Поддержание процесса Linux после выхода из системы


142

Я подключаюсь к машине Linux через SSH и пытаюсь запустить тяжелый скрипт bash, который выполняет операции с файловой системой. Ожидается, что он будет работать часами, но я не могу оставить сеанс SSH открытым из-за проблем с интернет-подключением, которые у меня есть.

Я сомневаюсь, что запуск сценария с оператором фона, ampersand ( &), сработает, потому что я попробовал это и позже обнаружил, что процесс не завершен. Как я могу выйти и сохранить процесс запущенным?

Ответы:


135

Лучший способ - запустить процесс в терминальном мультиплексоре. В качестве альтернативы вы можете заставить процесс не получать сигнал HUP.


Терминальный мультиплексор обеспечивает «виртуальные» терминалы , которые работают независимо от «реального» терминала ( на самом деле все терминалы сегодня «виртуальные» , но это уже другая тема для другого дня). Виртуальный терминал будет продолжать работать, даже если ваш реальный терминал закрыт с вашим сеансом SSH.

Все процессы, запущенные из виртуального терминала, будут продолжать работать с этим виртуальным терминалом. При повторном подключении к серверу вы можете подключиться к виртуальному терминалу, и все будет так, как будто ничего не произошло, кроме прошедшего времени.

Двумя популярными терминальными мультиплексорами являются screen и tmux .

Экран имеет крутой кривой обучения. Вот хороший учебник с диаграммами, объясняющими эту концепцию: http://www.ibm.com/developerworks/aix/library/au-gnu_screen/


Сигнал HUP (или SIGHUP) отправляется терминалом всем его дочерним процессам, когда терминал закрыт. Общее действие после получения SIGHUP - прекратить. Таким образом, когда ваш ssh-сеанс отключается, все ваши процессы завершаются. Чтобы избежать этого, вы можете сделать так, чтобы ваши процессы не получали SIGHUP.

Два простых способа сделать это nohupи disown.

Для получения дополнительной информации о том, как nohupи как disownработает, прочитайте этот вопрос и ответ: https://unix.stackexchange.com/questions/3886/difference-between-nohup-disown-and

Примечание: хотя процессы будут продолжать работать, вы больше не можете взаимодействовать с ними, потому что они больше не подключены ни к одному терминалу. Этот метод в основном полезен для длительных пакетных процессов, которые после запуска больше не нуждаются в вводе пользователем.


3
Мне нравится этот ответ, поскольку он предоставляет решение как для интерактивных, так и для неинтерактивных ситуаций. В интерактивном случае screenпредоставляет гораздо больше возможностей, но если вы используете, authorized_keysчтобы позволить людям запускать сценарий удаленно с помощью ssh, этот nohupпараметр является хорошим простым способом для сценария запускать процессы, которые длятся дольше, чем sshсеанс, используемый для их запуска. ,
Марк Бут

1
@rahmanisback - помните, что вы можете изменить свой принятый ответ в любое время. Тот факт, что до сих пор за ответ EricA голосуют наиболее высоко, не означает, что это лучший ответ для вас, и, действительно, принятие его в качестве принятого ответа может побудить большее количество людей голосовать за него как за хороший ответ.
Марк Бут

3
* кашель * tmuxisbetter * кашель *
авария

3
tmux > экран. Попробуйте, вы никогда не вернетесь.
h0tw1r3

1
@TheLQ - byobu - это экран GNU. Вы по-прежнему используете экран, только с сильно настроенным .screenrc.
EEAA

92

Есть несколько способов сделать это, но наиболее полезным я считаю использование экрана GNU .

После того, как вы в ssh, бегите screen. Это запустит другую оболочку, работающую на экране. Запустите вашу команду, затем выполните Ctrl- a d.

Это «отключит» вас от сеанса экрана. На этом этапе вы можете выйти из системы или сделать все, что захотите.

Если вы хотите повторно подключиться к сеансу экрана, просто запустите screen -RDиз командной строки (как и тот же пользователь, который создал сеанс).


6
Экран имеет целую кучу команд, все начинающиеся с Ctrl-a. Если вы изучите только один дополнительный, начните с «Ctrl-a?». Тогда вам не захочется изучать «Ctrl-a c» и «Ctrl-a n»
olafure

@olafure +1, спасибо. Похоже, что Screen будет моей основной панелью инструментов.
doc_id

tmux > экран. Попробуйте, вы никогда не вернетесь.
h0tw1r3

+1 за тмукс. Я отказался от экрана 5 недель назад.
Брайан Хант

73

В bash, disownключевое слово идеально подходит для этого. Сначала запустите ваш процесс в фоновом режиме (либо используйте &, либо ^Zвведите bg):

$ wget --quiet http://server/some_big_file.zip &
[1] 1156

Набрав, jobsвы можете увидеть, что процесс по-прежнему принадлежит оболочке:

$ jobs
[1]+  Running  wget

Если вы выйдете из системы на этом этапе, фоновая задача также будет уничтожена. Однако, если вы запустите disown, bash отсоединит задание и позволит продолжить его выполнение:

$ disown

Вы можете подтвердить это:

$ jobs
$ logout

Вы можете даже объединить &и disownв одной строке, например:

$ wget --quiet http://server/some_big_file.zip & disown
$ logout

По nohupмоему мнению, это лучше, чем работать, потому что это не оставляет nohup.outфайлы засоренными по всей вашей файловой системе. Кроме того, nohupдолжен быть запущен до запуска команды - disownможет быть использован, если вы только позже решите, что вы хотите в фоновом режиме и отсоединить задачу.


1
Это очень хороший ответ, 1+. Единственным предпочтением для nohup или Screen будет независимость от bash, и он может использоваться с другой оболочкой. Но я буду придерживаться вашего подхода всякий раз, когда использую bash.
doc_id

Да, это зависит от bash, так как bash - единственная оболочка, которую я когда-либо использовал. Интересно, поддерживают ли другие оболочки что-либо подобное (например, запуск в фоновом режиме без nohup) - было бы здорово, если бы кто-то мог публиковать другие ответы для других оболочек.
Джереми Виссер

1
см. мой ответ, показывающий, как это сделать с любым
подобным

1
+1 из-за возможности решить позже. Просто в этот момент у меня была потребность в этом. работал как рекламируется
code_monk

37

Инструмент nohup, доступный в большинстве Linux-боксов, сделает это.


1
Это, безусловно, самый простой ответ. Любые выходные данные автоматически направляются на nohup.out и могут быть рассмотрены позже.
Джулиан

3
nohup вообще не требует zsh.
Аарон Браун

nohup - правильный ответ, он короткий, чтобы не зависать.
Кинджал Диксит

2
nohup встречается на гораздо большем количестве машин, чем на экране, поэтому вы должны знать, как его использовать.
Зенон

27

Просто чтобы быть точным, я укажу на tmux , который имеет ту же основную идею, что и screen:

Предполагается, что tmux является современной альтернативой BSD-лицензированию для таких программ, как GNU screen. Основные функции включают в себя:

  • Мощный, согласованный, хорошо документированный и легко создаваемый сценарий командный интерфейс.
  • Окно может быть разбито по горизонтали и вертикали на панели.
  • Панели можно свободно перемещать и изменять их размер, или размещать в предустановленных макетах.
  • Поддержка UTF-8 и 256-цветных терминалов.
  • Скопируйте и вставьте несколько буферов.
  • Интерактивные меню для выбора окон, сессий или клиентов.
  • Измените текущее окно, выполнив поиск текста в цели.
  • Блокировка терминала, вручную или после тайм-аута.
  • Чистая, легко расширяемая, BSD-лицензированная кодовая база, в стадии активной разработки.

Однако поиск в Google примерно бесконечно проще.


2
Использование в "gnu screen"качестве поискового запроса работает довольно хорошо.
Гнур

4
+1000 за tmux!
МБк

11

Экран излишне просто для того, чтобы поддерживать процессы запущенными при выходе из системы.

Попробуй дтач :

dtach - это программа, написанная на C, которая имитирует функцию отсоединения экрана, которая позволяет выполнять программу в среде, защищенной от управляющего терминала. Например, программа под управлением dtach не будет зависеть от отключения терминала по какой-то причине.

DTACH был написан, потому что экран не соответствует моим потребностям; Мне не нужны были дополнительные функции экрана, такие как поддержка нескольких терминалов или поддержка эмуляции терминала. Экран также был слишком большим, громоздким и имел исходный код, который было трудно понять.

