Linux 实现后台进程
每次终端关闭时,它的所有子进程也会因此而终止,显然,这是无法在实际运用中忽略的问题,此时,就需要把持续活动的进程移至后台运行。
SIGHUP信号拦截
在Linux中,大多数进程的状态与它收到的信号有关。
其中,SIGHUP信号作用是连接断开后终止某个进程,即当一个终端被断开时,它的所有子进程都会收到SIGHUP信号,从而终止这些进程,所以可以想办法拦截这个信号,使目标进程无法收到SIGHUP信号而在后台运行。
准备一个死循环的C++文件,在Ubuntu中 通过g++编译成可执行文件,ssh连接到Ubuntu服务器,然后正常执行文件后,直接断开ssh连接,打开新的终端并搜索有无这文件的进程。
C++代码编写:
#include<iostream>
#include<unistd.h>
#include<signal.h>
using namespace std;
int main() {
cout << "Linux C++" << endl;
//拦截SIGHUP信号
signal(SIGHUP, SIG_IGN);
while (1){
sleep(1);
cout << "terminal and bash Process" << endl;
}
cout << "end!" << endl;
return 0;
}
编译:
# 执行完下述直接关闭终端
g++ -o t141 /mnt/hgfs/c/t141.cpp
./t141
结果:
# 新终端查看进程状态
ps -eo pid,ppid,sid,tty,pgrp,comm,stat | grep -E 'bash|PID|t141'
可以发现,t141仍在运行(STAT为S),由于它的终端被关闭了,TT变成了?,而且PPID变成了1,也就是说,这个进程现在被进程init收留了,是一个孤儿进程。
验证完毕,确认可行,可以执行kill -9 7650
杀死这个进程
使用setsid函数
该命令用于启动一个进程,而且能够使启动的进程在一个新的session(会话)中,这样终端关闭时进程就不会退出。
大佬fork的理解:fork
修改之前的C++文件:
#include<iostream>
#include<stdio.h>
#include<unistd.h>
#include<signal.h>
using namespace std;
int main() {
pid_t pid;
cout << "Linux C++" << endl;
pid = fork(); //系统函数,用来创建新进程,即创建主进程的子进程
if ( pid < 0 ){
cout << "fork进程出错" << endl;
}else if ( pid == 0 ){
cout << "子进程开始执行" << endl;
setsid(); //创建新session
while (1){
sleep(1);
cout << "子进程" << endl;
}
return 0;
}else{
//父进程执行
while (1){
sleep(1);
cout << "父进程" << endl;
}
return 0;
}
cout << "end!" << endl;
return 0;
}
编译:
g++ -o t141 /mnt/hgfs/c/t141.cpp
执行 ./t141
:
可以发现,父进程和子进程是同时运行的,相当于两个进程。
终止主进程后,可以发现子进程还在跑:
关闭终端后,这个子进程已经被init收留了,且STAT显示Ss,说明还在运行中:
kill掉这个子进程,sudo kill -9 34039
使用setsid命令
有没有什么其它方法能做到终端退出,启动的进程不关闭的呢?
可以使用setsid命令。setsid不但是个函数,其实它也是一个命令。该命令用于启动一个进程,而且能够使启动的进程在一个新的session中,这样终端关闭时进程就不会退出。
修改C++文件为:
#include<iostream>
#include<stdio.h>
#include<unistd.h>
#include<signal.h>
using namespace std;
int main() {
pid_t pid;
cout << "Linux C++" << endl;
while (1){
sleep(1);
cout << "子进程" << endl;
}
cout << "end!" << endl;
return 0;
}
执行:
setsid ./t141
可以发现,跟使用了setsid函数一个结局,终止主进程之后,作为子进程的它还在跑:
依旧被init进程收留,而且运行着:
一样kill了
使用nohup命令
直接执行:
qiye@ubuntu:~/Desktop$ nohup ./t141
nohup: ignoring input and appending output to 'nohup.out'
关闭终端后,在新终端查看:
再次被init收留,kill了
后台执行
在执行程序末尾增加一个“&”, 即输入:
./t141 &
它不会被进程init收留,这个进程的终端没了,它也会终止。