一言で言えば、次のようなラッパースクリプトの例を見てきました。
#!/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インスタンスの子プロセスとして開始されます。
最初のアプローチの利点は何ですか?
exec
を使用すると、ラッパーがより透過的になります。つまり、スクリプトを呼び出すユーザーまたはアプリケーションが、リレーが「実際の」プログラムを起動するリレーであることを認識する必要が少なくなります。
特に、呼び出し元がプログラムを強制終了したい場合は、起動したプロセスを強制終了します。ラッパースクリプトが子プロセスを実行する場合、呼び出し元は、ラッパーの子を見つけて、代わりにそれを強制終了する必要があることを知る必要があります。ラッパースクリプトは、一部の信号をリレーするトラップを設定できますが、キャッチできないSIGSTOPまたはSIGKILLでは機能しません。
exec
を呼び出すと、何もすることなく余分なシェルを保持する必要がないため、メモリ(およびPIDなどの他のリソース)も節約できます。
複数のラッパーがある場合、問題が追加されます(強制終了する適切なプロセス、メモリのオーバーヘッドなどを見つけるのが困難)。
一部のシェル(Kornシェルなど)は、コマンドが最後のコマンドであり、アクティブなトラップがない場合に自動的に検出し、暗黙的なexec
を配置しますが、すべてのシェルが実行するわけではありません(たとえばbashではありません)。
重複が見つからない... FreeBSDハンドブック を参照してください。これには十分な理由があります。
exec
ステートメントは、シェルプロセスを指定されたプログラムに置き換えます。exec
を省略した場合、プログラムの実行中はシェルプロセスがメモリに残り、システムリソースを不必要に消費します。
これは本質的にかなり前に(ポーターの1人によって)私に説明された理由であり、かなりよく知られています。