screen также мешал мне использовать полноэкранные приложения, такие как emacs и ircII, из-за чрезмерной интерпретации потока между программой и подключенными терминалами. У dtach нет уровня эмуляции терминала, и он передает необработанный поток вывода программы на подключенные терминалы. Единственная обработка ввода, которую выполняет dtach, - это поиск символа отсоединения (который сигнализирует dtach об отсоединении от программы) и обработка ключа приостановки (который сообщает dtach временно приостановить себя, не затрагивая работающую программу), и оба они могут оба быть отключен при желании.

В отличие от экрана, dtach имеет минимальные возможности и чрезвычайно мал. Это позволяет легче проверять dtach на наличие ошибок и брешей в безопасности, а также делает его доступным в средах с ограниченным пространством, таких как аварийные диски.


Спасибо. Я пришел сюда просто, чтобы написать о dtach тоже. Теперь это мое решение для отделения терминала; экран делает слишком много и мешает вводу до смешного. Экран фактов нуждается в своем собственном termcap, довольно тревожит.
пушистый

9

Вот способ демонизации любого процесса оболочки, не требующий внешних программ:

( while sleep 5; do date; done ) <&- >output.txt &

Когда вы затем закроете сеанс, задание продолжит выполняться, о чем свидетельствует файл output.txt (в котором есть буферизация, поэтому для отображения ненулевого значения требуется некоторое время). Не забудьте убить свою работу после тестирования.

Поэтому все, что вам нужно сделать, это закрыть стандартный ввод и выполнить задание. Чтобы быть действительно хорошим, во-первых, cd /чтобы вы не держались за гору.

Это работает даже в простой sh под Solaris.


Интересно. Это вызвало некоторые заметные вопросы. Я вижу, что вы установили STDIN на ничего, -оператор? В чем разница между < /dev/nullи &-? Я предполагаю, что STDIN (и другие STDOUT и STDERR) могут быть назначены либо файлом < file, либо потоком <& streamв случае STDIN. Будет ли это так же, как < /dev/nullв вашем примере выше? И оператор -выше ссылается на нуль как поток?
doc_id

Когда вы делаете x <& -, это закрывает файловый дескриптор x. В этом случае нет x, что делает bash по умолчанию равным 1, т.е. стандартным вводом. Если вы используете </ dev / null, вы не закрываете стандартный ввод, вы просто даете пустой файл программе в качестве входных данных.
w00t

1
И, честно говоря, я действительно не знаю, почему это демонизирует то, что вы запускаете :-) Это работает, хотя, мы используем его в производстве. Я обнаружил это, бездельничая, надеясь, что смогу демонизировать процесс в оболочке, не требуя ничего особенного - поэтому я начал с закрытия stdin, и этого было достаточно. Мне следует прочитать некоторые исходные коды оболочки, но я предполагаю, что если вы закроете стандартный ввод и создадите фоновый процесс, он также отсоединит процесс.
w00t

2
Я думаю, что причина в том, что SIGHUP (фактический сигнал, который заставляет дочернего элемента выйти, когда оболочка умирает), запускается, когда родительский процесс закрывает дескриптор своего дочернего элемента stdin. Однако, если stdin начинается со значения NULL, а не закрывается после факта, родитель не может запустить SIGHUP. Хорошая находка, хотя - никогда бы не подумал об этом.
Джереми Виссер

@ JeremyVisser, это звучит правдоподобно!
w00t

7

Команда atможет быть полезна для такой ситуации. Например, введите:

at now

И затем вы можете ввести команду или серию команд, которые будут выполняться. Результаты должны быть отправлены вам по электронной почте, если на аппарате правильно настроена электронная почта.

Вместо этого nowвы можете указать время, необязательно, с датой или с помощью выражения времени now + 15 minutes. Смотрите man atдля более подробной информации.


7

byobuна Ubuntu хороший интерфейс для экрана. При нажатии Ctrl- ?вы получите список всех сочетаний клавиш. Он добавляет строку состояния, которая может быть полезна для наблюдения за загрузкой процессора, дисковым пространством и т. Д. В целом, он предоставляет опыт, который я бы описал как терминальное соединение VNC.

nohup позволяет запускать задание в фоновом режиме с выводом его в файл журнала, который всегда может быть перенаправлен в / dev / null, если не требуется.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.