Почему% random% в Windows времени и как получить реальное случайное число? - PullRequest
1 голос
/ 20 января 2020

Я использую следующий скрипт:

set /a num=%random% %%1000 +3000
timeout /T %num%
taskkill /F /IM chrome.exe

Я запускаю его с помощью планировщика задач Windows на нескольких виртуальных машинах одновременно.

Проблема заключается в следующем: не совсем случайно. Такое ощущение, что оно Windows основано на времени. Я получаю одинаковое значение на каждой машине.

Ответы [ 3 ]

0 голосов
/ 22 января 2020

Используйте powershell для получения случайных чисел в диапазоне:

@Echo Off
For /F %%a in ('Powershell -Command "& {[math]::Floor(Get-Random -Maximum 3000 -Minimum 1000)}"') Do Set rand=%%a
Echo %rand%
Timeout /T %rand%
Taskkill /F /Im chrome.exe
Pause >nul
0 голосов
/ 02 апреля 2020

Это чисто пакетное решение без каких-либо VBS, JScript или PowerShell, но настоятельно рекомендуется просто избегать использования cmd с неприятными унаследованными вещами и просто использовать PowerShell

Почему% случайный% Windows время и как получить реальное случайное число?

%random% - это специальная переменная в cmd.exe. Он не имеет ничего общего с Windows. Он засеян известным классом c srand((unsigned)time(NULL)); 1 , как и большинство наивных / простых C или C ++ кодов, поэтому он не может обеспечить правильные случайные последовательности, если все они начинаются в одну секунду (что разрешение функции time()). Есть так много связанных проблем:

Распространенным решением является использование значения времени высокого разрешения, такого как наносекунда. Это все еще «основано на времени», но почти все случайные числа являются псевдослучайными и засеваются со временем, подобным этому. Нет другого хорошего способа получить другое семя, которое меняется каждый раз. Вы никогда не сможете получить действительное случайное число в компьютерах без реального источника энтропии

Вы можете сделать подобный обходной путь, изменив значение с точностью до секунды: set /a "num=(%random% ^ %time:~-2%) %% 1000 + 3000". Или получите миллисекунду как это

for /F "usebackq tokens=2 delims==" %%i in (
    `wmic os get LocalDateTime /VALUE`
) do @set ctime=%%i
set /a "num=(%random% ^ %ctime:~15,3%) %% 1000 + 3000"

Для лучших результатов некоторые программы объединяют время с идентификатором процесса, чтобы ни у двух процессов не было одинакового начального числа. Вы также можете сделать это

for /f "usebackq tokens=2 delims==; " %%a in (
    `wmic process call create '"cmd.exe" "/c exit"' ^| find "ProcessId"`
) do @set PID=%%a
for /F "usebackq tokens=2 delims==" %%i in (
    `wmic os get LocalDateTime /VALUE`
) do @set ctime=%%i
set /a "num=(%random% + %ctime:~15,3%*31 ^ %PID%) %% 1000 + 3000"

Здесь вместо текущего PID используется PID ребенка, но для этой цели он такой же


1 Как бы случайно я ни был: почему cmd.exe% RANDOM% не такой случайный

0 голосов
/ 20 января 2020

Используйте vbscript, чтобы получить случайное число и введите свой номер в max и Min значение:

@echo off
cd /d "%~dp0"
set /a max=3000
set /a min=1
(
Echo max=%max%:min=%min%:Randomize
Echo WSH.Echo ^(Int^(^(max-min+1^)^*Rnd+min^) + max^) ) >> Vbscript.vbs
FOR /F %%A IN ('cscript //nologo Vbscript.vbs') DO Set RAND=%%A
Del "Vbscript.vbs"
Echo %RAND%
timeout /T %RAND%
taskkill /F /IM chrome.exe
pause>nul
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...