Як запобігти зупинці фонового процесу після закриття SSH-клієнта в Linux


291

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

На мій подив, це не працює. Як тільки я закриваю вікно Putty, процес зупиняється.

Як я можу не допустити цього ??

Відповіді:


301

Ознайомтеся з програмою " nohup ".


4
Як зупинити це згодом?
Дерек Дамер

9
Увійдіть і виконайте "вбив <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-коробці, в яку я схиляюсь від ВСІХ, і я можу просто приєднатись до мого екрана і мати всі мої термінали, де я роблю всілякі речі.
Адам Яскевич

1
Я можу засвідчити це. Екран - чудове додаток. Можливість повторного приєднання дивує, і економить багато потенційно втраченої роботи.
Вільно, що

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

17
Залежить від того, потрібно підключитися до фонового додатка чи ні. Якщо так, то, так, екран - це єдиний спосіб літати. Якщо це вогонь і забудь, то nohup підходить до рахунку так само добре, якщо не краще.
Дейв Шерохман

1
+1 для екрана Або, як альтернатива, tmux (мені це подобається більше, ніж екран), або навіть byobu, що є приємним інтерфейсом для екрану чи tmux. Ви можете просто ввести екран, щоб отримати оболонку для використання та повернення пізніше в будь-який час, або запустити свою команду екраном, як-от "команда екрана": сеанс на екрані буде існувати до тих пір, поки існує "командна команда" процесу, і якщо це щось дуже довго ви можете в будь-який час повернутися назад і подивитися на його стандартний вихід.
gerlos

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
Перевагою тут є те, що відмова працює для вже запущених процесів.
Крістіан К.

1
Чи означає "jobspec" під?
Стюарт

1
Не хвилюйтесь, знайшов цю відповідь тут stackoverflow.com/questions/625409/…
Стюарт

42

демонізувати? 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[$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замість того, :що це злегка швидкість, і я отримаю помилку "файл зайнятий" - ніколи не трапляється, якщо виконується реальна команда (наприклад, command true)

"пошук гередока":

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

Це працює на кожній оболонці, яку я коли-небудь пробував, включаючи зайнятий / тощо (initramfs). Я ніколи не бачив, як це робилося раніше, я самостійно виявляв це під час видання, хто знав, що джерело може прийняти аргументи? Але це часто служить набагато більш керованою формою eval, якщо є така річ.


2
чому голос "за" - "ні", і що, якщо питання старе; це, очевидно, актуально, враховуючи, що є 11 інших відповідей. це рішення, sans systemd, ідіоматичний і прийнятий спосіб демонізації за останні 30 років, а не безглузді програми, наприклад. ногуп та ін.
антонірізінгер

7
незалежно від того, наскільки хороша ваша відповідь, іноді комусь із ТАК це не сподобається, і він спростує. Краще не надто турбуватися про це.
Алекс Д

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

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

1
Це чудово. єдине рішення, яке насправді працює у зайнятій скриньці. він заслуговує на більші результати
Хемі

34
nohup blah &

Замініть своє ім'я процесу на бла!


2
ви можете додати стандартний вихід і стандартну помилку.
Девід Неме

9
nohup перенаправляє stdout і stderr на nohup.out (або nohup.out і nohup.err залежно від версії), тому, якщо ви не виконуєте кілька команд, це не потрібно.
Час. Овенс

17

Особисто мені подобається команда 'batch'.

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

Це додає його на другий план, а потім надсилає вам результати. Це частина крону.


11

Як зазначали інші, щоб запустити процес у фоновому режимі, щоб ви могли відключитися від свого сеансу SSH, вам потрібно, щоб фоновий процес належним чином відмежувався від свого керуючого терміналу - це псевдо-tty, яку використовує сеанс 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)

Подвійний тире необов’язковий для систем, які не використовують функцію getopt () GNU; це необхідно (або вам потрібно вказати POSIXLY_CORRECT у середовищі) на Linux тощо. Оскільки подвійний тире працює скрізь, найкраще використовувати його.

Ви все ще можете зв’язатися зі мною (прізвище крапки з ім'ям на gmail dot com), якщо ви хочете джерело для daemonize.

Однак код тепер (нарешті) доступний на GitHub у моєму сховищі SOQ (Stack Overflow) як файл daemonize-1.10.tgzу підкаталозі пакунків .


13
Чому ви не покладете джерело на github чи bitbucket?
Роб

5
Чому відсутність джерела з github є причиною знищення?
Джонатан Леффлер

7
@JonathanLeffler IMHO перелічує всі цікаві варіанти програми, яка не є загальнодоступною у будь-якій формі (навіть комерційно) не обмежує витрачання читацького часу.
ДепресіяДаніель

7

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

sudo apt-get install tmux

Використання:

tmux

запускайте потрібні команди

Щоб перейменувати сеанс:

Ctrl + B, то $

встановити ім'я

Щоб вийти з сеансу:

Ctrl + B, потім D

(це залишає сеанс tmux). Потім ви можете вийти із SSH.

Коли вам потрібно повернутися / перевірити його ще раз, запустіть SSH та введіть

tmux вкласти ім'я_сеансу

Це поверне вас до вашого tmux сеансу.


це шлях
кілгоретро

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


Щоб перейти до створеного вами екрану n ext

ctrl + a + n


До д етач

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

Я б також пішов на екранні програми (я знаю, що відповідь Some1 else був екраном, але це завершення)

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

screen will background your process without losing interactive control to it

і btw, це питання, якого я ніколи не задавав би в першу чергу :) ... я використовую екран з мого початку робити що-небудь в будь-якому Unix ... я (майже) НІКОЛИ не працюю в оболонці unix / linux без запуску екрана по-перше ... і я повинен зупинитися зараз, інакше я розпочну нескінченну презентацію того, що таке хороший екран і що можна зробити для тебе ... подивіться самі, воно того варте;)


PS anthonyrisinger, ти хороший, я тобі це даю, але ... 30 років? Б'юсь об заклад, що це рішення, коли &, bg, nohup чи екран ще не було, і не ображаюсь, я ціную ваші знання, але це занадто складно для його використання :)
THESorcerer

2
(вбік: див. Tmux ), хоча це значною мірою передувало мені [1987], &(асинхронне виконання) було введено оболонкою Томпсона в 1971 році , для першої версії UNIX ... так це буквально "завжди було" ;-) на жаль, Я був занадто консервативним - насправді минуло 41 рік.
anthonyrisinger

2

Існує також команда демон демонстраційного пакету з відкритим кодом.

daemon цілком налаштовується і не турбується про всі нудні речі демон, такі як автоматичний перезапуск, ведення журналів або обробка файлами pidfile.


2

Додайте цей рядок до вашої команди:> & - 2> & - <& - &. > & - означає закрити stdout. 2> & - означає близько stderr. <& - означає близький stdin. & означає працювати у фоновому режимі. Це працює і для програмного початку роботи через ssh:

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


1

Прийнята відповідь пропонує використовувати ногуп . Я вважаю за краще запропонувати використовувати pm2 . Використання PM2 над поЬіром має багато переваг, як тримати додаток живим, зберігати файли журнал для програми та багато інших інших функції. Для більш детальної інформації перевірте це .

Щоб встановити 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.