linux下SVN+rsync+inotify實現代碼自動同步到生產服務器

1、環境簡介

操作系統:CentOS release 5.7 (Final)

Apache版本:Apache/2.2.21 (Unix)

Subversion版本:svn, version 1.7.2

Rsync版本:rsync  version 3.0.6  protocol version 30

Inotify版本:inotifywait 3.14

SVN Server端服務器:以下統稱A

同步測試服務器:以下統稱B

 

2、需求及流程簡介

由於程序員協同開發,彼此之間開發習慣各有不同,經常會出現大家誤刪改他人代碼的情況,對線上生產環境的穩定造成了極大的影響。因此特請出SVN來負責代碼版本控制,以解決上述問題。

但是簡單的代碼控制要增加很多不必要的人工成本,如:手動提交、檢出、發佈、測試等,所以作爲運維人員,就自然而然想到有什麼辦法可以讓其將以上操作都自動執行完成。固有了如下需求。

1、代碼commit至A服務器後,自動update到代碼的working copy

2、update後需直接遠程同步至B服務器進行測試

3、定期備份svn服務器代碼庫文件至備份服務器(此處與B公用一臺)

4、待測試完畢後,通過程序控制將working copy文件,自動發佈到生產環境(待開發)

以上前3步均是由系統級操作完成,第4步需要程序寫出一個交互系統,來完成測試完畢發佈的過程。本文檔主要實現前3步。

 

3、準備

SVN相關下載,詳見:

http://www.ttlsa.com/html/723.html

 

rsync下載安裝

[codesyntax lang="php"]

rpm -qa | grep rsync

(如果沒有輸出的話,執行下面命令安裝,如果有,跳過)

yum install -y rsync

[/codesyntax]

inotify下載

[codesyntax lang="php"]

wget http://cloud.github.com/downloads/rvoicilas/inotify-tools/inotify-tools-3.14.tar.gz

[/codesyntax]

4、安裝配置SVN

詳見:http://www.ttlsa.com/html/723.html

注:由於在A服務器和B服務器上都要安裝Svn client

所以,爲了簡單起見,建議兩臺服務器上都完整安裝SVN

 

5、安裝配置rsync+inotify服務端

安裝過程主要參考:http://kerry.blog.51cto.com/172631/734087

這裏根據自身情況,略加修改,具體內容如下

5.1、B服務器(rsync daemon)

由於是將版本庫代碼同步至B服務器,所以安裝rsync server端的任務就落在了B服務器的身上

[codesyntax lang="php"]

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

# vi /etc/rsyncd.conf

 

uid = nobody

gid = nobody

use chroot = no

max connections = 100

timeout = 600

pid file = /var/run/rsyncd.pid

lock file = /var/run/rsyncd.lock

log file = /var/log/rsyncd.log

[test]

path = /data/www/test/

ignore errors

read only = no

list = no

hosts allow = 192.168.1.0/255.255.255.0

auth users = test

secrets file = /etc/rsyncd/test_server.pwd

[/codesyntax]

[codesyntax lang="php"]

# vi /etc/rsyncd/test_server.pwd

test:test

# chmod 600 /etc/rsyncd.conf /etc/rsyncd/test_server.pwd

# echo "Welcome to use the rsync services\!" >> /var/rsyncd.motd

# /usr/bin/rsync --daemon

[/codesyntax]

ok,這樣rsync server端就搞定了,接下來就是client端的腳本了

5.2、A服務器版本庫

由於A服務器端是源服務器,所以inotify需要安裝在源服務器上

 

[codesyntax lang="php"]

# cd /usr/local/src/tarbag

# tar xvf inotify-tools-3.14.tar.gz -C ../software

# cd ../software/inotify-tools-3.14

# ./configure && make && make install

[/codesyntax]

 

6、通過svn自帶hooks實現自動update(本節內容是爲svnsync準備,文件內容可留空即可,如果不使用svnsync功能,可略過此節)

6.1、A服務器,修改post-commit文件

[codesyntax lang="php"]

# cd  /data/svn/test/hooks/

# cp  post-commit.tmpl  post-commit

# vi post-commit

清空所有信息,將如下信息替換

#!/bin/sh

export LANG=en_US.UTF-8
REPOS="$1"
REV="$2"

AUTHOR=/usr/local/bin/svnlook author -r $REV $REPOS
DATE=date '+%F'
TIME=date '+%F %T'
DIR=/data/svn/test/hooks
PATH=/usr/local/bin
LOCAL_WORKING_COPY=/data/svn_data/test/
SVN_SRC=/data/svn_data/test/
WEB_SRC=/data/www/test/
PASSWD=/etc/rsyncd/test.pwd
DES=test
USER=test
SVN=$PATH/svn
SVNSYNC=$PATH/svnsync
RSYNC=/usr/bin/rsync
RSYNC_LOGFILE=/var/log/rsyncd/${DATE}-rsync.log
SVN_LOGFILE=/var/log/svn/${DATE}-svn.log
SVN_LOGIN_INFO="--username tonyty163 --password ty1224"

