GNU/Linux >> Linux の 問題 >  >> Linux

BusyBox シェルで乱数を生成する方法

$RANDOMod は BusyBox のオプション機能です。バイナリに含まれていないという質問があったと思います。コメントで /dev/urandom と言及しました 存在する、それは良いことです。それは、乱数ジェネレーターを実装するというはるかに難しい問題ではなく、そこからバイトを使用可能な形式で取得する必要があることを意味します。 /dev/urandom を使用する必要があることに注意してください /dev/random ではありません /dev/urandom からのランドはログインキーとして安全ですか? を参照してください。

tr の場合 または sed/dev/urandom からバイトを読み取ることができます 望ましい文字ではないバイトを破棄します。また、ストリームから一定のバイト数を抽出する方法も必要です:head -c (FEATURE_FANCY_HEAD が必要です) 有効にする) または dd (dd が必要です) でコンパイルされます)。破棄するバイト数が多いほど、このメソッドは遅くなります。それでも、ランダム バイトの生成は通常、外部バイナリのフォークと実行に比べてかなり高速であるため、それらの多くを破棄してもそれほど問題はありません。たとえば、次のスニペットは 0 から 65535 までの乱数を生成します:

n=65536
while [ $n -ge 65536 ]; do
  n=1$(</dev/urandom tr -dc 0-9 | dd bs=5 count=1 2>/dev/null)
  n=$((n-100000))
done

バッファリングのため、tr であることに注意してください。 dd よりもかなり多くのバイトを処理します 維持してしまいます。 BusyBox の tr 一度にバッファフル (少なくとも 512 バイト) を読み取り、入力バッファが完全に処理されるたびに出力バッファをフラッシュするため、上記のコマンドは常に /dev/urandom から少なくとも 512 バイトを読み取ります。 (512 入力バイトから予想されるテイクは 20 桁の 10 進数であるため、それ以上になることはめったにありません)。

一意の印刷可能な文字列が必要な場合は、ASCII 以外の文字と、おそらく厄介な句読点文字を破棄してください:

nonce=$(</dev/urandom tr -dc A-Za-z0-9-_ | head -c 22)

この状況では、小さな専用の C プログラムを作成することを真剣に検討します。これは、4 バイトを読み取り、対応する 10 進数を出力するものです。システム コール read のラッパー以外の libc 関数に依存していません。 と write 、非常に小さなバイナリを取得できます。コマンド ラインで 10 進整数として渡される変数 cap のサポートは、演習として残されています。数百バイトのコードが必要になります (ターゲットが Linux を実行するのに十分な大きさであれば、心配する必要はありません)。

#include <stddef.h>
#include <unistd.h>
int main () {
    int n;
    unsigned long x = 0;
    unsigned char buf[4];
    char dec[11]; /* Must fit 256^sizeof(buf) in decimal plus one byte */
    char *start = dec + sizeof(dec) - 1;
    n = read(0, buf, sizeof(buf));
    if (n < (int)sizeof(buf)) return 1;
    for (n = 0; n < (int)sizeof(buf); n++) x = (x << 8 | buf[n]);
    *start = '\n';
    if (x == 0) *--start = '0';
    else while (x != 0) {
        --start;
        *start = '0' + (x % 10);
        x = x / 10;
    }
    while (n = write(1, start, dec + sizeof(dec) - start),
           n > 0 && n < dec + sizeof(dec) - start) {
        start += n;
    }
    return n < 0;
}

</dev/urandom sed 's/[^[:digit:]]\+//g' | head -c10

Linux
  1. パイプバッファの大きさはどれくらいですか?

  2. シェルで制御文字(^ c、^ d、^ [、…)を異なる方法で表示する方法は?

  3. シェルで PYTHONPATH を取得するには?

  1. シェルから Vim コマンドを実行するには?

  2. 同じバイトをグループ化して、ファイル内のバイト数をカウントする方法は?

  3. Busybox のデフォルト シェルとは何ですか?

  1. Linuxシェルスクリプトで数値と文字列を比較する方法

  2. コマンドの出力をシェル変数に割り当てる方法は?

  3. Linux コマンドラインからランダムな MAC アドレスを生成する方法