How do you monitor the progress of dd?

dd is a wonder. It lets you duplicate a hard drive to another, completely zero a hard drive, etc. But once you launch a dd command, there’s nothing to tell you of its progress. It just sits there at the cursor until the command finally finishes. So how does one monitor dd’s progress?

Asked By: James

||

From HowTo: Monitor the progress of dd

You can monitor the progress of dd once it’s running without halting it by using the kill command to send a signal to the process.

After you start dd, open another terminal and enter either:

sudo kill -USR1 $(pgrep ^dd$)

Or, if you’re on BSD or OS X:

sudo kill -INFO $(pgrep ^dd$)

This will display the progress in the dd terminal window without halting the process (by printing to its stderr stream). For example:

# dd if=/dev/urandom of=rando bs=1024 count=1048576
335822+0 records in
335821+0 records out
343880704 bytes (344 MB, 328 MiB) copied, 6.85661 s, 50.2 MB/s

If you would like to get regular updates of the dd progress, then enter:

watch -n5 'sudo kill -USR1 $(pgrep ^dd$)'

watch will probe the dd process every -n seconds (-n5 = 5 seconds) and report without halting it.

Note the proper single quotes in the commands above.

Answered By: James

Update 2016: If you use GNU coreutils >= 8.24 (default in Ubuntu Xenial 16.04 upwards), you can simply add status=progress to your dd command. See method 2 below for details.


Method 1: By using pv

Install pv and put it between input / output only dd commands.

Note: you cannot use it when you already started dd.

From the package description:

pv – Pipe Viewer – is a terminal-based tool for monitoring the
progress of data through a pipeline. It can be inserted into any
normal pipeline between two processes to give a visual indication of
how quickly data is passing through, how long it has taken, how near
to completion it is, and an estimate of how long it will be until
completion.

Installation

sudo apt-get install pv

Example

dd if=/dev/urandom | pv | dd of=/dev/null

Output

1,74MB 0:00:09 [ 198kB/s] [      <=>                               ]

You could specify the approximate size with the --size if you want a time estimation.


Example Assuming a 2GB disk being copied from /dev/sdb

Command without pv would be:

sudo dd if=/dev/sdb of=DriveCopy1.dd bs=4096

Command with pv:

sudo dd if=/dev/sdb | pv -s 2G | dd of=DriveCopy1.dd bs=4096

Output:

440MB 0:00:38 [11.6MB/s] [======>                             ] 21% ETA 0:02:19

Other uses

You can of course use pv directly to pipe the output to stdout:

pv /home/user/bigfile.iso | md5sum

Output

50,2MB 0:00:06 [8,66MB/s] [=======>         ] 49% ETA 0:00:06

Note that in this case, pv recognizes the size automatically.


Method 2: New status option added to dd (GNU Coreutils 8.24+)

dd in GNU Coreutils 8.24+ (Ubuntu 16.04 and newer) got a new status option to display the progress:

Example

dd if=/dev/urandom of=/dev/null status=progress

Output

462858752 bytes (463 MB, 441 MiB) copied, 38 s, 12,2 MB/s
Answered By: phoibos

If you have already started dd, and if you are writing a file such as when creating a copy of a pendrive to disk, you can use the watch command to constantly observe the size of the output file to see changes and estimate completion.

watch ls -l /pathtofile/filename

To see only file size (h-human view):

watch ls -sh /pathtofile/filename
Answered By: fabricator4

The best is using http://dcfldd.sourceforge.net/ it is easy to install through apt-get

Answered By: TheNano

So today I got a little frustrated with trying to run kill in a loop while dd was running, and came up with this method for running them in parallel, easily:

function vdd {
    sudo dd "$@" &
    sudo sh -c "while pkill -10 ^dd$; do sleep 5; done"
}

Now just use vdd anywhere you’d normally use dd (it passes all arguments directly through) and you’ll get a progress report printed every 5s.

The only downside is that the command doesn’t return immediately when dd completes; so it’s possible that this command can keep you waiting an extra 5s after dd returns before it notices and exits.

Answered By: robru

A few handy sample usages with pv and less typing or more progress then other answers:

First you will need to install pv, with the command:

sudo apt-get install pv

Then some examples are:

pv -n /dev/urandom | dd of=/dev/null
pv -tpreb source.iso | dd of=/dev/BLABLA bs=4096 conv=notrunc,noerror

