如何在命令行上获取bash子进程的进程id

时间:2012-02-02 20:56:24

标签: macos bash shell unix process

我知道在bash中我们可以使用圆括号()创建子壳。根据bash手册页:

(list) list  is  executed  in  a  subshell environment 

另外,为了获得当前进程ID ,我们使用:

echo $$

现在我的问题是如何在命令行中使用()获取子shell的进程ID?

如果我使用它:

echo $$; ( echo $$; ) 

我将在stdout上打印父shell的进程ID ,因为$$在创建subshel​​l之前就已展开。那么如何真正强迫懒惰的扩张呢?

[解决方案应该适用于Mac,而不仅仅适用于Linux]

更新

建议的关联答案不起作用,因为我的Mac上的echo $BASHPID 不起作用并返回空白。

6 个答案:

答案 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_)