批处理 - Ping网络IP在嵌套for循环迭代中返回错误结果

时间:2015-03-15 18:59:16

标签: batch-file if-statement for-loop popup ping

请记住,我处于学习批处理脚本的早期阶段。我怀疑它不仅仅是我脚本中的一个错误,它对其奇怪的行为负责。测试场景如下。有一个名为netips.txt的文件,其中包含我的LAN上的IP地址列表,例如。

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。然后对netips.txt中的每个IP地址进行ping操作,每个IP的弹出式msgbox只有Online才会显示IP,然后在3秒后消失。每个弹出窗口都应伴有一声蜂鸣声。然后应根据用户间隔选择重复整个过程(循环)。

目前发生的事情是(我不确定原因),所有IP弹出式广告为Online以及

' '不被识别为内部或外部命令,可操作程序或批处理文件。

CMD窗口中的

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子(见下文)并进行了一些改进,现在正确的IP弹出为Online,但ipalert.txt现在只显示那些IP& #39; s,而不是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
)
)
)

4 个答案:

答案 0 :(得分:1)

您的脚本没有任何错误消息,但这种错误可能是由于错误的转义特殊字符或错误的()个括号引起的;要本地化错误的地点,请强制ECHO ON并暂时不要使用cls清除屏幕。

但是,即使目标主机无法访问ping -n 1 ...也会返回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),请使用 Ctrl G 或按住 Alt 键,键入 0 7 (数字小键盘上的数字)。

答案 1 :(得分:1)

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
)

您的代码有三处变化。

  1. 如果一个值被多次使用(这里是文件引用),最好使用变量

  2. 由于没有退出循环,后撤goto已被无限for循环取代

  3. 条件执行用于测试ping操作的结果。

  4. 而不是

    ping....
    if errorlevel 1 (
        rem failure
    ) else (
        sucess 
    )
    

    &&(如果前一个命令没有引发错误级别则执行代码)和||(如果上一个命令引发了错误级别则执行代码)

    请记住&#34;通常&#34;如果if errorlevel n 等于或高于而不是errorlevel,则表达式n将被评估为真,因此必须从较高的值到较低的值执行errorlevel。

答案 2 :(得分:0)

我不打算挑选你的努力,但使用vbscript或powershell进行ping类型操作要比使用批处理更容易。读/写文件和注册表数据相同。批处理没什么问题,但它只是一种工具,尝试用一种语言做所有事情就像用扳手敲击钉子一样,因为扳手在螺栓上工作得很好。

答案 3 :(得分:0)

感谢您的(复数)帮助。我希望有一种方法可以将不止一个回复标记为答案。 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