Мне нужно сгенерировать случайный номер порта между 2000-65000
из сценария оболочки. Проблема $RANDOM
в 15-битном числе, поэтому я застрял!
PORT=$(($RANDOM%63000+2001))
будет работать хорошо, если бы не ограничение размера.
У кого-нибудь есть пример того, как я могу сделать это, возможно, извлекая что-то из этого /dev/urandom
и получая это в пределах диапазона?
shuf
это относительно недавно - я видел это в системах Ubuntu в последние пару лет, но не в нынешних RHEL / CentOS.shuf
что на самом деле переставляет весь ввод. Это делает плохой выбор, если вы генерируете случайные числа очень часто.time for i in {1..1000}; do shuf -i 0-$end -n 1000 > /dev/null; done
и сравнениеend=1
сend=65535
показателем улучшения примерно на 25% для более короткого диапазона, что составило разницу примерно в 4 секунды на миллион итераций. И это много быстрее , чем выполнение расчета Баш OP в миллион раз.-n 1
показало незначительную разницу во времени, даже сend=4000000000
. Полезно знать,shuf
работает умно, а не усердно :-)В Mac OS X и FreeBSD вы также можете использовать jot:
источник
jot
имеет несправедливое распределение для минимума и максимума интервала (например, 2000 и 65000). Другими словами, min и max будут генерироваться реже. Смотрите мой краткий ответ для деталей и обходного пути.jot
также доступно в большинстве дистрибутивов GNU / LinuxСогласно справочной странице bash,
$RANDOM
распределяется между 0 и 32767; то есть это 15-разрядное значение без знака. Предполагая, что$RANDOM
оно равномерно распределено, вы можете создать равномерно распределенное беззнаковое 30-разрядное целое число следующим образом:Так как ваш диапазон не является степенью 2, простая операция по модулю почти даст вам равномерное распределение, но с 30-битным входным диапазоном и менее чем 16-битным выходным диапазоном, как у вас в вашем случае, это действительно должно быть достаточно близко:
источник
$RANDOM
не всегда доступна во всех оболочках. В поисках другого решения$RANDOM
дважды. В поддерживаемых оболочках$RANDOM
новое значение генерируется каждый раз, когда на него ссылаются. Таким образом, этот код заполняет биты с 0 по 14 одним$RANDOM
значением и заполняет биты с 15 по 29 другим. Предполагая, что$RANDOM
он равномерный и независимый, он охватывает все значения от 0 до 2 ** 30-1, не пропуская ничего.и вот один с Python
и один с awk
источник
RANDOM
не гарантируется POSIX,-S
опции приводит кImportError: No module named random
. Работает, если я уберу это. Не уверен, что намерение призрака было для этого.python -S -c "import random; print random.randrange(2000,63000)"
Кажется, работает нормально. Однако, когда я пытаюсь получить случайное число от 1 до 2, я, кажется, всегда получаю 1 ... Мысли?Самый простой общий способ, который приходит на ум - это Perl One-Liner:
Вы всегда можете просто использовать два числа:
Вы все еще должны обрезать свой диапазон. Это не обычный n-битный метод случайных чисел, но он будет работать для вашего случая, и все это внутри bash.
Если вы хотите быть очень милым и читать из / dev / urandom, вы можете сделать это:
Это прочитает два байта и напечатает их как беззнаковое целое; Вы все еще должны сделать свою вырезку.
источник
awk
версии из другого ответаЕсли вы не являетесь экспертом по bash и хотели получить это в виде переменной в сценарии bash на основе Linux, попробуйте следующее:
VAR=$(shuf -i 200-700 -n 1)
Это дает вам диапазон от 200 до 700
$VAR
включительно.источник
Вот еще один. Я думал, что это сработает практически на что угодно, но случайная опция сортировки недоступна на моем ящике с кентосом на работе.
источник
sort -R
также недоступно в OS X$RANDOM
это число от 0 до 32767. Вы хотите порт между 2000 и 65000. Это 63001 возможных портов. Если мы придерживаемся значений$RANDOM + 2000
между 2000 и 33500 , мы покрываем диапазон 31501 портов. Если мы подбросим монету и затем условно добавим 31501 к результату, мы сможем получить больше портов, от 33501 до 65001 . Тогда, если мы просто отбросим 65001, мы получим точное необходимое покрытие с равномерным распределением вероятности для всех портов.тестирование
источник
Ты можешь сделать это
Если вам нужно больше подробностей, смотрите Генератор случайных чисел в скрипте оболочки .
источник
То же самое с рубином:
источник
В документации Bash говорится, что при каждой
$RANDOM
ссылке возвращается случайное число от 0 до 32767. Если мы суммируем две последовательные ссылки, мы получим значения от 0 до 65534, что покрывает желаемый диапазон 63001 возможностей для случайного числа между 2000 и 65000.Чтобы скорректировать его до точного диапазона, мы используем сумму по модулю 63001, которая даст нам значение от 0 до 63000. Это, в свою очередь, просто требует увеличения на 2000, чтобы получить желаемое случайное число, между 2000 и 65000. Это может быть резюмируется следующим образом:
тестирование
Правильность расчета
Вот полный тест грубой силы для правильности расчета. Эта программа просто пытается генерировать все 63001 различных возможностей случайным образом, используя тестируемый расчет.
--jobs
Параметр должен сделать его работать быстрее, но это не детерминированным (всего возможностей сгенерированных может быть ниже , чем 63001).Для определения того, сколько итераций необходимо для получения заданной вероятности
p/q
того, что все 63001 возможностей были сгенерированы, я полагаю, что мы можем использовать выражение ниже. Например, вот расчет для вероятности больше 1/2 , а здесь для больше 9/10 .источник
$RANDOM
является целым числом . С вашей «хитростью» есть много ценностей, которые никогда не будут достигнуты.-1
,$RANDOM
Вместо этого нам нужно суммировать два доступа и не преобразовывать их в умножение на два, поскольку$RANDOM
предполагается, что оно изменяется при каждом доступе. Я обновил ответ с версией суммы.RANDOM+RANDOM
не даст вам равномерного распределения случайных чисел между 0 иИли на OS-X у меня работает следующее:
источник
PORT=$(($RANDOM%63000+2001))
это близко к тому, что вы хотите, я думаю.PORT=$(($RANDOM$RANDOM$RANDOM%63000+2001))
обходит ограничение размера, которое вас беспокоит. Поскольку bash не делает различий между числовой переменной и строковой переменной, это работает на отлично. «Число»$RANDOM
может быть объединено как строка, а затем использовано в качестве числа в расчете. Удивительный!источник
x=$(( $n%63000 )
примерно похож наx=$(( $n % 65535 )); if [ $x -gt 63000 ]; then x=63000
.Вы можете получить случайное число через
urandom
head -200 /dev/urandom | cksum
Вывод:
3310670062 52870
Чтобы получить одну часть вышеуказанного номера.
head -200 /dev/urandom | cksum | cut -f1 -d " "
Тогда вывод
3310670062
Чтобы удовлетворить ваши требования,
head -200 /dev/urandom |cksum | cut -f1 -d " " | awk '{print $1%63000+2001}'
источник
Так я обычно генерирую случайные числа. Затем я использую «NUM_1» в качестве переменной для номера порта, который я использую. Вот краткий пример сценария.
источник