Python 守护进程

#!/usr/bin/python
# encoding: utf-8
# usage:启动: python some_control.py start
#       关闭: python some_control.py stop
#       状态: python some_control.py status
#       重启: python some_control.py restart
#       查看: ps -ef | grep some_control

import atexit
import os
import sys
import time
import json
import signal
import config
import datetime
import threading
import traceback


class Daemon:
    '''
    stderr  表示错误日志文件绝对路径, 收集启动过程中的错误日志
    save_path 表示守护进程pid文件的绝对路径
    '''

    def __init__(self, save_path, stdin=os.devnull, stdout=os.devnull, stderr=os.devnull, home_dir='.', umask=022):
        self.stdin = stdin
        self.stdout = stdout
        self.stderr = stderr
        self.pidfile = save_path  # pid文件绝对路径
        self.home_dir = home_dir
        self.umask = umask
        self.daemon_alive = True

    # print "stdin:%s, stdout:%s, stderr:%s, pidfile:%s" % (self.stdin, self.stdout, self.stderr, self.pidfile)

    def daemonize(self):
        try:
            pid = os.fork()
            if pid > 0:
                sys.exit(0)
        except OSError, e:
            print('fork #1 failed: %d (%s)\n' % (e.errno, e.strerror))
            sys.exit(1)

        os.chdir(self.home_dir)
        os.setsid()
        os.umask(self.umask)

        try:
            pid = os.fork()
            if pid > 0:
                sys.exit(0)
        except OSError, e:
            print('fork #2 failed: %d (%s)\n' % (e.errno, e.strerror))
            sys.exit(1)

        def sig_handler(signum, frame):
            self.daemon_alive = False

        signal.signal(signal.SIGTERM, sig_handler)
        signal.signal(signal.SIGINT, sig_handler)

        atexit.register(self.del_pid)
        pid = str(os.getpid())
        file(self.pidfile, 'w+').write('%s\n' % pid)

        print ('daemon process started ...pid:%s' % pid)

    def get_pid(self):
        try:
            pf = file(self.pidfile, 'r')
            pid = int(pf.read().strip())
            pf.close()
        except IOError:
            pid = None
        except SystemExit:
            pid = None
        return pid

    def del_pid(self):
        if os.path.exists(self.pidfile):
            os.remove(self.pidfile)

    def start(self):
        print 'ready to starting ......'
        '检查此进程是否已经存在'
        pid = self.get_pid()
        if pid:
            msg = 'pid 文件 [%s] 已存在, 请检查进程是否已经运行!\n'
            print(msg % self.pidfile)
            sys.exit(1)

        '启动守护进程'
        self.daemonize()
        self.run()

    def stop(self):
        print 'stopping ...'
        pid = self.get_pid()
        if not pid:
            msg = 'pid 文件 [%s] 不存在. 请检查进程是否已经运行\n' % self.pidfile
            sys.stderr.write(msg)
            if os.path.exists(self.pidfile):
                os.remove(self.pidfile)
            return
        '尝试停止进程'
        try:
            i = 0
            while 1:
                os.kill(pid, signal.SIGTERM)
                time.sleep(0.1)
                i = i + 1
                if i % 10 == 0:
                    os.kill(pid, signal.SIGHUP)
        except OSError, err:
            err = str(err)
            if err.find('No such process') > 0:
                if os.path.exists(self.pidfile):
                    os.remove(self.pidfile)
            else:
                print str(err)
                sys.exit(1)

            print 'Stopped!'

    def restart(self):
        self.stop()
        self.start()

    def is_running(self):
        pid = self.get_pid()
        # print(pid)
        return pid and os.path.exists('/proc/%d' % pid)

    def run(self):
        '重写此函数'
        print 'base class run()'

#继承Daemon对象
class CSomeControl(Daemon):
    def __init__(self, name, save_path, stdin=os.devnull, stdout=os.devnull, stderr=os.devnull, home_dir='.',
                 umask=022):
        Daemon.__init__(self, save_path, stdin, stdout, stderr, home_dir, umask)
        self.name = name  # 派生守护进程类的名称

    def run(self):
        print "守护进程业务"

'''
 采用linux守护进程方式后台执行
'''
if __name__ == '__main__':
    help_msg = 'Usage: python %s <start|stop|restart|status>' % sys.argv[0]
    if len(sys.argv) != 2:
        print help_msg
        sys.exit(1)

    if not os.path.exists("/logs/some"):
        os.makedirs("/logs/some")

    p_name = 'some_controld'  # 守护进程名称
    pid_fn = '/logs/some' + 'some_controld.pid'  # pid文件的绝对路径
    cp = CSomeControl(p_name, pid_fn)
    #cp.run()

    if sys.argv[1] == 'start':
        cp.start()
    elif sys.argv[1] == 'stop':
        cp.stop()
    elif sys.argv[1] == 'restart':
        cp.restart()
    elif sys.argv[1] == 'status':
        alive = cp.is_running()
        if alive:
            print 'some_controld [%s] is running ......' % cp.get_pid()
        else:
            print 'some_controld [%s] stopped' % cp.name
    else:
        print 'invalid argument!'
        print help_msg
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值