为啥 $$ 返回与父进程相同的 id?
Posted
技术标签:
【中文标题】为啥 $$ 返回与父进程相同的 id?【英文标题】:Why is $$ returning the same id as the parent process?为什么 $$ 返回与父进程相同的 id? 【发布时间】:2014-01-30 13:46:49 【问题描述】:我在使用 Bash 时遇到问题,我不知道为什么。 在shell下,我输入:
echo $$ ## print 2433
(echo $$) ## also print 2433
(./getpid) ## print 2602
“getpid”是一个获取当前pid的C程序,如:
int main() printf("%d", (int)getpid()); return 0;
让我困惑的是:
-
我认为“(command)”是一个子进程(对吗?),我认为它的 pid 应该与它的父 pid 不同,但它们是相同的,为什么......
当我使用我的程序在括号之间显示 pid 时,它显示的 pid 是不同的,对吗?
'$$' 是不是类似于宏?
你能帮帮我吗?
【问题讨论】:
请注意,getpid
会显示不同的进程 ID,即使它没有在子 shell 中运行。
@Marian echo $$ $BASHPID ; ( echo $$ $BASHPID )
证明确实如此。圆括号创建一个子外壳。这些语句可能会更改变量值,并且父 shell 不能看到这些更改。这是作为fork()
操作实现的。
【参考方案1】:
$$
被定义为返回子shell中父进程ID;来自“特殊参数”下的手册页:
$ 扩展为 shell 的进程 ID。在 () 子shell 中,它扩展为当前shell 的进程ID,而不是子shell。
在bash
4中,可以通过BASHPID
获取子进程ID。
~ $ echo $$
17601
~ $ ( echo $$; echo $BASHPID )
17601
17634
【讨论】:
"parent" 有点误导(至少对我来说是这样),它实际上是“***”外壳。例如:echo $$; (echo $$; (echo $$))
三次回显同一个 pid
对;我应该说该值是从父 shell 继承的(它从 its 父 shell 等继承了它的值)。*** shell 最初设置它,而不是从其(非 shell)父进程继承。
$ Expands to the process ID of the shell
是吗? echo $
只是与文字 $ 相呼应。
好吧,我真的不知道这意味着什么,但echo $BASHPID
在 bash 4 和 5 中工作(但在 MacOS 上不是 3.2.57 版)
所有参数扩展都以$
开头,但$
也是特殊参数之一的名称。 $
、#
、@
、*
等是一些特殊参数; $$
、$#
、$@
、$*
等是扩展为每个值的表达式。【参考方案2】:
您可以使用以下方法之一。
$!
是最后一个后台进程的 PID。
kill -0 $PID
检查它是否仍在运行。
$$
是当前 shell 的 PID。
【讨论】:
如果我们在谈论后台进程,第二个子弹不应该是kill -0 $!
吗? PID
默认没有设置任何东西。【参考方案3】:
-
括号调用subshell in Bash。由于它只是一个子外壳,它可能具有相同的 PID - 取决于实现。
您调用的 C 程序是一个单独的进程,它有自己唯一的 PID - 是否在子 shell 中无关紧要。
$$
是 Bash 中 the current script PID 的别名。请参阅differences between $$
and $BASHPID
here,以及正上方包含嵌套级别的附加变量$BASH_SUBSHELL
。
【讨论】:
【参考方案4】:如果您希望 C 程序打印 shell 的 PID,请尝试 getppid()
。
【讨论】:
或者如果你使用 Rust,只需尝试nix::unistd::getppid()
,它将获得当前进程父进程的 pid - docs.rs/nix/0.18.0/nix/unistd/fn.getppid.html【参考方案5】:
这是获得正确 pid 的一种通用方法
pid=$(cut -d' ' -f4 < /proc/self/stat)
同样适用于 sub
SUB()
pid=$(cut -d' ' -f4 < /proc/self/stat)
echo "$$ != $pid"
echo "pid = $$"
(SUB)
检查输出
pid = 8099
8099 != 8100
【讨论】:
好主意,但这不会让你得到 shell 运行的 fork 的 pid 来捕获 cut 的输出吗?如果我运行它两次,一次使用 echo $(...) 一次没有,然后我会得到不同的答案。【参考方案6】:如果您询问如何获取已知命令的 PID,它类似于以下内容:
如果您发出了以下命令 #发出的命令是***
dd if=/dev/diskx of=/dev/disky
那么你会使用:
PIDs=$(ps | grep dd | grep if | cut -b 1-5)
这里发生的事情是将所有需要的唯一字符通过管道传输到一个字段,并且可以使用该字段来回显
回显 $PIDs
【讨论】:
【参考方案7】:如果您想要一个简单的 shell 脚本来获取带有变量的最大 PID,请执行此操作
pid=$(cat /proc/sys/kernel/pid_max)
echo $pid
这将打印出最大的 PID。
【讨论】:
以上是关于为啥 $$ 返回与父进程相同的 id?的主要内容,如果未能解决你的问题,请参考以下文章