Linux

Bash 程式設計教學與範例:inotify-tools 監控檔案變動、觸發處理動作

介紹如何在 Linux 系統上透過 inotify-tools 指令工具,監控檔案的各種變動,觸發對應的處理動作。

inotify(代表 inode notify)是一個 Linux 核心子系統,負責監看檔案系統並將任何檔案變動通知應用程式,可用於自動更新目錄顯示、重新載入設定檔、記錄檔、備份檔案或上傳檔案。

安裝 inotify-tools 工具

大部分的 Linux 發行版的套件庫中,都有收錄 inotify-tools 工具,使用對應的套件管理工具安裝 inotify-tools 套件即可:

# 安裝 inotify-tools 套件(Debian/Ubuntu)
sudo apt install inotify-tools

# 安裝 inotify-tools 套件(Fedora)
sudo yum install inotify-tools

# 安裝 inotify-tools 套件(RHEL/CentOS)
sudo yum install -y epel-release && yum update
sudo yum install inotify-tools

關於其他各種 Linux 環境的安裝方式,可以參考 inotify-tools 的說明

監看目錄

inotifywait 指令是 inotify-tools 套件所提供的工具之一,可以用來監看指定的檔案變動事件,並觸發對應的動作。

如果要監看 /tmp 目錄下所有的檔案事件,可以執行:

# 持續監看 /tmp 目錄下的所有檔案事件
inotifywait -m /tmp
Setting up watches.
Watches established.

執行 inotifywait 之後,會占用一個終端機,並將所有檔案事件的訊息輸出在終端機中。這裡的 -m 參數是代表讓 inotifywait 持續獨斷監看檔案事件(如果沒有加上此參數,預設會在收到一筆檔案事件之後就停止監看)。

接著開啟另外一個終端機,執行一些檔案的操作:

# 進行一些檔案操作
date > /tmp/date.output
rm /tmp/date.output

這時候就會看到 inotifywait 的輸出中出現以下的檔案事件訊息:

/tmp/ CREATE date.output
/tmp/ OPEN date.output
/tmp/ MODIFY date.output
/tmp/ CLOSE_WRITE,CLOSE date.output
/tmp/ DELETE date.output

監看目錄與子目錄

如果要對指定目錄與其子目錄下的所有檔案進行監看,可以加上 -r 參數以遞迴的方式監看:

# 持續監看 /tmp 目錄與子目錄下的所有檔案事件(遞迴)
inotifywait -m -r /tmp

監看檔案

inotifywait 也可以針對特定的檔案進行監看,例如監看 /var/log/syslog 這個系統記錄檔的檔案事件:

# 持續監看 /var/log/syslog 檔案的所有事件
inotifywait -m /var/log/syslog
Setting up watches.
Watches established.
/var/log/syslog MODIFY

自訂輸出訊息格式

我們可以使用 --format 自訂輸出訊息的格式:

# 自訂輸出訊息格式
inotifywait -m --format "%:e %f" /tmp
CREATE date.output
OPEN date.output
MODIFY date.output
CLOSE_WRITE:CLOSE date.output
DELETE date.output

事件訊息格式支援以下幾種轉換代碼:

代碼 說明
%w 觸發事件的監看檔案。
%f 若事件發生在目錄之內,則顯示觸發事件的檔案,否則為空字串。
%e 發生事件,以逗號區隔。
%Xe 發生事件,以 X 符號區隔。
%T 時間,可用 --timefmt 參數指令時間格式。

指定檔案事件

inotifywait 在預設的狀況下會傾聽所有的檔案事件:

名稱 說明
access 讀取檔案。
modify 寫入檔案。
attrib 更改檔案屬性,例如修改時間、權限等。
close_write 檔案從寫入模式關閉,但不代表有實際寫入資料。
close_nowrite 檔案從唯讀模式關閉。
close 關閉檔案,等同於 close_writeclose_nowrite
open 開啟檔案。
moved_to 檔案或目錄移入監看目錄,包含監看目錄內的搬移。
moved_from 檔案或目錄移出監看目錄,包含監看目錄內的搬移。
move 搬移檔案或目錄,等同於 moved_tomoved_from
move_self 移動監看目錄本身,搬移之後該目錄就會脫離監看範圍。
create 建立檔案或目錄。
delete 刪除檔案或目錄。
delete_self 刪除監看目錄本身。
unmount 卸載監看目錄本身,卸載之後該目錄就會脫離監看範圍。

若要監看 /tmp 目錄之下所有檔案的建立(create)與刪除(delete)事件:

# 持續監看 /tmp 目錄下的 create 與 delete 檔案事件
inotifywait -m -e create -e delete /tmp
Setting up watches.
Watches established.
/tmp/ CREATE sh-thd.3CAUNM
/tmp/ DELETE sh-thd.3CAUNM

輸出事件訊息至檔案

inotifywait 預設會將檔案事件訊息都輸出在標準錯誤(stderr),若要將訊息儲存至檔案,可以使用 -o 參數指定輸出的檔案:

# 將事件訊息輸出至 events.log
inotifywait -m -o events.log /tmp

若要將事件訊息輸出至系統的 syslog 中,可以加上 -s 參數:

# 將事件訊息輸出至系統的 syslog
inotifywait -m -s /tmp

背景執行

inotifywait 加上 -d 參數即可以背景 daemon 的方式執行,而通常這種方式都會搭配 -o-s 將事件訊息輸出至檔案:

# 背景執行,事件訊息輸出至 syslog
inotifywait -m -d -s /tmp

應用範例

以下是一些搭配 inotifywait 指令所撰寫的實際應用指令稿。

自動處理新增檔案

如果要監看指定目錄,當目錄中有新增檔案時,對新檔案作立即性的處理,可以使用以下指令稿進行修改:

# 監看 myfolder 目錄中新增的檔案,觸發指定動作
inotifywait -m -e create -e moved_to myfolder |
  while read dir action file; do
    echo "$dir 目錄透過 $action 方式新增檔案 $file"
    # 進行後續處理 ...
  done
Setting up watches.
Watches established.
myfolder/ 目錄透過 CREATE 方式新增檔案 test1.txt
myfolder/ 目錄透過 MOVED_TO 方式新增檔案 myscript.sh

監看使用者登入記錄檔

以下指令稿可用來監看 /var/log/auth.log 這個使用者登入的記錄檔,篩選出使用者都入系統的記錄,每當有使用者登入時,觸發對應的處理動作:

# 監看 /var/log/auth.log 檔案內容變動
while inotifywait -e modify /var/log/auth.log; do

  # 取得檔案最後一行內容
  new_msg=`tail -n1 /var/log/auth.log`

  # 檢查內容是否包含 systemd-logind 這個關鍵字,並取出使用者名稱
  if [[ $new_msg =~ systemd-logind.*user(.*)\. ]]; then

    echo "使用者登入:${BASH_REMATCH[1]}"
    # 進行後續處理 ...

  fi
done
Setting up watches.
Watches established.
/var/log/auth.log MODIFY
Setting up watches.
Watches established.
/var/log/auth.log MODIFY
使用者登入: ubuntu

統計檔案事件

inotifywatch 可以用來統計指定路徑之下的檔案事件,例如統計 /var/log 目錄下的 accessmodify 檔案事件:

# 統計 /var/log 目錄下的 access 與 modify 檔案事件
inotifywatch -v -e access -e modify -t 60 -r /var/log
Establishing watches...
Setting up watch(es) on /var/log
OK, /var/log is now being watched.
Total of 15 watches.
Finished establishing watches, now collecting statistics.
Will listen for events for 60 seconds.
total  access  modify  filename
79     42      37      /var/log/
12     4       8       /var/log/journal/b8484d93cddf4bff9e38ce21e93587ea/
4      4       0       /var/log/journal/

參考資料

Share
Published by
Office Guide
Tags: Bash

Recent Posts

Python 使用 PyAutoGUI 自動操作滑鼠與鍵盤

本篇介紹如何在 Python ...

9 個月 ago

Ubuntu Linux 以 WireGuard 架設 VPN 伺服器教學與範例

本篇介紹如何在 Ubuntu ...

9 個月 ago

Linux 網路設定 ip 指令用法教學與範例

本篇介紹如何在 Linux 系...

9 個月 ago

Windows 使用 TPM 虛擬智慧卡保護 SSH 金鑰教學與範例

本篇介紹如何在 Windows...

10 個月 ago

Linux 以 Shamir’s Secret Sharing 分割保存金鑰教學與範例

介紹如何在 Linux 中使用...

10 個月 ago

Linux 以 Cryptsetup、LUKS 加密 USB 隨身碟教學與範例

介紹如何在 Linux 系統中...

10 個月 ago