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

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

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

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

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

"heredoc sourcing":

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

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


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

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

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


как отмечали другие, чтобы запустить процесс в фоновом режиме, чтобы вы могли отключиться от своего сеанса 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 и т. д. Поскольку double-dash работает везде, лучше всего использовать его.

вы все еще можете свяжитесь со мной (firstname dot lastname в 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 установить 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] и т. д. В том же сеансе шпаклевки.

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

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


до create следующий экран

ctrl+a+c


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

ctrl+a+n


до detach

ctrl+a+d


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

экран-r

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

Подробнее см. В разделе man screen.


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

не только тот факт, что&, ctrl+z BG disown, 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 над nohup имеет много преимуществ, как держать применение живым, поддерживает файлы журнала для применения и много больше других особенностей. Более подробно зацените.

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

sudo apt-get install npm

и для Redhat

sudo yum install 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

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

$ 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", to "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 - хороший инструмент для запуска независимых от сеанса процессов. Ненавистники будут ненавидеть