通過shell腳本實現代碼自動化部署


通過shell腳本實現代碼自動化部署

一、傳統部署方式及優缺點

1.傳統部署方式

1)純手工scp

2)純手工登錄git pullsvn update

3)純手工xftp往上拉

4)開發給打一個壓縮包,rz上去;解壓

2.缺點

1)全程運維參與,占用大量時間

2)上線速度慢

3)人為失誤多,管理混亂

4)回滾慢,不及時

二、環境規划

1、開發環境--開發者本地有自己的環境。

運維需要設置的開發環境,大家共用的服務。

2、測試環境:功能測試環境和性能測試環境。

3、預生產環境:生產環境集群中的某一個節點。

4、生產環境:直接對用戶提供服務的環境。

測試環境與生產環境的數據庫不一致時,可能會導致測試的功能不全面,在測試環境測無問題,放在線上可能出現問題

三、需求分析

一、功能需求需求

一個集群有十個節點

1.實現 一鍵部署10個節點

2.一鍵回滾到任意版本

3.一鍵回滾到上個版本

二、部署需求

部署:

1.代碼在哪里:svngit

2.獲取什么版本代碼?

svn/git:直接拉去某個分支

svn:指定版本號

git:指定tag

3.差異解決:

1)各個節點直接差異:配置文件未必一致(crontab.xml)。預生產節點。

2)代碼倉庫和實際的差異。配置文件是否放在代碼倉庫中。

4.如何更新

更新時需要考慮是否重啟。例如java代碼,需要考慮重啟tomcat。重啟過程中,用戶就不能訪問了。

5.測試

部署多個節點,某個節點由於配置問題導致部署不成功。如何測試。

6.串行和並行

部署多個節點,串行部署還是並行部署,視具體業務需求決定。

7.如何執行

1.shell腳本,直接執行

2.web界面

三、部署流程

1.獲取代碼(直接拉取)---- 2.編譯(可選)---- 3.配置文件放進去---- 4.打包 ---- 

 

5.SCP到目標服務器---- 6.將目標服務器移除集群---- 7.解壓 ---- 8.放置到webroot ----

 

9.SCP差異文件 ---- 10.重啟(可選) ---- 11.測試 ---- 12.加入集群

四、代碼實現

1、設置無交互訪問

通過ssh-keygen將部署機的公鑰發送給應用服務器。

注意,這里通常是用普通用戶登陸部署機,生成公鑰后,再把公鑰發給應用服務器

 

ssh-keygen -t rsa

 

切換到.ssh目錄下

[www@linux-node1 ~/.ssh]$ ll

total 16

-rwx------ 1 www www  397 Jul 31 22:45 authorized_keys

-rwx------ 1 www www 1679 Jul 31 22:44 id_rsa

-rwx------ 1 www www  397 Jul 31 22:44 id_rsa.pub

 

id_rsa.pub中的內容復制粘貼到應用服務器的www用戶的.ssh目錄下,

文件名稱為authorized_keys

 

[www@linux-node2 .ssh]$ cat authorized_keys 

ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCqT3VwY9Wo7tKsXa4Ce1zXGLT/Iygy30tDBKnV4HW4g5BdUS48urTvYljL9cwJ/HWvoqbtJ5mc7PMmhDMOAjIh1CRZtGxKEkQFB/Xp5cLeAsE7iH+WfkNqavFHD75+YuM2mbNBvisDXO+/pJ/QfbmYwWJ6CW6uLpQKpitdJwrLpQDJGQv5H3aV0kHKZdoA+twdXm0LmQcWWJt7zruPq19CAXG5b93KTdgyt/1x4BfcT5/+PCaEd9suYwEneI2Io8CX9oTAe3MRyRPtlN0szT89qP/q+Q4sktVjc1nkxHhdP2mahqeiBLUGULfkgUBtEjaGAFSWb+ejFV0fRDHk6bSJ www@linux-node1

 

注意,修改authorized_keys的權限

chmod 600 authorized_keys

 

另外,將.ssh目錄的權限設置成700

chmod 700 .ssh

