2012-11-14 76 views
1

我需要有多个远程管理员在现场测试他们的下载速度。 Speedtest.net等都不是我们广域网中性能的真实指标。我不希望使用iperf,因为我需要尽量减少远程管理员的技术知识和工作量。我不希望他们也不得不安装任何东西。因此我需要一个简单的批处理文件来下载一个测试文件5次。这是我到目前为止:批处理脚本for循环不工作

@echo off 
rem localize variables to this script 
setlocal 
rem delete the test file if it already exists 
if exist %HomePath%\Downloads\100meg.test del %HomePath%\Downloads\100meg.test 
rem perform the test 5 times 
for /l %%i IN (1,1,5) DO (
    rem mark the start time 
    set STARTTIME=%TIME% 
    echo Download started at:%STARTTIME% 
    rem start download 
    C:\windows\explorer.exe http://mirror.internode.on.net/pub/test/100meg.test 
    rem check for file download completion 
    :while 
     if exist %HomePath%\Downloads\100meg.test goto wend 
     goto while 
    :wend 
    rem mark the end time 
    set ENDTIME=%TIME% 
    echo Download completed at:%ENDTIME% 
    rem convert STARTTIME and ENDTIME to centiseconds 
    set /A STARTTIME=(1%STARTTIME:~0,2%-100)*360000 + (1%STARTTIME:~3,2%-100)*6000 + (1%STARTTIME:~6,2%-100)*100 + (1%STARTTIME:~9,2%-100) 
    set /A ENDTIME=(1%ENDTIME:~0,2%-100)*360000 + (1%ENDTIME:~3,2%-100)*6000 + (1%ENDTIME:~6,2%-100)*100 + (1%ENDTIME:~9,2%-100) 
    rem calculate the time taken in seconds 
    set /A DURATION=(%ENDTIME%-%STARTTIME%)/100 
    echo Download took:%DURATION% seconds 
    rem delete the test file ready for next iteration 
    del %HomePath%\Downloads\100meg.test 
) 

问题是,因为添加for并将括号括起来,它停止工作。任何人都可以阐明为什么这是失败的?

谢谢!

+0

注释掉“@echo off”,看看有什么失败。 – jdigital

+0

好的,首先脚本似乎设置了变量,但立即忘记它: C:\ Users \ j \ Desktop> for/L%i IN(1 1 5)DO( set STARTTIME = 11:59:26.39 回声下载的开始: 暂停 其次,它只有通过for循环 – James

+0

单次迭代去(这个网站有未格式化的,以前的评论,我只想说,“下载开始时间:”读取“下载开始时间: 11:59:26.39“for循环未使用时 – James

回答

3

在FOR循环中使用GOTO总会打断循环 - 一旦使用了GOTO,剩余的迭代就不会发生。

这是因为CMD.EXE的工作方式。括号中的整个命令块将被解析并一次加载到内存中。每次迭代都会执行存储在内存中的已解析命令。这些解析的命令不包含任何标签。 GOTO必须扫描文件,这需要打破循环。

STARTTIME的“消失”值也与整个块被一次解析的事实有关。 %STARTTIME%在解析时展开,但在执行任何块之前解析该命令。所以你得到了FOR命令执行前存在的值,这可能是未定义的。有一个称为延迟扩展的特性,可用于在执行时获取变量的值而不是解析时间。从命令提示符处输入HELP SET,并阅读有关延迟扩展的部分,该部分从文档的中途开始。

但是有一个简单的方法让你的代码工作 - 只要将DO块的内容移动到子程序中,然后在你的循环中调用例程。 (我假设你在DO子句中的逻辑是正确的)。 CALL不打破循环:-)

您必须记住在常规标签之前放置一个EXIT/B,以便您的主代码不会落入子程序。

@echo off 
rem localize variables to this script 
setlocal 
rem delete the test file if it already exists 
if exist %HomePath%\Downloads\100meg.test del %HomePath%\Downloads\100meg.test 
rem perform the test 5 times 
for /l %%i IN (1,1,5) do call :downloadTest 
exit /b 

:downloadTest 
rem mark the start time 
set STARTTIME=%TIME% 
echo Download started at:%STARTTIME% 
rem start download 
C:\windows\explorer.exe http://mirror.internode.on.net/pub/test/100meg.test 
rem check for file download completion 
:while 
    if exist %HomePath%\Downloads\100meg.test goto wend 
    goto while 
:wend 
rem mark the end time 
set ENDTIME=%TIME% 
echo Download completed at:%ENDTIME% 
rem convert STARTTIME and ENDTIME to centiseconds 
set /A STARTTIME=(1%STARTTIME:~0,2%-100)*360000 + (1%STARTTIME:~3,2%-100)*6000 + (1%STARTTIME:~6,2%-100)*100 + (1%STARTTIME:~9,2%-100) 
set /A ENDTIME=(1%ENDTIME:~0,2%-100)*360000 + (1%ENDTIME:~3,2%-100)*6000 + (1%ENDTIME:~6,2%-100)*100 + (1%ENDTIME:~9,2%-100) 
rem calculate the time taken in seconds 
set /A DURATION=(%ENDTIME%-%STARTTIME%)/100 
echo Download took:%DURATION% seconds 
rem delete the test file ready for next iteration 
del %HomePath%\Downloads\100meg.test 
exit /b 
+0

怎么样加入一个** GOTO:EOF **到最后GOTO“循环”,所以它返回到FOR语句? – Lizz

+0

@Lizz - Nope; GOTO:EOF和EXIT/B只能从CALL返回,而不能从GOTO返回。 GOTO:EOF和EXIT/B将在CALL尚未创建时退出批处理脚本。 – dbenham

+0

谢谢dbenham - 第一段完全是问题 - GOTO打破了循环 – James