在 linux 服务器上,启动程序时在尾部添加&,可以把程序丢到后台运行。
当终端退出后,该终端启动的后台程序也可能会停止运行。
原因是终端退出后,该终端启动的后台程序会收到 SIGHUP 信号。如果后台程序内部没有处理 SIGHUP 信号,SIGHUP 信号的默认处理行为是停止程序运行。
为什么后台程序可能会停止运行我用了可能两个字呢?因为我在实验时发现这和终端环境有关系。
当我使用一台终端配置的比较完善的 mac 电脑(安装了 iterm,zsh,tmux 等一堆乱七八糟的东西)去操作远程服务器时,我发现退出终端后,终端启动的后台程序并没有退出。为了进一步验证,我在关闭终端后,重新打开终端,在本地使用 netstat 和 ps 命令查看,发现和远程服务器的连接依然保持存在。
而当我使用一台比较原始的 mac 电脑去操作远程服务器时,我发现退出终端后,终端启动的后台程序也停止了。
为了避免终端退出时后台程序也停止运行,可选择使用如下几种方式:
- 在后台程序内部编写处理 SIGHUP 信号的代码
- 将后台程序编写为 daemon 守护进程
- 使用 nohup 命令启动我们的后台程序
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.
关于 Linux 进程组、会话、守护进程、终端的资料:
- Linux 的进程组、会话、守护进程\\_Linux 教程\\_Linux 公社-Linux 系统门户网站[1]
- Linux 进程、进程组、会话周期、控制终端[2]
我的测试程序,以及一些命令:
<code>#include <signal.h>
#include <stdio.h>
void func(int sig) {
// 通过 man signal,可以看到SIGHUP对应的信号值为1
// 1 SIGHUP terminate process terminal line hangup
fprintf(stderr, "sig:%d\\n", sig);
fflush(stderr);
exit(0);
}
int main() {
int i = 0;
// 程序内部处理SIGHUP
signal(SIGHUP, func);
for (;;) {
fprintf(stderr, "%d\\n", i++);
fflush(stderr);
sleep(1);
}
return 0;
}
/<stdio.h>/<signal.h>/<code>
<code># 远程
$gcc main.c
$./a.out
$./a.out 2> stderr.txt &
$nohup ./a.out 2> stderr.txt &
$jobs
$ps -ef | grep a.out
$tail -f stderr.txt
# 本地
$ps -ef | grep ssh
$netstat -an | grep 22
/<code>
[1]
Linux 的进程组、会话、守护进程_Linux教程_Linux公社-Linux系统门户网站: https://www.linuxidc.com/Linux/2015-04/115764.htm
[2]
Linux 进程、进程组、会话周期、控制终端: http://yangxikun.github.io/linux/2013/11/11/linux-process.html
閱讀更多 非常程序員 的文章