dd
はあまり使用していませんが、今のところまだ失敗していません。現在、dd
を12時間以上行っています-元のディスクにイメージを書き込んでいます-dd
をディスクからイメージに約7時間で送信します。
OSX 10.6.6を実行していて、コア2 Duoと2.1ギガバイト/コア、4ギガバイトのRAMを搭載したMacBookを使用しています。 7200rpmハードドライブ(ブートドライブ)の.dmgから読み取り、SATA-to-USBコネクタを介して接続された7200rpmドライブに書き込みます。私はデフォルトでブロックサイズを残しました、そして画像は約160GBです。
編集:そして、14時間の純粋なストレスの後、dd
は結局完全に機能しました。ただし、次回はpv
を介して実行し、strace
を使用して追跡します。皆様のご協力に感謝いたします。
dd
kill
コマンドを使用して特定の信号を送信し、現在のステータスを出力させることができます。シグナルは、BSDシステム(OSXを含む)ではINFO
であり、USR1
Linuxの場合。あなたの場合:
kill -INFO $PID
プロセスID($PID
上記)ps
コマンドを使用;または、より便利な方法については mac os xのpgrepおよびpkillの代替案 を参照してください。
もっと簡単に言えば、 AntoineG が 彼の答え で指摘しているので、ctrl-T
シェルでddを実行してINFO
シグナルを送信します。
Linuxの例として、次のようにすべてのアクティブなdd
プロセスの出力ステータスを作成できます。
pkill -USR1 -x dd
ステータスを出力した後、dd
は対処を続行します。
OS X(Linuxでは試さなかった)では、単純に次のように入力できます。 Ctrl+T ターミナルでdd
を実行しています。 kill -INFO $PID
と同じ出力と、CPU使用率を出力します。
load: 1.40 cmd: dd 34536 uninterruptible 3.49u 64.58s
5020305+0 records in
5020304+0 records out
2570395648 bytes transferred in 4284.349974 secs (599950 bytes/sec)
私はそれがこのスレッドを読んでいて、私のターミナルで新しいタブを開こうとしましたが、混合していることを知りました ⌘+T と Ctrl+T。
私は通常、そのような実行中のプロセスにstrace
を付けます(-p $PID
オプション)システムコールでブロックされたままであるかどうか、またはまだアクティブであるかどうかを確認します。
または、実行中のddにシグナルを送信することに不安がある場合は、別のddを開始して、これが機能するかどうかを検証します。
次回は、最初からpv
を使用できます(パッケージマネージャーから利用できる場合は、インストールしてください)。これは、入力を出力にパイプし、進行状況と速度を監視することを唯一の目的とするユーティリティです。
次に、イメージをドライブに書き込むために、4MBのブロックサイズを指定します。
pv -ptearb /path/to/image.bin | dd iflag=fullblock of=/dev/whatever bs=4M
最初のバッファリング(必要に応じてdd
を介して実行できる最終同期によってオフセットされる)の他に、これは進行状況バー、平均速度、現在の速度、およびETAを表示します。
iflag=fullblock
オプションを指定すると、ddはpv
を介して入力の完全なブロックを取得します。それ以外の場合は、ブロックサイズのパイプのなすがままです。
逆に移動するには、ddを使用して読み取り、pvを使用して書き込みますが、ソースがブロックデバイスの場合はサイズを明示的に指定する必要があります。 4GBデバイスの場合:
dd if=/dev/whatever bs=4M | pv -ptearb -s 4096m > /path/to/image.bin
次のようなサイズを自動的に決定することもできます。
dd if=/dev/whatever bs=4M | pv -ptearb -s `blockdev --getsize64 /dev/whatever` > /path/to/image.bin
実際にdd
とpv
を実行する順序は関係ありません。それは完全にパフォーマンスに関連しています。読み取りまたは読み取りを行うデバイスが、特定のブロックサイズに対して最適なパフォーマンスを持っている場合そのデバイスにアクセスするには、dd
ではなくpv
を使用してください。必要に応じて、両端にdd
を貼り付けることも、気にしない場合はまったく貼り付けないこともできます。
pv -ptearb /path/to/image.bin > /dev/whatever
sync
coreutils
v8.24以降、dd
は進行状況の表示をネイティブでサポートしています。オプションstatus=progress
を追加するだけです。
例:
dd if=Arch.iso of=/dev/sdb bs=4M status=progress
ddrescue
を実行すると、統計が表示されます。
私はdcfldd(1)の使用を開始しました。これはdd操作をよりわかりやすく示しています。
dd
プロセスのstderrストリームにアクセスできないため(たとえば、それが実行された端末がすでに閉じられているため)、INFOまたはUSR1信号を使用できない場合があります。この場合の回避策は次のことです(FreeBSDでテスト済み、Linuxでは多少異なる場合があります):
iostat
を使用して、ターゲットデバイスへの平均書き込み速度(MB /秒)を推定します。例:
iostat -d -w30 ada0
ここでada0
をターゲットデバイス名に置き換え、それが2、3回結果を出すまで1分待ちます。 「w」パラメーターは、サンプル間の秒数を決定します。値を大きくすると、分散が少なく、より良い平均推定値が得られますが、より長く待つ必要があります。
ps
を使用して、dd
の実行時間を確認します。
ps -xo etime,command | grep dd
これを秒に変換して、ランタイムの合計秒数を取得します。
デバイスサイズをMB単位で取得します。
grep ada0 /var/run/dmesg.boot
ada0
をターゲットデバイス名に置き換えます。結果を平均書き込み速度で割り、合計転送時間を秒単位で取得します。残り時間を取得するには、これまで実行していた時間を差し引きます。
この戦略が機能するのは、dd
が開始されてから現在の平均書き込み速度で継続的に書き込みを行っている場合のみです。他のプロセスがCPUまたはI/Oリソース(I/Oバスを含む)をめぐって競合している場合、転送速度が低下する可能性があります。
progress
を使用できます。これは特に、実行中のdd
の進行状況を示します。それは使用しています /proc/$pid/fd
および/proc/$pid/fdinfo
手動で監視することもできます。
dd
の実行中に、これを別の端末でrootとして実行します。
while pgrep ^dd; do pkill -INFO dd; sleep 1; done
1秒ごとにdd
ステータスを出力します元のターミナルウィンドウ内dd
が実行されており、コマンドが完了すると終了します。
_/proc/$pid/io
_のwchar
行(書き込まれた文字)は、dd
プロセスに関する正確な情報を提供します。変更がある限り、dd
は引き続き機能します。
以下は、きちんとした小さなphpスクリプトです。これを保存し、dd
の実行中に_php filename.php
_で実行して、書き込まれたバイトを表示できます。 kill -USR1 $(pidof dd)
を介して_/proc/$pid/io
_を監視する利点は、端末間を切り替える必要がないことです。これは必ずしもオプションではありません。
_<?php
/** Time between refreshs in seconds */
$refresh = 1;
/**
* Start of Script
*/
if (!($pid = exec('pidof dd')))
exit("no dd running\n");
$history = array();
$break_ms = $refresh * 1000000;
$start_time = exec("ls -ld /proc/$pid --time-style=+\"%s\" | egrep -o [0-9]{10}");
fprintf(STDOUT, "PID: %s\n", $pid);
fprintf(STDOUT, "START TIME: %s\n\n", date("Y-m-d H:i:s", $start_time));
while (true) {
if (isset($curr))
array_Push($history, $curr);
if (count($history) > 10) array_shift($history);
$oldest = reset($history);
$latest = end($history);
/**
* get number of written bytes from /proc/$pid/io
*/
#if (!($curr = exec("cat /proc/$pid/io | grep ^write_bytes | sed 's/write_bytes: //g'")))
# break;
/* prepare proc_open() parameter */
$descriptorspec = array(
0 => array('pipe', 'r'), // stdin
1 => array('pipe', 'w'), // stdout
2 => array('pipe', 'w'), // stderr
);
$process = proc_open("cat /proc/$pid/io | grep ^write_bytes | sed 's/write_bytes: //g'", $descriptorspec, $pipes);
if (!is_resource($process)) break;
$stdout = stream_get_contents($pipes[1]);
$stderr = stream_get_contents($pipes[2]);
proc_close($process);
if (!empty($stderr)) break;
$curr = trim($stdout);
/**
* caculate elapsed time from start */
$time_elapsed = time() - $start_time;
/**
* avg speed since start */
$avg = $time_elapsed > 0 ? round($curr / $time_elapsed) : 0;
/**
* avg speed of last 10 updates */
if (count($history) > 0)
$speed = human_file_size(round(($latest - $oldest) / count($history) / $refresh));
$output = sprintf("\rBYTES WRITTEN: %s [%s] :: CURRENT: %s/s :: AVERAGE: %s/s :: ELAPSED: %s", $curr, human_file_size($curr), isset($speed) ? $speed : 0, human_file_size($avg), gmdate("H:i:s", $time_elapsed));
printf("%s%s", $output, str_repeat(" ", exec("tput cols") - strlen($output)));
usleep($break_ms);
}
fprintf(STDOUT, "\ndd has finished!\n\n");
function human_file_size($size,$unit="") {
if( (!$unit && $size >= 1<<30) || $unit == "GB")
return number_format($size/(1<<30),2)." GB";
if( (!$unit && $size >= 1<<20) || $unit == "MB")
return number_format($size/(1<<20),2)." MB";
if( (!$unit && $size >= 1<<10) || $unit == "kB")
return number_format($size/(1<<10),2)." kB";
return number_format($size)." bytes";
}
_