Хтось може детально пояснити, що робить “set -m”?


17

На сторінці чоловіка просто написано:

-m Управління роботою включено.

Але що це насправді означає?

Я зіткнувся з цією командою в питанні SO , у мене така ж проблема, що і у OP, яка є "тканина не може запустити tomcat". І set -mвирішили це. ОП трохи пояснила, але я не зовсім розумію:

Проблема була у фонових завданнях, оскільки вони будуть вбиті, коли команда закінчиться.

Рішення просте: просто додайте "set -m;" префікс перед командою.

Відповіді:


10

Цитуючи документацію bash (від man bash):

JOB CONTROL
       Job  control  refers to  the  ability  to selectively  stop
       (suspend) the execution of  processes and continue (resume)
       their execution at a later point.  A user typically employs
       this facility via an interactive interface supplied jointly
       by the operating system kernel's terminal driver and bash.

Так, просто сказано, наявність set -m(за замовчуванням для інтерактивних оболонок) дозволяє використовувати вбудовані модулі, такі як fgі bg, які були б відключені в set +m(за замовчуванням для неінтерактивних оболонок).

Мені не очевидно, який зв’язок між контролем роботи та вбивством фонових процесів при виході, однак я можу підтвердити, що є один: запуску set -m; (sleep 10 ; touch control-on) &створить файл, якщо вийдете з оболонки відразу після введення цієї команди, але set +m; (sleep 10 ; touch control-off) &не буде.

Я думаю, що відповідь лежить у решті документації щодо set -m:

-m      Monitor  mode. [...]                     Background pro‐
        cesses run in a separate process group and a  line  con‐
        taining  their exit status is printed upon their comple‐
        tion.

Це означає, що фонові завдання, розпочаті в умовах set +m, не є власне "фоновими процесами" ("Фонові процеси - це ті, чий ідентифікатор групи процесів відрізняється від терміналу"): вони мають той самий ідентифікатор групи процесів, що і оболонка, що їх запустила, а не мати власний група процесів, як правильні фонові процеси. Це пояснює поведінку, яка спостерігається, коли оболонка закривається перед деякими з її фонових завдань: якщо я правильно розумію, під час виходу сигнал надсилається процесам у тій же групі процесів, що і оболонка (таким чином знищуючи фонові завдання, розпочаті під set +m), але не для інших груп процесів (таким чином, залишаючи в спокої справжні фонові процеси, розпочаті внизу set -m).

Отже, у вашому випадку startup.shсценарій, імовірно, починає фонове завдання. Коли цей скрипт запускається неінтерактивно, наприклад, над SSH, як у запитанні, до якого ви пов’язані, контроль роботи відключений, "фонове" завдання поділяє групу процесів віддаленої оболонки, і таким чином вбивається, як тільки оболонка виходить. І навпаки, ввімкнувши контроль за роботою в цій оболонці, фонове завдання набуває власну групу процесів, і не вбивається при виході його батьківської оболонки.


Thx для вашої відповіді, але як це tomcat/bin/startup.shпов’язано з fg/ bg?
laike9m

1
Це не пов'язано безпосередньо; Я намагався відповісти "Увімкнено управління роботою / що це насправді означає?" загалом. Можливо, я цього не прояснив, але, здається, ваш сценарій розпочинає фонове завдання, до чого стосується решта моєї відповіді.
даг

2

Я знайшов це у списку випусків github, і я думаю, що це справді відповідає на ваше запитання.

Це насправді не проблема SSH, це більш тонка поведінка навколо неінтерактивних / інтерактивних режимів BASH та розповсюдження сигналу для процесових груп.

Далі базується на /programming/14679178/why-does-ssh-wait-for-my-subshells-without-t-and-kill-them-with-t/14866774#14866774 та http: //www.itp.uzh.ch/~dpotter/howto/daemonize , з деякими припущеннями не повністю підтвердженими, але тести про те, як це працює, наче підтверджують.

pty / tty = хибно

Запущена оболонка bash підключається до stdout / stderr / stdin запущеного процесу і продовжує працювати, поки нічого не приєднано до розеток, і діти не вийдуть. Хороший процес Deamon забезпечить, щоб він не чекав, поки діти вийдуть, розщедрить дочірній процес і потім вийдуть. У цьому режимі SSH жоден SIGHUP не надсилатиме дочірній процес. Я вважаю, що це спрацює правильно для більшості сценаріїв, виконуючи процес, який обробляє деамонізацію і не потребує фонового зображення. Якщо сценарії init використовують "&" для фонового процесу, то, ймовірно, основною проблемою буде те, чи спрацьований фоновий процес коли-небудь намагається прочитати з stdin, оскільки це спровокує SIGHUP, якщо сеанс припинено.

pty / tty = вірно *

Якщо фоновий скрипт init процес запустився, батьківська оболонка BASH поверне код виходу на SSH-з'єднання, яке, в свою чергу, виглядає негайно, оскільки він не чекає, коли дочірній процес закінчиться і не блокується в stdout / stderr / stdin. Це призведе до того, що SIGHUP буде надісланий до батьківської групи процесів оболонки bash, яка, оскільки контроль роботи відключена в неінтерактивному режимі в bash, включатиме дочірні процеси, щойно запущені. Якщо демон-процес явно починає новий сеанс процесу під час розгортання або в роздвоєному процесі, тоді він або його діти не отримають SIGHUP від ​​вихідного процесу BASH. Зауважте, що це відрізняється від призупинених завдань, які відображатимуться SIGTERM. Я підозрюю, що проблеми навколо цього лише працюють іноді пов'язані з умовами легкої гонки. http://www.itp.uzh.ch/~dpotter/howto/daemonize , ви побачите, що в коді новий сеанс створюється роздвоєним процесом, який може не запускатися до виходу з батьків, таким чином, виходить випадковий поведінка успіху / невдачі, згадана вище. Запис уві сні дозволить достатньо часу для того, щоб процес роздрібнився створив новий сеанс, тому він працює в деяких випадках.

pty / tty = вірно, а керування роботою явно включено в bash

SSH не підключатиметься до stdout / stderr / stdin bash-оболонки або будь-яких запущених дочірніх процесів, що означає, що він вийде, як тільки батьківська оболонка bash почне завершувати виконання запитуваних команд. У цьому випадку, з явним увімкненим контролем за роботою, будь-які процеси, запущені оболонкою bash з позначкою '&' для їх фонового зображення, будуть негайно розміщені в окремий сеанс і не отримають сигнал SIGHUP, коли вихідний процес до сеансу BASH закінчується ( SSH-з'єднання в цьому випадку).

Що потрібно виправити

Я думаю, що рішення просто потрібно чітко вказати в документації на виконання операцій / sudo як особливий випадок при роботі з фоновими процесами / послугами. В основному або використовуйте 'pty = false', або там, де це неможливо, явно ввімкніть управління роботою як першу команду, і поведінка буде правильною.

З https://github.com/fabric/fabric/isissue/395

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