Linux'ta sabit sürücünün sıfırlarla dolu olduğunu nasıl doğrularım?


16

Sıfırlarla dolu sabit diskim var.

Sabit diskteki tüm bitlerin bash kullanarak sıfır olup olmadığını nasıl kontrol edebilirim?


Tüm sürücünün üzerine sıfır yazılması kabul edilebilir mi? Yoksa mevcut içeriği doğrulamanız mı gerekiyor?
Bob

Sabit sürücünün sıfırlarla dolu olduğunu doğrulamak istiyorum.
gkfvbnhjh2

1
Teorik olarak, bazı verileri bozulmadan kaldıran veri temizleme araçlarında hata olabilir. Her bitin sıfır olduğundan emin olmak istemiyorum. Peki hdd'nin sıfırlarla dolu olup olmadığını nasıl kontrol edebilirim?
gkfvbnhjh2

Neden sıfır? Birkaç kez rasgele sıfırlar ve 1'ler yazmaz mısınız?

13
1'ler 0'lardan daha dar olduğu için aralarındaki eski verileri daha kolay görebilirsiniz.
ChrisA

Yanıtlar:


29

odaynı şeyin çalışmalarını yerine koyar *, böylece sıfır olmayan bayt taraması için kolayca kullanabilirsiniz:

$ sudo od /dev/disk2 | head
0000000    000000  000000  000000  000000  000000  000000  000000  000000
*
234250000

8
Bunun | headsonuna, sürücünün sıfırlanmadığı ortaya çıkarsa, tüm sürücüyü ekrana dökmek yerine, gerçeği göstermek için yeterli çıktı ürettikten sonra durur.
Wyzard

2
@Wyzard: Mükemmel fikir; Cevabıma ekleyeceğim.
Gordon Davisson

8

Bunu yapmak için kısa bir C ++ programı yazdım, kaynak burada mevcut .

İnşa etmek için:

wget -O iszero.cpp https://gist.github.com/BobVul/5070989/raw/2aba8075f8ccd7eb72a718be040bb6204f70404a/iszero.cpp
g++ -o iszero iszero.cpp

Çalıştırmak için:

dd if=/dev/sdX 2>/dev/null | ./iszero

Sıfır olmayan baytların konumunu ve değerini çıktılar. Bu çıktıyı aşağıdaki gibi bir dosyaya yönlendirebilirsiniz >:

dd if=/dev/sdX 2>/dev/null | ./iszero >nonzerochars.txt

Daha BUFFER_SIZEiyi verimlilik için değiştirmeyi denemek isteyebilirsiniz . Optimum değerin ne olabileceğinden emin değilim. Bunun ilerlemeyi ne sıklıkta yazdırdığını da etkiler; bu da hızı biraz etkiler (konsola yazdırma çıktısı yavaştır ). Ekle 2>/dev/nullilerleme çıkışı kurtulmak için.

Bunun standart bash ve hatta builtin kullanmadığının farkındayım, ancak ekstra ayrıcalık gerektirmemelidir. @Hennes'ın çözümü hala daha hızlı (Gerçekten hiçbir şeyi optimize etmedim - bu naif çözümdür); ancak, bu küçük program silicinizin kaç bayt kaçırdığını ve hangi konumda olduğunu daha iyi bir fikir verebilir. İlerleme çıkışını devre dışı bırakırsanız, çoğu sabit sürücünün okuyabileceğinden (> 150 MB / sn) daha hızlı olacaktır, bu büyük bir sorun değildir.

Daha az ayrıntılı çıktıya sahip daha hızlı bir sürüm burada mevcuttur . Ancak, hala @Hennes'ın çözümünden biraz daha yavaş. Bununla birlikte, bu, karşılaştığı ilk sıfır olmayan karakterden çıkacaktır, bu nedenle akışın başlangıcına yakın bir sıfır olmayan varsa potansiyel olarak çok daha hızlıdır.


Cevabı daha iyi tutmak için yayına kaynak eklemek:

#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;
}

Bu harika bir cevap, ancak komut dosyasının normal bir komut gibi çalışmasını sağlamanın herhangi bir yolu var mı - böyle bir iszero /dev/sdaşeyle pipetlenmesini gerektirmek yerine iszero < /dev/sda?
Hashim

