Проверьте, запущен ли скрипт Python - PullRequest
85 голосов
/ 25 апреля 2009

У меня есть демон python, работающий как часть моего веб-приложения / Как я могу быстро проверить (используя python), работает ли мой демон и, если нет, запустить его?

Я хочу сделать это таким образом, чтобы исправить любые сбои демона, и поэтому скрипт не нужно запускать вручную, он автоматически запустится, как только он будет вызван, а затем продолжит работу.

Как я могу проверить (используя python), работает ли мой скрипт?

Ответы [ 19 ]

137 голосов
/ 13 октября 2011

Техника, которая удобна в системе 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, что сокеты автоматически закрываются при сборке мусора.

85 голосов
/ 25 апреля 2009

Перетащите 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-файл при любых обстоятельствах (при уничтожении, возникновении исключений и т. Д.).

16 голосов
/ 09 октября 2015

Библиотека pid может сделать именно это.

from pid import PidFile

with PidFile():
  do_something()

Он также автоматически обрабатывает случай, когда pid-файл существует, но процесс не запущен.

10 голосов
/ 27 ноября 2010

Конечно, пример с Дэном не будет работать так, как должно быть.

Действительно, если скрипт завершится аварийно, вырастет исключение или не очистит 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 голосов
/ 25 апреля 2009

В UNIX есть очень хорошие пакеты для перезапуска процессов. Тот, у которого есть большое руководство по созданию и настройке, это monit . С некоторыми изменениями вы можете получить надежную проверенную технологию, поддерживающую вашего демона.

4 голосов
/ 25 апреля 2009

Есть множество вариантов. Одним из методов является использование системных вызовов или библиотек Python, которые выполняют такие вызовы для вас. Другой - просто создать такой процесс, как:

ps ax | grep processName

и разобрать вывод. Многие люди выбирают этот подход, на мой взгляд, это не обязательно плохой подход.

3 голосов
/ 02 октября 2012

Попробуйте эту другую версию

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)
2 голосов
/ 26 апреля 2009

Я большой поклонник Супервизор для управления демонами. Он написан на Python, поэтому существует множество примеров того, как взаимодействовать с ним или расширять его с помощью Python. Для ваших целей API управления процессом XML-RPC должен работать хорошо.

2 голосов
/ 27 апреля 2018

Мое решение - проверить аргументы процесса и командной строки Протестировано на 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)
1 голос
/ 06 июня 2017

Наткнулся на этот старый вопрос в поисках решения сам.

Использование 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'])
...