我怎么知道dd是否仍在工作?


147

我没有用dd太多,但是到目前为止,这还没有使我失望。目前,我已经dd使用了12多个小时-我正在将映像写回到它所来自的磁盘上-我有点担心,因为我能够dd从磁盘上读取映像7小时。

我在配备Core 2 Duo的MacBook上运行OSX 10.6.6,速度为2.1ghz / core,内存为4gb。我正在从7200rpm硬盘驱动器(引导驱动器)上的.dmg读取,并且正在写入通过SATA-USB连接器连接的7200rpm驱动器。默认情况下,我保留了块大小,图像约为160gb。

编辑:而且,经过14个小时的纯压力dd之后,毕竟工作正常。不过,下一次,我将运行它pv并使用进行跟踪strace。感谢大家的帮助。


7
没有回答您的问题,但是IMO的时间很高。您是否还记得将默认的512字节以外的更大的块大小传递给dd?dd ... bs=16M考虑到您的RAM,磁盘大小和速度,这是我的建议。
朱利诺

我没有,只是因为我想安全玩。不过,下次我会尝试的。谢谢。
eckza 2011年

以我的经验,dd在Mac OS X上有冻结的趋势,以至于我什至无法终止进程,而不得不重新启动系统。然后,我求助于在Linux VM上进行工作。
ssc 2014年

Answers:


174

您可以dd使用kill命令发送特定信号以使其输出当前状态。该信号INFO在BSD系统(包括OSX)和USR1Linux上。在您的情况下:

kill -INFO $PID

您可以$PID使用以下ps命令找到进程ID(上面);或在Mac OS X上查看pgrep和pkill替代品,以获取更方便的方法。

更简单地说,正如AntoineG其答案中指出的那样,您可以ctrl-T在运行dd的shell上键入INFO信号来发送信号。

例如,在Linux上,您可以使所有活动dd进程的输出状态如下:

pkill -USR1 -x dd

输出其状态后,dd将继续应对。


9
哦,很酷。您可以将它们与pkill -USR1 -x dd
Michael Mrozek一起使用

9
@kivetros:在BSD系统上,您需要发送INFO信号。Linux没有SIGINFO,USR1而是使用SIGINFO 。
Gilles

5
SIGUSRx信号用于程序执行其所需的操作,而不是具有标准化含义。例如,当终端更改其大小并且程序可能需要重绘其屏幕时,会引发SIGWINCH。操作系统不会发送SIGUSRx,因此可用于自定义用途。
LawrenceC

11
实际上,在启动后过早发送dd USR1信号(即,在bash脚本中,即启动它后的行)实际上将终止它。在它们之间放置0.1秒的睡眠,它将正确输出其进度。顺便说一句,一个非常好的dd命令来测试USR1 / INFO dd if=/dev/zero of=/dev/null。:)
Lauritz V. Thaulow 2011年

11
顺便说一句,如果状态字符(默认为Ctrl + T)发送到终端,则所有“真” BSD都会将SIGINFO发送到前台进程组。但是我不知道MacOSX是否适用。
Netch 2012年

101

在OS X下(不在Linux上尝试),您只需在运行终端中输入Ctrl+ 即可。它将输出与相同的输出,外加CPU使用率:Tddkill -INFO $PID

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使用率也可以吗?
2014年

这真是一个更好的解决方案!
Stephn_R 2015年

我在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 2011年

1
+1- pv看起来像票。
boehj 2011年

17

一种更通用的方法是使用iotop该方法显示每个程序的当前磁盘读取/写入量。

编辑:iotop -o仅显示当前执行I / O操作的程序(感谢Jason C的评论)。


1
这也是我首选的快速检查方法。iotop -o会隐藏没有执行IO的进程,使人们一眼就能知道发生了什么。
詹森C

13

我通常附加strace到这样一个正在运行的进程(带有该-p $PID选项),以查看它是否在系统调用中保持阻塞或仍处于活动状态。

或者,如果您对将信号发送到正在运行的dd感到不安,请启动另一个dd以验证其是否有效。


2
您将如何进行附加strace?另外,我确实启动了另一个,dd并向其中发送了一个建议的信号,然后...将其杀死。
eckza 2011年

2
如果您知道正在运行的dd进程的pid,只需执行strace -p <pid>。您应该看到该进程调用的所有系统调用的日志(主要是读写)
philfr 2011年

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

实际上,您执行的顺序dd和顺序无关紧要pv,这完全与性能相关-如果您要读取或读取的设备对于要使用dd而不是pv访问该设备的某些块大小具有最佳性能。dd如果需要,您甚至可以在两端都贴上a ,如果您不在乎,则根本可以不贴:

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

有时您可能无法使用INFO或USR1信号,因为dd无法访问该进程的stderr流(例如,由于执行该进程的终端已经关闭)。在这种情况下,一种解决方法是执行以下操作(在FreeBSD上进行测试,在Linux上可能略有不同):

  1. 使用iostat的平均写入速率(MB / s)的估计到目标设备,例如:

    iostat -d -w30 ada0

    将您的目标设备名称替换为ada0此处,然后等待一分钟,以得到一些结果。“ w”参数确定样本之间的间隔秒数。增加它可以得到更好的平均估计,并且方差较小,但是您必须等待更长的时间。

  2. 使用ps以确定多长时间dd已运行:

    ps -xo etime,command | grep dd

    将其转换为秒数可获得运行时间的总秒数。

  3. 将运行时间的总秒数乘以平均写入速率即可得出总的已传输MB。
  4. 使用以下命令获取设备大小(MB):

    grep ada0 /var/run/dmesg.boot

    将您的目标设备名称替换为ada0。将结果除以平均写入速率即可得到以秒为单位的总传输时间。减去到目前为止已运行的时间,以获取剩余时间。

此策略仅dd在自开始以来一直以当前的平均写入速率连续写入时才有效。如果其他进程正在争夺CPU或I / O资源(包括I / O总线),则可能会降低传输速率。


4

我开始使用dcfldd(1),它以更好的方式显示了dd操作。


2

dd执行时,我以root身份在另一个终端中运行此命令:

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

dd每隔1秒钟dd正在执行的原始终端窗口中打印一次状态,并在完成命令后退出。


非常酷。在El Capitan领导下工作良好
Stefano Mtangoo

2

您可以使用progress它来特别显示运行的进度dd。它采用/proc/$pid/fd/proc/$pid/fdinfo 你也可以通过手工监测。


1

中的wchar行(文字)/proc/$pid/io可以为您提供有关该dd过程的准确信息。只要更改,您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";
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.