【linux】inotify监控目录内文件的变化(create、delete、move_from、move_to)

程序 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';
    //printf("path: %s\n", processPath);
	ch = strrchr(processPath,  '/');
	if(ch == NULL)
        exit(EXIT_FAILURE);
    ch++;
    strncpy(processName, ch, strlen(ch));
    processName[strlen(processName) + 1] = '\0';
    //printf("processName: %s, %d\n", processName, strlen(processName));
}

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 {
		//printf("num >= NUMBER\n");
		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);
					//printf("newPath=%s\n", newPath);
					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);
			    //goto FAIL;
            }
		} 
	}
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;
		}
	}
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值