1. 程式人生 > >《Shell 程式設計》06_if 條件語句

《Shell 程式設計》06_if 條件語句

《Shell 程式設計》06_if 條件語句

標籤(空格分隔): Shell


文章目錄

6.1 if 條件語句的語法

6.1.1. 單分支結構

第一種:

if <條件表示式>
    then
        指令
fi

第二種:

if <條件表示式>; then
    指令
fi

條件語句巢狀:

if <條件表示式>
    then
        if <條件表示式>
            then 
                指令
        fi
fi
  • “<條件表示式>” 可以是 test、[]、[[]]、(()),也可以是命令;
  • 分號相當於命令換行。

6.1.2. 雙分支結構

if <條件表示式>
  then
    指令集1
else
    指令集2
fi

6.1.3 多分支結構

if <條件表示式>; then
    指令1
elif <條件表示式2>; then
    指令2
else
    指令3
fi
  • 每個 elif 都要帶有 then;
  • 最後結尾的 else 後面沒有 then。

6.2 if 條件語句多種條件表示式語法

(1)test 條件表示式

if test 表示式; then 
    指令
fi

(2)[] 條件表示式

if [ 字串或算數表示式 ]; then
    指令
fi

(3)[[]] 條件表示式

if [[ 字串表示式 ]]; then
    指令
fi

(4)(()) 條件表示式

if ((算術表示式)); then
    指令
fi

(5) 命令表示式

if 命令; then
    指令
fi

例 6-1 開發 Shell 指令碼判斷系統剩餘記憶體的大小,如果低於 100 MB,就郵件報警給系統管理員,並且將指令碼加入定時任務,即每 3 分鐘檢查一次。

1)獲取系統當前剩餘記憶體的值

[[email protected] ~]# free -m
              total        used        free      shared  buff/cache   available
Mem:           1823         154        1071          34         596        1451
Swap:          1023           0        1023
[[email protected] ~]# free -m|awk 'NR==3 {print $NF}'
1023

2)配置郵件報警

[[email protected] ~]# echo -e "set [email protected] smtp=smtp.163.com nset smtp-auth-user=yanglt7 smtp-auth-password=授權碼 smtp-auth=login" >>/etc/mail.rc
[[email protected] ~]# tail -1 /etc/mail.rc
set [email protected] smtp=smtp.163.com nset smtp-auth-user=yanglt7 smtp-auth-password=授權碼 smtp-auth=login
[[email protected] ~]# echo "ylt"|mail -s "title" [email protected]
#<==測試郵件傳送
[[email protected] ~]# echo "mail test" >/tmp/test.txt
#<==將正文放入檔案
[[email protected] ~]# mail -s "title" [email protected] </tmp/test.txt
#<==讀取檔案內容併發送郵件

3)編寫 Shell 指令碼

#!/bin/bash
FreeMem=`free -m|awk 'NR==3 {print $NF}'`
CHARS="Current memory is $FreeMem."

if [ $FreeMem -lt 100 ]; then
    echo $CHARS|tee /tmp/messages.txt #<==螢幕輸出提示,並寫入檔案。
    mail -s "`date + $F-$T`$CHARS [email protected]" </tmp/memssages.txt
fi
#<[email protected] 是接收報警郵件的郵箱,[email protected] 是傳送報警郵件的郵箱。

4)將上述指令碼加入crond 定時任務中,每 3 分鐘檢查一次,達到閥值就發郵件報警

[[email protected] ~]# crontab -l|tail -2
# monitor sys mem at 20181024 by ylt
*/3 * * * * /bin/sh /home/ylt/scripts/mailMem.sh &>/dev/null

例 6-2 使用 if 語句和 read 讀入實現整數大小的比較。

#!/bin/bash
read -t 10 -p "pls input two num:" a b
[ -z $a ] || [ -z $b ] &&{
    echo "pls input two num again."
    exit 1
}
expr $a + 1 &>/dev/null
RETVAL1=$?
expr $b + 1 &>/dev/null
RETVAL2=$?
[[ $RETVAL1 -eq 0 -a $RETVAL2 -eq 0 ]] ||{
    echo "pls input two 'num'."
    exit 3
}
if [ $a -gt $b ]; then
    echo "$a > $b"
