程序 start、stop、restart

在/root目录下进行文件操作

对应的日志记录

#define _XOPEN_SOURCE 500
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <ftw.h>
#include <sys/inotify.h>
#include <limits.h>
#include <time.h>
#include <signal.h>
#include <errno.h>
#define NUMBER 8192
#define PATH_LENGTH 1024
#define LENGTH (50 * sizeof(struct inotify_event) + NAME_MAX + 1)
struct wdDirectory {
int wd;
char *path;
};
struct wdDirectory wdSet[NUMBER];
int num = 0;
int inotify_fd;
FILE *fp;
char path_backup[500];
char processName[30];
void getProcessName(char *processName) {
char processPath[PATH_LENGTH];
char *ch;
memset(processName, 0, sizeof(processName));
if(readlink("/proc/self/exe", processPath, sizeof(processPath)) <= 0)
exit(EXIT_FAILURE);
processPath[strlen(processPath) + 1] = '\0';
ch = strrchr(processPath, '/');
if(ch == NULL)
exit(EXIT_FAILURE);
ch++;
strncpy(processName, ch, strlen(ch));
processName[strlen(processName) + 1] = '\0';
}
static char *getTime(void)
{
time_t nowTime;
static char date[30];
memset(date, 0, sizeof(date));
nowTime = time(NULL);
strftime(date, 30, "%Y-%m-%d %H:%M:%S", localtime(&nowTime));
return date;
}
void newDirectory_create(const char *newPath)
{
int i, flag, s, wd;
if (num < NUMBER - 1) {
flag = 0;
for (i = 0; i < num; i++) {
if (wdSet[i].path == NULL) {
flag = 1;
wdSet[i].path = (char *)malloc(PATH_LENGTH);
memset(wdSet[i].path, 0, PATH_LENGTH);
strcpy(wdSet[i].path, newPath);
wd = inotify_add_watch(inotify_fd, newPath, IN_CREATE | IN_DELETE_SELF | IN_MOVE | IN_DELETE);
wdSet[i].wd = wd;
break;
}
}
if (flag == 0) {
wdSet[num].path = (char *)malloc(PATH_LENGTH);
memset(wdSet[num].path, 0, PATH_LENGTH);
strcpy(wdSet[num].path, newPath);
wd = inotify_add_watch(inotify_fd, newPath, IN_CREATE | IN_DELETE_SELF | IN_MOVE | IN_DELETE);
wdSet[num].wd = wd;
num++;
}
} else {
exit(EXIT_FAILURE);
}
}
int directoryTree(const char *pathname, const struct stat *statbuf,
int type, struct FTW *ftw)
{
switch (statbuf->st_mode & S_IFMT) {
case S_IFDIR:
newDirectory_create(pathname);
break;
}
return 0;
}
int filter(char *name)
{
if (*name == '.' || *(name + strlen(name) - 1) == '~')
return 0;
else
return 1;
}
int displayEvent(struct inotify_event *event)
{
int i, wd, fd, nftw_fd, j;
struct stat st;
char newPath[NAME_MAX];
if ((filter(event->name) == 1) && (strcmp(event->name, "4913") != 0)) {
for (i = 0; i < num; i++){
if (event->wd == wdSet[i].wd){
if (event->mask & IN_CREATE) {
chdir(wdSet[i].path);
stat(event->name, &st);
if ((st.st_mode & S_IFMT) == S_IFDIR) {
if (realpath(event->name, newPath) == NULL)
exit(EXIT_FAILURE);
newDirectory_create(newPath);
}
fprintf(fp, "%s, name = %s, IN_CREATE, wd = %d, path = %s\n", getTime(), event->name, event->wd, wdSet[i].path);
fflush(fp);
break;
}
else if (event->mask & IN_DELETE) {
printf("%s\n", getTime());
fprintf(fp, "%s, name = %s, IN_DELETE, wd = %d, path = %s\n", getTime(), event->name, event->wd, wdSet[i].path);
fflush(fp);
break;
}
else if (event->mask & IN_DELETE_SELF) {
inotify_rm_watch(inotify_fd, wdSet[i].wd);
free(wdSet[i].path);
wdSet[i].path = NULL;
break;
}
else if (event->mask & IN_MOVED_FROM) {
fprintf(fp, "%s, name = %s, IN_MOVED_FROM, wd = %d, path = %s\n", getTime(), event->name, event->wd, wdSet[i].path);
fflush(fp);
for (i = 0; i < num; i++) {
if (event->wd == wdSet[i].wd) {
strcpy(newPath, wdSet[i].path);
strcat(newPath, "/");
strcat(newPath, event->name);
for (j = 0; j < num; j++) {
if (wdSet[j].path == NULL)
continue;
if (strstr(wdSet[j].path, newPath) != NULL) {
inotify_rm_watch(inotify_fd, wdSet[j].wd);
free(wdSet[j].path);
wdSet[j].path = NULL;
}
}
break;
}
}
break;
}
else if (event->cookie > 0 && (event->mask & IN_MOVED_TO)) {
fprintf(fp, "%s, name = %s, IN_MOVED_TO, wd = %d, path = %s\n", getTime(), event->name, event->wd, wdSet[i].path);
fflush(fp);
strcpy(newPath, wdSet[i].path);
strcat(newPath, "/");
strcat(newPath, event->name);
stat(newPath, &st);
if ((st.st_mode & S_IFMT) == S_IFDIR) {
nftw_fd = nftw(newPath, directoryTree, 20, 0);
close(nftw_fd);
}
break;
}
}
}
}
}
void start(char *workDir)
{
FILE *pidFp = NULL;
char monitorPID[PATH_LENGTH];
sprintf(monitorPID, "%s/monitor.pid", workDir);
pidFp = fopen(monitorPID, "w");
if (pidFp == NULL)
exit(EXIT_FAILURE);
fprintf(pidFp, "%d", getpid());
fclose(pidFp);
}
void stop(char *workDir)
{
FILE *pidFp = NULL;
pid_t pid;
char path[20], monitorPID[PATH_LENGTH];
sprintf(monitorPID, "%s/monitor.pid", workDir);
if(access(monitorPID, F_OK) == 0) {
pidFp = fopen(monitorPID, "r");
if (pidFp == NULL)
exit(EXIT_FAILURE);
fseek(pidFp, 0, SEEK_END);
if (ftell(pidFp) == 0) {
printf("%s is empty!\n", monitorPID);
fclose(pidFp);
remove(monitorPID);
goto FAIL;
}
fseek(pidFp, 0, SEEK_SET);
fscanf(pidFp, "%d", &pid);
sprintf(path, "/proc/%d/comm", pid);
if (access(path, F_OK) == 0) {
pidFp = freopen(path, "r", pidFp);
if (pidFp == NULL)
exit(EXIT_FAILURE);
char name[30];
fscanf(pidFp, "%s", name);
if (strcmp(name, processName) == 0) {
while (1) {
if (kill(-pid, 0) == -1 && errno == ESRCH)
break;
kill(-pid, SIGTERM);
}
fclose(pidFp);
remove(monitorPID);
printf("stop %s: \033[32msuccess\033[0m\n", processName);
return;
} else {
fclose(pidFp);
remove(monitorPID);
}
}
}
FAIL:
printf("stop %s:\033[31m failed, process no exits! \033[0m\n", processName);
}
void usage(char *file)
{
printf("Usage: %s -d monitor_directory [start|stop|restart]\n", file);
exit(EXIT_FAILURE);
}
int main(int argc, char *argv[])
{
int nftw_fd, wd, len, i, ch, s;
char monitorEvent[LENGTH], workDir[PATH_LENGTH],
localDir[PATH_LENGTH], logFile[PATH_LENGTH],
*p = NULL, monitorPID[PATH_LENGTH];
struct inotify_event *itfEvent = NULL;
struct stat st;
if ((argc > 1 && strcmp(argv[1], "--help") == 0) ||
(argc > 1 && strcmp(argv[1], "-h") == 0) ||
(argc != 4))
usage(argv[0]);
getcwd(localDir, LENGTH);
sprintf(workDir, "%s/monitorConf", localDir);
getProcessName(processName);
if (access(workDir, F_OK) == -1) {
mkdir(workDir, 0766);
}
while ((ch = getopt(argc, argv, "d:") != -1)) {
switch (ch) {
case 'd':
s = stat(optarg, &st);
if (st.st_mode & S_IFMT != S_IFDIR) {
printf("Error: the monitor file must be a directory!\n");
usage(argv[0]);
}
strcpy(path_backup, optarg);
break;
}
}
if (strcmp(argv[argc - 1], "start") == 0 ) {
sprintf(monitorPID, "%s/monitor.pid", workDir);
if (access(monitorPID, F_OK) == 0) {
FILE *startFp = NULL;
if ((startFp = fopen(monitorPID, "r")) == NULL) {
printf("open %s error!\n", monitorPID);
exit(EXIT_FAILURE);
}
fseek(startFp, 0, SEEK_END);
if (ftell(startFp) == 0) {
printf("%s is empty!\n", monitorPID);
remove(monitorPID);
exit(EXIT_FAILURE);
}
fseek(startFp, 0, SEEK_SET);
int pid;
fscanf(startFp, "%d", &pid);
fclose(startFp);
char exe[PATH_LENGTH];
sprintf(exe, "/proc/%d/exe", pid);
if (access(exe, F_OK) != -1) {
printf("start %s:\033[31m failed, process exits! \033[0m\n", processName);
exit(EXIT_FAILURE);
}
}
} else if (strcmp(argv[argc - 1], "stop") == 0) {
stop(workDir);
exit(EXIT_SUCCESS);
} else if (strcmp(argv[argc - 1], "restart") == 0) {
stop(workDir);
} else {
printf("Error: incorrect operation!\n");
usage(argv[0]);
}
printf("start %s: \033[32msuccess\033[0m\n", processName);
daemon(0, 0);
start(workDir);
sprintf(logFile, "%s/monitor.log", workDir);
fp = fopen(logFile, "a+");
inotify_fd = inotify_init();
nftw_fd = nftw(argv[argc - 2], directoryTree, 20, 0);
close(nftw_fd);
while(1) {
memset(monitorEvent, 0, sizeof(monitorEvent));
len = read(inotify_fd, monitorEvent, sizeof(monitorEvent));
for (p = monitorEvent; p < monitorEvent + len;) {
itfEvent = (struct inotify_event *) p;
if ((itfEvent->mask & IN_CREATE) && (strcmp(itfEvent->name, "4913") == 0)) {
break;
} else if ((itfEvent->mask & (IN_CREATE | IN_DELETE_SELF | IN_MOVE | IN_DELETE))) {
displayEvent(itfEvent);
}
p += sizeof(struct inotify_event) + itfEvent->len;
}
}
}