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启动守护进程的更多相关文章

  1. Yii2.0 安装yii2-queue并在Linux启动守护进程监听消息

    一.什么是yii2-queue? Yii2-queue是Yii2.0 PHP框架下一个消息队列拓展插件,支持基于DB, Redis, RabbitMQ, AMQP, Beanstalk 和 Gearm ...

  2. linux 创建守护进程的相关知识

    linux 创建守护进程的相关知识 http://www.114390.com/article/46410.htm linux 创建守护进程的相关知识,这篇文章主要介绍了linux 创建守护进程的相关 ...

  3. 【Linux】- 守护进程的启动方法

    转自:Linux 守护进程的启动方法 Linux中"守护进程"(daemon)就是一直在后台运行的进程(daemon). 本文介绍如何将一个 Web 应用,启动为守护进程. 一.问 ...

  4. asp.net core2.0 部署centos7/linux系统 --守护进程supervisor(二)

    原文:asp.net core2.0 部署centos7/linux系统 --守护进程supervisor(二) 续上一篇文章:asp.net core2.0 部署centos7/linux系统 -- ...

  5. linux C守护进程编写

    linux编程-守护进程编写 守护进程(Daemon)是运行在后台的一种特殊进程.它独立于控制终端并且周期性地执行某种任务或等待 处理某些发生的事件.守护进程是一种很有用的进程. Linux的大多数服 ...

  6. python中的daemon守护进程实现方法

    原文参考:http://blog.csdn.net/tao_627/article/details/49532021 守护进程是生存期长的一种进程.它们独立于控制终端并且周期性的执行某种任务或等待处理 ...

  7. 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修改为具体 ...

  8. Linux Supervisor 守护进程基本配置

    supervisor:C/S架构的进程控制系统,可使用户在类UNIX系统中监控.管理进程.常用于管理与某个用户或项目相关的进程. 组成部分supervisord:服务守护进程supervisorctl ...

  9. Python与Hack之守护进程

    1.什么是守护进程: 在linux或者unix操作系统中,守护进程(Daemon)是一种运行在后台的特殊进程,它独立于控制终端并且周期性的执行某种任务或等待处理某些发生的事件.由于在linux中,每个 ...

随机推荐

  1. 硬件升级win8.1重新安装系统

    上次重装系统一年后升级了硬件配置,双11后,再次折腾系统. 配置硬件的选择 部分配件已经升级过了,之前的一直是AMD平台,发热大功耗高,08年我配的AMD 8450+映泰GX790 128M待机在10 ...

  2. Bootstrap中glyphicons-halflings-regular.woff字体报404错notfound

    今天查看网站的源代码,发现有个glyphicons-halflings-regular.woff文件没有找到,因为我的网站使用了bootstrap的Glyphicons 字体图标,因此需要加载Glyp ...

  3. java list随机打乱

    java list随机打乱package arrlist; import java.util.ArrayList; import java.util.Collections; import java. ...

  4. pageEncoding与contentType属性

    1图例分析 由图中可以看出,这个两个属性没有任何关系. 把这两个设置成不同的编码格式对中文显示不会产生任何影响 2.原因分析 pageEncoding规定了以什么编码方式存储和读取,使两者保持一致性, ...

  5. 如何升级Ceph版本及注意事项

    升级软件版本在日常运维中是一个常见操作. 本文分享一下Ceph版本升级的一些经验. 一般升级流程和注意如下: 1.  关注社区Release notes 和 ceph-user邮件订阅列表,获取社区发 ...

  6. Redis集群(五):集群搭建

    一.本文目的        演示在一台机器上搭建3主3从的redis集群,通过演示了解redis集群的搭建,使用和注意事项     二.搭建说明        1.同一台机器搭建3主3从的伪集群   ...

  7. maven-腾讯SDK(QQ)接口java引入pom配置

    maven的pom.xml配置 <dependency> <groupId>net.gplatform</groupId> <artifactId>Sd ...

  8. Maven2-profile多环境配置

    使用maven管理项目有一个好处是就是可以针对不同的环境使用不同的编译打包设置,方便了多环境下的打包部署,一般我们开发项目都会有至少开发环境和正式环境两个,针对这两个环境的配置信息也会有所不同,比如数 ...

  9. JACASCRIPT--的奇技技巧的44招

    JavaScript是一个绝冠全球的编程语言,可用于Web开发.移动应用开发(PhoneGap.Appcelerator).服务器端开发(Node.js和Wakanda)等等.JavaScript还是 ...

  10. CocoaPods安装使用及上传

    1.升级Ruby环境 sudo gem update --system 如果Ruby没有安装,请参考 如何在Mac OS X上安装 Ruby运行环境 2.安装CocoaPods时我们要访问cocoap ...