我有一个如下所示的新贵脚本:
start on stopped hw_boot
script
/usr/bin/python_program
end script
这很好。但为了优化,我想隐藏缓慢的 Python 库导入的延迟(目前需要 5-10 秒)。一个明显的方法是即使在硬件启动期间也启动 Python 库导入。
所以,我想要做的事情如下:
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
我们如何在 upstart 脚本中编写一个逻辑来等待“stopped hw_boot”?
答案1
我不会详细介绍并为您列出整个 Upstart 脚本,因为您似乎已经知道如何编写它们,但我将向您展示关键部分。
从你的问题中我将使用
some_boot_event
作为“较早”的启动事件,应该触发初始化Python 程序和stopped hw_boot
因为这应该会触发执行Python 程序。
它的工作原理如下:
重构您的 Python 程序以包含一个可调用的入口点,该入口点稍后可从其他模块任意时间调用。(理想情况下,您的 Python 模块/程序已经以这种方式编写。)如果程序当前在模块加载时(即在全局范围内)执行任何非初始化任务,则应将它们包装在方法中。
例如,如果你的模块当前看起来像这样,
#!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,你可以参考Python 3 的 Signal.sigwaitinfo 相当于 Python 2.7 吗?在 Python 2 中可以找到等效的东西。
使用 处的先前 Python 程序启动 Upstart “服务” 任务
some_boot_event
。我们将其命名为my_service_task
。启动第二个 Upstart “一次性” 任务,并向前一个任务
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