elif [$a -lt $b ]; then
    echo "$a < $b"
else
    echo "$a=$b"
exit 0

6.3 監控 Web 和資料庫

例 6-3 用 if 條件語句針對 Nginx Web 服務或 MySQL 資料庫服務是否正常進行檢測,如果服務未啟動,則啟動相應的服務。

1)監控 Web 服務和 MySQL 資料庫服務是否異常的常見方法:

  • 埠監控
    • 在伺服器本地監控服務埠的常見命令有 netstat、ss、lsof
    • 從遠端監控伺服器本地埠的命令有 telnet、nmap、nc
  • 監控服務程序或程序數
    • 此方法適合本地伺服器,過濾的是程序的名字。命令為:
      • ps -ef|grep nginx|wc-l
      • ps -ef|grep mysql|wc-l
  • 在客戶端模擬使用者訪問
    • 使用 wget 或 curl 命令進行測試(如果監控資料庫,則需要轉為通過 Web 伺服器去訪問資料庫),並對測試結果做三種判斷:
      • 利用返回值(echo $?)
      • 獲取特殊字串(需事先開發程式)
      • 根據 HTTP 響應 header 的情況
  • 登入 MySQL 資料庫判斷
    • 通過 MySQL 客戶端連線資料庫,根據返回值或返回內容判斷。例如:mysql -uroot -pylt -e “select version();” &>/dev/null; echo $?

2)監控 mysql 資料庫異常

埠監控:

[[email protected] scripts]# /etc/init.d/mysqld start
Starting MySQL.. SUCCESS!
[[email protected] scripts]# netstat -lntup|grep 3306|wc -l
1
[[email protected] scripts]# netstat -lntup|grep mysql|wc -l
1
[[email protected] scripts]# ss -lntup|grep mysql|wc -l
1
[[email protected] scripts]# ss -lntup|grep 3306|wc -l
1
[[email protected] scripts]# lsof -i tcp:3306|wc -l
2

遠端監控伺服器監控本地埠:

[[email protected] scripts]# nmap 127.0.0.1 -p 3306|grep open|wc -l
1
[[email protected] scripts]# echo -e "\n"|telnet 127.0.0.1 3306 2>/dev/null|grep Connected|wc -l
1
[[email protected] scripts]# nc -w 2 127.0.0.1 3306 &>/dev/null

伺服器程序或程序數進行監控(適合本地伺服器):

[[email protected] scripts]# ps -ef|grep mysql|grep -v grep|wc -l
2

3)開發監控 MySQL 資料庫的指令碼

#!/bin/bash
#if [ `netstat -lnt|grep 3306|awk -F "[ :]+" '{print $5}'` -eq 3306 ]; then
#if [ "`netstat -lnt|grep 3306|awk -F "[ :]+" '{print $5}'`" = "3306" ]; then
#if [ `netstat -lntup|grep mysqld|wc -l` -gt 0 ]; then
#if [ `lsof -i tcp:3306|wc-l` -gt 0 ]; then
if [ `ps -ef|grep -v grep|grep mysql|wc -l` -gt 0 ]; then
    echo "MySQL is Running."
else
    echo "MySQL is Stopped."
    /etc/init.d/mysqld start
fi

4)監控 Nginx Web 服務異常

埠監控:

[[email protected] ~]# /application/nginx/sbin/nginx
[[email protected] ~]# netstat -lntup|grep nginx|wc -l
1
[[email protected] ~]# netstat -lntup|grep 80|wc -l
1
[[email protected] ~]# ss -lntup|grep -w 80|wc -l
1
[[email protected] ~]# lsof -i tcp:80|wc -l
3

伺服器程序或程序數進行監控(適合本地伺服器):

[[email protected] scripts]# ps -ef|grep nginx|grep -v grep|wc -l
2

5)開發監控 Nginx 的指令碼

