Как поставить уже запущенный процесс в nohup?

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

Как поместить его в nohup (то есть, как заставить его продолжать работать, даже если я закрою терминал?)

Ответ 1

Используя Управление заданиями bash, чтобы отправить процесс в фоновый режим:

  • Ctrl + Z, чтобы остановить (приостановить) программу и вернуться в оболочку.
  • bg, чтобы запустить его в фоновом режиме.
  • disown -h [job-spec] где [job-spec] - номер задания (например, %1 для первого запущенного задания; найдите свой номер с помощью команды jobs), чтобы задание не было убито, когда терминал закрывается.

Ответ 2

Предположим, по какой-то причине Ctrl + Z также не работает, перейдите на другой терминал, найдите идентификатор процесса (используя ps) и запустите:

kill -SIGSTOP PID 
kill -SIGCONT PID

SIGSTOP приостановит процесс, а SIGCONT возобновит процесс в фоновом режиме. Теперь закрытие обоих терминалов не остановит ваш процесс.

Ответ 3

Команда отделить запущенное задание от оболочки (= делает его nohup) равна disown и базовой командной оболочке.

Из bash -manpage (man bash):

disown [-ar] [-h] [jobspec...]

Без параметров каждый параметр занятости исключается из таблицы активных заданий. Если задана опция -h, каждая спецификация не является удаляется из таблицы, но помечается так, что SIGHUP не отправляется на задание, если оболочка получает SIGHUP. Если никакой присутствует, и ни одна опция -a или -r не предоставляется, используется текущее задание. Если задание не задано, параметр -a означает удалить или отметить все задания; параметр -r без аргумента jobspec ограничивает операцию выполнением заданий. Возврат значение равно 0, если спецификация jobspec не указывает действительное задание.

Это означает, что простой

disown -a

удалит все задания из таблицы заданий и сделает их nohup

Ответ 4

Это хорошие ответы выше, я просто хотел добавить разъяснение:

Вы не можете disown pid или процесс, вы disown задание, и это важное различие.

Задача - это то, что является понятием процесса, прикрепленного к оболочке, поэтому вам нужно бросить задание в фоновом режиме (не приостанавливать его), а затем отключить его.

Вопрос:

%  jobs
[1]  running java 
[2]  suspended vi
%  disown %1

См. http://www.quantprinciple.com/invest/index.php/docs/tipsandtricks/unix/jobcontrol/ для более подробного обсуждения Unix Job Control.

Ответ 5

Непринужденный disown относится к bash и недоступен во всех оболочках.

В некоторых вариантах Unix (например, AIX и Solaris) есть опция в самой команде nohup, которая может быть применена к запущенному процессу:

nohup -p pid

См. http://en.wikipedia.org/wiki/Nohup

Ответ 6

Node Ответ действительно велик, но он оставил открытым вопрос, как можно перенаправить stdout и stderr. Я нашел решение на Unix и Linux, но оно также не завершено. Я хотел бы объединить эти два решения. Вот он:

Для моего теста я сделал небольшой bash script, называемый loop.sh, который печатает сам pid с минутным сном в бесконечном цикле.

$./loop.sh

Теперь получите PID этого процесса. Обычно ps -C loop.sh достаточно хорош, но он напечатан в моем случае.

Теперь мы можем переключиться на другой терминал (или нажмите ^ Z и на том же терминале). Теперь gdb должен быть присоединен к этому процессу.

$ gdb -p <PID>

Это останавливает script (если выполняется). Его состояние можно проверить с помощью ps -f <PID>, где поле STAT равно "T +" (или в случае ^ Z 'T'), что означает (man ps (1))

    T Stopped, either by a job control signal or because it is being traced
    + is in the foreground process group

(gdb) call close(1)
$1 = 0

Закрыть (1) возвращает нуль при успешном завершении.

(gdb) call open("loop.out", 01102, 0600)
$6 = 1

Open (1) возвращает успешный файл нового дескриптора файла.

Это открытие равно open(path, O_TRUNC|O_CREAT|O_RDWR, S_IRUSR|S_IWUSR). Вместо O_RDWR O_WRONLY можно применить, но /usr/sbin/lsof говорит "u" для всех обработчиков файлов std * (столбец FD), который равен O_RDWR.

Я проверил значения в файле заголовка /usr/include/bits/fcntl.h.

Выходной файл можно открыть с помощью O_APPEND, как это сделал бы nohup, но это не предлагается man open(2) из-за возможных проблем с NFS.

Если мы получим -1 как возвращаемое значение, тогда call perror("") выводит сообщение об ошибке. Если нам нужно errno, используйте p errno gdb comand.

Теперь мы можем проверить вновь перенаправленный файл. /usr/sbin/lsof -p <PID> Отпечатки:

loop.sh <PID> truey    1u   REG   0,26        0 15008411 /home/truey/loop.out

