This post originated from an RSS feed registered with Python Buzz
by Ben Last.
Original Post: Self-Starting Singleton Scripts
Feed Title: The Law Of Unintended Consequences
Feed URL: http://benlast.livejournal.com/data/rss
Feed Description: The Law Of Unintended Consequences
I wrote some nonsense a while back about how to make a Python script run one instance of itself only. This works very well for me, with scripts being (re)started at regular intervals by cron jobs, the new instances detecting that there's an old instance and dying off. But it's sometimes a bit of a pain to have to manually kill off a task when I've updated the actual Python script. I don't want to arbitrarily kill it, because it might be in the middle of something that I want to run to completion - a lot of the database stuff that goes on is time-consuming and whilst a kill will roll back anything done so far, that's not efficient.
So a few minutes' though brought this to light (this includes the run-one-of-me-only code):
#Make a note of the time we start running.
startTime = long(time.time())
#Get the current PID of this process
pid = os.getpid()
#Use an external command to see if any other process is running this script
#Derive the scriptname from sys.argv. Note that if there are scripts with
#the same name in different directories, this check will fail.
scriptName = os.path.basename(sys.argv[0])
ps = os.popen('ps --no-headers -elf|fgrep %s' % scriptName)
psl = ps.readlines()
ps.close()
for p in psl:
if p.find('python')>-1 and p.find('trigger.py')>-1:
otherpid = int(p.split()[3])
if otherpid <> pid: sys.exit()
Then, in the main loop of the script...
while True:
#Sleep for a bit...
time.sleep(SLEEPTIME)
#Check to see if this script has been updated since the last
#iteration. If so, die now so that the new version can take over
#and be restarted by cron. Assumes that the working directory
#is that of the script (or that from which the script was started).
x = os.stat(sys.argv[0])
#Check the modification time of the script against the time we started running
if x.st_mtime > startTime:
print "Script has changed; will exit to allow restart"
sys.exit(0)
Cheap and cheerful stuff, but useful. And hey, I didn't even mention static typing once...