- Вопрос или проблема
- Метод #1 – ps
- Пример
- Метод #2 – pgrep
- Пример
- Метод #3 – pkill
- Пример
- Метод #4 – jobs
- Пример
- Метод #5 – fg
- Пример
- Примечание
- например
- Ответ или решение
- Метод 1: Использование команды ps
- Метод 2: Использование команды pgrep
- Метод 3: Использование команды pkill
- Метод 4: Использование команды jobs
- Метод 5: Использование команды fg
- Уточнения
- Заключение
Вопрос или проблема
Я запустил wget на удаленной машине в фоновом режиме, используя &
. Вдруг он перестал скачивать. Я хочу завершить этот процесс и затем снова запустить команду. Как я могу его завершить?
Я не закрыл окно оболочки. Но, как вы знаете, он не останавливается с помощью Ctrl+C и Ctrl+Z.
Существует множество способов сделать это.
Метод #1 – ps
Вы можете использовать команду ps
, чтобы найти идентификатор процесса для этого процесса, а затем использовать PID, чтобы убить процесс.
Пример
$ ps -eaf | grep [w]get
saml 1713 1709 0 Dec10 pts/0 00:00:00 wget ...
$ kill 1713
Метод #2 – pgrep
Вы также можете найти идентификатор процесса с помощью pgrep
.
Пример
$ pgrep wget
1234
$ kill 1234
Метод #3 – pkill
Если вы уверены, что это единственный запущенный вами wget
, вы можете использовать команду pkill
, чтобы убить задачу по имени.
Пример
$ pkill wget
Метод #4 – jobs
Если вы находитесь в той же оболочке, из которой запустили задание, которое теперь находится в фоновом режиме. Вы можете проверить, выполняется ли оно все еще, используя команду jobs
, а также убить его по номеру задания.
Пример
Моя фальшивая задача, sleep
.
$ sleep 100 &
[1] 4542
Найдите номер задания. ПРИМЕЧАНИЕ: число 4542 — это идентификатор процесса.
$ jobs
[1]+ Запущено sleep 100 &
$ kill %1
[1]+ Завершено sleep 100
Метод #5 – fg
Вы можете вернуть задание из фона в передний план, используя команду fg
.
Пример
Фальшивая задача, sleep
.
$ sleep 100 &
[1] 4650
Получите номер задания.
$ jobs
[1]+ Запущено sleep 100 &
Верните задачу #1 в передний план, а затем используйте Ctrl+C.
$ fg 1
sleep 100
^C
$
В bash вы можете использовать fg
, чтобы вернуть задание на передний план, а затем использовать Ctrl+C.
Или выведите список процессов в фоновом режиме с помощью jobs
, а затем выполните
kill %1
(где 1 заменяется номером, который дал вам jobs
)
Также вы можете использовать kill $!
, чтобы убить последнее задание, запущенное в фоновом режиме.
ИЗМЕНЕНИЕ: Оказавшись на переднем плане, вы можете Ctrl+C, или, как упоминает @Zelda, убить с помощью ‘%x’, где ‘x’ — это номер задания, что вызовет сигнал по умолчанию (скорее всего, SIGTERM в случае Linux).
Просто введите fg
, чтобы вернуть его на передний план, если это был последний процесс, который вы отправили в фон (с помощью ‘&’).
Если это не был последний, введите: jobs
и найдите ‘номер задания’, представленный в ‘[]’. Затем просто введите:
fg 2
..где ‘2’ — это номер задания, например:
foo@bar:~/junk/books$ jobs
[1]+ Запущено okular how_to_cook_a_turkey.pdf &
foo@bar:~/junk/books$ fg 1
okular how_to_cook_a_turkey.pdf <- это теперь на переднем плане.
Это старая проблема, и уже есть несколько хороших ответов, но я постараюсь представить свой немного другим способом.
На самом деле, фоновые процессы называются задачами, а управление заданиями очень хорошо объясняется на этих 3 коротких страницах: https://www.gnu.org/software/bash/manual/html_node/Job-Control.html
В основном, мы можем ссылаться на задачу с помощью jobspec, то есть символа %
, за которым следует либо другой символ (или последовательность в некоторых более сложных случаях), либо идентификатор задания. И это то же самое для kill
, fg
, bg
или disown
.
%+
(или просто%
, или%%
) будет ссылаться на последнюю отправленную в фон
задачу (текущую)%-
будет ссылаться на предыдущую%{jobid}
будет ссылаться на указанную задачу
Чтобы перечислить ваши фоновые задачи, вы используете команду jobs
.
Примечание
kill $!
имеет другое поведение, он убивает последний процесс, отправленный в фон в качестве задачи, а не последнюю созданную задачу.
например
Вы отправили 5 задач в фон.
Вы возвращаете задачу #2 на передний план (fg %2
, или просто %2
), затем отправляете ее обратно в фон (<Ctrl-Z>
, затем bg
).
Это последний процесс, отправленный в фон, но он остается задачей #2.
Таким образом, kill $!
завершит задачу #2 — последний (повторно)отправленный в фон процесс, тогда как kill %+
убьет задачу #5, последнюю созданную задачу (“текущая задача”):
$ jobs [1] Запущено sleep 1000 & [2] Запущено sleep 2000 & [3] Запущено sleep 3000 & [4]- Запущено sleep 4000 & [5]+ Запущено sleep 5000 & $ fg %2 sleep 2000 ^Z [2]+ Остановлено sleep 2000 $ bg [2]+ sleep 2000 & $ jobs [1] Запущено sleep 1000 & [2] Запущено sleep 2000 & [3] Запущено sleep 3000 & [4]- Запущено sleep 4000 & [5]+ Запущено sleep 5000 & $ kill %+ $ jobs [1] Запущено sleep 1000 & [2] Запущено sleep 2000 & [3] Запущено sleep 3000 & [4]- Запущено sleep 4000 & [5]+ Завершено sleep 5000 $ kill $! [2] Завершено sleep 2000 $ jobs [1] Запущено sleep 1000 & [3]- Запущено sleep 3000 & [4]+ Запущено sleep 4000 &
Одна вещь, которую я не вижу здесь, которую я нашел очень полезной, особенно при тестировании команд, это pidof
. Вы можете использовать pidof [команда]
, чтобы найти идентификатор процесса запущенного процесса. Мне это нравится, потому что это позволяет быстро найти идентификатор команды, которую я хочу, и это обычно что-то, что я только что вызвал.
Как только у вас есть pid, вы можете просто убить процесс. Это позволяет создавать простые скрипты для завершения процесса только в том случае, если он в данный момент выполняется.
в bash последний остановленный процесс (Ctrl-Z) вы убьете с помощью:
kill %%
kill -9 %%
или если хотите выбрать, используйте:
jobs
затем:
kill %N
например kill %2
Правильный способ – ввести jobs
, затем использовать номер задания, чтобы убить его. Чтобы использовать pid для завершения, вам нужно вернуть его на передний план, как отмечено в первом ответе.
Попробуйте это
~/Desktop$ sleep 1000 &
[1] 7056
~/Desktop$ jobs
[1]+ Запущено sleep 1000 &
/Desktop$ kill %1 #(%1 - это номер задания)
Если вы запустите jobs сразу после его завершения, вы должны увидеть это
Desktop$ jobs
[1]+ Завершено sleep 1000
Самый простой способ – использовать флаг -9
на команде kill
user@host:/path> jobs
[1]+ Запущено /usr/home/script1.sh $i &
user@host:/path> fg
/usr/home/script1.sh $i
^C
[1]+ Остановлено /usr/home/script1.sh $i
user@host:/path> kill -9 %1
[1]+ Остановлено /usr/home/script1.sh $i
user@host:/path>
[1]+ Убит /usr/home/script1.sh $i
user@host:/path>
user@host:/path> jobs
user@host:/path>
Обычный пример — это инструмент stress
. Допустим, вы выполнили следующее:
$ stress -c 4 -m 4
и закрыли окно терминала. Процесс продолжит использовать ваши ресурсы в фоновом режиме.
Вот что я делаю:
$ x=`pgrep stress` ; sudo kill -9 $x
pgrep
отображает PID подлежащего процесса и сохраняет его в переменной x
, которая затем используется командой kill -9
для завершения.
Перечислите все задачи, введя
jobs
Результат>>[1]+ Остановлено sudo nano ls.txt
Перенесите этот процесс на передний план и завершите
fg %1
затем нажмите ctrl+c
Я ленив и немного устал гуглить, какие инкантации ctrl
%
номер сигнала
fg
bg
jobs
disown
и бог знает что еще использовать для чего-то, что должно быть тривиально.
Я рекомендую посмотреть альтернативы командной строки для обычно используемых команд в целом как способ повысить производительность, потому что для всего, что связано с запущенными процессами, я не могу достаточно рекомендовать btop
. Я не скажу вам, как его использовать, потому что его на самом деле сделали для использования людьми.
Я почти уверен, что его можно найти через менеджер пакетов на ваш выбор, попробуйте, вы не пожалеете, также есть очень хороший procs
.
Чтобы убить задание номер 1, вам нужно просто выполнить kill -9 `jobs -p 1`
.
Чтобы убить все задания, не указывайте конкретный номер задания kill -9 `jobs -p`
.
Конечно, чтобы перечислить задания, вы можете запустить jobs
.
Ответ или решение
Чтобы завершить фоновый процесс, такой как wget
, который вы запустили в фоновом режиме с помощью &
, вы можете воспользоваться несколькими методами. Предполагается, что вы находитесь в той же оболочке, где был запущен процесс, и окно терминала не было закрыто. Вот несколько способов, как вы можете это сделать:
Метод 1: Использование команды ps
Вы можете использовать команду ps
для поиска идентификатора процесса (PID) и последующего завершения процесса:
ps -eaf | grep [w]get
После этого найдите PID и выполните:
kill <PID>
Метод 2: Использование команды pgrep
Команда pgrep
позволяет вам найти PID прямо по имени процесса:
pgrep wget
Затем завершите его:
kill <PID>
Метод 3: Использование команды pkill
Если вы уверены, что это единственный запущенный процесс wget
, вы можете использовать pkill
:
pkill wget
Метод 4: Использование команды jobs
Если вы находитесь в той же оболочке, где запустили фоновую задачу, используйте jobs
для проверки статуса:
jobs
После этого, чтобы завершить процесс, используйте команду kill
с указанием номера задания:
kill %<номер_задания>
Метод 5: Использование команды fg
Вы также можете вернуть фоновый процесс в передний план, используя fg
, а затем завершить его с помощью комбинации клавиш Ctrl+C
:
fg %<номер_задания>
Уточнения
- Если вы хотите завершить последний фоновый процесс, вы можете использовать команду
kill $!
, что завершит последний запущенный фоновый процесс. - Учтите, что использование
kill
отправляет сигнал по умолчанию (обычноSIGTERM
, который мягко завершает процесс). Если процесс не реагирует, вы можете использовать более жесткий способ:
kill -9 <PID>
или
kill -9 %<номер_задания>
Заключение
Работа с фоновыми процессами и управление ими в GNU/Linux выполняется с помощью различных команд, которые позволяют пользователю гибко управлять запущенными задачами. Выберите подходящий способ в зависимости от вашей ситуации. Если у вас есть специфические требования, такие как длительная работа с загруженной system, рассмотрите возможность использования более продвинутых инструментов, например, htop
или btop
.