Спи в цикле время получает свой пид - PullRequest
4 голосов
/ 15 декабря 2010

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

(while true;do sleep 99999;done)&

Итак, я выполняю приведенную выше строку из приглашения bash и получаю что-то вроде: [1] 12345

Где [1] - номер задания, а 12345 - идентификатор процесса (pid) цикла while. Я делаю kill 12345 и получаю:

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

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

Итак, у меня два вопроса:

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

Ответы [ 6 ]

5 голосов
/ 15 декабря 2010
  1. Sleep получает свой собственный PID, потому что это процесс, запущенный и просто ожидающий. Попробуйте which sleep, чтобы увидеть, где это.
  2. Вы можете использовать ps -uf, чтобы увидеть дерево процессов в вашей системе. Оттуда вы можете определить, что такое PPID (родительский PID) оболочки (тот, который выполняет цикл) сна.
1 голос
/ 17 августа 2016
  1. Поскольку "сон" - это процесс, а не встроенная функция или аналогичная

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

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

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

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

#!/bin/bash

set -m
1 голос
/ 15 декабря 2010

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

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

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 )
1 голос
/ 15 декабря 2010

"ps --ppid" выбирает все процессы с указанным родительским pid, например:

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

$ ppid=12345 ; kill -9 $ppid $(ps --ppid $ppid -o pid --no-heading)
1 голос
/ 15 декабря 2010

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

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

0 голосов
/ 11 марта 2013

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

(trap 'kill ${!}; exit' TERM; while true; do sleep 99999 & wait ${!}; done)&
kill -TERM ${!}
...