用inotifywait监控文件系统

起因:文件共享服务器原本开启的NFS共享,发现在Windows客户端访问并不稳定,想改用Samba共享,但是很多人在用NFS访问,想先同时开启两种共享同时支持访问,遇到的问题是通过NFS客户端创建出的文件权限是0755,通过Samba客户端不可写,而通过Samba客户端创建的文件可以通过create mask和 force create mask指定成任意的权限,可以保证NFS客户端可写,而且没有找到NFS如何配置可以控制新建文件的权限。于是想换个思路监视文件创建,在创建后立刻修改权限。

inotifywait 异步文件系统监控机制

inotify 一种强大的、细粒度的、异步文件系统监控机制,它满足各种各样的文件监控需要,可以监控文件系统的访问属性、读写属性、权限属性、删除创建、移动等操作,也就是可以监控文件发生的一切变化。
inotify-tools 是一个C库和一组命令行的工作提供Linux下inotify的简单接口。inotify-tools安装后会得到inotifywait和inotifywatch这两条命令:

inotifywait命令 可以用来收集有关文件访问信息,Linux发行版一般没有包括这个命令,需要安装inotify-tools,这个命令还需要将inotify支持编译入Linux内核,好在大多数Linux发行版都在内核中启用了inotify。
inotifywatch命令 用于收集关于被监视的文件系统的统计数据,包括每个 inotify 事件发生多少次。

安装

1
apt install inotify-tools

修改最大监控文件数

1
sysctl -w fs.inotify.max_user_watches="1000000"

可以通过下面的命令确认修改成功

1
cat /proc/sys/fs/inotify/max_user_watches

永久修改(重启后自动修改)

vim /etc/sysctl.conf

追加 fs.inotify.max_user_watches=1000000

编写监控脚本

1
2
3
4
5
6
7
#!/bin/bash
inotifywait -mrq --timefmt '%y-%m-%d %H:%M' --format '%T %e %w%f' -e create /data/share/ | while read DATE TIME EVENT FILEPATH
do
echo "${FILEPATH} was ${EVENT} at ${DATE}_${TIME}"
chmod 777 "${FILEPATH}"
done

此脚本监控/data/share目录下的create事件,一旦出现create事件则调用chmod把刚创建的文件权限修改为0777。

BTW:通常情况可以正常工作,实际测试时,如果在创建后立即重命名,可能会导致监控脚本来不及处理,在执行到chmod时文件已经不存在。

注意这里把%w%f拼在一起用FILEPATH作为最后一个变量读取出来是可以解决路径或文件名有空格的问题。

其他选项

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
inotifywait 3.14
Wait for a particular event on a file or set of files.
Usage: inotifywait [ options ] file1 [ file2 ] [ file3 ] [ ... ]
Options:
-h|--help Show this help text.
@<file> Exclude the specified file from being watched.
--exclude <pattern>
Exclude all events on files matching the
extended regular expression <pattern>.
--excludei <pattern>
Like --exclude but case insensitive.
-m|--monitor Keep listening for events forever. Without
this option, inotifywait will exit after one
event is received.
-d|--daemon Same as --monitor, except run in the background
logging events to a file specified by --outfile.
Implies --syslog.
-r|--recursive Watch directories recursively.
--fromfile <file>
Read files to watch from <file> or `-' for stdin.
-o|--outfile <file>
Print events to <file> rather than stdout.
-s|--syslog Send errors to syslog rather than stderr.
-q|--quiet Print less (only print events).
-qq Print nothing (not even events).
--format <fmt> Print using a specified printf-like format
string; read the man page for more details.
--timefmt <fmt> strftime-compatible format string for use with
%T in --format string.
-c|--csv Print events in CSV format.
-t|--timeout <seconds>
When listening for a single event, time out after
waiting for an event for <seconds> seconds.
If <seconds> is 0, inotifywait will never time out.
-e|--event <event1> [ -e|--event <event2> ... ]
Listen for specific event(s). If omitted, all events are
listened for.

Exit status:
0 - An event you asked to watch for was received.
1 - An event you did not ask to watch for was received
(usually delete_self or unmount), or some error occurred.
2 - The --timeout option was given and no events occurred
in the specified interval of time.

Events:
access file or directory contents were read
modify file or directory contents were written
attrib file or directory attributes changed
close_write file or directory closed, after being opened in
writable mode
close_nowrite file or directory closed, after being opened in
read-only mode
close file or directory closed, regardless of read/write mode
open file or directory opened
moved_to file or directory moved to watched directory
moved_from file or directory moved from watched directory
move file or directory moved to or from watched directory
create file or directory created within watched directory
delete file or directory deleted within watched directory
delete_self file or directory was deleted
unmount file system containing file or directory unmounted