0%

Linux dd命令

Linux 的 dd 命令

dd这个命令一直没有弄明白缩写的含义,这个命令应该归到Linux炫技里面,因为我也是很晚才用到,不过有些功能还可以尝试一下。

官方含义为:

dd - convert and copy a file

从官方含义来看,是不是定义为cc比较合适,^_^

dd命令用于复制文件,转换或者格式化文件。

dd命令功能很强大的,对于一些比较底层的问题,使用dd命令往往可以得到出人意料的效果。

命令格式

命令比较简单:

1
$ dd 选项

对于刚开始而言,仅仅下面几个掌握下面几个参数就完全够用了。

  • of=FILE, 将输出定位到FILE,而不是默认的stdout
  • bs=BYTES,每次读取的字节数,默认为512字节
  • count=N, 拷贝N个输入块
  • if=FILE, 从FILE输入,而不是默认的stdin

考虑替换cp命令

既然命令第一个说明就是拷贝文件,那么正常情况下基本是可以替换cp的,不过前提是有参数指定,比如:

1
2
3
4
5
6
7
8
9
10
11

# 默认cp拷贝,一个1GB的文件,花费1.05秒
$ time cp a b
cp a b 0.02s user 1.05s system 75% cpu 1.403 total

# 默认dd拷贝,一个1GB的文件,竟然花费了29.17秒
$ time dd if=a of=b
2048000+0 records in
2048000+0 records out
1048576000 bytes (1.0 GB, 1000 MiB) copied, 34.7214 s, 30.2 MB/s
dd if=a of=b 1.31s user 29.17s system 87% cpu 34.996 total

为什么dd这么慢,很简单,在不指定bs的情况下,默认为512字节,dd就会根据512来切分,时间都浪费在了这个上面。

所以简单地加上这个参数,迅速提升效率

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
$ time dd if=a of=b bs=2M
500+0 records in
500+0 records out
1048576000 bytes (1.0 GB, 1000 MiB) copied, 1.04747 s, 1.0 GB/s
dd if=a of=b bs=2M 0.00s user 1.05s system 78% cpu 1.332 total
$ time dd if=a of=b bs=4M
250+0 records in
250+0 records out
1048576000 bytes (1.0 GB, 1000 MiB) copied, 1.00866 s, 1.0 GB/s
dd if=a of=b bs=4M 0.00s user 1.00s system 76% cpu 1.304 total
$ time dd if=a of=b bs=8M
125+0 records in
125+0 records out
1048576000 bytes (1.0 GB, 1000 MiB) copied, 0.937974 s, 1.1 GB/s
dd if=a of=b bs=8M 0.00s user 0.92s system 79% cpu 1.164 total
$ time dd if=a of=b bs=10M
100+0 records in
100+0 records out
1048576000 bytes (1.0 GB, 1000 MiB) copied, 1.01666 s, 1.0 GB/s
dd if=a of=b bs=10M 0.00s user 1.03s system 82% cpu 1.257 total

测试硬盘速度

我最常使用的dd命令的用例是,测试硬盘的读写速度,比如很简单地写入1GB、10GB来看一下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$ dd if=/dev/zero of=tmp bs=1M count=1000
1000+0 records in
1000+0 records out
1048576000 bytes (1.0 GB, 1000 MiB) copied, 0.7338 s, 1.4 GB/s

$ dd if=/dev/zero of=tmp bs=2M count=500
500+0 records in
500+0 records out
1048576000 bytes (1.0 GB, 1000 MiB) copied, 0.611315 s, 1.7 GB/s

$ dd if=/dev/zero of=tmp bs=4M count=250
250+0 records in
250+0 records out
1048576000 bytes (1.0 GB, 1000 MiB) copied, 0.602517 s, 1.7 GB/s

然后根据这些参数,可以简单写一个脚本来评估系统的整体读写速率了。

当然dd系统管理员用的最多的应该是系统备份和克隆了,暂且不表。

#######TODO

backup an entire copy of a hard disk to another hard disk

