简单分享下我们之前的采用的基于git的开发上线流程,以及所采用的的上线脚本。流程只简单说下,只能希望是抛砖引玉了;上线脚本是本文“重点”。之所以想分享这套脚本,因为个人感觉这套脚本提供了一种目录间“备份--更新/同步--回滚”的实现思路,对其中的细节稍作修改,应该可以适用到其他地方。
总结了两张图来说明基于git的开发流程和上线流程
<a href="http://s3.51cto.com/wyfs02/M01/76/B1/wKiom1ZZcfixzaTKAAClXbP22xI942.png" target="_blank"></a>
<a href="http://s4.51cto.com/wyfs02/M02/76/B1/wKiom1ZZcg3ysKPiAAEP-Kum-S4914.png" target="_blank"></a>
下面一起来看上线脚本
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
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
<code>#!/bin/sh</code>
<code>###定义检查上一条命令是否执行成功的函数</code>
<code>function</code> <code>check {</code>
<code> </code><code>if</code> <code>[ $? -</code><code>ne</code> <code>0 ];</code><code>then</code>
<code> </code><code>echo</code> <code>-e </code><code>"\e[1;31m `date +%Y%m%d_%H:%M:%S` $1 exec failed,please check it ! \e[0m"</code><code>|</code><code>tee</code> <code>-a </code><code>/root/shells/update_online/logs/www</code><code>.err</code>
<code> </code><code>exit</code> <code>-1</code>
<code> </code><code>fi</code>
<code>}</code>
<code>ips=</code><code>"192.xxx.xx.x 192.xxx.xx.x 192.xxx.xx.x"</code>
<code>domain=www.xxx.com </code><code>###项目域名</code>
<code>app_base_dir=</code><code>/app</code> <code>###线上server:项目所在目录,如$app_base_dir/$app_dir拼起来即为项目所在绝对路径/app/www</code>
<code>app_dir=www </code><code>###线上server:项目相对目录</code>
<code>local_dir=</code><code>/home/update/to_online/www</code> <code>###本地server:该目录是从远程git库检出的master分支,即“随时可上线的代码”</code>
<code>bak_dir=</code><code>/update_bak</code> <code>###线上server:备份目录</code>
<code>cat</code> <code><<update</code>
<code>+------------------------------------------+</code>
<code>+ A) 备份 +</code>
<code>+ B) 更新 +</code>
<code>+ C) 回滚 +</code>
<code>+ Q) 退出 +</code>
<code>update</code>
<code>read</code> <code>-p </code><code>"请输入 (A|B|C|Q) ,再按ENTER键: "</code> <code>INPUT</code>
<code>###备份</code>
<code>if</code> <code>[ $INPUT = </code><code>"A"</code> <code>]; </code><code>then</code>
<code> </code><code>for</code> <code>ip </code><code>in</code> <code>$ips</code>
<code> </code><code>do</code>
<code> </code><code>###在远程服务器备份,留三次的备份</code>
<code> </code><code>echo</code> <code>-e </code><code>"\e[1;33m\n-----------backup $ip $domain------------\e[0m"</code>
<code> </code><code>ssh</code> <code>$ip "</code><code>if</code> <code>[ ! -z $bak_dir ] && [ ! -z $app_dir ];</code><code>then</code><code>\</code>
<code> </code><code>mkdir</code> <code>$bak_dir &> </code><code>/dev/null</code><code>; </code><code>cd</code> <code>$bak_dir;</code>
<code> </code><code>ls</code> <code>-d $base_dir*|</code><code>sort</code> <code>-r|</code><code>cat</code> <code>-n |</code><code>awk</code> <code>'\$1 > 2 {print \$NF}'</code><code>|</code><code>xargs</code> <code>rm</code> <code>-rf;</code>
<code> </code><code>rsync</code> <code>-a --delete $app_base_dir/$app_dir/ $bak_dir/$app_dir-`</code><code>date</code> <code>+%Y%m%d_%H.%M`/ --exclude </code><code>'xxx'</code> <code>--exclude </code><code>'xxx/xxx'</code>
<code> </code><code>else</code><code>\</code>
<code> </code><code>exit</code> <code>-1;</code>
<code> </code><code>fi</code><code>" </code>
<code> </code>
<code> </code><code>check </code><code>"backup $ip $domain"</code><code>;</code>
<code> </code><code>echo</code> <code>-e </code><code>"\e[1;32m\n------backup $ip $domain success--------\e[0m\n"</code>
<code> </code><code>done</code>
<code>###更新</code>
<code>elif</code> <code>[ $INPUT = </code><code>"B"</code> <code>]; </code><code>then</code>
<code> </code><code>###拉取最新代码</code>
<code> </code><code>echo</code> <code>-e </code><code>"\e[1;33m\n---------------git pull--------------\e[0m"</code>
<code> </code><code>cd</code> <code>$local_dir </code>
<code> </code><code>git pull</code>
<code> </code><code>check </code><code>"git pull"</code><code>;</code>
<code> </code><code>echo</code> <code>-e </code><code>"\e[1;32m\n-----------git pull success------------\e[0m"</code>
<code> </code>
<code> </code><code>###执行更新操作</code>
<code> </code><code>echo</code> <code>-e </code><code>"\e[1;33m----------update $ip $domain--------------\e[0m\n"</code>
<code> </code><code>cd</code> <code>$local_dir</code>
<code> </code><code>if</code> <code>[ ! -z $app_base_dir ] && [ ! -z $app_dir ];</code><code>then</code> <code>###此处因有--delete参数,故而先判断目录变量是否存在</code>
<code> </code><code>rsync</code> <code>-avz --delete --exclude </code><code>".gitignore"</code> <code>--exclude </code><code>".git"</code> <code>./ $ip:$app_base_dir/$app_dir/</code>
<code> </code><code>check </code><code>"rsync to $ip"</code><code>;</code>
<code> </code><code>else</code>
<code> </code><code>exit</code> <code>-1</code>
<code> </code><code>fi</code>
<code> </code><code>echo</code> <code>-e </code><code>"\e[1;32m\n--------update $ip $domain success----------\e[0m"</code>
<code>###回滚</code>
<code>elif</code> <code>[ $INPUT = </code><code>"C"</code> <code>]; </code><code>then</code>
<code> </code><code>echo</code> <code>-e </code><code>"\e[1;33m\n--------$ip $domain Start Rollback----------\e[0m"</code>
<code> </code><code>###在远程获取备份目录的倒序排列,这里没有将命令集成到下面的远程命令代码块中是因为远程for i in `cat`操作需用单引号,进而无法使用awk,故而放到这里,多了一次ssh链接</code>
<code> </code><code>ssh</code> <code>$ip </code><code>"cd /update_bak && ls -d $base_dir*|sort -r|cat -n|awk '{print \"-\"\$1\",\"\$NF}' > /tmp/bak_dirs.txt"</code>
<code> </code>
<code> </code><code>ssh</code> <code>$ip 'app_dir=www;</code>
<code> </code><code>app_base_dir=</code><code>/app</code><code>;</code>
<code> </code><code>app_dir=www;</code>
<code> </code><code>bak_dir=</code><code>/update_bak</code><code>;</code>
<code> </code><code>info_file=</code><code>/tmp/bak_dirs</code><code>.txt; </code><code>###以倒序排列记录备份目录的文件</code>
<code> </code>
<code> </code><code>unset</code> <code>bak_arr && </code><code>declare</code> <code>-A bak_arr; </code><code>###定义以(-1,-2,-3)为key,以备份文件名称为value的关联数组</code>
<code> </code>
<code> </code><code>###下面的for循环用于给关联数组赋值</code>
<code> </code><code>for</code> <code>i </code><code>in</code> <code>$(</code><code>cat</code> <code>$info_file);</code><code>do</code> <code>\</code>
<code> </code><code>bak_arr[$(</code><code>echo</code> <code>$i|</code><code>cut</code> <code>-d </code><code>","</code> <code>-f 1)]=$(</code><code>echo</code> <code>$i|</code><code>cut</code> <code>-d </code><code>","</code> <code>-f 2);</code>
<code> </code><code>done</code><code>;</code>
<code> </code><code>echo</code> <code>-e </code><code>"\e[1;33m\n There are ${#bak_arr[@]} old version \n\e[0m"</code><code>;</code>
<code> </code><code>cat</code> <code>$info_file|</code><code>sed</code> <code>"s/,/) /"</code><code>; </code><code>###显示本台机器上旧版本倒序排列</code>
<code> </code><code>echo</code> <code>-e </code><code>"\e[1;33m\n Which one do you want to roolback ?\n Input one of \"-1, -2, -3\"\n \e[0m"</code><code>;</code>
<code> </code><code>read</code> <code>INPUT;</code>
<code> </code><code>###下面对输入以及目录存在性做判断</code>
<code> </code><code>if</code> <code>[[ -z </code><code>"${bak_arr[$INPUT]}"</code> <code>]];</code><code>then</code> <code>\</code>
<code> </code><code>echo</code> <code>-e </code><code>"\e[1;31m Your input is wrong !\e[0m"</code><code>;</code>
<code> </code><code>elif</code> <code>[[ ! -d </code><code>"$bak_dir/${bak_arr[$INPUT]}"</code> <code>]];</code><code>then</code> <code>\</code>
<code> </code><code>echo</code> <code>-e </code><code>"\e[1;31m $bak_dir/${bak_arr[$INPUT]} not exist ! \e[0m"</code><code>;</code>
<code> </code><code>else</code> <code>\</code>
<code> </code><code>###执行回滚操作</code>
<code> </code><code>cd</code> <code>$bak_dir/${bak_arr[$INPUT]};</code>
<code> </code><code>rsync</code> <code>-av --delete ./ $app_base_dir/$app_dir/ --exclude </code><code>"xxx"</code> <code>--exclude </code><code>"xxx/xxx"</code>
<code> </code><code>fi</code><code>'</code>
<code> </code><code>check </code><code>"$ip rollback"</code><code>;</code>
<code> </code><code>echo</code> <code>-e </code><code>"\e[1;32m\n--------$ip $domain rollback success----------\e[0m"</code>
<code>elif</code> <code>[ $INPUT = </code><code>"Q"</code> <code>]; </code><code>then</code>
<code> </code><code>echo</code> <code>-e </code><code>"\n -----bye bye-----"</code>
<code> </code><code>exit</code> <code>0</code>
<code>else</code>
<code> </code><code>exit</code> <code>1</code>
<code>fi</code>
以下是使用截图
备份:
<a href="http://s4.51cto.com/wyfs02/M02/89/0C/wKioL1gGPgyDampGAAE5CqwJal0744.png" target="_blank"></a>
更新:
<a href="http://s5.51cto.com/wyfs02/M00/76/B1/wKioL1ZZecKhM8ovAAFkugCC84A926.png" target="_blank"></a>
<a href="http://s1.51cto.com/wyfs02/M00/89/0C/wKioL1gGPg_wDzGYAAQhUT8Q5c8342.png" target="_blank"></a>
回滚:
本文转自kai404 51CTO博客,原文链接:http://blog.51cto.com/kaifly/1717650,如需转载请自行联系原作者