2010-12-15 2 views
4

У меня есть скрипт bash, который выполняет некоторую параллельную обработку в цикле. Я не хочу, чтобы параллельный процесс увеличивал процессор, поэтому я использую команду sleep. Вот упрощенная версия.Bash: сон в цикле while получает свой собственный pid

 
(while true;do sleep 99999;done)& 

Так я исполняю эту строку из Баш строки и получить что-то вроде: [1] 12345

Где [1] это количество рабочих мест и 12345 идентификатор процесса (PID) из цикла. Я делаю kill 12345 и получите:

 
[1]+ Terminated    (while true; do 
    sleep 99999; 
done) 

Похоже, что весь сценарий был прекращен. Тем не менее, я делаю ps aux|grep sleep и нахожу, что команда сна по-прежнему сильна, но со своим pid! Я могу убить sleep, и все кажется прекрасным. Однако, если бы я сначала должен был убить сон, цикл while запускает новый sleep pid. Это такой сюрприз для меня, поскольку сон не параллелен циклу while. Сам цикл является единственным путем выполнения.

Поэтому у меня есть два вопроса:

  1. Почему команда сна получить свой собственный идентификатор процесса?
  2. Как легко убить цикл while и sleep?

ответ

5
  1. сна получает свой собственный PID, потому что это процесс работает и просто ждать. Попробуйте which sleep, чтобы увидеть, где он находится.
  2. Вы можете использовать ps -uf, чтобы увидеть дерево процессов в вашей системе. Оттуда вы можете определить, что такое PPID (родительский PID) оболочки (тот, который запускает цикл) сна.
+1

Я вижу. Я думал, что `sleep` был встроенной командой в bash, а не каким-то процессом. Теперь это имеет больше смысла. – User1 2010-12-15 16:55:41

+0

Если вы используете bash, `type sleep` или` type -a sleep` предпочтительнее `which`. `which` является внешней командой; он не может обнаружить псевдонимы, функции или встроенные команды. Сравните вывод `which echo` и` type echo`. – 2016-08-17 19:00:09

1

Вы пытались сделать kill %1, где 1 - номер, который вы получаете после запуска команды в фоновом режиме?

Я сделал это прямо сейчас после запуска (while true;do sleep 99999;done)&, и он правильно его разорвал.

1

«п.с. --ppid» выбирает все процессы с указанным родительским PID, например:

$ (while true;do sleep 99999;done)& 
[1] 12345 

$ ppid=12345 ; kill -9 $ppid $(ps --ppid $ppid -o pid --no-heading) 
1

Вы можете убить группу процессов.

Чтобы найти группу процессов вашего процесса запуска:

ps --no-headers -o "%r" -p 15864 

Затем убить группу процессов с помощью:

kill -- -[PGID] 

Вы можете сделать все это в одной команде. Давайте попробуем это:

$ (while true;do sleep 99999;done)& 
[1] 16151 

$ kill -- -$(ps --no-headers -o "%r" -p 16151) 
[1]+ Terminated    (while true; do 
    sleep 99999; 
done) 
0

Чтобы убить петлю while и sleep с помощью $! вы также можете использовать обработчик trap сигнала внутри подоболочки.

(trap 'kill ${!}; exit' TERM; while true; do sleep 99999 & wait ${!}; done)& 
kill -TERM ${!} 
1
  1. Потому что "сон" это процесс, а не функцию сборки в или аналогичный

  2. Вы можете сделать следующее:

    (while true;do sleep 99999;done)& 
    whilepid=$! 
    kill -- -$whilepid 
    

приведенный выше код убивает группу процессов, потому что PID указан как отрицательное число (например, -123 вместо 123). Кроме того, он использует переменную $!, в которой хранится PID самого последнего выполненного процесса.

Примечание: При выполнении любого процесса в фоновом режиме в интерактивном режиме (т. Е. С помощью командной строки) создается новая группа процессов, что происходит с вами. Таким образом, относительно легко «убить всех», потому что вам просто нужно убить всю группу процессов. Однако, когда то же самое делается в скрипте, он не создает никакой новой группы, потому что все новые процессы относятся к PID скрипта, даже если они выполняются в фоновом режиме (по умолчанию управление заданиями отключено). Чтобы включить управление заданиями в сценарии, вам просто нужно поставить следующее в начале скрипта:

#!/bin/bash 

set -m 
Смежные вопросы