天天看點

[Shell]bash的良好編碼實踐

最好的bash腳本不僅可以工作,而且以易于了解和修改的方式編寫。很多好的編碼實踐都是來自使用一緻的變量名稱和一緻的編碼風格。驗證使用者提供的參數是否正确,并檢查指令是否能成功運作,以及長時間運作是否能保持可用性。下面分享一下我的工作技巧。

1. 使用良好的縮進 http://gitlab.corp.qunar.com/jifeng.si/learningnotes/blob/master/IT/%E8%84%9A%E6%9C%AC/Shell/%5BShell%5Dbash%E7%9A%84%E8%89%AF%E5%A5%BD%E7%BC%96%E7%A0%81%E5%AE%9E%E8%B7%B5.md#1

使用良好的縮進能使代碼可讀性更好,進而能更好的維護。

當你有三級以上的邏輯時,縮進能使我們輕松的檢視腳本的整體邏輯。使用多少個空格縮進并不重要,盡管大多數人更多的使用4個空格或8個空格進行縮進。

#!/bin/bash

if [ $# -ge 1 ] && [ -d $1 ]; then
  for file in `ls $1`
    do
        if [ $debug == "on" ]; then
            echo working on $file
         fi
         wc -l $1/$file
      done
else
  echo "USAGE: $0 directory"
    exit 1
fi
           

2. 提供使用說明 http://gitlab.corp.qunar.com/jifeng.si/learningnotes/blob/master/IT/%E8%84%9A%E6%9C%AC/Shell/%5BShell%5Dbash%E7%9A%84%E8%89%AF%E5%A5%BD%E7%BC%96%E7%A0%81%E5%AE%9E%E8%B7%B5.md#2

使用幫助語句可以幫助使用者運作腳本,即使兩年後你自己也能知道腳本需要提供什麼參數

#!/bin/bash

if [ $# == 0 ]; then
    echo "Usage: $0 filename"
    exit 1
fi
           

3. 使用合理的注釋 http://gitlab.corp.qunar.com/jifeng.si/learningnotes/blob/master/IT/%E8%84%9A%E6%9C%AC/Shell/%5BShell%5Dbash%E7%9A%84%E8%89%AF%E5%A5%BD%E7%BC%96%E7%A0%81%E5%AE%9E%E8%B7%B5.md#3

提供說明你代碼的注釋,特别是當代碼很複雜時,但也沒有必要解釋意圖很明顯的代碼.解釋你所使用的每一個指令,或組合中重要的指令。

#!/bin/bash

username=$1

# make sure the account exists on the system
grep ^$username: /etc/passwd
if [ $? != 0 ]; then
    echo "No such user: $username"
    exit 1
fi
           

4. 出現問題時使用傳回碼退出 http://gitlab.corp.qunar.com/jifeng.si/learningnotes/blob/master/IT/%E8%84%9A%E6%9C%AC/Shell/%5BShell%5Dbash%E7%9A%84%E8%89%AF%E5%A5%BD%E7%BC%96%E7%A0%81%E5%AE%9E%E8%B7%B5.md#4

當代碼中出現問題時傳回一個非0傳回碼,即使你自己不會看,但這也是一個好主意。假設有一天,你可能需要一個簡單的方法來檢查腳本中出現的問題,傳回代碼為1或4或11可能會幫助你快速找出問題。

#!/bin/bash

echo -n "In what year were you born?> "
read year

if [ $year -gt `date +%Y` ]; then
    echo "Sorry, but that's just not possible."
    exit 2
fi
           

5. 使用函數而不是重複一組指令 http://gitlab.corp.qunar.com/jifeng.si/learningnotes/blob/master/IT/%E8%84%9A%E6%9C%AC/Shell/%5BShell%5Dbash%E7%9A%84%E8%89%AF%E5%A5%BD%E7%BC%96%E7%A0%81%E5%AE%9E%E8%B7%B5.md#5

函數也可以使你的代碼具有更好的可讀性以及更易于維護。如果隻是重複使用一個指令,沒有必要使用函數,但是如果很簡單的就能區分開一些常用的指令(separate a handful of focused commands),使用函數這是值得的。如果以後對此進行更改,你隻需要在一個地方進行更改。

#!/bin/bash

function lower()
{
    local str="$@"
    local output
    output=$(tr '[A-Z]' '[a-z]'<<<"${str}")
    echo $output
}
           

6. 賦予變量有意義的名字 http://gitlab.corp.qunar.com/jifeng.si/learningnotes/blob/master/IT/%E8%84%9A%E6%9C%AC/Shell/%5BShell%5Dbash%E7%9A%84%E8%89%AF%E5%A5%BD%E7%BC%96%E7%A0%81%E5%AE%9E%E8%B7%B5.md#6

Unix管理者通常會盡最大努力的避免輸入一些額外的字元,但不要在腳本中這樣操作。花費一點時間為變量提供有意義的名稱,并在命名時保持一緻性。

#!/bin/bash

if [ $# != 1 ]; then
    echo "Usage: $0 address"
    exit 1
else
    ip=$1
fi
           

7. 檢查參數是否是正确類型 http://gitlab.corp.qunar.com/jifeng.si/learningnotes/blob/master/IT/%E8%84%9A%E6%9C%AC/Shell/%5BShell%5Dbash%E7%9A%84%E8%89%AF%E5%A5%BD%E7%BC%96%E7%A0%81%E5%AE%9E%E8%B7%B5.md#7

如果在使用參數之前檢查以確定提供給腳本的參數是符合預期類型的,那麼可以節省很多麻煩。下面是一種簡單檢查參數是否為數字的方法:

#!/bin/bash

if ! [ "$1" -eq "$1" 2> /dev/null ]
then
  echo "ERROR: $1 is not a number!"
  exit 1
fi
           

8. 檢查參數是否缺失或者順序錯誤 http://gitlab.corp.qunar.com/jifeng.si/learningnotes/blob/master/IT/%E8%84%9A%E6%9C%AC/Shell/%5BShell%5Dbash%E7%9A%84%E8%89%AF%E5%A5%BD%E7%BC%96%E7%A0%81%E5%AE%9E%E8%B7%B5.md#8

如果提供一個以上的參數,最好要确認一下。

#!/bin/bash

if [ $# != 3 ]; then
    echo "What part of THREE ARGUMENTS don't you understand?"
fi
           

9. 檢查需要的檔案是否存在 http://gitlab.corp.qunar.com/jifeng.si/learningnotes/blob/master/IT/%E8%84%9A%E6%9C%AC/Shell/%5BShell%5Dbash%E7%9A%84%E8%89%AF%E5%A5%BD%E7%BC%96%E7%A0%81%E5%AE%9E%E8%B7%B5.md#9

在使用某個檔案之前,很容易檢查該檔案是否存在。下面是一個簡單的檢查,來檢視第一個參數指定的檔案是否實際存在。

#!/bin/bash

if [ ! -f $1 ]; then
    echo "$1 -- no such file"
fi
           

10. 指令輸出發送到/dev/null http://gitlab.corp.qunar.com/jifeng.si/learningnotes/blob/master/IT/%E8%84%9A%E6%9C%AC/Shell/%5BShell%5Dbash%E7%9A%84%E8%89%AF%E5%A5%BD%E7%BC%96%E7%A0%81%E5%AE%9E%E8%B7%B5.md#10-dev-null

将指令輸出發送到

/dev/null

,并以更加“友好”的方式告訴使用者出了什麼問題,可以讓你的腳本更容易的運作。

#!/bin/bash

if [ $1 == "help" ]; then
    echo "Sorry -- No help available for $0"
else
    CMD=`which $1 >/dev/null 2>&1`
    if [ $? != 0 ]; then
        echo "$1: No such command -- maybe misspelled or not on your search path"
        exit 2
    else
        cmd=`basename $1`
        whatis $cmd
    fi
fi
           

11. 充分利用錯誤代碼 http://gitlab.corp.qunar.com/jifeng.si/learningnotes/blob/master/IT/%E8%84%9A%E6%9C%AC/Shell/%5BShell%5Dbash%E7%9A%84%E8%89%AF%E5%A5%BD%E7%BC%96%E7%A0%81%E5%AE%9E%E8%B7%B5.md#11

可以在腳本中使用傳回碼來确定指令是否得到預期的結果。

#!/bin/bash

# check if the person is still logged in or has running processes
ps -U $username 2> /dev/null
if [ $? == 0 ]; then
    echo "processes:" >> /home/oldaccts/$username
    ps -U $username >> /home/oldaccts/$username
fi
           

12. 給予回報 http://gitlab.corp.qunar.com/jifeng.si/learningnotes/blob/master/IT/%E8%84%9A%E6%9C%AC/Shell/%5BShell%5Dbash%E7%9A%84%E8%89%AF%E5%A5%BD%E7%BC%96%E7%A0%81%E5%AE%9E%E8%B7%B5.md#12

不要忘記告訴運作你的腳本人需要知道什麼。他們不必閱讀代碼就可以提醒他們為其建立檔案的位置 - 特别是如果它不在目前目錄中。

...
date >> /tmp/report$$
echo "Your report is /tmp/report$$"
           

13. 引号與擴充參數 http://gitlab.corp.qunar.com/jifeng.si/learningnotes/blob/master/IT/%E8%84%9A%E6%9C%AC/Shell/%5BShell%5Dbash%E7%9A%84%E8%89%AF%E5%A5%BD%E7%BC%96%E7%A0%81%E5%AE%9E%E8%B7%B5.md#13

如果你正在使用腳本中擴充的字元,不要忘記使用引号,這樣就不會得到與預期不同的結果。

#!/bin/bash

msg="Be careful to name your files *.txt"
# this will expand *.txt
echo $msg # Be careful to name your files behavior_20170728.txt exception.txt
# this will not
echo "$msg" # Be careful to name your files *.txt
           

14. 使用$@引用所有參數 http://gitlab.corp.qunar.com/jifeng.si/learningnotes/blob/master/IT/%E8%84%9A%E6%9C%AC/Shell/%5BShell%5Dbash%E7%9A%84%E8%89%AF%E5%A5%BD%E7%BC%96%E7%A0%81%E5%AE%9E%E8%B7%B5.md#14

$@變量列出了提供給腳本的所有參數:

#!/bin/bash

for i in "$@"
do
    echo "$i"
done
           

原文:

http://www.networkworld.com/article/2694433/unix-good-coding-practices-for-bash.html