That One Stupid dd Trick and the Ballad of SIGINFO

2 minute read

dd is the *NIX byte copying utility. It’s typically used for copying disks, creating disk images, or initializing disks from images. It can also be using to recover damaged files that can’t otherwise be copied. I mostly use it to make create bootable USB sticks for server installs. However, it’s also pretty opaque.

dd is as old as UNIX itself, so old that it’s flags don’t follow the using convention of using a dash:

dd if=ubuntu-14.04.4-server-amd64.img of=/dev/rdisk3 bs=1m

if, of, and bs are all command line flags. In fact, dd’s syntax is based on IBM’s Job Control Language (JCL), which is why it doesn’t look like UNIX at all.

When dd is running, it give no status information, only reporting what’s it’s done when it’s finished or fails:

sudo dd if=ubuntu-14.04.4-server-amd64.img of=/dev/rdisk3 bs=1m
579+0 records in
579+0 records out
607125504 bytes transferred in 180.563254 secs (3362398 bytes/sec)

Or does it? The trick is this, by sending the dd process SIGUSR1 (Linux) or SIGINFO (BSD, OS X), you can get it to display a version of the “final” status at any time.

sudo dd if=ubuntu-14.04.4-server-amd64.img of=/dev/rdisk3 bs=1m
# Gets signal
load: 1.65  cmd: dd 99732 uninterruptible 0.00u 0.13s
249+0 records in
248+0 records out
260046848 bytes transferred in 0.330818 secs (786072393 bytes/sec)
# Time passes and it finishes.
579+0 records in
579+0 records out
607125504 bytes transferred in 180.563254 secs (3362398 bytes/sec)

On BSD based systems, including OS X, it’s super easy to raise SIGINFO, it’s bound to Control-T in the same way SIGINT is bound to Control-C. Hitting ^T while dd is running triggers the status output.

SIGINFO is awesome. By default raising it with ^T will cause the system load and current running app to be displayed, handy to figure out what a long running script is doing.

rails s
Thin web server (v1.6.3 codename Protein Powder)
Maximum connections set to 1024
Listening on localhost:3000, CTRL+C to stop
# ^T hit here
load: 2.27  cmd: ruby 7291 waiting 1.65u 0.49s

Commands can catch SIGINFO to trigger their own status messages. tar, ftp, and cp will respond with stats and the name of the file that is currently being process. ping will give you the summary it usually displays when it exits. There are probably many others I’ve never discovered.

But your servers are running Linux, aren’t they? SIGINFO is not one of the official POSIX signals and Linux doesn’t implement it. Your loss really.

Instead the GNU version of dd, which ships with most Linux distros, gives us the same behavior when it receives the generic SIGUSR1. Of course, unlike SIGINFO, SIGUSR1 not bound to anything, so you need to use kill. And to do that, you need to have another window and the dd processes PID:

# Star dd in another window.
ps | grep dd
13747 pts/0    00:00:19 dd
kill -SIGUSR1 13747

Alternatively, you can start dd in the background, capture the PID, and use it with kill:

sudo dd if=ubuntu-14.04.4-server-amd64.img of=/dev/rdisk3 bs=1m & dd_pid=$!
kill -USR1 $dd_pid
load: 1.65  cmd: dd 99732 uninterruptible 0.00u 0.13s
249+0 records in
248+0 records out
260046848 bytes transferred in 0.330818 secs (786072393 bytes/sec)

But personally, I’d rather keep the process in the foreground where I can see it.

So, now you know, dd’s progress isn’t a black box. And, if your on a BSD based system, it’s right at your finger tips!

Tags:

Updated:

Comments