1. 程式人生 > 實用技巧 >BASH編寫入門與例項

BASH編寫入門與例項

怎麼寫shell指令碼:
。使用任何編輯工具編寫shell指令碼 例如vi
    -#!/bin/bash    #在第一行放置頭格式說明
  -#!/usr/bin/gawk  //awk需要新增的頭格式,讓系統知道用什麼方式去解析此檔案
  -#!/usr/local/bin/python    //python的頭格式
。在寫完shell指令碼之後,設定指令碼執行許可權 -chmod +x you-script-name -chmod 755 your-script-name 。執行你的指令碼做測試 -bash your-script-name -sh your-script-name -./your-script-name
shell中的變數
。Linux(shell)中有兩種型別的變數:
    -系統變數:由Linux系統本身維護,通常為大寫的變數名
    -使用者定義變數(UDV):由使用者建立和維護,通常小寫
。檢視系統變數可以通過Linux指令set羅列出來,也可以輸入declare
。在呼叫變數時,在名稱前加以“$"(美元符號)
    -echo $USERNAME
    -echo $HOME
如何定義使用者自己的變數
。要定義UDV可以使用下面的語法:
    變數名=值    (注意:等號之間沒有空格)
。通過”=“將右邊的值賦給左邊的變數
    no=10    #正確
    10=no    #錯誤,值必須在右邊
    vech=Bus    #頂一個一個vech的變數值為Bus
    n= 30    #錯誤,等號右邊存在空格
    n =20    #錯誤,等號左邊存在空格
。只讀變數設定:

#readonly BOOK=”Linux“
#BOOK=”Windows“  //將會報錯。
取消變數#unset BOOK
彩色Shell輸出
。echo -e 指令可以在控制檯輸出彩色的字元。
。色彩分為前景色和背景色,十位數的數字3或4表示
    -前景色30-37(以3x代表)
    -背景色40-47(以4x代表)
。個位數表示為色彩
    30(黑色)、31(紅色)、32(綠色)、33(黃色)、34(藍色)、35(洋紅)、36(青色)、37(白色)。
