Чому браузер Chrome вбивається, коли я закриваю термінал, незважаючи на nohup?


12

Це питання давнє, і мені досі не зрозуміло, чому.


Оригінальне запитання 2014 року:

На вкладці терміналу Gnome я побіг

$ nohup chromium-browser &

Але коли я закриваю вкладку терміналу, chromium-browserтакож виходить. Хіба це не nohupповинно запобігти? Жил сказав:

nohup та unanwn, як можна сказати, пригнічують SIGHUP, але різними способами. nohup змушує програму ігнорувати сигнал спочатку (програма може змінити це). nohup також намагається домовитись, щоб програма не мала керуючого терміналу, так що вона не буде відправлена ​​ядром SIGHUP, коли термінал закритий. відпадання суто внутрішнє для оболонки; це змушує оболонку не надсилати SIGHUP, коли вона закінчується.

Тож чи не змушує Chrome-браузер ігнорувати 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?


1
Ви повинні розповісти більше про своє оточення. Я не відтворюю ваш тестовий випадок.
jlliagre

З якими іншими виконуваними файлами ви це бачите? Спробуйте щось просте, наприклад, наприклад xeyes.
Варрен Янг

@WarrenYoung: Emacs (GUI). Але xeyes працює.
Тім

Відповіді:


12

Коли ви закриєте вікно терміналу GNOME, SIGHUP надсилається до оболонки, на якій він працював. Оболонка, як правило, надсилає SIGHUP до кожної групи процесів, для якої вона знає, що вона створена - навіть із тих, що почалися з nohup-, а потім вийде. Якщо оболонка є bash, вона пропустить надсилання SIGHUP до будь-якої групи процесів, якою користувач позначений disown.

Запуск команди з допомогою nohupпримушує її ігнорувати SIGHUP, але процес може це змінити. Якщо диспозиція SIGHUP для процесу є типовою, то, якщо він отримує SIGHUP, процес буде припинено.

Linux надає деякі інструменти для вивчення параметрів сигналу запущеного процесу.

Сценарій оболонки Chrome-браузера виконує execкомпільований додаток, тому його ідентифікатор процесу залишається таким же. Отож, щоб побачити його настройки сигналу, я побіг, nohup chromium-browser &а потім подивився, /proc/$!/statusщоб побачити розміщення сигналу.

SigBlk: 0000000000000000
SigIgn: 0000000000001000
SigCgt: 0000000180014003

Це шістнадцяткові номери. Це показує, що SIGHUP не спійманий і не ігнорується. Ігнорується лише SIGPIPE (13-й біт у SigIgn). Я простежив це до наступного коду :

// 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 повинен вийти, він не надсилав SIGHUP до chromium-browserгрупи процесів. Ви можете написати функцію для цього:

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

Дякую. Тепер я зрозумів здебільшого, що ви мали на увазі. "Оскільки сценарій ніколи не скидає цю пастку, фактичний бінарний хром викликається, коли диспозиція SIGHUP встановлена ​​за замовчуванням." "Скинути цю пастку", ви маєте на увазі зміни пастки для SIGHUP назад на стандартну, що завершує процес? Як "скинути цю пастку"?
Тім

О, під "скиданням цієї пастки" я мав на увазі "повернути дислокацію цього сигналу так, як це було до того, як скрипт оболонки встановив обробник для нього". Якщо оболонка зробила це trap "" 1, це змусило б оболонку (та її дітей) ігнорувати SIGHUP. Я проясню це.
Марк Плотнік

Дякую. Перевірте це після вашого уточнення. Зараз я намагаюся зрозуміти демона, нохупа, відхрещення та передісторію, тому я повернувся переглянути свої старі питання та відповіді, які не зрозумів. Плутанини щодо nohup, disown та background в основному вирішуються, і я застряг у концепції демона та способах демонізувати процес (див. Нижче). Я знову вдячний, якщо у вас є час знову допомогти.
Тім


Я переглянув код програми Chrome, і виявляється, що код C ++ у додатку безумовно скидає SIGHUP до типового. Ці trapкоманди в сценарії оболонки обгортка не перешкоджає цьому, і біжить nohupне можуть запобігти цьому. Я перегляну свою відповідь, щоб це відобразити.
Марк Плотнік

3

Якщо chromium-browserщось подібне, google-chromeто я думаю, що найбільш ймовірною проблемою є те, що chromium-browser це не,chromium а натомість оболонка оболонки, яка ініціалізує стан, то execs chromium.

У моїй google-chromeустановці бінарний файл фактично розташований у, /opt/google/chromeа обгортка /usr/bin- просто сценарій оболонки, який створює безліч середовищ, що стосуються xdg-*значень за замовчуванням та абсолютних шляхів тощо, перш ніж замінити себе на власне бінарне.

У цей момент будь-які сигнали, які, nohupможливо, спочатку ігнорувались від імені скрипту, який він називав, оскільки його дитина перестане мати значення, і, якщо сценарій обгортки не буде ретельним, щоб упорядкувати його інакше (чого це не так), ctty успадковується.

Спробуйте file /usr/bin/chromium-browserперевірити, чи це сценарій оболонки, я думаю, що це так. Якщо так, подумайте про те, щоб переписати його, щоб краще підходити вам.

Я можу сказати, що саме це google-chrome 2>/dev/null &робить для мене відкритим, але я не можу згадати, чи це ймовірний результат змін, які я внесла до сценарію - це було більше року тому.


Дякую. Те саме, що було chromium-browserраніше, трапляється і google-chromeзараз. Я не chromium-browserвстановив. nohup google-chrome 2>/dev/null &не рятує його від закриття, коли вкладка терміналу закрита. google-chromeє баш сценарієм /opt/google/chrome/google-chrome. Чому nohup, застосований до скрипту bash, не працює? Як ми можемо змусити його працювати над скриптами bash? Що з сценаріями Python?
Тім

Ну, це робить роботу над сценарієм, але скрипт працює тільки в протягом декількох наносекунд , перш ніж замінити фактичного chromeдвійковим.
mikeserv

Ви говорите, що в сценарії є execфактично chromeбінарне? Як потім змінити сценарій? Ось мій/opt/google/chrome/google-chrome
Тім

@Tim - так - бачите дно? exec -a "$0" "$HERE/chrome" ... || exec -a "$0" "$HERE/chrome"... Вгорі $HEREвстановлено значення readlink $0 (для якого встановлено ваш шлях встановлення google-chrome), але /opt/google/chrome/chromeє двійковим - на що сценарій замінює себе.
mikeserv

@Tim: Що стосується того, як йде - ви можете просто відмовитись, execймовірно. Ви заведете додатковий під (понад 1000 інших) і процес оболонки очікування, але я думаю, що в цьому і полягає ступінь. Або ви можете замінити execw / nohupможливо. Все залежить головним чином від того, що chromeбуде терпіти - але це має працювати так.
mikeserv

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.