Windows下Subversion配置管理員指南

lastwinner發表於2008-02-23
作者: rocksun  來源:Subversion

Subversion安裝成service

 以前的svnserve要想成為windows服務,必須依賴於svnservice或其他工具。從Subversion1.4開始,Subversion本身就整合Windows服務的工具。

1,安裝svnservice

 在Windows NT中(包括Windows XP, Windows 2000, Windows 2003 Server)本身包含了一個安裝服務的工具,叫做"Service Control",也就是sc.exe。

例如我的Subversion安裝在"D:\Subversion",版本庫在"D:\svnroot",而我希望對應的Subversion服務名為svnservice,安裝這個svn服務的命令就可以這樣寫:

sc create svnservice
binpath= "D:\Subversion\bin\svnserve.exe --service -r D:\svnroot"
displayname= "SVNService"
depend= Tcpip

請注意,因為便於察看,上面的命令分為多行,但在實際執行時應該在一行裡。另外,在以前啟動svnserve時會使用"-d"選項,也就是守護程式模式,在這裡不能使用,會導致服務無法啟動。同樣,"-i"和"-t"選項也不能使用。

在命令列視窗執行完這個命令之後,服務還沒有啟動,你可以繼續執行"net start svnservice"啟動這個服務,然後使用"net stop svnservice"停止服務。

另外還有兩點需要小心處理。首先,如果路徑中包括空格,一定要用“\”處理“"”號,例如上面的例子中如果svnserve.exe在“c:\program files\subversion\”中,則命令應該寫為“binpath= "\"c:\program files\subversion\bin\svnserve.exe\"”(“”中的內容),整個命令如下,紅色部分是改變部分:

sc create svnservice
binpath= "\"D:\program files\Subversion\bin\svnserve.exe\" --service -r D:\svnroot"
displayname= "SVNService"
depend= Tcpip

其次,sc對選項的格式還有要求,例如“depend= Tcpip”不能寫為“depend = Tcpip”或“depend=Tcpip”,也就是“=”前不能有空各,而後面必須有空格。

2,刪除服務

 如果服務安裝的有問題,你可能需要刪除服務。要刪除前面新增的服務,只需要執行"net start svnservice","svnservice"就是我們建立服務時使用的名字。

3,配置服務是自動啟動

 預設情況下安裝的服務不會隨Windows的啟動而啟動,為了使svn服務能夠隨Windows啟動而啟動,需要修改一下"sc create"命令(首先要刪除),增加"start= auto"選項:

sc create svnservice
binpath= "D:\Subversion\bin\svnserve.exe --service -r D:\svnroot"
displayname= "SVNService"
depend= Tcpip
start= auto

當然你也可以使用圖形化的工具修改服務的屬性,你可以在“開始->執行...”中執行"services.msc",然後在介面中修改。

Subversion的許可權控制

 1,認證(Authentication)和授權(Authorization)


 這兩個術語經常一起出現。其中認證的意思就是鑑別使用者的身份,最常見的方式就是使用使用者名稱和密碼,授權就是判斷使用者是否具備某種操作的許可權,在Subversion裡提供了“authz-db”檔案,實現了以路徑為基礎的授權,也就是判斷使用者是否有操作對應路徑的許可權,在Subversion 1.3之後,svnserve和Apache一樣都可以使用“authz-db”檔案。

2. svnserve下的配置檔案

 因為本文是以svnserve為例的,所以先介紹一下版本庫目錄的結構:

D:\SVNROOT\PROJECT1
├─conf
├─dav
├─db
│ ├─revprops
│ ├─revs
│ └─transactions
├─hooks
└─locks

其中conf下面有三個檔案:

authz
passwd
svnserve.conf

其中的“svnserve.conf”是這個版本庫的配置檔案,當使用svnserve時,這個配置檔案決定了使用什麼認證和授權檔案:

password-db = passwd
authz-db = authz

上面的配置說明使用“svnserve.conf”同目錄的passwd和authz,其中的password-db指定了使用者密碼檔案,authz-db是我們的授權檔案,也就是我們本文主要介紹的檔案。

注意:使用Apache作為伺服器時,根本就不會參考“svnserve.conf”檔案的內容,而是會參考Apache的配置。

3,基於svnserve的版本庫檔案佈局

 使用svnserve時,為了管理的方便,應該使用相同的認證和授權檔案,所以應該讓所有版本庫的配置檔案svnserve.conf指向同一個password-db和authz-db檔案。下面是一個多版本庫的目錄:

D:\SVNROOT
├─project1
│ ├─conf
│ ├─dav
│ ├─db
│ │ ├─revprops
│ │ ├─revs
│ │ └─transactions
│ ├─hooks
│ └─locks
└─project2
├─conf
├─dav
├─db
│ ├─revprops
│ ├─revs
│ └─transactions
├─hooks
└─locks

D:\SVNROOT下有兩個目錄project1和project2,都已經建立了版本庫,所以我們修改每個conf目錄下的svnserve.conf,使之指向同一個password-db和authz-db檔案。

password-db = ..\..\passwd

 authz-db = ..\..\authz這樣,D:\SVNROOT\passwd和D:\SVNROOT\authz就控制了所有版本庫的svnserve訪問。另外在後面的操作中要關閉匿名訪問,應該去掉“anon-access = none”前的“#”號,保證只有認證使用者可以訪問。

注意:還有一點需要注意,那就是svnserve的“realm”的值,在上面的設定下,應該保證所有的版本庫使用相同的realm值,這樣,對版本庫的密碼快取可以在多個版本庫之間共享,更多細節見客戶端憑證快取。

4,測試使用者和組說明

 版本庫禁止任何匿名使用者的訪問,只對認證使用者有效。

root:配置管理管理員,對版本庫有完全的管理許可權。

p1_admin1:project1的管理員,對project1有完全許可權。
 p1_d1:project1的開發者,對project1的trunk有完全的許可權,但是對其中的/trunk/admin目錄沒有任何許可權。
 p1_t1:project1的測試者,對project1的trunk有完全的讀許可權,但是對其中的/trunk/admin目錄沒有任何許可權。

p2_admin1:project2的管理員,對project2有完全許可權。
 p2_d1:project2的開發者,對project2的trunk有完全的許可權,但是對其中的/trunk/admin目錄沒有任何許可權。
 p2_t1:project2的測試者,對project2的trunk有完全的讀許可權,但是對其中的/trunk/admin目錄沒有任何許可權。

對應的組及組的使用者:

p1_group_a:p1_admin1
p1_group_d:p1_d1
p1_group_t:p1_t1
p2_group_a:p2_admin1
p2_group_d:p2_d1
p2_group_t:p2_t1

5,修改D:\SVNROOT\passwd檔案

前面已經說過了,使用者和密碼檔案應該是在D:\SVNROOT\passwd,所以我們為每一位使用者設定許可權,檔案內容如下:

[users]
p1_admin1 = p1_admin1
p1_d1 = p1_d1
p1_t1 = p1_t1

p2_admin1 = p2_admin1
p2_d1 = p2_d1

p2_t1 = p2_t1為了便於驗證,所有密碼和使用者名稱一致,如果你使用的是其他認證方式,這一步可能不同,但是使用者名稱應該都是一樣的。

6,配置授權,修改D:\SVNROOT\authz

[groups]
# 定義組資訊

p1_group_a = p1_admin1
p1_group_d = p1_d1
p1_group_t = p1_t1

p2_group_a = p2_admin1
p2_group_d = p2_d1
p2_group_t = p2_t1

[/]
# 指定所有的版本庫預設只讀,root可讀寫
* = r
root = rw

[project1:/]
# 指定對版本庫project1根目錄的許可權
@p1_group_a = rw
@p1_group_d = rw
@p1_group_t = r

[project1:/trunk/admin]
# 指定對版本庫project1的/trunk/admin根目錄的許可權,
# p1_group_a讀寫,p1_group_d和p1_group_t沒有任何許可權。
@p1_group_a = rw
@p1_group_d =
@p1_group_t =

[project2:/]
# 指定對版本庫project2根目錄的許可權
@p2_group_a = rw
@p2_group_d = rw
@p2_group_t = r

[project2:/trunk/admin]
# 指定對版本庫project1的/trunk/admin根目錄的許可權
@p2_group_a = rw
@p2_group_d =
@p2_group_t =

經過以上設定以後,你會發現一些有趣的事情。當使用使用者“p1_d1”,檢出project1的trunk時,目錄是空的,好像admin目錄根本不存在一樣,當使用p1_d1使用者瀏覽版本庫時,能夠看到admin目錄,但是其中的內容卻無法看到。

