我知道在bash中我们可以使用圆括号(
和)
创建子壳。根据bash手册页:
(list) list is executed in a subshell environment
另外,为了获得当前进程ID ,我们使用:
echo $$
现在我的问题是如何在命令行中使用(
和)
获取子shell的进程ID?
如果我使用它:
echo $$; ( echo $$; )
我将在stdout上打印父shell的进程ID ,因为$$
在创建subshell之前就已展开。那么如何真正强迫懒惰的扩张呢?
[解决方案应该适用于Mac,而不仅仅适用于Linux]
建议的关联答案不起作用,因为我的Mac上的echo $BASHPID
不起作用并返回空白。
答案 0 :(得分:18)
感谢大家花了宝贵的时间在这里找到我的问题的答案。
但是我现在正在回答我自己的问题,因为我发现了 hack 方法来获取bash ver< 4(虽然适用于所有版本)。这是命令:
echo $$; ( F='/tmp/myps'; [ ! -f $F ] && echo 'echo $PPID' > $F; )
打印:
5642
13715
其中13715是子壳的pid。我这样做时要测试:
echo $$; ( F='/tmp/myps'; [ ! -f $F ] && echo 'echo $PPID' > $F; bash $F; ps; )
我明白了:
5642
13773
PID TT STAT TIME COMMAND
5642 s001 S 0:02.07 -bash
13773 s001 S+ 0:00.00 -bash
告诉我13773确实是子壳的pid。
注意:我恢复了原来的解决方案,因为@ChrisDodd评论说echo $$; ( bash -c 'echo $PPID'; )
不适用于Linux。我的上述解决方案适用于Mac和Linux。
答案 1 :(得分:7)
不幸的是,在引入$ BASHPID之前,在bash版本4之前没有简单的方法可以做到这一点。你可以做的一件事就是编写一个打印其父PID的小程序:
int main()
{
printf("%d\n", getppid());
return 0;
}
如果您将其编译为ppid
并将其放在路径中,则可以调用它,例如:
$ (echo $$; ppid)
2139
29519
$ (x=$(ppid); echo $x)
29521
然而,我注意到的一个奇怪的是,如果你写
$ (ppid)
它实际上似乎没有在子shell中运行它 - 你需要在括号内至少有两个命令让bash实际在子shell中运行它们。
答案 2 :(得分:4)
你可以这样做:
$ ( your_action ) &
[1] 44012
找到子进程'PID那样:
$ echo "The sub PID : $!"
The Sub PID : 44012
$!
返回后台PID中的最后一个作业。 (见this manual)
答案 3 :(得分:2)
使用自制软件在Mac上安装pgrep:brew install pgrep
查看http://mxcl.github.com/homebrew/以安装Homebrew。
答案 4 :(得分:1)
这似乎有效:
(echo $$; echo `ps axo pid,command,args | grep "$$" |awk '{ getline;print $1}'`)
14609
17365
无论出于何种原因,OSX是有限的,并没有附带pgrep,或者可以做(在Linux中有效):
(echo $$; echo `pgrep -P $$`)
14609
17390
答案 5 :(得分:1)
当您第一次进入shell时,您可以通过回显父项的ppid
来使用父项的BASHPID
,然后您可以查看该过程,并可以通过pid
来查找ppid
使用父pid
。
E.g。获取在子shell中后面的sleep 555
命令的pid:
(echo "$BASHPID" > /tmp/_tmp_pid_ && sleep 555 &) && ps -ho pid --ppid=$(< /tmp/_tmp_pid_)