Linux: предотвратите остановку фонового процесса после закрытия SSH-клиента


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

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

20 268

20 ответов:

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

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

когда сеанс закрыт, процесс получает сигнал 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.
nohup blah &

замените имя процесса на бла!

демонизации? команды nohup? Экран? (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[] -> 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

и там вы идете, икру что угодно. sleep 1 вместо : потому что его немного колоритно, и я бы получил ошибку "файл занят" - никогда не происходит, если выполняется реальная команда (например,command true)

"heredoc sourcing":

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

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

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

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

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

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

вы можете найти информацию о процессах демонизации в таких книгах, как "Advanced Network Program, Vol 1, 3rd Edn" Стивенса или "Advanced Unix Programming"Рохкинда.

Я недавно (в последние пару лет) пришлось иметь дело с непокорной программой, которая не демонизировала себя должным образом. В итоге я столкнулся с этим, создав общую демонизирующую программу - аналогичную 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 и т. д. Поскольку двойной тире работает везде, лучше всего использовать его.

вы все еще можете свяжитесь со мной (firstname dot фамилия в gmail dot com), Если вы хотите источник для daemonize.

тем не менее, код теперь (наконец) доступен на GitHub в my SOQ (стек Переполнение вопросов) репозиторий в виде файла daemonize-1.10.tgz в пакетов подкаталог.

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

nohup /bin/sh -c "echo $$ > $pidfile; exec $FOO_BIN $FOO_CONFIG  " > /dev/null

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

экрана использовать. Он очень прост в использовании и работает как VNC для терминалов. http://www.bangmoney.org/presentations/screen.html

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

Если этот процесс должен выполняться регулярно, и у вас есть достаточный доступ на сервере, лучшим вариантом было бы использовать cron для запуска задания. Вы также можете использовать init.d (супер-демон), чтобы начать процесс в фоновом режиме, и он может завершиться, как только это сделанный.

в системе на базе Debian (на удаленной машине) Установить:

sudo apt-get install tmux

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

tmux

запуск команд, которые вы хотите

переименовать сессии:

Ctrl+B затем $

название

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

Ctrl+B затем D

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

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

tmux attach session_name

Это вернет вас к вашей сессии tmux.

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

основные команды, которые вы должны знать:

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


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

ctrl+a + c


перейти к n ext экран, который вы создали

ctrl+a+n


до detach

ctrl+a + d


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

экран-r

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

для получения более подробной информации см. man screen.

Я бы также пошел на экран программы (я знаю, что some1 еще ответ был экран, но это завершение)

не только тот факт, что&, ctrl+z BG открещиваются, nohup и т. д. может дать вам неприятный сюрприз, что когда вы выходите из системы, работа все равно будет убита (я не знаю, почему, но это случилось со мной, и это не беспокоило меня, потому что я переключился на использование экрана, но я думаю, что решение anthonyrisinger как двойное разветвление решит это), также экран имеет майор преимущество над просто заземление:

screen will background your process without losing interactive control to it

и кстати, это вопрос, который я бы никогда не задал в первую очередь :) ... я использую экран с самого начала делать что-либо в любом unix ... я (почти) никогда не работаю в оболочке unix/linux без запуска экрана сначала ... и я должен остановиться сейчас, или я начну бесконечную презентацию того, что такое хороший экран и что может сделать для вас ... посмотрите сами, оно того стоит;)

есть еще демон команда пакета libslack с открытым исходным кодом.

daemon вполне настраивается и заботится обо всех утомительных вещах демона, таких как автоматический перезапуск, ведение журнала или обработка pidfile.

добавить эту строку в команду: >&- 2>&- & - означает закрыть stdout. 2 > & - означает закрыть stderr.

$ ssh myhost 'sleep 30 >&- 2>&- <&- &'
# ssh returns right away, and your sleep job is running remotely
$

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

# ((mycommand &)&)

например:

# ((sleep 30 &)&)
# exit

затем откройте новое окно терминала и:

# ps aux | grep sleep

покажем, что sleep 30 по-прежнему работает.

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

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

Если вы хотите запустить X приложений, а также-используйте xpra вместе с "экраном".

Я использовал команду экран. Эта ссылка имеет подробную информацию о том, как это сделать

https://www.rackaid.com/blog/linux-screen-tutorial-and-how-to/#starting

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

установить pm2 вам нужно скачать npm. Для Debian на основе система

sudo apt-get install npm

и для Redhat

sudo yum install npm

или вы можете следовать эти инструкции. После установки npm используйте его для установки pm2

npm install pm2@latest -g

как только это будет сделано, вы можете запустить свое приложение с помощью

$ pm2 start app.js              # Start, Daemonize and auto-restart application (Node)
$ pm2 start app.py              # Start, Daemonize and auto-restart application (Python)

для мониторинга процесса используйте следующие команды:

$ pm2 list                      # List all processes started with PM2
$ pm2 monit                     # Display memory and cpu usage of each app
$ pm2 show [app-name]           # Show all informations about application

управление процессами с помощью имени приложения или идентификатора процесса или управлять всеми процессами вместе:

$ pm2 stop     <app_name|id|'all'|json_conf>
$ pm2 restart  <app_name|id|'all'|json_conf>
$ pm2 delete   <app_name|id|'all'|json_conf>

файлы журнала можно найти в

$HOME/.pm2/logs #contain all applications logs

двоичные исполняемые файлы также могут быть запущены с помощью pm2. Вы должны внести изменения в файл Джейсона. Измените "exec_interpreter" : "node" до "exec_interpreter" : "none". (см. атрибуты).

#include <stdio.h>
#include <unistd.h>  //No standard C library
int main(void)
{
    printf("Hello World\n");
    sleep (100);
    printf("Hello World\n");

    return 0;
}

компиляция кода выше

gcc -o hello hello.c  

и запустить его с np2 в фоновом режиме

pm2 start ./hello

на systemd / Linux, systemd-run это хороший инструмент для запуска независимых от сеанса процессов. Ненавистники будут ненавидеть