(轉(zhuǎn))30個(gè)關(guān)于Shell腳本的經(jīng)典案例

https://www.cnblogs.com/linuxprobe/p/11518761.html

30個(gè)關(guān)于Shell腳本的經(jīng)典案例(上)

| 對于初學(xué)者而言,因?yàn)闆]有實(shí)戰(zhàn)經(jīng)驗(yàn),寫不出來Shell腳本很正常,如果工作了幾年的運(yùn)維老年還是寫不出來,那就是沒主動(dòng)找需求,缺乏練習(xí),缺乏經(jīng)驗(yàn)。針對以上問題,總結(jié)了30個(gè)生產(chǎn)環(huán)境中經(jīng)典的Shell腳本,通過這些需求案例,希望能幫助大家提升Shell編寫思路,掌握編寫技巧。 |

先了解下編寫Shell過程中注意事項(xiàng):

<pre style="margin: 0px; padding: 0px; white-space: pre-wrap; overflow-wrap: break-word;">開頭加解釋器:#!/bin/bash
語法縮進(jìn),使用四個(gè)空格;多加注釋說明。
命名建議規(guī)則:變量名大寫、局部變量小寫,函數(shù)名小寫,名字體現(xiàn)出實(shí)際作用。
默認(rèn)變量是全局的,在函數(shù)中變量local指定為局部變量,避免污染其他作用域。
有兩個(gè)命令能幫助我調(diào)試腳本:set -e 遇到執(zhí)行非0時(shí)退出腳本,set-x 打印執(zhí)行過程。
寫腳本一定先測試再到生產(chǎn)上。
</pre>

1、獲取隨機(jī)字符串或數(shù)字

<pre style="margin: 0px; padding: 0px; white-space: pre-wrap; overflow-wrap: break-word;">獲取隨機(jī)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

獲取隨機(jī)8位數(shù)字:
方法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效驗(yàn)和統(tǒng)計(jì)字節(jié)
</pre>

2、定義一個(gè)顏色輸出字符串函數(shù)

<pre style="margin: 0px; padding: 0px; white-space: pre-wrap; overflow-wrap: break-word;">方法1:
function echo_color() {
if [ 1 == "green" ]; then echo -e "\033[32;40m2\033[0m"
elif [ 1 == "red" ]; then echo -e "\033[31;40m2\033[0m"
fi
}
方法2:
function echo_color() {
case 1 in green) echo -e "[32;40m2[0m"
;;
red)
echo -e "[31;40m$2[0m"
;;
*)
echo "Example: echo_color red string"
esac
}

使用方法:echo_color green "test"

function關(guān)鍵字定義一個(gè)函數(shù),可加或不加。
</pre>

3、批量創(chuàng)建用戶

<pre style="margin: 0px; padding: 0px; white-space: pre-wrap; overflow-wrap: break-word;">#!/bin/bash
DATE=(date +%F_%T) USER_FILE=user.txt echo_color(){ if [1 == "green" ]; then
echo -e "[32;40m2[0m" elif [1 == "red" ]; then
echo -e "[31;40m$2[0m"
fi
}

如果用戶文件存在并且大小大于0就備份

if [ -s USER_FILE ]; then mvUSER_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 ! idUSER &>/dev/null; then
PASS=(echoRANDOM |md5sum |cut -c 1-8)
useradd USER echoPASS |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
</pre>

4、檢查軟件包是否安裝

<pre style="margin: 0px; padding: 0px; white-space: pre-wrap; overflow-wrap: break-word;">#!/bin/bash
if rpm -q sysstat &>/dev/null; then
echo "sysstat is already installed."
else
echo "sysstat is not installed!"
fi
</pre>

5、檢查服務(wù)狀態(tài)

<pre style="margin: 0px; padding: 0px; white-space: pre-wrap; overflow-wrap: break-word;">#!/bin/bash
PORT_C=(ss -anu |grep -c 123) PS_C=(ps -ef |grep ntpd |grep -vc grep)
if [ PORT_C -eq 0 -oPS_C -eq 0 ]; then
echo "內(nèi)容" | mail -s "主題" dst@example.com
fi
</pre>

6、檢查主機(jī)存活狀態(tài)

<pre style="margin: 0px; padding: 0px; white-space: pre-wrap; overflow-wrap: break-word;">方法1:將錯(cuò)誤IP放到數(shù)組里面判斷是否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 failureNUM"
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:將錯(cuò)誤次數(shù)放到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 1IP >/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循環(huán)將ping通就跳出循環(huán)繼續(xù),如果不跳出就會(huì)走到打印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
</pre>

