В Linux, как предотвратить остановку фонового процесса после закрытия клиента SSH - PullRequest
279 голосов
/ 12 ноября 2008

Я работаю на машине с Linux через SSH (Putty). Мне нужно оставить процесс работающим ночью, поэтому я подумал, что могу сделать это, запустив процесс в фоновом режиме (с амперсандом в конце команды) и перенаправив стандартный вывод в файл. К моему удивлению, это не работает. Как только я закрываю окно Putty, процесс останавливается.

Как я могу предотвратить это?

Ответы [ 20 ]

294 голосов
/ 12 ноября 2008

Проверьте программу " nohup ".

163 голосов
/ 12 ноября 2008

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

78 голосов
/ 12 ноября 2008

Когда сеанс закрыт, процесс получает сигнал SIGHUP, который он явно не перехватывает. Вы можете использовать команду nohup при запуске процесса или встроенную команду bash disown -h после запуска процесса, чтобы этого не происходило:

> help disown
disown: disown [-h] [-ar] [jobspec ...]
     By default, removes each JOBSPEC argument from the table of active jobs.
    If the -h option is given, the job is not removed from the table, but is
    marked so that SIGHUP is not sent to the job if the shell receives a
    SIGHUP.  The -a option, when JOBSPEC is not supplied, means to remove all
    jobs from the job table; the -r option means to remove only running jobs.
37 голосов
/ 10 марта 2012

демон? поЬир? SCREEN? (tmux ftw, экран мусорный; -)

Просто сделайте то, что делало любое другое приложение с самого начала - двойная вилка.

# ((exec sleep 30)&)
# grep PPid /proc/`pgrep sleep`/status
PPid:   1
# jobs
# disown
bash: disown: current: no such job

Взрыв! Готово :-) Я использовал это бесчисленное количество раз на всех типах приложений и на многих старых машинах. Вы можете комбинировать с перенаправлениями и так далее, чтобы открыть частный канал между вами и процессом.

Создать как coproc.sh:

#!/bin/bash

IFS=

run_in_coproc () {
    echo "coproc[$1] -> main"
    read -r; echo $REPLY
}

# dynamic-coprocess-generator. nice.
_coproc () {
    local i o e n=${1//[^A-Za-z0-9_]}; shift
    exec {i}<> <(:) {o}<> >(:) {e}<> >(:)
. /dev/stdin <<COPROC "${@}"
    (("\$@")&) <&$i >&$o 2>&$e
    $n=( $o $i $e )
COPROC
}

# pi-rads-of-awesome?
for x in {0..5}; do
    _coproc COPROC$x run_in_coproc $x
    declare -p COPROC$x
done

for x in COPROC{0..5}; do
. /dev/stdin <<RUN
    read -r -u \${$x[0]}; echo \$REPLY
    echo "$x <- main" >&\${$x[1]}
    read -r -u \${$x[0]}; echo \$REPLY
RUN
done

, а затем

# ./coproc.sh 
declare -a COPROC0='([0]="21" [1]="16" [2]="23")'
declare -a COPROC1='([0]="24" [1]="19" [2]="26")'
declare -a COPROC2='([0]="27" [1]="22" [2]="29")'
declare -a COPROC3='([0]="30" [1]="25" [2]="32")'
declare -a COPROC4='([0]="33" [1]="28" [2]="35")'
declare -a COPROC5='([0]="36" [1]="31" [2]="38")'
coproc[0] -> main
COPROC0 <- main
coproc[1] -> main
COPROC1 <- main
coproc[2] -> main
COPROC2 <- main
coproc[3] -> main
COPROC3 <- main
coproc[4] -> main
COPROC4 <- main
coproc[5] -> main
COPROC5 <- main

А вот и ты, порождай что угодно. <(:) открывает анонимный канал через подстановку процесса, которая умирает, но канал остается на месте, потому что у вас есть дескриптор. Я обычно делаю <code>sleep 1 вместо :, потому что он немного грубый, и я получаю ошибку "file busy" - никогда не происходит, если выполняется настоящая команда (например, command true)

"heredoc sourcing":

. /dev/stdin <<EOF
[...]
EOF

Это работает на всех оболочках, которые я когда-либо пробовал, включая busybox / etc (initramfs). Я никогда не видел, чтобы это было сделано раньше, я самостоятельно обнаружил это, подталкивая, кто знал, что источник может принимать аргументы? Но это часто служит гораздо более управляемой формой eval, если она существует.

33 голосов
/ 12 ноября 2008
nohup blah &

Замените имя вашего процесса на бла!

17 голосов
/ 12 ноября 2008

Лично мне нравится команда 'batch'.

$ batch
> mycommand -x arg1 -y arg2 -z arg3
> ^D

Это помещает его в фон, а затем отправляет результаты вам по почте. Это часть cron.

11 голосов
/ 12 ноября 2008

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

Вы можете найти информацию о демонизирующих процессах в книгах, таких как «Расширенная сетевая программа Стивенса», том 1, 3-е издание, или «Расширенное программирование Unix» Рочкинда.

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

Usage: daemonize [-abchptxV][-d dir][-e err][-i in][-o out][-s sigs][-k fds][-m umask] -- command [args...]
  -V          print version and exit
  -a          output files in append mode (O_APPEND)
  -b          both output and error go to output file
  -c          create output files (O_CREAT)
  -d dir      change to given directory
  -e file     error file (standard error - /dev/null)
  -h          print help and exit
  -i file     input file (standard input - /dev/null)
  -k fd-list  keep file descriptors listed open
  -m umask    set umask (octal)
  -o file     output file (standard output - /dev/null)
  -s sig-list ignore signal numbers
  -t          truncate output files (O_TRUNC)
  -p          print daemon PID on original stdout
  -x          output files must be new (O_EXCL)

Двойная черта не обязательна в системах, не использующих функцию GNU getopt (); это необходимо (или вы должны указать POSIXLY_CORRECT в среде) в Linux и т. д. Поскольку двойная черта работает везде, лучше всего ее использовать.

Вы все еще можете связаться со мной (имя, точка, фамилия на gmail, точка com), если вам нужен источник для daemonize.

Однако код теперь (наконец-то) доступен на GitHub в моем SOQ (стек Переполнение Вопросы) хранилище в виде файла daemonize-1.10.tgz в пакеты подкаталог.

5 голосов
/ 03 июля 2016

Для большинства процессов вы можете псевдо-демонизировать, используя этот старый трюк командной строки Linux:

# ((mycommand &)&)

Например:

# ((sleep 30 &)&)
# exit

Затем запустите новое окно терминала и:

# ps aux | grep sleep

покажет, что sleep 30 все еще работает.

Что вы сделали, так это запустили процесс как дочерний элемент дочернего процесса, и при выходе команда nohup, которая обычно запускает выход процесса, не переходит к внуку, оставляя его как процесс-сирота, все еще работающий.

Я предпочитаю этот подход «установи и забудь», нет необходимости иметь дело с nohup, screen, tmux, перенаправлением ввода-вывода или чем-то подобным.

5 голосов
/ 26 апреля 2014

В системе на основе Debian (на удаленной машине) Установка:

sudo apt-get install tmux

Использование:

tmux

Запустите нужные вам команды

Чтобы переименовать сессию:

Ctrl + B , затем $

имя набора

Для выхода из сеанса:

Ctrl + B , затем D

(это оставляет сеанс tmux). Затем вы можете выйти из SSH.

Когда вам нужно вернуться / проверить это снова, запустите SSH и введите

tmux attach_name_name

Он вернет вас к сеансу tmux.

5 голосов
/ 05 марта 2014

nohup очень хорошо, если вы хотите записать свои данные в файл. Но когда дело доходит до фона, вы не можете дать ему пароль, если ваши скрипты просят. Я думаю, что вы должны попробовать screen. Это утилита, которую вы можете установить в своем дистрибутиве Linux с помощью yum, например, на CentOS yum install screen, а затем получить доступ к вашему серверу с помощью замазки или другого программного обеспечения в вашей оболочке типа screen. Откроется экран [0] в замазке. Ты работаешь. Вы можете создать больше экрана [1], экрана [2] и т. Д. За один сеанс замазки.

Основные команды, которые вам необходимо знать:

Для запуска экрана

экран


К с открыть следующий экран

Ctrl + а + с


Для перехода на n ext созданный вами экран

Ctrl + A + N


К д Этач

Ctrl + A + D


Во время работы закройте замазку. И в следующий раз при входе через шпаклевку наберите

screen -r

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

Подробнее см. man screen.

...