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


291

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

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

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

Ответы:


301

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


4
Как вы остановите это потом?
Дерек Дамер

9
Войдите в систему и выполните команду «kill <pid>». Используйте «pidof», если вы не знаете, pid.
JesperE

32
Вы можете использовать nohup command > /dev/null 2>&1 &для запуска в фоновом режиме, не создавая вывод stdout или stderr (без nohup.outфайла)
KCD

Что делать, если мне нужно предоставить какой-то вклад? Например, у меня есть долгосрочный скрипт, который мне нужно запустить в фоновом режиме, но сначала он запрашивает мой пароль FTP. nohupне помогает в этом случае. Есть ли способ возиться с Ctrl+Z/ bg?
Сергей

1
Так как я ленив и плохо запоминаю загадочные последовательности символов, я написал это , основываясь на том, что сказал @KCD, и много использовал его.
Аномалия

167

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


7
Это одна из величайших программ, которые я когда-либо использовал. Шутки в сторону. У меня он работает на BSD-боксе, в который я запускаю ssh из ВЕЗДЕ, и я могу просто заново подключить его к моему экрану и иметь все свои терминалы, где я делаю все виды вещей.
Адам Яскевич

1
Я могу засвидетельствовать это. Экран - отличное приложение. Способность повторно прикрепить удивительна и экономит много потенциально потерянной работы.
Будет

Я даже использую его на локальных машинах и присоединяю несколько xterms к одному сеансу экрана (screen -x). Таким образом, я могу открыть много окон в своем сеансе экрана и свободно переключать свои различные xterms из окна в окно.
Адам Яскевич

17
Зависит от того, нужно ли вам повторно подключаться к фоновому приложению или нет. Если вы это сделаете, то да, экран - единственный способ летать. Однако, если это огонь и забыл, то nohup отвечает всем требованиям так же хорошо, если не лучше.
Дейв Шерохман

1
+1 за экран. Или, в качестве альтернативы, tmux (мне это нравится больше, чем screen) или даже byobu, который является хорошим интерфейсом для screen или tmux. Вы можете просто набрать screen, чтобы использовать оболочку и вернуться позже в любое время, или выполнить команду с экраном, например, «команда экрана»: сеанс экрана будет существовать до тех пор, пока существует «команда» процесса, и если это что-то очень долго, вы можете вернуться и посмотреть на его стандартный вывод в любое время.
Герлос

81

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

4
Преимущество здесь в том, что disown работает для процессов, которые уже были запущены.
Кристиан К.

1
«Jobpec» означает пид?
Стюарт

1
Не беспокойтесь, нашел этот ответ здесь stackoverflow.com/questions/625409/…
Стюарт

42

демон? поЬир? 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

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

"Heredoc Sourcing":

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

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


2
почему голосование "за" ... так что, если вопрос старый; это очевидно актуально, учитывая, что есть еще 11 ответов, которые отстой Это решение без системного, идиоматического и общепринятого способа демонизации в течение последних 30 лет, а не бессмысленные приложения, например. nohup et al.
Anthonyrisinger

7
Неважно, насколько хорош ваш ответ, иногда кому-то в SO это не понравится и он понизит голос. Лучше не беспокоиться об этом слишком сильно.
Алекс Д

1
@ tbc0 ... попробуйssh myhost "((exec sleep 500)&) >/dev/null"
anthonyrisinger

1
@anthonyrisinger хорошо, это работает. Я думаю, что это чище: ssh myhost 'sleep 500 >&- 2>&- <&- &' TMTOWTDI;)
tbc0

1
Это круто. единственное решение, которое действительно работает в busybox. он заслуживает больше upvotes
Hamy

34
nohup blah &

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


2
Вы могли бы хотеть добавить стандартное перенаправление и стандартную ошибку.
Дэвид Нехм

9
nohup перенаправляет stdout и stderr на nohup.out (или nohup.out и nohup.err в зависимости от версии), поэтому, если вы не запускаете несколько команд, это необязательно.
час. Оуэнс

17

Лично мне нравится команда «партия».

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

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


11

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


13
Почему бы вам не поставить исходники на github или bitbucket?
Роб

5
Почему отсутствие источника в github оправдывает снижение?
Джонатан Леффлер

7
@JonathanLeffler ИМХО, перечисляющий все классные опции программы, которая недоступна публично в любой форме (даже в коммерческой), граничит с потерей времени читателя
ДепрессияДаниэль

7

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

sudo apt-get установить tmux

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

tmux

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

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

Ctrl + B, затем $

Имя набора

Чтобы выйти из сеанса:

Ctrl + B, затем D

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

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

tmux прикрепить имя_сессии

Это вернет вас к сеансу tmux.


это путь, чтобы пойти
kilgoretrout

6

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

# ((mycommand &)&)

Например:

# ((sleep 30 &)&)
# exit

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

# ps aux | grep sleep

Покажет что sleep 30еще работает.

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

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


5

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

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


5

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

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

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

экран


К с reate следующего экрана

Ctrl + A + C


Перейти к п экрану внутра вы создали

Ctrl + A + N


К г etach

Ctrl + A + D


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

экран -r

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

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


предполагать, что yumэто правильный инструмент, когда вы не знаете дистрибутив, это не хорошо. Вы должны четко указать, на какие дистрибутивы screenможно установить yum.
тымик

5

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

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

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




2

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

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

screen will background your process without losing interactive control to it

и кстати, это вопрос, который я бы никогда не задал в первую очередь :) ... я использую экран с самого начала, чтобы что-то делать в любом Unix ... я (почти) НИКОГДА не работаю в оболочке Unix / Linux без начального экрана во-первых ... и я должен остановиться сейчас, или я начну бесконечное представление о том, что такое хороший экран и что может для вас сделать ... посмотрите сами, оно того стоит;)


PS Anthonyrisinger, ты хороший, я даю тебе это, но ... 30 лет? Могу поспорить, что это решение, когда &, bg, nohup или screen еще не было, и без обид я ценю ваши знания, но это слишком сложно, чтобы их использовать :)
THESorcerer

2
(в сторону: см. Tmux ), хотя это значительно предшествует мне [1987], &(асинхронное выполнение) было введено оболочкой Томпсона в 1971 году для первой версии UNIX ... так что буквально "всегда было" ;-) увы, Я был слишком консервативен - на самом деле это был 41 год.
Антонирингер

2

Также есть команда daemon из пакета с открытым исходным кодом libslack.

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


2

Добавьте эту строку в вашу команду:> & - 2> & - <& - &. > & - означает закрытый стандартный вывод. 2> & - означает закрыть stderr. <& - означает закрытие стандартного ввода. & означает запуск в фоновом режиме. Это также работает для программного запуска задания через ssh:

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


1

Принятый ответ предлагает использовать nohup . Я бы предпочел использовать pm2 . Использование pm2 по сравнению с 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

Может ли это использоваться для запуска двоичных исполняемых файлов?
GetFree

@Получить бесплатно; Да. Ты можешь.
Хак

Добавьте пример, пожалуйста. Ответ, как он есть сейчас, выглядит так, как будто он подходит только для файлов сценариев.
GetFree

@Получить бесплатно; Добавил пример. Дайте мне знать, если у вас возникнут проблемы.
Хак

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.