7、監(jiān)控CPU、內(nèi)存和硬盤利用率

<pre style="margin: 0px; padding: 0px; white-space: pre-wrap; overflow-wrap: break-word;">1)CPU
借助vmstat工具來分析CPU統(tǒng)計(jì)信息。

!/bin/bash

DATE=(date +%F" "%H:%M) IP=(ifconfig eth0 |awk -F [ :]+ /inet addr/{print 4} ) # 只支持[CentOS](https://www.linuxprobe.com/ "centos")6 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 utilizationUSE
" | mail -s "CPU Monitor" $MAIL
fi

2)內(nèi)存

!/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))

內(nèi)存小于1G發(fā)送報(bào)警郵件

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/{print1,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
</pre>

8、批量主機(jī)磁盤利用率監(jiān)控

<pre style="margin: 0px; padding: 0px; white-space: pre-wrap; overflow-wrap: break-word;">前提監(jiān)控端和被監(jiān)控端SSH免交互登錄或者密鑰登錄。

寫一個(gè)配置文件保存被監(jiān)控主機(jī)SSH連接信息,文件內(nèi)容格式:IP User Port

!/bin/bash

HOST_INFO=host.info
for IP in (awk /^[^#]/{print1} HOST_INFO); do USER=(awk -v ip=IP ip==1{print 2}HOST_INFO)
PORT=(awk -v ip=IP ip==1{print3} HOST_INFO) TMP_FILE=/tmp/disk.tmp ssh -pPORT USER@IP df -h > TMP_FILE USE_RATE_LIST=(awk BEGIN{OFS="="}/^/dev/{print 1,int(5)} TMP_FILE) for USE_RATE inUSE_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
</pre>

9、檢查網(wǎng)站可用性

<pre style="margin: 0px; padding: 0px; white-space: pre-wrap; overflow-wrap: break-word;">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超時(shí)時(shí)間,--tries嘗試1次,--spider爬蟲模式

    echo "Warning: $1 Access failure!"
fi

}

使用方法:check_url www.baidu.com

2)判斷三次URL可用性
思路與上面檢查主機(jī)存活狀態(tài)一樣。

方法1:利用循環(huán)技巧,如果成功就跳出當(dāng)前循環(huán),否則執(zhí)行到最后一行

!/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 inURL_LIST; do
check_url URL check_urlURL
check_url URL echo "Warning:URL Access failure!"
done

方法2:錯(cuò)誤次數(shù)保存到變量

!/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:錯(cuò)誤次數(shù)保存到數(shù)組

!/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 #創(chuàng)建數(shù)組,以NUM下標(biāo),IP元素 let NUM++ else break fi done if [{#FAIL_COUNT[]} -eq 3 ]; then
echo "Warning: $URL Access failure!"
unset FAIL_COUNT[
] #清空數(shù)組
fi
done
</pre>

10、檢查MySQL主從同步狀態(tài)

<pre style="margin: 0px; padding: 0px; white-space: pre-wrap; overflow-wrap: break-word;">#!/bin/bash
USER=bak
PASSWD=123456
IO_SQL_STATUS=(mysql -uUSER -pPASSWD -e show slave statusG |awk -F: /Slave_.*_Running/{gsub(": ",":");print0} ) #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 isTHREAD_STATUS!"
fi
done
</pre>

動(dòng)手練一練,讓你的Shell功底上升一個(gè)段位!

本文目錄

<pre style="margin: 0px; padding: 0px; white-space: pre-wrap; overflow-wrap: break-word; color: rgb(51, 51, 51); font-size: 14px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); text-decoration-style: initial; text-decoration-color: initial;">11、iptables自動(dòng)屏蔽訪問網(wǎng)站頻繁的IP
12、判斷用戶輸入的是否為IP地址
13、判斷用戶輸入的是否為數(shù)字
14、給定目錄找出包含關(guān)鍵字的文件
15、監(jiān)控目錄,將新創(chuàng)建的文件名追加到日志中
16、給用戶提供多個(gè)網(wǎng)卡選擇
17、查看網(wǎng)卡實(shí)時(shí)流量
18、MySQL數(shù)據(jù)庫備份
19、Nginx服務(wù)管理腳本
20、用戶根據(jù)菜單選擇要連接的Linux主機(jī)
</pre>

11、iptables自動(dòng)屏蔽訪問網(wǎng)站頻繁的IP

<pre style="margin: 0px; padding: 0px; white-space: pre-wrap; overflow-wrap: break-word; color: rgb(51, 51, 51); font-size: 14px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); text-decoration-style: initial; text-decoration-color: initial;">場景:惡意訪問,安全防范

1)屏蔽每分鐘訪問超過200的IP

