Как приостановить и вывести фоновый процесс на передний план

167

У меня есть процесс, первоначально запущенный на переднем плане. Я приостановил на Ctrl+ Z, а затем возобновил его работу в фоновом режиме bg <jobid>.

Интересно, как приостановить процесс, работающий в фоновом режиме?

Как вывести фоновый процесс на передний план?

Редактировать:

Процесс выводит на stderr, так как мне выполнить команду, fg <jobid>пока процесс выводит на терминал?

Тим
источник
1
Вы все еще можете вводить команды в терминале, который издает ошибки. Текст, израсходованный на STDERR, не считается вводом, а только те ключи, которые вы отправляете. На экране это выглядит странно, но работает.
Калеб
@Caleb: Даже когда процесс выводит на стандартный вывод, я все еще могу напечатать, fg <jobid>чтобы сделать его приоритетным?
Тим
@ Тим: Да, вы можете.
Калеб

Ответы:

216

Как сказал Тим, наберите, fgчтобы вернуть последний процесс на передний план.

Если у вас есть несколько процессов, работающих в фоновом режиме, сделайте это:

$ jobs
[1]   Stopped                 vim
[2]-  Stopped                 bash
[3]+  Stopped                 vim 23

fg %3вернуть vim 23процесс на первый план.

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

kill -STOP %job_id

Сигнал SIGSTOP останавливает (приостанавливает) процесс по существу так же, как это делает Ctrl+ Z.

Пример: kill -STOP %3.

источники: как посылать сигналы процессам в Linux и Unix и как управлять фоновыми и приоритетными заданиями .

fromnaboo
источник
23
сигнал 19 SIGCONTдля меня; Я все равно использую kill -STOPи kill -CONTпредпочитаю запоминать числа, но вы можете проверить, kill -lчтобы напомнить себе о числовых значениях
Бесполезно
Процесс выводит на stderr, так как мне выполнить команду jobи fg <jobid>пока процесс выводится на терминал?
Тим
1
@Tim Просто введите команду, как обычно. Пока задание выполнено на заднем плане, оно не читает то, что вы печатаете - ваша оболочка. То, что вы печатаете, может показаться вам разбитым, но оболочка прекрасно это поймет.
AlexWebr
@AlexWebr: Спасибо, это работает! (1) Фоновое задание не принимает ввод и вывод, включая "Ctrl + Z" и т. Д., Верно? (2) Может ли задание, работающее в фоновом режиме, быть приостановлено напрямую? Если да, то как? Если нет, нужно ли сначала изменить его, чтобы он работал на переднем плане, прежде чем его можно будет приостановить?
Тим
2
Может ли задание, работающее в фоновом режиме, быть приостановлено напрямую? Да kill -STOP %job_id, как объяснено
Бесполезно
31

Это должно относиться к любой оболочке с контролем заданий, которую (по большей части) вы можете принять как должное, если не имеете дело с действительно древней оболочкой. Он соответствует стандарту POSIX , поэтому даже dashподдерживает управление заданиями (при запуске в интерактивном режиме или с помощью -m).

интерактивный

  • Ctrl+ zприостановит текущую программу
  • bgсоздаст фон для самой последней приостановленной программы
    (используйте bg %2номер задания, который вы можете проверить jobs)
  • fg выдвинет на первый план самую последнюю приостановленную программу

В zsh, вы можете написать привязку ключа для неявного запуска fgиз приглашения через другой Ctrl+ z:

_zsh_cli_fg() { fg; }
zle -N _zsh_cli_fg
bindkey '^Z' _zsh_cli_fg

Вероятно, есть и умный способ неявного запуска bgпри приостановке, но он кажется неразумным; по крайней мере для меня, большинство моих Ctrl+ zиспользований, потому что Ctrl+ cне в состоянии вспыхнуть; Я хочу следовать этому, например, kill %1вместо bg, и я, конечно же, не хочу по умолчанию убивать! (Эта логика также распространяется на то, почему я больше не использую эту привязку клавиш: если я нажимаю Ctrl+, zчтобы остановить процесс, последнее, что я хочу, это возобновить!)

Неинтерактивный

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

