zshはこのコマンドが完了するのを待ちますが、bashがコマンドが完了する前にプロンプ​​トに書き込むのはなぜですか?

zshはこのコマンドが完了するのを待ちますが、bashがコマンドが完了する前にプロンプ​​トに書き込むのはなぜですか?

これはコマンドです:

{ ( echo "to stdout"; echo "to stderr" >&2 ) > >(sleep 1; tee stdout.txt); } 2> >(sleep 2; tee stderr.txt >&2 )

これが私が見るものです:

扱いにくい

% { ( echo "to stdout"; echo "to stderr" >&2 ) > >(sleep 1; tee stdout.txt); } 2> >(sleep 2; tee stderr.txt >&2 )
to stdout
to stderr
%

強く打つ

$ { ( echo "to stdout"; echo "to stderr" >&2 ) > >(sleep 1; tee stdout.txt); } 2> >(sleep 2; tee stderr.txt >&2 )
$ to stdout
to stderr

bashは出力が完了する前にプロンプ​​トを作成します$が、zshはユーザーにプロンプ​​トを表示する前に交換プロセスが完了するのを待ちます%

合理的な答えは、「それがzshがどのように機能するかだ」と思います。しかし、これがより多くのことを学ぶためにどこに文書化されているのか知りたいです。多くのbashユーザーのうち、zshユーザーとして、私は「このコマンドを実行してみてください」と言って何が起こるのかを知るために違いを理解しようとします。

(関連質問:https://stackoverflow.com/a/53051506/1054322)

ベストアンサー1

短い例は、両方のシェルで同じように機能します。親シェルは待ちません。

(sleep 1; echo done) > >(cat >file) &

次のように修正すると、zsh 〜するちょっと待ってください。しかし、bashそうではありません:

{ (sleep 1; echo done) & } > >(cat >file)

zshexpn(1)同様の例がマニュアルの「PROCESS SUBSTITUTION」に記載されています。そこ{ ... }では、非同期プロセスの出力をプロセス置換(両方のシェルで非同期)にリダイレクトすると、シェルは非同期プロセスを待ちます{ ... }

このマニュアルでは、問題について次のように説明しています。

>(process)外部コマンドに接続すると、追加の問題が発生します。親シェルはプロセスが完了するのを待たないため、後続のコマンドは完了結果に依存できません。

非同期コマンドを複合としてカプセル化することで、{ ... }「ここの追加プロセスは親シェルで作成され、親シェルが完了するまで待ちます。」これに対する私の解釈は、私たちがリダイレクトするプロセスがシェルで生成されるのに対して、>(...)そうでないプロセスは{ ... }バックグラウンドタスクで始まったタスクから生成されるということです(シェルはこれを待ちません)。

$ZSH_SUBSHELLリダイレクトするプロセスの置き換えから出力を取得すると、その証拠を見つけることができます。遮断コードの場合を出力し1、非遮断コードの場合を出力します。これは2、出力が別のサブシェル内でサブシェルに実行されるようにリダイレクトされることを示します(メインシェルは待機しません)。

出力プロセスの置き換えの出力が で同じ動作を示していても、シェルはbashこれを異なる方法で処理し、どちらの場合も親シェルとは無関係にすべてのバックグラウンドジョブを作成するようです。$BASH_SUBSHELLzsh

おすすめ記事