如何 Ping 多个 IP 地址并仅在 ping 失败或延迟大于 X 毫秒时保存到文件? (Bash 或 PowerShell)

How to Ping multiple IP addresses AND only save to file if ping failed OR latency is greater than X milliseconds? (Bash or PowerShell)

我想编写一个简单的 PowerShell/Bash 脚本,该脚本将 运行 在一台高效 PC 的后台运行,每 1-5 秒检查一次每个选定成员是否可 ping 通。如果不是,则应将结果保存到带有时间戳和 IP 地址的 .txt 文件中。如果延迟大于例如,结果也应该保存到 .txt 文件中。 30 毫秒。

我已经有了

ping -t xxx.xxx.xxx.xxx | 
    ForEach-Object {"{0} - {1}" -f (Get-Date), $_} > C:\Users\xy\pingtest.txt

但这会将每个输出保存到 .txt 文件中,这对我帮助不大。

如何从这个解决方案到我想要的解决方案?

这对我来说有什么诀窍

$processName = "PROCESSNAME"
$basePath = "~\Documents\PingTests"
$archivePath = "~\Documents\PingTests\Archive"

# Set temporary timestamp, which will be used to check, if one day has passed,
# so that the moving and removing of the files will be done just once a day
$dateTemp = (get-date -f dd-MM-yyyy)

# Function to get the current timestamp in the desired format
function Get-TimeStamp {

    return "[{0:MM/dd/yy} {0:HH:mm:ss}]" -f (Get-Date)

}

# Create the basePath for the logs
If(!(test-path $basePath)){
    New-Item -ItemType Directory -Force -Path $basePath
}

# Create an archivePath for the logs
If(!(test-path $archivePath)){
    New-Item -ItemType Directory -Force -Path $archivePath
}



while($True){
    # Check, if the desired process is running. This is crucial for the correct execution of the script.
    # Only in this case, the current pc is the productive one that has connection to the modbus members.
    $process  = Get-Process | Where-Object {$_.ProcessName -eq $processName}
    if($process){
        # List of modbus members, that one wants to monitor
        $COMPUTERs="IP-LIST"
        
        # For-Loop that checks every member in "COMPUTERs"
        ForEach ($COMPUTER in $COMPUTERs){
            # In case the member is not pingable, write it to the .txt file
                if(!(Test-Connection -Cn $computer -BufferSize 16 -Count 1 -ea 0 -quiet)){
                # Console output for debugging purposes (not relevant, if execution is done via Task scheduler)
                write-host "cannot reach $computer"
                
                # Call of function "Get-TimeStamp"
                $timestamp = (Get-TimeStamp)
                
                # Write results to file
                "TIMESTAMP:      $timestamp, cannot reach IP-ADRESS:      $computer" | 
                out-file -filepath "~\Documents\PingTests\ping_$(get-date -f dd-MM-yyyy).log" -append -width 200
            }
            
            # If the member is pingable, check the latency
            else {
                $Testoutput = Test-Connection -ComputerName $computer -Count 1 | Select -ExpandProperty ResponseTime
                Write-Host $Testoutput
                
                # If latency is greater than 30 milliseconds, write the event to the .log file (Testoutput 
                # has been typecasted, that Powershell can check, if the value is greater than 30ms)
                if([int]$Testoutput -gt 30){
                    
                    # Call of function "Get-TimeStamp"
                    $timestamp = (Get-TimeStamp)
                    
                    # Console output for debugging purposes (not relevant, if execution is done via Task scheduler)
                    write-host $timestamp "," $computer "," $Testoutput
                    
                    # Write results to file
                    "TIMESTAMP:      $timestamp,              IP-ADRESS:      $computer ,             LATENCY:      $Testoutput" | 
                    out-file -filepath "~\Documents\PingTests\ping $(get-date -f dd-MM-yyyy).log" -append -width 200
                }
            }
        }
        
        # If one day has passed, move files that are older than 7 days to the archive folder and
        # remove files in archive folder, that are older than 30 days
        if(!($dateTemp -eq (get-date -f dd-MM-yyyy))){
            
            # Set dateTemp variable to current day
            $dateTemp = (get-date -f dd-MM-yyyy)
            
            # Move files
            $date1 = (get-date).AddDays(-7)
            get-childitem ~\Documents\PingTests\ping *.log | where-object {$_.LastWriteTime -lt $date1} | 
            move-item -destination ~\Documents\PingTests\Archive
            
            # Remove files
            $date2 = (get-date).AddDays(-30)
            get-childitem ~\Documents\PingTests\Archive\ping *.log | where-object {$_.LastWriteTime -lt $date2} | 
            Remove-Item -Force
        }
        
        # Wait one second until the next execution
        Start-Sleep 1
    }
}

