it-swarm-ru.tech

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

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

redshift

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

339
Matthew

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

$ Nohup redshift &

или

$ redshift &
$ disown

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

342
Steven D

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

$ sleep 1000
^Z
[1]+  Stopped                 sleep 1000
$ bg
$ disown
$ exit
147
Stefan

Хороший ответ уже опубликован @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, которое будет поддерживать работу оболочки независимо от терминала.

50
gertvdijk

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

setsid process

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

31
hanoo

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

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

10
apolinsky

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

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

например: [email protected]:~$ (chromium-browser &)

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

8
daGo

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

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

  • Остановите их от уничтожения с помощью окна терминала

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

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

Я использую его в основном для 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
7
jozxyqk

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

command <&- & 

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

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

7
w00t

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

Nohup -p PID
4
tony

Возможно, похоже на ответ, предложенный apolinsky , я использую вариант на 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 "[email protected]; echo; echo '--------------------'; read -p 'ALL DONE (Enter to exit):'"
    echo "ERROR: 'screen' is not installed on this system" >&2
fi
exit 1

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

3
roaima

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

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