Compare commits
2 Commits
20d355a0f6
...
master
Author | SHA1 | Date | |
---|---|---|---|
cc8bd2c972 | |||
90e7e58cb5 |
2
Makefile
2
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)
|
||||
|
47
README.md
47
README.md
@ -1,24 +1,35 @@
|
||||
### Daemon
|
||||
根据程序名称和时间为判断条件的进程守护程序.
|
||||
配置文件默认 daemon.conf
|
||||
global {
|
||||
PROCESS_NAME = "frpc"; //进程名称条件变量
|
||||
COMMAND = "ls -al"; //进程名称条件变量不成立执行的命令
|
||||
TIME = "10"; //时间条件变量, 单位秒
|
||||
LOGFILE = "log.txt"; //日志记录
|
||||
}
|
||||
# Daemon
|
||||
Process daemon
|
||||
|
||||
### Build
|
||||
Linux编译:
|
||||
git clone https://github.com/niuyuling/daemon.git
|
||||
git clone https://github.com/niuyuling/libconf.git
|
||||
# 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
|
||||
# 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="ls1" -> "ls -al"; // 同上
|
||||
PROCESS="id" -> "id"; // 同上
|
||||
TIME = "10"; // 循环时间, 单位秒. 大于等于1
|
||||
LOGFILE = "log_daemon.txt"; // 日志文件
|
||||
}
|
||||
|
||||
|
||||
|
215
conf.c
Normal file
215
conf.c
Normal file
@ -0,0 +1,215 @@
|
||||
#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;
|
||||
char *p1 = NULL, *s = NULL, *t = NULL;
|
||||
char *p2 = 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->PROCESS_len = val_end - val_begin;
|
||||
|
||||
p1 = strstr(val_begin, "->");
|
||||
for (t = p1; *t != '"'; ++t) ;
|
||||
conf_node->PROCESS_command = strdup(t + 1);
|
||||
p2 = strchr(t+1, '\0');
|
||||
conf_node->PROCESS_command_len = p2 - (t + 1);
|
||||
|
||||
for (s = p1 - 1; *s == ' '; s--) {
|
||||
if (s == val_begin)
|
||||
return;
|
||||
}
|
||||
if (*s == '"')
|
||||
s--;
|
||||
|
||||
conf_node->PROCESS_name = strndup(val_begin, s - val_begin + 1);
|
||||
conf_node->PROCESS_name_len = s - val_begin + 1;
|
||||
|
||||
|
||||
|
||||
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 print_conf(conf * p) {
|
||||
conf *temp = p; //将temp指针重新指向头结点
|
||||
while (temp) { //只要temp指针指向的结点的next不是Null就执行输出
|
||||
if (temp->PROCESS)
|
||||
printf("%s %d\n", temp->PROCESS, temp->PROCESS_len);
|
||||
if (temp->PROCESS_name)
|
||||
printf("%s %d\n", temp->PROCESS_name, temp->PROCESS_name_len);
|
||||
if (temp->PROCESS_command)
|
||||
printf("%s %d\n", temp->PROCESS_command, temp->PROCESS_command_len);
|
||||
|
||||
temp = temp->next;
|
||||
}
|
||||
}
|
||||
|
||||
void free_conf(conf *p) {
|
||||
conf *temp = p;
|
||||
while (temp) {
|
||||
if (temp->PROCESS)
|
||||
free(temp->PROCESS);
|
||||
if (temp->PROCESS_name)
|
||||
free(temp->PROCESS_name);
|
||||
if (temp->PROCESS_command)
|
||||
free(temp->PROCESS_command);
|
||||
|
||||
temp = temp->next;
|
||||
}
|
||||
}
|
||||
|
||||
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");
|
||||
exit(1);
|
||||
}
|
||||
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);
|
||||
|
||||
}
|
22
conf.h
Normal file
22
conf.h
Normal file
@ -0,0 +1,22 @@
|
||||
#ifndef CONF_H
|
||||
#define CONF_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
typedef struct conf {
|
||||
char *PROCESS;
|
||||
char *PROCESS_name, *PROCESS_command;
|
||||
|
||||
int PROCESS_len, PROCESS_name_len, PROCESS_command_len;
|
||||
struct conf *next;
|
||||
} conf;
|
||||
|
||||
|
||||
extern conf *conf_head;
|
||||
extern void read_conf_link(char *path);
|
||||
extern void free_conf(conf *p);
|
||||
extern void print_conf(conf *p);
|
||||
|
||||
#endif
|
@ -1,6 +1,7 @@
|
||||
global {
|
||||
PROCESS_NAME = "frpc";
|
||||
COMMAND = "ls -al";
|
||||
PROCESS="ls" -> "ls -al";
|
||||
PROCESS="ls1" -> "ls -al";
|
||||
PROCESS="init" -> "id";
|
||||
TIME = "10";
|
||||
LOGFILE = "log.txt";
|
||||
LOGFILE = "log_daemon.txt";
|
||||
}
|
113
main.c
113
main.c
@ -1,8 +1,10 @@
|
||||
#include "main.h"
|
||||
#include "conf.h"
|
||||
#include "libconf.h"
|
||||
|
||||
int get_process_pid(char *proces_name)
|
||||
{
|
||||
conf *conf_head = NULL;
|
||||
|
||||
int get_process_pid(char *proces_name) {
|
||||
char bufer[PATH_SIZE];
|
||||
char comm[PATH_SIZE];
|
||||
char proc_comm_name[PATH_SIZE];
|
||||
@ -41,60 +43,95 @@ 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 log_content[CACHE_SIZE];
|
||||
memset(log_content, 0, CACHE_SIZE);
|
||||
while (1) {
|
||||
while (conf) {
|
||||
if (conf->PROCESS) {
|
||||
if (get_process_pid(conf->PROCESS_name) <= 0) {
|
||||
strcpy(log_content, times());
|
||||
strcat(log_content, conf->PROCESS_name);
|
||||
strcat(log_content, " Not running\n");
|
||||
logs(log_content, configfile);
|
||||
|
||||
fp = _popen(conf->PROCESS_command, "r");
|
||||
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, conf->PROCESS_name);
|
||||
strcat(log_content, " Running\n");
|
||||
logs(log_content, configfile);
|
||||
}
|
||||
}
|
||||
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 +140,20 @@ 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);
|
||||
/* Test Code
|
||||
print_conf(conf_head);
|
||||
free_conf(conf_head);
|
||||
exit(0);
|
||||
*/
|
||||
loop(configfile, conf_head);
|
||||
free_conf(conf_head);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
10
main.h
10
main.h
@ -1,3 +1,7 @@
|
||||
#ifndef MAIN_H
|
||||
#define MAIN_H
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@ -6,7 +10,11 @@
|
||||
#include <dirent.h>
|
||||
#include <time.h>
|
||||
|
||||
#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
|
||||
|
Loading…
Reference in New Issue
Block a user