在*nix世界中,shell脚本有没有办法获得有关哪个程序执行了它的信息?
例子:
/path/to/script1 /path/to/script_xyz
在这个假想的场景中,script_xyz
将有路径信息 ( /path/to/script1
)
或者
过程PID
执行它的实体。
注意:我对不同的解决方案和方法感到好奇,我并不认为这实际上是可能的
答案1
进程分叉和执行之间经常会出现混淆。
当您在 shell 的提示下执行此操作时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 上另一个被指定为副收割者代替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 shell 中,$PPID
将包含在该 shell 初始化时执行该 shell 的父进程的 pid。之后,如上所示,如果 id 的进程$PPID
死亡,父进程可能会发生变化。
zsh
在zsh/system
模块中,可以查询当前的当前(子)shell 的父 pid,后缀为$sysparams[ppid]
.在 POSIX shell 中,您可以获得当前的执行解释器的进程的 ppid(假设它仍在运行),带有ps -o ppid= -p "$$"
.使用bash
,您可以使用 获取当前(子)shell 的 ppid ps -o ppid= -p "$BASHPID"
。
答案2
是的,程序可以知道它的父程序是谁。
为了说明这一点,我们创建两个 bash 脚本。第一个脚本报告其 PID 并启动第二个脚本:
$ cat s1.sh
#!/bin/bash
echo s1=$$
bash s2.sh
第二个脚本报告其进程 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
正如您所看到的,第二个脚本实际上知道其父脚本的 PID。使用ps
,该 PID 显示用于调用父级的命令行。
有关 PPID 的更深入讨论,请参阅 Stéphane Chazelas 的回答。