如何读取 .txt 文件中不同行上的 URL 并 ping 每个 URL

如何读取 .txt 文件中不同行上的 URL 并 ping 每个 URL

我有一个.txt包含 5 个 URL 的文件。我想逐行读取它,并为每个站点执行 4 个 ping 请求,然后提取时间。我写的代码如下,但它不起作用。

有人可以给我提示吗?

#!/bin/bash

cat /home/akis/Desktop/sites.txt
declare -i var=1
while read -r line
do
    while $var <= 5 
    do
        var2=$((var2+1)) 
        name="$line" | ping -c 4 $name > $var.txt | awk '{ print $8 }' < $var.txt | awk '/time/' > $var2.txt | tr '=' '\t' < $var2.txt | awk '{ print $2 }' > $var2.txt
    done

    var=$((var+1))  
done 

答案1

这也Sergiy 的回答来自循环遍历包含 URL 的文本文件并对每个文件执行 ping

假设文件urls位于当前目录中并包含您的 url仅有的,每行一个:

#!/bin/bash
while IFS='' read -r l || [ -n "$l" ]; do
  avg=$(ping -q -w 10 "$l" | sed '$!d;s_.*=[^/]*/\([^/]*\)/.*_\1_')
  echo "Average respond time for $l: $avg ms" >> avg_time
done < "urls"

示例运行

上面的脚本在这里被命名avg

$ cat urls
askubuntu.com
unix.stackexchange.com
stackoverflow.com
$ ./avg
$ cat avg_time 
Average respond time for askubuntu.com: 37.742 ms
Average respond time for unix.stackexchange.com: 35.966 ms
Average respond time for stackoverflow.com: 38.982 ms

解释

  • #!/bin/bash
    这个所谓的舍邦定义你的脚本必须从哪个 shell 启动,这里是bash
  • while IFS='' read -r l || [ -n "$l" ]; do stuff; done < "urls"
    read逐行命名文件urls,将当前处理行的内容赋给变量l并执行stuff用它
  • ping -q -w 10 "$l"(= ping -qw10 "$l")
    调用ping,使用变量的内容l作为参数,并使用选项-quiet(我们不需要的较少输出)和-w 10(以秒为单位的超时时间),以便当前处理的 URL 被 ping 精确的10秒数——您可以根据需要调整此值,也可以指定其他选项(请参阅man ping) 查看列表)
  • avg=$(ping … | sed …)
    将输出管道传输到ping其中以sed减少平均响应时间并将该值保存在变量中avg

    • sed '$!d;s_.*=[^/]*/\([^/]*\)/.*_\1_'
    • sed '$!d
      不要(!d删除最后一行($),而是删除其余部分
    • sed 's/a/b/'
      substitute aby b– 也可以写成例如sed 's_a_b_',这样我们就不需要在字符串中转义文字斜杠字符
      • .*– 拿走一切
      • =/– 文字“=”和“/”
      • [^/]*^– 取除 ( ) 斜线之外的所有内容
      • \([^/]*\)– 取出所有不是 ( ^) 斜线的内容并将其保存到组中
      • \1– 第一组保存\(…\)之前
    • 也可以使用以下方法完成相同的工作awk -F/ '/^rtt/{print$5}'
      • -F/– 定义/F字段分隔符
      • /^rtt/{…}^– 选择以“rtt”开头的行( )并执行该操作
      • print$5print仅限字段编号。5
  • echo "Average respond time for $l: $avg ms" >> avg_time
    打印插入变量内容的文本l并将avg此输出重定向到文件avg_time并附加到其内容

答案2

对于诸如 这样的单个简单命令ping,可以使用xargs。 很酷的是,xargs它有--arg-file一个选项,允许您指定xargs将用于为您尝试运行的命令提供位置参数的文件;在您的例子中,这将是文本文件中每行一个站点。

具体来说,您想要的命令是这样的:

xargs -I% --arg-file=./input.txt  ping -c 4 %
  • -I允许我们为每个参数选择占位符,其xargs内部将
  • --arg-file是位置参数的来源文件;请注意,我们使用 来./指示文件位于当前工作目录中
  • ping -c 4将尝试使用4 个数据包访问ping来自的每个站点input.txt

请注意,我们还可以使用-q选项来ping阻止打印每个接收/发送的数据包的行,而只输出统计信息。从那里,我们可以使用awk或任何其他文本处理实用程序进一步清理输出(请记住,输出将在通过管道时进行缓冲,并等待ping实际完成并输出统计信息,因此在屏幕上显示会有点慢):

$ xargs -I% --arg-file=./input.txt  ping -c 4 % -q | awk '/^---/||/avg/'                                                                                     
--- askubuntu.com ping statistics ---
rtt min/avg/max/mdev = 49.677/73.403/94.312/19.276 ms
--- unix.stackexchange.com ping statistics ---
rtt min/avg/max/mdev = 40.015/59.099/115.545/32.590 ms
--- stackoverflow.com ping statistics ---
rtt min/avg/max/mdev = 40.130/40.878/42.685/1.056 ms

$ xargs -I% --arg-file=./input.txt  ping -c 4 % -q | awk -F'[ /]' '/^---/{print $2};/avg/{print $8}'                                                         
askubuntu.com
39.809
unix.stackexchange.com
189.557
stackoverflow.com
161.974

相关内容