Linux에서 하드 드라이브가 0으로 채워져 있는지 확인하는 방법


16

하드 드라이브에 0이 채워져 있습니다.

bash를 사용하여 하드 드라이브의 모든 비트가 0인지 확인하는 방법은 무엇입니까?


전체 드라이브를 0으로 덮어 쓰는 것이 허용됩니까? 아니면 실제로 현재 내용을 확인해야합니까?
Bob

하드 드라이브가 0으로 채워져 있는지 확인하고 싶습니다.
gkfvbnhjh2

1
이론적으로 일부 데이터를 그대로 두는 데이터 삭제 도구에 버그가있을 수 있습니다. 모든 비트가 0인지 확인하고 싶지 않습니다. 그렇다면 hdd가 0으로 가득 차 있는지 어떻게 확인합니까?
gkfvbnhjh2

왜 제로? 무작위로 0과 1을 여러 번 쓰지 않겠습니까?

13
1은 0보다 좁기 때문에 오래된 데이터를 더 쉽게 볼 수 있습니다.
ChrisA

답변:


29

od같은 실행을로 대체 *하므로 0을 사용하지 않는 바이트를 쉽게 스캔 할 수 있습니다.

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

8
내가 추가 거라고 | head는 드라이브가 제로 불가능한 것으로 판명되는 경우,이 사실을 보여주기 위해 충분한 출력을 생성, 대신 화면 전체 드라이브를 덤프 후 중지 그래서, 그 끝에.
Wyzard 2014 년

2
@Wyzard : 훌륭한 아이디어; 내 답변에 추가하겠습니다.
Gordon Davisson

8

그렇게하기 위해 짧은 C ++ 프로그램을 작성했습니다 . 소스는 here .

그것을 구축하려면 :

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

그것을 실행하려면 :

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

0이 아닌 바이트의 위치와 값을 출력합니다. 다음을 사용하여이 출력을 파일로 리디렉션 할 수 있습니다 >.

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

BUFFER_SIZE더 나은 효율성 을 위해 변경을 시도 할 수 있습니다 . 최적의 값이 무엇인지 잘 모르겠습니다. 이것은 또한 진행률을 인쇄하는 빈도에 영향을 미치며 속도에 다소 영향을 미칩니다 (콘솔에 출력하는 속도가 느림 ). 2>/dev/null진행률 출력을 제거하려면 추가하십시오 .

나는 이것이 표준 bash 또는 내장을 사용하지 않는다는 것을 알고 있지만 추가 권한이 필요하지 않습니다. @Hennes의 솔루션은 여전히 ​​더 빠릅니다 (실제로 아무것도 최적화하지 않았습니다-이것은 순진한 솔루션입니다). 그러나이 작은 프로그램은 와이퍼가 몇 바이트를 놓쳤는 지, 어떤 위치에서 더 나은 아이디어를 제공 할 수 있습니다. 진행률 출력을 비활성화하면 여전히 대부분의 소비자 용 하드 드라이브가 읽을 수있는 것보다 빠릅니다 (> 150MB / s). 그리 큰 문제는 아닙니다.

보다 자세한 출력이 적은 더 빠른 버전이 여기에 있습니다 . 그러나 여전히 @Hennes '솔루션보다 약간 느립니다. 그러나 이것은 0이 아닌 첫 번째 문자에서 종료되므로 스트림의 시작 부분 근처에 0이 아닌 문자가 있으면 잠재적으로 훨씬 빠릅니다.


더 나은 독립성을 유지하기 위해 게시 할 소스 추가 :

#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를 파이프로 연결하는 대신 스크립트를 일반 명령처럼 작동시키는 방법이 iszero < /dev/sda있습니까?
Hashim

1
@Hashim 이것은 꽤 오래 전의 끔찍한 프로그램으로 작성되었습니다 (지금은 적어도 컴파일 된 C가 아닌 Python과 같은 스크립팅 언어로 수행했습니다) ... 가장 간단한 방법, 그것을 만드는 라인을 따라 어딘가에있을 거라고 int main(int argc, char *argv[])다음과 FILE* file = fopen(argv[1], "r");. 인수가 실제로 존재하는지 점검하고, 성공적으로 열린 오류 점검 (. 다음에 추가 ferror점검을 수행하는 fopen등) 등 은 올바르게 수행 하지만, 버리기 프로그램에는 너무 많은 문제가 있습니다.
Bob

1
@Hashim 나는 numpy에서 SIMD 벡터화 된 연산이 C의 벡터화 된 명령에 가깝다고 생각합니다. 그리고 C 컴파일러가 순진한 C 프로그램의 루프를 벡터화 할만 큼 똑똑하다고 가정합니다. 확실하게 벤치마킹해야 할 것이다. 불행히도 나는 지금 그렇게 할 시간이 없습니다. 파이썬 (et al.)의 주요 장점은 일반적으로 컴파일러없이 사용 가능하고 실행할 수 있다는 점이며, gcc추가 패키지를 풀지 않고 모든 Linux 배포판에서 반드시 사용할 수 있는 것은 아닙니다. numpy도 표준 파이썬 패키지의 일부가 아닙니다.
Bob

1
당신이 컴파일하는 경우 @Hashim -O3-march=native일부 속도 향상을 볼 수 있습니다; 이를 통해 GCC가 자동 벡터화를 활성화하고 현재 CPU (AVX, SSE2 / SSE3 등)에 가장 적합한 것을 사용해야합니다. 그와 함께 버퍼 크기로 재생할 수 있습니다. 다른 버퍼 크기는 벡터화 루프에서 더 최적 일 수 있습니다 (1MB 이상으로 재생, 현재는 1kB 임).
Bob

1
@Hashim 위의 댓글은 보지 못했을 경우 수정되었습니다. 당신은 더 논의하려는 경우 그건 그렇고, 당신은 저 (Ping 할 수 있습니다 @Bob) 채팅을 : chat.stackexchange.com/rooms/118/root-access

7

Gordon의 답변을 확장 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

이것은 큰 하드 드라이브에 매우 유용합니다!
Martin Hansen

5

이것은 못생긴 비효율적 인 솔루션으로 보이지만 한 번만 확인 해야하는 경우 :

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

dd를 사용하여 디스크에서 읽습니다 sdX. (X를 읽으려는 드라이브로 바꾸십시오)
그런 다음 인쇄 할 수없는 모든 0 바이트를 처리 할 수있는 것으로 변환 하십시오.

우리는 하나 계산 다음으로는 우리가 처리하고 그것이 바로 수 (사용 있는지 확인 할 수 바이트 wc -c그 경우), 또는 우리가 계산을 건너 뛰고을 사용 -s하거나 --squeeze-repeats하나의 문자에 모든 여러 번 짜내.

따라서 dd if=/dev/sdX | tr --squeeze-repeats "\000" "T"단일 T 만 인쇄해야합니다.

이 작업을 정기적으로 수행하려면보다 효율적인 것을 원하십시오.
이 작업을 한 번만 수행하려면이 kludge가 정상적인 와이퍼가 작동하고 있으며 신뢰할 수 있는지 확인할 수 있습니다.


왜이 솔루션이 비효율적이라고 생각합니까? NUL이 아닌 첫 번째 위치를지나 쳐야하는 버퍼링이 있습니까?
Daniel Beck

스팀에 리터럴 'T'가 유일하지 않은 문자로 존재하는 잠재적 인 문제가 있습니까?
Bob

진실. 그것은 디자인의 결함입니다. 나는 또한 bash (쉘 자체)를 사용하지 않지만 "Bash"를 사용하면 "bash 프롬프트가 아니라 셸 프롬프트 및 표준 텍스트 모드 도구를 사용하는 것"을 의미한다고 가정했습니다.
Hennes

3
@daniel : 간단한 C 프로그램은 모든 읽기 바이트를 변경하지 않고 모든 데이터를 읽을 수 있어야합니다. 더 효율적이고 심미적으로 좋을 것입니다. 비효율적 인 방법으로 사용 가능한 도구를 사용하는 것보다 이러한 프로그램을 작성하는 데 훨씬 더 많은 시간이 걸릴 수 있습니다.
Hennes

3

확인하기 만하면 일치하지 않는 블록이 나열됩니다.

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

