2009-03-23 11:59:25 +0000 2009-03-23 11:59:25 +0000
311
311

Как полностью отделить процесс от терминала?

Я использую Tilda (выпадающий терминал) на Ubuntu в качестве “центра команд” - в основном так, как другие могут использовать GNOME Do, Quicksilver или Launchy.

Однако, я борюсь с тем, как полностью отделить процесс (например, Firefox) от терминала, с которого он был запущен - то есть. предотвратить, чтобы такой (не)дочерний процесс

  • завершался при закрытии исходного терминала
  • “загрязняет” исходный терминал через STDOUT/STDERR

Например, чтобы запустить Vim в “правильном” окне терминала, я попробовал простой скрипт вроде:

exec gnome-terminal -e "vim $@" &> /dev/null &

Тем не менее, это все равно приводит к загрязнению (также, передача имени файла, похоже, не срабатывает).

Ответы (18)

355
355
355
2009-03-23 13:18:35 +0000

Прежде всего, как только вы запустили процесс, вы можете сделать его фоновым, сначала остановив его (нажмите Ctrl-Z), а затем набрав bg, чтобы он возобновился в фоновом режиме. Теперь это “задание”, и его stdout/stderr/stdin все еще подключены к вашему терминалу.

Можно сразу же начать процесс в фоновом режиме, добавив к его концу “&”:

firefox &

Чтобы запустить его в фоновом режиме без звука, используйте следующее:

firefox </dev/null &>/dev/null &

Дополнительная информация:

nohup это программа, которую вы можете использовать ** для запуска вашего приложения с ** таким образом, что его stdout/stderr может быть отправлен в файл вместо этого, и так, что закрытие родительского скрипта не будет SIGHUP дочернего. Тем не менее, вы должны были иметь предвидение, чтобы использовать его до того, как вы запустили приложение. Из-за того, как работает nohup, вы не можете просто приложить его к запущенному процессу.

disown - это bash builtin, который удаляет задание оболочки из списка заданий оболочки. По сути, это означает, что вы больше не можете использовать fg, bg в ней, но, что более важно, когда вы закрываете оболочку, она больше не будет зависать или посылать SIGHUP этому дочернему процессу. В отличие от nohup, disown используется после запуска процесса и в фоновом режиме.

Что вы не можете сделать, так это изменить stdout/stderr/stdin процесса после его запуска. По крайней мере, не из оболочки. Если вы запускаете процесс и говорите ему, что его stdout - ваш терминал (что вы и делаете по умолчанию), то этот процесс настроен на вывод на ваш терминал. Ваша оболочка не имеет никакого отношения к настройке FD процессов, это чисто то, чем управляет сам процесс. Сам процесс может решить, закрыть его stdout/stderr/stdin или нет, но вы не можете использовать оболочку, чтобы заставить его это сделать.

Для управления выводом фоновых процессов, у вас есть множество опций из скриптов, “nohup”, вероятно, приходит на ум первым. Но для интерактивных процессов, которые вы начинаете, но забыли заставить замолчать (firefox < /dev/null &>/dev/null &), на самом деле, вы не можете сделать много.

Я рекомендую вам получить GNU screen. С помощью экрана вы можете просто закрыть вашу выполняющуюся оболочку, когда вывод процесса становится беспокойным, и открыть новую (^Ac).

  • *

О, и, кстати, не используйте “$@” там, где вы его используете.

$@ означает, $1, $2, $3 …, что превратит вашу команду в:

gnome-terminal -e "vim $1" "$2" "$3" ...

Возможно, это не то, что вы хотите, потому что -e takes only one argument. Используйте $1, чтобы показать, что ваш сценарий может обрабатывать только один аргумент.

Очень сложно заставить несколько аргументов работать правильно в сценарии, который вы дали (с gnome-terminal -e), потому что -e принимает только один аргумент, который является командной строкой оболочки. Вам придется кодировать свои аргументы в один. Лучший и самый надежный, но довольно неуклюжий способ:

