web-dev-qa-db-ja.com

ラッパースクリプトでのexecの理由

一言で言えば、次のようなラッパースクリプトの例を見てきました。

#!/bin/bash

myprog=sleep
echo "This is the wrapper script, it will exec "$myprog""

exec "$myprog" "$@"

上記のように、彼らはexecを使用して、新しく作成されたシェルをほぼ即座に$myprogに置き換えます。 execなしで同じことを達成できます:

#!/bin/bash

myprog=sleep
echo "This is the wrapper script, it will exec "$myprog""

"$myprog" "$@"

この最後の例では、新しいbashインスタンスが開始され、次に$myprogがbashインスタンスの子プロセスとして開始されます。

最初のアプローチの利点は何ですか?

29
Martin

execを使用すると、ラッパーがより透過的になります。つまり、スクリプトを呼び出すユーザーまたはアプリケーションが、リレーが「実際の」プログラムを起動するリレーであることを認識する必要が少なくなります。

特に、呼び出し元がプログラムを強制終了したい場合は、起動したプロセスを強制終了します。ラッパースクリプトが子プロセスを実行する場合、呼び出し元は、ラッパーの子を見つけて、代わりにそれを強制終了する必要があることを知る必要があります。ラッパースクリプトは、一部の信号をリレーするトラップを設定できますが、キャッチできないSIGSTOPまたはSIGKILLでは機能しません。

execを呼び出すと、何もすることなく余分なシェルを保持する必要がないため、メモリ(およびPIDなどの他のリソース)も節約できます。

複数のラッパーがある場合、問題が追加されます(強制終了する適切なプロセス、メモリのオーバーヘッドなどを見つけるのが困難)。

一部のシェル(Kornシェルなど)は、コマンドが最後のコマンドであり、アクティブなトラップがない場合に自動的に検出し、暗黙的なexecを配置しますが、すべてのシェルが実行するわけではありません(たとえばbashではありません)。

重複が見つからない... FreeBSDハンドブック を参照してください。これには十分な理由があります。

execステートメントは、シェルプロセスを指定されたプログラムに置き換えます。 execを省略した場合、プログラムの実行中はシェルプロセスがメモリに残り、システムリソースを不必要に消費します

これは本質的にかなり前に(ポーターの1人によって)私に説明された理由であり、かなりよく知られています。

10
Thomas Dickey