问题1:发布代码这种事,开发嫌慢,运维嫌烦,策划和测试狂催,如果开发直接提交svn后线上代码也是最新的就大家都不用烦了.
问题2:小公司电脑少,svn只有一个,永远不够用啊,各种文件和代码堆堆堆,时间一长就连自己也不知道放哪里了,如果一台机有多个svn目录独立控制,那就简单了.
我相信上面两个问题在大部分公司都存在,代码发布和文件管理是任何公司都有的核心功能,当然了,有的公司技术强大,用高大上git必须比svn好用,不过大部分还是svn为主,要解决上面两个问题,那就看下面了.
先来看看原理图:
问题一的解决方案
问题的关键就在钩子脚本,一会看一下详细的.
问题二的解决方案
问题的关键就是利用apache多域控制多端口,不同的端口指向不同的svn数据库,这样就可以做到单机多svn目录.
下面来说怎么安装和配置整套应用
1.安装应用
说到安装方法,那当然是yum最简单,呵呵~!我也就不纠结太多了,纠结编译安装的,可以看着下面的软件逐个去弄,这真的不是问题,编译参数我在附录贴一下.
顺便说说,我是在centos7.2安装的,所以按道理是通用的了.
#安装依赖包 yum install -y Python pyOpenSSL zlib* apr* swig* neon* #安装libiconv,这个yum不了,只能编译,但是也很简单就是了 wget "http://ftp.gnu.org/pub/gnu/libiconv/libiconv-1.14.tar.gz" tar xf libiconv-1.14.tar.gz cd libiconv-1.14 ./configure --prefix=/usr/local/libiconv make make install #安装apache服务 yum install -y httpd #安装svn服务和httpd模块 yum install -y subversion mod_dav_svn
这个就安装完了,如果硬要编译的话,嗯~!那可是一长串,我表示不太喜欢,反正这些需求都是内部的,能用就行,性能都不是重点.
2.配置apache和关联svn
理论上apache安装完就能用,但是这个并不是重点,他和svn两者要配合使用,那必然是有关联的地方,而因为是yum安装的,http的conf目录在/etc下面,
先配置apache的基本配置,
#创建运行用户,注意不要创建/sbin/nologin的用户使用在apache+svn上,因为会导致钩子脚本无法使用 groupadd www useradd www -g www #修改httpd.conf,里面东西太多,只说几个重点 vim /etc/httpd/conf/httpd.conf #配置端口,默认80,你喜欢改什么都可以,不冲突就行 Listen 8001 #运行用户和用户组,你创什么就用什么,要保证是可以运行脚本的权限/bin/bash User www Group www
然后其他默认就可以了.
然后配置两者关联的相关配置配置
#配置subversion.conf文件如下内容 vim /etc/httpd/conf.modules.d/10-subversion.conf LoadModule dav_svn_module modules/mod_dav_svn.so LoadModule authz_svn_module modules/mod_authz_svn.so LoadModule dontdothat_module modules/mod_dontdothat.so <Location /svn> Dav svn SVNListParentPath on #----允许在网页上显示svn父目录list --记住,注释不要和配置项写到同一行,否则会出错.. SVNParentPath "/data/svn" AuthType Basic #----连接框提示 AuthName "Subversion Repository" #----用户密码配置文件 AuthUserFile /etc/svn/passwd #----用户权限配置文件 AuthzSVNAccessFile /etc/svn/authz #----限制登录配置,可细化到只允许那个IP登录,这里注释了,暂时不使用 # Order Allow,Deny # Allow from 127.0.0.1 # Allow from {任何IP类型} # Deny from All Require valid-user </Location> #可以再加一个Location来实现多svn仓库,类似这样 #<Location /svn2> #中间省略... #</Location>
再然后修改一些权限的问题和启动apache
#修改数据仓库目录/data/svn权限(后面用到) chown www:www -R /data/svn chmod 777 -R /data/svn #关闭SELinux setenforce 0 #重启apache服务 service httpd restart
这样apache部分就完毕了
3.创建svn数据仓库
首先要强调,svn的数据仓库和我们认知的checkout出来的svn文件目录不同,svn的数据仓库他是经过编码的二进制文件,不能直接解析,和我们能直接操作的svn文件夹是两回事,我们提交和下载的文件都是经过编码解析的,大家心里要又这个概念.
下面来看操作
#创建仓库目录 mkdir -p /data/svn/test_1 #创建svn仓库 svnadmin create /data/svn/test_1 #配置改仓库的配置文件 vim /data/svn/test_1/conf/svnserve.conf #禁用匿名用户并开启验证用户权限。 anon-access = none auth-access = write
4.创建svn用户
还记得关联svn时apache配置的用户认证相关目录么,没错,是/etc/svn,另外,因为用了apache,所以用户的密码不再是传统svn的明文保存,需要通过htpasswd来加密配置,所以要独立开来讲讲
#进入目录 cd /etc/svn #使用htpasswd创建用户,首次创建用户会建立新文件,删除旧文件,前面是用户,后面是密码 htpasswd -cb passwd test 123 #添加/修改用户 htpasswd -b passwd new-user new-password #删除用户 htpasswd -D passwd new-user
然后相关的用户名和密码就会加密保存在/etc/svn/passwd里面,有兴趣的可以看一下文件内容,是密文存储的.
5.配置svn权限
和密码认证文件一样的位置,主要要注意的地方是他分为组权限,不同的组可以有不同的权限,没规定什么名字,可以细化到目录,其实也就只分读和写两个权限,
#编辑authz文件,设置guest组包含test和abc两个用户,devl组aaa和bbb两个用户。 vim /etc/svn/authz [groups] guest = test,abc devl = aaa,bbb #配置组权限,设置根目录下guest组为可读写,其他用户为可读。 [/] @guest = rw * = r #设置test_1目录下devl组为可读,其他没权限 [test_1:/] @g_developer = r * = #设置test_1目录下tags文件夹devl组为可读写,其他没权限 [test_1:/tags] @g_developer = rw * =
权限配置就这么完毕了,然后,并不需要启动svn程序,就可以使用的了,因为apache会调用插件,不需要svn程序额外启动,相当方便,减少一个程序占用内存.
6.创建钩子脚本
关于钩子脚本的用途,就是说在提交/更新/删除各种场景发生前后执行的脚本的意思,是svn自带的功能,非常方便,这也是自动发布代码的关键所在.
svn也自带一些模板,就在数据仓库目录里面
ll /data/svn/test_1/hooks/ -rw-r--r-- 1 www www 1977 9月 13 10:33 post-commit.tmpl -rw-r--r-- 1 www www 1638 9月 13 10:33 post-lock.tmpl -rw-r--r-- 1 www www 2289 9月 13 10:33 post-revprop-change.tmpl -rw-r--r-- 1 www www 1567 9月 13 10:33 post-unlock.tmpl -rw-r--r-- 1 www www 3426 9月 13 10:33 pre-commit.tmpl -rw-r--r-- 1 www www 2434 9月 13 10:33 pre-lock.tmpl -rw-r--r-- 1 www www 2786 9月 13 10:33 pre-revprop-change.tmpl -rw-r--r-- 1 www www 2122 9月 13 10:33 pre-unlock.tmpl -rw-r--r-- 1 www www 2780 9月 13 10:33 start-commit.tmpl
有心研究的可以慢慢研究,下面这个就是提交后执行的那个脚本post-commit,只要有提交动做,这个脚本就会执行.
#创建或修改post-commit,成功提交后执行的钩子 vim /data/svn/test_1/hooks/post-commit #!/bin/bash SVN=/usr/bin/svn LOG=/var/log/svnup-houtai.log wwwurl=/data/htdocs/ export LANG=zh_CN.UTF-8 export PATH cat $LOG >> ${LOG}.bak echo "" > $LOG echo `date` >> $LOG echo "##############################" >> $LOG cd ${wwwurl};$SVN co --username test --password '123' http://192.168.1.86:8001/svn/test_1 www >> $LOG echo "##############################" >> $LOG wait
=========================================
升级版钩子脚本,远程checkout,要预先使用ssh-keygen做好免密码登录
#!/bin/bash SVN=/usr/bin/svn LOG=/var/log/svnup-newips.log export LANG=zh_CN.UTF-8 export PATH cat $LOG >> ${LOG}.bak echo "" > $LOG echo `date` >> $LOG echo "##############################" >> $LOG commend="$SVN co --username test --password '123' http://192.168.1.86:8001/svn/newips /data/htdocs/www " auto_scp() { ip=10.29.66.55 PORT=22 expect<<EOF set timeout 1200 spawn ssh -q -o StrictHostKeyChecking=no ${ip} -l root -p ${PORT} expect -- "*~]#*" send -- "${commend}\r" expect -- "*~]#*" send -- "exit\r" expect eof EOF } auto_scp >>$LOG echo "##############################" >> $LOG wait
===========================================
重点解析下,注意空格分割
SVN co --username test --password '123' http://192.168.1.86:8001/svn/test www
svn是命令,co是更新数据的意思,username就是用户,password就是密码,http后面那串就是svn地址,最后的www意思是创建并更新到什么目录的意思,例如我的代码是放在/data/htdocs的www目录,如果有就更新,如果没就创建了再更新.
所以这句的意思就是把svn仓库的文件更新到/data/htdocs/www代码目录里面,你的代码目录如果叫app,那最后的www就可以改成app.
而这个目录要是一开始就配置成nginx等web系统的php或者java代码目录的话,那么只要你提交svn代码,通过钩子脚本的运行,你的代码目录也会同时更新,也就是我开头说的---代码直接发布系统.
然后还没完,因为这个是要apache执行的,而apache的执行用户是www,所以要做脚本运行就要操作这一步
#设置post-commit执行权限,不然会报错的 chmod 777 /data/svn/test_1/hooks/post-commit #切换用户执行下脚本,如果不执行,可能钩子也是不生效的,因为有应答提醒 su - www /data/svn/test_1/hooks/post-commit 上一次登录:二 9月 13 12:01:08 CST 2016pts/0 上 ----------------------------------------------------------------------- 注意! 你的密码,对于认证域: <http://192.168.1.86:8001> Subversion Repository 只能明文保存在磁盘上! 如果可能的话,请考虑配置你的系统,让 Subversion 可以保存加密后的密码。请参阅文档以获得详细信息。 你可以通过在“/home/www/.subversion/servers”中设置选项“store-plaintext-passwords”为“yes”或“no”, 来避免再次出现此警告。 ----------------------------------------------------------------------- 保存未加密的密码(yes/no)?yes ll /data/svn/test_1/hooks/post-commit 总用量 40 -rwxrwxrwx 1 www www 416 9月 13 12:07 post-commit
然后,你的就可以用了
有些时候,我们的svn要求必须有做注释,方便翻(zhao)查(ren)数(bei)据(guo),所以就有了第二个脚本,强制提交时输入注释:
#这个是要求在提交时触发的钩子,当然就不是原本那个文件了 vim /data/svn/test_1/hooks/pre-commit #!/bin/bash REPOS="$1" TXN="$2" SVNLOOK=/usr/bin/svnlook LOGMSG=$($SVNLOOK log -t "$TXN" "$REPOS" | grep "[a-zA-Z0-9]" | wc -c) if [ "$LOGMSG" -lt 3 ]; then echo -e "\n 提交文件时必须添加注释,提交中止."1>&2 exit 1 fi #别忘记切换用户执行以下,和上面一样操作就可以了, su - www /data/svn/test_1/hooks/pre-commit
其中注意,
LOGMSG=$($SVNLOOK log -t "$TXN" "$REPOS" | grep "[a-zA-Z0-9]" | wc -c)
是统计这个注释有多少个字母和数字的字符总数量的意思.中文不能被统计,所以要注意注释的格式,
if [ "$LOGMSG" -lt 3 ]; then
是限制输入字数的意思,这里是至少3个字符的意思可以更多,也可以更少,大家看自己偏好.
7.测试
其实钩子脚本里面也有地址测试,不过也可以自己测试,无论是windows还是linux都用这个地址http://192.168.1.86:8001/svn/test_1
svn co http://192.168.1.86:8001/svn/test_1 /data/htdocs/www --username=test --password=123
windows的怎么测我就不多说了,就是界面而已.
8.备份/还原svn数据仓库
这个算是个基本需求吧,不过我觉得一定情况来说其实有点鸡肋,一般来说svn都是很多人一起用,每个人电脑里面的文件就是一个备份,还特地去备份和还原就有点多此一举的感觉,除非说这个svn数据非常多,重新上传超级费时间,或者说非常在意svn存放的注释记录和版本记录,那倒是说得过去,上面纯属个人简介,下面转回正题.
备份的方式现在有三种,其实有很多同类文章了,我也就不想详细介绍了,
1)svnadmin dump
2)svnadmin hotcopy
3)svnsync.
第三种除了特定场景几乎没人用,也很少例子,第二种在以前资源紧张的旧服务器倒是有优势,现在也是没什么优势了,先看第一种.
#第一种方法备份命令,详细参数请看下面 svnadmin dump /data/svn/[你的svn目录] --deltas > test-svn-7.dump 2>/dev/null #参数说明: -r [--revision]: 指定备份的版本号(或X:Y范围) --incremental: 以增量方式进行转存 --deltas: 使用压缩,消耗更多cpu资源 -q [--quiet]: 在标准错误输出不显示进度(仅错误) #备份完了还想加大压缩比,那就在tar一下吧, tar zcf test-svn-7.tar.gz test-svn-7.dump
然后来看第二种
#第二种方法备份命令,其实也等于直接拷贝 svnadmin hotcopy /data/svn/[你的svn目录] /root/[目的备份svn目录] #这个文件夹肯定是和原本的一样大,所以你更加需要压缩 tar zcf test-svn-7.tar.gz /root/test-svn
然后,就看怎么恢复了,第二种方式就不用说了,都是一个完整目录了,直接改配置文件或者复制到相关http目录就完全能用起来了,主要来看第一种,
#第一种方式恢复命令,先创建一个新的版本库 svnadmin create /svn/project/test1 #先还原完全备份, svnadmin load /svn/project/test1 < test-svn-7.dump #如果有做增量备份,再还原增量备份的内容 svnadmin load /svn/project/test1 < svn.bak.1
这样就完成了备份和恢复了.
9.搭建用户密码自助修改功能
如果大家用起来,就会发现这个svn的账户密码,必须管理员来添加和修改.其实不算很方便,然而创建密码用的工具htpasswd本身是具有加密功能的,单纯用脚本调用修改又变得很麻烦,网上很多同类的文章也都是忽略了加密算法问题,造成实现不了的情况,我也是翻查了很多资料,然后分析了脚本得出这个结果.
那要怎么办呢?经过分析和权衡利弊,总算找到一个姑且能算是解决的方法,不过有一个大坑,而这个坑的解决方案,就得看有没有高手去破解算法了,我暂时是没有办法的了.
好了,转回正题,我们用的方法,其实就是cgi方法的变种,网上一搜一大堆的ChangePasswd.cgi,不过如果你按他们的方法做,一般情况下是失败的,也就是因为我说的算法问题,这个cgi的perl脚本里的crypt函数的算法和htpasswd的算法是不一样的,所以无论你怎么改,都会提示旧密码错误.不过从另一方面来说也有好的一面,密码那么容易被破解,那这个加密算法还真是失败透了.
先来看ChangePasswd.ini,只是个配置文件了,记得给读的权限啊
#打开 vim ChangePasswd.ini [path] authuserfile=/etc/svn/passwd logfile=/var/www/cgi-bin/ChangePasswd.log [setup] pwdminlen=6 [html] title=SVN用户密码自助修改 description=SVN用户密码自助修改 yourname=用户名 oldpwd=旧密码 newpwd1=新密码 newpwd2=确认新密码 btn_change=修 改 btn_reset=重 置 changepwdok=成功修改密码 changepwdfailed=修改密码失败 servererror=服务器错误 passmustgreater=新密码位数必须大于 twopassnotmatched=两密码不一致 entername=请输入用户名 enterpwd=密码未输入 errorpwd=你的密码不正确 back=返回
需要改的只有两个地方,authuserfile就是你svn密码存放文件,logfile就是你日志的文件了,通常你保证能读写就好了.
再看重点的ChangePasswd.cgi,这个就是执行文件,要给执行权限
#!/usr/bin/perl -w use strict; use CGI; my $time = localtime; my $remote_id = $ENV{REMOTE_HOST} || $ENV{REMOTE_ADDR}; my $admin_email = $ENV{SERVER_ADMIN}; my $cgi = new CGI; my $pwd_not_alldiginal = "密码不能全为数字"; my $pwd_not_allchar = "密码不能全为字符"; my $user_not_exists ="该用户不存在"; my $file_not_found ="文件不存在,请联系管理员"; my $authuserfile; my $logfile; my $pwdminlen; my $title; my $description; my $yourname; my $oldpwd; my $newpwd1; my $newpwd2; my $btn_change; my $btn_reset; my $changepwdok; my $changepwdfailed; my $oldpwderror; my $passmustgreater; my $twopassnotmatched; my $entername; my $enterpwd; my $errorpwd; my $back; &IniInfo; if ($cgi -> param()) {#8 my $User = $cgi->param('UserName'); my $UserPwd = $cgi->param('OldPwd'); my $UserNewPwd = $cgi->param('NewPwd1'); my $MatchNewPwd = $cgi->param('NewPwd2'); if (!$User) {&Writer_Log("Enter no user name"); &otherhtml($title,$entername,$back);} elsif (!$UserPwd ) {&Writer_Log("Enter no OldPasswd"); &otherhtml($title,$enterpwd,$back); } elsif (length($UserNewPwd)<$pwdminlen) {&Writer_Log("Password's length must greater than".$pwdminlen); &otherhtml($title,$passmustgreater.$pwdminlen,$back);} elsif ($UserNewPwd =~/^\d+$/) {&Writer_Log("New Passwd isn't all diginal"); &otherhtml($title,$pwd_not_alldiginal,$back);} elsif ($UserNewPwd =~/^[A-Za-z]+$/) {&Writer_Log("New Passwd isn't all char"); &otherhtml($title,$pwd_not_allchar,$back);} elsif ($UserNewPwd ne $MatchNewPwd) {&Writer_Log("Two new passwords are not matched"); &otherhtml($title,$twopassnotmatched,$back);} else {if($authuserfile) {#6 open UserFile, "<$authuserfile" or die "打开文件失败:$!"; while (<UserFile>) {#5 my $varstr=$_; if($varstr =~/($User)/) {#3 my $eqpos =index($varstr, ":"); my $UserName = substr($varstr,0,$eqpos); my $cryptpwd = substr($varstr,$eqpos + 1,13); next if($UserName ne $User); # if(crypt($UserPwd,$cryptpwd) eq $cryptpwd) if(crypt($UserPwd,$cryptpwd) ne $cryptpwd) {#a my $rc = system("/usr/bin/htpasswd -b $authuserfile $User $UserNewPwd"); if ($rc == 0) {#1 &Writer_Log( $User.":Change Passwd"); &otherhtml($title,$changepwdok,$back); }#1 else {#2 &Writer_Log( $User.":Change Passwd Failed"); &otherhtml($title,$changepwdfailed,$back); }#2 exit; }#a else {#b &Writer_Log("Old Passwd is Incorrect "); &otherhtml($title,$errorpwd,$back); }#b exit; }#3 else {#4 if(eof) { &Writer_Log($User.":no this user"); &otherhtml($title,$user_not_exists,$back); exit; } else {next;} }#4 }#5 close UserFile; }#6 else {#7 &Writer_Log($authuserfile.":no found"); &otherhtml($title,$file_not_found,$back); }#7 } }#8 else {&Index_Html;} sub IniInfo{ my $inifile = "/var/www/cgi-bin/ChangePasswd.ini"; open CGI_INI_FILE, "<$inifile" or die "打开文件失败:$!";; while (<CGI_INI_FILE>) { my $eqpos =index($_,'='); my $len = length($_); if ($_ =~/authuserfile/) {$authuserfile= substr($_, $eqpos + 1, $len - $eqpos -2);} elsif ($_ =~/logfile/) {$logfile= substr($_, $eqpos + 1);} elsif ($_ =~/pwdminlen/) {$pwdminlen= substr($_, $eqpos + 1);} elsif ($_ =~/title/) {$title = substr($_, $eqpos + 1);} elsif ($_ =~/description/) {$description = substr($_, $eqpos + 1);} elsif ($_ =~/yourname/) {$yourname = substr($_, $eqpos + 1);} elsif ($_ =~/oldpwd/) {$oldpwd= substr($_, $eqpos + 1);} elsif ($_ =~/newpwd1/) {$newpwd1= substr($_, $eqpos + 1);} elsif ($_ =~/newpwd2/) {$newpwd2= substr($_, $eqpos + 1);} elsif ($_ =~/btn_change/) {$btn_change = substr($_, $eqpos + 1);} elsif ($_ =~/btn_reset/) {$btn_reset = substr($_, $eqpos + 1);} elsif ($_ =~/changepwdok/) {$changepwdok = substr($_, $eqpos + 1);} elsif ($_ =~/changepwdfailed/) {$changepwdfailed = substr($_, $eqpos + 1);} elsif ($_ =~/oldpwderror/) {$oldpwderror = substr($_, $eqpos + 1);} elsif ($_ =~/passmustgreater/) {$passmustgreater = substr($_, $eqpos + 1);} elsif ($_ =~/twopassnotmatched/) {$twopassnotmatched = substr($_, $eqpos + 1);} elsif ($_ =~/entername/) {$entername = substr($_, $eqpos + 1);} elsif ($_ =~/enterpwd/) {$enterpwd= substr($_, $eqpos + 1);} elsif ($_ =~/errorpwd/) {$errorpwd= substr($_, $eqpos + 1);} elsif ($_ =~/back/) {$back = substr($_, $eqpos + 1);} } close CGI_INI_FILE; } sub Index_Html{ print "Content-type: text/html\n\n"; print <<END_OF_PAGE; <html > <head> <title>$title</title> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> </head> <body> <HR> <center><h1>$description</h1> </center> <form method="POST" enctype="multipart/form-data" action="/cgi-bin/ChangePasswd.cgi"> <br> <TABLE align="center"> <TR><TD class="t_text">$yourname</TD><TD><input type="text" name="UserName" /></TD></TR> <TR><TD class="t_text">$oldpwd</TD><TD><input type="password" name="OldPwd" /></TD></TR> <TR><TD class="t_text">$newpwd1</TD><TD><input type="password" name="NewPwd1" /></TD></TR> <TR><TD class="t_text">$newpwd2</TD><TD><input type="password" name="NewPwd2" /></TD></TR> </TABLE> <br> <TABLE align="center"> <TR><TD><input type="submit" name="chgpasswd" value="$btn_change"> <input type="reset" value="$btn_reset"></TD></TR> </TABLE> </form> <HR> <font color="#FF0000">注意:新密码位数必需大于$pwdminlen,且为字母与数字组合</font> </body> </html> END_OF_PAGE } sub otherhtml{ print "Content-type: text/html\n\n"; print <<END_OF_PAGE; <html> <head> <meta http-equiv="Content-Language" content="zh-cn"> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>$_[0]</title> </head> <body> <p align="center"><font size="5">$_[1]</font></p> <p align="center"><a href="/cgi-bin/ChangePasswd.cgi"><font size="4">$_[2]</font></a></p> <HR> </body> </html> END_OF_PAGE } sub Writer_Log{ if($logfile) { my $loginfo ="[".$time."] "." [".$remote_id."] "." || ".$_[0]; open LOGFILE,">>$logfile" or die "Couldn't open LOG FILE for writing: $!"; print LOGFILE ("$loginfo\n"); close LOGFILE; } }
这个脚本其实和网上的相差不大,只是我改了一个地方,把本来不成立的判断变成了成立,所以就没了我开始说的算法不一致导致不能用的问题.重点就在这里:
# if(crypt($UserPwd,$cryptpwd) eq $cryptpwd) if(crypt($UserPwd,$cryptpwd) ne $cryptpwd)
原本是求crypt函数结果和用htpasswd加密的结果相等,那才会更改密码,但是事实上两者是恒定不等的,因为算法不一样,所以就造成永远用不了的问题,后来我想,既然他们不相等,那就干脆把相等的条件改成不等吧.不过,隐患还是很明显,这样做的话,就算乱输一个密码,也是能把密码改掉,这样做就很危险了,其他人只要知道账号,那就随便把密码改了,所以说是一个大坑了,期待有大牛能解决这个问题.
虽然伴随着大坑的到来,但是功能终究是能实现的,只要控制得当,限制修改密码的时间或者配置apache的条件,我觉得还是有搞头的,所以就这么上马了.
好了,然后继续下面的步骤,把这两个文件,放到apache的默认cgi代码目录,并创建刚才的log文件
#放到这个目录 ll /var/www/cgi-bin/ total 24 -rwxrwxrwx 1 www www 6342 Mar 24 19:24 ChangePasswd.cgi* -rwxrwxrwx 1 www www 566 Mar 24 17:54 ChangePasswd.ini* -rwxrwxrwx 1 www www 365 Mar 25 10:49 ChangePasswd.log* #因为是perl脚本,还需要安装一个perl插件,不然可能报错 yum install -y perl-CGI #重载apache service apache2 reload
一般来说,如果你是用centos的yum安装的话,就直接能用了,默认是加载cgi插件的,不过可能没有perl的插件而已,yum一下也是可以的了.
不过如果你是ubuntu或者其他安装的话,apache未必是加载cgi插件的,所以就要多下面这些步骤了
#假设是ubuntu,也是先安装perl插件,不过名字不一样 apt-get install -y libapache2-mod-perl2 #然后,创建一个连接,并且让他加载cgi.pl vim /etc/apache2/mods-enabled/alias.conf Alias /cgi-bin/ "/var/www/cgi-bin/" <Directory "/var/www/cgi-bin/"> AddType application/x-httpd-php .php AddHandler cgi-script .pl AddHandler cgi-script .cgi Options ExecCGI DirectoryIndex index.html AllowOverride none Order allow,deny Allow from all </Directory> #重载apache service apache2 reload
然后,就可以用了,访问地址
http://'svn地址'/cgi-bin/ChangePasswd.cgi
就能出现界面了