Note: the first sample is 5 characters less typing then dd if=/dev/urandom | pv | dd of=/dev/null.

And my favorite for cloning a disk drive (replace X with drive letters):

(pv -n /dev/sdX | dd of=/dev/sdX bs=128M conv=notrunc,noerror) 2>&1 | dialog --gauge "Running dd command (cloning), please wait..." 10 70 0

screenshot

source: http://www.cyberciti.biz/faq/linux-unix-dd-command-show-progress-while-coping/

Also for archiving myself.

Answered By: JSBach

Use Ctrl+Shift+T while dd is running, and it will output the progress (in bytes):

load: 1.51  cmd: dd 31215 uninterruptible 0.28u 3.67s
321121+0 records in
321120+0 records out
164413440 bytes transferred in 112.708791 secs (1458745 bytes/sec)
Answered By: 01010101

I have created bash wrapper over dd that will use pv to show progress. Put it into your .bashrc and use dd as usual:

# dd if=/dev/vvg0/root of=/dev/vvg1/root bs=4M
    2GB 0:00:17 [ 120MB/s] [===========================================================>] 100%            
0+16384 records in
0+16384 records out
2147483648 bytes (2.1 GB) copied, 18.3353 s, 117 MB/s

Source:

dd()
{
    local dd=$(which dd); [ "$dd" ] || {
        echo "'dd' is not installed!" >&2
        return 1
    }

    local pv=$(which pv); [ "$pv" ] || {
        echo "'pv' is not installed!" >&2
        "$dd" "$@"
        return $?
    }

    local arg arg2 infile
    local -a args
    for arg in "$@"
    do
        arg2=${arg#if=}
        if [ "$arg2" != "$arg" ]
        then
            infile=$arg2
        else
            args[${#args[@]}]=$arg
        fi
    done

    "$pv" -tpreb "$infile" | "$dd" "${args[@]}"
}
Answered By: midenok

The dd | pv | dd triad made my 50GB vm copy take 800 seconds, as opposed to 260 seconds using just dd. With this pipeline, at least, pv has no idea how big the input file is so it won’t be able to tell you how far along you are so there’s no disadvantage to doing it as follows- and you get a nice speed advantage:

I would avoid pv on anything large, and (if using Bash):

Control-Z the dd process

bg to put it in background. Observe that bg will give you output like [1] 6011 where the latter number is a process id. So, do:

while true; do kill -USR1 process_id ; sleep 5; done

where process_id is the process id you observed. Hit Control-C when you see something like:

[1]+  Done dd if=/path/file.qcow2 of=/dev/kvm/pxetest bs=4194304 conv=sparse
-bash: kill: (60111) - No such process

You are done.

Edit: Silly Systems Administrator! Automate your life, don’t work! If I have a long dd process that I want to monitor, here’s a one-liner that will take care of the whole enchilada for you; put this all on one line:

 dd if=/path/to/bigimage of=/path/to/newimage conv=sparse bs=262144 & bgid=$!; while true; do sleep 1; kill -USR1 $bgid || break; sleep 4; done

You can, of course, script it, perhaps make $1 your input file and $2 your output file. This is left as an exercise for the reader. Note that you need that little sleep before the kill or the kill may die trying to send a signal to dd when it’s not ready yet. Adjust your sleeps as desired (maybe even remove the second sleep altogether).

Bash- FTW! 🙂

Answered By: Mike S

For the sake of completeness:

Version 8.24 of the GNU coreutils includes a patch for dd introducing a parameter to print the progress.

The commit introducing this change has the comment:

dd: new status=progress level to print stats periodically

Many distributions, including Ubuntu 16.04.2 LTS use this version.

Answered By: davidDavidson

Native progress status was added to dd!!!

The new version of Coreutils (8.24) adds a progress status to the dd tool:

Usage on Xubuntu 15.10:

Open a terminal and type these commands:

wget ftp://ftp.gnu.org/pub/gnu/coreutils/coreutils-8.24.tar.xz
tar -xf coreutils-8.24.tar.xz
cd coreutils-8.24
./configure && make -j $(nproc)

Run dd as root:

sudo su
cd src
./dd if=/dev/sdc of=/dev/sda conv=noerror status=progress

You will see: Bytes, seconds and speed (Bytes/second).

To check the versions of dd:

Native:

dd --version

New:

cd coreutils-8.24/src
./dd --version
Answered By: user3394963

I really like ddrescue, it works as dd but gives output and doesn’t fail on errors, on the contrary it has a very advanced algorithm an tries really hard to do a successful copy… There are also many GUIs for it

Project: https://www.gnu.org/software/ddrescue

Wikipedia: https://en.wikipedia.org/wiki/Ddrescue

enter image description here

Answered By: SuperMau

On Ubuntu 16.04

Ubuntu 16.04 comes with dd (coreutils) Version 8.25 . Hence the option status=progress is Supported 🙂

To use it, just add status=progress along with your dd command.

Example :

dd bs=4M if=/media/severus/tools-soft/OperatingSystems/ubuntu-16.04-desktop-amd64.iso of=/dev/null status=progress && sync

Gives the status as

1282846183 bytes (1.2 GiB, 1.1 GiB) copied, 14.03 s, 101.9 MB/s

enter image description here

Answered By: Severus Tux

Easiest is:

 dd if=... of=... bs=4M status=progress oflag=dsync

oflag=dsync will keep your writing in sync, so information of status=progress is more accurate. However it might be a bit slower.

Answered By: zevero

This one forces dd to provide stats every 2 seconds which is default for watch:

watch killall -USR1 dd

To change from every 2 seconds to every 5 seconds, add -n 5 option like this:

watch -n 5 killall -USR1 dd
Answered By: Kostyantyn

Use option status=progress to get the progress during the transfert.

In addition, conv=fsync will display I/O errors.

Example:

sudo dd if=mydistrib.iso of=/dev/sdb status=progress conv=fsync
Answered By: MUY Belgium

You can watch the progress of any coreutils program using progress - Coreutils Progress Viewer.

It can monitor:

cp mv dd tar cat rsync grep fgrep egrep cut sort md5sum sha1sum sha224sum sha256sum sha384sum sha512sum adb gzip gunzip bzip2 bunzip2 xz unxz lzma unlzma 7z 7za zcat bzcat lzcat split gpg

You can see the manpage

You can use it in a seperate terminal window while the command is running or launch it with the dd command:

dd if=/dev/sda of=file.img & progress -mp $!

Here & forks the first command and continues immediately instead of waiting until the command ends.

The progress command is launched with: -m so it waits until the monitored process ended, -p so it monitors a given pid and $! is the last command pid.

If you issue dd with sudo, you have to too with progress too:

sudo dd if=/dev/sda of=file.img &
sudo progress -m
# with no -p, this will wait for all coreutil commands to finish
# but $! will give the sudo command's pid
Answered By: labsin

Just in case anybody from CentOS land happens to find this thread…

The ‘status=progress’ option works with CentOS 7.5 and 7.6

The answer above by @davidDavidson implies the feature was newly added in Coreutils 8.24.

Version 8.24 of the GNU coreutils includes a patch for dd introducing a parameter to print the progress.

This may be the case, but CentOS might not be following the same versioning scheme.

The version of Coreutils that comes with CentOS 7.6.1810 is:

coreutils-8.22-23.el7.x86_64 : A set of basic GNU tools commonly used in shell scripts

And the version of dd that is installed is:

[root@hostname /]# dd --version
dd (coreutils) 8.22
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Written by Paul Rubin, David MacKenzie, and Stuart Kemp.

This shows versions 8.22.

However, I have tested the ‘status=progress’ with dd on both CentOS 7.5 and CentOS 7.6 (both with version 8.22 of Coreutils) and it functions properly.

I don’t know why RedHat chooses to use such an old version of Coreutils but the functionality does exist with 8.22.

Answered By: J Hauss

On my ubuntu 20.04 system I use, dcfldd

❯ sudo dcfldd if=20210708.img status=on of=/dev/sdd bs=1M sizeprobe=if

[46% of 3814Mb] 1792 blocks (1792Mb) written. 00:00:28 remaining.

Here in sizeprobe we have 3 options, if,of,BYTES which is to determine the size of the input,output or an amount of BYTES for use with status messages

status is by default ‘on’, I just used explicitly.

Answered By: mrigendra

To add on @JSBack great answer, here is how you can get a dialog to wipe a disk with dd:

(dd if=/dev/zero | pv -s $(lsblk -b -o SIZE /dev/sdX | tail -n 1) -n | sudo dd of=/dev/sdX bs=1M) 2>&1  | dialog --gauge "Wiping disk /dev/sdX, Please wait..." 10 70 0
Answered By: Louis Ouellet

Some years ago, I got this dd progress script from somewhere (I do not recall where, and in my OPS infancy didn’t include source or references in the code comments. Thanks to the original developer, and apologies for not having the source info):

#!/bin/bash
# show progress of dd command
# example: sdd.sh if=/dev/random of=random10M.dat bs=1M count=10
# script modified to redirect to stdout and show only units less than MB

unset parameters
ibs=512
obs=512
iconvrate=1024
oconvrate=1024

while [ -n "${1}" ] ; do
    key="${1%%=*}"
    value="${1#*=}"
    case "${key}" in
        (ibs)   ibs="${value}" ;;
        (obs)   obs="${value}" ;;
        (bs)    ibs="${value}" ; obs="${value}" ;;
    esac

    parameters="${parameters} ${1}"
    shift
done

#   BLOCKS  and  BYTES  may  be  followed by the following multiplicative suffixes: xM M, c 1, w 2, b 512, kB 1000, K 1024, MB 1000*1000, M
#   1024*1024, GB 1000*1000*1000, G 1024*1024*1024, and so on for T, P, E, Z, Y.

case "${ibs: -1}" in
    (c) ibs="${ibs%c}" ; iconvrate=1024 ;;
    (w) ibs="$(( ${ibs%w} * 2))" ; iconvrate=1024 ;;
    (b) ibs="${ibs%b}" ; iconvrate=1024 ;;
    (B) ibs="${ibs%B}" ; iconvrate=1000 ;
        case "${ibs: -1}" in
            (K) ibs="$(( ${ibs%K} * 1000 ))" ;;
            (M) ibs="$(( ${ibs%M} * 1000 * 1000 ))" ;;
            (G) ibs="$(( ${ibs%G} * 1000 * 1000 * 1000 ))" ;;
            (T) ibs="$(( ${ibs%T} * 1000 * 1000 * 1000 * 1000 ))" ;;
            (P) ibs="$(( ${ibs%P} * 1000 * 1000 * 1000 * 1000 * 1000 ))" ;;
            (E) ibs="$(( ${ibs%E} * 1000 * 1000 * 1000 * 1000 * 1000 * 1000 ))" ;;
            (Z) ibs="$(( ${ibs%Z} * 1000 * 1000 * 1000 * 1000 * 1000 * 1000 * 1000 ))" ;;
            (Y) ibs="$(( ${ibs%Y} * 1000 * 1000 * 1000 * 1000 * 1000 * 1000 * 1000 * 1000 ))" ;;
        esac ;;
    (K) ibs="$(( ${ibs%K} * 1024 ))" ; iconvrate=1024 ;;
    (M) ibs="$(( ${ibs%M} * 1024 * 1024 ))" ; iconvrate=1024 ;;
    (G) ibs="$(( ${ibs%G} * 1024 * 1024 * 1024 ))" ; iconvrate=1024 ;;
    (T) ibs="$(( ${ibs%T} * 1024 * 1024 * 1024 * 1024 ))" ; iconvrate=1024 ;;
    (P) ibs="$(( ${ibs%P} * 1024 * 1024 * 1024 * 1024 * 1024 ))" ; iconvrate=1024 ;;
    (E) ibs="$(( ${ibs%E} * 1024 * 1024 * 1024 * 1024 * 1024 * 1024 ))" ; iconvrate=1024 ;;
    (Z) ibs="$(( ${ibs%Z} * 1024 * 1024 * 1024 * 1024 * 1024 * 1024 * 1024 ))" ; iconvrate=1024 ;;
    (Y) ibs="$(( ${ibs%Y} * 1024 * 1024 * 1024 * 1024 * 1024 * 1024 * 1024 * 1024 ))" ; iconvrate=1024 ;;
esac

case "${obs: -1}" in
    (c) obs="${obs%c}" ; oconvrate=1024 ;;
    (w) obs="$(( ${obs%w} * 2))" ; oconvrate=1024 ;;
    (b) obs="${obs%b}" ; oconvrate=1024 ;;
    (B) obs="${obs%B}" ; oconvrate=1000 ;
        case "${obs: -1}" in
            (K) obs="$(( ${obs%K} * 1000 ))" ;;
            (M) obs="$(( ${obs%M} * 1000 * 1000 ))" ;;
            (G) obs="$(( ${obs%G} * 1000 * 1000 * 1000 ))" ;;
            (T) obs="$(( ${obs%T} * 1000 * 1000 * 1000 * 1000 ))" ;;
            (P) obs="$(( ${obs%P} * 1000 * 1000 * 1000 * 1000 * 1000 ))" ;;
            (E) obs="$(( ${obs%E} * 1000 * 1000 * 1000 * 1000 * 1000 * 1000 ))" ;;
            (Z) obs="$(( ${obs%Z} * 1000 * 1000 * 1000 * 1000 * 1000 * 1000 * 1000 ))" ;;
            (Y) obs="$(( ${obs%Y} * 1000 * 1000 * 1000 * 1000 * 1000 * 1000 * 1000 * 1000 ))" ;;
        esac ;;
    (K) obs="$(( ${obs%K} * 1024 ))" ; oconvrate=1024 ;;
    (M) obs="$(( ${obs%M} * 1024 * 1024 ))" ; oconvrate=1024 ;;
    (G) obs="$(( ${obs%G} * 1024 * 1024 * 1024 ))" ; oconvrate=1024 ;;
    (T) obs="$(( ${obs%T} * 1024 * 1024 * 1024 * 1024 ))" ; oconvrate=1024 ;;
    (P) obs="$(( ${obs%P} * 1024 * 1024 * 1024 * 1024 * 1024 ))" ; oconvrate=1024 ;;
    (E) obs="$(( ${obs%E} * 1024 * 1024 * 1024 * 1024 * 1024 * 1024 ))" ; oconvrate=1024 ;;
    (Z) obs="$(( ${obs%Z} * 1024 * 1024 * 1024 * 1024 * 1024 * 1024 * 1024 ))" ; oconvrate=1024 ;;
    (Y) obs="$(( ${obs%Y} * 1024 * 1024 * 1024 * 1024 * 1024 * 1024 * 1024 * 1024 ))" ; oconvrate=1024 ;;
esac

tmp="$( mktemp )"
rm -f "${tmp}"
mkfifo "${tmp}"
chmod 0600 "${tmp}"

dd ${parameters} 2> ${tmp} &
pid=${!}

SECONDS=0
while [ -d /proc/${pid} ] ; do
    sleep 1
    kill -USR1 ${pid} > /dev/null 2> /dev/null
#114718+0 records in
#114717+0 records out
#58735104 bytes (59 MB) copied, 5.61526 seconds, 10.5 MB/s

    read line1
    read line2
    read line3
    isuff=""
    osuff=""
    ipssuff=""
    opssuff=""
    line1="${line1%+*}"
    line2="${line2%+*}"
    in="$(( ${line1} * ${ibs} ))"
    out="$(( ${line2} * ${obs} ))"
    ips="$(( ${in} / ${SECONDS} ))"
    ops="$(( ${out} / ${SECONDS} ))"
#   for x in k M G T P E Z F ; do
    for x in k M ; do
        if [ ${ips} -gt ${iconvrate} ] ; then
            ips="$(( ${ips} / ${iconvrate} ))"
            ipssuff="${x}"
            [ ${iconvrate} -eq 1000 ] && ipssuff="${ipssuff}B"
        fi
        if [ ${ops} -gt ${oconvrate} ] ; then
            ops="$(( ${ops} / ${oconvrate} ))"
            opssuff="${x}"
            [ ${oconvrate} -eq 1000 ] && opssuff="${opssuff}B"
        fi
        if [ ${in} -gt ${iconvrate} ] ; then
            in="$(( ${in} / ${iconvrate} ))"
            isuff="${x}"
            [ ${iconvrate} -eq 1000 ] && isuff="${ipssuff}B"
        fi
        if [ ${out} -gt ${oconvrate} ] ; then
            out="$(( ${out} / ${oconvrate} ))"
            osuff="${x}"
        fi
    done
    echo -en "rIn: ${in}${isuff} (${ips}${ipssuff}/sec) - Out: ${out}${osuff} (${ops}${opssuff}/sec)" > /dev/stderr
done < "${tmp}"
echo > /dev/stderr
rm -f "${tmp}"

This script starts dd and sends it a HUP signal each second, parsing the output to make it more readable and showing the progress data in a single updating line.

I didn’t write the code and never took the time to optimize it.

Answered By: Fjor
Categories: Answers Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.