c++ 守护进程

#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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值