為什麼啟動後臺程序需要使用nohup

在 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


為什麼啟動後臺程序需要使用nohup


分享到:


相關文章: