自动化代码部署、代码回滚、命令执行软件之capistrano

简介:

Hi,本周第一天没什么事,所以就先分享一下我研究自动化代码部署与回滚软件的经验。这个软件有什么用途?主要是解决自动进行代码的部署,避免手动部署时出现错误,节省时间,同时在出现问题的时候,能回滚到之前的版本(或者你指定的版本),我在gitlab里找到了这样的软件,名为capistrano。下面就先给大家介绍一下。

文章结构

一、介绍

二、要求的环境

三、安装

四、命令行测试

五、代码部署(结合git)

六、代码部署(结合svn)

七、代码回滚

八、总结

九、namespace

一、介绍

Capistrano是一种在多台服务器上运行脚本的开源工具,它主要用于部署web应用。它自动完成多台服务器上新版本的同步更新,包括数据库的改变。Capistrano最初由Jamis Buck用Ruby开发,并用RubyGems部署渠道部署。现在Capistrano不仅限于应用Ruby on Rails的 web应用框架,而且可以用于部署用其他框架的web应用程序,比如用PHP开发的。Capistran最初是用来应用于bash指令行。现在Ruby on Rails框架的用于也可以使用它的新特性,例如,对当前web应用部署改变使其更新版本,或者使其回滚到之前的旧版本。

二、要求的环境

1、Ruby一定要1.9.x;

2、server端与client端一定要进行ssh信任或者client端统一一个相同的密码;

三、安装

1
gem install capistrano

四、命令行测试

1
2
3
4
root@ubuntu:/tmp# cat capfile
task :du, :hosts =>  "ubuntu.hadoop.com"  do
run  "df -h"
end

在ubuntu.hadoop.com(本机)机器上运行df –h命令查看磁盘空间

1
2
3
4
5
6
7
8
9
10
11
12
13
root@ubuntu:/tmp# cap du
2013 - 06 - 25  13 : 34 : 48  executing `du'
* executing  "df -h"
servers: [ "ubuntu.hadoop.com" ]
[ubuntu.hadoop.com] executing command
** [out :: ubuntu.hadoop.com] Filesystem               Size  Used Avail Use% Mounted on
** [out :: ubuntu.hadoop.com] /dev/mapper/ubuntu-root   39G   3 .3G   33G   10 % /
** [out :: ubuntu.hadoop.com] udev                     489M   4 .0K  489M    1 % /dev
** [out :: ubuntu.hadoop.com] tmpfs                    199M  336K  199M    1 % /run
** [out :: ubuntu.hadoop.com] none                      5 .0M      0   5 .0M    0 % /run/lock
** [out :: ubuntu.hadoop.com] none                     498M      0   498M    0 % /run/shm
** [out :: ubuntu.hadoop.com] /dev/sda1                228M   51M  166M   24 % /boot
command finished  in  981ms

可以看到类似使用python的fabric,但capistrano比fabric多了一个代码回滚功能。

需要注意的是如果你的client机器的ssh端口不是默认22的话,你还想操作的话,需要添加

ssh_options[:port] = 50020#ssh port

如果不添加的话,就会出现connection failed for: ip (Errno::ECONNREFUSED: Connection refused - connect(2))

如果你在使用iptables的机器上使用capistrano,只需要开启ssh端口就可以正常的使用capistrano。

五、代码部署(结合git)

测试环境

1
2
3
主机名                 ip          状态      ruby
ubuntu.hadoop.com    192.168 . 56.102   server       1.9 . 3
server.hadoo.com         192.168 . 56.101   client       1.9 . 3

1、进入tmp目录,然后创建capi目录

1
2
3
cd /tmp
mkdir capi
cd capi

2、capistrano部署我的应用

1
capify .

这将产生两个文件,一个是capfile,这个是Capistrano需要的主要文件,就像make自动产生makefile,rake自动产生Rakefile一样,Capistrano默认寻找并加载capfile文件,默认产生的rapfile非常小,它所做的事就是加载“config/deploy.rb";第二个文件是"config/deploy.rb",这个文件包含你的应用程序部署所需的设置。Ralis的所有设置文档都放在config目录下,通常,你不需要管capfile文件,只需要把精力放在config/deploy.rb的设置和优化上。如果你的Capistrano用于非Rails环境,你可能只有一个capfile文件,而没有config/deploy.rb这个文件。

3、修改config/deploy.rb文件

1
2
3
4
5
6
7
8
9
10
11
set  :application,  "test"
set  :scm, :git
set  :repository,   "ssh://git@192.168.1.250/data/gitrepo/jsonLib.git"
set  :deploy_to,  "/tmp/result"
set  :normalize_asset_timestamps,  false
set  :scm, :git # You can  set  :scm explicitly or Capistrano will make an intelligent guess based on known version control directory names
# Or: `accurev`, `bzr`, `cvs`, `darcs`, `git`, `mercurial`, `perforce`, `subversion` or `none`
role :web,  "192.168.56.101"                           # Your HTTP server, Apache/etc
role :app,  "192.168.56.101"                           # This may be the same  as  your `Web` server
role :db,   "192.168.56.101" , :primary =>  true  # This  is  where Rails migrations will run
#role :db,   "your slave db-server here"

我的修改内容如上

主要是从192.168.1.250里获取git库,然后应用部署到192.168.56.102机器的/tmp/result目录。

1
set  :application,  "test"

是告诉Capistrano我们的应用程序被"调用"了

1
set  :scm, :git

默认启动svn,而不是git,如果使用的话,需要set :scm, :git开启。

1
set  :repository,   "ssh://git@192.168.1.250/data/gitrepo/jsonLib.git"

然后我们需要告诉Capistrano我们的源代码在哪里,这个地址你的本地主机和服务器都可以到达。

1
set  :deploy_to,  "/tmp/result"

我们需要告诉Capistran我们的应用放在服务器的哪里,如果不加的话,默认为"/u/apps/#{application}"。

1
set  :normalize_asset_timestamps,  false

如果不添加这句话,在deploy:update的时候会出现

1
2
3
4
*** [err ::  192.168 . 56.101 ] find: `/tmp/result_svn/releases/ 20130625071724 / public /images'
*** [err ::  192.168 . 56.101 ] : No such file or directory
*** [err ::  192.168 . 56.101 ] find: `/tmp/result_svn/releases/ 20130625071724 / public /stylesheets': No such file or directory
*** [err ::  192.168 . 56.101 ] find: `/tmp/result_svn/releases/ 20130625071724 / public /javascripts': No such file or directory

原因是

1
2
3
Capistrano  default  behavior  is  to  'touch'  all assets files. (To make sure that any cache  get  the deployment date). Assets are images, stylesheets, etc.
If your PHP application  is  not using these directories, capistrano complains  in  such an ugly way.
To disable asset timestamps updates, simply add:

app,web,db是Capistrano需要的三种角色:

web:你的服务器软件运行的地方;

app:你的应用层运行的地方;

db:迁移运行的地方;

4、部署目录结构

1
cap deploy:setup

会在192.168.56.101创建/tmp/result目录,然后在这个目录里创建releases与shared目录

1
2
3
4
5
6
7
8
9
10
root@ubuntu:/tmp/capi# cap deploy:setup
2013 - 06 - 25  15 : 26 : 47  executing `deploy:setup'
* executing  "sudo -p 'sudo password: ' mkdir -p /tmp/result /tmp/result/releases /tmp/result/shared /tmp/result/shared/system /tmp/result/shared/log /tmp/result/shared/pids"
servers: [ "192.168.56.101" ]
[ 192.168 . 56.101 ] executing command
command finished  in  781ms
* executing  "sudo -p 'sudo password: ' chmod g+w /tmp/result /tmp/result/releases /tmp/result/shared /tmp/result/shared/system /tmp/result/shared/log /tmp/result/shared/pids"
servers: [ "192.168.56.101" ]
[ 192.168 . 56.101 ] executing command
command finished  in  40ms

5、检查

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
root@ubuntu:/tmp/capi# cap deploy:check
2013 - 06 - 25  15 : 29 : 04  executing `deploy:check'
* executing  "test -d /tmp/result/releases"
servers: [ "192.168.56.101" ]
[ 192.168 . 56.101 ] executing command
command finished  in  819ms
* executing  "test -w /tmp/result"
servers: [ "192.168.56.101" ]
[ 192.168 . 56.101 ] executing command
command finished  in  25ms
* executing  "test -w /tmp/result/releases"
servers: [ "192.168.56.101" ]
[ 192.168 . 56.101 ] executing command
command finished  in  26ms
* executing  "which git"
servers: [ "192.168.56.101" ]
[ 192.168 . 56.101 ] executing command
command finished  in  26ms
You appear to have all necessary dependencies installed

没有问题继续下一步更新

还得注意,如果你使用ssh模式的git,你需要把客户端与服务端的ssh key都传到服务器里,否则更新失败。

6、更新

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
root@ubuntu:/tmp/capi# cap deploy:update
2013 - 06 - 25  15 : 29 : 22  executing `deploy:update'
** transaction: start
2013 - 06 - 25  15 : 29 : 22  executing `deploy:update_code'
executing locally:  "git ls-remote ssh://git@192.168.1.250/data/gitrepo/jsonLib.git HEAD"
command finished  in  219ms
* executing  "git clone -q ssh://git@192.168.1.250/data/gitrepo/jsonLib.git /tmp/result/releases/20130625072923 && cd /tmp/result/releases/20130625072923 && git checkout -q -b deploy ed8339e65d263fb9076b8f6168073765540bc4c4 && (echo ed8339e65d263fb9076b8f6168073765540bc4c4 > /tmp/result/releases/20130625072923/REVISION)"
servers: [ "192.168.56.101" ]
[ 192.168 . 56.101 ] executing command
command finished  in  1151ms
2013 - 06 - 25  15 : 29 : 24  executing `deploy:finalize_update'
* executing  "chmod -R -- g+w /tmp/result/releases/20130625072923 && rm -rf -- /tmp/result/releases/20130625072923/public/system && mkdir -p -- /tmp/result/releases/20130625072923/public/ && ln -s -- /tmp/result/shared/system /tmp/result/releases/20130625072923/public/system && rm -rf -- /tmp/result/releases/20130625072923/log && ln -s -- /tmp/result/shared/log /tmp/result/releases/20130625072923/log && rm -rf -- /tmp/result/releases/20130625072923/tmp/pids && mkdir -p -- /tmp/result/releases/20130625072923/tmp/ && ln -s -- /tmp/result/shared/pids /tmp/result/releases/20130625072923/tmp/pids"
servers: [ "192.168.56.101" ]
[ 192.168 . 56.101 ] executing command
command finished  in  41ms
2013 - 06 - 25  15 : 29 : 24  executing `deploy:create_symlink'
* executing  "sudo -p 'sudo password: ' rm -f /tmp/result/current && sudo -p 'sudo password: ' ln -s /tmp/result/releases/20130625072923 /tmp/result/current"
servers: [ "192.168.56.101" ]
[ 192.168 . 56.101 ] executing command
command finished  in  60ms
** transaction: commit

没有错误,去192.167.56.101查看文件,确认都正常的复制过去了。

需要注意,服务端与客户端的ssh key都需要添加到git server里。

同时如果你的git有分支的话,你可以设置更新分支,设置需要在配置文件里设置,内容为

1
set  :branch,  "master"

这样就会更新master分支

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
root@server:/tmp/result# ll
total  16
drwxrwxr-x   4  root root  4096  Jun  25  15 : 29  ./
drwxrwxrwt  32  root root  4096  Jun  25  15 : 30  ../
lrwxrwxrwx   1  root root    35  Jun  25  15 : 29  current -> /tmp/result/releases/ 20130625072923 /
drwxrwxr-x   3  root root  4096  Jun  25  15 : 29  releases/
drwxrwxr-x   5  root root  4096  Jun  25  15 : 26  shared/
root@server:/tmp/result# cd current
root@server:/tmp/result/current# ll
total  100
drwxrwxr-x  6  root root   4096  Jun  25  15 : 29  ./
drwxrwxr-x  3  root root   4096  Jun  25  15 : 29  ../
-rwxrwxr-x  1  root root    172  Jun  25  15 : 29  build_sh*
-rwxrwxr-x  1  root root    749  Jun  25  15 : 29  ckHashMap.h*
-rw-rw-r--  1  root root   1740  Jun  25  15 : 29  CStrUtils.cpp
-rw-rw-r--  1  root root    586  Jun  25  15 : 29  CStrUtils.h
drwxrwxr-x  8  root root   4096  Jun  25  15 : 29  .git/
lrwxrwxrwx  1  root root     22  Jun  25  15 : 29  log -> /tmp/result/shared/log/
drwxr-xr-x  2  root root   4096  Jun  25  15 : 29  public /
-rw-rw-r--  1  root root     41  Jun  25  15 : 29  REVISION
drwxr-xr-x  2  root root   4096  Jun  25  15 : 29  tmp/

六、代码部署(结合svn)

测试环境

1
2
3
主机名                 ip          状态      ruby
ubuntu.hadoop.com    192.168 . 56.102   server       1.9 . 3
server.hadoo.com         192.168 . 56.101   client       1.9 . 3

1、进入tmp目录,然后创建capi_svn

1
2
3
cd /tmp
mkdir capi_svn
cd capi_svn

2、capistrano部署我的应用

1
2
3
4
5
6
capify .
root@ubuntu:/tmp/capi_svn# capify .
[add] writing  './Capfile'
[add] making directory  './config'
[add] writing  './config/deploy.rb'
[done] capified!

3、修改config/deploy.rb文件

1
2
3
4
5
6
7
8
9
10
11
12
set  :application,  "test_svn"
set  :scm, :subversion
set  :repository,   "https://192.168.1.56/svn/sgol/trunk/0-sgol_server"
set  :scm_username,  "denglei"
set  :scm_password,  "123456"
set  :deploy_to,  "/tmp/result_svn"
set  :normalize_asset_timestamps,  false
set  :scm, :git # You can  set  :scm explicitly or Capistrano will make an intelligent guess based on known version control directory names
role :web,  "192.168.56.101"                           # Your HTTP server, Apache/etc
role :app,  "192.168.56.101"                           # This may ber
role :db,   "192.168.56.101" , :primary =>  true  # This  is  where Rails migrations will run
#role :db,   "your slave db-server here"

4、部署目录结构

1
cap deploy:setup

会在192.168.56.101创建/tmp/result目录,然后在这个目录里创建releases与shared目录

1
2
3
4
5
6
7
8
9
10
root@ubuntu:/tmp/capi_svn# cap deploy:setup
2013 - 06 - 25  15 : 19 : 29  executing `deploy:setup'
* executing  "sudo -p 'sudo password: ' mkdir -p /tmp/result_svn /tmp/result_svn/releases /tmp/result_svn/shared /tmp/result_svn/shared/system /tmp/result_svn/shared/log /tmp/result_svn/shared/pids"
servers: [ "192.168.56.101" ]
[ 192.168 . 56.101 ] executing command
command finished  in  783ms
* executing  "sudo -p 'sudo password: ' chmod g+w /tmp/result_svn /tmp/result_svn/releases /tmp/result_svn/shared /tmp/result_svn/shared/system /tmp/result_svn/shared/log /tmp/result_svn/shared/pids"
servers: [ "192.168.56.101" ]
[ 192.168 . 56.101 ] executing command
command finished  in  36ms

5、环境检查

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
root@ubuntu:/tmp/capi_svn# cap deploy:check
2013 - 06 - 25  15 : 21 : 03  executing `deploy:check'
* executing  "test -d /tmp/result_svn/releases"
servers: [ "192.168.56.101" ]
[ 192.168 . 56.101 ] executing command
command finished  in  1050ms
* executing  "test -w /tmp/result_svn"
servers: [ "192.168.56.101" ]
[ 192.168 . 56.101 ] executing command
command finished  in  21ms
* executing  "test -w /tmp/result_svn/releases"
servers: [ "192.168.56.101" ]
[ 192.168 . 56.101 ] executing command
command finished  in  22ms
* executing  "which svn"
servers: [ "192.168.56.101" ]
[ 192.168 . 56.101 ] executing command
command finished  in  28ms
You appear to have all necessary dependencies installed

没有问题

还有一个需要注意的,在进行更新前,需要在client里对svn先co一下,否则会出现

1
2
3
4
5
6
7
8
9
10
Error validating server certificate  for  'https://192.168.1.56:443' :
- The certificate  is  not issued by a trusted authority. Use the
fingerprint to validate the certificate manually!
- The certificate hostname does not match.
Certificate information:
- Hostname: yx
- Valid: from Fri,  14  Jan  2011  12 : 31 : 10  GMT until Mon,  11  Jan  2021  12 : 31 : 10  GMT
- Issuer: yx
- Fingerprint: b2:b2: 26 :5d:5a: 76 :cd:d2: 46 :e4:a6: 31 :d9:dc:c7:2b:2a:3a:eb: 46
(R)eject, accept (t)emporarily or accept (p)ermanently?

错误,选择p然后yes,之后你的用户名与密码即可。

6、更新

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
root@ubuntu:/tmp/capi_svn# cap deploy:update
2013 - 06 - 25  15 : 21 : 38  executing `deploy:update'
** transaction: start
2013 - 06 - 25  15 : 21 : 38  executing `deploy:update_code'
executing locally:  "svn info https://192.168.1.56/svn/sgol/trunk/0-sgol_server --username denglei --password **** --no-auth-cache  -rHEAD"
command finished  in  691ms
* executing  "svn checkout -q --username denglei --password **** o-auth-cache  -r2446 https://192.168.1.56/svn/sgol/trunk/0-sgol_server /tmp/result_svn/releases/20130625072139 && (echo 2446 > /tmp/result_svn/releases/20130625072139/REVISION)"
servers: [ "192.168.56.101" ]
[ 192.168 . 56.101 ] executing command
command finished  in  7259ms
2013 - 06 - 25  15 : 21 : 46  executing `deploy:finalize_update'
* executing  "chmod -R -- g+w /tmp/result_svn/releases/20130625072139 && rm -rf -- /tmp/result_svn/releases/20130625072139/public/system && mkdir -p -- /tmp/result_svn/releases/20130625072139/public/ && ln -s -- /tmp/result_svn/shared/system /tmp/result_svn/releases/20130625072139/public/system && rm -rf -- /tmp/result_svn/releases/20130625072139/log && ln -s -- /tmp/result_svn/shared/log /tmp/result_svn/releases/20130625072139/log && rm -rf -- /tmp/result_svn/releases/20130625072139/tmp/pids && mkdir -p -- /tmp/result_svn/releases/20130625072139/tmp/ && ln -s -- /tmp/result_svn/shared/pids /tmp/result_svn/releases/20130625072139/tmp/pids"
servers: [ "192.168.56.101" ]
[ 192.168 . 56.101 ] executing command
command finished  in  100ms
2013 - 06 - 25  15 : 21 : 46  executing `deploy:create_symlink'
* executing  "sudo -p 'sudo password: ' rm -f /tmp/result_svn/current && sudo -p 'sudo password: ' ln -s /tmp/result_svn/releases/20130625072139 /tmp/result_svn/current"
servers: [ "192.168.56.101" ]
[ 192.168 . 56.101 ] executing command
command finished  in  89ms
** transaction: commit

