7

AShell(制限付きbash)を使用して乱数を生成するにはどうすればよいですか?またはがないデバイスでBusyBoxバイナリを使用していodます$RANDOM。私のデバイスにはとが/dev/urandomあり/dev/randomます。

4

7 に答える 7

7

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

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

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。BusyBoxtrは一度にバッファフル(少なくとも512バイト)を読み取り、入力バッファが完全に処理されるたびに出力バッファをフラッシュするため、上記のコマンドは常に少なくとも512バイトを読み取ります/dev/urandom(512からの予想されるテイク以降は非常にまれです)入力バイトは10進数の20桁です)。

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

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

このような状況では、私は小さな専用のCプログラムを書くことを真剣に検討したいと思います。これは、4バイトを読み取り、対応する10進数を出力するものです。readシステムコールとのラッパー以外のlibc関数に依存しないwriteため、非常に小さなバイナリを取得できます。コマンドラインで10進整数として渡される可変キャップをサポートすることは、演習として残されています。数百バイトのコードが必要になります(ターゲットが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;
}
于 2011-10-04T21:54:07.117 に答える
2
</dev/urandom sed 's/[^[:digit:]]\+//g' | head -c10
于 2012-12-03T06:00:10.917 に答える
1

/ dev/randomまたは/dev/urandomが存在する可能性があります。

もう1つのオプションは、srand()、次にrand()を呼び出す小さなCプログラムを作成することです。

于 2011-10-04T02:38:58.980 に答える
1

BusyBox 1.22.1でGillesの最初のスニペットを試しましたが、コメントに収まらないパッチがいくつかあります。

while [ $n -gt 65535 ]; do
    n=$(</dev/urandom tr -dc 0-9 | dd bs=5 count=1 2>/dev/null | sed -e 's/^0\+//' )
done
  1. ループ条件は、最大値より大きいかどうかをチェックする必要があります。そうでない場合、実行は0になります。
  2. 私は沈黙しましddstderr
  3. 先行ゼロが削除されました。これは、8進数として解釈されるコンテキストでサプライズにつながる可能性があります(例$(( ))
于 2015-12-04T07:13:38.577 に答える
1

Hexdumpとdcはどちらもbusyboxで利用できます。ほとんどランダムの場合は/dev/ urandomを使用し、より良いランダムの場合は/ dev/randomを使用します。これらのオプションはどちらも$RANDOMよりも優れており、どちらもループして印刷可能な文字を探すよりも高速です。

32ビットの10進数の乱数:

CNT=4
RND=$(dc 10 o 0x$(hexdump -e '"%02x" '$CNT' ""' -n $CNT /dev/random) p)

24ビットの16進乱数:

CNT=3
RND=0x$(hexdump -e '"%02x" '$CNT' ""' -n $CNT /dev/random)

数値を小さくするには、hexdumpフォーマット文字列のフォーマットとhexdumpが読み取るバイト数を変更します。

于 2016-05-04T01:38:44.497 に答える
0

escitalopramのソリューションを試してみると、busybox v1.29.0では機能しませんでしたが、機能を実行するように促されました。

s私は実際に、桁数を要求し、かなりうまく機能するはずのポータブル乱数生成関数を思いついた(これまでのところ、Linux、WinNT10 bash、Busybox、およびmsys2でテスト済み)。

# Get a random number on Windows BusyBox alike, also works on most Unixes
function PoorMansRandomGenerator {
    local digits="${1}"     # The number of digits of the number to generate

    local minimum=1
    local maximum
    local n=0

    if [ "$digits" == "" ]; then
        digits=5
    fi

    # Minimum already has a digit
    for n in $(seq 1 $((digits-1))); do
        minimum=$minimum"0"
        maximum=$maximum"9"
    done
    maximum=$maximum"9"

    #n=0; while [ $n -lt $minimum ]; do n=$n$(dd if=/dev/urandom bs=100 count=1 2>/dev/null | tr -cd '0-9'); done; n=$(echo $n | sed -e 's/^0//')
    # bs=19 since if real random strikes, having a 19 digits number is not supported
    while [ $n -lt $minimum ] || [ $n -gt $maximum ]; do
        if [ $n -lt $minimum ]; then
            # Add numbers
            n=$n$(dd if=/dev/urandom bs=19 count=1 2>/dev/null | tr -cd '0-9')
            n=$(echo $n | sed -e 's/^0//')
            if [ "$n" == "" ]; then
                n=0
            fi
        elif [ $n -gt $maximum ]; then
            n=$(echo $n | sed 's/.$//')
        fi
    done
    echo $n
}

以下は、1000から9999の間の数値を示しますecho $(PoorMansRandomGenerator 4)

于 2018-06-04T09:17:42.527 に答える
0

上記の応答をより単純なバージョンに改善しました。これも非常に高速に実行され、Busybox、Linux、msys、およびWinNT10bashと互換性があります。

function PoorMansRandomGenerator {
    local digits="${1}" # The number of digits to generate
    local number

    # Some read bytes can't be used, se we read twice the number of required bytes
    dd if=/dev/urandom bs=$digits count=2 2> /dev/null | while read -r -n1 char; do
            number=$number$(printf "%d" "'$char")
            if [ ${#number} -ge $digits ]; then
                    echo ${number:0:$digits}
                    break;
            fi
    done
}

で使用

echo $(PoorMansRandomGenerator 5)

</ p>

于 2018-09-21T12:31:38.487 に答える