Tengo un disco duro lleno de ceros.
¿Cómo verificar si todos los bits en el disco duro son ceros usando bash?
Tengo un disco duro lleno de ceros.
¿Cómo verificar si todos los bits en el disco duro son ceros usando bash?
Respuestas:
od
reemplazará las ejecuciones de lo mismo *
, por lo que puede usarlo fácilmente para buscar bytes distintos de cero:
$ sudo od /dev/disk2 | head
0000000 000000 000000 000000 000000 000000 000000 000000 000000
*
234250000
| head
al final de eso, de modo que si resulta que la unidad no está puesta a cero, se detiene después de producir la salida suficiente para mostrar el hecho, en lugar de volcar toda la unidad en la pantalla.
He escrito un breve programa en C ++ para hacerlo, fuente disponible aquí .
Para construirlo:
wget -O iszero.cpp https://gist.github.com/BobVul/5070989/raw/2aba8075f8ccd7eb72a718be040bb6204f70404a/iszero.cpp
g++ -o iszero iszero.cpp
Para ejecutarlo:
dd if=/dev/sdX 2>/dev/null | ./iszero
Producirá la posición y el valor de cualquier byte distinto de cero. Puede redirigir esta salida a un archivo con >
, por ejemplo:
dd if=/dev/sdX 2>/dev/null | ./iszero >nonzerochars.txt
Es posible que desee intentar cambiar BUFFER_SIZE
para una mejor eficiencia. No estoy seguro de cuál podría ser un valor óptimo. Tenga en cuenta que esto también afecta la frecuencia con la que imprime el progreso, lo que afectará un poco la velocidad (la salida de impresión a la consola es lenta ). Agregue 2>/dev/null
para deshacerse de la salida de progreso.
Soy consciente de que esto no está utilizando bash estándar, ni siquiera incorporados, pero no debería requerir ningún privilegio adicional. La solución de @Hennes es aún más rápida (realmente no he optimizado nada, esta es la solución ingenua); sin embargo, este pequeño programa puede darle una mejor idea de cuántos bytes ha perdido su limpiador y en qué ubicación. Si deshabilita la salida de progreso, seguirá siendo más rápido de lo que la mayoría de los discos duros de consumo pueden leer (> 150 MB / s), por lo que no es un gran problema.
Una versión más rápida con una salida menos detallada está disponible aquí . Sin embargo, todavía es un poco más lento que la solución de @Hennes. Sin embargo, este se cerrará en el primer personaje distinto de cero que encuentre, por lo que es potencialmente mucho más rápido si hay un distinto de cero cerca del comienzo de la transmisión.
Agregar fuente a la publicación para mantener la respuesta mejor autocontenida:
#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
lugar de requerir que se canalice con algo como iszero < /dev/sda
?
int main(int argc, char *argv[])
y luego FILE* file = fopen(argv[1], "r");
. Hecho correctamente, incluiría verificar si el argumento realmente existe, la verificación de error se abrió con éxito (hacer una ferror
verificación adicional después de fopen
), etc., pero demasiados problemas para un programa desechable.
gcc
que no está necesariamente disponible en todas las distribuciones de Linux sin extraer paquetes adicionales. Por otra parte, numpy tampoco forma parte de los paquetes estándar de Python ...
-O3
y -march=native
puede ver algunas aceleraciones; eso debería asegurarse de que GCC habilite la vectorización automática y utilice el mejor disponible para su CPU actual (AVX, SSE2 / SSE3, etc.). Junto con eso puedes jugar con el tamaño del búfer; diferentes tamaños de búfer pueden ser más óptimos con bucles vectorizados (jugaría con 1MB +, el actual es 1kB).
@Bob
) en el chat: chat.stackexchange.com/rooms/118/root-access
Ampliando la respuesta de Gordon, pv
proporciona una indicación de qué tan avanzado está el proceso:
$ 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
Esto parece una solución fea e ineficiente, pero si tiene que verificar solo una vez:
dd if=/dev/sdX | tr --squeeze-repeats "\000" "T"
Usando dd para leer desde el disco sdX
. (reemplace la X con la unidad desde la que desea leer),
luego traduzca todos los bytes cero no imprimibles a algo que podamos manejar.
Luego, contamos los bytes que podemos manejar y verificamos si es el número correcto ( wc -c
para eso), o saltamos el conteo y usamos -s
o --squeeze-repeats
para exprimir todas las ocurrencias múltiples en un solo carácter.
Por dd if=/dev/sdX | tr --squeeze-repeats "\000" "T"
lo tanto, debe imprimir solo una T.
Si quieres hacer esto regularmente, entonces quieres algo más eficiente.
Si desea hacer esto solo una vez, este kludge puede verificar que su limpiador normal esté funcionando y que puede confiar en él.
Para verificar solo, verá los bloques que no coinciden en la lista
sudo badblocks -sv -t 0x00 /dev/sdX
O use badblocks para escribirlos y también verifique:
sudo badblocks -svw -t 0x00 /dev/sdX
La prueba de destrucción predeterminada es mi borrado seguro de elección
sudo badblocks -svw /dev/sdX
Si alguien puede recuperar algo después de llenar el disco con 0s y 1s alternativos, entonces su complemento, luego todos los 1s, luego todos los 0s, con cada pase verificado que funcionó, ¡buena suerte para ellos!
También realiza una buena comprobación previa a la implementación en unidades nuevas
man badblocks
para otras opciones
No digo que sea rápido, pero funciona ...
Lo mejor de ambos mundos. Este comando omitirá sectores defectuosos:
sudo dd if=/dev/sdX conv=noerror,sync | od | head
Use kill -USR1 <pid of dd>
para ver el progreso.
Hace algún tiempo tenía curiosidad AIO
. El resultado fue un programa de prueba de muestra que comprueba los sectores (bloques de 512 bytes) que están NUL
. Puede ver esto como una variante de un detector de regiones de archivos dispersos . Creo que la fuente dice todo.
NUL
salida 0000000000-eof
. Tenga en cuenta que hay un truco en el programa, la función fin()
no se llama en la línea 107 a propósito para dar la salida mostrada.AIO
que no es tan sencillo como otras formas,AIO
es probablemente la forma más rápida de mantener un disco ocupado leyendo , porque elNUL
comparar se realiza con el siguiente bloque de datos se lee en. (Podríamos exprima un poco más milisegundos haciendo superposición AIO
, pero realmente no creo que esto vale la pena el esfuerzo.)true
si el archivo es legible y todo funcionó. No regresa false
si el archivo no esNUL
.NUL
todavía funciona, ya que los búferes de memoria ya contienen NUL
. Si alguien piensa que esto necesita una solución, en la línea 95 memcmp(nullblock, buf+off, SECTOR)
podría leer memcmp(nullblock, buf+off, len-off<SECTOR : len-off : SECTOR)
. Pero la única diferencia es que el "informe final" quizás sea un poco aleatorio (no para un archivo que es completamente NUL
).memcmp()
también soluciona otro problema en las plataformas, que no NUL
alloc()
editan la memoria, porque el código no lo hace. Pero esto solo puede verse en archivos de menos de 4 MiB, pero checknul
probablemente sea una exageración para una tarea tan pequeña;)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;
}
Quería publicar esta solución inteligente a partir de una pregunta similar pero anterior, publicada por un usuario que no ha iniciado sesión por un tiempo:
Hay un dispositivo
/dev/zero
en un sistema Linux que siempre da ceros cuando se lee.Entonces, ¿qué hay de comparar su disco duro con este dispositivo:
cmp /dev/sdX /dev/zero
Si todo está bien al poner a cero su disco duro, terminará con:
cmp: EOF on /dev/sdb
diciéndole que los dos archivos son iguales hasta que llegó al final del disco duro. Si hay un bit distinto de cero en el disco duro
cmp
le indicará dónde está en el archivo.Si tiene el
pv
paquete instalado, entonces:pv /dev/sdX | cmp /dev/zero
hará lo mismo con una barra de progreso para mantenerte entretenido mientras revisa tu disco (el EOF ahora estará en STDIN en lugar de sdX).