全部博文(534)
分类: LINUX
2007-09-28 17:16:44
八、补丁部分
补丁是内核的一个补充或者修改,例如修改某些错误,增加某些功能等。
补丁的体积一般很小,但也有很大的(在后面可以看到),这是它的一个优点,下载一个几十KB的文件总比下载一个动辄几十MB 的内核源代码包要快得多
所以说补丁也不能忽视的。
要学习如何使用补丁,就必须从 diff 命令学起,因为补丁就是通过它来生成的。
1、我们先给出 diff 命令的主要选项
a)-e :ed 模式
b)-u :unified 模式
c)-i :忽略大小写
d)-s :文件相同时报告
e)-r :递归
f)-N :如果文件只存在于一方,则当成对方存在同名空文件。
g)--exclude= :排除匹配该 shell wildcard 的文件或者子目录
h)--exclude-from= :从指定文件读取 exluce 信息
i)-b :忽略空格的差异
j)-B :忽略空行的差异
k)-I :忽略指定模式的差异
l)--side-by-side :分列输出格式。
2、diff 的输出格式
diff 有5种输出格式,分别是 normal、ed、RCS、Context、Unified 。这5种各有不同,其中最常用的就是 normal 和 unified 格式,
其中 unified 格式也是内核补丁所采用的格式。它和直观,但所包含的内容也比 ed 格式或者 normal 格式的多,所以体积比较大,
特别是对于一些重大版本的升级更是如此。
下面只介绍 Normal 格式和 Unified 格式,ed 格式输出内容很少,不利于我们的阅读,但执行起来比较快
假设有两个文件 a 和 b,内容如下
CODE:
[bob@mail bob]$ cat -n a
1 ebc
2 de
3 123
4 ok1
[bob@mail bob]$ cat -n b
1 de
2 abc
3 123
4 ok
[bob@mail bob]$
下面是 Normal 格式的输出
CODE:
[bob@mail bob]$ diff a b
1d0 # 注释 :删除文件 a 的第1行 (ebc 行)
< ebc
> abc
< ok1
--- 也就是 dc → abc → 123 → ok
> ok
[bob@mail bob]$
下面是 Unified 格式的输出
CODE:
[bob@mail bob]$ diff -u a b
--- a 2007-09-20 17:23:40.000000000 +0800
+++ b 2007-09-20 17:23:41.000000000 +0800
@@ -1,4 +1,4 @@
-ebc # 注释 :删除 a 的 ebc 行
de
+abc # 注释 :在 de 后插入 abc 行
123
-ok1 # 注释 :删除 123 后的 ok1 行
+ok # 注释 :插入 ok 行
[bob@mail bob]$
上面只是把结果输出到 stdout ,你可以通过 IO 重定向把它保存起来。
3、使用diff 生成补丁
我们需要3个目录 ,分别是 :
QUOTE:
/home/bob/old :模拟开发者上的旧版本目录
/home/bobnew :模拟开发者上的新版本目录
/tmp/mine :这个是我们机器上的目录,将要更新的就是该目录下的文件
下面是生成补丁的过程
CODE:
[bob@mail bob]$ diff -Nru $(pwd)/old/ $(pwd)/new/ > new.patch
[bob@mail bob]$
[bob@mail bob]$ file new.patch
new.patch: 'diff' output text
[bob@mail bob]$
查看补丁文件 new.patch 的内容
CODE:
[bob@mail bob]$cat new.patch
diff -Nru /home/bob/old/a /home/bob/new/a
--- /home/bob/old/a 2007-09-20 23:30:43.000000000 +0800
+++ /home/bob/new/a 2007-09-20 23:30:46.000000000 +0800
@@ -1,6 +1,5 @@
-ebc
de
+abc
123
-ok1
-### tmpline
-
+ok
+# tmpline
diff -Nru /home/bob/old/b /home/bob/new/b
--- /home/bob/old/b 2007-09-21 16:07:28.000000000 +0800
+++ /home/bob/new/b 2007-09-21 16:08:05.000000000 +0800
@@ -1,3 +1,5 @@
-redhat 9
+rehdat 9
RHEL4
Windows
+CentOS
+Slackware
[bob@mail bob]$
上面有多行以 diff -Nru 开头的行,后面是 --- 和 +++ 开头的行,
对每个文件的修改都有这3行,diff -Nru 是给出生成指定文件的补丁的命令,--- 是指旧版本的文件,+++ 是指新版本的文件
可以看到补丁文件实际上就是由多个这样的块组成的。
4、下面用 new.patch 来”尝试“升级我们的文件
/tmp/mine/ 目录和 /home/bob/old/ 相比,后者就类似于发布该补丁的主机上的目录,前者就是我们想用该补丁升级的内容所在的目录
在打补丁之前需要做一件事,就是先查看补丁文件中的路径结构是否和我们的结构一致,也就是决定 -p 的值。
下面给出一个例子
CODE:
[bob@mail mine]$ head -n3 ../new.patch
diff -Nru /home/bob/old/a /home/bob/new/a
--- /home/bob/old/a 2007-09-20 23:30:43.000000000 +0800
+++ /home/bob/new/a 2007-09-20 23:30:46.000000000 +0800
[bob@mail mine]$ patch -p4 < ../new.patch --dry-run # 注释 :可以看到要指向 /tmp/mine/a,必须去掉前面的4个/ ,只剩下 ‘a’ 或者 ‘b’ 就可以
patching file a
patching file b
[bob@mail mine]$
如果使用了错误的 -p 值会怎样呢?
CODE:
[bob@mail mine]$ patch -p3 < ../new.patch --dry-run
can't find file to patch at input line 4 # 注释 :提示错误路径,因为 /tmp/mine 下没有 old/ 目录
Perhaps you used the wrong -p or --strip option?
The text leading up to this was:
--------------------------
|diff -Nru /home/bob/old/a /home/bob/new/a
|--- /home/bob/old/a 2007-09-20 23:30:43.000000000 +0800
|+++ /home/bob/new/a 2007-09-20 23:30:46.000000000 +0800
--------------------------
File to patch:
(此处按 CTRL-C )
[bob@mail mine]$
注 :建议在真正打补丁之前,都要用 --dry-run 先测试一番,以免无畏浪费时间
5、使用 new.patch ”真正“升级
[bob@mail mine]$ patch -b -p4 < ../new.patch
patching file a
patching file b
[bob@mail mine]$
[/code]
CODE:
[bob@mail mine]$ ll
total 16
-rw-rw-r-- 1 bob bob 24 Sep 21 16:
-rw-rw-r-- 1 bob bob 28 Sep 21 15:
-rw-rw-r-- 1 bob bob 40 Sep 21 16:42 b
-rw-rw-r-- 1 bob bob 23 Sep 21 16:17 b.orig
[bob@mail mine]$
可以看到有 .orig 文件存在,这是 -b 选项所造成的,-b 用于强制备份每个修改过的文件
6、查看新版本的文件的内容
CODE:
查看新的 a 、b 文件的内容
[bob@mail mine]$ cat a
de
abc
123
ok
# tmpline
[bob@mail mine]$
[bob@mail mine]$ cat b
rehdat 9
RHEL4
Windows
CentOS
Slackware
[bob@mail mine]$
是否变成了和 /home/bob/new/ 下的 a 和 b 文件一样的内容了呢 ! ^_^
7、如何撤销一个补丁
如果一个补丁我们打到一半报错了,应该怎么办呢?或者说我们发现该补丁有 bug ,想卸载它呢?
这就要用到 -R 选项了,-R 是 reverse (相反)的意思,顾名思义就是去掉之前打的补丁,回到原来的老样子
CODE:
[bob@mail mine]$ rm -f *.rej
[bob@mail mine]$
[bob@mail mine]$ patch -R -p4 < ../new.patch
patching file a
patching file b
[bob@mail mine]$
[bob@mail mine]$ cat a
ebc
de
123
ok1
### tmpline
[bob@mail mine]$ cat b
redhat 9
RHEL4
Windows
[bob@mail mine]$
可以看到 a 和 b 文件又变成原来的内容了
8、重复打补丁会怎样?
假设我们刚刚打了 new.patch ,然后又再打一次会怎样呢?
CODE:
[bob@mail mine]$ patch -b -p4 < ../new.patch
patching file a
Reversed (or previously applied) patch detected! Assume -R? [n] n
Apply anyway? [n] n
Skipping patch.
1 out of 1 hunk ignored -- saving rejects to file a.rej
patching file b
Reversed (or previously applied) patch detected! Assume -R? [n] n
Apply anyway? [n] n
Skipping patch.
1 out of 1 hunk ignored -- saving rejects to file b.rej
[bob@mail mine]$ ll
total 24
-rw-rw-r-- 1 bob bob 24 Sep 21 16:
-rw-rw-r-- 1 bob bob 28 Sep 21 15:
-rw-rw-r-- 1 bob bob 116 Sep 21 16:
-rw-rw-r-- 1 bob bob 40 Sep 21 16:42 b
-rw-rw-r-- 1 bob bob 23 Sep 21 16:17 b.orig
-rw-rw-r-- 1 bob bob 121 Sep 21 16:46 b.rej
[bob@mail mine]$
可以看到生成了.rej 文件,一旦 patch 生成了 .rej ,就意味着有某些文件无法正确地被修改。这有可能是你自己改过源文件所致