Come verificare che il disco rigido sia pieno di zero in Linux?


15

Ho il disco rigido pieno di zero.

Come verificare se tutti i bit sul disco rigido sono zeri usando bash?


Sarebbe accettabile sovrascrivere l'intera unità con zero? O hai davvero bisogno di confermare i contenuti attuali?
Bob

Voglio verificare che il disco rigido sia pieno di zeri.
gkfvbnhjh2

1
In teoria potrebbe esserci un bug negli strumenti di disinfezione dei dati che lascia intatti alcuni dati. Non voglio essere sicuro che ogni bit sia zero. Quindi, come posso verificare se hdd è pieno di zero?
gkfvbnhjh2,

Perché zero? Non scriveresti a caso zero e 1, più volte?

13
Poiché gli 1 sono più stretti degli 0, puoi vedere più facilmente i vecchi dati tra di loro.
ChrisA

Risposte:


28

odsostituirà le esecuzioni della stessa cosa con *, quindi puoi facilmente usarlo per scansionare i byte diversi da zero:

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

8
Aggiungerei | headalla fine quello, in modo che se si scopre che l'unità non è azzerata, si arresta dopo aver prodotto l'output sufficiente per mostrare il fatto, invece di scaricare l'intero disco sullo schermo.
Wyzard,

2
@Wyzard: ottima idea; Lo aggiungerò alla mia risposta.
Gordon Davisson

8

Ho scritto un breve programma C ++ per farlo, fonte disponibile qui .

Per costruirlo:

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

Per eseguirlo:

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

Produrrà la posizione e il valore di tutti i byte diversi da zero. È possibile reindirizzare questo output su un file con >, ad esempio:

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

Potresti provare a cambiare BUFFER_SIZEper una migliore efficienza. Non sono sicuro di quale possa essere un valore ottimale. Notare che ciò influisce anche sulla frequenza con cui stampa l'avanzamento, il che influirà in qualche modo sulla velocità (la stampa dell'output sulla console è lenta ). Aggiungi 2>/dev/nullper eliminare l'output dei progressi.

Sono consapevole che questo non utilizza bash standard, né incorpora, ma non dovrebbe richiedere alcun privilegio aggiuntivo. La soluzione di @Hennes è ancora più veloce (non ho davvero ottimizzato nulla - questa è la soluzione ingenua); tuttavia, questo piccolo programma può darti un'idea di quanti byte ha perso il tuo tergicristallo e in quale posizione. Se disabiliti l'output di avanzamento, sarà comunque più veloce di quanto la maggior parte dei dischi rigidi consumer possa leggere (> 150 MB / s), quindi non è un grosso problema.

Una versione più veloce con output meno dettagliato è disponibile qui . Tuttavia, è ancora un po 'più lento della soluzione di @Hennes. Questo, tuttavia, si chiuderà sul primo carattere diverso da zero che incontra, quindi è potenzialmente molto più veloce se c'è un diverso da zero vicino all'inizio del flusso.


Aggiunta della fonte ai post per mantenere una risposta più autonoma:

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

Questa è un'ottima risposta, ma c'è un modo per far funzionare lo script più come un normale comando - usando iszero /dev/sdaanziché richiedere che sia convogliato con qualcosa del genere iszero < /dev/sda?
Hashim,

1
@Hashim Questo è stato scritto più o meno come un programma usa e getta un po 'di tempo fa (al giorno d'oggi lo farei almeno in un linguaggio di scripting come Python piuttosto che compilato C) ... che diceva, se volevi prendere argomenti nel il modo più semplice, sarebbe da qualche parte sulla falsariga di farlo int main(int argc, char *argv[])e poi FILE* file = fopen(argv[1], "r");. Fatto correttamente includerebbe il controllo se l'argomento esiste realmente, il controllo degli errori si è aperto correttamente (fare un ferrorcontrollo aggiuntivo dopo il fopen), ecc., Ma troppi problemi per un programma usa e getta.
Bob,

1
@Hashim Sospetto che le operazioni vettorializzate SIMD in numpy sarebbero vicine alle istruzioni vettorizzate in C. E questo presuppone che il compilatore C sia abbastanza intelligente da vettorializzare il ciclo nel programma ingenuo C. Dovrebbe essere benchmark per essere sicuro; sfortunatamente non ho davvero il tempo di farlo proprio ora. Il vantaggio principale di Python (et al.) È che è generalmente disponibile e eseguibile senza un compilatore, mentre gccnon è necessariamente disponibile su tutte le distribuzioni Linux senza estrarre pacchetti aggiuntivi. Quindi di nuovo numpy non fa parte dei pacchetti standard di Python ...
Bob

1
@Hashim Se si compila con -O3 e -march=nativepotresti vedere alcune accelerazioni; ciò dovrebbe assicurarsi che GCC abiliti l'auto-vettorializzazione e utilizzi il meglio disponibile per la CPU corrente (AVX, SSE2 / SSE3, ecc.). Insieme a questo puoi giocare con la dimensione del buffer; diverse dimensioni del buffer potrebbero essere più ottimali con loop vettoriali (giocherei con 1 MB +, quello attuale è 1 KB).
Bob,

1
@Hashim Sopra il commento modificato, nel caso non lo vedessi. Oltre a ciò, se desideri discutere ulteriormente, puoi eseguire il ping ( @Bob) nella chat: chat.stackexchange.com/rooms/118/root-access
Bob

6

Espandendo la risposta di Gordon, pvfornisce un'indicazione di quanto è lungo il processo:

