天天看點

inotify + rsync 使用觸發同步機制 實作檔案 "實時同步"

 公司一套系統的同步使用的donotify,不能實作子目錄的實時同步,通過查資料,發現inotify可以實作子目錄的實時同步,以下為筆記。

一、介紹

Inotify 是檔案系統事件監控機制,作為 dnotify 的有效替代。dnotify 是較早核心支援的檔案監控機制。Inotify 是一種強大的、細粒度的、異步的機制,它滿足各種各樣的檔案監控需要,不僅限于安全和性能。

inotify 可以監視的檔案系統事件包括:

IN_ACCESS,即檔案被通路

IN_MODIFY,檔案被 write

IN_ATTRIB,檔案屬性被修改,如 chmod、chown、touch 等

IN_CLOSE_WRITE,可寫檔案被 close

IN_CLOSE_NOWRITE,不可寫檔案被 close

IN_OPEN,檔案被 open

IN_MOVED_FROM,檔案被移走,如 mv

IN_MOVED_TO,檔案被移來,如 mv、cp

IN_CREATE,建立新檔案

IN_DELETE,檔案被删除,如 rm

IN_DELETE_SELF,自删除,即一個可執行檔案在執行時删除自己

IN_MOVE_SELF,自移動,即一個可執行檔案在執行時移動自己

IN_UNMOUNT,宿主檔案系統被 umount

IN_CLOSE,檔案被關閉,等同于(IN_CLOSE_WRITE | IN_CLOSE_NOWRITE)

IN_MOVE,檔案被移動,等同于(IN_MOVED_FROM | IN_MOVED_TO)

注:上面所說的檔案也包括目錄。

二、為能在shell下使用inotify特性,需要安裝inotify-tools

1、inotify-tools:The general purpose of this package is to allow inotify's features to be used from within shell scripts.

下載下傳位址:http://inotify-tools.sourceforge.net/

編譯安裝

./configure

make

make install

完成後,注意檢視manpage,man inotify 、 man inotifywait

# inotifywait 僅執行阻塞,等待 inotify 事件。您可以監控任何一組檔案和目錄,或監控整個目錄樹(目錄、子目錄、子目錄的子目錄等等)。在 shell 腳本中使用 inotifywait。

# inotifywatch 收集關于被監視的檔案系統的統計資料,包括每個 inotify 事件發生多少次。

2、inotify的系統相關參數:

/proc interfaces

The following interfaces can be used to limit the amount of kernel memory consumed by inotify:

/proc/sys/fs/inotify/max_queued_events

The value in this file is used when an application calls inotify_init(2) to set an upper  limit  on  the number  of  events  that  can be queued to the corresponding inotify instance.  Events in excess of this limit are dropped, but an IN_Q_OVERFLOW event is always generated.

/proc/sys/fs/inotify/max_user_instances

This specifies an upper limit on the number of inotify instances that can be created per real user ID.

/proc/sys/fs/inotify/max_user_watches

This specifies a limit on the number of watches that can be associated with each inotify instance.

3、inotifywait 相關的參數(更多,檢視manpage):

inotifywait

This command simply blocks for inotify events, making it appropriate for use in shell scripts. It can watch any set of files and directories, and can recursively watch entire directory trees.

-m, --monitor

Instead  of  exiting  after receiving a single event, execute indefinitely.  The default behaviour is to exit after the first event occurs.

-r, --recursive

Watch all subdirectories of any directories passed as arguments.  Watches will be set up recursively  to an  unlimited  depth.   Symbolic  links  are  not

traversed.  Newly created subdirectories will also be watched.

-q, --quiet

If specified once, the program will be less verbose.  Specifically, it will not state when it  has  completed establishing all inotify watches.

-e <event>, --event <event>

Listen for specific event(s) only.  The events which can be listened for are listed in the  EVENTS  section.  This option can be specified more than once.  If omitted, all events are listened for. use“,”separate multi events

三、使用

1.檢視是否支援inotify,從kernel 2.6.13開始正式并入核心,RHEL5已經支援。

看看是否有 /proc/sys/fs/inotify/目錄,以确定核心是否支援inotify

[root@RHEL5 Rsync]# ll /proc/sys/fs/inotify

total 0

-rw-r--r-- 1 root root 0 Oct  9 09:36 max_queued_events

-rw-r--r-- 1 root root 0 Oct  9 09:36 max_user_instances

-rw-r--r-- 1 root root 0 Oct  9 09:36 max_user_watches

2.關于遞歸:

3.使用:

#!/bin/sh

src=/opt/webmail

des=/tmp

ip=192.168.7.192

/usr/local/bin/inotifywait -mrq --timefmt '%d/%m/%y %H:%M' --format  '%T %w%f' /

