原理:在svn服务端编写post-commit钩子,当svn客户端更新svn时,服务端会自动执行钩子脚本,在web目录自动执行svnup命令同步最新文件。
方式一:
利用svn update命令------svn update svn://192.168.1.1 /data/www/htdocs
编写钩子脚本vim /data/svn/repositories/hooks/post-commit
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
#!/bin/sh export LANG=en_US.UTF-8 REPOS="$1" REV="$2" SVN_PATH=/usr/bin/ WEB_PATH=/data/www/xingame SVN_USER=test SVN_PASS=ptest WEB_USER=www LOG_PATH=/data/log/svn/svn.log echo `date "+%Y-%m-%d %H:%M:%S"` >> $LOG_PATH echo `whoami`,$REPOS,$REV >> $LOG_PATH $SVN_PATH/svn update svn://192.168.1.69:3690/xingame $WEB_PATH --force --username $SVN_USER --password $SVN_PASS --no-auth-cache >> $LOG_PATH chown $WEB_USER.$WEB_USER -R $WEB_PATH #同步多台服务器 cd /data/www/htdocs/ /usr/bin/rsync --timeout=30 -Ravz --exclude-from=/data/svn/repositories/exclude/htdocs.list ./* 192.168.1.2::htdocs /usr/bin/rsync --timeout=30 -Ravz --exclude-from=/data/svn/repositories/exclude/htdocs.list ./* 192.168.1.3::htdocs chown -R apache:apache /data/www/htdocs/ chmod -R 755 /data/www/htdocs/ #htdocs.list是存放不被同步的文件,包括子目录下出现此类文件都不会被同步 #往htdocs.list加入.svn这样只要包含.svn的目录都不会被同步
方式二:
利用svn export命令------svn export svn://192.168.1.69:3690/xing $WEB_PATH --force --username $SVN_USER --password $SVN_PASS --no-auth-cache
如果只是用export代替update的话,不会再网站根目录产生.svn文件夹但是每次更新会export整个目录而且还要更改属组,文件少也没什么,文件多了就耗时耗资源了,所以有了下面的php脚本。
配合执行php脚本就可以实现只更新提交文件,编写钩子脚本vim /data/svn/repositories/hooks/post-commit.
#!/bin/sh # 语言环境 export LANG=en_US.UTF-8 # 库的路径 REPOS="$1" # 新提交的版本号 REV="$2" SVN_PATH=/usr/bin/ WEB_PATH=/data/www/xing/ SVN_USER=test SVN_PASS=stest SVN_PATH=svn://192.168.1.69:3690/xing/ WEB_USER=www # 日志位置 LOG_PATH=/data/log/svn/svn.log # 改变的内容 changed=$(svnlook changed -r $REV $REPOS) #记录日志 log=$(svnlook log -r $REV $REPOS) #变量回车 n=$'\n' #日志输出角色、资源路径、版本号 #root,/srv/svn/webcoper,65 echo `whoami`,$REPOS,$REV >> $LOG_PATH #echo $changed >> $LOG_PATH php -q /srv/svn/xing/hooks/svn_post_commit_resources.php "$changed" "$SVN_USER" "$SVN_PASS" "$WEB_USER" "$LOG_PATH" "$WEB_PATH" "$SVN_PATH"
这里是svn_post_commit_resources.php文件
<?php
// var_dump($argv[1]);
$files = explode ( "\n", $argv [1] );
$web_path = $argv [6];
if (! is_array ( $files )) {
$files = ( array ) $files;
}
foreach ( $files as $v ) {
//判断更新类型,删除D不做svn更新操作并删除对应文件标志位true
preg_match('/^D\s{3}/', $v, $matches);
$action_type=count($matches)>0?true:false;
error_log ( ($action_type?"delete ":"change ").": $v \n", 3, $argv [5] );
// 取文件名chapter.php
$f_tem = trim ( substr ( $v, 2 ) );
$localpath=$web_path.$f_tem;
// 是否带有目录
$is_dir = strrpos ( $f_tem, '/' );
$d_tem = substr ( $f_tem, 0, $is_dir ? $is_dir + 1 : strlen ( $f_tem ) );
// 排除的目录
/*
* if (!in_array($d_tem, array('web', 'framework', 'conf', 'shell'))) {
* continue;
* }
*/
// to更新到该目录
$t_name = $web_path . ($is_dir?$d_tem:'');
error_log ( "to :$t_name \n", 3, $argv [5] );
// form将要下载的文件
$f_name = $svn_path . $f_tem;
error_log ( "from :$f_name \n", 3, $argv [5] );
// chown $WEB_USER.$WEB_USER -R $WEB_PATH
$cmd = "/usr/bin/svn export '$f_name' '$t_name' --force --username '$argv[2]' --password '$argv[3]' --no-auth-cache >> '$argv[5]';chown '$argv[4]'.'$argv[4]' '$web_path$f_tem'";
$logcmd="/usr/bin/svn export '$f_name' '$t_name' --force --username '$argv[2]' --password ****** --no-auth-cache >> '$argv[5]';chown '$argv[4]'.'$argv[4]' '$web_path$f_tem'";
error_log ( "cmd :$logcmd \n", 3, $argv [5] );
// 判断目录是否存在
if (! is_readable ( $t_name ) ) {
is_file ( $t_name ) or mkdir ( $t_name, 0755 ,true);
//chown($path, $user_name);
exec ( "chown '$argv[4]'.'$argv[4]' '$t_name'" );
error_log ( "creat :$t_name \n", 3, $argv [5] );
}
if(!$action_type){
exec ( $cmd );
}else{
//删除操作
if(is_dir($localpath))
unlinkDir($localpath);
else
unlinkFile($localpath);
error_log ( "delete :$localpath \n", 3, $argv [5] );
}
// 配置更新重启相关服务
/*
* if (strpos($f_tem, 'nginx.conf')) {
* exec("kill -HUP `cat /dev/shm/nginx.pid`");
* }
*/
}
function unlinkDir($aimDir) {
$aimDir = str_replace('', '/', $aimDir);
$aimDir = substr($aimDir, -1) == '/' ? $aimDir : $aimDir . '/';
if (!is_dir($aimDir)) {
return false;
}
$dirHandle = opendir($aimDir);
while (false !== ($file = readdir($dirHandle))) {
if ($file == '.' || $file == '..') {
continue;
}
if (!is_dir($aimDir . $file)) {
unlinkFile($aimDir . $file);
} else {
unlinkDir($aimDir . $file);
}
}
closedir($dirHandle);
return rmdir($aimDir);
}
function unlinkFile($aimUrl) {
if (file_exists($aimUrl)) {
unlink($aimUrl);
return true;
} else {
return false;
}
}
exit ();
?>
如果出现:post-commit hook failed (exit code 255) with no output的错误,请检查post-commit权限+x,简单粗暴chmod 777 post-commit,哈哈