#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. Это полезно для меня