如何在 rename() 過後持續使用 inotify 來監控文件?
由於工作上遇到此問題,請教了咕狗大神半天也找不太到合適的答案,只好自己研究了。
平常使用 inotify() 可以拿來監控文件的變更,最常見的就是透過 IN_CLOSE_WRITE 這個 mask 來監視,範例如下:
某天發現,某一支程式內會針對範例的 "/sysconf/conf.network" 做 rename() 的動作,這將導致 inotify 誤認為檔案已刪除,而發出一個 mask 訊號 IN_IGNORED,告訴 inotify 不再監控,進而失去對此文件的掌控。
要避免此方法其實很簡單(當初找了老半天),只要在偵測到此訊號時,重新透過 inotify_add_watch() 來建立新的 inotify 即可。底下的範例會先將舊有的 inotify 透過 inotify_rm_watch() 移除掉,並 close(fd),然後再重新 inotify_init()、inotify_add_watch() 與 read():
參考資料:
1. inotify介绍
2. inotify failed when /etc/hosts file change
3. Linux下使用inotify监控文件动作
PS. Blog 版面好像太小了,貼上這種大程式碼,閱讀起來有點慘不忍睹阿...
平常使用 inotify() 可以拿來監控文件的變更,最常見的就是透過 IN_CLOSE_WRITE 這個 mask 來監視,範例如下:
Net->network_ity5.ity_fd = inotify_init(); Net->network_ity5.wd = inotify_add_watch( Net->network_ity5.ity_fd, "/sysconf/conf.network", IN_CLOSE_WRITE ); Net->network_ity5.length = read( Net->network_ity5.ity_fd, Net->network_ity5.ity_buffer, ITY_BUF_LEN ); while ( Net->network_ity5.ity_i < Net->network_ity5.length ) { if (event->mask & IN_CLOSE_WRITE) { .... } }
某天發現,某一支程式內會針對範例的 "/sysconf/conf.network" 做 rename() 的動作,這將導致 inotify 誤認為檔案已刪除,而發出一個 mask 訊號 IN_IGNORED,告訴 inotify 不再監控,進而失去對此文件的掌控。
要避免此方法其實很簡單(當初找了老半天),只要在偵測到此訊號時,重新透過 inotify_add_watch() 來建立新的 inotify 即可。底下的範例會先將舊有的 inotify 透過 inotify_rm_watch() 移除掉,並 close(fd),然後再重新 inotify_init()、inotify_add_watch() 與 read():
while ( Net->network_ity5.ity_i < Net->network_ity5.length ) { struct inotify_event *event = ( struct inotify_event *) &Net->network_ity5.ity_buffer[ Net->network_ity5.ity_i ]; /* * If the file was renamed, we must close the old inotify and re-crate the inotify again. */ if (event->mask & IN_IGNORED) { DBGPRINT(RT_DEBUG_INFO, ("inotify The file conf.network_ity5 was IN_IGNORED\n")); /* Remove inotify and close fd. */ inotify_rm_watch( Net->network_ity5.ity_fd, Net->network_ity5.wd ); close( Net->network_ity5.ity_fd ); /* Re-init the inotify. */ Net->network_ity5.ity_fd = inotify_init(); if (Net->network_ity5.ity_fd < 0) { DBGPRINT(RT_DEBUG_BOSS, ("creat network_ity5 fail .. \n")); return -1; } /* Recreate inotify watch */ Net->network_ity5.wd = inotify_add_watch( Net->network_ity5.ity_fd, "/sysconf/conf.network", IN_CLOSE_WRITE ); Net->network_ity5.length = read( Net->network_ity5.ity_fd, Net->network_ity5.ity_buffer, ITY_BUF_LEN ); if ( Net->network_ity5.length < 0 ) { perror( "network_ity5 read length < 0" ); } /* Continue the while loop to re-detect the inotify. */ continue; } }
參考資料:
1. inotify介绍
2. inotify failed when /etc/hosts file change
3. Linux下使用inotify监控文件动作
PS. Blog 版面好像太小了,貼上這種大程式碼,閱讀起來有點慘不忍睹阿...
留言
張貼留言