Предотвратить уничтожение запущенной в данный момент задачи linux после выхода из SSH

18

У меня есть вычислительная задача, выполняемая в течение нескольких дней на сервере Linux через SSH-соединение. Это не на заднем плане, поэтому SSH-соединение находится в режиме ожидания задачи.

Я хочу перезагрузить локальную машину (не сервер), с которой я открыл сессию ssh, но хочу, чтобы задача продолжалась. Это возможно?

Али
источник

Ответы:

22

Если ваша задача уже запущена, она слишком поздно , *чтобы рассмотреть альтернативные решения, вставка дополнительный слой между sshсессией и оболочки , выполнив команду, как screen, tmux, byobu, nohupи любит.

Если ваша поддержка процесс будет выполняться в фоновом режиме и , в частности , не зависает , когда stdoutи stderrв записи нового / закрыто, вы можете поместить его в фоновом режиме перед выходом из системы с ControlZи bgзатем отсоединить его от оболочки с disownвстроенной командой.

например:

$ ssh localhost
You have new mail.
Last login: Fri Jun  6 11:26:56 2014

$ /bin/sleep 3600    


^Z[1] + Stopped                  /bin/sleep 3600
$ bg
[1] /bin/sleep 3600&
$ jobs
[1] +  Running                 /bin/sleep 3600
$ disown %1
$ exit
Connection to localhost closed.
$ ps -ef|grep sleep
jlliagre 12864     1  0 21:12 ?        00:00:00 /bin/sleep 3600
jlliagre 13056 12477  0 21:13 pts/18   00:00:00 grep sleep
$ 

*Как прокомментировал Боб, на самом деле есть несколько хакерских способов переписать tty-сессию под Linux. repty, retty , injcode и neercs . Наиболее продвинутый выглядит как reptyr, но вам могут потребоваться привилегии root, чтобы ptrace могла взломать ваш процесс.

jlliagre
источник
Я использовал Ctrl + Z, работа остановилась и переместилась в фоновый режим, затем выполнила disownкоманду. Он вернул: bash: warning: удаление остановленного задания 1 с группой процессов 24876. Теперь моя работа указана в списке, ps -allно, кажется, не работает ( загрузка ЦП составляет 0%)
Али
Кажется, мой процесс остановлен. Я думаю, что я должен был предоставить идентификатор процесса с disownкомандой
Али
@ Али Я думаю, ты забыл запустить команду bg, чтобы возобновить приостановленную работу.
Джейсон
1
@JasonZhu Спасибо, что указали на это. Было неясно, какая bgкоманда требовалась в первой части моего ответа. Ред.
июля
2
Если вы забыли команду bg и выполнили только команду disown, вы сможете снова запустить процесс, который будет работать kill -CONTпримерно так же, как bg.
Касперд
5

Одним из решений является использование экрана GNU . Вы можете запустить screen, выполнить команду, а затем отключиться C-a d. Позже, чтобы восстановить соединение, сделайте screen -r, и вы вернетесь к предыдущей сессии.

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

Редактировать: как отмечено в комментариях, это будет работать только в том случае, если вы не забыли запустить screenперед запуском команды. Если команда уже запущена, вам понадобится решение @ jlliagre.

Скотт Уэлдон
источник
2
tmuxдругая программа, подобная screenэтой, которая позволяет вам иметь удаленный сеанс, который не привязан к вашему текущему SSH-соединению.
Дарт Андроид
2
Ваше решение великолепно. Однако это не совсем соответствует моему вопросу - я спросил о текущем запущенном процессе, а не о процессе, который будет запущен в будущем screen.
Али
Ах хорошо. В этом случае, я думаю, вам нужно будет использовать решение @ jlliagre. (Насколько я знаю, нет способа связать уже запущенный процесс с чем-то вроде screenили tmux.)
Скотт Уэлдон,
1

Один из «стандартных» способов сделать это - использовать nohupкоманду, включенную в coreutils:

nohup COMMAND [ARGS] &

Но команда перенаправит вывод ( STDOUT& STDERRAFAIK) программы в файл nohup.out, что иногда делает его несколько раздражающим (например, создание огромного файла журнала), поэтому вы можете захотеть сделать свое собственное перенаправление или перенаправить его в / dev / null если хочешь.

wangguoqin1001
источник
2
Прочитай заново. Процесс уже запущен .
Легкость гонок с Моникой
/ стыдно не читал внимательно. Сожалею.
wangguoqin1001
На самом деле nohupможет быть использовано для этого. Просто приостановите запущенный процесс и отправьте его в фоновый режим ( Ctrl+ Zи запустите bg), и тогда вы сможете выполнить команду nohup %1.
Майк
0

В дополнение к этому nohupвы можете запустить процесс в фоновом режиме, используя «&» и subshell:

Добавьте к команде команду & и заключите в скобки

$ (thecommand args &)

Допустим, ваш процесс получает pid 1922:

$ ps -f
UID        PID  PPID  C STIME TTY          TIME CMD
usr      11473  2643  0 15:07 pts/1    00:00:00 bash
usr      11922     1  0 15:11 pts/1    00:00:00 thecommand

Посмотрите, что он отсоединен от процесса оболочки 11473, который был его первоначальным родителем. Итак, если вы выйдете или убьете текущую оболочку (11473), процесс 11922 продолжит работу, и он будет отключен от точки.

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

$ ps -fp 11922
UID        PID  PPID  C STIME TTY          TIME CMD
usr      11922     1  0 15:11 ?        00:00:00 thecommand

Я не знаю, как это называется или задокументировано в Posix, но я использую этот способ с 1990 года в bsh, ksh и теперь в bash.

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

Просто запустите свою программу и, если вы решите приостановить ее или планируете оставить ее в фоновом режиме, нажмите CTRL + Z:

$ thecommand
^Z
[1] Stopped          thecommand

Теперь позвольте ему продолжать работать в фоновом режиме:

$ bg
[1]+ thecommand &

Если вы посмотрите на информацию о процессе, у него есть родительский процесс:

$ ps -f
UID        PID  PPID  C STIME TTY          TIME CMD
usr      12046  2643  0 15:18 pts/6    00:00:00 bash
usr      12571 12046  0 16:00 pts/6    00:00:00 thecommand
usr      12601 12046  0 16:04 pts/6    00:00:00 ps -f

Итак, выход из текущего процесса. Запущенный процесс в фоновом режиме отсоединяется от своего исходного родителя и продолжает работать в фоновом режиме:

$ exit

Войдите снова и посмотрите информацию о процессе:

$ ps -f 12571
UID        PID  PPID  C STIME TTY          TIME CMD
usr      12571     1  0 16:00 ?        00:00:00 thecommand
Лучано
источник