本文鏈接:個(gè)人站 | 簡(jiǎn)書(shū) | CSDN
版權(quán)聲明:除特別聲明外副签,本博客文章均采用 BY-NC-SA 許可協(xié)議帆疟。轉(zhuǎn)載請(qǐng)注明出處。
重啟服務(wù)之前往往需要檢查一下是否還有未處理完的請(qǐng)求。此時(shí)可以使用 ss
命令查看端口是否還有 TCP 連接施流。例如:
pi@raspberrypi:~ $ ss -nt state established src 192.168.1.26:8888
Recv-Q Send-Q Local Address:Port Peer Address:Port
0 0 192.168.1.26:8888 192.168.1.25:50390
我們可以統(tǒng)計(jì)這條命令輸出的行數(shù),若小于 2鄙信,則說(shuō)明服務(wù)已經(jīng)處于閑置狀態(tài)瞪醋。腳本如下:
#!/bin/bash
# 獲取本機(jī) IP
host=$(ifconfig -a | grep inet | grep -v 127.0.0.1 | grep -v inet6 | awk '{print $2}' | tr -d "addr:")
# 超時(shí)時(shí)間
timeout=3600
check(){
port="$1"
begin=$(date +'%s')
while true
do
current=$(date +'%s')
duration=$(($current-$begin))
if [[ $duration -gt $timeout ]]; then
# 超時(shí)退出
result="TIMEOUT"
code=1
break
count=$(ss -nt state established src $host:$port | wc -l)
if [[ $count -lt 2 ]]; then
# 閑置退出
result="IDLE"
code=0
break
else
sleep 2
fi
done
echo "the result is $result"
return $code
}
if [[ $# -ne 1 ]]; then
echo "Usage: $0 [port]"
exit 1
else
check "$1"
exit $?
fi
如果 ss
命令發(fā)生錯(cuò)誤怎么辦?為了進(jìn)一步完善腳本装诡,我們需要加入異常處理機(jī)制银受。bash
中沒(méi)有 try...catch..
之類(lèi)的語(yǔ)法,那么該如何捕獲異常呢鸦采?下面介紹兩個(gè)特殊的寫(xiě)法:
-
command1 || command2
:當(dāng)且僅當(dāng)command1
發(fā)生錯(cuò)誤時(shí)執(zhí)行command2
宾巍。 -
command1 && command2
:當(dāng)且僅當(dāng)command1
沒(méi)有錯(cuò)誤時(shí)執(zhí)行command2
。
利用上面這兩個(gè)特性赖淤,我們引入異常處理蜀漆,把腳本改寫(xiě)成:
#!/bin/bash
set -o pipefail
# 獲取本機(jī) IP
host=$(ifconfig -a | grep inet | grep -v 127.0.0.1 | grep -v inet6 | awk '{print $2}' | tr -d "addr:")
# 超時(shí)時(shí)間
timeout=3600
check(){
port="$1"
begin=$(date +'%s')
while true
do
current=$(date +'%s')
duration=$(($current-$begin))
if [[ $duration -gt $timeout ]]; then
# 超時(shí)退出
result="TIMEOUT"
code=1
break
{
count=$(ss -nt state established src $host:$port | wc -l) &&
if [[ $count -lt 2 ]]; then
# 閑置退出
result="IDLE"
code=0
break
else
sleep 2
fi
}||{
# 異常退出
result="ERROR"
code=1
break
}
done
echo "the result is $result"
return $code
}
if [[ $# -ne 1 ]]; then
echo "Usage: $0 [port]"
exit 1
else
check "$1"
exit $?
fi
ss -nt state established src $host:$port | wc -l
利用了管道,而默認(rèn)情況下咱旱,前面的 ss
命令出錯(cuò)并不會(huì)影響后面的 wc
命令的執(zhí)行确丢。為了捕獲管道中的錯(cuò)誤,我們?cè)谀_本開(kāi)頭添加了 set -o pipefail
吐限。
現(xiàn)在我們的腳本可以檢測(cè)一個(gè)服務(wù)實(shí)例是否閑置鲜侥。如果我們需要同時(shí)檢查多個(gè)實(shí)例該怎么辦?如果可以并行地執(zhí)行我們的 check
函數(shù)就好了诸典。我們知道描函,在一條命令后面加上 &
,就可以將它放到子 shell 中執(zhí)行狐粱,達(dá)到多線(xiàn)程的效果舀寓。進(jìn)一步地,我們可以用 wait
命令實(shí)現(xiàn)多線(xiàn)程同步肌蜻』ツ梗基于此,我們給出可以同時(shí)檢查多個(gè)實(shí)例的 check_all
函數(shù):
check_all(){
ports="$#"
anyfailed=0
for port in $ports
do
check $port &
done
for pid in $(jobs -p)
do
wait $pid
if [[ $? -ne 0 ]]; then
anyfailed=1
fi
done
return $anyfailed
}