?

Log in

No account? Create an account

Перезапуск скрипта - Узором созвездий по мантии ночи

01.10.2015, Четверг

15:20:00 - Перезапуск скрипта

Previous Entry Поделиться Next Entry

Вот такая задачка:
Есть некий скрипт, писанный на питоне, крутится более-менее постоянно (под screen).
Обощённо цикл работы состоит из проверки, не пришли ли "данные" для обработки, и если пришли -- происходит довольно долгая (десятки минут) обработка.
Захотелось его перезапускать для обновления, не ловя момент окончания обработки.

Простейшие варианты:

1) Функции семейства os.exec* -- успешно подменят старый процесс новым, всё замечательно, но если новый почему-либо не стартует, то это надо заметить, потом исправить -- только тогда работа продолжится.

2) Вызвать новый скрипт через subprocess.Popen, убедиться, что он нормально взлетел, после чего завершить старый. Исправляет недостаток первого пункта, но новый скрипт, используя ту же "консоль" (те же stdin/stdiut, stderr), при этом выпадает из jobcontrol'а, т.е. крутится в фоне по отношению к шеллу, из которого был запущен старый скрипт, а из старого мы попадаем обратно в шелл. И при том отт фоновый новый скрипт не может подхватить команда fg.

Есть ли способ избавиться от недостатков обоих методов, не выделяе контроль за перезапуском в отдельный процесс?
Кроссплатформенности от данного механизма (пока?) не требуется.

(На крайняк мне пока годится первый вариант, поскольку перезапуски пока что как правило контролируются вручную, да и короткий даунтайм в общем-то не страшен. Но всё же интересно, может, есть простое решение?)

This entry was originally posted at http://arilou.dreamwidth.org/975307.html. Please comment there using OpenID.

Comments:

[User Picture]
From:vitus_wagner
Date:01.10.2015 13:23:49
(Link)
Сначала прогнать скрипт через pylint, а потом os.exec.
понятно, что pylint (как и компилятор с -W error, если бы там был C а не питон), не гарантирует от того, что очередные изменения все сломают, но, возможно. сведет вероятность поломки к достаточно небольшой, чтобы с ней можно было мириться.
(Ответить) (Thread)
[User Picture]
From:arilou
Date:01.10.2015 13:45:12
(Link)
Про pylint я думал. Но он ведь проверяет синтаксис только самого модуля, по импортам не ходит?
Я думал уже, что тут может быть уместно вызвать мини программку, которая под try сделает import (чем проверит, за одно, и все импортируемые модули), ну и кодом возврата отсигналит вызывающему, получилось или нет.

А неизвратного способа передать child-процесс (результат subprocess.Popen()) от скрипта его родителю не существует? Чтобы bash принял новый процесс под свой jobcontrol.

(Ну и, да, я помню, что правильнее всего, наверное, сделать процесс демоном, писать логи, сделать к нему *ctl утилиту. Позже дойдут руки и до этого.)
(Ответить) (Parent) (Thread)
[User Picture]
From:vitus_wagner
Date:01.10.2015 14:29:12
(Link)
jobcontrol в баше неизвратным быть не может. Это вообще такой костыль...

У тебя должен быть Makefile (ну ли setup.py) без разницы, который прогонит pylint по всем модулям, а по некоторым - и юниттесты, и только после этого перезапишет старые модули на новые. (python setup.py install),

А работающий скрипт будет перезапускаться по факту обнаружения обновления своих исходников.

Кстати, есть еще интересный вариант, я нечно подобное в GUI приложениях на tcl использовал - иметь в главном скрипте ТОЛЬКО логику перезагрузки модулей, которую один раз отладить и больше никогда не менять.

А всю остальную функциональность держать в модулях, которые перегружать по ходу в текущий процесс. Для этого в python есть функция reload.
И в принципе можно даже сделать откат на предыдущую версию модуля, если reload обломился.
(Ответить) (Parent) (Thread)
[User Picture]
From:phd
Date:01.10.2015 14:27:03
(Link)
#!/bin/sh
set -e
while true; do
    RESTART=old
    if [ -x new-script.py ]; then
        ./new-script.py --test && RESTART=new
    fi
    if [ "$RESTART" = old ]; then
        rm new-script.py
    elif [ "$RESTART" = new ]; then
        mv new-script.py script.py
    fi
    ./script.py --do-the-job
done


Edited at 2015-10-01 14:48 (UTC)
(Ответить) (Thread)
[User Picture]
From:beldmit
Date:01.10.2015 19:56:33
(Link)
Я прописываю в cron периодический запуск, а самим скриптом лочу файл. Не смог залочить - значит, предыдущий ещё работает. И всё. Всех делов - flock и проверку.
(Ответить) (Thread)