#SVN UPDATE
echo "----------------------------------BEGIN------------------------------------" >> ${SVN_LOGFILE}
echo "The following changes were made to the code:" >> ${SVN_LOGFILE}
echo "[$TIME]--[$AUTHOR] svn commit file:" >> ${SVN_LOGFILE}
echo "REV is $REV,REPOS is $REPOS" >> ${SVN_LOGFILE}
$SVN update $SVN_LOGIN_INFO $LOCAL_WORKING_COPY >> ${SVN_LOGFILE}
if [ "$?" = "0" ];
then
echo "update successed" >> ${SVN_LOGFILE};
else
echo "update failed" >> ${SVN_LOGFILE};
fi
$SVN log $LOCAL_WORKING_COPY -v -r "$REV" $SVN_LOGIN_INFO >> ${SVN_LOGFILE}
$SVN diff $LOCAL_WORKING_COPY -c "$REV" --no-diff-deleted $SVN_LOGIN_INFO >> ${SVN_LOGFILE}
echo "------------------------------------END------------------------------------" >> ${SVN_LOGFILE}

#Rsync TO WEB_SRC
${RSYNC} -aH --delete --progress --exclude=".svn/" ${SVN_SRC} ${WEB_SRC} &&  echo "local rsync succesed" >> ${RSYNC_LOGFILE} 2>&1
echo "------------------------------------END------------------------------------" >> ${RSYNC_LOGFILE} 2>&1;
[/codesyntax]

簡單描述下上述腳本的功能

首先post-commit腳本,最主要的作用就是等版本庫有人commit提交了以後進行的動作

這個腳本最先生成了一個以日期爲文件名的日誌在$DIR/logs目錄下

然後分別記錄了時間,作者,以及svn updata的情況和svn log,svn diff的信息

注:記錄日誌是爲了方便查詢排錯使用

 

 

6.2、B服務器,修改start-commit和pre-revprop-change

[codesyntax lang="php"]

# cd /data/svn/test/hooks/

# vi start-commit

 

#!/bin/sh

 

USER="$2"

 

if [ "$USER" = "user" ]; then exit 0; fi

 

echo "Only the user user may change revision properties as this is a read-only, mirror repository." >&2

# All checks passed, so allow the commit.

exit 1

[/codesyntax]

將文件內容修改爲上述內容

[codesyntax lang="php"]

# vi pre-revprop-change

 

#!/bin/sh

 

REPOS="$1"

REV="$2"

USER="$3"

PROPNAME="$4"

ACTION="$5"

 

if [ "$ACTION" = "M" -a "$PROPNAME" = "svn:log" ]; then exit 0; fi

 

echo "Changing revision properties other than svn:log is prohibited" >&2

exit 0

 

if [ "$USER" = "user" ]; then exit; fi

 

echo "Only the user user may change revision properties as this is a read-only, mirror repository." >&2

exit 1

[/codesyntax]

將文件內容修改爲上述內容

 

 

7、通過rsync和inotify實現A服務器與B服務器同步

各組件安裝完畢,接下來要自己寫一個rsync後臺監控腳本,內容如下

[codesyntax lang="php"]

# vi /usr/local/src/scripts/rsync.sh

#!/bin/bash
HOST=107.6.15.235
SVN_SRC=/data/svn_data/test/
WEB_SRC=/data/www/test/
PASSWD=/etc/rsyncd/test.pwd
DES=test
USER=test
DATE=date '+%F'
RSYNC_LOGFILE=/var/log/rsyncd/${DATE}-rsync.log

/usr/local/bin/inotifywait -mrq --timefmt '%d/%m/%y %H:%M' --format  '%T %w%f' -e modify,delete,create,attrib ${WEB_SRC} | while read  file
do
rsync -aH --delete --progress ${WEB_SRC} ${USER}@${HOST}::${DES} --password-file=${PASSWD} &&  echo "${file} rsync succesed" >> ${RSYNC_LOGFILE} 2>&1
if [ $? -ne 0 ];
then
echo "remote rsync failed" >> ${RSYNC_LOGFILE};
fi
echo "-----------------------------------END-------------------------------------" >> ${RSYNC_LOGFILE} 2>&1;
done

[/codesyntax]

簡單說明一下腳本的功能,主要是兩個

a、由inotifywait監控${src}目錄的變化

b、將變化的文件存入${file},傳遞給rsync進行同步(即增量同步),並將更新的文件寫入日誌

 

8、通過crontab定時備份SVN

[codesyntax lang="php"]

# crontab -e

* * * * * /usr/local/src/scripts/svnsync.sh

 

# vi /usr/local/src/scripts/svnsync.sh

#!/bin/sh

DATE=date '+%F'

TIME=date '+%F %T'

DIR=/data/svn/test/hooks

PATH=/usr/local/bin

SVN=$PATH/svn

SVNSYNC=$PATH/svnsync

MIRROR_SVN=http://192.168.1.204/svn/test/

SVN_LOGIN_INFO="--username user --password passwd"

$SVNSYNC sync $MIRROR_SVN $SVN_LOGIN_INFO >> $DIR/logs/$DATE-log.txt

if [ "$?" = "0" ];

then

echo "svnsync successed" >> $DIR/logs/$DATE-log.txt;

else

echo "svnsync failed" >> $DIR/logs/$DATE-log.txt;

fi

[/codesyntax]

上述腳本主要功能簡介:

首先crontab每分鐘執行一次svnsync.sh腳本

腳本中是遠程同步本地版本庫(注:非working copy,即svn的db文件)

同步完成後將腳本執行結果記錄進日誌


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