суббота, 5 октября 2013 г.

Всякое бывает...


Бывает так, что из-под питонячего кода нужно вызвать какой-то исполняемый файл(*.sh). Бывает так, что этот исполняемый файл (*.sh) должен выполнить какой-то питонячий скрипт. Бывает так, что исполняемый файл надо остановить.
Тут логично, что при остановке исполняемого файла, питоновский скрипт тоже должен остановиться. Но это не так...



# Под катом:
cat fruits.py

import subprocess
like_fruit = subprocess.Popen("start_import_fruits.sh", stdout=log.stream, stderr=subprocess.STDOUT) #  выполняем скрипт с помощью Popen

... # (тут извне приходит сигнал "ОСТАНОВИТЕ выброс экзотических фруктов!")

like_fruit.poll() # провереям завершение дочерних процессов и устанавливаем код возврата

if like_fruit.returncode is None: # код возврата None тогда, когда дочерний процесс еще не завершился
like_fruit.kill() # сейчас хотим убить дочерний процесс
...

cat start_import_fruits.sh
./import_fruits.py

cat import_fruits.py
# здесь долгий процесс импорта экзотических фруктов

Если посмотрим на состояние выполнения дочернего процесса (ps aux | grep start_import_fruits.sh), то увидим, что после kill'a он будет убит (ведь kill() посылает SIGKILL сигнал).
Но если внутри start_import_fruits.sh запускается долгий импорт фруктов из холодильника(под названием import_fruits.py), то даже после убийства start_import_fruits.sh импорт не завершиться. Все потому что import_fruits.py не будет убит. И об этом надо помнить.

Чтобы убить процессы, порожденные start_import_fruits.sh, можно, например, после основного убийства сделать дополнительное: запустить отдельный скрипт, который убьет то, что было порождено start_import_fruits.sh. Либо можно сохранять порождаемые pid'ы в определнной директории, а потом разом всех убивать. Либо смотреть все порождаемые родителем процессы в /proc/<number>/stat и тоже кого-то убивать. В итоге, по-любому, нужно будет дополнительного кого-то убить, например так:

ps aux | grep import_fruits.py| grep -v 'grep' | awk '{ print $2 }'` | xargs sudo kill -9 

Для тех, кто еще с моим фруктами...
(с) http://www.flickr.com/photos/27495785@N05/3179853645/sizes/l/in/photostream/

2 комментария:

  1. А ты не пробовала убивать дочерние процессы из .sh скрипта при получении им SIGTERM?
    По идее, что-то вроде:

    ....
    trap "kill import_fruits.py; exit" TERM
    ./import_fruits.py
    ....

    По идее, когда ты скажешь скрипту kill - он сам прибьет питон по 15 сигналу

    ОтветитьУдалить