本指南将阐述如何在Linux系统中利用文件系统事件(也称为通知)功能,以便在目录中出现新文件时立即收到通知。 这项技术可作为触发器,用于自动化系统上的各种常规任务。
我们将创建一个脚本,该脚本能够监控特定目录,并对新添加的文件执行操作。 当检测到新文件时,脚本会自动将其压缩并移动到另一个指定目录。 该脚本的核心功能依赖于名为inotify-tools
的工具包,它利用了inotify子系统。 首先,我们需要安装此工具包并进行一些初步实验。
安装 inotify-tools 和 gzip
对于使用Ubuntu或任何基于Debian的Linux发行版的用户,可以通过apt-get
命令在系统中安装必要的软件包。 而其他Linux发行版的用户,则应使用其各自发行版的包管理工具进行安装。
sudo apt-get install inotify-tools gzip
初探 inotify-tools
让我们先从观察一个目录开始,看看当新文件到达时会触发哪些事件。我们将使用inotifywatch
工具,它是inotify-tools
工具包的一部分。首先,创建一个名为incoming
的新目录:
mkdir incoming
通过执行以下命令开始监视这个目录:
inotifywatch -v incoming
此命令指示inotify监控incoming
目录内的所有文件系统事件。 -v
选项会使该工具打印出额外的详细信息。 由于我们没有指定超时时间(-t
选项),命令将持续收集事件,直到我们按下CTRL+C
退出。此时,您的终端应该显示类似下面的内容:
现在,打开一个新的终端窗口(或标签页),切换到incoming
目录。 使用touch
命令创建一个名为newfile
的新文件。
cd incoming/ touch newfile
然后,返回到第一个终端窗口,并按下CTRL+C
停止inotifywatch
。
控制台将显示一个事件表格,其中显示了create
、open
、attrib
和close_write
事件的实例。 这四个事件发生在当我们使用touch
命令创建一个新文件时,设置文件的访问属性,打开文件写入一个空的终止符,然后关闭文件之后。 这些只是inotify-tools
可以在文件系统上监视的众多事件中的一部分。 您可以在inotifywatch
的帮助文档中查看完整的事件列表。
在本例中,我们只关注以下两个事件:
create
– 当目标目录中创建新文件时。moved_to
– 当文件从其他位置移动到目标目录时。
我们再次尝试使用inotifywatch
,但这次只监控这两个事件。在第一个终端窗口中运行此命令:
inotifywatch -v -e create -e moved_to incoming
在第二个终端窗口或标签页中,我们尝试创建一个新文件,修改它的内容,然后将一个文件从其他位置移动到目标目录。所有这些命令都从主目录运行。
touch incoming/created echo Testing123 >> incoming/created touch /tmp/created2 mv /tmp/created2 incoming/
返回第一个终端窗口,按下CTRL+C
停止inotifywatch
。我们将看到如下的输出:
只统计了两个事件:创建名为created
的文件,以及将名为created2
的现有文件移动进来。其他所有的操作,比如对created
的修改,都被忽略了。
监控目录并执行任务
既然我们了解了要跟踪的事件,我们可以使用另一个名为inotifywait
的工具,该工具会阻塞执行直到目标目录中创建或移动文件。 我们将使用与inotifywatch
相同的参数,并指定我们希望如何格式化文件名以用于我们的任务。
在开始之前,我们需要一个目录来存储已经处理过的文件。创建一个名为processed
的目录:
mkdir processed
接下来,创建一个名为watch-incoming.sh
的新脚本,并添加以下内容:
#!/bin/bash TARGET=~/incoming/ PROCESSED=~/processed/ inotifywait -m -e create -e moved_to --format "%f" $TARGET | while read FILENAME do echo Detected $FILENAME, moving and zipping mv "$TARGET/$FILENAME" "$PROCESSED/$FILENAME" gzip "$PROCESSED/$FILENAME" done
这个脚本使用-m
选项来执行inotifywait
命令。这使得该命令无限期地监视变更。每当检测到新事件时,文件名会传递给read
命令并赋值给FILENAME
变量。然后执行while
循环下的代码块,首先将文件移动到processed
目录,然后对其进行gzip压缩。原始文件会被压缩文件替换,文件名以.gz
结尾。
让我们授予这个脚本的执行权限并从我们的主目录运行它。
chmod u+x watch-incoming.sh ./watch-incoming.sh
打开第二个终端窗口,在incoming
目录中创建一个新文件。列出incoming
和processed
目录的内容,查看检测到的事件结果:
我们复制到incoming
目录的原始文本文件被脚本检测到,复制到processed
目录,然后使用gzip压缩。
现在,我们可以执行更有趣的任务,因为我们能够监控到达目录的新文件。例如,我们可以为图像文件添加水印,将原始视频压缩为mp4格式,甚至将我们看到的每个新文件上传到Amazon S3存储桶。这个脚本是开始构建您自己的工作流程,并自动化系统上的常用任务的一个很好的起点。