天天看點

Shell腳本(四)-腳本中的常用語句及控制器

腳本中的常用語句

for語句(循環)

for語句會将語句中的值依次賦予語句中的變量,每一次指派執行一次
格式:
for 變量 in 值
do
    執行内容
done
或
for ((變量初始值;循環控制條件;變量修正值))
do
    執行内容
done

例:
[[email protected] ~]# vim for.sh 
for a in {1..5}
do
        echo a=$a
done
for ((b=1;b<=5;b++))
do
        echo b=$b
done
[[email protected] ~]# sh for.sh 
a=1
a=2
a=3
a=4
a=5
b=1
b=2
b=3
b=4
b=5
           

while語句

while指令當條件滿足時,進入循環
格式:
while 條件
do
    執行内容
done

例:檢測/目錄使用超過30%,列印提示到目前shell
[[email protected] sh]# vim disk.sh
#!/bin/bash
DISK_USE=`df | awk '/\/$/{print $5}' | awk -F "%" '{print $1}'`

while [ "$DISK_USE" -ge "30" ] ; do
        echo "Your / will full !!" > `tty`
        sleep 10
done

[[email protected] sh]# sh disk.sh 
Your / will full !!
Your / will full !!
^C
           

if語句

if語句判斷多個條件,不同條件成立,執行相應的内容
格式:
if 條件1           ##如果
then 執行内容1     ##則執行
elif 條件2         ##又如果
then 執行内容2     ##則執行
。。。             ##可重複加多個條件
else              ##當條件都不滿足時,執行
fi 

例:
#!/bin/bash
read -p "Do you like cats or dogs?" LIKE
if [ "$LIKE" = cat ]
then
        echo dog?
elif [ "$LIKE" = dog ]
then
        echo cat?
else
        echo what?
fi

[[email protected] sh]# sh if.sh 
Do you like cats or dogs?cat
dog?
[[email protected] sh]# sh if.sh 
Do you like cats or dogs?dog
cat?
[[email protected] sh]# sh if.sh 
Do you like cats or dogs?ls
what?
           

case語句

case語句同if語句都是判斷多條件,差别在于if語句為逐條判斷,case語句為同時判斷,效率較高
格式:
case 判斷條件 in
    條件1)
    執行内容1
    ;;
    條件2)
    執行内容2
    ;;
    。。。
    *)
    預設執行内容        ##當使用前面的各種模式均無法比對該變量時,将執行“*)”後
    ;;
esac

例:
[[email protected] sh]# vim case.sh
case $1 in
        cat)
        echo dog
        ;;
        dog)
        echo cat
        ;;
        *)
        echo "Errot:input cat or dog after script !!"
esac

[[email protected] sh]# sh case.sh cat
dog
[[email protected] sh]# sh case.sh dog
cat
[[email protected] sh]# sh case.sh 
Errot:input cat or dog after script !!

           

expect

通過上面的語句我們可以實作簡單的循環、判斷等功能,但對于需要互動的場景,就不許通過人工來幹預。expect則是可以實作互動的程式
spawn    expect中的監控程式,其運作後會監控指令提出的互動問題
send    發送問題答案給互動指令
"\r"    回車
exp_continue    目前問題如果不存在時,繼續回答下面的問題
expect eof      問題回答完畢退出expect環境
interact        問題回答完畢留在互動界面
set NAME [ lindex $argv n ]    定義變量

###安裝expect服務
[[email protected] sh]# yum install expect -y
[[email protected] sh]# type expect
expect is /usr/bin/expect

例:
[[email protected] sh]# vim ssh.exp
#!/usr/bin/expect
set ip [ lindex $argv 0 ]
set password [ lindex $argv 1 ]
set timeout 5
spawn ssh root@$ip
expect {
        "yes/no" { send "yes\r";exp_continue }
        "password" { send "$password\r" }
}
interact

[[email protected] sh]# ./ssh.exp 172.25.80.100 redhat
spawn ssh [email protected]
[email protected]'s password: 
Last login: Tue Jun 26 20:59:00 2018 from 172.25.80.250
[[email protected] ~]# exit
           

腳本中的語句控制器

exit n:腳本退出,退出值為n
break:退出目前循環,但不退出腳本
continue:提前結束循環内部的指令,但不終止目前循環
           

腳本應用示例

使用者建立腳本
執行users_create.sh userlist passlist
建立userlist清單中的使用者
設定清單中使用者的密碼為passlist清單中的密碼
腳本後輸入檔案個數不足時報錯
兩個檔案行數不一緻時報錯
檔案不存在時報錯
使用者存在時報錯

