【问题标题】:How to Write Block of Random Data to File using Bash如何使用 Bash 将随机数据块写入文件
【发布时间】:2022-06-12 00:21:08
【问题描述】:

我需要将从 /dev/urandom 获得的 5MB 数据块写入分区中特定位置的分区。然后我需要检查写入是否正确执行。我之前在 C++ 中成功地做到了这一点,但现在我想在 bash 脚本中实现它。

我的 C++ 代码包括:

  • 创建从 /dev/urandom (RANDOM_ARRAY) 填充的 10MB 数据数组
  • 用 open() 打开分区
  • 使用 lseek() 导航到分区中的所需位置
  • 使用 write() 将数组写入分区
  • 关闭并重新打开分区,使用 lseek 导航回所需位置
  • 使用 read() 在此位置读取 5MB 并使用此数据填充另一个数组 (WRITTEN_ARRAY)
  • 将 (RANDOM_ARRAY) 中的每个元素与 (WRITTEN_ARRAY) 进行比较

我没有编写 bash 脚本的经验,但这是我目前所掌握的,虽然它似乎不起作用:

random_data="$(cat /dev/urandom | head -c<5MB>)"

printf $random_data | dd of=<partition_path> bs=1 seek=<position_in_partition> count=<5MB>

file_data=$(dd if=<partition_path> bs=1 skip=<position_in_partition> count=<5MB>)

if [ "$random_data" == "$file_data" ]
then
 echo "data write successful"
fi

感谢乐于助人的评论者,我的脚本现在看起来像这样:

# get 10MB random data 
head -c<10MB> /dev/urandom > random.bin
# write 10MB random data to partition
dd if=random.bin of=<partition_location>
# copy the written data
dd if=<partition_location> count=<10MB/512 bytes> of=newdata.bin
# compare 
cmp random.bin newdata.bin

此时 cmp 返回第一个字符不同。查看 cmp 的详细输出,结果 newdata.bin 中的所有值都是 0。

【问题讨论】:

  • 你不能像这样printf你的二进制数据。使用中间文件:head -c 5MB /dev/urandom &gt; data.bin。然后:dd if=data.bin of=&lt;partition_path&gt;... 另一个方向相同:dd if=&lt;partition_path&gt; of=newdata.bin...
  • bash 中的变量是以\0 结尾的字符串:这不适合二进制。这就是random_data=... 小于 5 MB 的原因。正如@RenaudPacalet 所写,需要使用中间文件。
  • 二进制文件可以用cmp命令比较。
  • 感谢@RenaudPacalet。当我将分区位置设为二进制文件时,这很有效。分区是一个RAM块,由于某种原因,newdata.bin文件全为0。就好像由于某种原因写入没有正确执行。
  • @Jayjargot 谢谢,这是有道理的,我根据你所说的对我的脚本进行了更改,所以我相信我现在离找到一个可行的解决方案更近了。

标签: linux bash sh dd


【解决方案1】:

Bash 字符串不能保存任意二进制数据,因为 ASCII NUL 字符用作字符串终止符。

做你想做的事情的一种方法是将数据放在文件中而不是变量中,并使用cmp 来比较文件。

另一种选择是将数据的加密哈希存储在 Bash 变量中。这个Shellcheck-clean 代码演示了这个想法:

#! /bin/bash -p

partition_path=testpart
position_in_partition=10

sha256_1=$( exec 3>&1
            head -c 5MB /dev/urandom                \
                | tee >(sha256sum >&3)              \
                | dd of="$partition_path" bs=1  \
                        seek="$position_in_partition" count=5MB)

sha256_2=$(dd if="$partition_path" bs=1 \
                skip="$position_in_partition" count=5MB \
            | sha256sum)

[[ $sha256_1 == "$sha256_2" ]] && echo 'data write successful'
  • 您需要将partition_pathposition_in_partion 变量设置为适合您的值。
  • exec 3&gt;&amp;1 将文件描述符 3 连接到用于读取 sha256_1 值的流。
  • tee &gt;(sha256sum &gt;&amp;3) 使用标准 tee 实用程序和 Bash process substitution 将管道数据作为输入复制到 sha256sum 进程,其输出重定向到文件描述符 3。这样做的效果是 sha256sum 输出(带有尾随换行符被删除)成为sha256_1 变量的值。
  • 您可以使用更强大的加密哈希函数,将sha256sum 替换为(例如)sha512sum

【讨论】:

  • 感谢您的回答,我将尝试加密哈希方法。你介意看看我对我的帖子所做的编辑,我在其中修改了中间文件的脚本吗?
  • @Mickthekangaroo,中间文件代码在我看来基本上是合理的,但显然不完整。我建议在你的真实分区上尝试之前,使用像“test.dat”这样的普通磁盘文件创建一些实际工作的真实代码。我发布的代码运行成功并打印了“数据写入成功”。
【解决方案2】:

这是一种更简单的方法,它只是将数据保存在一个临时文件中。

#!/bin/sh

set -e

random_data=$(mktemp -t ideone.XXXXXXXX) || exit
trap 'rm -rf "$t"' EXIT

dd if=/dev/urandom bs=10240 count=512 of="$random_data"

dd if="$random_data" of=<partition_path> bs=1 seek=<position_in_partition> count=<5MB>

if dd if=<partition_path> bs=1 skip=<position_in_partition> count=<5MB> |
    cmp "$random_data"
then
 echo "data write successful"
fi

【讨论】:

    猜你喜欢
    • 2021-06-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-15
    • 2016-09-06
    • 1970-01-01
    • 2019-12-21
    相关资源
    最近更新 更多