學習 shell scripts(转)

學習 shell scripts

最近更新日期:2002/06/27

幹嘛學習 Scripts
scripts 的執行與第一支 scripts
標籤與運算符號declare
對談式 scriptsread
scripts 邏輯判斷式與運算式
條件式判斷if...then...fi, case.....esac
迴圈for....do....done, while...do...done, until...do...done,
script 如何 debug
本章習題練習


幹嘛學習 Scripts

這個問題可有趣的很了,我為什麼要學習 scripts 呢?不要學可不可以呀!?呵呵!如果您只想要『會用』 Linux 就好的話,那麼這一個部分確實可以先跳過去不看也沒關係,不過,如果您想要更加的瞭解與控制 Linux ,使 Linux 運作更順暢之外,還可以高枕無憂的讓你的 Linux Server 在 Internet 上面提供相關服務的話,那麼 scripts 還是多少學一學吧!為什麼呢?因為 scripts 可以設計到『很聰明的知道什麼條件之下需要進行什麼動作!』不要小看這個功能呦!當您不在電腦前面的時候,突然之間,主機被一些不明封包試圖入侵了,這個時候如果你的 Linux 主機可以透過『當該封包嘗試幾次還是連線失敗之後,就予以抵擋住該 IP 』,如果可以設計到如此功能的話,呵呵!那麼可就不得了了!您的 Linux 主機就可以說是『好聰明呀! smart!』

除了針對主機之外,其實 scripts 還有相當多的運用功能呦!例如您想要在 Linux 上面作你的作業,而這個作業是一些數值方面的計算,這個時候 Scripts 也可以幫您計算呦!還不需要用到 fortran, c 這類高階的程式語言呢! scripts 本身就是一個可以用的 program 囉!相當的棒吧!其實, scripts 最開始被新手使用的功能就是『彙整一些在 command line 下達的連續指令,將他寫入 scripts 當中,而由直接執行 scripts 來啟動一連串的 command line 指令輸出入!』例如: 防火牆連續規則 ( iptables ),開機載入程序的項目 ( 就是在 /etc/rc.d/rc.local 裡頭的資料 ) ,等等都是相似的功能啦! 其實,說穿了,如果不考慮 program 的部分,那麼 scripts 也可以想成,僅是幫我們把一大串的指令彙整在一個檔案裡面,而直接執行該檔案就可以執行那一串又臭又長的指令段!就是這麼簡單啦!

另外的另外,在編寫 scripts 時,在 Linux 當中,最常使用的就是 vi 這一套文書編輯器了,所以囉,為了更簡易的控管我們的 Linux ,嗯!還是學習一下好了啦!好不好呀! ^_^


scripts 的執行與第一支 scripts

  • scripts 的執行:
嗯!在上一章 bash shell 當中說了一堆變數啦!管線指令啦!等等的,都是為了接著而來的 scripts 的咚咚啦!什麼是 script 啊?由字面上的意思來說, script 就是『腳本、劇本』的意思,那夠清楚了吧!就是將我們要執行的內容寫成一個『腳本』,讓系統依據這個『腳本』來執行我們想要的東西!好了!現在我們來討論一下怎麼寫 scripts 好了!基本上,一個 script 被執行的時候, bash 會據以判斷執行的步驟為:
  1. 如果讀取到一個 Enter 符號( CR ),就嘗試開始執行該行命令;
  2. 如同前面 bash command 提到的,指令間的多個空白會被忽略掉;
  3. 而空白行也將被忽略掉!,並且 tab 也是不會被理會的!
  4. 至於如果一行的內容太多,則可以使用 \ 來延伸至下一行;
  5. 此外,使用最多的 # 可做為註解!任何加在 # 後面的字,將全部被視為註解文字而被忽略!
然後,在撰寫一個 scripts 的時候,最好養成良好的習慣:
  1. 先宣告使用的 shell 為何?(特別留意這一點,在某些狀況中,例如 /etc/crontab 情況下,如果沒有宣告使用的 shell ,常常會出現錯誤訊息而導致 scripts 無法被執行呦!)
  2. 註明該 script 的內容功能、版本資訊、作者、建檔日期等等
  3. 每一個大步驟的主要功能(也順便提供自己未來修改之用!)
那麼 scripts 這個檔案要如何來執行呢?執行的方法有兩種:
  • 一個是將該檔案改成可以執行的屬性,如chmod 755 scripts.file ,然後執行該檔案;
  • 另一種則是直接以 sh 這個執行檔來執行 script 的內容,如 sh scripts.file
大致上就是這樣啦!OK!那麼還記得我們在前面一章已經說過了變數的設定方式了吧?好了,那麼我們就以第一支 scripts 來將我們設定的變數直接給他 show 出來!嗯!來設計一下這支 script 吧!
  • 建立你的第一支 script:
好了,我們來建立第一支簡單的 script 吧!最簡單的一個例子,就是在螢幕上列出『 Hello ! How are you ?』,可以這樣寫:(註:最常使用來作為 shell scripts 的寫作的軟體,就是 vi 啦!有空真的要多熟悉一下 vi 呦!)
 
[root @test /root]# mkdir test; cd test  <==建立一個新的目錄,所有的 scripts 都暫存在此!
[root @test test]# vi test01-hello.sh
#!/bin/bash                        <==在 # 之後加上 ! 與 shell 的名稱,用來宣告使用的 shell
# 這個腳本的用途在於列出 Hello ! How are you 在螢幕上
# 建檔日期: 2002/05/20
# Made by VBird
hello=Hello\ \!\ How\ are\ you\ \?      <==這就是變數啦!
echo $hello

[root @test test]# sh test01-hello.sh
Hello ! How are you ?                   <=輸出的結果顯示在螢幕上!

這裡給他注意一下:

  • 所有在 scripts 裡面的東西,基本規則 ( 如變數設定規則 ) 需要與 command line 時相同;
  • scripts 的附檔名最好為 .sh 提供他人的認識;
  • 並非加上 .sh 就可以是執行檔,還需要查看其屬性中是否有 x 這個屬性。
呵呵!很興奮吧!你已經會寫 scripts 了呦!已經具有初階的程式設計能力囉!嗯!是該覺得高興的!^_^...!好了,接著下來我們寫稍微複雜一點的,若一個 script 裡頭有兩個以上的變數要相互引用呢?呵呵!這個時候順便來比較一下 " 與 ' 的異同吧!
 
[root @test test]# vi test02-2var.sh
#!/bin/bash 
# 這個腳本用途在於引用兩個變數,順便比較一下 " 與 ' 的異同
# Date: 2002/06/27
# Made by VBird
name="V.Bird"
myname1="My name is $name"
myname2='My name is $name'
echo $name
echo $myname1
echo $myname2

[root @test test]# sh test02-2var.sh
V.Bird
My name is V.Bird
My name is $name

看到輸出的結果了吧!呵呵!沒錯!那個 " 與 ' 最大的不同就是在於能不能保有『變數內容』啦!再提醒一次,那個單引號『 ' 』裡頭的資料都將變成『單純的字元』而不是有特殊的字體呦!


標籤與運算符號:declare

    OK!瞭解了變數的 scripts 寫法之後,現在我們來進行一個有趣的實驗好了!就是說,當我們在進行『計算』的時候,到底 bash 能不能瞭解我們所給予的是『數字』還是單純的『字元』呢?這個很重要的,因為會造成系統的誤判呦!好了,我們來試試看!當我們需要輸出 3 * 5 的結果時,需要如何做呢?用單純的 command line 一行一行輸入的結果如下:
     
    [root @test test]# a=3
    [root @test test]# b=5
    [root @test test]# c=$a*$b
    [root @test test]# echo $c
    3*5  <==糟糕!怎麼變成了字串了?!

    發現了嗎?嘿嘿!上面輸出的是不是我們所希望的 3*5 = 15 的結果?嗯!這是因為我們沒有定義該變數,則該變數預設是呈現『字串』的型態!那麼自然 $c 就成為自串型態了!所以我們需要來宣告一下變數(嘿嘿!跟程式語言很相近吧!也是需要宣告變數的啦!),宣告變數使用的是 declare 這個指令,而變數名稱有底下這些囉!


  • declare
    宣告變數內容
    語法
    [test @test test]# declare [-afirx]
    參數說明:
    -a  :定義為陣列 array
    -f  :定義為函數 function 
    -i  :定義為整數 integer
    -r  :定義為『唯讀』
    -x  :定義為透過環境輸出變數
    範例:
    [test @test test]# declare -i a=3
    [test @test test]# declare -i b=5
    [test @test test]# declare -i c=$a*$b
    [test @test test]# echo $c
    15  <==變成數字囉! ^_^
初步瞭解了吧!?好了,現在我們來玩玩看,如果您的計算結果當中,需要輸入為 2*3+5*13-32+25 時,並且在最後輸出『 Your result is ==> 』該怎樣寫這一支簡單的 script 呢?可以這樣試試看:
 
[root @test test]# vi test03-declare.sh
#!/bin/bash
# This program is used to "declare" variables
# VBird 2002/06/27
number1=2*3+5*13-32+25
declare -i number2=2*3+5*13-32+25
echo "Your result is ==> $number1"
echo "Your result is ==> $number2"
[root @test test]# sh test03-declare.sh
Your result is ==> 2*3+5*13-32+25
Your result is ==> 64

怎樣?很有趣吧!更好玩的還在後頭呦!再往下看一下吧!


對談式 scripts :

什麼是對談式的 scripts 呢?很簡單啦!例如你在執行 Windows 的安裝程式時,系統不是常常會跳出一個視窗,問你『下一步』、『上一步』或『取消』嗎?那就是對談啦!程式會依據您輸入的資料來進行判斷,OK!那麼最簡單的對談式指令是什麼呢?呵呵!就是 read 這個指令啦! read 的功能就是『依據您在鍵盤輸入的結果 input 到變數內容中』,例如:
 
[root @test test]# read name
VBird <==這是鍵盤輸入的結果
[root @test test]# echo $name
VBird

好了!那麼我們來設定一下,當您的 script 在執行的時候,將您由鍵盤輸入的資料列出來!如何做呢?

[root @test test]# vi test04-read.sh
#!/bin/bash
# This program is used to "read" variables
# VBird 2002/06/27
echo "Please keyin your name, and press Enter to start."
read name
echo "This is your keyin data ==> $name"
[root @test test]# sh test04-read.sh
Please keyin your name, and press Enter to start.
VBird Tsai
This is your keyin data ==> VBird Tsai

就是這麼簡單,我們後面還會繼續的談到判別式,那個時候輸入的資料可就更重要了!

好了!下一步我們再來說一說怎樣定義一個 script 的參數的代號!?以底下我們的說明為例:
 
[root @test test]# myscript opt1 opt2 opt3 opt4
          $0    $1  $2  $3  $4

這是什麼意思呢?嘿嘿!就是說,在這個 script ( myscript )裡面,只要變數名稱為 $0 就表示為 myscript 這個咚咚,也就是說:

$0 : myscript 亦即是 script 的檔名
$1 : opt1 亦即是第一個附加的參數 (parameter)
$2 : opt2
$3 : opt3
這樣說或許不是很清楚,我們來玩一玩底下這個 script 看看就曉得他的意思啦!
 
[root @test test]# vi test05-0123
#!/bin/bash
# This program will define what is the parameters
# VBird 2002/06/27
echo "This script's name => $0"
echo "parameters $1 $2 $3"
[root @test test]# sh test05-0123 pa1 pa2 pa3
This script's name => test05-0123
parameters pa1 pa2 pa3

這個東西在運用上也是相當的重要的,例如當您要取得 script 的名稱時(因為有時候使用者會自行更改檔案名稱),則這個功能變數就相當的重要了!瞭解乎!?


scripts 邏輯判斷式與運算式:

再來的這個東西可就更重要了,尤其在 scripts 當中!那就如『如何判定某個檔案或目錄,或者是如何判定程式應該朝向那個方向行進』?這個東西需要有比較好一些的邏輯概念的說明才行!底下我們分別說明一下邏輯判斷式與運算式之後,再來設定幾個小 scripts 試試看不同的用法,以期得到大家的瞭解囉!
  • 邏輯判斷式:
    在 scripts 裡頭很重要的一項工作就是『判斷是否可行』的目標!舉個例子來說,當我們要建立一個目錄的時候,先偵測有沒有該目錄,如果有的話,那麼就不需要建立,如果沒有的話,那麼就建立該目錄!這個就需要 script 來主動的判斷了!那麼如何判斷呢?基本上由於是判斷式,那麼應該都會與『條件』有關的,所以底下的判斷式大多與『 if... then... fi 』這一種條件判斷式有關係!這部份後面再提,這裡先提一下邏輯判斷式的幾個重要的咚咚:
     
    邏輯標籤 表示意思
    1. 關於檔案與目錄的偵測邏輯標籤!
    -f 常用!偵測『檔案』是否存在
    -d 常用!偵測『目錄』是否存在
    -b 偵測是否為一個『 block 檔案
    -c 偵測是否為一個『 character 檔案
    -S 偵測是否為一個『 socket 標籤檔案
     -L 偵測是否為一個『 symbolic link 的檔案
     -e 偵測『某個東西』是否存在!
    2. 關於程序的邏輯標籤!
    -G 偵測是否由 GID 所執行的程序所擁有
    -O 偵測是否由 UID 所執行的程序所擁有
    -p 偵測是否為程序間傳送資訊的 name pipe 或是 FIFO (老實說,這個不太懂!)
    3.  關於檔案的屬性偵測!
    -r 偵測是否為可讀的屬性
    -w 偵測是否為可以寫入的屬性
    -x 偵測是否為可執行的屬性
    -s 偵測是否為『非空白檔案
    -u 偵測是否具有『 SUID 』的屬性
    -g 偵測是否具有『 SGID 』的屬性
    -k 偵測是否具有『 sticky bit 』的屬性
    4. 兩個檔案之間的判斷與比較 ;例如『 test file1 -nt file2
    -nt 第一個檔案比第二個檔案新
    -ot 第一個檔案比第二個檔案舊
    -ef 第一個檔案與第二個檔案為同一個檔案( link 之類的檔案)
    5. 邏輯的『和(and)』『或(or)』
    && 邏輯的 AND 的意思
    || 邏輯的 OR 的意思

    比較有趣的應該算是 1, 3 這兩種種類的判斷,尤其是在建立一些 permission 相關的檔案時,這個就更重要了!然後那個『兩個檔案之間的判斷』也是挺有意思的!有空的話不妨去試一試去!還有,那個 &&|| 這兩個東西也是很重要的!接著下來,我們要來談一談運算符號囉!

  • 運算符號簡介:
    在 bash shell scripts 的運算符號的加減乘除是怎樣的一回事呀!?談一談吧!
     
    運算符號 代表意義
    = 等於
    != 不等於
    < 小於
    > 大於
    -eq 等於
    -ne 不等於
    -lt 小於
    -gt 大於
    -le 小於或等於
    -ge 大於或等於
    -a 雙方都成立(and)
    -o 單方成立(or)
    -z 空字串
    -n 非空字串

    邏輯判斷式與 if...then...fi 的關係是密不可分的,我們底下就先來談一談這一個判斷式當中最常使用的語法吧!


條件式判斷:if...then...fi, case.....esac

  • 條件判斷一:if then fi 的方式
OK!剛剛我們 建立了第一支 script ,在螢幕上面以 script 來輸出問候語!好了,現在我們如果要讓 scripts 加上『判斷』要如何來工作呢?這就是所謂的條件式判斷了!最常使用到的就是『 if ... then .... else if .... then ... end if 』的作法了!這個條件判斷的語法為:
 
if [ 條件判斷一 ] && (||) [ 條件判斷二 ]; then       <== if 是起始的意思,後面可以接若干個判斷式,使用 && 或 ||
    執行內容程式
elif [ 條件判斷三 ] && (||) [ 條件判斷四 ]; then     <==第二段的判斷,如果第一段沒有符合就來此搜尋條件
    執行第二段內容程式
else                                            <==當前兩段都不符合時,就以這段內容來執行!
    執行第三段內容程式
fi                                              <==結束 if then 的條件判斷!

上面的意思是這這樣的:在中刮號『[]』裡面的是條件式,如果是複合式的條件判斷(如若A及B則C之類的邏輯判斷),那麼就需要在兩個中刮號之間加上『 && (and)』或者是『 || (or)』這樣的邏輯運算式才行!如果是多重選擇的話,那麼就需要以 elif (optional, 選擇性的,若有需要才加上!)來新增另一個條件;如果所有的條件都不適用,則使用 else (optional)來進行最後的執行內容囉!

不過,這裡有幾個新手常犯的錯誤,我們需要來加強說明一下:
  1. 在 [ ] 當中,只能有一個判別式;
  2. 在 [ ] 與 [ ] 當中,可以使用 && 或 || 來組織判別式;
  3. 每一個獨立的元件之間『都需要有空白鍵來隔開』!
尤其是最後一點,最容易犯的錯啦!好了,我們來進行一個簡單的判別式好了!
 
[root @test test]# vi test06-ifthen.sh
#!/bin/bash
# This program is used to study if then
# VBird 2002/06/27
echo "Press y to continue"
read yn
if [ "$yn" = "y" ]; then
        echo "script is running..."
else
        echo "STOP!"
fi
[root @test test]# sh test06-ifthen.sh
Press y to continue
y
script is running...
[root @test test]$ sh test06-ifthen.sh
Press y to continue
n
STOP!

很簡單的一個例子吧!當輸入為 y 的時候,就給他進行,若非為 y 則予以進行!但是這裡有個問題,就是如果我輸入為 Y 時,程式還是停止了!怎麼辦?!這個時候就需要使用到 || 這個東西啦!我們可以這樣做!

[root @test test]# cp test06-ifthen.sh test07-ifthen.sh
[root @test test]# vi test07-ifthen.sh
#!/bin/bash
# This program is used to study if then
# VBird 2002/06/27
echo "Press y to continue"
read yn
if [ "$yn" = "y" ] || [ "$yn" = "Y" ]; then
        echo "script is running..."
else
        echo "STOP!"
fi
[root @test test]# sh test07-ifthen.sh
Press y to continue
y
script is running...
[root @test test]$ sh test07-ifthen.sh
Press y to continue
Y
script is running...

好了!那麼如果再加上前面提過的: parameter 的選用呢?呵呵!這個也蠻有趣的,我們再來試試看:

[root @test test]# vi test08-ifthen.sh
#!/bin/bash
# set parameters in the if then
# 需要加上 hello 這個參數才會顯示正確的!
# VBird 2002/06/27
if [ "$1" = "hello" ]; then
        echo "Hello! How are you ?"
elif [ "$1" = "" ]; then
        echo "You MUST input parameters"
else
        echo "The only accept parameter is hello"
fi
[root @test test]# sh test08-ifthen.sh hello
Hello! How are you ?
[root @test test]$ sh test08-ifthen.sh
You MUST input parameters
[root @test test]$ sh test08-ifthen.sh djdkf
The only accept parameter is hello

呵呵!是不是不難呢?玩到這裡應該對於 scripts 的認識有一定程度的瞭解了吧!嗯!好了,底下我們來玩一個大的!假設您已經知道 netstat 與 grep 這兩個東西的用法,那麼如果要來偵測你的主機上面的 port 是否有開啟時,可以使用底下的範例來進行:

[test @test test]# vi port.sh                                  <==編輯一個檔案為 test1.sh 的 script
#!/bin/bash                                                     <==宣告使用的 shell 類型
# program: Using to study the [if ... then ... fi] program
# Made by:  VBird
# date:  2002/05/20
# content: I will using this program to show your services
# 1. print the program's work in your screen
  echo "Now, the services of your Linux system will be detect!"
  echo "The www, ftp, ssh, and sendmail + pop3 will be detect!"
  echo " "
# 2. www
  www=`netstat -an|grep LISTEN|grep :80`                    <==這個就是變數啦!並使用了管線命令!
  if [ "$www" != "" ]; then                                     <==開始條件的判斷囉!
      echo "WWW is running"                                <==若條件成立,那麼就列印這一行的內容!
  else
      echo "WWW is NOT running"
  fi
# 3. ftp
  ftp=`netstat -an|grep LISTEN|grep :21`
  if [ "$ftp" != "" ]; then
      echo "FTP is running"
  else
      echo "FTP is NOT running"
  fi
# 4. ssh
  ssh=`netstat -an|grep LISTEN|grep :22`
  if [ "$ssh" != "" ]; then
      echo "SSH is running"
  else
      echo "SSH is NOT running"
  fi
# 5. sendmail + pop3
  smtp=`netstat -an|grep LISTEN|grep :25`
  pop3=`netstat -an|grep LISTEN|grep :110`
  if [ "$smtp" != "" ]   && [ "$pop3" != "" ]; then           <==有兩個以上的條件式,就使用 && 或 || 來分隔!
      echo "sendmail is OK!"
  elif [ "$smtp" != "" ] && [ "$pop3"  = "" ]; then
      echo "sendmail have some problem of your pop3"
  elif [ "$smtp"  = "" ] && [ "$pop3" != "" ]; then
      echo "sendmail have some problem of your smtp"
  else
      echo "sendmail is NOT running"
  fi
