Как я могу запустить команду, которая выживет после закрытия терминала?

313

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

redshift

Я не могу закрыть терминал, иначе он убьет процесс. Могу ли я выполнить команду таким образом, чтобы я мог закрыть терминал, не прерывая процесс?

Мэтью
источник
4
Не установка по умолчанию на всех дистрибутивах, но экран - ваш друг: en.wikipedia.org/wiki/GNU_Screen
Зейн С. Халсолл
Для тех, кто сталкивается с той же проблемой: помните, что даже если вы печатаете, yourExecutable &и выходы продолжают появляться на экране и Ctrl+C, кажется, ничего не останавливает, просто печатайте вслепую disown;и нажимайте, Enterдаже если экран прокручивается с выходами, и вы не можете видеть, что ты печатаешь Процесс будет остановлен, и вы сможете закрыть терминал без его остановки.
Nav
Вы можете использовать экранный мультиплексор такой tmux . Он доступен через apt-get на машинах с Ubuntu
Химаншу,

Ответы:

311

Один из следующих 2 должен работать:

$ nohup redshift &

или же

$ redshift &
$ disown

Ниже приведено немного больше информации о том, как это работает:

Стивен Д
источник
5
Второй ( redshift & disown) работал для меня на Ubuntu 10.10. Кажется, все работает хорошо, помещая все это в одну строку. Есть ли причина, по которой я не должен этого делать?
Мэтью
4
@ Matthew Первое тоже должно работать нормально, оно просто не фоновое, как второе (вы, возможно, хотите, nohup redshift &чтобы оно работало в фоновом режиме). И помещать второе на одной строке - это хорошо, хотя обычно вы отделяете ;( redshift &; disown)
Майкл Мрозек
10
@Michael: Оба ;и &являются разделителями команд и имеют одинаковый приоритет. Единственная разница - синхронное и асинхронное выполнение (соответственно). Нет необходимости использовать &;в предпочтении просто &(это работает, но это немного избыточно).
Крис Джонсен
4
хороший ответ, можно добавить, что было бы неплохо перенаправить stdout и stderr, чтобы терминал не был спам с выходом отладки
Ким
12
Кроме того, redshift &!немедленно откажется от красного смещения.
143

Если ваша программа уже запущена, вы можете приостановить ее Ctrl-Z, переместить в фоновый режим, bgа затем disown, например, так:

$ sleep 1000
^Z
[1]+  Stopped                 sleep 1000
$ bg
$ disown
$ exit
Стефан
источник
3
после того, как отречься, как я могу снова прочитать стандартный вывод запущенного процесса?
Necktwi
2
@neckTwi, serverfault.com/questions/55880/…
Стефан
1
Это не работает для меня по какой - то причине (CentOS)
Ian
Как убить процесс после этой процедуры?
Palak Darji
2
@necktwi disownне отключает стандартный вывод или стандартный вывод. Тем nohupне менее , как и >/dev/null(отключить стандартный выход) 2>/dev/null(отключить стандартную ошибку). Это ( disown) отключает контроль работы.
Ctrl-Alt-Delor
45

Хороший ответ уже опубликован @StevenD, но я думаю, что это могло бы прояснить это немного больше.

Причиной того, что процесс завершается при завершении терминала, является то, что запускаемый вами процесс является дочерним процессом терминала. Как только вы закроете терминал, это также уничтожит эти дочерние процессы. Вы можете увидеть дерево процессов pstree, например, при запуске kate &в Konsole:

init-+
     ├─konsole─┬─bash─┬─kate───2*[{kate}]
     │         │      └─pstree
     │         └─2*[{konsole}]

Чтобы kateотделить процесс от konsoleзавершения konsole, используйте nohupкоманду, например:

nohup kate &

После закрытия konsole, pstreeбудет выглядеть следующим образом :

init-+
     |-kate---2*[{kate}]

и kateвыживет. :)

Альтернативой является использование screen/ tmux/ byobu, которая будет поддерживать работу оболочки независимо от терминала.

gertvdijk
источник
У меня были проблемы с методами отречения. Это в настоящее время работает для меня, так что голосование. Мне также нравится это, потому что я могу отследить -f nohup.out, чтобы увидеть, что происходит, но не беспокоиться о сбое моего сеанса
Ян
27

Вы можете запустить процесс, как это в терминале

setsid process

Это запустит программу в новом сеансе. Как объяснено http://hanoo.org/index.php?article=run-program-in-new-session-linux

hanoo
источник
1
В чем вы видите преимущества setsid перед nohup?
Брюс
1
1) Он не печатает раздражающее сообщение о nohup.out. 2) Он не остается в списке заданий вашей оболочки, поэтому он не загромождает вывод jobs.
Микель
Это единственное решение, которое работает со сценарием, который запускается в lxterminal, запускает pcmanfm и завершает работу (с setsid терминал может закрыться, пока pcmanfm продолжает работать). Спасибо вам большое!
desgua
9

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

