bash 获取当前子shell的pid
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/20725925/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Get pid of current subshell
提问by awojo
I am trying to get the pid of a currently executing subshell - but $$
is only returning the parent pid:
我正在尝试获取当前正在执行的子 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
Output
输出
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
As you can see above, when I run $$
from the function that I've backgrounded, it does not display the PID as when I do $!
from the parent shell.
正如您在上面看到的,当我$$
从后台运行的函数中运行时,它不会像$!
从父 shell中那样显示 PID 。
回答by John1024
Modern bash
现代狂欢
If you are running bash v4 or better, the PID of the subshell is available in $BASHPID
. For example:
如果您运行的是 bash v4 或更高版本,则子 shell 的 PID 在$BASHPID
. 例如:
$ echo $$ $BASHPID ; ( echo $$ $BASHPID )
32326 32326
32326 1519
In the main shell, $BASHPID
is the same as $$
. In the subshell, it is updated to the subshell's PID.
在主 shell 中,$BASHPID
与$$
. 在子外壳中,它被更新为子外壳的 PID。
Old bash (Version 3.x or Earlier)
旧 bash(版本 3.x 或更早版本)
Pre version 4, you need a workaround:
在版本 4 之前,您需要一个解决方法:
$ echo $$; ( : ; bash -c 'echo $PPID' )
11364
30279
(Hat tip: kubanczyk)
(帽子提示:kubanczyk)
Why the colon?
为什么是结肠?
Notice that, without the colon, the work-around does notwork:
请注意,没有冒号,工作,各地确实不工作:
$ echo $$; ( bash -c 'echo $PPID' )
11364
11364
It appears that, in the above, a subshell is never created and hence the second statement returns the main shell's PID. By contrast, if we put two statements inside the parens, the subshell is created and the output is as we expect. This is true even if the other statement is a mere colon, :
. In shell, the :
is a no-operation: it does nothing. It does, in our case however, force the creation of the subshell which is enough to accomplish what we want.
看起来,在上面,从来没有创建子shell,因此第二个语句返回主shell的PID。相比之下,如果我们将两个语句放在括号内,就会创建子shell,并且输出如我们预期的那样。即使另一个语句只是一个冒号,也是如此:
。在 shell 中,这:
是一个无操作:它什么都不做。然而,在我们的例子中,它确实会强制创建足以完成我们想要的子shell。
Dash
短跑
On debian-like systems, dash
is the default shell (/bin/sh
). The PPID
approach works for dash
but with yet another twist:
在类似 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
With dash
, placing the :
command before the command is not sufficient but placing it after is.
使用dash
,将:
命令放在命令之前是不够的,但将其放在之后是。
POSIX
POSIX
PPID
is included in the POSIX specification.
PPID
包含在POSIX 规范中。
Portability
可移植性
mklement0 reports that the following works as is with bash
, dash
, andzsh
but notksh
:
mklement0报道,以下作品是bash
,dash
,和zsh
而不是ksh
:
echo $$; (sh -c 'echo $PPID' && :)
回答by alvits
The output is correct.
输出是正确的。
Here's from the man page of bash.
这是来自bash的手册页。
Special Parameters
The shell treats several parameters specially. These parameters may only be referenced; assignment to them is not allowed.
*
Expands to the positional parameters, starting from one. When the expansion occurs within double quotes, it expands to a single word with the value of each parameter separated by the first character of the IFS special variable. That is,"$*"
is equivalent to"$1c$2c..."
, where c is the first character of the value of the IFS variable. If IFS is unset, the parameters are separated by spaces. If IFS is null, the parameters are joined without intervening separators.@
Expands to the positional parameters, starting from one. When the expansion occurs within double quotes, each parameter expands to a separate word. That is,"$@"
is equivalent to"$1" "$2" ...
If the double-quoted expansion occurs within a word, the expansion of the first parameter is joined with the beginning part of the original word, and the expansion of the last parameter is joined with the last part of the original word. When there are no positional parameters,"$@"
and$@
expand to nothing (i.e., they are removed).#
Expands to the number of positional parameters in decimal.?
Expands to the exit status of the most recently executed foreground pipeline.-
Expands to the current option flags as specified upon invocation, by the set builtin command, or those set by the shell itself (such as the-i
option).$
Expands to the process ID of the shell. In a()
subshell, it expands to the process ID of the current shell, not the subshell.!
Expands to the process ID of the most recently executed background (asynchronous) command.
特殊参数
shell 对几个参数进行了特殊处理。这些参数只能被引用;不允许分配给他们。
*
扩展到位置参数,从 1 开始。当扩展发生在双引号内时,它扩展为单个单词,每个参数的值由 IFS 特殊变量的第一个字符分隔。也就是说,"$*"
相当于"$1c$2c..."
,其中 c 是 IFS 变量值的第一个字符。如果未设置 IFS,则参数以空格分隔。如果 IFS 为空,则连接参数时不插入分隔符。@
扩展到位置参数,从 1 开始。当扩展发生在双引号内时,每个参数都扩展为一个单独的词。也就是说,"$@"
等价于"$1" "$2" ...
如果双引号扩展发生在一个词内,则第一个参数的扩展与原词的开头部分连接,最后一个参数的扩展与原词的最后部分连接。当有没有位置参数,"$@"
并且$@
扩大到什么(即,它们被删除)。#
扩展到十进制位置参数的数量。?
扩展到最近执行的前台管道的退出状态。-
扩展到调用时指定的当前选项标志,由 set 内置命令或由 shell 本身设置的那些(例如-i
选项)。$
扩展到 shell 的进程 ID。在一个()
subshell,它扩展到当前 shell 的进程 ID,而不是 subshell。!
扩展到最近执行的后台(异步)命令的进程 ID。
To get the PID inside of a subshell, you may use BASHPID. This is a bash only env variable.
要在子外壳中获取 PID,您可以使用 BASHPID。这是一个仅限 bash 的环境变量。
Your new script will look like this.
您的新脚本将如下所示。
#!/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
回答by Panda
@John1024 's answer is great, but there's a little problem in there.
@John1024 的回答很好,但那里有一个小问题。
when a command run like (...), the command will run in a new subprocess, so
当一个命令像 (...) 一样运行时,该命令将在一个新的子进程中运行,所以
( : ; bash -c 'echo $PPID' )
will return process_id of (...), not the function's process id that call (...)
将返回(...)的process_id,而不是调用(...)的函数的进程ID
if you want the function's process_id, you can just run:
如果你想要函数的 process_id,你可以运行:
$SHELL -c 'echo $PPID'
and the process_id will be outputed to stderr
并且 process_id 将输出到 stderr
if you want get the function's process_id form a variable, you can run:
如果你想从一个变量中获取函数的 process_id,你可以运行:
$SHELL -c 'echo $PPID' | read -s func_pid
then you can get the pid from variable ${func_pid}
然后你可以从变量 ${func_pid} 中获取 pid
note: don't run this command in (...), otherwise it'll return the process_id of (...)
注意:不要在(...)中运行这个命令,否则会返回(...)的process_id
回答by illiterate
If you use Linux-kernel, you can use Linux-kernel's /proc/self
feature to do this:
如果你使用 Linux-kernel,你可以使用 Linux-kernel 的/proc/self
特性来做到这一点:
In simplest form: cd -P /proc/self && basename "${PWD}"
以最简单的形式: cd -P /proc/self && basename "${PWD}"
To keep the PWD
and OLDPWD
variable: PWD_BACKUP="${PWD}";OLDPWD_BACKUP="${OLDPWD}";cd -P /proc/self && basename "${PWD}";cd "${PWD_BACKUP}";OLDPWD="${OLDPWD_BACKUP}"
保持PWD
和OLDPWD
变量:PWD_BACKUP="${PWD}";OLDPWD_BACKUP="${OLDPWD}";cd -P /proc/self && basename "${PWD}";cd "${PWD_BACKUP}";OLDPWD="${OLDPWD_BACKUP}"
For example:
例如:
$ cd -P /proc/self && basename "${PWD}"
26758
$ (cd -P /proc/self && basename "${PWD}")
26959
$ (cd -P /proc/self && basename "${PWD}")
26961
$
回答by fk0
It's better to use $(exec sh -c 'echo $PPID')
rather than tricks shown in answer by John1024 (those tricks not work witn modern shells at present time, when I writing my reply).
最好使用$(exec sh -c 'echo $PPID')
而不是 John1024 回答中显示的技巧(当我写我的回复时,这些技巧目前不适用于现代 shell)。
See this question: https://unix.stackexchange.com/questions/484442/how-can-i-get-the-pid-of-a-subshell
看到这个问题:https: //unix.stackexchange.com/questions/484442/how-can-i-get-the-pid-of-a-subshell
回答by jramos
Environment:
环境:
SUSE Linux Enterprise Server 10 SP2 (i586)
SUSE Linux Enterprise Server 10 SP2 (i586)
GNU bash, version 3.1.17(1)-release (i586-suse-linux) Copyright (C) 2005 Free Software Foundation, Inc.
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
Result:
结果:
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