[test @test test]# sh port.sh                                <==執行看看輸出的結果!
Now, the services of your Linux system will be detect!
The www, ftp, ssh, and sendmail + pop3 will be detect!

WWW is running
FTP is running
SSH is running
sendmail is OK!

很簡單吧!上面這樣就可以將你主機上面的資料進行解析囉!

  • 條件判斷二:使用 case ...esac 的方式
剛剛的『 if then fi 』的形式是以程式來自行判斷,那麼如果我已經規劃好幾個項目要來執行,只要選擇執行的『種類方式』就可以正確的執行的話,要怎麼做呢?最簡單的例子就是我們常常使用到的 /etc/rc.d/init.d/ 裡頭的 scripts 囉!例如:重新啟動 xinetd 是使用:
/etc/rc.d/init.d/xinetd restart
注意囉!那個是 restart 的項目,然後 script 就會自動的去搜尋 restart 項目裡面的情況去執行!那個就是 case ... esac 的使用模式囉!有沒有注意到,開始是『 case 』結束則是使用 case 的倒寫『 esac 』喝!很有趣吧!那麼這種格式是怎樣呢?
 
case 種類方式(string) in          <==開始階段,那個種類方式可分成兩種類型,通常使用 $1 這一種直接下達類型!
    種類方式一)
       程式執行段
       ;;                     <==種類方式一的結束符號!
    種類方式二)
       程式執行段
       ;;
    *)
       echo "Usage: {種類方式一|種類方式二}"     <==列出可以利用的參數值!
       exit 1
esac                         <==這個 case 的設定結束處!

在種類方式(string)的格式主要有兩種:

  1. 直接下達式:就是以『 執行檔案 + string 』的方式來執行的(/etc/rc.d/init.d 裡頭的基本設定方式),則 string 可以直接寫成『 $1 』(在執行檔案後面直接加入參數的第一個參數!)
  2. 互動式:就是由螢幕輸出可能的項目,然後讓使用者輸入,這個通常必須配合『 read variable 』然後 string 則寫成『 $variable 』的格式!
同樣的,我們建立一個名為 test2.sh 的檔案來試做看看。假如我們共可分三段格式來進行實作,分別為 one, two, three ,並假設使用直接下達式,則可以寫成:
 
[test @test test]# vi test09-case.sh
#!/bin/bash
# program:      Using case mode
# Made by:      VBird
# date:         2002/05/20
# content:      I will use this program to study the case mode!
# 1. print this program
  echo "This program will print your selection!"

case $1 in                                   <==使用直接下達指令型態!
  one)
        echo "your choice is one"
        ;;
  two)
        echo "your choice is two"
        ;;
  three)
        echo "your choice is three"
        ;;
  *)
        echo "Usage {one|two|three}"       <==列出可以使用的參數(如果使用者下達錯誤的參數時)
        exit 1
esac
[test @test test]# sh test09-case.sh       <==執行結果!顯示沒有相對的參數!所以列出可以參數!
This program will print your selection!
Usage {one|two|three}
[test @test test]# sh test09-case.sh three
This program will print your selection!
your choice is three

那麼對談式的 case 又如何呢?嗯!我們利用上面的方式來修改一下內容囉!

[root @test test]# vi test10-case.sh
#!/bin/bash
# program:      Using case mode
# Made by:      VBird
# date:         2002/06/27
# content:      I will use this program to study the case mode!
# 1. print this program
echo "Press your select one, two, three"
read number

case $number in
  one)
        echo "your choice is one"
        ;;
  two)
        echo "your choice is two"
        ;;
  three)
        echo "your choice is three"
        ;;
  *)
        echo "Usage {one|two|three}"
        exit 1
esac
[root @test test]# sh test10-case.sh
Press your select one, two, three
two   <=這一行是您輸入的呦!
your choice is two

如何!很簡單吧!以後對於 /etc/rc.d/init.d/ 裡頭的 script 就應該看的懂了吧!此外,由於還有所謂的『函數(function)』也就是『先將需要執行的程式段寫成一個小區塊,而這個小區塊則以一個名稱來取代之』,簡單的方式可以請您參考一下您系統中的 /etc/rc.d/init.d/sendmail !注意看一下 start() 底下的那些個咚咚!你就可以知道什麼意思了!由於我們這裡並不教你如何寫程式(基本上, scripts 就是小程式啦!還好! VBird 以前就有程式的底子!不然還真怕 script 呢!),所以就只好點到為止囉!