方法1:根據(jù)訪問日志(Nginx為例)

!/bin/bash

DATE=(date +%d/%b/%Y:%H:%M) ABNORMAL_IP=(tail -n5000 access.log |grep DATE |awk '{a[1]++}END{for(i in a)if(a[i]>100)print i}')

先tail防止文件過大,讀取慢,數(shù)字可調(diào)整每分鐘最大的訪問量。awk不能直接過濾日志,因?yàn)榘厥庾址?/h1>

for IP in ABNORMAL_IP; do if [(iptables -vnL |grep -c "IP") -eq 0 ]; then iptables -I INPUT -sIP -j DROP
fi
done
方法2:通過TCP建立的連接

!/bin/bash

ABNORMAL_IP=(netstat -an |awk '4~/:80/ &&6~/ESTABLISHED/{gsub(/:[0-9]+/,"",5);{a[5]++}}END{for(i in a)if(a[i]>100)print i}')

gsub是將第五列(客戶端IP)的冒號和端口去掉

for IP in ABNORMAL_IP; do if [(iptables -vnL |grep -c "IP") -eq 0 ]; then iptables -I INPUT -sIP -j DROP
fi
done

2)屏蔽每分鐘SSH嘗試登錄超過10次的IP

方法1:通過lastb獲取登錄狀態(tài):

!/bin/bash

DATE=(date +"%a %b %e %H:%M") #星期月天時(shí)分 %e單數(shù)字時(shí)顯示7,而%d顯示07 ABNORMAL_IP=(lastb |grep "DATE" |awk '{a[3]++}END{for(i in a)if(a[i]>10)print i}')
for IP in ABNORMAL_IP; do if [(iptables -vnL |grep -c "IP") -eq 0 ]; then iptables -I INPUT -sIP -j DROP
fi
done
方法2:通過日志獲取登錄狀態(tài)

!/bin/bash

DATE=(date +"%b %d %H") ABNORMAL_IP="(tail -n10000 /var/log/auth.log |grep "DATE" |awk '/Failed/{a[(NF-3)]++}END{for(i in a)if(a[i]>5)print i}')"
for IP in ABNORMAL_IP; do if [(iptables -vnL |grep -c "IP") -eq 0 ]; then iptables -A INPUT -sIP -j DROP
echo "(date +"%F %T") - iptables -A INPUT -sIP -j DROP" >>~/ssh-login-limit.log
fi
done
</pre>

12、判斷用戶輸入的是否為IP地址

<pre style="margin: 0px; padding: 0px; white-space: pre-wrap; overflow-wrap: break-word; color: rgb(51, 51, 51); font-size: 14px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); text-decoration-style: initial; text-decoration-color: initial;">方法1:

!/bin/bash

function check_ip(){
IP=1 VALID_CHECK=(echo IP|awk -F. '1< =255&&2<=255&&3<=255&&4<=255{print "yes"}') if echoIP|grep -E "^[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}">/dev/null; then if [VALID_CHECK == "yes" ]; then
echo "IP available." else echo "IP not available!"
fi
else
echo "Format error!"
fi
}
check_ip 192.168.1.1
check_ip 256.1.1.1
方法2:

!/bin/bash

function check_ip(){
IP=1 if [[IP =~ ^[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}]]; then FIELD1=(echo IP|cut -d. -f1) FIELD2=(echo IP|cut -d. -f2) FIELD3=(echo IP|cut -d. -f3) FIELD4=(echo IP|cut -d. -f4) if [FIELD1 -le 255 -a FIELD2 -le 255 -aFIELD3 -le 255 -a FIELD4 -le 255 ]; then echo "IP available."
else
echo "$IP not available!"
fi
else
echo "Format error!"
fi
}
check_ip 192.168.1.1
check_ip 256.1.1.1
增加版:

加個(gè)死循環(huán),如果IP可用就退出,不可用提示繼續(xù)輸入,并使用awk判斷。

!/bin/bash

function check_ip(){
local IP=1 VALID_CHECK=(echo IP|awk -F. '1< =255&&2<=255&&3<=255&&4<=255{print "yes"}') if echoIP|grep -E "^[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}" >/dev/null; then if [VALID_CHECK == "yes" ]; then
return 0
else
echo "IP not available!" return 1 fi else echo "Format error! Please input again." return 1 fi } while true; do read -p "Please enter IP: " IP check_ipIP
[ $? -eq 0 ] && break || continue
done
</pre>