gnome-terminal -e "vim $(printf "%q " "$@")"
```.
202
202
202
2009-03-23 12:17:32 +0000
nohup cmd &

nohup полностью отсоединяет процесс (даемонизирует его).

62
62
62
2009-03-23 12:05:02 +0000

Если вы используете bash, попробуйте disown [jobspec]; смотрите bash(1) .

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

41
41
41
2014-01-22 17:08:16 +0000

Читая эти ответы, у меня сложилось первоначальное впечатление, что выпуска nohup <command> & будет достаточно. Запустив zsh в гном-терминале, я обнаружил, что nohup <command> & не помешало моей оболочке убить детские процессы на выходе. Хотя nohup полезен, особенно с неинтерактивными оболочками, он гарантирует такое поведение только в том случае, если дочерний процесс не сбросит свой обработчик для сигнала SIGHUP.

В моем случае, nohup должен был предотвратить попадание зависающих сигналов в приложение, но дочернее приложение (в данном случае VMWare Player) сбросило свой обработчик SIGHUP. В результате, при выходе эмулятора терминала, он все равно мог убить ваши подпроцессы. Это можно решить, насколько мне известно, только убедившись, что процесс удален из таблицы заданий оболочки. Если nohup будет переопределена оболочкой, как это иногда бывает, этого может быть достаточно, однако, в случае, если это не…

  • *

disown - оболочка, собранная в bash, zsh, и ksh93,

<command> &
disown

или

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

После отключения, процесс все еще является дочерним от вашего терминального эмулятора (играйте с pstree, если вы хотите посмотреть это в действии), но после выхода терминального эмулятора, вы должны увидеть его прикрепленным к init процессу. Другими словами, все как должно быть, и как вы предположительно хотите, чтобы это было.

Что делать, если ваш оболочка не поддерживает disown? Я бы решительно поддержал переход на тот, который поддерживает, но при отсутствии этого варианта у вас есть несколько вариантов.

  1. screen и tmux могут решить эту проблему, но это гораздо более тяжелые решения, и мне не нравится, когда их приходится запускать для выполнения такой простой задачи. Они гораздо больше подходят для ситуаций, в которых вы хотите обслуживать tty, обычно на удаленной машине.
  2. Для многих пользователей может быть желательно посмотреть, поддерживает ли ваша оболочка такие возможности, как zsh’s setopt nohup. Это можно использовать для указания, что SIGHUP не должна отправляться в задания в таблице заданий при выходе оболочки командной строки. Вы можете либо применить ее непосредственно перед выходом из оболочки, либо добавить ее в конфигурацию оболочки, такую как ~/.zshrc, если вы всегда хотите, чтобы она была включена.
  3. Найдите способ редактировать таблицу заданий. Я не смог найти способа сделать это в tcsh или csh, что несколько беспокоит.
  4. Напишите небольшую программу на C, чтобы вилка и exec(). Это очень плохое решение, но исходник должен состоять только из пары дюжин строк. Затем вы можете передавать команды в качестве аргументов командной строки в программу на Си, и таким образом избежать записи в таблице заданий, относящейся к конкретному процессу.
30
30
30
2015-08-25 14:39:31 +0000
  1. nohup $COMMAND &
  2. $COMMAND & disown
  3. setsid command

Я использую номер 2 очень долго, но номер 3 работает также хорошо. Кроме того, disown имеет nohup флаг -h, может отключить все процессы с -a, и может отключить все запущенные процессы с -ar.

Звукоподавление осуществляется $COMMAND &>/dev/null.

Надеюсь, это поможет!

9
9
9
2017-05-05 11:55:05 +0000

Самый простой и единственный правильный ответ для bash:

command & disown

Вы не должны отсоединять процесс от терминала, а от оболочки.

9
9
9
2009-03-23 14:55:15 +0000

В tcsh (и, возможно, в других оболочках), вы можете использовать скобки для отсоединения процесса.

Сравните это:

> jobs # shows nothing
> firefox &
> jobs
[1] + Running firefox

Сравните это:

> jobs # shows nothing
> (firefox &)
> jobs # still shows nothing
>

Это удаляет firefox из списка заданий, но он все еще привязан к терминалу; если вы вошли на этот узел через ‘ssh’, попытка выйти из системы все равно повесит процесс ssh.

7
7
7
2012-08-07 05:18:25 +0000

Чтобы расчленить tty оболочку, выполните команду через подоболочку, например,

(команда)

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

Проверка -

(sleep 100) & exit

Открыть другой терминал

ps aux | grep sleep

Процесс все еще жив.

5
5
5
2013-05-22 23:00:56 +0000

Фоновое изображение и выдвижение на передний план - вероятно, одна из первых вещей, которую должен знать каждый системный администратор Unix.

Вот как это делается с bash:

./script.sh
# suspend process
{ctrl-Z}
# background process
bg
# list all backgrounded jobs
jobs
# bring it back to foreground
fg
4
4
4
2009-03-23 12:03:50 +0000

Вы можете запустить свою команду с помощью команды nohup, это отсоединит ваш процесс и перенаправит результаты в заданный файл… но я не уверен, что это именно то, что вам нужно…

2
2
2
2018-02-05 16:14:17 +0000

Просто добавьте это в bashrc/zshrc:

detach() {
  "$@" 1>/dev/null 2>/dev/null &; disown
}

Тогда вы можете запустить команды dis dis disowned типа:

detach gedit ~/.zshrc
2
2
2
2009-03-23 12:10:49 +0000

Попробуйте демон – должен быть доступен в дружественном менеджере пакетов и всесторонне позаботиться о каждом способе отмежеваться от терминала.

1
1
1
2015-06-14 17:53:47 +0000

В моем .bashrc, у меня есть эти функции именно для этой цели:

function run_disowned() {
    "$@" & disown
}

function dos() {
    # run_disowned and silenced

    run_disowned "$@" 1>/dev/null 2>/dev/null
}

Prefix команда с dos для запуска ее отдельно от терминала.

Функция написана для работы с bash и zsh.

0
0
0
2010-06-19 16:46:44 +0000

На Mac OS X я обнаружил, что мне нужно использовать как nohup, так и disown, чтобы убедиться, что дочерний процесс не будет сорван с помощью терминала.

0
0
0
2014-09-21 04:42:43 +0000

Для этого я использую следующий сценарий. Он останавливает процесс печати на терминале, отсоединяется с помощью nohup и выходит со статусом возврата, если команда заканчивается в TIMEOUT.

#!/bin/bash

TIMEOUT=0.1

CMD=( "$@" )
#Could have some shortcuts here, e.g. replace "somefile.c" with "gedit somefile.c"

#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
#print the command for debugging and to see bash variable expansion
printf "%q " "${CMD[@]}"
echo
nohup "${CMD[@]}" >/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: $CMD"
#return the exit status of nohup, whatever it was
exit $NOHUP_STATUS

Пример использования:

>>> run false
false
Error: false
>>> echo $?
1
>>> run true
true
>>> run sleep 10
sleep 10
>>>
0
0
0
2019-06-21 07:14:46 +0000

sudo apt install ucommon-utils

pdetach command

Там вы идете :)

-1
-1
-1
2017-02-15 04:16:48 +0000

Многие ответы были предложены с использованием nohup. Я предпочитаю использовать pm2 . Использование pm2 поверх nohup имеет много преимуществ, таких как сохранение работоспособности приложения, поддержка лог-файлов для приложения и многое другое. Для более подробной информации смотрите это .

Для установки pm2 необходимо скачать npm. Для системы на базе Debian

sudo apt-get install npm

и для Redhat

Или вы можете следовать эта инструкция . После установки npm используйте ее для установки pm2

sudo yum install npm

После ее завершения вы можете запустить ваше приложение с помощью

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>
```.
-1
-1
-1
2017-04-05 13:47:37 +0000

Если ваша цель - просто запустить приложение из командной строки, не удерживая при этом окно терминала, то вы можете попробовать запустить приложение после запуска терминала с помощью alt-F2.

Похожие вопросы

6
10
11
5
8