18

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

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

4 ответа4

22

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

Если ваша поддержка процесса находится в фоновом режиме и, в частности, не зависает, когда stdout и stderr недоступны для записи / закрытия, вы можете поместить его в фоновый режим перед выходом из системы с помощью Control Z и 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 могла взломать ваш процесс.

5

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

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

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

1

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

nohup COMMAND [ARGS] &

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

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

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