
簡(jiǎn)介這份資源面向在銀河麒麟國(guó)產(chǎn) Linux系統(tǒng)上需要搭建版本控制服務(wù)的管理員與開發(fā)人員圍繞「從源碼編譯安裝 SVN 環(huán)境」這一實(shí)際問題給出一條可落地的完整安裝路線。包中共 1 個(gè) docx 文檔約 202KB以文字步驟與命令片段為主體積小、查閱方便適合作為部署時(shí)的對(duì)照手冊(cè)。內(nèi)容覆蓋預(yù)編譯依賴 apr、apr-util 與 sqlite 的下載與 configure/make 安裝Subversion 源碼編譯/etc/profile 環(huán)境變量配置與 svnserve 版本驗(yàn)證以及版本庫(kù)目錄創(chuàng)建、svnadmin create 建庫(kù)等環(huán)節(jié)并說明 svnserve.conf、passwd、authz 三個(gè)配置文件的關(guān)鍵項(xiàng)寫法包括匿名訪問關(guān)閉、鑒權(quán)用戶讀寫、用戶口令與群組權(quán)限設(shè)置還涉及服務(wù)啟動(dòng)與開機(jī)自啟腳本、Windows 客戶端訪問地址格式等延伸細(xì)節(jié)。已有 2798 人學(xué)習(xí)適合需要在內(nèi)網(wǎng)或離線環(huán)境自建 SVN 服務(wù)、希望減少編譯與配置踩坑的讀者參考。1. 銀河麒麟上裝 SVN系統(tǒng)源自帶的版本為什么常常不能直接用一臺(tái)銀河麒麟服務(wù)器要接回一套跑了很多年的版本管理流程運(yùn)維給過來的要求很樸素地址不變、賬號(hào)不變、hook 腳本別動(dòng)。真正動(dòng)手才發(fā)現(xiàn)系統(tǒng)源里的 subversion 版本和這套流程對(duì)不上svnadmin dump出來的東西在兩邊行為不一致鉤子腳本里的路徑假設(shè)也不一樣。老項(xiàng)目維護(hù)最怕版本漂移所以我一般不從源里裝而是把 subversion 1.8.14 連同 apr、apr-util、sqlite 一起源碼編譯鎖死在/usr/local/svn這個(gè)前綴下。這條路適合兩類人一是在國(guó)產(chǎn)化平臺(tái)上必須把 svnserve 跑起來、又拿不到合適軟件包的運(yùn)維二是需要固定版本、機(jī)器在內(nèi)網(wǎng)、只能靠 U 盤或跳板機(jī)往里傳包的開發(fā)。整個(gè)過程不難難的是依賴順序、動(dòng)態(tài)庫(kù)路徑和那三個(gè)配置文件里的細(xì)節(jié)下面按我實(shí)際走通的順序拆。2. 依賴三件套apr、apr-util、sqlite 的編譯順序與參數(shù)怎么定subversion 不是一個(gè)能單獨(dú)站住的程序。它把文件操作、內(nèi)存池、字符串處理、網(wǎng)絡(luò)收發(fā)幾乎全部壓在 Apache Portable Runtime 上所以 apr 和 apr-util 必須先就位而 1.8 這一支又把 sqlite 的源碼直接塞進(jìn)自己的構(gòu)建流程里用一份 amalgamation 源碼現(xiàn)場(chǎng)編不依賴系統(tǒng)里的 libsqlite3。三者的關(guān)系是一條鏈順序錯(cuò)了 configure 就會(huì)在探測(cè)階段直接退出。2.1 為什么必須先 apr 后 apr-util再輪到 subversionapr-util 的 configure 腳本第一件事就是找 apr 的頭文件和庫(kù)找不到就報(bào)錯(cuò)退出。而 subversion 的 configure 會(huì)同時(shí)找 apr 和 apr-util兩個(gè)都齊了才繼續(xù)往下探測(cè)。所以順序只能是 apr → apr-util → subversion沒有別的排列。這里還有個(gè)容易被忽略的點(diǎn)apr 和 apr-util 的版本要成套。apr-1.6.5 配 apr-util-1.6.1 是同一代的組合跨代混搭時(shí) configure 未必報(bào)錯(cuò)但編譯到一半出現(xiàn)結(jié)構(gòu)體成員不匹配的情況我見過不止一次。手上沒有成套的包就先停下來把版本對(duì)齊別硬編。安裝前綴我習(xí)慣分開寫/usr/local/apr、/usr/local/apr-util、/usr/local/svn。全都塞進(jìn)/usr/local看著省事實(shí)際是給自己埋雷——頭文件和庫(kù)全糊在一起將來想單獨(dú)升級(jí)或卸掉其中一個(gè)根本分不清哪些文件是誰的。# 全程 root源碼包統(tǒng)一放在 /home/dmdba/svn 下 cd /home/dmdba/svn # 1) 編譯 apr只依賴系統(tǒng)自帶的 gcc / make cd apr-1.6.5 ./configure --prefix/usr/local/apr make -j4 make install # 2) 編譯 apr-util--with-apr 指向 apr 的安裝前綴不是源碼目錄 cd ../apr-util-1.6.1 ./configure --prefix/usr/local/apr-util --with-apr/usr/local/apr make -j4 make install--prefix決定make install把東西放到哪后面 subversion 的--with-apr必須和它一字不差。-j4是按 CPU 核數(shù)給的編譯機(jī)上核多可以給到 8核少就給 2給太高在內(nèi)存緊張的虛機(jī)上會(huì)因?yàn)?OOM 直接殺掉編譯進(jìn)程表現(xiàn)成莫名其妙的make: *** [xxx] Killed。2.2 apr-util 的--with-apr寫錯(cuò)會(huì)怎么表現(xiàn)--with-apr后面跟的必須是 apr 的安裝前綴/usr/local/apr不是解壓出來的源碼目錄/home/dmdba/svn/apr-1.6.5。寫成源碼目錄時(shí) configure 有時(shí)也能過因?yàn)樗茉谠创a樹里找到apr.h但make install之后 apr-util 里記錄的路徑是錯(cuò)的等到 subversion 鏈接階段才會(huì)以cannot find -lapr-1的形式爆出來。判斷方法很直接configure 跑完看它打印的摘要行./configure --prefix/usr/local/apr-util --with-apr/usr/local/apr 21 | tail -20正常的輸出里會(huì)出現(xiàn)checking for apr-config... /usr/local/apr/bin/apr-1-config這樣的行。如果這一行顯示的是源碼目錄或者干脆是no就說明路徑給錯(cuò)了別急著 make先回去改。另外如果系統(tǒng)里缺 expat 開發(fā)包apr-util 會(huì)跳過 expat 支持繼續(xù)編。這對(duì) svnserve 本身影響不大但如果后面要接 Apache httpd 做 http 訪問就會(huì)缺 DAV 相關(guān)能力。想一次到位編譯前把expat-devel、zlib-devel、openssl-devel裝上能省掉后面重編 apr-util 的返工。2.3 sqlite-amalgamation 不用編譯但改名和位置是硬約束subversion 1.8.14 的構(gòu)建腳本不調(diào)用系統(tǒng)的 sqlite3而是在源碼根目錄下找sqlite-amalgamation/sqlite3.c這個(gè)文件找到之后現(xiàn)場(chǎng)編進(jìn)去。這個(gè)約定非常死目錄名差一個(gè)字符都不認(rèn)。從官網(wǎng)下下來的是sqlite-amalgamation-3071501.zip解壓出來是同名目錄。必須把它挪到 subversion 源碼根目錄下并且改名為sqlite-amalgamationcd /home/dmdba/svn unzip sqlite-amalgamation-3071501.zip # 挪進(jìn) subversion 源碼樹并改成構(gòu)建腳本認(rèn)的名字 mv sqlite-amalgamation-3071501 subversion-1.8.14/sqlite-amalgamation # 確認(rèn)文件在位這一步別省 ls -l subversion-1.8.14/sqlite-amalgamation/sqlite3.c最后那條ls是我每次都會(huì)敲的。少敲這一下等到 subversion 編了十幾分鐘才報(bào)sqlite3.c: No such file返工的時(shí)間遠(yuǎn)比這一行命令貴。2.4 離線傳包與解壓后的目錄規(guī)劃內(nèi)網(wǎng)機(jī)器最常見的傳包方式是跳板機(jī) scp 或 U 盤掛載。不管哪種落地之后統(tǒng)一解壓到同一個(gè)父目錄路徑才好寫cd /home/dmdba/svn tar -zxvf apr-1.6.5.tar.gz tar -zxvf apr-util-1.6.1.tar.gz tar -zxvf subversion-1.8.14.tar.gz unzip sqlite-amalgamation-3071501.zip ls -d apr-1.6.5 apr-util-1.6.1 subversion-1.8.14 sqlite-amalgamation-3071501四個(gè)包解壓后應(yīng)該平級(jí)出現(xiàn)在/home/dmdba/svn下這是后面所有cd命令的前提。傳包過程中最怕的是壓縮包被截?cái)鄑ar -zxvf報(bào)unexpected EOF就是這個(gè)原因重傳一遍即可別懷疑包本身。提示銀河麒麟的默認(rèn) shell 和 coreutils 與新版本發(fā)行版存在差異腳本里凡是涉及通配符和路徑拼接的地方寧可寫全路徑也別依賴相對(duì)路徑的推斷。3. subversion 1.8.14 編譯configure 三個(gè)--with與 make 中斷的處理依賴齊了之后subversion 這一關(guān)卡人的地方集中在兩個(gè)階段configure 的依賴探測(cè)和 make 的鏈接階段。前者報(bào)錯(cuò)很干脆一行紅字告訴你缺什么后者往往要滾幾百行才露出真正的原因得會(huì)從日志尾部往回翻。3.1 configure 階段依賴探測(cè)的三個(gè)關(guān)鍵參數(shù)subversion 的 configure 參數(shù)不少真正必須顯式給的就三個(gè)安裝前綴、apr 路徑、apr-util 路徑。cd /home/dmdba/svn/subversion-1.8.14 ./configure \ --prefix/usr/local/svn \ --with-apr/usr/local/apr \ --with-apr-util/usr/local/apr-util \ 21 | tee /tmp/svn-configure.log三個(gè)參數(shù)的含義務(wù)必分清--prefix是自己要裝到哪--with-apr和--with-apr-util是依賴在哪。前一個(gè)寫錯(cuò)裝完找不到命令后兩個(gè)寫錯(cuò)configure 直接報(bào)APR not found或APR-UTIL not found然后退出。tee那一段不是多余的。configure 輸出動(dòng)輒幾百行滾屏之后想回頭找具體是哪個(gè)探測(cè)失敗只能靠日志。養(yǎng)成把 configure 和 make 的輸出都落一份到/tmp的習(xí)慣出問題時(shí)grep -i error一下就能定位。configure 順利跑完時(shí)末尾會(huì)打印一段摘要里面能看到APR、APR-UTIL、SQLite各自的版本和路徑。這一段建議截圖或復(fù)制留存將來排查版本不一致時(shí)是唯一的對(duì)照依據(jù)。3.2 make 中斷先看這三處不要急著重裝系統(tǒng)make 失敗的原因五花八門但在麒麟上裝 1.8.14 這個(gè)組合九成跑不出下面三種第一處sqlite3.c 找不到。前面 2.3 節(jié)說過目錄名和位置不對(duì)就會(huì)在編譯到 sqlite 那一層時(shí)中斷。解決辦法是把sqlite-amalgamation目錄放回 subversion 源碼根目錄并確認(rèn)文件名。第二處鏈接階段報(bào)undefined reference to一串 apr 符號(hào)。這基本是 apr-util 編譯時(shí)沒真正鏈上 apr回頭重編 apr-util--with-apr指向安裝前綴別指向源碼目錄。第三處編譯器把警告當(dāng)錯(cuò)誤。新版 gcc 對(duì)某些老代碼的隱式類型轉(zhuǎn)換會(huì)給出-Werror級(jí)別的提示1.8.14 這樣的老代碼在新工具鏈上偶爾會(huì)撞上。這種情況不是代碼壞了是編譯選項(xiàng)太嚴(yán)可以在 configure 時(shí)加一句放寬# 編譯失敗時(shí)先把完整日志留下來再?zèng)Q定怎么改 make -j4 21 | tee /tmp/svn-make.log # 從日志尾部往前找第一個(gè) error而不是從頭讀 grep -n -i error /tmp/svn-make.log | head -20grep出來的第一條 error 往往不是根因真正的根因通常在它上面幾十行。用sed -n 起始行,結(jié)束行p /tmp/svn-make.log把上下文打出來看比一行行往上翻快得多。3.3 動(dòng)態(tài)庫(kù)路徑/etc/ld.so.conf.d里那兩行省不得make install成功不代表能跑。subversion 的可執(zhí)行文件鏈接的是/usr/local/svn/lib下的libsvn_*apr 的庫(kù)在/usr/local/apr/lib這些目錄都不在系統(tǒng)默認(rèn)的庫(kù)搜索路徑里。不處理的話svnserve --version會(huì)以error while loading shared libraries: libsvn_client-1.so.0收?qǐng)?。正確做法是交給 ldconfig 管理而不是在/etc/profile里堆LD_LIBRARY_PATHcat /etc/ld.so.conf.d/svn.conf EOF /usr/local/apr/lib /usr/local/apr-util/lib /usr/local/svn/lib EOF # 讓新配置生效 ldconfig # 驗(yàn)證庫(kù)是否已被系統(tǒng)識(shí)別 ldconfig -p | grep -E libsvn_client|libapr-1三行路徑按依賴順序排列l(wèi)dconfig會(huì)把它們加進(jìn)緩存。用 conf.d 的好處是干凈、可回滾將來升級(jí)只需改這一個(gè)文件再ldconfig。相比之下往/etc/profile里追加LD_LIBRARY_PATH只對(duì)交互式登錄的 shell 生效systemd 拉起的服務(wù)和 cron 任務(wù)讀不到是典型的“手動(dòng)能跑、開機(jī)就掛”。3.4 PATH 生效與svnserve --version的冒煙驗(yàn)證最后一步是把/usr/local/svn/bin加進(jìn) PATH。寫在/etc/profile末尾對(duì)所有用戶生效cat /etc/profile EOF # Subversion export PATH$PATH:/usr/local/svn/bin EOF # 當(dāng)前會(huì)話立即生效 source /etc/profile # 三件事一起驗(yàn)命令找得到、版本對(duì)得上、動(dòng)態(tài)庫(kù)加載正常 which svnserve svnserve --version svn --version --quietwhich svnserve應(yīng)該輸出/usr/local/svn/bin/svnserve。如果輸出的是/usr/bin/svnserve說明系統(tǒng)里原本就裝著 subversionPATH 順序不對(duì)把/usr/local/svn/bin提到前面或者干脆把系統(tǒng)自帶的卸掉避免兩套混用。svnserve --version會(huì)打印版本號(hào)和編譯時(shí)間同時(shí)把依賴的 apr、apr-util、sqlite 版本一并列出來。這一屏信息極其有用后面遇到任何行為異常第一件事就是回來核對(duì)這三個(gè)版本號(hào)。注意svn --version --quiet只輸出版本號(hào)適合寫進(jìn)腳本做版本斷言svnserve --version輸出更全適合人工核對(duì)。4. 版本庫(kù)與權(quán)限svnadmin create之后的三個(gè)配置文件怎么落地服務(wù)能啟動(dòng)只是開始真正決定這套 SVN 好不好用的是版本庫(kù)結(jié)構(gòu)和權(quán)限模型。svnadmin create一條命令就能建庫(kù)但它生成的conf目錄里那三個(gè)文件任何一個(gè)改錯(cuò)都會(huì)讓客戶端連不上而且報(bào)錯(cuò)信息相當(dāng)不友好。4.1svnadmin create的實(shí)際產(chǎn)物與目錄規(guī)劃版本庫(kù)根目錄的選擇有講究。放在/home/svn下方便備份但要注意系統(tǒng)安全策略對(duì)這個(gè)路徑的讀取限制放在/var/svn下更符合常規(guī)權(quán)限管理也更順。我這邊沿用/home/svn因?yàn)閭浞菽_本早就按這個(gè)路徑寫死了。# 版本庫(kù)的父目錄注意這一步只是普通目錄 mkdir -p /home/svn # 項(xiàng)目目錄作為單個(gè)版本庫(kù)存在 mkdir -p /home/svn/project # 關(guān)鍵一步把普通目錄變成 SVN 版本庫(kù) svnadmin create /home/svn/project # 看它生成了什么 ls -l /home/svn/project執(zhí)行完svnadmin create之后/home/svn/project下會(huì)多出conf、db、hooks、locks、format、README.txt。db是 FSFS 格式的實(shí)際存儲(chǔ)日常不用碰hooks放提交前后的鉤子腳本老流程里那些“提交后發(fā)郵件”的邏輯就掛在這conf是接下來要改的三個(gè)文件所在。有一點(diǎn)要提前說清楚/home/svn是所有版本庫(kù)的父目錄/home/svn/project才是一個(gè)版本庫(kù)。這個(gè)層級(jí)關(guān)系決定了后面svnserve -r參數(shù)該指到哪搞混了客戶端就會(huì)連到空路徑。4.2svnserve.conf四行配置的作用域和頂格規(guī)則conf/svnserve.conf是服務(wù)端的總開關(guān)里面的配置項(xiàng)全部要頂格寫行首不能留空格注釋行用#開頭。這不是格式潔癖解析器對(duì)前導(dǎo)空白極敏感行首多一個(gè)空格就會(huì)導(dǎo)致啟動(dòng)失敗而且報(bào)錯(cuò)信息只說“配置錯(cuò)誤”不告訴你是哪一行。[general] anon-access none auth-access write password-db passwd authz-db authz realm /home/svn五行的含義逐條過一遍anon-access none匿名用戶什么都不能做。默認(rèn)是read意味著不登錄也能看代碼這個(gè)默認(rèn)值在公網(wǎng)環(huán)境是重大風(fēng)險(xiǎn)必須改。auth-access write通過認(rèn)證的用戶可以讀寫。只想給某些人讀權(quán)限靠下面的 authz 文件控制這一行給write是上限。password-db passwd賬號(hào)密碼文件。這里寫的是相對(duì)路徑相對(duì)于conf目錄所以實(shí)際讀的是conf/passwd。authz-db authz權(quán)限控制文件同樣是相對(duì)conf的路徑。realm /home/svn認(rèn)證域。這一行原配置里沒有建議加上。不設(shè)的話客戶端會(huì)用默認(rèn)域緩存憑據(jù)同一臺(tái)機(jī)器連多個(gè)不同 SVN 服務(wù)時(shí)賬號(hào)密碼會(huì)互相覆蓋表現(xiàn)成“密碼明明對(duì)卻一直認(rèn)證失敗”。password-db和authz-db也可以寫絕對(duì)路徑。寫絕對(duì)路徑的好處是不受conf目錄位置影響壞處是遷移版本庫(kù)時(shí)要跟著改。我一般保持相對(duì)路徑把整個(gè)版本庫(kù)目錄一起搬走就能用。4.3passwd與authz分組、路徑前綴與匹配順序passwd只管賬號(hào)不管權(quán)限格式極簡(jiǎn)[users] admin 123456 dev01 123456 dev02 123456等號(hào)兩邊可以有空格解析器會(huì)裁掉。密碼是明文存儲(chǔ)這一點(diǎn)要有心理準(zhǔn)備——conf目錄的權(quán)限必須收緊到700否則同機(jī)器上任何用戶都能看到密碼。authz才是真正決定誰能訪問哪里的地方它支持分組、路徑和權(quán)限三元組[groups] g_admin admin g_dev dev01,dev02 [/] g_admin rw g_dev r * 逐段解釋[groups]段定義組。一個(gè)用戶可以屬于多個(gè)組組名前面加引用。[/]表示版本庫(kù)根路徑。注意這個(gè)斜杠是相對(duì)版本庫(kù)根不是文件系統(tǒng)根。如果只想放開某個(gè)子目錄寫成[/trunk/docs]這種形式。g_admin rw管理員組讀寫。g_dev r開發(fā)組只讀。* 除上面列出的組之外的所有用戶權(quán)限為空也就是拒絕。這一行必須寫不寫的話未列出的用戶會(huì)落到默認(rèn)策略容易出現(xiàn)“誰都能進(jìn)”的意外。匹配順序是從具體到寬泛路徑越長(zhǎng)的規(guī)則優(yōu)先同一條路徑上用戶規(guī)則的優(yōu)先級(jí)高于組規(guī)則。所以給某個(gè)特定用戶單獨(dú)開權(quán)限時(shí)直接把用戶名寫進(jìn)去比如zhangsan rw它會(huì)覆蓋所在組的限制。改完這三個(gè)文件不需要重啟服務(wù)svnserve 每次請(qǐng)求都會(huì)重新讀配置。這一點(diǎn)很省事但也意味著改錯(cuò)了會(huì)立刻生效改之前先備份一份。4.4svnserve -d -r的-r到底停在哪一層啟動(dòng)命令是svnserve -d -r /home/svn。-d是守護(hù)進(jìn)程模式-r是版本庫(kù)根路徑。關(guān)鍵在于-r要指到所有版本庫(kù)的父目錄不是某個(gè)具體版本庫(kù)# 正確指到父目錄 /home/svn svnserve -d -r /home/svn # 錯(cuò)誤指到具體版本庫(kù)客戶端 URL 會(huì)多一層且其他庫(kù)訪問不到 # svnserve -d -r /home/svn/project # 確認(rèn)進(jìn)程和端口 ps -ef | grep svnserve ss -lntp | grep 3690-r /home/svn之后客戶端訪問地址是svn://服務(wù)器IP/project。如果寫成-r /home/svn/project地址就變成svn://服務(wù)器IP/而且再想加第二個(gè)項(xiàng)目就得重啟服務(wù)換路徑。端口默認(rèn) 3690啟動(dòng)后必須確認(rèn)防火墻放行# firewalld 環(huán)境 firewall-cmd --permanent --add-port3690/tcp firewall-cmd --reload firewall-cmd --list-portsps能看到進(jìn)程但客戶端連不上八成就是防火墻這一層。這個(gè)坑后面還會(huì)細(xì)說。5. 避坑與排查五條在麒麟上真踩過的記錄下面的每一條都是實(shí)際遇到的按“現(xiàn)象 → 原因 → 解決”的順序?qū)懹龅酵悊栴}時(shí)可以直接對(duì)號(hào)入座。5.1 啟動(dòng)即退出日志里只有一行 “Option expected”現(xiàn)象執(zhí)行svnserve -d -r /home/svn后進(jìn)程沒起來前臺(tái)跑一次就輸出svnserve: /home/svn/project/conf/svnserve.conf:12: Option expected然后退出。原因svnserve.conf里某個(gè)配置項(xiàng)前面留了空格或制表符。這個(gè)文件是 ini 風(fēng)格解析但解析器對(duì)行首空白零容忍。常見的觸發(fā)場(chǎng)景是從網(wǎng)頁或聊天窗口復(fù)制配置粘貼時(shí)帶了縮進(jìn)。解決用cat -A conf/svnserve.conf把所有不可見字符打出來行首出現(xiàn)^I制表符或一串空格的就是元兇。把所有配置項(xiàng)改成頂格注釋行統(tǒng)一用#開頭改完再啟動(dòng)。養(yǎng)成習(xí)慣改完這個(gè)文件先cat -A掃一眼再敲啟動(dòng)命令。5.2 客戶端 Connection refused服務(wù)端ps卻能看到進(jìn)程現(xiàn)象服務(wù)器上ps -ef | grep svnserve有進(jìn)程端口也在監(jiān)聽但 Windows 客戶端連svn://192.168.10.20/project報(bào)Unable to connect to a repository at URL底層是連接被拒。原因系統(tǒng)防火墻沒放行 3690。另一種情況是svnserve監(jiān)聽在 IPv6 而客戶端走 IPv4ss -lntp的輸出里如果只有[::]:3690而沒有0.0.0.0:3690就是這個(gè)原因。解決先放行端口firewall-cmd --permanent --add-port3690/tcp firewall-cmd --reload再確認(rèn)監(jiān)聽地址ss -lntp | grep 3690應(yīng)能看到0.0.0.0:3690。如果只監(jiān)聽 IPv6檢查/etc/hosts和系統(tǒng)是否禁用了 IPv4 回環(huán)。5.3 密碼沒錯(cuò)卻一直認(rèn)證失敗現(xiàn)象客戶端反復(fù)彈認(rèn)證框輸入admin/123456始終提示認(rèn)證失敗服務(wù)端日志里沒有明顯報(bào)錯(cuò)。原因最常見的是passwd文件里的用戶名帶了前后空格或者authz里根本沒有為這個(gè)用戶配置任何路徑權(quán)限。還有一種隱蔽情況是客戶端緩存了舊憑據(jù)清掉緩存前怎么輸都不對(duì)。解決先用svn auth --show-passwords或客戶端自帶的“清除認(rèn)證緩存”把本地緩存清掉再核對(duì)authz里是否有[/]段對(duì)這個(gè)用戶或所在組授權(quán)最后檢查passwd文件的編碼必須是 UTF-8 無 BOM帶 BOM 時(shí)第一行用戶名會(huì)解析失敗。5.4 重啟后 SVN 沒起來rc.local里的腳本像沒執(zhí)行現(xiàn)象手動(dòng)執(zhí)行/root/svn.sh一切正常重啟機(jī)器后ps里沒有 svnserve 進(jìn)程腳本里的日志也沒寫。原因/etc/rc.d/rc.local這個(gè)文件在新版系統(tǒng)上默認(rèn)沒有執(zhí)行權(quán)限systemd 不會(huì)去跑它。另一個(gè)原因是腳本里寫的是相對(duì)路徑svnserve而開機(jī)時(shí) PATH 還沒加載到/usr/local/svn/bin。解決chmod x /etc/rc.d/rc.local給上執(zhí)行權(quán)限腳本里改用絕對(duì)路徑/usr/local/svn/bin/svnserve -d -r /home/svn。查絕對(duì)路徑用which svnserve。更穩(wěn)妥的做法是舍棄 rc.local寫成 systemd 服務(wù)單元下一章展開。5.5svn命令能跑svnserve卻說找不到 libsvn_client現(xiàn)象交互式登錄后svn --version正常但svnserve啟動(dòng)報(bào)error while loading shared libraries: libsvn_client-1.so.0: cannot open shared object file。原因動(dòng)態(tài)庫(kù)搜索路徑?jīng)]配。svn和svnserve鏈接的庫(kù)不完全相同前者可能命中了系統(tǒng)自帶的舊庫(kù)后者走的是/usr/local/svn/lib。解決按 3.3 節(jié)寫/etc/ld.so.conf.d/svn.conf把三個(gè) lib 目錄列進(jìn)去執(zhí)行l(wèi)dconfig再用ldconfig -p | grep libsvn確認(rèn)。改完必須重開一個(gè)會(huì)話舊會(huì)話的環(huán)境變量還是老的。6. 把 svnserve 交給 systemd一次寫對(duì)之后不用再碰 rc.localrc.local那套做法在老系統(tǒng)上能用但在麒麟這一類新系統(tǒng)上它依賴“被手動(dòng)賦予執(zhí)行權(quán)限”這個(gè)前提換臺(tái)機(jī)器部署就得重新記得敲一次chmod x屬于典型的靠人肉記憶維持的配置。我現(xiàn)在的做法是直接寫 systemd 單元一次寫對(duì)后面復(fù)制過去就能用。先看單元文件。放在/etc/systemd/system/svnserve.service[Unit] DescriptionSubversion Server Afternetwork.target [Service] Typeforking ExecStart/usr/local/svn/bin/svnserve -d -r /home/svn ExecStop/usr/bin/pkill -f svnserve -d -r /home/svn Restarton-failure RestartSec3 [Install] WantedBymulti-user.target幾個(gè)關(guān)鍵點(diǎn)說明一下。Typeforking是因?yàn)閟vnserve -d會(huì)自己 fork 到后臺(tái)父進(jìn)程立刻退出systemd 需要知道這一點(diǎn)才不會(huì)誤判服務(wù)已死。ExecStart里用的是絕對(duì)路徑繞開 PATH 未加載的問題。ExecStop用pkill -f按完整命令行匹配比按進(jìn)程名殺更精確避免誤傷其他 svn 相關(guān)進(jìn)程。Restarton-failure加RestartSec3是給自己留的后悔藥——進(jìn)程意外退出時(shí) 3 秒后自動(dòng)拉起比人肉發(fā)現(xiàn)再登錄處理快得多。啟用和驗(yàn)證按這個(gè)順序走# 重新加載單元文件讓新寫的 service 生效 systemctl daemon-reload # 設(shè)為開機(jī)自啟并立即啟動(dòng) systemctl enable --now svnserve # 看狀態(tài)重點(diǎn)看 Active 那一行是不是 active (running) systemctl status svnserve --no-pager # 從外部驗(yàn)證端口真的在監(jiān)聽 ss -lntp | grep 3690systemctl status的輸出里如果出現(xiàn)Active: active (running)說明服務(wù)起來了如果是failed用journalctl -u svnserve -n 50 --no-pager看最近 50 行日志比翻/var/log/messages快得多。服務(wù)起來之后驗(yàn)證要分三層做別只做最上面一層層次驗(yàn)證命令通過標(biāo)準(zhǔn)進(jìn)程與端口ss -lntp | grep 3690顯示0.0.0.0:3690處于 LISTEN服務(wù)端自檢svn info svn://127.0.0.1/project輸出倉(cāng)庫(kù) UUID 和 Revision客戶端拉取svn checkout svn://192.168.10.20/project /tmp/proj-test檢出成功能提交一次測(cè)試文件三層里最容易漏的是第二層。很多人直接拿 Windows 客戶端試連不上時(shí)分不清是服務(wù)端問題還是網(wǎng)絡(luò)問題。先在服務(wù)器本機(jī)用svn info打一次本機(jī)通了再排查網(wǎng)絡(luò)問題范圍立刻縮小一半。最后說個(gè)我自己的習(xí)慣。每次交付這類環(huán)境我都會(huì)把svnserve.conf、passwd、authz三個(gè)文件連同 systemd 單元一起打包到版本庫(kù)的docs/目錄下寫清楚版本號(hào)和改動(dòng)日期。不是怕自己忘是怕半年后接手的人對(duì)著一個(gè)跑著的服務(wù)完全不知道它當(dāng)初是怎么配起來的——這臺(tái)機(jī)器會(huì)變成一個(gè)黑匣子。從那以后我每次裝完 SVN都會(huì)強(qiáng)制走一遍“本機(jī) svn info → 外部 checkout → 重啟機(jī)器再驗(yàn)一次”這三步缺一步都不算交付完成。希望幫到你。本文還有配套的精品資源點(diǎn)擊獲取