ファイルの変更を監視
Linux だと inotify(2) を利用してできる.poll(2) 等と組み合わせるといい.*BSD とか Mac OS X とかだと kqueue(2) を使うらしいけどあんまり調べてない.
監視対象のファイルが削除されるか C-c されると止まる.
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <stddef.h> #include <errno.h> #include <poll.h> #include <sys/inotify.h> int main(int argc, char *argv[]) { if (argc != 2) { printf("usage: %s filename\n", argv[0]); exit(EXIT_SUCCESS); } const int fd = inotify_init(); if (fd < 0) { perror("inotify_init"); exit(EXIT_FAILURE); } const int wd = inotify_add_watch(fd, argv[1], IN_MODIFY | IN_DELETE_SELF); if (wd < 0) { perror("inotify_add_watch"); exit(EXIT_FAILURE); } while (1) { struct pollfd fds[1]; fds[0].fd = fd; fds[0].events = POLLIN | POLLERR; int nfds = poll(fds, 1, -1); if (nfds < 0) { if (errno == EINTR) { goto FINISH; } else { perror("poll"); exit(EXIT_FAILURE); } } else if (nfds > 0) { char buf[1024]; const ssize_t s = read(fd, buf, sizeof buf); if (s < 0) { perror("read"); exit(EXIT_FAILURE); } int i = 0; while (i < s) { const struct inotify_event *ev = (const struct inotify_event *)buf; i += offsetof(struct inotify_event, name) + ev->len; if (ev->mask & IN_MODIFY) { puts("modified"); } else if (ev->mask & IN_DELETE_SELF) { puts("deleted"); goto FINISH; } } } } FINISH: close(fd); return 0; }
しかし C で書くのも面倒.Ruby + EventMachine でもっと手軽に扱える.
#!/usr/bin/ruby require 'eventmachine' module Watcher def file_modified puts 'modified' end def file_deleted puts 'deleted' EM.stop_event_loop end end EM.kqueue = true if EM.kqueue? EM.run do EM.watch_file ARGV.first, Watcher end