#include <iostream>
#include <fstream>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <signal.h>
#include "glog/logging.h"
#include "json/json.h"
using namespace std;
volatile int run_flag = true;
void SigintHandler(int sig) {
run_flag = false;
}
int daemon() {
//创建子进程,父进程退出
pid_t pid = fork();
if (pid < 0) {
LOG(ERROR) << "fork error!!!!";
return -1;
}
//父进程退出
if (pid > 0) {
exit(0);
}
//创建新会话
pid = setsid();
if (pid < -1) {
LOG(ERROR) << "setsid error!!!!";
return -1;
}
//改变当前工作目录
// int ret = chdir("/home/");
// if(-1==ret){
// LOG(ERROR) << "chdir error!!!!";
// return -1;
// }
//设置权限掩码
umask(0);
//关闭文件描述符
close(STDIN_FILENO);
close(STDOUT_FILENO);
close(STDERR_FILENO);
return 0;
}
bool InitGlog(const std::string& log_path) {
if (log_path.length() < 1) {
LOG(INFO) << "path error!!!!";
cout << "path error!!!!" << endl;
return false;
}
if (access(log_path.c_str(), 0) == -1) {
cout << "mkdir log_path!" << endl;
LOG(INFO) << "mkdir log_path!!!!";
// -rwxrwxrwx (777) — 每个人都能够读取、写入、和执行。
int ret = mkdir(log_path.c_str(), 777);
if (ret == -1) {
LOG(INFO) << "mkdir log_path failed: " << log_path;
return false;
}
}
google::InitGoogleLogging(log_path.c_str());
// 是否将日志输出到stderr而非文件。
FLAGS_logtostderr = false;
// 是否将日志输出到文件和stderr,如果:true,忽略FLAGS_stderrthreshold的限制,所有信息打印到终端。
FLAGS_alsologtostderr = false;
// 输出到stderr的限值,默认为2(ERROR),默认ERORR以下的信息(INFO、WARNING)不打印到终端。
FLAGS_stderrthreshold = google::GLOG_ERROR;
FLAGS_log_prefix = true; // 设置日志前缀是否应该添加到每行输出。
FLAGS_logbufsecs = 0; // 设置可以缓冲日志的最大秒数,0指实时输出。
FLAGS_max_log_size = 10; // 设置最大日志文件大小(以MB为单位)。
FLAGS_stop_logging_if_full_disk = true; // 设置是否在磁盘已满时避免日志记录到磁盘。
// 大于指定级别的日志都输出到标准错误(包括自己)。
google::SetStderrLogging(google::GLOG_INFO);
// 日志的输出目录和前缀。
google::SetLogDestination(google::GLOG_INFO, (log_path + "/info_").c_str());
google::SetLogDestination(google::GLOG_WARNING, (log_path + "/warning_").c_str());
google::SetLogDestination(google::GLOG_ERROR, (log_path + "/error_").c_str());
// 在日志文件名中级别后添加一个扩展名
//google::SetLogFilenameExtension(".txt");
return true;
}
int main() {
// 开启守护进程
daemon();
std::string path = getcwd(nullptr, 0);
std::ifstream in(path + "/config.json", std::ios::binary);
if (!in.is_open()) {
cout << "Error opening file" << endl;
perror("Error opening file!");
return -1;
}
signal(SIGINT, SigintHandler);
Json::Reader reader;
Json::Value root;
Json::Value dataVal;
if (!reader.parse(in, root, false)) {
return -1;
}
if (!root["log_path"].isNull()){
std::string log_path = root["log_path"].asString();
InitGlog(log_path);
} else {
perror("Error get log path!!");
}
int sleep_time = 30;
if (!root["sleep_time"].isNull()){
sleep_time = root["sleep_time"].asInt();
}
if (!root["data"].isNull()){
dataVal = root["data"];
//记录守护进程pid
LOG(INFO) << "current process ID: " << getpid();
while (run_flag) {
for (int i = 0; i < dataVal.size(); i++) {
char process_cmd[128];
sprintf(process_cmd, "ps -ef | grep %s | grep -v grep | wc -l", dataVal[i]["process_name"].asCString());
char buf[10];
FILE* fp = popen(process_cmd, "r");
if (fp == nullptr) {
LOG(ERROR) << "check " << process_cmd <<" error !!";
}
if (fgets(buf, 10, fp) != nullptr) {
int count = atoi(buf);
if (count == 0) {
LOG(ERROR) << dataVal[i]["process_name"].asCString() <<" process lost!!";
char start_cmd[128];
sprintf(start_cmd, "%s",dataVal[i]["start_cmd"].asCString());
system(start_cmd);
LOG(INFO) << dataVal[i]["process_name"].asCString() <<" process restart!!";
}
}
}
sleep(sleep_time);
}
}
in.close();
return 0;
}
c++ 守护进程
最新推荐文章于 2025-04-01 11:15:24 发布