Necesito generar un número de puerto aleatorio entre 2000-65000un script de shell. El problema es$RANDOM es un número de 15 bits, ¡así que estoy atascado!
PORT=$(($RANDOM%63000+2001)) funcionaría bien si no fuera por la limitación de tamaño.
¿Alguien tiene un ejemplo de cómo puedo hacer esto, tal vez extrayendo algo /dev/urandomy poniéndolo dentro de un rango?

shufes relativamente reciente: lo he visto en los sistemas Ubuntu en los últimos dos años, pero no en el RHEL / CentOS actual.shufque en realidad permuta toda la entrada. Esto lo convierte en una mala elección si está generando números aleatorios con mucha frecuencia.time for i in {1..1000}; do shuf -i 0-$end -n 1000 > /dev/null; doney comparandoend=1aend=65535mostró aproximadamente una mejora del 25% para la gama más corta que ascendió a aproximadamente 4 segundos diferencia más de un millón iteraciones. Y es mucho más rápido que realizar el cálculo de Bash del OP un millón de veces.-n 1mostró diferencias de tiempo insignificantes, incluso conend=4000000000. Es bueno saber queshuffunciona de manera inteligente, no difícil :-)En Mac OS X y FreeBSD también puede usar jot:
fuente
jottiene una distribución injusta para el mínimo y el máximo del intervalo (es decir, 2000 y 65000). En otras palabras, el mínimo y el máximo se generarán con menos frecuencia. Vea mi respuesta jota para más detalles y una solución alternativa.jottambién está disponible en la mayoría de las distribuciones de GNU / LinuxSegún la página de manual de bash,
$RANDOMse distribuye entre 0 y 32767; es decir, es un valor de 15 bits sin signo. Suponiendo que$RANDOMse distribuye uniformemente, puede crear un entero de 30 bits sin signo distribuido uniformemente de la siguiente manera:Debido a que su rango no es una potencia de 2, un simple operación de módulo sólo será casi le dan una distribución uniforme, pero con un rango de entrada de 30 bits y un rango de salida de menos-que-16 bits, ya que tiene en su caso, esto realmente debería estar lo suficientemente cerca:
fuente
$RANDOMno siempre está disponible en todos los shells. Buscando otra solución$RANDOMdos veces. En los shells que admiten$RANDOM, se genera un nuevo valor cada vez que se hace referencia a él. Entonces, este código llena los bits 0 a 14 con un$RANDOMvalor y los bits 15 a 29 con otro. Suponiendo que$RANDOMsea uniforme e independiente, esto cubre todos los valores de 0 a 2 ** 30-1 sin omitir nada.y aquí hay uno con Python
y uno con awk
fuente
RANDOMPOSIX no lo garantiza,-Sopción da como resultadoImportError: No module named random. Funciona si elimino eso. No estoy seguro de cuál era la intención de ghostdog para eso.python -S -c "import random; print random.randrange(2000,63000)"Parece funcionar bien. Sin embargo, cuando trato de obtener un número aleatorio entre 1 y 2, parece que siempre obtengo 1 ... ¿Pensamientos?La forma general más simple que me viene a la mente es una línea perl:
Siempre puedes usar dos números:
Todavía tiene que recortar a su rango. No es un método general de números aleatorios de n bits, pero funcionará para su caso, y todo está dentro de bash.
Si quieres ser realmente lindo y leer desde / dev / urandom, puedes hacer esto:
Eso leerá dos bytes y los imprimirá como un int sin signo; todavía tienes que hacer tu recorte.
fuente
awkSi no eres un experto en bash y estabas buscando convertir esto en una variable en un script bash basado en Linux, prueba esto:
VAR=$(shuf -i 200-700 -n 1)Eso te da el rango de 200 a 700
$VAR, inclusive.fuente
Aqui hay otro más. Pensé que funcionaría en casi cualquier cosa, pero la opción aleatoria de ordenar no está disponible en mi caja de centos en el trabajo.
fuente
sort -Rtampoco está disponible en OS X.$RANDOMes un número entre 0 y 32767. Desea un puerto entre 2000 y 65000. Estos son 63001 puertos posibles. Si nos atenemos a valores$RANDOM + 2000entre 2000 y 33500 , cubrimos un rango de 31501 puertos. Si lanzamos una moneda y luego agregamos condicionalmente 31501 al resultado, podemos obtener más puertos, de 33501 a 65001 . Entonces, si simplemente dejamos caer 65001, obtenemos la cobertura exacta necesaria, con una distribución de probabilidad uniforme para todos los puertos, parece.Pruebas
fuente
Puedes hacerlo
Si necesita más detalles, consulte Shell Script Random Number Generator .
fuente
Lo mismo con el rubí:
fuente
La documentación de Bash dice que cada vez
$RANDOMse hace referencia, se devuelve un número aleatorio entre 0 y 32767. Si sumamos dos referencias consecutivas, obtenemos valores de 0 a 65534, que cubren el rango deseado de 63001 posibilidades para un número aleatorio entre 2000 y 65000.Para ajustarlo al rango exacto, utilizamos el módulo de suma 63001, que nos dará un valor de 0 a 63000. Esto a su vez solo necesita un incremento en 2000 para proporcionar el número aleatorio deseado, entre 2000 y 65000. Esto puede ser resumido de la siguiente manera:
Pruebas
Corrección del cálculo.
Aquí hay una prueba completa de fuerza bruta para la exactitud del cálculo. Este programa solo intenta generar todas las 63001 posibilidades diferentes al azar, utilizando el cálculo bajo prueba. El
--jobsparámetro debería hacer que se ejecute más rápido, pero no es determinista (el total de posibilidades generadas puede ser inferior a 63001).Para determinar cuántas iteraciones se necesitan para obtener una probabilidad dada
p/qde que se hayan generado todas las posibilidades de 63001, creo que podemos usar la expresión a continuación. Por ejemplo, aquí está el cálculo para una probabilidad mayor que 1/2 , y aquí para mayor que 9/10 .fuente
$RANDOMes un número entero . Con su "truco" hay muchos valores que nunca se alcanzarán.-1.$RANDOM, y no refactorizar eso en una multiplicación por dos, ya que$RANDOMse supone que cambia en cada acceso. He actualizado la respuesta con la versión de suma.RANDOM+RANDOMno te dará una distribución uniforme de números aleatorios entre 0 y 65534.O en OS-X, lo siguiente funciona para mí:
fuente
PORT=$(($RANDOM%63000+2001))está cerca de lo que quieres, creo.PORT=$(($RANDOM$RANDOM$RANDOM%63000+2001))evita la limitación de tamaño que te preocupa. Como bash no hace distinciones entre una variable numérica y una variable de cadena, esto funciona perfectamente bien. El "número"$RANDOMpuede concatenarse como una cadena, y luego usarse como un número en un cálculo. ¡Asombroso!fuente
x=$(( $n%63000 )es más o menos similar ax=$(( $n % 65535 )); if [ $x -gt 63000 ]; then x=63000.Puede obtener el número aleatorio a través de
urandomhead -200 /dev/urandom | cksumSalida:
3310670062 52870Para recuperar la parte del número anterior.
head -200 /dev/urandom | cksum | cut -f1 -d " "Entonces la salida es
3310670062Para cumplir con sus requisitos,
head -200 /dev/urandom |cksum | cut -f1 -d " " | awk '{print $1%63000+2001}'fuente
Así es como generalmente genero números aleatorios. Luego uso "NUM_1" como la variable para el número de puerto que uso. Aquí hay un breve script de ejemplo.
fuente