Bagaimana cara memverifikasi bahwa hard drive diisi dengan nol di Linux?


15

Saya memiliki hard drive yang diisi dengan angka nol.

Bagaimana memeriksa apakah semua bit pada hard drive nol menggunakan bash?


Apakah bisa diterima untuk hanya menimpa seluruh drive dengan nol? Atau apakah Anda benar-benar perlu mengkonfirmasi konten saat ini?
Bob

Saya ingin memverifikasi bahwa hard drive diisi dengan nol.
gkfvbnhjh2

1
Secara teori mungkin ada bug dalam alat sanitasi data yang membuat beberapa data utuh. Saya tidak ingin memastikan bahwa setiap bit adalah nol. Jadi, bagaimana saya memeriksa apakah hdd penuh dengan nol?
gkfvbnhjh2

Mengapa nol? Apakah Anda tidak akan menulis nol dan 1 secara acak, beberapa kali?

13
Karena 1 lebih sempit dari 0 - Anda dapat melihat data lama di antara mereka lebih mudah.
ChrisA

Jawaban:


28

od akan menggantikan proses yang sama dengan * , sehingga Anda dapat dengan mudah menggunakannya untuk memindai byte yang bukan nol:

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

8
Saya akan menambahkan | headpada akhirnya, sehingga jika ternyata drive tidak memusatkan perhatian, berhenti setelah hanya menghasilkan output yang cukup untuk menunjukkan fakta, alih-alih membuang seluruh drive ke layar.
Wyzard

2
@ Wyzard: Ide bagus; Saya akan menambahkannya ke jawaban saya.
Gordon Davisson

8

Saya telah menulis program C ++ singkat untuk melakukannya, sumber tersedia di sini .

Untuk membangunnya:

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

Untuk menjalankannya:

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

Ini akan menampilkan posisi dan nilai byte yang bukan nol. Anda dapat mengarahkan output ini ke file dengan> , misalnya:

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

Anda mungkin ingin mencoba mengubah BUFFER_SIZEuntuk efisiensi yang lebih baik. Saya tidak yakin apa nilai optimalnya. Perhatikan bahwa ini juga memengaruhi seberapa sering ia mencetak kemajuan, yang agaknya akan mempengaruhi kecepatan (hasil cetak ke konsol lambat ). Tambahkan 2>/dev/nulluntuk menyingkirkan hasil kemajuan.

Saya sadar ini tidak menggunakan standar bash, atau bahkan builtin, tetapi seharusnya tidak memerlukan hak istimewa tambahan. Solusi @Hennes masih lebih cepat (saya belum benar-benar mengoptimalkan apa pun - ini adalah solusi naif); Namun, program kecil ini dapat memberi Anda gambaran yang lebih baik tentang berapa banyak byte yang dihapus oleh wiper Anda, dan di lokasi apa. Jika Anda menonaktifkan output progres, itu masih akan lebih cepat daripada yang dapat dibaca oleh kebanyakan hard drive konsumen (> 150 MB / s), jadi itu bukan masalah besar.

Versi yang lebih cepat dengan output yang lebih sedikit tersedia di sini . Namun, masih sedikit lebih lambat dari solusi @ Henne. Yang ini, bagaimanapun, akan berhenti pada karakter bukan nol pertama yang dihadapinya sehingga berpotensi jauh lebih cepat jika ada nol di dekat awal aliran.


Menambahkan sumber ke pos untuk menjaga agar jawaban tetap lengkap:

#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;
}

Ini adalah jawaban yang bagus, tetapi apakah ada cara untuk membuat skrip bekerja lebih seperti perintah normal - menggunakan iszero /dev/sdadaripada mengharuskannya untuk disalurkan dengan sesuatu seperti iszero < /dev/sda?
Hashim

1
@Hashim Ini ditulis kurang lebih sebagai program sekali pakai beberapa waktu lalu (saat ini saya setidaknya akan melakukannya dalam bahasa scripting seperti Python daripada mengkompilasi C) ... yang mengatakan, jika Anda ingin mengambil argumen di cara paling sederhana, itu akan berada di suatu tempat di sepanjang garis membuatnya int main(int argc, char *argv[])lalu FILE* file = fopen(argv[1], "r");. Dilakukan dengan benar itu termasuk memeriksa apakah argumen itu benar-benar ada, memeriksa kesalahan berhasil terbuka (melakukan pemeriksaan tambahan ferrorsetelah fopen), dll, tetapi terlalu banyak kesulitan untuk program sekali pakai.
Bob

