/proc/self/fd/2は `sudo -u other_user`からアクセスできません。

/proc/self/fd/2は `sudo -u other_user`からアクセスできません。

私はしばしばこれを使用してtee /proc/self/fd/2stdoutとstderrに何かを表示し、stdoutへのすべての出力を維持しながらstdoutをキャプチャします。

たとえば、次のようになりますdo.sh

STD_OUT_STR=$(CMD ARGS ... 2>&1 | tee /proc/self/fd/2)
# handle STD_OUT_STR ...
...

これは非常にうまく機能します。

例えば、

./do.sh

デフォルトでは、次のように動作します。

bash -c 'echo hi | tee /proc/self/fd/2'

出力

hi
hi

しかしある日、私はそれを実行しsudo -u A_USER ./do.shましたが失敗しました。

sudo -u A_USER ./do.sh'

デフォルトでは、次のように実行されます。

sudo -u A_USER bash -c 'echo hi | tee /proc/self/fd/2'

出力

tee: /proc/self/fd/2: Permission denied
hi

これまでは、次の回避策に従う必要があります。

sudo -u A_USER bash -c 'echo hi | tee >(cat >&2)'

私はこれがセキュリティ上の理由であることを理解しています。現在、ユーザーの pty は他のユーザーと共有されません。

sudo -u A_USERプロセスにそのptyへのアクセスを許可するオプションがあるかどうか疑問に思います。

編集:do.shスクリプトに入れる必要があります。つまり、do.shの外にtee /proc/self/fd/2入れることができないので役に立ちません。tee /proc/self/fd/2sudo -u A_USER bash -c '...' | tee ...

ベストアンサー1

sudo -u A_USER bash -c 'cmd | tee /dev/fd/2'

または:

sudo -u A_USER sh -c 'cmd | tee /dev/fd/2'

bashに関連する内容がないので、システムで動作します。外のLinuxやシグウィン。

ただし、ほとんどのシステムでは、オープンは/dev/fd/xLinuxまたはCygwinと同じでdup(x)あり、そのファイル記述子で開かれたファイルを指す「魔法の」シンボリックリンクであるため、ファイルを開くことはまったく同じではありません。>&xsh/dev/fd/x/proc/self/fd/xdup()

あなたの場合のように、書き込みのために開く権限がないファイルでfd 2が開いたり、ソケットでまったく開くことができない可能性があります(通常はsystemdstderrがソケットによって開始されたプロセスjournald)。

書き込み権限を持つ通常のファイルでも、そのファイルを最初から開いて切り取るため、間違っているか間違っていますtee /proc/self/fd/2tee /dev/fd/2Eventee -a /proc/self/fd/2は間違っています(実際は良いですが)。切り捨てが多すぎてファイルの最後で書き込みが完了するため、stderrが別の方法で開いている場合にのみ機能します。追加モデル。

たとえば、次のようになります。

(
  echo test | tee -a /proc/self/fd/2
  echo hi >&2
) 2> file
$ cat file
hi
t

出力はを介して記録さhiれます。testtee

Linux / Cygwinでの/dev/fd/x/ /proc/self/fd/x(または/dev/stdout/dev/stderr)の使用は、そのfdが見つからないファイル(パイプやttyデバイスなど)で開かれている場合にのみ許可されますが、その場合でもここでこれらの権限の問題などの問題が発生する可能性があります。

シェルtee >(cat >&2)はシェルをパイプで開いているどこかに変換し、パイプはユーザーがパイプtee /proc/self/fd/somefdsomefd書き込んで作成したため、権限の問題はありませんが、bashシェルでこれを行うことはまだ間違っています。特にそうではないbashのようなものです。その過程をお待ちくださいcat

後ろに:

(bash -c 'echo test | tee >(cat>&2)'; echo hi >&2) 2> file

時には以下fileが含まれる場合もあります。

hi
tee

以前は最初の項目をbash返し、cat正常に作成して出力testechoたためです。hi

ここでは、ファイルの代わりに複数のファイル記述子を使用する代わりに、次のようにzsh使用できます。bashtee

sudo -u A_USER zsh -c 'echo hi >&1 >&2'

fd(ここでは1 / stdout)が出力のために複数回リダイレクトされると、サービスを実行する内部プロセスにつながるパイプにリダイレクトされます。

sudo -u A_USER zsh -c 'echo hi | tee >(cat >&2)'

これは上記のbash警告なしで機能しますが、zshには機能が組み込まれているため、これらのtee警告は必要ありません。cat

zshシェルから呼び出す場合は、USER_Aの代わりに呼び出すユーザーに内部提供を完了させることができます。

sudo -u A_USER sh -c 'echo hi' >&1 >&2

Linux/Cygwinで比較します。

sudo -u A_USER sh -c 'echo hi' | tee -a /dev/fd/2

それ自体より

sudo -u A_USER sh -c 'echo hi' | tee /dev/fd/2

(ライセンスの問題も解決しましたが)上記の理由によるものです。

権限の問題を解決するために stderr をパイプに変換するソリューションは、sh(プロセス置換を使用できません) + を使用して手動で実行することです.tee

sudo sh -c '
  {
    {
      cmd |
        tee /dev/fd/2
    } 2>&1 >&3 3>&- |
      cat >&2 3>&-
  } 3>&1'

内部コマンドグループ内では、stderrはcat共有パイプになりますが、stderrをそのままにすることcmdもできますcmd

sudo sh -c '
  {
    {
      cmd 3>&- |
        tee /dev/fd/3
    } 3>&1 >&4 4>&- |
      cat >&2 4>&-
  } 4>&1'

cmd | tee >(cat >&2)ここでcat適切な待機が与えられたにもかかわらず、これはあなたの状況に近いです。

おすすめ記事