&1"と">/proc/self/fd/1"リダイレクトの違いは何ですか?">

">&1"と">/proc/self/fd/1"リダイレクトの違いは何ですか?

&1"と">/proc/self/fd/1"リダイレクトの違いは何ですか?">

私は起動時に実行されるいくつかのスクリプトを作業していますrc.localが、出力リダイレクトが非常に奇妙な方法で動作することを発見しました。

そのように書くと、echo "foo" >&1システムログに書き込まれ、すべてが正常です。

echo "foo" >>/dev/stdoutしかし、またはと書くと、echo "foo" >>/proc/self/fd/1No such device or addressというエラーが発生します。

さらなる調査によると、これは/proc/self/fd/1実際にソケットでした。ls -l /proc/self/fd印刷コンテンツにはrc.local以下が含まれます。

lr-x------. 1 root root 64 Jul 14 05:28 0 -> /dev/null
lrwx------. 1 root root 64 Jul 14 05:28 1 -> socket:[18485]
lrwx------. 1 root root 64 Jul 14 05:28 2 -> socket:[18485]
lr-x------. 1 root root 64 Jul 14 05:28 255 -> /etc/rc.d/rc.local

説明された動作はを使用して簡単に再現できますnc。まず、どのファイル記述子がソケットにバインドされているかを調べます。nc -l -p 25566 -c "ls -l /proc/self/fd"最初の端末で発行し、telnet localhost 25566別の端末で発行してこれを行うことができます。私の場合は5番目の記述子です。

[OK] その後、最初の端末で問題を再現するには、次の手順を実行します。

nc -l -p 25566 -c "echo 'hello' >&5"

2番目のターミナルで:

telnet localhost 25566

接続を確立および終了するためのTelnetメッセージ間の2番目の端末出力に「hello」が表示されます。

これで起こるのは、ファイル記述子擬似ファイルが次から来るということです/proc

最初の端末:

nc -l -p 25566 -c "echo 'hello' >/proc/self/fd/5"

2番目のターミナル:

telnet localhost 25566

2番目の端末には接続が確立され、すぐに閉じるためのTelnetメッセージのみが含まれ、最初の端末にはエラーが表示されますsh: /proc/self/fd/5: No such device or address

編集する:オペレーティングシステムはFedora 23 i686サーバーです。


さて、ここで問題が発生します。>&1これらとそしての違いは何ですか>/proc/self/fd/1?現在の標準出力と正確に一致するいくつかのファイルに出力をリダイレクトする一般的で信頼性の高い方法はありますか?

ありがとうございます。


編集2:

明確にするために、上記のシナリオでは、Fedora 23 i686の正確な入力/出力は次のとおりです。

Terminal 1                                       | Terminal 2
$ nc -l -p 25566 -c 'ls -go /proc/self/fd'       | 
                                                 | $ telnet localhost 25566
                                                 | Trying ::1...
                                                 | Connected to localhost.
                                                 | Escape character is '^]'.
                                                 | total 0
                                                 | lr-x------ 1 64 Jul 14 08:56 0 -> pipe:[19687]
                                                 | l-wx------ 1 64 Jul 14 08:56 1 -> pipe:[19688]
                                                 | lrwx------ 1 64 Jul 14 08:56 2 -> /dev/tty2
                                                 | lr-x------ 1 64 Jul 14 08:56 3 -> pipe:[19687]
                                                 | lr-x------ 1 64 Jul 14 08:56 4 -> /proc/1285/fd
                                                 | lrwx------ 1 64 Jul 14 08:56 5 -> socket:[19686]
                                                 | l-wx------ 1 64 Jul 14 08:56 7 -> /pipe:[19688]
                                                 | Connection closed by foreign host.
$ nc -l -p 25566 -c "echo 'hi' >&5"              | 
                                                 | $ telnet localhost 25566
                                                 | Trying ::1...
                                                 | Connected to localhost.
                                                 | Escape character is '^]'.
                                                 | hi
                                                 | Connection closed by foreign host.
$ nc -l -p 25566 -c "echo 'hi' >/proc/self/fd/5" | 
                                                 | $ telnet localhost 25566
                                                 | Trying ::1...
                                                 | Connected to localhost.
sh: /proc/self/fd/5: No such device or address   | Escape character is '^]'.
                                                 | Connection closed by foreign host.
$                                                | $

ベストアンサー1

使用>&N。これは移植可能で、見てわかるように、実際にソケットと連携して動作します。

使用する唯一の理由/proc/self/fdは、ファイル名が必要なプログラムを実行していて、すでに開いているファイル記述子を使用するように指示されない場合です。たとえば、ほとんど<(cmd...)すべてのコマンドラインユーティリティは名前で指定されたファイルを開くことができますが、すべてのコマンドラインユーティリティが事前に開かれたファイル記述子を直接サポートしているわけではないため、リダイレクトはそれを使用します。

ただし、シェルは既存のファイル記述子を使用できるため/proc


また、これはLinuxに固有のものであり、私のLinuxシステムには、および他のものはなどへのシンボリックリンクなので、インストールする必要があります/proc/NNN/fd/。他のUnixでは異なる場合があります。 ~によると/proc/dev/stdout/dev/fd/*/proc/self/fd/*/proc古い質問への回答 /dev/stdoutPOSIX の外部に明示的にリストされます。

リダイレクトが必要に応じて機能しない理由は次のとおりです。を試してください。 2straceつの違いは、>&Nリダイレクトの場合はファイル記述子がbash呼び出され、.txtを使用して通常のファイルとして開こうとすることです。 。このような新しいソケットコピーを開くことは明らかにサポートされていないため、呼び出しは失敗します。ストリームソケットはほぼポイントツーポイントリンクなので、新しいコピーを開くことを無効にすることはそれほど不自然に見えません。しかし、なぜパイプやと一緒に動作するのかわかりません。dup()>/proc/self/fd/Nopen()procdup

$ ls -l /proc/self/fd/3
lrwx------ 1 itvirta itvirta 64 Jul 14 18:24 /proc/self/fd/3 -> socket:[168157]
$ strace bash -c "echo foo >>/proc/self/fd/3" 2>&1 | grep open.*proc/self
open("/proc/self/fd/3", O_WRONLY|O_CREAT|O_APPEND, 0666) = -1 ENXIO (No such device or address)

返品この回答移植性に関するいくつかの情報があります。/proc/NNN/fd

おすすめ記事