web-dev-qa-db-ja.com

pythonスクリプトが実行されているかどうかを確認する

pythonデーモンをWebアプリの一部として実行しています/デーモンが実行されているかどうかを(pythonを使用して)すばやく確認し、実行されていない場合は起動するにはどうすればよいですか?

デーモンのクラッシュを修正するためにそのようにしたいので、スクリプトを手動で実行する必要はありません。スクリプトが呼び出されるとすぐに自動的に実行され、実行されたままになります。

スクリプトが実行されているかどうかを(Pythonを使用して)確認するにはどうすればよいですか?

89
Josh Hunt

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(上記)がこれを行うことができます。または、psからの戻りコードを使用して、単純なシェルスクリプトを作成して確認することができます。

ps up `cat /tmp/mydaemon.pid ` >/dev/null && echo "Running" || echo "Not running"

信用を高めるために、atexitモジュールを使用して、プログラムがどのような状況(強制終了時、例外発生時など)でも確実にpidfileをクリーンアップできるようにします。

88
Dan Udey

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が送信された場合にロックファイルが横たわる問題を回避します。

socket.closeのドキュメントを読む ガベージコレクション時にソケットが自動的に閉じられるようにできます。

141
aychedee

pid ライブラリはまさにこれを行うことができます。

from pid import PidFile

with PidFile():
  do_something()

また、pidfileは存在するがプロセスが実行されていない場合も自動的に処理します。

17
Decko

もちろん、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の値をチェックし、二重実行を回避します。

私はそれが役立つことを願っています。

10
Shylock

UNIXでプロセスを再起動するための非常に優れたパッケージがあります。 monit の構築と設定に関する優れたチュートリアルがあります。微調整を行うと、デーモンを維持する確かな実績のあるテクノロジーを使用できます。

10
ojblass

無数のオプションがあります。 1つの方法は、システムコールまたはpythonこのような呼び出しを実行するライブラリを使用します。もう1つの方法は、次のようなプロセスを生成することです。

ps ax | grep processName

出力を解析します。多くの人がこのアプローチを選択しますが、私の考えでは必ずしも悪いアプローチではありません。

4
BobbyShaftoe

この他のバージョンを試してください

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 __== '__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)
3
debuti

私の解決策は、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)
3
kabapy

私はデーモンを管理するための Supervisor の大ファンです。 Pythonで書かれているため、Pythonとやり取りしたり、Pythonから拡張したりする方法の例はたくさんあります。あなたの目的のために XML-RPCプロセス制御API はうまく機能するはずです。

2
Matt Good

独自のPIDファイルソリューションを開発するのではなく(あなたが思うよりも微妙でコーナーケースが多い)、 supervisord を見てください。これは、ジョブ制御を簡単にラップできるプロセス制御システムです。既存のPythonスクリプトの周りのデーモンの動作。

1
Chris Johnson

自分で解決策を探しているこの古い質問に出くわしました。

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'])
1
NST

プロセス名が存在するかどうかだけを探している場合の簡単な例:

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
Tomba

次に、より便利なコードを示します(正確に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 __== '__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を返します。

0
Dmitry Allyanov

他の答えはcronジョブなどには最適ですが、デーモンを実行している場合は、 daemontools のようなもので監視する必要があります。

0
bobpoekert

これを試して:

#/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
MrRolling
ps ax | grep processName

pycharmのyorデバッグスクリプトが常に終了する場合

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