Проверить запущен ли скрипт python

Проверьте, работает ли python script

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

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

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

Оставьте 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 (упомянутый выше) может сделать это для вас, или вы можете написать простую оболочку script, чтобы проверить ее для вас, используя код возврата из ps.

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

Для дополнительного кредита вы можете использовать модуль atexit, чтобы гарантировать, что ваша программа очистит свой pidfile при любых обстоятельствах (когда убиты, подняты исключения и т.д.).

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

Читайте также:  Float and integer in python

Вы можете прочитать в документации по socket.close что сокеты автоматически закрываются при сборке мусора.

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

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

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

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

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

В самом деле, если сбой script, появление исключения или очистка файла pid, script будет выполняться несколько раз.

Я предлагаю следующее на другом сайте:

Это проверить, существует ли уже существующий файл блокировки

\#/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 по сравнению с существующим запущенным процессом., избегая двойного выполнения.

Существует множество вариантов. Один из методов – использование системных вызовов или библиотек python, которые выполняют такие вызовы для вас. Другой – это просто создать такой процесс, как:

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

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

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) 

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

Мое решение заключается в проверке аргументов процесса и командной строки. Протестировано на 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) 

Прошел этот старый вопрос, ища решение самостоятельно.

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

Другие ответы отлично подходят для таких вещей, как задания cron, но если вы используете демон, вы должны отслеживать его с помощью daemontools.

если yor debug script в pycharm всегда выходит

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

Вместо того, чтобы разрабатывать собственное решение PID файла (у которого больше тонкостей и угловых случаев, чем вы думаете), посмотрите supervisord – это система управления процессом, которая упрощает перенос управления заданиями и поведения демона вокруг существующего Python script.

#/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 выполняет script):

#! /usr/bin/env python import os from sys import exit def checkPidRunning(pid): global script_name if pid 
ps_command = "ps -o command= %s | grep -Eq 'python .*/%s'" % (pid,script_name) 

возвращает 0, если “grep” успешно, а процесс “python” в настоящее время запущен с именем вашего script в качестве параметра.

Простой пример, если вы ищете только имя процесса:

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 

Рассмотрим следующий пример, чтобы решить вашу проблему:

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

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

Использование bash для поиска процесса с текущим именем script. Нет дополнительного файла.

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 ''| awk ''" % script_name) if l[1]: sys.exit(0); 
stop_if_already_running() print "running normally" while True: time.sleep(3) 

Вот что я использую в 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() 

Этот подход хорошо работает без какой-либо зависимости от внешнего модуля.

Источник

Оцените статью