天天看點

shell腳本之判斷 if,elif, case

單分支if語句:

if 條件; then

語句1

語句2

...

fi

if 條件

then

例子1:寫一個腳本,實作如下功能:

如果使用者存在,就說明其存在;

#!/bin/bash

#

UserName=user1

if grep "^$UserName\>" /etc/passwd &> /dev/null; then

echo "$UserName exists."

if id $UserName &> /dev/null; then

練習:寫一個腳本,實作如下功能:

如果用存在,就顯示其UID和SHELL;

grep "^$UserName\>" /etc/passwd | cut -d: -f3,7

如果裝置/dev/sda3已經挂載,就顯示其挂載點;

Device='/dev/sda3'

if mount | grep "^$Device" &> /dev/null; then

mount | grep "/dev/sda3" | cut -d' ' -f3

如果/etc/rc.d/rc.sysinit中有空白行,就顯示其空白行數;

File='/etc/rc.d/rc.sysinit'

if grep "^$" $File &> /dev/null; then

grep "^$" $File | wc -l

雙分支if語句:

語句1

語句2

...

else

例子:寫一個腳本:

如果指定的使用者存,先說明其已經存在,并顯示其ID号和SHELL;否則,就添加使用者,并顯示其ID号;

如果裝置/dev/sda3已經挂載,就顯示其挂載點;否則,就說明其未挂載或裝置不存在;

echo "$Device not mounted or not exist."

bash條件測試:

[ expression ]

` expression `

test expression

整數測試

字元測試

檔案測試

整數測試:

expression: 數值1 比較符号 數值2

$A 比較符号 $B

大于:-gt, 例如 $A -gt $B

大于或等于:-ge

等于:-eq

小于:-lt

小于或等于:-le

不等于:-ne

例子:寫一個腳本,生成兩個随機數,比較其大小;顯示大數;

bash有個内置變量:$RANDOM

A=$RANDOM

B=$RANDOM

if [ $A -ge $B ]; then

echo "Max number is $A."

echo "Max number is $B."

練習:寫一腳本,随機生成一個整數,判定,顯示其奇偶性;

if [ $[$A%2] -eq 0 ]; then

echo "$A: Even"

echo "$A: Odd"

練習:給定一個使用者,如果其ID号大于499,就說明其是普通使用者,否則,就說明其是管理者或系統使用者;

UserName=daemon

Uid=`id -u $UserName`

if [ $Uid -gt 499 ]; then

echo "A common user: $UserName."

echo "admin user or system user: $UserName."

練習:求200以内所有為3的整數倍的整數之和;

Sum=0

for I in {1..200}; do

if [ $[$I%3] -eq 0 ]; then

Sum=$[$Sum+$I]

fi

done

echo "Sum: $Sum."

練習:給定一個使用者,如果其UID等于GID,就說明這是個“good guy”,否則,“Bad guy.”

if [ `id -u $UserName` -eq `id -g $UserName` ]; then

echo "Good Guy."

echo "Bad Guy."

寫一個腳本:

計算100以内所有奇數的和以及所有偶數的和;分别顯示之;

EvenSum=0

OddSum=0

for I in {1..100}; do

if [ $[$I%2] -eq 0 ]; then

EvenSum=$[$EvenSum+$I]

else

OddSum=$[$OddSum+$I]

echo "EvenSum is: $EvenSum. OddSum is: $OddSum."

bash程式設計: 位置變量

$1, $2, $3, $4, ...

計算N以内所有奇數的和以及所有偶數的和;分别顯示之;N是通過參數傳遞過來的正整數;

for I in `seq 1 $1`;do

if [ $[$I%2] -eq 1 ]; then

echo "EvenSum: $EvenSum."

echo "OddSUm: $OddSum."

echo "Sum: $[$EvenSum+$OddSum]"

shift [n]:實作位置參數輪替;

例子:通過參數傳遞n個正整數給腳本,求其和;

for I in `seq 1 $#`; do

Sum=$[$Sum+$1]

shift

echo $Sum

練習,寫一個腳本,完成以下要求:

1、添加10個使用者user1, user2, ..., user10;但要先判斷使用者是否存在,不存在而後再添加;

2、添加完成後,顯示一共添加了幾個使用者;當然,不能包括因為事先存在而沒有添加的;

3、最後顯示目前系統上共有多少個使用者;

Count=0

for I in {1..10}; do

if id user$I &> /dev/null; then

echo "user$I exists."

useradd user$I

echo "Add user$I successfully."

Count=$[$Count+1]

echo "Add $Count new users."

echo "Total users: `wc -l /etc/passwd | cut -d' ' -f1`."

1、通過參數傳遞一系列使用者名給腳本,讓腳本添加這些使用者;但要先判斷使用者是否存在,不存在而後再添加;

for UserName in $@; do

if id $UserName &> /dev/null; then

echo "$UserName exists."

useradd $UserName

echo "Add $UserName successfully."

給定一個使用者:

1、如果其UID為0,就顯示此為管理者;

2、否則,就顯示其為普通使用者;

練習:寫一個腳本,完成以下要求:

通過參數傳遞一個磁盤裝置檔案給腳本,讓腳本來判斷其是否有擴充分區;有則顯示有,否則顯示為無;

練習:寫一個腳本

給定一個檔案,比如/etc/inittab

判斷這個檔案中是否有空白行;

如果有,則顯示其空白行數;否則,顯示沒有空白行。

練習:寫一個腳本;(要求:不使用id指令獲得其id号;)

給定一個使用者,判斷其UID與GID是否一樣

如果一樣,就顯示此使用者為“good guy”;否則,就顯示此使用者為“bad guy”。

給腳本傳遞兩個參數(整數);

顯示此兩者之和,之乘積;

寫一個腳本,分别顯示目前系統上所有預設shell為bash的使用者和預設shell為/sbin/nologin的使用者,并統計各類shell下的使用者總數。顯示結果形如:

BASH,3users,they are:

root,redhat,gentoo

NOLOGIN, 2users, they are:

bin,ftp

bash腳本知識點:

條件測試方式:

bash指令;

條件測試:

大于:-gt

大等:-ge

小等:-le

不等:-ne

指令執行狀态傳回值: 0-255

0: 正确執行

1-255: 錯誤執行

exit [n]

腳本執行的最後一條件指令的狀态傳回值;

bash字元測試:

>: 大于

<: 小于

==: 等于

=~: 判斷左邊的字元串是否能夠被右邊的模式所比對;通常用于[[]];

[[ $opt1 =~ $opt2 ]]

一般做行首、行尾錨定;不要加引号;

單目:

-z $STRING: 為空則為真,不空則為假;

-n $STRING: 為空則為假,不空則真;

例子:寫一個腳本,判定使用者的shell是否為bash;

[ "$Shell" == "/bin/bash" ]

Shell=`grep "^$1:" /etc/passwd | cut -d: -f7`

if [ "$Shell" == "/bin/bash" ]; then

echo "Bash User."

Ret=0

echo "Not Bash User."

Ret=9

exit $Ret

改進版:

if [ -z $Shell ]; then

echo "No such user or User's shell is null."

exit 10

例子:根據使用者shell的結束符是否為sh來判定其是否為登入使用者:

echo "No shell."

exit 3

if [[ "$Shell" =~ sh$ ]]; then

echo "Login User."

echo "None Login User."

Ret=4

判斷目前主機的CPU生産商,其資訊在/proc/cpuinfo檔案中vendor id一行中。

如果其生産商為GenuineIntel,就顯示其為Intel公司;

否則,就顯示其為AMD公司;

Vendor=`grep "vendor_id" /proc/cpuinfo | uniq | cut -d: -f2`

if [[ "$Vendor" =~ [[:space:]]*GenuineIntel$ ]]; then

echo "Intel"

echo "AMD"

通過參數傳遞一個字元串給腳本,如果傳遞的字元串為“memory”或“Memory”,就以MB為機關顯示目前主機的記憶體資訊;

否則,就顯示/proc/uptime檔案的内容。

if [[ $1 =~ [Mm]emory$ ]]; then

free -m

cat /proc/uptime

bash知識點:組合條件測試

-a: 與

-o: 或

!: 非,單目操作符

A=3

UID>=1, UID<=499

bash測試:

bash指令

[]

[[]]

test

bash指令組合測試:

&&: 與

||: 或

!: 非

寫一腳本,給定使用者,如果其不存在,就退出腳本。

if ! id $1 &> /dev/null; then

echo "No such user."

exit 6

if [ `id -u $1` -eq `id -g $1` ]; then

echo "Good Guy"

else

echo "Bad Guy"

[ $1 == "memory" -o $1 == "Memory" ]

