GNU/Linux >> Linux Esercitazione >  >> Linux

Come generare numeri casuali nella shell BusyBox

$RANDOM e od sono funzionalità opzionali in BusyBox, presumo data la tua domanda che non siano incluse nel tuo file binario. In un commento menzioni che /dev/urandom è presente, va bene, significa che ciò che devi fare è recuperare i byte da esso in una forma utilizzabile, e non il problema molto più difficile dell'implementazione di un generatore di numeri casuali. Nota che dovresti usare /dev/urandom e non /dev/random , vedi È sicuro un rand da /dev/urandom per una chiave di accesso?.

Se hai tr o sed , puoi leggere i byte da /dev/urandom e scartare qualsiasi byte che non è un carattere desiderabile. Avrai anche bisogno di un modo per estrarre un numero fisso di byte da uno stream:head -c (richiede FEATURE_FANCY_HEAD da abilitare) o dd (richiede dd da compilare). Più byte scarti, più lento sarà questo metodo. Tuttavia, la generazione di byte casuali di solito è piuttosto veloce rispetto al fork e all'esecuzione di binari esterni, quindi scartarne molti non farà molto male. Ad esempio, il seguente frammento produrrà un numero casuale compreso tra 0 e 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

Nota che a causa del buffering, tr elaborerà un bel po' di byte in più rispetto a quanto dd finirà per mantenere. tr di BusyBox legge un buffer pieno (almeno 512 byte) alla volta e scarica il suo buffer di output ogni volta che il buffer di input è completamente elaborato, quindi il comando precedente leggerà sempre almeno 512 byte da /dev/urandom (e molto raramente di più poiché il recupero previsto da 512 byte di input è di 20 cifre decimali).

Se hai bisogno di una stringa stampabile univoca, elimina i caratteri non ASCII e forse alcuni fastidiosi caratteri di punteggiatura:

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

In questa situazione, prenderei seriamente in considerazione la possibilità di scrivere un piccolo programma C dedicato. Eccone uno che legge quattro byte e restituisce il numero decimale corrispondente. Non si basa su alcuna funzione libc diversa dai wrapper per le chiamate di sistema read e write , quindi puoi ottenere un binario molto piccolo. Il supporto di una variabile cap passata come numero intero decimale sulla riga di comando viene lasciato come esercizio; ti costerà centinaia di byte di codice (non qualcosa di cui devi preoccuparti se il tuo target è abbastanza grande per eseguire 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. Come assegnare l'output di un comando a una variabile di shell?

  2. Come rilevare se la shell è controllata da Ssh?

  3. Somma una colonna di numeri nella shell Unix

  4. Come ottenere PYTHONPATH nella shell?

  5. Come verificare se la shell attualmente in esecuzione è BusyBox

Come installare Fish, la shell interattiva amichevole, in Linux

Come modificare la shell predefinita nel sistema Linux

Semplici modi per generare una password casuale su Linux Shell

Come avviare KVM Guest in una shell di Rescue

Come eseguire il comando Vim dalla shell?

Come contare il numero di byte in un file, raggruppando gli stessi byte?