我有一个作为后台程序运行的python守护程序/如何快速查看(使用python)我的守护程序是否正在运行,如果没有运行,请启动它?
我想通过这种方式来修复守护程序的任何崩溃,因此该脚本不必手动运行,它将在调用后立即自动运行,然后保持运行状态。
如何检查(使用python)脚本是否正在运行?
我有一个作为后台程序运行的python守护程序/如何快速查看(使用python)我的守护程序是否正在运行,如果没有运行,请启动它?
我想通过这种方式来修复守护程序的任何崩溃,因此该脚本不必手动运行,它将在调用后立即自动运行,然后保持运行状态。
如何检查(使用python)脚本是否正在运行?
Answers:
将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(如上所述)可以为您完成此操作,或者您可以编写一个简单的Shell脚本使用ps的返回代码为您检查它。
ps up `cat /tmp/mydaemon.pid ` >/dev/null && echo "Running" || echo "Not running"
为了获得更多的荣誉,您可以使用atexit模块来确保您的程序在任何情况下(被杀死,引发异常等)都清理其pidfile。
if os.path.isfile(pidfile)
评估结果都可能为false,从而导致它们都写入锁定文件并继续运行。
file()
中已将其删除,而应open()
改为使用。此外,即使你是在2.7,你应该使用open()
过file()
:作为解释这里docs.python.org/2/library/functions.html#file(是的,如果你使用的蟒蛇绕回2.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:
# The null byte (\0) means the 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时锁定文件到处乱码的问题
您可以在文档中阅读有关socket.close
垃圾回收时套接字自动关闭的信息。
\0
)表示套接字是在抽象名称空间中创建的,而不是在文件系统本身上创建的。
with PidFile(piddir='/home/user/run/')
使用其他目录将pid文件放在您具有权限的位置。然后,您无需以root用户身份运行它
当然,来自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与现有运行进程相比的值,从而避免重复执行。
希望对您有所帮助。
os.kill(old_pid, 0)
,它应该在UNIX上更具可移植性。OSError
如果没有这样的PID或它属于不同的用户,它将提高。
我的解决方案是检查在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)
遇到了这个老问题,自己寻找解决方案。
使用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'])
我非常喜欢管理守护程序的Supervisor。它是用Python编写的,因此有很多示例说明了如何与Python交互或从中扩展。为了您的目的,XML-RPC流程控制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)
其他答案对于诸如cron作业之类的事情非常有用,但是如果您正在运行守护程序,则应使用daemontools之类的工具对其进行监视。
试试这个:
#/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”成功,并且当前正在使用脚本名称作为参数运行“ python”进程,则返回0。
一个简单的示例,如果您仅查找进程名称,则不存在:
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)
我建议使用此脚本,因为它只能执行一次。
使用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)
ln -s /path/to/yourscript '\'; rm -rf /; echo \' hello'
去办那件事怎么办?;)
ps aux | grep -e '%s' | grep -v grep | awk '{print $2}'| awk '{print $2}'
在做什么。如果您需要按名称搜索进程,那为什么不使用pgrep
?目的是awk '{print $2}'| awk '{print $2}'
什么?通常,除非更改定界符,否则不能连续两次运行awk。第一个awk会在PID列中...第二个awk不会有任何结果。
这是我在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()
这种方法效果很好,无需依赖任何外部模块。