web-dev-qa-db-ja.com

一部のLinuxシェルスクリプトがexecを使用してコマンドを実行するのはなぜですか?

次のようなLinux bashスクリプトでは:

exec /usr/lib/4.5/mono-service.exe ./AudioVideoRecorder.exe "$@"

、なぜexecコマンドをexecなしで実行するだけでなく、コマンドを実行する必要があるのですか?

23
Frank

短い答えは次のとおりです:そうではありませんが、(最近のCPUで)約1msのCPU時間を節約できます。 (execの後は何も実行されないため、スクリプトの最後でのみexecを実行する必要があることに注意してください)。

長い答えは次のとおりです。Execは、現在のプロセスのプロセスイメージを、実行する実行可能ファイルのプロセスイメージに置き換えます。つまり、実行すると、execingを実行するシェルプロセスが完全に破棄され、execedプログラムに置き換えられます。 execを実行しない場合、シェルは自身をforkし、forkで実行して、子プロセスが終了するまで待機し、戻りステータスを収集します。その後、追加のコマンドが実行されることを期待しています(fork + execは、新しいコマンドが生成される標準の手順です)。何もないので、forkは完全に時間の無駄であり、直接実行してforking時間を節約することもできます。

ほとんどの意図と目的のために、それは本質的にプロセスがどのようにUnicesで生成されるかの知識に基づいたマイクロ最適化です。


注:(thanks to ilkkach )わずかな意味上の違いは、スクリプトを生成するプロセスがどのように多分実行されたプログラムは死ぬ。おそらく実行された子が正常に終了する場合、シェルスクリプトは最後に待機した終了ステータスを独自の終了ステータスに転送するため、execフォームとnon-execフォームは同等です。ただし、子がシグナルnで死亡した場合、シェルはそれを終了ステータス128+nに変換し、シグナルされた情報を事実上失います。 (通常、子が終了コード>128で定期的に終了しないことが確実であれば、情報は失われません。) execを実行すると、仲介者シェルはなくなり、終了ステータス情報は実行スクリプトの呼び出し元に直接送信されます(子が終了したか、シグナルが送信されたかについての情報は、それをマージする仲介者シェルがないため、保持されます)終了コード)。 (詳細は waitpid(2) を参照してください)。

31
PSkocik