首页 > 解决方案 > 从 bash 脚本启动进程时的不同 pid

问题描述

我正在编写init.d脚本,但在保存分叉进程 pid 时遇到了一些问题。

这是我的初始化脚本片段:

sudo -u $USER nohup -- nice -n "0" java Test >> /dev/null 2>&1 < /dev/null &
NEWPID="$!"
echo $NEWPID

但是当我运行这个脚本时,我打印了以下 pid

$./scr.sh
4595

$ps  | grep java
 4596 pts/23   00:00:01 java

如您所见,pids 是不同的(45964595)。但是,如果尝试编写以下内容:

java Test &
NEWPID="$!"
echo $NEWPID

我得到了正确的结果:

$./scr.sh
4653
$ps  | grep java
 4653 pts/23   00:00:03 java

第一个有什么问题?

标签: linuxbashpid

解决方案


在一个效率低下的世界中,将涉及多个过程:

<the shell>   1234
    |
    |
  sudo        4595
    |
    |
  nohup       4596
    |
    |
  nice        4597
    |
    |
  java        4598

$!只指shell本身在后台启动的进程,也就是运行的进程sudojava,您感兴趣的进程位于进程 4598 中。您需要使用ps(或其他一些工具)来获取该进程 ID,因为 shell 不会知道它。


现实世界中,涉及的进程并不多,因为并非上述链中的每个作业都必须派生一个新进程;其中一些可以简单地用exec他们运行的程序替换自己。我认为sudo两者nice都这样做(nohup必须在不同的进程组中启动一个新进程才能完成它的工作)。所以链条看起来更像

<the shell>      1234
    |
    |
 sudo/nohup      4595
    |
    |
 nice/java       4596

但最终结果是一样的;shell 无法获取java最终运行的进程的进程 ID。


推荐阅读