web-dev-qa-db-ja.com

Linuxでハードドライブがゼロで満たされていることを確認するにはどうすればよいですか?

私はゼロでいっぱいのハードドライブを持っています。

ハードドライブのすべてのビットがbashを使用してゼロであるかどうかを確認するにはどうすればよいですか?

16
gkfvbnhjh2

odは、同じものの実行を*で置き換えます。そのため、これを使用してゼロ以外のバイトをスキャンすることが簡単にできます。

$ Sudo od /dev/disk2 | head
0000000    000000  000000  000000  000000  000000  000000  000000  000000
*
234250000
29
Gordon Davisson

私はそうするために短いC++プログラムを書きました、利用可能なソース here

それを構築するには:

wget -O iszero.cpp https://Gist.github.com/BobVul/5070989/raw/2aba8075f8ccd7eb72a718be040bb6204f70404a/iszero.cpp
g++ -o iszero iszero.cpp

それを実行するには:

dd if=/dev/sdX 2>/dev/null | ./iszero

ゼロ以外のバイトの位置と値を出力します。この出力を>のファイルにリダイレクトできます。例:

dd if=/dev/sdX 2>/dev/null | ./iszero >nonzerochars.txt

効率を上げるために、BUFFER_SIZEを変更してみてください。最適な値が何かはわかりません。これは、進行状況を印刷する頻度にも影響し、速度に多少影響することに注意してください(コンソールへの出力の印刷はslowです)。 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;
}
8
Bob

ゴードンの答えを拡張すると、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
7
Chris

これは醜い非効率的な解決策のようですが、一度だけチェックする必要がある場合:

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

Ddを使用してディスクsdXから読み取ります。 (Xを読み取りたいドライブに置き換えます)、
次に 翻訳する 印刷できないすべてのゼロバイトを処理できるものに。

次に、処理できるバイト数をカウントして、それが正しい数であるかどうかを確認するか(wc -cを使用)、カウントをスキップして-sまたは--squeeze-repeatsを使用して複数をすべてスクイーズします。単一の文字への出現。

したがって、dd if=/dev/sdX | tr --squeeze-repeats "\000" "T"は1つのTのみを出力する必要があります。

これを定期的に行う場合は、より効率的な方法が必要です。
これを1度だけ実行したい場合、このクラッジは通常のワイパーが機能していて、信頼できることを確認する場合があります。

5
Hennes

確認するために、リストに一致しないブロックが表示されます

Sudo badblocks -sv -t 0x00 /dev/sdX

または、badblocksを使用してそれらを書き込み、チェックします。

Sudo badblocks -svw -t 0x00 /dev/sdX

デフォルトの破壊テストは私の安全な消去です

Sudo badblocks -svw /dev/sdX

ドライブに0と1を交互に入れた後、誰かが何かを取得できる場合は、その補数、次にすべて1、次にすべて0で、すべてのパスが正常に機能することを確認して、幸運を祈ります!

新しいドライブでも適切な展開前チェックを行います

man badblocks

他のオプション

速いとは言わないが、うまくいく...

3
Beardy

両方の長所。このコマンドは不良セクタをスキップします:

Sudo dd if=/dev/sdX conv=noerror,sync | od | head

使用する kill -USR1 <pid of dd>進捗状況を確認します。

2
jiveformation

少し前、私はAIOに興味がありました。結果は、NULであるセクター(512バイトブロック)をたまたまチェックするサンプルテストプログラムでした。これは、スパースファイル領域検出器のバリアントとして見ることができます。 source がすべてを語っていると思います。

  • ファイル/ドライブ全体がNULの場合、出力は_0000000000-eof_のようになります。プログラムにはトリックがあることに注意してください。示されている出力を提供するために、107行目で関数fin()が呼び出されていません。
  • 十分にテストされていないため、バグが含まれている可能性があります
  • AIOは他の方法ほど単純ではないため、コードは少し長くなりますが、
  • ただし、AIOおそらくドライブをビジー状態に保つ最も速い方法です。これは、NULの比較が次のデータブロックの読み込み中に行われるためです。(重複するAIOを実行して、さらに数ミリ秒を絞り出しますが、これは努力する価値があるとは思いません。)
  • ファイルが読み取り可能ですべてが機能している場合、常にtrueを返します。ファイルがfalseでない場合は、NULを返しません。
  • これは、ファイルサイズが512の倍数であることを前提としています。最後のセクターにバグがありますが、メモリバッファにはすでにNULが含まれているため、ファイル全体がNULでも機能します。誰かがこれを修正する必要があると思った場合、95行目でmemcmp(nullblock, buf+off, SECTOR)memcmp(nullblock, buf+off, len-off<SECTOR : len-off : SECTOR)を読み取ることができます。ただし、唯一の違いは、「レポートの終了」がおそらく少しランダムであるということです(完全にNULであるファイルの場合ではありません)。
  • 変更されたmemcmp()は、プラットフォームでの別の問題も修正します。これは、コードがそれを行わないため、メモリをNULalloc() edしません。しかし、これは4 MiB未満のファイルでのみ見られる可能性がありますが、checknulは、このような小さなタスクではおそらくやり過ぎです;)

