├── LICENSE ├── README.md ├── cecho.sh ├── clean-log.sh ├── conf.sh ├── core.rsync.sh ├── core.sh ├── deploy-ot.sh ├── deploy-qa.sh ├── deploy-rsync.sh ├── deploy-work.sh ├── exec.sh ├── function.sh ├── init.sh └── version.sh /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 代码部署系统 2 | 3 | 日常开发中,经常会有把本地的代码push到qa机器、worker机器、正式环境机器,无底线的手动重复操作为我们的工作增添了太多的枯燥。 4 | 5 | 如果需要同步代码的机器有成百上千台,每次手动去操作实在是在给自己找麻烦,不但效率低下,而且容易出事故。 6 | 7 | 如果你没有一套好用的代码推送系统、或者正在苦寻,那么这套基于shell deploy也许是你不错的选择! 8 | 9 | codedeploy 支持多项目、多集群、多模式的代码部署系统。 10 | 11 | conf.sh 脚本是deploy配置文件,其它文件不要去改动它。 12 | 13 | 非正式的线上环境机器,谁最后一次部署的代码,需要本人才能解锁,防止代码被冲洗。 14 | 15 | codedeploy 采用轮询推送,如果某集群有100台机器,在推送这集群的时候,其中有几台机器推送失败了,会提示你重新推送失败的机器。 16 | 17 | 注: 18 | 集群代码部署, 建议配置好无密码登录(RSA密钥认证)。否则部署过程中每一台机器都需要手动输入用户(conf.sh中变量SSH_USER)密码。 19 | 20 | ## 1. 命令手册 21 | 22 | #### 1.1 git 模式部署代码 23 | ```Bash 24 | sh deploy-qa.sh 分支名称 qa集群编号 25 | sh deploy-ot.sh 分支名称 online集群编号 26 | sh deploy-worker.sh 分支名称 worker集群编号 27 | ``` 28 | 29 | #### 1.2 file 模式部署代码 30 | ```Bash 31 | sh deploy-qa.sh file qa集群编号 32 | sh deploy-ot.sh file online集群编号 33 | sh deploy-worker.sh file worker集群编号 34 | ``` 35 | 36 | #### 1.3 两种模式通用, 释放当前用户占用机器例子 37 | ```Bash 38 | sh deploy-qa.sh clean qa集群编号 39 | sh deploy-ot.sh clean online集群编号 40 | sh deploy-worker.sh clean worker集群编号 41 | ``` 42 | 43 | #### 1.4 释放对机器的独占模式,让其他同事可以部署代码 44 | ```Bash 45 | sh deploy-qa.sh clean 集群编号 46 | sh deploy-worker.sh clean 集群编号 47 | sh deploy-ot.sh clean 集群编号 48 | ``` 49 | 50 | ### 1.5 特殊模式:rsync 代码推送,用于回归机上执行,不提供 clean 方法 51 | ```Bash 52 | sh deploy-rsync.sh 集群编号 53 | ``` 54 | 55 | #### 多服务器批处理命令执行 56 | 57 | ##### 1.6 Debug模式 58 | ```Bash 59 | sh exec.sh "command" debug 60 | ``` 61 | 62 | ##### 1.7 非Dubug模式: 63 | ```Bash 64 | sh exec.sh "command" 65 | ``` 66 | 67 | ## 2. 例子大全 68 | 69 | ##### 2.1 (file模式,代码部署例子) 70 | 71 | 首先打开文件conf.sh, 找到变量 **SSH_USER**,填入公共账号; 72 | 继续找到变量 **project_name**、**qa**、**online**、**worker**、**local_web_path**、**remote_web_path**;(这些变量都在一起的) 73 | ```Bash 74 | [test@test01v ~/codedeploy]$ vim conf.sh 75 | 76 | SSH_USER='public_user' # 部署代码, 用到的用户, 整个系统通用 77 | 78 | number=1 79 | project_name[$number]="test.codedeploy.cn" 80 | 81 | # 顾名思义, 这是线上机器了, 可以填写IP地址、hostname 多台机器以空格分割 82 | online[$number]="" 83 | 84 | # 顾名思义, 这是测试机器了,可以填写IP地址、hostname 多台机器以空格分割 85 | qa[$number]="test01v.add.net" 86 | 87 | # 顾名思义, 这是worker机器了,可以填写IP地址、hostname 多台机器以空格分割 88 | worker[$number]="" 89 | 90 | # 项目本地跟目录, 权限(wr) 91 | local_web_path[$number]="/home/test/codedeploy" 92 | 93 | # 项目部署到远端机器的目录, 前提这个目录有读写(wr)权限 94 | remote_web_path[$number]="/home/web/test/${project_name[1]}" 95 | ``` 96 | 97 | ###### 2.2 file模式 执行结果如下(分支模式同理,把“file”参数换成“git分支名称”) 98 | ```Bash 99 | [test@test01v ~/codedeploy]$ sh deploy-qa.sh file 1 100 | 101 | [file模式] - [qa1 环境] 102 | 103 | 本地配置 [1] 开始打包 ... ... 104 | 本地配置 [1] 打包成功: /tmp/codedeploy_tmp/test/test.codedeploy.cn/codedeploy_test.codedeploy.cn_20160627153426.tar.gz 105 | 本地配置 [1] 文件大小: 172K 106 | 107 | 1. test01v.add.net => 代码上传中 ... ... 108 | 1. test01v.add.net => 代码上传成功: /home/public_user/codedeploy_history/test.codedeploy.cn/codedeploy_test.codedeploy.cn_20160627153426.tar.gz 109 | 1. test01v.add.net => 耗时: 150ms [非常快] 110 | 1. test01v.add.net => 开始解压远程代码包 ... ... 111 | 1. test01v.add.net => 代码解压成功: /home/web/test/test.codedeploy.cn 112 | 1. test01v.add.net => 清理远程过期的tar包 113 | 114 | 115 | [result] 机器数量: 1 全部部署成功! 116 | ``` 117 | 118 | ##### 2.3 (rsync模式,代码部署例子) 119 | 120 | 首先打开文件conf.sh, 找到变量 **SSH_USER**,填入公共账号; 121 | 继续找到变量 **project_name**、**rsync**、**local_web_path**、**remote_web_path**;(这些变量都在一起的) 122 | ```Bash 123 | [test@test01v ~/codedeploy]$ vim conf.sh 124 | 125 | SSH_USER='public_user' # 部署代码, 用到的用户, 整个系统通用 126 | 127 | number=1 128 | project_name[$number]="test.codedeploy.cn" 129 | 130 | # 顾名思义, 这是回归机机器了,可以填写IP地址、hostname 多台机器以空格分割 131 | rsync[$number]="test01v.add.net" 132 | 133 | # 项目本地跟目录, 权限(wr) 134 | local_web_path[$number]="/home/test/codedeploy" 135 | 136 | # 项目部署到远端机器的目录, 前提这个目录有读写(wr)权限 137 | remote_web_path[$number]="/home/web/test/${project_name[1]}" 138 | ``` 139 | 140 | ###### 2.4 rsync模式 执行结果如下 141 | ```Bash 142 | [test@test01v ~/codedeploy]$ sh deploy-rsync.sh 1 143 | 144 | [rsync模式] - [环境 1] 145 | 146 | 1. test01v.add.net => 代码同步中 ... ... 147 | 1. test01v.add.net => 代码同步成功: /home/web/test/test.codedeploy.cn 148 | 1. test01v.add.net => 耗时: 183ms [非常快] 149 | 150 | 151 | [result] 机器数量: 1 全部部署成功! 152 | 153 | ``` 154 | 155 | ##### 2.5 (释放占用的环境,只支持模式:file、git) 156 | ```Bash 157 | [test@test01v ~/codedeploy]$ sh deploy-qa.sh clean 1 158 | 159 | [qa1 环境] - [执行操作 clean] 160 | 161 | 1. test01v.add.net => 环境释放成功. 162 | ``` 163 | 164 | ##### 2.6 (清理当前用户登录日志) 165 | ```Bash 166 | [test@test01v ~/codedeploy]$ sh clean-log.sh 167 | 168 | clean log omplete! 169 | ``` 170 | 171 | ##### 2.7 (多服务器批处理命令执行例子) 172 | 173 | 首先打开文件conf.sh, 找到变量 **EXEC_HOSTS**,填入需要执行的主机名称,以可以填写IP地址; 174 | 继续找到变量 **SSH_USER**,填入公共账号; 175 | ```Bash 176 | [test@test01v ~/codedeploy]$ vim conf.sh 177 | 178 | EXEC_HOSTS='test01v.add.net 127.0.0.1' # 多个主机之间用空格分割 179 | SSH_USER='public_user' # 部署代码, 用到的用户, 整个系统通用 180 | ``` 181 | 182 | ###### 执行结果如下: 183 | ```Bash 184 | [test@test01v ~/codedeploy]$ sh exec.sh 'hostname' debug 185 | 186 | ============== 服务器列表(开始) ============== 187 | 188 | 1. test01v.add.net 189 | 2. 127.0.0.1 190 | 191 | ============== 服务器列表(结束) ============== 192 | 193 | 确认服务器列表? [y/n]: y 194 | 195 | 1. [ test01v.add.net ] 196 | 197 | test01v.add.net 198 | 199 | 2. [ 127.0.0.1 ] 200 | 201 | test02v.add.net 202 | 203 | [result] 机器数量: 2 Done! 204 | ``` 205 | 206 | ##### 2.8 集群与机器一对一怎么配置 207 | 208 | 这里假设有 8 台 QA机器,而且需要一对一推送场景。也就是说代码只部署其中一台QA机器; 209 | 210 | ```Bash 211 | [test@test01v ~/codedeploy]$ vim conf.sh 212 | 213 | number=8 214 | 215 | for ((i = 1; i <= $number; i++)) 216 | do 217 | project_name[$i]="wifi.360.cn" 218 | online[$i]="" 219 | worker[$i]="" 220 | local_web_path[$i]=`dirname $DEPLOY_DIRECTORY` 221 | remote_web_path[$i]="/home/www/"${project_name[$i]} 222 | done 223 | 224 | qa[1]="test01v.hostname" 225 | qa[2]="test02v.hostname" 226 | qa[3]="test03v.hostname" 227 | qa[4]="test04v.hostname" 228 | qa[5]="test05v.hostname" 229 | qa[6]="test06v.hostname" 230 | qa[7]="test07v.hostname" 231 | qa[8]="test08v.hostname" 232 | ``` 233 | 234 | 向 QA 1 服务器推送代码 235 | ```Bash 236 | sh deploy/deploy-qa.sh master 1 237 | ``` 238 | 239 | 向 QA 2 服务器推送代码,以此类推 240 | ```Bash 241 | sh deploy/deploy-qa.sh master 2 242 | ``` 243 | 244 | ## 3. 特别感谢 245 | 246 | 蔡玉光 247 | 248 | ## 4. 联系我们 249 | 250 | [codedeploy 官网] (http://www.cdvphp.com/wiki/index.php?title=Cd_start) 251 | [Team: 随时随地,手机免费上网] (http://wifi.360.cn/) 252 | -------------------------------------------------------------------------------- /cecho.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # source me in your script or .bashrc/.zshrc if wanna use cecho 4 | # source '/path/to/cecho.sh' 5 | 6 | # check this var to detect "cecho" being imported 7 | CECHO_IS_IMPORTED=1 8 | 9 | cecho() 10 | { 11 | #FOREGROUND 12 | 13 | local FG_BLACK="\e[30m" 14 | local FG_RED="\e[31m" 15 | local FG_GREEN="\e[32m" 16 | local FG_YELLOW="\e[33m" 17 | local FG_BLUE="\e[34m" 18 | local FG_PURPLE="\e[35m" 19 | local FG_CYAN="\e[36m" 20 | local FG_WHITE="\e[37m" 21 | 22 | #BACKGROUND 23 | 24 | local BG_BLACK="\e[40m" 25 | local BG_RED="\e[41m" 26 | local BG_GREEN="\e[42m" 27 | local BG_YELLOW="\e[43m" 28 | local BG_BLUE="\e[44m" 29 | local BG_PURPLE="\e[45m" 30 | local BG_CYAN="\e[46m" 31 | local BG_WHITE="\e[47m" 32 | 33 | #ACTION 34 | 35 | local DONE="\e[0m" 36 | local HIGHLIGHT="\e[1m" 37 | local UNDERLINE="\e[4m" 38 | local BLINK="\e[5m" 39 | local REVERSE="\e[7m" 40 | local INVISIBLE="\e[8m" 41 | 42 | # for Bash compatibility 43 | 44 | local WS="\\ " 45 | 46 | # for self-adapting: inactive if output is pipe/file, active if screen 47 | 48 | local CECHO_IS_INACTIVE_INTL=$CECHO_IS_INACTIVE 49 | if [ ! -t 1 ] 50 | then 51 | CECHO_IS_INACTIVE_INTL=1 52 | fi 53 | 54 | # for keeping format when inactive 55 | 56 | local IS_NEED_BLANK= 57 | local INTL_SINGLE_BLANK= 58 | 59 | # other 60 | 61 | local msg= 62 | 63 | local version_info='cecho \ 64 | cecho -B 0.2 -B "" -n \ 65 | Written -B by -B Springlie -B ""' 66 | 67 | local help_info='cecho \ 68 | -r -hl -re -t -t -t -t "the page is generated by" -B -bl "cecho" -d -r -hl -re -t -t -t -t -d -n \ 69 | -hl Usage: -d -n \ 70 | -t "a light and simple wrapper of echo, with colour flags." -d -n -n \ 71 | -hl Syntax: -d -n \ 72 | -t -g -hl cecho -d -B -y -color1 -B -b message1 -w -B "[ -color2 message2 ... ]" -r -B "[ -done ]" -d -n \ 73 | -t -g -hl cecho -d -B -y -fg_color -B -p -bg_color -B -c -action -B -b message -B -w "[...]" -B -r "[ -done ]" -d -n -n \ 74 | -hl "ForeGround color flag:" -d -n \ 75 | -t -r "-r | -red" -t -g "-g | -green" -t -y "-y | -yellow" -t -bk -bw "-bk | -black" -d "(here with white bg)" -d -n \ 76 | -t -b "-b | -blue" -t -p "-p | -purple" -t -c "-c | -cyan" -t -w "-w | -gr | -white | -gray" -d -n -n \ 77 | -hl "BackGround color flag:" -d -n \ 78 | -t -br "-br | -b_red" -t -bg "-bg | -b_green" -t -by "-by | -b_yellow" -t -bbk "-bbk | -b_black" -d -n \ 79 | -t -bb "-bb | -b_blue" -t -bp "-bp | -b_purple" -t -bc "-bc | -b_cyan" -t -bw "-bw | -bgr | -b_white | -b_gray" -d -n -n \ 80 | -hl "Action flag:" -d -n \ 81 | -t "-d | -done" -t -hl "-hl | -highlight" -d -t -ul "-ul | -underline" -d -t -re "-re | -reverse" -d -n \ 82 | -t -bl "-bl | -blink" -d -t "[ there is invisible here ]" -t "-->" -iv "-iv | -invisible" -d "<--" -n -n \ 83 | -hl "Escaped character:" -d -n \ 84 | -t "-B | -blank" -t "-t | -tab" -t "-n | -newline" -d -n \ 85 | -g -hl -re -t -t -t -t "the src of above (as an example)" -t -t -t -d' 86 | 87 | # main looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooop 88 | 89 | while (($#!=0)) 90 | do 91 | 92 | # set internal single blank(avoid duplicate blanks in inactive mode) 93 | 94 | if [ -z $IS_NEED_BLANK ] 95 | then 96 | INTL_SINGLE_BLANK="" 97 | else 98 | INTL_SINGLE_BLANK=" " 99 | fi 100 | 101 | IS_NEED_BLANK= 102 | 103 | 104 | # switch 105 | 106 | case $1 in 107 | 108 | # escape character 109 | 110 | -B|-blank |$WS-B|$WS-blank )msg+=" "; ;; 111 | -t|-tab |$WS-t|$WS-tab )msg+="\t"; ;; 112 | -n|-newline|$WS-n|$WS-newline)msg+="\n"; ;; 113 | #-t| -tab ) msg+=`[ -z $CECHO_IS_INACTIVE_INTL ] && echo "\t" || echo $INTL_SINGLE_BLANK`; ;; 114 | #-n| -newline ) [ -z $CECHO_IS_INACTIVE_INTL ] && msg+="\n" || msg+=$INTL_SINGLE_BLANK; ;; 115 | 116 | # foreground color 117 | 118 | -bk|-black |$WS-bk|$WS-black )msg+=`[ -z $CECHO_IS_INACTIVE_INTL ] && echo $FG_BLACK || echo $INTL_SINGLE_BLANK`; ;; 119 | -r |-red |$WS-r |$WS-red )msg+=`[ -z $CECHO_IS_INACTIVE_INTL ] && echo $FG_RED || echo $INTL_SINGLE_BLANK`; ;; 120 | -g |-green |$WS-g |$WS-green )msg+=`[ -z $CECHO_IS_INACTIVE_INTL ] && echo $FG_GREEN || echo $INTL_SINGLE_BLANK`; ;; 121 | -y |-yellow|$WS-y |$WS-yellow)msg+=`[ -z $CECHO_IS_INACTIVE_INTL ] && echo $FG_YELLOW|| echo $INTL_SINGLE_BLANK`; ;; 122 | -b |-blue |$WS-b |$WS-blue )msg+=`[ -z $CECHO_IS_INACTIVE_INTL ] && echo $FG_BLUE || echo $INTL_SINGLE_BLANK`; ;; 123 | -p |-purple|$WS-p |$WS-purple)msg+=`[ -z $CECHO_IS_INACTIVE_INTL ] && echo $FG_PURPLE|| echo $INTL_SINGLE_BLANK`; ;; 124 | -c |-cyan |$WS-c |$WS-cyan )msg+=`[ -z $CECHO_IS_INACTIVE_INTL ] && echo $FG_CYAN || echo $INTL_SINGLE_BLANK`; ;; 125 | -w |-white |$WS-w |$WS-white )msg+=`[ -z $CECHO_IS_INACTIVE_INTL ] && echo $FG_WHITE || echo $INTL_SINGLE_BLANK`; ;; 126 | -gr|-gray |$WS-gr|$WS-gray )msg+=`[ -z $CECHO_IS_INACTIVE_INTL ] && echo $FG_WHITE || echo $INTL_SINGLE_BLANK`; ;; 127 | 128 | # background color 129 | 130 | -bbk|-b_black |$WS-bbk|$WS-b_black )msg+=`[ -z $CECHO_IS_INACTIVE_INTL ] && echo $BG_BLACK || echo $INTL_SINGLE_BLANK`; ;; 131 | -br |-b_red |$WS-br |$WS-b_red )msg+=`[ -z $CECHO_IS_INACTIVE_INTL ] && echo $BG_RED || echo $INTL_SINGLE_BLANK`; ;; 132 | -bg |-b_green |$WS-bg |$WS-b_green )msg+=`[ -z $CECHO_IS_INACTIVE_INTL ] && echo $BG_GREEN || echo $INTL_SINGLE_BLANK`; ;; 133 | -by |-b_yellow|$WS-by |$WS-b_yellow)msg+=`[ -z $CECHO_IS_INACTIVE_INTL ] && echo $BG_YELLOW|| echo $INTL_SINGLE_BLANK`; ;; 134 | -bb |-b_blue |$WS-bb |$WS-b_blue )msg+=`[ -z $CECHO_IS_INACTIVE_INTL ] && echo $BG_BLUE || echo $INTL_SINGLE_BLANK`; ;; 135 | -bp |-b_purple|$WS-bp |$WS-b_purple)msg+=`[ -z $CECHO_IS_INACTIVE_INTL ] && echo $BG_PURPLE|| echo $INTL_SINGLE_BLANK`; ;; 136 | -bc |-b_cyan |$WS-bc |$WS-b_cyan )msg+=`[ -z $CECHO_IS_INACTIVE_INTL ] && echo $BG_CYAN || echo $INTL_SINGLE_BLANK`; ;; 137 | -bw |-b_white |$WS-bw |$WS-b_white )msg+=`[ -z $CECHO_IS_INACTIVE_INTL ] && echo $BG_WHITE || echo $INTL_SINGLE_BLANK`; ;; 138 | -bgr|-b_gray |$WS-bgr|$WS-b_gray )msg+=`[ -z $CECHO_IS_INACTIVE_INTL ] && echo $BG_WHITE || echo $INTL_SINGLE_BLANK`; ;; 139 | 140 | # action, some can be overlaid 141 | 142 | -d |-done |$WS-d |$WS-done )msg+=`[ -z $CECHO_IS_INACTIVE_INTL ] && echo $DONE || echo $INTL_SINGLE_BLANK`; ;; 143 | -hl|-highlight|$WS-hl|$WS-highlight)msg+=`[ -z $CECHO_IS_INACTIVE_INTL ] && echo $HIGHLIGHT|| echo $INTL_SINGLE_BLANK`; ;; 144 | -ul|-underline|$WS-ul|$WS-underline)msg+=`[ -z $CECHO_IS_INACTIVE_INTL ] && echo $UNDERLINE|| echo $INTL_SINGLE_BLANK`; ;; 145 | -bl|-blink |$WS-bl|$WS-blink )msg+=`[ -z $CECHO_IS_INACTIVE_INTL ] && echo $BLINK || echo $INTL_SINGLE_BLANK`; ;; 146 | -re|-reverse |$WS-re|$WS-reverse )msg+=`[ -z $CECHO_IS_INACTIVE_INTL ] && echo $REVERSE || echo $INTL_SINGLE_BLANK`; ;; 147 | -iv|-invisible|$WS-iv|$WS-invisible)msg+=`[ -z $CECHO_IS_INACTIVE_INTL ] && echo $INVISIBLE|| echo $INTL_SINGLE_BLANK`; ;; 148 | 149 | # functional 150 | 151 | -v|-version|--version|$WS-v|$WS-version|$WS--version) 152 | eval $version_info 153 | return 0 154 | ;; 155 | 156 | -h|-help|--help|$WS-h|$WS-help|$WS--help) 157 | eval $help_info 158 | 159 | if [ $0 "==" "bash" ] 160 | then 161 | echo $help_info | sed -r 's/\\/\\\n/g' 162 | else 163 | echo $help_info 164 | fi 165 | 166 | return 0 167 | ;; 168 | 169 | # string 170 | 171 | *) 172 | msg=$msg$1 173 | 174 | # reset 175 | 176 | IS_NEED_BLANK=1 177 | ;; 178 | 179 | esac 180 | shift 181 | done 182 | 183 | # clear 184 | 185 | msg=$DONE$msg$DONE 186 | 187 | # print 188 | 189 | echo -e $msg 190 | } 191 | -------------------------------------------------------------------------------- /clean-log.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # --------------------------------------------------------------- 3 | # 清理用户登录日志 & 命令记录 4 | # 5 | # Filename: clean-log.sh 6 | # Copyright: (c) 2016 360 Free WiFi Team. (http:://wifi.360.cn) 7 | # License: http://www.apache.org/licenses/LICENSE-2.0 8 | # --------------------------------------------------------------- 9 | 10 | # 系统的每一次登录, 二进制文件 11 | # view: last -f /var/log/wtmp 12 | echo > /var/log/wtmp 13 | 14 | # 件记录错误的登录尝试 15 | # view: lastb -f /var/log/btmp 16 | echo > /var/log/btmp 17 | 18 | # 如果没有这个文件, 重启syslog进程service syslog restart 19 | echo > /var/log/secure 20 | echo > .bash_history 21 | 22 | # 清除命令记录 23 | history -c 24 | 25 | 26 | echo 'clean log omplete!' 27 | -------------------------------------------------------------------------------- /conf.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # ------------------------------------------------------ 3 | # 基础配置文件 4 | # 5 | # Filename: conf.sh 6 | # Copyright: (c) 2016 360 Free WiFi Team. (http:://wifi.360.cn) 7 | # License: http://www.apache.org/licenses/LICENSE-2.0 8 | # --------------------------------------------------------------- 9 | 10 | # 如果会话是gbk, 请修改成gbk编码 11 | export LANGUAGE="utf-8" 12 | 13 | # 部署代码, 用到的用户, 整个系统通用 14 | SSH_USER="public360" 15 | 16 | # 所有用户: 本地上传代码时过滤这些文件或者文件夹, 支持通配符 17 | BLACKLIST="*.log *.tmp *.svn.* *.swp /ENV /logs .gitignore .git" 18 | 19 | # 本地、远程推送tar包保存时间(单位: 天), 支持小数、整数 20 | # 推送代码中自动delete超过配置项时间的tar包 21 | TAR_KEEP_TIME=10 22 | 23 | # -------------------- 多服务端命令行搜索 start -------------------- 24 | # (可配置) 主机列表; 多个主机名称以空格分割(可以填写 IP地址、hostname) 25 | 26 | EXEC_HOSTS='aaa.host.1 bbb.host.2 ccc.host.3' 27 | 28 | # -------------------- 多服务端命令行搜索 end -------------------- 29 | 30 | # -------------------- 项目1 git模式例子 带注释 -------------------- 31 | # 项目名称, 推送到远端机器会自动创建的文件夹名字 32 | # 推送代码的方式 33 | # git 基于git做代码的打包操作 34 | # file 基于文本文件的打包操作 35 | number=1 36 | project_name[$number]="test.codedeploy.cn" 37 | 38 | # 推送的机器, 可以填写IP地址、hostname 多台机器以空格分割 39 | online[$number]="" 40 | 41 | # 顾名思义, 这是测试机器了 42 | qa[$number]="test01v.ccc.hostname.net" 43 | 44 | # 顾名思义, 这是worker机器了 45 | worker[$number]="" 46 | 47 | # 项目本地跟目录, 权限(wr) 48 | local_web_path[$number]="/home/fanjiapeng/api" 49 | 50 | # 项目部署到远端机器的目录, 前提这个目录有读写(wr)权限 51 | remote_web_path[$number]="/home/web/test/${project_name[1]}" 52 | 53 | # -------------------- 项目5 git模式例子 -------------------- 54 | number=2 55 | project_name[$number]="test1.360.cn" 56 | online[$number]="ot.hostname" 57 | qa[$number]="qa.test1.360.cn" 58 | worker[$number]="" 59 | local_web_path[$number]="/home/fanjiapeng/project/conf" 60 | remote_web_path[$number]="/home/web/${project_name[$number]}" 61 | 62 | -------------------------------------------------------------------------------- /core.rsync.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # --------------------------------------------------------------- 3 | # 核心文件 4 | # 5 | # Filename: core.sh 6 | # Copyright: (c) 2016 360 Free WiFi Team. (http:://wifi.360.cn) 7 | # License: http://www.apache.org/licenses/LICENSE-2.0 8 | # --------------------------------------------------------------- 9 | 10 | # 配置项 11 | FILENAME=$0 12 | 13 | # load function 14 | DEPLOY_DIRECTORY=`dirname $FILENAME` 15 | . $DEPLOY_DIRECTORY/cecho.sh 16 | . $DEPLOY_DIRECTORY/function.sh 17 | 18 | # 当前部署代码的模式 19 | current_method="rsync" 20 | 21 | # 获取参数 22 | params_1=$1 23 | 24 | # help 25 | if [ -z "$params_1"] || [ "$params_1" == "-h" ] || [ "$params_1" == "-help" ] || [ "$params_1" == "--h" ] || [ "$params_1" == "--help" ]; then 26 | showHelpRsync 27 | fi 28 | 29 | # 输出当前的模式 30 | if [ `isInt $params_1` == 0 ]; then 31 | cecho -n -hl "[rsync模式] - [环境 ${params_1}]" -n 32 | else 33 | showHelpRsync 34 | fi 35 | 36 | # load function 37 | . $DEPLOY_DIRECTORY/conf.sh 38 | . $DEPLOY_DIRECTORY/init.sh 39 | 40 | # 初始化 41 | init 42 | 43 | hosts=${rsync[$params_1]} 44 | 45 | # 检查机器列表 46 | if [ -z "$hosts" ]; then 47 | cecho -r "没有正确配置可用机器列表" -n 48 | exit -1 49 | fi 50 | 51 | # 黑名单 52 | exclude="" 53 | for back_list in $BLACKLIST 54 | do 55 | exclude=" ${exclude} --exclude=${back_list}" 56 | done 57 | unset back_list 58 | 59 | # 计数器 60 | INT_COUNT_FAILED=0 61 | INT_COUNT_SUCCESS=0 62 | no=0 63 | ARR_FAILED_HOST='' 64 | filesize=0; 65 | 66 | # 上一次部署失败log 67 | last_failed_publish="${LOCAL_CODEDEPLOY_TMP_DIR}/${project_name[$params_1]}/failed.${CURRENT_ACTION}" 68 | 69 | # -------------------------- 检查上次部署失败情况 (start) ------------- 70 | checkLastPublish $last_failed_publish 71 | # -------------------------- 检查上次部署失败情况 (end) --------------- 72 | 73 | # -------------------------- 开始上传代码 (start) -------------------------- 74 | no=0; 75 | for host in $hosts 76 | do 77 | no=`echo "$no + 1" | bc` 78 | 79 | cecho $no". " -c "$host" -w " => 代码同步中 ... ..." 80 | 81 | start_time=`getMsTime` 82 | msg=`$RSYNC -tIpgocrvl --delay-updates --timeout=60 $exclude ${local_web_path[$params_1]}/ ${SSH_USER}@${host}:${remote_web_path[$params_1]}/ 2>&1` 83 | end_time=`getMsTime` 84 | end_time=$((end_time - start_time)) 85 | 86 | result=`echo $msg | grep -i 'error' | wc -L` 87 | 88 | if [ "$result" == 0 ]; then 89 | cecho $no". " -c "$host" -w " => 代码同步" -g "成功" -w ": ${remote_web_path[$params_1]}/" 90 | cecho $no". " -c "$host" -w " => 耗时: " $(checkSpeed $end_time) 91 | else 92 | cecho $no". " -c "$host" -w " => 代码同步" -r "失败" -w ": ${remote_web_path[$params_1]}/" -n 93 | cecho "失败原因:" 94 | cecho -r "${msg}" 95 | 96 | INT_COUNT_FAILED=$((INT_COUNT_FAILED + 1)) 97 | if [ ! -z "${host}" ]; then 98 | ARR_FAILED_HOST="${ARR_FAILED_HOST} ${host}" 99 | fi 100 | continue 101 | fi 102 | 103 | INT_COUNT_SUCCESS=$((INT_COUNT_SUCCESS + 1)) 104 | 105 | echo "" 106 | done 107 | 108 | # 显示部署代码的结果 109 | if [ $INT_COUNT_FAILED -eq 0 ] && [ $INT_COUNT_SUCCESS -gt 0 ]; then 110 | cecho -n -w "[" -g "result" -w "] 机器数量: " -g $INT_COUNT_SUCCESS -w " 全部部署" -g "成功!" 111 | clearLogFile $last_failed_publish 112 | elif [ $INT_COUNT_SUCCESS -gt 0 ]; then 113 | cecho -n -w "[" -g "result" -w "] 机器数量: " -g $INT_COUNT_SUCCESS -w " 部分机器部署" -g "成功!" 114 | fi 115 | 116 | if [ $INT_COUNT_FAILED -gt 0 ]; then 117 | cecho -n -w "[" -r "result" -w "] 机器数量: " -r $INT_COUNT_FAILED -w " 部署失败机器如下:" -n 118 | i=0 119 | for host in $ARR_FAILED_HOST 120 | do 121 | i=$((i + 1)) 122 | cecho -w "${i}. " $host -w " => " -r "失败 !" 123 | done 124 | 125 | #写入失败文件 126 | writeLogFile $last_failed_publish "${ARR_FAILED_HOST}" 127 | fi 128 | 129 | echo "" 130 | 131 | -------------------------------------------------------------------------------- /core.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # --------------------------------------------------------------- 3 | # 核心文件 4 | # 5 | # Filename: core.sh 6 | # Copyright: (c) 2016 360 Free WiFi Team. (http:://wifi.360.cn) 7 | # License: http://www.apache.org/licenses/LICENSE-2.0 8 | # --------------------------------------------------------------- 9 | 10 | # 配置项 11 | FILENAME=$0 12 | 13 | # load function 14 | DEPLOY_DIRECTORY=`dirname $FILENAME` 15 | . $DEPLOY_DIRECTORY/cecho.sh 16 | . $DEPLOY_DIRECTORY/function.sh 17 | 18 | # 当前部署代码的模式 19 | current_method="" 20 | 21 | # 获取参数 22 | params_1=$1 23 | params_2=$2 24 | 25 | # help 26 | if [ "$params_1" == "-h" ] || [ "$params_1" == "-help" ] || [ "$params_1" == "--h" ] || [ "$params_1" == "--help" ]; then 27 | showHelp 28 | fi 29 | 30 | # 输出当前的模式 31 | if [ $# == 2 ] && [ "$params_1" == "file" ]; then 32 | current_method="file" 33 | cecho -n -hl "[file模式 + ${CURRENT_ACTION}${params_2} 环境]" -n 34 | elif [ $# == 2 ] && [ `isInt $params_2` == 0 ] && [ "$params_1" == "clean" ]; then 35 | cecho -n -hl "[${CURRENT_ACTION}${params_2} 环境] - [执行操作 ${params_1}]" -n 36 | current_method="git" 37 | elif [ $# == 2 ] && [ `isInt $params_2` == 0 ]; then 38 | cecho -n -hl "[git模式] - [${CURRENT_ACTION}${params_2} 环境] - [推送分支 ${params_1}]" -n 39 | current_method="git" 40 | else 41 | showHelp 42 | fi 43 | 44 | # load function 45 | . $DEPLOY_DIRECTORY/conf.sh 46 | . $DEPLOY_DIRECTORY/init.sh 47 | 48 | # 初始化 49 | LOCAL_CODEDEPLOY_TMP_DIR="${LOCAL_CODEDEPLOY_TMP_DIR}/${project_name[$params_2]}" 50 | init 51 | 52 | if [ "$CURRENT_ACTION" == "qa" ]; then 53 | hosts=${qa[$params_2]} 54 | elif [ "$CURRENT_ACTION" == "worker" ]; then 55 | hosts=${worker[$params_2]} 56 | else 57 | hosts=${online[$params_2]} 58 | fi 59 | 60 | # 检查机器列表 61 | if [ -z "$hosts" ]; then 62 | cecho -r "没有正确配置可用机器列表" -n 63 | exit -1 64 | fi 65 | 66 | # 黑名单 67 | exclude="" 68 | for back_list in $BLACKLIST 69 | do 70 | exclude=" ${exclude} --exclude=${back_list}" 71 | done 72 | unset back_list 73 | 74 | # 计数器 75 | INT_COUNT_FAILED=0 76 | INT_COUNT_SUCCESS=0 77 | no=0 78 | ARR_FAILED_HOST='' 79 | filesize=0; 80 | 81 | # 上一次部署失败log 82 | last_failed_publish="${LOCAL_CODEDEPLOY_TMP_DIR}/failed.${CURRENT_ACTION}" 83 | 84 | # --------------------- 清理本地超限时间包 (start) --------------------- 85 | findDelCtime $LOCAL_CODEDEPLOY_TMP_DIR 86 | # --------------------- 清理本地超限时间包 (end) ----------------------- 87 | 88 | # -------------------------- 释放环境 (start) -------------------------- 89 | if [ "$params_1" == "clean" ]; then 90 | for host in $hosts 91 | do 92 | no=$(($no + 1)) 93 | checkLastUpdateUser 94 | 95 | $SSH $host "echo "" > ${REMOTE_CODEDEPLOY_ALLUSER_LOG} 2>/dev/null" 96 | 97 | if [ $? != 0 ]; then 98 | cecho $no". " -c "${host}" -w " => " -r "环境释放失败!" 99 | else 100 | clearLogFile $last_failed_publish 101 | cecho $no". " -c "${host}" -w " => " -g "环境释放成功." 102 | fi 103 | 104 | done 105 | 106 | echo "" 107 | exit 0 108 | fi 109 | # -------------------------- 释放环境 (end) --------------------------- 110 | 111 | # -------------------------- 检查上次部署失败情况 (start) ------------- 112 | checkLastPublish $last_failed_publish 113 | # -------------------------- 检查上次部署失败情况 (end) --------------- 114 | 115 | # -------------------------- 打包代码 (start) -------------------------- 116 | CURRENT_TIME=`getTime` 117 | file_name="codedeploy_${project_name[$params_2]}_${params_1}_${CURRENT_TIME}.tar.gz" 118 | local_directory_package="${LOCAL_CODEDEPLOY_TMP_DIR}/${file_name}" 119 | 120 | cecho -w "本地配置 [$params_2] 开始打包 ... ..." 121 | 122 | # 非commit时, git archive错误提示: "fatal: current working directory is untracked" 123 | # commit时, git archive 正确 124 | # 兼容两种情况 125 | # --verbose 126 | if [ $current_method == "git" ]; then 127 | cd ${local_web_path[$params_2]} && git archive --format=tar.gz $params_1 -o $local_directory_package 128 | else 129 | cd ${local_web_path[$params_2]} && tar -zcf $local_directory_package . ${exclude} 130 | fi 131 | 132 | if [ ! -s "$local_directory_package" ]; then 133 | echo "本地配置 [$params_2] 打包失败!" 134 | exit -1 135 | fi 136 | 137 | filesize=`getFileSize $local_directory_package` 138 | cecho -w "本地配置 [$params_2] 打包" -g "成功" -w ": ${local_directory_package}" 139 | cecho -w "本地配置 [$params_2] 文件大小: " $filesize -n 140 | 141 | # -------------------------- 开始上传代码 (start) -------------------------- 142 | remote_directory_package="${REMOTE_CODEDEPLOY_HISTORY_DIR}/${file_name}" 143 | 144 | no=0; 145 | for host in $hosts 146 | do 147 | no=$(($no + 1)) 148 | checkLastUpdateUser 149 | 150 | if [ -z "$last_update_user" ]; then 151 | $SSH $host "mkdir -p ${REMOTE_CODEDEPLOY_HISTORY_DIR} && mkdir -p ${remote_web_path[$params_2]} 1>/dev/null" 152 | checkExecResult $host 153 | fi 154 | 155 | cecho $no". " -c "$host" -w " => 代码上传中 ... ..." 156 | 157 | start_time=`getMsTime` 158 | $SCP $local_directory_package ${host}:${remote_directory_package} 1>/dev/null 159 | end_time=`getMsTime` 160 | end_time=$((end_time - start_time)) 161 | 162 | checkExecResult $host 163 | 164 | cecho $no". " -c "$host" -w " => 代码上传" -g "成功" -w ": $remote_directory_package" 165 | cecho $no". " -c "$host" -w " => 耗时: " $(checkSpeed $end_time) 166 | 167 | cecho $no". " -c "$host" -w " => 开始解压远程代码包 ... ..." 168 | $SSH $host "tar -zxmf $remote_directory_package ${exclude} -C ${remote_web_path[$params_2]}" 169 | cecho $no". " -c "$host" -w " => 代码解压" -g "成功" -w ": ${remote_web_path[$params_2]}" 170 | 171 | checkExecResult $host 172 | 173 | if [ -z "$last_update_user" ]; then 174 | $SSH $host "echo $USER > $REMOTE_CODEDEPLOY_ALLUSER_LOG" 175 | fi 176 | 177 | $SSH $host "sh ${remote_web_path[$params_2]}/project/autoload_builder.sh 1>/dev/null 2>&1" 178 | if [ $? == 0 ]; then 179 | cecho $no". " -c "$host" -w " => 执行远程autoload_builder脚本" -g "成功" 180 | fi 181 | 182 | cecho $no". " -c "$host" -w " => 清理远程过期的tar包" 183 | $SSH $host "find $REMOTE_CODEDEPLOY_HISTORY_DIR/*.gz -type f -ctime +${TAR_KEEP_TIME} -delete" 184 | 185 | INT_COUNT_SUCCESS=$((INT_COUNT_SUCCESS + 1)) 186 | 187 | echo "" 188 | done 189 | 190 | # 显示部署代码的结果 191 | if [ $INT_COUNT_FAILED -eq 0 ] && [ $INT_COUNT_SUCCESS -gt 0 ]; then 192 | cecho -n -w "[" -g "result" -w "] 机器数量: " -g $INT_COUNT_SUCCESS -w " 全部部署" -g "成功!" 193 | clearLogFile $last_failed_publish 194 | elif [ $INT_COUNT_SUCCESS -gt 0 ]; then 195 | cecho -n -w "[" -g "result" -w "] 机器数量: " -g $INT_COUNT_SUCCESS -w " 部分机器部署" -g "成功!" 196 | fi 197 | 198 | if [ $INT_COUNT_FAILED -gt 0 ]; then 199 | cecho -n -w "[" -r "result" -w "] 机器数量: " -r $INT_COUNT_FAILED -w " 部署失败机器如下:" -n 200 | i=0 201 | for host in $ARR_FAILED_HOST 202 | do 203 | i=$((i + 1)) 204 | cecho -w "${i}. " $host -w " => " -r "失败 !" 205 | done 206 | 207 | #写入失败文件 208 | writeLogFile $last_failed_publish "${ARR_FAILED_HOST}" 209 | fi 210 | 211 | echo "" 212 | 213 | -------------------------------------------------------------------------------- /deploy-ot.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # --------------------------------------------------------------- 3 | # 线上机器、线上测试机器代码部署文件 4 | # 5 | # Filename: deploy-online.sh 6 | # Copyright: (c) 2016 360 Free WiFi Team. (http:://wifi.360.cn) 7 | # License: http://www.apache.org/licenses/LICENSE-2.0 8 | # --------------------------------------------------------------- 9 | 10 | # 配置当前动作 11 | CURRENT_ACTION="ot" 12 | 13 | FILENAME=$0 14 | 15 | DEPLOY_DIRECTORY=`dirname $FILENAME` 16 | 17 | # 开始执行代码部署 18 | . $DEPLOY_DIRECTORY/core.sh 19 | -------------------------------------------------------------------------------- /deploy-qa.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # --------------------------------------------------------------- 3 | # qa机器代码部署文件 4 | # 5 | # Filename: deploy-qa.sh 6 | # Copyright: (c) 2016 360 Free WiFi Team. (http:://wifi.360.cn) 7 | # License: http://www.apache.org/licenses/LICENSE-2.0 8 | # --------------------------------------------------------------- 9 | 10 | # 配置当前动作 11 | CURRENT_ACTION="qa" 12 | 13 | FILENAME=$0 14 | 15 | DEPLOY_DIRECTORY=`dirname $FILENAME` 16 | 17 | # 开始执行代码部署 18 | . $DEPLOY_DIRECTORY/core.sh 19 | -------------------------------------------------------------------------------- /deploy-rsync.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # --------------------------------------------------------------- 3 | # 回归机代码部署文件 4 | # 5 | # Filename: deploy-rsync.sh 6 | # Copyright: (c) 2016 360 Free WiFi Team. (http:://wifi.360.cn) 7 | # License: http://www.apache.org/licenses/LICENSE-2.0 8 | # --------------------------------------------------------------- 9 | 10 | # 配置当前动作 11 | CURRENT_ACTION="rsync" 12 | 13 | FILENAME=$0 14 | 15 | DEPLOY_DIRECTORY=`dirname $FILENAME` 16 | 17 | # 开始执行代码部署 18 | . $DEPLOY_DIRECTORY/core.rsync.sh 19 | -------------------------------------------------------------------------------- /deploy-work.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # --------------------------------------------------------------- 3 | # worker机器代码部署文件 4 | # 5 | # Filename: deploy-worker.sh 6 | # Copyright: (c) 2016 360 Free WiFi Team. (http:://wifi.360.cn) 7 | # License: http://www.apache.org/licenses/LICENSE-2.0 8 | # --------------------------------------------------------------- 9 | 10 | # 配置当前动作, 调用conf.sh里不同的配置项 11 | CURRENT_ACTION="worker" 12 | 13 | FILENAME=$0 14 | 15 | DEPLOY_DIRECTORY=`dirname $FILENAME` 16 | 17 | # 开始执行代码部署 18 | . $DEPLOY_DIRECTORY/core.sh 19 | -------------------------------------------------------------------------------- /exec.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # --------------------------------------------------------------- 3 | # 多服务器命令批量执行脚本 4 | # 5 | # Filename: exec.sh 6 | # Copyright: (c) 2016 360 Free WiFi Team. (http:://wifi.360.cn) 7 | # License: http://www.apache.org/licenses/LICENSE-2.0 8 | # --------------------------------------------------------------- 9 | 10 | FILENAME=$0 11 | 12 | # load function 13 | DEPLOY_DIRECTORY=`dirname $FILENAME` 14 | . $DEPLOY_DIRECTORY/function.sh 15 | . $DEPLOY_DIRECTORY/cecho.sh 16 | . $DEPLOY_DIRECTORY/conf.sh 17 | . $DEPLOY_DIRECTORY/init.sh 18 | 19 | # 使用帮助 20 | if [ $# -lt 1 ] || [ "-h" = "$1" ] || [ "--help" = "$1" ]; then 21 | showHelpByExec 22 | fi 23 | 24 | if [ $# == 2 ] &&[ "$2" == "debug" ]; then 25 | # 确认服务器列表 26 | cecho -n "============== 服务器列表(开始) ==============" -n 27 | no=0; 28 | for host in $EXEC_HOSTS 29 | do 30 | no=`echo "$no + 1" | bc` 31 | cecho $no". " -c "$host" 32 | INT_COUNT_SUCCESS=$((INT_COUNT_SUCCESS + 1)) 33 | done 34 | cecho -n "============== 服务器列表(结束) ==============" -n 35 | fi 36 | 37 | confirm "确认服务器列表?" 38 | 39 | # $? 上一个命令的退出码 40 | if [ 1 != $? ]; then 41 | if [ $# == 2 ] &&[ "$2" == "debug" ]; then 42 | cecho -n "[" -p "result" -w "] 机器数量: " -g $INT_COUNT_SUCCESS -p " 放弃了本次操作!" -n 43 | fi 44 | exit 0; 45 | fi 46 | 47 | INT_COUNT_SUCCESS=0; 48 | # 开始批处理执行命令 49 | for host in $EXEC_HOSTS 50 | do 51 | if [ $# == 2 ] &&[ "$2" == "debug" ]; then 52 | INT_COUNT_SUCCESS=$((INT_COUNT_SUCCESS + 1)) 53 | cecho -n -w $INT_COUNT_SUCCESS". [ " -c "$host" -w " ]" -n 54 | $SSH $host "$1" 55 | else 56 | $SSH $host "$1" 57 | fi 58 | done 59 | 60 | if [ $# == 2 ] &&[ "$2" == "debug" ]; then 61 | cecho -n -g "[" -g "result" -w "] 机器数量: " -g $INT_COUNT_SUCCESS -w " Done!" -n 62 | fi 63 | 64 | -------------------------------------------------------------------------------- /function.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # --------------------------------------------------------------- 3 | # 公共函数库 4 | # 5 | # Filename: function.sh 6 | # Copyright: (c) 2016 360 Free WiFi Team. (http:://wifi.360.cn) 7 | # License: http://www.apache.org/licenses/LICENSE-2.0 8 | # --------------------------------------------------------------- 9 | 10 | # 帮助说明 11 | function showHelp() 12 | { 13 | cecho -n -hl "[HELP]" -n 14 | cecho "git 模式用法:" 15 | cecho -g "sh deploy-qa.sh 分支名称 集群编号" 16 | cecho -g "sh deploy-ot.sh 分支名称 集群编号" 17 | cecho -g "sh deploy-worker.sh 分支名称 集群编号" 18 | cecho "" 19 | cecho "file 模式用法:" 20 | cecho -g "sh deploy-qa.sh file 集群编号" 21 | cecho -g "sh deploy-ot.sh file 集群编号" 22 | cecho -g "sh deploy-worker.sh file 集群编号" 23 | cecho "" 24 | cecho "两种模式通用, 释放当前用户占用机器例子:" 25 | cecho -g "sh deploy-qa.sh clean 集群编号" 26 | cecho -g "sh deploy-ot.sh clean 集群编号" 27 | cecho -g "sh deploy-worker.sh clean 集群编号" 28 | cecho "" 29 | cecho "git模式部署代码例子:" 30 | cecho "将分支dev推送到 [ $CURRENT_ACTION 1 ] 单台机器/集群:" -g " sh deploy-${CURRENT_ACTION}.sh dev 1" 31 | cecho "将分支dev推送到 [ $CURRENT_ACTION 2 ] 单台机器/集群:" -g " sh deploy-${CURRENT_ACTION}.sh dev 2" 32 | cecho "" 33 | cecho "file模式部署代码例子:" 34 | cecho "把/www/deploy.cn目录下的全部文件推送到 [ $CURRENT_ACTION 1 ] 单台机器/集群:" -g " sh deploy-${CURRENT_ACTION}.sh file 1" 35 | cecho "把/www/deploy.cn目录下的全部文件推送到 [ $CURRENT_ACTION 2 ] 单台机器/集群:" -g " sh deploy-${CURRENT_ACTION}.sh file 2" 36 | cecho -n -r "注意: 建议把部署系统全部代码解压到 git 项目根目录!" -n 37 | exit 0 38 | } 39 | 40 | # rsync模式帮助说明 41 | function showHelpRsync() 42 | { 43 | cecho -n -hl "[HELP]" -n 44 | cecho "rsync 模式用法:" -g " sh deploy-rsync.sh 集群编号" 45 | cecho -n -r "注意: rsync模式常用于回归机同步代码到线上机器,不提供clean操作!" -n 46 | exit 0 47 | } 48 | 49 | # 帮助说明 exec.sh 50 | function showHelpByExec() 51 | { 52 | cecho -n -hl "[HELP]" -n 53 | cecho "说明: 通过公共授权账户, 多服务器执行批处理命令脚本" 54 | cecho "参数: 第一个参数要用双引号包起来; 第二个参数等于debug开启调试模式" 55 | cecho "" 56 | cecho "第一步: 先切换到公共授权账户(如):" -g " sudo su sync_user" 57 | cecho "第二步:" -g " sh exec.sh \"shell 命令语句\"" 58 | cecho "" 59 | cecho "Example #1:" 60 | cecho -g "sh exec.sh \"执行命令语句\"" 61 | cecho "" 62 | cecho "Example #2: (重定向输出到 xxx.log)" 63 | cecho -g "sh exec.sh \"执行命令语句\" > xxx.log" 64 | cecho "" 65 | cecho "Example #3: (开启debug调试模式)" 66 | cecho -g "sh exec.sh \"执行命令语句\" debug" 67 | cecho "" 68 | exit 0 69 | } 70 | 71 | # 初始化 72 | function init() 73 | { 74 | mkdir -p $LOCAL_CODEDEPLOY_TMP_DIR; 75 | chmod 755 $LOCAL_CODEDEPLOY_TMP_DIR 1>/dev/null 2>&1 76 | chmod 755 $LOCAL_CODEDEPLOY_TMP_DIR/.. 1>/dev/null 2>&1 77 | } 78 | 79 | # 获取当前系统时间 80 | function getTime() 81 | { 82 | date +%Y%m%d%H%M%S; 83 | } 84 | 85 | # 获取ms时间戳 86 | function getMsTime() 87 | { 88 | local current=`date "+%Y-%m-%d %H:%M:%S"` #获取当前系统时间 89 | local timestamp=`date -d "$current" +%s` #将current转换为时间戳,精确到秒 90 | local current_timestamp=$((timestamp * 1000 + 10#`date "+%N"` / 1000000)) #将current转换为时间戳,精确到毫秒 91 | echo $current_timestamp 92 | } 93 | 94 | # 判断上一次执行的结果 95 | function checkExecResult() 96 | { 97 | if [ $? != 0 ]; then 98 | INT_COUNT_FAILED=$((INT_COUNT_FAILED + 1)) 99 | if [ ! -z "$1" ]; then 100 | ARR_FAILED_HOST="${ARR_FAILED_HOST} ${1}" 101 | fi 102 | continue 103 | fi 104 | } 105 | 106 | # check user 107 | function checkLastUpdateUser() 108 | { 109 | last_update_user=`$SSH $host "tail -n 1 ${REMOTE_CODEDEPLOY_ALLUSER_LOG} 2>/dev/null"` 110 | if [ ! -z "$last_update_user" ] && [ "$USER" != "$last_update_user" ]; then 111 | cecho $no". " -c "${host}" -w " => " -w "环境已经被用户" -r " $last_update_user " -w "占用, 请自行联系协调操作!" 112 | continue 113 | fi 114 | } 115 | 116 | # show method 117 | function showMsg() 118 | { 119 | echo "" 120 | echo "[${1}]" 121 | echo "" 122 | } 123 | 124 | # 判断整数 125 | function isInt() 126 | { 127 | if [[ "$1" =~ ^[0-9]+$ ]]; then 128 | echo 0 129 | else 130 | echo -1 131 | fi 132 | } 133 | 134 | # 检测网速 135 | function checkSpeed() 136 | { 137 | if [ $1 -lt 500 ]; then 138 | echo -w "$1 ms\t[" -g "非常快" -w "]" 139 | elif [ $1 -lt 1000 ]; then 140 | echo -w "$1 ms\t[" -y "中等" -w "]" 141 | else 142 | echo -w "$1 ms\t[" -r "太慢了" -w "]" 143 | fi 144 | } 145 | 146 | # 确认用户的输入 147 | confirm() 148 | { 149 | if [ $LANGUAGE = "utf-8" ] 150 | then 151 | message=$1 152 | else 153 | echo $1 > /tmp/exec_tools_tmp 154 | message=`iconv -f "utf-8" -t $LANGUAGE /tmp/exec_tools_tmp` 155 | rm -f /tmp/exec_tools_tmp 156 | fi 157 | while [ 1 = 1 ] 158 | do 159 | cread -p "$message [y/n]: " CONTINUE 160 | if [ "y" = "$CONTINUE" ]; then 161 | return 1; 162 | fi 163 | 164 | if [ "n" = "$CONTINUE" ]; then 165 | return 0; 166 | fi 167 | done 168 | 169 | return 0; 170 | } 171 | 172 | cread() 173 | { 174 | read $1 "$2" $3 175 | tput sgr0 # Reset to normal. 176 | return 177 | } 178 | 179 | cdate() 180 | { 181 | cdate=`date "+%Y-%m-%d %H:%M:%S"` 182 | cecho " 当前系统时间: $cdate \n" 183 | return 184 | } 185 | 186 | # 写入失败log文件 187 | writeLogFile() 188 | { 189 | echo $2 > $1 190 | } 191 | 192 | # 清理日志文件 193 | clearLogFile() 194 | { 195 | if [ -f $1 ]; then 196 | rm -f $1 197 | fi 198 | } 199 | 200 | # 检查上一次部署是否存在未清理的机器 201 | checkLastPublish() 202 | { 203 | if [ -f $1 ]; then 204 | local failed_rs=`cat $1` 205 | else 206 | return 0 207 | fi 208 | 209 | cecho -r "检测到上一次部署失败的主机 ... ..." 210 | echo "" 211 | 212 | for host in $failed_rs 213 | do 214 | i=$((i + 1)) 215 | cecho -w "${i}. " $host -w " => " -r "失败 !" 216 | done 217 | 218 | echo "" 219 | 220 | while [ 1 = 1 ] 221 | do 222 | cread -p "是否需要处理? [y/n]: " CONTINUE 223 | if [ "y" = "$CONTINUE" ]; then 224 | echo "" 225 | hosts=$failed_rs 226 | return 1; 227 | fi 228 | 229 | if [ "n" = "$CONTINUE" ]; then 230 | echo "" 231 | return 0; 232 | fi 233 | done 234 | } 235 | 236 | # 计算文件大小 237 | getFileSize() 238 | { 239 | if [ -f $1 ]; then 240 | local size=`du -sh $1 | awk '{print $1}'` 241 | echo $size 242 | else 243 | echo 0 244 | fi 245 | } 246 | 247 | # 获取uname 248 | function getOs() 249 | { 250 | uname -s 251 | } 252 | 253 | # ---------------------------------------------------- 254 | # 获取文件列表 255 | # getFileList root_dir blacklist node1 node2 node3 256 | # node 可以是文件,也可以是文件夹 257 | # ---------------------------------------------------- 258 | function getFileList() 259 | { 260 | local files='' 261 | local root_dir="${1}/" 262 | local blists='' 263 | local dir_len=0; 264 | 265 | dir_len=`echo "${root_dir}" | wc -m` 266 | 267 | for blist in $BLACKLIST 268 | do 269 | blists="${blists}|.${blist}" 270 | done 271 | 272 | if [ $(getOs) == "Linux" ] 273 | then 274 | files=`echo "find ${root_dir}./ -regextype posix-extended -type f -not -regex '$blists' | cut -c '$dir_len-1000' | xargs echo" | bash` 275 | else 276 | # FreeBSD 277 | files=`echo "find -E ${root_dir}./ -type f -not -regex '$blists' | cut -c '$dir_len-1000' | xargs echo" | bash` 278 | fi 279 | 280 | echo $files 281 | } 282 | 283 | # find删除多少天之前的创建的文件 284 | findDelCtime() 285 | { 286 | find $1/*.gz -type f -ctime +${TAR_KEEP_TIME} -delete 1>/dev/null 2>&1 287 | } 288 | 289 | -------------------------------------------------------------------------------- /init.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # --------------------------------------------------------------- 3 | # 初始化代码部署系统 4 | # 5 | # Filename: init.sh 6 | # Copyright: (c) 2016 360 Free WiFi Team. (http:://wifi.360.cn) 7 | # License: http://www.apache.org/licenses/LICENSE-2.0 8 | # --------------------------------------------------------------- 9 | 10 | # 关闭SSH-2 GSSAPI认证 & 关闭秘钥记录到known_hosts 11 | SSH="sudo -u ${SSH_USER} ssh -o GSSAPIAuthentication=no -o StrictHostKeyChecking=no" 12 | SCP="sudo -u ${SSH_USER} scp -o GSSAPIAuthentication=no -o StrictHostKeyChecking=no -C" 13 | RSYNC="sudo -u ${SSH_USER} rsync" 14 | 15 | # 所有用户: 保存本地临时文件的公共目录, 所有用户发布的代码都会保存在这里 16 | LOCAL_CODEDEPLOY_TMP_DIR="/tmp/codedeploy_tmp/${USER}" 17 | 18 | # 当前用户: 线上每次收到代码, bak目录地址 19 | REMOTE_CODEDEPLOY_HISTORY_DIR="/home/${SSH_USER}/codedeploy_history/${project_name[$params_2]}" 20 | 21 | # 所有用户: 线上记录最后一次更新的用户名称 22 | REMOTE_CODEDEPLOY_ALLUSER_LOG="${REMOTE_CODEDEPLOY_HISTORY_DIR}/codedeploy_alluser_log" 23 | 24 | # 部署成功的机器数量 25 | INT_COUNT_SUCCESS=0 26 | 27 | # 部署失败的机器数量 28 | INT_COUNT_FAILED=0 29 | 30 | # 部署失败的机器列表 31 | ARR_FAILED_HOST="" 32 | 33 | -------------------------------------------------------------------------------- /version.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # --------------------------------------------------------------- 3 | # 代码部署系统版本号文件 4 | # 5 | # Filename: version.sh 6 | # Copyright: (c) 2016 360 Free WiFi Team. (http:://wifi.360.cn) 7 | # License: http://www.apache.org/licenses/LICENSE-2.0 8 | # --------------------------------------------------------------- 9 | 10 | DEPLOY_DIRECTORY=`dirname $0` 11 | . $DEPLOY_DIRECTORY/cecho.sh 12 | 13 | CODE_DEPLOY_VERSION='1.1.7' 14 | CODE_DEPLOY_UPTIME='2017/07/11' 15 | 16 | cecho -w "This is Codedeploy System." 17 | cecho -w "Version: " -g ${CODE_DEPLOY_VERSION} 18 | cecho -w "LastUptime: " -g ${CODE_DEPLOY_UPTIME} 19 | --------------------------------------------------------------------------------