จะตรวจสอบว่าฮาร์ดไดรฟ์เต็มไปด้วยศูนย์ใน Linux ได้อย่างไร


16

ฉันมีฮาร์ดไดรฟ์ที่เต็มไปด้วยเลขศูนย์

วิธีตรวจสอบว่าบิตทั้งหมดในฮาร์ดไดรฟ์เป็นศูนย์โดยใช้ bash หรือไม่


เป็นที่ยอมรับหรือไม่ที่จะเขียนทับไดรฟ์ทั้งหมดด้วยศูนย์ หรือคุณต้องการยืนยันเนื้อหาปัจจุบันจริง ๆ ?
Bob

ฉันต้องการตรวจสอบว่าฮาร์ดไดรฟ์เต็มไปด้วยเลขศูนย์
gkfvbnhjh2

1
ในทางทฤษฎีอาจมีข้อผิดพลาดในเครื่องมือฆ่าเชื้อข้อมูลที่ทำให้ข้อมูลบางอย่างเสียหาย ฉันไม่แน่ใจว่าทุกบิตเป็นศูนย์ ดังนั้นฉันจะตรวจสอบได้อย่างไรว่า hdd เต็มไปด้วยเลขศูนย์?
gkfvbnhjh2

ทำไมต้องเป็นศูนย์ คุณจะไม่สุ่มเขียนเลขศูนย์และ 1s หลายครั้งไหม

13
เนื่องจาก 1s นั้นแคบกว่า 0 - คุณสามารถดูข้อมูลเก่าได้ง่ายขึ้น
ChrisA

คำตอบ:


29

odจะแทนที่การรันในสิ่งเดียวกันด้วย*ดังนั้นคุณสามารถใช้มันเพื่อสแกนหาไบต์ที่ไม่ใช่ศูนย์:

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

8
ฉันจะเพิ่ม| headในตอนท้ายของมันเพื่อที่ว่าถ้ามันเป็นว่าไดรฟ์ไม่ได้เป็นศูนย์ก็จะหยุดหลังจากที่ผลิตเพียงพอที่จะแสดงความจริงแทนการทิ้งไดรฟ์ทั้งหมดไปที่หน้าจอ
Wyzard

2
@ Wyzard: ความคิดที่ยอดเยี่ยม; ฉันจะเพิ่มเข้าไปในคำตอบของฉัน
Gordon Davisson

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เพื่อกำจัดเอาต์พุตความคืบหน้า

ฉันรู้ว่านี่ไม่ได้ใช้ทุบตีมาตรฐานหรือแม้แต่บิวอิน แต่ไม่ควรต้องการสิทธิ์พิเศษใด ๆ @Hennes 'solution ยังเร็วขึ้น (ฉันไม่ได้ปรับอะไรให้ดีที่สุด - นี่เป็นโซลูชั่นที่ไร้เดียงสา); อย่างไรก็ตามโปรแกรมเล็ก ๆ นี้สามารถช่วยให้คุณมีความคิดที่ดีขึ้นว่ามีกี่ไบต์ที่ปัดน้ำฝนที่คุณพลาดและอยู่ในตำแหน่งใด หากคุณปิดใช้งานเอาต์พุตความคืบหน้าจะยังคงเร็วกว่าฮาร์ดไดรฟ์สำหรับผู้บริโภคส่วนใหญ่ที่สามารถอ่านได้ (> 150 MB / s) ดังนั้นจึงไม่ใช่ปัญหาใหญ่

รุ่นที่เร็วขึ้นด้วยน้อย verbose ส่งออกสามารถใช้ได้ที่นี่ อย่างไรก็ตามมันยังช้ากว่าโซลูชันของ @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?
Hashim

1
@Hashim สิ่งนี้เขียนขึ้นเป็นโปรแกรมที่ถูกทิ้งมากขึ้นเมื่อไม่นานมานี้ (ทุกวันนี้ฉันทำอย่างน้อยในภาษาสคริปต์เช่น Python มากกว่าที่จะคอมไพล์ C) ... ที่กล่าวถ้าคุณต้องการโต้แย้งใน วิธีที่ง่ายที่สุดก็ต้องการจะอยู่ที่ไหนสักแห่งตามแนวของการทำมันแล้วint main(int argc, char *argv[]) FILE* file = fopen(argv[1], "r");ทำอย่างถูกต้องซึ่งรวมถึงการตรวจสอบว่ามีข้อโต้แย้งเกิดขึ้นจริงหรือไม่การตรวจสอบข้อผิดพลาดเปิดสำเร็จ (ทำการferrorตรวจสอบเพิ่มเติมหลังจากfopen) และอื่น ๆ แต่มีปัญหามากเกินไปสำหรับโปรแกรมการทิ้ง
Bob

1
@Hashim ฉันสงสัยว่าการดำเนินการ vectorised SIMD ใน numpy จะใกล้เคียงกับคำสั่ง vectorised ใน C. และนั่นคือสมมติว่าคอมไพเลอร์ C ฉลาดพอที่จะ vectorise ลูปในโปรแกรม C ไร้เดียงสา จะต้องมีมาตรฐานเพื่อให้แน่ใจว่า; โชคไม่ดีที่ฉันไม่มีเวลาที่จะทำอย่างนั้นในตอนนี้ ข้อได้เปรียบหลักของ Python (et al.) คือโดยทั่วไปจะมีอยู่และสามารถรันได้โดยไม่ต้องมีคอมไพเลอร์ในขณะที่gccไม่จำเป็นต้องมีใน Linux distros ทั้งหมดโดยไม่ต้องดึงแพ็คเกจเพิ่มเติม จากนั้น numpy อีกครั้งไม่ได้เป็นส่วนหนึ่งของแพคเกจหลามมาตรฐานทั้ง ...
บ๊อบ

