當前位置:
首頁 > 知識 > 10 個實戰及面試常用 Shell 腳本編寫

10 個實戰及面試常用 Shell 腳本編寫

(點擊

上方公眾號

,可快速關注)




來源:李振良


blog.51cto.com/lizhenliang/1929044




注意事項




1)開頭加解釋器:#!/bin/bash




2)語法縮進,使用四個空格;多加註釋說明。




3)命名建議規則:變數名大寫、局部變數小寫,函數名小寫,名字體現出實際作用。




4)默認變數是全局的,在函數中變數local指定為局部變數,避免污染其他作用域。




5)有兩個命令能幫助我調試腳本:set -e 遇到執行非0時退出腳本,set-x 列印執行過程。




6)寫腳本一定先測試再到生產上。




1 獲取隨機字元串或數字



獲取隨機8位字元串:



方法1:

# echo $RANDOM |md5sum |cut -c 1-8


471b94f2
方法2:

# openssl rand -base64 4


vg3BEg==
方法3:

# cat /proc/sys/kernel/random/uuid |cut -c 1-8


ed9e032c



獲取隨機8位數字:



方法1:

#

 

echo

 

$RANDOM

 |cksum |cut -c 1-8


23648321
方法2:

#

 openssl rand -base64 4 |cksum |cut -c 1-8


38571131
方法3:

#

 date +%N |cut -c 1-8


69024815


cksum:列印CRC效驗和統計位元組




2 定義一個顏色輸出字元串函數



方法1:

function

 

echo_color

