批处理 - Ping 网络 IP 的 returns 错误导致嵌套 for 循环迭代
Batch - Pinging network IP's returns erroneous result in nested for loop iterations
请记住,我正处于学习批处理脚本的早期阶段。我怀疑这不仅仅是我脚本中的一个错误导致了它的奇怪行为。测试场景如下。有一个名为 netips.txt
的文件,其中包含我的 LAN 上的 IP 地址列表,需要 ping,例如
192.168.1.1
192.168.1.2
192.168.1.3
192.168.1.33
192.168.1.34
192.168.1.35
执行脚本(底部)时,期望的结果如下:在每个循环结束时提示用户输入循环间隔以及是否接收文本文件ipalert.txt
。然后 ping netips.txt
中的每个 IP 地址,每个 IP 的弹出消息框 Online
应该只显示 IP,然后在 3 秒后消失。每个弹出窗口都应发出哔哔声。然后应根据用户间隔选择重复整个过程(循环)。
目前发生的事情是(我不确定为什么),所有 IP 的弹出窗口都是 Online
以及
' ' 不是内部或外部命令,也不是可运行的程序或批处理文件。
在 CMD window 中。 ipalert.txt
日志显示:
15/03/2015 at 12:44:23.12
192.168.1.1 Online
192.168.1.2 Online
192.168.1.3 Online
192.168.33 Online
192.168.34 Online
192.168.35 Online
并非所有 IP 都应该以这种方式显示(有些应该是 Offline
)。任何人都可以帮助我了解正在发生的事情,以及我必须做些什么来纠正这个问题吗?
@echo off
setlocal enabledelayedexpansion
if exist c:\netips.txt goto START
echo.
echo Cannot find "C:\netips.txt"
echo.
echo Please create this file, containing a list of network IP addresses to monitor for activity
echo.
goto EOF
:START
echo.
echo [1] 5 mins
echo [2] 15 mins
echo [3] 30 mins
echo [4] 60 mins
echo.
set interval=0
choice /c 1234 /n /m "Please enter the activity notification rate:"
if errorlevel 1 set interval=300
if errorlevel 2 set interval=900
if errorlevel 3 set interval=1800
if errorlevel 4 set interval=3600
echo.
echo You will be notified every %interval% seconds
echo.
set log=0
choice /m "Would you like to automatically view the activity log after each cycle? "
if errorlevel 1 set log=Y
if errorlevel 2 set log=N
if "%log%"=="N" (
echo.
echo You can view the activity log [ipalert.txt] in the root directory
)
echo.
echo You can minimise this CMD window while it is running
echo.
echo Press any key to begin
pause>nul
:LOOP
cls
echo.
echo Executing...
echo. >>c:\ipalert.txt
echo %date% at %time% >>c:\ipalert.txt
echo. >>c:\ipalert.txt
set state=down
for /f %%i in (c:\netips.txt) do (
for /f "tokens=5,7" %%a in ('ping -n 1 %%i') do (
if "x%%a"=="xReceived" if "x%%b"=="x1," set state=up
)
if !state!==up (
echo %%i Online >> c:\ipalert.txt
echo %%i Online > c:\ipnotify.txt
BELL rem special character for 'beep'
msg "%username%" /time:3 < c:\ipnotify.txt
del /q c:\ipnotify.txt
) else (
echo %%i Offline >> c:\ipalert.txt
)
set state=down
)
if "%log%"=="Y" (
start notepad c:\ipalert.txt
timeout /t 6 >nul
taskkill /im notepad.exe>nul
)
timeout /t !interval! /nobreak >nul
goto LOOP
endlocal
更新
我已经修改了 LOOP sub(见下文)并做了一些改进,正确的 IP 现在弹出为 Online
,但是 ipalert.txt
现在只显示那些 IP,而不是Offline
还有……?
:LOOP
cls
echo.
echo Executing...
echo. >>c:\ipalert.txt
echo %date% at %time% >>c:\ipalert.txt
echo. >>c:\ipalert.txt
for /f %%i in (c:\netips.txt) do (
for /f "tokens=*" %%a in ('ping -n 1 %%i ^| find "TTL="') do (
if errorlevel 0 (
echo %%i Online >> c:\ipalert.txt
echo %%i Online > c:\ipnotify.txt
BELL
msg "%username%" /time:3 < c:\ipnotify.txt
del /q c:\ipnotify.txt
)
if errorlevel 1 (
echo %%i Offline >> c:\ipalert.txt
)
)
)
你的脚本对我来说没有任何错误信息,但这种错误可能是由错误的转义特殊字符或错误的 ()
个括号引起的;定位错误的地方,强制ECHO ON
,暂时不要用cls
清屏。
然而,ping -n 1 ...
returns Received = 1,
即使 目标主机无法访问:
==>ping -n 1 -4 192.168.1.2
Pinging 192.168.1.2 with 32 bytes of data:
Reply from 192.168.1.100: Destination host unreachable.
Ping statistics for 192.168.1.2:
Packets: Sent = 1, Received = 1, Lost = 0 (0% loss),
我将使用下一个测试 find
并强制 IPV4
:
set state=down
for /f "tokens=*" %%a in ('ping -n 1 -4 %%i^|find "TTL="') do (
set state=up
)
我不知道你的msg
命令是什么。批处理文件中的以下命令将触发大多数 PC 上的默认蜂鸣声:ECHO
(^G)。要键入 BELL
字符 (ASCII 7),请使用 CtrlG 或按住 Alt键,键入 07(数字键盘上的数字)。
我无意挑剔你的努力,但使用 vbscript 或 powershell 执行 ping 类型的操作比使用批处理要容易得多。 reading/writing 文件和注册表数据也是如此。批处理没有错,但它只是一种工具,试图用一种语言做所有事情就像用扳手敲钉子,因为扳手在螺栓上工作得很好。
set "netIPs=c:\netips.txt"
set "ipAlert=c:\ipalert.txt"
:: ....
for /l %%a in (0) do (
cls
echo(
echo Executing...
>> "%ipAlert%" (
setlocal enabledelayedexpansion
echo(
echo(!date! at !time!
echo(
endlocal
)
(for /f "usebackq" %%i in ("%netIPs%") do (
ping -n 1 "%%~i" | find "TTL=" >nul && (
echo %%i Online
msg "%userName%" /time:3 "%%i Online"
) || (
echo %%i Offline
)
)) >> "%ipAlert%"
timeout /t %interval% /nobreak >nul
)
对您的代码进行了三处更改。
如果一个值被多次使用(这里是文件引用),最好使用变量
由于没有退出循环,backwars goto
已替换为无限 for
循环
条件执行用于测试ping
操作的结果。
而不是
ping....
if errorlevel 1 (
rem failure
) else (
sucess
)
使用&&
(如果前一个命令没有提高错误级别则执行代码)和||
(如果前一个命令已经提高错误级别则执行代码)
请记住,"usually" errorlevel 必须从较高的值到较低的值完成,因为如果 errorlevel
等于或更高,表达式 if errorlevel n
将被评估为 true 比 n
。
感谢您的(复数)帮助。我希望有一种方法可以将多个回复标记为答案。 JosefZ 和 MC ND 都解决了我的脚本中的一些非常重要的错误,他们都对我的工作版本的开发具有指导意义并最终起到了帮助作用。下面是我完成的脚本(它似乎按预期为我工作,没有偏离其原始结构太多)。再次感谢大家!
@echo off
title Network Activity Notifier
color 0a
cls
echo.
echo ============================
echo Network Activity Notifier
echo ============================
setlocal enabledelayedexpansion
if exist c:\netips.txt goto START
echo.
echo Cannot find "C:\netips.txt"
echo.
echo Please create this file, containing a list of network IP addresses to monitor for activity
echo.
goto EOF
:START
echo.
echo [1] 5 mins
echo [2] 15 mins
echo [3] 30 mins
echo [4] 60 mins
echo.
set interval=0
choice /c 1234 /n /m "Please enter the activity notification rate:"
if errorlevel 1 set interval=300
if errorlevel 2 set interval=900
if errorlevel 3 set interval=1800
if errorlevel 4 set interval=3600
echo.
echo You will be notified every %interval% seconds
echo.
set log=0
choice /m "Would you like to automatically view the activity log after each cycle? "
if errorlevel 1 set log=Y
if errorlevel 2 set log=N
if "%log%"=="N" (
echo.
echo You can view the activity log [ipalert.txt] in the root directory
)
echo.
echo You can minimise this CMD window while it is running
echo.
echo Press any key to begin
pause>nul
:LOOP
cls
echo.
echo Executing...
echo. >>c:\ipalert.txt
echo %date% at %time% >>c:\ipalert.txt
echo. >>c:\ipalert.txt
for /f %%i in (c:\netips.txt) do (
ping -n 1 %%i | find "TTL=" >nul
if errorlevel 1 (
echo %%i Offline >> c:\ipalert.txt
) else (
echo %%i Online >> c:\ipalert.txt
echo %%i Online > c:\ipnotify.txt
echo
msg "%username%" /time:3 < c:\ipnotify.txt
del /q c:\ipnotify.txt
)
)
if "%log%"=="Y" (
start notepad c:\ipalert.txt
timeout /t 6 >nul
taskkill /im notepad.exe>nul
)
timeout /t !interval! /nobreak >nul
goto LOOP
endlocal
请记住,我正处于学习批处理脚本的早期阶段。我怀疑这不仅仅是我脚本中的一个错误导致了它的奇怪行为。测试场景如下。有一个名为 netips.txt
的文件,其中包含我的 LAN 上的 IP 地址列表,需要 ping,例如
192.168.1.1
192.168.1.2
192.168.1.3
192.168.1.33
192.168.1.34
192.168.1.35
执行脚本(底部)时,期望的结果如下:在每个循环结束时提示用户输入循环间隔以及是否接收文本文件ipalert.txt
。然后 ping netips.txt
中的每个 IP 地址,每个 IP 的弹出消息框 Online
应该只显示 IP,然后在 3 秒后消失。每个弹出窗口都应发出哔哔声。然后应根据用户间隔选择重复整个过程(循环)。
目前发生的事情是(我不确定为什么),所有 IP 的弹出窗口都是 Online
以及
' ' 不是内部或外部命令,也不是可运行的程序或批处理文件。
在 CMD window 中。 ipalert.txt
日志显示:
15/03/2015 at 12:44:23.12
192.168.1.1 Online
192.168.1.2 Online
192.168.1.3 Online
192.168.33 Online
192.168.34 Online
192.168.35 Online
并非所有 IP 都应该以这种方式显示(有些应该是 Offline
)。任何人都可以帮助我了解正在发生的事情,以及我必须做些什么来纠正这个问题吗?
@echo off
setlocal enabledelayedexpansion
if exist c:\netips.txt goto START
echo.
echo Cannot find "C:\netips.txt"
echo.
echo Please create this file, containing a list of network IP addresses to monitor for activity
echo.
goto EOF
:START
echo.
echo [1] 5 mins
echo [2] 15 mins
echo [3] 30 mins
echo [4] 60 mins
echo.
set interval=0
choice /c 1234 /n /m "Please enter the activity notification rate:"
if errorlevel 1 set interval=300
if errorlevel 2 set interval=900
if errorlevel 3 set interval=1800
if errorlevel 4 set interval=3600
echo.
echo You will be notified every %interval% seconds
echo.
set log=0
choice /m "Would you like to automatically view the activity log after each cycle? "
if errorlevel 1 set log=Y
if errorlevel 2 set log=N
if "%log%"=="N" (
echo.
echo You can view the activity log [ipalert.txt] in the root directory
)
echo.
echo You can minimise this CMD window while it is running
echo.
echo Press any key to begin
pause>nul
:LOOP
cls
echo.
echo Executing...
echo. >>c:\ipalert.txt
echo %date% at %time% >>c:\ipalert.txt
echo. >>c:\ipalert.txt
set state=down
for /f %%i in (c:\netips.txt) do (
for /f "tokens=5,7" %%a in ('ping -n 1 %%i') do (
if "x%%a"=="xReceived" if "x%%b"=="x1," set state=up
)
if !state!==up (
echo %%i Online >> c:\ipalert.txt
echo %%i Online > c:\ipnotify.txt
BELL rem special character for 'beep'
msg "%username%" /time:3 < c:\ipnotify.txt
del /q c:\ipnotify.txt
) else (
echo %%i Offline >> c:\ipalert.txt
)
set state=down
)
if "%log%"=="Y" (
start notepad c:\ipalert.txt
timeout /t 6 >nul
taskkill /im notepad.exe>nul
)
timeout /t !interval! /nobreak >nul
goto LOOP
endlocal
更新
我已经修改了 LOOP sub(见下文)并做了一些改进,正确的 IP 现在弹出为 Online
,但是 ipalert.txt
现在只显示那些 IP,而不是Offline
还有……?
:LOOP
cls
echo.
echo Executing...
echo. >>c:\ipalert.txt
echo %date% at %time% >>c:\ipalert.txt
echo. >>c:\ipalert.txt
for /f %%i in (c:\netips.txt) do (
for /f "tokens=*" %%a in ('ping -n 1 %%i ^| find "TTL="') do (
if errorlevel 0 (
echo %%i Online >> c:\ipalert.txt
echo %%i Online > c:\ipnotify.txt
BELL
msg "%username%" /time:3 < c:\ipnotify.txt
del /q c:\ipnotify.txt
)
if errorlevel 1 (
echo %%i Offline >> c:\ipalert.txt
)
)
)
你的脚本对我来说没有任何错误信息,但这种错误可能是由错误的转义特殊字符或错误的 ()
个括号引起的;定位错误的地方,强制ECHO ON
,暂时不要用cls
清屏。
然而,ping -n 1 ...
returns Received = 1,
即使 目标主机无法访问:
==>ping -n 1 -4 192.168.1.2
Pinging 192.168.1.2 with 32 bytes of data:
Reply from 192.168.1.100: Destination host unreachable.
Ping statistics for 192.168.1.2:
Packets: Sent = 1, Received = 1, Lost = 0 (0% loss),
我将使用下一个测试 find
并强制 IPV4
:
set state=down
for /f "tokens=*" %%a in ('ping -n 1 -4 %%i^|find "TTL="') do (
set state=up
)
我不知道你的msg
命令是什么。批处理文件中的以下命令将触发大多数 PC 上的默认蜂鸣声:ECHO
(^G)。要键入 BELL
字符 (ASCII 7),请使用 CtrlG 或按住 Alt键,键入 07(数字键盘上的数字)。
我无意挑剔你的努力,但使用 vbscript 或 powershell 执行 ping 类型的操作比使用批处理要容易得多。 reading/writing 文件和注册表数据也是如此。批处理没有错,但它只是一种工具,试图用一种语言做所有事情就像用扳手敲钉子,因为扳手在螺栓上工作得很好。
set "netIPs=c:\netips.txt"
set "ipAlert=c:\ipalert.txt"
:: ....
for /l %%a in (0) do (
cls
echo(
echo Executing...
>> "%ipAlert%" (
setlocal enabledelayedexpansion
echo(
echo(!date! at !time!
echo(
endlocal
)
(for /f "usebackq" %%i in ("%netIPs%") do (
ping -n 1 "%%~i" | find "TTL=" >nul && (
echo %%i Online
msg "%userName%" /time:3 "%%i Online"
) || (
echo %%i Offline
)
)) >> "%ipAlert%"
timeout /t %interval% /nobreak >nul
)
对您的代码进行了三处更改。
如果一个值被多次使用(这里是文件引用),最好使用变量
由于没有退出循环,backwars
goto
已替换为无限for
循环条件执行用于测试
ping
操作的结果。
而不是
ping....
if errorlevel 1 (
rem failure
) else (
sucess
)
使用&&
(如果前一个命令没有提高错误级别则执行代码)和||
(如果前一个命令已经提高错误级别则执行代码)
请记住,"usually" errorlevel 必须从较高的值到较低的值完成,因为如果 errorlevel
等于或更高,表达式 if errorlevel n
将被评估为 true 比 n
。
感谢您的(复数)帮助。我希望有一种方法可以将多个回复标记为答案。 JosefZ 和 MC ND 都解决了我的脚本中的一些非常重要的错误,他们都对我的工作版本的开发具有指导意义并最终起到了帮助作用。下面是我完成的脚本(它似乎按预期为我工作,没有偏离其原始结构太多)。再次感谢大家!
@echo off
title Network Activity Notifier
color 0a
cls
echo.
echo ============================
echo Network Activity Notifier
echo ============================
setlocal enabledelayedexpansion
if exist c:\netips.txt goto START
echo.
echo Cannot find "C:\netips.txt"
echo.
echo Please create this file, containing a list of network IP addresses to monitor for activity
echo.
goto EOF
:START
echo.
echo [1] 5 mins
echo [2] 15 mins
echo [3] 30 mins
echo [4] 60 mins
echo.
set interval=0
choice /c 1234 /n /m "Please enter the activity notification rate:"
if errorlevel 1 set interval=300
if errorlevel 2 set interval=900
if errorlevel 3 set interval=1800
if errorlevel 4 set interval=3600
echo.
echo You will be notified every %interval% seconds
echo.
set log=0
choice /m "Would you like to automatically view the activity log after each cycle? "
if errorlevel 1 set log=Y
if errorlevel 2 set log=N
if "%log%"=="N" (
echo.
echo You can view the activity log [ipalert.txt] in the root directory
)
echo.
echo You can minimise this CMD window while it is running
echo.
echo Press any key to begin
pause>nul
:LOOP
cls
echo.
echo Executing...
echo. >>c:\ipalert.txt
echo %date% at %time% >>c:\ipalert.txt
echo. >>c:\ipalert.txt
for /f %%i in (c:\netips.txt) do (
ping -n 1 %%i | find "TTL=" >nul
if errorlevel 1 (
echo %%i Offline >> c:\ipalert.txt
) else (
echo %%i Online >> c:\ipalert.txt
echo %%i Online > c:\ipnotify.txt
echo
msg "%username%" /time:3 < c:\ipnotify.txt
del /q c:\ipnotify.txt
)
)
if "%log%"=="Y" (
start notepad c:\ipalert.txt
timeout /t 6 >nul
taskkill /im notepad.exe>nul
)
timeout /t !interval! /nobreak >nul
goto LOOP
endlocal