Eu tenho disco rígido cheio de zeros.
Como verificar se todos os bits no disco rígido são zeros usando o bash?
Eu tenho disco rígido cheio de zeros.
Como verificar se todos os bits no disco rígido são zeros usando o bash?
Respostas:
od
substituirá as execuções da mesma coisa por *
, para que você possa usá-lo facilmente para verificar bytes diferentes de zero:
$ sudo od /dev/disk2 | head
0000000 000000 000000 000000 000000 000000 000000 000000 000000
*
234250000
| head
ao final disso, para que, se a unidade não estiver zerada, pare após produzir apenas o suficiente para mostrar o fato, em vez de colocar a unidade inteira na tela.
Eu escrevi um programa C ++ curto para fazer isso, fonte disponível aqui .
Para construí-lo:
wget -O iszero.cpp https://gist.github.com/BobVul/5070989/raw/2aba8075f8ccd7eb72a718be040bb6204f70404a/iszero.cpp
g++ -o iszero iszero.cpp
Para executá-lo:
dd if=/dev/sdX 2>/dev/null | ./iszero
Ele exibirá a posição e o valor de quaisquer bytes diferentes de zero. Você pode redirecionar esta saída para um arquivo com >
, por exemplo:
dd if=/dev/sdX 2>/dev/null | ./iszero >nonzerochars.txt
Você pode tentar mudar BUFFER_SIZE
para obter melhor eficiência. Não tenho certeza do valor ideal. Observe que isso também afeta a frequência com que imprime o progresso, o que afetará um pouco a velocidade (a saída de impressão no console é lenta ). Adicione 2>/dev/null
para se livrar da saída do progresso.
Estou ciente de que isso não está usando o bash padrão, nem mesmo os internos, mas não deve exigir privilégios extras. A solução da @Hennes ainda é mais rápida (eu realmente não otimizei nada - esta é a solução ingênua); no entanto, este pequeno programa pode lhe dar uma idéia melhor de quantos bytes seu limpador perdeu e em que local. Se você desabilitar a saída de progresso, ainda será mais rápido do que a maioria dos discos rígidos de consumo 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 que encontrar, por isso é potencialmente muito mais rápido se houver um diferente de zero próximo ao início do fluxo.
Adicionando fonte à postagem para manter a resposta melhor independente:
#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
vez de exigir que ele seja canalizado com algo parecido iszero < /dev/sda
?
int main(int argc, char *argv[])
e depois FILE* file = fopen(argv[1], "r");
. Feito corretamente, incluiria a verificação se o argumento realmente existe, a verificação de erros com êxito (faça uma ferror
verificação adicional após a fopen
), etc., mas muitos problemas para um programa descartável.
gcc
não está necessariamente disponível em todas as distros do Linux sem a necessidade de baixar pacotes adicionais. Então, novamente numpy não é parte de pacotes Python padrão ou ...
-O3
e -march=native
poderá ver algumas acelerações; isso deve garantir que o GCC habilite a vetorização automática e use o melhor disponível para sua CPU atual (AVX, SSE2 / SSE3, etc.). Junto com isso você pode jogar com o tamanho do buffer; tamanhos de buffer diferentes podem ser mais ideais com loops vetorizados (eu jogaria com 1 MB +, o atual é 1 kB).
@Bob
) no chat: chat.stackexchange.com/rooms/118/root-access
Expandindo a resposta de Gordon, pv
fornece uma indicação de quão longe 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
Parece uma solução feia e ineficiente, mas se você precisar verificar apenas uma vez:
dd if=/dev/sdX | tr --squeeze-repeats "\000" "T"
Usando dd para ler do disco sdX
. (substitua o X pela unidade da qual você deseja ler) e
depois traduza todos os zero bytes não imprimíveis em algo que possamos manipular.
Em seguida, contamos os bytes que podemos manipular e verificamos se é o número certo (use wc -c
para isso) ou pulamos a contagem e usamos o -s
ou--squeeze-repeats
para espremer todas as múltiplas ocorrências em um único caractere.
Assim, dd if=/dev/sdX | tr --squeeze-repeats "\000" "T"
deve imprimir apenas um único T.
Se você deseja fazer isso regularmente, deseja algo mais eficiente.
Se você quiser fazer isso apenas uma vez, esse kludge poderá verificar se o limpador normal está funcionando e se você pode confiar nele.
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 é minha opção segura de exclusão
sudo badblocks -svw /dev/sdX
Se alguém puder recuperar alguma coisa depois de encher a unidade com 0s e 1s alternados, então o complemento, todos os 1s e todos os 0s, com cada passe verificado, funcionou, boa sorte para eles!
Também faz uma boa verificação pré-implantação em novas unidades
man badblocks
para outras opções
Não estou dizendo que é rápido, mas funciona ...
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.
Algum tempo atrás, eu estava curioso 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 esparsas . Eu acho que a fonte diz tudo.
NUL
exibido, será semelhante 0000000000-eof
. Observe que há um truque no programa, a função fin()
não é chamada na linha 107 de propósito para fornecer a saída mostrada.AIO
não é tão direto quanto outras formas,AIO
é provavelmente a maneira mais rápida de manter uma unidade ocupada lendo , porque a NUL
comparação é feita enquanto o próximo bloco de dados é lido. (Podemos espremer mais alguns milissegundos fazendo sobreposiçõesAIO
, mas eu realmente não acho que isso vale a pena o esforço.)true
se o arquivo é legível e tudo funcionou. Ele não retorna false
se o arquivo não for NUL
.NUL
ele ainda funciona, pois os buffers de memória já contêmNUL
. Se alguém acha que isso precisa de uma correção, na linha 95 memcmp(nullblock, buf+off, SECTOR)
pode ler-se 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
).memcmp()
também corrige outro problema nas plataformas, que nãoNUL
alloc()
editam memória, porque o código não faz isso. Mas isso só pode ser visto em arquivos com menos de 4 MiB, mas checknul
provavelmente é um exagero 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;
}
Queria postar esta solução inteligente a partir de uma pergunta semelhante, mas anterior, postada por um usuário que não faz login há um tempo:
Existe um dispositivo
/dev/zero
em um sistema Linux que sempre dá zeros quando lido.Então, que tal comparar seu disco rígido com este dispositivo:
cmp /dev/sdX /dev/zero
Se tudo estiver bem em zerar o disco rígido, ele terminará com:
cmp: EOF on /dev/sdb
dizendo que os dois arquivos são os mesmos até o final do disco rígido. Se houver um bit diferente de zero no disco rígido,
cmp
será informado onde está o arquivo.Se você tiver o
pv
pacote instalado, então:pv /dev/sdX | cmp /dev/zero
fará o mesmo com uma barra de progresso para mantê-lo divertido enquanto verifica sua unidade (o EOF agora estará no STDIN, e não no sdX).