Как отслеживать файл, чтобы узнать, какой процесс запишет или удалит его в будущем

#linux

#linux

Вопрос:

Процесс запишет файл в будущем, как я могу использовать инструменты Linux или написать код, чтобы определить, какой процесс это сделал?

Комментарии:

1. Вы можете использовать lsof для этого.

2. @Dominique Я знаю lsof или fuser могу узнать, какой процесс использует файл, если процесс не использует этот файл, но будет использовать его в будущем, могу ли я использовать lsof ?

3. Как насчет этого: linux.die.net/man/1/inotifywait

4. @jamieguinan inotifywait может отслеживать изменения файла

5. До появления fanotify , благодаря этому вопросу.

Ответ №1:

fanotify может помочь вам отслеживать все файлы в вашей системе. когда к файлу был получен доступ, fanotify он сообщит вам pid этого процесса.

fanotify более мощный, чем inotify и dnotify , они не могут сообщить вам, какой процесс записывает файл, а только сообщают вам, что файл был подключен

Это использование для командной программы Linux:

 #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 *) amp;buf, sizeof(buf));
       if (len == -1 amp;amp; 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 amp; FAN_OPEN_PERM) {
                   printf("FAN_OPEN_PERM: ");
                   /* Allow file to be opened */
                   response.fd = metadata->fd;
                   response.response = FAN_ALLOW;
                   write(fd, amp;response,
                         sizeof(struct fanotify_response));
               }
               /* Handle closing of writable file event */
               if (metadata->mask amp; 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] = '';
               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 MOUNTn", 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 amp; POLLIN) {
               /* Console input is available: empty stdin and quit */
               while (read(STDIN_FILENO, amp;buf, 1) > 0 amp;amp; buf != 'n')
                   continue;
               break;
           }
           if (fds[1].revents amp; POLLIN) {
               /* Fanotify events are available */
               handle_events(fd);
           }
       }
   }
   printf("Listening for events stopped.n");
   exit(EXIT_SUCCESS);
}
 

Комментарии:

1. Это полезно для меня