From 90e7e58cb5796826aa8ba9fc7656d2f65edbef24 Mon Sep 17 00:00:00 2001 From: aixiao Date: Sat, 11 Dec 2021 13:20:06 +0800 Subject: [PATCH] =?UTF-8?q?=E6=94=AF=E6=8C=81=E5=A4=9A=E4=B8=AA=E8=BF=9B?= =?UTF-8?q?=E7=A8=8B=E7=9A=84=E5=88=A4=E6=96=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Makefile | 2 +- README.md | 48 ++++++++++------ conf.c | 163 ++++++++++++++++++++++++++++++++++++++++++++++++++++ conf.h | 17 ++++++ daemon.conf | 6 +- main.c | 140 ++++++++++++++++++++++++++++++++------------ main.h | 10 +++- 7 files changed, 324 insertions(+), 62 deletions(-) create mode 100644 conf.c create mode 100644 conf.h diff --git a/Makefile b/Makefile index 96218ec..9c1f8ef 100644 --- a/Makefile +++ b/Makefile @@ -5,7 +5,7 @@ CFLAGS += -g -O2 -Wall -I../libconf -L../libconf LIBS = -lconf -static OBJ := daemon -all: popen.o main.o +all: conf.o popen.o main.o $(CC) $(CFLAGS) -o $(OBJ) $^ $(LIBS) $(STRIP) $(OBJ) -chmod a+x $(OBJ) diff --git a/README.md b/README.md index 98e8322..1481448 100644 --- a/README.md +++ b/README.md @@ -1,24 +1,34 @@ -### Daemon - 根据程序名称和时间为判断条件的进程守护程序. - 配置文件默认 daemon.conf - global { - PROCESS_NAME = "frpc"; //进程名称条件变量 - COMMAND = "ls -al"; //进程名称条件变量不成立执行的命令 - TIME = "10"; //时间条件变量, 单位秒 - LOGFILE = "log.txt"; //日志记录 - } - -### Build - Linux编译: - git clone https://github.com/niuyuling/daemon.git - git clone https://github.com/niuyuling/libconf.git +# Daemon + Process daemon + +# build + git clone https://git.aixiao.me:443/aixiao/libconf.git + git clone https://git.aixiao.me:443/aixiao/daemon.git cd libconf make clean; make cd ../daemon make clean; make -### Help - #启动 - ./daemon - #关闭 - killall daemon \ No newline at end of file +# HELP + root@NIUYULING:/mnt/c/Users/niuyuling/Desktop/conf# ./daemon -? + Process daemon + Author: AIXIAO@AIXIAO.ME + Usage: [-?h] [-c filename] + + Options: + -c : set configuration file, (default: daemon.conf) + -? -h : help information + + root@NIUYULING:/mnt/c/Users/niuyuling/Desktop/conf# + + + 配置文件示列: + global { + PROCESS="ls->ls -al"; // 要执行的命令和进程名, 依'->'为分界, '->'之前的字符为进程名字, '->'之后的字符串为要执行的命令.(PROCESS配置理论可以有无数个, 通过链表存储) + PROCESS="id->id"; // 同上 + TIME = "10"; // 循环时间, 单位秒. 大于等于1 + LOGFILE = "log_daemon.txt"; // 日志文件 + } + + + \ No newline at end of file diff --git a/conf.c b/conf.c new file mode 100644 index 0000000..9fac36f --- /dev/null +++ b/conf.c @@ -0,0 +1,163 @@ +#include "conf.h" + +/* 字符串预处理,设置转义字符 */ +static void string_pretreatment(char *str, int *len) +{ + char *lf, *p, *ori_strs[] = { "\\r", "\\n", "\\b", "\\v", "\\f", "\\t", "\\a", "\\b", "\\0" }, to_chrs[] = { '\r', '\n', '\b', '\v', '\f', '\t', '\a', '\b', '\0' }; + int i; + + while ((lf = strchr(str, '\n')) != NULL) { + for (p = lf + 1; *p == ' ' || *p == '\t' || *p == '\n' || *p == '\r'; p++) + *len -= 1; + strcpy(lf, p); + *len -= 1; + } + for (i = 0; i < sizeof(to_chrs); i++) { + for (p = strstr(str, ori_strs[i]); p; p = strstr(p, ori_strs[i])) { + //支持\\r + *(p - 1) == '\\' ? (*p--) : (*p = to_chrs[i]); + memmove(p + 1, p + 2, strlen(p + 2)); + (*len)--; + } + } +} + +/* 在content中,设置变量(var)的首地址,值(val)的位置首地址和末地址,返回下一行指针 */ +static char *set_var_val_lineEnd(char *content, char **var, char **val_begin, char **val_end) +{ + char *p, *pn, *lineEnd; + ; + int val_len; + + while (1) { + if (content == NULL) + return NULL; + + for (; *content == ' ' || *content == '\t' || *content == '\r' || *content == '\n'; content++) ; + if (*content == '\0') + return NULL; + *var = content; + pn = strchr(content, '\n'); + p = strchr(content, '='); + if (p == NULL) { + if (pn) { + content = pn + 1; + continue; + } else + return NULL; + } + content = p; + //将变量以\0结束 + for (p--; *p == ' ' || *p == '\t'; p--) ; + *(p + 1) = '\0'; + //值的首地址 + for (content++; *content == ' ' || *content == '\t'; content++) ; + if (*content == '\0') + return NULL; + //双引号引起来的值支持换行 + if (*content == '"') { + *val_begin = content + 1; + *val_end = strstr(*val_begin, "\";"); + if (*val_end != NULL) + break; + } else + *val_begin = content; + *val_end = strchr(content, ';'); + if (pn && *val_end > pn) { + content = pn + 1; + continue; + } + break; + } + + if (*val_end) { + **val_end = '\0'; + val_len = *val_end - *val_begin; + lineEnd = *val_end; + } else { + val_len = strlen(*val_begin); + *val_end = lineEnd = *val_begin + val_len; + } + string_pretreatment(*val_begin, &val_len); + *val_end = *val_begin + val_len; + //printf("var[%s]\nbegin[%s]\n\n", *var, *val_begin); + return lineEnd; +} + +/* 在buff中读取模块(global http https httpdns httpudp)内容 */ +static char *read_module(char *buff, const char *module_name) +{ + int len; + char *p, *p0; + + len = strlen(module_name); + p = buff; + while (1) { + while (*p == ' ' || *p == '\t' || *p == '\r' || *p == '\n') + p++; + if (strncasecmp(p, module_name, len) == 0) { + p += len; + while (*p == ' ' || *p == '\t' || *p == '\r' || *p == '\n') + p++; + if (*p == '{') + break; + } + if ((p = strchr(p, '\n')) == NULL) + return NULL; + } + if ((p0 = strchr(++p, '}')) == NULL) + return NULL; + + return strndup(p, p0 - p); +} + +static void parse_global_module(char *content) +{ + char *var, *val_begin, *val_end, *lineEnd; + conf *conf_node = NULL; + + while ((lineEnd = set_var_val_lineEnd(content, &var, &val_begin, &val_end)) != NULL) { + + if (strcasecmp(var, "PROCESS") == 0) { + conf_node = (conf *)malloc(sizeof(*conf_node)); + conf_node->PROCESS = strdup(val_begin); + conf_node->next = NULL; + if (conf_head == NULL) { + conf_head = conf_node; + } else { + conf_node->next = conf_head; + conf_head = conf_node; + + } + } + + content = strchr(lineEnd + 1, '\n'); + } +} + +void read_conf_link(char *path) +{ + char *buff, *global_content; + FILE *file; + long file_size; + + /* 读取配置文件到缓冲区 */ + file = fopen(path, "r"); + if (file == NULL) + printf("cannot open config file.\n"); + fseek(file, 0, SEEK_END); + file_size = ftell(file); + buff = (char *)alloca(file_size + 1); + if (buff == NULL) + printf("out of memory.\n"); + rewind(file); + fread(buff, file_size, 1, file); + fclose(file); + buff[file_size] = '\0'; + /* 读取global模块内容 */ + if ((global_content = read_module(buff, "global")) == NULL) + printf("read global module error\n"); + parse_global_module(global_content); + free(global_content); + +} diff --git a/conf.h b/conf.h new file mode 100644 index 0000000..e8826ea --- /dev/null +++ b/conf.h @@ -0,0 +1,17 @@ +#ifndef CONF_H +#define CONF_H + +#include +#include +#include + +typedef struct conf { + char *PROCESS; + struct conf *next; +} conf; + + +extern conf *conf_head; +extern void read_conf_link(char *path); + +#endif diff --git a/daemon.conf b/daemon.conf index 767a7b9..bad8dc9 100644 --- a/daemon.conf +++ b/daemon.conf @@ -1,6 +1,6 @@ global { - PROCESS_NAME = "frpc"; - COMMAND = "ls -al"; + PROCESS="ls->ls -al"; + PROCESS="init->id"; TIME = "10"; - LOGFILE = "log.txt"; + LOGFILE = "log_daemon.txt"; } \ No newline at end of file diff --git a/main.c b/main.c index 29f3f69..bb6e5be 100644 --- a/main.c +++ b/main.c @@ -1,8 +1,28 @@ #include "main.h" +#include "conf.h" #include "libconf.h" -int get_process_pid(char *proces_name) -{ +conf *conf_head = NULL; + +void print_conf(conf * p) { + conf *temp = p; //将temp指针重新指向头结点 + while (temp) { //只要temp指针指向的结点的next不是Null就执行输出 + if (temp->PROCESS) + printf("%s\n", temp->PROCESS); + temp = temp->next; + } +} + +void free_conf(conf *p) { + conf *temp = p; + while (temp) { + if (temp->PROCESS) + free(temp->PROCESS); + temp = temp->next; + } +} + +int get_process_pid(char *proces_name) { char bufer[PATH_SIZE]; char comm[PATH_SIZE]; char proc_comm_name[PATH_SIZE]; @@ -41,60 +61,103 @@ int get_process_pid(char *proces_name) return 0; } -char *times() -{ +char *times() { time_t t; struct tm *timeinfo; + time(&t); timeinfo = localtime(&t); return asctime(timeinfo); } -int logs(char *str, char *configfile) -{ +int logs(char *str, char *configfile) { FILE *fp = NULL; + fp = fopen(read_conf(configfile, "global", "LOGFILE"), "a+"); fprintf(fp, str); return fclose(fp); } -int loop(char *configfile) -{ - FILE *fp; - char buffer[PATH_SIZE]; - while (1) { - if (get_process_pid(read_conf(configfile, "global", "PROCESS_NAME")) <= 0) { - logs(times(), configfile); - logs("没有运行\n", configfile); - fp = _popen(read_conf(configfile, "global", "COMMAND"), "r"); +int8_t copy_new_mem(char *src, int src_len, char **dest) { + *dest = (char *)malloc(src_len + 1); + if (*dest == NULL) + return 1; + memcpy(*dest, src, src_len); + *((*dest)+src_len) = '\0'; - logs(times(), configfile); - logs("执行结果\n", configfile); - while (fgets(buffer, sizeof(buffer), fp)) { - //printf("%s", buffer); - logs(buffer, configfile); - } - _pclose(fp); - } else { - logs(times(), configfile); - logs("运行\n", configfile); - } - sleep(atoi(read_conf(configfile, "global", "TIME"))); - } + return 0; } -int main(int argc, char **argv, char **env) +int loop(char *configfile, conf *p) { + conf *conf = p; + + FILE *fp; + char buffer[CACHE_SIZE]; + char *key; //键 + char *val; //值 + char log_content[CACHE_SIZE]; + memset(log_content, 0, CACHE_SIZE); + while (1) { + while (conf) { + if (conf->PROCESS) { + val = strstr(conf->PROCESS, "->"); + copy_new_mem(conf->PROCESS, val - conf->PROCESS, &key); + + if (get_process_pid(key) <= 0) { + strcpy(log_content, times()); + strcat(log_content, key); + strcat(log_content, " Not running\n"); + logs(log_content, configfile); + + fp = _popen(val+2, "r"); + val = NULL; + memset(buffer, 0, CACHE_SIZE); + while (fgets(buffer, sizeof(buffer), fp)) { + //printf("%s", buffer); + logs(buffer, configfile); + } + _pclose(fp); + } else { + strcpy(log_content, times()); + strcat(log_content, key); + strcat(log_content, " Running\n"); + logs(log_content, configfile); + } + + free(key); + } + conf = conf->next; + } + conf = p; + sleep(atoi(read_conf(configfile, "global", "TIME"))); + } + + return 0; +} + +int main(int argc, char *argv[], char **env) { char configfile[PATH_SIZE]; int opt; memset(configfile, 0, PATH_SIZE); - while ((opt = getopt(argc, argv, "c:")) != -1) { + while ((opt = getopt(argc, argv, "c:h?")) != -1) { switch (opt) { case 'c': strcpy(configfile, optarg); break; - + case 'h': + case '?': + printf("%s\n", + "Process daemon\n"\ + "Author: AIXIAO@AIXIAO.ME\n"\ + "Usage: [-?h] [-c filename]\n"\ + "\n"\ + "Options:\n"\ + "-c : set configuration file, (default: daemon.conf)\n"\ + "-? -h : help information\n"); + exit(1); + break; default: break; } @@ -103,14 +166,15 @@ int main(int argc, char **argv, char **env) if (strlen(configfile) == 0) { strcpy(configfile, "daemon.conf"); } - printf("%s\n", configfile); - - if (daemon(1, 1)) { + + if (daemon(1, 1)) { // 守护, 脱离终端 perror("daemon"); - return 1; } - - loop(configfile); - + + read_conf_link(configfile); + loop(configfile, conf_head); + free_conf(conf_head); + return 0; } + diff --git a/main.h b/main.h index 791b4c8..cd138ac 100644 --- a/main.h +++ b/main.h @@ -1,3 +1,7 @@ +#ifndef MAIN_H +#define MAIN_H + + #include #include #include @@ -6,7 +10,11 @@ #include #include -#define PATH_SIZE 270 +#define PATH_SIZE 2700 +#define CACHE_SIZE 2700 FILE *_popen(const char *cmdstring, const char *type); int _pclose(FILE * fp); +int8_t copy_new_mem(char *src, int src_len, char **dest); + +#endif