#!/bin/bash
#if [ `netstat -lntup|grep nginx|wc -l` -gt 0 ]; then
#if [ `netstat -lntup|grep -w 80|wc -l` -eq 80 ]; then
if [ `lsof -i tcp:80|wc -l` -gt 0 ]; then
if [ `ps -ef|grep -v grep|grep nginx|wc -l` -ge 1 ]   
    echo "Nginx is Running."
else
    echo "Nginx is Stopped."
    /application/nginx/sbin/nginx
fi

6.4 判斷字串是否為數字

1)使用 sed 加正則表示式

#<==刪除一個字串中的所有數字,看字串的長度是否為0,如果不為0,則說明不是整數。

[[email protected] ~]# [ -n "`echo ylt123|sed 's/[0-9]//g'`" ] && echo char || echo int
char
[[email protected] ~]# [ -n "`echo 123|sed 's/[0-9]//g'`" ] && echo char || echo int
int
[[email protected] ~]# [ -z "`echo ylt123|sed 's/[0-9]//g'`" ] && echo int || echo char
char
[[email protected] ~]# [ -z "`echo 123|sed 's/[0-9]//g'`" ] && echo int || echo char
int

2)變數的子串替換加正則表示式

#<==如果 num 長度不為0,並且把 num 中的非數字部分刪除,然後再看結果是不是等於 num 本身,如果兩者成立,則 num 就是數字。

[[email protected] ~]# num=222
[[email protected] ~]# [ -n "$num" -a "$num" = "${num//[^0-9]/}" ] && echo "it is num."
it is num.

3)通過 expr 判斷

[[email protected] ~]# expr ylt + 1 &>/dev/null
[[email protected] ~]# echo $?
2
[[email protected] ~]# expr 123 + 1 &>/dev/null
[[email protected] ~]# echo $?
0

4)利用 “=~” 符號判斷

[[email protected] ~]# [[ ylt123 =~ ^[0-9]+$ ]] && echo int || echo char
char
[[email protected] ~]# [[ 123 =~ ^[0-9]+$ ]] && echo int || echo char
int

6.5 判斷字串長度是否為 0

1)使用字串條件表示式 -z 和 -n

[[email protected] ~]# [ -z "ylt" ] && echo 1 || echo 0
0
[[email protected] ~]# [ -n "ylt" ] && echo 1 || echo 0
1

2)使用變數子串判斷

[[email protected] ~]# char=ylt
[[email protected] ~]# [ ${#char} -eq 0 ] && echo 1 || echo 0
0

3)使用 ecpr length 函式判斷

[[email protected] ~]# [ `expr length "ylt"` -eq 0 ] && echo 1 || echo 0
0

4)使用 wc 的 -L 引數統計判斷

[[email protected] ~]# [ `echo ylt|wc -L` -eq 0 ] && echo 1 || echo 0
0

5)使用 awk lenghth 函式判斷

[[email protected] ~]# [ `echo ylt|awk '{print length}'` -eq 0 ] && echo 1 || echo 0
0

6.6 開發 rsync 服務的啟動指令碼

#!/bin/bash
if [ $# -ne 1 ]; then
        echo $"USAGE:$0 {start|stop|restart}"
        exit 1
fi
if [ "$1" = "start" ]; then
        echo "rsyncd is starting..."
        rsync --daemon
        sleep 2
        if [ `netstat -lntup|grep 873|wc -l` -ge 1 ]; then
                echo "rsyndc is started."
                exit 0
        fi
elif [ "$1" = "stop" ]; then
        echo "rsyncd is stopping..."
        pkill rsync
        sleep 1
        if [ `netstat -lntup|grep 873|wc -l` -eq 0 ]; then
                echo "rsyncd is stopped."
                exit 0
        fi
elif [ "$1" = "restart" ]; then
        echo "rsyncd is stopping..."
        pkill rsync
        sleep 1
        killpro=`netstat -lntup|grep 873|wc -l`
        rsync --daemon
        echo "rsyncd is starting..."
        sleep 1
        startpro=`netstat -lntup|grep 873|wc -l`
        if [ $killpro -eq 0 -a $startpro -ge 1 ]; then
                echo "rsyncd is restarted."
                exit 0
        fi
else
        echo $"USAGE:$0 {start|stop|restart}"
        exit 2
fi