这个问题很老了,我仍然不清楚为什么。
2014年的原始问题:
在 Gnome 终端选项卡中,我运行
$ nohup chromium-browser &
但是当我关闭终端选项卡时,chromium-browser
也会退出。不是nohup
应该阻止吗?吉尔斯说:
nohup 和 disown 都可以说是抑制 SIGHUP,但是方式不同。 nohup 使程序最初忽略该信号(程序可能会改变这一点)。 nohup 还尝试安排程序没有控制终端,这样当终端关闭时,内核就不会发送 SIGHUP 信号。 disown 纯粹是 shell 内部的;它导致 shell 在终止时不发送 SIGHUP。
那么 nohup 不会让 chromium 浏览器忽略 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 脚本呢?
答案1
当您关闭 GNOME 终端窗口时,会向其正在运行的 shell 发送 SIGHUP 信号。 shell 通常会向它知道它创建的每个进程组发送 SIGHUP(即使是启动的进程组nohup
),然后退出。如果是,shellbash
将跳过向用户标记的任何进程组发送 SIGHUP disown
。
运行命令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 $!; }
答案2
铬看起来很特别。
nohup chromium-browser & disown
在这种情况下应该有效。也可以看看:
https://stackoverflow.com/questions/11421810/nohup-doesnt-work-with-chromium
答案3
如果chromium-browser
是这样的google-chrome
话我认为最有可能的问题是chromium-browser
不是chromium
但它是一个 shell 包装器,它先初始化状态,然后初始化exec
s chromium
。
在我的google-chrome
安装中,二进制文件实际上位于其中/opt/google/chrome
,其中的包装器/usr/bin
只是一个 shell 脚本,它设置了许多有关xdg-*
默认值和绝对路径等的环境,然后再将其替换为正确的二进制文件。
此时,任何nohup
最初可能被其作为子脚本调用的脚本忽略的信号都将不再重要,除非包装脚本小心地以其他方式安排它(事实并非如此)ctty 是继承的。
尝试file /usr/bin/chromium-browser
检查它是否是我认为的 shell 脚本。如果是这样,请考虑重写它以更适合您。
我可以说,只是这样做google-chrome 2>/dev/null &
就让我保持开放,但我不记得这是否是我对脚本所做修改的可能结果 - 那是一年多前的事了。