一、循環終止的特殊命令
break、exit、continue、return的區別
break n:如果省略n,則表示跳出整個循環、n表示跳出循環的層數
continue n:如果省略n,則表示跳出本次循環,忽略本次循環的剩餘代碼,進入循環的下一個循環。n表示退到第n層繼續循環
exit n:退出當前shell,n爲上一次程序執行的狀態返回值,n也可以省略,在下一個shell裏可通過"$?"接收exit n 的n值
return n :用於在函數裏作爲函數值返回,以判斷函數執行是否正確,在下一個shell裏可通過"$?"接收exit n 的n值
例一:
#!/bin/bash
if [ $# -ne 1 ];then
echo $"usage:$0 {break|continue|exit|return}"
exit 1
fi
function test(){
for ((i=0;i<5;i++))
do
if [ $i -eq 3 ];then
$*;
fi
done
echo "I am in func"
}
test $*
func_ret=$?
if [ $(echo $*|grep return | wc -l) -eq 1 ];then
echo "return's exit status:$func_ret"
fi
echo "ok"
效果如圖:
[root@mycentos shell]# sh 2.sh break
0
1
2
I am in func #跳出for循環,後繼續執行函數後面的代碼
ok #執行腳本後面的代碼
[root@mycentos shell]# sh 2.sh continue
0
1
2
4
I am in func #將跳出for循環中本次循環,繼續執行下次循環
ok #腳本後面的內容繼續執行
[root@mycentos shell]# sh 2.sh "exit 119"
0
1
2 #直接跳出腳本,函數和腳本後面的內容不執行
[root@mycentos shell]# echo $?
119 退出程序時指定了"119",則執行腳本後獲取"$?"的返回值就返回了"119",給當前的shell
[root@mycentos shell]# sh 2.sh "return 119"
0
1
2 #return 直接退出當前函數
return's exit status:119 #將119返回到了函數的外部腳本
ok
[root@mycentos shell]# echo $?
0 #執行腳本後的返回值爲0,因爲腳本中最後一條命令"ok"打印成功
實戰一:
開發shell腳本實現服務器臨時配置多個IP,並且可以隨時撤銷配置的所有IP.IP的地址範圍爲:10.0.2.1~10.0.2.16,其中10.0.2.10不能配置
預備知識:
一、給網卡配置額外IP的兩種方式
1.)ifconfig配置別名IP的方式
ifconfig eth0:0 10.0.2.10/24 up #添加IP
ifconfig eth0:0 10.0.2.10/24 down #刪除IP
2.)使用ip配置輔助IP的方式:
ip addr add 10.0.2.11/24 dev eth0 label eth0:0 #添加ip
ip addr del 10.0.2.11/24 dev eth0 label eth0:0 #刪除ip
簡略版:
#!/bin/bash
for num in $(seq 16)
do
if [ $num -eq 10 ];then
continue
else
#ip addr add 10.0.2.$num/24 dev eth0 label eth0:$num <==這個也可以
ifconfig eth0:$num 10.0.2.$num/24 down
fi
done
簡單版本:
#!/bin/bash
[ -f /etc/init.d/functions ]&& . /etc/init.d/functions
RETVAL=0
function add(){
for ip in {1..16}
do
if [ $ip -eq 10 ];then
continue
else
ifconfig eth0:$ip 10.0.2.${ip}/24 up
RETVAL=$?
if [ $RETVAL -eq 0 ];then
action "add $ip" /bin/true
else
action "add $ip" /bin/false
fi
fi
done
return $RETVAL
}
function del(){
for ip in {1..16}
do
if [ $ip -eq 10 ];then
continue
else
ifconfig eth0:$ip 10.0.2.${ip}/24 down
RETVAL=$?
if [ $RETVAL -eq 0 ];then
action "del $ip" /bin/true
else
action "del $ip" /bin/false
fi
fi
done
return $RETVAL
}
case "$1" in
start)
add
RETVAL=$?
;;
stop)
del
RETVAL=$?
;;
restart)
del
sleep 2
add
RETVAL=$?
;;
*)
printf $"usage:$0 {start|stop|restart}"
esac
exit $RETVAL
注:
一、此版本代碼冗餘多,可以將冗餘代碼組合
去除代碼冗餘版:
#!/bin/bash
[ -f /etc/init.d/functions ]&& . /etc/init.d/functions
RETVAL=0
function op(){
if [ "$1" == "del" ];then #空格不要忘了
list=$(echo {16..1})#從後往前刪除
else
list=$(echo {1..16})
fi
for ip in $list
do
if [ $ip -eq 10 ];then
continue #跳出此次循環
else
ip addr $1 10.0.2.$ip/24 dev eth0 label eth0:$ip &>/dev/null
RETVAL=$?
if [ $RETVAL -eq 0 ];then
action "$1 $ip" /bin/true
else
action "$1 $ip" /bin/false
fi
fi
done
return $RETVAL
}
case "$1" in
start)
op add #注意傳參到op函數中去
RETVAL=$?
;;
stop)
op del
RETVAL=$?
;;
restart)
op del
sleep 2
op add
RETVAL=$?
;;
*)
printf $"usage:$0 {start|stop|restart}"
esac
exit $RETVAL
效果如下:
[root@mycentos ~]# sh 1.sh start
add 1 [ OK ]
add 2 [ OK ]
add 3 [ OK ]
add 4 [ OK ]
add 5 [ OK ]
add 6 [ OK ]
add 7 [ OK ]
add 8 [ OK ]
add 9 [ OK ]
add 11 [ OK ]
add 12 [ OK ]
add 13 [ OK ]
add 14 [ OK ]
add 15 [ OK ]
add 16 [ OK ]
使用ifconfig可查看eth0的虛擬ip
實戰二:
已知下面字符串是將RANDOM隨機數採用md5sum加密後任意取出的連續10位結果,請破解這些字符串對應的md5sum前對的字符串的數字?
"4fe8bf20ed"
一、預備知識
RANDOM的範圍是:0~32767
二、思路:
1.)先將RANDOM隨機的所有可能寫成字典
2.)用腳本做密碼匹配
1)RANDOM字典的生成
#!/bin/bash
for n in {0..32767}
do
echo "$(echo $n | md5sum) : $n" >> zhiwen.txt
done
echo "ok"
2)匹配密碼
#!/bin/bash
md5char="4fe8bf20ed" #要匹配的字符串
while read line #變量是line
do
if [ $(echo $line | grep $md5char | wc -l) -eq 1 ];then
echo $line
break #匹配到後就退出程序
fi
done<zhiwen.txt #按行讀取字典
將上述代碼合併
#!/bin/bash
>zidian.txt #清空字典文件
for n in {0..32767}
do
echo "$(echo $n |md5sum) : $n" >>zidian.txt #此處不能是">"
done
echo "input ok"
md5char="4fe8bf20ed" #要破解密碼
while read line
do
if [ $(echo $line | grep $md5char |wc -l ) -eq 1 ];then
echo $line
break
fi
done<zidian.txt
效果如圖:
[root@mycentos shell]# sh 7.sh
1dcca23355272056f04fe8bf20edfce0 - : 5
二、數組
數組的操作
1.定義數組:
方式一:用小括號將變量值括起來賦值給數組變量,每個變量之間要用空格進行分格
[root@mycentos shell]# array=(1 2 3)
[root@mycentos shell]# echo ${array[*]} #打印單個數組元素時用"${數組名[下標]}",當未指定數組下標時,數組的下標將從0開始。
1 2 3
方式二:用小括號將變量括起來,同時1採用鍵值對的形式賦值
array=([1]=one [2]=two [3]=three)
小括號裏對應的數字爲數組下標,等號後面的內容爲下標對應的數組變量的值。
[root@mycentos shell]# array=([1]=one [2]=twe [3]=three)
[root@mycentos shell]# echo ${array[1]}
one
[root@mycentos shell]# echo ${array[2]}
twe
[root@mycentos shell]# echo ${array[3]}
three
[root@mycentos shell]# echo ${array[*]}
one twe three
此方式繁瑣,不推薦
方法三:動態的定義數組變量,並使用命令的輸出結果作爲數組內容
array=($(命令))
或
array=(`命令`)
[root@mycentos Desktop]# touch array/{1..3}.txt
[root@mycentos Desktop]# ls -l array/
total 0
-rw-r--r--. 1 root root 0 Nov 15 14:44 1.txt
-rw-r--r--. 1 root root 0 Nov 15 14:44 2.txt
-rw-r--r--. 1 root root 0 Nov 15 14:44 3.txt
[root@mycentos Desktop]# array=($(ls array/))
[root@mycentos Desktop]# echo ${array[*]}
1.txt 2.txt 3.txt
------------------------------------------------------------------------------------------------
2.打印數組長度
echo {#數組名[*]}
數組是特殊的變量,變量子串的知識也試用。
------------------------------------------------------------------------------------------------
3.數組的賦值:
數組名[下標]=值
------------------------------------------------------------------------------------------------
4.數組的刪除:
由於數組本質上是變量,則可通過unset 數組[下標]來清除相應的數組元素,如果不帶下標,則表示清除整個數組的所有數據。
------------------------------------------------------------------------------------------------
5.數組內容的截取和替換:
[root@mycentos ~]# array=(1 2 3 4 5)
[root@mycentos ~]# echo ${array[*]:1:3} #從下標爲1的元素開始截取3個數組元素
2 3 4
[root@mycentos ~]# array=({a..z})
[root@mycentos ~]# echo ${array[*]}
a b c d e f g h i j k l m n o p q r s t u v w x y z
[root@mycentos ~]# echo ${array[*]:1:2} #從下標爲1的元素開始截取2個數組元素
b c
[root@mycentos ~]# array=(1 2 3 4 5)
[root@mycentos ~]# echo ${array[*]/1/b} #把數組的1替換成b,原來數組被修改和sed很像
b 2 3 4 5
替換方法:
${數組名[@或*]/查找字符/替換字符},該操作並不會改變原先數組的內容。
例一:
使用循環批量輸出數組的元素
方式一:C語言型打印數組元素
#!/bin/bash
array=(1 2 3 4 5)
for ((i=0;i<${#array[*]};i++))
do
echo ${array[i]}
done
方式二:
普通循環打印數組元素
#!/bin/bash
array=(1 2 3 4 5)
for n in ${array[*]} #<==${array[*]}表示輸出數組的所有元素,相當於列表數組元素
do
echo $n
done
方式三:
#!/bin/bash
array=(1 2 3 4 5)
i=0
while ((i<${#array[*]}))
do
echo ${array[i]}
((i++))
done
例二:通過豎向列舉法定義數組元素批量打印
#!/bin/bash
array=(
oldboy
oldgirl
xiaoming
xiaoqiang
)
for ((i=0;i<${#array[*]};i++))
do
echo "this is num $i,then content is ${array[$i]}"
done
echo "array len:${#array[*]}"
結果如圖:
[root@mycentos arr]# sh 4.sh
this is num 0,then content is oldboy
this is num 1,then content is oldgirl
this is num 2,then content is xiaoming
this is num 3,then content is xiaoqiang
array len:4
例三:
將命令結果作爲數組元素定義並打印
#!/bin/bash
dir=($(ls ./*.txt))
for ((i=0;i<${#dir[*]};i++))
do
echo "this is NO.$i,filename is ${dir[$i]}"
done
結果如圖:
[root@mycentos arr]# sh 5.sh
this is NO.0,filename is ./1.txt
this is NO.1,filename is ./2.txt
this is NO.2,filename is ./3.txt
this is NO.3,filename is ./4.txt
關於數組的總結:
1).定義:
靜態array=(1 2 3)
動態array=($(ls))
2).賦值:array[3]=4
3).打印:${array[*]}或${array[*]}
數組長度:${#array[@]}或${#array[*]}
單個元素:${array[i]}
4).循環打印
#!/bin/bash
arr=(
10.0.0.11
10.0.0.22
10.0.0.33
)
#<==C語言循環打印
for ((i=0;i<${#arr[*]};i++))
do
echo "${arr[i]}"
done
echo '-----------------------------------'
#<==普通循環打印
for n in ${arr[*]}
do
echo "$n"
done
實戰三
利用for循環打印下面這句話不大於6的單詞
I am lodboy teacher welcome to oldboy training class
計算變量內容長度方式:
[root@mycentos arr]# char=oldboy
[root@mycentos arr]# echo {char}
oldboy
[root@mycentos arr]# echo char
6
[root@mycentos arr]# expr 0)}'
6
方式一(數組實現):
#!/bin/bash
arr=(I am oldboy teacher welcome to oldboy training class)
for ((i=0;i<${#arr[*]};i++))
do
#if [ $(expr length ${arr[i]}) -lt 6 ];then
# echo ${arr[i]}
#fi
if [ ${#arr[i]} -lt 6 ];then
echo ${arr[i]}
fi
done
方式二(列表實現):#!/bin/bash
for word in I am oldboy teacher welcome to oldboy training class
do
if [ ${#word} -lt 6 ];then
echo $word
fi
done
方法三(awk循環):
[root@mycentos arr]# char="I am oldboy teacher welcome to oldboy training class"
[root@mycentos arr]# echo $char | awk '{for(i=1;i<=NF;i++) if(length($i)<6)print $i}'
I
am
to
class
實戰四
檢測多個網站地址是否正常
要求:
1)使用shell數組的方法實現,檢測策略儘量使用模擬用戶訪問
2)每10秒進行一次全部檢測,無法訪問的輸出報警
3)待檢測的地址如下
http://www.baidu.com
http://www.sina.com
http://www.qq.com
http://www.1.com
思路:
一、網站放到數組中
二、編寫URL檢測腳本,傳入數組的元素,即URL
三、組合實現整個案例,編寫main的主函數(即執行函數),每隔10秒檢查一次
#!/bin/bash
. /etc/init.d/functions
check_count=0
urlArr=(
http://www.linuxprobe.com
http://www.sina.com
http://www.a.co
http://www.baidu.com
)
function wait(){ #定義倒計數3、2、1函數
echo -n "3秒後,執行檢查URL的操作"
for ((i=0;i<3;i++))
do
echo -n '.';sleep 1
done
echo
}
function check_url(){
wait #執行倒計時函數
for ((i=0;i<$(echo ${#urlArr[*]});i++))
do
wget -o /dev/null -T 5 --tries=1 --spider ${urlArr[i]} &>/dev/null
if [ $? -eq 0 ];then
action "${urlArr[i]}" /bin/true
else
action "${urlArr[i]}" /bin/false
fi
done
((chenk_count++)) #檢測次數
}
function main(){
while true
do
check_url
echo "-------check count:${check_count}-----"
sleep 1
done
}
main
效果如圖: