Search code examples
pythonlinuxapscheduler

Automatic start and stop of APScheduler during boot of linux?


How to automatic start and stop the Python APScheduler during Linux boot (Centos in my case), and stop it during shutdown?

I can start a python script during boot in linux, but then how to stop it? (remember the PID?)

And I am wondering if that is the way to go, as I want to have an easy deployment, such that developers can easily update the files in test/production and restart the scheduler, without becoming a root such that they can start/stop the service.

Currently I have the scheduler started/stopped by using tmux, which works, but I can't seem to find a good way to improve that such that during a server start/stop it's automatically started/stopped and easy updated during a deployment :(


Solution

  • It's usual to create a file with extension .pid to hold the process PID. Then you need to register a signal handler to cleanly exit, and make sure you delete the .pid file at exit.

    For example:

    #!/usr/bin/env python
    
    import signal
    import atexit
    import os
    
    PID_FILE_PATH = "program.pid"
    stop = False
    
    def create_pid_file():
        # this creates a file called program.pid
        with open(PID_FILE_PATH, "w") as fhandler:
            # and stores the PID in it
            fhandler.write(str(os.getpid()))
    
    def sigint_handler(signum, frame):
        print("Cleanly exiting")
        global stop
    
        # this will break the main loop
        stop = True
    
    def exit_handler():
        # delete PID file
        os.unlink(PID_FILE_PATH)
    
    def main():
        create_pid_file()
    
        # this makes exit_handler to be called automatically when the program exists
        atexit.register(exit_handler)
    
        # this makes sigint_handler to be called when a signal SIGTERM 
        # is sent to the process, e.g with command: kill -SIGTERM $PID
        signal.signal(signal.SIGTERM, sigint_handler)
    
        while not stop:
            # this represents your main loop
            pass
    
    if __name__ == "__main__":
        main()