没有问题,192.168.56.101查看,文件都正常复制过去没有问题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
root@server:/tmp/result_svn# pwd
/tmp/result_svn
root@server:/tmp/result_svn# ll
total  16
drwxrwxr-x   4  root root  4096  Jun  25  15 : 21  ./
drwxrwxrwt  32  root root  4096  Jun  25  15 : 21  ../
lrwxrwxrwx   1  root root    39  Jun  25  15 : 21  current -> /tmp/result_svn/releases/ 20130625072139 /
drwxrwxr-x   3  root root  4096  Jun  25  15 : 21  releases/
drwxrwxr-x   5  root root  4096  Jun  25  15 : 19  shared/
root@server:/tmp/result_svn# cd current
root@server:/tmp/result_svn/current# ll
total  80
drwxrwxr-x  19  root root  4096  Jun  25  15 : 21  ./
drwxrwxr-x   3  root root  4096  Jun  25  15 : 21  ../
drwxrwxr-x   3  root root  4096  Jun  25  15 : 21  config/
drwxrwxr-x   4  root root  4096  Jun  25  15 : 21  controller/
drwxrwxr-x   7  root root  4096  Jun  25  15 : 21  data/
drwxrwxr-x   4  root root  4096  Jun  25  15 : 21  docs/
drwxrwxr-x   3  root root  4096  Jun  25  15 : 21  lib/
lrwxrwxrwx   1  root root    26  Jun  25  15 : 21  log -> /tmp/result_svn/shared/log/
drwxrwxr-x  17  root root  4096  Jun  25  15 : 21  logs/
drwxrwxr-x   3  root root  4096  Jun  25  15 : 21  model/
drwxrwxr-x   5  root root  4096  Jun  25  15 : 21  plugins/
drwxr-xr-x   2  root root  4096  Jun  25  15 : 21  public /
-rw-rw-r--   1  root root     5  Jun  25  15 : 21  REVISION
drwxrwxr-x   3  root root  4096  Jun  25  15 : 21  server1001/
drwxrwxr-x   6  root root  4096  Jun  25  15 : 21  .svn/

在顺便说一下,如果你想要指定版本升级的话,可以使用cap -s revision=2449 deploy:update

revision后添加版本后即可

七、代码回滚

1、为了做测试,我新部署个应用,然后用本机测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
root@ubuntu:/tmp/check# ll
total  8
drwxrwxr-x   2  root root  4096  Jun  25  11 : 05  ./
drwxrwxrwt  16  root root  4096  Jun  25  14 : 09  ../
root@ubuntu:/tmp/check# capify .
[add] writing  './Capfile'
[add] making directory  './config'
[add] writing  './config/deploy.rb'
[done] capified!
root@ubuntu:/tmp/check# cat config/deploy.rb
set  :application,  "test"
set  :repository,   "/tmp/svn"
set  :deploy_to,  "/tmp/result"
set  :normalize_asset_timestamps,  false
set  :scm, :git # You can  set  :scm explicitly or Capistrano will make an intelligent guess based on known version control directory names
# Or: `accurev`, `bzr`, `cvs`, `darcs`, `git`, `mercurial`, `perforce`, `subversion` or `none`
role :web,  "192.168.56.102"                           # Your HTTP server, Apache/etc
role :app,  "192.168.56.102"                           # This may be the same  as  your `Web` server
role :db,   "192.168.56.102" , :primary =>  true  # This  is  where Rails migrations will run
#role :db,   "your slave db-server here"

2、然后在/tmp/svn(这个目录为上面config/deploy.rb里定义的)里创建个文件为1,内容也是1

1
2
3
root@ubuntu:/tmp/check# echo  "1" >/tmp/svn/ 1
root@ubuntu:/tmp/check# cat /tmp/svn/ 1
1

3、然后先部署目录结构

