监视目录树的更改

1. 概述

在本教程中,我们将学习如何使用 inotifywait 监视目录树的更改。例如,我们将了解如何检测何时创建新文件。

我们将从对问题的介绍开始。然后,我们将了解 inotify 事件。最后,我们将讨论 inotifywait 命令以及如何使用它来解决问题。

2. 依赖关系

由于我们的示例将使用 inotifywait 命令,因此我们需要确保它已安装。如果未安装,我们可以通过安装 inotify-tools 包来添加它。如果我们有 Debian 发行版或类似发行版,我们可以以 root 身份运行 apt-get 命令来安装软件包:

apt-get install inotify-tools

另一方面,如果我们有 Red Hat 发行版或类似发行版,我们可以使用 yum 命令,但首先,我们必须安装 epel-release 存储库:

yum install epel-release
yum install inotify-tools

3. 问题介绍

让我们从一个名为 main 的目录开始,它包含几个子目录。使用 tree 命令,我们可以看到我们的主目录树:

tree main/
main/
├── 1
│   ├── 1
│   └── 2
│       └── 1
├── 2
└── 3
    ├── 1
    └── 2
        └── 1
            └── 1

10 directories, 0 files

首先,我们将监视此目录树。例如,我们可以知道文件何时创建或删除、打开、写入、读取或关闭。然后,当我们检测到此目录树上的事件时,我们将使用此信息来运行其他程序。例如,当进程删除此目录树中的文件时,我们可以提醒用户。

4. 了解 inotify 事件

在 Linux 中,我们可以使用 inotify 接口来监控目录或文件。为此,我们向目录或文件添加监视。当我们将手表添加到文件时,我们可以监控它。例如,我们将知道进程何时打开、修改、读取、关闭、移动或删除文件。当我们将监视添加到目录时,我们还会监视该目录中任何文件中的事件。此外,我们可以知道另一个进程是否在该目录中创建、删除或移动文件。我们可以选择监视所有事件或仅监视其中的一些事件。当任何这些事件发生时,系统将通知我们。

5.使用 inotifywait

我们可以使用 inotifywait 命令来监视目录树。要监视目录树(包括其子目录),我们将使用 -r 参数。此外,我们必须使用 -m 参数。这会将 inotifywait 配置为永远监视目录。否则,inotifywait 将在第一个事件后退出。让我们看看如何监视目录中的任何事件:

inotifywait -m -r main
Setting up watches. Beware: since -r was given, this may take a while!
Watches established.

这样,inotifywait 命令将继续在前台运行,等待事件。现在,当 inotifywait 仍在运行时,让我们打开一个新的 shell 并在 main/1/2/file1 >运行 echo 示例。此命令在 main/1/2 文件夹中创建一个新文件让我们回到运行 inotifywait 的 shell 以查看其输出:

main/1/2/ CREATE file1
main/1/2/ OPEN file1
main/1/2/ MODIFY file1
main/1/2/ CLOSE_WRITE,CLOSE file1

我们可以看到 inotifywait 输出有三列。首先是基目录,然后是事件,最后是触发该事件的文件。现在,让我们在 main/2 目录中创建一个名为 1 的新文件夹。然后,我们将在新目录中创建一个名为 file1 的新文件:

mkdir main/2/1
echo example > main/2/1/file1

让我们看看 inotifywait 的输出:

main/2/ CREATE,ISDIR 1
main/2/ OPEN,ISDIR 1
main/2/ ACCESS,ISDIR 1
main/2/ CLOSE_NOWRITE,CLOSE,ISDIR 1
main/2/1/ CREATE file1
main/2/1/ OPEN file1
main/2/1/ MODIFY file1
main/2/1/ CLOSE_WRITE,CLOSE file1

我们可以注意到 inotifywait 会自动监视新目录中的事件。最后,让我们看看如何指定要监视的确切事件。为此,我们将使用 -e 参数并添加用逗号分隔的所需事件。首先,让我们用 Ctrl+C 完成前面的 inotifywait 命令。然后,让我们只监视创建和修改事件:

