答え1
私はこれを初めて試してみます。他の人も改善されることを願っています。
スクリプトを実行する前に、シェルはファイルのファイル記述子を開きます。通常、fd 255に割り当てられます。とにかくオープンがあれば見つけることができますfd
。lsof
だから私たちはlsof -p $$
最高のファイル記述子のファイル名を使用して取得します。lsof
すべてのUNIXバージョンに適用されるわけではありません。 BSD Wikiには同等のものがあることがわかりますfstat
。 Darwin(Mac OS)にあるようです。 `-Fで
スクリプト例:
#!/bin/sh
this_script_path=`lsof -p $$ | awk '/\/'${0##*/}'$/' | cut -c 55-`
明らかに、クリッピングはlsofの特定の形式に大きく依存します。バージョン 2 では、この問題を軽減できます。注:私のバージョンでは、lsof
印刷できない文字を変換してパス名のタブ文字も\t
。
バージョン2。醜いPerlコードについて事前に申し訳ありません。今回は-F
オプションを使って出力を制御します。私たちは-F fn
次のような結果を得るでしょう:
p3834
fcwd
n/home/joe/test
frtd
n/
ftxt
n/bin/bash
fmem
n/lib64/ld-2.12.so
fmem
n/lib64/libdl-2.12.so
fmem
n/lib64/libc-2.12.so
fmem
n/lib64/libtinfo.so.5.7
fmem
n/usr/lib/locale/locale-archive
fmem
n/usr/lib64/gconv/gconv-modules.cache
f0
n/dev/pts/1
f1
n/dev/pts/1
f2
n/dev/pts/1
f255
n/home/joe/test/t.sh
私たちは、最高のファイル記述子(255と信じられないと仮定します)がスクリプト名になるように、この混乱した部分を変換する必要があります。 (これもdash
当てはまるようです。)
this_script_path=`lsof -p $$ -F fn |
perl -lane '
$fd=$1,next if /^f(\d+)/;
$p{$fd}=$1 if $fd and /^n(.*)/;
$fd="";
}END {
@x=sort {$a<=>$b} keys %p;
print $p{$x[-1]};
}{'`
Perlスクリプトは見苦しいことに同意します。これは一行で、明確にするために分類しました。行が始まると、ファイル記述子の番号がキャプチャされます。f
有効なファイル記述子と有効なファイル名がある場合は、ファイル名をハッシュとしてキャプチャします。これらの条件のいずれも満たしていない場合は、キャンセルしてください$fd
。すべての行が処理されたら、ハッシュ(ファイル記述子)のキーを数字でソートし、結果を配列に保存し、配列の最後の要素(最も大きい値)でインデックス付けされたx
ファイル名hashの内容を出力します。p
x
唯一の質問は、lsofがすべてのシステムにインストールされているかどうか、およびこの出力形式がどれほど安定しているかです。
答え2
役に立ついくつかの経験的な方法がありますが、完全に信頼できる方法はありません。
Otheusはファイル記述子の使い方を示しています。。これはほとんどの場合に機能する良い経験的な方法です。ただし、失敗して失敗を検出できない極端なケースがあります。
例:次のスクリプトを使用してください。
#!/bin/sh
set
lsof -p$$ | sed 's/[0-9][0-9]*//'
このスクリプトのコピーを2つ作成します。 1つは名前が付けられ、foo
もう1つはbar
。それでは少し強調してみましょう。
$ env -i PATH=/bin:/usr/bin perl -MPOSIX -e 'dup2(4, 11) or die $!; exec "dash", "foo", "bar"' 3<foo 4<bar </dev/null >foo.out
$ env -i PATH=/bin:/usr/bin perl -MPOSIX -e 'dup2(3, 10) or die $!; exec "dash", "bar", "foo"' 3<foo 4<bar </dev/null >bar.out
$ diff foo.out bar.out
17c17 < dash gils 1w reg 0,24 99 10130024 /tmp/202954/foo.out ---
ダッシュザイルズ 1w REG 0,24 99 10130022 /tmp/202954/bar.out
ここで唯一の違いは、出力を記録するファイルです。
この経験的な方法が失敗する別のケースでは、シェルが標準入力から呼び出されるか-c
。
別のアプローチは、シェルのコマンドラインを解析することです。 Linuxでは/proc
引数がnullで区切られているため、ポータブルシェルツールで解析するのは困難ですが(最近のGNUツールを使用すると簡単になります)。移植可能なパラメータにアクセスするには呼び出す必要があり、ps
明示的な出力形式はありません。ps -o args
パラメータはスペースで連結され、切り捨てることができます。
Linuxでもここで発生する問題は、スクリプトが知らないオプションでシェルを呼び出すことができ、そのオプションの1つが引数を取ることができることです。たとえば、名前の付いたスクリプト1
と名前の異なるスクリプトがあるとします2
。
mksh -T 1 2
その後、mkshが呼び出され、/dev/tty1
スクリプトが実行されます2
。
zsh -T 1 2
オプションを使用してzshを呼び出し、cprecedences
引数を使用してスクリプトを実行します。1
2
各シェルを区別するには、各シェルを知る必要があります。このアプローチを使用すると、極端なケースを検出できます。標準以外のオプションが表示された場合は、終了してください。