ddがまだ機能しているかどうかを確認するにはどうすればよいですか?


147

私はddそれほど多く使用していませんが、これまでのところ、私はまだ失敗していません。今、私はdd12時間以上行ってきました-私は元のディスクに画像を書き戻しています-そして、私はddディスクから画像に約できたので、少し心配しています7時間。

OSX 10.6.6を、Core 2 Duoを搭載したMacBookで、4 GB RAMを搭載した2.1 GHz /コアで実行しています。7200rpmのハードドライブ(ブートドライブ)の.dmgから読み取り、SATA-to-USBコネクタで接続された7200rpmのドライブに書き込みます。デフォルトではブロックサイズのままにしており、画像は約160GBです。

編集:そして、14時間の純粋なストレスのdd後、結局完璧に働きました。ただし、次回は、実行してpv、で追跡しstraceます。皆様のご協力に感謝します。


7
あなたの質問には答えませんが、あなたの時代は非常に高いIMOです。デフォルトの512バイト以外の大きなブロックサイズをddに渡すことを覚えていますか?dd ... bs=16MあなたのRAM、ディスクサイズと速度を考えると、私の提案です。
ジュリアーノ

ただ、安全にプレイしたかったからです。ただし、次回はそれを試してみます。ありがとう。
-eckza

私の経験ではdd、Mac OS Xでは、プロセスを強制終了することもできないが、システムを再起動する必要があるまでフリーズする傾向があります。そのときは、Linux VMで作業することに頼ります。
ssc 14年

回答:


173

コマンドをdd使用して特定の信号を送信し、kill現在のステータスを出力させることができます。信号はINFO、BSDシステム(OSXを含む)およびUSR1Linux上にあります。あなたの場合:

kill -INFO $PID

コマンドでプロセスID($PID上記)を見つけることができますps。または、より便利な方法については、mac os xpgrepおよびpkillの代替を参照してください。

もっと簡単に言えば、AntoineGが答えで指摘しているようにctrl-T ddを実行しているシェルで入力してINFOシグナルを送信できます。

Linuxの例として、すべてのアクティブddプロセスに次のようなステータスを出力させることができます。

pkill -USR1 -x dd

ステータスを出力した後、dd対処を続けます。


9
ああ、とてもクール。これらと組み合わせることができますpkill -USR1 -x dd
マイケルMrozek

9
@kivetros:BSDシステムでは、INFOシグナルを送信する必要があります。LinuxにはSIGINFOがUSR1なく、代わりに使用します。
ジル

5
SIGUSRxシグナルは、標準化された意味を持つのではなく、プログラムが望むことを行うためのものです。たとえば、SIGWINCHは、端末のサイズが変更され、プログラムが画面を再描画する必要がある場合に発生します。オペレーティングシステムはSIGUSRxを送信しないため、カスタムで使用できます。
ローレンス

11
USR1シグナルを開始してからすぐに(つまり、bashスクリプトでは、開始した後の行に)ddを送信すると、実際に終了します。間に0.1秒のスリープを設定すると、進行状況が適切に出力されます。ところで、USR1 / INFOをテストする非常に良いddコマンドはdd if=/dev/zero of=/dev/nullです。:)
ラウリッツV.ソーロウ

11
ところで、ステータス文字(デフォルトではCtrl + T)が端末に送信されると、すべての「真の」BSDはフォアグラウンドプロセスグループにSIGINFOを送信します。しかし、MacOSXに当てはまるかどうかはわかりません。
Netch

100

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)

私はこのスレッドを読んで、私の端末で新しいタブを開こうとしているが、+ TCtrl+を混ぜていることを知りましたT


1
ああ、それではloadCPU使用率はどうですか?
pje 14

これは非常に優れたソリューションでした!
-Stephn_R

Linuxのddで試しました^Tが、端末にエコーするだけです。
mwfearnley

1
Mac端末でctrl + shift + Tを実行していることを確認してください
-JBaczuk

26

のためにdd、あなたは信号送ることができます。ファイルを読み書きする他のコマンドについては、を使用してファイル内のコマンドの位置を監視できますlsof

lsof -o -p1234    # where 1234 is the process ID of the command
lsof -o /path/to/file

事前に計画している場合は、データをにパイプしますpv


1
pvは素晴らしく見えます。次回は間違いなく使用します。どうもありがとうございます。
-eckza