關於中文目錄,也是沒有問題的,只是注意要把authz檔案轉化為UTF-8格式,在我的WINXP的UltraEdit裡顯示的檔案格式為U8-DOS,具體的做法是用UltraEdit開啟authz檔案,然後選擇“檔案->轉換->ASCII轉UTF-8”,然後儲存。

再複雜的情況也不過如此,在實際的工作中要首先規劃好許可權,只賦給使用者最小的許可權,保證以最小的配置實現最複雜的許可權控制。

Subversion備份

 
版本控制最關鍵的一件事是保證資料的安全性,不能因為磁碟損壞,程式故障造成版本庫無可挽回的錯誤,為此必須制定較完備的備份策略。在Subversion中,我們有三種備份方式:完全備份,增量備份和同步版本庫。

1, 完全備份

 最常見和簡單的備份就是直接使用複製命令,將版本庫目錄複製到備份目錄上,就可以了。但是這樣不是很安全的方式,因為如果在複製時版本庫發生變化,將會造成備份的結果不夠準確,失去備份的作用,為此Subversion提供了“svnadmin hotcopy”命令,可以防止這種問題。

還記得我們的版本庫目錄嗎?

D:\SVNROOT
├─project1
│ ├─conf
│ ├─dav
│ ├─db
│ │ ├─revprops
│ │ ├─revs
│ │ └─transactions
│ ├─hooks
│ └─locks
└─project2
├─conf
├─dav
├─db
│ ├─revprops
│ ├─revs
│ └─transactions
├─hooks
└─locks

如果要把project1備份到d:\svnrootbak目錄下,只需要執行:

svnadmin hotcopy d:\svnroot\project1 d:\svnrootbak\project1

但是我們作為配置管理員,必須想辦法最佳化這個過程,如果我們這個目錄下有許多版本庫,需要為每個版本庫寫這樣一條語句備份,為此我寫了下面的指令碼,實現備份一個目錄下的所有版本庫。我們在D:\SVNROOT下建立了兩個檔案,simpleBackup.bat:

@echo 正在備份版本庫%1......
 @%SVN_HOME%\bin\svnadmin hotcopy %1 %BACKUP_DIRECTORY%\%2
 @echo 版本庫%1成功備份到了%2!

這個檔案僅僅是對“svnadmin hotcopy”的包裝,然後是backup.bat:

echo off

rem Subversion的安裝目錄
set SVN_HOME="D:\Subversion"

rem 所有版本庫的父目錄
set SVN_ROOT=D:\svnroot

rem 備份的目錄
set BACKUP_SVN_ROOT=D:\svnrootbak

set BACKUP_DIRECTORY=%BACKUP_SVN_ROOT%\%date:~0,10%
if exist %BACKUP_DIRECTORY% goto checkBack
echo 建立備份目錄%BACKUP_DIRECTORY%>>%SVN_ROOT%/backup.log

mkdir %BACKUP_DIRECTORY%

rem 驗證目錄是否為版本庫,如果是則取出名稱備份
for /r %SVN_ROOT% %%I in (.) do @if exist "%%I\conf\svnserve.conf" %SVN_ROOT%\simpleBackup.bat "%%~fI" %%~nI
goto end

:checkBack
echo 備份目錄%BACKUP_DIRECTORY%已經存在,請清空。
goto end

:end

你在使用的時候,只需要修改backup.bat開頭的三個路徑,將兩個指令碼複製到“SVN_ROOT”下就可以了。根據以上的配置,你只需要執行backup.bat,就可以把“SVN_ROOT”下的版本庫都備份到“BACKUP_SVN_ROOT”裡,並且存放在備份所在日的目錄裡,例如“D:\svnrootbak\2006-10-22”。

雖然這部分工作很簡單,可是必須有人定時地去執行這個操作(例如每週一凌晨),為了避免發生遺忘的情況,我們可以將這個操作加入到系統的at任務當中去,例如還是上面的環境,為了安裝at任務,我們執行:

at 1:00 /every:M D:\svnroot\backup.bat這樣在每週一凌晨1:00都會執行這個備份過程。當然備份在本機也是不安全的,你也許需要上傳到別的機器,這個就要靠你自己去實現了。

2, 增量備份

 儘管完全備份非常簡單,但是也是有代價的,當版本庫非常巨大時,經常進行完全備份是不現實的,也並不必要,但是一旦版本庫在備份之間發生問題,該如何呢,這裡我們就用到了增量備份。

