简体   繁体   English

停止运行 python 程序的 systemd 服务

[英]Stop systemd service running a python program

I created a service to run a Python program and added some lines of code to create a lock to avoid launching it twice.我创建了一个服务来运行 Python 程序并添加了一些代码行来创建一个锁以避免启动它两次。

Unfortunately I don't know how to configure the service to stop the running program correctly.不幸的是,我不知道如何配置服务以正确停止正在运行的程序。 When running the stop command it doesn't delete the lock, then I can't start the service anymore.运行停止命令时它不会删除锁,然后我无法再启动该服务。 If I execute the program myself via CLI and exit with a Ctrl+C, the lock is deleted.如果我自己通过 CLI 执行程序并使用 Ctrl+C 退出,锁将被删除。

I've read the manual about KillMode , ExecStop and Signal .我已经阅读了有关KillModeExecStopSignal的手册。 My understanding is that the default configuration was the one I needed.我的理解是默认配置是我需要的。

Any help please?有什么帮助吗?

Main program主程序

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)

Service服务

[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

Systemd sends the SIGTERM to the process - so you need to handle that. Systemd 将 SIGTERM 发送到进程 - 因此您需要处理它。

So following little example uses the a signal handler for SIGTERM to clean up a file.因此,下面的小示例使用SIGTERM的信号处理程序来清理文件。 Actually it uses atexit to clean up the file, as that handles standard exit conditions as well and a signal handler to initiate in "normal" closing down of the process on receiving the SIGTERM signal实际上它使用 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)

As a note: there is a file locking library you might want to look at: https://pypi.org/project/filelock/ as that should handle that use case as well.请注意:您可能想查看一个文件锁定库: https://pypi.org/project/filelock/因为它也应该处理该用例。

It is not only testing for presents of a file but uses the os-file locking mechanism.它不仅测试文件的存在,而且使用操作系统文件锁定机制。 Ie not only the existence of the file is tested - but if it can be locked as well.即不仅测试了文件的存在性——而且还测试了它是否可以被锁定。 In effect that means even if the file still exists but the previous process died it is not a problem, as the file is no longer locked.实际上,这意味着即使文件仍然存在但先前的进程已死亡,这也不是问题,因为文件不再被锁定。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM