shell腳本控制流程

語言控制結構分爲三種:

順序執行:默認法則,逐條執行各語句

選擇執行:條件判斷,只有部分是符合條件的,只執行符合條件的部分

循環執行:將同一段代碼反覆的執行n次

這篇博客寫關於選擇控制結構。

linux的選擇控制結構有兩種一種是 if-then,一種是case--esac。

1、if-then

bash條件測試:

[ expression ]

` expression `

test expression

bash命令

if-then有三種結構形式:

單分支if語句

if [ 條件 ];then

語句...

fi

這種單分支的語句,當條件滿足的時候,就會運行then後面的語句,不滿足就直接退出判斷語句

eg:系統中是否存在mysql用戶,存在就顯示mysql exist.

1
2
3
4
5
#!/bin/bash
#this shell test mysql user exist system.
ifidmysql ;then
echo"mysql exist."
fi


雙分支if語句

if [ 條件 ];then

語句...

else

語句...

fi

這種雙分支的語句,等條件滿足的時候就會運行then後面的語句,條件不滿足的時候就運行else後面的語句。

eg1:如果指定的用戶存,先說明其已經存在,並顯示其ID號和SHELL;否則,就添加用戶,並顯示其ID號

1
2
3
4
5
6
7
8
9
10
11
#!/bin/bash
Username=mysql
ifid$Username &>/dev/null;then
Id=`grep"^$Username\>"/etc/passwd| cut-d: -f3`
Shell=`grep"^$Username\>"/etc/passwd| cut-d: -f7`
echo"$Username exist,ID is $Id,shell is $Shell."
else
useradd$Username
Id=`grep"^$Username\>"/etc/passwd| cut-d: -f3`
echo"$Username ID is $Id."
fi

eg2:判斷用戶是否存在,存在則顯示ID和SHELL,不存在就添加用戶,並顯示其ID。

分析:這題與上一個列子不一樣的地方是這個用戶沒有指定,既然沒有指定,就需要自己手動去shell一個參數,而腳本怎麼去引用參數。這裏就用到了bash變量中的位置變量

位置變量:$1,$2.....$9($1就是腳本傳遞的第一個參數...)

$0:腳本自身名稱

$@:所有位置參數的列表

$*:所有位置參數

$#:位置參數的個數

1
2
3
4
5
6
7
8
9
10
#!/bin/bash
ifid$1 &>/dev/null;then
Id=`grep"^$1\>"/etc/passwd| cut-d: -f3`
Shell=`grep"^$1\>"/etc/passwd| cut-d: -f7`
echo"$1 exist,ID is $Id,shell is $Shell."
else
useradd$1
Id=`grep"^$1\>"/etc/passwd| cut-d: -f3`
echo"$1 ID is $Id."
fi

運行腳本 bash eg2.sh mysql (eg.sh是腳本的名稱,mysql是傳遞給腳本的第一個參數)

eg3:通過參數傳遞一系列用戶名給腳本,讓腳本添加這些用戶;但要先判斷用戶是否存在,不存在而後再添加;添加完成後,顯示一共添加了幾個用戶;當然,不能包括因爲事先存在而沒有添加的;

分析:這個腳本不明確的是不知道要傳遞幾個參數,所以用位置變量有點不符合要求,所以引用了$@這個特殊的變量,然後這些用戶,你得一個一個的去取這些用戶,然後進行判斷是否存在,用循環控制瞭如何一個一個的取這些用戶,然後用戶不能重複的一個一個的取,所以用戶得取一個T掉$@列表中的用戶,用了shift命令,shift命令就是輪流的T除用戶。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#!/bin/bash
count=0
foruser in$@;do
ifid$1 &>/dev/null;then
echo"user $1 exsit."
shift
else
useradd$1
count=$[$count+1]
echo"add $1."
shift
fi
done
echo"total users:$count"


運行腳本

113958134.png


嵌套if語句(最常見的嵌套)

if [ 條件1 ];then

if [ 條件2 ];then

語句...

else

語句.....

fi

else

語句....

fi

這種嵌套的if語句就相對複雜一點,當條件1滿足時,就運行第一個then後面的語句,在條件1滿足後,在判斷條件2,當條件1和條件2同時滿足的時候就會運行第二個then後面的語句,當只有條件1滿足,條件2不滿足就會運行第一個else後面的語句,如果條件1都不滿足,那就直接運行第二個else後面的語句了。

eg4:判斷一個用戶,如果存在則判斷是否是普通用戶,還是系統用戶,還是admin用戶。不存在則顯示該用戶不存在。

分析:首先判斷用戶是否存在,存在則比較用戶的ID是否爲大於等於500,大於等於500則表示爲普通用戶,是否1-499,是則表示爲系統用戶,是否爲0,是則爲admin用戶。

本例子還用到了數值的比較,然後還用到了條件的組合

linux test命令支持數值比較、字符串比較、文件比較 詳情請man test

數值比較

num1 -eq num2 檢查num1是否等於num2