13、判斷用戶輸入的是否為數(shù)字

<pre style="margin: 0px; padding: 0px; white-space: pre-wrap; overflow-wrap: break-word; color: rgb(51, 51, 51); font-size: 14px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); text-decoration-style: initial; text-decoration-color: initial;">方法1:

!/bin/bash

if [[ 1 =~ ^[0-9]+ ]]; then
echo "Is Number."
else
echo "No Number."
fi
方法2:

!/bin/bash

if [ $1 -gt 0 ] 2>/dev/null; then
echo "Is Number."
else
echo "No Number."
fi
方法3:

!/bin/bash

echo 1 |awk '{print0~/^[0-9]+/?"Is Number.":"No Number."}' #三目運(yùn)算符 12.14 找出包含關(guān)鍵字的文件 DIR=1
KEY=2 for FILE in(find DIR -type f); do if grepKEY FILE &>/dev/null; then echo "-->FILE"
fi
done
</pre>

14、給定目錄找出包含關(guān)鍵字的文件

<pre style="margin: 0px; padding: 0px; white-space: pre-wrap; overflow-wrap: break-word; color: rgb(51, 51, 51); font-size: 14px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); text-decoration-style: initial; text-decoration-color: initial;">#!/bin/bash
DIR=1 KEY=2
for FILE in (findDIR -type f); do
if grep KEYFILE &>/dev/null; then
echo "--> $FILE"
fi
done
</pre>

15、監(jiān)控目錄,將新創(chuàng)建的文件名追加到日志中

<pre style="margin: 0px; padding: 0px; white-space: pre-wrap; overflow-wrap: break-word; color: rgb(51, 51, 51); font-size: 14px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); text-decoration-style: initial; text-decoration-color: initial;">場景:記錄目錄下文件操作。

需先安裝inotify-tools軟件包。

!/bin/bash

MON_DIR=/opt
inotifywait -mq --format %f -e create MON_DIR |\ while read files; do echofiles >> test.log
done
</pre>

16、給用戶提供多個(gè)網(wǎng)卡選擇

<pre style="margin: 0px; padding: 0px; white-space: pre-wrap; overflow-wrap: break-word; color: rgb(51, 51, 51); font-size: 14px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); text-decoration-style: initial; text-decoration-color: initial;">場景:服務(wù)器多個(gè)網(wǎng)卡時(shí),獲取指定網(wǎng)卡,例如網(wǎng)卡流量

!/bin/bash