bash條件判斷之多分支if語句:

文法格式:

if 條件1; then

elif 條件2; then

elif 條件3; then

如果其生産商為AuthenticAMD,就顯示其為AMD公司;

否則,就顯示無法識别;

if [[ $Vendor =~ [[:space:]]*GenuineIntel$ ]]; then

echo "intel"

elif [[ $Vendor =~ [[:space:]]*AuthenticAMD$ ]]; then

echo "Unknown"

練習:通過參數傳遞給腳本一個字元串,如Fedora, Gentoo, Redhat,判斷Linux發行版所處理主流發行系列:

如果為fedora, centos, redhat,就顯示RedHat;

[ $1 == fedora -o $1 == centos -o $1 == redhat ]

如果為suse, opensuse,就顯示為SUSE;

如果為ubuntu, mint, debian,就顯示為Debian;

否則,顯示為其它或無法識别;

寫一個腳本,其可以接受三個參數,最後一個參數為檔案名,但參數可變化,形如:

script.sh -a MageEdu /magedu.com/scripts/test1.sh

script.sh -d 2013-07-19 /magedu.com/scripts/test1.sh

script.sh -D 'some infomation' /magedu.com/scripts/test1.sh

此腳本能夠建立/magedu.com/scripts/test1.sh檔案,并且,如果給出了-a MageEdu,則檔案前兩行為:

# Author: MageEdu

如果給出了-d 2013-07-19,則檔案前兩行為:

# Date: 2013-07-19

如果給出了-D "some infomation",則檔案前兩行為:

# Description: some infomation

其它任何參數,均提示錯誤并退出;

進一步:如果沒有退出,則使用vim打開此檔案,并使用光标預設處于最後一行;

再進一步:儲存退出後,如果檔案有文法錯誤提示使用者有錯誤;

更進一步:如果沒有文法錯誤,則給些檔案賦予執行權限;

a.sh -a mageedu /tmp/test.sh

# Author: mageedu

a.sh -d 2013-07-19 /tmp/test.sh

a.sh -D "test script" /tmp/test.sh

# Description: test script

mkscript

if [ $# -ne 3 ]; then

echo "the number of arguements is wrong."

exit 4

echo '#!/bin/bash' >> $3

if [ $1 == '-a' ]; then

echo "# Author: $2" >> $3

elif [ $1 == '-d' ]; then

echo "# Date: $2" >> $3

elif [ $1 == '-D' ]; then

echo "# Description: $2" >> $3

echo "Unknown option, ignore it."

rm -f $3

exit 5

vim + $3

if bash -n $3 &> /dev/null; then

chmod +x $3

echo "Syntax wrong in $3."

bash測試之檔案測試:

操作符 檔案路徑

-f: 測試其是否為普通檔案,即ls -l時檔案類型為-的檔案;

-d: 測試其是否為目錄檔案,即ls -l時檔案類型為d的檔案;

-e: 測試檔案是否存在;存在為真,否則為假;

-r: 測試檔案對目前使用者來說是否可讀;

-w: 測試檔案對目前使用者來說是否可寫;

-x: 測試檔案對目前使用者來說是否可執行;

-s: 測試檔案大小是否不空,不空則真,空則假;

如果/tmp/test10不存在,就建立之;

if [ ! -e /tmp/test10 ]; then

mkdir /tmp/test10

短路操作:隻要前半段已經可以決定最終結果,後半段就不再運算;

與運算:

真 && 真 = 真

真 && 假 = 假

假 && {真|假} = 假

或運算:

假 || 0 = 0

假 || 1 = 1

真 || =1

[ -e /tmp/test10 ] || mkdir /tmp/test10

id $UserName &> /dev/null || useradd $UserName

! id $UserName &> /dev/null && useradd $UserName || echo "$UserName exists."

id $UserName &> /dev/null && echo "$UserName exists." || useradd $UserName

例子:給定一個路徑,判斷

如果為普通檔案,顯示之;

如果為目錄,顯示之;

否則,說無法識别;

if [ ! -e $1 ]; then

echo "No such file."

exit 7

if [ -f $1 ]; then

echo "Common file."

elif [ -d $1 ]; then

echo "Directory."

echo "Unknown file."

bash的特殊參數:$0: 腳本名稱;

/tmp/script.sh

basename $0

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

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}”

進一步:修改start的機制為:

如果參數為start,且/var/lock/subsys/script檔案不存在,則建立空檔案/var/lock/subsys/script,并顯示“Starting script successfully.”;

否則,顯示“script is already running.”

進一步:修改stop的機制為:

如果參數為stop,且/var/lock/subsys/script檔案存在,則删除檔案/var/lock/subsys/script,并顯示“Stop script finished.”;

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

SysV網絡服務腳本:

# service network restart

# /etc/rc.d/init.d/network start

# /etc/init.d/network start

SvcName=`basename $0`

LockFile="/var/lock/subsys/$SvcName"

if [ $# -lt 1 ]; then

echo "Usage: $SvcName {start|stop|restart|status}"

if [ $1 == 'start' ]; then

if [ -e $LockFile ]; then

echo "$SvcName is running."

touch $LockFile &> /dev/null

echo "Starting $SvcName successfully."

elif [ $1 == 'stop' ]; then

if [ -e $LockFile ];then

rm -f $LockFile &> /dev/null

echo "Stopping $SvcName finished."

echo "$SvcName is stopped yet."

elif [ $1 == 'restart' ]; then

rm -f $LockFile &> /dev/null

touch $LockFile &> /dev/null

echo "Restarting $SvcName successfully."

elif [ $1 == 'status' ]; then

echo "$SvcName is stopped."

字元串測試:

>

<

==

!=

-z

-n

=~:模式比對檢測;

檔案測試:

-e

-f

-d

-r

-w

-x

-s

測試條件的邏輯組合:組合測試

與:-a

或:-o

非:!

與:&&

或:||

if [ $# -gt 1 -a $# -lt 10 ]

if id $UserName &> /dev/null && [ `id -u $UserName` -ge 500 ]; then

給定一個檔案:

如果是一個普通檔案,就顯示之;

如果是一個目錄,亦顯示之;

否則,此為無法識别之檔案;

File=

if [ -f $File ]; then

echo

elif [ -d $File ]; then

echo

判斷某目錄中所有檔案的類型:

for File in /var/log/*; do

bash的程式設計之case語句:用法格式

case 變量引用(${}) in

value1)

;;

value2)

value3)

*)

esac

Com=$1

if [ -z $Com ]; then

Com=gzip

[ -d /backup ] || mkdir /backup

case $Com in

gzip)

tar zcf /backup/etc-`date +%F-%H-%M-%S`.tar.gz /etc/*

RetVal=$?

;;

bzip2)

tar jcf /backup/etc-`date +%F-%H-%M-%S`.tar.bz2 /etc/*

xz)

tar Jcf /backup/etc-`date +%F-%H-%M-%S`.tar.xz /etc/*

echo "Usage: `basename $0` {[gzip|bzip2|xz]}"

esac

[ $RetVal -eq 0 ] && echo "Backup etc finished.($Com)."

case語句解決上一個服務腳本的問題:

LockFile=/var/lock/subsys/$SvcName

echo "Usage: $SvcName {start|restart|stop|status}"

case $1 in

start)

touch $LockFile

echo "Starting $SvcName finished." ;;

stop)

rm -f $LockFile

echo "Stopping $SvcName finished." ;;

restart)

echo "Restarting $SvcName finished." ;;

status)

echo "$SvcName is running..."

echo "$SvcName is stopped..."

練習:判斷目前Linux發行版是RedHat, Fedora, CentOS還是其它。

方法:取得/etc/issue檔案第一行的第一個單詞後進行比較;

bash如何與使用者互動:bash内置指令, read

-p "prompt":提示資訊

-t #: 逾時秒數

例子:

read -p "Do you agree [yes|no]?: " YesNo

case $YesNo in

y|Y|[Yy]es)

echo "Agreed, proceed." ;;

n|N|[nN]o)

echo "Disagreed, can't proceed." ;;

echo "Invalid input." ;;

例子:寫一個腳本

1、顯示如下菜單給使用者:

m|M) show memory usages;

d|D) show disk usages;

q|Q) quit

2、如果使用者選擇了第一項,則顯示記憶體使用資訊;

如果選擇了第二項,則顯示磁盤挂載及使用相關資訊;

如果是第三項,退出,并顯示選擇退出;

其它任何内容,均說明錯誤選項;

cat << EOF

EOF

read -p "Your choice: " Choice

case $Choice in

m|M)

free -m ;;

d|D)

df -lh ;;

q|Q)

echo "Quit..."

exit 0

echo "Invalid input."

exit 5