首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >获取当前子subshell的pid

获取当前子subshell的pid
EN

Stack Overflow用户
提问于 2013-12-22 11:21:16
回答 6查看 18.1K关注 0票数 34

我正在尝试获取当前正在执行子外壳的pid -但$$仅返回父pid:

代码语言:javascript
复制
#!/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

输出

代码语言:javascript
复制
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。

EN

回答 6

Stack Overflow用户

发布于 2013-12-22 11:45:25

现代狂欢

如果您运行的是bash v4或更好的版本,那么可以在$BASHPID中找到该子subshell的PID。例如:

代码语言:javascript
复制
$ echo $$ $BASHPID ; ( echo $$ $BASHPID  )
32326 32326
32326 1519

在主shell中,$BASHPID$$相同。在subshell中,它被更新为subshell的PID。

旧bash ( 3.x或更早版本)

在版本4之前,您需要一个workaround

代码语言:javascript
复制
$ echo $$; ( : ; bash -c 'echo $PPID' )
11364
30279

(帽子提示: kubanczyk)

为什么是冒号?

请注意,在没有冒号的情况下,解决方法是不能使用

代码语言:javascript
复制
$ echo $$; ( bash -c 'echo $PPID' )
11364
11364

在上面的代码中,似乎从来没有创建子shell,因此第二个语句返回主shell的PID。相反,如果我们在括号中放入两个语句,则会创建子subshell,并且输出如我们所预期的那样。即使另一条语句只是一个冒号,:也是如此。在shell中,:是一个无操作:它什么也不做。然而,在我们的例子中,它确实强制创建子subshell,这足以完成我们想要的。

破折号

在类似debian的系统上,dash是默认的shell (/bin/sh)。PPID方法适用于dash,但还有另一个问题:

代码语言:javascript
复制
$ echo $$; (  dash -c 'echo $PPID' ) 
5791
5791
$ echo $$; ( : ; dash -c 'echo $PPID' )
5791
5791
$ echo $$; (  dash -c 'echo $PPID'; : )   
5791
20961

对于dash,将:命令放在命令之前是不够的,而将它放在命令之后是不够的。

POSIX

POSIX specification中包含PPID

可移植性

mklement0报告以下命令与bashdash zsh 的工作方式相同,但不适用于 ksh

代码语言:javascript
复制
echo $$; (sh -c 'echo $PPID' && :)
票数 48
EN

Stack Overflow用户

发布于 2013-12-22 11:31:08

输出是正确的。

这里来自bash的手册页。

特殊参数

shell对几个参数进行了特殊处理。这些参数只能引用,不允许赋值。

*扩展到位置参数,从1开始。当扩展发生在双引号内时,它将扩展为一个单词,每个参数的值由IFS特殊变量的第一个字符分隔。也就是说,"$*"等同于"$1c$2c...",其中c是IFS值的第一个字符。如果未设置IFS,则参数之间用空格分隔。如果IFS为null,则在没有中间分隔符的情况下连接参数。

@扩展到位置参数,从1开始。当扩展出现在双引号内时,每个参数都扩展为一个单独的单词。也就是说,如果双引号扩展出现在单词内,则"$@"等效于"$1" "$2" ...,第一个参数的扩展与原始单词的开头部分连接,最后一个参数的扩展与原始单词的最后部分连接。当没有位置参数时,"$@"$@展开为空(即,它们被删除)。

#扩展为以十进制表示的位置参数数量。

?扩展到最近执行的前台管道的退出状态。

在调用时,通过设置内置命令或由-本身设置的那些选项(如-i选项),shell将扩展到当前的选项标志。

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

!扩展为最近执行的后台(异步)命令的进程ID。

要获得子subshell中的PID,可以使用BASHPID。这是一个仅限bash的环境变量。

您的新脚本将如下所示。

代码语言:javascript
复制
#!/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
票数 5
EN

Stack Overflow用户

发布于 2018-09-25 20:39:47

如果您使用Linux-kernel,您可以使用Linux-kernel的/proc/self特性来完成此操作:

最简单的形式:cd -P /proc/self && basename "${PWD}"

保留PWDOLDPWD变量:PWD_BACKUP="${PWD}";OLDPWD_BACKUP="${OLDPWD}";cd -P /proc/self && basename "${PWD}";cd "${PWD_BACKUP}";OLDPWD="${OLDPWD_BACKUP}"

例如:

代码语言:javascript
复制
$ cd -P /proc/self && basename "${PWD}"
26758
$ (cd -P /proc/self && basename "${PWD}")
26959
$ (cd -P /proc/self && basename "${PWD}")
26961
$ 
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/20725925

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档