让鞭尾在 for 循环中工作

让鞭尾在 for 循环中工作

我有一个 bash 脚本,用于检查 163 个站点(全国各地的商店)的 ping,如下所示:

#!/bin/bash
#storestest.sh
#version 0.9.2

clear;
printf "Check stores procedure started; `date +"%d/%m/%Y %H:%M:%S"`\n";

declare -a STORESITE=($(cat 'stores.txt' | awk -F, '{print $1}')); # Declaring an array and populated by the file stores.txt
declare -i UP=0; # Create a variable to serve as a counter for stores that are up
declare -i DOWN=0; # Create a variable to serve as a counter for stores that are down

touch storesdown.txt; # Create a file if does not exist to store the list of the store the stores that are down
printf "" > storesdown.txt; # Clear the contents of the file
touch storesup.txt; # Create a file if does not exist to store the list of the store the stores that are up
printf "" > storesup.txt; # Clear the contents of the file

whiptail --title "Testing stores connectivity" --backtitle "Store Test" --yes-button "OK" --no-button "Cancel" --yesno "Check stores procidure has started" 10 50

if [ $? -ne 0 ]; then
    exit;
fi


for i in "${STORESITE[@]}" ; do
    ping -c 3 $i > /dev/null 2> /dev/null;
    if [ $? -eq 0 ]; then
        echo "$i is up" >> storesup.txt;
        let UP++
        sleep 1
    else
        echo "$i is down"  >> storesdown.txt;
        let DOWN++
        sleep 1
    fi
    printf "Total: $UP are online and $DOWN are off line.\r";
done

echo "Total: $UP are online and $DOWN are off line.";
exit;

上面的脚本运行良好,但我决定通过添加一个仪表来显示它的总进度,让它变得更奇特一些。这就是我接下来所做的:

#!/bin/bash
#storestest.sh
#version 0.9.3

clear;
printf "Check stores procedure started; `date +"%d/%m/%Y %H:%M:%S"`\n";

declare -a STORESITE=($(cat 'stores.txt' | awk -F, '{print $1}')); # Declaring an array and populated by the file stores.txt
declare -i UP=0; # Create a variable to serve as a counter for stores that are up
declare -i DOWN=0; # Create a variable to serve as a counter for stores that are down

touch storesdown.txt; # Create a file if does not exist to store the list of the store the stores that are down
printf "" > storesdown.txt; # Clear the contents of the file
touch storesup.txt; # Create a file if does not exist to store the list of the store the stores that are up
printf "" > storesup.txt; # Clear the contents of the file

whiptail --title "Testing stores connectivity" --backtitle "Store Test" --yes-button "OK" --no-button "Cancel" --yesno "Check stores procidure has started" 10 50

if [ $? -ne 0 ]; then
    exit;
fi

total="${#STORESITE[*]}";

{
for ((g = 0; g <= $(( $total -1)); g++)); do

    for i in "${STORESITE[@]}"; do
        ping -c 3 $i > /dev/null 2> /dev/null;
        if [ $? -eq 0 ]; then
            echo "$i is up" >> storesup.txt;
            let UP++
            sleep 2
        else
            echo "$i is down"  >> storesdown.txt;
            let DOWN++
            sleep 2
        fi
        printf "Total: $UP are online and $DOWN are off line.\r";
    done
    sleep 1
    echo $g
  done
} | whiptail --gauge "Please wait" 6 60 0


echo "Total: $UP are online and $DOWN are off line.";
exit;

这并不像我想象的那样工作......这是我可以思考和编写的最好的方法,至少可以使鞭尾工作,但显然它发生的是跳过嵌套循环。

PS 我知道我的一些编码已经过时,而且是老式的 bash 脚本方式。

答案1

您的脚本有一个额外的循环(无论如何都会执行)。它正在 ping 阵列下标而不是数组的下标成员。

这是一个没有额外循环的版本(并 ping 预期的$site):

#!/bin/bash
#storestest.sh
#version 0.9.3

clear;
printf "Check stores procedure started; `date +"%d/%m/%Y %H:%M:%S"`\n";

declare -a STORESITE=($(cat 'stores.txt' | awk -F, '{print $1}')); # Declaring an array and populated by the file stores.txt
declare -i UP=0; # Create a variable to serve as a counter for stores that are up
declare -i DOWN=0; # Create a variable to serve as a counter for stores that are down

touch storesdown.txt; # Create a file if does not exist to store the list of the store the stores that are down
printf "" > storesdown.txt; # Clear the contents of the file
touch storesup.txt; # Create a file if does not exist to store the list of the store the stores that are up
printf "" > storesup.txt; # Clear the contents of the file

total="${#STORESITE[*]}";

whiptail --title "Testing stores connectivity" --backtitle "Store Test" --yes-button "OK" --no-button "Cancel" --yesno "Check stores procedure has started, with $total stores" 10 50

if [ $? -ne 0 ]; then
    exit;
fi

{
UP=0
DOWN=0
for ((g = 0; g <= $(( $total -1)); g++)); do

    site="${STORESITE[$g]}"
    ping -c 3 $site > /dev/null 2> /dev/null;
    if [ $? -eq 0 ]; then
        echo "$site is up" >> storesup.txt;
        let UP++
    else
        echo "$site is down"  >> storesdown.txt;
        let DOWN++
    fi
    # sleep 2
    # stdbuf --output=L printf "Total: $UP are online and $DOWN are off line.\r"
    stdbuf --output=L echo $(( ( g * 100 ) / total ))
    sleep 1
  done
} | whiptail --gauge "Please wait" 6 60 0

online=$(wc -l storesup.txt | awk '{print $1;}')
offline=$(wc -l storesdown.txt | awk '{print $1;}')

echo "Total: $online are online and $offline are off line.";
exit;

其他修复:

  • 我曾经stdbuf做过输出行缓冲(这有助于使仪表按预期工作)。
  • 重定向使UPandDOWN在子进程中,因此总计没有到达最后一行。我通过计算输出文件中的行数来解决这个问题。
  • 最后,它在进度栏中显示百分比。

相关内容