Спящий в пакетном файле

При написании командного файла для автоматизации чего-либо на 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 Resource Kit предоставляет Una-подобную команду сна (наконец-то!). В то же время, для тех из нас, кто все еще использует 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

Если у вас установлен Python или вы не против его установить (он также используется и в других целях :), просто создайте следующий скрипт sleep.py и добавьте его где-нибудь в своем PATH:

import time, sys

time.sleep(float(sys.argv[1]))

Это позволит делать паузы длительностью менее секунды (например, 1,5 с, 0,1 и т.д.), если у вас есть такая необходимость. Если вы хотите назвать его как sleep, а не sleep.py, то вы можете добавить расширение .PY в переменную среды PATHEXT. В Windows XP вы можете отредактировать его в:

Мой компьютер → Свойства (меню) → Дополнительно (вкладка) → Переменные среды (кнопка) → Системные переменные (рамка)

ОБНОВЛЕНИЕ: Команда timeout, доступная в Windows Vista и далее, должна быть используемой командой, как описано в другом ответе на этот вопрос.

Ответ 2

Команда 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

Примечание: он не работает с перенаправлением ввода - тривиальный пример:

C:\>echo 1 | timeout /t 1 /nobreak
ERROR: Input redirection is not supported, exiting the process immediately.

Ответ 3

Используя метод ping, как описано, как это сделать, когда я не могу (или не хочу) добавлять дополнительные исполняемые файлы или устанавливать любое другое программное обеспечение.

Вы должны пинговать что-то, чего там нет, и использовать флаг -w, чтобы он терпел неудачу после такого количества времени, а не пинговать что-то, что есть (например, 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

Ответ 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 для задержки в пакетном файле:

DELAY.BAT:

@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

У меня возникла аналогичная проблема, но я просто сбил очень короткое консольное приложение на С++, чтобы сделать то же самое. Просто запустите 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\n"), argv[1]);
        Sleep(_tstoi(argv[1]));
    }
    else
    {
        _tprintf(_T("Wrong number of arguments.\n"));
    }
    return 0;
}

Ответ 8

Вы можете использовать Windows cscript WSH и этот файл JavaScript wait.js:

if (WScript.Arguments.Count() == 1)
    WScript.Sleep(WScript.Arguments(0)*1000);
else
    WScript.Echo("Usage: cscript wait.js seconds");

Ответ 9

Вы можете использовать ping:

ping 127.0.0.1 -n 11 -w 1000 >nul: 2>nul:

Он будет ждать 10 секунд.

Причина, по которой вы должны использовать 11, состоит в том, что первый пинг выходит сразу, а не через одну секунду. Номер всегда должен быть больше, чем количество секунд, которое вы хотите подождать.

Имейте в виду, что цель -w - не ждать одной секунды. Это позволит вам ждать не более одной секунды, если есть проблемы с сетью. ping сам пошлет один ICMP-пакет в секунду. Вероятно, это не требуется для локального хоста, но старые привычки умирают.

Ответ 10

В зависимости от ваших потребностей в совместимости используйте ping:

ping -n <numberofseconds+1> localhost >nul 2>&1

например. подождите 5 секунд, используйте

ping -n 6 localhost >nul 2>&1

или в Windows 7 или более поздней версии используйте timeout:

timeout 6 >nul

Ответ 11

Есть лучший способ спать, используя пинг. Вы захотите выполнить 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

Ответ 12

timeout /t <seconds> <options>

Например, чтобы сделать script выполнение не-прерывистого 2-секундного ожидания:

timeout /t 2 /nobreak >NUL

Это означает, что script будет ждать 2 секунды, прежде чем продолжить.

По умолчанию нажатие клавиши прерывает таймаут, поэтому используйте переключатель /nobreak, если вы не хотите, чтобы пользователь мог прервать (отменить) ожидание. Кроме того, тайм-аут будет предоставлять уведомления за секунду, чтобы уведомить пользователя о том, как долго осталось ждать; это можно удалить, выполнив команду NUL.

изменить. @martineau указывает в комментариях, Команда timeout доступна только для Windows 7 и выше. Кроме того, команда ping использует меньшее процессорное время, чем timeout. Я по-прежнему верю в использование timeout, где это возможно, хотя это более читаемо, чем ping 'hack'. Подробнее здесь.

Ответ 13

Просто поместите это в свой командный файл, где вы хотите подождать.

@ping 127.0.0.1 -n 11 -w 1000 > null

Ответ 14

Если у вас есть PowerShell в вашей системе, вы можете просто выполнить эту команду:

powershell -command "Start-Sleep -s 1"

Изменить: от мой ответ на аналогичный поток, люди подняли проблему, когда количество времени, которое требуется для запуска, будет значительным по сравнению с тем, как долго вы пытаетесь ждать. Если важна точность времени ожидания (т.е. Вторая или две дополнительные задержки неприемлемы), вы можете использовать этот подход:

powershell -command "$sleepUntil = [DateTime]::Parse('%date% %time%').AddSeconds(5); $sleepDuration = $sleepUntil.Subtract((get-date)).TotalMilliseconds; start-sleep -m $sleepDuration"

Это занимает время, когда была выписана команда Windows, а powershell script спящий до 5 секунд после этого времени. Таким образом, пока PowerShell занимает меньше времени, чем ваша продолжительность сна, этот подход будет работать (он составляет около 600 мс на моей машине).

Ответ 15

Resource Kit всегда включал это. По крайней мере, с Windows 2000.

Кроме того, пакет Cygwin имеет sleep - plop, который находится в вашем PATH, и включает в себя cygwin.dll (или что бы он там ни называл) и путь!

Ответ 16

В Блокноте напишите:

@echo off
set /a WAITTIME=%1+1
PING 127.0.0.1 -n %WAITTIME% > nul
goto:eof

