文档库 最新最全的文档下载
当前位置:文档库 › Shell脚本编程,生成TCP活动状况报告

Shell脚本编程,生成TCP活动状况报告

Shell脚本编程,生成TCP活动状况报告
Shell脚本编程,生成TCP活动状况报告

LINUX编程环境实验报告2

——B-Shell及编程

班级:2012211307 姓名:LZ

写在前面

亲爱的学弟/学妹,如果你正因为本次实验而困惑,希望你在看完本文后会帮你解惑。但并不希望你直接copy后上交,自己亲手做实验而得到的提升是只有做完实验才知道的,而且可能会发现一些有意思的问题。相信这次实验也不会花费太长时间。加油,少年~

一、实验内容

Shell脚本编程,生成TCP活动状况报告。 netstat --statistics --tcp命令可以列出tcp统计信息。编写shell脚本程序,每隔1分钟生成1行信息:当前时间;这一分钟内TCP发送了多少报文;接收了多少报文;收发报文总数;行尾给出符号+或-或空格(+表示这分钟收发报文总数比上分钟多,收发报文总数相同用空格,否则用符号-)。运行示例如下:

观察示例后,又发现了两个需要注意的细节:

①第一行的最后一个参数必定是空格;

②输出要对齐

此外,在实验中发现netstat --statistics –tcp命令的收发报文数所在的行数是变动的,受ICMPMSG长度的影响。但本程序可以做到不受变动行数的影响,准确提取收发报文数。详情将在第三、3和第四部分阐述。

二、实验步骤及分析

经过分析,该程序分4步完成:每隔1分钟生成一行信息、当前时间、一分钟内首发报文数及收发总数和根据收发总数的变化行尾给出符号+或-或空格。下面,将针对这4个步骤分别进行阐述。

1.每隔1分钟生成1行信息

要实现这点,只需要一个简单的循环结构即可:

while true

do

echo “……”

sleep 60

done

2.当前时间

使用date命令的格式化输出。%F是以xxxx-xx-xx的形式打印年月日;%H是两位数长的24小时的小时数;%M为分钟数。打印效果如下:

3.这一分钟内TCP收、发报文数以及收发报文总数

首先,使用netstat --statistics –tcp命令查看命令的格式:

可见,所需的数据被白框圈出,当前累计的收发报文数分别在第10和第11行。可以使用AWK命令进行提取,条件为NR == 10 和NR == 11 ,每行都是提取第一个变量,即$1。所以使用语句:

recieve_total_before=$(netstat --statistics --tcp | awk 'NR == 10{print $1}')

send_total_before=$(netstat --statistics --tcp | awk 'NR == 11{print $1}')

但是,在实践中发现,所需的两个数据位置是不定的,受IcmpMsg长度的影响,有两种解决方案:①每次手动修改NR后面的值;②用segments received和segments send out匹配需要的行,然后提起该行的第一个变量。显然第2个解决方案是用户所期望的。所以,语句这样改正,即可实现准确提取收、发报文数而不受netstat命令变化的影响:

recieve_total_before=$(netstat --statistics --tcp | awk '$2$3~/segmentsreceived/{print $1}') send_total_before=$(netstat --statistics --tcp | awk '$2$3$4~/segmentssendout/{print $1}')

这样,提取累计收、发报文数就完成了。但本次实验要求列出的数据是某一分钟内的。那么就在一分钟开始的时候记录一次累计收、发报文数;60秒后再记录一次累计收、发报文数。将两次记录相减就是一分钟内的收、发报文数;将一分钟内的收、发报文数相加,就是一分钟内的收发报文总数。

4.行尾给出符号+或-或空格

行尾符号是+、-或空格,取决于本分钟收发报文总数和前一分钟收发报文总数的大小关系:大为‘+’、相等为空格,否则为‘-’。所以,这部分代码如下:

if [ $total -gt $total_before ]

then

More='+'

elif [ $total -eq $total_before ]

then

More=' '

else

More='-'

fi

正如第一部分所述,本程序中的一个细节是第一行数据的尾部必为空格,所以将第一部分提到while循环之外,尾部直接输出空格。

三、实验结果

四、问题与解决

1.问题: 程序刚开始是正常的,可以反应收、发报文数的变化,但后来

再调试的时候,数据全部为0。

解答:netstat --statistics –tcp命令中,收、发报文累计值所在行会发生变化,由IcmpMsg长度的变化引起。之前程序提取收、发报文累计值是用行数提取的。但后来行数发生了变化,提取的值是在这段时间不变的值,所以导致了上述情况。将提取策略改变后即可:

recieve_total_before=$(netstat --statistics --tcp | awk '$2$3~/segmentsreceived/{print $1}') send_total_before=$(netstat --statistics --tcp | awk '$2$3$4~/segmentssendout/{print $1}')

2.问题:程序的输出使用echo命令,不整齐怎么办?

解答:使用printf函数进行格式化输出即可。

printf "%-22s%-8s%-8s%-8s%-8s\n" "$DateandTime" "$recieve" "$send" "$total" "$More"

3.问题:这个地方为什么报错?

解答:if语句后,“[”和“ ]”需要和逻辑判断语句用空格隔开。

Shell中的空格十分十分重要!命令需要用空格来提取参数!

参考文献:

[1] 《实用UNIX教程》蒋砚军清华大学出版社

[2] 《LINUX Shell脚本编程入门》

[3] 《Unix shell脚本编程,生成TCP活动状况报告》

https://www.wendangku.net/doc/0b6638008.html,/link?url=qgCU4uuV_pjOf6tSoYVnBhPo2epZP-ILrA8wNTBGUnreF6c8e_Dxg PTOAPzJjPWkybKG7uU-K6PEy98biDAU8ls3K2lpHVuhu2bwpjjjxwG

附:源代码

DateandTime=$(date +"%F %H:%M")

recieve_total_before=$(netstat --statistics --tcp | awk '$2$3~/segmentsreceived/{print $1}') send_total_before=$(netstat --statistics --tcp | awk '$2$3$4~/segmentssendout/{print $1}')

sleep 60

recieve_total=$(netstat --statistics --tcp | awk '$2$3~/segmentsreceived/{print $1}')

send_total=$(netstat --statistics --tcp | awk '$2$3$4~/segmentssendout/{print $1}')

recieve=$(expr $recieve_total - $recieve_total_before)

send=$(expr $send_total - $send_total_before)

total=$(expr $recieve + $send)

total_before=$total

printf "%-22s%-8s%-8s%-8s\n" "$DateandTime" "$recieve" "$send" "$total"

while true

do

recieve_total_before=$(netstat --statistics --tcp | awk '$2$3~/segmentsreceived/{print $1}') send_total_before=$(netstat --statistics --tcp | awk '$2$3$4~/segmentssendout/{print $1}')

sleep 60

DateandTime=$(date +"%F %H:%M")

recieve_total=$(netstat --statistics --tcp | awk '$2$3~/segmentsreceived/{print $1}')

send_total=$(netstat --statistics --tcp | awk '$2$3$4~/segmentssendout/{print $1}')

recieve=$(expr $recieve_total - $recieve_total_before)

send=$(expr $send_total - $send_total_before)

total=$(expr $recieve + $send)

if [ $total -gt $total_before ]

then

More='+'

elif [ $total -eq $total_before ]

then

More=' '

else

More='-'

fi

total_before=$total

printf "%-22s%-8s%-8s%-8s%-8s\n" "$DateandTime" "$recieve" "$send" "$total" "$More" done

相关文档