Linux用inotify監聽檔案和目錄
日常應用中,常常會遇到以下場景,監控資料夾A,若資料夾中的B檔案發生變化,則執行C命令。Linux下可以通過inotify完成該功能。
自從Linux kernel 2.6.13起,inotify以作為核心的一部份,同時需要glibc 2.4以上版本。
1. 相關函式
inotify_init() – 建立一個inotify例項
inotify_add_watch(int fd, const char *pathname, uint32_t mask) – 加入檔案或目錄到inotify進行監測
inotify_rm_watch(int fd, int wd) – 移除一個watcher
2. 相關結構
struct inotify_event {
int wd; /* Watch descriptor */
uint32_t mask; /* Mask of events */
uint32_t cookie; /* Unique cookie associating related
events (for rename(2)) */
uint32_t len; /* Size of name field */
char name[]; /* Optional null-terminated name */
};
3. Mask
適用於 inotify_add_watch mask 與 read 返回的inotify_event中mask
IN_ACCESS檔案被訪問
IN_ATTRIB檔案屬性發生變化
IN_CLOSE_WRITE以write方式開啟檔案並關閉
IN_CLOSE_NOWRITE以非write方式開啟檔案並關閉
IN_CREATE檔案或目錄被建立
IN_DELETE檔案或目錄被刪除(被監測的資料夾A中B檔案被刪除)
IN_DELETE_SELF被監測的檔案或目錄被刪除(被監測的資料夾A被刪除)
IN_MODIFY檔案被修改
IN_MOVE_SELF被監測的檔案或目錄移動
IN_MOVED_FROM檔案移出被監測的目錄
IN_MOVED_TO檔案移入被監測的目錄
IN_OPEN檔案被開啟
上述flag的集合
IN_ALL_EVENTS以上所有flag的集合
IN_MOVEIN_MOVED_TO|IN_MOVED_FROM
IN_CLOSEIN_CLOSE_WRITE|IN_CLOSE_NOWRITE
不常用的flag
IN_DONT_FOLLOW不follow符號連結 (since 2.6.15)
IN_EXCL_UNLINK當檔案從監測目中unlink後,則不再報告該檔案的相關event,比如監控/tmp使用 (since 2.6.36)
IN_MASK_ADD追打MASK到被監測的pathname
IN_ONESHOT只監測一次
IN_ONLYDIR只監測目錄
僅由read返回
IN_IGNOREDinotify_rm_watch,檔案被刪除或者檔案系統被umount
IN_ISDIR發生事件的是一個目錄
IN_Q_OVERFLOWEvent佇列溢位
IN_UNMOUNT檔案系統unmount
4. 例子
用途:監測指定檔案或目錄(或不指定則為當前目錄)的一切動作。
使用:inotify [檔案或目錄]
[cpp] view plain copy
#include
#include
#include
#include
#include
#include
#include
#define ERROR(text) error(1, errno, “%s”, text)
struct EventMask {
int flag;
const char *name;
};
int freadsome(void *dest, size_t remain, FILE *file)
{
char *offset = (char*)dest;
while (remain) {
int n = fread(offset, 1, remain, file);
if (n == 0) {
return -1;
}
remain -= n;
offset += n;
}
return 0;
}
//http://www.ibm.com/developerworks/cn/linux/l-inotify/
//http://www.jiangmiao.org/blog/2179.html
int main(int argc, char *argv[])
{
const char *target;
if (argc == 1) {
target =”.”;
}
else {
target = argv[1];
}
struct EventMask event_masks[] = {
{ IN_ACCESS,”IN_ACCESS” },
{ IN_ATTRIB,”IN_ATTRIB” },
{ IN_CLOSE_WRITE,”IN_CLOSE_WRITE” },
{ IN_CLOSE_NOWRITE,”IN_CLOSE_NOWRITE” },
{ IN_CREATE,”IN_CREATE” },
{ IN_DELETE,”IN_DELETE” },
{ IN_DELETE_SELF,”IN_DELETE_SELF” },
{ IN_MODIFY,”IN_MODIFY” },
{ IN_MOVE_SELF,”IN_MOVE_SELF” },
{ IN_MOVED_FROM,”IN_MOVED_FROM” },
{ IN_MOVED_TO,”IN_MOVED_TO” },
{ IN_OPEN,”IN_OPEN” },
{ IN_DONT_FOLLOW,”IN_DONT_FOLLOW” },
//{ IN_EXCL_UNLINK, “IN_EXCL_UNLINK” },
{ IN_MASK_ADD,”IN_MASK_ADD” },
{ IN_ONESHOT,”IN_ONESHOT” },
{ IN_ONLYDIR,”IN_ONLYDIR” },
{ IN_IGNORED,”IN_IGNORED” },
{ IN_ISDIR,”IN_ISDIR” },
{ IN_Q_OVERFLOW,”IN_Q_OVERFLOW” },
{ IN_UNMOUNT,”IN_UNMOUNT” },
};
int monitor = inotify_init();
if (-1 == monitor) {
ERROR(“monitor”);
}
int watcher = inotify_add_watch(monitor, target, IN_ALL_EVENTS);
if (-1 == watcher) {
ERROR(“inotify_add_watch error”);
}
FILE *monitor_file = fdopen(monitor, “r”);
char last_name[1024];
char name[1024];
/* event:inotify_event -> name:char[event.len] */
while (true) {
struct inotify_event event;
if (-1 == freadsome(&event, sizeof(event), monitor_file)) {
ERROR(“freadsome error”);
}
if (event.len) {
freadsome(name, event.len, monitor_file);
}
else {
sprintf(name,”FD: %d
“, event.wd);
}
if (strcmp(name, last_name) != 0) {
puts(name);
strcpy(last_name, name);
}
/* 顯示event的mask的含義 */
int i = 0;
for (i = 0; i < sizeof(event_masks) / sizeof(struct EventMask); ++i) {
if (event.mask & event_masks[i].flag) {
printf(” %s
“, event_masks[i].name);
}
}
}
return 0;
}
Linux系統中提供了一套intotify的機制來監視檔案系統的事件,比如建立檔案,開啟,關閉等等。利用這一機制,我們可以很容易寫出監控目錄變化的工具。更何況更有了一個inotify_tools的開源工程呢。inotify_tools對inotify的API做了進一步的封裝,更加方便使用。
下面的例子來源於inotify_tools的示例程式碼,但是做了一些改進。inotify_tools監視一個目錄時,可以得到該目錄變化的資訊。但是在該目錄下,建立一個子目錄後,子目錄中的變化,inotify_tools不能獲取。所以我新增了動態監控目錄的程式碼。
#include
#include
#include
#include
enum {
ACTION_NULL_WD,
ACTION_ADD_WD,
ACTION_DEL_WD,
};
int main(int argc, const char **argv)
{
int err = 0;
if (!inotifytools_initialize()) {
printf(“inotifytools_initialize failedn”);
goto error;
}
inotifytools_initialize_stats();
const char *monitor_path = “.”;
if (argc > 1) {
monitor_path = argv[1];
}
printf(“Monitor dir(%s)n”, monitor_path);
if (!inotifytools_watch_recursively(monitor_path, IN_ALL_EVENTS)) {
printf(“inotifytools_watch_recursively failedn”);
goto error;
}
inotifytools_set_printf_timefmt(“%F %T”);
struct inotify_event * event = inotifytools_next_event(-1);
char path[256];
while (event) {
inotifytools_printf( event, “%T %w%f %en” );
if (IN_ISDIR&event->mask) {
int action = ACTION_NULL_WD;
if ((IN_DELETE|IN_DELETE_SELF|IN_MOVED_FROM)&event->mask) {
action = ACTION_DEL_WD;
snprintf(path, sizeof(path), “%s%s”,
inotifytools_filename_from_wd(event->wd),
event->name);
printf(“Remove path(%s) from wdn”, path);
} else if (((IN_CREATE|IN_MOVED_TO)&event->mask) && (IN_ISDIR&event->mask)) {
action = ACTION_ADD_WD;
snprintf(path, sizeof(path), “%s%s”,
inotifytools_filename_from_wd(event->wd),
event->name);
printf(“Add path(%s) into wdn”, path);
}
if (ACTION_ADD_WD == action) {
if (!inotifytools_watch_recursively(path, IN_ALL_EVENTS)) {
printf(“inotifytools_watch_recursively failedn”);
goto error;
}
} else if (ACTION_DEL_WD == action) {
if (!inotifytools_remove_watch_by_wd(event->wd)) {
printf(“inotifytools_remove_watch_by_wd failed. event->wd(%d)n”, event->wd);
goto error;
}
}
}
event = inotifytools_next_event(-1);
}
printf(“Exitn”);
return 0;
error:
err = inotifytools_error();
printf(“Error(%d)n”, err);
return -1;
}
程式碼很簡單。就是在獲得事件以後,檢查是否為目錄。如果是目錄,則需要進行動態監控的檢查。如果是建立動作,那麼就新增新的監控。如果是刪除動作,就去掉已有的監控wd。
相關文章
- Linux使用inotify-tools監聽檔案或目錄Linux
- Linux 使用 inotify 監控檔案或目錄變化Linux
- Linux檔案和目錄管理Linux
- adb命令管理Linux 檔案和目錄Linux
- 在 Linux 中如何歸檔檔案和目錄Linux
- Linux 檔案與目錄Linux
- Linux的檔案屬性和目錄配置Linux
- 筆記:Linux命令(目錄和檔案管理)筆記Linux
- scp命令 用於Linux之間複製檔案和目錄Linux
- Linux檔案系統、目錄Linux
- Linux檔案及目錄管理Linux
- linux檔案與目錄管理命令Linux
- Linux檔案與目錄管理(2)Linux
- Linux檔案和目錄的粘滯位(sticky bit)Linux
- linux 刪除檔案或目錄——rmLinux
- linux目錄及檔案命令學習Linux
- Linux rm(刪除檔案/目錄) 命令Linux
- Linux常見命令-目錄檔案命令Linux
- Linux檔案系統目錄結構Linux
- Linux 基礎-檔案及目錄管理Linux
- 快速上手Linux核心命令(三):檔案和目錄操作命令Linux
- pythonpyinotify監控檔案與目錄的變化Python
- Linux排查磁碟大檔案或大目錄Linux
- Linux系統的目錄及重要檔案Linux
- Linux中檔案與目錄的區別Linux
- Linux rm命令:刪除檔案或目錄Linux
- 8.var目錄下的檔案和目錄詳解
- Linux中操作工作目錄和檔案目錄Linux
- Linux 檔案與目錄管理常用命令 記錄Linux
- Linux基礎學習——檔案與目錄管理Linux
- linux伺服器目錄檔案的命令操作Linux伺服器
- Linux解壓檔案到指定目錄的方法Linux
- Linux 只複製目錄,不復制目錄下的資料檔案Linux
- Linux 主目錄中的隱藏檔案是幹什麼用的?Linux
- 【ZIP】打包過濾指定目錄和檔案
- 無緩衝檔案IO和目錄操作
- 如何統計 Linux 中檔案和資料夾/目錄的數量Linux
- 在linux下顯示中文目錄和檔名Linux