1
2
3
4
5
6
7
8
9
10
root@ubuntu:/tmp/check# cap deploy:setup
2013 - 06 - 25  15 : 33 : 17  executing `deploy:setup'
* executing  "sudo -p 'sudo password: ' mkdir -p /tmp/result /tmp/result/releases /tmp/result/shared /tmp/result/shared/system /tmp/result/shared/log /tmp/result/shared/pids"
servers: [ "192.168.56.102" ]
[ 192.168 . 56.102 ] executing command
command finished  in  997ms
* executing  "sudo -p 'sudo password: ' chmod g+w /tmp/result /tmp/result/releases /tmp/result/shared /tmp/result/shared/system /tmp/result/shared/log /tmp/result/shared/pids"
servers: [ "192.168.56.102" ]
[ 192.168 . 56.102 ] executing command
command finished  in  45ms

查看/tmp/result目录里内容

1
2
3
4
5
6
root@ubuntu:/tmp/check# ll /tmp/result/
total  16
drwxrwxr-x   4  root root  4096  Jun  25  15 : 33  ./
drwxrwxrwt  17  root root  4096  Jun  25  15 : 17  ../
drwxrwxr-x   2  root root  4096  Jun  25  15 : 33  releases/
drwxrwxr-x   5  root root  4096  Jun  25  15 : 33  shared/

4、然后进行更新

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
root@ubuntu:/tmp/check# cap deploy:update
2013 - 06 - 25  15 : 35 : 01  executing `deploy:update'
** transaction: start
2013 - 06 - 25  15 : 35 : 01  executing `deploy:update_code'
* executing  "cp -R /tmp/svn /tmp/result/releases/20130625073501 && (echo  > /tmp/result/releases/20130625073501/REVISION)"
servers: [ "192.168.56.102" ]
[ 192.168 . 56.102 ] executing command
command finished  in  945ms
2013 - 06 - 25  15 : 35 : 02  executing `deploy:finalize_update'
* executing  "chmod -R -- g+w /tmp/result/releases/20130625073501 && rm -rf -- /tmp/result/releases/20130625073501/public/system && mkdir -p -- /tmp/result/releases/20130625073501/public/ && ln -s -- /tmp/result/shared/system /tmp/result/releases/20130625073501/public/system && rm -rf -- /tmp/result/releases/20130625073501/log && ln -s -- /tmp/result/shared/log /tmp/result/releases/20130625073501/log && rm -rf -- /tmp/result/releases/20130625073501/tmp/pids && mkdir -p -- /tmp/result/releases/20130625073501/tmp/ && ln -s -- /tmp/result/shared/pids /tmp/result/releases/20130625073501/tmp/pids"
servers: [ "192.168.56.102" ]
[ 192.168 . 56.102 ] executing command
command finished  in  36ms
2013 - 06 - 25  15 : 35 : 02  executing `deploy:create_symlink'
* executing  "sudo -p 'sudo password: ' rm -f /tmp/result/current && sudo -p 'sudo password: ' ln -s /tmp/result/releases/20130625073501 /tmp/result/current"
servers: [ "192.168.56.102" ]
[ 192.168 . 56.102 ] executing command
command finished  in  49ms
** transaction: commit

然后在查看更新情况

1
2
3
4
5
6
7
root@ubuntu:/tmp/check# ll /tmp/result/
total  16
drwxrwxr-x   4  root root  4096  Jun  25  15 : 35  ./
drwxrwxrwt  17  root root  4096  Jun  25  15 : 17  ../
lrwxrwxrwx   1  root root    35  Jun  25  15 : 35  current -> /tmp/result/releases/ 20130625073501 /
drwxrwxr-x   3  root root  4096  Jun  25  15 : 35  releases/
drwxrwxr-x   5  root root  4096  Jun  25  15 : 34  shared/

可以看到已经有了一个current指向正确的版本了,然后看看里面都有什么内容

1
2
root@ubuntu:/tmp/check# cat /tmp/result/current/ 1
1

可以看到已经有我之前追加到/tmp/svn/1里的内容了

5、再/tmp/svn/1里添加一个内容为2,需要覆盖修改

1
2
3
root@ubuntu:/tmp/result/current# echo  "2" >/tmp/svn/ 1
root@ubuntu:/tmp/result/current# cat /tmp/svn/ 1
2

6、然后在更新

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
root@ubuntu:/tmp/check# cap deploy:update
2013 - 06 - 25  15 : 36 : 28  executing `deploy:update'
** transaction: start
2013 - 06 - 25  15 : 36 : 28  executing `deploy:update_code'
* executing  "cp -R /tmp/svn /tmp/result/releases/20130625073628 && (echo  > /tmp/result/releases/20130625073628/REVISION)"
servers: [ "192.168.56.102" ]
[ 192.168 . 56.102 ] executing command
command finished  in  1251ms
2013 - 06 - 25  15 : 36 : 29  executing `deploy:finalize_update'
* executing  "chmod -R -- g+w /tmp/result/releases/20130625073628 && rm -rf -- /tmp/result/releases/20130625073628/public/system && mkdir -p -- /tmp/result/releases/20130625073628/public/ && ln -s -- /tmp/result/shared/system /tmp/result/releases/20130625073628/public/system && rm -rf -- /tmp/result/releases/20130625073628/log && ln -s -- /tmp/result/shared/log /tmp/result/releases/20130625073628/log && rm -rf -- /tmp/result/releases/20130625073628/tmp/pids && mkdir -p -- /tmp/result/releases/20130625073628/tmp/ && ln -s -- /tmp/result/shared/pids /tmp/result/releases/20130625073628/tmp/pids"
servers: [ "192.168.56.102" ]
[ 192.168 . 56.102 ] executing command
command finished  in  71ms
2013 - 06 - 25  15 : 36 : 30  executing `deploy:create_symlink'
* executing  "sudo -p 'sudo password: ' rm -f /tmp/result/current && sudo -p 'sudo password: ' ln -s /tmp/result/releases/20130625073628 /tmp/result/current"
servers: [ "192.168.56.102" ]
[ 192.168 . 56.102 ] executing command
command finished  in  53ms
** transaction: commit

在查看一下/tmp/result里的最新版本里1的内容

1
2
root@ubuntu:/tmp/check# cat /tmp/result/current/ 1
2

可以看到已经更新为2了

7、在继续对/tmp/svn/1里修改内容为3,覆盖修改(此步骤主要是想测试连续回滚的时候,恢复那个版本)

1
2
3
root@ubuntu:/tmp/check# echo  "3" >/tmp/svn/ 1
root@ubuntu:/tmp/check# cat /tmp/svn/ 1
3

在继续更新

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
root@ubuntu:/tmp/check# cap deploy:update
2013 - 06 - 25  15 : 37 : 11  executing `deploy:update'
** transaction: start
2013 - 06 - 25  15 : 37 : 11  executing `deploy:update_code'
* executing  "cp -R /tmp/svn /tmp/result/releases/20130625073711 && (echo  > /tmp/result/releases/20130625073711/REVISION)"
servers: [ "192.168.56.102" ]
[ 192.168 . 56.102 ] executing command
command finished  in  890ms
2013 - 06 - 25  15 : 37 : 12  executing `deploy:finalize_update'
* executing  "chmod -R -- g+w /tmp/result/releases/20130625073711 && rm -rf -- /tmp/result/releases/20130625073711/public/system && mkdir -p -- /tmp/result/releases/20130625073711/public/ && ln -s -- /tmp/result/shared/system /tmp/result/releases/20130625073711/public/system && rm -rf -- /tmp/result/releases/20130625073711/log && ln -s -- /tmp/result/shared/log /tmp/result/releases/20130625073711/log && rm -rf -- /tmp/result/releases/20130625073711/tmp/pids && mkdir -p -- /tmp/result/releases/20130625073711/tmp/ && ln -s -- /tmp/result/shared/pids /tmp/result/releases/20130625073711/tmp/pids"
servers: [ "192.168.56.102" ]
[ 192.168 . 56.102 ] executing command
command finished  in  42ms
2013 - 06 - 25  15 : 37 : 12  executing `deploy:create_symlink'
* executing  "sudo -p 'sudo password: ' rm -f /tmp/result/current && sudo -p 'sudo password: ' ln -s /tmp/result/releases/20130625073711 /tmp/result/current"
servers: [ "192.168.56.102" ]
[ 192.168 . 56.102 ] executing command
command finished  in  56ms
** transaction: commit

查看结果

1
2
root@ubuntu:/tmp/check# cat /tmp/result/current/ 1
3

也是正确的。

8、测试回滚

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
root@ubuntu:/tmp/check# cap deploy:rollback
2013 - 06 - 25  15 : 37 : 42  executing `deploy:rollback'
2013 - 06 - 25  15 : 37 : 42  executing `deploy:rollback:revision'
* executing  "sudo -p 'sudo password: ' ls -x /tmp/result/releases"
servers: [ "192.168.56.102" ]
[ 192.168 . 56.102 ] executing command
command finished  in  980ms
* executing  "sudo -p 'sudo password: ' rm /tmp/result/current; sudo -p 'sudo password: ' ln -s /tmp/result/releases/20130625073628 /tmp/result/current"
servers: [ "192.168.56.102" ]
[ 192.168 . 56.102 ] executing command
command finished  in  94ms
2013 - 06 - 25  15 : 37 : 43  executing `deploy:restart'
2013 - 06 - 25  15 : 37 : 43  executing `deploy:rollback:cleanup'
* executing  "if [ `readlink /tmp/result/current` != /tmp/result/releases/20130625073711 ]; then sudo -p 'sudo password: ' rm -rf /tmp/result/releases/20130625073711; fi"
servers: [ "192.168.56.102" ]
[ 192.168 . 56.102 ] executing command
command finished  in  65ms

查看结果

1
2
root@ubuntu:/tmp/check# cat /tmp/result/current/ 1
2

已经回滚到之前的版本

9、测试连续回滚

也就是说在回滚后继续回滚

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
root@ubuntu:/tmp/check# cap deploy:rollback
2013 - 06 - 25  15 : 38 : 09  executing `deploy:rollback'
2013 - 06 - 25  15 : 38 : 09  executing `deploy:rollback:revision'
* executing  "sudo -p 'sudo password: ' ls -x /tmp/result/releases"
servers: [ "192.168.56.102" ]
[ 192.168 . 56.102 ] executing command
command finished  in  987ms
* executing  "sudo -p 'sudo password: ' rm /tmp/result/current; sudo -p 'sudo password: ' ln -s /tmp/result/releases/20130625073501 /tmp/result/current"
servers: [ "192.168.56.102" ]
[ 192.168 . 56.102 ] executing command
command finished  in  49ms
2013 - 06 - 25  15 : 38 : 10  executing `deploy:restart'
2013 - 06 - 25  15 : 38 : 10  executing `deploy:rollback:cleanup'
* executing  "if [ `readlink /tmp/result/current` != /tmp/result/releases/20130625073628 ]; then sudo -p 'sudo password: ' rm -rf /tmp/result/releases/20130625073628; fi"
servers: [ "192.168.56.102" ]
[ 192.168 . 56.102 ] executing command
command finished  in  66ms
root@ubuntu:/tmp/check# cat /tmp/result/current/ 1
1

可以从结果了解到,使用回滚的时候,默认都是按照更新的时间来回滚(比如你第一个更新为1,第二次更新为2,第三次更新为3的时候,想回滚,你只能使用rollback回滚到第二次,值为2的,不知直接回滚到第一次,值为1的,如果还想回滚到1,就在回滚一次,也就是在第3次,值为3的时候,连续回滚2次)

在深入一下,默认的回滚是到之前的版本,如果你想回滚到指定的版本,可以使用

cap -s previous_release=/tmp/result_svn/releases/20130627023154 deploy:rollback

其中previous_release为你在client里release的路径加上你想回滚的版本

八、总结

从上面的介绍与实例,大家可以很方便的理解capistrano的用途,可以配置crontab或者puppet实现自动化的部署更新代码,简化运维人员的工作量、减少部署错误、增加自己的时间。

九、namespace

在简单的讲一下namespace,就是同一个任务不同的规则,具体如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
root@server:~/capistrano# cat Capfile
namespace  :command  do
task :hostname, :hosts =>  "127.0.0.1"  do
run  "hostname"
end
task :ip, :hosts =>  "127.0.0.1"  do
run  "ifconfig"
end
end
root@server:~/capistrano# cap -vT
cap command:hostname #
cap command:ip       #
cap invoke           # Invoke a single command on the remote servers.
cap shell            # Begin an interactive Capistrano session.
Extended help may be available  for  these tasks.
Type `cap -e taskname' to view it.

