代码之家  ›  专栏  ›  技术社区  ›  Josh Hunt bstahlhood

检查python脚本是否正在运行

  •  129
  • Josh Hunt bstahlhood  · 技术社区  · 17 年前

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

    21 回复  |  直到 7 年前
        1
  •  164
  •   HoldOffHunger Lux    5 年前

    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时,锁文件到处乱放的问题

    你可以 read in the documentation for socket.close 当垃圾被回收时,插座会自动关闭。

        2
  •  106
  •   rightfold Eugene Lazutkin    10 年前

    将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模块来确保您的程序在任何情况下(当被杀死、引发异常等时)都能清理其pidfile。

        3
  •  26
  •   Decko    10 年前

    pid

    from pid import PidFile
    
    with PidFile():
      do_something()
    

    它还将自动处理pidfile存在但进程未运行的情况。

        4
  •  11
  •   Tapajit Dey Shylock    12 年前

    我的解决方案是检查进程和命令行参数 在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)
    
        5
  •  10
  •   ojblass    17 年前

    当然,丹的例子不会像它应该的那样起作用。

    我建议以下内容来自另一个网站:

    这是为了检查是否已经存在锁文件

    \#/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"))
    

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

    此代码将检查与现有运行进程相比的pid值。避免双重执行。

    我希望这会有所帮助。

        6
  •  8
  •   kabapy    8 年前

    在UNIX上重启进程有很多很好的软件包。有一个关于构建和配置它的很好的教程是 monit 通过一些调整,你可以拥有一种坚如磐石的成熟技术来保持你的守护进程。

        7
  •  6
  •   BobbyShaftoe    17 年前

    我自己也遇到了这个老问题,正在寻找解决方案。

    使用 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'])
    
        8
  •  6
  •   NST    9 年前

    ps ax | grep processName
    

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

        9
  •  2
  •   Matt Good    17 年前
        10
  •  2
  •   debuti    13 年前

    尝试其他版本

    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)
    
        11
  •  1
  •   Chris Johnson user3351229    11 年前

    一种便携式解决方案,依赖于 multiprocessing.shared_memory :

    import atexit
    from multiprocessing import shared_memory
    
    _ensure_single_process_store = {}
    
    
    def ensure_single_process(name: str):
        if name in _ensure_single_process_store:
            return
        try:
            shm = shared_memory.SharedMemory(name='ensure_single_process__' + name,
                                             create=True,
                                             size=1)
        except FileExistsError:
            print(f"{name} is already running!")
            raise
        _ensure_single_process_store[name] = shm
        atexit.register(shm.unlink)
    

    通常你不必使用 atexit ,但有时它有助于在异常退出时进行清理。

        12
  •  0
  •   bobpoekert    14 年前

    与其开发自己的PID文件解决方案(它比你想象的有更多的微妙之处和极端情况),不如看看 supervisord --这是一个过程控制系统,可以很容易地将作业控制和守护进程行为包裹在现有的Python脚本周围。

        13
  •  0
  •   user3366072    12 年前

    其他答案对于像cron作业这样的事情来说很好,但如果你正在运行一个守护进程,你应该用类似的东西来监视它 daemontools .

        14
  •  0
  •   MrRolling    9 年前
    ps ax | grep processName
    

    pydevd.py --multiproc --client 127.0.0.1 --port 33882 --file processName
    
        15
  •  0
  •   Dmitry Allyanov    9 年前

    #/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)
    
        16
  •  0
  •   Tomba    9 年前

    以下是更有用的代码(检查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)
    

    这是字符串:

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

    如果“grep”成功,并且进程“python”当前正在以脚本名称作为参数运行,则返回0。

        17
  •  0
  •   Edw590    5 年前

    一个简单的例子,如果你只是在寻找一个进程名称是否存在:

    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
    
        18
  •  -1
  •   octopusgrabbus ufukgun    14 年前

    我一直在寻找这个问题的答案,在我看来,我想到了一个非常简单和很好的解决方案(因为在这个问题上不可能存在误报,我想——如果程序不这样做,TXT上的时间戳怎么能更新呢):

    -->根据您的需要,在TXT上继续写下某个时间间隔内的当前时间戳(这里每半小时一次是完美的)。

    如果检查时TXT上的时间戳相对于当前时间戳已经过时,则程序存在问题,应该重新启动或执行您喜欢的操作。

        19
  •  -1
  •   Jerome Jaglale theRana    13 年前

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

    我建议使用这个脚本,因为它只能执行一次。

        20
  •  -1
  •   SH_Rohit    8 年前

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