Linux【6】-硬盘管理6-7-Linux数据备份及格式转换(dd)

dd,是 device driver 的缩写,它可以称得上是“Linux 世界中的搬运工”,它用来读取设备、文件中的内容,并原封不动地复制到指定位置。

当我们用 dd 命令读取 /dev/null 文件时,就可以创造出空洞文件,而如果你的磁盘足够大,你甚至可以创造出一个宇宙黑洞呢!

dd 命令主要用来进行数据备份,并且可以在备份的过程中进行格式转换。其实 dd 命令可以把源数据复制成目标数据,而且不管源数据是文件、分区、磁盘还是光盘,都可以进行数据备份。

一、基本参数

dd 命令的基本格式如下:

[root@localhost ~]# dd if="输入文件" of="输出文件" bs="数据块" count="数量"

参数:

if:定义输入数据的文件,也可以是输入设备;
of:定义输出数据的文件,也可以是输出设备;
bs:指定数据块的大小,也就是定义一次性读取或写入多少字节。模式数据块大小是 512 字节;
count:指定 bs 的数量;
conv=标志:依据标志转换文件。标志有以下这些:
ascii:由 EBCDIC 码转换至 ASCII 码;
ebcdic:由 ASCII 码转换至 EBCDIC 码;
ibm:由 ASCII 码转换至替换的 EBCDIC 码;
block:将结束字符块里的换行替换成等长的空格;
unblock:将 cbs 大小的块中尾部的空格替换为一个换行符;
lcase:将大写字符转换为小写;
notrunc:不截断输出文件;
ucase:将小写字符转换为大写;
swab:交换每一对输入数据字节;
noerror:读取数据发生错误后仍然继续;
sync:将每个输入数据块以 NUL 字符填满至 ibs 的大小;当配合 block 或 unblock 时,会以空格代替 NUL 字符填充;

二、常见用法

2.1 备份文件

[root@localhost ~]# dd if=/etc/httpd/conf/httpd.conf of=/tmp/httpd.bak

记录了67+1 的读入
#数据占了写满的67个数据块,以及1个没有写满的数据块
记录了67+1 的写出
#默认数据块大小是512字节
34439字节(34 kB)已复制,0.0524897 秒,656 kB/秒
#如果要备份文件,那么dd命令和cp命令非常类似
[root@localhost ~]# ll -h /tmp/httpd.bak
-rw-r--r--.1 root root 34K 6月 5 18:04 /tmp/httpd.bak
#查看一下生成的备份文件的大小

2.2 备份分区为一个备份文件

[root@localhost ~]# df -h

文件系统 容量 已用 可用 已用%% 挂载点
/dev/sda3 20G 2.0G 17G 11% /
tmpfs 306M 0 306M 0% /dev/shm
/dev/sda1 194M 27M 157M 15% /boot
/dev/sr0 3.5G 3.5G 0 100% /mnt/cdrom
#查看一下分区容量,我们备份/boot分区

[root@localhost ~]# dd if=/dev/sda1 of=/tmp/boot.bak
#备份完成

[root@localhost ~]# ll -h /tmp/boot.bak
-rw-r--r--.1 root root 200M 6月 5 18:14 /tmp/boot.bak
#查看生成的备份文件

#如果需要恢复,则执行以下命令
[root@localhost ~]# dd if=/tmp/boot.bak of=/dev/sda1

如果想要把分区直接备份成另一个分区,就需要生成一个新的分区,这个分区的大小不能比源分区小,只能和源分区大小一致或比它大。命令如下:

[root@localhost ~]# dd if=/dev/sda1 of=/dev/sdb1

#如果需要恢复,则只需把输入项和输出项反过来即可,命令如下
[root@localhost ~]# dd if=/dev/sdb1 of=/dev/sda1

2.3 整盘备份

[root@localhost ~]# dd if=/dev/sda of=/dev/sdb

#把磁盘a备份到磁盘b
[root@localhost ~]# dd if=/dev/sda of=/tmp/disk.bak
#把磁盘a备份成文件disk.bak
#备份恢复
#如果要备份到另一块硬盘上,那么,当源硬盘数据损坏时,只需用备份硬盘替换源硬盘即可
#如果要备份成文件,那么在恢复时需要把备份数据复制到其他Linux中,然后把新硬盘安装到这台Linux
#服务器上,再把磁盘备份数据复制到新硬盘中。命令如下
[root@localhost ~]# dd if=/tmp/disk.bak of=/dev/sdb

2.5 复制软盘

[root@localhost ~]# dd if=/dev/fd0 of=/tmp/fd.bak
#在Linux中软盘的设备文件名是/dev/fd0
#这条命令先把软盘中的数据保存为临时数据文件
[root@localhost ~]# dd if=/tmp/fd.bak of=/dev/fd0
#然后更换新的软盘,把数据备份复制到新软盘中,就实现了软盘的复制

如果需要备份的是光盘,那么在 Linux 中就是使用 dd 命令制作光盘的 ISO 镜像的。命令如下:

#制作光盘ISO镜像

[root@localhost ~]# dd if=/dev/cdrom of-/tmp/cd.iso #把光盘中所有的数据制作成ISO镜像
[root@localhost ~J # mkdir /mnt/cd
#建立一个新的挂载点
[root@localhost ~]# mount -o loop /tmp/cd.iso /mnt/cd #挂栽ISO文件到挂载点
[root@localhost ~]# cd /mnt/cd
#进入挂栽点
[root@localhost cd]# ls
CentOS_BuildTag images RELEASE-NOTES-en-tJS.html RPM-GPG-KEY-CentOS-Debug-6 TRANS.TBL
EULA    isolinux repodata   RPM-GPG-KEY-CentOS-Security-6
GPL Packages RPM-GPG-KEY-CentOS-6 RPM-GPG-KEY-CentOS-Testing-6
#数据是光盘当中的数据,这个ISO镜像是可以被当作真正的光盘使用的

我们有时需要制作指定大小的文件,比如,在增加 swap 分区时,就需要建立指定大小的文件,这时也使用 dd 命令。命令如下:

[root@localhost ~]# dd if=/dev/zero of=/tmp/testfile bs=1M count=10
#数据输入项是/dev/zero会向目标文件中不停地写入二进制的0
#指定数据块大小是1MB
#指定生成10个数据块。也就是定义输出的文件大小为10MB
记录了10+0 的读入
#显示数据占满了10个数据块
记录了10+0 的写出
#不过这里数据块的大小已经是1MB了
10485760字节(10 MB)已复制,0.00709902 秒,1.5 GB/秒
[root@localhost ~]# ll -h /tmp/testfile
-rw-r--r--.1 root root 10M 6月 5 18:46 /tmp/testfile
#生成的testfile文件的大小刚好是10MB

dd 命令在进行整盘复制时,类似于 GHOST 工具的功能,不过通过 dd 命令复制出来的硬盘数据要比 GHOST 复制出来的硬盘数据稳定得多。虽然 dd 命令功能强大,不过也有一个明显的缺点,就是复制的时间较长,复制 100GB 的数据需要 15~25 分钟(根据服务器的性能不同而不同)。

实现数据备份还有非常多的方法和工具,比如 tar 和 cpio 命令。至于网络复制工具,如 rsync 和 scp 等,需要较完善的网络知识才能够学习,这里不再介绍。

2.6 备份时进行压缩

数据没有压缩就进行整盘备份,势必需要很大的备份空间,从而导致备份成本升高。这对于备份场景来说,是低效能的表现。

假如遇到磁盘空间不足,连备份操作都没办法圆满完成:

#看, 报出了磁盘空间不足的警告
[root@roclinux ~]# dd if=/dev/sda of=/root/sda.img
dd: writing to '/root/sda.img': No space left on device

其实我们在使用 dd 做备份时,可以使用 gzip 或者 bzip2 压缩算法进行数据压缩处理,这样可以大大减少我们的磁盘空间用量,也就降低了备份成本。

下面就使用 gzip 压缩算法配合 dd 命令来备份 /dev/sda 盘:

#没有指定of则表示输出到标准输出
[root@roclinux ~]# dd if=/dev/sda | gzip > /root/sda.img.gz

然后再将其恢复到 /dev/sdb 盘中去,方法如下:

#没有指定if就表示从标准输入读取

下面我们更换 bzip2 压缩算法配合 dd 命令再来实现一遍上面示例的效果:

[root@roclinux ~]# dd if=/dev/sda | bzip2 > disk.img.bz2
[root@roclinux ~]# bzip2 -dc /root/sda.img.gz | dd of=/dev/sdc

2.7 分区、内存、软盘一个都不能少

在上面的内容中,介绍的都是备份整盘的知识,那如果只是想备份某一个分区的数据,应该如何操作呢?

卖了一个关子,其实在 dd 命令看来,备份整盘和备份分区,在命令形式上并没有区别,我们来看示例:

[root@roclinux ~]# dd if=/dev/sda2 of=/root/sda_part1.img

同理,将内存中的数据整体备份,照样可以如法炮制:

[root@roclinux ~]# dd if=/dev/mem of=/root/mem.img

随着科技的飞速发展,无论是台式机还是笔记本,都已经取消了软驱和光驱设备,软盘和光盘也已经接近灭绝的边缘,很多九零后们应该都不知道软驱为何物了吧。

所以接下来要介绍的软盘、光盘备份法,权当是追忆过去吧,谨以此内容来怀念我们逝去的青春。

#备份软盘
[root@roclinux ~]# dd if=/dev/fd0 of=/root/fd0.img count=1 bs=1440k
 
#备份光盘
[root@roclinux ~]# dd if=/dev/cdrom of=/root/cd.img

对于 dd 命令来说,除了 if、of 两个选项之外,还应该掌握下面这两个重要选项:

  • bs=N:设置单次读入或单次输出的数据块(block)的大小为 N 个字节。当然也可以使用 ibs 和 obs 选项来分别设置。
  • ibs=N:单次读入的数据块(block)的大小为 N 个字节,默认为 512 字节。
  • obs=N:单次输出的数据块(block)的大小为 N 个字节,默认为 512 字节。
  • count=N:表示总共要复制 N 个数据块(block)。

所以这里备份的软盘大小是 1440kB,可以看出这是一块 3 寸盘,其大小为 1.44MB。为了追忆青春,我们再来一起看看软盘的样子。

2.8 备份磁盘的 MBR

MBR,是 Master Boot Record,即硬盘的主引导记录,MBR 一旦损坏,分区表也就被破坏,数据大量丢失,系统就再也无法正常引导了,真是不堪设想啊!所以,对 MBR 的定期备份是十分必要的,在紧急关头,把它比喻成一颗救死扶伤的速效救心丸,也绝不为过。

一块磁盘的第一个扇区的 512 个字节所存储的正是这块磁盘的 MBR 信息,我们尝试用 dd 命令备份 MBR:

[root@roclinux ~]# dd if=/dev/sda of=/root/sda_mbr.img count=1 bs=512

如果未来遇到分区表损坏的情况,我们用曾经备份的 MBR 信息写回磁盘,就能起到立竿见影的效果。下面来一起看看如何将 MBR 写回硬盘:

[root@roclinux ~]# dd if=/root/sda_mbr.img of=/dev/sda

方法是不是比你想象得要简单,即使是面对 MBR 如此重要的敏感数据,dd 命令也是闲庭信步,信手拈来。

2.9 使用 /dev/zero 和 /dev/null 来测试磁盘

本段落开始前,我们要为大家介绍两位新朋友:

/dev/null,也叫空设备,小名“无底洞”。任何写入它的数据都会被无情抛弃。 /dev/zero,可以产生连续不断的 null 的流(二进制的零流),用于向设备或文件写入 null 数据,一般用它来对设备或文件进行初始化。

我们可以观察下面两个命令的执行时间,来计算出硬盘的读、写性能: #向磁盘上写一个大文件, 来看写性能

[root@roclinux ~]# dd if=/dev/zero bs=1024 count=1000000 of=/root/1Gb.file
 
#从磁盘上读取一个大文件, 来看读性能
[root@roclinux ~]# dd if=/root/1Gb.file bs=64k | dd of=/dev/null

上面命令生成了一个 1GB 的文件 1Gb.file,下面我们配合 time 命令,可以看出不同的块大小数据的写入时间,从而可以测算出到底块大小为多少时可以实现最佳的写入性能。

[root@roclinux ~]# time dd if=/dev/zero bs=1024 count=1000000 of=/root/1Gb.file
[root@roclinux ~]# time dd if=/dev/zero bs=2048 count=500000 of=/root/1Gb.file
[root@roclinux ~]# time dd if=/dev/zero bs=4096 count=250000 of=/root/1Gb.file
[root@roclinux ~]# time dd if=/dev/zero bs=8192 count=125000 of=/root/1Gb.file

2.10 利用 /dev/urandom 进行格式化

除了 /dev/null 和 /dev/zero 之外,还有一个很重要的文件,即 /dev/urandom,它是“随机数设备”,它的本领就是可以生成理论意义上的随机数。

如果我们想清除硬盘里的某些机密数据,就可以使用 /dev/urandom 这个随机数生成器来产生随机数据,写到磁盘上,以确保将磁盘原始数据完全覆盖掉。

[root@roclinux ~]# dd if=/dev/urandom of=/dev/sda

参考资料

药企,独角兽,苏州。团队长期招人,感兴趣的都可以发邮件聊聊:tiehan@sina.cn
个人公众号,比较懒,很少更新,可以在上面提问题,如果回复不及时,可发邮件给我: tiehan@sina.cn