一、前言
相信大家在使用类unix系统(linux、macos)的时候,肯定有一些后台运行程序的需求,如启动tomcat,启动各种各样的服务时,都有一个需求,那就是想即使我们当前这个终端(terminal)关闭后,仍然可以保持程序的继续运行。
二、正文
&,子进程式的后台运行,不靠谱
其实我们都知道有个命令 &,这个的意思是后台运行,虽然我们使用这个&之后,程序是进入后台运行了,可以不受我们crtl+c的这种强制退出命令的干扰一直执行,但是如果我们退出当前的终端,也会导致整个程序的退出。
比如我们当前测试使用ping命令。
ping www.baidu.com &
在后面加上&后,ping进入后台执行,但是他的输出依旧为当前终端,因此我们会看到ping命令的输出,此时ctrl+c无法终端进程,因为ping已经进入了当前系统的后台。此时我们可以通过 ps -ef |grep ping 。查看ping的进程号30524,然后kill掉它。
但是其实由于类unix系统的特性,由当前进程启动的进程均默认为当前线程的子进程,而且在父进程退出(exit)之后,其下的所有相关子进程均会接收到信号退出,因此我们刚才使用 ping www.baidu.com& 命令即使进入了后台运行,但在我们当前操作的终端退出后,ping进程也会被kill掉,可以尝试一下。
因此光是&保持后台运行还不行,因此需要让我们衍生出来的子进程忽略掉父进程的退出信号 HUP(hangup),这里就牵扯到了另外一个东西nohup。
nohup+&,后台运行忽略hup信号
nohup的意思就是我们当前启用的这个进程,会忽略由父进程被销毁带来的hup信号而避免退出。让我们先来看一下 nohup 的帮助信息:
[root@ls ~]# nohup --help
Usage: nohup COMMAND [ARG]...or: nohup OPTION
Run COMMAND, ignoring hangup signals.--help display this help and exit--version output version information and exitIf standard input is a terminal, redirect it from /dev/null.
If standard output is a terminal, append output to 'nohup.out' if possible,
'$HOME/nohup.out' otherwise.
If standard error is a terminal, redirect it to standard output.
To save output to FILE, use 'nohup COMMAND > FILE'
可见,nohup 的使用是十分方便的,只需在要处理的命令前加上 nohup 即可,标准输出和标准错误缺省会被重定向到 nohup.out 文件中。一般我们可在结尾加上"&"来将命令同时放入后台运行,也可用">filename 2>&1"
来更改缺省的重定向文件名。即 nohup ping www.baidu.com &,这个命令会缺省的在当前目录下将ping进程的输出重定向到nohup.out 中。
当然,也可以指定输出文件
nohup ping www.baidu.com >ping.log &
setid,将进程变为非终端子进程
上面的nohup解决方案是将当前终端启动的子进程完全忽略父进程的hup信号,完成后台运行且不受干扰。但是如果我们换个思路呢,将当前子进程变为非终端启动的子进程,那么终端退出之后,这个子进程也就不会收到hup信号了。
setsid 就能帮助我们做到这一点,如下
setsid ping www.baidu.com
查看进程信息之后如下所示:,当前启动的ping,父进程号为1,1号进程为linux的系统内核进程,因此当前进程便不会受到其他进程的影响。
三、结语
在这篇博客中,我们介绍了两种在类unix系统中将进程后台运行的办法,及nouhp+&、setsid,均能有效执行。
其实不仅仅是后台运行进程的需求,我们在创建一个守护进程时也需要对守护进程做出这个后台运行操作。
笔者在使用jenkins部署脚本时就忽略了父子进程间的关系问题,每次启动完脚本后就忽略了脚本父进程已经结束,因此子进程也无法正常运行,使用nohup解决。