it-swarm-ru.tech

Как я узнаю, что дд все еще работает?

Я не так много использовал dd, но пока это не подвело меня. Прямо сейчас у меня dd идет более 12 часов - я записываю образ обратно на диск, с которого он пришел - и я немного волнуюсь, поскольку смог dd с диска до образа примерно за 7 часов.

Я использую OSX 10.6.6 на MacBook с Core 2 Duo с частотой 2,1 ГГц/ядро ​​и 4 ГБ ОЗУ. Я читаю из .dmg на жестком диске со скоростью 7200 об/мин (загрузочный диск) и пишу на диск со скоростью 7200 об/мин, подключенный через разъем SATA-to-USB. Я оставил размер блока по умолчанию, и изображение составляет около 160 ГБ.

Правка: И после 14 часов чистого стресса, dd в конце концов работал отлично. В следующий раз, однако, я собираюсь запустить его через pv и ​​отследить с помощью strace. Спасибо всем за вашу помощь.

150
eckza

Вы можете отправить dd определенный сигнал с помощью команды kill, чтобы он вывел свой текущий статус. Сигнал INFO в системах BSD (включая OSX) и USR1 в Linux. В твоем случае:

kill -INFO $PID

Вы можете найти идентификатор процесса ($PID выше) с помощью команды ps; или смотрите альтернативы pgrep и pkill на mac os x для более удобных методов.

Проще говоря, поскольку AntoineG указывает на его ответ , вы можете набрать ctrl-T в командной консоли dd для отправки ему сигнала INFO.

Например, в Linux вы можете сделать все активные dd процессы вывода такими, как это:

pkill -USR1 -x dd

После вывода его состояния dd продолжит копирование.

176
Caleb

Под OS X (не пробовал в Linux), вы можете просто набрать Ctrl+T в терминале работает dd. Он выведет тот же вывод, что и kill -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)

Я узнал об этом, читая эту ветку и пытаясь открыть новую вкладку в моем терминале, но смешивая +T с Ctrl+T,.

104
AntoineG

Для dd вы можете отправить сигнал . Для других команд, которые читают или записывают в файл, вы можете наблюдать их положение в файле с помощью lsof .

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

Если вы планируете заранее, направьте данные через pv .

26
Gilles 'SO- stop being evil'

Более общий способ - использовать iotop , который отображает текущее количество операций чтения/записи на диск для каждой программы.

Правка: iotop -o показывать только программы, которые выполняют текущие операции ввода/вывода (спасибо Jason C за этот комментарий).

17
jofel

Я обычно присоединяю strace к такому запущенному процессу (с -p $PID опция), чтобы увидеть, остается ли он заблокированным в системном вызове или все еще активным.

Или, если вы нервничаете по поводу отправки сигнала работающему дд, запустите другой дд, чтобы проверить, работает ли это.

13
philfr

В следующий раз вы можете просто использовать pv с самого начала (если это доступно через менеджер пакетов, установите его). Это утилита, единственная цель которой состоит в том, чтобы направлять входные данные на выход и контролировать ход и скорость.

Затем для записи образа на диск, скажем, с размером блока 4 МБ:

pv -ptearb /path/to/image.bin | dd iflag=fullblock of=/dev/whatever bs=4M

Помимо начальной буферизации (смещение путем окончательной синхронизации, которая может быть выполнена через dd, если вы хотите), она покажет вам индикатор выполнения, среднюю скорость, текущую скорость и ETA.

Параметр iflag=fullblock вынуждает dd захватывать полные блоки ввода через pv, в противном случае вы можете рассчитывать на размер канала.

Чтобы пойти другим путем, используйте dd для чтения и pv для записи, хотя вы должны явно указать размер, если источником является блочное устройство. Для устройства 4 ГБ:

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
11
Jason C

Начиная с coreutils v8.24, dd имеет встроенную поддержку для отображения прогресса. Просто добавьте опцию status=progress.

Пример:

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

Источник

10
Chirag Bhatia - chirag64

ddrescue даст вам статистику во время работы.

демо: http://www.youtube.com/watch?v=vqq9A01geeA#t=144s

5
Ben Preston

Я начал использовать dcfldd (1), который лучше показывает операции dd.

4
Kartik M

Иногда вы не можете использовать сигнал INFO или USR1, потому что поток stderr процесса dd недоступен (например, потому что терминал, в котором он был выполнен, уже был закрыт). В этом случае, обходной путь должен сделать следующее (проверено на FreeBSD, может немного отличаться на Linux):

  1. Используйте iostat для оценки средней скорости записи (МБ/с) на целевое устройство, например:

    iostat -d -w30 ada0

    Замените имя целевого устройства на ada0 здесь, и подождите минуту, пока он даст пару результатов. Параметр "w" определяет, сколько секунд между выборками. Увеличение его даст лучшую среднюю оценку с меньшей дисперсией, но вам придется ждать дольше.

  2. Используйте ps, чтобы определить, как долго dd работает:

    ps -xo etime,command | grep dd

    Преобразуйте это в секунды, чтобы получить общее количество секунд времени выполнения.

  3. Умножьте общее количество секунд времени выполнения на среднюю скорость записи, чтобы получить общее количество переданных МБ.
  4. Получите размер устройства в МБ с помощью:

    grep ada0 /var/run/dmesg.boot

    Замените имя целевого устройства на ada0. Разделите результат на среднюю скорость записи, чтобы получить общее время передачи в секундах. Вычтите время, которое уходит до сих пор, чтобы получить оставшееся время.

Эта стратегия работает только в том случае, если dd непрерывно писал с текущей средней скоростью записи с момента ее начала. Если другие процессы конкурируют за ресурсы ЦП или В/В (включая шину В/В), это может снизить скорость передачи.

4
D Coetzee

Вы можете использовать progress , который, в частности, показывает ход выполнения dd. Оно использует /proc/$pid/fd а также /proc/$pid/fdinfo, который вы также можете контролировать вручную.

3
jofel

Пока выполняется dd, я запускаю это в другом терминале от имени пользователя root:

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

Он печатает состояние dd каждую 1 секунду в исходном окне терминала, где выполняется dd, и завершается, когда команда выполнена.

2
ccpizza

Строка wchar (письменные символы) в _/proc/$pid/io_ может дать вам точную информацию о процессе dd. Пока он меняется, ваш dd все еще работает!

Вот небольшой аккуратный php-скрипт, который вы можете сохранить и затем выполнить с помощью _php filename.php_ во время dd для отображения записанных байтов. Приятным преимуществом просмотра _/proc/$pid/io_ over 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";
}
_
1
Leon Kramer