【问题标题】: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;
   }

让我困惑的是:

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

你能帮帮我吗?

【问题讨论】:

  • 请注意,getpid 会显示不同的进程 ID,即使它没有在子 shell 中运行。
  • @Marian echo $$ $BASHPID ; ( echo $$ $BASHPID ) 证明确实如此。圆括号创建一个子外壳。这些语句可能会更改变量值,并且父 shell 不能看到这些更改。这是作为fork() 操作实现的。

标签: bash shell pid subshell


【解决方案1】:

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

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

bash4中,可以通过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】:
  1. 括号调用subshell in Bash。由于它只是一个子外壳,它可能具有相同的 PID - 取决于实现。
  2. 您调用的 C 程序是一个单独的进程,它有自己唯一的 PID - 是否在子 shell 中无关紧要。
  3. $$ 是 Bash 中 the current script PID 的别名。请参阅differences between $$ and $BASHPID here,以及正上方包含嵌套级别的附加变量$BASH_SUBSHELL

【讨论】:

    【解决方案4】:

    如果您希望 C 程序打印 shell 的 PID,请尝试 getppid()

    【讨论】:

    【解决方案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。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-12-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-06-29
        • 1970-01-01
        • 2014-05-18
        相关资源
        最近更新 更多