支持多个进程的判断

This commit is contained in:
aixiao 2021-12-11 13:20:06 +08:00
parent 20d355a0f6
commit 90e7e58cb5
7 changed files with 324 additions and 62 deletions

View File

@ -5,7 +5,7 @@ CFLAGS += -g -O2 -Wall -I../libconf -L../libconf
LIBS = -lconf -static LIBS = -lconf -static
OBJ := daemon OBJ := daemon
all: popen.o main.o all: conf.o popen.o main.o
$(CC) $(CFLAGS) -o $(OBJ) $^ $(LIBS) $(CC) $(CFLAGS) -o $(OBJ) $^ $(LIBS)
$(STRIP) $(OBJ) $(STRIP) $(OBJ)
-chmod a+x $(OBJ) -chmod a+x $(OBJ)

View File

@ -1,24 +1,34 @@
### Daemon # Daemon
根据程序名称和时间为判断条件的进程守护程序. Process daemon
配置文件默认 daemon.conf
global { # build
PROCESS_NAME = "frpc"; //进程名称条件变量 git clone https://git.aixiao.me:443/aixiao/libconf.git
COMMAND = "ls -al"; //进程名称条件变量不成立执行的命令 git clone https://git.aixiao.me:443/aixiao/daemon.git
TIME = "10"; //时间条件变量, 单位秒
LOGFILE = "log.txt"; //日志记录
}
### Build
Linux编译:
git clone https://github.com/niuyuling/daemon.git
git clone https://github.com/niuyuling/libconf.git
cd libconf cd libconf
make clean; make make clean; make
cd ../daemon cd ../daemon
make clean; make make clean; make
### Help # HELP
#启动 root@NIUYULING:/mnt/c/Users/niuyuling/Desktop/conf# ./daemon -?
./daemon Process daemon
#关闭 Author: AIXIAO@AIXIAO.ME
killall daemon 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"; // 日志文件
}

163
conf.c Normal file
View File

@ -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);
}

17
conf.h Normal file
View File

@ -0,0 +1,17 @@
#ifndef CONF_H
#define CONF_H
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct conf {
char *PROCESS;
struct conf *next;
} conf;
extern conf *conf_head;
extern void read_conf_link(char *path);
#endif

View File

@ -1,6 +1,6 @@
global { global {
PROCESS_NAME = "frpc"; PROCESS="ls->ls -al";
COMMAND = "ls -al"; PROCESS="init->id";
TIME = "10"; TIME = "10";
LOGFILE = "log.txt"; LOGFILE = "log_daemon.txt";
} }

140
main.c
View File

@ -1,8 +1,28 @@
#include "main.h" #include "main.h"
#include "conf.h"
#include "libconf.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 bufer[PATH_SIZE];
char comm[PATH_SIZE]; char comm[PATH_SIZE];
char proc_comm_name[PATH_SIZE]; char proc_comm_name[PATH_SIZE];
@ -41,60 +61,103 @@ int get_process_pid(char *proces_name)
return 0; return 0;
} }
char *times() char *times() {
{
time_t t; time_t t;
struct tm *timeinfo; struct tm *timeinfo;
time(&t); time(&t);
timeinfo = localtime(&t); timeinfo = localtime(&t);
return asctime(timeinfo); return asctime(timeinfo);
} }
int logs(char *str, char *configfile) int logs(char *str, char *configfile) {
{
FILE *fp = NULL; FILE *fp = NULL;
fp = fopen(read_conf(configfile, "global", "LOGFILE"), "a+"); fp = fopen(read_conf(configfile, "global", "LOGFILE"), "a+");
fprintf(fp, str); fprintf(fp, str);
return fclose(fp); return fclose(fp);
} }
int loop(char *configfile) int8_t copy_new_mem(char *src, int src_len, char **dest) {
{ *dest = (char *)malloc(src_len + 1);
FILE *fp; if (*dest == NULL)
char buffer[PATH_SIZE]; return 1;
while (1) { memcpy(*dest, src, src_len);
if (get_process_pid(read_conf(configfile, "global", "PROCESS_NAME")) <= 0) { *((*dest)+src_len) = '\0';
logs(times(), configfile);
logs("没有运行\n", configfile);
fp = _popen(read_conf(configfile, "global", "COMMAND"), "r");
logs(times(), configfile); return 0;
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")));
}
} }
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]; char configfile[PATH_SIZE];
int opt; int opt;
memset(configfile, 0, PATH_SIZE); memset(configfile, 0, PATH_SIZE);
while ((opt = getopt(argc, argv, "c:")) != -1) { while ((opt = getopt(argc, argv, "c:h?")) != -1) {
switch (opt) { switch (opt) {
case 'c': case 'c':
strcpy(configfile, optarg); strcpy(configfile, optarg);
break; 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: default:
break; break;
} }
@ -103,14 +166,15 @@ int main(int argc, char **argv, char **env)
if (strlen(configfile) == 0) { if (strlen(configfile) == 0) {
strcpy(configfile, "daemon.conf"); strcpy(configfile, "daemon.conf");
} }
printf("%s\n", configfile);
if (daemon(1, 1)) { // 守护, 脱离终端
if (daemon(1, 1)) {
perror("daemon"); perror("daemon");
return 1;
} }
loop(configfile); read_conf_link(configfile);
loop(configfile, conf_head);
free_conf(conf_head);
return 0; return 0;
} }

10
main.h
View File

@ -1,3 +1,7 @@
#ifndef MAIN_H
#define MAIN_H
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@ -6,7 +10,11 @@
#include <dirent.h> #include <dirent.h>
#include <time.h> #include <time.h>
#define PATH_SIZE 270 #define PATH_SIZE 2700
#define CACHE_SIZE 2700
FILE *_popen(const char *cmdstring, const char *type); FILE *_popen(const char *cmdstring, const char *type);
int _pclose(FILE * fp); int _pclose(FILE * fp);
int8_t copy_new_mem(char *src, int src_len, char **dest);
#endif