1
+1- pvチケットのように見えます。
boehj

17

より一般的な方法は、iotopプログラムごとの読み取り/書き込みディスクの現在の量を表示することです。

編集:iotop -o現在I / O操作を実行するプログラムのみを表示します(このコメントについてはJason Cに感謝します)。


1
これも私の好みのクイックチェック方法です。iotop -oIOを実行していないプロセスを非表示にし、何が起こっているかを一目でわかりやすくします。
ジェイソンC 14年

13

通常strace、このような実行中のプロセスに(-p $PIDオプションを付けて)接続し、システムコールでブロックされたままであるか、まだアクティブであるかを確認します。

または、実行中のddに信号を送信することに不安がある場合は、別のddを起動して、これが機能するかどうかを検証します。


2
正確にどのように取り付けstraceますか?また、私は別のものddを開始し、提案された信号の1つをそれに送信しました...そしてそれはそれを殺しました。
eckza

2
実行中のddプロセスのpidがわかっている場合は、strace -p <pid>を実行します。プロセスによって呼び出されるすべてのシステムコールのログが表示されるはずです(主に読み取りと書き込み)
philfr

11

次回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

実際にどの順序で実行しddpvも、パフォーマンスに完全に関連しています。読み取りまたは読み取りを行うデバイスが、そのデバイスにアクセスするdd代わりに使用したい特定のブロックサイズに対して最適なパフォーマンスを持っている場合pvdd必要に応じて両端に貼り付けることも、気にしない場合はまったく貼り付けないこともできます。

pv -ptearb /path/to/image.bin > /dev/whatever
sync

10

coreutilsv8.24 現在、dd進行状況を表示するためのネイティブサポートがあります。オプションを追加するだけstatus=progressです。

例:

dd if=arch.iso of=/dev/sdb bs=4M status=progress

ソース



4

ddプロセスのstderrストリームにアクセスできないため(たとえば、実行された端末が既に閉じられているため)、INFOまたはUSR1シグナルを使用できない場合があります。この場合、回避策は以下を実行することです(FreeBSDでテスト済み、Linuxでは若干異なる場合があります)。

  1. iostatターゲットデバイスへの平均書き込み速度(MB / s)を推定するために使用します。例:

    iostat -d -w30 ada0

    ada0ここでターゲットデバイス名を置き換えて、2、3の結果が得られるまで1分間待ちます。「w」パラメータは、サンプル間の秒数を決定します。値を大きくすると、より少ない分散でより良い平均推定値が得られますが、もっと長く待つ必要があります。

  2. を使用psddて実行時間を決定します。

    ps -xo etime,command | grep dd

    これを秒に変換して、ランタイムの合計秒を取得します。

  3. ランタイムの合計秒数に平均書き込み速度を掛けて、転送された合計MBを取得します。
  4. 以下を使用して、デバイスサイズをMBで取得します。

    grep ada0 /var/run/dmesg.boot

    ターゲットデバイス名をに置き換えますada0。結果を平均書き込み速度で除算して、合計転送時間を秒単位で取得します。これまで実行していた時間を減算して、残り時間を取得します。

この戦略ddは、開始以来現在の平均書き込み速度で継続的に書き込みを行っている場合にのみ機能します。他のプロセスがCPUまたはI / Oリソース(I / Oバスを含む)を奪い合っている場合、転送速度が低下する可能性があります。



2

一方でdd実行されて、私はrootとして別の端末でこれを実行します。

while pgrep ^dd; do pkill -INFO dd; sleep 1; done

実行中の元のターミナルウィンドウdd1秒ごとにステータスを出力し、コマンドが完了すると終了します。dd


とてもクール。ここでエルキャピタンの下でうまく働いた
ステファノMtangoo

2

progress特に、実行中の進行状況を示すを使用できますdd。それは使用しています/proc/$pid/fdし、/proc/$pid/fdinfo あなたも手で監視することができました。


1

wchar行(文字が書かれている)は/proc/$pid/ioddプロセスに関する正確な情報を提供します。それが変化する限り、あなたddはまだ働いています!

ここでは、保存した後で実行することができます小ぎれいなPHPスクリプト、あるphp filename.php時にdd書き込まれたバイトを表示します。見守る/proc/$pid/ioことの良い利点はkill -USR1 $(pidof dd)、ターミナルを切り替える必要がないことです。これは必ずしもオプションではありません。

<?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";
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.