【问题标题】:How to Ping multiple IP addresses AND only save to file if ping failed OR latency is greater than X milliseconds? (Bash or PowerShell)如果 ping 失败或延迟大于 X 毫秒,如何 ping 多个 IP 地址并仅保存到文件? (Bash 或 PowerShell)
【发布时间】:2021-07-07 12:16:49
【问题描述】:

我想编写一个简单的 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 文件中,这对我没有多大帮助。

我怎样才能从这个解决方案工作到我想要的解决方案?

【问题讨论】:

  • 你是如何得出“每个选定的成员”的?
  • 我们有 5 个区域,区域特定网络中有 10-20 个成员。他们中的一些人最近出现了问题,我们希望将其缩小到问题所在的位置。因此,我们选择最后有问题并希望记录“坏”事件的成员,以获得更多洞察力。 @RamanSailopal
  • 首先查看if 语句
  • @Abraham Zinala,谢谢。我面临的唯一问题是,我不知道如何访问延迟以及 ping 是否成功。只要我知道,如何访问这些参数,剩下的就简单了
  • Test-Connection开始

标签: bash powershell ping


【解决方案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 $5}')
        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 的 idaddress 列表保存在文件中,然后将其保存在此变量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的ip

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

这行迭代一个名为 list 的数组访问所有带有 [@] 的项目,这是 bash 的特殊语法。

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

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

-c 参数,ping ip 特定次数,在本例中为 2 次。 ping 之后,将该 OUTPUT 保存到文件 [ipOutput.txt] 而不是带有&gt; 的控制台,这会为每个新 IP 保存 OUTPUT ONCE

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

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

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

如果没有错误则继续 ELSE 语句

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

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

抓取 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, &gt;=, |。运算符&gt;= 必须有' '| bc -l 用于比较 bash 中的浮点数。

这只是一个 IF 语句,但是 bash 需要特殊的 sintax 来比较两个浮点数。

保存到文件,因为需要更多时间来 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 更轻松地检索信息。

【讨论】:

    【解决方案2】:

    这对我有什么用

    $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
        }
    }
    

    【讨论】:

    • @InfiProg 下面的 bash 答案
    猜你喜欢
    • 2013-09-08
    • 1970-01-01
    • 1970-01-01
    • 2012-07-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-24
    相关资源
    最近更新 更多