平常工作中,你是否感觉shell脚本只是命令的堆砌;很多时候只是为了实现功能而没有好的组织结构;自己的脚本都不想再看一遍;哈哈,我这就教给shell的“葵花宝典“,自此让你的shell脚本有python一样的美感并且极易维护,真的是shell脚本写到停不下来。
现以nginx控制脚本为例,看一下脚本的美容过程:
; U6 T- U. j2 d# C9 `" \: [- #!/bin/bash
* C% J" l. B# N - # set命令的奇妙用途留在文章末尾
) Y/ T \# I" W; \ - set -eu5 \3 w9 A0 m2 O1 r* h# t: I
- # nginx重载配置文件2 F* e9 C/ W+ a7 l$ |
- nginx -c /etc/nginx/nginx.conf -t
$ U- v" G3 ?, ^ - kill -HUP `ps auxf | grep -E "nginx:[[:space:]]+master"| awk '{print $2}'`: U- V1 Y9 P4 C3 x3 i. k+ ?% U
复制代码
: s% i& L) M0 R$ G5 \ 宝典秘籍之变量抽离在脚本中,需要依赖外部的配置,比如配置文件位置,监听端口之类的可变参数,编程时,需要将其抽离为变量,为了更好的引用与维护,省去了外部配置变化时,一个个修改带来的麻烦。 - <font style="background-color:rgb(255, 255, 255)">
7 X$ W6 B! r; M! }! K F- l8 O - #!/bin/bash
9 X. r6 V/ n3 m4 f% c6 I - # set命令的奇妙用途留在文章末尾/ }; W, c9 i; t) D2 B6 m
- set -eu Q0 z! J( c; I) c" m: B/ G8 }
- # nginx配置文件在不同环境中,位置可能不同,所以需要将其抽离成可配置变量,脚本来引用
7 D7 j# T1 ]- d3 g& l+ L; Q/ T - NGINX_CONFIG_FILE=/etc/nginx/nginx.conf
1 Y' [; ]6 C) x# }- I! m6 T* U1 q - 2 O' w( o+ u& q/ k0 N4 W
- # nginx重载配置文件6 h( k$ K$ T2 Z$ Z: o5 F
- nginx -c $NGINX_CONFIG_FILE -t
) o( k9 t5 P3 s& h# J - kill -HUP `ps auxf | grep -E "nginx:[[:space:]]+master"| awk '{print $2}'`</font><font style="background-color:rgb(255, 255, 255)">
( W# b( B X( X - </font>
复制代码 宝典秘籍之模块化运维毕竟不是专业程序员,写脚本时是怎么舒服怎么来,简单讲就是从上到下依次执行,这就导致复用性差,不易维护,解决这问题的关键在于函数化、模块化思想,shell虽然是一种比较简单的语言,但语言基本的逻辑控制、函数功能都有,这就让我们编写高质量shell脚本带了无限可能。接下来就看一下具体例子来感受一下:
* V7 r" F, {' t- # 由于nginx配置文件检查是执行其他操作的第一步,所以我们将其独立成一个单独函数% X+ |5 A; x* B+ u4 K
- #!/bin/bash( S3 K2 D( G) f! q- ^
- # set命令的奇妙用途留在文章末尾( b. [6 T' [0 U6 z4 K( Z B
- set -eu
1 `6 {6 e. T/ [3 \/ ^. c% V/ {6 i9 ~, Y - # nginx配置文件在不同环境中,位置可能不同,所以需要将其抽离成可配置变量,脚本来引用% U8 c7 O l% i5 S) {
- NGINX_CONFIG_FILE=/etc/nginx/nginx.conf% x- _/ \9 d( R0 d8 j. F
- $ _, ~/ d8 Z; J: Z' ?+ z6 k, o* s
- # 抽离配置文件检查为单独的函数
3 P. |/ R1 y. |7 m. W3 F - config_test() {
, w, V$ u2 ^ f" ~3 V( Y - nginx -c $NGINX_CONFIG_FILE -t
: H3 }5 N& x# v) F, |! Q @5 l3 A - }
2 w/ I3 Z# g% ? - get_nginx_master_pid(){
! a8 r# E2 @# L% f- T) F# e - echo `ps auxf | grep -E "nginx:[[:space:]]+master"| awk '{print $2}'`
, u% ` v5 I8 W k; h+ ` - }: A5 R- B; b4 b( x& A
- # 抽离配置重载为独立函数" B( n3 B8 D9 K3 p0 p
- reload() {
1 n2 ]- l+ y! t: Z - kill -HUP `get_nginx_master_pid`" k: B9 j) Z! k- \" F& u
- }
) u5 p( c3 T" e( y/ P- P - - b, y% R) E8 q
- # nginx重载配置文件
8 v. l' D2 n* D - config_test
! W# ~1 T' u9 x - reload
复制代码 2 k& y% x% F9 B
宝典秘籍之main函数脚本的可维护性在于脚本的结构的好坏,为了拥有更好的结构,通常需要在脚本中定义入口函数,即main函数,让我在维护脚本时,可以更好的把握脚本的组织架构,找到切入点: - <font style="background-color:rgb(255, 255, 255)"># n% O2 b- m5 B0 l: t
- # 由于nginx配置文件检查是执行其他操作的第一步,所以我们将其独立成一个单独函数
5 H4 c( j. N) ?- Z0 j - #!/bin/bash0 l) G( {5 P* \+ c
- # set命令的奇妙用途留在文章末尾2 y- ^0 I- @; T1 o% I6 f
- set -eu
1 T7 Q6 J" E; f& r1 Y1 } - # nginx配置文件在不同环境中,位置可能不同,所以需要将其抽离成可配置变量,脚本来引用) b/ z( _; v0 r
- NGINX_CONFIG_FILE=/etc/nginx/nginx.conf
, M; {4 ]' I0 N+ f$ e9 B' ^5 |8 _0 ], I - + I4 c6 E9 r# d5 b# Z1 G/ T
- # 抽离配置文件为单独的函数
7 c7 @) x5 K! [# K6 w - config_test() {
" w& T& Z5 u7 B2 ?1 }: n5 [ - nginx -c $NGINX_CONFIG_FILE -t) c+ n5 W+ h0 V |
- }1 P6 R" [3 \# S$ y/ R( v
- 7 e; s- L. d4 `+ u' r
- get_nginx_master_pid(){
- s/ L9 P3 t8 p& x/ G8 L# e5 e - echo `ps auxf | grep -E "nginx:[[:space:]]+master"| awk '{print $2}'`
# t7 ]9 O- P; E K5 K8 S - }
% X. K) d! P; ~! c+ B% G; { - # 抽离配置重载为独立函数1 h* X9 u0 A& \$ t
- reload() {
, a: @; ^4 f; |" W ^ - kill -HUP `get_nginx_master_pid`- Q& T/ ~5 h( i; n0 g4 x9 F
- }' t1 A2 k5 Y( u' F
5 ~7 ]. V$ {/ c( r' w. ]- # 入口函数
" q- Q* w1 _- y1 s9 u: a0 h8 N F2 m - main() {
* Z y' C# }3 P* v! L - config_test# B8 _$ X0 a+ ?4 L" t
- reload( N* N! {. D. T N2 X( E1 i& s
- }8 g- f$ _ q2 b% Z5 z# J
8 t! S6 y, U s$ F5 D# w4 A/ Z- # main在此需要获取脚本本身的参数, 故将$@传递给main函数
' ^0 h0 c6 s% C, V0 G4 U% ] - main $@</font><font style="background-color:rgb(255, 255, 255)">
& n1 N/ l$ K' ]' u2 \( d! @* j - </font>
复制代码 宝典秘籍之函数返回值在其他编程语言,可以通过return获得函数的返回值,但是return语句在shell中含义不同,return命令会使一个函数返回,会返回一个单一的数字参数,而这个数字参数在调用这个函数的脚本是可见的,如果没有指定返回参数,return在默认情况下会返回上一次命令的返回代码。那如何实现类似其他编程语言的return效果呢?可以使用echo命令: - <font style="background-color:rgb(255, 255, 255)">
8 z, F2 Q) G9 J+ Y2 N3 A W' X1 X; o - #!/bin/bash
1 N9 S% z* c( n# F3 a" ?; D - set -eu( b3 b6 T' C- s7 y% N7 i) U
- NGINX_CONFIG_FILE=/etc/nginx/nginx.conf2 `+ Z+ ~3 V2 u5 L
- # W9 @& a: n" c2 q N
- config_test() {. g& k0 {8 L3 y& d/ |4 M: K
- nginx -c $NGINX_CONFIG_FILE -t8 L+ r. T$ p0 V. {9 D, j
- }% i! o- F( F1 j0 h W
- 8 F" t+ u0 _8 ?6 ]
- # 在此处直接把nginx的master pid可以通过反引号来获取echo后的值
+ U( f' v/ v: ` - get_nginx_master_pid(){- {9 G$ Q7 ?7 Z2 w% x" ] d
- echo `ps auxf | grep -E "nginx:[[:space:]]+master"| awk '{print $2}'`- A0 ^" n2 Q( w- @& j9 B) |- p
- }
5 y+ C* q, \0 g2 A
6 R; A5 p+ A0 r4 M. e6 L- reload() {( i" a. N! M. y) q+ N9 ^
- # `get_nginx_master_pid` 获得nginx master pid
- P2 _& H! r8 x4 w' `- c - kill -HUP `get_nginx_master_pid`
0 Z0 g" K0 [/ l7 H - }# i* P+ V: t! E4 ?; `. C4 E% R
- ! z) l) q7 h4 M" W$ e: {) _
- # 入口函数
, t: X% U8 `% [9 V/ e - main() {% K; Y. m7 e( y
- config_test
$ Q! ^$ J6 t1 T+ |6 n8 B - reload
S9 \. w2 t6 b) \. { - }& E8 g* d+ Q: }& }( J; ^$ {
- 9 I1 w+ ]9 l# \" {
- # main在此需要获取脚本本身的参数, 故将$@传递给main函数
1 p$ M. K2 @6 Z% C5 C& o: B8 a# W - main $@</font><font style="background-color:rgb(255, 255, 255)">" e9 N$ @# M* F- \% T0 ]
- </font>
复制代码 宝典秘籍之set命令bash内置的set命令,可以改变我们脚本的执行行为,让我对脚本的把握和调试更有力,下面说几种常用的set指令,相信你都会喜欢的: •set -e: bash脚本遇到错误立即退出•set -n: 检查脚本语法但不执行•set -u: 遇到未设置的变量立即退出•set -o pipefail: 控制在管道符执行过程中有错误立即退出•set -x: 分步调试命令 在写脚本时,我们可以直接在脚本开头简写为如下格式: - <font style="background-color:rgb(255, 255, 255)">
# q5 D4 ^, |% u- E( B - #!/bin/bash3 Z. a0 x! [4 f( S3 V
- set -euxo pipefail</font><font style="background-color:rgb(255, 255, 255)">4 I" s* u+ Z* h. `1 t5 x
- </font>
复制代码检查bash脚本的语法时,可以这样写: I( o% W" c9 q! y6 V y; u7 ^- j
- bash -n main.sh
8 P4 \3 i7 H$ v
|
非常好的资料,感谢分享非常好的资料,感谢分享非常好的资料,感谢分享非常好的资料,感谢分享