。前景色和背景色個位數不要一致,否則看不到任何資訊(可以用在密碼輸入處)
彩色Shell輸出二
。使用格式:
    -    \033[前景色;背景色m    #同事更改前/背景色
    -    \033[前景色m    #只更改前景色
    -    \033[背景色m    #只更改背景色
    -    \033[0m    #還原所有的前/背景色,最後部分一定要還原色彩
。echo "You are login to \033[34;40m bulefox \033[0m system"  //這裡的第一個\033[[34;40m是說前景色和背景色設定,而\033則是讓所有的前景色和背景色還原。
-列印藍色的bulefox 。下面的程式碼用在防止密碼被窺探 echo "Please input a password”
   echo -e “\033[34;44m" read PASSWD;
   echo -e "\033[0m" echo PASSWD | openssl md5
echo命令
。使用echo 命令可以顯示文字或比變數的值
。echo 【選項】【字元,變數...】
。選項
    -n 不換行輸出,預設echo一次換一行,用在持續的列印輸出
    -e啟用轉義字元解析
        \a    響鈴    \b    退格    \c去除尾部的新行
        \n    新的一行    \r    回車    \t    水平製表符功能
        \\    斜槓
    echo -e "An apple a day keeps away \a\t\tdoctor\n"
shell中數學計算
。使用下面的語法執行數學運算,注意中間都存在空格,一次只能處理兩個數字
    語法:expr    運算元1    數學計算    運算元2
    expr 1+3    #加法計算
    expr 10/2    除法計算
    expr 20%3    求餘數
    expr 10\*3    #乘法他叔,由於”*“星號為萬用字元之一,必須對*轉義
    echo ‘expr 6+3‘    #顯示結果,注意”‘"(斜點)的使用,代表先行執行Bash命令
。如果使用echo “expr 6+3”或者echo 'expr 6+3'將顯示“expr 6+3”字元本身
將表示式計算結果賦值給變數方法:
#TMP=$(expr 3333 \*10)  //將3333*10的結果賦值給變數TMP
#echo “$((1+100/3*6))"  // 可以使用括號的方式進行運算,這種限制比較少

引號的使用
。我們來區分一下引號
    ”“(雙引號)    對”\"做轉義,對“$"的變數做解析
    ''(單引號)    其中的內容不作任何修改
    ‘‘(斜點)    用來執行命令
。請觀察下面的命令區別:
    -echo ”Today is date“    #輸出Today is date
    -echo ”Today is ‘date‘“    #輸出Today is 及日期
    -echo 'Today is ‘date‘’    #原樣輸出Today is ‘date‘ 
退出和退出狀態
。在Linux執行指令,它將返回兩種型別的值,用來判斷此前執行的命令或shell指令碼成功與否
    -返回0,命令執行成功
    -返回任何不為0,命令不成功或者執行中有一些錯誤
。這些值稱呼為退出狀態,可以通過$?檢查退出狀態
    -rm nonexist-file
    -echo $?
    -ls
    -echo $?  //判斷前面一條指令執行成功與否,立刻執行echo $?檢視返回值,0表示執行成功,否則執行失敗。
萬用字元的使用
。”*“星號代表任何的字元出現0到多次
    ls /lib/*.so    //任何以.so為字尾的檔案
    ls /lib/lib*.so.*    //以lib開頭+.so.+任何其他字尾
。”?“問號代表一個而且只有一個任何字元
    ls /lib/lib??.so.?    //此檔名長度為10
。”[]“括號內提供的字元選擇一個
    ls /lib/lib[bcp]*.so     //b,c,p選一,libb,libc,libp
。”[-]“括號內一段字元,0-9數字,a-z小寫,A-Z大寫
    ls /lib/lib[b-p]*.so    //從b到p選擇一個
  ls /lib/lib[a-z]*.so等同於ls /lib/lib[ab-z]*.so 。”[^]"括號內的都排除掉,[^bc]除了b和c以外的其他全部 ls /lib/lib[^c]*.so.*
命令列的處理
。Linux絕大多數命令可以帶引數和選項,請識別下面的命令帶有多少引數
#命令                #引數總數($#)
ls foo                #1
cp y y.bak            #2
date                     #0
tail -10 myf            #2
mail raj                #1
sort -r -r myf        #2
命令列引數
。根據前面觀察的結果
    -$#儲存著命令後面所帶的引數的總數
    -$*或者$@將命令後的所有引數作為一個字串儲存
  -$0  永遠是命令本身
  -$1,2,3...  命令引數

shell指令碼中條件判斷
。返回shell中0(代表True)或1(False)結果
    -if/then結構
    -test或者[...]執行shell測試,返回shell結果
。Bash2.02版本以上[[...]]
。返回常規程式語言格式的結果
    -((...))和let...還可以做數字的比較
。bc指令提供我們對條件的測試
測試條件:
。字元比較        數字比較        代表意思
    ==                -eq            相等
    >                   -gt            大於
    <                   -lt             小於
    !=                  -ne            不等於
    <=/>=           -le/ge        小於等於/大於等於
多個條件測試時
    -a並且,邏輯與-o或者,邏輯或
test命令或[]
。[]中寫入測試條件,注意條件和開/閉中括號之間要保留空格
。初學者使用此模式時,要特別注意,0代表TRUE,可以理解成沒有錯誤,而1代表FALSE
    if [ 0 ];then
        echo "0 is true"
    else
        echo "0 is false"
    fi
if...else...fi
。語法:
    if [ 條件判斷]
    then
        命令1        #上面條件判斷結果為0,代表TRUE
        命令2
    else
        命令3        #上面條件判斷結果為1,代表FALSE
        命令4
    fi
if語句直接使用示例
。if語句可以直接使用Shell指令,再根據$?結果判斷
    DIR=/var/test
    if cd $DIR &> /dev/null;then    #直接丟棄錯誤訊息,這裡由於不需要判斷條件,這裡的條件就可以去掉[]
        echo "now in $DIR"
    else
        echo "Can't change to $DIR"
    fi
測試檔案/資料夾屬性
。常見判斷
    -a    #檔案是否存在
    -b    #檔案是否為塊裝置
    -d    #檔案是否為目錄
    -s    #檔案大小是否為0
    -r    #檔案是否具有可讀許可權
    -w    #檔案是否具有可寫許可權
    -x    #檔案是否具有可執行許可權
。man bash可以得到更為詳盡的幫助
#[ -f /etc/passwd ]; echo $?  //檢視/etc/passwd檔案是否存在
if語句巢狀
。一步一步測試時,可能需要if-then-else語句的巢狀使用
OSCH=0
echo “1.Unix(IBM AIX)”
echo “2.Linux(Red Hat Enterprise Linux)”
read OSCH
if [ $OSCH -eq 1 ]; then
    echo "You pick UNIX OS"
else
    if [ $OSCH -eq 2 ];then
        echo "Your Pick Linux OS"
    else
        echo "What you don't Like Linux/Unix OS"
    fi
fi
多級if-then-else
。多級if-then-else可以替換掉if-then-else的巢狀使用,直接使用另一個/多個條件測試,請將之前的程式修改以下語法
。語法
if    [    測試條件1    ];then
    命令1
elif  [    測試條件2    ];then
    命令2
elif    [    測試條件n    ];then
    命令n
else
    命令
fi
退出和退出狀態
。在Linux執行指令,它將返回兩種型別的值,用來判斷此前執行的命令或shell指令碼成功與否
    -返回0,命令成功
    -返回任何不為0,命令不成功或者在執行中有一些錯誤
。這些值稱呼為退出狀態,可以通過$?檢查退出狀態
    -rm    nonexit-file
    -echo    $?
    -ls
    -echo    $?
case語句
。case語句是多級if-then-elif語句的替代語句。可以讓你多個值做匹配測試,更方便讀寫。
。語法:
case 變數名    in
    匹配1)    命令1;;
    匹配2)    命令2;;
    匹配N)    命令N;;
    *)    命令;;
esac
比較以下兩段程式碼:、

將手動寫的指令碼加入到chkconfig裡面步驟:
比如已經編寫好的myserv.sh指令碼,需要加入到開機啟動裡面
1.將此指令碼加入到/etc/init.d
#mv myserv.sh /etc/init.d/myserv
2.需要在指令碼中新增chkconfig和descirption資訊,可以參考/etc/init.d/network部分,下圖中標色部分即為需要新增內容
3.chkconfig --add myserv  //新增此服務到chkcofnig下
4.chkcofnig --list myserv  //檢視該服務在不同級別下啟停狀態。

Shell中loop迴圈
迴圈的定義:
    -計算機可以重複一而再,再而三的執行特定的指令,直到給定的條件滿足為止,重複執行的這一組指令就叫做loop
。Bash中支援
    -for loop    
    -while loop
。注意每個迴圈使用時
    首先,用在迴圈中的變數必須要在迴圈前初始化
    對每次迴圈都需要對條件做測試
    在迴圈體中執行一次需要對迴圈測試條件值修改  
for loop
。語法:
        for    變數名    in    列表
        do    
                迴圈體
        done
。列表就是一個集合,集合由空格間隔,可以使以下的集中:
    -數字/字元集合
        -1 2 5 7 9
        -{1...254}
    -檔案集合
        -/etc/*.conf
    -指令結果集合
        -$(find /etc/ -perm -003)
例項1(數字迴圈):
建立file1,2,3,4檔案
#touch file{1,2,3,4,5}
#vim test.sh
內容如下:
#!/bin/bash
for FILENAME in file1 file2  file3 file5
do
    echo "You are going to remove the $FILENAME
    rm $FILENAME -f 
done

例項2:
。數字集合
#vim test.sh
內容如下:
#!/bin/bash
echo "#!/bin/bash" > /bin/setFilewall.sh
for IP in {1...254}
do
    echo "iptables -I INPUT -s 192.168.0.$IP -p tcp
        -m state --state NEW -j ACCEPT" >>
        /bin/setFirewall.sh
done
/etc/sysconfig/selinx    //其中/etc/sysconfig通過dirname可以獲取,而selinux則可以通過basename獲取。
#date +%F  //可以獲取當前日期

for loop例項三
for FILE in $(find /var/ -size +10M)
do
    rm -f $FILE 
    logger "$FILE has been deleted"
    echo -e "\033[33m$FILE\033[0mhas been deleted">>/var/tmp/largefile.log
done
獲取某個檔案中的空格或者換行的ip地址方法:
#cat /etc/testservers.conf | grep -Ev '^(#|$)'
如獲取以下檔案中的有效ip
#vim testservers.conf
檔案內容如下:
#This file is the host ip
#172.23.2.1
192.168.1.1
#FTP Server
192.13.1.1
127.0.0.1
        192.156.1.1
全文搜尋例項:
此指令碼用於搜多某個目錄下所有檔案裡面是否含有某個關鍵字
指令碼內容如下:
#!/bin/bash DIR=$1 KEYWORD=$2 for FILENAME in $(find $DIE -type f) do if grep $KEYWORD $FILENAME &> /dev/null;then echo "The file -->$FILENAME has the keyword" #else fi done
for loop迴圈巢狀一

for NUM1 in {1. .9}
do
    for NUM2 in {1..9}
    do
        RES = $((NUM1*NUM2))    #注意此處沒有呼叫$
        echo "$NUM1*$NUM2=$RES"
    done
done
#請把此程式碼改成C語言格式

while迴圈
。語法:
    -while  [條件測試]
      do
            命令
      done
。注意要修改測試條件的值,防止死迴圈。還可以與if-then-fi巢狀使用,使用exit函式退出
read $1 $2 $3        //可以用來讀取文字檔案中某一行的第一個,第二個,第三個不規則的引數作為輸入
函式的使用
。函式是一系列的指令和命令
。本身不執行,可以多次呼叫,可以簡化程式碼
。語法
函式()
{
    命令1;命令2
        return    #返回值
}
函式的引數
。函式也可以作為一個程式一樣執行,接收引數
-fname $arg1    $arg2
    -這和shell中位置引數一樣,我們可以對$1,$2測試

max()
{
    if (($1>$2));then
        return $1    #注意,此時函式已經結束了
    fi    
        return $2
}
max 10 100
echo $?    #通過$?取得函式的返回值
函式示例

setPath()
{
    PATH=/bin:/usr/bin
    if (($UID == 0 ));then    #如果為root
        PATH=$PATH:/usr/bin/sbin:/sbin    #路徑追加sbin的目錄
    fi
    if (($2 == "after"));then    #根據位置引數2,決定如何新增新路徑
        PATH=$PATH:$1    #在原PATH後面追加
    else
        PATH=$1:$PATH    #在原PATH之前新增
    fi
}
getopts命令
。getopts用來檢測命令中傳遞給指令碼的有效引數
。通常用在while loop中
。語法:
    -getopts <選項字串>    <變數1>
。<選項字串>包含了要識別的選項字元;如果字元前存在"-"(橫槓),而此選項期待著有一個引數,他們之間用空格空開。
。每次呼叫getopts的時候,他講下一選項設定給<變數1>
。當選項需要引數時,getopts將引數設定給變數OPTARG
。如果選項不正確,返回  ?  給<變數1>
getopts示例

while getopts n:a: opt    #此程式就有-n和-a選項,注意選項字串尾部的冒號(:)
do
    case "$opt" in
        n)    name="$OPTARG";;
        a)    age="$OPTARG";;
        \?)    echo “Usage:..."
    esac
done
echo ”Welcome $name,you age is $age"