迴圈:for....do....done, while...do...done, until...do...done,

在程式段當中,最常使用到的就是迴圈了!迴圈是很重要的一項工具,尤其是具有判斷形式的迴圈,很常被使用來判斷一些事項的可行性與否!但是程式怎麼知道什麼時候應該要停止這個程式呢?呵呵!就需要加入判斷囉!好了,最簡單的判斷式可以是底下幾種:
  • for (( 條件一; 條件二; 條件三 ))
  • for variable in variable1 variable2 .....
  • while [ condition1 ] && { || } [ condition2 ] ...
  • until [ condition1 ] && { || } [ condition2 ] ...
for 是已經知道有多少個 run 了,即是已經知道要跑幾次了,至於 until 與 while 則分別是:
  • until:直到條件相同的時候才離開程式』;
  • while:當條件相同的時候,就繼續做!
這兩者不太相同的啦!
好了!我們先來談一下最簡單的迴圈,就是利用 for 這個東西來進行!好了,假設我們計算 1 + 2 + 3 .... + 100 ,以 script 要如何寫呢?有很多的方式,我們來談一談 do...done 好了!
 
[test @test test]# vi test11-loop.sh
#!/bin/bash
# Using for and loop
# VBird 2002/06/27
declare -i s  # <==變數宣告
for (( i=1; i<=100; i=i+1 ))
do
        s=s+i
done
echo "The count is ==> $s"

[test @test test]# sh test11-loop.sh
The count is ==> 5050

請注意! for (( 條件一; 條件二; 條件三)) 這是必須要的!

  • 條件一:這可以看成是『初始值』,如上面的例子中,初始值是 i=1 啦!
  • 條件二:這可以看成是『符合值』,如上面的例子中,當 i<=100 的時候都是符合條件的!
  • 條件三:這可以看成是『步階』!也就是說, i 每次都加一!
所以啦!上面的例子是說:由 i=1 開始到 i<= 100 ,每次 i 都加一來執行底下的程式段(就是 s=s+i ),當 i >100 (也就是 i=101 )就跳出這一段程式段!怎樣!不難吧!
好了!那麼使用 while 或者是 until 要怎樣執行呢?其實都是差不多的情況!我們使用底下的兩個 script 來進行 1 ~ 100 的累加動作!
 
1. 使用 while :
[test @test test]# vi test12-loop.sh
#!/bin/bash
# Using while and loop
# VBird 2002/06/27
declare -i i
declare -i s
while [ "$i" != "101" ]
do
        s=s+i
        i=i+1
done
echo "The count is ==> $s"

2. 使用 until :
[test @test test]# vi test13-loop.sh
#!/bin/bash
# Using until and loop
# VBird 2002/06/27
declare -i i
declare -i s
until [ "$i" = "101" ]
do
        s=s+i
        i=i+1
done
echo "The count is ==> $s"

[test @test test]# sh test12-loop.sh
The count is ==> 5050

嘻嘻嘻嘻!很簡單吧!

第二個例子來自於網友 jony 的提供!這是另外一種迴圈的方式,可以用來判斷非數字的類型呦!
 
[test @test test]# vi test14-for.sh
#!/bin/bash
# using for...do ....done
# VBird 2002/06/27

LIST="Tomy Jony Mary Geoge"

for i in $LIST
do
        echo $i
done

[test @test test]# sh test5.sh
Tomy
Jony
Mary
Geoge

這一種格式是以空白鍵當作 i 這個變數的選擇項目!也就是說,上面的 $LIST 這個變數當中,以空白鍵來分隔的時候,共可以分離出來四個!所以囉!當以 do ..... done ... 就可以分別寫出四個咚咚啦!好啦!那麼有沒有辦法利用這個東西來將你的 Linux 主機上的帳號 ( account ) 印出來呢?!很簡單呀!我們利用 cut 跟 sort 以及 /etc/passwd 這個檔案來完成這一支 script ,作法如下囉:

