摘要:概述、script的編寫、test命令、[]判斷符號、默認變量($1...)、if...then條件判斷式、正則表達式
1、概述shell
【什麼是shell script】bash
針對shell所寫的腳本,將多個命令彙整起來一塊兒執行網絡
能夠進行相似程序的編寫,而且不須要通過編譯就可以執行less
利用shell的功能所寫的一個「程序」,這個程序是使用純文本文件,將一些shell的語法與命令寫在裏面,搭配正則表達式、管道命令與數據流重定向等功能,以達到咱們所想要的處理目的。ide
【用途】函數
簡化咱們平常的工做管理oop
一些服務的啓動都是經過shell script進行的測試
2、編寫第一個Hello world程序this
【預處理】
新建一個script文件:vi helloworld.sh
【代碼】
1 #!bin/bash 2 # Program: 3 # This is my first script. 4 # History: 5 # 2017-9-30 liuyu First release 6 7 echo "Hello World!" 8 exit 0
說明:
#!bin/bash:聲明這個script使用的shell名稱
聲明這個文件內是使用bash的語法,即這個程序被執行時,它就可以加載bash的相關環境配置文件(通常來講就是non-login shell的~/.bashrc),而且執行bash使咱們下面的命名可以執行。
exit 0:告知執行結果
咱們能夠利用exit這個命令來讓程序中斷,而且回傳一個數值給系統。如「exit 0」表明離開script而且回傳一個0給系統,即咱們執行完這個script後,若接着執行echo $?則可獲得0的值。
【執行script程序】
bash 文件名
3、簡單的shell script練習
1. 交互式腳本:變量內容由用戶決定
題目:請你以read命令的用途,編寫一個script,它可讓用戶輸入firstname與lastname,最後而且在屏幕上顯示「Your full name is: 」的內容。
1 #!bin/bash 2 # Program: 3 # an easy interactive program 4 # History: 5 # 2017-9-30 liuyu First release 6 7 8 read -p "Please input your firstname: " firstname 9 read -p "please input your lastname: " lastname 10 echo "Your full name is $firstname $lastname!"
2. 把日期做文件名:利用日期進行文件的建立
題目:我但願將天天的數據備份在不一樣的文件裏,因此就須要以天天的日期做爲文件名。關鍵是日期怎麼來!假設我要建立3個空的文件,文件名最開頭由用戶決定(咱們假設是filename),那今天的日期是2017/9/30,我想之前天、昨天、今天的日期來建立這些文件,即filename20170928, filename20170929, dilename20170930,該如何是好?
1 #!bin/bash 2 # Program: 3 # filename is created by user's input. 4 # History: 5 # 2017-9-30 liuyu First release 6 7 echo "I will use 'touch' to create three files." 8 read -p "Please input your filename: " fileuser 9 10 #開始判斷有否配置文件名,防止用戶隨意按[Enter],咱們默認開頭爲filename 11 filename=${fileuser:-"filename"} 12 13 date1=$(date --date='2 days ago' +%Y%m%d) #前兩天的日期 14 date2=$(date --date='1 days ago' +%Y%m%d) 15 date3=$(date +%Y%m%d) #今天的日期 16 file1=${filename}${date1} #追加的方式配置文件名 17 file2=${filename}${date2} 18 file3=${filename}${date3} 19 20 touch "$file1" #防止有空格 21 touch "$file2" 22 touch "$file3"
說明:此程序運用了許多bash中的變量知識,因此學好shell才能輕鬆地編寫script!
3. 數值運算:簡單的加減乘除
題目:讓用戶輸入兩個整數,而後計算出這兩個數相乘的結果。
1 #!bin/bash 2 # Program: 3 # multiply two integer. 4 # History: 5 # liuyu 2017-9-30 First release 6 7 echo "You should input 2 integers,i will cross them!" 8 read -p "first number: " firnum 9 read -p "second number: " secnum 10 total=$(($firnum*$secnum)) 11 echo "The result of $firnum*$secnum is $total."
4、test命令的測試功能
1. 功能
檢測系統上面某些文件、測試文件的相關屬性。
2. 經常使用命令
命令 | 意義 |
test -e filename | 該文件名是否存在 |
test -f filename | 該文件名是否存在且爲文件 |
test -e filename | 該文件名是否存在且爲目錄 |
test -S filename | 該文件名是否存在且爲一個Socket文件 |
test -L filename | 該文件名是否存在且爲一個鏈接文件 |
test -r filename | 該文件名是否存在且具備「可讀」的權限 |
test -w filename | 該文件名是否存在且具備「可寫」的權限 |
test -x filename | 該文件名是否存在且具備「可執行」的權限 |
test file1 -nt file2 | 判斷file1是否比file2新 |
test file1 -ef file2 | 判斷file1與file2是否爲同一個文件,主要用於hard link |
test n1 -eq n2 | 兩數值相等 |
test n1 -gt n2 | n1大於n2 |
test n1 -lt n2 | n1小於n2 |
test n1 -ge n2 | n1大於等於n2 |
test n1 -le n2 | n1小於等於n2 |
test -z string | 判斷是否爲空字符串,如果,返回true |
test str1=str2 | 判斷str1是否等於str2 |
-a | 兩個條件同時成立,如test -r file -a -x file,則file同時具備r與x權限時,纔回傳true |
-o | 任何一個條件成立,如test -r file -o -x file,則file具備r或x權限時,就可回傳true |
! | 反向狀態,如test ! -x file,當file不具備x時,纔回傳true |
3. 示例
題目:寫一個script,讓用戶輸入一個文件名,要求進行下面的判斷:
這個文件是否存在,若不存在則給予一個「Filename does not exist」的信息,並中斷程序;
若這個文件存在,則判斷它是個目錄或文件,結果輸出「Filename is regular file」或「Filename is directory」;
判斷一下,執行者的身份對這個文件或目錄所擁有的權限,並輸出權限數據。
1 #!bin/bash 2 # Program: 3 # A script which covers the using of test. 4 # History: 5 # 2017-9-30 liuyu First release 6 7 echo "Please input a filename, I will check the filename's type and permission." 8 read -p "Input a filename: " filename 9 test -z $filename && echo "You must input a filename." && exit 0 10 11 test ! -e $filename && echo "The filename '$filename' DO NOT exist" && exit 0 12 13 test -f $filename && filetype="regular file" 14 test -d $filename && filetype="directory" 15 test -r $filename && perm="readable" 16 test -w $filename && perm="writable" 17 test -x $filename && perm="executable" 18 19 echo "The filename: $filename is a $filetype" 20 echo "And the permissions are : $perm"
5、判斷符號[]的使用
1. 功能
數據的判斷、字符串判別
2. 用法
命令 | 意義 |
[ -z "$HOME" ] | 判斷HOME變量是否爲空 |
[ "$HOME" == "$var" ] | 判斷兩個變量是否相等 |
[ "$HOME" == "string" ] | 判斷變量的內容是否爲string |
3. 示例
題目:寫一個script,要求以下:
當執行一個程序的時候,這個程序會讓用戶選擇Y或N;
若是用戶輸入Y或y時,就顯示「OK, continue」;
若是用戶輸入N或n時,就顯示「Oh, interrupt!」;
若是不是Y/y/N/n以內的其餘字符,就顯示「I don't know what your choice is」。
1 #!/bin/bash 2 # Program: 3 # A practice with []. 4 # History: 5 # 2017-9-30 liuyu First release 6 7 read -p "Please input (Y/N): " yn 8 [ "$yn" == "Y" -o "$yn" == "y" ] && echo "OK, continue" && exit 0 9 [ "$yn" == "N" -o "$yn" == "n" ] && echo "Oh, interrupt!" && exit 0 10 echo "I don't know what your choice is." && exit 0
6、默認變量($0,$1...)
1. 概述
咱們知道命令能夠帶有參數,而咱們還須要知道的是shell script也能夠在腳本文件名後面帶有參數。(注意!必定是script文件喔!)
2. 示例
題目:從新啓動系統註冊表文件
命令:/etc/init.d/syslog restart
評講:此命令能夠從新啓動/etc/init.d/syslog這個程序
題目:承上,關閉該服務
命令:/etc/init.d/syslog stop
3. 用法
文件名 opt1 opt2 opt3 opt4
$0 $1 $2 $3 $4
解釋:執行的腳本文件名爲$0這個變量,第一個接的參數就是$1。
補充:只要咱們在script裏面善用$1的話,就能夠很簡單地當即執行某些命令功能了!
補充:除了這些數字的變量以外,咱們還有一些較爲特殊的變量能夠在script內使用來調用這些參數。
$#:表明後接的參數「個數」
$@:表明"$1"、"$2"、"$3"、"$4"之意,每一個變量是獨立的(用雙引號括起來)
$*:表明「"$1c$2c$3c$4"」,其中c爲分隔字符,默認爲空格鍵,因此本例中表明「"$1 $2 $3 $4"」之意
4. 練習
題目:假設你要執行一個能夠帶參數的script,執行該腳本後屏幕會顯示以下的數據。
程序的文件名
共有幾個參數
若參數的個數小於2則告知用戶參數數量太少
所有的參數內容
第一個參數
第二個參數
1 #!/bin/bash 2 # Program: 3 # Default variable of shell script. 4 # History: 5 # 2017-10-1 liuyu First release 6 7 echo "The script name is ==> $0" 8 echo "Total parameter number is ==> $#" 9 [ "$#" -lt 2 ] && echo "The number of parameter is less than 2. Stop here." && exit 0 10 echo "Your whole parameter is ==> '$@'" 11 echo "The 1st parameter ==> $1" 12 echo "The 2nd parameter ==> $2"
注意:參數個數就是你執行該文件時在該文件後加的參數個數,即,若你執行「bash sh07.sh」,則參數個數爲0。
5. shift:形成參數變量號碼偏移
咱們要知道的是——腳本後面所接的變量可以進行偏移。
咱們經過一個例子來講明偏移是什麼。
題目:咱們將上個文件中的內容稍做變化,用來顯示每次偏移後參數的變化狀況。
1 #!/bin/bash 2 # Program: 3 # Default variable of shell script. 4 # History: 5 # 2017-10-1 liuyu First release 6 7 echo "Total parameter number is ==> $#" 8 echo "Your whole parameter is ==> '$@'" 9 shift #進行第一次「一個變量的shift」 10 echo "Total parameter number is ==> $#" 11 echo "Your whole parameter is ==> '$@'" 12 shift 3 #進行第二次「三個變量的shift」 13 echo "Total parameter number is ==> $#" 14 echo "Your whole parameter is ==> '$@'"
若是咱們執行「bash sh08.sh one two three four five six」,咱們會看到以下顯示:
分析:經過這個結果,咱們知道shift會移動變量,並且shift後面能夠接數字,表明拿掉最前面的幾個參數的意思。
注:「七/八/九」都屬於條件判斷式下的子內容。
7、條件判斷式——if...then
1. 單層判斷
【命令】
if [ 條件判斷式 ]; then
當條件判斷式成立時,能夠進行的命令工做內容;
fi
【條件判斷式】
當有多個條件要判別時,除了能夠將多個條件寫入一箇中括號內的狀況以外,還可使用多箇中括號,而此時每一箇中括號內只寫入一個判斷式。
即[ "$yn" == "Y" -o "$yn" == "y" ] 能夠被替換爲 [ "$yn" == "Y" ] || [ "$yn" == "y" ]
【示例】
題目:將sh06.sh這個腳本修改爲爲if...then的樣式
1 #!/bin/bash 2 # Program: 3 # A practice with []. 4 # History: 5 # 2017-9-30 liuyu First release 6 7 read -p "Please input (Y/N): " yn 8 if [ "$yn" == "Y" ] || [ "$yn" == "y" ]; then 9 echo "OK, continue" 10 exit 0 11 fi 12 if [ "$yn" == "N" ] || [ "$yn" == "n" ]; then 13 echo "oh, interrupt!" 14 exit 0 15 fi 16 echo "I don't know what your choice is." && exit 0
2. 多層判斷
【命令1】
if [ 條件判斷式 ]; then
當條件判斷式成立時,能夠進行的命令工做內容;
else
當條件判斷式不成立時,能夠進行的命令工做內容;
fi
【命令2】
if [ 條件判斷式一 ]; then
當條件判斷式一成立時,能夠進行的命令工做內容;
elif [ 條件判斷式二 ]; then
當條件判斷式二成立時,能夠進行的命令工做內容;
else
當條件判斷式一與二均不成立時,能夠進行的命令工做內容;
fi
【示例】
題目:將sh06-2.sh這個腳本修改爲爲if...elif...else的樣式
1 #!/bin/bash 2 # Program: 3 # A practice with []. 4 # History: 5 # 2017-9-30 liuyu First release 6 7 read -p "Please input (Y/N): " yn 8 if [ "$yn" == "Y" ] || [ "$yn" == "y" ]; then 9 echo "OK, continue" 10 elif [ "$yn" == "N" ] || [ "$yn" == "n" ]; then 11 echo "oh, interrupt!" 12 else 13 echo "I don't know what your choice is." 14 fi
【練習】
題目:通常來講,若是你不但願用戶由鍵盤輸入額外的數據時,可使用上一節提到的參數功能($1)!讓用戶在執行命令時就將參數代進去。如今咱們想讓用戶輸入「hello」這個關鍵字時,利用參數的方法能夠這樣依序設計:①判斷$1是否爲hello,若是是的話,就顯示「Hello,how are you?」;②若是沒有加任何參數,就提示用戶必需要使用的參數;③而若是加入的參數不是hello,就提醒用戶僅能使用hello爲參數。
1 #!/bin/bash 2 # Program: 3 # Check $1 is equal to "hello" 4 # History: 5 # 2017-10-1 liuyu FIrst release 6 7 if [ "$1" == "hello" ]; then 8 echo "Hello,how are you?" 9 elif [ "$1" == "" ]; then 10 echo "You must input parameters,ex> {$0 someword}" 11 else 12 echo "The only parameter is 'hello',ex> {$0 hello}" 13 fi
評講:咱們在$1的位置分別輸入hello、沒有輸入、隨意輸入,就能夠看到不一樣的輸出。
8、利用case...esac判斷
9、利用函數功能
10、循環(loop)
1. 條件循環
【while do done】
while [ condition ] //中括號內的狀態就是判斷式
do //循環的開始
程序段落
done //循環的結束
解釋:當 condition 條件成立時,就進行循環,直到 condition 的條件不成立才中止。
【until do done】
until [ condition ]
do
程序段落
done
解釋:當 condition 條件成立時,就終止循環,不然就持續進行循環的程序段。
【練習】
題目1:假設我要讓用戶輸入yes或者是YES才結束程序的執行,不然就一直進行告知用戶輸入字符串。
1 #!/bin/bash 2 # Program: 3 # while:Repeat question until user input correct answer. 4 # History: 5 # 2017-10-1 liuyu First release 6 7 while [ "$yn" != "yes" -a "$yn" != "YES" ] 8 do 9 read -p "Please input yes/YES to stop this program: " yn 10 done 11 echo "OK! you input the correct answer."
1 #!/bin/bash 2 # Program: 3 # until:Repeat question until user input correct answer. 4 # History: 5 # 2017-10-1 liuyu First release 6 7 until [ "$yn" == "yes" -o "$yn" == "YES" ] 8 do 9 read -p "Please input yes/YES to stop this program: " yn 10 done 11 echo "OK! you input the correct answer."
題目2:計算1+2+3+...+100這個數據。
1 #!/bin/bash 2 # Program: 3 # Use loop to calculate "1+2+3+...+100" result. 4 # History: 5 # 2017-10-1 liuyu First release 6 7 ans=0 # 這是累加的數值變量 8 i=0 # 這是累計的數值,亦便是1,2,3... 9 while [ "$i" != "100" ] 10 do 11 i=$(($i+1)) 12 ans=$(($ans+$i)) 13 done 14 echo "The result of '1+2+3+...+100' is ==> $ans"
題目3:讓用戶自行輸入一個數字,讓程序由1+2+...直到用戶輸入的數字爲止。
1 #!/bin/bash 2 # Program: 3 # practice of until of page 394. 4 # History: 5 # 2017-10-1 liuyu First release 6 7 ans=0 8 i=0 9 read -p "Please input a integer: " n 10 if [ "$n" -le "0" ]; then 11 echo "Sorry, you input a integer which isn't bigger than one!" 12 exit 0; 13 else 14 until [ "$i" -eq "$n" ] 15 do 16 i=$(($i+1)) 17 ans=$(($ans+$i)) 18 done 19 echo "The result of '1+2+3+...+$n' is ==> $ans" 20 fi
2. 固定循環
【for do done】
for var in con1 con2 con3 ...
do
程序段
done
解釋:變量var的內容在第 i 次循環時爲coni
【練習】
題目1:假設我有三種動物,分別是 dog, cat, elephant 三種,我想每一行都輸出這樣:「There are dogs...」之類的字樣。
1 #!/bin/bash 2 # Program: 3 # Using for...loop to print 3 animals 4 # History: 5 # 2017-10-1 liuyu First release 6 7 for animal in dog cat elephant 8 do 9 echo "There are ${animal}s..." 10 done
題目2:系統上的帳號都是寫在/etc/passwd內的第一個字段,你能不能經過管道命令 cut 找出單純的帳號名稱後,以 id 及 finger 分別檢查用戶的標識符與特殊參數呢?
1 #!/bin/bash 2 # Program: 3 # Use id,finger command to check system account's information. 4 # History: 5 # 2017-10-1 liuyu First release 6 7 users=$(cut -d ':' -f1 /etc/passwd) 8 for username in $users 9 do 10 id $username 11 finger $username 12 done
評講:執行此腳本後,咱們的系統帳號就會被獲取出來檢查。
補充:這個操做還能夠用在每一個帳號的刪除/更改上面呢!
題目3:我如今須要一連串的數字來進行循環。如我想要利用 ping 這個能夠判斷網絡狀態的命令。來進行網絡狀態的實際檢測時,我想要檢測的域是本機所在的192.168.1.1~192.168.1.100,因爲有100臺主機,故我不想在 for 後面輸入1到100。
1 #!/bin/bash 2 # Program: 3 # Use ping command to check the network's PC state. 4 # History: 5 # 2017-10-1 liuyu First release 6 7 network="192.168.1" #先定義一個域的前面部分 8 for sitenu in $(seq 1 100) #seq爲sequence(連續)的縮寫之意 9 do 10 #下面的語句取得ping的回傳值是正確的仍是失敗的 11 ping -c l -w l ${network}.${sitenu} &> /dev/null && result=0 || result=1 12 #開始回顯結果是正確的啓動(UP)仍是錯誤的沒有連通(DOWN) 13 if [ "$result" == 0 ]; then 14 echo "Sever ${network}.${sitenu} is UP." 15 else 16 echo "Sever ${network}.${sitenu} is DOWN." 17 fi 18 done
評講:上面這一串命令執行以後就能夠顯示出192.168.1.1~192.168.1.100共100部主機目前是否能與你的機器連通!若是你的域與咱們所在的位置不一樣,則直接修改上面那個network的變量內容便可!
題目4:讓用戶輸入某個目錄文件名,而後找出某目錄內的文件名的權限。
1 #!/bin/bash 2 # Program: 3 # User input dir name, I find the permission of files. 4 # History: 5 # 2017-10-1 liuyu First release 6 7 # 1.先看看這個目錄是否存在 8 read -p "Please input a directory: " dir 9 if [ "$dir" == "" -o ! -d "$dir" ]; then 10 echo "The $dir is NOT exist in your system." 11 exit 1; 12 fi 13 14 # 2. 開始測試文件 15 filelist=$(ls $dir) # 列出全部在該目錄下的文件名 16 for filename in $filelist 17 do 18 perm="" 19 test -r "$dir/$filename" && perm="$perm readable" 20 test -w "$dir/$filename" && perm="$perm writable" 21 test -x "$dir/$filename" && perm="$perm executable" 22 echo "The file $dir/$filenam's permission is $perm." 23 done
評講:此題涉及判斷式與循環的綜合。
【另外一種使用方式——適合於數值運算中】
for ( ( 初始值; 限制值; 執行步長 ) )
do
程序段
done
解釋:初始值爲某個變量在循環當中的初始值(直接以相似i=1設置好);限制值爲當變量的值在這個限制值的範圍內,就繼續進行循環,例如i<=100;執行步長爲每作一次循環時變量的變化量,如i=i+1。
題目:進行1累加到用戶輸入的循環
1 #!/bin/bash 2 # Program: 3 # Use for to calculate "1+2+...+${your_input}". 4 # History: 5 # 2017-10-1 liuyu release 6 7 read -p "Please input a number, I will count for 1+2+...+your_input: " n 8 9 ans=0 10 for ((i=1; i<=$n; i=i+1)) 11 do 12 ans=$(($ans+$i)) 13 done 14 echo "The result of '1+2+3+...+$n' is ==> $ans."
11、shell script的追蹤與調試
1. 概述
script在執行以前,最怕出現語法錯誤的問題了!那麼咱們如何調試呢?
咱們有沒有辦法不須要經過直接執行該 script 就能夠來判斷是否有問題呢?
有的,並且很簡單,只要在執行該script的命令中加上相關參數便可。
2. 用法
bash [-nx] 文件名 //-n爲不執行script,僅查詢語法的問題;-x爲將使用到的script內容顯示到屏幕上(執行過程顯示出來,很重要)