$ 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

Questo è molto utile con un grande disco rigido!
Martin Hansen,

5

Questa sembra una brutta soluzione inefficiente, ma se devi controllare solo una volta:

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

Utilizzando dd per leggere dal disco sdX . (sostituisci la X con l'unità da cui vuoi leggere),
quindi traduci tutti i byte zero non stampabili in qualcosa che possiamo gestire.

Successivamente contiamo i byte che possiamo gestire e controlliamo se è il numero giusto (usare wc -cper quello), oppure saltiamo il conteggio e usiamo -so --squeeze-repeatsper comprimere tutte le ricorrenze multiple su un singolo carattere.

Quindi dd if=/dev/sdX | tr --squeeze-repeats "\000" "T"dovrebbe stampare solo un singolo T.

Se vuoi farlo regolarmente, allora vuoi qualcosa di più efficiente.
Se vuoi farlo solo una volta, questo kludge può verificare che il tuo normale tergicristallo funzioni e che ti puoi fidare.


Perché ritieni che questa soluzione sia inefficiente? Esiste un buffering che richiede la lettura ben oltre la prima posizione non NUL?
Daniel Beck

Esiste un potenziale problema in cui una "T" letterale è presente nel vapore come unico carattere diverso da zero?
Bob

Vero. Questo è un difetto nel design. Inoltre non sto usando bash (la shell stessa), ma ho ipotizzato che con "Bash" intendevi "Non da bash, dall'uso di qualsiasi prompt della shell e strumenti di modalità testo standard".
Hennes,

3
@daniel: un semplice programma C dovrebbe essere in grado di leggere tutti i dati senza cambiare ogni byte letto. Quale sarebbe più efficiente ed esteticamente piacevole. Potrebbe anche volerci molto più tempo per scrivere un tale programma piuttosto che usare gli strumenti disponibili in modo inefficiente.
Hennes,

3

Per verificare solo, vedrai tutti i blocchi che non corrispondono elencati

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

Oppure usa i badblock per scriverli e controllare:

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

Il test distruttivo predefinito è la mia cancellazione sicura della scelta

sudo badblocks -svw /dev/sdX

Se qualcuno riesce a recuperare qualcosa dopo aver riempito l'unità con 0 e 1 alternati, quindi il loro complemento, quindi tutti gli 1, quindi tutti gli 0, con ogni passaggio verificato funzionava, buona fortuna a loro!

Esegue un buon controllo pre-implementazione anche su nuove unità

man badblocks

per altre opzioni

Non dire che è veloce, ma funziona ...


2

Il meglio di entrambi i mondi. Questo comando salterà i settori danneggiati:

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

Usa kill -USR1 <pid of dd>per vedere i progressi.


0

Qualche tempo fa ero curioso AIO. Il risultato è stato un programma di test di esempio che verifica la presenza di settori (blocchi da 512 byte) NUL. Puoi vederlo come una variante di un rilevatore di regioni di file sparse . Penso che la fonte dica tutto.

  • Se l'intero file / unità viene NULemesso appare come 0000000000-eof. Si noti che c'è un trucco nel programma, funzionefin() non viene chiamata apposta alla linea 107 per fornire l'output mostrato.
  • Non pesantemente testato, quindi potrebbe contenere bug
  • Il codice è un po 'più lungo, come AIO non è semplice come altri modi,
  • tuttavia AIOè probabilmente il modo più veloce per tenere occupata la lettura di un'unità , perché il NULconfronto viene eseguito mentre viene letto il blocco di dati successivo.AIO , ma davvero non pensiamo questo vale il sforzo.)
  • Restituisce sempre truese il file è leggibile e tutto ha funzionato. Non restituisce falsese il file non èNUL .
  • Presuppone che la dimensione del file sia un multiplo di 512. C'è un bug sull'ultimo settore, tuttavia su un file NULfunziona ancora completamente , poiché i buffer di memoria già contengono NUL. Se qualcuno pensa che questo abbia bisogno di una correzione, nella riga 95 memcmp(nullblock, buf+off, SECTOR)potrebbe leggere memcmp(nullblock, buf+off, len-off<SECTOR : len-off : SECTOR). Ma l'unica differenza è che il "end reporting" è forse un po 'casuale (non per un file che è interamente NUL).
  • La modifica memcmp()risolve anche un altro problema sulle piattaforme, che non modificano la NUL alloc()memoria, perché il codice non lo fa. Ma questo potrebbe essere visto solo da file inferiori a 4 MiB, ma checknulprobabilmente è semplicemente eccessivo per un compito così piccolo;)

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

Volevo pubblicare questa soluzione intelligente da una domanda simile ma precedente, pubblicata da un utente che non ha effettuato l'accesso per un po ':

C'è un dispositivo /dev/zero su un sistema Linux che dà sempre zero quando viene letto.

Quindi, che ne dici di confrontare il tuo disco rigido con questo dispositivo:

cmp /dev/sdX /dev/zero

Se tutto va bene con l'azzeramento del disco rigido, terminerà con:

cmp: EOF on /dev/sdb

dicendoti che i due file sono uguali fino a quando non arriva alla fine del disco rigido. Se sul disco rigido è presente un bit diverso da zerocmp verrà indicato dove si trova nel file.

Se il pvpacchetto è installato, allora:

pv /dev/sdX | cmp /dev/zero

farà la stessa cosa con una barra di avanzamento per farti divertire mentre controlla il tuo disco (l'EOF sarà ora su STDIN anziché su sdX).

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.