次のコマンドを実行すると:
cat <(echo 1 | pv) | pv
cat <(echo 1 | pv) | less
cat <(echo 1 | pv) | cat
コマンドが永久に実行されるようです。 (SIGINT)と入力すると、^C
実行されたコマンドだけでなく、シェル全体が終了します。なぜですか?
ps xf
他のシェルの最小関連出力cat <(pv) | less
:
Ss /bin/bash
S+ \_ cat /dev/fd/XX
S | \_ /bin/bash
T | \_ pv
S+ \_ less
次のファイル記述子を開きます。
強く打つ
0 -> /dev/pts/YY
1 -> /dev/pts/YY
2 -> /dev/pts/YY
255 -> /dev/pts/YY
猫/開発者/fd/ZZ
0 -> /dev/pts/YY
1 -> pipe:[RRRRRRRR]
2 -> /dev/pts/YY
3 -> pipe:[QQQQQQQQ]
ZZ -> pipe:[QQQQQQQQ]
強く打つ
0 -> /dev/pts/YY
1 -> pipe:[QQQQQQQQ]
2 -> /dev/pts/YY
255 -> /dev/pts/YY
PV
0 -> /dev/pts/YY
1 -> pipe:[QQQQQQQQ]
2 -> /dev/pts/YY
少ない
0 -> pipe:[RRRRRRRR]
1 -> /dev/pts/YY
2 -> /dev/pts/YY
3 -> /dev/tty
cat <(echo 1 | pv) | less
元の例を使用すると(これはbash組み込みではなく他のプログラムでも発生します。例:echo
dd if=/dev/zero bs=1 count=1
Ss /bin/bash
S+ \_ cat /dev/fd/63
S | \_ /bin/bash
T | \_ pv
S+ \_ less
強く打つ
0 -> /dev/pts/18
1 -> /dev/pts/18
2 -> /dev/pts/18
255 -> /dev/pts/18
猫/開発者/fd/63
0 -> /dev/pts/18
1 -> pipe:[36932796]
2 -> /dev/pts/18
3 -> pipe:[36929317]
63 -> pipe:[36929317]
強く打つ
0 -> /dev/pts/18
1 -> pipe:[36929317]
2 -> /dev/pts/18
255 -> /dev/pts/18
PV
0 -> pipe:[36930391]
1 -> pipe:[36929317]
2 -> /dev/pts/18
少ない
0 -> pipe:[36932796]
1 -> /dev/pts/18
2 -> /dev/pts/18
3 -> /dev/tty
答え1
これは<(
、プロセスに)
適切なジョブ制御がないために発生します。つまり、フォークされて忘れてしまいます。ほとんどの場合、これは問題ではありません。なぜならほぼプロセスは作成されるとすぐに別々のプロセスグループとバックグラウンドに配置されます。 ~のため即時シェルはこのプロセスの入出力を開く必要がありますが、これはttyの前景プロセスグループであるため、SIGINTに対して脆弱です。インタラクティブシェルが通常行うようにキャプチャまたは無視されない限り。
しかし問題はこんな感じです。パイプラインがデッドロックに陥りました。親プロセスがプロセスの出力を開こうとすると、パイプはブロックされます。プロセスグループと他のすべてのグループを変更する機会はありません。CTRL+C
フォアグラウンドグループが終了し、SIGINTが送信されます。前景グループが終了し、親グループがまだパイプによってブロックされており、制御権を再取得できない場合は、自宅に誰もいないため、ターミナルからHUPを送信します。カブーム
別のパイプを開くには、まず開くパイプごとに作成者とリーダーが必要です。