GNU/Linux >> Znalost Linux >  >> Linux

Proč cat /dev/urandom zavěsil můj bash skript?

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 )

Linux
  1. Jak Linux zpracovává více po sobě jdoucích oddělovačů cest (/home////username///soubor)?

  2. Bash =~ Regex A Https://regex101.com/?

  3. Kdy použít /dev/random vs /dev/urandom?

  1. Proč nemohu použít CD ve skriptu Bash?

  2. Linux – Co znamená písmeno „u“ v /dev/urandom?

  3. Jak kódovat base64 /dev/random nebo /dev/urandom?

  1. Spusťte příkaz bash na jenkins pipeline

  2. Proč Linux uvádí jednotky NVMe jako /dev/nvme0 namísto /dev/sda?

  3. Jak Linux používá /dev/tty a /dev/tty0