1
@Hashim Bu, bir süre önce bir ıskarta programı olarak yazılmıştır (bugünlerde en azından C derlemek yerine Python gibi bir betik dilinde yapardım) ... en basit yolu, onu yapma çizgisinde yerde olurdum int main(int argc, char *argv[])sonra ve FILE* file = fopen(argv[1], "r");. Düzgün bir şekilde yapıldığında, argümanın gerçekten var olup olmadığını kontrol etme, başarılı bir şekilde açma kontrolü ( ferrorsonra ek bir kontrol yapın fopen) vb., Ancak bir bırakma programı için çok fazla sorun bulunur.
Bob

1
@Hashim SIMD vektörleştirilmiş işlemlerinin numpy cinsinden vektörlenmiş talimatlara yakın olacağından şüpheleniyorum ve bu da C derleyicisinin saf C programındaki döngüyü vektörleştirecek kadar akıllı olduğu varsayılıyor. Emin olmak için karşılaştırma yapmak zorunda kalacak; ne yazık ki şu anda bunu yapmak için gerçekten zamanım yok. Python (ve ark.) 'In temel avantajı, genellikle bir derleyici olmadan kullanılabilir ve çalıştırılabilirken, gccek paketler çekilmeden tüm Linux dağıtımlarında zorunlu olarak bulunmamasıdır. Sonra tekrar numpy standart Python paketlerinin bir parçası değil ...
Bob