可以看到command任务有hostname与ip这2个不同的规则,下面分别运行一下看看

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
root@server:~/capistrano# cap command:ip
2013 - 07 - 30  10 : 07 : 05  executing `command:ip'
* executing  "ifconfig"
servers: [ "127.0.0.1" ]
[ 127.0 . 0.1 ] executing command
** [out ::  127.0 . 0.1 ] eth0      Link encap:Ethernet  HWaddr  08 : 00 : 27 : 66 :7a:7a
** [out ::  127.0 . 0.1 ] inet addr: 192.168 . 56.101   Bcast: 192.168 . 56.255   Mask: 255.255 . 255.0
** [out ::  127.0 . 0.1 ] inet6 addr: fe80::a00:27ff:fe66:7a7a/ 64  Scope:Link
** [out ::  127.0 . 0.1 ] UP BROADCAST RUNNING MULTICAST  MTU: 1500   Metric: 1
** [out ::  127.0 . 0.1 ] RX packets: 2821  errors: 0  dropped: 0  overruns: 0  frame: 0
** [out ::  127.0 . 0.1 ] TX packets: 1161  errors: 0  dropped: 0  overruns: 0  carrier: 0
** [out ::  127.0 . 0.1 ] collisions: 0  txqueuelen: 1000
** [out ::  127.0 . 0.1 ] RX bytes: 211437  ( 211.4  KB)  TX bytes: 183757  ( 183.7  KB)
** [out ::  127.0 . 0.1 ]
** [out ::  127.0 . 0.1 ] eth1      Link encap:Ethernet  HWaddr  08 : 00 : 27 : 29 :f6:9a
** [out ::  127.0 . 0.1 ] inet6 addr: fe80::a00:27ff:fe29:f69a/ 64  Scope:Link
** [out ::  127.0 . 0.1 ] UP BROADCAST RUNNING MULTICAST  MTU: 1500   Metric: 1
** [out ::  127.0 . 0.1 ] RX packets: 28  errors: 0  dropped: 0  overruns: 0  frame: 0
** [out ::  127.0 . 0.1 ] TX packets: 81  errors: 0  dropped: 0  overruns: 0  carrier: 0
** [out ::  127.0 . 0.1 ] collisions: 0  txqueuelen: 1000
** [out ::  127.0 . 0.1 ] RX bytes: 9576  ( 9.5  KB)  TX bytes: 26118  ( 26.1  KB)
** [out ::  127.0 . 0.1 ]
** [out ::  127.0 . 0.1 ] lo        Link encap:Local Loopback
** [out ::  127.0 . 0.1 ] inet addr: 127.0 . 0.1   Mask: 255.0 . 0.0
** [out ::  127.0 . 0.1 ] inet6 addr: :: 1 / 128  Scope:Host
** [out ::  127.0 . 0.1 ] UP LOOPBACK RUNNING  MTU: 16436   Metric: 1
** [out ::  127.0 . 0.1 ] RX packets: 504  errors: 0  dropped: 0  overruns: 0  frame: 0
** [out ::  127.0 . 0.1 ] TX packets: 504  errors: 0  dropped: 0  overruns: 0  carrier: 0
** [out ::  127.0 . 0.1 ] collisions: 0  txqueuelen: 0
** [out ::  127.0 . 0.1 ] RX bytes: 71762  ( 71.7  KB)  TX bytes: 71762  ( 71.7  KB)
** [out ::  127.0 . 0.1 ]
command finished  in  941ms
root@server:~/capistrano# cap command:hostname
2013 - 07 - 30  10 : 07 : 11  executing `command:hostname'
* executing  "hostname"
servers: [ "127.0.0.1" ]
[ 127.0 . 0.1 ] executing command
** [out ::  127.0 . 0.1 ] server.hadoop.com
command finished  in  978ms

从结果可以看出namespace,就是把不同的规则都统一的挂到一个任务下。

在namespace里运行命令可以使用run与system,但这2个区别,可以从下面的结果看到

1
2
3
4
5
6
7
8
root@ubuntu:/tmp/caphub/test/config/deploy# cat ec2.rb
namespace  :world  do
task :hostname, :hosts =>  "192.168.56.101"  do
run  "hostname"
run  "ifconfig"
system( "ifconfig" )
end
end

运行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
root@ubuntu:/tmp/caphub/test/config/deploy# cap ec2 world:hostname
triggering load callbacks
2013 - 07 - 30  11 : 59 :