() {
    

if

 [ 

$1

 == 

"green"

 ]; 

then


        

echo

 -e 

"33[32;40m

$2

33[0m"


    

elif

 [ 

$1

 == 

"red"

 ]; 

then


        

echo

 -e 

"33[31;40m

$2

33[0m"


    

fi


}
方法2:

function

 

echo_color

() {
    

case

 

$1

 

in


        green)
            

echo

 -e 

"33[32;40m

$2

33[0m"


            ;;
        red)
            

echo

 -e 

"33[31;40m

$2

33[0m"

 
            ;;
        *) 
            

echo

 

"Example: echo_color red string"


    

esac


}
使用方法:echo_color green 

"test"





function關鍵字定義一個函數,可加或不加。




3 批量創建用戶



#!/bin/bash


DATE=$(date +%F_%T)
USER_FILE=user.txt

echo_color

(){
    

if

 [ 

$1

 == 

"green"

 ]; 

then


        

echo

 -e 

"33[32;40m

$2

33[0m"


    

elif

 [ 

$1

 == 

"red"

 ]; 

then


        

echo

 -e 

"33[31;40m

$2

33[0m"


    

fi


}

# 如果用戶文件存在並且大小大於0就備份


if

 [ -s 

$USER_FILE

 ]; 

then


    mv 

$USER_FILE

 

${USER_FILE}

-

${DATE}

.bak
    echo_color green 

"

$USER_FILE

 exist, rename 

${USER_FILE}

-

${DATE}

.bak"


fi


echo

 -e 

"User Password"

 >> 

$USER_FILE


echo

 

"----------------"

 >> 

$USER_FILE


for

 USER 

in

 user{1..10}; 

do


    

if

 ! id 

$USER

 &>/dev/null; 

then


        PASS=$(

echo

 

$RANDOM

 |md5sum |cut -c 1-8)
        useradd 

$USER


        

echo

 

$PASS

 |passwd --stdin 

$USER

 &>/dev/null
        

echo

 -e 

"

$USER

$PASS

"

 >> 

$USER_FILE


        

echo

 

"

$USER

 User create successful."


    

else


        echo_color red 

"

$USER

 User already exists!"


    

fi


done





4 檢查軟體包是否安裝



#!/bin/bash


if

 rpm -q sysstat &>/dev/null; 

then


    

echo

 

"sysstat is already installed."


else


    

echo

 

"sysstat is not installed!"


fi





5 檢查服務狀態



#!/bin/bash


PORT_C=$(ss -anu |grep -c 123)
PS_C=$(ps -ef |grep ntpd |grep -vc grep)

if

 [ 

$PORT_C

 -eq 0 -o 

$PS_C

 -eq 0 ]; 

then


    

echo

 

"內容"

 | mail -s 

"主題"

 dst@example.com

fi





6 檢查主機存活狀態




方法1:將錯誤IP放到數組裡面判斷是否ping失敗三次



#!/bin/bash  


IP_LIST=

"192.168.18.1 192.168.1.1 192.168.18.2"


for

 IP 

in

 

$IP_LIST

do


    NUM=1
    

while

 [ 

$NUM

 -le 3 ]; 

do


        

if

 ping -c 1 

$IP

 > /dev/null; 

then


            

echo

 

"

$IP

 Ping is successful."


            

break


        

else


            

# echo "$IP Ping is failure $NUM"


            FAIL_COUNT[

$NUM

]=

$IP


            

let

 NUM++
        

fi


    

done


    

if

 [ 

${#FAIL_COUNT[*]}

 -eq 3 ];

then


        

echo

 

"

${FAIL_COUNT[1]}

 Ping is failure!"


        

unset

 FAIL_COUNT[*]
    

fi


done





方法2:將錯誤次數放到FAIL_COUNT變數裡面判斷是否ping失敗三次


#!/bin/bash  


IP_LIST=

"192.168.18.1 192.168.1.1 192.168.18.2"


for

 IP 

in

 

$IP_LIST

do


    FAIL_COUNT=0
    

for

 ((i=1;i<=3;i++)); 

do


        

if

 ping -c 1 

$IP

 >/dev/null; 

then


            

echo

 

"

$IP

 Ping is successful."


            

break


        

else


            

# echo "$IP Ping is failure $i"


            

let

 FAIL_COUNT++
        

fi


    

done


    

if

 [ 

$FAIL_COUNT

 -eq 3 ]; 

then


        

echo

 

"

$IP

 Ping is failure!"


    

fi


done





方法3:利用for循環將ping通就跳出循環繼續,如果不跳出就會走到列印ping失敗



#!/bin/bash


ping_success_status

() {
    

if

 ping -c 1 

$IP

 >/dev/null; 

then


        

echo

 

"

$IP

 Ping is successful."


        

continue


    

fi


}
IP_LIST=

"192.168.18.1 192.168.1.1 192.168.18.2"


for

 IP 

in

 

$IP_LIST

do


    ping_success_status
    ping_success_status
    ping_success_status
    

echo

 

"

$IP

 Ping is failure!"


done





7 監控CPU、內存和硬碟利用率




1)CPU




藉助vmstat工具來分析CPU統計信息。



#!/bin/bash


DATE=$(date +%F

" "

%H:%M)
IP=$(ifconfig eth0 |awk -F 

"[ :]+"

 

"/inet addr/{print $4}"

)  

# 只支持CentOS6


MAIL=

"example@mail.com"


if

 ! 

which

 vmstat &>/dev/null; 

then


    

echo

 

"vmstat command no found, Please install procps package."

 
    

exit

 1

fi


US=$(vmstat |awk 

"NR==3{print $13}"

)
SY=$(vmstat |awk 

"NR==3{print $14}"

)
IDLE=$(vmstat |awk 

"NR==3{print $15}"

)
WAIT=$(vmstat |awk 

"NR==3{print $16}"

)
USE=$((

$US

+

$SY

))

if

 [ 

$USE

 -ge 50 ]; 

then


    

echo

 

"
    Date: 

$DATE


    Host: 

$IP


    Problem: CPU utilization 

$USE


    "

 | mail -s 

"CPU Monitor"

 

$MAIL


fi





2)內存



#!/bin/bash


DATE=$(date +%F

" "

%H:%M)
IP=$(ifconfig eth0 |awk -F 

"[ :]+"

 

"/inet addr/{print $4}"

)  
MAIL=

"example@mail.com"


TOTAL=$(free -m |awk 

"/Mem/{print $2}"

)
USE=$(free -m |awk 

"/Mem/{print $3-$6-$7}"

)
FREE=$((

$TOTAL

-

$USE

))

# 內存小於1G發送報警郵件


if

 [ 

$FREE

 -lt 1024 ]; 

then


    

echo

 

"
    Date: 

$DATE


    Host: 

$IP


    Problem: Total=

$TOTAL

,Use=

$USE

,Free=

$FREE


    "

 | mail -s 

"Memory Monitor"

 

$MAIL


fi





3)硬碟



#!/bin/bash


DATE=$(date +%F

" "

%H:%M)
IP=$(ifconfig eth0 |awk -F 

"[ :]+"

 

"/inet addr/{print $4}"

)  
MAIL=

"example@mail.com"


TOTAL=$(fdisk -l |awk -F

"[: ]+"

 

"BEGIN{OFS="="}/^Disk /dev/{printf "%s=%sG,",$2,$3}"

)
PART_USE=$(df -h |awk 

"BEGIN{OFS="="}/^/dev/{print $1,int($5),$6}"

)

for

 i 

in

 

$PART_USE

do


    PART=$(

echo

 

$i

 |cut -d

"="

 -f1)
    USE=$(

echo

 

$i

 |cut -d

"="

 -f2)
    MOUNT=$(

echo

 

$i

 |cut -d

"="

 -f3)
    

if

 [ 

$USE

 -gt 80 ]; 

then


        

echo

 

"
        Date: 

$DATE


        Host: 

$IP


        Total: 

$TOTAL


        Problem: 

$PART

=

$USE

(

$MOUNT

)
        "

 | mail -s 

"Disk Monitor"

 

$MAIL


    

fi


done





8 批量主機磁碟利用率監控




前提監控端和被監控端SSH免交互登錄或者密鑰登錄。




寫一個配置文件保存被監控主機SSH連接信息,文件內容格式:IP User Port



#!/bin/bash


HOST_INFO=host.info

for

 IP 

in

 $(awk 

"/^[^#]/{print $1}"

 

$HOST_INFO

); 

do


    USER=$(awk -v ip=

$IP

 

"ip==$1{print $2}"

 

$HOST_INFO

)
    PORT=$(awk -v ip=

$IP

 

"ip==$1{print $3}"

 

$HOST_INFO

)
    TMP_FILE=/tmp/disk.tmp
    ssh -p 

$PORT

 

$USER

@

$IP

 

"df -h"

 > 

$TMP_FILE


    USE_RATE_LIST=$(awk 

"BEGIN{OFS="="}/^/dev/{print $1,int($5)}"

 

$TMP_FILE

)
    

for

 USE_RATE 

in

 

$USE_RATE_LIST

do


        PART_NAME=

${USE_RATE%=*}


        USE_RATE=

${USE_RATE#*=}


        

if

 [ 

$USE_RATE

 -ge 80 ]; 

then


            

echo

 

"Warning: 

$PART_NAME

 Partition usage 

$USE_RATE

%!"


        

fi


    

done


done





9 檢查網站可用性




1)檢查URL可用性



方法1:

check_url

() {
    HTTP_CODE=$(curl -o /dev/null --connect-timeout 3 -s -w 

"%{http_code}"

 

$1

)
    

if

 [ 

$HTTP_CODE

 -ne 200 ]; 

then


        

echo

 

"Warning: 

$1

 Access failure!"


    

fi


}
方法2:

check_url

() {

if

 ! wget -T 10 --tries=1 --spider 

$1

 >/dev/null 2>&1; 

then

  

#-T超時時間,--tries嘗試1次,--spider爬蟲模式


        

echo

 

"Warning: 

$1

 Access failure!"


    

fi


}



使用方法:check_url www.baidu.com




2)判斷三次URL可用性




