SVN是Subversion的简称,是一个开放源代码的版本控制系统,可以超越时间的管理文件和目录。文件保存在中央版本库,除了能记住文件和目录的每次修改以外,版本库非常像普通的文件服务器。你可以将文件恢复到过去的版本,并且可以通过检查历史知道数据做了哪些修改,谁做的修改。这就是为什么许多人将 Subversion 和版本控制系统看作一种“时间机器”。说得简单一点SVN就是用于多个人共同开发同一个项目,共用资源的目的。
svn与git的区别
svn
svn版本控制系统是集中式的数据管理,存在一个中央版本库。所有开发人员本地开发使用的代码都是来自这个版本库,提交代码也都必须提交到这个中央版本库。
svn工作流程:
1、在中央版本库中创建一个项目,项目中包含主干和分支,分支是从主干复制的;
2、开发人员从中央版本库check out下这个分支的代码;
3、增加自己的代码、修改或删除现存的代码;
4、commit 代码,如果修改期间其他人提交了代码,就会提示过期无法提交,就需要先up,之后再提交;如果up代码时出现冲突,就需要解决冲突之后在提交(开发人员协商解决冲突);
5、测试环境测试,解决问题之后合并到主干中,在之后更新生产环境代码;
缺点:
1、严重依赖网络环境,连接不到中央版本库时无法工作;
2、需要备份-------->需要备份数据和修改的历史记录
git
git是分布式版本控制系统,没有中央版本库的说法,和svn不同的是,开发者本地有一个完整的git仓库,但是实际使用中需要建立一个远程的git仓库,以方便共享代码和版本控制;
git工作流程:
1、本地创建一个git库,并将其add到远程git库中;
2、在本地添加、删除、修改文件,然后commit,此时commit是提交到本地git仓库中;
3、将本地git库分支push到远程git库的分支,如果此时远程已经有别人push过,那远程git将不允许你push,必须先pull。并解决冲突之后才能在push到远程git库;
优点:
1、开发时不依赖网络,随时commit到本地,和随时查看修改历史,只有在合并代码时才需要连接远程git仓库;
2、svn还是主流,git正在发展,将来会成为主流,都掌握会更好;
svn运维人员需要掌握的程度:
1、安装、部署、维护、排障;
2、简单使用,很多公司都是有开发来管理,包括建立仓库和添加删除账号。
3、对于版本控制系统---->运维相当于开发商,开发人员是业主,运维搭建的系统为开发人员服务。
svn之运行方式和访问方式:
服务端运行方式:
1、独立服务器访问:(svn://svn.etiantian.org/www/)
2、和apache等http服务结合:(http://svn.etiantian.org/www/)
a、单独安装apache+svn;
b、csvn()是一个整合好的一体软件,带有web管理页面的svn软件;
3、本地直接访问:(file://application/data/www/)
客户端访问方式:
访问方式 说明
file:// 直接访问本地磁盘或网络磁盘访问版本库
http:// 通过webdav协议访问支持subversion的apache服务器
https:// 与http://类似,只是用了ssl加密访问
svn:// 通过TCP/IP自定义协议访问subversion服务器
svn+ssh:// 通过认证并加密的TCP/IP自定义协议访问subversion服务器
SVN中的一些概念 :
(1). repository(源代码库)
源代码统一存放的地方
(2). Checkout (提取)
当你手上没有源代码的时候,你需要从repository checkout一份
(3). Commit (提交)
当你已经修改了代码,你就需要Commit到repository
(4). Update (更新)
当你已经Checkout了一份源代码, Update一下你就可以和Repository上的源代码同步,你手上的代码就会有最新的变更。
安装配置SVN服务:
[root@moban ~]# cat /etc/redhat-release
CentOS release 6.8 (Final)
[root@moban ~]# uname -r
2.6.32-642.el6.x86_64
[root@moban ~]# rpm -qa subversion
[root@moban ~]# yum -y install subversion
[root@moban ~]# sed -i 's/keepcache=0/keepcache=1/g' /etc/yum.conf
[root@moban ~]# grep "keepcache" /etc/yum.conf
keepcache=1 //rpm包下载安装后不清除
[root@moban ~]# mkdir -p /application/svndata <==数据存储的根目录
[root@moban ~]# mkdir -p /application/svnpasswd <==用户及密码和权限目录
[root@moban ~]# svn
svn svnlook svnversion
svnadmin svnserve
svndumpfilter svnsync
[root@moban ~]# svnserve --help
usage: svnserve [-d | -i | -t | -X] [options]
Valid options:
-d [--daemon] //以守护进程的方式运行 : daemon mode
-r [--root] ARG //指定存储的根目录 : root of directory to serve
其它剩余参数省略。。。。。。
[root@moban ~]# svnserve -d -r /application/svndata/ #启动SVN服务并指定数据存储的根目录
[root@moban ~]# ps -ef| grep svn|grep -v grep
root 8554 1 0 23:48 ? 00:00:00 svnserve -d -r /application/svndata/
[root@moban ~]# netstat -tunlp|grep svn
tcp 0 0 0.0.0.0:3690 0.0.0.0:* LISTEN 8554/svnserve
[root@moban ~]# lsof -i:3690
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
svnserve 8554 root 3u IPv4 20242 0t0 TCP *:svn (LISTEN)
创建项目版本库:
[root@moban ~]# svnadmin --help
general usage: svnadmin SUBCOMMAND REPOS_PATH [ARGS & OPTIONS ...]
Type 'svnadmin help <subcommand>' for help on a specific subcommand.
Type 'svnadmin --version' to see the program version and FS modules.
Available subcommands:
crashtest
create
deltify
dump
help (?, h)
hotcopy
list-dblogs
list-unused-dblogs
load
lslocks
lstxns
pack
recover
rmlocks
rmtxns
setlog
setrevprop
setuuid
upgrade
verify
[root@moban ~]# svnadmin help create
create: usage: svnadmin create REPOS_PATH
Create a new, empty repository at REPOS_PATH.
Valid options:
--bdb-txn-nosync : disable fsync at transaction commit [Berkeley DB]
--bdb-log-keep : disable automatic log file removal [Berkeley DB]
--config-dir ARG : read user configuration files from directory ARG
--fs-type ARG : type of repository: 'fsfs' (default) or 'bdb'
--pre-1.4-compatible : use format compatible with Subversion versions
earlier than 1.4
--pre-1.5-compatible : use format compatible with Subversion versions
earlier than 1.5
--pre-1.6-compatible : use format compatible with Subversion versions
earlier than 1.6
[root@moban ~]# svnadmin create /application/svndata/sadoc
[root@moban ~]# ll /application/svndata/
total 4
drwxr-xr-x. 6 root root 4096 Oct 26 23:58 sadoc
[root@moban ~]# tree /application/svndata/
/application/svndata/
└── sadoc
├── conf
│ ├── authz
│ ├── passwd
│ └── svnserve.conf
├── db
│ ├── current
│ ├── format
│ ├── fsfs.conf
│ ├── fs-type
│ ├── min-unpacked-rev
│ ├── rep-cache.db
│ ├── revprops
│ │ └── 0
│ │ └── 0
│ ├── revs
│ │ └── 0
│ │ └── 0
│ ├── transactions
│ ├── txn-current
│ ├── txn-current-lock
│ ├── txn-protorevs
│ ├── uuid
│ └── write-lock
├── format
├── hooks
│ ├── post-commit.tmpl
│ ├── post-lock.tmpl
│ ├── post-revprop-change.tmpl
│ ├── post-unlock.tmpl
│ ├── pre-commit.tmpl
│ ├── pre-lock.tmpl
│ ├── pre-revprop-change.tmpl
│ ├── pre-unlock.tmpl
│ └── start-commit.tmpl
├── locks
│ ├── db.lock
│ └── db-logs.lock
└── README.txt
调整svn配置文件及权限文件:
[root@moban ~]# cd /application/svndata/sadoc/conf/
[root@moban conf]# cp svnserve.conf svnserve.conf.bak
[root@moban conf]# grep "^[a-Z]" /application/svndata/sadoc/conf/svnserve.conf
anon-access = none
auth-access = write
password-db = /application/svnpasswd/passwd
authz-db = /application/svnpasswd/authz
[root@moban conf]# diff svnserve.conf.bak svnserve.conf
12,13c12,13
< # anon-access = read //匿名用户访问权限
< # auth-access = write //认证用户访问权限
---
> anon-access = none
> auth-access = write
20c20
< # password-db = passwd //密码认证文件
---
> password-db = /application/svnpasswd/passwd
27c27
< # authz-db = authz
---
> authz-db = /application/svnpasswd/authz //权限配置数据文件
[root@moban conf]# egrep "\-access|\-db =" svnserve.conf
anon-access = none
auth-access = write
password-db = /application/svnpasswd/passwd
authz-db = /application/svnpasswd/authz
[root@moban conf]# ls
authz passwd svnserve.conf svnserve.conf.bak
[root@moban conf]# cp authz passwd /application/svnpasswd/
[root@moban conf]# ll /application/svnpasswd/
total 8
-rw-r--r--. 1 root root 1080 Oct 27 00:29 authz
-rw-r--r--. 1 root root 309 Oct 27 00:29 passwd
[root@moban conf]# cd /application/svnpasswd/
[root@moban svnpasswd]# ll
total 8
-rw-r--r--. 1 root root 1080 Oct 27 00:29 authz
-rw-r--r--. 1 root root 309 Oct 27 00:29 passwd
[root@moban svnpasswd]# chmod 700 * //修改密码文件(passwd)、权限配置文件(authz)的文件权限为700,提高安全。安全无小事,但是,重视的运维却少的可怜。
[root@moban svnpasswd]# ll
total 8
-rwx------. 1 root root 1080 Oct 27 00:29 authz
-rwx------. 1 root root 309 Oct 27 00:29 passwd
[root@moban svnpasswd]# vi passwd
[users]
# harry = harryssecret
# sally = sallyssecret
linuxzkq = 123456 //添加用户与密码,注意必须在[users]标签下添加。
guest = guest //添加用户与密码,等号前面是用户名,后面是密码。
提示:更改svnserve.conf文件时,需要重启svn,更改passwd、authz文件时不需要重启。
[root@moban svnpasswd]# vi authz
在最下面添加配置权限如下:
[groups]
linux = linuxzkq,guest //定义用户组及所包含的用户,其中,1个用户组可以包含1个或多个用户,用户间以逗号分隔。
[sadoc:/]
linuxzkq = rw //用户访问权限
guest = r
@linux = r //用户组访问权限
* = //* = 表示,除了linuxzkq、guest用户、linux用户组,任何人都被禁止访问版本库
注意:
权限配置文件中出现的用户名必须已在用户配置文件中定义。
用户组格式:
[groups]
= ,
其中,1个用户组可以包含1个或多个用户,用户间以逗号分隔。
版本库目录格式:
[<版本库>:/项目/目录]
@<用户组名> = <权限>
<用户名> = <权限>
其中,方框号内部分可以有多种写法:
[/],表示根目录及以下,根目录是svnserve启动时指定的,[/]就是表示对全部版本库设置权限。
权限主体可以是用户组、用户或*,用户组在前面加@
权限可以是w、r、wr和空,空表示没有任何权限。
重启svn命令<非必需>:
kill -USR1 `cat /application/svndata/svn.pid`
svnserve -d -r /application/svndata/ --pid-file=/application/svndata/svn.pid
[root@moban svnpasswd]# pkill svnserve
[root@moban svnpasswd]# svnserve -d -r /application/svndata/ --pid-file=/application/svndata/svn.pid
客户端软件windows安装使用:
windows 64位的话下载:TortoiseSVN-1.7.6.22632-x64-svn-1.7.4.msi
windows 32位的话下载:TortoiseSVN-1.6.5.16974-win32-svn-1.6.5.msi
具体的下载文件可以在网上下载下,一找一大堆
通过客户端进行访问,地址如下:
svn://{your-server-ip}/sadoc
用户名:guest
密码:guest
linux下Svn客户端命令的使用:
[root@moban ~]# svn --help
usage: svn <subcommand> [options] [args]
Subversion command-line client, version 1.6.11.
Type 'svn help <subcommand>' for help on a specific subcommand.
Type 'svn --version' to see the program version and RA modules
or 'svn --version --quiet' to see just the version number.
Most subcommands take file and/or directory arguments, recursing
on the directories. If no arguments are supplied to such a command, it recurses on the current directory (inclusive) by default.
Available subcommands:
add
blame (praise, annotate, ann)
cat
changelist (cl)
checkout (co) //从源码库提取一个工作版本的拷贝,常用的
cleanup
commit (ci) //提交当前工作拷贝的更改。这个地方是有可能出现代码冲突的。常用的
copy (cp) //做一个工作拷贝的拷贝
delete (del, remove, rm) //删除本地或者svn server response上的文件或目录
diff (di) //比较某个文件与库中的对应文件的不同,类似于系统的diff命令。
export //导出一个无版本控制的目录树拷贝。一般用于导出发行,或者投入运行的版本
help (?, h)
import //将本地当前目录下的文件导入到svn response中。
info //当前目录工作拷贝中某文件信息,如URL,版本,修改日期等。
list (ls) //列出当前工作拷贝下的文件,相当于系统ls命令。
lock
log
merge //将两个来源之间的差异应用到工作拷贝路径。
mergeinfo
mkdir //在本地或者svn reponse上新建一个文件夹。
move (mv, rename, ren)
propdel (pdel, pd)
propedit (pedit, pe)
propget (pget, pg)
proplist (plist, pl)
propset (pset, ps)
resolve
resolved
revert
status (stat, st) //svn工作拷贝当前状态,与svn server上的源码比较的结果。
switch (sw)
unlock
update (up) //将svn server端文件同步到本地,常用的。
Subversion is a tool for version control.
For additional information, see http://subversion.tigris.org/
[root@c6 ~]# mkdir /svndata
[root@c6 ~]# svn co svn://192.168.0.111/sadoc/ /svndata/ --username=guest --password=guest
-----------------------------------------------------------------------
ATTENTION! Your password for authentication realm:
<svn://192.168.0.111:3690> 10073e1b-bf6e-4d4c-b01f-1358a1a9a561
can only be stored to disk unencrypted! You are advised to configure
your system so that Subversion can store passwords encrypted, if
possible. See the documentation for details.
You can avoid future appearances of this warning by setting the value
of the 'store-plaintext-passwords' option to either 'yes' or 'no' in
'/root/.subversion/servers'.
-----------------------------------------------------------------------
Store password unencrypted (yes/no)? yes
A /svndata/22.txt
Checked out revision 1.
Checked out revision 1.
[root@c6 ~]# ll /svndata/
total 0
-rw-r--r--. 1 root root 0 Oct 27 23:41 22.txt
[root@c6 ~]# svn up svn://192.168.0.111/sadoc/ /svndata/ --username=guest --password=guest
Skipped 'svn://192.168.0.111/sadoc'
A /svndata/33.bmp
Updated to revision 2.
Summary of conflicts:
Skipped paths: 1
[root@c6 ~]# ll /svndata/
total 0
-rw-r--r--. 1 root root 0 Oct 27 23:41 22.txt
-rw-r--r--. 1 root root 0 Oct 27 23:49 33.bmp
[root@c6 ~]# svn up svn://192.168.0.111/sadoc/ /svndata/ --username=guest --password=guest
Skipped 'svn://192.168.0.111/sadoc'
A /svndata/22
Updated to revision 3.
Summary of conflicts:
Skipped paths: 1
[root@c6 ~]# ll /svndata/
total 4
drwxr-xr-x. 3 root root 4096 Oct 27 23:51 22
-rw-r--r--. 1 root root 0 Oct 27 23:41 22.txt
-rw-r--r--. 1 root root 0 Oct 27 23:49 33.bmp
[root@c6 ~]# svn co svn://192.168.0.111/sadoc/ /svndata/ --username=guest --password=guest
A /svndata/666.txt
Checked out revision 4.
[root@c6 ~]# ll /svndata/
total 4
drwxr-xr-x. 3 root root 4096 Oct 27 23:51 22
-rw-r--r--. 1 root root 0 Oct 27 23:41 22.txt
-rw-r--r--. 1 root root 0 Oct 27 23:49 33.bmp
-rw-r--r--. 1 root root 0 Oct 27 23:53 666.txt
[root@moban ~]# svn co file:///application/svndata/sadoc //在服务端本地以文件的方式访问提取,文件提取只适用于服务端本地访问。
A sadoc/666.txt
A sadoc/22.txt
A sadoc/33.bmp
A sadoc/22
Checked out revision 4.
[root@c6 ~]# svn list svn://192.168.0.111/sadoc
22/
22.txt
33.bmp
666.txt
新建文本文档 (2).txt
新建文本文档.txt
[root@c6 ~]# touch /svndata/{a..d}
[root@c6 ~]# cd /svndata/
[root@c6 ~]# touch /svndata/{a..d}
[root@c6 svndata]# svn add a b c d e f g
A a
A b
A c
A d
svn: warning: 'e' not found
svn: warning: 'f' not found
svn: warning: 'g' not found
[root@c6 svndata]# svn ci -m "svn ci data" /svndata/ --username=linuxzkq --password=123456
-----------------------------------------------------------------------
ATTENTION! Your password for authentication realm:
<svn://192.168.0.111:3690> 10073e1b-bf6e-4d4c-b01f-1358a1a9a561
can only be stored to disk unencrypted! You are advised to configure
your system so that Subversion can store passwords encrypted, if
possible. See the documentation for details.
You can avoid future appearances of this warning by setting the value
of the 'store-plaintext-passwords' option to either 'yes' or 'no' in
'/root/.subversion/servers'.
-----------------------------------------------------------------------
Store password unencrypted (yes/no)? yes
Adding a
Adding b
Adding c
Adding d
Transmitting file data ....
Committed revision 7.
[root@c6 svndata]# svn ci -m "svn ci data" /svndata/
Adding {rr..tt}.txt
Transmitting file data .
Committed revision 8.
[root@c6 svndata]# svn list svn://192.168.0.111/sadoc
22/
22.txt
33.bmp
666.txt
a
b
c
d
{rr..tt}.txt
新建文本文档 (2).txt
新建文本文档.txt
[root@c6 svndata]# svn up svn://192.168.0.111/sadoc /svndata
Skipped 'svn://192.168.0.111/sadoc'
D /svndata/新建文本文档 (2).txt
A /svndata/新建 Microsoft Excel 工作表.xlsx
Updated to revision 9.
Summary of conflicts:
Skipped paths: 1
[root@c6 svndata]# ll
total 12
drwxr-xr-x. 3 root root 4096 Oct 28 00:40 22
-rw-r--r--. 1 root root 0 Oct 27 23:41 22.txt
-rw-r--r--. 1 root root 0 Oct 27 23:49 33.bmp
-rw-r--r--. 1 root root 0 Oct 27 23:53 666.txt
-rw-r--r--. 1 root root 0 Oct 28 00:35 a
-rw-r--r--. 1 root root 0 Oct 28 00:35 b
-rw-r--r--. 1 root root 0 Oct 28 00:35 c
-rw-r--r--. 1 root root 0 Oct 28 00:35 d
-rw-r--r--. 1 root root 0 Oct 28 00:45 {rr..tt}.txt
-rw-r--r--. 1 root root 6327 Oct 28 00:54 新建 Microsoft Excel 工作表.xlsx
-rw-r--r--. 1 root root 0 Oct 28 00:03 新建文本文档.txt
[root@c6 svndata]# svn up svn://192.168.0.111/sadoc /svndata
Skipped 'svn://192.168.0.111/sadoc'
D /svndata/22
D /svndata/新建 Microsoft Excel 工作表.xlsx
D /svndata/{rr..tt}.txt
A /svndata/888l.xlsx
Updated to revision 10.
Summary of conflicts:
Skipped paths: 1
[root@c6 svndata]# svn up /svndata
D /svndata/新建文本文档.txt
A /svndata/777.txt
Updated to revision 11.
[root@c6 svndata]# ll
total 8
-rw-r--r--. 1 root root 0 Oct 27 23:41 22.txt
-rw-r--r--. 1 root root 0 Oct 27 23:49 33.bmp
-rw-r--r--. 1 root root 0 Oct 27 23:53 666.txt
-rw-r--r--. 1 root root 0 Oct 28 00:58 777.txt
-rw-r--r--. 1 root root 6327 Oct 28 00:56 888l.xlsx
-rw-r--r--. 1 root root 0 Oct 28 00:35 a
-rw-r--r--. 1 root root 0 Oct 28 00:35 b
-rw-r--r--. 1 root root 0 Oct 28 00:35 c
-rw-r--r--. 1 root root 0 Oct 28 00:35 d
[root@c6 svndata]# svn help copy
copy (cp): Duplicate something in working copy or repository, remembering
history.
usage: copy SRC[@REV]... DST
When copying multiple sources, they will be added as children of DST,
which must be a directory.
SRC and DST can each be either a working copy (WC) path or URL:
WC -> WC: copy and schedule for addition (with history)
WC -> URL: immediately commit a copy of WC to URL
URL -> WC: check out URL into WC, schedule for addition
URL -> URL: complete server-side copy; used to branch and tag
All the SRCs must be of the same type.
WARNING: For compatibility with previous versions of Subversion,
copies performed using two working copy paths (WC -> WC) will not
contact the repository. As such, they may not, by default, be able
to propagate merge tracking information from the source of the copy
to the destination.
Valid options:
-r [--revision] ARG : ARG (some commands also take ARG1:ARG2 range)
A revision argument can be one of:
NUMBER revision number
'{' DATE '}' revision at start of the date
'HEAD' latest in repository
'BASE' base rev of item's working copy
'COMMITTED' last commit at or before BASE
'PREV' revision just before COMMITTED
-q [--quiet] : print nothing, or only summary information
--ignore-externals : ignore externals definitions
--parents : make intermediate directories
-m [--message] ARG : specify log message ARG
-F [--file] ARG : read log message from file ARG
--force-log : force validity of log message source
--editor-cmd ARG : use ARG as external editor
--encoding ARG : treat value as being in charset encoding ARG
--with-revprop ARG : set revision property ARG in new revision
using the name[=value] format
Global options:
--username ARG : specify a username ARG
--password ARG : specify a password ARG
--no-auth-cache : do not cache authentication tokens
--non-interactive : do no interactive prompting
--trust-server-cert : accept unknown SSL server certificates without
prompting (but only with '--non-interactive')
--config-dir ARG : read user configuration files from directory ARG
--config-option ARG : set user configuration option in the format:
FILE:SECTION:OPTION=[VALUE]
For example:
servers:global:http-library=serf
svn钩子:
钩子脚本的具体写法就是操作系统中shell脚本程序的写法,可根据自己的SVN所在的操作系统和shell程序进行相应的开发。
钩子脚本就是被某些版本库事件触发的程序,例如:创建新版本或修改未被版本控制的属性。每个钩子都能掌管足够的信息来了解发生了什么事件,操作对像是什么以及触发事件用户的账号。类似inotify或sersync。
通过钩子的输出或返回状态,钩子程序能让该动作继续执行、停止或是以某种方式挂起。
默认情况下,钩子的子目录中包含各种版本库钩子模板。如下:
[root@moban ~]# tree /application/svndata/sadoc/hooks/
/application/svndata/sadoc/hooks/
├── post-commit.tmpl //提交的
├── post-lock.tmpl //上(加)锁的
├── post-revprop-change.tmpl
├── post-unlock.tmpl //解锁的
├── pre-commit.tmpl //预提交的
├── pre-lock.tmpl //预上锁的
├── pre-revprop-change.tmpl
├── pre-unlock.tmpl //预解锁的
└── start-commit.tmpl //开始提交的
0 directories, 9 files
对每种Subversion版本库支持的钩子都有一个模板,通过查看这些脚本的内容,你能看到是什么事件触发了脚本及如何传脚本,传递数据。
要实际安装一个可用的钩子,你需要在 repos/hooks目录下安装一些与钩子同名(如 start-commit或者post-commit)的可执行程序或脚本。注意:去掉模板的扩展名。
重要提示:
由于安全原因,Subversion版本库在一个空环境中执行钩子脚本—就是没有任何环境变量,甚至没有$PATH或%PATH%。由于这个原因,许多管理员会感到很困惑,它们的钩子脚本手工运行时正常,可在Subversion中却不能运行。要注意,必须在你的钩子中设置好环境变量或为你的程序指定好绝对径。
常用钩子脚本:
1.post-commit
在提交成功完成、创建版本之后执行该钩子,提交已经完成,不可更改。因此,本脚本的返回值被忽略。提交完成时触发事务。
2.pre-commit
提交完成前触发执行该脚本。
3.start-commit
在客户端还没有向服务器提交数据之前,即还没有建立Subversion transaction(缩写为txn)之前,执行该脚本(提交前触发事务)
svn钩子生产应用场景举例:
pre-commit
1.限制上传文件扩展名及大小,控制提交要输入的信息等。
post-commit
2.SVN更新自动通知,MSN,邮件或短信通知。
3.SVN更新触发checkout程序,然后实时rsync推送到服务器等。
svn钩子生产应用实战:
一、rsync与svn钩子结合实现数据实时同步(某企业小案例)
1.建立同步web目录
mkdir /data/www
[root@c6 ~]# mkdir /data/www -p
[root@c6 ~]# ll /data/www/
total 0
2.将SVN中内容checkout到web目录一份。
[root@c6 ~]# svn co svn://192.168.0.111/sadoc /data/www --username=guest --password=guest
-----------------------------------------------------------------------
ATTENTION! Your password for authentication realm:
<svn://192.168.0.111:3690> 10073e1b-bf6e-4d4c-b01f-1358a1a9a561
can only be stored to disk unencrypted! You are advised to configure
your system so that Subversion can store passwords encrypted, if
possible. See the documentation for details.
You can avoid future appearances of this warning by setting the value
of the 'store-plaintext-passwords' option to either 'yes' or 'no' in
'/root/.subversion/servers'.
-----------------------------------------------------------------------
Store password unencrypted (yes/no)? yes
A /data/www/666.txt
A /data/www/888l.xlsx
A /data/www/a
A /data/www/22.txt
A /data/www/b
A /data/www/33.bmp
A /data/www/777.txt
A /data/www/c
A /data/www/d
Checked out revision 11.
[root@c6 ~]# ll /data/www
total 8
-rw-r--r--. 1 root root 0 Oct 28 08:28 22.txt
-rw-r--r--. 1 root root 0 Oct 28 08:28 33.bmp
-rw-r--r--. 1 root root 0 Oct 28 08:28 666.txt
-rw-r--r--. 1 root root 0 Oct 28 08:28 777.txt
-rw-r--r--. 1 root root 6327 Oct 28 08:28 888l.xlsx
-rw-r--r--. 1 root root 0 Oct 28 08:28 a
-rw-r--r--. 1 root root 0 Oct 28 08:28 b
-rw-r--r--. 1 root root 0 Oct 28 08:28 c
-rw-r--r--. 1 root root 0 Oct 28 08:28 d
3.利用钩子同步程序到远程服务器
[root@moban ~]# cd /application/svndata/sadoc/hooks
[root@moban hooks]# cp post-commit.tmpl post-commit
[root@moban hooks]# mv post-commit post-commit.ori
[root@moban hooks]# vi post-commit
创建svn钩子脚本(post-commit):
#!/bin/sh
#设定环境变量,如果没有设定可能会出现update报错
export LC_CTYPE="en_US.UTF-8"
export LC_ALL=
REPOS="$1"
REV="$2"
SVN_PATH="/usr/bin/svn"
WEB_PATH="/data/www"
LOG_PATH="/app/log"
RSYNC_PATH="/usr/bin/rsync"
#/usr/bin/svn update --username user --password password $WEB_PATH --no-auth-cache
#echo "\n##############开始提交" `date "+%Y-%m-%d %H:%M:%S"` '##################' >>$LOG_PATH
#echo `whoami`,$REPOS,$REV >>$LOG_PATH
[ ! -d ${LOG_PATH} ] && mkdir ${LOG_PATH} -p
#update content from svn
$SVN_PATH update --username linuxzkq --password 123456 $WEB_PATH >>$LOG_PATH/up_$(date +%F_%H:%M:%S).log 2>&1
if [ $? -eq 0 ]
then
$RSYNC_PATH -az --delete $WEB_PATH /tmp/
fi
[root@moban hooks]# chmod 700 post-commit
[root@moban hooks]# ll /tmp
total 0
-rw-------. 1 root root 0 Oct 26 21:56 yum.log
[root@moban hooks]# ll /tmp/www
total 16
-rw-r--r--. 1 root root 0 Oct 27 13:45 100.txt
-rw-r--r--. 1 root root 0 Oct 27 13:28 123.bmp
-rw-r--r--. 1 root root 6327 Oct 27 13:45 200.xlsx
-rw-r--r--. 1 root root 0 Oct 27 13:28 22.txt
-rw-r--r--. 1 root root 0 Oct 27 13:36 55.txt
-rw-r--r--. 1 root root 0 Oct 27 13:36 66.bmp
-rw-r--r--. 1 root root 0 Oct 27 13:34 7.txt
-rw-r--r--. 1 root root 0 Oct 27 13:42 8888.bmp
写svn钩子脚本的一些注意事项:
1.钩子脚本的权限要允许svn执行,一般可以设置chmod 700 post-commit。
2.写钩子脚本时要尽可能定义环境变量,主要是用过的命令的全路径。因为svn考虑安全问题,不会调用系统环境变量,所以如果发现手动执行post-commit没有问题,但SVN自动执行也可能会无法执行。
3.老男孩老师提供的案例脚本,在SVN update之前一定要先手动checkout一份出来,还有尽可能要加上用户名和密码,如果只是手动一样会更新,但自动触发可能就不能更新了。
4.加上了对前一个命令的判断,如果update的时候出了问题,程序没有退出的话还会继续同步代码到WEB服务器上,这样会造成代码有问题。
5.记得要设置所属用户,因为rsync可以同步文件属性,而且我们的WEB服务器一般都不是root用户,用户不正确会造成WEB程序无法正常工作。
6.建议最好记录日志,出错的时候可以很快的排错。
7.最后最关键的数据同步,rsync的相关参数一定要清楚,这个就不说了。注意几个场景:
场景一、如果目的WEB服务器为综合的混杂的,像只有一个WEB静态资源,用户提交的,自动生成的都在WEB的一个目录下,建议不要用--delete这个参数
上面这个程序就是这样,实现的是源服务器到目的服务器的更新和添加,而没有删除操作,WEB服务器的内容会多于源SVN的服务器的
场景二、实现镜像,即目的WEB服务器与源SVN服务器一样的数据,SVN上任何变化WEB上一样的变化,就需要--delete参数
场景三、不需要同步某些子目录,可能有些目录是缓存的临时垃圾目录,或者是专用的图片目录(而不是样式或者排版的)要用exclude这个参数
注意:这个参数的使用不用写绝对路径,只要目录名称就行 aa代表文件 aa/ 代表目录 ,缺点就是如果有多个子目录都是一样的名称 那么这些名称就都不会被同步
建议用--exclude-from=/home/svn/exclude.list 用文件的形式可以方便的添加和删除
exclude.list
利用SVN的钩子还可以写出很多的程序来控制SVN 如代码提交前查看是否有写日志,是否有tab,有将换成空格,是否有不允许上传的文件,是否有超过限制大小的文件等等。
最重要的是看帮助,如看post-commit默认的帮助
[root@moban hooks]# more post-commit.tmpl
#!/bin/sh
# POST-COMMIT HOOK
#
# The post-commit hook is invoked after a commit. Subversion runs
# this hook by invoking a program (script, executable, binary, etc.)
# named 'post-commit' (for which this file is a template) with the
# following ordered arguments:
#
# [1] REPOS-PATH (the path to this repository)
# [2] REV (the number of the revision just committed)
#
# The default working directory for the invocation is undefined, so
# the program should set one explicitly if it cares.
#
# Because the commit has already completed and cannot be undone,
# the exit code of the hook program is ignored. The hook program
# can use the 'svnlook' utility to help it examine the
# newly-committed tree.
#
# On a Unix system, the normal procedure is to have 'post-commit'
# invoke other programs to do the real work, though it may do the
# work itself too.
#
# Note that 'post-commit' must be executable by the user(s) who will
# invoke it (typically the user httpd runs as), and that user must
# have filesystem-level permission to access the repository.
#
# On a Windows system, you should name the hook program
# 'post-commit.bat' or 'post-commit.exe',
# but the basic idea is the same.
#
# The hook program typically does not inherit the environment of
# its parent process. For example, a common problem is for the
# PATH environment variable to not be set to its usual value, so
# that subprograms fail to launch unless invoked via absolute path.
# If you're having unexpected problems with a hook program, the
# culprit may be unusual (or missing) environment variables.
#
# Here is an example hook script, for a Unix /bin/sh interpreter.
# For more examples and pre-written hooks, see those in
# the Subversion repository at
# http://svn.apache.org/repos/asf/subversion/trunk/tools/hook-scripts/ and
# http://svn.apache.org/repos/asf/subversion/trunk/contrib/hook-scripts/
二、利用pre-commit限制上传文件扩展名及大小
参考:
http://blog.chinaunix.net/uid-22646981-id-2921564.html
http://blog.chinaunix.net/uid-22646981-id-2921557.html
[root@moban ~]# svnlook --help
general usage: svnlook SUBCOMMAND REPOS_PATH [ARGS & OPTIONS ...]
Note: any subcommand which takes the '--revision' and '--transaction'
options will, if invoked without one of those options, act on
the repository's youngest revision.
Type 'svnlook help <subcommand>' for help on a specific subcommand.
Type 'svnlook --version' to see the program version and FS modules.
Available subcommands:
author
cat
changed
date
diff
dirs-changed
help (?, h)
history
info
lock
log
propget (pget, pg)
proplist (plist, pl)
tree
uuid
youngest
[root@moban ~]# svnlook help log
log: usage: svnlook log REPOS_PATH
Print the log message.
Valid options:
-r [--revision] ARG : specify revision number ARG
-t [--transaction] ARG : specify transaction name ARG
[root@moban ~]# cd /application/svndata/sadoc/hooks/
[root@moban hooks]# vi pre-commit
#!/bin/sh
REPOS="$1"
TXN="$2"
#此处更改大小限制,为5M
MAX_SIZE=5242880
#此处限制文件后缀名
FILTER='\.(zip|rar|o|obj|tar|gz)$'
# Make sure that the log message contains some text.
SVNLOOK=/usr/bin/svnlook
######svnlook log/cat
#svn提交时有个参数 -m 用来记录提交信息,下面这一段是为了验证提交信息长度(规范操作嘛,否则svn里真的是一堆垃圾了)
#LOGMSG=`$SVNLOOK log -t "$TXN" "$REPOS"|grep "[a-zA-Z0-9]"|wc -c`
LOGMSG=`$SVNLOOK log -t "$TXN" "$REPOS"|wc -c`
if [ "$LOGMSG" -lt 9 ];
then
echo -e "Log message cann't be empty! you must input more than 8 chars as comment!" 1>&2
exit 1
fi
files=$($SVNLOOK changed -t "$TXN" "$REPOS"|cut -d " " -f 4-)
#echo "$files">&2
#echo "$r">&2
#exit 1
rc=0
echo "$files"|while read f;
do
#check file type
if echo $f|tr A-Z a-z|grep -Eq $FILTER;
then
echo "File $f is not allow ($FILTER) file" 1>&2
exit 1;
fi
#check file size
filesize=`$SVNLOOK cat -t "$TXN" "$REPOS" "$f"|wc -c`
if [ "$filesize" -gt "$MAX_SIZE" ];
then
echo "File $f is too large(must <=$MAX_SIZE) Byte" 1>&2
exit 1
fi
done
#All checks passed,so allow the commit.
if [ $? -eq 1 ];
then
exit 1
else
exit 0
fi
[root@moban hooks]# chmod 700 pre-commit
大中小型企业上线解决方案:
SVN目录组织结构说明
trunk <==主线(分支),与正式线相对应,当天不上线文件不允许提交。
branches <==分支,为测试时使用,几天以上的项目必须开分支,测试需要本分支通过,主线合并到分支通过,才能合并到主线进行测试。
tags <==版本记录用
SVN上线解决方案说明:
1.小型公司代码上线案例(通过FTP随时随地上传更新代码)
1、一般公司人员少,为了方便都随时随地更新,发布快;
2、经常不经测试人员测试就上线,拿用户来测试,用户体验较差;
3、据统计网站中50%的故障都是和代码有关,但都是运维人员承担责任。
建议:
a、开发人员需在个人电脑搭建LNMP/LAMP环境进行测试代码,并且在办公室或IDC机房的测试环境测试通过,最好有专职测试人员。
b、规定代码上线时间,比如三天一上线,满足需求的同时也要有原则,一切为了客户体验度;
c、代码上线之前需要备份,出了问题方便回滚(新浪做法:先传到临时目录,传完整后再直接mv过去,或做软链接)
线上更新代码的思路。如果严格更新,把应用服务器从集群节点平滑下线,然后再更新。
d、上线尽量由运维人员管理操作上线,对于代码的功能性,开发人员更在意,而对于代码的性能优化和上线后服务器的稳定,运维更在意服务器的稳定,因此,如果网站宕机问题归运维管,就要让运维控制上线更科学。否则开发随意更新上传,出了问题运维负责,这样就太不科学了。
2.中型企业上线解决方案
中型企业上线,一般是规范运维人员的步骤,制定统一的上线脚本、备份脚本、回滚脚本,备份文件名称,备份文件路径,降低损失。使操作人性化,统一化,自动化。
3.大型企业上线解决方案
大型企业上线,一般制度和流程控制较多,比较严谨。
1.特别是JAVA代码环境,上线时,有数台机器同时需要更新或者分批更新:
1).本地开发人员取svn代码。当天上线提交到trunk,否则,长期项目单开分支开发,然后在合并主线(trunk)
2).办公内网开发测试时,由开发人员或配置管理员通过部署平台jenkins实现统一部署,(即在部署平台上控制开发机器从svn取代码,编译,打包,发布到开发机,包名如idc_dep.war).
3).开发人员通知或和测试人员一起测试程序,没有问题后,由配置管理员打上新的tag标记。这里要注意,不同环境的配置文件是随代码同时发布的。
4).配置管理员,根据上一步的tag标记,checkout出上线代码,并配置好IDC测试环境的所有配置,执行编译,打包(mvn,ant)(php不需要打包),然后发布到IDC内的统一分发服务器。
5).配置管理员或SA上线人员,把分发的程序代码内容推送到相关测试服务器(包名如idc_test.war),然后通知开发及测试人员进行测试。如果有问题向上回退,继续修改。
6).如果IDC测试没有问题,继续打好tag标记,此时,配置管理员,根据上步的tag标记,checkout出测试好的代码,并配置好IDC正式环境的所有配置,执行编译,打包(mvn,ant)(php不需要打包),然后发布到IDC内的统一分发服务器主机,准备批量发布。
7).配置管理员或SA上线人员,把分发的内容推送到相关正式服务器(包名如idc_product.war),然后通知开发及测试人员进行测试。如果有问题直接发布回滚指令。
IDC正式上线的过程对于JAVA程序,可以是AB组分组上线的思路,即平滑下线一半的服务器,然后发布更新代码,重启测试,无问题后,挂上更新后的服务器,同时再平滑下线另一半的服务器,然后发布更新代码测试(或者直接发布后,重启,挂上线)
php程序代码上线的具体方案:
对于PHP上线方法:发布代码时(也需要测试流程)可以直接发布到正式线临时目录 ,然后mv或更改link的方式发布到正式上线目录 ,不需要重启http服务。这是新朗,赶集的上线方案。
JAVA程序代码上线的具体方案:
对于java上线方法:较大公司需要分组平滑上线(如从负载均衡器上摘掉一半的服务器),发布代码后,重启服务器测试,没问题后,挂上上好线的一半,再下另外一半。如果前端有DNS智能解析,上线还可以分地区上线若干服务器,逐渐普及到全国的服务器,这个被称为“灰度发布”,在后面门户网站上线的知识里我们在讲解。
代码上线解决方案注意事项:
1).上线的流程里,办公室测试环境-->IDC测试环境-->正式生产环境,所有环境中的所有软件均应版本统一,其次尽量单一,否则将后患无穷,开发测试成功,IDC测试就可能有问题(如:操作系统,web服务器,jdk,php,tomcat,resin等版本)
2).开发团队小组办公内部测试环境测试(该测试环境属于开发小组维护,或定时自动更新代码),代码有问题返回给某开发人员重新开发。
3).有专门的测试工程师,程序有问题直接返回给开发人员(此时返回的一般为程序的BUG,称为BUG库),无问题进行IDC测试
4).IDC测试由测试人员和运维人员参与,叫IDCtest,进行程序的压力测试,有问题直接返回给开发人员,无问题进行线上环境上线。
5).数台服务器代码分发上线方案举例(JAVA程序)
A:假设同业务服务器有6台,将服务器分为A,B两组,A组三台,B组三台,先对A组进行从负载均衡器上平滑下线,B组正常提供服务,避免服务器因上线影响业务。
B:下线过程是通过脚本将A组服务器从RS池(LVS,NGINX,HAPROXY,F5等均有平滑方案)中踢出,避免负裁均衡器将请求发送给A组服务器(此时的时间应该为网站流量少时,一般为晚上)
C:将代码分发到A组服务器的站点目录下,对A组服务器上线并重启服务,并由专业的测试人员进行访问测试,测试成功后,挂上A组的服务器,同时下线B组服务器,B组代码上线操作测试等和A组相同,期间也要观察上线提供服务的服务器状况,有问题及时回滚。
6).特别说明:如果是PHP程序,则上线可以简单化,直接将上线代码(最好全量)发布到所有上线服务器的特定目录后,分发完成后,一次性mv或ln到站点目录,当然测试也是少不了的。测试除了人员测试外,还有各种测试脚本测试各个相关业务接口。
7).大多数门户公司的前端页面都已经静态化或者cache了,因此,动态的部分访问平时就不会特别多,流量低谷时就更少了。再加上是平滑上下线,因此基本上是对用户体验无影响的,当然,也有上线出问题的情况,这个是避免不了的。
8)SVN上包含代码和配置
(1)、SVN上存放程序代码(不含资源,大公司基本资源和程序都是分离的)
尽可能全量上线的原因:因为我们务必要保证SVN的代码是最新的。
(2)、存放所有服务的配置文件(LAMP环境,如:apache的httpd.conf配置文件)
a)、开发小组测试环境使用的配置文件
b)、办公测试环使用配置文件
c)、IDC测试使用的配置文件
d)、线上应用使用的配置文件
在上线不同环境时,由配置管理员协调上线。
什么时配置管理员?
就是在开发和运维中间起一个连接纽带的一个职位,这个职位一般在大公司里会设置,负责SVN的管理,上线管理,流程申请,业务协调等工作。
平滑代码上线是什么?
就是在网站代码更新时,不影响正在浏览用户的正常浏览网页或其正使用的其他相关应用。