Теперь сохраните как wait.bat в папке C:\WINDOWS\System32, то всякий раз, когда вы хотите подождать, используйте:

CALL WAIT.bat <whole number of seconds without quotes>

Ответ 17

Я использую эту программу сна С#. Это может быть более удобно для вас, если С# - ваш предпочтительный язык:

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>\nExample: sleep 10");
            }
        }
    }
}

Ответ 18

Мне нравится ответ Aacini. Я добавил к нему, чтобы обработать этот день, а также позволить ему обрабатывать centiseconds (%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

Ответ 19

Использование ping является хорошим, если вы просто хотите "подождать немного". Это связано с тем, что вы зависите от других функций, таких как ваша сеть, и того факта, что на 127.0.0.1 ничего не найдено.;-) Возможно, это маловероятно, но это не невозможно...

Если вы хотите быть уверенным, что вы ожидаете точно указанное время, вы должны использовать функциональность sleep (которая также имеет то преимущество, что она не использует мощность процессора или не ждет, когда сеть станет готовой).

Найти уже сделанный исполняемый файл для сна - самый удобный способ. Просто запустите его в свою папку Windows или любую другую часть вашего стандартного пути, и она всегда доступна.

В противном случае, если у вас есть среда компиляции, вы можете легко сделать ее самостоятельно. Функция sleep доступна в kernel32.dll, поэтому вам просто нужно использовать ее.:-) Для VB/VBA объявите следующее в начале вашего источника, чтобы объявить функцию сна:

private Declare Sub Sleep Lib "kernel32" Alias "Sleep" (byval dwMilliseconds as Long)

Для С#:

[DllImport("kernel32.dll")]
static extern void Sleep(uint dwMilliseconds);

Подробнее об этой функциональности (доступной с Windows 2000) вы найдете в функция сна (MSDN).

В стандарте C, sleep() включен в стандартную библиотеку, а в Microsoft Visual Studio C функция называется sleep(), если мне служит память.;-) Эти два аргумента принимают за секунды, а не в миллисекундах, как две предыдущие объявления.

Ответ 20

Еще более легкий, чем решение Python, - это Perl один вкладыш.

Чтобы спать в течение семи секунд, поместите это в BAT script:

perl -e "sleep 7"

Это решение обеспечивает разрешение одной секунды.

Если вам требуется более высокое разрешение, используйте Time:: HiRes модуль из CPAN. Он обеспечивает usleep(), который спит в микросекунд и nanosleep(), который спит в наносекундах (обе функции принимают только целые аргументы). См. Stack Вопрос о переполнении Как спятиться за миллисекунду в Perl? для получения дополнительной информации.

Я использовал ActivePerl в течение многих лет. Очень легко установить.

Ответ 21

Или в командной строке Python, например, в течение 6 с половиной секунд:

python -c "import time;time.sleep(6.5)"

Ответ 22

Лучшим решением, которое должно работать на всех версиях Windows после Windows 2000, будет следующее:

timeout numbersofseconds /nobreak > nul

Ответ 23

Я впечатлен этим:

http://www.computerhope.com/batch.htm#02

choice /n /c y /d y /t 5 > NUL

Технически вы сообщаете команде choice принимать только y. По умолчанию он равен y, чтобы сделать это за 5 секунд, чтобы не нарисовать приглашение, и сбросить все, что он говорит в NUL (например, нулевой терминал в Linux).

Ответ 24

Из Windows Vista у вас есть TIMEOUT и SLEEP, но для их использования в Windows XP или Windows Server 2003 вам понадобится набор инструментов для Windows Server 2003.

Здесь у вас есть хороший обзор альтернатив сна (пинг-подход является самым популярным, поскольку он будет работать на каждой машине Windows) но там (по крайней мере) не указано, что (ab) использует команду W32TM (Time Service):

w32tm /stripchart /computer:localhost /period:1 /dataonly /samples:N  >nul 2>&1

Где вы должны заменить N секундами, которые вы хотите приостановить. Кроме того, он будет работать на каждой системе Windows без предварительных условий.

Также можно использовать Typeperf:

typeperf "\System\Processor Queue Length" -si N -sc 1 >nul

Ответ 25

Вы также можете использовать файл .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"

Ответ 26

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

Ответ 27

Вы можете получить фантазию, поместив сообщение ПАУЗА в строку заголовка:

@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

Ответ 28

Это было протестировано на Windows XP SP3 и Windows 7 и использует CScript. Я поставил несколько безопасных охранников, чтобы избежать "подсказки". (/q было бы опасно)

Подождите одну секунду:

sleepOrDelayExecution 1000

Подождите 500 мс, а затем запустите файл после:

sleepOrDelayExecution 500 dir \ /s

sleepOrDelayExecution.bat:

@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

Ответ 29

Поскольку другие предлагают сторонние программы (Python, Perl, пользовательские приложения и т.д.), Другой вариант - GNU CoreUtils для Windows, доступный по адресу http://gnuwin32.sourceforge.net/packages/coreutils.htm.

2 варианта развертывания:

  1. Установите полный пакет (который будет включать полный набор CoreUtils, зависимостей, документации и т.д.).
  2. Установите только двоичный файл "sleep.exe" и необходимые зависимости (для получения зависимостей используйте зависящий от .exe файл).

Одним из преимуществ развертывания CoreUtils является то, что вы дополнительно получите множество других программ, которые полезны для сценариев (пакет Windows оставляет желать лучшего).

Ответ 30

ping -n X 127.0.0.1 > nul

Замените X числом секунд + 1.

Например, если вы должны подождать 10 секунд, замените X на 11. Чтобы подождать 5 секунд, используйте 6.

Прочитайте более ранние ответы за миллисекунды.