思路與上面檢查主機存活狀態一樣。



方法1:利用循環技巧,如果成功就跳出當前循環,否則執行到最後一行

#!/bin/bash  


check_url

() {
    HTTP_CODE=$(curl -o /dev/null --connect-timeout 3 -s -w 

"%{http_code}"

 

$1

)
    

if

 [ 

$HTTP_CODE

 -eq 200 ]; 

then


        

continue


    

fi


}
URL_LIST=

"www.baidu.com www.agasgf.com"


for

 URL 

in

 

$URL_LIST

do


    check_url 

$URL


    check_url 

$URL


    check_url 

$URL


    

echo

 

"Warning: 

$URL

 Access failure!"


done




方法2:錯誤次數保存到變數

#!/bin/bash  


URL_LIST=

"www.baidu.com www.agasgf.com"


for

 URL 

in

 

$URL_LIST

do


    FAIL_COUNT=0
    

for

 ((i=1;i<=3;i++)); 

do


        HTTP_CODE=$(curl -o /dev/null --connect-timeout 3 -s -w 

"%{http_code}"

 

$URL

)
        

if

 [ 

$HTTP_CODE

 -ne 200 ]; 

then


            

let

 FAIL_COUNT++
        

else


            

break


        

fi


    

done


    

if

 [ 

$FAIL_COUNT

 -eq 3 ]; 

