如何 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 }
抓取 数 毫秒。
抓取 grep 和 awk
的输出
- 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 的数据,因此您可以使用 grep
和 awk
.
更轻松地检索信息
我想编写一个简单的 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 }
抓取 数 毫秒。
抓取 grep 和 awk
的输出- 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 的数据,因此您可以使用 grep
和 awk
.