私はゼロでいっぱいのハードドライブを持っています。
ハードドライブのすべてのビットがbashを使用してゼロであるかどうかを確認するにはどうすればよいですか?
od
は、同じものの実行を*
で置き換えます。そのため、これを使用してゼロ以外のバイトをスキャンすることが簡単にできます。
$ Sudo od /dev/disk2 | head
0000000 000000 000000 000000 000000 000000 000000 000000 000000
*
234250000
私はそうするために短い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
ゼロ以外のバイトの位置と値を出力します。この出力を>
のファイルにリダイレクトできます。例:
dd if=/dev/sdX 2>/dev/null | ./iszero >nonzerochars.txt
効率を上げるために、BUFFER_SIZE
を変更してみてください。最適な値が何かはわかりません。これは、進行状況を印刷する頻度にも影響し、速度に多少影響することに注意してください(コンソールへの出力の印刷はslowです)。 2>/dev/null
を追加して、進行状況の出力を削除します。
これは標準のbashも組み込みも使用していないことを認識していますが、追加の特権は必要ありません。 @Hennesのソリューションはさらに高速です(私は実際には何も最適化していません-これはナイーブなソリューションです)。ただし、この小さなプログラムを使用すると、ワイパーが何バイトを逃したか、どの場所にあるかをより正確に把握できます。進行状況の出力を無効にしても、ほとんどの消費者向けハードドライブが読み取ることができる速度(> 150 MB/s)よりも高速であるため、大きな問題にはなりません。
冗長な出力が少ない高速バージョンが利用可能です ここ 。ただし、それでも@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"
は1つのTのみを出力する必要があります。
これを定期的に行う場合は、より効率的な方法が必要です。
これを1度だけ実行したい場合、このクラッジは通常のワイパーが機能していて、信頼できることを確認する場合があります。
確認するために、リストに一致しないブロックが表示されます
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
に興味がありました。結果は、NUL
であるセクター(512バイトブロック)をたまたまチェックするサンプルテストプログラムでした。これは、スパースファイル領域検出器のバリアントとして見ることができます。 source がすべてを語っていると思います。
NUL
の場合、出力は_0000000000-eof
_のようになります。プログラムにはトリックがあることに注意してください。示されている出力を提供するために、107行目で関数fin()
が呼び出されていません。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()
edしません。しかし、これは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;
}
_
これを投稿したかった 賢い解決策 似ているが以前の質問から、しばらくログインしていない ユーザー によって投稿されました:
デバイスがあります
/dev/zero
読み取り時に常にゼロを与えるLinuxシステム。それでは、ハードドライブをこのデバイスと比較してみてはどうでしょうか。
cmp /dev/sdX /dev/zero
ハードドライブをゼロにすることですべてがうまくいけば、それは次のように終了します:
cmp: EOF on /dev/sdb
ハードドライブの最後に到達するまで、2つのファイルは同じであることを伝えます。ハードドライブにゼロ以外のビットがある場合、
cmp
はそれがファイルのどこにあるかを通知します。
pv
パッケージがインストールされている場合は、次のようにします。pv /dev/sdX | cmp /dev/zero
ドライブをチェックしている間、プログレスバーで同じことを行い、面白がっておくことができます(EOFはsdXではなくSTDINになります)。