catを使った簡単なプロセスの交換が中断されたようです。
cat >( echo hello; )
決して終わりません。また試しました:
cat >( echo hello; exit; )
子プロセスでstdoutファイルの説明を手動で閉じても機能しません。
cat >( echo hello; 1>&- )
cat >( echo hello; 1>&- exit; )
私はGNU bashバージョン4.4.23(1)-リリース、GNU bash、バージョン4.1.2(2)-リリースとzsh 5.5.1(x86_64-debian-linux-gnu)を試しました。
なぜこれが起こるのか説明できますか?私はプロセスの置き換えが大好きです...
ありがとう
編集:catがechoから読み取られた場合、プロセス置換の正しいリダイレクトは次のとおりです。
cat <( echo hello; )
答え1
あなたのコードは決してcat >( echo hola; )
終了しません。
- まずパターンをエコーします。
hola
- 書き込みのための入力を受け入れます。
- 私たちがそれを与えると、書き込む
Ctrl+D
ファイルを検索し続けます。
オプション1:エコーされたファイルへのコンテキストの書き込み
cat > $( echo hola; )
したがって、以下に提供するすべてのコンテキストはhola
。
注:次のようにcatブロックを終了できます。Ctrl+D
オプション2:エコーされたコンテキストをキャプチャします。
cat <(echo hola;)
答え2
何を達成したいのか分からないが、
>(...)
実行中のすべての項目の標準入力を書き込み可能にします。cat
読み取り可能なファイルが必要です。
(1) が提供する内容を読むことができるという保証はありません。 macOSではエラーが発生しました。
bash-4.4$ cat >( echo foo)
foo
cat: /dev/fd/63: Permission denied
Linuxでは、もう一方の端に何も書かれていないパイプです。
$ strace -e openat cat >(echo foo)
foo
...
openat(AT_FDCWD, "/dev/fd/63", O_RDONLY) = 3
そして:
$ ll /proc/$(pgrep cat)/fd/3
lr-x------ 1 muru muru 64 Aug 13 18:55 /proc/3381/fd/3 -> 'pipe:[37501]'
$ lsof | grep 37501
strace 3433 muru 63w FIFO 0,12 0t0 37501 pipe
cat 3435 muru 3r FIFO 0,12 0t0 37501 pipe
cat 3435 muru 63w FIFO 0,12 0t0 37501 pipe
もう一方の端がstdinを閉じて終了することは重要ではありません。パイプを開くだけです。読む、何も記録されず、パイプにも何も記録されません。それでcat
そこに置いて読書が完了するのを待ちます。 (ここstrace
とcat
ここは両方ともパイプに書き込むために開いているファイルハンドルを持っていますが、これはbashが書き込みのためにファイルハンドルを開いて使用できるようにしたためです。どちらも書き込めません。)
答え3
プロセスの置き換えはそれ自体のトピックです。知っておくべき重要な点は、これがstdinやstdoutよりもFIFOに近いことです。 echoを使用してこれを確認できます。
echo >( echo hello; )
あなたに: /dev/fd/63 こんにちは
外部エコーは実際に与えられたパラメータを提供します/dev/fd/63
。だからあなたの
cat >( echo hello; )
実際にcat /dev/fd/43
出力はに送信されますecho hello
。 (43は単なる例で、数字はランダムですが、通常63です。)
以下の違いも確認できます。
echo hop > >(cat)
これは提供hop
します
echo hop >(cat)
これは作るhop /dev/fd/63
。
また、例えば次のようになります。
sed 's/$/klap/' | tee >(sed 's/^/hop/')
コメントを提示するklop
klopklap
hopklopklap
これはklopklap
標準出力でありtee
、プロセスで置き換えられた標準出力ですhopklopklap
。sed
それではなぜ停止しますかcat >(echo hello)
?前述のように、catは引数を受け取り、/dev/fd/32
その「ファイル」ではEOFを取得できないためです。
答え4
停止せずcat
にユーザーの入力を待っています。cat
標準入力を読み、標準出力に書き込みます。標準入力をリダイレクトしないため、標準入力は端末です。と入力するとCtrl+D
ファイルの終わりを示し、ファイルがcat
終了します。