Linux/MAC監控目錄和文件修改變化的利器—fswatch

fswatch 的介紹

fswatch 一個跨平臺文件變化監測器,當指定的文件或目錄的內容被修改時接收通知。fswatch是一個工具, 通過檢測文件的變化,並觸發指定的命令。總之,fswatch是一個跨平臺的文件更改監視,獲取通知警報在指定的文件或目錄的內容被改變或修改。

它在不同的操作系統上執行四種類型的監視器,例如:

  1. 基於Apple OS X的文件系統事件API的監視器構建。
  2. 基於kqueue的顯示器,目前在FreeBSD的4.1通知接口還支持許多* BSD系統,OS X的包容性。
  3. 基於Solaris內核的文件事件通知API的監視器及其附加功能。
  4. 基於inotify的監視器,一個顯示文件系統對應用程序修改的內核子系統。
  5. 基於ReadDirectoryChangesW的監視器,它是記錄更改爲目錄的Windows API。
  6. 定期檢查文件系統狀態,在內存中保存文件修改時間,以及手動確定文件系統更改(可在任何地方使用stat)的監視器。

fswatch的特點

  1. 支持幾種特定於OS的API
  2. 允許遞歸目錄監視
  3. 使用包含和排除正則表達式執行路徑過濾
  4. 支持自定義記錄格式
  5. 此外,它支持週期性空閒事件

fswatch地址:https://github.com/emcrisostomo/fswatch(原版) https://github.com/codeskyblue/fswatch(改過)

使用場景:

當服務器文件夾的文件內容有改動的時候通知管理員或者執行某些操作,如easyswoole框架,啓動的時候是先加載到內存的,有文件更新了,需要重啓服務器才能生效,每次更改文件都重啓web服務,開發效率會大大降低,所以需要監控文件夾的改動,如果有文件發生變化,自動停止服務器,然後啓動服務器,不需要每次更新代碼都手動重啓。 

同類工具對比:

目前拿這個fswatch替代bee, 實時的去編譯運行c,cpp,java,golang等等, 應該都不是問題. 但是和bee比有什麼優勢呢?

既然大神問了,我就列舉下:

  1. bee只適合Go語言; 而fswatch可以適用各種語言, 甚至是文件的遠程同步
  2. bee可以通過配置指定監控的文件夾; fswatch可以配置監控的文件夾並指定監控的深度(0代表當前目錄)
  3. bee可以指定監控文件的後綴; fswatch支持使用正則表達式, 來過濾監控到的文件.
  4. bee.json需要重其他地方拷貝;但是fswatch.json可以自動生成出來.
  5. fswatch支持group-kill. 這樣可以確保fswatch停止後,不會有垃圾進程的存在.
  6. fswatch會根據程序的運行時間自動判斷, 是否爲服務端程序, 並適當的修改重啓策略.
  7. bee功能龐大; fswatch的代碼精簡.

fswatch的安裝

重要提示 :請確保您已經GNU GCC(C和C ++編譯器)和開發工具( 編譯必須Debian / Ubuntu的 )安裝在系統上,你從源代碼編譯fswatch之前。 如果沒有,請使用以下命令在相應的Linux發行版上安裝它。

# yum group install 'Development Tools'		[On CentOS/RHEL]
# dnf group install 'Development Tools'		[On Fedora 22+ Versions]
$ sudo apt-get install build-essential          [On Debian/Ubuntu Versions]
wget https://github.com/emcrisostomo/fswatch/releases/download/1.11.2/fswatch-1.11.2.tar.gz
tar -xvzf fswatch-1.11.2.tar.gz
cd fswatch-1.11.2
sudo ./configure
sudo make
sudo make install sudo ldconfig

fswatch的使用

運行fswatch的一般語法是:

$ fswatch [option] [path]

Linux上,我們建議您使用默認的inotify的顯示器,你可以列出採用現有的顯示器-M- list-monitors選項:

$ fswatch -M
$ fswatch --list-monitors

 

fswatch - 列表監視器

下面的命令讓您觀看在當前目錄(變動/home/howtoing ),與事件傳遞到每4秒標準輸出。

-l或- -latency選項允許您設置在幾秒鐘的等待時間,默認是1秒。

$ fswatch -l 4 . 

接下來的命令監控更改爲每5/var/log/auth.log文件:

$ fswatch -l 5 /var/log/auth.log

使用-t--timestamp選項可以打印時間戳每個事件,要打印UTC格式的時間,使用-u--utf-time選項。 您可以使用以及格式化時間-f--format-time格式選項:

$ fswatch --timestamp /var/log/auth.log

接下來, -x--event-flags告訴fswatch打印的事件標誌的旁邊事件路徑。 您可以使用-event-現場分隔符選項,打印使用特定的分離活動。

$ fswatch --events-flags ~ /var/log/auth.log

要打印顯示在你的目錄/var/log/auth.log文件更改事件的數值,使用-n--numeric選項如下:

$ fswatch --numeric ~ /var/log/auth.log 

也許你可以通過看詳細用法選項和信息fswatch手冊頁:

$ man fswatch

欲瞭解更多信息和用法,請訪問fswatch Github上庫: https://github.com/emcrisostomo/fswatch

腳本案例