num1 -ge num2 檢查num1是否>或等於num2

num1 -gt num2 檢查num1是否大於num2

num1 -le num2 檢查num1是否<等於num2

num1 -lt num2 檢查num1是否<num2

num1 -ne num2 檢查num1是否不等於num2


組合條件測試

-a:與 [ $Uid -ge 1 -a $Uid -le 499 ]

-o:或 [ $Uid -eq 0 -a $Uid -ge 500 ]

!:非,單目操作符 [ ! $Uid -eq 0 ]


1
2
3
4
5
6
7
8
9
10
11
12
13
#!/bin/bash
ifid$1 &> /dev/null;then
Id=`grep"^$1\>"/etc/passwd| cut-d: -f3`
if[ $Id -ge500 ];then
echo"$1 is common user."
elif[ $Id -lt 500 -a $Id -ge1 ];then
echo"$1 is system user."
else
echo"$1 is admin user."
fi
else
echo"$1 Not exist."
fi

腳本執行結果

121056810.png

eg5:判定用戶的shell是否爲登錄shell;

分析:首先判斷用戶的shell是否存在,redhat中有一個用戶的shell就爲空,如果shell存在則判斷shell是否爲bash,如果是則表示爲登錄用戶,如果不是則表示爲不能登錄用戶。在redhat 5.x的版本上。


字符串比較

str1 = str2 檢查str1與str2是否相同

str1 != str2 檢查str1與str2是否不同

str1 < str2 檢查str1是否小於str2

str1 > str2 檢查str1是否大於str2

-n str1 檢查str1的長度是否大於0

-z str1 檢查str1的長度是否爲0

=~:判斷左邊的字符串是否能夠被右邊的模式所匹配,通常用於[[]]; [[ "$opt1" =~ pattern ]],

一般錨定行首和行尾

1
2
3
4
5
6
7
8
9
10
11
#!/bin/bash
Shell=`grep"^$1:"/etc/passwd| cut-d: -f7`
if[ -z $Shell ];then
echo"$1 user no shell"
else
if[ "$Shell"== "/bin/bash"]; then
echo"$1 user shell is login shell."
else
echo"$1 user shell is nologin shell."
fi
fi

運行結果

122900285.png

eg6:判斷當前主機的CPU生產商,其信息在/proc/cpuinfo文件中vendor id一行中。如果其生產商爲GenuineIntel,就顯示其爲Intel公司;否則,就顯示其爲AMD公司;


1
2
3
4
5
6
7
#!/bin/bash
Vendor=`grep"vendor_id"/proc/cpuinfo| uniq| cut-d: -f2`
if[[ "$Vendor"=~ [[:space:]]*GenuineIntel$ ]]; then
echo"Intel"
else
echo"AMD"
fi

運行結果

[root@Redhat5 test]# bash eg6.sh

Intel


eg7:

寫一個腳本:可以接受一個參數,其使用形式如下:

script.sh {start|stop|restart|status}

如果參數爲start,創建空文件/var/lock/subsys/script,並顯示“Starting script successfully.”;

如果參數爲stop,則刪除文件/var/lock/subsys/script,並顯示“Stop script finished.”;

如果參數爲restart,則刪除文件/var/lock/subsys/script後重新創建,並顯示“Restarting script successfully.”;

如果參數爲status,那麼:

如果/var/lock/subsys/script文件存在,則顯示爲“script is running.”

否則,則顯示爲“script is stopped.”

其它任何參數:則顯示“script.sh {start|stop|restart|status}”


文件比較

-b file 檢查文件是否存在且是一個塊特殊文件

-c file 檢查文件是否存在且是一個字符文件

-d file 檢查file是否存在並且是一個目錄

-e file 檢查文件是否存在

-f file 檢查文件是否存在並且是一個文件

-h file 檢查文件存在且爲一個符合鏈接

-r file 檢查文件是否存在並且可讀

-s file 檢查文件是否存在且不爲空

-w file 檢查文件是否存在且可寫

-x file 檢查文件是否存在且可執行

-O file 檢查文件是否存在且別當前用戶擁有

-G file 檢查是否存在並且默認組是否爲當前用戶組


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#!/bin/bash
#Author:litaotao
dir=`basename$0`
if[ $1 == "start"];then
touch/var/lock/subsys/$dir
echo"Starting script successfully."
elif[ $1 == "stop"];then
rm/var/lock/subsys/$dir&> /dev/null
echo"Stop script finished."
elif[ $1 == "restart"];then
rm/var/lock/subsys/$dir&> /dev/null
touch/var/lock/subsys/$dir
echo"Restarting script sucessfully."
elif[ $1 == "status"];then
if[ -e /var/lock/subsys/$dir];then
echo"script is running."
else
echo"script is stopped."
fi
else
echo"$dir.sh {statr|stop|restart|status}"
fi

運行方式 bash eg6.sh start 各位博友可以自己把shell copy後執行一遍分析結果


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章