我对此完全是新手,但我正在尝试将其他人的代码改编为越狱的 Kindle 3(电子阅读器)。
我使用以下代码生成 0 到 X 之间的随机数(其中 X 是我拥有的图像数量,当前为 33),这样我就可以每隔几个小时显示一个随机图像(当前每 2 小时) 使用cron
运行脚本。
#generate random number between my 33 images (compatible with busybox)
n=32
while [ $n -ge 32 ]; do
n=1$(</dev/urandom tr -dc 0-9 | dd bs=5 count=1 2>/dev/null)
n=$((n-100000))
done
ImageNumber=$n
#My images are numbered as follows - pic_0.png, pic_1.png, pic_3.png... etc
SelectedImage=$( find /mnt/us/timelit/images/pic_${ImageNumber}*.png)
# clear the screen
eips -c
# show that image
eips -g $SelectedImage
它正在发挥作用,但是有一些问题需要解决。
1)我认为脚本的随机数生成器部分存在问题,因为它在生成数字之前随时间变化(请参见下面的日志)
14:00:02: Script started
14:02:43: Random number is 2
14:02:44: Image shown is pic_2.png
15:00:02: Script started
15:00:19: Random number is 18
15:00:20: Image shown is pic_18.png
16:00:01: Script started
16:02:44: Random number is 10
16:02:45: Image shown is pic_10.png
2) Kindle 有时会显示空白屏幕而不是图像之一。我猜测生成的随机数存在问题,这意味着无法找到具有匹配数字的 PNG,因此 Kindle 显示为空白。
任何帮助是极大的赞赏。
答案1
#generate random number between my 33 images (compatible with busybox) n=32 while [ $n -ge 32 ]; do n=1$(</dev/urandom tr -dc 0-9 | dd bs=5 count=1 2>/dev/null) n=$((n-100000)) done ImageNumber=$n
因此,您在这里生成一个随机数 00000-99999,并且仅当它低于 32 时才终止。100'000 中的概率为 32。如果前导 0 被解释为八进制数,甚至可能会导致无效算术表达式问题。 (编辑:哦,我想这就是你在前面加上 1 的原因)
不管怎样……需要一段时间才能终止。并提出了一个问题,为什么你不只使用$RANDOM%32
.对于较小的数字$RANDOM
(限制为 0-32767)效果很好。
$RANDOM
如果Kindle 的 busybox 中没有(可能是如果CONFIG_ASH_RANDOM_SUPPORT=n
),您可以使用 ... 获取单个号码tr
,或者hexdump
如果可用,则直接使用它。
无论如何,while 循环都是非常低效且毫无意义的。
不带循环的示例:
random=1$(</dev/urandom tr -dc 0-9 | dd bs=5 count=1 2>/dev/null)
ImageNumber=$(($random % 32))
仍然有点低效,因为tr
必须读取比您想要的 5 个更多的随机字节(256 次读取数字的机会中有 10 次)。
如果hexdump
可用(读取固定的 3 个随机字节):
random=0x$(hexdump -v -e '3/1 "%02x"' -n 3 /dev/urandom)
ImageNumber=$(($random % 32))
#My images are numbered as follows - pic_0.png, pic_1.png, pic_3.png... etc SelectedImage=$( find /mnt/us/timelit/images/pic_${ImageNumber}*.png)
如果您的 ImageNumber 为 1,则该表达式将转换为pic_1*.png
which might be but is ,pic_1.png
依此类推。如果文件名中没有多余的字符,请删除 *.否则,您需要另一个分隔符(以允许类似 的文件名)。pic_10-19.png
pic-100-199.png
pic_${ImageNumber}_*.png
pic_1_spaceship.png
无论哪种方式,您都可以跳过查找并直接使用表达式:
eips -g /mnt/us/timelit/images/pic_${ImageNumber}.png
答案2
看霜舒兹的回答为什么你的代码不能很好地工作。我将给出不同的解决方案。
如果您的 BusyBox 环境包含 awk,则生成适合此应用程序的随机数的更简单方法是
awk -v n=32 'BEGIN {srand(); print int(rand() * n); exit}'
srand()
仅基于四舍五入到最接近的秒的当前时间,因此在很多情况下它是不合适的(任何与安全相关的事情,任何每秒可能有超过一次随机抽取的事情)。但在这里已经足够好了。
不要为每张图片分配一个编号并对编号范围进行硬编码,而是列出文件并随机选择一个。更确切地说:
- 将位置参数设置为文件列表。
- 使用 awk 随机选择一个位置参数。
- 在位置参数中选择该文件名。
set -- /mnt/us/timelit/images/pic*.png
i=$(awk -v n=$# 'BEGIN {srand(); print int(rand() * n ) + 1; exit}')
eval "SelectedImage=\${$i}"
eips -c
eips -g $SelectedImage
您甚至可以让 awk 直接选择图像文件,但如果文件很多,您可能会遇到命令行长度限制。
SelectedImage=$(awk '
BEGIN {srand(); print ARGV[int(rand() * (length(ARGV)-1) + 1)]; exit}
' /mnt/us/timelit/images/pic*.png)
(请注意,如果您有一个包含 bash 和 GNU 实用程序的更完整的环境,那么会有更简单的方法来做一些事情。我的答案坚持每个 POSIX shell 和许多 BusyBox 安装中都可用的功能。)