GNU/Linux >> Tutoriales Linux >  >> Linux

Cómo generar números aleatorios en el shell BusyBox

$RANDOM y od son características opcionales en BusyBox, asumo dada su pregunta que no están incluidas en su binario. Mencionas en un comentario que /dev/urandom está presente, eso es bueno, significa que lo que debe hacer es recuperar bytes de él en una forma utilizable, y no el problema mucho más difícil de implementar un generador de números aleatorios. Tenga en cuenta que debe usar /dev/urandom y no /dev/random , consulte ¿Es seguro un rand de /dev/urandom para una clave de inicio de sesión?

Si tienes tr o sed , puede leer bytes desde /dev/urandom y descarta cualquier byte que no sea un carácter deseable. También necesitará una forma de extraer un número fijo de bytes de una secuencia:head -c (requiere FEATURE_FANCY_HEAD para ser habilitado) o dd (requiere dd para ser compilado). Cuantos más bytes descartes, más lento será este método. Aún así, generar bytes aleatorios suele ser bastante rápido en comparación con bifurcar y ejecutar binarios externos, por lo que descartar muchos de ellos no va a doler mucho. Por ejemplo, el siguiente fragmento generará un número aleatorio entre 0 y 65535:

n=65536
while [ $n -ge 65536 ]; do
  n=1$(</dev/urandom tr -dc 0-9 | dd bs=5 count=1 2>/dev/null)
  n=$((n-100000))
done

Tenga en cuenta que debido al almacenamiento en búfer, tr va a procesar bastantes bytes más que lo que dd se acabará manteniendo. tr de BusyBox lee un búfer completo (al menos 512 bytes) a la vez y vacía su búfer de salida cada vez que el búfer de entrada se procesa por completo, por lo que el comando anterior siempre leerá al menos 512 bytes de /dev/urandom (y muy raramente más ya que la toma esperada de 512 bytes de entrada es de 20 dígitos decimales).

Si necesita una cadena imprimible única, simplemente deseche los caracteres que no sean ASCII y quizás algunos caracteres de puntuación molestos:

nonce=$(</dev/urandom tr -dc A-Za-z0-9-_ | head -c 22)

En esta situación, consideraría seriamente escribir un programa C pequeño y dedicado. Aquí hay uno que lee cuatro bytes y genera el número decimal correspondiente. No se basa en ninguna función libc que no sean los contenedores para las llamadas del sistema read y write , por lo que puede obtener un binario muy pequeño. Se deja como ejercicio admitir un tope variable pasado como un entero decimal en la línea de comando; le costará cientos de bytes de código (no es algo de lo que deba preocuparse si su objetivo es lo suficientemente grande como para ejecutar Linux).

#include <stddef.h>
#include <unistd.h>
int main () {
    int n;
    unsigned long x = 0;
    unsigned char buf[4];
    char dec[11]; /* Must fit 256^sizeof(buf) in decimal plus one byte */
    char *start = dec + sizeof(dec) - 1;
    n = read(0, buf, sizeof(buf));
    if (n < (int)sizeof(buf)) return 1;
    for (n = 0; n < (int)sizeof(buf); n++) x = (x << 8 | buf[n]);
    *start = '\n';
    if (x == 0) *--start = '0';
    else while (x != 0) {
        --start;
        *start = '0' + (x % 10);
        x = x / 10;
    }
    while (n = write(1, start, dec + sizeof(dec) - start),
           n > 0 && n < dec + sizeof(dec) - start) {
        start += n;
    }
    return n < 0;
}

</dev/urandom sed 's/[^[:digit:]]\+//g' | head -c10

Linux
  1. ¿Cómo asignar la salida de un comando a una variable de shell?

  2. ¿Cómo detectar si el Shell está controlado desde Ssh?

  3. CentOS / RHEL:cómo cambiar el shell de inicio de sesión del usuario

  4. Cómo iniciar KVM Guest en un shell de rescate

  5. ¿Cómo obtener el PYTHONPATH en shell?

Cómo instalar Fish, The Friendly Interactive Shell, en Linux

Cómo cambiar el shell predeterminado en el sistema Linux

Maneras simples de generar una contraseña aleatoria en Linux Shell

¿Cómo mostrar los caracteres de control (^c, ^d, ^[, …) de manera diferente en el Shell?

Cómo cambiar el shell predeterminado en Linux

Sume una columna de números en el shell de Unix