zshでは、cat <(cat)vs cat | cat vs cat =(cat)?


18

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

代わりに、cat <(cat)端末で入力できますが、入力行はコピー^Dされず、シグナルを送信できませんEOFcat | cat期待どおりに動作します。

さらなる実験として、にcat =(cat)似た問題があるかどうかを確認cat <(cat)しました^Dが、期待どおりに動作します。aまでのすべてのstdin が一度にstdoutにコピーされます。

誰もzshがボンネットの下で何をしているのかを理解するのを助けることができますか?

回答:


23
  1. a | bコネクトSTDOUTからaSTDINからbちょうど使用してdup/dup2。両方のコマンドは並行して実行されます。

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

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

    bバックグラウンドにあり、端末から読み取ることができません。strace -p $PID2番目のcatプロセスにアタッチしてプロセスを表示することで、自分でテストできます。

    aその間、名前付きパイプからの読み取りを試みますが、読み取りできないほど読み取りはbできません。

    •これは、基本的に、a読み取りを試みても読み取りbbできず、STDIN書き込みができないデッドロックがあることを意味します。a

man bashのバックグラウンドプロセスとターミナルの詳細:

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


よろしくお願いします。これでかなり改善されました。
アランオドネル

1
インタラクティブではない場合、zshはバックグラウンドコマンド(を含む<(cmd))の標準入力をにリダイレクトする/dev/nullため、動作が異なることに注意してください(zsh -c 'cat <(cat)'すぐに戻り、何も出力しません)。
ステファンシャゼル
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.