1
@Hashim ถ้าคุณคอมไพล์ด้วย-O3และ-march=nativeคุณอาจเห็น speedups; ที่ควรตรวจสอบให้แน่ใจว่า GCC เปิดใช้งาน auto-vectorisation และใช้งานได้ดีที่สุดสำหรับ CPU ปัจจุบันของคุณ (AVX, SSE2 / SSE3 ฯลฯ ) พร้อมกับที่คุณสามารถเล่นกับขนาดบัฟเฟอร์; ขนาดบัฟเฟอร์ที่แตกต่างกันอาจดีที่สุดเมื่อใช้ vectorised ลูป (ฉันเล่นด้วย 1MB + ปัจจุบันคือ 1kB)
Bob

1
@Hashim ด้านบนแก้ไขความคิดเห็นในกรณีที่คุณไม่เห็น นอกเหนือจากนั้นหากคุณต้องการหารือเพิ่มเติมคุณสามารถ ping ฉัน ( @Bob) ในการแชท: chat.stackexchange.com/rooms/118/root-access
Bob

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

นี่เป็นประโยชน์อย่างมากกับฮาร์ดไดรฟ์ขนาดใหญ่!
Martin Hansen

5

ดูเหมือนว่าจะเป็นวิธีที่ไม่มีประสิทธิภาพน่าเกลียด แต่ถ้าคุณต้องตรวจสอบเพียงครั้งเดียว:

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"ควรพิมพ์เพียงทีเดียว

หากคุณต้องการทำสิ่งนี้เป็นประจำคุณต้องการบางสิ่งที่มีประสิทธิภาพมากขึ้น
หากคุณต้องการทำสิ่งนี้เพียงครั้งเดียวกระบองนี้อาจตรวจสอบว่าที่ปัดน้ำฝนปกติของคุณทำงานได้และคุณสามารถเชื่อถือได้


ทำไมคุณถึงคิดว่าวิธีนี้ไม่มีประสิทธิภาพ? มีการกำหนดบัฟเฟอร์บางอย่างที่ต้องอ่านผ่านตำแหน่งที่ไม่ใช่ NUL แรกหรือไม่
Daniel Beck

มีปัญหาที่อาจเกิดขึ้นหรือไม่ที่ตัวอักษร 'T' ปรากฏอยู่ในไอน้ำว่าเป็นตัวละครที่ไม่ใช่ศูนย์เท่านั้น
Bob

จริง นั่นคือข้อบกพร่องในการออกแบบ ฉันไม่ได้ใช้ bash (ตัวเชลล์) แต่ฉันคิดว่าด้วย "Bash" คุณหมายถึง "ไม่ใช่จากการทุบตีจากการใช้ shell prompt และเครื่องมือโหมดข้อความมาตรฐาน"
Hennes

3
@daniel: โปรแกรม C แบบง่ายควรอ่านข้อมูลทั้งหมดโดยไม่ต้องเปลี่ยนทุกไบต์อ่าน ซึ่งจะมีประสิทธิภาพและเป็นที่ชื่นชอบมากขึ้น มันอาจใช้เวลามากในการเขียนโปรแกรมเช่นนี้มากกว่าแค่ใช้เครื่องมือที่มีอยู่อย่างไม่มีประสิทธิภาพ
Hennes

3

ในการตรวจสอบเท่านั้นคุณจะเห็นบล็อคที่ไม่ตรงกับรายการ

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

หรือใช้ badblocks เพื่อเขียนและตรวจสอบ:

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

การทดสอบการทำลายล้างเริ่มต้นคือการลบตัวเลือกที่ปลอดภัยของฉัน

sudo badblocks -svw /dev/sdX

หากใครสามารถเรียกคืนข้อมูลใด ๆ หลังจากเติมไดรฟ์ด้วย 0s และ 1s จากนั้นส่วนประกอบของพวกเขาจากนั้น 1s ทั้งหมดจากนั้น 0s ทั้งหมดโดยผ่านการตรวจสอบผ่านทุกครั้งมันทำงานได้ดีโชคดีกับพวกเขา!

ทำการตรวจสอบ pre-deployment ที่ดีสำหรับไดรฟ์ใหม่ด้วย

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หากไฟล์นั้นสามารถอ่านได้และทุกอย่างทำงานได้ มันไม่กลับถ้าไฟล์คือไม่ใช่falseNUL
  • ก็ถือว่าขนาดไฟล์มีหลาย 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อาจเป็น overkill ธรรมดาสำหรับงานเล็ก ๆ น้อย ๆ ;)

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/zeroบนระบบ Linux ที่ให้ค่าเป็นศูนย์เสมอเมื่ออ่าน

ดังนั้นวิธีเปรียบเทียบฮาร์ดไดรฟ์ของคุณกับอุปกรณ์นี้:

cmp /dev/sdX /dev/zero

หากทุกอย่างดีโดยไม่ทำให้ฮาร์ดไดรฟ์ของคุณเป็นศูนย์มันจะจบลงด้วย:

cmp: EOF on /dev/sdb

บอกคุณว่าทั้งสองไฟล์เหมือนกันจนกว่าจะถึงจุดสิ้นสุดของฮาร์ดไดรฟ์ หากมีบิตที่ไม่เป็นศูนย์ในฮาร์ดไดรฟ์cmpจะบอกคุณว่ามันอยู่ที่ไหนในไฟล์

หากคุณpvติดตั้งแพ็คเกจแล้ว:

pv /dev/sdX | cmp /dev/zero

จะทำสิ่งเดียวกันกับแถบความคืบหน้าเพื่อให้คุณสนุกสนานในขณะที่ตรวจสอบไดรฟ์ของคุณ (EOF จะอยู่ใน STDIN มากกว่า sdX แม้ว่า)

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.