【问题标题】:Stop systemd service running a python program停止运行 python 程序的 systemd 服务
【发布时间】:2021-08-19 09:37:55
【问题描述】:

我创建了一个服务来运行 Python 程序,并添加了几行代码来创建一个锁以避免启动它两次。

不幸的是,我不知道如何配置服务以正确停止正在运行的程序。运行停止命令时它不会删除锁定,然后我无法再启动服务。如果我通过 CLI 自己执行程序并使用 Ctrl+C 退出,则锁定被删除。

我已阅读有关KillMode、ExecStop 和Signal 的手册。我的理解是默认配置是我需要的。

有什么帮助吗?

主程序

if __name__ == '__main__':

    #Creating lock to avoid launching program twice
    lock = pathlib.Path("program.lock")

    if not lock.exists():

        lock_acquired_on = datetime.now()

        with open('program.lock', 'w') as lock:
            lock.write(f'Lock acquired on {lock_acquired_on}')
            logger.info('Added lock file to avoid running the program twice.')
    
        try:
            while True:

                #Doing stuff here


        except KeyboardInterrupt:
            close_program() #Close other threads

        #Removing the lock file
        os.remove(pathlib.Path("program.lock"))

    else:
        with open('program.lock', 'r') as lock:
            lock_acquisition_time = str(lock.readlines()[0])
            logger.info('Programme Maquette Status is already running.') 
            logger.info(lock_acquisition_time)

服务

[Unit]
Description=Programme Maquette IoT End-to-End
After=multi-user.target
Conflicts=getty@tty1.service

[Service]
WorkingDirectory=/home/pi/Documents/ProductionMaquette
Type=simple
ExecStart=/usr/local/bin/python3.8 /home/pi/Documents/ProductionMaquette/Lo_main.py
StandardInput=tty-force

[Install]
WantedBy=multi-user.target

【问题讨论】:

    标签: python linux loops exit systemd


    【解决方案1】:

    Systemd 将 SIGTERM 发送到进程 - 所以你需要处理它。

    所以下面的小例子使用SIGTERM 的信号处理程序来清理文件。实际上它使用 atexit 来清理文件,因为它也处理标准退出条件和一个信号处理程序,以在接收到SIGTERM 信号时启动“正常”关闭进程

    import atexit
    import signal
    import os
    
    locking_file = "/var/lock/my_service.lock"
    
    if __name__ == '__main__':
    
        def clean_lock():
            # atexit handler to clean up a file
            os.remove(locking_file)
    
        def signal_term_handler(sigNum, frame):
            # on receiving a signal initiate a normal exit
            raise SystemExit('terminating')
    
        with open("test_file.lock", "w") as lock:
             while True:
                 lock.write("x")
                 time.sleep(10)
    
        # register the cleanup handler
        atexit.register(clean_lock)
        # register the signal handler
        signal.signal(signal.SIGTERM, signal_term_handler)
    

    请注意:您可能需要查看一个文件锁定库:https://pypi.org/project/filelock/,因为它也可以处理该用例。

    它不仅测试文件的存在,而且使用 os-file 锁定机制。 IE。不仅测试文件的存在 - 而且它是否可以被锁定。实际上,这意味着即使文件仍然存在,但前一个进程已终止,这也不是问题,因为文件不再被锁定。

    【讨论】:

    • 感谢您的帮助。我只需要将信号放在主块的开头,您的解决方案就可以工作。否则它不会删除锁定文件。我也试过filelock,但我无法使用这个模块启动服务,而我可以直接执行程序,我找不到原因。
    • 更改了示例脚本,使信号处理程序在if __name__ == "__main__":下
    猜你喜欢
    • 2016-04-26
    • 1970-01-01
    • 2017-03-17
    • 1970-01-01
    • 2019-04-17
    • 1970-01-01
    • 2020-01-22
    • 2019-11-19
    • 2017-04-03
    相关资源
    最近更新 更多