function local_nic() {
local NUM ARRAY_LENGTH
NUM=0
for NIC_NAME in (ls /sys/class/net|grep -vE "lo|docker0"); do NIC_IP=(ifconfig NIC_NAME |awk -F'[: ]+' '/inet addr/{print4}')
if [ -n "NIC_IP" ]; then NIC_IP_ARRAY[NUM]="NIC_NAME:NIC_IP" #將網(wǎng)卡名和對應(yīng)IP放到數(shù)組
let NUM++
fi
done
ARRAY_LENGTH={#NIC_IP_ARRAY[*]} if [ARRAY_LENGTH -eq 1 ]; then #如果數(shù)組里面只有一條記錄說明就一個(gè)網(wǎng)卡
NIC={NIC_IP_ARRAY[0]%:*} return 0 elif [ARRAY_LENGTH -eq 0 ]; then #如果沒有記錄說明沒有網(wǎng)卡
echo "No available network card!"
exit 1
else
#如果有多條記錄則提醒輸入選擇
for NIC in {NIC_IP_ARRAY[*]}; do echoNIC
done
while true; do
read -p "Please enter local use to network card name: " INPUT_NIC_NAME
COUNT=0
for NIC in {NIC_IP_ARRAY[*]}; do NIC_NAME={NIC%:}
if [ NIC_NAME == "INPUT_NIC_NAME" ]; then
NIC={NIC_IP_ARRAY[COUNT]%:
}
return 0
else
COUNT+=1
fi
done
echo "Not match! Please input again."
done
fi
}
local_nic
</pre>

17、查看網(wǎng)卡實(shí)時(shí)流量

<pre style="margin: 0px; padding: 0px; white-space: pre-wrap; overflow-wrap: break-word; color: rgb(51, 51, 51); font-size: 14px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); text-decoration-style: initial; text-decoration-color: initial;">適用于CentOS6操作系統(tǒng)。

!/bin/bash

Description: Only CentOS6

traffic_unit_conv() {
local traffic=1 if [traffic -gt 1024000 ]; then
printf "%.1f%s" "((traffic/1024/1024))" "MB/s"
elif [ traffic -lt 1024000 ]; then printf "%.1f%s" "((traffic/1024))" "KB/s" fi } NIC=1
echo -e " In ------ Out"
while true; do
OLD_IN=(awk -F'[: ]+' '0~"'NIC'"{print3}' /proc/net/dev)
OLD_OUT=(awk -F'[: ]+' '0~"'NIC'"{print11}' /proc/net/dev)
sleep 1
NEW_IN=(awk -F'[: ]+' '0~"'NIC'"{print3}' /proc/net/dev)
NEW_OUT=(awk -F'[: ]+' '0~"'NIC'"{print11}' /proc/net/dev)
IN=((NEW_IN-OLD_IN)) OUT=((NEW_OUT-OLD_OUT))
echo "(traffic_unit_convIN) (traffic_unit_convOUT)"
sleep 1
done
使用:./traffic.sh eth0
</pre>

18、MySQL數(shù)據(jù)庫備份

<pre style="margin: 0px; padding: 0px; white-space: pre-wrap; overflow-wrap: break-word; color: rgb(51, 51, 51); font-size: 14px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); text-decoration-style: initial; text-decoration-color: initial;">#!/bin/bash
DATE=(date +%F_%H-%M-%S) HOST=192.168.1.120 DB=test USER=bak PASS=123456 MAIL="zhangsan@example.com lisi@example.com" BACKUP_DIR=/data/db_backup SQL_FILE={DB}fullDATE.sql BAK_FILE={DB}fullDATE.zip cdBACKUP_DIR
if mysqldump -hHOST -uUSER -pPASS --single-transaction --routines --triggers -BDB > SQL_FILE; then zipBAK_FILE SQL_FILE && rm -fSQL_FILE
if [ ! -s BAK_FILE ]; then echo "DATE 內(nèi)容" | mail -s "主題" MAIL fi else echo "DATE 內(nèi)容" | mail -s "主題" MAIL fi findBACKUP_DIR -name '*.zip' -ctime +14 -exec rm {} ;
</pre>

19、Nginx服務(wù)管理腳本

<pre style="margin: 0px; padding: 0px; white-space: pre-wrap; overflow-wrap: break-word; color: rgb(51, 51, 51); font-size: 14px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); text-decoration-style: initial; text-decoration-color: initial;">場景:使用源碼包安裝Nginx不含帶服務(wù)管理腳本,也就是不能使用"service nginx start"或"/etc/init.d/nginx start",所以寫了以下的服務(wù)管理腳本。

!/bin/bash

Description: Only support RedHat system

. /etc/init.d/functions
WORD_DIR=/usr/local/nginx
DAEMON=WORD_DIR/sbin/nginx CONF=WORD_DIR/conf/nginx.conf
NAME=nginx
PID=(awk -F'[; ]+' '/^[^#]/{if(0~/pid;/)print 2}'CONF)
if [ -z "PID" ]; then PID=WORD_DIR/logs/nginx.pid
else
PID=WORD_DIR/PID
fi
stop() {
DAEMON -s stop sleep 1 [ ! -fPID ] && action "* Stopping NAME" /bin/true || action "* StoppingNAME" /bin/false
}
start() {
DAEMON sleep 1 [ -fPID ] && action "* Starting NAME" /bin/true || action "* StartingNAME" /bin/false
}
reload() {
DAEMON -s reload } test_config() {DAEMON -t
}
case "1" in start) if [ ! -fPID ]; then
start
else
echo "NAME is running..." exit 0 fi ;; stop) if [ -fPID ]; then
stop
else
echo "NAME not running!" exit 0 fi ;; restart) if [ ! -fPID ]; then
echo "NAME not running!" start else stop start fi ;; reload) reload ;; testconfig) test_config ;; status) [ -fPID ] && echo "NAME is running..." || echo "NAME not running!"
;;
*)
echo "Usage: $0 {start|stop|restart|reload|testconfig|status}"
exit 3
;;
esac</pre>

https://article.pchome.net/content-2100027.html
http://www.51cto.com/it/news/2019/0909/14338.html
https://www.linuxprobe.com/books

20、用戶根據(jù)菜單選擇要連接的Linux主機(jī)

