source

python 스크립트가 실행 중인지 확인합니다.

ittop 2023. 10. 14. 10:37
반응형

python 스크립트가 실행 중인지 확인합니다.

웹 앱의 일부로 파이썬 데몬이 실행 중입니다./ 데몬이 실행 중인지(파이썬을 사용하여) 빠르게 확인하고 실행하지 않으면 실행하려면 어떻게 해야 합니까?

데몬의 충돌을 해결하기 위해 그렇게 하고 싶습니다. 따라서 스크립트를 수동으로 실행할 필요가 없습니다. 스크립트가 호출되는 즉시 자동으로 실행되고 실행 상태를 유지합니다.

스크립트가 실행 중인지(python 사용) 확인하려면 어떻게 해야 합니까?

리눅스 시스템에서 편리한 기술은 도메인 소켓을 사용하는 것입니다.

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로 전송될 경우 잠금 파일이 주변에 방치되는 문제를 방지합니다.

가비지를 수집할 때 소켓이 자동으로 닫히는 경우 설명서에서 확인할 수 있습니다.

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(위에서 언급한)이 대신 할 수도 있고, 간단한 셸 스크립트를 작성하여 ps에서 반환 코드를 사용하여 확인할 수도 있습니다.

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

추가 크레딧을 위해 atexit 모듈을 사용하여 어떤 상황에서도 프로그램이 pid 파일을 정리할 수 있습니다(죽었을 때, 예외 사항이 제기된 경우 등).

pid 라이브러리는 정확히 이것을 할 수 있습니다.

from pid import PidFile

with PidFile():
  do_something()

또한 pid 파일이 존재하지만 프로세스가 실행되지 않는 경우도 자동으로 처리됩니다.

나의 해결책은 프로세스와 명령줄 인수를 확인하는 것입니다. 윈도우와 우분투 리눅스에서 테스트되었습니다.

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)

물론 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 값을 확인하여 이중 실행을 방지합니다.

도움이 되었으면 좋겠습니다.

UNIX에서 프로세스를 재시작하기 위한 매우 좋은 패키지가 있습니다.구축 및 구성에 대한 훌륭한 튜토리얼이 있는 것은 monit입니다.약간의 조정을 통해 강력하고 검증된 기술로 데몬을 유지할 수 있습니다.

제가 해결책을 찾고 있는 이 오래된 질문을 우연히 발견했습니다.

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

다양한 선택지가 있습니다.한 가지 방법은 시스템 호출이나 이러한 호출을 수행하는 파이썬 라이브러리를 사용하는 것입니다.다른 하나는 단순히 다음과 같은 프로세스를 생성하는 것입니다.

ps ax | grep processName

출력을 파싱합니다.많은 사람들이 이 방법을 선택하는데, 제가 보기에는 반드시 나쁜 방법은 아닙니다.

저는 데몬을 관리하는 슈퍼바이저의 열렬한 팬입니다.Python으로 작성되어 있어서 Python과 상호 작용하거나 확장하는 방법에 대한 예시가 많습니다.당신의 목적을 위해서 XML-RPC process control API가 잘 작동해야 합니다.

이 다른 버전을 사용해 보십시오.

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)

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 하는 데 이 되기도 합니다.

자체 PID 파일 솔루션을 개발하는 대신(생각보다 더 많은 미묘함과 코너 케이스를 가지고 있음) 슈퍼바이저를 살펴보십시오. 이는 기존 Python 스크립트에 작업 제어 및 데몬 동작을 쉽게 랩핑할 수 있는 프로세스 제어 시스템입니다.

다른 대답은 cron 작업과 같은 경우에 좋습니다. 하지만 데몬을 실행하는 경우 데몬툴과 같은 것으로 모니터링해야 합니다.

ps ax | grep processName

pycharm의 debug 스크립트가 항상 종료되는 경우

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

시도해 보십시오.

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

문자열은 다음과 같습니다.

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

저는 이에 대한 답을 찾고 있었는데, 제 경우에는 매우 쉽고 매우 좋은 해결책이 떠올랐다고 생각합니다. (이에 대해 오탐이 존재하는 것은 불가능하기 때문에, 프로그램이 이를 수행하지 않을 경우 TXT의 타임스탬프가 어떻게 업데이트될 수 있을까 하는 생각이 듭니다.

--> TXT에 필요에 따라 일정 시간 간격으로 현재 타임스탬프를 계속 적습니다(여기서는 매 30분이 완벽했습니다).

확인할 때 TXT의 타임스탬프가 현재 타임스탬프보다 상대적으로 오래된 경우 프로그램에 문제가 발생하여 다시 시작하거나 원하는 작업을 수행해야 합니다.

문제를 해결하기 위해 다음 예를 생각해 보십시오.

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

이 대본은 한 번만 실행할 수 있기 때문에 추천합니다.

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)

이미 실행 중인 경우 스크립트를 시작하지 않기 위해 리눅스에서 사용하는 방법은 다음과 같습니다.

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

이 방법은 외부 모듈에 의존하지 않고 효과가 좋습니다.

언급URL : https://stackoverflow.com/questions/788411/check-to-see-if-python-script-is-running

반응형