J'ai un disque dur rempli de zéros.
Comment vérifier si tous les bits du disque dur sont des zéros en utilisant bash?
J'ai un disque dur rempli de zéros.
Comment vérifier si tous les bits du disque dur sont des zéros en utilisant bash?
Réponses:
od
remplacera les exécutions de la même chose *
, vous pouvez donc facilement l'utiliser pour rechercher des octets non nuls:
$ sudo od /dev/disk2 | head
0000000 000000 000000 000000 000000 000000 000000 000000 000000
*
234250000
| head
à la fin de cela, de sorte que s'il s'avère que le lecteur n'est pas mis à zéro, il s'arrête après avoir produit juste assez de sortie pour montrer le fait, au lieu de vider le lecteur entier à l'écran.
J'ai écrit un petit programme C ++ pour le faire, source disponible ici .
Pour le construire:
wget -O iszero.cpp https://gist.github.com/BobVul/5070989/raw/2aba8075f8ccd7eb72a718be040bb6204f70404a/iszero.cpp
g++ -o iszero iszero.cpp
Pour l'exécuter:
dd if=/dev/sdX 2>/dev/null | ./iszero
Il affichera la position et la valeur de tout octet différent de zéro. Vous pouvez rediriger cette sortie vers un fichier avec >
, par exemple:
dd if=/dev/sdX 2>/dev/null | ./iszero >nonzerochars.txt
Vous voudrez peut-être essayer de changer BUFFER_SIZE
pour une meilleure efficacité. Je ne sais pas quelle valeur optimale pourrait être. Notez que cela affecte également la fréquence d'impression de la progression, ce qui affectera quelque peu la vitesse (la sortie d'impression vers la console est lente ). Ajouter 2>/dev/null
pour se débarrasser de la sortie de progression.
Je suis conscient que cela n'utilise pas bash standard, ni même des commandes intégrées, mais cela ne devrait pas nécessiter de privilèges supplémentaires. La solution de @Hennes est encore plus rapide (je n'ai vraiment rien optimisé - c'est la solution naïve); cependant, ce petit programme peut vous donner une meilleure idée du nombre d'octets manquants dans votre essuie-glace et de son emplacement. Si vous désactivez la sortie de progression, elle sera toujours plus rapide que la plupart des disques durs grand public peuvent lire (> 150 Mo / s), ce n'est donc pas un gros problème.
Une version plus rapide avec une sortie moins verbeuse est disponible ici . Cependant, elle est encore un peu plus lente que la solution @Hennes. Celui-ci, cependant, se fermera sur le premier caractère non nul qu'il rencontre, il est donc potentiellement beaucoup plus rapide s'il y a un non nul près du début du flux.
Ajout de la source au message pour garder la réponse mieux autonome:
#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
plutôt qu'en exigeant qu'il soit canalisé avec quelque chose comme iszero < /dev/sda
?
int main(int argc, char *argv[])
et puis FILE* file = fopen(argv[1], "r");
. Fait correctement, il comprendrait la vérification si l'argument existe réellement, la vérification des erreurs réussie (faites une ferror
vérification supplémentaire après le fopen
), etc., mais trop de problèmes pour un programme jetable.
gcc
n'est pas nécessairement disponible sur toutes les distributions Linux sans retirer des packages supplémentaires. Là encore, numpy ne fait pas non plus partie des packages Python standard ...
-O3
et -march=native
vous pourriez voir des accélérations; cela devrait garantir que GCC active la vectorisation automatique et utilise le meilleur disponible pour votre CPU actuel (AVX, SSE2 / SSE3, etc.). Parallèlement à cela, vous pouvez jouer avec la taille du tampon; différentes tailles de mémoire tampon peuvent être plus optimales avec des boucles vectorisées (je jouerais avec 1 Mo +, la valeur actuelle est de 1 Ko).
@Bob
) dans le chat: chat.stackexchange.com/rooms/118/root-access
Élargissant la réponse de Gordon, pv
fournit une indication de la longueur du processus:
$ 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
Cela semble une mauvaise solution inefficace, mais si vous ne devez vérifier qu'une seule fois:
dd if=/dev/sdX | tr --squeeze-repeats "\000" "T"
Utilisation de dd pour lire à partir du disque sdX
. (remplacez le X par le lecteur à partir duquel vous voulez lire),
puis traduisez tous les octets zéro non imprimables en quelque chose que nous pouvons gérer.
Ensuite, soit nous comptons les octets que nous pouvons gérer et vérifions s'il s'agit du bon nombre (à utiliser wc -c
pour cela), soit nous ignorons le comptage et utilisons le -s
ou --squeeze-repeats
pour compresser toutes les occurrences multiples en un seul caractère.
Il dd if=/dev/sdX | tr --squeeze-repeats "\000" "T"
ne faut donc imprimer qu'un seul T.
Si vous voulez le faire régulièrement, vous voulez quelque chose de plus efficace.
Si vous ne voulez faire cela qu'une seule fois, alors ce kludge peut vérifier que votre essuie-glace normal fonctionne et que vous pouvez lui faire confiance.
Pour vérifier uniquement, vous verrez tous les blocs qui ne correspondent pas répertoriés
sudo badblocks -sv -t 0x00 /dev/sdX
Ou utilisez des badblocks pour les écrire ainsi que pour vérifier:
sudo badblocks -svw -t 0x00 /dev/sdX
Le test destructif par défaut est mon effacement sécurisé de choix
sudo badblocks -svw /dev/sdX
Si quelqu'un peut récupérer quoi que ce soit après avoir rempli le lecteur avec une alternance de 0 et de 1, alors leur complément, puis tous les 1, puis tous les 0, avec chaque passe vérifiée, cela a fonctionné, bonne chance à eux!
Effectue également une bonne vérification de pré-déploiement sur les nouveaux disques
man badblocks
pour d'autres options
Je ne dis pas que c'est rapide, mais ça marche ...
Le meilleur des deux mondes. Cette commande sautera les secteurs défectueux:
sudo dd if=/dev/sdX conv=noerror,sync | od | head
Utilisez kill -USR1 <pid of dd>
pour voir les progrès.
Il y a quelque temps, j'étais curieux de savoir AIO
. Le résultat a été un exemple de programme de test qui vérifie les secteurs (blocs de 512 octets) qui le sont NUL
. Vous pouvez voir cela comme une variante d'un détecteur de régions de fichiers épars . Je pense que la source dit tout.
NUL
sortie, cela ressemble 0000000000-eof
. Notez qu'il y a une astuce dans le programme, fonctionfin()
n'est pas appelée à la ligne 107 pour donner la sortie affichée.AIO
n'est pas aussi simple que d'autres façons,AIO
c'est probablement le moyen le plus rapide de garder un lecteur occupé à lire , car la NUL
comparaison est effectuée pendant la lecture du bloc de données suivant. (Nous pourrions extraire quelques millisecondes supplémentaires en faisant un chevauchementAIO
, mais je ne pense vraiment pas que cela vaut la effort.)true
si le fichier est lisible et que tout a fonctionné. Il ne revient pasfalse
si le fichier est non NUL
.NUL
il fonctionne toujours, car les tampons de mémoire contiennent déjà NUL
. Si quelqu'un pense que cela a besoin d'un correctif, à la ligne 95, le memcmp(nullblock, buf+off, SECTOR)
pourrait lirememcmp(nullblock, buf+off, len-off<SECTOR : len-off : SECTOR)
. Mais la seule différence est que le "rapport final" est peut-être un peu aléatoire (pas pour un fichier qui l'est entièrement NUL
).memcmp()
corrige également un autre problème sur les plates-formes, qui ne NUL
alloc()
réduisent pas la mémoire, car le code ne le fait pas. Mais cela ne peut être vu que par des fichiers de moins de 4 Mo, mais c'est checknul
probablement une surpuissance pour une si petite tâche;)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;
}
Je voulais publier cette solution intelligente à partir d'une question similaire mais antérieure, publiée par un utilisateur qui ne s'est pas connecté depuis un certain temps:
Il y a un appareil
/dev/zero
sur un système Linux qui donne toujours des zéros lors de la lecture.Alors, que diriez-vous de comparer votre disque dur avec cet appareil:
cmp /dev/sdX /dev/zero
Si tout va bien avec la remise à zéro de votre disque dur, cela se terminera par:
cmp: EOF on /dev/sdb
vous indiquant que les deux fichiers sont les mêmes jusqu'à ce qu'ils arrivent à la fin du disque dur. S'il y a un bit différent de zéro sur le disque dur
cmp
il vous indiquera où il se trouve dans le fichier.Si le
pv
package est installé, alors:pv /dev/sdX | cmp /dev/zero
fera la même chose avec une barre de progression pour vous amuser pendant qu'il vérifie votre lecteur (le EOF sera désormais sur STDIN plutôt que sur sdX).