<pre style="margin: 0px; padding: 0px; white-space: pre-wrap; overflow-wrap: break-word; color: rgb(51, 51, 51); font-size: 14px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); text-decoration-style: initial; text-decoration-color: initial;">Linux主機(jī)SSH連接信息:

cat host.txt

Web 192.168.1.10 root 22
DB 192.168.1.11 root 22
內(nèi)容格式:主機(jī)名 IP User Port

!/bin/bash

PS3="Please input number: "
HOST_FILE=host.txt
while true; do
select NAME in (awk '{print1}' HOST_FILE) quit; do [{NAME:=empty} == "quit" ] && exit 0
IP=(awk -v NAME={NAME} '1==NAME{print2}' HOST_FILE) USER=(awk -v NAME={NAME} '1==NAME{print 3}'HOST_FILE)
PORT=(awk -v NAME={NAME} '1==NAME{print4}' HOST_FILE) if [IP ]; then
echo "Name: NAME, IP:IP"
ssh -o StrictHostKeyChecking=no -p PORT -i id_rsaUSER@$IP # 密鑰免交互登錄
break
else
echo "Input error, Please enter again!"
break
fi
done
done</pre>

本文目錄

<pre style="margin: 0px; padding: 0px; white-space: pre-wrap; overflow-wrap: break-word; color: rgb(51, 51, 51); font-size: 14px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); text-decoration-style: initial; text-decoration-color: initial;">21、從FTP服務(wù)器下載文件
22、連續(xù)輸入5個(gè)100以內(nèi)的數(shù)字,統(tǒng)計(jì)和、最小和最大
23、將結(jié)果分別賦值給變量
24、批量修改文件名
25、統(tǒng)計(jì)當(dāng)前目錄中以.html結(jié)尾的文件總大
26、掃描主機(jī)端口狀態(tài)
27、Expect實(shí)現(xiàn)SSH免交互執(zhí)行命令
28、批量修改服務(wù)器用戶密碼
29、打印乘法口訣
30、getopts工具完善腳本命令行參數(shù)
</pre>

21、從FTP服務(wù)器下載文件

