Linuxでハードドライブがゼロで埋められていることを確認する方法は?


15

ゼロでいっぱいのハードドライブがあります。

bashを使用してハードドライブのすべてのビットがゼロであるかどうかを確認する方法


ドライブ全体をゼロで上書きしても問題ありませんか?または、実際に現在の内容を確認する必要がありますか?
ボブ

ハードドライブがゼロで埋められていることを確認したい。
gkfvbnhjh2

1
理論的には、一部のデータをそのまま残すデータサニタイズツールにバグがある可能性があります。すべてのビットがゼロであることを確認したくありません。それでは、hddがゼロでいっぱいかどうかを確認するにはどうすればよいですか?
gkfvbnhjh2

なぜゼロになるのですか?ゼロと1を数回ランダムに書きませんか?

13
1は0よりも狭いため、古いデータをより簡単に見ることができます。
ChrisA

回答:


28

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

$ sudo od /dev/disk2 | head
0000000    000000  000000  000000  000000  000000  000000  000000  000000
*
234250000

8
| head最後に追加します。ドライブがゼロになっていないことが判明した場合、ドライブ全体を画面にダンプするのではなく、事実を示すのに十分な出力を生成した後に停止します。
ワイザー

2
@Wyzard:素晴らしいアイデア。回答に追加します。
ゴードンデイヴィソン

8

そのための短いC ++プログラムを作成しました。ソースはこちらから入手できます

ビルドするには:

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

これは素晴らしい答えですが、より多くの通常のコマンドのようなスクリプトを動作させるためにどのような方法があります-使用してiszero /dev/sdaではなく、のようなものでパイプさ、それを必要としますかiszero < /dev/sda
ハシム

1
@Hashimこれは、かなり以前に使い捨てプログラムとして書かれていました(最近は、少なくともコンパイルされたCではなくPythonのようなスクリプト言語でやります)...最も簡単な方法は、それはそれを作るの線に沿ってどこかになると思いint main(int argc, char *argv[])、その後とFILE* file = fopen(argv[1], "r");。適切に実行すると、引数が実際に存在するかどうかのチェック、オープンのエラーチェックの成功(のferror後に追加のチェックを行うfopen)などが含まれますが、使い捨てプログラムにとっては面倒です。
ボブ

1
@Hashim私は、numpyのSIMDベクトル化操作はCのベクトル化命令に近いと思います。そして、CコンパイラがナイーブCプログラムのループをベクトル化するのに十分スマートであると仮定しています。確実にベンチマークする必要があります。残念ながら、今はそれをする時間がありません。Python(など)の主な利点は、コンパイラなしで一般に利用可能で実行可能であることgccです。また、追加のパッケージをプルダウンせずにすべてのLinuxディストリビューションで必ずしも利用できるわけではありません。その後、再びnumpyのは...どちらかの標準のPythonパッケージの一部ではありません
ボブ

1
@Hashimを使用してコンパイルすると-O3、速度が向上する場合があり-march=nativeます。これにより、GCCで自動ベクトル化が有効になり、現在のCPU(AVX、SSE2 / SSE3など)で利用可能な最適なものが使用されるようになります。それに加えて、バッファサイズで遊ぶことができます。ベクトル化されたループでは、さまざまなバッファサイズがより最適な場合があります(1MB +で再生します。現在のバッファサイズは1kBです)。
ボブ

1
@Hashim上記のコメントは、表示されない場合のために編集されています。さらに、さらに議論したい場合は@Bob、チャットでping()できます:chat.stackexchange.com/rooms/118/root-access
Bob

6

Gordonの答えを拡張する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

これは、大きなハードドライブで非常に便利です。
マーティンハンセン14年

5

これはい非効率的なソリューションのように見えますが、一度だけチェックする必要がある場合:

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

ddを使用してディスクから読み取りますsdX。、(あなたから読みたいドライブとXを置き換える)
次に、翻訳、我々は扱うことができる何かにすべて印刷できないゼロバイトを。

次に、処理可能なバイト数をカウントして正しい数であるかどうかを確認する(そのために使用wc -cする)か、カウントをスキップして-sまたは--squeeze-repeatsを使用して複数のオカレンスをすべて1つの文字に絞り込みます。

したがってdd if=/dev/sdX | tr --squeeze-repeats "\000" "T"、単一のTのみを印刷する必要があります。

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


このソリューションが非効率であると考えるのはなぜですか?最初のNUL以外の場所をはるかに超えて読み取る必要があるバッファリングはありますか?
ダニエルベック

文字列「T」が唯一の非ゼロ文字としてスチームに存在する潜在的な問題はありますか?
ボブ

本当です。これは設計上の欠陥です。私はbash(シェル自体)も使用していませんが、「bash」では「bashからではなく、シェルプロンプトと標準テキストモードツールを使用すること」を意味すると想定しました。
ヘネス

3
@daniel:単純なCプログラムは、すべての読み取りバイトを変更することなく、すべてのデータを読み取ることができるはずです。どちらがより効率的で、見た目も楽しいでしょう。また、利用可能なツールを非効率的な方法で使用するよりも、このようなプログラムを作成するのにはるかに時間がかかる場合があります。
ヘネス

3

チェックのみを行うには、一致しないブロックがリストされます

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

他のオプション用

速いとは言いませんが、うまくいきます...


2

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

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

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


0

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

  • ファイル/ドライブ全体がNUL出力される場合、次のようになり0000000000-eofます。プログラムにはトリックがあります。関数fin()は、表示された出力を提供するために意図的に107行目では呼び出されません。
  • あまりテストされていないため、バグが含まれている可能性があります
  • 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()により、プラットフォームでの別の問題も修正されます。これはNUL alloc()、コードが実行しないため、メモリを編集しません。しかし、これは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

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

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

それでは、ハードドライブとこのデバイスを比較してみてください。

cmp /dev/sdX /dev/zero

すべてが正常にハードドライブのゼロ化に成功した場合、次のコマンドで終了します。

cmp: EOF on /dev/sdb

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

あなたが持っている場合はpv、パッケージをインストールした後:

pv /dev/sdX | cmp /dev/zero

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

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.