校園網(wǎng)站建設(shè)模板上海網(wǎng)站排名seo公司哪家好
先了解下編寫Shell過程中注意事項(xiàng)
- 開頭加解釋器:#!/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í)行過程。
- 寫腳本一定先測(cè)試再到生產(chǎn)上。
1、獲取隨機(jī)字符串或數(shù)字
獲取隨機(jī)8位字符串
方法1:
# echo $RANDOM |md5sum |cut -c 1-8
c9f36977
#這個(gè)命令使用$RANDOM變量生成一個(gè)隨機(jī)的整數(shù),然后將其經(jīng)過MD5哈希處理,并使用cut命令截取前8個(gè)字符作為生成的隨機(jī)字符串。
方法2:
# openssl rand -base64 4
f4C+pw==
#這個(gè)命令使用openssl命令生成一個(gè)長(zhǎng)度為4的隨機(jī)字節(jié)流
方法3:
# cat /proc/sys/kernel/random/uuid | cut -c 1-8
c1268803
#只是截取了 UUID 的前8個(gè)字符,并不是生成一個(gè)隨機(jī)的8位字符串
獲取隨機(jī)8位數(shù)字
方法1:
# echo $RANDOM | cksum |cut -c 1-8
55264714
#這個(gè)命令使用$RANDOM變量生成一個(gè)隨機(jī)的整數(shù),并通過cksum命令對(duì)其進(jìn)行校驗(yàn)和計(jì)算,然后使用cut命令截取校驗(yàn)和結(jié)果的前8個(gè)字符作為生成的隨機(jī)8位數(shù)字
方法2:
# openssl rand -base64 4 |cksum |cut -c 1-8
30318431
#這個(gè)命令使用openssl rand命令生成一個(gè)長(zhǎng)度為4的隨機(jī)字節(jié)流,并通過cksum命令對(duì)其進(jìn)行校驗(yàn)和計(jì)算,然后使用cut命令截取校驗(yàn)和結(jié)果的前8個(gè)字符作為生成的隨機(jī)8位數(shù)字
方法3:
# date +%N |cut -c 1-8
94705141
#這個(gè)命令使用date命令獲取當(dāng)前時(shí)間的納秒部分,并使用cut命令截取前8個(gè)字符作為生成的隨機(jī)8位數(shù)字
2、定義一個(gè)顏色輸出字符串函數(shù)
方法1:# 定義一個(gè)輸出帶顏色文本的函數(shù)
function echo_color() {# 判斷參數(shù)值是否為 "green"if [ $1 == "green" ]; then# 使用綠色的前景色輸出文本echo -e "\e[1;32m$2\e[0m"# 判斷參數(shù)值是否為 "red"elif [ $1 == "red" ]; then# 使用紅色的前景色輸出文本echo -e "\033[31m$2\033[0m"fi
}
方法2:# 定義一個(gè)輸出帶顏色文本的函數(shù)
function echo_color() {# 根據(jù)參數(shù)值進(jìn)行匹配case $1 in# 如果參數(shù)值為 "green"green)# 使用綠色的前景色輸出文本echo -e "\e[1;32m$2\e[0m";;# 如果參數(shù)值為 "red"red)# 使用紅色的前景色輸出文本echo -e "\033[31m$2\033[0m";;*) # 參數(shù)值不在以上兩種情況,則輸出提示信息echo "Example: echo_color red string"esac
}
echo_color green "This is a green text" #這行代碼會(huì)輸出綠色的文本 “This is a green text”。
echo_color red "This is a red text" #這行代碼會(huì)輸出紅色的文本 “This is a red text”。
3、批量創(chuàng)建用戶
#!/bin/bash
DATE=$(date +%F_%T) # 當(dāng)前日期和時(shí)間,用于備份文件的命名
USER_FILE=user.txt # 用戶文件名# 定義一個(gè)輸出帶顏色文本的函數(shù)
echo_color(){if [ $1 == "green" ]; thenecho -e "\e[1;32m$2\e[0m" # 輸出綠色文本elif [ $1 == "red" ]; thenecho -e "\033[31m$2\033[0m" # 輸出紅色文本fi
}# 如果用戶文件存在并且大小大于0就備份
if [ -s $USER_FILE ]; thenmv $USER_FILE ${USER_FILE}-${DATE}.bak # 備份用戶文件echo_color green "$USER_FILE exist, rename ${USER_FILE}-${DATE}.bak" # 輸出提示信息,綠色文本
fiecho -e "User\tPassword" >> $USER_FILE # 在用戶文件中添加表頭
echo "----------------" >> $USER_FILE # 在用戶文件中添加分隔線# 創(chuàng)建用戶,并記錄到用戶文件中
for USER in user{1..10}; doif ! id $USER &>/dev/null; thenPASS=$(echo $RANDOM |md5sum |cut -c 1-8) # 生成隨機(jī)密碼useradd $USER # 創(chuàng)建用戶echo $PASS |passwd --stdin $USER &>/dev/null # 設(shè)置用戶密碼echo -e "$USER\t$PASS" >> $USER_FILE # 在用戶文件中添加用戶名和密碼echo "$USER User create successful." # 輸出創(chuàng)建用戶成功的提示信息elseecho_color red "$USER User already exists!" # 輸出用戶已存在的提示信息,紅色文本fi
done
主要流程
- 獲取當(dāng)前日期和時(shí)間作為備份文件的命名。
- 定義了一個(gè)echo_color函數(shù),用于輸出帶顏色的文本。
- 如果用戶文件存在且文件大小大于0,則將用戶文件進(jìn)行備份,并輸出相應(yīng)提示信息(綠色文本)。
- 向用戶文件中添加表頭和分隔線。
- 使用循環(huán)創(chuàng)建10個(gè)用戶,并記錄到用戶文件中。
- 如果用戶不存在,則生成隨機(jī)密碼并創(chuàng)建用戶,并將用戶名和密碼記錄到用戶文件中,同時(shí)輸出創(chuàng)建用戶成功的提示信息。
- 如果用戶已經(jīng)存在,則輸出用戶已存在的提示信息(紅色文本)。
4、檢查軟件包是否安裝
#!/bin/bash# 檢查 sysstat 軟件包是否已安裝
if rpm -q sysstat &>/dev/null; thenecho "sysstat is already installed." # 輸出已安裝的提示信息
elseecho "sysstat is not installed!" # 輸出未安裝的提示信息
fi
- rpm -q sysstat命令用于查詢系統(tǒng)中sysstat軟件包的安裝情況
- &>/dev/null用于將標(biāo)準(zhǔn)輸出和標(biāo)準(zhǔn)錯(cuò)誤輸出重定向到空設(shè)備,即不顯示輸出信息
- 如果sysstat軟件包已安裝,則輸出"sysstat is already installed.",表示已經(jīng)存在且已安裝
- 如果sysstat軟件包未安裝,則輸出"sysstat is not installed!",表示尚未安裝
5、檢查服務(wù)狀態(tài)
#!/bin/bash# 使用 ss 命令查找所有 UDP 連接,并使用 grep 統(tǒng)計(jì)包含 "123" 字符串的個(gè)數(shù)
PORT_C=$(ss -anu | grep -c 123)# 使用 ps 命令查找所有 ntpd 進(jìn)程,并使用 grep 過濾掉 grep 進(jìn)程本身,再統(tǒng)計(jì)過濾后的行數(shù)
PS_C=$(ps -ef | grep ntpd | grep -vc grep)# 如果統(tǒng)計(jì)到的端口數(shù)為 0 或統(tǒng)計(jì)到的進(jìn)程數(shù)為 0,則執(zhí)行下面的操作
if [ $PORT_C -eq 0 -o $PS_C -eq 0 ]; then# 通過 echo 命令輸出郵件內(nèi)容,然后使用 mail 命令發(fā)送郵件給指定的郵箱echo "內(nèi)容" | mail -s "主題" dst@example.com
fi
- ss -anu命令用于查看系統(tǒng)中所有的UDP連接
- rep -c 123用于統(tǒng)計(jì)結(jié)果中包含"123"字符串的行數(shù)
- ps -ef命令用于查看系統(tǒng)中的所有進(jìn)程
- grep ntpd用于過濾出包含"ntpd"字符串的行
- grep -vc grep用于過濾掉包含"grep"字符串的行,并統(tǒng)計(jì)過濾后的行數(shù)
6、檢查主機(jī)存活狀態(tài)
方法1:將錯(cuò)誤IP放到數(shù)組里面判斷是否ping失敗三次
#!/bin/bashIP_LIST="192.168.18.1 192.168.1.1 192.168.18.2"# 循環(huán)處理 IP_LIST 中的每個(gè) IP 地址
for IP in $IP_LIST; doNUM=1 # 用于記錄當(dāng)前重試次數(shù)的變量# 使用 while 循環(huán),最多重試 3 次while [ $NUM -le 3 ]; do# 檢測(cè)指定 IP 地址是否可以通過 ping 命令連通if ping -c 1 $IP > /dev/null; thenecho "$IP Ping is successful." # 輸出提示信息,表示 Ping 成功break # 跳出當(dāng)前循環(huán),繼續(xù)處理下一個(gè) IP 地址else# 如果 ping 失敗,記錄失敗次數(shù)和相應(yīng)的 IP 地址FAIL_COUNT[$NUM]=$IPlet NUM++fidone# 如果連續(xù)失敗次數(shù)達(dá)到 3 次,則輸出錯(cuò)誤信息并清空 FAIL_COUNT 數(shù)組if [ ${#FAIL_COUNT[*]} -eq 3 ];thenecho "${FAIL_COUNT[1]} Ping is failure!" # 輸出提示信息,表示 Ping 失敗unset FAIL_COUNT[*] # 清空 FAIL_COUNT 數(shù)組的內(nèi)容fi
done
- IP_LIST 字符串包含要檢測(cè)的多個(gè) IP 地址。
- 使用 for 循環(huán)遍歷每個(gè) IP 地址。
- NUM 變量記錄每個(gè) IP 地址的重試次數(shù)。
代碼的功能: - 對(duì)于 IP_LIST 中的每個(gè) IP 地址
- 使用 while 循環(huán)嘗試最多 3 次進(jìn)行 ping 命令檢測(cè)。
- 如果 ping 成功,則輸出提示信息表示 Ping 成功,并跳出循環(huán)繼續(xù)處理下一個(gè) IP 地址。
- 如果 ping 失敗,則記錄失敗次數(shù)和相應(yīng)的 IP 地址。
- 如果連續(xù)失敗次數(shù)達(dá)到 3 次,則輸出錯(cuò)誤信息并清空 FAIL_COUNT 數(shù)組。
方法2:將錯(cuò)誤次數(shù)放到FAIL_COUNT變量里面判斷是否ping失敗三次
#!/bin/bashIP_LIST="192.168.18.1 192.168.1.1 192.168.18.2"# 循環(huán)處理 IP_LIST 中的每個(gè) IP 地址
for IP in $IP_LIST; doFAIL_COUNT=0 # 用于記錄失敗次數(shù)的變量# 使用 for 循環(huán)嘗試最多 3 次 ping 命令for ((i=1;i<=3;i++)); do# 檢測(cè)指定 IP 地址是否可以通過 ping 命令連通if ping -c 1 $IP >/dev/null; thenecho "$IP Ping is successful." # 輸出提示信息,表示 Ping 成功break # 跳出當(dāng)前循環(huán),繼續(xù)處理下一個(gè) IP 地址elselet FAIL_COUNT++ # 失敗次數(shù)加 1fidone# 如果連續(xù)失敗次數(shù)達(dá)到 3 次,則輸出錯(cuò)誤信息if [ $FAIL_COUNT -eq 3 ]; thenecho "$IP Ping is failure!" # 輸出提示信息,表示 Ping 失敗fi
done
- IP_LIST 字符串包含要檢測(cè)的多個(gè) IP 地址。
- 使用 for 循環(huán)遍歷每個(gè) IP 地址。
- FAIL_COUNT 變量用于記錄每個(gè) IP 地址的失敗次數(shù)。
代碼的功能: - 對(duì)于 IP_LIST 中的每個(gè) IP 地址
- 使用 for 循環(huán)嘗試最多 3 次 ping 命令檢測(cè)。
- 如果 ping 成功,則輸出提示信息表示 Ping 成功,并跳出循環(huán)繼續(xù)處理下一個(gè) IP 地址。
- 如果 ping 失敗,則增加失敗次數(shù)。
- 如果連續(xù)失敗次數(shù)達(dá)到 3 次,則輸出錯(cuò)誤信息表示 Ping 失敗。
方法3:利用for循環(huán)將ping通就跳出循環(huán)繼續(xù),如果不跳出就會(huì)走到打印ping失敗
#!/bin/bash# 定義函數(shù)用于檢測(cè) Ping 狀態(tài)并輸出結(jié)果
ping_success_status() {if ping -c 1 $IP >/dev/null; thenecho "$IP Ping is successful." # 輸出提示信息,表示 Ping 成功continue # 繼續(xù)循環(huán)處理下一個(gè) IP 地址fi
}IP_LIST="192.168.18.1 192.168.1.1 192.168.18.2"# 循環(huán)處理 IP_LIST 中的每個(gè) IP 地址
for IP in $IP_LIST; doping_success_statusping_success_statusping_success_statusecho "$IP Ping is failure!" # 輸出提示信息,表示 Ping 失敗
done
-
ping_success_status() 函數(shù)用于檢測(cè)指定IP地址的Ping狀態(tài)并輸出結(jié)果。
-
IP_LIST 字符串包含要檢測(cè)的多個(gè) IP 地址。
-
使用 for 循環(huán)遍歷每個(gè) IP 地址,對(duì)每個(gè) IP 地址調(diào)用 ping_success_status() 函數(shù)進(jìn)行 Ping 測(cè)試。
代碼的功能: -
定義了一個(gè)名為 ping_success_status 的函數(shù)用于檢測(cè) Ping 狀態(tài)并輸出結(jié)果。
-
對(duì)于 IP_LIST 中的每個(gè) IP 地址
- 分別調(diào)用 ping_success_status() 函數(shù)三次,進(jìn)行 Ping 測(cè)試。
- 如果三次中有任意一次 Ping 成功,則輸出提示信息表示 Ping 成功,并繼續(xù)處理下一個(gè) IP 地址。
- 如果三次都 Ping 失敗,則輸出提示信息表示 Ping 失敗。
7、監(jiān)控CPU、內(nèi)存利用率
1)CPU
借助vmstat工具來分析CPU統(tǒng)計(jì)信息。
#!/bin/bashDATE=$(date +%F" "%H:%M) # 獲取當(dāng)前日期和時(shí)間
IP=$(ifconfig eth0 | awk -F"[ :]+" '/inet addr/{print $4}') # 獲取 eth0 網(wǎng)卡的 IP 地址(在 CentOS 6 中)
MAIL="example@mail.com"# 檢查系統(tǒng)是否安裝了 vmstat 命令,如果沒有找到,則輸出錯(cuò)誤信息并退出腳本
if ! which vmstat &>/dev/null; thenecho "vmstat command not found. Please install the procps package."exit 1
fi# 使用 vmstat 命令獲取 CPU 相關(guān)的統(tǒng)計(jì)數(shù)據(jù)
US=$(vmstat 1 3 | awk 'NR==5{print $13}') # 用戶CPU時(shí)間占用百分比
SY=$(vmstat 1 3 | awk 'NR==5{print $14}') # 系統(tǒng)CPU時(shí)間占用百分比
IDLE=$(vmstat 1 3 | awk 'NR==5{print $15}') # 空閑CPU時(shí)間百分比
WAIT=$(vmstat 1 3 | awk 'NR==5{print $16}') # IO等待百分比USE=$(($US+$SY)) # 計(jì)算用戶CPU時(shí)間占用和系統(tǒng)CPU時(shí)間占用的總和# 檢查 CPU 使用率是否超過閾值(80%),如果超過則發(fā)送電子郵件通知
if [ $USE -ge 80 ]; thenecho "Date: $DATEHost: $IPProblem: CPU utilization $USE" | mail -s "CPU Monitor" $MAIL
fi
代碼的功能:
- 聲明并初始化了 DATE 變量,用于存儲(chǔ)當(dāng)前的日期和時(shí)間。
- 使用 ifconfig 命令獲取 eth0 網(wǎng)卡的 IP 地址(在 CentOS 6 中)。
- 設(shè)置郵件接收地址 MAIL。
- 檢查系統(tǒng)是否安裝了 vmstat 命令,如果沒有找到,則輸出錯(cuò)誤信息并退出腳本。、使用 vmstat 命令獲取 CPU 相關(guān)的統(tǒng)計(jì)數(shù)據(jù),包括用戶 CPU 時(shí)間占用、系統(tǒng) CPU 時(shí)間占用、空閑 CPU 時(shí)間和 IO 等待時(shí)間。
- 計(jì)算用戶 CPU 時(shí)間占用和系統(tǒng) CPU 時(shí)間占用的總和,并存儲(chǔ)在 USE 變量中。
- 檢查 CPU 使用率是否超過閾值(80%),如果超過,則發(fā)送電子郵件通知,包括日期、主機(jī)名和問題描述。
2)內(nèi)存
#!/bin/bashDATE=$(date +%F" "%H:%M) # 獲取當(dāng)前日期和時(shí)間
IP=$(ifconfig eth0 | awk -F"[ :]+" '/inet addr/{print $4}') # 獲取 eth0 網(wǎng)卡的 IP 地址(在 CentOS 6 中)
MAIL="example@mail.com"# 使用 free 命令獲取內(nèi)存相關(guān)的統(tǒng)計(jì)數(shù)據(jù)
TOTAL=$(free -m | awk '/Mem/{print $2}') # 內(nèi)存總量
USE=$(free -m | awk '/Mem/{print $3-$6-$7}') # 已使用的內(nèi)存量
FREE=$(($TOTAL-$USE)) # 剩余內(nèi)存量# 如果剩余內(nèi)存小于 1G,則發(fā)送電子郵件通知
if [ $FREE -lt 1024 ]; thenecho "Date: $DATEHost: $IPProblem: Total=$TOTAL, Use=$USE, Free=$FREE" | mail -s "Memory Monitor" $MAIL
fi
代碼的功能:
- 聲明并初始化了 DATE 變量,用于存儲(chǔ)當(dāng)前的日期和時(shí)間。
- 使用 ifconfig 命令獲取 eth0 網(wǎng)卡的 IP 地址(在 CentOS 6 中)。
- 設(shè)置郵件接收地址 MAIL。
- 使用 free 命令獲取內(nèi)存相關(guān)的統(tǒng)計(jì)數(shù)據(jù),包括內(nèi)存總量、已使用的內(nèi)存量和剩余的內(nèi)存量。
- 計(jì)算剩余內(nèi)存量(Total - Use)并存儲(chǔ)在 FREE 變量中。
- 檢查剩余內(nèi)存量是否小于 1G(1024MB),如果小于則發(fā)送電子郵件通知,包括日期、主機(jī)名和問題描述。
8、批量主機(jī)磁盤利用率監(jiān)控
前提監(jiān)控端和被監(jiān)控端SSH免交互登錄或者密鑰登錄。
寫一個(gè)配置文件保存被監(jiān)控主機(jī)SSH連接信息,文件內(nèi)容格式:IP User Port
#!/bin/bashHOST_INFO=host.info # 主機(jī)信息保存的文件路徑
rm -f mail.txt # 刪除已存在的郵件內(nèi)容文件# 遍歷主機(jī)信息文件中的每個(gè) IP 地址
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 # 臨時(shí)文件路徑,用于保存磁盤信息# 通過公鑰登錄到遠(yuǎn)程主機(jī),獲取磁盤信息,并保存到臨時(shí)文件中ssh -p $PORT $USER@$IP 'df -h' > $TMP_FILE# 從臨時(shí)文件中提取磁盤利用率信息,并保存到變量 USE_RATE_LIST 中USE_RATE_LIST=$(awk 'BEGIN{OFS="="}/^\/dev/{print $NF,int($5)}' $TMP_FILE)# 對(duì)磁盤利用率進(jìn)行循環(huán)判斷for USE_RATE in $USE_RATE_LIST; doPART_NAME=${USE_RATE%=*} # 獲取掛載點(diǎn)部分,即等號(hào)(=)左邊的值USE_RATE=${USE_RATE#*=} # 獲取磁盤利用率部分,即等號(hào)(=)右邊的值# 判斷磁盤利用率是否超過閾值(80%),如果超過則將警告信息添加到郵件內(nèi)容文件中if [ $USE_RATE -ge 80 ]; thenecho "Warning: $PART_NAME Partition usage $USE_RATE%!" >> mail.txtelseecho "服務(wù)器$IP的$PART_NAME目錄空間良好"fidone# 發(fā)送郵件,將郵件內(nèi)容文件作為內(nèi)容,郵件主題為 "空間不足警告"cat mail.txt | mail -s "空間不足警告" xiaobai@cdeledu.com
done
代碼的功能:
- 定義 HOST_INFO 變量,表示保存主機(jī)信息的文件路徑。
- 刪除已存在的郵件內(nèi)容文件 mail.txt。
- 使用 awk 從主機(jī)信息文件中提取非注釋行的 IP 地址,并依次處理每個(gè) IP。
- 從主機(jī)信息文件中獲取用戶名和端口信息。
- 定義臨時(shí)文件路徑 TMP_FILE,用于保存遠(yuǎn)程主機(jī)的磁盤信息。
- 使用 ssh 命令通過公鑰登錄到遠(yuǎn)程主機(jī),在遠(yuǎn)程主機(jī)上執(zhí)行 df -h 命令,并將輸出重定向到臨時(shí)文件中。
- 從臨時(shí)文件中提取磁盤利用率信息,并保存到 USE_RATE_LIST 變量中。
- 使用循環(huán)遍歷磁盤利用率列表,并進(jìn)行判斷。
- 獲取掛載點(diǎn)部分和磁盤利用率部分。
- 如果磁盤利用率超過閾值(80%),將警告信息添加到郵件內(nèi)容文件 mail.txt 中。
- 如果磁盤利用率未超過閾值,則輸出相應(yīng)信息表示磁盤空間良好。
- 使用 cat 命令將郵件內(nèi)容文件作為郵件內(nèi)容,向 xiaobai@cdeledu.com 發(fā)送郵件,郵件主題為 “空間不足警告”。
9、檢查網(wǎng)站可用性
1)檢查URL可用性
# 方法1:使用 curl 命令檢查 URL 的訪問狀態(tài)
check_url() {HTTP_CODE=$(curl -o /dev/null --connect-timeout 3 -s -w "%{http_code}" $1)# 使用 curl 命令測(cè)試 HTTP 頭以檢查 URL 的訪問狀態(tài),超時(shí)時(shí)間為 3 秒,并將 HTTP 狀態(tài)碼保存到變量 HTTP_CODE 中if [ $HTTP_CODE -ne 200 ]; thenecho "Warning: $1 Access failure!"# 如果 HTTP 狀態(tài)碼不等于 200(即不成功),則輸出警告信息,表示 URL 訪問失敗fi
}# 方法2:使用 wget 命令檢查 URL 的訪問狀態(tài)
check_url() {if ! wget -T 10 --tries=1 --spider $1 >/dev/null 2>&1; then # 使用 wget 命令以爬蟲模式檢查 URL 的訪問狀態(tài),超時(shí)時(shí)間為 10 秒,并嘗試訪問 1 次,將輸出重定向到 /dev/null,將錯(cuò)誤輸出重定向到標(biāo)準(zhǔn)輸出并丟棄echo "Warning: $1 Access failure!"# 如果 wget 命令返回非零退出碼,則輸出警告信息,表示 URL 訪問失敗fi
}
代碼的功能:
- 方法1:使用 curl 命令。通過設(shè)置選項(xiàng) -o /dev/null,–connect-timeout 3,-s 和 -w “%{http_code}”,來測(cè)試 HTTP 頭,并將 HTTP 狀態(tài)碼保存到變量 HTTP_CODE 中。然后,檢查 HTTP 狀態(tài)碼是否等于 200,如果不等于,則輸出警告信息,表示 URL 訪問失敗。
- 方法2:使用 wget 命令。通過設(shè)置選項(xiàng) -T 10,–tries=1 和 --spider,以爬蟲模式測(cè)試URL的訪問狀態(tài),并設(shè)置超時(shí)時(shí)間為10秒,嘗試訪問1次。使用重定向?qū)⑤敵龊湾e(cuò)誤信息都丟棄。然后,檢查 wget 命令的返回值,如果返回非零退出碼,則輸出警告信息,表示 URL 訪問失敗。
2)判斷三次URL可用性
方法1:利用循環(huán)技巧,如果成功就跳出當(dāng)前循環(huán),否則執(zhí)行到最后一行
#!/bin/bash# 檢查URL的訪問狀態(tài)
check_url() {HTTP_CODE=$(curl -o /dev/null --connect-timeout 3 -s -w "%{http_code}" $1)# 使用 curl 命令測(cè)試 HTTP 頭以檢查 URL 的訪問狀態(tài),超時(shí)時(shí)間為 3 秒,并將 HTTP 狀態(tài)碼保存到變量 HTTP_CODE 中if [ $HTTP_CODE -eq 200 ]; thencontinue# 如果 HTTP 狀態(tài)碼等于 200(即成功),則繼續(xù)循環(huán),不執(zhí)行后續(xù)操作fi
}URL_LIST="www.baidu.com www.agasgf.com"
# 存儲(chǔ)待檢查的 URL 列表for URL in $URL_LIST; docheck_url $URL# 依次遍歷 URL 列表,調(diào)用 check_url 函數(shù)檢查每個(gè) URL 的訪問狀態(tài)# 如果返回的 HTTP 狀態(tài)碼等于 200,則繼續(xù)循環(huán),不執(zhí)行后續(xù)操作check_url $URLcheck_url $URL# 連續(xù)調(diào)用 check_url 函數(shù),最多嘗試三次echo "Warning: $URL Access failure!"# 輸出警告信息,表示 URL 訪問失敗
done
代碼的功能:
- 定義了函數(shù) check_url(),用于檢查 URL 的訪問狀態(tài)。通過設(shè)置選項(xiàng) -o /dev/null,–connect-timeout 3,-s 和 -w “%{http_code}”,使用 curl 命令測(cè)試 HTTP 頭,并將返回的 HTTP 狀態(tài)碼保存到變量 HTTP_CODE 中。
- 在函數(shù)中,如果返回的 HTTP 狀態(tài)碼等于 200,那么繼續(xù)循環(huán),不執(zhí)行后續(xù)操作。
- 定義了一個(gè)字符串變量 URL_LIST,用于存儲(chǔ)待檢查的 URL 列表。
- 使用 for 循環(huán)遍歷 URL_LIST 中的每個(gè) URL,依次調(diào)用 check_url 函數(shù)來檢查 URL 的訪問狀態(tài)。
- 在每次循環(huán)中,連續(xù)調(diào)用 check_url 函數(shù),最多嘗試三次。
- 如果訪問失敗(即返回的 HTTP 狀態(tài)碼不等于 200),則輸出警告信息,表示 URL 訪問失敗。
方法2:錯(cuò)誤次數(shù)保存到變量
#!/bin/bashURL_LIST="www.baidu.com www.agasgf.com"
# 存儲(chǔ)待檢查的 URL 列表for URL in $URL_LIST; doFAIL_COUNT=0# 用于統(tǒng)計(jì) URL 訪問失敗的次數(shù)的變量for ((i=1;i<=3;i++)); do# 進(jìn)行最多三次的訪問嘗試HTTP_CODE=$(curl -o /dev/null --connect-timeout 3 -s -w "%{http_code}" $URL)# 使用 curl 命令測(cè)試 HTTP 頭以檢查 URL 的訪問狀態(tài),超時(shí)時(shí)間為 3 秒,并將 HTTP 狀態(tài)碼保存到變量 HTTP_CODE 中if [ $HTTP_CODE -ne 200 ]; thenlet FAIL_COUNT++# 如果 HTTP 狀態(tài)碼不等于 200(即訪問失敗),則將失敗次數(shù)加一elsebreak# 如果 HTTP 狀態(tài)碼等于 200(即訪問成功),則跳出循環(huán),不執(zhí)行后續(xù)嘗試fidoneif [ $FAIL_COUNT -eq 3 ]; thenecho "Warning: $URL Access failure!"# 如果 URL 訪問失敗的次數(shù)等于 3,即嘗試了三次都失敗,則輸出警告信息,表示 URL 訪問失敗fi
done
代碼的功能:
- 定義了一個(gè)字符串變量 URL_LIST,用于存儲(chǔ)待檢查的 URL 列表。
- 使用 for 循環(huán)遍歷 URL_LIST 中的每個(gè) URL。
- 在每次循環(huán)中,初始化變量 FAIL_COUNT 為 0,用于統(tǒng)計(jì) URL 訪問失敗的次數(shù)。
- 使用 for 循環(huán)進(jìn)行最多三次的訪問嘗試。
- 在每次嘗試中,使用 curl 命令測(cè)試 URL 的 HTTP 頭,超時(shí)時(shí)間為 3 秒,并將返回的 HTTP 狀態(tài)碼保存到變量 HTTP_CODE 中
- 如果 HTTP 狀態(tài)碼不等于 200(即訪問失敗),則將 FAIL_COUNT 的值加一。
- 如果 HTTP 狀態(tài)碼等于 200(即訪問成功),則跳出循環(huán),不執(zhí)行后續(xù)嘗試。
- 在完成三次訪問嘗試后,如果失敗次數(shù)等于 3,則輸出警告信息,表示 URL 訪問失敗。
方法3:錯(cuò)誤次數(shù)保存到數(shù)組
#!/bin/bashURL_LIST="www.baidu.com www.agasgf.com"
# 存儲(chǔ)待檢查的 URL 列表for URL in $URL_LIST; doNUM=1# 用于計(jì)數(shù)的變量 NUM,初始值為 1while [ $NUM -le 3 ]; do# 進(jìn)行最多三次的訪問嘗試HTTP_CODE=$(curl -o /dev/null --connect-timeout 3 -s -w "%{http_code}" $URL)# 使用 curl 命令測(cè)試 HTTP 頭以檢查 URL 的訪問狀態(tài),超時(shí)時(shí)間為 3 秒,并將 HTTP 狀態(tài)碼保存到變量 HTTP_CODE 中if [ $HTTP_CODE -ne 200 ]; thenFAIL_COUNT[$NUM]=$IP# 如果 HTTP 狀態(tài)碼不等于 200(即訪問失敗),則將失敗的 URL 存儲(chǔ)到數(shù)組 FAIL_COUNT 中,以 NUM 作為下標(biāo),IP 作為元素let NUM++# 數(shù)量加一,進(jìn)行下一次嘗試elsebreak# 如果 HTTP 狀態(tài)碼等于 200(即訪問成功),則跳出循環(huán),不再進(jìn)行嘗試fidoneif [ ${#FAIL_COUNT[*]} -eq 3 ]; thenecho "Warning: $URL Access failure!"unset FAIL_COUNT[*]# 如果 FAIL_COUNT 數(shù)組中有三個(gè)元素,即進(jìn)行了三次嘗試都失敗,則輸出警告信息,表示 URL 訪問失敗,并清空 FAIL_COUNT 數(shù)組fi
done
代碼的功能:
- 定義了一個(gè)字符串變量 URL_LIST,用于存儲(chǔ)待檢查的 URL 列表。
- 使用 for 循環(huán)遍歷 URL_LIST 中的每個(gè) URL。
- 在每次循環(huán)中,初始化變量 NUM 為 1,用于計(jì)數(shù)訪問嘗試的次數(shù)。
- 使用 while 循環(huán)進(jìn)行最多三次的訪問嘗試。
- 在每次嘗試中,使用 curl 命令測(cè)試 URL 的 HTTP 頭,超時(shí)時(shí)間為 3 秒,并將返回的 HTTP 狀態(tài)碼保存到變量 HTTP_CODE 中。
- 如果 HTTP 狀態(tài)碼不等于 200(即訪問失敗),則將失敗的 URL 存儲(chǔ)到 FAIL_COUNT 數(shù)組中,以 NUM 作為下標(biāo),IP 作為元素。然后,NUM 加一,進(jìn)行下一次嘗試。
- 如果 HTTP 狀態(tài)碼等于 200(即訪問成功),則跳出循環(huán),不再進(jìn)行嘗試。
使用 for 循環(huán)遍歷 URL_LIST 中的每個(gè) URL。 - 在完成三次訪問嘗試后,如果 FAIL_COUNT 數(shù)組中有三個(gè)元素(即進(jìn)行了三次嘗試都失敗),則輸出警告信息,表示 URL 訪問失敗,并清空 FAIL_COUNT 數(shù)組。
10、檢查MySQL主從同步狀態(tài)
#!/bin/bashUSER=bak
PASSWD=123456IO_SQL_STATUS=$(mysql -u$USER -p$PASSWD -e show slave statusG | awk -F: /Slave_.*_Running/{gsub(": ",":");print $0})
# 執(zhí)行 mysql 命令獲取 MySQL 主從狀態(tài),并使用 awk 命令根據(jù)關(guān)鍵字 "Slave_.*_Running" 解析出對(duì)應(yīng)的行,并去除冒號(hào)后的空格for i in $IO_SQL_STATUS; doTHREAD_STATUS_NAME=${i%:*}# 通過 %:* 取 THREAD_STATUS_NAME 字符串變量,獲取冒號(hào)前的部分THREAD_STATUS=${i#*:}# 通過 #*: 取 THREAD_STATUS 字符串變量,獲取冒號(hào)后的部分if [ "$THREAD_STATUS" != "Yes" ]; thenecho "Error: MySQL Master-Slave $THREAD_STATUS_NAME status is $THREAD_STATUS!"# 如果 THREAD_STATUS 不等于 "Yes",則輸出錯(cuò)誤信息,表示 MySQL 主從狀態(tài)異常fi
done
代碼的功能:
- 定義了字符串變量 USER 和 PASSWD,分別存儲(chǔ)登錄 MySQL 的用戶名和密碼。
- 使用 mysql 命令執(zhí)行查詢語句 show slave statusG,獲取 MySQL 主從復(fù)制的狀態(tài)。-u$ USER 指定用戶名,-p$PASSWD 指定密碼,-e 后面跟查詢語句,G 匹配 show slave status 的輸出格式。
- 使用 awk 命令根據(jù)關(guān)鍵字 “Slave_.*_Running” 解析出對(duì)應(yīng)的行,并去除冒號(hào)后的空格。
- 使用 for 循環(huán)遍歷 $IO_SQL_STATUS 中的每個(gè)值。
- 在每次循環(huán)中,通過 %:* 取出冒號(hào)前的部分,賦值給 THREAD_STATUS_NAME 變量。
- 通過 #*: 取出冒號(hào)后的部分,賦值給 THREAD_STATUS 變量。
- 如果 THREAD_STATUS 不等于 “Yes”,則輸出錯(cuò)誤信息,表示 MySQL 主從狀態(tài)異常。
11、iptables自動(dòng)屏蔽訪問網(wǎng)站頻繁的IP
場(chǎng)景:惡意訪問,安全防范
1)屏蔽每分鐘訪問超過200的IP
方法1:根據(jù)訪問日志(Nginx為例)
#!/bin/bashDATE=$(date +%d/%b/%Y:%H:%M)
# 獲取當(dāng)前日期和時(shí)間,并格式化為 "%d/%b/%Y:%H:%M" 的形式,賦值給變量 DATEABNORMAL_IP=$(tail -n 5000 access.log | grep $DATE | awk '{a[$1]++}END{for(key in a)if(a[key]>100)print key}')
# 使用 tail 命令讀取文件 access.log 的最后 5000 行日志,然后通過 grep 過濾出包含當(dāng)前日期的行,最后使用 awk 命令統(tǒng)計(jì) IP 地址出現(xiàn)的次數(shù),如果次數(shù)大于 100,則將 IP 地址打印出來,賦值給變量 ABNORMAL_IPfor IP in $ABNORMAL_IP; do# 使用 for 循環(huán)遍歷 ABNORMAL_IP 中的每個(gè) IP 地址if [ $(iptables -vnL |grep -c "$IP") -eq 0 ]; then# 使用 iptables 命令查看當(dāng)前防火墻規(guī)則,并使用 grep 過濾出包含指定 IP 地址的行,并使用 -c 參數(shù)統(tǒng)計(jì)匹配行的數(shù)量# 如果匹配行的數(shù)量等于 0,表示當(dāng)前 IP 地址不在防火墻規(guī)則中iptables -I INPUT -s $IP -j DROP# 在 INPUT 鏈的開頭插入一條規(guī)則,拒絕指定 IP 地址的所有輸入流量fi
done
這段代碼的功能是根據(jù) access.log 中的日志數(shù)據(jù),檢測(cè)發(fā)起請(qǐng)求次數(shù)超過設(shè)定閾值的 IP 地址,并將這些 IP 地址加入防火墻規(guī)則,拒絕其輸入流量。
代碼的功能:
- 定義了字符串變量 DATE,使用 date 命令獲取當(dāng)前日期和時(shí)間,并使用 %d/%b/%Y:%H:%M 格式化。
- 使用 tail 命令讀取文件 access.log 的最后 5000 行日志。
- 使用 grep 過濾出包含當(dāng)前日期的行。
- 使用 awk 命令統(tǒng)計(jì) IP 地址出現(xiàn)的次數(shù),將出現(xiàn)次數(shù)大于 100 的 IP 地址打印出來,賦值給變量 ABNORMAL_IP。
- 使用 for 循環(huán)遍歷 ABNORMAL_IP 中的每個(gè) IP 地址。
- 使用 iptables 命令查看當(dāng)前防火墻規(guī)則,使用 grep 過濾出包含指定 IP 地址的行,并使用 -c 參數(shù)統(tǒng)計(jì)匹配行的數(shù)量。
- 如果匹配行的數(shù)量等于 0,表示當(dāng)前 IP 地址不在防火墻規(guī)則中。
- 使用 iptables 命令在 INPUT 鏈的開頭插入一條規(guī)則,拒絕指定 IP 地址的所有輸入流量。
方法2:通過TCP建立的連接
#!/bin/bashABNORMAL_IP=$(netstat -an | awk '$4~/:80$/ && $6~/ESTABLISHED/{gsub(/:[0-9]+/,"",$5);{a[$5]++}}END{for(key in a)if(a[key]>100)print key}')
# 使用 netstat 命令獲取網(wǎng)絡(luò)連接狀態(tài),通過 awk 過濾出本地端口為 80 的已建立連接(ESTABLISHED)的行,并使用 gsub 函數(shù)去除客戶端 IP 地址中的冒號(hào)和端口號(hào),然后統(tǒng)計(jì)每個(gè) IP 地址的出現(xiàn)次數(shù),如果次數(shù)大于 100,則將 IP 地址打印出來,賦值給變量 ABNORMAL_IPfor IP in $ABNORMAL_IP; do# 使用 for 循環(huán)遍歷 ABNORMAL_IP 中的每個(gè) IP 地址if [ $(iptables -vnL |grep -c "$IP") -eq 0 ]; then# 使用 iptables 命令查看當(dāng)前防火墻規(guī)則,并使用 grep 過濾出包含指定 IP 地址的行,并使用 -c 參數(shù)統(tǒng)計(jì)匹配行的數(shù)量# 如果匹配行的數(shù)量等于 0,表示當(dāng)前 IP 地址不在防火墻規(guī)則中iptables -I INPUT -s $IP -j DROP# 在 INPUT 鏈的開頭插入一條規(guī)則,拒絕指定 IP 地址的所有輸入流量fi
done
這段代碼的功能是通過 netstat 命令檢測(cè)當(dāng)前與本地端口 80 建立的連接,并統(tǒng)計(jì)每個(gè)客戶端 IP 地址的連接次數(shù),如果連接次數(shù)超過設(shè)定閾值,就將對(duì)應(yīng) IP 地址加入防火墻規(guī)則。
代碼的功能:
- 使用 netstat 命令獲取當(dāng)前的網(wǎng)絡(luò)連接狀態(tài)。
- 使用 awk 過濾出本地端口為 80 的已建立連接(ESTABLISHED)的行,并使用 gsub 函數(shù)將客戶端 IP 地址中的冒號(hào)和端口號(hào)去除。
- 統(tǒng)計(jì)每個(gè) IP 地址的出現(xiàn)次數(shù),如果次數(shù)大于 100,則將 IP 地址打印出來,賦值給變量 ABNORMAL_IP。
- 使用 for 循環(huán)遍歷 ABNORMAL_IP 中的每個(gè) IP 地址。
- 使用 iptables 命令查看當(dāng)前防火墻規(guī)則,使用 grep 過濾出包含指定 IP 地址的行,并使用 -c 參數(shù)統(tǒng)計(jì)匹配行的數(shù)量。
- 如果匹配行的數(shù)量等于 0,表示當(dāng)前 IP 地址不在防火墻規(guī)則中。
- 使用 iptables 命令在 INPUT 鏈的開頭插入一條規(guī)則,拒絕指定 IP 地址的所有輸入流量。
2)屏蔽每分鐘SSH嘗試登錄超過10次的IP
方法1:通過lastb獲取登錄狀態(tài)
#!/bin/bashDATE=$(date +"%a %b %e %H:%M")
# 獲取當(dāng)前日期和時(shí)間,并使用格式化字符串 "%a %b %e %H:%M" 賦值給變量 DATE
# %a: 星期幾的縮寫(例如:Mon、Tue)
# %b: 月份的縮寫(例如:Jan、Feb)
# %e: 月份中的天數(shù)(僅用一個(gè)數(shù)字表示,如:7)
# %H: 小時(shí)(24小時(shí)制)
# %M: 分鐘ABNORMAL_IP=$(lastb | grep "$DATE" | awk '{a[$3]++}END{for(key in a)if(a[key]>10)print key}')
# 使用 lastb 命令獲取登錄失敗的記錄,通過 grep 過濾出包含當(dāng)前日期的行,然后使用 awk 命令統(tǒng)計(jì)每個(gè) IP 地址出現(xiàn)的次數(shù),如果次數(shù)大于 10,則將 IP 地址打印出來,賦值給變量 ABNORMAL_IPfor IP in $ABNORMAL_IP; do# 使用 for 循環(huán)遍歷 ABNORMAL_IP 中的每個(gè) IP 地址if [ $(iptables -vnL | grep -c "$IP") -eq 0 ]; then# 使用 iptables 命令查看當(dāng)前防火墻規(guī)則,并使用 grep 過濾出包含指定 IP 地址的行,并使用 -c 參數(shù)統(tǒng)計(jì)匹配行的數(shù)量# 如果匹配行的數(shù)量等于 0,表示當(dāng)前 IP 地址不在防火墻規(guī)則中iptables -I INPUT -s $IP -j DROP# 在 INPUT 鏈的開頭插入一條規(guī)則,拒絕指定 IP 地址的所有輸入流量fi
done
這段代碼的功能是檢測(cè)最近登錄失敗的記錄(使用 lastb 命令),并統(tǒng)計(jì)每個(gè) IP 地址的登錄失敗次數(shù)。如果登錄失敗次數(shù)超過設(shè)定閾值,就將對(duì)應(yīng) IP 地址加入防火墻規(guī)則,禁止其輸入流量。
代碼的功能:
- 使用 date 命令獲取當(dāng)前日期和時(shí)間,并使用格式化字符串 “%a %b %e %H:%M” 格式化成星期幾、月份、日期、小時(shí)和分鐘的形式,賦值給變量 DATE。
- 使用 lastb 命令獲取登錄失敗的記錄。
- 使用 grep 過濾出包含當(dāng)前日期的行。
- 使用 awk 命令統(tǒng)計(jì)每個(gè) IP 地址出現(xiàn)的次數(shù),如果次數(shù)大于 10,則將 IP 地址打印出來,賦值給變量 ABNORMAL_IP。
- 使用 for 循環(huán)遍歷 ABNORMAL_IP 中的每個(gè) IP 地址。
- 使用 iptables 命令查看當(dāng)前防火墻規(guī)則,使用 grep 過濾出包含指定 IP 地址的行,并使用 -c 參數(shù)統(tǒng)計(jì)匹配行的數(shù)量。
- 如果匹配行的數(shù)量等于 0,表示當(dāng)前 IP 地址不在防火墻規(guī)則中。
- 使用 iptables 命令在 INPUT 鏈的開頭插入一條規(guī)則,拒絕指定 IP 地址的所有輸入流量。
方法2:通過日志獲取登錄狀態(tài)
#!/bin/bashDATE=$(date +"%b %d %H")
# 獲取當(dāng)前日期和時(shí)間,并使用格式化字符串 "%b %d %H" 格式化成月份、日期、小時(shí)的形式,賦值給變量 DATE
# %b: 月份的縮寫(例如:Jan、Feb)
# %d: 月份中的天數(shù)(例如:07)
# %H: 小時(shí)(24小時(shí)制)ABNORMAL_IP="$(tail -n10000 /var/log/auth.log | grep "$DATE" | awk '/Failed/{a[$(NF-3)]++}END{for(key in a)if(a[key]>5)print key}')"
# 使用 tail 命令讀取文件 /var/log/auth.log 的最后10000行日志
# 通過 grep 過濾出包含當(dāng)前日期的行
# 使用 awk 命令找出包含 "Failed" 關(guān)鍵詞的行,并以行中倒數(shù)第 3 個(gè)字段(即 IP 地址)為 key,統(tǒng)計(jì)出現(xiàn)次數(shù)
# 如果次數(shù)大于 5,則將 IP 地址打印出來,賦值給變量 ABNORMAL_IPfor IP in $ABNORMAL_IP; do# 使用 for 循環(huán)遍歷 ABNORMAL_IP 中的每個(gè) IP 地址if [ $(iptables -vnL | grep -c "$IP") -eq 0 ]; then# 使用 iptables 命令查看當(dāng)前防火墻規(guī)則,并使用 grep 過濾出包含指定 IP 地址的行,并使用 -c 參數(shù)統(tǒng)計(jì)匹配行的數(shù)量# 如果匹配行的數(shù)量等于 0,表示當(dāng)前 IP 地址不在防火墻規(guī)則中iptables -A INPUT -s $IP -j DROP# 在 INPUT 鏈的末尾追加一條規(guī)則,拒絕指定 IP 地址的所有輸入流量echo "$(date +"%F %T") - iptables -A INPUT -s $IP -j DROP" >> ~/ssh-login-limit.log# 將執(zhí)行的 iptables 命令和時(shí)間記錄到 ~/ssh-login-limit.log 日志文件中fi
done
這段代碼的功能是檢測(cè) /var/log/auth.log 文件中最近出現(xiàn)的登錄失敗記錄,并統(tǒng)計(jì)每個(gè) IP 地址的登錄失敗次數(shù)。如果登錄失敗次數(shù)超過設(shè)定閾值,就將對(duì)應(yīng) IP 地址加入防火墻規(guī)則,禁止其輸入流量,并將執(zhí)行的 iptables 命令和時(shí)間記錄到 ~/ssh-login-limit.log 日志文件中。
代碼的功能:
- 使用 date 命令獲取當(dāng)前日期和時(shí)間,并使用格式化字符串 “%b %d %H” 格式化成月份、日期、小時(shí)的形式,賦值給變量 DATE。
- 使用 tail 命令讀取文件 /var/log/auth.log 的最后10000行日志。
- 使用 grep 過濾出包含當(dāng)前日期的行。
- 使用 awk 命令找出包含 “Failed” 關(guān)鍵詞的行,并以行中倒數(shù)第 3 個(gè)字段(即 IP 地址)為 key,統(tǒng)計(jì)出現(xiàn)次數(shù)。
- 如果次數(shù)大于 5,則將 IP 地址打印出來,賦值給變量 ABNORMAL_IP。
- 使用 for 循環(huán)遍歷 ABNORMAL_IP 中的每個(gè) IP 地址。
- 使用 iptables 命令查看當(dāng)前防火墻規(guī)則,使用 grep 過濾出包含指定 IP 地址的行,并使用 -c 參數(shù)統(tǒng)計(jì)匹配行的數(shù)量。
- 如果匹配行的數(shù)量等于 0,表示當(dāng)前 IP 地址不在防火墻規(guī)則中。
- 使用 iptables 命令在 INPUT 鏈的末尾追加一條規(guī)則,拒絕指定 IP 地址的所有輸入流量。
- 使用 echo 命令將執(zhí)行的 iptables 命令和時(shí)間記錄到 ~/ssh-login-limit.log 日志文件中。
12、判斷用戶輸入的是否為IP地址
方法1:
#!/bin/bash# 定義函數(shù) check_ip,用于檢查輸入的 IP 地址是否合法
function check_ip(){local IP=$1VALID_CHECK=$(echo $IP | awk -F"." '{if($1<=255&&$2<=255&&$3<=255&&$4<=255) print "yes"; else print "no"}')# 將 IP 地址按照 "." 分隔成四個(gè)字段,并使用 awk 判斷每個(gè)字段的取值范圍是否合法(0-255)if echo $IP | grep -E "^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$" > /dev/null; then# 使用正則表達(dá)式驗(yàn)證 IP 地址的格式,必須為 1-3 位數(shù)字 + "." + 1-3 位數(shù)字 + "." + 1-3 位數(shù)字 + "." + 1-3 位數(shù)字# 將匹配結(jié)果重定向到 /dev/null,即丟棄匹配結(jié)果if [[ "$VALID_CHECK" == "yes" ]]; thenecho "$IP available."return 0elseecho "$IP not available!"return 1fielseecho "Format error!"return 1fi
}while true; doread -p "Please enter IP: " ip# 提示用戶輸入 IP 地址,并將輸入保存到變量 ip 中check_ip $ip# 調(diào)用函數(shù) check_ip,傳入用戶輸入的 IP 地址作為參數(shù)進(jìn)行檢查# 如果函數(shù)返回值為 0,表示 IP 地址合法,跳出循環(huán)# 如果函數(shù)返回值為 1,表示 IP 地址不合法,繼續(xù)循環(huán)
done
這段代碼實(shí)現(xiàn)了一個(gè)循環(huán),提示用戶輸入 IP 地址,并通過調(diào)用函數(shù) check_ip 對(duì)輸入的 IP 地址進(jìn)行檢查,直到用戶輸入合法的 IP 地址為止。
代碼的功能:
- 定義了一個(gè)函數(shù) check_ip,用于檢查輸入的 IP 地址是否合法。
- 在函數(shù)內(nèi)部,首先將 IP 地址按照 “.” 分隔成四個(gè)字段,并使用 awk 判斷每個(gè)字段的取值范圍是否合法(0-255)。
- 使用正則表達(dá)式驗(yàn)證 IP 地址的格式,必須為 1-3 位數(shù)字 + “.” + 1-3 位數(shù)字 + “.” + 1-3 位數(shù)字 + “.” + 1-3 位數(shù)字。
- 如果 IP 地址格式合法并且每個(gè)字段的取值也合法,輸出 “IP available.”。
- 如果 IP 地址格式合法但有字段取值不合法,輸出 “IP not available!”。
- 如果 IP 地址格式不合法,輸出 “Format error!”。
- 在 while 循環(huán)中,使用 read 命令提示用戶輸入 IP 地址,并將輸入保存到變量 ip 中。
- 調(diào)用 check_ip 函數(shù),傳入用戶輸入的 IP 地址作為參數(shù)進(jìn)行檢查。
- 如果函數(shù)返回值為 0,表示 IP 地址合法,跳出循環(huán)。
- 如果函數(shù)返回值為 1,表示 IP 地址不合法,繼續(xù)循環(huán)。
方法2:
#!/bin/bash# 定義函數(shù) check_ip,用于檢查輸入的 IP 地址是否合法
function check_ip(){IP=$1if [[ $IP =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then# 使用正則表達(dá)式驗(yàn)證 IP 地址的格式,必須為 1-3 位數(shù)字 + "." + 1-3 位數(shù)字 + "." + 1-3 位數(shù)字 + "." + 1-3 位數(shù)字FIELD1=$(echo $IP|cut -d. -f1)FIELD2=$(echo $IP|cut -d. -f2)FIELD3=$(echo $IP|cut -d. -f3)FIELD4=$(echo $IP|cut -d. -f4)# 使用 cut 命令按照 "." 分割 IP 地址,并分別將每個(gè)字段賦值給對(duì)應(yīng)的變量if [ $FIELD1 -le 255 -a $FIELD2 -le 255 -a $FIELD3 -le 255 -a $FIELD4 -le 255 ]; then# 判斷每個(gè)字段的取值是否都小于等于 255echo "$IP available."# 輸出 IP 地址合法elseecho "$IP not available!"# 輸出 IP 地址不合法,至少有一個(gè)字段的取值大于 255fielseecho "Format error!"# 輸出 IP 地址格式錯(cuò)誤fi
}check_ip 192.168.1.1
# 調(diào)用 check_ip 函數(shù),傳入?yún)?shù) 192.168.1.1 進(jìn)行檢查check_ip 256.1.1.1
# 調(diào)用 check_ip 函數(shù),傳入?yún)?shù) 256.1.1.1 進(jìn)行檢查
這段代碼定義了一個(gè)函數(shù) check_ip,用于檢查輸入的 IP 地址是否合法,并對(duì)兩個(gè) IP 地址進(jìn)行了檢查。
代碼的功能:
- 定義了一個(gè)函數(shù) check_ip,用于檢查輸入的 IP 地址是否合法。
- 使用正則表達(dá)式驗(yàn)證 IP 地址的格式,必須為 1-3 位數(shù)字 + “.” + 1-3 位數(shù)字 + “.” + 1-3 位數(shù)字 + “.” + 1-3 位數(shù)字。
- 使用 cut 命令按照 “.” 分割 IP 地址,并分別將每個(gè)字段賦值給對(duì)應(yīng)的變量。
- 判斷每個(gè)字段的取值是否都小于等于 255。
- 如果 IP 地址合法且每個(gè)字段的取值都小于等于 255,輸出 “IP available.”。
- 如果 IP 地址合法但至少有一個(gè)字段的取值大于 255,輸出 “IP not available!”。
- 如果 IP 地址不合法,輸出 “Format error!”。
在主程序中,調(diào)用 check_ip 函數(shù)進(jìn)行兩次檢查:
- 第一次傳入?yún)?shù) 192.168.1.1 進(jìn)行檢查,輸出 “192.168.1.1 available.”,表示該 IP 地址合法。
- 第二次傳入?yún)?shù) 256.1.1.1 進(jìn)行檢查,輸出 “256.1.1.1 not available!”,表示該 IP 地址不合法,有一個(gè)字段的取值大于 255。
13、判斷用戶輸入的是否為數(shù)字
方法1:
#!/bin/bash# 使用正則表達(dá)式判斷參數(shù)是否為數(shù)字
if [[ $1 =~ ^[0-9]+$ ]]; thenecho "Is Number."# 如果參數(shù)是由一個(gè)或多個(gè)數(shù)字組成,輸出 "Is Number."
elseecho "No Number."# 如果參數(shù)不是由一個(gè)或多個(gè)數(shù)字組成,輸出 "No Number."
fi
段代碼使用正則表達(dá)式判斷參數(shù)是否為數(shù)字。
代碼的功能:
- 使用正則表達(dá)式 ^ [0-9]+$ 判斷參數(shù)是否由一個(gè)或多個(gè)數(shù)字組成。
- ^ 表示匹配字符串的起始位置。
- [0-9] 表示匹配數(shù)字字符的范圍,即 0 到 9。
- +表示匹配前面的元素一次或多次。
- $表示匹配字符串的結(jié)束位置。
- 如果參數(shù)是由一個(gè)或多個(gè)數(shù)字組成,即滿足正則表達(dá)式的匹配條件,輸出 “Is Number.”。
- 如果參數(shù)不是由一個(gè)或多個(gè)數(shù)字組成,即不滿足正則表達(dá)式的匹配條件,輸出 “No Number.”。
方法2:
#!/bin/bash# 判斷參數(shù)是否為一個(gè)數(shù)字
if [ $1 -gt 0 ] 2>/dev/null; thenecho "Is Number."# 如果參數(shù)大于 0,即參數(shù)是一個(gè)數(shù)字,輸出 "Is Number."
elseecho "No Number."# 如果參數(shù)不是一個(gè)數(shù)字,輸出 "No Number."
fi
這段代碼使用條件判斷語句判斷參數(shù)是否為一個(gè)數(shù)字。
代碼的功能:
- 使用條件判斷語句 [ … ] 判斷 $1 是否大于 0。
- $1 表示腳本或函數(shù)的第一個(gè)參數(shù),用于接收命令行傳入的參數(shù)。
- -gt 是一個(gè)數(shù)值比較操作符,表示大于。
- 2>/dev/null 表示將標(biāo)準(zhǔn)錯(cuò)誤輸出重定向到 /dev/null,即丟棄錯(cuò)誤輸出。
- 這是為了避免在參數(shù)不是一個(gè)數(shù)字時(shí)生成不必要的錯(cuò)誤輸出。
- 如果參數(shù)大于 0,即滿足條件判斷,輸出 “Is Number.”。
- 如果參數(shù)不是一個(gè)數(shù)字,即不滿足條件判斷,輸出 “No Number.”。
方法3:
#!/bin/bashecho $1 | awk '{print $0~/^[0-9]+$/?"Is Number.":"No Number."}'
# 使用 awk 命令打印判斷結(jié)果,使用三元運(yùn)算符進(jìn)行條件判斷# 解釋:
# - `echo $1` 打印第一個(gè)參數(shù)
# - `awk` 命令用于處理文本數(shù)據(jù)
# - `{print $0~/^[0-9]+$/?"Is Number.":"No Number."}` 是 awk 的腳本部分,用于判斷參數(shù)是否為一個(gè)數(shù)字并進(jìn)行打印
# - `$0` 表示當(dāng)前行的文本內(nèi)容,即傳入的參數(shù)
# - `~` 是 awk 的匹配操作符
# - `/^[0-9]+$/` 是正則表達(dá)式,用于匹配一個(gè)或多個(gè)數(shù)字的字符串
# - `?` 是三元運(yùn)算符的條件部分,即判斷參數(shù)是否匹配正則表達(dá)式
# - 如果參數(shù)匹配正則表達(dá)式,返回 "Is Number.",否則返回 "No Number."
這段代碼使用了 awk 命令和三元運(yùn)算符來判斷參數(shù)是否是一個(gè)數(shù)字,并進(jìn)行相應(yīng)的輸出。
14、給定目錄找出包含關(guān)鍵字的文件
#!/bin/bashDIR=$1 # 存儲(chǔ)目錄路徑
KEY=$2 # 存儲(chǔ)要搜索的關(guān)鍵詞# 使用循環(huán)逐個(gè)遍歷目錄下的文件
for FILE in $(find $DIR -type f); do# 在文件中搜索關(guān)鍵詞,并將輸出重定向到 `/dev/null`,即丟棄匹配結(jié)果if grep $KEY $FILE &>/dev/null; thenecho "--> $FILE"# 如果搜索到關(guān)鍵詞,輸出文件路徑fi
done
這段代碼的功能是在給定的目錄中搜索包含指定關(guān)鍵詞的文件,并輸出文件的路徑。
代碼的功能:
- DIR=$1,將第一個(gè)命令行參數(shù)賦值給變量 DIR,用于存儲(chǔ)目錄路徑。
- KEY=$2,將第二個(gè)命令行參數(shù)賦值給變量 KEY,用于存儲(chǔ)要搜索的關(guān)鍵詞。
- for FILE in $(find $DIR -type f); do … done,使用循環(huán)逐個(gè)遍歷目錄下的文件。
- find $DIR -type f,使用 find 命令在目錄 $DIR 中搜索所有類型為文件的項(xiàng),并將結(jié)果以空格分隔輸出。
- grep $KEY $FILE &>/dev/null,在文件 $FILE 中搜索關(guān)鍵詞 $KEY,并將匹配結(jié)果重定向到 /dev/null,即丟棄匹配結(jié)果。
- grep 命令用于在文本中搜索指定的模式,這里用于搜索關(guān)鍵詞。
- &> 是重定向的語法,將標(biāo)準(zhǔn)輸出和標(biāo)準(zhǔn)錯(cuò)誤輸出都重定向到同一個(gè)地方,這里是 /dev/null,即丟棄匹配結(jié)果。
- if grep $KEY $FILE &>/dev/null; then … fi,如果搜索到關(guān)鍵詞,則進(jìn)入條件判斷語句。
- echo “–> $FILE”,在終端輸出帶有 --> 前綴的文件路徑,即輸出搜索到的文件路徑。
15、監(jiān)控目錄,將新創(chuàng)建的文件名追加到日志中
場(chǎng)景:記錄目錄下文件操作。
需先安裝inotify-tools軟件包。
-m #持續(xù)監(jiān)聽
-r #使用遞歸形式監(jiān)控目錄
-q #減少冗余信息,只打印出需要的信息
-e #指定要監(jiān)控的事件,多個(gè)事件使用逗號(hào)隔開access #訪問,讀取文件modify #修改,文件內(nèi)容被修改attrib #屬性,文件元數(shù)據(jù)被修改move #移動(dòng),對(duì)文件進(jìn)行移動(dòng)操作 move_to move_fromcreate #創(chuàng)建,生成新文件open #打開,對(duì)文件進(jìn)行打開操作close #關(guān)閉,對(duì)文件進(jìn)行關(guān)閉操作 close_write close_nowritedelete #刪除,文件被刪除 delete_selfunmount #卸載文件或目錄的文件系統(tǒng)
--timefmt #時(shí)間格式 y 年 m月 d日 H小時(shí) M分鐘
--format #監(jiān)控事件發(fā)生后的信息輸出格式%w #表示發(fā)生事件的目錄%f #表示發(fā)生事件的文件%e #表示發(fā)生的事件%Xe #事件以“X”分隔%T #使用由 --timefmt定義的時(shí)間格式
--exclude #排除文件或目錄時(shí),大小寫敏感# --exclude="(.*.swp)|(.*~$)|(.*.swx)"使用正則匹配排除文件
# inotifywait + rsync 同步,放在后臺(tái)跑#!/bin/bash
MON_DIR=/tmp # 要監(jiān)視的目錄
# 使用 inotifywait 監(jiān)視 $MON_DIR 目錄中的文件創(chuàng)建事件,并輸出文件名
inotifywait -mq --format %f -e create $MON_DIR | \
while read files; do# 對(duì)每個(gè)文件執(zhí)行 rsync 命令echo rsync -avz $files admin@ip:/tmp
done
這段代碼的功能是使用 inotifywait 監(jiān)視指定目錄中的文件創(chuàng)建事件,并在有文件創(chuàng)建時(shí)執(zhí)行 rsync 命令。
代碼的功能:
- MON_DIR=/tmp,將 /tmp 目錄路徑賦值給變量 MON_DIR,表示要監(jiān)視的目錄。
- inotifywait -mq --format %f -e create $MON_DIR,使用 inotifywait 命令監(jiān)視目錄 $MON_DIR 中的文件創(chuàng)建事件,并以簡(jiǎn)潔的格式輸出文件名。
- while read files; do … done,使用 while 循環(huán)逐行讀取輸出的文件名。
- echo rsync -avz $files admin@ip:/tmp,對(duì)于每個(gè)讀取的文件名,輸出 rsync 命令。
- rsync 命令用于文件同步和傳輸。
- -avz 表示啟用歸檔模式并壓縮傳輸。
- $files 表示讀取到的文件名,即待同步的文件。
- admin@ip:/tmp 表示目標(biāo)地址,具體的 IP 地址和目錄可以根據(jù)實(shí)際情況進(jìn)行修改。
16、給用戶提供多個(gè)網(wǎng)卡選擇
場(chǎng)景:服務(wù)器多個(gè)網(wǎng)卡時(shí),獲取指定網(wǎng)卡,例如網(wǎng)卡流量
#!/bin/bashfunction local_nic() {local NUM ARRAY_LENGTHNUM=0for NIC_NAME in $(ls /sys/class/net | grep -vE "lo|docker0"); doNIC_IP=$(ifconfig $NIC_NAME | awk -F'[: ]+' '/inet addr/{print $4}')if [ -n "$NIC_IP" ]; thenNIC_IP_ARRAY[$NUM]="$NIC_NAME:$NIC_IP"# 將網(wǎng)卡名和對(duì)應(yīng)IP放到數(shù)組let NUM++fidoneARRAY_LENGTH=${#NIC_IP_ARRAY[*]}# 獲取數(shù)組長(zhǎng)度if [ $ARRAY_LENGTH -eq 1 ]; then# 如果數(shù)組里面只有一條記錄,說明只有一個(gè)網(wǎng)卡NIC=${NIC_IP_ARRAY[0]%:*}# 獲取網(wǎng)卡名稱(去除IP地址部分)return 0elif [ $ARRAY_LENGTH -eq 0 ]; then# 如果沒有記錄,說明沒有可用的網(wǎng)卡echo "No available network card!"exit 1else# 如果有多條記錄,則提醒輸入選擇for NIC in ${NIC_IP_ARRAY[*]}; doecho $NIC# 輸出所有網(wǎng)卡名稱和對(duì)應(yīng)的IP地址donewhile true; doread -p "Please enter the name of the network card to use: " INPUT_NIC_NAME# 提示用戶輸入要使用的網(wǎng)卡名稱COUNT=0for NIC in ${NIC_IP_ARRAY[*]}; doNIC_NAME=${NIC%:*}if [ $NIC_NAME == "$INPUT_NIC_NAME" ]; thenNIC=${NIC_IP_ARRAY[$COUNT]%:*}# 獲取用戶輸入網(wǎng)卡名稱對(duì)應(yīng)的IP地址return 0elseCOUNT+=1fidoneecho "Not match! Please input again."# 如果輸入不匹配,要求用戶重新輸入donefi
}local_nic
這段代碼的功能是獲取本地可用的網(wǎng)卡和對(duì)應(yīng)的IP地址,并要求用戶選擇要使用的網(wǎng)卡。
代碼的功能:
- function local_nic(),定義了一個(gè)名為 local_nic 的函數(shù)。
- NUM=0,設(shè)置一個(gè)變量 NUM 為 0,用于記錄數(shù)組的索引。
- for NIC_NAME in $(ls /sys/class/net | grep -vE “l(fā)o|docker0”); do … done,循環(huán)遍歷 /sys/class/net 目錄下的網(wǎng)卡名稱,排除 lo(本地回環(huán)接口)和 docker0(Docker 網(wǎng)絡(luò)接口)。
- NIC_IP=$(ifconfig $NIC_NAME | awk -F’[: ]+’ ‘/inet addr/{print $4}’),獲取每個(gè)網(wǎng)卡的 IP 地址,并將結(jié)果賦值給 NIC_IP。
- if [ -n “$NIC_IP” ]; then … fi,如果 NIC_IP 不為空(即獲取到了 IP 地址),則執(zhí)行條件判斷的代碼塊。
- NIC_IP_ARRAY[$ NUM]=“$ NIC_NAME:$NIC_IP”,將網(wǎng)卡名稱和對(duì)應(yīng)的 IP 地址放入數(shù)組 NIC_IP_ARRAY 中,索引為 $NUM。
- let NUM++,將 NUM 的值加 1,用于下次循環(huán)時(shí)的數(shù)組索引。
- ARRAY_LENGTH=${#NIC_IP_ARRAY[*]},獲取數(shù)組 NIC_IP_ARRAY 的長(zhǎng)度。
- if [ $ARRAY_LENGTH -eq 1 ]; then … fi,如果數(shù)組長(zhǎng)度為 1,說明只有一個(gè)可用網(wǎng)卡。
- NIC=${NIC_IP_ARRAY[0]%:*},將數(shù)組中的第一個(gè)元素賦值給變量 NIC,并去除末尾的 IP 地址部分。
- return 0,函數(shù)執(zhí)行成功,返回 0。
- elif [ $ARRAY_LENGTH -eq 0 ]; then … fi,如果數(shù)組長(zhǎng)度為 0,說明沒有可用的網(wǎng)卡。
- echo “No available network card!”,輸出提示信息 “No available network card!”。
- exit 1,正常退出腳本并返回狀態(tài)碼 1。
- else,如果有多條可用網(wǎng)卡,則要求用戶選擇要使用的網(wǎng)卡。
- for NIC in ${NIC_IP_ARRAY[*]}; do … done,循環(huán)遍歷數(shù)組 NIC_IP_ARRAY 中的每個(gè)元素,即每個(gè)網(wǎng)卡名稱和對(duì)應(yīng)的 IP 地址。
- echo $NIC,輸出每個(gè)網(wǎng)卡的名稱和對(duì)應(yīng)的 IP 地址。
- while true; do … done,使用無限循環(huán),要求用戶輸入網(wǎng)卡名稱并進(jìn)行匹配。
- read -p "Please enter the name of the network card to use: " INPUT_NIC_NAME,提示用戶輸入要使用的網(wǎng)卡名稱,將其保存在變量 INPUT_NIC_NAME 中。
- COUNT=0,設(shè)置一個(gè)變量 COUNT 為 0,用于記錄數(shù)組的索引。
- for NIC in ${NIC_IP_ARRAY[*]}; do … done,循環(huán)遍歷數(shù)組 NIC_IP_ARRAY 中的每個(gè)元素,即每個(gè)網(wǎng)卡名稱和對(duì)應(yīng)的 IP 地址。
- NIC_NAME=${NIC%: *},將數(shù)組元素中的 IP 地址部分截取掉,只保留網(wǎng)卡名稱。
- if [ $ NIC_NAME == “$INPUT_NIC_NAME” ]; then … fi,如果網(wǎng)卡名稱與用戶輸入的名稱匹配。
- NIC=$ {NIC_IP_ARRAY[$COUNT]%: *},將數(shù)組元素中的 IP 地址部分截取掉,只保留網(wǎng)卡名稱,賦值給變量 NIC。
- return 0,函數(shù)執(zhí)行成功,返回 0。
- else,如果輸入不匹配,輸出提示信息并要求用戶重新輸入。
- done,結(jié)束內(nèi)層循環(huán)。
- done,結(jié)束函數(shù)的整體邏輯。
- local_nic,調(diào)用 local_nic 函數(shù)。
17、查看網(wǎng)卡實(shí)時(shí)流量
適用于CentOS操作系統(tǒng)。
#!/bin/bash# Description: Only CentOS# traffic_unit_conv函數(shù)將流量轉(zhuǎn)換為合適的單位(KB/s或MB/s)
traffic_unit_conv() {local traffic=$1if [ $traffic -gt 1024000 ]; thenprintf "%.1f%s" "$(($traffic/1024/1024))" "MB/s"# 如果流量大于1024000(1024KB),將流量轉(zhuǎn)換為MB/s并保留1位小數(shù)elif [ $traffic -lt 1024000 ]; thenprintf "%.1f%s" "$(($traffic/1024))" "KB/s"# 如果流量小于1024000(1024KB),將流量轉(zhuǎn)換為KB/s并保留1位小數(shù)fi
}NIC=$1 # 獲取用戶傳入的參數(shù)作為要監(jiān)測(cè)的網(wǎng)卡名稱echo -e " In ------ Out"
# 打印標(biāo)題 "In ------ Out"while true; do# 進(jìn)入無限循環(huán),監(jiān)測(cè)流量變化OLD_IN=$(awk -F'[: ]+' '$0~"'$NIC'"{print $3}' /proc/net/dev)# 獲取舊的接收流量(使用awk命令從/proc/net/dev中提取)OLD_OUT=$(awk -F'[: ]+' '$0~"'$NIC'"{print $11}' /proc/net/dev)# 獲取舊的發(fā)送流量(使用awk命令從/proc/net/dev中提取)sleep 1# 等待1秒,以便獲取新的流量數(shù)據(jù)NEW_IN=$(awk -F'[: ]+' '$0~"'$NIC'"{print $3}' /proc/net/dev)# 獲取新的接收流量NEW_OUT=$(awk -F'[: ]+' '$0~"'$NIC'"{print $11}' /proc/net/dev)# 獲取新的發(fā)送流量IN=$(($NEW_IN-$OLD_IN))# 計(jì)算接收的流量差值OUT=$(($NEW_OUT-$OLD_OUT))# 計(jì)算發(fā)送的流量差值echo "$(traffic_unit_conv $IN) $(traffic_unit_conv $OUT)"# 調(diào)用traffic_unit_conv函數(shù)將流量差值轉(zhuǎn)換為合適的單位并打印sleep 1# 等待1秒,以便下一次獲取流量數(shù)據(jù)
done
# 結(jié)束循環(huán)
這段代碼的功能是監(jiān)測(cè)指定網(wǎng)卡的接收和發(fā)送流量,并每秒打印一次流量值。
代碼的功能:
- #Description: Only CentOS6,描述腳本的作用,限定適用于 CentOS 系統(tǒng)。
- traffic_unit_conv(),定義了一個(gè)名為 traffic_unit_conv 的函數(shù),用于將流量轉(zhuǎn)換為合適的單位(KB/s或MB/s)。
- local traffic=$1,將傳入的第一個(gè)參數(shù)賦值給變量 traffic,表示要轉(zhuǎn)換的流量值。
if [ $traffic -gt 1024000 ]; then … fi,如果流量值大于 1024000(1024KB),執(zhí)行條件判斷的代碼塊。 - printf “%.1f%s” “$ (($traffic/1024/1024))” “MB/s”,將流量值除以1024再除以1024,并保留1位小數(shù),表示為 MB/s。
- elif [ $ traffic -lt 1024000 ]; then … fi,如果流量值小于 1024000(1024KB),執(zhí)行條件判斷的代碼塊。
- printf “%.1f%s” “$ (($ traffic/1024))” “KB/s”,將流量值除以1024,保留1位小數(shù),表示為 KB/s。
- NIC=$ 1,將傳入的第一個(gè)參數(shù)賦值給變量 NIC,表示要監(jiān)測(cè)的網(wǎng)卡名稱。
- echo -e " In ------ Out",打印標(biāo)題 “In ------ Out”,使用 -e 選項(xiàng)表示支持特殊字符的解釋。
- while true; do … done,進(jìn)入無限循環(huán),用于持續(xù)監(jiān)測(cè)流量變化。
- OLD_IN=$ (awk -F’[: ]+’ ‘$ 0~"’$ NIC’"{print $ 3}’ /proc/net/dev),使用 awk 命令獲取當(dāng)前網(wǎng)卡的舊的接收流量值。
- OLD_OUT=$ (awk -F’[: ]+’ ‘$ 0~"’$ NIC’"{print $ 11}’ /proc/net/dev),使用 awk 命令獲取當(dāng)前網(wǎng)卡的舊的發(fā)送流量值。
- sleep 1,等待1秒,以便獲取新的流量數(shù)據(jù)。
- NEW_IN=$ (awk -F’[: ]+’ ‘$ 0~"’$ NIC’"{print $ 3}’ /proc/net/dev),使用 awk 命令獲取當(dāng)前網(wǎng)卡的新的接收流量值。
- NEW_OUT=$ (awk -F’[: ]+’ ‘$ 0~"’$NIC’"{print $11}’ /proc/net/dev),使用 awk 命令獲取當(dāng)前網(wǎng)卡的新的發(fā)送流量值。
- IN=$ (($ NEW_IN-$ OLD_IN)),計(jì)算接收的流量差值。
- OUT=$ (($ NEW_OUT-$ OLD_OUT)),計(jì)算發(fā)送的流量差值。
- echo “$(traffic_unit_conv $IN) $(traffic_unit_conv $OUT)”,調(diào)用 traffic_unit_conv 函數(shù)將流量差值轉(zhuǎn)換為合適的單位,并打印接收和發(fā)送流量。
- sleep 1,等待1秒,以便下一次獲取流量數(shù)據(jù)。
- done,結(jié)束內(nèi)層循環(huán)。
使用:./traffic.sh eth0
18、MySQL數(shù)據(jù)庫備份
#!/bin/bashDATE=$(date +%F_%H-%M-%S) # 獲取當(dāng)前日期和時(shí)間,用于備份文件名
HOST=192.168.1.120 # 數(shù)據(jù)庫主機(jī)地址
DB=test # 數(shù)據(jù)庫名稱
USER=bak # 數(shù)據(jù)庫用戶名
PASS=123456 # 數(shù)據(jù)庫密碼
MAIL="zhangsan@example.com lisi@example.com" # 接收備份結(jié)果通知的郵件地址
BACKUP_DIR=/data/db_backup # 備份文件存儲(chǔ)路徑
SQL_FILE=${DB}_full_$DATE.sql # 生成的 SQL 備份文件名
BAK_FILE=${DB}_full_$DATE.zip # 生成的壓縮備份文件名cd $BACKUP_DIR # 切換到備份文件存儲(chǔ)路徑# 使用 mysqldump 命令備份數(shù)據(jù)庫,并將結(jié)果輸出到 SQL 備份文件中
if mysqldump -h$HOST -u$USER -p$PASS --single-transaction --routines --triggers -B $DB > $SQL_FILE; then# 如果備份成功,則將 SQL 備份文件壓縮為壓縮備份文件,并刪除原始 SQL 備份文件zip $BAK_FILE $SQL_FILE && rm -f $SQL_FILE# 如果壓縮備份文件為空,則表示備份數(shù)據(jù)可能出錯(cuò),發(fā)送郵件通知if [ ! -s $BAK_FILE ]; thenecho "$DATE 內(nèi)容" | mail -s "主題" $MAILfi
else# 如果備份失敗,發(fā)送郵件通知echo "$DATE 內(nèi)容" | mail -s "主題" $MAIL
fi# 刪除14天前的壓縮備份文件
find $BACKUP_DIR -name '*.zip' -ctime +14 -exec rm {} \;
這段代碼的功能是備份指定數(shù)據(jù)庫,并將備份文件壓縮,最后刪除過期的備份文件。
代碼的功能:
- DATE=$ (date +%F_%H-%M-%S),使用 date 命令獲取當(dāng)前的日期和時(shí)間,并賦值給變量 DATE,用于生成備份文件名。
- HOST=192.168.1.120,設(shè)置數(shù)據(jù)庫主機(jī)地址。
- DB=test,設(shè)置要備份的數(shù)據(jù)庫名稱。
- USER=bak,設(shè)置連接數(shù)據(jù)庫所使用的用戶名。
- PASS=123456,設(shè)置連接數(shù)據(jù)庫所使用的密碼。
- MAIL=“zhangsan@example.com lisi@example.com”,設(shè)置接收備份結(jié)果通知的郵件地址,多個(gè)郵件地址之間使用空格分隔。
- BACKUP_DIR=/data/db_backup,設(shè)置備份文件存儲(chǔ)路徑。
- SQL_FILE=$ {DB}full$ DATE.sql,生成 SQL 備份文件的文件名。
- BAK_FILE=$ {DB}full$ DATE.zip,生成的壓縮備份文件名。
- cd $ BACKUP_DIR,切換到備份文件存儲(chǔ)路徑。
- if mysqldump -h$ HOST -u$ USER -p$ PASS --single-transaction --routines --triggers -B $ DB > $ SQL_FILE; then … fi,使用 mysqldump 命令備份指定數(shù)據(jù)庫,并將結(jié)果輸出到 SQL 備份文件中。如果備份成功,則執(zhí)行條件判斷的代碼塊。
- zip $ BAK_FILE $ SQL_FILE && rm -f $ SQL_FILE,將 SQL 備份文件壓縮為壓縮備份文件,并刪除原始 SQL 備份文件。
- if [ ! -s $ BAK_FILE ]; then … fi,如果壓縮備份文件為空(沒有內(nèi)容),執(zhí)行條件判斷的代碼塊。
- echo “$DATE 內(nèi)容” | mail -s “主題” $MAIL,使用 mail 命令發(fā)送郵件通知,郵件主題為 “主題”,郵件內(nèi)容包含當(dāng)前的日期和時(shí)間。
- else … fi,如果備份失敗,執(zhí)行條件判斷的代碼塊。
- find $BACKUP_DIR -name ‘*.zip’ -ctime +14 -exec rm {} ;,使用 find 命令查找指定路徑下14天前的所有壓縮備份文件,并刪除它們。
19、Nginx服務(wù)管理腳本
場(chǎng)景:使用源碼包安裝Nginx不含帶服務(wù)管理腳本,也就是不能使用"service nginx start"或"/etc/init.d/nginx start",所以寫了以下的服務(wù)管理腳本。
#!/bin/bash
# Description: Only support RedHat system. /etc/init.d/functionsWORD_DIR=/usr/local/nginx # Nginx安裝目錄
DAEMON=$WORD_DIR/sbin/nginx # Nginx可執(zhí)行文件路徑
CONF=$WORD_DIR/conf/nginx.conf # Nginx配置文件路徑
NAME=nginx # 進(jìn)程名稱
PID=$(awk -F'[; ]+' '/^[^#]/{if($0~/pid;/)print $2}' $CONF) # 獲取配置文件中定義的PID文件路徑# 如果配置文件中未定義PID文件路徑,設(shè)置默認(rèn)的PID文件路徑
if [ -z "$PID" ]; thenPID=$WORD_DIR/logs/nginx.pid
elsePID=$WORD_DIR/$PID
fistop() {$DAEMON -s stop # 發(fā)送信號(hào)停止Nginx進(jìn)程sleep 1# 判斷PID文件是否存在,根據(jù)結(jié)果輸出不同的操作提示[ ! -f $PID ] && action "* Stopping $NAME" /bin/true || action "* Stopping $NAME" /bin/false
}start() {$DAEMON # 啟動(dòng)Nginx進(jìn)程sleep 1# 判斷PID文件是否存在,根據(jù)結(jié)果輸出不同的操作提示[ -f $PID ] && action "* Starting $NAME" /bin/true || action "* Starting $NAME" /bin/false
}reload() {$DAEMON -s reload # 發(fā)送信號(hào)重新加載Nginx配置
}test_config() {$DAEMON -t # 檢查Nginx配置文件語法是否正確
}case "$1" instart)# 如果PID文件不存在,啟動(dòng)Nginx進(jìn)程;否則輸出進(jìn)程正在運(yùn)行的提示if [ ! -f $PID ]; thenstartelseecho "$NAME is running..."exit 0fi;;stop)# 如果PID文件存在,停止Nginx進(jìn)程;否則輸出進(jìn)程未運(yùn)行的提示if [ -f $PID ]; thenstopelseecho "$NAME not running!"exit 0fi;;restart)# 如果PID文件不存在,輸出進(jìn)程未運(yùn)行的提示并啟動(dòng)Nginx進(jìn)程;否則先停止再啟動(dòng)if [ ! -f $PID ]; thenecho "$NAME not running!" startelsestopstartfi;;reload)# 發(fā)送信號(hào)重新加載Nginx配置reload;;testconfig)# 檢查Nginx配置文件語法是否正確test_config;;status)# 根據(jù)PID文件是否存在輸出不同的狀態(tài)提示[ -f $PID ] && echo "$NAME is running..." || echo "$NAME not running!";;*)# 輸出腳本的使用方法,并退出腳本(返回退出碼3)echo "Usage: $0 {start|stop|restart|reload|testconfig|status}"exit 3;;
esac
這段腳本實(shí)現(xiàn)了對(duì) Nginx 服務(wù)的啟停、重啟、重新加載配置文件以及檢查配置文件語法的功能。
代碼的功能:
- . /etc/init.d/functions,引入 /etc/init.d/functions 文件,該文件包含用于輸出提示信息的函數(shù)。
- WORD_DIR=/usr/local/nginx,設(shè)置 Nginx 的安裝目錄。
- DAEMON=$WORD_DIR/sbin/nginx,設(shè)置 Nginx 可執(zhí)行文件的路徑。
- CONF=$ WORD_DIR/conf/nginx.conf,設(shè)置 Nginx 的配置文件路徑。
- NAME=nginx,設(shè)置進(jìn)程名稱為 “nginx”。
- PID=$ (awk -F’[; ]+’ ‘/^ [ ^#]/{if($ 0~/pid;/)print $ 2}’ $ CONF),使用 awk 命令從配置文件中提取 PID 文件路徑。
- if [ -z “$ PID” ]; then … else … fi,如果 PID 文件路徑為空,則設(shè)置默認(rèn)的 PID 文件路徑為 $ WORD_DIR/logs/nginx.pid。
- stop() { … },定義一個(gè)函數(shù) stop,用于停止 Nginx 進(jìn)程。
- start() { … },定義一個(gè)函數(shù) start,用于啟動(dòng) Nginx 進(jìn)程。
- reload() { … },定義一個(gè)函數(shù) reload,用于重新加載 Nginx 配置文件。
- test_config() { … },定義一個(gè)函數(shù) test_config,用于檢查 Nginx 配置文件的語法是否正確。
- case “$1” in … esac,根據(jù)腳本傳入的參數(shù)執(zhí)行不同的操作。
- action “* Stopping $NAME” /bin/true,輸出停止進(jìn)程的操作提示,后面的 /bin/true 表示操作成功。
- action “* Starting $NAME” /bin/true,輸出啟動(dòng)進(jìn)程的操作提示,后面的 /bin/true 表示操作成功。
- action “* Stopping $NAME” /bin/false,輸出停止進(jìn)程的操作提示,后面的 /bin/false 表示操作失敗。
- action “* Starting $NAME” /bin/false,輸出啟動(dòng)進(jìn)程的操作提示,后面的 /bin/false 表示操作失敗。
- if [ ! -f $PID ]; then … else … fi,如果 PID 文件不存在,則啟動(dòng) Nginx 進(jìn)程;否則輸出進(jìn)程正在運(yùn)行的提示。
- if [ -f $PID ]; then … else … fi,如果 PID 文件存在,則停止 Nginx 進(jìn)程;否則輸出進(jìn)程未運(yùn)行的提示。
- if [ ! -f $PID ]; then … else … fi,如果 PID 文件不存在,則輸出進(jìn)程未運(yùn)行的提示并啟動(dòng) Nginx - ;否則先停止再啟動(dòng)。
- reload,發(fā)送信號(hào)重新加載 Nginx 配置。
- test_config,檢查 Nginx 配置文件的語法是否正確。
- [ -f $ PID ] && echo “$ NAME is running…” || echo “$NAME not running!”,根據(jù) PID 文件是否存在輸出不同的狀態(tài)提示。
- echo “Usage: $0 {start|stop|restart|reload|testconfig|status}”,輸出腳本的使用方法。
- exit 3,退出腳本,返回退出碼 3。
20、用戶根據(jù)菜單選擇要連接的Linux主機(jī)
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/bashPS3="Please input number: " # 設(shè)置 select 命令的提示信息HOST_FILE=host.txt # 存儲(chǔ)主機(jī)連接信息的文件路徑# 無限循環(huán),用于不斷提供主機(jī)選擇菜單
while true; do# 使用 select 命令選擇主機(jī)名(從 host.txt 文件中獲取)select NAME in $(awk '{print $1}' $HOST_FILE) quit; do# 如果選擇的主機(jī)名為 "quit",退出腳本[ ${NAME:=empty} == "quit" ] && exit 0# 根據(jù)選擇的主機(jī)名從 host.txt 文件中獲取對(duì)應(yīng)的 IP、用戶名和端口號(hào)IP=$(awk -v NAME=${NAME} '$1==NAME{print $2}' $HOST_FILE)USER=$(awk -v NAME=${NAME} '$1==NAME{print $3}' $HOST_FILE)PORT=$(awk -v NAME=${NAME} '$1==NAME{print $4}' $HOST_FILE)if [ $IP ]; thenecho "Name: $NAME, IP: $IP"# 使用 ssh 命令連接遠(yuǎn)程主機(jī),使用密鑰免交互登錄ssh -o StrictHostKeyChecking=no -p $PORT -i id_rsa $USER@$IPbreakelseecho "Input error, Please enter again!"breakfidone
done
這段腳本實(shí)現(xiàn)了根據(jù)主機(jī)名從 host.txt 文件中獲取主機(jī)的連接信息,并使用 SSH 命令連接遠(yuǎn)程主機(jī)的功能。
代碼的功能:
- PS3="Please input number: ",設(shè)置 select 命令的提示信息,用于用戶選擇主機(jī)時(shí)顯示。
- HOST_FILE=host.txt,設(shè)置存儲(chǔ)主機(jī)連接信息的文件路徑為 host.txt。
- while true; do … done,無限循環(huán),用于不斷提供主機(jī)選擇菜單。
- select NAME in $(awk ‘{print $1}’ $HOST_FILE) quit; do … done,使用 select 命令選擇主機(jī)名(從 host.txt 文件中獲取),并加上 quit 選項(xiàng)用于退出腳本。
- [ ${NAME:=empty} == “quit” ] && exit 0,如果選擇的主機(jī)名為 quit,則退出腳本。
- IP=$ (awk -v NAME=${NAME} ‘$1==NAME{print $2}’ $HOST_FILE),根據(jù)選擇的主機(jī)名從 host.txt 文件中獲取對(duì)應(yīng)的 IP 地址。
- USER=$ (awk -v NAME=${NAME} ‘$1==NAME{print $3}’ $HOST_FILE),根據(jù)選擇的主機(jī)名從 - host.txt 文件中獲取對(duì)應(yīng)的用戶名。
- PORT=$ (awk -v NAME=${NAME} ‘$1==NAME{print $4}’ $HOST_FILE),根據(jù)選擇的主機(jī)名從 host.txt 文件中獲取對(duì)應(yīng)的端口號(hào)。
- if [ $IP ]; then … else … fi,如果 IP 地址存在,則輸出主機(jī)名和 IP 地址,并使用 SSH 命令連接遠(yuǎn)程主機(jī);否則輸出輸入錯(cuò)誤的提示信息。
- echo “Name: $NAME, IP: $IP”,輸出選擇的主機(jī)名和對(duì)應(yīng)的 IP 地址。
- ssh -o StrictHostKeyChecking=no -p $ PORT -i id_rsa $ USER@$IP,使用 SSH 命令連接遠(yuǎn)程主機(jī),其中使用 -o StrictHostKeyChecking=no 參數(shù)禁止嚴(yán)格的主機(jī)密鑰檢查,-p $PORT 指定連接的端口號(hào),-i id_rsa 指定使用密鑰文件進(jìn)行免交互登錄。
- break,結(jié)束當(dāng)前循環(huán),回到外層的無限循環(huán),等待下一次主機(jī)選擇。
- echo “Input error, Please enter again!”,輸出輸入錯(cuò)誤的提示信息。
- exit 0,退出腳本,返回退出碼 0。
21、從FTP服務(wù)器下載文件
#!/bin/bash# 檢查參數(shù)數(shù)量是否為1
if [ $# -ne 1 ]; thenecho "Usage: $0 filename"
fi# 獲取指定文件的目錄和文件名
dir=$(dirname $1)
file=$(basename $1)# 使用 ftp 命令連接 FTP 服務(wù)器并執(zhí)行操作
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
這段腳本實(shí)現(xiàn)了通過 FTP 下載指定文件的功能。
代碼的功能:
- if [ $# -ne 1 ]; then … fi,檢查傳入的參數(shù)數(shù)量是否為1,如果不是1個(gè)參數(shù),輸出用法提示信息。
- echo “Usage: $0 filename”,輸出用法提示信息,告知用戶正確的參數(shù)輸入格式。
- dir=$(dirname $1),獲取指定文件的目錄路徑。
- file=$(basename $1),獲取指定文件的文件名。
- ftp -n -v << EOF,使用 ftp 命令連接 FTP 服務(wù)器并執(zhí)行操作,-n 參數(shù)表示在連接后不執(zhí)行任何自動(dòng)登錄操作,-v 參數(shù)表示輸出詳細(xì)的執(zhí)行過程信息。
- open 192.168.1.10,使用 ftp 命令連接到指定的 FTP 服務(wù)器,其中 192.168.1.10 是 FTP 服務(wù)器的 IP 地址。
- user admin password,使用指定的用戶名 admin 和密碼 password 進(jìn)行登錄。
- binary,設(shè)置 FTP 傳輸模式為二進(jìn)制,以確保傳輸?shù)奈募3衷瓨?#xff0c;避免出現(xiàn) MD5 值不同或 .tar.gz 壓縮包格式錯(cuò)誤的問題。
- cd $dir,切換到指定的目錄。
- get “$ file”,下載指定的文件,其中 $ 用于獲取變量的值,“$file” 使用雙引號(hào)包圍變量值,以處理文件名中可能包含的特殊字符。
- EOF,表示結(jié)束 ftp 命令的輸入。
22、連續(xù)輸入5個(gè)100以內(nèi)的數(shù)字,統(tǒng)計(jì)和、最小和最大
#!/bin/bash# 初始化計(jì)數(shù)器、和、最小值、最大值
COUNT=1
SUM=0
MIN=0
MAX=100# 循環(huán)5次,讀取用戶輸入的整數(shù)并進(jìn)行相關(guān)操作
while [ $COUNT -le 5 ]; doread -p "請(qǐng)輸入1-10個(gè)整數(shù):" INT # 提示用戶輸入1-10個(gè)整數(shù)if [[ ! $INT =~ ^[0-9]+$ ]]; then # 判斷輸入是否為整數(shù)echo "輸入必須是整數(shù)!"exit 1 # 若輸入不是整數(shù),退出腳本,返回退出碼 1elif [[ $INT -gt 100 ]]; then # 判斷輸入是否小于等于100echo "輸入必須是100以內(nèi)!"exit 1 # 若輸入大于100,退出腳本,返回退出碼 1fiSUM=$(($SUM+$INT)) # 累加輸入的整數(shù)到和變量[ $MIN -lt $INT ] && MIN=$INT # 更新最小值變量[ $MAX -gt $INT ] && MAX=$INT # 更新最大值變量let COUNT++ # 計(jì)數(shù)器自增
done# 輸出計(jì)算結(jié)果
echo "SUM: $SUM" # 輸出和
echo "MIN: $MIN" # 輸出最小值
echo "MAX: $MAX" # 輸出最大值
這段腳本實(shí)現(xiàn)了讀取用戶輸入的整數(shù),計(jì)算輸入的整數(shù)的和、最小值和最大值,并輸出結(jié)果。
代碼的功能:
- COUNT=1,初始化計(jì)數(shù)器變量為1。
- SUM=0,初始化和變量為0。
- MIN=0,初始化最小值變量為0。
- MAX=100,初始化最大值變量為100。
- while [ $COUNT -le 5 ]; do … done,循環(huán)5次,用于接收和處理用戶輸入的整數(shù)。
- read -p “請(qǐng)輸入1-10個(gè)整數(shù):” INT,提示用戶輸入1-10個(gè)整數(shù),并將輸入的值保存到變量 INT。
- if [[ ! $ INT =~ ^ [0-9]+$ ]]; then … fi,如果輸入的值不是整數(shù),則提示錯(cuò)誤并退出腳本。
- echo “輸入必須是整數(shù)!”,輸出提示信息,告知用戶輸入必須是整數(shù)。
- exit 1,退出腳本,返回退出碼 1。
- elif [[ $INT -gt 100 ]]; then … fi,如果輸入的值大于100,則提示錯(cuò)誤并退出腳本。
- echo “輸入必須是100以內(nèi)!”,輸出提示信息,告知用戶輸入必須是100以內(nèi)的整數(shù)。
- SUM=$ (($ SUM+$INT)),將輸入的整數(shù)累加到和變量。
- [ $ MIN -lt $ INT ] && MIN=$INT,更新最小值變量,如果新輸入的整數(shù)大于最小值,則更新最小值。
- [ $ MAX -gt $ INT ] && MAX=$INT,更新最大值變量,如果新輸入的整數(shù)小于最大值,則更新最大值。
- let COUNT++,將計(jì)數(shù)器自增。
- echo “SUM: $SUM”,輸出計(jì)算的和。
- echo “MIN: $MIN”,輸出計(jì)算的最小值。
- echo “MAX: $MAX”,輸出計(jì)算的最大值。
23、將結(jié)果分別賦值給變量
應(yīng)用場(chǎng)景:希望將執(zhí)行結(jié)果或者位置參數(shù)賦值給變量,以便后續(xù)使用。
方法1:
for i in $(echo "4 5 6"); do # 循環(huán)遍歷 "4 5 6"eval a$i=$i # 為變量 a4、a5、a6 賦值,變量名由 $i 決定,值為 $i 的值
done
echo $a4 $a5 $a6 # 輸出變量 a4、a5、a6 的值# 這段代碼的目的是創(chuàng)建變量 a4、a5、a6,并將其賦值為 4、5、6
這段代碼使用 for 循環(huán)遍歷列表 “4 5 6”,對(duì)于每個(gè)列表中的元素,使用 eval 命令動(dòng)態(tài)創(chuàng)建變量 a4、a5、a6,并賦值為相應(yīng)的值。最后通過 echo 命令輸出變量 a4、a5、a6 的值。
方法2:將位置參數(shù)192.168.1.1{1,2}拆分為到每個(gè)變量
num=0 # 初始化計(jì)數(shù)器變量為0
for i in $(eval echo $*); do # 循環(huán)遍歷命令行參數(shù),并使用 eval 命令展開參數(shù)中的花括號(hào)拓展表達(dá)式let num+=1 # 計(jì)數(shù)器自增eval node${num}="$i" # 動(dòng)態(tài)創(chuàng)建變量 node1、node2、node3,并賦值為相應(yīng)的參數(shù)值
done
echo $node1 $node2 $node3 # 輸出變量 node1、node2、node3 的值# 示例運(yùn)行命令:bash a.sh 192.168.1.1{1,2}
# 輸出:192.168.1.11 192.168.1.12# 這段代碼的目的是根據(jù)命令行參數(shù)動(dòng)態(tài)創(chuàng)建變量,并賦予相應(yīng)的值
這段代碼通過 for 循環(huán)遍歷命令行參數(shù)(使用 $* 獲取所有參數(shù)),使用 eval 命令將參數(shù)中的花括號(hào)拓展表達(dá)式展開(如 192.168.1.1{1,2} 拓展為 192.168.1.11 192.168.1.12),然后在循環(huán)中,計(jì)數(shù)器 num 自增,然后使用 eval 命令動(dòng)態(tài)創(chuàng)建變量 node1、node2、node3,并賦值為相應(yīng)的參數(shù)值。最后通過 echo 命令輸出變量 node1、node2、node3 的值。
方法3:
arr=(4 5 6) # 創(chuàng)建包含元素 4、5、6 的數(shù)組 arrINDEX1=$(echo ${arr[0]}) # 獲取數(shù)組 arr 中的第一個(gè)元素,并將其賦值給變量 INDEX1
INDEX2=$(echo ${arr[1]}) # 獲取數(shù)組 arr 中的第二個(gè)元素,并將其賦值給變量 INDEX2
INDEX3=$(echo ${arr[2]}) # 獲取數(shù)組 arr 中的第三個(gè)元素,并將其賦值給變量 INDEX3# 這段代碼的目的是從數(shù)組 arr 中提取元素,并賦值給相應(yīng)的變量
這段代碼創(chuàng)建了一個(gè)名為 arr 的數(shù)組,其中包含了元素 4、5、6。
然后,使用 ${arr[index]} 的形式從數(shù)組 arr 中提取特定索引位置的元素,并使用 echo 命令將其輸出。通過將提取的元素賦值給相應(yīng)的變量(INDEX1、INDEX2、INDEX3),來存儲(chǔ)和使用這些值。
- INDEX1=$(echo ${arr[0]}),將數(shù)組 arr 的第一個(gè)元素(索引為 0)賦值給變量 INDEX1。
- INDEX2=$(echo ${arr[1]}),將數(shù)組 arr 的第二個(gè)元素(索引為 1)賦值給變量 INDEX2。
- INDEX3=$(echo ${arr[2]}),將數(shù)組 arr 的第三個(gè)元素(索引為 2)賦值給變量 INDEX3。
通過這種方式,變量 INDEX1、INDEX2 和 INDEX3 將分別包含數(shù)組 arr 中對(duì)應(yīng)索引位置的值。
24、批量修改文件名
示例:
# 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 # 循環(huán)遍歷當(dāng)前目錄下以 html 結(jié)尾的文件mv $file bbs_${file#*_} # 將文件名修改為 bbs_ 后加上原文件名中第一個(gè)下劃線后的部分# 同等效果的替代方法1:# mv $file $(echo $file |sed -r 's/.*(_.*)/bbs\1/')# 同等效果的替代方法2:# mv $file $(echo $file |echo bbs_$(cut -d_ -f2)
done
這段代碼的作用是遍歷當(dāng)前目錄下以 .html 結(jié)尾的文件,并將文件名進(jìn)行修改。
- for file in $(ls *html),使用 *html 通配符來查找當(dāng)前目錄下以 .html 結(jié)尾的文件,并逐個(gè)進(jìn)行處理。
- mv $ file bbs_$ {file#},使用 mv 命令將文件名修改為 bbs 后再加上原文件名第一個(gè)下劃線后的部分。${file#_} 是一種字符串截取的方式,表示獲取變量 file 中第一個(gè)下劃線后的部分。
-
替代方法1:mv $file $(echo $file |sed -r 's/*(_.* )/bbs\1/'),使用 sed 命令進(jìn)行正則表達(dá)式的替換操作,將文件名中的第一個(gè)下劃線及其后的部分替換為 bbs_ 加上對(duì)應(yīng)的部分。
-
替代方法2:mv $ file $ (echo $ file |echo bbs_$(cut -d_ -f2),使用 cut 命令提取文件名中第一個(gè)下劃線后的部分,然后將其拼接為 bbs_ 加上對(duì)應(yīng)的部分。
這段代碼的目的是對(duì)當(dāng)前目錄下以 .html 結(jié)尾的文件進(jìn)行批量重命名,將文件名修改為以 bbs_ 開頭并保留原文件名中第一個(gè)下劃線后的部分。
方法2:
for file in $(find . -maxdepth 1 -name "*html"); do # 使用 find 命令查找當(dāng)前目錄下的以 html 結(jié)尾的文件mv $file bbs_${file#*_} # 將文件名修改為 bbs_ 后加上原文件名中第一個(gè)下劃線后的部分
done
這段代碼的作用是在當(dāng)前目錄下查找以 .html 結(jié)尾的文件,并將這些文件的文件名進(jìn)行修改。
- . -maxdepth 1 -name “*html”,使用 find 命令在當(dāng)前目錄下查找滿足以下條件的文件:
- -maxdepth 1:僅在當(dāng)前目錄進(jìn)行查找,不遞歸查找子目錄。
- -name “*html”:文件名以 .html 結(jié)尾。
- for file in $(find . -maxdepth 1 -name “*html”),將查找到的文件列表循環(huán)處理。
- mv $ file bbs_$ {file#},使用 mv 命令將文件名修改為 bbs 后再加上原文件名中第一個(gè)下劃線后的部分。${file#_} 是一種字符串截取的方式,表示獲取變量 file 中第一個(gè)下劃線后的部分。
- 例如文件名為 prefix_filename.html,那么 ${file#*_} 的值就是 filename.html,然后將文件名修改為 bbs_filename.html。
這段代碼的目的是在當(dāng)前目錄下查找以 .html 結(jié)尾的文件,并將這些文件的文件名批量修改為以 bbs_ 開頭并保留原文件名中第一個(gè)下劃線后的部分。
方法3:
# rename article bbs *.html
這段代碼使用了 rename 命令,對(duì)當(dāng)前目錄下以 .html 結(jié)尾的文件進(jìn)行批量重命名。
- rename 命令用于批量重命名文件名中的指定部分。
- article 是要被替換的部分,bbs 是替換后的部分。
- *.html 是要進(jìn)行重命名操作的文件匹配模式,表示當(dāng)前目錄下所有以 .html 結(jié)尾的文件。
這段代碼的目的是將當(dāng)前目錄下以 .html 結(jié)尾的文件名中的 article 替換為 bbs,實(shí)現(xiàn)文件名的批量重命名操作。
25、統(tǒng)計(jì)當(dāng)前目錄中以.html結(jié)尾的文件總大
方法1:
# find . -name "*.html" -exec du -k {} \; |awk '{sum+=$1}END{print sum}'
這段代碼使用了find命令、du命令和awk命令來計(jì)算當(dāng)前目錄下以.html結(jié)尾的文件的總大小(以KB為單位)。
- find . -name “*.html”:使用find命令在當(dāng)前目錄及其子目錄下查找文件名以.html結(jié)尾的文件。
- -exec du -k {} ;:對(duì)于每個(gè)找到的文件,使用du -k命令以KB為單位顯示文件大小。通過-exec選項(xiàng)和{}占位符將找到的文件傳遞給du命令進(jìn)行處理。
- |:使用管道(pipe)將du命令的輸出傳遞給下一個(gè)命令。
- awk ‘{sum+=$1}END{print sum}’:使用awk命令對(duì)du命令的輸出進(jìn)行處理,計(jì)算文件大小的總和。awk命令中的代碼逐行讀取du命令的輸出,并將每一行的第一個(gè)字段(文件大小)累加到變量sum中。最后,在處理完所有行后,在END部分使用print sum打印出總和。
這段代碼的目的是計(jì)算當(dāng)前目錄下以.html結(jié)尾的文件的總大小(以KB為單位)。
方法2:
for size in $(ls -l *.html | awk '{print $5}'); do # 獲取當(dāng)前目錄下以 .html 結(jié)尾的文件的大小列表sum=$(($sum+$size)) # 對(duì)每個(gè)文件的大小進(jìn)行累加
done
echo $sum # 打印所有文件大小的總和
這段代碼的作用是計(jì)算當(dāng)前目錄下以 .html 結(jié)尾的文件的總大小(以字節(jié)為單位)。
- ls -l *.html | awk ‘{print $5}’:使用 ls -l 命令獲取當(dāng)前目錄下以 .html 結(jié)尾的文件的詳細(xì)列表,并通過管道將結(jié)果傳遞給 awk 命令。awk ‘{print $5}’ 表示只輸出每行的第五個(gè)字段(文件大小)。
- for size in $(ls -l *.html | awk ‘{print $5}’):將獲取到的文件大小列表逐個(gè)賦值給變量 size 進(jìn)行循環(huán)處理。
- sum=$ (($ sum+$ size)):將每個(gè)文件的大小累加到變量 sum 中。$ sum+$ size 表示將變量 sum 和 size 的值相加。$((…)) 是一種算術(shù)表達(dá)式的寫法。
- echo $sum:打印所有文件大小的總和。
這段代碼的目的是計(jì)算當(dāng)前目錄下以 .html 結(jié)尾的文件的總大小(以字節(jié)為單位),將每個(gè)文件的大小累加到變量 sum 中,并最后打印出總和。
26、掃描主機(jī)端口狀態(tài)
#!/bin/bash
HOST=$1 # 獲取第一個(gè)命令行參數(shù),作為主機(jī)名或 IP 地址
PORT="22 25 80 8080" # 定義要檢測(cè)的端口列表for PORT in $PORT; do # 遍歷端口列表if echo &>/dev/null > /dev/tcp/$HOST/$PORT; then # 使用 /dev/tcp 文件系統(tǒng),嘗試與指定的主機(jī)和端口建立 TCP 連接echo "$PORT open" # 如果 TCP 連接成功,則輸出端口為開放狀態(tài)elseecho "$PORT close" # 如果 TCP 連接失敗,則輸出端口為關(guān)閉狀態(tài)fi
done
這段代碼的作用是檢測(cè)指定主機(jī)的一些常見端口是否開放。
- #!/bin/bash:指定該腳本以 Bash 解釋器運(yùn)行。
- HOST=$1:將第一個(gè)命令行參數(shù)賦值給變量 HOST,表示要檢測(cè)的主機(jī)名或 IP 地址。
- PORT=“22 25 80 8080”:定義要檢測(cè)的端口列表,包括 22、25、80 和 8080。
- for PORT in $PORT; do:遍歷端口列表。
- if echo &>/dev/null > /dev/tcp/$ HOST/$PORT; then:使用 /dev/tcp 文件系統(tǒng),嘗試與指定的主機(jī)和端口建立 TCP 連接。通過重定向輸入輸出到 /dev/null 來實(shí)現(xiàn)靜默連接的效果。
- echo “$PORT open”:如果 TCP 連接成功,則輸出該端口為開放狀態(tài)。
- echo “$PORT close”:如果 TCP 連接失敗,則輸出該端口為關(guān)閉狀態(tài)。
這段代碼的目的是遍歷指定主機(jī)的端口列表,并嘗試與每個(gè)端口建立 TCP 連接,通過輸出端口狀態(tài)來告知該端口是否開放。
27、Expect實(shí)現(xiàn)SSH免交互執(zhí)行命令
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 # 設(shè)置要登錄的遠(yuǎn)程主機(jī)的用戶名
PASS=123.com # 設(shè)置遠(yuǎn)程主機(jī)用戶的登錄密碼
IP=192.168.1.120 # 設(shè)置遠(yuǎn)程主機(jī)的 IP 地址expect << EOF # 使用 expect 來編寫自動(dòng)化交互腳本
set timeout 30 # 設(shè)置超時(shí)時(shí)間為 30 秒spawn ssh $USER@$IP # 使用 spawn 命令啟動(dòng) ssh 進(jìn)行遠(yuǎn)程登錄連接expect {"(yes/no)" {send "yes\r"; exp_continue} # 如果出現(xiàn) "(yes/no)" 提示,自動(dòng)發(fā)送 "yes" 并繼續(xù)等待"password:" {send "$PASS\r"} # 如果出現(xiàn) "password:" 提示,自動(dòng)發(fā)送密碼進(jìn)行登錄
}expect "$USER@*" {send "$1\r"} # 在成功登錄后,根據(jù)需要執(zhí)行的操作,這里發(fā)送了一個(gè) $1 變量
expect "$USER@*" {send "exit\r"} # 執(zhí)行完操作后,發(fā)送 "exit" 命令退出登錄
expect eof # 等待所有交互完成后,終止 expect 腳本
EOF
這段代碼使用了 expect 工具編寫了一個(gè)自動(dòng)化交互腳本,用于實(shí)現(xiàn)通過 SSH 遠(yuǎn)程登錄到指定主機(jī),并執(zhí)行一些操作。
- USER=root:將要登錄的遠(yuǎn)程主機(jī)的用戶名設(shè)置為 root。
- PASS=123.com:將遠(yuǎn)程主機(jī)用戶的登錄密碼設(shè)置為 123.com。
- IP=192.168.1.120:設(shè)置遠(yuǎn)程主機(jī)的 IP 地址為 192.168.1.120。
在 expect 命令的使用過程中:
- set timeout 30:設(shè)置超時(shí)時(shí)間為 30 秒,用于控制登錄的等待時(shí)間。
- spawn ssh U S E R @ USER@ USER@IP:使用 spawn 命令啟動(dòng) ssh 進(jìn)程進(jìn)行遠(yuǎn)程登錄連接。
- expect 塊中使用模式匹配來等待特定的交互信息,并根據(jù)不同的提示進(jìn)行相應(yīng)的操作。
- send 命令用于向程序發(fā)送輸入信息,完成自動(dòng)化交互。
- $1 是一個(gè)變量,它被發(fā)送給遠(yuǎn)程主機(jī)以執(zhí)行特定操作。
- expect eof:等待所有交互完成后,終止 expect 腳本。
這段代碼的目的是使用 expect 實(shí)現(xiàn)自動(dòng)化登錄遠(yuǎn)程主機(jī),并在登錄后執(zhí)行指定的操作。
方法2:
#!/bin/bash
USER=root # 設(shè)置要登錄的遠(yuǎn)程主機(jī)的用戶名
PASS=123.com # 設(shè)置遠(yuǎn)程主機(jī)的登錄密碼
IP=192.168.1.120 # 設(shè)置遠(yuǎn)程主機(jī)的 IP 地址expect -c " # 使用 expect 命令編寫內(nèi)聯(lián)腳本spawn ssh $USER@$IP # 使用 spawn 命令啟動(dòng) ssh 進(jìn)程進(jìn)行遠(yuǎn)程登錄連接expect {\"(yes/no)\" {send \"yes\r\"; exp_continue} # 如果出現(xiàn) "(yes/no)" 提示,自動(dòng)發(fā)送 "yes" 并繼續(xù)等待\"password:\" {send \"$PASS\r\"; exp_continue} # 如果出現(xiàn) "password:" 提示,自動(dòng)發(fā)送密碼并繼續(xù)等待\"$USER@*\" {send \"df -h\r exit\r\"; exp_continue} # 如果成功登錄,發(fā)送 "df -h" 命令查看磁盤使用情況,并發(fā)送 "exit" 命令退出登錄}"
這段代碼使用了 expect 工具以內(nèi)聯(lián)腳本的方式編寫,實(shí)現(xiàn)了通過 SSH 登錄到指定主機(jī),并執(zhí)行特定命令的自動(dòng)化操作。
- USER=root:將要登錄的遠(yuǎn)程主機(jī)的用戶名設(shè)置為 root。
- PASS=123.com:將遠(yuǎn)程主機(jī)的登錄密碼設(shè)置為 123.com。
- IP=192.168.1.120:設(shè)置遠(yuǎn)程主機(jī)的 IP 地址為 192.168.1.120。
在 expect -c 命令中:
- spawn ssh $ USER@$IP:使用 spawn 命令啟動(dòng) ssh 進(jìn)程進(jìn)行遠(yuǎn)程登錄連接。
- expect 塊中使用模式匹配來等待特定的交互信息,并根據(jù)不同的提示進(jìn)行相應(yīng)的操作。
- send 命令用于向程序發(fā)送輸入信息,完成自動(dòng)化交互。
- “(yes/no)” {send “yes\r”; exp_continue}:如果出現(xiàn) “(yes/no)” 提示,自動(dòng)發(fā)送 “yes” 并繼續(xù)等待。
- “password:” {send “$PASS\r”; exp_continue}:如果出現(xiàn) “password:” 提示,自動(dòng)發(fā)送密碼并繼續(xù)等待。
- “$USER@*” {send “df -h\r exit\r”; exp_continue}:如果成功登錄,則發(fā)送 “df -h” 命令查看磁盤使用情況,并發(fā)送 “exit” 命令退出登錄。
- exp_continue:使 expect 繼續(xù)等待下一個(gè)匹配。
這段代碼的目的是通過 expect 實(shí)現(xiàn)自動(dòng)化登錄遠(yuǎn)程主機(jī),并在登錄后執(zhí)行特定命令,如查看磁盤使用情況,并最后退出登錄。
28、批量修改服務(wù)器用戶密碼
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ī)生成
#!/bin/bash
OLD_INFO=old_pass.txt # 存儲(chǔ)舊密碼信息的文件路徑
NEW_INFO=new_pass.txt # 存儲(chǔ)新密碼信息的文件路徑for IP in $(awk '/^[^#]/{print $1}' $OLD_INFO); do # 使用 awk 命令遍歷獲取每行的 IP 地址USER=$(awk -v I=$IP 'I==$1{print $2}' $OLD_INFO) # 根據(jù) IP 地址獲取對(duì)應(yīng)的用戶名PASS=$(awk -v I=$IP 'I==$1{print $3}' $OLD_INFO) # 根據(jù) IP 地址獲取對(duì)應(yīng)的密碼PORT=$(awk -v I=$IP 'I==$1{print $4}' $OLD_INFO) # 根據(jù) IP 地址獲取對(duì)應(yīng)的端口號(hào)NEW_PASS=$(mkpasswd -l 8) # 使用 mkpasswd 命令生成一個(gè)具有 8 個(gè)字符長(zhǎng)度的隨機(jī)密碼echo "$IP $USER $NEW_PASS $PORT" >> $NEW_INFO # 將新的密碼信息追加到新密碼文件中expect -c "spawn ssh -p$PORT $USER@$IP # 使用 spawn 命令啟動(dòng) ssh 進(jìn)程進(jìn)行遠(yuǎn)程登錄連接set timeout 2 # 設(shè)置超時(shí)時(shí)間為 2 秒expect {\"(yes/no)\" {send \"yes\r\"; exp_continue} # 如果出現(xiàn) "(yes/no)" 提示,自動(dòng)發(fā)送 "yes" 并繼續(xù)等待\"password:\" {send \"$PASS\r\"; exp_continue} # 如果出現(xiàn) "password:" 提示,自動(dòng)發(fā)送舊密碼并繼續(xù)等待\"$USER@*\" {send \"echo \'$NEW_PASS\' | passwd --stdin $USER\r exit\r\"; exp_continue} # 如果成功登錄,發(fā)送命令將新密碼設(shè)置為隨機(jī)生成的新密碼,并發(fā)送 "exit" 命令退出登錄}"
done
生成新密碼文件:
# cat new_pass.txt
192.168.18.217 root n8wX3mU% 22
192.168.18.218 root c87;ZnnL 22
29、打印九九乘法口訣
for ((i=1;i<=9;i++)); do # 外層循環(huán),控制行數(shù),從 1 到 9for ((j=1;j<=i;j++)); do # 內(nèi)層循環(huán),控制每行的乘法表達(dá)式,從 1 到當(dāng)前行數(shù)result=$(($i*$j)) # 計(jì)算乘法結(jié)果echo -n "$j*$i=$result " # 打印乘法表達(dá)式和結(jié)果,不換行doneecho # 內(nèi)層循環(huán)結(jié)束后換行
done
這段代碼的作用是打印一個(gè)簡(jiǎn)單的乘法表,從 1 到 9,按行輸出。
在外層循環(huán)中,i 控制當(dāng)前行數(shù),從 1 到 9 逐漸增加。
在內(nèi)層循環(huán)中,j 控制每行的乘法表達(dá)式,從 1 到當(dāng)前行數(shù) 逐漸增加。
在每次內(nèi)層循環(huán)中,計(jì)算乘法結(jié)果 result 的值,并使用 echo -n 打印乘法表達(dá)式和結(jié)果,不換行。
內(nèi)層循環(huán)結(jié)束后,使用 echo 單獨(dú)打印一個(gè)換行符,換行后進(jìn)入下一行的循環(huán)。
這段代碼的輸出結(jié)果是一個(gè)九九乘法表。
30、斐波那契數(shù)列
#!/bin/bashecho "請(qǐng)輸入斐波那契數(shù)列的長(zhǎng)度:"
read length # 獲取用戶輸入的斐波那契數(shù)列長(zhǎng)度# 初始化前兩個(gè)斐波那契數(shù)
num1=0 # 第一個(gè)斐波那契數(shù)為 0
num2=1 # 第二個(gè)斐波那契數(shù)為 1# 輸出前兩個(gè)數(shù)
echo "斐波那契數(shù)列的前 $length 個(gè)數(shù)為:"
echo -n "$num1 $num2" # 輸出第一個(gè)和第二個(gè)斐波那契數(shù)# 循環(huán)計(jì)算并輸出斐波那契數(shù)列
for ((i=2;i<$length;i++))
dosum=$(($num1 + $num2)) # 計(jì)算下一個(gè)斐波那契數(shù)echo -n " $sum" # 輸出計(jì)算得到的斐波那契數(shù)num1=$num2 # 更新第一個(gè)斐波那契數(shù)為當(dāng)前的第二個(gè)斐波那契數(shù)num2=$sum # 更新第一個(gè)斐波那契數(shù)為當(dāng)前的計(jì)算結(jié)果
doneecho "" # 輸出換行符,使結(jié)果美觀
這段代碼的作用是根據(jù)用戶輸入的長(zhǎng)度,生成并輸出相應(yīng)長(zhǎng)度的斐波那契數(shù)列。
- echo “請(qǐng)輸入斐波那契數(shù)列的長(zhǎng)度:”:提示用戶輸入斐波那契數(shù)列的長(zhǎng)度。
- read length:將用戶輸入的長(zhǎng)度保存到變量 length 中。
通過循環(huán)計(jì)算斐波那契數(shù)列,并輸出結(jié)果:
- num1 和 num2 分別用于保存當(dāng)前計(jì)算的斐波那契數(shù)列的前兩個(gè)數(shù)。
- 使用 echo -n 輸出前兩個(gè)數(shù)。
- 利用循環(huán)計(jì)算出剩余的斐波那契數(shù),并使用 echo -n 輸出結(jié)果。
- 在每次循環(huán)中,更新 num1 和 num2 的值,并繼續(xù)計(jì)算下一個(gè)斐波那契數(shù)。