[test @test test]# vi test15-for.sh
#!/bin/bash
# Using for and loop to read the account of this linux server!
# VBird 2002/06/27
account=`cut -d ":" -f1 /etc/passwd|sort`
echo "The following is your linux server's account"

for i in $account
do
        echo $i
done

[test @test test]# sh test15-for.sh
The following is your linux server's account
adm
aerosol
alenchan
amanda
apache
....

OK!再來,我們來使用一下對談式的迴圈作用吧!嗯!當我們輸入 y 或 Y 時,程式就予以結束!該怎樣做?!

[test @test test]# vi test16-loop.sh
#!/bin/bash
# Using until
# VBird 2002/06/27

echo "Press Y/y to stop"
until [ "$yn" = "Y" ] || [ "$yn" = "y" ]
do
        read yn
done
echo "Stop here"

[test @test test]# sh test16-for.sh
Press Y/y to stop

GDSG
A
Y
Stop here

上面說的是,當輸入 Y 或者是 y 時才跳出 do...done 的迴圈之中!而去執行底下的東西!哈哈!很好玩吧!嗯!接著下來,我們來判斷一下目錄是否存在好了!這是常用的呦!

接下來我們判別一下所謂的『邏輯判斷式』的使用方式啦!剛剛我們不是已經知道了嗎,我們可以使用條件判斷來斷定到底有沒有檔案(用 -e )或者是該名稱是屬於目錄或者是檔案( -d -f ),接下來我們來判斷一個流程好了:
  1. 先查看一下 /root/test/logical 這個名稱是否存在;
  2. 若不存在,則建立一個檔案,使用 touch 來建立,建立完成後離開;
  3. 如果存在的話,判斷該名稱是否為檔案,若為檔案則將之刪除後建立一個檔案,檔名為 logical ,之後離開;
  4. 如果存在的話,而且該名稱為目錄,則移除此目錄!
看起來似乎很複雜,其實很簡單的啦!我們來試試看:
 
[test @test test]# vi test17-ifthen.sh
#!/bin/bash
# using if and then to select file or directory
# VBird 2002/06/27
if [ ! -e logical ]; then
        touch logical
        echo "Just make a file logical"
        exit 1
elif [ -e logical ] && [ -f logical ]; then
        rm logical
        mkdir logical
        echo "remove file ==> logical"
        echo "and make directory logical"
        exit 1
elif [ -e logical ] && [ -d logical ]; then
        rm -rf logical
        echo "remove directory ==> logical"
        exit 1
else
        echo "Does here have anything?"
fi

然後請你依序執行 sh test17-ifthen.sh ; ll 看看這個目錄底下 logical 那個檔案有什麼變化狀況!呵呵!瞭解了嗎?就是這麼簡單!這個動作可以讓我們很輕鬆的就判別到某個檔案的存在與否!嗯!不錯用!趕快來使用看看吧!


script 如何 debug

scripts 在執行之前,最怕的就是出現問題了!那麼我們如何 debug 呢?有沒有辦法不需要透過直接執行該 scripts 就可以來判斷是否有問題呢!?呵呵!當然是有的!我們就直接以 sh 來進行判斷吧!
 
[test @test test]# sh [-nvx] scripts
-n :不要執行 scripts ,查詢 scripts 內的語法,若有錯誤則予以列出!
-v :在執行 scripts 之前,先將 scripts 的內容顯示在螢幕上;
-x :將有使用到的 scripts 內容顯示在螢幕上,與 -v 稍微不同!
[test @test test]# sh -n test01-hello.sh
[test @test test]# sh -v test01-hello.sh
#!/bin/bash
# This program will print the "Hello! How are you" in your monitor
# Date: 2002/06/27
# User: VBird
hello="Hello! How are you"
echo $hello
Hello! How are you
[test @test test]# sh -x test01-hello.sh
+ hello=Hello! How are you
+ echo 'Hello!' How are you
Hello! How are you

熟悉 sh 的用法,將可以使您在管理 Linux 的過程中得心應手!
 
對於 Shell scripts 的學習方法上面,需要『多看、多模仿、並加以修改成自己的樣式!』是最快的學習手段了!網路上有相當多的朋友在開發一些相當有用的 scripts ,若是您可以將對方的 scripts 拿來,並且改成適合自己主機的樣子!那麼學習的效果會是最快的呢!

posted @ 2010-10-19 10:39  BloodAndBone  Views(364)  Comments(0Edit  收藏  举报