-e modify,delete,create,attrib /

${src} /

| while read  file

do

rsync -avz --delete --progress ${src} root@${ip}:${des} &&

echo "${src} was rsynced"

echo "---------------------------------------------------------------------------"

done

注:

當要排出同步某個目錄時,為rsync添加--exculde=PATTERN參數,注意,路徑是相對路徑。詳細檢視man rsync

當要排除都某個目錄的事件監控的處理時,為inotifywait添加--exclude或--excludei參數。詳細檢視man inotifywait

另:

上面的指令傳回的值類似于:

10/03/09 15:31 /wwwpic/1

這3個傳回值做為參數傳給read,關于此處,有人是這樣寫的:

inotifywait -mrq -e create,move,delete,modify $SRC | while read D E F;do

細化了傳回值。

注:要取得監控檔案發生的事件,在--format處指定%e參數,同時,使用--event參數來指定要監控的事件即可,如--format  '%T %w%f %e' --event modify,delete,create,attrib

說明: 當檔案系統發現指定目錄下有如上的條件的時候就觸發相應的指令,是一種主動告之的而非我用循環比較目錄下的檔案的異動,該程式在運作時,更改目錄内的檔案時系統核心會發送一個信号,這個信号會觸發運作rsync指令,這時會同步源目錄和目标目錄。

--timefmt:指定輸出時的輸出格式

--format:  '%T %w%f'指定輸出的格式,上面的輸出類似于:12/10/08 06:34 /opt/webmail/dovecot-1.1.2/src/test/1

小腳本,同步到多台主機:

檔案:    inotify_rsync.tar.gz

大小:    1KB

下載下傳:    下載下傳

更改後,更簡單,适用于同步到相同的目錄,監控多目錄,多檔案,同步到多台伺服器

#set -x

#var

src="/usr/local/nginx/html/lib /usr/local/nginx/html/www /usr/local/nginx/html/var/www.work.com.conf.php"

des_ip="172.18.1.35 172.18.1.36 172.18.1.37 172.18.1.38"

#function

inotify_fun ()

{

/usr/local/bin/inotifywait -mrq --timefmt '%d/%m/%y-%H:%M' --format '%T %w%f' /

-e modify,delete,create,move $1|while read time file

for ip in $des_ip

echo "`date +%Y%m%d-%T`: rsync -avzq --delete --progress $1 $ip:`dirname $1`"

rsync -avzq --delete --progress $1 $ip:`dirname $1`

echo

}

#main

for a in $src

inotify_fun $a &

參考:

http://www.ibm.com/developerworks/cn/linux/l-ubuntu-inotify/index.html

關于減少rsync的周遊,未完:

考慮到被監測的目錄每次有一下時間時都會觸發rsync,

modify,delete,create,move

每次rsync都會周遊源目錄,當被監測目錄内檔案特别多時,會造成系統資源的嚴重消耗,是以,

讓rsync每次隻同步修改的檔案。

因為,如果從監控目錄mv走一個目錄,那麼rsync隻會報告找不到你移走的目錄而無法删除備份機的應該删除的目錄。

是以,對于删除這個事件,沒有辦法了,隻能同步被删除檔案或目錄的上級目錄了。

将事件分為兩部分,modify,create,move事件,觸發rsync,隻同步修改了的檔案。

delete事件,同步被删除檔案或目錄的上級目錄(不能越過要同步的根目錄)。

關于腳本内容的一些說明:

rsync.conf裡的目錄格式一定要注意,沒有最後的“/"

boot.sh

對于rsync指令的目标位址,是由兩部分組成的:

1、rsync.conf裡的dest

des=`grep '^dest' ${basedir}/rsync.conf| cut -d '=' -f 2 `

2、被修改了的檔案的完全路徑,去掉源目錄部分,去掉被修改的檔案的檔案名。

mb=`echo $file|awk -F "/" '{NF=NF-1;OFS="/";print $0}'|sed "s#$src##g"`

#######################################################################################

先做個記錄,腳本在delete部分還有問題

#

basedir=/home/jason/Rsync

destNum=`grep -c '^dest' ${basedir}/rsync.conf`

src=`grep 'local directory=' ${basedir}/rsync.conf|cut -d '=' -f 2`

inotifywait -mrq --timefmt '%d/%m/%y %H:%M' --format  '%T %w%f %e' /

--event modify,create,move,delete  ${src} | while read  date time file event

echo $event

for i in $des

case $event in

MODIFY|CREATE|MOVE|MODIFY,ISDIR|CREATE,ISDIR|MODIFY,ISDIR)

#echo $src

no_src_root_file_name=`echo $file|sed "s#$src##g"`

final_target_dest=$i$no_src_root_file_name

下一篇: apache incubator

繼續閱讀