forループを使用してtxtファイルを解析するときの進行状況インジケータ

forループを使用してtxtファイルを解析するときの進行状況インジケータ

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とその中にある行の総数を印刷します。xy$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

トラップを使用して、シェルに定期的に進捗情報を印刷させることができます。

#!/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

関連情報