또는 불량 블록을 사용하여 작성하고 확인하십시오.

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

기본 파괴 테스트는 안전한 보안 선택입니다.

sudo badblocks -svw /dev/sdX

드라이브를 번갈아 가며 0과 1로 채우고 나서 모든 것을 검색 할 수 있다면, 그들의 보완, 모든 1, 모든 0, 모든 패스가 작동했는지 확인하십시오. 행운을 빕니다!

새 드라이브에서도 배포 전 검사를 잘 수행합니다.

man badblocks

다른 옵션

빠르지 만 작동하지만 ...


2

두 세계의 최고. 이 명령은 불량 섹터를 건너 뜁니다.

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

kill -USR1 <pid of dd>진행 상황을 보는 데 사용 합니다.


0

얼마 전에 나는 궁금했다 AIO. 결과는 다음과 같은 섹터 (512 바이트 블록)를 검사하는 샘플 테스트 프로그램이었습니다 NUL. 이것을 희소 파일 영역 검출기 의 변형으로 볼 수 있습니다 . 나는 소스 가 모든 것을 말한다고 생각합니다 .

  • 전체 파일 / 드라이브가 NUL출력 되면 다음과 같습니다 0000000000-eof. 프로그램에는 트릭이 있으며 fin(), 표시된 출력을 제공하기 위해 107 행에서 함수 가 호출되지 않습니다.
  • 많이 테스트되지 않았으므로 버그가 포함될 수 있습니다.
  • 코드는 AIO다른 방법만큼 간단하지 않기 때문에 조금 더 길지만
  • 그러나 AIO입니다 드라이브 바쁜 독서를 유지하는 가장 빠른 방법은 아마도 (가) 때문에, NUL다음 데이터 블록을 읽을 동안 이루어집니다 비교한다. (우리는 중복 수행하여 몇 밀리 초를 짜내 수 있습니다 AIO,하지만 난 정말이 가치라고 생각하지 않습니다 노력.)
  • true파일을 읽을 수 있고 모든 것이 작동하면 항상 반환 합니다. false파일이 아닌 경우에는 반환되지 않습니다 NUL.
  • 파일 크기가 512의 배수라고 가정합니다. 마지막 섹터에 버그가 있지만 NUL메모리 버퍼에 이미 포함되어 있기 때문에 파일에 대해서는 여전히 작동합니다 NUL. 누군가가 이것이 수정이 필요하다고 생각하면 95 번째 줄에서 memcmp(nullblock, buf+off, SECTOR)읽을 수 memcmp(nullblock, buf+off, len-off<SECTOR : len-off : SECTOR)있습니다. 그러나 유일한 차이점은 "최종보고"는 약간 무작위적일 수 있습니다 (전적으로 파일이 아닌 경우 NUL).
  • 변경 memcmp()사항 NUL alloc()은 코드가 수행하지 않기 때문에 메모리가 부족한 플랫폼의 다른 문제도 해결 합니다. 그러나 이것은 4 MiB 미만의 파일에서만 볼 수 있지만 checknul아마도 그러한 작은 작업에는 과잉 일 것입니다.)

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

한동안 로그인하지 않은 사용자가 게시 한 유사하지만 이전의 질문 에서이 영리한 솔루션 을 게시하고 싶었습니다 .

/dev/zeroLinux 시스템에는 읽을 때 항상 0을 제공 하는 장치가 있습니다 .

따라서 하드 드라이브와이 장치를 비교하는 방법은 다음과 같습니다.

cmp /dev/sdX /dev/zero

모든 것이 하드 드라이브의 제로 아웃에 성공하면 다음과 같이 종료됩니다.

cmp: EOF on /dev/sdb

하드 드라이브의 끝까지 두 파일이 동일하다는 것을 알려줍니다. 하드 드라이브에 0이 아닌 비트가 있으면 cmp파일의 어디에 있는지 알려줍니다.

당신이있는 경우 pv패키지는 설치 :

pv /dev/sdX | cmp /dev/zero

드라이브를 확인하는 동안 즐겁게 진행하기 위해 진행률 표시 줄과 동일한 작업을 수행합니다 (EOF는 이제 sdX가 아닌 STDIN에 있습니다).

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.