儘管 nohup 關閉終端,為什麼鉻瀏覽器會被殺死?
這個問題很老了,我仍然不清楚為什麼。
2014年的原始問題:
在 Gnome 終端選項卡中,我跑了
$ nohup chromium-browser &
但是當我關閉終端選項卡時,
chromium-browser
也會退出。不nohup
應該阻止嗎?吉爾斯說:nohup 和 disown 都可以說是抑制 SIGHUP,但方式不同。nohup 使程序最初忽略信號(程序可能會改變這一點)。nohup 還試圖安排程序沒有控制終端,這樣當終端關閉時,核心就不會發送 SIGHUP 信號。disown 純粹是在 shell 內部;它會導致 shell 在終止時不發送 SIGHUP。
那麼 nohup 不會讓 chromium-browser 忽略 SIGHUP 嗎?
我也在其他執行檔上看到了這一點,例如 Emacs(GUI 模式)。但不是在 xeyes 上。
發布問題時,這發生在 32 位 Ubuntu 12.04 上。
2015年更新,
現在我正在執行 Ubuntu 14.04,
google-chrome
而不是chromium-browser
安裝。以前發生在 chromium-browser 上的事情現在也發生在 google-chrome 上。nohup google-chrome 2>/dev/null &
當終端選項卡關閉時,它不會被關閉。/usr/bin/google-chrome
是一個 bash 腳本的連結/opt/google/chrome/google-chrome
。為什麼nohup
應用於 bash 腳本不起作用?我們如何使它在 bash 腳本上工作?Python 腳本呢?
當您關閉 GNOME 終端視窗時,會向它正在執行的 shell 發送一個 SIGHUP。shell 通常會向它知道它創建的每個程序組發送一個 SIGHUP——即使是那些以它開頭的程序組
nohup
——然後退出。如果 shell 是bash
,它將跳過向使用者標記的任何程序組發送 SIGHUPdisown
。執行命令
nohup
使其忽略 SIGHUP,但該過程可以改變這一點。當程序的 SIGHUP 處置是預設配置時,如果它收到 SIGHUP,則該程序將被終止。Linux 提供了一些工具來檢查正在執行的程序的信號設置。
chromium-browser shell 腳本執行
exec
編譯後的應用程序,因此它的程序 ID 保持不變。所以要查看它的信號設置,我跑了nohup chromium-browser &
,然後/proc/$!/status
查看了信號配置。SigBlk: 0000000000000000 SigIgn: 0000000000001000 SigCgt: 0000000180014003
這些是十六進制數字。這表明 SIGHUP 未被擷取且未被忽略。只有 SIGPIPE(SigIgn 中的第 13 位)被忽略。我將此追溯到以下程式碼:
// Setup signal-handling state: resanitize most signals, ignore SIGPIPE. void SetupSignalHandlers() { // Sanitise our signal handling state. Signals that were ignored by our // parent will also be ignored by us. We also inherit our parent's sigmask. sigset_t empty_signal_set; CHECK(0 == sigemptyset(&empty_signal_set)); CHECK(0 == sigprocmask(SIG_SETMASK, &empty_signal_set, NULL)); struct sigaction sigact; memset(&sigact, 0, sizeof(sigact)); sigact.sa_handler = SIG_DFL; static const int signals_to_reset[] = {SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGABRT, SIGFPE, SIGSEGV, SIGALRM, SIGTERM, SIGCHLD, SIGBUS, SIGTRAP}; // SIGPIPE is set below. for (unsigned i = 0; i < arraysize(signals_to_reset); i++) { CHECK(0 == sigaction(signals_to_reset[i], &sigact, NULL)); } // Always ignore SIGPIPE. We check the return value of write(). CHECK(signal(SIGPIPE, SIG_IGN) != SIG_ERR); }
儘管有評論,但父母忽略的信號並沒有被忽略。SIGHUP 會殺死鉻。
解決方法是執行@xx4h 指出的操作:
disown
在 bash 中使用該命令,這樣,如果 bash 必須退出,它不會向chromium-browser
程序組發送 SIGHUP。您可以編寫一個函式來執行此操作:mychromium () { /usr/bin/chromium-browser & disown $!; }