2、詳細代碼

 

  1 #!/bin/bash
  2 
  3 #Node List
  4 
  5 PRE_LIST="192.168.56.11"
  6 
  7 GROUP1_LIST="192.168.56.12"
  8 
  9 ROLLBACK_LIST="192.168.56.11 192.168.56.12"
 10 
 11 #Date/Time Variable
 12 
 13 LOG_DATE='date "+%Y-%m-%d"'
 14 
 15 LOG_TIME='date "+%H-%M-%S"'
 16 
 17 CDATE=$(date "+%Y-%m-%d")
 18 
 19 CTIME=$(date "+%H-%M-%S")
 20 
 21 #Shell env
 22 
 23 SHELL_NAME="/deploy1.sh"
 24 
 25 SHELL_DIR="/home/www/"
 26 
 27 SHELL_LOG="${SHELL_DIR}/${SHELL_NAME}.log"
 28 
 29 #Code ENV
 30 
 31 PRO_NAME="web-demo"
 32 
 33 CODE_DIR="/deploy/code/web-demo"
 34 
 35 CONFIG_DIR="/deploy/config/web-demo"
 36 
 37 TMP_DIR="/deploy/tmp"
 38 
 39 TAR_DIR="/deploy/tar"
 40 
 41 LOCK_FILE="/tmp/deploy.lock"
 42 
 43  
 44 
 45 usage(){
 46 
 47          echo $"Usage: $0 {deploy | rollback [ list | version ]} "
 48 
 49 }
 50 
 51  
 52 
 53 writelog(){
 54 
 55          LOGINFO=$1
 56 
 57          echo "${CDATE}${CTIME}: ${SHELL_NAME}: ${LOGINFO} " >> ${SHELL_LOG}
 58 
 59 }
 60 
 61  
 62 
 63  
 64 
 65 shell_lock(){
 66 
 67          touch ${LOCK_FILE}
 68 
 69 }
 70 
 71  
 72 
 73 shell_unlock(){
 74 
 75          rm -f ${LOCK_FILE} 
 76 
 77 }
 78 
 79  
 80 
 81 code_get(){
 82 
 83          writelog "code_get";
 84 
 85          cd $CODE_DIR && echo "git pull";
 86 
 87         cp -r ${CODE_DIR} ${TMP_DIR}/
 88 
 89          API_VER="456"       
 90 
 91 }
 92 
 93  
 94 
 95 code_build(){
 96 
 97          echo code_build
 98 
 99 }
