我正在尝试获取当前正在执行的子shell的pid - 但$$
仅返回父pid:
#!/usr/bin/sh
x() {
echo "I am a subshell x echo 1 and my pid is $$"
}
y() {
echo "I am a subshell y echo 1 and my pid is $$"
}
echo "I am the parent shell and my pid is $$"
x &
echo "Just launched x and the pid is $! "
y &
echo "Just launched y and the pid is $! "
wait
输出
I am the parent shell and my pid is 3107
Just launched x and the pid is 3108
I am a subshell x echo 1 and my pid is 3107
Just launched y and the pid is 3109
I am a subshell y echo 1 and my pid is 3107
正如您在上面所看到的,当我从我已经背景的函数运行$$
时,它不会像我从父shell那样$!
显示PID。
答案 0 :(得分:38)
如果您正在运行bash v4或更高版本,子shell的PID可在$BASHPID
中使用。例如:
$ echo $$ $BASHPID ; ( echo $$ $BASHPID )
32326 32326
32326 1519
在主shell中,$BASHPID
与$$
相同。在子shell中,它被更新为子shell的PID。
在第4版之前,您需要workaround:
$ echo $$; ( : ; bash -c 'echo $PPID' )
11364
30279
(帽子小贴士:kubanczyk)
请注意,如果没有冒号,解决办法不工作:
$ echo $$; ( bash -c 'echo $PPID' )
11364
11364
看来,在上面,从未创建子shell,因此第二个语句返回主shell的PID。相比之下,如果我们在parens中放入两个语句,则会创建子shell并且输出正如我们所期望的那样。即使另一个语句仅仅是冒号:
,也是如此。在shell中,:
是一个无操作:它什么都不做。在我们的例子中,它确实强制创建子壳,这足以完成我们想要的任务。
在类似debian的系统上,dash
是默认shell(/bin/sh
)。 PPID
方法适用于dash
,但还有另一种转折:
$ echo $$; ( dash -c 'echo $PPID' )
5791
5791
$ echo $$; ( : ; dash -c 'echo $PPID' )
5791
5791
$ echo $$; ( dash -c 'echo $PPID'; : )
5791
20961
使用dash
,在命令之前放置:
命令是不够的,但将其放在is之后。
PPID
包含在POSIX specification。
mklement0报告以下内容适用于bash
,dash
,和 zsh
,但不是 {{1} }:
ksh
答案 1 :(得分:5)
输出正确。
这是来自bash的手册页。
特殊参数
shell专门处理几个参数。这些参数只能被引用;不允许分配给他们。
*
从1开始扩展到位置参数。当扩展发生在双引号内时,它会扩展为单个单词,其值为each 参数由IFS特殊变量的第一个字符分隔。也就是说,"$*"
相当于"$1c$2c..."
,其中c是第一个字符 IFS变量的值。如果未设置IFS,则参数由空格分隔。如果IFS为null,则参数在没有插入分隔符的情况下连接@
从1开始扩展到位置参数。当扩展发生在双引号内时,每个参数都会扩展为单独的单词。那 是,"$@"
等价于"$1" "$2" ...
如果双引号扩展发生在一个单词中,则第一个参数的扩展与原始单词的开头部分连接,并扩展最后一个参数加上原始单词的最后一部分。没有位置时 参数,"$@"
和$@
扩展为空(即,它们被删除)#
扩展为十进制位置参数的数量?
扩展到最近执行的前台管道的退出状态-
扩展为调用时指定的当前选项标志,set builtin命令或shell本身设置的那些(例如-i
选项)。
$
扩展为shell的进程ID。在()
子shell中,它扩展为当前shell的进程ID,而不是子shell!
扩展到最近执行的后台(异步)命令的进程ID。
要在子shell中获取PID,可以使用BASHPID。这是一个仅限bash的env变量。
您的新脚本将如下所示。
#!/bin/bash
x() {
echo "I am a subshell x echo 1 and my pid is $BASHPID"
}
y() {
eval echo "I am a subshell y echo 1 and my pid is $BASHPID"
}
echo "I am the parent shell and my pid is $$"
x &
echo "Just launched x and the pid is $! "
y &
echo "Just launched y and the pid is $! "
wait
答案 2 :(得分:1)
@ John1024的答案很好,但是那里有一个小问题。
当命令像(...)一样运行时,该命令将在新的子进程中运行,因此
( : ; bash -c 'echo $PPID' )
将返回(...)的process_id,而不是调用(...)的函数的进程ID。
如果需要函数的process_id,则可以运行:
$SHELL -c 'echo $PPID'
和process_id将输出到stderr
如果要通过变量获取函数的process_id,可以运行:
$SHELL -c 'echo $PPID' | read -s func_pid
然后您可以从变量$ {func_pid}中获取pid。
注意:请勿在(...)中运行此命令,否则将返回(...)的process_id
答案 3 :(得分:0)
环境:
SUSE Linux Enterprise Server 10 SP2(i586)
GNU bash,版本3.1.17(1)-release(i586-suse-linux) 版权所有(C)2005 Free Software Foundation,Inc。
#!/usr/bin/sh
x() {
mypid=$(awk 'BEGIN {print PROCINFO["ppid"] ; exit}')
echo "I am a subshell x echo 1 and my pid is $mypid"
}
y() {
mypid=$(awk 'BEGIN {print PROCINFO["ppid"] ; exit}')
echo "I am a subshell y echo 1 and my pid is $mypid"
}
echo "I am the parent shell and my pid is $$"
x &
echo "Just launched x and the pid is $! "
y &
echo "Just launched y and the pid is $! "
wait
结果:
I am the parent shell and my pid is 27645
Just launched x and the pid is 27646
Just launched y and the pid is 27647
I am a subshell y echo 1 and my pid is 27647
I am a subshell x echo 1 and my pid is 27646
答案 4 :(得分:0)
如果您使用Linux内核,则可以使用Linux内核的/proc/self
功能来做到这一点:
最简单的形式:cd -P /proc/self && basename "${PWD}"
要保留PWD
和OLDPWD
变量:PWD_BACKUP="${PWD}";OLDPWD_BACKUP="${OLDPWD}";cd -P /proc/self && basename "${PWD}";cd "${PWD_BACKUP}";OLDPWD="${OLDPWD_BACKUP}"
例如:
$ cd -P /proc/self && basename "${PWD}"
26758
$ (cd -P /proc/self && basename "${PWD}")
26959
$ (cd -P /proc/self && basename "${PWD}")
26961
$
答案 5 :(得分:0)
最好使用 function test(value){
return value+ “hi”;
}
而不是John1024答案中显示的技巧(这些技巧目前在我撰写答复时无法在现代shell中使用)。
看到以下问题: https://unix.stackexchange.com/questions/484442/how-can-i-get-the-pid-of-a-subshell