Sleeping in a batch file
当编写批处理文件以在Windows机器上自动执行某些操作时,我需要暂停执行几秒钟(通常在测试/等待循环中,等待进程启动)。 当时,我能找到的最佳解决方案是使用ping(我不是你的孩子)来达到预期的效果。 我在这里找到了一个更好的写法,它描述了一个可调用的"wait.bat",实现如下:
1 2 | @ping 127.0.0.1 -n 2 -w 1000 > nul @ping 127.0.0.1 -n %1% -w 1000> nul |
然后,您可以在自己的批处理文件中包含对wait.bat的调用,并传入要休眠的秒数。
显然,Windows 2003资源工具包提供类似Unix的睡眠命令(最后!)。 与此同时,对于我们这些仍然使用WindowsXP,Windows 2000或(可悲)Windows NT的人来说,还有更好的方法吗?
我在接受的答案中修改了
1 2 3 | import time, sys time.sleep(float(sys.argv[1]) if len(sys.argv) > 1 else 1) |
从WindowsVista开始可以使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | c:\> timeout /? TIMEOUT [/T] timeout [/NOBREAK] Description: This utility accepts a timeout parameter to wait for the specified time period (in seconds) or until any key is pressed. It also accepts a parameter to ignore the key press. Parameter List: /T timeout Specifies the number of seconds to wait. Valid range is -1 to 99999 seconds. /NOBREAK Ignore key presses and wait specified time. /? Displays this help message. NOTE: A timeout value of -1 means to wait indefinitely for a key press. Examples: TIMEOUT /? TIMEOUT /T 10 TIMEOUT /T 300 /NOBREAK TIMEOUT /T -1 |
注意:它不适用于输入重定向 - 一些简单的例子:
1 2 | C:\>echo 1 | timeout /t 1 /nobreak ERROR: Input redirection is not supported, exiting the process immediately. |
使用所概述的
你应该ping那些不存在的东西,然后使用
例如
(不测试1.1.1.1)
1 2 3 4 5 | ECHO Waiting 15 seconds PING 1.1.1.1 -n 1 -w 15000 > NUL or PING -n 15 -w 1000 127.1 >NUL |
1 2 3 | Usage: sleep time-to-sleep-in-seconds sleep [-m] time-to-sleep-in-milliseconds sleep [-c] commited-memory ratio (1%-100%) |
我不同意我在这里找到的答案。
我完全基于WindowsXP功能使用以下方法在批处理文件中执行延迟:
DELAY.BAT:
1 2 3 4 5 6 7 8 9 10 | @ECHO OFF REM DELAY seconds REM GET ENDING SECOND FOR /F"TOKENS=1-3 DELIMS=:." %%A IN ("%TIME%") DO SET /A H=%%A, M=1%%B%%100, S=1%%C%%100, ENDING=(H*60+M)*60+S+%1 REM WAIT FOR SUCH A SECOND :WAIT FOR /F"TOKENS=1-3 DELIMS=:." %%A IN ("%TIME%") DO SET /A H=%%A, M=1%%B%%100, S=1%%C%%100, CURRENT=(H*60+M)*60+S IF %CURRENT% LSS %ENDING% GOTO WAIT |
您也可以在计算中插入日期,以便在延迟时间间隔超过午夜时该方法也可以使用。
我遇到了类似的问题,但我只是敲了一个很短的C ++控制台应用程序来做同样的事情。只需运行MySleep.exe 1000 - 可能比下载/安装整个资源工具包更容易。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | #include <tchar.h> #include <stdio.h> #include"Windows.h" int _tmain(int argc, _TCHAR* argv[]) { if (argc == 2) { _tprintf(_T("Sleeping for %s ms "), argv[1]); Sleep(_tstoi(argv[1])); } else { _tprintf(_T("Wrong number of arguments. ")); } return 0; } |
如果您安装了Python,或者不介意安装它(它还有其他用途:),只需创建以下sleep.py脚本并将其添加到PATH中的某个位置:
1 2 3 | import time, sys time.sleep(float(sys.argv[1])) |
如果您有此需要,它将允许亚秒级暂停(例如,1.5秒,0.1等)。如果要将其称为
我的电脑→属性(菜单)→高级(标签)→环境变量(按钮)→系统变量(框架)
更新:从Windows Vista及以后版本提供的
在服务器故障时,问了一个类似的问题,那里的解决方案是:
1 | choice /d y /t 5 > nul |
您可以使用Windows cscript WSH层和此wait.js JavaScript文件:
1 2 3 4 | if (WScript.Arguments.Count() == 1) WScript.Sleep(WScript.Arguments(0)*1000); else WScript.Echo("Usage: cscript wait.js seconds"); |
根据您的兼容性需求,使用
1 | ping -n <numberofseconds+1> localhost >nul 2>&1 |
例如等待5秒钟,使用
1 | ping -n 6 localhost >nul 2>&1 |
或者在Windows 7或更高版本上使用
1 | timeout 6 >nul |
你可以使用ping:
1 | ping 127.0.0.1 -n 11 -w 1000 >nul: 2>nul: |
它将等待10秒。
你必须使用11的原因是因为第一次ping立即熄灭,而不是一秒钟之后。该数字应始终比您要等待的秒数多一个。
请记住,
使用ping有一种更好的睡眠方式。您需要ping不存在的地址,因此您可以指定毫秒精度的超时。幸运的是,这样的地址是在标准(RFC 3330)中定义的,它是
192.0.2.0/24 - This block is assigned as"TEST-NET" for use in
documentation and example code. It is often used in conjunction with
domain names example.com or example.net in vendor and protocol
documentation. Addresses within this block should not appear on the
public Internet.
要睡眠123毫秒,请使用
1 | timeout /t <seconds> <options> |
例如,要使脚本执行非不间断的2秒等待:
1 | timeout /t 2 /nobreak >NUL |
这意味着脚本将在继续之前等待2秒。
默认情况下,按键会中断超时,因此如果您不希望用户能够中断(取消)等待,请使用
编辑:正如@martineau在评论中指出的那样,
如果您的系统上有PowerShell,则可以执行以下命令:
1 | powershell -command"Start-Sleep -s 1" |
编辑:从我在类似线程上的回答中,人们提出了一个问题,即PowerShell启动所需的时间与您尝试等待的时间相比是显着的。如果等待时间的准确性很重要(即不能接受额外的两秒或两个延迟),您可以使用以下方法:
1 | powershell -command"$sleepUntil = [DateTime]::Parse('%date% %time%').AddSeconds(5); $sleepDuration = $sleepUntil.Subtract((get-date)).TotalMilliseconds; start-sleep -m $sleepDuration" |
这将花费发出Windows命令的时间,并且powershell脚本会在该时间之后休眠5秒。因此,只要powershell启动的时间少于睡眠持续时间,这种方法就可以工作(我的机器上的时间大约为600毫秒)。
只需将它放在您想要等待的批处理文件中。
1 | @ping 127.0.0.1 -n 11 -w 1000 > null |
Resource Kit始终包含此功能。至少从Windows 2000开始。
此外,Cygwin包中有一个
在记事本中,写:
1 2 3 4 | @echo off set /a WAITTIME=%1+1 PING 127.0.0.1 -n %WAITTIME% > nul goto:eof |
现在保存为文件夹C: WINDOWS System32中的wait.bat,
那么每当你想等待时,使用:
1 | CALL WAIT.bat <whole number of seconds without quotes> |
我喜欢Aacini的回应。我添加它来处理这一天,并使其能够处理厘秒(
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | :delay SET DELAYINPUT=%1 SET /A DAYS=DELAYINPUT/8640000 SET /A DELAYINPUT=DELAYINPUT-(DAYS*864000) ::Get ending centisecond (10 milliseconds) FOR /F"tokens=1-4 delims=:." %%A IN ("%TIME%") DO SET /A H=%%A, M=1%%B%%100, S=1%%C%%100, X=1%%D%%100, ENDING=((H*60+M)*60+S)*100+X+DELAYINPUT SET /A DAYS=DAYS+ENDING/8640000 SET /A ENDING=ENDING-(DAYS*864000) ::Wait for such a centisecond :delay_wait FOR /F"tokens=1-4 delims=:." %%A IN ("%TIME%") DO SET /A H=%%A, M=1%%B%%100, S=1%%C%%100, X=1%%D%%100, CURRENT=((H*60+M)*60+S)*100+X IF DEFINED LASTCURRENT IF %CURRENT% LSS %LASTCURRENT% SET /A DAYS=DAYS-1 SET LASTCURRENT=%CURRENT% IF %CURRENT% LSS %ENDING% GOTO delay_wait IF %DAYS% GTR 0 GOTO delay_wait GOTO :EOF |
我一直在使用这个C#睡眠程序。如果C#是您的首选语言,对您来说可能更方便:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; namespace sleep { class Program { static void Main(string[] args) { if (args.Length == 1) { double time = Double.Parse(args[0]); Thread.Sleep((int)(time*1000)); } else { Console.WriteLine("Usage: sleep <seconds> Example: sleep 10"); } } } } |
或者命令行Python,例如,持续6秒半:
1 | python -c"import time;time.sleep(6.5)" |
Perl比Python解决方案更轻量级
需要一行代码。
要睡7秒钟,请将其放入BAT脚本中:
1 | perl -e"sleep 7" |
该解决方案仅提供一秒的分辨率。
如果您需要更高的分辨率,请使用Time :: HiRes
来自CPAN的模块。它提供
微秒和
(两个函数只接受整数参数)。见
StackOverflow问题如何在Perl中睡眠一毫秒?了解更多详情。
我已经使用ActivePerl多年了。这很容易
安装。
ping的用法很好,只要你只是想"等一下"。这是因为您依赖于下面的其他功能,例如您的网络工作以及127.0.0.1上没有任何回答的事实。 ;-)也许它不太可能失败,但这并非不可能......
如果要确保等待指定的时间,则应使用
要找到已经制作的睡眠可执行文件是最方便的方法。只需将其放入Windows文件夹或标准路径的任何其他部分即可,它始终可用。
否则,如果您有编译环境,您可以轻松自己制作一个。
对于VB / VBA,在源代码的开头声明以下内容以声明sleep函数:
1 | private Declare Sub Sleep Lib"kernel32" Alias"Sleep" (byval dwMilliseconds as Long) |
对于C#:
1 2 | [DllImport("kernel32.dll")] static extern void Sleep(uint dwMilliseconds); |
您可以在此处找到有关Sleep功能(MSDN)中此功能(自Windows 2000以来可用)的更多信息。
在标准C中,
在Windows 2000之后适用于所有Windows版本的最佳解决方案是:
1 | timeout numbersofseconds /nobreak > nul |
我对此印象深刻:
http://www.computerhope.com/batch.htm#02
1 | choice /n /c y /d y /t 5 > NUL |
从技术上讲,你告诉
从WindowsVista开始,您有TIMEOUT和SLEEP命令,但要在WindowsXP或Windows Server 2003上使用它们,您将需要Windows Server 2003资源工具包。
在这里你可以很好地了解睡眠替代方案(ping方法最受欢迎,因为它可以在每台Windows机器上运行),但是(至少)没有提到哪一个(ab)使用
1 | w32tm /stripchart /computer:localhost /period:1 /dataonly /samples:N >nul 2>&1 |
你应该用你想要暂停的秒数替换N.此外,它将适用于没有先决条件的每个Windows系统。
也可以使用Typeperf:
1 | typeperf"\System\Processor Queue Length" -si N -sc 1 >nul |
您还可以使用.vbs文件执行特定的超时:
下面的代码创建.vbs文件。把它放在你的rbatch代码的顶部附近:
1 | echo WScript.sleep WScript.Arguments(0) >"%cd%\sleeper.vbs" |
然后,下面的代码打开.vbs并指定等待的时间:
1 | start /WAIT"""%cd%\sleeper.vbs""1000" |
在上面的代码中,"1000"是以毫秒为单位发送到.vbs文件的时间延迟值,例如1000ms = 1s。您可以将此部分更改为您想要的任何时间。
完成后,下面的代码将删除.vbs文件。把它放在批处理文件的末尾:
1 | del /f /q"%cd%\sleeper.vbs" |
这里是代码,所以很容易复制:
1 2 3 | echo WScript.sleep WScript.Arguments(0) >"%cd%\sleeper.vbs" start /WAIT"""%cd%\sleeper.vbs""1000" del /f /q"%cd%\sleeper.vbs" |
pathping.exe可以睡不到秒。
1 2 3 | @echo off setlocal EnableDelayedExpansion echo !TIME! & pathping localhost -n -q 1 -p %~1 2>&1 > nul & echo !TIME! |
。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | > sleep 10 17:01:33,57 17:01:33,60 > sleep 20 17:03:56,54 17:03:56,58 > sleep 50 17:04:30,80 17:04:30,87 > sleep 100 17:07:06,12 17:07:06,25 > sleep 200 17:07:08,42 17:07:08,64 > sleep 500 17:07:11,05 17:07:11,57 > sleep 800 17:07:18,98 17:07:19,81 > sleep 1000 17:07:22,61 17:07:23,62 > sleep 1500 17:07:27,55 17:07:29,06 |
由于其他人正在建议第三方程序(Python,Perl,自定义应用程序等),另一个选项是Windows的GNU CoreUtils,可从http://gnuwin32.sourceforge.net/packages/coreutils.htm获得。
2个部署选项:
部署CoreUtils的一个好处是,您还将获得许多其他有助于编写脚本的程序(Windows批处理有很多不足之处)。
您可以通过在标题栏中放置PAUSE消息来获得幻想:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | @ECHO off SET TITLETEXT=Sleep TITLE %TITLETEXT% CALL :sleep 5 GOTO :END :: Function Section :sleep ARG ECHO Pausing... FOR /l %%a in (%~1,-1,1) DO (TITLE Script %TITLETEXT% -- time left^ %%as&PING.exe -n 2 -w 1000 127.1>NUL) EXIT /B 0 :: End of script :END pause ::this is EOF |
这是在WindowsXP SP3和Windows7上测试的,并使用CScript。我放了一些安全防护装置以避免del"提示。(
等一下:
sleepOrDelayExecution 1000
等待500毫秒然后运行之后:
1 | sleepOrDelayExecution 500 dir \ /s |
sleepOrDelayExecution.bat:
1 2 3 4 5 6 7 8 9 10 11 12 | @echo off if"%1" =="" goto end if NOT %1 GTR 0 goto end setlocal set sleepfn="%temp%\sleep%random%.vbs" echo WScript.Sleep(%1) >%sleepfn% if NOT %sleepfn% =="" if NOT EXIST %sleepfn% goto end cscript %sleepfn% >nul if NOT %sleepfn% =="" if EXIST %sleepfn% del %sleepfn% for /f"usebackq tokens=1*" %%i in (`echo %*`) DO @ set params=%%j %params% :end |
1 | ping -n X 127.0.0.1 > nul |
将X替换为秒数+ 1。
例如,如果您要等待10秒钟,请将X替换为11.要等待5秒钟,请使用6。
阅读前面的答案毫秒。