$RANDOM
a od
jsou volitelné funkce v BusyBox, předpokládám vzhledem k vaší otázce, že nejsou zahrnuty ve vašem binárním souboru. V komentáři uvádíte, že /dev/urandom
je přítomen, to je dobře, to znamená, že z něj musíte získat bajty v použitelné formě, a ne mnohem obtížnější problém implementace generátoru náhodných čísel. Všimněte si, že byste měli použít /dev/urandom
a ne /dev/random
, viz Je rand z /dev/urandom bezpečný pro přihlašovací klíč?.
Pokud máte tr
nebo sed
, můžete číst bajty od /dev/urandom
a zahoďte jakýkoli bajt, který není žádoucí znak. Budete také potřebovat způsob, jak extrahovat pevný počet bajtů ze streamu:buď head -c
(vyžaduje FEATURE_FANCY_HEAD
být povolen) nebo dd
(vyžaduje dd
ke zkompilování). Čím více bajtů zahodíte, tím pomalejší bude tato metoda. Generování náhodných bajtů je však obvykle poměrně rychlé ve srovnání s forkingem a spouštěním externích binárních souborů, takže vyřazení velkého množství z nich nebude moc bolet. Například následující fragment vytvoří náhodné číslo mezi 0 a 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
Všimněte si, že kvůli ukládání do vyrovnávací paměti tr
zpracuje o několik bajtů více než dd
nakonec udrží. BusyBox je tr
čte vyrovnávací paměť (alespoň 512 bajtů) najednou a vyprázdní její výstupní vyrovnávací paměť vždy, když je vstupní vyrovnávací paměť plně zpracována, takže příkaz výše vždy načte alespoň 512 bajtů z /dev/urandom
(a velmi zřídka více, protože očekávaný odběr z 512 vstupních bajtů je 20 dekadických číslic).
Pokud potřebujete jedinečný tisknutelný řetězec, vyhoďte jiné znaky než ASCII a možná i některé nepříjemné interpunkční znaky:
nonce=$(</dev/urandom tr -dc A-Za-z0-9-_ | head -c 22)
V této situaci bych vážně uvažoval o napsání malého, vyhrazeného C programu. Zde je jeden, který přečte čtyři bajty a vydá odpovídající desetinné číslo. Nespoléhá se na žádnou jinou funkci knihovny libc než na obaly pro systémová volání read
a write
, takže můžete získat velmi malou binární hodnotu. Podpora proměnné cap předaná jako celé desítkové číslo na příkazovém řádku je ponechána jako cvičení; bude vás to stát stovky bajtů kódu (není něco, o co byste se museli starat, pokud je váš cíl dostatečně velký na to, aby provozoval 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