Ad

Python Script That Can Be Externally Terminated In A Graceful Manner

- 1 answer

My server generates every minute ~30 xml files, and I would like to do a sftp to transfer files from server to my machine. I would like to use Paramiko to do an sftp, I am getting what I want with the bellow script:

import paramiko
import os
import time
filename = "addresses.text"
localpath= "******"
serverpath= "*******"


while True:
    try:
        current_time = time.time()
        with open(filename) as f:
            data = f.readlines()
        for ipAddr in data:
            ssh = paramiko.SSHClient()
            ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
            ssh.connect(ipAddr,username="root",password="root")
            sftp = ssh.open_sftp()
            for element in sftp.listdir(serverpath):
                if element.endswith(".xml"):
                    try:
                        print(os.stat(localpath+f))
                    except:
                        try:
                            creation_time = sftp.stat(serverpath+element).st_mtime
                            if (current_time+3400 - creation_time) / (3600) <= 1:
                                sftp.get(serverpath+element,localpath+element)
                        except:
                            print(Exception)
            sftp.close()
            ssh.close()
        for f in os.listdir(localpath):
            creation_time = os.path.getctime(localpath+f)
            print((3600+current_time - creation_time) / (3600))
            if (3600+current_time - creation_time) / (3600) >= 1.8:
                os.unlink(localpath+f)

    except OSError as e:
        print(OSError)

I would like to do something like start sftp.py and then run my script in the background. And when I want to stop the connection just run stop sftp.py

Ad

Answer

How this is usually implemented is that a running process stores its PID to a file.

And then you can implement another script (or a parameter to your existing script - like my example below does) that reads the PID from the file and terminates that process.

You can even make the termination graceful.

import signal
import time
import os
import sys

pidfile = "sftp.pid"

if (len(sys.argv) > 1) and (sys.argv[1] == "stop"):
    if os.path.isfile(pidfile):
        with open(pidfile, "r") as f:
            pid = int(f.read())
        print("stopping sftp process {0}".format(pid))
        os.kill(pid, signal.SIGTERM)
    else:
        print("sftp is not running")
    sys.exit()

class GracefulKiller:
    kill_now = False
    def __init__(self):
        signal.signal(signal.SIGINT, self.exit_gracefully)
        signal.signal(signal.SIGTERM, self.exit_gracefully)

    def exit_gracefully(self,signum, frame):
        self.kill_now = True

if __name__ == '__main__':
    pid = os.getpid()
    print("sftp is starting with pid {0}".format(str(pid)))
    with open(pidfile, "w") as f:
        f.write(str(pid))

    killer = GracefulKiller()
    while True:
        time.sleep(1)
        print("doing something in a loop ...")
        if killer.kill_now:
            break

    print "End of the program. I was killed gracefully :)"

    os.remove(pidfile)
Ad
source: stackoverflow.com
Ad