CronHelper is a simple, but incredibly useful, script — because, really, who wants to worry about cron overlap? Not me, that’s who.
Which is great for PHP, but I’ve been working on a Python CLI project, and what’s a fellow to do but write cronhelper.py.
cronhelper.py
- Accounts for both Windows and Linux
- The pidfile’s name contains a hash of the running script’s absolute path
import os
import sys
import platform
from hashlib import md5
pidfile = '.pidfile-' + md5(os.path.normcase(os.path.abspath(sys.argv[0])).encode('utf-8')).hexdigest();
pid = os.getpid()
def get_lock():
if os.path.isfile(pidfile):
s = open(pidfile,"r").read()
try:
s = int(s)
except:
pass
if s in active_pids():
return False
#else: Last run didn't shut down correctly
open(pidfile, "w").write(str(pid))
return True
def release_lock():
os.unlink(pidfile)
def active_pids():
pids = []
if platform.system() == 'Windows':
# Read the windows process list and get the PIDs
a = os.popen("tasklist").readlines()
for line in a:
p = line[29:34].strip()
try:
pids.append(int(p))
except:
pass
else:
# Read the linux process list and get the PIDs
a = os.popen("ps -aux").readlines()
for line in a:
p = line[9:16].strip()
try:
pids.append(int(p))
except:
pass
return pids
if __name__ == "__main__":
import time
if not get_lock():
print("Couldn't get lock. Another instance must be running")
else:
print("Running...")
time.sleep(10)
print("Finished.")
release_lock()
As you can see from the if __name__ == "__main__":
block, it’s pretty simple to use:
import cronhelper
if not cronhelper.get_lock():
// Error, script is probably already running
pass
else:
// Do your thing
cronhelper.release_lock()