1
@Hashim Saya menduga operasi vektor SIMD di numpy akan dekat dengan instruksi vectorised di C. Dan itu dengan asumsi kompiler C cukup pintar untuk membuat vektor loop dalam program C naif. Harus patokan untuk memastikan; sayangnya saya tidak punya waktu untuk melakukan itu sekarang. Keuntungan utama dari Python (et al.) Adalah ini umumnya tersedia dan dapat dijalankan tanpa kompiler, sementara gccitu tidak selalu tersedia di semua distro Linux tanpa menarik paket tambahan. Kemudian lagi numpy juga bukan bagian dari paket Python standar ...
Bob

1
@Hashim Jika Anda mengkompilasi -O3dan -march=nativeAnda mungkin melihat beberapa speedups; yang seharusnya memastikan GCC mengaktifkan auto-vectorisation dan menggunakan yang terbaik yang tersedia untuk CPU Anda saat ini (AVX, SSE2 / SSE3, dll.). Bersamaan dengan itu Anda bisa bermain dengan ukuran buffer; ukuran buffer yang berbeda mungkin lebih optimal dengan loop vectorised (saya akan bermain dengan 1MB +, yang sekarang adalah 1kB).
Bob

1
@Hashim Di atas komentar diedit, jika Anda tidak melihat. Di luar itu, jika Anda ingin membahas lebih lanjut, Anda dapat melakukan ping saya ( @Bob) dalam obrolan: chat.stackexchange.com/rooms/118/root-access
Bob

6

Memperluas jawaban Gordon, pvmemberikan indikasi seberapa jauh prosesnya adalah:

$ 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

Ini sangat berguna dengan hard drive besar!
Martin Hansen

5

Ini sepertinya solusi yang tidak efisien dan jelek, tetapi jika Anda hanya perlu memeriksa sekali:

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

Menggunakan dd untuk membaca dari disk sdX. (ganti X dengan drive yang ingin Anda baca),
Kemudian terjemahkan semua byte nol yang tidak dapat diproduksi menjadi sesuatu yang dapat kami tangani.

Selanjutnya kita menghitung byte yang bisa kita tangani dan periksa apakah itu angka yang tepat (gunakan wc -cuntuk itu), atau kita lewati menghitung dan menggunakan -satau--squeeze-repeats untuk memeras semua kemunculan banyak ke satu karakter.

Dengan demikian dd if=/dev/sdX | tr --squeeze-repeats "\000" "T"harus mencetak hanya satu T.

Jika Anda ingin melakukan ini secara teratur maka Anda menginginkan sesuatu yang lebih efisien.
Jika Anda ingin melakukan ini hanya sekali saja maka kludge ini dapat memverifikasi bahwa penghapus normal Anda berfungsi dan Anda dapat mempercayainya.


Mengapa Anda menganggap solusi ini tidak efisien? Apakah ada beberapa buffering yang mengharuskan pembacaan jauh melewati lokasi non-NUL pertama?
Daniel Beck

Apakah ada masalah potensial di mana 'T' literal hadir di steam sebagai satu-satunya karakter bukan nol?
Bob

Benar. Itu adalah cacat dalam desain. Saya juga tidak menggunakan bash (shell itu sendiri), tetapi saya berasumsi bahwa dengan "Bash" yang Anda maksud adalah "Bukan dari bash, dari menggunakan shell prompt dan alat mode teks standar".
Hennes

3
@aniel: Program C sederhana harus dapat membaca semua data tanpa mengubah setiap byte baca. Yang akan lebih efisien dan menyenangkan secara estetika. Mungkin juga membutuhkan lebih banyak waktu untuk menulis program semacam itu daripada hanya menggunakan alat yang tersedia dengan cara yang tidak efisien.
Hennes

3

Untuk memeriksa saja, Anda akan melihat blok apa pun yang tidak cocok tercantum

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

Atau gunakan badblock untuk menulisnya serta memeriksa:

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

Tes destrucive default adalah penghapusan pilihan saya yang aman

sudo badblocks -svw /dev/sdX

Jika ada yang bisa mengambil apa pun setelah mengisi drive dengan 0s dan 1s bergantian, maka pelengkap mereka, maka semua 1s, lalu semua 0s, dengan setiap pass diverifikasi berfungsi, semoga sukses untuk mereka!

Melakukan pemeriksaan pra-penempatan yang baik pada drive baru juga

man badblocks

untuk opsi lain

Tidak mengatakan itu cepat, tetapi berhasil ...


2

Terbaik dari kedua dunia. Perintah ini akan melewati bad sector:

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

Gunakan kill -USR1 <pid of dd>untuk melihat kemajuan.


0

Beberapa waktu lalu saya penasaran AIO. Hasilnya adalah program uji sampel yang terjadi untuk memeriksa sektor (blok 512 byte) yang NUL. Anda dapat melihat ini sebagai varian dari detektor wilayah file yang jarang . Saya pikir sumber mengatakan semuanya.

  • Jika seluruh file / drive NULterlihat seperti output 0000000000-eof. Perhatikan bahwa ada trik dalam fungsi programfin() tidak dipanggil pada baris 107 dengan sengaja untuk memberikan hasil yang ditunjukkan.
  • Tidak banyak diuji, jadi mungkin mengandung bug
  • Kode ini sedikit lebih lama, seperti AIO tidak lurus seperti cara lain,
  • Namun AIOadalah mungkin cara tercepat untuk menjaga drive sibuk membaca , karena NULmembandingkan dilakukan sedangkan blok data berikutnya dibaca dalam. (Kita bisa memeras beberapa milidetik lebih dengan melakukan tumpang tindihAIO , tapi aku benar-benar tidak berpikir ini bernilai upaya.)
  • Selalu kembali truejika file dapat dibaca dan semuanya berfungsi. Itu tidak kembali falsejika file tersebut bukanNUL .
  • Ini mengasumsikan bahwa ukuran file adalah kelipatan 512. Ada bug di sektor terakhir, namun pada file sepenuhnya NULmasih berfungsi, karena buffer memori sudah berisi NUL. Jika seseorang berpikir ini perlu diperbaiki, pada baris 95 memcmp(nullblock, buf+off, SECTOR)bisa dibaca memcmp(nullblock, buf+off, len-off<SECTOR : len-off : SECTOR). Tetapi satu-satunya perbedaan adalah, bahwa "pelaporan akhir" mungkin agak acak (bukan untuk file yang seluruhnya NUL).
  • Yang diubah memcmp()juga memperbaiki masalah lain pada platform, yang tidak mengubah NUL alloc()memori, karena kode tidak melakukannya. Tapi ini hanya dapat dilihat oleh file kurang dari 4 MiB, tapi checknulmungkin berlebihan untuk tugas sekecil itu;)

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

Ingin memposting solusi pintar ini dari pertanyaan yang serupa tetapi sebelumnya, diposkan oleh pengguna yang belum masuk untuk sementara waktu:

Ada sebuah perangkat /dev/zero di sistem Linux yang selalu memberikan angka nol saat membaca.

Jadi, bagaimana dengan membandingkan hard drive Anda dengan perangkat ini:

cmp /dev/sdX /dev/zero

Jika semuanya baik-baik saja dengan memusatkan perhatian pada hard drive Anda, itu akan berakhir dengan:

cmp: EOF on /dev/sdb

memberi tahu Anda bahwa kedua file itu sama hingga mencapai ujung hard drive. Jika ada bit yang tidak nol pada hard drivecmp akan memberi tahu Anda di mana file itu berada.

Jika Anda memiliki pvpaket yang diinstal maka:

pv /dev/sdX | cmp /dev/zero

akan melakukan hal yang sama dengan progress bar untuk membuat Anda tetap terhibur saat memeriksa drive Anda (EOF sekarang akan berada pada STDIN daripada sdX sekalipun).

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.