Reputation: 379
I am using the following script to count the number of connections in established, and time wait state for a specific range of TCP ports.
The script uses netstat and egrep to try and filter out valid connections. The script also reads input from a file and counts the number of connections observed.
#!/bin/bash
START=121
END=9089
[ -f /tmp/ports.txt ] && rm -f /tmp/ports.txt
for ((a=$START; a <= $END; a++)); do
netstat -an | nawk '/TIME_WAIT|ESTABLISHED/ && !/127.0.0.1/{split($4,a,".");print a[5]}' | egrep -c ^${a}$ | \
awk -v x=$a '\
$0 != 0 {printf("%d %d\n",x,$0)}' | tee -a /tmp/ports.txt
done
awk -v s=$START -v e=$END '\
BEGIN{t=0}
{t=t+$2}
END{printf("\nTotal Connections on ports %d-%d: %d\n",s,e,t)}' /tmp/ports.txt
rm -f /tmp/ports.txt
I'm looking for ways to improve the performance of the script. With the current range of ports (121-9089) it takes about 77 seconds to finish.
I'm looking for suggestions for improving the performance along with an example script.
Upvotes: 2
Views: 4443
Reputation: 379
Birei, using your example above, the script has been changed slightly.
#!/bin/bash
OS=$(uname)
case "$OS" in
'SunOS')
AWK=/usr/bin/nawk
;;
'Linux')
AWK=/bin/awk
;;
'AIX')
AWK=/usr/bin/awk
;;
esac
netstat -an | $AWK -v start=1 -v end=65535 ' $NF ~ /TIME_WAIT|ESTABLISHED/ && $4 !~ /127\.0\.0\.1/ {
if ($1 ~ /\./)
{sip=$1}
else {sip=$4}
if ( sip ~ /:/ )
{d=2}
else {d=5}
split( sip, a, /:|\./ )
if ( a[d] >= start && a[d] <= end ) {
++connections;
}
}
END {print connections}'
We are using this with our network monitoring tool. (zabbix) I have tested the script with solaris 10, Linux 6.3 and AIX 7, and the script works as intended and accounts for the differences in the way netstat outputs it's columns and for the difference in delimeter characters. I.E. the . or the : appearing in either the 2nd or 4th columns. It checks to see if the first column contains a . and sets the variable sip accordingly, and then determines if a : or a . is used as the port separator character.
The rest is much the same.
Thank you for your example!
Upvotes: 2
Reputation: 36262
One way:
netstat -an |
awk -v start=121 -v end=9089 '
$NF ~ /TIME_WAIT|ESTABLISHED/ && $4 !~ /127\.0\.0\.1/ {
split( $4, a, /:/ );
if ( a[2] >= start && a[2] <= end ) {
++connections;
}
}
END {
printf("\nTotal Connections on ports %d-%d: %d\n", start, end, connections );
}
'
Upvotes: 1
Reputation: 19788
You are running netstat -an
over 8000 times and extracting only one port at a time.
I would change your main loop with a different logic:
netstat -na | grep -E "TIME_WAIT|ESTABLISHED" | while read line; do
port=`echo $line | awk -F":" ' { print $2 }' | awk ' { print $1 }'` #<--- get here your port
[ $port -ge $START ] && [ $port -le $END ] && echo $line | tee -a /tmp/ports.txt #<---- put only the selected range
done
This way you will netstat
only once.
Note that you'll need to change the awk
logic in my example.
Upvotes: 3