批处理文件 - 分配新值时不会更新变量

时间:2014-02-04 18:31:55

标签: batch-file

我有一个简单地ping一个框的脚本,如果框回复,它会将名为“newstate”的变量更改为up。否则它被设置为“向下”。出于某种原因,当我在我的机器上运行时,newstate永远不会变为“up”,即使它在线并回复ping。

我可能错过了很小的东西,请你帮忙吗? (我还在变量时输入一个变量来记录状态,但是我还没有实现它,因为我甚至无法识别切换)。最终目标是记录状态从上到下的变化,反之亦然。

编辑 - 将%newstate%更改为!newstate!,仍然无效。

@setlocal enableextensions enabledelayedexpansion
@echo off

title loop test

set system=192.168.0.155
set oldstate=up
set newstate=down

:loop
echo.
echo ...........
echo pre check
echo old state is %oldstate%
echo new state is !newstate!
echo ...........
echo.

:::::: CONNECTIVITY CHECK ::::::
for /f "tokens=5,7" %%a in ('ping -n 1 -4 !system!') do (
if "x%%a"=="xReceived" if "x%%b"=="x1," set newstate=up
)

echo new state is !newstate!

if !newstate! neq up set newstate=down

set log=%time% - %sytem% - !newstate!

if %oldstate% neq !newstate! set oldstate=!newstate!

echo.
echo ...........
echo post check
echo old state is %oldstate%
echo new state is !newstate!
echo ...........
echo.

:::::: DELAY LOOP ::::::
ping -n 10 127.0.0.1 >nul: 2>nul:

goto :loop
endlocal

3 个答案:

答案 0 :(得分:1)

嗯,它对我有用,但由于我使用西班牙语的Windows副本,我必须更改Received文字并使用recibidos。不确定您的本地配置。

通常最好检查ping响应中是否存在TTL=值。如果找到,目标就会启动,否则就会失效

ping -n 1 192.168.0.155 | find "TTL=" >nul 
if errorlevel 1 (
    set "newstate=down"
) else (
    set "newstate=up"
)

所以,稍微简化一下,

@echo off
    setlocal enableextensions disabledelayedexpansion

    title loop test

    set "system=192.168.1.1"
    set "oldState=down"
    set "newState=up"

:loop
    ping -4 -n 1 %system% | find "TTL=" >nul && set "newState=up" || set "newState=down"

    if %newState%==%oldState% (
        echo %time% - %system% still %oldState%
    ) else (
        echo %time% - %system% goes %newState%
        set "oldState=%newState%"
    )
    ping -n 10 127.0.0.1 >nul 2>nul
    goto loop

ping行应该被读作“ping,在输出中找到ttl =,如果找到将newState设置为up,否则将newstate设置为down”

已编辑 -

这是测试ping响应的常用方法。在IPv4中。但是在IPv6中ping时,TTL字段没有显示,所以我们无法检查它。

在ping命令的输出中测试TTL=的最初原因是处理数据包计数和错误级别的方式。如果数据包丢失,则设置errorlevel。如果没有数据包丢失,则没有错误级别。但是,ping同一子网中的非活动计算机会生成“无法访问”的响应,并且不会丢失数据包,因此,没有错误级别和数据包计数反映0数据包丢失。而且,......

此外,ping输出中的几乎所有信息都是本地化的,因此很难检查ping命令的结果并使其在不同的OS本地化中保持一致。

但IPv6 ping中有些事情发生了变化。如果请求的计算机无法访问,则数据包将丢失并设置errorlevel。在同一子网中。

并且,如果某些数据包丢失,但至少有一个数据包没有丢失,则不设置errorlevel。

因此,在使用IPv4时,ping outout中TTL=存在的测试是检查远程计算机状态的“可靠”方式。

而且,在使用IPv6时,errorlevel反映了该过程失败的成功。

而且,请注意,我不是网络大师。这是我在测试时看到的。如果我错了,请评论。

答案 1 :(得分:0)

使用!newstate!获取变量值,而不是%newstate%。这是获取延迟变量值的方法。 继续使用“setlocal enabledelayedexpansion”。

答案 2 :(得分:0)

问题在于本声明

if "x%%a"=="xReceived" if "x%%b"=="x1," set newstate=up

表示if firstcondiion and secondcondition设置...

所以 - 我要插入一个调试行

echo +%%a+%%b+

在此if语句之前,观察结果。 + 就是一个明显的特征,可以让 Spaces 更容易。

请记住 - if区分大小写,因此如果您需要不区分大小写,请使用if /i

另外 - 观察 Spaces 作为if中的带引号的字符串,包含匹配中的任何空格。

在这个实例中,delayedexpansion没有任何意义,因为您没有尝试读取在其中发生变化的值(带括号的语句块)。在这种情况下,%var% == !var!