it-swarm.com.ru

Спать в пакетном файле

При написании командного файла для автоматизации чего-либо на 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 предоставляет 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)
137
Jason Etheridge

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

import time, sys

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

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

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

14
tzot

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

Используя описанный выше метод 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
21
daniel

SLEEP.exe включен в большинство наборов ресурсов, например Windows Server 2003 Resource Kit , который также может быть установлен в Windows XP.

Usage:  sleep      time-to-sleep-in-seconds
        sleep [-m] time-to-sleep-in-milliseconds
        sleep [-c] commited-memory ratio (1%-100%)
15
Luk

Я не согласен с ответами, которые нашел здесь.

Я использую следующий метод, полностью основанный на возможностях 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

Вы также можете вставить день в расчет, чтобы метод также работал, когда интервал задержки превышал полночь.

15
Aacini

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

При сбое сервера, был задан похожий вопрос , решение было:

choice /d y /t 5 > nul
10
mlsteeves

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

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

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

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

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

ping -n 6 localhost >nul 2>&1

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

timeout 6 >nul
8
Joey

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

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

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

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

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

8
paxdiablo
timeout /t <seconds> <options>

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

timeout /t 2 /nobreak >NUL

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

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

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

6
mgthomas99

Есть лучший способ спать, используя пинг. Вы захотите пропинговать адрес, который не существует, поэтому вы можете указать время ожидания с точностью до миллисекунды. К счастью, такой адрес определен в стандарте (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

5
mafu

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

@ping 127.0.0.1 -n 11 -w 1000 > null
5
Brent Stewart

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

@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>
4
SuperKael

Если у вас есть 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 мс).

4
Niall Connaughton

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

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

4
Daren Thomas

Мне нравится ответ Аасини . Я добавил его для обработки дня, а также разрешил обрабатывать сантисекунды (%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
3
Hossy

Я использовал эту программу сна 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>\nExample: sleep 10");
            }
        }
    }
}
3
Liam

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

timeout numbersofseconds /nobreak > nul
2
Tato

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

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

Найти уже готовый исполняемый файл для сна - самый удобный способ. Просто поместите его в папку 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);

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

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

2
Tooony

Еще более легким, чем решение Python, является Perl Однострочный.

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

Perl -e "sleep 7"

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

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

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

2
Peter Mortensen

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

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

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

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

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

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

1
Chris Moschini

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

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

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
1
npocmaka

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
1
Andry

Вы также можете использовать файл .vbs для определенных таймаутов:

Код ниже создает файл .vbs. Поместите это в верхней части кода rbatch:

echo WScript.sleep WScript.Arguments(0) >"%cd%\sleeper.vbs"

Затем приведенный ниже код открывает файл .vbs и указывает, как долго ждать:

start /WAIT "" "%cd%\sleeper.vbs" "1000"

В приведенном выше коде «1000» - это значение временной задержки, отправляемой в файл .vbs в миллисекундах, например, 1000 мс = 1 с. Вы можете изменить эту часть так долго, как вы хотите.

Приведенный ниже код удаляет файл .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"
1
EpicNinjaCheese

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

2 варианта размещения:

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

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

0
codesniffer

Вы можете получить фантазию, поместив сообщение 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
0
djangofan

Это было проверено на 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
0
Anonymous Coward