1
@Hashim Derleme yaparsanız -O3ve -march=nativebazı hızlanmalar görebilirsiniz; GCC'nin otomatik vektörleştirmeyi etkinleştirdiğinden ve mevcut CPU'nuz için (AVX, SSE2 / SSE3 vb.) mümkün olan en iyisini kullandığından emin olmalıdır. Bununla birlikte tampon boyutu ile oynayabilirsiniz; farklı tampon boyutları vektörleştirilmiş döngülerle daha uygun olabilir (1MB + ile oynarım, mevcut olan 1kB'dir).
Bob

1
@Hashim Görmediğiniz takdirde yukarıdaki yorum düzenlendi. Bunun ötesinde, daha fazla tartışmak isterseniz, @Bobsohbette bana ( ) ping atabilirsiniz
Bob

7

Gordon'un cevabına pvgenişlemek, süreç boyunca ne kadar uzak olduğunun bir göstergesidir:

$ 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

Bu büyük bir sabit disk için çok kullanışlıdır!
Martin Hansen

5

Bu çirkin verimsiz bir çözüm gibi görünüyor, ancak sadece bir kez kontrol etmeniz gerekiyorsa:

dd if=/dev/sdX | tr --squeeze-repeats "\000" "T"

Diskten okumak için dd kullanma sdX. (okumak için kullanmak istediğiniz sürücü ile X yerine)
Sonra tercüme biz işleyebilir şeye tüm yazdırılamayan sıfır bayt.

Daha sonra, işleyebileceğimiz baytları sayarız ve doğru sayı olup olmadığını kontrol ederiz ( wc -cbunun için kullanın ) veya saymayı atlayıp tüm çoklu oluşumları tek bir karaktere sıkıştırmak için -sveya öğesini --squeeze-repeatskullanırız.

Bu dd if=/dev/sdX | tr --squeeze-repeats "\000" "T"yüzden sadece tek bir T yazdırmalıdır.

Bunu düzenli olarak yapmak istiyorsanız, daha verimli bir şey istersiniz.
Bunu sadece bir kez yapmak istiyorsanız, bu çamur normal silicinizin çalıştığını ve ona güvenebileceğinizi doğrulayabilir.


Bu çözümü neden verimsiz buluyorsunuz? NUL olmayan ilk konumun çok ötesinde okuma gerektiren bazı tamponlama var mı?
Daniel Beck

Buharda tek sıfır karakteri olarak gerçek bir 'T' bulunduğunda potansiyel bir problem var mı?
Bob

Doğru. Bu tasarımdaki bir kusur. Ben de bash (kabuk kendisi) kullanmıyorum, ama "Bash" ile "bash değil, herhangi bir kabuk istemi ve standart metin modu araçları kullanmaktan" demek istediğini varsaydı.
Hennes

3
@daniel: Basit bir C programı, her bayt değiştirilmeden tüm verileri okuyabilmelidir. Hangi daha verimli ve estetik olarak hoş olurdu. Ayrıca böyle bir programı yazmak, sadece mevcut araçları verimsiz bir şekilde kullanmaktan çok daha fazla zaman alabilir.
Hennes

3

Yalnızca kontrol etmek için, listelenmeyen tüm blokları görürsünüz

sudo badblocks -sv -t 0x00 /dev/sdX

Veya bunları yazmak ve kontrol etmek için badblock'ları kullanın:

sudo badblocks -svw -t 0x00 /dev/sdX

Varsayılan yıkıcı test seçimimi güvenli bir şekilde silmem

sudo badblocks -svw /dev/sdX

Herkes sürücüyü 0s ve 1s ile doldurduktan sonra bir şey alabilirse, tamamlayıcıları, sonra tüm 1'ler, daha sonra tüm 0'lar, her geçişle çalıştığını doğruladı, onlara iyi şanslar!

Yeni sürücülerde de iyi bir dağıtım öncesi kontrol yapar

man badblocks

diğer seçenekler için

Hızlı olduğunu söylemiyorum ama işe yarıyor ...


2

Her iki dünyanın en iyisi. Bu komut bozuk sektörleri atlayacaktır:

sudo dd if=/dev/sdX conv=noerror,sync | od | head

kill -USR1 <pid of dd>İlerlemeyi görmek için kullanın .


0

Bir süre önce merak ediyordum AIO. Sonuç, sektörleri (512 bayt blok) kontrol eden örnek bir test programıdır NUL. Bunu seyrek bir dosya bölgesi dedektörünün bir çeşidi olarak görebilirsiniz . Bence kaynak her şeyi söylüyor.

  • Tüm dosya / sürücü NULçıktısı gibi görünür 0000000000-eof. Programda bir hile olduğuna dikkat edin, fin()gösterilen çıktıyı vermek amacıyla fonksiyon 107 satırında çağrılmaz.
  • Çok fazla test edilmediğinden, hatalar içerebilir
  • Kod biraz daha uzundur, AIOçünkü diğer yollar kadar basit değildir,
  • Ancak AIOolan bir tahrik meşgul okumaya devam etmenin en hızlı yolu muhtemelen çünkü, NULbir sonraki veri bloğu okunduğunda ise yapılır karşılaştırın. (Biz örtüşen yaparak birkaç milisaniye sıkmak AIO, ama gerçekten bu değer olduğunu düşünmüyorum çaba.)
  • trueDosya okunabilirse ve her şey işe yaradıysa her zaman geri döner . falseDosya olmayan ise geri dönmez NUL.
  • Dosya boyutunun 512'nin katı olduğunu varsayar. Son sektörde bir hata vardır, ancak dosyada NULbellek arabellekleri zaten içerdiği için tamamen çalışır NUL. Birisi bunun bir düzeltmeye ihtiyacı olduğunu düşünürse, 95. satırda memcmp(nullblock, buf+off, SECTOR)okuyabilir memcmp(nullblock, buf+off, len-off<SECTOR : len-off : SECTOR). Ama tek fark "son raporlama" belki de (değil tamamen bir dosya için raslantısaldır yani, NUL).
  • Değişiklik , kodda yer almadığı için bellekte memcmp()bulunmayan platformlardaki başka bir sorunu da giderir NUL alloc(). Ancak bu sadece 4 MiB'den daha az olan dosyalar tarafından görülebilir, ancak checknulmuhtemelen bu kadar küçük bir görev için aşırı derecede aşırıdır;)

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;
}

0

Bu akıllı çözümü , bir süredir oturum açmamış bir kullanıcı tarafından gönderilen benzer ancak daha önceki bir sorudan göndermek istedi :

/dev/zeroLinux sisteminde okunduğunda daima sıfır veren bir cihaz vardır .

Peki, sabit sürücünüzü bu cihazla karşılaştırmaya ne dersiniz:

cmp /dev/sdX /dev/zero

Sabit diskinizi sıfırlamakla her şey yolundaysa, aşağıdakilerle sona erecektir:

cmp: EOF on /dev/sdb

size iki dosyanın sabit sürücünün sonuna kadar aynı olduğunu söyler. Sabit sürücüde sıfır olmayan bir bit cmpvarsa, dosyanın nerede olduğunu söyler.

Eğer varsa pvpaket daha sonra yüklü:

pv /dev/sdX | cmp /dev/zero

sürücünüzü kontrol ederken sizi eğlendirmek için bir ilerleme çubuğu ile aynı şeyi yapacak (EOF şimdi sdX yerine STDIN'de olacak).

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.