如何在 Linux 中验证硬盘驱动器是否填充了零?

gkf*_*jh2 19 bash hard-drive ubuntu-12.10

我有充满零的硬盘驱动器。

如何使用bash检查硬盘驱动器上的所有位是否为零?

Gor*_*son 32

od将使用 替换相同内容的运行*,因此您可以轻松使用它来扫描非零字节:

$ sudo od /dev/disk2 | head
0000000    000000  000000  000000  000000  000000  000000  000000  000000
*
234250000
Run Code Online (Sandbox Code Playgroud)

您可以将其与dd或结合使用pv以在扫描进行时显示进度:

$ sudo dd if=/dev/disk2 bs=1M status=progress | od | head

# or:

$ sudo pv /dev/disk2 | od | head
Run Code Online (Sandbox Code Playgroud)

  • 我会添加`| head` 到最后,这样如果发现驱动器没有归零,它会在产生足够的输出以显示事实后停止,而不是将整个驱动器转储到屏幕上。 (8认同)
  • @Wyzard:好主意;我会把它添加到我的答案中。 (2认同)
  • @pemfir 如果没有 `od=` 参数,`dd` 将数据发送到标准输出,在本例中意味着它通过管道发送到 `od` 命令` (2认同)

Bob*_*Bob 8

为此,我编写了一个简短的 C++ 程序,可在此处获取源代码。

要构建它:

wget -O iszero.cpp https://gist.github.com/BobVul/5070989/raw/2aba8075f8ccd7eb72a718be040bb6204f70404a/iszero.cpp
g++ -o iszero iszero.cpp
Run Code Online (Sandbox Code Playgroud)

运行它:

dd if=/dev/sdX 2>/dev/null | ./iszero
Run Code Online (Sandbox Code Playgroud)

它将输出任何非零字节的位置和值。您可以将此输出重定向到一个文件>,例如:

dd if=/dev/sdX 2>/dev/null | ./iszero >nonzerochars.txt
Run Code Online (Sandbox Code Playgroud)

您可能想尝试更改BUFFER_SIZE以提高效率。我不确定最佳值可能是多少。请注意,这也会影响它打印进度的频率,这会在一定程度上影响速度(打印输出到控制台很)。添加2>/dev/null以摆脱进度输出。

我知道这不是使用标准的 bash,甚至不是内置函数,但它不需要任何额外的权限。@Hennes 的解决方案仍然更快(我还没有真正优化任何东西——这是天真的解决方案);但是,这个小程序可以让您更好地了解您的擦除器丢失了多少字节以及在哪个位置。如果您禁用进度输出,它仍然会比大多数消费者硬盘驱动器可以读取的速度更快(> 150 MB/s),所以这不是一个大问题。

此处提供具有较少详细输出的更快版本。但是,它仍然比@Hennes 的解决方案慢一点。然而,这个将在它遇到的第一个非零字符上退出,因此如果在流的开头附近有一个非零字符,它可能会快得多。


将源添加到帖子以保持答案更好地独立:

#include <cstdio>

#define BUFFER_SIZE 1024

int main() {
    FILE* file = stdin;
    char buffer[BUFFER_SIZE];
    long long bytes_read = 0;
    long long progress = 0;
    long long nonzero = 0;

    while (bytes_read = fread(buffer, 1, BUFFER_SIZE, file)) {
        for (long long i = 0; i < bytes_read; i++) {
            progress++;
            if (buffer[i] != 0) {
                nonzero++;
                printf("%lld: %x\n", progress, buffer[i]);
            }
        }
        fprintf(stderr, "%lld bytes processed\r", progress);
    }

    fprintf(stderr, "\n");

    int error = 0;
    if (error = ferror(file)) {
        fprintf(stderr, "Error reading file, code: %d\n", error);
        return -1;
    }

    printf("%lld nonzero characters encountered.\n", nonzero);
    return nonzero;
}
Run Code Online (Sandbox Code Playgroud)


小智 7

扩展戈登的回答,pv提供了该过程有多远的指示:

$ sudo pv -tpreb /dev/sda | od | head
0000000 000000 000000 000000 000000 000000 000000 000000 000000
*
9.76GiB 0:06:30 [25.3MiB/s] [=================>               ] 59% ETA 0:04:56
Run Code Online (Sandbox Code Playgroud)


Hen*_*nes 5

这似乎是一个丑陋的低效解决方案,但如果您只需要检查一次:

dd if=/dev/sdX | tr --squeeze-repeats "\000" "T"

使用 dd 从磁盘读取sdX。(用您要读取的驱动器替换 X),
然后所有不可打印的零字节转换为我们可以处理的内容。

接下来我们要么计算我们可以处理的字节数并检查它是否是正确的数字(wc -c用于那个),或者我们跳过计数并使用-sor--squeeze-repeats将所有多次出现压缩到单个字符中。

因此dd if=/dev/sdX | tr --squeeze-repeats "\000" "T"应该只打印一个 T。

如果您想定期执行此操作,那么您需要更有效的方法。
如果你只想这样做一次,那么这个 kludge 可以验证你的普通雨刮器是否正常工作并且你可以信任它。

  • @daniel:一个简单的 C 程序应该能够读取所有数据而无需更改每个读取字节。这会更有效,更美观。编写这样的程序可能比仅仅以低效的方式使用可用的工具花费更多的时间。 (3认同)