В течение многих лет я использовал nohup или screen для поддержания работы процессов после того, как я отключился от терминала через SSH. Поэтому меня очень шокировало, когда один из моих друзей, зеленая рука в Linux или CS, сказал мне, что ctrl + D (или exit) может сделать то же самое, и, вероятно, более элегантно.

Итак, вот как это сделать: сначала запустите ваш процесс в фоновом режиме, как обычно (добавив & или используя bg , что угодно), затем, когда вы хотите отключиться от терминала, используйте ctrl + D или exit для выхода.

Я знаю, что Ctrl + D или exit - очень распространенные способы выхода из системы. Но после повторного входа в систему вы обнаружите, что процесс, который вы только что инициировали, запущен .... В это может показаться трудно поверить, и я сказал, что был шокирован. Я попробовал метод в нескольких различных ситуациях, включая простые скрипты Python с мертвым циклом, он действительно работал.

Я пытался найти некоторую информацию об этом, но, кажется, все говорят о nohup или screen . Является ли метод, о котором я говорю, общеизвестным? Это просто особенность некоторых систем или сред? Если это вообще доступно, то в чем смысл nohup?

2 ответа2

1

Во-первых, вы можете использовать nohup или screen случае, если перед запуском команды вы знаете, что она потребуется для продолжения перед выходом из системы.

Когда вы нажимаете Ctrl + D , входной буфер отправляется в запущенный процесс. Что будет дальше, зависит от того, в каком приложении вы сейчас находитесь.

В большинстве (все?) эмуляторы терминалов и терминалы это просто вышло бы из системы, завершив процесс. Это означает , что если у вас есть процесс , работающий в фоновом режиме, который не был nohup « под ред или в сеансе screen он умрет бы вместе с выходом.

Однако возможно, что вы находитесь в каком-то приложении, что использование Ctrl + D на самом деле не завершает его, а переводит в некоторое фоновое состояние.

Другая мысль состоит в том, что ваш друг думал о ctrl + z - это приостановит запущенный процесс, который вы можете затем «отключить» от сеанса работающего терминала, используя bg и disown . Сделав это, вы можете закрыть свой терминал. Это в основном то же самое, что и использование nohup перед запуском процесса.

Вы не можете «присоединиться» к такому процессу, как только он отрекся.

1

Ctrl+D соответствует EOT в таблице ASCII. Во многих (большинство?) в случаях это сопоставляется с EOF, что означает, что данных больше нет.

Для терминалов (например, bash запущенный с tty в качестве stdin), вызов read() при отсутствии пользовательского ввода обычно блокирует или возвращает ноль (нет данных для чтения). Когда tty « уходит », bash , наконец, прочитает EOF, заявив, что входных данных категорически больше нет - никогда. Вы можете представить EOF вручную, набрав Ctrl+D.

Стоит отметить, что такие вещи, как bash которые используют readline , не будут представлять EOF, если текущая строка не пуста. Попробуйте набрать что-нибудь, а затем нажмите Ctrl+D - ничего не произойдет.

Когда bash выполняется со скриптом в качестве входных данных (например, работает с файлом как stdin), то после прочтения последнего байта read() вернет EOF. На этом этапе сценарий завершен, и bash завершает работу. Это то же самое поведение, что и терминал.

Если вы поместите процесс в фоновом режиме (завершите команду с помощью & или используйте Ctrl+Z и bg), то вы вернетесь в оболочку. На этом этапе уничтожение оболочки будет иметь разные последствия для процесса, в зависимости от того, что он делает.

  • Процесс с файлом stdin , скорее всего, продолжит выполняться, теперь он унаследован от init (PID 1).
  • Процесс с каналом из bash качестве stdin также продолжит выполняться ... Пока он не попытается вызвать read() . в этот момент read() завершится ошибкой, и приложение либо поглотит ошибку и продолжит работу, либо (более вероятно) завершит работу с ошибкой.

SIGHUP (он же Hang-Up) - это сигнал, который выдается процессу, чтобы сообщить ему, что другой конец «завис». Я ценю, что это может быть загадочной концепцией ... но при таком использовании он сообщает процессу, что SSH-клиент отключился, или сообщает потомку bash что bash завершил работу и т. Д ...

Если процесс явно не обрабатывает SIGHUP , то действием по умолчанию является его завершение. Таким образом, запрос bash не посылать SIGHUP одному из его дочерних элементов позволит эффективно запустить его после того, как оболочка исчезнет.


Если вы хотите оставить команду, работающую в фоновом режиме, не закладывая сначала основы (посмотрите на tmux как на лучшую версию screen), то вам нужно конкретно указать:« Я больше не хочу, чтобы этот процесс был присоединен к этой оболочке ».

Чтобы достичь этого, вы можете использовать disown (см. Здесь, но вам нужно будет искать / прокручивать), что поможет вам разобраться и оставит процесс запущенным:

отречься [-ar] [-h] [спецификация работы ...]

Без параметров каждая спецификация заданий удаляется из таблицы активных заданий. Если jobspec отсутствует и не указан ни -a, ни -r, используется оболочка для текущего задания. Если задана опция -h, каждая спецификация заданий не удаляется из таблицы, а помечается так, что SIGHUP не отправляется заданию, если оболочка получает SIGHUP. Если спецификация заданий отсутствует и не указана ни опция -a, ни опция -r, используется текущее задание. Если спецификация заданий не указана, опция -a означает удаление или пометку всех заданий; опция -r без аргумента jobspec ограничивает выполнение операций заданиями. Возвращаемое значение равно 0, если в задании не указано допустимое задание.

Все будет по- прежнему , вероятно , пойдет не так , если процесс пытается read() из stdin так что если вы явно хотите отключить запущенный процесс, а затем либо убедитесь , что stdin указывает на /dev/null или аналогичный, или использовать tmux загодя ,


ПРИМЕЧАНИЕ: запись в stdout или stderr , вероятно, будет столь же смертельной, как и попытка чтения из stdin в этих случаях ... SIGPIPE ахой.


Это возможно с помощью инструментов для перенаправления stdin , stdout , stderr запущенного процесса, что делает его более безопасным для выхода с помощью отладочных системных вызовов (у вас могут возникнуть трудности, смотрите это). Я изо всех сил пытаюсь вспомнить название приложения на C, которое я использовал в прошлом, но немного dupx который также может помочь или, по крайней мере, будет интересным для изучения.

Оба работают в основном следующим образом в рамках целевого процесса:

fd = open("/dev/null", O_RDONLY);
dup2(fd, stdin);
close(fd);

fd = open("/dev/null", O_WRONLY);
dup2(fd, stdout);
dup2(fd, stderr);
close(fd);

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .