如何监视文件以找出将来将哪个进程写入或删除该进程

时间:2019-04-18 13:06:33

标签: linux

将来某个进程将写入文件,如何使用linux工具或编写代码来查找是哪个进程?

1 个答案:

答案 0 :(得分:1)

fanotify可以帮助您监视系统术语中的所有文件。当文件被访问后,fanotify会告诉您该过程的信息。

  

fanotifyinotifydnotify更强大,它们不能告诉您哪个进程写入文件,而只能告诉您该文件已被写入

#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <poll.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/fanotify.h>
#include <unistd.h>
/* Read all available fanotify events from the file descriptor 'fd' */
static void handle_events(int fd)
{
   const struct fanotify_event_metadata *metadata;
   struct fanotify_event_metadata buf[200];
   ssize_t len;
   char path[PATH_MAX];
   ssize_t path_len;
   char procfd_path[PATH_MAX];
   struct fanotify_response response;
   /* Loop while events can be read from fanotify file descriptor  */
   for(;;) {
       /* Read some events */
       len = read(fd, (void *) &buf, sizeof(buf));
       if (len == -1 && errno != EAGAIN) {
           perror("read");
           exit(EXIT_FAILURE);
       }
       /* Check if end of available data reached */
       if (len <= 0) 
           break;
       /* Point to the first event in the buffer */
       metadata = buf;
       /* Loop over all events in the buffer */
       while (FAN_EVENT_OK(metadata, len)) {
           /* Check that run-time and compile-time structures match */
           if (metadata->vers != FANOTIFY_METADATA_VERSION) {
               fprintf(stderr,
                       "Mismatch of fanotify metadata version.\n");
               exit(EXIT_FAILURE);
           }
           /* metadata->fd contains either FAN_NOFD, indicating a
*                       queue overflow, or a file descriptor (a nonnegative
*                                             integer). Here, we simply ignore queue overflow. */
           if (metadata->fd >= 0) {
               /* Handle open permission event */
               if (metadata->mask & FAN_OPEN_PERM) {
                   printf("FAN_OPEN_PERM: ");
                   /* Allow file to be opened */
                   response.fd = metadata->fd;
                   response.response = FAN_ALLOW;
                   write(fd, &response,
                         sizeof(struct fanotify_response));
               }
               /* Handle closing of writable file event */
               if (metadata->mask & FAN_CLOSE_WRITE)
                   printf("FAN_CLOSE_WRITE: ");
               /* Retrieve and print pathname of the accessed file */
               snprintf(procfd_path, sizeof(procfd_path),
                        "/proc/self/fd/%d", metadata->fd);
               path_len = readlink(procfd_path, path,
                                   sizeof(path) - 1);
               if (path_len == -1) {
                   perror("readlink");
                   exit(EXIT_FAILURE);
               }
               path[path_len] = '\0';
               printf(" %s %d %d \n", path, metadata->fd, metadata->pid);
               /* Close the file descriptor of the event */
               close(metadata->fd);
           }
           /* Advance to next event */
           metadata = FAN_EVENT_NEXT(metadata, len);
       }
   }
}
int main(int argc, char *argv[])
{
   char buf;
   int fd, poll_num;
   nfds_t nfds;
   struct pollfd fds[2];
   /* Check mount point is supplied */
   if (argc != 2) {
       fprintf(stderr, "Usage: %s MOUNT\n", argv[0]);
       exit(EXIT_FAILURE);
   }
   printf("Press enter key to terminate.\n");
   /* Create the file descriptor for accessing the fanotify API */
   fd = fanotify_init(FAN_CLOEXEC | FAN_CLASS_CONTENT | FAN_NONBLOCK,
                      O_RDONLY | O_LARGEFILE);
   if (fd == -1) {
       perror("fanotify_init");
       exit(EXIT_FAILURE);
   }
   if (fanotify_mark(fd, FAN_MARK_ADD | FAN_MARK_MOUNT,
                     FAN_OPEN_PERM | FAN_CLOSE_WRITE, AT_FDCWD,
                     argv[1]) == -1) {
       perror("fanotify_mark");
       exit(EXIT_FAILURE);
   }
   /* Prepare for polling */
   nfds = 2;
   /* Console input */
   fds[0].fd = STDIN_FILENO;
   fds[0].events = POLLIN;
   /* Fanotify input */
   fds[1].fd = fd;
   fds[1].events = POLLIN;
   /* This is the loop to wait for incoming events */
   printf("Listening for events.\n");
   while (1) {
       poll_num = poll(fds, nfds, -1);
       if (poll_num == -1) {
           if (errno == EINTR)     /* Interrupted by a signal */
               continue;           /* Restart poll() */
           perror("poll");         /* Unexpected error */
           exit(EXIT_FAILURE);
       }
       if (poll_num > 0) {
           if (fds[0].revents & POLLIN) {
               /* Console input is available: empty stdin and quit */
               while (read(STDIN_FILENO, &buf, 1) > 0 && buf != '\n')
                   continue;
               break;
           }
           if (fds[1].revents & POLLIN) {
               /* Fanotify events are available */
               handle_events(fd);
           }
       }
   }
   printf("Listening for events stopped.\n");
   exit(EXIT_SUCCESS);
}