vim fswatch.sh 
chmod 755 fswatch.sh 賦予腳本執行權限,copy內容到 fswatch.sh

#!/bin/bash
DIR=$1

if [ ! -n "$DIR" ] ;then
    echo "you have not choice Application directory !"
    exit
fi

php easyswoole stop
php easyswoole start --d

fswatch $DIR | while read file
do
   echo "${file} was modify" >> ./Temp/reload.log 2>&1
   php easyswoole reload
done


運行腳本監聽/easyswoole/App文件夾的改動

 ./fswatch.sh  /easyswoole/App  

 

【企業應用—使用inotify/fswatch構建自動監控腳本】

自動告警腳本

最近項目上有這樣一個需求:系統中有一個後臺服務會不斷的生成監控日誌,根據系統的運行情況,它每天會在目錄/var/alarms下生成一個文件,文件名帶有時間戳,其中內容格式如下:

 

1

$ cat /var/alarms/alarms-20150228130522.csv
node,summary,occurrence,proiority
VIQ002,heartbeat failure,2/12/2015 01:23 AM,critical
VIQ002,packages are rejected,2/12/2015 01:22 AM,major
VIQ002,connection cannot be established,2/11/2015 01:23 AM,medium
VIQ001,packages are rejected,2/11/2015 01:23 AM,warning
VIQ001,connection cannot be established,2/09/2015 01:23 AM,medium
...

運維團隊需要監控這個目錄,如果裏邊的文件發生了變化,就要及時的發送郵件給工程團隊解決。我們當然不可能人工的監控該目錄,然後編寫郵件,再拷貝粘貼,所以需要編寫一個腳本來自動化這個任務。

處理方法有兩種:

  1. 編寫一個crontab的任務,每隔五分鐘輪詢一下,然後編寫腳本來探測變化,發送郵件
  2. 使用操作系統提供的inotify相關API探測變化,編寫腳本發送郵件

不過作爲程序員,第二種方法顯然更高級一些。另外相對於檢測文件變化(對比目錄樹,檢查時間戳,而且還要記錄上一次變更的狀態等),編寫一個發送郵件的腳本要簡單得多。

使用inotify

如果在Linux下,我們可以使用inotify相關的工具,你可以使用你正在使用的系統下的包管理工具來安裝。也可以直接從源碼包編譯安裝。

安裝之後,系統中就有了一個叫做inotifywait的命令,這個命令提供多個參數。默認的inotifywait在接收到指定的事件(文件變化)後,會打印信息並退出。可以使用-m參數讓inotifywati處於監聽狀態。-e參數指定需要監聽的事件類型,下面是幾個常見的事件類型:

  1. CREATE,創建
  2. MODIFY,修改
  3. CLOSE_WRITE,CLOSE,寫入成功

還可以通過--format來指定事件的輸出,%w表示監控的文件名,%f表示如果被監控的對象是目錄,則當發生事件時返回文件名。比如下面的命令:

 

1
$ inotifywait -m -e close_write /var/alarms --format "%w%f"

表示以監控模式(事件發生後不退出,繼續監聽),監聽close_write事件,在/var/alarms目錄上,並且輸出的格式爲%w%f

這樣我們在另一個窗口上模擬事件發生:

 

1
$ touch /var/alarms/alarms-20150228130522.csv

當前的窗口就會出現/var/alarms/alarms-20150228130522.csv這樣的輸出。有了這個功能,我們只需要編寫一段簡單的腳本就可以完成上一小節中的問題了:

 

1

#!/bin/bash
DIR=$1

inotifywait -m -e close_write $DIR --format "%w%f" | while read FILE
do
  cat ${FILE} | mail -s "Alarm: $FILE" [email protected]
done

命令mail是Linux下默認的郵件客戶端,可以完成郵件的發送功能。將上邊的腳本命名爲monitor.sh,添加可執行權限,並啓動監控:

 

1
2
$ chmod +x monitor.sh
$ ./monitor.sh /var/alarms

這樣,當目標目錄/var/alarms發生變化後,我們就可以收到告警郵件了!

Mac OSX下使用fswatch

如果是在Mac OSX下,雖然沒有了inotify相關的API,但是我們可以使用fswatch來完成同樣的工作。

使用brew安裝fswatch

 

1
$ brew install fswatch

即可。fswatch也有很多選項,我們這裏僅使用-0(表示以傳統的NUL作爲字符串終結符,因爲*nix下文件名可以包含任意字符,比如空格)。我們可以很容易的用xargs將檢測到的事件進行進一步的處理:

 

1
fswatch -0 /var/alarms | xargs -0 -n 1 ~/bin/send-notify.sh

其中,-0的意思與fswatch的命令中的-0一致,-n 1表示每條NUL結尾的字符串都執行一次腳本。腳本send-notify.sh的內容如下:

 


1


#!/bin/bash

FILE=$1
cat $FILE | mail -s "Alarm: $FILE" [email protected]

這樣,當文件發生變化時,腳本就會發送一封郵件到指定郵箱了(由於我自己的laptop的hostname不像是一個合理的主機名,所以Gmail會把這封郵件放到垃圾郵件列表中,這裏只是用作示例而已)。

 

當然,由於腳本是我們自己可以編寫的,所以理論上當檢測到變化之後,我們可以做任何事情,比如說幾句話,播放一段音樂等。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章