Вы по-прежнему можете работать с другим процессом, узнав его идентификатор процесса (PID). Вы можете получить PID с помощью pgrep …, или ps aux |grep …(или из той же оболочки jobs -l, или $!), и затем вы можете запустить:

kill -STOP $PID  # suspend
kill -CONT $PID  # continue (resume)

Если вы не знаете идентификатор процесса и не беспокоитесь о приостановке других экземпляров процесса по имени, вы можете передать сигналы одному из них:

killall -STOP program_name
pkill -STOP program_name
pkill -f -STOP program_name_or_args

CONTСигнал к программе останавливали Ctrl+ z(а не bg«г) возобновит прогресс (на переднем плане), то же самое , как если бы вы были fgего.

Re: Стандартная ошибка

Правка к этому вопросу спрашивает о стандартной ошибке:

Процесс выводит на stderr, так как мне выполнить команду, fg <jobid>пока процесс выводит на терминал?

Если в рассматриваемой работе нет компонентов, которые являются фоновыми (или вся работа является фоновой, возможно, через kill -CONT), вы фактически не должны видеть выходные данные, пока они приостановлены.

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

Если вам нужно найти дескриптор задания, используйте другой терминал для отправки ему STOPсигнала с помощью неинтерактивных методов, описанных выше. Это должно освободить ваш дисплей (возможно, ударить Enterнесколько раз или запустить clearили Ctrl+ L), чтобы вы могли затем запустить, jobsчтобы найти дескриптор задания, а затем запустить, fg %Nгде Nэто число.

Адам Кац
источник
Единственная проблема с приостановкой и возобновлением процессов состоит в том, что если вы установили какие-либо подключения к какой-либо другой программе (например, к RabbitMQ), соединение будет потеряно при возобновлении работы.
Nav
@Nav - Это потому, что ты не управлял им без головы. В bash и zsh я считаю, что вам просто нужно отказаться от фонового процесса. Я предпочитаю запускать такие задачи с nohup или терминальным мультиплексором, таким как screen или tmux . Вы не можете выбрать процесс nohup (точно так же, как вы не можете возобновить фоновый процесс из отдельного соединения), но вы можете подключиться к мультиплексору.
Адам Кац
Это был фоновый процесс. Я закрыл терминал, а затем вошел на сервер с другого терминала.
Nav
Да, вы не можете возобновить процесс из другой оболочки, если он не был запущен с учетом этого. Я рекомендую screen или tmux для этого.
Адам Кац
Я считаю, что если вы отправите CONTсигнал процессу (заданию / конвейеру), остановленному с помощью Ctrl + Z, он возобновится в фоновом режиме, даже если вы этого не сделали bg.
G-Man
10

Типа, fgчтобы вывести его на передний план.

Тим
источник
Спасибо! Процесс выводит на stderr, так как мне выполнить команду, fg <jobid>пока процесс выводит на терминал?
Тим
1
  1. список заданий с помощью jobsкоманды
  2. Вывести вашу целевую работу на первый план с fg; например: fg %4
  3. Хит, CTRL Zчтобы приостановить
  4. Чтобы запустить его в фоновом режиме, используйте bg; например:bg %4
kmiklas
источник
0

Завершение процесса может быть сделано несколькими различными способами. Часто из консольной команды отправка Ctrlcнажатия клавиши (символ прерывания по умолчанию) приводит к завершению команды. Это работает, когда процесс работает в режиме переднего плана.

Если процесс выполняется в фоновом режиме, то сначала вам нужно будет получить его Job ID с помощью psкоманды, а затем вы можете использовать команду kill, чтобы завершить процесс следующим образом:

$ps -f
UID      PID  PPID C STIME    TTY   TIME CMD
amrood   6738 3662 0 10:23:03 pts/6 0:00 first_one
amrood   6739 3662 0 10:22:54 pts/6 0:00 second_one
amrood   3662 3657 0 08:10:53 pts/6 0:00 -ksh
amrood   6892 3662 4 10:51:50 pts/6 0:00 ps -f
$kill 6738
Terminated

Здесь killкоманда завершит first_oneпроцесс. Если процесс игнорирует обычную killкоманду, вы можете использовать следующий kill -9за ним идентификатор процесса:

$kill -9 6738
Terminated
Лакшми
источник
1
Хотя это правда, это не ответ на вопрос ...
Джейсонвриан