如何获取子shell的pid?
例如:
$ echo $$
16808
这不起作用,因为原始外壳会扩展$$
:
$ ( echo $$ )
16808
为什么单引号不起作用?原shell去掉单引号后,子shell$$
本身不展开吗?
$ ( echo '$$' )
$$
为什么eval
也不起作用?是eval
由子shell运行的吗?为什么它给我原始 shell 的 PID?
$ ( eval echo '$$' )
16808
谢谢。
答案1
$ echo $BASHPID
37152
$ ( echo $BASHPID )
18633
从手册中:
BASHPID
扩展为当前 bash 进程的进程 ID。这与
$$
某些情况下不同,例如不需要重新初始化 bash 的子 shell。
$
扩展为 shell 的进程 ID。在
()
子 shell 中,它扩展为当前 shell 的进程 ID,而不是子 shell。
有关的:
- 括号真的将命令放入子 shell 中吗?,尤其是部分吉尔斯的回答。
答案2
除了bash
s之外$BASHPID
,您还可以使用以下方法进行移植:
pid=$(exec sh -c 'echo "$PPID"')
例子:
(pid=$(exec sh -c 'echo "$PPID"'); echo "$$ $pid")
您可以将其变成一个函数:
# usage getpid [varname]
getpid(){
pid=$(exec sh -c 'echo "$PPID"')
test "$1" && eval "$1=\$pid"
}
请注意,某些 shell(例如zsh
或ksh93
)不会为使用 ; 创建的每个子 shell 启动子进程(...)
。在这种情况下,$pid
最终可能与 相同,这是正确的,因为这是调用$$
进程的 PID 。getpid
答案3
在 Linux 上,不生成新进程的跨 shell 解决方案(至少是 dash、bash、zsh)是
read -r this_pid < /proc/self/stat; echo ${this_pid%% *}
至少在 bash 和 zsh 中我们还可以使用空格作为读取分隔符:
read -d ' ' this_pid < /proc/self/stat ; echo $this_pid
也可以看看人5过程 /proc/[pid]/stat 节
答案4
要回答最初的“为什么”问题 - 为什么不$$
扩展到子shell pid,甚至懒惰地评估eval
?
引用POSIX 文档:
$
扩展为所调用 shell 的十进制进程 ID。在子 shell 中(请参阅 Shell 执行环境),“$”应扩展为与当前 shell 相同的值。