鈎子腳本的具體寫法就是操作系統中shell腳本程序的寫法,請根據自己SVN所在的操作系統和shell程序進行相應的寫作
所謂鈎子就是與一些版本庫事件觸發的程序,例如新修訂版本的創建,或是未版本化屬性的修改。每個鈎子都會被告知足夠多的信息,包括那是什么事件,所操作的對象,和觸發事件的用戶名。通過鈎子的輸出或返回狀態,鈎子程序能讓工作繼續、停止或是以某種方式掛起。
默認情況下,鈎子的子目錄中包含各種版本庫鈎子模板。
$ ls repos/hooks/
post-commit.tmpl pre-revprop-change.tmpl
post-revprop-change.tmpl start-commit.tmpl
pre-commit.tmpl
對每種Subversion版本庫支持的鈎子的都有一個模板,通過查看這些腳本的內容,你能看到是什么事件觸發了腳本及如何給傳腳本傳遞數據。同時,這些模版也是如何使用這些腳本,結合Subversion支持的工具來完成有用任務的例子。要實際安裝一個可用的鈎子,你需要在 repos/hooks目錄下安裝一些與鈎子同名(如 start-commit或者post-commit)的可執行程序或腳本。
提示
由於安全原因,Subversion版本庫在一個空環境中執行鈎子腳本—就是沒有任何環境變量,甚至沒有$PATH或%PATH%。由於這個原因,許多管理員會感到很困惑,它們的鈎子腳本手工運行時正常,可在Subversion中卻不能運行。要注意,必須在你的鈎子中設置好環境變量或為你的程序指定好絕對路徑。
目前Subversion有已實現了五種鈎子:
start-commit.bat
它在提交事務產生前已運行,通常用來判定一個用戶是否有權提交。版本庫傳給該程序兩個參數:到版本庫的路徑,和要進行提交的用戶名。如果程序返回一個非零值,會在事務產生前停止該提交操作。如果鈎子程序要在stderr中寫入數據,它將排隊送至客戶端。
pre-commit.bat
在事務完成提交之前運行,通常這個鈎子是用來保護因為內容或位置(例如,你要求所有到一個特定分支的提交必須包括一個bug追蹤的ticket號,或者是要求日志信息不為空)而不允許的提交。版本庫傳遞兩個參數到程序:版本庫的路徑和正在提交的事務名稱,如果程序返回非零值,提交會失敗,事務也會刪除。如果鈎子程序在stderr中寫入了數據,也會傳遞到客戶端。
Subversion的分發版本包括了一些訪問控制腳本(在Subversion源文件目錄樹的tools/hook-scripts目錄),可以用來被pre-commit調用來實現精密的寫訪問控制。另一個選擇是使用Apache的httpd模塊mod_authz_svn,可以對單個目錄進行讀寫訪問控制(見“每目錄訪問控制”一節)。在未來的Subversion版本中,我們計划直接在文件系統中實現訪問控制列表(ACL)。
post-commit.bat
它在事務完成后運行,創建一個新的修訂版本。大多數人用這個鈎子來發送關於提交的描述性電子郵件,或者作為版本庫的備份。版本庫傳給程序兩個參數:到版本庫的路徑和被創建的新的修訂版本號。退出程序會被忽略。
Subversion分發版本中包括mailer.py和commit-email.pl腳本(存於Subversion源代碼樹中的 tools/hook-scripts/目錄中)可以用來發送描述給定提交的email(並且或只是追加到一個日志文件),這個mail包含變化的路徑清單,提交的日志信息、日期和作者以及修改文件的GNU區別樣式輸出。
Subversion提供的另一個有用的工具是hot-backup.py腳本(在Subversion源代碼樹中的tools/backup/目錄中)。這個腳本可以為Subversion版本庫進行熱備份(Berkeley DB數據庫后端支持的一種特性),可以制作版本庫每次提交的快照作為歸檔和緊急情況的備份。
pre-revprop-change.bat
因為Subversion的修訂版本屬性不是版本化的,對這類屬性的修改(例如提交日志屬性 svn:log)將會永久覆蓋以前的屬性值。因為數據在此可能丟失,所以Subversion提供了這種鈎子(及與之對應的post-revprop- change),因此版本庫管理員可用一些外部方法記錄變化。作為對丟失未版本化屬性數據的防范,Subversion客戶端不能遠程修改修訂版本屬性,除非為你的版本庫實現這個鈎子。
這個鈎子在對版本庫進行這種修改時才會運行,版本庫給鈎子傳遞四個參數:到版本庫的路徑,要修改屬性的修訂版本,經過認證的用戶名和屬性自身的名字。
post-revprop-change.bat
我們在前面提到過,這個鈎子與pre-revprop-change對應。事實上,因為多疑的原因,只有存在pre-revprop-change時這個腳本才會執行。當這兩個鈎子都存在時,post-revprop-change在修訂版本屬性被改變之后運行,通常用來發送包含新屬性的email。版本庫傳遞四個參數給該鈎子:到版本庫的路徑,屬性存在的修訂版本,經過校驗的產生變化的用戶名,和屬性自身的名字。
Subversion分發版本中包含propchange-email.pl腳本(在Subversion源代碼樹中的tools/hook- scripts/目錄中),可以用來發送修訂版本屬性修改細節的email(並且或只是追加到一個日志文件)。這個email包含修訂版本和發生變化的屬性名,作出修改的用戶和新屬性值。
警告
不要嘗試用鈎子腳本修改事務。一個常見的例子就是在提交時自動設置svn:eol-style或svn:mime-type這類屬性。這看起來是個好主意,但它會引起問題。主要的問題是客戶並不知道由鈎子腳本進行的修改,同時沒有辦法通告客戶它的數據是過時的,這種矛盾會導致出人意料和不能預測的行為。
作為嘗試修改事務的替代,我們通過檢查pre-commit鈎子的事務,在不滿足要求時拒絕提交。
Subversion會試圖以當前訪問版本庫的用戶身份執行鈎子。通常,對版本庫的訪問總是通過Apache HTTP服務器和mod_dav_svn進行,因此,執行鈎子的用戶就是運行Apache的用戶。鈎子本身需要具有操作系統級的訪問許可,用戶可以運行它。另外,其它被鈎子直接或間接使用的文件或程序(包括Subversion版本庫本身)也要被同一個用戶訪問。換句話說,要注意潛在的訪問控制問題,它可能會讓你的鈎子無法按照你的目的順利執行
原文:http://hi.baidu.com/gacmotor/blog/item/da499e2b4f65fa25d42af192.html
安裝測試環境:109 CentOS4.6
安裝:
SVN1.32http://subversion.tigris.org/downloads/subversion-1.3.2.tar.gz |
一、版本庫鈎子
3.1 start-commit 開始提交的通知
輸入參數:傳遞給你鈎子程序的命令行參數,順序如下:
1. 版本庫路徑
2. 認證過的嘗試提交的用戶名
3. Depth,mergeinfo,log-revprops
3.2 pre-commit 在提交結束之前提醒
輸入參數:傳遞給你鈎子程序的命令行參數。順序是:
1. 版本庫路徑
2. 提交事務的名稱
3.3 post-commit 成功提交的通知
傳遞給你鈎子程序的命令行參數,順序為:
1. 版本庫路徑
2. 提交創建的修訂版本號
3.4 pre-revprop-change –修訂版本屬性修改的通知
這個鈎子在修訂版本屬性修改之前,正常提交范圍之外被執行,不像其它鈎子,這個鈎子默認是拒絕所有的屬性修改,鈎子必須要實際存在並且返回一個零值。
----------------------SVN配置用戶權限 -------------------------------------------
整理文檔如下:
1. 建立SVN版本庫目錄(即你的SVN服務器里面的文件存放在哪個目錄)
#mkdir -p /opt/svndata/repos1
說明:svn mkdir 是其實是相當於#mkdir && svn add 操作。只差一步commit操作
Svn有許多操作是可以直接一步到位進行的!
2. 有了目錄現在就可以創建SVN版本庫
#svnadmin create /opt/svndata/repos1/
3. 編輯SVN的配置文件主要是權限這塊的相關配置信息
#vi /opt/svndata/repos1/conf/svnserve.conf
[general]
anon-access = none
auth-access = write
password-db = passwd #還可以指定到其它目錄都是可以的
authz-db = authz
realm = repos1
4. 配置允許訪問SVN的用戶
#vi /opt/svndata/repos1/conf/passwd
[users]
test = test
5. 配置用戶訪問權限相關
#vi /opt/svndata/repos1/conf/authz
[groups]
admin = test
# harry_and_sally = harry,sally
[/]
@admin = rw
[repos1:/abc/aaa]
@admin = r
版本庫目錄格式:
[<版本庫>:/項目/目錄] #是以項目名作為第一個單位。試想肯定是以項目為單元的
@<用戶組名> = <權限>
<用戶名> = <權限>
其中,方框號內部分可以有多種寫法:
/,表示根目錄及以下。根目錄是svnserve啟動時指定的,我們指定為/opt/svndata。這樣,/就是表示對全部版本庫設置權限。
repos1:/,表示對版本庫1設置權限
repos2:/abc, ,表示對版本庫2中的abc項目設置權限
repos2:/abc/aaa, ,表示對版本庫2中的abc項目的aaa目錄設置權限
權限主體可以是用戶組、用戶或*,用戶組在前面加@,*表示全部用戶。權限可以是w、r、wr和空,空表示沒有任何權限。
6. 啟動svnserve -d -r /opt/svndata/
其中:
-d表示以daemon方式(后台運行)運行
-r /opt/svndata指定根目錄是/opt/svndata
7. 現在有了倉庫了就可以往倉庫里面提交東西了。我們是以一個項目為單位的進行提交
#mkdir -p /var/www/dotproject 項目文件目錄是在這。項目名稱為dotproject
#svn import -m 'project' /var/www/dotproject svn://192.168.0.109/repos1
這個時候就會讓你輸入用戶名與密碼了
8. 從版本庫中checkout東西
#mkdir myproj && cd myproj 表示全部的項目都存在這個目錄下面
#svn checkout svn://192.168.1.109/repos1 dotproect 表示把repos1里面的項目搞出來。
以上操作成功!以下是操作總結
1. #mkdir -p /opt/svndata/repos1
#svnadmin create /opt/svndata/repos1/
這樣的話我們的SVN倉庫的名稱其實就是repos1 這個非常有用。在定義權限的時候有用
2. [repos1:/abc/aaa] 其中abc表示的是項目名稱。像上面就是dotproject這個名稱
@admin = r 表示這個組的用戶可以進行讀的權限
1. svnserve -d -r /opt/svndata/
-r /opt/svndata指定根目錄是/opt/svndata #這個也非常有用!(哦明白了這個其實跟JSP里面的根目錄一個效果如果指定了WEB項目的根目錄了其實后面的文件或目錄都是相對於這個根目錄進行訪問的。這里面如果我們指定了其實倉庫的根目錄的話后面的文件訪問其實也是依據這個根目錄進行的其中的 -d 參數表示 svnserve.exe 將會作為一個服務程序運行在后台,而 -r 參數表示將 D:\svn 目錄指定為代碼庫的根目錄。這樣,當客戶端使用類似 svn://192.168.0.1/foo 這樣內容的 URL 來訪問服務器時候,其所訪問到的真實代碼庫,其實就是 D:\svn\foo)
3. svn import -m 'project' /var/www/dotproject svn://192.168.0.109/repos1
其中這里面的dotproject就是項目名稱了!
2. svn checkout svn://192.168.1.109/repos1 dotproect #表示將這個倉庫中的這個項目提取出來
看我測試權限:
# vi /opt/svndata/repos1/conf/authz
[groups]
admin = test
[repos1:/dotproject/]
@admin = r #讓這個用戶只有讀的權限
現在到項目目錄下面就不可以再commit動作了
--no-auth-cache –username rory --password 8809117
1. 我編輯/opt/svndata/repos1/hooks/ pre-commit 這個文件里面的內容如下:
#!/bin/bash REPOS="$1" TXN="$2" # Make sure that the log message contains some text. SVNLOOK=/usr/local/bin/svnlook $SVNLOOK log -t "$TXN" "$REPOS" | \ grep "[a-zA-Z0-9]" > /tmp/aaa || exit 1 # Check that the author of this commit has the rights to perform # the commit on the files and directories being modified. # commit-access-control.pl "$REPOS" "$TXN" commit-access-control.cfg || exit 1 # All checks passed, so allow the commit. exit 0 #返回0表示允許提交? |
運行這段程序正常了!
然后我將其換成我自己的腳本看:(這台正常了哦哦!)
#!/bin/bash /bin/echo "a" >> /tmp/aaa.out 成功記錄日志 # exit 1 #REPOS="$1" #TXN="$2" # Make sure that the log message contains some text. #SVNLOOK=/usr/local/bin/svnlook #$SVNLOOK log -t "$TXN" "$REPOS" | \ # grep "[a-zA-Z0-9]" > /tmp/aaa || exit 1 # Check that the author of this commit has the rights to perform # the commit on the files and directories being modified. # commit-access-control.pl "$REPOS" "$TXN" commit-access-control.cfg || exit 1 # All checks passed, so allow the commit. exit 0 |
-rwxr-xr-x 1 root root 494 Nov 1 13:21 pre-commit
OK我們現在來寫一個成功svn-commit之后要觸發的一個鈎子
#!/bin/bash REPOS="$1" TXN="$2" /bin/echo "eeeee" >> /tmp/dddddsvn.out 成功! |
OK!現在換一個python腳本來試試
我想讓SVN在提交之后執行一段python程序
#!/usr/bin/env python #這一段的意義就是當將這個python程序置成可執行時候。它會去哪尋找python。如果沒有這段的話將其設置成可執行的時候就不會跑起來 if __name__ == '__main__': import sys,string try: logfile = open('/tmp/python.out','a+') #簡單寫個日志記錄一下 logfile.write("this is a python hook") logfile.close() except: exit(1) sys.exit(0) |
然后在post-commit里面的代碼如下:
#!/bin/bash REPOS="$1" TXN="$2" /usr/bin/python /opt/svndata/repos1/hooks/so.py #直接調用這段python程序 |
OK!現在來編寫SVNUPDATE這塊的代碼。
實現原理:當用戶提交commit動作發生都讓另外一處project馬上從倉庫中進行代碼checkout一份出來!
說明:post-commit會接受兩個參數
REPOS="$1" /opt/svndata/repos1 表示svn倉庫的絕對路徑值
TXN="$2" 表示最新的一個版本號。最后一個版本號
來看看update的相關參數項
對它的描述如下:
Svn update會把版本庫的修改帶到工作拷貝(工作拷貝的理解其實就是一個工作區)中。如果沒有給定修訂的版本它就會把當前的工作拷貝更新到HEAD最新版本。否則就是它會把工作拷貝更新到指定的修訂版本即—revision后面所帶的參數值。為了保持同步svn update也會刪除所有在工作拷貝發現的無效鎖定。
正式的代碼如下:
#vi /opt/svndata/repos1/hooks/post-commit
#!/bin/bash
/usr/local/bin/svn update /home/myproject/dotproect/ --username test --password test
if [ $? == 0 ]
then
echo "ok" >> /tmp/z.out
fi
測試發現當我修改一個文件然后再commit提交的時候另外一個項目位置是可以。
現在正式搭建SVN的環境。包括用戶權限相關的內容!
--------------------------搭建puppet與svn環境--------------------------------
環境:108
項目名稱:puppet
項目代碼目錄:mkdir -p /var/www/puppet (將/etc/puppet下面的東西先cp過來)
代碼倉庫名稱:repos1
倉庫的目錄:mkdir -p /opt/svndata/repos1
到時會在/etc/ 下面進行一次一次checkout將項目直接checkout到etc目錄下面
#svn checkout svn://192.168.0.109/repos1 puppet #表示將這個項目直接checkout下來(可以先在一個目錄進行測試下看看)
具體步驟如下:
整理文檔如下:
9. 建立SVN版本庫目錄(即你的SVN服務器里面的文件存放在哪個目錄)
#mkdir -p /opt/svndata/repos1
說明:svn mkdir 是其實是相當於#mkdir && svn add 操作。只差一步commit操作
Svn有許多操作是可以直接一步到位進行的!
10. 有了目錄現在就可以創建SVN版本庫
#svnadmin create /opt/svndata/repos1/
11. 編輯SVN的配置文件主要是權限這塊的相關配置信息
#vi /opt/svndata/repos1/conf/svnserve.conf
[general]
anon-access = none
auth-access = write
password-db = passwd #還可以指定到其它目錄都是可以的
authz-db = authz
realm = repos1
12. 配置允許訪問SVN的用戶
#vi /opt/svndata/repos1/conf/passwd
[users]
test = test
13. 配置用戶訪問權限相關
#vi /opt/svndata/repos1/conf/authz
[groups]
admin = test
# harry_and_sally = harry,sally
[/]
@admin = rw
[repos1:/abc/aaa]
@admin = r
版本庫目錄格式:
[<版本庫>:/項目/目錄] #是以項目名作為第一個單位。試想肯定是以項目為單元的
@<用戶組名> = <權限>
<用戶名> = <權限>
其中,方框號內部分可以有多種寫法:
/,表示根目錄及以下。根目錄是svnserve啟動時指定的,我們指定為/opt/svndata。這樣,/就是表示對全部版本庫設置權限。
repos1:/,表示對版本庫1設置權限
repos2:/abc, ,表示對版本庫2中的abc項目設置權限
repos2:/abc/aaa, ,表示對版本庫2中的abc項目的aaa目錄設置權限
權限主體可以是用戶組、用戶或*,用戶組在前面加@,*表示全部用戶。權限可以是w、r、wr和空,空表示沒有任何權限。
14. 啟動svnserve -d -r /opt/svndata/
其中:
-d表示以daemon方式(后台運行)運行
-r /opt/svndata指定根目錄是/opt/svndata
15. 現在有了倉庫了就可以往倉庫里面提交東西了。我們是以一個項目為單位的進行提交
#mkdir -p /var/www/puppet 項目文件目錄是在這。項目名稱為dotproject
#svn import -m 'project' /var/www/puppet svn://192.168.0.109/repos1
這個時候就會讓你輸入用戶名與密碼了(注意passwz里面不要有前綴空格)
16. 從版本庫中checkout東西
(先:#rm –rf /puppet/)將puppet目錄先刪除掉。再執行這一條命令。我覺得這太繞了!!!這樣的話就會有這個目錄而且這里面的文件均進來了!
#svn checkout svn://192.168.0.109/repos1 puppet 表示把repos1里面的項目搞出來。
17. 編寫這個SVN的鈎子
#!/bin/bash
/usr/local/bin/svn update /home/myproject/dotproect/ --username test --password test
if [ $? == 0 ]
then
echo "ok" >> /tmp/z.out
fi
----------------然后就可以在WINDOWS平台連接過來。進行操作然后直接SVN提交。
--------------------------高級應用篇-----------------------------------------
1. 如何精確地進行用戶權限划分
示例:對於modules目錄里面的划分非常強烈。比如apache/ mysql/目錄其中mysql用戶只能管理mysql里面的東西。Apache用戶只能管理apache里面東西
WIN平台要想讓TV不記密碼可以將:
C:\Documents and Settings\Administrator\Application Data\Subversion\auth里面的全部文件給刪除掉即可!
Authz文件配置如下:
[groups]
admin = test
db = mysql
www = apache
[repos1:/]
test = rw
[repos1:/modules/mysql]
mysql = rw
*=
[repos1:/modules/apache] 原來上面的寫法說第一節表示項目名稱是錯了。
apache = rw
*=
這樣一寫我就可以控制某個目錄某個用戶的訪問權限了!將來puppet本身的配置文件管理是可以這樣進行細分的!
2. 如果將一個目錄刪除掉了如何同步呢?
假設你使用Windows的客戶端TortoiseSVN,你可以這樣操作:
1。在工作目錄下,選中要刪除的文件和目錄.
2。右鍵,點擊菜單TortoiseSVN -> Delete,這時會看到那些文件已經沒了
3。然后執行commit,會看到在提交對話框中出現了那些刪除文件
提交后,這些文件和目錄就被刪除了
其它開發者update一下,他們工作目錄的那些文件也相應地被刪除
優點:在操作時看不到多余的文件,版本號保留了
缺點:庫大小還是沒有變
使用命令操作如下:
#svn delete test 將這個文件或目錄給刪除掉
#svn commit -m 'delete test' 將其提交一下
現在換到客戶端進行刪除文件
按照上面的說法進行操作成功將文件刪除掉!
------------------------到此!成功配置完成SVN+PUPPET---------------------------
(全文完.)
原文地址:http://blog.chinaunix.net/uid-25525723-id-360264.html