foocaller
Ruby スクリプトを呼び出すbash スクリプトがありますfoo
:
フーコーラー
/path/to/foo
内でfoo
、 のパスを取得したいfoocaller
。この提案そのために次のコードを追加しました:
フー
#!/usr/bin/env ruby
puts File.read("/proc/#{Process.ppid}/cmdline")
実行すると:
$ bash foocaller
すると、次の結果が得られます。
bash^@/path/to/foocaller
しかし、直接電話するとfoocaller
:
$ foocaller
すると次のようになります:
/bin/bash^@--noediting^@-i
へのパスが表示されません。を使わずにを直接呼び出してfoocaller
へのパスを取得するにはどうすればよいでしょうか?foocaller
foocaller
bash
答え1
多くのシェルは、スクリプト内の最後のコマンドを同じプロセスで実行することで最適化します。
$ sh -c 'ps
ps'
PID TTY TIME CMD
32673 pts/3 00:00:00 zsh
32696 pts/3 00:00:00 sh
32697 pts/3 00:00:00 ps
PID TTY TIME CMD
32673 pts/3 00:00:00 zsh
32696 pts/3 00:00:00 ps
ps
最初に実行されたプロセス (32696) で2 番目が実行されsh
、その親が の親sh
(この場合はzsh
対話型シェル) になっていることを確認します。
次の行を追加することでこれを回避できますexit
。
#! /bin/sh -
foo
exit
sh
は、終了foo
後も解釈すべきことがまだあるため、同じプロセスで実行することはできません。そのため、代わりに別のプロセスで実行し、それを待機します。その後、を実行します(これにより、 と同じ終了ステータスでスクリプトが終了します)。foo
foo
exit
foo
ここでプロセスを節約できたはずなので、これはあまり最適ではありません。
foo
のパスについて知るためのより良い方法は、foocaller
次のように伝えることです。
#! /bin/sh -
CALLER=$0 foo
次に、環境変数をfoo
照会してCALLER
、呼び出し元のパスを取得します(import os;print(os.environ["CALLER"])
Pythonの場合)