问题:
ssh登录服务器,并开启一个后台进程,然后自己去做其他事情了。等过了一会儿,当再来查看时,发现开启的后台进程莫名其妙的挂掉了。
原因:
无论进程是在后台还是在前台,它都与启动它的终端实例紧密绑定。当终端关闭时,它通常向绑定到终端的所有进程(前台、后台进程)发送SIGHUP信号。 这表示进程终止,因为它们的控制终端将很快不可用。
本例中,ssh登录终端,超过一定时间没有操作后,连接断开,终端关闭,与终端相关的所有进程(包括前台和后台进程)都将终止。
验证:
开启一个后台进程
代码如下:
terminal_process.c
#include <unistd.h>
int main()
{
while(1)
{
sleep(10);
}
return 0;
}
编译、后台运行
$ gcc terminal_process.c -o terminal_process
$ ./terminal_process &
查看前后台进程、终端
$ ps -o pid,ppid,pgrp,session,tpgid,comm,tty
PID PPID PGRP SESS TPGID COMMAND TT
15907 15906 15907 15907 16145 bash pts/1
15946 15907 15946 15907 16145 terminal_proces pts/1
16145 15907 16145 15907 16145 ps pts/1
其中,
- pgrp 进程组ID
- tpgid 控制进程组ID
- tty 控制终端号
- 15097是会话首进程,会话ID为其ID,此时会话首进程属于后台进程组。
- terminal_proces进程是15946,其父进程为bash(会话首进程15907)。
- 16145拥有控制终端,所以是前台进程组。
- 15907、15946都是后台进程组。
过一段时间,没有操作终端,ssh登录终端自动断开。
再查看进程,可以看到刚才开启的进程已经终止。
另外,本地终端强制关闭,也有类似的问题。
解决办法:
终端开启一个后台进程后,例如termal_process,然后终端下输入命令exit正常退出.
$ ./terminal_process &
$ ps -ef | grep terminal_process
lanyang 16946 16907 0 10:18 pts/1 00:00:00 ./terminal_process
$ exit
登录另一个终端查看
$ ps -ef | grep terminal_process
lanyang 16946 1 0 10:18 ? 00:00:00 ./terminal_process
terminal_process的父进程已经变成了init进程,不会出现刚才的问题。
除了这个方法,还有nohup,disown等其他,有兴趣可以自行搜索查看。