检查python脚本是否正在运行

检查python脚本是否正在运行,python,process,daemon,Python,Process,Daemon,我有一个python守护进程作为我的web应用程序的一部分运行/如何快速检查(使用python)我的守护进程是否正在运行,如果没有,如何启动它 我希望通过这种方式修复守护进程的任何崩溃,因此脚本不必手动运行,它将在调用后自动运行,然后保持运行 如何检查(使用python)脚本是否正在运行?有很多选项。一种方法是使用系统调用或python库为您执行此类调用。另一个是简单地产生一个过程,如: ps ax | grep processName 并解析输出。许多人选择这种方法,在我看来,这不一定是一种

我有一个python守护进程作为我的web应用程序的一部分运行/如何快速检查(使用python)我的守护进程是否正在运行,如果没有,如何启动它

我希望通过这种方式修复守护进程的任何崩溃,因此脚本不必手动运行,它将在调用后自动运行,然后保持运行


如何检查(使用python)脚本是否正在运行?

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

ps ax | grep processName

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

有非常好的软件包可以在UNIX上重新启动进程。有一个关于构建和配置它的很好的教程是。通过一些调整,您可以拥有一种坚如磐石的经验证的技术来保持您的守护进程。

将一个PID文件放到某个地方(例如/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模块来确保您的程序在任何情况下(被杀死、引发异常等)都会清理其PID文件。

我非常喜欢管理守护程序。它是用Python编写的,因此有很多示例说明如何与Python交互或从Python扩展它。出于您的目的,这个例子应该很好地工作。

当然,Dan的例子不会像它应该的那样工作

实际上,如果脚本崩溃、引发异常或没有清理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值与现有运行进程的比较,避免重复执行


我希望这会有所帮助。

在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:
        # The null byte (\0) means the socket is created 
        # in the abstract namespace instead of being created 
        # on the file system itself.
        # Works only in Linux
        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消息时锁定文件的问题


您可以确定套接字在垃圾收集时会自动关闭。

其他答案对于cron作业之类的任务非常有用,但如果您正在运行守护进程,则应使用类似的方法对其进行监控。

考虑以下示例来解决您的问题:

#!/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)
我建议使用此脚本,因为它只能执行一次。

请尝试其他版本

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)

使用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)
如果您在pycharm中调试脚本,请始终退出

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

与其开发您自己的PID文件解决方案(比您想象的要复杂得多),不如看一看——这是一个进程控制系统,可以很容易地将作业控制和守护程序行为包装到现有的Python脚本中。

该库可以做到这一点

from pid import PidFile

with PidFile():
  do_something()
它还将自动处理pidfile存在但进程未运行的情况。

尝试以下操作:

下面是更有用的代码(检查python是否完全执行脚本):


如果“grep”成功,并且进程“python”当前以脚本名称作为参数运行,则返回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

我自己也遇到了这个老问题,正在寻找解决办法

使用:


我的解决方案是检查进程和命令行参数 在windows和ubuntu linux上测试

import psutil
import os

def is_running(script):
    for q in psutil.process_iter():
        if q.name().startswith('python'):
            if len(q.cmdline())>1 and script in q.cmdline()[1] and q.pid !=os.getpid():
                print("'{}' Process is already running".format(script))
                return True

    return False


if not is_running("test.py"):
    n = input("What is Your Name? ")
    print ("Hello " + n)

这是我在Linux中用来避免在已经运行的情况下启动脚本的方法:

import os
import sys


script_name = os.path.basename(__file__)
pidfile = os.path.join("/tmp", os.path.splitext(script_name)[0]) + ".pid"


def create_pidfile():
    if os.path.exists(pidfile):
        with open(pidfile, "r") as _file:
            last_pid = int(_file.read())

        # Checking if process is still running
        last_process_cmdline = "/proc/%d/cmdline" % last_pid
        if os.path.exists(last_process_cmdline):
            with open(last_process_cmdline, "r") as _file:
                cmdline = _file.read()
            if script_name in cmdline:
                raise Exception("Script already running...")

    with open(pidfile, "w") as _file:
        pid = str(os.getpid())
        _file.write(pid)


def main():
    """Your application logic goes here"""


if __name__ == "__main__":
    create_pidfile()
    main()

这种方法在不依赖外部模块的情况下运行良好

我一直在寻找这个问题的答案,在我看来,我想到了一个非常简单、非常好的解决方案(因为这不可能存在假阳性,我猜-如果程序不这样做,如何更新TXT上的时间戳):

-->根据您的需要,只需在一段时间间隔内将当前时间戳写在TXT上(这里每半个小时就可以了)


如果检查时TXT上的时间戳相对于当前时间戳过期,然后程序出现问题,应该重新启动,或者您更喜欢做什么。

processName会包括我脚本的文件名吗?这取决于您如何启动进程例如:ps ax | grep pythonAre您确定不想让您的进程也用python编写其他进程吗?试试Tendo,创建脚本的单例实例,因此,如果脚本已经在运行,它将不会运行。这不是守护进程的作业,而是启动守护进程的“上层”应用程序的作业。使用systemd或其他工具,如supervisord。不要依赖写入文件的pid。如果你不能使用systemd/supervisord,那么使用锁定来确定它不会被执行两次。我同意,不要重新发明轮子,有很多方法可以对你的应用程序进行后台监控,包括在应用程序死机时重新启动应用程序,在不运行时启动应用程序,等等。如果程序已经崩溃,os.unlink()将不会执行,程序也不会再次运行,因为文件不存在。对吗?正确,但这可能是预期的行为。如果PID文件存在,但内部的PID未运行,则表示非正常关机,这意味着应用程序崩溃。这会让您知道有问题,并检查日志。如前所述,atexit模块也可以处理这个问题,假设这个bug不在Pyth中
ps_command = "ps -o command= %s | grep -Eq 'python .*/%s'" % (pid,script_name)
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
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'])
import psutil
import os

def is_running(script):
    for q in psutil.process_iter():
        if q.name().startswith('python'):
            if len(q.cmdline())>1 and script in q.cmdline()[1] and q.pid !=os.getpid():
                print("'{}' Process is already running".format(script))
                return True

    return False


if not is_running("test.py"):
    n = input("What is Your Name? ")
    print ("Hello " + n)
import os
import sys


script_name = os.path.basename(__file__)
pidfile = os.path.join("/tmp", os.path.splitext(script_name)[0]) + ".pid"


def create_pidfile():
    if os.path.exists(pidfile):
        with open(pidfile, "r") as _file:
            last_pid = int(_file.read())

        # Checking if process is still running
        last_process_cmdline = "/proc/%d/cmdline" % last_pid
        if os.path.exists(last_process_cmdline):
            with open(last_process_cmdline, "r") as _file:
                cmdline = _file.read()
            if script_name in cmdline:
                raise Exception("Script already running...")

    with open(pidfile, "w") as _file:
        pid = str(os.getpid())
        _file.write(pid)


def main():
    """Your application logic goes here"""


if __name__ == "__main__":
    create_pidfile()
    main()