Чому наче «su -c <command> &» дозволяє команді запускатися у фоновому режимі, не зависаючи


11

Я допомагав колезі, який мав проблеми з фоновим процесом, що періодично вмирав.

Я дізнався, що вони починають фоновий процес, увійшовши на сервер і виконавши:

su - <user> -c '<command>' &

- Ага, - вигукнув я. "Якщо ви запускаєте команду з" & ", вона зависне, коли ви виходите з керуючого терміналу. Для цього потрібно використовувати щось на кшталт nohup. Дійсно, цей процес повинен підтримувати запуск як демон, tut tut."

Ми перевірили вищевказану команду, щоб продемонструвати свою точку зору, і ... здавалося, це працює: процес, розпочатий командою , не закінчувався, коли ми виходили з терміналу, який виконував вищевказану команду.

Команда - це користувацький скрипт Python, вихід якого надходить у файл. Наскільки я можу сказати, у сценарію немає такого розумного "демонізування", як здатність. Він не робить жодної з речей, необхідних для запуску демона, переліченого у Вікіпедії: Демон (обчислення): сторінка створення .

Виконання команди на зразок так поводиться як очікувалося:

<command> &
exit

У наведеному вище випадку фоновий процес, розпочатий командою, закінчується, коли ми виходимо з терміналу.

Моє запитання таке:

  1. Що відбувається, коли ми додаємо "su--c &", що запобігає виходу із процесу, коли наш термінал виходить. Я хотів би детально розібратися щодо керуючого терміналу, стандартного вводу та виводу тощо.

  2. Це розумний спосіб досягти мети виконання цієї команди як фонового процесу. Якщо ні, то чому, ні?

Я хочу розповсюджувати кращі практики у своїй компанії, але мені потрібно вміти демонструвати та створювати резервні копії будь-яких рекомендацій, які я даю.

Я також хочу зрозуміти, що саме відбувається.

Відповіді:


12

Існує кілька способів, через які процес може бути вбитий через термін, що помирає.

  1. Перший спосіб полягає в тому, що драйвер терміналу в ядрі надсилає сигнал SIGHUP до керуючого процесу, для якого термінал є керуючим терміналом . У більшості випадків процес управління - це оболонка, яка спочатку запускається в терміналі, а її керуючий термінал - той, до якого підключені його stdin, stdout та stderr. Процес відключається від керуючого терміналу, якщо він дзвонить setsid.

  2. Другий спосіб полягає в тому, що оболонка, отримуючи SIGHUP, повторно передає цей сигнал своїм підпроцесам - точніше, до своїх фонових завдань. Деякі оболонки (ksh, bash, zsh) мають disownвбудований модуль, щоб сказати оболонці не надсилати SIGHUP на певну роботу.

  3. Якщо термінал відходить і програма намагається прочитати з нього, він повідомляється про стан кінця файлу (або, можливо, EIO для фонового завдання). Якщо термінал відходить і програма намагається записати на нього, запис повертається з помилкою EIO. Це може призвести до виходу програми.

Отже, suзміни тут полягають у тому, що (2) зазвичай призводить до того, що початкова оболонка вбиває фонове завдання, але оскільки цей фоновий процес працює як інший користувач, сигнал не може бути доставлений, і фоновий процес продовжується.


Я бачив root користувача chroot --userspec root:root / sh -c "exec some_forever_process" &. Робота працює як той самий користувач, без явного nohupдо або disownпізніше. Отже, у цьому випадку, як це сигнал не може бути переданий під час виходу?
Тоддіус Жо

@ToddiusZho Presumable повинен some_forever_processбув працювати назавжди (демон) і таким чином захищає себе від прийому SIGHUP від ​​термінального виходу (запуск у власній групі процесів).
Жил 'ТАК - перестань бути злим'

bash / tail не захищає від SIGHUP, але це все ще працює: `` `локальний $ ssh root @ REMOTE_HOST віддалений # chroot --userspec root: root / sh -c" exec bash -c "tail -f / dev / null '"& [1] 6376 дистанційний # ps -p $! --no-заголовок -o pid, uid, команда -ww 6376 0 хвіст -f / dev / null remote # вихід локального $ ssh root @ REMOTE_HOST remote # ps -p 6376 --no-header -o pid, uid, команда -ww 6376 0 хвіст -f / dev / null `` `
Toddius Zho
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.