我如何使用AShell(限制bash)生成随机数字? 我在没有od
或$RANDOM
的设备上使用BusyBox二进制文件。 我的设备有/dev/urandom
和/dev/random
。
$RANDOM
和od
是BusyBox中的可选功能,我假设给你的问题,他们不包括在你的二进制文件。 你在/dev/urandom
存在的意见中提到,这很好,这意味着你需要做的是以一种可用的形式从它中获取字节,而不是实现一个随机数生成器的更困难的问题。 请注意,您应该使用/dev/urandom
而不是/dev/random
,请参阅/ dev / urandom中的rand是否为安全的登录密钥? 。
如果你有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个十进制数字)。
如果你需要一个独特的可打印的字符串,只要放弃非ASCII字符,也许还有一些恼人的标点符号:
nonce=$(</dev/urandom tr -dc A-Za-z0-9-_ | head -c 22)
在这种情况下,我会认真考虑写一个小型的,专用的C程序。 这是一个读取四个字节并输出相应的十进制数字。 它不依赖于系统调用read
的包装以外的任何libc函数,所以你可以得到一个非常小的二进制文件。 在命令行中支持一个以十进制整数形式传递的变量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 / random或/ dev / urandom可能存在。
另一个选择是编写一个调用srand(),然后是rand()的小型C程序。
</dev/urandom sed 's/[^[:digit:]]\+//g' | head -c10
我用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
dd
的stderr
$(( ))
) Hexdump和dc都可以在busybox中使用。 使用/ dev / urandom主要是随机的或/ dev / random来获得更好的随机性。 这两个选项都比$ RANDOM更好,并且比查找可打印字符的循环更快。
32位十进制随机数:
CNT=4 RND=$(dc 10 o 0x$(hexdump -e '"%02x" '$CNT' ""' -n $CNT /dev/random) p)
24位十六进制随机数:
CNT=3 RND=0x$(hexdump -e '"%02x" '$CNT' ""' -n $CNT /dev/random)
要获得更小的数字,请更改hexdump格式字符串的格式和hexdump读取的字节数。