支持多个进程的判断
This commit is contained in:
parent
20d355a0f6
commit
90e7e58cb5
2
Makefile
2
Makefile
@ -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)
|
||||||
|
48
README.md
48
README.md
@ -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
163
conf.c
Normal 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
17
conf.h
Normal 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
|
@ -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
140
main.c
@ -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
10
main.h
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user