簡単に言えば、いくつかのシステムの動作を追跡するために特定の実行可能ファイルが呼び出される方法を追跡したいと思います。実行可能ファイルがあるとしましょう。
/usr/bin/do_stuff
実際、シンボリックリンクを介してさまざまな名前で呼び出されます。
/usr/bin/make_tea -> /usr/bin/do_stuff
/usr/bin/make_coffee -> /usr/bin/do_stuff
など。明らかにdo_stuff
受け取った最初の引数は、取るべき実際のアクションを決定するために使用され、残りの引数はそれに応じて処理されます。
行われた呼び出し/usr/bin/do_stuff
(および完全なパラメータのリスト)を記録したいと思います。シンボリックリンクがない場合は、単に移動してdo_stuff
スクリプトdo_stuff_real
を作成するだけです。
#!/bin/sh
echo "$0 $@" >> logfile
/usr/bin/do_stuff_real "$@"
しかし、私が知っている限り、呼び出された名前を解決するのはうまくいきません。同じ目標を達成しながら、正しいdo_stuff
「実行ファイルで使用される名前」を渡すスクリプトをどのように書くことができますか?
記録のために次の質問に答えないようにするには:
- 私はCで(execveを使用して)それを行うことができることを知っていますが、この場合、シェルスクリプトを使用できる場合ははるかに簡単になります。
do_stuff
単にロギングプログラムに置き換えることはできません。
ベストアンサー1
busybox
ほとんどの一般的なUNIXユーティリティを単一の実行可能ファイルとして提供するなどのユーティリティでこれをよく見ることができます。このユーティリティの動作は、呼び出されるかbusybox
渡されるacpid
項目によって異なりますzcat
。
argv[0]
通常、パラメータを見て何をすべきかを決定しますmain()
。単純な比較にしてはいけません。なぜなら、argv[0]
似たようなことがあるかもしれないしsleep
、そうかもしれないし/bin/sleep
、同じことをすることに決めなければならないからです。つまり、このパスは状況をより複雑にします。
したがって、ワーカーが正しく実行すると、ロギングラッパーが同じもので実行される可能性があります/bin/realstuff/make_tea
。ワーカーがデフォルト名だけを見ると、argv[0]
正しい関数を実行する必要があります。
#!/bin/sh -
myexec=/tmp/MYEXEC$$
mybase=`basename -- "$0"`
echo "$0 $@" >> logfile
mkdir "$myexec" || exit
ln -fs /usr/bin/real/do_stuff "$myexec/$mybase" || exit
"$myexec/$mybase" "$@"
ret=$?
rm -rf "$myexec"
exit "$ret"
上記の例では、argv[0]
次のように読み取る必要があります/tmp/MYEXEC4321/make_tea
(4321が実行されているPIDの場合/bin/sh
)。これはbasenamemake_tea
アクションをトリガーする必要があります。
argv[0]
ラッパーなしで状況を正確に複製したい場合は、より困難な問題に直面するでしょう。絶対ファイルパスが/
.で始まるため、新しいパスを作成できません。/bin/sleep
(私がいなければchroot
そこに行きたくないと思います。)ご存知のように、これを行うためにいくつかの味を使うことができますが、exec()
シェルで包まれません。
エイリアスを使用してロガーにアクセスし、スクリプトラッパーの代わりに基本プログラムを起動することを検討しましたか?限られた一連のイベントだけをキャプチャしますが、おそらくそのイベントにのみ興味があるかもしれません。