加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

perl实现对各种命令的守护进程,能够自动重启进程

发布时间:2020-12-16 00:37:05 所属栏目:大数据 来源:网络整理
导读:运维需要对一些关键的服务进程进行守护,例如tomcat进程,mysql之类,这种进程没有自己的守护进程,而我们又不可能去改它们的源代码。 为此我用perl写了一个守护进程,根据传入的命令,启动要守护的进程,若是进程挂了,则重新启动进程。 即使子进程被杀死了

运维需要对一些关键的服务进程进行守护,例如tomcat进程,mysql之类,这种进程没有自己的守护进程,而我们又不可能去改它们的源代码。

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

?

 
 
  1. #!/usr/bin/perl ?
  2. ?
  3. #################################################### ?
  4. ?
  5. #功能:实现把传入的命令执行,并守护,当命令被杀死了,能够重新启动命令 ?
  6. ?
  7. #系统环境:centos?5 ?
  8. ?
  9. #编译环境:perl,?v5.8.8?built?for?i386-linux-thread-multi ?
  10. ?
  11. #执行:????????????? ?
  12. ?
  13. #echo?"i=0;"?>?/root/w.sh ?
  14. ?
  15. #echo?'while(true)'?>>?/root/w.sh ?
  16. ?
  17. #echo?"do"?>>?/root/w.sh ?
  18. ?
  19. #echo?'?echo?$i;let?i=$i+1;sleep?1;'?>>?/root/w.sh ?
  20. ?
  21. #echo?'done'?>>?/root/w.sh ?
  22. ?
  23. #perl?deamon.pl?"sh?/root/w.sh?>>?/root/w.log"?
  24. ?
  25. # ?
  26. ?
  27. #################################################### ?
  28. ?
  29. use?POSIX?(); ?
  30. ?
  31. use?Carp; ?
  32. ?
  33. ?
  34. ?
  35. our?$logfile="/tmp/deamon.log";?#输出日志 ?
  36. ?
  37. our?$child_pid;?#记录子进程的id,以便父进程去杀死子进程 ?
  38. ?
  39. our?$parent_pid;#记录父进程的id,以便区分父子进程 ?
  40. ?
  41. our?$maxloop=10000;?#放置大量产生子进程 ?
  42. ?
  43. our?$loop=0; ?
  44. ?
  45. our?$CMD=$ARGV[0]; ?
  46. ?
  47. if(!$CMD){ ?
  48. ?
  49. ????die("please?input?a?cmdn"); ?
  50. ?
  51. } ?
  52. ?
  53. ?
  54. ?
  55. #杀死父子进程 ?
  56. ?
  57. sub?kill_pid{ ?
  58. ?
  59. ????logs("catch?quit?signaln"); ?
  60. ?
  61. ????if($parent_pid){#判断是不是父进程 ?
  62. ?
  63. ????????#父进程杀死所有的子进程 ?
  64. ?
  65. ????????logs("parent?kill?childn"); ?
  66. ?
  67. ????????kill(15,$child_pid); ?
  68. ?
  69. ????????kill(15,-$$); ?
  70. ?
  71. ????????logs("parent?quitn"); ?
  72. ?
  73. ????????exit?0; ?
  74. ?
  75. ????}else{ ?
  76. ?
  77. ????????#子进程退出 ?
  78. ?
  79. ????????logs("child?quitn");???????? ?
  80. ?
  81. ????????exit?0; ?
  82. ?
  83. ????} ?
  84. ?
  85. }; ?
  86. ?
  87. $SIG{'INT'}?=?'kill_pid';?#?中断退出 ?
  88. ?
  89. $SIG{'TERM'}?=?'kill_pid'; ?
  90. ?
  91. $SIG{CHLD}?=?'IGNORE';?#?忽略?SIGCHLD?信号,系统会自动回收结束的子进程 ?
  92. ?
  93. #deamon方式 ?
  94. ?
  95. daemonize(); ?
  96. ?
  97. #启动服务 ?
  98. ?
  99. logs("START?deamon?'$CMD'n"); ?
  100. ?
  101. ?
  102. ?
  103. while(1){ ?
  104. ?
  105. ????#防止输入的命令不是服务性命令,例如ls,执行很短时间的命令,或者后台执行的命令,这样最多会产生$maxloop个进程,不会把系统崩溃 ?
  106. ?
  107. ????$loop++; ?
  108. ?
  109. ????if($loop>$maxloop){ ?
  110. ?
  111. ????????exit?0;???? ?
  112. ?
  113. ????} ?
  114. ?
  115. ???? ?
  116. ?
  117. ????#产生子进程 ?
  118. ?
  119. ????$child_pid=fork(); ?
  120. ?
  121. ????if?(not?defined?$child_pid)?{ ?
  122. ?
  123. ????????print?"cannot?forkn"; ?
  124. ?
  125. ????????exit?0; ?
  126. ?
  127. ????} ?
  128. ?
  129. ????if($child_pid) ?
  130. ?
  131. ????{?#?child?>;?0,?so?we're?the?parent ?
  132. ?
  133. ?????????$parent_pid=1;? ?
  134. ?
  135. ?????logs("launching?'$CMD'n");? ?
  136. ?
  137. ?????setpgrp(0,?0);?#成为进程首领 ?
  138. ?
  139. ?????wait();#等待子进程结束,若是结束则继续循环生成子进程 ?
  140. ?
  141. ????}else{? ?
  142. ?
  143. ????????????$parent_pid=0; ?
  144. ?
  145. ????????????system($CMD);#?child?handles,子进程应该也是死循环的 ?
  146. ?
  147. ????????????logs("system?return?:?$r?"); ?
  148. ?
  149. ?????#执行命令非正常退出 ?
  150. ?
  151. ?????if?($??==?-1)?{ ?
  152. ?
  153. ????????logs("failed?to?execute:?$!?"); ?
  154. ?
  155. ?????????} ?
  156. ?
  157. ?????????elsif?($??&?127)?{ ?
  158. ?
  159. ?????????logs("child?died?with?signal",($??&?127),",",($??&?128)???'with'?:?'without','?coredump'); ?
  160. ?
  161. ?????????} ?
  162. ?
  163. ?????????else?{ ?
  164. ?
  165. ?????????logs("child?exited?with?value?",$??>>?8); ?
  166. ?
  167. ?????????????#若是$CMD正常退出的话,表示$CMD不是服务性程序 ?
  168. ?
  169. ?????????????????logs("cannot?deamon?on?'$CMD'"); ?
  170. ?
  171. ?????????} ?
  172. ?
  173. ?????#子进程退出???? ?
  174. ?
  175. ?????exit?0; ?
  176. ?
  177. ????}? ?
  178. ?
  179. } ?
  180. ?
  181. ?
  182. ?
  183. #记录日志 ?
  184. ?
  185. sub?logs{ ?
  186. ?
  187. ????open(LOGFILE,">>$logfile")?or?die("cannot?open?$logfile"); ?
  188. ?
  189. ????????my($sec,$min,$hour,$mday,$mon,$year)=localtime(); ?
  190. ?
  191. ????print?LOGFILE?sprintf("%04d-%02d-%02d?%02d:%02d:%02d?",($year<?2000?($year+1900):$year),($mon+1),$sec); ?
  192. ?
  193. ????for?my?$msg?(@_){ ?
  194. ?
  195. ????????print?LOGFILE?$msg; ?
  196. ?
  197. ????} ?
  198. ?
  199. ????print?LOGFILE?"n"; ?
  200. ?
  201. ????close(LOGFILE); ?
  202. ?
  203. } ?
  204. ?
  205. ?
  206. ?
  207. #deamon方式 ?
  208. ?
  209. sub?daemonize?{ ?
  210. ?
  211. ?
  212. ?
  213. ????????#????使当前进程对自己所写文件拥有完全控制权,避免继承的umask()设置带来困挠。这一步可选 ?
  214. ?
  215. ????????umask(0); ?
  216. ?
  217. ????????#????关闭0、1、2三个句柄。许多daemon程序用sysconf()获取_SC_OPEN_MAX,并在一个?环中关闭所有可能打开的文件句柄。目的在于释放不必要的系统资源,它们是有限资源。 ?
  218. ?
  219. ????????close?STDIN; ?
  220. ?
  221. ????????close?STDOUT; ?
  222. ?
  223. ????????close?STDERR; ?
  224. ?
  225. ????chdir?'/'?or?croak?"Can't?chdir?to?/:?$!";?#减少管理员卸载(unmount)文件系统时可能遇上的麻烦。这一步可选,也可chdir()到其它目录。 ?
  226. ?
  227. ????open?STDIN,?'/dev/null'?or?croak?"Can't?read?/dev/null:?$!"; ?
  228. ?
  229. ????open?STDOUT,?'>/dev/null'?or?croak?"Can't?write?to?/dev/null:?$!"; ?
  230. ?
  231. ????open?STDERR,?'>&STDOUT'?or?croak?"Can't?dup?stdout:?$!"; ?
  232. ?
  233. ????defined(my?$pid?=?fork)?or?croak?"Can't?fork:?$!"; ?
  234. ?
  235. ????exit?if?$pid; ?
  236. ?
  237. ????#创建新的session和process?group,成为其leader,并脱离控制终端。 ?
  238. ?
  239. ????setsid?or?croak?"Can't?start?a?new?session:?$!"; ?
  240. ?
  241. ????$SIG{CHLD}?=?'IGNORE

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读