增量備份通常要與完全備份結合使用,就像oracle資料庫的歸檔日誌,記錄著每次Subversion提交的變化,然後在需要恢復時能夠回到最新的可用狀態。在我們這個例子中我們使用的是,svnadmin dump命令進行增量的備份,使用方法是:

svnadmin dump project1 --revision 15 --incremental > dumpfile2

上面的命令實現了對修訂版本15進行增量的備份,其中的輸出檔案dumpfile2只儲存了修訂版本15更改的內容。

為了記錄每次提交的結果,我們需要使用一項Subversion的特性--鉤子(hook),看看我們的project1目錄:

├─project1
│ ├─conf
│ ├─dav
│ ├─db
│ │ ├─revprops
│ │ ├─revs
│ │ └─transactions
│ ├─hooks
│ └─locks

其中的hooks目錄裡存放的就是鉤子指令碼,我們在此處只使用post-commit鉤子,這個鉤子會在每次提交之後執行,為了實現我們的備份功能,我們在hooks下建立一個檔案post-commit.bat,內容如下:

echo off
set SVN_HOME="C:\Program Files\Subversion"
set SVN_ROOT=D:\svnroot
set UNIX_SVN_ROOT=D:/svnroot
set DELTA_BACKUP_SVN_ROOT=D:\svnrootbak\delta
set LOG_FILE=%1\backup.log
echo backup revision %2 >> %LOG_FILE%
for /r %SVN_ROOT% %%I in (.) do if D:/svnroot/%%~nI == %1 %SVN_ROOT%\%%~nI\hooks\deltaBackup.bat %%~nI %2
goto end
:end

透過這個指令碼,可以實現D:\svnroot下的版本庫提交時自動增量備份到D:\svnrootbak\delta(確定這個目錄存在),其中使用的deltaBackup.bat其實可以放在任何地方,只是對指令碼的svnadmin dump的包裝,內容如下:

@echo 正在備份版本庫%2......
 %SVN_HOME%\bin\svnadmin dump %SVN_ROOT%\%1 --incremental --revision %2 >> %DELTA_BACKUP_SVN_ROOT%\%1.dump
 @echo 版本庫%2成功備份到了%3!

以上兩個指令碼可以直接複製到project2的hooks目錄下,不需要修改就可以實現project2的自動備份。

以上的操作已經OK了,現在需要做的是將完全備份和增量備份結合起來,也就是在完全備份後清理增量備份的結果,使之只儲存完全備份後的結果。

當果真出現版本庫的故障,就要求我們實現版本庫的恢復操作了,這是用要使用svnadmin load命令,同時也需要上次的完全備份例如要把上次完全備份backuprepo,和之後的增量備份dumpfile:

svnadmin load backuprepo < dumpfile

最後的結果,可以下載svnroot.rar,將之解壓縮到d:\下,然後修改幾個bat檔案的SVN_HOME就可以使用了。

3, 版本庫同步

Subversion 1.4增加了同步機制,可以實現一個版本庫同另一個版本庫的同步(但好像只是單向的),我們可以用來實現版本庫的備份或映象。

3.1. 對目標庫初始化

 svnsync init svn://localhost/project2 svn://localhost/project1
 其中project2是目標的版本庫,而project1是源版本庫。其中的目標版本庫必須為空,而且必須允許修訂版本屬性的修改,也就是在目標的版本庫的hooks目錄裡新增一個檔案pre-revprop-change.bat,內容為空即可。

3.2. 同步project2到project1

 svnsync sync svn://localhost/project2
 這時候你update一下你的project2的一個工作複製,就會發現有了project1的所有內容。如果project1又有提交,這時候project2的版本庫無法看到最新的變化,還需要再執行一遍sync操作,這樣才能將最新的變化同步。需要注意的是,目標版本庫只能做成只讀的,如果目標版本庫發生了變更,則無法繼續同步了。

3.3. 同步歷史屬性的修改

 因為同步不會更新對歷史屬性的修改,所以svnsync還有子命令copy-revprops,可以同步某個版本的屬性。

3.4. 鉤子自動同步

 希望在每次提交時同步,則需要在源版本庫增加post-commit指令碼,內容如下:

echo off
set SVN_HOME="D:\Subversion"
%SVN_HOME%\bin\svnsync sync --non-interactive svn://localhost/project2

把以上內容存放為post-commit.bat,然後放到版本庫project1下的hooks目錄下,這樣project1每次提交,都會引起project2的同步。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/29867/viewspace-192107/,如需轉載,請註明出處,否則將追究法律責任。

相關文章