web-dev-qa-db-ja.com

zshでは、cat <(cat)とcatの違い|猫vs猫=(猫)?

cat <(cat)と_cat | cat_が同じことをすることを期待していました:stdinからstdoutに行をコピーします。私の理解では、どちらもサブシェルでcatを実行し、サブシェルcatのstdoutを一時的な名前付きパイプにリダイレクトしてから、現在のシェルで別のcatを実行します。 stdinがパイプにリダイレクトされました。

代わりに、cat <(cat)を使用すると端末で入力できますが、入力行がコピーされず、_^D_がEOFの通知に失敗します。 _cat | cat_は期待どおりに機能します。

さらなる実験として、cat =(cat)cat <(cat)と同様の問題を抱えているかどうかを確認しましたが、期待どおりに機能します。_^D_までのすべてのstdinがstdoutにコピーされます。ワンゴー。

Zshが内部で何をしているのかを誰かが理解するのを手伝ってくれませんか?

19
Alan O'Donnell
  1. _a | b_は、 _dup/dup2_ を使用するだけで、STDOUTaSTDINbを接続します。両方のコマンドは並行して実行されます。

  2. a =(b)は、aの引数を一時的なファイル名に置き換えます。 bに渡す前に一時ファイルを作成する必要があるため、aaの前に実行されます。

  3. a <(b)は、aの引数を名前付きパイプに置き換えます。 abは並行して実行されます。ここで少し複雑になります。

    bはバックグラウンドにあり、端末から読み取ることができません。 _strace -p $PID_を使用して2番目のcatプロセスに接続し、プロセスを確認することで、自分でテストできます。

    •その間、aは名前付きパイプからの読み取りを試みますが、bが読み取れないため、何も読み取ることができません。

    •これは、基本的に、abから読み取ろうとするが、bSTDINから読み取れず、aに書き込めないというデッドロックがあることを意味します。

man bash からのバックグラウンドプロセスとターミナルに関する詳細情報:

ジョブ制御へのユーザーインターフェイスの実装を容易にするために、オペレーティングシステムは現在の端末プロセスグループIDの概念を維持します。このプロセスグループのメンバー(プロセスグループIDが現在の端末プロセスグループIDと等しいプロセス)は、[〜#〜] sigint [〜#〜]などのキーボード生成信号を受信します。これらのプロセスはforegroundにあると言われています。 バックグラウンドプロセスは、プロセスグループIDが端末のものと異なるプロセスです。このようなプロセスは、キーボードで生成された信号の影響を受けません。フォアグラウンドプロセスのみが、ターミナルからの読み取り、またはユーザーがstty tostopで指定した場合は、ターミナルへの書き込みが許可されます。ターミナルからの読み取り(stty tostopが有効な場合の書き込み)を試みるバックグラウンドプロセスには、カーネルのターミナルドライバーからSIGTTIN(SIGTTOU)シグナルが送信され、キャッチされない限り、プロセスが中断されます。

24
Ulrich Dangel