Добавьте руководство & ldquo; wait & rdquo; в сценарии upstart

У меня есть сценарий выскочки, как показано ниже:

start on stopped hw_boot script /usr/bin/python_program end script

Это отлично работает. Но для оптимизации я хотел бы скрыть задержку медленного импорта библиотеки python (в настоящее время она занимает 5-10 секунд). Один из очевидных способов - запустить импорт библиотеки python даже во время загрузки hw.

Итак, я хочу сделать следующее:

start on some_boot_event (this event is earlier than stopped hw_boot) script //import bunch of python libraries that are needed later wait for "stopped hw_boot" /usr/bin/python_program end_script

Как мы можем написать логику ждать «остановленного hw_boot» в сценарии выскочки?

2
задан 19 August 2017 в 01:51

2 ответа

Я не буду вдаваться в подробности и вычеркивать все сценарии Upstart для вас, поскольку вы, похоже, знаете, как их писать, но я покажу вам важные части.

Из вашего вопроса Я буду использовать

some_boot_event в качестве «более раннего» загрузочного события, которое должно инициировать инициализацию программы Python и stopped hw_boot как равномерное, которое должно запускать выполнение программы Python.

Вот как это работает:

Реорганируйте вашу программу Python, чтобы включить вызываемую точку входа, которую можно вызвать позже в произвольное время из других модулей. (В идеале ваш модуль / программа Python уже написан таким образом.) Если программа в настоящее время выполняет любую задачу без инициализации во время загрузки модуля, i. е. в глобальном масштабе, вы должны обернуть их внутри метода. E. g. если ваш модуль в настоящий момент выглядит так, #!shebang import foo, bar # ... various constant, class and method definitions ... print("Hello World") , вы должны его реорганизовать: #!shebang import foo, bar # ... various constant, class and method definitions ... def main(): print("Hello World!") if __name__ == "__main__": main() Записать модуль Python, который импортирует основной модуль вашей программы Python, ждет сигнала и затем вызывает основной метод основного модуля: #!/usr/bin/env python3 import signal, MyMainModule # Perform other initialisation tasks if necessary signal.sigwaitinfo((signal.SIGCONT,)) MyMainModule.main() Если вы не можете использовать Python 3, вы можете обратиться к эквиваленту Signal.sigwaitinfo Python 3 в Python 2.7? для чего-то эквивалентного в Python 2. Запустите задачу «Службы» Upstart с предыдущей программой Python в some_boot_event. Назовем это my_service_task. Начните вторую задачу «одноразовое» на старте в stopped hw_boot, которая отправляет сигнал CONT в предыдущую задачу: set -e kill -s CONT -- "$(initctl status my_service_task | grep -oEe '[0-9]+$')"

Если вам нужно сообщить информацию о статусе из my_service_task в задачу на шаге 4 вы можете настроить FIFO перед отправкой сигнала в последнем:

#!/usr/bin/env python3 import errno, signal, MyMainModule # Perform other initialisation tasks if necessary signal.sigwaitinfo((signal.SIGCONT,)) try: return_value = MyMainModule.main() except Exception as ex: return_value = ex try: with open("/var/run/my_service_task.status") as status_fifo: print(return_value, file=status_fifo) except OSError as ex: if ex.errno not in (errno.ENOENT, errno.EPIPE): raise ex if isinstance(return_value, Exception): raise return_value

На конце считывания:

set -e STATUS_FIFO=/var/run/my_service_task.status mkfifo -m 0600 "$STATUS_FIFO" trap 'rm -f "$STATUS_FIFO"' 0 INT QUIT TERM kill -s CONT -- "$(initctl status my_service_task | grep -oEe '[0-9]+$')" read return_value < "$STATUS_FIFO" # Do stuff with $return_value
3
ответ дан 18 July 2018 в 08:18

Я не буду вдаваться в подробности и вычеркивать все сценарии Upstart для вас, поскольку вы, похоже, знаете, как их писать, но я покажу вам важные части.

Из вашего вопроса Я буду использовать

some_boot_event в качестве «более раннего» загрузочного события, которое должно инициировать инициализацию программы Python и stopped hw_boot как равномерное, которое должно запускать выполнение программы Python.

Вот как это работает:

Реорганируйте вашу программу Python, чтобы включить вызываемую точку входа, которую можно вызвать позже в произвольное время из других модулей. (В идеале ваш модуль / программа Python уже написан таким образом.) Если программа в настоящее время выполняет любую задачу без инициализации во время загрузки модуля, i. е. в глобальном масштабе, вы должны обернуть их внутри метода. E. g. если ваш модуль в настоящий момент выглядит так, #!shebang import foo, bar # ... various constant, class and method definitions ... print("Hello World") , вы должны его реорганизовать: #!shebang import foo, bar # ... various constant, class and method definitions ... def main(): print("Hello World!") if __name__ == "__main__": main() Записать модуль Python, который импортирует основной модуль вашей программы Python, ждет сигнала и затем вызывает основной метод основного модуля: #!/usr/bin/env python3 import signal, MyMainModule # Perform other initialisation tasks if necessary signal.sigwaitinfo((signal.SIGCONT,)) MyMainModule.main() Если вы не можете использовать Python 3, вы можете обратиться к эквиваленту Signal.sigwaitinfo Python 3 в Python 2.7? для чего-то эквивалентного в Python 2. Запустите задачу «Службы» Upstart с предыдущей программой Python в some_boot_event. Назовем это my_service_task. Начните вторую задачу «одноразовое» на старте в stopped hw_boot, которая отправляет сигнал CONT в предыдущую задачу: set -e kill -s CONT -- "$(initctl status my_service_task | grep -oEe '[0-9]+$')"

Если вам нужно сообщить информацию о статусе из my_service_task в задачу на шаге 4 вы можете настроить FIFO перед отправкой сигнала в последнем:

#!/usr/bin/env python3 import errno, signal, MyMainModule # Perform other initialisation tasks if necessary signal.sigwaitinfo((signal.SIGCONT,)) try: return_value = MyMainModule.main() except Exception as ex: return_value = ex try: with open("/var/run/my_service_task.status") as status_fifo: print(return_value, file=status_fifo) except OSError as ex: if ex.errno not in (errno.ENOENT, errno.EPIPE): raise ex if isinstance(return_value, Exception): raise return_value

На конце считывания:

set -e STATUS_FIFO=/var/run/my_service_task.status mkfifo -m 0600 "$STATUS_FIFO" trap 'rm -f "$STATUS_FIFO"' 0 INT QUIT TERM kill -s CONT -- "$(initctl status my_service_task | grep -oEe '[0-9]+$')" read return_value < "$STATUS_FIFO" # Do stuff with $return_value
3
ответ дан 24 July 2018 в 19:03

Другие вопросы по тегам:

Похожие вопросы: