2009-04-25 143 views
72

我有一个蟒蛇守护进程运行作为我的web应用程序的一部分/我怎样可以快速检查,如果我的守护进程正在运行(使用python),如果没有,启动它?检查是否python脚本运行

我想这样做的修复守护进程的任何崩溃,所以脚本不必手动运行,它就会自动运行,因为它是所谓的,然后保持运行。

如何检查(使用python),如果我的脚本运行?

+0

你肯定你wan't你的过程太让您的其他过程长达写在Python? – ojblass 2009-04-25 07:18:06

+0

在Tendo中去吧,创建脚本的单例实例,因此如果脚本已经在运行,它将不会运行。 https://github.com/pycontribs/tendo – JasTonAChair 2016-02-21 07:54:51

回答

74

删除一个pidfile进程文件某处(例如是/ tmp)。然后,您可以通过检查文件中是否存在PID来检查进程是否正在运行。不要忘记在关闭时删除文件,并在启动时检查它。

#/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进程文件(当杀,异常升高等)。

+0

忘记关闭文件后写入PID? – ibz 2010-07-12 04:58:57

+1

由于对文件对象的引用永远不会实际存储,因此在write()调用完成后它不会保留引用计数。我不确定这是否被认为是Pythonic,但它工作得很好。 具体来说:将分配对象,调用write()方法,然后它将立即释放,这将为您关闭文件。 – 2010-07-13 03:37:06

+4

如果程序中断,os.unlink()将不会执行,程序将不会再次运行,因为该文件存在。对 ? – 2011-05-28 17:00:42

1

有选项万千。一种方法是使用系统调用或python库为您执行此类调用。另一种是简单地产生一个过程,如:

ps ax | grep processName 

并解析输出。许多人选择这种方法,在我看来,这不一定是坏方法。

+0

会processName包含我的脚本的文件名? – 2009-04-25 07:08:48

+0

这取决于你如何开始你的过程 – ojblass 2009-04-25 07:13:31

+0

例如:ps ax | grep python – User 2014-07-23 20:37:01

10

有在UNIX上重新启动的过程非常好包。有一个关于构建和配置它的好教程是monit。随着一些调整,你可以有坚实的证明技术保持守护进程。

+0

我同意,不要重新发明轮子,有很多方法来守护你的应用程序,包括重新启动它,如果它死了,启动如果没有运行等等 – davr 2009-04-25 07:47:35

2

我的Supervisor管理守护进程的大风扇。它是用Python编写的,所以有很多关于如何与Python进行交互或扩展的例子。为了您的目的,XML-RPC process control API应该很好地工作。

10

当然,从丹的例子是行不通的,因为它应该是。

事实上,如果脚本崩溃,上升异常,或者不干净pid文件,该脚本就会被运行多次。

我建议以下基于从其他网站:

这是检查是否已经有现有

\#/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文件中的锁锁文件文件

pidfile = open(os.path.expanduser("~/.lockfile.vestibular.lock"), "w") 
pidfile.write("%s" % os.getpid()) 
pidfile.close() 

该代码将检查相比,现有的正在运行的进程的PID的值。,避免了双重执行。

我希望这会有所帮助。

126

的技术是在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) 

它是原子,如果你的进程被发送一个SIGKILL

您避免了锁文件躺在身边的问题可以read in the documentation for socket.close当垃圾收集时,套接字会自动关闭。

0

其他的答案是伟大的东西像cron作业,但如果你正在运行一个后台程序,你应该像daemontools监控。

-1

请看下面的例子来解决你的问题:

#!/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) 

我建议这个脚本,因为它可以在一个时间才可以执行。

3

试试这个其他版本的

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) 
-1

使用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); 

要进行测试,添加

stop_if_already_running() 
print "running normally" 
while True: 
    time.sleep(3) 
0
ps ax | grep processName 

如果pycharm侑调试脚本始终退出

pydevd.py --multiproc --client 127.0.0.1 --port 33882 --file processName 
0

,而不是开发自己的PID文件的解决方案(其中有更多的细微之处和你可能会想到的情况下),看看supervisord - 这是一个过程控制系统,使它ea sy将现有Python脚本的作业控制和守护进程行为封装起来。

15

pid库可以做的正是这一点。

from pid import PidFile 

with PidFile(): 
    do_something() 

它也会自动处理pidfile存在,但进程没有运行的情况。

0

试试这个:

#/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) 
0

这里是比较有用的代码(有检查,如果恰好蟒蛇执行脚本):

#! /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) 

这里是字符串:

ps_command = "ps -o command= %s | grep -Eq 'python .*/%s'" % (pid,script_name) 

回报0如果“grep”成功,并且进程“python”正在与na一起运行我的脚本作为参数。

0

一个简单的例子,如果你只在寻找的过程形同虚设与否:

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 
0

遇到了这个老问题寻找解决方案自己。

使用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']) 
相关问题