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端统一一个相同的密码;
三、安装
gem install capistrano
四、命令行测试
root@ubuntu:/tmp# cat capfile task :du, :hosts => "ubuntu.hadoop.com" do run "df -h" end
在ubuntu.hadoop.com(本机)机器上运行df –h命令查看磁盘空间
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)
测试环境
主机名 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目录
cd /tmp mkdir capi cd capi
2、capistrano部署我的应用
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文件
set :application, "test" set :scm, :git set :repository, "ssh://[email protected]/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目录。
set :application, "test"
是告诉Capistrano我们的应用程序被"调用"了
set :scm, :git
默认启动svn,而不是git,如果使用的话,需要set :scm, :git开启。
set :repository, "ssh://[email protected]/data/gitrepo/jsonLib.git"
然后我们需要告诉Capistrano我们的源代码在哪里,这个地址你的本地主机和服务器都可以到达。
set :deploy_to, "/tmp/result"
我们需要告诉Capistran我们的应用放在服务器的哪里,如果不加的话,默认为"/u/apps/#{application}"。
set :normalize_asset_timestamps, false
如果不添加这句话,在deploy:update的时候会出现
*** [err :: 192.168.56.101] find: `/tmp/result_svn/releases/20130625071724/public/p_w_picpaths' *** [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
原因是
Capistrano default behavior is to 'touch' all assets files. (To make sure that any cache get the deployment date). Assets are p_w_picpaths, 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、部署目录结构
cap deploy:setup
会在192.168.56.101创建/tmp/result目录,然后在这个目录里创建releases与shared目录
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、检查
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、更新
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://[email protected]/data/gitrepo/jsonLib.git HEAD" command finished in 219ms * executing "git clone -q ssh://[email protected]/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有分支的话,你可以设置更新分支,设置需要在配置文件里设置,内容为
set :branch, "master"
这样就会更新master分支
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)
测试环境
主机名 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
cd /tmp mkdir capi_svn cd capi_svn
2、capistrano部署我的应用
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文件
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、部署目录结构
cap deploy:setup
会在192.168.56.101创建/tmp/result目录,然后在这个目录里创建releases与shared目录
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、环境检查
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一下,否则会出现
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、更新
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查看,文件都正常复制过去没有问题
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、为了做测试,我新部署个应用,然后用本机测试
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
root@ubuntu:/tmp/check# echo "1">/tmp/svn/1 root@ubuntu:/tmp/check# cat /tmp/svn/1 1
3、然后先部署目录结构
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目录里内容
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、然后进行更新
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
然后在查看更新情况
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指向正确的版本了,然后看看里面都有什么内容
root@ubuntu:/tmp/check# cat /tmp/result/current/1 1
可以看到已经有我之前追加到/tmp/svn/1里的内容了
5、再/tmp/svn/1里添加一个内容为2,需要覆盖修改
root@ubuntu:/tmp/result/current# echo "2">/tmp/svn/1 root@ubuntu:/tmp/result/current# cat /tmp/svn/1 2
6、然后在更新
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的内容
root@ubuntu:/tmp/check# cat /tmp/result/current/1 2
可以看到已经更新为2了
7、在继续对/tmp/svn/1里修改内容为3,覆盖修改(此步骤主要是想测试连续回滚的时候,恢复那个版本)
root@ubuntu:/tmp/check# echo "3">/tmp/svn/1 root@ubuntu:/tmp/check# cat /tmp/svn/1 3
在继续更新
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
查看结果
root@ubuntu:/tmp/check# cat /tmp/result/current/1 3
也是正确的。
8、测试回滚
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
查看结果
root@ubuntu:/tmp/check# cat /tmp/result/current/1 2
已经回滚到之前的版本
9、测试连续回滚
也就是说在回滚后继续回滚
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,就是同一个任务不同的规则,具体如下
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个不同的规则,下面分别运行一下看看
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个区别,可以从下面的结果看到
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
运行
root@ubuntu:/tmp/caphub/test/config/deploy# cap ec2 world:hostname triggering load callbacks * 2013-07-30 11:59:23 11:59:23 == Currently executing `uptodate' * 2013-07-30 11:59:23 11:59:23 == Currently executing `uptodate:git' * 2013-07-30 11:59:23 11:59:23 == Currently executing `ec2' triggering start callbacks for `world:hostname' * 2013-07-30 11:59:23 11:59:23 == Currently executing `multiconfig:ensure' * 2013-07-30 11:59:23 11:59:23 == Currently executing `world:hostname' * executing "hostname" servers: ["192.168.56.101"] [192.168.56.101] executing command ** [out :: 192.168.56.101] server.hadoop.com command finished in 975ms * executing "ifconfig" servers: ["192.168.56.101"] [192.168.56.101] executing command ** [out :: 192.168.56.101] eth0 Link encap:Ethernet HWaddr 08:00:27:66:7a:7a ** [out :: 192.168.56.101] inet addr:192.168.56.101 Bcast:192.168.56.255 Mask:255.255.255.0 ** [out :: 192.168.56.101] inet6 addr: fe80::a00:27ff:fe66:7a7a/64 Scope:Link ** [out :: 192.168.56.101] UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 ** [out :: 192.168.56.101] RX packets:9888 errors:0 dropped:0 overruns:0 frame:0 ** [out :: 192.168.56.101] TX packets:8763 errors:0 dropped:0 overruns:0 carrier:0 ** [out :: 192.168.56.101] collisions:0 txqueuelen:1000 ** [out :: 192.168.56.101] RX bytes:830795 (830.7 KB) TX bytes:1496795 (1.4 MB) ** [out :: 192.168.56.101] ** [out :: 192.168.56.101] eth1 Link encap:Ethernet HWaddr 08:00:27:29:f6:9a ** [out :: 192.168.56.101] inet addr:192.168.8.229 Bcast:192.168.8.255 Mask:255.255.255.0 ** [out :: 192.168.56.101] inet6 addr: fe80::a00:27ff:fe29:f69a/64 Scope:Link ** [out :: 192.168.56.101] UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 ** [out :: 192.168.56.101] RX packets:94100 errors:0 dropped:0 overruns:0 frame:0 ** [out :: 192.168.56.101] TX packets:18954 errors:0 dropped:0 overruns:0 carrier:0 ** [out :: 192.168.56.101] collisions:0 txqueuelen:1000 ** [out :: 192.168.56.101] RX bytes:71655678 (71.6 MB) TX bytes:1413729 (1.4 MB) ** [out :: 192.168.56.101] ** [out :: 192.168.56.101] lo Link encap:Local Loopback ** [out :: 192.168.56.101] inet addr:127.0.0.1 Mask:255.0.0.0 ** [out :: 192.168.56.101] inet6 addr: ::1/128 Scope:Host ** [out :: 192.168.56.101] UP LOOPBACK RUNNING MTU:16436 Metric:1 ** [out :: 192.168.56.101] RX packets:1355 errors:0 dropped:0 overruns:0 frame:0 ** [out :: 192.168.56.101] TX packets:1355 errors:0 dropped:0 overruns:0 carrier:0 ** [out :: 192.168.56.101] collisions:0 txqueuelen:0 ** [out :: 192.168.56.101] RX bytes:183369 (183.3 KB) TX bytes:183369 (183.3 KB) command finished in 63ms eth0 Link encap:Ethernet HWaddr 08:00:27:dc:ff:20 inet addr:192.168.8.104 Bcast:192.168.8.255 Mask:255.255.255.0 inet6 addr: fe80::a00:27ff:fedc:ff20/64 Scope:Link UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:33300 errors:0 dropped:0 overruns:0 frame:0 TX packets:535 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:3383618 (3.3 MB) TX bytes:106195 (106.1 KB) eth1 Link encap:Ethernet HWaddr 08:00:27:af:1e:13 inet addr:192.168.56.102 Bcast:192.168.56.255 Mask:255.255.255.0 inet6 addr: fe80::a00:27ff:feaf:1e13/64 Scope:Link UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:10153 errors:0 dropped:0 overruns:0 frame:0 TX packets:8767 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:935274 (935.2 KB) TX bytes:1437233 (1.4 MB) lo Link encap:Local Loopback inet addr:127.0.0.1 Mask:255.0.0.0 inet6 addr: ::1/128 Scope:Host UP LOOPBACK RUNNING MTU:16436 Metric:1 RX packets:440 errors:0 dropped:0 overruns:0 frame:0 TX packets:440 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:78000 (78.0 KB) TX bytes:78000 (78.0 KB)
从上面可以看到使用system更符合我们的要求。
而且run不能调用 cap命令,比如使用run调用cap git deploy:check来进行git的检测
* executing "cap git deploy:check" servers: ["192.168.56.101"] [192.168.56.101] executing command *** [err :: 192.168.56.101] sh: 1: cap: not found command finished in 29ms failed: "sh -c 'cap git deploy:check'" on 192.168.56.101
如果使用就会出现上面的结果,但使用system就没有问题。