then


        

echo

 

"Warning: 

$URL

 Access failure!"


    

fi


done




方法3:錯誤次數保存到數組

#!/bin/bash  


URL_LIST=

"www.baidu.com www.agasgf.com"


for

 URL 

in

 

$URL_LIST

do


    NUM=1
    

while

 [ 

$NUM

 -le 3 ]; 

do


        HTTP_CODE=$(curl -o /dev/null --connect-timeout 3 -s -w 

"%{http_code}"

 

$URL

)
        

if

 [ 

$HTTP_CODE

 -ne 200 ]; 

then


            FAIL_COUNT[

$NUM

]=

$IP

  

#創建數組,以$NUM下標,$IP元素


            

let

 NUM++
        

else


            

break


        

fi


    

done


    

if

 [ 

${#FAIL_COUNT[*]}

 -eq 3 ]; 

then


        

echo

 

"Warning: 

$URL

 Access failure!"


        

unset

 FAIL_COUNT[*]    

#清空數組


    

fi


done





10 檢查MySQL主從同步狀態



#!/bin/bash  


USER=bak
PASSWD=123456
IO_SQL_STATUS=$(mysql -u

$USER

 -p

$PASSWD

 -e 

"show slave statusG"

 |awk -F: 

"/Slave_.*_Running/{gsub(": ",":");print $0}"

)  

#gsub去除冒號後面的空格


for

 i 

in

 

$IO_SQL_STATUS

do


    THREAD_STATUS_NAME=

${i%:*}


    THREAD_STATUS=

${i#*:}


    

if

 [ 

"

$THREAD_STATUS

"

 != 

"Yes"

 ]; 

then


        

echo

 

"Error: MySQL Master-Slave 

$THREAD_STATUS_NAME

 status is 

$THREAD_STATUS

!"


    

fi


done





本章寫的Shell腳本例子都比較實用,在面試題中也經常出現,希望大家參考著多動手寫寫,不要複製粘貼就拿來跑,這樣是學不會的!






【關於投稿】




如果大家有原創好文投稿,請直接給公號發送留言。




① 留言格式:


【投稿】+《 文章標題》+ 文章鏈接

② 示例:


【投稿】《不要自稱是程序員,我十多年的 IT 職場總結》:


http://blog.jobbole.com/94148/

③ 最後請附上您的個人簡介哈~






看完本文有收穫?請轉

發分享給更多人


關注「P

ython開發者」,提升Python技能



喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 Python開發者 的精彩文章:

一文讀懂 PySpark 數據框
順豐該不該開除刪庫的運維工程師?

TAG:Python開發者 |