cat
は絶対に使用しないでください /dev/urandom
で .また、テキスト ファイル用に設計されたユーティリティも使用しないでください。
/dev/urandom
ランダム データの連続ストリームです。ファイルの終わりを生成することはありません。バッファリングされた読み取りは読み取りバッファを満たすため、cat
の出力をパイプしても 他のプログラムに挿入すると、パイプが閉じられるまで読み取りは終了しません。
/dev/urandom
を読むときを除いて、どれも非効率的です。 、貴重なリソースであるエントロピー(ランダム性)を使い果たしています。エントロピーが使い果たされると、/dev/urandom
の出力はランダム性が低くなり、目的に反します。 (より多くのエントロピーが収集されますが、蓄積するのに時間がかかります。)
/dev/random
の場合、これらすべてが 2 倍になります 、エントロピーを使い果たすと、通常はブロックされるためです。 (/dev/random
を作成する OS を除く) /dev/urandom
の同義語 .)
したがって、常に必要な量のランダム データを正確に読み取る必要があり、それ以上は読み取らないでください。
どうやら英数字24文字を狙っているようですね。使用可能な英数字は 62 文字です。他の 2 文字の合計を 64 にすることができれば、非常に簡単になります。その場合、18 バイトのランダム性を抽出して base64 エンコーダーに渡すことで、24 文字を生成できます。正確な量のデータを抽出するには、dd
を使用します 、目的のために設計されています:
dd bs=18 count=1 if=/dev/urandom | base64 | tr +/ _.
(tr
最後に、base64
によって生成された 2 つの英数字以外の文字を変換します よりファイル名に適した 2 つの異なる文字に変換されます。単なる提案です。)
正確に英数字を使用することに決めた場合は、現在使用しているものと同様の拒否戦略を使用できますが、上記に基づいています.残念ながら、この場合に必要な入力量を正確に予測することはできません。そのため、最も簡単な方法は、少し余分に読み取り、十分に得られないまれなケースで再試行することです:
# 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}
bash がない場合は、((${#s} >= 24))
を置き換えることができます [ ${#s} -ge 24 ]
で と s=${s:0:24}
s=$(printf %.24s $s)
で
しかし、適切なランダムなファイル名を生成しようとしているだけなら、 mktemp
を使用する必要があります これにより、名前のスケルトンを指定でき、生成された名前がまだ存在しないことも確認できます。 man mktemp
を参照 .
実際には cat /dev/urandom
それ自体で終わることはありません。しかし head -1
の場合 最初の行を読み取って終了し、標準入力を閉じてパイプを閉じます。 OS が SIGPIPE
を発生させます fold
へ も終了などなので、 cat /dev/urandom
最終的に終了します。
あなたの場合、SIGPIPE
をブロックする何か 、つまりtrapはそれを行うことができます:
$ trap '' PIPE
$ cat /dev/urandom | LC_ALL=C tr -dc 'a-zA-Z0-9' | fold -w 24 | head -n 1
7FazO6mnsIow3ylkvEHB55jE
(hungs)
サブシェルで再度有効にしてみてください:
( trap - PIPE ; cat /dev/urandom | LC_ALL=C tr -dc 'a-zA-Z0-9' | fold -w 24 | head -n 1 )