* nixの世界では、どのスクリプトがそれを実行したかについての情報をシェルスクリプトが持つ方法はありますか?
例:
/path/to/script1 /path/to/script_xyz
この想像上のシナリオでscript_xyz
は、パス情報(/path/to/script1
)
または
プロセスPID
実行したエンティティの
注:さまざまなソリューションとアプローチに興味がありますが、実際にこれが実際に可能になるとは思わない
* nixの世界では、どのスクリプトがそれを実行したかについての情報をシェルスクリプトが持つ方法はありますか?
例:
/path/to/script1 /path/to/script_xyz
この想像上のシナリオでscript_xyz
は、パス情報(/path/to/script1
)
または
プロセスPID
実行したエンティティの
注:さまざまなソリューションとアプローチに興味がありますが、実際にこれが実際に可能になるとは思わない
回答:
プロセスの分岐と実行の間にはしばしば混乱があります。
bash
シェルのプロンプトで行うとき。
$ sh -c 'exec env ps'
そのプロンプトを発行するプロセスP1$
は現在bash
コードを実行しています。それbash
コードは、実行する新しいプロセスP2をフォークします。/bin/sh
/usr/bin/env
/bin/ps
だからP2順番にのコードを実行したbash
、sh
、env
とps
。
ps
(またはここで代わりに使用するスクリプトのような他のコマンド)は、env
コマンドによって実行されたことを知る方法がありません。
それは行うことができますすべては、このケースではどちらかと思われる、その親プロセスIDが何であるかを見つけることですP1または1
場合P1として指定されている別のプロセス間隔でまたはLinux上で死亡したsubreaperの代わりに1
。
次に、そのプロセスがどのコマンドであるかをシステムに照会できます 現在実行(readlink /proc/<pid>/exe
Linuxの場合など)または実行した最後のコマンドに渡された引数(など)ps -o args= -p <pid>
。
スクリプトが何を呼び出したかを知りたい場合、信頼できる方法は、呼び出し側にそれを伝えることです。これは、たとえば環境変数を介して実行できます。例えばscript1
ように書くことができます。
#! /bin/sh -
INVOKER=$0 script2 &
そして script2
:
#! /bin/sh -
printf '%s\n' "I was invoked by $INVOKER"
# and in this case, we'll probably find the parent process is 1
# (if not now, at least one second later) as script1 exited just after
# invoking script2:
ps -fp "$$"
sleep 1
ps -fp "$$"
exit
$INVOKER
(一般に)へのパスが含まれscript1
ます。ただし、場合によっては相対パスである可能性があります。このパスは、script1
開始時に現在の作業ディレクトリからの相対パスになります。したがって、をscript1
呼び出す前に現在の作業ディレクトリを変更するとscript2
、呼び出し元script2
に関する誤った情報が取得されます。そのため$INVOKER
、次のように記述して、絶対パスを含むようにすることscript1
をお勧めします(ベース名を保持することが望ましい)
#! /bin/sh -
mypath=$(
mydir=$(dirname -- "$0") &&
cd -P -- "$mydir" &&
pwd -P) && mypath=$mypath/$(basename -- "$0") || mypath=$0
... some code possibly changing the current working directory
INVOKER=$mypath script2
POSIXシェルで$PPID
は、シェルの初期化時にシェルを実行したプロセスの親のpidが含まれます。その後、上記のように、idのプロセスが停止$PPID
すると、親プロセスが変更される場合があります。
zsh
でzsh/system
、モジュール、照会することができ、現在と現在の(サブ)シェルの親のpidを$sysparams[ppid]
。POSIXシェルでは、でインタープリターを実行しているプロセスの現在の ppidを取得できます(まだ実行されていると仮定)ps -o ppid= -p "$$"
。ではbash
、あなたが現在(サブ)シェルのPPIDを取得することができますps -o ppid= -p "$BASHPID"
。
はい、プログラムはその親が誰であるかを知ることができます。
説明のために、2つのbashスクリプトを作成しましょう。最初のものはPIDを報告し、2番目のスクリプトを開始します。
$ cat s1.sh
#!/bin/bash
echo s1=$$
bash s2.sh
2番目のスクリプトは、プロセスID、親のPID、および親の実行に使用されるコマンドラインを報告します。
$ cat s2.sh
#!/bin/bash
echo s2=$$ PPID=$PPID
echo "Parent command: $(ps -o cmd= -q $PPID)"
それでは、実行してみましょう。
$ bash s1.sh
s1=17955
s2=17956 PPID=17955
Parent command: bash s1.sh
ご覧のとおり、2番目のスクリプトは実際にその親のPIDを知っています。を使用するとps
、そのPIDは親の呼び出しに使用されるコマンドラインを明らかにします。
PPIDの詳細については、StéphaneChazelasの回答を参照してください。
s1
、s2
およびPPID
後に複数行で、その後、値をが、ERROR: Unsupported SysV option.
空の値-追加説明として、いくつかのラインParent command
ps
して上記をテストしましたprocps-ng
。Jasenが提案したように、親のコマンドラインを印刷するために異なる構文を必要とする可能性のある異なるバージョンを使用している可能性があります。試してくださいps -f | grep $PPID
。