<pre style="margin: 0px; padding: 0px; white-space: pre-wrap; overflow-wrap: break-word; color: rgb(51, 51, 51); font-size: 14px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); text-decoration-style: initial; text-decoration-color: initial;">#!/bin/bash
if [ # -ne 1 ]; then echo "Usage:0 filename"
fi
dir=(dirname1)
file=(basename1)
ftp -n -v << EOF # -n 自動(dòng)登錄
open 192.168.1.10 # ftp服務(wù)器
user admin password
binary # 設(shè)置ftp傳輸模式為二進(jìn)制,避免MD5值不同或.tar.gz壓縮包格式錯(cuò)誤
cd dir get "file"
EOF
</pre>

22、連續(xù)輸入5個(gè)100以內(nèi)的數(shù)字,統(tǒng)計(jì)和、最小和最大

<pre style="margin: 0px; padding: 0px; white-space: pre-wrap; overflow-wrap: break-word; color: rgb(51, 51, 51); font-size: 14px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); text-decoration-style: initial; text-decoration-color: initial;">#!/bin/bash
COUNT=1
SUM=0
MIN=0
MAX=100
while [ COUNT -le 5 ]; do read -p "請輸入1-10個(gè)整數(shù):" INT if [[ !INT =~ ^[0-9]+]]; then echo "輸入必須是整數(shù)!" exit 1 elif [[INT -gt 100 ]]; then
echo "輸入必須是100以內(nèi)!"
exit 1
fi
SUM=((SUM+INT)) [MIN -lt INT ] && MIN=INT
[ MAX -gtINT ] && MAX=INT let COUNT++ done echo "SUM:SUM"
echo "MIN: MIN" echo "MAX:MAX"
</pre>

30個(gè)關(guān)于Shell腳本的經(jīng)典案例(下)30個(gè)關(guān)于Shell腳本的經(jīng)典案例(下)

23、將結(jié)果分別賦值給變量

<pre style="margin: 0px; padding: 0px; white-space: pre-wrap; overflow-wrap: break-word; color: rgb(51, 51, 51); font-size: 14px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); text-decoration-style: initial; text-decoration-color: initial;">應(yīng)用場景:希望將執(zhí)行結(jié)果或者位置參數(shù)賦值給變量,以便后續(xù)使用。

方法1:

for i in (echo "4 5 6"); do eval ai=i done echoa4 a5a6
方法2:將位置參數(shù)192.168.1.1{1,2}拆分為到每個(gè)變量

num=0
for i in (eval echo*);do #eval將{1,2}分解為1 2
let num+=1
eval node{num}="i"
done
echo node1node2 $node3

bash a.sh 192.168.1.1{1,2}

192.168.1.11 192.168.1.12
方法3:

arr=(4 5 6)
INDEX1=(echo{arr[0]})
INDEX2=(echo{arr[1]})
INDEX3=(echo{arr[2]})
</pre>

24、批量修改文件名

<pre style="margin: 0px; padding: 0px; white-space: pre-wrap; overflow-wrap: break-word; color: rgb(51, 51, 51); font-size: 14px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); text-decoration-style: initial; text-decoration-color: initial;">示例:

touch article_{1..3}.html

ls

article_1.html article_2.html article_3.html
目的:把a(bǔ)rticle改為bbs

方法1:

for file in (ls *html); do mvfile bbs_{file#*_} # mvfile (echofile |sed -r 's/.(_.)/bbs\1/')
# mv file(echo file |echo bbs_(cut -d_ -f2)
done
方法2:

for file in (find . -maxdepth 1 -name "*html"); do mvfile bbs_${file#*_}
done
方法3:

rename article bbs *.html

</pre>

25、統(tǒng)計(jì)當(dāng)前目錄中以.html結(jié)尾的文件總大

<pre style="margin: 0px; padding: 0px; white-space: pre-wrap; overflow-wrap: break-word; color: rgb(51, 51, 51); font-size: 14px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); text-decoration-style: initial; text-decoration-color: initial;">方法1:

find . -name "*.html" -exec du -k {} ; |awk '{sum+=$1}END{print sum}'

方法2:

for size in (ls -l *.html |awk '{print5}'); do
sum=((sum+size)) done echosum
</pre>

26、掃描主機(jī)端口狀態(tài)

<pre style="margin: 0px; padding: 0px; white-space: pre-wrap; overflow-wrap: break-word; color: rgb(51, 51, 51); font-size: 14px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); text-decoration-style: initial; text-decoration-color: initial;">#!/bin/bash
HOST=1 PORT="22 25 80 8080" for PORT inPORT; do
if echo &>/dev/null > /dev/tcp/HOST/PORT; then
echo "PORT open" else echo "PORT close"
fi
done
</pre>

27、Expect實(shí)現(xiàn)SSH免交互執(zhí)行命令

<pre style="margin: 0px; padding: 0px; white-space: pre-wrap; overflow-wrap: break-word; color: rgb(51, 51, 51); font-size: 14px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); text-decoration-style: initial; text-decoration-color: initial;">Expect是一個(gè)自動(dòng)交互式應(yīng)用程序的工具,如telnet,ftp,passwd等。

需先安裝expect軟件包。

方法1:EOF標(biāo)準(zhǔn)輸出作為expect標(biāo)準(zhǔn)輸入

!/bin/bash

USER=root
PASS=123.com
IP=192.168.1.120
expect << EOF
set timeout 30
spawn ssh USER@IP
expect {
"(yes/no)" {send "yes\r"; exp_continue}
"password:" {send "PASS\r"} } expect "USER@" {send "1\r"} expect "USER@" {send "exit\r"}
expect eof
EOF
方法2:

!/bin/bash

USER=root
PASS=123.com
IP=192.168.1.120
expect -c "
spawn ssh USER@IP
expect {
"(yes/no)" {send "yes\r"; exp_continue}
"password:" {send "PASS\r\"; exp_continue} \"USER@*" {send "df -h\r exit\r"; exp_continue}
}"
方法3:將expect腳本獨(dú)立出來

登錄腳本:

cat login.exp

!/usr/bin/expect

set ip [lindex argv 0] set user [lindexargv 1]
set passwd [lindex argv 2] set cmd [lindexargv 3]
if { argc != 4 } { puts "Usage: expect login.exp ip user passwd" exit 1 } set timeout 30 spawn sshuser@ip expect { "(yes/no)" {send "yes\r"; exp_continue} "password:" {send "passwd\r"}
}
expect "user@*" {send "cmd\r"}
expect "$user@*" {send "exit\r"}
expect eof
執(zhí)行命令腳本:寫個(gè)循環(huán)可以批量操作多臺服務(wù)器

!/bin/bash

HOST_INFO=user_info.txt
for ip in (awk '{print1}' HOST_INFO) do user=(awk -v I="ip" 'I==1{print 2}'HOST_INFO)
pass=(awk -v I="ip" 'I==1{print3}' HOST_INFO) expect login.expip userpass $1
done
Linux主機(jī)SSH連接信息:

cat user_info.txt

192.168.1.120 root 123456
</pre>

28、批量修改服務(wù)器用戶密碼

<pre style="margin: 0px; padding: 0px; white-space: pre-wrap; overflow-wrap: break-word; color: rgb(51, 51, 51); font-size: 14px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); text-decoration-style: initial; text-decoration-color: initial;">Linux主機(jī)SSH連接信息:舊密碼

cat old_pass.txt

192.168.18.217 root 123456 22
192.168.18.218 root 123456 22
內(nèi)容格式:IP User Password Port

SSH遠(yuǎn)程修改密碼腳本:新密碼隨機(jī)生成
https://www.linuxprobe.com/books

!/bin/bash

OLD_INFO=old_pass.txt
NEW_INFO=new_pass.txt
for IP in (awk '/^[^#]/{print1}' OLD_INFO); do USER=(awk -v I=IP 'I==1{print 2}'OLD_INFO)
PASS=(awk -v I=IP 'I==1{print3}' OLD_INFO) PORT=(awk -v I=IP 'I==1{print 4}'OLD_INFO)
NEW_PASS=(mkpasswd -l 8) # 隨機(jī)密碼 echo "IP USERNEW_PASS PORT" >>NEW_INFO
expect -c "
spawn ssh -pPORTUSER@IP set timeout 2 expect { \"(yes/no)\" {send \"yes\r\";exp_continue} \"password:\" {send \"PASS\r";exp_continue}
"USER@*\" {send \"echo \'NEW_PASS' |passwd --stdin $USER\r exit\r";exp_continue}
}"
done
生成新密碼文件:

cat new_pass.txt

192.168.18.217 root n8wX3mU% 22
192.168.18.218 root c87;ZnnL 22
</pre>

29、打印乘法口訣

<pre style="margin: 0px; padding: 0px; white-space: pre-wrap; overflow-wrap: break-word; color: rgb(51, 51, 51); font-size: 14px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); text-decoration-style: initial; text-decoration-color: initial;">方法1:

awk 'BEGIN{for(n=0;n++<9;){for(i=0;i++<n;)printf i"x"n"="i*n" ";print ""}}'

方法2:

for ((i=1;i<=9;i++)); do
for ((j=1;j<=i;j++)); do
result=((ij)) echo -n "ji=result "
done
echo
done
</pre>

30、getopts工具完善腳本命令行參數(shù)

<pre style="margin: 0px; padding: 0px; white-space: pre-wrap; overflow-wrap: break-word; color: rgb(51, 51, 51); font-size: 14px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); text-decoration-style: initial; text-decoration-color: initial;">getopts是一個(gè)解析腳本選項(xiàng)參數(shù)的工具。

命令格式:getopts optstring name [arg]

初次使用你要注意這幾點(diǎn):

腳本位置參數(shù)會(huì)與optstring中的單個(gè)字母逐個(gè)匹配,如果匹配到就賦值給name,否則賦值name為問號;

optstring中單個(gè)字母是一個(gè)選項(xiàng),如果字母后面加冒號,表示該選項(xiàng)后面帶參數(shù),參數(shù)值并會(huì)賦值給OPTARG變量;

optstring中第一個(gè)是冒號,表示屏蔽系統(tǒng)錯(cuò)誤(test.sh: illegal option -- h);

允許把選項(xiàng)放一起,例如-ab

下面寫一個(gè)打印文件指定行的簡單例子,引導(dǎo)你思路:

!/bin/bash

while getopts :f:n: option; do
case option in f) FILE=OPTARG
[ ! -f FILE ] && echo "FILE File not exist!" && exit
;;
n)
sed -n "{OPTARG}p"FILE
;;
?)
echo "Usage: $0 -f -n "
echo "-f, --file specified file"
echo "-n, --line-number print specified line"
exit 1
;;
esac
done
</pre>

30個(gè)關(guān)于Shell腳本的經(jīng)典案例(下)30個(gè)關(guān)于Shell腳本的經(jīng)典案例(下)

根據(jù)工作經(jīng)驗(yàn)總結(jié)的30個(gè)Shell腳本案例至此完結(jié),都還是比較實(shí)用的,面試筆試題也經(jīng)常會(huì)出。希望朋友們多動(dòng)手練一練,讓你的Shell功底上升一個(gè)段位!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容