EXIT
バッシュトラップを使いたいそしてexec
新しいプロセスの生成を避けるために使用します。これは可能ですか?
あれは、
#!/bin/bash
touch $0.$$
trap "rm -v $0.$$" EXIT
/bin/echo Hello
$0.$$
bashのEXIT
トラップを使用して一時ファイルを削除します
#!/bin/bash
touch $0.$$
trap "rm -v $0.$$" EXIT
exec /bin/echo Hello
トラップを「起動」することはありません (完了後に からのメッセージやrm
ファイル$0.$$
が存在しません)。
もちろん、トラップが発動できないのは、bashが制御不能になった後だからであるexec
。これを機能させる方法はあるだろうか?そして使用ですかexec
? これは確かに実用的な問題というよりも好奇心から来ています。
ベストアンサー1
一般的には、いいえ。あなたが述べた理由により、これは不可能です。
それは退屈な答えです。回避策のオプションを見てみましょう。
exec セマンティクスを重視し、複数のプロセスの開始をあまり気にしない場合は、任意の実行可能ファイルに対して次の操作を実行できます。
{ while kill -0 $$; do sleep 5; done; rm "$0.$$"; } &
exec ./file
これによりexec
、ファイルが別のプロセスによってポーリングされ、完了したらクリーンアップが実行されます。
フォークを避けたい場合、別のシェルスクリプトを実行するには次のようにします。
exec bash --rcfile <(echo 'trap "..." exit') -i ./file
exec
ファイルに を追加し、その後クリーンアップを実行します (スクリプトがexec
トラップを上書きしない限り)。新しいプロセスは開始されません。source
の代わりに を使用するとexec
、ほぼ同じ効果が得られます。
trap "..." exit
source ./file
本当にハックしたい場合は、LD_PRELOAD
を使用してオーバーライドしexit(3)
、選択したコマンドを実行することができます。
#include <stdlib.h>
void exit(int c) {
char* cmd = getenv("EXIT");
char *argv[] = { "bash", "-c", cmd, NULL };
char *envp[] = { NULL };
execvpe("bash", argv, envp);
}
これをライブラリとしてコンパイルできます:
$ gcc -shared -fPIC foo.c -o libfoo.so
そして、それを任意の動的にリンクされた実行可能ファイルにプリロードします。
$ LD_PRELOAD=./libfoo.so EXIT='echo "This is a hack"' ls *foo*
foo.c libfoo.so
This is a hack
これらのハックは楽しいですが、現実世界で必要になることはほとんどありません。よりシンプルで、より優れた、より標準的な解決策は、単にハックしないことですexec
。