In Linux, how to prevent a background process from being stopped after closing SSH client
Я работаю на машине Linux через SSH (Putty). Мне нужно оставить процесс работающим ночью, поэтому я подумал, что смогу сделать это, запустив процесс в фоновом режиме (с амперсандом в конце команды) и перенаправив стандартный вывод в файл. К моему удивлению, это не работает. Как только я закрываю окно Putty, процесс останавливается.
Как я могу предотвратить это?
20 ответов
Я бы порекомендовал использовать GNU Screen. Это позволяет вам отключиться от сервера, пока все ваши процессы продолжают работать. Я не знаю, как я жил без этого, прежде чем я знал, что это существует.
Когда сессия закрыта, процесс получает сигнал 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.
Демон? поЬир? 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). Я никогда не видел, чтобы это было сделано раньше, я самостоятельно обнаружил это, подталкивая, кто знал, что источник может принимать аргументы? Но это часто служит гораздо более управляемой формой оценки, если такая вещь существует.
Лично мне нравится команда "партия".
$ batch
> mycommand -x arg1 -y arg2 -z arg3
> ^D
Это заполняет его на задний план, а затем отправляет результаты по почте вам. Это часть cron.
Для большинства процессов вы можете псевдо-демонизировать, используя этот старый трюк командной строки Linux:
# ((mycommand &)&)
Например:
# ((sleep 30 &)&)
# exit
Затем запустите новое окно терминала и:
# ps aux | grep sleep
Покажет что sleep 30
все еще работает.
Что вы сделали, так это запустили процесс, будучи ребенком ребенка, и когда вы выходите, nohup
Команда, которая обычно запускает процесс для выхода, не распространяется на внучат, оставляя его как процесс-сирота, все еще работающий.
Я предпочитаю такой подход "установи и забудь", не нужно иметь дело с nohup
, screen
, tmux, перенаправление ввода / вывода или что-то в этом роде.
Как уже отмечали другие, для запуска процесса в фоновом режиме, чтобы вы могли отключиться от сеанса 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
в подкаталоге пакетов.
В системе на основе Debian (на удаленной машине) Установите:
sudo apt-get установить tmux
Использование:
tmux
запустить команды, которые вы хотите
Чтобы переименовать сессию:
Ctrl + B, затем $
Имя набора
Чтобы выйти из сеанса:
Ctrl + B, затем D
(это оставляет сеанс tmux). Затем вы можете выйти из SSH.
Когда вам нужно вернуться / проверить это снова, запустите SSH и введите
tmux прикрепить имя_сессии
Это вернет вас к сеансу tmux.
nohup
очень хорошо, если вы хотите записать свои данные в файл. Но когда дело доходит до фона, вы не можете дать ему пароль, если ваши скрипты просят. Я думаю, что вы должны попробовать screen
, это утилита, которую вы можете установить в свой дистрибутив Linux, используя yum, например, для CentOS yum install screen
затем получить доступ к вашему серверу с помощью замазки или другого программного обеспечения, в вашем типе оболочки screen
, Откроется экран [0] в замазке. Ты работаешь. Вы можете создать больше экрана [1], экрана [2] и т. Д. В одном сеансе замазки.
Основные команды, которые вам нужно знать:
Для запуска экрана
экран
Чтобы создать следующий экран
Ctrl+ A + C
Для перехода на новый экран, который вы создали
Ctrl+ A + N
Чтобы быть
Ctrl+ A + D
Во время работы закройте замазку. И в следующий раз, когда вы входите через тип замазки
экран -r
Для повторного подключения к экрану, и вы можете увидеть, что ваш процесс все еще работает на экране. И для выхода из экрана наберите #exit.
Для более подробной информации смотрите man screen
,
Nohup позволяет клиентскому процессу не быть убитым, если родительский процесс убит, для аргумента при выходе из системы. Еще лучше еще использовать:
nohup /bin/sh -c "echo \$\$ > $pidfile; exec $FOO_BIN $FOO_CONFIG " > /dev/null
Nohup делает процесс, который вы запускаете, невосприимчивым к прекращению, которое сеанс SSH и его дочерние процессы уничтожают при выходе из системы. Команда, которую я дал, предоставляет вам способ сохранить pid приложения в pid-файле, чтобы вы могли корректно убить его позже и позволить процессу запускаться после выхода из системы.
Если вы используете экран для запуска процесса от имени пользователя root, остерегайтесь возможности атак с повышением привилегий. Если ваша собственная учетная запись каким-то образом будет скомпрометирована, то будет прямой путь к захвату всего сервера.
Если этот процесс необходимо запускать регулярно и у вас есть достаточный доступ к серверу, лучшим вариантом будет использование cron для запуска задания. Вы также можете использовать init.d (супер-демон) для запуска вашего процесса в фоновом режиме, и он может завершиться, как только это будет сделано.
Используйте экран. Он очень прост в использовании и работает как vnc для терминалов. http://www.bangmoney.org/presentations/screen.html
Также есть команда daemon из пакета с открытым исходным кодом libslack.
daemon
вполне настраивается и заботится обо всех утомительных вещах демона, таких как автоматический перезапуск, ведение журнала или обработка pidfile.
Принятый ответ предлагает использовать 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
Если вы также хотите запускать X-приложения - используйте xpra вместе с "screen".
Я также хотел бы пойти на экран программы (я знаю, что еще один ответ был экран, но это завершение)
не только тот факт, что &, ctrl+z bg disown, nohup и т. д. может преподнести вам неприятный сюрприз, что когда вы выйдете из системы, работа все равно будет убита (я не знаю почему, но это случилось со мной, и это не беспокоило это потому, что я переключился на использование экрана, но я думаю, что решение anthonyrisinger, поскольку двойное разветвление решило бы это), также экран имеет большое преимущество по сравнению с просто отступлением:
screen will background your process without losing interactive control to it
и кстати, это вопрос, который я бы никогда не задал в первую очередь:) ... я использую screen с самого начала, чтобы что-то делать в любом unix ... я (почти) НИКОГДА не работаю в оболочке unix/linux без начального экрана сначала... и я должен остановиться сейчас, или я начну бесконечное представление о том, что такое хороший экран и что может для вас сделать... посмотрите сами, оно того стоит;)
Добавьте эту строку в вашу команду:> & - 2> & - <& - &. >& - означает закрытие стандартного вывода. 2>&- означает закрыть stderr. <& - означает закрытие стандартного ввода. & означает запуск в фоновом режиме. Это также работает для программного запуска задания через ssh:
$ ssh myhost 'sleep 30 >&- 2>&- <&- &'
# ssh returns right away, and your sleep job is running remotely
$
Я использовал экранную команду. Эта ссылка подробно о том, как это сделать
https://www.rackaid.com/blog/linux-screen-tutorial-and-how-to/
В systemd/Linux systemd-run - хороший инструмент для запуска независимых от сессии процессов. Ненавистники пусть ненавидят