Завершить каждый фоновый процесс

У меня есть несколько Stopped фоновых процессов.

kill $(jobs -p) и kill `jobs -p` имеют эффекта

kill %1 , kill %2 и т. д. успешно завершают отдельные процессы

Как я могу убить каждый фоновый процесс с помощью одной команды?

Кроме того, почему первые две команды не работают для меня?

Я запускаю Linux Mint 15, 64 бит

Когда они бегут

Похоже, вы можете просто сделать это с помощью kill и вывода jobs -p .

пример

 $ sleep 1000 & [1] 21952 $ sleep 1000 & [2] 21956 $ sleep 1000 & [3] 21960 

Теперь у меня есть 3 поддельные задания.

 $ jobs [1] Running sleep 1000 & [2]- Running sleep 1000 & [3]+ Running sleep 1000 & 

Убейте их всех так:

 $ kill $(jobs -p) [1] Terminated sleep 1000 [2]- Terminated sleep 1000 [3]+ Terminated sleep 1000 

Подтверждая, что они ушли.

 $ jobs $ 

Когда они остановлены

Если у вас есть задание, которое остановлено, не выполняйте это вместо этого.

пример

 $ kill $(jobs -p) $ jobs [1]+ Stopped sleep 1000 [2]- Stopped sleep 1000 [3] Stopped sleep 1000 

ОК, чтобы не убить их, но это потому, что сигнал об ударе не может обрабатываться самим процессом, он остановлен. Поэтому скажите ОС, чтобы убить вместо этого. Для этого -9 .

 $ kill -9 $(jobs -p) [1]+ Killed sleep 1000 [2]- Killed sleep 1000 [3] Killed sleep 1000 

Так-то лучше.

 $ jobs $ 

Когда некоторые из них запущены, а некоторые остановлены

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

 $ kill $(jobs -p); sleep <time>; \ kill -18 $(jobs -p); sleep <time>; kill -9 $(jobs -p) 

Немного увеличивайте время, если вам нужно больше, чтобы процессы сначала остановились.

сигналы

Ни HUP (-1), ни SIGTERM (-15), чтобы убить, преуспеют. Но почему? Это потому, что эти сигналы более добры в том смысле, что они говорят, что приложение прекращает свое существование. Но поскольку приложение находится в состоянии остановки, оно не может обрабатывать эти сигналы. Таким образом, вы используете только SIGKILL (-9).

Вы можете увидеть все сигналы, которые kill с помощью kill -l .

 $ kill -l | column -t 1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP 6) SIGABRT 7) SIGBUS 8) SIGFPE 9) SIGKILL 10) SIGUSR1 11) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM 16) SIGSTKFLT 17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP 21) SIGTTIN 22) SIGTTOU 23) SIGURG 24) SIGXCPU 25) SIGXFSZ 26) SIGVTALRM 27) SIGPROF 28) SIGWINCH 29) SIGIO 30) SIGPWR 31) SIGSYS 34) SIGRTMIN 35) SIGRTMIN+1 36) SIGRTMIN+2 37) SIGRTMIN+3 38) SIGRTMIN+4 39) SIGRTMIN+5 40) SIGRTMIN+6 41) SIGRTMIN+7 42) SIGRTMIN+8 43) SIGRTMIN+9 44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13 48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12 53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9 56) SIGRTMAX-8 57) SIGRTMAX-7 58) SIGRTMAX-6 59) SIGRTMAX-5 60) SIGRTMAX-4 61) SIGRTMAX-3 62) SIGRTMAX-2 63) SIGRTMAX-1 64) SIGRTMAX 

Если вы хотите узнать больше о различных сигналах, я очень рекомендую взглянуть на страницу man 7 signal .

Вы можете попробовать это.

 for x in `jobs -p`; do kill -9 $x; done 

Однако, если вы хотите завершить процесс, вы можете выполнить команду как,

 for x in `jobs -p`; do kill -15 $x; done 

На странице Wiki команды Kill ,

Процесс может быть отправлен сигнал SIGTERM четырьмя способами (в этом случае идентификатор процесса равен «1234»):

 kill 1234 kill -s TERM 1234 kill -TERM 1234 kill -15 1234 

Процесс может быть отправлен сигналом SIGKILL тремя способами:

 kill -s KILL 1234 kill -KILL 1234 kill -9 1234 

Как объясняется в этом ответе, это разница между прекращением и убийством .

Сигнал завершения, SIGTERM , является сигналом, который может быть перехвачен в программе. Часто процессы, которые предназначены для работы в фоновом режиме, поймают этот сигнал и начнут процесс выключения, что приведет к чистому выходу. Сигнал kill, SIGKILL , не может быть перехвачен. Когда это отправляется процессу, это приведет к резкому прекращению этой программы.

Например, когда вы завершаете или перезагружаете свой компьютер, обычно SIGTERM отправляется на запущенные процессы, сначала разрешая им выйти чистым способом, если они его поддерживают. Затем через несколько секунд SIGKILL отправляется в процессы, которые все еще запущены, чтобы принудительно освободить используемые ресурсы (например, используемые файлы) и последовательность выключения может продолжаться (например, размонтирование файловых систем).

Хорошо, играя с этим, я вижу, что, когда вы убиваете задание, которое остановлено (когда выполнение приостановлено, но не завершено), оно не будет завершено до тех пор, пока оно не будет перенесено на передний план. Обычно программы останавливаются нажатием Ctrl- Z на терминале. Большинство терминалов отправляют SIGSTOP в этом случае, но, конечно, есть и другие способы их отправки, такие как kill -STOP или kill -19 .

Это нормальное поведение для того, чтобы программа не закончила сразу, так как программа должна быть запущена для обработки сигнала SIGTERM по умолчанию, отправленного с помощью kill . Более того, иногда после того, как bash отправляет SIGTERM в фоновый процесс, он каким-то образом заканчивается (хотя SIGTERM все еще находится на рассмотрении).

Самый безопасный способ завершить все задания ( не прибегая к kill -9 ) – это сначала отправить SIGTERM с обычным kill , а затем отправить SIGCONT на любые оставшиеся задания, например:

 kill $(jobs -p) kill -18 $(jobs -p) 

SIGCONT ( 18 – номер сигнала) приведет к остановке заданий на переднем плане, чтобы они могли обрабатывать SIGTERM как обычно.

Если все программы не заканчиваются этим, тогда есть несколько других сигналов, которые вы можете попробовать, которые обычно завершают процесс, прежде чем прибегать к kill -9 . Первое, что я рекомендую, это SIGHUP так как многие программы, которые обычно блокируют другие сигналы завершения, реагируют на SIGHUP . Обычно это отправляется, когда контрольный терминал закрывается, в частности, он отправляется, когда сеанс ssh с tty заканчивается. Многие интерактивные программы, такие как оболочки, не будут реагировать на другие сигналы завершения, но будут с этим, так как это будет проблемой для их продолжения работы после завершения сеанса ssh (или после закрытия любого контрольного терминала). Чтобы попробовать это, вы можете так

 kill -1 $(jobs -p) kill -18 $(jobs -p) 

Опять же, конечно, вам нужно убедиться, что программа не остановлена, чтобы она могла обрабатывать сигнал. Другими сигналами окончания вы можете попробовать SIGINT ( kill -2 ) и SIGQUIT ( kill -3 ). Но, конечно, польза от попыток полного диапазона уменьшиться и может привести к неизбежному SIGKILL (aka kill -9 ).

Это приведет к завершению всех заданий в вашей текущей оболочке по одному:

 while kill %; do :; done 

Объяснение: % ссылается на последнее задание в списке, поэтому оно будет зацикливаться до тех пор, пока kill вернет ненулевое значение, что будет означать, что больше не нужно прекращать работу.

Другой подход – сначала отправить SIGTERM , затем SIGCONT чтобы ваши задания могли продолжаться, и первое, что они сделают, это получить ваш SIGTERM .

 /bin/kill $(jobs -p) && /bin/kill -CONT $(jobs -p) 

(по какой-то причине встроенное kill странно, поэтому я использовал внешний здесь).