Если мы хотим, мы можем перенаправить stderr в другой файл, если мы хотим снова использовать call close(2) и call open(...), используя другое имя файла.

Теперь прикрепленный bash должен быть выпущен, и мы можем выйти gdb:

(gdb) detach
Detaching from program: /bin/bash, process <PID>
(gdb) q

Если script был остановлен на gdb с другого терминала, он продолжает работать. Мы можем вернуться к контуру loop.sh. Теперь он ничего не пишет на экране, но работает и записывается в файл. Мы должны положить это на задний план. Поэтому нажмите ^Z.

^Z
[1]+  Stopped                 ./loop.sh

(Теперь мы находимся в том же состоянии, что и в начале нажатия ^Z).

Теперь мы можем проверить состояние задания:

$ ps -f 24522
UID        PID  PPID  C STIME TTY      STAT   TIME CMD
<UID>    <PID><PPID>  0 11:16 pts/36   S      0:00 /bin/bash ./loop.sh
$ jobs
[1]+  Stopped                 ./loop.sh

Таким образом, процесс должен выполняться в фоновом режиме и отсоединяться от терминала. Число в команде команды jobs в квадратных скобках идентифицирует задание внутри bash. Мы можем использовать в следующих встроенных командах bash, применяя знак "%" перед номером задания:

$ bg %1
[1]+ ./loop.sh &
$ disown -h %1
$ ps -f <PID>
UID        PID  PPID  C STIME TTY      STAT   TIME CMD
<UID>    <PID><PPID>  0 11:16 pts/36   S      0:00 /bin/bash ./loop.sh

И теперь мы можем выйти из вызывающего bash. Процесс продолжает работать в фоновом режиме. Если мы оставим свой PPID, получим 1 (init (1)), а контрольный терминал станет неизвестным.

$ ps -f <PID>
UID        PID  PPID  C STIME TTY      STAT   TIME CMD
<UID>    <PID>     1  0 11:16 ?        S      0:00 /bin/bash ./loop.sh
$ /usr/bin/lsof -p <PID>
...
loop.sh <PID> truey    0u   CHR 136,36                38 /dev/pts/36 (deleted)
loop.sh <PID> truey    1u   REG   0,26     1127 15008411 /home/truey/loop.out
loop.sh <PID> truey    2u   CHR 136,36                38 /dev/pts/36 (deleted)

К.П

Материал gdb можно автоматизировать, создав файл (например, loop.gdb), содержащий команды, и запустите gdb -q -x loop.gdb -p <PID>. Мой loop.gdb выглядит так:

call close(1)
call open("loop.out", 01102, 0600)
# call close(2)
# call open("loop.err", 01102, 0600)
detach
quit

Или можно использовать следующий один вкладыш:

gdb -q -ex 'call close(1)' -ex 'call open("loop.out", 01102, 0600)' -ex detach -ex quit -p <PID>

Надеюсь, это довольно полное описание решения.

Ответ 7

Чтобы отправить запущенный процесс в nohup (http://en.wikipedia.org/wiki/Nohup)

nohup -p pid, у меня не получилось

Затем я попробовал следующие команды, и это работало очень хорошо

  1. Запустите SOMECOMMAND, скажем, /usr/bin/python/vol/scripts/python_scripts/retention_all_properties.py 1.

  2. Ctrl + Z, чтобы остановить (приостановить) программу и вернуться в оболочку.

  3. bg чтобы запустить его в фоновом режиме.

  4. disown -h чтобы процесс не был disown -h терминала.

  5. Введите команду exit чтобы выйти из оболочки, потому что теперь все готово, поскольку операция будет выполняться в фоновом режиме в своем собственном процессе, поэтому она не привязана к оболочке.

Этот процесс эквивалентен запуску nohup SOMECOMMAND.

Ответ 8

В моей системе AIX я попробовал

nohup -p  processid>

Это сработало хорошо. Он продолжал мой процесс даже после закрытия окон терминала. У нас есть ksh в качестве оболочки по умолчанию, поэтому команды bg и disown не работают.

Ответ 9

  1. ctrl + z - это приостановит работу (не отменять!)
  2. bg - это переведет задание в фоновый режим и вернется в рабочий процесс
  3. disown -a - это отрежет все вложения с заданием (так что вы можете закрыть терминал, и он все еще будет работать)

Эти простые шаги позволят вам закрыть терминал, продолжая процесс.

Он не включит nohup (исходя из моего понимания вашего вопроса, он вам здесь не нужен).

Ответ 10

Это работало для меня на Ubuntu Linux, в то время как в Tcshell.

  1. Ctrl Z, чтобы приостановить его

  2. bg для запуска в фоновом режиме

  3. jobs чтобы получить свой номер работы

  4. nohup %n где n - номер задания