1 #!/bin/bash
2
3 #write by zhumaohai(admin#centos.bz)
4 #author blog: www.centos.bz
5
6
7 #显示菜单(单选)
8 display_menu(){
9 local soft=$1
10 local prompt="which ${soft} you'd select: "
11 eval local arr=(\${${soft}_arr[@]})
12 while true
13 do
14 echo -e "#################### ${soft} setting ####################\n\n"
15 for ((i=1;i<=${#arr[@]};i++ )); do echo -e "$i) ${arr[$i-1]}"; done
16 echo
17 read -p "${prompt}" $soft
18 eval local select=\$$soft
19 if [ "$select" == "" ] || [ "${arr[$soft-1]}" == "" ];then
20 prompt="input errors,please input a number: "
21 else
22 eval $soft=${arr[$soft-1]}
23 eval echo "your selection: \$$soft"
24 break
25 fi
26 done
27 }
28
29 #把带宽bit单位转换为人类可读单位
30 bit_to_human_readable(){
31 #input bit value
32 local trafficValue=$1
33
34 if [[ ${trafficValue%.*} -gt 922 ]];then
35 #conv to Kb
36 trafficValue=`awk -v value=$trafficValue 'BEGIN{printf "%0.1f",value/1024}'`
37 if [[ ${trafficValue%.*} -gt 922 ]];then
38 #conv to Mb
39 trafficValue=`awk -v value=$trafficValue 'BEGIN{printf "%0.1f",value/1024}'`
40 echo "${trafficValue}Mb"
41 else
42 echo "${trafficValue}Kb"
43 fi
44 else
45 echo "${trafficValue}b"
46 fi
47 }
48
49 #判断包管理工具
50 check_package_manager(){
51 local manager=$1
52 local systemPackage=''
53 if cat /etc/issue | grep -q -E -i "ubuntu|debian";then
54 systemPackage='apt'
55 elif cat /etc/issue | grep -q -E -i "centos|red hat|redhat";then
56 systemPackage='yum'
57 elif cat /proc/version | grep -q -E -i "ubuntu|debian";then
58 systemPackage='apt'
59 elif cat /proc/version | grep -q -E -i "centos|red hat|redhat";then
60 systemPackage='yum'
61 else
62 echo "unkonw"
63 fi
64
65 if [ "$manager" == "$systemPackage" ];then
66 return 0
67 else
68 return 1
69 fi
70 }
71
72
73 #实时流量
74 realTimeTraffic(){
75 local eth=""
76 local nic_arr=(`ifconfig | grep -E -o "^[a-z0-9]+" | grep -v "lo" | uniq`)
77 local nicLen=${#nic_arr[@]}
78 if [[ $nicLen -eq 0 ]]; then
79 echo "sorry,I can not detect any network device,please report this issue to author."
80 exit 1
81 elif [[ $nicLen -eq 1 ]]; then
82 eth=$nic_arr
83 else
84 display_menu nic
85 eth=$nic
86 fi
87
88 local clear=true
89 local eth_in_peak=0
90 local eth_out_peak=0
91 local eth_in=0
92 local eth_out=0
93
94 while true;do
95 #移动光标到0:0位置
96 printf "\033[0;0H"
97 #清屏并打印Now Peak
98 [[ $clear == true ]] && printf "\033[2J" && echo "$eth--------Now--------Peak-----------"
99 traffic_be=(`awk -v eth=$eth -F'[: ]+' '{if ($0 ~eth){print $3,$11}}' /proc/net/dev`)
100 sleep 2
101 traffic_af=(`awk -v eth=$eth -F'[: ]+' '{if ($0 ~eth){print $3,$11}}' /proc/net/dev`)
102 #计算速率
103 eth_in=$(( (${traffic_af[0]}-${traffic_be[0]})*8/2 ))
104 eth_out=$(( (${traffic_af[1]}-${traffic_be[1]})*8/2 ))
105 #计算流量峰值
106 [[ $eth_in -gt $eth_in_peak ]] && eth_in_peak=$eth_in
107 [[ $eth_out -gt $eth_out_peak ]] && eth_out_peak=$eth_out
108 #移动光标到2:1
109 printf "\033[2;1H"
110 #清除当前行
111 printf "\033[K"
112 printf "%-20s %-20s\n" "Receive: $(bit_to_human_readable $eth_in)" "$(bit_to_human_readable $eth_in_peak)"
113 #清除当前行
114 printf "\033[K"
115 printf "%-20s %-20s\n" "Transmit: $(bit_to_human_readable $eth_out)" "$(bit_to_human_readable $eth_out_peak)"
116 [[ $clear == true ]] && clear=false
117 done
118 }
119
120 #流量和连接概览
121 trafficAndConnectionOverview(){
122 if ! which tcpdump > /dev/null;then
123 echo "tcpdump not found,going to install it."
124 if check_package_manager apt;then
125 apt-get -y install tcpdump
126 elif check_package_manager yum;then
127 yum -y install tcpdump
128 fi
129 fi
130
131 local reg=""
132 local eth=""
133 local nic_arr=(`ifconfig | grep -E -o "^[a-z0-9]+" | grep -v "lo" | uniq`)
134 local nicLen=${#nic_arr[@]}
135 if [[ $nicLen -eq 0 ]]; then
136 echo "sorry,I can not detect any network device,please report this issue to author."
137 exit 1
138 elif [[ $nicLen -eq 1 ]]; then
139 eth=$nic_arr
140 else
141 display_menu nic
142 eth=$nic
143 fi
144
145 echo "please wait for 20s to generate network data..."
146 echo
147 #当前流量值
148 local traffic_be=(`awk -v eth=$eth -F'[: ]+' '{if ($0 ~eth){print $3,$11}}' /proc/net/dev`)
149 #tcpdump监听网络
150 tcpdump -v -i $eth -tnn > /tmp/tcpdump_temp 2>&1 &
151 sleep 20
152 clear
153 kill `ps aux | grep tcpdump | grep -v grep | awk '{print $2}'`
154
155 #10s后流量值
156 local traffic_af=(`awk -v eth=$eth -F'[: ]+' '{if ($0 ~eth){print $3,$11}}' /proc/net/dev`)
157 #打印10s平均速率
158 local eth_in=$(( (${traffic_af[0]}-${traffic_be[0]})*8/10 ))
159 local eth_out=$(( (${traffic_af[1]}-${traffic_be[1]})*8/10 ))
160 echo -e "\033[32mnetwork device $eth average traffic in 10s: \033[0m"
161 echo "$eth Receive: $(bit_to_human_readable $eth_in)/s"
162 echo "$eth Transmit: $(bit_to_human_readable $eth_out)/s"
163 echo
164
165 local regTcpdump=$(ifconfig | grep -A 1 $eth | awk -F'[: ]+' '$0~/inet addr:/{printf $4"|"}' | sed -e 's/|$//' -e 's/^/(/' -e 's/$/)\\\\\.[0-9]+:/')
166
167 #新旧版本tcpdump输出格式不一样,分别处理
168 if awk '/^IP/{print;exit}' /tmp/tcpdump_temp | grep -q ")$";then
169 #处理tcpdump文件
170 awk '/^IP/{print;getline;print}' /tmp/tcpdump_temp > /tmp/tcpdump_temp2
171 else
172 #处理tcpdump文件
173 awk '/^IP/{print}' /tmp/tcpdump_temp > /tmp/tcpdump_temp2
174 sed -i -r 's#(.*: [0-9]+\))(.*)#\1\n \2#' /tmp/tcpdump_temp2
175 fi
176
177 awk '{len=$NF;sub(/\)/,"",len);getline;print $0,len}' /tmp/tcpdump_temp2 > /tmp/tcpdump
178
179 #统计每个端口在10s内的平均流量
180 echo -e "\033[32maverage traffic in 10s base on server port: \033[0m"
181 awk -F'[ .:]+' -v regTcpdump=$regTcpdump '{if ($0 ~ regTcpdump){line="clients > "$8"."$9"."$10"."$11":"$12}else{line=$2"."$3"."$4"."$5":"$6" > clients"};sum[line]+=$NF*8/10}END{for (line in sum){printf "%s %d\n",line,sum[line]}}' /tmp/tcpdump | \
182 sort -k 4 -nr | head -n 10 | while read a b c d;do
183 echo "$a $b $c $(bit_to_human_readable $d)/s"
184 done
185 echo -ne "\033[11A"
186 echo -ne "\033[50C"
187 echo -e "\033[32maverage traffic in 10s base on client port: \033[0m"
188 awk -F'[ .:]+' -v regTcpdump=$regTcpdump '{if ($0 ~ regTcpdump){line=$2"."$3"."$4"."$5":"$6" > server"}else{line="server > "$8"."$9"."$10"."$11":"$12};sum[line]+=$NF*8/10}END{for (line in sum){printf "%s %d\n",line,sum[line]}}' /tmp/tcpdump | \
189 sort -k 4 -nr | head -n 10 | while read a b c d;do
190 echo -ne "\033[50C"
191 echo "$a $b $c $(bit_to_human_readable $d)/s"
192 done
193
194 echo
195
196 #统计在10s内占用带宽最大的前10个ip
197 echo -e "\033[32mtop 10 ip average traffic in 10s base on server: \033[0m"
198 awk -F'[ .:]+' -v regTcpdump=$regTcpdump '{if ($0 ~ regTcpdump){line=$2"."$3"."$4"."$5" > "$8"."$9"."$10"."$11":"$12}else{line=$2"."$3"."$4"."$5":"$6" > "$8"."$9"."$10"."$11};sum[line]+=$NF*8/10}END{for (line in sum){printf "%s %d\n",line,sum[line]}}' /tmp/tcpdump | \
199 sort -k 4 -nr | head -n 10 | while read a b c d;do
200 echo "$a $b $c $(bit_to_human_readable $d)/s"
201 done
202 echo -ne "\033[11A"
203 echo -ne "\033[50C"
204 echo -e "\033[32mtop 10 ip average traffic in 10s base on client: \033[0m"
205 awk -F'[ .:]+' -v regTcpdump=$regTcpdump '{if ($0 ~ regTcpdump){line=$2"."$3"."$4"."$5":"$6" > "$8"."$9"."$10"."$11}else{line=$2"."$3"."$4"."$5" > "$8"."$9"."$10"."$11":"$12};sum[line]+=$NF*8/10}END{for (line in sum){printf "%s %d\n",line,sum[line]}}' /tmp/tcpdump | \
206 sort -k 4 -nr | head -n 10 | while read a b c d;do
207 echo -ne "\033[50C"
208 echo "$a $b $c $(bit_to_human_readable $d)/s"
209 done
210
211 echo
212 #统计连接状态
213 local regSS=$(ifconfig | grep -A 1 $eth | awk -F'[: ]+' '$0~/inet addr:/{printf $4"|"}' | sed -e 's/|$//')
214 ss -an | grep -v -E "LISTEN|UNCONN" | grep -E "$regSS" > /tmp/ss
215 echo -e "\033[32mconnection state count: \033[0m"
216 awk 'NR>1{sum[$(NF-4)]+=1}END{for (state in sum){print state,sum[state]}}' /tmp/ss | sort -k 2 -nr
217 echo
218 #统计各端口连接状态
219 echo -e "\033[32mconnection state count by port base on server: \033[0m"
220 awk 'NR>1{sum[$(NF-4),$(NF-1)]+=1}END{for (key in sum){split(key,subkey,SUBSEP);print subkey[1],subkey[2],sum[subkey[1],subkey[2]]}}' /tmp/ss | sort -k 3 -nr | head -n 10
221 echo -ne "\033[11A"
222 echo -ne "\033[50C"
223 echo -e "\033[32mconnection state count by port base on client: \033[0m"
224 awk 'NR>1{sum[$(NF-4),$(NF)]+=1}END{for (key in sum){split(key,subkey,SUBSEP);print subkey[1],subkey[2],sum[subkey[1],subkey[2]]}}' /tmp/ss | sort -k 3 -nr | head -n 10 | awk '{print "\033[50C"$0}'
225 echo
226 #统计端口为80且状态为ESTAB连接数最多的前10个IP
227 echo -e "\033[32mtop 10 ip ESTAB state count at port 80: \033[0m"
228 cat /tmp/ss | grep ESTAB | awk -F'[: ]+' '{sum[$(NF-2)]+=1}END{for (ip in sum){print ip,sum[ip]}}' | sort -k 2 -nr | head -n 10
229 echo
230 #统计端口为80且状态为SYN-RECV连接数最多的前10个IP
231 echo -e "\033[32mtop 10 ip SYN-RECV state count at port 80: \033[0m"
232 cat /tmp/ss | grep -E "$regSS" | grep SYN-RECV | awk -F'[: ]+' '{sum[$(NF-2)]+=1}END{for (ip in sum){print ip,sum[ip]}}' | sort -k 2 -nr | head -n 10
233 }
234
235 main(){
236 while true; do
237 echo -e "1) real time traffic.\n2) traffic and connection overview.\n"
238 read -p "please input your select(ie 1): " select
239 case $select in
240 1) realTimeTraffic;break;;
241 2) trafficAndConnectionOverview;break;;
242 *) echo "input error,please input a number.";;
243 esac
244 done
245 }
246
247 main