您好,登錄后才能下訂單哦!
平常工作中,你是否感覺
shell
腳本只是
命令的堆砌;很多時候只是為了實現功能而沒有好的組織結構;自己的
腳本都不想再看一遍;哈哈,我這就教給shell的“葵花寶典“,自此讓你的shell腳本有python一樣的美感并且極易維護,真的是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函數,讓我在維護腳本時,可以更好的把握腳本的組織架構,找到切入點:
# 由于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 $@
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
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。