目录
以下是关于在 Debian 系统上管理二进制和文本数据的工具及其相关提示。
![]() |
警告 |
---|---|
The uncoordinated write access to actively accessed devices and files from multiple processes must not be done to avoid the race condition. File locking mechanisms using flock(1) may be used to avoid it. |
The security of the data and its controlled sharing have several aspects.
存档文件的建立
远程存储访问
复制
The tracking of the modification history
The facilitation of data sharing
The prevention of unauthorized file access
The detection of unauthorized file modification
这些可以通过使用工具集来实现。
存档和压缩工具
复制和同步工具
网络文件系统
移动存储媒介
The secure shell
认证体系
版本控制系统工具
Hash and cryptographic encryption tools
以下是 Debian 系统上可用的存档和压缩工具的预览。
表 10.1. 存档和压缩工具列表
软件包 | 流行度 | 大小 | 扩展名 | 命令 | 描述 |
---|---|---|---|---|---|
tar
|
V:901, I:999 | 2770 |
.tar
|
tar(1) | 标准的归档工具(默认) |
cpio
|
V:298, I:998 | 720 |
.cpio
|
cpio(1) | Unix System V style archiver, use with find(1) |
binutils
|
V:196, I:721 | 22939 |
.ar
|
ar(1) | 创建静态库的归档工具 |
fastjar
|
V:6, I:58 | 171 |
.jar
|
fastjar(1) | Java 归档工具(类似 zip) |
pax
|
V:17, I:56 | 170 |
.pax
|
pax(1) |
新的 POSIX 归档工具,介于 tar 和 cpio 之间
|
gzip
|
V:874, I:999 | 225 |
.gz
|
gzip(1), zcat(1), … | GNU LZ77 压缩工具(默认) |
bzip2
|
V:251, I:931 | 84 |
.bz2
|
bzip2(1), bzcat(1), … | Burrows-Wheeler
block-sorting compression utility with higher compression ratio than
gzip(1)
(slower than gzip with similar syntax)
|
lzma
|
V:5, I:66 | 144 |
.lzma
|
lzma(1) | LZMA 压缩工具有着比 gzip(1) 更高的压缩率(不推荐) |
xz-utils
|
V:315, I:952 | 511 |
.xz
|
xz(1), xzdec(1), … | XZ 压缩工具有着比
bzip2(1)
更高的压缩率(压缩速度慢于 gzip 但是比 bzip2 快; LZMA 压缩工具的替代品)
|
p7zip
|
V:32, I:154 | 866 |
.7z
|
7zr(1), p7zip(1) | 有着更高压缩率的 7-zip 文件归档器(LZMA 压缩) |
p7zip-full
|
V:181, I:528 | 4215 |
.7z
|
7z(1), 7za(1) | 有着更高压缩率的 7-Zip 文件归档器(LZMA 压缩和其他) |
lzop
|
V:5, I:42 | 92 |
.lzo
|
lzop(1) | LZO compression utility with higher compression
and decompression speed than
gzip(1)
(lower compression ratio than gzip with similar syntax)
|
zip
|
V:49, I:389 | 572 |
.zip
|
zip(1) | InfoZip:DOS 归档器和压缩工具 |
unzip
|
V:318, I:790 | 506 |
.zip
|
unzip(1) | InfoZIP:DOS 解档器和解压缩工具 |
![]() |
警告 |
---|---|
除非你知道将会发生什么,否则不要设置 " |
![]() |
注意 |
---|---|
gzipped
tar(1)
归档器用于扩展名是 " |
![]() |
注意 |
---|---|
xz-compressed
tar(1)
归档器用于扩展名是 " |
![]() |
注意 |
---|---|
Popular compression method in FOSS tools such as
tar(1)
has been moving as follows: |
![]() |
注意 |
---|---|
cp(1),scp(1) 和 tar(1) 工具可能并不适用于一些特殊的文件。cpio(1) 工具的适用范围是最广的。 |
![]() |
注意 |
---|---|
cpio(1) is designed to be used with find(1) and other commands and suitable for creating backup scripts since the file selection part of the script can be tested independently. |
![]() |
注意 |
---|---|
Libreoffice 数据文件的内部结构是 " |
以下是 Debian 系统上的可用的简单复制和备份工具的预览。
表 10.2. 复制和同步工具列表
软件包 | 流行度 | 大小 | 工具 | 功能 |
---|---|---|---|---|
coreutils
|
V:876, I:999 | 14642 | GNU cp | 复制本地文件和目录("-a" 参数实现递归) |
openssh-client
|
V:544, I:995 | 3778 | scp |
复制远端文件和目录(客户端,"-r " 参数实现递归)
|
openssh-server
|
V:665, I:802 | 898 | sshd | 复制远端文件和目录(远程服务器) |
rsync
|
V:219, I:589 | 687 | - | 1-way remote synchronization and backup |
unison
|
V:5, I:20 | 2213 | - | 2-way remote synchronization and backup |
obnam
|
V:1, I:2 | 977 | - | (remote) incremental backup |
rdiff-backup
|
V:9, I:19 | 704 | - | (remote) incremental backup |
Copying files with rsync(8) offers richer features than others.
delta-transfer algorithm that sends only the differences between the source files and the existing files in the destination
quick check algorithm (by default) that looks for files that have changed in size or in last-modified time
"--exclude
" 和 "--exclude-from
" 选项类似于
tar(1)
"a trailing slash on the source directory" syntax that avoids creating an additional directory level at the destination.
![]() |
提示 |
---|---|
Execution of the |
![]() |
提示 |
---|---|
Version control system (VCS) tools in 表 10.11 “List of version control system tools” can function as the multi-way copy and synchronization tools. |
以下是用不同的工具压缩和解压缩整个 "./source
" 目录中的内容。
GNU tar(1):
$ tar -cvJf archive.tar.xz ./source $ tar -xvJf archive.tar.xz
或者,如下所示。
$ find ./source -xdev -print0 | tar -cvJf archive.tar.xz --null -F -
cpio(1):
$ find ./source -xdev -print0 | cpio -ov --null > archive.cpio; xz archive.cpio $ zcat archive.cpio.xz | cpio -i
如下是用不同的工具复制整个 "./source
" 目录中的内容。
本地复制: "./source
" 目录 → "/dest
" 目录
远程复制:本地主机上的 "./source" 目录
→
"user@host.dom
" 主机上的 "/dest
" 目录
rsync(8):
# cd ./source; rsync -aHAXSv . /dest # cd ./source; rsync -aHAXSv . user@host.dom:/dest
You can alternatively use "a trailing slash on the source directory" syntax.
# rsync -aHAXSv ./source/ /dest # rsync -aHAXSv ./source/ user@host.dom:/dest
或者,如下所示。
# cd ./source; find . -print0 | rsync -aHAXSv0 --files-from=- . /dest # cd ./source; find . -print0 | rsync -aHAXSv0 --files-from=- . user@host.dom:/dest
GNU cp(1) 和 openSSH scp(1):
# cd ./source; cp -a . /dest # cd ./source; scp -pr . user@host.dom:/dest
GNU tar(1):
# (cd ./source && tar cf - . ) | (cd /dest && tar xvfp - ) # (cd ./source && tar cf - . ) | ssh user@host.dom '(cd /dest && tar xvfp - )'
cpio(1):
# cd ./source; find . -print0 | cpio -pvdm --null --sparse /dest
你能够在所有包含 ".
" 的例子里用 "foo
" 替代
".
",这样就可以从 "./source/foo
" 目录复制文件到
"/dest/foo
" 目录。
You can substitute ".
" with the absolute path
"/path/to/source/foo
" for all examples containing
".
" to drop "cd ./source;
". These
copy files to different locations depending on tools used as follows.
"/dest/foo
":
rsync(8),
GNU
cp(1),
和
scp(1)
"/dest/path/to/source/foo
": GNU
tar(1),
和
cpio(1)
![]() |
提示 |
---|---|
rsync(8)
和 GNU
cp(1)
可以用 " |
find(1) is used to select files for archive and copy commands (see 第 10.1.3 节 “归档语法” and 第 10.1.4 节 “复制语法”) or for xargs(1) (see 第 9.3.9 节 “使用文件循环来重复一个命令”). This can be enhanced by using its command arguments.
以下是 find(1)基本语法的总结。
find 条件参数的运算规则是从左到右。
This evaluation stops once its outcome is determined.
“逻辑 OR" (由条件之间的 "-o
"
参数指定的)优先级低于 "逻辑 AND" (由
"-a
" 参数指定或者条件之间没有任何参数)。
”逻辑 NOT" (由条件前面的 "!
"
指定) 优先级高于 “逻辑 AND”。
"-prune
" always returns logical TRUE and, if it is a directory, searching of file
is stopped beyond this point.
"-name
" matches the base of the filename with shell glob
(see 第 1.5.6 节 “Shell 通配符”) but it also matches its initial
".
" with metacharacters such as "*
"
and "?
". (New POSIX feature)
"-regex
" matches the full path with emacs style BRE (see 第 1.6.2 节 “正则表达式”) as
default.
"-size
" matches the file based on the file size (value
precedented with "+
" for larger, precedented with
"-
" for smaller)
"-newer
" 参数匹配比参数名中指定的文件还要新的文件。
"-print0
" 参数总是返回逻辑 TRUE 并将完整文件名 (null
terminated) 打印到标准输出设备上。
如下是 find(1) 语法格式。
# find /path/to \ -xdev -regextype posix-extended \ -type f -regex ".*\.cpio|.*~" -prune -o \ -type d -regex ".*/\.git" -prune -o \ -type f -size +99M -prune -o \ -type f -newer /path/to/timestamp -print0
这些命令会执行如下动作。
查找 "/path/to
" 下的所有文件
Globally limit its search within its starting filesystem and uses ERE (see 第 1.6.2 节 “正则表达式”) instead
Exclude files matching regex of ".*\.cpio
" or
".*~
" from search by stop processing
Exclude directories matching regex of ".*/\.git
" from
search by stop processing
Exclude files larger than 99 Megabytes (units of 1048576 bytes) from search by stop processing
Print filenames which satisfy above search conditions and are newer than
"/path/to/timestamp
"
Please note the idiomatic use of "-prune -o
" to exclude
files in the above example.
![]() |
注意 |
---|---|
对于非 Debian 系的 Unix-like 系统,有些参数可能不被
find(1)
命令所支持。在这种情况下,应该考虑调整匹配方法并用 " |
为重要的数据存档寻找 存储设备 时,你应该注意它们的局限性。对于小型的个人数据备份,我使用品牌公司的 CD-R 和 DVD-R 然后把它放在阴凉、干燥、清洁的地方。(专业的一般使用磁带存档介质)
![]() |
注意 |
---|---|
A fire-resistant safe are meant for paper documents. Most of the computer data storage media have less temperature tolerance than paper. I usually rely on multiple secure encrypted copies stored in multiple secure locations. |
网上(主要是来源于供应商信息)可以查看存储介质的最大使用寿命。
大于100年:用墨水的无酸纸
100年:光盘存储(CD/DVD,CD/DVD-R)
30年:磁带存储(磁带,软盘)
20年:相变光盘存储(CD-RW)
这不包括由于人为导致的机械故障等等。
网上(主要来源于供应商信息)可以查看存储介质的最大的写次数。
大于250,000次:硬盘驱动器
大于10,000次:闪存
1,000次:CD/DVD-RW
1次:CD/DVD-R,纸
![]() |
小心 |
---|---|
Figures of storage life and write cycle here should not be used for decisions on any critical data storage. Please consult the specific product information provided by the manufacture. |
![]() |
提示 |
---|---|
因为 CD/DVD-R 和 纸只能写一次,它们从根本上阻止了因为重写导致的数据意外丢失。这是优点! |
![]() |
提示 |
---|---|
如果你需要更快更频繁的进行大数据备份,那么通过高速网络连接的远端主机上的硬盘来实现备份,可能是唯一可行的方法。 |
可移动存储设备可能是以下的任何一种。
它们可以通过以下的方式来进行连接。
Modern desktop environments such as GNOME and KDE can mount these removable
devices automatically without a matching "/etc/fstab
"
entry.
![]() |
提示 |
---|---|
Automounted devices may have the " |
![]() |
提示 |
---|---|
只有当这些可移动设备没有在 " |
Mount point under modern desktop environment is chosen as
"/media/<disk_label>
" which can be customized by
the following.
FAT 格式的文件系统使用 mlabel(1) 命令
ISO9660 文件系统使用带有 "-V
" 选项的
genisoimage(1)
命令
ext2/ext3/ext4 文件系统使用带有 "-L
" 选项的
tune2fs(1)
命令
![]() |
提示 |
---|---|
挂载时可能需要提供编码选项(参见 第 8.3.6 节 “文件名编码”)。 |
![]() |
提示 |
---|---|
在图形界面菜单上移除文件系统,可能会移除它的动态设备节点例如
" |
当你通过可移动存储设备与其他系统分享数据的时候,你应该先把它格式化为被两种操作系统都支持的通用的 文件系统。下面是文件系统的列表。
表 10.3. List of filesystem choices for removable storage devices with typical usage scenarios
文件系统 | 典型使用场景描述 |
---|---|
FAT12 | 软盘(<32MiB)上跨平台的数据分享 |
FAT16 | 在小硬盘(<2GiB)上的跨平台的数据分享 |
FAT32 | 在大硬盘(<8TiB,被 MS Windows95 OSR2 以上的操作系统所支持) 上的跨平台的数据分享 |
NTFS | cross platform sharing of data on the large hard disk like device (supported natively on MS Windows NT and later version, and supported by NTFS-3G via FUSE on Linux) |
ISO9660 | 在 CD-R 和 DVD+/-R 上的跨平台的静态数据分享 |
UDF | incremental data writing on CD-R and DVD+/-R (new) |
MINIX filesystem | space efficient unix file data storage on the floppy disk |
ext2 文件系统 | 在装有老旧 linux 系统的硬盘上的数据分享 |
ext3 文件系统 | 在装有老旧 linux 系统的硬盘上的数据分享 |
ext4 文件系统 | 在装有较新的 linux 系统的硬盘上的数据分享 |
![]() |
提示 |
---|---|
查看第 9.8.1 节 “Removable disk encryption with dm-crypt/LUKS”来获得关于使用设备级加密的跨平台的数据共享的信息。 |
The FAT filesystem is supported by almost all modern operating systems and is quite useful for the data exchange purpose via removable hard disk like media.
当格式化像装有 FAT 文件系统的跨平台数据共享的可移动设备时,以下应该是保险的选择。
用 fdisk(8),cfdisk(8) 或者 parted(8) 命令(参见第 9.5.2 节 “硬盘分区配置”)把它们格式化为单个的主分区并对把它做如下标记。
标记小于 2GB 的 FAT 设备为 字符"6"。
标记更大的 FAT32 设备为字符 "c"。
如下所示是用 mkfs.vfat(8) 命令格式化主分区的。
它的设备名字,例如 "/dev/sda1
" 用于 FAT16 设备
明确的选项和它的设备名,例如 "-F 32 /dev/sda1
" 用于 FAT32 设备
当使用 FAT 或 ISO9660 文件系统分享数据时,如下是需要注意的安全事项。
用 tar(1),或cpio(1)命令压缩文件,目地是为了保留文件名,符号链接,原始的文件权限和文件所有者信息。
用 split(1) 命令把压缩文件分解成若干小于 2GiB的小文件,使其免受文件大小限制。
加密压缩文件保护其内容免受未经授权的访问。
![]() |
注意 |
---|---|
因为 FAT 文件系统的设计,最大的文件大小为 |
![]() |
注意 |
---|---|
微软系统本身并不建议在超过 200MB 的分区或者驱动器上使用 FAT。他们的 " Overview of FAT, HPFS, and NTFS File Systems 这篇文章突出显示了微软系统的缺点,例如低效的磁盘空间利用。当然了,我们在 Linux 系统上还是应该使用 ext4 文件系统。 |
![]() |
提示 |
---|---|
有关文件系统和访问文件系统的更多信息,请参考 "Filesystems HOWTO"。 |
当使用网络来分享数据的时候,你应该使用通用的服务。这里有一些提示。
表 10.4. List of the network service to chose with the typical usage scenario
网络服务 | 典型使用场景描述 |
---|---|
SMB/CIFS network mounted filesystem with Samba |
通过 “Microsoft Windows 网络” 分享文件,参见
smb.conf(5)
和 官方 Samba 3.x.x 指导和参考手册(The
Official Samba 3.x.x HOWTO and Reference Guide) 或
samba-doc 软件包
|
NFS network mounted filesystem with the Linux kernel | 通过 “Unix/Linux 网络" 分享文件,参见 exports(5) 和 Linux NFS-HOWTO |
HTTP 服务 | 在 web 服务器/客户端之间分享文件 |
HTTPS 服务 | sharing file between the web server/client with encrypted Secure Sockets Layer (SSL) or Transport Layer Security (TLS) |
FTP 服务 | 在 FTP 服务器/客户端之间分享文件 |
Although these filesystems mounted over network and file transfer methods over network are quite convenient for sharing data, these may be insecure. Their network connection must be secured by the following.
我们都熟知计算机有时会出问题,或者由于人为的错误导致系统和数据损坏。备份和恢复操作是成功的系统管理中非常重要的一部分。可能有一天你的电脑就会出问题。
![]() |
提示 |
---|---|
Keep your backup system simple and backup your system often. Having backup data is more important than how technically good your backup method is. |
有3个关键的因素决定实际的备份和恢复策略。
知道要备份和恢复什么。
你自己创建的数据文件:在 "~/
" 下的数据
你使用的应用程序创建的数据文件:在 "/var/
" 下的数据(除了
"/var/cache/
","/var/run/
" 和
"/var/tmp/
")
系统配置文件:在 "/etc/
” 下的数据
本地软件:在 "/usr/local/
" 或 "/opt/
" 下的数据
System installation information: a memo in plain text on key steps (partition, …)
Proven set of data: confirmed by experimental recovery operations in advance
知道怎样去备份和恢复。
安全的数据存储:保护其免于覆盖和系统故障
经常备份:有计划的备份
Redundant backup: data mirroring
Fool proof process: easy single command backup
评估涉及的风险和成本。
Value of data when lost
备份所需的资源:人力,硬件,软件,…
Failure mode and their possibility
![]() |
注意 |
---|---|
除非你知道自己做的是什么,否则不要备份 |
至于安全的数据存储,数据至少是应该在不同的磁盘分区上最好是在不同的磁盘和机器上,来承受文件系统发生的损坏。重要的数据最好存储在只能写一次的媒介上例如 CD/DVD-R 来防止覆盖事故。(参见 第 9.7 节 “二进制数据” 怎样在 shell 命令行写入存储媒介。GNOME 桌面图形环境可以让你轻松的通过菜单:“位置 → CD/DVD 刻录”来实现写入操作。)
![]() |
注意 |
---|---|
当备份数据的时候,你可能希望停止一些应用程序的守护进程例如 MTA(参见第 6.3 节 “Mail transport agent (MTA)”)。 |
![]() |
注意 |
---|---|
你应该格外小心地备份和恢复身份认证相关的数据文件例如 " |
![]() |
注意 |
---|---|
If you run a cron job as a user process, you must restore files in
" |
以下是 Debian 系统上值得注意的实用备份程序套件的列表。
表 10.5. 实用备份程序套件列表
软件包 | 流行度 | 大小 | 说明 |
---|---|---|---|
dump
|
V:1, I:7 | 341 | 4.4 BSD dump(8) 和 restore(8) 命令用于 ext2/ext3/ext4 文件系统 |
xfsdump
|
V:0, I:11 | 810 | dump and restore with xfsdump(8) and xfsrestore(8) for XFS filesystem on GNU/Linux and IRIX |
backupninja
|
V:3, I:4 | 277 | lightweight, extensible meta-backup system |
sbackup
|
V:0, I:0 | 488 | 用于 GNOME 桌面的简单备份套件 |
bacula-common
|
V:9, I:20 | 1276 | Bacula: 网络数据备份,恢复和核查-常见的支持文件 |
bacula-client
|
I:6 | 157 | Bacula: 网络数据备份,恢复和核查-客户端元软件包 |
bacula-console
|
V:2, I:7 | 64 | Bacula: 网络数据备份,恢复和核查-文本终端 |
bacula-server
|
I:2 | 160 | Bacula: 网络数据备份,恢复和核查-服务器端元软件包 |
amanda-common
|
V:1, I:3 | 7417 | Amanda: 马里兰大学开发的高级自动化网络磁盘归档器(库) |
amanda-client
|
V:1, I:2 | 996 | Amanda: 马里兰大学开发的高级自动化网络磁盘归档器(客户端) |
amanda-server
|
V:0, I:0 | 1045 | Amanda: 马里兰大学开发的高级自动化网络磁盘归档器(服务器端) |
backuppc
|
V:4, I:5 | 2232 | BackupPC 是用于备份 PC 机数据(基于磁盘)的高性能的企业级工具 |
backup-manager
|
V:1, I:2 | 543 | 命令行备份工具 |
backup2l
|
V:1, I:1 | 113 | low-maintenance backup/restore tool for mountable media (disk based) |
备份工具有各自的专用的用途。
Mondo Rescue is a backup system to facilitate restoration of complete system quickly from backup CD/DVD etc. without going through normal system installation processes.
sbackup
和 keep
软件包提供了易于桌面用户使用的 GUI
前端,用于定期备份用户数据。同样的功能可以通过一个简单的脚本(第 10.2.2 节 “一个系统备份的脚本例子”)和
cron(8)
来实现。
第 10.1.1 节 “存档和压缩工具” 和 第 10.1.2 节 “复制和同步工具” 描述的基础工具能够通过自定义脚本来帮助系统备份。这些脚本的功能可以通过如下的工具来增强。
obnam
软件包能够增量备份(远程)。
rdiff-backup
软件包能够增量备份(远程)。
The dump
package helps to archive and restore the whole
filesystem incrementally and efficiently.
![]() |
提示 |
---|---|
参见 " |
对于运行 unstable
套件的个人 Debian
桌面系统来说,只需要保护个人数据和关键数据。我不管怎样每年都会重新安装一次系统。因此没理由去备份整个系统或者安装全功能的备份实用程序。
我使用简单的脚本来制作用于备份的压缩文件并用 GUI 界面把它烧写到 CD/DVD 里。以下是关于这个的脚本例子。
#!/bin/sh -e # Copyright (C) 2007-2008 Osamu Aoki <osamu@debian.org>, Public Domain BUUID=1000; USER=osamu # UID and name of a user who accesses backup files BUDIR="/var/backups" XDIR0=".+/Mail|.+/Desktop" XDIR1=".+/\.thumbnails|.+/\.?Trash|.+/\.?[cC]ache|.+/\.gvfs|.+/sessions" XDIR2=".+/CVS|.+/\.git|.+/\.svn|.+/Downloads|.+/Archive|.+/Checkout|.+/tmp" XSFX=".+\.iso|.+\.tgz|.+\.tar\.gz|.+\.tar\.bz2|.+\.cpio|.+\.tmp|.+\.swp|.+~" SIZE="+99M" DATE=$(date --utc +"%Y%m%d-%H%M") [ -d "$BUDIR" ] || mkdir -p "BUDIR" umask 077 dpkg --get-selections \* > /var/lib/dpkg/dpkg-selections.list debconf-get-selections > /var/cache/debconf/debconf-selections { find /etc /usr/local /opt /var/lib/dpkg/dpkg-selections.list \ /var/cache/debconf/debconf-selections -xdev -print0 find /home/$USER /root -xdev -regextype posix-extended \ -type d -regex "$XDIR0|$XDIR1" -prune -o -type f -regex "$XSFX" -prune -o \ -type f -size "$SIZE" -prune -o -print0 find /home/$USER/Mail/Inbox /home/$USER/Mail/Outbox -print0 find /home/$USER/Desktop -xdev -regextype posix-extended \ -type d -regex "$XDIR2" -prune -o -type f -regex "$XSFX" -prune -o \ -type f -size "$SIZE" -prune -o -print0 } | cpio -ov --null -O $BUDIR/BU$DATE.cpio chown $BUUID $BUDIR/BU$DATE.cpio touch $BUDIR/backup.stamp
这是一个用 root 权限执行的脚本例子。
我建议你按照如下所示的去更改和执行这个脚本。
编辑这个脚本使其能够覆盖到你所有的重要数据(参见第 10.1.5 节 “查找文件的语法” 和 第 10.2 节 “备份和恢复”)。
用 "find ...-newer $BUDIR/backup.stamp -print0
" 替代
"find ...-print0
" 来实现增量备份。
为保险起见,使用 scp(1) 或 rsync(1) 命令来备份文件到远端 或者把它们烧写到 CD/DVD 里。(我使用 GNOME 桌面 GUI 来烧写 CD/DVD。参见 第 12.1.8 节 “zenity 的 shell 脚本案例” 来获得更多的信息。)
把事情简单化!
![]() |
提示 |
---|---|
You can recover debconf configuration data with
" |
对于目录树下面的数据集,"cp -a
" 命令可以实现常规备份。
For the set of large non-overwritten static data under a directory tree such
as the one under the "/var/cache/apt/packages/
"
directory, hardlinks with "cp -al
" provide an alternative
to the normal backup with efficient use of the disk space.
以下是一个用于数据备份的名为 bkup
的复制脚本。它把当前目录下的所有 (non-VCS)
文件复制到父目录下的指定目录中或者远程主机上。
#!/bin/sh -e # Copyright (C) 2007-2008 Osamu Aoki <osamu@debian.org>, Public Domain fdot(){ find . -type d \( -iname ".?*" -o -iname "CVS" \) -prune -o -print0;} fall(){ find . -print0;} mkdircd(){ mkdir -p "$1";chmod 700 "$1";cd "$1">/dev/null;} FIND="fdot";OPT="-a";MODE="CPIOP";HOST="localhost";EXTP="$(hostname -f)" BKUP="$(basename $(pwd)).bkup";TIME="$(date +%Y%m%d-%H%M%S)";BU="$BKUP/$TIME" while getopts gcCsStrlLaAxe:h:T f; do case $f in g) MODE="GNUCP";; # cp (GNU) c) MODE="CPIOP";; # cpio -p C) MODE="CPIOI";; # cpio -i s) MODE="CPIOSSH";; # cpio/ssh t) MODE="TARSSH";; # tar/ssh r) MODE="RSYNCSSH";; # rsync/ssh l) OPT="-alv";; # hardlink (GNU cp) L) OPT="-av";; # copy (GNU cp) a) FIND="fall";; # find all A) FIND="fdot";; # find non CVS/ .???/ x) set -x;; # trace e) EXTP="${OPTARG}";; # hostname -f h) HOST="${OPTARG}";; # user@remotehost.example.com T) MODE="TEST";; # test find mode \?) echo "use -x for trace." esac; done shift $(expr $OPTIND - 1) if [ $# -gt 0 ]; then for x in $@; do cp $OPT $x $x.$TIME; done elif [ $MODE = GNUCP ]; then mkdir -p "../$BU";chmod 700 "../$BU";cp $OPT . "../$BU/" elif [ $MODE = CPIOP ]; then mkdir -p "../$BU";chmod 700 "../$BU" $FIND|cpio --null --sparse -pvd ../$BU elif [ $MODE = CPIOI ]; then $FIND|cpio -ov --null | ( mkdircd "../$BU"&&cpio -i ) elif [ $MODE = CPIOSSH ]; then $FIND|cpio -ov --null|ssh -C $HOST "( mkdircd \"$EXTP/$BU\"&&cpio -i )" elif [ $MODE = TARSSH ]; then (tar cvf - . )|ssh -C $HOST "( mkdircd \"$EXTP/$BU\"&& tar xvfp - )" elif [ $MODE = RSYNCSSH ]; then rsync -aHAXSv ./ "${HOST}:${EXTP}-${BKUP}-${TIME}" else echo "Any other idea to backup?" $FIND |xargs -0 -n 1 echo fi
This is meant to be command examples. Please read script and edit it by yourself before using it.
![]() |
提示 |
---|---|
I keep this |
![]() |
提示 |
---|---|
For making snapshot history of a source file tree or a configuration file tree, it is easier and space efficient to use git(7) (see 第 10.6.5 节 “记录配置历史的 Git”). |
数据安全基础设施是数据加密,讯息摘要和签名工具的结合。
表 10.6. 数据安全基础工具列表
软件包 | 流行度 | 大小 | 命令 | 说明 |
---|---|---|---|---|
gnupg
|
V:614, I:998 | 1960 | gpg(1) | GNU 隐私卫士 - OpenPGP 加密和签名工具 |
gpgv
|
V:866, I:999 | 615 | gpgv(1) | GNU 隐私卫士 - 签名验证工具 |
paperkey
|
V:0, I:1 | 39 | paperkey(1) | extract just the secret information out of OpenPGP secret keys |
cryptsetup
|
V:20, I:71 | 343 | cryptsetup(8), … | utilities for dm-crypto block device encryption supporting LUKS |
ecryptfs-utils
|
V:5, I:9 | 393 | ecryptfs(7), … | utilities for ecryptfs stacked filesystem encryption |
coreutils
|
V:876, I:999 | 14642 | md5sum(1) | 计算与校验 MD5 讯息摘要 |
coreutils
|
V:876, I:999 | 14642 | sha1sum(1) | 计算与校验 SHA1 讯息摘要 |
openssl
|
V:777, I:988 | 1248 | openssl(1ssl) |
compute message digest with "openssl dgst " (OpenSSL)
|
See 第 9.8 节 “数据加密提示” on dm-crypto and ecryptfs which implement automatic data encryption infrastructure via Linux kernel modules.
如下是 GNU 隐私卫士 基本的钥匙管理命令。
表 10.7. GNU 隐私卫士钥匙管理命令的列表
命令 | 说明 |
---|---|
gpg --gen-key
|
产生一个新的钥匙对 |
gpg --gen-revoke my_user_ID
|
generate revoke key for my_user_ID |
gpg --edit-key user_ID
|
edit key interactively, "help" for help |
gpg -o file --export
|
把所有的钥匙输出到文件 |
gpg --import file
|
import all keys from file |
gpg --send-keys user_ID
|
发送 user_ID 的公钥到公钥服务器 |
gpg --recv-keys user_ID
|
recv. key of user_ID from keyserver |
gpg --list-keys user_ID
|
列出 user_ID 的所有钥匙 |
gpg --list-sigs user_ID
|
list sig. of user_ID |
gpg --check-sigs user_ID
|
check sig. of user_ID |
gpg --fingerprint user_ID
|
检查 user_ID 的指纹 |
gpg --refresh-keys
|
update local keyring |
Here is the meaning of the trust code.
表 10.8. List of the meaning of the trust code
code | description of trust |
---|---|
-
|
no owner trust assigned / not yet calculated |
e
|
trust calculation failed |
q
|
not enough information for calculation |
n
|
never trust this key |
m
|
marginally trusted |
f
|
fully trusted |
u
|
ultimately trusted |
如下命令上传我的 "1DD8D791
" 公钥到主流的公钥服务器
"hkp://keys.gnupg.net
"。
$ gpg --keyserver hkp://keys.gnupg.net --send-keys 1DD8D791
A good default keyserver set up in "~/.gnupg/gpg.conf
"
(or old location "~/.gnupg/options
") contains the
following.
keyserver hkp://keys.gnupg.net
The following obtains unknown keys from the keyserver.
$ gpg --list-sigs --with-colons | grep '^sig.*\[User ID not found\]' |\ cut -d ':' -f 5| sort | uniq | xargs gpg --recv-keys
There was a bug in OpenPGP Public Key
Server (pre version 0.9.6) which corrupted key with more than 2
sub-keys. The newer gnupg
(>1.2.1-2) package can
handle these corrupted subkeys. See
gpg(1)
under "--repair-pks-subkey-bug
" option.
Here are examples for using GNU Privacy Guard commands on files.
表 10.9. List of GNU Privacy Guard commands on files
命令 | 说明 |
---|---|
gpg -a -s file
|
sign file into ASCII armored file.asc |
gpg --armor --sign file
|
同上 |
gpg --clearsign file
|
clear-sign message |
gpg --clearsign file|mail foo@example.org
|
mail a clear-signed message to foo@example.org
|
gpg --clearsign --not-dash-escaped patchfile
|
clear-sign patchfile |
gpg --verify file
|
verify clear-signed file |
gpg -o file.sig -b file
|
create detached signature |
gpg -o file.sig --detach-sig file
|
同上 |
gpg --verify file.sig file
|
verify file with file.sig |
gpg -o crypt_file.gpg -r name -e file
|
public-key encryption intended for name from file to binary crypt_file.gpg |
gpg -o crypt_file.gpg --recipient name --encrypt file
|
同上 |
gpg -o crypt_file.asc -a -r name -e file
|
public-key encryption intended for name from file to ASCII armored crypt_file.asc |
gpg -o crypt_file.gpg -c file
|
symmetric encryption from file to crypt_file.gpg |
gpg -o crypt_file.gpg --symmetric file
|
同上 |
gpg -o crypt_file.asc -a -c file
|
symmetric encryption intended for name from file to ASCII armored crypt_file.asc |
gpg -o file -d crypt_file.gpg -r name
|
decryption |
gpg -o file --decrypt crypt_file.gpg
|
同上 |
Add the following to "~/.muttrc
" to keep a slow GnuPG
from automatically starting, while allowing it to be used by typing
"S
" at the index menu.
macro index S ":toggle pgp_verify_sig\n" set pgp_verify_sig=no
The gnupg
plugin let you run GnuPG transparently for
files with extension ".gpg
", ".asc
",
and ".ppg
".
# aptitude install vim-scripts vim-addon-manager $ vim-addons install gnupg
md5sum(1) provides utility to make a digest file using the method in rfc1321 and verifying each file with it.
$ md5sum foo bar >baz.md5 $ cat baz.md5 d3b07384d113edec49eaa6238ad5ff00 foo c157a79031e1c40f85931829bc5fc552 bar $ md5sum -c baz.md5 foo: OK bar: OK
![]() |
注意 |
---|---|
The computation for the MD5 sum is less CPU intensive than the one for the cryptographic signature by GNU Privacy Guard (GnuPG). Usually, only the top level digest file is cryptographically signed to ensure data integrity. |
这里有许多源代码合并工具。如下的是我感兴趣的工具。
表 10.10. 源代码合并工具列表
软件包 | 流行度 | 大小 | 命令 | 说明 |
---|---|---|---|---|
diffutils
|
V:850, I:975 | 1319 | diff(1) | 逐行比较两个文件 |
diffutils
|
V:850, I:975 | 1319 | diff3(1) | compare and merges three files line by line |
vim
|
V:112, I:391 | 2366 | vimdiff(1) | 在 vim 中并排比较两个文件 |
patch
|
V:104, I:937 | 191 | patch(1) | 给原文件打补丁 |
dpatch
|
V:1, I:18 | 191 | dpatch(1) | manage series of patches for Debian package |
diffstat
|
V:23, I:190 | 65 | diffstat(1) | produce a histogram of changes by the diff |
patchutils
|
V:21, I:182 | 223 | combinediff(1) | create a cumulative patch from two incremental patches |
patchutils
|
V:21, I:182 | 223 | dehtmldiff(1) | extract a diff from an HTML page |
patchutils
|
V:21, I:182 | 223 | filterdiff(1) | extract or excludes diffs from a diff file |
patchutils
|
V:21, I:182 | 223 | fixcvsdiff(1) | fix diff files created by CVS that patch(1) mis-interprets |
patchutils
|
V:21, I:182 | 223 | flipdiff(1) | exchange the order of two patches |
patchutils
|
V:21, I:182 | 223 | grepdiff(1) | show which files are modified by a patch matching a regex |
patchutils
|
V:21, I:182 | 223 | interdiff(1) | show differences between two unified diff files |
patchutils
|
V:21, I:182 | 223 | lsdiff(1) | show which files are modified by a patch |
patchutils
|
V:21, I:182 | 223 | recountdiff(1) | recompute counts and offsets in unified context diffs |
patchutils
|
V:21, I:182 | 223 | rediff(1) | fix offsets and counts of a hand-edited diff |
patchutils
|
V:21, I:182 | 223 | splitdiff(1) | separate out incremental patches |
patchutils
|
V:21, I:182 | 223 | unwrapdiff(1) | demangle patches that have been word-wrapped |
wiggle
|
V:0, I:0 | 166 | wiggle(1) | apply rejected patches |
quilt
|
V:5, I:46 | 710 | quilt(1) | manage series of patches |
meld
|
V:13, I:42 | 3022 | meld(1) | compare and merge files (GTK) |
dirdiff
|
V:0, I:2 | 144 | dirdiff(1) | display differences and merge changes between directory trees |
docdiff
|
V:0, I:0 | 573 | docdiff(1) | compare two files word by word / char by char |
imediff2
|
V:0, I:0 | 34 | imediff2(1) | interactive full screen 2-way merge tool |
makepatch
|
V:0, I:0 | 102 | makepatch(1) | generate extended patch files |
makepatch
|
V:0, I:0 | 102 | applypatch(1) | apply extended patch files |
wdiff
|
V:6, I:88 | 643 | wdiff(1) | display word differences between text files |
The following procedures extract differences between two source files and
create unified diff files "file.patch0
" or
"file.patch1
" depending on the file location.
$ diff -u file.old file.new > file.patch0 $ diff -u old/file new/file > file.patch1
The diff file (alternatively called patch file) is used to send a program update. The receiving party applies this update to another file by the following.
$ patch -p0 file < file.patch0 $ patch -p1 file < file.patch1
Here is a summary of the version control systems (VCS) on the Debian system.
![]() |
注意 |
---|---|
If you are new to VCS systems, you should start learning with Git, which is growing fast in popularity. |
表 10.11. List of version control system tools
软件包 | 流行度 | 大小 | 工具 | VCS type | 描述 |
---|---|---|---|---|---|
cssc
|
V:0, I:2 | 2012 | CSSC | local | clone of the Unix SCCS (deprecated) |
rcs
|
V:5, I:25 | 547 | RCS | local | "Unix SCCS done right" |
cvs
|
V:7, I:63 | 4124 | CVS | remote | previous standard remote VCS |
subversion
|
V:44, I:168 | 4743 | Subversion | remote | "CVS done right", the new de facto standard remote VCS |
git
|
V:246, I:413 | 27879 | Git | distributed | fast DVCS in C (used by the Linux kernel and others) |
mercurial
|
V:14, I:65 | 205 | Mercurial | distributed | DVCS in Python and some C |
bzr
|
V:5, I:24 | 71 | Bazaar | distributed |
DVCS influenced by tla written in Python (used by Ubuntu)
|
darcs
|
V:0, I:8 | 36373 | Darcs | distributed | DVCS with smart algebra of patches (slow) |
tla
|
V:0, I:8 | 912 | GNU arch | distributed | DVCS mainly by Tom Lord (Historic) |
monotone
|
V:0, I:0 | 5815 | Monotone | distributed | DVCS in C++ |
tkcvs
|
V:0, I:1 | 1400 | CVS, … | remote | GUI display of VCS (CVS, Subversion, RCS) repository tree |
gitk
|
V:8, I:51 | 1383 | Git | distributed | GUI display of VCS (Git) repository tree |
VCS is sometimes known as revision control system (RCS), or software configuration management (SCM).
Distributed VCS such as Git is the tool of choice these days. CVS and Subversion may still be useful to join some existing open source program activities.
Debian provides free VCS services via Debian Alioth service. It supports practically all VCSs. Its documentation can be found at http://wiki.debian.org/Alioth .
There are few basics for creating a shared access VCS archive.
使用 "umask 002
" (参见 第 1.2.4 节 “控制新建文件的权限:umask”)
Make all VCS archive files belonging to a pertinent group
Enable set group ID on all VCS archive directories (BSD-like file creation scheme, see 第 1.2.3 节 “文件系统权限”)
Make user sharing the VCS archive belonging to the group
Here is an oversimplified comparison of native VCS commands to provide the big picture. The typical command sequence may require options and arguments.
表 10.12. Comparison of native VCS commands
Git | CVS | Subversion | 功能 |
---|---|---|---|
git init
|
cvs init
|
svn create
|
create the (local) repository |
- |
cvs login
|
- | login to the remote repository |
git clone
|
cvs co
|
svn co
|
check out the remote repository as the working tree |
git pull
|
cvs up
|
svn up
|
update the working tree by merging the remote repository |
git add .
|
cvs add
|
svn add
|
add file(s) in the working tree to the VCS |
git rm
|
cvs rm
|
svn rm
|
remove file(s) in working tree from the VCS |
- |
cvs ci
|
svn ci
|
commit changes to the remote repository |
git commit -a
|
- | - | commit changes to the local repository |
git push
|
- | - | update the remote repository by the local repository |
git status
|
cvs status
|
svn status
|
display the working tree status from the VCS |
git diff
|
cvs diff
|
svn diff
|
diff <reference_repository> <working_tree> |
git repack -a -d; git prune
|
- | - | repack the local repository into single pack |
gitk
|
tkcvs
|
tkcvs
|
GUI display of VCS repository tree |
![]() |
小心 |
---|---|
Invoking a |
![]() |
提示 |
---|---|
If there is a executable file |
![]() |
提示 |
---|---|
GUI tools such as tkcvs(1) and gitk(1) really help you with tracking revision history of files. The web interface provided by many public archives for browsing their repositories is also quite useful, too. |
![]() |
提示 |
---|---|
Git can work directly with different VCS repositories such as ones provided
by CVS and Subversion, and provides the local repository for local changes
with |
![]() |
提示 |
---|---|
Git has commands which have no equivalents in CVS and Subversion: "fetch", "rebase", "cherry-pick", … |
Git 可以用来做本地和远程源代码管理的任何事情。这意味着,你能够在本地记录源代码修改,而不是必须要和远程仓库有网络连接。
你可以在 "~/.gitconfig
" 里面设置几个 Git
接下来需要使用的全局配置,比如说你的名字和电子邮件地址。
$ git config --global user.name "姓名" $ git config --global user.email 电子邮件地址
如果你习惯使用 CVS 或 Subversion 命令,你也许希望设置如下几个命令别名。
$ git config --global alias.ci "commit -a" $ git config --global alias.co checkout
你能够通过如下方式检查你的全局配置:
$ git config --global --list
参见下面内容。
man 手册: git(1)
(/usr/share/doc/git-doc/git.html
)
Git 用户手册
(/usr/share/doc/git-doc/user-manual.html
)
git 介绍教程
(/usr/share/doc/git-doc/gittutorial.html
)
git 介绍教程:第二部
(/usr/share/doc/git-doc/gittutorial-2.html
)
GIT 每一天 20个左右的命令
(/usr/share/doc/git-doc/everyday.html
)
CVS 用户用 git
(/usr/share/doc/git-doc/gitcvs-migration.html
)
描述了怎样搭建服务,以及如何把老的数据从 CVS 迁移到 Git。
Git 魔术
(/usr/share/doc/gitmagic/html/index.html
)
git-gui(1) 和 gitk(1) 命令使 Git 变得非常容易使用。
![]() |
警告 |
---|---|
不要使用带空格的标签字符串。即使一些工具,如
gitk(1)
允许你使用它,但会阻碍其它 |
即使你的上游使用不同的版本控制系统,使用 git(1) 作为本地活动的版本控制系统,仍然是一个好的主意,因为 git 可以让你在没有上游网络连接的情况下,管理你的本地源代码树拷贝。这里有一些 git(1) 使用的包和命令。
表 10.13. git 相关包和命令列表
软件包 | 流行度 | 大小 | 命令 | 说明 |
---|---|---|---|---|
git-doc
|
I:20 | 10308 | N/A | Git 官方文档 |
gitmagic
|
I:2 | 719 | N/A | "Git 魔术",易于理解的 Git 手册 |
git
|
V:246, I:413 | 27879 | git(7) | Git 快速、可扩展、分布式的版本控制系统 |
gitk
|
V:8, I:51 | 1383 | gitk(1) | 有历史功能的 Git 图形仓库浏览器 |
git-gui
|
V:2, I:29 | 2079 | git-gui(1) | Git 图形界面(无历史功能) |
git-svn
|
V:2, I:30 | 922 | git-svnimport(1) | 从 Subversion 导出数据,导入到 Git |
git-svn
|
V:2, I:30 | 922 | git-svn(1) | 在 Subversion 和 Git 之间提供双向操作 |
git-cvs
|
V:0, I:13 | 1045 | git-cvsimport(1) | 从 CVS 导出数据,导入到 Git |
git-cvs
|
V:0, I:13 | 1045 | git-cvsexportcommit(1) | export a commit to a CVS checkout from Git |
git-cvs
|
V:0, I:13 | 1045 | git-cvsserver(1) | Git 的 CVS 服务模拟器 |
git-email
|
V:0, I:13 | 725 | git-send-email(1) | 从 Git 用电子邮件发送收集到的补丁 |
stgit
|
V:0, I:1 | 1692 | stg(1) | 封装的 git (Python) |
git-buildpackage
|
V:2, I:12 | 3784 | git-buildpackage(1) | 用 Git 自动制作 Debian 包 |
guilt
|
V:0, I:0 | 147 | guilt(7) | 封装的 git (SH/AWK/SED/…) |
![]() |
提示 |
---|---|
With
git(1),
you work on a local branch with many commits and use something like
" |
![]() |
提示 |
---|---|
When you want to go back to a clean working directory without loosing the
current state of the working directory, you can use " |
你可以把一个在 "svn+ssh://svn.example.org/project/module/trunk
"
的 Subversion 仓库检出到一个本地的 Git 仓库,使用"./dest
"目录,并把修改提交回
Subversion 仓库。
$ git svn clone -s -rHEAD svn+ssh://svn.example.org/project dest $ cd dest ... 进行修改 $ git commit -a ... 继续在本地用 git 工作 $ git svn dcommit
![]() |
提示 |
---|---|
使用 " |
你可以使用 Git
工具来手工记录按时间先后顺序的配置历史。这里是一个例子,让你练习记录"/etc/apt/
" 内容。
$ cd /etc/apt/ $ sudo git init $ sudo chmod 700 .git $ sudo git add . $ sudo git commit -a
提交配置,描述此次提交。
对配置文件进行修改。
$ cd /etc/apt/ $ sudo git commit -a
提交配置,说明提交,继续你的工作。
$ cd /etc/apt/ $ sudo gitk --all
你有全部的配置历史。
![]() |
注意 |
---|---|
sudo(8)
是需要用于配置数据文件,任意文件权限的情况。 对于普通用户的配置数据,你需要省略 |
![]() |
注意 |
---|---|
在上面例子里的 " |
![]() |
提示 |
---|---|
要更加完整的建立配置历史记录,请参阅 |
参见下面内容。
cvs(1)
"/usr/share/doc/cvs/html-cvsclient
"
"/usr/share/doc/cvs/html-info
"
"/usr/share/doc/cvsbook
"
"info cvs
"
The following configuration allows commits to the CVS repository only by a
member of the "src
" group, and administration of CVS only
by a member of the "staff
" group, thus reducing the
chance of shooting oneself.
# cd /var/lib; umask 002; mkdir cvs # export CVSROOT=/srv/cvs/project # cd $CVSROOT # chown root:src . # chmod 2775 . # cvs -d $CVSROOT init # cd CVSROOT # chown -R root:staff . # chmod 2775 . # touch val-tags # chmod 664 history val-tags # chown root:src history val-tags
![]() |
提示 |
---|---|
You may restrict creation of new project by changing the owner of
" |
The default CVS repository is pointed by "$CVSROOT
". The
following sets up "$CVSROOT
" for the local access.
$ export CVSROOT=/srv/cvs/project
Many public CVS servers provide read-only remote access to them with account
name "anonymous
" via pserver service. For example,
Debian web site contents are maintained by webwml project via CVS at Debian alioth
service. The following sets up "$CVSROOT
" for the remote
access to this CVS repository.
$ export CVSROOT=:pserver:anonymous@anonscm.debian.org:/cvs/webwml $ cvs login
![]() |
注意 |
---|---|
Since pserver is prone to eavesdropping attack and insecure, write access is usually disable by server administrators. |
The following sets up "$CVS_RSH
" and
"$CVSROOT
" for the remote access to the CVS repository by
webwml project with SSH.
$ export CVS_RSH=ssh $ export CVSROOT=:ext:account@cvs.alioth.debian.org:/cvs/webwml
You can also use public key authentication for SSH which eliminates the remote password prompt.
Create a new local source tree location at
"~/path/to/module1
" by the following.
$ mkdir -p ~/path/to/module1; cd ~/path/to/module1
Populate a new local source tree under
"~/path/to/module1
" with files.
Import it to CVS with the following parameters.
Module name: "module1
"
Vendor tag: "Main-branch
" (tag for the entire branch)
Release tag: "Release-initial
" (tag for a specific
release)
$ cd ~/path/to/module1 $ cvs import -m "Start module1" module1 Main-branch Release-initial $ rm -Rf . # optional
CVS does not overwrite the current repository file but replaces it with
another one. Thus, write permission to the repository directory is
critical. For every new module for "module1
" in
repository at "/srv/cvs/project
", run the following to
ensure this condition if needed.
# cd /srv/cvs/project # chown -R root:src module1 # chmod -R ug+rwX module1 # chmod 2775 module1
Here is an example of typical work flow using CVS.
Check all available modules from CVS project pointed by
"$CVSROOT
" by the following.
$ cvs rls CVSROOT module1 module2 ...
Checkout "module1
" to its default directory
"./module1
" by the following.
$ cd ~/path/to $ cvs co module1 $ cd module1
Make changes to the content as needed.
Check changes by making "diff -u [repository] [local]
"
equivalent by the following.
$ cvs diff -u
You find that you broke some file "file_to_undo
" severely
but other files are fine.
Overwrite "file_to_undo
" file with the clean copy from
CVS by the following.
$ cvs up -C file_to_undo
Save the updated local source tree to CVS by the following.
$ cvs ci -m "Describe change"
Create and add "file_to_add
" file to CVS by the
following.
$ vi file_to_add $ cvs add file_to_add $ cvs ci -m "Added file_to_add"
Merge the latest version from CVS by the following.
$ cvs up -d
Watch out for lines starting with "C filename
" which
indicates conflicting changes.
Look for unmodified code in ".#filename.version
".
Search for "<<<<<<<
" and
">>>>>>>
" in files for conflicting
changes.
Edit files to fix conflicts as needed.
Add a release tag "Release-1
" by the following.
$ cvs ci -m "last commit for Release-1" $ cvs tag Release-1
Edit further.
Remove the release tag "Release-1
" by the following.
$ cvs tag -d Release-1
Check in changes to CVS by the following.
$ cvs ci -m "real last commit for Release-1"
Re-add the release tag "Release-1
" to updated CVS HEAD of
main by the following.
$ cvs tag Release-1
Create a branch with a sticky branch tag
"Release-initial-bugfixes
" from the original version
pointed by the tag "Release-initial
" and check it out to
"~/path/to/old
" directory by the following.
$ cvs rtag -b -r Release-initial Release-initial-bugfixes module1 $ cd ~/path/to $ cvs co -r Release-initial-bugfixes -d old module1 $ cd old
![]() |
提示 |
---|---|
Use " |
Work on this local source tree having the sticky tag
"Release-initial-bugfixes
" which is based on the original
version.
Work on this branch by yourself … until someone else joins to this
"Release-initial-bugfixes
" branch.
Sync with files modified by others on this branch while creating new directories as needed by the following.
$ cvs up -d
Edit files to fix conflicts as needed.
Check in changes to CVS by the following.
$ cvs ci -m "checked into this branch"
Update the local tree by HEAD of main while removing sticky tag
("-A
") and without keyword expansion
("-kk
") by the following.
$ cvs up -d -kk -A
Update the local tree (content = HEAD of main) by merging from the
"Release-initial-bugfixes
" branch and without keyword
expansion by the following.
$ cvs up -d -kk -j Release-initial-bugfixes
Fix conflicts with editor.
Check in changes to CVS by the following.
$ cvs ci -m "merged Release-initial-bugfixes"
Make archive by the following.
$ cd .. $ mv old old-module1-bugfixes $ tar -cvzf old-module1-bugfixes.tar.gz old-module1-bugfixes $ rm -rf old-module1-bugfixes
![]() |
提示 |
---|---|
" |
![]() |
提示 |
---|---|
You can checkout only a sub directory of " |
表 10.14. Notable options for CVS commands (use as first argument(s) to cvs(1))
option | 说明 |
---|---|
-n
|
dry run, no effect |
-t
|
display messages showing steps of cvs activity |
To get the latest files from CVS, use "tomorrow
" by the
following.
$ cvs ex -D tomorrow module_name
Add module alias "mx
" to a CVS project (local server) by
the following.
$ export CVSROOT=/srv/cvs/project $ cvs co CVSROOT/modules $ cd CVSROOT $ echo "mx -a module1" >>modules $ cvs ci -m "Now mx is an alias for module1" $ cvs release -d .
Now, you can check out "module1
" (alias:
"mx
") from CVS to "new
" directory by
the following.
$ cvs co -d new mx $ cd new
![]() |
注意 |
---|---|
In order to perform above procedure, you should have appropriate file permissions. |
When you checkout files from CVS, their execution permission bit is retained.
Whenever you see execution permission problems in a checked out file,
e.g. "filename
", change its permission in the
corresponding CVS repository by the following to fix it.
# chmod ugo-x filename
Subversion is a recent-generation version control system replacing older CVS. It has most of CVS's features except tags and branches.
You need to install subversion
,
libapache2-svn
and subversion-tools
packages to set up a Subversion server.
Currently, the subversion
package does not set up a
repository, so one must set it up manually. One possible location for a
repository is in "/srv/svn/project
".
Create a directory by the following.
# mkdir -p /srv/svn/project
Create the repository database by the following.
# svnadmin create /srv/svn/project
If you only access Subversion repository via Apache2 server, you just need to make the repository only writable by the WWW server by the following.
# chown -R www-data:www-data /srv/svn/project
Add (or uncomment) the following in
"/etc/apache2/mods-available/dav_svn.conf
" to allow
access to the repository via user authentication.
<Location /project> DAV svn SVNPath /srv/svn/project AuthType Basic AuthName "Subversion repository" AuthUserFile /etc/subversion/passwd <LimitExcept GET PROPFIND OPTIONS REPORT> Require valid-user </LimitExcept> </Location>
Create a user authentication file with the command by the following.
# htpasswd2 -c /etc/subversion/passwd some-username
Restart Apache2.
Your new Subversion repository is accessible at URL
"http://localhost/project
" and
"http://example.com/project
" from
svn(1)
(assuming your URL of web server is
"http://example.com/
").
The following sets up Subversion repository for the local access by a group,
e.g. project
.
# chmod 2775 /srv/svn/project # chown -R root:src /srv/svn/project # chmod -R ug+rwX /srv/svn/project
Your new Subversion repository is group accessible at URL
"file:///localhost/srv/svn/project
" or
"file:///srv/svn/project
" from
svn(1)
for local users belonging to project
group. You must run
commands, such as svn
, svnserve
,
svnlook
, and svnadmin
under
"umask 002
" to ensure group access.
A group accessible Subversion repository is at URL
"example.com:/srv/svn/project
" for SSH, you can access it
from
svn(1)
at URL "svn+ssh://example.com:/srv/svn/project
".
Many projects uses directory tree similar to the following for Subversion to compensate its lack of branches and tags.
----- module1 | |-- branches | |-- tags | | |-- release-1.0 | | `-- release-2.0 | | | `-- trunk | |-- file1 | |-- file2 | `-- file3 | `-- module2
![]() |
提示 |
---|---|
You must use " |
Create a new local source tree location at
"~/path/to/module1
" by the following.
$ mkdir -p ~/path/to/module1; cd ~/path/to/module1
Populate a new local source tree under
"~/path/to/module1
" with files.
Import it to Subversion with the following parameters.
Module name: "module1
"
Subversion site URL: "file:///srv/svn/project
"
Subversion directory: "module1/trunk
"
Subversion tag: "module1/tags/Release-initial
"
$ cd ~/path/to/module1 $ svn import file:///srv/svn/project/module1/trunk -m "Start module1" $ svn cp file:///srv/svn/project/module1/trunk file:///srv/svn/project/module1/tags/Release-initial
或者,如下所示。
$ svn import ~/path/to/module1 file:///srv/svn/project/module1/trunk -m "Start module1" $ svn cp file:///srv/svn/project/module1/trunk file:///srv/svn/project/module1/tags/Release-initial
![]() |
提示 |
---|---|
You can replace URLs such as " |
Here is an example of typical work flow using Subversion with its native client.
![]() |
提示 |
---|---|
Client commands offered by the |
Check all available modules from Subversion project pointed by URL
"file:///srv/svn/project
" by the following.
$ svn list file:///srv/svn/project module1 module2 ...
Checkout "module1/trunk
" to a directory
"module1
" by the following.
$ cd ~/path/to $ svn co file:///srv/svn/project/module1/trunk module1 $ cd module1
Make changes to the content as needed.
Check changes by making "diff -u [repository] [local]
"
equivalent by the following.
$ svn diff
You find that you broke some file "file_to_undo
" severely
but other files are fine.
Overwrite "file_to_undo
" file with the clean copy from
Subversion by the following.
$ svn revert file_to_undo
Save the updated local source tree to Subversion by the following.
$ svn ci -m "Describe change"
Create and add "file_to_add
" file to Subversion by the
following.
$ vi file_to_add $ svn add file_to_add $ svn ci -m "Added file_to_add"
Merge the latest version from Subversion by the following.
$ svn up
Watch out for lines starting with "C filename
" which
indicates conflicting changes.
Look for unmodified code in, e.g., "filename.r6
",
"filename.r9
", and "filename.mine
".
Search for "<<<<<<<
" and
">>>>>>>
" in files for conflicting
changes.
Edit files to fix conflicts as needed.
Add a release tag "Release-1
" by the following.
$ svn ci -m "last commit for Release-1" $ svn cp file:///srv/svn/project/module1/trunk file:///srv/svn/project/module1/tags/Release-1
Edit further.
Remove the release tag "Release-1
" by the following.
$ svn rm file:///srv/svn/project/module1/tags/Release-1
Check in changes to Subversion by the following.
$ svn ci -m "real last commit for Release-1"
Re-add the release tag "Release-1
" from updated
Subversion HEAD of trunk by the following.
$ svn cp file:///srv/svn/project/module1/trunk file:///srv/svn/project/module1/tags/Release-1
Create a branch with a path
"module1/branches/Release-initial-bugfixes
" from the
original version pointed by the path
"module1/tags/Release-initial
" and check it out to
"~/path/to/old
" directory by the following.
$ svn cp file:///srv/svn/project/module1/tags/Release-initial file:///srv/svn/project/module1/branches/Release-initial-bugfixes $ cd ~/path/to $ svn co file:///srv/svn/project/module1/branches/Release-initial-bugfixes old $ cd old
![]() |
提示 |
---|---|
Use " |
Work on this local source tree pointing to branch
"Release-initial-bugfixes
" which is based on the original
version.
Work on this branch by yourself … until someone else joins to this
"Release-initial-bugfixes
" branch.
Sync with files modified by others on this branch by the following.
$ svn up
Edit files to fix conflicts as needed.
Check in changes to Subversion by the following.
$ svn ci -m "checked into this branch"
Update the local tree with HEAD of trunk by the following.
$ svn switch file:///srv/svn/project/module1/trunk
Update the local tree (content = HEAD of trunk) by merging from the
"Release-initial-bugfixes
" branch by the following.
$ svn merge file:///srv/svn/project/module1/branches/Release-initial-bugfixes
Fix conflicts with editor.
Check in changes to Subversion by the following.
$ svn ci -m "merged Release-initial-bugfixes"
Make archive by the following.
$ cd .. $ mv old old-module1-bugfixes $ tar -cvzf old-module1-bugfixes.tar.gz old-module1-bugfixes $ rm -rf old-module1-bugfixes
![]() |
提示 |
---|---|
You can replace URLs such as " |
![]() |
提示 |
---|---|
You can checkout only a sub directory of " |
表 10.15. Notable options for Subversion commands (use as first argument(s) to svn(1))
option | 说明 |
---|---|
--dry-run
|
dry run, no effect |
-v
|
display detail messages of svn activity |