Якщо якісь спарені дочірні процеси провалюються, вбийте всіх і вийдіть


9

У своєму скрипті я розділив набір даних на input_aa, input_ab тощо. Потім я запускаю кожен через той самий сценарій Python як такий:

# Execute program on each split file
for part in input_*; do
        python3 $part &
done
wait

Моє запитання двояке: як я можу виявити, що процес Python не вдався, і коли виявлено, як я вбиваю всіх нерегулярних дітей та вийшов зі скрипту з помилкою?

Відповіді:


10

Ви можете використовувати групу процесів:

set -m
(
   for part in input_*; do
     (python3 "$part" || kill 0) &
   done
   wait
)

set -m(і додаткова функція оболонки POSIX, необхідна функція оболонки Unix) виконує завдання у власній групі процесів. В bash, yash, zsh, mksh, це робочі місця подоболочкі де set -mвключена тому зовнішній (...)і всі процеси , створені в межах , які будуть розміщені в тій же самій групі процесу.

Для оболонок на основі dashта інших ash, які працюють лише в процесі оболонки верхнього рівня. Отже, цей код буде працювати, якщо він не буде розміщений в підпакеті.

Це не працюватиме в AT&T kshабо старій оболонці SysV / Bourne.

kill 0 посилає сигнал SIGTERM всім членам поточної групи процесів.


В баш. Чому я включив шебанг - потрібна оболонка не зрозуміла. Гарна відповідь
— jim mcnamara

@jimmcnamara, що працює в bash, dash, yash, mksh, zsh. В основному будь-яка оболонка POSIX, але AT&T ksh. set -mвказано (недостатньо) в POSIX, але як додаткова функція.
— Стефан Шазелас

Я використовую Solaris. / бін / ш не полетить.
— jim mcnamara

@jimmcnamara, no / bin / sh на Solaris 10 і раніше - оболонка Bourne (не оболонка POSIX), а 11, AT&T ksh. Як я вже сказав, він працює в bash, dash, yash, mksh, zsh.
— Стефан Шазелас

1
@mikeserv, це відновить процес до 1, але не виведе його з групи процесів. kill 0вбиває всіх членів процесної групи незалежно від того, хто є їхнім батьком. Дивіться, ps -jщоб побачити ідентифікатори групи процесів.
— Стефан Шазелас

3

Це приклад. ГРУЙТЕ з цим першим, щоб отримати саме те, що вам потрібно. Він не може зламатись так, як є.

#!/bin/bash
# Example of killing off all children

> killfile
> outfile.err
kill_em()
{
   echo 'killing all children ' > 2
   while read pid
   do
      kill -0 $pid && kill -9 $pid  # if still running kill it
   done < killfile
   exit 1
}

export grandparentpid=$$
trap 'kill_em' 6
for i in 2 2 3 4 5 6 7 8 9 10
do
        ( sleep $i && ls oinkle  >> outfile 2>> outfile.err &
          pid=$!
          echo $pid >> killfile
          wait $!
          [ $? -ne 0 ] && kill -6 $grandparentpid
        ) &
done
wait

Це налаштування для відмови навмисно, тому що ls oinkleвийде з ладу (на моїй машині).

Коли ви отримаєте те, що вам потрібно після майстерності із початковим сценарієм --- Змініть:

for i in 2 2 3 4 5 6 7 8 9 10

до:

for part in input_* 

зміни:

sleep $i && ls oinkle 

до:

python3 $part 

Перенаправлення є для збереження журналів. Ви можете не хотіти їх.


Це трохи раціонально. Якщо одне із завдань виходить з ладу до того, killfileяк початимуться всі інші, можливо, вони не містять усіх підручників, які були розпочаті.
— Стефан Шазелас

Кілька поганих практик, таких як змінні, які не котируються, використання сигнальних номерів замість імен, використання сигналу 6 (наприклад, ABRT на Linux amd64) замість USR1 / USR2 як сигнал користувача, [ $? -ne 0 ]...
— Stéphane Chazelas
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.