之前的SVN服务器部署在VPS上,主要功能包括:
- nginx+apache+svn,可以通过http访问;
- 自定义了post-commit,在每次收到版本提交时
- 自动发送邮件通知更新内容;
- 自动增量备份版本库,并把备份文件上传到指定的FTP
post-commit的内容如下:
#!/bin/sh REPOS="$1" REV="$2" export LANG="en_US.UTF-8" #"$REPOS"/hooks/mailer.py commit "$REPOS" $REV "$REPOS"/mailer.conf /usr/local/bin/svnnotify --repos-path "$1" --revision "$2" --to someone@bernieyu.com,someone2@bernieyu.com --from svn@bernieyu.com --handler "HTML::ColorDiff" --smtp smtp.bernieyu.com --smtp-user svn@bernieyu.com --smtp-pass password --svnlook /usr/bin/svnlook --subject-prefix '[SVN Update]' svnadmin dump "$REPOS" --revision "$REV" --incremental >/home/svn/dev/export/rev_$REV.dump ftp -n<<! open bernieyoo.bernieyu.com user ftpuser password binary cd /svnbak lcd /home/svn/dev/export prompt put rev_$REV.dump close bye ! rm -f /home/svn/dev/export/rev_$REV.dump
考虑到数据安全性,以及连接SVN的速度,决定把SVN迁移到家里的Synology上。
1. 在Synology的套件中心里安装SVN;
安装好后有一个问题,就是SVN的存储目录不能指定放在哪块硬盘,比如我想放在/volume2/svn,而安装后会自动安装在/volume4/svn. 于是将/volume4/svn删除,然后再建立到/volume2/svn的软连接
rm -rf /volume4/svn ln -s /volume2/svn /volume4/svn
2. 建立repository
在Synology中打开Svn管理页面,创建名为dev的repository,并创建用户。
3. 导出VPS上的SVN版本库, 并复制到Synology
#!/bin/sh
cd ~/svnbak
svndump(){
file_name=rev_$1.dump
svnadmin dump /home/svn/dev -r $1 --incremental > $file_name
}
ver=`svnlook youngest /home/svn/dev`
svndump 0;
for i in `seq $ver`; do
svndump $i;
done;
exit 0
4. 导入SVN数据到Synology
#!/bin/sh svnadmin load /volume2/svn/dev < /volume2/doc/projects/svnbak/dev/rev_0.dump; for i in `seq 184`; do svnadmin load /volume2/svn/dev < /volume2/doc/projects/svnbak/dev/rev_$i.dump; done; exit 0
5. 修改post-commit,以实现邮件通知和自动备份功能
- mailer.py需要安装python-svn,但ipkg里的版本与Synology套件中心提供的python版本不一样,于是不考虑了
- svnnotify没有在ipkg里找到
于是考虑用curl把版本库信息提交到一个web页面,再由这个页面发送邮件。但是一查curl的帮助,发现最新版的已经可以直接使用Smtp发送邮件了,大喜,一试发现竟然真的可以,而且还支持SMTPS
#!/bin/sh
REPOS="$1"
REV="$2"
export LANG="en_US.UTF-8"
#生成备份
svnadmin dump "$REPOS" --revision "$REV" --incremental >/volume2/doc/projects/svnbak/dev/rev_$REV.dump
#复制到baidu云的自动备份目录
cp /volume2/doc/projects/svnbak/dev/rev_$REV.dump /volume2/doc/baidu/svn_bak/dev/rev_$REV.dump
#得到版本更新相关信息
svnuid=`svnlook uuid $REPOS`
author=`svnlook author -r $REV $REPOS`
date=`svnlook date -r $REV $REPOS`
log=`svnlook log -r $REV $REPOS`
changed=`svnlook changed -r $REV $REPOS`
file="content.txt"
smtpserver="smtps://smtp.bernieyu.com:465"
mailfrom="svn@bernieyu.com"
mailrcpt="someone@bernieyu.com"
smtpuser="svn@bernieyu.com"
smtppwd="password"
#HTML邮件的CSS,从svnnotify复制来的
css="<style type=\"text/css\"> <!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff;}
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg{ font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; }
#msg dl a { font-weight: bold}
#msg dl a:link { color:#fc3; }
#msg dl a:active { color:#ff0; }
#msg dl a:visited { color:#cc6; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote{ margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd{ line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6{ margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child{ margin-top: 0; }
#logmsg ul, #logmsg ol{ padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }
#logmsg ol { text-indent: -1.5em; padding-left: 1.5em;}
#logmsg > ul, #logmsg > ol{ margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'�';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer{ color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4{margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff{padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile{border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info{color:#888;background:#fff;}
-->}
</style>"
echo "From: \"SVN\" <$mailfrom>
To: \"Bernie Yu\" <$mailrcpt>
Subject: [SVN Update][$REV] $log
Content-Type: text/html; charset=\"us-ascii\"
<html> <head>$css</head> <body>
<div id=\"msg\">
<dl class=\"meta\">
<dt>Revision</dt> <dd>$REV</dd>
<dt>Author</dt> <dd>$author</dd>
<dt>Date</dt> <dd>$date</dd>
</dl>
<h3>Log Message</h3>
<pre>$log</pre>
<h3>Change Detail</h3>
<ul>" > $file
OLDIFS=$IFS
IFS=$'\n'
for line in $changed
do
echo "<li>$line</li>" >> $file
done
IFS=$OLDIFS
echo "</ul>
</div>
</body> </html>" >> $file
curl --url "$smtpserver" --ssl-reqd --mail-from "$mailfrom" --mail-rcpt "$mailrcpt" --upload-file $file --user "$smtpuser:$smtppwd" --insecure
测试成功,搞定!
PS:
目前遗留的问题一是Synology自带的SVN不支持HTTP访问,只能通过SVN协议访问。在路由器添加了端口映射后,用SVN协议访问影响不大。安装SVN后需要重启一下Synology,我当时没重启,结果端口映射后怎么也访问不到。二是SSH+SVN还没有搞定,因为SVN添加的用户只是SVN的用户而不是SSH用户,暂时还找不到解决办法。
