shell高效程式設計:shell指令碼從未如此美麗

安全劍客發表於2020-06-28
平常工作中,你是否感覺 shell 指令碼只是 命令的堆砌;很多時候只是為了實現功能而沒有好的組織結構;自己的 指令碼都不想再看一遍;哈哈,我這就教給shell的“葵花寶典“,自此讓你的shell指令碼有python一樣的美感並且極易維護,真的是shell指令碼寫到停不下來。

shell高效程式設計:shell指令碼從未如此美麗shell高效程式設計:shell指令碼從未如此美麗

平常工作中,你是否感覺shell指令碼只是 命令的堆砌;很多時候只是為了實現功能而沒有好的組織結構;自己的指令碼都不想再看一遍;哈哈,我這就教給shell的“葵花寶典“,自此讓你的shell指令碼有python一樣的美感並且極易維護,真的是shell指令碼寫到停不下來。

現以nginx控制指令碼為例,看一下指令碼的美容過程:

#!/bin/bash 
# set命令的奇妙用途留在文章末尾 
set -eu 
# nginx過載配置檔案 
nginx -c /etc/nginx/nginx.conf -t 
kill -HUP `ps auxf | grep -E "nginx:[[:space:]]+master"| awk '{print $2}'`
寶典祕籍之變數抽離

在指令碼中,需要依賴外部的配置,比如配置檔案位置,監聽埠之類的可變引數,程式設計時,需要將其抽離為變數,為了更好的引用與維護,省去了外部配置變化時,一個個修改帶來的麻煩。

#!/bin/bash 
# set命令的奇妙用途留在文章末尾 
set -eu 
# nginx配置檔案在不同環境中,位置可能不同,所以需要將其抽離成可配置變數,指令碼來引用 
NGINX_CONFIG_FILE=/etc/nginx/nginx.conf 
 
# nginx過載配置檔案 
nginx -c $NGINX_CONFIG_FILE -t 
kill -HUP `ps auxf | grep -E "nginx:[[:space:]]+master"| awk '{print $2}'`
寶典祕籍之變數抽離

在指令碼中,需要依賴外部的配置,比如配置檔案位置,監聽埠之類的可變引數,程式設計時,需要將其抽離為變數,為了更好的引用與維護,省去了外部配置變化時,一個個修改帶來的麻煩。

#!/bin/bash 
# set命令的奇妙用途留在文章末尾 
set -eu 
# nginx配置檔案在不同環境中,位置可能不同,所以需要將其抽離成可配置變數,指令碼來引用 
NGINX_CONFIG_FILE=/etc/nginx/nginx.conf 
 
# nginx過載配置檔案 
nginx -c $NGINX_CONFIG_FILE -t 
kill -HUP `ps auxf | grep -E "nginx:[[:space:]]+master"| awk '{print $2}'`
寶典祕籍之模組化

運維畢竟不是專業程式設計師,寫指令碼時是怎麼舒服怎麼來,簡單講就是從上到下依次執行,這就導致複用性差,不易維護,解決這問題的關鍵在於函式化、模組化思想,shell雖然是一種比較簡單的語言,但語言基本的邏輯控制、函式功能都有,這就讓我們編寫高質量shell指令碼帶了無限可能。接下來就看一下具體例子來感受一下:

# 由於nginx配置檔案檢查是執行其他操作的第一步,所以我們將其獨立成一個單獨函式 
#!/bin/bash 
# set命令的奇妙用途留在文章末尾 
set -eu 
# nginx配置檔案在不同環境中,位置可能不同,所以需要將其抽離成可配置變數,指令碼來引用 
NGINX_CONFIG_FILE=/etc/nginx/nginx.conf 
 
# 抽離配置檔案檢查為單獨的函式 
config_test() { 
    nginx -c $NGINX_CONFIG_FILE -t 
} 
get_nginx_master_pid(){ 
    echo `ps auxf | grep -E "nginx:[[:space:]]+master"| awk '{print $2}'` 
} 
# 抽離配置過載為獨立函式 
reload() { 
    kill -HUP `get_nginx_master_pid` 
} 
 
# nginx過載配置檔案 
config_test 
reload
寶典祕籍之main函式

指令碼的可維護性在於指令碼的結構的好壞,為了擁有更好的結構,通常需要在指令碼中定義入口函式,即main函式,讓我在維護指令碼時,可以更好的把握指令碼的組織架構,找到切入點:

# 由於nginx配置檔案檢查是執行其他操作的第一步,所以我們將其獨立成一個單獨函式 
#!/bin/bash 
# set命令的奇妙用途留在文章末尾 
set -eu 
# nginx配置檔案在不同環境中,位置可能不同,所以需要將其抽離成可配置變數,指令碼來引用 
NGINX_CONFIG_FILE=/etc/nginx/nginx.conf 
 
# 抽離配置檔案為單獨的函式 
config_test() { 
    nginx -c $NGINX_CONFIG_FILE -t 
} 
 
get_nginx_master_pid(){ 
    echo `ps auxf | grep -E "nginx:[[:space:]]+master"| awk '{print $2}'` 
} 
# 抽離配置過載為獨立函式 
reload() { 
    kill -HUP `get_nginx_master_pid` 
} 
 
# 入口函式 
main() { 
    config_test 
    reload 
} 
 
# main在此需要獲取指令碼本身的引數, 故將$@傳遞給main函式 
main $@
寶典祕籍之函式返回值

在其他程式語言,可以通過return獲得函式的返回值,但是return語句在shell中含義不同,return命令會使一個函式返回,會返回一個單一的數字引數,而這個數字引數在呼叫這個函式的指令碼是可見的,如果沒有指定返回引數,return在預設情況下會返回上一次命令的返回程式碼。那如何實現類似其他程式語言的return效果呢?可以使用echo命令:

#!/bin/bash 
set -eu 
NGINX_CONFIG_FILE=/etc/nginx/nginx.conf 
 
config_test() { 
    nginx -c $NGINX_CONFIG_FILE -t 
} 
 
# 在此處直接把nginx的master pid可以通過反引號來獲取echo後的值 
get_nginx_master_pid(){ 
    echo `ps auxf | grep -E "nginx:[[:space:]]+master"| awk '{print $2}'` 
} 
 
reload() { 
    # `get_nginx_master_pid` 獲得nginx master pid 
    kill -HUP `get_nginx_master_pid` 
} 
 
# 入口函式 
main() { 
    config_test 
    reload 
} 
 
# main在此需要獲取指令碼本身的引數, 故將$@傳遞給main函式 
main $@
寶典祕籍之set命令

bash內建的set命令,可以改變我們指令碼的執行行為,讓我對指令碼的把握和除錯更有力,下面說幾種常用的set指令,相信你都會喜歡的:
set -e: bash指令碼遇到錯誤立即退出
set -n: 檢查指令碼語法但不執行
set -u: 遇到未設定的變數立即退出
set -o pipefail: 控制在管道符執行過程中有錯誤立即退出
set -x: 分步除錯命令

在寫指令碼時,我們可以直接在指令碼開頭簡寫為如下格式:

#!/bin/bash
set -euxo pipefail

檢查bash指令碼的語法時,可以這樣寫:

bash -n main.sh

原文地址: https://www.linuxprobe.com/shell-programming-scripts.html

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31559985/viewspace-2700800/,如需轉載,請註明出處,否則將追究法律責任。

相關文章