为什么$$返回与父进程相同的ID?


159

我对Bash有问题,我也不知道为什么。
在shell下,我输入:

echo $$    ## print 2433
(echo $$)  ## also print 2433
(./getpid) ## print 2602

“ getpid”是获取当前pid的C程序,例如:

   int main() {
    printf("%d", (int)getpid());
    return 0;
   }

让我感到困惑的是:

  1. 我认为“(命令)”是一个子进程(对吗?),我认为其pid应该与其父pid不同,但是它们是相同的,为什么...
  2. 当我使用程序在括号之间显示pid时,显示的pid不同,对吗?
  3. 是“ $$”之类的宏吗?

你能帮助我吗?


8
请注意,getpid即使未在子Shell中运行,也会显示不同的进程ID。
chepner 2014年

1
@Marian echo $$ $BASHPID ; ( echo $$ $BASHPID )证明了。圆括号创建一个子壳。这些语句可能会更改变量值,并且父外壳程序不得看到这些更改。这被实现为fork()操作。

Answers:


222

$$定义为在子shell中返回父级的进程ID;从手册页的“特殊参数”下:

$扩展为shell的进程ID。在()子外壳程序中,它扩展为当前外壳程序的进程ID,而不是子外壳程序。

bash4中,您可以使用获得子进程的ID BASHPID

~ $ echo $$
17601
~ $ ( echo $$; echo $BASHPID )
17601
17634

16
“父母”有点误导(至少对我来说是这样),它实际上是“顶层”外壳。例如:echo $$; (echo $$; (echo $$))
重复

1
对; 我应该说该值从父壳(其继承其值继承母体,等等)。顶层shell最初对其进行设置,而不是从其(非shell)父进程继承。
chepner

$ Expands to the process ID of the shell是吗?echo $只是回显文字$。
亚历山大·米尔斯

@AlexanderMills好吧,是的;$单独不是参数扩展。手册页指的是特殊参数的名称,即$;。并不是说有$单独的扩张。
chepner

好的,老实说,我不知道这是什么意思,但是echo $BASHPID可以在bash 4和5中使用(但不适用于MacOS上的3.2.57版)
Alexander Mills,

81

您可以使用以下之一。

  • $! 是最后一个后台进程的PID。
  • kill -0 $PID 检查它是否仍在运行。
  • $$ 是当前外壳的PID。

2
kill -0 $!如果我们在谈论后台流程,那第二个子弹不应该吗?PID默认情况下未设置为任何值。
艾萨克·弗里曼



2

如果您要询问如何获取已知命令的PID,它将类似于以下内容:

如果您已在下面发出命令#发出的命令是***

dd if = / dev / diskx of = / dev / disky


然后,您将使用:

PIDs=$(ps | grep dd | grep if | cut -b 1-5)

这里发生的事情是将所有需要的唯一字符通过管道传递到一个字段,并且可以使用以下命令回显该字段

回显$ PID


1

这是一种获取正确pid的普遍方式

pid=$(cut -d' ' -f4 < /proc/self/stat)

同样不错的工作

SUB(){
    pid=$(cut -d' ' -f4 < /proc/self/stat)
    echo "$$ != $pid"
}

echo "pid = $$"

(SUB)

检查输出

pid = 8099
8099 != 8100

这是个好主意,但是难道不是让shell捕捉到了cut的输出的叉子的pid吗?如果我运行两次,一次使用echo $(...),一次不使用echo,那么我会得到不同的答案。
马丁·多瑞
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.