25

EXITbashトラップ使用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.$$が存在します)。

もちろん、exec. . それを機能させて使用する方法はありますexecか?これは確かに、実際的な問題というよりは好奇心によるものです。

4

1 に答える 1

34

一般的に、いいえ。これは、あなたが言及した理由により不可能です。

つまらない回答ですが。回避策のオプションを見てみましょう。

exec セマンティクスを重視し、複数のプロセスを開始することを重視しない場合、任意の実行可能ファイルに対して次のことができます。

{ while kill -0 $$; do sleep 5; done; rm "$0.$$"; } &
exec ./file

これexecにより、ファイルが別のプロセスでポーリングされ、完了時にクリーンアップが実行されます。

フォークを避けたい場合、実行しているのは別のシェル スクリプトです。

exec bash --rcfile <(echo 'trap "..." exit') -i ./file

ファイルに追加し、後でクリーンアップを実行します (スクリプトがトラップを実行または上書きexecしない限り)、新しいプロセスを開始する必要はありません。ing の代わりにing を使用しても、ほぼ同じ効果があります。execsourceexec

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です。

于 2014-06-09T02:12:11.023 に答える