需求介绍
以前php代码文件从本机更新到2.11测试环境的流程是这样的:
1.1 本地修改代码
1.2 用svn提交到branch分支
1.3 将提交的文件列表发送给主管
1.4 主管手动将文件列表中的文件从branch覆盖到trunk
1.5 主管提交trunk
现在,由echo.zhang 同学开发了网页版更新到trunk分支的系统, 登陆下方的网址,
http://to.be.published
在文本框中输入需要提交到2.11环境(即trunk分支)的文件列表,点击提交,就会自动完成 上面的 1.3, 1.4, 1.5 三个过程
实现机制
//背景说明: 我们本地提交代码到branch分支的过程中,会经过echo.zhang同学的代码检测系统进行安全检查,同时,提交成功后,会把我们的提交的文件清单保存到一个单独的数据库中
在网页的文件清单输入框中,输入我们要更新到2.11环境的文件清单, 点击提交时,后台的controller 执行以下逻辑:
3.1 收集用户提交的文件清单,
3.2 将用户提交的文件清单,逐一在branch分支的数据库中进行查找, 如果清单中的文件在branch分支的数据库中存在,则表示该文件为修改操作; 如果在数据库中不存在,则表示该文件为删除操作(需从trunk分支的磁盘上删除)
3.3. 根据提交的文件清单,从branch分支的数据库中找到这些文件在branch分支的磁盘路径, 并解析出这些文件对应的trunk分支的磁盘路径
3.4 若文件为修改操作,则将branch分支中的文件使用copy命令覆盖到trunk分支的磁盘上; 若文件为删除操作, 则将trunk分支的磁盘文件unlink掉
3.5 至此,磁盘上的branch分支和trunk分支的文件已经相同; 这时,根据提交的文件清单,整理出trunk分支需要提交的svn文件列表,调用socket 服务, 将trunk分支要提交的文件列表作为参数发送给 socket服务脚本
3.6 socket服务脚本接收待提交的文件列表,
使用 svn —add new_files -m “comment” 添加新文件到trunk分支的svn服务器
再使用 svn —commit all_files -m “comment” 提交所有更新到trunk分支的svn服务器
3.7 socket服务脚本返回 svn命令的执行结果给3.5
3.8 根据3.7中的返回值,提示用户提交成功或者失败
之所以需要使用socket的方式来执行svn命令, 是因为3.1~3.4中的代码是在controller文件中完成的,controller脚本的的调用者是apache或nginx , 用户角色是www,而非root
而www用户是没有权限执行 svn命令的,因此,我们 另写一个socket服务器脚本,在命令行中的方式去执行该服务脚本,该脚本即具有了root权限
A. 客户端脚本代码, 如 svnFileController::submitAction()
客户端
//注: 这里的客户端,指提供网页版更新文件的web服务器, 是svn的socket命令的请求方
error_reporting(E_ALL);
$host = ‘192.168.3.244’; //socket服务器的ip地址
$port = 10000; //socket服务器提供的端口号
$socket = socket_create ( AF_INET, SOCK_STREAM, SOL_TCP ) or die( “Could not create socket\n” ); // 创建一个Socket
socket_connect ( $socket, $host, $port ) or die( “Could not connet server\n” ); // 连接
//$command 为命令行命令 ,前一部分如( ‘ipconfig /all’ 等)为需要在cmd中执行的命令,
//后一部分( ‘2>&1’ ) 是一个shell命令, 用于将错误信息(stderr)重定向到标准输出(stdout)中,而非显示在终端屏幕上. ( 其中 2>表示错误信息重定向, &1 表示输出到标准输出中)
$command = “ipconfig 2>&1”;
// 向服务器发送消息,消息的内容即为我们要执行的命令
socket_write ( $socket, $command ) or die( “Write failed\n” );
echo “—— socket started ———
“;
$allresponse = ‘’; //该变量保存服务器返回的消息(消息的类型是字符串)
while( $response_buffer = @socket_read ( $socket, 128, PHP_NORMAL_READ ) ){ //每次从socket中读取 128个字符,直到socket中已经没有内容了(所谓的没有内容了,实质上是指读取时遇到到了 ‘\n’ 的字符.该字符为socket默认的结束符)
if ( $response_buffer ) {
$allresponse .= $response_buffer;
}
}
echo “—— response_from_server :
“;
//此处我在服务器端将消息设置成了一个json格式的字符串 ,格式为 [code => ‘’ ,msg => array() ]
$responseArr = json_decode ( $allresponse, TRUE );
var_dump ( $responseArr );
echo “
—— socket finished ———“;
socket_close ( $socket ); //记得关闭socket连接哦
die;
B. 服务器端脚本,打开命令行,键入 $~ php server_svn_socket.php 来运行
服务器端 $value) {$exec_result[$key] = mb_convert_encoding($value, ‘utf-8’, ‘GBK’);}$responseArr[‘code’] = $code;$responseArr[‘msg’] = $exec_result;return json_encode($responseArr);}?>
客户端实例图:
服务器端实例图: