继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

用python编写daemon监控进程并自动恢复(附Shell版)

holdtom
关注TA
已关注
手记 1842
粉丝 240
获赞 991


因为hadoop集群中datanode是大量存在的,那么多机器,什么事都可能发生,最通常的大概就是进程挂掉了。所以为了省事,参考别人的代码写了这个监控进程的daemon。当然,稍加修改就可以用来监控别的必须常驻的进程。只需start,不用后面跟&或者前面加nohup。

其实很多人都对进程挂掉很头疼,没事半夜得爬起来上服务器启动进程是一件非常痛苦的事情。

每2秒监测一次进程,发现进程消失就重启进程。主要原理是fork出子进程,然后将子进程挂起,并退出父进程。其程序本身作为被监控进程的外壳程序存在。

#!/usr/bin/env python

import sys, os, time, atexit, string

from signal import SIGTERM 

class Daemon:

  def __init__(self, pidfile, stdin='/dev/null', stdout='/dev/null', stderr='/dev/null'):

    #需要获取调试信息,改为stdin='/dev/stdin', stdout='/dev/stdout', stderr='/dev/stderr',以root身份运行。

    self.stdin = stdin

    self.stdout = stdout

    self.stderr = stderr

    self.pidfile = pidfile

  

  def _daemonize(self):

    try: 

      pid = os.fork() 

      if pid > 0:

        #退出主进程

        sys.exit(0) 

    except OSError, e:

      sys.stderr.write('fork #1 failed: %d (%s)\n' % (e.errno, e.strerror))

      sys.exit(1)

  

    os.chdir("/") 

    os.setsid() 

    os.umask(0) 

  

    #创建子进程

    try: 

      pid = os.fork() 

      if pid > 0:

        sys.exit(0) 

    except OSError, e: 

      sys.stderr.write('fork #2 failed: %d (%s)\n' % (e.errno, e.strerror))

      sys.exit(1) 

  

    #重定向文件描述符

    sys.stdout.flush()

    sys.stderr.flush()

    si = file(self.stdin, 'r')

    so = file(self.stdout, 'a+')

    se = file(self.stderr, 'a+', 0)

    os.dup2(si.fileno(), sys.stdin.fileno())

    os.dup2(so.fileno(), sys.stdout.fileno())

    os.dup2(se.fileno(), sys.stderr.fileno())

  

    #创建processid文件

    atexit.register(self.delpid)

    pid = str(os.getpid())

    file(self.pidfile,'w+').write('%s\n' % pid)

  

  def delpid(self):

    os.remove(self.pidfile)

  def start(self):

    #检查pid文件是否存在以探测是否存在进程

    try:

      pf = file(self.pidfile,'r')

      pid = int(pf.read().strip())

      pf.close()

    except IOError:

      pid = None

  

    if pid:

      message = 'pidfile %s already exist. Daemon already running?\n'

      sys.stderr.write(message % self.pidfile)

      sys.exit(1)

    

    #启动监控

    self._daemonize()

    self._run()

  def stop(self):

    #从pid文件中获取pid

    try:

      pf = file(self.pidfile,'r')

      pid = int(pf.read().strip())

      pf.close()

    except IOError:

      pid = None

  

    if not pid:

      message = 'pidfile %s does not exist. Daemon not running?\n'

      sys.stderr.write(message % self.pidfile)

      return #重启不报错

    #杀进程

    try:

      while 1:

        os.kill(pid, SIGTERM)

        time.sleep(0.1)

        os.system('/opt/modules/hadoop/hadoop-0.20.203.0/bin/hadoop-daemon.sh stop datanode')

        os.system('/opt/modules/hadoop/hadoop-0.20.203.0/bin/hadoop-daemon.sh stop tasktracker')

    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)

  def restart(self):

    self.stop()

    self.start()

  def _run(self):

    while True:

      datanode = os.popen('ps -fe | grep "java" | grep "datanode" | grep -v "grep" | wc -l').read().strip()

      tasktracker = os.popen('ps -fe | grep "java" | grep "tasktracker" | grep -v "grep" | wc -l').read().strip()

      #选出进程中含有java且含有datanode|tasktracker且不含有grep,计算出现行数。修改上面的进程监控语句以适应其他应用需求

                 if datanode == '0':

                                 os.system('/opt/modules/hadoop/hadoop-0.20.203.0/bin/hadoop-daemon.sh start datanode')

          #修改这里的启动命令

                 if tasktracker == '0':

                                 os.system('/opt/modules/hadoop/hadoop-0.20.203.0/bin/hadoop-daemon.sh start tasktracker')

          #修改这里的启动命令

      time.sleep(2)

      #修改这里的停留时间

    

    

if __name__ == '__main__':

        daemon = Daemon('/tmp/watch_process.pid')

        if len(sys.argv) == 2:

                if 'start' == sys.argv[1]:

                        daemon.start()

                elif 'stop' == sys.argv[1]:

                        daemon.stop()

                elif 'restart' == sys.argv[1]:

                        daemon.restart()

                else:

                        print 'Unknown command'

                        sys.exit(2)

                sys.exit(0)

        else:

                print 'usage: %s start|stop|restart' % sys.argv[0]

                sys.exit(2)

实际使用中还是比较好用的,把该程序加入到启动文件中,重启服务器,服务器重启后会自动启动其所监控的进程。用到的都是python的基本模块,不会存在依赖缺失问题。

#/bin/sh

while true;

do

  count=`ps -fe | grep "java" | grep "datanode" | grep -v "grep"`

  if [ "$?" != "0" ]; then

    /opt/modules/hadoop/hadoop-0.20.203.0/bin/hadoop-daemon.sh start datanode

  fi

  sleep 2

done

-----------------------------------

#/bin/sh

while true;

do

  count=`ps -fe | grep "java" | grep "tasktracker" | grep -v "grep"`

  if [ "$?" != "0" ]; then

    /opt/modules/hadoop/hadoop-0.20.203.0/bin/hadoop-daemon.sh start tasktracker

  fi

  sleep 2

done

其实作用是一样的,只是一个前台,一个后台。一个占用bash,一个占用python。

©著作权归作者所有:来自51CTO博客作者Slaytanic的原创作品,如需转载,请与作者联系,否则将追究法律责任


打开App,阅读手记
0人推荐
发表评论
随时随地看视频慕课网APP