nohupにもかかわらず端末を閉じると、クロムブラウザが殺されるのはなぜですか?


12

この質問は古いものであり、その理由についてはまだ明確ではありません。


2014年の元の質問:

Gnome Terminalタブで、私は走りました

$ nohup chromium-browser &

しかし、ターミナルタブを閉じると、chromium-browser終了します。されていないnohupことを防ぐことになって?ジルは言った:

nohupとdisownは両方ともSIGHUPを抑制すると言えますが、方法は異なります。nohupは、プログラムに最初にシグナルを無視させます(プログラムはこれを変更する場合があります)。nohupはまた、プログラムが制御端末を持たないように調整し、端末が閉じられたときにカーネルによってSIGHUPが送信されないようにします。否認は純粋にシェルの内部にあります。これにより、シェルは終了時にSIGHUPを送信しなくなります。

だから、nohupはクロムブラウザにSIGHUPを無視させないのですか?

これは、Emacs(GUIモード)などの他の実行可能ファイルでも見られます。しかし、xeyesではそうではありません。

これは、質問が投稿された32ビットのUbuntu 12.04で発生しています。


2015年に更新、

現在、Ubuntu 14.04を実行していgoogle-chromeますが、代わりにchromium-browserインストールされています。以前にchrome-browserで発生したのと同じことが、今ではgoogle-chromeでも発生します。nohup google-chrome 2>/dev/null &端子タブが閉じられたときに閉じられないように保存しません。/usr/bin/google-chromeはbashスクリプトへのリンク/opt/google/chrome/google-chromeです。nohupbashスクリプトへの適用が機能しないのはなぜですか?bashスクリプトでどのように機能させることができますか?Pythonスクリプトはどうですか?


1
環境について詳しく説明する必要があります。テストケースは再現しません。
jlliagre 14年

他のどの実行可能ファイルでこれを見ていますか?たとえば、のような簡単なものを試してくださいxeyes
ウォーレンヤング14年

@WarrenYoung:Emacs(GUI)。しかし、xeyesは機能します。
ティム14年

回答:


11

GNOMEターミナルウィンドウを閉じると、実行中のシェルにSIGHUPが送信されます。シェルは通常、SIGHUPを、それが作成されたことがわかっているすべてのプロセスグループ(開始されたものも含む)に送信してからnohup終了します。シェルの場合、bashユーザーがマークしたプロセスグループへのSIGHUPの送信はスキップされdisownます。

でコマンドを実行するとnohup、SIGHUPが無視されますが、プロセスはそれを変更できます。プロセスのSIGHUPの処理がデフォルトである場合、SIGHUPを受け取ると、プロセスは終了します。

Linuxには、実行中のプロセスのシグナル設定を調べるためのツールがいくつかあります。

クロムブラウザーシェルスクリプトはexecコンパイル済みアプリを実行するため、そのプロセスIDは変わりません。そのため、信号の設定を確認するために走っnohup chromium-browser &/proc/$!/statusから、信号の性質を確認しました。

SigBlk: 0000000000000000
SigIgn: 0000000000001000
SigCgt: 0000000180014003

これらは16進数です。これは、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が指摘することを行うことです。bashでdisownコマンドを使用して、bashを終了する必要がある場合にSIGHUPをchromium-browserプロセスグループに送信しないようにします。これを行う関数を作成できます。

mychromium () { /usr/bin/chromium-browser & disown $!; }

ありがとう。今、私はあなたが何を意味していたかをほとんど理解するようになりました。「スクリプトはこのトラップをリセットしないため、実際のクロムバイナリは、デフォルトに設定されたSIGHUPの処理で呼び出されます。」「このトラップをリセット」とは、SIGHUPのトラップをデフォルトのトラップに戻し、プロセスを終了することを意味しますか?どのようにして「このトラップをリセットしますか?」
ティム

ああ、「このトラップをリセットする」とは、「この信号の処理を、シェルスクリプトがハンドラを設定する前の状態に戻す」ことを意味していました。シェルがを実行した場合、シェルtrap "" 1(およびその子)はSIGHUPを無視します。これを明確にします。
マークプロトニック

ありがとう。明確化後、確認します。私は今、デーモン、nohup、disown、および背景を理解しようとしているので、私は理解できなかった私の古い質問と回答を再訪するために戻ってきました。nohup、disown、およびbackgroundに関する混乱はほとんど解決され、デーモンの概念とプロセスをデーモン化する方法に固執しています(以下を参照)。もう一度時間を割いていただければ幸いです。
ティム


クロムアプリのコードを見てみると、アプリケーションのC ++コードが無条件にSIGHUPをデフォルトにリセットしていることがわかりました。trapシェルスクリプトラッパーのコマンドはこれを防ぎませんnohup。実行してもこれを防ぐことはできません。これを反映するように回答を修正します。
マークプロトニック

3

もしchromium-browserようなものされてgoogle-chrome、私が最も可能性の高い問題はそれだと思う、その後はchromium-browser ないchromiumが、代わりに、状態を初期化シェルラッパーですexecchromium

私のgoogle-chromeインストールでは、バイナリは実際に配置され/opt/google/chrome、ラッパー/usr/binは単なるシェルスクリプトであり、xdg-*デフォルトおよび絶対パスなどの多くの環境をセットアップしてから、適切なバイナリに置き換えます。

この時点nohupで、その子として呼び出されたスクリプトに代わって最初に無視された可能性のある信号は重要ではなくなります。

file /usr/bin/chromium-browserそれがシェルスクリプトであるかどうかを確認してみてください。もしそうなら、あなたに合うようにそれを書き換えることを検討してください。

ただgoogle-chrome 2>/dev/null &それをするだけでオープンになっていると言えますが、それがスクリプトに加えた変更の結果である可能性があるかどうかは思い出せません-1年以上前のことです。


ありがとう。chromium-browser以前に起こったことと同じことがgoogle-chrome今も起こります。chromium-browserインストールしていません。nohup google-chrome 2>/dev/null &端子タブが閉じられたときに閉じられないように保存しません。google-chromeはbashスクリプト/opt/google/chrome/google-chromeです。bashスクリプトに適用されたnohupが機能しないのはなぜですか?bashスクリプトでどのように機能させることができますか?Pythonスクリプトはどうですか?
ティム

まあ、それスクリプト上で動作しますが、スクリプトは実際のchromeバイナリに置き換えられる前に数ナノ秒だけ実行されます。
mikeserv

exec実際のchromeバイナリにあるスクリプトで言っているのですか?スクリプトを修正するにはどうすればよいですか?ここに私の/opt/google/chrome/google-chrome
ティム

@ティム-ええ-下を参照してください? exec -a "$0" "$HERE/chrome" ... || exec -a "$0" "$HERE/chrome"...トップで$HEREの値に設定されているreadlink $0 (のためのインストール・パスですgoogle-chromeが、/opt/google/chrome/chromeスクリプトがで自身を置き換えるものです-バイナリです。
mikeserv

@Tim:方法については、execおそらくドロップするだけです。余分なpid (他の1000個を超える)と待機中のシェルプロセスを使用して終了しますが、これがその範囲だと思います。または、おそらくexecw /を置き換える可能性がありますnohup。それはすべて、主に何chromeが許容されるかに依存しますが、そのように動作するはずです。
mikeserv

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.