鳥哥linux的簡單sh程式設計—http://blog.chinaunix.net/u/22249/showart.php?id=149846

最美的回憶發表於2017-11-16
幹嘛學習 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 拿來,並且改成適合自己主機的樣子!那麼學習的效果會是最快的呢

本文轉自kenty部落格園部落格,原文連結

http://www.cnblogs.com/kentyshang/archive/2007/07/11/814087.html如需轉載請自行聯絡原作者


kenty


相關文章