尽管 nohup 关闭终端时,为什么铬浏览器会被杀死?

Tim*_*Tim 14 chrome nohup

这个问题很老了,我仍然不清楚为什么。


2014 年的原始问题:

在 Gnome 终端选项卡中,我跑了

$ nohup chromium-browser &
Run Code Online (Sandbox Code Playgroud)

但是当我关闭终端选项卡时,chromium-browser也会退出。不nohup应该阻止吗?吉尔斯说:

nohup 和 disown 都可以说是抑制 SIGHUP,只是方式不同。nohup 使程序最初忽略信号(程序可能会改变这一点)。nohup 还尝试安排程序没有控制终端,以便在终端关闭时内核不会向它发送 SIGHUP。disown 纯粹是 shell 内部的;它会导致 shell 在终止时不发送 SIGHUP。

那么 nohup 不是让铬浏览器忽略 SIGHUP 吗?

我也在其他可执行文件上看到了这一点,例如 Emacs(GUI 模式)。但不是在 xeyes 上。

发布问题时,这发生在 32 位 Ubuntu 12.04 上。


2015年更新,

现在我运行的是 Ubuntu 14.04,google-chrome而不是chromium-browser安装。以前发生在 Chrome 浏览器上的事情现在也发生在 google-chrome 上。nohup google-chrome 2>/dev/null &当终端选项卡关闭时,它不会被关闭。/usr/bin/google-chrome是一个指向 bash 脚本的链接/opt/google/chrome/google-chrome。为什么nohup应用于 bash 脚本不起作用?我们如何让它在 bash 脚本上工作?Python脚本呢?

Mar*_*ick 15

当您关闭 GNOME 终端窗口时,一个 SIGHUP 被发送到它正在运行的 shell。shell 通常会向它知道它创建的每个进程组发送一个 SIGHUP - 即使是开始的进程组nohup- 然后退出。如果 shell 是bash,它将跳过向用户标记的任何进程组发送 SIGHUP disown

运行命令nohup使其忽略 SIGHUP,但进程可以改变它。当一个进程的 SIGHUP 的处置是默认的,那么如果它收到一个 SIGHUP,该进程将被终止。

Linux 提供了一些工具来检查正在运行的进程的信号设置。

铬浏览器 shell 脚本执行exec编译后的应用程序,因此其进程 ID 保持不变。所以为了查看它的信号设置,我跑了nohup chromium-browser &然后/proc/$!/status查看了信号配置。

SigBlk: 0000000000000000
SigIgn: 0000000000001000
SigCgt: 0000000180014003
Run Code Online (Sandbox Code Playgroud)

这些是十六进制数字。这表明 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);
}
Run Code Online (Sandbox Code Playgroud)

尽管有评论,父母忽略的信号并没有被忽略。SIGHUP 将杀死铬。

解决方法是执行@xx4h 指出的操作:disown在 bash 中使用该命令,这样,如果 bash 必须退出,它就不会向chromium-browser进程组发送 SIGHUP 。您可以编写一个函数来执行此操作:

mychromium () { /usr/bin/chromium-browser & disown $!; }
Run Code Online (Sandbox Code Playgroud)