python实现Linux启动守护进程
python实现Linux启动守护进程
DaemonClass.py代码:
#/usr/bin/env python
# -*- coding: utf-8 -*- import sys
import os
import time
import atexit
import subprocess
from signal import SIGTERM BaseDir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) DIRS = {'ROOT': BaseDir,
'PID': '%s/var/guard.pid' % BaseDir,
} class Daemon(object):
"""
daemon class.
Usage: subclass the Daemon class and override the _run() method
"""
def __init__(self, stdin='/dev/null', stdout='/dev/null', stderr='/dev/null'):
self.stdin = stdin
self.stdout = stdout
self.stderr = stderr
self.pidfile = DIRS['PID'] def _daemonize(self):
"""
@guard 守护进程主方法
"""
# 脱离父进程
try:
pid = os.fork()
print("[_daemonize]pid:%s" % pid)
if pid > 0:
sys.exit(0)
except OSError as e:
sys.stderr.write("[_daemonize]fork #1 failed: %d (%s)\n" % (e.errno, e.strerror))
print("[_daemonize]fork #1 failed:"+str(e.strerror))
sys.exit(1) # 脱离终端
os.setsid()
# 修改当前工作目录
os.chdir(DIRS['ROOT'])
# 加载环境变量
guardpath = DIRS['ROOT'] sys.path.append(guardpath)
# 重设文件创建权限
os.umask(0) # 第二次fork,禁止进程重新打开控制终端
try:
pid = os.fork()
if pid > 0:
sys.exit(0)
except OSError as e:
sys.stderr.write("[_daemonize]fork #2 failed: %d (%s)\n" % (e.errno, e.strerror))
print("[_daemonize]fork #2 failed:"+str(e.strerror))
sys.exit(1) sys.stdout.flush()
sys.stderr.flush() # 重定向文件描述符
with open(self.stdin, 'rb', 0) as f:
os.dup2(f.fileno(), sys.stdin.fileno())
with open(self.stdout, 'ab', 0) as f:
os.dup2(f.fileno(), sys.stdout.fileno())
with open(self.stderr, 'ab', 0) as f:
os.dup2(f.fileno(), sys.stderr.fileno()) # 注册程序退出时的函数,即删掉pid文件
atexit.register(lambda: os.remove(self.pidfile))
pid = str(os.getpid())
file(self.pidfile, 'w+').write("%s\n" % pid) def start(self):
"""
Start the daemon
"""
# Check for a pidfile to see if the daemon already runs
try:
with open(self.pidfile, 'r') as pf:
pid = int(pf.read().strip())
except IOError as e:
pid = None
print("daemon ioerror :"+str(e)) if pid:
message = "Start error,pidfile %s already exist. Daemon already running?\n"
print(message)
sys.stderr.write(message % self.pidfile)
sys.exit(1) # Start the daemon
self._daemonize()
self._run() def stop(self):
"""
Stop the daemon
"""
# Get the pid from the pidfile
try:
with open(self.pidfile, 'r') as pf:
pid = int(pf.read().strip())
except IOError as err:
pid = None
print(err) if not pid:
message = "pidfile %s does not exist. Daemon not running?\n" % self.pidfile
print(message)
sys.stderr.write(message)
return # not an error in a restart
# Try killing the daemon process
try:
while 1:
os.kill(pid, SIGTERM)
time.sleep(0.1)
except OSError as err:
err = str(err)
if err.find("No such process") > 0:
if os.path.exists(self.pidfile):
os.remove(self.pidfile)
else:
print('Stop error,'+str(err))
sys.exit(1) def status(self):
"""
Status the daemon
"""
# Get the pid from the pidfile
try:
with open(self.pidfile, 'r') as pf:
pid = int(pf.read().strip())
except IOError as err:
pid = None
print(err) if not pid:
message = "pidfile %s does not exist. Daemon not running?\n" % self.pidfile
print(message)
sys.stderr.write(message)
else:
p = subprocess.Popen('ps -ef|grep %s |grep -v grep' % pid, shell=True,
stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
lines = p.stdout.readlines()
print(lines)
if len(lines) > 0:
message = "pidfile %s exist. Daemon running!\n" % self.pidfile
print(message)
sys.stdout.write(message)
else:
message = "pidfile %s exist. But pid not exist, please administrator check process\n" % self.pidfile
print(message)
sys.stderr.write(message) def restart(self):
"""
Restart the daemon
"""
self.stop()
time.sleep(0.1)
self.start() def _run(self):
"""
You should override this method when you subclass Daemon. It will be called after the process has been
daemonized by start() or restart().
"""
raise NotImplementedError
MainClass.py 继承Daemon类
#/usr/bin/env python
# -*- coding: utf-8 -*- import sys
from DaemonClass import *
import time
import subprocess class ArgvHandler(Daemon):
"""
help_msg: 帮助方法
parse_argv: 参数检查
""" def __init__(self, argv_list):
Daemon.__init__(self)
self.argvs = argv_list
print("程序输入参数:%s" % self.argvs)
self.parse_argv() def parse_argv(self):
"""
:return: 获取执行程序后面的参数值,如果没有打印帮助内容
"""
if len(self.argvs) > 1:
if hasattr(self, self.argvs[1]):
func = getattr(self, self.argvs[1])
func()
else:
self.help_msg()
else:
self.help_msg() def help_msg(self):
print "Unknow Command!"
print "Usage: %s start|stop|restart|status" % self.argvs[0] def _run(self):
"""
监控入口
"""
MonitorRun() def MonitorRun():
while 1:
monitor_process('进程名')
time.sleep(600) def monitor_process(processname):
# 进程数量判断
try:
p = subprocess.Popen('ps -ef|grep %s |grep -v grep' % processname, shell=True,
stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
lines = p.stdout.readlines() if len(lines) == 1:
print("进程名:%s, 数量:%s" % (processname, len(lines)))
return
else:
print("进程名:%s, 数量:%s" % (processname, len(lines)))
message = 'process[%s] is lost' % (processname)
print(message)
return message
except Exception as err:
message = "[monitor_process]%s" % err
print(message)
sys.stderr.write(message)
启动程序入口
#/usr/bin/env python
# -*- coding: utf-8 -*- import os
import sys
import platform if platform.system() == "Windows":
BASE_DIR = '\\'.join(os.path.abspath(os.path.dirname(__file__)).split('\\')[:-1])
else: # for linux
BASE_DIR = '/'.join(os.path.abspath(os.path.dirname(__file__)).split('/')[:-1])
sys.path.append(BASE_DIR) from lib import MainClass if __name__ == '__main__': MainClass.ArgvHandler(sys.argv)
参考文档:
http://blog.csdn.net/taiyang1987912/article/details/44850999
http://python3-cookbook-zh.readthedocs.io/zh_CN/latest/c12/p14_launching_daemon_process_on_unix.html
python实现Linux启动守护进程的更多相关文章
- Yii2.0 安装yii2-queue并在Linux启动守护进程监听消息
一.什么是yii2-queue? Yii2-queue是Yii2.0 PHP框架下一个消息队列拓展插件,支持基于DB, Redis, RabbitMQ, AMQP, Beanstalk 和 Gearm ...
- linux 创建守护进程的相关知识
linux 创建守护进程的相关知识 http://www.114390.com/article/46410.htm linux 创建守护进程的相关知识,这篇文章主要介绍了linux 创建守护进程的相关 ...
- 【Linux】- 守护进程的启动方法
转自:Linux 守护进程的启动方法 Linux中"守护进程"(daemon)就是一直在后台运行的进程(daemon). 本文介绍如何将一个 Web 应用,启动为守护进程. 一.问 ...
- asp.net core2.0 部署centos7/linux系统 --守护进程supervisor(二)
原文:asp.net core2.0 部署centos7/linux系统 --守护进程supervisor(二) 续上一篇文章:asp.net core2.0 部署centos7/linux系统 -- ...
- linux C守护进程编写
linux编程-守护进程编写 守护进程(Daemon)是运行在后台的一种特殊进程.它独立于控制终端并且周期性地执行某种任务或等待 处理某些发生的事件.守护进程是一种很有用的进程. Linux的大多数服 ...
- python中的daemon守护进程实现方法
原文参考:http://blog.csdn.net/tao_627/article/details/49532021 守护进程是生存期长的一种进程.它们独立于控制终端并且周期性的执行某种任务或等待处理 ...
- hadoop启动守护进程报JAVA_HOME is not set and could not be found
hadoop启动守护进程 sbin/start-dfs.sh 报如下错误:JAVA_HOME is not set and could not be found 解决办法(JAVA_HOME修改为具体 ...
- Linux Supervisor 守护进程基本配置
supervisor:C/S架构的进程控制系统,可使用户在类UNIX系统中监控.管理进程.常用于管理与某个用户或项目相关的进程. 组成部分supervisord:服务守护进程supervisorctl ...
- Python与Hack之守护进程
1.什么是守护进程: 在linux或者unix操作系统中,守护进程(Daemon)是一种运行在后台的特殊进程,它独立于控制终端并且周期性的执行某种任务或等待处理某些发生的事件.由于在linux中,每个 ...
随机推荐
- JNI系列——简便开发流程
1.编写Java代码 2.选中工程目录--右键单击Android Tools--Add Native Support 3.输入要生成的库名 4.到工程目录中jni目录下对自动生成文件和.mk文件进行相 ...
- springMVC+mybatis 增删该操作后判断影响行数一直返回-2147482646
MyBatis发现更新和插入返回值一直为"-2147482646"的错误是由defaultExecutorType设置引起的,如果设置为BATCH,更新返回值就会丢失.mybati ...
- vmware 虚拟机克隆之后配IP重启网络失败
在日常实验中,我新安装了一个虚拟机(全新的)node1,然后为了实验,又克隆了一天虚拟机node2 然后我给两台机器设置IP和主机名node1 : 192.168.220.128 node2 : 1 ...
- [转] easyui 获取数据表格中选中行的数据 Get selected row data from...
原文地址:http://my.oschina.net/meSpace/blog/41463 http://www.easyui.net/2010/06/easyui-tutorial-get-sele ...
- git 删除和重命名文件
1. 删除文件 git rm a.txt git rm--cached filename 会删除索引中的文件并把它保留在工作目录中 而 git rm 则会将文件从索引和工作目录中都删除 文件删除后的恢 ...
- 浅谈HTTP请求头content-type
请求消息和响应消息都可以包含实体信息,实体信息一般由实体头域和实体组成.实体头域包含关于实体的原信息,实体头包括Allow.Content- Base.Content-Encoding.Content ...
- Entity Framework在WCF中序列化的问题
问题描述 如果你在WCF中用Entity Framework来获取数据并返回实体对象,那么对下面的错误一定不陌生. 接收对 http://localhost:5115/ReService.svc 的 ...
- Java-开启一个新的线程
java实现多线程有2种方法:1扩展java.lang.Thread类:2实现java.lang.Runnable接口 下面举个例子,实现Runnable,来实现多线程 public class Do ...
- Thinking in java学习笔记之垃圾回收器如何工作
垃圾回收器使得java在堆上分配空间的速度可以和其他语言从堆栈上分配空间的速度媲美.
- Cell右滑的动作状态
//允许cell可以进行编辑 - (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)index ...