获得NOHUP进程的PID
1. 概述
有时我们在后台运行命令,因为它可能需要很长时间才能完成。通常,如果我们在后台作业运行时注销,它会被终止。但是,我们可以使用nohup 命令运行即使我们注销也会继续运行的作业。 稍后,在注销并再次登录后,我们可能需要获取我们在后台启动的进程的进程标识符 ( PID )。例如,我们可能想检查它是否仍在运行。
在本教程中,我们将了解如何使用nohup获取后台进程的 PID 。我们还将触及shopt 命令的huponexit选项,因为它与nohup相关。
2. 获取使用nohup命令执行的进程的 PID
让我们使用nohup在后台启动一个进程:
$ bash -l
$ nohup sleep infinity >& nohup.out &
[1] 20634
$ exit
logout
$
首先,我们使用bash命令启动了一个交互式登录 shell 。bash的*-l*选项 将 shell 作为登录 shell 启动。
然后,我们使用nohup在后台启动了一个进程sleep infinity。我们将标准输出和标准错误重定向到文件nohup.out。
最后,我们使用exit 命令退出了交互式登录 shell 。
2.1. 在启动过程时保存 PID
当我们使用上面的nohup启动进程 时,命令执行的输出是 [1] 20634。括号内的数字1是作业 ID。作业 ID 后面的数字20634是通过执行sleep infinity命令生成的进程的 PID。
我们可以稍后使用这个 PID 来检查或控制过程。例如,我们可以检查进程是否还在运行:
$ ps -ef -o pid | grep 20634
20634
与其手动记下进程的 PID 以记住它,我们可以将 PID 保存到文件中并稍后使用:
$ bash -l
$ nohup sleep infinity >& nohup.out &
[1] 21443
$ echo $! > $HOME/pid.nohup
$ exit
logout
$ cat $HOME/pid.nohup
21443
现在,我们将 PID 存储在文件*$HOME/pid.nohup中。$!* 是在后台运行的最后一个命令的 PID,在我们的例子中是sleep infinity。
因此,我们可以稍后使用这个 PID,例如,杀死进程:
$ kill -9 `cat $HOME/pid.nohup`
[1]+ Killed nohup sleep infinity
2.2. 使用ps命令
如果我们在使用nohup启动进程时忘记记下进程的 PID ,我们可以稍后使用ps 获取它。让我们在现有进程中搜索命令sleep infinity :
$ ps -ef | grep "sleep infinity"
alice 21443 1 0 00:27 pts/0 00:00:00 sleep infinity
alice 21673 4672 0 00:27 pts/0 00:00:00 grep sleep infinity
在这里,我们使用grep过滤了ps的输出。我们没有在搜索中使用术语“ nohup ”,因为它没有出现在ps命令的输出中。
由于管道中的grep “sleep infinity”命令也列在输出中,我们可以使用grep进一步过滤它:
$ ps -ef | grep "sleep infinity" | grep -v grep
alice 21443 1 0 00:27 pts/0 00:00:00 sleep infinity
最后,我们可以使用awk 命令仅打印进程的 PID :
$ ps -ef | grep "sleep infinity" | grep -v grep | awk '{print $2}'
21443
2.3. 使用pgrep命令
或者,如果我们在使用nohup启动进程后忘记记录进程的 PID ,我们也可以使用pgrep命令:
$ pgrep -a sleep
21443 sleep infinity
在这里,pgrep的*-a*选项将命令连同它的 PID 一起打印出来。
3 、 shopt命令的huponexit选项
让我们再次在交互式登录 shell 中在后台生成一个进程并注销。但是,在这种情况下,我们将在没有nohup的情况下启动该过程:
$ bash -l
$ sleep infinity &
[1] 25101
$ exit
logout
$
让我们检查进程是否仍在运行:
$ ps -ef -o pid | grep 25101
25101
即使我们从交互式登录 shell 中注销,该进程似乎仍在运行。那么,这是否意味着如果我们希望后台进程在注销后继续运行,我们就不必使用nohup呢?
答案是,如果我们想要可移植性,我们应该使用nohup。仅在没有nohup的情况下在后台运行命令可能并不总是有效。
**事实上,这个问题与 shell 选项huponexit相关。**我们可以使用shopt命令检查此选项的值:
$ shopt | grep huponexit
huponexit off
shopt命令用于设置和显示几个 shell 选项。如果huponexit选项off,当交互式登录 shell 退出时,Bash 不会向在该会话中生成的已经运行的进程发送SIGHUP信号。这就是为什么我们通过执行sleep infinity命令生成的进程在使用**exit命令终止登录 shell 后仍然存在的原因。
可以启用和禁用huponexit选项。我们可以使用*-s选项来启用它,使用-u*选项来禁用它:
$ shopt -s huponexit
$ shopt | grep huponexit
huponexit on
$ shopt -u huponexit
huponexit off
现在,让我们启用huponexit选项并检查行为:
$ bash -l
$ shopt –s huponexit
$ shopt | grep huponexit
huponexit on
$ sleep infinity &
[1] 26238
$ exit
logout
$ ps –ef –o pid | grep 26238
$
现在,在我们退出登录 shell 后,该进程不再处于活动状态,因为内核在退出时向该进程发送信号SIGHUP。因此,进程在收到此信号时终止。