我正在尝试创建一个非常简单的脚本来测试 dns 服务器并将结果返回到 csv 文件中,它工作得很好,但是使用大型域源文件需要很长时间。
有没有办法使用 pv 或 awk 创建进度指示器?
#!/bin/bash
# File name of domain list: One FQDN per line in file.
domain_list='domains.txt'
#
# IP address of the nameserver used for lookups:
ns1_ip='1.1.1.1' # Cloudflare
ns2_ip='9.9.9.9' # Quad9
#
# Seconds to wait between lookups:
loop_wait='1'
#
echo "Domain name, $ns1_ip,$ns2_ip" > dns-test-results.csv;
for domain in `cat $domain_list`
do
ip1=`dig @$ns1_ip +short $domain |tail -n1`;
ip2=`dig @$ns2_ip +short $domain |tail -n1`;
echo -en "$domain,$ip1,$ip2\n" >> dns-test-results.csv;
#
done;
答案1
您可以首先将项目存储在数组中以对它们进行计数,然后在每次循环迭代中打印已处理项目的数量和总数。
例如这样的事情:
items=( $(cat items.txt) )
i=0; for x in "${items[@]}"; do
printf "\r%d/%d" "$(( i += 1 ))" "${#items[@]}";
sleep 1 # do some actual work here
done
echo
但请注意,依赖于分词$(cat file...)
有点问题,并且您最好使用readarray
更安全地将每个输入文件读入数组元素:
readarray -t items < items.txt
答案2
与 ilkkachu 的建议类似,您可以使用 while 循环来阅读:
#!/bin/bash
# File name of domain list: One FQDN per line in file.
domain_list='domains.txt'
number=$( wc -l < "$domain_list")
#
# IP address of the nameserver used for lookups:
ns1_ip='1.1.1.1' # Cloudflare
ns2_ip='9.9.9.9' # Quad9
#
# Seconds to wait between lookups:
loop_wait='1'
#
echo "Domain name, $ns1_ip,$ns2_ip" > dns-test-results.csv;
count=0
while read -r domain
do
(( count++ ))
printf '\rProcessing domain %d of %d' "$count" "$number"
ip1=$(dig @$ns1_ip +short $domain |tail -n1);
ip2=$(dig @$ns2_ip +short $domain |tail -n1);
printf "%s,%s,%s\n" "$domain" "$ip1" "$ip2" >> dns-test-results.csv;
sleep "$loop_wait"
#
done < "$domain_list"
echo
上面的代码将打印当前正在查看的数字在Processing domain x of y
哪里以及中的总行数。x
y
$domains_list
答案3
printf .
每次检查记录时,您都可以在脚本中添加。并通过 pv 进行管道传输(假设domains.txt
每个记录是行分隔的):
script.sh | pv -p -s "$(wc -l < domains.txt)" > /dev/null
但你可以做得更好。
相反echo -en "$domain,$ip1,$ip2\n" >> dns-test-results.csv;
,你可以只拥有echo "$domain,$ip1,$ip2"
。然后使用pv
行模式并以更“关注点分离”的方式调用:
script.sh | pv -p -l -s "$(wc -l < domains.txt)" > dns-test-results.csv
答案4
您可以使用陷阱使 shell 定期打印进度信息。
#!/bin/bash
# child sends SIGUSR1 to the parent every $PERIOD seconds.
MAINPID=$BASHPID
PERIOD=3
pinger() {
(
trap exit ERR
while true
do
sleep $PERIOD
kill -USR1 $MAINPID
done
) &
}
# ====
# when main process receives SIGUSR1, print some progress info
trap progress SIGUSR1
progress() {
printf "Progress: %d spins are spun\r" $COUNT
return
}
# ====
# Start the pinger
pinger
# actual work goes here
for((COUNT=1; COUNT<300; COUNT++))
do
sleep 0.100
done
exit