C++ - 写一个守护进程A,用于监控进程B,B挂掉就拉起
概述:
1、A可以是守护进程也可以是守护脚本
2、A是守护进程
3、A具有保活其他进程的服务
守护进程(已验证)
1 //main.c 2 3 #include <stdio.h> 4 #include <unistd.h> 5 #include <sys/types.h> 6 #include <sys/stat.h> 7 #include <fcntl.h> 8 #include <syslog.h> 9 10 //守护应用名 11 #define APP_NAME "untitled_ATU201console" 12 //生成日志文件 13 #define LOG_FILE "/home/root/ljc/folder_daemon/untitled_ATU201console.log" 14 //匹配成功 15 #define MATCH_RES "1" 16 //启动守护应用的脚本 17 #define SCRIPT_FILE "start_daemon" 18 19 20 21 int daemon(int nochdir, int noclose) { 22 pid_t pid; 23 24 //让init进程成为新产生进程的父进程 25 pid = fork(); 26 //如果创建进程失败 27 if (pid < 0) { 28 perror("fork"); 29 return -1; 30 } 31 //父进程退出运行 32 if (pid != 0) { 33 exit(0); 34 } 35 //创建新的会话 36 pid = setsid(); 37 if (pid < -1) { 38 perror("set sid"); 39 return -1; 40 } 41 //更改当前工作目录,将工作目录修改成根目录 42 if (!nochdir) { 43 chdir("/"); 44 } 45 //关闭文件描述符,并重定向标准输入,输出合错误输出 46 //将标准输入输出重定向到空设备 47 if (!noclose) { 48 int fd; 49 fd = open("/dev/null", O_RDWR, 0); 50 if (fd != -1) { 51 dup2(fd, STDIN_FILENO); 52 dup2(fd, STDOUT_FILENO); 53 dup2(fd, STDERR_FILENO); 54 if (fd > 2) { 55 close(fd); 56 } 57 } 58 } 59 //设置守护进程的文件权限创建掩码 60 umask(0027); 61 62 return 0; 63 } 64 65 //是否有匹配的字符,有则返回1,没有返回0 66 //src:源字符串 67 //dst:目标字符串 68 //len:源字符串被比较的长度 69 int match(char *src, char *dst, int len) { 70 syslog(LOG_INFO, "--------------------match1"); 71 72 int i = 0; 73 int j = 0; 74 int size_dst = 0; 75 76 //获得目标字符串的长度 77 size_dst = strlen(dst); 78 //如果目标字符串的长度大于len,返回失败 79 if (size_dst > len) { 80 syslog(LOG_INFO, "--------------------match11"); 81 return 0; 82 } 83 84 syslog(LOG_INFO, "--------------------match2"); 85 86 //开始比较 87 for (i = 0; i < len; i++) { 88 for (j = 0; j < size_dst; j++) { 89 if (src[i + j] != dst[j]) { 90 break; 91 } 92 } 93 if (j == size_dst) { 94 return 1; 95 } 96 } 97 98 syslog(LOG_INFO, "--------------------match3"); 99 100 return 0; 101 } 102 103 int main(int argc, char *argv[]) { 104 int fd = 0; 105 char buf[100]; 106 107 //开启守护进程 108 daemon(0, 0); 109 110 while (1) { 111 syslog(LOG_INFO, "--------------------main1"); 112 113 //打开日志 114 openlog(argv[0], LOG_CONS | LOG_PID, LOG_USER); 115 116 //查看程序是否运行 117 //新建输出文件 118 system("touch "LOG_FILE); 119 //获得程序ID 120 system("ps -ef | grep "APP_NAME" | grep -v grep | wc -l >> "LOG_FILE); 121 //打开输出文件 122 fd = open(LOG_FILE, O_CREAT | O_RDONLY, 0777); 123 //清空缓存 124 memset(buf, 0, 100); 125 //读取全部 126 read(fd, buf, 100); 127 128 syslog(LOG_INFO, "--------------------main2"); 129 130 //判断是否有程序文件运行 131 // if (match(buf, MATCH_RES, 1)) { 132 // syslog(LOG_INFO, "match success!!!"); 133 // } else { 134 // syslog(LOG_INFO, "match fail!!!"); 135 // //运行程序 136 // system(SCRIPT_FILE); 137 // } 138 139 int res = memcmp(buf, MATCH_RES, 1); 140 syslog(LOG_INFO, "buf = %s\n", buf); 141 syslog(LOG_INFO, "MATCH_RES = %s\n", MATCH_RES); 142 syslog(LOG_INFO, "res = %d\n", res); 143 if ( res == 0) { 144 syslog(LOG_INFO, "match success!!!"); 145 } else { 146 syslog(LOG_INFO, "match fail!!!"); 147 //运行程序 148 // system(SCRIPT_FILE); 149 system("/home/root/ljc/folder_daemon/untitled_ATU201console &"); 150 } 151 152 syslog(LOG_INFO, "--------------------main3"); 153 154 //休眠 155 sleep(2); 156 //删除输出文件 157 system("rm "LOG_FILE); 158 //休眠 159 sleep(5); 160 } 161 //关闭日志 162 closelog(); 163 164 return 0; 165 }
守护脚本1(待验证)
1 //假设要监控的进程名称为test,TargetProcessName为启动该进程的脚本,status 有一系列的宏 对应可以检测。 2 while [ 0 ] 3 do 4 Result=$(ps -ef | grep -v grep |grep "test") 5 if [ "" == "$Result" ] 6 then 7 RecordTime=$(date) 8 echo "Restar test" >>$LogFile 9 nohup $TargetProcessName>>$LogFile & 10 sleep 2 11 fi 12 Result= 13 done
守护脚本2(待验证)
1 #!/bin/bash 2 # 直接上代码吧 3 # watchdog.sh 4 5 #定义映射表 k=进程号 v=作业 6 declare -A mapper 7 #进程号文件 8 conf=dog.pid 9 10 11 function debug 12 { 13 echo $@ 14 } 15 16 #param pid 进程号 17 #使用ps命令查询该进程是否存在,如果不存在返回"gone",否则返回"stay" 18 19 function watch 20 { 21 local pid=$1 22 local index=`ps -ef|awk '{print $2}'|grep -P "^${pid}$"` 23 if [ "${index}None" = "None" ]; then 24 echo gone 25 return 26 fi 27 echo stay 28 } 29 30 #每过5秒钟检查一遍所有的进程,调用上面的watch 31 32 function dogit 33 { 34 while [ 1 ] 35 do 36 sleep 5 37 for pid in ${!mapper[@]} 38 do 39 debug pid:$pid 40 local t=`watch $pid` 41 debug "test result is $t!!!" 42 if [ "$t" = "gone" ]; then 43 debug "$c with pid $pid was gone" 44 loadscript ${mapper[$pid]} 45 unset mapper[$pid] 46 sed -i "/$pid/d" $conf 47 fi 48 done 49 done 50 } 51 52 #从作业文件加载需要守护的作业命令 53 54 function loadscript 55 { 56 local script=$@ 57 debug script=$script 58 $script > /dev/null & 59 local pid=$! 60 mapper[$pid]=$script 61 echo $pid >> $conf 62 } 63 64 function clean 65 { 66 if [ -f $conf ]; then 67 while read line; do 68 if [ -n "$line" ]; then 69 pid=`ps -ef|awk '{print $2}'|grep $line|grep -v 'grep'` 70 if [ -n "${pid}" ]; then 71 debug killing $pid 72 kill $pid 73 fi 74 fi 75 done < $conf 76 fi 77 echo > $conf 78 debug done! 79 } 80 81 function main 82 { 83 clean 84 local file=$1 85 if [ -f $file ]; then 86 while read line 87 do 88 loadscript $line 89 done < $file 90 dogit 91 else 92 echo "Not a file!" 93 fi 94 } 95 96 main $1;
博客园文作者:Citrusliu
博文地址:https://www.cnblogs.com/citrus
分类:
C++/Qt
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· [.NET]调用本地 Deepseek 模型
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性