[[email protected] sh]# vim users_create.sh
#!/bin/bash
if [ $# -lt 2 ]
then
        echo "Please input userlist and passlist after the script !!"
        exit 1
elif [ ! -e $1 ]
then
        echo "ERROR: $1 is not exist!!"
        exit 1
elif [ ! -e $2 ]
then
        echo "ERROR: $2 is not exist!!"
        exit 1
elif [ `cat $1 | wc -l` -ne `cat $2 | wc -l` ]
then
        echo "The number of file lines must be the same !!"
        exit 1
else
        Max_Line=`cat $1 | wc -l`
        for Line_num in `seq 1 $Max_Line`
        do
                Username=`sed -n "${Line_num}p" $1`
                Password=`sed -n "${Line_num}p" $2`
                useradd $Username && {
                echo $Username Created successfully     
                echo $Password | passwd --stdin $Username
                }
        done
fi

測試:
[[email protected] sh]# sh users_create.sh                     ##運作腳本
Please input userlist and passlist after the script !!      ##錯誤提示
[[email protected] sh]# cat >> userlist << EOF                 ##建立使用者清單檔案
> user1
> user2
> user3
> user4
> EOF
[[email protected] sh]# sh users_create.sh userlist passlist    ##執行腳本
ERROR: passlist is not exist!!                               ##錯誤提示

[[email protected] sh]# cat >> passlist << EOF                  ##建立密碼檔案,與使用者檔案行數不對應
> pass1
> pass2
> pass3
> EOF
[[email protected] sh]# sh users_create.sh userlist passlist    ##執行腳本
The number of file lines must be the same !!                 ##錯誤提示

[[email protected] sh]# echo pass4 >> passlist                  ##修改passlist檔案
[[email protected] sh]# sh users_create.sh userlist passlist    ##執行腳本
user1 Created successfully
Changing password for user user1.
passwd: all authentication tokens updated successfully.
user2 Created successfully
Changing password for user user2.
passwd: all authentication tokens updated successfully.
user3 Created successfully
Changing password for user user3.
passwd: all authentication tokens updated successfully.
user4 Created successfully
Changing password for user user4.
passwd: all authentication tokens updated successfully.

[[email protected] sh]# sh users_create.sh userlist passlist    ##再次執行,提示使用者已存在
useradd: user 'user1' already exists
useradd: user 'user2' already exists
useradd: user 'user3' already exists
useradd: user 'user4' already exists

########################################邪惡的分隔線########################################

資料庫備份
執行db_dump.sh westos(資料庫密碼)
腳本執行後會備份資料庫中的所有庫到/mnt/mysqldump目錄中
備份檔案名稱為"庫名稱.sql" 當次檔案存在時報錯并詢問動作
輸入"S"跳過備份,輸入"B"備份"庫名稱.sql"檔案為"庫名稱_backup_目前日期.sql",輸入"O"時,覆寫源檔案

[[email protected] sh]# vim db_dump.sh
ACTION_CMD(){
        read -p "[S]kip [B]ackup [O]verwrite
        Please input action: " ACTION
        ACTION=`echo $ACTION | tr 'a-z' 'A-Z'`
        case $ACTION in
                S)
                continue
                ;;
                B)
                mv /mnt/mysqldump/${2}.sql /mnt/mysqldump/${2}_backup_`date +%y-%m-%d`.sql
                ;;
                O)
                mysqldump -uroot -p$1 $2 > /mnt/mysqldump/${2}.sql
                ;;
                exit)
                echo bye[[email protected] sh]# vim test.sh 


                exit 0[[email protected] sh]# vim test.sh 


                ;;
                *)
                echo "ERROR: please input [S] [B] [O] "
                ACTION_CMD
        }

TABASE_MESSAGE=`mysql -uroot -EN -e "show databases;" | grep -v -E "^\*|schema$"`

for DATABASE_NAME in $DATABASE_MESSAGE
do
        [ -e "/mnt/mysqldump/${DATABASE_NAME}.sql" ] && {
        ACTION_CMD $1 $DATABASE_NAME 
        } || {
        mysqldump -uroot -p$2 $DATABASE_NAME > /mnt/mysqldump/$DATABASE_NAME.sql
        }
done

########################################邪惡的分隔線########################################

自動部署服務
執行lamp.sh,自動部署apache服務,并設定監聽端口為8080

[[email protected] sh]# vim lamp.sh 
#!/bin/bash
yum repolist
yum install httpd -y
sed -i "/^Listen/cListen 8080" /etc/httpd/conf/httpd.conf
systemctl stop httpd
systemctl start httpd
systemctl enable httpd