inotifywait -m -r -e create,modify main

现在,让我们写入 main/1/2/file1 文件,然后在 main/1/2 目录中创建一个名为 file2 的新空文件:

echo example2 >> main/1/2/file1
touch main/1/2/file2

让我们看看新的输出:

main/1/2/ MODIFY file1
main/1/2/ CREATE file2

6. 将 inotifywait 输出与另一个脚本集成

到目前为止,我们已经学会了如何使用 inotifywait。 所以现在,让我们创建一个脚本来运行另一个程序,具体取决于事件 inotifywait 报告。首先,让我们编写一个运行 xmessage 的函数来通知用户文件已被删除:

file_removed() {
    xmessage "$2 was removed from $1" &
}

此函数接收两个参数。第一个是目录,另一个是已删除的文件。此外,我们将在后台运行 xmessage,因此该函数不会阻塞。然后,让我们编写两个函数,以便在修改和创建文件时写入日志文件:

file_modified() {
    TIMESTAMP=`date`
    echo "[$TIMESTAMP]: The file $1$2 was modified" >> monitor_log
}
file_created() {
    TIMESTAMP=`date`
    echo "[$TIMESTAMP]: The file $1$2 was created" >> monitor_log
}

现在,我们可以解析 inotifywait 输出,将其提供给 while 循环。我们将使用 read 命令将目录、事件和文件字段从输出中拆分出来。接下来,我们可以使用 case 命令根据事件决定调用哪个函数。此外,我们将向 inotifywait 命令添加 -q 参数,以便 inotifywait 仅打印事件而不打印初始消息。让我们把所有这些放在一个名为 monitor_directory_tree.sh 的脚本中。 此脚本接收要监视的目录作为第一个参数。然后,当 inotifywait 报告事件时,它会调用相应的函数:

!/bin/bash

file_removed() {
    xmessage "$2 was removed from $1" &
}

file_modified() {
    TIMESTAMP=`date`
    echo "[$TIMESTAMP]: The file $1$2 was modified" >> monitor_log
}

file_created() {
    TIMESTAMP=`date`
    echo "[$TIMESTAMP]: The file $1$2 was created" >> monitor_log
}

inotifywait -q -m -r -e modify,delete,create $1 | while read DIRECTORY EVENT FILE; do
    case $EVENT in
        MODIFY*)
            file_modified "$DIRECTORY" "$FILE"
            ;;
        CREATE*)
            file_created "$DIRECTORY" "$FILE"
            ;;
        DELETE*)
            file_removed "$DIRECTORY" "$FILE"
            ;;
    esac
done

让我们首先在后台运行 monitor_directory_tree.sh 来测试此脚本。然后,我们将删除 main/3/2/1 目录。接下来,我们将向 main/1/2/file1 文件写入一些文本。最后,我们将创建并写入 main/file1 文件:

./monitor_directory_tree.sh main &
[1] 4800
rm -r main/3/2/1
echo example >> main/1/2/file1
echo example >> main/file1

有了这个,我们可以注意到出现了两个 xmessage 警报。一个警报显示“1 已从 main/3/2/1 中删除”,另一个警报显示“1 已从 main/3/2 中删除”。这是因为当我们运行 rm -r main/3/2/1 时,它还删除了 main/3/2/1/1 子目录。现在,让我们看一下 monitor_log 文件:

cat monitor_log
[Tue Sep 21 21:49:31 -03 2021]: The file main/1/2/file1 was modified
[Wed Sep 21 21:49:34 -03 2021]: The file main/file1 was created
[Wed Sep 21 21:49:34 -03 2021]: The file main/file1 was modified

我们可以看到,日志显示我们修改了 main/1/2/file1。然后它显示文件 main/file1 是创建和修改的,就像我们所做的那样。

7. 结论

在本文中,我们了解了如何监控目录树。我们首先看到了对 inotify 接口的介绍。然后,我们看到了如何使用 inotifywait 来监视目录及其子目录中的事件。最后,我们学习了如何将 inotifywait 输出与其他脚本集成。

  • 20
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值