100 
101  
102 
103 code_config(){
104 
105          writelog "code_config"
106 
107          /bin/cp -r ${CONFIG_DIR}/base/* ${TMP_DIR}/"${PRO_NAME}"
108 
109          PKG_NAME="${PRO_NAME}"_"$API_VER"_"${CDATE}-${CTIME}"
110 
111          cd ${TMP_DIR} && mv ${PRO_NAME} ${PKG_NAME}       
112 
113 }
114 
115  
116 
117 code_tar(){
118 
119          writelog "code_tar"
120 
121          cd ${TMP_DIR} && tar czf ${PKG_NAME}.tar.gz $PKG_NAME
122 
123          writelog "${PKG_NAME}.tar.gz"
124 
125 }
126 
127  
128 
129 code_scp(){
130 
131          writelog "code_scp"
132 
133          for node in $PRE_LIST;do
134 
135                  scp ${TMP_DIR}/${PKG_NAME}.tar.gz $node:/opt/webroot
136 
137          done
138 
139          for node in $GROUP1_LIST;do
140 
141                  scp ${TMP_DIR}/${PKG_NAME}.tar.gz $node:/opt/webroot
142 
143          done
144 
145 }
146 
147  
148 
149 cluster_node_remove(){
150 
151          writelog  "cluster_node_remove"
152 
153 }
154 
155  
156 
157 pre_deploy(){
158 
159          writelog "remove from cluster"  
160 
161         ssh $PRE_LIST "cd /opt/webroot && tar zxf ${PKG_NAME}.tar.gz"
162 
163         ssh $PRE_LIST "rm -rf /webroot/web-demo && ln -s /opt/webroot/${PKG_NAME} /webroot/web-demo"
164 
165 }
166 
167 url_test(){
168 
169          URL=$1
170 
171          curl -s --head $URL|grep "200 OK"
172 
173          if [ $? -ne 0 ];then
174 
175                  shell_unlock;
176 
177                  writelog "test error" && exit;
178 
179          fi
180 
181 }
182 
183 pre_test(){
184 
185          url_test "http://${PRE_LIST}/index.html"
186 
187          echo "add to cluster"
188 
189 }
190 
191  
192 
193 group1_deploy(){
194 
195          writelog "remove from cluster"
196 
197         
198 
199          for node in $GROUP1_LIST;do
200 
201                 ssh $node "cd /opt/webroot && tar zxf ${PKG_NAME}.tar.gz"
202 
203                  ssh $node "rm -rf /webroot/web-demo && ln -s /opt/webroot/${PKG_NAME} /webroot/web-demo"
204 
205         done    
206 
207          scp ${CONFIG_DIR}/other/192.168.56.12.crontab.xml 192.168.56.12:/webroot/web-demo/crontab.xml
208 
209 }
210 
211  
212 
213 group1_test(){
214 
215          url_test "http://192.168.56.12/index.html"
216 
217          echo "add to cluster"
218 
219 }
220 
221 rollback_fun(){
222 
223          for node in $ROLLBACK_LIST;do
224 
225                 ssh $node "rm -rf /webroot/web-demo && ln -s /opt/webroot/$1 /webroot/web-demo"
226 
227         done 
228 
229 }
230 
231 rollback(){
232 
233 if [ -z $1 ];then
234 
235          shell_unlock; 
236 
237          echo "please input rollback version" && exit;
238 
239 fi
240 
241          case $1 in
242 
243              list)
244 
245                  ls -l /opt/webroot/*.tar.gz
246 
247                  ;;
248 
249              *)
250 
251                  rollback_fun $1
252 
253          esac        
254 
255 }
256 
257  
258 
259 main(){
260 
261     if [ -f $LOCK_FILE ];then
262 
263          echo "Deploy is running" && exit;
264 
265     fi
266 
267     DEPLOY_METHON=$1
268 
269     ROLLBACK_VER=$2
270 
271     case $DEPLOY_METHON in
272 
273         deploy)
274 
275              shell_lock;
276 
277              code_get;
278 
279              code_build;
280 
281              code_config;
282 
283              code_tar;
284 
285              code_scp;
286 
287              pre_deploy;
288 
289              pre_test;
290 
291              group1_deploy;
292 
293              group1_test;
294 
295              shell_unlock;
296 
297              ;;
298 
299          rollback)
300 
301              shell_lock;
302 
303              rollback $ROLLBACK_VER;
304 
305              shell_unlock;
306 
307              ;;
308 
309          *)
310 
311              usage;
312 
313          esac 
314 
315 }
316 
317 main $1 $2
View Code

測試方式

[www@linux-node1 ~]$ curl --head http://192.168.56.11/index.html

HTTP/1.1 200 OK

Date: Mon, 01 Aug 2016 09:42:23 GMT

Server: Apache/2.4.6 (CentOS) OpenSSL/1.0.1e-fips PHP/5.4.16 mod_wsgi/3.4 Python/2.7.5

Last-Modified: Mon, 01 Aug 2016 09:39:52 GMT

ETag: "17-538ff61ca0a00"

Accept-Ranges: bytes

Content-Length: 23

Content-Type: text/html; charset=UTF-8

 

[www@linux-node1 ~]$ curl -s --head http://192.168.56.11/index.html|grep "200 OK"

HTTP/1.1 200 OK

上面腳本遠程執行命令或者拷貝 是使用ssh/scp完成的。當服務器稍多的時候,效率並不高。

我在生產環境中是使用 ansible 替代的,個人感覺對於這個腳本來說,就是個並行、串行的區別。

進一步的發展,還可以開發一些WEB界面去結合這個腳本,做到WEB化自動部署,當然也可以使用開源的jenkis。

3、回滾

1.列出回滾版本

2.目標服務器移除集群

3.執行回滾

4.重啟和測試

5.加入集群

===========

如果是遇到重大bug

1.列出回滾版本

2.執行回滾(重啟)

==========

非常緊急

1.直接回滾到上個版本(重啟)

自動化部署的核心是創建軟鏈接,同樣在回滾的時候也能實現秒級回滾。

但是在生產環境中,使用軟連接可能會造成WEB打開頁面空白,這點需要注意。

 






免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM