學習 shell scripts(转)
幹嘛學習 Scripts
scripts 的執行與第一支 scripts:
標籤與運算符號:declare
對談式 scripts : read
scripts 邏輯判斷式與運算式:
條件式判斷:if...then...fi, case.....esac
迴圈:for....do....done, while...do...done, until...do...done,
script 如何 debug :
本章習題練習
這個問題可有趣的很了,我為什麼要學習 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 的執行:
嗯!在上一章 bash shell 當中說了一堆變數啦!管線指令啦!等等的,都是為了接著而來的 scripts 的咚咚啦!什麼是 script 啊?由字面上的意思來說, script 就是『腳本、劇本』的意思,那夠清楚了吧!就是將我們要執行的內容寫成一個『腳本』,讓系統依據這個『腳本』來執行我們想要的東西!好了!現在我們來討論一下怎麼寫 scripts 好了!基本上,一個 script 被執行的時候, bash 會據以判斷執行的步驟為:然後,在撰寫一個 scripts 的時候,最好養成良好的習慣:
- 如果讀取到一個 Enter 符號( CR ),就嘗試開始執行該行命令;
- 如同前面 bash command 提到的,指令間的多個空白會被忽略掉;
- 而空白行也將被忽略掉!,並且 tab 也是不會被理會的!
- 至於如果一行的內容太多,則可以使用 \ 來延伸至下一行;
- 此外,使用最多的 # 可做為註解!任何加在 # 後面的字,將全部被視為註解文字而被忽略!
那麼 scripts 這個檔案要如何來執行呢?執行的方法有兩種:
- 先宣告使用的 shell 為何?(特別留意這一點,在某些狀況中,例如 /etc/crontab 情況下,如果沒有宣告使用的 shell ,常常會出現錯誤訊息而導致 scripts 無法被執行呦!)
- 註明該 script 的內容功能、版本資訊、作者、建檔日期等等
- 每一個大步驟的主要功能(也順便提供自己未來修改之用!)
大致上就是這樣啦!OK!那麼還記得我們在前面一章已經說過了變數的設定方式了吧?好了,那麼我們就以第一支 scripts 來將我們設定的變數直接給他 show 出來!嗯!來設計一下這支 script 吧!
- 一個是將該檔案改成可以執行的屬性,如chmod 755 scripts.file ,然後執行該檔案;
- 另一種則是直接以 sh 這個執行檔來執行 script 的內容,如 sh scripts.file!
- 建立你的第一支 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 了呦!已經具有初階的程式設計能力囉!嗯!是該覺得高興的!^_^...!好了,接著下來我們寫稍微複雜一點的,若一個 script 裡頭有兩個以上的變數要相互引用呢?呵呵!這個時候順便來比較一下 " 與 ' 的異同吧!
- 所有在 scripts 裡面的東西,基本規則 ( 如變數設定規則 ) 需要與 command line 時相同;
- scripts 的附檔名最好為 .sh 提供他人的認識;
- 並非加上 .sh 就可以是執行檔,還需要查看其屬性中是否有 x 這個屬性。
[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看到輸出的結果了吧!呵呵!沒錯!那個 " 與 ' 最大的不同就是在於能不能保有『變數內容』啦!再提醒一次,那個單引號『 ' 』裡頭的資料都將變成『單純的字元』而不是有特殊的字體呦!
-
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 這個指令,而變數名稱有底下這些囉!
初步瞭解了吧!?好了,現在我們來玩玩看,如果您的計算結果當中,需要輸入為 2*3+5*13-32+25 時,並且在最後輸出『 Your result is ==> 』該怎樣寫這一支簡單的 script 呢?可以這樣試試看:
- 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 <==變成數字囉! ^_^
[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 呢?很簡單啦!例如你在執行 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 的檔名這樣說或許不是很清楚,我們來玩一玩底下這個 script 看看就曉得他的意思啦!
$1 : opt1 亦即是第一個附加的參數 (parameter)
$2 : opt2
$3 : opt3
[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 裡頭很重要的一項工作就是『判斷是否可行』的目標!舉個例子來說,當我們要建立一個目錄的時候,先偵測有沒有該目錄,如果有的話,那麼就不需要建立,如果沒有的話,那麼就建立該目錄!這個就需要 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
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)來進行最後的執行內容囉!
不過,這裡有幾個新手常犯的錯誤,我們需要來加強說明一下:尤其是最後一點,最容易犯的錯啦!好了,我們來進行一個簡單的判別式好了!
- 在 [ ] 當中,只能有一個判別式;
- 在 [ ] 與 [ ] 當中,可以使用 && 或 || 來組織判別式;
- 每一個獨立的元件之間『都需要有空白鍵來隔開』!
[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!很簡單吧!上面這樣就可以將你主機上面的資料進行解析囉!
剛剛的『 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)的格式主要有兩種:
同樣的,我們建立一個名為 test2.sh 的檔案來試做看看。假如我們共可分三段格式來進行實作,分別為 one, two, three ,並假設使用直接下達式,則可以寫成:
- 直接下達式:就是以『 執行檔案 + string 』的方式來執行的(/etc/rc.d/init.d 裡頭的基本設定方式),則 string 可以直接寫成『 $1 』(在執行檔案後面直接加入參數的第一個參數!)
- 互動式:就是由螢幕輸出可能的項目,然後讓使用者輸入,這個通常必須配合『 read variable 』然後 string 則寫成『 $variable 』的格式!
[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 numbercase $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 是已經知道有多少個 run 了,即是已經知道要跑幾次了,至於 until 與 while 則分別是:
- for (( 條件一; 條件二; 條件三 ))
- for variable in variable1 variable2 .....
- while [ condition1 ] && { || } [ condition2 ] ...
- until [ condition1 ] && { || } [ condition2 ] ...
這兩者不太相同的啦!
- 『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 都加一來執行底下的程式段(就是 s=s+i ),當 i >100 (也就是 i=101 )就跳出這一段程式段!怎樣!不難吧!
- 條件一:這可以看成是『初始值』,如上面的例子中,初始值是 i=1 啦!
- 條件二:這可以看成是『符合值』,如上面的例子中,當 i<=100 的時候都是符合條件的!
- 條件三:這可以看成是『步階』!也就是說, i 每次都加一!
好了!那麼使用 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/27LIST="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/27echo "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 stopGDSG
A
Y
Stop here上面說的是,當輸入 Y 或者是 y 時才跳出 do...done 的迴圈之中!而去執行底下的東西!哈哈!很好玩吧!嗯!接著下來,我們來判斷一下目錄是否存在好了!這是常用的呦!
接下來我們判別一下所謂的『邏輯判斷式』的使用方式啦!剛剛我們不是已經知道了嗎,我們可以使用條件判斷來斷定到底有沒有檔案(用 -e )或者是該名稱是屬於目錄或者是檔案( -d -f ),接下來我們來判斷一個流程好了:看起來似乎很複雜,其實很簡單的啦!我們來試試看:
- 先查看一下 /root/test/logical 這個名稱是否存在;
- 若不存在,則建立一個檔案,使用 touch 來建立,建立完成後離開;
- 如果存在的話,判斷該名稱是否為檔案,若為檔案則將之刪除後建立一個檔案,檔名為 logical ,之後離開;
- 如果存在的話,而且該名稱為目錄,則移除此目錄!
[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 那個檔案有什麼變化狀況!呵呵!瞭解了嗎?就是這麼簡單!這個動作可以讓我們很輕鬆的就判別到某個檔案的存在與否!嗯!不錯用!趕快來使用看看吧!
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 拿來,並且改成適合自己主機的樣子!那麼學習的效果會是最快的呢!