時々 `bash -c somecommand`がbashプロセスを終了しないのはなぜですか?

時々 `bash -c somecommand`がbashプロセスを終了しないのはなぜですか?

Ubuntu 12.04では、GNU bashバージョン4.2.25(1)-リリース(x86_64-pc-linux-gnu)を使用して次のコマンドを試しました。

$ bash -c 'pstree -s $$'
init───sshd───sshd───sshd───bash───pstree
$ bash -c 'pstree -s $$;echo'
init───sshd───sshd───sshd───bash───bash───pstree

2つ目は私が期待したものです。 1つbash目はこのコマンドを実行する場所、2つ目はbash私が起動する場所、bash -c ...2番目のbashはbashという子プロセスを起動しますpstree

しかし、最初の人に何が起こったのか知りたいです。 2番目のプロセスbashが消えてpstree元のサブプロセスになるのはなぜですかbash?以前の質問に対する回答が2番目の質問に適用されないのはなぜですかbash -c ...

ベストアンサー1

私はそれだけだと言うでしょう 呼ぶ 最適化しかし、実際には(最後のリンクからわかるように)bashテール呼び出しは最適化されていません。実行するコマンドが単純なコマンド(つまり、複合コマンドではない場合)の場合にのみ最適化されているように見えますが、リダイレクトがある場合は最適化されません。また、コマンドが and-or リストで最後の場合 (たとえばtrue && true && cmdor false && true || cmd) を最適化するように見えますが、traps が所定の位置にある場合 (たとえばtrap uname EXIT && cmd) が正しくないため、最適化されないようです。

2番目のコマンドはコマンドラインの最後のコマンドではないpstreeため、仕上げ呼び出しではありません。pstree(テールコールですが、通常はecho組み込まechoれているため、とにかく子プロセスは作成されません。)

これらすべてのリンクを読む時間を節約するために(面白いことを望んでいますが)、関数/プログラム/何か他の関数/プログラム/何でも呼び出してすぐに返し、返された値が次の値になることを知っている場合、同じです。関数/プログラム/値を返すすべての項目と呼ばれる場合は、新しいスタックフレームをプッシュして(新しいプロセスの作成)、呼び出しの代わりに現在のスタックフレーム(またはシェルスクリプトの場合はプロセス)を再利用できます。関数(スクリプト実行)を実行して返します。シェルスクリプトではfor lastコマンドを使用して手動でこれを実行できますが、execシェルは自動的に実行することもできます。

zshどちらもkshこれを行うことができるようですが、次のようになりますbash

$ zsh -c 'if [[ -n foo ]]; then pstree -s $$; else echo hello; fi'
init───lightdm───lightdm───init───konsole───bash───pstree
$ ksh -c 'if [[ -n foo ]]; then pstree -s $$; else echo hello; fi'
init───lightdm───lightdm───init───konsole───bash───pstree
$ bash -c 'if [[ -n foo ]]; then pstree -s $$; else echo hello; fi'
init───lightdm───lightdm───init───konsole───bash───bash───pstree

しかし、この観察は私がインストールしたシェルバージョンによる観察だけです。したがって、YMMV:

$ zsh --version
zsh 5.0.2 (x86_64-pc-linux-gnu)
$ ksh --version
  version         sh (AT&T Research) 93u+ 2012-08-01
$ bash --version
GNU bash, version 4.2.45(1)-release (x86_64-pc-linux-gnu)

おすすめ記事