Nikdy byste neměli používat cat
s /dev/urandom
. Také byste neměli používat žádné nástroje, které jsou určeny pro textové soubory.
/dev/urandom
je nepřetržitý proud náhodných dat. Nikdy nevytvoří konec souboru. Čtení s vyrovnávací pamětí zaplní vyrovnávací paměť čtení, takže i když zpracováváte výstup cat
do nějakého jiného programu, čtení nebude ukončeno, dokud nebude roura uzavřena.
Nic z toho by nebylo nic jiného než neefektivní, kromě toho, když si přečtete /dev/urandom
, spotřebováváte entropii (náhodnost), což je vzácný zdroj. Jakmile je entropie vyčerpána, /dev/urandom
výstup bude méně náhodný, což maří účel. (Bude shromážděno více entropie, ale její vytvoření chvíli trvá.)
To vše platí dvojnásobně pro /dev/random
, protože když mu dojde entropie, většinou se zablokuje. (S výjimkou OS, které dělají /dev/random
synonymum pro /dev/urandom
.)
V důsledku toho byste měli vždy číst přesně takové množství náhodných dat, které potřebujete, a nic víc.
Zřejmě míříte na 24 alfanumerických znaků. Existuje 62 možných alfanumerických znaků; značně by to zjednodušilo, kdybyste byli ochotni dovolit dvěma dalším znakům, aby celkový počet dosáhl 64. V takovém případě byste mohli získat 24 znaků extrahováním 18 bajtů náhodnosti a jejich předáním přes kodér base64. Chcete-li extrahovat přesné množství dat, použijte dd
, který je určen pro tento účel:
dd bs=18 count=1 if=/dev/urandom | base64 | tr +/ _.
(tr
na konci přeloží dva nealfanumerické znaky vytvořené base64
do dvou různých znaků, které jsou přívětivější k názvu souboru. Jen návrh.)
Pokud jste rozhodnuti používat přesně alfanumerické znaky, můžete použít strategii odmítnutí podobnou té, kterou aktuálně používáte, ale na základě výše uvedeného. Bohužel není možné přesně předpovědět, kolik vstupů budete v tomto případě potřebovat, takže nejjednodušším přístupem je přečíst si něco navíc a opakovat to ve vzácném případě, že nemáte dost:
# Here we produce 28 characters each time
until s=$(dd bs=21 count=1 if=/dev/urandom |
LC_ALL=C tr -cd A-Za-z0-9)
((${#s} >= 24)); do :; done
# When the loop ends we have at least 24 characters; truncate
s=${s:0:24}
Pokud bash nemáte, můžete nahradit ((${#s} >= 24))
s [ ${#s} -ge 24 ]
a s=${s:0:24}
s s=$(printf %.24s $s)
Ale pokud se jen pokoušíte vygenerovat dobré náhodné názvy souborů, měli byste použít mktemp
, který umožňuje zadat kostru pro jména a také ověřuje, že vygenerovaný název již není přítomen. Viz man mktemp
.
Ve skutečnosti cat /dev/urandom
nikdy nekončí sám o sobě. Ale když head -1
přečte první řádek, odejde, čímž uzavře stdin a uzavře potrubí. OS zvyšuje hodnotu SIGPIPE
na fold
je také exits a tak dále, takže cat /dev/urandom
nakonec skončí.
Ve vašem případě něco blokuje SIGPIPE
, tj. past to umí:
$ trap '' PIPE
$ cat /dev/urandom | LC_ALL=C tr -dc 'a-zA-Z0-9' | fold -w 24 | head -n 1
7FazO6mnsIow3ylkvEHB55jE
(hungs)
Zkuste to znovu povolit v subshell:
( trap - PIPE ; cat /dev/urandom | LC_ALL=C tr -dc 'a-zA-Z0-9' | fold -w 24 | head -n 1 )