分享下使用svn或者git时,测试服务器代码自动更新、线上服务器代码手动更新的配置经验

本篇不是长篇大论服务器的架设,只是谈与svn或者git相关的内容。

首先说下自己的思路,每个开发人员将代码提交到svn服务器的时候,触发post-commit钩子,使得代码自动更新到测试服务器,在测试服务器上查看代码上线后是否OK。如果没问题,则对与测试服务器环境完全一致的线上服务器的代码进行手动更新。手动更新的方式为通过web访问,web访问一个php脚本,php脚本去执行shell命令来更新。

如果我们每次都是对线上服务器做ssh连接,然后执行svn up的命令实在有点儿浪费时间。而且不是所有人都权限去访问线上服务器,如果所有人更新代码都要一个人去更新,更是麻烦。而且,笔者现在的实际开发环境中,线上服务器只对外开放了一个80端口,想连ssh,还得先连自己搭建的vpn。所以我们最好是能直接通过web端进行更新。

代码github地址 https://github.com/zhoumengkang/svn-hook-to-remote-server

下面说下实现的代码的详细解释:

首先是svn服务器上的钩子post-commit代码

  1. #!/bin/sh
  2. export LANG="zh_CN.UTF-8"
  3. #更新到远程的服务器
  4. #/home/wwwroot/xxx/svn.php 为svn.php在svn服务器上的存放地址
  5. /usr/local/php/bin/php /home/wwwroot/xxx/svn.php

这里是在post-commit里面执行一个php脚本。下面看这个脚本(svn.php)的代码:

  1. /**
  2. * svn钩子post-commit里执行的文件
  3. * 存放在svn服务器上
  4. */
  5. $updateUrl = "http://test.mengkang.net/update.php";//远程测试服务器上的update.php的地址
  6. $ch = curl_init();
  7. curl_setopt($ch, CURLOPT_URL, $updateUrl);
  8. curl_setopt($ch, CURLOPT_HEADER, 0);
  9. curl_exec($ch);
  10. curl_close($ch);

在这个脚本里是使用的curl去模拟访问了测试服务器上的URLhttp://test.mengkang.net/update.php 

  1. /**
  2. * svn服务器上的钩子需要模拟访问的文件,必须是外网可以访问的
  3. * 存放在远程服务器上
  4. * @author zhoumengkang <i@zhoumengkang.com>
  5. */
  6. error_reporting(E_ALL);
  7.  
  8. //"/home/wwwroot/test/" 为代码更新到的指定目录路径
  9. putenv("LC_CTYPE=zh_CN.UTF-8");//有时候字符集会很坑爹,所以设置环境变量还是很有必要的
  10. $handle = popen('svn up /home/wwwroot/test/ --username zmk --password 123456 2>&1','r');
  11. //echo "'$handle'; " . gettype($handle) . "\n";
  12. $read = stream_get_contents($handle);
  13. //TODO 如果在$read中可以匹配到“error/conflict”,就应该发送邮件到管理员的邮箱了!
  14. echo $read;
  15. pclose($handle);

稍微做点安全判断扩展版

  1. <?php
  2. header("Cache-Control:no-cache,must-revalidate");
  3. //首先判断ip是否合法
  4. if(!preg_match('/123\.123\.123\.[0-9]+/', $_SERVER['REMOTE_ADDR']){
  5. //可以给管理员发送邮件
  6. die('ip不合法');
  7. }
  8. ?>
  9. <form action="" method="post">
  10. <input type="password" name="password" id="password" value="">
  11. <input type="submit" value="提交" onclick="storePassword();">
  12. <script type="text/javascript">
  13. //自动填充密码
  14. function setValue(){
  15. var passwordInput = document.getElementById('password');
  16. passwordInput.value = getcookie('svnupdate');
  17. }
  18. window.onload=setValue;
  19.  
  20. //存储密码
  21. function storePassword(){
  22. var passwordInputValue = document.getElementById('password').value;
  23. if(getcookie('svnupdate') != passwordInputValue){
  24. setcookie('svnupdate',passwordInputValue,365);
  25. }
  26. }
  27.  
  28. //Cookie操作函数
  29. function setcookie(name,value,days){
  30. if("undefined" == typeof(days)){
  31. days = 30;
  32. }else{
  33. days = parseInt(days);
  34. }
  35. var exp = new Date();
  36. exp.setTime(exp.getTime() + days*24*60*60*1000);
  37. document.cookie = name + "="+ value + ";expires=" + exp.toGMTString();
  38. }
  39. function getcookie(name){
  40. var arr = document.cookie.match(new RegExp("(^| )"+name+"=([^;]*)(;|$)"));
  41. if(arr != null){
  42. return (arr[2]);
  43. }else{
  44. return "";
  45. }
  46. }
  47. </script>
  48. </form>
  49. <?php
  50. if($_POST['password'] !='123456'){
  51. die('密码错误');
  52. }
  53. putenv("LC_CTYPE=zh_CN.UTF-8");
  54. $handle = popen('svn up /test --username zmk --password 123456 2>&1', 'r');
  55. $read = stream_get_contents($handle);
  56. echo "<pre>";
  57. printf($read);
  58. echo "

";

  • pclose($handle);

这样就实现了测试服务器的自动更新,线上服务器则通过访问http://mengkang.net/update.php来手动更新代码。

代码以演示为主,大家可以在脚本中添加svn更新出错发送邮件等扩展功能。

别忘了这些代码是建立在svn搭建完毕之后,测试服务器和线上服务器都做了一次检出之上的。

线上服务器的update.php代码与测试服务器上的代码相似,可以做一些安全防护措施,比如加一个限定和密码输入。

在上面这些代码都部署完毕之后,可能会因为各种权限问题,导致不能正常自动更新,你可以update.php页面,那上面输出各种错误的原因。

在svn 1.6 以后的版本之后,当然执行svn up的时候会默认提示是否需要保存密码,需要修改下配置文件才可能跳过这步。

假设你的svn的配置文件在这/home/www/.subversion/servers请编辑下它,全局密码保存配置修改为如下规则

  1. [global]
  2. store-passwords = yes
  3. store-plaintext-passwords = no

具体资料可以参考我的旧博客:http://www.mengkang.net/blog/post/373.html

不管是测试服务器还是线上服务器都应该拒绝对所有.svn目录的访问。

  1. location ~ ^(.*)\/\.svn\/{
  2. deny all;
  3. }

类似的,如果测试服务器在外网必须设置为只有开发人员的ip才能访问。

下面简单说下github上的webhook的使用

原理和svn的相似,只不过github在git的基础上封装了更加方便的webhook,这其中传递了一个json格式的数据到webhook端供调用!

比如所属者,最新提交者,提交时间等等,如果你想好好利用其中的数据,可以参考 https://developer.github.com/webhooks/

这里简单实现自动更新,代码如下:

  1. error_reporting ( E_ALL );
  2. $dir = '/data/test/';//该目录为git检出目录
  3. $handle = popen('cd '.$dir.' && git pull 2>&1','r');
  4. $read = stream_get_contents($handle);
  5. //TODO 如果在$read中可以匹配到“error:”,就应该发送邮件到管理员的邮箱了!
  6. printf($read);
  7. pclose($handle);

参考资料:

https://wiki.lib.umn.edu/Subversion/ClientConfiguration.html

https://github.com/blog/1778-webhooks-level-up

http://stackoverflow.com/questions/21870660

http://blog.s135.com/

本文由 黑白世界4648 第一时间收藏到GET,原文来自 → mengkang.net

「GetParty」

关注微信号,推送好文章

微信中长按图片即可关注

更多精选文章

评论
微博一键登入