Вы можете начать с этого . Экран может быть установлен практически на все производные Linux и Unix. Нажатие + и (нижний регистр) начнется второй сеанс. Это позволит вам переключаться между начальным сеансом, нажимая +, и / или более новый сеанс, нажимая + и . Вы можете иметь до десяти сеансов в одном терминале. Я использовал, чтобы начать сеанс на работе, пойти домой, SSH в мою рабочую машину, а затем вызвать . Это соединит вас с этим удаленным сеансом.screen -S session_nameCtrlACCtrlA0CtrlA1screen -d -R session_name

apolinsky
источник
screen -d -m commandзапустит его на уже оторванном экране: ~# screen -d -m top ~# screen -ls There is a screen on: 10803..Server-station (Detached) 1 Socket in /root/.screen. ~# screen -x .... и вы внутри.
Доктор Александр
7

Единственный способ сделать все это - закрыть команду stdin и выполнить команду background:

command <&- & 

Тогда он не выйдет, когда вы выйдете из оболочки. Перенаправление stdout - хорошая дополнительная опция.

Недостатком является то, что вы не можете сделать это после факта.

w00t
источник
Я пробовал в Ubuntu. Убивающий терминал также закрыл запущенный процесс. Любая идея о том, почему это может иметь место?
Ашок Кои
7

У меня есть скрипт для:

  • Запускать произвольные команды в фоновом режиме

  • Остановите их от убийства с окном терминала

  • Подавить их вывод

  • Обрабатывает статус выхода

Я использую это главным образом для gedit, evinceи inkscapeт.д., что у всех есть много раздражающего вывода терминала. Если команда завершается раньше TIMEOUT, состояние выхода nohup возвращается вместо нуля.

#!/bin/bash

TIMEOUT=0.1

#use nohup to run the command, suppressing its output and allowing the terminal to be closed
#also send nohup's output to /dev/null, supressing nohup.out
#run nohup in the background so this script doesn't block
nohup "${@}" >/dev/null 2>&1 &
NOHUP_PID=$!

#kill this script after a short time, exiting with success status - command is still running
#this is needed as there is no timeout argument for `wait` below
MY_PID=$$
trap "exit 0" SIGINT SIGTERM
sleep $TIMEOUT && kill $MY_PID 2>/dev/null & #ignore "No such process" error if this exits normally

#if the command finishes before the above timeout, everything may be just fine or there could have been an error
wait $NOHUP_PID
NOHUP_STATUS=$?
#print an error if there was any. most commonly, there was a typo in the command
[ $NOHUP_STATUS != 0 ] && echo "Error ${@}"
#return the exit status of nohup, whatever it was
exit $NOHUP_STATUS

Примеры...

>>> run true && echo success || echo fail
success
>>> run false && echo success || echo fail
Error false
fail
>>> run sleep 1000 && echo success || echo fail
success
>>> run notfound && echo success || echo fail
Error notfound
fail
jozxyqk
источник
7

Я предпочитаю:

(Имя приложения &)

например: linux@linux-desktop:~$ (chromium-browser &)

Обязательно используйте круглые скобки при вводе команды!

даго
источник
1
Закрытие терминала убьет процесс , которого хочет избежать именно тот ОП (и я, таким образом, пришедший сюда)
gromit190
1
Вероятно, у вас есть подсказка, которую я использовал в своем ответе без круглых скобок, если это так, закрытие терминала убьет процесс, иначе это НЕ произойдет. Я уже отредактировал решение выше, чтобы прояснить его.
ДаГо
работа для меня, tnx
noadev
Мне интересно, почему это не получило больше голосов. nohupпредотвращает вывод tty, и я на самом деле просто хотел перенаправить вывод в файл, и это помешало, так что это лучшее решение для меня.
Redanimalwar
4

Вы можете настроить процесс (PID) так, чтобы он не получал сигнал HUP после выхода из системы и закрытия сеанса терминала. Используйте следующую команду:

nohup -p PID
Тони
источник
3

Возможно, похоже на ответ, предложенный Аполинским , я использую вариант на screen. Ванильная команда такая

screen bash -c 'long_running_command_here; echo; read -p "ALL DONE:"'

Сеанс можно отключить Ctrl ACtrl Dи снова подключить в простом случае с screen -r. У меня есть это завернутый в сценарий под названием, sessionкоторый живет в моем PATHготовы для удобного доступа:

#!/bin/bash
#
if screen -ls | awk '$1 ~ /^[1-9][0-9]*\.'"$1"'/' >/dev/null
then
    echo "WARNING: session is already running (reattach with 'screen -r $1')" >&2
else
    exec screen -S "$1" bash -c "$@; echo; echo '--------------------'; read -p 'ALL DONE (Enter to exit):'"
    echo "ERROR: 'screen' is not installed on this system" >&2
fi
exit 1

Это работает только тогда, когда вы заранее знаете, что хотите отключить программу. Он не предусматривает отключение уже запущенной программы.

roaima
источник
2

Как и в других ответах, опубликованных ранее, можно использовать запущенный процесс для ретроспективного использования «экрана» благодаря reptyr, а затем закрыть терминал. Шаги описаны в этом посте . Шаги, которые необходимо предпринять:

  1. Приостановить процесс
  2. Возобновить процесс в фоновом режиме
  3. Отказаться от процесса
  4. Запустите сеанс экрана
  5. Найти PID процесса
  6. Используйте reptyr, чтобы взять на себя процесс
user308879
источник