检查python脚本是否正在运行
我有一个python守护进程运行作为我的web应用程序的一部分/我如何快速检查(使用python)如果我的守护进程正在运行,如果没有,启动它?
我想这样做来修复守护进程的任何崩溃,所以脚本不必手动运行,只要调用它就会自动运行,然后保持运行。
我如何检查(使用Python)如果我的脚本正在运行?
把pidfile放在某个地方(例如/ tmp)。 然后可以通过检查文件中是否存在PID来检查进程是否正在运行。 不要忘了closures干净的文件,并在启动时检查它。
#/usr/bin/env python import os import sys pid = str(os.getpid()) pidfile = "/tmp/mydaemon.pid" if os.path.isfile(pidfile): print "%s already exists, exiting" % pidfile sys.exit() file(pidfile, 'w').write(pid) try: # Do some actual work here finally: os.unlink(pidfile)
然后,通过检查/tmp/mydaemon.pid的内容是否是现有进程,可以检查进程是否正在运行。 Monit(上面提到的)可以为你做这个,或者你可以编写一个简单的shell脚本来使用ps的返回码来检查它。
ps up `cat /tmp/mydaemon.pid ` >/dev/null && echo "Running" || echo "Not running"
为了额外的功劳,你可以使用atexit模块来确保你的程序在任何情况下清理它的pidfile(当被杀死,引发exception等)。
在Linux系统上使用的技术是使用域套接字:
import socket import sys import time def get_lock(process_name): # Without holding a reference to our socket somewhere it gets garbage # collected when the function exits get_lock._lock_socket = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM) try: get_lock._lock_socket.bind('\0' + process_name) print 'I got the lock' except socket.error: print 'lock exists' sys.exit() get_lock('running_test') while True: time.sleep(3)
它是primefaces的,避免了如果你的进程被发送SIGKILLlocking文件的问题
你可以在socket.close
的文档中看到,当垃圾收集时,套接字会自动closures。
pid库可以做到这一点。
from pid import PidFile with PidFile(): do_something()
它也会自动处理pidfile存在的情况,但进程没有运行。
当然,丹的例子不会按原样工作。
的确,如果脚本崩溃,引发exception,或者不清除pid文件,脚本将会多次运行。
我build议以下基于另一个网站:
这是为了检查是否已经存在locking文件
\#/usr/bin/env python import os import sys if os.access(os.path.expanduser("~/.lockfile.vestibular.lock"), os.F_OK): #if the lockfile is already there then check the PID number #in the lock file pidfile = open(os.path.expanduser("~/.lockfile.vestibular.lock"), "r") pidfile.seek(0) old_pid = pidfile.readline() # Now we check the PID from lock file matches to the current # process PID if os.path.exists("/proc/%s" % old_pid): print "You already have an instance of the program running" print "It is running as process %s," % old_pid sys.exit(1) else: print "File is there but the program is not running" print "Removing lock file for the: %s as it can be there because of the program last time it was run" % old_pid os.remove(os.path.expanduser("~/.lockfile.vestibular.lock"))
这是我们把一个PID文件放在locking文件中的代码的一部分
pidfile = open(os.path.expanduser("~/.lockfile.vestibular.lock"), "w") pidfile.write("%s" % os.getpid()) pidfile.close()
此代码将检查与现有运行进程相比较的pid值,避免双重执行。
我希望这会有所帮助。
在UNIX上有非常好的重新启动进程的软件包。 有一个关于构build和configuration它的好教程是monit 。 通过一些调整,你可以有一个坚实的certificate技术保持守护进程。
试试这个其他版本
def checkPidRunning(pid): '''Check For the existence of a unix pid. ''' try: os.kill(pid, 0) except OSError: return False else: return True # Entry point if __name__ == '__main__': pid = str(os.getpid()) pidfile = os.path.join("/", "tmp", __program__+".pid") if os.path.isfile(pidfile) and checkPidRunning(int(file(pidfile,'r').readlines()[0])): print "%s already exists, exiting" % pidfile sys.exit() else: file(pidfile, 'w').write(pid) # Do some actual work here main() os.unlink(pidfile)
我是pipe理守护进程的主pipe的粉丝。 它是用Python编写的,所以有很多关于如何与Python进行交互或扩展的例子。 为了您的目的, XML-RPC过程控制API应该很好地工作。
有无数的select。 一种方法是使用系统调用或python库来执行这样的调用。 另一个是简单地产生一个过程,如:
ps ax | grep processName
并parsing输出。 很多人select这种方法,我认为这不一定是坏的方法。
其他的答案对于cron作业是很好的,但是如果你运行的是一个守护进程,你应该用daemontools来监视它。
ps ax | grep processName
如果你在pycharm中debugging脚本总是退出
pydevd.py --multiproc --client 127.0.0.1 --port 33882 --file processName
而不是开发你自己的PID文件解决scheme(它比你想象的更微妙,更具细节性),看看supervisord – 这是一个过程控制系统,可以很容易地将作业控制和守护进程的行为封装在现有的Python脚本。
尝试这个:
#/usr/bin/env python import os, sys, atexit try: # Set PID file def set_pid_file(): pid = str(os.getpid()) f = open('myCode.pid', 'w') f.write(pid) f.close() def goodby(): pid = str('myCode.pid') os.remove(pid) atexit.register(goodby) set_pid_file() # Place your code here except KeyboardInterrupt: sys.exit(0)
这里是更有用的代码(检查Python是否执行脚本):
#! /usr/bin/env python import os from sys import exit def checkPidRunning(pid): global script_name if pid<1: print "Incorrect pid number!" exit() try: os.kill(pid, 0) except OSError: print "Abnormal termination of previous process." return False else: ps_command = "ps -o command= %s | grep -Eq 'python .*/%s'" % (pid,script_name) process_exist = os.system(ps_command) if process_exist == 0: return True else: print "Process with pid %s is not a Python process. Continue..." % pid return False if __name__ == '__main__': script_name = os.path.basename(__file__) pid = str(os.getpid()) pidfile = os.path.join("/", "tmp/", script_name+".pid") if os.path.isfile(pidfile): print "Warning! Pid file %s existing. Checking for process..." % pidfile r_pid = int(file(pidfile,'r').readlines()[0]) if checkPidRunning(r_pid): print "Python process with pid = %s is already running. Exit!" % r_pid exit() else: file(pidfile, 'w').write(pid) else: file(pidfile, 'w').write(pid) # main programm .... .... os.unlink(pidfile)
这里是string:
ps_command = "ps -o command= %s | grep -Eq 'python .*/%s'" % (pid,script_name)
如果“grep”成功,则返回0,进程“python”当前正在以脚本名称作为参数运行。
一个简单的例子,如果你只是在寻找一个进程的名字是否存在:
import os def pname_exists(inp): os.system('ps -ef > /tmp/psef') lines=open('/tmp/psef', 'r').read().split('\n') res=[i for i in lines if inp in i] return True if res else False Result: In [21]: pname_exists('syslog') Out[21]: True In [22]: pname_exists('syslog_') Out[22]: False
遇到这个老问题我自己寻找解决scheme。
使用psutil :
import psutil import sys from subprocess import Popen for process in psutil.process_iter(): if process.cmdline() == ['python', 'your_script.py']: sys.exit('Process found: exiting.') print('Process not found: starting it.') Popen(['python', 'your_script.py'])
考虑下面的例子来解决你的问题:
#!/usr/bin/python # -*- coding: latin-1 -*- import os, sys, time, signal def termination_handler (signum,frame): global running global pidfile print 'You have requested to terminate the application...' sys.stdout.flush() running = 0 os.unlink(pidfile) running = 1 signal.signal(signal.SIGINT,termination_handler) pid = str(os.getpid()) pidfile = '/tmp/'+os.path.basename(__file__).split('.')[0]+'.pid' if os.path.isfile(pidfile): print "%s already exists, exiting" % pidfile sys.exit() else: file(pidfile, 'w').write(pid) # Do some actual work here while running: time.sleep(10)
我build议这个脚本,因为它只能执行一次。
用bash用当前脚本的名字查找一个进程。 没有额外的文件。
import commands import os import time import sys def stop_if_already_running(): script_name = os.path.basename(__file__) l = commands.getstatusoutput("ps aux | grep -e '%s' | grep -v grep | awk '{print $2}'| awk '{print $2}'" % script_name) if l[1]: sys.exit(0);
要testing,请添加
stop_if_already_running() print "running normally" while True: time.sleep(3)