在日常的使用中,你有良好备份的习惯吗?对于一台计算机来说,备份是非常重要的。如果你的计算机遭遇了一些故障,而你没有提前备份,可能会造成很大的损失,而且这些故障何时发生是我们完全无法预知的。
对于运维专家来说,他们在做备份时总会做好最坏的打算。对于我们手头的树莓派来说,硬件设备的成本并不高,但是里面存储的数据往往是十分重要的。所以,经常备份会是一个很好的习惯。在接下来的内容里,研究一下如何使用命令行来简化备份的操作。
最简单的备份方法就是把数据复制到其他地方去,同时这也是工作量最大的一种方法。虽然这种方法听上去非常低级,但有时会很有效,所以我们在此做一定的讨论。
在使用这种方法做备份时,文件越小越好。推荐使用zip压缩技术,它的通用性可以让其他系统的用户也能方便地使用这种格式的压缩文件。如果你想要更高的压缩率,也可以选用LZMA或者bzip2,它们对应的压缩时间会比zip更长一些。
在这里创建一个可执行的脚本文件,把~/bin文件夹添加到PATH变量后,可以直接通过文件名来调用命令,如图2-15所示。
图2-15
只需要一个命令就可以完成打包与压缩的任务,如图2-16所示。
图2-16
接下来把需要备份的文件夹打包成一个压缩文件:
$ tar czvf mybackup.tgz myfolder
这里的c表示递归处理所有的子文件夹;f表示把输出重定向到mybackup.tgz;v表示把输出的详细信息打印到终端,其中会包括可能出现的错误信息。最后,z表示使用gzip进行压缩。
如果你想要解压这个tar包,就需要把命令中的x替换为c,然后去掉z,因为tar命令会自动判断压缩的类型:
$ tar xvf mybackup.tgz
tar文件类型有悠久的历史,可以一直追溯到20世纪60年代。tar包可以储存各种类型的文件信息,比如归属权以及被创建的时间。
如果想要备份你的用户主文件夹,tar命令可以很轻松地完成这个任务。如果你想要备份的数据在不同的文件夹,比如/etc以及/var/www,那么最好的办法是备份整张SD卡。
首先,你需要创建一个与整张SD卡上的数据一样大的文件。在我们的机器上,这张8GB存储量的SD卡会生成一个大约2.5GB的镜像文件。回想一下前面是如何确定盘符的,然后使用相同的方法来确定SD卡的盘符(在笔者的机器上是/dev/sdb):
$ dd bs=4M if=/dev/sdb | gzip > back-raspbian.img.gz
如果你觉得自己的硬盘空间可能不够,可以打开另一个终端,然后通过df命令来确认剩余的空间。若是检查出空间确实不够了,那么可以使用Ctrl+C结束当前的dd命令,然后使用rm命令删除已经生成的镜像文件。
现在我们已经备份好了所有的文件,如果你想要把备份后的压缩包恢复成原本的文件系统,可以输入以下命令:
$ gzip -cd back-raspbian.img.gz | dd bs=4M of=/dev/sdb
注意,在上面的命令中,dd是需要root权限的,同时在/home/pi主文件夹外保存文件也是需要root权限的。
在树莓派上,sudo命令不需要你输入密码,看似很方便,但是会有安全性上的隐患。在其他的UNIX系统上,你可以输入“sudo –s”进入一个具有完全root权限的交互环境,然后输入“exit”退出这个环境。除此以外,如果你输入的命令是一长串的复合指令,只需要在头上加一个sudo就可以了:
$ sudo bash -c "gzip -cd back-raspbian.img.gz | dd bs=4M of=/dev/sdb"
上面介绍的是在本地创建备份文件的方法。在更多的情况下,需要通过网络来存储备份文件,这时就需要用到之前讲过的SCP命令了。下面输入命令:
$ scp -p back-raspbian.img.gz pi@192.168.0.207:/home/pi/bak/
接下来你只需要输入密码就可以完成连接并且将备份内容复制过去了。如果想要改成其他的服务器怎么办?其实也很简单,只需要把pi@及后面的内容改为对应的服务器名称、IP、文件夹即可。
scp的-p选项可以保存文件上一次的访问时间,另外-P选项可以指定一个端口。在前文中,我们展示了如何设定一个固定的IP地址。这样一来,配合上USB大容量存储设备,你手上的树莓派就可以用作一个不错的备份设备,比如说可以用来存储你的影像资料。
另外,由于是通过命令行发送这些信息的,因此也可以运用一些命令行独有的高级特性,比如之前提到的正则表达式以及tab键自动补全。假设在同一个文件夹里有www-backup-20181225.gz以及data-backup-20181226.gz两个文件,下面的命令可以同时复制它们:
$ scp -p ./*backup*gz pi@192.168.0.207:/home/pi/bak/
接下来讨论如何把这些备份的过程自动化。
通常,使用scp命令可以使得在不同的设备上传输数据非常简单,如图2-17所示。
图2-17
为什么要使用远程备份?远程备份的最大好处是降低了集中式存储遭遇紧急情况从而丢失重要数据的危险性。虽然可能性很小,但是对于运维人员来说再小的风险都是需要尽量避免的。
前面讨论了ssh登录相关的内容,在使用ssh的时候,可以用ssh-keygen命令来生成一个用于登录的密钥,然后就可以免密登录了。ssh-copy-id是系统上一个用来在不同设备之间传输密钥的工具,使用范例如下:
$ ssh-copy-id pi@192.168.0.207
-i选项可以用来指定一个.pub文件,-p文件可以用来指定一个端口(在使用公网上的服务器时会很重要)。现在已经设定好远程的备份,如果设定脚本让它们经常进行备份,那么备份文件会占用大量空间。
rsync与scp一样是远程传输工具,优势是差分传输算法。具体来说,rsync只会传输发生了变化的那部分内容。这样的好处是明显的,既能够减少传输占用的带宽,又能减少备份文件占用的空间(如果你使用的是收费的服务,那么rsync可以为你省下一大笔钱)。
如果你的电脑上还没有安装rsync,那么可以通过apt-get来安装。一般来说,rsync是通过ssh协议进行传输的,但是也可以设定一个rsync后台进程,然后通过rsync:// URL的方式进行TCP传输。在后面的一种情况下,你需要设定好RSYNC_PASSWORD环境变量,或者使用--password-file手动提供密码。
虽然rsync并不是内置的bash指令,但它是非常有帮助的工具。除了rsync以外,你也可以考虑使用git这样的版本控制工具来进行远程备份。
脚本里的datestamp变量确保了备份文件不会重名。首先回到之前学过的简单指令,然后通过脚本把原先手动完成的任务自动化。除了通过管道来嵌套执行bash指令以外,还可以通过写自己的脚本文件来一次执行多条指令。接下来看一个脚本的示例。
#! /bin/sh cd /home/pi tar czf mydocsbackup.tgz Documents scp mydocsbackup.tgz pi@192.168.0.207:/home/pi/bak/
运行效果如图2-18所示。
图2-18
你可以根据实际情况修改脚本的内容,比如先把scp改为cp,然后把IP地址改成你自己的服务器地址。想要让这个脚本运行,还需要修改运行权限:
$ chmod u+x test.sh
接下来就可以通过./test.sh来运行脚本了。如果报错,那么应该再次确认自己的信息有没有填对或者是否进行了上面的ssh-copy-id操作。亲手运行一下这个脚本,你会发现每一次运行它,新的备份文件都会覆盖原有的文件,所以要做一些修改:
#! /bin/sh TODAY=$(date +"%F") cd /home/pi tar czf mydocsbackup-"$TODAY".tgz Documents scp mydocsbackup-"$TODAY".tgz pi@192.168.0.207:/home/pi/bak/
创建一个日期的变量。在命令行里试着运行一下date命令,你会发现date+“%F”会返回一个YYYY-MM-DD形式的日期。
编写完脚本后,就可以试着让它自动运行。你可以把它放到/usr/bin文件夹下,然后使用cron让它自动运行。
脚本文件的扩展性是很强的,目前这个脚本的功能还很简单,你可以试着设计更多的功能。举例来说,你可以设计一些echo语句来输出用户的状态,通过交互式的输入语句让用户手动输入备份的目录等。
关于脚本文件的编写,网络上有很多资源,同时系统上也有很多脚本编程范例。比如,之前提到过的raspi-config本身就是一个脚本文件,你可以通过阅读它的源代码来进行学习。
在编写脚本文件的过程中,要记住一个原则:循序渐进。不需要一开始就设计大量复杂的功能,而是应该从简单的设计开始,慢慢添加更多的功能模块,同时做好每个模块的测试。
在编写好代码以后,你可以使用shellcheck.net上的工具进行检查。举例来说,它会提示你把简单的cd语句替换为下面的语句:
$ cd /home/pi || exit
这样在cd出错后就能够自动退出了。在编写代码的过程中,一定要注意各种可能出错的情况,并把它们排除。
免密登录
设置好你的密钥后,就可以免密地使用scp登录远程服务器了。感兴趣的话,可以亲自动手尝试一下。
如果你看过《碟中谍》,那么你可能会对里面上级下达任务的方式印象深刻。在电影里,一个类似磁带的设备会弹出任务信息,然后立即自毁。
在信息时代,数据的安全性是非常重要的。想要安全地保护自己的隐私,就要了解硬盘是如何存储数据的,并且要知道如何安全地移除数据。
硬盘是以块的形式组织起来的,每个块的大小一般为4096KB,并且被文件系统用inode来进行寻址以及存储。现代化的SSD硬盘不再有磁头这样的设计,但是内部的组织结构还是与传统的机械硬盘类似。对于现在的硬盘处理来说,大部分操作都是通过inode来完成的,比如移动文件实际上就是通过对inode进行重命名。类似的,rm命令并不会实际把数据从硬盘上抹去,只是删除了对应数据块的inode表项。
在拿到一块新的硬盘后,执行rm –rf,看上去已经被清理干净了,实际上只是表面效果,你还可以通过对底层数据的修复来还原整个文件系统。如果你想安全地彻底清理掉某些敏感的数据,那么下面讨论的方法才是你应该使用的。
shred命令会安全地清理掉数据,可以用于某些文件或整块硬盘,如图2-19所示。
图2-19
必须提醒你要小心操作,因为它们是极具危险性的,可能会直接抹去所有的数据。
先回忆一下学过的dd命令,它可以以比特为单位重新覆盖一块硬盘上的所有数据。即使是在这样的情况下,数据依然可以被恢复。为了应对这样的问题,可以使用shred命令。它与dd做的事情是类似的,不同的是它会把这样的事情做很多遍。例如,以下命令会把文件重写5遍:
$ shred -vf -n 5 /dev/sdb
其中,-z选项表示使用随机数据而不是默认的零来进行重写,这样会生成一个看上去是真实数据的硬盘;-u选项表示在重写后把原来的数据全部删除。使用shred,你可以非常安全地清理掉自己硬盘上的数据。