У меня жесткий диск заполнен нулями.
Как проверить, что все биты на жестком диске являются нулями, используя bash?
У меня жесткий диск заполнен нулями.
Как проверить, что все биты на жестком диске являются нулями, используя bash?
od
заменит запуск одной и той же вещи на *
, так что вы можете легко использовать ее для поиска ненулевых байтов:
$ sudo od /dev/disk2 | head
0000000 000000 000000 000000 000000 000000 000000 000000 000000
*
234250000
Я написал короткую C++ программу для этого, источник доступен здесь.
Чтобы построить это:
wget -O iszero.cpp https://gist.github.com/Elusive138/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
чтобы избавиться от результатов выполнения.
Я знаю, что это не использует стандартный Bash, ни даже встроенные, но это не должно требовать каких-либо дополнительных привилегий. Решение @Hennes все еще быстрее (я ничего не оптимизировал - это наивное решение); тем не менее, эта небольшая программа может дать вам лучшее представление о том, сколько байтов пропал ваш очиститель и в каком месте. Если вы отключите вывод хода выполнения, он все равно будет быстрее, чем может прочитать большинство потребительских жестких дисков (> 150 МБ / с), так что это не является большой проблемой.
Более быстрая версия с менее подробным выводом доступна здесь. Тем не менее, это все еще немного медленнее, чем решение @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;
}
Расширяя ответ Гордона, 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
Это кажется уродливым неэффективным решением, но если вам нужно проверить только один раз:
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"
должен печатать только один T.
Если вы хотите делать это регулярно, то вы хотите что-то более эффективное.
Если вы хотите сделать это только один раз, тогда этот клудж может проверить, работает ли ваш обычный стеклоочиститель и можете ли вы доверять ему.
Только для проверки вы увидите все блоки, которые не соответствуют перечисленным
sudo badblocks -sv -t 0x00 /dev/sdX
Или используйте badblocks, чтобы написать их, а также проверить:
sudo badblocks -svw -t 0x00 /dev/sdX
Разрушающий тест по умолчанию - мое безопасное стирание выбора
sudo badblocks -svw /dev/sdX
Если кто-нибудь может извлечь что-либо после заполнения диска чередующимися 0 и 1, то их дополнение, затем все 1, затем все 0, с каждым проверенным проходом, сработавшим, удачи им!
Хорошая проверка перед развертыванием на новых дисках
man badblocks
для других вариантов
Не сказать, что это быстро, но это работает ...
Лучшее из обоих миров. Эта команда пропустит плохие сектора:
sudo dd if=/dev/sdX conv=noerror,sync | od | head
Используйте kill -USR1 <pid of dd>
чтобы увидеть прогресс.
Некоторое время назад мне было интересно узнать об AIO
. Результатом стала тестовая программа, которая проверяет сектора (блоки 512 байт), которые имеют значение NUL
. Вы можете видеть это как вариант детектора разреженных областей файла . Я думаю, что источник говорит все это.
NUL
вывод будет выглядеть как 0000000000-eof
. Обратите внимание, что в программе есть хитрость, функция fin()
не вызывается в строке 107 специально для получения показанного результата.AIO
не так прост, как другие способы,AIO
, вероятно, является самым быстрым способом сохранить занятость чтения диска , потому что сравнение NUL
выполняется во время чтения следующего блока данных. (Мы могли бы выжать еще несколько миллисекунд, сделав AIO
перекрытием, но я действительно не думаю, что это стоит усилий.)true
если файл доступен для чтения и все работает. Он не возвращает false
если файл не NUL
.NUL
он все еще работает, поскольку буферы памяти уже содержат NUL
. Если кто-то считает, что это нужно исправить, в строке 95 memcmp(nullblock, buf+off, SECTOR)
может прочитать memcmp(nullblock, buf+off, len-off<SECTOR : len-off : SECTOR)
. Но единственное отличие состоит в том, что "отчет об окончании", возможно, немного случайный (не для файла, который является полностью NUL
).memcmp()
также исправляет другую проблему на платформах, которые не выделяют NUL
alloc()
память, поскольку код этого не делает. Но это может быть видно только для файлов размером менее 4 МБ, но checknul
вероятно, просто излишне для такой небольшой задачи;)НТН
/* 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;
}