У меня есть процесс, который уже запущен в течение длительного времени, и я не хочу его завершать.
Как поместить его в nohup (то есть, как заставить его продолжать работать, даже если я закрою терминал?)
У меня есть процесс, который уже запущен в течение длительного времени, и я не хочу его завершать.
Как поместить его в nohup (то есть, как заставить его продолжать работать, даже если я закрою терминал?)
Ответы:
Использование Job Control в bash для отправки процесса в фоновый режим:
bg
запустить его в фоновом режиме.disown -h [job-spec]
где [job-spec] - номер задания (как %1
для первого запущенного задания; узнайте о вашем номере с помощью jobs
команды), чтобы задание не было убито при закрытии терминала.disown -h
возможно, более точный ответ: «заставить disown вести себя больше как nohup (то есть задания будут оставаться в дереве процессов вашей текущей оболочки до тех пор, пока вы не выйдете из нее). Это позволяет увидеть все работы, которые начались этой оболочкой ". (из [ quantprinciple.com/invest/index.php/docs/tipsandtricks/unix/… )
disown
, disown делает процесс демоном, что означает, что стандартный ввод / вывод перенаправляется в / dev / null. Итак, если вы планируете отказаться от работы, лучше начать ее с входа в файл, напримерmy_job_command | tee my_job.log
Предположим, по какой-то причине Ctrl+ Zтоже не работает, перейдите на другой терминал, найдите идентификатор процесса (используя ps
) и запустите:
kill -SIGSTOP PID
kill -SIGCONT PID
SIGSTOP
приостановит процесс и SIGCONT
возобновит процесс в фоновом режиме. Теперь закрытие обоих терминалов не остановит ваш процесс.
disown %1
в первом терминале, прежде чем закрывать его.
kwin
после сбоя, не задумываясь о последствиях). Так что, если бы я остановил Kwin, все бы заморозилось, и у меня не было возможности бежать bg
!
Команда для отделения запущенного задания от оболочки (= делает его nohup) является disown
и основной командой оболочки.
Из man-страницы bash (man bash):
отречься [-ar] [-h] [задание на работу ...]
Без параметров каждая спецификация заданий удаляется из таблицы активных заданий. Если указана опция -h, каждая спецификация заданий не удаляется из таблицы, а помечается так, что SIGHUP не отправляется заданию, если оболочка получает SIGHUP. Если спецификация заданий отсутствует и не указана ни опция -a, ни опция -r, используется текущее задание. Если спецификация заданий не указана, опция -a означает удалить или отметить все задания; опция -r без аргумента jobspec ограничивает выполнение операций заданиями. Возвращаемое значение равно 0, если в задании не указано допустимое задание.
Это означает, что простой
disown -a
удалит все задания из таблицы заданий и сделает их нету
disown -a
удаляет все задания Простое disown
удаляет только текущую работу. Как говорится в справочной странице в ответе.
Это хорошие ответы выше, я просто хотел добавить пояснение:
Вы не можете disown
пид или процесс, вы disown
работа, и это важное различие.
Задание - это то, что является понятием процесса, прикрепленного к оболочке, поэтому вы должны выбросить задание в фоновый режим (не приостанавливать его), а затем отказаться от него.
Выпуск:
% jobs
[1] running java
[2] suspended vi
% disown %1
См. Http://www.quantprinciple.com/invest/index.php/docs/tipsandtricks/unix/jobcontrol/ для более подробного обсуждения Unix Job Control.
К сожалению, disown
это специфично для bash и доступно не во всех оболочках.
Некоторые разновидности Unix (например, AIX и Solaris) имеют параметр для самой nohup
команды, который можно применить к запущенному процессу:
nohup -p pid
Смотрите http://en.wikipedia.org/wiki/Nohup
AIX
а Solaris
. «Версии nohup в AIX и Solaris имеют опцию -p, которая изменяет запущенный процесс, игнорируя будущие сигналы SIGHUP. В отличие от описанного выше встроенного в bash disown, nohup -p принимает идентификаторы процессов». Источник
Ответ Node действительно хорош, но он оставил открытым вопрос, как перенаправить stdout и stderr. Я нашел решение для Unix и Linux , но оно также не завершено. Я хотел бы объединить эти два решения. Вот:
Для своего теста я создал небольшой скрипт bash, называемый loop.sh, который печатает pid самого себя с минутным сном в бесконечном цикле.
$./loop.sh
Теперь получите PID этого процесса как-то. Обычно ps -C loop.sh
это достаточно хорошо, но это напечатано в моем случае.
Теперь мы можем переключиться на другой терминал (или нажать ^ Z и на том же терминале). Теперь gdb
следует присоединиться к этому процессу.
$ gdb -p <PID>
Это останавливает скрипт (если запущен). Его состояние может быть проверено 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
Close (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("")
выводит сообщение об ошибке. Если нам нужна ошибка, используйте команду p errno
gdb.
Теперь мы можем проверить вновь перенаправленный файл. /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
Если скрипт был остановлен 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>
Я надеюсь, что это довольно полное описание решения.
lsof
(имя дескриптора файла pipe
, а не как /dev/pts/1
) или с помощью ls -l /proc/<PID>/fd/<fd>
(это показывает символическую ссылку на дескриптор). Также подпроцессы все еще могут иметь не перенаправленные выходные данные, которые должны быть перенаправлены в файл.
Чтобы отправить запущенный процесс в nohup ( http://en.wikipedia.org/wiki/Nohup )
nohup -p pid
у меня не получилось
Затем я попробовал следующие команды, и это работало очень хорошо
Запустите SOMECOMMAND, скажем /usr/bin/python /vol/scripts/python_scripts/retention_all_properties.py 1
.
Ctrl+ Zостановить (приостановить) программу и вернуться в оболочку.
bg
запустить его в фоновом режиме.
disown -h
так что процесс не будет убит при закрытии терминала.
Напечатайте, exit
чтобы выйти из оболочки, потому что теперь все готово, поскольку операция будет выполняться в фоновом режиме в своем собственном процессе, поэтому она не привязана к оболочке.
Этот процесс эквивалентен запуску nohup SOMECOMMAND
.
bg
- это переведет задание в фоновый режим и вернется в рабочий процессdisown -a
- это отрежет все вложения с заданием (так что вы можете закрыть терминал, и он все еще будет работать)Эти простые шаги позволят вам закрыть терминал, продолжая процесс.
Он не наденет nohup
(исходя из моего понимания вашего вопроса, он вам здесь не нужен).
Это работало для меня на Ubuntu Linux в то время как в Tcshell.
CtrlZ приостановить это
bg
бежать в фоновом режиме
jobs
чтобы получить свой номер работы
nohup %n
где n - номер работы
nohup: failed to run command '%1': No such file or directory
yourExecutable &
и выходы продолжают появляться на экране иCtrl+C
, кажется, ничего не останавливает, просто печатайте вслепуюdisown;
и нажимайте,Enter
даже если экран прокручивается с выходами, и вы не видите ты печатаешь Процесс будет остановлен, и вы сможете закрыть терминал без его остановки.