我有一个 query.sh
脚本,它运行 dig
命令,从不同的 DNS 服务器执行一组查找,目前在单个输入的一列中给出使用的文件 (sites.txt
)。
我的目标是修改此脚本以使用不同的输入文件 dns_servers.txt
来查找 DNS 服务器以针对每个查询进行迭代。
我不清楚从哪里开始。我需要做什么才能安全地嵌套 while read
循环?
当前输入:
查询.sh
#!/bin/sh
while read line;
do
set $line
echo "SITE:" $1@$2
/usr/sbin/dig +short -4 @$2 $1
sleep 5
exitStatus=$?
echo "Exit Status: " $exitStatus
done < sites.txt
网站.txt
当前格式有一个主机名和一个用于查找该主机名的 DNS 服务器。
www.google.com 8.8.4.4
目的是忽略包含 DNS 服务器的列,而是使用 dns_servers.txt
的内容。
所需的输入
dns_servers.txt
10.1.1.1
12.104.1.232
...
最佳答案
忽略 sites.txt
文件中的任何其他列,并遍历 dns_servers.txt
的行,可能如下所示:
#!/bin/sh
while read -r site _ <&3; do
while read -r dns_server <&4; do
dig +short -4 "@$dns_server" "$site"; exit=$?
sleep 5
echo "Exit status: $exit"
done 4<dns_servers.txt
done 3<sites.txt
这里的关键变化:
- 将要解析的字段列表作为参数传递给
read
。作为第二个位置参数传递给第一个read
的下划线是现在保存site.txt
第二列的变量名。 - 嵌套您的循环,因为您希望在每次通过外循环时都从内循环读取数据。
- 为外循环和内循环使用不同的文件描述符(此处为
3
和4
)以将它们分开。
顺便说一下,如果您的目标是 bash (#!/bin/bash
) 而不是 POSIX sh (#!/bin/sh
),我可能会采取不同的方式.下面使用 bash 4 扩展 mapfile
一次性读取 dns_servers.txt
:
#!/bin/bash
readarray -t dns_servers <dns_servers.txt
while read -r site _; do
for from_ip in "${dns_servers[@]}"; do
dig +short -4 "@$from_ip" "$site"; exit=$?
sleep 5
echo "Exit status: $exit"
done
done <sites.txt
在这里,我们只读取一次 dns_servers.txt
,然后为从 sites.txt
读取的每个值重复使用该值列表。
如果您使用的是 bash 3.x,mapfile
可以替换为循环:
dns_servers=( )
while read -r; do dns_servers+=( "$REPLY" ); done <dns_servers.txt
关于Bash:循环多个输入源(嵌套 "while read"循环?),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31791324/