使程序在后台运行,后台进程实现原理

要想程序在后台稳定运行,先要关闭或者重定向其标准输出,然后需要先解决两个问题:

  1. ctrl+c, ctrl+z 不能终止程序。
  2. 关闭命令行终端后,默认会向此终端启动的所有程序发生SIGHUP信号,导致程序被终止。

解决第一个问题,我们只需要在程序后面加上&即可。

在解决第二个问题之前,我们先看看终端连接。

终端连接

我们xshell这样的工具连接上服务器,其实就是建立ssh连接,默认是22端口,每一个连接就是一个进程,我在一个终端启动了一个进程main60,然后在另一个终端执行如下命令

$ ps -ef | grep main60
vagrant  13890 13865  0 09:19 pts/0    00:00:00 ./main60
vagrant  13932 13910  0 09:19 pts/1    00:00:00 grep --color=auto main60

第一行输出,13890 为 main60 的进程ID,13865 为其父进程ID,pts/0 为终端编号默认从0开始。

第二行输出,13932 为 grep 程序的进程ID,13910 为其父进程ID,pts/1 为终端编号。

那么它们的父进程是什么呢?

$ ps -ef | grep 13865
vagrant  13865 13851  0 09:12 pts/0    00:00:00 -bash
vagrant  13890 13865  0 09:19 pts/0    00:00:00 ./main60
vagrant  13937 13910  0 09:33 pts/1    00:00:00 grep --color=auto 13865

其实就是ssh连接。

你通过终端启动的进程,它们的父进程或者更上级的进程就是连接进程。

当你关闭终端的时候,ssh服务就能检测到,它在退出连接进程之前会先找到所有的子进程,向它们发生SIGHUP信号,如果你的进程没有捕获此信号,那么就会终止。

我将启动方式由./main60改成./main60 &,虽然看起来程序在后台运行了,但是当我关闭 pts/0 这个终端的时候,程序都退出了。

扫描二维码关注公众号,回复: 14207783 查看本文章

那么解决方式就是捕获 SIGHUP 信号;或者和它断绝父子关系。一般会选择后者。

断绝父子关系也很简单,那就是让 main60 fork 出一个子进程,然后父进程退出,这样子进程就会被 PID=1 的进程接管。

修改了 main60 程序,增加了 fork 子进程,再次运行。

$ ps -ef | grep main60
vagrant  14077     1  0 10:19 pts/0    00:00:00 ./main60
vagrant  14081 13910  0 10:20 pts/1    00:00:00 grep --color=auto main60

可见父进程以及变为1,但是还是有 pts/0 的标记,会有影响吗?

我关闭了 pts/0 之后

$ ps -ef |grep main60
vagrant  14077     1  0 10:19 ?        00:00:00 ./main60
vagrant  14084 13910  0 10:22 pts/1    00:00:00 grep --color=auto main60

这样看着就完美了,程序也没有退出。

其实使用这种方式就同时解决了上面的两个问题了。连&符都不需要加,非常推荐。

nohup命令简介

nohup 命令的作用可以将程序以忽略挂起信号(SIGHUP)的方式运行。常见的用法是和 & 命令一同使用,将命令放置到后台运行,即使终端关掉了,进程会忽略挂起信号,继续运行。

nohup官网地址: http://www.gnu.org/software/coreutils/manual/html_node/nohup-invocation.html

官网的简单介绍:
nohup runs the given command with hangup signals ignored, so that the command can continue running in the background after you log out.

注意:
1,如果使用 nohup 执行程序未显示进行标准输出重定向,则标准输出默认重定向当前工作目录的 nohup.out 文件中。如果当前工作目录的 nohup.out 文件不可写,输出重定向到 $HOME/nohup.out 文件中。如果没有文件能创建或打开用于追加,那么 command 参数指定的命令不可调用。

2,如果标准错误未显示重定向,那么标准错误默认重定向到与标准输出相同的文件。

命令格式

nohup COMMAND [ARGS]
nohup OPTION
3选项说明

--help
 显示帮助信息并退出
--version
 显示版本信息并退出

常用示例

$ nohup ./main60
nohup: 忽略输入并把输出追加到"nohup.out"
$ ps -ef | grep main60
vagrant  14148 14124  0 10:55 pts/0    00:00:00 ./main60

$ ps -ef | grep 14124
vagrant  14124 14110  0 10:52 pts/0    00:00:00 -bash
vagrant  14148 14124  0 10:55 pts/0    00:00:00 ./main60

可见 nohup 的实现原理并不是创建子进程,而是直接将main60替换了自己的进程空间,然后捕获 SIGHUP 信号,然后再启动进程。

2,标准输出与标准错误输出重定向。
nohup ./main60 > test.log 2>&1 &

nohup ./main60 > /dev/null 2>&1 &

3,指定输出文件, 输出被重定向到 output.txt 文件中
nohup bash a.sh &> error.txt

注意:
1,2>&1 标识标准错误输出重定向等同于标准输出重定向,即标准错误输出也重定向到文件 test.log;
2,& 命令是命令放在后台执行,需要放在命令的最后面。

猜你喜欢

转载自blog.csdn.net/raoxiaoya/article/details/124822601
今日推荐