在批处理文件中休眠
- 2025-02-18 09:23:00
- admin 原创
- 87
问题描述:
在编写批处理文件以在 Windows 机器上自动执行某些操作时,我需要暂停执行几秒钟(通常在测试/等待循环中,等待进程启动)。当时,我能找到的最佳解决方案是使用 ping(我不是在开玩笑)来实现所需的效果。我在这里找到了更好的解决方案,其中描述了一个可调用的“wait.bat”,实现如下:
@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 的睡眠命令(终于!)。与此同时,对于我们这些仍在使用 Windows XP、Windows 2000 或(遗憾的是)Windows NT 的人来说,有没有更好的方法?
我修改了接受的答案sleep.py
中的脚本,以便如果在命令行上没有传递任何参数,则默认为一秒:
import time, sys
time.sleep(float(sys.argv[1]) if len(sys.argv) > 1 else 1)
解决方案 1:
该timeout
命令从 Windows Vista 开始可用:
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
用法,休眠2秒:
c:> timeout /T 2
使用方法,睡眠然后执行其他操作同一行:
c:> timeout /T 2 && echo hi
注意:它不适用于输入重定向-简单示例:
C:>echo 1 | timeout /t 1 /nobreak
ERROR: Input redirection is not supported, exiting the process immediately.
解决方案 2:
ping
当我不能(或不想)添加更多可执行文件或安装任何其他软件时,我就会使用所述方法。
您应该 ping 不存在的某个东西,并使用-w
标志,使其在这段时间后失败,而不是 ping存在的东西(如 localhost)-n
多次。这允许您处理少于一秒的时间,我认为它稍微更准确一些。
例如
(测试 1.1.1.1 是否未被占用)
ECHO Waiting 15 seconds
PING 1.1.1.1 -n 1 -w 15000 > NUL
or
PING -n 15 -w 1000 127.1 >NUL
解决方案 3:
更新
从 Windows Vista 及更高版本开始提供的命令timeout
应该是使用的命令,如该问题的另一个答案中所述。下面是一个旧答案。
旧答案
如果你已经安装了 Python,或者不介意安装它(它还有其他用途:),只需创建以下sleep.py脚本并将其添加到你的 PATH 中的某个位置:
import time, sys
time.sleep(float(sys.argv[1]))
如果您有这样的需要,它将允许亚秒级暂停(例如,1.5 秒、0.1 秒等)。如果您想将其称为 而sleep
不是sleep.py
,则可以将.PY
扩展名添加到 PATHEXT 环境变量中。在 Windows XP 上,您可以在以下位置编辑它:
我的电脑 → 属性(菜单)→ 高级(选项卡)→ 环境变量(按钮)→ 系统变量(框架)
解决方案 4:
SLEEP.exe
包含在大多数资源工具包中,例如Windows Server 2003 资源工具包,它也可以安装在 Windows XP 上。
Usage: sleep time-to-sleep-in-seconds
sleep [-m] time-to-sleep-in-milliseconds
sleep [-c] commited-memory ratio (1%-100%)
解决方案 5:
我不同意在这里找到的答案。
我使用以下完全基于 Windows XP 功能的方法在批处理文件中执行延迟:
延时棒:
@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
您还可以在计算中插入日期,这样当延迟间隔超过午夜时该方法仍然有效。
解决方案 6:
我遇到了类似的问题,但我只是编写了一个非常短的 C++ 控制台应用程序来做同样的事情。只需运行MySleep.exe 1000 - 可能比下载/安装整个资源工具包更容易。
#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;
}
解决方案 7:
您可以使用 ping:
ping 127.0.0.1 -n 11 -w 1000 >nul: 2>nul:
它将等待10秒。
您必须使用 11 的原因是因为第一次 ping 会立即发出,而不是一秒钟后。该数字应始终比您要等待的秒数多一。
请记住,目的-w
不是控制数据包的发送频率,而是为了确保在出现网络问题时您等待的时间不会超过一段时间。如果您正在 ping 127.0.0.1,则不太可能出现问题,因此这可能毫无意义。
该ping
命令本身通常每秒发送一个数据包。这实际上并未记录在 Windows 文档中,但它似乎遵循与 Linux 版本相同的规则(记录在文档中)。
解决方案 8:
在 Server Fault 上,有人问了类似的问题,那里的解决方案是:
choice /d y /t 5 > nul
解决方案 9:
您可以使用 Windows cscript WSH层和此wait.js JavaScript 文件:
if (WScript.Arguments.Count() == 1)
WScript.Sleep(WScript.Arguments(0)*1000);
else
WScript.Echo("Usage: cscript wait.js seconds");
解决方案 10:
有一种更好的方法,即使用 ping 进入休眠状态。您需要 ping 一个不存在的地址,这样就可以指定毫秒精度的超时时间。幸运的是,这样的地址在标准 (RFC 3330) 中进行了定义,并且它是192.0.2.x
。这不是虚构的,它确实是一个唯一目的就是不存在的地址。需要明确的是,这甚至适用于本地网络。
192.0.2.0/24 - 此地址块被指定为“TEST-NET”,用于文档和示例代码。它通常与供应商和协议文档中的域名 example.com 或 example.net 一起使用。此地址块内的地址不应出现在公共互联网上。
要休眠 123 毫秒,请使用ping 192.0.2.1 -n 1 -w 123 >nul
更新:根据评论,还有127.255.255.255
。
解决方案 11:
根据您的兼容性需求,可以使用ping
:
ping -n <numberofseconds+1> localhost >nul 2>&1
例如等待 5 秒,使用
ping -n 6 localhost >nul 2>&1
或者在 Windows 7 或更高版本上使用timeout
:
timeout 6 >nul
解决方案 12:
如果您的系统上有PowerShell,您可以执行以下命令:
powershell -command "Start-Sleep -s 1"
编辑:从我在类似主题上的回答中,人们提出了一个问题,即 powershell 启动所需的时间与您尝试等待的时间相比非常重要。如果等待时间的准确性很重要(即一两秒的额外延迟是不可接受的),您可以使用这种方法:
powershell -command "$sleepUntil = [DateTime]::Parse('%date% %time%').AddSeconds(5); $sleepDuration = $sleepUntil.Subtract((get-date)).TotalMilliseconds; start-sleep -m $sleepDuration"
这需要执行 Windows 命令时的时间,并且 powershell 脚本会休眠到该时间之后的 5 秒。因此,只要 powershell 启动所需的时间少于您的休眠时间,此方法就会起作用(在我的计算机上大约为 600 毫秒)。
解决方案 13:
timeout /t <seconds> <options>
例如,要使脚本执行不可中断的 2 秒等待:
timeout /t 2 /nobreak >NUL
这意味着脚本将等待 2 秒才继续。
默认情况下,按键将中断超时,因此/nobreak
如果您不希望用户能够中断(取消)等待,请使用开关。此外,超时将提供每秒通知,以通知用户还需等待多长时间;这可以通过将命令传送到 来删除NUL
。
编辑:正如@martineau 在评论中指出的那样,该timeout
命令仅适用于 Windows 7 及更高版本。此外,该ping
命令比 占用更少的处理器时间timeout
。不过,我仍然相信timeout
尽可能使用,因为它比“黑客”更具可读性。在此处ping
阅读更多信息。
解决方案 14:
只需将其放入您想要等待的批处理文件中即可。
@ping 127.0.0.1 -n 11 -w 1000 > null
解决方案 15:
在记事本中写入:
@echo off
set /a WAITTIME=%1+1
PING 127.0.0.1 -n %WAITTIME% > nul
goto:eof
现在将其保存为文件夹 C:\WINDOWS\System32 中的 wait.bat,然后每当您想要等待时,使用:
CALL WAIT.bat <whole number of seconds without quotes>
解决方案 16:
资源工具包始终包含此功能。至少从 Windows 2000 开始。
此外,Cygwin 包中有一个sleep
- 将其放入您的 PATH 中并包含cygwin.dll
(或任何它被称为的)然后就可以了!
解决方案 17:
比 Python 解决方案更轻量的是 Perl 单行代码。
要睡眠七秒,请将其放入 BAT 脚本中:
perl -e "sleep 7"
该解决方案仅提供一秒的分辨率。
如果您需要更高的分辨率,请使用 CPAN 中的 Time::HiRes 模块。它提供usleep()
以微秒为单位的休眠和以纳秒为单位的休眠(两个函数都只接受整数参数)。有关更多详细信息,nanosleep()
请参阅 Stack Overflow 问题如何在 Perl 中休眠一毫秒?
我已经使用ActivePerl很多年了。它的安装非常简单。
解决方案 18:
ping的使用很好,只要您只想“等待一会儿”。这是因为您依赖于下面的其他功能,例如您的网络正在运行,并且 127.0.0.1 上没有任何响应。;-) 也许它不太可能失败,但并非不可能......
如果您想确保您正在等待指定的时间,您应该使用该sleep
功能(它的优点还在于它不使用 CPU 能力或等待网络准备就绪)。
找到已制作好的睡眠可执行文件是最方便的方法。只需将其放入 Windows 文件夹或标准路径的任何其他部分,它始终可用。
否则,如果您有编译环境,您可以轻松地自己创建一个。该Sleep
函数在中可用kernel32.dll
,因此您只需使用那个。:-) 对于 VB / VBA,请在源代码开头声明以下内容以声明睡眠函数:
private Declare Sub Sleep Lib "kernel32" Alias "Sleep" (byval dwMilliseconds as Long)
对于 C#:
[DllImport("kernel32.dll")]
static extern void Sleep(uint dwMilliseconds);
您可以在睡眠功能(MSDN) 中找到有关此功能 (自 Windows 2000 起可用) 的更多信息。
在标准 C 中,sleep()
包含在标准库中,Sleep()
如果我没记错的话,在 Microsoft 的 Visual Studio C 中该函数名为。;-) 这两个函数以秒为单位接收参数,而不是像前两个声明那样以毫秒为单位。
解决方案 19:
我喜欢Aacini 的回复。我添加了它来处理日期,并使其能够处理厘秒(%TIME%
输出H:MM:SS.CC
):
: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
解决方案 20:
我一直在使用这个 C# 睡眠程序。如果您首选 C# 语言,那么它可能对您来说更方便:
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");
}
}
}
}
解决方案 21:
或者以命令行 Python 为例,持续 6 秒半:
python -c "import time;time.sleep(6.5)"
解决方案 22:
适用于 Windows 2000 之后的所有 Windows 版本的最佳解决方案是:
timeout numbersofseconds /nobreak > nul
解决方案 23:
有很多方法可以在 cmd/batch 中实现“睡眠”:
我最喜欢的一个:
TIMEOUT /NOBREAK 5 >NUL 2>NUL
这将使控制台停止 5 秒,没有任何输出。
最常用:
ping localhost -n 5 >NUL 2>NUL
这将尝试建立 5 次连接localhost
。由于它托管在您的计算机上,因此它将始终到达主机,因此每秒它都会尝试新的连接。标志-n
表示脚本将尝试连接的次数。在本例中为 5,因此它将持续 5 秒。
最后一个的变体:
ping 1.1.1.1 -n 5 >nul
此脚本与上一个脚本相比有一些不同。它不会尝试调用localhost
。相反,它将尝试连接到1.1.1.1
一个非常快的网站。只有当您有活动的互联网连接时,此操作才会持续 5 秒。否则,它将持续大约 15 秒才能完成操作。我不建议使用此方法。
ping 127.0.0.1 -n 5 >nul
这与示例 2(最常用)完全相同。此外,您还可以使用:
ping [::1] -n 5 >nul
相反,它使用 IPv6localhost
版本。
有很多方法可以执行此操作。不过,对于 Windows Vista 及更高版本,我更喜欢方法 1,而对于早期版本的操作系统,我更喜欢最常用的方法(方法 2)。
解决方案 24:
pathping.exe 的休眠时间少于一秒。
@echo off
setlocal EnableDelayedExpansion
echo !TIME! & pathping localhost -n -q 1 -p %~1 2>&1 > nul & echo !TIME!
。
> 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
解决方案 25:
我对这个印象深刻:
http://www.computerhope.com/batch.htm#02
choice /n /c y /d y /t 5 > NUL
从技术上讲,您是在告诉choice
命令仅接受 y。它默认为 y,在 5 秒内执行此操作,不绘制提示,并将其所说的任何内容转储到 NUL(如 Linux 上的空终端)。
解决方案 26:
您还可以使用.vbs 文件来执行特定的超时:
以下代码创建 .vbs 文件。将其放在 rbatch 代码顶部附近:
echo WScript.sleep WScript.Arguments(0) >"%cd%sleeper.vbs"
然后,下面的代码打开.vbs 并指定等待的时间:
start /WAIT "" "%cd%sleeper.vbs" "1000"
在上面的代码中,“1000”是要发送到 .vbs 文件的时间延迟值(以毫秒为单位),例如 1000 ms = 1 s。您可以将此部分更改为您想要的任意长度。
完成操作后,以下代码将删除 .vbs 文件。将其放在批处理文件的末尾:
del /f /q "%cd%sleeper.vbs"
以下是全部代码,方便复制:
echo WScript.sleep WScript.Arguments(0) >"%cd%sleeper.vbs"
start /WAIT "" "%cd%sleeper.vbs" "1000"
del /f /q "%cd%sleeper.vbs"
解决方案 27:
由于其他人建议使用第三方程序(Python、Perl、自定义应用程序等),另一个选择是适用于 Windows 的 GNU CoreUtils,可从http://gnuwin32.sourceforge.net/packages/coreutils.htm获取。
两种部署选项:
安装完整包(其中将包括全套 CoreUtils、依赖项、文档等)。
仅安装“sleep.exe”二进制文件和必要的依赖项(使用depends.exe获取依赖项)。
部署 CoreUtils 的一个好处是,您还将获得大量其他有助于脚本编写的程序(Windows 批处理有很多不足之处)。
解决方案 28:
只是为了好玩,如果你安装了 Node.js,你可以使用
node -e 'setTimeout(a => a, 5000)'
休眠 5 秒。它适用于安装了 Node v12.14.0 的 Mac。
解决方案 29:
关于这个问题有很多答案提到了 ping 的使用,但大多数都指向环回地址或现在被视为 DNS 有效地址的地址。
相反,您应该使用 IETF 为文档使用而保留的 TEST-NET IP 地址。
(更多信息请见此处)
下面是一个完整注释的批处理脚本,用于演示如何使用 ping 的睡眠功能:
@echo off
:: turns off command-echoing
echo/Script will now wait for 2.5 seconds & echo/
:: prints a line followed by a linebreak
call:sleep 2500
:: waits for two-and-a-half seconds (2500 milliseconds)
echo/Done! Press any key to continue ... & pause >NUL
:: prints a line and pauses
goto:EOF
:: prevents the batch file from executing functions beyond this point
::--FUNCTIONS--::
:SLEEP
:: call this function with the time to wait (in milliseconds)
ping 203.0.113.0 -n 1 -w "%~1" >NUL
:: 203.0.113.0 = TEST-NET-3 reserved IP; -n = ping count; -w = timeout
goto:EOF
:: ends the call subroutine
当然,如果你不想创建函数,也可以直接使用命令:
ping 203.0.113.0 -n 1 -w
timeInMilliseconds >NUL
解决方案 30:
您可以通过将 PAUSE 消息放在标题栏中来实现这一点:
@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
扫码咨询,免费领取项目管理大礼包!