HTH

_/* Output offset of NUL sector spans on disk/partition/file
 *
 * This uses an AIO recipe to speed up reading,
 * so "processing" can take place while data is read into the buffers.
 *
 * usage: ./checknul device_or_file
 *
 * This Works is placed under the terms of the Copyright Less License,
 * see file COPYRIGHT.CLL.  USE AT OWN RISK, ABSOLUTELY NO WARRANTY.
 */

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>

#include <malloc.h>
#include <aio.h>

#define SECTOR  512
#define SECTORS 40960
#define BUFFERLEN   (SECTOR*SECTORS)

static void
oops(const char *s)
{
  perror(s);
  exit(1);
}

static void *
my_memalign(size_t len)
{
  void      *ptr;
  static size_t pagesize;

  if (!pagesize)
    pagesize = sysconf(_SC_PAGESIZE);
  if (len%pagesize)
    oops("alignment?");
  ptr = memalign(pagesize, len);
  if (!ptr)
    oops("OOM");
  return ptr;
}

static struct aiocb aio;

static void
my_aio_read(void *buf)
{
  int   ret;

  aio.aio_buf = buf;
  ret = aio_read(&aio);
  if (ret<0)
    oops("aio_read");
}

static int
my_aio_wait(void)
{
  const struct aiocb    *cb;
  int           ret;

  cb = &aio;
  ret = aio_suspend(&cb, 1, NULL);
  if (ret<0)
    oops("aio_suspend");
  if (aio_error(&aio))
    return -1;
  return aio_return(&aio);
}

static unsigned long long   nul_last;
static int          nul_was;

static void
fin(void)
{
  if (!nul_was)
    return;
  printf("%010llx\n", nul_last);
  fflush(stdout);
  nul_was   = 0;
}

static void
checknul(unsigned long long pos, unsigned char *buf, int len)
{
  static unsigned char  nullblock[SECTOR];
  int           off;

  for (off=0; off<len; off+=SECTOR)
    if (memcmp(nullblock, buf+off, SECTOR))
      fin();
    else
      {
        if (!nul_was)
          {
            printf("%010llx-", pos+off);
            fflush(stdout);
            nul_was = 1;
          }
        nul_last    = pos+off+SECTOR-1;
      }
}

int
main(int argc, char **argv)
{
  unsigned char *buf[2];
  int       fd;
  int       io, got;

  buf[0] = my_memalign(BUFFERLEN);
  buf[1] = my_memalign(BUFFERLEN);

  if (argc!=2)
    oops("Usage: checknul file");
  if ((fd=open(argv[1], O_RDONLY))<0)
    oops(argv[1]);

  aio.aio_nbytes    = BUFFERLEN;
  aio.aio_fildes    = fd;
  aio.aio_offset    = 0;

  io = 0;
  my_aio_read(buf[io]);
  while ((got=my_aio_wait())>0)
    {
      unsigned long long    pos;

      pos   = aio.aio_offset;

      aio.aio_offset += got;
      my_aio_read(buf[1-io]);

      checknul(pos, buf[io], got);

      io    = 1-io;
    }
  if (got<0)
    oops("read error");
  printf("eof\n");
  close(fd);
  return 0;
}
_
0
Tino

これを投稿したかった 賢い解決策 似ているが以前の質問から、しばらくログインしていない ユーザー によって投稿されました:

デバイスがあります/dev/zero読み取り時に常にゼロを与えるLinuxシステム。

それでは、ハードドライブをこのデバイスと比較してみてはどうでしょうか。

cmp /dev/sdX /dev/zero

ハードドライブをゼロにすることですべてがうまくいけば、それは次のように終了します:

cmp: EOF on /dev/sdb

ハードドライブの最後に到達するまで、2つのファイルは同じであることを伝えます。ハードドライブにゼロ以外のビットがある場合、cmpはそれがファイルのどこにあるかを通知します。

pvパッケージがインストールされている場合は、次のようにします。

pv /dev/sdX | cmp /dev/zero

ドライブをチェックしている間、プログレスバーで同じことを行い、面白がっておくことができます(EOFはsdXではなくSTDINになります)。

0
Hashim