我的目标是计算网站在前10个计数上的平均ping时间,计算第二个10个计数的平均值,并计算最后10个计数的平均值,并使用bash脚本一次打印它们。 到目前为止,我已经提出了以下脚本:
ping -c 30 google.com > pings.txt
sed 's/\=/= /g' pings.txt > formatted_op.txt
sed -n '2, 11p' formatted_op.txt > 1.txt
sed -n '12, 22p' formatted_op.txt > 2.txt
sed -n '22, 32p' formatted_op.txt > 3.txt
awk '{print $10}' 1.txt | awk '{ sum += $1 } END {print sum/10}' > 1_avg.txt
awk '{print $10}' 2.txt | awk '{ sum += $1 } END {print sum/10}' > 2_avg.txt
awk '{print $10}' 3.txt | awk '{ sum += $1 } END {print sum/10}' > 3_avg.txt
cat 1_avg.txt 2_avg.txt 3_avg.txt > final_avg.txt
cat final_avg.txt
rm 1.txt 2.txt 3.txt 1_avg.txt 2_avg.txt 3_avg.txt formatted_op.txt pings.txt
但是,我希望能够在不创建任何临时文件的情况下执行此操作。我该怎么办? 我也尝试使用管道进行如下操作:
ping -c 30 google.com | sed 's/\=/= /g' | sed -n '2, 11p' | awk '{print $10}'| awk '{ sum += $1 } END {print sum/10}'
但这只计算前10次ping的平均值,使用ping 3次会产生不同的结果。
答案 0 :(得分:2)
这一切都可以通过awk轻松完成。假设您的ping输出如下所示:
64 bytes from yyz08s09-in-f110.1e100.net (172.217.1.110): icmp_seq=27 ttl=59 time=0.636 ms
64 bytes from yyz08s09-in-f110.1e100.net (172.217.1.110): icmp_seq=28 ttl=59 time=0.638 ms
64 bytes from yyz08s09-in-f110.1e100.net (172.217.1.110): icmp_seq=29 ttl=59 time=0.658 ms
64 bytes from yyz08s09-in-f110.1e100.net (172.217.1.110): icmp_seq=30 ttl=59 time=0.666 ms
这样可以解决问题:
ping -c 30 google.com | \
awk '
{
split($8,a,"=");
if(NR > 1 && NR < 12) {
round1+=a[2]
} else if (NR < 22) {
round2+=a[2]
} else if (NR < 32) {
round3+=a[2]
}
}
END {
print round1/10" "round2/10" "round3/10
}
'
我们使用NR
变量来检查正在处理的输出行,然后递增适当的变量。 (通过在等号上分割时间字段来获取该值。)
答案 1 :(得分:1)
你不必那么复杂。做点什么
for i in {1..10}
do
ping -c 30 google.com | tail -n1 |
awk -v count="$i" -v FS="/" '{print "Count", count,"average : ",$5}'
done
示例输出
Count 1 average : 78.484
Count 2 average : 74.473
Count 3 average : 76.971
Count 4 average : 78.789
Count 5 average : 103.609
Count 6 average : 105.754
Count 7 average : 98.969
Count 8 average : 99.009
Count 9 average : 86.186
Count 10 average : 86.521
答案 2 :(得分:1)
纯Bash解决方案是不可能的,因为Bash不支持浮点运算。您至少需要bc
。
为了计算平均值,不必收集和存储所有值。您可以逐步计算平均值。有关数学的信息,请参阅here或here或阅读Donald Knuth&#34; The Art of Computer Programming&#34;的第2卷。作为Bash函数的公式可能如下所示:
avg ()
{
local a=$1 # average of the values already seen in the past
local x=$2 # new sample
local n=$3 # sequence number
bc -l <<<"$a + ($x - $a) / $n"
}
以下功能可以收集单个ping时间。
pingtime ()
{
ping -c1 ${host:-localhost} |
sed -n 's/.*time=\(.*\) .*/\1/p'
}
使用上述函数,可以使用两个n
循环计算每个平均值m
样本的for
平均值。
n=3
m=10
for i in $(seq $n); do
a=
for j in $(seq $m); do
t=$(pingtime)
if [ -z "$a" ]; then
a=$t
else
a=$(avg $a $t $j)
fi
done
LC_NUMERIC=C printf '%2g\n' $a
done
在外循环中,首先清除平均a
。在内循环中,测量ping时间。如果平均值为空,则使用第一个样本初始化。否则计算平均值。结果在外循环中报告。
bc
和printf
的行为取决于本地化。如有必要,可以通过设置LC_NUMERIC
来强制执行特定行为。
如果您希望在sleep 1
前添加ping
,则每秒只能测量一个样本。
答案 3 :(得分:0)
您也可以尝试我的解决方案
#!/bin/bash
pings=10
for i in {1..10};
do
ping -c ${pings} google.pl | grep -o 'time=.*' | sed 's/time=\(.*\) ms/\1/g' | awk -v iteration="$i" -v pings="$pings" '{sum+=$1+$2+$3} END {print "Iteration " iteration " Average time " sum/pings}'
done