Mam dysk twardy wypełniony zerami.
Jak sprawdzić, czy wszystkie bity na dysku twardym są zerami przy użyciu bash?
Mam dysk twardy wypełniony zerami.
Jak sprawdzić, czy wszystkie bity na dysku twardym są zerami przy użyciu bash?
Odpowiedzi:
od
zastąpi przebiegi tej samej rzeczy *
, dzięki czemu można łatwo użyć go do skanowania w poszukiwaniu niezerowych bajtów:
$ sudo od /dev/disk2 | head
0000000 000000 000000 000000 000000 000000 000000 000000 000000
*
234250000
| head
do tego koniec, aby jeśli okaże się, że dysk nie jest wyzerowany, zatrzymuje się po wygenerowaniu wystarczającej ilości danych wyjściowych, aby pokazać ten fakt, zamiast zrzucić cały dysk na ekran.
Napisałem do tego krótki program w C ++, źródło dostępne tutaj .
Aby zbudować:
wget -O iszero.cpp https://gist.github.com/BobVul/5070989/raw/2aba8075f8ccd7eb72a718be040bb6204f70404a/iszero.cpp
g++ -o iszero iszero.cpp
Aby uruchomić:
dd if=/dev/sdX 2>/dev/null | ./iszero
Wyświetli pozycję i wartość niezerowych bajtów. Możesz przekierować to wyjście do pliku za pomocą >
np .:
dd if=/dev/sdX 2>/dev/null | ./iszero >nonzerochars.txt
Możesz spróbować zmienić w BUFFER_SIZE
celu zwiększenia wydajności. Nie jestem pewien, jaka może być optymalna wartość. Pamiętaj, że wpływa to również na częstotliwość drukowania postępu, co nieco wpłynie na prędkość (drukowanie na konsoli jest wolne ). Dodaj, 2>/dev/null
aby pozbyć się postępu produkcji.
Wiem, że nie używa to standardowej wersji bash ani nawet poleceń wbudowanych, ale nie powinno to wymagać żadnych dodatkowych uprawnień. Rozwiązanie @Hennes jest jeszcze szybsze (tak naprawdę niczego nie zoptymalizowałem - jest to naiwne rozwiązanie); jednak ten mały program może dać ci lepsze pojęcie o tym, ile bajtów pominął wycieracz i w jakiej lokalizacji. Jeśli wyłączysz wyjście postępu, będzie ono nadal szybsze niż większość dysków twardych dla konsumentów może odczytać (> 150 MB / s), więc nie jest to duży problem.
Szybsza wersja z mniej szczegółowym wyjściem jest dostępna tutaj . Jednak nadal jest nieco wolniejszy niż rozwiązanie @Hennes. Ten jednak zakończy pracę z pierwszą napotkaną niezerową postacią, więc jest potencjalnie znacznie szybszy, jeśli w pobliżu strumienia znajduje się niezerowa postać.
Dodanie źródła do posta, aby zachować odpowiedź, bardziej niezależną:
#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
raczej niż wymagającego potoku z czymś takim iszero < /dev/sda
?
int main(int argc, char *argv[])
i wtedy FILE* file = fopen(argv[1], "r");
. Prawidłowo wykonane, obejmowałoby sprawdzenie, czy argument rzeczywiście istnieje, sprawdzenie błędu powiodło się otwarcie (wykonaj dodatkowe ferror
sprawdzenie po fopen
), itp., Ale zbyt wiele problemów dla programu do wyrzucania.
gcc
niekoniecznie jest dostępny we wszystkich dystrybucjach Linuksa bez pobierania dodatkowych pakietów. Z drugiej strony numpy nie jest częścią standardowych pakietów Pythona ...
-O3
i -march=native
możesz zauważyć pewne przyspieszenia; to powinno upewnić się, że GCC włącza automatyczną wektoryzację i używa najlepszego dostępnego dla twojego procesora (AVX, SSE2 / SSE3 itp.). Oprócz tego możesz grać z wielkością bufora; różne rozmiary buforów mogą być bardziej optymalne z wektoryzowanymi pętlami (grałbym z 1 MB +, obecnie jeden to 1kB).
@Bob
) na czacie: chat.stackexchange.com/rooms/118/root-access
Rozszerzenie odpowiedzi Gordona pv
wskazuje, jak daleko jest ten proces:
$ 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
To wydaje się brzydkie nieefektywne rozwiązanie, ale jeśli musisz sprawdzić tylko raz:
dd if=/dev/sdX | tr --squeeze-repeats "\000" "T"
Używanie dd do odczytu z dysku sdX
. (zamień X na dysk, z którego chcesz czytać), a
następnie tłumacz wszystkie niedrukowalne bajty zerowe na coś, co możemy obsłużyć.
Następnie albo zliczamy bajty, które możemy obsłużyć i sprawdzamy, czy jest to poprawna liczba (użyj wc -c
do tego), albo pomijamy liczenie i używamy -s
lub, --squeeze-repeats
aby wycisnąć wszystkie wielokrotne wystąpienia do jednego znaku.
Dlatego dd if=/dev/sdX | tr --squeeze-repeats "\000" "T"
powinien wydrukować tylko jeden T.
Jeśli chcesz to robić regularnie, potrzebujesz czegoś bardziej wydajnego.
Jeśli chcesz to zrobić tylko raz, ta kludge może sprawdzić, czy normalna wycieraczka działa i czy możesz jej zaufać.
Aby to sprawdzić, zobaczysz na liście wszystkie bloki, które nie pasują
sudo badblocks -sv -t 0x00 /dev/sdX
Lub użyj złych bloków, aby je napisać i sprawdzić:
sudo badblocks -svw -t 0x00 /dev/sdX
Domyślnym testem destrucive jest moje bezpieczne usunięcie
sudo badblocks -svw /dev/sdX
Jeśli ktokolwiek może coś odzyskać po zapełnieniu dysku naprzemiennymi zerami i jedynkami, to ich dopełnienie, następnie wszystkie jedynki, a następnie wszystkie zera, przy każdym sprawdzeniu, czy zadziałało, powodzenia!
Sprawdza również przed instalacją nowe dyski
man badblocks
dla innych opcji
Nie mówię, że jest szybki, ale działa ...
Najlepsze z obu światów. To polecenie pominie złe sektory:
sudo dd if=/dev/sdX conv=noerror,sync | od | head
Użyj, kill -USR1 <pid of dd>
aby zobaczyć postęp.
Jakiś czas temu byłem ciekawy AIO
. Rezultatem był przykładowy program testowy, który sprawdza, czy istnieją sektory (bloki 512 bajtów) NUL
. Możesz to zobaczyć jako wariant rzadkiego detektora obszarów plików . Myślę, że źródło mówi wszystko.
NUL
wyprowadzany, wygląda to tak 0000000000-eof
. Zauważ, że w programie jest sztuczka, funkcja fin()
nie jest wywoływana w linii 107 celowo, aby dać pokazane wyjście.AIO
nie jest tak prosty jak inne sposoby,AIO
jest to jednak prawdopodobnie najszybszy sposób na utrzymanie zajętości dysku , ponieważ NUL
porównywanie odbywa się podczas wczytywania następnego bloku danych. (Możemy nakładać kilka milisekund przez nakładanie się AIO
, ale naprawdę nie sądzę, że jest to warte wysiłek.)true
jeśli plik jest czytelny i wszystko działało. Nie zwraca, false
jeśli plik nie jest NUL
.NUL
nadal działa, ponieważ bufory pamięci już zawierają NUL
. Jeśli ktoś myśli, że to wymaga naprawy, w wierszu 95 memcmp(nullblock, buf+off, SECTOR)
można przeczytać memcmp(nullblock, buf+off, len-off<SECTOR : len-off : SECTOR)
. Ale jedyną różnicą jest to, że „raportowanie końcowe” może być nieco losowe (nie dotyczy pliku, który jest całkowicie NUL
).memcmp()
rozwiązuje również inny problem na platformach, które nie NUL
alloc()
edują pamięci, ponieważ kod tego nie robi. Ale może to być widoczne tylko w plikach mniejszych niż 4 MiB, ale checknul
prawdopodobnie jest to zwykła przesada w przypadku tak małego zadania;)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;
}
Chciałem opublikować to sprytne rozwiązanie z podobnego, ale wcześniejszego pytania zadanego przez użytkownika, który nie logował się przez pewien czas:
W
/dev/zero
systemie Linux jest urządzenie , które zawsze odczytuje zera podczas odczytu.A co powiesz na porównanie dysku twardego z tym urządzeniem:
cmp /dev/sdX /dev/zero
Jeśli wszystko jest w porządku z zerowaniem dysku twardego, zakończy się on:
cmp: EOF on /dev/sdb
mówiąc, że dwa pliki są takie same, dopóki nie dotarł do końca dysku twardego. Jeśli na dysku twardym jest niezerowy bit
cmp
, powie Ci, gdzie jest w pliku.Jeśli masz
pv
zainstalowany pakiet, to:pv /dev/sdX | cmp /dev/zero
zrobi to samo z paskiem postępu, abyś był rozbawiony podczas sprawdzania dysku (EOF będzie teraz na STDIN, a nie na sdX).