fswatch 安装使用

环境信息

  • Centos 7
  • fswatch-1.17.1

安装

Centos 7 默认安装的 gcc 版本太低,无法满足 fswatch-1.17.1 的编译配置要求,需要首先升级 gcc 版本,本示例中 gcc-8.3.0 安装位置为 /usr/local/gcc-8.3.0/,如果系统安装的 gcc 版本符合要求,无需在 ./configure 时指定 gcc 环境变量 CXX=/usr/local/gcc-8.3.0/bin/g++

wget https://github.com/emcrisostomo/fswatch/archive/refs/tags/1.17.1.tar.gz
tar -xf 1.17.1.tar.gz
cd fswatch-1.17.1/
sh autogen.sh

./configure CXX=/usr/local/gcc-8.3.0/bin/g++ --prefix=/usr/local/fswatch-1.17.1

make
make install

使用

常用选项。参考文档安装 man 手册 后可以查看详细的帮助文档

fswatch 会为监控到的每条事件记录以下信息

  • timestamp - 事件发生的时间戳
  • path - 触发事件的文件(夹)路径
  • event types - 空格分割的事件类型
选项 说明 示例
-0, --print0 ASCII NUL character (\0) as line separator
Since file names can potentially contain any character but NUL, this option assures that the output of fswatch can be safely parsed using NUL as delimiter, such as using xargs -0 and the shell builtin read -d ''.
使用示例
-1, --one-event Exit fswatch after the first set of events is received
--event name can be used multiple times
-e, --exclude regexp Exclude paths matching regexp, Multiple exclude filters can be specified using this option multiple times
-i, --include regexp Include paths matching regexp
-f, --format-time format Print the event time using the specified format
-I, --insensitive Use case insensitive regular expressions
-m, --monitor name Uses the monitor specified by name
可用的 monitor:
- inotify_monitor
- poll_monitor
-r, --recursive Watch subdirectories recursively
-t, --timestamp Print the event timestamp.
-u, --utf-time Print the event time in UTC format. When this option is not specified, the time is printed using the system local time, as defined by localtime
-l, --latency latency 监听间隔,默认1s

常用事件

事件 说明 示例
NoOp Idle event, optionally issued when no changes were detected
Created The object has been created.
Updated The object has been updated. The kind of update is monitor-dependent.
Removed The object has been removed.
Renamed The object has been renamed.
OwnerModified The object’s owner has changed.
AttributeModified An object’s attribute has changed.
MovedFrom The object has moved from this location to a new location of the same file system.
MovedTo The object has moved from another location in the same file system into this location.
IsFile The object is a regular file.
IsDir The object is a directory.
IsSymLink The object is a symbolic link.
Link The object link count has changed.
Overflow The monitor has overflowed.

使用示例

输出事件的行分隔符

以下示例中监视文件 nohup.out,输出事件的每一行使用 \0 分割,read 读取时也使用 \0 ("") 分割,可以防止文件名中包含了空格,使用 read 时读取文件名不全。

$ fswatch -0 nohup.out | while read -d "" file; do echo ${file}; done
/root/nohup.out
/root/nohup.out
/root/nohup.out

使用 xargs 处理监听事件

$ fswatch -0 [opts] [paths] | xargs -0 -n 1 -I {} [command]

  • fswatch -0 will split records using the NUL character.

  • xargs -0 will split records using the NUL character. This is required to correctly match impedance with fswatch.

  • xargs -n 1 will invoke command every record. If you want to do it every x records, then use xargs -n x.

  • xargs -I {} will substitute occurrences of {} in command with the parsed argument. If the command you are running
    does not need the event path name, just delete this option. If you prefer using another replacement string, substi‐
    tute {} with yours.

以下示例监视文件变化后进行备份

fswatch -0 nohup.out | xargs -0 -I {} cp {} {}.`date +%Y%m%d%H%M%S`

以上命令中 date +%Y%m%d%H%M%S 只会被计算一次,假如第一次执行时 date +%Y%m%d%H%M%S = nohup.out.20230609132143,那么之后每次触发 xargs,变量 date +%Y%m%d%H%M%S 的值都是 nohup.out.20230609132143不会被重新计算

常见问题

Event queue overflow

执行以下命令,过一段时间后会输出 Event queue overflow

$ fswatch -0 nohup.out | xargs -0 -I {} cp {} {}.`date +%Y%m%d%H%M%S`
Event queue overflow.
Status code: 1

解决方法 可以选择以下之一。

  1. 使用 poll_monitor monitor 而不是默认的 inotify_monitor

    fswatch -0 --monitor=poll_monitor nohup.out | xargs -0 -I {} cp {} {}.`date +%Y%m%d%H%M%S`
  2. 此限制是因为内核参数限制,主要参数 fs.inotify.max_queued_events [1]

    查看内核参数 fs.inotify.max_queued_events 的值,默认值为 16384

    $ sysctl fs.inotify.max_queued_events
    fs.inotify.max_queued_events = 16384

    修改默认值后,重新测试,结果正常

    $ sysctl fs.inotify.max_queued_events=1000000
    fs.inotify.max_queued_events = 1000000

    $ sysctl fs.inotify.max_queued_events
    fs.inotify.max_queued_events = 1000000

    永久修改此参数的值,可以将其写入内核配置文件 /etc/sysctl.conf

脚注