Проверьте, работает ли python script
У меня есть демон python, запущенный как часть моего веб-приложения/Как я могу быстро проверить (используя python), если мой демон запущен, а если нет, запустите его?
Я хочу сделать это таким образом, чтобы исправить любые сбои демона, и поэтому script не нужно запускать вручную, он будет автоматически запускаться, как только он будет вызываться, а затем останется работать.
Как я могу проверить (используя python), если мой script запущен?
Ответы
Ответ 1
Оставьте 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 при любых обстоятельствах (когда убиты, подняты исключения и т.д.).
Ответ 2
Техника, которая удобна в системе 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
что сокеты автоматически закрываются при сборке мусора.
Ответ 3
Библиотека pid может сделать именно это.
from pid import PidFile
with PidFile():
do_something()
Он также автоматически обрабатывает случай, когда существует файл pidfile, но процесс не запущен.
Ответ 4
Есть очень хорошие пакеты для перезапуска процессов в UNIX. Тот, у которого есть большой учебник по его созданию и настройке, monit. С некоторой настройкой вы можете испытать солидную технологию, поддерживающую ваш демон.
Ответ 5
Конечно, пример от Дэна не будет работать так, как должно быть.
В самом деле, если сбой 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 по сравнению с существующим запущенным процессом., избегая двойного выполнения.
Надеюсь, это поможет.
Ответ 6
Существует множество вариантов. Один из методов - использование системных вызовов или библиотек python, которые выполняют такие вызовы для вас. Другой - это просто создать такой процесс, как:
ps ax | grep processName
и проанализировать вывод. Многие люди выбирают этот подход, это не обязательно плохой подход на мой взгляд.
Ответ 7
Попробуйте эту другую версию
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)
Ответ 8
Я большой поклонник Supervisor для управления демонами. Он написан на Python, поэтому есть много примеров того, как взаимодействовать с Python или расширять его. Для ваших целей API-интерфейс управления XML-RPC должен работать хорошо.
Ответ 9
Мое решение заключается в проверке аргументов процесса и командной строки. Протестировано на 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)
Ответ 10
Прошел этот старый вопрос, ища решение самостоятельно.
Используйте 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'])
Ответ 11
Другие ответы отлично подходят для таких вещей, как задания cron, но если вы используете демон, вы должны отслеживать его с помощью daemontools.
Ответ 12
ps ax | grep processName
если yor debug script в pycharm всегда выходит
pydevd.py --multiproc --client 127.0.0.1 --port 33882 --file processName
Ответ 13
Вместо того, чтобы разрабатывать собственное решение PID файла (у которого больше тонкостей и угловых случаев, чем вы думаете), посмотрите supervisord - это система управления процессом, которая упрощает перенос управления заданиями и поведения демона вокруг существующего Python script.
Ответ 14
попробуйте следующее:
#/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)
Ответ 15
Вот более полезный код (с проверкой, если именно python выполняет script):
#! /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)
возвращает 0, если "grep" успешно, а процесс "python" в настоящее время запущен с именем вашего script в качестве параметра.
Ответ 16
Простой пример, если вы ищете только имя процесса:
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
Ответ 17
Рассмотрим следующий пример, чтобы решить вашу проблему:
#!/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, потому что он может быть выполнен только один раз.
Ответ 18
Использование 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 '{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)
Ответ 19
Вот что я использую в 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()
Этот подход хорошо работает без какой-либо зависимости от внешнего модуля.