Como verificar se o disco rígido está cheio de zeros no Linux?

12

Eu tenho disco rígido cheio de zeros.

Como verificar se todos os bits no disco rígido são zeros usando o bash?

    
por gkfvbnhjh2 02.03.2013 / 12:24

7 respostas

23

od substituirá as execuções da mesma coisa com * , para que você possa usá-lo facilmente para procurar bytes diferentes de zero:

$ sudo od /dev/disk2 | head
0000000    000000  000000  000000  000000  000000  000000  000000  000000
*
234250000
    
por 02.03.2013 / 17:05
8

Eu escrevi um programa C ++ curto para fazer isso, fonte disponível aqui .

Para construí-lo:

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

Para executá-lo:

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

Ele mostrará a posição e o valor de quaisquer bytes diferentes de zero. Você pode redirecionar essa saída para um arquivo com > , por exemplo:

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

Você pode tentar alterar BUFFER_SIZE para uma melhor eficiência. Não tenho certeza de qual seria o valor ideal. Observe que isso também afeta a frequência com que o progresso é impresso, o que afetará a velocidade (a saída da impressão para o console é lenta ). Adicione 2>/dev/null para se livrar da saída do progresso.

Estou ciente de que isso não está usando bash padrão, nem mesmo builtins, mas não deve exigir privilégios extras. A solução da @Hennes ainda é mais rápida (eu realmente não otimizei nada - essa é a solução ingênua); No entanto, esse pequeno programa pode dar uma idéia melhor de quantos bytes seu limpador perdeu e em que local. Se você desativar a saída do progresso, ela ainda será mais rápida do que a maioria dos discos rígidos dos consumidores pode ler (> 150 MB / s), então isso não é um grande problema.

Uma versão mais rápida com saída menos detalhada está disponível aqui . No entanto, ainda é um pouco mais lento que a solução da @Hennes. Este, no entanto, será encerrado no primeiro caractere diferente de zero encontrado, por isso é potencialmente muito mais rápido se houver um número diferente de zero próximo ao início do fluxo.

Adicionando fonte para postar para manter a resposta melhor autônoma:

#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;
}
    
por 02.03.2013 / 14:42
5

Esta parece ser uma solução feia e ineficiente, mas se você precisar verificar apenas uma vez:

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

Usando o dd para ler do disco wc -c . (substitua o X pela unidade que você deseja ler),
Então traduzindo todos os zero bytes não imprimíveis para algo que possamos manipular.

Em seguida, contamos os bytes que podemos manipular e verificamos se é o número correto (use -s para isso), ou ignoramos a contagem e usamos o --squeeze-repeats ou dd if=/dev/sdX | tr --squeeze-repeats "%code%0" "T" para espremer todas as ocorrências múltiplas em um único char.

Assim, %code% deve imprimir apenas um único T.

Se você quiser fazer isso regularmente, então você quer algo mais eficiente.
Se você quiser fazer isso apenas uma vez, este kludge pode verificar se o limpador normal está funcionando e se pode confiar nele.

    
por 02.03.2013 / 13:50
5

Expandindo a resposta de Gordon, pv fornece uma indicação de até onde o processo está:

$ 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
    
por 27.09.2013 / 01:08
2

Para verificar apenas, você verá todos os blocos que não correspondem listados

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

Ou use badblocks para escrevê-los e verificar:

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

O teste destrutivo padrão é meu apagamento seguro de escolha

sudo badblocks -svw /dev/sdX

Se alguém puder recuperar qualquer coisa depois de encher o drive com 0s e 1s alternados, então o complemento deles, então todos os 1s, depois todos os 0s, com cada passe verificado, funcionou, boa sorte para eles!

Também faz uma boa verificação de pré-implantação em novas unidades

man badblocks

para outras opções

Não estou dizendo que é rápido, mas funciona ...

    
por 29.04.2014 / 01:47
1

Melhor dos dois mundos. Este comando irá pular setores defeituosos:

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

Use kill -USR1 <pid of dd> para ver o progresso.

    
por 01.10.2013 / 15:15
0

Algum tempo atrás eu estava curioso sobre AIO . O resultado foi um programa de teste de amostra que verifica os setores (blocos de 512 bytes) que são NUL . Você pode ver isso como uma variante de um detector de regiões de arquivo esparso . Acho que a fonte diz tudo.

  • Se o arquivo / unidade inteira for NUL , a saída será semelhante a 0000000000-eof . Note que há um truque no programa, a função fin() não é chamada na linha 107 para propiciar a saída mostrada.
  • Não altamente testado, portanto, pode conter bugs
  • O código é um pouco mais longo, pois AIO não é tão direto quanto outras formas,
  • no entanto AIO é provavelmente a maneira mais rápida de manter uma unidade ocupada lendo , porque a comparação NUL é feita enquanto o próximo bloco de dados é lido. (Podemos extrair alguns mais milissegundos, fazendo sobreposição de AIO , mas eu realmente não acho que vale a pena o esforço.
  • Ele sempre retorna true se o arquivo for legível e tudo funcionou. Ele não retorna false se o arquivo não for NUL .
  • Ele assume que o tamanho do arquivo é um múltiplo de 512. Há um bug no último setor, no entanto, em um arquivo totalmente NUL ele ainda funciona, já que os buffers de memória já contêm NUL . Se alguém achar que isso precisa de uma correção, na linha 95, o memcmp(nullblock, buf+off, SECTOR) poderia ler memcmp(nullblock, buf+off, len-off<SECTOR : len-off : SECTOR) . Mas a única diferença é que o "relatório final" talvez seja um pouco aleatório (não para um arquivo que é inteiramente NUL ).
  • O memcmp() alterado também corrige outro problema nas plataformas, o que não é NUL alloc() ed memory, porque o código não o faz. Mas isso só pode ser visto por arquivos com menos de 4 MiB, mas checknul provavelmente é um exagero simples para uma tarefa tão pequena;)

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;
}
    
por 10.05.2014 / 12:50