保存此脚本,添加执行权限chmod +x myScript
运行 它在终端中 watch -n 5 ./myScript

#!/usr/bin/bash
list=(192.168.1.{0..12})
my_time=0.7
file=fileName_"$(date)".txt

for ip in "${list[@]}"; do
    ping -c 2 "$ip" >ipOutput.txt
    if [[ $? -ne 0 ]]; then
        cat <ipOutput.txt >>"$file"
        echo "error: $ip $(date) [saving to file]"
    else
        get_time=$(cat <ipOutput.txt | grep avg | awk -F '/' '{print }')
        if (($(echo "$get_time" '>='"$my_time" | bc -l))); then
            cat <ipOutput.txt >>"$file"
            echo "$ip OK, MORE time: $get_time milliseconds [saving to file]"
        else
            echo "$ip : OK, less than $my_time milliseconds [$get_time]"
        fi
    fi
done
rm ipOutput.txt

解释答案

创建 IP 地址数组

list=(192.168.1.{0..12}) 

您可以在文件中保存要 ping 的 iddress 列表,然后将其保存在该变量中list。这是一个 bash 序列表达式 {0..12} 填充一个范围内的数字,这种情况下,从 0 到 12。最终结果是 list=(192.168.1.0 192.168.1.1 192.168.1.2...)

这可以是字符串[域] 的列表,示例:并且工作正常

 list=("amazon.com" "google.com" "target.com")  

创建变量:

file=fileName_"$(date)".txt  

$(date) 此命令将日期添加到文件[file_with_errors]

迭代数组list of ip's

for ip in "${list[@]}"; do  

此行迭代名称为 list 的数组访问名称为 [@] 的所有项目,这是 bash.

的特殊语法

ping 每个 IP 2 次并将其保存到文件

ping -c 2 "$ip" >ipOutput.txt  

-c 参数,ping 一个 ip 特定次数,在本例中为 2 次。 ping 后,将该输出保存到文件[ipOutput.txt] 而不是使用 > 的控制台,这会为每个新 IP 保存输出 ONCE

检查 PING 的输出,如果存在错误,将其保存到文件

if [[ $? -ne 0 ]]; then
    cat <file.txt >>"$file"
    echo "error: $ip $(date) [saving to file]"  

$? 打印最后一个命令 [PING] 的最后输出,因为它不等于 0,这意味着错误。 cat< ipOutput.txt 它显示 PING 的 OUTPUT 的内容,然后将该数据重定向到变量 $file[your_log_file] 和 >>,这意味着附加 [NO overwrite]。 echo 在终端中打印文本格式

如果没有报错继续ELSE语句

else
    get_time=$(cat <ipOutput.txt | grep avg | awk -F '/' '{print }')  

get_time 保存 ping ip 地址的平均时间,以毫秒为单位。
awk awk 是一个检查文本列的程序。 -F '/' 参数告诉 awk 使用哪个定界符,在本例中为 /{print } 抓取 毫秒。

抓取 grepawk

的输出
  • rtt min/avg/max/mdev = 1.637/1.693/1.749/0.056 ms

查看ping ip地址需要多长时间

if (($(echo "$get_time" '>='"$my_time" | bc -l))); then  

我认为 (( )) 很奇怪,但为了比较,还是这样做。 $(commands) 用于在本例中编写命令和管道 echo, >=, |。运算符 >= 必须有 ' '| bc -l 用于比较 bash.

中的浮点数

This is just an IF STATEMENT, but bash needs special sintax for comparing two floats.

保存到文件,因为需要更多时间来 ping 所需时间

cat <ipOutput.txt >>"$file".txt
echo "$ip OK, but took MORE time: $get_time milliseconds [saving to file]"  
else
    echo "$ip : OK, less than $my_time milliseconds [$get_time]"  

else 一切正常,未保存到文件,但在终端中显示正常状态

删除文件ipOutput.txt

rm ipOutput.txt  

此文件用于保存每个 ip 使用 ping 命令的输出。此文件会覆盖每个新 ip 的数据,因此您可以使用 grepawk.

更轻松地检索信息