svn更新自动发布网站

原理:在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

  

#!/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的目录都不会被同步 
View Code
  方式一会在网站根目录留下.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=$'
'

#日志输出角色、资源路径、版本号 	
#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 ( " ", $argv [1] ); $web_path = $argv [6]; if (! is_array ( $files )) { $files = ( array ) $files; } foreach ( $files as $v ) { //判断更新类型,删除D不做svn更新操作并删除对应文件标志位true preg_match('/^Ds{3}/', $v, $matches); $action_type=count($matches)>0?true:false; error_log ( ($action_type?"delete ":"change ").": $v ", 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 ", 3, $argv [5] ); // form将要下载的文件 $f_name = $svn_path . $f_tem; error_log ( "from :$f_name ", 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 ", 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 ", 3, $argv [5] ); } if(!$action_type){ exec ( $cmd ); }else{ //删除操作 if(is_dir($localpath)) unlinkDir($localpath); else unlinkFile($localpath); error_log ( "delete :$localpath ", 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,哈哈

原文地址:https://www.cnblogs.com/perfectzhang/p/5528857.html