Sie sollten niemals cat
verwenden mit /dev/urandom
. Sie sollten auch keine Dienstprogramme verwenden, die für Textdateien entwickelt wurden.
/dev/urandom
ist ein kontinuierlicher Strom zufälliger Daten. Es wird niemals ein Dateiende erzeugt. Gepufferte Lesevorgänge füllen den Lesepuffer, also auch dann, wenn Sie die Ausgabe von cat
weiterleiten in ein anderes Programm, wird der Lesevorgang erst beendet, wenn die Pipe geschlossen wird.
Nichts davon wäre alles andere als ineffizient, außer wenn Sie /dev/urandom
lesen verbrauchen Sie Entropie (Zufälligkeit), die eine wertvolle Ressource ist. Sobald die Entropie aufgebraucht ist, /dev/urandom
Die Ausgabe von ist weniger zufällig, was den Zweck verfehlt. (Es wird mehr Entropie gesammelt, aber der Aufbau dauert eine Weile.)
All dies geht doppelt für /dev/random
, denn wenn ihm die Entropie ausgeht, blockiert er normalerweise. (Außer auf Betriebssystemen, die /dev/random
machen ein Synonym für /dev/urandom
.)
Folglich sollten Sie immer genau die Menge an Zufallsdaten lesen, die Sie benötigen, und nicht mehr.
Anscheinend zielen Sie auf 24 alphanumerische Zeichen ab. Es gibt 62 mögliche alphanumerische Zeichen; Es würde die Dinge erheblich vereinfachen, wenn Sie zwei weitere Zeichen zulassen würden, um die Gesamtzahl auf 64 zu bringen. In diesem Fall könnten Sie 24 Zeichen erzeugen, indem Sie 18 Bytes Zufall extrahieren und durch einen Base64-Encoder leiten. Um eine genaue Datenmenge zu extrahieren, verwenden Sie dd
, die für den folgenden Zweck entwickelt wurde:
dd bs=18 count=1 if=/dev/urandom | base64 | tr +/ _.
(Die tr
übersetzt am Ende die beiden nicht-alphanumerischen Zeichen, die von base64
erzeugt werden in zwei verschiedene Zeichen, die Dateinamen-freundlicher sind. Nur ein Vorschlag.)
Wenn Sie entschlossen sind, genau alphanumerische Zeichen zu verwenden, können Sie eine ähnliche Zurückweisungsstrategie wie die verwenden, die Sie derzeit verwenden, jedoch auf der Grundlage des oben Gesagten. Leider ist es nicht möglich, genau vorherzusagen, wie viel Eingabe Sie in diesem Fall benötigen, daher ist der einfachste Ansatz, ein wenig mehr zu lesen und es in dem seltenen Fall, dass Sie nicht genug bekommen, erneut zu versuchen:
# 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}
Wenn Sie keine bash haben, können Sie ((${#s} >= 24))
ersetzen mit [ ${#s} -ge 24 ]
und s=${s:0:24}
mit s=$(printf %.24s $s)
Aber wenn Sie nur versuchen, gute zufällige Dateinamen zu generieren, sollten Sie mktemp
verwenden , mit dem Sie ein Skelett für die Namen angeben können, und überprüft außerdem, ob der generierte Name nicht bereits vorhanden ist. Siehe man mktemp
.
Eigentlich cat /dev/urandom
endet nie von alleine. Aber wenn head -1
liest die erste Zeile, es wird beendet, wodurch stdin geschlossen und eine Pipe geschlossen wird. Betriebssystem löst SIGPIPE
aus bis fold
ist auch beendet, und so weiter, also cat /dev/urandom
endet irgendwann.
In Ihrem Fall blockiert etwas SIGPIPE
, d.h. trap kann das:
$ trap '' PIPE
$ cat /dev/urandom | LC_ALL=C tr -dc 'a-zA-Z0-9' | fold -w 24 | head -n 1
7FazO6mnsIow3ylkvEHB55jE
(hungs)
Versuchen Sie, es in der Subshell erneut zu aktivieren:
( trap - PIPE ; cat /dev/urandom | LC_ALL=C tr -dc 'a-zA-Z0-9' | fold -w 24 | head -n 1 )