同僚は、次のコマンドを使用してランダムなキーを作成することを提案しました:
tr -dc A-Za-z0-9_\!\@\#\$\%\^\&\*\(\)-+= < /dev/urandom | head -c 32 | xargs
それは私にエラーを与えました:
tr:不正なバイトシーケンス
システムに/dev/urandom
がないのではないかと心配です。このファイルをインストールする方法をグーグルで調べてみましたが、空になりました。私はlocate urandom
を試しましたが、空っぽになりました。 (実際には、manページが見つかりましたが、それは役に立ちません)
Mac OSXシステムでurandom
を利用できるようにするにはどうすればよいですか? (ライオン)
あなたが受け取るエラーメッセージに基づいて、私は/ dev/urandomが問題だとは思いません。もしそうなら、「そのようなファイルやディレクトリはありません」のようなエラーが予想されます。
私はあなたが得たエラーメッセージを検索し、これを見つけました、それはあなたの問題に関連しているようです http://nerdbynature.de/s9y/2010/04/11/tr-Illegal-byte-sequence
基本的には、tr
コマンドの前にLC_CTYPE=C
を付けてロケールを指定します。
LC_CTYPE=C tr -dc A-Za-z0-9_\!\@\#\$\%\^\&\*\(\)-+= < /dev/urandom | head -c 32 | xargs
tr
は、入力をUTF-8エンコーディングのテキストとして解釈しようとします。そのため、有効なUTF-8ではない最初のバイトシーケンスでエラーが発生し、中断します。 tr
の前にLC_ALL=C
またはLC_CTYPE=C
を付けると、その変数はtr
の環境にエクスポートされ、ローカル文字セットの考え方がC標準、つまりすべてに変更されます単なる不透明なバイトのシーケンスです。
ところで、コマンドのシーケンス\)-+
は意図的なものですか?これには、すでに含まれている*
も含まれますが、意図したとおりに-
自体は含まれていません。代わりに次のいずれかを書く方が良いでしょう:
LC_ALL=C tr -dc 'A-Za-z0-9_!@#$%^&*()\-+=' < /dev/urandom
LC_CTYPE=C tr -dc A-Za-z0-9_\!\@\#\$\%\^\&\*\(\)\\-+= < /dev/urandom
他の人が指摘したように、あなたの問題はそれではありません/dev/urandom
がありませんが、OS Xでのtr
の動作方法が異なります。環境変数をいじる代わりに、Perl
の代わりにtr
を使用します。
Perl -pe 'binmode(STDIN, ":bytes"); tr/A-Za-z0-9_\!\@\#\$\%\^\&\*\(\)-+=//dc;' < /dev/urandom | head -c 32; echo
これには、OS X、Redhat、Ubuntu間で移植できるという利点があります。
(また、xargs
へのパイプを削除し、witch echo
を置き換えて、出力の最後で改行を取得しました。)
まず、有効な文字のリストに-
または*
を含めるつもりでしたか? tr
のパラメーターには、シーケンス)-+
が含まれています。これは、「)
で始まり、+
で終わるバイト範囲、実際には)*+
です。
次に、カーネルのエントロピープールから数キロバイトを読み取る(つまり、プール全体を安全でないとマークし、安全なエントロピーを必要とする他のプロセスに影響を与える)のではなく、必要なビットだけを読み取ることを検討してください:head -c...
を使用してくださいfirstステップとして、不要な文字を破棄するのではなく、翻訳します。
この問題のこの特定のバージョンは、76の異なるシンボルを使用するという点で少し変わっています。ほとんどの場合、英数字が必要なので、64シンボルだけで十分な場合は、base64
ユーティリティを使用すると、エントロピープールの消費が最小限になります(24は32の6/8であることに注意してください)。
head -c24 < /dev/random | base64
ロケールの文字エンコーディング(locale charmap
で確認できます)は、1文字あたりマルチバイトです。
現在最も一般的なのはUTF-8で、文字は1〜4バイトでエンコードできます。バイトのすべてのシーケンスがUTF-8で有効な文字を形成するわけではありません。 UTF-8のすべての非ASCII文字は、2つの最高ビットセットを持つ1バイトで始まり、最高(ただし2番目に高いビットではない)ビットセットを持つバイト数が続きます。
/dev/urandom
には、ランダムなバイトストリームが含まれます。 tr
は文字を文字変換するため、これらのバイトを文字としてデコードする必要があります。これらのASCII=範囲内の文字はすべてUTF-8で1文字にエンコードされますが、tr
はすべての文字をデコードする必要があります。たとえば、他のマルチバイトエンコーディングがあります。ここで、A
以外の一部の文字には0x41バイト(A
のコード)が含まれています。
そのランダムなバイトストリームは無効なシーケンスを含むようにバインドされているため(たとえば、ASCII以外の文字は0xc1より大きいバイトで始まる必要があるため、0x80バイト自体はUTF-8では無効です(0xc0および0xc1はUTF- 8文字))なので、tr
は、エラーが発生するとエラーを返します。
ここで必要なのは、1バイトが1文字であるエンコーディングのバイトストリームを文字として考えることです。範囲内のすべての文字(AZと仮定すると、ABCDEFGHIJKLMNOPQRSTUVWXYZを意味し、Ý
、Ê
などではない)はポータブル文字セットの一部であるため、どちらを選択しても重要ではありません。システムでサポートされているすべての文字セット。
そのためには、使用する文字セットとblank
、alpha
などの文字クラスに含まれるものを決定するLC_CTYPE
ローカリゼーション変数を設定します。ただし、A〜Zの範囲を定義するには、LC_COLLATE
変数(文字列の順序を決定する変数)も設定する必要があります。
C
aka POSIX
ロケールは、文字がシングルバイトであることを保証するロケールであり、A-ZはABCDEFGHIJKLMNOPQRSTUVWXYZです。あなたがすることができます:
LC_CTYPE=C LC_COLLATE=C tr -dc 'A-Za-z0-9_!@#$%^&*()+=-'
(ここで-
を最後に移動します。それ以外の場合、)-+
はA-Z
のような範囲と見なされます)
ただし、LC_ALL
変数は他のすべてのLC_*
およびLANG
変数をオーバーライドすることに注意してください。したがって、LC_ALL
がすでに定義されている場合は、上記の効果はありません。だから代わりにあなたは単に行うことができます:
LC_ALL=C tr -dc 'A-Za-z0-9_!@#$%^&*()+=-'
これはエラーメッセージの言語などの他のことに影響しますが、いずれにしても、LC_CTYPEの変更は既にエラーメッセージの問題である可能性があります(たとえば、Cロケールの文字セットでロシア語または日本語のエラーメッセージを表現する方法はありません)。
man page によると、おそらく/ dev/randomで十分です。おそらくAppleは不要なので/ dev/urandomの作成をやめましたか?