1
# dd if=/dev/sda of=/dev/sdb conv=sync,noerror
   cbs=BYTES
          convert BYTES bytes at a time

   conv=CONVS
          convert the file as per the comma separated symbol list


   ibs=BYTES
          read up to BYTES bytes at a time (default: 512)


   iflag=FLAGS
          read as per the comma separated symbol list

   obs=BYTES
          write BYTES bytes at a time (default: 512)

   oflag=FLAGS
          write as per the comma separated symbol list

   seek=N skip N obs-sized blocks at start of output

   skip=N skip N ibs-sized blocks at start of input

   status=LEVEL
          The  LEVEL of information to print to stderr; 'none' suppresses everything but error messages, 'noxfer'
          suppresses the final transfer statistics, 'progress' shows periodic transfer statistics

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

   Each CONV symbol may be:

   ascii  from EBCDIC to ASCII

   ebcdic from ASCII to EBCDIC

   ibm    from ASCII to alternate EBCDIC

   block  pad newline-terminated records with spaces to cbs-size

   unblock
          replace trailing spaces in cbs-size records with newline

   lcase  change upper case to lower case

   ucase  change lower case to upper case

   sparse try to seek rather than write the output for NUL input blocks

   swab   swap every pair of input bytes

   sync   pad  every  input  block with NULs to ibs-size; when used with block or unblock, pad with spaces rather
          than NULs

   excl   fail if the output file already exists

   nocreat
          do not create the output file

   notrunc
          do not truncate the output file

   noerror
          continue after read errors

   fdatasync
          physically write output file data before finishing

   fsync  likewise, but also write metadata

   Each FLAG symbol may be:

   append append mode (makes sense only for output; conv=notrunc suggested)

   direct use direct I/O for data

   directory
          fail unless a directory

   dsync  use synchronized I/O for data

   sync   likewise, but also for metadata

   fullblock
          accumulate full blocks of input (iflag only)

   nonblock
          use non-blocking I/O

   noatime
          do not update access time

   nocache
          Request to drop cache.  See also oflag=sync

   noctty do not assign controlling terminal from file

   nofollow
          do not follow symlinks

   count_bytes
          treat 'count=N' as a byte count (iflag only)

   skip_bytes
          treat 'skip=N' as a byte count (iflag only)

   seek_bytes
          treat 'seek=N' as a byte count (oflag only)

   Sending a USR1 signal to a running 'dd' process makes it print I/O statistics to standard error and  then  re‐
   sume copying.

使用dd命令克隆整个系统

进入Linux操作系统,打开命令行,执行如下命令:

1
sudo  fdisk -u -l

可以查看所有磁盘上的所有分区的尺寸和布局情况。

-u,让start和end中数字的单位是512字节,也就是一个sector扇区的大小。

具体步骤

找一个U盘,安装UbuntuLive Cd系统。

U盘启动,进入盘上的Ubuntu系统,打开命令行,执行:

1
sudo  fdisk -u -l /dev/sda

查看硬件的分区情况。

然后执行:

1
dd   bs=512 count=[fdisk命令中最大的end数+1] if=/dev/sda of=/ghost.img

这样,就可以把我需要的分区数据全部copy到ghost.img文件中。镜像制作完成了!

然后,我们就可以把U盘插到其他系统上,用U盘启动,进入UbuntuLiveCD,打开命令行,执行如下命令:

1
dd if=/ghost.img of=/dev/sda

完成后,拔掉U盘,启动计算机,就可以看到我们的Linux系统已经安装完毕了!

注意:不要直接在计算机上用本地磁盘启动系统后执行dd命令生成本地磁盘的镜像。而应该使用livecd启动计算机。因此计算机运行时会对系统盘产生大量写操作。 直接对运行中的系统盘生成的镜像,在恢复到其他硬盘上时,很可能会无法启动!

一样适用于非Linux操作系统, 在linux上用dd命令实现系统镜像备份和恢复,是不是很简单呢?

对于Windows系统,甚至Mac等等任意系统,其实都可以用dd命令实现系统镜像的备份和恢复。
因为,Linux的fdisk命令能够识别任意系统下的分区格式。fdisk并不关系分区上的文件系统,甚至有无文件系统都不关心。fdisk总是可以报告分区占用了哪些扇区。
dd命令也不关心磁盘的文件系统格式,它只是简单地按照要求从指定的位置,复制多少字节数据而已。
dd命令实现镜像备份和恢复,比Ghost软件简单和强大多了。使用ghost软件,依然需要用户进行复杂而危险的磁盘分区操作。
而使用fdisk和dd这两条命令,一切都免了!

压缩和解压缩

可能我们需要备份的分区很大,使用dd命令生成的镜像文件也就很大。存储和传输这些镜像不太方便。 我们也可以使用压缩程序压缩生成的镜像文件。 这里,我选择使用gzip程序,配合dd命令一起使用。

gzip参数:

  • -c 表示输出到stdout
  • -d 表示解压缩
  • -1 表示最快压缩
  • -9 表示最好压缩

默认使用的是-6压缩级别。

要使用 dd 和 gzip 生成压缩的镜像文件,可以执行命令:

1
# dd bs=512 count=[fdisk命令中最大的end数+1] if=/dev/sda | gzip -6 > /ghost.img.gz

还原时,可以执行下列命令: # gzip -dc /ghost.img.gz.gz | dd of=/dev/sda

提醒:
如果你把镜像恢复到另一台计算机上,你可能会发现你的网卡是eth1,而不是eth0。这是因为
/etc/udev/rules.d/70-persistent-net.rules 文件把你做镜像的计算机的网卡作为eth0登记了。
如果你的网络脚本对eth0进行了处理,而没有对eth1进行处理,那么不修改网络脚本,你可能就无法上网了。

也许你会希望在做镜像之前,先删除 /etc/udev/rules.d/70-persistent-net.rules 文件。这样你恢复镜像时,网卡的名字就是eth0。 就不会造成你在恢复后的计算机上无法上网的问题了。

处无为之事,行不言之教;作而弗始,生而弗有,为而弗恃,功成不居!

欢迎关注我的其它发布渠道