设为首页 收藏本站
查看: 1007|回复: 0

[经验分享] perl实现对各种命令的守护进程,能够自动重启进程

[复制链接]

尚未签到

发表于 2018-8-31 13:34:08 | 显示全部楼层 |阅读模式
  运维需要对一些关键的服务进程进行守护,例如tomcat进程,mysql之类,这种进程没有自己的守护进程,而我们又不可能去改它们的源代码。

为此我用perl写了一个守护进程,根据传入的命令,启动要守护的进程,若是进程挂了,则重新启动进程。
即使子进程被杀死了,也能自动起来,但是程序有点缺陷:
1. 这个守护进程只是针对那些永远不退出的进程有效。
2. 若是杀死了守护进程,被守护的进程有可能不会退出,还要手动去杀死被守护进程,才能退出。因为我们找到杀死整个进程树的方法,  


  • #!/usr/bin/perl

  • ####################################################

  • #功能:实现把传入的命令执行,并守护,当命令被杀死了,能够重新启动命令

  • #系统环境:centos 5

  • #编译环境:perl, v5.8.8 built for i386-linux-thread-multi

  • #执行:

  • #echo "i=0;" > /root/w.sh

  • #echo 'while(true)' >> /root/w.sh

  • #echo "do" >> /root/w.sh

  • #echo ' echo $i;let i=$i+1;sleep 1;' >> /root/w.sh

  • #echo 'done' >> /root/w.sh

  • #perl deamon.pl "sh /root/w.sh >> /root/w.log"

  • #

  • ####################################################

  • use POSIX ();

  • use Carp;



  • our $logfile="/tmp/deamon.log"; #输出日志

  • our $child_pid; #记录子进程的id,以便父进程去杀死子进程

  • our $parent_pid;#记录父进程的id,以便区分父子进程

  • our $maxloop=10000; #放置大量产生子进程

  • our $loop=0;

  • our $CMD=$ARGV[0];

  • if(!$CMD){

  •     die("please input a cmd\n");

  • }



  • #杀死父子进程

  • sub kill_pid{

  •     logs("catch quit signal\n");

  •     if($parent_pid){#判断是不是父进程

  •         #父进程杀死所有的子进程

  •         logs("parent kill child\n");

  •         kill(15,$child_pid);

  •         kill(15,-$$);

  •         logs("parent quit\n");

  •         exit 0;

  •     }else{

  •         #子进程退出

  •         logs("child quit\n");

  •         exit 0;

  •     }

  • };

  • $SIG{'INT'} = 'kill_pid'; # 中断退出

  • $SIG{'TERM'} = 'kill_pid';

  • $SIG{CHLD} = 'IGNORE'; # 忽略 SIGCHLD 信号,系统会自动回收结束的子进程

  • #deamon方式

  • daemonize();

  • #启动服务

  • logs("START deamon '$CMD'\n");



  • while(1){

  •     #防止输入的命令不是服务性命令,例如ls,执行很短时间的命令,或者后台执行的命令,这样最多会产生$maxloop个进程,不会把系统崩溃

  •     $loop++;

  •     if($loop>$maxloop){

  •         exit 0;

  •     }



  •     #产生子进程

  •     $child_pid=fork();

  •     if (not defined $child_pid) {

  •         print "cannot fork\n";

  •         exit 0;

  •     }

  •     if($child_pid)

  •     { # child >; 0, so we're the parent

  •          $parent_pid=1;

  •      logs("launching '$CMD'\n");

  •      setpgrp(0, 0); #成为进程首领

  •      wait();#等待子进程结束,若是结束则继续循环生成子进程

  •     }else{

  •             $parent_pid=0;

  •             system($CMD);# child handles,子进程应该也是死循环的

  •             logs("system return : $r ");

  •      #执行命令非正常退出

  •      if ($? == -1) {

  •         logs("failed to execute: $! ");

  •          }

  •          elsif ($? & 127) {

  •          logs("child died with signal",($? & 127),",",($? & 128) ? 'with' : 'without',' coredump');

  •          }

  •          else {

  •          logs("child exited with value ",$? >> 8);

  •              #若是$CMD正常退出的话,表示$CMD不是服务性程序

  •                  logs("cannot deamon on '$CMD'");

  •          }

  •      #子进程退出

  •      exit 0;

  •     }

  • }



  • #记录日志

  • sub logs{

  •     open(LOGFILE,">>$logfile") or die("cannot open $logfile");

  •         my($sec,$min,$hour,$mday,$mon,$year)=localtime();

  •     print LOGFILE sprintf(&quot;%04d-%02d-%02d %02d:%02d:%02d &quot;,($year< 2000?($year+1900):$year),($mon+1),$mday,$hour,$min,$sec);

  •     for my $msg (@_){

  •         print LOGFILE $msg;

  •     }

  •     print LOGFILE &quot;\n&quot;;

  •     close(LOGFILE);

  • }



  • #deamon方式

  • sub daemonize {



  •         #    使当前进程对自己所写文件拥有完全控制权,避免继承的umask()设置带来困挠。这一步可选

  •         umask(0);

  •         #    关闭0、1、2三个句柄。许多daemon程序用sysconf()获取_SC_OPEN_MAX,并在一个偱环中关闭所有可能打开的文件句柄。目的在于释放不必要的系统资源,它们是有限资源。

  •         close STDIN;

  •         close STDOUT;

  •         close STDERR;

  •     chdir '/' or croak &quot;Can't chdir to /: $!&quot;; #减少管理员卸载(unmount)文件系统时可能遇上的麻烦。这一步可选,也可chdir()到其它目录。

  •     open STDIN, '/dev/null' or croak &quot;Can't read /dev/null: $!&quot;;

  •     open STDOUT, '>/dev/null' or croak &quot;Can't write to /dev/null: $!&quot;;

  •     open STDERR, '>&STDOUT' or croak &quot;Can't dup stdout: $!&quot;;

  •     defined(my $pid = fork) or croak &quot;Can't fork: $!&quot;;

  •     exit if $pid;

  •     #创建新的session和process group,成为其leader,并脱离控制终端。

  •     setsid or croak &quot;Can't start a new session: $!&quot;;

  •     $SIG{CHLD} = 'IGNORE
  




运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-559426-1-1.html 上篇帖子: Perl一次读取文件的方法 下篇帖子: 升级系统自带的perl-BSDerの
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表