确保只有一个进程为使用python的长时间运行的进程执行

问题描述:

我正在寻找最佳实践来确保每分钟执行的脚本脚本只有一个运行实例。对于例如如果我有一个每分钟执行一次的cron,并且万一这个过程需要更长的时间然后一分钟,那么不要再执行另一个。确保只有一个进程为使用python的长时间运行的进程执行

现在我有以下功能。实质上,我得到当前进程的名称,并执行ps grep来查看当前进程的计数是否已列出。有点麻烦,所以我正在寻找更pythonic的方式。

我将代码放在文件的顶部。它确实有效,但又是一团糟。

def doRunCount(stop=False,min_run=1): 
    import inspect 
    current_file = inspect.getfile(inspect.currentframe()) 
    print current_file 
    fn = current_file.split() 
    run_check = os.popen('ps aux | grep python').read().strip().split('\n') 
    run_count = 0 
    for i in run_check: 
     if i.find('/bin/sh')<0: 
      if i.find(current_file)>=0: 
       run_count = run_count + 1 
    if run_count>min_run: 
     print 'max proccess already running' 
     exit() 
    return run_count 
+0

这听起来像你正试图避免资源竞争条件。为什么不直接通过确保cron作业是原子解决问题?也许描述他们在做什么的性质。 – HeyWatchThis 2012-03-06 04:22:56

+0

只需编写一个PID文件并检查它是否存在。请参阅http://*.com/questions/788411/check-to-see-if-python-script-is-running – 2012-03-06 04:43:12

+0

但是如果进程崩溃并且存在一个现有的pid,并且进程没有时间删除pid? – Tampa 2012-03-06 05:52:43

我不知道你是否可以将此描述为最佳实践,但我会使用pid文件。下面的代码片段与我多次使用的片段相似,以确保只有一个特定应用程序的实例正在运行。

import os, sys 

PID_FILE = '/path/to/somewhere.pid' 

if os.path.exists(PID_FILE): 
    pid = int(open(PID_FILE,'rb').read().rstrip('\n')) 
    if len(os.popen('ps %i' % pid).read().split('\n')) > 2: 
     print "Already Running as pid: %i" % pid 
     sys.exit(1) 
# If we get here, we know that the app is not running so we can start a new one... 
pf = open(PID_FILE,'wb') 
pf.write('%i\n' % os.getpid()) 
pf.close() 

if __name__ == '__main__': 
    #Do something here! 
    pass 

就像我说的,这是类似我用什么,但我只是重新写这个片段是多了几分优雅。但它应该得到一般的概念!希望这可以帮助。

这是一个微小的修改,它应该清除由进程崩溃引起的任何问题。 此代码不仅会验证是否存在pid文件,而且该文件中的pid仍然存在,并且该pid仍然是可执行文件。

import os, sys 

PID_FILE = '/path/to/somewhere.pid' 

if os.path.exists(PID_FILE): 
    pid = int(open(PID_FILE,'rb').read().rstrip('\n')) 
    pinfo = os.popen('ps %i' % pid).read().split('\n') 
    if len(pinfo) > 2: 
     # You might need to modify this to your own usage... 
     if pinfo[1].count(sys.argv[0]): 
      # Varify that the process found by 'ps' really is still running... 
      print "Already Running as pid: %i" % pid 
     sys.exit(1) 
# If we get here, we know that the app is not running so we can start a new one... 
pf = open(PID_FILE,'wb') 
pf.write('%i\n' % os.getpid()) 
pf.close() 

if __name__ == '__main__': 
    #Do something here! 
    pass 

之后,我只是离开pid文件,因为你不需要担心误报。请注意,您可能需要将验证的第二步修改为您自己的特定用法!

+0

我喜欢这个方法,但是现在好奇于一个永远不会被删除的挥之不去的问题 – Tampa 2012-03-06 05:54:31

+0

我发布了第二个版本,应该回答您的一些担忧。基本上,我尽我所能来验证pid文件中的进程是否真的死了。之后,pid文件的存在是一个非问题! – 2012-03-06 06:14:26

+0

Thnaks,当我运行你的代码时,我得到这个错误。 pf.write('%i \ n'%pid) NameError:name'pid'is not defined – Tampa 2012-03-07 01:25:02