鸟哥的 Linux 私房菜 - 离线包

鸟哥的 Linux 私房菜
为取得较佳浏览结果，请爱用 firefox 浏览本网页

目录
最近更新日期：2011/12/11
大家好，我是彼岸！ 这本书，我从网上下载了好多版本，其中这个版本是最新最全的。 好像是一位叫minchao的网友提供了2009.10.12离线下载包，然后一位叫bigjar的网友整理得来的。 谢谢他们的无私贡献。。 我发现原来的文件字体显示不正常，看起来很别扭，就修改了一下。。 如果有什么不好的地方请大家多多指教！^_^

1. 快速索引
2. 基础文件
3. 架站文件
4. 企业运用
5. 我的共享空间：http://www.dbank.com/share/beeanggx


鸟哥的 Linux 私房菜 -- 快速连结索引

为取得较佳浏览结果，请爱用 firefox 浏览本网页
鸟哥的 Linux 私房菜馆 | 目录 | Linux 基础文件 | Linux 架站文件 | Linux 企业运用 | 安全管理 | 新手讨论 |

基础学习篇快速索引
为了方便读者可以快速的找到自己想要查询的指令功能与相关用语说明，底下建立的就是一些指令速查表啰！

大标题的图示 指令与用语速查表
A B C D E F G H I J K L M N O P Q R S T U W X Y 其他

指令与用语 | 相关连结
A
ACL | 第十四章、3.1
alias | 第十一章、3.1
anacron | 第十六章、4.1
apropos | 第五章、3.1
array | 第十一章、2.6
at | 第十六章、2.2
atq, atrm | 第十六章、2.2
auditd | 第十七章、5.5
audit2why | 第十七章、5.5
awk | 第十二章、4.2
B
badblocks | 第八章、3.3
basename | 第七章、2.3
bash | 第十一章 第五章、2.1
bashrc | 第十一章、4.3
batch | 第十六章、2.2
bg | 第十七章、2.2
BIOS vs CMOS | 第零章、2.6
bc | 第五章、2.2
block | 第八章、1.3
boot loader | 第二十章、1.2
bzip2, bzcat | 第九章、2.3
C
cal | 第五章、2.2
case | 第十三章、4.2
cat | 第七章、3.1
cd | 第七章、1.2
cdrecord | 第九章、5.2
chage | 第十四章、2.1
chattr | 第七章、4.2
chcon | 第十七章、5.4
chfn | 第十四章、2.2
chgrp | 第六章、2.2
chkconfig | 第十八章、4.2
chkfontpath | 第二十四章、2.2
chmod | 第六章、2.2
chown | 第六章、2.2
chpasswd | 第十四章、7.1
chroot | 第二十章、4.5
chsh | 第十四章、2.2
CISC | 第零章、1.2
cmp | 第十二章、4.3
col | 第十一章、6.4
compress | 第九章、2.1
cp | 第七章、2.2
cpio | 第九章、6.2
crontab | 第十六章、3.1
cups | 第二十一章、2.0
cut | 第十一章、6.1
D
date | 第五章、2.2 第十三章、2.1
dd | 第八章、5.2 第九章、6.1
declare | 第十一章、2.6
depmod | 第二十章、2.1
device.map | 第二十章、4.3
df | 第八章、2.1
diff | 第十二章、4.3
dirname | 第七章、2.3
dmesg | 第十七章、3.4
dos2unix | 第十章、4.2
du | 第八章、2.1
dump | 第九章、4.0
dumpe2fs | 第八章、1.3
E
e2label | 第八章、3.5
echo | 第十一章、2.2
edquota | 第十五章、1.5
env | 第十一章、2.3
expand | 第十一章、6.4
export | 第十一章、2.3
EXT2 filesystem | 第八章、1.3
F
fc-cache, fc-list | 第二十四章、2.2
fdisk | 第八章、3.1
fg | 第十七章、2.2
free | 第八章、5.1 第十七章、3.4
file | 第七章、4.4
find | 第七章、5.2
finger | 第十四章、2.2
FHS | 第一章、2.6 第六章、3.1
fsck | 第八章、3.3
fstab | 第八章、4.1
function | 第十三章、4.3
fuser | 第十七章、4.3
G
gcc | 第二十二章、2.4
getenforce | 第十七章、5.3
getsebool | 第十七章、5.6
getfacl | 第十四章、3.3
GNU | 第一章、1.3
GNU GPL | 第一章、1.2
gpasswd | 第十四章、2.3
grep | 第十一章、6.1 第十二章、2.2
group | 第十四章、1.3
groupadd | 第十四章、2.3
groupdel | 第十四章、2.3
groupmod | 第十四章、2.3
groups | 第十四章、1.3
grub | 第二十章、3.0 第二十章、3.4
grub-install | 第二十章、3.4
grub-md5-crypt | 第二十章、3.8
gtf | 第二十四章、2.3
gzip, zcat | 第九章、2.2
H
hal | 第二十一章、3.4
Hardware support | 第三章、1.2
hdparm | 第八章、3.5
head | 第七章、3.3
history | 第十一章、3.2
I
iconv | 第十章、4.3
id | 第十四章、2.2
if | 第十三章、4.1
info | 第五章、3.2
init | 第五章、5.0 第二十章、1.3 第二十章、1.9
initrd | 第二十章、3.3
inode | 第八章、1.3
insmod | 第二十章、2.3
iostat | 第二十一章、3.1
issue | 第十一章、4.2
J
jobs | 第十七章、2.2
join | 第十一章、6.4
journaling filesystem | 第八章、1.5
K
kill | 第十七章、2.2 第十七章、3.2
killall | 第十七章、3.2
L
LANG | 第五章、2.1 第十章、4.1 第十二章、2.1
last | 第十四章、6.1
lastlog | 第十四章、6.1
ldconfig | 第二十二章、5.2
ldd | 第十八章、3.1 第二十二章、5.3
less | 第七章、3.2
link (hard, symbolic) | 第八章、2.2
Linux distributions | 第一章、2.6
Linux 核心版本 | 第一章、2.5
lm_sensors | 第二十一章、3.0
ln | 第八章、2.2
locale | 第十一章、2.4
locate | 第七章、5.2
login-shell | 第十一章、4.3
logrotate | 第十九章、3.0
logwatch | 第十九章、4.1
lp | 第二十一章、2.6
lpadmin | 第二十一章、2.6
lpq | 第二十一章、2.6
lpr | 第二十一章、2.6
lprm | 第二十一章、2.6
lpstat | 第二十一章、2.6
ls, ll | 第七章、2.1
lsattr | 第七章、4.2
LSB | 第一章、2.6
lsb_release | 第六章、3.4
lsmod | 第二十章、2.2
lsof | 第十七章、4.3
lspci | 第二十一章、3.1
lsusb | 第二十一章、3.1
LVM | 第十五章、3.0
lvcreate, lvscan, lvdisplay lvextend, lvreduce lvremove, lvresize | 第十五章、3.2
M
mail | 第十一章、2.1 第十四章、6.3
make | 第二十二章、1.3
makefile | 第二十二章、3.2
man | 第五章、3.1
MBR | 第三章、2.4
md5sum | 第二十二章、6.1
mdadm | 第十五章、2.3
mdadm.conf | 第十五章、2.5
mesg | 第十四章、6.2
menu.list | 第二十章、3.2
mkdir | 第七章、1.2
mke2fs | 第八章、3.2
mkfs | 第八章、3.2
mkinitrd | 第二十章、3.3
mknod | 第八章、3.5
mkisofs | 第九章、5.1
mkswap | 第八章、5.1
modinfo | 第二十章、2.2
modprobe | 第二十章、2.3
more | 第七章、3.2
motd | 第十一章、4.2
mount (含常用参数) | 第八章、3.4
mount (remount) | 第八章、3.4
mount (vfat, 中文) | 第八章、3.4
mount (--bind) | 第八章、3.4
mount (option) | 第八章、4.1
mount (loop) | 第八章、4.2
mv | 第七章、2.2
N
nano | 第五章、4.0
netstat | 第十七章、3.4
newgrp | 第十四章、1.3
nice | 第十七章、3.3
nl | 第七章、3.1
nohup | 第十七章、2.3
nologin | 第十四章、5.1
non-login-shell | 第十一章、4.3
ntsysv | 第十八章、4.2
O
od | 第七章、3.4
P
PAM | 第十四章、5.1
parted | 第八章、6.3
partition table | 第三章、2.3
partprobe | 第八章、3.1
passwd | 第十四章、1.2 第十四章、2.1
paste | 第十一章、6.4
patch | 第十二章、4.3 第二十二章、4.5
PATH | 第七章、1.3 第十一章、4.1
permission | 第六章、2.1
pidof | 第十七章、4.3
pr | 第十二章、4.4
printf | 第十二章、4.1
profile | 第十一章、4.3
ps | 第十七章、3.1
pstree | 第十七章、3.1
pvscan, pvcreate pvdisplay, pvremove | 第十五章、3.2
pwck | 第十四章、7.1
pwconv | 第十四章、7.1
pwd | 第七章、1.2
pwunconv | 第十四章、7.1
Q
quota | 第十五章、1.0 第十五章、1.6
quotacheck | 第十五章、1.4
quotaoff | 第十五章、1.5
quotaon | 第十五章、1.5
R
RAID | 第十五章、2.1
read | 第十一章、2.6 第十三章、2.1
reboot, halt, poweroff | 第五章、5.0
renice | 第十七章、3.3
repquota | 第十五章、1.6
resize2fs | 第十五章、3.3
restore | 第九章、4.0
restorecon | 第十七章、5.4
RISC | 第零章、1.2
rm | 第七章、2.2
rmdir | 第七章、1.2
rmmod | 第二十章、2.3
rpm | 第二十三章、1.0 第二十三章、2.0
rpmbuild | 第二十三章、3.0
rsync | 第十八章、2.2
runlevel | 第二十章、1.3 第二十章、1.9
S
SBIT | 第七章、4.4
sealert | 第十七章、5.5
securetty | 第十四章、5.4
sed | 第十二章、2.5
seinfo | 第十七章、5.6
semanage | 第十七章、5.6
sensors | 第二十一章、3.3
sensors-detect | 第二十一章、3.3
service | 第十八章、1.3
sesearch | 第十七章、5.6
sestatus | 第十七章、5.3
set | 第十一章、2.3 第十一章、4.4
setenforce | 第十七章、5.3
setfacl | 第十四章、3.3
setquota | 第十五章、1.7
setroubleshoot | 第十七章、5.5
setsebool | 第十七章、5.6
setup | 第二十一章、1.0
SGID | 第七章、4.4
shadow | 第十四章、1.2
sha1sum | 第二十二章、6.1
shells | 第十一章、1.3
shift | 第十三章、3.3
shutdown | 第五章、5.0
signal | 第十七章、3.2
sort | 第十一章、6.2
source (.) | 第十一章、4.3
split | 第十一章、6.5
stand alone daemon | 第十八章、1.1
startx | 第五章、1.4 第二十四章、1.3
su | 第十四章、4.1
sudo | 第十四章、4.2
SUID | 第七章、4.4
super block | 第八章、1.3 第八章、6.1
syslog | 第十九章、2.0
super daemon | 第十八章、1.1
swapoff | 第八章、5.1
swapon | 第八章、5.1
sync | 第五章、5.0
T
[tab]/[ctrl]-c/[ctrl]-d | 第五章、2.3 第十一章、1.4
tac | 第七章、3.1
tail | 第七章、3.3
tar | 第九章、3.0
TCP Wrappers | 第十八章、3.2
tee | 第十一章、6.3
test | 第十三章、3.1
time modification time(mtime) status time(ctime) access time(atime) | 第七章、3.5
top | 第十七章、3.1
touch | 第七章、3.5
tr | 第十一章、6.4
tty1 ~ tty7 | 第五章、1.4
tune2fs | 第八章、3.5
type | 第十一章、1.5
U
udev | 第二十一章、3.4
ulimit | 第十一章、2.7 第十四章、5.5
umask | 第七章、4.1
umount | 第八章、3.4
unalias | 第十一章、3.1
uname | 第十七章、3.4
uniq | 第十一章、6.2
UNIX | 第一章、1.2
unix2dos | 第十章、4.2
unset | 第十一章、2.2
updatedb | 第七章、5.2
uptime | 第十七章、3.4
useradd | 第十四章、2.1
userdel | 第十四章、2.1
usermod | 第十四章、2.1
V
VFS | 第八章、1.8
vgcreate, vgscan, vgdisplay vgextend, vgreduce, vgchange vgremove | 第十五章、3.2
vim 按键说明 | 第十章、2.2
.vimrc | 第十章、3.4
visudo | 第十四章、4.2
vmstat | 第十七章、3.4
W
w, who | 第十四章、6.1
wall | 第十四章、6.2
warnquota | 第十五章、1.7
wc | 第十一章、6.2
whatis | 第五章、3.1
whereis | 第七章、5.2
which | 第七章、5.1
write | 第十四章、6.2
X
xargs | 第十一章、6.5
xinetd, xinetd.conf | 第十八章、2.1
xinit | 第二十四章、1.3
xorg.conf | 第二十四章、2.1
X window system | 第二十四章、1.0
Y
yum | 第二十三章、4.0
其他
; && || | 第十一章、5.2
$? | 第十一章、2.3
& | 第十七章、2.2
绝对路径与相对路径 | 第六章、3.3 第七章、1.1
磁碟重组 | 第八章、1.2
变数 | 第十一章、2.1
变数设定规则 | 第十一章、2.2
万用字元 | 第十一章、4.5
资料流重导向 | 第十一章、5.1
管线命令 (pipe) | 第十一章、6.0

本网页主要以 firefox 配合解析度 1024x768 作为设计依据
http://linux.vbird.org is designed by VBird during 2001-2009. Aerosol Lab.


鸟哥的 Linux 私房菜 -- 伺服器篇--作者序

为取得较佳浏览结果，请爱用 firefox 浏览本网页

作者再版序
切换解析度为 800x600
最近更新日期：2007/03/01
大标题的图示 初版序：
笔者在 2002 年底写完了‘鸟哥的 Linux 私房菜 -- 基础学习篇’以来， 接到很多朋友们的鼓励，很感谢大家的支持呐！另外也有很多的来信要鸟哥将接下来的伺服器架设篇赶紧给他写一写， 其实鸟哥也觉得应该早点将架站篇的内容也给他完成的，这样才能够连贯的起来啊！不过， 架站篇比起基础篇来说，说实在的，要复杂的很多！怎么说呢？如果说 ‘架站篇’就单纯的讲架站流程，呵呵！ 那么随便几个钟头就可以将好几个不同的伺服器的架设方法写完了，因为这些架设的方法都有资料可以参考，而且， Linux 本身就有极为丰富的说明文件了！所以说，如果架站篇只是写架设的流程，鸟哥实在觉得不够过瘾～

而且，网站的架设其实由网站成立之初的规划开始，到实际硬碟的分割 ( partition )，软体的选择与安装，架设完成之后的后续监测与维护，还有那个挺重要的备份工作等等， 其实是需要‘一贯作业程序’的，什么是 ‘一贯’作业程序呢？其实就是上面所有的工作都需要 ‘全部一起搭配来思考’的意思，您不能单纯的只想到某个比较重要的地方而已。

举个例子来说好了，假如您想要架设一个给学生使用的档案伺服器 ( File Server, 一般使用 SAMBA )，那么在架设之前，您想到，嘿嘿！学生数很多，所以我的硬碟要很大，也因此，您就在 Linux 上面安装了一款 120 GB 的硬碟，然后，很高兴的将硬碟分割为‘只有 / + Swap ’这样的懒人分割法。等到实际上机运作之后，却发现有的学生占用了主机硬碟好几 GB 的空间，使得其他同学无法使用主机所提供的档案服务！等到发现这样的情况，要再加以使用 Quota 解决的时候，却发现当初硬碟规划的不好(因为只有 / 啊！)，使得无法进行较佳的 quota 设定。还有，备份也成了一个大问题，因为没有多余的额外空间来存放备份资料了～ 这样可以了解一贯作业程序了吧？！是的！您必需要视自己的需要来规划主机，并且规划的时候， 就需要从头到尾的做一个整体的设计了呢！

这些整体搭配的架设网站流程，其实都是网站架设者所需要进行的工作，不过， 目前大家常见的书籍在这方面谈的都不多，而大多纯粹的讲一些技巧性的架站手法，嗯！ 这样的书籍也是有需要的啦！不过，鸟哥认为，如果可以谈的更深入一点， 将网站从架设之前所需要考虑的事情以及架设完成后的后续工作都一起谈进去的话， 那么对于网站维护者来说，应该会有一个比较容易入门的管理与维护方法的认识吧！ 所以啰，这一本书的内容，除了基本的网站架设流程之外， 还会谈到许多的网路基础概念、网站的相关维护技巧以及鸟哥平时维护主机时所认为较佳的维护经验谈。
大标题的图示 再版序：
笔者在去年 (2006/03) 修改完基础篇第二版后，很多朋友来信问到那么伺服器篇是否也需要修改呢？ 本来鸟哥觉得这个伺服器篇并没有什么需要修改的地方，尤其第一版已经谈过很多基础协定的介绍， 虽然写的并不好，不过，应该符合大部分朋友们的需求了。然而伺服器篇第一版的内容由于基于较旧的 Red Hat 9 作业系统来撰写的，因此很多伺服器软体的设定鸟哥是以 Tarball 的方式来进行安装与设定， 这在当时应该是个不错的选择。

不过时至今日，由于各家 Linux distributions 的线上升级与支援时限都有很不错的改进， 包括 RHEL, SuSE, Ubuntu 等都已经支援完善的线上升级，且支援时限都可达数年之久， 在这样的条件下，使用 Tarball 来安装设定伺服器软体，就有点说不过去了！ 因为人都是有惰性的，如果能够让咱们的 Linux server 自动升级与自动维护伺服器软体， 那不是省时又省力吗？

因此，在这个伺服器篇第二版当中，鸟哥几乎完全使用 Linux distributions 所提供的软体与机制来进行伺服器的设定， 当然啰，基础的概念还是会加以强调的！如此一来朋友们还是可以读到一些网路协定的基础概念， 并且可以很轻松的就搞定您的伺服器软体，而不需要下载一堆 Tarball 的原始码来安装了！

由于这次改版的幅度其实也不小，例如拿掉 sendmail 主要改以 postfix 这个邮件伺服器软体来说明， 拿掉比较不常用的 wu-ftpd 与 proftpd ，改以 vsftpd 来说明。碍于篇幅有限，因此这一版的内容拿掉了 proxy server, apt server 等等，这是考虑到这本书主要是给小型企业想要利用单部 Linux 主机来进行网站架设的缘故。 未来如果有机会且有时间，鸟哥或许会将其余的伺服器以企业使用的角度来谈一谈呢！^_^

大标题的图示 谁适合这本书：
这本书既然是谈论比较深入的架站规划、流程、技巧与维护等工作，那么比较基础的 Linux 操作与相关的 Shell 语法，在这本书里面就不可能谈论的很多，毕竟， Linux 基础篇 已经完成了，没有必要在这本书里面再次的重复提及的。 所以，当您尝试阅读这本书的时候，请注意，您最好已经具备有 Linux 作业系统的相关知识，以及文字介面 ( BASH Shell ) 的相关技巧，还有，必需要能够了解一些 Unix-Like 的工作流程，例如登录档的产生与放置的地点、服务的启动与关闭方式、 工作排程的使用方法、以及其他种种相关的事项。也就是说，如果您从未接触过 Linux ，那么建议您由‘鸟哥的 Linux 私房菜 -- 基础学习篇’开始 Linux 的探索历程，否则，这本书对您而言，可能会过于难以理解。

另外，这本书的内容很多时候会提到一些简单的概念而不是僵化的流程， 尤其每个人对于网站的要求都不相同，也就是说，每个人的网站其实都是带有个人风格的， 因此僵化的流程并没有太大的意义～只要能够依据这些简单的概念来进行网站的架设，鸟哥认为， 您的主机设定应该都不会有太大的问题。怕的是什么呢？都没有碰过 Linux ，却想直接参考架站的程序来完成网站的架设的朋友，这些朋友最容易忽略后续的维护与管理了！ 这也容易造成网站的不稳定或者是造成被网路怪客 ( Cracker ) 入侵的问题啊！

这本书主要的目的是引导使用者进入 Linux 强大的网路功能的世界， 书内的范例都是鸟哥自己实际测试过没有问题才写上来的，不过，毕竟每个人的网路环境与操作习惯都不相同， 因此，鸟哥不敢说我书内的范例一定可以在您的系统上操作成功的！ 然而，书内都会提到一些基本概念的问题，只要理解这些基本的概念，并且对于 Linux 的操作熟悉，相信您一定可以利用书内的范例来开发出适合您自己的伺服器设定的！不过，对于没有碰过 Linux 的朋友，还是建议从头学起，至于为什么一定得从头学起，在本书的第一章内会仔细谈论喔。
大标题的图示 章节安排：
本书在章节的规划上面，主要分为三大部分，分别是‘网路基础篇’、 ‘简易防火措施篇’与‘伺服器架设篇’，前两篇的所有内容与‘伺服器架设篇’都具有很高的相关性， 所以，您在开始伺服器的架设之前，请务必将前面两篇共十二章先念过一遍才好呐！

在‘网路基础篇’当中，我们会介绍简易的网路基础， 这包含了硬体的选择与布线。此外，还有在 Linux 上面连上 Internet 的方法，以及在 Linux 发生无法连接网际网路的问题时，简易的查验方法。 看完了这一篇之后，您的 Linux 不论以何种方式来进行 Internet 的连接，就应该都不成问题啰，而且，鸟哥希望看完这一篇之后，您可以了解 Linux 的网路问题，并自行解决喔！

在‘简易防火措施篇’中，我们会简单的介绍 Linux 的强大网路功能下，可能会发生的网路入侵问题。 接下来，了解了问题后，当然就是需要来解决他啰！所以，我们会就 TCP/IP, port, 套件漏洞的修补与防火墙等来推敲一下，该如何做好 Linux 主机的防备呢？ ‘没有永远安全的主机’是正确的言论，所以， 即使您的主机只是一个小小的网站，也千万不能忽略这个防火墙的认识喔！

在‘伺服器架设篇’当中，我们会介绍 WWW, dns, mail, ftp, dhcp, samba.....等等的伺服器，在这一篇内的文章您就可以跳着看了！ 因为不想玩的伺服器，当然就不需要去看他啊！唯一一个例外的就是 DNS 伺服器 ( 领域名称伺服器 ) 啰， DNS 是所有伺服器能否正常工作的基础，因此，您虽然不需要架设 DNS 伺服器，但是得了解 DNS 的整体运作流程呢！

章节的安排主要仍然是由浅入深来进行编排的，因此，还是希望读者们可以由前面慢慢的往下看， 不要着急的直接翻到后面去抄一些架设流程喔！而且，几乎每一章节后面都会具有一些简单的课后练习题， 这些练习题有的是鸟哥参加过的考试内容，有的是鸟哥想到的一些资料，很适合大家思考喔！ 不要错过这些练习题的训练喔！

大标题的图示 感谢：
这本书是由网站资料整理来的，网站的内容其实受惠于很多前辈的指点， 这也是这本书能够成册的原因，很感谢许多网路上的大哥前辈的帮忙，包括： Netman、ZMAN、小州、梁枫、沙易蔡大哥、果正兄等，鸟站讨论区的伙伴们：日京三子、Jou、James Wu、HaWay、 DR、bono、thyme、wilson、老妖怪等版主群们，酷学园的伙伴们：sakana、ericshei、black_cat、Darkhero、lzy、 damon、duncan、逸晨、Jerry Wu、哈克、twu2等等，当然还有更多不及备载的朋友们的协助， 感谢您们的扶持！此外，当然还有更多的读者们的支持，没有大家的支持，就没有鸟哥的私房菜啊！

在写作的过程当中是快乐的，但是当松懈下来后，过日子的生活多亏了数十年老友们：士杰、玉南、景阳、耀东以及 Honda 夫妇、宓志夫妇、大维夫妇的鼓励； 家人俊明、秀明、瑞明帮忙打点家里的事情，让鸟哥无后顾之忧来全心处理自己的工作； 多亏邱爸爸与邱妈妈一家人对我的照应，否则生活白痴的鸟哥肯定无法过活！ 还要感谢昆山科大资传系的世熙主任与维珍小姐，让鸟哥的工作更加顺利；以及感谢成大环工510研究室的伙伴们，尤其是乙原， 谢谢你老是听我发牢骚！最要感谢女友慧真在身边帮我打理所有的杂务，让单工思考的鸟哥得以不必花脑筋在其他的事物上。 最后，仅将这本书献给我所有的朋友以及读者们，感谢你们的支持与鼓励！鸟哥会继续努力的！

鸟哥 2007/03/01

另外，关于本书的戡误资讯，请参考：
  • http://linux.vbird.org/book/
    • 2003/07/14：第一次完成日期！
    2003/09/18：加入一些说明，尤其是各个伺服器的简介。a
    2007/03/01：取消各个伺服器的简介，太占篇幅了！修改初版序的内容，增加再版序的部分。
    2007/03/01：初版序我将他拿到 这里
    2003/07/14以来统计人数


鸟哥的 Linux 私房菜 -- 基础学习篇

为取得较佳浏览结果，请爱用 firefox 浏览本网页
鸟哥的 Linux 私房菜馆 | Linux 基础文件 | Linux 架站文件 | Linux 企业运用 | 安全管理 | 新手讨论 |

鸟哥的 Linux 私房菜 -- 基础学习篇目录
底下的几篇文章是学习Linux的基础文件，这些文件是基础中的基础，如果您能将其中的文件都看完并且消化过，那么未来在管理 Linux主机以及架设网站方面，就能够达到‘事半功倍’的成效，请不要忽略这部份了！否则，再怎么讨论都是枉然的啦！^_^。 因为Linux的资料非常的多，每份资料彼此的相关性都很强，要单独的一项一项讲解并不容易， 所以底下的文件该怎么看呢？建议先按照顺序将内容大致浏览过一次，看不懂的地方也可以先略过不要紧。 全部看完之后，再从头开始‘仔细’的实际操作过一遍，那应该就能够进入Linux的世界啰～

另外，每篇文章底下的日期，指的是重大改版日期而非最新日期，每篇文章的最新日期请以该篇文章最下方的工作日志为主；

第一部份：Linux的规划与安装
第二部份：Linux档案、目录与磁碟格式
第三部份：学习Shell与Shell Scripts
第四部份：Linux使用者管理
第五部份：Linux系统管理员
第六部份：其他备份文章
    这部份包括了早期的Red Hat 6.x以及
    鸟哥写的一、二版的基础篇各章节文章汇整！
第一部份 Linux 的规划与安装
常常听到Linux具有非常优良的血统，所以具有相当良好的多人多工环境，可以方便程式设计师来开发软体。 此外，Linux本身是不用钱的‘自由软体’，使用上面并没有所谓的‘盗版’问题。但是，为什么Linux不用钱？ 随便修改或发布Linux为什么不会被罚？为什么Linux有这么多的版本？包括Fedora, SuSE, CentOS, Debian等等？ 这个都是我们必须要来了解的部分！了解这些部分，你才会对Linux有一个正确的理解，才能够跟你的同事、同学、 上司说明，为什么使用Linux具有很多优点与好处！ ^_^

Linux并不好学习，鸟哥也是‘重伤’过好几次才能对Linux有一些基础的认知。那么到底应该如何学习Linux呢？关键在实作。 既然要实作就得要实际的安装一部Linux，那么Linux要安装前需要熟悉哪些基础观念？计算机概论是非常重要的一环！ 因为Linux与硬体的关系还不小～此外，打造一台Windows/Linux共存的主机也是很有用的， 至少对于需要多平台但又缺乏空间与金钱的朋友来说，这样的处理是非常有用的！

在第一篇里面，我们会由计算机概论谈起，再讲到Linux的历史渊源与自由软体的关系，然后重点在于如何规划硬体与Linux安装， 最后谈到如何登入与使用Linux图形/文字介面的环境。本篇资料较多，第一次接触Linux的新朋友， 很多资料若看不懂可以先略过，等到后续文章都读完了再回来看，才会有帮助喔！ ^_^

计算机概论 2008/07/22 | 这几年鸟哥开始在大学任教了，在教学的经验中发现到，由于对Linux有兴趣的朋友很多可能并非资讯相关科系出身， 因此对于电脑硬体及计算机方面的概念不熟。然而作业系统这种咚咚跟硬体有相当程度的关连性， 所以.....
Linux是什么 2008/07/26 | 众所皆知的，Linux的核心原型是1991年由托瓦兹(Linus Torvalds)写出来的，但是托瓦兹为何可以写出Linux这个作业系统？ 为什么他要选择386的电脑来开发？为什么Linux的发展可以这么迅速？又为什么Linux是免费的？.....
Linux如何学习 2008/07/28 | 目前Linux上头有两种主要的操作模式，分别是图形介面与文字介面，那么学习Linux要用X-Window(图形介面)好还是Command Line(文字介面)好？这两种学习心态有什么优缺点呢？此外，有没有良好的入门文件可供参考？.....
主机规划与磁碟分割 2008/08/21 | 事实上，要安装好一部Linux主机并不是那么简单的事情，你必须要针对distributions的特性、伺服器的软体能力、 未来的升级需求、硬体扩充性需求等等来考量，还得要知道磁碟分割、档案系统.....
安装CentOS 5.x 与多重开机技巧 2008/09/02 | Linux distributions越作越成熟，所以在安装方面也越来越简单！虽然安装非常的简单， 但是刚刚前一章所谈到的基础认知还是需要了解的，包括MBR, partition, boot loader, mount, software的.....
首次登入与 线上求助 man page 2008/09/09 | 终于可以开始使用Linux这个有趣的系统了！由于Linux系统使用了非同步的磁碟/记忆体资料传输模式， 同时又是个多人多工的环境，所以你不能随便的不正常关机，关机有一定的程序喔！错误的关机方法.....
第二部分 Linux 档案、目录与磁碟格式
安装完了 Linux 之后，接着下来自然就是要使用他了！我们在 开机与关机及简易指令操作 稍微说明了指令下达的方法，以及指令线上查询的方式， 因此您可以轻易的使用指令列模式来进行诸多的动作与工作。那么接着下来呢？当然就是想要知道 Linux 里面有什么东西啰，所以，在这一个部分当中，我们将介绍 Linux 最基本的档案权限概念， 与每个档案目录所带有的意涵。

当然啰，要了解权限的概念，那么对于不同的‘身份’就需要了解一下才行， 不同的身份的人，所建立的或拥有的档案是否会相同呢？例如系统管理员与一般身份使用者的档案？ 当然不太一样！除此之外，如果您的硬碟空间不足，需要增加硬碟时，应该要如何新增呢？ 还有，记忆体不足的情况下，有没有增进虚拟记忆体容量的方法？在接下来的几个章节之中，我们将介绍 Linux 主要的档案架构、以及磁碟在 Linux 当中该如何使用及挂载等问题。

Linux档案权限与 目录配置 2008/09/23 | Linux最优秀的地方之一，就在于他的多人多工的环境。而为了让各个使用者具有较保密的档案资料， 因此档案的权限管理就变的很重要了。 Linux一般将档案可存取的身份分为三个类别，分别是 owner/group/other， 且三种身份各有read/write/execute.....
Linux档案与目录管理 2008/09/29 | 在第六章我们认识了Linux系统下的档案权限概念以及目录的配置说明。 在这个章节当中， 我们就直接来进一步的操作与管理档案与目录吧！包括在不同的目录间变换、 建立与删除目录、建立与删除档案， 还有寻找档案、查阅档案内容.....
Linux 磁碟与 档案系统管理 2008/10/31 | 系统管理员很重要的任务之一就是管理好自己的磁碟档案系统，每个分割槽不可太大也不能太小， 太大会造成磁碟容量的浪费，太小则会产生档案无法储存的困扰。此外，我们在前面几章谈到的档案权限与属性中， 这些权限与属性.....
档案的压缩与打包 2008/12/18 | 在 Linux 底下有相当多的压缩指令可以运作喔！这些压缩指令可以让我们更方便从网路上面下载大型的档案呢！ 此外，我们知道在 Linux 底下的副档名是没有什么很特殊的意义的，不过，针对这些压缩指令所做出来的压缩档， 为了方便记忆.....
第三部分：学习 Shell 与 Shell scripts
了解了基本的 Linux 档案属性与目录的配置之后，在进入更深入的 Linux 世界之前，有几个课题还是一定要知道的，那就是我们所使用的这个文字模式介面，也就是所谓的‘Shell’这个咚咚。在 Linux 的世界中，使用的是 GNU 发展出来的强化的第二代 shell ，称为 BASH Shell ，他有什么特异功能呢？简单的说，我们之前下达的几个指令都是 bash 管理的，除此之外， 他还可以记录指令、档案或命令的补全功能、环境变数的使用等等，还有很多功能等着你去发掘呢！

在知道了部分的 bash 功能后，在接着下来，我们还得了解一下什么是资料流重导向？还有常规表示法等等的问题， 这都是未来我们系统管理员在管理主机上面，一个不可缺乏的利器！当然啰，要将这些功能整合起来运用的话， 就不能不学习一下所谓的脚本‘ shell scripts ’，他具有基础的程式能力( Program )，当真是个管理系统的好帮手呢！

再来，在未来的架站设定当中，常会使用到文字编辑器来编辑参数设定档，这个时候， 系统管理员至少务必要熟悉一套文字介面下的文书编辑软体，当然不限制哪一套软体啦，但是 vi 是最标准的 Unix-Like 的文字介面之文书处理软体，所以，我们几乎一定可以在每部 Unix-Like 上面发现他的踪迹，所以，就来了解他一下吧，这也是挺重要的工作呢！

vim程式编辑器 2009/01/13 | 系统管理员的重要工作就是得要修改与设定某些重要软体的设定档， 因此至少得要学会一种以上的文字介面的文书编辑器。 在所有版本的 Linux 上头都会有的一套文书编辑器就是 vi ，而且很多软体.....
认识与学习 BASH 2009/02/07 | 在 Linux 的环境下，如果你不懂 bash 是什么，那么其他的东西就不用学了！ 因为前面几章我们使用终端机下达指令的方式， 就是透过 bash 的环境来处理的喔！ 所以说，他很重要吧！bash 的东西非常的多，包括变数.....
正规表示法与 文件格式化处理 2009/02/10 | 正规表示法 (Regular Expression, RE, 或称为常规表示法)是透过一些特殊字元的排列， 用以‘搜寻/取代/删除’一列或多列文字字串， 简单的说， 正规表示法就是用在字串的处理上面的一项‘表示式’。正规表示法并.....
学习 shell scripts 2009/02/18 | 如果你真的很想要走资讯这条路，并且想要好好的管理好属于你的主机，那么，别说鸟哥不告诉你， 可以自动管理你的系统的好工具： Shell scripts 真的是得要好好学习学习的！ 基本上， shell script 有点像是早期的批次档，亦即是.....
第四部分：Linux 使用者管理
好了！终于要到了管理 Linux 帐号的时刻了！对于 Linux 有一定的熟悉度之后，再来就是要管理连上 Linux 的帐号问题了！这个帐号的问题可大可小啦！大到可以限制他使用 Linux 主机的各项资源，小到甚至一般帐号的密码订定规则都可以进行规定！端看您对于安全的需求啦！ 此外，如果站在资源平均分配的角度上，那么 Linux 主机上面有限的资源当然是平均分配给大家比较好！这个时候就得来规定一下‘谁可以使用多少的硬碟空间？’那就是 Quota 喔！呵呵！厉害吧！

在订定完了一些帐号的规则之后，那么我们就继续来管理一下主机的系统与程序的管理吧！ 这个包括了观察每个程序 ( Process ) 与工作排程及工作管理 ( jobs control )，这些也都是很重要的工作呢！

Linux 帐号管理与 ACL 权限控制 2009/03/04 | 要登入 Linux 系统一定要有帐号与密码才行，否则怎么登入，您说是吧？不过， 不同的使用者应该要拥有不同的权限才行吧？我们还可以透过 user/group 的特殊权限设定，来规范出不同的群组开发专案呢.....
磁碟配额(Quota)与 进阶档案系统管理 2009/03/12 | 如果您的 Linux 伺服器有多个用户经常存取资料时，为了维护所有使用者在硬碟容量的公平使用，磁碟配额 (Quota) 就是一项非常有用的工具！另外，如果你的用户常常抱怨磁碟容量不够用，那么更进阶的档案系统就得要学习学习.....
例行性工作排程 (crontab) 2009/03/15 | 学习了基础篇也一阵子了，你会发现到为什么系统常常会主动的进行一些任务？ 这些任务到底是谁在设定工作的？ 如果你想要让自己设计的备份程式可以自动的在系统底下执行，.....
程序管理与 SELinux 初探 2009/03/25 | 一个程式被载入到记忆体当中运作，那么在记忆体内的那个资料就被称为程序(process)。程式是作业系统上非常重要的概念， 所有系统上面跑的资料都会以程序的型态存在。那么系统的程序有哪些状态.....
第五部分：Linux 系统管理员
嗯！终于来到系统管理员 ( root ) 要注意的工作事项之篇幅了！各位准系统管理员心理准备好了吗？ 我们要管理机器啰，呵呵！那么管理员的工作是什么？看报喝茶？！没错！管理员最大的享受就是看报喝茶了。 一个好的系统管理员，平时不会希望挂载网站上面一再不断的查询、检查漏洞等等的， 因为果真如此的话，那么就表示‘机器一定有问题了！’。为了让我们的 Linux 机器跑得更稳更顺畅，好让我这个管理员有更多的时间去看报喝茶，哈哈！ 更深入的了解系统是需要的！所以，这一篇我们由开机关机的整体流程谈起，好了解一下 Linux 在开机的过程中到底做了哪些事情，这样才能知道我们在什么时候应该做什么事情呐！

此外，由于‘没有一个套件是永远安全的！’，所以套件管理是相当重要的一部份，这里我们以 RPM 与 Tarball 来介绍一下如何管理你系统上面的套件。再来，你知道你的系统上面跑了多少资料吗？ 虽然知道什么是 ps 来查询程序，但是总是得知道我的系统有哪些服务吧！嘿嘿！ 来看看先?不但如此，还得针对登录档进行解析，以及对于系统进行备份。呵呵！ 管理员的工作还真多那。不止不止，还要进行核心的管理呢！哇！果然是忙毙了！无论如何， 还是得要了解呐！

认识系统服务 (daemon) 2009/04/02 | 在 Unix-Like 的系统中，你常常听到 daemon 这个字眼！那么什么是传说中的 daemon 呢？这些 daemon 放在什么地方？他的功能是什么？该如何启动这些 daemon ？又如何有效的将这些 daemon 管理妥当.....
认识与分析登录档 2009/04/09 | 当你的 Linux 系统出现不明原因的问题时，很多人都告诉你，你要查阅一下登录档才能够知道系统出了什么问题了， 所以说，了解登录档是很重要的事情呢。登录档可以记录系统在什么时间、哪个主机、哪个服务.....
开机流程、模组管理 与 loader 2009/04/30 | 系统开机其实是一项非常复杂的程序，因为核心得要侦测硬体并载入适当的驱动程式后， 接下来则必须要呼叫程序来准备好系统运作的环境，以让使用者能够顺利的操作整部主机系统。 如果你能够理解开机的原理.....
系统设定工具(网路与 印表机)与硬体侦测 2009/06/03 | 除了手动设定之外，其实系统提供了一个名为 setup 的指令给系统管理员使用喔！ 这个指令还能够设定网路呢。此外，我们也应该要知道如何在 Linux 底下连接印表机吧！ 否则一些资料怎么印出来？另外.....
软体安装： 原始码与 Tarball 2009/06/20 | 我们在第一章、Linux是什么当中提到了 GNU 计划与 GPL 授权所产生的自由软体与开放源码等咚咚。 不过，前面的章节都还没有提到真正的开放源码是什么的讯息！在这一章当中，我们将藉由 Linux 作业系统里面的执行档.....
软体安装： RPM, SRPM 与 YUM 功能 2009/07/03 | 虽然使用原始码进行编译可以进行客制化的设定，但对于 Linux distribution 的原本发布商来说， 则有软体管理不易的问题， 毕竟不是每个人都会进行原始码编译的。 如果能够将软体预先在相同的硬体与作业系统上面编译好才发布的话.....
X Window 设定介绍 2009/07/15 | 在 Linux 上头的图形介面我们称之为 X Window System，简称为 X 或 X11 啰！为何称之为系统呢？这是因为 X 视窗系统又分为 X server 与 X client ，既然是 Server/Client (主从架构) 这就表示其实 X 视窗系统是可以跨网路且跨平台的.....
Linux 备份策略 2009/07/21 | 万一不幸你的 Linux 被骇客入侵了、或是你的 Linux 系统由于硬体关系 (不论是天灾还是人祸) 而挂掉了！这个时候，请问如何快速的回复你的系统呢？呵呵！当然啰，如果有备份资料的话， 那么回复系统所花费的时间与成本将降低相当的多.....
核心编译 2009/07/31 | 我们说的 Linux 其实指的就是核心 (kernel) 而已。这个核心控制你主机的所有硬体并提供系统所有的功能， 所以说，他重不重要啊！我们开机的时候其实就是利用开机管理程式载入这个核心档案来侦测硬体， 在核心载入适当的驱动程式后.....

第六部分：其他备份文章
这个部分的内容是鸟哥基于自己的需求而将某一时期的文章结合在一起，以方便鸟哥自己的查询之用。 如果您使用的Linux distribution是旧的，那么这个文件可能对你有帮助，不过，还是建议读新的资料， 因为旧的资料可能会有些疏失啦！

内容大纲 | 主要内容说明
Linux 系统与指令练习题 2002/06/28 | 赶快来试试看对于 Linux 了解有多深？！这里的题目都只与基础系统有关，其他的关于 Server 的部分将在以后才会摆上来。
SPFDISK 的一个范例 2005/06/12 | 安装 Linux 最重要的就是硬碟空间了！然而很抱歉的是， Windows 的 fdisk 并不认识 Linux 的磁碟格式！所以如果您已经安装了 Linux 之后，却想将该 partition ( 硬碟磁区 ) 删除的话，那么使用 Windows 的 FDISK 程式是无法做的！另外，使用 全中文 的 spfdisk 也可以让您更容易了解 fdisk 在做什么工作呦！
较小安装 Red Hat 7.2 2003/02/03 (Older) | 终于要安装 Red Hat Linux 了！呼～真是麻烦～那么 Linux 的安装模式有哪些呢？ 嗯！基本上可以分为图形安装模式 ( 好消息是 Red Hat 7.3 已经支援中文安装了 )与文字安装模式， ....
Red Hat 6.x 旧文件 1999~2001 | 这些是早期的 Red Hat 6.x 的相关基础文件，当时写的比较简单， 而且也比较没有系统，不过，如果您还是使用旧版的 Red Hat 的话，那么，或许还是有可以参考的地方吧！？ ^_^..
基础篇第一版 Mandrake 9为例 2001~2004 | 这个部分是鸟哥写的第一本书的内容！不过，因为时间隔的太久了，很多文章都经过了部分的编修， 所以与书籍上的章节不太相同。列出来只是为了要对鸟哥自己负责就是了！^_^.....
基础篇第二版 Fedora Core 4为例 2005~2008 | 这个部分则是基础篇的第二版，基本上已经是非常完整的书籍内容了！ 不过，仍然是具有部分的疏失啦！尤其是内容字太多了！新版的希望能够图多点～.....


鸟哥的 Linux 私房菜 -- 基础学习篇

为取得较佳浏览结果，请爱用 firefox 浏览本网页
鸟哥的 Linux 私房菜馆 | Linux 基础文件 | Linux 架站文件 | Linux 企业运用 | 安全管理 | 新手讨论 |

第零章、计算机概论
最近更新日期：2009/08/03
这几年鸟哥开始在大学任教了，在教学的经验中发现到，由于对 Linux 有兴趣的朋友很多可能并非资讯相关科系出身， 因此对于电脑硬体及计算机方面的概念不熟。然而作业系统这种咚咚跟硬体有相当程度的关连性， 所以，如果不了解一下计算机概论，要很快的了解 Linux 的概念是有点难度的。因此，鸟哥就自作聪明的新增一个小章节来谈谈计概啰！ 因为鸟哥也不是资讯相关学门出身，所以，写的不好的地方请大家多多指教啊！^_^

1. 电脑：辅助人脑的好工具
    1.1 电脑硬体的五大单元
1.2 CPU的种类
1.3 周边设备
1.4 运作流程
1.5 电脑分类
1.6 电脑上面常用的计算单位 (容量、速度等)
 2. 个人电脑架构与周边设备
    2.1 CPU： CPU的外频与倍频, 32位元与64位元, CPU等级
2.2 记忆体
2.3 显示卡
2.4 硬碟与储存设备
2.5 PCI介面卡
2.6 主机板
2.7 电源供应器
2.8 选购须知
 3. 资料表示方式
    3.1 数字系统
3.2 文字编码系统
 4. 软体程式运作
    4.1 机器程式与编译程式
4.2 作业系统
4.3 应用程式
 5. 重点回顾
6. 本章习题
7. 参考资料与延伸阅读
8. 针对本文的建议：http://phorum.vbird.org/viewtopic.php?t=31574
电脑：辅助人脑的好工具

进入二十一世纪的现在，没有用过电脑的朋友应该算很少了吧？但是，你了解电脑是什么吗？ 电脑的机壳里面含有什么元件？不同的电脑可以作什么事情？你生活周遭有哪些电器用品内部是含有电脑相关元件的？ 底下我们就来谈一谈这些东西呢！

所谓的电脑就是一种计算机，而计算机其实是：‘接受使用者输入指令与资料， 经由中央处理器的数学与逻辑单元运算处理后，以产生或储存成有用的资讯’。 因此，只要有输入设备 (不管是键盘还是触控式荧幕)及输出设备(荧幕或直接列印出来)，让你可以输入资料使该机器产生资讯的， 那就是一部计算机了。

计算机的功能
图1.1.1、计算机的功能

根据这个定义你知道哪些东西是计算机了吗？包括一般商店用的简易型加减乘除计算机、打电话用的手机、开车用的卫星定位系统 (GPS)、提款用的提款机 (ATM)、你常使用的桌上型个人电脑、可携带的笔记型电脑还有这两年 (2008, 2009) 很火红的 Eee PC (或称为 netbook) 等等，这些都是计算机！

那么计算机主要的组成元件是什么呢？底下我们以常见的个人电脑来作为说明。

电脑硬体的五大单元

关于电脑的组成部分，其实你可以观察你的桌上型电脑分析一下，依外观来说这家伙主要分为三部分：

  • 输入单元：包括键盘、滑鼠、读卡机、扫描器、手写板、触控荧幕等等一堆；
  • 主机部分：这个就是系统单元，被主机机壳保护住了，里面含有 CPU 与主记忆体等；
  • 输出单元：例如荧幕、印表机等等

我们主要透过输入设备如滑鼠与键盘来将一些资料输入到主机里面，然后再由主机的功能处理成为图表或文章等资讯后， 将结果传输到输出设备，如荧幕或印表机上面。重点在于主机里面含有什么元件呢？如果你曾经拆开过电脑主机机壳， 会发现其实主机里面最重要的就是一片主机板，上面安插了中央处理器 (CPU) 以及主记忆体还有一些介面卡装置而已。

整部主机的重点在于中央处理器 (Central Processing Unit, CPU)，CPU 为一个具有特定功能的晶片， 里头含有微指令集，如果你想要让主机进行什么特异的功能，就得要参考这颗 CPU 是否有相关内建的微指令集才可以。 由于 CPU 的工作主要在于管理与运算，因此在 CPU 内又可分为两个主要的单元，分别是： 算数逻辑单元与控制单元。(注1) 其中算数逻辑单元主要负责程式运算与逻辑判断，控制单元则主要在协调各周边元件与各单元间的工作。

既然 CPU 的重点是在进行运算与判断，那么要被运算与判断的资料是从哪里来的？ CPU 读取的资料都是从主记忆体来的！ 主记忆体内的资料则是从输入单元所传输进来！而 CPU 处理完毕的资料也必须要先写回主记忆体中， 最后资料才从主记忆体传输到输出单元。

综合上面所说的，我们会知道其实电脑是由几个单元所组成的，包括输入单元、 输出单元、CPU内部的控制单元、算数逻辑单元与主记忆体五大部分。 相关性如下所示：

电脑的五大单元
图1.1.2、电脑的五大单元(注2)

上面图示中的‘系统单元’其实指的就是电脑机壳内的主要元件，而重点在于CPU与主记忆体。 特别要看的是实线部分的传输方向，基本上资料都是流经过主记忆体再转出去的！ 至于资料会流进/流出记忆体则是CPU所发布的控制命令！而CPU实际要处理的资料则完全来自于主记忆体！ 这是个很重要的概念喔！

而由上面的图示我们也能知道，所有的单元都是由CPU内部的控制单元来负责协调的，因此CPU是整个电脑系统的最重要部分！ 那么目前世界上有哪些主流的CPU呢？是否刚刚我们谈到的硬体内全部都是相同的CPU种类呢？底下我们就来谈一谈。

CPU的种类

如前面说过的，CPU其实内部已经含有一些小指令集，我们所使用的软体都要经过CPU内部的微指令集来达成才行。 那这些指令集的设计主要又被分为两种设计理念，这就是目前世界上常见到的两种主要CPU种类： 分别是精简指令集(RISC)与复杂指令集(CISC)系统。底下我们就来谈谈这两种不同CPU种类的差异啰！

  • 精简指令集(Reduced Instruction Set Computing, RISC)：(注3)

这种CPU的设计中，微指令集较为精简，每个指令的执行时间都很短，完成的动作也很单纯，指令的执行效能较佳； 但是若要做复杂的事情，就要由多个指令来完成。常见的RISC微指令集CPU主要例如升阳(Sun)公司的SPARC系列、 IBM公司的Power Architecture(包括PowerPC)系列、与ARM系列等。

在应用方面，SPARC架构的电脑常用于学术领域的大型工作站中，包括银行金融体系的主要伺服器也都有这类的电脑架构； 至于PowerPC架构的应用上，例如新力(Sony)公司出产的Play Station 3(PS3)就是使用PowerPC架构的Cell处理器； 那ARM呢？你常使用的各厂牌手机、PDA、导航系统、网路设备(交换器、路由器等)等，几乎都是使用ARM架构的CPU喔！ 老实说，目前世界上使用范围最广的CPU可能就是ARM呢！ (注4)

  • 复杂指令集(Complex Instruction Set Computer, CISC)：(注5)

与RISC不同的，CISC在微指令集的每个小指令可以执行一些较低阶的硬体操作，指令数目多而且复杂， 每条指令的长度并不相同。因为指令执行较为复杂所以每条指令花费的时间较长， 但每条个别指令可以处理的工作较为丰富。常见的CISC微指令集CPU主要有AMD、Intel、VIA等的x86架构的CPU。

由于AMD、Intel、VIA所开发出来的x86架构CPU被大量使用于个人电脑(Personal computer)用途上面， 因此，个人电脑常被称为x86架构的电脑！那为何称为x86架构(注6)呢？ 这是因为最早的那颗Intel发展出来的CPU代号称为8086，后来依此架构又开发出80286, 80386...， 因此这种架构的CPU就被称为x86架构了。

在2003年以前由Intel所开发的x86架构CPU由8位元升级到16、32位元，后来AMD依此架构修改新一代的CPU为64位元， 为了区别两者的差异，因此64位元的个人电脑CPU又被统称为x86_64的架构喔！

那么不同的x86架构的CPU有什么差异呢？除了CPU的整体结构(如第二层快取、每次运作可执行的指令数等)之外， 主要是在于微指令集的不同。新的x86的CPU大多含有很先进的微指令集， 这些微指令集可以加速多媒体程式的运作，也能够加强虚拟化的效能，而且某些微指令集更能够增加能源效率， 让CPU耗电量降低呢！由于电费越来越高，购买电脑时，除了整体的效能之外， 节能省电的CPU特色也可以考虑喔！

例题：
最新的Intel/AMD的x86架构中，请查询出多媒体、虚拟化、省电功能各有哪些重要的微指令集？(仅供参考)
答：
  • 多媒体微指令集：MMX, SSE, SSE2, SSE3, SSE4, AMD-3DNow!
  • 虚拟化微指令集：Intel-VT, AMD-SVM
  • 省电功能：Intel-SpeedStep, AMD-PowerNow!
  • 64/32位元相容技术：AMD-AMD64, Intel-EM64T

周边设备

单有CPU也无法运作电脑的，所以电脑还需要其他的周边设备才能够实际运作。 除了前面稍微提到的输入/输出设备，以及CPU与主记忆体之外，还有什么周边设备呢？ 其实最重要的周边设备是主机板！因为主机板负责将所有的设备通通连接在一起，让所有的设备能够进行协调与沟通。 而主机板上面最重要的元件就是主机板晶片组！这个晶片组可以将所有的设备汇集在一起！

其他重要的设备还有：

  • 储存装置：储存装置包括硬碟、软碟、光碟、磁带等等；
  • 显示装置：显示卡对于玩3D游戏来说是非常重要的一环，他与显示的精致度、色彩与解析度都有关系；
  • 网路装置：没有网路活不下去啊！所以网路卡对于电脑来说也是相当重要的！

更详细的各项周边装置我们将在下个小节进行介绍！在这里我们先来了解一下各元件的相关系啰！ 那就是，电脑是如何运作的呢？

运作流程

如果不是很了解电脑的运作流程，鸟哥拿个简单的想法来思考好了～ 假设电脑是一个人体，那么每个元件对应到那个地方呢？可以这样思考：

各元件运作
图1.4.1、各元件运作
  • CPU=脑袋瓜子：每个人会作的事情都不一样(微指令集的差异)， 但主要都是透过脑袋瓜子来进行判断与控制身体各部分的活动；

  • 主记忆体=脑袋中的记录区块：在实际活动过程中，我们的脑袋瓜子能够将外界的互动暂时记录起来， 提供CPU来进行判断；

  • 硬碟=脑袋中的记忆区块：将重要的资料记录起来，以便未来将这些重要的经验再次的使用；

  • 主机板=神经系统：好像人类的神经一样，将所有重要的元件连接起来，包括手脚的活动都是脑袋瓜子发布命令后， 透过神经(主机板)传导给手脚来进行活动啊！

  • 各项周边设备=人体与外界沟通的手、脚、皮肤、眼睛等：就好像手脚一般，是人体与外界互动的重要关键！

  • 显示卡=脑袋中的影像：将来自眼睛的刺激转成影响后在脑袋中呈现，所以显示卡所产生的资料来源也是CPU控制的。

  • 电源供应器 (Power)=心脏：所有的元件要能运作得要有足够的电力供给才行！这电力供给就好像心脏一样，如果心脏不够力， 那么全身也就无法动弹的！心脏不稳定呢？那你的身体当然可能断断续续的～不稳定！

由这样的关系图当中，我们知道整个活动中最重要的就是脑袋瓜子！ 而脑袋瓜子当中与现在正在进行的工作有关的就是CPU与主记忆体！任何外界的接触都必须要由脑袋瓜子中的主记忆体记录下来， 然后给脑袋中的CPU依据这些资料进行判断后，再发布命令给各个周边设备！如果需要用到过去的经验， 就得由过去的经验(硬碟)当中读取啰！

也就是说，整个人体最重要的地方就是脑袋瓜子，同样的，整部主机当中最重要的就是CPU与主记忆体， 而CPU的资料来源通通来自于主记忆体，如果要由过去的经验来判断事情时， 也要将经验(硬碟)挪到目前的记忆(主记忆体)当中，再交由CPU来判断喔！这点得要再次的强调啊！ 下个章节当中，我们就对目前常见的个人电脑各个元件来进行说明啰！

电脑分类

知道了电脑的基本组成与周边装置，也知道其实电脑的CPU种类非常的多，再来我们想要了解的是，电脑如何分类？ 电脑的分类非常多种，如果以电脑的复杂度与运算能力进行分类的话，主要可以分为这几类：

  • 超级电脑(Supercomputer)
    超级电脑是运作速度最快的电脑，但是他的维护、操作费用也最高！主要是用于需要有高速计算的计划中。 例如：国防军事、气象预测、太空科技，用在模拟的领域较多。详情也可以参考： 国家高速网路与计算中心http://www.nchc.org.tw的介绍！ 至于全世界最快速的前500大超级电脑，则请参考：http://www.top500.org。

  • 大型电脑(Mainframe Computer)
    大型电脑通常也具有数个高速的CPU，功能上虽不及超级电脑，但也可用来处理大量资料与复杂的运算。 例如大型企业的主机、全国性的证券交易所等每天需要处理数百万笔资料的企业机构， 或者是大型企业的资料库伺服器等等。

  • 迷你电脑(Minicomputer)
    迷你电脑仍保有大型电脑同时支援多使用者的特性，但是主机可以放在一般作业场所， 不必像前两个大型电脑需要特殊的空调场所。通常用来作为科学研究、工程分析与工厂的流程管理等。

  • 工作站(Workstation)
    工作站的价格又比迷你电脑便宜许多，是针对特殊用途而设计的电脑。在个人电脑的效能还没有提升到目前的状况之前， 工作站电脑的性能/价格比是所有电脑当中较佳的，因此在学术研究与工程分析方面相当常见。

  • 微电脑(Microcomputer)
    又可以称为个人电脑，也是我们这里主要探讨的目标！体积最小，价格最低，但功能还是五脏俱全的！ 大致又可分为桌上型、笔记型等等。

若光以效能来说，目前的个人电脑效能已经够快了，甚至已经比工作站等级以上的电脑运算速度还要快！ 但是工作站电脑强调的是稳定不当机，并且运算过程要完全正确，因此工作站以上等级的电脑在设计时的考量与个人电脑并不相同啦！ 这也是为啥工作站等级以上的个人电脑售价较贵的原因。

电脑上面常用的计算单位 (容量、速度等)

电脑的运算能力是由速度来决定的，而存放在电脑储存设备当中的资料容量也是有单位的。

  • 容量单位

电脑依有没有通电来记录资讯，所以理论上它只认识 0 与 1 而已。0/1 的单位我们称为 bit。但 bit 实在太小了， 并且在储存资料时每份简单的资料都会使用到 8 个 bits 的大小来记录，因此定义出 byte 这个单位，他们的关系为：

1 Byte = 8 bits

不过同样的，Byte 还是太小了，在较大的容量情况下，使用 byte 相当不容易判断资料的大小，举例来说，1000000 bytes 这样的显示方式你能够看得出有几个零吗？所以后来就有一些常见的简化单位表示法，例如 K 代表 1024，M 代表 1024K 等。 而这些单位在不同的进位制下有不同的数值表示，底下就列出常见的单位与进位制对应：

进位制 | K | M | G | T | P
二进位 | 1024 | 1024K | 1024M | 1024G | 1024T
十进位 | 1000 | 1000K | 1000M | 1000G | 1000T

一般来说，档案容量使用的是二进位的方式，所以 1 GBytes 的档案大小实际上为：1024x1024x1024 Bytes 这么大！ 速度单位则常使用十进位，例如 1GHz 就是 1000x1000x1000 Hz 的意思。

  • 速度单位

CPU的运算速度常使用 MHz 或者是 GHz 之类的单位，这个 Hz 其实就是秒分之一。而在网路传输方面，由于网路使用的是 bit 为单位，因此网路常使用的单位为 Mbps 是 Mbits per second，亦即是每秒多少 Mbit。举例来说，大家常听到的 8M/1M ADSL 传输速度，如果转成档案容量的 byte 时，其实理论最大传输值为：每秒 1Mbyte/ 每秒125Kbyte的上传/下载容量喔！

例题：
假设你今天购买了500GB的硬碟一颗，但是格式化完毕后却只剩下460GB左右的容量，这是什么原因？
答：
因为一般硬碟制造商会使用十进位的单位，所以500GByte代表为500*1000*1000*1000Byte之意。 转成档案的容量单位时使用二进位(1024为底)，所以就成为466GB左右的容量了。

硬碟厂商并非要骗人，只是因为硬碟的最小物理量为512Bytes，最小的组成单位为磁区(sector)， 通常硬碟容量的计算采用‘多少个sector’，所以才会使用十进位来处理的。相关的硬碟资讯在这一章后面会提到的！

个人电脑架构与周边设备

一般消费者常说的电脑通常指的就是x86的个人电脑架构，因此我们有必要来了解一下这个架构的各个元件。 事实上，Linux最早在发展的时候，就是依据个人电脑的架构来发展的，所以，真的得要了解一下呢！ 另外，因为两大主流x86开发商(Intel, AMD)的CPU架构并不相容，而且设计理念也有所差异， 所以两大主流CPU所需要的主机板晶片组设计也就不太相同。目前(2009)最新的主机板架构主要是这样的：

Intel晶片架构
图2.1.1、Intel晶片架构

就如同前一小节提到的，整个主机板上面最重要的就是晶片组了！而晶片组通常又分为两个桥接器来控制各元件的沟通， 分别是：(1)北桥：负责连结速度较快的CPU、主记忆体与显示卡等元件；(2)南桥：负责连接速度较慢的周边介面， 包括硬碟、USB、网路卡等等。(晶片组的南北桥与三国的大小乔没有关系 @_@)至于AMD的晶片组架构如下所示：

AMD晶片架构
图2.1.2、AMD晶片架构

与Intel不同的地方在于主记忆体是直接与CPU沟通而不透过北桥！从前面的说明我们可以知道CPU的资料主要都是来自于主记忆体提供， 因此AMD为了加速这两者的沟通，所以将记忆体控制元件整合到CPU当中， 理论上这样可以加速CPU与主记忆体的传输速度！这是两种CPU在架构上面主要的差异点。

毕竟目前世界上x86的CPU主要供应商为Intel，所以底下鸟哥将以Intel的主机板架构说明各元件啰！ 我们以技嘉公司出的主机板，型号：Gigabyte GA-X48-DQ6作为一个说明的范例，主机板各元件如下所示：

技嘉主机板各元件
图2.1.3、技嘉主机板各元件(图片为各公司所有)

主要的元件为：CPU、主记忆体、磁碟装置(IDE/SATA)、汇流排晶片组(南桥/北桥)、显示卡介面(PCI-Express)与其他介面卡(PCI)。 底下的各项元件在讲解时，请参考Intel晶片组架构与技嘉主机板各元件来印证喔！

CPU

如同技嘉主机板示意图上最上方的中央部分，那就是CPU插槽。 由于CPU负责大量运算，因此CPU通常是具有相当高发热量的元件。所以如果你曾经拆开过主机板， 应该就会看到CPU上头通常会安插一颗风扇来主动散热的。

x86个人电脑的CPU主要供应商为Intel与AMD，目前(2009)主流的CPU都是双核以上的架构了！ 原本的单核心CPU仅有一个运算单元，所谓的多核心则是在一颗CPU封装当中嵌入了两个以上的运算核心， 简单的说，就是一个实体的CPU外壳中，含有两个以上的CPU单元就是了。

不同的CPU型号大多具有不同的脚位(CPU上面的插脚)，能够搭配的主机板晶片组也不同， 所以当你想要将你的主机升级时，不能只考虑CPU，你还得要留意你的主机板上面所支援的CPU型号喔！ 不然买了最新的CPU也不能够安插在你的旧主机板上头的！目前主流的CPU有Intel的Core 2 Duo与AMD的Athlon64 X2双核CPU， 高阶产品则有Intel的Core i7 与AMD的Phenom II 四核心CPU喔！

不同的CPU脚位
图2.1.4、不同的CPU脚位

我们前面谈到CPU内部含有微指令集，不同的微指令集会导致CPU工作效率的优劣。除了这点之外， CPU效能的比较还有什么呢？那就是CPU的时脉了！什么是时脉呢？简单的说， 时脉就是CPU每秒钟可以进行的工作次数。 所以时脉越高表示这颗CPU单位时间内可以作更多的事情。举例来说，Intel的Core 2 Duo型号E8400的CPU时脉为3.0GHz， 表示这颗CPU在一秒内可以进行3.0x109次工作，每次工作都可以进行少数的指令运作之意。

Tips:
注意，不同的CPU之间不能单纯的以时脉来判断运算效能喔！这是因为每颗CPU的微指令集不相同，架构也不见得一样， 每次时脉能够进行的工作指令数也不同之故！所以，时脉目前仅能用来比较同款CPU的速度！
  • CPU的‘外频’与‘倍频’

我们可以看到图2.1.1的晶片架构图当中各个元件都是透过北桥与南桥所连接在一起。 但就像一群人共同在处理一个连续作业一般，如果这一群人里面有个人的动作特别快或特别慢， 将导致前面或者是后面的人事情一堆处理不完！也就是说，这一群人最好能够速度一致较佳！ 所以，CPU与外部各元件的速度理论上应该要一致才好。但是因为CPU需要较强大的运算能力， 因为很多判断与数学都是在CPU内处理的，因此CPU开发商就在CPU内再加上一个加速功能， 所以CPU有所谓的外频与倍频！

所谓的外频指的是CPU与外部元件进行资料传输时的速度，倍频则是 CPU 内部用来加速工作效能的一个倍数， 两者相乘才是CPU的时脉速度。我们以刚刚Intel Core 2 Duo E8400 CPU来说，他的时脉是3.0GHz， 而外频是333MHz，因此倍频就是9倍啰！(3.0G=333Mx9, 其中1G=1000M)

Tips:
很多电脑硬体玩家很喜欢玩‘超频’，所谓的超频指的是： 将CPU的倍频或者是外频透过主机板的设定功能更改成较高频率的一种方式。但因为CPU的倍频通常在出厂时已经被锁定而无法修改， 因此较常被超频的为外频。
举例来说，像上述3.0GHz的CPU如果想要超频， 可以将他的外频333MHz调整成为400MHz，但如此一来整个主机板的各个元件的运作频率可能都会被增加成原本的1.333倍(4/3)， 虽然CPU可能可以到达3.6GHz，但却因为频率并非正常速度，故可能会造成当机等问题。
  • 32位元与64位元

前面谈到CPU运算的资料都是由主记忆体提供的，主记忆体与CPU的沟通速度靠的是外部频率， 那么每次工作可以传送的资料量有多大呢？那就是汇流排的功能了。一般主机板晶片组有分北桥与南桥， 北桥的汇流排称为系统汇流排，因为是记忆体传输的主要通道，所以速度较快。 南桥就是所谓的输入输出(I/O)汇流排，主要在联系硬碟、USB、网路卡等周边设备。

目前北桥所支援的频率可高达333/400/533/800/1066/1333/1600MHz等不同频率，支援情况依晶片组功能而有不同。 北桥所支援的频率我们称为前端汇流排速度(Front Side Bus, FSB)， 而每次传送的位元数则是汇流排宽度。 那所谓的汇流排频宽则是：‘FSBx汇流排宽度’亦即每秒钟可传送的最大资料量。 目前常见的汇流排宽度有32/64位元(bits)。

而如图 2.1.1中的图示，在该架构中前端汇流排最高速度可达1600MHz。 我们看到记忆体与北桥的频宽为12.8GBytes/s，亦即是1600MHz*64bits = 1600MHz*8Bytes = 12800MByes/s = 12.8GBytes/s

与汇流排宽度相似的，CPU每次能够处理的资料量称为字组大小(word size)， 字组大小依据CPU的设计而有32位元与64位元。我们现在所称的电脑是32或64位元主要是依据这个 CPU解析的字组大小而来的！早期的32位元CPU中，因为CPU每次能够解析的资料量有限， 因此由主记忆体传来的资料量就有所限制了。这也导致32位元的CPU最多只能支援最大到4GBytes的记忆体。

Tips:
字组大小与汇流排宽度是可以不同的！举例来说，在Pentium Pro时代，该CPU是32位元的处理器， 但当时的晶片组可以设计出64位元的汇流排宽度。在这样的架构下我们通常还是以CPU的字组大小来称呼该架构。 个人电脑的64位元CPU是到2003年由AMD Athlon64后才出现的。
  • CPU等级

由于x86架构的CPU在Intel的Pentium系列(1993年)后就有不统一的脚位与设计，为了将不同种类的CPU规范等级， 所以就有i386,i586,i686等名词出现了。基本上，在Intel Pentium MMX与AMD K6年代的CPU称为i586等级， 而Intel Celeron与AMD Athlon(K7)年代之后的32位元CPU就称为i686等级。 至于目前的64位元CPU则统称为x86_64等级。

目前很多的程式都有对CPU做最佳化的设计，万一哪天你发现一些程式是注明给686的CPU使用时， 就不要将他安装在586以下等级的电脑中，否则可是会无法执行该软体的！ 不过，在686倒是可以安装386的软体喔！也就是说，这些东西具有向下相容的能力啦！

记忆体

如同图2.1.3、技嘉主机板示意图中的右上方部分的那四根插槽，那就是主记忆体的插槽了。 主记忆体插槽中间通常有个突起物将整个插槽稍微切分成为两个不等长的距离， 这样的设计可以让使用者在安装主记忆体时，不至于前后脚位安插错误，是一种防呆的设计喔。

前面提到CPU所使用的资料都是来自于主记忆体(main memory)，不论是软体程式还是资料，都必须要读入主记忆体后CPU才能利用。 个人电脑的主记忆体主要元件为动态随机存取记忆体(Dynamic Random Access Memory, DRAM)， 随机存取记忆体只有在通电时才能记录与使用，断电后资料就消失了。因此我们也称这种RAM为挥发性记忆体。

DRAM根据技术的更新又分好几代，而使用上较广泛的有所谓的SDRAM与DDR SDRAM两种。 这两种记忆体的差别除了在于脚位与工作电压上的不同之外，DDR是所谓的双倍资料传送速度(Double Data Rate)， 他可以在一次工作周期中进行两次资料的传送，感觉上就好像是CPU的倍频啦！ 所以传输频率方面比SDRAM还要好。新一代的PC大多使用DDR记忆体了。 下表列出SDRAM与DDR SDRAM的型号与频率及频宽之间的关系。

SDRAM/DDR | 型号 | 资料宽度(bit) | 外频(MHz) | 频率速度 | 频宽(频率x宽度)
SDRAM | PC100 | 64 | 100 | 100 | 800MBytes/sec
SDRAM | PC133 | 64 | 133 | 133 | 1064MBytes/sec
DDR | DDR266 | 64 | 133 | 266 | 2.1GBytes/sec
DDR | DDR400 | 64 | 200 | 400 | 3.2GBytes/sec
DDR | DDRII800 | 64 | 400 | 800 | 6.4GBytes/sec

DDR SDRAM又依据技术的发展，有DDR, DDRII, DDRIII等等。

Tips:
主记忆体型号的挑选与CPU及晶片组有关，所以主机板、CPU与记忆体在购买的时候必须要考虑其相关性喔。 并不是任何主机板都可以安插DDR III的记忆体呢！

主记忆体除了频率/频宽与型号需要考虑之外，记忆体的容量也是很重要的喔！ 因为所有的资料都得要载入记忆体当中才能够被CPU判读，如果记忆体容量不够大的话将会导致某些大容量资料无法被完整的载入， 此时已存在记忆体当中但暂时没有被使用到的资料必须要先被释放，使得可用记忆体容量大于该资料，那份新资料才能够被载入呢！ 所以，通常越大的记忆体代表越快速的系统，这是因为系统不用常常释放一些记忆体内部的资料。 以伺服器来说，主记忆体的容量有时比CPU的速度还要来的重要的！

  • 双通道设计

由于所有的资料都必须要存放在主记忆体，所以主记忆体的资料宽度当然是越大越好。 但传统的汇流排宽度一般大约仅达64位元，为了要加大这个宽度，因此晶片组厂商就将两个主记忆体汇整在一起， 如果一支记忆体可达64位元，两支记忆体就可以达到128位元了，这就是双通道的设计理念。

如上所述，要启用双通道的功能你必须要安插两支(或四支)主记忆体，这两支记忆体最好连型号都一模一样比较好， 这是因为启动双通道记忆体功能时，资料是同步写入/读出这一对主记忆体中，如此才能够提升整体的频宽啊！ 所以当然除了容量大小要一致之外，型号也最好相同啦！

你有没有发现图 2.1.3、技嘉主机板示意图上那四根记忆体插槽的颜色呢？是否分为两种颜色，且两两成对？ 为什么要这样设计？答出来了吗？是啦！这种颜色的设计就是为了双通道来的！要启动双通道的功能时， 你必须要将两根容量相同的主记忆体插在相同颜色的插槽当中喔！

  • CPU时脉与主记忆体的关系

理论上，CPU与主记忆体的外频应该要相同才好。不过，因为技术方面的提升，因此这两者的频率速度不会相同， 但外频则应该是一致的较佳。举例来说，上面提到的Intel E8400 CPU外频为333MHz，则应该选用DDR II 667这个型号， 因为该记忆体型号的外频为333MHz之故喔！

  • DRAM与SRAM

除了主记忆体之外，事实上整部个人电脑当中还有许许多多的记忆体存在喔！最为我们所知的就是CPU内的第二层快取记忆体。 我们现在知道CPU的资料都是由主记忆体提供，但主记忆体的资料毕竟得经由北桥送到CPU内。 如果某些很常用的程式或资料可以放置到CPU内部的话，那么CPU资料的读取就不需要透过北桥了！ 对于效能来说不就可以大大的提升了？这就是第二层快取的设计概念。第二层快取与主记忆体及CPU的关系如下图所示：

记忆体相关性
图2.2.1、记忆体相关性

因为第二层快取(L2 cache)整合到CPU内部，因此这个L2记忆体的速度必须要CPU时脉相同。 使用DRAM是无法达到这个时脉速度的，此时就需要静态随机存取记忆体(Static Random Access Memory, SRAM)的帮忙了。 SRAM在设计上使用的电晶体数量较多，价格较高，且不易做成大容量，不过由于其速度快， 因此整合到CPU内成为快取记忆体以加快资料的存取是个不错的方式喔！新一代的CPU都有内建容量不等的L2快取在CPU内部， 以加快CPU的运作效能。

  • 唯读记忆体(ROM)

主机板上面的元件是非常多的，而每个元件的参数又具有可调整性。举例来说，CPU与记忆体的时脉是可调整的； 而主机板上面如果有内建的网路卡或者是显示卡时，该功能是否要启动与该功能的各项参数， 是被记录到主机板上头的一个称为CMOS的晶片上，这个晶片需要藉着额外的电源来发挥记录功能， 这也是为什么你的主机板上面会有一颗电池的缘故。

那CMOS内的资料如何读取与更新呢？还记得你的电脑在开机的时候可以按下[Del]按键来进入一个名为BIOS的画面吧？ BIOS(Basic Input Output System)是一套程式，这套程式是写死到主机板上面的一个记忆体晶片中， 这个记忆体晶片在没有通电时也能够将资料记录下来，那就是唯读记忆体(Read Only Memory, ROM)。 ROM是一种非挥发性的记忆体。另外，BIOS对于个人电脑来说是非常重要的， 因为他是系统在开机的时候首先会去读取的一个小程式喔！

另外，韧体(firmware)(注7)很多也是使用ROM来进行软体的写入的。 韧体像软体一样也是一个被电脑所执行的程式，然而他是对于硬体内部而言更加重要的部分。例如BIOS就是一个韧体， BIOS虽然对于我们日常操作电脑系统没有什么太大的关系，但是他却控制着开机时各项硬体参数的取得！ 所以我们会知道很多的硬体上头都会有ROM来写入韧体这个软体。

BIOS 对电脑系统来讲是非常重要的，因为他掌握了系统硬体的详细资讯与开机设备的选择等等。但是电脑发展的速度太快了， 因此 BIOS 程式码也可能需要作适度的修改才行，所以你才会在很多主机板官网找到 BIOS 的更新程式啊！但是 BIOS 原本使用的是无法改写的 ROM ，因此根本无法修正 BIOS 程式码！为此，现在的 BIOS 通常是写入类似快闪记忆体 (flash) 或 EEPROM (注8) 中。(注9)

显示卡

显示卡插槽如同图 2.1.3、技嘉主机板示意图所示，是在中央较长的插槽！ 这张主机板中提供了两个显示卡插槽喔！

显示卡又称为VGA(Video Graphics Array)，他对于图形影像的显示扮演相当关键的角色。 一般对于图形影像的显示重点在于解析度与色彩深度，因为每个图像显示的颜色会占用掉记忆体， 因此显示卡上面会有一个记忆体的容量，这个显示卡记忆体容量将会影响到最终你的荧幕解析度与色彩深度的喔！

除了显示卡记忆体之外，现在由于三度空间游戏(3D game)与一些3D动画的流行，因此显示卡的‘运算能力’越来越重要。 一些3D的运算早期是交给CPU去运作的，但是CPU并非完全针对这些3D来进行设计的，而且CPU平时已经非常忙碌了呢！ 所以后来显示卡厂商直接在显示卡上面嵌入一个3D加速的晶片，这就是所谓的GPU称谓的由来。

显示卡主要也是透过北桥晶片与CPU、主记忆体等沟通。如前面提到的，对于图形影像(尤其是3D游戏)来说， 显示卡也是需要高速运算的一个元件，所以资料的传输也是越快越好！因此显示卡的规格由早期的PCI导向AGP， 近期AGP又被PCI-Express规格所取代了。如前面技嘉主机板图示当中看到的就是PCI-Express的插槽。 这些插槽最大的差异就是在资料传输的频宽了！如下所示：

规格 | 宽度 | 速度 | 频宽
PCI | 32 bits | 33 MHz | 133 MBytes/s
PCI 2.2 | 64 bits | 66 MHz | 533 MBytes/s
PCI-X | 64 bits | 133 MHz | 1064 MBytes/s
AGP 4x | 32 bits | 66x4 MHz | 1066 MBytes/s
AGP 8x | 32 bits | 66x8 MHz | 2133 MBytes/s
PCIe x1 | 无 | 无 | 250 MBytes/s
PCIe x8 | 无 | 无 | 2 GBytes/s
PCIe x16 | 无 | 无 | 4 GBytes/s

比较特殊的是，PCIe(PCI-Express)使用的是类似管线的概念来处理，每条管线可以具有250MBytes/s的频宽效能， 管线越大(最大可达x32)则总频宽越高！目前显示卡大多使用x16的PCIe规格，这个规格至少可以达到4GBytes/s的频宽！ 比起AGP是快很多的！此外，新的PCIe 2.0规格也已经推出了，这个规格又可将每个管线的效能提升一倍呢！ 好可怕的传输量....

如果你的主机是用来打3D游戏的，那么显示卡的选购是非常重要喔！如果你的主机是用来做为网路伺服器的， 那么简单的入门级显示卡对你的主机来说就非常够用了！因为网路伺服器很少用到3D与图形影像功能。

例题：
假设你的桌面使用1024x768解析度，且使用全彩(每个像素占用3bytes的容量)，请问你的显示卡至少需要多少记忆体才能使用这样的彩度？
答：
因为1024x768解析度中会有786432个像素，每个像素占用3bytes，所以总共需要2.25MBytes以上才行！ 但如果考虑荧幕的更新率(每秒钟荧幕的更新次数)，显示卡的记忆体还是越大越好！

硬碟与储存设备

电脑总是需要记录与读取资料的，而这些资料当然不可能每次都由使用者经过键盘来打字！所以就需要有储存设备咯。 电脑系统上面的储存设备包括有：硬碟、软碟、MO、CD、DVD、磁带机、随身碟(快闪记忆体)、还有新一代的蓝光光碟机等， 乃至于大型机器的区域网路储存设备(SAN, NAS)等等，都是可以用来储存资料的。而其中最常见的应该就是硬碟了吧！

  • 硬碟的物理组成

大家应该都看过硬碟吧！硬碟依据桌上型与笔记型电脑而有分为3.5吋及2.5吋的大小。我们以3.5吋的桌上型电脑使用硬碟来说明。 在硬碟盒里面其实是由许许多多的圆形磁碟盘、机械手臂、 磁碟读取头与主轴马达所组成的，整个内部如同下图所示：

硬碟物理构造
图2.4.1、硬碟物理构造(图片取自维基百科)

实际的资料都是写在具有磁性物质的磁碟盘上头，而读写主要是透过在机械手臂上的读取头(head)来达成。 实际运作时， 主轴马达让磁碟盘转动，然后机械手臂可伸展让读取头在磁碟盘上头进行读写的动作。 另外，由于单一磁碟盘的容量有限，因此有的硬碟内部会有两个以上的磁碟盘喔！

  • 磁碟盘上的资料

既然资料都是写入磁碟盘上头，那么磁碟盘上头的资料又是如何写入的呢？ 其实磁碟盘上头的资料有点像下面的图示所示：

磁碟盘上的资料格式
图2.4.2、磁碟盘上的资料格式

整个磁碟盘上头好像有多个同心圆绘制出的圆形图，而由圆心以放射状的方式分割出磁碟的最小储存单位，那就是磁区(Sector)， 在物理组成分面，每个磁区大小为512Bytes，这个值是不会改变的。而磁区组成一个圆就成为磁轨(track)， 如果是在多碟的硬碟上面，在所有磁碟盘上面的同一个磁轨可以组成一个磁柱(Cylinder)， 磁柱也是一般我们分割硬碟时的最小单位了！

在计算整个硬碟的储存量时，简单的计算公式就是：‘header数量 * 每个header负责的磁柱数量 * 每个磁柱所含有的磁区数量 * 磁区的容量’，单位换算为‘header * cylinder/header * secter/cylinder * 512bytes/secter’，简单的写法如下： Head x Cylinder x Sector x 512 Bytes。 不过要注意的是，一般硬碟制造商在显示硬碟的容量时，大多是以十进位来编号，因此市售的500GB硬碟， 理论上仅会有460GBytes左右的容量喔！

  • 传输介面

由于传输速度的需求提升，目前硬碟与主机系统的联系主要有几种传输介面规格：

两款硬碟介面(左边为IDE介面，右边为SATA介面)
图2.4.3、两款硬碟介面(左边为IDE介面，右边为SATA介面)
  • IDE介面：

    如同图 2.1.3、技嘉主机板图示右侧的较宽的插槽所示，那就是IDE的介面插槽。 IDE介面插槽所使用的排线较宽，每条排线上面可以接两个IDE装置，由于可以接两个装置，那为了判别两个装置的主/从架构， 因此这种磁碟机上面需要调整跳针(Jump)成为Master或slave才行喔！这种介面的最高传输速度为Ultra 133规格， 亦即每秒理论传输速度可达133MBytes。

    IDE 介面的排线 (图示取自 Seagate 网站)
    图2.4.4、IDE 介面的排线 (图示取自 Seagate 网站)

  • SATA介面：

    如同技嘉主机板图示右下方所示为SATA硬碟的连接介面插槽。 我们可以看到该插槽要比IDE介面的小很多，每条SATA连接线仅能接一个SATA装置。SATA介面除了速度较快之外， 由于其排线较细小所以有利于主机机壳内部的散热与安装！目前SATA已经发展到了第二代， 其速度由SATA-1的每秒150MBytes提升到SATA-2每秒300MBytes的传输速度喔， 也因此目前主流的个人电脑硬碟已经被SATA取代了。SATA的插槽示意图如下所示：

    SATA 介面的排线 (图示取自 Seagate 网站)
    图2.4.5、SATA 介面的排线 (图示取自 Seagate 网站)

    由于SATA一条排线仅接一颗硬碟，所以你不需要调整跳针。不过一张主机板上面SATA插槽的数量并不是固定的， 且每个插槽都有编号，在连接SATA硬碟与主机板的时候，还是需要留意一下。

  • SCSI介面：

    另一种常见于工作站等级以上的硬碟传输介面为SCSI介面，这种介面的硬碟在控制器上含有一颗处理器， 所以除了运转速度快之外，也比较不会耗费CPU资源喔！在个人电脑上面这种介面的硬碟不常见啦！

  • 选购与运转须知

如果你想要增加一颗硬碟在你的主机里头时，除了需要考虑你的主机板可接受的插槽介面(IDE/SATA)之外， 还有什么要注意的呢？

  • 容量
    通常首先要考量的就是容量的问题！目前(2009)主流市场硬碟容量已经到达320GB以上，甚至有的厂商已经生产高达 2TB 的产品呢！硬碟可能可以算是一种消耗品，要注意重要资料还是得常常备份出来喔！

  • 缓冲记忆体
    硬碟上头含有一个缓冲记忆体，这个记忆体主要可以将硬碟内常使用的资料快取起来，以加速系统的读取效能。 通常这个缓冲记忆体越大越好，因为缓冲记忆体的速度要比资料从硬碟盘中被找出来要快的多了！ 目前主流的产品可达16MB左右的记忆体大小喔。

  • 转速
    因为硬碟主要是利用主轴马达转动磁碟盘来存取，因此转速的快慢会影响到效能。 主流的桌上型电脑硬碟为每分钟7200转，笔记型电脑则是5400转。有的厂商也有推出高达10000转的硬碟， 若有高效能的资料存取需求，可以考虑购买高转速硬碟。

  • 运转须知
    由于硬碟内部机械手臂上的磁头与硬碟盘的接触是很细微的空间， 如果有抖动或者是脏污在磁头与硬碟盘之间就会造成资料的损毁或者是实体硬碟整个损毁～ 因此，正确的使用电脑的方式，应该是在电脑通电之后，就绝对不要移动主机，并免抖动到硬碟， 而导致整个硬碟资料发生问题啊！另外，也不要随便将插头拔掉就以为是顺利关机！因为机械手臂必须要归回原位， 所以使用作业系统的正常关机方式，才能够有比较好的硬碟保养啊！因为他会让硬碟的机械手臂归回原位啊！
Tips:
可能因为环境的关系，电脑内部的风扇常常会卡灰尘而造成一些声响。很多朋友只要听到这种声响都是二话不说的 ‘用力拍几下机壳’就没有声音了～现在你知道了，这么做的后果常常就是你的硬碟容易坏掉！ 下次千万不要再这样做啰！
PCI介面卡

PCI介面卡的插槽就如同图2.1.3、技嘉主机板示意图所示的左下方那个白色的插槽， 这种PCI插槽通常会提供多个给使用者，如果使用者有额外需要的功能卡， 就能够安插在这种PCI介面插槽上。

我们在前面显示卡的部分稍微谈过PCI介面，事实上有相当多的元件是使用PCI介面作为传输的， 例如网路卡、音效卡、特殊功能卡等等。但由于PCI Express规格的发展，很多制造商都往PCIe介面开发硬体了。 不过还是有很多硬体使用PCI介面啦，例如大卖场上面常见的网路卡就是一个。

目前在个人电脑上面常见到的网路卡是一种称为乙太网路(Ethernet)的规格，目前乙太网路卡速度轻轻松松的就能到达10/100/1000 Mbits/second的速度，但同样速度的乙太网路卡所支援的标准可能不太一样，因此造成的价差是非常大的。 如果想要在伺服器主机上面安装新的网路卡时，得要特别注意标准的差异呢！

由于各元件的价格直直落，现在主机板上面通常已经整合了相当多的设备元件了！ 常见整合到主机板的元件包括音效卡、网路卡、USB控制卡、显示卡、磁碟阵列卡等等。 你可以在主机板上面发现很多方形的晶片，那通常是一些个别的设备晶片喔。 由于主机板已经整合了很多常用的功能晶片，所以现在的主机板上面所安插的PCI介面卡就少很多了！

主机板

主机板可以说是整部主机相当重要的一个部分，因为上面我们所谈到的所有元件都是安插在主机板上面的呢！ 而主机板上面负责沟通各个元件的就是晶片组，如同图2.1.1、Intel晶片组图示所示， 图中我们也可以发现晶片组一般分为北桥与南桥喔！北桥负责CPU/RAM/VGA等的连接，南桥则负责PCI介面与速度较慢的I/O装置。

由于晶片组负责所有设备的沟通，所以事实上晶片组(尤其是北桥)也是一个可能会散发出高热量的元件。 因此在主机板上面常会发现一些外接的小风扇或者是散热片在这组晶片上面。在本章所附的主机板图示中， 技嘉使用较高散热能力的热导管技术，因此你可以发现图中的南桥与北桥上面覆盖着黄铜色的散热片， 且连接着数根圆形导管，主要就是为了要散热的。

  • 晶片组功能

所有的晶片组几乎都是参考CPU的能力去规划的，而CPU能够接受的主记忆体规格也不相同，因此在新购买或升级主机时，CPU、主机板、主记忆体与相关的周边设备都需要同时考虑才行 ！此外，每一种晶片组的功能可能都不太相同， 有的晶片组强调的是全功能，因此连显示卡、音效、网路等都整合了，在这样的整合型晶片中， 你几乎只要购买CPU、主机板、主记忆体再加上硬碟，就能够组装成一部主机了。不过整合型晶片的效能通常比较弱， 对于爱玩3D游戏的玩家以及强调高效能运算的主机来说，就不是这么适合了。

至于独立型晶片组虽然可能具有较高的效能，不过你可能必须要额外负担周边设备的CoCo呢！ 例如显示卡、网路卡、音效卡等等。但独立型晶片组也有一定程度的好处，那就是你可以随时抽换周边设备。

  • 设备I/O位址与IRQ中断通道

主机板是负责各个电脑元件之间的沟通，但是电脑元件实在太多了，有输出/输入/不同的储存装置等等， 主机板晶片组怎么知道如何负责沟通呐？这个时候就需要用到所谓的I/O位址与IRQ啰！

I/O位址有点类似每个装置的门牌号码，每个装置都有他自己的位址，一般来说，不能有两个装置使用同一个I/O位址， 否则系统就会不晓得该如何运作这两个装置了。而除了I/O位址之外，还有个IRQ中断(Interrupt)这个咚咚。

如果I/O位址想成是各装置的门牌号码的话，那么IRQ就可以想成是各个门牌连接到邮件中心(CPU)的专门路径啰！ 各装置可以透过IRQ中断通道来告知CPU该装置的工作情况，以方便CPU进行工作分配的任务。 老式的主机板晶片组IRQ只有15个，如果你的周边介面太多时可能就会不够用， 这个时候你可以选择将一些没有用到的周边介面关掉，以空出一些IRQ来给真正需要使用的介面喔！ 当然，也有所谓的sharing IRQ的技术就是了！

  • CMOS与BIOS

前面记忆体的地方我们有提过CMOS与BIOS的功能，在这里我们再来强调一下： CMOS主要的功能为记录主机板上面的重要参数， 包括系统时间、CPU电压与频率、各项设备的I/O位址与IRQ等，由于这些资料的记录要花费电力，因此主机板上面才有电池。 BIOS为写入到主机板上某一块 flash 或 EEPROM 的程式，他可以在开机的时候执行，以载入CMOS当中的参数， 并尝试呼叫储存装置中的开机程式，进一步进入作业系统当中。BIOS程式也可以修改CMOS中的资料， 每种主机板呼叫BIOS设定程式的按键都不同，一般桌上型电脑常见的是使用[del]按键进入BIOS设定画面。

  • 连接周边设备的介面

主机板与各项输出/输入设备的连结主要都是在主机机壳的后方，主要有：

  • PS/2介面：这是常见的键盘与滑鼠的介面，不过渐渐有被USB介面取代的趋势；
  • USB介面：目前相当流行的一个介面，支援随插即用。 主流的USB版本为USB 2.0，这个规格的速度可达480Mbps，相对之下的USB 1.1仅达12Mbps差异很大，购买周边设备要注意啊！ 不然copy一些资料到USB硬碟时，会吐血....
  • 声音输出、输入与麦克风：这个是一些圆形的插孔， 而必须你的主机板上面有内建音效晶片时，才会有这三个东西；
  • RJ-45网路头：如果有内建网路晶片的话，那么就会有这种接头出现。 这种接头有点类似电话接头，不过内部有八蕊线喔！接上网路线后在这个接头上会有灯号亮起才对！
  • 其他过时介面：包括早期的用来连结滑鼠的九针序列埠(com1)，以及连结印表机的25针并列埠(LPT1)等等。

我们以技嘉主机板的连结介面来看的话，主要有这些：

连接周边介面
图2.6.1、连接周边介面
电源供应器

除了上面这些元件之外，其实还有一个很重要的元件也要来谈一谈，那就是电源供应器(Power)。 在你的机壳内，有个大大的铁盒子，上头有很多电源线会跑出来，那就是电源供应器了。 我们的CPU/RAM/主机板/硬碟等等都需要用电，而近来的电脑元件耗电量越来越高，以前很古早的230W电源已经不够用了， 有的系统甚至得要有500W以上的电源才能够运作～真可怕～

电源供应器的价差非常大！贵一点的300W可以到4000 NT，便宜一点的300W只要500 NT不到！ 怎么差这么多？没错～因为Power的用料不同，电源供应的稳定度也会差很多。如前所述，电源供应器相当于你的心脏， 心脏差的话，活动力就会不足了！所以， 稳定度差的电源供应器甚至是造成电脑不稳定的元凶呢！所以，尽量不要使用太差的电源供应器喔！

  • 能源转换率

电源供应器本身也会吃掉一部份的电力的！如果你的主机系统需要 300W 的电力时，因为电源供应器本身也会消耗掉一部份的电力， 因此你最好要挑选400W以上的电源供应器。电源供应器出厂前会有一些测试数据，最好挑选高转换率的电源供应器。 所谓的高转换率指的是‘输出的功率/输入的功率’。意思是说，假如你的主机板用电量为250W， 但是电源供应器其实已经使用掉320W的电力，则转换率为：250/320=0.78的意思。 这个数值越高表示被电源供应器‘玩掉’的电力越少，那就符合能源效益了！^_^

  • 连接介面

目前主机板与电源供应器的连接介面主要有20pin与24pin两种规格，购买时也需要考虑你的主机板所需要的规格喔！

选购须知

在购买主机时应该需要进行整体的考量，很难依照某一项标准来选购的。 老实说，如果你的公司需要一部伺服器的话，建议不要自行组装，买品牌电脑的伺服器比较好！ 这是因为自行组装的电脑虽然比较便宜，但是每项设备之间的适合性是否完美则有待自行检测。

另外，在效能方面并非仅考量CPU的能力而已，速度的快慢与‘整体系统的最慢的那个设备有关！’，如果你是使用最快速的Intel Core 2 Duo，使用最快的DDR II记忆体， 但是配上一个慢慢的过时显示卡，那么整体的3D速度效能将会卡在那个显示卡上面喔！所以，在购买整套系统时， 请特别留意需要全部的介面都考虑进去喔！尤其是当您想要升级时，要特别注意这个问题， 并非所有的旧的设备都适合继续使用的。

  • 系统不稳定的可能原因

除此之外，到底那个元件特别容易造成系统的不稳定呢？有几个常见的系统不稳定的状态是：

  • 系统超频：这个行为很不好！不要这么做！

  • 电源供应器不稳： 这也是个很严重的问题，当您测试完所有的元件都没有啥大问题时，记得测试一下电源供应器的稳定度！

  • 记忆体无法负荷：现在的记忆体品质差很多，差一点的记忆体，可能会造成您的主机在忙碌的工作时， 产生不稳定或当机的现象喔！

  • 系统过热：‘热’是造成电子零件运作不良的主因之一，如果您的主机在夏天容易当机， 冬天却还好，那么考虑一下加几个风扇吧！有助于机壳内的散热，系统会比较稳定喔！ ‘ 这个问题也是很常见的系统当机的元凶！’(鸟哥之前的一台伺服器老是容易当机， 后来拆开机壳研究后才发现原来是北桥上面的小风扇坏掉了，导致北桥温度太高。后来换掉风扇就稳定多了。)
Tips:
事实上，要了解每个硬体的详细架构与构造是很难的！这里鸟哥仅是列出一些比较基本的概念而已。 另外，要知道某个硬体的制造商是哪间公司时，可以看该硬体上面的资讯。 举例来说，主机板上面都会列出这个主机板的开发商与主机板的型号，知道这两个资讯就可以找到驱动程式了。 另外，显示卡上面有个小小的晶片，上面也会列出显示卡厂商与晶片资讯喔。
资料表示方式

事实上我们的电脑只认识0与1，记录的资料也是只能记录0与1而已，所以电脑常用的资料是二进位的。 但是我们人类常用的数值运算是十进位，文字方面则有非常多的语言，台湾常用的语言就有英文、中文(又分正体与简体中文)、日文等。 那么电脑如何记录与显示这些数值/文字呢？就得要透过一系列的转换才可以啦！底下我们就来谈谈数值与文字的编码系统啰！

小标题的图示 数字系统

早期的电脑使用的是利用通电与否的特性的真空管，如果通电就是1，没有通电就是0， 后来沿用至今，我们称这种只有0/1的环境为二进位制，英文称为binary的哩。所谓的十进位指的是逢十进一位， 因此在个位数归为零而十位数写成1。所以所谓的二进位，就是逢二就前进一位的意思。

那二进位怎么用呢？我们先以十进位来解释好了。如果以十进位来说，3456的意义为：

3456 = 3x103 + 4x102 + 5x101 + 6x100

特别注意：‘任何数值的零次方为1’所以100的结果就是1啰。 同样的，将这个原理带入二进位的环境中，我们来解释一下1101010的数值转为十进位的话，结果如下：

1101010=1x26 + 1x25 + 0x24 + 1x23 + 0x22 + 1x21 + 0x20
= 64 + 32 + 0x16 + 8 + 0x4 + 2 + 0x1 = 106

这样你了解二进位的意义了吗？二进位是电脑基础中的基础喔！了解了二进位后，八进位、十六进位就依此类推啦！ 那么知道二进位转成十进位后，那如果有十进位数值转为二进位的环境时，该如何计算？ 刚刚是乘法，现在则是除法就对了！我们同样的使用十进位的106转成二进位来测试一下好了：

二进位转十进位
图3.1.1、十进位转二进位的方法

最后的写法就如同上面的红色箭头，由最后的数字向上写，因此可得到1101010的数字啰！ 这些数字的转换系统是非常重要的，因为电脑的加减乘除都是使用这些机制来处理的！ 有兴趣的朋友可以再参考一下其他计算计概论的书籍中，关于1的补数/2的补数等运算方式喔！

文字编码系统

既然电脑都只有记录0/1而已，甚至记录的资料都是使用byte/bit等单位来记录的，那么文字该如何记录啊？ 事实上文字档案也是被记录为0与1而已，而这个档案的内容要被取出来查阅时，必须要经过一个编码系统的处理才行。 所谓的‘编码系统’可以想成是一个‘字码对照表’，他的概念有点像底下的图示：

编码表
图3.2.1、资料参考编码表的示意图

当我们要写入档案的文字资料时，该文字资料会由编码对照表将该文字转成数字后，再存入档案当中。 同样的，当我们要将档案内容的资料读出时，也会经过编码对照表将该数字转成对应的文字后，再显示到荧幕上。 现在你知道为何浏览器上面如果编码写错时，会出现乱码了吗？这是因为编码对照表写错， 导致对照的文字产生误差之故啦！

常用的英文编码表为ASCII系统，这个编码系统中， 每个符号(英文、数字或符号等)都会占用1bytes的记录， 因此总共会有28=256种变化。至于中文字当中的编码系统目前最常用的就是big5这个编码表了。 每个中文字会占用2bytes，理论上最多可以有216=65536，亦即最多可达6万多个中文字。 但是因为big5编码系统并非将所有的位元都拿来运用成为对照，所以并非可达这么多的中文字码的。 目前big5仅定义了一万三千多个中文字，很多中文利用big5是无法成功显示的～所以才会有造字程式说。

big5码的中文字编码对于某些资料库系统来说是很有问题的，某些字码例如‘许、盖、功’等字， 由于这几个字的内部编码会被误判为单/双引号，在写入还不成问题，在读出资料的对照表时， 常常就会变成乱码。不只中文字，其他非英语系国家也常常会有这样的问题出现啊！

为了解决这个问题，由国际组织ISO/IEC跳出来制订了所谓的Unicode编码系统， 我们常常称呼的UTF8或万国码的编码就是这个咚咚。因为这个编码系统打破了所有国家的不同编码， 因此目前网际网路社会大多朝向这个编码系统在走，所以各位亲爱的朋友啊，记得将你的编码系统修订一下喔！

软体程式运作

鸟哥在上课时常常会开玩笑的问：‘我们知道没有插电的电脑是一堆废铁，那么插了电的电脑是什么？’ 答案是：‘一堆会电人的废铁’！这是因为没有软体的运作，电脑的功能就无从发挥之故。 就好像没有了灵魂的躯体也不过就是行尸走肉，重点在于软体/灵魂啰！所以底下咱们就得要了解一下‘软体’是什么。

一般来说，目前的电脑系统将软体分为两大类，一个是系统软体，一个是应用程式。但鸟哥认为我们还是得要了解一下什么是程式， 尤其是机器程式，了解了之后再来探讨一下为什么现今的电脑系统需要‘作业系统’这玩意儿呢！

机器程式与编译程式

我们前面谈到电脑只认识0与1而已，而且电脑最重要的运算与逻辑判断是在CPU内部， 而CPU其实是具有微指令集的。因此，我们需要CPU帮忙工作时，就得要参考微指令集的内容， 然后撰写让CPU读的懂得指令码给CPU执行，这样就能够让CPU运作了。

不过这样的流程有几个很麻烦的地方，包括：

  • 需要了解机器语言：机器只认识0与1，因此你必须要学习直接写给机器看的语言！ 这个地方相当的难呢！

  • 需要了解所有硬体的相关功能函数：因为你的程式必须要写给机器看， 当然你就得要参考机器本身的功能，然后针对该功能去撰写程式码。例如，你要让DVD影片能够放映， 那就得要参考DVD光碟机的硬体资讯才行。万一你的系统有比较冷门的硬体，光是参考技术手册可能会昏倒～

  • 程式不具有可携性：每个CPU都有独特的微指令集，同样的，每个硬体都有其功能函数。 因此，你为A电脑写的程式，理论上是没有办法在B电脑上面运作的！而且程式码的修改非常困难！ 因为是机器码，并不是人类看的懂得程式语言啊！

  • 程式具有专一性：因为这样的程式必须要针对硬体功能函数来撰写， 如果已经开发了一支浏览器程式，想要再开发档案管理程式时，还是得从头再参考硬体的功能函数来继续撰写， 每天都在和‘硬体’挑战！可能需要天天喝蛮牛了！@_@

那怎么解决啊？为了解决这个问题，电脑科学家设计出一种让人类看的懂得程式语言， 然后创造一种‘编译器’来将这些人类能够写的程式语言转译成为机器能看懂得机器码， 如此一来我们修改与撰写程式就变的容易多了！目前常见的编译器有C, C++, Java, Fortran等等。 机器语言与高阶程式语言的差别如下所示：

编译器
图4.1.1、编译器的角色

从上面的图示我们可以看到高阶程式语言的程式码是很容易察看的！鸟哥已将经程式码(英文)写成中文说～ 这样比较好理解啦！所以这样已经将程式的修改问题处理完毕了。 问题是，在这样的环境底下我们还是得要考量整体的硬体系统来设计程式喔！

举例来说，当你需要将运作的资料写入记忆体中，你就得要自行分配一个记忆体区块出来让自己的资料能够填上去， 所以你还得要了解到记忆体的位址是如何定位的，啊！眼泪还是不知不觉的流了下来... 怎么写程式这么麻烦啊！

为了要克服硬体方面老是需要重复撰写控制码的问题，所以就有作业系统(Operating System, OS)的出现了！ 什么是作业系统呢？底下就来谈一谈先！

作业系统

如同前面提到的，在早期想要让电脑执行程式就得要参考一堆硬体功能函数，并且学习机器语言才能够撰写程式。 同时每次写程式时都必须要重新改写，因为硬体与软体功能不见得都一致之故。那如果我能够将所有的硬体都驱动， 并且提供一个发展软体的参考介面来给工程师开发软体的话，那发展软体不就变的非常的简单了？那就是作业系统啦！

  • 作业系统核心(Kernel)

作业系统(Operating System, OS)其实也是一组程式， 这组程式的重点在于管理电脑的所有活动以及驱动系统中的所有硬体。 我们刚刚谈到电脑没有软体只是一堆废铁，那么作业系统的功能就是让CPU可以开始判断逻辑与运算数值、 让主记忆体可以开始载入/读出资料与程式码、让硬碟可以开始被存取、让网路卡可以开始传输资料、 让所有周边可以开始运转等等。总之，硬体的所有动作都必须要透过这个作业系统来达成就是了。

上述的功能就是作业系统的核心(Kernel)了！你的电脑能不能做到某些事情，都与核心有关！ 只有核心有提供的功能，你的电脑系统才能帮你完成！举例来说，你的核心并不支援TCP/IP的网路协定， 那么无论你购买了什么样的网卡，这个核心都无法提供网路能力的！

但是单有核心我们使用者也不知道能作啥事的～因为核心主要在管控硬体与提供相关的能力(例如网路功能)， 这些管理的动作是非常的重要的，如果使用者能够直接使用到核心的话，万一使用者不小心将核心程式停止或破坏， 将会导致整个系统的崩溃！因此核心程式所放置到记忆体当中的区块是受保护的！ 并且开机后就一直常驻在记忆体当中。

Tips:
所以整部系统只有核心的话，我们就只能看着已经准备好运作(Ready)的电脑系统，但无法操作他！ 好像有点望梅止渴的那种感觉啦！这个时候就需要软体的帮忙了！
  • 系统呼叫(System Call)

既然我的硬体都是由核心管理，那么如果我想要开发软体的话，自然就得要去参考这个核心的相关功能！ 唔！如此一来不是从原本的参考硬体函数变成参考核心功能，还是很麻烦啊！有没有更简单的方法啊！

为了解决这个问题，作业系统通常会提供一整组的开发介面给工程师来开发软体！ 工程师只要遵守该开发介面那就很容易开发软体了！举例来说，我们学习C程式语言只要参考C程式语言的函式即可， 不需要再去考量其他核心的相关功能，因为核心的系统呼叫介面会主动的将C程式语言的相关语法转成核心可以了解的任务函数， 那核心自然就能够顺利运作该程式了！

如果我们将整个电脑系统的相关软/硬体绘制成图的话，他的关系有点像这样：

作业系统的角色
图4.2.1、作业系统的角色

电脑系统主要由硬体构成，然后核心程式主要在管理硬体，提供合理的电脑系统资源分配(包括CPU资源、记忆体使用资源等等)， 因此只要硬体不同(如x86架构与RISC架构的CPU)，核心就得要进行修改才行。 而由于核心只会进行电脑系统的资源分配，所以在上头还需要有应用程式的提供，使用者才能够操作系统的。

为了保护核心，并且让程式设计师比较容易开发软体，因此作业系统除了核心程式之外，通常还会提供一整组开发介面， 那就是系统呼叫层。软体开发工程师只要遵循公认的系统呼叫参数来开发软体，该软体就能够在该核心上头运作。 所以你可以发现，软体与核心有比较大的关系，与硬体关系则不大！硬体也与核心有比较大的关系！ 至于与使用者有关的，那就是应用程式啦！

Tips:
在定义上，只要能够让电脑硬体正确无误的运作，那就算是作业系统了。所以说， 作业系统其实就是核心与其提供的介面工具，不过就如同上面讲的，因为最阳春的核心缺乏了与使用者沟通的亲和介面， 所以在目前，一般我们提到的‘作业系统’都会包含核心与相关的使用者应用软体呢！

简单的说，上面的图示可以带给我们底下的概念：

  • 作业系统的核心层直接参考硬体规格写成， 所以同一个作业系统程式不能够在不一样的硬体架构下运作。举例来说，个人电脑版的Windows XP不能直接在RISC架构的电脑下运作。 所以您知道为何Windows XP又分为32位元及64位元的版本了吧？因为32/64位元的CPU指令集不太相同， 所以当然要设计不同的作业系统版本了。

  • 作业系统只是在管理整个硬体资源，包括CPU、记忆体、输入输出装置及档案系统档。 如果没有其他的应用程式辅助，作业系统只能让电脑主机准备妥当(Ready)而已！并无法运作其他功能。 所以你现在知道为何Windows XP上面要达成网页影像的运作还需要类似PhotoImpact或Photoshop之类的软体安装了吧？

  • 应用程式的开发都是参考作业系统提供的开发介面， 所以该应用程式只能在该作业系统上面运作而已，不可以在其他作业系统上面运作的。 现在您知道为何去购买线上游戏的光碟时，光碟上面会明明白白的写着该软体适合用于哪一种作业系统上了吧？ 也该知道某些游戏为何不能够在Linux上面安装了吧？

  • 核心功能

既然核心主要是在负责整个电脑系统相关的资源分配与管理，那我们知道其实整部电脑系统最重要的就是CPU与主记忆体， 因此，核心至少也要有这些功能的：

  • 系统呼叫介面(System call interface)
    刚刚谈过了，这是为了方便程式开发者可以轻易的透过与核心的沟通，将硬体的资源进一步的利用， 于是需要有这个简易的介面来方便程式开发者。

  • 程序管理(Process control)
    总有听过所谓的‘多工环境’吧？一部电脑可能同时间有很多的工作跑到CPU等待运算处理， 核心这个时候必须要能够控制这些工作，让CPU的资源作有效的分配才行！另外， 良好的CPU排程机制(就是CPU先运作那个工作的排列顺序)将会有效的加快整体系统效能呢！

  • 记忆体管理(Memory management)
    控制整个系统的记忆体管理，这个记忆体控制是非常重要的，因为系统所有的程式码与资料都必须要先存放在记忆体当中。 通常核心会提供虚拟记忆体的功能，当记忆体不足时可以提供记忆体置换(swap)的功能哩。

  • 档案系统管理(Filesystem management)
    档案系统的管理，例如资料的输入输出(I/O)等等的工作啦！还有不同档案格式的支援啦等等， 如果你的核心不认识某个档案系统，那么您将无法使用该档案格式的档案啰！例如：Windows 98就不认识NTFS档案格式的硬碟；

  • 装置的驱动(Device drivers)
    就如同上面提到的，硬体的管理是核心的主要工作之一，当然啰，装置的驱动程式就是核心需要做的事情啦！ 好在目前都有所谓的‘可载入模组’功能，可以将驱动程式编辑成模组，就不需要重新的编译核心啦！ 这个也会在后续的第二十章当中提到的！
Tips:
事实上，驱动程式的提供应该是硬体厂商的事情！硬体厂商要推出硬体时，应该要自行参考作业系统的驱动程式开发介面， 开发完毕后将该驱动程式连同硬体一同贩卖给使用者才对！举例来说，当你购买显示卡时， 显示卡包装盒都会附上一片光碟，让你可以在进入Windows之后进行驱动程式的安装啊！
  • 作业系统与驱动程式

老实说，驱动程式可以说是作业系统里面相当重要的一环了！不过，硬体可是持续在进步当中的！ 包括主机板、显示卡、硬碟等等。那么比较晚推出的较新的硬体，例如显示卡，我们的作业系统当然就不认识啰！ 那作业系统该如何驱动这块新的显示卡？为了克服这个问题，作业系统通常会提供一个开发介面给硬体开发商， 让他们可以根据这个介面设计可以驱动他们硬体的‘驱动程式’，如此一来，只要使用者安装驱动程式后， 自然就可以在他们的作业系统上面驱动这块显示卡了。

驱动程式与作业系统的关系
图4.2.2、驱动程式与作业系统的关系

由上图我们可以得到几个小重点：

  • 作业系统必须要能够驱动硬体，如此应用程式才能够使用该硬体功能；
  • 一般来说，作业系统会提供开发介面，让开发商制作他们的驱动程式；
  • 要使用新硬体功能，必须要安装厂商提供的驱动程式才行；
  • 驱动程式是由厂商提供的，与作业系统开发者无关。

所以，如果你想要在某个作业系统上面安装一张新的显示卡，那么请要求该硬体厂商提供适当的驱动程式吧！ ^_^！ 为什么要强调‘适当的驱动程式’呢？ 因为驱动程式仍然是依据作业系统而开发的， 所以，给Windows用的驱动程式当然不能使用于Linux的环境下了。

应用程式

应用程式是参考作业系统提供的开发介面所开发出来软体，这些软体可以让使用者操作，以达到某些电脑的功能利用。 举例来说，办公室软体(Office)主要是用来让使用者办公用的；影像处理软体主要是让使用者用来处理影音资料的； 浏览器软体主要是让使用者用来上网浏览用的等等。

需要注意的是，应用程式是与作业系统有关系的，如同上面的图示当中的说明喔。因此，如果你想要购买新软体， 请务必参考软体上面的说明，看看该软体是否能够支援你的作业系统啊！举例来说，如果你想要购买线上游戏光碟， 务必参考一下该光碟是否支援你的作业系统，例如是否支援Windows XP/Windows Vista/MAC/Linux等等。 不要购买了才发现该软体无法安装在你的作业系统上喔！

我们拿常见的微软公司的产品来说明。你知道Windows XP, Office 2007之间的关系了吗？

  • Windows XP是一套作业系统，他必须先安装到个人电脑上面，否则电脑无法开机运作；
  • Windows 98与Windows XP是两套不同的作业系统，所以能在Win 98上安装的软体不见得可在WinXP上安装；
  • Windows XP安装好后，就只能拥有很少的功能，并没有办公室软体；
  • Office 2007是一套应用程式，要安装前必须要了解他能在哪些作业系统上面运作。
重点回顾
  • 计算机的定义为：‘接受使用者输入指令与资料，经由中央处理器的数学与逻辑单元运算处理后，以产生或储存成有用的资讯’；
  • 电脑的五大单元包括：输入单元、 输出单元、CPU内部的控制单元、算数逻辑单元与主记忆体五大部分；
  • 资料会流进/流出记忆体是CPU所发布的控制命令，而CPU实际要处理的资料则完全来自于主记忆体；
  • CPU依设计理念主要分为：精简指令集(RISC)与复杂指令集(CISC)系统；
  • 关于CPU的时脉部分：外频指的是CPU与外部元件进行资料传输时的速度，倍频则是CPU内部用来加速工作效能的一个倍数， 两者相乘才是CPU的时脉速度；
  • 一般主机板晶片组有分北桥与南桥，北桥的汇流排称为系统汇流排，因为是记忆体传输的主要通道，所以速度较快。 南桥就是所谓的输入输出(I/O)汇流排，主要在联系硬碟、USB、网路卡等周边设备；
  • 北桥所支援的频率我们称为前端汇流排速度(Front Side Bus, FSB)，而每次传送的位元数则是汇流排宽度。
  • CPU每次能够处理的资料量称为字组大小(word size)，字组大小依据CPU的设计而有32位元与64位元。 我们现在所称的电脑是32或64位元主要是依据这个 CPU解析的字组大小而来的！
  • 个人电脑的主记忆体主要元件为动态随机存取记忆体(Dynamic Random Access Memory, DRAM)， 至于CPU内部的第二层快取则使用静态随机存取记忆体(Static Random Access Memory, SRAM)；
  • BIOS(Basic Input Output System)是一套程式，这套程式是写死到主机板上面的一个记忆体晶片中， 这个记忆体晶片在没有通电时也能够将资料记录下来，那就是唯读记忆体(Read Only Memory, ROM)；
  • 显示卡的规格有PCI/AGP/PCIe，目前的主流为PCIe介面；
  • 硬碟的组成为：圆形磁碟盘、机械手臂、 磁碟读取头与主轴马达所组成的，其中磁碟盘的组成为磁区、磁轨与磁柱；
  • 作业系统(Operating System, OS)其实也是一组程式， 这组程式的重点在于管理电脑的所有活动以及驱动系统中的所有硬体。
  • 电脑主要以二进位作为单位，常用的磁碟容量单位为bytes，其单位换算为1 Byte = 8bits。
  • 最阳春的作业系统仅在驱动与管理硬体，而要使用硬体时，就得需要透过应用软体或者是壳程式(shell)的功能， 来呼叫作业系统操纵硬体工作。目前称为作业系统的，除了上述功能外，通常已经包含了日常工作所需要的应用软体在内了。
本章习题
  • 动动手实作题：假设你不知道你的主机内部的各项元件资料，请拆开你的主机机壳，并将内部所有的元件拆开，并且依序列出：
    • CPU的厂牌、型号、最高时脉；
    • 主记忆体的容量、介面 (DDR/DDR II等)；
    • 显示卡的介面 (AGP/PCIe/内建) 与容量
    • 主机板的厂牌、南北桥的晶片型号、BIOS的厂牌、有无内建的网卡或音效卡等
    • 硬碟的连接介面 (IDE/SATA等)、硬碟容量、转速、缓冲记忆体容量等。
    然后再将他组装回去。注意，拆装前务必先取得你主机板的说明书，因此你可能必须要上网查询上述的各项资料。

  • 利用软体：假设你不想要拆开主机机壳，但想了解你的主机内部各元件的资讯时，该如何是好？ 如果使用的是Windows作业系统，可使用CPU-Z(http://www.cpuid.com/cpuz.php)这套软体，如果是Linux环境下，可以使用‘cat /proc/cpuinfo’ 及使用‘lspci’来查阅各项元件的型号；

  • 依据文末的延伸阅读连结，自行搜寻出 BIOS 的主要任务，以及目前在个人电脑上面常见的 BIOS 制造商有哪几家？
参考资料与延伸阅读
  • 注1：对于CPU的原理有兴趣的读者，可以参考维基百科的说明：
    英文CPU(http://en.wikipedia.org/wiki/CPU)
    中文CPU(http://zh.wikipedia.org/wiki/中央处理器)。
  • 注2：图片参考：作者：陈锦辉，‘计算机概论-探索未来2008’，金禾资讯，2007出版
  • 注3：更详细的RISC架构可以参考维基百科：
    http://zh.wikipedia.org/w/index.php?title=精简指令集&variant=zh-tw
  • 注4：关于ARM架构的说明，可以参考维基百科：
    http://zh.wikipedia.org/w/index.php?title=ARM架构&variant=zh-tw
  • 注5：更详细的CISC架构可参考维基百科：
    http://zh.wikipedia.org/w/index.php?title=CISC&variant=zh-tw
  • 注6：更详细的x86架构发展史可以参考维基百科：
    http://zh.wikipedia.org/w/index.php?title=X86&variant=zh-tw
  • 注7：相关的韧体说明可参考维基百科：
    http://zh.wikipedia.org/w/index.php?title=韧体&variant=zh-hant
  • 注8：相关 EEPROM 可以参考维基百科：
    http://zh.wikipedia.org/w/index.php?title=EEPROM&variant=zh-tw
  • 注9：相关 BIOS 的说明可以参考维基百科：
    http://zh.wikipedia.org/w/index.php?title=BIOS&variant=zh-tw
  • 感谢：本章当中出现很多图示，很多是从Tom's Hardware(http://www.tomshardware.tw/)网站取得的，在此特别感谢！
2008/07/22：利用暑假期间足足写了快要两个星期这篇才写完！好多图示都不知道如何呈现比较漂亮～@_@
2008/07/29：又加入了SATA/IDE的连线排线，还有一些额外的图示。
2009/08/03：加入电源供应器是心脏一词的说明
2009/08/03：更正原本 BIOS 只放于 ROM 的资料，新的 BIOS 通常放于 EEPROM 或 Flash 记忆体中。


鸟哥的 Linux 私房菜 -- 基础学习篇

为取得较佳浏览结果，请爱用 firefox 浏览本网页
鸟哥的 Linux 私房菜馆 | Linux 基础文件 | Linux 架站文件 | Linux 企业运用 | 安全管理 | 新手讨论 |

第一章、Linux是什么
最近更新日期：2009/08/05
众所皆知的，Linux的核心原型是1991年由托瓦兹(Linus Torvalds)写出来的，但是托瓦兹为何可以写出Linux这个作业系统？ 为什么他要选择386的电脑来开发？为什么Linux的发展可以这么迅速？又为什么Linux是免费的？ 以及目前为何有这么多的Linux版本(distributions)呢？了解这些东西后，才能够知道为何Linux可以免除专利软体之争， 并且了解到Linux为何可以同时在个人电脑与大型主机上面大放异彩！ 所以，在实际进入Linux的世界前，就让我们来谈一谈这些有趣的历史故事吧！ ^_^

1. Linux是什么
    1.1 Linux是什么
1.2 Linux之前，Unix的历史
1.3 关于GNU计划
 2. Torvalds的Linux发展
    2.1 与Minix之间
2.2 对386硬体的多工测试
2.3 初次释出Linux 0.02
2.4 Linux的发展：虚拟团队的产生
2.5 Linux 的核心版本
2.6 Linux distributions
 3. Linux的特色
    3.1 Linux的特色
3.2 Linux的优缺点
3.3 关于授权
 4. 重点回顾
5. 本章习题
6. 参考资料与延伸阅读
7. 针对本文的建议：http://phorum.vbird.org/viewtopic.php?t=23871
大标题的图示 Linux是什么

我们知道Linux这玩意儿是在电脑上面运作的，所以说Linux就是一组软体。问题是这个软体是作业系统还是应用程式？ 且Linux可以在哪些种类的电脑上面运作？而Linux源自哪里？为什么 Linux 还不用钱？这些我们都得来谈一谈先！

小标题的图示 Linux是什么

我们在第零章、计算机概论里面有提到过整个电脑系统的概念， 电脑是由一堆硬体所组成的，为了有效率的控制这些硬体资源，于是乎就有作业系统的产生了。 作业系统除了有效率的控制这些硬体资源的分配，并提供电脑运作所需要的功能(如网路功能)之外， 为了要提供程式设计师更容易开发软体的环境，所以作业系统也会提供一整组系统呼叫介面来给软体设计师开发用喔！

知道为什么要讲这些了吗？嘿嘿！没错，因为Linux就是一套作业系统！如同下图所示， Linux就是核心与系统呼叫介面那两层。至于应用程式算不算Linux呢？当然不算啦！这点要特别注意喔！

作业系统的角色
图1.1.1、作业系统的角色

由上图中我们可以看到其实核心与硬体的关系非常的强烈。早期的Linux是针对386来开发的， 由于Linux只是一套作业系统并不含有其他的应用程式，因此很多工程师在下载了 Linux 核心并且实际安装之后，就只能看着电脑开始运作了！ 接下来这些高级工程师为了自己的需求，再在Linux上面安装他们所需要的软体就是了。

Tips:
Torvalds先生在写出Linux的时候，其实该核心仅能‘驱动386所有的硬体’而已， 所谓的‘让386电脑开始运作，并且等待使用者指令输入’而已，事实上， 当时能够在Linux上面跑的软体还很少呢！ 		鸟哥的图示

由于不同的硬体他的功能函数并不相同，例如IBM的Power CPU与Intel的x86架构就是不一样！ 所以同一套作业系统是无法在不同的硬体平台上面运作的！举例来说，如果你想要让x86上面跑的那套作业系统也能够在Power CPU上运作时，就得要将该作业系统进行修改才行。如果能够参考硬体的功能函数并据以修改你的作业系统程式码， 那经过改版后的作业系统就能够在另一个硬体平台上面运作了。 这个动作我们通常就称为‘软体移植’了！

例题：
请问Windows作业系统能否在苹果公司的麦金塔电脑(MAC)上面安装与运作？
答：
由上面的说明中，我们知道硬体是由‘核心’来控制的，而每种作业系统都有他自己的核心。 在2006年以前的苹果电脑公司是请IBM公司帮忙开发硬体(所谓的Power CPU)， 而苹果电脑公司则在该硬体架构上发展自家的作业系统(就是俗称的麦金塔，MAC是也)。Windows则是开发在x86架构上的作业系统之一， 因此Windows是没有办法安装到麦金塔电脑硬体上面的。

不过，在2006年以后，苹果电脑转而请Intel设计其硬体架构，亦即其硬体架构已经转为x86系统， 因此在2006年以后的苹果电脑若使用x86架构时，其硬体则‘可能’可以安装Windows作业系统了。 不过，你可能需要自己想些方式来处理该硬体的相容性啰！

Tips:
Windows作业系统本来就是针对个人电脑x86架构的硬体去设计的，所以他当然只能在x86的个人电脑上面运作， 在不同的平台当然就无法运行了。也就是说，每种作业系统都是在他专门的机器上面运行的喔！这点得要先了解。 不过，Linux由于是Open Source的作业系统，所以他的程式码可以被修改成适合在各种机器上面运行的， 也就是说，Linux是具有‘可移植性’，这可是很重要的一个功能喔！ ^_^ 		鸟哥的图示

Linux提供了一个完整的作业系统当中最底层的硬体控制与资源管理的完整架构， 这个架构是沿袭Unix良好的传统来的，所以相当的稳定而功能强大！此外， 由于这个优良的架构可以在目前的个人电脑(x86系统)上面跑， 所以很多的软体开发者渐渐的将他们的工作心血移转到这个架构上面，所以 Linux 作业系统也有很多的应用软体啦！

虽然Linux仅是其核心与核心提供的工具，不过由于核心、核心工具与这些软体开发者提供的软体的整合， 使得Linux成为一个更完整的、功能强大的作业系统啰！约略了解Linux是何物之后，接下来，我们要谈一谈， ‘为什么说Linux是很稳定的作业系统呢？他是如何来的？’

小标题的图示 Linux之前，Unix的历史

早在Linux出现之前的二十年(大约在1970 年代)，就有一个相当稳定而成熟的作业系统存在了！ 那就是Linux的老大哥‘Unix’是也！怎么这么说呢？他们这两个家伙有什么关系呀？这里就给他说一说啰！

众所皆知的，Linux的核心是由Linus Torvalds在1991年的时候给他开发出来的， 并且丢到网路上提供大家下载，后来大家觉得这个小东西(Linux Kernel)相当的小而精巧， 所以慢慢的就有相当多的朋友投入这个小东西的研究领域里面去了！ 但是为什么这的小东西这么棒呢？又为什么大家都可以免费的下载这个东西呢？ 嗯！等鸟哥慢慢的唬xx....喔不！听我慢慢的道来！

  • 1969年以前：一个伟大的梦想--Bell,MIT与GE的‘Multics’系统

早期的电脑并不像现在的个人电脑一样普遍，他可不是一般人碰的起的呢～ 除非是军事或者是高科技用途，或者是学术单位的学术研究，否则真的很难接触到。 非但如此，早期的电脑架构还很难使用，除了运算速度并不快之外，操作介面也很困扰的！ 因为那个时候的输入设备只有读卡机、输出设备只有印表机， 使用者也无法与作业系统互动(批次型作业系统)。

在那个时候，写程式是件很可怜的事情，因为程式设计者，必须要将程式相关的资讯在读卡纸上面打洞， 然后再将读卡纸插入读卡机来将资讯读入主机中运算。光是这样就很麻烦了，如果程式有个小地方写错， 哈哈！光是重新打卡就很惨，加上主机少，使用者众多，光是等待，就耗去很多的时间了！

在那之后，由于硬体与作业系统的改良，使得后来可以使用键盘来进行资讯的输入。 不过，在一间学校里面，主机毕竟可能只有一部，如果多人等待使用，那怎么办？大家还是得要等待啊！ 好在1960年代初期麻省理工学院(MIT)发展了所谓的： ‘相容分时系统(Compatible Time-Sharing System, CTSS)’， 它可以让大型主机透过提供数个终端机(terminal)以连线进入主机，来利用主机的资源进行运算工作。 架构有点像这样：

早期主机与终端机的相关性图示
图1.2.1、早期主机与终端机的相关性图示
Tips:
这个相容分时系统可以说是近代作业系统的始祖呢！他可以让多个使用者在某一段时间内分别使用CPU的资源， 感觉上你会觉得大家是同时使用该主机的资源！事实上，是CPU在每个使用者的工作之间进行切换， 在当时，这可是个划时代的技术喔！ 		鸟哥的图示

如此一来，无论主机在哪里，只要在终端机前面进行输入输出的作业，就可利用主机提供的功能了。 不过，需要注意的是，此时终端机只具有输入/输出的功能，本身完全不具任何运算或者软体安装的能力。 而且，比较先进的主机大概也只能提供30个不到的终端机而已。

为了更加强化大型主机的功能，以让主机的资源可以提供更多使用者来利用，所以在1965年前后， 由贝尔实验室(Bell)、麻省理工学院(MIT)及奇异公司(GE, 或称为通用电器)共同发起了Multics的计划， Multics计划的目的是想要让大型主机可以达成提供300个以上的终端机连线使用的目标。 不过，到了1969年前后，计划进度落后，资金也短缺，所以该计划虽然继续在研究，但贝尔实验室还是退出了该计划的研究工作。 (注：Multics有复杂、多数的意思存在。)

Tips:
最终Multics还是有成功的发展出他们的系统，完整的历史说明可以参考： http://www.multicians.org/网站内容。 Multics计划虽然后来没有受到很大的重视，但是他培养出来的人材是相当优秀的！ ^_^ 		鸟哥的图示
  • 1969年：Ken Thompson的小型file server system

在认为Multics计划不可能成功之后，贝尔研究室就退出该计划。不过，原本参与Multics计划的人员中，已经从该计划当中获得一些点子， Ken Thompson 就是其中一位！

Thompson因为自己的需要，希望开发一个小小的作业系统以提供自己的需求。 在开发时，有一部DEC(Digital Equipment Corporation)公司推出的PDP-7刚好没人使用， 于是他就准备针对这部主机进行作业系统核心程式的撰写。本来Thompson应该是没时间的(有家有小孩的宿命？)， 无巧不巧的是，在1969年八月份左右，刚好Thompson的妻儿去了美西探亲， 于是他有了额外的一个月的时间好好的待在家将一些构想实现出来！

经过四个星期的奋斗，他终于以组合语言(Assembler)写出了一组核心程式，同时包括一些核心工具程式， 以及一个小小的档案系统。那个系统就是Unix的原型！ 当时Thompson将Multics庞大的复杂系统简化了不少，于是同实验室的朋友都戏称这个系统为：Unics。(当时尚未有Unix的名称)

Thompson 的这个档案系统有两个重要的概念，分别是：

  • 所有的程式或系统装置都是档案
  • 不管建构编辑器还是附属档案，所写的程式只有一个目的，且要有效的完成目标。

这些概念在后来对于Linux的发展有相当重要的影响喔！

Tips:
套一句常听到的广告词：‘科技始终来自于人性’，当初Thompson会写这套Unix核心程式， 却是想要移植一套名为‘太空旅游’的游戏呢！ ^_^ 		鸟哥的图示
  • 1973年：Unix的正式诞生，Ritchie等人以C语言写出第一个正式Unix核心

由于Thompson写的那个作业系统实在太好用了，所以在贝尔实验室内部广为流传，并且数度经过改版。 但是因为Unics本来是以组合语言写成的，而如第零章计算机概论谈到的， 组合语言具有专一性，加上当时的电脑机器架构都不太相同，所以每次要安装到不同的机器都得要重新编写组合语言，真不方便！

后来Thompson与Ritchie合作想将Unics改以高阶程式语言来撰写。当时现成的高阶程式语言有B语言。 但是由B语言所编译出来的核心效能不是很好。后来Dennis Ritchie将B语言重新改写成C语言，再以C语言重新改写与编译Unics的核心， 最后正名与发行出Unix的正式版本！

Tips:
这群高级骇客实在很厉害！因为自己的需求来开发出这么多好用的工具！ C程式语言开发成功后，甚至一直沿用至今呢！你说厉不厉害啊！这个故事也告诉我们，不要小看自己的潜能喔！ 你想作的，但是现实生活中没有的，就动手自己搞一个来玩玩吧！ 		鸟哥的图示

由于贝尔实验室是隶属于美国电信大厂AT&T公司的， 只是AT&T当时忙于其他商业活动，对于Unix并不支持也不排斥。此外，Unix在这个时期的发展者都是贝尔实验室的工程师， 这些工程师对于程式当然相当有研究，所以，Unix在此时当然是不容易被一般人所接受的！不过对于学术界的学者来说， 这个 Unix 真是学者们进行研究的福音！因为程式码可改写并且可作为学术研究之用嘛！

需要特别强调的是，由于Unix是以较高阶的C语言写的，相对于组合语言需要与硬体有密切的配合， 高阶的C语言与硬体的相关性就没有这么大了！所以，这个改变也使得Unix很容易被移植到不同的机器上面喔！

  • 1977年：重要的Unix分支--BSD的诞生

虽然贝尔属于AT&T，但是AT&T此时对于Unix是采取较开放的态度，此外，Unix是以高阶的C语言写成的， 理论上是具有可移植性的！亦即只要取得Unix的原始码，并且针对大型主机的特性加以修订原有的原始码(Source Code)， 就可能将Unix移植到另一部不同的主机上头了。所以在1973年以后，Unix便得以与学术界合作开发！ 最重要的接触就是与加州柏克莱(Berkeley)大学的合作了。

柏克莱大学的Bill Joy在取得了Unix的核心原始码后，着手修改成适合自己机器的版本， 并且同时增加了很多工具软体与编译程式，最终将它命名为Berkeley Software Distribution (BSD)。这个BSD是Unix很重要的一个分支，Bill Joy也是Unix业者‘Sun(升阳)’这家公司的创办者！ Sun公司即是以BSD发展的核心进行自己的商业Unix版本的发展的。 (后来可以安装在x86硬体架构上面FreeBSD即是BSD改版而来！)

  • 1979年：重要的 System V 架构与版权宣告

由于Unix的高度可移植性与强大的效能，加上当时并没有版权的纠纷， 所以让很多商业公司开始了Unix作业系统的发展，例如AT&T自家的System V、IBM的AIX以及HP与DEC等公司， 都有推出自家的主机搭配自己的Unix作业系统。

但是，如同我们前面提到的，作业系统的核心(Kernel)必须要跟硬体配合， 以提供及控制硬体的资源进行良好的工作！而在早期每一家生产电脑硬体的公司还没有所谓的‘协定’的概念， 所以每一个电脑公司出产的硬体自然就不相同啰！因此他们必须要为自己的电脑硬体开发合适的Unix系统。 例如在学术机构相当有名的Sun、Cray与HP就是这一种情况。 他们开发出来的Unix作业系统以及内含的相关软体并没有办法在其他的硬体架构下工作的！ 另外，由于没有厂商针对个人电脑设计Unix系统，因此，在早期并没有支援个人电脑的Unix作业系统的出现。

Tips:
如同相容分时系统的功能一般，Unix强调的是多人多工的环境！ 但早期的286个人电脑架构下的CPU是没有能力达到多工的作业，因此，并没有人对移植Unix到x86的电脑上有兴趣。 		鸟哥的图示

每一家公司自己出的Unix虽然在架构上面大同小异，但是却真的仅能支援自身的硬体， 所以啰，早先的Unix只能与伺服器(Server)或者是大型工作站(Workstation)划上等号！ 但到了 1979 年时，AT&T推出 System V 第七版 Unix 后，这个情况就有点改善了。 这一版最重要的特色是可以支援x86架构的个人电脑系统，也就是说 System V 可以在个人电脑上面安装与运作了。

不过因为AT&T由于商业的考量，以及在当时现实环境下的思考，于是将想Unix的版权收回去。因此， AT&T在1979年发行的第七版Unix中，特别提到了 ‘不可对学生提供原始码’的严格限制！ 同时，也造成Unix业界之间的紧张气氛，并且也引爆了很多的商业纠纷～

Tips:
目前被称为纯种的Unix指的就是System V以及BSD这两套啰！ 		鸟哥的图示
  • 1984年之一：x86架构的Minix作业系统诞生

关于1979年的版权声明中，影响最大的当然就是学校教Unix核心原始码相关学问的教授了！ 想一想，如果没有核心原始码，那么如何教导学生认识Unix呢？这问题对于Andrew Tanenbaum(谭宁邦)教授来说，实在是很伤脑筋的！不过，学校的课程还是得继续啊！那怎么办？

既然1979年的Unix第七版可以在Intel的x86架构上面进行移植， 那么是否意味着可以将Unix改写并移植到x86上面了呢？在这个想法上， 谭宁邦教授于是乎自己动手写了Minix这个Unix Like的核心程式！ 在撰写的过程中，为了避免版权纠纷，谭宁邦完全不看Unix核心原始码！ 并且强调他的Minix必须能够与Unix相容才行！谭宁邦在1984年开始撰写核心程式， 到了1986年终于完成，并于次年出版Minix相关书籍，同时与新闻群组(BBS及News)相结合～

Tips:
之所以称为Minix的原因，是因为他是个Mini的Unix系统啰！^_^ 		鸟哥的图示

这个Minix版本比较有趣的地方是，他并不是完全免费的，无法在网路上提供下载！ 必须要透过磁片/磁带购买才行！虽然真的很便宜～不过，毕竟因为没有在网路上流传， 所以Minix的传递速度并没有很快速！此外，购买时，随磁片还会附上Minix的原始码！ 这意味着使用者可以学习Minix的核心程式设计概念喔！ (这个特色对于Linux的启始开发阶段，可是有很大的关系喔！)

此外，Minux作业系统的开发者仅有谭宁邦教授，因为学者很忙啊！加上谭宁邦始终认为Minix主要用在教育用途上面， 所以对于Minix是点到为止！没错，Minix是很受欢迎，不过，使用者的要求/需求的声音可能就比较没有办法上升到比较高的地方了！ 这样说，你明白吧？^_^

  • 1984年之二：GNU计划与FSF基金会的成立

Richard Mathew Stallman(史托曼)在1984年发起的GNU计划，对于现今的自由软体风潮， 真有不可磨灭的地位！目前我们所使用得很多自由软体，几乎均直接或间接受益于GNU这个计划呢！ 那么史托曼是何许人也？为何他会发起这个GNU计划呢？

  • 一个分享的环境：

    Richard Mathew Stallman(生于1953年， 网路上自称的ID为RMS)从小就很聪明！他在1971年的时候，进入骇客圈中相当出名的人工智慧实验室(AI Lab.)， 这个时候的骇客专指电脑功力很强的人，而非破坏电脑的怪客(cracker)喔！

    当时的骇客圈对于软体的着眼点几乎都是在‘分享’，所以并没有专利方面的困扰！ 这个特色对于史托曼的影响很大！不过，后来由于管理阶层的问题，导致实验室的优秀骇客离开该实验室， 并且进入其他商业公司继续发展优秀的软体。但史托曼并不服输，仍然持续在原来的实验室开发新的程式与软体。 后来，他发现到，自己一个人并无法完成所有的工作，于是想要成立一个开放的团体来共同努力！

  • 使用Unix开发阶段：

    1983年以后，因为实验室硬体的更换，使得史托曼无法继续以原有的硬体与作业系统继续自由程式的撰写～ 而且他进一步发现到，过去他所使用的Lisp作业系统，是麻省理工学院的专利软体， 是无法共享的，这对于想要成立一个开放团体的史托曼是个阻碍。于是他便放弃了Lisp这个系统。 后来，他接触到Unix这个系统，并且发现，Unix在理论与实际上，都可以在不同的机器间进行移植。虽然 Unix 依旧是专利软体， 但至少 Unix 架构上还是比较开放的！于是他开始转而使用Unix系统。

    因为Lisp与Unix是不同的系统，所以，他原本已经撰写完毕的软体是无法在Unix上面运行的！为此， 他就开始将软体移植到Unix上面。并且，为了让软体可以在不同的平台上运作， 因此，史托曼将他发展的软体均撰写成可以移植的型态！也就是他都会将程式的原始码公布出来！

  • GNU计划的推展：

    1984年，史托曼开始GNU计划， 这个计划的目的是：建立一个自由、开放的Unix作业系统(Free Unix)。 但是建立一个作业系统谈何容易啊！而且在当时的GNU是仅有自己一个人单打独斗的史托曼～ 这实在太麻烦，但又不想放弃这个计划，那可怎么办啊？

    聪明的史托曼干脆反其道而行～‘既然作业系统太复杂，我就先写可以在Unix上面运行的小程式，这总可以了吧？’在这个想法上， 史托曼开始参考Unix上面现有的软体，并依据这些软体的作用开发出功能相同的软体，且开发期间史托曼绝不看其他软体的原始码， 以避免吃上官司。后来一堆人知道免费的GNU软体，并且实际使用后发现与原有的专利软体也差不了太多，于是便转而使用GNU软体， 于是GNU计划逐渐打开知名度。

    虽然GNU计划渐渐打开知名度，但是能见度还是不够。这时史托曼又想：不论是什么软体， 都得要进行编译成为二进位档案(binary program)后才能够执行，如果能够写出一个不错的编译器，那不就是大家都需要的软体了吗？ 因此他便开始撰写C语言的编译器，那就是现在相当有名的GNU C Compiler(gcc)！ 这个点相当的重要！这是因为C语言编译器版本众多，但都是专利软体， 如果他写的C编译器够棒，效能够佳，那么将会大大的让GNU计划出现在众人眼前！如果忘记啥是编译器， 请回到第零章去瞧瞧编译程式吧！

    但开始撰写GCC时并不顺利，为此，他先转而将他原先就已经写过的Emacs编辑器写成可以在Unix上面跑的软体，并公布原始码。 Emacs是一种程式编辑器，他可以在使用者撰写程式的过程中就进行程式语法的检验，此一功能可以减少程式设计师除错的时间！ 因为Emacs太优秀了，因此，很多人便直接向他购买。

    此时网际网路尚未流行，所以，史托曼便藉着Emacs以磁带(tape)出售，赚了一点钱 ，进而开始全力撰写其他软体。并且成立自由软体基金会(FSF, Free Software Foundation)，请更多工程师与志工撰写软体。终于还是完成了GCC，这比Emacs还更有帮助！ 此外，他还撰写了更多可以被呼叫的C函式库(GNU C library)，以及可以被使用来操作作业系统的基本介面BASH shell！ 这些都在1990年左右完成了！

    Tips:
    如果纯粹使用文字编辑器来编辑程式的话，那么程式语法如果写错时，只能利用编译时发生的错误讯息来修订了，这样实在很没有效率。 Emacs则是一个很棒的编辑器！注意！是编辑(editor)而非编译(compiler)！ 他可以很快的立刻显示出你写入的语法可能有错误的地方，这对于程式设计师来说， 实在是一个好到不能再好的工具了！所以才会这么的受到欢迎啊！     		鸟哥的图示
  • GNU的通用公共许可证：

    到了1985年，为了避免GNU所开发的自由软体被其他人所利用而成为专利软体， 所以他与律师草拟了有名的通用公共许可证(General Public License, GPL)， 并且称呼他为copyleft(相对于专利软体的copyright！)。 关于GPL的相关内容我们在下一个小节继续谈论，在这里，必须要说明的是， 由于有GNU所开发的几个重要软体，如：

    • Emacs
    • GNU C (GCC)
    • GNU C Library (glibc)
    • Bash shell

    造成后来很多的软体开发者可以藉由这些基础的工具来进行程式开发！ 进一步壮大了自由软体团体！这是很重要的！不过，对于GNU的最初构想 ‘建立一个自由的Unix作业系统’来说，有这些优秀的程式是仍无法满足， 因为，当下并没有‘自由的Unix核心’存在...所以这些软体仍只能在那些有专利的 Unix平台上工作～～一直到Linux的出现...更多的FSF开发的软体可以参考如下网页：

    • https://www.fsf.org/resources

  • 1988年：图形介面XFree86计划

有鉴于图形使用者介面(Graphical User Interface, GUI) 的需求日益加重，在1984年由MIT与其他协力厂商首次发表了X Window System ，并且更在1988年成立了非营利性质的XFree86这个组织。所谓的XFree86其实是 X Window System + Free + x86的整合名称呢！ 而这个XFree86的GUI介面更在Linux的核心1.0版于1994年释出时，整合于Linux作业系统当中！

Tips:
为什么称图形使用者介面为X呢？因为由英文单字来看，Window的W接的就是X啦！意指Window的下一版就是了！ 需注意的是，X Window并不是X Windows喔！ 		鸟哥的图示
  • 1991年：芬兰大学生Linus Torvalds的一则简讯

到了1991年，芬兰的赫尔辛基大学的Linus Torvalds在BBS上面贴了一则消息， 宣称他以bash, gcc等工具写了一个小小的核心程式，这个核心程式可以在Intel的386机器上面运作， 让很多人很感兴趣！从此开始了Linux不平凡的路程！

小标题的图示 关于GNU计划

GNU计划对于整个自由软体来说是占有非常重要的角色！底下我们就来谈谈这咚咚吧！

  • 自由软体的活动：

1984年创立GNU计划与FSF基金会的Stallman先生认为，写程式最大的快乐就是让自己发展的良好的软体让大家来使用了！ 而既然程式是想要分享给大家使用的，不过，每个人所使用的电脑软硬体并不相同， 既然如此的话，那么该程式的原始码(Source code)就应该要同时释出， 这样才能方便大家修改而适用于每个人的电脑中呢！这个将原始码连同软体程式释出的举动， 就称为自由软体(Free Software)运动！

此外，史托曼同时认为，如果你将你程式的Source code分享出来时，若该程式是很优秀的，那么将会有很多人使用， 而每个人对于该程式都可以查阅source code，无形之中，就会有一票人帮你除错啰！ 你的这支程式将会越来越壮大！越来越优秀呢！

  • 自由软体的版权GNU GPL：

而为了避免自己的开发出来的Open source自由软体被拿去做成专利软体， 于是Stallman同时将GNU与FSF发展出来的软体，都挂上GPL的版权宣告～ 这个FSF的核心观念是‘版权制度是促进社会进步的手段， 版权本身不是自然权力。’对于FSF有兴趣或者对于GNU想要更深入的了解时，请参考朝阳科技大学洪朝贵教授的网站 http://people.ofset.org/~ckhung/a/c_83.php，或直接到GNU去： http://www.gnu.org 里面有更为深入的解说！

Tips:
为什么要称为GNU呢？其实GNU是GNU's Not Unix的缩写，意思是说，GNU并不是Unix啊！那么GNU又是什么呢？ 就是GNU's Not Unix嘛！.....如果你写过程式就会知道，这个GNU = GNU's Not Unix可是无穷回圈啊！忙碌～

另外，什么是Open Source呢？所谓的source是程式发展者写出的原始程式码， Open Source就是，软体在发布时，同时将作者的原始码一起公布的意思！ 		鸟哥的图示
  • 自由(Free)的真谛：

那么这个GPL(GNU General Public License, GPL)是什么玩意儿？ 为什么要将自由软体挂上GPL的‘版权宣告’呢？这个版权宣告对于作者有何好处？ 首先，Stallman对GPL一直是强调Free的，这个Free的意思是这样的：

"Free software" is a matter of liberty, not price. To understand the concept, you should think of "free speech", not "free beer". "Free software" refers to the users' freedom to run, copy, distribute, study, change, and improve the software

大意是说，Free Software(自由软体)是一种自由的权力，并非是‘价格！’ 举例来说，你可以拥有自由呼吸的权力、你拥有自由发表言论的权力， 但是，这并不代表你可以到处喝‘免费的啤酒！(free beer)’，也就是说， 自由软体的重点并不是指‘免费’的，而是指具有‘自由度, freedom’的软体， 史托曼进一步说明了自由度的意义是： 使用者可以自由的执行、复制、再发行、学习、修改与强化自由软体。

这无疑是个好消息！因为如此一来，你所拿到的软体可能原先只能在Unix上面跑， 但是经过原始码的修改之后，你将可以拿他在Linux或者是Windows上面来跑！总之， 一个软体挂上了GPL版权宣告之后，他自然就成了自由软体！这个软体就具有底下的特色：

  • 取得软体与原始码：你可以根据自己的需求来执行这个自由软体；
  • 复制：你可以自由的复制该软体；
  • 修改：你可以将取得的原始码进行程式修改工作，使之适合你的工作；
  • 再发行：你可以将你修改过的程式，再度的自由发行，而不会与原先的撰写者冲突；
  • 回馈：你应该将你修改过的程式码回馈于社群！

但请特别留意，你所修改的任何一个自由软体都不应该也不能这样：

  • 修改授权：你不能将一个GPL授权的自由软体，在你修改后而将他取消GPL授权～
  • 单纯贩卖：你不能单纯的贩卖自由软体。

也就是说，既然GPL是站在互助互利的角度上去开发的，你自然不应该将大家的成果占为己有， 对吧！因此你当然不可以将一个GPL软体的授权取消，即使你已经对该软体进行大幅度的修改！ 那么自由软体也不能贩卖吗？当然不是！还记得上一个小节里面， 我们提到史托曼藉由贩卖Emacs取得一些经费，让自己生活不至于匮乏吧？是的！ 自由软体是可以贩售的，不过，不可仅贩售该软体，应同时搭配售后服务与相关手册～ 这些可就需要工本费了呢！

  • 自由软体与商业行为：

很多人还是有疑问，目前不是有很多Linux开发商吗？为何他们可以贩售Linux这个GPL授权的软体？ 原因很简单，因为他们大多都是贩售‘售后服务！’所以，他们所使用的自由软体， 都可以在他们的网站上面下载！(当然，每个厂商他们自己开发的工具软体就不是GPL的授权软体了！) 但是，你可以购买他们的Linux光碟，如果你购买了光碟，他们会提供相关的手册说明文件， 同时也会提供你数年不等的谘询、售后服务、软体升级与其他协力工作等等的附加价值！

所以说，目前自由软体工作者，他们所赖以维生的，几乎都是在‘服务’这个领域呢！ 毕竟自由软体并不是每个人都会撰写，有人有需要你的自由软体时，他就会请求你的协助， 此时，你就可以透过服务来收费了！这样来说， 自由软体确实还是具有商业空间的喔！

Tips:
很多人对于GPL授权一直很疑惑，对于GPL的商业行为更是无法接受！ 关于这一点，鸟哥在这里还是要再次的申明，GPL是可以从事商业行为的！ 而很多的作者也是藉由这些商业行为来得以取得生活所需，更进一步去发展更优秀的自由软体！ 千万不要听到‘商业’就排斥！这对于发展优良软体的朋友来说，是不礼貌的！ 		鸟哥的图示

上面提到的大多是与使用者有关的项目，那么 GPL 对于自由软体的作者有何优点呢？大致的优点有这些：

  • 软体安全性较佳；
  • 软体执行效能较佳；
  • 软体除错时间较短；
  • 贡献的原始码远永都存在。

这是因为既然是Open Source的自由软体，那么你的程式码将会有很多人帮你查阅， 如此一来，程式的漏洞与程式的优化将会进展的很快！所以，在安全性与效能上面， 自由软体一点都不输给商业软体喔！此外，因为GPL授权当中，修改者并不能修改授权， 因此，你如果曾经贡献过程式码，嘿嘿！你将名留青史呢！不错吧！ ^_^

对于程式开发者来说，GPL实在是一个非常好的授权，因为大家可以互相学习对方的程式撰写技巧， 而且自己写的程式也有人可以帮忙除错。那你会问啊，对于我们这些广大的终端用户，GPL有没有什么好处啊？有啊！当然有！ 虽然终端用户或许不会自己编译程式码或者是帮人家除错，但是终端用户使用的软体绝大部分就是GPL的软体， 全世界有一大票的工程师在帮你维护你的系统，这难道不是一件非常棒的事吗？ ^_^

大标题的图示 Torvalds的Linux发展

我们前面一节当中，提到了Unix的历史，也提到了Linux是由Torvalds这个芬兰人所发明的。那么为何托瓦兹可以发明Linux呢？ 凭空想像而来的？还是有什么渊源？这里我们就来谈一谈啰！

小标题的图示 与Minix之间

Linus Torvalds(托瓦兹, 1969年出生)的外祖父是赫尔辛基大学的统计学家， 他的外祖父为了让自己的小孙子能够学点东西，所以从小就将托瓦兹带到身边来管理一些微电脑。 在这个时期，托瓦兹接触了组合语言(Assembly Language)，那是一种直接与晶片对谈的程式语言，也就是所谓的低阶语言。 必须要很了解硬体的架构，否则很难以组合语言撰写程式的。

在1988年间，托瓦兹顺利的进入了赫尔辛基大学，并选读了电脑科学系。在就学期间，因为学业的需要与自己的兴趣， 托瓦兹接触到了Unix这个作业系统。当时整个赫尔辛基只有一部最新的Unix系统，同时仅提供16个终端机(terminal)。 还记得我们上一节刚刚提过的，早期的电脑仅有主机具有运算功能，terminal仅负责提供Input/Output而已。在这种情况下， 实在很难满足托瓦兹的需求，因为.....光是等待使用Unix的时间，就很耗时～为此，他不禁想到： ‘我何不自己搞一部Unix来玩？’不过，就如同Stallman当初的GNU计划一样，要写核心程式，谈何容易～

不过，幸运之神并未背离托瓦兹，因为不久之后，他就知道有一个类似Unix的系统， 并且与Unix完全相容，还可以在Intel 386机器上面跑的作业系统， 那就是我们上一节提过的，谭宁邦教授为了教育需要而撰写的Minix系统！ 他在购买了最新的Intel 386的个人电脑后，就立即安装了Minix这个作业系统。 另外，上个小节当中也谈到，Minix这个作业系统是有附上原始码的， 所以托瓦兹也经由这个原始码学习到了很多的核心程式设计的设计概念喔！

小标题的图示 对386硬体的多工测试

事实上，托瓦兹对于个人电脑的CPU其实并不满意，因为他之前碰的电脑都是工作站型的电脑， 这类电脑的CPU特色就是可以进行‘多工处理’的能力。什么是多工呢？理论上， 一个CPU在一个时间内仅能进行一个程式， 那如果有两个以上的程式同时出现到系统中呢？举例来说， 你可以在现今的电脑中同时开启两个以上的办公软体，例如电子试算表与文书处理软体。 这个同时开启的动作代表着这两个程式同时要交给CPU来处理～

啊！CPU一个时间点内仅能处理一个程式，那怎么办？没关系，这个时候如果具有多工能力的CPU就会在不同的程式间切换～ 还记得前一章谈到的CPU时脉吧？假设CPU时脉为1GHz的话，那表示CPU一秒钟可以进行109次工作。 假设CPU对每个程式都只进行1000次运作周期，然后就得要切换到下个程式的话，那么CPU一秒钟就能够切换106次呢！ (当然啦，切换工作这件事情也会花去一些CPU时间，不过这里暂不讨论)。这么快的处理速度下，你会发现， 两个程式感觉上几乎是同步在进行啦！

Tips:
为什么有的时候我同时开两个档案(假设为A, B档案)所花的时间， 要比开完A再去开B档案的时间还要多？现在是否稍微可以理解？ 因为如果同时开启的话，CPU就必须要在两个工作之间不停的切换～ 而切换的动作还是会耗去一些CPU时间的！所以啰，同时启用两个以上的工作在一个CPU上， 要比一个一个的执行还要耗时一点。这也是为何现在CPU开发商要整合两个CPU于一个晶片中！ 也是为何在运作情况比较复杂的伺服器上，需要比较多的CPU负责的原因！ 		鸟哥的图示

早期Intel x86架构电脑不是很受重视的原因，就是因为x86的晶片对于多工的处理不佳， CPU在不同的工作之间切换不是很顺畅。但是这个情况在386电脑推出后，有很大的改善。 托瓦兹在得知新的386晶片的相关资讯后，他认为，以性能价格比的观点来看， Intel的386相当的便宜，所以在性能上也就稍微可以将就将就 ^_^。最终他就贷款去买了一部Intel的386来玩。

早期的电脑效能没有现在这么好，所以压榨电脑效能就成了工程师的一项癖好！ 托瓦兹本人早期是玩组合语言的，组合语言对于硬体有很密切的关系，托瓦兹自己也说：‘我始终是个性能癖’^_^。 为了彻底发挥386的效能，于是托瓦兹花了不少时间在测试386机器上！ 他的重要测试就是在测试386的多功效能。首先，他写了三个小程式，一个程式会持续输出A、一个会持续输出B， 最后一个会将两个程式进行切换。他将三个程式同时执行，结果，他看到荧幕上很顺利的一直出现ABABAB...... 他知道，他成功了！ ^_^

386电脑的多工测试
图2.2.1、386电脑的多工测试
Tips:
要达到多工(multitasking)的环境，除了硬体(主要是CPU)需要能够具有多工的特性外，作业系统也需要支援这个功能喔！ 一些不具有多工特性的作业系统，想要同时执行两个程式是不可能的。除非先被执行的程式执行完毕，否则， 后面的程式不可能被主动执行。

至于多工的作业系统中，每个程式被执行时，都会有一个最大CPU使用时间，若该工作运作的时间超过这个CPU使用时间时， 该工作就会先被丢出CPU的运作中，而再度的进入核心工作排程中等待下一次被CPU取用来运作。

这有点像在开记者会啦，主持人(CPU)会问‘谁要发问’？一群记者(工作程式) 就会举手(看谁的工作重要！)，先举手的自然就被允许发问，问完之后， 主持人又会问一次谁要发问，当然，所有人(包括刚刚那个记者)都可以举手！ 如此一次一次的将工作给他完成啊！ ^_^ 多工的环境对于复杂的工作情况，帮助很大喔！ 		鸟哥的图示
小标题的图示 初次释出Linux 0.02

探索完了386的硬体之后，终于拿到Minix并且安装在托瓦兹的386电脑上之后，托瓦兹跟BBS上面一堆工程师一样， 他发现Minix虽然真的很棒，但是谭宁邦教授就是不愿意进行功能的加强，导致一堆工程师在作业系统功能上面的欲求不满！ 这个时候年轻的托瓦兹就想：‘既然如此，那我何不自己来改写一个我想要的作业系统？’ 于是他就开始了核心程式的撰写了。

撰写程式需要什么呢？首先需要的是能够进行工作的环境，再来则是可以将原始码编译成为可执行档的编译器。 好在有GNU计划提供的bash工作环境软体以及gcc编译器等自由软体， 让托瓦兹得以顺利的撰写核心程式。他参考Minix的设计理念与书上的程式码，然后仔细研究出386个人电脑的效能最佳化， 然后使用GNU的自由软体将核心程式码与386紧紧的结合在一起，最终写出他所需要的核心程式。 而这个小玩意竟然真的可以在386上面顺利的跑起来～还可以读取Minix的档案系统。 真是太好了！不过还不够，他希望这个程式可以获得大家的一些修改建议， 于是他便将这个核心放置在网路上提供大家下载，同时在BBS上面贴了一则消息：

Hello everybody out there using minix-
I'm doing a (free) operation system (just a hobby,
won't be big and professional like gnu) for 386(486) AT clones.

I've currently ported bash (1.08) and gcc (1.40),
and things seem to work. This implies that i'll get
something practical within a few months, and I'd like to know
what features most people want. Any suggestions are welcome,
but I won't promise I'll implement them :-)

他说，他完成了一个小小的作业系统，这个核心是用在386机器上的， 同时，他真的仅是好玩，并不是想要做一个跟GNU一样大的计划！ 另外，他希望能够得到更多人的建议与回馈来发展这个作业系统！这个概念跟Minix刚好背道而驰呢！ 这则新闻引起很多人的注意，他们也去托瓦兹提供的网站上下载了这个核心来安装。 有趣的是，因为托瓦兹放置核心的那个FTP网站的目录为：Linux， 从此，大家便称这个核心为Linux了。(请注意，此时的Linux就是那个kernel喔！ 另外，托瓦兹所丢到该目录下的第一个核心版本为0.02呢！)

同时，为了让自己的Linux能够相容于Unix系统，于是托瓦兹开始将一些能够在Unix上面运作的软体拿来在Linux上面跑。 不过，他发现到有很多的软体无法在Linux这个核心上运作。这个时候他有两种作法， 一种是修改软体，让该软体可以在Linux上跑， 另一种则是修改Linux，让Linux符合软体能够运作的规范！ 由于Linux希望能够相容于Unix，于是托瓦兹选择了第二个作法‘修改Linux’！ 为了让所有的软体都可以在Linux上执行，于是托瓦兹开始参考标准的POSIX规范。

Tips:
POSIX是可携式作业系统介面(Portable Operating System Interface)的缩写，重点在规范核心与应用程式之间的介面， 这是由美国电器与电子工程师学会(IEEE)所发布的一项标准喔！ 		鸟哥的图示

这个正确的决定让Linux在起步的时候体质就比别人优良～因为POSIX标准主要是针对Unix与一些软体运行时候的标准规范， 只要依据这些标准规范来设计的核心与软体，理论上，就可以搭配在一起执行了。 而Linux的发展就是依据这个POSIX的标准规范，Unix上面的软体也是遵循这个规范来设计的， 如此一来，让Linux很容易就与Unix相容共享互有的软体了！同时，因为Linux直接放置在网路下，提供大家下载， 所以在流通的速度上相当的快！导致Linux的使用率大增！这些都是造成Linux大受欢迎的几个重要因素呢！

小标题的图示 Linux 的发展：虚拟团队的产生

Linux能够成功除了托瓦兹个人的理念与力量之外，其实还有个最重要的团队！

  • 单一个人维护阶段

Linux虽然是托瓦兹发明的，而且内容还绝不会涉及专利软体的版权问题。 不过，如果单靠托瓦兹自己一个人的话，那么Linux要茁壮实在很困难～ 因为一个人的力量是很有限的。好在托瓦兹选择Linux的开发方式相当的务实！ 首先，他将释出的Linux核心放置在FTP上面，并请告知大家新的版本资讯， 等到使用者下载了这个核心并且安装之后，如果发生问题， 或者是由于特殊需求亟需某些硬体的驱动程式，那么这些使用者就会主动回报给托瓦兹。 在托瓦兹能够解决的问题范围内，他都能很快速的进行Linux核心的更新与除错。

  • 广大骇客志工加入阶段

不过，托瓦兹总是有些硬体无法取得的啊，那么他当然无法帮助进行驱动程式的撰写与相关软体的改良。 这个时候，就会有些志工跳出来说：‘这个硬体我有，我来帮忙写相关的驱动程式。’ 因为Linux的核心是Open Source的，骇客志工们很容易就能够跟随Linux的原本设计架构， 并且写出相容的驱动程式或者软体。志工们写完的驱动程式与软体托瓦兹是如何看待的呢？ 首先，他将该驱动程式/软体带入核心中，并且加以测试。 只要测试可以运行，并且没有什么主要的大问题，那么他就会很乐意的将志工们写的程式码加入核心中！

总之，托瓦兹是个很务实的人，对于Linux核心所欠缺的项目，他总是‘先求有且能跑， 再求进一步改良’的心态！这让Linux使用者与志工得到相当大的鼓励！ 因为Linux的进步太快了！使用者要求虚拟记忆体，结果不到一个星期推出的新版Linux就有了！ 这不得不让人佩服啊！

另外，为因应这种随时都有程式码加入的状况，于是Linux便逐渐发展成具有模组的功能！ 亦即是将某些功能独立出于核心外，在需要的时候才载入到核心中。如此一来， 如果有新的硬体驱动程式或者其他协定的程式码进来时，就可以模组化， 大大的增加了Linux核心的可维护能力！

Tips:
核心是一组程式，如果这组程式每次加入新的功能都得要重新编译与改版的话会变成如何？ 想像一下，如果你只是换了显示卡就得要重新安装新的Windows作业系统，会不会傻眼？ 模组化之后，原本的核心程式不需要更动，你可以直接将他想成是‘驱动程式’即可！ ^_^ 		鸟哥的图示
  • 核心功能细部分工发展阶段

后来，因为Linux核心加入了太多的功能，光靠托瓦兹一个人进行核心的实际测试并加入核心原始程式实在太费力～ 结果，就有很多的朋友跳出来帮忙这个前置作业！例如考克斯(Alan Cox)、与崔迪(Stephen Tweedie)等等， 这些重要的副手会先将来自志工们的修补程式或者新功能的程式码进行测试， 并且结果上传给托瓦兹看，让托瓦兹作最后核心加入的原始码的选择与整并！ 这个分层负责的结果，让Linux的发展更加的容易！

特别值得注意的是，这些托瓦兹的Linux发展副手，以及自愿传送修补程式的骇客志工， 其实都没有见过面，而且彼此在地球的各个角落，大家群策群力的共同发展出现今的Linux， 我们称这群人为虚拟团队！而为了虚拟团队资料的传输，于是Linux便成立的核心网站： http://www.kernel.org！

而这群素未谋面的虚拟团队们，在1994年终于完成的Linux的核心正式版！version 1.0。 这一版同时还加入了X Window System的支援呢！更于1996年完成了2.0版。此外，托瓦兹指明了企鹅为Linux的吉祥物。

Tips:
奇怪的是，托瓦兹是因为小时候去动物园被企鹅咬了一口念念不忘， 而正式的2.0推出时，大家要他想一个吉祥物。他在想也想不到什么动物的情况下， 就将这个念念不忘的企鹅当成了Linux的吉祥物了...... 		鸟哥的图示

Linux由于托瓦兹是针对386写的，跟386硬体的相关性很强，所以， 早期的Linux确实是不具有移植性的。不过，大家知道Open source的好处就是， 可以修改程式码去适合作业的环境。因此，在1994年以后，Linux便被开发到很多的硬体上面去了！ 目前除了x86之外，IBM、HP、Sun等等公司出的硬体也都有被Linux所支援呢！

小标题的图示 Linux的核心版本

Linux的核心版本编号有点类似如下的样子：

2.6.18-92.el5
主版本.次版本.释出版本-修改版本

如前所述，因为对于Linux核心的开发者太多了，以致于造成Linux核心经常性的变动。 但对于一般家用电脑或企业关键应用的话，常变动的核心并不适合的。因此托瓦兹便将核心的发展趋势分为两股， 并根据这两股核心的发展分别给予不同的核心编号，那就是：

  • 主、次版本为奇数：发展中版本(development)
    如2.5.xx，这种核心版本主要用在测试与发展新功能，所以通常这种版本仅有核心开发工程师会使用。 如果有新增的核心程式码，会加到这种版本当中，等到众多工程师测试没问题后，才加入下一版的稳定核心中；

  • 主、次版本为偶数：稳定版本(stable)
    如2.6.xx，等到核心功能发展成熟后会加到这类的版本中，主要用在一般家用电脑以及企业版本中。 重点在于提供使用者一个相对稳定的Linux作业环境平台。

至于释出版本则是在主、次版本架构不变的情况下，新增的功能累积到一定的程度后所新释出的核心版本。 而由于Linux核心是使用GPL的授权，因此大家都能够进行核心程式码的修改。因此，如果你有针对某个版本的核心修改过部分的程式码， 那么那个被修改过的新的核心版本就可以加上所谓的修改版本了。

Linux核心版本与distribution (下个小节会谈到) 的版本并不相同，很多朋友常常上网问到：‘我的Linux是9.x版，请问....’之类的留言， 这是不对的提问方式，因为所谓的Linux版本指的应该是核心版本， 而目前最新的核心版本应该是2.6.30(2009/08) 才对，并不会有9.x的版本出现的。

你常用的Linux系统则应该说明为distribution才对！因此，如果以CentOS这个distribution来说， 你应该说：‘我用的Linux是CentOS这个 distribution，版本为5.x 版，请问....’才对喔！

Tips:
当你有任何问题想要在Linux论坛发言时，请务必仔细的说明你的distribution版本， 因为虽然各家distributions使用的都是Linux核心，不过每家distributions所选用的软体以及他们自己发展的工具并不相同， 多少还是有点差异，所以留言时得要先声明distribution的版本才行喔！ ^_^ 		鸟哥的图示
小标题的图示 Linux distributions

好了，经过上面的说明，我们知道了Linux其实就是一个作业系统最底层的核心及其提供的核心工具。 他是GNU GPL授权模式，所以，任何人均可取得原始码与可执行这个核心程式，并且可以修改。 此外，因为Linux参考POSIX设计规范，于是相容于Unix作业系统，故亦可称之为Unix Like的一种。

Tips:
鸟哥曾在上课的时候问过同学：‘什么是Unix Like啊’？可爱的同学们回答的答案是：‘就是很喜欢(like)Unix啦！’ 囧rz...那个like是‘很像’啦！所以Unix like是‘很像Unix的作业系统’哩！ 		鸟哥的图示
  • 可完整安装的Linux发布套件

Linux的出现让GNU计划放下了心里的一块大石头，因为GNU一直以来就是缺乏了核心程式， 导致他们的GNU自由软体只能在其他的Unix上面跑。既然目前有Linux出现了，且 Linux也用了很多的GNU相关软体，所以Stallman认为Linux的全名应该称之为GNU/Linux呢！ 不管怎么说，Linux实在很不错，让GNU软体大多以Linux为主要作业系统来进行开发， 此外，很多其他的自由软体团队，例如sendmail, wu-ftp, apache等等也都有以Linux 为开发测试平台的计划出现！如此一来，Linux除了主要的核心程式外，可以在Linux 上面运行的软体也越来越多，如果有心，就能够将一个完整的Linux作业系统搞定了！

虽然由Torvalds负责开发的Linux仅具有Kernel与Kernel提供的工具， 不过，如上所述，很多的软体已经可以在Linux上面运作了，因此， ‘Linux + 各种软体’就可以完成一个相当完整的作业系统了。 不过，要完成这样的作业系统......还真难～ 因为Linux早期都是由骇客工程师所开发维护的，他们并没有考虑到一般使用者的能力......

为了让使用者能够接触到Linux，于是很多的商业公司或非营利团体， 就将Linux Kernel(含tools)与可运行的软体整合起来，加上自己具有创意的工具程式， 这个工具程式可以让使用者以光碟/DVD或者透过网路直接安装/管理Linux系统。 这个‘Kernel + Softwares + Tools的可完整安装’的咚咚，我们称之为Linux distribution， 一般中文翻译成可完整安装套件，或者Linux发布商套件等。

Linux可完整安装发布套件
图2.5.1、Linux可完整安装发布套件
Tips:
由于Linux核心是由骇客工程师写的，要由原始码安装到x86电脑上面成为可以执行的binary档案， 这个过程可不是人人都会的～所以早期确实只有工程师对Linux有兴趣。 一直到一些社群与商业公司将Linux核心配合自由软体，并提供完整的安装程序， 且制成光碟/DVD后，对于一般使用者来说，Linux才越来越具有吸引力！ 因为只要一直‘下一步’就可以将Linux安装完成啊！ ^_^ 		鸟哥的图示

由于GNU的GPL授权并非不能从事商业行为，于是很多商业公司便成立来贩售Linux distribution。 而由于Linux的GPL版权宣告，因此，商业公司所贩售的Linux distributions通常也都可以从Internet上面来下载的！ 此外，如果你想要其他商业公司的服务，那么直接向该公司购买光碟来安装，也是一个很不错的方式的！

  • 各大Linux Distributions的主要异同：支援标准！

不过，由于发展Linux distributions的社群与公司实在太多了，例如在台湾有名的Red Hat, SuSE, Ubuntu, Fedora, Debian等等，所以很多人都很担心，如此一来每个distribution是否都不相同呢？ 这就不需要担心了，因为每个Linux distributions使用的kernel都是http://www.kernel.org所释出的，而他们所选择的软体，几乎都是目前很知名的软体，重复性相当的高， 例如网页伺服器的Apache，电子邮件伺服器的Postfix/sendmail，档案伺服器的Samba等等。

此外，为了让所有的Linux distributions开发不致于差异太大，且让这些开发商在开发的时候有所依据，还有Linux Standard Base (LSB)等标准来规范开发者，以及目录架构的File system Hierarchy Standard (FHS)标准规范！ 唯一差别的，可能就是该开发者自家所开发出来的管理工具，以及套件管理的模式吧！ 所以说，基本上，每个Linux distributions除了架构的严谨度与选择的套件内容外， 其实差异并不太大啦！ ^_^ 。大家可以选择自己喜好的distribution来安装即可！

  • FHS: http://www.pathname.com/fhs/
  • LSB: http://www.linuxbase.org/
Tips:
事实上鸟哥认为distributions主要分为两大系统，一种是使用RPM方式安装软体的系统，包括Red Hat, Fedora, SuSE等都是这类； 一种则是使用Debian的dpkg方式安装软体的系统，包括Debian, Ubuntu, B2D等等。 		鸟哥的图示

底下列出几个主要的Linux distributions发行者网址：

  • Red Hat: http://www.redhat.com
  • Fedora: http://fedoraproject.org/
  • Mandriva: http://www.mandriva.com
  • Novell SuSE: http://www.novell.com/linux/
  • Debian: http://www.debian.org/
  • Slackware: http://www.slackware.com/
  • Gentoo: http://www.gentoo.org/
  • Ubuntu: http://www.ubuntu.com/
  • CentOS: http://www.centos.org/
Tips:
到底是要买商业版还是社群版的Linux distribution呢？如果是要装在个人电脑上面做为桌上型电脑用的，建议使用社群版， 包括Fedora, Ubuntu, OpenSuSE等等。如果是用在伺服器上面的，建议使用商业版本，包括Red Hat, SuSE等。 这是因为社群版通常开发者会加入最新的软体，这些软体可能会有一些bug存在。至于商业版则是经过一段时间的磨合后， 才将稳定的软体放进去。

举例来说，Fedora兜出来的软体套件经过一段时间的维护后，等到该软体稳定到不容易发生错误后， Red Hat才将该软体放到他们最新的释出版本中。所以，Fedora的软体比较经常改版，Red Hat的软体就较少更版。 		鸟哥的图示
  • Linux在台湾

当然发行套件者不仅于此。但是值得大书特书的，是中文Linux的延伸计划：CLE这个套件！ 早期的Linux因为是工程师发展的，而这些工程师大多以英文语系的国家为主， 所以Linux对于国人的学习是比较困扰一点。后来由国人发起的CLE计划： http://cle.linux.org.tw/ 开发很多的中文套件及翻译了很多的英文文件，使得我们目前得以使用中文的Linux呢！ 另外，目前正在开发中的还有台南县卧龙小三等老师们发起的众多自由软体计划， 真是造福很多的朋友啊！

  • 自由软体技术交流网： http://freesf.tnc.edu.tw/index.php
  • B2D: http://b2d.tnc.edu.tw/
此外，如果只想看看Linux的话，还可以选择所谓的可光碟开机进入Linux的Live CD版本， 亦即是KNOPPIX这个Linux distributions呢！台湾也有阿里巴巴兄维护的中文Live CD喔！
  • http://www.knoppix.net/
  • 中文 KNOPPIX: http://knoppix.tnc.edu.tw/
Tips:
对于没有额外的硬碟或者是没有额外的主机的朋友来说，KNOPPIX这个可以利用光碟开机而进入Linux作业系统的Live CD 真的是一个不错的选择！你只要下载了KNOPPIX的映象档，然后将他烧录成为CD， 放入你主机的光碟机，并在BIOS内设定光碟为第一个开机选项，就可以使用Linux系统了呢！ 		鸟哥的图示
如果你还想要知道更多的Linux distributions的下载与使用资讯，可以参考：
  • http://distrowatch.com/

  • 选择适合你的Linux distribution

那我到底应该要选择哪一个distributions？就如同我们上面提到的，其实每个distributions差异性并不大！ 不过，由于套件管理的方式主要分为Debian的dpkg及Red Hat系统的RPM方式， 目前鸟哥的建议是，先学习以RPM套件管理为主的RHEL/Fedora/SuSE/CentOS等台湾使用者较多的版本， 这样一来，发生问题时，可以提供解决的管道比较多。如果你已经接触过Linux了， 还想要探讨更严谨的Linux版本，那可以考虑使用Debian，如果你是以效能至上来考量， 那么或许Gentoo是不错的建议！

总之，版本很多，但是各版本差异其实不大，建议你一定要先选定一个版本后， 先彻头彻尾的了解他，那再继续玩其他的版本时，就可以很快的进入状况。 鸟哥的网站仅提供一个版本，不过是以比较基础的方式来介绍的， 因此，如果能够熟练俺这个网站的话，呵呵！哪一个distributions对你来说，都不成问题啦！

不过，如果依据电脑主机的用途来分的话，在台湾鸟哥会这样建议：

  • 用于企业环境：建议使用商业版本，例如Red Hat的RHEL或者是Novell的SuSE都是很不错的选择！ 毕竟企业的环境强调的是永续的经营，你可不希望网管人员走了之后整个机房的主机都没有人管理吧！ 由于商业版本都会提供客户服务，所以可以降低企业的风险喔！

  • 用于个人或教学的伺服器环境：要是你的伺服器所在环境如果当机还不会造成太大的问题的话， 加上你的环境是在教学的场合当中时(就是说，唔！经费不足的环境啦！)那么可以使用‘号称’完全相容商业版RHEL的CentOS。 因为CentOS是抓RHEL的原始码来重新兜起来的一个Linux distribution，所以号称相容于RHEL。 这一版的软体完全与RHEL相同，在改版的幅度较小，适合于伺服器系统的环境；

  • 用于个人的桌上型电脑：想要尝鲜吗？建议使用很炫的Fedora/Ubuntu等Desktop(桌面环境)使用的版本！ 如果不想要安装Linux的话，那么Fedora或CentOS也有推出Live CD了！也很容易学习喔！
大标题的图示 Linux的特色

Linux是Torvalds先生所开发出来的，基于GPL的版权宣告之下，可以在x86的架构下运作，也可以被移植到其他的大型主机上面。 由于开发的相关理念与相容的问题，因此，我们也可以称Linux为Unix Like作业系统的一种。

Tips:
其实Unix-Like可以说是目前伺服器类型的作业系统的统称啦！ 因为，不论是FreeBSD, BSD, Sun Unix, HP Unix, Red Hat Linux, Mandrake Linux等等，都是由同一个祖先Thompson所写的‘Unix’来的， 因此，这些咚咚都被统称为Unix-Like的作业系统啰！ 		鸟哥的图示
小标题的图示 Linux的特色

那么这个系统有什么特异功能呢？简单的说：

  • 自由与开放的使用与学习环境：

    由于Linux是基于GPL的授权之下，因此他是自由软体， 也就是任何人都可以自由的使用或者是修改其中的原始码的意思！ 这种开放性架构对科学界来说是相当重要的！ 因为很多的工程师由于特殊的需求，常常需要修改系统的原始码， 使该系统可以符合自己的需求！而这个开放性的架构将可以满足各不同需求的工程师！ 因此当然就有可能越来越流行啰！以鸟哥来说，目前环境工程界的空气品质模式最新版 Models-3/CMAQ 就是以Linux为基准平台设计的呢！

  • 配备需求低廉：

    Linux可以支援个人电脑的x86架构，系统资源不必像早先的Unix系统那般，仅适合于单一公司所出产的设备！ 单就这一点来看，就可以造成很大的流行啰！不过，如果你想要在Linux下执行X Window系统， 那么硬体的等级就不能太低了！

  • 核心功能强大而稳定：

    而且由于Linux功能并不会输给一些大型的Unix工作站，因此，近年来越来越多的公司或者是团体、 个人投入这一个作业系统的开发与整合工作！例如IBM与升阳公司都有推出x86的Linux伺服器呢！

  • 独立作业：

    另外，由于很多的软体套件逐渐被这套作业系统拿来使用，而很多套件软体也都在 Linux这个作业系统上面进行发展与测试，因此，Linux近来已经可以独力完成几乎所有的工作站或伺服器的服务了，例如 Web, Mail, Proxy, FTP.....。

目前Linux已经是相当成熟的一套作业系统啰！而且不耗资源又可以自由取得！呵呵， 可以说造成微软相当大的压力呀！此外，由于他的系统硬体要求很低， 加上目前很多的人由于‘Intel 的阴谋’而造成手边有相当多的淘汰掉的硬体配备， Linux在这些被淘汰的硬体中就可以执行的相当的顺畅与稳定！因此也造成相当多朋友的关注啰！

Tips:
呵呵！开玩笑的，因为Tom的硬体评论 (http://www.big5.tomshardware.com/) 网站常常这样取笑Intel的说！呵！很好笑！ 		鸟哥的图示

这也是造成Linux成为最近几年来最受瞩目的作业系统之一，如前所述， 他会受到瞩目的原因主要是因为他是‘free’的，就是可以自由取得的作业系统啦！ 然后他是开放性的系统，也就是你可以随时的取得程式的原始码，这对于程式开发工程师是很重要的！ 而且，虽然他是Free的自由软体，不过功能却很强大！另外， Linux对于硬体的需求是很低的，这一点更造成它流行的主因，因为硬体的汰换率太快了， 所以很多人手边都有一些很少在用的零件，这些零件组一组就可以用来跑Linux了， 反正做一个工作站又不用使用到荧幕(只要主机就可以啰)，因此Linux就越来越流行啰！

Tips:
也就是因为Linux具有 1.硬体需求低、 2.架构开放、 3.系统稳定性及保密性功能够强、 4.完全免费，所以造成一些所谓‘反微软联盟’的程式设计高手不断的开发新软体！以与Microsoft进行抗衡！ 		鸟哥的图示
小标题的图示 Linux的优缺点

那干嘛要使用Linux做为我们的主机系统呢？这是因为Linux有底下这些优点：

  • 稳定的系统：
    Linux本来就是基于Unix概念而发展出来的作业系统，因此，Linux具有与Unix系统相似的的程式介面跟操作方式， 当然也继承了Unix稳定并且有效率的特点。常听到安装Linux的主机连续运做一年以上而不曾当机、 不必关机是稀松平常的事；

  • 免费或少许费用：
    由于Linux是基于GPL授权下的产物，因此任何人皆可以自由取得Linux， 至于一些‘安装套件’的发行者， 他们发行的安装光碟也仅需要些许费用即可获得！不同于Unix需要负担庞大的版权费用，当然也不同于微软需要一而再、 再而三的更新你的系统，并且缴纳大量费用啰！

  • 安全性、漏洞的快速修补：
    如果你常玩网路的话，那么你最常听到的应该是‘没有绝对安全的主机’！ 没错！不过Linux由于支援者日众，有相当多的热心团体、个人参与其中的开发， 因此可以随时获得最新的安全资讯，并给予随时的更新，亦即是具有相对的较安全！

  • 多工、多使用者：
    与Windows系统不同的，Linux主机上可以同时允许多人上线来工作， 并且资源的分配较为公平，比起Windows的单人多工系统要稳定的多啰！ 这个多人多工可是Unix-Like上面相当好的一个功能，怎么说呢？你可以在一部 Linux主机上面规划出不同等级的使用者，而且每个使用者登入系统时的工作环境都可以不相同， 此外，还可以允许不同的使用者在同一个时间登入主机，以同时使用主机的资源。

  • 使用者与群组的规划：
    在Linux的机器中，档案的属性可以分为‘可读、可写、可执行’ 等参数来定义一个档案的适用性，此外，这些属性还可以分为三个种类， 分别是‘档案拥有者、档案所属群组、其他非拥有者与群组者’。 这对于专案计划或者其他计划开发者具有相当良好的系统保密性。

  • 相对比较不耗资源的系统：
    Linux只要一部P-III以上等级的电脑就可以安装并且使用愉快啰！还不需要到P-4或AMD K8 等级的电脑呢！不过，如果你要架设的是属于大型的主机（服务上百人以上的主机系统）， 那么就需要比较好一点的机器了。不过，目前市面上任何一款个人电脑均可以达到这一个要求啰！

  • 适合需要小核心程式的嵌入式系统：
    由于Linux只要几百K不到的程式码就可以完整的驱动整个电脑硬体并成为一个完整的作业系统， 因此相当适合于目前家电或者是小电子用品的作业系统呢！那就是当红炸子鸡‘嵌入式’系统啦！ Linux真的是很适合例如手机、数位相机、PDA、家电用品等等的微电脑作业系统呢！ ^_^

  • 整合度佳且多样的图形使用者介面(GUI)：
    自从1994年Linux 1.0后就加入的X Window系统，在众多骇客的努力之下终于与Linux有高度整合， 且主要的绘图卡公司(Intel, NVidia, ATI等)都有针对Linux推出最新的驱动程式， 因此Linux的GUI已经有长足的进步了！另外，Linux环境下的图形介面不只有一种呢！ 包括大家耳熟能详的KDE(http://www.kde.org/)以及GNOME(http://www.gnome.org)都是很常见的！

反正Linux好处说不完啦！不过虽然Linux具有这样多的好处，但是他先天上有一个足以致命的地方， 使他的普及率受到很大的限制，就是Linux需要使用‘指令列’的终端机模式进行系统的管理！ 虽然近年来有很多的图形介面开发使用在Linux上面，但毕竟要熟悉Linux还是以指令列来使用是比较好的， 因此要接受Linux的玩家必须比较要能熟悉对电脑下指令的行为，而不是用滑鼠点一点icon就行了！ Linux 还可以改进的地方：

  • 没有特定的支援厂商：
    因为在Linux上面的所有套件几乎都是自由软体，而每个自由软体的开发者可能并不是公司团体， 而是非营利性质的团体。如此一来，在你Linux主机上面的软体若发生问题，该如何是好？ 好在由于目前Linux商业界的整合还不错，目前在台湾比较具名的Red Hat与SuSE 均有设立了服务点。你可以经由这个服务点来直接向他们购买/谘询相关的软硬体问题呢！ 不过，如果你并非选择有专门商业公司的Linux distributions时？怎么办？ 没有专人到府服务呢～这点倒是还不需要太担心， 因为拜网路风行之赐，你要问的问题几乎在网路上都可以找到答案喔！看你有没有用心去找就是了！

  • 游戏的支援度不足：
    在现代这个时候，敢说你们家的桌上型电脑里面完全没有游戏的小朋友应该不多了！ 游戏软体也是个应用程式，所以它与作业系统的关系就相当密切了。 可惜的是目前很多游戏开发商并没有在Linux平台上面开发大型游戏，这间接导致Linux无法进入一般家庭说。

  • 专业软体的支援度不足：
    这是鸟哥到学校教书后才发现的一件事，目前很多专业绘图软体公司所推出的专业软体并不支援Linux作业系统， 这让同学很难在不同的平台上面操作相同的软体！唉！很伤脑筋～

  • 教育训练作的还不够好：
    如果能够在国小就教导小朋友使用自由软体，那么长大自然就会使用自由软体了！ 在台湾目前政策方面还是相当的摇摆不定，希望未来能够给自由软体一些机会。

老实说，这些缺点绝大部分都不是Linux本身的问题，倒是一些政策面与商业方面的考量，才是最大的困扰。 不过，Linux与其他的作业系统一样，就是一个工具而已！希望大家能够在快乐中学习到Linux的精髓啦！^_^

小标题的图示 关于授权

现在市面上有好多的软体，有的是自由软体，有的是专利软体。有的专利软体免费，有的自由软体要钱～ 啊！好烦啊！怎么分辨这些东西？其实，鸟哥并不是律师，对于法律也不十分懂，不过， 还是有几个授权模式可以来谈一谈～

  • Open Source (开放源码)

软体以Open Source的方式释出时，表示除了可执行的软体本身外，一定伴随着原始码的释出喔！通常Open Source的软体有几个好处：

  1. 程式设计师通常会等到程式成熟之后才会释出(免得被笑, ^_^)，所以通常程式在雏形的时候，就已经具有相当的优良体质；

  2. Open Source的精神，相信当程式原设计人将程式原始码释出之后，其他的程式设计师接受这份原始码之后， 由于需要将程式改成自己所需的样式，所以会经由本身的所学来加以改良，并从中加以改良与除虫， 所以程式的debug功能会比传统的close source来的快！

  3. 由于程式是伴随原始码的，因此，系统将会不易存在鲜为人知的木马程式或一些安全漏洞， 相对而言，会比较更加的安全！

Open source的代表授权为GNU的GPL授权及BSD等等，底下列出知名的Open Source授权网页：

  • GNU General Public License：
    http://www.gnu.org/licenses/licenses.html#GPL
    目前有version 2, version 3两种版本，Linux使用的是version 2这一版。 鸟哥也有收集一份GPL version 2 的中文化条文，您可以参考：http://linux.vbird.org/linux_basic/1010appendix_A.php

  • Berkeley Software Distribution (BSD)：
    http://en.wikipedia.org/wiki/BSD_license
    使用BSD source code最常接触到的就是BSD授权模式了！这个授权模式其实与GPL很类似， 而其精神也与Open Source相呼应呢！

  • Apache License, Version 2.0：
    http://www.apache.org/licenses/LICENSE-2.0
    Apache是一种网页伺服器软体，这个软体的发布方式也是使用Open source的。只是在apache的授权中规定， 如果想要重新发布此软体时(如果你有修改过该软体)，软体的名称依旧需要定名为Apache才行！

  • Close Source

相对于Open Source的软体会释出原始法，Close source的程式则仅推出可执行的二进位程式(binary program)而已。 这种软体的优点是有专人维护，你不需要去更动他；缺点则是灵活度大打折扣，使用者无法变更该程式成为自己想要的样式！ 此外，若有木马程式或者安全漏洞，将会花上相当长的一段时间来除错！这也是所谓专利软体(copyright)常见的软体出售方式。

虽然专利软体常常代表就是需要花钱去购买，不过有些专利软体还是可以免费提供大众使用的！ 免费的专利软体代表的授权模式有：

  • Freeware：
    http://en.wikipedia.org/wiki/Freeware
    不同于Free software，Freeware为‘免费软体’而非‘自由软体！’虽然它是免费的软体，但是不见得要公布其原始码， 端看释出者的意见啰！这个东西与Open Source毕竟是不太相同的东西喔！此外，目前很多标榜免费软体的程式很多都有小问题！ 例如假藉免费软体的名义，实施使用者资料窃取的目的！ 所以‘来路不明的软体请勿安装！’

  • Shareware：
    http://en.wikipedia.org/wiki/Shareware
    共享软体这个名词就有趣了！与免费软体有点类似的是，Shareware在使用初期，它也是免费的，但是， 到了所谓的‘试用期限’之后，你就必须要选择‘付费后继续使用’或者‘将它移除’的宿命～ 通常，这些共享软体都会自行撰写失效程式，让你在试用期限之后就无法使用该软体。
大标题的图示 重点回顾
  • 电脑主要以二进位作为单位，而目前常用的磁碟容量单位为bytes，其单位换算为1Byte = 8bits， 其他的以1024为其倍数，如 1GByte=1024MBytes等等。
  • 作业系统(Operation System)主要在管理与驱动硬体，因此必须要能够管理记忆体、管理装置、 负责行程管理以及系统呼叫等等。因此，只要能够让硬体准备妥当(Ready)的情况， 就是一个阳春的作业系统了。
  • 最阳春的作业系统仅在驱动与管理硬体，而要使用硬体时，就得需要透过应用软体或者是壳程式(shell) 的功能，来呼叫作业系统操纵硬体工作。因此，目前称为作业系统的， 除了上述功能外，通常已经包含了日常工作所需要的应用软体在内了。
  • Unix的前身是由贝尔实验室(Bell lab.)的Ken Thompson利用组合语言写成的， 后来在1971-1973年间由Dennis Ritchie以C程式语言进行改写，才称为Unix。
  • 1977年由Bill Joy释出BSD (Berkeley Software Distribution)，这些称为Unix-like的作业系统。
  • 1984年由Andrew Tannenbaum制作出Minix作业系统，该系统可以提供原始码以及软体；
  • 1984年由Richard Stallman提倡GNU计划，倡导自由软体(Free software)， 强调其软体可以‘自由的取得、复制、修改与再发行’，并规范出GPL授权模式， 任何GPL(General Public License)软体均不可单纯仅贩卖其软体，也不可修改软体授权。
  • 1991年由芬兰人Linus Torvalds开发出Linux作业系统。简而言之，Linux成功的地方主要在于： Minix(Unix), GNU, Internet, POSIX 及虚拟团队的产生。
  • Linux本身就是个最阳春的作业系统，其开发网站设立在http://www.kernel.org，我们亦称Linux作业系统最底层的资料为‘核心(Kernel)’。
  • 目前Linux核心的发展分为两种版本，分别是稳定版本的偶数版，如2.6.X，适合于商业与家用环境使用； 一种是发展中版本如2.5.X 版，适合开发特殊功能的环境。
  • Linux distributions的组成含有：‘Linux Kernel + Free Software + Documentations(Tools) + 可完整安装的程序’所制成的一套完整的系统。
大标题的图示 本章习题
(要看答案请将滑鼠移动到‘答：’底下的空白处，按下左键圈选空白处即可察看)
实作题部分：
  • 请依据本章内容的说明，下载 Fedora 最新版本的 Live CD ，并将该 Live CD 烧录成为光碟 (或 DVD) 后， 调整你的主机 BIOS 成为使用光碟机开机，在开机时放入刚刚烧录的 Live CD ，使用该光碟机开机。在开机后你应该能够进入系统。 请进入该系统，尝试打开终端机、浏览器等，并尝试操作一下该系统。由于该系统并不会影响到你的硬碟资料， 请尽量玩玩！

  • 承上题，打开终端机并且输入‘ uname -r ’这个指令，出现的核心版本为何？是稳定还是发展中版本？

  • 请上网找出目前 Linux 核心的最新稳定版与发展中版本的版本号码，请注明查询的日期与版本的对应。

  • 请上网找出 Linux 的吉祥物企鹅的名字，以及最原始的图档画面。(提示：请前往 http://www.linux.org 查阅)

简答题部分：
  • 你在你的主机上面安装了一张网路卡，但是开机之后，系统却无法使用，你确定网路卡是好的，那么可能的问题出在哪里？该如何解决？
    因为所有的硬体都没有问题，所以，可能出问题的地方在于系统的核心(kernel) 不支援这张网路卡。解决的方法，(1)到网路卡的开发商网站，(2)下载支援你主机作业系统的驱动程式， (3)安装网路卡驱动程式后，就可以使用了。
  • 我在一部主机上面安装Windows作业系统时，并且安装了显示卡的驱动程式，他是没有问题的。但是安装Linux时，却无法完整的显示整个X Window。请问，我可不可以将Windows上面的显示卡驱动程式拿来安装在Linux上？
    不行！因为核心不同，针对硬体所写的驱动程式也会不相同，编译器也不同，当然，驱动程式也无法在两个作业系统间相容。 这也是为何开发商在他们的网站上面，都会同时提供许多不同作业系统的驱动程式之故。
  • 一个作业系统至少要能够完整的控制整个硬体，请问，作业系统应该要控制硬体的哪些单元？
    根据硬体的运作，以及资料在主机上面的运算情况与写入/读取情况，我们知道至少要能够控制： (1)input/output crontrol, (2)device control, (3)process management, (4)file management. 等等！
  • 一个GBytes的硬碟空间，等于几个KBytes？
    1GBytes = 1024 MBytes * 1024 KBytes/MBytes = 1048576 KBytes
  • 我在Windows上面玩的游戏，可不可以拿到Linux去玩？
    当然不行！因为游戏也是一个应用程式 (application)，他必须要使用到核心所提供的工具来开发他的游戏， 所以这个游戏是不可在不同的平台间运作的。除非这个游戏已经进行了移植。
  • Linux本身仅是一个核心与相关的核心工具而已，不过，他已经可以驱动所有的硬体， 所以，可以算是一个很阳春的作业系统了。经过其他应用程式的开发之后，被整合成为Linux distribitions。请问众多的distributions之间，有何异同？
    相同：(1)同样使用 http://www.kernel.org 所释出的核心； (2)支援同样的标准，如 FHS、LSB 等； (3)使用几乎相同的自由软体 (例如 GNU 里面的 gcc/glibc/vi/apache/bind/sendmail... )； (4)几乎相同的操作介面 (例如均使用 bash/KDE/GNOME 等等)。
    不同：使用的 kernel 与各软体的版本可能会不同；各开发商加入的应用工具不同，使用的套件管理模式不同(dpkg 与 RPM)
  • Unix 是谁写出来的？ GNU 计划是谁发起的？
    Unix 是 Ken Thompson 写的，1973 年再由 Dennis Ritchie 以 C 语言改写成功。 至于 GNU 与 FSF 则是 Richard Stallman 发起的。
  • GNU 的全名为何？他主要由那个基金会支持？
    GNU 是 GNU is Not Unix 的简写，是个无穷回圈！ 另外，这个计划是由自由软体基金会 (Free Software Foundation, FSF) 所支持的！ 两者都是由 Stallman 先生所发起的！
  • 何谓多人 ( Multi-user ) 多工 ( Multitask )？
    Multiuser 指的是 Linux 允许多人同时连上主机之外，每个使用者皆有其各人的使用环境，并且可以同时使用系统的资源！
    Multitask 指的是多工环境，在 Linux 系统下， CPU 与其他例如网路资源可以同时进行多项工作， Linux 最大的特色之一即在于其多工时，资源分配较为平均！
  • 简单说明 GNU General Public License ( GPL ) 与 Open Source 的精神：
    1. GPL 的授权之软体，乃为自由软体（Free software），任何人皆可拥有他； 2. 开发 GPL 的团体(或商业企业)可以经由该软体的服务来取得服务的费用； 3. 经过 GPL 授权的软体，其属于 Open source 的情况，所以应该公布其原始码； 4. 任何人皆可修改经由 GPL 授权过的软体，使符合自己的需求； 5. 经过修改过后 Open source 应该回馈给 Linux 社群。
  • 什么是 POSIX ?为何说 Linux 使用 POSIX 对于发展有很好的影响？
    POSIX 是一种标准规范，主要针对在 Unix 作业系统上面跑的程式来进行规范。 若你的作业系统符合 POSIX ，则符合 POSIX 的程式就可以在你的作业系统上面运作。 Linux 由于支援 POSIX ，因此很多 Unix 上的程式可以直接在 Linux 上运作， 因此程式的移植相当简易！也让大家容易转换平台，提升 Linux 的使用率。
  • Linux 的发展主要分为哪两种核心版本？
    主要分为奇数的发展中版本(develop)，如 2.5 ，及偶数的稳定版本，如 2.6 。
  • 简单说明 Linux 成功的因素？
    1. 藉由 Minix 作业系统开发的 Unix like ，没有版权的纠纷；
    2. 藉助于 GNU 计划所提供的各项工具软体， gcc/bash 等；
    3. 藉由 Internet 广为流传；
    4. 藉由支持 POSIX 标准，让核心能够适合所有软体的开发；
    5. 托瓦兹强调务实，虚拟团队的自然形成！
大标题的图示 参考资料与延伸阅读
  • Multics计划网站：http://www.multicians.org/。
  • 葛林穆迪着，杜默译，‘Linux传奇’，时报文化出版企业。
    书本介绍：http://findbook.tw/book/9789571333632/basic
  • 网路农夫，2001，Unix简史：
    http://netlab.cse.yzu.edu.tw/~statue/freebsd/docs/csh/
  • Ken Thompson的个人网站：http://plan9.bell-labs.com/cm/cs/who/ken/index.html
  • Dennis Ritchie的个人网站： http://cm.bell-labs.com/cm/cs/who/dmr/
  • Richard Stallman的个人网站： http://www.stallman.org/
  • GNU计划： http://www.gnu.org
  • XFree86的网站：http://www.xfree86.org/
  • 洪朝贵老师的GNU/FSF介绍： http://people.ofset.org/~ckhung/a/c_83.php
  • 维基百科对Linus Torvalds的介绍：http://en.wikipedia.org/wiki/Linus_Torvalds。
  • POSIX的相关说明：
    维基百科：http://en.wikipedia.org/wiki/POSIX
    IEEE POSIX标准：http://standards.ieee.org/regauth/posix/
2002/06/25：第一次完成
2003/01/26：重新修订，加入一些历史事件、重新编排与加入 FAQ
2003/02/28：加入百资以及 distrowatch 两个网站的推荐！
2005/05/31：旧有的资料放于 此处
2005/06/02：做了大幅度的改版，很多资料参考了网路农夫及 Linux 传奇等书籍，建议大家要多看看网路农夫的大作喔！
2005/06/08：将原本的 binary / compiler / Emacs 的地方再说明一下！比较容易了解那是什么！顺便加入习题
2005/07/21：网路农夫的网站结束了～真伤心～只好提供网路农夫之前发表的文章连结了！
2005/08/03：感谢网友 babab 的来信告知，修订了国家高速网路中心网址：http://www.nchc.org.tw
2005/10/24：经由网友的回报，洪朝贵老师已经调职到树德大学，因此整个连结内容已作修订。
2006/05/31：加入了重点回顾的项目啦！
2006/06/06：感谢网友 "Warren Hsieh" 兄的提醒，由于麦金塔在 2006 年后使用 Intel 的 x86 硬体架构，故 Windows 是可能可以在上面安装的！
2008/07/23：因为加入了计算机概论的章节，所以本文做了挺大幅度的修改！原本针对FC4的版本请点选这里。
2007/07/26：将整份文章重新校阅过，修订一些文辞，也将格式调整为适合的XHTML了！
2007/07/29：将主、次核心版本加强说明！
2009/08/05：移除最后一小节的标准，将FHS与LSB向前挪到distribution解释中。拿掉伺服器、工作站、终端机的说明。


鸟哥的 Linux 私房菜 -- 基础学习篇

为取得较佳浏览结果，请爱用 firefox 浏览本网页
鸟哥的 Linux 私房菜馆 | Linux 基础文件 | Linux 架站文件 | Linux 企业运用 | 安全管理 | 新手讨论 |

第二章、 Linux 如何学习
最近更新日期：2009/08/06
目前Linux上头有两种主要的操作模式，分别是图形介面与文字介面，那么学习Linux要用X-Window(图形介面)好还是Command Line(文字介面)好？这两种学习心态有什么优缺点呢？此外，有没有良好的入门文件可供参考？ Linux学习有困扰的时候应该要如何发问？要到哪里去搜寻网路资源？还有，怎样进行有智慧的提问？嗯！ 在这一章里面，就让我们好好谈一谈！

1. Linux当前的应用角色
    1.1 企业环境的利用
1.2 个人环境的使用
 2. 鸟哥的Linux苦难经验全都录
    2.1 鸟哥的Linux学习之路
2.2 学习心态的分别
2.3 X window的学习
 3. 有心朝Linux作业系统学习者的学习态度
    3.1 从头学习Linux基础
3.2 选择一本易读的工具书
3.3 实作再实作
3.4 发生问题怎么处理啊？建议流程是这样...
 4. 鸟哥的建议(重点在solution的学习)
5. 重点回顾
6. 本章习题
7. 参考资料与延伸阅读
8. 针对本文的建议：http://phorum.vbird.org/viewtopic.php?t=23872
大标题的图示 Linux当前的应用角色

在第一章Linux是什么当中，我们谈到了Linux相关的历史， 与简单的介绍了一下Linux这个‘Kernel’与Linux distributions等等。 而在开始进入Linux的基础学习之前，我们有必要了解一下应该要如何有效的学习Linux！ 但在谈到Linux如何学习之前，我们得就Linux目前的一般应用来说明一下，因为每种应用你所需要的Linux技能都不相同！ 了解Linux的应用后，你才好理解你需要的是什么样的学习方式！

由于Linux kernel实在是非常的小巧精致，可以在很多强调省电以及较低硬体资源的环境底下执行； 此外，由于Linux distributions整合了非常多非常棒的软体(不论是专利软体或自由软体)， 因此也相当适合目前个人电脑的使用呢！当前的Linux常见的应用可约略分为企业应用与个人应用两方面来说：

小标题的图示 企业环境的利用

企业对于数位化的目标在于提供消费者或员工一些产品方面的资讯 (例如网页介绍)，以及整合整个企业内部的资料统一性 (例如统一的帐号管理/文件管理系统等)。另外，某些企业例如金融业等，则强调在资料库、安全强化等重大关键应用。 学术单位则很需要强大的运算能力等。所以企业环境运用Linux作些什么呢？

  • 网路伺服器：

这是Linux当前最热门的应用了！ 承袭了Unix高稳定性的良好传统，Linux上面的网路功能特别的稳定与强大！ 此外，由于GNU计划与Linux的GPL授权模式，让很多优秀的软体都在Linux上面发展， 且这些在Linux上面的伺服器软体几乎都是自由软体！因此，做为一部网路伺服器，例如WWW, Mail Server, File Server等等，Linux绝对是上上之选！当然，这也是Linux的强项！ 目前很多硬体厂商甚至搭配自家的硬体来销售Linux呢！例如底下的连结看看先：

  • HP公司的产品：http://h18000.www1.hp.com/products/servers/byos/linuxservers.html
  • IBM公司的产品：http://www-07.ibm.com/servers/eserver/tw/openpower/

  • 关键任务的应用(金融资料库、大型企业网管环境)：

由于个人电脑的效能大幅提升且价格便宜，所以金融业与大型企业的环境为了要精实自己机房的机器设备， 因此很多企业渐渐的走向Intel相容的x86主机环境。而这些企业所使用的软体大多使用Unix作业系统平台的软体， 总不能连过去发展的软体都一口气全部换掉吧！所以啰， 这个时候符合Unix作业系统标准并且可以在x86上运作的Linux就渐渐崭露头角了！^_^

目前很多金融业界都已经使用Linux做为他们的关键任务应用。所谓的关键任务就是该企业最重要的业务啦！ 举例来说，金融业最重要的就是那些投资者、帐户的资料了，这些资料大多使用资料库系统来作为存取介面， 这些资料很重要吧！很多金融业将这么重要的任务交给了Linux了！你说Linux厉不厉害啊？(注1)

  • 学术机构的高效能运算任务：

学术机构的研究常常需要自行开发软体，所以对于可作为开发环境的作业系统需求非常的迫切！举例来说， 非常多技职体系的科技大学就很需要这方面的环境，好进行一些毕业专题的制作呢！ 又例如工程界流体力学的数值模式运算、娱乐事业的特效功能处理、软体开发者的工作平台等等。 由于Linux的创造者本身就是个电脑性能癖，所以Linux有强大的运算能力；并且Linux具有支援度相当广泛的GCC编译软体， 因此Linux在这方面的优势可是相当明显的！

举个鸟哥自己的案例好了，鸟哥之前待的研究室有跑一套空气品质模式的数值模拟软体。 这套软体原本只能在Sun的SPARC机器上面跑。后来该软体转向Linux作业系统平台发展， 鸟哥也将自己实验室的数值模式程式由Sun的Solaris平台移植到Linux上面呢！ 据美国环保署内部人员的测试，发现Linux平台的整体硬体费用不但比较便宜(x86系统嘛！)而且速度还比较快呢！

另外，为了加强整体系统的效能，丛集电脑系统(Cluster)的平行运算能力在近年来一直被拿出来讨论(注2)。 所谓的平行运算指的是‘将原本的工作分成多份，然后交给多部主机去运算，最终再将结果收集起来’的一种方式。 由于透过高速网路使用到多部主机，将能够让原本需要很长运算时间的工作，大幅的降低等待的时间！ 例如中央气象局的气象预报就很需要这样的系统来帮忙！而Linux作业系统则是这种架构下相当重要的一个环境平台呢！

Tips:
目前鸟哥所在的昆山科技大学资讯传播系，我们系上就有一套由12部双核心个人电脑组成的丛集电脑架构； 这一整组配备组起来差不多30万左右，不过却可以让我们的数值模式大幅降低等待时间！这12部主机装的就是Linux啦！ 		鸟哥的图示
小标题的图示 个人环境的使用

你知道你平时接触的电子用品中，哪些咚咚里面有Linux系统存在呢？其实相当的多呢！我们就来谈一谈吧！

  • 桌上型电脑：

所谓的桌上型电脑，其实就是你我在办公室使用的电脑啦。一般我们称之为Desktop的系统。那么这个 Desktop 的系统平时都在做什么呢？大概都是这些工作吧：

  • 上网浏览+即时通讯(MSN, Skype, Yahoo...)；
  • 文书处理；
  • 网路介面之公文处理系统；
  • 办公室软体(Office Software)处理资料；
  • 收发电子邮件；

想进行这些电脑工作时，你的Desktop环境需要什么咚咚？很简单，‘就是需要视窗’！ 因为上网浏览、文书编排的所见即所得介面，以及电子公文系统等等， 如果没有视窗介面的辅助，那么将对使用者造成很大的困扰。而众所皆知的， Linux早期都是由工程师所发展的，对于视窗介面并没有很需要，所以造成Linux不太亲和的印象。

好在，为了要强化桌上型电脑的使用率，Linux与X Window System结合了！ 要注意的是，X Window System仅只是Linux上面的一套软体， 而不是核心喔！所以即使X Window挂了，对Linux也可能不会有直接的影响呢！ 更多关于 X window system 的详细资讯我们留待第二十四章再来介绍。

近年来在各大社群的团结合作之下，Linux的视窗系统上面能够跑的软体实在是多的吓人！而且也能够应付的了企业的办公环境！ 例如美观的KDE与GNOME视窗介面，搭配可相容微软Office的Open Office软体， Open Office包含了文书处理、电子试算表、简报软体等等，功能齐全啊！然后配合功能强大速度又快的Firefox浏览器， 以及可下载信件的雷鸟(ThunderBird)软体(类似微软的Outlook Express)，还有可连上多种即时通讯的Pidgin！ Linux能够做到企业所需要的各项功能啦！

  • 手持系统(PDA、手机)：

别跟我说在台湾你没有用过手机！你知道吗，很多的手机、PDA、导航系统都可能使用的是Linux作业系统喔！ 而为了加强Linux作业系统在手机上面的统一标准，很多国际厂商合作了一个LiMo的计划(Linux Mobile phone)，也有Linux的手机论坛，你可以参考一下底下的连结：

  • LiMo基金会：http://www.limofoundation.org/
  • Linux手机论坛：http://www.lipsforum.org/

除此之外，还有社群以及Google这个高超的家伙也在玩Linux手机喔！例如底下的连结说明：

  • OpenMoKo网站：http://www.openmoko.com/
  • Google的手机平台：http://code.google.com/android/

了解了吧？在你天天碰的手机里头可能就含有Linux作业系统呢！很有趣的发现吧！ ^_^

  • 嵌入式系统：

在第零章当中我们谈到过硬体系统， 而要让硬体系统顺利的运作就得要撰写合适的作业系统才行。那硬体系统除了我们常看到的电脑之外， 其实家电产品、PDA、手机、数位相机以及其他微型的电脑配备也是硬体系统啦！ 这些电脑配备也都是需要作业系统来控制的！而作业系统是直接嵌入于产品当中的，理论上你不应该会更动到这个作业系统， 所以就称为嵌入式系统啦！

包括路由器、防火墙、手机、PDA、IP分享器、交换器、家电用品的微电脑控制器等等，都可以是Linux作业系统喔！ 酷学园内的Hoyo大大就曾经介绍过如何在嵌入式设备上面载入Linux！ 目前火红的netbook中，很多也是使用Linux哩！

虽然嵌入式设备很多，大家也想要转而使用Linux作业系统，不过在台湾，这方面的人才还是太少了！ 要玩嵌入式系统必须要很熟悉Linux Kernel与驱动程式的结合才行！这方面的学习可就不是那么简单喔！ ^_^

总之，网路伺服器、工作站电脑、桌上型电脑等等，就是Linux目前最常被应用的环境了。 而您如果想要针对桌上型电脑，或者是网路伺服器主机来学习的话，对于Linux， 您应该如何进行学习的课题呢？底下我们就来谈一谈。

大标题的图示 鸟哥的Linux苦难经验全都录

为什么鸟哥要先介绍Linux的应用，并且还要写这一章‘如何学习’呢？原因就是.....鸟哥曾经受过伤害啊！ 瞎密？什么伤害呢？是要看外科还是精神科？都不是啦！因为鸟哥玩Linux初期曾经犯了‘天下新手都可能容易犯的错’～@_@ 所以这里才先要跟大家耳提面命一番嘛！

小标题的图示 鸟哥的Linux学习之路
  • 接触Linux的原因

大约在1999年左右，鸟哥因为学业上的需要，‘被迫’得去学习Unix系统，那个时候我们使用的Unix系统是Sun 的SPARC+Solaris作业系统，当时的Sun Unix可不是一般人玩的起的，鸟哥也是一般人，所以当然也就玩不起Sun Unix啰！ 然而学业上所需要完成的计划案还是需要进行的，那怎么办呢？这个时候就得要想一些替代方案啦！

咦！听说有另外一种可以在PC上头跑的Unix-Like系统，叫做Linux的，他的介面、功能以及基本的档案架构都跟Unix差不多， 甚至连系统稳定性也可以说是一模一样，而且对于硬体配备的要求并不高。嗯！既然玩不起几十万起跳的Unix系统， 那么使用一些即将淘汰的电脑配备来架设一部Linux主机吧！

在经过了一些时候的努力之后，呵呵！竟然真的给鸟哥架起来了(当时的版本是Red Hat 6.1)！哇！好高兴！ 那么就赶快先来熟悉他，然后等到有了一定的经验值‘升级’成老手级之后， 再来玩Unix吧， 以免玩坏了几十万的大电脑！嗯！这似乎是不错的方式，所以就开始了鸟哥的Linux学习之路啦！

  • 错误的学习方针阶段

由于鸟哥之前连Unix是啥都没听过，当然就更别提Linux这套作业系统，更可怕的是，听说Linux还需要使用到指令列模式！ 刚开始碰还真的有点紧张。还好，鸟哥玩电脑的历史可以追溯之前的DOS年代，所以对于指令列模式多多少少还有点概念， 这过去的经验或许应该可以撑上一阵子吧？但是没想到Linux的指令真是‘博大精深’呐！早期的DOS概念简直就是不够用啊～ 因此，为了偷懒，一开始鸟哥就舍弃指令列模式，直接在X-Window上面玩起来了！

在还没有安装Linux之前，鸟哥就买了两三本书，每本都看了N遍，发现到每一本书的前半段， 在Linux的基础方面的介绍谈的不多，了不起就是以一些工具教你如何设定一些很重要的参数档案， 但偏偏没有告诉你这些工具到底做了什么事情或修改了哪些档案？不过书的后半段却放上了很多的架站文件， 然而却都有点‘点到为止’，所以当时总觉得Linux很有点朦朦胧胧的感觉， 而且在当时最严重的现象是‘只要一出现问题，身为使用者的鸟哥完全无法解决， 所以只好选择重新安装，重新设定与书本教的内容完全一模一样的环境！’不过，即使如此， 很多时候仍然解决不了发生问题的窘境！

Tips:
那个时候真的很好笑，由于鸟哥并非资讯科系出身，所以身旁并没有懂电脑/作业系统的朋友，也就不知道怎么发问！ 曾经为了要安装光碟机里面的资料，放进光碟机后，利用X Window的自动挂载将光碟挂载起来， 用完之后却发现无法退出光碟机，最终竟然用回纹针将光碟强制退片～唔！这样光碟就无法再使用～@_@只好又重新开机.... 		鸟哥的图示

在当时，由于知道Linux可以用来做为很多功能的伺服器，而鸟哥的研究室当时又需要一部电子邮件伺服器， 所以鸟哥就很高兴的藉由书上的说明，配合Red Hat 6.1提供的一些工具程式，例如：Linuxconf, netcfg等等的工具来架设。 然而由于工具程式的整合度并不见得很好，所以常常修改一个小地方会搞上一整天！

好不容易使用了所有的知道的工具来架设好了鸟哥的电子邮件伺服器，哈哈！真高兴， 请注意呦！这个时候鸟哥的Linux主机上面开了多少的ports/services其实当时的鸟哥并不清楚， 当时认为‘俺的机器就只有我认识的一些朋友知道而已， 所以反正机器能跑就好了，其他的设定似乎也就不这么重要’。

  • 恶梦的开始.....

然而事实上，这种学习心态却造成了后来鸟哥恶梦的开端！怎么说呢？虽然Linux号称需要的硬体等级不高， 不过X-Window却是很耗系统资源的一项软体，因为只要涉及到图形介面的话，需要亲和力嘛！就需要多一点RAM啦、 多一些硬碟空间啦、显示卡与CPU要好一点啦等等的，且早期的图形介面整合度不是很高，所以造成X-Window死掉的机会是很高的。

在鸟哥当时安装的Linux主机当中，使用的是旧旧的电脑，系统的配备并不高，在跑了X-Window之后， 剩下可以使用的实体记忆体其实已经不多了，再跑其他的服务，例如mail server，实际上很有点吃力！ 所以当时的一些同仁常常抱怨我们的机器怎么老是服务不良？怪怪！这个Linux怎么跟‘号称稳定’的名号不符？ 而在鸟哥登入系统检查之后，才发现，哇！X-Window又挂了？当时还不清楚原来可以使用ps及kill等指令将X-Window杀掉即可让 Linux恢复正常，竟然是用reset的方式来重新启动Linux，现在想起来，当时真糗....

后来再重新安装一次，并选择了文字介面登入系统，呵呵！果然系统是稳定多了！服务上面似乎也就安定了许多。 不过，你以为恶梦这样就解决了吗？当然不是！在鸟哥的机器服务了一阵子之后，我老板竟然接到上层单位的来信， 信中说明‘贵单位的主机可能有尝试入侵国外主机之嫌，敬请妥善改善！’ 哇！这不就是警告信吗？还好不是律师存证信函～当时至少还知道有所谓的系统登录档案可以分析确切日期有谁在线上， 没想到一登入之后才发现，搞了老半天，原来我们的机器被入侵了！而身为管理者的鸟哥竟然还茫然不知～这真是一大败笔....

Tips:
瞎密？由图形介面转到文字介面竟然用‘重新安装’来处理？不要怀疑，当初没有学好Linux的时候， 就是以为需要重新安装，尤其Windows的经验告诉我们，这样做‘才是对的！’@_@ 		鸟哥的图示

在赶快重新安装，并且重新参考很多文件，架设好了防火墙之后，以为终于从此就可以高枕无忧了！ 唉～结果还是不尽然的，因为我们的电子邮件伺服器早就被当成垃圾转信站，造成区域网路内网路流量的大量提高， 导致常常会无法连上网际网路....

  • 一个贵人的出现

在经过了一年多以及经历那么多事件后，鸟哥还是没有觉悟ㄟ！真糟糕！ 后来因为某些小事情无法解决而上网搜寻，竟然找到Study Area(酷学园)， 并主动发出email给站长网中人(netman)先生，网中人完全没有就我的问题来回答，竟然是大发雷霆的臭骂鸟哥一顿～ 唔！怎么会这样～鸟哥从小到大念书几乎没有被念过～竟然读到这么大了还被人家骂！真可悲～ 于是乎痛定思痛，遵循网中人大哥的教诲，从他的网站(http://www.study-area.org)的内容出发，并将鸟哥原本的网站全部砍掉重练！

花了两三个月在网中人的网站上学习到Linux最基础的档案架构、指令模式与脚本(Shell and shell scripts)、 软体管理方式和资源与帐号管理等等，而在将这些基础的架构理解之后，再回头看一下各式各样的server启动服务与相关的技巧， 发现‘哇！原来如此呀！怎么这么简单的东西当初搞了我几天几夜睡不好！’ 尤其最重要的登录资讯的追踪，帮鸟哥避免了很多不必要的系统伤害行为。

此外，而为了方便鸟哥本身的管理，于是开始了一些脚本(shell scripts)的编写，让日常的管理变的更轻松而有效率！ 当然，这些工作几乎都是在文字介面底下完成的，图形介面之下的工作毕竟还是有限的。

  • 撰写文件的有趣经验

后来鸟哥为了想要赶快毕业，但希望能够让我在实验室的努力不被学弟妹所搞烂，所以开始撰写一些FAQ的文件。 但是没想到越写越发现自己懂得竟然是那么少，于是乎就越写越多，资料也越查阅多，渐渐的就有‘鸟哥的Linux私房菜’网站的出现！ 而在写了这个网站之后发现到更多的朋友其实与鸟哥有相同的经验，他们也在讨论区上面提供非常多有用的意见， 于是网站就越来越热闹了！

从撰写文件的经验里面也接触到很多业界的朋友，才发现到一部Linux主机其实是做不了什么大事的！ 重点是‘我们要让Linux解决什么问题’，而不是单纯的只是去学习架站而已！ 尤其酷学园的ZMAN对鸟哥网站关于伺服器方面的资料影响很大！我们不能够让Linux死板板的定位在那边， 还有更多可用的功能可以让我们去思考呢！

  • 鸟哥的忠言，希望不会逆耳

经过上面鸟哥学习之路的经验分享之后，我想，您应该也慢慢的了解鸟哥想要提出这本经验谈的书籍最主要的目的了， 那就是想‘让想要学习Linux的玩家可以快速且以较为正确的心态来进入Linux的世界！’ 而不要像鸟哥在Linux的环境中打转了一年多之后才来正确的建立概念。希望我这老家伙的苦口婆心不要让您误会啊！

但是玩Linux并不一定要很辛苦的！因为‘你玩Linux的目的跟我又不一样’！ 鸟哥是为了要学习Linux上面的功能，好应用在未来学术研究领域上，所以才这样接触他～ 那难道你不能只为了要使用Linux的桌上办公环境吗？是的！所以鸟哥想来谈一谈Linux的学习者心态！

小标题的图示 学习心态的分别
  • 架不架站有所谓：

大家都知道Linux最强项的地方在于网路，而Windows是赢在使用者介面较为亲善。 然而很多使用者还是常常会比较Linux与Windows这两套相当流行的作业系统，初次接触Linux的人比到最后的结果都是 ‘Linux怎么都要使用文字介面来架站，怎么这么麻烦，还是Windows比较好用’， 事实上这么比较实在是有点不公平且没有意义， 为什么呢？基本上，Windows是很普及的一个作业系统，这点我们都无法否认，但是，一般使用Windows的使用者用Windows来做什么？

  • 上网、即时通讯、打屁聊天打发时间；
  • 做做文书工作，处理电子试算表；
  • 玩Game及其他休闲娱乐；

当然啦，Windows的工作环境还有很多可以发展的空间，不过这里我们主要以一般使用者的角度来看。 OK！说了上面这几个工作，请问一下，‘一般使用者谁有在使用Windows玩架站！’？ 很少对不对！是的！真的是很少人在玩Windows的架站！那么如何可以说Linux无法普及是文字介面惹的祸呢？ 鸟哥相信，如果是一般使用者，应该不至于想要使用Linux来架设网站，所以美美的X-Window对于一般使用者已经相当的好用了， 实在没有必要来学习架站的原理与过程，还有防火墙的注意事项等等的。

话再说回来，那么你干嘛要使用Linux架站呢？‘因为Linux的网路功能比较强呀！’ 说的没错，但是，相对的，比较强的项目可能也具有比较‘危险’的指数，当你一开始学习Linux就只想满脑子的玩架站， 却又不好好的弄懂一点Linux与网路基础的话，Windows底下了不起是被攻击到您的Windows死掉， 但是在Linux底下，却有可能让你吃上官司的！像上面提到的鸟哥的惨痛教训！

  • 只是图形介面，可以吗？

而如果你已经习惯以图形化介面来管理你的Linux主机时，请特别留意，因为Linux的软体是由多个团队研发出来的， 图形介面也仅是一个团队的研发成果，你认为，一个团队的东西可以将所有团队的内容都完整无缺的表现出来吗？ 如果你依赖图形久了，呵呵！那如果你的系统出问题，看来就只能求助于外面的工程师了，如此一来，有学跟没有学有何不同？

曾经有个朋友问我说‘唉！Linux怎么这么麻烦？架设一个DNS真是不容易呀！不像Windows，简单的很， 按几个按钮就搞定了！’这个时候鸟哥就回答了一句话‘不会呀！如果你只是想要安装DNS的话， 网路上面一大堆按部就班的设定方式教学，照着做，一样可以在十分钟之内就完成一个DNS主机的设定呀！’ 他想一想，确实有道理！同时鸟哥又反问的一件事：‘你以为学Windows就不需要了解DNS的概念吗？ 你有尝试过使用Windows架设DNS却无法让他实地跑的问题吗？果真如此的话，这个时候你怎么解决？’ 他愣住了！因为在Windows上面他确实也没有办法解决！所以说，不论是学哪一套系统， ‘基础的理论都是不变的’，也只有了解了基础的咚咚之后，其他的技能才能够‘触类旁通’呀！

网路上一些老手不太喜欢搞图形介面，是因为觉得图形介面预设的设定常常不合他们的意， 尤其是图形化介面软体为了方便使用者，常常自己加入一些设定，但是这些设定却往往是因地制宜的， 所以反而常常会导致架设的网站无法正常工作！这点在网路新闻群组上面讨论的已经相当清楚了！ 与其如此，何不一开始就玩文字介面，去弄懂他呢？

  • 学习Linux还是学习Distributions：

此外，很多玩过Linux的朋友大概都会碰到这样的一个问题，就是Linux distributions事实上是非常多的！ 而每个distribution所提供的软体内容虽然大同小异，然而其整合的工具却都不一样，同时， 每种软体在不同的distribution上面摆放的目录位置虽然也是大同小异，然而某些设定档就是摆在不同的目录下， 这个时候您怎么找到该资讯？难道非得来一套distribution就学他的主要内容吗？这么一来， 市面上少说也有数十套Linux distributions，每一套都学？如果您时间多到如此地步， 那鸟哥也不知道该说什么好了！如果是我的话，那么我会干脆直接学习一些Linux的基本技巧， 可以让我很轻易的就找到不同版本之间的差异性，而且学习之路也会变的更宽广呢！

鸟哥的观念不见得一定适合你，不过就只是以一个过来人的身份给个小建议， 要么就不要拿Linux来架站，跟Windows一样，玩玩X-Window就很开心了，要嘛真的得花一点时间来玩一玩比较深入的东西， 中国话不是说过吗：‘要怎么收获就怎么栽’虽然努力不一定有成果，但最起码，有成果的时候，成果肯定是自己的！

小标题的图示 X window的学习

如果你只是想要拿Linux来取代原本的Windows桌面(Desktop)的话，那么你几乎不需要通过‘严格的学习’啦！ 目前的Linux distribution绝大部分预设就是以Desktop的角度来安装所需要的软体，也就是说，你只要将Linux安装好， 接下来就能够进入Linux玩弄啦！根本就不需要什么学习的哩！你只需要购买一本介绍Linux桌面设定的书籍， 里面有说明输入法、印表机设定、网际网路设定的书籍就很够用了！鸟哥建议的distributions包括有：

  • Ubuntu下载: http://www.ubuntu.com/getubuntu/download
  • OpenSuSE下载: http://software.opensuse.org/
  • Fedora下载： http://fedoraproject.org/en/get-fedora, 台湾Fedora社群： http://fedora.tw/
  • Mandriva下载: http://www.mandriva.com/en/download/free

另外还有一些网路上面的桌面调教文章也可以参考的！包括有：

  • 杨老师的图解桌面 http://apt.nc.hcc.edu.tw/docs/FC3_X/
  • Ubuntu 中文指南 http://ubuntuguide.org/wiki/Ubuntu:Hardy_tw

如果想知道更多关于图形使用者介面能够使用的软体资讯，可以参考底下的连结(感谢昆山计中提供的连结资讯)：

  • Open Office(http://www.latex-project.org/)：
    就是办公室软体，包含有电子试算表、文书处理与简报软体等；
  • Free Maid(http://freemind.sourceforge.net/wiki/index.php/Main_Page)：
    可绘制组织图的软体，酷学园里的SAKANA曾用过，鸟哥觉得挺好看；
  • AbiWord(http://www.abisource.com/)：
    非常类似微软的Word的文书处理软体；
  • Tex/LaTeX(http://www.latex-project.org/)：
    可进行文件排版的软体(很多自由软体文件使用此编辑器喔！)；
  • Dia(http://dia-installer.de/index_en.html)：
    非常类似微软Visio的软体，可绘制流程图；
  • Scribus(http://www.scribus.net/)：
    专业的排版软体，老实说，鸟哥确实不会用～@_@；
  • GanttProject(http://ganttproject.biz/)：
    可绘制甘特图(就是时程表)的软体；
  • GIMP(http://www.gimp.org/)：
    在业界相当有名的绘图自由软体！

更多的可用软体，可以参考教育部自由软体谘询中心网页的介绍：

  • http://ossacc.moe.edu.tw/modules/tinyd1/index.php?id=21

如果你不需要很特别的专业软体的支援，那么一般的办公环境中，上面的这些软体通通免费！ 而且相信已经足以应付你日常所需的工作环境啦！不过，千万记得，玩X window就好，不要搞架站的东西！ 不论是Windows/Linux/Mac/Unix还是什么的，只要是玩到架站，他就不是这么安全的东西！ 所以，很多东西都需要学习啦！底下我们就来谈谈，如果有心想要朝Linux作业系统学习的话，最好可以具备什么心态呢？

大标题的图示 有心朝Linux作业系统学习者的学习态度

为什么大家老是建议学习Linux最好能够先舍弃X Window的环境呢？ 这是因为X window了不起也只是Linux内的‘一套软体’而不是‘Linux核心’。 此外，目前发展出来的X-Window对于系统的管理上还是有无法掌握的地方，举个例子来说，如果 Linux本身捉不到网路卡的时候，请问如何以X Window来捉这个硬体并且驱动他呢？

还有，如果需要以Tarball(原始码)的方式来安装软体并加以设定的时候，请以X Window 来架设他！这可能吗？当然可能，但是这是在考验‘X Window开发商’的技术能力， 对于了解Linux架构与核心并没有多大的帮助的！所以说，如果只是想要‘会使用Linux’的角度来看， 那么确实使用X Window也就足够了，反正搞不定的话，花钱请专家来搞定即可；但是如果想要更深入 Linux的话，那么指令列模式才是不二的学习方式！

以伺服器或者是嵌入式系统的应用来说，X Window是非必备的软体，因为伺服器是要提供用户端来连线的， 并不是要让使用者直接在这部伺服器前面按键盘或滑鼠来操作的！所以图形介面当然就不是这么重要了！ 更多的时候甚至大家会希望你不要启动X window在伺服器主机上，这是因为X Window通常会吃掉很多系统资源的缘故！

再举个例子来说，假如你是个软体服务的工程师，你的客户人在台北，而你人在远方的台南。某一天客户来电说他的Linux伺服器出了问题， 要你马上解决他，请问：要您亲自上台北去修理？还是他搬机器下来让你修理？或者是直接请他开个帐号给你进去设定即可？ 想当然尔，就会选择开帐号给你进入设定即可啰！因为这是最简单而且迅速的方法！这个方法通常使用文字介面会较为单纯， 使用图形介面则非常麻烦啦！所以啦！这时候就得要学学文字介面来操作Linux比较好啦！

另外，在伺服器的应用上，档案的安全性、人员帐号的管理、软体的安装/修改/设定、 登录档的分析以及自动化工作排程与程式的撰写等等，都是需要学习的， 而且这些东西都还未涉及伺服器软体呢！对吧！这些东西真的很重要，所以，建议你得要这样学习才好：

小标题的图示 从头学习Linux基础

其实，不论学什么系统，‘从头学起’是很重要的！还记得你刚刚接触微软的Windows都在干什么？ 还不就是由档案总管学起，然后慢慢的玩到控制台、玩到桌面管理， 然后还去学办公室软体，我想，你总该不会直接就跳过这一段学习的历程吧？那么 Linux的学习其实也差不多，就是要从头慢慢的学起啦！不能够还不会走路之前就想要学飞了吧！^_^！

常常有些朋友会写信来问鸟哥一些问题，不过，信件中大多数的问题都是很基础的！ 例如：‘为什么我的使用者个人网页显示我没有权限进入？’、 ‘为什么我下达一个指令的时候，系统告诉我找不到该指令？’、 ‘我要如何限制使用者的权限’等等的问题，这些问题其实都不是很难的，只要了解了 Linux的基础之后，应该就可以很轻易的解决掉这方面的问题呢！ 所以请耐心的，慢慢的，将后面的所有章节内容都看完。自然你就知道如何解决了！

此外，网路基础与安全也很重要，例如TCP/IP的基础知识，网路路由的相关概念等等。 很多的朋友一开始问的问题就是‘为什么我的邮件伺服器主机无法收到信件？’ 这种问题相当的困扰，因为发生的原因太多了，而朋友们常常一接触Linux就是希望 ‘架站！’根本没有想到要先了解一下Linux的基础！这是相当伤脑筋的！ 尤其近来电脑怪客(Cracker)相当多，(真奇怪，闲闲没事干的朋友还真是不少....) ，一个不小心您的主机就被当成怪客跳板了！ 甚至发生被警告的事件也层出不穷！这些都是没能好好的注意一下网路基础的原因呀！

所以，鸟哥希望大家能够更了解Linux，好让他可以为你做更多的事情喔！ 而且这些基础知识是学习更深入的技巧的必备条件呀！因此建议：

  1. 计算机概论与硬体相关知识：
    因为既然想要走Linux这门路，资讯相关的基础技能也不能没有啊！ 所以先理解一下基础的硬体知识，不用一定要全懂啦！又不是真的要你去组电脑～^_^， 但是至少要‘听过、有概念’即可；

  2. 先从Linux的安装与指令学起：
    没有Linux怎么学习Linux呢？所以好好的安装起一套你需要的Linux吧！虽然说Linux distributions很多， 不过基本上架构都是大同小异的，差别在于介面的亲和力与软体的选择不同罢了！ 选择一套你喜欢的就好了，倒是没有哪一套特别好说～

  3. Linux作业系统的基础技能：
    这些包含了‘使用者、群组的概念’、‘权限的观念’，‘程序的定义’等等，尤其是权限的概念， 由于不同的权限设定会妨碍你的使用者的便利性，但是太过于便利又会导致入侵的可能！ 所以这里需要了解一下你的系统呦！

  4. 务必学会vi文书编辑器：
    Linux的文书编辑器多到会让你数到生气！不过，vi却是强烈建议要先学习的！ 这是因为vi会被很多软体所呼叫，加上所有的Unix like系统上面都有vi，所以你一定要学会才好！

  5. Shell与Shell Script的学习：
    其实鸟哥上面一直谈到的‘文字介面’说穿了就是一个名为shell的软体啦！既然要玩文字介面，当然就是要会使用shell的意思。 但是shell上面的资料太多了，包括‘正规表示法’、‘管线命令’与‘资料流重导向’等等，真的需要了解比较好呦！ 此外，为了帮助你未来的管理伺服器的便利性，shell scripts也是挺重要的！要学要学！

  6. 一定要会软体管理员：
    因为玩Linux常常会面临得要自己安装驱动程式或者是安装额外软体的时候，尤其是嵌入式设备或者是学术研究单位等。 这个时候Tarball/RPM/DPKG等软体管理员的安装方式的了解，对你来说就重要到不行了！

  7. 网路基础的建立：
    如果上面你都通过了，那么网路的基础就是下一阶段要接触的咚咚，这部份包含了‘IP概念’‘路由概念’等等；

  8. 如果连网路基础都通过了，那么网站的架设对你来说，简直就是‘太简单啦！’

在一些基础知识上，可能的话，当然得去书店找书来读啊！ 如果您想要由网路上面阅读的话，那么这里推荐一下由Netman大哥主笔的Study-Area里面的基础文章，相当的实用！

  • 电脑基础 (http://www.study-area.org/compu/compu.htm)
  • 网路基础 (http://www.study-area.org/network/network.htm)
小标题的图示 选择一本易读的工具书

一本好的工具书是需要的，不论是未来作为查询之用，还是在正确的学习方法上。 可惜的是，目前坊间的书大多强调速成的Linux教育，或者是强调Linux的网路功能， 却欠缺了大部分的Linux基础管理～鸟哥在这里还是要再次的强调，Linux的学习历程并不容易， 他需要比较长的时间来适应、学习与熟悉，但是只要能够学会这些简单的技巧， 这些技巧却可以帮助您在各个不同的OS之间遨游！

您既然看到这里了，应该是已经取得了鸟哥的 Linux 私房菜 -- 基础学习篇了吧！ ^_^ 。 希望这本书可以帮助您缩短基础学习的历程，也希望能够带给您一个有效的学习观念！ 而在这本书看完之后，或许还可以参考一下Netman推荐的相关网路书籍：

  • 请推荐有关网路的书： http://linux.vbird.org/linux_basic/0120howtolinux/0120howtolinux_1.php

不过，要强调的是，每个人的阅读习惯都不太一样，所以，除了大家推荐的书籍之外， 您必须要亲眼看过该本书籍，确定您可以吸收的了书上的内容，再下去购买喔！

小标题的图示 实作再实作

要增加自己的体力，就是只有运动；要增加自己的知识，就只有读书；当然，要增加自己对于Linux的认识， 大概就只有实作经验了！所以，赶快找一部电脑，赶快安装一个Linux distribution，然后快点进入Linux的世界里面晃一晃！ 相信对于你自己的Linux能力必然大有斩获！除了自己的实作经验之外，也可以参考网路上一些善心人士整理的实作经验分享喔！ 例如最有名的Study-Area(http://www.study-area.org)等网站。

此外，人脑不像电脑的硬碟一样，除非硬碟坏掉了或者是资料被你抹掉了， 否则储存的资料将永远而且立刻的记忆在硬碟中！在人类记忆的曲线中， 你必须要‘不断的重复练习’才会将一件事情记得比较熟！同样的，学习Linux也一样， 如果你无法经常摸索的话，那么，抱歉的是，学了后面的， 前面的忘光光！学了等于没学，这也是为什么鸟哥当初要写‘鸟哥的私房菜’这个网站的主要原因， 因为，我的忘性似乎比一般人还要好～～呵呵！所以，除了要实作之外，还得要常摸！才会熟悉Linux而且不会怕他呢！

好了，底下列出几个学习网站来提供大家做为参考实作的依据：

  • Study-Area http://www.study-area.org
  • 鸟哥的私房菜馆 http://linux.vbird.org
  • 卧龙大师的网路技术文件 http://linux.tnc.edu.tw/techdoc/
  • 台湾 Linux 社群 http://www.linux.org.tw/
  • 狼主的网路实验室 http://netlab.kh.edu.tw/index.htm
  • 大南国小（林克敏主任文件集）http://freebsd.lab.mlc.edu.tw/
  • 吴仁智的文件集 http://www.cses.tcc.edu.tw/~chihwu/
Tips:
由于不同的网站当初撰写的时候所用的Linux软体或版本与目前的主流并不相同，因此参考他人的实作经验时， 必须要特别留意对方的版本，否则反而可能造成你的困扰喔！ 		鸟哥的图示
小标题的图示 发生问题怎么处理啊？建议流程是这样..

我们是‘人’不是‘神’，所以在学习的过程中发生问题是很常见的啦！重点是，我们该如何处理在自身所发生的Linux问题呢？ 在这里鸟哥的建议是这样的流程：

  1. 在自己的主机/网路资料库上查询How-To或FAQ

    其实，在Linux主机及网路上面已经有相当多的FAQ整理出来了！所以，当你发生任何问题的时候，除了自己检查， 或者到上述的实作网站上面查询一下是否有设定错误的问题之外，最重要的当然就是到各大FAQ的网站上查询啰！ 以下列出一些有用的FAQ与How-To网站给您参考一下：

    • Linux自己的文件资料： /usr/share/doc (在你的Linux系统中)
    • CLDP 中文文件计划 http://www.linux.org.tw/CLDP/
    • The Linux Documentation Project：http://www.tldp.org/

    上面比较有趣的是那个TLDP(The Linux Documentation Project)， 他几乎列出了所有Linux上面可以看到的文献资料，各种How-To的作法等等，虽然是英文的，不过，很有参考价值！

    除了这些基本的FAQ之外，其实，还有更重要的问题查询方法，那就是利用酷狗(Google)帮您去搜寻答案呢！ 在鸟哥学习Linux的过程中，如果有什么奇怪的问题发生时，第一个想到的， 就是去http://www.google.com.tw搜寻是否有相关的议题。 举例来说，我想要找出Linux底下的NAT，只要在上述的网站内，输入Linux跟NAT， 立刻就有一堆文献跑出来了！真的相当的优秀好用喔！您也可以透过酷狗来找鸟哥网站上的资料呢！

    • Google： http://www.google.com.tw
    • 鸟哥网站： http://linux.vbird.org/Searching.php

  2. 注意讯息输出，自行解决疑难杂症：

    一般而言，Linux在下达指令的过程当中，或者是log file里头就可以自己查得错误资讯了，举个例子来说，当你下达：
    [root@linux ~]# ls -l /vbird
    由于系统并没有 /vbird 这个目录，所以会在荧幕前面显示：
    ls: /vbird: No such file or directory
    这个错误讯息够明确了吧！系统很完整的告诉您‘查无该资料’！ 呵呵！所以啰，请注意，发生错误的时候，请先自行以荧幕前面的资讯来进行 debug(除错)的动作，然后，如果是网路服务的问题时，请到/var/log/这个目录里头去查阅一下 log file(登录档)，这样可以几乎解决大部分的问题了！

  3. 搜寻过后，注意网路礼节，讨论区大胆的发言吧：

    一般来说，如果发生错误现象，一定会有一些讯息对吧！那么当您要请教别人之前，就得要将这些讯息整理整理， 否则网路上人家也无法告诉您解决的方法啊！这一点很重要的喔！

    万一真的经过了自己的查询，却找不到相关的资讯，那么就发问吧！不过，在发问之前建议您最好先看一下‘ 提问的智慧 http://phorum.vbird.org/viewtopic.php?t=96’ 这一篇讨论！然后，你可以到底下几个讨论区发问看看：

    • 酷学园讨论区 http://phorum.study-area.org
    • 鸟哥的私房菜馆讨论区 http://phorum.vbird.org
    • telnet://bbs.sayya.org

    不过，基本上去每一个讨论区回答问题的熟手，其实都差不多是那几个， 所以，您的问题‘不要重复发表在各个主要的讨论区！’ 举例来说，鸟园与酷学园讨论区上的朋友重复性很高，如果您两边都发问， 可能会得到反效果，因为大家都觉得，另外一边已经回答您的问题了呢～～

  4. Netman大大给的建议：

    此外，Netman 兄提供的一些学习的基本方针，提供给大家参考：

    • 在Windows里面，程式有问题时，如果可能的话先将所有其它程式保存并结束，然后尝试按救命三键 (Ctrl+Alt+Delete)，将有问题的程式(不要选错了程式哦)‘结束工作’，看看能不能恢复系统。不要动不动就直接关机或reset。
    • 有系统地设计档案目录，不要随便到处保存档案以至以后不知道放哪里了， 或找到档案也不知道为何物。
    • 养成一个做记录的习惯。尤其是发现问题的时候， 把错误信息和引发状况以及解决方法记录清楚，同时最后归类及定期整理。别以为您还年轻，等你再弄多几年电脑了， 您将会非常庆幸您有此一习惯。
    • 如果看在网路上看到任何好文章，可以为自己留一份copy，同时定好题目，归类存档。(鸟哥注：需要注意智慧财产权！)
    • 作为一个使用者，人要迁就机器；做为一个开发者，要机器迁就人。
    • 学写 script 的确没设定 server 那么好玩，不过以我自己的感觉是：关键是会得‘偷’， 偷了会得改，改了会得变，变则通矣。
    • 在Windows里面，设定不好设备，您可以骂它；在Linux里面，如果设定好设备了，您得要感激它！
大标题的图示 鸟哥的建议(重点在Solution的学习)：

除了上面的学习建议之外，还有其他的建议吗？确实是有的！其实， 无论作什么事情，对人类而言，两个重要的因素是造成我们学习的原动力：

  • 成就感
  • 兴趣

很多人问过我，鸟哥是怎么学习Linux的？由上面鸟哥的悲惨Linux学习之路你会发现， 原来我本人对于电脑就蛮有兴趣的，加上工作的需要，而鸟哥又从中得到了相当多的成就感， 所以啰，就一发不可收拾的爱上Linux啰！因此，鸟哥个人认为，学习Linux如果玩不出兴趣， 他对你也不是什么重要的生财工具，那么就不要再玩下去了！ 因为很累人ㄋㄟ～而如果你真的想要玩这么一套优良的作业系统， 除了前面提到的一些建议之外，说真的，得要培养出兴趣与成就感才行！ 那么如何培养出兴趣与成就感呢？可能有几个方向可以提供给你参考：

  • 建立兴趣：
    Linux上面可以玩的东西真的太多了，你可以选择一个有趣的课题来深入的玩一玩！不论是Shell还是图形介面等等， 只要能够玩出兴趣，那么再怎么苦你都会不觉得喔！

  • 成就感：
    成就感是怎么来的？说实在话，就是‘被认同’来的！怎么被认同呢？写心得分享啊！当你写了心得分享，并且公告在 BBS 上面，自然有朋友会到你的网页去瞧一瞧，当大家觉得你的网页内容很棒的时候， 哈哈！你肯定会加油继续的分享下去而无法自拔的！那就是我啦...... ^_^！

    就鸟哥的经验来说，你‘学会一样东西’与 ‘要教人家会一样东西’思考的纹路是不太一样的！ 学会一样东西可能学一学会了就算了！但是要‘教会’别人，那可就不是闹着玩的！ 得要思考相当多的理论性与实务性方面的咚咚，这个时候，你所能学到的东西就更深入了！ 鸟哥常常说，我这个网站对我在Linux的了解上面真的的帮助很大！

  • 协助回答问题：
    另一个创造成就感与满足感的方法就是‘助人为快乐之本！’当你在 BBS 上面告诉一些新手，回答他们的问题，你可以获得的可能只是一句‘谢谢！感恩呐！’ 但是那句话真的会让人很有快乐的气氛！很多的老手都是因为有这样的满足感， 才会不断的协助新来的朋友的呢！此外，回答别人问题的时候，就如同上面的说明一般， 你会更深入的去了解每个项目，哈哈！又多学会了好多东西呢！

  • 参与讨论：
    参与大家的技术讨论一直是一件提升自己能力的快速道路！因为有这些技术讨论， 你提出了意见，不论讨论的结果你的意见是对是错，对你而言，都是一次次的知识成长！这很重要喔！ 目前台湾地区办活动的能力是数一数二的Linux社群‘酷学园(Study Area, SA)’，每个月不定期的在北/中/南举办自由软体相关活动， 有兴趣的朋友可以看看：
    http://phorum.study-area.org/index.php/board,22.0.html

此外，除了这些鸟哥的经验之外，还有在 BBS 上面有一封对于Linux新手相当有帮助的文件资料，大家可以多看一看：

  • 李果正先生之 GNU/Linux 初学者之旅： http://info.sayya.org/~edt1023/linux_entry.html
    鸟哥这里有也一个备份 http://linux.vbird.org/linux_basic/0120howtolinux/0120howtolinux_3.php
  • 资讯人的有效学习(洪朝贵教授网页) http://people.ofset.org/~ckhung/a/c013.php

除了这些基本的初学者建议外，其实，对于未来的学习，这里建议大家要‘眼光看远！’一般来说，公司行号会发生问题时， 他们绝不会只要求各位‘单独解决一部主机的问题’而已，他们需要的是整体环境的总体解决‘Total Solution’。 而我们目前学习的Linux其实仅是在一部主机上面进行各项设定而已， 还没有到达解决整体公司所有问题的状态。当然啦，得要先学会Linux相关技巧后， 才有办法将这些技巧用之于其他的solution上面！

所以，大家在学习Linux的时候，千万不要有‘门户之见’，认为MS的东西就比较不好～ 否则，未来在职场上，竞争力会比人家弱的！有办法的话，多接触，不排斥任何学习的机会！都会带给自己很多的成长！ 而且要谨记：‘不同的环境下，解决问题的方法有很多种，只要行的通，就是好方法！’

大标题的图示 重点回顾
  • Linux在企业应用方面，着重于‘网路伺服器’、‘关键任务的应用(金融资料库、大型企业网管环境)’及‘高效能运算’等任务；
  • Linux在个人环境的使用上，着重于：桌上型电脑、手持系统(PDA、手机)、嵌入式设备(如家电用品等)；
  • Linux distributions有针对桌面电脑所开发的，例如Ubuntu, OpenSuSE及Fedora等等，为学习X Window的好工具；
  • 有心朝Linux学习者，应该多接触文字介面(shell)的环境，包括正规表示法、管线命令与资料流重导向，最好都要学习！ 最好连shell script都要有能力自行撰写；
  • ‘实作’是学习Linux的最佳方案，空读书，遇到问题也不见得能够自己处理的！
  • 学习Linux时，建立兴趣、建立成就感是很重要的，另外，协助回答问题、参与社群活动也是增加热情的方式！
  • Linux文件计划的网站在：http://www.tldp.org
大标题的图示 本章习题
( 要看答案请将滑鼠移动到‘答：’底下的空白处，按下左键圈选空白处即可察看 )
实作题部分：
  • 我的 Linux 系统上面老是出现问题，他有一个错误讯息为‘fatal: SASL per-connection security setup’请帮我找出可能的原因为何？
    先跑到 http://www.google.com.tw 里面去，输入上列的错误讯息，就可以找到很多文件，根据文件去判断吧！
  • Windows的作业系统当中，老是自动出现一个名为internet optimizer的软体，我想要知道他是什么，可以怎么找？
    利用 http://www.google.com.tw 输入 inetnet optimizer 后， 就可以找到相关的资讯。基本上，这是一个木马程式啦！赶紧移除吧！
  • 想一想再回答，为何您想要学习Linux？有没有持续学习的动力？您想要Linux帮您达成什么样的工作目标？
问答题部分：
  • 我的Linux发生问题，我老是找不到正确的答案，想要去http://phorum.study-area.org提问，应该要先做哪些动作才发问？
    1. 先将您 Linux 上面的问题作一个清楚的描述，例如，做了什么动作，结果发生了什么讯息与结果。
    2. 先到 http://phorum.study-area.org 内的‘搜寻’查询有无相关的问题
    3. 再到 http://www.google.com.tw 查询一下有无相关的资讯
    4. 将您的问题描述写下，并且写下您的判断，以及查询过资料的结果。
    5. 等待回覆～
  • 你觉得学习Linux最重要的一环是什么？
    其实是自己的学习心态～最重要的地方在于能够‘刻苦耐劳～’ ^_^
  • 什么是TLDP？全名为何？网站在哪里？
    TLDP是 The Linux Documentation Project 的缩写，内容提到的是 Linux 作业系统的各个 How-To 以及相关的说明文件如 man page 等等。网站在 http://www.tldp.org 喔！
大标题的图示 参考资料与延伸阅读
  • 注1：例如甲骨文(Oracle)资料库系统公司就有支援Linux的版本出现。有兴趣的朋友可以参考底下数则新闻：
    http://www.openfoundry.org/index.php?option=com_content&Itemid=345&id=1501&lang=en&task=view
    http://www.zdnet.com.tw/news/software/0,2000085678,20064784,00.htm
    http://govforge.e-land.gov.tw/modules/news/article.php?storyid=84
    http://www.openfoundry.org/index.php?option=com_content&Itemid=336&id=1283&lang=en&task=view
    http://www.oc.com.tw/readvarticle.asp?id=9539
    http://searchenterpriselinux.techtarget.com/news/article/0,289142,sid39_gci1309650,00.html
  • 注2：维基百科对于 cluster 的解释：http://en.wikipedia.org/wiki/Cluster_%28computing%29
2002/07/08：第一次完成或者是上次更新...忘记了～ @_@
2003/01/28：重新修订，加入 X-Window 的简易说明
2005/06/03：将旧的资料移至 此处。同时更新网页资料！
2005/06/08：加入一些练习题～之前的写的不好～已经抽换掉了～
2008/07/26：将原本旧的FC4的版本移动到此处。
2008/07/28：将本章与‘新手建议’做个连结，加强Linux应用的说明！
2009/08/06：调整一些显示的方式，调整一下课后练习的部分，将题目分开处理。


鸟哥的 Linux 私房菜 -- 基础学习篇

为取得较佳浏览结果，请爱用 firefox 浏览本网页
鸟哥的 Linux 私房菜馆 | Linux 基础文件 | Linux 架站文件 | Linux 企业运用 | 安全管理 | 新手讨论 |

第三章、主机规划与磁碟分割
最近更新日期：2009/08/06
事实上，要安装好一部Linux主机并不是那么简单的事情，你必须要针对distributions的特性、伺服器软体的能力、 未来的升级需求、硬体扩充性需求等等来考量，还得要知道磁碟分割、档案系统、Linux操作较频繁的目录等等， 都得要有一定程度的了解才行，所以，安装Linux并不是那么简单的工作喔！ 不过，要学习Linux总得要有Linux系统存在吧？所以鸟哥在这里还是得要提前说明如何安装一部Linux练习机。 在这一章里面，鸟哥会介绍一下，在开始安装Linux之前，您应该要先思考哪些工作？ 好让您后续的主机维护轻松愉快啊！此外，要了解这个章节的重要性，您至少需要了解到Linux档案系统的基本概念， 所以，在您完成了后面的相关章节之后，记得要再回来这里看看如何规划主机喔！ ^_^

1. Linux与硬体的搭配
    1.1 认识电脑的硬体配备
1.2 选择与Linux搭配的主机配备： 硬体支援相关网站
1.3 各硬体装置在Linux中的档名
 2. 磁碟分割
    2.1 磁碟连接的方式与装置档名的关系
2.2 磁碟的组成复习
2.3 磁碟分割表(partition table)
2.4 开机流程与主要开机记录区(MBR)
2.5 Linux安装模式下，磁碟分割的选择(极重要)
 3. 安装Linux前的规划
    3.1 选择适当的distribution
3.2 主机的服务规划与硬体的关系
3.3 主机硬碟的主要规划(partition)
3.4 鸟哥说：关于练习机的安装建议
3.5 鸟哥的两个实际案例
3.6 大硬碟配合旧主机造成的无法开机问题
 4. 重点回顾
5. 本章习题
6. 参考资料与延伸阅读
7. 针对本文的建议：http://phorum.vbird.org/viewtopic.php?t=23874
大标题的图示 Linux与硬体的搭配

虽然个人电脑各元件的主要介面是大同小异的，包括前面第零章计算机概论讲到的种种介面等， 但是由于新的技术来得太快，Linux核心针对新硬体所纳入的驱动程式模组比不上硬体更新的速度， 加上硬体厂商针对Linux所推出的驱动程式较慢，因此你在选购新的个人电脑(或伺服器)时， 应该要选择已经过安装Linux测试的硬体比较好。

此外，在安装Linux之前，你最好了解一下你的Linux预计是想达成什么任务，这样在选购硬体时才会知道那个元件是最重要的。 举例来说，桌面电脑(Desktop)的使用者，应该会用到X Window系统， 此时，显示卡的优劣与记忆体的大小可就占有很重大的影响。如果是想要做成档案伺服器， 那么硬碟或者是其他的储存设备，应该就是您最想要增购的元件啰！所以说，功课还是需要作的啊！

鸟哥在这里要不厌其烦的再次的强调，Linux对于电脑各元件/装置的分辨， 与大家惯用的Windows系统完全不一样！因为，各个元件或装置在Linux底下都是‘一个档案！’ 这个观念我们在第一章Linux是什么里面已经提过， 这里我们再次的强调。因此，你在认识各项装置之后，学习Linux的装置档名之前， 务必要先将Windows对于装置名称的概念先拿掉～否则会很难理解喔！

小标题的图示 认识电脑的硬体配备

‘什么？学Linux还得要玩硬体？’呵呵！没错！ 这也是为什么鸟哥要将计算机概论搬上台面之故！ 我们这里主要是介绍较为普遍的个人电脑架构来设定Linux伺服器，因为比较便宜啦！ 至于各相关的硬体元件说明已经在第零章计概内讲过了，这里不再重复说明。 仅将重要的主机板与元件的相关性图示如下：

个人电脑各元件的相关性
图1.1.1、个人电脑各元件的相关性
(上述图示主要取自tom's硬体指南，各元件图片分属个别公司所有)

那么我们应该如何挑选电脑硬体呢？随便买买就好，还是有特殊的考量？底下有些思考角度可以提供给大家参考看看：

  • 游戏机/工作机的考量

事实上，电脑主机的硬体配备与这部主机未来的功能是很有相关性的！举例来说，家里有小孩， 或者自己仍然算是小孩的朋友大概都知道：‘要用来打Game的‘游戏机电脑’ 所需要的配备一定比办公室用的‘工作机电脑’配备更高档’，为什么呢？ 因为现在一般的三维(3D)电脑游戏所需要的3D光影运算太多了，所以显示卡与CPU资源都会被耗用的非常多！ 当然就需要比较高级的配备啰，尤其是在显示卡、CPU(例如Intel的Core 2 Duo及AMD的Athlon64 X2等)及主机板晶片组方面的功能。

至于办公室的工作环境中，最常使用到的软体大多是办公软体(Office)，最常使用的网路功能是浏览器， 这些软体所需要的运算并不高，理论上目前的入门级电脑都能够跑得非常顺畅了！(例如Intel Celeron及AMD的Sempron)。 甚至很多企业都喜欢购买将显示卡、主机板晶片组整合在一起的整合型晶片的电脑，因为便宜又好用！

  • 效能/价格比的考量

并不是‘贵就比较好’喔！在目前(2009)全球经济萧条的情况下，如何兼顾省钱与电脑硬体的效能问题，很重要！ 如果你喜欢购买最新最快的电脑零件，这些刚出炉的元件都非常的贵，而且作业系统还不见得能够完整的支援。 所以，鸟哥都比较喜欢购买主流级的产品而非最高档的。因为我们最好能够考虑到效能/价格比。 如果高一级的产品让你的花费多一倍，但是新增加的效能却只有10%而已，那这个效能/价格的比值太低，不建议啦！

此外，由于电价越来越高，如何‘省电’就很重要啦！因此目前硬体评论界有所谓的‘每瓦效能’的单位， 每瓦电力所发挥的效能越高，当然代表越省电啊！这也是购买硬体时的考量之一啦！要知道，如果是做为伺服器用， 一年365天中时时刻刻都开机，则你的电脑多花费50瓦的电力时，每年就得要多花450度电左右，如果以企业来讲， 每百部电脑每年多花450度电的话，每年得多花十万块以上的电费呢！所以这也需要考量啊！

  • 支援度的考量

并非所有的产品都会支援特定的作业系统，这牵涉到硬体开发商是否有意愿提供适当的驱动程式之故。 因此，当我们想要购买或者是升级某些电脑元件时，应该要特别注意该硬体是否有针对您的作业系统提供适当的驱动程式， 否则，买了无法使用，那才是叫人呕死啊！因此，针对Linux来说，底下的硬体分析就重要啦！

小标题的图示 选择与Linux搭配的主机配备

由于硬体的加速发展与作业系统核心功能的增强，导致较早期的电脑已经没有能力再负荷新的作业系统了。 举例来说，Pentun-II以前的硬体配备可能已经不再适合现在的新的Linux distribution。 而且较早期的硬体配备也可能由于保存的问题或者是电子零件老化的问题， 导致这样的电脑系统反而非常容易在运作过程中出现不明的当机情况，因此在利用旧零件拼凑Linux使用的电脑系统时， 真的得要特别留意呢！

不过由于Linux运作所需要的硬体配备实在不需要太高档，因此，如果有近期汰换下来的， 比Pentun-III 500还要新的硬体配备， 不必急着丢弃。由于P-III的硬体不算太老旧，在效能方面其实也算的上非常OK了～所以， 鸟哥建议您如果有P-III以后等级的电脑被淘汰，可以拿下来测试一下，说不定能够作为你日常生活的Linux伺服器， 或者是备用伺服器，都是非常好用的功能哩！

但是由于不同的任务的主机所需要的硬体配备并不相同，举例来说，如果你的Linux主机是要作为企业内部的Mail server或者是Proxy server时，或者是需要使用到图形介面的运算(X Window内的Open GL等等功能)， 那么你就必须要选择高档一点的电脑配备了，使用过去的电脑零件可能并不适合呢。

底下我们稍微谈一下，如果你的Linux主要是作为小型伺服器使用，并不负责学术方面的大量运算， 而且也没有使用X Window的图形介面，那你的硬体需求只要像底下这样就差不多了：

  • CPU
    CPU只要不是老旧到会让你的硬体系统当机的都能够支援！如同前面谈到的，目前(2009)的环境中， Pentun-III的CPU不算太旧而且效能也不错，也就是说P-III就非常好用了。

  • RAM
    主记忆体是越大越好！事实上在Linux伺服器中，主记忆体的重要性比CPU还要高的多！因为如果主记忆体不够大， 就会使用到硬碟的记忆体置换空间(swap)。 而由计算机概论的内容我们知道硬碟比记忆体的速度要慢的多， 所以主记忆体太小可能会影响到整体系统的效能的！尤其如果你还想要玩X window的话，那主记忆体的容量就不能少。 对于一般的小型伺服器来说，建议至少也要512MB以上的主记忆体容量较佳。

  • Hard Disk
    由于资料量与资料存取频率的不同，对于硬碟的要求也不相同。 举例来说，如果是一般小型伺服器，通常重点在于容量，硬碟容量大于20GB就够用到不行了！ 但如果你的伺服器是作为备份或者是小企业的档案伺服器，那么你可能就得要考量较高阶的磁碟阵列(RAID)模式了。
    Tips:
    磁碟阵列(RAID)是利用硬体技术将数个硬碟整合成为一个大硬碟的方法，作业系统只会看到最后被整合起来的大硬碟。 由于磁碟阵列是由多个硬碟组成，所以可以达成速度效能、备份等任务。更多相关的磁碟阵列我们会在第十五章中介绍的。     		鸟哥的图示
  • VGA
    对于不需要X Window的伺服器来说，显示卡算是最不重要的一个元件了！你只要有显示卡能够让电脑启动，那就够了。 但如果需要X window系统时，你的显示卡最好能够拥有32MB以上的记忆体容量，否则跑X系统会很累喔！ 鸟哥曾使用一块只有2MB记忆体的显示卡跑X，光是按一个按钮就花费数分钟时间，真是折磨人家的耐心啊！

  • Network Interface Card
    网路卡是伺服器上面最重要的元件了！目前新式的主机板大多拥有10/100/1000Mbps的高速网路，不过，老实说， 只要好一点的10/100网路卡就非常够用了！毕竟我们的频宽并没有大到Gigabit的速度！如果是小型伺服器， 一块Realtek RTL8139晶片的网卡就非常好用了，不过，如果是读取非常频繁的网站， 好一点的Intel/3Com网卡应该是比较适合的喔。

  • 光碟、软碟、键盘与滑鼠
    不要旧到你的电脑不支援就好了，因为这些配备都是非必备的喔！举例来说，鸟哥安装好Linux系统后， 可能就将该系统的光碟机、滑鼠、软碟机等通通拔除，只有网路线连接在电脑后面而已，其他的都是透过网路连线来管控的哩！ 因为通常伺服器这东西最需要的就是稳定，而稳定的最理想状态就是平时没事不要去动他是最好的。

底下鸟哥针对一般你可能会接触到的电脑主机的用途与相关硬体配备的基本要求来说明一下好了：

  • 一般小型主机且不含X Window系统：
    • 用途：家庭用NAT主机(IP分享器功能)或小型企业之非图形介面小型主机。
    • CPU：大于P-III 500以上等级即可。
    • RAM：至少128MB，不过还是大于256MB以上比较妥当！
    • 网路卡：一般的10/100 Mbps即可应付。
    • 显示卡：只要能够被Linux捉到的显示卡即可，例如NVidia或ATI的主流显示卡均可。
    • 硬碟：20GB以上即可！

  • 桌上型(Desktop)Linux系统/含X Window：
    • 用途：Linux的练习机或办公室(Office)工作机。(一般我们会用到的环境)
    • CPU：最好等级高一点，例如P-4以上等级。
    • RAM：一定要大于512MB比较好！否则容易有图形介面停顿的现象。
    • 网路卡：普通的10/100 Mbps就好了！
    • 显示卡：使用32MB以上记忆体的显示卡！
    • 硬碟：越大越好，最好有60GB。

  • 中型以上Linux伺服器：
    • 用途：中小型企业/学校单位的FTP/mail/WWW等网路服务主机。
    • CPU：最好等级高一点，可以考虑使用双核心系统。
    • RAM：最好能够大于1GB以上，大于4GB更好！
    • 网路卡：知名的3Com或Intel等厂牌，比较稳定效能较佳！也可选购10/100/1000 Mbps的速度。
    • 显示卡：如果有使用到图形功能，则一张64MB记忆体的显示卡是需要的！
    • 硬碟：越大越好，如果可能的话，使用磁碟阵列，或者网路硬碟等等的系统架构， 能够具有更稳定安全的传输环境，更佳！
    • 建议企业用电脑不要自行组装，可购买商用伺服器较佳， 因为商用伺服器已经通过制造商的散热、稳定度等测试，对于企业来说，会是一个比较好的选择。

总之，鸟哥在这里仅是提出一个方向：如果你的Linux主机是小型环境使用的，即时当机也不太会影响到企业环境的运作时， 那么使用升级后被淘汰下来的零件以组成电脑系统来运作，那是非常好的回收再利用的案例。 但如果你的主机系统是非常重要的，你想要更一部更稳定的Linux伺服器，那考虑系统的整体搭配与运作效能的考量， 购买已组装测试过的商用伺服器会是一个比较好的选择喔！

Tips:
一般来说，目前(2009)的入门电脑机种，CPU至少都是Intel Core的2GHz系列的等级以上， 主记忆体至少有1GB，显示卡记忆体也有128MB以上，所以如果您是新购置的电脑， 那么该电脑用来作为Linux的练习机，而且加装X Window系统，肯定是可以跑的吓吓叫的啦！^_^ 		鸟哥的图示

此外，Linux开发商在释出Linux distribution之前，都会针对该版所预设可以支援的硬体做说明， 因此，你除了可以在Linux的Howto文件去查询硬体的支援度之外，也可以到各个相关的Linux distributions网站去查询呢！ 底下鸟哥列出几个常用的硬体与Linux distributions搭配的网站，建议大家想要了解你的主机支不支援该版Linux时， 务必到相关的网站去搜寻一下喔！

  • Red Hat的硬体支援：https://hardware.redhat.com/?pagename=hcl
  • Open SuSE的硬体支援：http://en.opensuse.org/Hardware?LANG=en_UK
  • Mandriva的硬体支援：http://hcl.mandriva.com/
  • Linux对笔记型电脑的支援：http://www.linux-laptop.net/
  • Linux对印表机的支援：http://www.openprinting.org/
  • 显示卡对XFree86/Xorg的支援：http://www.linuxhardware.org/
  • Linux硬体支援的中文HowTo：http://www.linux.org.tw/CLDP/HOWTO/hardware.html#hardware

总之，如果是自己维护的一个小网站，考虑到经济因素，你可以自行组装一部主机来架设。 而如果是中、大型企业，那么主机的钱不要省～因为，省了这些钱，未来主机挂点时， 光是要找出哪个元件出问题，或者是系统过热的问题，会气死人ㄟ！ 而且，要注意的就是未来你的Linux主机规划的‘用途’来决定你的Linux主机硬体配备喔！相当的重要呢！

小标题的图示 各硬体装置在Linux中的档名

选择好你所需要的硬体配备后，接下来得要了解一下各硬体在Linux当中所扮演的角色啰。 这里鸟哥再次的强调一下：‘在Linux系统中，每个装置都被当成一个档案来对待’ 举例来说，IDE介面的硬碟的档案名称即为/dev/hd[a-d]，其中， 括号内的字母为a-d当中的任意一个，亦即有/dev/hda, /dev/hdb, /dev/hdc, 及 /dev/hdd这四个档案的意思。

Tips:
这种中括号[]型式的表示法在后面的章节当中会使用得很频繁，请特别留意

另外先提出来强调一下，在Linux这个系统当中，几乎所有的硬体装置档案都在/dev这个目录内， 所以你会看到/dev/hda, /dev/fd0等等的档名喔。 		鸟哥的图示

那么印表机与软碟呢？分别是/dev/lp0, /dev/fd0啰！好了，其他的周边设备呢？ 底下列出几个常见的装置与其在Linux当中的档名啰：

装置 | 装置在Linux内的档名
IDE硬碟机 | /dev/hd[a-d]
SCSI/SATA/USB硬碟机 | /dev/sd[a-p]
USB快闪碟 | /dev/sd[a-p](与SATA相同)
软碟机 | /dev/fd[0-1]
印表机 | 25针: /dev/lp[0-2] USB: /dev/usb/lp[0-15]
滑鼠 | USB: /dev/usb/mouse[0-15] PS2: /dev/psaux
当前CDROM/DVDROM | /dev/cdrom
当前的滑鼠 | /dev/mouse
磁带机 | IDE: /dev/ht0 SCSI: /dev/st0

需要特别留意的是硬碟机(不论是IDE/SCSI/USB都一样)，每个磁碟机的磁碟分割(partition)不同时， 其磁碟档名还会改变呢！下一小节我们会介绍磁碟分割的相关概念啦！需要特别注意的是磁带机的档名， 在某些不同的distribution当中可能会发现不一样的档名，需要稍微留意。 总之，你得先背一下IDE与SATA硬碟的档名就是了！其他的，用的到再来背吧！

Tips:
更多Linux核心支援的硬体装置与档名，可以参考如下网页：
http://www.kernel.org/pub/linux/docs/device-list/devices.txt 		鸟哥的图示
大标题的图示 磁碟分割

这一章在规划的重点是为了要安装Linux，那Linux系统是安装在电脑元件的那个部分呢？就是磁碟啦！所以我们当然要来认识一下磁碟先。 我们知道一块磁碟是可以被分割成多个分割槽的(partition)，以旧有的Windows观点来看，你可能会有一颗磁碟并且将他分割成为C:, D:, E:槽对吧！那个C, D, E就是分割槽(partition)啰。但是Linux的装置都是以档案的型态存在，那分割槽的档名又是什么？ 如何进行磁碟分割，磁碟分割有哪些限制？是我们这个小节所要探讨的内容啰。

小标题的图示 磁碟连接的方式与装置档名的关系

由第零章提到的磁碟说明，我们知道个人电脑常见的磁碟介面有两种， 分别是IDE与SATA介面，目前(2009)的主流已经是SATA介面了，但是老一点的主机其实大部分还是使用IDE介面。 我们称呼可连接到IDE介面的装置为IDE装置，不管是磁碟还是光碟设备。

以IDE介面来说，由于一个IDE排线可以连接两个IDE装置，又通常主机都会提供两个IDE介面，因此最多可以接到四个IDE装置。 也就是说，如果你已经有一个光碟设备了，那么最多就只能再接三颗IDE介面的磁碟啰。 这两个IDE介面通常被称为IDE1(primary)及IDE2(secondary)， 而每条排线上面的IDE装置可以被区分为Master与Slave。这四个IDE装置的档名为：

IDE\Jumper | Master | Slave
IDE1(Primary) | /dev/hda | /dev/hdb
IDE2(Secondary) | /dev/hdc | /dev/hdd

例题：
假设你的主机仅有一颗IDE介面的磁碟，而这一颗磁碟接在IDE2的Master上面，请问他在Linux作业系统里面的装置档名为何？
答：
比较上表的装置档名对照，IDE2的Master之装置档名为/dev/hdc

再以SATA介面来说，由于SATA/USB/SCSI等磁碟介面都是使用SCSI模组来驱动的， 因此这些介面的磁碟装置档名都是/dev/sd[a-p]的格式。 但是与IDE介面不同的是，SATA/USB介面的磁碟根本就没有一定的顺序，那如何决定他的装置档名呢？ 这个时候就得要根据Linux核心侦测到磁碟的顺序了！这里以底下的例子来让你了解啰。

例题：
如果你的PC上面有两个SATA磁碟以及一个USB磁碟，而主机板上面有六个SATA的插槽。这两个SATA磁碟分别安插在主机板上的SATA1, SATA5插槽上， 请问这三个磁碟在Linux中的装置档名为何？
答：
由于是使用侦测到的顺序来决定装置档名，并非与实际插槽代号有关，因此装置的档名如下：
  1. SATA1插槽上的档名：/dev/sda
  2. SATA5插槽上的档名：/dev/sdb
  3. USB磁碟(开机完成后才被系统捉到)：/dev/sdc

通过上面的介绍后，你应该知道了在Linux系统下的各种不同介面的磁碟的装置档名了。 OK！好像没问题了呦！才不是呢～问题很大呦！ 因为如果你的磁碟被分割成两个分割槽，那么每个分割槽的装置档名又是什么？在了解这个问题之前，我们先来复习一下磁碟的组成， 因为现今磁碟的分割与他物理的组成很有关系！

小标题的图示 磁碟的组成复习

我们在计算机概论谈过磁碟的组成主要有磁碟盘、机械手臂、磁碟读取头与主轴马达所组成， 而资料的写入其实是在磁碟盘上面。磁碟盘上面又可细分出磁区(Sector)与磁柱(Cylinder)两种单位， 其中磁区每个为512bytes那么大。假设磁碟只有一个磁碟盘，那么磁碟盘有点像底下这样：

磁碟盘组成示意图
图2.2.1、磁碟盘组成示意图

那么是否每个磁区都一样重要呢？其实整颗磁碟的第一个磁区特别的重要，因为他记录了整颗磁碟的重要资讯！ 磁碟的第一个磁区主要记录了两个重要的资讯，分别是：

  • 主要开机记录区(Master Boot Record, MBR)：可以安装开机管理程式的地方，有446 bytes
  • 分割表(partition table)：记录整颗硬碟分割的状态，有64 bytes

MBR是很重要的，因为当系统在开机的时候会主动去读取这个区块的内容，这样系统才会知道你的程式放在哪里且该如何进行开机。 如果你要安装多重开机的系统，MBR这个区块的管理就非常非常的重要了！ ^_^

那么分割表又是啥？其实你刚刚拿到的整颗硬碟就像一根原木，你必须要在这根原木上面切割出你想要的区段， 这个区段才能够再制作成为你想要的家具！如果没有进行切割，那么原木就不能被有效的使用。 同样的道理，你必须要针对你的硬碟进行分割，这样硬碟才可以被你使用的！

Tips:
更多的磁碟分割与档案系统管理，我们将在第二篇的时候深入介绍喔！ 		鸟哥的图示
小标题的图示 磁碟分割表(partition table)

但是硬碟总不能真的拿锯子来切切割割吧？那硬碟还真的是会坏掉去！那怎办？在前一小节的图示中， 我们有看到‘开始与结束磁柱’吧？那是档案系统的最小单位，也就是分割槽的最小单位啦！没有错， 我们就是利用参考对照磁柱号码的方式来处理啦！ 在分割表所在的64 bytes容量中，总共分为四组记录区，每组记录区记录了该区段的启始与结束的磁柱号码。 若将硬碟以长条形来看，然后将磁柱以直条图来看，那么那64 bytes的记录区段有点像底下的图示：

磁碟分割表的作用示意图
图2.3.1、磁碟分割表的作用示意图

假设上面的硬碟装置档名为/dev/hda时，那么这四个分割槽在Linux系统中的装置档名如下所示， 重点在于档名后面会再接一个数字，这个数字与该分割槽所在的位置有关喔！

  • P1:/dev/hda1
  • P2:/dev/hda2
  • P3:/dev/hda3
  • P4:/dev/hda4

上图中我们假设硬碟只有400个磁柱，共分割成为四个分割槽，第四个分割槽所在为第301到400号磁柱的范围。 当你的作业系统为Windows时，那么第一到第四个分割槽的代号应该就是C, D, E, F。当你有资料要写入F槽时， 你的资料会被写入这颗磁碟的301~400号磁柱之间的意思。

由于分割表就只有64 bytes而已，最多只能容纳四笔分割的记录， 这四个分割的记录被称为主要(Primary)或延伸(Extended)分割槽。 根据上面的图示与说明，我们可以得到几个重点资讯：

  • 其实所谓的‘分割’只是针对那个64 bytes的分割表进行设定而已！
  • 硬碟预设的分割表仅能写入四组分割资讯
  • 这四组分割资讯我们称为主要(Primary)或延伸(Extended)分割槽
  • 分割槽的最小单位为磁柱(cylinder)
  • 当系统要写入磁碟时，一定会参考磁碟分割表，才能针对某个分割槽进行资料的处理

咦！你会不会突然想到，为啥要分割啊？基本上你可以这样思考分割的角度：

  1. 资料的安全性：
    因为每个分割槽的资料是分开的！所以，当你需要将某个分割槽的资料重整时，例如你要将电脑中Windows的C槽重新安装一次系统时， 可以将其他重要资料移动到其他分割槽，例如将邮件、桌面资料移动到D槽去，那么C槽重灌系统并不会影响到D槽！ 所以善用分割槽，可以让你的资料更安全。

  2. 系统的效能考量：
    由于分割槽将资料集中在某个磁柱的区段，例如上图当中第一个分割槽位于磁柱号码1~100号，如此一来当有资料要读取自该分割槽时， 磁碟只会搜寻前面1~100的磁柱范围，由于资料集中了，将有助于资料读取的速度与效能！所以说，分割是很重要的！

既然分割表只有记录四组资料的空间，那么是否代表我一颗硬碟最多只能分割出四个分割槽？当然不是啦！有经验的朋友都知道， 你可以将一颗硬碟分割成十个以上的分割槽的！那又是如何达到的呢？在Windows/Linux系统中， 我们是透过刚刚谈到的延伸分割(Extended)的方式来处理的啦！延伸分割的想法是： 既然第一个磁区所在的分割表只能记录四笔资料， 那我可否利用额外的磁区来记录更多的分割资讯？实际上图示有点像底下这样：

磁碟分割表的作用示意图
图2.3.2、磁碟分割表的作用示意图

在上图当中，我们知道硬碟的四个分割记录区仅使用到两个，P1为主要分割，而P2则为延伸分割。请注意， 延伸分割的目的是使用额外的磁区来记录分割资讯，延伸分割本身并不能被拿来格式化。 然后我们可以透过延伸分割所指向的那个区块继续作分割的记录。

如上图右下方那个区块有继续分割出五个分割槽， 这五个由延伸分割继续切出来的分割槽，就被称为逻辑分割槽(logical partition)。 同时注意一下，由于逻辑分割槽是由延伸分割继续分割出来的，所以他可以使用的磁柱范围就是延伸分割所设定的范围喔！ 也就是图中的101~400啦！

同样的，上述的分割槽在Linux系统中的装置档名分别如下：

  • P1:/dev/hda1
  • P2:/dev/hda2
  • L1:/dev/hda5
  • L2:/dev/hda6
  • L3:/dev/hda7
  • L4:/dev/hda8
  • L5:/dev/hda9

仔细看看，怎么装置档名没有/dev/hda3与/dev/hda4呢？因为前面四个号码都是保留给Primary或Extended用的嘛！ 所以逻辑分割槽的装置名称号码就由5号开始了！这是个很重要的特性，不能忘记喔！

主要分割、延伸分割与逻辑分割的特性我们作个简单的定义啰：

  • 主要分割与延伸分割最多可以有四笔(硬碟的限制)
  • 延伸分割最多只能有一个(作业系统的限制)
  • 逻辑分割是由延伸分割持续切割出来的分割槽；
  • 能够被格式化后，作为资料存取的分割槽为主要分割与逻辑分割。延伸分割无法格式化；
  • 逻辑分割的数量依作业系统而不同，在Linux系统中，IDE硬碟最多有59个逻辑分割(5号到63号)， SATA硬碟则有11个逻辑分割(5号到15号)。

事实上，分割是个很麻烦的东西，因为他是以磁柱为单位的‘连续’磁碟空间， 且延伸分割又是个类似独立的磁碟空间，所以在分割的时候得要特别注意。我们举底下的例子来解释一下好了：

例题：
在Windows作业系统当中，如果你想要将D与E槽整合成为一个新的分割槽，而如果有两种分割的情况如下图所示， 图中的特殊颜色区块为D与E槽的示意，请问这两种方式是否均可将D与E整合成为一个新的分割槽？
磁碟空间整合示意图
图2.3.3、磁碟空间整合示意图
答：
  • 上图可以整合：因为上图的D与E同属于延伸分割内的逻辑分割，因此只要将两个分割槽删除，然后再重新建立一个新的分割槽， 就能够在不影响其他分割槽的情况下，将两个分割槽的容量整合成为一个。

  • 下图不可整合：因为D与E分属主分割与逻辑分割，两者不能够整合在一起。除非将延伸分割破坏掉后再重新分割。 但如此一来会影响到所有的逻辑分割槽，要注意的是：如果延伸分割被破坏，所有逻辑分割将会被删除。 因为逻辑分割的资讯都记录在延伸分割里面嘛！

由于第一个磁区所记录的分割表与MBR是这么的重要，几乎只要读取硬碟都会先由这个磁区先读起。 因此，如果整颗硬碟的第一个磁区(就是MBR与partition table所在的磁区)物理实体坏掉了，那这个硬碟大概就没有用了！ 因为系统如果找不到分割表，怎么知道如何读取磁柱区间呢？您说是吧！底下还有一些例题您可以思考看看：

例题：
如果我想将一颗大硬碟‘暂时’分割成为四个partitions，同时还有其他的剩余容量可以让我在未来的时候进行规划， 我能不能分割出四个Primary？若不行，那么你建议该如何分割？
答：
  • 由于Primary+Extended最多只能有四个，其中Extended最多只能有一个，这个例题想要分割出四个分割槽且还要预留剩余容量， 因此P+P+P+P的分割方式是不适合的。因为如果使用到四个P，则即使硬碟还有剩余容量， 因为无法再继续分割，所以剩余容量就被浪费掉了。

  • 假设你想要将所有的四笔记录都花光，那么P+P+P+E是比较适合的。所以可以用的四个partitions有3个主要及一个逻辑分割， 剩余的容量在延伸分割中。

  • 如果你要分割超过4槽以上时，一定要有Extended分割槽，而且必须将所有剩下的空间都分配给Extended， 然后再以logical的分割来规划Extended的空间。 另外，考虑到磁碟的连续性，一般建议将Extended的磁柱号码分配在最后面的磁柱内。

例题：
我能不能仅分割出一个Primary与一个Extended即可？
答：
当然可以，这也是早期Windows作业系统惯用的手法！此外，逻辑分割槽的号码在IDE可达63号，SATA则可达15号， 因此仅一个主要与一个延伸分割即可，因为延伸分割可继续被分割出逻辑分割槽嘛！

例题：
假如我的PC有两颗SATA硬碟，我想在第二颗硬碟分割出6个可用的分割槽(可以被格式化来存取资料之用)， 那每个分割槽在Linux系统下的装置档名为何？且分割类型各为何？至少写出两种不同的分割方式。
答：
由于P(primary)+E(extended)最多只能有四个，其中E最多只能有一个。现在题目要求6个可用的分割槽，因此不可能分出四个P。 底下我们假设两种环境，一种是将前四号全部用完，一种是仅花费一个P及一个E的情况：
  • P+P+P+E的环境：
    分割示意图
    图2.3.4、分割示意图

    实际可用的是/dev/sdb1, /dev/sdb2, /dev/sdb3, /dev/sdb5, /dev/sdb6, /dev/sdb7这六个，至于/dev/sdb4这个延伸分割本身仅是提供来给逻辑分割槽建立之用。

  • P+E的环境：
    分割示意图
    图2.3.5、分割示意图

    注意到了吗？因为1~4号是保留给主要/延伸分割槽的，因此第一个逻辑分割槽一定是由5号开始的！再次强调啊！ 所以/dev/sdb3, /dev/sdb4就会被保留下来没有用到了！

小标题的图示 开机流程与主要开机记录区(MBR)

我们在计算机概论里面谈到了，没有执行软体的硬体是没有用的，除了会电人之外...， 而为了电脑硬体系统的资源合理分配，因此有了作业系统这个系统软体的产生。由于作业系统会控制所有的硬体并且提供核心功能， 因此我们的电脑就能够认识硬碟内的档案系统，并且进一步的读取硬碟内的软体档案与执行该软体来达成各项软体的执行目的。

问题是，你有没有发现，既然作业系统也是软体，那么我的电脑又是如何认识这个作业系统软体并且执行他的？ 明明开机时我的电脑还没有任何软体系统，那他要如何读取硬碟内的作业系统档案啊？嘿嘿！这就得要牵涉到电脑的开机程序了！ 底下就让我们来谈一谈这个开机程序吧！

在计算机概论里面我们有谈到那个可爱的BIOS与CMOS两个东西， CMOS是记录各项硬体参数且嵌入在主机板上面的储存器，BIOS则是一个写入到主机板上的一个韧体(再次说明， 韧体就是写入到硬体上的一个软体程式)。这个BIOS就是在开机的时候，电脑系统会主动执行的第一个程式了！

接下来BIOS会去分析电脑里面有哪些储存设备，我们以硬碟为例，BIOS会依据使用者的设定去取得能够开机的硬碟， 并且到该硬碟里面去读取第一个磁区的MBR位置。 MBR这个仅有446 bytes的硬碟容量里面会放置最基本的开机管理程式， 此时BIOS就功成圆满，而接下来就是MBR内的开机管理程式的工作了。

这个开机管理程式的目的是在载入(load)核心档案， 由于开机管理程式是作业系统在安装的时候所提供的，所以他会认识硬碟内的档案系统格式，因此就能够读取核心档案， 然后接下来就是核心档案的工作，开机管理程式也功成圆满，之后就是大家所知道的作业系统的任务啦！

简单的说，整个开机流程到作业系统之前的动作应该是这样的：

  1. BIOS：开机主动执行的韧体，会认识第一个可开机的装置；
  2. MBR：第一个可开机装置的第一个磁区内的主要开机记录区块，内含开机管理程式；
  3. 开机管理程式(boot loader)：一支可读取核心档案来执行的软体；
  4. 核心档案：开始作业系统的功能...

由上面的说明我们会知道，BIOS与MBR都是硬体本身会支援的功能，至于Boot loader则是作业系统安装在MBR上面的一套软体了。由于MBR仅有446 bytes而已，因此这个开机管理程式是非常小而美的。 这个boot loader的主要任务有底下这些项目：

  • 提供选单：使用者可以选择不同的开机项目，这也是多重开机的重要功能！
  • 载入核心档案：直接指向可开机的程式区段来开始作业系统；
  • 转交其他loader：将开机管理功能转交给其他loader负责。

上面前两点还容易理解，但是第三点很有趣喔！那表示你的电脑系统里面可能具有两个以上的开机管理程式呢！ 有可能吗？我们的硬碟不是只有一个MBR而已？是没错啦！但是开机管理程式除了可以安装在MBR之外， 还可以安装在每个分割槽的开机磁区(boot sector)喔！瞎密？分割槽还有各别的开机磁区喔？ 没错啊！这个特色才能造就‘多重开机’的功能啊！

我们举一个例子来说，假设你的个人电脑只有一个硬碟，里面切成四个分割槽，其中第一、二分割槽分别安装了Windows及Linux， 你要如何在开机的时候选择用Windows还是Linux开机呢？假设MBR内安装的是可同时认识Windows/Linux作业系统的开机管理程式， 那么整个流程可以图示如下：

开机管理程式的工作执行示意图
图2.4.1、开机管理程式的工作执行示意图

在上图中我们可以发现，MBR的开机管理程式提供两个选单，选单一(M1)可以直接载入Windows的核心档案来开机； 选单二(M2)则是将开机管理工作交给第二个分割槽的开机磁区(boot sector)。当使用者在开机的时候选择选单二时， 那么整个开机管理工作就会交给第二分割槽的开机管理程式了。 当第二个开机管理程式启动后，该开机管理程式内(上图中)仅有一个开机选单，因此就能够使用Linux的核心档案来开机啰。 这就是多重开机的工作情况啦！我们将上图作个总结：

  • 每个分割槽都拥有自己的开机磁区(boot sector)
  • 图中的系统槽为第一及第二分割槽，
  • 实际可开机的核心档案是放置到各分割槽内的！
  • loader只会认识自己的系统槽内的可开机核心档案，以及其他loader而已；
  • loader可直接指向或者是间接将管理权转交给另一个管理程式。

那现在请你想一想，为什么人家常常说：‘如果要安装多重开机， 最好先安装Windows再安装Linux’呢？这是因为：

  • Linux在安装的时候，你可以选择将开机管理程式安装在MBR或各别分割槽的开机磁区， 而且Linux的loader可以手动设定选单(就是上图的M1, M2...)，所以你可以在Linux的boot loader里面加入Windows开机的选项；

  • Windows在安装的时候，他的安装程式会主动的覆盖掉MBR以及自己所在分割槽的开机磁区，你没有选择的机会， 而且他没有让我们自己选择选单的功能。

因此，如果先安装Linux再安装Windows的话，那MBR的开机管理程式就只会有Windows的项目，而不会有Linux的项目 (因为原本在MBR内的Linux的开机管理程式就会被覆盖掉)。 那需要重新安装Linux一次吗？当然不需要，你只要用尽各种方法来处理MBR的内容即可。 例如利用全中文的spfdisk(http://spfdisk.sourceforge.net/)软体来安装认识Windows/Linux的管理程式， 也能够利用Linux的救援模式来挽救MBR即可。

Tips:
开机管理程式与Boot sector的观念是非常重要的，我们会在第二十章分别介绍，您在这里只要先对于(1)开机需要开机管理程式， 而(2)开机管理程式可以安装在MBR及Boot Sector两处这两个观念有基本的认识即可， 一开始就背太多东西会很混乱啦！ 		鸟哥的图示
小标题的图示 Linux安装模式下， 磁碟分割的选择(极重要)
  • 目录树结构(directory tree)

我们前面有谈过Linux内的所有资料都是以档案的形态来呈现的，所以啰，整个Linux系统最重要的地方就是在于目录树架构。 所谓的目录树架构(directory tree)就是以根目录为主，然后向下呈现分支状的目录结构的一种档案架构。 所以，整个目录树架构最重要的就是那个根目录(root directory)，这个根目录的表示方法为一条斜线‘/’， 所有的档案都与目录树有关。目录树的呈现方式如下图所示：

目录树相关性示意图
图2.5.1、目录树相关性示意图

如上图所示，所有的档案都是由根目录(/)衍生来的，而次目录之下还能够有其他的资料存在。上图中长方形为目录， 波浪形则为档案。那当我们想要取得mydata那个档案时，系统就得由根目录开始找，然后找到home接下来找到dmtsai， 最终的档名为：/home/dmtsai/mydata的意思。

我们现在知道整个Linux系统使用的是目录树架构，但是我们的档案资料其实是放置在磁碟分割槽当中的， 现在的问题是‘如何结合目录树的架构与磁碟内的资料’呢？ 这个时候就牵扯到‘挂载(mount)’的问题啦！

  • 档案系统与目录树的关系(挂载)

所谓的‘挂载’就是利用一个目录当成进入点，将磁碟分割槽的资料放置在该目录下； 也就是说，进入该目录就可以读取该分割槽的意思。这个动作我们称为‘挂载’，那个进入点的目录我们称为‘挂载点’。 由于整个Linux系统最重要的是根目录，因此根目录一定需要挂载到某个分割槽的。 至于其他的目录则可依使用者自己的需求来给予挂载到不同的分割槽。我们以下图来作为一个说明：

目录树与分割槽之间的相关性
图2.5.2、目录树与分割槽之间的相关性

上图中假设我的硬碟分为两槽，partition 1是挂载到根目录，至于partition 2则是挂载到/home这个目录。 这也就是说，当我的资料放置在/home内的各次目录时，资料是放置到partition 2的，如果不是放在/home底下的目录， 那么资料就会被放置到partition 1了！

其实判断某个档案在那个partition底下是很简单的，透过反向追踪即可。以上图来说， 当我想要知道/home/vbird/test这个档案在那个partition时，由test --> vbird --> home --> /，看那个‘进入点’先被查到那就是使用的进入点了。 所以test使用的是/home这个进入点而不是/喔！

例题：
现在让我们来想一想，我的电脑系统如何读取光碟内的资料呢？在Windows里面使用的是‘光碟机’的代号方式处理(假设为E槽时)， 但在Linux底下我们依旧使用目录树喔！在预设的情况下，Linux是将光碟机的资料放置到/media/cdrom里头去的。 如果光碟片里面有个档案档名为‘我的档案’时，那么这个档案是在哪里？
答：
这个档案最终会在如下的完整档名中：
  • Windows： 桌面\我的电脑\E:\我的档案
  • Linux： /medai/cdrom/我的档案
如果光碟机并非被挂载到/media/cdrom，而是挂载到/mnt这个目录时，刚刚读取的这个档案的档名会变成：
  • /mnt/我的档案
如果你了解这个档名，这表示你已经知道挂载的意义了！初次接触Linux时，这里最容易搞混，因为他与Windows的分割槽代号完全不一样！

  • distributions安装时，挂载点与磁碟分割的规划：

既然我们在Linux系统下使用的是目录树系统，所以安装的时候自然就得要规划磁碟分割与目录树的挂载了。 实际上，在Linux安装的时候已经提供了相当多的预设模式让你选择分割的方式了， 不过，无论如何，分割的结果可能都不是很能符合自己主机的样子！因为毕竟每个人的‘想法’都不太一样！ 因此，强烈建议使用‘自订安装, Custom ’这个安装模式！在某些Linux distribution中，会将这个模式写的很厉害，叫做是‘Expert, 专家模式’，这个就厉害了， 请相信您自己，了解上面的说明后，就请自称为专家了吧！没有问题！

  • 自订安装‘Custom’：
    • A：初次接触Linux：只要分割‘ / ’及‘swap’即可：

    通常初次安装Linux系统的朋友们，我们都会建议他直接以一个最大的分割槽‘ / ’来安装系统。 这样作有个好处，就是不怕分割错误造成无法安装的困境！例如/usr是Linux的可执行程式及相关的文件摆放的目录， 所以他的容量需求蛮大的，万一你分割了一块分割槽给/usr，但是却给的不够大，那么就伤脑筋了！ 因为会造成无法将资料完全写入的问题，就有可能会无法安装啦！因此如果你是初次安装的话， 那么可以仅分割成两个分割槽‘ / 与 Swap ’即可。

    • B：建议分割的方法：预留一个备用的剩余磁碟容量！

    在想要学习Linux的朋友中，最麻烦的可能就是得要常常处理分割的问题，因为分割是系统管理员很重要的一个任务。 但如果你将整个硬碟的容量都用光了，那么你要如何练习分割呢？^_^。所以鸟哥在后续的练习中也会这样做， 就是请你特别预留一块不分割的磁碟容量，作为后续练习时可以用来分割之用！

    此外，预留的分割槽也可以拿来做为备份之用。因为我们在实际操作Linux系统的过程中， 可能会发现某些script或者是重要的档案很值得备份时，就可以使用这个剩余的容量分割出新的分割槽， 并使用来备份重要的设定档或者是script。这有个最大的好处， 就是当我的Linux重新安装的时候，我的一些软体或工具程式马上就可以直接在硬碟当中找到！呵呵！重新安装比较便利啦。 为什么要重新安装？因为没有安装过Linux十次以上，不要说你学会了Linux了啦！慢慢体会这句话吧！ ^_^

  • 选择Linux安装程式提供的预设硬碟分割方式：

    对于首次接触Linux的朋友们，鸟哥通常不建议使用各个distribution所提供预设的Server安装方式， 因为会让你无法得知Linux在搞什么鬼，而且也不见得可以符合你的需求！而且要注意的是， 选择Server的时候，请‘确定’你的硬碟资料是不再需要！因为Linux会自动的把你的硬碟里面旧有的资料全部杀掉！ 此外，硬碟至少需要2 GB以上才可以选择这一个模式！

现在你知道Linux为什么不好学了吧？因为很多基础知识都得要先了解！否则连安装都不知道怎么安装～ 现在你知道Linux的可爱了吧！因为如果你学会了，嘿嘿！很多电脑系统/作业系统的概念都很清晰， 转换到不同的资讯跑道是比较容易的喔！^_^

大标题的图示 安装Linux前的规划

从前面的说明我们知道作业系统与硬体的相关性是很高的，而目前最热门的电脑硬体系统为x86个人电脑系统。 我们也讨论了一下各硬体元件在Linux当中的装置档名，同时也了解到磁碟分割与每个分割槽在Linux目录树的关系， 也简单谈论了开机管理程式的用途。接下来我们得要开始安装Linux啰。

安装最重要的第一件事，就是要取得Linux distributions的光碟资料，该如何去下载？ 目前有这么多的distributions，你应该要选择哪一个版本比较好？为什么会比较好？ 在台湾，你可以在哪里下载你所需要的Linux distribution呢？这都是这一小节所要讨论的喔！

小标题的图示 选择适当的distribution

就如同第一章、Linux是什么里面的distributions谈到的， 事实上每个Linux distributions使用的都是来自于http://www.kernel.org官方网站所提供的Linux核心，各家distribution使用的软体其实也都是大同小异， 最大的差别或许就是在于软体的安装模式而已。所以，您只要选择其中一套，并且玩得出神入化， 那么Linux肯定可以学的成的。

不过，由于近年来网路环境实在不很安全，因此你在选择distribution时，特别要了解到该distribution适合的环境， 并且最好选择最新的distribution较佳喔！ 以鸟哥来说，如果是将Linux定位在伺服器上面的话，那么Red Hat Enterprise Linux及SuSE Enterprise Linux应该是很不错的选择，因为他的版本更动幅度较小，并且更新支援的期限较长的原因。

在我们这次的练习中，不想给大家太沉重的$$负担啦，所以鸟哥选择CentOS这一个号称与RHEL完全相容的版本来练习， 目前(2009/08)最新的版本是CentOS 5.3版，你可以选择i386或x86_64的版本来安装，请依据您的硬体来选择。 如果你不知道你的硬体规格时，那么建议就直接安装i386的版本即可。因为i386的CentOS 5.x是可以安装在x86_64的硬体中的。

你可以选择到CentOS的官方网站去下载最新的版本，不过我们在台湾嘛！台湾有映设站台(mirror site)， 所以由映设站台来下载比较快啊！底下列出CentOS的下载点：

  • 国家高速网路中心：http://ftp.twaren.net/Linux/CentOS/5/isos/
  • 义守大学：http://ftp.isu.edu.tw/pub/Linux/CentOS/5.3/isos/
  • CentOS官方网站：http://mirror.centos.org/centos/5/isos/

你要知道的是，因为Linux distributions里面的软体越包越多，所以使用到的光碟(CD)片越来越多了， 因此目前各distribution都有提供DVD的版本。以上面的连结来说，每个连结里面的i386版本中， 你会发现到有DVD版本例如：CentOS-5.3-i386-bin-DVD.iso，也有CD版本例如： CentOS-5.3-i386-bin-[1-6]of6.iso。鸟哥建议您可以下载DVD版本，因为只有一片，比较环保啦！

Tips:
你所下载的档案副档名是.iso，这就是所谓的image档案(映像档)。这种image档案是由光碟直接烧录成档案的， 档案非常的大，建议你不要使用浏览器(IE/Firefox..)来下载，可以使用FTP用户端程式来下载，例如Filezilla (http://filezilla-project.org/download.php)等。这样比较不需要担心断线的问题，因为可以续传啊！

此外，这种映像档可不能以资料格式烧录成为光碟/DVD的！你必须要使用烧录程式的功能， 将他以‘映像档格式’烧录成为光碟或DVD才行！切记不要使用烧录资料档格式来烧录喔！重要重要！ 		鸟哥的图示
小标题的图示 主机的服务规划与硬体的关系

我们前面已经提过，由于主机的服务目的不同，所需要的硬体等级与配备自然也就不一样！ 底下鸟哥稍微提一提每种服务可能会需要的硬体配备规划，当然，还是得提醒， 每个朋友的需求都不一样，所以设计您的主机之前，请先针对自己的需求进行考量。而， 如果您不知道自己的考量为何，那么就先拿一部普通的电脑来玩一玩吧！不过要记得！ 不要将重要资料放在练习用的Linux主机上面。

  • 打造Windows与Linux共存的环境：

在某些情况之下，你可能会想要在‘一部主机上面安装两套以上的作业系统’， 例如底下这些状况：

  • 我的环境里面仅能允许我拥有一部主机，不论是经济问题还是空间问题～
  • 因为目前各主要硬体还是针对Windows进行驱动程式的开发，我想要同时保有Windows作业系统与Linux作业系统， 以确定在Linux底下的硬体应该使用那个I/O port或者是IRQ的分配等等；
  • 我的工作需要同时使用到Windows与Linux作业系统。

果真如此的话，那么刚刚我们在上一个小节谈到的开机流程与多重开机的资料就很重要了。 因为需要如此你才能够在一部主机上面操弄两种不同的作业系统嘛！

Tips:
一般来说，你还可以在Windows作业系统上面安装Virtualbox (http://www.virtualbox.org/) 之类的软体，让你可以在Windows系统上面‘同时’使用Linux系统， 就是两个作业系统同时启动！不过，那样的环境比较复杂，尤其Virtualbox环境中很多硬体都是模拟的， 会让新手很难理解系统控制原理。基本上，鸟哥很不建议您使用这样的方式来学习Linux喔！ 		鸟哥的图示

如果你的Linux主机已经是想要拿来作为某些服务之用时，那么务必不要选择太久的硬体喔！ 前面谈到过，太老旧的硬体可能会有电子零件老化的问题～另外，如果你的Linux主机必须要全年无休的开机着， 那么摆放这部主机的位置也需要选择啊！好了，底下再来谈一谈，在一般小型企业或学校单位中， 常见的某些服务与你的硬体关系有哪些？

  • NAT(达成IP分享器的功能)：

通常小型企业或者是学校单位大多仅会有一条对外的连线，然后全公司/学校内的电脑全部透过这条连线连到网际网路上。 此时我们就得要使用IP分享器来让这一条对外连线分享给所有的公司内部员工使用。 那么Linux能不能达到此一IP分享的功能呢？当然可以，就是透过NAT服务即可达成这项任务了！

在这种环境中，由于Linux作为一个内/外分离的实体，因此网路流量会比较大一点。 此时Linux主机的网路卡就需要比较好些的配备。其他的CPU、RAM、硬碟等等的影响就小很多。 事实上，单利用Linux作为NAT主机来分享IP是很不智的～因为PC的耗电能力比IP分享器要大的多～

那么为什么你还要使用Linux作为NAT呢？因为Linux NAT还可以额外的加装很多分析软体， 可以用来分析用户端的连线，或者是用来控制频宽与流量，达到更公平的频宽使用呢！ 更多的功能则有待后续更多的学习啰！你也可以参考我们在伺服器架设篇当中的资料啰！

  • SAMBA(加入Windows网路上的芳邻)：

在你的Windows系统之间如何传输资料呢？当然就是透过网路上的芳邻来传输啦！那还用问。 这也是学校老师在上课过程中要分享资料给同学常用的机制了。问题是，Windows XP的网芳一般只能同时分享十部用户端连线，超过的话就得要等待了～真不人性化。

我们可以使用Linux上面的SAMBA这个软体来达成加入Windows网芳的功能喔！SAMBA的效能不错， 也没有用户端连线数的限制，相当适合于一般学校环境的档案伺服器(file server)的角色呢！

这种伺服器由于分享的资料量较大，对于系统的网路卡与硬碟的大小及速度就比较重要， 如果你还针对不同的使用者提供档案伺服器功能，那么/home这个目录可以考虑独立出来，并且加大容量。

  • Mail(邮件伺服器)：

邮件伺服器是非常重要的，尤其对于现代人来说，电子邮件几乎已经取代了传统的人工邮件递送了。 拜硬碟价格大跌及Google/Yahoo/MicroSoft公平竞争之赐，一般免费的email信箱几乎都提供了很不错的邮件服务， 包过Web介面的传输、大于2GB以上的容量空间及全年无休的服务等等。例如非常多人使用的gmail就是一例： http://gmail.com。

虽然免费的信箱已经非常够用了，老实说，鸟哥也不建议您架设mail server了。问题是， 如果你是一间私人单位的公司，你的公司内传送的email是具有商业机密或隐私性的，那你还想要交给免费信箱去管理吗？ 此时才有需要架设mail server啰。CentOS一安装完毕就提供了Sendmail及Postfix两种mail server软体了！

在mail server上面，重要的也是硬碟容量与网路卡速度，在此情境中，也可以将/var目录独立出来，并加大容量。

  • Web(WWW伺服器)：

WWW伺服器几乎是所有的网路主机都会安装的一个功能，因为他除了可以提供Internet的WWW连线之外， 很多在网路主机上面的软体功能(例如某些分析软体所提供的最终分析结果的画面)也都使用WWW作为显示的介面， 所以这家伙真是重要到不行的。

CentOS使用的是Apache这套软体来达成WWW网站的功能，在WWW伺服器上面，如果你还有提供资料库系统的话， 那么CPU的等级就不能太低，而最重要的则是RAM了！要增加WWW伺服器的效能，通常提升RAM是一个不错的考量。

  • DHCP(提供用户端自动取得IP的功能)：

如果你是个区域网路管理员，你的区网内共有20部以上的电脑给一般员工使用，这些员工假设并没有电脑网路的维护技能。 那你想要让这些电脑在连上Internet时需要手动去设定IP还是他可以自动的取得IP呢？当然是自动取得比较方便啦！ 这就是DHCP服务的功能了！用户端电脑只要选择‘自动取得IP’，其他的，就是你系统管理员在DHCP伺服器上面设定一下即可。 这个咚咚的硬体要求可以不必很高啰。

  • Proxy(代理伺服器)：

这也是常常会安装的一个伺服器软体，尤其像中小学校的频宽较不足的环境下， Proxy将可有效的解决频宽不足的问题！当然，你也可以在家里内部安装一个Proxy喔！但是， 这个伺服器的硬体要求可以说是相对而言最高的，他不但需要较强有力的CPU来运作，对于硬碟的速度与容量要求也很高！ 自然，既然提供了网路服务，网路卡则是重要的一环！

  • FTP：

常常看到很多朋友喜欢架设FTP去进行网路资料的传输，甚至很多人会架设地下FTP网站去传输些违法的资料。 老实说，‘FTP传输再怎么地下化也是很容易被捉到的’啦！所以，鸟哥相当不建议您架设FTP的喔！ 不过，对于大专院校来说，因为常常需要分享给全校师生一些免费的资源， 此时匿名使用者的FTP软体功能就很需要存在了。对于FTP的硬体需求来说，硬碟容量与网路卡好坏相关性较高。

大致上我们会安装的伺服器软体就是这一些啰！ 当然啦，还是那句老话，在目前你刚接触Linux的这个阶段中，还是以Linux基础为主， 鸟哥也希望你先了解Linux的相关主机操作技巧，其他的架站，未来再谈吧！ 而上面列出的各项服务，仅是提供给你，如果想要架设某种网路服务的主机时，你应该如何规划主机比较好！

小标题的图示 主机硬碟的主要规划

系统对于硬碟的需求跟刚刚提到的主机开放的服务有关，那么除了这点之外，还有没有其他的注意事项呢？ 当然有，那就是资料的分类与资料安全性的考量。所谓的‘资料安全’并不是指资料被网路cracker所破坏， 而是指‘当主机系统的硬体出现问题时，你的档案资料能否安全的保存’之意。

常常会发现网路上有些朋友在问‘我的Linux主机因为跳电的关系，造成不正常的关机，结果导致无法开机，这该如何是好？’ 呵呵，幸运一点的可以使用fsck来解决硬碟的问题，麻烦一点的可能还需要重新安装Linux呢！伤脑筋吧！另外， 由于Linux是多人多工的环境，因此很可能上面已经有很多人的资料在其中了， 如果需要重新安装的话，光是搬移与备份资料就会疯掉了！所以硬碟的分割考量是相当重要的！

虽然我们在本章的第二小节部分有谈论过磁碟分割了，但是，硬碟的规划对于Linux新鲜人而言，那将是造成你‘头疼’的主要凶手之一！ 因为硬碟的分割技巧需要对于Linux档案结构有相当程度的认知之后才能够做比较完善的规划的！ 所以，在这里你只要有个基础的认识即可。老实说，没有安装过十次以上的Linux系统，是学不会Linux与磁碟分割的啦！

无论如何，底下还是说明一下基本硬碟分割的模式吧！

  • 最简单的分割方法：
    这个在上面第二节已经谈过了，就是仅分割出根目录与记忆体置换空间( / & swap )即可。 然后再预留一些剩余的磁碟以供后续的练习之用。不过，这当然是不保险的分割方法(所以鸟哥常常说这是‘懒人分割法’)！ 因为如果任何一个小细节坏掉(例如坏轨的产生)，你的根目录将可能整个的损毁～挽救方面较困难！

  • 稍微麻烦一点的方式：
    较麻烦一点的分割方式就是先分析这部主机的未来用途，然后根据用途去分析需要较大容量的目录， 以及读写较为频繁的目录，将这些重要的目录分别独立出来而不与根目录放在一起， 那当这些读写较频繁的磁碟分割槽有问题时，至少不会影响到根目录的系统资料，那挽救方面就比较容易啊！ 在预设的CentOS环境中，底下的目录是比较符合容量大且(或)读写频繁的目录啰：
    • /
    • /usr
    • /home
    • /var
    • Swap

以鸟哥为例，通常我会希望我的邮件主机大一些，因此我的/var通常会给个数GB的大小， 如此一来就可以不担心会有邮件空间不足的情况了！另外，由于我开放SAMBA服务， 因此提供每个研究室内人员的资料备份空间，所以啰，/home所开放的空间也很大！至于/usr/的容量， 大概只要给2-5GB即可！凡此种种均与您当初预计的主机服务有关！ 因此，请特别注意您的服务项目！然后才来进行硬碟的规划。

小标题的图示 鸟哥说：关于练习机的安装建议
  • 关于硬体方面

老实说，安装Linux是非常困难的一件事，所以在补教界的教材方面，安装(Installation)通常是在系统管理教完后才教的。 那因为我们不是在补教业的教室中，所以没有现成的Linux系统可以用，当然就得要自行安装一个啦！ 因此这里才会先跟大家介绍如何安装Linux的。虽然很多朋友都喜欢使用Virtualbox安装Linux去学习， 但是Virtualbox或其他相关的虚拟化软体都是用模拟的方式去启动Linux的，新手学习方面常常会误解～

有鉴于此，因此，鸟哥‘强烈的建议您，务必拥有一台独立的主机， 而且内含一颗仅有Linux作业系统的硬碟’，以鸟哥自己为例，我的主机上面有一个抽取式硬碟盒，而我有两颗分离的硬碟， 分别安装Windows与Linux系统，要使用不同的作业系统时就抽换硬碟，如此一来，主机很单纯， 而抽换也很快速，不需要对机壳拆拆装装的，很方便！提供给您做为参考。

  • 关于硬碟分割方面

此外，在硬碟的分割方面，鸟哥也建议新手们，先暂时以/及swap两个分割即可，而且，还要预留一个未分割的空间喔！ 因为我们是练习机，暂时不会提供网路服务，所以只要有/及Swap提供给我们进行安装Linux的空间即可。不过， 我们未来会针对系统的磁碟部分进行分割的练习以及磁碟配额(quota)的练习，因此，预留一个磁碟空间是必须要的！

举例来说，如果你有一个20GB的硬碟，那么建议你分15 GB给/来安装Linux，512 MB给Swap，另外的4 GB左右不要分割，先保留下来，未来我们可以继续来练习喔！^_^

  • 关于软体方面

另一个容易发现问题的地方，在于使用者常常会找不到某些指令，导致无法按照书上的说明去执行某些指令。 因为无法执行指令，所以就会一直给他放在那边，不会继续往下学习啊！真是可惜！ 为什么会找不到指令呢？很简单啊！就是因为没有安装该软体啊！所以，‘强烈的建议新手，务必将所有的套件都给他安装上去！’也就是选择‘安装所有套件’就是了。

当然啦，上面提到的都是针对‘练习机’而言喔！如果是您自己预计要上线的Linux主机， 那就不建议按照上面的说明安装了！切记切记！

小标题的图示 鸟哥的两个实际案例

这里说一下鸟哥的两个实际的案例，这两个案例是目前还在运作的主机喔！ 要先声明的是，鸟哥的范例不见得是最好的，因为每个人的考量并不一样。我只是提供相对可以使用的方案而已喔！

  • 案例一：家用的小型Linux伺服器，IP分享与档案分享中心：
  • 提供服务：
    提供家里的多部电脑的网路连线分享，所以需要NAT功能。提供家庭成员的资料存放容量，由于家里使用Windows系统的成员不少， 所以建置SAMBA伺服器，提供网芳的网路磁碟功能。

  • 主机硬体配备：
    • CPU使用P-III 800 MHz；
    • 记忆体大小为512 MB的RAM；
    • 两张网路卡，控制晶片为常见的螃蟹卡(Realtek)；
    • 共有两颗磁碟，一颗系统碟一颗资料碟。资料碟高达160 GB；
    • 显示卡为以前很流行的GeForce 2 MX含32 MB的记忆体；
    • 安装完毕后将荧幕,键盘,滑鼠,DVD-ROM等配备均移除，仅剩下网路线与电源线。

  • 硬碟分割：
    • 分成/boot, /, /usr, /var, /tmp等目录均独立；
    • /home独立出来，放置到那颗160GB的磁碟，提供给家庭成员存放个人资料；
    • 1 GB的Swap；

  • 案例二：提供Linux的PC丛集(Cluster)电脑群：
  • 提供服务：
    提供研究室成员对于模式模拟的软、硬体平台，主要提供的服务并非网际网路服务， 而是研究室内部的研究工作分析。

  • 主机硬体配备：
    • 利用两部双CPU(均为双核)的x86_64系统(泰安主机板提供的特殊功能)；
    • 使用Geforce 7300显示卡，内含64MB的记忆体；
    • 使用一颗硬碟作为主系统，六颗磁碟组成磁碟阵列，以储存模式模拟的结果；
    • 使用PCI-Express介面的网路卡，速度为Gbps；
    • 共有4 GB的主记忆体容量；

  • 硬碟分割：
    • 全部的磁碟阵列容量均给/cluster/raid目录，占有2TB的容量；
    • 2 GB的swap容量；
    • 分割出/, /usr, /var, /tmp等目录，避免程式错误造成系统的困扰；
    • /home也独立出来，让每个研究室成员可以拥有自己的资料存放容量；

在上面的案例中，案例一是属于小规模的主机系统，因此只要使用预计被淘汰的配备即可进行主机的架设！ 唯一可能需要购买的大概是网路卡吧！呵呵！而在案例二中，由于我需要大量的数值运算， 且运算结果的资料非常的庞大，因此就需要比较大的磁碟容量与较佳的网路系统了。 以上的资料请先记得，因为下一章节在实际安装Linux之前，你得先进行主机的规划呀！

小标题的图示 大硬碟配合旧主机造成的无法开机问题

随着时代的演变，在2009年中的目前，个人电脑上面的硬碟容量竟然都已经高达750 GB以上了！ 这么大的硬碟用起来当然是很爽快的啦～不过，也有一些问题的～那就是～开机的问题～

某些比较旧的主机板中，他们的BIOS可能找不到比较大容量的磁碟的。所以，你在旧主机板上面安装新的大容量磁碟时， 很可能你的磁碟容量会被误判！不过，即使是这样，Linux还是能够安装喔！而且能够顺利的捉到完整的硬碟容量呢！ 为什么呢？因为当Linux核心顺利开机启动后，他会重新再去侦测一次整个硬体而不理会BIOS所提供的资讯， 所以就能够顺利的捉到正确的硬碟，并且让你安装Linux。

但是，安装完毕后，可能会无法开机喔！为什么啊？前一小节里面我们不是谈到过开机流程与MBR的内容吗？ 安装的时候是以光碟开机并且由光碟载入Linux核心，所以核心可以被顺利载入来安装。但是若以这样的配备来开机时， 因为BIOS捉到的硬碟是不对的，所以使用硬碟开机可能就会出现无法开机的错误了。那怎办？

由于BIOS捉到的磁碟容量不对，但是至少在整颗磁碟前面的磁区他还读的到啊！ 因此，你只要将这个磁碟最前面的容量分割出一个小分割槽，并将这个分割槽与系统开机档案的放置目录摆在一起， 那就是 /boot 这个目录！就能够解决了！很简单吧！ 其实，重点是：‘将开机磁区所在分割槽规范在小于1024个磁柱以内～’ 即可！那怎么做到呢？很简单，在进行安装的时候，规划出三个磁区，分别是：

  • /boot
  • /
  • swap

那个/boot只要给100M Bytes左右即可！而且/boot要放在整块硬碟的最前面！这部份你先有印象与概念即可，未来我们谈到第二十章的开机流程时，会再加强说明的！ ^_^

大标题的图示 重点回顾
  • 新添购电脑硬体配备时，需要考量的角度有‘游戏机/工作机的考量’、‘效能/价格笔的考量’、‘支援度的考量’等；
  • 旧的硬体配备可能由于保存的问题或者是电子零件老化的问题， 导致电脑系统非常容易在运作过程中出现不明的当机情况
  • Red Hat的硬体支援：https://hardware.redhat.com/?pagename=hcl
  • 在Linux系统中，每个装置都被当成一个档案来对待，每个装置都会有装置档名。
  • 磁碟的装置档名主要分为 (1)IDE介面的/dev/hd[a-d]及 (2)SATA/SCSI/USB介面的/dev/sd[a-p]两种；
  • 磁碟的第一个磁区主要记录了两个重要的资讯，分别是： (1)主要开机记录区(Master Boot Record, MBR)：可以安装开机管理程式的地方，有446 bytes (1)分割表(partition table)：记录整颗硬碟分割的状态，有64 bytes；
  • 磁碟的主要与延伸分割最多可以有四个，逻辑分割的装置档名号码，一定由5号开始；
  • 开机的流程由：BIOS-->MBR-->-->boot loader-->核心档案；
  • boot loader的功能主要有：提供选单、载入核心、转交控制权给其他loader
  • boot loader可以安装的地点有两个，分别是 MBR 与 boot sector
  • Linux作业系统的档案使用目录树系统，与磁碟的对应需要有‘挂载’的动作才行；
  • 新手的简单分割，建议只要有/及swap两个分割槽即可
大标题的图示 本章习题
(要看答案请将滑鼠移动到‘答：’底下的空白处，按下左键圈选空白处即可察看)
实作题部分：
  • 请分析你的家用电脑，以你的硬体配备来计算可能产生的耗电量，最终再以计算出来的总瓦数乘上你可能开机的时间， 以推估出一年你可能会花费多少钱在你的这部主机上面？
    硬体里面包括 CPU/硬碟/主机板/记忆体/显示卡/荧幕等等都会消耗电力，同时电源供应器也会消耗一部份的电力。 若有实际测量工具时，请使用测量结果来计算。若无测量工具，请上网找出每个元件的最大理论消耗功率来计算。
问答题部分：
  • 一部电脑主机是否只要 CPU 够快，整体速度就会提高？
    不见得！一部电脑系统的速度与整体电脑系统的运作有关，每个元件皆会影响电脑的速度！ 这包括了记忆体、CPU、AGP与显示卡速度，硬碟的速度以及其他相关的输入输出介面等等！ 所以，如果您的系统是升级的，那么还得必须要注意各个旧元件是否可以保留， 或者旧的可以用的元件必须要舍弃！
  • Linux 对于硬体的要求需要的考虑为何？是否一定要很高的配备才能安装 Linux ？
    Linux 对于硬体的要求是因‘服务种类、服务范围及主机的角色’而定的。例如一部专门用来运算数值解析的 Linux 运算工作站，需要比较强大的 CPU 与足够的 RAM 来进行工作，至于一般家庭用的仅用来做为 ADSL 宽频分享器的 Linux 主机，则只要 P-III 等级的电脑，甚至 P-II 系列的等级，就可以很顺利的运行 Linux 了。
  • 一部好的主机在安装之前，最好先进行规划，哪些是必定需要注意的 Linux 主机规划事项？
    依据上一题的答案内容，我们知道 Linux 对于硬体的要求是‘因地制宜’地！所以，要进行 Linux 的安装之前，一定需要规划 Linux 主机的定位与角色！因此， Linux 的主机是否开放网路服务？这部主机的未来规划中，是否需要进行大量的运算？这 部主机是否需要提供很大的硬碟容量来服务客户端的使用？这部主机预计开放的网路服务内容？ 等等，都是需要经过考量的，尤其未来的‘套件选择安装’上面，更需要依据这些规划来设定。
  • 请写下下列配备中，在 Linux 的装置档名：
    IDE 硬碟：
    CDROM：
    印表机：
    软碟机：
    网路卡：
    • IDE 硬碟：/dev/hd[a-d]
    • CDROM：/dev/cdrom
    • 印表机：/dev/lp[0-2]
    • 软碟机：/dev/fd[0-1]
    • 网路卡：/dev/eth[0-n]
  • 如果您的系统常常当机，又找不到方法解决，您可以朝硬体的那个方向去搜寻？
    如果软体没有问题的话，那么当然发生当机的，可能就是硬体的问题了。 1.可以先检测系统有没有超频？ 2.再来则是查阅当系统运作时，系统的机壳内温度会不会过高？ 因为过高的温度常常会造成当机。 3.再者，检查一下 CPU 的温度，这也很重要。 4.再来，则是检查是否插了多条的记忆体，因为不同厂牌的记忆体混插很容易造成系统不稳定。 5.电源供应器是否合乎标准？这些都可以进行检测喔！
  • 目前在个人电脑上面常见的硬碟与主机板的连接介面有哪两个？
    有早期的 IDE 介面与最近的 SATA 介面，购买时要分的很清楚！
大标题的图示 参考资料与延伸阅读
  • SPFdisk http://spfdisk.sourceforge.net/
2002/04/08：第一次完成吧？
2003/02/02：重新编排与加入 FAQ
2005/06/04：将旧的文章移动到 这里
2005/06/12：风格修订之外，新增了 Linux 练习机硬体选择与软体安装的建议
2005/06/15：感谢上奇编辑 Tim 兄来信告知一些可能有争议的部分！包括 AthlonXP 已被 Sempron 取代，已经修订！
2008/07/29：将旧的FC4文章移动到此处。
2008/08/21：将整份文件作个重新整理，移除计概有谈到的硬体部分，增加partition的资料量。
2009/08/06：重新修订习题与解答，尤其一些计概方面的问题将他挪开！


鸟哥的 Linux 私房菜 -- 基础学习篇

为取得较佳浏览结果，请爱用 firefox 浏览本网页
鸟哥的 Linux 私房菜馆 | Linux 基础文件 | Linux 架站文件 | Linux 企业运用 | 安全管理 | 新手讨论 |

第四章、安装 CentOS 5.x 与多重开机小技巧
最近更新日期：2009/08/11
Linux distributions越作越成熟，所以在安装方面也越来越简单！虽然安装非常的简单， 但是刚刚前一章所谈到的基础认知还是需要了解的，包括MBR, partition, boot loader, mount, software的选择等等的资料。 这一章鸟哥的安装定义为‘一部练习机’，所以安装的方式都是以最简单的方式来处理的。 另外，鸟哥选择的是CentOS 5.x的版本来安装的啦！在内文中，只要标题内含有(Option) 的，代表是鸟哥额外的说明，你应该看看就好，不需要实作喔！^_^

1. 本练习机的规划--尤其是分割参数
2. 开始安装CentOS 5
    2.1 调整开机媒体(BIOS)
2.2 选择安装模式与开机, 测试记忆体稳定度
2.3 选择语系资料
2.4 磁碟分割, 进阶软体阵列建置
2.5 开机管理程式、网路、时区设定与root密码
2.6 软体选择
2.7 其他功能：RAM testing, 安装笔记型电脑的核心参数(Option)
 3. 安装后的首次设定
4. 多重开机安装流程与技巧
    4.1 新主机仅有一颗硬碟
4.2 旧主机有两颗以上硬碟
4.3 旧主机只有一颗硬碟
 5. 关于大硬碟导致无法开机的问题
6. 重点回顾
7. 本章习题
8. 参考资料与延伸阅读
9. 针对本文的建议：http://phorum.vbird.org/viewtopic.php?p=135157
大标题的图示 本练习机的规划--尤其是分割参数

读完第三章、主机规划与磁碟分割之后，相信你对于安装 Linux 之前要作的事情已经有基本的概念了。唔！并没有读第三章...千万不要这样跳着读，赶紧回去念一念第三章， 了解一下安装前的各种考量对你Linux的学习会比较好啦！

如果你已经读完第三章了，那么底下就实际针对第三章的介绍来一一规划我们所要安装的练习机了吧！ 请大家注意唷，我们后续的章节与本章的安装都有相关性，所以，请务必要了解到我们这一章的作法喔！

  • Linux主机的角色定位：

    本主机架设的主要目的在于练习Linux的相关技术，所以几乎所有的资料都想要安装进来。 因此连较耗系统资源的X Window System也必须要包含进来才行。所以使用的是前一章讲到的Desktop类型的使用啰；

  • 选择的distribution：

    由于我们对于Linux的定位为‘伺服器’的角色，因此选择号称完全相容于商业版RHEL的社群版本， 就是CentOS 5.x版啰。请回到前一章去获得下载的资讯吧！ ^_^。另外，由于鸟哥后续使用的硬体配备并非64位元， 因此使用的版本为i386的版本喔！

  • 电脑系统硬体配备：

    由于鸟哥身边的电脑都有用途了，只剩下一部较旧的主机。硬体配备如下所示。虽然这样的硬体配备已经过时了， 不过，对于练习Linux或者是架设一部实际上线的Linux server来说，还是很够力的：

    • 主机板与CPU：
      使用Celoron 1.2GHz的CPU，内建256KBytes的第二层快取记忆体。 搭配华硕小型主机板(准系统用)；

    • 记忆体：
      总共具有三条256MB的PC133记忆体，总记忆体为768MB；

    • 硬碟：
      使用一颗40GB的IBM硬碟，规格为IDE介面，并且接到IDE2的master，所以装置档名为/dev/hdc喔！

    • 网路卡：
      由于主机板内建的网路卡需要额外的驱动程式，所以安插了一张螃蟹卡(Realtek 8139)， 并且于BIOS中关闭了内建的网路卡功能；

    • 显示卡(VGA)：
      由于这部主机是准系统，因此是主机板内建的显示晶片。显示卡记忆体为与主记忆体分享的， 鸟哥分享出64MB给显示卡使用。因此本系统主记忆体仅剩(768-64=704MB)喔；

    • 其他输入/输出装置：
      具有一部DVD光碟机、1.44MB软碟机、USB光学滑鼠、300W电源供应器。并使用17吋的液晶荧幕。

  • 磁碟分割的配置

    第三章谈到关于旧主机板加上大容量硬碟可能会导致能安装但无法开机的问题， 为了避免这个问题在各位朋友的实际案例中发生，因此鸟哥将我的40GB硬碟进行如下的分割：

    所需目录/装置 | 磁碟容量 | 分割类型
    /boot | 100MB | primary
    / 10GB primary
    /home | 5GB | primary
    swap | 1GB | logical

    你也可以仅分割出/及swap。如果想要安装多重作业系统的，那甚至可以只存在/即可呢！连swap都不需要了！ 如果能安装却无法开机，可能就是由于没有/boot存在的关系，请参考本章最后一节的说明了。

  • 开机管理程式(boot loader)：

    练习机的开机管理程式使用CentOS 5.x预设的grub软体，并且安装到MBR上面。 也必须要安装到MBR上面才行！因为我们的硬碟是全部用在Linux上面的啊！ ^_^

  • 选择软体：

    如前所述，将所有的软体通通安装上去！等到未来再次重新安装时，你再使用最小安装来安装你的系统， 藉以提升自己的功力啰！注意，第一次安装Linux的朋友，真的建议要完全安装整个系统喔！切记切记！

  • 检查表单：

    最后，你可以使用底下的表格来检查一下，你要安装的资料与实际的硬体是否吻合喔：

    是与否，或详细资讯 | 细部项目
    是, DVD版 | 01. 是否已下载且烧录所需的Linux distribution？(DVD或CD)
    CentOS 5.3, i386 | 02. Linux distribution的版本为何？(如CentOS 5.3 i386版本)
    i386 | 03. 硬体等级为何(如i386, x86_64, SPARC等等，以及DVD/CD-ROM)
    是, 均为i386 | 04. 前三项安装媒体/作业系统/硬体需求，是否吻合？
    是 | 05. 硬碟资料是否可以全部被删除？
    已确认分割方式 | 06. Partition是否做好确认(包括/与swap等容量)
       硬碟数量: 1颗40GB硬碟
    /: 10GB
    swap: 1GB
    其他：/boot: 100MB, /home: 5GB
    无 | 07. 是否具有特殊的硬体装置(如SCSI磁碟阵列卡等)
    无此需要 | 08. 若有上述特殊硬体，是否已下载驱动程式？
    grub, MBR | 09. 开机管理程式与安装的位置为何？
    未取得IP参数 | 10. 网路资讯(IP参数等等)是否已取得？
       未取得IP的情况下，可以套用如下的IP参数：
    是否使用DHCP：无
    IP:192.168.1.100
    子遮罩网路：255.255.255.0
    主机名称：www.vbird.tsai
    预设安装 | 11. 所需要的软体有哪些？(预设/最小/全部/自订安装)

    上面的表单中第11点颇有趣，如果你是第一次安装Linux，那么建议你使用全部安装；如果是已经有安装过的话， 那可以使用预设安装；如果要挑战自己的功力，那就使用最小安装。如果想要自行挑选软体的话，那就使用自订安装吧。 如果上面表单确认过都没有问题的话，那么我们就可以开始来安装咱们的CentOS 5.x i386版本啰！ ^_^
大标题的图示 开始安装CentOS 5

由于本章的内容主要是针对安装一部Linux练习机来设定的，所以安装的分割等过程较为简单。 如果你已经不是第一次接触Linux，并且想要架设一部要上线的Linux主机，请务必前往第三章看一下整体规划的想法喔！ 在本章中，你只要依照前一小节的检查表单检查你所需要的安装媒体/硬体/软体资讯等等， 然后就能够安装啦！

安装的步骤在各主要Linux distributions都差不多，主要的内容大概是：

  1. 调整开机媒体(BIOS)：务必要使用CD或DVD光碟开机，通常需要调整BIOS；
  2. 选择安装模式与开机：包括图形介面/文字介面等，也可加入特殊参数来开机进入安装画面；
  3. 选择语系资料：由于不同地区的键盘按键不同，此时需要调整语系/键盘/滑鼠等配备；
  4. 磁碟分割：最重要的项目之一了！记得将刚刚的规划单拿出来设定；
  5. 开机管理程式、网路、时区设定与root密码：一些需要的系统基础设定！
  6. 软体选择：需要什么样的软体？全部安装还是预设安装即可？
  7. 安装后的首次设定：安装完毕后还有一些事项要处理，包括使用者、SELinux与防火墙等！
大概就是这样子吧！好了，底下我们就真的要来安装啰！

小标题的图示 1. 调整开机媒体(BIOS)

你不能在Windows的环境下安装Linux的，你必须要使用Linux的安装光碟开机后才能够进行Linux的安装流程。 目前几乎所有的Linux distributions以及主机板都有支援光碟开机，所以以往使用软碟开机的安装方式我们就不再介绍了。

那如何让你的主机可以用光碟开机呢？由前一章的开机流程我们知道开机的装置是由BIOS调整的， 所以要让光碟可以开机，当然就得要进入BIOS调整开机装置的顺序了。不过，各家主机板使用的BIOS程式不一样， 而且进入BIOS的按键也不相同，因此这部份得要参考你的主机板说明书才好。鸟哥这里使用的是我的测试机来解释喔。

  1. 开机进入BIOS的按键
    将你的PC重新开机，在开机的画面中按下[del]按键，以进入BIOS画面，如下图的箭头所示：

    按[Del]进入BIOS画面示意图
    图2.1.1、按[Del]进入BIOS画面示意图

  2. 进入BIOS操作介面
    然后会出现如下的图示，显示出目前你的BIOS主要架构：

    BIOS画面示意图
    图2.1.2、BIOS画面示意图

    上图画面中最上方为主选单部分，计有‘Main, Advanced, Power, Boot, Exit’等项目。我们有兴趣的地方在‘Boot’中。 上图最下方则是一些BIOS操作说明，包括使用上、下、左、右等按键以及[Enter]按键等。 此时，请按照BIOS的操作说明，利用向右的方向键将选单移动到‘Boot’项目

  3. 开机装置的顺序调整
    进入到Boot的画面后，你就可以使用[+][-]按键来调整开机顺序。以鸟哥的环境来说，我就调整开机装置为光碟啦！ 如下图所示：

    BIOS内的开机顺序选单
    图2.1.3、BIOS内的开机顺序选单

  4. 储存后离开
    接下来，只要输入[F10]然后按下[Enter]就能够储存刚刚的设定，系统会自动重新开机，就能够使用光碟机里面的光碟来开机了。 就是这么简单啊！
Tips:
另外一款常见的BIOS画面中，会有一个‘BIOS Features Setup’之类字眼的选项，进入该选项后找到‘Boot Sequence’ 或者是‘First Boot Device’之类的字样，并选择CD-ROM开机为第一优先即可。 通常鸟哥都是用CD-ROM为第一项，然后是硬碟(HD-0)。 		鸟哥的图示

在调整完BIOS内的开机装置的顺序后，理论上你的主机已经可使用可开机光碟来开机了！ 如果发生一些错误讯息导致无法以CentOS 5.x DVD来开机，很可能是由于：1)电脑硬体不支援； 2)光碟机会挑片； 3)光碟片有问题； 如果是这样，那么建议你再仔细的确认一下你的硬体是否有超频？或者其他不正常的现象。 另外，你的光碟来源也需要再次的确认！

在进行完上面的步骤之后，请放入我们的CentOS 5.x i386的DVD进入光碟机中，重新开机准备进入安装画面吧！

小标题的图示 2. 选择安装模式与开机

由于为了画面撷取的解析度，鸟哥使用Virtualbox(注1)这套软体来捉图给大家看。 所以如果有看到与上面练习机的规划的资讯不同时，请大家多多包涵啊！好了， 如果一切都没问题，那么使用DVD开机后，你应该会看到荧幕出现如下的画面了：

安装程式的安装模式选择画面，预设的[F1]画面
图2.2.1、安装程式的安装模式选择画面，预设的[F1]画面

上面的画面中说明了：

  1. 你可以直接按下<Enter>来进入图形介面的安装方式；
  2. 也可以直接在boot:(上图箭头4所指处)后面输入‘linux text’来进入文字介面的安装；
  3. 还有其他功能选单，可按下键盘最上方那一列的[F1]...[F5]按键来查阅各功能。

要特别注意的是，如果你在 10 秒钟内没有按下任何按键的话，那么安装程式预设会使用图形介面来开始安装流程喔！ 由于目前安装程式都作的非常棒！因此，建议你可以使用图形介面来安装即可。鸟哥底下就是使用图形介面来安装的。 如果想要知道安装程式还提供什么功能，我们可以按下功能键。例如底下就是[F2]的功能说明：

安装程式的安装模式选择画面，[F2]的画面
图2.2.2、安装程式的安装模式选择画面，[F2]的画面

上图中箭头指的地方需要留意一点点，那个是还算常用的功能！意义是这样的：

  • linux noprobe (1号箭头)：
    不进行硬体的侦测，如果你有特殊硬体时，或许可以使用这一项来停止硬体侦测；

  • linux askmethod (2号箭头)：
    进入互动模式，安装程式会进行一些询问。如果你的硬碟内含有安装媒体时， 或者是你的环境内有安装伺服器(Installation server)，那就可以选这一项来填入正确的网路主机来安装；

  • memtest86 (3号箭头)：
    这个有趣了！这个项目会一直进行记忆体的读写，如果你怀疑你的记忆体稳定度不足的话， 可以使用这个项目来测试你的记忆体喔！测试完成后需要重新开机！

那如果按下的是[F5]时，就会进入到救援模式的说明画面，如下图所示：

安装程式的安装模式选择画面，[F5]的救援模式说明画面
图2.2.3、安装程式的安装模式选择画面，[F5]的救援模式说明画面

上图的意思是说，如果你的Linux系统因为设定错误导致无法开机时，可以使用‘linux rescue’来进入救援模式。这个救援模式很有帮助喔！ 在我们后面各章节的练习中有很多练习是需要更动到系统设定档的，万一你设定错误将可能会导致无法开机。 此时请拿出此片DVD来进行救援模式，能够救回你的Linux而不需要重新安装呢！

因为我们是首次安装Linux嘛！所以就请直接按下<Enter>按键，此时安装程式会开始去侦测硬体， 侦测的结果会回报到你的荧幕上，如下所示：

安装程式的核心进行硬体侦测流程示意图
图2.2.4、安装程式的核心进行硬体侦测流程示意图

如果侦测过程中没有问题，那么就会出现要你选择是否要进行储存媒体的检验画面，如下所示：

是否进行安装媒体的检测示意图
图2.2.5、是否进行安装媒体的检测示意图

如果你确定你所下载的DVD或光碟没有问题的话，那么这里可以选择‘Skip(忽略)’， 不过，你也可以按下‘OK’来进行DVD的分析，因为通过DVD的分析后，后续的安装比较不会出现奇怪的问题。 不过如果你按下‘OK’后，程式会开始分析光碟内的所有档案的资讯，会花非常多的时间喔！如下所示：

是否真的要测试光碟或 DVD 碟？
图2.2.6、是否真的要测试光碟或 DVD 碟？

若没有问题，请按下‘ Test ’按钮，此时会出现分析过程如下图所示：

开始分析 DVD 的内容！
图2.2.7、开始分析 DVD 的内容！

最终的分析结果如下所示，按下‘ OK ’即可！如果你发现了分析错误的情况，很可能是你下载的 DVD 来源档案不完整， 或者是光碟/DVD被你的光碟机挑片，或者是烧录的速度倍数太高而导致烧录不完整等等，总之，可能就是要你再重新捉一片新的 DVD 啦！这就是测试 DVD 的优点，虽然会花去一些时间就是了。

检验结果是正确的情况
图2.2.8、检验结果是正确的情况

如果还有其他光碟想要被测试时，在下图中按下‘ Test ’继续！不过我们仅有一片 DVD 而已， 因此这边选择‘ Continue ’来进入安装的程序喔！

检验结束，开始安装的流程
图2.2.9、检验结束，开始安装的流程
小标题的图示 3. 选择语系资料

接下来就是整个安装的程序了。安装的画面如下所示：

欢迎画面荧幕
图2.3.1、欢迎画面荧幕

如果你想要了解这一版的CentOS 5.3有什么公告的注意事项，请按下上图的‘Release Notes’按钮(1号箭头处)， 就能够看到释出公告的项目。如果没有问题的话，请按下‘Next’开始安装程序啦！如下所示会出现语系的选择了。

安装过程的语系选择
图2.3.2、安装过程的语系选择

我们惯用的中文为繁体中文，请先选择繁体中文的项目(Chinese, Traditional)，然后继续给他‘Next’即可出现如下画面：

键盘字元对应表的选择
图2.3.3、键盘字元对应表的选择

因为繁体中文预设也是使用美式英文的键盘对照表，因此你会看到画面直接就是美式英文，你只要按下‘下一步’即可！ 此时你也会发现，整个画面通通变成中文介面啦！真是好具有亲和力喔！

如果没有问题的话，理论上应该会进入下个步骤，亦即是磁碟分割的画面才对。不过，如果你的硬碟是全新的， 而且并没有经过任何的磁碟分割时，就会出现如下的警告讯息：

安装程式找不到磁碟分割表的警告图示
图2.3.4、安装程式找不到磁碟分割表的警告图示

因为鸟哥使用的是Virtualbox虚拟机器的环境，所以预设的那颗硬碟是全新的，所以才会出现上述的讯息。 请在上图中按下‘是’吧！你的主机内的硬碟如果不是全新的，上述的警告画面不会出现！而如果你曾经安装过 Linux 的话，那么可能会出现如下图的样子：

曾经安装过 CentOS 出现的全新安装或升级
图2.3.5、曾经安装过 CentOS 出现的全新安装或升级

如果没有其他特别的需求，那就选择全新安装吧！接下来让我们开始磁碟分割去！

小标题的图示 4. 磁碟分割

如同前面谈到的，磁碟分割是整个安装过程里面最重要的部分了。CentOS预设给了我们四种分割模式，分别为：

  • 移除所选磁碟上的所有分割区，并建立预设分割模式： 如果选择这种模式，你硬碟会整个被Linux拿去使用，并且硬碟里面的分割全部被删除后， 以安装程式的预设方式重新建立分割槽，使用上要特别注意！

  • 移除所选磁碟上的 Linux 分割区，并建立预设的分割模式： 在这个硬碟内，只有Linux的分割槽会被删除，然后再以安装程式的预设方式重新建立分割槽。

  • 使用所选取磁碟上的未使用空间，建立预设的分割模式： 如果你的这颗硬碟内还有未被分割的磁柱空间(注意，是未被分割，而不是该分割槽内没有资料的意思！)， 那么使用这个项目后，他不会更动原有的分割槽，只会就剩余的未分割区块进行预设分割的建置。

  • 建立自订的分割模式： 就是我们要使用的啦！不要使用安装程式的预设分割方式，使用我们需要的分割方式来处理。

如果你想要玩一玩不同的分割模式，那如下图箭头所指的地方，点一下该按钮就会出现上面说明的四种模式了。自己玩玩先！ 但是因为我们已经规划好要建立四个分割槽，分别是/, /boot, /home与swap四个，所以不想要使用安装程式预设的分割方式。 因此如下所示，我们所使用的是自订分割的模式。不要搞错喔！

磁碟分割方式的挑选
图2.4.1、磁碟分割方式的挑选

按下‘下一步’后就会出现如下的分割视窗。这个画面主要分为三大区块，最上方为硬碟的分割示意图， 目前因为鸟哥的硬碟并未分割，所以呈现的就是一整块而且为Free的字样。中间则是指令区，下方则是每个分割槽的装置档名、 挂载点目录、档案系统类型、是否需要格式化、分割槽容量大小、开始与结束的磁柱号码等。

磁碟分割操作主画面
图2.4.2、磁碟分割操作主画面

至于指令区，总共有六大区块，其中RAID与LVM是硬碟特殊的应用，这部份我们会在后续的第十五章的进阶档案系统当中再来说明。至于其他指令的作用如下：

  • ‘新增’是增加新分割，亦即进行分割动作，以建立新的磁碟分割槽；
  • ‘编辑’则是编辑已经存在的磁碟分割槽， 你可以在实际状态显示区点选想要修改的分割槽，然后再点选‘编辑’即可进行该分割槽的编辑动作。
  • ‘删除’则是删除一个磁碟分割槽，同样的， 你得要在实际状态显示区点选想要删除的分割槽喔！
  • ‘重设’则是恢复最原始的磁碟分割状态！

需要注意的是，你的系统与鸟哥的系统当然不可能完全一样，所以你荧幕上的硬碟资讯应该不会与鸟哥的相同的喔！ 所以看到不同，不要太紧张啊，那是正常的！

  • 建立根目录的分割槽

好，接下来我们就尝试来建立根目录(/)的分割槽看看。按下‘新增’后，就会出现如下的画面。 由于我们需要的根目录是使用Linux的档案系统，因此预设就是ext3这个档案系统啦！ 至于在挂载点的地方，你可以手动输入也可以用滑鼠来挑选。 最后在大小(MB)的地方输入你所需要的磁碟容量即可。不过由于鸟哥这个系统当中只有一颗磁碟， 所以在‘可用的磁碟机’里面就不能够自由挑选啰！

新增磁碟分割槽的画面
图2.4.3、新增磁碟分割槽的画面

如果你想要知道Linux还支援什么档案系统类型，点一下上图中的ext3那个按钮，就会出现如下的画面啦！

分割过程的档案系统类型挑选
图2.4.4、分割过程的档案系统类型挑选

这几种档案系统类型分别是：

  • ext2/ext3：是Linux适用的档案系统类型。由于ext3档案系统多了日志的记录， 对于系统的复原比较快速，因此建议你务必要选择新的ext3不要用ext2了。 (日志式档案系统我们会在后续的第八章介绍他的意义。)

  • physical volume (LVM)：这是用来弹性调整档案系统容量的一种机制， 可以让你的档案系统容量变大或变小而不改变原有的档案资料内容！这部份我们会在第十五章、进阶档案系统管理中谈到！

  • software RAID：利用Linux作业系统的特性，用软体模拟出磁碟阵列的功能！ 这东西很棒！不过目前我们还用不到！在后续的第十五章再跟大家报告了！

  • swap：就是记忆体置换空间！由于swap并不会使用到目录树的挂载， 所以用swap就不需要指定挂载点喔！

  • vfat：同时被Linux与Windows所支援的档案系统类型。 如果你的主机硬碟内同时存在Windows与Linux作业系统，为了资料的交换，确实可以建置一个vfat的档案系统喔！

这几样东西都很有趣！不过，毕竟我们才刚刚碰这个Linux嘛！先安装起来其他的以后再说。 所以，你只要使用ext3以及swap这两者即可啦！

一切资料都填入妥当后，就会出现如下的画面。因为我们的根目录就是需要10GB的容量， 因此在大小(MB)的地方就得要填入10000的大小。 因为1G=1000M比较好记忆嘛！而且我们的根目录容量是固定的，所以在下图的大小选项就选择‘固定大小’了。 此外，如果你硬要自己调整主要/延伸/逻辑分割的类型时，最后那个‘强制成为主要分割’可以自己玩一玩先！最后按下确定吧！

新增根目录分割槽的最终图示
图2.4.5、新增根目录分割槽的最终图示

按下确定后就会回到原本的分割操作画面(如下图所示)。此时你会看到分割示意图多了一个hda1，且在实际分割区域显示中， 也会看到/dev/hda1是对应到根目录的。在‘格式化’的项目中出现一个打勾的符号， 那代表后续的安装会将/dev/hda1重新格式化的意思。接下来，我们继续按下‘新增’来建立/boot这个分割槽吧！

磁碟分割主画面的改变示意图
图2.4.6、磁碟分割主画面的改变示意图
  • 建立/boot目录的分割槽

同样的，在按下‘新增’后，如下依序填入正确的资讯，包括挂载点、档案系统、档案大小等。 由于第三章的大硬碟配合旧主机当中我们谈到如果有/boot独立分割槽时， 务必让该分割槽在整颗硬碟的最前面部分。因此，我们针对/boot就选择‘强制成为主要分割’啰！如下图所示：

新增/boot分割槽的最终结果
图2.4.7、新增/boot分割槽的最终结果

最终建立/boot分割槽的结果如下所示，仔细看输出的结果喔！安装程式还挺聪明的， 他会主动的将/boot这个特殊目录移到磁碟最前面，所以你会看到/boot所在的磁碟分割槽为/dev/hda1，而起始磁柱则为1号呢！ 很有趣吧！情况如下图所示：

图2.4.8、/boot分割槽自动调整磁柱号码示意图
  • 建立记忆体置换空间swap的分割槽

在上图中继续按下‘新增’来处理记忆体置换空间(swap)。如同上面谈到的， 因为swap是记忆体置换空间，因此不需要有挂载点。所以，请如同下图所示，在‘档案系统类型’处挑选为‘swap’吧！

swap档案系统的挑选示意图
图2.4.9、swap档案系统的挑选示意图

挑选了swap之后，你就会发现到‘挂载点’部分自动变成‘不适用’了！因为不需要挂载啦！那么swap应该要选多大呢？ 虽然我们已经自订为1GB这么大的置换空间，不过，在传统的Linux说明文件当中特别有指定到 ‘swap最好为实体记忆体的1.5到2倍之间’。swap置换空间是很重要的， 因为他可以避免因为实体记忆体不足而造成的系统效能低落的问题。但是如果你的实体记忆体有4GB以上时， 老实说，swap也可以不必额外设定啦！

Tips:
swap记忆体置换空间的功能是：当有资料被存放在实体记忆体里面，但是这些资料又不是常被CPU所取用时， 那么这些不常被使用的程序将会被丢到硬碟的swap置换空间当中， 而将速度较快的实体记忆体空间释放出来给真正需要的程序使用！ 所以，如果你的系统不很忙，而记忆体又很大，自然不需要swap啰。 		鸟哥的图示
新增swap分割的最终结果
图2.4.10、新增swap分割的最终结果

某些安装程式在你没有指定swap为记忆体的1.5~2倍时会有警告讯息的告知，此时只要将警告讯息忽略，按下一步即可。 好了，如果一切都顺利完成的话，那么你就会看到如下的分割结果啰！

详细的分割参数结果
图2.4.11、详细的分割参数结果
  • 建立/home目录的分割槽

让我们继续完成最后一个分割槽的分割吧！继续按下上图的‘新增’然后完成如下资料的填写并按下确定：

新增/home分割槽的最终结果
图2.4.12、新增/home分割槽的最终结果

分割的最终结果终于出炉！如下图所示。你会发现到系统自动的将/dev/hda4变成延伸分割喔！然后将所有容量都给/dev/hda4， 并且将swap分配到/dev/hda5去了！这就是分割的用途！这也是为什么我们要在第三章花这么多时间来解释分割的原因啦！

详细的分割参数结果
图2.4.13、详细的分割参数结果

到此为止，我们这个练习机的分割就已经完成了！底下我们额外介绍如果你还想要删除与建立软体磁碟阵列， 该如何在安装时就制作呢？

  • 删除已存在分割的方法：(Option, 看看就好别实作)

如果你想要将某个分割槽删除，或者是你刚刚错误指定了一个分割槽的相关参数，想要重新处理时，要怎办啊？ 举例来说，我想要将上图的/dev/hda5那个swap分割槽删除掉。好，先将滑鼠指定到swap上面点一下，如下图所示， 该分割槽会反白，然后再按下‘删除’此时会如下图所示跳出一个视窗，在该视窗内按下‘删除’这个分割槽就被删除啦！

删除已存在分割的方法
图2.4.14、删除已存在分割的方法
  • 建立软体磁碟阵列的方法：(Option, 看看就好别实作)

如果你知道什么是磁碟阵列的话，那么底下的步骤可以让你建置一个软体模拟的磁碟阵列喔！ 由于磁碟阵列在后面第十五章、进阶档案系统管理才会讲到，这里只是先告诉您， 其实磁碟阵列可以在安装时就建置了呢！首先，同样的，在分割操作按键区按下‘新增’，然后出现下图，选择‘Software RAID’项目，并填入1000MB的大小，按下确定！

软体磁碟阵列分割槽的建立示意图
图2.4.15、软体磁碟阵列分割槽的建立示意图

上述的动作‘请要连续作两次’之后，就会出现如下图示。注意喔，由于我们尚未讲到RAID的等级(level)， 所以你应该还不了解为什么要作两次。没关系，先有个底，读完整份资料后再回来查阅时，你就会知道如何处理了。 两个软体RAID的分割资讯如下图所示：

已具有软体磁碟阵列分割槽的状态下建置RAID
图2.4.16、在已具有软体磁碟阵列分割槽的状态下建置RAID

由于我们已经具有软体RAID的分割槽，此时才能按下‘RAID’来建立软体磁碟阵列的装置。 如上图所示，看到了两个软体磁碟阵列，然后按下右上方的RAID按钮，就会出现如下图示：

图2.4.17、建立软体磁碟阵列/dev/md0

与一般装置档名不同的，第一个软体磁碟阵列的装置名称为/dev/md0。 如上图所示，你会发现到系统多出了一个怪怪的装置名称，这个档名就是未来给我们格式化用的装置啦！ 而这个软体磁碟阵列的装置其实是利用实体的分割槽来建立的哩。按下上图的‘确定’后就会出现如下的图示：

软体磁碟阵列的挂载点、等级与档案系统格式
图2.4.18、软体磁碟阵列的挂载点、等级与档案系统格式

由于我们仅建立两个软体磁碟阵列分割槽，因此在这边只能选择RAID0或RAID1。我们以RAID0来作为示范， 你会发现中间白色框框的地方会有两个可以选择的分割槽，那就是刚刚我们建立起来的software RAID分割槽。 我们将这个/dev/md0挂载到/myshare目录去！然后再按下确定吧！

最终细部分割参数示意图
图2.4.19、最终细部分割参数示意图

最终的结果就像上图所示，在实际分割区就会显示/dev/md0，而由于这个装置是Linux系统模拟来的， 所以在磁柱号码(开始/结束)的地方就会留白！这样可以了解吗？

小标题的图示 5. 开机管理程式、网路、 时区设定与root密码
  • 开机管理程式的处理

分割完成后就会进入开机管理程式的安装了，目前较新的Linux distributions大多使用grub管理程式， 而且我们也必须要将他安装到MBR里面才行！因此如下图所示，在1号箭头的地方就得要选择整部磁碟的档名 (/dev/hda)， 其实那就代表该颗硬碟的MBR之意。

下图中2号箭头所指的就是开机时若出现选单，那么选单内就会有一个名为‘CentOS’的可选择标签。 这个标签代表他根目录所在的位置为/dev/hda2这样的意思。而如果开机内5秒钟不按下任何按键，就预设会以此一标签来开机。

如果你还想要加入/编辑各个标签，那可以按下3号箭头所指的那三个按键喔！

开机管理程式的处理
图2.5.1、开机管理程式的处理

如果你觉得‘CentOS’这个选单不好看，想要自订自己的选单名称，那么在上图中先点一下‘CentOS’那个标签， 然后按下3号箭头所指的‘编辑’按钮，就会出现如下画面。在如下画面中可以填写你自己想要的选单名称喔！ 鸟哥是很讨厌麻烦的，所以就使用预设的选单名称而已。

编辑开机选单的标签名称
图2.5.2、编辑开机选单的标签名称

如果你的电脑系统当中还有其他的‘已安装作业系统’时，而且你想要让Linux在开机的时候就能够让你选择不同的作业系统开机， 那么就如同下图所示，你可以先按下‘新增’，然后在2号箭头的地方选择其他作业系统所在的分割槽， 并在3号箭头处填入适当的名称(例如WindowsXP等等)，按下确定就能够在开机时新增一个选单啰！

新增开机选单标签的示意图
图2.5.3、新增开机选单标签的示意图

如果你是个很龟毛的人，你希望你的系统除非你自己在电脑前面开机并输入密码后才能开始开机流程的话， 那么可以如同下图所示加入密码管理机制。不过grub开机管理程式加入密码虽然有好处， 但是如此一来我们就无法在远端重新开机了，因此鸟哥暂时不建议你设定开机管理程式的密码喔！ 底下只是一个示意图，让你知道如何加入密码管理而已！

设定开机管理程式的密码
图2.5.4、设定开机管理程式的密码
  • 将开机管理程式安装到boot sector(Option, 看看就好，不要实作)

如果你因为特殊需求，所以Linux的开机管理程式无法安装到MBR时，那就得要安装到每块partition的开机磁区(boot sector)了。果真如此的话，那么如同下图所示，先勾选‘设定进阶开机管理程式选项’的地方：

进阶开机管理程式选项
图2.5.5、进阶开机管理程式选项

然后就会出现如下的图示，预设Linux会将开机管理程式安装到MBR，如果你想要安装到不同的地方去， 请如同下图的箭头处，选择‘开机分割区的第一个磁区’就是该分割槽的boot sector啰！

将开机管理程式安装到boot sector的方法
图2.5.6、将开机管理程式安装到boot sector的方法
  • 网路参数的给予

如果你的网路卡可以被安装程式捉到的话，那么你就可以设定网路参数了！例如下图所示的模样。 目前各大版本几乎都会预设网路卡IP的取得方式为‘自动取得IP’，也就是所谓的‘DHCP’网路协定啦！ 不过，由于这个协定需要有DHCP伺服器的辅助才行，如果你的环境没有种伺服器存在的话， 那开机的过程中可能会等待一段时间。所以通常鸟哥都改成手动设定。不过，无论如何，都要与你的网路环境相同才是。

设定网路参数的过程
图2.5.7、设定网路参数的过程

在上图中我们可以看到所有的网路参数都是经过dhcp取得的，所以通通不需要设定任何项目。 至于网路装置内的白色框框中仅有一张网卡的显示。由于我们要将IP改为手动给予， 但我们尚未谈到伺服器与网路基础，所以这里你不懂也没有关系，请先按照先前我们所规划的IP参数去填写即可。 请按下上图的‘编辑’按钮，就会出现如下的画面了：

手动编辑网路IP参数
图2.5.8、手动编辑网路IP参数

在上图中的最上方我们可以看到这张网路卡的制造商(AMD)与网卡卡号(Hardware address:)， 并且我们的Linux也支援IPv4与IPv6(第四版与第六版的IP参数)。因为目前(2009)支援IPv6的环境还是很少， 所以我们先将IPv6的支援取消(3号箭头处)。

至于IPv4的IP参数给予，如上图所示，你得先在1号箭头处点选手动设定(Manual configuration)， 然后在2号箭头处输入正确的IP与子遮罩网路(Netmask)，最后再按下确定即可。处理完毕后就会显示如下的图示了：

设定网路参数的过程
图2.5.9、设定网路参数的过程

完成IP参数的设定后，接下来是这部练习机的主机名称，请输入你喜欢的主机名称。 因为目前我们的主机尚未能与网际网路接轨，所以你可以随便填写任何你喜欢的主机名称。 主机名称通常的格式都是‘主机名.网域名’，其实就有点像是‘名字.姓氏’的样子。 为了不与网际网路的其他主机冲突，因此这里鸟哥使用我自己的名字作为主机名！ 填写完毕后请按下‘下一步’吧！

未设定闸道器的警告讯息
图2.5.10、未设定闸道器的警告讯息

咦！怎么会出现如同上图所示的错讯息呢？别担心，因为我们的主机还不能够连上Internet， 所以出现这个错误讯息是正常的。请按下‘继续’来往后处理吧！

  • 时区的选择

时区是很重要的！因为不同的时区会有不一样的日期/时间显示嘛！可能造成档案时间的不一致呢， 所以，得要告知系统我们的时区在哪里才行啊！ 如下图所示，你可以直接在1号箭头处选择亚洲台北， 或直接用滑鼠在地图上面点选也可以！要特别注意的是那个‘UTC’，他与所谓的‘日光节约时间’有关。 不过，我们不需要选择这个，不然的话，还可能造成时区被影响，导致系统显示的时间会与本地时间不同。

时区的选择
图2.5.11、时区的选择
  • 设定root的密码

再来则是最重要的‘系统管理员的密码’设定啦！ 在Linux底下系统管理员的预设帐号名称为root，请注意，这个密码很重要！虽然我们是练习用的主机， 不过，还是请你养成良好的习惯，最好root的密码可以设定的严格一点。可以设定至少8个字元以上， 而且含有特殊符号更好，例如：I&my_dog之类，有点怪，但是对你又挺好记的密码！

设定root密码
图2.5.12、设定root密码
小标题的图示 6. 软体选择

一切都差不多之后，就能够开始挑选软体的安装啦！咦！我怎么知道我要什么套件？哈哈！ 您当然不可能会知道～知道的话.....就不会来这儿查阅资料了 @_@ 没有啦！开开玩笑....呼～好冷～～

关于软体的安装有非常多的想法，如果你是初次接触Linux的话，当然是全部安装最好。 如果是已经安装过多次Linux了，那么使用预设安装即可，以后有需要其他的软体时，再透过网路安装就好了！ 这样你的系统也会比较干净。但是在这个练习机的安装中，我们使用预设值加上CentOS提供的选项来安装即可。 如下图所示：

额外选择多的软体群组
图2.6.1、额外选择多的软体群组

如上图所示，你可以增加1号箭头所指的三个项目，然后在2号箭头处保持预设值，再给他下一步即可。 这样的安装对于初学者来说已经是非常OK的啦！

  • 额外的软体自订模式(Option, 进阶使用者可以参考)

在Linux的软体安装中，由于每个各别软体的功能非常庞大，很多软体的开发工具其实一般用户都用不到。 如果每个软体都仅释出一个档案给我们安装，那么我们势必会安装到很多不需要的档案。 所以，Linux开发商就将一项软体分成多个档案来给使用者选择。如果你想要了解每项软体背后的档案资料， 就可以如同下图所示，选择‘立即自订’来设定专属的软体功能。

软体自订安装的功能
图2.6.2、软体自订安装的功能

自订软体的画面如下所示，1号箭头处为软体群组，是开发商将某些相似功能的软体绑在一起成为一个群组。 你可以在1号箭头处选择你有兴趣的功能，然后在2号箭头处挑选该项目内的细项。如下图所示， 鸟哥挑选了‘程式开发’的群组后，在2号箭头处挑选了鸟哥有兴趣的‘开发工具’等， 而这些工具的意义在3号箭头处所指的白色框框中就会有详细的说明了。

自己选择所需软体的画面
图2.6.3、自己选择所需软体的画面

检查完毕后安装程式会去检查你所挑选的软体有没有冲突(相依性检查)，然后就会出现下列视窗， 告诉你你的安装过程写入到/root/install.log档案中，并且你刚刚选择的所有项目则写入到/root/anaconda-ks.cfg档案内。 这两个档案很有趣，安装完毕后你可以自己先看看。

准备开始安装
图2.6.4、准备开始安装

然后就是开始一连串的等待了！这个等待的过程与你的硬体以及选择的软体数量有关。 如下图所示，2号箭头处所指的则是安装程式评估的剩余时间这个时间不见得准啦！看看就好！

安装过程的画面示意图
图2.6.5、安装过程的画面示意图

安装完毕并按下‘Reboot’重新开机后，荧幕会出现如下的讯息，这是正确的资讯，不要担心出问题啊！ 此时请拿出你的DVD光碟，让系统自动重新开机。其他的后续设定，请参考下一小节呢！

安装完毕后，重新开机的示意图
图2.6.6、安装完毕后，重新开机的示意图
小标题的图示 7. 其他功能：RAM testing, 安装笔记型电脑的核心参数(Option)
  • 记忆体压力测试：memtest86

CentOS的DVD除了提供一般PC来安装Linux之外，还提供了不少有趣的东西，其中一个就是进行‘烧机’的任务！ 这个烧机不是台湾名产烧酒鸡啊，而是当你组装了一部新的个人电脑，想要测试这部主机是否稳定时， 就在这部主机上面运作一些比较耗系统资源的程式，让系统在高负载的情况下去运作一阵子(可能是一天)， 去测试稳定度的一种情况，就称为‘烧机’啦！

那要如何进行呢？同样的，放入CentOS的DVD到你的光碟中，然后用这片DVD重新开机，在进入到开机选单时， 输入memtest86即可。如下图所示：

RAM测试
图2.7.1、RAM测试

之后系统就会进入这支记忆体测试的程式中，开始一直不断的对记忆体写入与读出！ 如果烧机个一两天，这支程式还是不断的跑而没有因为任何原因来当机，表示你的记忆体应该还算稳定啦！ 如下所示。如果不想跑这支程式了，就按下箭头所指的‘ESC’处，亦即按下[Esc]按键，就能够重新开机啰！

RAM测试
图2.7.2、RAM测试

对memtest86有兴趣的朋友，可以参考如下的连结喔：

  • http://www.memtest.org/
  • 安装笔记型电脑或其他类PC电脑的参数

由于笔记型电脑加入了非常多的省电机制或者是其他硬体的管理机制，包括显示卡常常是整合型的， 因此在笔记型电脑上面的硬体常常与一般桌上型电脑不怎么相同。所以当你使用适合于一般桌上型电脑的DVD来安装Linux时， 可能常常会出现一些问题，导致无法顺利的安装Linux到你的笔记型电脑中啊！那怎办？

其实很简单，只要在安装的时候，告诉安装程式的linux核心不要载入一些特殊功能即可。 最常使用的方法就是，在使用DVD开机时，加入底下这些选项：

boot: linux nofb apm=off acpi=off pci=noacpi

apm(Advanced Power Management)是早期的电源管理模组，acpi(Advanced Configuration and Power Interface)则是近期的电源管理模组。这两者都是硬体本身就有支援的，但是笔记型电脑可能不是使用这些机制， 因此，当安装时启动这些机制将会造成一些错误，导致无法顺利安装。

nofb则是取消显示卡上面的缓冲记忆体侦测。因为笔记型电脑的显示卡常常是整合型的， Linux安装程式本身可能就不是很能够侦测到该显示卡模组。此时加入nofb将可能使得你的安装过程顺利一些。

对于这些在开机的时候所加入的参数，我们称为‘核心参数’，这些核心参数是有意义的！ 如果你对这些核心参数有兴趣的话，可以参考文后的参考资料来查询更多资讯(注2)。

大标题的图示 安装后的首次设定

安装完毕并且重新开机后，系统就会开始以Linux开机啰！但事实上我们的安装尚未完成喔！ 因为还没有进行诸如防火墙、SELinux、惯用登入帐号的设定等等。在X Window里面还有重要的音效装置也还没有设定哩！ 所以，底下我们就来处理首次进入X Window的设定吧！

重新开机后，一开始荧幕会出现如下的讯息，这个讯息是说，你如果没有在数秒钟之内按下任意按键， 那么系统就会以CentOS (2.6.18-128.el5)那个开机选项进入开机的流程喔。

开机过程的读秒画面
图3.1、开机过程的读秒画面

那如果你真的按下了任意按键，荧幕就会出现如下的讯息，该讯息是由grub开机管理程式所控管的， 目前鸟哥的系统里面也只有一个选项，那就是刚刚你在读秒画面中看到的那个项目。 如果你还有想要加入什么特殊的参数在开机的过程当中，可以使用下图中箭头所指的地方，利用几个简单的项目来处理喔！ 这部份我们会在第二十章、开机管理程式中谈到的！如果你有设定多重开机， 那么在下图的画面中就会看到多个选单啰！

grub管理程式的选单画面
图3.2、grub管理程式的选单画面

一切都没有问题就按下[Enter]吧！此时grub就会去读取核心档案来进行硬体侦测，并载入适当的硬体驱动程式后， 就开始进行CentOS各项服务的启动了。下图中箭头有指到/vmlinuz-2.6.18-128.el5吧？那就是我们的Linux核心档案啦！ 至于出现Welcome字样后，就是开始执行各项服务的流程了。

开机过程的核心侦测与服务启动
图3.3、开机过程的核心侦测与服务启动

接下来系统会开始出现图形介面，如下图所示。如果你想要知道系统目前实际在进行什么服务的启动时， 可以按下箭头所指的‘详细资料’。

开机进入图形介面的示意图
图3.4、开机进入图形介面的示意图

按下‘详细资料’就会出现下图，因为安装的时候我们选择的是中文，此时启动各项服务就会以中文来显示啰！很不错吧！ ^_^

查阅详细开机资讯的示意图
图3.5、查阅详细开机资讯的示意图

怕了吧？有这么多不知名的咚咚已经在你的Linux里面启动了呢！里面其实有很多是我们不需要的， 在未来你了解了Linux相关的知识之后，就可以将那些不需要的程式(或称为服务)给他关掉了。目前还不需要紧张， 因为我们还没有连上Internet呐！还不需要太紧张啦！ ^_^

好了，接下来让我们开始来设定X Window的相关功能吧！设定很简单，用滑鼠点一点就可以完成了！别担心！

  1. 防火墙与SELinux

    首先，系统会进入欢迎画面，如下图所示。下图的左手边则是等一下需要设定的项目有哪些。如果没有问题的话，按‘下一页’继续设定。

    首次设定的欢迎画面
    图3.6、首次设定的欢迎画面

    因为我们目前是Linux练习机而已，因此，建议你将防火墙的功能先取消，反正我们也还没有连上Intenet嘛！ 所以请在下图的箭头处将他点选成为‘停用’的状态。

    关闭防火墙的设定项目
    图3.7、关闭防火墙的设定项目

    因为我们停用防火墙，安装程式很好心的会提示我们：‘你没有启用防火墙喔！’ 没关系！继续吧！ 因为我们在伺服器篇里面会提到自己设定的防火墙功能啊！所以如下图箭头所指，点选‘是’即可继续。

    关闭防火墙的警告讯息
    图3.8、关闭防火墙的警告讯息

    接下来如下图所示出现一个‘SELinux’的东西，这个SELinux可就重要了！ 他是Security Enhanced Linux的缩写，这个软体是由美国国家安全局(National Security Agency, NAS,注3)所开发的，这东西并不是防火墙喔！SELinux是一个Linux系统存取控制(Access control)的细部设定， 重点在于控制程式对于系统档案的存取权限限制。由于CentOS 5.x以后的Linux版本对于SELinux的设定已经非常的妥当了， 因此建议您务必要打开这个功能！这部份我们会在第十七章继续说明的。

    启动SELinux的示意图
    图3.9、启动SELinux的示意图

  2. Kdump与时区的校正

    完成了防火墙与SELinux的选择后，接下来会出现如下的Kdump视窗。什么是Kdump呢？这个Kdump就是，当核心出现错误的时候， 是否要将当时的记忆体内的讯息写到档案中，而这个档案就能够给核心开发者研究为啥会当机之用。 我们并不是核心开发者，而且记忆体内的资料实在太大了，因此常常进行Kdump会造成硬碟空间的浪费。 所以，这里建议不要启动Kdump的功能喔！

    关闭Kdump示意图
    图3.10、关闭Kdump示意图

    再来就是时间的确认啦！先看一下系统的日期与你的手表一致否？若不一致请自行调整他。

    时区与时间的校正
    图3.11、时区与时间的校正

    常常手动调整时间很讨厌吧！尤其是如果你的系统是老电脑，一关机BIOS电力不足就会造成系统时间的错乱时！真讨厌～ 此时我们可以使用网路来进行时间的校正喔！如下图所示，先按下1号箭头所指处，然后勾选2号箭头指的‘启用网路时间通讯协定’， 接下来按下3号箭头处所指的‘新增’来增加时间伺服器喔！

    网路校时设定
    图3.12、网路校时设定

    按下‘新增’后就会出现如下画面，由于系统预设给予的三部网路上面可以提供人家进行时间校正的主机都不在台湾， 为了快速的校正时间，建议你可以将下图中前三个主机都删除，只保留后来我们自己加上的台湾的时间伺服器， 就是：tock.stdtime.gov.tw这一部即可。输入完毕后请按下[Enter]吧！

    加入网路时间伺服器的方式
    图3.13、加入网路时间伺服器的方式

    由于我们的Linux练习机还没有连上Internet，所以当你加上上图所指向的那部主机时，就会出现如下图的错误啦！ 没关系，不要理他！那是正常的！请按下‘是’来继续吧！

    未连上Interenet的警告讯息
    图3.14、未连上Interenet的警告讯息

  3. 建立一般使用者

    一般来说，我们在操作Linux系统时，除非必要，否则不要使用root的权限，这是因为管理员(root)的权限太大了！ 我们可能会随时不小心搞错了一个小咚咚，结果却造成整个系统的挂点去.....所以，建立一个一般身份使用者来操作才是好习惯。 举例来说，鸟哥都会建立一个一般身份使用者的帐号(例如底下的vbird)，用这个帐号来操作Linux， 而当我的主机需要额外的root权限来管理时，才使用身份转换指令来切换身份成为root来管理维护呢！^_^

    如下图所示，鸟哥建立的登入帐号名称为vbird，而全名仅是一个简易的说明而已，那个地方随便填没关系(不填也无所谓！)。 但是两个密码栏均需填写，荧幕并不会显示出你输入的字元，而是以黑点来取代。两个栏位必须输入相同的密码喔！

    一般帐号的建立
    图3.15、一般帐号的建立

  4. 音效卡与其他软体的安装

    如果你的主机有音效卡，而且Linux也能够正确的捉到该音效卡时，就会出现如下画面。如果你想要知道到底这个音效卡能否顺利运作， 如下图箭头所指处，按下测试就能够听听有没有声音的输出啦！

    音效卡的测试
    图3.16、音效卡的测试

    最后，如果你还有自己的第三方软体需要安装，才放入光碟继续安装。我们当然没有额外的光碟，所以下图不用理他！

    额外的软体光碟安装
    图3.17、额外的软体光碟安装

到此为止，我们的Linux就安装与设定好了，接下来就能够登入Linux啦！如果没有特殊需求的话， 请开始阅读下一章首次开关机与线上求助(man page)吧！

大标题的图示 多重开机安装流程与技巧

有鉴于自由软体的蓬勃发展以及专利软体越来越贵，所以政府单位也慢慢的希望各部门在选购电脑时， 能够考量同时含有两种以上作业系统的机器了。加上很多朋友其实也常常有需要两种不同作业系统来处理日常生活与工作的事情。 那我是否需要两部主机来操作不同的作业系统？不需要的，我们可以透过多重开机来选择登入不同的作业系统喔！ 一部机器搞定不同作业系统哩。

不过，就如同鸟哥之前提过的，多重开机系统是有很多风险存在的，而且你也不能随时变动这个多重作业系统的开机磁区， 这对于初学者想要‘很猛烈的’玩Linux是有点妨碍～所以，鸟哥不是很建议新手使用多重开机啦！ 所以，底下仅是提出一个大概，你可以看一看，未来我们谈到后面的章节时，你自然就会有‘豁然开朗’的笑容出现了！ ^_^

小标题的图示 新主机仅有一颗硬碟

如果你的系统是新的，并且想要安装多重作业系统时，那么这个多重作业系统的安装将显的很简单啊！ 假设以目前主流的160GB硬碟作为规划好了，而你想要有WindowsXP, WindowsXP的资料碟, Linux, Swap及一个共用分割槽， 那我们首先来规划一下硬碟分割吧！如果是这样的需求，那你可以这样规划：

Linux装置档名 | Windows装置 | 实际内容 | 档案系统 | 容量(GB)
/dev/sda1 | C | Windows系统 | NTFS | 30
/dev/sda2 | D | Windows资料碟 | NTFS | 60
/dev/sda3 | 不要挂载 | Linux根目录(/) | Ext3 | 50
/dev/sda5 | 不要挂载 | 记忆体置换空间swap | swap | 1
/dev/sda6 | E | Windows/Linux共用 | vfat | 其他所有

接下来就是系统的安装了！安装一定要先装WindowsX再装Linux才好！顺序搞错了会很麻烦喔！ 基本上，你可以这样安装：

  1. 先装Windows XP
    在这个阶段依旧使用Windows XP光碟开机来安装，安装到了分割时，记得依照上述表格的规划制作出两个主要分割槽， 并且将档案系统格式化为NTFS，然后再将Windows XP装到C槽当中。理论上，此时仅有/dev/sda1, /dev/sda2而已喔！

  2. 安装CentOS 5.x
    再来则是安装Linux啰，安装时要注意的地方也是在分割的地方，请回到前一小节的磁碟分割部分来进行分割设定。另外一个要注意的地方则是在开机管理程式的地方， 同样回到前一小节看一下开机管理程式是如何指定开机选单的！ 尤其是‘预设开机’项目，是预设要Windows还是Linux开机呢？这需要你的选择喔！而且grub务必要安装到MBR上头。

  3. 后续维护的注意事项
    多重开机设定完毕后请特别注意， (1)Windows的环境中最好将Linux的根目录与swap取消挂载，否则未来你打开档案总管时， 该软体会要求你‘格式化！’如果一个不留神，你的Linux系统就毁了。 (2)你的Linux不可以随便的删除！ 因为grub会去读取Linux根目录下的/boot/目录内容，如果你将Linux移除了，你的Windows也就无法开机了！ 因为整个开机选单都会不见喔！
小标题的图示 旧主机有两颗以上硬碟

如果你的主机上面已经有Windows了，为了担心与Linux冲突，所以你想要加装一颗新的硬碟来安装Linux，这样好吗？ 也是不错的想法啦！不过你得要注意的是，整部个人电脑仅会有一个MBR而已！虽然你有两颗硬碟。

为什么有两颗硬碟却只有一个MBR呢？因为你得在BIOS里面调整开机的装置，只有第一个可开机装置内的MBR会被系统主动读取。 所以啰，理论上，你不会将Windows的开机管理程式安装到/dev/sda而将Linux安装到/dev/sdb上头， 而是得要将grub安装到/dev/sda上，透过他来管理Windows/Linux才行，即使你的Linux是放到/dev/sdb这颗硬碟上面的。

比较聪明的朋友会想到‘我可以调整BIOS内的开机装置，使得要进入不同的作业系统时，就用不同的开机装置来开机， 如此一来应该就能够避免将grub安装到/dev/sda了吧？’这个想法本身是OK的，只不过， 因为SATA的装置档名是利用侦测的顺序来决定的，所以你如果这样调整来调整去的话， 你的SATA装置档名可能会产生不同，这对于linux的运作会有问题，因此如果这样随时调整BIOS时， 可能还是会造成无法开机成功的问题！

所以鸟哥还是建议BIOS内的开机顺序不要改变，然后以grub来控制全部的开机选单较佳！ 不过，如果你觉得grub不是这么好用，那怎办？没关系，你可以使用spfdisk这个国人写的开机管理程式来管理喔！ 如果你真的想要使用spfdisk来管理开机选单的话，那你在安装Linux的时候，记得将grub安装到开机磁区(boot sector)， 然后重新开机进入Windows后，以spfdisk来设定正确的开机选单即可。spfdisk的官网与鸟哥之前写的教学文章可以参考：

  • spfdisk官网：http://spfdisk.sourceforge.net/
  • 鸟哥的spfdisk教学：http://linux.vbird.org/linux_basic/0140spfdisk.php
小标题的图示 旧主机只有一颗硬碟

如果你想要在你的Windows主机上面多加一个Linux作业系统呢？那就得要注意啦！ 因为Windows/Linux不能共存在同一个partition上！而Linux的根目录最好使用Ext3这种Linux支援的档案系统。 所以，你就得要清出来一个空的分割槽给Linux使用才行喔。

举例来说，如果你的系统只有C槽，那能不能安装Linux呢？很抱歉！没办法！如果你的系统有C与D槽， 但是你又想要保留一个资料槽给Windows使用，那你就得要这样做：

  1. 先将D槽的资料搬移出来，不论是搬到随身碟还是C槽中暂存；
  2. 在Windows的逻辑分割管理员中，将D槽删除并重建成两个分割槽，一个是D一个是E；
  3. 将D槽格式化为NTFS(或FAT32)，然后将刚刚的备份资料搬回D槽去；
  4. E槽不要挂载，这是Linux预计要安装的系统槽。

这种情况是比较麻烦啦，因为资料需要搬来搬去的，需要很注意移动的过程喔！ 否则，很容易将自己好几年辛苦工作的资料一不小心的全部删除！那就欲哭无泪了！

大标题的图示 关于大硬碟导致无法开机的问题

有些朋友可能在第一次安装完Linux后，却发现无法开机的问题，也就是说，确实可以使用上面鸟哥介绍的方法来安装CentOS5， 但就是无法顺利开机，只要重新开机就会出现类似底下的画面：

# 前面是一些奇怪的提示字元啊！

grub> _

然后等待你输入一些资料～如果不幸你发生了这样的问题，那么可能的主要原因就是......

  • 你的主机板BIOS太旧，导致捉不到您的新硬碟；
  • 你的硬碟容量太大了(例如超过120 GB以上)，但是主机板并不支援～

如果真的是这样，那就麻烦了～你可能可以这样做：

  • 前往您主机板的官方网站，下载最新的BIOS档案，并且更新BIOS吧！
  • 将你硬碟的cylinders, heads, sectors抄下来，进入BIOS内，将硬碟的型号以使用者设定的方式手动设定好～

当然还有一个最简单的解决方法，那就是：重新安装Linux，并且在磁碟分割的地方，建立一个100MB左右的分割槽， 将他挂载到/boot这个挂载点。并且要注意，/boot的那个挂载点，必须要在整个硬碟的最前面！ 例如，必须是/dev/hda1才行！

至于会产生这个问题的原因确实是与BIOS支援的硬碟容量有关，处理方法虽然比较麻烦，不过也只能这样做了。 更多与硬碟及开机有关的问题，鸟哥会在第二十章开机与关机程序再进一步说明的啦！

大标题的图示 重点回顾
  • 不论你要安装什么样的Linux作业系统角色，都应该要事先规划例如分割、开机管理程式等；
  • 建议练习机安装时的磁碟分割能有/, /boot, /home, swap四个分割槽；
  • 调整开机装置的顺序必须要重新开机并进入BIOS系统调整；
  • 安装CentOS 5.x的模式至少有两种，分别是图形介面与文字介面；
  • 若安装笔记型电脑时失败，可尝试在开机时加入‘linux nofb apm=off acpi=off’来关闭省电功能；
  • 安装过程进入分割后，请以‘自订的分割模式’来处理自己规划的分割方式；
  • 在安装的过程中，可以建立软体磁碟阵列(software RAID)；
  • 一般要求swap应该要是1.5~2倍的实体记忆体量；
  • 即使没有swap依旧能够安装与运作Linux作业系统；
  • CentOS 5.x的开机管理程式为grub，安装时最好选择安装置MBR中；
  • 没有连上Internet时，可尝试关闭防火墙，但SELinux最好选择‘强制’状态；
  • 设定时不要选择启动kdump，因为那是给核心开发者查阅当机资料的；
  • 可加入时间伺服器来同步化时间，台湾可选择tock.stdtime.gov.tw这一部；
  • 尽量使用一般用户来操作Linux，有必要再转身份成为root即可。
大标题的图示 本章习题
( 要看答案请将滑鼠移动到‘答：’底下的空白处，按下左键圈选空白处即可察看 )
问答题部分：
  • Linux的目录配置以‘树状目录’来配置，至于磁碟分割槽(partition)则需要与树状目录相配合！ 请问，在预设的情况下，在安装的时候系统会要求你一定要分割出来的两个Partition为何？
    就是根目录‘/’与记忆体置换空间‘Swap’
  • 若在分割的时候，在 IDE1 的 slave 硬碟中，分割‘六个有用’的分割槽 (具有 filesystem 的) ，此外，已知有两个 primary 的分割类型！请问六个分割槽的档名？
    /dev/hdb1(primary)
    /dev/hdb2(primary)
    /dev/hdb3(extended)
    /dev/hdb5(logical 底下皆为 logical)
    /dev/hdb6
    /dev/hdb7
    /dev/hdb8
    请注意，5-8 这四个 logical 容量相加的总和为 /dev/hdb3！
  • 一般而言，在RAM为64 MB或128 MB的系统中，swap要开多大？
    Swap 可以简单的想成是虚拟记忆体，通常他的建议大小为 RAM 的两倍， 但是实际上还是得视您的主机规格配备与用途而定。约两倍的 RAM ，亦即为 128 MB 或 256 MB ，可获得较佳效能！
  • 什么是GMT时间？台北时间差几个钟头？
    GMT 时间指的是格林威治时间，称为标准的时间，而台北时间较 GMT 快了 8 小时！
  • 软体磁碟阵列的装置档名为何？
    RAID : /dev/md[0-15];
  • 如果我的磁碟分割时，设定了四个 Primary 分割槽，但是磁碟还有空间，请问我还能不能使用这些空间？
    不行！因为最多只有四个 Primary 的磁碟分割槽，没有多的可以进行分割了！且由于没有 Extended ，所以自然不能再使用 Logical 分割
  • 硬碟的第零轨含有MBR及partition table，请问，partition 的最小单位为(磁柱、磁头、磁轨)
    为 Cylinder (磁柱)，所以 partition 的大小为磁柱大小的倍数。
大标题的图示 参考资料与延伸阅读
  • 注1：Virtualbox为一个虚拟机器的软体，可以在一部机器上面同时运作多个作业系统。 鸟哥是在Windows XP上面安装Virtualbox本版来进行CentOS 5.x的捉图。其官网如下：
    http://www.virtualbox.org/
  • 进阶记忆体测试网站：http://www.memtest.org/
  • 注2：更多的核心参数可以参考如下连结：
    http://www.faqs.org/docs/Linux-HOWTO/BootPrompt-HOWTO.html
    对于安装过程所加入的参数有兴趣的，则可以参考底下这篇连结，里面有详细说明硬体原因：
    http://polishlinux.org/choose/laptop/
  • 注3：SELinux是由美国国家安全局开发出来的，SELinux是被整合到Linux核心当中， SELinux并非防火墙，他是一个存取权限控制的模组。 最早之前SELinux的开发是有鉴于系统常常会被一般使用者误用而造成系统资料的安全性问题， 因此加上这个模组来防止系统被终端用户不小心滥用系统资源喔！详细的说明可以参考底下的连结：
    http://www.nsa.gov/selinux/
  • SPFdisk的官网：http://spfdisk.sourceforge.net/
2008/08/21：旧的FC4安装文章被移到到此处
2008/09/02：经过过去两个星期的忙碌，终于完成这篇安装说明！
2009/08/11：重新以 CentOS 5.3 的 DVD 来捉图解释！


鸟哥的 Linux 私房菜 -- 基础学习篇

为取得较佳浏览结果，请爱用 firefox 浏览本网页
鸟哥的 Linux 私房菜馆 | Linux 基础文件 | Linux 架站文件 | Linux 企业运用 | 安全管理 | 新手讨论 |

第五章、首次登入与线上求助 man page
最近更新日期：2009/08/17
终于可以开始使用Linux这个有趣的系统了！由于Linux系统使用了非同步的磁碟/记忆体资料传输模式，同时又是个多人多工的环境， 所以你不能随便的不正常关机，关机有一定的程序喔！错误的关机方法可能会造成磁碟资料的损毁呢！ 此外，Linux有多种不同的操作方式，图形介面与文字介面的操作有何不同？ 我们能否在文字介面取得大量的指令说明，而不需要硬背某些指令的选项与参数等等。这都是这一章要来介绍的呢！

1. 首次登入系统
    1.1 首次登入CentOS 5.x图形介面
1.2 GNOME的操作与登出
1.3 KDE的操作与登出
1.4 X Window与文字模式的切换
1.5 在终端介面登入linux
 2. 文字模式下指令的下达
    2.1 开始下达指令, 语系的支援
2.2 基础指令的操作, date, cal, bc
2.3 重要的几个热键[Tab], [ctrl]-c, [ctrl]-d
2.4 错误讯息的查看
 3. Linux系统的线上求助man page与info page
    3.1 man page
3.2 info page
3.3 其他有用的文件(documents)
 4. 超简单文书编辑器： nano
5. 正确的关机方法: sync, shutdown, reboot, halt, poweroff, init
6. 开机过程的问题排解
7. 重点回顾
8. 本章习题
9. 参考资料与延伸阅读
10. 针对本文的建议：http://phorum.vbird.org/viewtopic.php?t=23877
大标题的图示 首次登入系统

登入系统有这么难吗？并不难啊！虽然说是这样说，然而很多人第一次登入Linux的感觉都是‘接下来我要干啥？’如果是以图形介面登入的话，或许还有很多好玩的事物， 但要是以文字介面登入的话，面对着一片黑压压的荧幕，还真不晓得要干嘛呢！为了让大家更了解如何正确的使用Linux， 正确的登入与离开系统还是需要说明的！

小标题的图示 首次登入CentOS 5.x图形介面

开机就开机呀！怎么还有所谓的登入与离开呀？不是开机就能够用电脑了吗？ 开什么玩笑，在Linux系统中由于是多人多工的环境，所以系统随时都有很多任务在进行，因此正确的开关机可是很重要的！ 不正常的关机可能会导致档案系统错乱，造成资料的毁损呢！这也是为什么通常我们的Linux主机都会加挂一个不断电系统啰！

如果在第四章一切都顺利的将CentOS 5.x完成安装并且重新开机后， 应该就会出现如下的等待登入的图形画面才对。画面的左上方是CentOS 5的distribution说明， 而1号箭头所指处的四个文字则是可以改变工作环境的地方，2号箭头说明今天的日期/时间与主机名称(www.vbird.tsai)， 3号箭头就是我们可以使用帐号登入的输入框框啰。

X等待登入的画面
图1.1.1、X等待登入的画面

让我们来了解一下上图1号箭头所指的那四个功能吧！先点选一下‘语言’按钮，你会发现荧幕出现很多可以选择的语系资料！ 鸟哥撷取部分画面如下所示。在下图中你可以选择不同的中文或者是其他语言，等一下你登入后， 荧幕就会显示你所选择的语系画面了。不过要注意的是，如果你选择的语系的软体档案并没有被安装， 那么登入系统后就会出现很多乱码啊！如下图所示，鸟哥先选择台湾的繁体中文，然后按下‘改变语言’按钮即可。

选择语系的画面
图1.1.2、选择语系的画面

接下来让我们按一下‘作业阶段’按钮吧！按下作业阶段后荧幕就会出现如下的画面。 所谓的作业阶段指的是你可以使用不同的图形介面来操作整个Linux系统。 这个图形介面并不是只有将桌面背景更改而已，而是整个显示、控制、管理、图形软体都不相同了！ 非常的好玩！目前CentOS 5.x预设至少就提供GNOME/KDE这两种图形介面(我们称为视窗管理员, Window Manager, 注1)。 如下图所示。CentOS 5.x预设使用的是GNOME这个玩意儿，如果你没有改变的话，那等一下就会登入GNOME的图形介面啰。

更改作业阶段的视窗示意图
图1.1.3、更改作业阶段的视窗示意图

接下来准备要登入啦！我们在经过第四章的安装过程后，理论上现在会有两个可用的帐号，以鸟哥的安装为例， 我有root及vbird两个可用的帐号喔！那第四章我们也说过，最好不要使用root啦！因此， 鸟哥就在图1.1.1的地方开始用vbird来登入了，如下所示，记得输入完毕后要按‘Enter’喔！

输入使用者帐号的地方
图1.1.4、输入使用者帐号的地方

接着系统会要你输入密码，此时请在密码栏填入该帐号的密码！在你输入密码时该栏位会显示黑点来取代！ 这是为了保密啦！输入完毕后请按下‘Enter’开始登入啰！

输入密码的示意图
图1.1.5、输入密码的示意图

由于鸟哥在图1.1.2曾经修改过语系资料，因此系统就会询问你， 是否要将刚刚的设定变更成为预设值？还是只有这次登入才使用呢？你可以按下‘成为预设值’， 让你这次的决定套用到未来的操作喔！OK！让我们开始来玩一玩GNOME这个预设的视窗管理员吧！

询问是否将设定值更改为预设值的视窗
图1.1.6、询问是否将设定值更改为预设值的视窗
小标题的图示 GNOME的操作与登出

终于给他看到图形介面啦！真是很开心吧！如下图所示，整个GNOME的视窗大约分为三个部分：

  • 上方工作列(control panel)
    上半部有应用程式、位置与系统及快捷键的地方，可以看成是工作列，你可以使用滑鼠在1号箭头处 (应用程式) 点击一下， 就会有更多的程式集出现！然后移动滑鼠就能够使用各个软体了。至于3号箭头所指的地方，就是系统时间与声音调整。 另外，在3号箭头的左边不是有个打X的符号吗？那个是CentOS 5.x的线上更新系统(update)。由于我们尚未连上Internet， 所以这边就会显示X喔。

  • 桌面
    整个画面中央就是桌面啦！在桌面上预设有三个小按钮，例如箭头2所指的就是档案总管。你可以使用滑鼠连击两下就能够打开该功能。 其实电脑与个人资料夹都是档案总管啦！如果有执行各种程式，程式的显示也都是在桌面位置喔。

  • 下方工作列
    下方工作列的目的是将各工作显示在这里，可以方便使用者点选之用。其中4号箭头所指处为将所有工作最小化隐藏， 至于5号箭头处指的那四个玩意儿，就是四个虚拟桌面(Virtual Desktop)了！GNOME提供四个桌面给使用者操作， 你可以在那四个桌面随便点一点，看看有啥不同！尤其是当你有执行不同的程式时，就会发现他的功能啦！ ^_^
GNOME的视窗画面示意图
图1.2.1、GNOME的视窗画面示意图

Linux桌面的使用方法几乎跟Windows一模一样，你可以在桌面上按下右键就可以有额外的选单出现； 你也可以直接按下桌面上的‘个人资料夹’，就会出现类似Windows的‘档案总管’的档案/目录管理视窗， 里面则出现你自己的工作目录；好了，让我们点击一下‘应用程式’那个按钮吧！看看下拉式选单中有什么软体可用！ 如下图所示。你要注意的是，因为我们的Linux尚未连上Internet，所以线上更新系统会有警告讯息(2号箭头处)， 请你将他关闭吧！

Tips:
关于‘个人资料夹’的内容，记得我们之前说过Linux是多人多工的作业系统吧？ 每个人都会有自己的‘工作目录’，这个目录是使用者可以完全掌控的， 所以就称为‘使用者个人家目录’了。一般来说，家目录都在/home底下， 以鸟哥这次的登入为例，我的帐号是vbird，那么我的家目录就应该在/home/vbird/啰！ 		鸟哥的图示
应用程式的下拉式选单示意图
图1.2.2、应用程式的下拉式选单示意图
Tips:
那个线上升级的按钮不是不重要喔！而是因为我们尚未连上Internet所以这里才先将他略过的。 你的系统稳不稳定、安不安全与这个玩意儿相关性可大了！千万别小看他啰！ 有兴趣的朋友可以到google先搜寻一下yum这个机制来看看先！ ^_^ 因为你的Linux尚未线上更新过，所以先不要连上Internet喔！ 		鸟哥的图示
  • 使用档案总管

首先我们来了解一下常用的GNOME档案总管要怎么用？要说明的是，GNOME的档案总管其实称为‘鹦鹉螺(Nautilus)’， 只是我们比较习惯称呼档案总管就是了。^_^。当你在桌面中点选‘个人资料夹’就会出现如下图示。 预设鹦鹉螺是用小图示来显示档案，而且隐藏档也没有显示出来呢！ 所以你只会看到一个档案。注意1号箭头所指的地方，你可以按下那个小按钮来切换到不同的目录去喔！

鹦鹉螺档案总管的预设显示画面
图1.2.3、鹦鹉螺档案总管的预设显示画面

鸟哥还是比较喜欢清单式的将所有资料都列出来，所以我们的设定需要修正一下。 请在上图中按下‘编辑’点选‘偏好设定’后，会出现如下图示，请将箭头所在处的两个地方修订一下， 包括以清单显示及显示隐藏档喔！填完就按下右下角的‘关闭’即可。

鹦鹉螺档案总管的偏好设定视窗
图1.2.4、鹦鹉螺档案总管的偏好设定视窗

将原本的画面关闭再重开一个档案总管，请如下图所示，按下‘显示’选择‘显示隐藏档’及‘以清单方式显示’后， 就可以发现到好多档案啰！什么是隐藏档呢？其实档名开头为小数点‘.’的， 那个档案就是隐藏档了。所以在如下图的画面中，你会看到多出来的档案档名都是小数点开头的！

家目录下的隐藏档资料
图1.2.5、家目录下的隐藏档资料

除了自己的家目录之外，你可以在上图的左下角‘vbird’处点一下，然后选择根目录(/)，就会出现如下图示。 1号箭头告诉我们，这个vbird帐号无法登入该目录，所以有个红色的禁止图示；如果想要查阅某目录的内容， 如2号箭头所指处，你可以点一下三角形的图示，就能够将该目录内的资料捉出来了；最后，如同3号箭头所指的， 如果是出现纸张的图示，代表那是个档案而不是目录啰！

鹦鹉螺档案总管的目录/档案显示情况
图1.2.6、鹦鹉螺档案总管的目录/档案显示情况

  • 中文输入法

在CentOS 5.x当中所使用的中文输入法为SCIM软体，你要启动SCIM很简单，只要叫出任何一个能够输入文字的软体， 然后按下‘Ctrl’+‘Space(空白键)’就能够呼叫出来了！以下图为例，鸟哥执行‘附属应用程式’内的‘文字编辑’软体， 然后按下[ctrl]+[space]就出现下图。然后点一下图中的箭头所指处，你就会看到很多输入法了！ 比较有趣的是那个‘新酷音’输入法， 其实那就是大家常用的新注音啦！可以自动挑字的输入法！不错用喔！

SCIM中文输入法呼叫示意图
图1.2.7、SCIM中文输入法呼叫示意图

  • 登出GNOME

如果你没有想要继续玩X Window了，那就登出吧！如何登出呢？如下图所示，点选‘系统’内的‘登出’即可。 要记得的是，登出前最好将所有不需要的程式都关闭了再登出啊！

登出GNOME的按钮
图1.2.8、登出GNOME的按钮

会有一个确认视窗跑出来给我们确认一下，就给他点选‘登出’吧！

登出GNOME的确认视窗
图1.2.9、登出GNOME的确认视窗

请注意喔，登出并不是关机！只是让你的帐号离开系统而已喔！

  • 其他练习

底下的例题请大家自行参考并且实作一下喔！题目很简单，所以鸟哥就不额外抓图了！

  • 如何在上方工作列中新增其他的图示(icons)，让操作更方便？请尝试新增终端机图示；
  • 尝试浏览一下/etc这个目录内，有哪些档案/目录存在；
  • 请将/etc/crontab这个档案‘复制’到你的家目录中；
  • 请修改四个Virtual Desktop的底色图案，让他们都不相同；
  • 尝试修改荧幕解析度；
小标题的图示 KDE的操作与登出

玩过了GNOME之后，接下来让我们来了解一下KDE这个也是很常见的视窗管理程式吧！ 请回到图1.1.1中，在按下‘作业阶段’后请选择KDE，然后输入你的帐号密码来登入KDE的环境。 登入后的预设画面如下所示：

KDE登入后的预设画面
图1.3.1、KDE登入后的预设画面

上图中的箭头所指处的功能说明如下：

  • 桌面：上图中整个蓝色画面就是桌面。而一号箭头指的地方，一开始仅有垃圾桶而已，你可以自行增加其他的快速按钮在桌面！ 当有工作被执行时，该工作就是显示在这个桌面的区域中；

  • 工作列快捷键：2号箭头指的地方就是KDE的K选单！你给他按一下该选单就会出现更多的选项功能。 感觉上就是开始功能表啰！至于K选单的右边还有很多的快捷按钮，你可以自行点选看看；

  • 虚拟桌面：3号箭头所指的就是虚拟桌面。与GNOME相似的，CentOS的KDE也提供四个虚拟桌面。 你可以在各个桌面分别放置不同的底图哩！自己玩看看吧！

  • 工作列：4号箭头处，当你有执行任何工作时，该工作的图示就会显示到这个地方。

  • 小时钟：5号箭头所指的地方就是目前的时间。预设是数位时钟，你可以将他改为圆形的小时钟喔！

  • KDE内的档案管理

同样的，得先来了解一下档案管理的软体啊！在GNOME档案总管称为鹦鹉螺， 在KDE档案总管称为‘Konqueror, 征服家’。你可以按下‘K选单’然后选择‘家目录’，如下所示：

开启征服家的方式之一
图1.3.2、开启征服家的方式之一

启动征服家预设会出现如下图所示的画面：

KDE的征服家显示档案资料图示
图1.3.3、KDE的征服家显示档案资料图示

如上图所示为征服家的预设显示情况。画面的左边有点类似目录的列表，右边则是档案详细的资讯。 而征服家可以让你仅选择使用者可以随意应用的家目录 (2号箭头处) 或者是整个系统的档案资讯 (1号箭头处)。 征服家预设显示的是家目录啦。3号箭头处指出该目录内有哪些资讯，4号箭头则是详细的档案参数啦。 接下来请点选‘Root资料夹’吧！让我们瞧瞧整个档案系统有些什么东西？

根目录资料的显示
图1.3.4、根目录资料的显示

如上图所示，当你点选Root资料夹，并且按下/etc那个资料夹后，画面右边就会出现/etc资料夹的档案内容了。 一开始档案是以小图示来显示，如果你按下清单图示，就是上图中3号箭头处，那就会出现详细的档案资料了。 如下图所示：

档案资料的详细清单显示
图1.3.5、档案资料的详细清单显示

如上图所示，按下2号箭头处让加号 (+) 展开，你就能够看到更详细的档案资料。然后拉动4号箭头处的移动钮， 你就能够看到3号箭头处的更详细的资讯，包括档案大小、类型、更动时间、所属使用者与群组等参数资料。 其他更详细的资料就请自己玩玩吧！

  • 登出KDE或关机

如果不想要玩KDE了，请按下‘K选单’，然后选择‘登出’功能，就会出现如下图示：

KDE的登出画面示意图
图1.3.6、KDE的登出画面示意图

如上图所示，画面最上方的‘vbird’指的是你的帐号，如果你使用不同的帐号登入，这里就会有不同的帐号名称。 至于画面中的三个按钮功能为：

  • ‘关闭目前的工作阶段’：就是登出而已，会回到图1.1.1等待登入的画面；
  • ‘关闭电脑’：就是关机的功能；
  • ‘重新启动电脑’：就是重新开机的功能！

至于更多的X window相关的使用技巧，以及相关的软体应用，鸟哥这里就不多说了， 因为鸟哥着重在Linux作业系统的基础应用以及网路伺服器的应用啊！ ^_^ 如果你还真的有兴趣， 建议你可以前往杨老师的网站上看看喔！http://apt.nc.hcc.edu.tw/docs/FC3_X/ 。

  • 其他练习
  • 由‘K选单’-->‘寻找档案/资料夹’启动搜寻，并找寻档名为 crontab 的档案在哪里？
  • 工作列的最右方原本是数字形态的时钟，请将他改为图形显示的时钟；
  • 如何叫出控制台？控制台的‘区域性’里面的‘键盘配置’有何用处？

  • 重新启动X Window的快速按钮

一般来说，我们是可以手动来直接修改X Window的设定档的，不过，修改完成之后的设定项目并不会立刻被载入， 必须要重新启动X才行(特别注意，不是重新开机，而是重新启动X！) 。那么如何重新启动X呢？ 最简单的方法就是：

  • 直接登出，然后再重新登入即可；
  • 在X的画面中直接按下[Alt] + [Ctrl] + [Backspace]

第二个方法比较有趣，[backspace]是倒退键，你按下三个按钮后X Window立刻会被重新启动。 如果你的X Window因为不明原因导致有点问题时，也可以利用这个方法来重新启动X喔！^_^

小标题的图示 X window与文字模式的切换

我们前面一直谈到的是X Window的视窗管理员环境，那么在这里面有没有纯文字介面的环境啊？ 当然有啊！但是，要怎么切换X Window与文字模式呢？注意喔，通常我们也称文字模式为终端机介面, terminal 或 console喔！Linux预设的情况下会提供六个Terminal来让使用者登入， 切换的方式为使用：[Ctrl] + [Alt] + [F1]~[F6]的组合按钮。

那这六个终端介面如何命名呢，系统会将[F1] ~ [F6]命名为tty1 ~ tty6的操作介面环境。 也就是说，当你按下[crtl] + [Alt] + [F1]这三个组合按钮时 (按着[ctrl]与[Alt]不放，再按下[F1]功能键)， 就会进入到tty1的terminal介面中了。同样的[F2]就是tty2啰！那么如何回到刚刚的X视窗介面呢？很简单啊！按下[Ctrl] + [Alt] + [F7]就可以了！我们整理一下登入的环境如下：

  • [Ctrl] + [Alt] + [F1] ~ [F6] ：文字介面登入 tty1 ~ tty6 终端机；
  • [Ctrl] + [Alt] + [F7] ：图形介面桌面。

在Linux预设的登入模式中，主要分为两种，一种是仅有纯文字介面(所谓的执行等级run level 3)的登入环境，在这种环境中你可以有tty1~tty6的终端介面，但是并没有图形视窗介面的环境喔。 另一种则是图形介面的登入环境(所谓的执行等级run level 5)，这也是我们第四章安装妥当后的预设环境！ 在这个环境中你就具有tty1~tty7了！其中的tty7就是开机完成后的预设等待登入的图形环境！

如果你是以纯文字环境启动Linux的，预设的tty7是没有东西的！万一如此的话，那要怎么启动X视窗画面呢？ 你可以在tty1~tty6的任意一个终端介面使用你的帐号登入后(登入的方法下一小节会介绍)， 然后下达如下的指令即可：

[vbird@www ~]$ startx

不过startx这个指令并非万灵丹，你要让startx生效至少需要底下这几件事情的配合：

  • 你的tty7并没有其他的视窗软体正在运作(tty7必须是空出来的)；
  • 你必须要已经安装了X Window system，并且X server是能够顺利启动的；
  • 你最好要有视窗管理员，例如GNOME/KDE或者是阳春的TWM等；
  • 启动X所必须要的服务，例如字型伺服器(X Font Server, xfs)必须要先启动。

刚刚我们谈到的Linux启动时可以选择纯文字或者是视窗环境，也谈到了执行等级(run level)这东西！ Linux预设提供了七个Run level给我们使用，其中最常用到的就是run level 3与run level 5这两者了。 如果你想要让Linux在下次开机时使用纯文字环境(run level 3)来登入， 只要修订一下/etc/inittab这个档案的内容，就能够在下次重新开机时生效了！ 因为我们尚未提到vi以及开机过程的详细资讯， 所以啊，这部分得到系统管理员篇幅的时候再说明！别担心，再仔细的看下去吧！

小标题的图示 在终端介面登入linux

刚刚你如果有按下[Ctrl] + [Alt] + [F1]就可以来到tty1的登入画面，而如果你是使用纯文字介面(其实是run level 3)启动Linux主机的话，那么预设就是会来到tty1这个环境中。这个环境的等待登入的画面有点像这样：

CentOS release 5.3 (Final)
Kernel 2.6.18-128.el5 on an i686

www login: vbird
Password:
[vbird@www ~]$ _

上面显示的内容是这样的：

  1. CentOS release 5.3 (Final)：
    显示Linux distribution的名称(CentOS)与版本(5.3)；

  2. Kernel 2.6.18-128.el5 on an i686：
    显示核心的版本为2.6.18-128.el5， 且目前这部主机的硬体等级为i686。如果是使用x86_64的Linux版本且安装到64位元的PC，那你的硬体等级就会是‘X86_64’喔！

  3. www login:：
    那个www是你的主机名称。我们在第四章安装时有填写主机名称为： www.vbird.tsai，主机名称的显示通常只取第一个小数点前的字母，所以就成为www啦！至于login:则是一支可以让我们登入的程式。 你可以在login:后面输入你的帐号。以鸟哥为例，我输入的就是第四章建立的vbird那个帐号啦！ 当然啰，你也可以使用root这个帐号来登入的。不过‘root’这个帐号代表在Linux系统下无穷的权力， 所以尽量不要使用root帐号来登入啦！

  4. Password:：
    这一行则在第三行的vbird输入后才会出现，要你输入密码啰！ 请注意，在输入密码的时候，荧幕上面‘不会显示任何的字样！’， 所以不要以为你的键盘坏掉去！很多初学者一开始到这里都会拼命的问！啊我的键盘怎么不能用...

  5. [vbird@www ~]$ _：
    这一行则是正确登入之后才显示的讯息， 最左边的vbird显示的是‘目前使用者的帐号’，而@之后接的www则是‘主机名称’，至于最右边的~则指的是 ‘目前所在的目录’，那个$则是我们常常讲的‘提示字元’啦！
Tips:
那个 ~ 符号代表的是‘使用者的家目录’的意思，他是个‘变数！’ 这相关的意义我们会在后续的章节依序介绍到。举例来说，root的家目录在/root， 所以 ~ 就代表/root的意思。而vbird的家目录在/home/vbird， 所以如果你以vbird登入时，他看到的 ~ 就会等于/home/vbird喔！

至于提示字元方面，在Linux当中，预设root的提示字元为 # ，而一般身份使用者的提示字元为 $ 。

还有，上面的第一、第二行的内容其实是来自于/etc/issue这个档案喔！ 		鸟哥的图示

好了这样就是登入主机了！很快乐吧！耶～

另外，再次强调，在Linux系统下最好常使用一般帐号来登入即可，所以上例中鸟哥是以自己的帐号vbird来登入的。 因为系统管理员帐号(root)具有无穷大的权力，例如他可以删除任何一个档案或目录。因此若你以root身份登入Linux系统， 一个不小心下错指令，这个时候可不是‘欲哭无泪’就能够解决的了问题的～

因此，一个称职的网路/系统管理人员，通常都会具有两个帐号，平时以自己的一般帐号来使用Linux主机的任何资源， 有需要动用到系统功能修订时，才会转换身份成为root呢！所以，鸟哥强烈建议你建立一个普通的帐号来供自己平时使用喔！ 更详细的帐号讯息，我们会在后续的‘第十四章帐号管理’再次提及！ 这里先有概念即可！

那么如何离开系统呢？其实应该说‘登出Linux’才对！登出很简单，直接这样做：

[vbird@www ~]$ exit

就能够登出Linux了。但是请注意：‘离开系统并不是关机！’ 基本上，Linux本身已经有相当多的工作在进行，你的登入也仅是其中的一个‘工作’而已， 所以当你离开时，这次这个登入的工作就停止了，但此时Linux其他的工作是还是继续在进行的！ 本章后面我们再来提如何正确的关机，这里先建立起这个概念即可！

大标题的图示 文字模式下指令的下达

其实我们都是透过‘程式’在跟系统作沟通的，本章上面提到的视窗管理员或文字模式都是一组或一只程式在负责我们所想要完成的指令。 文字模式登入后所取得的程式被称为壳(Shell)，这是因为这支程式负责最外面跟使用者(我们)沟通，所以才被戏称为壳程式！ 更多与作业系统及壳程式的相关性可以参考第零章、计算机概论内的说明。

我们Linux的壳程式就是厉害的bash这一支！关于更多的bash我们在第三篇再来介绍。现在让我们来练一练打字吧！

小标题的图示 开始下达指令

其实整个指令下达的方式很简单，你只要记得几个重要的概念就可以了。 举例来说，你可以这样下达指令的：

[vbird@www ~]$ command [-options] parameter1 parameter2 ...
                  指令     选项      参数(1)    参数(2)
说明：
0. 一行指令中第一个输入的部分绝对是‘指令(command)’或‘可执行档案’
1. command 为指令的名称，例如变换路径的指令为 cd 等等；
2. 中刮号[]并不存在于实际的指令中，而加入选项设定时，通常选项前会带 - 号，
   例如 -h；有时候会使用选项的完整全名，则选项前带有 -- 符号，例如 --help；
3. parameter1 parameter2.. 为依附在选项后面的参数，或者是 command 的参数；
4. 指令, 选项, 参数等这几个咚咚中间以空格来区分，不论空几格 shell 都视为一格；
5. 按下[Enter]按键后，该指令就立即执行。[Enter]按键代表着一行指令的开始启动。
6. 指令太长的时候，可以使用反斜线 (\) 来跳脱[Enter]符号，使指令连续到下一行。
   注意！反斜线后就立刻接特殊字符，才能跳脱！
其他：
a. 在 Linux 系统中，英文大小写字母是不一样的。举例来说， cd 与 CD 并不同。
b. 更多的介绍等到第十一章 bash 时，再来详述。

注意到上面的说明当中，‘第一个被输入的资料绝对是指令或者是可执行的档案’！ 这个是很重要的概念喔！还有，按下[Enter]键表示要开始执行此一命令的意思。我们来实际操作一下： 以ls这个‘指令’列出‘自己家目录(~)’下的‘所有隐藏档与相关的档案属性’， 要达成上述的要求需要加入 -al 这样的选项，所以：

[vbird@www ~]$ ls -al ~
[vbird@www ~]$ ls           -al   ~
[vbird@www ~]$ ls -a  -l ~

上面这三个指令的下达方式是一模一样的执行结果喔！为什么？请参考上面的说明吧！ 关于更详细的文字模式使用方式，我们会在第十一章认识BASH再来强调喔！ 此外，请特别留意，在Linux的环境中， ‘大小写字母是不一样的东西！’也就是说，在Linux底下， VBird与vbird这两个档案是‘完全不一样的’档案呢！所以， 你在下达指令的时候千万要注意到指令是大写还是小写。例如当输入底下这个指令的时候，看看有什么现象：

[vbird@www ~]$ date  <==结果显示日期与时间

[vbird@www ~]$ Date  <==结果显示找不到指令
[vbird@www ~]$ DATE  <==结果显示找不到指令

很好玩吧！只是改变小写成为大写而已，该指令就变的不存在了！ 因此，请千万记得这个状态呦！

  • 语系的支援

另外，很多时候你会发现，咦！怎么我输入指令之后显示的结果的是乱码？ 这跟鸟哥说的不一样啊！呵呵！不要紧张～我们前面提到过，Linux是可以支援多国语系的，若可能的话， 荧幕的讯息是会以该支援语系来输出的。但是，我们的终端机介面(terminal)在预设的情况下， 无法支援以中文编码输出资料的。这个时候，我们就得将支援语系改为英文，才能够以英文显示出正确的讯息。 那怎么做呢？你可以这样做：

1. 显示目前所支援的语系

[vbird@www ~]$ echo $LANG
zh_TW.UTF-8
# 上面的意思是说，目前的语系(LANG)为zh_TW.UTF-8，亦即台湾繁体中文的万国码

2. 修改语系成为英文语系
[vbird@www ~]$ LANG=en_US
# 注意到上面的指令中没有空白字元，且英文语系为en_US才对喔！
[vbird@www ~]$ echo $LANG

en_US
# 再次确认一下，结果出现，确实是en_US这个英文语系！

注意一下，那个‘LANG=en_US’是连续输入的，等号两边并没有空白字元喔！ 这样一来，就能够在‘这次的登入’察看英文讯息啰！为什么说是‘这次的登入’呢？ 因为，如果你登出Linux后，刚刚下达的指令就没有用啦！ ^_^，这个我们会在第十一章再好好聊一聊的！好啰，底下我们来练习一下一些简单的指令， 好让你可以了解指令下达方式的模式：

小标题的图示 基础指令的操作

底下我们立刻来操作几个简单的指令看看啰！

  • 显示日期与时间的指令： date
  • 显示日历的指令： cal
  • 简单好用的计算机： bc

1. 显示日期的指令： date

如果在文字介面中想要知道目前Linux系统的时间，那么就直接在指令列模式输入date即可显示：

[vbird@www ~]$ date
Mon Aug 17 17:02:52 CST 2009

上面显示的是：星期一, 八月十七日, 17:02 分, 52秒，在 2009 年的 CST 时区！台湾在CST时区中啦！ 请赶快动手做做看呦！好了，那么如果我想要让这个程式显示出‘2009/08/17’这样的日期显示方式呢？ 那么就使用date的格式化输出功能吧！

[vbird@www ~]$ date +%Y/%m/%d
2009/08/17
[vbird@www ~]$ date +%H:%M
17:04

那个‘+%Y%m%d’就是date指令的一些参数功能啦！很好玩吧！那你问我， 鸟哥怎么知道这些参数的啊？要背起来吗？当然不必啦！底下再告诉你怎么查这些参数啰！

从上面的例子当中我们也可以知道，指令之后的选项除了前面带有减号‘-’之外，某些特殊情况下， 选项或参数前面也会带有正号‘+’的情况！这部份可不要轻易的忘记了呢！

2. 显示日历的指令： cal

那如果我想要列出目前这个月份的月历呢？呵呵！直接给他下达cal即可！

[vbird@www ~]$ cal
     August 2009
Su Mo Tu We Th Fr Sa
                   1
 2  3  4  5  6  7  8
 9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31

除了本月的日历之外，连同今日所在处都会有反白的显示呢！真有趣！cal (calendar)这个指令可以做的事情还很多，例如你可以显示整年的月历情况：

[vbird@www ~]$ cal 2009
                               2009

       January               February                 March
Su Mo Tu We Th Fr Sa   Su Mo Tu We Th Fr Sa   Su Mo Tu We Th Fr Sa
             1  2  3    1  2  3  4  5  6  7    1  2  3  4  5  6  7
 4  5  6  7  8  9 10    8  9 10 11 12 13 14    8  9 10 11 12 13 14
11 12 13 14 15 16 17   15 16 17 18 19 20 21   15 16 17 18 19 20 21
18 19 20 21 22 23 24   22 23 24 25 26 27 28   22 23 24 25 26 27 28
25 26 27 28 29 30 31                          29 30 31

        April                   May                   June
Su Mo Tu We Th Fr Sa   Su Mo Tu We Th Fr Sa   Su Mo Tu We Th Fr Sa
          1  2  3  4                   1  2       1  2  3  4  5  6
 5  6  7  8  9 10 11    3  4  5  6  7  8  9    7  8  9 10 11 12 13
12 13 14 15 16 17 18   10 11 12 13 14 15 16   14 15 16 17 18 19 20
19 20 21 22 23 24 25   17 18 19 20 21 22 23   21 22 23 24 25 26 27
26 27 28 29 30         24 25 26 27 28 29 30   28 29 30
                       31
....(以下省略)....

基本上cal这个指令可以接的语法为：

[vbird@www ~]$ cal [month] [year]

所以，如果我想要知道2009年10月的月历，可以直接下达：

[vbird@www ~]$ cal 10 2009
    October 2009
Su Mo Tu We Th Fr Sa
             1  2  3
 4  5  6  7  8  9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31

那请问今年有没有13月啊？来测试一下这个指令的正确性吧！下达下列指令看看：

[vbird@www ~]$ cal 13 2009
cal: illegal month value: use 1-12

cal竟然会告诉我们‘错误的月份，请使用1-12’这样的资讯呢！所以， 未来你可以很轻易的就以cal来取得日历上面的日期啰！简直就是万年历啦！ ^_^。 另外，由这个cal指令的练习我们也可以知道，某些指令有特殊的参数存在， 若输入错误的参数，则该指令会有错误讯息的提示，透过这个提示我们可以藉以了解指令下达错误之处。 这个练习的结果请牢记在心中喔！

3. 简单好用的计算机： bc

如果在文字模式当中，突然想要作一些简单的加减乘除，偏偏手边又没有计算机！这个时候要笔算吗？ 不需要啦！我们的Linux有提供一支计算程式，那就是bc喔。你在指令列输入bc后，荧幕会显示出版本资讯， 之后就进入到等待指示的阶段。如下所示：

[vbird@www ~]$ bc
bc 1.06
Copyright 1991-1994, 1997, 1998, 2000 Free Software Foundation, Inc.
This is free software with ABSOLUTELY NO WARRANTY.
For details type `warranty'.
_ <==这个时候，游标会停留在这里等待你的输入

事实上，我们是‘进入到bc这个软体的工作环境当中’了！ 就好像我们在Windows里面使用‘小算盘’一样！所以，我们底下尝试输入的资料， 都是在bc程式当中在进行运算的动作。所以啰，你输入的资料当然就得要符合bc的要求才行！ 在基本的bc计算机操作之前，先告知几个使用的运算子好了：

  • + 加法
  • - 减法
  • * 乘法
  • / 除法
  • ^ 指数
  • % 余数

好！让我们来使用bc计算一些咚咚吧！

[vbird@www ~]$ bc
bc 1.06
Copyright 1991-1994, 1997, 1998, 2000 Free Software Foundation, Inc.
This is free software with ABSOLUTELY NO WARRANTY.
For details type `warranty'.
1+2+3+4  <==只有加法时
10
7-8+3
2
10*52
520
10%3     <==计算‘余数’

1
10^2
100
10/100   <==这个最奇怪！不是应该是 0.1 吗？
0
quit     <==离开 bc 这个计算器

在上表当中，粗体字表示输入的资料，而在每个粗体字的底下就是输出的结果。 咦！每个计算都还算正确，怎么10/100会变成0呢？这是因为bc预设仅输出整数，如果要输出小数点下位数，那么就必须要执行 scale=number ，那个number就是小数点位数，例如：

[vbird@www ~]$ bc
bc 1.06
Copyright 1991-1994, 1997, 1998, 2000 Free Software Foundation, Inc.
This is free software with ABSOLUTELY NO WARRANTY.
For details type `warranty'.
scale=3     <==没错！就是这里！！
1/3
.333
340/2349
.144
quit

注意啊！要离开bc回到命令提示字元时，务必要输入‘quit’来离开bc的软体环境喔！ 好了！就是这样子啦！简单的很吧！以后你可以轻轻松松的进行加减乘除啦！

从上面的练习我们大概可以知道在指令列模式里面下达指令时，会有两种主要的情况：

  • 一种是该指令会直接显示结果然后回到命令提示字元等待下一个指令的输入；
  • 一种是进入到该指令的环境，直到结束该指令才回到命令提示字元的环境。

我们以一个简单的图示来说明：

指令下达的环境
图2.2.1、指令下达的环境，上图为直接显示结果，下图为进入软体功能

如图2.2.1所示，上方指令下达后立即显示讯息且立刻回到命令提示字元的环境。 如果有进入软体功能的环境(例如上面的bc软体)，那么就得要使用该软体的结束指令 (例如在bc环境中输入quit)才能够回到命令提示字元中！那你怎么知道你是否在命令提示字元的环境呢？ 很简单！你只要看到游标是在‘[vbird@www ~]$’这种提示字元后面， 那就是等待输入指令的环境了。很容易判断吧！不过初学者还是很容易忘记啦！

小标题的图示 重要的几个热键[Tab], [ctrl]-c, [ctrl]-d

在继续后面章节的学习之前，这里很需要跟大家再来报告一件事，那就是我们的文字模式里头具有很多的功能组合键， 这些按键可以辅助我们进行指令的编写与程式的中断呢！这几个按键请大家务必要记住的！很重要喔！

  • [Tab]按键

[Tab]按键就是在键盘的大写灯切换按键([Caps Lock])上面的那个按键！在各种Unix-Like的Shell当中， 这个[Tab]按键算是Linux的Bash shell最棒的功能之一了！他具有‘命令补全’与‘档案补齐’的功能喔！ 重点是，可以避免我们打错指令或档案名称呢！很棒吧！但是[Tab]按键在不同的地方输入，会有不一样的结果喔！ 我们举下面的例子来说明。上一小节我们不是提到 cal 这个指令吗？如果我在指令列输入 ca 再按两次 [tab] 按键， 会出现什么讯息？

[vbird@www ~]$ ca[tab][tab]    <==[tab]按键是紧接在 a 字母后面！
cadaver             callgrind_control   capifax             card
cal                 cameratopam         capifaxrcvd         case
caller              cancel              capiinfo            cat
callgrind_annotate  cancel.cups         captoinfo           catchsegv
# 上面的 [tab] 指的是‘按下那个tab键’，不是要你输入中括号内的tab啦！

发现什么事？所有以ca为开头的指令都被显示出来啦！很不错吧！那如果你输入‘ls -al ~/.bash’再加两个[tab]会出现什么？

[vbird@www ~]$ ls -al ~/.bash[tab][tab]
.bash_history  .bash_logout   .bash_profile  .bashrc

咦！在该目录下面所有以 .bash 为开头的档案名称都会被显示出来了呢！注意看上面两个例子喔， 我们按[tab]按键的地方如果是在command(第一个输入的资料)后面时，他就代表着 ‘命令补全’，如果是接在第二个字以后的，就会变成‘档案补齐’的功能了！总结一下：

  • [Tab] 接在一串指令的第一个字的后面，则为命令补全；
  • [Tab] 接在一串指令的第二个字以后时，则为‘档案补齐’！

善用 [tab] 按键真的是个很好的习惯！可以让你避免掉很多输入错误的机会！

  • [Ctrl]-c 按键

如果你在Linux底下输入了错误的指令或参数，有的时候这个指令或程式会在系统底下‘跑不停’这个时候怎么办？别担心， 如果你想让当前的程式‘停掉’的话，可以输入：[Ctrl]与c按键(先按着[Ctrl]不放，且再按下c按键，是组合按键)， 那就是中断目前程式的按键啦！举例来说，如果你输入了‘find /’这个指令时，系统会开始跑一些东西(先不要理会这个指令串的意义)，此时你给他按下 [Ctrl]-c 组合按键，嘿嘿！是否立刻发现这个指令串被终止了！就是这样的意思啦！

[vbird@www ~]$ find /
....(一堆东西都省略)....
# 此时荧幕会很花，你看不到命令提示字元的！直接按下[ctrl]-c即可！
[vbird@www ~]$ <==此时提示字元就会回来了！find程式就被中断！

不过你应该要注意的是，这个组合键是可以将正在运作中的指令中断的， 如果你正在运作比较重要的指令，可别急着使用这个组合按键喔！ ^_^

  • [Ctrl]-d 按键

那么[Ctrl]-d是什么呢？就是[Ctrl]与d按键的组合啊！这个组合按键通常代表着： ‘键盘输入结束(End Of File, EOF 或 End Of Input)’的意思！ 另外，他也可以用来取代exit的输入呢！例如你想要直接离开文字介面，可以直接按下[Ctrl]-d就能够直接离开了(相当于输入exit啊！)。

总之，在Linux底下，文字介面的功能是很强悍的！要多多的学习他，而要学习他的基础要诀就是...多使用、多熟悉啦！

小标题的图示 错误讯息的察看

万一我下达了错误的指令怎么办？不要紧呀！你可以藉由荧幕上面显示的错误讯息来了解你的问题点， 那就很容易知道如何改善这个错误讯息啰！举个例子来说，假如想执行date却因为大小写打错成为DATE时， 这个错误的讯息是这样显示的：

[vbird@www ~]$ DATE
-bash: DATE: command not found

上面那个bash:表示的是我们的Shell的名称， 本小节一开始就谈到过Linux的预设壳程式就是bash啰！ 那么上面的例子说明了bash有错误，什么错误呢？bash告诉你：

DATE: command not found

字面上的意思是说‘指令找不到’，那个指令呢？就是DATE这个指令啦！ 所以说，系统上面可能并没有DATE这个指令啰！就是这么简单！通常出现‘command not found’的可能原因为：

  • 这个指令不存在，因为该软体没有安装之故。解决方法就是安装该软体；
  • 这个指令所在的目录目前的用户并没有将他加入指令搜寻路径中，请参考bash的PATH说明；
  • 很简单！因为你打错字！

另外常见的错误就是我们曾经看过的例子，如下所示：

[vbird@www ~]$ cal 13 2009
cal: illegal month value: use 1-12

荧幕会告诉我们错误的讯息啦！照着荧幕的讯息去处理即可解决你的错误啦！是否很简单啊！ 因此，以后如果出现了问题，荧幕上的讯息真的是很重要的呢！不要忽略了他呦！

介绍这几个指令让你玩一玩先，更详细的指令操作方法我们会在第三篇的时候再进行介绍！ 现在让我们来想一想，万一我在操作date这个指令的时候，手边又没有这本书，我要怎么知道要如何加那些奇怪的参数， 好让输出的结果符合我想要的输出格式呢？嘿嘿！到下一节鸟哥来告诉你怎么办吧！

大标题的图示 Linux系统的线上求助man page与info page

先来了解一下Linux有多少指令呢？在文字模式下，你可以直接按下两个[Tab]按键，看看总共有多少指令可以让你用？

[vbird@www ~]$ <==在这里不要输入任何字元，直接输入两次[tab]按键
Display all 2450 possibilities? (y or n) <==如果不想要看，按 n 离开

如上所示，鸟哥安装的这个系统中，少说也有2000多个以上的指令可以让vbird这个帐号使用。 那在Linux里面到底要不要背‘指令’啊？可以啊！你背啊！这种事，鸟哥这个‘忘性’特佳的老人家实在是背不起来 @_@ ～当然啦，有的时候为了要考试(例如一些认证考试等等的)还是需要背一些重要的指令与选项的！ 不过，鸟哥主要还是以理解‘在什么情况下，应该要使用哪方面的指令’为准的！

既然鸟哥说不需要背指令，那么我们如何知道每个指令的详细用法？还有，某些设定档的内容到底是什么？ 这个可就不需要担心了！因为在Linux上开发的软体大多数都是自由软体，而这些软体的开发者为了让大家能够了解指令的用法， 都会自行制作很多的文件，而这些文件也可以直接在线上就能够轻易的被使用者查询出来喔！很不赖吧！ 这根本就是‘线上说明文件’嘛！哈哈！没错！确实如此。我们底下就来谈一谈，Linux到底有多少的线上文件资料呢？

小标题的图示 man page

嗄？不知道怎么使用date这个指令？嘿嘿！不要担心，我们Linux上面的线上求助系统已经都帮你想好要怎么办了， 所以你只要使用简单的方法去寻找一下说明的内容，马上就清清楚楚的知道该指令的用法了！怎么看呢？就是找男人(man) 呀！喔！不是啦！这个man是manual(操作说明)的简写啦！只要下达：‘man date’ 马上就会有清楚的说明出现在你面前喔！如下所示：

[vbird@www ~]$ LANG="en"
# 还记得这个咚咚的用意吧？前面提过了，是为了‘语系’的需要啊！下达过一次即可！

[vbird@www ~]$ man date
DATE(1)                          User Commands                         DATE(1)
# 请注意上面这个括号内的数字
NAME  <==这个指令的完整全名，如下所示为date且说明简单用途为设定与显示日期/时间
       date - print or set the system date and time

SYNOPSIS  <==这个指令的基本语法如下所示

       date [OPTION]... [+FORMAT]
       date [-u|--utc|--universal] [MMDDhhmm[[CC]YY][.ss]]

DESCRIPTION  <==详细说明刚刚语法谈到的选项与参数的用法
       Display  the  current  time  in  the given FORMAT, or set the system
       date.

       -d, --date=STRING  <==左边-d为短选项名称，右边--date为完整选项名称
              display time described by STRING, not 'now'

       -f, --file=DATEFILE
              like --date once for each line of DATEFILE

       -r, --reference=FILE
              display the last modification time of FILE
....(中间省略)....
       # 找到了！底下就是格式化输出的详细资料！
       FORMAT controls the output.  The only valid option  for  the  second
       form  specifies  Coordinated  Universal Time.  Interpreted sequences
       are:

       %%     a literal %

       %a     locale's abbreviated weekday name (e.g., Sun)

       %A     locale's full weekday name (e.g., Sunday)

....(中间省略)....
ENVIRONMENT  <==与这个指令相关的环境参数有如下的说明
       TZ     Specifies the timezone, unless  overridden  by  command  line
              parameters.   If  neither  is  specified,  the  setting  from
              /etc/localtime is used.

AUTHOR  <==这个指令的作者啦！
       Written by David MacKenzie.

REPORTING BUGS  <==有问题请留言给底下的email的意思！
       Report bugs to <bug-coreutils@gnu.org>.

COPYRIGHT  <==受到著作权法的保护！用的就是 GPL 了！

       Copyright ? 2006 Free Software Foundation, Inc.
       This is free software.  You may redistribute copies of it under  the
       terms      of      the      GNU      General      Public     License
       <http://www.gnu.org/licenses/gpl.html>.  There is  NO  WARRANTY,  to
       the extent permitted by law.

SEE ALSO  <==这个重要，你还可以从哪里查到与date相关的说明文件之意
       The  full  documentation for date is maintained as a Texinfo manual.
       If the info and date programs are properly installed at  your  site,
       the command

              info date

       should give you access to the complete manual.

date 5.97                          May 2006                            DATE(1)
Tips:
进入man指令的功能后，你可以按下‘空白键’往下翻页，可以按下‘ q ’按键来离开man的环境。 更多在man指令下的功能，本小节后面会谈到的！ 		鸟哥的图示

看(鸟哥没骂人！)马上就知道一大堆的用法了！如此一来，不就可以知道date的相关选项与参数了吗？真方便！ 而出现的这个荧幕画面，我们称呼他为man page， 你可以在里头查询他的用法与相关的参数说明。如果仔细一点来看这个man page的话，你会发现几个有趣的东西。

首先，在上个表格的第一行，你可以看到的是：‘DATE(1)’，DATE我们知道是指令的名称， 那么(1)代表什么呢？他代表的是‘一般使用者可使用的指令’的意思！咦！还有这个用意啊！呵呵！ 没错～在查询资料的后面的数字是有意义的喔！他可以帮助我们了解或者是直接查询相关的资料。 常见的几个数字的意义是这样的：

代号 | 代表内容
1 | 使用者在shell环境中可以操作的指令或可执行档
2 | 系统核心可呼叫的函数与工具等
3 | 一些常用的函数(function)与函式库(library)，大部分为C的函式库(libc)
4 | 装置档案的说明，通常在/dev下的档案
5 | 设定档或者是某些档案的格式
6 | 游戏(games)
7 | 惯例与协定等，例如Linux档案系统、网路协定、ASCII code等等的说明
8 | 系统管理员可用的管理指令
9 | 跟kernel有关的文件

上述的表格内容可以使用‘man 7 man’来更详细的取得说明。透过这张表格的说明， 未来你如果使用man page在察看某些资料时，就会知道该指令/档案所代表的基本意义是什么了。 举例来说，如果你下达了‘man null’时，会出现的第一行是：‘NULL(4)’，对照一下上面的数字意义， 嘿嘿！原来null这个玩意儿竟然是一个‘装置档案’呢！很容易了解了吧！

Tips:
上表中的1, 5, 8这三个号码特别重要，也请读者要将这三个数字所代表的意义背下来喔！ 		鸟哥的图示

再来，man page的内容也分成好几个部分来加以介绍该指令呢！就是上头man date那个表格内， 以NAME作为开始介绍，最后还有个SEE ALSO来作为结束。基本上，man page大致分成底下这几个部分：

代号 | 内容说明
NAME | 简短的指令、资料名称说明
SYNOPSIS | 简短的指令下达语法(syntax)简介
DESCRIPTION | 较为完整的说明，这部分最好仔细看看！
OPTIONS | 针对 SYNOPSIS 部分中，有列举的所有可用的选项说明
COMMANDS | 当这个程式(软体)在执行的时候，可以在此程式(软体)中下达的指令
FILES | 这个程式或资料所使用或参考或连结到的某些档案
SEE ALSO | 可以参考的，跟这个指令或资料有相关的其他说明！
EXAMPLE | 一些可以参考的范例
BUGS | 是否有相关的臭虫！

有时候除了这些外，还可能会看到Authors与Copyright等，不过也有很多时候仅有NAME与DESCRIPTION等部分。 通常鸟哥在查询某个资料时是这样来查阅的：

  1. 先察看NAME的项目，约略看一下这个资料的意思；
  2. 再详看一下DESCRIPTION，这个部分会提到很多相关的资料与使用时机，从这个地方可以学到很多小细节呢；
  3. 而如果这个指令其实很熟悉了(例如上面的date)，那么鸟哥主要就是查询关于OPTIONS的部分了！ 可以知道每个选项的意义，这样就可以下达比较细部的指令内容呢！
  4. 最后，鸟哥会再看一下，跟这个资料有关的还有哪些东西可以使用的？举例来说，上面的SEE ALSO就告知我们还可以利用‘info coreutils date’来进一步查阅资料；
  5. 某些说明内容还会列举有关的档案(FILES 部分)来提供我们参考！这些都是很有帮助的！

大致上了解了man page的内容后，那么在man page当中我还可以利用哪些按键来帮忙查阅呢？首先， 如果要向下翻页的话，可以按下键盘的空白键，也可以使用[Page Up]与[Page Down]来翻页呢！同时，如果你知道某些关键字的话， 那么可以在任何时候输入‘/word’，来主动搜寻关键字！例如在上面的搜寻当中，我输入了‘/date’会变成怎样？

DATE(1)                          User Commands                         DATE(1)

NAME
       date - print or set the system date and time

SYNOPSIS
       date [OPTION]... [+FORMAT]
       date [-u|--utc|--universal] [MMDDhhmm[[CC]YY][.ss]]

DESCRIPTION
       Display  the  current  time  in  the given FORMAT, or set the system date.

....(中间省略)....

/date <==只要按下/，游标就会跑到这个地方来，你就可以开始输入搜寻字串咯

看到了吗，当你按下‘/’之后，游标就会移动到荧幕的最下面一行， 并等待你输入搜寻的字串了。此时，输入date后，man page就会开始搜寻跟date有关的字串， 并且移动到该区域呢！很方便吧！最后，如果要离开man page时，直接按下‘ q ’就能够离开了。 我们将一些在man page常用的按键给他整理整理：

按键 | 进行工作
空白键 | 向下翻一页
[Page Down] | 向下翻一页
[Page Up] | 向上翻一页
[Home] | 去到第一页
[End] | 去到最后一页
/string | 向‘下’搜寻 string 这个字串，如果要搜寻 vbird 的话，就输入 /vbird
?string | 向‘上’搜寻 string 这个字串
n, N | 利用 / 或 ? 来搜寻字串时，可以用 n 来继续下一个搜寻 (不论是 / 或 ?) ，可以利用 N 来进行‘反向’搜寻。举例来说，我以 /vbird 搜寻 vbird 字串， 那么可以 n 继续往下查询，用 N 往上查询。若以 ?vbird 向上查询 vbird 字串， 那我可以用 n 继续‘向上’查询，用 N 反向查询。
q | 结束这次的 man page

要注意喔！上面的按键是在man page的画面当中才能使用的！ 比较有趣的是那个搜寻啦！我们可以往下或者是往上搜寻某个字串，例如要在man page内搜寻vbird这个字串， 可以输入 /vbird 或者是 ?vbird ，只不过一个是往下而一个是往上来搜寻的。而要 重复搜寻 某个字串时，可以使用 n 或者是 N 来动作即可呢！ 很方便吧！^_^

既然有man page，自然就是因为有一些文件资料，所以才能够以man page读出来啰！那么这些man page的资料 放在哪里呢？不同的distribution通常可能有点差异性，不过，通常是放在/usr/share/man这个目录里头，然而，我们可以透过修改他的man page搜寻路径来改善这个目录的问题！修改/etc/man.config (有的版本为man.conf或manpath.conf)即可啰！至于更多的关于man的讯息你可以使用‘ man man ’来查询呦！关于更详细的设定，我们会在第十一章 bash 当中继续的说明喔！

  • 搜寻特定指令/档案的man page说明文件

在某些情况下，你可能知道要使用某些特定的指令或者是修改某些特定的设定档，但是偏偏忘记了该指令的完整名称。 有些时候则是你只记得该指令的部分关键字。这个时候你要如何查出来你所想要知道的man page呢？ 我们以底下的几个例子来说明man这个指令有用的地方喔！

例题：
你可否查出来，系统中还有哪些跟‘man’这个指令有关的说明文件呢？
答：
你可以使用底下的指令来查询一下：
[vbird@www ~]$ man -f man

man                  (1)  - format and display the on-line manual pages
man                  (7)  - macros to format man pages
man.config [man]     (5)  - configuration data for man
使用 -f 这个选项就可以取得更多与man相关的资讯，而上面这个结果当中也有提示了 (数字) 的内容， 举例来说，第二行的‘ man (7) ’表示有个man (7)的说明文件存在喔！但是却有个man (1)存在啊！ 那当我们下达‘ man man ’的时候，到底是找到哪一个说明档呢？ 其实，你可以指定不同的文件的，举例来说，上表当中的两个 man 你可以这样将他的文件叫出来：
[vbird@www ~]$ man 1 man  <==这里是用 man(1) 的文件资料
[vbird@www ~]$ man 7 man  <==这里是用 man(7) 的文件资料
你可以自行将上面两个指令输入一次看看，就知道，两个指令输出的结果是不同的。 那个1, 7就是分别取出在man page里面关于1与7相关资料的文件档案啰！ 好了，那么万一我真的忘记了下达数字，只有输入‘ man man ’时，那么取出的资料到底是1还是7啊？ 这个就跟搜寻的顺序有关了。搜寻的顺序是记录在/etc/man.conf这个设定档当中， 先搜寻到的那个说明档，就会先被显示出来！ 一般来说，通常会先找到数字较小的那个啦！因为排序的关系啊！所以， man man 会跟 man 1 man 结果相同！

除此之外，我们还可以利用‘关键字’找到更多的说明文件资料喔！什么是关键字呢？ 从上面的‘man -f man’输出的结果中，我们知道其实输出的资料是：

  • 左边部分：指令(或档案)以及该指令所代表的意义(就是那个数字)；
  • 右边部分：这个指令的简易说明，例如上述的‘-macros to format man pages’

当使用‘man -f 指令’时，man只会找资料中的左边那个指令(或档案)的完整名称，有一点不同都不行！ 但如果我想要找的是‘关键字’呢？也就是说，我想要同时找上面说的两个地方的内容，只要该内容有关键字存在， 不需要完全相同的指令(或档案)就能够找到时，该怎么办？请看下个范例啰！

例题：
找出系统的说明档中，只要有man这个关键字就将该说明列出来。
答：
[vbird@www ~]$ man -k man

. [builtins]         (1)  - bash built-in commands, see bash(1)
.TP 15 php [php]     (1)  - PHP Command Line Interface 'CLI'
....(中间省略)....
zshall               (1)  - the Z shell meta-man page
zshbuiltins          (1)  - zsh built-in commands
zshzle               (1)  - zsh command line editor
看到了吧！很多对吧！因为这个是利用关键字将说明文件里面只要含有man那个字眼的(不见得是完整字串) 就将他取出来！很方便吧！ ^_^(上面的结果有特殊字体的显示是为了方便读者查看， 实际的输出结果并不会有特别的颜色显示喔！)

事实上，还有两个指令与man page有关呢！而这两个指令是man的简略写法说～就是这两个：

[vbird@www ~]$ whatis  [指令或者是资料]   <==相当于 man -f [指令或者是资料]
[vbird@www ~]$ apropos [指令或者是资料]   <==相当于 man -k [指令或者是资料]

而要注意的是，这两个特殊指令要能使用，必须要有建立 whatis 资料库才行！这个资料库的建立需要以 root 的身份下达如下的指令：

[root@www ~]# makewhatis
Tips:
一般来说，鸟哥是真的不会去背指令的，只会去记住几个常见的指令而已。那么鸟哥是怎么找到所需要的指令呢？ 举例来说，列印的相关指令，鸟哥其实仅记得 lp (line print)而已。那我就由 man lp 开始，去找相关的说明， 然后，再以 lp[tab][tab] 找到任何以 lp 为开头的指令，找到我认为可能有点相关的指令后， 再以 man 去查询指令的用法！呵呵！所以，如果是实际在管理 Linux ， 那么真的只要记得几个很重要的指令即可，其他需要的，嘿嘿！努力的找男人(man)吧！ 		鸟哥的图示
小标题的图示 info page

在所有的Unix Like系统当中，都可以利用 man 来查询指令或者是相关档案的用法； 但是，在Linux里面则又额外提供了一种线上求助的方法，那就是利用info这个好用的家伙啦！

基本上，info与man的用途其实差不多，都是用来查询指令的用法或者是档案的格式。但是与man page一口气输出一堆资讯不同的是，info page则是将文件资料拆成一个一个的段落，每个段落用自己的页面来撰写， 并且在各个页面中还有类似网页的‘超连结’来跳到各不同的页面中，每个独立的页面也被称为一个节点(node)。 所以，你可以将info page想成是文字模式的网页显示资料啦！

不过你要查询的目标资料的说明文件必须要以info的格式来写成才能够使用info的特殊功能(例如超连结)。 而这个支援info指令的文件预设是放置在/usr/share/info/这个目录当中的。 举例来说，info这个指令的说明文件有写成info格式，所以，你使用‘ info info ’可以得到如下的画面：

[vbird@www ~]$ info info
File: info.info,  Node: Top,  Next: Getting Started,  Up: (dir)

Info: An Introduction
*********************

The GNU Project distributes most of its on-line manuals in the "Info
format", which you read using an "Info reader".  You are probably using
an Info reader to read this now.

....(中间省略)....

   To read about expert-level Info commands, type `n' twice.  This
brings you to `Info for Experts', skipping over the `Getting Started'
chapter.
* Menu:

* Getting Started::             Getting started using an Info reader.
* Expert Info::                 Info commands for experts.
* Creating an Info File::       How to make your own Info file.
* Index::                       An index of topics, commands, and variables.

--zz-Info: (info.info.gz)Top, 29 lines --Top------------------------------
Welcome to Info version 4.8. Type ? for help, m for menu item.

仔细的看到上面这个显示的结果，里面的第一行显示了很多的资讯喔！第一行里面的资料意义为：

  • File：代表这个info page的资料是来自info.info档案所提供的；
  • Node：代表目前的这个页面是属于Top节点。 意思是info.info内含有很多资讯，而Top仅是info.info档案内的一个节点内容而已；
  • Next：下一个节点的名称为Getting Started，你也可以按‘N’到下个节点去；
  • Up：回到上一层的节点总揽画面，你也可以按下‘U’回到上一层；
  • Prev：前一个节点。但由于Top是info.info的第一个节点，所以上面没有前一个节点的资讯。

从第一行你可以知道这个节点的内容、来源与相关连结的资讯。更有用的资讯是，你可以透过直接按下N, P, U来去到下一个、上一个与上一层的节点(node)！非常的方便！ 第一行之后就是针对这个节点的说明。在上表的范例中，第二行以后的说明就是针对info.info内的Top这个节点所做的。

再来，你也会看到有‘Menu’那个咚咚吧！底下共分为四小节，分别是Getting Started等等的，我们可以使用上下左右按键来将游标移动到该文字或者‘ * ’上面，按下Enter， 就可以前往该小节了！另外，也可以按下[Tab]按键，就可以快速的将游标在上表的画面中的node间移动， 真的是非常的方便好用。如果将info.info内的各个节点串在一起并绘制成图表的话，情况有点像底下这样：

info page各说明文件相关性的示意图
图3.2.1、info page各说明文件相关性的示意图

如同上图所示，info的说明文件将内容分成多个node，并且每个node都有定位与连结。 在各连结之间还可以具有类似‘超连结’的快速按钮，可以透过[tab]键在各个超连结间移动。 也可以使用U,P,N来在各个阶层与相关连结中显示！非常的不错用啦！ 至于在info page当中可以使用的按键，可以整理成这样：

按键 | 进行工作
空白键 | 向下翻一页
[Page Down] | 向下翻一页
[Page Up] | 向上翻一页
[tab] | 在 node 之间移动，有 node 的地方，通常会以 * 显示。
[Enter] | 当游标在 node 上面时，按下 Enter 可以进入该 node 。
b | 移动游标到该 info 画面当中的第一个 node 处
e | 移动游标到该 info 画面当中的最后一个 node 处
n | 前往下一个 node 处
p | 前往上一个 node 处
u | 向上移动一层
s(/) | 在 info page 当中进行搜寻
h | 显示求助选单
? | 指令一览表
q | 结束这次的 info page

info page是只有Linux上面才有的产物，而且易读性增强很多～不过查询的指令说明要具有info page功能的话，得用info page的格式来写成线上求助文件才行！我们CentOS 5将info page的文件放置到/usr/share/info/目录中！至于非以info page格式写成的说明文件(就是man page)，虽然也能够使用info来显示，不过其结果就会跟man相同。 举例来说，你可以下达‘info man’就知道结果了！ ^_^

小标题的图示 其他有用的文件(documents)

刚刚前面说，一般而言，指令或者软体制作者，都会将自己的指令或者是软体的说明制作成‘线上说明文件’！ 但是，毕竟不是每个咚咚都需要做成线上说明文件的，还有相当多的说明需要额外的文件！此时，这个所谓的 How-To(如何做的意思)就很重要啦！还有，某些软体不只告诉你‘如何做’， 还会有一些相关的原理会说明呢。

那么这些说明文件要摆在哪里呢？哈哈！就是摆在/usr/share/doc这个目录啦！所以说，你只要到这个目录底下， 就会发现好多好多的说明文件档啦！还不需要到网路上面找资料呢！厉害吧！^_^ 举例来说，你想要知道这一版的CentOS相关的各项资讯，可以直接到底下的目录去瞧瞧：

  • /usr/share/doc/centos-release-notes-5.3/

那如果想要知道本章讲过多次的bash是什么，则可以到/usr/share/doc/bash-3.2/ 这个目录中去浏览一番！很多东西呦！而且/usr/share/doc这个目录下的资料主要是以套件(packages)为主的， 例如GCC这个套件的相关资讯在/usr/share/doc/gcc-xxx(那个xxx表示版本的意思！)。 未来可得多多查阅这个目录喔！ ^_^

总结上面的三个咚咚(man, info, /usr/share/doc/)，请记住喔：

  • 在文字介面下，有任何你不知道的指令或档案格式这种玩意儿，但是你想要了解他，请赶快使用man或者是info来查询！
  • 而如果你想要架设一些其他的服务，或想要利用一整组软体来达成某项功能时，请赶快到/usr/share/doc 底下查一查有没有该服务的说明档喔！
  • 另外，再次的强调，因为Linux毕竟是外国人发明的，所以中文文件确实是比较少的！ 但是不要害怕，拿本英文字典在身边吧！随时查阅！不要害怕英文喔！
大标题的图示 超简单文书编辑器： nano

在Linux系统当中有非常多的文书编辑器存在，其中最重要的就是后续章节我们会谈到的vi这家伙！ 不过其实还有很多不错用的文书编辑器存在的！在这里我们就介绍一下简单的nano这一支文书编辑器来玩玩先！

nano的使用其实很简单，你可以直接加上档名就能够开启一个旧档或新档！底下我们就来开启一个名为test.txt的档名来看看：

[vbird@www ~]$ nano text.txt

# 不管text.txt存不存在都没有关系！存在就开启旧档，不存在就开启新档

  GNU nano 1.3.12          File: text.txt

   <==这个是游标所在处

                           [ New File ]
^G Get Help^O WriteOut^R Read Fil^Y Prev Pag^K Cut Text^C Cur Pos

^X Exit    ^J Justify ^W Where Is^V Next Pag^U UnCut Te^T To Spell

# 上面两行是指令说明列，其中^代表的是[ctrl]的意思

如上图所示，你可以看到第一行反白的部分，那仅是在宣告nano的版本与档名(File: text.txt)而已。 之后你会看到最底下的三行，分别是档案的状态(New File)与两行指令说明列。指令说明列反白的部分就是组合键， 接的则是该组合键的功能。那个指数符号(^)代表的是键盘的[Ctrl]按键啦！底下先来说说比较重要的几个组合按键：

  • [ctrl]-G：取得线上说明(help)，很有用的！
  • [ctrl]-X：离开naon软体，若有修改过档案会提示是否需要储存喔！
  • [ctrl]-O：储存档案，若你有权限的话就能够储存档案了；
  • [ctrl]-R：从其他档案读入资料，可以将某个档案的内容贴在本档案中；
  • [ctrl]-W：搜寻字串，这个也是很有帮助的指令喔！
  • [ctrl]-C：说明目前游标所在处的行数与列数等资讯；
  • [ctrl]-_：可以直接输入行号，让游标快速移动到该行；
  • [alt]-Y：校正语法功能开启或关闭(按一下开、再按一下关)
  • [alt]-M：可以支援滑鼠来移动游标的功能

比较常见的功能是这些，如果你想要取得更完整的说明，可以在nano的画面中按下[ctrl]-G或者是[F1]按键， 就能够显示出完整的naon内指令说明了。好了，请你在上述的画面中随便输入许多字， 输入完毕之后就储存后离开，如下所示：

  GNU nano 1.3.12          File: text.txt

Type some words in this nano editor program.
You can use [ctrl] plus some keywords to go to some functions.
Hello every one.
Bye bye.
   <==这个是由标所在处

                           [ New File ]
^G Get Help^O WriteOut^R Read Fil^Y Prev Pag^K Cut Text^C Cur Pos

^X Exit    ^J Justify ^W Where Is^V Next Pag^U UnCut Te^T To Spell

此时按下[crtl]-X会出现类似下面的画面：

  GNU nano 1.3.12          File: text.txt

Type some words in this nano editor program.
You can use [ctrl] plus some keywords to go to some functions.
Hello every one.
Bye bye.

Save modified buffer (ANSWERING "No" WILL DESTROY CHANGES) ? ▋

 Y Yes
 N No           ^C Cancel

如果不要储存资料只想要离开，可以按下N即可离开。如果确实是需要储存的，那么按下Y后，最后三行会出现如下画面：

File Name to Write: text.txt▋  <==可在这里修改档名或直接按[enter]
^G Get Help     ^T To Files     M-M Mac Format  M-P Prepend

^C Cancel       M-D DOS Format  M-A Append      M-B Backup File

如果是单纯的想要储存而已，直接按下[enter]即可储存后离开nano程式。不过上图中最底下还有两行，我们知道指数符号代表[crtl]， 那个M是代表什么呢？其实就是[alt]啰！其实nano也不需要记太多指令啦！只要知道怎么进入nano、怎么离开，怎么搜寻字串即可。 未来我们还会学习更有趣的vi呢！

大标题的图示 正确的关机方法

OK！大概知道开机的方法，也知道基本的指令操作，而且还已经知道线上查询了，好累呦！ 想去休息呢！那么如何关机呢？我想，很多朋友在DOS的年代已经有在玩电脑了！ 在当时我们关掉DOS的系统时，常常是直接关掉电源开关，而 Windows 在你不爽的时候，按着电源开关四秒也可以关机！但是在Linux则相当的不建议这么做！

Why？在 Windows (非 NT 主机系统) 系统中，由于是单人假多工的情况，所以即使你的电脑关机， 对于别人应该不会有影响才对！不过呢，在 Linux 底下，由于每个程序 (或者说是服务) 都是在在背景下执行的，因此，在你看不到的荧幕背后其实可能有相当多人同时在你的主机上面工作， 例如浏览网页啦、传送信件啦以 FTP 传送档案啦等等的，如果你直接按下电源开关来关机时， 则其他人的资料可能就此中断！那可就伤脑筋了！

此外，最大的问题是，若不正常关机，则可能造成档案系统的毁损 （因为来不及将资料回写到档案中，所以有些服务的档案会有问题！）。所以正常情况下，要关机时需要注意底下几件事：

  • 观察系统的使用状态：
    如果要看目前有谁在线上，可以下达‘who’这个指令，而如果要看网路的连线状态，可以下达 ‘ netstat -a ’这个指令，而要看背景执行的程序可以执行‘ ps -aux ’这个指令。使用这些指令可以让你稍微了解主机目前的使用状态！当然啰，就可以让你判断是否可以关机了 （这些指令在后面Linux常用指令中会提及喔！）

  • 通知线上使用者关机的时刻：
    要关机前总得给线上的使用者一些时间来结束他们的工作，所以，这个时候你可以使用 shutdown 的特别指令来达到此一功能。

  • 正确的关机指令使用：
    例如 shutdown 与 reboot 两个指令！

所以底下我们就来谈一谈几个与关机/重新开机相关的指令啰！

  • 将资料同步写入硬碟中的指令： sync
  • 惯用的关机指令： shutdown
  • 重新开机，关机： reboot, halt, poweroff
Tips:
由于Linux系统的关机/重新开机是很重大的系统运作，因此只有root才能够进行例如shutdown, reboot等指令。 不过在某些distributions当中，例如我们这里谈到的CentOS系统，他允许你在本机前的tty7使用图形介面登入时， 可以用一般帐号来关机或重新开机！但某些distributions则在你要关机时，他会要你输入root的密码呢！^_^ 		鸟哥的图示
小标题的图示 资料同步写入磁碟： sync

在第零章、计算机概论里面我们谈到过资料在电脑中运作的模式， 所有的资料都得要被读入记忆体后才能够被CPU所处理，但是资料又常常需要由记忆体写回硬碟当中(例如储存的动作)。 由于硬碟的速度太慢(相对于记忆体来说)，如果常常让资料在记忆体与硬碟中来回写入/读出，系统的效能就不会太好。

因此在Linux系统中，为了加快资料的读取速度，所以在预设的情况中， 某些已经载入记忆体中的资料将不会直接被写回硬碟，而是先暂存在记忆体当中，如此一来， 如果一个资料被你重复的改写，那么由于他尚未被写入硬碟中，因此可以直接由记忆体当中读取出来， 在速度上一定是快上相当多的！

不过，如此一来也造成些许的困扰，那就是万一你的系统因为某些特殊情况造成不正常关机 (例如停电或者是不小心踢到power)时，由于资料尚未被写入硬碟当中，哇！所以就会造成资料的更新不正常啦！ 那要怎么办呢？这个时候就需要sync这个指令来进行资料的写入动作啦！ 直接在文字介面下输入sync，那么在记忆体中尚未被更新的资料，就会被写入硬碟中！所以，这个指令在系统关机或重新开机之前， 很重要喔！最好多执行几次！

虽然目前的 shutdown/reboot/halt 等等指令均已经在关机前进行了 sync 这个工具的呼叫， 不过，多做几次总是比较放心点～呵呵～

[root@www ~]# sync
Tips:
事实上sync也可以被一般帐号使用喔！只不过一般帐号使用者所更新的硬碟资料就仅有自己的资料， 不像root可以更新整个系统中的资料了。 		鸟哥的图示
小标题的图示 惯用的关机指令： shutdown

由于Linux的关机是那么重要的工作，因此除了你是在主机前面以tty7图形介面来登入系统时， 不论用什么身份都能够关机之外，若你是使用远端管理工具(如透过pietty使用ssh服务来从其他电脑登入主机)， 那关机就只有root有权力而已喔！

嗯！那么就来关机试试看吧！我们较常使用的是shutdown这个指令，而这个指令会通知系统内的各个程序 (processes)，并且将通知系统中的run-level内的一些服务来关闭。shutdown可以达成如下的工作：

  • 可以自由选择关机模式：是要关机、重新开机或进入单人操作模式均可；
  • 可以设定关机时间: 可以设定成现在立刻关机, 也可以设定某一个特定的时间才关机。
  • 可以自订关机讯息：在关机之前，可以将自己设定的讯息传送给线上 user 。
  • 可以仅发出警告讯息：有时有可能你要进行一些测试，而不想让其他的使用者干扰， 或者是明白的告诉使用者某段时间要注意一下！这个时候可以使用 shutdown 来吓一吓使用者，但却不是真的要关机啦！
  • 可以选择是否要 fsck 检查档案系统 。

那么shutdown的语法是如何呢？聪明的读者大概已经开始找‘男人’了！没错，随时随地的 man 一下，是很不错的举动！好了，简单的语法规则为：

[root@www ~]# /sbin/shutdown [-t 秒] [-arkhncfF] 时间 [警告讯息]
选项与参数：
-t sec ： -t 后面加秒数，亦即‘过几秒后关机’的意思
-k     ： 不要真的关机，只是发送警告讯息出去！
-r     ： 在将系统的服务停掉之后就重新开机(常用)
-h     ： 将系统的服务停掉后，立即关机。 (常用)
-n     ： 不经过 init 程序，直接以 shutdown 的功能来关机
-f     ： 关机并开机之后，强制略过 fsck 的磁碟检查
-F     ： 系统重新开机之后，强制进行 fsck 的磁碟检查
-c     ： 取消已经在进行的 shutdown 指令内容。
时间   ： 这是一定要加入的参数！指定系统关机的时间！时间的范例底下会说明。
范例：
[root@www ~]# /sbin/shutdown -h 10 'I will shutdown after 10 mins'
# 告诉大家，这部机器会在十分钟后关机！并且会显示在目前登入者的荧幕前方！
# 至于参数有哪些呢？以下介绍几个吧！

此外，需要注意的是，时间参数请务必加入指令中，否则shutdown会自动跳到 run-level 1 (就是单人维护的登入情况)，这样就伤脑筋了！底下提供几个时间参数的例子吧：

[root@www ~]# shutdown -h now
立刻关机，其中 now 相当于时间为 0 的状态
[root@www ~]# shutdown -h 20:25

系统在今天的 20:25 分会关机，若在21:25才下达此指令，则隔天才关机
[root@www ~]# shutdown -h +10
系统再过十分钟后自动关机
[root@www ~]# shutdown -r now
系统立刻重新开机
[root@www ~]# shutdown -r +30 'The system will reboot'
再过三十分钟系统会重新开机，并显示后面的讯息给所有在线上的使用者

[root@www ~]# shutdown -k now 'This system will reboot'
仅发出警告信件的参数！系统并不会关机啦！吓唬人！
小标题的图示 重新开机，关机： reboot, halt, poweroff

还有三个指令可以进行重新开机与关机的任务，那就是reboot, halt, poweroff。 其实这三个指令呼叫的函式库都差不多，所以当你使用‘man reboot’时，会同时出现三个指令的用法给你看呢。 其实鸟哥通常都只有记shutdown与reboot这两个指令啦！不过使用poweroff这个指令却比较简单就是了！^_^ 通常鸟哥在重新开机时，都会下达如下的指令喔：

[root@www ~]# sync; sync; sync; reboot

既然这些指令都能够关机或重新开机，那他有没有什么差异啊？基本上，在预设的情况下， 这几个指令都会完成一样的工作！(因为halt会先呼叫shutdown，而shutdown最后会呼叫halt！)。 不过，shutdown可以依据目前已启动的服务来逐次关闭各服务后才关机；至于halt却能够在不理会目前系统状况下， 进行硬体关机的特殊功能！你可以在你的主机上面使用root进行底下两个指令来关机，比较看看差异在哪里喔！

[root@www ~]# shutdown -h now
[root@www ~]# poweroff -f

更多halt与poweroff的选项功能，请务必使用man去查询一下喔！

小标题的图示 切换执行等级： init

本章上头有谈到过关于run level的问题。之前谈到的是系统运作的模式，分为纯文字(run level 3)及图形介面模式(run level 5)。除了这两种模式外，有没有其他模式呢？其实Linux共有七种执行等级， 七种等级的意义我们在后面会再谈到。本章你只要知道底下四种执行等级就好了：

  • run level 0：关机
  • run level 3：纯文字模式
  • run level 5：含有图形介面模式
  • run level 6：重新开机

那如何切换各模式呢？可以使用init这个指令来处理喔！也就是说，如果你想要关机的话， 除了上述的shutdown -h now以及poweroff之外，你也可以使用如下的指令来关机：

[root@www ~]# init 0
大标题的图示 开机过程的问题排解

事实上，Linux主机是很稳定的，除非是硬体问题与系统管理员不小心的动作，否则， 很难会造成一些无法挽回的错误的。但是，毕竟我们目前使用的可能是练习机，会常常开开关关的， 所以确实可能会有一些小问题发生。好了，我们先来简单的谈一谈，如果无法顺利开机时， 你应该如何解决。要注意的是，底下说到的内容很多都还没有开始介绍， 因此，看不懂也不要太紧张～在本书全部都读完且看第二遍时，你自然就会有感觉了！ ^_^

小标题的图示 档案系统错误的问题

在开机的过程中最容易遇到的问题就是硬碟可能有坏轨或档案系统发生错误(资料损毁)的情况， 这种情况虽然不容易发生在稳定的Linux系统下，不过由于不当的开关机行为， 还是可能会造成的，常见的发生原因可能有：

  • 最可能发生的原因是因为断电或不正常关机所导致的档案系统发生错误， 鸟哥的主机就曾经发生过多次因为跳电，家里的主机又没有安装不断电系统， 结果就导致硬碟内的档案系统错误！档案系统错误并非硬体错误，而是软体资料的问题喔！

  • 硬碟使用率过高或主机所在环境不良也是一个可能的原因， 例如你开放了一个FTP服务，里面有些资料很有用， 所以一堆人抢着下载，如果你又不是使用较稳定的SCSI介面硬碟，仅使用一般PC使用的硬碟， 虽然机率真的不高，但还是有可能造成硬碟坏轨的。此外，如果主机所在环境没有散热的设备， 或者是相对湿度比较高的环境，也很容易造成硬碟的损坏喔！

解决的方法其实很简单，不过因为出错磁区所挂载的目录不同，处理的流程困难度就有差异了。 举例来说，如果你的根目录‘/’并没有损毁，那就很容易解决，如果根目录已经损毁了，那就比较麻烦！

  • 如果根目录没有损毁：

假设你发生错误的partition是在/dev/sda7这一块，那么在开机的时候，荧幕应该会告诉你：press root password or ctrl+D : 这时候请输入root的密码登入系统，然后进行如下动作：

  • 在游标处输入root密码登入系统，进行单人单机的维护工作；
  • 输入‘ fsck /dev/sda7 ’(fsck 为档案系统检查的指令，/dev/sda7为错误的partition，请依你的情况下达参数)， 这时荧幕会显示开始修理硬碟的讯息，如果有发现任何的错误时，荧幕会显示： clear [Y/N]？ 的询问讯息，就直接输入 Y 吧！
  • 修理完成之后，以 reboot 重新开机啰！

  • 如果根目录损毁了

一般初学者喜欢将自己的硬碟只划分为一个大partition，亦即只有根目录， 那档案系统错误一定是根目录的问题啰！这时你可以将硬碟拔掉，接到另一台Linux系统的电脑上， 并且不要挂载(mount)该硬碟，然后以root的身份执行‘ fsck /dev/sdb1 ’(/dev/sdb1 指的是你的硬碟装置档名，你要依你的实际状况来设定)，这样就 OK 啰！

另外，也可以使用近年来很热门的Live CD，也就是利用光碟开机就能够进入Linux作业系统的特性， 你可以前往：‘http://knoppix.tnc.edu.tw/’ 这个网站来下载，并且烧录成为CD，这个时候先用Live CD光碟开机，然后使用fsck去修复原本的根目录， 例如： fsck /dev/sda1 ，就能够救回来了！

  • 如果硬碟整个坏掉：

如果硬碟实在坏的离谱时，那就先将旧硬碟内的资料，能救出来的救出来，然后换一颗硬碟来重新安装Linux吧！ 不要不愿意换硬碟啊！啥时后硬碟会坏掉谁也说不准的！

那么硬碟该如何预防发生档案系统错误的问题呢？可以参考底下说明：

  • 妥善保养硬碟：
    例如：主机通电之后不要搬动，避免移动或震动硬碟；尽量降低硬碟的温度，可以加装风扇来冷却硬碟； 或者可以换装 SCSI 硬碟。

  • 划分不同的partition：
    为什么磁碟分割这么重要！因为Linux每个目录被读写的频率不同，妥善的分割将会让我们的Linux更安全！ 通常我们会建议划分下列的磁碟区块：
    • /
    • /boot
    • /usr
    • /home
    • /var
    这样划分有些好处，例如/var是系统预设的一些资料暂存或者是cache资料的储存目录， 像 e-mail 就含在这里面。如果还有使用proxy时，因为常常存取，所以有可能会造成磁碟损坏， 而当这部份的磁碟损坏时，由于其他的地方是没问题的，因此资料得以保存，而且在处理时也比较容易！
小标题的图示 忘记 root 密码：

常常有些朋友在设定好了Linux之后，结果root密码给他忘记去！要重新安装吗？不需要的， 你只要以单人维护模式登入即可更改你的root密码喔！由于lilo这个开机管理程式已经很少见了， 这里鸟哥使用grub开机管理程式作为范例来介绍啰！

先将系统重新开机，在读秒的时候按下任意键就会出现如同第四章图3.2的选单画面，仔细看选单底下的说明， 按下‘e’就能够进入grub的编辑模式了。此时你看到的画面有点像底下这样：

root (hd0,0)
kernel /vmlinuz-2.6.18-128.el5 ro root=LABEL=/ rhgb quiet
initrd /initrd-2.6.18-128.el5.img

此时，请将游标移动到kernel那一行，再按一次‘ e ’进入kernel该行的编辑画面中， 然后在出现的画面当中，最后方输入 single ：

kernel /vmlinuz-2.6.18-128.el5 ro root=LABEL=/ rhgb quiet single

再按下‘ Enter ’确定之后，按下 b 就可以开机进入单人维护模式了！ 在这个模式底下，你会在tty1的地方不需要输入密码即可取得终端机的控制权(而且是使用root的身份喔！)。 之后就能够修改root的密码了！请使用底下的指令来修改root的密码喔！

[root@www ~]# passwd
# 接下来系统会要求你输入两次新的密码，然后再来reboot即可顺利修订root密码了！

这里仅是介绍一个简单的处理方法而已，更多的原理与说明将会在后续的各相关章节介绍的喔！

大标题的图示 重点回顾
  • 为了避免瞬间断电造成的Linux系统危害，建议做为伺服器的Linux主机应该加上不断电系统来持续提供稳定的电力；
  • 预设的图形模式登入中，可以选择语系以及作业阶段。作业阶段为多种视窗管理员软体所提供，如GNOME及KDE等；
  • CentOS 5.x预设的中文输入法为使用SCIM这个软体所提供的输入；
  • 不论是KDE还是GNOME预设都提供四个Virtual Desktop给使用者使用；
  • 在X的环境下想要重新启动X的组合按键为：‘[alt]+[ctrl]+[backspace]’；
  • 预设情况下，Linux提供tty1~tty6的文字介面登入，以及tty7的图形介面登入环境；
  • 除了run level 5预设取得图形介面之外，run level 3亦可使用 startx 进入图形环境；
  • 在终端机环境中，可依据提示字元为$或#判断为一般帐号或root帐号；
  • 取得终端机支援的语系资料可下达‘echo $LANG’或‘locale’指令；
  • date可显示日期、cal可显示日历、bc可以做为计算机软体；
  • 组合按键中，[tab]按键可做为命令补齐或档名补齐，[crtl]-[c]可以中断目前正在运作中的程式；
  • 线上说明系统有man及info两个常见的指令；
  • man page说明后面的数字中，1代表一般帐号可用指令，8代表系统管理员常用指令，5代表系统设定档格式；
  • info page可将一份说明文件拆成多个节点(node)显示，并具有类似超连结的功能，增加易读性；
  • 系统需正确的关机比较不容易损坏，可使用shutdown, poweroff等指令关机。
大标题的图示 本章习题
( 要看答案请将滑鼠移动到‘答：’底下的空白处，按下左键圈选空白处即可察看)
情境模拟题一：我们在tty1里面看到的欢迎画面，就是在那个login:之前的画面(CentOS release 5.3 (Final)...)是怎么来的？
  • 目标：了解到终端机介面的欢迎讯息是怎么来的？
  • 前提：欢迎讯息的内容，是记录到/etc/issue当中的
  • 需求：利用man找到该档案当中的变数内容
情境模拟题一的解决步骤：
  1. 欢迎画面是在/etc/issue档案中，你可以使用‘nano /etc/issue’看看该档案的内容(注意，不要修改这个档案内容，看完就离开)，这个档案的内容有点像底下这样：
    CentOS release 5.3 (Final)
Kernel \r on an \m
  2. 与tty2比较之下，发现到核心版本使用的是 \r 而硬体等级则是 \m 来取代，这两者代表的意义为何？ 由于这个档案的档名是issue，所以我们使用‘man issue’来查阅这个档案的格式；

  3. 透过上一步的查询我们会知道反斜线(\)后面接的字元是与mingetty(8)有关，故进行‘man mingetty’这个指令的查询。

  4. 由于反斜线(\)的英文为‘escape’因此在上个步骤的man环境中，你可以使用‘/escape’来搜寻各反斜线后面所接字元所代表的意义为何。

  5. 请自行找出：如果我想要在/etc/issue档案内表示‘时间(localtime)’与‘tty号码(如tty1, tty2的号码)’的话， 应该要找到那个字元来表示(透过反斜线的功能)？(答案为：\t 与 \l)
简答题部分：
  • 请问如果我以文字模式登入Linux主机时，我有几个终端机介面可以使用？如何切换各个不同的终端机介面？
    共有六个， tty1 ~ tty6 ，切换的方式为 Crtl + Alt + [F1]~[F6]，其中， [F7] 为图形介面的使用。
  • 在Linux系统中，/VBird与/vbird是否为相同的档案？
    两者为不同的档案，因为 Linux 系统中，大小写字母代表意义不一样！
  • 我想要知道 date 如何使用，应该如何查询？
    最简单的方式就是使用 man date 或 info date 来查看，如果该套件有完整说明的话，那么应该也可以在 /usr/share/doc 里面找到说明档！
  • 我想要在今天的 1:30 让系统自己关机，要怎么做？
    shutdown -h 1:30
  • 如果我 Linux 的 X Window 突然发生问题而挂掉，但 Linux 本身还是好好的，那么我可以按下哪三个按键来让 X window 重新启动？
    [crtl]+[alt]+[backspace]
  • 我想要知道 2010 年 5 月 2 日是星期几？该怎么做？
    最简单的方式直接使用 cal 5 2010 即可找出 2010 年 5 月份的月历。
  • 使用 man date 然后找出显示目前的日期与时间的参数，成为类似：2009/10/16-20:03
    date +%Y/%m/%d-%H:%M
  • 若以 X-Window 为预设的登入方式，那请问如何进入 Virtual console 呢？
    可以按下 [Ctrl] + [Alt] + [F1] ~ [F6] 进入 Virtual console ( 共六个 )； 而按下 [Ctrl] + [Alt] + [F8] 或 [F7] 可回到 X-Window 的 desktop 中！
  • 简单说明在 bash shell 的环境下， [tab] 按键的用途？
    [Tab] 按键可做为命令补齐或档案补齐的功能，与所接的指令位置有关。 接在一串指令的第一个单字后面，则为命令补齐，否则则为档案补齐！
  • 如何强制中断一个程式的进行？(利用按键，非利用 kill 指令)
    可以利用 [Ctrl] + c 来中断！
  • Linux 提供相当多的线上查询，称为 man page，请问，我如何知道系统上有多少关于 passwd 的说明？又，可以使用其他的程式来取代 man 的这个功能吗？
    可以利用 man -f passwd 来查询，另外，如果有提供 info 的文件资料时 (在 /usr/share/info/ 目录中) ，则能够利用 info passwd 来查询之！
  • man -k passwd 与 man -K passwd 有什么差异(大小写的 K )？
    小写的 -k 为查询关键字，至于 -K 则是整个系统的 man page 查询～ 每个被检查到有关键字的 man page file 都会被询问是否要显示， 你可以输入‘ynq’，来表示：y:要显示到荧幕上；n:不显示；q:结束 man 的查询。
  • 在 man 的时候， man page 显示的内容中，指令(或档案)后面会接一组数字，这个数字若为 1, 5, 8 ，表示该查询的指令(或档案)意义为何？
    代表意义为 1) 一般使用者可以使用的指令或可执行档案 5)一些设定档的档案内容格式 8)系统管理员能够使用的管理指令。
  • man page 显示的内容的档案是放置在哪些目录中？
    放置在 /usr/share/man/ 与 /usr/local/man 等预设目录中。
  • 请问这一串指令‘ foo1 -foo2 foo3 foo4 ’中，各代表什么意义？
    foo1 一定是指令， -foo2 则是 foo1 这个指令的选择项目参数， foo3 与 foo4 则不一定， 可能是 foo1 的参数设定值，也可能是额外加入的 parameters。
  • 当我输入 man date 时，在我的终端机却出现一些乱码，请问可能的原因为何？如何修正？
    如果没有其他错误的发生，那么发生乱码可能是因为语系的问题所致。 可以利用 LANG=en 或者是 LANG=en_US 等设定来修订这个问题。
  • 我输入这个指令‘ls -al /vbird’，系统回覆我这个结果：‘ls: /vbird: No such file or directory’ 请问发生了什么事？’
    不要紧张，很简单的英文，因为系统根本没有 /vbird 这个档案的存在啊！ ^_^
  • 你目前的 Linux 底下，预设共有多少可以被你执行的指令？
    最简单的做法，直接输入两次 [tab] 按键即可知道有多少指令可以被执行。
  • 我想知道目前系统有多少指令是以 bz 为开头的，可以怎么作？
    直接输入 bz[tab][tab] 就可以知道了！
  • 承上题，在出现的许多指令中，请问 bzip2 是干嘛用的？
    在使用 man bzip2 之后，可以发现到，其实 bzip2 是用来作为压缩与解压缩档案用的！
  • Linux 提供一些线上文献资料，这些资料通常放在那个目录当中
    通常放在 /usr/share/doc 当中！
  • 在终端机里面登入后，看到的提示字元 $ 与 # 有何不同？平时操作应该使用哪一个？
    # 代表以 root 的身份登入系统，而 $ 则代表一般身份使用者。依据提示字元的不同， 我们可以约略判断登入者身份。一般来说，建议日常操作使用一般身份使用者登入，亦即是 $ ！
  • 我使用dmtsai这个帐号登入系统了，请问我能不能使用reboot来重新开机？ 若不能，请说明原因，若可以，请说明指令如何下达？
    理论上reboot仅能让root执行。不过，如果dmtsai是在主机前面以图形介面登入时，则dmtsai还是可以透过图形介面功能来关机。
大标题的图示 参考资料与延伸阅读
  • 注1：为了让Linux的视窗显示效果更佳，很多团体开始发展桌面应用的环境，GNOME/KDE都是。 他们的目标就是发展出类似Windows桌面的一整套可以工作的桌面环境，他可以进行视窗的定位、放大、缩小、 同时还提供很多的桌面应用软体。底下是KDE与GNOME的相关连结：
    http://www.kde.org/
    http://www.gnome.org/
  • 杨锦昌老师的X Window操作图解，以Fedora Core 3为例：http://apt.nc.hcc.edu.tw/docs/FC3_X/
  • man 7 man ：取得更详细的数字说明内容
2002/07/16：第一次完成吧？
2003/02/06：重新编排与加入 FAQ
2004/05/01：在shutdown的指令部分，修改 shutdown -k "messages" 成为 shutdown -k now "messages"，很抱歉，写错了！
2005/06/17：将原本的文章移动到 这里
2005/06/27：终于写完了！写的真久～没办法，将 man page 扩大解释，增加的幅度还挺多的！
2005/08/23：刚刚才发现，那个man page的内部指令说明中， n 与 N 的说明错误了！已订正！
2007/12/08：透过网友sheaushyong的发现，之前将Live CD中，说明要挂载 / 才 fsck 是不对的！请查阅此处。
2008/09/03：将原本的Fedora Core IV的文章移动到此处。
2008/09/08：加入了一些图示说明，尤其是info的部分多了一个示意图！
2008/09/09：加入了nano这个简单的文书编辑器说明，以及情境模拟题的解释！
2009/09/17：修订了显示的资讯，将图片重新抓图汇整。


鸟哥的 Linux 私房菜 -- 基础学习篇

为取得较佳浏览结果，请爱用 firefox 浏览本网页

第六章、Linux 的档案权限与目录配置
最近更新日期：2009/08/18
Linux最优秀的地方之一，就在于他的多人多工环境。而为了让各个使用者具有较保密的档案资料，因此档案的权限管理就变的很重要了。 Linux一般将档案可存取的身份分为三个类别，分别是 owner/group/others，且三种身份各有 read/write/execute 等权限。若管理不当，你的Linux主机将会变的很‘不苏服！@_@’。另外，你如果首次接触Linux的话，那么， 在Linux底下这么多的目录/档案，到底每个目录/档案代表什么意义呢？底下我们就来一一介绍呢！

1. 使用者与群组
2. Linux档案权限概念
    2.1 Linux档案属性
    2.2 如何改变档案属性与权限： chgrp, chown, chmod
    2.3 目录与档案之权限意义
    2.4 Linux档案种类与副档名
 3. Linux目录配置
    3.1 Linux目录配置的依据--FHS：/, /usr, /var
    3.2 目录树(directory tree)
    3.3 绝对路径与相对路径
    3.4 CentOS 的观察： lsb_release
 4. 重点回顾
5. 本章练习
6. 参考资料与延伸阅读
7. 针对本文的建议：http://phorum.vbird.org/viewtopic.php?t=23878
大标题的图示 使用者与群组

经过第五章的洗礼之后，你应该可以在Linux的指令列模式底下输入指令了吧？ 接下来，当然是要让你好好的浏览一下Linux系统里面有哪些重要的档案啰。 不过，每个档案都有相当多的属性与权限，其中最重要的可能就是档案的拥有者的概念了。 所以，在开始档案相关资讯的介绍前，鸟哥先就简单的(1)使用者及(2)群组与(3)非本群组外的其他人等概念作个说明吧～ 好让你快点进入状况的哩！ ^_^

  1. 档案拥有者

    初次接触Linux的朋友大概会觉得很怪异，怎么‘Linux有这么多使用者， 还分什么群组，有什么用？’。这个‘使用者与群组’的功能可是相当健全而好用的一个安全防护呢！怎么说呢？ 由于Linux是个多人多工的系统，因此可能常常会有多人同时使用这部主机来进行工作的情况发生， 为了考虑每个人的隐私权以及每个人喜好的工作环境，因此，这个‘档案拥有者’的角色就显的相当的重要了！

    例如当你将你的e-mail情书转存成档案之后，放在你自己的家目录，你总不希望被其他人看见自己的情书吧？ 这个时候，你就把该档案设定成‘只有档案拥有者，就是我，才能看与修改这个档案的内容’， 那么即使其他人知道你有这个相当‘有趣’的档案，不过由于你有设定适当的权限， 所以其他人自然也就无法知道该档案的内容啰！

  2. 群组概念

    那么群组呢？为何要设定档案还有所属的群组？其实，群组最有用的功能之一，就是当你在团队开发资源的时候啦！ 举例来说，假设有两组专题生在我的主机里面，第一个专题组别为projecta，里面的成员有 class1, class2, class3三个；第二个专题组别为projectb，里面的成员有class4, class5, class6。 这两个专题之间是有竞争性质的，但却要缴交同一份报告。每组的组员之间必须要能够互相修改对方的资料， 但是其他组的组员则不能看到本组自己的档案内容，此时该如何是好？

    在Linux底下这样的限制是很简单啦！我可以经由简易的档案权限设定，就能限制非自己团队(亦即是群组啰) 的其他人不能够阅览内容啰！而且亦可以让自己的团队成员可以修改我所建立的档案！ 同时，如果我自己还有私人隐密的文件，仍然可以设定成让自己的团队成员也看不到我的档案资料。 很方便吧！

    另外，如果teacher这个帐号是projecta与projectb这两个专题的老师， 他想要同时观察两者的进度，因此需要能够进入这两个群组的权限时，你可以设定teacher这个帐号， ‘同时支援projecta与projectb这两个群组！’，也就是说：每个帐号都可以有多个群组的支援呢！

    这样说或许你还不容易理解这个使用者与群组的关系吧？没关系，我们可以使用目前‘家庭’的观念来进行解说喔！ 假设有一家人，家里只有三兄弟，分别是王大毛、王二毛与王三毛三个人， 而这个家庭是登记在王大毛的名下的！所以，‘王大毛家有三个人，分别是王大毛、王二毛与王三毛’， 而且这三个人都有自己的房间，并且共同拥有一个客厅喔！

    • 使用者的意义：由于王家三人各自拥有自己的房间，所以， 王二毛虽然可以进入王三毛的房间，但是二毛不能翻三毛的抽屉喔！那样会被三毛K的！ 因为抽屉里面可能有三毛自己私人的东西，例如情书啦，日记啦等等的，这是‘私人的空间’，所以当然不能让二毛拿啰！

    • 群组的概念：由于共同拥有客厅，所以王家三兄弟可以在客厅打开电视机啦、 翻阅报纸啦、坐在沙发上面发呆啦等等的！ 反正，只要是在客厅的玩意儿，三兄弟都可以使用喔！ 因为大家都是一家人嘛！

    这样说来应该有点晓得了喔！那个‘王大毛家’就是所谓的‘群组’啰， 至于三兄弟就是分别为三个‘使用者’，而这三个使用者是在同一个群组里面的喔！ 而三个使用者虽然在同一群组内，但是我们可以设定‘权限’， 好让某些使用者个人的资讯不被群组的拥有者查询，以保有个人‘私人的空间’啦！ 而设定群组共享，则可让大家共同分享喔！

  3. 其他人的概念

    好了，那么今天又有个人，叫做张小猪，他是张小猪家的人，与王家没有关系啦！ 这个时候，除非王家认识张小猪，然后开门让张小猪进来王家，否则张小猪永远没有办法进入王家， 更不要说进到王三毛的房间啦！不过，如果张小猪透过关系认识了三毛，并且跟王三毛成为好朋友， 那么张小猪就可以透过三毛进入王家啦！呵呵！没错！那个张小猪就是所谓的‘其他人，Others’啰！

    因此，我们就可以知道啦，在Linux里面，任何一个档案都具有‘User, Group及Others’三种身份的个别权限， 我们可以将上面的说明以底下的图示来解释：

    每个档案的拥有者、群组与 others 的示意图
    图1.1、每个档案的拥有者、群组与其他人的示意图

    我们以王三毛为例，王三毛这个‘档案’的拥有者为王三毛，他属于王大毛这个群组， 而张小猪相对于王三毛，则只是一个‘其他人(others)’而已。

    不过，这里有个特殊的人物要来介绍的，那就是‘万能的天神’！这个天神具有无限的神力， 所以他可以到达任何他想要去的地方，呵呵！那个人在Linux系统中的身份代号是‘ root ’啦！所以要小心喔！那个root可是‘万能的天神’喔！

    无论如何，‘使用者身份’，与该使用者所支援的‘群组’概念，在Linux的世界里面是相当的重要的， 他可以帮助你让你的多工Linux环境变的更容易管理！更详细的 ‘身份与群组’ 设定，我们将在第十四章、帐号管理再进行解说。 底下我们将针对档案系统与档案权限来进行说明。
  • Linux 使用者身份与群组记录的档案

在我们Linux系统当中，预设的情况下，所有的系统上的帐号与一般身份使用者，还有那个root的相关资讯， 都是记录在/etc/passwd这个档案内的。至于个人的密码则是记录在/etc/shadow这个档案下。 此外，Linux所有的群组名称都纪录在/etc/group内！这三个档案可以说是Linux系统里面帐号、密码、群组资讯的集中地啰！ 不要随便删除这三个档案啊！ ^_^

至于更多的与帐号群组有关的设定，还有这三个档案的格式，不要急，我们在第十四章的帐号管理时，会再跟大家详细的介绍的！这里先有概念即可。

大标题的图示 Linux 档案权限概念

大致了解了Linux的使用者与群组之后，接着下来，我们要来谈一谈， 这个档案的权限要如何针对这些所谓的‘使用者’与‘群组’来设定呢？ 这个部分是相当重要的，尤其对于初学者来说，因为档案的权限与属性是学习Linux的一个相当重要的关卡， 如果没有这部份的概念，那么你将老是听不懂别人在讲什么呢！尤其是当你在你的荧幕前面出现了‘Permission deny’的时候，不要担心，‘肯定是权限设定错误’啦！呵呵！好了，闲话不多聊，赶快来瞧一瞧先。

小标题的图示 Linux档案属性

嗯！既然要让你了解Linux的档案属性，那么有个重要的也是常用的指令就必须要先跟你说啰！那一个？就是‘ ls ’这一个察看档案的指令啰！在你以root的身份登入Linux之后，下达‘ ls -al ’看看，会看到底下的几个咚咚：

[root@www ~]# ls -al
total 156
drwxr-x---   4    root   root     4096   Sep  8 14:06 .
drwxr-xr-x  23    root   root     4096   Sep  8 14:21 ..
-rw-------   1    root   root     1474   Sep  4 18:27 anaconda-ks.cfg
-rw-------   1    root   root      199   Sep  8 17:14 .bash_history
-rw-r--r--   1    root   root       24   Jan  6  2007 .bash_logout
-rw-r--r--   1    root   root      191   Jan  6  2007 .bash_profile
-rw-r--r--   1    root   root      176   Jan  6  2007 .bashrc
-rw-r--r--   1    root   root      100   Jan  6  2007 .cshrc
drwx------   3    root   root     4096   Sep  5 10:37 .gconf      <=范例说明处
drwx------   2    root   root     4096   Sep  5 14:09 .gconfd
-rw-r--r--   1    root   root    42304   Sep  4 18:26 install.log <=范例说明处
-rw-r--r--   1    root   root     5661   Sep  4 18:25 install.log.syslog

[    1   ][  2 ][   3  ][  4 ][    5   ][     6     ][       7          ]
[  权限  ][连结][拥有者][群组][档案容量][  修改日期 ][      档名        ]
Tips:
由于本章后续的chgrp, chown等指令可能都需要使用root的身份才能够处理，所以这里建议您以root的身份登入Linux来学习本章。 		鸟哥的图示

ls是‘list’的意思，重点在显示档案的档名与相关属性。而选项‘-al’则表示列出所有的档案详细的权限与属性 (包含隐藏档，就是档名第一个字元为‘ . ’的档案)。如上所示，在你第一次以root身份登入Linux时， 如果你输入上述指令后，应该有上列的几个东西，先解释一下上面七个栏位个别的意思：

档案属性的示意图
图2.1.1、档案属性的示意图

  • 第一栏代表这个档案的类型与权限(permission)：

这个地方最需要注意了！仔细看的话，你应该可以发现这一栏其实共有十个字元：(图2.1.1及图2.1.2内的权限并无关系)

档案的类型与权限之内容
图2.1.2、档案的类型与权限之内容

  • 第一个字元代表这个档案是‘目录、档案或连结档等等’：

    • 当为[ d ]则是目录，例如上表档名为‘.gconf’的那一行；
    • 当为[ - ]则是档案，例如上表档名为‘install.log’那一行；
    • 若是[ l ]则表示为连结档(link file)；
    • 若是[ b ]则表示为装置档里面的可供储存的周边设备(可随机存取装置)；
    • 若是[ c ]则表示为装置档里面的序列埠设备，例如键盘、滑鼠(一次性读取装置)。

  • 接下来的字元中，以三个为一组，且均为‘rwx’ 的三个参数的组合。其中，[ r ]代表可读(read)、[ w ]代表可写(write)、[ x ]代表可执行(execute)。 要注意的是，这三个权限的位置不会改变，如果没有权限，就会出现减号[ - ]而已。

    • 第一组为‘档案拥有者的权限’，以‘install.log’那个档案为例， 该档案的拥有者可以读写，但不可执行；
    • 第二组为‘同群组的权限’；
    • 第三组为‘其他非本群组的权限’。

例题：
若有一个档案的类型与权限资料为‘-rwxr-xr--’，请说明其意义为何？
答：
先将整个类型与权限资料分开查阅，并将十个字元整理成为如下所示：
[-][rwx][r-x][r--]
1 234 567 890
1 为：代表这个档名为目录或档案，本例中为档案(-)；
234为：拥有者的权限，本例中为可读、可写、可执行(rwx)；
567为：同群组使用者权限，本例中为可读可执行(rx)；
890为：其他使用者权限，本例中为可读(r)

同时注意到，rwx所在的位置是不会改变的，有该权限就会显示字元，没有该权限就变成减号(-)就是了。

另外，目录与档案的权限意义并不相同，这是因为目录与档案所记录的资料内容不相同所致。 由于目录与档案的权限意义非常的重要，所以鸟哥将他独立到2.3节目录与档案之权限意义中再来谈。

  • 第二栏表示有多少档名连结到此节点(i-node)：

每个档案都会将他的权限与属性记录到档案系统的i-node中，不过，我们使用的目录树却是使用档名来记录， 因此每个档名就会连结到一个i-node啰！这个属性记录的，就是有多少不同的档名连结到相同的一个i-node号码去就是了。 关于i-node的相关资料我们会在第八章谈到档案系统时再加强介绍的。

  • 第三栏表示这个档案(或目录)的‘拥有者帐号’
  • 第四栏表示这个档案的所属群组

在Linux系统下，你的帐号会附属于一个或多个的群组中。举刚刚我们提到的例子，class1, class2, class3均属于projecta这个群组，假设某个档案所属的群组为projecta，且该档案的权限如图2.1.2所示(-rwxrwx---)， 则class1, class2, class3三人对于该档案都具有可读、可写、可执行的权限(看群组权限)。 但如果是不属于projecta的其他帐号，对于此档案就不具有任何权限了。

  • 第五栏为这个档案的容量大小，预设单位为bytes；
  • 第六栏为这个档案的建档日期或者是最近的修改日期：

这一栏的内容分别为日期(月/日)及时间。如果这个档案被修改的时间距离现在太久了，那么时间部分会仅显示年份而已。 如下所示：

[root@www ~]# ls -l /etc/termcap /root/install.log
-rw-r--r-- 1 root root 807103 Jan  7  2007 /etc/termcap
-rw-r--r-- 1 root root  42304 Sep  4 18:26 /root/install.log
# 如上所示，/etc/termcap 为 2007 年所修改过的档案，离现在太远之故；
# 至于 install.log 是今年 (2009) 所建立的，所以就显示完整的时间了。

如果想要显示完整的时间格式，可以利用ls的选项，亦即：‘ls -l --full-time’就能够显示出完整的时间格式了！包括年、月、日、时间喔。 另外，如果你当初是以繁体中文安装你的Linux系统，那么日期栏位将会以中文来显示。 可惜的是，中文并没有办法在纯文字的终端机模式中正确的显示，所以此栏会变成乱码。 那你就得要使用‘LANG=en_US’来修改语系喔！

如果想要让系统预设的语系变成英文的话，那么你可以修改系统设定档‘/etc/sysconfig/i18n’，利用第五章谈到的nano来修改该档案的内容，使LANG这个变数成为上述的内容即可。

  • 第七栏为这个档案的档名

这个栏位就是档名了。比较特殊的是：如果档名之前多一个‘ . ’，则代表这个档案为‘隐藏档’，例如上表中的.gconf那一行，该档案就是隐藏档。 你可以使用‘ls’及‘ls -a’这两个指令去感受一下什么是隐藏档啰！

Tips:
对于更详细的 ls 用法，还记得怎么查询吗？对啦！使用 man ls 或 info ls 去看看他的基础用法去！自我进修是很重要的， 因为‘师傅带进门，修行看个人！’，自古只有天才学生，没有天才老师呦！加油吧！^_^ 		鸟哥的图示

这七个栏位的意义是很重要的！务必清楚的知道各个栏位代表的意义！尤其是第一个栏位的九个权限， 那是整个Linux档案权限的重点之一。底下我们来做几个简单的练习，你就会比较清楚啰！

例题：
假设test1, test2, test3同属于testgroup这个群组，如果有下面的两个档案，请说明两个档案的拥有者与其相关的权限为何？
-rw-r--r--  1 root     root          238 Jun 18 17:22 test.txt
-rwxr-xr--  1 test1    testgroup    5238 Jun 19 10:25 ping_tsai
答：
  • 档案test.txt的拥有者为root，所属群组为root。至于权限方面则只有root这个帐号可以存取此档案，其他人则仅能读此档案；

  • 另一个档案ping_tsai的拥有者为test1，而所属群组为testgroup。其中：
    • test1 可以针对此档案具有可读可写可执行的权力；
    • 而同群组的test2, test3两个人与test1同样是testgroup的群组帐号，则仅可读可执行但不能写(亦即不能修改)；
    • 至于非testgoup这一个群组的人则仅可以读，不能写也不能执行！

例题：
如果我的目录为底下的样式，请问testgroup这个群组的成员与其他人(others)是否可以进入本目录？
    drwxr-xr--   1 test1    testgroup    5238 Jun 19 10:25 groups/
答：
  • 档案拥有者test1[rwx]可以在本目录中进行任何工作；
  • 而testgroup这个群组[r-x]的帐号，例如test2, test3亦可以进入本目录进行工作，但是不能在本目录下进行写入的动作；
  • 至于other的权限中[r--]虽然有r ，但是由于没有x的权限，因此others的使用者，并不能进入此目录！

  • Linux档案权限的重要性：

与Windows系统不一样的是，在Linux系统当中，每一个档案都多加了很多的属性进来，尤其是群组的概念，这样有什么用途呢？ 其实，最大的用途是在‘资料安全性’上面的。

  • 系统保护的功能：
    举个简单的例子，在你的系统中，关于系统服务的档案通常只有root才能读写或者是执行，例如/etc/shadow这一个帐号管理的档案，由于该档案记录了你系统中所有帐号的资料， 因此是很重要的一个设定档，当然不能让任何人读取(否则密码会被窃取啊)，只有root才能够来读取啰！所以该档案的权限就会成为[ -rw------- ]啰！

  • 团队开发软体或资料共用的功能：
    此外，如果你有一个软体开发团队，在你的团队中，你希望每个人都可以使用某一些目录下的档案， 而非你的团队的其他人则不予以开放呢？以上面的例子来说，testgroup的团队共有三个人，分别是test1, test2, test3，那么我就可以将团队所需的档案权限订为[ -rwxrwx--- ]来提供给testgroup的工作团队使用啰！

  • 未将权限设定妥当的危害：
    再举个例子来说，如果你的目录权限没有作好的话，可能造成其他人都可以在你的系统上面乱搞啰！ 例如本来只有root才能做的开关机、ADSL的拨接程式、新增或删除使用者等等的指令，若被你改成任何人都可以执行的话， 那么如果使用者不小心给你重新开机啦！重新拨接啦！等等的！那么你的系统不就会常常莫名其妙的挂掉啰！ 而且万一你的使用者的密码被其他不明人士取得的话，只要他登入你的系统就可以轻而易举的执行一些root的工作！

可怕吧！因此，在你修改你的linux档案与目录的属性之前，一定要先搞清楚， 什么资料是可变的，什么是不可变的！千万注意啰！接下来我们来处理一下档案属性与权限的变更吧！

小标题的图示 如何改变档案属性与权限

我们现在知道档案权限对于一个系统的安全重要性了，也知道档案的权限对于使用者与群组的相关性， 那么如何修改一个档案的属性与权限呢？又！有多少档案的权限我们可以修改呢？ 其实一个档案的属性与权限有很多！我们先介绍几个常用于群组、拥有者、各种身份的权限之修改的指令，如下所示：

  • chgrp ：改变档案所属群组
  • chown ：改变档案拥有者
  • chmod ：改变档案的权限, SUID, SGID, SBIT等等的特性
  • 改变所属群组, chgrp

改变一个档案的群组真是很简单的，直接以chgrp来改变即可，咦！这个指令就是change group的缩写嘛！这样就很好记了吧！ ^_^。不过，请记得，要被改变的群组名称必须要在/etc/group档案内存在才行，否则就会显示错误！

假设你是以root的身份登入Linux系统的，那么在你的家目录内有一个install.log的档案， 如何将该档案的群组改变一下呢？假设你已经知道在/etc/group里面已经存在一个名为users的群组， 但是testing这个群组名字就不存在/etc/group当中了，此时改变群组成为users与testing分别会有什么现象发生呢？

[root@www ~]# chgrp [-R] dirname/filename ...
选项与参数：
-R : 进行递回(recursive)的持续变更，亦即连同次目录下的所有档案、目录
     都更新成为这个群组之意。常常用在变更某一目录内所有的档案之情况。
范例：
[root@www ~]# chgrp users install.log
[root@www ~]# ls -l
-rw-r--r--  1 root users 68495 Jun 25 08:53 install.log
[root@www ~]# chgrp testing install.log

chgrp: invalid group name `testing' <== 发生错误讯息啰～找不到这个群组名～

发现了吗？档案的群组被改成users了，但是要改成testing的时候， 就会发生错误～注意喔！发生错误讯息还是要努力的查一查错误讯息的内容才好！ 将他英文翻译成为中文，就知道问题出在哪里了。

  • 改变档案拥有者, chown

如何改变一个档案的拥有者呢？很简单呀！既然改变群组是change group，那么改变拥有者就是change owner啰！BINGO！那就是chown这个指令的用途，要注意的是， 使用者必须是已经存在系统中的帐号，也就是在/etc/passwd 这个档案中有纪录的使用者名称才能改变。

chown的用途还满多的，他还可以顺便直接修改群组的名称呢！此外，如果要连目录下的所有次目录或档案同时更改档案拥有者的话，直接加上 -R 的选项即可！我们来看看语法与范例：

[root@www ~]# chown [-R] 帐号名称 档案或目录
[root@www ~]# chown [-R] 帐号名称:群组名称 档案或目录
选项与参数：
-R : 进行递回(recursive)的持续变更，亦即连同次目录下的所有档案都变更

范例：将install.log的拥有者改为bin这个帐号：
[root@www ~]# chown bin install.log
[root@www ~]# ls -l
-rw-r--r--  1 bin  users 68495 Jun 25 08:53 install.log

范例：将install.log的拥有者与群组改回为root：
[root@www ~]# chown root:root install.log

[root@www ~]# ls -l
-rw-r--r--  1 root root 68495 Jun 25 08:53 install.log
Tips:
事实上，chown也可以使用‘chown user.group file’，亦即在拥有者与群组间加上小数点‘.’也行！ 不过很多朋友设定帐号时，喜欢在帐号当中加入小数点(例如vbird.tsai这样的帐号格式)，这就会造成系统的误判了！ 所以我们比较建议使用冒号‘:’来隔开拥有者与群组啦！此外，chown也能单纯的修改所属群组呢！ 例如‘chown .sshd install.log’就是修改群组～看到了吗？就是那个小数点的用途！ 		鸟哥的图示

知道如何改变档案的群组与拥有者了，那么什么时候要使用chown或chgrp呢？或许你会觉得奇怪吧？ 是的，确实有时候需要变更档案的拥有者的，最常见的例子就是在复制档案给你之外的其他人时， 我们使用最简单的cp指令来说明好了：

[root@www ~]# cp 来源档案 目的档案

假设你今天要将.bashrc这个档案拷贝成为.bashrc_test档名，且是要给bin这个人，你可以这样做：

[root@www ~]# cp .bashrc .bashrc_test

[root@www ~]# ls -al .bashrc*
-rw-r--r--  1 root root 395 Jul  4 11:45 .bashrc
-rw-r--r--  1 root root 395 Jul 13 11:31 .bashrc_test  <==新档案的属性没变

由于复制行为(cp)会复制执行者的属性与权限，所以！怎么办？.bashrc_test还是属于root所拥有， 如此一来，即使你将档案拿给bin这个使用者了，那他仍然无法修改的(看属性/权限就知道了吧)， 所以你就必须要将这个档案的拥有者与群组修改一下啰！知道如何修改了吧？

  • 改变权限, chmod

档案权限的改变使用的是chmod这个指令，但是，权限的设定方法有两种， 分别可以使用数字或者是符号来进行权限的变更。我们就来谈一谈：

  • 数字类型改变档案权限

    Linux档案的基本权限就有九个，分别是owner/group/others三种身份各有自己的read/write/execute权限， 先复习一下刚刚上面提到的资料：档案的权限字元为：‘-rwxrwxrwx’， 这九个权限是三个三个一组的！其中，我们可以使用数字来代表各个权限，各权限的分数对照表如下：
    r:4
    w:2
    x:1
    每种身份(owner/group/others)各自的三个权限(r/w/x)分数是需要累加的，例如当权限为： [-rwxrwx---] 分数则是：
    owner = rwx = 4+2+1 = 7
    group = rwx = 4+2+1 = 7
    others= --- = 0+0+0 = 0
    所以等一下我们设定权限的变更时，该档案的权限数字就是770啦！变更权限的指令chmod的语法是这样的：
    [root@www ~]# chmod [-R] xyz 档案或目录
选项与参数：
xyz : 就是刚刚提到的数字类型的权限属性，为 rwx 属性数值的相加。
-R : 进行递回(recursive)的持续变更，亦即连同次目录下的所有档案都会变更
    举例来说，如果要将.bashrc这个档案所有的权限都设定启用，那么就下达：
    [root@www ~]# ls -al .bashrc

-rw-r--r--  1 root root 395 Jul  4 11:45 .bashrc
[root@www ~]# chmod 777 .bashrc
[root@www ~]# ls -al .bashrc
-rwxrwxrwx  1 root root 395 Jul  4 11:45 .bashrc
    那如果要将权限变成‘ -rwxr-xr-- ’呢？那么权限的分数就成为 [4+2+1][4+0+1][4+0+0]=754 啰！所以你需要下达‘ chmod 754 filename’。 另外，在实际的系统运作中最常发生的一个问题就是，常常我们以vim编辑一个shell的文字批次档后，他的权限通常是 -rw-rw-r-- 也就是664， 如果要将该档案变成可执行档，并且不要让其他人修改此一档案的话， 那么就需要-rwxr-xr-x这样的权限，此时就得要下达：‘ chmod 755 test.sh ’的指令啰！

    另外，如果有些档案你不希望被其他人看到，那么应该将档案的权限设定为例如：‘-rwxr-----’，那就下达‘ chmod 740 filename ’吧！

    例题：
    将刚刚你的.bashrc这个档案的权限修改回-rw-r--r--的情况吧！
    答：
    -rw-r--r--的分数是644，所以指令为：
    chmod 644 .bashrc

  • 符号类型改变档案权限

    还有一个改变权限的方法呦！从之前的介绍中我们可以发现，基本上就九个权限分别是(1)user (2)group (3)others三种身份啦！那么我们就可以藉由u, g, o来代表三种身份的权限！此外， a 则代表 all 亦即全部的身份！那么读写的权限就可以写成r, w, x啰！也就是可以使用底下的方式来看：

    chmod u
    g
    o
    a     		+(加入)
    -(除去)
    =(设定)     		r
    w
    x     		档案或目录

    来实作一下吧！假如我们要‘设定’一个档案的权限成为‘-rwxr-xr-x’时，基本上就是：

    • user (u)：具有可读、可写、可执行的权限；
    • group 与 others (g/o)：具有可读与执行的权限。

    所以就是：
    [root@www ~]# chmod  u=rwx,go=rx  .bashrc
# 注意喔！那个 u=rwx,go=rx 是连在一起的，中间并没有任何空白字元！
[root@www ~]# ls -al .bashrc
-rwxr-xr-x  1 root root 395 Jul  4 11:45 .bashrc
    那么假如是‘ -rwxr-xr-- ’这样的权限呢？可以使用‘ chmod u=rwx,g=rx,o=r filename ’来设定。此外，如果我不知道原先的档案属性，而我只想要增加.bashrc这个档案的每个人均可写入的权限， 那么我就可以使用：
    [root@www ~]# ls -al .bashrc
-rwxr-xr-x  1 root root 395 Jul  4 11:45 .bashrc
[root@www ~]# chmod  a+w  .bashrc
[root@www ~]# ls -al .bashrc
-rwxrwxrwx  1 root root 395 Jul  4 11:45 .bashrc
    而如果是要将权限去掉而不更动其他已存在的权限呢？例如要拿掉全部人的可执行权限，则：
    [root@www ~]# chmod  a-x  .bashrc
[root@www ~]# ls -al .bashrc
-rw-rw-rw-  1 root root 395 Jul  4 11:45 .bashrc
    知道 +, -, = 的不同点了吗？对啦！ + 与 – 的状态下，只要是没有指定到的项目，则该权限‘不会被变动’， 例如上面的例子中，由于仅以 – 拿掉 x 则其他两个保持当时的值不变！多多实作一下，你就会知道如何改变权限啰！ 这在某些情况底下很好用的～举例来说，你想要教一个朋友如何让一个程式可以拥有执行的权限， 但你又不知道该档案原本的权限为何，此时，利用‘chmod a+x filename’ ，就可以让该程式拥有执行的权限了。是否很方便？
小标题的图示 目录与档案之权限意义：

现在我们知道了Linux系统内档案的三种身份(拥有者、群组与其他人)，知道每种身份都有三种权限(rwx)， 已知道能够使用chown, chgrp, chmod去修改这些权限与属性，当然，利用ls -l去观察档案也没问题。 前两小节也谈到了这些档案权限对于资料安全的重要性。那么，这些档案权限对于一般档案与目录档案有何不同呢？ 有大大的不同啊！底下就让鸟哥来说清楚，讲明白！

  • 权限对档案的重要性

档案是实际含有资料的地方，包括一般文字档、资料库内容档、二进位可执行档(binary program)等等。 因此，权限对于档案来说，他的意义是这样的：

  • r (read)：可读取此一档案的实际内容，如读取文字档的文字内容等；
  • w (write)：可以编辑、新增或者是修改该档案的内容(但不含删除该档案)；
  • x (eXecute)：该档案具有可以被系统执行的权限。

那个可读(r)代表读取档案内容是还好了解，那么可执行(x)呢？这里你就必须要小心啦！ 因为在Windows底下一个档案是否具有执行的能力是藉由‘ 副档名 ’来判断的， 例如：.exe, .bat, .com 等等，但是在Linux底下，我们的档案是否能被执行，则是藉由是否具有‘x’这个权限来决定的！跟档名是没有绝对的关系的！

至于最后一个w这个权限呢？当你对一个档案具有w权限时，你可以具有写入/编辑/新增/修改档案的内容的权限， 但并不具备有删除该档案本身的权限！对于档案的rwx来说， 主要都是针对‘档案的内容’而言，与档案档名的存在与否没有关系喔！因为档案记录的是实际的资料嘛！

  • 权限对目录的重要性

档案是存放实际资料的所在，那么目录主要是储存啥玩意啊？目录主要的内容在记录档名清单，档名与目录有强烈的关连啦！ 所以如果是针对目录时，那个 r, w, x 对目录是什么意义呢？

  • r (read contents in directory)：

    表示具有读取目录结构清单的权限，所以当你具有读取(r)一个目录的权限时，表示你可以查询该目录下的档名资料。 所以你就可以利用 ls 这个指令将该目录的内容列表显示出来！

  • w (modify contents of directory)：

    这个可写入的权限对目录来说，是很了不起的！ 因为他表示你具有异动该目录结构清单的权限，也就是底下这些权限：

    • 建立新的档案与目录；
    • 删除已经存在的档案与目录(不论该档案的权限为何！)
    • 将已存在的档案或目录进行更名；
    • 搬移该目录内的档案、目录位置。

    总之，目录的w权限就与该目录底下的档名异动有关就对了啦！

  • x (access directory)：

    咦！目录的执行权限有啥用途啊？目录只是记录档名而已，总不能拿来执行吧？没错！目录不可以被执行，目录的x代表的是使用者能否进入该目录成为工作目录的用途！ 所谓的工作目录(work directory)就是你目前所在的目录啦！举例来说，当你登入Linux时， 你所在的家目录就是你当下的工作目录。而变换目录的指令是‘cd’(change directory)啰！

大致的目录权限概念是这样，底下我们来看几个范例，让你了解一下啥是目录的权限啰！

例题：
有个目录的权限如下所示：
drwxr--r--  3  root  root  4096   Jun 25 08:35   .ssh
系统有个帐号名称为vbird，这个帐号并没有支援root群组，请问vbird对这个目录有何权限？是否可切换到此目录中？
答：
vbird对此目录仅具有r的权限，因此vbird可以查询此目录下的档名列表。因为vbird不具有x的权限， 因此vbird并不能切换到此目录内！(相当重要的概念！)

上面这个例题中因为vbird具有r的权限，因为是r乍看之下好像就具有可以进入此目录的权限，其实那是错的。 能不能进入某一个目录，只与该目录的x权限有关啦！此外， 工作目录对于指令的执行是非常重要的，如果你在某目录下不具有x的权限， 那么你就无法切换到该目录下，也就无法执行该目录下的任何指令，即使你具有该目录的r的权限。

很多朋友在架设网站的时候都会卡在一些权限的设定上，他们开放目录资料给网际网路的任何人来浏览， 却只开放r的权限，如上面的范例所示那样，那样的结果就是导致网站伺服器软体无法到该目录下读取档案(最多只能看到档名)， 最终用户总是无法正确的查阅到档案的内容(显示权限不足啊！)。要注意：要开放目录给任何人浏览时，应该至少也要给予r及x的权限，但w权限不可随便给！ 为什么w不能随便给，我们来看下一个例子：

例题：
假设有个帐号名称为dmtsai，他的家目录在/home/dmtsai/，dmtsai对此目录具有[rwx]的权限。 若在此目录下有个名为the_root.data的档案，该档案的权限如下：
-rwx------ 1 root  root  4365 Sep 19 23:20  the_root.data
请问dmtsai对此档案的权限为何？可否删除此档案？
答：
如上所示，由于dmtsai对此档案来说是‘others’的身份，因此这个档案他无法读、无法编辑也无法执行， 也就是说，他无法变动这个档案的内容就是了。

但是由于这个档案在他的家目录下， 他在此目录下具有rwx的完整权限，因此对于the_root.data这个‘档名’来说，他是能够‘删除’的！ 结论就是，dmtsai这个用户能够删除the_root.data这个档案！

还是看不太懂？有听没有懂喔！没关系～我们底下就来设计一个练习， 让你实际玩玩看，应该就能够比较近入状况啦！不过，由于很多指令我们还没有教， 所以底下的指令有的先了解即可，详细的指令用法我们会在后面继续介绍的。

  • 先用root的身份建立所需要的档案与目录环境

我们用root的身份在所有人都可以工作的/tmp目录中建立一个名为testing的目录， 该目录的权限为744且目录拥有者为root。另外，在testing目录下在建立一个空的档案， 档名亦为testing。建立目录可用mkdir(make directory)，建立空档案可用touch(下一章会说明)来处理。 所以过程如下所示：

[root@www ~]# cd /tmp                     <==切换工作目录到/tmp
[root@www tmp]# mkdir testing             <==建立新目录
[root@www tmp]# chmod 744 testing         <==变更权限

[root@www tmp]# touch testing/testing     <==建立空的档案
[root@www tmp]# chmod 600 testing/testing <==变更权限
[root@www tmp]# ls -ald testing testing/testing
drwxr--r-- 2 root root 4096 Sep 19 16:01 testing
-rw------- 1 root root    0 Sep 19 16:01 testing/testing
# 仔细看一下，目录的权限是 744 ，且所属群组与使用者均是 root 喔！
# 那么在这样的情况底下，一般身份使用者对这个目录/档案的权限为何？
  • 一般用户的读写权限为何？观察中

在上面的例子中，虽然目录是744的权限设定，一般用户应该能有 r 的权限， 但这样的权限使用者能做啥事呢？假设鸟哥的系统中含有一个帐号名为 vbird 的， 我们可以透过‘ su - vbird ’这个指令来变换身份喔！看看底下的操作先！

[root@www tmp]# su - vbird <==切换身份成为 vbird 啰！
[vbird@www ~]$ cd /tmp     <==看一下，身份变了喔！提示字元也变成 $ 了！
[vbird@www tmp]$ ls -l testing/

?--------- ? ? ? ?             ? testing
# 因为具有 r 的权限可以查询档名。不过权限不足(没有x)，所以会有一堆问号。
[vbird@www tmp]$ cd testing/
-bash: cd: testing/: Permission denied
# 因为不具有 x ，所以当然没有进入的权限啦！有没有呼应前面的权限说明啊！
  • 如果该目录属于用户本身，会有什么状况？

上面的练习我们知道了只有r确实可以让使用者读取目录的档名列表，不过详细的资讯却还是读不到的， 同时也不能将该目录变成工作目录(用 cd 进入该目录之意)。那如果我们让该目录变成使用者的， 那么使用者在这个目录底下是否能够删除档案呢？底下的练习做看看：

[vbird@www tmp]$ exit               <==让 vbird 变回原本的 root 身份喔！
[root@www tmp]# chown vbird testing <==修改权限，让vbird拥有此目录
[root@www tmp]# su - vbird          <==再次变成vbird来操作

[vbird@www ~]$ cd /tmp/testing      <==可以进入目录了呢！
[vbird@www testing]$ ls -l
-rw------- 1 root root 0 Sep 19 16:01 testing  <==档案不是vbird的！
[vbird@www testing]$ rm testing     <==尝试杀掉这个档案看看！
rm: remove write-protected regular empty file `testing'? y

# 竟然可以删除！这样理解了吗？！

透过上面这个简单的步骤，你就可以清楚的知道， x 在目录当中是与‘能否进入该目录’有关， 至于那个 w 则具有相当重要的权限，因为他可以让使用者删除、更新、新建档案或目录， 是个很重要的参数啊！这样可以理解了吗？！ ^_^

小标题的图示 Linux档案种类与副档名

我们在基础篇一直强调一个概念，那就是：任何装置在Linux底下都是档案， 不仅如此，连资料沟通的介面也有专属的档案在负责～所以，你会了解到，Linux的档案种类真的很多～ 除了前面提到的一般档案(-)与目录档案(d)之外，还有哪些种类的档案呢？

  • 档案种类：

我们在刚刚提到使用‘ls -l’观察到第一栏那十个字元中，第一个字元为档案的类型。 除了常见的一般档案(-)与目录档案(d)之外，还有哪些种类的档案类型呢？

  • 正规档案(regular file )：
    就是一般我们在进行存取的类型的档案，在由 ls -al 所显示出来的属性方面，第一个字元为 [ - ]，例如 [-rwxrwxrwx ]。另外，依照档案的内容，又大略可以分为：

    • 纯文字档(ASCII)：这是Linux系统中最多的一种档案类型啰， 称为纯文字档是因为内容为我们人类可以直接读到的资料，例如数字、字母等等。 几乎只要我们可以用来做为设定的档案都属于这一种档案类型。 举例来说，你可以下达‘ cat ~/.bashrc ’就可以看到该档案的内容。 (cat 是将一个档案内容读出来的指令)

    • 二进位档(binary)：还记得我们在‘ 第零章、计算机概论 ’里面的软体程式的运作中提过， 我们的系统其实仅认识且可以执行二进位档案(binary file)吧？没错～ 你的Linux当中的可执行档(scripts, 文字型批次档不算)就是这种格式的啦～ 举例来说，刚刚下达的指令cat就是一个binary file。

    • 资料格式档(data)： 有些程式在运作的过程当中会读取某些特定格式的档案，那些特定格式的档案可以被称为资料档 (data file)。举例来说，我们的Linux在使用者登入时，都会将登录的资料记录在 /var/log/wtmp那个档案内，该档案是一个data file，他能够透过last这个指令读出来！ 但是使用cat时，会读出乱码～因为他是属于一种特殊格式的档案。了乎？

  • 目录(directory)：
    就是目录啰～第一个属性为 [ d ]，例如 [drwxrwxrwx]。

  • 连结档(link)：
    就是类似Windows系统底下的捷径啦！ 第一个属性为 [ l ](英文L的小写)，例如 [lrwxrwxrwx] ；

  • 设备与装置档(device)：
    与系统周边及储存等相关的一些档案， 通常都集中在/dev这个目录之下！通常又分为两种：

    • 区块(block)设备档 ：就是一些储存资料， 以提供系统随机存取的周边设备，举例来说，硬碟与软碟等就是啦！ 你可以随机的在硬碟的不同区块读写，这种装置就是区块装置啰！你可以自行查一下/dev/sda看看， 会发现第一个属性为[ b ]喔！

    • 字元(character)设备档：亦即是一些序列埠的周边设备， 例如键盘、滑鼠等等！这些设备的特色就是‘一次性读取’的，不能够截断输出。 举例来说，你不可能让滑鼠‘跳到’另一个画面，而是‘滑动’到另一个地方啊！第一个属性为 [ c ]。

  • 资料接口档(sockets)：
    既然被称为资料接口档， 想当然尔，这种类型的档案通常被用在网路上的资料承接了。我们可以启动一个程式来监听用户端的要求， 而用户端就可以透过这个socket来进行资料的沟通了。第一个属性为 [ s ]， 最常在/var/run这个目录中看到这种档案类型了。

  • 资料输送档(FIFO, pipe)：
    FIFO也是一种特殊的档案类型，他主要的目的在解决多个程序同时存取一个档案所造成的错误问题。 FIFO是first-in-first-out的缩写。第一个属性为[p] 。

除了设备档是我们系统中很重要的档案，最好不要随意修改之外(通常他也不会让你修改的啦！)， 另一个比较有趣的档案就是连结档。如果你常常将应用程式捉到桌面来的话，你就应该知道在 Windows底下有所谓的‘捷径’。同样的，你可以将 linux下的连结档简单的视为一个档案或目录的捷径。 至于socket与FIFO档案比较难理解，因为这两个咚咚与程序(process)比较有关系， 这个等到未来你了解process之后，再回来查阅吧！此外， 你也可以透过man fifo及man socket来查阅系统上的说明！

  • Linux档案副档名：

基本上，Linux的档案是没有所谓的‘副档名’的，我们刚刚就谈过，一个Linux档案能不能被执行，与他的第一栏的十个属性有关， 与档名根本一点关系也没有。这个观念跟Windows的情况不相同喔！在Windows底下， 能被执行的档案副档名通常是 .com .exe .bat等等，而在Linux底下，只要你的权限当中具有x的话，例如[ -rwx-r-xr-x ] 即代表这个档案可以被执行喔！

不过，可以被执行跟可以执行成功是不一样的～举例来说，在root家目录下的install.log 是一个纯文字档，如果经由修改权限成为 -rwxrwxrwx 后，这个档案能够真的执行成功吗？ 当然不行～因为他的内容根本就没有可以执行的资料。所以说，这个x代表这个档案具有可执行的能力， 但是能不能执行成功，当然就得要看该档案的内容啰～

虽然如此，不过我们仍然希望可以藉由副档名来了解该档案是什么东西，所以， 通常我们还是会以适当的副档名来表示该档案是什么种类的。底下有数种常用的副档名：

  • *.sh ： 脚本或批次档 (scripts)，因为批次档为使用shell写成的，所以副档名就编成 .sh 啰；

  • *Z, *.tar, *.tar.gz, *.zip, *.tgz： 经过打包的压缩档。这是因为压缩软体分别为 gunzip, tar 等等的，由于不同的压缩软体，而取其相关的副档名啰！

  • *.html, *.php：网页相关档案，分别代表 HTML 语法与 PHP 语法的网页档案啰！ .html 的档案可使用网页浏览器来直接开启，至于 .php 的档案， 则可以透过 client 端的浏览器来 server 端浏览，以得到运算后的网页结果呢！

基本上，Linux系统上的档名真的只是让你了解该档案可能的用途而已， 真正的执行与否仍然需要权限的规范才行！例如虽然有一个档案为可执行档， 如常见的/bin/ls这个显示档案属性的指令，不过，如果这个档案的权限被修改成无法执行时， 那么ls就变成不能执行啰！

上述的这种问题最常发生在档案传送的过程中。例如你在网路上下载一个可执行档，但是偏偏在你的 Linux系统中就是无法执行！呵呵！那么就是可能档案的属性被改变了！不要怀疑，从网路上传送到你的 Linux系统中，档案的属性与权限确实是会被改变的喔！

  • Linux档案长度限制：

在Linux底下，使用预设的Ext2/Ext3档案系统时，针对档案的档名长度限制为：

  • 单一档案或目录的最大容许档名为 255 个字元；
  • 包含完整路径名称及目录 (/) 之完整档名为 4096 个字元。

是相当长的档名喔！我们希望Linux的档案名称可以一看就知道该档案在干嘛的， 所以档名通常是很长很长！而用惯了Windows的人可能会受不了，因为档案名称通常真的都很长， 对于用惯Windows而导致打字速度不快的朋友来说，嗯！真的是很困扰.....不过，只得劝你好好的加强打字的训练啰！

而由第五章谈到的热键你也会知道， 其实可以透过[tab]按键来确认档案的档名的！这很好用啊！ 当然啦，如果你已经读完了本书第三篇关于BASH的用法，那么你将会发现 ‘哇！变数真是一个相当好用的东西呐！’ 嗯！看不懂，没关系，到第三篇谈到bash再说！

  • Linux档案名称的限制：

由于Linux在文字介面下的一些指令操作关系，一般来说，你在设定Linux底下的档案名称时， 最好可以避免一些特殊字元比较好！例如底下这些：

* ? > < ; & ! [ ] | \ ' " ` ( ) { }

因为这些符号在文字介面下，是有特殊意义的！另外，档案名称的开头为小数点‘.’时， 代表这个档案为‘隐藏档’喔！同时，由于指令下达当中，常常会使用到 -option 之类的选项， 所以你最好也避免将档案档名的开头以 - 或 + 来命名啊！

大标题的图示 Linux目录配置

在了解了每个档案的相关种类与属性，以及了解了如何更改档案属性/权限的相关资讯后，再来要了解的就是， 为什么每套Linux distributions他们的设定档啊、执行档啊、每个目录内放置的咚咚啊，其实都差不多？ 原来是有一套标准依据的哩！我们底下就来瞧一瞧。

小标题的图示 Linux目录配置的依据--FHS

因为利用Linux来开发产品或distributions的社群/公司与个人实在太多了， 如果每个人都用自己的想法来配置档案放置的目录，那么将可能造成很多管理上的困扰。 你能想像，你进入一个企业之后，所接触到的Linux目录配置方法竟然跟你以前学的完全不同吗？ 很难想像吧～所以，后来就有所谓的Filesystem Hierarchy Standard (FHS)标准的出炉了！

根据FHS(http://www.pathname.com/fhs/)的官方文件指出， 他们的主要目的是希望让使用者可以了解到已安装软体通常放置于那个目录下， 所以他们希望独立的软体开发商、作业系统制作者、以及想要维护系统的使用者，都能够遵循FHS的标准。 也就是说，FHS的重点在于规范每个特定的目录下应该要放置什么样子的资料而已。 这样做好处非常多，因为Linux作业系统就能够在既有的面貌下(目录架构不变)发展出开发者想要的独特风格。

事实上，FHS是根据过去的经验一直再持续的改版的，FHS依据档案系统使用的频繁与否与是否允许使用者随意更动， 而将目录定义成为四种交互作用的形态，用表格来说有点像底下这样：

 | 可分享的(shareable) | 不可分享的(unshareable)
不变的(static) | /usr (软体放置处) | /etc (设定档)
 | /opt (第三方协力软体) | /boot (开机与核心档)
可变动的(variable) | /var/mail (使用者邮件信箱) | /var/run (程序相关)
 | /var/spool/news (新闻群组) | /var/lock (程序相关)

上表中的目录就是一些代表性的目录，该目录底下所放置的资料在底下会谈到，这里先略过不谈。 我们要了解的是，什么是那四个类型？

  • 可分享的：可以分享给其他系统挂载使用的目录，所以包括执行档与使用者的邮件等资料， 是能够分享给网路上其他主机挂载用的目录；

  • 不可分享的：自己机器上面运作的装置档案或者是与程序有关的socket档案等， 由于仅与自身机器有关，所以当然就不适合分享给其他主机了。

  • 不变的：有些资料是不会经常变动的，跟随着distribution而不变动。 例如函式库、文件说明档、系统管理员所管理的主机服务设定档等等；

  • 可变动的：经常改变的资料，例如登录档、一般用户可自行收受的新闻群组等。

事实上，FHS针对目录树架构仅定义出三层目录底下应该放置什么资料而已，分别是底下这三个目录的定义：

  • / (root, 根目录)：与开机系统有关；
  • /usr (unix software resource)：与软体安装/执行有关；
  • /var (variable)：与系统运作过程有关。

为什么要定义出这三层目录呢？其实是有意义的喔！每层目录底下所应该要放置的目录也都又特定的规定喔！ 由于我们尚未介绍完整的Linux系统，所以底下的介绍你可能会看不懂！没关系，先有个概念即可， 等到你将基础篇全部看完后，就重头将基础篇再看一遍！到时候你就会豁然开朗啦！^_^

Tips:
这个 root 在 Linux 里面的意义真的很多很多～多到让人搞不懂那是啥玩意儿。 如果以‘帐号’的角度来看，所谓的 root 指的是‘系统管理员！’的身份， 如果以‘目录’的角度来看，所谓的 root 意即指的是根目录，就是 / 啦～ 要特别留意喔！ 		鸟哥的图示
  • 根目录 (/) 的意义与内容：

根目录是整个系统最重要的一个目录，因为不但所有的目录都是由根目录衍生出来的， 同时根目录也与开机/还原/系统修复等动作有关。 由于系统开机时需要特定的开机软体、核心档案、开机所需程式、 函式库等等档案资料，若系统出现错误时，根目录也必须要包含有能够修复档案系统的程式才行。 因为根目录是这么的重要，所以在FHS的要求方面，他希望根目录不要放在非常大的分割槽内， 因为越大的分割槽你会放入越多的资料，如此一来根目录所在分割槽就可能会有较多发生错误的机会。

因此FHS标准建议：根目录(/)所在分割槽应该越小越好， 且应用程式所安装的软体最好不要与根目录放在同一个分割槽内，保持根目录越小越好。 如此不但效能较佳，根目录所在的档案系统也较不容易发生问题。

有鉴于上述的说明，因此FHS定义出根目录(/)底下应该要有底下这些次目录的存在才好：

目录 | 应放置档案内容
/bin | 系统有很多放置执行档的目录，但/bin比较特殊。因为/bin放置的是在单人维护模式下还能够被操作的指令。 在/bin底下的指令可以被root与一般帐号所使用，主要有：cat, chmod, chown, date, mv, mkdir, cp, bash等等常用的指令。
/boot | 这个目录主要在放置开机会使用到的档案，包括Linux核心档案以及开机选单与开机所需设定档等等。 Linux kernel常用的档名为：vmlinuz，如果使用的是grub这个开机管理程式， 则还会存在/boot/grub/这个目录喔！
/dev | 在Linux系统上，任何装置与周边设备都是以档案的型态存在于这个目录当中的。 你只要透过存取这个目录底下的某个档案，就等于存取某个装置啰～ 比要重要的档案有/dev/null, /dev/zero, /dev/tty, /dev/lp*, /dev/hd*, /dev/sd*等等
/etc 系统主要的设定档几乎都放置在这个目录内，例如人员的帐号密码档、 各种服务的启始档等等。一般来说，这个目录下的各档案属性是可以让一般使用者查阅的， 但是只有root有权力修改。FHS建议不要放置可执行档(binary)在这个目录中喔。比较重要的档案有： /etc/inittab, /etc/init.d/, /etc/modprobe.conf, /etc/X11/, /etc/fstab, /etc/sysconfig/ 等等。另外，其下重要的目录有：
  • /etc/init.d/：所有服务的预设启动 script 都是放在这里的，例如要启动或者关闭 iptables 的话：‘ /etc/init.d/iptables start’、‘/etc/init.d/iptables stop’
  • /etc/xinetd.d/：这就是所谓的super daemon管理的各项服务的设定档目录。
  • /etc/X11/：与 X Window 有关的各种设定档都在这里，尤其是 xorg.conf 这个 X Server 的设定档。
/home 这是系统预设的使用者家目录(home directory)。在你新增一个一般使用者帐号时， 预设的使用者家目录都会规范到这里来。比较重要的是，家目录有两种代号喔：
~：代表目前这个使用者的家目录，而
~dmtsai ：则代表 dmtsai 的家目录！
/lib | 系统的函式库非常的多，而/lib放置的则是在开机时会用到的函式库， 以及在/bin或/sbin底下的指令会呼叫的函式库而已。 什么是函式库呢？你可以将他想成是‘外挂’，某些指令必须要有这些‘外挂’才能够顺利完成程式的执行之意。 尤其重要的是/lib/modules/这个目录， 因为该目录会放置核心相关的模组(驱动程式)喔！
/media | media是‘媒体’的英文，顾名思义，这个/media底下放置的就是可移除的装置啦！ 包括软碟、光碟、DVD等等装置都暂时挂载于此。常见的档名有：/media/floppy, /media/cdrom等等。
/mnt | 如果你想要暂时挂载某些额外的装置，一般建议你可以放置到这个目录中。 在古早时候，这个目录的用途与/media相同啦！只是有了/media之后，这个目录就用来暂时挂载用了。
/opt | 这个是给第三方协力软体放置的目录。什么是第三方协力软体啊？ 举例来说，KDE这个桌面管理系统是一个独立的计划，不过他可以安装到Linux系统中，因此KDE的软体就建议放置到此目录下了。 另外，如果你想要自行安装额外的软体(非原本的distribution提供的)，那么也能够将你的软体安装到这里来。 不过，以前的Linux系统中，我们还是习惯放置在/usr/local目录下呢！
/root | 系统管理员(root)的家目录。之所以放在这里，是因为如果进入单人维护模式而仅挂载根目录时， 该目录就能够拥有root的家目录，所以我们会希望root的家目录与根目录放置在同一个分割槽中。
/sbin | Linux有非常多指令是用来设定系统环境的，这些指令只有root才能够利用来‘设定’系统，其他使用者最多只能用来‘查询’而已。 放在/sbin底下的为开机过程中所需要的，里面包括了开机、修复、还原系统所需要的指令。 至于某些伺服器软体程式，一般则放置到/usr/sbin/当中。至于本机自行安装的软体所产生的系统执行档(system binary)， 则放置到/usr/local/sbin/当中了。常见的指令包括：fdisk, fsck, ifconfig, init, mkfs等等。
/srv | srv可以视为‘service’的缩写，是一些网路服务启动之后，这些服务所需要取用的资料目录。 常见的服务例如WWW, FTP等等。举例来说，WWW伺服器需要的网页资料就可以放置在/srv/www/里面。
/tmp | 这是让一般使用者或者是正在执行的程序暂时放置档案的地方。 这个目录是任何人都能够存取的，所以你需要定期的清理一下。当然，重要资料不可放置在此目录啊！ 因为FHS甚至建议在开机时，应该要将/tmp下的资料都删除唷！

事实上FHS针对根目录所定义的标准就仅有上面的咚咚，不过我们的Linux底下还有许多目录你也需要了解一下的。 底下是几个在Linux当中也是非常重要的目录喔：

目录 | 应放置档案内容
/lost+found | 这个目录是使用标准的ext2/ext3档案系统格式才会产生的一个目录，目的在于当档案系统发生错误时， 将一些遗失的片段放置到这个目录下。这个目录通常会在分割槽的最顶层存在， 例如你加装一颗硬碟于/disk中，那在这个系统下就会自动产生一个这样的目录‘/disk/lost+found’
/proc | 这个目录本身是一个‘虚拟档案系统(virtual filesystem)’喔！他放置的资料都是在记忆体当中， 例如系统核心、行程资讯(process)、周边装置的状态及网路状态等等。因为这个目录下的资料都是在记忆体当中， 所以本身不占任何硬碟空间啊！比较重要的档案例如：/proc/cpuinfo, /proc/dma, /proc/interrupts, /proc/ioports, /proc/net/* 等等。
/sys | 这个目录其实跟/proc非常类似，也是一个虚拟的档案系统，主要也是记录与核心相关的资讯。 包括目前已载入的核心模组与核心侦测到的硬体装置资讯等等。这个目录同样不占硬碟容量喔！

除了这些目录的内容之外，另外要注意的是，因为根目录与开机有关，开机过程中仅有根目录会被挂载， 其他分割槽则是在开机完成之后才会持续的进行挂载的行为。就是因为如此，因此根目录下与开机过程有关的目录， 就不能够与根目录放到不同的分割槽去！那哪些目录不可与根目录分开呢？有底下这些：

  • /etc：设定档
  • /bin：重要执行档
  • /dev：所需要的装置档案
  • /lib：执行档所需的函式库与核心所需的模组
  • /sbin：重要的系统执行档

这五个目录千万不可与根目录分开在不同的分割槽！请背下来啊！ 好了，谈完了根目录，接下来我们就来谈谈/usr以及/var啰！先看/usr里面有些什么东西：

  • /usr 的意义与内容：

依据FHS的基本定义，/usr里面放置的资料属于可分享的与不可变动的(shareable, static)， 如果你知道如何透过网路进行分割槽的挂载(例如在伺服器篇会谈到的NFS伺服器)，那么/usr确实可以分享给区域网路内的其他主机来使用喔！

很多读者都会误会/usr为user的缩写，其实usr是Unix Software Resource的缩写， 也就是‘Unix作业系统软体资源’所放置的目录，而不是使用者的资料啦！这点要注意。 FHS建议所有软体开发者，应该将他们的资料合理的分别放置到这个目录下的次目录，而不要自行建立该软体自己独立的目录。

因为是所有系统预设的软体(distribution发布者提供的软体)都会放置到/usr底下，因此这个目录有点类似Windows 系统的‘C:\Windows\ + C:\Program files\’这两个目录的综合体，系统刚安装完毕时，这个目录会占用最多的硬碟容量。 一般来说，/usr的次目录建议有底下这些：

目录 | 应放置档案内容
/usr/X11R6/ | 为X Window System重要资料所放置的目录，之所以取名为X11R6是因为最后的X版本为第11版，且该版的第6次释出之意。
/usr/bin/ | 绝大部分的使用者可使用指令都放在这里！请注意到他与/bin的不同之处。(是否与开机过程有关)
/usr/include/ | c/c++等程式语言的档头(header)与包含档(include)放置处，当我们以tarball方式 (*.tar.gz 的方式安装软体)安装某些资料时，会使用到里头的许多包含档喔！
/usr/lib/ | 包含各应用软体的函式库、目标档案(object file)，以及不被一般使用者惯用的执行档或脚本(script)。 某些软体会提供一些特殊的指令来进行伺服器的设定，这些指令也不会经常被系统管理员操作， 那就会被摆放到这个目录下啦。要注意的是，如果你使用的是X86_64的Linux系统， 那可能会有/usr/lib64/目录产生喔！
/usr/local/ | 系统管理员在本机自行安装自己下载的软体(非distribution预设提供者)，建议安装到此目录， 这样会比较便于管理。举例来说，你的distribution提供的软体较旧，你想安装较新的软体但又不想移除旧版， 此时你可以将新版软体安装于/usr/local/目录下，可与原先的旧版软体有分别啦！ 你可以自行到/usr/local去看看，该目录下也是具有bin, etc, include, lib...的次目录喔！
/usr/sbin/ | 非系统正常运作所需要的系统指令。最常见的就是某些网路伺服器软体的服务指令(daemon)啰！
/usr/share/ 放置共享文件的地方，在这个目录下放置的资料几乎是不分硬体架构均可读取的资料， 因为几乎都是文字档案嘛！在此目录下常见的还有这些次目录：
  • /usr/share/man：线上说明文件
  • /usr/share/doc：软体杂项的文件说明
  • /usr/share/zoneinfo：与时区有关的时区档案
/usr/src/ | 一般原始码建议放置到这里，src有source的意思。至于核心原始码则建议放置到/usr/src/linux/目录下。

  • /var 的意义与内容：

如果/usr是安装时会占用较大硬碟容量的目录，那么/var就是在系统运作后才会渐渐占用硬碟容量的目录。 因为/var目录主要针对常态性变动的档案，包括快取(cache)、登录档(log file)以及某些软体运作所产生的档案， 包括程序档案(lock file, run file)，或者例如MySQL资料库的档案等等。常见的次目录有：

目录 | 应放置档案内容
/var/cache/ | 应用程式本身运作过程中会产生的一些暂存档；
/var/lib/ | 程式本身执行的过程中，需要使用到的资料档案放置的目录。在此目录下各自的软体应该要有各自的目录。 举例来说，MySQL的资料库放置到/var/lib/mysql/而rpm的资料库则放到/var/lib/rpm去！
/var/lock/ | 某些装置或者是档案资源一次只能被一个应用程式所使用，如果同时有两个程式使用该装置时， 就可能产生一些错误的状况，因此就得要将该装置上锁(lock)，以确保该装置只会给单一软体所使用。 举例来说，烧录机正在烧录一块光碟，你想一下，会不会有两个人同时在使用一个烧录机烧片？ 如果两个人同时烧录，那片子写入的是谁的资料？所以当第一个人在烧录时该烧录机就会被上锁， 第二个人就得要该装置被解除锁定(就是前一个人用完了)才能够继续使用啰。
/var/log/ | 重要到不行！这是登录档放置的目录！里面比较重要的档案如/var/log/messages, /var/log/wtmp(记录登入者的资讯)等。
/var/mail/ | 放置个人电子邮件信箱的目录，不过这个目录也被放置到/var/spool/mail/目录中！ 通常这两个目录是互为连结档啦！
/var/run/ | 某些程式或者是服务启动后，会将他们的PID放置在这个目录下喔！ 至于PID的意义我们会在后续章节提到的。
/var/spool/ | 这个目录通常放置一些伫列资料，所谓的‘伫列’就是排队等待其他程式使用的资料啦！ 这些资料被使用后通常都会被删除。举例来说，系统收到新信会放置到/var/spool/mail/中， 但使用者收下该信件后该封信原则上就会被删除。信件如果暂时寄不出去会被放到/var/spool/mqueue/中， 等到被送出后就被删除。如果是工作排程资料(crontab)，就会被放置到/var/spool/cron/目录中！

建议在你读完整个基础篇之后，可以挑战FHS官方英文文件(参考本章参考资料)，相信会让你对于Linux作业系统的目录有更深入的了解喔！

  • 针对FHS，各家distributions的异同

由于FHS仅是定义出最上层(/)及次层(/usr, /var)的目录内容应该要放置的档案或目录资料， 因此，在其他次目录层级内，就可以随开发者自行来配置了。举例来说，CentOS的网路设定资料放在 /etc/sysconfig/network-scripts/ 目录下，但是SuSE则是将网路放置在 /etc/sysconfig/network/ 目录下，目录名称可是不同的呢！不过只要记住大致的FHS标准，差异性其实有限啦！

小标题的图示 目录树(directory tree)

另外，在Linux底下，所有的档案与目录都是由根目录开始的！那是所有目录与档案的源头～ 然后再一个一个的分支下来，有点像是树枝状啊～因此，我们也称这种目录配置方式为：‘目录树(directory tree)’ 这个目录树有什么特性呢？他主要的特性有：

  • 目录树的启始点为根目录 (/, root)；
  • 每一个目录不止能使用本地端的 partition 的档案系统，也可以使用网路上的 filesystem 。举例来说， 可以利用 Network File System (NFS) 伺服器挂载某特定目录等。
  • 每一个档案在此目录树中的档名(包含完整路径)都是独一无二的。

好，谈完了FHS的标准之后，实际来看看CentOS在根目录底下会有什么样子的资料吧！我们可以下达以下的指令来查询：

[root@www ~]# ls -l /
drwxr-xr-x   2 root root  4096 Sep  5 12:34 bin
drwxr-xr-x   4 root root  1024 Sep  4 18:06 boot
drwxr-xr-x  12 root root  4320 Sep 22 12:10 dev
drwxr-xr-x 105 root root 12288 Sep 22 12:10 etc
drwxr-xr-x   4 root root  4096 Sep  5 14:08 home
drwxr-xr-x  14 root root  4096 Sep  5 12:12 lib
drwx------   2 root root 16384 Sep  5 01:49 lost+found
drwxr-xr-x   2 root root  4096 Mar 30  2007 media
drwxr-xr-x   2 root root     0 Sep 22 12:09 misc
drwxr-xr-x   2 root root  4096 Mar 30  2007 mnt
drwxr-xr-x   2 root root     0 Sep 22 12:09 net
drwxr-xr-x   2 root root  4096 Mar 30  2007 opt
dr-xr-xr-x  95 root root     0 Sep 22  2008 proc
drwxr-x---   4 root root  4096 Sep  8 14:06 root
drwxr-xr-x   2 root root 12288 Sep  5 12:33 sbin
drwxr-xr-x   4 root root     0 Sep 22  2008 selinux
drwxr-xr-x   2 root root  4096 Mar 30  2007 srv
drwxr-xr-x  11 root root     0 Sep 22  2008 sys
drwxrwxrwt   6 root root  4096 Sep 22 12:10 tmp
drwxr-xr-x  14 root root  4096 Sep  4 18:00 usr
drwxr-xr-x  26 root root  4096 Sep  4 18:19 var

上面表格中比较特殊的应该是/selinux这个目录了，这个目录的内容资料也是在记忆体中的资讯， 同样的不会占用任何的硬碟容量。这个/selinux是Secure Enhance Linux(SELinux)的执行目录， 而SELinux是Linux核心的重要外挂功能之一，他可以用来作为细部权限的控管，主要针对程序(尤其是网路程序)的存取权限来限制。 关于SELinux我们会在后续的章节继续做介绍的喔！

如果我们将整个目录树以图示的方法来显示，并且将较为重要的档案资料列出来的话，那么目录树架构有点像这样：

目录树架构示意图
图3.2.1、目录树架构示意图

鸟哥只有就各目录进行简单的解释，看看就好，详细的解释请回到刚刚说明的表格中去查阅喔！ 看完了FHS标准之后，现在回到第三章里面去看看安装前Linux规划的分割情况， 对于当初为何需要分割为这样的情况，有点想法了吗？^_^。根据FHS的定义，你最好能够将/var独立出来， 这样对于系统的资料还有一些安全性的保护呢！因为至少/var死掉时，你的根目录还会活着嘛！ 还能够进入救援模式啊！

小标题的图示 绝对路径与相对路径

除了需要特别注意的FHS目录配置外，在档名部分我们也要特别注意喔！因为根据档名写法的不同，也可将所谓的路径(path)定义为绝对路径(absolute)与相对路径(relative)。 这两种档名/路径的写法依据是这样的：

  • 绝对路径：由根目录(/)开始写起的档名或目录名称， 例如 /home/dmtsai/.bashrc；
  • 相对路径：相对于目前路径的档名写法。 例如 ./home/dmtsai 或 ../../home/dmtsai/ 等等。反正开头不是 / 就属于相对路径的写法

而你必须要了解，相对路径是以‘你当前所在路径的相对位置’来表示的。举例来说，你目前在 /home 这个目录下， 如果想要进入 /var/log 这个目录时，可以怎么写呢？

  1. cd /var/log (absolute)
  2. cd ../var/log (relative)

因为你在 /home 底下，所以要回到上一层 (../) 之后，才能继续往 /var 来移动的！ 特别注意这两个特殊的目录：

  • . ：代表当前的目录，也可以使用 ./ 来表示；
  • .. ：代表上一层目录，也可以 ../ 来代表。

这个 . 与 .. 目录概念是很重要的，你常常会看到 cd .. 或 ./command 之类的指令下达方式， 就是代表上一层与目前所在目录的工作状态喔！很重要的呐！

例题：
如何先进入/var/spool/mail/目录，再进入到/var/spool/cron/目录内？
答：
由于/var/spool/mail与/var/spool/cron是同样在/var/spool/目录中，因此最简单的指令下达方法为：
  1. cd /var/spool/mail
  2. cd ../cron
如此就不需要在由根目录开始写起了。这个相对路径是非常有帮助的！尤其对于某些软体开发商来说。 一般来说，软体开发商会将资料放置到/usr/local/里面的各相对目录，你可以参考图3.2.1的相对位置。 但如果使用者想要安装到不同目录呢？就得要使用相对路径啰！^_^

例题：
网路文件常常提到类似‘./run.sh’之类的资料，这个指令的意义为何？
答：
由于指令的执行需要变数(bash章节才会提到)的支援，若你的执行档放置在本目录，并且本目录并非正规的执行档目录(/bin, /usr/bin等为正规)，此时要执行指令就得要严格指定该执行档。‘./’代表‘本目录’的意思，所以‘./run.sh’代表‘执行本目录下， 名为run.sh的档案’啰！
小标题的图示 CentOS 的观察

某些时刻你可能想要知道你的 distribution 使用的是那个 Linux 标准 (Linux Standard Base)， 而且我们也知道 distribution 使用的都是 Linux 的核心！那你如何观察这些基本的资讯呢？ 可以使用如下的指令来观察看看啦：

[root@www ~]# uname -r
2.6.18-128.el5 <==可以察看实际的核心版本
[root@www ~]# lsb_release -a

LSB Version:    :core-3.1-amd64:core-3.1-ia32:core-3.1-noarch:graphics-3.1-amd64:
graphics-3.1-ia32:graphics-3.1-noarch      <==LSB 的版本
Distributor ID: CentOS
Description:    CentOS release 5.3 (Final) <==distribution 的版本
Release:        5.3
Codename:       Final
大标题的图示 重点回顾
  • Linux的每个档案中，依据权限分为使用者、群组与其他人三种身份；
  • 群组最有用的功能之一，就是当你在团队开发资源的时候，且每个帐号都可以有多个群组的支援；
  • 利用ls -l显示的档案属性中，第一个栏位是档案的权限，共有十个位元，第一个位元是档案类型， 接下来三个为一组共三组，为使用者、群组、其他人的权限，权限有r,w,x三种；
  • 如果档名之前多一个‘ . ’，则代表这个档案为‘隐藏档’；
  • 更改档案的群组支援可用chgrp，修改档案的拥有者可用chown，修改档案的权限可用chmod
  • chmod修改权限的方法有两种，分别是符号法与数字法，数字法中r,w,x分数为4,2,1；
  • 对档案来讲，权限的效能为：
    • r：可读取此一档案的实际内容，如读取文字档的文字内容等；
    • w：可以编辑、新增或者是修改该档案的内容(但不含删除该档案)；
    • x：该档案具有可以被系统执行的权限。
  • 对目录来说，权限的效能为：
    • r (read contents in directory)
    • w (modify contents of directory)
    • x (access directory)
  • 要开放目录给任何人浏览时，应该至少也要给予r及x的权限，但w权限不可随便给；
  • Linux档名的限制为：单一档案或目录的最大容许档名为 255 个字元；包含完整路径名称及目录 (/) 之完整档名为 4096 个字元
  • 根据FHS的官方文件指出， 他们的主要目的是希望让使用者可以了解到已安装软体通常放置于那个目录下
  • FHS订定出来的四种目录特色为：shareable, unshareable, static, variable等四类；
  • FHS所定义的三层主目录为：/, /var, /usr三层而已；
  • 有五个目录不可与根目录放在不同的partition，分别为/etc, /bin, /lib, /dev, /sbin五个。
大标题的图示 本章练习
( 要看答案请将滑鼠移动到‘答：’底下的空白处，按下左键圈选空白处即可察看 )
  • 请说明/bin与/usr/bin目录所放置的执行档有何不同之处？
    /bin主要放置在开机时，以及进入单人维护模式后还能够被使用的指令，至于/usr/bin则是大部分软体提供的指令放置处。
  • 请说明/bin与/sbin目录所放置的执行档有何不同之处？
    /bin放置的是一般使用者惯用的指令，至于/sbin则是系统管理员才会使用到的指令。不过/bin与/sbin都与开机、单人维护模式有关。 更多的执行档会被放置到/usr/bin及/usr/sbin底下。
  • 哪几个目录不能够与根目录(/)放置到不同的partition中？并请说明该目录所放置的资料为何？
    /etc(设定档), /bin(一般身份可用执行档), /dev(装置档案), /lib(执行档的函式库或核心模组等), /sbin(系统管理员可用指令)
  • 试说明为何根目录要小一点比较好？另外在分割时，为什么/home, /usr, /var, /tmp最好与根目录放到不同的分割槽？ 试说明可能的原因为何(由目录放置资料的内容谈起)？
    根据FHS的说明，越小的/可以放置的较为集中且读取频率较不频繁，可避免较多的错误。 至于/home(使用者家目录), /usr(软体资源), /var(变动幅度较大的资料), /tmp(系统暂存，资料莫名)中， 因为资料量较大或者是读取频率较高，或者是不明的使用情况较多，因此建议不要与根目录放在一起， 也会有助于系统安全。
  • 早期的 Unix 系统档名最多允许 14 个字元，而新的 Unix 与 Linux 系统中，档名最多可以容许几个字元？
    由于使用Ext2/Ext3档案系统，单一档名可达 255 字元，完整档名 (包含路径) 可达 4096 个字元
  • 当一个一般档案权限为 -rwxrwxrwx 则表示这个档案的意义为？
    任何人皆可读取、修改或编辑、可以执行，但不一定能删除。
  • 我需要将一个档案的权限改为 -rwxr-xr-- 请问该如何下达指令？
    chmod 754 filename 或 chmod u=rwx,g=rx,o=r filename
  • 若我需要更改一个档案的拥有者与群组，该用什么指令？
    chown, chgrp
  • Linux 传统的档案系统为何？此外，常用的 Journaling 档案格式有哪些？
    传统档案格式为：ext2,
    Journaling 有 ext3 及 Reiserfs 等
  • 请问底下的目录与主要放置什么资料：
    /etc/, /etc/init.d, /boot, /usr/bin, /bin, /usr/sbin, /sbin, /dev, /var/log
    • /etc/：几乎系统的所有设定档案均在此，尤其 passwd,shadow
    • /etc/init.d：系统开机的时候载入服务的 scripts 的摆放地点
    • /boot：开机设定档，也是预设摆放核心 vmlinuz 的地方
    • /usr/bin, /bin：一般执行档摆放的地方
    • /usr/sbin, /sbin：系统管理员常用指令集
    • /dev：摆放所有系统装置档案的目录
    • /var/log：摆放系统登录档案的地方
  • 若一个档案的档名开头为‘ . ’，例如 .bashrc 这个档案，代表什么？另外，如何显示出这个档名与他的相关属性？
    有‘ . ’为开头的为隐藏档，需要使用 ls -a 这个 -a 的选项才能显示出隐藏档案的内容，而使用 ls -al 才能显示出属性。
大标题的图示 参考资料与延伸阅读
  • FHS的标准官方文件：http://proton.pathname.com/fhs/，非常值得参考的文献！
  • 关于 Journaling 日志式文章的相关说明 http://www.linuxplanet.com/linuxplanet/reports/3726/1/
2002/07/18：第一次完成
2003/02/06：重新编排与加入FAQ
2005/06/28：将旧的资料移动到 这里
2005/07/15：呼呼～终于改完成了～这次的修订当中，加入了 FHS 的说明，希望大家能够比较清楚 Linux 的目录配置！
2005/08/05：修订了最大档名字元，应该是 255 才对！另外，加入了‘档名限制’的部分！
2005/09/03：修订了目录权限相关的说明，将原本仅具有 r 却写成无法使用 ls 浏览的说明资料移除！
2008/09/08：旧的针对FC4所写的文章移动到此处
2008/09/20：针对FHS加强说明了一下，分为/, /usr, /var三层来个别说明！并非抄袭官网的资料而已喔！
2008/09/23：经过一场大感冒，停工了四、五天，终于还是给他完工了！^_^
2008/10/21：原本的第四小节 Linux 的档案系统，因为与第八章重复性太高，将他移除了！
2009/08/01：加入了 lsb_release 的相关说明！
2009/08/18：调整一下显示的情况，使得更易读～


鸟哥的 Linux 私房菜 -- 基础学习篇

为取得较佳浏览结果，请爱用 firefox 浏览本网页

第七章、Linux 档案与目录管理
最近更新日期：2009/08/26
在第六章我们认识了Linux系统下的档案权限概念以及目录的配置说明。 在这个章节当中，我们就直接来进一步的操作与管理档案与目录吧！包括在不同的目录间变换、 建立与删除目录、建立与删除档案，还有寻找档案、查阅档案内容等等， 都会在这个章节作个简单的介绍啊！

1. 目录与路径
    1.1 相对路径与绝对路径
    1.2 目录的相关操作： cd, pwd, mkdir, rmdir
    1.3 关于执行档路径的变数： $PATH
 2. 档案与目录管理
    2.1 档案与目录的检视： ls
    2.2 复制、删除与移动： cp, rm, mv
    2.3 取得路径的档案名称与目录名称
 3. 档案内容查阅：
    3.1 直接检视档案内容： cat, tac, nl
    3.2 可翻页检视： more, less
    3.3 资料撷取： head, tail
    3.4 非纯文字档： od
    3.5 修改档案时间与建置新档： touch
 4. 档案与目录的预设权限与隐藏权限
    4.1 档案预设权限：umask
    4.2 档案隐藏属性： chattr, lsattr
    4.4 档案特殊权限：SUID, SGID, SBIT, 权限设定
    4.3 观察档案类型：file
 5. 指令与档案的搜寻：
    5.1 指令档名的搜寻： which
    5.2 档案档名的搜寻： whereis, locate, find
 6. 极重要！权限与指令间的关系：
7. 重点回顾
8. 本章习题
9. 参考资料与延伸阅读
10. 针对本文的建议：http://phorum.vbird.org/viewtopic.php?t=23879
大标题的图示 目录与路径：

由第六章Linux的档案权限与目录配置中透过FHS了解了Linux的‘树状目录’概念之后， 接下来就得要实际的来搞定一些基本的路径问题了！这些目录的问题当中，最重要的莫过于第六章也谈过的‘绝对路径’与‘相对路径’的意义啦！ 绝对/相对路径的写法并不相同，要特别注意。此外，当你下达指令时，该指令是透过什么功能来取得的？ 这与PATH这个变数有关呢！底下就让我们来谈谈啰！

小标题的图示 相对路径与绝对路径：

在开始目录的切换之前，你必须要先了解一下所谓的‘路径(PATH)’， 有趣的是：什么是‘相对路径’与‘绝对路径’？ 虽然前一章已经稍微针对这个议题提过一次，不过，这里不厌其烦的再次的强调一下！

  • 绝对路径：路径的写法‘一定由根目录 / 写起’，例如： /usr/share/doc 这个目录。
  • 相对路径：路径的写法‘不是由 / 写起’，例如由 /usr/share/doc 要到 /usr/share/man 底下时，可以写成： ‘cd ../man’这就是相对路径的写法啦！相对路径意指‘相对于目前工作目录的路径！’

  • 相对路径的用途

那么相对路径与绝对路径有什么了不起呀？喝！那可真的是了不起了！假设你写了一个软体， 这个软体共需要三个目录，分别是 etc, bin, man 这三个目录，然而由于不同的人喜欢安装在不同的目录之下， 假设甲安装的目录是 /usr/local/packages/etc, /usr/local/packages/bin 及 /usr/local/packages/man ，不过乙却喜欢安装在 /home/packages/etc, /home/packages/bin, /home/packages/man 这三个目录中，请问如果需要用到绝对路径的话，那么是否很麻烦呢？是的！ 如此一来每个目录下的东西就很难对应的起来！这个时候相对路径的写法就显的特别的重要了！

此外，如果你跟鸟哥一样，喜欢将路径的名字写的很长，好让自己知道那个目录是在干什么的，例如： /cluster/raid/output/taiwan2006/smoke 这个目录，而另一个目录在 /cluster/raid/output/taiwan2006/cctm ，那么我从第一个要到第二个目录去的话，怎么写比较方便？ 当然是‘ cd ../cctm ’比较方便啰！对吧！

  • 绝对路径的用途

但是对于档名的正确性来说，‘绝对路径的正确度要比较好～’。 一般来说，鸟哥会建议你，如果是在写程式 (shell scripts) 来管理系统的条件下，务必使用绝对路径的写法。 怎么说呢？因为绝对路径的写法虽然比较麻烦，但是可以肯定这个写法绝对不会有问题。 如果使用相对路径在程式当中，则可能由于你执行的工作环境不同，导致一些问题的发生。 这个问题在工作排程(at, cron, 第十六章)当中尤其重要！这个现象我们在十三章、shell script时，会再次的提醒你喔！ ^_^

小标题的图示 目录的相关操作：

我们之前稍微提到变换目录的指令是cd，还有哪些可以进行目录操作的指令呢？ 例如建立目录啊、删除目录之类的～还有，得要先知道的，就是有哪些比较特殊的目录呢？ 举例来说，底下这些就是比较特殊的目录，得要用力的记下来才行：

.         代表此层目录
..        代表上一层目录
-         代表前一个工作目录
~         代表‘目前使用者身份’所在的家目录
~account  代表 account 这个使用者的家目录(account是个帐号名称)

需要特别注意的是：在所有目录底下都会存在的两个目录，分别是‘.’与‘..’ 分别代表此层与上层目录的意思。那么来思考一下底下这个例题：

例题：
请问在Linux底下，根目录下有没有上层目录(..)存在？
答：
若使用‘ ls -al / ’去查询，可以看到根目录下确实存在 . 与 .. 两个目录，再仔细的查阅， 可发现这两个目录的属性与权限完全一致，这代表根目录的上一层(..)与根目录自己(.)是同一个目录。

底下我们就来谈一谈几个常见的处理目录的指令吧：

  • cd：变换目录
  • pwd：显示目前的目录
  • mkdir：建立一个新的目录
  • rmdir：删除一个空的目录

  • cd (变换目录)

我们知道vbird这个使用者的家目录是/home/vbird/，而root家目录则是/root/，假设我以root身份在 Linux系统中，那么简单的说明一下这几个特殊的目录的意义是：

[root@www ~]# cd [相对路径或绝对路径]

# 最重要的就是目录的绝对路径与相对路径，还有一些特殊目录的符号啰！
[root@www ~]# cd ~vbird
# 代表去到 vbird 这个使用者的家目录，亦即 /home/vbird
[root@www vbird]# cd ~
# 表示回到自己的家目录，亦即是 /root 这个目录
[root@www ~]# cd
# 没有加上任何路径，也还是代表回到自己家目录的意思喔！

[root@www ~]# cd ..
# 表示去到目前的上层目录，亦即是 /root 的上层目录的意思；
[root@www /]# cd -
# 表示回到刚刚的那个目录，也就是 /root 啰～
[root@www ~]# cd /var/spool/mail
# 这个就是绝对路径的写法！直接指定要去的完整路径名称！
[root@www mail]# cd ../mqueue

# 这个是相对路径的写法，我们由/var/spool/mail 去到/var/spool/mqueue 就这样写！

cd是Change Directory的缩写，这是用来变换工作目录的指令。注意，目录名称与cd指令之间存在一个空格。 一登入Linux系统后，root会在root的家目录！那回到上一层目录可以用‘ cd .. ’。 利用相对路径的写法必须要确认你目前的路径才能正确的去到想要去的目录。例如上表当中最后一个例子， 你必须要确认你是在/var/spool/mail当中，并且知道在/var/spool当中有个mqueue的目录才行啊～ 这样才能使用cd ../mqueue去到正确的目录说，否则就要直接输入cd /var/spool/mqueue啰～

其实，我们的提示字元，亦即那个 [root@www ~]# 当中，就已经有指出目前的目录了， 刚登入时会到自己的家目录，而家目录还有一个代码，那就是‘ ~ ’符号！ 例如上面的例子可以发现，使用‘ cd ~ ’可以回到个人的家目录里头去呢！ 另外，针对 cd 的使用方法，如果仅输入 cd 时，代表的就是‘ cd ~ ’的意思喔～ 亦即是会回到自己的家目录啦！而那个‘ cd - ’比较难以理解，请自行多做几次练习， 就会比较明白了。

Tips:
还是要一再地提醒，我们的 Linux 的预设指令列模式 (bash shell) 具有档案补齐功能， 你要常常利用 [tab] 按键来达成你的目录完整性啊！这可是个好习惯啊～ 可以避免你按错键盘输入错字说～ ^_^ 		鸟哥的图示
  • pwd (显示目前所在的目录)
[root@www ~]# pwd [-P]
选项与参数：
-P  ：显示出确实的路径，而非使用连结 (link) 路径。

范例：单纯显示出目前的工作目录：
[root@www ~]# pwd

/root   <== 显示出目录啦～

范例：显示出实际的工作目录，而非连结档本身的目录名而已
[root@www ~]# cd /var/mail   <==注意，/var/mail是一个连结档
[root@www mail]# pwd
/var/mail         <==列出目前的工作目录

[root@www mail]# pwd -P
/var/spool/mail   <==怎么回事？有没有加 -P 差很多～
[root@www mail]# ls -ld /var/mail
lrwxrwxrwx 1 root root 10 Sep  4 17:54 /var/mail -> spool/mail
# 看到这里应该知道为啥了吧？因为 /var/mail 是连结档，连结到 /var/spool/mail
# 所以，加上 pwd -P 的选项后，会不以连结档的资料显示，而是显示正确的完整路径啊！

pwd是Print Working Directory的缩写，也就是显示目前所在目录的指令， 例如在上个表格最后的目录是/var/mail这个目录，但是提示字元仅显示mail， 如果你想要知道目前所在的目录，可以输入pwd即可。此外，由于很多的套件所使用的目录名称都相同，例如 /usr/local/etc还有/etc，但是通常Linux仅列出最后面那一个目录而已，这个时候你就可以使用pwd 来知道你的所在目录啰！免得搞错目录，结果...

其实有趣的是那个 -P 的选项啦！他可以让我们取得正确的目录名称，而不是以连结档的路径来显示的。 如果你使用的是CentOS 5.x的话，刚刚好/var/mail是/var/spool/mail的连结档， 所以，透过到/var/mail下达pwd -P就能够知道这个选项的意义啰～ ^_^

  • mkdir (建立新目录)
[root@www ~]# mkdir [-mp] 目录名称

选项与参数：
-m ：设定档案的权限喔！直接设定，不需要看预设权限 (umask) 的脸色～
-p ：帮助你直接将所需要的目录(包含上层目录)递回建立起来！

范例：请到/tmp底下尝试建立数个新目录看看：
[root@www ~]# cd /tmp
[root@www tmp]# mkdir test    <==建立一名为 test 的新目录
[root@www tmp]# mkdir test1/test2/test3/test4
mkdir: cannot create directory `test1/test2/test3/test4':
No such file or directory       <== 没办法直接建立此目录啊！

[root@www tmp]# mkdir -p test1/test2/test3/test4
# 加了这个 -p 的选项，可以自行帮你建立多层目录！

范例：建立权限为rwx--x--x的目录
[root@www tmp]# mkdir -m 711 test2
[root@www tmp]# ls -l
drwxr-xr-x  3 root  root 4096 Jul 18 12:50 test
drwxr-xr-x  3 root  root 4096 Jul 18 12:53 test1
drwx--x--x  2 root  root 4096 Jul 18 12:54 test2

# 仔细看上面的权限部分，如果没有加上 -m 来强制设定属性，系统会使用预设属性。
# 那么你的预设属性为何？这要透过底下介绍的 umask 才能了解喔！ ^_^

如果想要建立新的目录的话，那么就使用mkdir (make directory)吧！ 不过，在预设的情况下， 你所需要的目录得一层一层的建立才行！例如：假如你要建立一个目录为 /home/bird/testing/test1，那么首先必须要有 /home 然后 /home/bird ，再来 /home/bird/testing 都必须要存在，才可以建立 /home/bird/testing/test1 这个目录！假如没有 /home/bird/testing 时，就没有办法建立 test1 的目录啰！

不过，现在有个更简单有效的方法啦！那就是加上 -p 这个选项喔！你可以直接下达：‘ mkdir -p /home/bird/testing/test1 ’ 则系统会自动的帮你将 /home, /home/bird, /home/bird/testing 依序的建立起目录！并且， 如果该目录本来就已经存在时，系统也不会显示错误讯息喔！挺快乐的吧！ ^_^。 不过鸟哥不建议常用-p这个选项，因为担心如果你打错字，那么目录名称就会变的乱七八糟的！

另外，有个地方你必须要先有概念，那就是‘预设权限’的地方。我们可以利用 -m 来强制给予一个新的目录相关的权限， 例如上表当中，我们给予 -m 711 来给予新的目录 drwx--x--x 的权限。不过，如果没有给予 -m 选项时， 那么预设的新建目录权限又是什么呢？这个跟 umask 有关，我们在本章后头会加以介绍的。

  • rmdir (删除‘空’的目录)
[root@www ~]# rmdir [-p] 目录名称

选项与参数：
-p ：连同上层‘空的’目录也一起删除

范例：将于mkdir范例中建立的目录(/tmp底下)删除掉！
[root@www tmp]# ls -l   <==看看有多少目录存在？
drwxr-xr-x  3 root  root 4096 Jul 18 12:50 test
drwxr-xr-x  3 root  root 4096 Jul 18 12:53 test1
drwx--x--x  2 root  root 4096 Jul 18 12:54 test2
[root@www tmp]# rmdir test   <==可直接删除掉，没问题
[root@www tmp]# rmdir test1  <==因为尚有内容，所以无法删除！

rmdir: `test1': Directory not empty
[root@www tmp]# rmdir -p test1/test2/test3/test4
[root@www tmp]# ls -l        <==您看看，底下的输出中test与test1不见了！
drwx--x--x  2 root  root 4096 Jul 18 12:54 test2
# 瞧！利用 -p 这个选项，立刻就可以将 test1/test2/test3/test4 一次删除～
# 不过要注意的是，这个 rmdir 仅能‘删除空的目录’喔！

如果想要删除旧有的目录时，就使用rmdir吧！例如将刚刚建立的test杀掉，使用‘ rmdir test ’即可！请注意呦！目录需要一层一层的删除才行！而且被删除的目录里面必定不能存在其他的目录或档案！ 这也是所谓的空的目录(empty directory)的意思啊！那如果要将所有目录下的东西都杀掉呢？！ 这个时候就必须使用‘ rm -r test ’啰！不过，还是使用 rmdir 比较不危险！你也可以尝试以 -p 的选项加入，来删除上层的目录喔！

小标题的图示 关于执行档路径的变数： $PATH

经过第六章FHS的说明后，我们知道查阅档案属性的指令ls完整档名为：/bin/ls(这是绝对路径)， 那你会不会觉得很奇怪：‘为什么我可以在任何地方执行/bin/ls这个指令呢？ ’ 为什么我在任何目录下输入 ls 就一定可以显示出一些讯息而不会说找不到该 /bin/ls 指令呢？ 这是因为环境变数 PATH 的帮助所致呀！

当我们在执行一个指令的时候，举例来说‘ls’好了，系统会依照PATH的设定去每个PATH定义的目录下搜寻档名为ls的可执行档， 如果在PATH定义的目录中含有多个档名为ls的可执行档，那么先搜寻到的同名指令先被执行！

现在，请下达‘echo $PATH’来看看到底有哪些目录被定义出来了？ echo有‘显示、印出’的意思，而 PATH 前面加的 $ 表示后面接的是变数，所以会显示出目前的 PATH ！

范例：先用root的身份列出搜寻的路径为何？
[root@www ~]# echo $PATH
/usr/kerberos/sbin:/usr/kerberos/bin:/usr/local/sbin:/usr/local/bin:/sbin
:/bin:/usr/sbin:/usr/bin:/root/bin  <==这是同一行！

范例：用vbird的身份列出搜寻的路径为何？
[root@www ~]# su - vbird
[vbird@www ~]# echo $PATH
/usr/kerberos/bin:/usr/local/bin:/bin:/usr/bin:/home/vbird/bin
# 仔细看，一般用户vbird的PATH中，并不包含任何‘sbin’的目录存在喔！

PATH(一定是大写)这个变数的内容是由一堆目录所组成的，每个目录中间用冒号(:)来隔开， 每个目录是有‘顺序’之分的。仔细看一下上面的输出，你可以发现到无论是root还是vbird都有/bin 这个目录在PATH变数内，所以当然就能够在任何地方执行ls来找到/bin/ls执行档啰！

我们用几个范例来让你了解一下，为什么PATH是那么重要的项目！

例题：
请问你能不能使用一般身份使用者下达ifconfig eth0这个指令呢？
答：
如上面的范例所示，当你使用vbird这个帐号执行ifconfig时，会出现‘-bash: ifconfig: command not found’的字样， 因为ifconfig的是放置到/sbin底下，而由上表的结果中我们可以发现vbird的PATH并没有设置/sbin， 所以预设无法执行。

但是你可以使用‘/sbin/ifconfig eth0’来执行这个指令喔！因为一般用户还是可以使用ifconfig来查询系统IP的参数， 既然PATH没有规范到/sbin，那么我们使用‘绝对路径’也可以执行到该指令的！

例题：
假设你是root，如果你将ls由/bin/ls移动成为/root/ls(可用‘mv /bin/ls /root’指令达成)，然后你自己本身也在/root目录下， 请问(1)你能不能直接输入ls来执行？(2)若不能，你该如何执行ls这个指令？(3)若要直接输入ls即可执行，又该如何进行？
答：
由于这个例题的重点是将某个执行档移动到非正规目录去，所以我们先要进行底下的动作才行：(务必使用root的身份)
[root@www ~]# mv /bin/ls /root
# mv 为移动，可将档案在不同的目录间进行移动作业
(1)接下来不论你在那个目录底下输入任何与ls相关的指令，都没有办法顺利的执行ls了！ 也就是说，你不能直接输入ls来执行，因为/root这个目录并不在PATH指定的目录中， 所以，即使你在/root目录下，也不能够搜寻到ls这个指令！

(2)因为这个ls确实存在于/root底下，并不是被删除了！所以我们可以透过使用绝对路径或者是相对路径直接指定这个执行档档名， 底下的两个方法都能够执行ls这个指令：
[root@www ~]# /root/ls  <==直接用绝对路径指定该档名
[root@www ~]# ./ls      <==因为在 /root 目录下，就用./ls来指定
(3)如果想要让root在任何目录均可执行/root底下的ls，那么就将/root加入PATH当中即可。 加入的方法很简单，就像底下这样：
[root@www ~]# PATH="$PATH":/root
上面这个作法就能够将/root加入到执行档搜寻路径PATH中了！不相信的话请您自行使用‘echo $PATH’去查看吧！ 如果确定这个例题进行没有问题了，请将ls搬回/bin底下，不然系统会挂点的！
[root@www ~]# mv /root/ls /bin

例题：
如果我有两个ls指令在不同的目录中，例如/usr/local/bin/ls与/bin/ls那么当我下达 ls 的时候，哪个ls会被执行？
答：
那还用说，就找出 PATH 里面哪个目录先被查询，则那个目录下的指令就会被先执行了！

例题：
为什么PATH搜寻的目录不加入本目录(.)？加入本目录的搜寻不是也不错？
答：
如果在PATH中加入本目录(.)后，确实我们就能够在指令所在目录进行指令的执行了。 但是由于你的工作目录并非固定(常常会使用cd来切换到不同的目录)， 因此能够执行的指令会有变动(因为每个目录底下的可执行档都不相同嘛！)，这对使用者来说并非好事。

另外，如果有个坏心使用者在/tmp底下做了一个指令，因为/tmp是大家都能够写入的环境，所以他当然可以这样做。 假设该指令可能会窃取使用者的一些资料，如果你使用root的身份来执行这个指令，那不是很糟糕？ 如果这个指令的名称又是经常会被用到的ls时，那‘中标’的机率就更高了！

所以，为了安全起见，不建议将‘.’加入PATH的搜寻目录中。

而由上面的几个例题我们也可以知道几件事情：

  • 不同身份使用者预设的PATH不同，预设能够随意执行的指令也不同(如root与vbird)；
  • PATH是可以修改的，所以一般使用者还是可以透过修改PATH来执行某些位于/sbin或/usr/sbin下的指令来查询；
  • 使用绝对路径或相对路径直接指定某个指令的档名来执行，会比搜寻PATH来的正确；
  • 指令应该要放置到正确的目录下，执行才会比较方便；
  • 本目录(.)最好不要放到PATH当中。

对于PATH更详细的‘变数’说明，我们会在第三篇的bash shell中详细说明的！

大标题的图示 档案与目录管理：

谈了谈目录与路径之后，再来讨论一下关于档案的一些基本管理吧！档案与目录的管理上，不外乎‘显示属性’、 ‘拷贝’、‘删除档案’及‘移动档案或目录’等等，由于档案与目录的管理在 Linux 当中是很重要的， 尤其是每个人自己家目录的资料也都需要注意管理！所以我们来谈一谈有关档案与目录的一些基础管理部分吧！

小标题的图示 档案与目录的检视： ls
[root@www ~]# ls [-aAdfFhilnrRSt] 目录名称
[root@www ~]# ls [--color={never,auto,always}] 目录名称
[root@www ~]# ls [--full-time] 目录名称

选项与参数：
-a  ：全部的档案，连同隐藏档( 开头为 . 的档案) 一起列出来(常用)
-A  ：全部的档案，连同隐藏档，但不包括 . 与 .. 这两个目录
-d  ：仅列出目录本身，而不是列出目录内的档案资料(常用)
-f  ：直接列出结果，而不进行排序 (ls 预设会以档名排序！)
-F  ：根据档案、目录等资讯，给予附加资料结构，例如：
      *:代表可执行档； /:代表目录； =:代表 socket 档案； |:代表 FIFO 档案；
-h  ：将档案容量以人类较易读的方式(例如 GB, KB 等等)列出来；
-i  ：列出 inode 号码，inode 的意义下一章将会介绍；
-l  ：长资料串列出，包含档案的属性与权限等等资料；(常用)
-n  ：列出 UID 与 GID 而非使用者与群组的名称 (UID与GID会在帐号管理提到！)
-r  ：将排序结果反向输出，例如：原本档名由小到大，反向则为由大到小；
-R  ：连同子目录内容一起列出来，等于该目录下的所有档案都会显示出来；
-S  ：以档案容量大小排序，而不是用档名排序；
-t  ：依时间排序，而不是用档名。
--color=never  ：不要依据档案特性给予颜色显示；
--color=always ：显示颜色
--color=auto   ：让系统自行依据设定来判断是否给予颜色
--full-time    ：以完整时间模式 (包含年、月、日、时、分) 输出
--time={atime,ctime} ：输出 access 时间或改变权限属性时间 (ctime)
                       而非内容变更时间 (modification time)

在Linux系统当中，这个 ls 指令可能是最常被执行的吧！因为我们随时都要知道档案或者是目录的相关资讯啊～ 不过，我们Linux的档案所记录的资讯实在是太多了，ls 没有需要全部都列出来呢～ 所以，当你只有下达 ls 时，预设显示的只有：非隐藏档的档名、 以档名进行排序及档名代表的颜色显示如此而已。举例来说， 你下达‘ ls /etc ’之后，只有经过排序的档名以及以蓝色显示目录及白色显示一般档案，如此而已。

那如果我还想要加入其他的显示资讯时，可以加入上头提到的那些有用的选项呢～ 举例来说，我们之前一直用到的 -l 这个长串显示资料内容，以及将隐藏档也一起列示出来的 -a 选项等等。 底下则是一些常用的范例，实际试做看看：

范例一：将家目录下的所有档案列出来(含属性与隐藏档)
[root@www ~]# ls -al ~
total 156
drwxr-x---  4 root root  4096 Sep 24 00:07 .
drwxr-xr-x 23 root root  4096 Sep 22 12:09 ..

-rw-------  1 root root  1474 Sep  4 18:27 anaconda-ks.cfg
-rw-------  1 root root   955 Sep 24 00:08 .bash_history
-rw-r--r--  1 root root    24 Jan  6  2007 .bash_logout
-rw-r--r--  1 root root   191 Jan  6  2007 .bash_profile
-rw-r--r--  1 root root   176 Jan  6  2007 .bashrc
drwx------  3 root root  4096 Sep  5 10:37 .gconf
-rw-r--r--  1 root root 42304 Sep  4 18:26 install.log
-rw-r--r--  1 root root  5661 Sep  4 18:25 install.log.syslog
# 这个时候你会看到以 . 为开头的几个档案，以及目录档 (.) (..) .gconf 等等，
# 不过，目录档档名都是以深蓝色显示，有点不容易看清楚就是了。

范例二：承上题，不显示颜色，但在档名末显示出该档名代表的类型(type)
[root@www ~]# ls -alF --color=never  ~
total 156
drwxr-x---  4 root root  4096 Sep 24 00:07 ./
drwxr-xr-x 23 root root  4096 Sep 22 12:09 ../
-rw-------  1 root root  1474 Sep  4 18:27 anaconda-ks.cfg
-rw-------  1 root root   955 Sep 24 00:08 .bash_history
-rw-r--r--  1 root root    24 Jan  6  2007 .bash_logout
-rw-r--r--  1 root root   191 Jan  6  2007 .bash_profile
-rw-r--r--  1 root root   176 Jan  6  2007 .bashrc
drwx------  3 root root  4096 Sep  5 10:37 .gconf/
-rw-r--r--  1 root root 42304 Sep  4 18:26 install.log
-rw-r--r--  1 root root  5661 Sep  4 18:25 install.log.syslog
# 注意看到显示结果的第一行，嘿嘿～知道为何我们会下达类似 ./command
# 之类的指令了吧？因为 ./ 代表的是‘目前目录下’的意思啊！至于什么是 FIFO/Socket ？
# 请参考前一章节的介绍啊！另外，那个.bashrc 时间仅写2007，能否知道详细时间？

范例三：完整的呈现档案的修改时间 *(modification time)

[root@www ~]# ls -al --full-time  ~
total 156
drwxr-x---  4 root root  4096 2008-09-24 00:07:00.000000 +0800 .
drwxr-xr-x 23 root root  4096 2008-09-22 12:09:32.000000 +0800 ..
-rw-------  1 root root  1474 2008-09-04 18:27:10.000000 +0800 anaconda-ks.cfg
-rw-------  1 root root   955 2008-09-24 00:08:14.000000 +0800 .bash_history
-rw-r--r--  1 root root    24 2007-01-06 17:05:04.000000 +0800 .bash_logout
-rw-r--r--  1 root root   191 2007-01-06 17:05:04.000000 +0800 .bash_profile
-rw-r--r--  1 root root   176 2007-01-06 17:05:04.000000 +0800 .bashrc
drwx------  3 root root  4096 2008-09-05 10:37:49.000000 +0800 .gconf
-rw-r--r--  1 root root 42304 2008-09-04 18:26:57.000000 +0800 install.log
-rw-r--r--  1 root root  5661 2008-09-04 18:25:55.000000 +0800 install.log.syslog
# 请仔细看，上面的‘时间’栏位变了喔！变成较为完整的格式。
# 一般来说， ls -al 仅列出目前短格式的时间，有时不会列出年份，
# 藉由 --full-time 可以查阅到比较正确的完整时间格式啊！

其实 ls 的用法还有很多，包括查阅档案所在 i-node 号码的 ls -i 选项，以及用来进行档案排序的 -S 选项，还有用来查阅不同时间的动作的 --time=atime 等选项(更多时间说明请参考本章后面touch的说明)。而这些选项的存在都是因为 Linux 档案系统记录了很多有用的资讯的缘故。那么 Linux 的档案系统中，这些与权限、属性有关的资料放在哪里呢？ 放在 i-node 里面。关于这部分，我们会在下一章继续为你作比较深入的介绍啊！

无论如何， ls 最常被使用到的功能还是那个 -l 的选项，为此，很多 distribution 在预设的情况中， 已经将 ll (L 的小写) 设定成为 ls -l 的意思了！其实，那个功能是 Bash shell 的 alias 功能呢～也就是说，我们直接输入 ll 就等于是输入 ls -l 是一样的～关于这部分，我们会在后续 bash shell 时再次的强调滴～

小标题的图示 复制、删除与移动： cp, rm, mv

要复制档案，请使用 cp (copy) 这个指令即可～不过， cp 这个指令的用途可多了～ 除了单纯的复制之外，还可以建立连结档 (就是捷径啰)，比对两档案的新旧而予以更新， 以及复制整个目录等等的功能呢！至于移动目录与档案，则使用 mv (move)， 这个指令也可以直接拿来作更名 (rename) 的动作喔！至于移除吗？那就是 rm (remove) 这个指令啰～底下我们就来瞧一瞧先～

  • cp (复制档案或目录)
[root@www ~]# cp [-adfilprsu] 来源档(source) 目标档(destination)
[root@www ~]# cp [options] source1 source2 source3 .... directory
选项与参数：
-a  ：相当于 -pdr 的意思，至于 pdr 请参考下列说明；(常用)
-d  ：若来源档为连结档的属性(link file)，则复制连结档属性而非档案本身；
-f  ：为强制(force)的意思，若目标档案已经存在且无法开启，则移除后再尝试一次；
-i  ：若目标档(destination)已经存在时，在覆盖时会先询问动作的进行(常用)

-l  ：进行硬式连结(hard link)的连结档建立，而非复制档案本身；
-p  ：连同档案的属性一起复制过去，而非使用预设属性(备份常用)；
-r  ：递回持续复制，用于目录的复制行为；(常用)
-s  ：复制成为符号连结档 (symbolic link)，亦即‘捷径’档案；
-u  ：若 destination 比 source 旧才更新 destination ！
最后需要注意的，如果来源档有两个以上，则最后一个目的档一定要是‘目录’才行！

复制(cp)这个指令是非常重要的，不同身份者执行这个指令会有不同的结果产生，尤其是那个-a, -p的选项， 对于不同身份来说，差异则非常的大！底下的练习中，有的身份为root有的身份为一般帐号(在我这里用vbird这个帐号)， 练习时请特别注意身份的差别喔！好！开始来做复制的练习与观察：

范例一：用root身份，将家目录下的 .bashrc 复制到 /tmp 下，并更名为 bashrc
[root@www ~]# cp ~/.bashrc /tmp/bashrc

[root@www ~]# cp -i ~/.bashrc /tmp/bashrc
cp: overwrite `/tmp/bashrc'? n  <==n不覆盖，y为覆盖
# 重复作两次动作，由于 /tmp 底下已经存在 bashrc 了，加上 -i 选项后，
# 则在覆盖前会询问使用者是否确定！可以按下 n 或者 y 来二次确认呢！

范例二：变换目录到/tmp，并将/var/log/wtmp复制到/tmp且观察属性：
[root@www ~]# cd /tmp
[root@www tmp]# cp /var/log/wtmp . <==想要复制到目前的目录，最后的 . 不要忘

[root@www tmp]# ls -l /var/log/wtmp wtmp
-rw-rw-r-- 1 root utmp 96384 Sep 24 11:54 /var/log/wtmp
-rw-r--r-- 1 root root 96384 Sep 24 14:06 wtmp

# 注意上面的特殊字体，在不加任何选项的情况下，档案的某些属性/权限会改变；
# 这是个很重要的特性！要注意喔！还有，连档案建立的时间也不一样了！
# 那如果你想要将档案的所有特性都一起复制过来该怎办？可以加上 -a 喔！如下所示：

[root@www tmp]# cp -a /var/log/wtmp wtmp_2
[root@www tmp]# ls -l /var/log/wtmp wtmp_2
-rw-rw-r-- 1 root utmp 96384 Sep 24 11:54 /var/log/wtmp
-rw-rw-r-- 1 root utmp 96384 Sep 24 11:54 wtmp_2
# 了了吧！整个资料特性完全一模一样ㄟ！真是不赖～这就是 -a 的特性！

这个 cp 的功能很多，由于我们常常会进行一些资料的复制，所以也会常常用到这个指令的。 一般来说，我们如果去复制别人的资料 (当然，该档案你必须要有 read 的权限才行啊！ ^_^) 时， 总是希望复制到的资料最后是我们自己的，所以，在预设的条件中， cp 的来源档与目的档的权限是不同的，目的档的拥有者通常会是指令操作者本身。举例来说， 上面的范例二中，由于我是 root 的身份，因此复制过来的档案拥有者与群组就改变成为 root 所有了！ 这样说，可以明白吗？^_^

由于具有这个特性，因此当我们在进行备份的时候，某些需要特别注意的特殊权限档案， 例如密码档 (/etc/shadow) 以及一些设定档，就不能直接以 cp 来复制，而必须要加上 -a 或者是 -p 等等可以完整复制档案权限的选项才行！另外，如果你想要复制档案给其他的使用者， 也必须要注意到档案的权限(包含读、写、执行以及档案拥有者等等)， 否则，其他人还是无法针对你给予的档案进行修订的动作喔！注意注意！

范例三：复制 /etc/ 这个目录下的所有内容到 /tmp 底下
[root@www tmp]# cp /etc/ /tmp
cp: omitting directory `/etc'   <== 如果是目录则不能直接复制，要加上 -r 的选项
[root@www tmp]# cp -r /etc/ /tmp

# 还是要再次的强调喔！ -r 是可以复制目录，但是，档案与目录的权限可能会被改变
# 所以，也可以利用‘ cp -a /etc /tmp ’来下达指令喔！尤其是在备份的情况下！

范例四：将范例一复制的 bashrc 建立一个连结档 (symbolic link)
[root@www tmp]# ls -l bashrc
-rw-r--r-- 1 root root 176 Sep 24 14:02 bashrc  <==先观察一下档案情况
[root@www tmp]# cp -s bashrc bashrc_slink
[root@www tmp]# cp -l bashrc bashrc_hlink

[root@www tmp]# ls -l bashrc*
-rw-r--r-- 2 root root 176 Sep 24 14:02 bashrc  <==与原始档案不太一样了！
-rw-r--r-- 2 root root 176 Sep 24 14:02 bashrc_hlink
lrwxrwxrwx 1 root root   6 Sep 24 14:20 bashrc_slink -> bashrc

范例四可有趣了！使用 -l 及 -s 都会建立所谓的连结档(link file)，但是这两种连结档却有不一样的情况。这是怎么一回事啊？ 那个 -l 就是所谓的实体连结(hard link)，至于 -s 则是符号连结(symbolic link)， 简单来说，bashrc_slink 是一个‘捷径’，这个捷径会连结到bashrc去！所以你会看到档名右侧会有个指向(->)的符号！

至于bashrc_hlink档案与bashrc的属性与权限完全一模一样，与尚未进行连结前的差异则是第二栏的link数由1变成2了！ 鸟哥这里先不介绍实体连结，因为实体连结涉及 i-node 的相关知识，我们下一章谈到档案系统(filesystem)时再来讨论这个问题。

范例五：若 ~/.bashrc 比 /tmp/bashrc 新才复制过来
[root@www tmp]# cp -u ~/.bashrc /tmp/bashrc
# 这个 -u 的特性，是在目标档案与来源档案有差异时，才会复制的。
# 所以，比较常被用于‘备份’的工作当中喔！ ^_^

范例六：将范例四造成的 bashrc_slink 复制成为 bashrc_slink_1 与bashrc_slink_2
[root@www tmp]# cp bashrc_slink bashrc_slink_1
[root@www tmp]# cp -d bashrc_slink bashrc_slink_2
[root@www tmp]# ls -l bashrc bashrc_slink*
-rw-r--r-- 2 root root 176 Sep 24 14:02 bashrc
lrwxrwxrwx 1 root root   6 Sep 24 14:20 bashrc_slink -> bashrc
-rw-r--r-- 1 root root 176 Sep 24 14:32 bashrc_slink_1       <==与原始档案相同

lrwxrwxrwx 1 root root   6 Sep 24 14:33 bashrc_slink_2 -> bashrc <==是连结档！
# 这个例子也是很有趣喔！原本复制的是连结档，但是却将连结档的实际档案复制过来了
# 也就是说，如果没有加上任何选项时，cp复制的是原始档案，而非连结档的属性！
# 若要复制连结档的属性，就得要使用 -d 的选项了！如 bashrc_slink_2 所示。

范例七：将家目录的 .bashrc 及 .bash_history 复制到 /tmp 底下
[root@www tmp]# cp ~/.bashrc ~/.bash_history /tmp
# 可以将多个资料一次复制到同一个目录去！最后面一定是目录！
例题：
你能否使用vbird的身份，完整的复制/var/log/wtmp档案到/tmp底下，并更名为vbird_wtmp呢？
答：
实际做看看的结果如下：
[vbird@www ~]$ cp -a /var/log/wtmp /tmp/vbird_wtmp
[vbird@www ~]$ ls -l /var/log/wtmp /tmp/vbird_wtmp

-rw-rw-r-- 1 vbird vbird 96384  9月 24 11:54 /tmp/vbird_wtmp
-rw-rw-r-- 1 root  utmp  96384  9月 24 11:54 /var/log/wtmp
由于vbird的身份并不能随意修改档案的拥有者与群组，因此虽然能够复制wtmp的相关权限与时间等属性， 但是与拥有者、群组相关的，原本vbird身份无法进行的动作，即使加上 -a 选项，也是无法达成完整复制权限的！

总之，由于 cp 有种种的档案属性与权限的特性，所以，在复制时，你必须要清楚的了解到：

  • 是否需要完整的保留来源档案的资讯？
  • 来源档案是否为连结档 (symbolic link file)？
  • 来源档是否为特殊的档案，例如 FIFO, socket 等？
  • 来源档是否为目录？

  • rm (移除档案或目录)
[root@www ~]# rm [-fir] 档案或目录
选项与参数：
-f  ：就是 force 的意思，忽略不存在的档案，不会出现警告讯息；
-i  ：互动模式，在删除前会询问使用者是否动作
-r  ：递回删除啊！最常用在目录的删除了！这是非常危险的选项！！！

范例一：将刚刚在 cp 的范例中建立的 bashrc 删除掉！
[root@www ~]# cd /tmp
[root@www tmp]# rm -i bashrc

rm: remove regular file `bashrc'? y
# 如果加上 -i 的选项就会主动询问喔，避免你删除到错误的档名！

范例二：透过万用字元*的帮忙，将/tmp底下开头为bashrc的档名通通删除：
[root@www tmp]# rm -i bashrc*
# 注意那个星号，代表的是 0 到无穷多个任意字元喔！很好用的东西！

范例三：将 cp 范例中所建立的 /tmp/etc/ 这个目录删除掉！
[root@www tmp]# rmdir /tmp/etc

rmdir: etc: Directory not empty  <== 删不掉啊！因为这不是空的目录！
[root@www tmp]# rm -r /tmp/etc
rm: descend into directory `/tmp/etc'? y
....(中间省略)....
# 因为身份是 root ，预设已经加入了 -i 的选项，所以你要一直按 y 才会删除！
# 如果不想要继续按 y ，可以按下‘ [ctrl]-c ’来结束 rm 的工作。
# 这是一种保护的动作，如果确定要删除掉此目录而不要询问，可以这样做：
[root@www tmp]# \rm -r /tmp/etc
# 在指令前加上反斜线，可以忽略掉 alias 的指定选项喔！至于 alias 我们在bash再谈！

范例四：删除一个带有 - 开头的档案
[root@www tmp]# touch ./-aaa-  <==touch这个指令可以建立空档案！
[root@www tmp]# ls -l
-rw-r--r-- 1 root  root      0 Sep 24 15:03 -aaa-  <==档案大小为0，所以是空档案
[root@www tmp]# rm -aaa-

Try `rm --help' for more information.  <== 因为 "-" 是选项嘛！所以系统误判了！
[root@www tmp]# rm ./-aaa-

这是移除的指令(remove)，要注意的是，通常在Linux系统下，为了怕档案被误杀，所以很多 distributions 都已经预设加入 -i 这个选项了！而如果要连目录下的东西都一起杀掉的话， 例如子目录里面还有子目录时，那就要使用 -r 这个选项了！不过，使用‘ rm -r ’这个指令之前，请千万注意了，因为该目录或档案‘肯定’会被 root 杀掉！因为系统不会再次询问你是否要砍掉呦！所以那是个超级严重的指令下达呦！ 得特别注意！不过，如果你确定该目录不要了，那么使用 rm -r 来循环杀掉是不错的方式！

另外，范例四也是很有趣的例子，我们在之前就谈过，档名最好不要使用 "-" 号开头， 因为 "-" 后面接的是选项，因此，单纯的使用‘ rm -aaa- ’系统的指令就会误判啦！ 那如果使用后面会谈到的正规表示法时，还是会出问题的！所以，只能用避过首位字元是 "-" 的方法啦！ 就是加上本目录‘ ./ ’即可！如果 man rm 的话，其实还有一种方法，那就是‘ rm -- -aaa- ’也可以啊！

  • mv (移动档案与目录，或更名)
[root@www ~]# mv [-fiu] source destination
[root@www ~]# mv [options] source1 source2 source3 .... directory
选项与参数：
-f  ：force 强制的意思，如果目标档案已经存在，不会询问而直接覆盖；
-i  ：若目标档案 (destination) 已经存在时，就会询问是否覆盖！
-u  ：若目标档案已经存在，且 source 比较新，才会更新 (update)

范例一：复制一档案，建立一目录，将档案移动到目录中
[root@www ~]# cd /tmp
[root@www tmp]# cp ~/.bashrc bashrc
[root@www tmp]# mkdir mvtest
[root@www tmp]# mv bashrc mvtest
# 将某个档案移动到某个目录去，就是这样做！

范例二：将刚刚的目录名称更名为 mvtest2
[root@www tmp]# mv mvtest mvtest2 <== 这样就更名了！简单～
# 其实在 Linux 底下还有个有趣的指令，名称为 rename ，
# 该指令专职进行多个档名的同时更名，并非针对单一档名变更，与mv不同。请man rename。

范例三：再建立两个档案，再全部移动到 /tmp/mvtest2 当中
[root@www tmp]# cp ~/.bashrc bashrc1

[root@www tmp]# cp ~/.bashrc bashrc2
[root@www tmp]# mv bashrc1 bashrc2 mvtest2
# 注意到这边，如果有多个来源档案或目录，则最后一个目标档一定是‘目录！’
# 意思是说，将所有的资料移动到该目录的意思！

这是搬移 (move) 的意思！当你要移动档案或目录的时后，呵呵！这个指令就很重要啦！ 同样的，你也可以使用 -u ( update )来测试新旧档案，看看是否需要搬移啰！ 另外一个用途就是‘变更档名！’，我们可以很轻易的使用 mv 来变更一个档案的档名呢！不过，在 Linux 才有的指令当中，有个 rename ， 可以用来更改大量档案的档名，你可以利用 man rename 来查阅一下，也是挺有趣的指令喔！

小标题的图示 取得路径的档案名称与目录名称

我们前面介绍的完整档名 (包含目录名称与档案名称) 当中提到，完整档名最长可以到达 4096 个字元。 那么你怎么知道那个是档名？那个是目录名？嘿嘿！就是利用斜线 (/) 来分辨啊！ 其实，取得档名或者是目录名称，一般的用途应该是在写程式的时候，用来判断之用的啦～ 所以，这部分的指令可以用在第三篇内的 shell scripts 里头喔！ 底下我们简单的以几个范例来谈一谈 basename 与 dirname 的用途！

[root@www ~]# basename /etc/sysconfig/network
network         <== 很简单！就取得最后的档名～

[root@www ~]# dirname /etc/sysconfig/network
/etc/sysconfig  <== 取得的变成目录名了！
大标题的图示 档案内容查阅：

如果我们要查阅一个档案的内容时，该如何是好呢？这里有相当多有趣的指令可以来分享一下： 最常使用的显示档案内容的指令可以说是 cat 与 more 及 less 了！此外，如果我们要查看一个很大型的档案 (好几百MB时)，但是我们只需要后端的几行字而已，那么该如何是好？呵呵！用 tail 呀，此外， tac 这个指令也可以达到！好了，说说各个指令的用途吧！

  • cat 由第一行开始显示档案内容
  • tac 从最后一行开始显示，可以看出 tac 是 cat 的倒着写！
  • nl 显示的时候，顺道输出行号！
  • more 一页一页的显示档案内容
  • less 与 more 类似，但是比 more 更好的是，他可以往前翻页！
  • head 只看头几行
  • tail 只看尾巴几行
  • od 以二进位的方式读取档案内容！
小标题的图示 直接检视档案内容

直接查阅一个档案的内容可以使用 cat/tac/nl 这几个指令啊！

  • cat (concatenate)
[root@www ~]# cat [-AbEnTv]

选项与参数：
-A  ：相当于 -vET 的整合选项，可列出一些特殊字符而不是空白而已；
-b  ：列出行号，仅针对非空白行做行号显示，空白行不标行号！
-E  ：将结尾的断行字元 $ 显示出来；
-n  ：列印出行号，连同空白行也会有行号，与 -b 的选项不同；
-T  ：将 [tab] 按键以 ^I 显示出来；
-v  ：列出一些看不出来的特殊字符

范例一：检阅 /etc/issue 这个档案的内容
[root@www ~]# cat /etc/issue
CentOS release 5.3 (Final)
Kernel \r on an \m

范例二：承上题，如果还要加印行号呢？
[root@www ~]# cat -n /etc/issue

     1  CentOS release 5.3 (Final)
     2  Kernel \r on an \m
     3
# 看到了吧！可以印出行号呢！这对于大档案要找某个特定的行时，有点用处！
# 如果不想要编排空白行的行号，可以使用‘cat -b /etc/issue’，自己测试看看：

范例三：将 /etc/xinetd.conf 的内容完整的显示出来(包含特殊字元)
[root@www ~]# cat -A /etc/xinetd.conf
#$
....(中间省略)....
$

defaults$
{$
# The next two items are intended to be a quick access place to$
....(中间省略)....
^Ilog_type^I= SYSLOG daemon info $

^Ilog_on_failure^I= HOST$
^Ilog_on_success^I= PID HOST DURATION EXIT$
....(中间省略)....
includedir /etc/xinetd.d$

 $
# 上面的结果限于篇幅，鸟哥删除掉很多资料了。另外，输出的结果并不会有特殊字体，
# 鸟哥上面的特殊字体是要让您发现差异点在哪里就是了。基本上，在一般的环境中，
# 使用 [tab] 与空白键的效果差不多，都是一堆空白啊！我们无法知道两者的差别。
# 此时使用 cat -A 就能够发现那些空白的地方是啥鬼东西了！[tab]会以 ^I 表示，
# 断行字元则是以 $ 表示，所以你可以发现每一行后面都是 $ 啊！不过断行字元
# 在Windows/Linux则不太相同，Windows的断行字元是 ^M$ 啰。
# 这部分我们会在第十章 vim 软体的介绍时，再次的说明到喔！

嘿嘿！Linux 里面有‘猫’指令？喔！不是的， cat 是 Concatenate （连续）的简写， 主要的功能是将一个档案的内容连续的印出在荧幕上面！例如上面的例子中，我们将 /etc/issue 印出来！如果加上 -n 或 -b 的话，则每一行前面还会加上行号呦！

鸟哥个人是比较少用 cat 啦！毕竟当你的档案内容的行数超过 40 行以上，嘿嘿！根本来不及在荧幕上看到结果！ 所以，配合等一下要介绍的 more 或者是 less 来执行比较好！此外，如果是一般的 DOS 档案时，就需要特别留意一些奇奇怪怪的符号了， 例如断行与 [tab] 等，要显示出来，就得加入 -A 之类的选项了！

  • tac (反向列示)
[root@www ~]# tac /etc/issue

Kernel \r on an \m
CentOS release 5.3 (Final)
# 嘿嘿！与刚刚上面的范例一比较，是由最后一行先显示喔！

tac 这个好玩了！怎么说呢？详细的看一下， cat 与 tac ，有没有发现呀！对啦！ tac 刚好是将 cat 反写过来，所以他的功能就跟 cat 相反啦， cat 是由‘第一行到最后一行连续显示在荧幕上’，而 tac 则是‘ 由最后一行到第一行反向在荧幕上显示出来 ’，很好玩吧！

  • nl (添加行号列印)
[root@www ~]# nl [-bnw] 档案
选项与参数：
-b  ：指定行号指定的方式，主要有两种：
      -b a ：表示不论是否为空行，也同样列出行号(类似 cat -n)；
      -b t ：如果有空行，空的那一行不要列出行号(预设值)；
-n  ：列出行号表示的方法，主要有三种：
      -n ln ：行号在荧幕的最左方显示；
      -n rn ：行号在自己栏位的最右方显示，且不加 0 ；
      -n rz ：行号在自己栏位的最右方显示，且加 0 ；
-w  ：行号栏位的占用的位元数。

范例一：用 nl 列出 /etc/issue 的内容
[root@www ~]# nl /etc/issue

     1  CentOS release 5.3 (Final)
     2  Kernel \r on an \m

# 注意看，这个档案其实有三行，第三行为空白(没有任何字元)，
# 因为他是空白行，所以 nl 不会加上行号喔！如果确定要加上行号，可以这样做：

[root@www ~]# nl -b a /etc/issue
     1  CentOS release 5.3 (Final)
     2  Kernel \r on an \m
     3
# 呵呵！行号加上来啰～那么如果要让行号前面自动补上 0 呢？可这样

[root@www ~]# nl -b a -n rz /etc/issue
000001  CentOS release 5.3 (Final)
000002  Kernel \r on an \m
000003

# 嘿嘿！自动在自己栏位的地方补上 0 了～预设栏位是六位数，如果想要改成 3 位数？

[root@www ~]# nl -b a -n rz -w 3 /etc/issue
001     CentOS release 5.3 (Final)
002     Kernel \r on an \m
003
# 变成仅有 3 位数啰～

nl 可以将输出的档案内容自动的加上行号！其预设的结果与 cat -n 有点不太一样， nl 可以将行号做比较多的显示设计，包括位数与是否自动补齐 0 等等的功能呢。

小标题的图示 可翻页检视

前面提到的 nl 与 cat, tac 等等，都是一次性的将资料一口气显示到荧幕上面，那有没有可以进行一页一页翻动的指令啊？ 让我们可以一页一页的观察，才不会前面的资料看不到啊～呵呵！有的！那就是 more 与 less 啰～

  • more (一页一页翻动)
[root@www ~]# more /etc/man.config

#
# Generated automatically from man.conf.in by the
# configure script.
#
# man.conf from man-1.6d
....(中间省略)....
--More--(28%)  <== 重点在这一行喔！你的游标也会在这里等待你的指令

仔细的给他看到上面的范例，如果 more 后面接的档案内容行数大于荧幕输出的行数时， 就会出现类似上面的图示。重点在最后一行，最后一行会显示出目前显示的百分比， 而且还可以在最后一行输入一些有用的指令喔！在 more 这个程式的运作过程中，你有几个按键可以按的：

  • 空白键 (space)：代表向下翻一页；
  • Enter ：代表向下翻‘一行’；
  • /字串 ：代表在这个显示的内容当中，向下搜寻‘字串’这个关键字；
  • :f ：立刻显示出档名以及目前显示的行数；
  • q ：代表立刻离开 more ，不再显示该档案内容。
  • b 或 [ctrl]-b ：代表往回翻页，不过这动作只对档案有用，对管线无用。

要离开 more 这个指令的显示工作，可以按下 q 就能够离开了。而要向下翻页，就使用空白键即可。 比较有用的是搜寻字串的功能，举例来说，我们使用‘ more /etc/man.config ’来观察该档案， 若想要在该档案内搜寻 MANPATH 这个字串时，可以这样做：

[root@www ~]# more /etc/man.config
#
# Generated automatically from man.conf.in by the
# configure script.
#
# man.conf from man-1.6d
....(中间省略)....
/MANPATH   <== 输入了 / 之后，游标就会自动跑到最底下一行等待输入！

如同上面的说明，输入了 / 之后，游标就会跑到最底下一行，并且等待你的输入， 你输入了字串并按下[enter]之后，嘿嘿！ more 就会开始向下搜寻该字串啰～而重复搜寻同一个字串， 可以直接按下 n 即可啊！最后，不想要看了，就按下 q 即可离开 more 啦！

  • less (一页一页翻动)
[root@www ~]# less /etc/man.config
#
# Generated automatically from man.conf.in by the
# configure script.
#
# man.conf from man-1.6d

....(中间省略)....
:   <== 这里可以等待你输入指令！

less 的用法比起 more 又更加的有弹性，怎么说呢？在 more 的时候，我们并没有办法向前面翻， 只能往后面看，但若使用了 less 时，呵呵！就可以使用 [pageup] [pagedown] 等按键的功能来往前往后翻看文件，你瞧，是不是更容易使用来观看一个档案的内容了呢！

除此之外，在 less 里头可以拥有更多的‘搜寻’功能喔！不止可以向下搜寻，也可以向上搜寻～ 实在是很不错用～基本上，可以输入的指令有：

  • 空白键 ：向下翻动一页；
  • [pagedown]：向下翻动一页；
  • [pageup] ：向上翻动一页；
  • /字串 ：向下搜寻‘字串’的功能；
  • ?字串 ：向上搜寻‘字串’的功能；
  • n ：重复前一个搜寻 (与 / 或 ? 有关！)
  • N ：反向的重复前一个搜寻 (与 / 或 ? 有关！)
  • q ：离开 less 这个程式；

查阅档案内容还可以进行搜寻的动作～瞧～ less 是否很不错用啊！ 其实 less 还有很多的功能喔！详细的使用方式请使用 man less 查询一下啊！ ^_^

你是否会觉得 less 使用的画面与环境与 man page 非常的类似呢？没错啦！因为man这个指令就是呼叫 less 来显示说明文件的内容的！ 现在你是否觉得 less 很重要呢？ ^_^

小标题的图示 资料撷取

我们可以将输出的资料作一个最简单的撷取，那就是取出前面 (head) 与取出后面 (tail) 文字的功能。 不过，要注意的是， head 与 tail 都是以‘行’为单位来进行资料撷取的喔！

  • head (取出前面几行)
[root@www ~]# head [-n number] 档案
选项与参数：
-n  ：后面接数字，代表显示几行的意思

[root@www ~]# head /etc/man.config
# 预设的情况中，显示前面十行！若要显示前 20 行，就得要这样：
[root@www ~]# head -n 20 /etc/man.config

范例：如果后面100行的资料都不列印，只列印/etc/man.config的前面几行，该如何是好？
[root@www ~]# head -n -100 /etc/man.config

head 的英文意思就是‘头’啦，那么这个东西的用法自然就是显示出一个档案的前几行啰！ 没错！就是这样！若没有加上 -n 这个选项时，预设只显示十行，若只要一行呢？那就加入‘ head -n 1 filename ’即可！

另外那个 -n 选项后面的参数较有趣，如果接的是负数，例如上面范例的-n -100时，代表列前的所有行数， 但不包括后面100行。举例来说，/etc/man.config共有141行，则上述的指令‘head -n -100 /etc/man.config’ 就会列出前面41行，后面100行不会列印出来了。这样说，比较容易懂了吧？ ^_^

  • tail (取出后面几行)
[root@www ~]# tail [-n number] 档案

选项与参数：
-n  ：后面接数字，代表显示几行的意思
-f  ：表示持续侦测后面所接的档名，要等到按下[ctrl]-c才会结束tail的侦测

[root@www ~]# tail /etc/man.config
# 预设的情况中，显示最后的十行！若要显示最后的 20 行，就得要这样：
[root@www ~]# tail -n 20 /etc/man.config

范例一：如果不知道/etc/man.config有几行，却只想列出100行以后的资料时？
[root@www ~]# tail -n +100 /etc/man.config

范例二：持续侦测/var/log/messages的内容
[root@www ~]# tail -f /var/log/messages
  <==要等到输入[crtl]-c之后才会离开tail这个指令的侦测！

有 head 自然就有 tail ( 尾巴 ) 啰！没错！这个 tail 的用法跟 head 的用法差不多类似，只是显示的是后面几行就是了！预设也是显示十行，若要显示非十行，就加 -n number 的选项即可。

范例一的内容就有趣啦！其实与head -n -xx有异曲同工之妙。当下达‘tail -n +100 /etc/man.config’ 代表该档案从100行以后都会被列出来，同样的，在man.config共有141行，因此第100~141行就会被列出来啦！ 前面的99行都不会被显示出来喔！

至于范例二中，由于/var/log/messages随时会有资料写入，你想要让该档案有资料写入时就立刻显示到荧幕上， 就利用 -f 这个选项，他可以一直侦测/var/log/messages这个档案，新加入的资料都会被显示到荧幕上。 直到你按下[crtl]-c才会离开tail的侦测喔！

例题：
假如我想要显示 /etc/man.config 的第 11 到第 20 行呢？
答：
这个应该不算难，想一想，在第 11 到第 20 行，那么我取前 20 行，再取后十行，所以结果就是：‘ head -n 20 /etc/man.config | tail -n 10 ’，这样就可以得到第 11 到第 20 行之间的内容了！ 但是里面涉及到管线命令，需要在第三篇的时候才讲的到！

小标题的图示 非纯文字档： od

我们上面提到的，都是在查阅纯文字档的内容。 那么万一我们想要查阅非文字档，举例来说，例如 /usr/bin/passwd 这个执行档的内容时， 又该如何去读出资讯呢？事实上，由于执行档通常是 binary file ，使用上头提到的指令来读取他的内容时， 确实会产生类似乱码的资料啊！那怎么办？没关系，我们可以利用 od 这个指令来读取喔！

[root@www ~]# od [-t TYPE] 档案
选项或参数：
-t  ：后面可以接各种‘类型 (TYPE)’的输出，例如：
      a       ：利用预设的字元来输出；
      c       ：使用 ASCII 字元来输出
      d[size] ：利用十进位(decimal)来输出资料，每个整数占用 size bytes ；
      f[size] ：利用浮点数值(floating)来输出资料，每个数占用 size bytes ；
      o[size] ：利用八进位(octal)来输出资料，每个整数占用 size bytes ；
      x[size] ：利用十六进位(hexadecimal)来输出资料，每个整数占用 size bytes ；

范例一：请将/usr/bin/passwd的内容使用ASCII方式来展现！
[root@www ~]# od -t c /usr/bin/passwd
0000000 177   E   L   F 001 001 001  \0  \0  \0  \0  \0  \0  \0  \0  \0
0000020 002  \0 003  \0 001  \0  \0  \0 260 225 004  \b   4  \0  \0  \0
0000040 020   E  \0  \0  \0  \0  \0  \0   4  \0      \0  \a  \0   (  \0
0000060 035  \0 034  \0 006  \0  \0  \0   4  \0  \0  \0   4 200 004  \b
0000100   4 200 004  \b 340  \0  \0  \0 340  \0  \0  \0 005  \0  \0  \0
.....(后面省略)....
# 最左边第一栏是以 8 进位来表示bytes数。以上面范例来说，第二栏0000020代表开头是
# 第 16 个 byes (2x8) 的内容之意。

范例二：请将/etc/issue这个档案的内容以8进位列出储存值与ASCII的对照表
[root@www ~]# od -t oCc /etc/issue
0000000 103 145 156 164 117 123 040 162 145 154 145 141 163 145 040 065
          C   e   n   t   O   S       r   e   l   e   a   s   e       5
0000020 056 062 040 050 106 151 156 141 154 051 012 113 145 162 156 145
          .   2       (   F   i   n   a   l   )  \n   K   e   r   n   e
0000040 154 040 134 162 040 157 156 040 141 156 040 134 155 012 012
          l       \   r       o   n       a   n       \   m  \n  \n
0000057
# 如上所示，可以发现每个字元可以对应到的数值为何！
# 例如e对应的记录数值为145，转成十进位：1x8^2+4x8+5=101。

利用这个指令，可以将 data file 或者是 binary file 的内容资料给他读出来喔！ 虽然读出的来数值预设是使用非文字档，亦即是 16 进位的数值来显示的， 不过，我们还是可以透过 -t c 的选项与参数来将资料内的字元以 ASCII 类型的字元来显示， 虽然对于一般使用者来说，这个指令的用处可能不大，但是对于工程师来说， 这个指令可以将 binary file 的内容作一个大致的输出，他们可以看得出东西的啦～ ^_^

如果对纯文字档使用这个指令，你甚至可以发现到 ASCII 与字元的对照表！非常有趣！ 例如上述的范例二，你可以发现到每个英文字 e 对照到的数字都是 145，转成十进位你就能够发现那是 101 啰！ 如果你有任何程式语言的书，拿出来对照一下 ASCII 的对照表，就能够发现真是正确啊！呵呵！

小标题的图示 修改档案时间或建置新档： touch

我们在 ls 这个指令的介绍时，有稍微提到每个档案在linux底下都会记录许多的时间参数， 其实是有三个主要的变动时间，那么三个时间的意义是什么呢？

  • modification time (mtime)：
    当该档案的‘内容资料’变更时，就会更新这个时间！内容资料指的是档案的内容，而不是档案的属性或权限喔！

  • status time (ctime)：
    当该档案的‘状态 (status)’改变时，就会更新这个时间，举例来说，像是权限与属性被更改了，都会更新这个时间啊。

  • access time (atime)：
    当‘该档案的内容被取用’时，就会更新这个读取时间 (access)。举例来说，我们使用 cat 去读取 /etc/man.config ， 就会更新该档案的 atime 了。

这是个挺有趣的现象，举例来说，我们来看一看你自己的 /etc/man.config 这个档案的时间吧！

[root@www ~]# ls -l /etc/man.config
-rw-r--r-- 1 root root 4617 Jan  6  2007 /etc/man.config
[root@www ~]# ls -l --time=atime /etc/man.config
-rw-r--r-- 1 root root 4617 Sep 25 17:54 /etc/man.config
[root@www ~]# ls -l --time=ctime /etc/man.config
-rw-r--r-- 1 root root 4617 Sep  4 18:03 /etc/man.config

看到了吗？在预设的情况下，ls 显示出来的是该档案的 mtime ，也就是这个档案的内容上次被更动的时间。 至于鸟哥的系统是在 9 月 4 号的时候安装的，因此，这个档案被产生导致状态被更动的时间就回溯到那个时间点了(ctime)！ 而还记得刚刚我们使用的范例当中，有使用到man.config这个档案啊，所以啊，他的 atime 就会变成刚刚使用的时间了！

档案的时间是很重要的，因为，如果档案的时间误判的话，可能会造成某些程式无法顺利的运作。 OK！那么万一我发现了一个档案来自未来，该如何让该档案的时间变成‘现在’的时刻呢？ 很简单啊！就用‘touch’这个指令即可！

Tips:
嘿嘿！不要怀疑系统时间会‘来自未来’喔！很多时候会有这个问题的！举例来说在安装过后系统时间可能会被改变！ 因为台湾时区在国际标准时间‘格林威治时间, GMT’的右边，所以会比较早看到阳光，也就是说，台湾时间比GMT时间快了八小时！ 如果安装行为不当，我们的系统可能会有八小时快转，你的档案就有可能来自八小时候了。

至于某些情况下，由于BIOS的设定错误，导致系统时间跑到未来时间，并且你又建立了某些档案。 等你将时间改回正确的时间时，该档案不就变成来自未来了？^_^ 		鸟哥的图示
[root@www ~]# touch [-acdmt] 档案

选项与参数：
-a  ：仅修订 access time；
-c  ：仅修改档案的时间，若该档案不存在则不建立新档案；
-d  ：后面可以接欲修订的日期而不用目前的日期，也可以使用 --date="日期或时间"
-m  ：仅修改 mtime ；
-t  ：后面可以接欲修订的时间而不用目前的时间，格式为[YYMMDDhhmm]

范例一：新建一个空的档案并观察时间
[root@www ~]# cd /tmp
[root@www tmp]# touch testtouch
[root@www tmp]# ls -l testtouch
-rw-r--r-- 1 root root 0 Sep 25 21:09 testtouch

# 注意到，这个档案的大小是 0 呢！在预设的状态下，如果 touch 后面有接档案，
# 则该档案的三个时间 (atime/ctime/mtime) 都会更新为目前的时间。若该档案不存在，
# 则会主动的建立一个新的空的档案喔！例如上面这个例子！

范例二：将 ~/.bashrc 复制成为 bashrc，假设复制完全的属性，检查其日期
[root@www tmp]# cp -a ~/.bashrc bashrc
[root@www tmp]# ll bashrc; ll --time=atime bashrc; ll --time=ctime bashrc
-rw-r--r-- 1 root root 176 Jan  6  2007 bashrc  <==这是 mtime
-rw-r--r-- 1 root root 176 Sep 25 21:11 bashrc  <==这是 atime

-rw-r--r-- 1 root root 176 Sep 25 21:12 bashrc  <==这是 ctime

在上面这个案例当中我们使用了‘ll’这个指令(两个英文L的小写)，这个指令其实就是‘ls -l’的意思， ll本身不存在，是被‘做出来’的一个命令别名。相关的命令别名我们会在bash章节当中详谈的，这里先知道ll="ls -l"即可。 至于分号‘ ; ’则代表连续指令的下达啦！你可以在一行指令当中写入多重指令， 这些指令可以‘依序’执行。由上面的指令我们会知道ll那一行有三个指令被下达在同一行中。

至于执行的结果当中，我们可以发现资料的内容与属性是被复制过来的，因此档案内容时间(mtime)与原本档案相同。 但是由于这个档案是刚刚被建立的，因此状态(ctime)与读取时间就便呈现在的时间啦！ 那如果你想要变更这个档案的时间呢？可以这样做：

范例三：修改案例二的 bashrc 档案，将日期调整为两天前

[root@www tmp]# touch -d "2 days ago" bashrc
[root@www tmp]# ll bashrc; ll --time=atime bashrc; ll --time=ctime bashrc
-rw-r--r-- 1 root root 176 Sep 23 21:23 bashrc
-rw-r--r-- 1 root root 176 Sep 23 21:23 bashrc
-rw-r--r-- 1 root root 176 Sep 25 21:23 bashrc
# 跟上个范例比较看看，本来是 25 日的变成了 23 日了 (atime/mtime)～
# 不过， ctime 并没有跟着改变喔！

范例四：将上个范例的 bashrc 日期改为 2007/09/15 2:02
[root@www tmp]# touch -t 0709150202 bashrc
[root@www tmp]# ll bashrc; ll --time=atime bashrc; ll --time=ctime bashrc

-rw-r--r-- 1 root root 176 Sep 15  2007 bashrc
-rw-r--r-- 1 root root 176 Sep 15  2007 bashrc
-rw-r--r-- 1 root root 176 Sep 25 21:25 bashrc
# 注意看看，日期在 atime 与 mtime 都改变了，但是 ctime 则是记录目前的时间！

透过 touch 这个指令，我们可以轻易的修订档案的日期与时间。并且也可以建立一个空的档案喔！ 不过，要注意的是，即使我们复制一个档案时，复制所有的属性，但也没有办法复制 ctime 这个属性的。 ctime 可以记录这个档案最近的状态 (status) 被改变的时间。无论如何，还是要告知大家， 我们平时看的档案属性中，比较重要的还是属于那个 mtime 啊！我们关心的常常是这个档案的‘内容’ 是什么时候被更动的说～了乎？

无论如何， touch 这个指令最常被使用的情况是：

  • 建立一个空的档案；
  • 将某个档案日期修订为目前 (mtime 与 atime)
大标题的图示 档案与目录的预设权限与隐藏权限

由第六章、Linux档案权限的内容我们可以知道一个档案有若干个属性， 包括读写执行(r, w, x)等基本权限，及是否为目录 (d) 与档案 (-) 或者是连结档 (l) 等等的属性！ 要修改属性的方法在前面也约略提过了(chgrp, chown, chmod) ，本小节会再加强补充一下！

除了基本r, w, x权限外，在Linux的Ext2/Ext3档案系统下，我们还可以设定其他的系统隐藏属性， 这部份可使用 chattr 来设定，而以 lsattr 来查看，最重要的属性就是可以设定其不可修改的特性！让连档案的拥有者都不能进行修改！ 这个属性可是相当重要的，尤其是在安全机制上面 (security)！

首先，先来复习一下上一章谈到的权限概念，将底下的例题看一看先：

例题：
你的系统有个一般身份使用者 dmtsai，他的群组属于 users，他的家目录在 /home/dmtsai， 你是root，你想将你的 ~/.bashrc 复制给他，可以怎么作？
答：
由上一章的权限概念我们可以知道 root 虽然可以将这个档案复制给 dmtsai，不过这个档案在 dmtsai 的家目录中却可能让 dmtsai 没有办法读写(因为该档案属于 root 的嘛！而 dmtsai 又不能使用 chown 之故)。 此外，我们又担心覆盖掉 dmtsai 自己的 .bashrc 设定档，因此，我们可以进行如下的动作喔：
复制档案： cp ~/.bashrc ~dmtsai/bashrc
修改属性： chown dmtsai:users ~dmtsai/bashrc

例题：
我想在 /tmp 底下建立一个目录，这个目录名称为 chapter7_1 ，并且这个目录拥有者为 dmtsai， 群组为 users ，此外，任何人都可以进入该目录浏览档案，不过除了 dmtsai 之外，其他人都不能修改该目录下的档案。
答：
因为除了 dmtsai 之外，其他人不能修改该目录下的档案，所以整个目录的权限应该是 drwxr-xr-x 才对！ 因此你应该这样做：
建立目录： mkdir /tmp/chapter7_1
修改属性： chown -R dmtsai:users /tmp/chapter7_1
修改权限： chmod -R 755 /tmp/chapter7_1

在上面这个例题当中，如果你知道 755 那个分数是怎么计算出来的，那么你应该对于权限有一定程度的概念了。 如果你不知道 755 怎么来的？那么...赶快回去前一章看看 chmod 那个指令的介绍部分啊！这部分很重要喔！你得要先清楚的了解到才行～否则就进行不下去啰～ 假设你对于权限都认识的差不多了，那么底下我们就要来谈一谈，‘新增一个档案或目录时，预设的权限是什么？’这个议题！

小标题的图示 档案预设权限：umask

OK！那么现在我们知道如何建立或者是改变一个目录或档案的属性了，不过， 你知道当你建立一个新的档案或目录时，他的预设权限会是什么吗？呵呵！那就与 umask 这个玩意儿有关了！那么 umask 是在搞什么呢？基本上， umask 就是指定 ‘目前使用者在建立档案或目录时候的权限预设值’， 那么如何得知或设定 umask 呢？他的指定条件以底下的方式来指定：

[root@www ~]# umask

0022             <==与一般权限有关的是后面三个数字！
[root@www ~]# umask -S
u=rwx,g=rx,o=rx

查阅的方式有两种，一种可以直接输入 umask ，就可以看到数字型态的权限设定分数， 一种则是加入 -S (Symbolic) 这个选项，就会以符号类型的方式来显示出权限了！ 奇怪的是，怎么 umask 会有四组数字啊？不是只有三组吗？是没错啦。 第一组是特殊权限用的，我们先不要理他，所以先看后面三组即可。

在预设权限的属性上，目录与档案是不一样的。从第六章我们知道 x 权限对于目录是非常重要的！ 但是一般档案的建立则不应该有执行的权限，因为一般档案通常是用在于资料的记录嘛！当然不需要执行的权限了。 因此，预设的情况如下：

  • 若使用者建立为‘档案’则预设‘没有可执行( x )权限’，亦即只有 rw 这两个项目，也就是最大为 666 分，预设权限如下：
    -rw-rw-rw-

  • 若使用者建立为‘目录’，则由于 x 与是否可以进入此目录有关，因此预设为所有权限均开放，亦即为 777 分，预设权限如下：
    drwxrwxrwx

要注意的是，umask 的分数指的是‘该预设值需要减掉的权限！’因为 r、w、x 分别是 4、2、1 分，所以啰！也就是说，当要拿掉能写的权限，就是输入 2 分，而如果要拿掉能读的权限，也就是 4 分，那么要拿掉读与写的权限，也就是 6 分，而要拿掉执行与写入的权限，也就是 3 分，这样了解吗？请问你， 5 分是什么？呵呵！ 就是读与执行的权限啦！

如果以上面的例子来说明的话，因为 umask 为 022 ，所以 user 并没有被拿掉任何权限，不过 group 与 others 的权限被拿掉了 2 (也就是 w 这个权限)，那么当使用者：

  • 建立档案时：(-rw-rw-rw-) - (-----w--w-) ==> -rw-r--r--
  • 建立目录时：(drwxrwxrwx) - (d----w--w-) ==> drwxr-xr-x
不相信吗？我们就来测试看看吧！
[root@www ~]# umask
0022
[root@www ~]# touch test1
[root@www ~]# mkdir test2
[root@www ~]# ll

-rw-r--r-- 1 root root     0 Sep 27 00:25 test1
drwxr-xr-x 2 root root  4096 Sep 27 00:25 test2

呵呵！瞧见了吧！确定新建档案的权限是没有错的。

  • umask的利用与重要性：专题制作

想像一个状况，如果你跟你的同学在同一部主机里面工作时，因为你们两个正在进行同一个专题， 老师也帮你们两个的帐号建立好了相同群组的状态，并且将 /home/class/ 目录做为你们两个人的专题目录。 想像一下，有没有可能你所制作的档案你的同学无法编辑？果真如此的话，那就伤脑筋了！

这个问题很常发生啊！举上面的案例来看就好了，你看一下 test1 的权限是几分？ 644 呢！意思是‘如果 umask 订定为 022 ，那新建的资料只有使用者自己具有 w 的权限， 同群组的人只有 r 这个可读的权限而已，并无法修改喔！’这样要怎么共同制作专题啊！您说是吧！

所以，当我们需要新建档案给同群组的使用者共同编辑时，那么 umask 的群组就不能拿掉 2 这个 w 的权限！ 所以啰， umask 就得要是 002 之类的才可以！这样新建的档案才能够是 -rw-rw-r-- 的权限模样喔！ 那么如何设定 umask 呢？简单的很，直接在 umask 后面输入 002 就好了！

[root@www ~]# umask 002
[root@www ~]# touch test3

[root@www ~]# mkdir test4
[root@www ~]# ll
-rw-rw-r-- 1 root root     0 Sep 27 00:36 test3
drwxrwxr-x 2 root root  4096 Sep 27 00:36 test4

所以说，这个 umask 对于新建档案与目录的预设权限是很有关系的！这个概念可以用在任何伺服器上面， 尤其是未来在你架设档案伺服器 (file server) ，举例来说， SAMBA Server 或者是 FTP server 时， 都是很重要的观念！这牵涉到你的使用者是否能够将档案进一步利用的问题喔！不要等闲视之！

例题：
假设你的 umask 为 003 ，请问该 umask 情况下，建立的档案与目录权限为？
答：
umask 为 003 ，所以拿掉的权限为 --------wx，因此：
档案： (-rw-rw-rw-) - (--------wx) = -rw-rw-r--
目录： (drwxrwxrwx) - (--------wx) = drwxrwxr--

Tips:
关于 umask 与权限的计算方式中，教科书喜欢使用二进位的方式来进行 AND 与 NOT 的计算， 不过，鸟哥还是比较喜欢使用符号方式来计算～联想上面比较容易一点～

但是，有的书籍或者是 BBS 上面的朋友，喜欢使用档案预设属性 666 与目录预设属性 777 来与 umask 进行相减的计算～这是不好的喔！以上面例题来看， 如果使用预设属性相加减，则档案变成：666-003=663，亦即是 -rw-rw--wx ，这可是完全不对的喔！ 想想看，原本档案就已经去除 x 的预设属性了，怎么可能突然间冒出来了？ 所以，这个地方得要特别小心喔！ 		鸟哥的图示

在预设的情况中， root 的 umask 会拿掉比较多的属性，root 的 umask 预设是 022 ， 这是基于安全的考量啦～至于一般身份使用者，通常他们的 umask 为 002 ，亦即保留同群组的写入权力！ 其实，关于预设 umask 的设定可以参考 /etc/bashrc 这个档案的内容，不过，不建议修改该档案， 你可以参考第十一章 bash shell 提到的环境参数设定档 (~/.bashrc) 的说明！

小标题的图示 档案隐藏属性：

什么？档案还有隐藏属性？光是那九个权限就快要疯掉了，竟然还有隐藏属性，真是要命～ 但是没办法，就是有档案的隐藏属性存在啊！不过，这些隐藏的属性确实对于系统有很大的帮助的～ 尤其是在系统安全 (Security) 上面，重要的紧呢！不过要先强调的是，底下的chattr指令只能在Ext2/Ext3的档案系统上面生效， 其他的档案系统可能就无法支援这个指令了。底下我们就来谈一谈如何设定与检查这些隐藏的属性吧！

  • chattr (设定档案隐藏属性)
[root@www ~]# chattr [+-=][ASacdistu] 档案或目录名称
选项与参数：
+   ：增加某一个特殊参数，其他原本存在参数则不动。
-   ：移除某一个特殊参数，其他原本存在参数则不动。
=   ：设定一定，且仅有后面接的参数

A  ：当设定了 A 这个属性时，若你有存取此档案(或目录)时，他的存取时间 atime
     将不会被修改，可避免I/O较慢的机器过度的存取磁碟。这对速度较慢的电脑有帮助
S  ：一般档案是非同步写入磁碟的(原理请参考第五章sync的说明)，如果加上 S 这个
     属性时，当你进行任何档案的修改，该更动会‘同步’写入磁碟中。
a  ：当设定 a 之后，这个档案将只能增加资料，而不能删除也不能修改资料，只有root
     才能设定这个属性。
c  ：这个属性设定之后，将会自动的将此档案‘压缩’，在读取的时候将会自动解压缩，
     但是在储存的时候，将会先进行压缩后再储存(看来对于大档案似乎蛮有用的！)
d  ：当 dump 程序被执行的时候，设定 d 属性将可使该档案(或目录)不会被 dump 备份
i  ：这个 i 可就很厉害了！他可以让一个档案‘不能被删除、改名、设定连结也无法
     写入或新增资料！’对于系统安全性有相当大的助益！只有 root 能设定此属性
s  ：当档案设定了 s 属性时，如果这个档案被删除，他将会被完全的移除出这个硬碟
     空间，所以如果误删了，完全无法救回来了喔！
u  ：与 s 相反的，当使用 u 来设定档案时，如果该档案被删除了，则资料内容其实还
     存在磁碟中，可以使用来救援该档案喔！
注意：属性设定常见的是 a 与 i 的设定值，而且很多设定值必须要身为 root 才能设定

范例：请尝试到/tmp底下建立档案，并加入 i 的参数，尝试删除看看。

[root@www ~]# cd /tmp
[root@www tmp]# touch attrtest     <==建立一个空档案
[root@www tmp]# chattr +i attrtest <==给予 i 的属性
[root@www tmp]# rm attrtest        <==尝试删除看看

rm: remove write-protected regular empty file `attrtest'? y
rm: cannot remove `attrtest': Operation not permitted  <==操作不许可
# 看到了吗？呼呼！连 root 也没有办法将这个档案删除呢！赶紧解除设定！

范例：请将该档案的 i 属性取消！
[root@www tmp]# chattr -i attrtest

这个指令是很重要的，尤其是在系统的资料安全上面！由于这些属性是隐藏的性质，所以需要以 lsattr 才能看到该属性呦！其中，个人认为最重要的当属 +i 与 +a 这个属性了。+i 可以让一个档案无法被更动，对于需要强烈的系统安全的人来说， 真是相当的重要的！里头还有相当多的属性是需要 root 才能设定的呢！

此外，如果是 log file 这种的登录档，就更需要 +a 这个可以增加，但是不能修改旧有的资料与删除的参数了！怎样？很棒吧！ 未来提到登录档 (十九章) 的认知时，我们再来聊一聊如何设定他吧！

  • lsattr (显示档案隐藏属性)
[root@www ~]# lsattr [-adR] 档案或目录

选项与参数：
-a ：将隐藏档的属性也秀出来；
-d ：如果接的是目录，仅列出目录本身的属性而非目录内的档名；
-R ：连同子目录的资料也一并列出来！

[root@www tmp]# chattr +aij attrtest
[root@www tmp]# lsattr attrtest
----ia---j--- attrtest

使用 chattr 设定后，可以利用 lsattr 来查阅隐藏的属性。不过， 这两个指令在使用上必须要特别小心，否则会造成很大的困扰。例如：某天你心情好，突然将 /etc/shadow 这个重要的密码记录档案给他设定成为具有 i 的属性，那么过了若干天之后， 你突然要新增使用者，却一直无法新增！别怀疑，赶快去将 i 的属性拿掉吧！

小标题的图示 档案特殊权限： SUID, SGID, SBIT

我们前面一直提到关于档案的重要权限，那就是 rwx 这三个读、写、执行的权限。 但是，眼尖的朋友们在第六章的目录树章节中， 一定注意到了一件事，那就是，怎么我们的 /tmp 权限怪怪的？ 还有，那个 /usr/bin/passwd 也怪怪的？怎么回事啊？看看先：

[root@www ~]# ls -ld /tmp ; ls -l /usr/bin/passwd
drwxrwxrwt 7 root root 4096 Sep 27 18:23 /tmp
-rwsr-xr-x 1 root root 22984 Jan  7  2007 /usr/bin/passwd

不是应该只有 rwx 吗？还有其他的特殊权限( s 跟 t )啊？啊.....头又开始昏了～ @_@ 因为 s 与 t 这两个权限的意义与系统的帐号 (第十四章)及系统的程序(process, 第十七章)较为相关， 所以等到后面的章节谈完后你才会比较有概念！底下的说明先看看就好，如果看不懂也没有关系， 先知道s放在哪里称为SUID/SGID以及如何设定即可，等系统程序章节读完后，再回来看看喔！

  • Set UID

当 s 这个标志出现在档案拥有者的 x 权限上时，例如刚刚提到的 /usr/bin/passwd 这个档案的权限状态：‘-rwsr-xr-x’，此时就被称为 Set UID，简称为 SUID 的特殊权限。 那么SUID的权限对于一个档案的特殊功能是什么呢？基本上SUID有这样的限制与功能：

  • SUID 权限仅对二进位程式(binary program)有效；
  • 执行者对于该程式需要具有 x 的可执行权限；
  • 本权限仅在执行该程式的过程中有效 (run-time)；
  • 执行者将具有该程式拥有者 (owner) 的权限。

讲这么硬的东西你可能对于 SUID 还是没有概念，没关系，我们举个例子来说明好了。 我们的 Linux 系统中，所有帐号的密码都记录在 /etc/shadow 这个档案里面，这个档案的权限为：‘-r-------- 1 root root’，意思是这个档案仅有root可读且仅有root可以强制写入而已。 既然这个档案仅有 root 可以修改，那么鸟哥的 vbird 这个一般帐号使用者能否自行修改自己的密码呢？ 你可以使用你自己的帐号输入‘passwd’这个指令来看看，嘿嘿！一般使用者当然可以修改自己的密码了！

唔！有没有冲突啊！明明 /etc/shadow 就不能让 vbird 这个一般帐户去存取的，为什么 vbird 还能够修改这个档案内的密码呢？ 这就是 SUID 的功能啦！藉由上述的功能说明，我们可以知道

  1. vbird 对于 /usr/bin/passwd 这个程式来说是具有 x 权限的，表示 vbird 能执行 passwd；
  2. passwd 的拥有者是 root 这个帐号；
  3. vbird 执行 passwd 的过程中，会‘暂时’获得 root 的权限；
  4. /etc/shadow 就可以被 vbird 所执行的 passwd 所修改。

但如果 vbird 使用 cat 去读取 /etc/shadow 时，他能够读取吗？因为 cat 不具有 SUID 的权限，所以 vbird 执行 ‘cat /etc/shadow’ 时，是不能读取 /etc/shadow 的。我们用一张示意图来说明如下：

SUID程式执行的过程示意图
图4.4.1、SUID程式执行的过程示意图

另外，SUID 仅可用在binary program 上， 不能够用在 shell script 上面！这是因为 shell script 只是将很多的 binary 执行档叫进来执行而已！所以 SUID 的权限部分，还是得要看 shell script 呼叫进来的程式的设定， 而不是 shell script 本身。当然，SUID 对于目录也是无效的～这点要特别留意。

  • Set GID

当 s 标志在档案拥有者的 x 项目为 SUID，那 s 在群组的 x 时则称为 Set GID, SGID 啰！是这样没错！^_^。 举例来说，你可以用底下的指令来观察到具有 SGID 权限的档案喔：

[root@www ~]# ls -l /usr/bin/locate
-rwx--s--x 1 root slocate 23856 Mar 15  2007 /usr/bin/locate

与 SUID 不同的是，SGID 可以针对档案或目录来设定！如果是对档案来说， SGID 有如下的功能：

  • SGID 对二进位程式有用；
  • 程式执行者对于该程式来说，需具备 x 的权限；
  • 执行者在执行的过程中将会获得该程式群组的支援！

举例来说，上面的 /usr/bin/locate 这个程式可以去搜寻 /var/lib/mlocate/mlocate.db 这个档案的内容 (详细说明会在下节讲述)， mlocate.db 的权限如下：

[root@www ~]# ll /usr/bin/locate /var/lib/mlocate/mlocate.db

-rwx--s--x 1 root slocate   23856 Mar 15  2007 /usr/bin/locate
-rw-r----- 1 root slocate 3175776 Sep 28 04:02 /var/lib/mlocate/mlocate.db

与 SUID 非常的类似，若我使用 vbird 这个帐号去执行 locate 时，那 vbird 将会取得 slocate 群组的支援， 因此就能够去读取 mlocate.db 啦！非常有趣吧！

除了 binary program 之外，事实上 SGID 也能够用在目录上，这也是非常常见的一种用途！ 当一个目录设定了 SGID 的权限后，他将具有如下的功能：

  • 使用者若对于此目录具有 r 与 x 的权限时，该使用者能够进入此目录；
  • 使用者在此目录下的有效群组(effective group)将会变成该目录的群组；
  • 用途：若使用者在此目录下具有 w 的权限(可以新建档案)，则使用者所建立的新档案，该新档案的群组与此目录的群组相同。

SGID 对于专案开发来说是非常重要的！因为这涉及群组权限的问题，您可以参考一下本章后续情境模拟的案例，应该就能够对于 SGID 有一些了解的！^_^

  • Sticky Bit

这个 Sticky Bit, SBIT 目前只针对目录有效，对于档案已经没有效果了。 SBIT 对于目录的作用是：

  • 当使用者对于此目录具有 w, x 权限，亦即具有写入的权限时；
  • 当使用者在该目录下建立档案或目录时，仅有自己与 root 才有权力删除该档案

换句话说：当甲这个使用者于 A 目录是具有群组或其他人的身份，并且拥有该目录 w 的权限， 这表示‘甲使用者对该目录内任何人建立的目录或档案均可进行 "删除/更名/搬移" 等动作。’ 不过，如果将 A 目录加上了 SBIT 的权限项目时， 则甲只能够针对自己建立的档案或目录进行删除/更名/移动等动作，而无法删除他人的档案。

举例来说，我们的 /tmp 本身的权限是‘drwxrwxrwt’， 在这样的权限内容下，任何人都可以在 /tmp 内新增、修改档案，但仅有该档案/目录建立者与 root 能够删除自己的目录或档案。这个特性也是挺重要的啊！你可以这样做个简单的测试：

  1. 以 root 登入系统，并且进入 /tmp 当中；
  2. touch test，并且更改 test 权限成为 777 ；
  3. 以一般使用者登入，并进入 /tmp；
  4. 尝试删除 test 这个档案！

由于 SUID/SGID/SBIT 牵涉到程序的概念，因此再次强调，这部份的资料在您读完第十七章关于程序方面的知识后，要再次的回来瞧瞧喔！ 目前，你先有个简单的基础概念就好了！文末的参考资料也建议阅读一番喔！

  • SUID/SGID/SBIT 权限设定

前面介绍过 SUID 与 SGID 的功能，那么如何设定档案使成为具有 SUID 与 SGID 的权限呢？ 这就需要第六章的数字更改权限的方法了！ 现在你应该已经知道数字型态更改权限的方式为‘三个数字’的组合， 那么如果在这三个数字之前再加上一个数字的话，最前面的那个数字就代表这几个权限了！

  • 4 为 SUID
  • 2 为 SGID
  • 1 为 SBIT

假设要将一个档案权限改为‘-rwsr-xr-x’时，由于 s 在使用者权限中，所以是 SUID ，因此， 在原先的 755 之前还要加上 4 ，也就是：‘ chmod 4755 filename ’来设定！此外，还有大 S 与大 T 的产生喔！参考底下的范例啦！

Tips:
注意：底下的范例只是练习而已，所以鸟哥使用同一个档案来设定，你必须了解 SUID 不是用在目录上，而 SBIT 不是用在档案上的喔！ 		鸟哥的图示
[root@www ~]# cd /tmp
[root@www tmp]# touch test                  <==建立一个测试用空档

[root@www tmp]# chmod 4755 test; ls -l test <==加入具有 SUID 的权限
-rwsr-xr-x 1 root root 0 Sep 29 03:06 test
[root@www tmp]# chmod 6755 test; ls -l test <==加入具有 SUID/SGID 的权限
-rwsr-sr-x 1 root root 0 Sep 29 03:06 test
[root@www tmp]# chmod 1755 test; ls -l test <==加入 SBIT 的功能！

-rwxr-xr-t 1 root root 0 Sep 29 03:06 test
[root@www tmp]# chmod 7666 test; ls -l test <==具有空的 SUID/SGID 权限
-rwSrwSrwT 1 root root 0 Sep 29 03:06 test

最后一个例子就要特别小心啦！怎么会出现大写的 S 与 T 呢？不都是小写的吗？ 因为 s 与 t 都是取代 x 这个权限的，但是你有没有发现阿，我们是下达 7666 喔！也就是说， user, group 以及 others 都没有 x 这个可执行的标志( 因为 666 嘛 )，所以，这个 S, T 代表的就是‘空的’啦！怎么说？ SUID 是表示‘该档案在执行的时候，具有档案拥有者的权限’，但是档案 拥有者都无法执行了，哪里来的权限给其他人使用？当然就是空的啦！ ^_^

而除了数字法之外，你也可以透过符号法来处理喔！其中 SUID 为 u+s ，而 SGID 为 g+s ，SBIT 则是 o+t 啰！来看看如下的范例：

# 设定权限成为 -rws--x--x 的模样：
[root@www tmp]# chmod u=rwxs,go=x test; ls -l test

-rws--x--x 1 root root 0 Aug 18 23:47 test

# 承上，加上 SGID 与 SBIT 在上述的档案权限中！
[root@www tmp]# chmod g+s,o+t test; ls -l test
-rws--s--t 1 root root 0 Aug 18 23:47 test
小标题的图示 观察档案类型：file

如果你想要知道某个档案的基本资料，例如是属于 ASCII 或者是 data 档案，或者是 binary ， 且其中有没有使用到动态函式库 (share library) 等等的资讯，就可以利用 file 这个指令来检阅喔！ 举例来说：

[root@www ~]# file ~/.bashrc
/root/.bashrc: ASCII text  <==告诉我们是 ASCII 的纯文字档啊！
[root@www ~]# file /usr/bin/passwd
/usr/bin/passwd: setuid ELF 32-bit LSB executable, Intel 80386, version 1
(SYSV), for GNU/Linux 2.6.9, dynamically linked (uses shared libs), for
GNU/Linux 2.6.9, stripped

# 执行档的资料可就多的不得了！包括这个档案的 suid 权限、相容于 Intel 386
# 等级的硬体平台、使用的是 Linux 核心 2.6.9 的动态函式库连结等等。
[root@www ~]# file /var/lib/mlocate/mlocate.db
/var/lib/mlocate/mlocate.db: data  <== 这是 data 档案！

透过这个指令，我们可以简单的先判断这个档案的格式为何喔！

大标题的图示 指令与档案的搜寻：

档案的搜寻可就厉害了！因为我们常常需要知道那个档案放在哪里，才能够对该档案进行一些修改或维护等动作。 有些时候某些软体设定档的档名是不变的，但是各 distribution 放置的目录则不同。 此时就得要利用一些搜寻指令将该设定档的完整档名捉出来，这样才能修改嘛！您说是吧！^_^

小标题的图示 指令档名的搜寻：

我们知道在终端机模式当中，连续输入两次[tab]按键就能够知道使用者有多少指令可以下达。 那你知不知道这些指令的完整档名放在哪里？举例来说，ls 这个常用的指令放在哪里呢？ 就透过 which 或 type 来找寻吧！

  • which (寻找‘执行档’)
[root@www ~]# which [-a] command
选项或参数：
-a ：将所有由 PATH 目录中可以找到的指令均列出，而不止第一个被找到的指令名称

范例一：分别用root与一般帐号搜寻 ifconfig 这个指令的完整档名
[root@www ~]# which ifconfig

/sbin/ifconfig            <==用 root 可以找到正确的执行档名喔！
[root@www ~]# su - vbird <==切换身份成为 vbird 去！
[vbird@www ~]$ which ifconfig
/usr/bin/which: no ifconfig in (/usr/kerberos/bin:/usr/local/bin:/bin:/usr/bin
:/home/vbird/bin)         <==见鬼了！竟然一般身份帐号找不到！
# 因为 which 是根据使用者所设定的 PATH 变数内的目录去搜寻可执行档的！所以，
# 不同的 PATH 设定内容所找到的指令当然不一样啦！因为 /sbin 不在 vbird 的
# PATH 中，找不到也是理所当然的啊！了乎？
[vbird@www ~]$ exit      <==记得将身份切换回原本的 root

范例二：用 which 去找出 which 的档名为何？
[root@www ~]# which which
alias which='alias | /usr/bin/which --tty-only --read-alias --show-dot '
        /usr/bin/which
# 竟然会有两个 which ，其中一个是 alias 这玩意儿呢！那是啥？
# 那就是所谓的‘命令别名’，意思是输入 which 会等于后面接的那串指令啦！
# 更多的资料我们会在 bash 章节中再来谈的！

范例三：请找出 cd 这个指令的完整档名
[root@www ~]# which cd
/usr/bin/which: no cd in (/usr/kerberos/sbin:/usr/kerberos/bin:/usr/local/sbin
:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin)
# 瞎密？怎么可能没有 cd ，我明明就能够用 root 执行 cd 的啊！

这个指令是根据‘PATH’这个环境变数所规范的路径，去搜寻‘执行档’的档名～ 所以，重点是找出‘执行档’而已！且 which 后面接的是‘完整档名’喔！若加上 -a 选项，则可以列出所有的可以找到的同名执行档，而非仅显示第一个而已！

最后一个范例最有趣，怎么 cd 这个常用的指令竟然找不到啊！为什么呢？这是因为 cd 是‘bash 内建的指令’啦！ 但是 which 预设是找 PATH 内所规范的目录，所以当然一定找不到的啊！那怎办？没关系！我们可以透过 type 这个指令喔！ 关于 type 的用法我们将在 第十一章的 bash 再来谈！

小标题的图示 档案档名的搜寻：

再来谈一谈怎么搜寻档案吧！在 Linux 底下也有相当优异的搜寻指令呦！通常 find 不很常用的！因为速度慢之外， 也很操硬碟！通常我们都是先使用 whereis 或者是 locate 来检查，如果真的找不到了，才以 find 来搜寻呦！ 为什么呢？因为 whereis 与 locate 是利用资料库来搜寻资料，所以相当的快速，而且并没有实际的搜寻硬碟， 比较省时间啦！

  • whereis (寻找特定档案)
[root@www ~]# whereis [-bmsu] 档案或目录名

选项与参数：
-b    :只找 binary 格式的档案
-m    :只找在说明档 manual 路径下的档案
-s    :只找 source 来源档案
-u    :搜寻不在上述三个项目当中的其他特殊档案

范例一：请用不同的身份找出 ifconfig 这个档名
[root@www ~]# whereis ifconfig
ifconfig: /sbin/ifconfig /usr/share/man/man8/ifconfig.8.gz
[root@www ~]# su - vbird        <==切换身份成为 vbird
[vbird@www ~]$ whereis ifconfig <==找到同样的结果喔！

ifconfig: /sbin/ifconfig /usr/share/man/man8/ifconfig.8.gz
[vbird@www ~]$ exit              <==回归身份成为 root 去！
# 注意看，明明 which 一般使用者找不到的 ifconfig 却可以让 whereis 找到！
# 这是因为系统真的有 ifconfig 这个‘档案’，但是使用者的 PATH 并没有加入 /sbin
# 所以，未来你找不到某些指令时，先用档案搜寻指令找找看再说！

范例二：只找出跟 passwd 有关的‘说明文件’档名(man page)
[root@www ~]# whereis -m passwd
passwd: /usr/share/man/man1/passwd.1.gz /usr/share/man/man5/passwd.5.gz

等一下我们会提到 find 这个搜寻指令， find 是很强大的搜寻指令，但时间花用的很大！ (因为 find 是直接搜寻硬碟，为如果你的硬碟比较老旧的话，嘿嘿！有的等！) 这个时候 whereis 就相当的好用了！另外， whereis 可以加入选项来找寻相关的资料， 例如如果你是要找可执行档( binary )那么加上 -b 就可以啦！ 如果不加任何选项的话，那么就将所有的资料列出来啰！

那么 whereis 到底是使用什么咚咚呢？为何搜寻的速度会比 find 快这么多？ 其实那也没有什么！这是因为 Linux 系统会将系统内的所有档案都记录在一个资料库档案里面， 而当使用 whereis 或者是底下要说的 locate 时，都会以此资料库档案的内容为准， 因此，有的时后你还会发现使用这两个执行档时，会找到已经被杀掉的档案！ 而且也找不到最新的刚刚建立的档案呢！这就是因为这两个指令是由资料库当中的结果去搜寻档案的所在啊！ 更多与这个资料库有关的说明，请参考下列的 locate 指令。

  • locate
[root@www ~]# locate [-ir] keyword
选项与参数：
-i  ：忽略大小写的差异；
-r  ：后面可接正规表示法的显示方式

范例一：找出系统中所有与 passwd 相关的档名
[root@www ~]# locate passwd
/etc/passwd
/etc/passwd-
/etc/news/passwd.nntp
/etc/pam.d/passwd
....(底下省略)....

这个 locate 的使用更简单，直接在后面输入‘档案的部分名称’后，就能够得到结果。 举上面的例子来说，我输入 locate passwd ，那么在完整档名 (包含路径名称) 当中，只要有 passwd 在其中， 就会被显示出来的！这也是个很方便好用的指令，如果你忘记某个档案的完整档名时～～

但是，这个东西还是有使用上的限制呦！为什么呢？你会发现使用 locate 来寻找资料的时候特别的快， 这是因为 locate 寻找的资料是由‘已建立的资料库 /var/lib/mlocate/’ 里面的资料所搜寻到的，所以不用直接在去硬碟当中存取资料，呵呵！当然是很快速啰！

那么有什么限制呢？就是因为他是经由资料库来搜寻的，而资料库的建立预设是在每天执行一次 (每个 distribution 都不同，CentOS 5.x 是每天更新资料库一次！)，所以当你新建立起来的档案， 却还在资料库更新之前搜寻该档案，那么 locate 会告诉你‘找不到！’呵呵！因为必须要更新资料库呀！

那能否手动更新资料库哪？当然可以啊！更新 locate 资料库的方法非常简单，直接输入‘ updatedb ’就可以了！ updatedb 指令会去读取 /etc/updatedb.conf 这个设定档的设定，然后再去硬碟里面进行搜寻档名的动作， 最后就更新整个资料库档案啰！因为 updatedb 会去搜寻硬碟，所以当你执行 updatedb 时，可能会等待数分钟的时间喔！

  • updatedb：根据 /etc/updatedb.conf 的设定去搜寻系统硬碟内的档名，并更新 /var/lib/mlocate 内的资料库档案；
  • locate：依据 /var/lib/mlocate 内的资料库记载，找出使用者输入的关键字档名。

  • find
[root@www ~]# find [PATH] [option] [action]
选项与参数：
1. 与时间有关的选项：共有 -atime, -ctime 与 -mtime ，以 -mtime 说明
   -mtime  n ：n 为数字，意义为在 n 天之前的‘一天之内’被更动过内容的档案；
   -mtime +n ：列出在 n 天之前(不含 n 天本身)被更动过内容的档案档名；
   -mtime -n ：列出在 n 天之内(含 n 天本身)被更动过内容的档案档名。
   -newer file ：file 为一个存在的档案，列出比 file 还要新的档案档名

范例一：将过去系统上面 24 小时内有更动过内容 (mtime) 的档案列出
[root@www ~]# find / -mtime 0

# 那个 0 是重点！0 代表目前的时间，所以，从现在开始到 24 小时前，
# 有变动过内容的档案都会被列出来！那如果是三天前的 24 小时内？
# find / -mtime 3 有变动过的档案都被列出的意思！

范例二：寻找 /etc 底下的档案，如果档案日期比 /etc/passwd 新就列出
[root@www ~]# find /etc -newer /etc/passwd
# -newer 用在分辨两个档案之间的新旧关系是很有用的！

时间参数真是挺有意思的！我们现在知道 atime, ctime 与 mtime 的意义，如果你想要找出一天内被更动过的档案名称， 可以使用上述范例一的作法。但如果我想要找出‘4天内被更动过的档案档名’呢？那可以使用‘ find /var -mtime -4 ’。那如果是‘4天前的那一天’就用‘ find /var -mtime 4 ’。有没有加上‘+, -’差别很大喔！我们可以用简单的图示来说明一下：

find 相关的时间参数意义
图5.2.1、find 相关的时间参数意义

图中最右边为目前的时间，越往左边则代表越早之前的时间轴啦。由图5.2.1我们可以清楚的知道：

  • +4代表大于等于5天前的档名：ex> find /var -mtime +4
  • -4代表小于等于4天内的档案档名：ex> find /var -mtime -4
  • 4则是代表4-5那一天的档案档名：ex> find /var -mtime 4

非常有趣吧！你可以在 /var/ 目录下搜寻一下，感受一下输出档案的差异喔！再来看看其他 find 的用法吧！

选项与参数：
2. 与使用者或群组名称有关的参数：
   -uid n ：n 为数字，这个数字是使用者的帐号 ID，亦即 UID ，这个 UID 是记录在
            /etc/passwd 里面与帐号名称对应的数字。这方面我们会在第四篇介绍。
   -gid n ：n 为数字，这个数字是群组名称的 ID，亦即 GID，这个 GID 记录在
            /etc/group，相关的介绍我们会第四篇说明～
   -user name ：name 为使用者帐号名称喔！例如 dmtsai
   -group name：name 为群组名称喔，例如 users ；
   -nouser    ：寻找档案的拥有者不存在 /etc/passwd 的人！
   -nogroup   ：寻找档案的拥有群组不存在于 /etc/group 的档案！
                当你自行安装软体时，很可能该软体的属性当中并没有档案拥有者，
                这是可能的！在这个时候，就可以使用 -nouser 与 -nogroup 搜寻。

范例三：搜寻 /home 底下属于 vbird 的档案
[root@www ~]# find /home -user vbird
# 这个东西也很有用的～当我们要找出任何一个使用者在系统当中的所有档案时，
# 就可以利用这个指令将属于某个使用者的所有档案都找出来喔！

范例四：搜寻系统中不属于任何人的档案
[root@www ~]# find / -nouser
# 透过这个指令，可以轻易的就找出那些不太正常的档案。
# 如果有找到不属于系统任何人的档案时，不要太紧张，
# 那有时候是正常的～尤其是你曾经以原始码自行编译软体时。

如果你想要找出某个使用者在系统底下建立了啥咚咚，使用上述的选项与参数，就能够找出来啦！ 至于那个 -nouser 或 -nogroup 的选项功能中，除了你自行由网路上面下载档案时会发生之外， 如果你将系统里面某个帐号删除了，但是该帐号已经在系统内建立很多档案时，就可能会发生无主孤魂的档案存在！ 此时你就得使用这个 -nouser 来找出该类型的档案啰！

选项与参数：
3. 与档案权限及名称有关的参数：
   -name filename：搜寻档案名称为 filename 的档案；
   -size [+-]SIZE：搜寻比 SIZE 还要大(+)或小(-)的档案。这个 SIZE 的规格有：
                   c: 代表 byte， k: 代表 1024bytes。所以，要找比 50KB
                   还要大的档案，就是‘ -size +50k ’
   -type TYPE    ：搜寻档案的类型为 TYPE 的，类型主要有：一般正规档案 (f),
                   装置档案 (b, c), 目录 (d), 连结档 (l), socket (s),
                   及 FIFO (p) 等属性。
   -perm mode  ：搜寻档案权限‘刚好等于’ mode 的档案，这个 mode 为类似 chmod
                 的属性值，举例来说， -rwsr-xr-x 的属性为 4755 ！
   -perm -mode ：搜寻档案权限‘必须要全部囊括 mode 的权限’的档案，举例来说，
                 我们要搜寻 -rwxr--r-- ，亦即 0744 的档案，使用 -perm -0744，
                 当一个档案的权限为 -rwsr-xr-x ，亦即 4755 时，也会被列出来，
                 因为 -rwsr-xr-x 的属性已经囊括了 -rwxr--r-- 的属性了。
   -perm +mode ：搜寻档案权限‘包含任一 mode 的权限’的档案，举例来说，我们搜寻
                 -rwxr-xr-x ，亦即 -perm +755 时，但一个档案属性为 -rw-------
                 也会被列出来，因为他有 -rw.... 的属性存在！

范例五：找出档名为 passwd 这个档案
[root@www ~]# find / -name passwd
# 利用这个 -name 可以搜寻档名啊！

范例六：找出 /var 目录下，档案类型为 Socket 的档名有哪些？
[root@www ~]# find /var -type s
# 这个 -type 的属性也很有帮助喔！尤其是要找出那些怪异的档案，
# 例如 socket 与 FIFO 档案，可以用 find /var -type p 或 -type s 来找！

范例七：搜寻档案当中含有 SGID 或 SUID 或 SBIT 的属性
[root@www ~]# find / -perm +7000
# 所谓的 7000 就是 ---s--s--t ，那么只要含有 s 或 t 的就列出，
# 所以当然要使用 +7000 ，使用 -7000 表示要含有 ---s--s--t 的所有三个权限，
# 因此，就是 +7000 ～了乎？

上述范例中比较有趣的就属 -perm 这个选项啦！他的重点在找出特殊权限的档案啰！ 我们知道 SUID 与 SGID 都可以设定在二进位程式上，假设我想要找出来 /bin, /sbin 这两个目录下， 只要具有 SUID 或 SGID 就列出来该档案，你可以这样做：

[root@www ~]# find /bin /sbin -perm +6000

因为 SUID 是 4 分，SGID 2 分，总共为 6 分，因此可用 +6000 来处理这个权限！ 至于 find 后面可以接多个目录来进行搜寻！另外， find 本来就会搜寻次目录，这个特色也要特别注意喔！ 最后，我们再来看一下 find 还有什么特殊功能吧！

选项与参数：
4. 额外可进行的动作：
   -exec command ：command 为其他指令，-exec 后面可再接额外的指令来处理搜寻到
                   的结果。
   -print        ：将结果列印到荧幕上，这个动作是预设动作！

范例八：将上个范例找到的档案使用 ls -l 列出来～
[root@www ~]# find / -perm +7000 -exec ls -l {} \;
# 注意到，那个 -exec 后面的 ls -l 就是额外的指令，指令不支援命令别名，
# 所以仅能使用 ls -l 不可以使用 ll 喔！注意注意！

范例九：找出系统中，大于 1MB 的档案
[root@www ~]# find / -size +1000k

# 虽然在 man page 提到可以使用 M 与 G 分别代表 MB 与 GB，
# 不过，俺却试不出来这个功能～所以，目前应该是仅支援到 c 与 k 吧！

find 的特殊功能就是能够进行额外的动作(action)。我们将范例八的例子以图解来说明如下：

find 相关的额外动作
图5.2.2、find 相关的额外动作

该范例中特殊的地方有 {} 以及 \; 还有 -exec 这个关键字，这些东西的意义为：

  • {} 代表的是‘由 find 找到的内容’，如上图所示，find 的结果会被放置到 {} 位置中；
  • -exec 一直到 \; 是关键字，代表 find 额外动作的开始 (-exec) 到结束 (\;) ，在这中间的就是 find 指令内的额外动作。 在本例中就是‘ ls -l {} ’啰！
  • 因为‘ ; ’在 bash 环境下是有特殊意义的，因此利用反斜线来跳脱。

透过图 5.2.2 你应该就比较容易了解 -exec 到 \; 之间的意义了吧！

如果你要找的档案是具有特殊属性的，例如 SUID 、档案拥有者、档案大小等等， 那么利用 locate 是没有办法达成你的搜寻的！此时 find 就显的很重要啦！ 另外，find 还可以利用万用字元来找寻档名呢！举例来说，你想要找出 /etc 底下档名包含 httpd 的档案， 那么你就可以这样做：

[root@www ~]# find /etc -name '*httpd*'

不但可以指定搜寻的目录(连同次目录)，并且可以利用额外的选项与参数来找到最正确的档名！真是好好用！ 不过由于 find 在寻找资料的时后相当的操硬碟！所以没事情不要使用 find 啦！有更棒的指令可以取代呦！那就是上面提到的 whereis 与 locate 啰！

大标题的图示 极重要！权限与指令间的关系：

我们知道权限对于使用者帐号来说是非常重要的，因为他可以限制使用者能不能读取/建立/删除/修改档案或目录！ 在这一章我们介绍了很多档案系统的管理指令，第六章则介绍了很多档案权限的意义。在这个小节当中， 我们就将这两者结合起来，说明一下什么指令在什么样的权限下才能够运作吧！^_^

一、让使用者能进入某目录成为‘可工作目录’的基本权限为何：

  • 可使用的指令：例如 cd 等变换工作目录的指令；
  • 目录所需权限：使用者对这个目录至少需要具有 x 的权限
  • 额外需求：如果使用者想要在这个目录内利用 ls 查阅档名，则使用者对此目录还需要 r 的权限。

二、使用者在某个目录内读取一个档案的基本权限为何？

  • 可使用的指令：例如本章谈到的 cat, more, less等等
  • 目录所需权限：使用者对这个目录至少需要具有 x 权限；
  • 档案所需权限：使用者对档案至少需要具有 r 的权限才行！

三、让使用者可以修改一个档案的基本权限为何？

  • 可使用的指令：例如 nano 或未来要介绍的 vi 编辑器等；
  • 目录所需权限：使用者在该档案所在的目录至少要有 x 权限；
  • 档案所需权限：使用者对该档案至少要有 r, w 权限

四、让一个使用者可以建立一个档案的基本权限为何？

  • 目录所需权限：使用者在该目录要具有 w,x 的权限，重点在 w 啦！

五、让使用者进入某目录并执行该目录下的某个指令之基本权限为何？

  • 目录所需权限：使用者在该目录至少要有 x 的权限；
  • 档案所需权限：使用者在该档案至少需要有 x 的权限
例题：
让一个使用者 vbird 能够进行‘cp /dir1/file1 /dir2’的指令时，请说明 dir1, file1, dir2 的最小所需权限为何？
答：
执行 cp 时， vbird 要‘能够读取来源档，并且写入目标档！’所以应参考上述第二点与第四点的说明！ 因此各档案/目录的最小权限应该是：
  • dir1 ：至少需要有 x 权限；
  • file1：至少需要有 r 权限；
  • dir2 ：至少需要有 w, x 权限。

例题：
有一个档案全名为 /home/student/www/index.html ，各相关档案/目录的权限如下：
drwxr-xr-x 23 root    root    4096 Sep 22 12:09 /
drwxr-xr-x  6 root    root    4096 Sep 29 02:21 /home
drwx------  6 student student 4096 Sep 29 02:23 /home/student
drwxr-xr-x  6 student student 4096 Sep 29 02:24 /home/student/www
-rwxr--r--  6 student student  369 Sep 29 02:27 /home/student/www/index.html
请问 vbird 这个帐号(不属于student群组)能否读取 index.html 这个档案呢？
答：
虽然 www 与 index.html 是可以让 vbird 读取的权限，但是因为目录结构是由根目录一层一层读取的， 因此 vbird 可进入 /home 但是却不可进入 /home/student/ ，既然连进入 /home/student 都不许了， 当然就读不到 index.html 了！所以答案是‘vbird不会读取到 index.html 的内容’喔！

那要如何修改权限呢？其实只要将 /home/student 的权限修改为最小 711 ，或者直接给予 755 就可以啰！ 这可是很重要的概念喔！
大标题的图示 重点回顾
  • 绝对路径：‘一定由根目录 / 写起’；相对路径：‘不是由 / 写起’
  • 特殊目录有：., .., -, ~, ~account需要注意；
  • 与目录相关的指令有：cd, mkdir, rmdir, pwd 等重要指令；
  • rmdir 仅能删除空目录，要删除非空目录需使用‘ rm -r ’指令；
  • 使用者能使用的指令是依据 PATH 变数所规定的目录去搜寻的；
  • 不同的身份(root 与一般用户)系统预设的 PATH 并不相同。差异较大的地方在于 /sbin, /usr/sbin ；
  • ls 可以检视档案的属性，尤其 -d, -a, -l 等选项特别重要！
  • 档案的复制、删除、移动可以分别使用：cp, rm , mv等指令来操作；
  • 检查档案的内容(读档)可使用的指令包括有：cat, tac, nl, more, less, head, tail, od 等
  • cat -n 与 nl 均可显示行号，但预设的情况下，空白行会不会编号并不相同；
  • touch 的目的在修改档案的时间参数，但亦可用来建立空档案；
  • 一个档案记录的时间参数有三种，分别是 access time(atime), status time (ctime), modification time(mtime)，ls 预设显示的是 mtime。
  • 除了传统的rwx权限之外，在Ext2/Ext3档案系统中，还可以使用chattr与lsattr设定及观察隐藏属性。 常见的包括只能新增资料的 +a 与完全不能更动档案的 +i 属性。
  • 新建档案/目录时，新档案的预设权限使用 umask 来规范。预设目录完全权限为drwxrwxrwx， 档案则为-rw-rw-rw-。
  • 档案具有SUID的特殊权限时，代表当使用者执行此一binary程式时，在执行过程中使用者会暂时具有程式拥有者的权限
  • 目录具有SGID的特殊权限时，代表使用者在这个目录底下新建的档案之群组都会与该目录的群组名称相同。
  • 目录具有SBIT的特殊权限时，代表在该目录下使用者建立的档案只有自己与root能够删除！
  • 观察档案的类型可以使用 file 指令来观察；
  • 搜寻指令的完整档名可用 which 或 type ，这两个指令都是透过 PATH 变数来搜寻档名；
  • 搜寻档案的完整档名可以使用 whereis 或 locate 到资料库档案去搜寻，而不实际搜寻档案系统；
  • 利用 find 可以加入许多选项来直接查询档案系统，以获得自己想要知道的档名。
大标题的图示 本章习题：
( 要看答案请将滑鼠移动到‘答：’底下的空白处，按下左键圈选空白处即可察看 )
情境模拟题一：假设系统中有两个帐号，分别是 alex 与 arod ，这两个人除了自己群组之外还共同支援一个名为 project 的群组。假设这两个用户需要共同拥有 /srv/ahome/ 目录的开发权，且该目录不许其他人进入查阅。 请问该目录的权限设定应为何？请先以传统权限说明，再以 SGID 的功能解析。
  • 目标：了解到为何专案开发时，目录最好需要设定 SGID 的权限！
  • 前提：多个帐号支援同一群组，且共同拥有目录的使用权！
  • 需求：需要使用 root 的身份来进行 chmod, chgrp 等帮用户设定好他们的开发环境才行！ 这也是管理员的重要任务之一！
首先我们得要先制作出这两个帐号的相关资料，帐号/群组的管理在后续我们会介绍， 您这里先照着底下的指令来制作即可：
[root@www ~]# groupadd project        <==增加新的群组
[root@www ~]# useradd -G project alex <==建立 alex 帐号，且支援 project
[root@www ~]# useradd -G project arod <==建立 arod 帐号，且支援 project

[root@www ~]# id alex                 <==查阅 alex 帐号的属性
uid=501(alex) gid=502(alex) groups=502(alex),501(project) <==确实有支援！
[root@www ~]# id arod
uid=502(arod) gid=503(arod) groups=503(arod),501(project)
然后开始来解决我们所需要的环境吧！
  1. 首先建立所需要开发的专案目录：
    [root@www ~]# mkdir /srv/ahome
[root@www ~]# ll -d /srv/ahome
drwxr-xr-x 2 root root 4096 Sep 29 22:36 /srv/ahome
  2. 从上面的输出结果可发现 alex 与 arod 都不能在该目录内建立档案，因此需要进行权限与属性的修改。 由于其他人均不可进入此目录，因此该目录的群组应为project，权限应为770才合理。
    [root@www ~]# chgrp project /srv/ahome
[root@www ~]# chmod 770 /srv/ahome
[root@www ~]# ll -d /srv/ahome
drwxrwx--- 2 root project 4096 Sep 29 22:36 /srv/ahome

# 从上面的权限结果来看，由于 alex/arod 均支援 project，因此似乎没问题了！
  3. 实际分别以两个使用者来测试看看，情况会是如何？先用 alex 建立档案，然后用 arod 去处理看看。
    [root@www ~]# su - alex       <==先切换身份成为 alex 来处理
[alex@www ~]$ cd /srv/ahome   <==切换到群组的工作目录去

[alex@www ahome]$ touch abcd  <==建立一个空的档案出来！
[alex@www ahome]$ exit        <==离开 alex 的身份

[root@www ~]# su - arod
[arod@www ~]$ cd /srv/ahome

[arod@www ahome]$ ll abcd
-rw-rw-r-- 1 alex alex 0 Sep 29 22:46 abcd
# 仔细看一下上面的档案，由于群组是 alex ，arod并不支援！
# 因此对于 abcd 这个档案来说， arod 应该只是其他人，只有 r 的权限而已啊！
[arod@www ahome]$ exit
    由上面的结果我们可以知道，若单纯使用传统的 rwx 而已，则对刚刚 alex 建立的 abcd 这个档案来说， arod 可以删除他，但是却不能编辑他！这不是我们要的样子啊！赶紧来重新规划一下。

  4. 加入 SGID 的权限在里面，并进行测试看看：
    [root@www ~]# chmod 2770 /srv/ahome
[root@www ~]# ll -d /srv/ahome
drwxrws--- 2 root project 4096 Sep 29 22:46 /srv/ahome

测试：使用 alex 去建立一个档案，并且查阅档案权限看看：
[root@www ~]# su - alex

[alex@www ~]$ cd /srv/ahome
[alex@www ahome]$ touch 1234
[alex@www ahome]$ ll 1234
-rw-rw-r-- 1 alex project 0 Sep 29 22:53 1234
# 没错！这才是我们要的样子！现在 alex, arod 建立的新档案所属群组都是 project，
# 由于两人均属于此群组，加上 umask 都是 002，这样两人才可以互相修改对方的档案！
    所以最终的结果显示，此目录的权限最好是‘2770’，所属档案拥有者属于root即可，至于群组必须要为两人共同支援的project 这个群组才行！
简答题部分：
  • 什么是绝对路径与相对路径
    绝对路径的写法为由 / 开始写，至于相对路径则不由 / 开始写！此外，相对路径为相对于目前工作目录的路径！
  • 如何更改一个目录的名称？例如由 /home/test 变为 /home/test2
    mv /home/test /home/test2
  • PATH 这个环境变数的意义？
    这个是用来指定执行档执行的时候，指令搜寻的目录路径。
  • umask 有什么用处与优点？
    umask 可以拿掉一些权限，因此，适当的定义 umask 有助于系统的安全， 因为他可以用来建立预设的目录或档案的权限。
  • 当一个使用者的 umask 分别为 033 与 044 他所建立的档案与目录的权限为何？
    在 umask 为 033 时，则预设是拿掉 group 与 other 的 w(2)x(1) 权限，因此权限就成为‘档案 -rw-r--r-- ， 目录 drwxr--r-- ’而当 umask 044 时，则拿掉 r 的属性，因此就成为‘档案 -rw--w--w-，目录 drwx-wx-wx’
  • 什么是 SUID ？
    当一个指令具有 SUID 的功能时，则：
    • SUID 权限仅对二进位程式(binary program)有效；
    • 执行者对于该程式需要具有 x 的可执行权限；
    • 本权限仅在执行该程式的过程中有效 (run-time)；
    • 执行者将具有该程式拥有者 (owner) 的权限。
  • 当我要查询 /usr/bin/passwd 这个档案的一些属性时(1)传统权限；(2)档案类型与(3)档案的隐藏属性，可以使用什么指令来查询？
    ls -al
    file
    lsattr
  • 尝试用 find 找出目前 linux 系统中，所有具有 SUID 的档案有哪些？
    find / -perm +4000 -print
  • 找出 /etc 底下，档案大小介于 50K 到 60K 之间的档案，并且将权限完整的列出 (ls -l)：
    find /etc -size +50k -a -size -60k -exec ls -l {} \;
    注意到 -a ，那个 -a 是 and 的意思，为符合两者才算成功
  • 找出 /etc 底下，档案容量大于 50K 且档案所属人不是 root 的档名，且将权限完整的列出 (ls -l)；
    find /etc -size +50k -a ! -user root -exec ls -ld {} \;
    find /etc -size +50k -a ! -user root -type f -exec ls -l {} \;
    上面两式均可！注意到 ! ，那个 ! 代表的是反向选择，亦即‘不是后面的项目’之意！
  • 找出 /etc 底下，容量大于 1500K 以及容量等于 0 的档案：
    find /etc -size +1500k -o -size 0
    相对于 -a ，那个 -o 就是或 (or) 的意思啰！
大标题的图示 参考资料与延伸阅读
  • 小洲大大回答 SUID/SGID 的一篇讨论：
    http://phorum.vbird.org/viewtopic.php?t=20256
2002/06/26：第一次完成 2003/02/06：重新编排与加入 FAQ
2003/02/07：加入 basename 与 dirname 的说明
2004/03/15：将连结档的内容移动至下一章节：Linux 磁碟与硬体管理
2005/07/19：将旧的文章移动到 这里 了。
2005/07/20：呼呼！好不容易啊～在被台风尾扫到的七月份，终于写完这个咚咚～
2005/07/21：在 find 部分，多增加了范例九，以及关于利用档案大小 (size) 搜寻的功能。
2005/07/25：在 SUID/SGID/SBIT 部分，依据 netman 与 小州 兄的建议，修改了部分的叙述！
2006/04/09：在 rmdir 的范例内，少了一个 -p 的参数！
2006/06/15：经由讨论区网友 dm421 的通知，发现 chattr 的部分关于 d 写错了，已订正。
2006/08/22：增加 rm 的一些简单的说明！尤其是‘ rm ./-aaa- ’的删除方法！
2008/09/23：将针对FC4版写的资料移到此处
2008/09/29：加入权限与指令的关系一节，并新增情境模拟题目喔！大家帮忙除错一下！
2009/08/18：加入符号法的方式来处理 SUID/SGID/SBIT 啰！
2009/08/26：感谢网友告知习题部分，找出 /etc 底下容量大于 50k 的那题，应使用 -type f 或 ls -ld 来避免目录内重复显示！


鸟哥的 Linux 私房菜 -- 基础学习篇

为取得较佳浏览结果，请爱用 firefox 浏览本网页

第八章、Linux 磁碟与档案系统管理
最近更新日期：2009/08/30
系统管理员很重要的任务之一就是管理好自己的磁碟档案系统，每个分割槽不可太大也不能太小， 太大会造成磁碟容量的浪费，太小则会产生档案无法储存的困扰。此外，我们在前面几章谈到的档案权限与属性中， 这些权限与属性分别记录在档案系统的那个区块内？这就得要谈到 filesystem 中的 inode 与 block 了。 在本章我们的重点在于如何制作档案系统，包括分割、格式化与挂载等，是很重要的一个章节喔！

1. 认识 EXT2 档案系统
    1.1 硬碟组成与分割的复习
    1.2 档案系统特性： 索引式档案系统
    1.3 Linux 的 EXT2 档案系统(inode): data block, inode table, superblock, dumpe2fs
    1.4 与目录树的关系
    1.5 EXT2/EXT3 档案的存取与日志式档案系统的功能
    1.6 Linux 档案系统的运作
    1.7 挂载点的意义 (mount point)
    1.8 其他 Linux 支援的档案系统与 VFS
 2. 档案系统的简单操作
    2.1 磁碟与目录的容量： df, du
    2.2 实体连结与符号连结： ln
 3. 磁碟的分割、格式化、检验与挂载
    3.1 磁碟分割： fdisk, partprobe
    3.2 磁碟格式化： mkfs, mke2fs
    3.3 磁碟检验： fsck, badblocks
    3.4 磁碟挂载与卸载： mount, umount
    3.5 磁碟参数修订： mknod, e2label, tune2fs, hdparm
 4. 设定开机挂载：
    4.1 开机挂载 /etc/fstab 及 /etc/mtab
    4.2 特殊装置 loop 挂载(映象档不烧录就挂载使用)
 5. 记忆体置换空间(swap)之建置：
    5.1 使用实体分割槽建置swap
    5.2 使用档案建置swap
    5.3 swap使用上的限制
 6. 档案系统的特殊观察与操作
    6.1 boot sector 与 superblock 的关系
    6.2 磁碟空间之浪费问题
    6.3 利用 GNU 的 parted 进行分割行为
 7. 重点回顾
8. 本章习题
9. 参考资料与延伸阅读
10. 针对本文的建议：http://phorum.vbird.org/viewtopic.php?t=23881
大标题的图示 认识 EXT2 档案系统

Linux最传统的磁碟档案系统(filesystem)使用的是EXT2这个啦！所以要了解档案系统就得要由认识EXT2开始！ 而档案系统是建立在硬碟上面的，因此我们得了解硬碟的物理组成才行。磁碟物理组成的部分我们在第零章谈过了，至于磁碟分割则在第三章谈过了，所以底下只会很快的复习这两部份。 重点在于inode, block还有superblock等档案系统的基本部分喔！

小标题的图示 硬碟组成与分割的复习

由于各项磁碟的物理组成我们在第零章里面就介绍过， 同时第三章也谈过分割的概念了， 所以这个小节我们就拿之前的重点出来介绍就好了！详细的资讯请您回去那两章自行复习喔！^_^。 好了，首先说明一下磁碟的物理组成，整颗磁碟的组成主要有：

  • 圆形的磁碟盘(主要记录资料的部分)；
  • 机械手臂，与在机械手臂上的磁碟读取头(可读写磁碟盘上的资料)；
  • 主轴马达，可以转动磁碟盘，让机械手臂的读取头在磁碟盘上读写资料。

从上面我们知道资料储存与读取的重点在于磁碟盘，而磁碟盘上的物理组成则为(假设此磁碟为单碟片， 磁碟盘图示请参考第三章图2.2.1的示意)：

  • 磁区(Sector)为最小的物理储存单位，每个磁区为 512 bytes；
  • 将磁区组成一个圆，那就是磁柱(Cylinder)，磁柱是分割槽(partition)的最小单位；
  • 第一个磁区最重要，里面有：(1)主要开机区(Master boot record, MBR)及分割表(partition table)， 其中 MBR 占有 446 bytes，而 partition table 则占有 64 bytes。

各种介面的磁碟在Linux中的档案名称分别为：

  • /dev/sd[a-p][1-15]：为SCSI, SATA, USB, Flash随身碟等介面的磁碟档名；
  • /dev/hd[a-d][1-63]：为 IDE 介面的磁碟档名；

复习完物理组成后，来复习一下磁碟分割吧！所谓的磁碟分割指的是告诉作业系统‘我这颗磁碟在此分割槽可以存取的区域是由 A 磁柱到 B 磁柱之间的区块’， 如此一来作业系统就能够知道他可以在所指定的区块内进行档案资料的读/写/搜寻等动作了。 也就是说，磁碟分割意即指定分割槽的启始与结束磁柱就是了。

那么指定分割槽的磁柱范围是记录在哪里？就是第一个磁区的分割表中啦！但是因为分割表仅有64bytes而已， 因此最多只能记录四笔分割槽的记录，这四笔记录我们称为主要 (primary) 或延伸 (extended) 分割槽，其中延伸分割槽还可以再分割出逻辑分割槽 (logical) ， 而能被格式化的则仅有主要分割与逻辑分割而已。

最后，我们再将第三章关于分割的定义拿出来说明一下啰：

  • 主要分割与延伸分割最多可以有四笔(硬碟的限制)
  • 延伸分割最多只能有一个(作业系统的限制)
  • 逻辑分割是由延伸分割持续切割出来的分割槽；
  • 能够被格式化后，作为资料存取的分割槽为主要分割与逻辑分割。延伸分割无法格式化；
  • 逻辑分割的数量依作业系统而不同，在Linux系统中，IDE硬碟最多有59个逻辑分割(5号到63号)， SATA硬碟则有11个逻辑分割(5号到15号)。
小标题的图示 档案系统特性

我们都知道磁碟分割完毕后还需要进行格式化(format)，之后作业系统才能够使用这个分割槽。 为什么需要进行‘格式化’呢？这是因为每种作业系统所设定的档案属性/权限并不相同， 为了存放这些档案所需的资料，因此就需要将分割槽进行格式化，以成为作业系统能够利用的‘档案系统格式(filesystem)’。

由此我们也能够知道，每种作业系统能够使用的档案系统并不相同。 举例来说，windows 98 以前的微软作业系统主要利用的档案系统是 FAT (或 FAT16)，windows 2000 以后的版本有所谓的 NTFS 档案系统，至于 Linux 的正统档案系统则为 Ext2 (Linux second extended file system, ext2fs)这一个。此外，在预设的情况下，windows 作业系统是不会认识 Linux 的 Ext2 的。

传统的磁碟与档案系统之应用中，一个分割槽就是只能够被格式化成为一个档案系统，所以我们可以说一个 filesystem 就是一个 partition。但是由于新技术的利用，例如我们常听到的LVM与软体磁碟阵列(software raid)， 这些技术可以将一个分割槽格式化为多个档案系统(例如LVM)，也能够将多个分割槽合成一个档案系统(LVM, RAID)！ 所以说，目前我们在格式化时已经不再说成针对 partition 来格式化了， 通常我们可以称呼一个可被挂载的资料为一个档案系统而不是一个分割槽喔！

那么档案系统是如何运作的呢？这与作业系统的档案资料有关。较新的作业系统的档案资料除了档案实际内容外， 通常含有非常多的属性，例如 Linux 作业系统的档案权限(rwx)与档案属性(拥有者、群组、时间参数等)。 档案系统通常会将这两部份的资料分别存放在不同的区块，权限与属性放置到 inode 中，至于实际资料则放置到 data block 区块中。 另外，还有一个超级区块 (superblock) 会记录整个档案系统的整体资讯，包括 inode 与 block 的总量、使用量、剩余量等。

每个 inode 与 block 都有编号，至于这三个资料的意义可以简略说明如下：

  • superblock：记录此 filesystem 的整体资讯，包括inode/block的总量、使用量、剩余量， 以及档案系统的格式与相关资讯等；
  • inode：记录档案的属性，一个档案占用一个inode，同时记录此档案的资料所在的 block 号码；
  • block：实际记录档案的内容，若档案太大时，会占用多个 block 。

由于每个 inode 与 block 都有编号，而每个档案都会占用一个 inode ，inode 内则有档案资料放置的 block 号码。 因此，我们可以知道的是，如果能够找到档案的 inode 的话，那么自然就会知道这个档案所放置资料的 block 号码， 当然也就能够读出该档案的实际资料了。这是个比较有效率的作法，因为如此一来我们的磁碟就能够在短时间内读取出全部的资料， 读写的效能比较好啰。

我们将 inode 与 block 区块用图解来说明一下，如下图所示，档案系统先格式化出 inode 与 block 的区块，假设某一个档案的属性与权限资料是放置到 inode 4 号(下图较小方格内)，而这个 inode 记录了档案资料的实际放置点为 2, 7, 13, 15 这四个 block 号码，此时我们的作业系统就能够据此来排列磁碟的读取顺序，可以一口气将四个 block 内容读出来！ 那么资料的读取就如同下图中的箭头所指定的模样了。

inode/block 资料存取示意图
图1.2.1、inode/block 资料存取示意图

这种资料存取的方法我们称为索引式档案系统(indexed allocation)。那有没有其他的惯用档案系统可以比较一下啊？ 有的，那就是我们惯用的随身碟(快闪记忆体)，随身碟使用的档案系统一般为 FAT 格式。FAT 这种格式的档案系统并没有 inode 存在，所以 FAT 没有办法将这个档案的所有 block 在一开始就读取出来。每个 block 号码都记录在前一个 block 当中， 他的读取方式有点像底下这样：

FAT档案系统资料存取示意图
图1.2.2、FAT档案系统资料存取示意图

上图中我们假设档案的资料依序写入1->7->4->15号这四个 block 号码中， 但这个档案系统没有办法一口气就知道四个 block 的号码，他得要一个一个的将 block 读出后，才会知道下一个 block 在何处。 如果同一个档案资料写入的 block 分散的太过厉害时，则我们的磁碟读取头将无法在磁碟转一圈就读到所有的资料， 因此磁碟就会多转好几圈才能完整的读取到这个档案的内容！

常常会听到所谓的‘磁碟重组’吧？ 需要磁碟重组的原因就是档案写入的 block 太过于离散了，此时档案读取的效能将会变的很差所致。 这个时候可以透过磁碟重组将同一个档案所属的 blocks 汇整在一起，这样资料的读取会比较容易啊！ 想当然尔，FAT 的档案系统需要三不五时的磁碟重组一下，那么 Ext2 是否需要磁碟重整呢？

由于 Ext2 是索引式档案系统，基本上不太需要常常进行磁碟重组的。但是如果档案系统使用太久， 常常删除/编辑/新增档案时，那么还是可能会造成档案资料太过于离散的问题，此时或许会需要进行重整一下的。 不过，老实说，鸟哥倒是没有在 Linux 作业系统上面进行过 Ext2/Ext3 档案系统的磁碟重组说！似乎不太需要啦！^_^

小标题的图示 Linux 的 EXT2 档案系统(inode)：

在第六章当中我们介绍过 Linux 的档案除了原有的资料内容外，还含有非常多的权限与属性，这些权限与属性是为了保护每个使用者所拥有资料的隐密性。 而前一小节我们知道 filesystem 里面可能含有的 inode/block/superblock 等。为什么要谈这个呢？因为标准的 Linux 档案系统 Ext2 就是使用这种 inode 为基础的档案系统啦！

而如同前一小节所说的，inode 的内容在记录档案的权限与相关属性，至于 block 区块则是在记录档案的实际内容。 而且档案系统一开始就将 inode 与 block 规划好了，除非重新格式化(或者利用 resize2fs 等指令变更档案系统大小)，否则 inode 与 block 固定后就不再变动。但是如果仔细考虑一下，如果我的档案系统高达数百GB时， 那么将所有的 inode 与 block 通通放置在一起将是很不智的决定，因为 inode 与 block 的数量太庞大，不容易管理。

为此之故，因此 Ext2 档案系统在格式化的时候基本上是区分为多个区块群组 (block group) 的，每个区块群组都有独立的 inode/block/superblock 系统。感觉上就好像我们在当兵时，一个营里面有分成数个连，每个连有自己的联络系统， 但最终都向营部回报连上最正确的资讯一般！这样分成一群群的比较好管理啦！整个来说，Ext2 格式化后有点像底下这样：

ext2档案系统示意图
图1.3.1、ext2档案系统示意图(注1)

在整体的规划当中，档案系统最前面有一个开机磁区(boot sector)，这个开机磁区可以安装开机管理程式， 这是个非常重要的设计，因为如此一来我们就能够将不同的开机管理程式安装到个别的档案系统最前端，而不用覆盖整颗硬碟唯一的 MBR， 这样也才能够制作出多重开机的环境啊！至于每一个区块群组(block group)的六个主要内容说明如后：

  • data block (资料区块)

data block 是用来放置档案内容资料地方，在 Ext2 档案系统中所支援的 block 大小有 1K, 2K 及 4K 三种而已。在格式化时 block 的大小就固定了，且每个 block 都有编号，以方便 inode 的记录啦。 不过要注意的是，由于 block 大小的差异，会导致该档案系统能够支援的最大磁碟容量与最大单一档案容量并不相同。 因为 block 大小而产生的 Ext2 档案系统限制如下：(注2)

Block 大小 | 1KB | 2KB | 4KB
最大单一档案限制 | 16GB | 256GB | 2TB
最大档案系统总容量 | 2TB | 8TB | 16TB

你需要注意的是，虽然 Ext2 已经能够支援大于 2GB 以上的单一档案容量，不过某些应用程式依然使用旧的限制， 也就是说，某些程式只能够捉到小于 2GB 以下的档案而已，这就跟档案系统无关了！ 举例来说，鸟哥在环工方面的应用中有一套秀图软体称为PAVE(注3)， 这套软体就无法捉到鸟哥在数值模式模拟后产生的大于 2GB 以上的档案！害的鸟哥常常还要重跑数值模式...

除此之外 Ext2 档案系统的 block 还有什么限制呢？有的！基本限制如下：

  • 原则上，block 的大小与数量在格式化完就不能够再改变了(除非重新格式化)；
  • 每个 block 内最多只能够放置一个档案的资料；
  • 承上，如果档案大于 block 的大小，则一个档案会占用多个 block 数量；
  • 承上，若档案小于 block ，则该 block 的剩余容量就不能够再被使用了(磁碟空间会浪费)。

如上第四点所说，由于每个 block 仅能容纳一个档案的资料而已，因此如果你的档案都非常小，但是你的 block 在格式化时却选用最大的 4K 时，可能会产生一些容量的浪费喔！我们以底下的一个简单例题来算一下空间的浪费吧！

例题：
假设你的Ext2档案系统使用 4K block ，而该档案系统中有 10000 个小档案，每个档案大小均为 50bytes， 请问此时你的磁碟浪费多少容量？
答：
由于 Ext2 档案系统中一个 block 仅能容纳一个档案，因此每个 block 会浪费‘ 4096 - 50 = 4046 (byte)’， 系统中总共有一万个小档案，所有档案容量为：50 x 10000 (bytes) = 488.3Kbytes，但此时浪费的容量为：‘ 4046 x 10000 (bytes) = 38.6MBytes ’。想一想，不到 1MB 的总档案容量却浪费将近 40MB 的容量，且档案越多将造成越多的磁碟容量浪费。

什么情况会产生上述的状况呢？例如 BBS 网站的资料啦！如果 BBS 上面的资料使用的是纯文字档案来记载每篇留言， 而留言内容如果都写上‘如题’时，想一想，是否就会产生很多小档案了呢？

好，既然大的 block 可能会产生较严重的磁碟容量浪费，那么我们是否就将 block 大小订为 1K 即可？ 这也不妥，因为如果 block 较小的话，那么大型档案将会占用数量更多的 block ，而 inode 也要记录更多的 block 号码，此时将可能导致档案系统不良的读写效能。

所以我们可以说，在您进行档案系统的格式化之前，请先想好该档案系统预计使用的情况。 以鸟哥来说，我的数值模式模拟平台随便一个档案都好几百 MB，那么 block 容量当然选择较大的！至少档案系统就不必记录太多的 block 号码，读写起来也比较方便啊！

  • inode table (inode 表格)

再来讨论一下 inode 这个玩意儿吧！如前所述 inode 的内容在记录档案的属性以及该档案实际资料是放置在哪几号 block 内！ 基本上，inode 记录的档案资料至少有底下这些：(注4)

  • 该档案的存取模式(read/write/excute)；
  • 该档案的拥有者与群组(owner/group)；
  • 该档案的容量；
  • 该档案建立或状态改变的时间(ctime)；
  • 最近一次的读取时间(atime)；
  • 最近修改的时间(mtime)；
  • 定义档案特性的旗标(flag)，如 SetUID...；
  • 该档案真正内容的指向 (pointer)；

inode 的数量与大小也是在格式化时就已经固定了，除此之外 inode 还有些什么特色呢？

  • 每个 inode 大小均固定为 128 bytes；
  • 每个档案都仅会占用一个 inode 而已；
  • 承上，因此档案系统能够建立的档案数量与 inode 的数量有关；
  • 系统读取档案时需要先找到 inode，并分析 inode 所记录的权限与使用者是否符合，若符合才能够开始实际读取 block 的内容。

我们约略来分析一下 inode / block 与档案大小的关系好了。inode 要记录的资料非常多，但偏偏又只有 128bytes 而已， 而 inode 记录一个 block 号码要花掉 4byte ，假设我一个档案有 400MB 且每个 block 为 4K 时， 那么至少也要十万笔 block 号码的记录呢！inode 哪有这么多可记录的资讯？为此我们的系统很聪明的将 inode 记录 block 号码的区域定义为12个直接，一个间接, 一个双间接与一个三间接记录区。这是啥？我们将 inode 的结构画一下好了。

inode 结构示意图
图1.3.2、inode 结构示意图(注5)

上图最左边为 inode 本身 (128 bytes)，里面有 12 个直接指向 block 号码的对照，这 12 笔记录就能够直接取得 block 号码啦！ 至于所谓的间接就是再拿一个 block 来当作记录 block 号码的记录区，如果档案太大时， 就会使用间接的 block 来记录号码。如上图 1.3.2 当中间接只是拿一个 block 来记录额外的号码而已。 同理，如果档案持续长大，那么就会利用所谓的双间接，第一个 block 仅再指出下一个记录号码的 block 在哪里， 实际记录的在第二个 block 当中。依此类推，三间接就是利用第三层 block 来记录号码啦！

这样子 inode 能够指定多少个 block 呢？我们以较小的 1K block 来说明好了，可以指定的情况如下：

  • 12 个直接指向： 12*1K=12K
    由于是直接指向，所以总共可记录 12 笔记录，因此总额大小为如上所示；

  • 间接： 256*1K=256K
    每笔 block 号码的记录会花去 4bytes，因此 1K 的大小能够记录 256 笔记录，因此一个间接可以记录的档案大小如上；

  • 双间接： 256*256*1K=2562K
    第一层 block 会指定 256 个第二层，每个第二层可以指定 256 个号码，因此总额大小如上；

  • 三间接： 256*256*256*1K=2563K
    第一层 block 会指定 256 个第二层，每个第二层可以指定 256 个第三层，每个第三层可以指定 256 个号码，因此总额大小如上；

  • 总额：将直接、间接、双间接、三间接加总，得到 12 + 256 + 256*256 + 256*256*256 (K) = 16GB

此时我们知道当档案系统将 block 格式化为 1K 大小时，能够容纳的最大档案为 16GB，比较一下档案系统限制表的结果可发现是一致的！但这个方法不能用在 2K 及 4K block 大小的计算中， 因为大于 2K 的 block 将会受到 Ext2 档案系统本身的限制，所以计算的结果会不太符合之故。

  • Superblock (超级区块)

Superblock 是记录整个 filesystem 相关资讯的地方， 没有 Superblock ，就没有这个 filesystem 了。他记录的资讯主要有：

  • block 与 inode 的总量；
  • 未使用与已使用的 inode / block 数量；
  • block 与 inode 的大小 (block 为 1, 2, 4K，inode 为 128 bytes)；
  • filesystem 的挂载时间、最近一次写入资料的时间、最近一次检验磁碟 (fsck) 的时间等档案系统的相关资讯；
  • 一个 valid bit 数值，若此档案系统已被挂载，则 valid bit 为 0 ，若未被挂载，则 valid bit 为 1 。

Superblock 是非常重要的，因为我们这个档案系统的基本资讯都写在这里，因此，如果 superblock 死掉了， 你的档案系统可能就需要花费很多时间去挽救啦！一般来说， superblock 的大小为 1024bytes。相关的 superblock 讯息我们等一下会以 dumpe2fs 指令来呼叫出来观察喔！

此外，每个 block group 都可能含有 superblock 喔！但是我们也说一个档案系统应该仅有一个 superblock 而已，那是怎么回事啊？ 事实上除了第一个 block group 内会含有 superblock 之外，后续的 block group 不一定含有 superblock ， 而若含有 superblock 则该 superblock 主要是做为第一个 block group 内 superblock 的备份咯，这样可以进行 superblock 的救援呢！

  • Filesystem Description (档案系统描述说明)

这个区段可以描述每个 block group 的开始与结束的 block 号码，以及说明每个区段 (superblock, bitmap, inodemap, data block) 分别介于哪一个 block 号码之间。这部份也能够用 dumpe2fs 来观察的。

  • block bitmap (区块对照表)

如果你想要新增档案时总会用到 block 吧！那你要使用那个 block 来记录呢？当然是选择‘空的 block ’来记录新档案的资料啰。 那你怎么知道那个 block 是空的？这就得要透过 block bitmap 的辅助了。从 block bitmap 当中可以知道哪些 block 是空的，因此我们的系统就能够很快速的找到可使用的空间来处置档案啰。

同样的，如果你删除某些档案时，那么那些档案原本占用的 block 号码就得要释放出来， 此时在 block bitmpap 当中相对应到该 block 号码的标志就得要修改成为‘未使用中’啰！这就是 bitmap 的功能。

  • inode bitmap (inode 对照表)

这个其实与 block bitmap 是类似的功能，只是 block bitmap 记录的是使用与未使用的 block 号码， 至于 inode bitmap 则是记录使用与未使用的 inode 号码啰！

了解了档案系统的概念之后，再来当然是观察这个档案系统啰！刚刚谈到的各部分资料都与 block 号码有关！ 每个区段与 superblock 的资讯都可以使用 dumpe2fs 这个指令来查询的！查询的方法与实际的观察如下：

[root@www ~]# dumpe2fs [-bh] 装置档名
选项与参数：
-b ：列出保留为坏轨的部分(一般用不到吧！？)
-h ：仅列出 superblock 的资料，不会列出其他的区段内容！

范例：找出我的根目录磁碟档名，并观察档案系统的相关资讯

[root@www ~]# df   <==这个指令可以叫出目前挂载的装置
Filesystem    1K-blocks      Used Available Use% Mounted on
/dev/hdc2       9920624   3822848   5585708  41% /        <==就是这个光！
/dev/hdc3       4956316    141376   4559108   4% /home
/dev/hdc1        101086     11126     84741  12% /boot
tmpfs            371332         0    371332   0% /dev/shm

[root@www ~]# dumpe2fs /dev/hdc2
dumpe2fs 1.39 (29-May-2006)
Filesystem volume name:   /1             <==这个是档案系统的名称(Label)

Filesystem features:      has_journal ext_attr resize_inode dir_index
  filetype needs_recovery sparse_super large_file
Default mount options:    user_xattr acl <==预设挂载的参数
Filesystem state:         clean          <==这个档案系统是没问题的(clean)
Errors behavior:          Continue
Filesystem OS type:       Linux
Inode count:              2560864        <==inode的总数
Block count:              2560359        <==block的总数
Free blocks:              1524760        <==还有多少个 block 可用

Free inodes:              2411225        <==还有多少个 inode 可用
First block:              0
Block size:               4096           <==每个 block 的大小啦！
Filesystem created:       Fri Sep  5 01:49:20 2008
Last mount time:          Mon Sep 22 12:09:30 2008
Last write time:          Mon Sep 22 12:09:30 2008
Last checked:             Fri Sep  5 01:49:20 2008
First inode:              11
Inode size:               128            <==每个 inode 的大小
Journal inode:            8              <==底下这三个与下一小节有关
Journal backup:           inode blocks
Journal size:             128M

Group 0: (Blocks 0-32767) <==第一个 data group 内容, 包含 block 的启始/结束号码

  Primary superblock at 0, Group descriptors at 1-1  <==超级区块在 0 号 block
  Reserved GDT blocks at 2-626
  Block bitmap at 627 (+627), Inode bitmap at 628 (+628)
  Inode table at 629-1641 (+629)                     <==inode table 所在的 block
  0 free blocks, 32405 free inodes, 2 directories    <==所有 block 都用完了！
  Free blocks:
  Free inodes: 12-32416                              <==剩余未使用的 inode 号码
Group 1: (Blocks 32768-65535)

....(底下省略)....
# 由于资料量非常的庞大，因此鸟哥将一些资讯省略输出了！上表与你的荧幕会有点差异。
# 前半部在秀出 supberblock 的内容，包括标头名称(Label)以及inode/block的相关资讯
# 后面则是每个 block group 的个别资讯了！您可以看到各区段资料所在的号码！
# 也就是说，基本上所有的资料还是与 block 的号码有关就是了！很重要！

如上所示，利用 dumpe2fs 可以查询到非常多的资讯，不过依内容主要可以区分为上半部是 superblock 内容， 下半部则是每个 block group 的资讯了。从上面的表格中我们可以观察到这个 /dev/hdc2 规划的 block 为 4K， 第一个 block 号码为 0 号，且 block group 内的所有资讯都以 block 的号码来表示的。 然后在 superblock 中还有谈到目前这个档案系统的可用 block 与 inode 数量喔！

至于 block group 的内容我们单纯看 Group0 资讯好了。从上表中我们可以发现：

  • Group0 所占用的 block 号码由 0 到 32767 号，superblock 则在第 0 号的 block 区块内！
  • 档案系统描述说明在第 1 号 block 中；
  • block bitmap 与 inode bitmap 则在 627 及 628 的 block 号码上。
  • 至于 inode table 分布于 629-1641 的 block 号码中！
  • 由于 (1)一个 inode 占用 128 bytes ，(2)总共有 1641 - 629 + 1(629本身) = 1013 个 block 花在 inode table 上， (3)每个 block 的大小为 4096 bytes(4K)。由这些数据可以算出 inode 的数量共有 1013 * 4096 / 128 = 32416 个 inode 啦！
  • 这个 Group0 目前没有可用的 block 了，但是有剩余 32405 个 inode 未被使用；
  • 剩余的 inode 号码为 12 号到 32416 号。

如果你对档案系统的详细资讯还有更多想要了解的话，那么请参考本章最后一小节的介绍喔！ 否则档案系统看到这里对于基础认知您应该是已经相当足够啦！底下则是要探讨一下， 那么这个档案系统概念与实际的目录树应用有啥关连啊？

小标题的图示 与目录树的关系

由前一小节的介绍我们知道在 Linux 系统下，每个档案(不管是一般档案还是目录档案)都会占用一个 inode ， 且可依据档案内容的大小来分配多个 block 给该档案使用。而由第六章的权限说明中我们知道目录的内容在记录档名， 一般档案才是实际记录资料内容的地方。那么目录与档案在 Ext2 档案系统当中是如何记录资料的呢？ 基本上可以这样说：

  • 目录

当我们在 Linux 下的 ext2 档案系统建立一个目录时， ext2 会分配一个 inode 与至少一块 block 给该目录。其中，inode 记录该目录的相关权限与属性，并可记录分配到的那块 block 号码； 而 block 则是记录在这个目录下的档名与该档名占用的 inode 号码资料。也就是说目录所占用的 block 内容在记录如下的资讯：

目录占用的 block 记录的资料示意图
图1.4.1、目录占用的 block 记录的资料示意图

如果想要实际观察 root 家目录内的档案所占用的 inode 号码时，可以使用 ls -i 这个选项来处理：

[root@www ~]# ls -li
total 92
654683 -rw------- 1 root root  1474 Sep  4 18:27 anaconda-ks.cfg
648322 -rw-r--r-- 1 root root 42304 Sep  4 18:26 install.log
648323 -rw-r--r-- 1 root root  5661 Sep  4 18:25 install.log.syslog

由于每个人所使用的电脑并不相同，系统安装时选择的项目与 partition 都不一样，因此你的环境不可能与我的 inode 号码一模一样！上表的右边所列出的 inode 仅是鸟哥的系统所显示的结果而已！而由这个目录的 block 结果我们现在就能够知道， 当你使用‘ ll / ’时，出现的目录几乎都是 1024 的倍数，为什么呢？因为每个 block 的数量都是 1K, 2K, 4K 嘛！ 看一下鸟哥的环境：

[root@www ~]# ll -d / /bin /boot /proc /lost+found /sbin
drwxr-xr-x 23 root root  4096 Sep 22 12:09 /           <==一个 4K block
drwxr-xr-x  2 root root  4096 Sep 24 00:07 /bin        <==一个 4K block
drwxr-xr-x  4 root root  1024 Sep  4 18:06 /boot       <==一个 1K block

drwx------  2 root root 16384 Sep  5 01:49 /lost+found <==四个 4K block
dr-xr-xr-x 96 root root     0 Sep 22 20:07 /proc       <==此目录不占硬碟空间
drwxr-xr-x  2 root root 12288 Sep  5 12:33 /sbin       <==三个 4K block

由于鸟哥的根目录 /dev/hdc2 使用的 block 大小为 4K ，因此每个目录几乎都是 4K 的倍数。 其中由于 /sbin 的内容比较复杂因此占用了 3 个 block ，此外，鸟哥的系统中 /boot 为独立的 partition ， 该 partition 的 block 为 1K 而已，因此该目录就仅占用 1024 bytes 的大小啰！至于奇怪的 /proc 我们在第六章就讲过该目录不占硬碟容量， 所以当然耗用的 block 就是 0 啰！

Tips:
由上面的结果我们知道目录并不只会占用一个 block 而已，也就是说： 在目录底下的档案数如果太多而导致一个 block 无法容纳的下所有的档名与 inode 对照表时，Linux 会给予该目录多一个 block 来继续记录相关的资料； 		鸟哥的图示
  • 档案：

当我们在 Linux 下的 ext2 建立一个一般档案时， ext2 会分配一个 inode 与相对于该档案大小的 block 数量给该档案。例如：假设我的一个 block 为 4 Kbytes ，而我要建立一个 100 KBytes 的档案，那么 linux 将分配一个 inode 与 25 个 block 来储存该档案！ 但同时请注意，由于 inode 仅有 12 个直接指向，因此还要多一个 block 来作为区块号码的记录喔！

  • 目录树读取：

好了，经过上面的说明你也应该要很清楚的知道 inode 本身并不记录档名，档名的记录是在目录的 block 当中。 因此在第六章档案与目录的权限说明中， 我们才会提到‘新增/删除/更名档名与目录的 w 权限有关’的特色！那么因为档名是记录在目录的 block 当中， 因此当我们要读取某个档案时，就务必会经过目录的 inode 与 block ，然后才能够找到那个待读取档案的 inode 号码， 最终才会读到正确的档案的 block 内的资料。

由于目录树是由根目录开始读起，因此系统透过挂载的资讯可以找到挂载点的 inode 号码(通常一个 filesystem 的最顶层 inode 号码会由 2 号开始喔！)，此时就能够得到根目录的 inode 内容，并依据该 inode 读取根目录的 block 内的档名资料，再一层一层的往下读到正确的档名。

举例来说，如果我想要读取 /etc/passwd 这个档案时，系统是如何读取的呢？

[root@www ~]# ll -di / /etc /etc/passwd

      2 drwxr-xr-x  23 root root  4096 Sep 22 12:09 /
1912545 drwxr-xr-x 105 root root 12288 Oct 14 04:02 /etc
1914888 -rw-r--r--   1 root root  1945 Sep 29 02:21 /etc/passwd

在鸟哥的系统上面与 /etc/passwd 有关的目录与档案资料如上表所示，该档案的读取流程为(假设读取者身份为 vbird 这个一般身份使用者)：

  1. / 的 inode：
    透过挂载点的资讯找到 /dev/hdc2 的 inode 号码为 2 的根目录 inode，且 inode 规范的权限让我们可以读取该 block 的内容(有 r 与 x) ；

  2. / 的 block：
    经过上个步骤取得 block 的号码，并找到该内容有 etc/ 目录的 inode 号码 (1912545)；

  3. etc/ 的 inode：
    读取 1912545 号 inode 得知 vbird 具有 r 与 x 的权限，因此可以读取 etc/ 的 block 内容；

  4. etc/ 的 block：
    经过上个步骤取得 block 号码，并找到该内容有 passwd 档案的 inode 号码 (1914888)；

  5. passwd 的 inode：
    读取 1914888 号 inode 得知 vbird 具有 r 的权限，因此可以读取 passwd 的 block 内容；

  6. passwd 的 block：
    最后将该 block 内容的资料读出来。

  • filesystem 大小与磁碟读取效能：

另外，关于档案系统的使用效率上，当你的一个档案系统规划的很大时，例如 100GB 这么大时， 由于硬碟上面的资料总是来来去去的，所以，整个档案系统上面的档案通常无法连续写在一起(block 号码不会连续的意思)， 而是填入式的将资料填入没有被使用的 block 当中。如果档案写入的 block 真的分的很散， 此时就会有所谓的档案资料离散的问题发生了。

如前所述，虽然我们的 ext2 在 inode 处已经将该档案所记录的 block 号码都记上了， 所以资料可以一次性读取，但是如果档案真的太过离散，确实还是会发生读取效率低落的问题。 因为磁碟读取头还是得要在整个档案系统中来来去去的频繁读取！ 果真如此，那么可以将整个 filesystme 内的资料全部复制出来，将该 filesystem 重新格式化， 再将资料给他复制回去即可解决这个问题。

此外，如果 filesystem 真的太大了，那么当一个档案分别记录在这个档案系统的最前面与最后面的 block 号码中， 此时会造成硬碟的机械手臂移动幅度过大，也会造成资料读取效能的低落。而且读取头再搜寻整个 filesystem 时， 也会花费比较多的时间去搜寻！因此， partition 的规划并不是越大越好， 而是真的要针对您的主机用途来进行规划才行！^_^

小标题的图示 EXT2/EXT3 档案的存取与日志式档案系统的功能

上一小节谈到的仅是读取而已，那么如果是新建一个档案或目录时，我们的 Ext2 是如何处理的呢？ 这个时候就得要 block bitmap 及 inode bitmap 的帮忙了！假设我们想要新增一个档案，此时档案系统的行为是：

  1. 先确定使用者对于欲新增档案的目录是否具有 w 与 x 的权限，若有的话才能新增；
  2. 根据 inode bitmap 找到没有使用的 inode 号码，并将新档案的权限/属性写入；
  3. 根据 block bitmap 找到没有使用中的 block 号码，并将实际的资料写入 block 中，且更新 inode 的 block 指向资料；
  4. 将刚刚写入的 inode 与 block 资料同步更新 inode bitmap 与 block bitmap，并更新 superblock 的内容。

一般来说，我们将 inode table 与 data block 称为资料存放区域，至于其他例如 superblock、 block bitmap 与 inode bitmap 等区段就被称为 metadata (中介资料) 啰，因为 superblock, inode bitmap 及 block bitmap 的资料是经常变动的，每次新增、移除、编辑时都可能会影响到这三个部分的资料，因此才被称为中介资料的啦。

  • 资料的不一致 (Inconsistent) 状态

在一般正常的情况下，上述的新增动作当然可以顺利的完成。但是如果有个万一怎么办？ 例如你的档案在写入档案系统时，因为不知名原因导致系统中断(例如突然的停电啊、 系统核心发生错误啊～等等的怪事发生时)，所以写入的资料仅有 inode table 及 data block 而已， 最后一个同步更新中介资料的步骤并没有做完，此时就会发生 metadata 的内容与实际资料存放区产生不一致 (Inconsistent) 的情况了。

既然有不一致当然就得要克服！在早期的 Ext2 档案系统中，如果发生这个问题， 那么系统在重新开机的时候，就会藉由 Superblock 当中记录的 valid bit (是否有挂载) 与 filesystem state (clean 与否) 等状态来判断是否强制进行资料一致性的检查！若有需要检查时则以 e2fsck 这支程式来进行的。

不过，这样的检查真的是很费时～因为要针对 metadata 区域与实际资料存放区来进行比对， 呵呵～得要搜寻整个 filesystem 呢～如果你的档案系统有 100GB 以上，而且里面的档案数量又多时， 哇！系统真忙碌～而且在对 Internet 提供服务的伺服器主机上面， 这样的检查真的会造成主机复原时间的拉长～真是麻烦～这也就造成后来所谓日志式档案系统的兴起了。

  • 日志式档案系统 (Journaling filesystem)

为了避免上述提到的档案系统不一致的情况发生，因此我们的前辈们想到一个方式， 如果在我们的 filesystem 当中规划出一个区块，该区块专门在记录写入或修订档案时的步骤， 那不就可以简化一致性检查的步骤了？也就是说：

  1. 预备：当系统要写入一个档案时，会先在日志记录区块中纪录某个档案准备要写入的资讯；
  2. 实际写入：开始写入档案的权限与资料；开始更新 metadata 的资料；
  3. 结束：完成资料与 metadata 的更新后，在日志记录区块当中完成该档案的纪录。

在这样的程序当中，万一资料的纪录过程当中发生了问题，那么我们的系统只要去检查日志记录区块， 就可以知道那个档案发生了问题，针对该问题来做一致性的检查即可，而不必针对整块 filesystem 去检查， 这样就可以达到快速修复 filesystem 的能力了！这就是日志式档案最基础的功能啰～

那么我们的 ext2 可达到这样的功能吗？当然可以啊！ 就透过 ext3 即可！ ext3 是 ext2 的升级版本，并且可向下相容 ext2 版本呢！ 所以啰，目前我们才建议大家，可以直接使用 ext3 这个 filesystem 啊！ 如果你还记得 dumpe2fs 输出的讯息，可以发现 superblock 里面含有底下这样的资讯：

Journal inode:            8
Journal backup:           inode blocks
Journal size:             128M

看到了吧！透过 inode 8 号记录 journal 区块的 block 指向，而且具有 128MB 的容量在处理日志呢！ 这样对于所谓的日志式档案系统有没有比较有概念一点呢？^_^。如果想要知道为什么 Ext3 档案系统会更适用于目前的 Linux 系统， 我们可以参考 Red Hat 公司中，首席核心开发者 Michael K. Johnson 的话：(注6)

‘为什么你想要从ext2转换到ext3呢？有四个主要的理由：可利用性、资料完整性、速度及易于转换’ ‘可利用性’，他指出，这意味着从系统中止到快速重新复原而不是持续的让e2fsck执行长时间的修复。ext3 的日志式条件可以避免资料毁损的可能。他也指出： ‘除了写入若干资料超过一次时，ext3往往会较快于ext2，因为ext3的日志使硬碟读取头的移动能更有效的进行’ 然而或许决定的因素还是在Johnson先生的第四个理由中。

‘它是可以轻易的从ext2变更到ext3来获得一个强而有力的日志式档案系统而不需要重新做格式化’。‘那是正确的，为了体验一下 ext3 的好处是不需要去做一种长时间的，冗长乏味的且易于产生错误的备份工作及重新格式化的动作’。
小标题的图示 Linux 档案系统的运作：

我们现在知道了目录树与档案系统的关系了，但是由第零章的内容我们也知道， 所有的资料都得要载入到记忆体后 CPU 才能够对该资料进行处理。想一想，如果你常常编辑一个好大的档案， 在编辑的过程中又频繁的要系统来写入到磁碟中，由于磁碟写入的速度要比记忆体慢很多， 因此你会常常耗在等待硬碟的写入/读取上。真没效率！

为了解决这个效率的问题，因此我们的 Linux 使用的方式是透过一个称为非同步处理 (asynchronously) 的方式。所谓的非同步处理是这样的：

当系统载入一个档案到记忆体后，如果该档案没有被更动过，则在记忆体区段的档案资料会被设定为干净(clean)的。 但如果记忆体中的档案资料被更改过了(例如你用 nano 去编辑过这个档案)，此时该记忆体中的资料会被设定为脏的 (Dirty)。此时所有的动作都还在记忆体中执行，并没有写入到磁碟中！ 系统会不定时的将记忆体中设定为‘Dirty’的资料写回磁碟，以保持磁碟与记忆体资料的一致性。 你也可以利用第五章谈到的 sync指令来手动强迫写入磁碟。

我们知道记忆体的速度要比硬碟快的多，因此如果能够将常用的档案放置到记忆体当中，这不就会增加系统性能吗？ 没错！是有这样的想法！因此我们 Linux 系统上面档案系统与记忆体有非常大的关系喔：

  • 系统会将常用的档案资料放置到主记忆体的缓冲区，以加速档案系统的读/写；
  • 承上，因此 Linux 的实体记忆体最后都会被用光！这是正常的情况！可加速系统效能；
  • 你可以手动使用 sync 来强迫记忆体中设定为 Dirty 的档案回写到磁碟中；
  • 若正常关机时，关机指令会主动呼叫 sync 来将记忆体的资料回写入磁碟内；
  • 但若不正常关机(如跳电、当机或其他不明原因)，由于资料尚未回写到磁碟内， 因此重新开机后可能会花很多时间在进行磁碟检验，甚至可能导致档案系统的损毁(非磁碟损毁)。
小标题的图示 挂载点的意义 (mount point)：

每个 filesystem 都有独立的 inode / block / superblock 等资讯，这个档案系统要能够连结到目录树才能被我们使用。 将档案系统与目录树结合的动作我们称为‘挂载’。 关于挂载的一些特性我们在第三章稍微提过， 重点是：挂载点一定是目录，该目录为进入该档案系统的入口。 因此并不是你有任何档案系统都能使用，必须要‘挂载’到目录树的某个目录后，才能够使用该档案系统的。

举例来说，如果你是依据鸟哥的方法安装你的 CentOS 5.x 的话， 那么应该会有三个挂载点才是，分别是 /, /boot, /home 三个 (鸟哥的系统上对应的装置档名为 /dev/hdc2, /dev/hdc1, /dev/hdc3)。 那如果观察这三个目录的 inode 号码时，我们可以发现如下的情况：

[root@www ~]# ls -lid / /boot /home
2 drwxr-xr-x 23 root root 4096 Sep 22 12:09 /
2 drwxr-xr-x  4 root root 1024 Sep  4 18:06 /boot

2 drwxr-xr-x  6 root root 4096 Sep 29 02:21 /home

看到了吧！由于 filesystem 最顶层的目录之 inode 一般为 2 号，因此可以发现 /, /boot, /home 为三个不同的 filesystem 啰！ (因为每一行的档案属性并不相同，且三个目录的挂载点也均不相同之故。) 我们在第七章一开始的路径中曾经提到根目录下的 . 与 .. 是相同的东西， 因为权限是一模一样嘛！如果使用档案系统的观点来看，同一个 filesystem 的某个 inode 只会对应到一个档案内容而已(因为一个档案占用一个 inode 之故)， 因此我们可以透过判断 inode 号码来确认不同档名是否为相同的档案喔！所以可以这样看：

[root@www ~]# ls -ild /  /.  /..

2 drwxr-xr-x 23 root root 4096 Sep 22 12:09 /
2 drwxr-xr-x 23 root root 4096 Sep 22 12:09 /.
2 drwxr-xr-x 23 root root 4096 Sep 22 12:09 /..

上面的资讯中由于挂载点均为 / ，因此三个档案 (/, /., /..) 均在同一个 filesystem 内，而这三个档案的 inode 号码均为 2 号，因此这三个档名都指向同一个 inode 号码，当然这三个档案的内容也就完全一模一样了！ 也就是说，根目录的上层 (/..) 就是他自己！这么说，看的懂了吗？ ^_^

小标题的图示 其他 Linux 支援的档案系统与 VFS

虽然 Linux 的标准档案系统是 ext2 ，且还有增加了日志功能的 ext3 ，事实上，Linux 还有支援很多档案系统格式的， 尤其是最近这几年推出了好几种速度很快的日志式档案系统，包括 SGI 的 XFS 档案系统， 可以适用更小型档案的 Reiserfs 档案系统，以及 Windows 的 FAT 档案系统等等， 都能够被 Linux 所支援喔！常见的支援档案系统有：

  • 传统档案系统：ext2 / minix / MS-DOS / FAT (用 vfat 模组) / iso9660 (光碟)等等；
  • 日志式档案系统： ext3 / ReiserFS / Windows' NTFS / IBM's JFS / SGI's XFS
  • 网路档案系统： NFS / SMBFS

想要知道你的 Linux 支援的档案系统有哪些，可以察看底下这个目录：

[root@www ~]# ls -l /lib/modules/$(uname -r)/kernel/fs

系统目前已载入到记忆体中支援的档案系统则有：

[root@www ~]# cat /proc/filesystems
  • Linux VFS (Virtual Filesystem Switch)

了解了我们使用的档案系统之后，再来则是要提到，那么 Linux 的核心又是如何管理这些认识的档案系统呢？ 其实，整个 Linux 的系统都是透过一个名为 Virtual Filesystem Switch 的核心功能去读取 filesystem 的。 也就是说，整个 Linux 认识的 filesystem 其实都是 VFS 在进行管理，我们使用者并不需要知道每个 partition 上头的 filesystem 是什么～ VFS 会主动的帮我们做好读取的动作呢～

假设你的 / 使用的是 /dev/hda1 ，用 ext3 ，而 /home 使用 /dev/hda2 ，用 reiserfs ， 那么你取用 /home/dmtsai/.bashrc 时，有特别指定要用的什么档案系统的模组来读取吗？ 应该是没有吧！这个就是 VFS 的功能啦！透过这个 VFS 的功能来管理所有的 filesystem， 省去我们需要自行设定读取档案系统的定义啊～方便很多！整个 VFS 可以约略用下图来说明：

VFS 档案系统的示意图
图 1.8.1、VFS 档案系统的示意图

老实说，档案系统真的不好懂！ 如果你想要对档案系统有更深入的了解，文末的相关连结(注7)务必要参考参考才好喔！ 鸟哥有找了一些资料放置于这里：

  • Ext2/Ext3 档案系统：http://linux.vbird.org/linux_basic/1010appendix_B.php

有兴趣的朋友务必要前往参考参考才好！

大标题的图示 档案系统的简单操作

稍微了解了档案系统后，再来我们得要知道如何查询整体档案系统的总容量与每个目录所占用的容量啰！ 此外，前两章谈到的档案类型中尚未讲的很清楚的连结档 (Link file) 也会在这一小节当中介绍的。

小标题的图示 磁碟与目录的容量：

现在我们知道磁碟的整体资料是在 superblock 区块中，但是每个各别档案的容量则在 inode 当中记载的。 那在文字介面底下该如何叫出这几个资料呢？底下就让我们来谈一谈这两个指令：

  • df：列出档案系统的整体磁碟使用量；
  • du：评估档案系统的磁碟使用量(常用在推估目录所占容量)

  • df
[root@www ~]# df [-ahikHTm] [目录或档名]
选项与参数：
-a  ：列出所有的档案系统，包括系统特有的 /proc 等档案系统；
-k  ：以 KBytes 的容量显示各档案系统；
-m  ：以 MBytes 的容量显示各档案系统；
-h  ：以人们较易阅读的 GBytes, MBytes, KBytes 等格式自行显示；
-H  ：以 M=1000K 取代 M=1024K 的进位方式；
-T  ：连同该 partition 的 filesystem 名称 (例如 ext3) 也列出；

-i  ：不用硬碟容量，而以 inode 的数量来显示

范例一：将系统内所有的 filesystem 列出来！
[root@www ~]# df
Filesystem      1K-blocks      Used Available Use% Mounted on
/dev/hdc2         9920624   3823112   5585444  41% /
/dev/hdc3         4956316    141376   4559108   4% /home
/dev/hdc1          101086     11126     84741  12% /boot
tmpfs              371332         0    371332   0% /dev/shm
# 在 Linux 底下如果 df 没有加任何选项，那么预设会将系统内所有的
# (不含特殊记忆体内的档案系统与 swap) 都以 1 Kbytes 的容量来列出来！
# 至于那个 /dev/shm 是与记忆体有关的挂载，先不要理他！

范例二：将容量结果以易读的容量格式显示出来

[root@www ~]# df -h
Filesystem            Size  Used Avail Use% Mounted on
/dev/hdc2             9.5G  3.7G  5.4G  41% /
/dev/hdc3             4.8G  139M  4.4G   4% /home
/dev/hdc1              99M   11M   83M  12% /boot
tmpfs                 363M     0  363M   0% /dev/shm
# 不同于范例一，这里会以 G/M 等容量格式显示出来，比较容易看啦！

范例三：将系统内的所有特殊档案格式及名称都列出来
[root@www ~]# df -aT
Filesystem    Type 1K-blocks    Used Available Use% Mounted on
/dev/hdc2     ext3   9920624 3823112   5585444  41% /
proc          proc         0       0         0   -  /proc
sysfs        sysfs         0       0         0   -  /sys
devpts      devpts         0       0         0   -  /dev/pts
/dev/hdc3     ext3   4956316  141376   4559108   4% /home
/dev/hdc1     ext3    101086   11126     84741  12% /boot
tmpfs        tmpfs    371332       0    371332   0% /dev/shm
none   binfmt_misc         0       0         0   -  /proc/sys/fs/binfmt_misc
sunrpc  rpc_pipefs         0       0         0   -  /var/lib/nfs/rpc_pipefs
# 系统里面其实还有很多特殊的档案系统存在的。那些比较特殊的档案系统几乎
# 都是在记忆体当中，例如 /proc 这个挂载点。因此，这些特殊的档案系统
# 都不会占据硬碟空间喔！ ^_^

范例四：将 /etc 底下的可用的磁碟容量以易读的容量格式显示
[root@www ~]# df -h /etc
Filesystem            Size  Used Avail Use% Mounted on
/dev/hdc2             9.5G  3.7G  5.4G  41% /
# 这个范例比较有趣一点啦，在 df 后面加上目录或者是档案时， df
# 会自动的分析该目录或档案所在的 partition ，并将该 partition 的容量显示出来，
# 所以，您就可以知道某个目录底下还有多少容量可以使用了！ ^_^

范例五：将目前各个 partition 当中可用的 inode 数量列出
[root@www ~]# df -ih
Filesystem            Inodes   IUsed   IFree IUse% Mounted on
/dev/hdc2               2.5M    147K    2.3M    6% /
/dev/hdc3               1.3M      46    1.3M    1% /home
/dev/hdc1                26K      34     26K    1% /boot
tmpfs                    91K       1     91K    1% /dev/shm
# 这个范例则主要列出可用的 inode 剩余量与总容量。分析一下与范例一的关系，
# 你可以清楚的发现到，通常 inode 的数量剩余都比 block 还要多呢

先来说明一下范例一所输出的结果讯息为：

  • Filesystem：代表该档案系统是在哪个 partition ，所以列出装置名称；
  • 1k-blocks：说明底下的数字单位是 1KB 呦！可利用 -h 或 -m 来改变容量；
  • Used：顾名思义，就是使用掉的硬碟空间啦！
  • Available：也就是剩下的磁碟空间大小；
  • Use%：就是磁碟的使用率啦！如果使用率高达 90% 以上时， 最好需要注意一下了，免得容量不足造成系统问题喔！(例如最容易被灌爆的 /var/spool/mail 这个放置邮件的磁碟)
  • Mounted on：就是磁碟挂载的目录所在啦！(挂载点啦！)

由于 df 主要读取的资料几乎都是针对一整个档案系统，因此读取的范围主要是在 Superblock 内的资讯， 所以这个指令显示结果的速度非常的快速！在显示的结果中你需要特别留意的是那个根目录的剩余容量！ 因为我们所有的资料都是由根目录衍生出来的，因此当根目录的剩余容量剩下 0 时，那你的 Linux 可能就问题很大了。

Tips:
说个陈年老笑话！鸟哥还在念书时，别的研究室有个管理 Sun 工作站的研究生发现， 他的硬碟明明还有好几 GB ，但是就是没有办法将光碟内几 MB 的资料 copy 进去， 他就去跟老板讲说机器坏了！嘿！明明才来维护过几天而已为何会坏了！ 结果他老板就将维护商叫来骂了 2 小时左右吧！

后来，维护商发现原来硬碟的‘总空间’还有很多， 只是某个分割槽填满了，偏偏该研究生就是要将资料 copy 去那个分割槽！呵呵！ 后来那个研究生就被命令‘再也不许碰 Sun 主机’了～～ 		鸟哥的图示

另外需要注意的是，如果使用 -a 这个参数时，系统会出现 /proc 这个挂载点，但是里面的东西都是 0 ，不要紧张！ /proc 的东西都是 Linux 系统所需要载入的系统资料，而且是挂载在‘记忆体当中’的， 所以当然没有占任何的硬碟空间啰！

至于那个 /dev/shm/ 目录，其实是利用记忆体虚拟出来的磁碟空间！ 由于是透过记忆体模拟出来的磁碟，因此你在这个目录底下建立任何资料档案时，存取速度是非常快速的！(在记忆体内工作) 不过，也由于他是记忆体模拟出来的，因此这个档案系统的大小在每部主机上都不一样，而且建立的东西在下次开机时就消失了！ 因为是在记忆体中嘛！

  • du
[root@www ~]# du [-ahskm] 档案或目录名称
选项与参数：
-a  ：列出所有的档案与目录容量，因为预设仅统计目录底下的档案量而已。
-h  ：以人们较易读的容量格式 (G/M) 显示；
-s  ：列出总量而已，而不列出每个各别的目录占用容量；

-S  ：不包括子目录下的总计，与 -s 有点差别。
-k  ：以 KBytes 列出容量显示；
-m  ：以 MBytes 列出容量显示；

范例一：列出目前目录下的所有档案容量
[root@www ~]# du
8       ./test4     <==每个目录都会列出来
8       ./test2
....中间省略....
12      ./.gconfd   <==包括隐藏档的目录

220     .           <==这个目录(.)所占用的总量
# 直接输入 du 没有加任何选项时，则 du 会分析‘目前所在目录’
# 的档案与目录所占用的硬碟空间。但是，实际显示时，仅会显示目录容量(不含档案)，
# 因此 . 目录有很多档案没有被列出来，所以全部的目录相加不会等于 . 的容量喔！
# 此外，输出的数值资料为 1K 大小的容量单位。

范例二：同范例一，但是将档案的容量也列出来
[root@www ~]# du -a
12      ./install.log.syslog   <==有档案的列表了
8       ./.bash_logout
8       ./test4
8       ./test2
....中间省略....

12      ./.gconfd
220     .

范例三：检查根目录底下每个目录所占用的容量
[root@www ~]# du -sm /*
7       /bin
6       /boot
.....中间省略....
0       /proc
.....中间省略....
1       /tmp
3859    /usr     <==系统初期最大就是他了啦！
77      /var
# 这是个很常被使用的功能～利用万用字元 * 来代表每个目录，
# 如果想要检查某个目录下，那个次目录占用最大的容量，可以用这个方法找出来
# 值得注意的是，如果刚刚安装好 Linux 时，那么整个系统容量最大的应该是 /usr
# 而 /proc 虽然有列出容量，但是那个容量是在记忆体中，不占硬碟空间。

与 df 不一样的是，du 这个指令其实会直接到档案系统内去搜寻所有的档案资料， 所以上述第三个范例指令的运作会执行一小段时间！此外，在预设的情况下，容量的输出是以 KB 来设计的， 如果你想要知道目录占了多少 MB ，那么就使用 -m 这个参数即可啰！而， 如果你只想要知道该目录占了多少容量的话，使用 -s 就可以啦！

至于 -S 这个选项部分，由于 du 预设会将所有档案的大小均列出，因此假设你在 /etc 底下使用 du 时， 所有的档案大小，包括 /etc 底下的次目录容量也会被计算一次。然后最终的容量 (/etc) 也会加总一次， 因此很多朋友都会误会 du 分析的结果不太对劲。所以啰，如果想要列出某目录下的全部资料， 或许也可以加上 -S 的选项，减少次目录的加总喔！

小标题的图示 实体连结与符号连结： ln

关于连结(link)资料我们第六章的Linux档案属性及Linux档案种类与副档名当中提过一些资讯， 不过当时由于尚未讲到档案系统，因此无法较完整的介绍连结档啦。不过在上一小节谈完了档案系统后， 我们可以来了解一下连结档这玩意儿了。

在 Linux 底下的连结档有两种，一种是类似 Windows 的捷径功能的档案，可以让你快速的连结到目标档案(或目录)； 另一种则是透过档案系统的 inode 连结来产生新档名，而不是产生新档案！这种称为实体连结 (hard link)。 这两种玩意儿是完全不一样的东西呢！现在就分别来谈谈。

  • Hard Link (实体连结, 硬式连结或实际连结)

在前一小节当中，我们知道几件重要的资讯，包括：

  • 每个档案都会占用一个 inode ，档案内容由 inode 的记录来指向；
  • 想要读取该档案，必须要经过目录记录的档名来指向到正确的 inode 号码才能读取。

也就是说，其实档名只与目录有关，但是档案内容则与 inode 有关。那么想一想， 有没有可能有多个档名对应到同一个 inode 号码呢？有的！那就是 hard link 的由来。 所以简单的说：hard link 只是在某个目录下新增一笔档名连结到某 inode 号码的关连记录而已。

举个例子来说，假设我系统有个 /root/crontab 他是 /etc/crontab 的实体连结，也就是说这两个档名连结到同一个 inode ， 自然这两个档名的所有相关资讯都会一模一样(除了档名之外)。实际的情况可以如下所示：

[root@www ~]# ln /etc/crontab .   <==建立实体连结的指令
[root@www ~]# ll -i /etc/crontab /root/crontab
1912701 -rw-r--r-- 2 root root 255 Jan  6  2007 /etc/crontab

1912701 -rw-r--r-- 2 root root 255 Jan  6  2007 /root/crontab

你可以发现两个档名都连结到 1912701 这个 inode 号码，所以您瞧瞧，是否档案的权限/属性完全一样呢？ 因为这两个‘档名’其实是一模一样的‘档案’啦！而且你也会发现第二个栏位由原本的 1 变成 2 了！ 那个栏位称为‘连结’，这个栏位的意义为：‘有多少个档名连结到这个 inode 号码’的意思。 如果将读取到正确资料的方式画成示意图，就类似如下画面：

实体连结的档案读取示意图
图 2.2.1、实体连结的档案读取示意图

上图的意思是，你可以透过 1 或 2 的目录之 inode 指定的 block 找到两个不同的档名，而不管使用哪个档名均可以指到 real 那个 inode 去读取到最终资料！那这样有什么好处呢？最大的好处就是‘安全’！如同上图中， 如果你将任何一个‘档名’删除，其实 inode 与 block 都还是存在的！ 此时你可以透过另一个‘档名’来读取到正确的档案资料喔！此外，不论你使用哪个‘档名’来编辑， 最终的结果都会写入到相同的 inode 与 block 中，因此均能进行资料的修改哩！

一般来说，使用 hard link 设定连结档时，磁碟的空间与 inode 的数目都不会改变！ 我们还是由图 2.2.1 来看，由图中可以知道， hard link 只是在某个目录下的 block 多写入一个关连资料而已，既不会增加 inode 也不会耗用 block 数量哩！

Tips:
hard link 的制作中，其实还是可能会改变系统的 block 的，那就是当你新增这笔资料却刚好将目录的 block 填满时，就可能会新加一个 block 来记录档名关连性，而导致磁碟空间的变化！不过，一般 hard link 所用掉的关连资料量很小，所以通常不会改变 inode 与磁碟空间的大小喔！ 		鸟哥的图示

由图 2.2.1 其实我们也能够知道，事实上 hard link 应该仅能在单一档案系统中进行的，应该是不能够跨档案系统才对！ 因为图 2.2.1 就是在同一个 filesystem 上嘛！所以 hard link 是有限制的：

  • 不能跨 Filesystem；
  • 不能 link 目录。

不能跨 Filesystem 还好理解，那不能 hard link 到目录又是怎么回事呢？这是因为如果使用 hard link 连结到目录时， 连结的资料需要连同被连结目录底下的所有资料都建立连结，举例来说，如果你要将 /etc 使用实体连结建立一个 /etc_hd 的目录时，那么在 /etc_hd 底下的所有档名同时都与 /etc 底下的档名要建立 hard link 的，而不是仅连结到 /etc_hd 与 /etc 而已。 并且，未来如果需要在 /etc_hd 底下建立新档案时，连带的， /etc 底下的资料又得要建立一次 hard link ，因此造成环境相当大的复杂度。 所以啰，目前 hard link 对于目录暂时还是不支援的啊！

  • Symbolic Link (符号连结，亦即是捷径)

相对于 hard link ， Symbolic link 可就好理解多了，基本上， Symbolic link 就是在建立一个独立的档案，而这个档案会让资料的读取指向他 link 的那个档案的档名！由于只是利用档案来做为指向的动作， 所以，当来源档被删除之后，symbolic link 的档案会‘开不了’， 会一直说‘无法开启某档案！’。实际上就是找不到原始‘档名’而已啦！

举例来说，我们先建立一个符号连结档连结到 /etc/crontab 去看看：

[root@www ~]# ln -s /etc/crontab crontab2
[root@www ~]# ll -i /etc/crontab /root/crontab2
1912701 -rw-r--r-- 2 root root 255 Jan  6  2007 /etc/crontab
 654687 lrwxrwxrwx 1 root root  12 Oct 22 13:58 /root/crontab2 -> /etc/crontab

由上表的结果我们可以知道两个档案指向不同的 inode 号码，当然就是两个独立的档案存在！ 而且连结档的重要内容就是他会写上目标档案的‘档名’， 你可以发现为什么上表中连结档的大小为 12 bytes 呢？ 因为箭头(-->)右边的档名‘/etc/crontab’总共有 12 个英文，每个英文占用 1 个 byes ，所以档案大小就是 12bytes了！

关于上述的说明，我们以如下图示来解释：

符号连结的档案读取示意图
图 2.2.2、符号连结的档案读取示意图

由 1 号 inode 读取到连结档的内容仅有档名，根据档名连结到正确的目录去取得目标档案的 inode ， 最终就能够读取到正确的资料了。你可以发现的是，如果目标档案(/etc/crontab)被删除了，那么整个环节就会无法继续进行下去， 所以就会发生无法透过连结档读取的问题了！

这里还是得特别留意，这个 Symbolic Link 与 Windows 的捷径可以给他划上等号，由 Symbolic link 所建立的档案为一个独立的新的档案，所以会占用掉 inode 与 block 喔！

由上面的说明来看，似乎 hard link 比较安全，因为即使某一个目录下的关连资料被杀掉了， 也没有关系，只要有任何一个目录下存在着关连资料，那么该档案就不会不见！举上面的例子来说，我的 /etc/crontab 与 /root/crontab 指向同一个档案，如果我删除了 /etc/crontab 这个档案，该删除的动作其实只是将 /etc 目录下关于 crontab 的关连资料拿掉而已， crontab 所在的 inode 与 block 其实都没有被变动喔！

不过由于 Hard Link 的限制太多了，包括无法做‘目录’的 link ， 所以在用途上面是比较受限的！反而是 Symbolic Link 的使用方面较广喔！好了， 说的天花乱坠，看你也差不多快要昏倒了！没关系，实作一下就知道怎么回事了！要制作连结档就必须要使用 ln 这个指令呢！

[root@www ~]# ln [-sf] 来源档 目标档
选项与参数：
-s  ：如果不加任何参数就进行连结，那就是hard link，至于 -s 就是symbolic link
-f  ：如果 目标档 存在时，就主动的将目标档直接移除后再建立！

范例一：将 /etc/passwd 复制到 /tmp 底下，并且观察 inode 与 block

[root@www ~]# cd /tmp
[root@www tmp]# cp -a /etc/passwd .
[root@www tmp]# du -sb ; df -i .
18340   .  <==先注意一下这里的容量是多少！
Filesystem            Inodes   IUsed   IFree IUse% Mounted on
/dev/hdc2            2560864  149738 2411126    6% /

# 利用 du 与 df 来检查一下目前的参数～那个 du -sb
# 是计算整个 /tmp 底下有多少 bytes 的容量啦！

范例二：将 /tmp/passwd 制作 hard link 成为 passwd-hd 档案，并观察档案与容量
[root@www tmp]# ln passwd passwd-hd
[root@www tmp]# du -sb ; df -i .
18340   .
Filesystem            Inodes   IUsed   IFree IUse% Mounted on
/dev/hdc2            2560864  149738 2411126    6% /

# 仔细看，即使多了一个档案在 /tmp 底下，整个 inode 与 block 的容量并没有改变！

[root@www tmp]# ls -il passwd*
586361 -rw-r--r-- 2 root root 1945 Sep 29 02:21 passwd
586361 -rw-r--r-- 2 root root 1945 Sep 29 02:21 passwd-hd

# 原来是指向同一个 inode 啊！这是个重点啊！另外，那个第二栏的连结数也会增加！

范例三：将 /tmp/passwd 建立一个符号连结
[root@www tmp]# ln -s passwd passwd-so
[root@www tmp]# ls -li passwd*
586361 -rw-r--r-- 2 root root 1945 Sep 29 02:21 passwd
586361 -rw-r--r-- 2 root root 1945 Sep 29 02:21 passwd-hd
586401 lrwxrwxrwx 1 root root    6 Oct 22 14:18 passwd-so -> passwd

# passwd-so 指向的 inode number 不同了！这是一个新的档案～这个档案的内容是指向
# passwd 的。passwd-so 的大小是 6bytes ，因为 passwd 共有六个字元之故

[root@www tmp]# du -sb ; df -i .
18346   .
Filesystem            Inodes   IUsed   IFree IUse% Mounted on
/dev/hdc2            2560864  149739 2411125    6% /
# 呼呼！整个容量与 inode 使用数都改变啰～确实如此啊！

范例四：删除原始档案 passwd ，其他两个档案是否能够开启？

[root@www tmp]# rm passwd
[root@www tmp]# cat passwd-hd
......正常显示完毕！
[root@www tmp]# cat passwd-so
cat: passwd-so: No such file or directory
[root@www tmp]# ll passwd*
-rw-r--r-- 1 root root 1945 Sep 29 02:21 passwd-hd
lrwxrwxrwx 1 root root    6 Oct 22 14:18 passwd-so -> passwd

# 怕了吧！符号连结果然无法开启！另外，如果符号连结的目标档案不存在，
# 其实档名的部分就会有特殊的颜色显示喔！
Tips:
还记得第六章当中，我们提到的 /tmp 这个目录是干嘛用的吗？是给大家作为暂存档用的啊！ 所以，您会发现，过去我们在进行测试时，都会将资料移动到 /tmp 底下去练习～ 嘿嘿！因此，有事没事，记得将 /tmp 底下的一些怪异的资料清一清先！ 		鸟哥的图示

要注意啰！使用 ln 如果不加任何参数的话，那么就是 Hard Link 啰！如同范例二的情况，增加了 hard link 之后，可以发现使用 ls -l 时，显示的 link 那一栏属性增加了！而如果这个时候砍掉 passwd 会发生什么事情呢？passwd-hd 的内容还是会跟原来 passwd 相同，但是 passwd-so 就会找不到该档案啦！

而如果 ln 使用 -s 的参数时，就做成差不多是 Windows 底下的‘捷径’的意思。当你修改 Linux 下的 symbolic link 档案时，则更动的其实是‘原始档’， 所以不论你的这个原始档被连结到哪里去，只要你修改了连结档，原始档就跟着变啰！ 以上面为例，由于你使用 -s 的参数建立一个名为 passwd-so 的档案，则你修改 passwd-so 时，其内容与 passwd 完全相同，并且，当你按下储存之后，被改变的将是 passwd 这个档案！

此外，如果你做了底下这样的连结：

ln -s /bin /root/bin

那么如果你进入 /root/bin 这个目录下，‘请注意呦！该目录其实是 /bin 这个目录，因为你做了连结档了！’所以，如果你进入 /root/bin 这个刚刚建立的连结目录， 并且将其中的资料杀掉时，嗯！ /bin 里面的资料就通通不见了！这点请千万注意！所以赶紧利用‘rm /root/bin ’ 将这个连结档删除吧！

基本上， Symbolic link 的用途比较广，所以您要特别留意 symbolic link 的用法呢！未来一定还会常常用到的啦！

  • 关于目录的 link 数量：

或许您已经发现了，那就是，当我们以 hard link 进行‘档案的连结’时，可以发现，在 ls -l 所显示的第二栏位会增加一才对，那么请教，如果建立目录时，他预设的 link 数量会是多少？ 让我们来想一想，一个‘空目录’里面至少会存在些什么？呵呵！就是存在 . 与 .. 这两个目录啊！ 那么，当我们建立一个新目录名称为 /tmp/testing 时，基本上会有三个东西，那就是：

  • /tmp/testing
  • /tmp/testing/.
  • /tmp/testing/..

而其中 /tmp/testing 与 /tmp/testing/. 其实是一样的！都代表该目录啊～而 /tmp/testing/.. 则代表 /tmp 这个目录，所以说，当我们建立一个新的目录时， ‘新的目录的 link 数为 2 ，而上层目录的 link 数则会增加 1 ’ 不信的话，我们来作个测试看看：

[root@www ~]# ls -ld /tmp
drwxrwxrwt 5 root root 4096 Oct 22 14:22 /tmp
[root@www ~]# mkdir /tmp/testing1

[root@www ~]# ls -ld /tmp
drwxrwxrwt 6 root root 4096 Oct 22 14:37 /tmp
[root@www ~]# ls -ld /tmp/testing1
drwxr-xr-x 2 root root 4096 Oct 22 14:37 /tmp/testing1

瞧！原本的所谓上层目录 /tmp 的 link 数量由 5 增加为 6 ，至于新目录 /tmp/testing 则为 2 ，这样可以理解目录的 link 数量的意义了吗？ ^_^

大标题的图示 磁碟的分割、格式化、检验与挂载：

对于一个系统管理者( root )而言，磁碟的的管理是相当重要的一环，尤其近来硬碟已经渐渐的被当成是消耗品了 ..... 如果我们想要在系统里面新增一颗硬碟时，应该有哪些动作需要做的呢：

  1. 对磁碟进行分割，以建立可用的 partition ；
  2. 对该 partition 进行格式化( format )，以建立系统可用的 filesystem；
  3. 若想要仔细一点，则可对刚刚建立好的 filesystem 进行检验；
  4. 在 Linux 系统上，需要建立挂载点 ( 亦即是目录 )，并将他挂载上来；

当然啰，在上述的过程当中，还有很多需要考虑的，例如磁碟分割槽 (partition) 需要定多大？ 是否需要加入 journal 的功能？inode 与 block 的数量应该如何规划等等的问题。但是这些问题的决定， 都需要与你的主机用途来加以考量的～所以，在这个小节里面，鸟哥仅会介绍几个动作而已， 更详细的设定值，则需要以你未来的经验来参考啰！

小标题的图示 磁碟分割： fdisk
[root@www ~]# fdisk [-l] 装置名称
选项与参数：
-l  ：输出后面接的装置所有的 partition 内容。若仅有 fdisk -l 时，
      则系统将会把整个系统内能够搜寻到的装置的 partition 均列出来。

范例：找出你系统中的根目录所在磁碟，并查阅该硬碟内的相关资讯
[root@www ~]# df /            <==注意：重点在找出磁碟档名而已
Filesystem           1K-blocks      Used Available Use% Mounted on
/dev/hdc2              9920624   3823168   5585388  41% /

[root@www ~]# fdisk /dev/hdc  <==仔细看，不要加上数字喔！

The number of cylinders for this disk is set to 5005.
There is nothing wrong with that, but this is larger than 1024,
and could in certain setups cause problems with:
1) software that runs at boot time (e.g., old versions of LILO)
2) booting and partitioning software from other OSs
   (e.g., DOS FDISK, OS/2 FDISK)

Command (m for help):     <==等待你的输入！

由于每个人的环境都不一样，因此每部主机的磁碟数量也不相同。所以你可以先使用 df 这个指令找出可用磁碟档名， 然后再用 fdisk 来查阅。在你进入 fdisk 这支程式的工作画面后，如果您的硬碟太大的话(通常指磁柱数量多于 1024 以上)，就会出现如上讯息。这个讯息仅是在告知你，因为某些旧版的软体与作业系统并无法支援大于 1024 磁柱 (cylinter) 后的磁区使用，不过我们新版的 Linux 是没问题啦！底下继续来看看 fdisk 内如何操作相关动作吧！

Command (m for help): m   <== 输入 m 后，就会看到底下这些指令介绍
Command action
   a   toggle a bootable flag
   b   edit bsd disklabel
   c   toggle the dos compatibility flag
   d   delete a partition            <==删除一个partition
   l   list known partition types
   m   print this menu
   n   add a new partition           <==新增一个partition
   o   create a new empty DOS partition table
   p   print the partition table     <==在荧幕上显示分割表

   q   quit without saving changes   <==不储存离开fdisk程式
   s   create a new empty Sun disklabel
   t   change a partition's system id
   u   change display/entry units
   v   verify the partition table
   w   write table to disk and exit  <==将刚刚的动作写入分割表
   x   extra functionality (experts only)

老实说，使用 fdisk 这支程式是完全不需要背指令的！如同上面的表格中，你只要按下 m 就能够看到所有的动作！ 比较重要的动作在上面已经用底线画出来了，你可以参考看看。其中比较不一样的是‘q 与 w’这两个玩意儿！ 不管你进行了什么动作，只要离开 fdisk 时按下‘q’，那么所有的动作‘都不会生效！’相反的， 按下‘w’就是动作生效的意思。所以，你可以随便玩 fdisk ，只要离开时按下的是‘q’即可。 ^_^！ 好了，先来看看分割表资讯吧！

Command (m for help): p  <== 这里可以输出目前磁碟的状态

Disk /dev/hdc: 41.1 GB, 41174138880 bytes        <==这个磁碟的档名与容量
255 heads, 63 sectors/track, 5005 cylinders      <==磁头、磁区与磁柱大小

Units = cylinders of 16065 * 512 = 8225280 bytes <==每个磁柱的大小

   Device Boot      Start         End      Blocks   Id  System
/dev/hdc1   *           1          13      104391   83  Linux
/dev/hdc2              14        1288    10241437+  83  Linux
/dev/hdc3            1289        1925     5116702+  83  Linux
/dev/hdc4            1926        5005    24740100    5  Extended
/dev/hdc5            1926        2052     1020096   82  Linux swap / Solaris
# 装置档名 开机区否 开始磁柱    结束磁柱  1K大小容量 磁碟分割槽内的系统

Command (m for help): q

# 想要不储存离开吗？按下 q 就对了！不要随便按 w 啊！

使用‘ p ’可以列出目前这颗磁碟的分割表资讯，这个资讯的上半部在显示整体磁碟的状态。 以鸟哥这颗磁碟为例，这个磁碟共有 41.1GB 左右的容量，共有 5005 个磁柱，每个磁柱透过 255 个磁头在管理读写， 每个磁头管理 63 个磁区，而每个磁区的大小均为 512bytes ，因此每个磁柱为‘ 255*63*512 = 16065*512 = 8225280bytes ’。

下半部的分割表资讯主要在列出每个分割槽的个别资讯项目。每个项目的意义为：

  • Device：装置档名，依据不同的磁碟介面/分割槽位置而变。
  • Boot：是否为开机启动区块？通常 Windows 系统的 C 需要这块！
  • Start, End：这个分割槽在哪个磁柱号码之间，可以决定此分割槽的大小；
  • Blocks：就是以 1K 为单位的容量。如上所示，/dev/hdc1 大小为104391K = 102MB
  • ID, System：代表这个分割槽内的档案系统应该是啥！不过这个项目只是一个提示而已， 不见得真的代表此分割槽内的档案系统喔！

从上表我们可以发现几件事情：

  • 整部磁碟还可以进行额外的分割，因为最大磁柱为 5005 ，但只使用到 2052 号而已；
  • /dev/hdc5 是由 /dev/hdc4 分割出来的，因为 /dev/hdc4 为 Extended，且 /dev/hdc5 磁柱号码在 /dev/hdc4 之内；

fdisk 还可以直接秀出系统内的所有 partition 喔！举例来说，鸟哥刚刚插入一个 USB 磁碟到这部 Linux 系统中， 那该如何观察 (1)这个磁碟的代号与 (2)这个磁碟的分割槽呢？

范例：查阅目前系统内的所有 partition 有哪些？
[root@www ~]# fdisk -l

Disk /dev/hdc: 41.1 GB, 41174138880 bytes
255 heads, 63 sectors/track, 5005 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes

   Device Boot      Start         End      Blocks   Id  System
/dev/hdc1   *           1          13      104391   83  Linux
/dev/hdc2              14        1288    10241437+  83  Linux
/dev/hdc3            1289        1925     5116702+  83  Linux
/dev/hdc4            1926        5005    24740100    5  Extended
/dev/hdc5            1926        2052     1020096   82  Linux swap / Solaris

Disk /dev/sda: 8313 MB, 8313110528 bytes
59 heads, 58 sectors/track, 4744 cylinders
Units = cylinders of 3422 * 512 = 1752064 bytes

   Device Boot      Start         End      Blocks   Id  System
/dev/sda1               1        4745     8118260    b  W95 FAT32

由上表的资讯我们可以看到我有两颗磁碟，磁碟档名为‘/dev/hdc 与 /dev/sda’，/dev/hdc 已经在上面谈过了， 至于 /dev/sda 则有 8GB 左右的容量，且全部的磁柱都已经分割给 /dev/sda1 ，该档案系统应该为 Windows 的 FAT 档案系统。这样很容易查阅到分割方面的资讯吧！

这个 fdisk 只有 root 才能执行，此外，请注意， 使用的‘装置档名’请不要加上数字，因为 partition 是针对‘整个硬碟装置’而不是某个 partition 呢！所以执行‘ fdisk /dev/hdc1 ’ 就会发生错误啦！要使用 fdisk /dev/hdc 才对！那么我们知道可以利用 fdisk 来查阅硬碟的 partition 资讯外，底下再来说一说进入 fdisk 之后的几个常做的工作！

Tips:
再次强调，你可以使用 fdisk 在您的硬碟上面胡搞瞎搞的进行实际操作，都不打紧， 但是请‘千万记住，不要按下 w 即可！’离开的时候按下 q 就万事无妨啰！ 		鸟哥的图示
  • 删除磁碟分割槽

如果你是按照鸟哥建议的方式去安装你的 CentOS ，那么你的磁碟应该会预留一块容量来做练习的。 实际练习新增硬碟之前，我们先来玩一玩恐怖的删除好了～如果想要测试一下如何将你的 /dev/hdc 全部的分割槽删除，应该怎么做？

  1. fdisk /dev/hdc ：先进入 fdisk 画面；
  2. p ：先看一下分割槽的资讯，假设要杀掉 /dev/hdc1；
  3. d ：这个时候会要你选择一个 partition ，就选 1 啰！
  4. w (or) q ：按 w 可储存到磁碟资料表中，并离开 fdisk ；当然啰， 如果你反悔了，呵呵，直接按下 q 就可以取消刚刚的删除动作了！
# 练习一： 先进入 fdisk 的画面当中去！
[root@www ~]# fdisk /dev/hdc

# 练习二： 先看看整个分割表的情况是如何
Command (m for help): p

Disk /dev/hdc: 41.1 GB, 41174138880 bytes
255 heads, 63 sectors/track, 5005 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes

   Device Boot      Start         End      Blocks   Id  System
/dev/hdc1   *           1          13      104391   83  Linux
/dev/hdc2              14        1288    10241437+  83  Linux
/dev/hdc3            1289        1925     5116702+  83  Linux
/dev/hdc4            1926        5005    24740100    5  Extended
/dev/hdc5            1926        2052     1020096   82  Linux swap / Solaris

# 练习三： 按下 d 给他删除吧！

Command (m for help): d
Partition number (1-5): 4

Command (m for help): d
Partition number (1-4): 3

Command (m for help): p

Disk /dev/hdc: 41.1 GB, 41174138880 bytes
255 heads, 63 sectors/track, 5005 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes

   Device Boot      Start         End      Blocks   Id  System
/dev/hdc1   *           1          13      104391   83  Linux
/dev/hdc2              14        1288    10241437+  83  Linux
# 因为 /dev/hdc5 是由 /dev/hdc4 所衍生出来的逻辑分割槽，因此 /dev/hdc4 被删除，
# /dev/hdc5 就自动不见了！最终就会剩下两个分割槽而已喔！

Command (m for help): q
# 鸟哥这里仅是做一个练习而已，所以，按下 q 就能够离开啰～

  • 练习新增磁碟分割槽

新增磁碟分割槽有好多种情况，因为新增 Primary / Extended / Logical 的显示结果都不太相同。 底下我们先将 /dev/hdc 全部删除成为干净未分割的磁碟，然后依序新增给大家瞧瞧！

# 练习一： 进入 fdisk 的分割软体画面中，并删除所有分割槽：
[root@www ~]# fdisk /dev/hdc
Command (m for help): d
Partition number (1-5): 4

Command (m for help): d
Partition number (1-4): 3

Command (m for help): d
Partition number (1-4): 2

Command (m for help): d

Selected partition 1
# 由于最后仅剩下一个 partition ，因此系统主动选取这个 partition 删除去！

# 练习二： 开始新增，我们先新增一个 Primary  的分割槽，且指定为 4 号看看！
Command (m for help): n
Command action            <==因为是全新磁碟，因此只会问extended/primary而已
   e   extended
   p   primary partition (1-4)
p                         <==选择 Primary 分割槽

Partition number (1-4): 4 <==设定为 4 号！
First cylinder (1-5005, default 1): <==直接按下[enter]按键决定！
Using default value 1               <==启始磁柱就选用预设值！
Last cylinder or +size or +sizeM or +sizeK (1-5005, default 5005): +512M
# 这个地方有趣了！我们知道 partition 是由 n1 到 n2 的磁柱号码 (cylinder)，
# 但磁柱的大小每颗磁碟都不相同，这个时候可以填入 +512M 来让系统自动帮我们找出
# ‘最接近 512M 的那个 cylinder 号码’！因为不可能刚好等于 512MBytes 啦！
# 如上所示：这个地方输入的方式有两种：

# 1) 直接输入磁柱的号码，你得要自己计算磁柱/分割槽的大小才行；

# 2) 用 +XXM 来输入分割槽的大小，让系统自己捉磁柱的号码。
#    +与M是必须要有的，XX为数字

Command (m for help): p

Disk /dev/hdc: 41.1 GB, 41174138880 bytes
255 heads, 63 sectors/track, 5005 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes

   Device Boot      Start         End      Blocks   Id  System
/dev/hdc4               1          63      506016   83  Linux
# 注意！只有 4 号！ 1 ~ 3 保留下来了！

# 练习三： 继续新增一个，这次我们新增 Extended 的分割槽好了！
Command (m for help): n
Command action
   e   extended
   p   primary partition (1-4)
e    <==选择的是 Extended 喔！
Partition number (1-4): 1
First cylinder (64-5005, default 64): <=[enter]

Using default value 64
Last cylinder or +size or +sizeM or +sizeK (64-5005, default 5005): <=[enter]
Using default value 5005
# 还记得我们在第三章的磁碟分割表曾经谈到过的，延伸分割最好能够包含所有
# 未分割的区间；所以在这个练习中，我们将所有未配置的磁柱都给了这个分割槽喔！
# 所以在开始/结束磁柱的位置上，按下两个[enter]用预设值即可！

Command (m for help): p

Disk /dev/hdc: 41.1 GB, 41174138880 bytes
255 heads, 63 sectors/track, 5005 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes

   Device Boot      Start         End      Blocks   Id  System
/dev/hdc1              64        5005    39696615    5  Extended
/dev/hdc4               1          63      506016   83  Linux

# 如上所示，所有的磁柱都在 /dev/hdc1 里面啰！

# 练习四： 这次我们随便新增一个 2GB 的分割槽看看！
Command (m for help): n
Command action
   l   logical (5 or over)     <==因为已有 extended ，所以出现 logical 分割槽
   p   primary partition (1-4)
p   <==偷偷玩一下，能否新增主要分割槽

Partition number (1-4): 2
No free sectors available   <==肯定不行！因为没有多余的磁柱可供配置

Command (m for help): n
Command action
   l   logical (5 or over)
   p   primary partition (1-4)
l   <==乖乖使用逻辑分割槽吧！
First cylinder (64-5005, default 64): <=[enter]

Using default value 64
Last cylinder or +size or +sizeM or +sizeK (64-5005, default 5005): +2048M

Command (m for help): p

Disk /dev/hdc: 41.1 GB, 41174138880 bytes
255 heads, 63 sectors/track, 5005 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes

   Device Boot      Start         End      Blocks   Id  System
/dev/hdc1              64        5005    39696615    5  Extended
/dev/hdc4               1          63      506016   83  Linux
/dev/hdc5              64         313     2008093+  83  Linux
# 这样就新增了 2GB 的分割槽，且由于是 logical ，所以由 5 号开始！
Command (m for help): q
# 鸟哥这里仅是做一个练习而已，所以，按下 q 就能够离开啰～

上面的练习非常重要！您得要自行练习一下比较好！注意，不要按下 w 喔！会让你的系统损毁的！ 由上面的一连串练习中，最重要的地方其实就在于建立分割槽的形式( primary/extended/logical )以及分割槽的大小了！一般来说建立分割槽的形式会有底下的数种状况：

  • 1-4 号尚有剩余，且系统未有 extended：
    此时会出现让你挑选 Primary / Extended 的项目，且你可以指定 1~4 号间的号码；

  • 1-4 号尚有剩余，且系统有 extended：
    此时会出现让你挑选 Primary / Logical 的项目；若选择 p 则你还需要指定 1~4 号间的号码； 若选择 l(L的小写) 则不需要设定号码，因为系统会自动指定逻辑分割槽的档名号码；

  • 1-4 没有剩余，且系统有 extended：
    此时不会让你挑选分割槽类型，直接会进入 logical 的分割槽形式。

例题：
请依照你的系统情况，建立一个大约 1GB 左右的分割槽，并显示该分割槽的相关资讯：
答：
鸟哥的磁碟为 /dev/hdc ，尚有剩余磁柱号码，因此可以这样做：
[root@www ~]# fdisk /dev/hdc
Command (m for help): n
First cylinder (2053-5005, default 2053): <==[enter]
Using default value 2053
Last cylinder or +size or +sizeM or +sizeK (2053-5005, default 5005): +2048M

Command (m for help): p

Disk /dev/hdc: 41.1 GB, 41174138880 bytes
255 heads, 63 sectors/track, 5005 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes

   Device Boot      Start         End      Blocks   Id  System
/dev/hdc1   *           1          13      104391   83  Linux
/dev/hdc2              14        1288    10241437+  83  Linux
/dev/hdc3            1289        1925     5116702+  83  Linux
/dev/hdc4            1926        5005    24740100    5  Extended
/dev/hdc5            1926        2052     1020096   82  Linux swap / Solaris
/dev/hdc6            2053        2302     2008093+  83  Linux

Command (m for help): w
The partition table has been altered!

Calling ioctl() to re-read partition table.

WARNING: Re-reading the partition table failed with error 16: Device or
resource busy.
The kernel still uses the old table.
The new table will be used at the next reboot.
Syncing disks. <==见鬼了！竟然需要 reboot 才能够生效！我可不要重新开机！

[root@www ~]# partprobe  <==强制让核心重新捉一次 partition table
在这个实作题中，请务必要按下‘ w ’这个动作！因为我们实际上确实要建立这个分割槽嘛！ 但请仔细看一下最后的警告讯息，因为我们的磁碟无法卸载(因为含有根目录)，所以核心无法重新取得分割表资讯， 因此此时系统会要求我们重新开机(reboot)以更新核心的分割表资讯才行。

如上的练习中，最终写入分割表后竟然会让核心无法捉到分割表资讯！此时你可以直接使用 reboot 来处理， 也可以使用 GNU 推出的工具程式来处置，那就是 partprobe 这个指令。这个指令的执行很简单， 他仅是告知核心必须要读取新的分割表而已，因此并不会在荧幕上出现任何资讯才是！ 这样一来，我们就不需要 reboot 啰！

  • 操作环境的说明

以 root 的身份进行硬碟的 partition 时，最好是在单人维护模式底下比较安全一些， 此外，在进行 fdisk 的时候，如果该硬碟某个 partition 还在使用当中， 那么很有可能系统核心会无法重新载入硬碟的 partition table ，解决的方法就是将该使用中的 partition 给他卸载，然后再重新进入 fdisk 一遍，重新写入 partition table ，那么就可以成功啰！

  • 注意事项：

另外在实作过程中请特别注意，因为 SATA 硬碟最多能够支援到 15 号的分割槽， IDE 则可以支援到 63 号。 但目前大家常见的系统都是 SATA 磁碟，因此在练习的时候千万不要让你的分割槽超过 15 号！ 否则即使你还有剩余的磁柱容量，但还是会无法继续进行分割的喔！

另外需要特别留意的是，fdisk 没有办法处理大于 2TB 以上的磁碟分割槽！ 这个问题比较严重！因为虽然 Ext3 档案系统已经支援达到 16TB 以上的磁碟，但是分割指令却无法支援。 时至今日(2009)所有的硬体价格大跌，硬碟也已经出到单颗 1TB 之谱，若加上磁碟阵列 (RAID) ， 高于 2TB 的磁碟系统应该会很常见！此时你就得使用 parted 这个指令了！我们会在本章最后谈一谈这个指令的用法。

小标题的图示 磁碟格式化

分割完毕后自然就是要进行档案系统的格式化啰！格式化的指令非常的简单，那就是‘make filesystem, mkfs’ 这个指令啦！这个指令其实是个综合的指令，他会去呼叫正确的档案系统格式化工具软体！ 不啰唆，让我们来瞧瞧吧！

  • mkfs
[root@www ~]# mkfs [-t 档案系统格式] 装置档名
选项与参数：
-t  ：可以接档案系统格式，例如 ext3, ext2, vfat 等(系统有支援才会生效)

范例一：请将上个小节当中所制作出来的 /dev/hdc6 格式化为 ext3 档案系统
[root@www ~]# mkfs -t ext3 /dev/hdc6
mke2fs 1.39 (29-May-2006)
Filesystem label=                <==这里指的是分割槽的名称(label)

OS type: Linux
Block size=4096 (log=2)          <==block 的大小设定为 4K
Fragment size=4096 (log=2)
251392 inodes, 502023 blocks     <==由此设定决定的inode/block数量
25101 blocks (5.00%) reserved for the super user
First data block=0
Maximum filesystem blocks=515899392
16 block groups
32768 blocks per group, 32768 fragments per group
15712 inodes per group
Superblock backups stored on blocks:
        32768, 98304, 163840, 229376, 294912

Writing inode tables: done
Creating journal (8192 blocks): done <==有日志记录
Writing superblocks and filesystem accounting information: done

This filesystem will be automatically checked every 34 mounts or
180 days, whichever comes first.  Use tune2fs -c or -i to override.
# 这样就建立起来我们所需要的 Ext3 档案系统了！简单明了！

[root@www ~]# mkfs[tab][tab]
mkfs         mkfs.cramfs  mkfs.ext2    mkfs.ext3    mkfs.msdos   mkfs.vfat
# 按下两个[tab]，会发现 mkfs 支援的档案格式如上所示！可以格式化 vfat 喔！

mkfs 其实是个综合指令而已，事实上如同上表所示，当我们使用‘ mkfs -t ext3 ...’时， 系统会去呼叫 mkfs.ext3 这个指令来进行格式化的动作啦！若如同上表所展现的结果， 那么鸟哥这个系统支援的档案系统格式化工具有‘cramfs, ext2, ext3, msdoc, vfat’等， 而最常用的应该是 ext3, vfat 两种啦！ vfat 可以用在 Windows/Linux 共用的 USB 随身碟啰。

例题：
将刚刚的 /dev/hdc6 格式化为 Windows 可读的 vfat 格式吧！
答：
mkfs -t vfat /dev/hdc6

在格式化为 Ext3 的范例中，我们可以发现结果里面含有非常多的资讯，由于我们没有详细指定档案系统的细部项目， 因此系统会使用预设值来进行格式化。其中比较重要的部分为：档案系统的标头(Label)、Block的大小以及 inode 的数量。 如果你要指定这些东西，就得要了解一下 Ext2/Ext3 的公用程式，亦即 mke2fs 这个指令啰！

  • mke2fs
[root@www ~]# mke2fs [-b block大小] [-i block大小] [-L 标头] [-cj] 装置
选项与参数：
-b  ：可以设定每个 block 的大小，目前支援 1024, 2048, 4096 bytes 三种；
-i  ：多少容量给予一个 inode 呢？
-c  ：检查磁碟错误，仅下达一次 -c 时，会进行快速读取测试；
      如果下达两次 -c -c 的话，会测试读写(read-write)，会很慢～
-L  ：后面可以接标头名称 (Label)，这个 label 是有用的喔！e2label指令介绍会谈到～
-j  ：本来 mke2fs 是 EXT2 ，加上 -j 后，会主动加入 journal 而成为 EXT3。

mke2fs 是一个很详细但是很麻烦的指令！因为里面的细部设定太多了！现在我们进行如下的假设：

  • 这个档案系统的标头设定为：vbird_logical
  • 我的 block 指定为 2048 大小；
  • 每 8192 bytes 分配一个 inode ；
  • 建置为 journal 的 Ext3 档案系统。

开始格式化 /dev/hdc6 结果会变成如下所示：

[root@www ~]# mke2fs -j -L "vbird_logical" -b 2048 -i 8192 /dev/hdc6

mke2fs 1.39 (29-May-2006)
Filesystem label=vbird_logical
OS type: Linux
Block size=2048 (log=1)
Fragment size=2048 (log=1)
251968 inodes, 1004046 blocks
50202 blocks (5.00%) reserved for the super user
First data block=0
Maximum filesystem blocks=537919488
62 block groups
16384 blocks per group, 16384 fragments per group
4064 inodes per group
Superblock backups stored on blocks:
        16384, 49152, 81920, 114688, 147456, 409600, 442368, 802816

Writing inode tables: done
Creating journal (16384 blocks): done
Writing superblocks and filesystem accounting information: done
# 比较看看，跟上面的范例用预设值的结果，有什么不一样的啊？

其实 mke2fs 所使用的各项选项/参数也可以用在‘ mkfs -t ext3 ... ’后面，因为最终使用的公用程式是相同的啦！ 特别要注意的是 -b, -i 及 -j 这几个选项，尤其是 -j 这个选项，当没有指定 -j 的时候， mke2fs 使用 ext2 为格式化档案格式，若加入 -j 时，则格式化为 ext3 这个 Journaling 的 filesystem 呦！

老实说，如果没有特殊需求的话，使用‘ mkfs -t ext3....’不但容易记忆，而且就非常好用啰！

小标题的图示 磁碟检验： fsck, badblocks

由于系统在运作时谁也说不准啥时硬体或者是电源会有问题，所以‘当机’可能是难免的情况(不管是硬体还是软体)。 现在我们知道档案系统运作时会有硬碟与记忆体资料非同步的状况发生，因此莫名其妙的当机非常可能导致档案系统的错乱。 问题来啦，如果档案系统真的发生错乱的话，那该如何是好？就...挽救啊！此时那个好用的 filesystem check, fsck 就得拿来仔细瞧瞧啰。

  • fsck
[root@www ~]# fsck [-t 档案系统] [-ACay] 装置名称
选项与参数：
-t  ：如同 mkfs 一样，fsck 也是个综合软体而已！因此我们同样需要指定档案系统。
      不过由于现今的 Linux 太聪明了，他会自动的透过 superblock 去分辨档案系统，
      因此通常可以不需要这个选项的啰！请看后续的范例说明。
-A  ：依据 /etc/fstab 的内容，将需要的装置扫瞄一次。/etc/fstab 于下一小节说明，
      通常开机过程中就会执行此一指令了。
-a  ：自动修复检查到的有问题的磁区，所以你不用一直按 y 啰！
-y  ：与 -a 类似，但是某些 filesystem 仅支援 -y 这个参数！
-C  ：可以在检验的过程当中，使用一个长条图来显示目前的进度！

EXT2/EXT3 的额外选项功能：(e2fsck 这支指令所提供)
-f  ：强制检查！一般来说，如果 fsck 没有发现任何 unclean 的旗标，不会主动进入
      细部检查的，如果您想要强制 fsck 进入细部检查，就得加上 -f 旗标啰！
-D  ：针对档案系统下的目录进行最佳化配置。

范例一：强制的将前面我们建立的 /dev/hdc6 这个装置给他检验一下！
[root@www ~]# fsck -C -f -t ext3 /dev/hdc6

fsck 1.39 (29-May-2006)
e2fsck 1.39 (29-May-2006)
Pass 1: Checking inodes, blocks, and sizes
Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
vbird_logical: 11/251968 files (9.1% non-contiguous), 36926/1004046 blocks
# 如果没有加上 -f 的选项，则由于这个档案系统不曾出现问题，
# 检查的经过非常快速！若加上 -f 强制检查，才会一项一项的显示过程。

范例二：系统有多少档案系统支援的 fsck 软体？
[root@www ~]# fsck[tab][tab]
fsck         fsck.cramfs  fsck.ext2    fsck.ext3    fsck.msdos   fsck.vfat

这是用来检查与修正档案系统错误的指令。注意：通常只有身为 root 且你的档案系统有问题的时候才使用这个指令，否则在正常状况下使用此一指令， 可能会造成对系统的危害！通常使用这个指令的场合都是在系统出现极大的问题，导致你在 Linux 开机的时候得进入单人单机模式下进行维护的行为时，才必须使用此一指令！

另外，如果你怀疑刚刚格式化成功的硬碟有问题的时后，也可以使用 fsck 来检查一硬碟呦！其实就有点像是 Windows 的 scandisk 啦！此外，由于 fsck 在扫瞄硬碟的时候，可能会造成部分 filesystem 的损坏，所以‘执行 fsck 时， 被检查的 partition 务必不可挂载到系统上！亦即是需要在卸载的状态喔！’

不知道你还记不记得第六章的目录配置中我们提过， ext2/ext3 档案系统的最顶层(就是挂载点那个目录底下)会存在一个‘lostt+found’的目录吧！ 该目录就是在当你使用 fsck 检查档案系统后，若出现问题时，有问题的资料会被放置到这个目录中喔！ 所以理论上这个目录不应该会有任何资料，若系统自动产生资料在里面，那...你就得特别注意你的档案系统啰！

另外，我们的系统实际执行的 fsck 指令，其实是呼叫 e2fsck 这个软体啦！可以 man e2fsck 找到更多的选项辅助喔！

  • badblocks
[root@www ~]# badblocks -[svw] 装置名称
选项与参数：
-s  ：在荧幕上列出进度
-v  ：可以在荧幕上看到进度
-w  ：使用写入的方式来测试，建议不要使用此一参数，尤其是待检查的装置已有档案时！

[root@www ~]# badblocks -sv /dev/hdc6
Checking blocks 0 to 2008093
Checking for bad blocks (read-only test): done
Pass completed, 0 bad blocks found.

刚刚谈到的 fsck 是用来检验档案系统是否出错，至于 badblocks 则是用来检查硬碟或软碟磁区有没有坏轨的指令！ 由于这个指令其实可以透过‘ mke2fs -c 装置档名 ’在进行格式化的时候处理磁碟表面的读取测试， 因此目前大多不使用这个指令啰！

小标题的图示 磁碟挂载与卸载

我们在本章一开始时的挂载点的意义当中提过挂载点是目录， 而这个目录是进入磁碟分割槽(其实是档案系统啦！)的入口就是了。不过要进行挂载前，你最好先确定几件事：

  • 单一档案系统不应该被重复挂载在不同的挂载点(目录)中；
  • 单一目录不应该重复挂载多个档案系统；
  • 要作为挂载点的目录，理论上应该都是空目录才是。

尤其是上述的后两点！如果你要用来挂载的目录里面并不是空的，那么挂载了档案系统之后，原目录下的东西就会暂时的消失。 举个例子来说，假设你的 /home 原本与根目录 (/) 在同一个档案系统中，底下原本就有 /home/test 与 /home/vbird 两个目录。然后你想要加入新的硬碟，并且直接挂载 /home 底下，那么当你挂载上新的分割槽时，则 /home 目录显示的是新分割槽内的资料，至于原先的 test 与 vbird 这两个目录就会暂时的被隐藏掉了！注意喔！并不是被覆盖掉， 而是暂时的隐藏了起来，等到新分割槽被卸载之后，则 /home 原本的内容就会再次的跑出来啦！

而要将档案系统挂载到我们的 Linux 系统上，就要使用 mount 这个指令啦！ 不过，这个指令真的是博大精深～粉难啦！我们学简单一点啊～ ^_^

[root@www ~]# mount -a
[root@www ~]# mount [-l]
[root@www ~]# mount [-t 档案系统] [-L Label名] [-o 额外选项] \
 [-n]  装置档名  挂载点
选项与参数：
-a  ：依照设定档 /etc/fstab 的资料将所有未挂载的磁碟都挂载上来
-l  ：单纯的输入 mount 会显示目前挂载的资讯。加上 -l 可增列 Label 名称！
-t  ：与 mkfs 的选项非常类似的，可以加上档案系统种类来指定欲挂载的类型。
      常见的 Linux 支援类型有：ext2, ext3, vfat, reiserfs, iso9660(光碟格式),
      nfs, cifs, smbfs(此三种为网路档案系统类型)
-n  ：在预设的情况下，系统会将实际挂载的情况即时写入 /etc/mtab 中，以利其他程式
      的运作。但在某些情况下(例如单人维护模式)为了避免问题，会刻意不写入。
      此时就得要使用这个 -n 的选项了。
-L  ：系统除了利用装置档名 (例如 /dev/hdc6) 之外，还可以利用档案系统的标头名称
      (Label)来进行挂载。最好为你的档案系统取一个独一无二的名称吧！
-o  ：后面可以接一些挂载时额外加上的参数！比方说帐号、密码、读写权限等：
      ro, rw:       挂载档案系统成为唯读(ro) 或可读写(rw)
      async, sync:  此档案系统是否使用同步写入 (sync) 或非同步 (async) 的
                    记忆体机制，请参考档案系统运作方式。预设为 async。
      auto, noauto: 允许此 partition 被以 mount -a 自动挂载(auto)
      dev, nodev:   是否允许此 partition 上，可建立装置档案？ dev 为可允许
      suid, nosuid: 是否允许此 partition 含有 suid/sgid 的档案格式？
      exec, noexec: 是否允许此 partition 上拥有可执行 binary 档案？
      user, nouser: 是否允许此 partition 让任何使用者执行 mount ？一般来说，
                    mount 仅有 root 可以进行，但下达 user 参数，则可让
                    一般 user 也能够对此 partition 进行 mount 。
      defaults:     预设值为：rw, suid, dev, exec, auto, nouser, and async
      remount:      重新挂载，这在系统出错，或重新更新参数时，很有用！

会不会觉得光是看这个指令的细部选项就快要昏倒了？如果有兴趣的话看一下 man mount ，那才会真的昏倒的。 事实上 mount 是个很万用的指令，他可以挂载 ext3/vfat/nfs 等档案系统，由于每种档案系统的资料并不相同， 想当然尔，详细的参数与选项自然也就不相同啦！不过实际应用时却简单的会让你想笑呢！ 看看底下的几个简单范例先！

  • 挂载Ext2/Ext3档案系统
范例一：用预设的方式，将刚刚建立的 /dev/hdc6 挂载到 /mnt/hdc6 上面！
[root@www ~]# mkdir /mnt/hdc6

[root@www ~]# mount /dev/hdc6 /mnt/hdc6
[root@www ~]# df
Filesystem           1K-blocks      Used Available Use% Mounted on
.....中间省略.....
/dev/hdc6              1976312     42072   1833836   3% /mnt/hdc6
# 看起来，真的有挂载！且档案大小约为 2GB 左右啦！

瞎密？竟然这么简单！利用‘mount 装置档名 挂载点’就能够顺利的挂载了！真是方便啊！ 为什么可以这么方便呢(甚至不需要使用 -t 这个选项)？由于档案系统几乎都有 superblock ， 我们的 Linux 可以透过分析 superblock 搭配 Linux 自己的驱动程式去测试挂载， 如果成功的套和了，就立刻自动的使用该类型的档案系统挂载起来啊！ 那么系统有没有指定哪些类型的 filesystem 才需要进行上述的挂载测试呢？ 主要是参考底下这两个档案：

  • /etc/filesystems：系统指定的测试挂载档案系统类型；
  • /proc/filesystems：Linux系统已经载入的档案系统类型。

那我怎么知道我的 Linux 有没有相关档案系统类型的驱动程式呢？我们 Linux 支援的档案系统之驱动程式都写在如下的目录中：

  • /lib/modules/$(uname -r)/kernel/fs/

例如 vfat 的驱动程式就写在‘/lib/modules/$(uname -r)/kernel/fs/vfat/’这个目录下啦！ 简单的测试挂载后，接下来让我们检查看看目前已挂载的档案系统状况吧！

范例二：观察目前‘已挂载’的档案系统，包含各档案系统的Label名称
[root@www ~]# mount -l

/dev/hdc2 on / type ext3 (rw) [/1]
proc on /proc type proc (rw)
sysfs on /sys type sysfs (rw)
devpts on /dev/pts type devpts (rw,gid=5,mode=620)
/dev/hdc3 on /home type ext3 (rw) [/home]
/dev/hdc1 on /boot type ext3 (rw) [/boot]
tmpfs on /dev/shm type tmpfs (rw)
none on /proc/sys/fs/binfmt_misc type binfmt_misc (rw)
sunrpc on /var/lib/nfs/rpc_pipefs type rpc_pipefs (rw)
/dev/hdc6 on /mnt/hdc6 type ext3 (rw) [vbird_logical]
# 除了实际的档案系统外，很多特殊的档案系统(proc/sysfs...)也会被显示出来！
# 值得注意的是，加上 -l 选项可以列出如上特殊字体的标头(label)喔

这个指令输出的结果可以让我们看到非常多资讯，以 /dev/hdc2 这个装置来说好了(上面表格的第一行)， 他的意义是：‘/dev/hdc2 是挂载到 / 目录，档案系统类型为 ext3 ，且挂载为可读写 (rw) ，另外，这个 filesystem 有标头，名字(label)为 /1 ’ 这样，你会解释上述表格中的最后一行输出结果了吗？自己解释一下先。^_^。 接下来请拿出你的 CentOS DVD 放入光碟机中，并拿 FAT 格式的 USB 随身碟(不要用 NTFS 的)插入 USB 插槽中，我们来测试挂载一下！

  • 挂载 CD 或 DVD 光碟
范例三：将你用来安装 Linux 的 CentOS 原版光碟拿出来挂载！
[root@www ~]# mkdir /media/cdrom
[root@www ~]# mount -t iso9660 /dev/cdrom /media/cdrom
[root@www ~]# mount /dev/cdrom /media/cdrom

# 你可以指定 -t iso9660 这个光碟片的格式来挂载，也可以让系统自己去测试挂载！
# 所以上述的指令只要做一个就够了！但是目录的建立初次挂载时必须要进行喔！

[root@www ~]# df
Filesystem           1K-blocks      Used Available Use% Mounted on
.....中间省略.....
/dev/hdd               4493152   4493152         0 100% /media/cdrom
# 因为我的光碟机使用的是 /dev/hdd 的 IDE 介面之故！

光碟机一挂载之后就无法退出光碟片了！除非你将他卸载才能够退出！ 从上面的资料你也可以发现，因为是光碟嘛！所以磁碟使用率达到 100% ，因为你无法直接写入任何资料到光碟当中ㄇㄟ！ 另外，其实 /dev/cdrom 是个连结档，正确的磁碟档名得要看你的光碟机是什么连接介面的环境。 以鸟哥为例，我的光碟机接在 /dev/hdd，所以正确的挂载应该是‘mount /dev/hdd /media/cdrom’比较正确喔！

Tips:
话说当时年记小 (其实是刚接触 Linux 的那一年)，摸 Linux 到处碰壁！连将 CDROM 挂载后， 光碟机竟然都不让我退片！那个时候难过的要死！解决的方法竟然是‘重新开机！’囧的可以啊！ 		鸟哥的图示
  • 格式化与挂载软碟

软碟的格式化可以直接使用 mkfs 即可。但是软碟也是可以格式化成为 ext3 或 vfat 格式的。 挂载的时候我们同样的使用系统自动测试挂载即可！真是粉简单！如果你有软碟片的话(很少人有了吧？)， 请先放置到软碟机当中啰！底下来测试看看(软碟片请勿放置任何资料，且将防写打开！)。

范例四：格式化后挂载软碟到 /media/floppy/ 目录中。
[root@www ~]# mkfs -t vfat /dev/fd0
# 我们格式化软碟成为 Windows/Linux 可共同使用的 FAT 格式吧！
[root@www ~]# mkdir /media/floppy
[root@www ~]# mount -t vfat /dev/fd0 /media/floppy
[root@www ~]# df
Filesystem           1K-blocks      Used Available Use% Mounted on

.....中间省略.....
/dev/fd0                  1424       164      1260  12% /media/floppy

与光碟机不同的是，你挂载了软碟后竟然还是可以退出软碟喔！不过，如此一来你的档案系统将会有莫名奇妙的问题发生！ 整个 Linux 最重要的就是档案系统，而档案系统是直接挂载到目录树上头， 几乎任何指令都会或多或少使用到目录树的资料，因此你当然不可以随意的将光碟/软碟拿出来！ 所以，软碟也请卸载之后再退出！很重要的一点！

  • 挂载随身碟

请拿出你的随身碟并插入 Linux 主机的 USB 槽中！注意，你的这个随身碟不能够是 NTFS 的档案系统喔！ 接下来让我们测试测试吧！

范例五：找出你的随身碟装置档名，并挂载到 /mnt/flash 目录中
[root@www ~]# fdisk -l
.....中间省略.....
Disk /dev/sda: 8313 MB, 8313110528 bytes
59 heads, 58 sectors/track, 4744 cylinders
Units = cylinders of 3422 * 512 = 1752064 bytes

   Device Boot      Start         End      Blocks   Id  System

/dev/sda1               1        4745     8118260    b  W95 FAT32
# 从上的特殊字体，可得知磁碟的大小以及装置档名，知道是 /dev/sda1

[root@www ~]# mkdir /mnt/flash
[root@www ~]# mount -t vfat -o iocharset=cp950 /dev/sda1 /mnt/flash
[root@www ~]# df
Filesystem           1K-blocks      Used Available Use% Mounted on
.....中间省略.....

/dev/sda1              8102416   4986228   3116188  62% /mnt/flash

如果带有中文档名的资料，那么可以在挂载时指定一下挂载档案系统所使用的语系资料。 在 man mount 找到 vfat 档案格式当中可以使用 iocharset 来指定语系，而中文语系是 cp950 ， 所以也就有了上述的挂载指令项目啰。

万一你使用的是随身硬碟，也就是利用笔记型电脑所做出来的USB磁碟时，通常这样的硬碟都使用 NTFS 格式的～ 怎办？没关系，可以参考底下这个网站：(注8)

  • NTFS 档案系统官网：Linux-NTFS Project: http://www.linux-ntfs.org/
  • CentOS 5.x 版的相关驱动程式下载页面：http://www.linux-ntfs.org/doku.php?id=redhat:rhel5

将她们提供的驱动程式捉下来并且安装之后，就能够使用 NTFS 的档案系统了！ 只是由于档案系统与 Linux 核心有很大的关系，因此以后如果你的 Linux 系统有升级 (update) 时， 你就得要重新下载一次相对应的驱动程式版本喔！

  • 重新挂载根目录与挂载不特定目录

整个目录树最重要的地方就是根目录了，所以根目录根本就不能够被卸载的！问题是，如果你的挂载参数要改变， 或者是根目录出现‘唯读’状态时，如何重新挂载呢？最可能的处理方式就是重新开机 (reboot)！ 不过你也可以这样做：

范例六：将 / 重新挂载，并加入参数为 rw 与 auto
[root@www ~]# mount -o remount,rw,auto /

重点是那个‘ -o remount,xx ’的选项与参数！请注意，要重新挂载 (remount) 时， 这是个非常重要的机制！尤其是当你进入单人维护模式时，你的根目录常会被系统挂载为唯读，这个时候这个指令就太重要了！

另外，我们也可以利用 mount 来将某个目录挂载到另外一个目录去喔！这并不是挂载档案系统，而是额外挂载某个目录的方法！ 虽然底下的方法也可以使用 symbolic link 来连结，不过在某些不支援符号连结的程式运作中，还是得要透过这样的方法才行。

范例七：将 /home 这个目录暂时挂载到 /mnt/home 底下：
[root@www ~]# mkdir /mnt/home
[root@www ~]# mount --bind /home /mnt/home
[root@www ~]# ls -lid /home/ /mnt/home
2 drwxr-xr-x 6 root root 4096 Sep 29 02:21 /home/
2 drwxr-xr-x 6 root root 4096 Sep 29 02:21 /mnt/home

[root@www ~]# mount -l
/home on /mnt/home type none (rw,bind)

看起来，其实两者连结到同一个 inode 嘛！ ^_^ 没错啦！透过这个 mount --bind 的功能， 您可以将某个目录挂载到其他目录去喔！而并不是整块 filesystem 的啦！所以从此进入 /mnt/home 就是进入 /home 的意思喔！

  • umount (将装置档案卸载)
[root@www ~]# umount [-fn] 装置档名或挂载点
选项与参数：
-f ：强制卸载！可用在类似网路档案系统 (NFS) 无法读取到的情况下；
-n ：不更新 /etc/mtab 情况下卸载。

就是直接将已挂载的档案系统给他卸载即是！卸载之后，可以使用 df 或 mount -l 看看是否还存在目录树中？ 卸载的方式，可以下达装置档名或挂载点，均可接受啦！底下的范例做看看吧！

范例八：将本章之前自行挂载的档案系统全部卸载：
[root@www ~]# mount
.....前面省略.....
/dev/hdc6 on /mnt/hdc6 type ext3 (rw)

/dev/hdd on /media/cdrom type iso9660 (rw)
/dev/sda1 on /mnt/flash type vfat (rw,iocharset=cp950)
/home on /mnt/home type none (rw,bind)

# 先找一下已经挂载的档案系统，如上所示，特殊字体即为刚刚挂载的装置啰！

[root@www ~]# umount /dev/hdc6      <==用装置档名来卸载
[root@www ~]# umount /media/cdrom   <==用挂载点来卸载
[root@www ~]# umount /mnt/flash     <==因为挂载点比较好记忆！

[root@www ~]# umount /dev/fd0       <==用装置档名较好记！
[root@www ~]# umount /mnt/home      <==一定要用挂载点！因为挂载的是目录

由于通通卸载了，此时你才可以退出光碟片、软碟片、USB随身碟等设备喔！如果你遇到这样的情况：

[root@www ~]# mount /dev/cdrom /media/cdrom
[root@www ~]# cd /media/cdrom
[root@www cdrom]# umount /media/cdrom
umount: /media/cdrom: device is busy
umount: /media/cdrom: device is busy

由于你目前正在 /media/cdrom/ 的目录内，也就是说其实‘你正在使用该档案系统’的意思！ 所以自然无法卸载这个装置！那该如何是好？就‘离开该档案系统的挂载点’即可。以上述的案例来说， 你可以使用‘ cd / ’回到根目录，就能够卸载 /media/cdrom 啰！简单吧！

  • 使用 Label name 进行挂载的方法

除了磁碟的装置档名之外，其实我们可以使用档案系统的标头(label)名称来挂载喔！ 举例来说，我们刚刚卸载的 /dev/hdc6 标头名称是‘vbird_logical’，你也可以使用 dumpe2fs 这个指令来查询一下啦！然后就这样做即可：

范例九：找出 /dev/hdc6 的 label name，并用 label 挂载到 /mnt/hdc6

[root@www ~]# dumpe2fs -h /dev/hdc6
Filesystem volume name:   vbird_logical
.....底下省略.....
# 找到啦！标头名称为 vbird_logical 啰！

[root@www ~]# mount -L "vbird_logical" /mnt/hdc6

这种挂载的方法有一个很大的好处：‘系统不必知道该档案系统所在的介面与磁碟档名！’ 更详细的说明我们会在下一小节当中的 e2label 介绍的！

小标题的图示 磁碟参数修订

某些时刻，你可能会希望修改一下目前档案系统的一些相关资讯，举例来说，你可能要修改 Label name ， 或者是 journal 的参数，或者是其他硬碟运作时的相关参数 (例如 DMA 启动与否～)。 这个时候，就得需要底下这些相关的指令功能啰～

  • mknod

还记得我们说过，在 Linux 底下所有的装置都以档案来代表吧！但是那个档案如何代表该装置呢？ 很简单！就是透过档案的 major 与 minor 数值来替代的～所以，那个 major 与 minor 数值是有特殊意义的，不是随意设定的喔！举例来说，在鸟哥的这个测试机当中， 那个用到的磁碟 /dev/hdc 的相关装置代码如下：

[root@www ~]# ll /dev/hdc*
brw-r----- 1 root disk 22, 0 Oct 24 15:55 /dev/hdc
brw-r----- 1 root disk 22, 1 Oct 20 08:47 /dev/hdc1
brw-r----- 1 root disk 22, 2 Oct 20 08:47 /dev/hdc2
brw-r----- 1 root disk 22, 3 Oct 20 08:47 /dev/hdc3
brw-r----- 1 root disk 22, 4 Oct 24 16:02 /dev/hdc4
brw-r----- 1 root disk 22, 5 Oct 20 16:46 /dev/hdc5
brw-r----- 1 root disk 22, 6 Oct 25 01:33 /dev/hdc6

上表当中 22 为主要装置代码 (Major) 而 0~6 则为次要装置代码 (Minor)。 我们的 Linux 核心认识的装置资料就是透过这两个数值来决定的！举例来说，常见的硬碟档名 /dev/hda 与 /dev/sda 装置代码如下所示：

磁碟档名 | Major | Minor
/dev/hda | 3 | 0~63
/dev/hdb | 3 | 64~127
/dev/sda | 8 | 0-15
/dev/sdb | 8 | 16-31

如果你想要知道更多核心支援的硬体装置代码 (major, minor) 请参考官网的连结(注9)：

  • http://www.kernel.org/pub/linux/docs/device-list/devices.txt

基本上，Linux 核心 2.6 版以后，硬体档名已经都可以被系统自动的即时产生了，我们根本不需要手动建立装置档案。 不过某些情况底下我们可能还是得要手动处理装置档案的，例如在某些服务被关到特定目录下时(chroot)， 就需要这样做了。此时这个 mknod 就得要知道如何操作才行！

[root@www ~]# mknod 装置档名 [bcp] [Major] [Minor]

选项与参数：
装置种类：
   b  ：设定装置名称成为一个周边储存设备档案，例如硬碟等；
   c  ：设定装置名称成为一个周边输入设备档案，例如滑鼠/键盘等；
   p  ：设定装置名称成为一个 FIFO 档案；
Major ：主要装置代码；
Minor ：次要装置代码；

范例一：由上述的介绍我们知道 /dev/hdc10 装置代码 22, 10，请建立并查阅此装置
[root@www ~]# mknod /dev/hdc10 b 22 10
[root@www ~]# ll /dev/hdc10
brw-r--r-- 1 root root 22, 10 Oct 26 23:57 /dev/hdc10
# 上面那个 22 与 10 是有意义的，不要随意设定啊！

范例二：建立一个 FIFO 档案，档名为 /tmp/testpipe
[root@www ~]# mknod /tmp/testpipe p
[root@www ~]# ll /tmp/testpipe
prw-r--r-- 1 root root 0 Oct 27 00:00 /tmp/testpipe
# 注意啊！这个档案可不是一般档案，不可以随便就放在这里！
# 测试完毕之后请删除这个档案吧！看一下这个档案的类型！是 p 喔！^_^

  • e2label

我们在 mkfs 指令介绍时有谈到设定档案系统标头 (Label) 的方法。 那如果格式化完毕后想要修改标头呢？就用这个 e2label 来修改了。那什么是 Label 呢？ 我们拿你曾用过的 Windows 系统来说明。当你打开‘档案总管’时，C/D等槽不是都会有个名称吗？ 那就是 label (如果没有设定名称，就会显示‘本机磁碟机’的字样)

这个东西除了有趣且可以让你知道磁碟的内容是啥玩意儿之外，也会被使用到一些设定档案当中！ 举例来说，刚刚我们聊到的磁碟的挂载时，不就有用到 Label name 来进行挂载吗？ 目前 CentOS 的设定档，也就是那个 /etc/fstab 档案的设定都预设使用 Label name 呢！ 那这样做有什么好处与缺点呢？

  • 优点：不论磁碟档名怎么变，不论你将硬碟插在那个 IDE / SATA 介面，由于系统是透过 Label ，所以，磁碟插在哪个介面将不会有影响；

  • 缺点：如果插了两颗硬碟，刚好两颗硬碟的 Label 有重复的，那就惨了～ 因为系统可能会无法判断那个磁碟分割槽才是正确的！

鸟哥一直是个比较‘硬派’作风，所以我还是比较喜欢直接利用磁碟档名来挂载啦！ 不过，如果没有特殊需求的话，那么利用 Label 来挂载也成！ 但是你就不可以随意修改 Label 的名称了！

[root@www ~]# e2label 装置名称  新的Label名称

范例一：将 /dev/hdc6 的标头改成 my_test 并观察是否修改成功？

[root@www ~]# dumpe2fs -h /dev/hdc6
Filesystem volume name:   vbird_logical  <==原本的标头名称
.....底下省略.....

[root@www ~]# e2label /dev/hdc6 "my_test"
[root@www ~]# dumpe2fs -h /dev/hdc6

Filesystem volume name:   my_test        <==改过来啦！
.....底下省略.....

  • tune2fs
[root@www ~]# tune2fs [-jlL] 装置代号
选项与参数：
-l  ：类似 dumpe2fs -h 的功能～将 superblock 内的资料读出来～
-j  ：将 ext2 的 filesystem 转换为 ext3 的档案系统；
-L  ：类似 e2label 的功能，可以修改 filesystem 的 Label 喔！

范例一：列出 /dev/hdc6 的 superblock 内容
[root@www ~]# tune2fs -l /dev/hdc6

这个指令的功能其实很广泛啦～上面鸟哥仅列出很简单的一些参数而已， 更多的用法请自行参考 man tune2fs 。比较有趣的是，如果你的某个 partition 原本是 ext2 的档案系统，如果想要将他更新成为 ext3 档案系统的话，利用 tune2fs 就可以很简单的转换过来啰～

  • hdparm

如果你的硬碟是 IDE 介面的，那么这个指令可以帮助你设定一些进阶参数！如果你是使用 SATA 介面的， 那么这个指令就没有多大用途了！另外，目前的 Linux 系统都已经稍微最佳化过，所以这个指令最多是用来测试效能啦！ 而且建议你不要随便调整硬碟参数，档案系统容易出问题喔！除非你真的知道你调整的资料是啥！

[root@www ~]# hdparm [-icdmXTt] 装置名称
选项与参数：
-i  ：将核心侦测到的硬碟参数显示出来！
-c  ：设定 32-bit (32位元)存取模式。这个 32 位元存取模式指的是在硬碟在与
      PCI 介面之间传输的模式，而硬碟本身是依旧以 16 位元模式在跑的！
      预设的情况下，这个设定值都会被打开，建议直接使用 c1 即可！
-d  ：设定是否启用 dma 模式， -d1 为启动， -d0 为取消；
-m  ：设定同步读取多个 sector 的模式。一般来说，设定此模式，可降低系统因为
      读取磁碟而损耗的效能～不过， WD 的硬碟则不怎么建议设定此值～
      一般来说，设定为 16/32 是最佳化，不过，WD 硬碟建议值则是 4/8 。
      这个值的最大值，可以利用 hdparm -i /dev/hda 输出的 MaxMultSect

      来设定喔！一般如果不晓得，设定 16 是合理的！
-X  ：设定 UtraDMA 的模式，一般来说， UDMA 的模式值加 64 即为设定值。
      并且，硬碟与主机板晶片必须要同步，所以，取最小的那个。一般来说：
      33 MHz DMA mode 0~2 (X64~X66)
      66 MHz DMA mode 3~4 (X67~X68)
      100MHz DMA mode 5   (X69)
      如果您的硬碟上面显示的是 UATA 100 以上的，那么设定 X69 也不错！
-T  ：测试暂存区 cache 的存取效能
-t  ：测试硬碟的实际存取效能 （较正确！）

范例一：取得我硬碟的最大同步存取 sector 值与目前的 UDMA 模式
[root@www ~]# hdparm -i /dev/hdc
 Model=IC35L040AVER07-0, FwRev=ER4OA41A, SerialNo=SX0SXL98406 <==硬碟的厂牌型号
 Config={ HardSect NotMFM HdSw>15uSec Fixed DTR>10Mbs }
 RawCHS=16383/16/63, TrkSize=0, SectSize=0, ECCbytes=40
 BuffType=DualPortCache, BuffSize=1916kB, MaxMultSect=16, MultSect=16

 CurCHS=16383/16/63, CurSects=16514064, LBA=yes, LBAsects=80418240
 IORDY=on/off, tPIO={min:240,w/IORDY:120}, tDMA={min:120,rec:120}
 PIO modes:  pio0 pio1 pio2 pio3 pio4
 DMA modes:  mdma0 mdma1 mdma2
 UDMA modes: udma0 udma1 udma2 udma3 udma4 *udma5 <==有 * 为目前的值
 AdvancedPM=yes: disabled (255) WriteCache=enabled
 Drive conforms to: ATA/ATAPI-5 T13 1321D revision 1:
    ATA/ATAPI-2 ATA/ATAPI-3 ATA/ATAPI-4 ATA/ATAPI-5
# 这颗硬碟缓冲记忆体只有 2MB(BuffSize)，但使用的是 udma5 ！还可以。

范例二：由上个范例知道最大 16 位元/UDMA 为 mode 5，所以可以设定为：
[root@www ~]# hdparm -d1 -c1 -X69 /dev/hdc

范例三：测试这颗硬碟的读取效能
[root@www ~]# hdparm -Tt /dev/hdc
/dev/hdc:
 Timing cached reads:   428 MB in  2.00 seconds = 213.50 MB/sec
 Timing buffered disk reads:  114 MB in  3.00 seconds =  38.00 MB/sec
# 鸟哥的这部测试机没有很好啦～这样的速度.....差强人意～

如果你是使用 SATA 硬碟的话，这个指令唯一可以做的，就是最后面那个测试的功能而已啰！ 虽然这样的测试不是很准确，至少是一个可以比较的基准。鸟哥在我的 cluster 机器上面测试的 SATA (/dev/sda) 与 RAID (/dev/sdb) 结果如下，可以提供给你参考看看。

[root@www ~]# hdparm -Tt /dev/sda /dev/sdb

/dev/sda:
 Timing cached reads:   4152 MB in  2.00 seconds = 2075.28 MB/sec
 Timing buffered disk reads:  304 MB in  3.01 seconds = 100.91 MB/sec

/dev/sdb:
 Timing cached reads:   4072 MB in  2.00 seconds = 2036.31 MB/sec
 Timing buffered disk reads:  278 MB in  3.00 seconds =  92.59 MB/sec
大标题的图示 设定开机挂载：

手动处理 mount 不是很人性化，我们总是需要让系统‘自动’在开机时进行挂载的！本小节就是在谈这玩意儿！ 另外，从 FTP 伺服器捉下来的映像档能否不用烧录就可以读取内容？我们也需要谈谈先！

小标题的图示 开机挂载 /etc/fstab 及 /etc/mtab

刚刚上面说了许多，那么可不可以在开机的时候就将我要的档案系统都挂好呢？这样我就不需要每次进入 Linux 系统都还要在挂载一次呀！当然可以啰！那就直接到 /etc/fstab 里面去修修就行啰！不过，在开始说明前，这里要先跟大家说一说系统挂载的一些限制：

  • 根目录 / 是必须挂载的，而且一定要先于其它 mount point 被挂载进来。
  • 其它 mount point 必须为已建立的目录，可任意指定，但一定要遵守必须的系统目录架构原则
  • 所有 mount point 在同一时间之内，只能挂载一次。
  • 所有 partition 在同一时间之内，只能挂载一次。
  • 如若进行卸载，您必须先将工作目录移到 mount point(及其子目录) 之外。

让我们直接查阅一下 /etc/fstab 这个档案的内容吧！

[root@www ~]# cat /etc/fstab

# Device        Mount point   filesystem parameters    dump fsck
LABEL=/1          /           ext3       defaults        1 1
LABEL=/home       /home       ext3       defaults        1 2
LABEL=/boot       /boot       ext3       defaults        1 2
tmpfs             /dev/shm    tmpfs      defaults        0 0
devpts            /dev/pts    devpts     gid=5,mode=620  0 0
sysfs             /sys        sysfs      defaults        0 0
proc              /proc       proc       defaults        0 0
LABEL=SWAP-hdc5   swap        swap       defaults        0 0
# 上述特殊字体的部分与实际磁碟有关！其他则是虚拟档案系统或
# 与记忆体置换空间 (swap) 有关。

其实 /etc/fstab (filesystem table) 就是将我们利用 mount 指令进行挂载时， 将所有的选项与参数写入到这个档案中就是了。除此之外， /etc/fstab 还加入了 dump 这个备份用指令的支援！ 与开机时是否进行档案系统检验 fsck 等指令有关。

这个档案的内容共有六个栏位，这六个栏位非常的重要！你‘一定要背起来’才好！ 各个栏位的详细资料如下：

Tips:
鸟哥比较龟毛一点，因为某些 distributions 的 /etc/fstab 档案排列方式蛮丑的， 虽然每一栏之间只要以空白字元分开即可，但就是觉得丑，所以通常鸟哥就会自己排列整齐， 并加上注解符号(就是 # )，来帮我记忆这些资讯！ 		鸟哥的图示
  • 第一栏：磁碟装置档名或该装置的 Label：

这个栏位请填入档案系统的装置档名。但是由上面表格的预设值我们知道系统预设使用的是 Label 名称！ 在鸟哥的这个测试系统中 /dev/hdc2 标头名称为 /1，所以上述表格中的‘LABEL=/1’也可以被取代成为‘/dev/hdc2’的意思。 至于Label可以使用 dumpe2fs 指令来查阅的。

Tips:
记得有一次有个网友写信给鸟哥，他说，依照 e2label 的设定去练习修改自己的 partition 的 Label name 之后，却发现，再也无法顺利开机成功！ 后来才发现，原来他的 /etc/fstab 就是以 Label name 去挂载的。但是因为在练习的时候， 将 Label name 改名字过了，导致在开机的过程当中再也找不到相关的Label name了。

所以啦，这里再次的强调，利用装置名称 (ex> /dev/hda1) 来挂载 partition 时， 虽然是被固定死的，所以您的硬碟不可以随意插在任意的插槽，不过他还是有好处的。 而使用 Label name 来挂载，虽然就没有插槽方面的问题，不过，您就得要随时注意您的 Label name 喔！尤其是新增硬碟的时候！ ^_^ 		鸟哥的图示
  • 第二栏：挂载点 (mount point)：：

就是挂载点啊！挂载点是什么？一定是目录啊～要知道啊！

  • 第三栏：磁碟分割槽的档案系统：

在手动挂载时可以让系统自动测试挂载，但在这个档案当中我们必须要手动写入档案系统才行！ 包括 ext3, reiserfs, nfs, vfat 等等。

  • 第四栏：档案系统参数：

记不记得我们在 mount 这个指令中谈到很多特殊的档案系统参数？ 还有我们使用过的‘-o iocharset=cp950’？这些特殊的参数就是写入在这个栏位啦！ 虽然之前在 mount 已经提过一次，这里我们利用表格的方式再汇整一下：

参数 | 内容意义
async/sync 非同步/同步 | 设定磁碟是否以非同步方式运作！预设为 async(效能较佳)
auto/noauto 自动/非自动 | 当下达 mount -a 时，此档案系统是否会被主动测试挂载。预设为 auto。
rw/ro 可读写/唯读 | 让该分割槽以可读写或者是唯读的型态挂载上来，如果你想要分享的资料是不给使用者随意变更的， 这里也能够设定为唯读。则不论在此档案系统的档案是否设定 w 权限，都无法写入喔！
exec/noexec 可执行/不可执行 | 限制在此档案系统内是否可以进行‘执行’的工作？如果是纯粹用来储存资料的， 那么可以设定为 noexec 会比较安全，相对的，会比较麻烦！
user/nouser 允许/不允许使用者挂载 | 是否允许使用者使用 mount 指令来挂载呢？一般而言，我们当然不希望一般身份的 user 能使用 mount 啰，因为太不安全了，因此这里应该要设定为 nouser 啰！
suid/nosuid 具有/不具有 suid 权限 | 该档案系统是否允许 SUID 的存在？如果不是执行档放置目录，也可以设定为 nosuid 来取消这个功能！
usrquota | 注意名称是‘ usrquota ’不要拼错了！这个是在启动 filesystem 支援磁碟配额模式，更多资料我们在第四篇再谈。
grpquota | 注意名称是‘grpquota’，启动 filesystem 对群组磁碟配额模式的支援。
defaults | 同时具有 rw, suid, dev, exec, auto, nouser, async 等参数。 基本上，预设情况使用 defaults 设定即可！

  • 第五栏：能否被 dump 备份指令作用：

dump 是一个用来做为备份的指令(我们会在第二十五章备份策略中谈到这个指令)， 我们可以透过 fstab 指定哪个档案系统必须要进行 dump 备份！ 0 代表不要做 dump 备份， 1 代表要每天进行 dump 的动作。 2 也代表其他不定日期的 dump 备份动作， 通常这个数值不是 0 就是 1 啦！

  • 是否以 fsck 检验磁区：

开机的过程中，系统预设会以 fsck 检验我们的 filesystem 是否完整 (clean)。 不过，某些 filesystem 是不需要检验的，例如记忆体置换空间 (swap) ，或者是特殊档案系统例如 /proc 与 /sys 等等。所以，在这个栏位中，我们可以设定是否要以 fsck 检验该 filesystem 喔。 0 是不要检验， 1 表示最早检验(一般只有根目录会设定为 1)， 2 也是要检验，不过 1 会比较早被检验啦！ 一般来说，根目录设定为 1 ，其他的要检验的 filesystem 都设定为 2 就好了。

例题：
假设我们要将 /dev/hdc6 每次开机都自动挂载到 /mnt/hdc6 ，该如何进行？
答：
首先，请用 nano 将底下这一行写入 /etc/fstab 当中；
[root@www ~]# nano /etc/fstab
/dev/hdc6  /mnt/hdc6    ext3    defaults   1 2
再来看看 /dev/hdc6 是否已经挂载，如果挂载了，请务必卸载再说！
[root@www ~]# df

Filesystem           1K-blocks      Used Available Use% Mounted on
/dev/hdc6              1976312     42072   1833836   3% /mnt/hdc6
# 竟然不知道何时被挂载了？赶紧给他卸载先！

[root@www ~]# umount /dev/hdc6
最后测试一下刚刚我们写入 /etc/fstab 的语法有没有错误！这点很重要！因为这个档案如果写错了， 则你的 Linux 很可能将无法顺利开机完成！所以请务必要测试测试喔！
[root@www ~]# mount -a

[root@www ~]# df
最终有看到 /dev/hdc6 被挂载起来的资讯才是成功的挂载了！而且以后每次开机都会顺利的将此档案系统挂载起来的！ 由于这个范例仅是测试而已，请务必回到 /etc/fstab 当中，将上述这行给他注解或者是删除掉！
[root@www ~]# nano /etc/fstab
# /dev/hdc6  /mnt/hdc6    ext3    defaults   1 2

/etc/fstab 是开机时的设定档，不过，实际 filesystem 的挂载是记录到 /etc/mtab 与 /proc/mounts 这两个档案当中的。每次我们在更动 filesystem 的挂载时，也会同时更动这两个档案喔！但是，万一发生您在 /etc/fstab 输入的资料错误，导致无法顺利开机成功，而进入单人维护模式当中，那时候的 / 可是 read only 的状态，当然您就无法修改 /etc/fstab ，也无法更新 /etc/mtab 啰～那怎么办？ 没关系，可以利用底下这一招：

[root@www ~]# mount -n -o remount,rw /
小标题的图示 特殊装置 loop 挂载 (映象档不烧录就挂载使用)
  • 挂载光碟/DVD映象档

想像一下如果今天我们从国家高速网路中心(http://ftp.twaren.net)或者是义守大学(http://ftp.isu.edu.tw)下载了 Linux 或者是其他所需光碟/DVD的映象档后， 难道一定需要烧录成为光碟才能够使用该档案里面的资料吗？当然不是啦！我们可以透过 loop 装置来挂载的！

那要如何挂载呢？鸟哥将整个 CentOS 5.2 的 DVD 映象档捉到测试机上面，然后利用这个档案来挂载给大家参考看看啰！

[root@www ~]# ll -h /root/centos5.2_x86_64.iso
-rw-r--r-- 1 root root 4.3G Oct 27 17:34 /root/centos5.2_x86_64.iso
# 看到上面的结果吧！这个档案就是映象档，档案非常的大吧！

[root@www ~]# mkdir /mnt/centos_dvd
[root@www ~]# mount -o loop /root/centos5.2_x86_64.iso /mnt/centos_dvd

[root@www ~]# df
Filesystem           1K-blocks      Used Available Use% Mounted on
/root/centos5.2_x86_64.iso
                       4493152   4493152         0 100% /mnt/centos_dvd
# 就是这个项目！ .iso 映象档内的所有资料可以在 /mnt/centos_dvd 看到！

[root@www ~]# ll /mnt/centos_dvd
total 584
drwxr-xr-x 2 root root 522240 Jun 24 00:57 CentOS <==瞧！就是DVD的内容啊！
-rw-r--r-- 8 root root    212 Nov 21  2007 EULA
-rw-r--r-- 8 root root  18009 Nov 21  2007 GPL
drwxr-xr-x 4 root root   2048 Jun 24 00:57 images
.....底下省略.....

[root@www ~]# umount /mnt/centos_dvd/
# 测试完成！记得将资料给他卸载！

非常方便吧！如此一来我们不需要将这个档案烧录成为光碟或者是 DVD 就能够读取内部的资料了！ 换句话说，你也可以在这个档案内‘动手脚’去修改档案的！这也是为什么很多映象档提供后，还得要提供验证码 (MD5) 给使用者确认该映象档没有问题！

  • 建立大档案以制作 loop 装置档案！

想一想，既然能够挂载 DVD 的映象档，那么我能不能制作出一个大档案，然后将这个档案格式化后挂载呢？ 好问题！这是个有趣的动作！而且还能够帮助我们解决很多系统的分割不良的情况呢！举例来说，如果当初在分割时， 你只有分割出一个根目录，假设你已经没有多余的容量可以进行额外的分割的！偏偏根目录的容量还很大！ 此时你就能够制作出一个大档案，然后将这个档案挂载！如此一来感觉上你就多了一个分割槽啰！ 用途非常的广泛啦！

底下我们在 /home 下建立一个 512MB 左右的大档案，然后将这个大档案格式化并且实际挂载来玩一玩！ 这样你会比较清楚鸟哥在讲啥！

  • 建立大型档案

    首先，我们得先有一个大的档案吧！怎么建立这个大档案呢？在 Linux 底下我们有一支很好用的程式 dd ！他可以用来建立空的档案喔！详细的说明请先翻到下一章 压缩指令的运用 来查阅，这里鸟哥仅作一个简单的范例而已。 假设我要建立一个空的档案在 /home/loopdev ，那可以这样做：
    [root@www ~]# dd if=/dev/zero of=/home/loopdev bs=1M count=512
512+0 records in   <==读入 512 笔资料
512+0 records out  <==输出 512 笔资料
536870912 bytes (537 MB) copied, 12.3484 seconds, 43.5 MB/s
# 这个指令的简单意义如下：
# if 是 input file ，输入档案。那个 /dev/zero 是会一直输出 0 的装置！
# of 是 output file ，将一堆零写入到后面接的档案中。
# bs 是每个 block 大小，就像档案系统那样的 block 意义；
# count 则是总共几个 bs 的意思。

[root@www ~]# ll -h /home/loopdev

-rw-r--r-- 1 root root 512M Oct 28 02:29 /home/loopdev
    dd 就好像在叠砖块一样，将 512 块，每块 1MB 的砖块堆叠成为一个大档案 (/home/loopdev) ！ 最终就会出现一个 512MB 的档案！粉简单吧！

  • 格式化

    很简单就建立起一个 512MB 的档案了呐！接下来当然是格式化啰！
    [root@www ~]# mkfs -t ext3 /home/loopdev

mke2fs 1.39 (29-May-2006)
/home/loopdev is not a block special device.
Proceed anyway? (y,n) y  <==由于不是正常的装置，所以这里会提示你！
Filesystem label=
OS type: Linux
Block size=1024 (log=0)
Fragment size=1024 (log=0)
131072 inodes, 524288 blocks
26214 blocks (5.00%) reserved for the super user
.....以下省略.....

  • 挂载

    那要如何挂载啊？利用 mount 的特殊参数，那个 -o loop 的参数来处理！
    [root@www ~]# mount -o loop /home/loopdev /media/cdrom/
[root@www ~]# df
Filesystem           1K-blocks      Used Available Use% Mounted on
/home/loopdev           507748     18768    462766   4% /media/cdrom

透过这个简单的方法，感觉上你就可以在原本的分割槽在不更动原有的环境下制作出你想要的分割槽就是了！ 这东西很好用的！尤其是想要玩 Linux 上面的‘虚拟主机’的话， 也就是以一部 Linux 主机再切割成为数个独立的主机系统时，类似 VMware 这类的软体， 在 Linux 上使用 xen 这个软体，他就可以配合这种 loop device 的档案类型来进行根目录的挂载， 真的非常有用的喔！ ^_^

大标题的图示 记忆体置换空间(swap)之建置

还记得在安装 Linux 之前大家常常会告诉你的话吧！就是安装时一定需要的两个 partition 啰！ 一个是根目录，另外一个就是 swap(记忆体置换空间)。关于记忆体置换空间的解释在第四章安装 Linux 内的磁碟分割时有约略提过， swap 的功能就是在应付实体记忆体不足的情况下所造成的记忆体延伸记录的功能。

一般来说，如果硬体的配备足够的话，那么 swap 应该不会被我们的系统所使用到， swap 会被利用到的时刻通常就是实体记忆体不足的情况了。从第零章的计算机概论当中，我们知道 CPU 所读取的资料都来自于记忆体， 那当记忆体不足的时候，为了让后续的程式可以顺利的运作，因此在记忆体中暂不使用的程式与资料就会被挪到 swap 中了。 此时记忆体就会空出来给需要执行的程式载入。由于 swap 是用硬碟来暂时放置记忆体中的资讯， 所以用到 swap 时，你的主机硬碟灯就会开始闪个不停啊！

虽然目前(2009)主机的记忆体都很大，至少都有 1GB 以上啰！因此在个人使用上你不要设定 swap 应该也没有什么太大的问题。 不过伺服器可就不这么想了～由于你不会知道何时会有大量来自网路的要求，因此你最好能够预留一些 swap 来缓冲一下系统的记忆体用量！ 至少达到‘备而不用’的地步啊！

现在想像一个情况，你已经将系统建立起来了，此时却才发现你没有建置 swap ～那该如何是好呢？ 透过本章上面谈到的方法，你可以使用如下的方式来建立你的 swap 啰！

  • 设定一个 swap partition
  • 建立一个虚拟记忆体的档案

不啰唆，就立刻来处理处理吧！

小标题的图示 使用实体分割槽建置swap

建立 swap 分割槽的方式也是非常的简单的！透过底下几个步骤就搞定啰：

  1. 分割：先使用 fdisk 在你的磁碟中分割中一个分割槽给系统作为 swap 。由于 Linux 的 fdisk 预设会将分割槽的 ID 设定为 Linux 的档案系统，所以你可能还得要设定一下 system ID 就是了。
  2. 格式化：利用建立 swap 格式的‘mkswap 装置档名’就能够格式化该分割槽成为 swap 格式啰
  3. 使用：最后将该 swap 装置启动，方法为：‘swapon 装置档名’。
  4. 观察：最终透过 free 这个指令来观察一下记忆体的用量吧！

不啰唆，立刻来实作看看！既然我们还有多余的磁碟容量可以分割，那么让我们继续分割出 256MB 的磁碟分割槽吧！ 然后将这个磁碟分割槽做成 swap 吧！

  • 1. 先进行分割的行为啰！
[root@www ~]# fdisk /dev/hdc
Command (m for help): n
First cylinder (2303-5005, default 2303):  <==这里按[enter]
Using default value 2303
Last cylinder or +size or +sizeM or +sizeK (2303-5005, default 5005): +256M

Command (m for help): p

   Device Boot      Start         End      Blocks   Id  System
.....中间省略.....
/dev/hdc6            2053        2302     2008093+  83  Linux
/dev/hdc7            2303        2334      257008+  83  Linux <==新增的项目

Command (m for help): t             <==修改系统 ID

Partition number (1-7): 7           <==从上结果看到的，七号partition
Hex code (type L to list codes): 82 <==改成 swap 的 ID
Changed system type of partition 7 to 82 (Linux swap / Solaris)

Command (m for help): p

   Device Boot      Start         End      Blocks   Id  System
.....中间省略.....

/dev/hdc6            2053        2302     2008093+  83  Linux
/dev/hdc7            2303        2334      257008+  82  Linux swap / Solaris

Command (m for help): w
# 此时就将 partition table 更新了！

[root@www ~]# partprobe
# 这个玩意儿很重要的啦！不要忘记让核心更新 partition table 喔！

  • 2. 开始建置 swap 格式
[root@www ~]# mkswap /dev/hdc7
Setting up swapspace version 1, size = 263172 kB  <==非常快速！

  • 3. 开始观察与载入看看吧！
[root@www ~]# free
             total       used       free     shared    buffers     cached
Mem:        742664     684592      58072          0      43820     497144
-/+ buffers/cache:     143628     599036
Swap:      1020088         96    1019992
# 我有 742664K 的实体记忆体，使用 684592K 剩余 58072K ，使用掉的记忆体有
# 43820K / 497144K 用在缓冲/快取的用途中。
# 至于 swap 已经存在了 1020088K 啰！这样会看了吧？！

[root@www ~]# swapon /dev/hdc7
[root@www ~]# free
             total       used       free     shared    buffers     cached
Mem:        742664     684712      57952          0      43872     497180
-/+ buffers/cache:     143660     599004
Swap:      1277088         96    1276992  <==有增加啰！看到否？

[root@www ~]# swapon -s
Filename                 Type            Size    Used    Priority
/dev/hdc5                partition       1020088 96      -1
/dev/hdc7                partition       257000  0       -2
# 上面列出目前使用的 swap 装置有哪些的意思！

小标题的图示 使用档案建置swap

如果是在实体分割槽无法支援的环境下，此时前一小节提到的 loop 装置建置方法就派的上用场啦！ 与实体分割槽不一样的只是利用 dd 去建置一个大档案而已。多说无益，我们就再透过档案建置的方法建立一个 128 MB 的记忆体置换空间吧！

  • 1. 使用 dd 这个指令来新增一个 128MB 的档案在 /tmp 底下：
[root@www ~]# dd if=/dev/zero of=/tmp/swap bs=1M count=128
128+0 records in
128+0 records out
134217728 bytes (134 MB) copied, 1.7066 seconds, 78.6 MB/s

[root@www ~]# ll -h /tmp/swap
-rw-r--r-- 1 root root 128M Oct 28 15:33 /tmp/swap
这样一个 128MB 的档案就建置妥当。若忘记上述的各项参数的意义，请回前一小节查阅一下啰！

  • 2. 使用 mkswap 将 /tmp/swap 这个档案格式化为 swap 的档案格式：
[root@www ~]# mkswap /tmp/swap
Setting up swapspace version 1, size = 134213 kB
# 这个指令下达时请‘特别小心’，因为下错字元控制，将可能使您的档案系统挂掉！

  • 3. 使用 swapon 来将 /tmp/swap 启动啰！
[root@www ~]# free
             total       used       free     shared    buffers     cached
Mem:        742664     450860     291804          0      45584     261284
-/+ buffers/cache:     143992     598672
Swap:      1277088         96    1276992

[root@www ~]# swapon /tmp/swap
[root@www ~]# free
             total       used       free     shared    buffers     cached
Mem:        742664     450860     291804          0      45604     261284
-/+ buffers/cache:     143972     598692
Swap:      1408152         96    1408056

[root@www ~]# swapon -s

Filename                 Type            Size    Used    Priority
/dev/hdc5                partition       1020088 96      -1
/dev/hdc7                partition       257000  0       -2
/tmp/swap                file            131064  0       -3

  • 4. 使用 swapoff 关掉 swap file
[root@www ~]# swapoff /tmp/swap

[root@www ~]# swapoff /dev/hdc7
[root@www ~]# free
             total       used       free     shared    buffers     cached
Mem:        742664     450860     291804          0      45660     261284
-/+ buffers/cache:     143916     598748
Swap:      1020088         96    1019992  <==回复成最原始的样子了！

小标题的图示 swap使用上的限制

说实话，swap 在目前的桌上型电脑来讲，存在的意义已经不大了！这是因为目前的 x86 主机所含的记忆体实在都太大了 (一般入门级至少也都有 512MB 了)，所以，我们的 Linux 系统大概都用不到 swap 这个玩意儿的。不过， 如果是针对伺服器或者是工作站这些常年上线的系统来说的话，那么，无论如何，swap 还是需要建立的。

因为 swap 主要的功能是当实体记忆体不够时，则某些在记忆体当中所占的程式会暂时被移动到 swap 当中，让实体记忆体可以被需要的程式来使用。另外，如果你的主机支援电源管理模式， 也就是说，你的 Linux 主机系统可以进入‘休眠’模式的话，那么， 运作当中的程式状态则会被纪录到 swap 去，以作为‘唤醒’主机的状态依据！ 另外，有某些程式在运作时，本来就会利用 swap 的特性来存放一些资料段， 所以， swap 来是需要建立的！只是不需要太大！

不过， swap 在被建立时，是有限制的喔！

  • 在核心 2.4.10 版本以后，单一 swap 量已经没有 2GB 的限制了，
  • 但是，最多还是仅能建立到 32 个 swap 的数量！
  • 而且，由于目前 x86_64 (64位元) 最大记忆体定址到 64GB， 因此， swap 总量最大也是仅能达 64GB 就是了！
大标题的图示 档案系统的特殊观察与操作

档案系统实在是非常有趣的东西，鸟哥学了好几年还是很多东西不很懂呢！ 在学习的过程中很多朋友在讨论区都有提供一些想法！这些想法将他归纳起来有底下几点可以参考的资料呢！

小标题的图示 boot sector 与 superblock 的关系

在过去非常多的文章都写到开机管理程式是安装到 superblock 内的，但是我们由官方的 How to 文件知道，图解(图 1.3.1)的结果是将可安装开机资讯的 boot sector (开机磁区) 独立出来，并非放置到 superblock 当中的！ 那么也就是说过去的文章写错了？这其实还是可以讨论讨论的！

经过一些搜寻，鸟哥找到几篇文章(非官方文件)的说明，大多是网友分析的结果啦！如下所示：(注10)

  • The Second Extended File System: http://www.nongnu.org/ext2-doc/ext2.html
  • Rob's ext2 documentation: http://www.landley.net/code/toybox/ext2.html
  • Life is different blog: ext2文件系统分析： http://www.qdhedu.com/blog/post/7.html

这几篇文章有几个重点，归纳一下如下：

  • superblock 的大小为 1024 bytes；
  • superblock 前面需要保留 1024 bytes 下来，以让开机管理程式可以安装。

分析上述两点我们知道 boot sector 应该会占有 1024 bytes 的大小吧！但是整个档案系统主要是依据 block 大小来决定的啊！ 因此要讨论 boot sector 与 superblock 的关系时，不得不将 block 的大小拿出来讨论讨论喔！

  • block 为 1024 bytes (1K) 时：

如果 block 大小刚好是 1024 的话，那么 boot sector 与 superblock 各会占用掉一个 block ， 所以整个档案系统图示就会如同图 1.3.1 所显示的那样，boot sector 是独立于 superblock 外面的！ 由于鸟哥在基础篇安装的环境中有个 /boot 的独立档案系统在 /dev/hdc1 中，使用 dumpe2fs 观察的结果有点像底下这样(如果你是按照鸟哥的教学安装你的 CentOS 时，可以发现相同的情况喔！)：

[root@www ~]# dumpe2fs /dev/hdc1
dumpe2fs 1.39 (29-May-2006)
Filesystem volume name:   /boot
....(中间省略)....
First block:              1
Block size:               1024
....(中间省略)....

Group 0: (Blocks 1-8192)
  Primary superblock at 1, Group descriptors at 2-2
  Reserved GDT blocks at 3-258

  Block bitmap at 259 (+258), Inode bitmap at 260 (+259)
  Inode table at 261-511 (+260)
  511 free blocks, 1991 free inodes, 2 directories
  Free blocks: 5619-6129
  Free inodes: 18-2008

# 看到最后一个特殊字体的地方吗？ Group0 的 superblock 是由 1  号 block 开始喔！

由上表我们可以确实的发现 0 号 block 是保留下来的，那就是留给 boot sector 用的啰！ 所以整个分割槽的档案系统分区有点像底下这样的图示：

1K block 的 boot sector 示意图
图 6.1.1、1K block 的 boot sector 示意图
  • block 大于 1024 bytes (2K, 4K) 时：

如果 block 大于 1024 的话，那么 superblock 将会在 0 号！我们撷取本章一开始介绍 dumpe2fs 时的内容来说明一下好了！

[root@www ~]# dumpe2fs /dev/hdc2
dumpe2fs 1.39 (29-May-2006)
....(中间省略)....
Filesystem volume name:   /1

....(中间省略)....
Block size:               4096
....(中间省略)....

Group 0: (Blocks 0-32767)
  Primary superblock at 0, Group descriptors at 1-1
  Reserved GDT blocks at 2-626
  Block bitmap at 627 (+627), Inode bitmap at 628 (+628)
  Inode table at 629-1641 (+629)
  0 free blocks, 32405 free inodes, 2 directories
  Free blocks:
  Free inodes: 12-32416

我们可以发现 superblock 就在第一个 block (第 0 号) 上头！但是 superblock 其实就只有 1024bytes 嘛！ 为了怕浪费更多空间，因此第一个 block 内就含有 boot sector 与 superblock 两者 ！举上头的表格来说，因为每个 block 占有 4K ，因此在第一个 block 内 superblock 仅占有 1024-2047 ( 由 0 号起算的话)之间的咚咚，至于 2048bytes 以后的空间就真的是保留啦！而 0-1023 就保留给 boot sector 来使用。

4K block 的 boot sector 示意图
图 6.1.2、4K block 的 boot sector 示意图

因为上述的情况，如果在比较大的 block 尺寸(size)中，我们可能可以说你能够将开机管理程式安装到 superblock 所在的 block 号码中！就是上表的 0 号啰！但事实上还是安装到 boot sector 的保留区域中啦！所以说， 以前的文章说开机管理程式可以安装到 superblock 内也不能算全错～但比较正确的说法，应该是安装到该 filesystem 最前面的 1024 bytes 内的区域，就是 boot sector 这样比较好！

小标题的图示 磁碟空间之浪费问题

我们在前面的 block 介绍中谈到了一个 block 只能放置一个档案， 因此太多小档案将会浪费非常多的磁碟容量。但你有没有注意到，整个档案系统中包括 superblock, inode table 与其他中介资料等其实都会浪费磁碟容量喔！所以当我们在 /dev/hdc6 建立起 ext3 档案系统时， 一挂载就立刻有很多容量被用掉了！

另外，不知道你有没有发现到，当你使用 ls -l 去查询某个目录下的资料时，第一行都会出现一个‘total’的字样！ 那是啥东西？其实那就是该目录下的所有资料所耗用的实际 block 数量 * block 大小的值。 我们可以透过 ll -s 来观察看看上述的意义：

[root@www ~]# ll -s
total 104

 8 -rw------- 1 root root  1474 Sep  4 18:27 anaconda-ks.cfg
 8 -rw-r--r-- 2 root root   255 Jan  6  2007 crontab
 4 lrwxrwxrwx 1 root root    12 Oct 22 13:58 crontab2 -> /etc/crontab
48 -rw-r--r-- 1 root root 42304 Sep  4 18:26 install.log

12 -rw-r--r-- 1 root root  5661 Sep  4 18:25 install.log.syslog
 4 -rw-r--r-- 1 root root     0 Sep 27 00:25 test1
 8 drwxr-xr-x 2 root root  4096 Sep 27 00:25 test2
 4 -rw-rw-r-- 1 root root     0 Sep 27 00:36 test3
 8 drwxrwxr-x 2 root root  4096 Sep 27 00:36 test4

从上面的特殊字体部分，那就是每个档案所使用掉 block 的容量！举例来说，那个 crontab 虽然仅有 255bytes ， 不过他却占用了两个 block (每个 block 为 4K)，将所有的 block 加总就得到 104Kbytes 那个数值了。 如果计算每个档案实际容量的加总结果，其实只有 56.5K 而已～所以啰，这样就耗费掉好多容量了！

如果想要查询某个目录所耗用的所有容量时，那就使用 du 吧！不过 du 如果加上 -s 这个选项时， 还可以依据不同的规范去找出档案系统所消耗的容量喔！举例来说，我们就来看看 /etc/ 这个目录的容量状态吧！

[root@www ~]# du -sb /etc
108360494       /etc   <==单位是 bytes 喔！

[root@www ~]# du -sm /etc
118     /etc           <==单位是 Kbytes 喔！

使用 bytes 去分析时，发现到实际的资料占用约 103.3Mbytes，但是使用 block 去测试，就发现其实耗用了 118Mbytes， 此时档案系统就耗费了约 15Mbytes 啰！这样看的懂我们在讲的资料了吧？

小标题的图示 利用 GNU 的 parted 进行分割行为

虽然你可以使用 fdisk 很快速的将你的分割槽切割妥当，不过 fdisk 却无法支援到高于 2TB 以上的分割槽！ 此时就得需要 parted 来处理了。不要觉得 2TB 你用不着！ 2009 年的现在已经有单颗硬碟高达 2TB 的容量了！ 如果再搭配主机系统有内建磁碟阵列装置，要使用数个 TB 的单一磁碟装置也不是不可能的！ 所以，还是得要学一下这个重要的工具！ parted ！

parted 可以直接在一行指令列就完成分割，是一个非常好用的指令！他的语法有点像这样：

[root@www ~]# parted [装置] [指令 [参数]]
选项与参数：
指令功能：
新增分割：mkpart [primary|logical|extended] [ext3|vfat] 开始 结束
分割表  ：print
删除分割：rm [partition]

范例一：以 parted 列出目前本机的分割表资料
[root@www ~]# parted /dev/hdc print
Model: IC35L040AVER07-0 (ide)              <==硬碟介面与型号
Disk /dev/hdc: 41.2GB                      <==磁碟档名与容量
Sector size (logical/physical): 512B/512B  <==每个磁区的大小
Partition Table: msdos                     <==分割表形式

Number  Start   End     Size    Type      File system  Flags
 1      32.3kB  107MB   107MB   primary   ext3         boot
 2      107MB   10.6GB  10.5GB  primary   ext3
 3      10.6GB  15.8GB  5240MB  primary   ext3
 4      15.8GB  41.2GB  25.3GB  extended
 5      15.8GB  16.9GB  1045MB  logical   linux-swap
 6      16.9GB  18.9GB  2056MB  logical   ext3
 7      18.9GB  19.2GB  263MB   logical   linux-swap
[  1 ]  [  2 ]  [  3  ] [  4  ] [  5  ]   [  6  ]

上面是最简单的 parted 指令功能简介，你可以使用‘ man parted ’，或者是‘ parted /dev/hdc help mkpart ’去查询更详细的资料。比较有趣的地方在于分割表的输出。我们将上述的分割表示意拆成六部分来说明：

  1. Number：这个就是分割槽的号码啦！举例来说，1号代表的是 /dev/hdc1 的意思；
  2. Start：起始的磁柱位置在这颗磁碟的多少 MB 处？有趣吧！他以容量作为单位喔！
  3. End：结束的磁柱位置在这颗磁碟的多少 MB 处？
  4. Size：由上述两者的分析，得到这个分割槽有多少容量；
  5. Type：就是分割槽的类型，有primary, extended, logical等类型；
  6. File system：就如同 fdisk 的 System ID 之意。

接下来我们尝试来建立一个全新的分割槽吧！因为我们仅剩下逻辑分割槽可用，所以等一下底下我们选择的会是 logical 的分割类型喔！

范例二：建立一个约为 512MB 容量的逻辑分割槽
[root@www ~]# parted /dev/hdc mkpart logical ext3 19.2GB 19.7GB
# 请参考前一表格的指令介绍，因为我们的 /dev/hdc7 在 19.2GB  位置结束，
# 所以我们当然要由 19.2GB 位置处继续下一个分割，这样懂了吧？
[root@www ~]# parted /dev/hdc print
.....前面省略.....
 7      18.9GB  19.2GB  263MB   logical   linux-swap
 8      19.2GB  19.7GB  502MB   logical  <==就是刚刚建立的啦！

范例三：将刚刚建立的第八号磁碟分割槽删除掉吧！
[root@www ~]# parted /dev/hdc rm 8
# 这样就删除了！实在很厉害！所以这个指令的下达要特别注意！
# 因为...指令一下去就立即生效了～如果写错的话，会哭死～

关于 parted 的介绍我们就到这里啦！除非你有使用到大于 2TB 以上的磁碟， 否则请爱用 fdisk 这个程式来进行分割喔！拜托拜托！

大标题的图示 重点回顾
  • 基本上 Linux 的正统档案系统为 Ext2 ，该档案系统内的资讯主要有：
    • superblock：记录此 filesystem 的整体资讯，包括inode/block的总量、使用量、剩余量， 以及档案系统的格式与相关资讯等；
    • inode：记录档案的属性，一个档案占用一个inode，同时记录此档案的资料所在的 block 号码；
    • block：实际记录档案的内容，若档案太大时，会占用多个 block 。
  • Ext2 档案系统的资料存取为索引式档案系统(indexed allocation)
  • 需要磁碟重组的原因就是档案写入的 block 太过于离散了，此时档案读取的效能将会变的很差所致。 这个时候可以透过磁碟重组将同一个档案所属的 blocks 汇整在一起。
  • Ext2档案系统主要有：boot sector, superblock, inode bitmap, block bitmap, inode table, data block 等六大部分。
  • data block 是用来放置档案内容资料地方，在 Ext2 档案系统中所支援的 block 大小有 1K, 2K 及 4K 三种而已
  • inode 记录档案的属性/权限等资料，其他重要项目为： 每个 inode 大小均固定为 128 bytes； 每个档案都仅会占用一个 inode 而已； 因此档案系统能够建立的档案数量与 inode 的数量有关；
  • 档案的 block 在记录档案的实际资料，目录的 block 则在记录该目录底下档名与其 inode 号码的对照表；
  • 日志式档案系统 (journal) 会多出一块记录区，随时记载档案系统的主要活动，可加快系统复原时间；
  • Linux 档案系统为增加效能，会让主记忆体作为大量的磁碟快取；
  • 实体连结只是多了一个档名对该 inode 号码的连结而已；
  • 符号连结就类似Windows的捷径功能。
  • 磁碟的使用必需要经过：分割、格式化与挂载，分别惯用的指令为：fdisk, mkfs, mount三个指令
  • 开机自动挂载可参考/etc/fstab之设定，设定完毕务必使用 mount -a 测试语法正确否；
大标题的图示 本章习题：
( 要看答案请将滑鼠移动到‘答：’底下的空白处，按下左键圈选空白处即可察看 )
  • 情境模拟题一：复原本章的各例题练习，本章新增非常多 partition ，请将这些 partition 删除，恢复到原本刚安装好时的状态。

    • 目标：了解到删除分割槽需要注意的各项资讯；
    • 前提：本章的各项范例练习你都必须要做过，才会拥有 /dev/hdc6, /dev/hdc7 出现；
    • 需求：熟悉 fdisk, umount, swapoff 等指令。

    由于本章处理完毕后，将会有 /dev/hdc6 与 /dev/hdc7 这两个新增的 partition ，所以请删除掉这两个 partition 。 删除的过程需要注意的是：

    1. 需先以 free / swapon -s / mount 等指令查阅， /dev/hdc6, /dev/hdc7 不可以被使用！ 如果有被使用，则你必须要使用 umount 卸载档案系统。如果是记忆体置换空间，则需使用 swapon -s 找出被使用的分割槽， 再以 swapoff 去卸载他！

    2. 观察 /etc/fstab ，该档案不能存在这两个 partition；

    3. 使用‘ fdisk /dev/hdc ’删除，注意，由于是逻辑分割槽，这些分割槽一定从 5 号开始连续编号，因此你最好不要从 6 号删除！否则原本的 7 号在你删除 6 号后，将会变成 6 号！因此，你应该由 7 号删除掉，再删除 6 号。

  • 情境模拟题二：由于我的系统原本分割的不够好，我的用户希望能够独立一个 filesystem 附挂在 /srv/myproject 目录下。 那你该如何建立新的 filesystem ，并且让这个 filesystem 每次开机都能够自动的挂载到 /srv/myproject ， 且该目录是给 project 这个群组共用的，其他人不可具有任何权限。且该 filesystem 具有 5GB 的容量。

    • 目标：理解档案系统的建置、自动挂载档案系统与专案开发必须要的权限；
    • 前提：你需要进行过第七章的情境模拟才可以继续本章；
    • 需求：本章的所有概念必须要清楚！

    那就让我们开始来处理这个流程吧！

    1. 首先，我们必须要使用 fdisk /dev/hdc 来建立新的 partition ，由于本章之前范例的 partition 已经在上一个练习中删除， 因此你应该会多出一个 /dev/hdc6 才对：‘fdisk /dev/hdc’，然后按下‘ n ’，按下‘Enter’选择预设的启始磁柱， 按下‘+5000M’建立 5GB 的磁碟分割槽，可以多按一次‘p ’看看是否正确，若无问题则按下‘w’写入分割表；

    2. 避免重新开机，因此使用‘ partprobe ’强制核心更新分割表；如果荧幕出现类似：‘ end_request: I/O error dev fd0, sector 0 ’的错误时，不要担心啊！这个说明的是‘找不到软碟’，我们本来就没有软碟， 所以这个错误是可以忽略的。

    3. 建立完毕后，开始进行格式化的动作如下：‘mkfs -t ext3 /dev/hdc6’，这样就 OK 了！

    4. 开始建立挂载点，利用：‘ mkdir /srv/myproject ’来建立即可；

    5. 编写自动挂载的设定档：‘ nano /etc/fstab ’，这个档案最底下新增一行，内容如下：
      /dev/hdc6 /srv/myproject ext3 defaults 1 2

    6. 测试自动挂载：‘ mount -a ’，然后使用‘ df ’观察看看有无挂载即可！

    7. 设定最后的权限，使用：‘ chgrp project /srv/myproject ’以及‘ chmod 2770 /srv/myproject ’即可。
简答题部分：
  • 如果由于你的主机磁碟容量不够大，你想要增加一颗新磁碟，并将该磁碟全部分割成单一分割槽，且将该分割槽挂载到 /home 目录， 你该如何处置？
    详细的流程可以分为硬体组装、磁碟分割、格式化、资料搬移与挂载等。
    • 安装硬碟：关掉 Linux 主机电源，若为 IDE 介面时，需要处理跳针 (jump) ，放入主机后插好硬碟的排线与电源线，重新启动电源；
    • 磁碟分割：透过类似上述情境模拟二的动作，将整颗磁碟分割成单一主要分割槽，类似 /dev/sdb1 占有全部容量；
    • 格式化：透过 mkfs -t ext3 来格式化；
    • 资料搬移：由于原本的 /home 还会有资料存在，因此你可以 mount /dev/sdb1 /mnt ，再将 /home 的资料复制到 /mnt/ 中，例如：‘ cp -a /home/* /mnt ’即可。复制完毕后卸载 /home 以及 /mnt
    • 重新挂载：编辑 /etc/fstab ，将 /home 所在的 filesystem 装置改为 /dev/sdb1 之类的新分割槽，然后 mount -a 测试看看是否正确，如果正确的话，才是顺利结束了这次的动作。
  • 如果磁区 /dev/hda3 有问题，偏偏他是被挂载上的，请问我要如何修理此一磁区？
    umount /dev/hda3
    fsck /dev/hda3
  • 我们常常说，开机的时候，‘发现硬碟有问题’，请问，这个问题的产生是‘filesystem 的损毁’，还是‘硬碟的损毁’？
    特别需要注意的是，如果您某个 filesystem 里面，由于操作不当，可能会造成 Superblock 资料的损毁， 或者是 inode 的架构损毁，或者是 block area 的记录遗失等等，这些问题当中，其实您的‘硬碟’还是好好的， 不过，在硬碟上面的‘档案系统’则已经无法再利用！一般来说，我们的 Linux 很少会造成 filesystem 的损毁， 所以，发生问题时，很可能整个硬碟都损毁了。但是，如果您的主机常常不正常断电，那么， 很可能硬碟是没问题的，但是，档案系统则有损毁之虞。此时，重建档案系统 (reinstall) 即可！ 不需要换掉硬碟啦！ ^_^
  • 当我有两个档案，分别是 file1 与 file2 ，这两个档案互为 hard link 的档案，请问， 若我将 file1 删除，然后再以类似 vi 的方式重新建立一个名为 file1 的档案， 则 file2 的内容是否会被更动？
    这是来自网友的疑问。当我删除 file1 之后， file2 则为一个正规档案，并不会与他人共同分享同一个 inode 与 block ，因此，当我重新建立一个档名为 file1 时，他所利用的 inode 与 block 都是由我们的 filesystem 主动去搜寻 meta data ，找到空的 inode 与 block 来建立的， 与原本的 file1 并没有任何关连性喔！所以，新建的 file1 并不会影响 file2 呢！
大标题的图示 参考资料与延伸阅读
  • 注1：根据The Linux Document Project的文件所绘制的图示，详细的参考文献可以参考如下连结：
    Filesystem How-To: http://tldp.org/HOWTO/Filesystems-HOWTO-6.html
  • 注2：参考维基百科所得资料，连结网址如下：
    条目： Ext2 介绍 http://en.wikipedia.org/wiki/Ext2
  • 注3：PAVE为一套秀图软体，常应用于数值模式的输出档案之再处理：
    PAVE 使用手册： http://www.ie.unc.edu/cempd/EDSS/pave_doc/index.shtml
  • 注4：详细的 inode 表格所定义的旗标可以参考如下连结：
    John's spec of the second extended filesystem: http://uranus.it.swin.edu.au/~jn/explore2fs/es2fs.htm
  • 注5：参考 Ext2 官网提供的解说文件，这份文件非常值得参考的！
    文章名称：‘Design and Implementation of the Second Extended Filesystem ’
    http://e2fsprogs.sourceforge.net/ext2intro.html
  • 注6：Red Hat 自己推出的白皮书内容：
    文章名称：Whitepaper: Red Hat's New Journaling File System: ext3
    http://www.redhat.com/support/wpapers/redhat/ext3/
  • 注7：其他值得参考的 Ext2 相关档案系统文章之连结如下：
    The Second Extended File System - An introduction: http://www.freeos.com/articles/3912/
    ext3 or ReiserFS? Hans Reiser Says Red Hat's Move Is Understandable
    http://www.linuxplanet.com/linuxplanet/reports/3726/1/ 档案系统的比较：维基百科：http://en.wikipedia.org/wiki/Comparison_of_file_systems
  • 注8：NTFS 档案系统官网：Linux-NTFS Project: http://www.linux-ntfs.org/
  • 注9： Linux 核心所支援的硬体之装置代号(Major, Minor)查询：
    http://www.kernel.org/pub/linux/docs/device-list/devices.txt
  • 注10：与 Boot sector 及 Superblock 的探讨有关的讨论文章：
    The Second Extended File System: http://www.nongnu.org/ext2-doc/ext2.html
    Rob's ext2 documentation: http://www.landley.net/code/toybox/ext2.html
    Life is different blog: ext2文件系统分析： http://www.qdhedu.com/blog/post/7.html
2002/07/15：第一次完成
2003/02/07：重新编排与加入 FAQ
2004/03/15：修改 inode 的说明，并且将连结档的说明移动至这个章节当中！
2005/07/20：将旧的文章移动到 这里 。
2005/07/22：将原本的附录一与附录二移动成为附录 B 啦！
2005/07/26：做了一个比较完整的修订，加入较完整的 ext3 的说明～
2005/09/08：看到了一篇讨论，说明 FC4 在预设的环境中，使用 mkswap 会有问题。
2005/10/11：新增加了一个目录的 link 数量说明！
2005/11/11：增加了一个 fsck 的 -f 参数在里头！
2006/03/02：参考：这里的说明，将 ext2/ext3 最大档案系统由 16TB 改为 32TB。
2006/03/31：增加了虚拟记忆体的相关说明在 这里
2006/05/01：将硬碟磁区的图做个修正，感谢网友 LiaoLiang 兄提供的资讯！并加入参考文献！
2006/06/09：增加 hard link 不能连结到目录的原因，详情参考：http://phorum.study-area.org/viewtopic.php?t=12235
2006/06/28：增加关于 loop device 的相关说明呐！
2006/09/08：加入 mknod 内的装置代号说明 ，以及列出 Linux 核心网站的装置代号查询。
2008/09/29：原本的FC4系列文章移动到此处
2008/10/24：由于软碟的使用已经越来越少了，所以将 fdformat 及 mkbootdisk 拿掉了！
2008/10/31：这个月事情好多～花了一个月才将资料整理完毕！修改幅度非常的大喔！
2008/11/01：最后一节的利用 GNU 的 parted 进行分割行为误植为 GUN ！感谢网友阿贤的来信告知！
2008/12/05：感谢网友 ian_chen 的告知，之前将 flash 当成 flush 了！真抱歉！已更新！
2009/04/01：感谢讨论区网友提供的说明， 鸟哥之前 superblock 这里写得不够好，有订正说明，请帮忙看看。
2009/08/19：加入两题情境模拟，重新修订一题简答题。
2009/08/30：加入 du 的 -S 说明中。


鸟哥的 Linux 私房菜 -- 基础学习篇

为取得较佳浏览结果，请爱用 firefox 浏览本网页

第九章、档案与档案系统的压缩与打包
最近更新日期：2009/08/20
在 Linux 底下有相当多的压缩指令可以运作喔！这些压缩指令可以让我们更方便从网路上面下载大型的档案呢！ 此外，我们知道在 Linux 底下的副档名是没有什么很特殊的意义的，不过，针对这些压缩指令所做出来的压缩档， 为了方便记忆，还是会有一些特殊的命名方式啦！就让我们来看看吧！

1. 压缩档案的用途与技术
2. Linux 系统常见的压缩指令
    2.1 compress
    2.2 gzip, zcat
    2.3 bzip2, bzcat
 3. 打包指令: tar
4. 完整备份工具：dump, restore
5. 光碟写入工具
    5.1 mkisofs：建立映像档
    5.2 cdrecord：光碟烧录工具
 6. 其他常见的压缩与备份工具
    6.1 dd
    6.2 cpio
 7. 重点回顾
8. 本章习题
9. 参考资料与延伸阅读
10. 针对本文的建议：http://phorum.vbird.org/viewtopic.php?t=23882
大标题的图示 压缩档案的用途与技术

你是否有过文件档案太大，导致无法以一片软碟将他复制完成的困扰？ 又，你是否有过，发现一个软体里面有好多档案，这些档案要将他复制与携带都很不方便的问题？ 还有，你是否有过要备份某些重要资料，偏偏这些资料量太大了，耗掉了你很多的硬碟与磁碟空间呢？ 这个时候，那个好用的‘档案压缩’技术可就派的上用场了！

因为这些比较大型的档案透过所谓的档案压缩技术之后，可以将他的磁碟使用量降低， 可以达到减低档案容量的效果，此外，有的压缩程式还可以进行容量限制， 使一个大型档案可以分割成为数个小型档案，以方便软碟片携带呢！

那么什么是‘档案压缩’呢？我们来稍微谈一谈他的原理好了。目前我们使用的电脑系统中都是使用所谓的 bytes 单位来计量的！不过，事实上，电脑最小的计量单位应该是 bits 才对啊，此外，我们也知道 1 byte = 8 bits 。但是如果今天我们只是记忆一个数字，亦即是 1 这个数字呢？他会如何记录？假设一个 byte 可以看成底下的模样：

□□□□□□□□
Tips:
由于 1 byte = 8 bits ，所以每个 byte 当中会有 8 个空格，而每个空格可以是 0, 1 ，这里仅是做为一个约略的介绍， 更多的详细资料请参考第零章的计算机概论吧！ 		鸟哥的图示

由于我们记录数字是 1 ，考虑电脑所谓的二进位喔，如此一来， 1 会在最右边占据 1 个 bit ，而其他的 7 个 bits 将会自动的被填上 0 啰！你看看，其实在这样的例子中，那 7 个 bits 应该是‘空的’才对！不过，为了要满足目前我们的作业系统资料的存取，所以就会将该资料转为 byte 的型态来记录了！而一些聪明的电脑工程师就利用一些复杂的计算方式， 将这些没有使用到的空间‘丢’出来，以让档案占用的空间变小！这就是压缩的技术啦！

另外一种压缩技术也很有趣，他是将重复的资料进行统计记录的。举例来说，如果你的资料为‘111....’共有100个1时， 那么压缩技术会记录为‘100个1’而不是真的有100个1的位元存在！这样也能够精简档案记录的容量呢！ 非常有趣吧！

简单的说，你可以将他想成，其实档案里面有相当多的‘空间’存在，并不是完全填满的， 而‘压缩’的技术就是将这些‘空间’填满，以让整个档案占用的容量下降！ 不过，这些‘压缩过的档案’并无法直接被我们的作业系统所使用的，因此， 若要使用这些被压缩过的档案资料，则必须将他‘还原’回来未压缩前的模样， 那就是所谓的‘解压缩’啰！而至于压缩前与压缩后的档案所占用的磁碟空间大小， 就可以被称为是‘压缩比’啰！更多的技术文件或许你可以参考一下：

  • RFC 1952 文件：http://www.ietf.org/rfc/rfc1952.txt
  • 鸟哥站上的备份：http://linux.vbird.org/linux_basic/0240tarcompress/0240tarcompress_gzip.php

这个‘压缩’与‘解压缩’的动作有什么好处呢？最大的好处就是压缩过的档案容量变小了， 所以你的硬碟容量无形之中就可以容纳更多的资料。此外，在一些网路资料的传输中，也会由于资料量的降低， 好让网路频宽可以用来作更多的工作！而不是老是卡在一些大型的档案传输上面呢！目前很多的 WWW 网站也是利用档案压缩的技术来进行资料的传送，好让网站频宽的可利用率上升喔！

Tips:
上述的WWW网站压缩技术蛮有趣的！他让你网站上面‘看的到的资料’在经过网路传输时，使用的是‘压缩过的资料’， 等到这些压缩过的资料到达你的电脑主机时，再进行解压缩，由于目前的电脑运算速度相当的快速， 因此其实在网页浏览的时候，时间都是花在‘资料的传输’上面，而不是 CPU 的运算啦！如此一来，由于压缩过的资料量降低了，自然传送的速度就会增快不少！ 		鸟哥的图示

若你是一位软体工程师，那么相信你也会喜欢将你自己的软体压缩之后提供大家下载来使用， 毕竟没有人喜欢自己的网站天天都是频宽满载的吧？举个例子来说， Linux 2.6.27.4 完整的核心大小约有 300 MB 左右，而由于核心主要多是 ASCII code 的纯文字型态档案，这种档案的‘多余空间’最多了。而一个提供下载的压缩过的 2.6.27.4 核心大约仅有 60MB 左右，差了几倍呢？你可以自己算一算喔！

大标题的图示 Linux 系统常见的压缩指令：

在Linux的环境中，压缩档案的副档名大多是：‘*.tar, *.tar.gz, *.tgz, *.gz, *.Z, *.bz2’，为什么会有这样的副档名呢？不是说 Linux 的副档名没有什么作用吗？

这是因为 Linux 支援的压缩指令非常多，且不同的指令所用的压缩技术并不相同，当然彼此之间可能就无法互通压缩/解压缩档案啰。 所以，当你下载到某个压缩档时，自然就需要知道该档案是由哪种压缩指令所制作出来的，好用来对照着解压缩啊！ 也就是说，虽然 Linux 档案的属性基本上是与档名没有绝对关系的， 但是为了帮助我们人类小小的脑袋瓜子，所以适当的副档名还是必要的！ 底下我们就列出几个常见的压缩档案副档名吧：

*.Z         compress 程式压缩的档案；
*.gz        gzip 程式压缩的档案；
*.bz2       bzip2 程式压缩的档案；
*.tar       tar 程式打包的资料，并没有压缩过；
*.tar.gz    tar 程式打包的档案，其中并且经过 gzip 的压缩
*.tar.bz2   tar 程式打包的档案，其中并且经过 bzip2 的压缩

Linux上常见的压缩指令就是 gzip 与 bzip2 ，至于 compress 已经退流行了。 gzip 是由 GNU 计划所开发出来的压缩指令，该指令已经取代了 compress 。 后来 GNU 又开发出 bzip2 这个压缩比更好的压缩指令！不过，这些指令通常仅能针对一个档案来压缩与解压缩，如此一来， 每次压缩与解压缩都要一大堆档案，岂不烦人？此时，那个所谓的‘打包软体, tar’就显的很重要啦！

这个 tar 可以将很多档案‘打包’成为一个档案！甚至是目录也可以这么玩。不过，单纯的 tar 功能仅是‘打包’而已，亦即是将很多档案集结成为一个档案， 事实上，他并没有提供压缩的功能，后来，GNU 计划中，将整个 tar 与压缩的功能结合在一起，如此一来提供使用者更方便并且更强大的压缩与打包功能！ 底下我们就来谈一谈这些在 Linux 底下基本的压缩指令吧！

小标题的图示 compress

compress这个压缩指令是非常老旧的一款，大概只有在非常旧的 Unix 机器上面还会找到这个软体。 我们的 CentOS 预设并没有安装这个软体到系统当中，所以想要了解这个软体的使用时，请先安装 ncompress 这个软体。 不过，由于 gzip 已经可以解开使用 compress 压缩的档案，因此， compress 可以不用学习啦！ 但是，如果你所在的环境还是有老旧的系统，那么还是得要学一学就是了。好了， 如果你有网路的话，那么安装其实很简单喔！

[root@www ~]# yum install ncompress
base        100% |=========================| 1.1 kB    00:00
updates     100% |=========================|  951 B    00:00
addons      100% |=========================|  951 B    00:00
extras      100% |=========================| 1.1 kB    00:00
Setting up Install Process
Parsing package install arguments
Resolving Dependencies              <==开始分析相依性

--> Running transaction check
---> Package ncompress.i386 0:4.2.4-47 set to be updated
--> Finished Dependency Resolution

Dependencies Resolved

=======================================================
 Package       Arch   Version     Repository     Size
=======================================================
Installing:
 ncompress     i386   4.2.4-47    base            23 k

Transaction Summary
=======================================================
Install      1 Package(s)  <==最后分析所要安装的软体数
Update       0 Package(s)
Remove       0 Package(s)

Total download size: 23 k
Is this ok [y/N]: y    <==这里请按下 y 来确认安装
Downloading Packages:
(1/1): ncompress-4.2.4-47 100% |=========================|  23 kB    00:00
warning: rpmts_HdrFromFdno: Header V3 DSA signature: NOKEY, key ID e8562897
Importing GPG key 0xE8562897 "CentOS-5 Key (CentOS 5 Official Signing Key)
<centos-5-key@centos.org>" from http://mirror.centos.org/centos/RPM-GPG-KEY-CentOS-5
Is this ok [y/N]: y    <==这里则是与数位签章有关

Running rpm_check_debug
Running Transaction Test
Finished Transaction Test
Transaction Test Succeeded
Running Transaction
  Installing: ncompress          ######################### [1/1]

Installed: ncompress.i386 0:4.2.4-47
Complete!

关于 yum 更详细的用法我们会在后续的章节介绍，这里仅是提供一个大概的用法而已。 等你安装好这个软体后，接下来让我们看看如何使用 compress 吧！

[root@www ~]# compress [-rcv] 档案或目录  <==这里是压缩
[root@www ~]# uncompress 档案.Z           <==这里是解压缩

选项与参数：
-r  ：可以连同目录下的档案也同时给予压缩呢！
-c  ：将压缩资料输出成为 standard output (输出到荧幕)
-v  ：可以秀出压缩后的档案资讯以及压缩过程中的一些档名变化。

范例一：将 /etc/man.config 复制到 /tmp ，并加以压缩
[root@www ~]# cd /tmp
[root@www tmp]# cp /etc/man.config .
[root@www tmp]# compress -v man.config
man.config:  -- replaced with man.config.Z Compression: 41.86%
[root@www tmp]# ls -l /etc/man.config /tmp/man*

-rw-r--r-- 1 root root 4617 Jan  6  2007 /etc/man.config   <==原有档案
-rw-r--r-- 1 root root 2684 Nov 10 17:14 /tmp/man.config.Z <==经过压缩的档案！

不知道你有没有发现，复制到 /tmp 的 man.config 不见了！因为被压缩成为 man.config.Z 啰 也就是说，在预设的情况中，被 compress 压缩的原始档案会不见，而压缩档案会被建立起来， 而且副档名会是 *.Z。仔细看一下，档案由原本的 4617bytes 降低到 2684bytes左右，确实有减少一点啦！ 那么如何解压缩呢？

范例二：将刚刚的压缩档解开
[root@www tmp]# uncompress man.config.Z
[root@www tmp]# ll man*
-rw-r--r-- 1 root root 4617 Nov 10 17:14 man.config

解压缩直接用 uncompress 即可！解压缩完毕后该档案就自动的变回来了！不过，那个压缩档却又不存在啰～ 这样可以理解用法了吗？那如果我想要保留原始档案且又要建立压缩档呢？可以使用 -c 的语法！

范例三：将 man.config 压缩成另外一个档案来备份
[root@www tmp]# compress -c man.config > man.config.back.Z
[root@www tmp]# ll man*
-rw-r--r-- 1 root root 4617 Nov 10 17:14 man.config
-rw-r--r-- 1 root root 2684 Nov 10 17:24 man.config.back.Z
# 这个 -c 的选项比较有趣！他会将压缩过程的资料输出到荧幕上，而不是写入成为
# *.Z 的压缩档。所以，我们可以透过资料流重导向的方法将资料输出成为另一个档名。
# 关于资料流重导向，我们会在第十一章 bash 详细谈论的啦！

再次强调，compress 已经很少人在使用了，因为这支程式无法解开 *.gz 的档案，而 gzip 则可以解开 *.Z 的档案， 所以，如果你的 distribution 上面没有 compress 的话，那就不要进行上面的练习啰！ ^_^

小标题的图示 gzip, zcat

gzip 可以说是应用度最广的压缩指令了！目前 gzip 可以解开 compress, zip 与 gzip 等软体所压缩的档案。 至于 gzip 所建立的压缩档为 *.gz 的档名喔！让我们来看看这个指令的语法吧：

[root@www ~]# gzip [-cdtv#] 档名
[root@www ~]# zcat 档名.gz
选项与参数：
-c  ：将压缩的资料输出到荧幕上，可透过资料流重导向来处理；
-d  ：解压缩的参数；
-t  ：可以用来检验一个压缩档的一致性～看看档案有无错误；
-v  ：可以显示出原档案/压缩档案的压缩比等资讯；
-#  ：压缩等级，-1 最快，但是压缩比最差、-9 最慢，但是压缩比最好！预设是 -6

范例一：将 /etc/man.config 复制到 /tmp ，并且以 gzip 压缩
[root@www ~]# cd /tmp
[root@www tmp]# cp /etc/man.config .

[root@www tmp]# gzip -v man.config
man.config:      56.1% -- replaced with man.config.gz
[root@www tmp]# ll /etc/man.config /tmp/man*
-rw-r--r-- 1 root root 4617 Jan  6  2007 /etc/man.config
-rw-r--r-- 1 root root 2684 Nov 10 17:24 /tmp/man.config.back.Z
-rw-r--r-- 1 root root 2057 Nov 10 17:14 /tmp/man.config.gz  <==gzip压缩比较佳

与 compress 类似的，当你使用 gzip 进行压缩时，在预设的状态下原本的档案会被压缩成为 .gz 的档名， 原始档案就不再存在了。您也可以发现，由于 gzip 的压缩比要比 compress 好的多，所以当然建议使用 gzip 啦！ 此外，使用 gzip 压缩的档案在 Windows 系统中，竟然可以被 WinRAR 这个软体解压缩呢！很好用吧！至于其他的用法如下：

范例二：由于 man.config 是文字档，请将范例一的压缩档的内容读出来！
[root@www tmp]# zcat man.config.gz
# 由于 man.config 这个原本的档案是是文字档，因此我们可以尝试使用 zcat  去读取！
# 此时荧幕上会显示 man.config.gz 解压缩之后的档案内容！

范例三：将范例一的档案解压缩
[root@www tmp]# gzip -d man.config.gz

# 不要使用 gunzip 这个指令，不好背！使用 gzip -d 来进行解压缩！
# 与 gzip 相反， gzip -d 会将原本的 .gz 删除，产生原本的 man.config 档案。

范例四：将范例三解开的 man.config 用最佳的压缩比压缩，并保留原本的档案
[root@www tmp]# gzip -9 -c man.config > man.config.gz

其实 gzip 的压缩已经最佳化过了，所以虽然 gzip 提供 1~9 的压缩等级，不过使用预设的 6 就非常好用了！ 因此上述的范例四可以不要加入那个 -9 的选项。范例四的重点在那个 -c 与 > 的使用啰！

cat 可以读取纯文字档，那个 zcat 则可以读取纯文字档被压缩后的压缩档！ 由于 gzip 这个压缩指令主要想要用来取代 compress 的，所以不但 compress 的压缩档案可以使用 gzip 来解开，同时 zcat 这个指令可以同时读取 compress 与 gzip 的压缩档呦！

小标题的图示 bzip2, bzcat

若说 gzip 是为了取代 compress 并提供更好的压缩比而成立的，那么 bzip2 则是为了取代 gzip 并提供更佳的压缩比而来的。 bzip2 真是很不错用的东西～这玩意的压缩比竟然比 gzip 还要好～至于 bzip2 的用法几乎与 gzip 相同！ 看看底下的用法吧！

[root@www ~]# bzip2 [-cdkzv#] 档名
[root@www ~]# bzcat 档名.bz2
选项与参数：
-c  ：将压缩的过程产生的资料输出到荧幕上！
-d  ：解压缩的参数
-k  ：保留原始档案，而不会删除原始的档案喔！
-z  ：压缩的参数
-v  ：可以显示出原档案/压缩档案的压缩比等资讯；
-#  ：与 gzip 同样的，都是在计算压缩比的参数， -9 最佳， -1 最快！

范例一：将刚刚的 /tmp/man.config 以 bzip2 压缩
[root@www tmp]# bzip2 -z man.config
# 此时 man.config 会变成 man.config.bz2 ！

范例二：将范例一的档案内容读出来！
[root@www tmp]# bzcat man.config.bz2
# 此时荧幕上会显示 man.config.bz2 解压缩之后的档案内容！！

范例三：将范例一的档案解压缩
[root@www tmp]# bzip2 -d man.config.bz2

范例四：将范例三解开的 man.config 用最佳的压缩比压缩，并保留原本的档案
[root@www tmp]# bzip2 -9 -c man.config > man.config.bz2
使用 compress 副档名自动建立为 .Z ，使用 gzip 副档名自动建立为 .gz 。这里的 bzip2 则是自动的将副档名建置为 .bz2 啰！所以当我们使用具有压缩功能的 bzip2 -z 时，那么刚刚的 man.config 就会自动的变成了 man.config.bz2 这个档名啰！

好了，那么如果我想要读取这个档案的内容呢？ 是否一定要解开？当然不需要啰！可以使用简便的 bzcat 这个指令来读取内容即可！例如上面的例子中， 我们可以使用 bzcat man.config.bz2 来读取资料而不需要解开！此外，当你要解开一个压缩档时， 这个档案的名称为 .bz, .bz2, .tbz, .tbz2 等等，那么就可以尝试使用 bzip2 来解看看啦！当然啰，也可以使用 bunzip2 这个指令来取代 bzip2 -d 啰。

大标题的图示 打包指令： tar

前一小节谈到的指令大多仅能针对单一档案来进行压缩，虽然 gzip 与 bzip2 也能够针对目录来进行压缩， 不过，这两个指令对目录的压缩指的是‘将目录内的所有档案 "分别" 进行压缩’的动作！ 而不像在 Windows 的系统，可以使用类似 WinRAR 这一类的压缩软体来将好多资料‘包成一个档案’的样式。

这种将多个档案或目录包成一个大档案的指令功能，我们可以称呼他是一种‘打包指令’啦！ 那 Linux 有没有这种打包指令呢？是有的！那就是鼎鼎大名的 tar 这个玩意儿了！ tar 可以将多个目录或档案打包成一个大档案，同时还可以透过 gzip/bzip2 的支援，将该档案同时进行压缩！ 更有趣的是，由于 tar 的使用太广泛了，目前 Windows 的 WinRAR 也支援 .tar.gz 档名的解压缩呢！ 很不错吧！所以底下我们就来玩一玩这个咚咚！

小标题的图示 tar

tar 的选项与参数非常的多！我们只讲几个常用的选项，更多选项您可以自行 man tar 查询啰！

[root@www ~]# tar [-j|-z] [cv] [-f 建立的档名] filename... <==打包与压缩

[root@www ~]# tar [-j|-z] [tv] [-f 建立的档名]             <==察看档名
[root@www ~]# tar [-j|-z] [xv] [-f 建立的档名] [-C 目录]   <==解压缩
选项与参数：
-c  ：建立打包档案，可搭配 -v 来察看过程中被打包的档名(filename)
-t  ：察看打包档案的内容含有哪些档名，重点在察看‘档名’就是了；
-x  ：解打包或解压缩的功能，可以搭配 -C (大写) 在特定目录解开
      特别留意的是， -c, -t, -x 不可同时出现在一串指令列中。
-j  ：透过 bzip2 的支援进行压缩/解压缩：此时档名最好为 *.tar.bz2
-z  ：透过 gzip  的支援进行压缩/解压缩：此时档名最好为 *.tar.gz
-v  ：在压缩/解压缩的过程中，将正在处理的档名显示出来！
-f filename：-f 后面要立刻接要被处理的档名！建议 -f 单独写一个选项啰！
-C 目录    ：这个选项用在解压缩，若要在特定目录解压缩，可以使用这个选项。

其他后续练习会使用到的选项介绍：
-p  ：保留备份资料的原本权限与属性，常用于备份(-c)重要的设定档
-P  ：保留绝对路径，亦即允许备份资料中含有根目录存在之意；
--exclude=FILE：在压缩的过程中，不要将 FILE 打包！

其实最简单的使用 tar 就只要记忆底下的方式即可：

  • 压　缩：tar -jcv -f filename.tar.bz2 要被压缩的档案或目录名称
  • 查　询：tar -jtv -f filename.tar.bz2
  • 解压缩：tar -jxv -f filename.tar.bz2 -C 欲解压缩的目录

那个 filename.tar.bz2 是我们自己取的档名，tar 并不会主动的产生建立的档名喔！我们要自订啦！ 所以副档名就显的很重要了！如果不加 [-j|-z] 的话，档名最好取为 *.tar 即可。如果是 -j 选项，代表有 bzip2 的支援，因此档名最好就取为 *.tar.bz2 ，因为 bzip2 会产生 .bz2 的副档名之故！ 至于如果是加上了 -z 的 gzip 的支援，那档名最好取为 *.tar.gz 喔！了解乎？

另外，由于‘ -f filename ’是紧接在一起的，过去很多文章常会写成‘-jcvf filename’，这样是对的， 但由于选项的顺序理论上是可以变换的，所以很多读者会误认为‘-jvfc filename’也可以～事实上这样会导致产生的档名变成 c ！ 因为 -fc 嘛！所以啰，建议您在学习 tar 时，将‘ -f filename ’与其他选项独立出来，会比较不容易发生问题。

闲话少说，让我们来测试几个常用的 tar 方法吧！

  • 使用 tar 加入 -j 或 -z 的参数备份 /etc/ 目录

有事没事备份一下 /etc 这个目录是件好事！备份 /etc 最简单的方法就是使用 tar 啰！让我们来玩玩先：

[root@www ~]# tar -zpcv -f /root/etc.tar.gz /etc
tar: Removing leading `/' from member names  <==注意这个警告讯息
/etc/
....中间省略....
/etc/esd.conf
/etc/crontab
# 由于加上 -v 这个选项，因此正在作用中的档名就会显示在荧幕上。
# 如果你可以翻到第一页，会发现出现上面的错误讯息！底下会讲解。
# 至于 -p 的选项，重点在于‘保留原本档案的权限与属性’之意。

[root@www ~]# tar -jpcv -f /root/etc.tar.bz2 /etc
# 显示的讯息会跟上面一模一样啰！

[root@www ~]# ll /root/etc*
-rw-r--r-- 1 root root  8740252 Nov 15 23:07 /root/etc.tar.bz2
-rw-r--r-- 1 root root 13010999 Nov 15 23:01 /root/etc.tar.gz
[root@www ~]# du -sm /etc

118     /etc
# 为什么建议您使用 -j 这个选项？从上面的数值你可以知道了吧？^_^

由上述的练习，我们知道使用 bzip2 亦即 -j 这个选项来制作备份时，能够得到比较好的压缩比！ 如上表所示，由原本的 /etc/ (118MBytes) 下降到 8.7Mbytes 左右！至于加上‘ -p ’这个选项的原因是为了保存原本档案的权限与属性！我们曾在第七章的 cp 指令介绍时谈到权限与档案类型(例如连结档)对复制的不同影响。 同样的，在备份重要的系统资料时，这些原本档案的权限需要做完整的备份比较好。此时 -p 这个选项就派的上用场了。 接下来让我们看看打包档案内有什么资料存在？

  • 查阅 tar 档案的资料内容(可察看档名)，与备份档名有否根目录的意义

要察看档名非常的简单！可以这样做：

[root@www ~]# tar -jtv -f /root/etc.tar.bz2
....前面省略....
-rw-r--r-- root/root  1016 2008-05-25 14:06:20 etc/dbus-1/session.conf
-rw-r--r-- root/root   153 2007-01-07 19:20:54 etc/esd.conf
-rw-r--r-- root/root   255 2007-01-06 21:13:33 etc/crontab

如果加上 -v 这个选项时，详细的档案权限/属性都会被列出来！如果只是想要知道档名而已， 那么就将 -v 拿掉即可。从上面的资料我们可以发现一件很有趣的事情，那就是每个档名都没了根目录了！这也是上一个练习中出现的那个警告讯息‘tar: Removing leading `/' from member names(移除了档名开头的 `/' )’所告知的情况！

那为什么要拿掉根目录呢？主要是为了安全！我们使用 tar 备份的资料可能会需要解压缩回来使用， 在 tar 所记录的档名 (就是我们刚刚使用 tar -jtvf 所察看到的档名) 那就是解压缩后的实际档名。 如果拿掉了根目录，假设你将备份资料在 /tmp 解开，那么解压缩的档名就会变成‘/tmp/etc/xxx’。 但‘如果没有拿掉根目录，解压缩后的档名就会是绝对路径， 亦即解压缩后的资料一定会被放置到 /etc/xxx 去！’如此一来，你的原本的 /etc/ 底下的资料， 就会被备份资料所覆盖过去了！

Tips:
你会说：‘既然是备份资料，那么还原回来也没有什么问题吧？’想像一个状况，你备份的资料是一年前的旧版 CentOS 4.x， 你只是想要了解一下过去的备份内容究竟有哪些资料而已，结果一解开该档案，却发现你目前新版的 CentOS 5.x 底下的 /etc 被旧版的备份资料覆盖了！此时你该如何是好？所以啰，当然是拿掉根目录比较安全一些的。 		鸟哥的图示

如果你确定你就是需要备份根目录到 tar 的档案中，那可以使用 -P (大写) 这个选项，请看底下的例子分析：

范例：将档名中的(根)目录也备份下来，并察看一下备份档的内容档名
[root@www ~]# tar -jpPcv -f /root/etc.and.root.tar.bz2 /etc

....中间过程省略....
[root@www ~]# tar -jtf /root/etc.and.root.tar.bz2
/etc/dbus-1/session.conf
/etc/esd.conf
/etc/crontab
# 这次查阅档名不含 -v 选项，所以仅有档名而已！没有详细属性/权限等参数。

有发现不同点了吧？如果加上 -P 选项，那么档名内的根目录就会存在喔！不过，鸟哥个人建议，还是不要加上 -P 这个选项来备份！ 毕竟很多时候，我们备份是为了要未来追踪问题用的，倒不一定需要还原回原本的系统中！ 所以拿掉根目录后，备份资料的应用会比较有弹性！也比较安全呢！

  • 将备份的资料解压缩，并考虑特定目录的解压缩动作 (-C 选项的应用)

那如果想要解打包呢？很简单的动作就是直接进行解打包嘛！

[root@www ~]# tar -jxv -f /root/etc.tar.bz2
[root@www ~]# ll
....(前面省略)....

drwxr-xr-x 105 root root    12288 Nov 11 04:02 etc
....(后面省略)....

此时该打包档案会在‘本目录下进行解压缩’的动作！ 所以，你等一下就会在家目录底下发现一个名为 etc 的目录啰！所以啰，如果你想要将该档案在 /tmp 底下解开， 可以 cd /tmp 后，再下达上述的指令即可。不过，这样好像很麻烦呢～有没有更简单的方法可以‘指定欲解开的目录’呢？ 有的，可以使用 -C 这个选项喔！举例来说：

[root@www ~]# tar -jxv -f /root/etc.tar.bz2 -C /tmp
[root@www ~]# ll /tmp

....(前面省略)....
drwxr-xr-x 105 root root    12288 Nov 11 04:02 etc
....(后面省略)....

这样一来，你就能够将该档案在不同的目录解开啰！鸟哥个人是认为，这个 -C 的选项务必要记忆一下的！ 好了，处理完毕后，请记得将这两个目录删除一下呢！

[root@www ~]# rm -rf /root/etc /tmp/etc

再次强调，这个‘ rm -rf ’是很危险的指令！下达时请务必要确认一下后面接的档名。我们要删除的是 /root/etc 与 /tmp/etc， 您可不要将 /etc/ 删除掉了！系统会死掉的～ ^_^

  • 仅解开单一档案的方法

刚刚上头我们解压缩都是将整个打包档案的内容全部解开！想像一个情况，如果我只想要解开打包档案内的其中一个档案而已， 那该如何做呢？很简单的，你只要使用 -jtv 找到你要的档名，然后将该档名解开即可。 我们用底下的例子来说明一下：

# 1. 先找到我们要的档名，假设解开 shadow 档案好了：
[root@www ~]# tar -jtv -f /root/etc.tar.bz2 | grep 'shadow'

-r-------- root/root  1230 2008-09-29 02:21:20 etc/shadow-
-r-------- root/root   622 2008-09-29 02:21:20 etc/gshadow-
-r-------- root/root   636 2008-09-29 02:21:25 etc/gshadow
-r-------- root/root  1257 2008-09-29 02:21:25 etc/shadow  <==这是我们要的！
# 先搜寻重要的档名！其中那个 grep 是‘撷取’关键字的功能！我们会在第三篇说明！
# 这里您先有个概念即可！那个管线 | 配合 grep 可以撷取关键字的意思！

# 2. 将该档案解开！语法与实际作法如下：
[root@www ~]# tar -jxv -f 打包档.tar.bz2 待解开档名
[root@www ~]# tar -jxv -f /root/etc.tar.bz2 etc/shadow
etc/shadow
[root@www ~]# ll etc

total 8
-r-------- 1 root root 1257 Sep 29 02:21 shadow  <==呦喝！只有一个档案啦！
# 很有趣！此时只会解开一个档案而已！不过，重点是那个档名！你要找到正确的档名。
# 在本例中，你不能写成 /etc/shadow ！因为记录在 etc.tar.bz2 内的档名之故！

  • 打包某目录，但不含该目录下的某些档案之作法

假设我们想要打包 /etc/ /root 这几个重要的目录，但却不想要打包 /root/etc* 开头的档案， 因为该档案都是刚刚我们才建立的备份档嘛！而且假设这个新的打包档案要放置成为 /root/system.tar.bz2 ， 当然这个档案自己不要打包自己 (因为这个档案放置在 /root 底下啊！)，此时我们可以透过 --exclude 的帮忙！ 那个 exclude 就是不包含的意思！所以你可以这样做：

[root@www ~]# tar -jcv  -f /root/system.tar.bz2 --exclude=/root/etc* \

> --exclude=/root/system.tar.bz2  /etc /root

上面的指令是一整列的～其实你可以打成：‘tar -jcv -f /root/system.tar.bz2 --exclude=/root/etc* --exclude=/root/system.tar.bz2 /etc /root’，如果想要两行输入时，最后面加上反斜线 (\) 并立刻按下 [enter] ， 就能够到第二行继续输入了。这个指令下达的方式我们会在第三章再仔细说明。 透过这个 --exclude="file" 的动作，我们可以将几个特殊的档案或目录移除在打包之列， 让打包的动作变的更简便喔！^_^

另外，在新版的 tar 指令中，鸟哥发现原本的‘ --exclude file ’似乎无法实际运作了！使用 man tar 明明有看到这个选项的说， 但使用 info tar 才发现，选项功能已经变成了‘ --exclude=file ’的模式！这个地方得要特别留意呢！

  • 仅备份比某个时刻还要新的档案

某些情况下你会想要备份新的档案而已，并不想要备份旧档案！此时 --newer-mtime 这个选项就粉重要啦！ 其实有两个选项啦，一个是‘ --newer ’另一个就是‘ --newer-mtime ’，这两个选项有何不同呢？ 我们在 第七章的 touch 介绍中谈到过三种不同的时间参数， 当使用 --newer 时，表示后续的日期包含‘ mtime 与 ctime ’，而 --newer-mtime 则仅是 mtime 而已！ 这样知道了吧！ ^_^ 。那就让我们来尝试处理一下啰！

# 1. 先由 find 找出比 /etc/passwd 还要新的档案
[root@www ~]# find /etc -newer /etc/passwd
....(过程省略)....
# 此时会显示出比 /etc/passwd 这个档案的 mtime 还要新的档名，
# 这个结果在每部主机都不相同！您先自行查阅自己的主机即可，不会跟鸟哥一样！

[root@www ~]# ll /etc/passwd
-rw-r--r-- 1 root root 1945 Sep 29 02:21 /etc/passwd

# 2. 好了，那么使用 tar 来进行打包吧！日期为上面看到的 2008/09/29
[root@www ~]# tar -jcv -f /root/etc.newer.then.passwd.tar.bz2 \
> --newer-mtime="2008/09/29" /etc/*
....(中间省略)....

/etc/smartd.conf    <==真的有备份的档案
....(中间省略)....
/etc/yum.repos.d/   <==目录都会被记录下来！
tar: /etc/yum.repos.d/CentOS-Base.repo: file is unchanged; not dumped
# 最后行显示的是‘没有被备份的’，亦即 not dumped 的意思！

# 3. 显示出档案即可
[root@www ~]# tar -jtv -f /root/etc.newer.then.passwd.tar.bz2 | \

> grep -v '/$'
# 透过这个指令可以呼叫出 tar.bz2 内的结尾非 / 的档名！就是我们要的啦！

现在你知道这个指令的好用了吧！甚至可以进行差异档案的记录与备份呢～ 这样子的备份就会显的更容易啰！你可以这样想像，如果我在一个月前才进行过一次完整的资料备份， 那么这个月想要备份时，当然可以仅备份上个月进行备份的那个时间点之后的更新的档案即可！ 为什么呢？因为原本的档案已经有备份了嘛！干嘛还要进行一次？只要备份新资料即可。这样可以降低备份的容量啊！

  • 基本名称： tarfile, tarball ？

另外值得一提的是，tar 打包出来的档案有没有进行压缩所得到档案称呼不同喔！ 如果仅是打包而已，就是‘ tar -cv -f file.tar ’而已，这个档案我们称呼为 tarfile 。 如果还有进行压缩的支援，例如‘ tar -jcv -f file.tar.bz2 ’时，我们就称呼为 tarball (tar 球？)！ 这只是一个基本的称谓而已，不过很多书籍与网路都会使用到这个 tarball 的名称！ 所以得要跟您介绍介绍。

此外，tar 除了可以将资料打包成为档案之外，还能够将档案打包到某些特别的装置去，举例来说， 磁带机 (tape) 就是一个常见的例子。磁带机由于是一次性读取/写入的装置，因此我们不能够使用类似 cp 等指令来复制的！ 那如果想要将 /home, /root, /etc 备份到磁带机 (/dev/st0) 时，就可以使用：‘tar -cv -f /dev/st0 /home /root /etc’，很简单容易吧！ 磁带机用在备份 (尤其是企业应用) 是很常见的工作喔！

  • 特殊应用：利用管线命令与资料流

在 tar 的使用中，有一种方式最特殊，那就是透过标准输入输出的资料流重导向(standard input/standard output)， 以及管线命令 (pipe) 的方式，将待处理的档案一边打包一边解压缩到目标目录去。 关于资料流重导向与管线命令更详细的资料我们会在第十一章 bash 再跟大家介绍， 底下先来看一个例子吧！

# 1. 将 /etc 整个目录一边打包一边在 /tmp 解开
[root@www ~]# cd /tmp
[root@www ~]# tar -cvf - /etc | tar -xvf -
# 这个动作有点像是 cp -r /etc /tmp 啦～依旧是有其有用途的！
# 要注意的地方在于输出档变成 - 而输入档也变成 - ，又有一个 | 存在～
# 这分别代表 standard output, standard input 与管线命令啦！
# 简单的想法中，你可以将 - 想成是在记忆体中的一个装置(缓冲区)。
# 更详细的资料流与管线命令，请翻到 bash 章节啰！

在上面的例子中，我们想要‘将 /etc 底下的资料直接 copy 到目前所在的路径，也就是 /tmp 底下’，但是又觉得使用 cp -r 有点麻烦，那么就直接以这个打包的方式来打包，其中，指令里面的 - 就是表示那个被打包的档案啦！ 由于我们不想要让中间档案存在，所以就以这一个方式来进行复制的行为啦！

  • 例题：系统备份范例

系统上有非常多的重要目录需要进行备份，而且其实我们也不建议你将备份资料放置到 /root 目录下！ 假设目前你已经知道重要的目录有底下这几个：

  • /etc/ (设定档)
  • /home/ (使用者的家目录)
  • /var/spool/mail/ (系统中，所有帐号的邮件信箱)
  • /var/spool/cron/ (所有帐号的工作排成设定档)
  • /root (系统管理员的家目录)

然后我们也知道，由于第八章曾经做过的练习的关系， /home/loop* 不需要备份，而且 /root 底下的压缩档也不需要备份，另外假设你要将备份的资料放置到 /backups ，并且该目录仅有 root 有权限进入！ 此外，每次备份的档名都希望不相同，例如使用：backup-system-20091130.tar.bz2 之类的档名来处理。 那你该如何处理这个备份资料呢？(请先动手作看看，再来察看一下底下的参考解答！)

# 1. 先处理要放置备份资料的目录与权限：
[root@www ~]# mkdir /backups
[root@www ~]# chmod 700 /backups
[root@www ~]# ll -d /backups
drwx------ 2 root root 4096 Nov 30 16:35 /backups

# 2. 假设今天是 2009/11/30 ，则建立备份的方式如下：

[root@www ~]# tar -jcv -f /backups/backup-system-20091130.tar.bz2 \
> --exclude=/root/*.bz2 --exclude=/root/*.gz --exclude=/home/loop* \
> /etc /home /var/spool/mail /var/spool/cron /root
....(过程省略)....

[root@www ~]# ll -h /backups/
-rw-r--r-- 1 root root 8.4M Nov 30 16:43 backup-system-20091130.tar.bz2
大标题的图示 完整备份工具：dump

某些时刻你想要针对档案系统进行备份或者是储存的功能时，不能不谈到这个 dump 指令！ 这玩意儿我们曾在前一章的 /etc/fstab 里面稍微谈过。 其实这个指令除了能够针对整个 filesystem 备份之外，也能够仅针对目录来备份喔！ 底下就让我们来谈一谈这个指令的用法吧！

小标题的图示 dump

其实 dump 的功能颇强，他除了可以备份整个档案系统之外，还可以制定等级喔！什么意思啊！ 假设你的 /home 是独立的一个档案系统，那你第一次进行过 dump 后，再进行第二次 dump 时， 你可以指定不同的备份等级，假如指定等级为 1 时，此时新备份的资料只会记录与第一次备份所有差异的档案而已。 看不懂吗？没关系！我们用一张简图来说明。

图 4.1.1、dump 运作的等级 (level)

如上图所示，上方的‘即时档案系统’是一直随着时间而变化的资料，例如在 /home 里面的档案资料会一直变化一样。 而底下的方块则是 dump 备份起来的资料，第一次备份时使用的是 level 0 ，这个等级也是完整的备份啦！ 等到第二次备份时，即时档案系统内的资料已经与 level 0 不一样了，而 level 1 仅只是比较目前的档案系统与 level 0 之间的差异后，备份有变化过的档案而已。至于 level 2 则是与 level 1 进行比较啦！这样了解呼？

虽然 dump 支援整个档案系统或者是单一各别目录，但是对于目录的支援是比较不足的，这也是 dump 的限制所在。 简单的说，如果想要备份的资料如下时，则有不同的限制情况：

  • 当待备份的资料为单一档案系统：
    如果是单一档案系统 (filesystem) ，那么该档案系统可以使用完整的 dump 功能，包括利用 0~9 的数个 level 来备份， 同时，备份时可以使用挂载点或者是装置档名 (例如 /dev/sda5 之类的装置档名) 来进行备份！

  • 待备份的资料只是目录，并非单一档案系统：
    例如你仅想要备份 /home/someone/ ，但是该目录并非独立的档案系统时。此时备份就有限制啦！包括：

    • 所有的备份资料都必须要在该目录 (本例为：/home/someone/) 底下；
    • 且仅能使用 level 0 ，亦即仅支援完整备份而已；
    • 不支援 -u 选项，亦即无法建立 /etc/dumpdates 这个各别 level 备份的时间记录档；

dump 的选项虽然非常的繁复，不过如果只是想要简单的操作时，您只要记得底下的几个选项就很够用了！

[root@www ~]# dump [-Suvj] [-level] [-f 备份档] 待备份资料

[root@www ~]# dump -W
选项与参数：
-S    ：仅列出后面的待备份资料需要多少磁碟空间才能够备份完毕；
-u    ：将这次 dump 的时间记录到 /etc/dumpdates 档案中；
-v    ：将 dump 的档案过程显示出来；
-j    ：加入 bzip2 的支援！将资料进行压缩，预设 bzip2 压缩等级为 2
-level：就是我们谈到的等级，从 -0 ~ -9 共十个等级；
-f    ：有点类似 tar 啦！后面接产生的档案，亦可接例如 /dev/st0 装置档名等
-W    ：列出在 /etc/fstab 里面的具有 dump 设定的 partition 是否有备份过？
  • 用 dump 备份完整的档案系统

现在就让我们来做几个范例吧！假如你要将系统的最小的档案系统捉出来进行备份，那该如何进行呢？

# 1. 先找出系统中最小的那个档案系统，如下所示：

[root@www ~]# df -h
Filesystem            Size  Used Avail Use% Mounted on
/dev/hdc2             9.5G  3.7G  5.3G  42% /
/dev/hdc3             4.8G  651M  3.9G  15% /home
/dev/hdc1              99M   11M   83M  12% /boot  <==看起来最小的就是他啦！
tmpfs                 363M     0  363M   0% /dev/shm

# 2. 先测试一下，如果要备份此档案系统，需多少容量？
[root@www ~]# dump -S /dev/hdc1
5630976     <==注意一下，这个单位是 bytes ，所以差不多是 5.6MBytes。

# 3. 将完整备份的档名记录成为 /root/boot.dump ，同时更新记录档：
[root@www ~]# dump -0u -f /root/boot.dump /boot
  DUMP: Date of this level 0 dump: Tue Dec  2 02:53:45 2008 <==记录等级与备份时间
  DUMP: Dumping /dev/hdc1 (/boot) to /root/boot.dump        <==dump的来源与目标
  DUMP: Label: /boot                                        <==档案系统的 label

  DUMP: Writing 10 Kilobyte records
  DUMP: mapping (Pass I) [regular files]                    <==开始进行档案对应
  DUMP: mapping (Pass II) [directories]
  DUMP: estimated 5499 blocks.                              <==评估整体block数量
  DUMP: Volume 1 started with block 1 at: Tue Dec  2 02:53:46 2008
  DUMP: dumping (Pass III) [directories]                    <==开始 dump 工作
  DUMP: dumping (Pass IV) [regular files]
  DUMP: Closing /root/boot.dump                             <==结束写入备份档
  DUMP: Volume 1 completed at: Tue Dec  2 02:53:47 2008
  DUMP: Volume 1 5550 blocks (5.42MB)                       <==最终备份资料容量

  DUMP: Volume 1 took 0:00:01
  DUMP: Volume 1 transfer rate: 5550 kB/s
  DUMP: 5550 blocks (5.42MB) on 1 volume(s)
  DUMP: finished in 1 seconds, throughput 5550 kBytes/sec
  DUMP: Date of this level 0 dump: Tue Dec  2 02:53:45 2008
  DUMP: Date this dump completed:  Tue Dec  2 02:53:47 2008
  DUMP: Average transfer rate: 5550 kB/s
  DUMP: DUMP IS DONE
# 在指令的下达方面，dump 后面接 /boot 或 /dev/hdc1 都可以的！
# 而执行 dump 的过程中会出现如上的一些讯息，您可以自行仔细的观察！

[root@www ~]# ll /root/boot.dump /etc/dumpdates
-rw-rw-r-- 1 root disk      43 Dec  2 02:53 /etc/dumpdates
-rw-r--r-- 1 root root 5683200 Dec  2 02:53 /root/boot.dump
# 由于加上 -u 的选项，因此 /etc/dumpdates 该档案的内容会被更新！注意，
# 这个档案仅有在 dump 完整的档案系统时才有支援主动更新的功能。

# 4. 观察一下系统主动建立的记录档：
[root@www ~]# cat /etc/dumpdates

/dev/hdc1     0   Tue Dec  2 02:53:47 2008 +0800
[档案系统] [等级] [       ctime 的时间         ]

这样很简单的就建立起来 /root/boot.dump 档案，该档案将整个 /boot/ 档案系统都备份下来了！ 并且将备份的时间写入 /etc/dumpdates 档案中，准备让下次备份时可以作为一个参考依据。 现在让我们来进行一个测试，检查看看能否真的建立 level 1 的备份呢？

# 0. 看一下有没有任何档案系统被 dump 过的资料？
[root@www ~]# dump -W
Last dump(s) done (Dump '>' file systems):

> /dev/hdc2     (     /) Last dump: never
> /dev/hdc3     ( /home) Last dump: never
  /dev/hdc1     ( /boot) Last dump: Level 0, Date Tue Dec  2 02:53:47 2008
# 如上列的结果，该结果会捉出 /etc/fstab 里面第五栏位设定有需要 dump 的
# partition，然后与 /etc/dumpdates 进行比对，可以得到上面的结果啦！
# 尤其是第三行，可以显示我们曾经对 /dev/hdc1 进行过 dump 的备份动作喔！

# 1. 先恶搞一下，建立一个大约 10 MB 的档案在 /boot 内：

[root@www ~]# dd if=/dev/zero of=/boot/testing.img bs=1M count=10
10+0 records in
10+0 records out
10485760 bytes (10 MB) copied, 0.166128 seconds, 63.1 MB/s

# 2. 开始建立差异备份档，此时我们使用 level 1 吧：
[root@www ~]# dump -1u -f /root/boot.dump.1 /boot
....(中间省略)....

[root@www ~]# ll /root/boot*
-rw-r--r-- 1 root root  5683200 Dec  2 02:53 /root/boot.dump
-rw-r--r-- 1 root root 10547200 Dec  2 02:56 /root/boot.dump.1

# 看看档案大小，岂不是就是刚刚我们所建立的那个大档案的容量吗？ ^_^

# 3. 最后再看一下是否有记录 level 1 备份的时间点呢？
[root@www ~]# dump -W
Last dump(s) done (Dump '>' file systems):
> /dev/hdc2     (     /) Last dump: never
> /dev/hdc3     ( /home) Last dump: never
> /dev/hdc1     ( /boot) Last dump: Level 1, Date Tue Dec  2 02:56:33 2008

....(中间省略)....

透过这个简单的方式，我们就能够仅备份差异档案的部分啰！底下再来看看针对单一目录的 dump 用途！

  • 用 dump 备份非档案系统，亦即单一目录的方法

现在让我们来处理一下 /etc 的 dump 备份吧！因为 /etc 并非单一档案系统，他只是个目录而已。 所以依据限制的说明， -u, level 1~9 都是不适用的。我们只能够使用 level 0 的完整备份将 /etc 给他 dump 下来。因此作法就变的很简单了！

# 让我们将 /etc 整个目录透过 dump 进行备份，且含压缩功能
[root@www ~]# dump -0j -f /root/etc.dump.bz2 /etc
  DUMP: Date of this level 0 dump: Tue Dec  2 12:08:22 2008
  DUMP: Dumping /dev/hdc2 (/ (dir etc)) to /root/etc.dump.bz2
  DUMP: Label: /1
  DUMP: Writing 10 Kilobyte records
  DUMP: Compressing output at compression level 2 (bzlib)
  DUMP: mapping (Pass I) [regular files]
  DUMP: mapping (Pass II) [directories]
  DUMP: estimated 115343 blocks.
  DUMP: Volume 1 started with block 1 at: Tue Dec  2 12:08:23 2008
  DUMP: dumping (Pass III) [directories]
  DUMP: dumping (Pass IV) [regular files]
  DUMP: Closing /root/etc.dump.bz2
  DUMP: Volume 1 completed at: Tue Dec  2 12:09:49 2008
  DUMP: Volume 1 took 0:01:26
  DUMP: Volume 1 transfer rate: 218 kB/s
  DUMP: Volume 1 124680kB uncompressed, 18752kB compressed, 6.649:1
  DUMP: 124680 blocks (121.76MB) on 1 volume(s)
  DUMP: finished in 86 seconds, throughput 1449 kBytes/sec
  DUMP: Date of this level 0 dump: Tue Dec  2 12:08:22 2008
  DUMP: Date this dump completed:  Tue Dec  2 12:09:49 2008
  DUMP: Average transfer rate: 218 kB/s
  DUMP: Wrote 124680kB uncompressed, 18752kB compressed, 6.649:1
  DUMP: DUMP IS DONE
# 上面特殊字体的部分显示：原本有 124680kb  的容量，被压缩成为 18752kb，
# 整个压缩比为 6.649:1 ，还可以的压缩情况啦！

一般来说 dump 不会使用包含压缩的功能，不过如果你想要将备份的空间降低的话，那个 -j 的选项是可以使用的。 加上 -j 之后你的 dump 成果会使用较少的硬碟容量啦！如上述的情况来看，档案容量由原本的 128MB 左右下滑到 18MB 左右，当然可以节省备份空间啰！

小标题的图示 restore

备份档就是在急用时可以回复系统的重要资料，所以有备份当然就得要学学如何复原了！ dump 的复原使用的是 restore 这个指令！这个指令的选项也非常的多～您可以自行 man restore 瞧瞧！ 鸟哥在这里仅作个简单的介绍啰！

[root@www ~]# restore -t [-f dumpfile] [-h]        <==用来察看 dump 档

[root@www ~]# restore -C [-f dumpfile] [-D 挂载点] <==比较dump与实际档案
[root@www ~]# restore -i [-f dumpfile]             <==进入互动模式
[root@www ~]# restore -r [-f dumpfile]             <==还原整个档案系统
选项与参数：
相关的各种模式，各种模式无法混用喔！例如不可以写 -tC 啦！
-t  ：此模式用在察看 dump 起来的备份档中含有什么重要资料！类似 tar -t 功能；
-C  ：此模式可以将 dump 内的资料拿出来跟实际的档案系统做比较，
      最终会列出‘在 dump 档案内有记录的，且目前档案系统不一样’的档案；
-i  ：进入互动模式，可以仅还原部分档案，用在 dump 目录时的还原！
-r  ：将整个 filesystem 还原的一种模式，用在还原针对档案系统的 dump 备份；
其他较常用到的选项功能：
-h  ：察看完整备份资料中的 inode 与档案系统 label 等资讯
-f  ：后面就接你要处理的那个 dump 档案啰！
-D  ：与 -C 进行搭配，可以查出后面接的挂载点与 dump 内有不同的档案！
  • 用 restore 观察 dump 后的备份资料内容

要找出 dump 的内容就使用 restore -t 来查阅即可！例如我们将 boot.dump 的档案内容捉出来看看！

[root@www ~]# restore -t -f /root/boot.dump
Dump   date: Tue Dec  2 02:53:45 2008              <==说明备份的日期

Dumped from: the epoch
Level 0 dump of /boot on www.vbird.tsai:/dev/hdc1  <==说明 level 状态
Label: /boot                                       <==说明该 filesystem 的表头！
         2      .
        11      ./lost+found
      2009      ./grub
      2011      ./grub/grub.conf
....底下省略....

[root@www ~]# restore -t -f /root/etc.dump
Dump tape is compressed.                          <==加注说明资料有压缩

Dump   date: Tue Dec  2 12:08:22 2008
Dumped from: the epoch
Level 0 dump of / (dir etc) on www.vbird.tsai:/dev/hdc2 <==是目录！
Label: /1
         2      .
   1912545      ./etc
   1912549      ./etc/rpm
   1912550      ./etc/rpm/platform
....底下省略....

这个查阅的资料其实显示出的是档名与原始档案的 inode 状态，所以我们可以说， dump 会参考 inode 的记录哩！ 透过这个查询我们也能知道 dump 的内容为何呢！再来查一查如何还原吧！

  • 比较差异并且还原整个档案系统

为什么 dump 可以进行累积备份呢？就是因为他具有可以查询档案系统与备份档案之间的差异， 并且将分析到的差异资料进行备份的缘故。所以我们先来看看，如何查询有变动过的资讯呢？你可以使用如下的方法检验：

# 0. 先尝试变更档案系统的内容：
[root@www ~]# cd /boot
[root@www boot]# mv config-2.6.18-128.el5 config-2.6.18-128.el5-back

# 1. 看使进行档案系统与备份档案之间的差异！

[root@www boot]# restore -C -f /root/boot.dump
Dump   date: Tue Dec  2 02:53:45 2008
Dumped from: the epoch
Level 0 dump of /boot on www.vbird.tsai:/dev/hdc1
Label: /boot
filesys = /boot
restore: unable to stat ./config-2.6.18-128.el5: No such file or directory
Some files were modified!  1 compare errors
# 看到上面的特殊字体了吧！那就是有差异的部分！总共有一个档案被变更！
# 我们刚刚确实有更动过该档案，嘿嘿！这样是否能了解？！

# 2. 将档案系统改回来啊！
[root@www boot]# mv config-2.6.18-128.el5-back config-2.6.18-128.el5
[root@www boot]# cd /root

如同上面的动作，透过曾经备份过的资讯，也可以找到与目前实际档案系统中有差异的资料呢！ 如果你不想要进行累积备份，但也能透过这个动作找出最近这一阵子有变动过的档案说！了解乎？ 那如何还原呢？由于 dump 是记录整个档案系统的，因此还原时你也应该要给予一个全新的档案系统才行。 因此底下我们先建立一个档案系统，然后再来还原吧！

# 1. 先建立一个新的 partition 来使用，假设我们需要的是 150M 的容量
[root@www ~]# fdisk /dev/hdc
Command (m for help): n
First cylinder (2335-5005, default 2335): <==这里按 Enter

Using default value 2335
Last cylinder or +size or +sizeM or +sizeK (2335-5005, default 5005): +150M
Command (m for help): p
....中间省略....
/dev/hdc8            2335        2353      152586   83  Linux

Command (m for help): w

[root@www ~]# partprobe   <==很重要的动作！别忘记！

# 这样就能够建立一个 /dev/hdc8 的 partition ，然后继续格式化吧！

[root@www ~]# mkfs -t ext3 /dev/hdc8
[root@www ~]# mount /dev/hdc8 /mnt

# 2. 开始进行还原的动作！请您务必到新档案系统的挂载点底下去！
[root@www ~]# cd /mnt
[root@www mnt]# restore -r -f /root/boot.dump

restore: ./lost+found: File exists

由于我们是备份整个档案系统，因此你也可以建置一个全新的档案系统 (partition) 来进行还原的动作！ 整个还原的动作也不难，如上表最后一个指令，就是将备份档案中的资料还原到本目录下。 你必须要变更目录到挂载点所在的那个目录才行啊！这样还原的档案才不会跑错地方！如果你还想要将 level 1 的 /root/boot.dump.1 那个档案的内容也还原的话，那就继续使用‘restore -r -f /root/boot.dump.1’去还原吧！

  • 仅还原部分档案的 restore 互动模式

某些时候你只是要将备份档的某个内容捉出来而已，并不想要全部解开，那该如何是好？此时你可以进入 restore 的互动模式 (interactive mode)。在底下我们使用 etc.dump 来进行范例说明。假如你要将 etc.dump 内的 passwd 与 shadow 捉出来而已，该如何进行呢？

[root@www ~]# cd /mnt
[root@www mnt]# restore -i -f /root/etc.dump
restore >
# 此时你就已经进入 restore 的互动模式画面中！要注意的是：
# 你目前已经在 etc.dump 这个档案内了！所有的动作都是在 etc.dump 内！

restore > help

Available commands are:
        ls [arg] - list directory          <==列出 etc.dump 内的档案或目录
        cd arg - change directory          <==在 etc.dump 内变更目录
        pwd - print current directory      <==列出在 etc.dump 内的路径档名
        add [arg] - add `arg' to list of files to be extracted
        delete [arg] - delete `arg' from list of files to be extracted
        extract - extract requested files
# 上面三个指令是重点！各指令的功能为：
# add file    ：将 file 加入等一下要解压缩的档案列表中
# delete file ：将 file 移除出解压缩的列表，并非删除 etc.dump 内的档案！别误会！^_^
# extract     ：开始将刚刚选择的档案列表解压缩了去！
        setmodes - set modes of requested directories
        quit - immediately exit program
        what - list dump header information
        verbose - toggle verbose flag (useful with ``ls'')
        prompt - toggle the prompt display
        help or `?' - print this list

restore > ls

.:
etc/  <==会显示出在 etc.dump 内主要的目录，因为我们备份 /etc ，所以档名为此！

restore > cd etc                  <==在 etc.dump 内变换路径到 etc 目录下
restore > pwd                     <==列出本目录的档名为？
/etc
restore > ls passwd shadow group  <==看看，真的有这三个档案喔！

passwd
shadow
group
restore > add passwd shadow group <==加入解压缩列表
restore > delete group            <==加错了！将 group 移除解压缩列表
restore > ls passwd shadow group
*passwd  <==有要被解压缩的，档名之前会出现 * 的符号呢！

*shadow
group
restore > extract                 <==开始进行解压缩去！
You have not read any volumes yet.   <==这里会询问你需要的volume
Unless you know which volume your file(s) are on you should start
with the last volume and work towards the first.
Specify next volume # (none if no more volumes): 1 <==只有一个 volume
set owner/mode for '.'? [yn] n <==不需要修改权限

restore > quit                    <==离开 restore 的功能

[root@www ~]# ll -d etc
drwxr-xr-x 2 root root 1024 Dec 15 17:49 etc  <==解压缩后，所建立出来的目录啦！
[root@www ~]# ll etc

total 6
-rw-r--r-- 1 root root 1945 Sep 29 02:21 passwd
-r-------- 1 root root 1257 Sep 29 02:21 shadow

透过互动式的 restore 功能，可以让你将备份的资料取出一部份，而不必全部都得解压缩才能够取得你想要的档案资料。 而 restore 内的 add 除了可以增加档案外，也能够增加整个备份的‘目录’喔！还不错玩吧！ 赶紧测试看看先！ ^_^

大标题的图示 光碟写入工具

某些时刻你可能会希望将系统上最重要的资料给他备份出来，虽然目前随身碟已经有够便宜，你可以使用这玩意儿来备份。 不过某些重要的、需要重复备份的资料(可能具有时间特性)，你可能会需要使用类似 DVD 之类的储存媒体来备份出来！ 举例来说，你的系统设定档或者是讨论区的资料库档案(变动性非常的频繁)。虽然 Linux 图形介面已经有不少的烧录软体可用， 但有时如果你希望系统自动在某些时刻帮你主动的进行烧录时，那么文字介面的烧录行为就有帮助啦！

那么文字模式的烧录行为要怎么处理呢？通常的作法是这样的：

  • 先将所需要备份的资料建置成为一个映像档(iso)，利用 mkisofs 指令来处理；
  • 将该映像档烧录至光碟或 DVD 当中，利用 cdrecord 指令来处理。

底下我们就分别来谈谈这两个指令的用法吧！

小标题的图示 mkisofs：建立映像档

我们从 FTP 站捉下来的 Linux 映像档 (不管是 CD 还是 DVD) 都得要继续烧录成为实体的光碟/DVD 后， 才能够进一步的使用，包括安装或更新你的 Linux 啦！同样的道理，你想要利用烧录机将你的资料烧录到 DVD 时， 也得要先将你的资料包成一个映像档，这样才能够写入DVD片中。而将你的资料包成一个映像档的方式就透过 mkisofs 这个指令即可。 mkisofs 的使用方式如下：

[root@www ~]# mkisofs [-o 映像档] [-rv] [-m file] 待备份档案.. [-V vol] \
>  -graft-point isodir=systemdir ...

选项与参数：
-o ：后面接你想要产生的那个映像档档名。
-r ：透过 Rock Ridge 产生支援 Unix/Linux 的档案资料，可记录较多的资讯；
-v ：显示建置 ISO 档案的过程
-m file ：-m 为排除档案 (exclude) 的意思，后面的档案不备份到映像档中
-V vol  ：建立 Volume，有点像 Windows 在档案总管内看到的 CD title 的东西
-graft-point：graft有转嫁或移植的意思，相关资料在底下文章内说明。

其实 mkisofs 有非常多好用的选项可以选择，不过如果我们只是想要制作资料光碟时，上述的选项也就够用了。 光碟的格式一般称为 iso9660 ，这种格式一般仅支援旧版的 DOS 档名，亦即档名只能以 8.3 (档名8个字元，副档名3个字元) 的方式存在。如果加上 -r 的选项之后，那么档案资讯能够被记录的比较完整，可包括UID/GID与权限等等！ 所以，记得加这个 -r 的选项。

此外，一般预设的情况下，所有要被加到映像档中的档案都会被放置到映象档中的根目录， 如此一来可能会造成烧录后的档案分类不易的情况。所以，你可以使用 -graft-point 这个选项，当你使用这个选项之后， 可以利用如下的方法来定义位于映像档中的目录，例如：

  • 映像档中的目录所在=实际 Linux 档案系统的目录所在
  • /movies/=/srv/movies/ (在 Linux 的 /srv/movies 内的档案，加至映像档中的 /movies/ 目录)
  • /linux/etc=/etc (将 Linux 中的 /etc/ 内的所有资料备份到映像档中的 /linux/etc/ 目录中)

我们透过一个简单的范例来说明一下吧。如果你想要将 /root, /home, /etc 等目录内的资料通通烧录起来的话， 先得要处理一下映像档，我们先不使用 -graft-point 的选项来处理这个映像档试看看：

[root@www ~]# mkisofs -r -v -o /tmp/system.img /root /home /etc
INFO:   ISO-8859-1 character encoding detected by locale settings.
        Assuming ISO-8859-1 encoded filenames on source filesystem,
        use -input-charset to override.
mkisofs 2.01 (cpu-pc-linux-gnu)
Scanning /root
Scanning /root/test4
....中间省略....
 97.01% done, estimate finish Tue Dec 16 17:07:14 2008  <==显示百分比
 98.69% done, estimate finish Tue Dec 16 17:07:15 2008
Total translation table size: 0

Total rockridge attributes bytes: 9840   <==额外记录属性所耗用之容量
Total directory bytes: 55296             <==目录占用容量
Path table size(bytes): 406
Done with: The File(s)              Block(s)    298728
Writing:   Ending Padblock          Start Block 298782
Done with: Ending Padblock          Block(s)    150
Max brk space used 0
298932 extents written (583 MB)

[root@www ~]# ll -h /tmp/system.img
-rw-r--r-- 1 root root 584M Dec 16 17:07 /tmp/system.img
[root@www ~]# mount -o loop /tmp/system.img /mnt

[root@www ~]# df -h
Filesystem            Size  Used Avail Use% Mounted on
/tmp/system.img       584M  584M     0 100% /mnt  <==就是这玩意儿！
[root@www ~]# ls /mnt
alex             crontab2               etc.tar.gz          system.tar.bz2
anaconda-ks.cfg  etc                    install.log         test1
arod             etc.and.root.tar.bz2   install.log.syslog  test2
boot.dump        etc.dump               loopdev             test3
# 看吧！一堆资料都放置在一起！包括有的没有的目录与档案等等！

[root@www ~]# umount /mnt

由上面的范例我们可以看到，三个目录 (/root, /home, /etc) 的资料通通放置到了映像档的最顶层目录中！ 真是不方便～尤其由于 /root/etc 的存在，导致那个 /etc 的资料似乎没有被包含进来的样子！真不合理～ 而且还有 lost+found 的目录存在！真是超不喜欢的！此时我们可以使用 -graft-point 来处理啰！

[root@www ~]# mkisofs -r -V 'linux_file' -o /tmp/system.img \
>  -m /home/lost+found -graft-point /root=/root /home=/home /etc=/etc
[root@www ~]# ll -h /tmp/system.img
-rw-r--r-- 1 root root 689M Dec 17 11:41 /tmp/system.img

# 上面的指令会建立一个大档案，期中 -graft-point 后面接的就是我们要备份的资料。
# 必须要注意的是那个等号的两边，等号左边是在映像档内的目录，右侧则是实际的资料。

[root@www ~]# mount -o loop /tmp/system.img /mnt
[root@www ~]# ll /mnt
dr-xr-xr-x 105 root root 32768 Dec 17 11:40 etc
dr-xr-xr-x   5 root root  2048 Dec 17 11:40 home
dr-xr-xr-x   7 root root  4096 Dec 17 11:40 root
# 瞧！资料是分门别类的在各个目录中喔这样了解乎？最后将资料卸载一下：

[root@www ~]# umount /mnt

其实鸟哥一直觉得很奇怪，怎么我的资料会这么大(600多MB)？原来是 /home 里面在第八章的时候，练习时多了一个 /home/loopdev 的大档案！所以在重新制作一次 iso 档，并多加一个‘ -m /home/loopdev ’来排除该档案的备份， 最终的档案则仅有 176MB 啰！还好还好！ ^_^！接下来让我们处理烧录的动作了吧！

小标题的图示 cdrecord：光碟烧录工具

我们是透过 cdrecord 这个指令来进行文字介面的烧录行为，这个指令常见的选项有底下数个：

[root@www ~]# cdrecord -scanbus dev=ATA                  <==查询烧录机位置
[root@www ~]# cdrecord -v dev=ATA:x,y,z blank=[fast|all] <==抹除重复读写片
[root@www ~]# cdrecord -v dev=ATA:x,y,z -format          <==格式化DVD+RW
[root@www ~]# cdrecord -v dev=ATA:x,y,z [可用选项功能] file.iso

选项与参数：
-scanbus        ：用在扫瞄磁碟汇流排并找出可用的烧录机，后续的装置为 ATA 介面
-v              ：在 cdrecord 运作的过程中，显示过程而已。
dev=ATA:x,y,z   ：后续的 x, y, z 为你系统上烧录机所在的位置，非常重要！
blank=[fast|all]：blank 为抹除可重复写入的CD/DVD-RW，使用fast较快，all较完整
-format         ：仅针对 DVD+RW 这种格式的 DVD 而已；
[可用选项功能] 主要是写入 CD/DVD 时可使用的选项，常见的选项包括有：
   -data   ：指定后面的档案以资料格式写入，不是以 CD 音轨(-audio)方式写入！
   speed=X ：指定烧录速度，例如CD可用 speed=40 为40倍数，DVD则可用 speed=4 之类
   -eject  ：指定烧录完毕后自动退出光碟
   fs=Ym   ：指定多少缓冲记忆体，可用在将映像档先暂存至缓冲记忆体。预设为 4m，
             一般建议可增加到 8m ，不过，还是得视你的烧录机而定。
针对 DVD 的选项功能：
   driveropts=burnfree ：打开 Buffer Underrun Free 模式的写入功能
   -sao                ：支援 DVD-RW 的格式
  • 侦测你的烧录机所在位置：

文字模式的烧录确实是比较麻烦的，因为没有所见即所得的环境嘛！要烧录首先就得要找到烧录机才行！ 而由于早期的烧录机都是使用 SCSI 介面，因此查询烧录机的方法就得要配合着 SCSI 介面的认定来处理了。 查询烧录机的方式为：

[root@www ~]# cdrecord -scanbus dev=ATA
Cdrecord-Clone 2.01 (cpu-pc-linux-gnu) Copyright (C) 1995-2004 J?rg Schilling

....中间省略....
scsibus1:
        1,0,0   100) *
        1,1,0   101) 'ASUS    ' 'DRW-2014S1      ' '1.01' Removable CD-ROM
        1,2,0   102) *
        1,3,0   103) *
        1,4,0   104) *
        1,5,0   105) *
        1,6,0   106) *
        1,7,0   107) *

利用 cdrecord -scanbus 就能够找到正确的烧录机！由于目前个人电脑上最常使用的磁碟机介面为 IDE 与 SATA ， 这两种介面都能够使用 dev=ATA 这种模式来查询，因此上述的指令得要背一下啦！另外，在查询的结果当中可以发现有一台烧录机， 其中也显示出这台烧录机的型号，而最重要的就是上表中有底线的那三个数字！那三个数字就是代表这台烧录机的位置！ 以上表的例子中，这部烧录机的位置在‘ ATA:1,1,0 ’这个地方喔！

好了，那么现在要如何将 /tmp/system.img 烧录到 CD/DVD 里面去呢？鸟哥这里先以 CD 为例，鸟哥用的是 CD-RW (可重复读写) 的光碟片，说实在话，虽然 CD-RW 或 DVD-RW 比较贵一点，不过至少可以重复利用， 对环境的冲击比较小啦！建议大家使用可重复读写的片子。由于 CD-RW 可能要先进行抹除的工作(将原本里面的资料删除)然后才能写入， 因此，底下我们先来看看如何抹除一片 CD/DVD 的方法，然后直接写入光碟吧！

Tips:
由于 CD/DVD 都是使用 cdrecord 这个指令，因此不论是 CD 还是 DVD 片，下达指令的方法都差不多！不过， DVD 的写入需要额外的 driveropts=burnfree 或 -dao 等选项的辅助才行。 另外，CD 片有 CD-R(一次写入) 与 CD-RW(重复写入)，至于 DVD 则主要有两种格式，分别是 DVD-R 及 DVD+R 两种格式。 如果是可重复读写的则为： DVD-RW, DVD+RW 。除了 DVD+RW 的抹除方法可能不太一样之外，其他写入的方式则是一样的。 		鸟哥的图示
  • 进行 CD 的烧录动作：
# 0. 先抹除光碟的原始内容：(非可重复读写则可略过此步骤)
[root@www ~]# cdrecord -v dev=ATA:1,1,0 blank=fast

# 中间会跑出一堆讯息告诉你抹除的进度，而且会有 10 秒钟的时间等待你的取消！
# 可以避免‘手滑’的情况！^_^

# 1. 开始烧录：
[root@www ~]# cdrecord -v dev=ATA:1,1,0 fs=8m -dummy -data \
>  /tmp/system.img
....中间省略....
Track 01:  168 of  176 MB written (fifo 100%) [buf 100%]  10.5x. <==显示百分比

# 上面会显示进度，还有 10.5x 代表目前的烧录速度！
cdrecord: fifo had 2919 puts and 2919 gets.
cdrecord: fifo was 0 times empty and 2776 times full, min fill was 97%.

# 2. 烧录完毕后，测试挂载一下，检验内容：
[root@www ~]# mount -t iso9660 /dev/cdrom /mnt
[root@www ~]# df -h /mnt
Filesystem            Size  Used Avail Use% Mounted on
/dev/hdd              177M  177M     0 100% /mnt      <==瞧！确实是光碟内容！

[root@www ~]# ll /mnt

dr-xr-xr-x 105 root root 32768 Dec 17 11:54 etc
dr-xr-xr-x   5 root root  2048 Dec 17 11:54 home
dr-xr-xr-x   7 root root  4096 Dec 17 11:54 root

[root@www ~]# umount /mnt    <==不要忘了卸载

事实上如果你忘记抹除可写入光碟时，其实 cdrecord 很聪明的会主动的帮你抹除啦！ 因此上面的资讯你只要记得烧录的功能即可。特别注意 -data 那个选项！因为如果没有加上 -data 的选项时， 预设资料会以音轨格式写入光碟中，所以最好能够加上 -data 这个选项啰！ 上述的功能是针对 CD ，底下我们使用一片可重复读写的 DVD-RW 来测试一下写入的功能！

  • 进行 DVD-RW 的烧录动作：
# 0. 同样的，先来抹除一下原本的内容：

[root@www ~]# cdrecord -v dev=ATA:1,1,0 blank=fast

# 1. 开始写入 DVD ，请注意，有些选项与 CD 并不相同了喔！
[root@www ~]# cdrecord -v dev=ATA:1,1,0 fs=8m -data -sao \
>  driveropts=burnfree /tmp/system.img

# 2. 同样的，来给他测试测试！
[root@www ~]# mount /dev/cdrom /mnt
[root@www ~]# df -h /mnt
Filesystem            Size  Used Avail Use% Mounted on
/dev/hdd              177M  177M     0 100% /mnt
[root@www ~]# umount /mnt

整体指令没有差很多啦！只是 CD-RW 会自动抹除，但 DVD-RW 似乎得要自己手动某除才行！并不会主动进入自动抹除的功能！ 害鸟哥重新测试过好几次～伤脑筋～ ^_^！好啦！现在你就知道如何将你的资料烧录出来啦！

如果你的 Linux 是用来做为伺服器之用的话，那么无时无刻的去想‘如何备份重要资料’是相当重要的！ 关于备份我们会在第五篇再仔细的谈一谈，这里你要会使用这些工具即可！

大标题的图示 其他常见的压缩与备份工具

还有一些很好用的工具得要跟大家介绍介绍，尤其是 dd 这个玩意儿呢！

小标题的图示 dd

我们在第八章当中的特殊 loop 装置挂载时使用过 dd 这个指令对吧？ 不过，这个指令可不只是制作一个档案而已喔～这个 dd 指令最大的功效，鸟哥认为，应该是在于‘备份’啊！ 因为 dd 可以读取磁碟装置的内容(几乎是直接读取磁区"sector")，然后将整个装置备份成一个档案呢！真的是相当的好用啊～ dd 的用途有很多啦～但是我们仅讲一些比较重要的选项，如下：

[root@www ~]# dd if="input_file" of="output_file" bs="block_size" \
> count="number"

选项与参数：
if   ：就是 input file 啰～也可以是装置喔！
of   ：就是 output file 喔～也可以是装置；
bs   ：规划的一个 block 的大小，若未指定则预设是 512 bytes(一个 sector 的大小)
count：多少个 bs 的意思。

范例一：将 /etc/passwd 备份到 /tmp/passwd.back 当中
[root@www ~]# dd if=/etc/passwd of=/tmp/passwd.back
3+1 records in
3+1 records out
1945 bytes (1.9 kB) copied, 0.000332893 seconds, 5.8 MB/s
[root@www ~]# ll /etc/passwd /tmp/passwd.back
-rw-r--r-- 1 root root 1945 Sep 29 02:21 /etc/passwd
-rw-r--r-- 1 root root 1945 Dec 17 18:09 /tmp/passwd.back
# 仔细的看一下，我的 /etc/passwd 档案大小为 1945 bytes，因为我没有设定 bs ，
# 所以预设是 512 bytes 为一个单位，因此，上面那个 3+1 表示有 3 个完整的
# 512 bytes，以及未满 512 bytes 的另一个 block 的意思啦！
# 事实上，感觉好像是 cp 这个指令啦～

范例二：将自己的磁碟之第一个磁区备份下来

[root@www ~]# dd if=/dev/hdc of=/tmp/mbr.back bs=512 count=1
1+0 records in
1+0 records out
512 bytes (512 B) copied, 0.0104586 seconds, 49.0 kB/s
# 第一个磁区内含有 MBR 与 partition table ，透过这个动作，
# 我们可以一口气将这个磁碟的 MBR 与 partition table 进行备份哩！

范例三：找出你系统最小的那个分割槽，并且将他备份下来：
[root@www ~]# df -h
Filesystem            Size  Used Avail Use% Mounted on
/dev/hdc2             9.5G  3.9G  5.1G  44% /
/dev/hdc3             4.8G  651M  3.9G  15% /home
/dev/hdc1              99M   21M   73M  23% /boot  <==就捉他好了！
[root@www ~]# dd if=/dev/hdc1 of=/tmp/boot.whole.disk

208782+0 records in
208782+0 records out
106896384 bytes (107 MB) copied, 6.24721 seconds, 17.1 MB/s
[root@www ~]# ll -h /tmp/boot.whole.disk
-rw-r--r-- 1 root root 102M Dec 17 18:14 /tmp/boot.whole.disk
# 等于是将整个 /dev/hdc1 通通捉下来的意思～如果要还原呢？就反向回去！
# dd if=/tmp/boot.whole.disk of=/dev/hdc1 即可！非常简单吧！
# 简单的说，如果想要整个硬碟备份的话，就类似 Norton 的 ghost 软体一般，
# 由 disk 到 disk ，嘿嘿～利用 dd 就可以啦～厉害厉害！

你可以说， tar 可以用来备份关键资料，而 dd 则可以用来备份整颗 partition 或 整颗 disk ，很不错啊～不过，如果要将资料填回到 filesystem 当中， 可能需要考虑到原本的 filesystem 才能成功啊！让我们来完成底下的例题试看看：

例题：
你想要将你的 /dev/hdc1 进行完整的复制到另一个 partition 上，请使用你的系统上面未分割完毕的容量再建立一个与 /dev/hdc1 差不多大小的分割槽 (只能比 /dev/hdc1 大，不能比他小！)，然后将之进行完整的复制 (包括需要复制 boot sector 的区块)。
答：
由于需要复制 boot sector 的区块，所以使用 cp 或者是 tar 这种指令是无法达成需求的！ 此时那个 dd 就派的上用场了。你可以这样做：
# 1. 先进行分割的动作
[root@www ~]# fdisk -l /dev/hdc
   Device Boot   Start    End    Blocks   Id  System
/dev/hdc1   *        1     13    104391   83  Linux
# 上面鸟哥仅撷取重要的资料而已！我们可以看到 /dev/hdc1 仅有 13 个磁柱

[root@www ~]# fdisk /dev/hdc
Command (m for help): n
First cylinder (2354-5005, default 2354): 这里按 enter
Using default value 2354
Last cylinder or +size or +sizeM or +sizeK (2354-5005, default 5005): 2366

Command (m for help): p
   Device Boot   Start    End    Blocks   Id  System
/dev/hdc9         2354   2366    104391   83  Linux

Command (m for help): w
# 为什么要使用 2366 呢？因为 /dev/hdc1 使用 13 个磁柱，因此新的 partition
# 我们也给她 13 个磁柱，因此 2354 + 13 -1 = 2366 啰！

[root@www ~]# partprobe

# 2. 不需要格式化，直接进行 sector 表面的复制！
[root@www ~]# dd if=/dev/hdc1 of=/dev/hdc9
208782+0 records in
208782+0 records out
106896384 bytes (107 MB) copied, 16.8797 seconds, 6.3 MB/s

[root@www ~]# mount /dev/hdc9 /mnt
[root@www ~]# df
Filesystem           1K-blocks      Used Available Use% Mounted on
/dev/hdc1               101086     21408     74459  23% /boot
/dev/hdc9               101086     21408     74459  23% /mnt
# 这两个玩意儿会‘一模一样’喔！
[root@www ~]# umount /mnt
非常有趣的范例吧！新分割出来的 partition 不需要经过格式化，因为 dd 可以将原本旧的 partition 上面，将 sector 表面的资料整个复制过来！ 当然连同 superblock, boot sector, meta data 等等通通也会复制过来！是否很有趣呢？未来你想要建置两颗一模一样的磁碟时， 只要下达类似： dd if=/dev/sda of=/dev/sdb ，就能够让两颗磁碟一模一样，甚至 /dev/sdb 不需要分割与格式化， 因为该指令可以将 /dev/sda 内的所有资料，包括 MBR 与 partition table 也复制到 /dev/sdb 说！ ^_^

小标题的图示 cpio

这个指令挺有趣的，因为 cpio 可以备份任何东西，包括装置设备档案。不过 cpio 有个大问题， 那就是 cpio 不会主动的去找档案来备份！啊！那怎办？所以啰，一般来说， cpio 得要配合类似 find 等可以找到档名的指令来告知 cpio 该被备份的资料在哪里啊！ 有点小麻烦啦～因为牵涉到我们在第三篇才会谈到的资料流重导向说～ 所以这里你就先背一下语法，等到第三篇讲完你就知道如何使用 cpio 啰！

[root@www ~]# cpio -ovcB  > [file|device] <==备份

[root@www ~]# cpio -ivcdu < [file|device] <==还原
[root@www ~]# cpio -ivct  < [file|device] <==察看
备份会使用到的选项与参数：
  -o ：将资料 copy 输出到档案或装置上
  -B ：让预设的 Blocks 可以增加至 5120 bytes ，预设是 512 bytes ！
       这样的好处是可以让大档案的储存速度加快(请参考 i-nodes 的观念)
还原会使用到的选项与参数：
  -i ：将资料自档案或装置 copy 出来系统当中
  -d ：自动建立目录！使用 cpio 所备份的资料内容不见得会在同一层目录中，因此我们
       必须要让 cpio 在还原时可以建立新目录，此时就得要 -d 选项的帮助！
  -u ：自动的将较新的档案覆盖较旧的档案！
  -t ：需配合 -i 选项，可用在"察看"以 cpio 建立的档案或装置的内容
一些可共用的选项与参数：
  -v ：让储存的过程中档案名称可以在荧幕上显示
  -c ：一种较新的 portable format 方式储存

你应该会发现一件事情，就是上述的选项与指令中怎么会没有指定需要备份的资料呢？还有那个大于 (>) 与小于 (<) 符号是怎么回事啊？因为 cpio 会将资料整个显示到荧幕上，因此我们可以透过将这些荧幕的资料重新导向 (>) 一个新的档案！ 至于还原呢？就是将备份档案读进来 cpio (<) 进行处理之意！我们来进行几个案例你就知道啥是啥了！

范例：找出 /boot 底下的所有档案，然后将他备份到 /tmp/boot.cpio 去！
[root@www ~]# find /boot -print
/boot
/boot/message
/boot/initrd-2.6.18-128.el5.img
....以下省略....
# 透过这个 find 我们可以找到 /boot 底下应该要存在的档名！包括档案与目录

[root@www ~]# find /boot | cpio -ocvB > /tmp/boot.cpio
[root@www ~]# ll -h /tmp/boot.cpio
-rw-r--r-- 1 root root 16M Dec 17 23:30 /tmp/boot.cpio

我们使用 find /boot 可以找出档名，然后透过那条管线 (|, 亦即键盘上的 shift+\ 的组合)， 就能将档名传给 cpio 来进行处理！最终会得到 /tmp/boot.cpio 那个档案喔！接下来让我们来进行解压缩看看。

范例：将刚刚的档案给他在 /root/ 目录下解开
[root@www ~]# cpio -idvc < /tmp/boot.cpio
[root@www ~]# ll /root/boot
# 你可以自行比较一下 /root/boot 与 /boot 的内容是否一模一样！

事实上 cpio 可以将系统的资料完整的备份到磁带机上头去喔！如果你有磁带机的话！

  • 备份：find / | cpio -ocvB > /dev/st0
  • 还原：cpio -idvc < /dev/st0

这个 cpio 好像不怎么好用呦！但是，他可是备份的时候的一项利器呢！因为他可以备份任何的档案， 包括 /dev 底下的任何装置档案！所以他可是相当重要的呢！而由于 cpio 必需要配合其他的程式，例如 find 来建立档名，所以 cpio 与管线命令及资料流重导向的相关性就相当的重要了！

其实系统里面已经含有一个使用 cpio 建立的档案喔！那就是 /boot/initrd-xxx 这个档案啦！ 现在让我们来将这个档案解压缩看看，看你能不能发现该档案的内容为何？

# 1. 我们先来看看该档案是属于什么档案格式，然后再加以处理：
[root@www ~]# file /boot/initrd-2.6.18-128.el5.img
/boot/initrd-2.6.18-128.el5.img: gzip compressed data, ...
# 唔！看起来似乎是使用 gzip 进行压缩过～那如何处理呢？

# 2. 透过更名，将该档案增加副档名，然后予以解压缩看看：
[root@www ~]# mkdir initrd
[root@www ~]# cd initrd
[root@www initrd]# cp /boot/initrd-2.6.18-128.el5.img initrd.img.gz
[root@www initrd]# gzip -d initrd.img.gz
[root@www initrd]# ll

-rw------- 1 root root 5408768 Dec 17 23:53 initrd.img
[root@www initrd]# file initrd.img
initrd.img: ASCII cpio archive (SVR4 with no CRC)
# 嘿嘿！露出马脚了吧！确实是 cpio 的文件档喔！

# 3. 开始使用 cpio 解开此档案：
[root@www initrd]# cpio -iduvc < initrd.img
sbin

init
sysroot
....以下省略....
# 瞧！这样就将这个档案解开啰！这样了解乎？
大标题的图示 重点回顾
  • 压缩指令为透过一些运算方法去将原本的档案进行压缩，以减少档案所占用的磁碟容量。 压缩前与压缩后的档案所占用的磁碟容量比值， 就可以被称为是‘压缩比’
  • 压缩的好处是可以减少磁碟容量的浪费，在 WWW 网站也可以利用档案压缩的技术来进行资料的传送，好让网站频宽的可利用率上升喔
  • 压缩档案的副档名大多是：‘*.tar, *.tar.gz, *.tgz, *.gz, *.Z, *.bz2’
  • 常见的压缩指令有 gzip 与 bzip2 ，其中 bzip2 压缩比较之 gzip 还要更好，建议使用 bzip2 ！
  • tar 可以用来进行档案打包，并可支援 gzip 或 bzip2 的压缩。
  • 压　缩：tar -jcv -f filename.tar.bz2 要被压缩的档案或目录名称
  • 查　询：tar -jtv -f filename.tar.bz2
  • 解压缩：tar -jxv -f filename.tar.bz2 -C 欲解压缩的目录
  • dump 指令可备份档案系统或单一目录
  • dump 的备份若针对档案系统时，可进行 0-9 的 level 差异备份！其中 level 0 为完整备份；
  • restore 指令可还原被 dump 建置的备份档；
  • 要建立光碟烧录资料时，可透过 mkisofs 指令来建置；
  • 可透过 cdrecord 来写入 CD 或 DVD 烧录机
  • dd 可备份完整的 partition 或 disk ，因为 dd 可读取磁碟的 sector 表面资料
  • cpio 为相当优秀的备份指令，不过必须要搭配类似 find 指令来读入欲备份的档名资料，方可进行备份动作。
大标题的图示 本章习题
(要看答案请将滑鼠移动到‘答：’底下的空白处，按下左键圈选空白处即可察看)
  • 情境模拟题一：你想要让系统恢复到第八章情境模拟后的结果，亦即仅剩下 /dev/hdc6 以前的 partition， 本章练习产生的 partition 都需要恢复原状。因此 /dev/hdc8, /dev/hdc9 (在本章练习过程中产生的) 请将他删除！删除的方法同第八章的情境模拟题一所示。

  • 情境模拟题二：你想要逐时备份 /srv/myproject 这个目录内的资料，又担心每次备份的资讯太多， 因此想要使用 dump 的方式来逐一备份资料到 /backups 这个目录下。该如何处理？

    • 目标：了解到 dump 以及各个不同 level 的作用；
    • 前提：被备份的资料为单一 partition ，亦即本例中的 /srv/myproject
    • 需求：/srv/myproject 为单一 filesystem ，且在 /etc/fstab 内此挂载点的 dump 栏位为 1

    实际处理的方法其实还挺简单的！我们可以这样做看看：

    1. 先替该目录制作一些资料，亦即复制一些东西过去吧！
      cp -a /etc /boot /srv/myproject

    2. 开始进行 dump ，记得，一开始是使用 level 0 的完整备份喔！
      mkdir /backups
      dump -0u -j -f /backups/myproject.dump /srv/myproject
      上面多了个 -j 的选项，目的是为了要进行压缩，减少备份的资料量。

    3. 尝试将 /srv/myproject 这个档案系统加大，将 /var/log/ 的资料复制进去吧！
      cp -a /var/log/ /srv/myproject
      此时原本的 /srv/myproject 已经被改变了！继续进行备份看看！

    4. 将 /srv/myproject 以 level 1 来进行备份：
      dump -1u -j -f /backups/myproject.dump.1 /srv/myproject
      ls -l /backups
      你应该就会看到两个档案，其中第二个档案 (myproject.dump.1) 会小的多！这样就搞定啰备份资料！

  • 情境模拟三：假设过了一段时间后，你的 /srv/myproject 变的怪怪的，你想要将该 filesystem 以刚刚的备份资料还原， 此时该如何处理呢？你可以这样做的：

    1. 先将 /srv/myproject 卸载，并且将该 partition 重新格式化！
      umount /dev/hdc6
      mkfs -t ext3 /dev/hdc6

    2. 重新挂载原本的 partition ，此时该目录内容应该是空的！
      mount -a
      你可以自行使用 df 以及 ls -l /srv/myproject 查阅一下该目录的内容，是空的啦！

    3. 将完整备份的 level 0 的档案 /backups/myproject.dump 还原回来：
      cd /srv/myproject
      restore -r -f /backups/myproject.dump
      此时该目录的内容为第一次备份的状态！还需要进行后续的处理才行！

    4. 将后续的 level 1 的备份也还原回来：
      cd /srv/myproject
      restore -r -f /backups/myproject.dump.1
      此时才是恢复到最后一次备份的阶段！如果还有 level 2, level 3 时，就得要一个一个的依序还原才行！
大标题的图示 参考资料与延伸阅读
  • 台湾学术网路管理文件：Backup Tools in UNIX(Linux):
    http://nmc.nchu.edu.tw/tanet/backup_tools_in_unix.htm
  • 中文 How to 文件计划 (CLDP)：http://www.linux.org.tw/CLDP/HOWTO/hardware/CD-Writing-HOWTO/CD-Writing-HOWTO-3.html
  • 熊宝贝工作记录之： Linux 烧录实作：http://csc.ocean-pioneer.com/docum/linux_burn.html
  • PHP5 网管实验室： http://www.php5.idv.tw/html.php?mod=article&do=show&shid=26
  • CentOS 5.x 之 man dump
  • CentOS 5.x 之 man restore
2003/02/09：第一次完成
2003/05/05：修改 tar 的部分内容，尤其是 -P 这个参数的配合用法
2005/07/26：将旧有的文章移动到 这里
2005/07/27：大略修改了一些风格，另外，动作较大的是在范例的部分！
2005/08/29：加入了 dd 这个有趣的指令喔！
2006/05/02：将原本‘tar -zxvpf /tmp/etc.tar.gz /etc’修改为‘tar -zcvpf /tmp/etc.tar.gz /etc’ 感谢讨论区网友 chinu 提供的资讯。
2008/10/31：将原本针对 FC4 的旧版本移动到此处
2008/12/18：这次的改版在这一章添加了不少东西！尤其是将 cpio 与 dd 的范例重新做个整理！并加入 dump/restore, mkisofs/cdrecord
2009/08/20：加入情境模拟的题目。


鸟哥的 Linux 私房菜 -- 基础学习篇

为取得较佳浏览结果，请爱用 firefox 浏览本网页

第十章、vim 程式编辑器
最近更新日期：2009/08/20
系统管理员的重要工作就是得要修改与设定某些重要软体的设定档，因此至少得要学会一种以上的文字介面的文书编辑器。 在所有的 Linux distributions 上头都会有的一套文书编辑器就是 vi ，而且很多软体预设也是使用 vi 做为他们编辑的介面， 因此鸟哥建议您务必要学会使用 vi 这个正规的文书编辑器。此外，vim 是进阶版的 vi ， vim 不但可以用不同颜色显示文字内容，还能够进行诸如 shell script, C program 等程式编辑功能， 你可以将 vim 视为一种程式编辑器！鸟哥也是用 vim 编辑鸟站的网页文章呢！ ^_^

1. vi 与 vim
    1.1 为何要学 vim
 2. vi 的使用
    2.1 简易执行范例
    2.2 按键说明
    2.3 一个案例的练习
    2.4 vim 的暂存档、救援回复与开启时的警告讯息
 3. vim 的额外功能
    3.1 区块选择(Visual Block)
    3.2 多档案编辑
    3.3 多视窗功能
    3.4 vim 环境设定与记录： ~/.vimrc, ~/.viminfo
    3.5 vim 常用指令示意图
 4. 其他 vim 使用注意事项
    4.1 中文编码的问题
    4.2 DOS 与 Linux 的断行字元： dos2unix, unix2dos
    4.3 语系编码转换： iconv
 5. 重点回顾
6. 本章习题
7. 参考资料与延伸阅读
8. 针对本文的建议：http://phorum.vbird.org/viewtopic.php?t=23883
大标题的图示 vi 与 vim

由前面一路走来，我们一直建议使用文字模式来处理 Linux 的系统设定问题，因为不但可以让你比较容易了解到 Linux 的运作状况，也比较容易了解整个设定的基本精神，更能‘保证’你的修改可以顺利的被运作。 所以，在 Linux 的系统中使用文字编辑器来编辑你的 Linux 参数设定档，可是一件很重要的事情呦！也因此呢，系统管理员至少应该要熟悉一种文书处理器的！

Tips:
这里要再次的强调，不同的 Linux distribution 各有其不同的附加软体，例如 Red Hat Enterprise Linux 与 Fedora 的 ntsysv 与 setup 等，而 SuSE 则有 YAST 管理工具等等， 因此，如果你只会使用此种类型的软体来控制你的 Linux 系统时，当接管不同的 Linux distributions 时，呵呵！那可就苦恼了！ 		鸟哥的图示

在 Linux 的世界中，绝大部分的设定档都是以 ASCII 的纯文字形态存在，因此利用简单的文字编辑软体就能够修改设定了！ 与微软的 Windows 系统不同的是，如果你用惯了 Microsoft Word 或 Corel Wordperfect 的话，那么除了 X window 里面的图形介面编辑程式(如 xemacs )用起来尚可应付外，在 Linux 的文字模式下，会觉得文书编辑程式都没有视窗介面来的直观与方便。

Tips:
什么是纯文字档？其实档案记录的就是 0 与 1 ，而我们透过编码系统来将这些 0 与 1 转成我们认识的文字就是了。 在第零章里面的资料表示方式有较多说明，请自行查阅。 ASCII 就是其中一种广为使用的文字编码系统，在 ASCII 系统中的图示与代码可以参考 http://zh.wikipedia.org/wiki/ASCII呢！ 		鸟哥的图示

那么 Linux 在文字介面下的文书编辑器有哪些呢？其实有非常多喔！常常听到的就有： emacs, pico, nano, joe, 与 vim 等等(注1)。 既然有这么多文字介面的文书编辑器，那么我们为什么一定要学 vi 啊？还有那个 vim 是做啥用的？底下就来谈一谈先！

小标题的图示 为何要学 vim

文书编辑器那么多，我们之前在第五章也曾经介绍过那简单好用的 nano ，既然已经学会了 nano ，干嘛鸟哥还一直要你学这不是很友善的 vi 呢？其实是有原因的啦！因为：

  • 所有的 Unix Like 系统都会内建 vi 文书编辑器，其他的文书编辑器则不一定会存在；
  • 很多个别软体的编辑介面都会主动呼叫 vi (例如未来会谈到的 crontab, visudo, edquota 等指令)；
  • vim 具有程式编辑的能力，可以主动的以字体颜色辨别语法的正确性，方便程式设计；
  • 因为程式简单，编辑速度相当快速。

其实重点是上述的第二点，因为有太多 Linux 上面的指令都预设使用 vi 作为资料编辑的介面，所以你必须、一定要学会 vi ，否则很多指令你根本就无法操作呢！这样说，有刺激到你务必要学会 vi 的热情了吗？ ^_^

那么什么是 vim 呢？其实你可以将 vim 视作 vi 的进阶版本，vim 可以用颜色或底线等方式来显示一些特殊的资讯。 举例来说，当你使用 vim 去编辑一个 C 程式语言的档案，或者是我们后续会谈到的 shell script 程式时，vim 会依据档案的副档名或者是档案内的开头资讯， 判断该档案的内容而自动的呼叫该程式的语法判断式，再以颜色来显示程式码与一般资讯。也就是说， 这个 vim 是个‘程式编辑器’啦！甚至一些 Linux 基础设定档内的语法，都能够用 vim 来检查呢！ 例如我们在第八章谈到的 /etc/fstab 这个档案的内容。

简单的来说， vi 是老式的文书处理器，不过功能已经很齐全了，但是还是有可以进步的地方。 vim 则可以说是程式开发者的一项很好用的工具，就连 vim 的官方网站 (http://www.vim.org) 自己也说 vim 是一个‘程式开发工具’而不是文书处理软体～^_^。 因为 vim 里面加入了很多额外的功能，例如支援正规表示法的搜寻架构、多档案编辑、区块复制等等。 这对于我们在 Linux 上面进行一些设定档的修订工作时，是很棒的一项功能呢！

Tips:
什么时候会使用到 vim 呢？其实鸟哥的整个网站都是在 vim 的环境下一字一字的建立起来的喔！ 早期鸟哥使用网页制作软体在编写网页，但是老是发现网页编辑软体都不怎么友善，尤其是写到 PHP 方面的程式码时。 后来就干脆不使用所见即所得的编辑软体，直接使用 vim ，然后标签 (tag) 也都自行用键盘输入！ 这样整个档案也比较干净！所以说，鸟哥我是很喜欢 vim 的啦！ ^_^ 		鸟哥的图示

底下鸟哥会先就简单的 vi 做个介绍，然后再跟大家报告一下 vim 的额外功能与用法呢！

大标题的图示 vi 的使用

基本上 vi 共分为三种模式，分别是‘一般模式’、‘编辑模式’与‘指令列命令模式’。 这三种模式的作用分别是：

  • 一般模式：
    以 vi 打开一个档案就直接进入一般模式了(这是预设的模式)。在这个模式中， 你可以使用‘上下左右’按键来移动游标，你可以使用‘删除字元’或‘删除整行’来处理档案内容， 也可以使用‘复制、贴上’来处理你的文件资料。

  • 编辑模式：
    在一般模式中可以进行删除、复制、贴上等等的动作，但是却无法编辑文件内容的！ 要等到你按下‘i, I, o, O, a, A, r, R’等任何一个字母之后才会进入编辑模式。注意了！通常在 Linux 中，按下这些按键时，在画面的左下方会出现‘ INSERT 或 REPLACE ’的字样，此时才可以进行编辑。而如果要回到一般模式时， 则必须要按下‘Esc’这个按键即可退出编辑模式。

  • 指令列命令模式：
    在一般模式当中，输入‘ : / ? ’三个中的任何一个按钮，就可以将游标移动到最底下那一行。在这个模式当中， 可以提供你‘搜寻资料’的动作，而读取、存档、大量取代字元、离开 vi 、显示行号等等的动作则是在此模式中达成的！

简单的说，我们可以将这三个模式想成底下的图示来表示：

vi三种模式的相互关系
图 2.1、vi 三种模式的相互关系

注意到上面的图示，你会发现一般模式可与编辑模式及指令列模式切换， 但编辑模式与指令列模式之间不可互相切换喔！这非常重要啦！ 闲话不多说，我们底下以一个简单的例子来进行说明吧！

小标题的图示 简易执行范例

如果你想要使用 vi 来建立一个名为 test.txt 的档案时，你可以这样做：

  1. 使用 vi 进入一般模式；
    [root@www ~]# vi test.txt
    直接输入‘ vi 档名’就能够进入 vi 的一般模式了。请注意，记得 vi 后面一定要加档名，不管该档名存在与否！ 整个画面主要分为两部份，上半部与最底下一行两者可以视为独立的。如下图 2.1.1 所示，图中那个虚线是不存在的， 鸟哥用来说明而已啦！上半部显示的是档案的实际内容，最底下一行则是状态显示列(如下图的[New File]资讯)， 或者是命令下达列喔！

    用 vi 开启一个新档案
    图 2.1.1、用 vi 开启一个新档案

    如果你开启的档案是旧档(已经存在的档案)，则可能会出现如下的资讯：

    用 vi 开启一个旧档案
    图 2.1.2、用 vi 开启一个旧档案

    如上图 2.1.2 所示，箭头所指的那个‘"/etc/man.config" 141L, 4617C’代表的是‘档名为 /etc/man.conf， 档案内有 141 行 以及具有 4617 个字元’的意思！ 那一行的内容并不是在档案内，而是 vi 显示一些资讯的地方喔！此时是在一般模式的环境下啦。 接下来开始来输入吧！

  2. 按下 i 进入编辑模式，开始编辑文字

    在一般模式之中，只要按下 i, o, a 等字元就可以进入编辑模式了！在编辑模式当中，你可以发现在左下角状态列中会出现 –INSERT- 的字样，那就是可以输入任意字元的提示啰！这个时候，键盘上除了 [Esc] 这个按键之外，其他的按键都可以视作为一般的输入按钮了，所以你可以进行任何的编辑啰！

    开始用 vi 来进行编辑
    图 2.1.3、开始用 vi 来进行编辑
    Tips:
    在 vi 里面， [tab] 这个按钮所得到的结果与空白字元所得到的结果是不一样的，特别强调一下！     		鸟哥的图示
  3. 按下 [ESC] 按钮回到一般模式

    好了，假设我已经按照上面的样式给他编辑完毕了，那么应该要如何退出呢？是的！没错！就是给他按下 [Esc] 这个按钮即可！马上你就会发现画面左下角的 – INSERT – 不见了！

  4. 在一般模式中按下 :wq 储存后离开 vi

    OK，我们要存档了，存档并离开的指令很简单，输入‘:wq’即可存档离开！ (注意了，按下 : 该游标就会移动到最底下一行去！) 这时你在提示字元后面输入‘ ls -l ’即可看到我们刚刚建立的 test.txt 档案啦！整个图示有点像底下这样：

    储存并离开 vi 环境
    图 2.1.4、储存并离开 vi 环境

如此一来，你的档案 test.txt 就已经建立起来啰！需要注意的是，如果你的档案权限不对，例如为 -r--r--r-- 时，那么可能会无法写入，此时可以使用‘强制写入’的方式吗？可以！使用‘ :wq! ’ 多加一个惊叹号即可！不过，需要特别注意呦！那个是在‘你的权限可以改变’的情况下才能成立的！ 关于权限的概念，请自行回去翻一下第六章的内容吧！

小标题的图示 按键说明

除了上面简易范例的 i, [Esc], :wq 之外，其实 vim 还有非常多的按键可以使用喔！在介绍之前还是要再次强调， vim 的三种模式只有一般模式可以与编辑、指令列模式切换，编辑模式与指令列模式之间并不能切换的！ 这点在图2.1里面有介绍到，注意去看看喔！底下就来谈谈 vim 软体中会用到的按键功能吧！

  • 第一部份：一般模式可用的按钮说明，游标移动、复制贴上、搜寻取代等

移动游标的方法
h 或 向左方向键(←) | 游标向左移动一个字元
j 或 向下方向键(↓) | 游标向下移动一个字元
k 或 向上方向键(↑) | 游标向上移动一个字元
l 或 向右方向键(→) | 游标向右移动一个字元
如果你将右手放在键盘上的话，你会发现 hjkl 是排列在一起的，因此可以使用这四个按钮来移动游标。 如果想要进行多次移动的话，例如向下移动 30 行，可以使用 "30j" 或 "30↓" 的组合按键， 亦即加上想要进行的次数(数字)后，按下动作即可！
[Ctrl] + [f] | 荧幕‘向下’移动一页，相当于 [Page Down]按键 (常用)
[Ctrl] + [b] | 荧幕‘向上’移动一页，相当于 [Page Up] 按键 (常用)
[Ctrl] + [d] | 荧幕‘向下’移动半页
[Ctrl] + [u] | 荧幕‘向上’移动半页
+ | 游标移动到非空白字元的下一列
- | 游标移动到非空白字元的上一列
n<space> | 那个 n 表示‘数字’，例如 20 。按下数字后再按空白键，游标会向右移动这一行的 n 个字元。例如 20<space> 则游标会向后面移动 20 个字元距离。
0 或功能键[Home] | 这是数字‘ 0 ’：移动到这一行的最前面字元处 (常用)
$ 或功能键[End] | 移动到这一行的最后面字元处(常用)
H | 游标移动到这个荧幕的最上方那一行的第一个字元
M | 游标移动到这个荧幕的中央那一行的第一个字元
L | 游标移动到这个荧幕的最下方那一行的第一个字元
G | 移动到这个档案的最后一行(常用)
nG | n 为数字。移动到这个档案的第 n 行。例如 20G 则会移动到这个档案的第 20 行(可配合 :set nu)
gg | 移动到这个档案的第一行，相当于 1G 啊！ (常用)
n<Enter> | n 为数字。游标向下移动 n 行(常用)
搜寻与取代
/word | 向游标之下寻找一个名称为 word 的字串。例如要在档案内搜寻 vbird 这个字串，就输入 /vbird 即可！ (常用)
?word | 向游标之上寻找一个字串名称为 word 的字串。
n | 这个 n 是英文按键。代表‘重复前一个搜寻的动作’。举例来说， 如果刚刚我们执行 /vbird 去向下搜寻 vbird 这个字串，则按下 n 后，会向下继续搜寻下一个名称为 vbird 的字串。如果是执行 ?vbird 的话，那么按下 n 则会向上继续搜寻名称为 vbird 的字串！
N | 这个 N 是英文按键。与 n 刚好相反，为‘反向’进行前一个搜寻动作。 例如 /vbird 后，按下 N 则表示‘向上’搜寻 vbird 。
使用 /word 配合 n 及 N 是非常有帮助的！可以让你重复的找到一些你搜寻的关键字！
:n1,n2s/word1/word2/g | n1 与 n2 为数字。在第 n1 与 n2 行之间寻找 word1 这个字串，并将该字串取代为 word2 ！举例来说，在 100 到 200 行之间搜寻 vbird 并取代为 VBIRD 则： ‘:100,200s/vbird/VBIRD/g’。(常用)
:1,$s/word1/word2/g | 从第一行到最后一行寻找 word1 字串，并将该字串取代为 word2 ！(常用)
:1,$s/word1/word2/gc | 从第一行到最后一行寻找 word1 字串，并将该字串取代为 word2 ！且在取代前显示提示字元给使用者确认 (confirm) 是否需要取代！(常用)
删除、复制与贴上
x, X | 在一行字当中，x 为向后删除一个字元 (相当于 [del] 按键)， X 为向前删除一个字元(相当于 [backspace] 亦即是倒退键) (常用)
nx | n 为数字，连续向后删除 n 个字元。举例来说，我要连续删除 10 个字元， ‘10x’。
dd | 删除游标所在的那一整列(常用)
ndd | n 为数字。删除游标所在的向下 n 列，例如 20dd 则是删除 20 列 (常用)
d1G | 删除游标所在到第一行的所有资料
dG | 删除游标所在到最后一行的所有资料
d$ | 删除游标所在处，到该行的最后一个字元
d0 | 那个是数字的 0 ，删除游标所在处，到该行的最前面一个字元
yy | 复制游标所在的那一行(常用)
nyy | n 为数字。复制游标所在的向下 n 列，例如 20yy 则是复制 20 列(常用)
y1G | 复制游标所在列到第一列的所有资料
yG | 复制游标所在列到最后一列的所有资料
y0 | 复制游标所在的那个字元到该行行首的所有资料
y$ | 复制游标所在的那个字元到该行行尾的所有资料
p, P | p 为将已复制的资料在游标下一行贴上，P 则为贴在游标上一行！ 举例来说，我目前游标在第 20 行，且已经复制了 10 行资料。则按下 p 后， 那 10 行资料会贴在原本的 20 行之后，亦即由 21 行开始贴。但如果是按下 P 呢？ 那么原本的第 20 行会被推到变成 30 行。 (常用)
J | 将游标所在列与下一列的资料结合成同一列
c | 重复删除多个资料，例如向下删除 10 行，[ 10cj ]
u | 复原前一个动作。(常用)
[Ctrl]+r | 重做上一个动作。(常用)
这个 u 与 [Ctrl]+r 是很常用的指令！一个是复原，另一个则是重做一次～ 利用这两个功能按键，你的编辑，嘿嘿！很快乐的啦！
. | 不要怀疑！这就是小数点！意思是重复前一个动作的意思。 如果你想要重复删除、重复贴上等等动作，按下小数点‘.’就好了！ (常用)

  • 第二部份：一般模式切换到编辑模式的可用的按钮说明

进入插入或取代的编辑模式
i, I | 进入插入模式(Insert mode)： i 为‘从目前游标所在处插入’， I 为‘在目前所在行的第一个非空白字元处开始插入’。 (常用)
a, A | 进入插入模式(Insert mode)： a 为‘从目前游标所在的下一个字元处开始插入’， A 为‘从游标所在行的最后一个字元处开始插入’。(常用)
o, O | 进入插入模式(Insert mode)： 这是英文字母 o 的大小写。o 为‘在目前游标所在的下一行处插入新的一行’； O 为在目前游标所在处的上一行插入新的一行！(常用)
r, R | 进入取代模式(Replace mode)： r 只会取代游标所在的那一个字元一次；R会一直取代游标所在的文字，直到按下 ESC 为止；(常用)
上面这些按键中，在 vi 画面的左下角处会出现‘--INSERT--’或‘--REPLACE--’的字样。 由名称就知道该动作了吧！！特别注意的是，我们上面也提过了，你想要在档案里面输入字元时， 一定要在左下角处看到 INSERT 或 REPLACE 才能输入喔！
[Esc] | 退出编辑模式，回到一般模式中(常用)

  • 第三部份：一般模式切换到指令列模式的可用的按钮说明

指令列的储存、离开等指令
:w | 将编辑的资料写入硬碟档案中(常用)
:w! | 若档案属性为‘唯读’时，强制写入该档案。不过，到底能不能写入， 还是跟你对该档案的档案权限有关啊！
:q | 离开 vi (常用)
:q! | 若曾修改过档案，又不想储存，使用 ! 为强制离开不储存档案。
注意一下啊，那个惊叹号 (!) 在 vi 当中，常常具有‘强制’的意思～
:wq | 储存后离开，若为 :wq! 则为强制储存后离开 (常用)
ZZ | 这是大写的 Z 喔！若档案没有更动，则不储存离开，若档案已经被更动过，则储存后离开！
:w [filename] | 将编辑的资料储存成另一个档案（类似另存新档）
:r [filename] | 在编辑的资料中，读入另一个档案的资料。亦即将 ‘filename’ 这个档案内容加到游标所在行后面
:n1,n2 w [filename] | 将 n1 到 n2 的内容储存成 filename 这个档案。
:! command | 暂时离开 vi 到指令列模式下执行 command 的显示结果！例如 ‘:! ls /home’即可在 vi 当中察看 /home 底下以 ls 输出的档案资讯！
vim 环境的变更
:set nu | 显示行号，设定之后，会在每一行的字首显示该行的行号
:set nonu | 与 set nu 相反，为取消行号！

特别注意，在 vi 中，‘数字’是很有意义的！数字通常代表重复做几次的意思！ 也有可能是代表去到第几个什么什么的意思。举例来说，要删除 50 行，则是用 ‘50dd’ 对吧！ 数字加在动作之前～那我要向下移动 20 行呢？那就是‘20j’或者是‘20↓’即可。

OK！会这些指令就已经很厉害了，因为常用到的指令也只有不到一半！通常 vi 的指令除了上面鸟哥注明的常用的几个外，其他是不用背的，你可以做一张简单的指令表在你的荧幕墙上， 一有疑问可以马上的查询呦！这也是当初鸟哥使用 vim 的方法啦！

小标题的图示 一个案例练习

来来来！赶紧测试一下你是否已经熟悉 vi 这个指令呢？请依照底下的需求进行指令动作。 (底下的操作为使用 CentOS 5.2 中的 man.config 来做练习的，该档案你可以在这里下载： http://linux.vbird.org/linux_basic/0310vi/man.config。) 看看你的显示结果与鸟哥的结果是否相同啊？

  1. 请在 /tmp 这个目录下建立一个名为 vitest 的目录；
  2. 进入 vitest 这个目录当中；
  3. 将 /etc/man.config 复制到本目录底下(或由上述的连结下载 man.config 档案)；
  4. 使用 vi 开启本目录下的 man.config 这个档案；
  5. 在 vi 中设定一下行号；
  6. 移动到第 58 行，向右移动 40 个字元，请问你看到的双引号内是什么目录？
  7. 移动到第一行，并且向下搜寻一下‘ bzip2 ’这个字串，请问他在第几行？
  8. 接着下来，我要将 50 到 100 行之间的‘小写 man 字串’改为‘大写 MAN 字串’，并且一个一个挑选是否需要修改，如何下达指令？如果在挑选过程中一直按‘y’， 结果会在最后一行出现改变了几个 man 呢？
  9. 修改完之后，突然反悔了，要全部复原，有哪些方法？
  10. 我要复制 65 到 73 这九行的内容(含有MANPATH_MAP)，并且贴到最后一行之后；
  11. 21 到 42 行之间的开头为 # 符号的注解资料我不要了，要如何删除？
  12. 将这个档案另存成一个 man.test.config 的档名；
  13. 去到第 27 行，并且删除 15 个字元，结果出现的第一个单字是什么？
  14. 在第一行新增一行，该行内容输入‘I am a student...’；
  15. 储存后离开吧！

整个步骤可以如下显示：

  1. ‘mkdir /tmp/vitest’
  2. ‘cd /tmp/vitest’
  3. ‘cp /etc/man.config .’
  4. ‘vi man.config’
  5. ‘:set nu’然后你会在画面中看到左侧出现数字即为行号。
  6. 先按下‘58G’再按下‘40→’会看到‘/dir/bin/foo’这个字样在双引号内；
  7. 先执行‘1G’或‘gg’后，直接输入‘/bzip2’，则会去到第 118 行才对！
  8. 直接下达‘ :50,100s/man/MAN/gc ’即可！若一直按‘y’最终会出现‘在 23 行内置换 25 个字串’的说明。
  9. (1)简单的方法可以一直按‘ u ’回复到原始状态，(2)使用不储存离开‘ :q! ’之后，再重新读取一次该档案；
  10. ‘65G’ 然后再‘ 9yy ’之后最后一行会出现‘复制九行’之类的说明字样。 按下‘ G ’到最后一行，再给他‘ p ’贴上九行！
  11. 因为 21~42 22 行，因此‘ 21G ’→‘ 22dd ’就能删除 22 行，此时你会发现游标所在 21 行的地方变成 MANPATH 开头啰， 注解的 # 符号那几行都被删除了。
  12. ‘ :w man.test.config ’，你会发现最后一行出现 "man.test.config" [New].. 的字样。
  13. ‘27G’ 之后，再给他‘ 15x ’即可删除 15 个字元，出现‘ you ’的字样；
  14. 先‘ 1G ’去到第一行，然后按下大写的‘ O ’便新增一行且在插入模式；开始输入‘I am a student...’后， 按下[Esc]回到一般模式等待后续工作；
  15. ‘:wq’

如果你的结果都可以查的到，那么 vi 的使用上面应该没有太大的问题啦！剩下的问题会是在…打字练习…。

小标题的图示 vim 的暂存档、救援回复与开启时的警告讯息

在目前主要的编辑软体都会有‘回复’的功能，亦即当你的系统因为某些原因而导致类似当机的情况时， 还可以透过某些特别的机制来让你将之前未储存的资料‘救’回来！这就是鸟哥这里所谓的‘回复’功能啦！ 那么 vim 有没有回复功能呢？有的！ vim 就是透过‘暂存档’来救援的啦！

当我们在使用 vim 编辑时， vim 会在与被编辑的档案的目录下，再建立一个名为 .filename.swp 的档案。 比如说我们在上一个小节谈到的编辑 /tmp/vitest/man.config 这个档案时， vim 会主动的建立 /tmp/vitest/.man.config.swp 的暂存档，你对 man.config 做的动作就会被记录到这个 .man.config.swp 当中喔！如果你的系统因为某些原因断线了， 导致你编辑的档案还没有储存，这个时候 .man.config.swp 就能够发会救援的功能了！我们来测试一下吧！ 底下的练习有些部分的指令我们尚未谈到，没关系，你先照着做，后续再回来了解啰！

[root@www ~]# cd /tmp/vitest
[root@www vitest]# vim man.config
# 此时会进入到 vim 的画面，请在 vim 的一般模式下按下‘ [ctrl]-z ’的组合键

[1]+  Stopped             vim man.config  <==按下 [ctrl]-z 会告诉你这个讯息

当我们在 vim 的一般模式下按下 [ctrl]-z 的组合按键时，你的 vim 会被丢到背景去执行！ 这部份的功能我们会在第十七章的程序管理当中谈到， 你这里先知道一下即可。回到命令提示字元后，接下来我们来模拟将 vim 的工作不正常的中断吧！

[root@www vitest]# ls -al
total 48
drwxr-xr-x 2 root root 4096 Jan 12 14:48 .
drwxrwxrwt 7 root root 4096 Jan 12 13:26 ..
-rw-r--r-- 1 root root 4101 Jan 12 13:55 man.config
-rw-r--r-- 1 root root 4096 Jan 12 14:48 .man.config.swp  <==就是他，暂存档

-rw-r--r-- 1 root root 4101 Jan 12 13:43 man.test.config

[root@www vitest]# kill -9 %1 <==这里模拟断线停止 vim 工作
[root@www vitest]# ls -al .man.config.swp
-rw-r--r-- 1 root root 4096 Jan 12 14:48 .man.config.swp  <==暂存档还是会存在！

那个 kill 可以模拟将系统的 vim 工作删除的情况，你可以假装当机了啦！ 由于 vim 的工作被不正常的中断，导致暂存档无法藉由正常流程来结束， 所以暂存档就不会消失，而继续保留下来。此时如果你继续编辑那个 man.config ，会出现什么情况呢？ 会出现如下所示的状态喔：

[root@www vitest]# vim man.config
E325: ATTENTION  <==错误代码
Found a swap file by the name ".man.config.swp"  <==底下数行说明有暂存档的存在
          owned by: root   dated: Mon Jan 12 14:48:24 2009
         file name: /tmp/vitest/man.config  <==这个暂存档属于哪个实际的档案？

          modified: no
         user name: root   host name: www.vbird.tsai
        process ID: 11539
While opening file "man.config"
             dated: Mon Jan 12 13:55:07 2009
底下说明可能发生这个错误的两个主要原因与解决方案！
(1) Another program may be editing the same file.
    If this is the case, be careful not to end up with two
    different instances of the same file when making changes.
    Quit, or continue with caution.

(2) An edit session for this file crashed.
    If this is the case, use ":recover" or "vim -r man.config"
    to recover the changes (see ":help recovery").
    If you did this already, delete the swap file ".man.config.swp"
    to avoid this message.

Swap file ".man.config.swp" already exists!底下说明你可进行的动作
[O]pen Read-Only, (E)dit anyway, (R)ecover, (D)elete it, (Q)uit, (A)bort:

由于暂存档存在的关系，因此 vim 会主动的判断你的这个档案可能有些问题，在上面的图示中 vim 提示两点主要的问题与解决方案，分别是这样的：

  • 问题一：可能有其他人或程式同时在编辑这个档案：

    由于 Linux 是多人多工的环境，因此很可能有很多人同时在编辑同一个档案。如果在多人共同编辑的情况下， 万一大家同时储存，那么这个档案的内容将会变的乱七八糟！为了避免这个问题，因此 vim 会出现这个警告视窗！ 解决的方法则是：

    • 找到另外那个程式或人员，请他将该 vim 的工作结束，然后你再继续处理。

    • 如果你只是要看该档案的内容并不会有任何修改编辑的行为，那么可以选择开启成为唯读(O)档案， 亦即上述画面反白部分输入英文‘ o ’即可，其实就是 [O]pen Read-Only 的选项啦！

  • 问题二：在前一个 vim 的环境中，可能因为某些不知名原因导致 vim 中断 (crashed)：

    这就是常见的不正常结束 vim 产生的后果。解决方案依据不同的情况而不同喔！常见的处理方法为：

    • 如果你之前的 vim 处理动作尚未储存，此时你应该要按下‘R’，亦即使用 (R)ecover 的项目， 此时 vim 会载入 .man.config.swp 的内容，让你自己来决定要不要储存！这样就能够救回来你之前未储存的工作。 不过那个 .man.config.swp 并不会在你结束 vim 后自动删除，所以你离开 vim 后还得要自行删除 .man.config.swp 才能避免每次打开这个档案都会出现这样的警告！

    • 如果你确定这个暂存档是没有用的，那么你可以直接按下‘D’删除掉这个暂存档，亦即 (D)elete it 这个项目即可。 此时 vim 会载入 man.config ，并且将旧的 .man.config.swp 删除后，建立这次会使用的新的 .man.config.swp 喔！

至于这个发现暂存档警告讯息的画面中，有出现六个可用按钮，各按钮的说明如下：

  • [O]pen Read-Only：打开此档案成为唯读档， 可以用在你只是想要查阅该档案内容并不想要进行编辑行为时。一般来说，在上课时，如果你是登入到同学的电脑去看他的设定档， 结果发现其实同学他自己也在编辑时，可以使用这个模式；

  • (E)dit anyway：还是用正常的方式打开你要编辑的那个档案， 并不会载入暂存档的内容。不过很容易出现两个使用者互相改变对方的档案等问题！不好不好！

  • (R)ecover：就是载入暂存档的内容，用在你要救回之前未储存的工作。 不过当你救回来并且储存离开 vim 后，还是要手动自行删除那个暂存档喔！

  • (D)elete it：你确定那个暂存档是无用的！那么开启档案前会先将这个暂存档删除！ 这个动作其实是比较常做的！因为你可能不确定这个暂存档是怎么来的，所以就删除掉他吧！哈哈！

  • (Q)uit：按下 q 就离开 vim ，不会进行任何动作回到命令提示字元。

  • (A)bort：忽略这个编辑行为，感觉上与 quit 非常类似！ 也会送你回到命令提示字元就是啰！
大标题的图示 vim 的额外功能

其实，目前大部分的 distributions 都以 vim 取代 vi 的功能了！如果你使用 vi 后，却看到画面的右下角有显示目前游标所在的行列号码，那么你的 vi 已经被 vim 所取代啰～ 为什么要用 vim 呢？因为 vim 具有颜色显示的功能，并且还支援许多的程式语法 (syntax)， 因此，当你使用 vim 编辑程式时( 不论是 C 语言，还是 shell script )， 我们的 vim 将可帮你直接进行‘程式除错 (debug)’的功能！真的很不赖吧！^_^

如果你在文字模式下，输入 alias 时，出现这样的画面：

[root@www ~]# alias
....其他省略....
alias vi='vim'  <==重点在这行啊！

这表示当你使用 vi 这个指令时，其实就是执行 vim 啦！如果你没有这一行，那么你就必须要使用 vim filename 来启动 vim 啰！基本上， vim 的一般用法与 vi 完全一模一样～没有不同啦！那么我们就来看看 vim 的画面是怎样啰！假设我想要编辑 /etc/man.config ，则输入‘vim /etc/man.config’

vim 的图示示意
图3.0.1、 vim 的图示示意

上面是 vim 的画面示意图，在这个画面中有几点特色要说明喔：

  1. 由于 man.config 是系统规划的设定档，因此 vim 会进行语法检验，所以你会看到画面中内部主要为深蓝色， 且深蓝色那一行是以注解符号 (#) 为开头；
  2. 最底下一行的左边显示该档案的属性，包括 141行与 4617 字元；
  3. 最底下一行的右边出现的 1,1 表示游标所在为第一行, 第一个字元位置之意(请看一下上图中的游标所在)；

所以，如果你向下移动到其他位置时，出现的非注解的资料就会有点像这样：

vim 的图示示意
图3.0.2、 vim 的图示示意

看到了喔！除了注解之外，其他的行就会有特别的颜色显示呢！可以避免你打错字啊！而且， 最右下角的 30% 代表目前这个画面占整体档案的 30% 之意！这样了乎？

小标题的图示 区块选择(Visual Block)

刚刚我们提到的简单的 vi 操作过程中，几乎提到的都是以行为单位的操作。那么如果我想要搞定的是一个区块范围呢？ 举例来说，像底下这种格式的档案：

192.168.1.1    host1.class.net
192.168.1.2    host2.class.net
192.168.1.3    host3.class.net
192.168.1.4    host4.class.net
.....中间省略......

这个档案我将他放置到 http://linux.vbird.org/linux_basic/0310vi/hosts ，你可以自行下载来看一看这个档案啊！现在我们来玩一玩这个档案吧！假设我想要将 host1, host2... 等等复制起来， 并且加到每一行的后面，亦即每一行的结果要是‘ 192.168.1.2 host2.class.net host2 ’这样的情况时， 在传统或现代的视窗型编辑器似乎不容易达到这个需求，但是咱们的 vim 是办的到的喔！那就使用区块选择 (Visual Block) 吧！当我们按下 v 或者 V 或者 [Ctrl]+v 时， 这个时候游标移动过的地方就会开始反白，这三个按键的意义分别是：

区块选择的按键意义
v | 字元选择，会将游标经过的地方反白选择！
V | 行选择，会将游标经过的行反白选择！
[Ctrl]+v | 区块选择，可以用长方形的方式选择资料
y | 将反白的地方复制起来
d | 将反白的地方删除掉

来实际进行我们需要的动作吧！就是将 host 再加到每一行的最后面，你可以这样做：

  1. 使用 vim hosts 来开启该档案，记得该档案请由上述的连结下载先！
  2. 将游标移动到第一行的 host 那个 h 上头，然后按下 [ctrl]-v ，左下角出现区块示意字样：

    进入区块功能的示意图
    图 3.1.1、进入区块功能的示意图

  3. 将游标移动到最底部，此时游标移动过的区域会反白！如下图所示：

    区块选择的结果示意图
    图 3.1.2、区块选择的结果示意图

  4. 此时你可以按下‘ y ’来进行复制，当你按下 y 之后，反白的区块就会消失不见啰！
  5. 最后，将游标移动到第一行的最右边，并且再用编辑模式向右按两个空白键，回到一般模式后， 再按下‘ p ’后，你会发现很有趣！如下图所示：

    将区块的资料贴上后的结果
    图 3.1.3、将区块的资料贴上后的结果

透过上述的功能，你可以复制一个区块，并且是贴在某个‘区块的范围’内，而不是以行为单位来处理你的整份文件喔！ 鸟哥个人是觉得这玩意儿非常的有帮助啦！至少在进行排列整齐的文字档案中复制/删除区块时，会是一个非常棒的功能！

小标题的图示 多档案编辑

假设一个例子，你想要将刚刚我们的 hosts 内的 IP 复制到你的 /etc/hosts 这个档案去， 那么该如何编辑？我们知道在 vi 内可以使用 :r filename 来读入某个档案的内容， 不过，这样毕竟是将整个档案读入啊！如果我只是想要部分内容呢？呵呵！这个时候多档案同时编辑就很有用了。 我们可以使用 vim 后面同时接好几个档案来同时开启喔！相关的按键有：

多档案编辑的按键
:n | 编辑下一个档案
:N | 编辑上一个档案
:files | 列出目前这个 vim 的开启的所有档案

在过去，鸟哥想要将 A 档案内的十条消息‘移动’到 B 档案去，通常要开两个 vim 视窗来复制， 偏偏每个 vim 都是独立的，因此并没有办法在 A 档案下达‘ nyy ’再跑到 B 档案去‘ p ’啦！ 在这种情况下最常用的方法就是透过滑鼠圈选， 复制后贴上。不过这样一来还是有问题，因为鸟哥超级喜欢使用 [Tab] 按键进行编排对齐动作， 透过滑鼠却会将 [Tab] 转成空白键，这样内容就不一样了！此时这个多档案编辑就派上用场了！

现在你可以做一下练习看看说！假设你要将刚刚鸟哥提供的 hosts 内的前四行 IP 资料复制到你的 /etc/hosts 档案内，那可以怎么进行呢？可以这样啊：

  1. 透过‘ vim hosts /etc/hosts ’指令来使用一个 vim 开启两个档案；
  2. 在 vim 中先使用‘ :files ’察看一下编辑的档案资料有啥？结果如下所示。 至于下图的最后一行显示的是‘按下任意键’就会回到 vim 的一般模式中！

    多档案编辑示意图
    图 3.2.1、多档案编辑示意图"

  3. 在第一行输入‘ 4yy ’复制四行；
  4. 在 vim 的环境下输入‘ :n ’会来到第二个编辑的档案，亦即 /etc/hosts 内；
  5. 在 /etc/hosts 下按‘ G ’到最后一行，再输入‘ p ’贴上；
  6. 按下多次的‘ u ’来还原原本的档案资料；
  7. 最终按下‘ :q ’来离开 vim 的多档案编辑吧！

看到了吧？利用多档案编辑的功能，可以让你很快速的就将需要的资料复制到正确的档案内。 当然啰，这个功能也可以利用视窗介面来达到，那就是底下要提到的多视窗功能。

小标题的图示 多视窗功能

在开始这个小节前，先来想像两个情况：

  • 当我有一个档案非常的大，我查阅到后面的资料时，想要‘对照’前面的资料， 是否需要使用 [ctrl]+f 与 [ctrl]+b (或 pageup, pagedown 功能键) 来跑前跑后查阅？

  • 我有两个需要对照着看的档案，不想使用前一小节提到的多档案编辑功能；

在一般视窗介面下的编辑软体大多有‘分割视窗’或者是‘冻结视窗’的功能来将一个档案分割成多个视窗的展现， 那么 vim 能不能达到这个功能啊？可以啊！但是如何分割视窗并放入档案呢？ 很简单啊！在指令列模式输入‘:sp {filename}’即可！那个 filename 可有可无， 如果想要在新视窗启动另一个档案，就加入档名，否则仅输入 :sp 时， 出现的则是同一个档案在两个视窗间！

让我们来测试一下，你先使用‘ vim /etc/man.config ’打开这个档案，然后‘ 1G ’去到第一行，之后输入‘ :sp ’ 再次的打开这个档案一次，然后再输入‘ G ’，结果会变成底下这样喔：

视窗分割的示意图
图 3.3.1、视窗分割的示意图

万一你再输入‘ :sp /etc/hosts ’时，就会变成下图这样喔：

视窗分割的示意图
图 3.3.2、视窗分割的示意图

怎样？帅吧！两个档案同时在一个荧幕上面显示，你还可以利用‘[ctrl]+w+↑’及‘[ctrl]+w+↓’ 在两个视窗之间移动呢！这样的话，复制啊、查阅啊等等的，就变的很简单啰～ 分割视窗的相关指令功能有很多，不过你只要记得这几个就好了：

多视窗情况下的按键功能
:sp [filename] | 开启一个新视窗，如果有加 filename， 表示在新视窗开启一个新档案，否则表示两个视窗为同一个档案内容(同步显示)。
[ctrl]+w+ j [ctrl]+w+↓ | 按键的按法是：先按下 [ctrl] 不放， 再按下 w 后放开所有的按键，然后再按下 j (或向下方向键)，则游标可移动到下方的视窗。
[ctrl]+w+ k [ctrl]+w+↑ | 同上，不过游标移动到上面的视窗。
[ctrl]+w+ q | 其实就是 :q 结束离开啦！ 举例来说，如果我想要结束下方的视窗，那么利用 [ctrl]+w+↓ 移动到下方视窗后，按下 :q 即可离开， 也可以按下 [ctrl]+w+q 啊！

鸟哥第一次玩 vim 的分割视窗时，真是很高兴啊！竟然有这种功能！太棒了！ ^_^

小标题的图示 vim 环境设定与记录： ~/.vimrc, ~/.viminfo

有没有发现，如果我们以 vim 软体来搜寻一个档案内部的某个字串时，这个字串会被反白， 而下次我们再次以 vim 编辑这个档案时，该搜寻的字串反白情况还是存在呢！甚至于在编辑其他档案时， 如果其他档案内也存在这个字串，哇！竟然还是主动反白耶！真神奇！ 另外，当我们重复编辑同一个档案时，当第二次进入该档案时， 游标竟然就在上次离开的那一行上头呢！真是好方便啊～但是，怎么会这样呢？

这是因为我们的 vim 会主动的将你曾经做过的行为登录下来，好让你下次可以轻松的作业啊！ 那个记录动作的档案就是： ~/.viminfo ！如果你曾经使用过 vim， 那你的家目录应该会存在这个档案才对。这个档案是自动产生的， 你不必自行建立。而你在 vim 里头所做过的动作，就可以在这个档案内部查询到啰～ ^_^

此外，每个 distributions 对 vim 的预设环境都不太相同，举例来说，某些版本在搜寻到关键字时并不会高亮度反白， 有些版本则会主动的帮你进行缩排的行为。但这些其实都可以自行设定的，那就是 vim 的环境设定啰～ vim 的环境设定参数有很多，如果你想要知道目前的设定值，可以在一般模式时输入‘ :set all ’ 来查阅，不过.....设定项目实在太多了～所以，鸟哥在这里仅列出一些平时比较常用的一些简单的设定值， 提供给你参考啊。

Tips:
所谓的缩排，就是当你按下 Enter 编辑新的一行时，游标不会在行首，而是在与上一行的第一个非空白字元处对齐！ 		鸟哥的图示
vim 的环境设定参数
:set nu :set nonu | 就是设定与取消行号啊！
:set hlsearch :set nohlsearch | hlsearch 就是 high light search(高亮度搜寻)。 这个就是设定是否将搜寻的字串反白的设定值。预设值是 hlsearch
:set autoindent :set noautoindent | 是否自动缩排？autoindent 就是自动缩排。
:set backup | 是否自动储存备份档？一般是 nobackup 的， 如果设定 backup 的话，那么当你更动任何一个档案时，则原始档案会被另存成一个档名为 filename~ 的档案。 举例来说，我们编辑 hosts ，设定 :set backup ，那么当更动 hosts 时，在同目录下，就会产生 hosts~ 档名的档案，记录原始的 hosts 档案内容
:set ruler | 还记得我们提到的右下角的一些状态列说明吗？ 这个 ruler 就是在显示或不显示该设定值的啦！
:set showmode | 这个则是，是否要显示 --INSERT-- 之类的字眼在左下角的状态列。
:set backspace=(012) | 一般来说， 如果我们按下 i 进入编辑模式后，可以利用倒退键 (backspace) 来删除任意字元的。 但是，某些 distribution 则不许如此。此时，我们就可以透过 backspace 来设定啰～ 当 backspace 为 2 时，就是可以删除任意值；0 或 1 时，仅可删除刚刚输入的字元， 而无法删除原本就已经存在的文字了！
:set all | 显示目前所有的环境参数设定值。
:set | 显示与系统预设值不同的设定参数， 一般来说就是你有自行变动过的设定参数啦！
:syntax on :syntax off | 是否依据程式相关语法显示不同颜色？ 举例来说，在编辑一个纯文字档时，如果开头是以 # 开始，那么该行就会变成蓝色。 如果你懂得写程式，那么这个 :syntax on 还会主动的帮你除错呢！但是， 如果你仅是编写纯文字档案，要避免颜色对你的荧幕产生的干扰，则可以取消这个设定 。
:set bg=dark :set bg=light | 可用以显示不同的颜色色调，预设是‘ light ’。如果你常常发现注解的字体深蓝色实在很不容易看， 那么这里可以设定为 dark 喔！试看看，会有不同的样式呢！

总之，这些设定值很有用处的啦！但是......我是否每次使用 vim 都要重新设定一次各个参数值？ 这不太合理吧？没错啊！所以，我们可以透过设定档来直接规定我们习惯的 vim 操作环境呢！ 整体 vim 的设定值一般是放置在 /etc/vimrc 这个档案，不过，不建议你修改他！ 你可以修改 ~/.vimrc 这个档案 (预设不存在，请你自行手动建立！)，将你所希望的设定值写入！ 举例来说，可以是这样的一个档案：

[root@www ~]# vim ~/.vimrc
"这个档案的双引号 (") 是注解
set hlsearch            "高亮度反白
set backspace=2         "可随时用倒退键删除
set autoindent          "自动缩排
set ruler               "可显示最后一行的状态
set showmode            "左下角那一行的状态
set nu                  "可以在每一行的最前面显示行号啦！
set bg=dark             "显示不同的底色色调
syntax on               "进行语法检验，颜色显示。

在这个档案中，使用‘ set hlsearch ’或‘ :set hlsearch ’，亦即最前面有没有冒号‘ : ’效果都是一样的！ 至于双引号则是注解符号！不要用错注解符号，否则每次使用 vim 时都会发生警告讯息喔！ 建立好这个档案后，当你下次重新以 vim 编辑某个档案时，该档案的预设环境设定就是上头写的啰～ 这样，是否很方便你的操作啊！多多利用 vim 的环境设定功能呢！^_^

小标题的图示 vim 常用指令示意图

为了方便大家查询在不同的模式下可以使用的 vim 指令，鸟哥查询了一些 vim 与 Linux 教育训练手册， 发现底下这张图非常值得大家参考！可以更快速有效的查询到需要的功能喔！看看吧！

vim 常用指令示意图
图 3.5.1 、 vim 常用指令示意图
大标题的图示 其他 vim 使用注意事项

vim 其实不是那么好学，虽然他的功能确实非常强大！所以底下我们还有一些需要注意的地方要来跟大家分享喔！

小标题的图示 中文编码的问题

很多朋友常常哀嚎，说他们的 vim 里面怎么无法显示正常的中文啊？其实这很有可能是因为编码的问题！ 因为中文编码有 big5 与 utf8 两种，如果你的档案是使用 big5 编码制作的，但在 vim 的终端介面中你使用的是万国码(utf8)， 由于编码的不同，你的中文档案内容当然就是一堆乱码了！怎么办？这时你得要考虑许多东西啦！有这些：

  1. 你的 Linux 系统预设支援的语系资料：这与 /etc/sysconfig/i18n 有关；
  2. 你的终端介面 (bash) 的语系： 这与 LANG 这个变数有关；
  3. 你的档案原本的编码；
  4. 开启终端机的软体，例如在 GNOME 底下的视窗介面。

事实上最重要的是上头的第三与第四点，只要这两点的编码一致，你就能够正确的看到与编辑你的中文档案。 否则就会看到一堆乱码啦！

一般来说，中文编码使用 big5 时，在写入某些资料库系统中，在‘许、盖、功’这些字体上面会发生错误！ 所以近期以来大多希望大家能够使用万国码 utf8 来进行中文编码！但是在 Windows XP 上的软体常常预设使用 big5 的编码， 包括鸟哥由于沿用以前的文件资料档案，也大多使用 big5 的编码。此时就得要注意上述的这些咚咚啰。

在 Linux 本机前的 tty1~tty6 原本预设就不支援中文编码，所以不用考虑这个问题！因为你一定会看到乱码！呵呵！ 现在鸟哥假设俺的文件档案内编码为 big5 时，而且我的环境是使用 Linux 的 GNOME ，启动的终端介面为 GNOME-terminal 软体， 那鸟哥通常是这样来修正语系编码的行为：

[root@www ~]# LANG=zh_TW.big5

然后在终端介面工具列的‘终端机’-->‘设定字元编码’ -->‘中文 (正体) (BIG5)’项目点选一下， 如果一切都没有问题了，再用 vim 去开启那个 big5 编码的档案，就没有问题了！以上！报告完毕！

小标题的图示 DOS 与 Linux 的断行字元

我们在第七章里面谈到 cat 这个指令时，曾经提到过 DOS 与 Linux 断行字元的不同。 而我们也可以利用 cat -A 来观察以 DOS (Windows 系统) 建立的档案的特殊格式， 也可以发现在 DOS 使用的断行字元为 ^M$ ，我们称为 CR 与 LF 两个符号。 而在 Linux 底下，则是仅有 LF ($) 这个断行符号。这个断行符号对于 Linux 的影响很大喔！ 为什么呢？

我们说过，在 Linux 底下的指令在开始执行时，他的判断依据是 ‘Enter’，而 Linux 的 Enter 为 LF 符号， 不过，由于 DOS 的断行符号是 CRLF ，也就是多了一个 ^M 的符号出来， 在这样的情况下，如果是一个 shell script 的程式档案，呵呵～将可能造成‘程式无法执行’的状态～ 因为他会误判程式所下达的指令内容啊！这很伤脑筋吧！

那怎么办啊？很简单啊，将格式转换成为 Linux 即可啊！‘废话’，这当然大家都知道，但是， 要以 vi 进入该档案，然后一个一个删除每一行的 CR 吗？当然没有这么没人性啦！ 我们可以透过简单的指令来进行格式的转换啊！

[root@www ~]# dos2unix [-kn] file [newfile]
[root@www ~]# unix2dos [-kn] file [newfile]
选项与参数：
-k  ：保留该档案原本的 mtime 时间格式 (不更新档案上次内容经过修订的时间)
-n  ：保留原本的旧档，将转换后的内容输出到新档案，如： dos2unix -n old new

范例一：将刚刚上述练习的 /tmp/vitest/man.config 修改成为 dos 断行
[root@www ~]# cd /tmp/vitest
[root@www vitest]# cp -a /etc/man.config .

[root@www vitest]# ll man.config
-rw-r--r-- 1 root root 4617 Jan  6  2007 man.config
[root@www vitest]# unix2dos -k man.config
unix2dos: converting file man.config to DOS format ...
# 荧幕会显示上述的讯息，说明断行转为 DOS 格式了！
[root@www vitest]# ll man.config
-rw-r--r-- 1 root root 4758 Jan  6  2007 man.config

# 断行字元多了 ^M ，所以容量增加了！

范例二：将上述的 man.config 转成 man.config.linux 的 Linux 断行字元
[root@www vitest]# dos2unix -k -n man.config man.config.linux
dos2unix: converting file man.config to file man.config.linux in UNIX format ...
[root@www vitest]# ll man.config*
-rw-r--r-- 1 root root 4758 Jan  6  2007 man.config
-rw------- 1 root root 4617 Jan  6  2007 man.config.linux

因为断行字符以及 DOS 与 Linux 作业系统底下一些字符的定义不同，因此， 不建议你在 Windows 系统当中将档案编辑好之后，才上传到 Linux 系统，会容易发生错误问题。 而且，如果你在不同的系统之间复制一些纯文字档案时，千万记得要使用 unix2dos 或 dos2unix 来转换一下断行格式啊！

小标题的图示 语系编码转换

很多朋友都会有的问题，就是想要将语系编码进行转换啦！举例来说，想要将 big5 编码转成 utf8 。 这个时候怎么办？难不成要每个档案打开会转存成 utf8 吗？不需要这样做啦！使用 iconv 这个指令即可！ 鸟哥将之前的 vi 章节做成 big5 编码的档案，你可以照底下的连结来下载先：

  • http://linux.vbird.org/linux_basic/0310vi/vi.big5

在终端机的环境下你可以使用‘ wget 网址’来下载上述的档案喔！鸟哥将他下载在 /tmp/vitest 目录下。 接下来让我们来使用 iconv 这个指令来玩一玩编码转换吧！

[root@www ~]# iconv --list
[root@www ~]# iconv -f 原本编码 -t 新编码 filename [-o newfile]
选项与参数：
--list ：列出 iconv 支援的语系资料
-f     ：from ，亦即来源之意，后接原本的编码格式；
-t     ：to ，亦即后来的新编码要是什么格式；
-o file：如果要保留原本的档案，那么使用 -o 新档名，可以建立新编码档案。

范例一：将 /tmp/vitest/vi.big5 转成 utf8 编码吧！
[root@www ~]# cd /tmp/vitest

[root@www vitest]# iconv -f big5 -t utf8 vi.big5 -o vi.utf8
[root@www vitest]# file vi*
vi.big5: ISO-8859 text, with CRLF line terminators
vi.utf8: UTF-8 Unicode text, with CRLF line terminators
# 是吧！有明显的不同吧！ ^_^

这指令支援的语系非常之多，除了正体中文的 big5, utf8 编码之外，也支援简体中文的 gb2312 ， 所以对岸的朋友可以简单的将鸟站的网页资料下载后，利用这个指令来转成简体，就能够轻松的读取文件资料啰！ 不过，不要将转成简体的档案又上传成为您自己的网页啊！这明明是鸟哥写的不是吗？ ^_^

不过如果是要将正体中文的 utf8 转成简体中文的 utf8 编码时，那就得费些功夫了！ 举例来说，如果要将刚刚那个 vi.utf8 转成简体的 utf8 时，可以这样做：

[root@www vitest]# iconv -f utf8 -t big5 vi.utf8 | \
> iconv -f big5 -t gb2312 | iconv -f gb2312 -t utf8 -o vi.gb.utf8
大标题的图示 重点回顾
  • Linux 底下的设定档多为文字档，故使用 vim 即可进行设定编辑；
  • vim 可视为程式编辑器，可用以编辑 shell script, 设定档等，避免打错字；
  • vi 为所有 unix like 的作业系统都会存在的编辑器，且执行速度快速；
  • vi 有三种模式，一般模式可变换到编辑与指令列模式，但编辑模式与指令列模式不能互换；
  • 常用的按键有i, [Esc], :wq 等；
  • vi 的画面大略可分为两部份，(1)上半部的本文与(2)最后一行的状态+指令列模式；
  • 数字是有意义的，用来说明重复进行几次动作的意思，如 5yy 为复制 5 行之意；
  • 游标的移动中，大写的 G 经常使用，尤其是 1G, G 移动到文章的头/尾功能！
  • vi 的取代功能也很棒！ :n1,n2s/old/new/g 要特别注意学习起来；
  • 小数点‘ . ’为重复进行前一次动作，也是经常使用的按键功能！
  • 进入编辑模式几乎只要记住： i, o, R 三个按钮即可！尤其是新增一行的 o 与取代的 R
  • vim 会主动的建立 swap 暂存档，所以不要随意断线！
  • 如果在文章内有对其的区块，可以使用 [ctrl]-v 进行复制/贴上/删除的行为
  • 使用 :sp 功能可以分割视窗
  • vim 的环境设定可以写入在 ~/.vimrc 档案中；
  • 可以使用 iconv 进行档案语系编码的转换
  • 使用 dos2unix 及 unix2dos 可以变更档案每一行的行尾断行字元。
大标题的图示 本章练习
(要看答案请将滑鼠移动到‘答：’底下的空白处，按下左键圈选空白处即可察看)
实作题部分：
  • 在第八章的情境模拟题二的第五点，编写 /etc/fstab 时，当时使用 nano 这个指令， 请尝试使用 vim 去编辑 /etc/fstab ，并且将第八章新增的那一行的 defatuls 改成 default ，会出现什么状态？ 离开前请务必要修订成原本正确的资讯。此外，如果将该行注解 (最前面加 #)，你会发现字体颜色也有变化喔！

  • 尝试在你的系统中，你惯常使用的那个帐号的家目录下，将本章介绍的 vimrc 内容进行一些常用设定，包括：
    • 设定搜寻高亮度反白
    • 设定语法检验启动
    • 设定预设启动行号显示
    • 设定有两行状态列 (一行状态+一行指令列) :set laststatus=2
简答题部分：
  • 我用 vi 开启某个档案后，要在第 34 行向右移动 15 个字元，应该在一般模式中下达什么指令？
    (1)先按下 34G 到第 34 行；(2)再按下 [ 15 + 向右键 ]，或 [ 15l ] 亦可！
  • 在 vi 开启的档案中，如何去到该档案的页首或页尾？
    去页首按下 1G 或 gg ；去页尾按下 G 即可
  • 在 vi 开启的档案中，如何在游标所在行中，移动到行头及行尾？
    移动到行头，按 0 ，移动到行尾按 $ 即可！
  • vi 的一般模式情况下，按下‘ r ’有什么功能？
    取代游标所在的那个字元
  • 在 vi 的环境中，如何将目前正在编辑的档案另存新档名为 newfilename？
    :w newfilename
  • 在 linux 底下最常使用的文书编辑器为 vi ，请问如何进入编辑模式？
    在一般模式底下输入： i, I, a, A 为在本行当中输入新字元；(出现 –Insert- )
    在一般模式当中输入： o, O 为在一个新的一行输入新字元；
    在一般模式当中输入： r, R 为取代字元！（左下角出现 –Replace-）
  • 在 vi 软体中，如何由编辑模式跳回一般模式？
    可以按下[Esc]
  • 在 vi 环境中，若上下左右键无法使用时，请问如何在一般模式移动游标？
    [h, j, k, l]分别代表[左、下、上、右]
  • 在 vi 的一般模式中，如何删除一行、n行；如何删除一个字元？
    分别为 dd, ndd, x 或 X （dG 及 d1G 分别表示删除到页首及页尾）
  • 在 vi 的一般模式中，如何复制一行、n行并加以贴上？
    分别为 yy, nyy, p 或 P
  • 在 vi 的一般模式中如何搜寻 string 这个字串？
    ?string (往前搜寻)
    /string (往后搜寻)
  • 在 vi 的一般模式中，如何取代 word1 成为 word2，而若需要使用者确认机制，又该如何？
    :1,$s/word1/word2/g 或
    :1,$s/word1/word2/gc （需要使用者确认）
  • 在 vi 目前的编辑档案中，在一般模式下，如何读取一个档案 filename 进来目前这个档案？
    :r filename
  • 在 vi 的一般模式中，如何存档、离开、存档后离开、强制存档后离开？
    :w； :q： :wq； :wq!
  • 在 vi 底下作了很多的编辑动作之后，却想还原成原来的档案内容，应该怎么进行？
    直接按下 :e! 即可恢复成档案的原始状态！
  • 我在 vi 这个程式当中，不想离开 vi ，但是想执行 ls /home 这个指令，vi 有什么额外的功能可以达到这个目的：
    事实上，可以使用[ :! ls /home ]不过，如果你学过后面的章节之后，你会发现，执行[ ctrl + z ]亦可暂时退出 vi 让你在指令列模式当中执行指令喔！
大标题的图示 参考资料与延伸阅读
  • 维基百科：ASCII 的代码与图示对应表：http://zh.wikipedia.org/wiki/ASCII
  • 注1：常见文书编辑器专案计划连结：
    • emacs: http://www.gnu.org/software/emacs/
    • pico: http://www.ece.uwaterloo.ca/~ece250/Online/Unix/pico/
    • nano: http://sourceforge.net/projects/nano/
    • joe: http://sourceforge.net/projects/joe-editor/
    • vim: http://www.vim.org
    • 常见文书编辑器比较：http://encyclopedia.thefreedictionary.com/List+of+text+editors
    • 维基百科的文书编辑器比较：http://en.wikipedia.org/wiki/Comparison_of_text_editors
  • 关于 vim 是什么的‘中文’说明：http://www.vim.org/6k/features.zh.txt。
  • 李果正兄的：大家来学 vim (http://info.sayya.org/~edt1023/vim/)
  • 麦克星球 Linux Fedora 心得笔记：
    正体/简体中文的转换方法：http://blog.xuite.net/michaelr/linux/15650102
2002/04/05：第一次完成
2003/02/07：重新编排与加入 FAQ
2003/02/25：新加入本章节与 LPI 的相关性说明！
2005/07/28：将旧文章移动到 这里 。
2005/08/01：加入果正兄文章的参考，还有查阅 vim 官方网站的资料！
2008/12/18：将原本针对 FC4 版本的文章移动到 此处
2009/01/13：这么简单的一篇改写，竟改了一个月！原因只是期末考将近太忙了～
2009/08/20：加入实作题，编辑简答题，加入 vim 指令示意图等


鸟哥的 Linux 私房菜 -- 基础学习篇

为取得较佳浏览结果，请爱用 firefox 浏览本网页

第十一章、认识与学习 BASH
最近更新日期：2009/08/25
在 Linux 的环境下，如果你不懂 bash 是什么，那么其他的东西就不用学了！因为前面几章我们使用终端机下达指令的方式， 就是透过 bash 的环境来处理的喔！所以说，他很重要吧！bash 的东西非常的多，包括变数的设定与使用、 bash 操作环境的建置、资料流重导向的功能，还有那好用的管线命令！好好清一清脑门，准备用功去啰～ ^_^ 这个章节几乎是所有指令列模式 (command line) 与未来主机维护与管理的重要基础，一定要好好仔细的阅读喔！

1. 认识 BASH 这个 Shell
    1.1 硬体、核心与 Shell
    1.2 为何要学文字介面的 shell
    1.3 系统的合法 shell 与 /etc/shells 功能
    1.4 Bash shell 的功能
    1.5 Bash shell 的内建命令： type
    1.6 指令的下达
 2. Shell 的变数功能
    2.1 什么是变数？
    2.2 变数的取用与设定：echo, 变数设定规则, unset
    2.3 环境变数的功能： env 与常见环境变数说明, set, export
    2.4 影响显示结果的语系变数 (locale)
    2.5 变数的有效范围：
    2.6 变数键盘读取、阵列与宣告： read, declare, array
    2.7 与档案系统及程序的限制关系： ulimit
    2.8 变数内容的删除、取代与替换：, 删除与取代, 测试与替换
 3. 命令别名与历史命令
    3.1 命令别名设定： alias, unalias
    3.2 历史命令： history, HISTSIZE
 4. Bash shell 的操作环境
    4.1 路径与指令搜寻顺序
    4.2 bash 的进站与欢迎讯息： /etc/issue, /etc/motd
    4.3 环境设定档: login, non-login shell, /etc/profile, ~/.bash_profile, source, ~/.bashrc
    4.4 终端机的环境设定： stty, set
    4.5 万用字元与特殊符号
 5. 资料流重导向 (Redirection)
    5.1 何谓资料流重导向？
    5.2 命令执行的判断依据： ; , &&, ||
 6. 管线命令 (pipe)
    6.1 撷取命令： cut, grep
    6.2 排序命令： sort, uniq, wc
    6.3 双向重导向： tee
    6.4 字元转换命令： tr, col, join, paste, expand
    6.5 分割命令： split
    6.6 参数代换： xargs
    6.7 关于减号 - 的用途
 7. 重点回顾
8. 本章习题
9. 参考资料与延伸阅读
10. 针对本文的建议：http://phorum.vbird.org/viewtopic.php?t=23884
大标题的图示 认识 BASH 这个 Shell

我们在第一章 Linux 是什么当中提到了： 管理整个电脑硬体的其实是作业系统的核心 (kernel)，这个核心是需要被保护的！ 所以我们一般使用者就只能透过 shell 来跟核心沟通，以让核心达到我们所想要达到的工作。 那么系统有多少 shell 可用呢？为什么我们要使用 bash 啊？底下分别来谈一谈喔！

小标题的图示 硬体、核心与 Shell

这应该是个蛮有趣的话题：‘什么是 Shell ’？相信只要摸过电脑，对于作业系统 (不论是 Linux 、 Unix 或者是 Windows) 有点概念的朋友们大多听过这个名词，因为只要有‘作业系统’那么就离不开 Shell 这个东西。不过，在讨论 Shell 之前，我们先来了解一下电脑的运作状况吧！ 举个例子来说：当你要电脑传输出来‘音乐’的时候，你的电脑需要什么东西呢？

  1. 硬体：当然就是需要你的硬体有‘音效卡晶片’这个配备，否则怎么会有声音；
  2. 核心管理：作业系统的核心可以支援这个晶片组，当然还需要提供晶片的驱动程式啰；
  3. 应用程式：需要使用者 (就是你) 输入发生声音的指令啰！

这就是基本的一个输出声音所需要的步骤！也就是说，你必须要‘输入’一个指令之后， ‘硬体’才会透过你下达的指令来工作！那么硬体如何知道你下达的指令呢？那就是 kernel (核心) 的控制工作了！也就是说，我们必须要透过‘ Shell ’将我们输入的指令与 Kernel 沟通，好让 Kernel 可以控制硬体来正确无误的工作！ 基本上，我们可以透过底下这张图来说明一下：

硬体、核心与使用者的相关性图示
图 1.1.1、硬体、核心与使用者的相关性图示

我们在第零章内的作业系统小节曾经提到过， 作业系统其实是一组软体，由于这组软体在控制整个硬体与管理系统的活动监测， 如果这组软体能被使用者随意的操作，若使用者应用不当，将会使得整个系统崩溃！因为作业系统管理的就是整个硬体功能嘛！ 所以当然不能够随便被一些没有管理能力的终端用户随意使用啰！

但是我们总是需要让使用者操作系统的，所以就有了在作业系统上面发展的应用程式啦！使用者可以透过应用程式来指挥核心， 让核心达成我们所需要的硬体任务！如果考虑如第零章所提供的作业系统图示(图4.2.1)， 我们可以发现应用程式其实是在最外层，就如同鸡蛋的外壳一样，因此这个咚咚也就被称呼为壳程式 (shell) 啰！

其实壳程式的功能只是提供使用者操作系统的一个介面，因此这个壳程式需要可以呼叫其他软体才好。 我们在第五章到第十章提到过很多指令，包括 man, chmod, chown, vi, fdisk, mkfs 等等指令，这些指令都是独立的应用程式， 但是我们可以透过壳程式 (就是指令列模式) 来操作这些应用程式，让这些应用程式呼叫核心来运作所需的工作哩！ 这样对于壳程式是否有了一定的概念了？

Tips:
也就是说，只要能够操作应用程式的介面都能够称为壳程式。狭义的壳程式指的是指令列方面的软体，包括本章要介绍的 bash 等。 广义的壳程式则包括图形介面的软体！因为图形介面其实也能够操作各种应用程式来呼叫核心工作啊！ 不过在本章中，我们主要还是在使用 bash 啦！ 		鸟哥的图示
小标题的图示 为何要学文字介面的 shell？

文字介面的 shell 是很不好学的，但是学了之后好处多多！所以， 在这里鸟哥要先对您进行一些心理建设，先来了解一下为啥学习 shell 是有好处的，这样你才会有信心继续玩下去 ^_^

  • 文字介面的 shell：大家都一样！

鸟哥常常听到这个问题：‘我干嘛要学习 shell 呢？ 不是已经有很多的工具可以提供我设定我的主机了？我为何要花这么多时间去学指令呢？不是以 X Window 按一按几个按钮就可以搞定了吗？’唉～还是得一再地强调， X Window 还有 Web 介面的设定工具例如 Webmin (注1) 是真的好用的家伙， 他真的可以帮助我们很简易的设定好我们的主机，甚至是一些很进阶的设定都可以帮我们搞定。

但是鸟哥在前面的章节里面也已经提到过相当多次了， X Window 与 web 介面的工具，他的介面虽然亲善，功能虽然强大， 但毕竟他是将所有利用到的软体都整合在一起的一组应用程式而已， 并非是一个完整的套件，所以某些时候当你升级或者是使用其他套件管理模组 (例如 tarball 而非 rpm 档案等等) 时，就会造成设定的困扰了。甚至不同的 distribution 所设计的 X window 介面也都不相同，这样也造成学习方面的困扰。

文字介面的 shell 就不同了！几乎各家 distributions 使用的 bash 都是一样的！如此一来， 你就能够轻轻松松的转换不同的 distributions ，就像武侠小说里面提到的‘一法通、万法通！’

  • 远端管理：文字介面就是比较快！

此外，Linux 的管理常常需要透过远端连线，而连线时文字介面的传输速度一定比较快， 而且，较不容易出现断线或者是资讯外流的问题，因此，shell 真的是得学习的一项工具。而且，他可以让您更深入 Linux ，更了解他，而不是只会按一按滑鼠而已！所谓‘天助自助者！’多摸一点文字模式的东西，会让你与 Linux 更亲近呢！

  • Linux 的任督二脉： shell 是也！

有些朋友也很可爱，常会说：‘我学这么多干什么？ 又不常用，也用不到！’嘿嘿！有没有听过‘书到用时方恨少？’ 当你的主机一切安然无恙的时候，您当然会觉得好像学这么多的东西一点帮助也没有呀！ 万一，某一天真的不幸给他中标了，您该如何是好？是直接重新安装？ 还是先追踪入侵来源后进行漏洞的修补？或者是干脆就关站好了？这当然涉及很多的考量， 但就以鸟哥的观点来看，多学一点总是好的，尤其我们可以有备而无患嘛！甚至学的不精也没有关系，了解概念也就 OK 啦！毕竟没有人要您一定要背这么多的内容啦！了解概念就很了不起了！

此外，如果你真的有心想要将您的主机管理的好，那么良好的 shell 程式编写是一定需要的啦！就鸟哥自己来说，鸟哥管理的主机虽然还不算多， 只有区区不到十部，但是如果每部主机都要花上几十分钟来查阅他的登录档资讯以及相关的讯息， 那么鸟哥可能会疯掉！基本上，也太没有效率了！这个时候，如果能够藉由 shell 提供的资料流重导向以及管线命令，呵呵！ 那么鸟哥分析登录资讯只要花费不到十分钟就可以看完所有的主机之重要资讯了！相当的好用呢！

由于学习 shell 的好处真的是多多啦！所以，如果你是个系统管理员，或者有心想要管理系统的话，那么 shell 与 shell scripts 这个东西真的有必要看一看！因为他就像‘打通任督二脉，任何武功都能随你应用’的说！

小标题的图示 系统的合法 shell 与 /etc/shells 功能

知道什么是 Shell 之后，那么我们来了解一下 Linux 使用的是哪一个 shell 呢？什么！哪一个？难道说 shell 不就是‘一个 shell 吗？’哈哈！那可不！由于早年的 Unix 年代，发展者众，所以由于 shell 依据发展者的不同就有许多的版本，例如常听到的 Bourne SHell (sh) 、在 Sun 里头预设的 C SHell、 商业上常用的 K SHell、, 还有 TCSH 等等，每一种 Shell 都各有其特点。至于 Linux 使用的这一种版本就称为‘ Bourne Again SHell (简称 bash) ’，这个 Shell 是 Bourne Shell 的增强版本，也是基准于 GNU 的架构下发展出来的呦！

在介绍 shell 的优点之前，先来说一说 shell 的简单历史吧(注2)：第一个流行的 shell 是由 Steven Bourne 发展出来的，为了纪念他所以就称为 Bourne shell ，或直接简称为 sh ！而后来另一个广为流传的 shell 是由柏克莱大学的 Bill Joy 设计依附于 BSD 版的 Unix 系统中的 shell ，这个 shell 的语法有点类似 C 语言，所以才得名为 C shell ，简称为 csh ！由于在学术界 Sun 主机势力相当的庞大，而 Sun 主要是 BSD 的分支之一，所以 C shell 也是另一个很重要而且流传很广的 shell 之一 。

Tips:
由于 Linux 为 C 程式语言撰写的，很多程式设计师使用 C 来开发软体，因此 C shell 相对的就很热门了。 另外，还记得我们在第一章、Linux 是什么提到的吧？ Sun 公司的创始人就是 Bill Joy，而 BSD 最早就是 Bill Joy 发展出来的啊。 		鸟哥的图示

那么目前我们的 Linux (以 CentOS 5.x 为例) 有多少我们可以使用的 shells 呢？ 你可以检查一下 /etc/shells 这个档案，至少就有底下这几个可以用的 shells：

  • /bin/sh (已经被 /bin/bash 所取代)
  • /bin/bash (就是 Linux 预设的 shell)
  • /bin/ksh (Kornshell 由 AT&T Bell lab. 发展出来的，相容于 bash)
  • /bin/tcsh (整合 C Shell ，提供更多的功能)
  • /bin/csh (已经被 /bin/tcsh 所取代)
  • /bin/zsh (基于 ksh 发展出来的，功能更强大的 shell)

虽然各家 shell 的功能都差不多，但是在某些语法的下达方面则有所不同，因此建议你还是得要选择某一种 shell 来熟悉一下较佳。 Linux 预设就是使用 bash ，所以最初你只要学会 bash 就非常了不起了！ ^_^！ 另外，咦！为什么我们系统上合法的 shell 要写入 /etc/shells 这个档案啊？ 这是因为系统某些服务在运作过程中，会去检查使用者能够使用的 shells ，而这些 shell 的查询就是藉由 /etc/shells 这个档案啰！

举例来说，某些 FTP 网站会去检查使用者的可用 shell ，而如果你不想要让这些使用者使用 FTP 以外的主机资源时，可能会给予该使用者一些怪怪的 shell，让使用者无法以其他服务登入主机。 这个时候，你就得将那些怪怪的 shell 写到 /etc/shells 当中了。举例来说，我们的 CentOS 5.x 的 /etc/shells 里头就有个 /sbin/nologin 档案的存在，这个就是我们说的怪怪的 shell 啰～

那么，再想一想，我这个使用者什么时候可以取得 shell 来工作呢？还有， 我这个使用者预设会取得哪一个 shell 啊？还记得我们在第五章的在终端介面登入linux小节当中提到的登入动作吧？ 当我登入的时候，系统就会给我一个 shell 让我来工作了。 而这个登入取得的 shell 就记录在 /etc/passwd 这个档案内！这个档案的内容是啥？

[root@www ~]# cat /etc/passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin

daemon:x:2:2:daemon:/sbin:/sbin/nologin
.....(底下省略).....

如上所示，在每一行的最后一个资料，就是你登入后可以取得的预设的 shell 啦！那你也会看到， root 是 /bin/bash ，不过，系统帐号 bin 与 daemon 等等，就使用那个怪怪的 /sbin/nologin 啰～关于使用者这部分的内容，我们留在第十四章的帐号管理时提供更多的说明。

小标题的图示 Bash shell 的功能

既然 /bin/bash 是 Linux 预设的 shell ，那么总是得了解一下这个玩意儿吧！bash 是 GNU 计划中重要的工具软体之一，目前也是 Linux distributions 的标准 shell 。 bash 主要相容于 sh ，并且依据一些使用者需求，而加强的 shell 版本。不论你使用的是那个 distribution ，你都难逃需要学习 bash 的宿命啦！那么这个 shell 有什么好处，干嘛 Linux 要使用他作为预设的 shell 呢？ bash 主要的优点有底下几个：

  • 命令编修能力 (history)：

bash 的功能里头，鸟哥个人认为相当棒的一个就是‘他能记忆使用过的指令！’ 这功能真的相当的棒！因为我只要在指令列按‘上下键’就可以找到前/后一个输入的指令！而在很多 distribution 里头，预设的指令记忆功能可以到达 1000 个！也就是说， 你曾经下达过的指令几乎都被记录下来了。

这么多的指令记录在哪里呢？在你的家目录内的 .bash_history 啦！ 不过，需要留意的是，~/.bash_history 记录的是前一次登入以前所执行过的指令， 而至于这一次登入所执行的指令都被暂存在记忆体中，当你成功的登出系统后，该指令记忆才会记录到 .bash_history 当中！

这有什么功能呢？最大的好处就是可以‘查询曾经做过的举动！’ 如此可以知道你的执行步骤，那么就可以追踪你曾下达过的指令，以作为除错的工具！ 但如此一来也有个烦恼，就是如果被骇客入侵了，那么他只要翻你曾经执行过的指令， 刚好你的指令又跟系统有关 (例如直接输入 MySQL 的密码在指令列上面)，那你的主机可就伤脑筋了！ 到底记录指令的数目越多还是越少越好？这部份是见仁见智啦，没有一定的答案的。

  • 命令与档案补全功能： ([tab] 按键的好处)

还记得我们在第五章内的重要的几个热键小节当中提到的 [tab] 这个按键吗？这个按键的功能就是在 bash 里头才有的啦！常常在 bash 环境中使用 [tab] 是个很棒的习惯喔！因为至少可以让你 1)少打很多字； 2)确定输入的资料是正确的！ 使用 [tab] 按键的时机依据 [tab] 接在指令后或参数后而有所不同。我们再复习一次：

  • [Tab] 接在一串指令的第一个字的后面，则为命令补全；
  • [Tab] 接在一串指令的第二个字以后时，则为‘档案补齐’！

所以说，如果我想要知道我的环境中，所有可以执行的指令有几个？ 就直接在 bash 的提示字元后面连续按两次 [tab] 按键就能够显示所有的可执行指令了。 那如果想要知道系统当中所有以 c 为开头的指令呢？就按下‘ c[tab][tab] ’就好啦！ ^_^

是的！真的是很方便的功能，所以，有事没事，在 bash shell 底下，多按几次 [tab] 是一个不错的习惯啦！

  • 命令别名设定功能： (alias)

假如我需要知道这个目录底下的所有档案 (包含隐藏档) 及所有的档案属性，那么我就必须要下达‘ ls -al ’这样的指令串，唉！真麻烦，有没有更快的取代方式？呵呵！就使用命令别名呀！例如鸟哥最喜欢直接以 lm 这个自订的命令来取代上面的命令，也就是说， lm 会等于 ls -al 这样的一个功能，嘿！那么要如何作呢？就使用 alias 即可！你可以在指令列输入 alias 就可以知道目前的命令别名有哪些了！也可以直接下达命令来设定别名呦：

alias lm='ls -al'

  • 工作控制、前景背景控制： (job control, foreground, background)

这部分我们在第十七章 Linux 程序控制中再提及！ 使用前、背景的控制可以让工作进行的更为顺利！至于工作控制(jobs)的用途则更广， 可以让我们随时将工作丢到背景中执行！而不怕不小心使用了 [Ctrl] + c 来停掉该程序！真是好样的！此外，也可以在单一登入的环境中，达到多工的目的呢！

  • 程式化脚本： (shell scripts)

在 DOS 年代还记得将一堆指令写在一起的所谓的‘批次档’吧？在 Linux 底下的 shell scripts 则发挥更为强大的功能，可以将你平时管理系统常需要下达的连续指令写成一个档案， 该档案并且可以透过对谈互动式的方式来进行主机的侦测工作！也可以藉由 shell 提供的环境变数及相关指令来进行设计，哇！整个设计下来几乎就是一个小型的程式语言了！该 scripts 的功能真的是超乎我的想像之外！以前在 DOS 底下需要程式语言才能写的东西，在 Linux 底下使用简单的 shell scripts 就可以帮你达成了！真的厉害！这部分我们在第十三章再来谈！

  • 万用字元： (Wildcard)

除了完整的字串之外， bash 还支援许多的万用字元来帮助使用者查询与指令下达。 举例来说，想要知道 /usr/bin 底下有多少以 X 为开头的档案吗？使用：‘ ls -l /usr/bin/X* ’就能够知道啰～此外，还有其他可供利用的万用字元， 这些都能够加快使用者的操作呢！

小标题的图示 Bash shell 的内建命令： type

我们在第五章提到关于 Linux 的线上说明文件部分，也就是 man page 的内容，那么 bash 有没有什么说明文件啊？开玩笑～ 这么棒的东西怎么可能没有说明文件！请你在 shell 的环境下，直接输入 man bash 瞧一瞧， 嘿嘿！不是盖的吧！让你看个几天几夜也无法看完的 bash 说明文件，可是很详尽的资料啊！ ^_^

不过，在这个 bash 的 man page 当中，不知道你是否有察觉到，咦！ 怎么这个说明文件里面有其他的档案说明啊？举例来说，那个 cd 指令的说明就在这个 man page 内？ 然后我直接输入 man cd 时，怎么出现的画面中，最上方竟然出现一堆指令的介绍？这是怎么回事？ 为了方便 shell 的操作，其实 bash 已经‘内建’了很多指令了，例如上面提到的 cd ， 还有例如 umask 等等的指令，都是内建在 bash 当中的呢！

那我怎么知道这个指令是来自于外部指令(指的是其他非 bash 所提供的指令) 或是内建在 bash 当中的呢？ 嘿嘿！利用 type 这个指令来观察即可！举例来说：

[root@www ~]# type [-tpa] name
选项与参数：
    ：不加任何选项与参数时，type 会显示出 name 是外部指令还是 bash 内建指令
-t  ：当加入 -t 参数时，type 会将 name 以底下这些字眼显示出他的意义：
      file    ：表示为外部指令；
      alias   ：表示该指令为命令别名所设定的名称；
      builtin ：表示该指令为 bash 内建的指令功能；
-p  ：如果后面接的 name 为外部指令时，才会显示完整档名；
-a  ：会由 PATH 变数定义的路径中，将所有含 name 的指令都列出来，包含 alias

范例一：查询一下 ls 这个指令是否为 bash 内建？
[root@www ~]# type ls
ls is aliased to `ls --color=tty' <==未加任何参数，列出 ls 的最主要使用情况

[root@www ~]# type -t ls
alias                             <==仅列出 ls 执行时的依据
[root@www ~]# type -a ls
ls is aliased to `ls --color=tty' <==最先使用 aliase
ls is /bin/ls                     <==还有找到外部指令在 /bin/ls

范例二：那么 cd 呢？

[root@www ~]# type cd
cd is a shell builtin             <==看到了吗？ cd 是 shell 内建指令

透过 type 这个指令我们可以知道每个指令是否为 bash 的内建指令。 此外，由于利用 type 搜寻后面的名称时，如果后面接的名称并不能以执行档的状态被找到， 那么该名称是不会被显示出来的。也就是说， type 主要在找出‘执行档’而不是一般档案档名喔！ 呵呵！所以，这个 type 也可以用来作为类似 which 指令的用途啦！找指令用的！

小标题的图示 指令的下达

我们在第五章的开始下达指令小节已经提到过在 shell 环境下的指令下达方法，如果你忘记了请回到第五章再去回忆一下！这里不重复说明了。 鸟哥这里仅就反斜线 (\) 来说明一下指令下达的方式啰！

范例：如果指令串太长的话，如何使用两行来输出？

[vbird@www ~]# cp /var/spool/mail/root /etc/crontab \
> /etc/fstab /root

上面这个指令用途是将三个档案复制到 /root 这个目录下而已。不过，因为指令太长， 于是鸟哥就利用‘ \[Enter] ’来将 [Enter] 这个按键‘跳脱！’开来，让 [Enter] 按键不再具有‘开始执行’的功能！好让指令可以继续在下一行输入。 需要特别留意， [Enter] 按键是紧接着反斜线 (\) 的，两者中间没有其他字元。 因为 \ 仅跳脱‘紧接着的下一个字符’而已！所以，万一我写成： ‘ \ [Enter] ’，亦即 [Enter] 与反斜线中间有一个空格时，则 \ 跳脱的是‘空白键’而不是 [Enter] 按键！这个地方请再仔细的看一遍！很重要！

如果顺利跳脱 [Enter] 后，下一行最前面就会主动出现 > 的符号， 你可以继续输入指令啰！也就是说，那个 > 是系统自动出现的，你不需要输入。

总之，当我们顺利的在终端机 (tty) 上面登入后， Linux 就会依据 /etc/passwd 档案的设定给我们一个 shell (预设是 bash)，然后我们就可以依据上面的指令下达方式来操作 shell， 之后，我们就可以透过 man 这个线上查询来查询指令的使用方式与参数说明， 很不错吧！那么我们就赶紧更进一步来操作 bash 这个好玩的东西啰！

大标题的图示 Shell 的变数功能

变数是 bash 环境中非常重要的一个玩意儿，我们知道 Linux 是多人多工的环境，每个人登入系统都能取得一个 bash ， 每个人都能够使用 bash 下达 mail 这个指令来收受‘自己’的邮件，问题是， bash 是如何得知你的邮件信箱是哪个档案？ 这就需要‘变数’的帮助啦！所以，你说变数重不重要呢？底下我们将介绍重要的环境变数、变数的取用与设定等资料， 呼呼！动动脑时间又来到啰！^_^

小标题的图示 什么是变数？

那么，什么是‘变数’呢？简单的说，就是让某一个特定字串代表不固定的内容就是了。举个大家在国中都会学到的数学例子， 那就是：‘ y = ax + b ’这东西，在等号左边的(y)就是变数，在等号右边的(ax+b)就是变数内容。 要注意的是，左边是未知数，右边是已知数喔！ 讲的更简单一点，我们可以‘用一个简单的 "字眼" 来取代另一个比较复杂或者是容易变动的资料’。这有什么好处啊？最大的好处就是‘方便！’。

  • 变数的可变性与方便性

举例来说，我们每个帐号的邮件信箱预设是以 MAIL 这个变数来进行存取的， 当 dmtsai 这个使用者登入时，他便会取得 MAIL 这个变数，而这个变数的内容其实就是 /var/spool/mail/dmtsai， 那如果 vbird 登入呢？他取得的 MAIL 这个变数的内容其实就是 /var/spool/mail/vbird 。 而我们使用信件读取指令 mail 来读取自己的邮件信箱时，嘿嘿，这支程式可以直接读取 MAIL 这个变数的内容， 就能够自动的分辨出属于自己的信箱信件啰！这样一来，设计程式的设计师就真的很方便的啦！

程式、变数与不同使用者的关系
图 2.1.1、程式、变数与不同使用者的关系

如上图所示，由于系统已经帮我们规划好 MAIL 这个变数，所以使用者只要知道 mail 这个指令如何使用即可， mail 会主动的取用 MAIL 这个变数，就能够如上图所示的取得自己的邮件信箱了！(注意大小写，小写的 mail 是指令， 大写的 MAIL 则是变数名称喔！)

那么使用变数真的比较好吗？这是当然的！想像一个例子，如果 mail 这个指令将 root 收信的邮件信箱 (mailbox) 档名为 /var/spool/mail/root 直接写入程式码中。那么当 dmtsai 要使用 mail 时，将会取得 /var/spool/mail/root 这个档案的内容！ 不合理吧！所以你就需要帮 dmtsai 也设计一个 mail 的程式，将 /var/spool/mail/dmtsai 写死到 mail 的程式码当中！ 天呐！那系统要有多少个 mail 指令啊？反过来说，使用变数就变的很简单了！因为你不需要更动到程式码啊！ 只要将 MAIL 这个变数带入不同的内容即可让所有使用者透过 mail 取得自己的信件！当然简单多了！

  • 影响 bash 环境操作的变数

某些特定变数会影响到 bash 的环境喔！举例来说，我们前面已经提到过很多次的那个 PATH 变数！ 你能不能在任何目录下执行某个指令，与 PATH 这个变数有很大的关系。例如你下达 ls 这个指令时，系统就是透过 PATH 这个变数里面的内容所记录的路径顺序来搜寻指令的呢！如果在搜寻完 PATH 变数内的路径还找不到 ls 这个指令时， 就会在荧幕上显示‘ command not found ’的错误讯息了。

如果说的学理一点，那么由于在 Linux System 下面，所有的执行续都是需要一个执行码， 而就如同上面提到的，你‘真正以 shell 来跟 Linux 沟通，是在正确的登入 Linux 之后！’这个时候你就有一个 bash 的执行程序，也才可以真正的经由 bash 来跟系统沟通啰！而在进入 shell 之前，也正如同上面提到的，由于系统需要一些变数来提供他资料的存取 (或者是一些环境的设定参数值， 例如是否要显示彩色等等的) ，所以就有一些所谓的‘环境变数’ 需要来读入系统中了！这些环境变数例如 PATH、HOME、MAIL、SHELL 等等，都是很重要的， 为了区别与自订变数的不同，环境变数通常以大写字元来表示呢！

  • 脚本程式设计 (shell script) 的好帮手

这些还都只是系统预设的变数的目的，如果是个人的设定方面的应用呢：例如你要写一个大型的 script 时，有些资料因为可能由于使用者习惯的不同而有差异，比如说路径好了，由于该路径在 script 被使用在相当多的地方，如果下次换了一部主机，都要修改 script 里面的所有路径，那么我一定会疯掉！ 这个时候如果使用变数，而将该变数的定义写在最前面，后面相关的路径名称都以变数来取代， 嘿嘿！那么你只要修改一行就等于修改整篇 script 了！方便的很！所以，良好的程式设计师都会善用变数的定义！

变数应用于 shell script 的示意图
图 2.1.2、变数应用于 shell script 的示意图

最后我们就简单的对‘什么是变数’作个简单定义好了： ‘变数就是以一组文字或符号等，来取代一些设定或者是一串保留的资料！’， 例如：我设定了‘myname’就是‘VBird’，所以当你读取 myname 这个变数的时候，系统自然就会知道！哈！那就是 VBird 啦！ 那么如何‘显示变数’呢？这就需要使用到 echo 这个指令啦！

小标题的图示 变数的取用与设定：echo, 变数设定规则, unset

说的口沫横飞的，也不知道‘变数’与‘变数代表的内容’有啥关系？ 那我们就将‘变数’的‘内容’拿出来给您瞧瞧好了。你可以利用 echo 这个指令来取用变数， 但是，变数在被取用时，前面必须要加上钱字号‘ $ ’才行，举例来说，要知道 PATH 的内容，该如何是好？

  • 变数的取用: echo
[root@www ~]# echo $variable
[root@www ~]# echo $PATH
/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin
[root@www ~]# echo ${PATH}

变数的取用就如同上面的范例，利用 ehco 就能够读出，只是需要在变数名称前面加上 $ ， 或者是以 ${变数} 的方式来取用都可以！当然啦，那个 echo 的功能可是很多的， 我们这里单纯是拿 echo 来读出变数的内容而已，更多的 echo 使用，请自行给他 man echo 吧！ ^_^

例题：
请在荧幕上面显示出您的环境变数 HOME 与 MAIL：
答：
echo $HOME 或者是 echo ${HOME}
echo $MAIL 或者是 echo ${MAIL}

现在我们知道了变数与变数内容之间的相关性了，好了，那么我要如何‘设定’或者是‘修改’ 某个变数的内容啊？很简单啦！用‘等号(=)’连接变数与他的内容就好啦！举例来说： 我要将 myname 这个变数名称的内容设定为 VBird ，那么：

[root@www ~]# echo $myname
       <==这里并没有任何资料～因为这个变数尚未被设定！是空的！
[root@www ~]# myname=VBird
[root@www ~]# echo $myname
VBird  <==出现了！因为这个变数已经被设定了！

瞧！如此一来，这个变数名称 myname 的内容就带有 VBird 这个资料啰～ 而由上面的例子当中，我们也可以知道： 在 bash 当中，当一个变数名称尚未被设定时，预设的内容是‘空’的。 另外，变数在设定时，还是需要符合某些规定的，否则会设定失败喔！ 这些规则如下所示啊！

  • 变数的设定规则
  1. 变数与变数内容以一个等号‘=’来连结，如下所示：
    ‘myname=VBird’

  2. 等号两边不能直接接空白字元，如下所示为错误：
    ‘myname = VBird’或‘myname=VBird Tsai’

  3. 变数名称只能是英文字母与数字，但是开头字元不能是数字，如下为错误：
    ‘2myname=VBird’

  4. 变数内容若有空白字元可使用双引号‘"’或单引号‘'’将变数内容结合起来，但
    • 双引号内的特殊字元如 $ 等，可以保有原本的特性，如下所示：
      ‘var="lang is $LANG"’则‘echo $var’可得‘lang is en_US’
    • 单引号内的特殊字元则仅为一般字元 (纯文字)，如下所示：
      ‘var='lang is $LANG'’则‘echo $var’可得‘lang is $LANG’

  5. 可用跳脱字元‘ \ ’将特殊符号(如 [Enter], $, \, 空白字元, '等)变成一般字元；

  6. 在一串指令中，还需要藉由其他的指令提供的资讯，可以使用反单引号‘`指令`’或 ‘$(指令)’。特别注意，那个 ` 是键盘上方的数字键 1 左边那个按键，而不是单引号！ 例如想要取得核心版本的设定：
    ‘version=$(uname -r)’再‘echo $version’可得‘2.6.18-128.el5’

  7. 若该变数为扩增变数内容时，则可用 "$变数名称" 或 ${变数} 累加内容，如下所示：
    ‘PATH="$PATH":/home/bin’

  8. 若该变数需要在其他子程序执行，则需要以 export 来使变数变成环境变数：
    ‘export PATH’

  9. 通常大写字元为系统预设变数，自行设定变数可以使用小写字元，方便判断 (纯粹依照使用者兴趣与嗜好) ；

  10. 取消变数的方法为使用 unset ：‘unset 变数名称’例如取消 myname 的设定：
    ‘unset myname’

底下让鸟哥举几个例子来让你试看看，就知道怎么设定好你的变数啰！

范例一：设定一变数 name ，且内容为 VBird
[root@www ~]# 12name=VBird
-bash: 12name=VBird: command not found  <==荧幕会显示错误！因为不能以数字开头！
[root@www ~]# name = VBird            <==还是错误！因为有空白！

[root@www ~]# name=VBird              <==OK 的啦！

范例二：承上题，若变数内容为 VBird's name 呢，就是变数内容含有特殊符号时：
[root@www ~]# name=VBird's name
# 单引号与双引号必须要成对，在上面的设定中仅有一个单引号，因此当你按下 enter 后，
# 你还可以继续输入变数内容。这与我们所需要的功能不同，失败啦！
# 记得，失败后要复原请按下 [ctrl]-c 结束！
[root@www ~]# name="VBird's name"    <==OK 的啦！

# 指令是由左边向右找→，先遇到的引号先有用，因此如上所示，单引号会失效！
[root@www ~]# name='VBird's name'    <==失败的啦！
# 因为前两个单引号已成对，后面就多了一个不成对的单引号了！因此也就失败了！
[root@www ~]# name=VBird\'s\ name     <==OK 的啦！
# 利用反斜线 (\) 跳脱特殊字元，例如单引号与空白键，这也是 OK 的啦！

范例三：我要在 PATH 这个变数当中‘累加’:/home/dmtsai/bin 这个目录
[root@www ~]# PATH=$PATH:/home/dmtsai/bin
[root@www ~]# PATH="$PATH":/home/dmtsai/bin
[root@www ~]# PATH=${PATH}:/home/dmtsai/bin
# 上面这三种格式在 PATH 里头的设定都是 OK 的！但是底下的例子就不见得啰！

范例四：呈范例三，我要将 name 的内容多出 "yes" 呢？
[root@www ~]# name=$nameyes

# 知道了吧？如果没有双引号，那么变数成了啥？name 的内容是 $nameyes 这个变数！
# 呵呵！我们可没有设定过 nameyes 这个变数呐！所以，应该是底下这样才对！
[root@www ~]# name="$name"yes
[root@www ~]# name=${name}yes  <==以此例较佳！

范例五：如何让我刚刚设定的 name=VBird 可以用在下个 shell 的程序？
[root@www ~]# name=VBird
[root@www ~]# bash        <==进入到所谓的子程序

[root@www ~]# echo $name  <==子程序：再次的 echo 一下；
       <==嘿嘿！并没有刚刚设定的内容喔！
[root@www ~]# exit        <==子程序：离开这个子程序
[root@www ~]# export name
[root@www ~]# bash        <==进入到所谓的子程序

[root@www ~]# echo $name  <==子程序：在此执行！
VBird  <==看吧！出现设定值了！
[root@www ~]# exit        <==子程序：离开这个子程序

什么是‘子程序’呢？就是说，在我目前这个 shell 的情况下，去启用另一个新的 shell ，新的那个 shell 就是子程序啦！在一般的状态下，父程序的自订变数是无法在子程序内使用的。但是透过 export 将变数变成环境变数后，就能够在子程序底下应用了！很不赖吧！至于程序的相关概念， 我们会在第十七章程序管理当中提到的喔！

范例六：如何进入到您目前核心的模组目录？
[root@www ~]# cd /lib/modules/`uname -r`/kernel
[root@www ~]# cd /lib/modules/$(uname -r)/kernel

每个 Linux 都能够拥有多个核心版本，且几乎 distribution 的核心版本都不相同。以 CentOS 5.3 (未更新前) 为例，他的预设核心版本是 2.6.18-128.el5 ，所以核心模组目录在 /lib/modules/2.6.18-128.el5/kernel/ 内。 也由于每个 distributions 的这个值都不相同，但是我们却可以利用 uname -r 这个指令先取得版本资讯。所以啰，就可以透过上面指令当中的内含指令 `uname -r` 先取得版本输出到 cd ... 那个指令当中，就能够顺利的进入目前核心的驱动程式所放置的目录啰！很方便吧！

其实上面的指令可以说是作了两次动作，亦即是：

  1. 先进行反单引号内的动作‘uname -r’并得到核心版本为 2.6.18-128.el5
  2. 将上述的结果带入原指令，故得指令为：‘cd /lib/modules/2.6.18-128.el5/kernel/’
范例七：取消刚刚设定的 name 这个变数内容
[root@www ~]# unset name

根据上面的案例你可以试试看！就可以了解变数的设定啰！这个是很重要的呦！请勤加练习！ 其中，较为重要的一些特殊符号的使用啰！例如单引号、双引号、跳脱字元、钱字号、反单引号等等，底下的例题想一想吧！

例题：
在变数的设定当中，单引号与双引号的用途有何不同？
答：
单引号与双引号的最大不同在于双引号仍然可以保有变数的内容，但单引号内仅能是一般字元 ，而不会有特殊符号。我们以底下的例子做说明：假设您定义了一个变数， name=VBird ，现在想以 name 这个变数的内容定义出 myname 显示 VBird its me 这个内容，要如何订定呢？
[root@www ~]# name=VBird
[root@www ~]# echo $name
VBird
[root@www ~]# myname="$name its me"
[root@www ~]# echo $myname
VBird its me
[root@www ~]# myname='$name its me'
[root@www ~]# echo $myname
$name its me
发现了吗？没错！使用了单引号的时候，那么 $name 将失去原有的变数内容，仅为一般字元的显示型态而已！这里必需要特别小心在意！

例题：
在指令下达的过程中，反单引号( ` )这个符号代表的意义为何？
答：
在一串指令中，在 ` 之内的指令将会被先执行，而其执行出来的结果将做为外部的输入资讯！例如 uname -r 会显示出目前的核心版本，而我们的核心版本在 /lib/modules 里面，因此，你可以先执行 uname -r 找出核心版本，然后再以‘ cd 目录’到该目录下，当然也可以执行如同上面范例六的执行内容啰。

另外再举个例子，我们也知道， locate 指令可以列出所有的相关档案档名，但是，如果我想要知道各个档案的权限呢？举例来说，我想要知道每个 crontab 相关档名的权限：
[root@www ~]# ls -l `locate crontab`
如此一来，先以 locate 将档名资料都列出来，再以 ls 指令来处理的意思啦！了了吗？ ^_^

例题：
若你有一个常去的工作目录名称为：‘/cluster/server/work/taiwan_2005/003/’，如何进行该目录的简化？
答：
在一般的情况下，如果你想要进入上述的目录得要‘cd /cluster/server/work/taiwan_2005/003/’， 以鸟哥自己的案例来说，鸟哥跑数值模式常常会设定很长的目录名称(避免忘记)，但如此一来变换目录就很麻烦。 此时，鸟哥习惯利用底下的方式来降低指令下达错误的问题：
[root@www ~]# work="/cluster/server/work/taiwan_2005/003/
[root@www ~]# cd $work
未来我想要使用其他目录作为我的模式工作目录时，只要变更 work 这个变数即可！而这个变数又可以在 bash 的设定档中直接指定，那我每次登入只要执行‘ cd $work ’就能够去到数值模式模拟的工作目录了！是否很方便呢？ ^_^

Tips:
老实说，使用‘ version=$(uname -r) ’来取代‘ version=`uname -r` ’比较好，因为反单引号大家老是容易打错或看错！ 所以现在鸟哥都习惯使用 $( 指令 ) 来介绍这个功能！ 		鸟哥的图示
小标题的图示 环境变数的功能

环境变数可以帮我们达到很多功能～包括家目录的变换啊、提示字元的显示啊、执行档搜寻的路径啊等等的， 还有很多很多啦！那么，既然环境变数有那么多的功能，问一下，目前我的 shell 环境中， 有多少预设的环境变数啊？我们可以利用两个指令来查阅，分别是 env 与 export 呢！

  • 用 env 观察环境变数与常见环境变数说明

范例一：列出目前的 shell 环境下的所有环境变数与其内容。
[root@www ~]# env
HOSTNAME=www.vbird.tsai    <== 这部主机的主机名称
TERM=xterm                 <== 这个终端机使用的环境是什么类型
SHELL=/bin/bash            <== 目前这个环境下，使用的 Shell 是哪一个程式？
HISTSIZE=1000              <== ‘记录指令的笔数’在 CentOS 预设可记录 1000 笔

USER=root                  <== 使用者的名称啊！
LS_COLORS=no=00:fi=00:di=00;34:ln=00;36:pi=40;33:so=00;35:bd=40;33;01:cd=40;33;01:
or=01;05;37;41:mi=01;05;37;41:ex=00;32:*.cmd=00;32:*.exe=00;32:*.com=00;32:*.btm=0
0;32:*.bat=00;32:*.sh=00;32:*.csh=00;32:*.tar=00;31:*.tgz=00;31:*.arj=00;31:*.taz=
00;31:*.lzh=00;31:*.zip=00;31:*.z=00;31:*.Z=00;31:*.gz=00;31:*.bz2=00;31:*.bz=00;3
1:*.tz=00;31:*.rpm=00;31:*.cpio=00;31:*.jpg=00;35:*.gif=00;35:*.bmp=00;35:*.xbm=00
;35:*.xpm=00;35:*.png=00;35:*.tif=00;35: <== 一些颜色显示
MAIL=/var/spool/mail/root  <== 这个使用者所取用的 mailbox 位置
PATH=/sbin:/usr/sbin:/bin:/usr/bin:/usr/X11R6/bin:/usr/local/bin:/usr/local/sbin:
/root/bin                  <== 不再多讲啊！是执行档指令搜寻路径
INPUTRC=/etc/inputrc       <== 与键盘按键功能有关。可以设定特殊按键！
PWD=/root                  <== 目前使用者所在的工作目录 (利用 pwd 取出！)

LANG=en_US                 <== 这个与语系有关，底下会再介绍！
HOME=/root                 <== 这个使用者的家目录啊！
_=/bin/env                 <== 上一次使用的指令的最后一个参数(或指令本身)

env 是 environment (环境) 的简写啊，上面的例子当中，是列出来所有的环境变数。当然，如果使用 export 也会是一样的内容～ 只不过， export 还有其他额外的功能就是了，我们等一下再提这个 export 指令。 那么上面这些变数有些什么功用呢？底下我们就一个一个来分析分析！

  • HOME
    代表使用者的家目录。还记得我们可以使用 cd ~ 去到自己的家目录吗？或者利用 cd 就可以直接回到使用者家目录了。那就是取用这个变数啦～ 有很多程式都可能会取用到这个变数的值！

  • SHELL
    告知我们，目前这个环境使用的 SHELL 是哪支程式？ Linux 预设使用 /bin/bash 的啦！

  • HISTSIZE
    这个与‘历史命令’有关，亦即是， 我们曾经下达过的指令可以被系统记录下来，而记录的‘笔数’则是由这个值来设定的。

  • MAIL
    当我们使用 mail 这个指令在收信时，系统会去读取的邮件信箱档案 (mailbox)。

  • PATH
    就是执行档搜寻的路径啦～目录与目录中间以冒号(:)分隔， 由于档案的搜寻是依序由 PATH 的变数内的目录来查询，所以，目录的顺序也是重要的喔。

  • LANG
    这个重要！就是语系资料啰～很多讯息都会用到他， 举例来说，当我们在启动某些 perl 的程式语言档案时，他会主动的去分析语系资料档案， 如果发现有他无法解析的编码语系，可能会产生错误喔！一般来说，我们中文编码通常是 zh_TW.Big5 或者是 zh_TW.UTF-8，这两个编码偏偏不容易被解译出来，所以，有的时候，可能需要修订一下语系资料。 这部分我们会在下个小节做介绍的！

  • RANDOM
    这个玩意儿就是‘随机乱数’的变数啦！目前大多数的 distributions 都会有乱数产生器，那就是 /dev/random 这个档案。 我们可以透过这个乱数档案相关的变数 ($RANDOM) 来随机取得乱数值喔。在 BASH 的环境下，这个 RANDOM 变数的内容，介于 0~32767 之间，所以，你只要 echo $RANDOM 时，系统就会主动的随机取出一个介于 0~32767 的数值。万一我想要使用 0~9 之间的数值呢？呵呵～利用 declare 宣告数值类型， 然后这样做就可以了：
    [root@www ~]# declare -i number=$RANDOM*10/32768 ; echo $number

8   <== 此时会随机取出 0~9 之间的数值喔！

大致上是有这些环境变数啦～里面有些比较重要的参数，在底下我们都会另外进行一些说明的～

  • 用 set 观察所有变数 (含环境变数与自订变数)

bash 可不只有环境变数喔，还有一些与 bash 操作介面有关的变数，以及使用者自己定义的变数存在的。 那么这些变数如何观察呢？这个时候就得要使用 set 这个指令了。 set 除了环境变数之外， 还会将其他在 bash 内的变数通通显示出来哩！资讯很多，底下鸟哥仅列出几个重要的内容：

[root@www ~]# set
BASH=/bin/bash           <== bash 的主程式放置路径
BASH_VERSINFO=([0]="3" [1]="2" [2]="25" [3]="1" [4]="release"
[5]="i686-redhat-linux-gnu")      <== bash 的版本啊！
BASH_VERSION='3.2.25(1)-release'  <== 也是 bash 的版本啊！

COLORS=/etc/DIR_COLORS.xterm      <== 使用的颜色纪录档案
COLUMNS=115              <== 在目前的终端机环境下，使用的栏位有几个字元长度
HISTFILE=/root/.bash_history      <== 历史命令记录的放置档案，隐藏档
HISTFILESIZE=1000        <== 存起来(与上个变数有关)的档案之指令的最大纪录笔数。
HISTSIZE=1000            <== 目前环境下，可记录的历史命令最大笔数。
HOSTTYPE=i686            <== 主机安装的软体主要类型。我们用的是 i686 相容机器软体

IFS=$' \t\n'             <== 预设的分隔符号
LINES=35                 <== 目前的终端机下的最大行数
MACHTYPE=i686-redhat-linux-gnu    <== 安装的机器类型
MAILCHECK=60             <== 与邮件有关。每 60 秒去扫瞄一次信箱有无新信！
OLDPWD=/home             <== 上个工作目录。我们可以用 cd - 来取用这个变数。
OSTYPE=linux-gnu         <== 作业系统的类型！

PPID=20025               <== 父程序的 PID (会在后续章节才介绍)
PS1='[\u@\h \W]\$ '      <== PS1 就厉害了。这个是命令提示字元，也就是我们常见的
                             [root@www ~]# 或 [dmtsai ~]$ 的设定值啦！可以更动的！
PS2='> '                 <== 如果你使用跳脱符号 (\) 第二行以后的提示字元也
name=VBird               <== 刚刚设定的自订变数也可以被列出来喔！
$                        <== 目前这个 shell 所使用的 PID

?                        <== 刚刚执行完指令的回传值。

一般来说，不论是否为环境变数，只要跟我们目前这个 shell 的操作介面有关的变数， 通常都会被设定为大写字元，也就是说，‘基本上，在 Linux 预设的情况中，使用{大写的字母}来设定的变数一般为系统内定需要的变数’。 OK！OK！那么上头那些变数当中，有哪些是比较重要的？大概有这几个吧！

  • PS1：(提示字元的设定)

    这是 PS1 (数字的 1 不是英文字母)，这个东西就是我们的‘命令提示字元’喔！ 当我们每次按下 [Enter] 按键去执行某个指令后，最后要再次出现提示字元时， 就会主动去读取这个变数值了。上头 PS1 内显示的是一些特殊符号，这些特殊符号可以显示不同的资讯， 每个 distributions 的 bash 预设的 PS1 变数内容可能有些许的差异，不要紧，‘习惯你自己的习惯’就好了。 你可以用 man bash (注3)去查询一下 PS1 的相关说明，以理解底下的一些符号意义。

    • \d ：可显示出‘星期 月 日’的日期格式，如："Mon Feb 2"
    • \H ：完整的主机名称。举例来说，鸟哥的练习机为‘www.vbird.tsai’
    • \h ：仅取主机名称在第一个小数点之前的名字，如鸟哥主机则为‘www’后面省略
    • \t ：显示时间，为 24 小时格式的‘HH:MM:SS’
    • \T ：显示时间，为 12 小时格式的‘HH:MM:SS’
    • \A ：显示时间，为 24 小时格式的‘HH:MM’
    • \@ ：显示时间，为 12 小时格式的‘am/pm’样式
    • \u ：目前使用者的帐号名称，如‘root’；
    • \v ：BASH 的版本资讯，如鸟哥的测试主机板本为 3.2.25(1)，仅取‘3.2’显示
    • \w ：完整的工作目录名称，由根目录写起的目录名称。但家目录会以 ~ 取代；
    • \W ：利用 basename 函数取得工作目录名称，所以仅会列出最后一个目录名。
    • \# ：下达的第几个指令。
    • \$ ：提示字元，如果是 root 时，提示字元为 # ，否则就是 $ 啰～

    好了，让我们来看看 CentOS 预设的 PS1 内容吧：‘[\u@\h \W]\$ ’，现在你知道那些反斜线后的资料意义了吧？ 要注意喔！那个反斜线后的资料为 PS1 的特殊功能，与 bash 的变数设定没关系啦！不要搞混了喔！ 那你现在知道为何你的命令提示字元是：‘ [root@www ~]# ’了吧？ 好了，那么假设我想要有类似底下的提示字元：
    [root@www /home/dmtsai 16:50 #12]#
    那个 # 代表第 12 次下达的指令。那么应该如何设定 PS1 呢？可以这样啊：
    [root@www ~ ]# cd /home
[root@www home]# PS1='[\u@\h \w \A #\#]\$ '
[root@www /home 17:02 #85]#
# 看到了吗？提示字元变了！变的很有趣吧！其中，那个 #85 比较有趣，
# 如果您再随便输入几次 ls 后，该数字就会增加喔！为啥？上面有说明滴！

  • $：(关于本 shell 的 PID)

    钱字号本身也是个变数喔！这个咚咚代表的是‘目前这个 Shell 的执行绪代号’，亦即是所谓的 PID (Process ID)。 更多的程序观念，我们会在第四篇的时候提及。想要知道我们的 shell 的 PID ，就可以用：‘ echo $$ ’即可！出现的数字就是你的 PID 号码。

  • ?：(关于上个执行指令的回传值)

    虾密？问号也是一个特殊的变数？没错！在 bash 里面这个变数可重要的很！ 这个变数是：‘上一个执行的指令所回传的值’， 上面这句话的重点是‘上一个指令’与‘回传值’两个地方。当我们执行某些指令时， 这些指令都会回传一个执行后的代码。一般来说，如果成功的执行该指令， 则会回传一个 0 值，如果执行过程发生错误，就会回传‘错误代码’才对！一般就是以非为 0 的数值来取代。 我们以底下的例子来看看：
    [root@www ~]# echo $SHELL
/bin/bash                                  <==可顺利显示！没有错误！
[root@www ~]# echo $?
0                                          <==因为没问题，所以回传值为 0
[root@www ~]# 12name=VBird

-bash: 12name=VBird: command not found     <==发生错误了！bash回报有问题
[root@www ~]# echo $?
127                                        <==因为有问题，回传错误代码(非为0)
# 错误代码回传值依据软体而有不同，我们可以利用这个代码来搜寻错误的原因喔！
[root@www ~]# echo $?
0
# 咦！怎么又变成正确了？这是因为 "?" 只与‘上一个执行指令’有关，
# 所以，我们上一个指令是执行‘ echo $? ’，当然没有错误，所以是 0 没错！

  • OSTYPE, HOSTTYPE, MACHTYPE：(主机硬体与核心的等级)

    我们在第零章、计算机概论内的 CPU 等级说明中谈过 CPU ， 目前个人电脑的 CPU 主要分为 32/64 位元，其中 32 位元又可分为 i386, i586, i686，而 64 位元则称为 x86_64。 由于不同等级的 CPU 指令集不太相同，因此你的软体可能会针对某些 CPU 进行最佳化，以求取较佳的软体性能。 所以软体就有 i386, i686 及 x86_64 之分。以目前 (2009) 的主流硬体来说，几乎都是 x86_64 的天下！ 但是毕竟旧机器还是非常多，以鸟哥的环境来说，我用 P-III 等级的电脑，所以上头就发现我的等级是 i686 啦！

    要留意的是，较高阶的硬体通常会向下相容旧有的软体，但较高阶的软体可能无法在旧机器上面安装！ 我们在第三章就曾说明过， 这里再强调一次，你可以在 x86_64 的硬体上安装 i386 的 Linux 作业系统，但是你无法在 i686 的硬体上安装 x86_64 的 Linux 作业系统！这点得要牢记在心！

  • export： 自订变数转成环境变数

谈了 env 与 set 现在知道有所谓的环境变数与自订变数，那么这两者之间有啥差异呢？其实这两者的差异在于‘ 该变数是否会被子程序所继续引用’啦！唔！那么啥是父程序？子程序？ 这就得要了解一下指令的下达行为了。

当你登入 Linux 并取得一个 bash 之后，你的 bash 就是一个独立的程序，被称为 PID 的就是。 接下来你在这个 bash 底下所下达的任何指令都是由这个 bash 所衍生出来的，那些被下达的指令就被称为子程序了。 我们可以用底下的图示来简单的说明一下父程序与子程序的概念：

程序相关性示意图
图 2.3.1、程序相关性示意图

如上所示，我们在原本的 bash 底下执行另一个 bash ，结果操作的环境介面会跑到第二个 bash 去(就是子程序)， 那原本的 bash 就会在暂停的情况 (睡着了，就是 sleep)。整个指令运作的环境是实线的部分！若要回到原本的 bash 去， 就只有将第二个 bash 结束掉 (下达 exit 或 logout) 才行。更多的程序概念我们会在第四篇谈及，这里只要有这个概念即可。

这个程序概念与变数有啥关系啊？关系可大了！因为子程序仅会继承父程序的环境变数， 子程序不会继承父程序的自订变数啦！所以你在原本 bash 的自订变数在进入了子程序后就会消失不见， 一直到你离开子程序并回到原本的父程序后，这个变数才会又出现！

换个角度来想，也就是说，如果我能将自订变数变成环境变数的话，那不就可以让该变数值继续存在于子程序了？ 呵呵！没错！此时，那个 export 指令就很有用啦！如你想要让该变数内容继续的在子程序中使用，那么就请执行：

[root@www ~]# export 变数名称

这东西用在‘分享自己的变数设定给后来呼叫的档案或其他程序’啦！ 像鸟哥常常在自己的主档案后面呼叫其他附属档案(类似函式的功能)，但是主档案与附属档案内都有相同的变数名称， 若一再重复设定时，要修改也很麻烦，此时只要在原本的第一个档案内设定好‘ export 变数 ’， 后面所呼叫的档案就能够使用这个变数设定了！而不需要重复设定，这非常实用于 shell script 当中喔！ 如果仅下达 export 而没有接变数时，那么此时将会把所有的‘环境变数’秀出来喔！例如：

[root@www ~]# export

declare -x HISTSIZE="1000"
declare -x HOME="/root"
declare -x HOSTNAME="www.vbird.tsai"
declare -x INPUTRC="/etc/inputrc"
declare -x LANG="en_US"
declare -x LOGNAME="root"
# 后面的鸟哥就都直接省略了！不然....浪费版面～ ^_^

那如何将环境变数转成自订变数呢？可以使用本章后续介绍的 declare 呢！

小标题的图示 影响显示结果的语系变数 (locale)

还记得我们在第五章里面提到的语系问题吗？ 就是当我们使用 man command 的方式去查询某个资料的说明档时，该说明档的内容可能会因为我们使用的语系不同而产生乱码。 另外，利用 ls 查询档案的时间时，也可能会有乱码出现在时间的部分。那个问题其实就是语系的问题啦。

目前大多数的 Linux distributions 已经都是支援日渐流行的万国码了，也都支援大部分的国家语系。 这有赖于 i18n (注4) 支援的帮助呢！ 那么我们的 Linux 到底支援了多少的语系呢？这可以由 locale 这个指令来查询到喔！

[root@www ~]# locale -a
....(前面省略)....
zh_TW
zh_TW.big5     <==大五码的中文编码
zh_TW.euctw
zh_TW.utf8     <==万国码的中文编码
zu_ZA
zu_ZA.iso88591
zu_ZA.utf8

正体中文语系至少支援了两种以上的编码，一种是目前还是很常见的 big5 ，另一种则是越来越热门的 utf-8 编码。 那么我们如何修订这些编码呢？其实可以透过底下这些变数的说：

[root@www ~]# locale  <==后面不加任何选项与参数即可！
LANG=en_US                   <==主语言的环境
LC_CTYPE="en_US"             <==字元(文字)辨识的编码
LC_NUMERIC="en_US"           <==数字系统的显示讯息
LC_TIME="en_US"              <==时间系统的显示资料

LC_COLLATE="en_US"           <==字串的比较与排序等
LC_MONETARY="en_US"          <==币值格式的显示等
LC_MESSAGES="en_US"          <==讯息显示的内容，如功能表、错误讯息等
LC_ALL=                      <==整体语系的环境
....(后面省略)....

基本上，你可以逐一设定每个与语系有关的变数资料，但事实上，如果其他的语系变数都未设定， 且你有设定 LANG 或者是 LC_ALL 时，则其他的语系变数就会被这两个变数所取代！ 这也是为什么我们在 Linux 当中，通常说明仅设定 LANG 这个变数而已，因为他是最主要的设定变数！ 好了，那么你应该要觉得奇怪的是，为什么在 Linux 主机的终端机介面 (tty1 ~ tty6) 的环境下，如果设定‘ LANG=zh_TW.big5 ’这个设定值生效后，使用 man 或者其他讯息输出时， 都会有一堆乱码，尤其是使用 ls -l 这个参数时？

因为在 Linux 主机的终端机介面环境下是无法显示像中文这么复杂的编码文字， 所以就会产生乱码了。也就是如此，我们才会必须要在 tty1 ~ tty6 的环境下， 加装一些中文化介面的软体，才能够看到中文啊！不过，如果你是在 MS Windows 主机以远端连线伺服器的软体连线到主机的话，那么，嘿嘿！其实文字介面确实是可以看到中文的。 此时反而你得要在 LANG 设定中文编码才好呢！

Tips:
无论如何，如果发生一些乱码的问题，那么设定系统里面保有的语系编码， 例如： en_US 或 en_US.utf8 等等的设定，应该就 OK 的啦！好了，那么系统预设支援多少种语系呢？ 当我们使用 locale 时，系统是列出目前 Linux 主机内保有的语系档案， 这些语系档案都放置在： /usr/lib/locale/ 这个目录中。 		鸟哥的图示

你当然可以让每个使用者自己去调整自己喜好的语系，但是整体系统预设的语系定义在哪里呢？ 其实就是在 /etc/sysconfig/i18n 啰！这个档案在 CentOS 5.x 的内容有点像这样：

[root@www ~]# cat /etc/sysconfig/i18n
LANG="zh_TW.UTF-8"

因为鸟哥在第四章的安装时选择的是中文语系安装画面， 所以这个档案预设就会使用中文编码啦！你也可以自行将他改成你想要的语系编码即可。

Tips:
假设你有一个纯文字档案原本是在 Windows 底下建立的，那么这个档案预设应该是 big5 的编码格式。 在你将这个档案上传到 Linux 主机后，在 X window 底下打开时，咦！怎么中文字通通变成乱码了？ 别担心！因为如上所示， i18n 预设是万国码系统嘛！你只要将开启该档案的软体编码由 utf8 改成 big5 就能够看到正确的中文了！ 		鸟哥的图示
小标题的图示 变数的有效范围

虾密？变数也有使用的‘范围’？没错啊～我们在上头的 export 指令说明中，就提到了这个概念了。如果在跑程式的时候，有父程序与子程序的不同程序关系时， 则‘变数’可否被引用与 export 有关。被 export 后的变数，我们可以称他为‘环境变数’！ 环境变数可以被子程序所引用，但是其他的自订变数内容就不会存在于子程序中。

Tips:
在某些不同的书籍会谈到‘全域变数, global variable’与‘区域变数, local variable’。 基本上你可以这样看待：
环境变数=全域变数
自订变数=区域变数 		鸟哥的图示

在学理方面，为什么环境变数的资料可以被子程序所引用呢？这是因为记忆体配置的关系！理论上是这样的：

  • 当启动一个 shell，作业系统会分配一记忆区块给 shell 使用，此记忆体内之变数可让子程序取用
  • 若在父程序利用 export 功能，可以让自订变数的内容写到上述的记忆区块当中(环境变数)；
  • 当载入另一个 shell 时 (亦即启动子程序，而离开原本的父程序了)，子 shell 可以将父 shell 的环境变数所在的记忆区块导入自己的环境变数区块当中。

透过这样的关系，我们就可以让某些变数在相关的程序之间存在，以帮助自己更方便的操作环境喔！ 不过要提醒的是，这个‘环境变数’与‘bash 的操作环境’意思不太一样，举例来说， PS1 并不是环境变数， 但是这个 PS1 会影响到 bash 的介面 (提示字元嘛)！相关性要厘清喔！^_^

小标题的图示 变数键盘读取、阵列与宣告： read, array, declare

我们上面提到的变数设定功能，都是由指令列直接设定的，那么，可不可以让使用者能够经由键盘输入？ 什么意思呢？是否记得某些程式执行的过程当中，会等待使用者输入 "yes/no" 之类的讯息啊？ 在 bash 里面也有相对应的功能喔！此外，我们还可以宣告这个变数的属性， 例如：阵列或者是数字等等的。底下就来看看吧！

  • read

要读取来自键盘输入的变数，就是用 read 这个指令了。这个指令最常被用在 shell script 的撰写当中， 想要跟使用者对谈？用这个指令就对了。关于 script 的写法，我们会在第十三章介绍，底下先来瞧一瞧 read 的相关语法吧！

[root@www ~]# read [-pt] variable
选项与参数：
-p  ：后面可以接提示字元！
-t  ：后面可以接等待的‘秒数！’这个比较有趣～不会一直等待使用者啦！

范例一：让使用者由键盘输入一内容，将该内容变成名为 atest 的变数
[root@www ~]# read atest
This is a test        <==此时游标会等待你输入！请输入左侧文字看看

[root@www ~]# echo $atest
This is a test          <==你刚刚输入的资料已经变成一个变数内容！

范例二：提示使用者 30 秒内输入自己的大名，将该输入字串作为名为 named 的变数内容
[root@www ~]# read -p "Please keyin your name: " -t 30 named
Please keyin your name: VBird Tsai   <==注意看，会有提示字元喔！

[root@www ~]# echo $named
VBird Tsai        <==输入的资料又变成一个变数的内容了！

read 之后不加任何参数，直接加上变数名称，那么底下就会主动出现一个空白行等待你的输入(如范例一)。 如果加上 -t 后面接秒数，例如上面的范例二，那么 30 秒之内没有任何动作时， 该指令就会自动略过了～如果是加上 -p ，嘿嘿！在输入的游标前就会有比较多可以用的提示字元给我们参考！ 在指令的下达里面，比较美观啦！ ^_^

  • declare / typeset

declare 或 typeset 是一样的功能，就是在‘宣告变数的类型’。如果使用 declare 后面并没有接任何参数，那么 bash 就会主动的将所有的变数名称与内容通通叫出来，就好像使用 set 一样啦！ 那么 declare 还有什么语法呢？看看先：

[root@www ~]# declare [-aixr] variable
选项与参数：
-a  ：将后面名为 variable 的变数定义成为阵列 (array) 类型
-i  ：将后面名为 variable 的变数定义成为整数数字 (integer) 类型
-x  ：用法与 export 一样，就是将后面的 variable 变成环境变数；
-r  ：将变数设定成为 readonly 类型，该变数不可被更改内容，也不能 unset

范例一：让变数 sum 进行 100+300+50 的加总结果
[root@www ~]# sum=100+300+50
[root@www ~]# echo $sum
100+300+50  <==咦！怎么没有帮我计算加总？因为这是文字型态的变数属性啊！

[root@www ~]# declare -i sum=100+300+50
[root@www ~]# echo $sum
450         <==了乎？？

由于在预设的情况底下， bash 对于变数有几个基本的定义：

  • 变数类型预设为‘字串’，所以若不指定变数类型，则 1+2 为一个‘字串’而不是‘计算式’。 所以上述第一个执行的结果才会出现那个情况的；
  • bash 环境中的数值运算，预设最多仅能到达整数形态，所以 1/3 结果是 0；

现在你晓得为啥你需要进行变数宣告了吧？如果需要非字串类型的变数，那就得要进行变数的宣告才行啦！ 底下继续来玩些其他的 declare 功能。

范例二：将 sum 变成环境变数
[root@www ~]# declare -x sum
[root@www ~]# export | grep sum

declare -ix sum="450"  <==果然出现了！包括有 i 与 x 的宣告！

范例三：让 sum 变成唯读属性，不可更动！
[root@www ~]# declare -r sum
[root@www ~]# sum=tesgting
-bash: sum: readonly variable  <==老天爷～不能改这个变数了！

范例四：让 sum 变成非环境变数的自订变数吧！

[root@www ~]# declare +x sum  <== 将 - 变成 + 可以进行‘取消’动作
[root@www ~]# declare -p sum  <== -p 可以单独列出变数的类型
declare -ir sum="450" <== 看吧！只剩下 i, r 的类型，不具有 x 啰！

declare 也是个很有用的功能～尤其是当我们需要使用到底下的阵列功能时， 他也可以帮我们宣告阵列的属性喔！不过，老话一句，阵列也是在 shell script 比较常用的啦！ 比较有趣的是，如果你不小心将变数设定为‘唯读’，通常得要登出再登入才能复原该变数的类型了！ @_@

  • 阵列 (array) 变数类型

某些时候，我们必须使用阵列来宣告一些变数，这有什么好处啊？在一般人的使用上， 果然是看不出来有什么好处的！不过，如果您曾经写过程式的话，那才会比较了解阵列的意义～ 阵列对写数值程式的设计师来说，可是不能错过学习的重点之一哩！好！不啰唆～ 那么要如何设定阵列的变数与内容呢？在 bash 里头，阵列的设定方式是：

var[index]=content

意思是说，我有一个阵列名称为 var ，而这个阵列的内容为 var[1]=小明， var[2]=大明， var[3]=好明 .... 等等，那个 index 就是一些数字啦，重点是用中刮号 ([ ]) 来设定的。 目前我们 bash 提供的是一维阵列。老实说，如果您不必写一些复杂的程式， 那么这个阵列的地方，可以先略过，等到有需要再来学习即可！因为要制作出阵列， 通常与回圈或者其他判断式交互使用才有比较高的存在意义！

范例：设定上面提到的 var[1] ～ var[3] 的变数。
[root@www ~]# var[1]="small min"
[root@www ~]# var[2]="big min"
[root@www ~]# var[3]="nice min"
[root@www ~]# echo "${var[1]}, ${var[2]}, ${var[3]}"
small min, big min, nice min

阵列的变数类型比较有趣的地方在于‘读取’，一般来说，建议直接以 ${阵列} 的方式来读取，比较正确无误的啦！

小标题的图示 与档案系统及程序的限制关系： ulimit

想像一个状况：我的 Linux 主机里面同时登入了十个人，这十个人不知怎么搞的， 同时开启了 100 个档案，每个档案的大小约 10MBytes ，请问一下， 我的 Linux 主机的记忆体要有多大才够？ 10*100*10 = 10000 MBytes = 10GBytes ... 老天爷，这样，系统不挂点才有鬼哩！为了要预防这个情况的发生，所以我们的 bash 是可以‘限制使用者的某些系统资源’的，包括可以开启的档案数量， 可以使用的 CPU 时间，可以使用的记忆体总量等等。如何设定？用 ulimit 吧！

[root@www ~]# ulimit [-SHacdfltu] [配额]
选项与参数：
-H  ：hard limit ，严格的设定，必定不能超过这个设定的数值；
-S  ：soft limit ，警告的设定，可以超过这个设定值，但是若超过则有警告讯息。
      在设定上，通常 soft 会比 hard 小，举例来说，soft 可设定为 80 而 hard
      设定为 100，那么你可以使用到 90 (因为没有超过 100)，但介于 80~100 之间时，
      系统会有警告讯息通知你！
-a  ：后面不接任何选项与参数，可列出所有的限制额度；
-c  ：当某些程式发生错误时，系统可能会将该程式在记忆体中的资讯写成档案(除错用)，
      这种档案就被称为核心档案(core file)。此为限制每个核心档案的最大容量。
-f  ：此 shell 可以建立的最大档案容量(一般可能设定为 2GB)单位为 Kbytes
-d  ：程序可使用的最大断裂记忆体(segment)容量；
-l  ：可用于锁定 (lock) 的记忆体量
-t  ：可使用的最大 CPU 时间 (单位为秒)
-u  ：单一使用者可以使用的最大程序(process)数量。

范例一：列出你目前身份(假设为root)的所有限制资料数值
[root@www ~]# ulimit -a
core file size          (blocks, -c) 0          <==只要是 0 就代表没限制
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0

file size               (blocks, -f) unlimited  <==可建立的单一档案的大小
pending signals                 (-i) 11774
max locked memory       (kbytes, -l) 32
max memory size         (kbytes, -m) unlimited
open files                      (-n) 1024       <==同时可开启的档案数量
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 10240
cpu time               (seconds, -t) unlimited
max user processes              (-u) 11774
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited

范例二：限制使用者仅能建立 10MBytes 以下的容量的档案
[root@www ~]# ulimit -f 10240
[root@www ~]# ulimit -a

file size               (blocks, -f) 10240 <==最大量为10240Kbyes，相当10Mbytes
[root@www ~]# dd if=/dev/zero of=123 bs=1M count=20
File size limit exceeded <==尝试建立 20MB 的档案，结果失败了！

还记得我们在第八章 Linux 磁碟档案系统里面提到过，单一 filesystem 能够支援的单一档案大小与 block 的大小有关。例如 block size 为 1024 byte 时，单一档案可达 16GB 的容量。但是，我们可以用 ulimit 来限制使用者可以建立的档案大小喔！ 利用 ulimit -f 就可以来设定了！例如上面的范例二，要注意单位喔！单位是 Kbytes。 若改天你一直无法建立一个大容量的档案，记得瞧一瞧 ulimit 的资讯喔！

Tips:
想要复原 ulimit 的设定最简单的方法就是登出再登入，否则就是得要重新以 ulimit 设定才行！ 不过，要注意的是，一般身份使用者如果以 ulimit 设定了 -f 的档案大小， 那么他‘只能继续减小档案容量，不能增加档案容量喔！’另外，若想要管控使用者的 ulimit 限值， 可以参考第十四章的 pam 的介绍。 		鸟哥的图示
小标题的图示 变数内容的删除、取代与替换

变数除了可以直接设定来修改原本的内容之外，有没有办法透过简单的动作来将变数的内容进行微调呢？ 举例来说，进行变数内容的删除、取代与替换等！是可以的！我们可以透过几个简单的小步骤来进行变数内容的微调喔！ 底下就来试试看！

  • 变数内容的删除与取代

变数的内容可以很简单的透过几个咚咚来进行删除喔！我们使用 PATH 这个变数的内容来做测试好了。 请你依序进行底下的几个例子来玩玩，比较容易感受的到鸟哥在这里想要表达的意义：

范例一：先让小写的 path 自订变数设定的与 PATH 内容相同
[root@www ~]# path=${PATH}

[root@www ~]# echo $path
/usr/kerberos/sbin:/usr/kerberos/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:
/usr/sbin:/usr/bin:/root/bin  <==这两行其实是同一行啦！

范例二：假设我不喜欢 kerberos，所以要将前两个目录删除掉，如何显示？
[root@www ~]# echo ${path#/*kerberos/bin:}
/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin

上面这个范例很有趣的！他的重点可以用底下这张表格来说明：

${variable#/*kerberos/bin:}
   上面的特殊字体部分是关键字！用在这种删除模式所必须存在的

${variable#/*kerberos/bin:}
   这就是原本的变数名称，以上面范例二来说，这里就填写 path 这个‘变数名称’啦！

${variable#/*kerberos/bin:}
   这是重点！代表‘从变数内容的最前面开始向右删除’，且仅删除最短的那个

${variable#/*kerberos/bin:}
   代表要被删除的部分，由于 # 代表由前面开始删除，所以这里便由开始的 / 写起。
   需要注意的是，我们还可以透过万用字元 * 来取代 0 到无穷多个任意字元

   以上面范例二的结果来看， path 这个变数被删除的内容如下所示：

/usr/kerberos/sbin:/usr/kerberos/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:
/usr/sbin:/usr/bin:/root/bin  <==这两行其实是同一行啦！

很有趣吧！这样了解了 # 的功能了吗？接下来让我们来看看底下的范例三！

范例三：我想要删除前面所有的目录，仅保留最后一个目录
[root@www ~]# echo ${path#/*:}
/usr/kerberos/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:
/root/bin     <==这两行其实是同一行啦！

# 由于一个 # 仅删除掉最短的那个，因此他删除的情况可以用底下的删除线来看：
# /usr/kerberos/sbin:/usr/kerberos/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:
# /usr/sbin:/usr/bin:/root/bin  <==这两行其实是同一行啦！

[root@www ~]# echo ${path##/*:}
/root/bin
# 嘿！多加了一个 # 变成 ## 之后，他变成‘删除掉最长的那个资料’！亦即是：
# /usr/kerberos/sbin:/usr/kerberos/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:
# /usr/sbin:/usr/bin:/root/bin  <==这两行其实是同一行啦！

非常有趣！不是吗？因为在 PATH 这个变数的内容中，每个目录都是以冒号‘:’隔开的， 所以要从头删除掉目录就是介于斜线 (/) 到冒号 (:) 之间的资料！但是 PATH 中不止一个冒号 (:) 啊！ 所以 # 与 ## 就分别代表：

  • # ：符合取代文字的‘最短的’那一个；
  • ##：符合取代文字的‘最长的’那一个

上面谈到的是‘从前面开始删除变数内容’，那么如果想要‘从后面向前删除变数内容’呢？ 这个时候就得使用百分比 (%) 符号了！来看看范例四怎么做吧！

范例四：我想要删除最后面那个目录，亦即从 : 到 bin 为止的字串
[root@www ~]# echo ${path%:*bin}
/usr/kerberos/sbin:/usr/kerberos/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:
/usr/sbin:/usr/bin  <==注意啊！最后面一个目录不见去！
# 这个 % 符号代表由最后面开始向前删除！所以上面得到的结果其实是来自如下：
# /usr/kerberos/sbin:/usr/kerberos/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:
# /usr/sbin:/usr/bin:/root/bin  <==这两行其实是同一行啦！

范例五：那如果我只想要保留第一个目录呢？

[root@www ~]# echo ${path%%:*bin}
/usr/kerberos/sbin
# 同样的， %% 代表的则是最长的符合字串，所以结果其实是来自如下：
# /usr/kerberos/sbin:/usr/kerberos/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:
# /usr/sbin:/usr/bin:/root/bin  <==这两行其实是同一行啦！

由于我是想要由变数内容的后面向前面删除，而我这个变数内容最后面的结尾是‘/root/bin’， 所以你可以看到上面我删除的资料最终一定是‘bin’，亦即是‘:*bin’那个 * 代表万用字元！ 至于 % 与 %% 的意义其实与 # 及 ## 类似！这样理解否？

例题：
假设你是 root ，那你的 MAIL 变数应该是 /var/spool/mail/root 。假设你只想要保留最后面那个档名 (root)， 前面的目录名称都不要了，如何利用 $MAIL 变数来达成？
答：
题意其实是这样‘/var/spool/mail/root’，亦即删除掉两条斜线间的所有资料(最长符合)。 这个时候你就可以这样做即可：
[root@www ~]# echo ${MAIL##/*/}
相反的，如果你只想要拿掉档名，保留目录的名称，亦即是‘/var/spool/mail/root’ (最短符合)。但假设你并不知道结尾的字母为何，此时你可以利用万用字元来处理即可，如下所示：
[root@www ~]# echo ${MAIL%/*}

了解了删除功能后，接下来谈谈取代吧！继续玩玩范例六啰！

范例六：将 path 的变数内容内的 sbin 取代成大写 SBIN：
[root@www ~]# echo ${path/sbin/SBIN}

/usr/kerberos/SBIN:/usr/kerberos/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:
/usr/sbin:/usr/bin:/root/bin
# 这个部分就容易理解的多了！关键字在于那两个斜线，两斜线中间的是旧字串
# 后面的是新字串，所以结果就会出现如上述的特殊字体部分啰！

[root@www ~]# echo ${path//sbin/SBIN}
/usr/kerberos/SBIN:/usr/kerberos/bin:/usr/local/SBIN:/usr/local/bin:/SBIN:/bin:
/usr/SBIN:/usr/bin:/root/bin

# 如果是两条斜线，那么就变成所有符合的内容都会被取代喔！

我们将这部份作个总结说明一下：

变数设定方式 说明
${变数#关键字}
${变数##关键字} 		若变数内容从头开始的资料符合‘关键字’，则将符合的最短资料删除
若变数内容从头开始的资料符合‘关键字’，则将符合的最长资料删除
${变数%关键字}
${变数%%关键字} 		若变数内容从尾向前的资料符合‘关键字’，则将符合的最短资料删除
若变数内容从尾向前的资料符合‘关键字’，则将符合的最长资料删除
${变数/旧字串/新字串}
${变数//旧字串/新字串} 		若变数内容符合‘旧字串’则‘第一个旧字串会被新字串取代’
若变数内容符合‘旧字串’则‘全部的旧字串会被新字串取代’

  • 变数的测试与内容替换

在某些时刻我们常常需要‘判断’某个变数是否存在，若变数存在则使用既有的设定，若变数不存在则给予一个常用的设定。 我们举底下的例子来说明好了，看看能不能较容易被你所理解呢！

范例一：测试一下是否存在 username 这个变数，若不存在则给予 username 内容为 root
[root@www ~]# echo $username
           <==由于出现空白，所以 username 可能不存在，也可能是空字串
[root@www ~]# username=${username-root}
[root@www ~]# echo $username
root       <==因为 username 没有设定，所以主动给予名为 root 的内容。

[root@www ~]# username="vbird tsai" <==主动设定 username 的内容
[root@www ~]# username=${username-root}
[root@www ~]# echo $username
vbird tsai <==因为 username 已经设定了，所以使用旧有的设定而不以 root 取代

在上面的范例中，重点在于减号‘ - ’后面接的关键字！基本上你可以这样理解：

new_var=${old_var-content}
   新的变数，主要用来取代旧变数。新旧变数名称其实常常是一样的

new_var=${old_var-content}
   这是本范例中的关键字部分！必须要存在的哩！

new_var=${old_var-content}
   旧的变数，被测试的项目！

new_var=${old_var-content}
   变数的‘内容’，在本范例中，这个部分是在‘给予未设定变数的内容’

不过这还是有点问题！因为 username 可能已经被设定为‘空字串’了！果真如此的话，那你还可以使用底下的范例来给予 username 的内容成为 root 喔！

范例二：若 username 未设定或为空字串，则将 username 内容设定为 root
[root@www ~]# username=""
[root@www ~]# username=${username-root}
[root@www ~]# echo $username
      <==因为 username 被设定为空字串了！所以当然还是保留为空字串！
[root@www ~]# username=${username:-root}

[root@www ~]# echo $username
root  <==加上‘ : ’后若变数内容为空或者是未设定，都能够以后面的内容替换！

在大括号内有没有冒号‘ : ’的差别是很大的！加上冒号后，被测试的变数未被设定或者是已被设定为空字串时， 都能够用后面的内容 (本例中是使用 root 为内容) 来替换与设定！这样可以了解了吗？除了这样的测试之外， 还有其他的测试方法喔！鸟哥将他整理如下：

Tips:
底下的例子当中，那个 var 与 str 为变数，我们想要针对 str 是否有设定来决定 var 的值喔！ 一般来说， str: 代表‘str 没设定或为空的字串时’；至于 str 则仅为‘没有该变数’。 		鸟哥的图示
变数设定方式 | str 没有设定 | str 为空字串 | str 已设定非为空字串
var=${str-expr} | var=expr | var= | var=$str
var=${str:-expr} | var=expr | var=expr | var=$str
var=${str+expr} | var= | var=expr | var=expr
var=${str:+expr} | var= | var= | var=expr
var=${str=expr} | str=expr var=expr | str 不变 var= | str 不变 var=$str
var=${str:=expr} | str=expr var=expr | str=expr var=expr | str 不变 var=$str
var=${str?expr} | expr 输出至 stderr | var= | var=$str
var=${str:?expr} | expr 输出至 stderr | expr 输出至 stderr | var=$str

根据上面这张表，我们来进行几个范例的练习吧！ ^_^！首先让我们来测试一下，如果旧变数 (str) 不存在时， 我们要给予新变数一个内容，若旧变数存在则新变数内容以旧变数来替换，结果如下：

测试：先假设 str 不存在 (用 unset) ，然后测试一下等号 (-) 的用法：
[root@www ~]# unset str; var=${str-newvar}
[root@www ~]# echo var="$var", str="$str"
var=newvar, str=        <==因为 str 不存在，所以 var 为 newvar

测试：若 str 已存在，测试一下 var 会变怎样？：
[root@www ~]# str="oldvar"; var=${str-newvar}

[root@www ~]# echo var="$var", str="$str"
var=oldvar, str=oldvar  <==因为 str 存在，所以 var 等于 str 的内容

关于减号 (-) 其实上面我们谈过了！这里的测试只是要让你更加了解，这个减号的测试并不会影响到旧变数的内容。 如果你想要将旧变数内容也一起替换掉的话，那么就使用等号 (=) 吧！

测试：先假设 str 不存在 (用 unset) ，然后测试一下等号 (=) 的用法：
[root@www ~]# unset str; var=${str=newvar}

[root@www ~]# echo var="$var", str="$str"
var=newvar, str=newvar  <==因为 str 不存在，所以 var/str 均为 newvar

测试：如果 str 已存在了，测试一下 var 会变怎样？
[root@www ~]# str="oldvar"; var=${str=newvar}
[root@www ~]# echo var="$var", str="$str"
var=oldvar, str=oldvar  <==因为 str 存在，所以 var 等于 str 的内容

那如果我只是想知道，如果旧变数不存在时，整个测试就告知我‘有错误’，此时就能够使用问号‘ ? ’的帮忙啦！ 底下这个测试练习一下先！

测试：若 str 不存在时，则 var 的测试结果直接显示 "无此变数"
[root@www ~]# unset str; var=${str?无此变数}
-bash: str: 无此变数    <==因为 str 不存在，所以输出错误讯息

测试：若 str 存在时，则 var 的内容会与 str 相同！

[root@www ~]# str="oldvar"; var=${str?novar}
[root@www ~]# echo var="$var", str="$str"
var=oldvar, str=oldvar  <==因为 str 存在，所以 var 等于 str 的内容

基本上这种变数的测试也能够透过 shell script 内的 if...then... 来处理， 不过既然 bash 有提供这么简单的方法来测试变数，那我们也可以多学一些嘛！ 不过这种变数测试通常是在程式设计当中比较容易出现，如果这里看不懂就先略过，未来有用到判断变数值时，再回来看看吧！ ^_^

大标题的图示 命令别名与历史命令：

我们知道在早期的 DOS 年代，清除荧幕上的资讯可以使用 cls 来清除，但是在 Linux 里面， 我们则是使用 clear 来清除画面的。那么可否让 cls 等于 clear 呢？可以啊！用啥方法？ link file 还是什么的？别急！底下我们介绍不用 link file 的命令别名来达成。那么什么又是历史命令？ 曾经做过的举动我们可以将他记录下来喔！那就是历史命令啰～底下分别来谈一谈这两个玩意儿。

小标题的图示 命令别名设定： alias, unalias

命令别名是一个很有趣的东西，特别是你的惯用指令特别长的时候！还有， 增设预设的选项在一些惯用的指令上面，可以预防一些不小心误杀档案的情况发生的时候！ 举个例子来说，如果你要查询隐藏档，并且需要长的列出与一页一页翻看，那么需要下达‘ ls -al | more ’这个指令，我是觉得很烦啦！ 要输入好几个单字！那可不可以使用 lm 来简化呢？当然可以，你可以在命令列下面下达：

[root@www ~]# alias lm='ls -al | more'

立刻多出了一个可以执行的指令喔！这个指令名称为 lm ，且其实他是执行 ls -al | more 啊！真是方便。不过， 要注意的是：‘alias 的定义规则与变数定义规则几乎相同’， 所以你只要在 alias 后面加上你的 {‘别名’='指令 选项...' }， 以后你只要输入 lm 就相当于输入了 ls -al|more 这一串指令！很方便吧！

另外，命令别名的设定还可以取代既有的指令喔！举例来说，我们知道 root 可以移除 (rm) 任何资料！所以当你以 root 的身份在进行工作时，需要特别小心， 但是总有失手的时候，那么 rm 提供了一个选项来让我们确认是否要移除该档案，那就是 -i 这个选项！所以，你可以这样做：

[root@www ~]# alias rm='rm -i'

那么以后使用 rm 的时候，就不用太担心会有错误删除的情况了！这也是命令别名的优点啰！ 那么如何知道目前有哪些的命令别名呢？就使用 alias 呀！

[root@www ~]# alias
alias cp='cp -i'
alias l.='ls -d .* --color=tty'
alias ll='ls -l --color=tty'
alias lm='ls -l | more'
alias ls='ls --color=tty'
alias mv='mv -i'
alias rm='rm -i'
alias which='alias | /usr/bin/which --tty-only --show-dot --show-tilde'

由上面的资料当中，你也会发现一件事情啊，我们在第十章的 vim 程式编辑器里面提到 vi 与 vim 是不太一样的，vim 可以多作一些额外的语法检验与颜色显示，预设的 root 是单纯使用 vi 而已。 如果你想要使用 vi 就直接以 vim 来开启档案的话，使用‘ alias vi='vim' ’这个设定即可。 至于如果要取消命令别名的话，那么就使用 unalias 吧！例如要将刚刚的 lm 命令别名拿掉，就使用：

[root@www ~]# unalias lm

那么命令别名与变数有什么不同呢？命令别名是‘新创一个新的指令， 你可以直接下达该指令’的，至于变数则需要使用类似‘ echo ’指令才能够呼叫出变数的内容！ 这两者当然不一样！很多初学者在这里老是搞不清楚！要注意啊！ ^_^

例题：
DOS 年代，列出目录与档案就是 dir ，而清除荧幕就是 cls ，那么如果我想要在 linux 里面也使用相同的指令呢？
答：
很简单，透过 clear 与 ls 来进行命令别名的建置：
alias cls='clear'
alias dir='ls -l'

小标题的图示 历史命令：history

前面我们提过 bash 有提供指令历史的服务！那么如何查询我们曾经下达过的指令呢？就使用 history 啰！当然，如果觉得 histsory 要输入的字元太多太麻烦，可以使用命令别名来设定呢！ 不要跟我说还不会设定呦！ ^_^

[root@www ~]# alias h='history'

如此则输入 h 等于输入 history 啰！好了，我们来谈一谈 history 的用法吧！

[root@www ~]# history [n]
[root@www ~]# history [-c]
[root@www ~]# history [-raw] histfiles
选项与参数：
n   ：数字，意思是‘要列出最近的 n 笔命令列表’的意思！
-c  ：将目前的 shell 中的所有 history 内容全部消除
-a  ：将目前新增的 history 指令新增入 histfiles 中，若没有加 histfiles ，
      则预设写入 ~/.bash_history
-r  ：将 histfiles 的内容读到目前这个 shell 的 history 记忆中；
-w  ：将目前的 history 记忆内容写入 histfiles 中！

范例一：列出目前记忆体内的所有 history 记忆
[root@www ~]# history

# 前面省略
 1017  man bash
 1018  ll
 1019  history
 1020  history
# 列出的资讯当中，共分两栏，第一栏为该指令在这个 shell 当中的代码，
# 另一个则是指令本身的内容喔！至于会秀出几笔指令记录，则与 HISTSIZE 有关！

范例二：列出目前最近的 3 笔资料
[root@www ~]# history 3
 1019  history
 1020  history
 1021  history 3

范例三：立刻将目前的资料写入 histfile 当中
[root@www ~]# history -w

# 在预设的情况下，会将历史纪录写入 ~/.bash_history 当中！
[root@www ~]# echo $HISTSIZE
1000

在正常的情况下，历史命令的读取与记录是这样的：

  • 当我们以 bash 登入 Linux 主机之后，系统会主动的由家目录的 ~/.bash_history 读取以前曾经下过的指令，那么 ~/.bash_history 会记录几笔资料呢？这就与你 bash 的 HISTFILESIZE 这个变数设定值有关了！

  • 假设我这次登入主机后，共下达过 100 次指令，‘等我登出时， 系统就会将 101~1100 这总共 1000 笔历史命令更新到 ~/.bash_history 当中。’ 也就是说，历史命令在我登出时，会将最近的 HISTFILESIZE 笔记录到我的纪录档当中啦！

  • 当然，也可以用 history -w 强制立刻写入的！那为何用‘更新’两个字呢？ 因为 ~/.bash_history 记录的笔数永远都是 HISTFILESIZE 那么多，旧的讯息会被主动的拿掉！ 仅保留最新的！

那么 history 这个历史命令只可以让我查询命令而已吗？呵呵！当然不止啊！ 我们可以利用相关的功能来帮我们执行命令呢！举例来说啰：

[root@www ~]# !number

[root@www ~]# !command
[root@www ~]# !!
选项与参数：
number  ：执行第几笔指令的意思；
command ：由最近的指令向前搜寻‘指令串开头为 command’的那个指令，并执行；
!!      ：就是执行上一个指令(相当于按↑按键后，按 Enter)

[root@www ~]# history
   66  man rm
   67  alias
   68  man history
   69  history
[root@www ~]# !66  <==执行第 66 笔指令

[root@www ~]# !!   <==执行上一个指令，本例中亦即 !66
[root@www ~]# !al  <==执行最近以 al 为开头的指令(上头列出的第 67 个)

经过上面的介绍，了乎？历史命令用法可多了！如果我想要执行上一个指令， 除了使用上下键之外，我可以直接以‘ !! ’ 来下达上个指令的内容，此外， 我也可以直接选择下达第 n 个指令，‘ !n ’来执行，也可以使用指令标头，例如 ‘ !vi ’来执行最近指令开头是 vi 的指令列！相当的方便而好用！

基本上 history 的用途很大的！但是需要小心安全的问题！尤其是 root 的历史纪录档案，这是 Cracker 的最爱！因为不小心的 root 会将很多的重要资料在执行的过程中会被纪录在 ~/.bash_history 当中，如果这个档案被解析的话，后果不堪呐！无论如何，使用 history 配合‘ ! ’曾经使用过的指令下达是很有效率的一个指令下达方法！

  • 同一帐号同时多次登入的 history 写入问题

有些朋友在练习 linux 的时候喜欢同时开好几个 bash 介面，这些 bash 的身份都是 root 。 这样会有 ~/.bash_history 的写入问题吗？想一想，因为这些 bash 在同时以 root 的身份登入， 因此所有的 bash 都有自己的 1000 笔记录在记忆体中。因为等到登出时才会更新记录档，所以啰， 最后登出的那个 bash 才会是最后写入的资料。唔！如此一来其他 bash 的指令操作就不会被记录下来了 (其实有被记录，只是被后来的最后一个 bash 所覆盖更新了) 。

由于多重登入有这样的问题，所以很多朋友都习惯单一 bash 登入，再用工作控制 (job control, 第四篇会介绍) 来切换不同工作！ 这样才能够将所有曾经下达过的指令记录下来，也才方便未来系统管理员进行指令的 debug 啊！

  • 无法记录时间

历史命令还有一个问题，那就是无法记录指令下达的时间。由于这 1000 笔历史命令是依序记录的， 但是并没有记录时间，所以在查询方面会有一些不方便。如果读者们有兴趣，其实可以透过 ~/.bash_logout 来进行 history 的记录，并加上 date 来增加时间参数，也是一个可以应用的方向喔！ 有兴趣的朋友可以先看看情境模拟题一吧！

大标题的图示 Bash Shell 的操作环境：

是否记得我们登入主机的时候，荧幕上头会有一些说明文字，告知我们的 Linux 版本啊什么的， 还有，登入的时候我们还可以给予使用者一些讯息或者欢迎文字呢。此外， 我们习惯的环境变数、命令别名等等的，是否可以登入就主动的帮我设定好？ 这些都是需要注意的。另外，这些设定值又可以分为系统整体设定值与各人喜好设定值， 仅是一些档案放置的地点不同啦！这我们后面也会来谈一谈的！

小标题的图示 路径与指令搜寻顺序

我们在第六章与第七章都曾谈过‘相对路径与绝对路径’的关系， 在本章的前几小节也谈到了 alias 与 bash 的内建命令。现在我们知道系统里面其实有不少的 ls 指令， 或者是包括内建的 echo 指令，那么来想一想，如果一个指令 (例如 ls) 被下达时， 到底是哪一个 ls 被拿来运作？很有趣吧！基本上，指令运作的顺序可以这样看：

  1. 以相对/绝对路径执行指令，例如‘ /bin/ls ’或‘ ./ls ’；
  2. 由 alias 找到该指令来执行；
  3. 由 bash 内建的 (builtin) 指令来执行；
  4. 透过 $PATH 这个变数的顺序搜寻到的第一个指令来执行。

举例来说，你可以下达 /bin/ls 及单纯的 ls 看看，会发现使用 ls 有颜色但是 /bin/ls 则没有颜色。 因为 /bin/ls 是直接取用该指令来下达，而 ls 会因为‘ alias ls='ls --color=tty' ’这个命令别名而先使用！ 如果想要了解指令搜寻的顺序，其实透过 type -a ls 也可以查询的到啦！上述的顺序最好先了解喔！

例题：
设定 echo 的命令别名成为 echo -n ，然后再观察 echo 执行的顺序
答：
[root@www ~]# alias echo='echo -n'
[root@www ~]# type -a echo
echo is aliased to `echo -n'
echo is a shell builtin
echo is /bin/echo
瞧！很清楚吧！先 alias 再 builtin 再由 $PATH 找到 /bin/echo 啰！

小标题的图示 bash 的进站与欢迎讯息： /etc/issue, /etc/motd

虾密！ bash 也有进站画面与欢迎讯息喔？真假？真的啊！ 还记得在终端机介面 (tty1 ~ tty6) 登入的时候，会有几行提示的字串吗？那就是进站画面啊！ 那个字串写在哪里啊？呵呵！在 /etc/issue 里面啊！先来看看：

[root@www ~]# cat /etc/issue
CentOS release 5.3 (Final)
Kernel \r on an \m

鸟哥是以完全未更新过的 CentOS 5.3 作为范例，里面预设有三行，较有趣的地方在于 \r 与 \m。 就如同 $PS1 这变数一样，issue 这个档案的内容也是可以使用反斜线作为变数取用喔！你可以 man issue 配合 man mingetty 得到底下的结果：

issue 内的各代码意义
\d 本地端时间的日期；
\l 显示第几个终端机介面；
\m 显示硬体的等级 (i386/i486/i586/i686...)；
\n 显示主机的网路名称；
\o 显示 domain name；
\r 作业系统的版本 (相当于 uname -r)
\t 显示本地端时间的时间；
\s 作业系统的名称；
\v 作业系统的版本。

做一下底下这个练习，看看能不能取得你要的进站画面？

例题：
如果你在 tty3 的进站画面看到如下显示，该如何设定才能得到如下画面？
CentOS release 5.3 (Final) (terminal: tty3)
Date: 2009-02-05 17:29:19
Kernel 2.6.18-128.el5 on an i686
Welcome!

注意，tty3 在不同的 tty 有不同显示，日期则是再按下 [enter] 后就会所有不同。
答：
很简单，参考上述的反斜线功能去修改 /etc/issue 成为如下模样即可(共五行)：

CentOS release 5.3 (Final) (terminal: \l)
Date: \d \t
Kernel \r on an \m
Welcome!
曾有鸟哥的学生在这个 /etc/issue 内修改资料，光是利用简单的英文字母作出属于他自己的进站画面， 画面里面有他的中文名字呢！非常厉害！也有学生做成类似很大一个‘囧’在进站画面，都非常有趣！

你要注意的是，除了 /etc/issue 之外还有个 /etc/issue.net 呢！这是啥？这个是提供给 telnet 这个远端登入程式用的。 当我们使用 telnet 连接到主机时，主机的登入画面就会显示 /etc/issue.net 而不是 /etc/issue 呢！

至于如果您想要让使用者登入后取得一些讯息，例如您想要让大家都知道的讯息， 那么可以将讯息加入 /etc/motd 里面去！例如：当登入后，告诉登入者， 系统将会在某个固定时间进行维护工作，可以这样做：

[root@www ~]# vi /etc/motd
Hello everyone,
Our server will be maintained at 2009/02/28 0:00 ~ 24:00.
Please don't login server at that time. ^_^

那么当你的使用者(包括所有的一般帐号与 root)登入主机后，就会显示这样的讯息出来：

Last login: Thu Feb  5 22:35:47 2009 from 127.0.0.1
Hello everyone,
Our server will be maintained at 2009/02/28 0:00 ~ 24:00.
Please don't login server at that time. ^_^
小标题的图示 bash 的环境设定档

你是否会觉得奇怪，怎么我们什么动作都没有进行，但是一进入 bash 就取得一堆有用的变数了？ 这是因为系统有一些环境设定档案的存在，让 bash 在启动时直接读取这些设定档，以规划好 bash 的操作环境啦！ 而这些设定档又可以分为全体系统的设定档以及使用者个人偏好设定档。要注意的是， 我们前几个小节谈到的命令别名啦、自订的变数啦，在你登出 bash 后就会失效，所以你想要保留你的设定， 就得要将这些设定写入设定档才行。底下就让我们来聊聊吧！

  • login 与 non-login shell

在开始介绍 bash 的设定档前，我们一定要先知道的就是 login shell 与 non-login shell！ 重点在于有没有登入 (login) 啦！

  • login shell：取得 bash 时需要完整的登入流程的，就称为 login shell。举例来说，你要由 tty1 ~ tty6 登入，需要输入使用者的帐号与密码，此时取得的 bash 就称为‘ login shell ’啰；

  • non-login shell：取得 bash 介面的方法不需要重复登入的举动，举例来说，(1)你以 X window 登入 Linux 后， 再以 X 的图形化介面启动终端机，此时那个终端介面并没有需要再次的输入帐号与密码，那个 bash 的环境就称为 non-login shell了。(2)你在原本的 bash 环境下再次下达 bash 这个指令，同样的也没有输入帐号密码， 那第二个 bash (子程序) 也是 non-login shell 。

为什么要介绍 login, non-login shell 呢？这是因为这两个取得 bash 的情况中，读取的设定档资料并不一样所致。 由于我们需要登入系统，所以先谈谈 login shell 会读取哪些设定档？一般来说，login shell 其实只会读取这两个设定档：

  1. /etc/profile：这是系统整体的设定，你最好不要修改这个档案；
  2. ~/.bash_profile 或 ~/.bash_login 或 ~/.profile：属于使用者个人设定，你要改自己的资料，就写入这里！

那么，就让我们来聊一聊这两个档案吧！这两个档案的内容可是非常繁复的喔！

  • /etc/profile (login shell 才会读)

你可以使用 vim 去阅读一下这个档案的内容。这个设定档可以利用使用者的识别码 (UID) 来决定很多重要的变数资料， 这也是每个使用者登入取得 bash 时一定会读取的设定档！ 所以如果你想要帮所有使用者设定整体环境，那就是改这里啰！不过，没事还是不要随便改这个档案喔 这个档案设定的变数主要有：

  • PATH：会依据 UID 决定 PATH 变数要不要含有 sbin 的系统指令目录；
  • MAIL：依据帐号设定好使用者的 mailbox 到 /var/spool/mail/帐号名；
  • USER：根据使用者的帐号设定此一变数内容；
  • HOSTNAME：依据主机的 hostname 指令决定此一变数内容；
  • HISTSIZE：历史命令记录笔数。CentOS 5.x 设定为 1000 ；

/etc/profile 可不止会做这些事而已，他还会去呼叫外部的设定资料喔！在 CentOS 5.x 预设的情况下， 底下这些资料会依序的被呼叫进来：

  • /etc/inputrc

    其实这个档案并没有被执行啦！/etc/profile 会主动的判断使用者有没有自订输入的按键功能，如果没有的话， /etc/profile 就会决定设定‘INPUTRC=/etc/inputrc’这个变数！此一档案内容为 bash 的热键啦、[tab]要不要有声音啦等等的资料！ 因为鸟哥觉得 bash 预设的环境已经很棒了，所以不建议修改这个档案！

  • /etc/profile.d/*.sh

    其实这是个目录内的众多档案！只要在 /etc/profile.d/ 这个目录内且副档名为 .sh ，另外，使用者能够具有 r 的权限， 那么该档案就会被 /etc/profile 呼叫进来。在 CentOS 5.x 中，这个目录底下的档案规范了 bash 操作介面的颜色、 语系、ll 与 ls 指令的命令别名、vi 的命令别名、which 的命令别名等等。如果你需要帮所有使用者设定一些共用的命令别名时， 可以在这个目录底下自行建立副档名为 .sh 的档案，并将所需要的资料写入即可喔！

  • /etc/sysconfig/i18n

    这个档案是由 /etc/profile.d/lang.sh 呼叫进来的！这也是我们决定 bash 预设使用何种语系的重要设定档！ 档案里最重要的就是 LANG 这个变数的设定啦！我们在前面的 locale 讨论过这个档案啰！ 自行回去瞧瞧先！

反正你只要记得，bash 的 login shell 情况下所读取的整体环境设定档其实只有 /etc/profile，但是 /etc/profile 还会呼叫出其他的设定档，所以让我们的 bash 操作介面变的非常的友善啦！ 接下来，让我们来瞧瞧，那么个人偏好的设定档又是怎么回事？

  • ~/.bash_profile (login shell 才会读)

bash 在读完了整体环境设定的 /etc/profile 并藉此呼叫其他设定档后，接下来则是会读取使用者的个人设定档。 在 login shell 的 bash 环境中，所读取的个人偏好设定档其实主要有三个，依序分别是：

  1. ~/.bash_profile
  2. ~/.bash_login
  3. ~/.profile

其实 bash 的 login shell 设定只会读取上面三个档案的其中一个， 而读取的顺序则是依照上面的顺序。也就是说，如果 ~/.bash_profile 存在，那么其他两个档案不论有无存在，都不会被读取。 如果 ~/.bash_profile 不存在才会去读取 ~/.bash_login，而前两者都不存在才会读取 ~/.profile 的意思。 会有这么多的档案，其实是因应其他 shell 转换过来的使用者的习惯而已。 先让我们来看一下 root 的 /root/.bash_profile 的内容是怎样呢？

[root@www ~]# cat ~/.bash_profile
# .bash_profile

# Get the aliases and functions
if [ -f ~/.bashrc ]; then   <==底下这三行在判断并读取 ~/.bashrc
        . ~/.bashrc
fi

# User specific environment and startup programs
PATH=$PATH:$HOME/bin        <==底下这几行在处理个人化设定
export PATH

unset USERNAME

这个档案内有设定 PATH 这个变数喔！而且还使用了 export 将 PATH 变成环境变数呢！ 由于 PATH 在 /etc/profile 当中已经设定过，所以在这里就以累加的方式增加使用者家目录下的 ~/bin/ 为额外的执行档放置目录。这也就是说，你可以将自己建立的执行档放置到你自己家目录下的 ~/bin/ 目录啦！ 那就可以直接执行该执行档而不需要使用绝对/相对路径来执行该档案。

这个档案的内容比较有趣的地方在于 if ... then ... 那一段！那一段程式码我们会在第十三章 shell script 谈到，假设你现在是看不懂的。 该段的内容指的是‘判断家目录下的 ~/.bashrc 存在否，若存在则读入 ~/.bashrc 的设定’。 bash 设定档的读入方式比较有趣，主要是透过一个指令‘ source ’来读取的！ 也就是说 ~/.bash_profile 其实会再呼叫 ~/.bashrc 的设定内容喔！最后，我们来看看整个 login shell 的读取流程：

login shell 的设定档读取流程
图 4.3.1、login shell 的设定档读取流程

实线的的方向是主线流程，虚线的方向则是被呼叫的设定档！从上面我们也可以清楚的知道，在 CentOS 的 login shell 环境下，最终被读取的设定档是‘ ~/.bashrc ’这个档案喔！所以，你当然可以将自己的偏好设定写入该档案即可。 底下我们还要讨论一下 source 与 ~/.bashrc 喔！

  • source ：读入环境设定档的指令

由于 /etc/profile 与 ~/.bash_profile 都是在取得 login shell 的时候才会读取的设定档，所以， 如果你将自己的偏好设定写入上述的档案后，通常都是得登出再登入后，该设定才会生效。那么，能不能直接读取设定档而不登出登入呢？ 可以的！那就得要利用 source 这个指令了！

[root@www ~]# source 设定档档名

范例：将家目录的 ~/.bashrc 的设定读入目前的 bash 环境中
[root@www ~]# source ~/.bashrc  <==底下这两个指令是一样的！
[root@www ~]#  .  ~/.bashrc

利用 source 或小数点 (.) 都可以将设定档的内容读进来目前的 shell 环境中！ 举例来说，我修改了 ~/.bashrc ，那么不需要登出，立即以 source ~/.bashrc 就可以将刚刚最新设定的内容读进来目前的环境中！很不错吧！还有，包括 ~/bash_profile 以及 /etc/profile 的设定中， 很多时候也都是利用到这个 source (或小数点) 的功能喔！

有没有可能会使用到不同环境设定档的时候？有啊！ 最常发生在一个人的工作环境分为多种情况的时候了！举个例子来说，在鸟哥的大型主机中， 常常需要负责两到三个不同的案子，每个案子所需要处理的环境变数订定并不相同， 那么鸟哥就将这两三个案子分别编写属于该案子的环境变数设定档案，当需要该环境时，就直接‘ source 变数档 ’，如此一来，环境变数的设定就变的更简便而灵活了！

  • ~/.bashrc (non-login shell 会读)

谈完了 login shell 后，那么 non-login shell 这种非登入情况取得 bash 操作介面的环境设定档又是什么？ 当你取得 non-login shell 时，该 bash 设定档仅会读取 ~/.bashrc 而已啦！那么预设的 ~/.bashrc 内容是如何？

[root@www ~]# cat ~/.bashrc
# .bashrc

# User specific aliases and functions
alias rm='rm -i'             <==使用者的个人设定
alias cp='cp -i'
alias mv='mv -i'

# Source global definitions
if [ -f /etc/bashrc ]; then  <==整体的环境设定
        . /etc/bashrc
fi

特别注意一下，由于 root 的身份与一般使用者不同，鸟哥是以 root 的身份取得上述的资料， 如果是一般使用者的 ~/.bashrc 会有些许不同。看一下，你会发现在 root 的 ~/.bashrc 中其实已经规范了较为保险的命令别名了。 此外，咱们的 CentOS 5.x 还会主动的呼叫 /etc/bashrc 这个档案喔！为什么需要呼叫 /etc/bashrc 呢？ 因为 /etc/bashrc 帮我们的 bash 定义出底下的资料：

  • 依据不同的 UID 规范出 umask 的值；
  • 依据不同的 UID 规范出提示字元 (就是 PS1 变数)；
  • 呼叫 /etc/profile.d/*.sh 的设定

你要注意的是，这个 /etc/bashrc 是 CentOS 特有的 (其实是 Red Hat 系统特有的)，其他不同的 distributions 可能会放置在不同的档名就是了。由于这个 ~/.bashrc 会呼叫 /etc/bashrc 及 /etc/profile.d/*.sh ， 所以，万一你没有 ~/.bashrc (可能自己不小心将他删除了)，那么你会发现你的 bash 提示字元可能会变成这个样子：

-bash-3.2$

不要太担心啦！这是正常的，因为你并没有呼叫 /etc/bashrc 来规范 PS1 变数啦！而且这样的情况也不会影响你的 bash 使用。 如果你想要将命令提示字元捉回来，那么可以复制 /etc/skel/.bashrc 到你的家目录，再修订一下你所想要的内容， 并使用 source 去呼叫 ~/.bashrc ，那你的命令提示字元就会回来啦！

  • 其他相关设定档

事实上还有一些设定档可能会影响到你的 bash 操作的，底下就来谈一谈：

  • /etc/man.config

    这个档案乍看之下好像跟 bash 没相关性，但是对于系统管理员来说， 却也是很重要的一个档案！这的档案的内容‘规范了使用 man 的时候， man page 的路径到哪里去寻找！’所以说的简单一点，这个档案规定了下达 man 的时候，该去哪里查看资料的路径设定！

    那么什么时候要来修改这个档案呢？如果你是以 tarball 的方式来安装你的资料，那么你的 man page 可能会放置在 /usr/local/softpackage/man 里头，那个 softpackage 是你的套件名称， 这个时候你就得以手动的方式将该路径加到 /etc/man.config 里头，否则使用 man 的时候就会找不到相关的说明档啰。

    事实上，这个档案内最重要的其实是 MANPATH 这个变数设定啦！ 我们搜寻 man page 时，会依据 MANPATH 的路径去分别搜寻啊！另外，要注意的是， 这个档案在各大不同版本 Linux distributions 中，档名都不太相同，例如 CentOS 用的是 /etc/man.config ，而 SuSE 用的则是 /etc/manpath.config ， 可以利用 [tab] 按键来进行档名的补齐啦！

  • ~/.bash_history

    还记得我们在历史命令提到过这个档案吧？预设的情况下， 我们的历史命令就记录在这里啊！而这个档案能够记录几笔资料，则与 HISTFILESIZE 这个变数有关啊。每次登入 bash 后，bash 会先读取这个档案，将所有的历史指令读入记忆体， 因此，当我们登入 bash 后就可以查知上次使用过哪些指令啰。至于更多的历史指令， 请自行回去参考喔！

  • ~/.bash_logout

    这个档案则记录了‘当我登出 bash 后，系统再帮我做完什么动作后才离开’的意思。 你可以去读取一下这个档案的内容，预设的情况下，登出时， bash 只是帮我们清掉荧幕的讯息而已。 不过，你也可以将一些备份或者是其他你认为重要的工作写在这个档案中 (例如清空暂存档)， 那么当你离开 Linux 的时候，就可以解决一些烦人的事情啰！
小标题的图示 终端机的环境设定： stty, set

我们在第五章首次登入 Linux 时就提过，可以在 tty1 ~ tty6 这六个文字介面的终端机 (terminal) 环境中登入，登入的时候我们可以取得一些字元设定的功能喔！ 举例来说，我们可以利用倒退键 (backspace，就是那个←符号的按键) 来删除命令列上的字元， 也可以使用 [ctrl]+c 来强制终止一个指令的运行，当输入错误时，就会有声音跑出来警告。这是怎么办到的呢？ 很简单啊！因为登入终端机的时候，会自动的取得一些终端机的输入环境的设定啊！

事实上，目前我们使用的 Linux distributions 都帮我们作了最棒的使用者环境了， 所以大家可以不用担心操作环境的问题。不过，在某些 Unix like 的机器中，还是可能需要动用一些手脚， 才能够让我们的输入比较快乐～举例来说，利用 [backspace] 删除，要比利用 [Del] 按键来的顺手吧！ 但是某些 Unix 偏偏是以 [del] 来进行字元的删除啊！所以，这个时候就可以动动手脚啰～

那么如何查阅目前的一些按键内容呢？可以利用 stty (setting tty 终端机的意思) 呢！ stty 也可以帮助设定终端机的输入按键代表意义喔！

[root@www ~]# stty [-a]
选项与参数：
-a  ：将目前所有的 stty 参数列出来；

范例一：列出所有的按键与按键内容
[root@www ~]# stty -a
speed 38400 baud; rows 24; columns 80; line = 0;
intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = <undef>;
eol2 = <undef>; swtch = <undef>; start = ^Q; stop = ^S; susp = ^Z;

rprnt = ^R; werase = ^W; lnext = ^V; flush = ^O; min = 1; time = 0;
....(以下省略)....

我们可以利用 stty -a 来列出目前环境中所有的按键列表，在上头的列表当中，需要注意的是特殊字体那几个， 此外，如果出现 ^ 表示 [Ctrl] 那个按键的意思。举例来说， intr = ^C 表示利用 [ctrl] + c 来达成的。几个重要的代表意义是：

  • eof : End of file 的意思，代表‘结束输入’。
  • erase : 向后删除字元，
  • intr : 送出一个 interrupt (中断) 的讯号给目前正在 run 的程序；
  • kill : 删除在目前指令列上的所有文字；
  • quit : 送出一个 quit 的讯号给目前正在 run 的程序；
  • start : 在某个程序停止后，重新启动他的 output
  • stop : 停止目前荧幕的输出；
  • susp : 送出一个 terminal stop 的讯号给正在 run 的程序。

记不记得我们在第五章讲过几个 Linux 热键啊？没错！ 就是这个 stty 设定值内的 intr / eof 啰～至于删除字元，就是 erase 那个设定值啦！ 如果你想要用 [ctrl]+h 来进行字元的删除，那么可以下达：

[root@www ~]# stty erase ^h

那么从此之后，你的删除字元就得要使用 [ctrl]+h 啰，按下 [backspace] 则会出现 ^? 字样呢！ 如果想要回复利用 [backspace] ，就下达 stty erase ^? 即可啊！ 至于更多的 stty 说明，记得参考一下 man stty 的内容喔！

除了 stty 之外，其实我们的 bash 还有自己的一些终端机设定值呢！那就是利用 set 来设定的！ 我们之前提到一些变数时，可以利用 set 来显示，除此之外，其实 set 还可以帮我们设定整个指令输出/输入的环境。 例如记录历史命令、显示错误内容等等。

[root@www ~]# set [-uvCHhmBx]
选项与参数：
-u  ：预设不启用。若启用后，当使用未设定变数时，会显示错误讯息；
-v  ：预设不启用。若启用后，在讯息被输出前，会先显示讯息的原始内容；
-x  ：预设不启用。若启用后，在指令被执行前，会显示指令内容(前面有 ++ 符号)
-h  ：预设启用。与历史命令有关；
-H  ：预设启用。与历史命令有关；
-m  ：预设启用。与工作管理有关；
-B  ：预设启用。与刮号 [] 的作用有关；
-C  ：预设不启用。若使用 > 等，则若档案存在时，该档案不会被覆盖。

范例一：显示目前所有的 set 设定值
[root@www ~]# echo $-
himBH
# 那个 $- 变数内容就是 set 的所有设定啦！ bash 预设是 himBH 喔！

范例二：设定 "若使用未定义变数时，则显示错误讯息"
[root@www ~]# set -u
[root@www ~]# echo $vbirding
-bash: vbirding: unbound variable
# 预设情况下，未设定/未宣告 的变数都会是‘空的’，不过，若设定 -u 参数，
# 那么当使用未设定的变数时，就会有问题啦！很多的 shell 都预设启用 -u 参数。
# 若要取消这个参数，输入 set +u 即可！

范例三：执行前，显示该指令内容。
[root@www ~]# set -x

[root@www ~]# echo $HOME
+ echo /root
/root
++ echo -ne '\033]0;root@www:~'
# 看见否？要输出的指令都会先被列印到荧幕上喔！前面会多出 + 的符号！

另外，其实我们还有其他的按键设定功能呢！就是在前一小节提到的 /etc/inputrc 这个档案里面设定。

[root@www ~]# cat /etc/inputrc
# do not bell on tab-completion
#set bell-style none

set meta-flag on
set input-meta on
set convert-meta off
set output-meta on

.....以下省略.....

还有例如 /etc/DIR_COLORS* 与 /etc/termcap 等，也都是与终端机有关的环境设定档案呢！ 不过，事实上，鸟哥并不建议您修改 tty 的环境呢，这是因为 bash 的环境已经设定的很亲和了， 我们不需要额外的设定或者修改，否则反而会产生一些困扰。不过，写在这里的资料， 只是希望大家能够清楚的知道我们的终端机是如何进行设定的喔！ ^_^！ 最后，我们将 bash 预设的组合键给他汇整如下：

组合按键 | 执行结果
Ctrl + C | 终止目前的命令
Ctrl + D | 输入结束 (EOF)，例如邮件结束的时候；
Ctrl + M | 就是 Enter 啦！
Ctrl + S | 暂停荧幕的输出
Ctrl + Q | 恢复荧幕的输出
Ctrl + U | 在提示字元下，将整列命令删除
Ctrl + Z | ‘暂停’目前的命令

小标题的图示 万用字元与特殊符号

在 bash 的操作环境中还有一个非常有用的功能，那就是万用字元 (wildcard) ！ 我们利用 bash 处理资料就更方便了！底下我们列出一些常用的万用字元喔：

符号 | 意义
* | 代表‘ 0 个到无穷多个’任意字元
? | 代表‘一定有一个’任意字元
[ ] | 同样代表‘一定有一个在括号内’的字元(非任意字元)。例如 [abcd] 代表‘一定有一个字元， 可能是 a, b, c, d 这四个任何一个’
[ - ] | 若有减号在中括号内时，代表‘在编码顺序内的所有字元’。例如 [0-9] 代表 0 到 9 之间的所有数字，因为数字的语系编码是连续的！
[^ ] | 若中括号内的第一个字元为指数符号 (^) ，那表示‘反向选择’，例如 [^abc] 代表 一定有一个字元，只要是非 a, b, c 的其他字元就接受的意思。

接下来让我们利用万用字元来玩些东西吧！首先，利用万用字元配合 ls 找档名看看：

[root@www ~]# LANG=C              <==由于与编码有关，先设定语系一下

范例一：找出 /etc/ 底下以 cron 为开头的档名
[root@www ~]# ll -d /etc/cron*    <==加上 -d 是为了仅显示目录而已

范例二：找出 /etc/ 底下档名‘刚好是五个字母’的档名

[root@www ~]# ll -d /etc/?????    <==由于 ? 一定有一个，所以五个 ? 就对了

范例三：找出 /etc/ 底下档名含有数字的档名
[root@www ~]# ll -d /etc/*[0-9]*  <==记得中括号左右两边均需 *

范例四：找出 /etc/ 底下，档名开头非为小写字母的档名：
[root@www ~]# ll -d /etc/[^a-z]*  <==注意中括号左边没有 *

范例五：将范例四找到的档案复制到 /tmp 中
[root@www ~]# cp -a /etc/[^a-z]* /tmp

除了万用字元之外，bash 环境中的特殊符号有哪些呢？底下我们先汇整一下：

符号 | 内容
# | 注解符号：这个最常被使用在 script 当中，视为说明！在后的资料均不执行
\ | 跳脱符号：将‘特殊字元或万用字元’还原成一般字元
| | 管线 (pipe)：分隔两个管线命令的界定(后两节介绍)；
; | 连续指令下达分隔符号：连续性命令的界定 (注意！与管线命令并不相同)
~ | 使用者的家目录
$ | 取用变数前置字元：亦即是变数之前需要加的变数取代值
& | 工作控制 (job control)：将指令变成背景下工作
! | 逻辑运算意义上的‘非’ not 的意思！
/ | 目录符号：路径分隔的符号
>, >> | 资料流重导向：输出导向，分别是‘取代’与‘累加’
<, << | 资料流重导向：输入导向 (这两个留待下节介绍)
' ' | 单引号，不具有变数置换的功能
" " | 具有变数置换的功能！
` ` | 两个‘ ` ’中间为可以先执行的指令，亦可使用 $( )
( ) | 在中间为子 shell 的起始与结束
{ } | 在中间为命令区块的组合！

以上为 bash 环境中常见的特殊符号汇整！理论上，你的‘档名’尽量不要使用到上述的字元啦！

大标题的图示 资料流重导向

资料流重导向 (redirect) 由字面上的意思来看，好像就是将‘资料给他传导到其他地方去’的样子？ 没错～资料流重导向就是将某个指令执行后应该要出现在荧幕上的资料， 给他传输到其他的地方，例如档案或者是装置 (例如印表机之类的)！这玩意儿在 Linux 的文字模式底下可重要的！ 尤其是如果我们想要将某些资料储存下来时，就更有用了！

小标题的图示 什么是资料流重导向

什么是资料流重导向啊？这得要由指令的执行结果谈起！一般来说，如果你要执行一个指令，通常他会是这样的：

指令执行过程的资料传输情况
图 5.1.1、指令执行过程的资料传输情况

我们执行一个指令的时候，这个指令可能会由档案读入资料，经过处理之后，再将资料输出到荧幕上。 在上图当中， standard output 与 standard error output 分别代表‘标准输出’与‘标准错误输出’， 这两个玩意儿预设都是输出到荧幕上面来的啊！那么什么是标准输出与标准错误输出呢？

  • standard output 与 standard error output

简单的说，标准输出指的是‘指令执行所回传的正确的讯息’，而标准错误输出可理解为‘ 指令执行失败后，所回传的错误讯息’。举个简单例子来说，我们的系统预设有 /etc/crontab 但却无 /etc/vbirdsay， 此时若下达‘ cat /etc/crontab /etc/vbirdsay ’这个指令时，cat 会进行：

  • 标准输出：读取 /etc/crontab 后，将该档案内容显示到荧幕上；
  • 标准错误输出：因为无法找到 /etc/vbirdsay，因此在荧幕上显示错误讯息

不管正确或错误的资料都是预设输出到荧幕上，所以荧幕当然是乱乱的！那能不能透过某些机制将这两股资料分开呢？ 当然可以啊！那就是资料流重导向的功能啊！资料流重导向可以将 standard output (简称 stdout) 与 standard error output (简称 stderr) 分别传送到其他的档案或装置去，而分别传送所用的特殊字元则如下所示：

  1. 标准输入　　(stdin) ：代码为 0 ，使用 < 或 << ；
  2. 标准输出　　(stdout)：代码为 1 ，使用 > 或 >> ；
  3. 标准错误输出(stderr)：代码为 2 ，使用 2> 或 2>> ；

为了理解 stdout 与 stderr ，我们先来进行一个范例的练习：

范例一：观察你的系统根目录 (/) 下各目录的档名、权限与属性，并记录下来
[root@www ~]# ll /  <==此时荧幕会显示出档名资讯

[root@www ~]# ll / > ~/rootfile <==荧幕并无任何资讯

[root@www ~]# ll  ~/rootfile <==有个新档被建立了！
-rw-r--r-- 1 root root 1089 Feb  6 17:00 /root/rootfile

怪了！荧幕怎么会完全没有资料呢？这是因为原本‘ ll / ’所显示的资料已经被重新导向到 ~/rootfile 档案中了！ 那个 ~/rootfile 的档名可以随便你取。如果你下达‘ cat ~/rootfile ’那就可以看到原本应该在荧幕上面的资料啰。 如果我再次下达：‘ ll /home > ~/rootfile ’后，那个 ~/rootfile 档案的内容变成什么？ 他将变成‘仅有 ll /home 的资料’而已！咦！原本的‘ ll / ’资料就不见了吗？是的！因为该档案的建立方式是：

  1. 该档案 (本例中是 ~/rootfile) 若不存在，系统会自动的将他建立起来，但是
  2. 当这个档案存在的时候，那么系统就会先将这个档案内容清空，然后再将资料写入！
  3. 也就是若以 > 输出到一个已存在的档案中，那个档案就会被覆盖掉啰！

那如果我想要将资料累加而不想要将旧的资料删除，那该如何是好？利用两个大于的符号 (>>) 就好啦！以上面的范例来说，你应该要改成‘ ll / >> ~/rootfile ’即可。 如此一来，当 (1) ~/rootfile 不存在时系统会主动建立这个档案；(2)若该档案已存在， 则资料会在该档案的最下方累加进去！

上面谈到的是 standard output 的正确资料，那如果是 standard error output 的错误资料呢？那就透过 2> 及 2>> 啰！同样是覆盖 (2>) 与累加 (2>>) 的特性！我们在刚刚才谈到 stdout 代码是 1 而 stderr 代码是 2 ， 所以这个 2> 是很容易理解的，而如果仅存在 > 时，则代表预设的代码 1 啰！也就是说：

  • 1> ：以覆盖的方法将‘正确的资料’输出到指定的档案或装置上；
  • 1>>：以累加的方法将‘正确的资料’输出到指定的档案或装置上；
  • 2> ：以覆盖的方法将‘错误的资料’输出到指定的档案或装置上；
  • 2>>：以累加的方法将‘错误的资料’输出到指定的档案或装置上；

要注意喔，‘ 1>> ‘以及‘ 2>> ’中间是没有空格的！OK！有些概念之后让我们继续聊一聊这家伙怎么应用吧！ 当你以一般身份执行 find 这个指令的时候，由于权限的问题可能会产生一些错误资讯。例如执行‘ find / -name testing ’时，可能会产生类似‘ find: /root: Permission denied ’之类的讯息。 例如底下这个范例：

范例二：利用一般身份帐号搜寻 /home 底下是否有名为 .bashrc 的档案存在
[root@www ~]# su - dmtsai  <==假设我的系统有名为 dmtsai 的帐号
[dmtsai@www ~]$ find /home -name .bashrc <==身份是 dmtsai 喔！
find: /home/lost+found: Permission denied  <== Starndard error

find: /home/alex: Permission denied        <== Starndard error
find: /home/arod: Permission denied        <== Starndard error
/home/dmtsai/.bashrc                       <== Starndard output

由于 /home 底下还有我们之前建立的帐号存在，那些帐号的家目录你当然不能进入啊！所以就会有错误及正确资料了。 好了，那么假如我想要将资料输出到 list 这个档案中呢？执行‘ find /home -name .bashrc > list ’ 会有什么结果？呵呵，你会发现 list 里面存了刚刚那个‘正确’的输出资料， 至于荧幕上还是会有错误的讯息出现呢！伤脑筋！如果想要将正确的与错误的资料分别存入不同的档案中需要怎么做？

范例三：承范例二，将 stdout 与 stderr 分存到不同的档案去
[dmtsai@www ~]$ find /home -name .bashrc > list_right 2> list_error

注意喔，此时‘荧幕上不会出现任何讯息’！因为刚刚执行的结果中，有 Permission 的那几行错误资讯都会跑到 list_error 这个档案中，至于正确的输出资料则会存到 list_right 这个档案中啰！这样可以了解了吗？ 如果有点混乱的话，去休息一下再来看看吧！

  • /dev/null 垃圾桶黑洞装置与特殊写法

想像一下，如果我知道错误讯息会发生，所以要将错误讯息忽略掉而不显示或储存呢？ 这个时候黑洞装置 /dev/null 就很重要了！这个 /dev/null 可以吃掉任何导向这个装置的资讯喔！将上述的范例修订一下：

范例四：承范例三，将错误的资料丢弃，荧幕上显示正确的资料
[dmtsai@www ~]$ find /home -name .bashrc 2> /dev/null
/home/dmtsai/.bashrc  <==只有 stdout 会显示到荧幕上， stderr 被丢弃了

再想像一下，如果我要将正确与错误资料通通写入同一个档案去呢？这个时候就得要使用特殊的写法了！ 我们同样用底下的案例来说明：

范例五：将指令的资料全部写入名为 list 的档案中
[dmtsai@www ~]$ find /home -name .bashrc > list 2> list  <==错误

[dmtsai@www ~]$ find /home -name .bashrc > list 2>&1     <==正确
[dmtsai@www ~]$ find /home -name .bashrc &> list         <==正确

上述表格第一行错误的原因是，由于两股资料同时写入一个档案，又没有使用特殊的语法， 此时两股资料可能会交叉写入该档案内，造成次序的错乱。所以虽然最终 list 档案还是会产生，但是里面的资料排列就会怪怪的，而不是原本荧幕上的输出排序。 至于写入同一个档案的特殊语法如上表所示，你可以使用 2>&1 也可以使用 &> ！ 一般来说，鸟哥比较习惯使用 2>&1 的语法啦！

  • standard input ： < 与 <<

了解了 stderr 与 stdout 后，那么那个 < 又是什么呀？呵呵！以最简单的说法来说， 那就是‘将原本需要由键盘输入的资料，改由档案内容来取代’的意思。 我们先由底下的 cat 指令操作来了解一下什么叫做‘键盘输入’吧！

范例六：利用 cat 指令来建立一个档案的简单流程
[root@www ~]# cat > catfile
testing
cat file test
<==这里按下 [ctrl]+d 来离开

[root@www ~]# cat catfile

testing
cat file test

由于加入 > 在 cat 后，所以那个 catfile 会被主动的建立，而内容就是刚刚键盘上面输入的那两行资料了。 唔！那我能不能用纯文字档取代键盘的输入，也就是说，用某个档案的内容来取代键盘的敲击呢？ 可以的！如下所示：

范例七：用 stdin 取代键盘的输入以建立新档案的简单流程
[root@www ~]# cat > catfile < ~/.bashrc

[root@www ~]# ll catfile ~/.bashrc
-rw-r--r-- 1 root root 194 Sep 26 13:36 /root/.bashrc
-rw-r--r-- 1 root root 194 Feb  6 18:29 catfile
# 注意看，这两个档案的大小会一模一样！几乎像是使用 cp 来复制一般！

这东西非常的有帮助！尤其是用在类似 mail 这种指令的使用上。 理解 < 之后，再来则是怪可怕一把的 << 这个连续两个小于的符号了。 他代表的是‘结束的输入字元’的意思！举例来讲：‘我要用 cat 直接将输入的讯息输出到 catfile 中， 且当由键盘输入 eof 时，该次输入就结束’，那我可以这样做：

[root@www ~]# cat > catfile << "eof"
> This is a test.
> OK now stop
> eof  <==输入这关键字，立刻就结束而不需要输入 [ctrl]+d

[root@www ~]# cat catfile
This is a test.
OK now stop     <==只有这两行，不会存在关键字那一行！

看到了吗？利用 << 右侧的控制字元，我们可以终止一次输入， 而不必输入 [crtl]+d 来结束哩！这对程式写作很有帮助喔！好了，那么为何要使用命令输出重导向呢？我们来说一说吧！

  • 荧幕输出的资讯很重要，而且我们需要将他存下来的时候；
  • 背景执行中的程式，不希望他干扰荧幕正常的输出结果时；
  • 一些系统的例行命令 (例如写在 /etc/crontab 中的档案) 的执行结果，希望他可以存下来时；
  • 一些执行命令的可能已知错误讯息时，想以‘ 2> /dev/null ’将他丢掉时；
  • 错误讯息与正确讯息需要分别输出时。

当然还有很多的功能的，最简单的就是网友们常常问到的：‘为何我的 root 都会收到系统 crontab 寄来的错误讯息呢’这个咚咚是常见的错误， 而如果我们已经知道这个错误讯息是可以忽略的时候，嗯！‘ 2> errorfile ’这个功能就很重要了吧！ 了解了吗？

小标题的图示 命令执行的判断依据： ; , &&, ||

在某些情况下，很多指令我想要一次输入去执行，而不想要分次执行时，该如何是好？基本上你有两个选择， 一个是透过第十三章要介绍的 shell script 撰写脚本去执行，一种则是透过底下的介绍来一次输入多重指令喔！

  • cmd ; cmd (不考虑指令相关性的连续指令下达)

在某些时候，我们希望可以一次执行多个指令，例如在关机的时候我希望可以先执行两次 sync 同步化写入磁碟后才 shutdown 电脑，那么可以怎么作呢？这样做呀：

[root@www ~]# sync; sync; shutdown -h now

在指令与指令中间利用分号 (;) 来隔开，这样一来，分号前的指令执行完后就会立刻接着执行后面的指令了。 这真是方便啊～再来，换个角度来想，万一我想要在某个目录底下建立一个档案，也就是说，如果该目录存在的话， 那我才建立这个档案，如果不存在，那就算了。也就是说这两个指令彼此之间是有相关性的， 前一个指令是否成功的执行与后一个指令是否要执行有关！那就得动用到 && 或 || 啰！

  • $? (指令回传值) 与 && 或 ||

如同上面谈到的，两个指令之间有相依性，而这个相依性主要判断的地方就在于前一个指令执行的结果是否正确。 还记得本章之前我们曾介绍过指令回传值吧！嘿嘿！没错，您真聪明！就是透过这个回传值啦！ 再复习一次‘若前一个指令执行的结果为正确，在 Linux 底下会回传一个 $? = 0 的值’。 那么我们怎么透过这个回传值来判断后续的指令是否要执行呢？这就得要藉由‘ && ’及‘ || ’的帮忙了！ 注意喔，两个 & 之间是没有空格的！那个 | 则是 [Shift]+[\] 的按键结果。

指令下达情况 | 说明
cmd1 && cmd2 | 1. 若 cmd1 执行完毕且正确执行($?=0)，则开始执行 cmd2。 2. 若 cmd1 执行完毕且为错误 ($?≠0)，则 cmd2 不执行。
cmd1 || cmd2 | 1. 若 cmd1 执行完毕且正确执行($?=0)，则 cmd2 不执行。 2. 若 cmd1 执行完毕且为错误 ($?≠0)，则开始执行 cmd2。

上述的 cmd1 及 cmd2 都是指令。好了，回到我们刚刚假想的情况，就是想要： (1)先判断一个目录是否存在； (2)若存在才在该目录底下建立一个档案。由于我们尚未介绍如何判断式 (test) 的使用，在这里我们使用 ls 以及回传值来判断目录是否存在啦！ 让我们进行底下这个练习看看：

范例一：使用 ls 查阅目录 /tmp/abc 是否存在，若存在则用 touch 建立 /tmp/abc/hehe
[root@www ~]# ls /tmp/abc && touch /tmp/abc/hehe
ls: /tmp/abc: No such file or directory

# ls 很干脆的说明找不到该目录，但并没有 touch 的错误，表示 touch 并没有执行

[root@www ~]# mkdir /tmp/abc
[root@www ~]# ls /tmp/abc && touch /tmp/abc/hehe
[root@www ~]# ll /tmp/abc
-rw-r--r-- 1 root root 0 Feb  7 12:43 hehe

看到了吧？如果 /tmp/abc 不存在时，touch 就不会被执行，若 /tmp/abc 存在的话，那么 touch 就会开始执行啰！ 很不错用吧！不过，我们还得手动自行建立目录，伤脑筋～能不能自动判断，如果没有该目录就给予建立呢？ 参考一下底下的例子先：

范例二：测试 /tmp/abc 是否存在，若不存在则予以建立，若存在就不作任何事情
[root@www ~]# rm -r /tmp/abc                <==先删除此目录以方便测试
[root@www ~]# ls /tmp/abc || mkdir /tmp/abc
ls: /tmp/abc: No such file or directory <==真的不存在喔！

[root@www ~]# ll /tmp/abc
total 0                                 <==结果出现了！有进行 mkdir

如果你一再重复‘ ls /tmp/abc || mkdir /tmp/abc ’画面也不会出现重复 mkdir 的错误！这是因为 /tmp/abc 已经存在， 所以后续的 mkdir 就不会进行！这样理解否？好了，让我们再次的讨论一下，如果我想要建立 /tmp/abc/hehe 这个档案， 但我并不知道 /tmp/abc 是否存在，那该如何是好？试看看：

范例三：我不清楚 /tmp/abc 是否存在，但就是要建立 /tmp/abc/hehe 档案
[root@www ~]# ls /tmp/abc || mkdir /tmp/abc && touch /tmp/abc/hehe

上面这个范例三总是会建立 /tmp/abc/hehe 的喔！不论 /tmp/abc 是否存在。那么范例三应该如何解释呢？ 由于Linux 底下的指令都是由左往右执行的，所以范例三有几种结果我们来分析一下：

  • (1)若 /tmp/abc 不存在故回传 $?≠0，则 (2)因为 || 遇到非为 0 的 $? 故开始 mkdir /tmp/abc，由于 mkdir /tmp/abc 会成功进行，所以回传 $?=0 (3)因为 && 遇到 $?=0 故会执行 touch /tmp/abc/hehe，最终 hehe 就被建立了；

  • (1)若 /tmp/abc 存在故回传 $?=0，则 (2)因为 || 遇到 0 的 $? 不会进行，此时 $?=0 继续向后传，故 (3)因为 && 遇到 $?=0 就开始建立 /tmp/abc/hehe 了！最终 /tmp/abc/hehe 被建立起来。

整个流程图示如下：

指令依序执行的关系示意图
图 5.2.1、 指令依序执行的关系示意图

上面这张图显示的两股资料中，上方的线段为不存在 /tmp/abc 时所进行的指令行为，下方的线段则是存在 /tmp/abc 所在的指令行为。如上所述，下方线段由于存在 /tmp/abc 所以导致 $?=0 ，让中间的 mkdir 就不执行了！ 并将 $?=0 继续往后传给后续的 touch 去利用啦！了乎？在任何时刻你都可以拿上面这张图作为示意！ 让我们来想想底下这个例题吧！

例题：
以 ls 测试 /tmp/vbirding 是否存在，若存在则显示 "exist" ，若不存在，则显示 "not exist"！
答：
这又牵涉到逻辑判断的问题，如果存在就显示某个资料，若不存在就显示其他资料，那我可以这样做：
ls /tmp/vbirding && echo "exist" || echo "not exist"
意思是说，当 ls /tmp/vbirding 执行后，若正确，就执行 echo "exist" ，若有问题，就执行 echo "not exist" ！那如果写成如下的状况会出现什么？
ls /tmp/vbirding || echo "not exist" && echo "exist"
这其实是有问题的，为什么呢？由图 5.2.1 的流程介绍我们知道指令是一个一个往后执行， 因此在上面的例子当中，如果 /tmp/vbirding 不存在时，他会进行如下动作：
  1. 若 ls /tmp/vbirding 不存在，因此回传一个非为 0 的数值；
  2. 接下来经过 || 的判断，发现前一个指令回传非为 0 的数值，因此，程式开始执行 echo "not exist" ，而 echo "not exist" 程式肯定可以执行成功，因此会回传一个 0 值给后面的指令；
  3. 经过 && 的判断，咦！是 0 啊！所以就开始执行 echo "exist" 。
所以啊，嘿嘿！第二个例子里面竟然会同时出现 not exist 与 exist 呢！真神奇～

经过这个例题的练习，你应该会了解，由于指令是一个接着一个去执行的，因此，如果真要使用判断， 那么这个 && 与 || 的顺序就不能搞错。一般来说，假设判断式有三个，也就是：

command1 && command2 || command3

而且顺序通常不会变，因为一般来说， command2 与 command3 会放置肯定可以执行成功的指令， 因此，依据上面例题的逻辑分析，您就会晓得为何要如此放置啰～这很有用的啦！而且.....考试也很常考～

大标题的图示 管线命令 (pipe)

就如同前面所说的， bash 命令执行的时候有输出的资料会出现！ 那么如果这群资料必需要经过几道手续之后才能得到我们所想要的格式，应该如何来设定？ 这就牵涉到管线命令的问题了 (pipe) ，管线命令使用的是‘ | ’这个界定符号！ 另外，管线命令与‘连续下达命令’是不一样的呦！ 这点底下我们会再说明。底下我们先举一个例子来说明一下简单的管线命令。

假设我们想要知道 /etc/ 底下有多少档案，那么可以利用 ls /etc 来查阅，不过， 因为 /etc 底下的档案太多，导致一口气就将荧幕塞满了～不知道前面输出的内容是啥？此时，我们可以透过 less 指令的协助，利用：

[root@www ~]# ls -al /etc | less

如此一来，使用 ls 指令输出后的内容，就能够被 less 读取，并且利用 less 的功能，我们就能够前后翻动相关的资讯了！很方便是吧？我们就来了解一下这个管线命令‘ | ’的用途吧！ 其实这个管线命令‘ | ’仅能处理经由前面一个指令传来的正确资讯，也就是 standard output 的资讯，对于 stdandard error 并没有直接处理的能力。那么整体的管线命令可以使用下图表示：

管线命令的处理示意图
图 6.1.1、 管线命令的处理示意图

在每个管线后面接的第一个资料必定是‘指令’喔！而且这个指令必须要能够接受 standard input 的资料才行，这样的指令才可以是为‘管线命令’，例如 less, more, head, tail 等都是可以接受 standard input 的管线命令啦。至于例如 ls, cp, mv 等就不是管线命令了！因为 ls, cp, mv 并不会接受来自 stdin 的资料。 也就是说，管线命令主要有两个比较需要注意的地方：

  • 管线命令仅会处理 standard output，对于 standard error output 会予以忽略
  • 管线命令必须要能够接受来自前一个指令的资料成为 standard input 继续处理才行。

多说无益，让我们来玩一些管线命令吧！底下的咚咚对系统管理非常有帮助喔！

小标题的图示 撷取命令： cut, grep

什么是撷取命令啊？说穿了，就是将一段资料经过分析后，取出我们所想要的。或者是经由分析关键字，取得我们所想要的那一行！ 不过，要注意的是，一般来说，撷取讯息通常是针对‘一行一行’来分析的， 并不是整篇讯息分析的喔～底下我们介绍两个很常用的讯息撷取命令：

  • cut

cut 不就是‘切’吗？没错啦！这个指令可以将一段讯息的某一段给他‘切’出来～ 处理的讯息是以‘行’为单位喔！底下我们就来谈一谈：

[root@www ~]# cut -d'分隔字元' -f fields <==用于有特定分隔字元
[root@www ~]# cut -c 字元区间            <==用于排列整齐的讯息
选项与参数：
-d  ：后面接分隔字元。与 -f 一起使用；
-f  ：依据 -d 的分隔字元将一段讯息分割成为数段，用 -f 取出第几段的意思；
-c  ：以字元 (characters) 的单位取出固定字元区间；

范例一：将 PATH 变数取出，我要找出第五个路径。
[root@www ~]# echo $PATH
/bin:/usr/bin:/sbin:/usr/sbin:/usr/local/bin:/usr/X11R6/bin:/usr/games:
# 1 |    2   |  3  |    4    |       5      |     6        |    7

[root@www ~]# echo $PATH | cut -d ':' -f 5
# 如同上面的数字显示，我们是以‘ : ’作为分隔，因此会出现 /usr/local/bin
# 那么如果想要列出第 3 与第 5 呢？，就是这样：
[root@www ~]# echo $PATH | cut -d ':' -f 3,5

范例二：将 export 输出的讯息，取得第 12 字元以后的所有字串
[root@www ~]# export
declare -x HISTSIZE="1000"
declare -x INPUTRC="/etc/inputrc"
declare -x KDEDIR="/usr"
declare -x LANG="zh_TW.big5"
.....(其他省略).....
# 注意看，每个资料都是排列整齐的输出！如果我们不想要‘ declare -x ’时，
# 就得这么做：

[root@www ~]# export | cut -c 12-
HISTSIZE="1000"
INPUTRC="/etc/inputrc"
KDEDIR="/usr"
LANG="zh_TW.big5"
.....(其他省略).....
# 知道怎么回事了吧？用 -c 可以处理比较具有格式的输出资料！
# 我们还可以指定某个范围的值，例如第 12-20 的字元，就是 cut -c 12-20 等等！

范例三：用 last 将显示的登入者的资讯中，仅留下使用者大名
[root@www ~]# last
root   pts/1    192.168.201.101  Sat Feb  7 12:35   still logged in
root   pts/1    192.168.201.101  Fri Feb  6 12:13 - 18:46  (06:33)
root   pts/1    192.168.201.254  Thu Feb  5 22:37 - 23:53  (01:16)
# last 可以输出‘帐号/终端机/来源/日期时间’的资料，并且是排列整齐的

[root@www ~]# last | cut -d ' ' -f 1
# 由输出的结果我们可以发现第一个空白分隔的栏位代表帐号，所以使用如上指令：
# 但是因为 root   pts/1 之间空格有好几个，并非仅有一个，所以，如果要找出
# pts/1 其实不能以 cut -d ' ' -f 1,2 喔！输出的结果会不是我们想要的。

cut 主要的用途在于将‘同一行里面的资料进行分解！’最常使用在分析一些数据或文字资料的时候！ 这是因为有时候我们会以某些字元当作分割的参数，然后来将资料加以切割，以取得我们所需要的资料。 鸟哥也很常使用这个功能呢！尤其是在分析 log 档案的时候！不过，cut 在处理多空格相连的资料时，可能会比较吃力一点。

  • grep

刚刚的 cut 是将一行讯息当中，取出某部分我们想要的，而 grep 则是分析一行讯息， 若当中有我们所需要的资讯，就将该行拿出来～简单的语法是这样的：

[root@www ~]# grep [-acinv] [--color=auto] '搜寻字串' filename
选项与参数：
-a ：将 binary 档案以 text 档案的方式搜寻资料
-c ：计算找到 '搜寻字串' 的次数
-i ：忽略大小写的不同，所以大小写视为相同
-n ：顺便输出行号
-v ：反向选择，亦即显示出没有 '搜寻字串' 内容的那一行！
--color=auto ：可以将找到的关键字部分加上颜色的显示喔！

范例一：将 last 当中，有出现 root 的那一行就取出来；
[root@www ~]# last | grep 'root'

范例二：与范例一相反，只要没有 root 的就取出！
[root@www ~]# last | grep -v 'root'

范例三：在 last 的输出讯息中，只要有 root 就取出，并且仅取第一栏
[root@www ~]# last | grep 'root' |cut -d ' ' -f1

# 在取出 root 之后，利用上个指令 cut 的处理，就能够仅取得第一栏啰！

范例四：取出 /etc/man.config 内含 MANPATH 的那几行
[root@www ~]# grep --color=auto 'MANPATH' /etc/man.config
....(前面省略)....
MANPATH_MAP     /usr/X11R6/bin          /usr/X11R6/man
MANPATH_MAP     /usr/bin/X11            /usr/X11R6/man
MANPATH_MAP     /usr/bin/mh             /usr/share/man
# 神奇的是，如果加上 --color=auto 的选项，找到的关键字部分会用特殊颜色显示喔！

grep 是个很棒的指令喔！他支援的语法实在是太多了～用在正规表示法里头， 能够处理的资料实在是多的很～不过，我们这里先不谈正规表示法～下一章再来说明～ 您先了解一下， grep 可以解析一行文字，取得关键字，若该行有存在关键字，就会整行列出来！

小标题的图示 排序命令： sort, wc, uniq

很多时候，我们都会去计算一次资料里头的相同型态的资料总数，举例来说， 使用 last 可以查得这个月份有登入主机者的身份。那么我可以针对每个使用者查出他们的总登入次数吗？ 此时就得要排序与计算之类的指令来辅助了！底下我们介绍几个好用的排序与统计指令喔！

  • sort

sort 是很有趣的指令，他可以帮我们进行排序，而且可以依据不同的资料型态来排序喔！ 例如数字与文字的排序就不一样。此外，排序的字元与语系的编码有关，因此， 如果您需要排序时，建议使用 LANG=C 来让语系统一，资料排序比较好一些。

[root@www ~]# sort [-fbMnrtuk] [file or stdin]
选项与参数：
-f  ：忽略大小写的差异，例如 A 与 a 视为编码相同；
-b  ：忽略最前面的空白字元部分；
-M  ：以月份的名字来排序，例如 JAN, DEC 等等的排序方法；
-n  ：使用‘纯数字’进行排序(预设是以文字型态来排序的)；
-r  ：反向排序；
-u  ：就是 uniq ，相同的资料中，仅出现一行代表；
-t  ：分隔符号，预设是用 [tab] 键来分隔；
-k  ：以那个区间 (field) 来进行排序的意思

范例一：个人帐号都记录在 /etc/passwd 下，请将帐号进行排序。
[root@www ~]# cat /etc/passwd | sort
adm:x:3:4:adm:/var/adm:/sbin/nologin
apache:x:48:48:Apache:/var/www:/sbin/nologin
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
# 鸟哥省略很多的输出～由上面的资料看起来， sort 是预设‘以第一个’资料来排序，
# 而且预设是以‘文字’型态来排序的喔！所以由 a 开始排到最后啰！

范例二：/etc/passwd 内容是以 : 来分隔的，我想以第三栏来排序，该如何？

[root@www ~]# cat /etc/passwd | sort -t ':' -k 3
root:x:0:0:root:/root:/bin/bash
uucp:x:10:14:uucp:/var/spool/uucp:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
bin:x:1:1:bin:/bin:/sbin/nologin
games:x:12:100:games:/usr/games:/sbin/nologin
# 看到特殊字体的输出部分了吧？怎么会这样排列啊？呵呵！没错啦～
# 如果是以文字型态来排序的话，原本就会是这样，想要使用数字排序：
# cat /etc/passwd | sort -t ':' -k 3 -n
# 这样才行啊！用那个 -n 来告知 sort 以数字来排序啊！

范例三：利用 last ，将输出的资料仅取帐号，并加以排序
[root@www ~]# last | cut -d ' ' -f1 | sort

sort 同样是很常用的指令呢！因为我们常常需要比较一些资讯啦！ 举个上面的第二个例子来说好了！今天假设你有很多的帐号，而且你想要知道最大的使用者 ID 目前到哪一号了！呵呵！使用 sort 一下子就可以知道答案咯！当然其使用还不止此啦！ 有空的话不妨玩一玩！

  • uniq

如果我排序完成了，想要将重复的资料仅列出一个显示，可以怎么做呢？

[root@www ~]# uniq [-ic]
选项与参数：
-i  ：忽略大小写字元的不同；
-c  ：进行计数

范例一：使用 last 将帐号列出，仅取出帐号栏，进行排序后仅取出一位；
[root@www ~]# last | cut -d ' ' -f1 | sort | uniq

范例二：承上题，如果我还想要知道每个人的登入总次数呢？
[root@www ~]# last | cut -d ' ' -f1 | sort | uniq -c
      1
     12 reboot
     41 root
      1 wtmp
# 从上面的结果可以发现 reboot 有 12 次， root 登入则有 41 次！
# wtmp 与第一行的空白都是 last 的预设字元，那两个可以忽略的！

这个指令用来将‘重复的行删除掉只显示一个’，举个例子来说， 你要知道这个月份登入你主机的使用者有谁，而不在乎他的登入次数，那么就使用上面的范例， (1)先将所有的资料列出；(2)再将人名独立出来；(3)经过排序；(4)只显示一个！ 由于这个指令是在将重复的东西减少，所以当然需要‘配合排序过的档案’来处理啰！

  • wc

如果我想要知道 /etc/man.config 这个档案里面有多少字？多少行？多少字元的话， 可以怎么做呢？其实可以利用 wc 这个指令来达成喔！他可以帮我们计算输出的讯息的整体资料！

[root@www ~]# wc [-lwm]
选项与参数：
-l  ：仅列出行；
-w  ：仅列出多少字(英文单字)；
-m  ：多少字元；

范例一：那个 /etc/man.config 里面到底有多少相关字、行、字元数？

[root@www ~]# cat /etc/man.config | wc
    141     722    4617
# 输出的三个数字中，分别代表： ‘行、字数、字元数’

范例二：我知道使用 last 可以输出登入者，但是 last 最后两行并非帐号内容，
        那么请问，我该如何以一行指令串取得这个月份登入系统的总人次？
[root@www ~]# last | grep [a-zA-Z] | grep -v 'wtmp' | wc -l
# 由于 last 会输出空白行与 wtmp 字样在最底下两行，因此，我利用
# grep 取出非空白行，以及去除 wtmp 那一行，在计算行数，就能够了解啰！

wc 也可以当作指令？这可不是上洗手间的 WC 呢！这是相当有用的计算档案内容的一个工具组喔！举个例子来说， 当你要知道目前你的帐号档案中有多少个帐号时，就使用这个方法：‘ cat /etc/passwd | wc -l ’啦！因为 /etc/passwd 里头一行代表一个使用者呀！ 所以知道行数就晓得有多少的帐号在里头了！而如果要计算一个档案里头有多少个字元时，就使用 wc -c 这个选项吧！

小标题的图示 双向重导向： tee

想个简单的东西，我们由前一节知道 > 会将资料流整个传送给档案或装置，因此我们除非去读取该档案或装置， 否则就无法继续利用这个资料流。万一我想要将这个资料流的处理过程中将某段讯息存下来，应该怎么做？ 利用 tee 就可以啰～我们可以这样简单的看一下：

tee 的工作流程示意图
图 6.3.1、tee 的工作流程示意图

tee 会同时将资料流分送到档案去与荧幕 (screen)；而输出到荧幕的，其实就是 stdout ，可以让下个指令继续处理喔！

[root@www ~]# tee [-a] file
选项与参数：
-a  ：以累加 (append) 的方式，将资料加入 file 当中！

[root@www ~]# last | tee last.list | cut -d " " -f1
# 这个范例可以让我们将 last 的输出存一份到 last.list 档案中；

[root@www ~]# ls -l /home | tee ~/homefile | more
# 这个范例则是将 ls 的资料存一份到 ~/homefile ，同时荧幕也有输出讯息！

[root@www ~]# ls -l / | tee -a ~/homefile | more
# 要注意！ tee 后接的档案会被覆盖，若加上 -a 这个选项则能将讯息累加。

tee 可以让 standard output 转存一份到档案内并将同样的资料继续送到荧幕去处理！ 这样除了可以让我们同时分析一份资料并记录下来之外，还可以作为处理一份资料的中间暂存档记录之用！ tee 这家伙在很多选择/填充的认证考试中很容易考呢！

小标题的图示 字元转换命令： tr, col, join, paste, expand

我们在 vim 程式编辑器当中，提到过 DOS 断行字元与 Unix 断行字元的不同，并且可以使用 dos2unix 与 unix2dos 来完成转换。好了，那么思考一下，是否还有其他常用的字元替代？ 举例来说，要将大写改成小写，或者是将资料中的 [tab] 按键转成空白键？还有，如何将两篇讯息整合成一篇？ 底下我们就来介绍一下这些字元转换命令在管线当中的使用方法：

  • tr

tr 可以用来删除一段讯息当中的文字，或者是进行文字讯息的替换！

[root@www ~]# tr [-ds] SET1 ...
选项与参数：
-d  ：删除讯息当中的 SET1 这个字串；
-s  ：取代掉重复的字元！

范例一：将 last 输出的讯息中，所有的小写变成大写字元：
[root@www ~]# last | tr '[a-z]' '[A-Z]'
# 事实上，没有加上单引号也是可以执行的，如：‘ last | tr [a-z] [A-Z] ’

范例二：将 /etc/passwd 输出的讯息中，将冒号 (:) 删除
[root@www ~]# cat /etc/passwd | tr -d ':'

范例三：将 /etc/passwd 转存成 dos 断行到 /root/passwd 中，再将 ^M 符号删除

[root@www ~]# cp /etc/passwd /root/passwd && unix2dos /root/passwd
[root@www ~]# file /etc/passwd /root/passwd
/etc/passwd:  ASCII text
/root/passwd: ASCII text, with CRLF line terminators <==就是 DOS 断行
[root@www ~]# cat /root/passwd | tr -d '\r' > /root/passwd.linux
# 那个 \r 指的是 DOS 的断行字元，关于更多的字符，请参考 man tr

[root@www ~]# ll /etc/passwd /root/passwd*
-rw-r--r-- 1 root root 1986 Feb  6 17:55 /etc/passwd
-rw-r--r-- 1 root root 2030 Feb  7 15:55 /root/passwd
-rw-r--r-- 1 root root 1986 Feb  7 15:57 /root/passwd.linux
# 处理过后，发现档案大小与原本的 /etc/passwd 就一致了！

其实这个指令也可以写在‘正规表示法’里头！因为他也是由正规表示法的方式来取代资料的！ 以上面的例子来说，使用 [] 可以设定一串字呢！也常常用来取代档案中的怪异符号！ 例如上面第三个例子当中，可以去除 DOS 档案留下来的 ^M 这个断行的符号！这东西相当的有用！相信处理 Linux & Windows 系统中的人们最麻烦的一件事就是这个事情啦！亦即是 DOS 底下会自动的在每行行尾加入 ^M 这个断行符号！这个时候我们可以使用这个 tr 来将 ^M 去除！ ^M 可以使用 \r 来代替之！

  • col
[root@www ~]# col [-xb]

选项与参数：
-x  ：将 tab 键转换成对等的空白键
-b  ：在文字内有反斜线 (/) 时，仅保留反斜线最后接的那个字元

范例一：利用 cat -A 显示出所有特殊按键，最后以 col 将 [tab] 转成空白
[root@www ~]# cat -A /etc/man.config  <==此时会看到很多 ^I 的符号，那就是 tab
[root@www ~]# cat /etc/man.config | col -x | cat -A | more
# 嘿嘿！如此一来， [tab] 按键会被取代成为空白键，输出就美观多了！

范例二：将 col 的 man page 转存成为 /root/col.man 的纯文字档

[root@www ~]# man col > /root/col.man
[root@www ~]# vi /root/col.man
COL(1)          BSD General Commands Manual               COL(1)

N^HNA^HAM^HME^HE
     c^Hco^Hol^Hl - filter reverse line feeds from input

S^HSY^HYN^HNO^HOP^HPS^HSI^HIS^HS
     c^Hco^Hol^Hl [-^H-b^Hbf^Hfp^Hpx^Hx] [-^H-l^Hl _^Hn_^Hu_^Hm]
# 你没看错！由于 man page 内有些特殊按钮会用来作为类似特殊按键与颜色显示，
# 所以这个档案内就会出现如上所示的一堆怪异字元(有 ^ 的)

[root@www ~]# man col | col -b > /root/col.man

虽然 col 有他特殊的用途，不过，很多时候，他可以用来简单的处理将 [tab] 按键取代成为空白键！ 例如上面的例子当中，如果使用 cat -A 则 [tab] 会以 ^I 来表示。 但经过 col -x 的处理，则会将 [tab] 取代成为对等的空白键！此外， col 经常被利用于将 man page 转存为纯文字档以方便查阅的功能！如上述的范例二！

  • join

join 看字面上的意义 (加入/参加) 就可以知道，他是在处理两个档案之间的资料， 而且，主要是在处理‘两个档案当中，有 "相同资料" 的那一行，才将他加在一起’的意思。我们利用底下的简单例子来说明：

[root@www ~]# join [-ti12] file1 file2
选项与参数：
-t  ：join 预设以空白字元分隔资料，并且比对‘第一个栏位’的资料，
      如果两个档案相同，则将两笔资料联成一行，且第一个栏位放在第一个！
-i  ：忽略大小写的差异；
-1  ：这个是数字的 1 ，代表‘第一个档案要用那个栏位来分析’的意思；
-2  ：代表‘第二个档案要用那个栏位来分析’的意思。

范例一：用 root 的身份，将 /etc/passwd 与 /etc/shadow 相关资料整合成一栏
[root@www ~]# head -n 3 /etc/passwd /etc/shadow
==> /etc/passwd <==
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin

==> /etc/shadow <==
root:$1$/3AQpE5e$y9A/D0bh6rElAs:14120:0:99999:7:::
bin:*:14126:0:99999:7:::
daemon:*:14126:0:99999:7:::

# 由输出的资料可以发现这两个档案的最左边栏位都是帐号！且以 : 分隔

[root@www ~]# join -t ':' /etc/passwd /etc/shadow
root:x:0:0:root:/root:/bin/bash:$1$/3AQpE5e$y9A/D0bh6rElAs:14120:0:99999:7:::
bin:x:1:1:bin:/bin:/sbin/nologin:*:14126:0:99999:7:::
daemon:x:2:2:daemon:/sbin:/sbin/nologin:*:14126:0:99999:7:::

# 透过上面这个动作，我们可以将两个档案第一栏位相同者整合成一行！
# 第二个档案的相同栏位并不会显示(因为已经在第一行了嘛！)

范例二：我们知道 /etc/passwd 第四个栏位是 GID ，那个 GID 记录在
        /etc/group 当中的第三个栏位，请问如何将两个档案整合？
[root@www ~]# head -n 3 /etc/passwd /etc/group
==> /etc/passwd <==
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin

==> /etc/group <==
root:x:0:root
bin:x:1:root,bin,daemon
daemon:x:2:root,bin,daemon

# 从上面可以看到，确实有相同的部分喔！赶紧来整合一下！

[root@www ~]#
[root@www ~]#
[root@www ~]# join -t ':' -1 4 /etc/passwd -2 3 /etc/group
0:root:x:0:root:/root:/bin/bash:root:x:root
1:bin:x:1:bin:/bin:/sbin/nologin:bin:x:root,bin,daemon

2:daemon:x:2:daemon:/sbin:/sbin/nologin:daemon:x:root,bin,daemon
# 同样的，相同的栏位部分被移动到最前面了！所以第二个档案的内容就没再显示。
# 请读者们配合上述显示两个档案的实际内容来比对！

这个 join 在处理两个相关的资料档案时，就真的是很有帮助的啦！ 例如上面的案例当中，我的 /etc/passwd, /etc/shadow, /etc/group 都是有相关性的， 其中 /etc/passwd, /etc/shadow 以帐号为相关性，至于 /etc/passwd, /etc/group 则以所谓的 GID (帐号的数字定义) 来作为他的相关性。根据这个相关性， 我们可以将有关系的资料放置在一起！这在处理资料可是相当有帮助的！ 但是上面的例子有点难，希望您可以静下心好好的看一看原因喔！

此外，需要特别注意的是，在使用 join 之前，你所需要处理的档案应该要事先经过排序 (sort) 处理！ 否则有些比对的项目会被略过呢！特别注意了！

  • paste

这个 paste 就要比 join 简单多了！相对于 join 必须要比对两个档案的资料相关性， paste 就直接‘将两行贴在一起，且中间以 [tab] 键隔开’而已！简单的使用方法：

[root@www ~]# paste [-d] file1 file2

选项与参数：
-d  ：后面可以接分隔字元。预设是以 [tab] 来分隔的！
-   ：如果 file 部分写成 - ，表示来自 standard input 的资料的意思。

范例一：将 /etc/passwd 与 /etc/shadow 同一行贴在一起
[root@www ~]# paste /etc/passwd /etc/shadow
bin:x:1:1:bin:/bin:/sbin/nologin        bin:*:14126:0:99999:7:::
daemon:x:2:2:daemon:/sbin:/sbin/nologin daemon:*:14126:0:99999:7:::
adm:x:3:4:adm:/var/adm:/sbin/nologin    adm:*:14126:0:99999:7:::
# 注意喔！同一行中间是以 [tab] 按键隔开的！

范例二：先将 /etc/group 读出(用 cat)，然后与范例一贴上一起！且仅取出前三行
[root@www ~]# cat /etc/group|paste /etc/passwd /etc/shadow -|head -n 3

# 这个例子的重点在那个 - 的使用！那玩意儿常常代表 stdin 喔！

  • expand

这玩意儿就是在将 [tab] 按键转成空白键啦～可以这样玩：

[root@www ~]# expand [-t] file

选项与参数：
-t  ：后面可以接数字。一般来说，一个 tab 按键可以用 8 个空白键取代。
      我们也可以自行定义一个 [tab] 按键代表多少个字元呢！

范例一：将 /etc/man.config 内行首为 MANPATH 的字样就取出；仅取前三行；
[root@www ~]# grep '^MANPATH' /etc/man.config | head -n 3
MANPATH /usr/man
MANPATH /usr/share/man
MANPATH /usr/local/man
# 行首的代表标志为 ^ ，这个我们留待下节介绍！先有概念即可！

范例二：承上，如果我想要将所有的符号都列出来？(用 cat)
[root@www ~]# grep '^MANPATH' /etc/man.config | head -n 3 |cat -A

MANPATH^I/usr/man$
MANPATH^I/usr/share/man$
MANPATH^I/usr/local/man$
# 发现差别了吗？没错～ [tab] 按键可以被 cat -A 显示成为 ^I

范例三：承上，我将 [tab] 按键设定成 6 个字元的话？
[root@www ~]# grep '^MANPATH' /etc/man.config | head -n 3 | \
>  expand -t 6 - | cat -A
MANPATH     /usr/man$
MANPATH     /usr/share/man$
MANPATH     /usr/local/man$
123456123456123456.....
# 仔细看一下上面的数字说明，因为我是以 6 个字元来代表一个 [tab] 的长度，所以，
# MAN... 到 /usr 之间会隔 12 (两个 [tab]) 个字元喔！如果 tab 改成 9 的话，
# 情况就又不同了！这里也不好理解～您可以多设定几个数字来查阅就晓得！

expand 也是挺好玩的～他会自动将 [tab] 转成空白键～所以，以上面的例子来说， 使用 cat -A 就会查不到 ^I 的字符啰～此外，因为 [tab] 最大的功能就是格式排列整齐！ 我们转成空白键后，这个空白键也会依据我们自己的定义来增加大小～ 所以，并不是一个 ^I 就会换成 8 个空白喔！这个地方要特别注意的哩！ 此外，您也可以参考一下 unexpand 这个将空白转成 [tab] 的指令功能啊！ ^_^

小标题的图示 分割命令： split

如果你有档案太大，导致一些携带式装置无法复制的问题，嘿嘿！找 split 就对了！ 他可以帮你将一个大档案，依据档案大小或行数来分割，就可以将大档案分割成为小档案了！ 快速又有效啊！真不错～

[root@www ~]# split [-bl] file PREFIX
选项与参数：
-b  ：后面可接欲分割成的档案大小，可加单位，例如 b, k, m 等；
-l  ：以行数来进行分割。
PREFIX ：代表前置字元的意思，可作为分割档案的前导文字。

范例一：我的 /etc/termcap 有七百多K，若想要分成 300K 一个档案时？
[root@www ~]# cd /tmp; split -b 300k /etc/termcap termcap
[root@www tmp]# ll -k termcap*
-rw-r--r-- 1 root root 300 Feb  7 16:39 termcapaa

-rw-r--r-- 1 root root 300 Feb  7 16:39 termcapab
-rw-r--r-- 1 root root 189 Feb  7 16:39 termcapac
# 那个档名可以随意取的啦！我们只要写上前导文字，小档案就会以
# xxxaa, xxxab, xxxac 等方式来建立小档案的！

范例二：如何将上面的三个小档案合成一个档案，档名为 termcapback
[root@www tmp]# cat termcap* >> termcapback
# 很简单吧？就用资料流重导向就好啦！简单！

范例三：使用 ls -al / 输出的资讯中，每十行记录成一个档案
[root@www tmp]# ls -al / | split -l 10 - lsroot
[root@www tmp]# wc -l lsroot*
  10 lsrootaa
  10 lsrootab
   6 lsrootac
  26 total
# 重点在那个 - 啦！一般来说，如果需要 stdout/stdin 时，但偏偏又没有档案，
# 有的只是 - 时，那么那个 - 就会被当成 stdin 或 stdout ～

在 Windows 作业系统下，你要将档案分割需要如何作？伤脑筋吧！在 Linux 底下就简单的多了！你要将档案分割的话，那么就使用 -b size 来将一个分割的档案限制其大小，如果是行数的话，那么就使用 -l line 来分割！好用的很！如此一来，你就可以轻易的将你的档案分割成软碟 (floppy) 的大小，方便你 copy 啰！

小标题的图示 参数代换： xargs

xargs 是在做什么的呢？就以字面上的意义来看， x 是加减乘除的乘号，args 则是 arguments (参数) 的意思，所以说，这个玩意儿就是在产生某个指令的参数的意思！ xargs 可以读入 stdin 的资料，并且以空白字元或断行字元作为分辨，将 stdin 的资料分隔成为 arguments 。 因为是以空白字元作为分隔，所以，如果有一些档名或者是其他意义的名词内含有空白字元的时候， xargs 可能就会误判了～他的用法其实也还满简单的！就来看一看先！

[root@www ~]# xargs [-0epn] command
选项与参数：
-0  ：如果输入的 stdin 含有特殊字元，例如 `, \, 空白键等等字元时，这个 -0 参数
      可以将他还原成一般字元。这个参数可以用于特殊状态喔！
-e  ：这个是 EOF (end of file) 的意思。后面可以接一个字串，当 xargs 分析到
      这个字串时，就会停止继续工作！
-p  ：在执行每个指令的 argument 时，都会询问使用者的意思；
-n  ：后面接次数，每次 command 指令执行时，要使用几个参数的意思。看范例三。
当 xargs 后面没有接任何的指令时，预设是以 echo 来进行输出喔！

范例一：将 /etc/passwd 内的第一栏取出，仅取三行，使用 finger 这个指令将每个
        帐号内容秀出来
[root@www ~]# cut -d':' -f1 /etc/passwd |head -n 3| xargs finger
Login: root                             Name: root
Directory: /root                        Shell: /bin/bash
Never logged in.
No mail.
No Plan.
......底下省略.....
# 由 finger account 可以取得该帐号的相关说明内容，例如上面的输出就是 finger root
# 后的结果。在这个例子当中，我们利用 cut 取出帐号名称，用 head 取出三个帐号，
# 最后则是由 xargs 将三个帐号的名称变成 finger 后面需要的参数！

范例二：同上，但是每次执行 finger 时，都要询问使用者是否动作？

[root@www ~]# cut -d':' -f1 /etc/passwd |head -n 3| xargs -p finger
finger root bin daemon ?...y
.....(底下省略)....
# 呵呵！这个 -p 的选项可以让使用者的使用过程中，被询问到每个指令是否执行！

范例三：将所有的 /etc/passwd 内的帐号都以 finger 查阅，但一次仅查阅五个帐号
[root@www ~]# cut -d':' -f1 /etc/passwd | xargs -p -n 5 finger
finger root bin daemon adm lp ?...y

.....(中间省略)....
finger uucp operator games gopher ftp ?...y
.....(底下省略)....
# 在这里鸟哥使用了 -p 这个参数来让您对于 -n 更有概念。一般来说，某些指令后面
# 可以接的 arguments 是有限制的，不能无限制的累加，此时，我们可以利用 -n
# 来帮助我们将参数分成数个部分，每个部分分别再以指令来执行！这样就 OK 啦！^_^

范例四：同上，但是当分析到 lp 就结束这串指令？
[root@www ~]# cut -d':' -f1 /etc/passwd | xargs -p -e'lp' finger
finger root bin daemon adm ?...
# 仔细与上面的案例做比较。也同时注意，那个 -e'lp' 是连在一起的，中间没有空白键。
# 上个例子当中，第五个参数是 lp 啊，那么我们下达 -e'lp' 后，则分析到 lp
# 这个字串时，后面的其他 stdin 的内容就会被 xargs 舍弃掉了！

其实，在 man xargs 里面就有三四个小范例，您可以自行参考一下内容。 此外， xargs 真的是很好用的一个玩意儿！您真的需要好好的参详参详！会使用 xargs 的原因是， 很多指令其实并不支援管线命令，因此我们可以透过 xargs 来提供该指令引用 standard input 之用！举例来说，我们使用如下的范例来说明：

范例五：找出 /sbin 底下具有特殊权限的档名，并使用 ls -l 列出详细属性
[root@www ~]# find /sbin -perm +7000 | ls -l
# 结果竟然仅有列出 root 所在目录下的档案！这不是我们要的！
# 因为 ll (ls) 并不是管线命令的原因啊！

[root@www ~]# find /sbin -perm +7000 | xargs ls -l

-rwsr-xr-x 1 root root 70420 May 25  2008 /sbin/mount.nfs
-rwsr-xr-x 1 root root 70424 May 25  2008 /sbin/mount.nfs4
-rwxr-sr-x 1 root root  5920 Jun 15  2008 /sbin/netreport
....(底下省略)....
小标题的图示 关于减号 - 的用途

管线命令在 bash 的连续的处理程序中是相当重要的！另外，在 log file 的分析当中也是相当重要的一环， 所以请特别留意！另外，在管线命令当中，常常会使用到前一个指令的 stdout 作为这次的 stdin ， 某些指令需要用到档案名称 (例如 tar) 来进行处理时，该 stdin 与 stdout 可以利用减号 "-" 来替代， 举例来说：

[root@www ~]# tar -cvf - /home | tar -xvf -

上面这个例子是说：‘我将 /home 里面的档案给他打包，但打包的资料不是纪录到档案，而是传送到 stdout； 经过管线后，将 tar -cvf - /home 传送给后面的 tar -xvf - ’。后面的这个 - 则是取用前一个指令的 stdout， 因此，我们就不需要使用 file 了！这是很常见的例子喔！注意注意！

大标题的图示 重点回顾
  • 由于核心在记忆体中是受保护的区块，因此我们必须要透过‘ Shell ’将我们输入的指令与 Kernel 沟通，好让 Kernel 可以控制硬体来正确无误的工作
  • 学习 shell 的原因主要有：文字介面的 shell 在各大 distribution 都一样；远端管理时文字介面速度较快； shell 是管理 Linux 系统非常重要的一环，因为 Linux 内很多控制都是以 shell 撰写的。
  • 系统合法的 shell 均写在 /etc/shells 档案中；
  • 使用者预设登入取得的 shell 记录于 /etc/passwd 的最后一个栏位；
  • bash 的功能主要有：命令编修能力；命令与档案补全功能；命令别名设定功能；工作控制、前景背景控制；程式化脚本；万用字元
  • type 可以用来找到执行指令为何种类型，亦可用于与 which 相同的功能；
  • 变数就是以一组文字或符号等，来取代一些设定或者是一串保留的资料
  • 变数主要有环境变数与自订变数，或称为全域变数与区域变数
  • 使用 env 与 export 可观察环境变数，其中 export 可以将自订变数转成环境变数；
  • set 可以观察目前 bash 环境下的所有变数；
  • $? 亦为变数，是前一个指令执行完毕后的回传值。在 Linux 回传值为 0 代表执行成功；
  • locale 可用于观察语系资料；
  • 可用 read 让使用者由键盘输入变数的值
  • ulimit 可用以限制使用者使用系统的资源情况
  • bash 的设定档主要分为 login shell 与 non-login shell。login shell 主要读取 /etc/profile 与 ~/.bash_profile， non-login shell 则仅读取 ~/.bashrc
  • 万用字元主要有： *, ?, [] 等等
  • 资料流重导向透过 >, 2>, < 之类的符号将输出的资讯转到其他档案或装置去；
  • 连续命令的下达可透过 ; && || 等符号来处理
  • 管线命令的重点是：‘管线命令仅会处理 standard output，对于 standard error output 会予以忽略’ ‘管线命令必须要能够接受来自前一个指令的资料成为 standard input 继续处理才行。’
  • 本章介绍的管线命令主要有：cut, grep, sort, wc, uniq, tee, tr, col, join, paste, expand, split, xargs 等。
大标题的图示 本章习题
( 要看答案请将滑鼠移动到‘答：’底下的空白处，按下左键圈选空白处即可察看 )
  • 情境模拟题一：由于 ~/.bash_history 仅能记录指令，我想要在每次登出时都记录时间，并将后续的指令 50 笔记录下来， 可以如何处理？

    • 目标：了解 history ，并透过资料流重导向的方式记录历史命令；
    • 前提：需要了解本章的资料流重导向，以及了解 bash 的各个环境设定档资讯。

    其实处理的方式非常简单，我们可以了解 date 可以输出时间，而利用 ~/.myhistory 来记录所有历史记录， 而目前最新的 50 笔历史记录可以使用 history 50 来显示，故可以修改 ~/.bash_logout 成为底下的模样：
    [root@www ~]# vim ~/.bash_logout

date >> ~/.myhistory
history 50 > > ~/.myhistory
clear

简答题部分：
  • 在 Linux 上可以找到哪些 shell(举出三个) ？那个档案记录可用的 shell ？而 Linux 预设的 shell 是？
    1) /bin/bash, /bin/tcsh, /bin/csh
    2) /etc/shells
    3) bash ，亦即是 /bin/bash。
  • 在 shell 环境下，有个提示字元 (prompt)，他可以修改吗？要改什么？预设的提示字元内容是？
    可以修改的，改 PS1 这个变数，这个 PS1 变数的预设内容为：‘[\u@\h \W]\$’
  • 如何显示 HOME 这个环境变数？
    echo $HOME
  • 如何得知目前的所有变数与环境变数的设定值？
    环境变数用 env 或 export 而所有变数用 set 即可显示
  • 我是否可以设定一个变数名称为 3myhome ？
    不行！变数不能以数字做为开头，参考变数设定规则的内容
  • 在这样的练习中‘A=B’且‘B=C’，若我下达‘unset $A’，则取消的变数是 A 还是 B？
    被取消的是 B 喔，因为 unset $A 相当于 unset B 所以取消的是 B ，A 会继续存在！
  • 如何取消变数与命令别名的内容？
    使用 unset 及 unalias 即可
  • 如何设定一个变数名称为 name 内容为 It's my name ？
    name=It\'s\ my\ name 或 name="It's my name"
  • bash 环境设定档主要分为哪两种类型的读取？分别读取哪些重要档案？
    (1)login shell：主要读取 /etc/profile 及 ~/.bash_profile
    (2)non-logni shell：主要读取 ~/.bashrc 而已。
  • CentOS 5.x 的 man page 的路径设定档案？
    /etc/man.config
  • 试说明 ', ", 与 ` 这些符号在变数定义中的用途？
    参考变数规则那一章节，其中， " 可以具有变数的内容属性，' 则仅有一般字元，至于 ` 之内则是可先被执行的指令。
  • 跳脱符号 \ 有什么用途？
    可以用来跳脱特殊字元，例如 Enter, $ 等等，使成为一般字元！
  • 连续命令中， ;, &&, || 有何不同？
    分号可以让两个 command 连续运作，不考虑 command1 的输出状态， && 则前一个指令必需要没有错误讯息，亦即回传值需为 0 则 command2 才会被执行， || 则与 && 相反！
  • 如何将 last 的结果中，独立出帐号，并且印出曾经登入过的帐号？
    last | cut -d ' ' -f1 | sort | uniq
  • 请问 foo1 && foo2 | foo3 > foo4 ，这个指令串当中， foo1/foo2/foo3/foo4 是指令还是档案？ 整串指令的意义为？
    foo1, foo2 与 foo3 都是指令， foo4 是装置或档案。整串指令意义为：
    (1)当 foo1 执行结果有错误时，则该指令串结束；
    (2)若 foo1 执行结果没有错误时，则执行 foo2 | foo3 > foo4 ；其中：
    (2-1)foo2 将 stdout 输出的结果传给 foo3 处理；
    (2-2)foo3 将来自 foo2 的 stdout 当成 stdin ，处理完后将资料流重新导向 foo4 这个装置/档案
  • 如何秀出在 /bin 底下任何以 a 为开头的档案档名的详细资料？
    ls -l /bin/a*
  • 如何秀出 /bin 底下，档名为四个字元的档案？
    ls -l /bin/????
  • 如何秀出 /bin 底下，档名开头不是 a-d 的档案？
    ls -l /bin/[^a-d]*
  • 我想要让终端机介面的登入提示字元修改成我自己喜好的模样，应该要改哪里？(filename)
    /etc/issue
  • 承上题，如果我是想要让使用者登入后，才显示欢迎讯息，又应该要改哪里？
    /etc/motd
大标题的图示 参考资料与延伸阅读
  • 注1：Webmin 的官方网站：http://www.webmin.com/
  • 注2：关于 shell 的相关历史可以参考网路农夫兄所整理的优秀文章。不过由于网路农夫兄所建置的网站暂时关闭， 因此底下的连结为鸟哥到网路上找到的片段文章连结。若有任何侵权事宜，请来信告知，谢谢：
    http://linux.vbird.org/linux_basic/0320bash/csh/
  • 注3：使用 man bash，再以 PS1 为关键字去查询，按下数次 n 往后查询后，可以得到 PS1 的变数说明。
  • 注4：i18n 是由一些 Linux distribution 贡献者共同发起的大型计划，目的在于让众多的 Linux distributions 能够有良好的万国码 (Unicode) 语系的支援。详细的资料可以参考：
    i18n 的官方网站：http://www.openi18n.org/
    康桥大学 Dr Markus Kuhn 的文献：http://www.cl.cam.ac.uk/~mgk25/unicode.html
    Debian 社群所写的文件：http://www.debian.org/doc/manuals/intro-i18n/
  • 卧龙小三的教学文件：http://linux.tnc.edu.tw/techdoc/shell/book1.html
  • GNU 计划的 BASH 说明：http://www.gnu.org/manual/bash-2.05a/html_mono/bashref.html
    鸟哥的备份：http://linux.vbird.org/linux_basic/0320bash/0320bash_reference.php
  • man bash
2002/06/27：第一次完成
2003/02/10：重新编排与加入 FAQ
2005/08/17：将旧的资料放置到 这里
2005/08/17：终于稍微搞定了～花了半个多月不眠不休～呼～补充了较多的管线命令与资料流重导向！
2005/08/18：加入额外的变数设定部分！
2005/08/30：加入了 login 与 non-login shell 的简单说明！
2006/03/19：原先在 col 的说明当中，原本指令‘cat -A /etc/man.config | col -x | cat -A | more’不该有 -A！
2006/10/05：感谢小州兄的告知，修正了原本 ~/.bashrc 说明当中的错误。
2007/04/05：原本的 cut 范例说明有误，原本是‘我要找出第三个’应该改为‘我要找出第五个’才对！
2007/04/11：原本的 join 说明没有加上排序，应该需要排序后再处理才对！
2007/07/15：原本的额外的变数功能表格有误，在 var=${str+expr} 与var=${str:+expr} 需要修改，请参考 此处
2009/01/13：将原本基于 FC4 写作的旧文章移动到此处
2009/02/03：拿掉了原本的‘变数的用途’部分，改以案例说明
2009/02/05：多加了变数删除、取代与替代部分的范例，看起来应该不会像前一版那样不容易理解！
2009/08/25：加入了情境模拟，并且进行一些说明的细部修改而已。


鸟哥的 Linux 私房菜 -- 基础学习篇

为取得较佳浏览结果，请爱用 firefox 浏览本网页

第十二章、正规表示法与文件格式化处理
最近更新日期：2009/08/26
正规表示法 (Regular Expression, RE, 或称为常规表示法)是透过一些特殊字元的排列，用以‘搜寻/取代/删除’一列或多列文字字串， 简单的说，正规表示法就是用在字串的处理上面的一项‘表示式’。正规表示法并不是一个工具程式， 而是一个字串处理的标准依据，如果您想要以正规表示法的方式处理字串，就得要使用支援正规表示法的工具程式才行， 这类的工具程式很多，例如 vi, sed, awk 等等。

正规表示法对于系统管理员来说实在是很重要！因为系统会产生很多的讯息，这些讯息有的重要有的仅是告知， 此时，管理员可以透过正规表示法的功能来将重要讯息撷取出来，并产生便于查阅的报表来简化管理流程。此外， 很多的套装软体也都支援正规表示法的分析，例如邮件伺服器的过滤机制(过滤垃圾信件)就是很重要的一个例子。 所以，您最好要了解正规表示法的相关技能，在未来管理主机时，才能够更精简处理您的日常事务！

注：本章节使用者需要多加练习，因为目前很多的套件都是使用正规表示法来达成其‘过滤、分析’的目的， 为了未来主机管理的便利性，使用者至少要能看的懂正规表示法的意义！

1. 前言： 什么是正规表示法
    1.1 什么是正规表示法
    1.2 正规表示法对于系统管理员的用途
    1.3 正规表示法的广泛用途
    1.4 正规表示法与 Shell 在 Linux 当中的角色定位
    1.5 延伸的正规表示法
 2. 基础正规表示法
    2.1 语系对正规表示法的影响
    2.2 grep 的一些进阶选项
    2.3 基础正规表示法练习
    2.4 基础正规表示法字符汇整(characters)
    2.5 sed 工具： 行的新增/删除, 行的取代/显示, 搜寻并取代, 直接改档
 3. 延伸正规表示法
4. 文件的格式化与相关处理
    4.1 printf： 格式化列印
    4.2 awk：好用的资料处理工具
    4.3 档案比对工具：, diff, cmp, patch
    4.4 档案列印准备工具： pr
 5. 重点回顾
6. 本章习题
7. 参考资料与延伸阅读
8. 针对本文的建议：http://phorum.vbird.org/viewtopic.php?t=23885
大标题的图示 前言：什么是正规表示法

约略了解了 Linux 的基本指令 (BASH) 并且熟悉了 vim 之后，相信你对于敲击键盘的打字与指令下达比较不陌生了吧？ 接下来，底下要开始介绍一个很重要的观念，那就是所谓的‘正规表示法 (Regular Expression)’啰！

小标题的图示 什么是正规表示法

任何一个有经验的系统管理员，都会告诉你：‘正规表示法真是挺重要的！’ 为什么很重要呢？因为日常生活就使用的到啊！举个例子来说， 在你日常使用 vim 作文书处理或程式撰写时使用到的‘搜寻/取代’等等的功能， 这些举动要作的漂亮，就得要配合正规表示法来处理啰！

简单的说，正规表示法就是处理字串的方法，他是以行为单位来进行字串的处理行为， 正规表示法透过一些特殊符号的辅助，可以让使用者轻易的达到‘搜寻/删除/取代’某特定字串的处理程序！

举例来说，我只想找到 VBird(前面两个大写字元) 或 Vbird(仅有一个大写字元) 这个字样，但是不要其他的字串 (例如 VBIRD, vbird 等不需要)，该如何办理？如果在没有正规表示法的环境中(例如 MS word)，你或许就得要使用忽略大小写的办法， 或者是分别以 VBird 及 Vbird 搜寻两遍。但是，忽略大小写可能会搜寻到 VBIRD/vbird/VbIrD 等等的不需要的字串而造成困扰。

再举个系统常见的例子好了，假设你发现系统在开机的时候，老是会出现一个关于 mail 程式的错误， 而开机过程的相关程序都是在 /etc/init.d/ 底下，也就是说，在该目录底下的某个档案内具有 mail 这个关键字，你想要将该档案捉出来进行查询修改的动作。此时你怎么找出来含有这个关键字的档案？ 你当然可以一个档案一个档案的开启，然后去搜寻 mail 这个关键字，只是.....该目录底下的档案可能不止 100 个说～ 如果了解正规表示法的相关技巧，那么只要一行指令就找出来啦：‘grep 'mail' /etc/init.d/*’ 那个 grep 就是支援正规表示法的工具程式之一！如何～很简单吧！

谈到这里就得要进一步说明了，正规表示法基本上是一种‘表示法’， 只要工具程式支援这种表示法，那么该工具程式就可以用来作为正规表示法的字串处理之用。 例如 vi, grep, awk ,sed 等等工具，因为她们有支援正规表示法， 所以，这些工具就可以使用正规表示法的特殊字元来进行字串的处理。但例如 cp, ls 等指令并未支援正规表示法， 所以就只能使用 bash 自己本身的万用字元而已。

小标题的图示 正规表示法对于系统管理员的用途

那么为何我需要学习正规表示法呢？对于一般使用者来说，由于使用到正规表示法的机会可能不怎么多， 因此感受不到他的魅力，不过，对于身为系统管理员的你来说，正规表示法则是一个‘不可不学的好东西！’ 怎么说呢？由于系统如果在繁忙的情况之下，每天产生的讯息资讯会多到你无法想像的地步， 而我们也都知道，系统的‘错误讯息登录档案 (第十九章)’ 的内容记载了系统产生的所有讯息，当然，这包含你的系统是否被‘入侵’的记录资料。

但是系统的资料量太大了，要身为系统管理员的你每天去看这么多的讯息资料， 从千百行的资料里面找出一行有问题的讯息，呵呵～光是用肉眼去看，想不疯掉都很难！ 这个时候，我们就可以透过‘正规表示法’的功能，将这些登录的资讯进行处理， 仅取出‘有问题’的资讯来进行分析，哈哈！如此一来，你的系统管理工作将会 ‘快乐得不得了’啊！当然，正规表示法的优点还不止于此，等你有一定程度的了解之后，你会爱上他喔！

小标题的图示 正规表示法的广泛用途

正规表示法除了可以让系统管理员管理主机更为便利之外，事实上，由于正规表示法强大的字串处理能力， 目前一堆软体都支援正规表示法呢！最常见的就是‘邮件伺服器’啦！

如果你留意网际网路上的消息，那么应该不能发现，目前造成网路大塞车的主因之一就是‘垃圾/广告信件’了， 而如果我们可以在伺服器端，就将这些问题邮件剔除的话，用户端就会减少很多不必要的频宽耗损了。 那么如何剔除广告信件呢？由于广告信件几乎都有一定的标题或者是内容，因此， 只要每次有来信时，都先将来信的标题与内容进行特殊字串的比对，发现有不良信件就予以剔除！ 嘿！这个工作怎么达到啊？就使用正规表示法啊！目前两大邮件伺服器软体 sendmail 与 postfix 以及支援邮件伺服器的相关分析软体，都支援正规表示法的比对功能！

当然还不止于此啦，很多的伺服器软体都支援正规表示法呢！当然， 虽然各家软体都支援他，不过，这些‘字串’的比对还是需要系统管理员来加入比对规则的， 所以啦！身为系统管理员的你，为了自身的工作以及用户端的需求， 正规表示法实在是很需要也很值得学习的一项工具呢！

小标题的图示 正规表示法与 Shell 在 Linux 当中的角色定位

说实在的，我们在学数学的时候，一个很重要、但是粉难的东西是一定要‘背’的， 那就是九九乘法表，背成功了之后，未来在数学应用的路途上，真是一帆风顺啊！ 这个九九乘法表我们在小学的时候几乎背了一整年才背下来，并不是这么好背的呢！ 但他却是基础当中的基础！你现在一定受惠相当的多呢 ^_^！

而我们谈到的这个正规表示法，与前一章的 BASH 就有点像是数学的九九乘法表一样，是 Linux 基础当中的基础，虽然也是最难的部分， 不过，如果学成了之后，一定是‘大大的有帮助’的！这就好像是金庸小说里面的学武难关：任督二脉！ 打通任督二脉之后，武功立刻成倍成长！所以啦， 不论是对于系统的认识与系统的管理部分，他都有很棒的辅助啊！请好好的学习这个基础吧！ ^_^

小标题的图示 延伸的正规表示法

唔！正规表示法还有分喔？没错喔！正规表示法的字串表示方式依照不同的严谨度而分为： 基础正规表示法与延伸正规表示法。延伸型正规表示法除了简单的一组字串处理之外，还可以作群组的字串处理， 例如进行搜寻 VBird 或 netman 或 lman 的搜寻，注意，是‘或(or)’而不是‘和(and)’的处理， 此时就需要延伸正规表示法的帮助啦！藉由特殊的‘ ( ’与‘ | ’等字元的协助， 就能够达到这样的目的！不过，我们在这里主力仅是介绍最基础的基础正规表示法而已啦！好啦！清清脑门，咱们用功去啰！

Tips:
有一点要向大家报告的，那就是：‘正规表示法与万用字元是完全不一样的东西！’ 这很重要喔！因为‘万用字元 (wildcard) 代表的是 bash 操作介面的一个功能’，但正规表示法则是一种字串处理的表示方式！ 这两者要分的很清楚才行喔！所以，学习本章，请将前一章 bash 的万用字元意义先忘掉吧！

老实说，鸟哥以前刚接触正规表示法时，老想着要将这两者归纳在一起，结果就是...错误认知一大堆～ 所以才会建议您学习本章先忘记万用字元再来学习吧！ 		鸟哥的图示
大标题的图示 基础正规表示法

既然正规表示法是处理字串的一种表示方式，那么对字元排序有影响的语系资料就会对正规表示法的结果有影响！ 此外，正规表示法也需要支援工具程式来辅助才行！所以，我们这里就先介绍一个最简单的字串撷取功能的工具程式，那就是 grep 啰！ 前一章已经介绍过 grep 的相关选项与参数，本章着重在较进阶的 grep 选项说明啰！ 介绍完 grep 的功能之后，就进入正规表示法的特殊字符的处理能力了。

小标题的图示 语系对正规表示法的影响

为什么语系的资料会影响到正规表示法的输出结果呢？我们在第零章计算机概论的文字编码系统里面谈到，档案其实记录的仅有 0 与 1，我们看到的字元文字与数字都是透过编码表转换来的。由于不同语系的编码资料并不相同，所以就会造成资料撷取结果的差异了。 举例来说，在英文大小写的编码顺序中，zh_TW.big5 及 C 这两种语系的输出结果分别如下：

  • LANG=C 时：0 1 2 3 4 ... A B C D ... Z a b c d ...z
  • LANG=zh_TW 时：0 1 2 3 4 ... a A b B c C d D ... z Z

上面的顺序是编码的顺序，我们可以很清楚的发现这两种语系明显就是不一样！如果你想要撷取大写字元而使用 [A-Z] 时， 会发现 LANG=C 确实可以仅捉到大写字元 (因为是连续的) ，但是如果 LANG=zh_TW.big5 时，就会发现到， 连同小写的 b-z 也会被撷取出来！因为就编码的顺序来看， big5 语系可以撷取到‘ A b B c C ... z Z ’这一堆字元哩！ 所以，使用正规表示法时，需要特别留意当时环境的语系为何， 否则可能会发现与别人不相同的撷取结果喔！

由于一般我们在练习正规表示法时，使用的是相容于 POSIX 的标准，因此就使用‘ C ’这个语系(注1)！ 因此，底下的很多练习都是使用‘ LANG=C ’这个语系资料来进行的喔！ 另外，为了要避免这样编码所造成的英文与数字的撷取问题，因此有些特殊的符号我们得要了解一下的！ 这些符号主要有底下这些意义：(注1)

特殊符号 | 代表意义
[:alnum:] | 代表英文大小写字元及数字，亦即 0-9, A-Z, a-z
[:alpha:] | 代表任何英文大小写字元，亦即 A-Z, a-z
[:blank:] | 代表空白键与 [Tab] 按键两者
[:cntrl:] | 代表键盘上面的控制按键，亦即包括 CR, LF, Tab, Del.. 等等
[:digit:] | 代表数字而已，亦即 0-9
[:graph:] | 除了空白字元 (空白键与 [Tab] 按键) 外的其他所有按键
[:lower:] | 代表小写字元，亦即 a-z
[:print:] | 代表任何可以被列印出来的字元
[:punct:] | 代表标点符号 (punctuation symbol)，亦即：" ' ? ! ; : # $...
[:upper:] | 代表大写字元，亦即 A-Z
[:space:] | 任何会产生空白的字元，包括空白键, [Tab], CR 等等
[:xdigit:] | 代表 16 进位的数字类型，因此包括： 0-9, A-F, a-f 的数字与字元

尤其上表中的[:alnum:], [:alpha:], [:upper:], [:lower:], [:digit:] 这几个一定要知道代表什么意思，因为他要比 a-z 或 A-Z 的用途要确定的很！好了，底下就让我们开始来玩玩进阶版的 grep 吧！

小标题的图示 grep 的一些进阶选项

我们在第十一章 BASH 里面的 grep 谈论过一些基础用法， 但其实 grep 还有不少的进阶用法喔！底下我们仅列出较进阶的 grep 选项与参数给大家参考， 基础的 grep 用法请参考前一章的说明啰！

[root@www ~]# grep [-A] [-B] [--color=auto] '搜寻字串' filename
选项与参数：
-A ：后面可加数字，为 after 的意思，除了列出该行外，后续的 n 行也列出来；
-B ：后面可加数字，为 befer 的意思，除了列出该行外，前面的 n 行也列出来；
--color=auto 可将正确的那个撷取资料列出颜色

范例一：用 dmesg 列出核心讯息，再以 grep 找出内含 eth 那行
[root@www ~]# dmesg | grep 'eth'
eth0: RealTek RTL8139 at 0xee846000, 00:90:cc:a6:34:84, IRQ 10
eth0:  Identified 8139 chip type 'RTL-8139C'
eth0: link up, 100Mbps, full-duplex, lpa 0xC5E1
eth0: no IPv6 routers present
# dmesg 可列出核心产生的讯息！透过 grep 来撷取网路卡相关资讯 (eth) ，
# 就可发现如上资讯。不过没有行号与特殊颜色显示！看看下个范例吧！

范例二：承上题，要将捉到的关键字显色，且加上行号来表示：
[root@www ~]# dmesg | grep -n --color=auto 'eth'
247:eth0: RealTek RTL8139 at 0xee846000, 00:90:cc:a6:34:84, IRQ 10
248:eth0:  Identified 8139 chip type 'RTL-8139C'
294:eth0: link up, 100Mbps, full-duplex, lpa 0xC5E1
305:eth0: no IPv6 routers present
# 你会发现除了 eth 会有特殊颜色来表示之外，最前面还有行号喔！

范例三：承上题，在关键字所在行的前两行与后三行也一起捉出来显示
[root@www ~]# dmesg | grep -n -A3 -B2 --color=auto 'eth'
245-PCI: setting IRQ 10 as level-triggered
246-ACPI: PCI Interrupt 0000:00:0e.0[A] -> Link [LNKB] ...
247:eth0: RealTek RTL8139 at 0xee846000, 00:90:cc:a6:34:84, IRQ 10
248:eth0:  Identified 8139 chip type 'RTL-8139C'
249-input: PC Speaker as /class/input/input2
250-ACPI: PCI Interrupt 0000:00:01.4[B] -> Link [LNKB] ...
251-hdb: ATAPI 48X DVD-ROM DVD-R-RAM CD-R/RW drive, 2048kB Cache, UDMA(66)
# 如上所示，你会发现关键字 247 所在的前两行及 248 后三行也都被显示出来！
# 这样可以让你将关键字前后资料捉出来进行分析啦！

grep 是一个很常见也很常用的指令，他最重要的功能就是进行字串资料的比对，然后将符合使用者需求的字串列印出来。 需要说明的是‘grep 在资料中查寻一个字串时，是以 "整行" 为单位来进行资料的撷取的！’也就是说，假如一个档案内有 10 行，其中有两行具有你所搜寻的字串，则将那两行显示在荧幕上，其他的就丢弃了！

在关键字的显示方面，grep 可以使用 --color=auto 来将关键字部分使用颜色显示。 这可是个很不错的功能啊！但是如果每次使用 grep 都得要自行加上 --color=auto 又显的很麻烦～ 此时那个好用的 alias 就得来处理一下啦！你可以在 ~/.bashrc 内加上这行：‘alias grep='grep --color=auto'’再以‘ source ~/.bashrc ’来立即生效即可喔！ 这样每次执行 grep 他都会自动帮你加上颜色显示啦！

小标题的图示 基础正规表示法练习

要了解正规表示法最简单的方法就是由实际练习去感受啦！所以在汇整正规表示法特殊符号前， 我们先以底下这个档案的内容来进行正规表示法的理解吧！先说明一下，底下的练习大前提是：

  • 语系已经使用‘ export LANG=C ’的设定值；
  • grep 已经使用 alias 设定成为‘ grep --color=auto ’

至于本章的练习用档案请由底下的连结来下载。需要特别注意的是，底下这个档案是鸟哥在 MS Windows 系统下编辑的， 并且已经特殊处理过，因此，他虽然是纯文字档，但是内含一些 Windows 系统下的软体常常自行加入的一些特殊字元，例如断行字元 (^M) 就是一例！ 所以，你可以直接将底下的文字以 vi 储存成 regular_express.txt 这个档案， 不过，还是比较建议直接点底下的连结：

http://linux.vbird.org/linux_basic/0330regularex/regular_express.txt

如果你的 Linux 可以直接连上 Internet 的话，那么使用如下的指令来捉取即可：

wget http://linux.vbird.org/linux_basic/0330regularex/regular_express.txt

至于这个档案的内容如下：

[root@www ~]# vi regular_express.txt
"Open Source" is a good mechanism to develop programs.
apple is my favorite food.
Football game is not use feet only.
this dress doesn't fit me.
However, this dress is about $ 3183 dollars.^M
GNU is free air not free beer.^M
Her hair is very beauty.^M
I can't finish the test.^M
Oh! The soup taste good.^M
motorcycle is cheap than car.
This window is clear.
the symbol '*' is represented as start.
Oh!     My god!
The gd software is a library for drafting programs.^M
You are the best is mean you are the no. 1.
The world <Happy> is the same with "glad".
I like dog.
google is the best tools for search keyword.
goooooogle yes!
go! go! Let's go.
# I am VBird

这档案共有 22 行，最底下一行为空白行！现在开始我们一个案例一个案例的来介绍吧！

  • 例题一、搜寻特定字串

搜寻特定字串很简单吧？假设我们要从刚刚的档案当中取得 the 这个特定字串，最简单的方式就是这样：

[root@www ~]# grep -n 'the' regular_express.txt
8:I can't finish the test.
12:the symbol '*' is represented as start.
15:You are the best is mean you are the no. 1.
16:The world <Happy> is the same with "glad".
18:google is the best tools for search keyword.

那如果想要‘反向选择’呢？也就是说，当该行没有 'the' 这个字串时才显示在荧幕上，那就直接使用：

[root@www ~]# grep -vn 'the' regular_express.txt

你会发现，荧幕上出现的行列为除了 8,12,15,16,18 五行之外的其他行列！ 接下来，如果你想要取得不论大小写的 the 这个字串，则：

[root@www ~]# grep -in 'the' regular_express.txt
8:I can't finish the test.
9:Oh! The soup taste good.
12:the symbol '*' is represented as start.
14:The gd software is a library for drafting programs.
15:You are the best is mean you are the no. 1.
16:The world <Happy> is the same with "glad".
18:google is the best tools for search keyword.

除了多两行 (9, 14行) 之外，第 16 行也多了一个 The 的关键字被撷取到喔！

  • 例题二、利用中括号 [] 来搜寻集合字元

如果我想要搜寻 test 或 taste 这两个单字时，可以发现到，其实她们有共通的 't?st' 存在～这个时候，我可以这样来搜寻：

[root@www ~]# grep -n 't[ae]st' regular_express.txt

8:I can't finish the test.
9:Oh! The soup taste good.

了解了吧？其实 [] 里面不论有几个字元，他都谨代表某‘一个’字元， 所以，上面的例子说明了，我需要的字串是‘tast’或‘test’两个字串而已！ 而如果想要搜寻到有 oo 的字元时，则使用：

[root@www ~]# grep -n 'oo' regular_express.txt

1:"Open Source" is a good mechanism to develop programs.
2:apple is my favorite food.
3:Football game is not use feet only.
9:Oh! The soup taste good.
18:google is the best tools for search keyword.
19:goooooogle yes!

但是，如果我不想要 oo 前面有 g 的话呢？此时，可以利用在集合字元的反向选择 [^] 来达成：

[root@www ~]# grep -n '[^g]oo' regular_express.txt
2:apple is my favorite food.
3:Football game is not use feet only.
18:google is the best tools for search keyword.
19:goooooogle yes!

意思就是说，我需要的是 oo ，但是 oo 前面不能是 g 就是了！仔细比较上面两个表格，你会发现，第 1,9 行不见了，因为 oo 前面出现了 g 所致！第 2,3 行没有疑问，因为 foo 与 Foo 均可被接受！但是第 18 行明明有 google 的 goo 啊～别忘记了，因为该行后面出现了 tool 的 too 啊！所以该行也被列出来～ 也就是说， 18 行里面虽然出现了我们所不要的项目 (goo) 但是由于有需要的项目 (too) ， 因此，是符合字串搜寻的喔！

至于第 19 行，同样的，因为 goooooogle 里面的 oo 前面可能是 o ，例如： go(ooo)oogle ，所以，这一行也是符合需求的！

再来，假设我 oo 前面不想要有小写字元，所以，我可以这样写 [^abcd....z]oo ， 但是这样似乎不怎么方便，由于小写字元的 ASCII 上编码的顺序是连续的， 因此，我们可以将之简化为底下这样：

[root@www ~]# grep -n '[^a-z]oo' regular_express.txt

3:Football game is not use feet only.

也就是说，当我们在一组集合字元中，如果该字元组是连续的，例如大写英文/小写英文/数字等等， 就可以使用[a-z],[A-Z],[0-9]等方式来书写，那么如果我们的要求字串是数字与英文呢？ 呵呵！就将他全部写在一起，变成：[a-zA-Z0-9]。例如，我们要取得有数字的那一行，就这样：

[root@www ~]# grep -n '[0-9]' regular_express.txt
5:However, this dress is about $ 3183 dollars.
15:You are the best is mean you are the no. 1.

但由于考虑到语系对于编码顺序的影响，因此除了连续编码使用减号‘ - ’之外， 你也可以使用如下的方法来取得前面两个测试的结果：

[root@www ~]# grep -n '[^[:lower:]]oo' regular_express.txt
# 那个 [:lower:] 代表的就是 a-z 的意思！请参考前两小节的说明表格

[root@www ~]# grep -n '[[:digit:]]' regular_express.txt

这样对于 [] 以及 [^] 以及 [] 当中的 - ，还有关于前面表格提到的特殊关键字有了解了吗？^_^！

  • 例题三、行首与行尾字元 ^ $

我们在例题一当中，可以查询到一行字串里面有 the 的，那如果我想要让 the 只在行首列出呢？ 这个时候就得要使用定位字元了！我们可以这样做：

[root@www ~]# grep -n '^the' regular_express.txt

12:the symbol '*' is represented as start.

此时，就只剩下第 12 行，因为只有第 12 行的行首是 the 开头啊～此外， 如果我想要开头是小写字元的那一行就列出呢？可以这样：

[root@www ~]# grep -n '^[a-z]' regular_express.txt
2:apple is my favorite food.
4:this dress doesn't fit me.
10:motorcycle is cheap than car.
12:the symbol '*' is represented as start.
18:google is the best tools for search keyword.
19:goooooogle yes!
20:go! go! Let's go.

你可以发现我们可以捉到第一个字元都不是大写的！只不过 grep 列出的关键字部分不只有第一个字元， grep 是列出一整个字 (word) 说！同样的，上面的指令也可以用如下的方式来取代的：

[root@www ~]# grep -n '^[[:lower:]]' regular_express.txt

好！那如果我不想要开头是英文字母，则可以是这样：

[root@www ~]# grep -n '^[^a-zA-Z]' regular_express.txt
1:"Open Source" is a good mechanism to develop programs.
21:# I am VBird
# 指令也可以是： grep -n '^[^[:alpha:]]' regular_express.txt

注意到了吧？那个 ^ 符号，在字元集合符号(括号[])之内与之外是不同的！ 在 [] 内代表‘反向选择’，在 [] 之外则代表定位在行首的意义！要分清楚喔！ 反过来思考，那如果我想要找出来，行尾结束为小数点 (.) 的那一行，该如何处理：

[root@www ~]# grep -n '\.$' regular_express.txt
1:"Open Source" is a good mechanism to develop programs.
2:apple is my favorite food.
3:Football game is not use feet only.
4:this dress doesn't fit me.

10:motorcycle is cheap than car.
11:This window is clear.
12:the symbol '*' is represented as start.
15:You are the best is mean you are the no. 1.
16:The world <Happy> is the same with "glad".

17:I like dog.
18:google is the best tools for search keyword.
20:go! go! Let's go.

特别注意到，因为小数点具有其他意义(底下会介绍)，所以必须要使用跳脱字元(\)来加以解除其特殊意义！ 不过，你或许会觉得奇怪，但是第 5~9 行最后面也是 . 啊～怎么无法列印出来？ 这里就牵涉到 Windows 平台的软体对于断行字元的判断问题了！我们使用 cat -A 将第五行拿出来看， 你会发现：

[root@www ~]# cat -An regular_express.txt | head -n 10 | tail -n 6

     5  However, this dress is about $ 3183 dollars.^M$
     6  GNU is free air not free beer.^M$
     7  Her hair is very beauty.^M$
     8  I can't finish the test.^M$
     9  Oh! The soup taste good.^M$
    10  motorcycle is cheap than car.$

我们在第十章内谈到过断行字元在 Linux 与 Windows 上的差异， 在上面的表格中我们可以发现 5~9 行为 Windows 的断行字元 (^M$) ，而正常的 Linux 应该仅有第 10 行显示的那样 ($) 。所以啰，那个 . 自然就不是紧接在 $ 之前喔！也就捉不到 5~9 行了！这样可以了解 ^ 与 $ 的意义吗？ 好了，先不要看底下的解答，自己想一想，那么如果我想要找出来，哪一行是‘空白行’， 也就是说，该行并没有输入任何资料，该如何搜寻？

[root@www ~]# grep -n '^$' regular_express.txt
22:

因为只有行首跟行尾 (^$)，所以，这样就可以找出空白行啦！再来，假设你已经知道在一个程式脚本 (shell script) 或者是设定档当中，空白行与开头为 # 的那一行是注解，因此如果你要将资料列出给别人参考时， 可以将这些资料省略掉以节省保贵的纸张，那么你可以怎么作呢？ 我们以 /etc/syslog.conf 这个档案来作范例，你可以自行参考一下输出的结果：

[root@www ~]# cat -n /etc/syslog.conf

# 在 CentOS 中，结果可以发现有 33 行的输出，很多空白行与 # 开头

[root@www ~]# grep -v '^$' /etc/syslog.conf | grep -v '^#'
# 结果仅有 10 行，其中第一个‘ -v '^$' ’代表‘不要空白行’，
# 第二个‘ -v '^#' ’代表‘不要开头是 # 的那行’喔！

是否节省很多版面啊？

  • 例题四、任意一个字元 . 与重复字元 *

在第十一章 bash 当中，我们知道万用字元 * 可以用来代表任意(0或多个)字元， 但是正规表示法并不是万用字元，两者之间是不相同的！ 至于正规表示法当中的‘ . ’则代表‘绝对有一个任意字元’的意思！这两个符号在正规表示法的意义如下：

  • . (小数点)：代表‘一定有一个任意字元’的意思；
  • * (星星号)：代表‘重复前一个 0 到无穷多次’的意思，为组合形态

这样讲不好懂，我们直接做个练习吧！假设我需要找出 g??d 的字串，亦即共有四个字元， 起头是 g 而结束是 d ，我可以这样做：

[root@www ~]# grep -n 'g..d' regular_express.txt
1:"Open Source" is a good mechanism to develop programs.
9:Oh! The soup taste good.
16:The world <Happy> is the same with "glad".

因为强调 g 与 d 之间一定要存在两个字元，因此，第 13 行的 god 与第 14 行的 gd 就不会被列出来啦！再来，如果我想要列出有 oo, ooo, oooo 等等的资料， 也就是说，至少要有两个(含) o 以上，该如何是好？是 o* 还是 oo* 还是 ooo* 呢？ 虽然你可以试看看结果， 不过结果太占版面了 @_@ ，所以，我这里就直接说明。

因为 * 代表的是‘重复 0 个或多个前面的 RE 字符’的意义， 因此，‘o*’代表的是：‘拥有空字元或一个 o 以上的字元’， 特别注意，因为允许空字元(就是有没有字元都可以的意思)，因此，‘ grep -n 'o*' regular_express.txt ’将会把所有的资料都列印出来荧幕上！

那如果是‘oo*’呢？则第一个 o 肯定必须要存在，第二个 o 则是可有可无的多个 o ， 所以，凡是含有 o, oo, ooo, oooo 等等，都可以被列出来～

同理，当我们需要‘至少两个 o 以上的字串’时，就需要 ooo* ，亦即是：

[root@www ~]# grep -n 'ooo*' regular_express.txt
1:"Open Source" is a good mechanism to develop programs.
2:apple is my favorite food.
3:Football game is not use feet only.
9:Oh! The soup taste good.
18:google is the best tools for search keyword.
19:goooooogle yes!

这样理解 * 的意义了吗？好了，现在出个练习，如果我想要字串开头与结尾都是 g，但是两个 g 之间仅能存在至少一个 o ，亦即是 gog, goog, gooog.... 等等，那该如何？

[root@www ~]# grep -n 'goo*g' regular_express.txt
18:google is the best tools for search keyword.
19:goooooogle yes!

如此了解了吗？再来一题，如果我想要找出 g 开头与 g 结尾的字串，当中的字元可有可无，那该如何是好？是‘g*g’吗？

[root@www ~]# grep -n 'g*g' regular_express.txt
1:"Open Source" is a good mechanism to develop programs.
3:Football game is not use feet only.
9:Oh! The soup taste good.
13:Oh!  My god!
14:The gd software is a library for drafting programs.
16:The world <Happy> is the same with "glad".
17:I like dog.
18:google is the best tools for search keyword.
19:goooooogle yes!
20:go! go! Let's go.

但测试的结果竟然出现这么多行？太诡异了吧？其实一点也不诡异，因为 g*g 里面的 g* 代表‘空字元或一个以上的 g’ 在加上后面的 g ，因此，整个 RE 的内容就是 g, gg, ggg, gggg ， 因此，只要该行当中拥有一个以上的 g 就符合所需了！

那该如何得到我们的 g....g 的需求呢？呵呵！就利用任意一个字元‘.’啊！ 亦即是：‘g.*g’的作法，因为 * 可以是 0 或多个重复前面的字符，而 . 是任意字元，所以： ‘.* 就代表零个或多个任意字元’的意思啦！

[root@www ~]# grep -n 'g.*g' regular_express.txt
1:"Open Source" is a good mechanism to develop programs.
14:The gd software is a library for drafting programs.
18:google is the best tools for search keyword.
19:goooooogle yes!
20:go! go! Let's go.

因为是代表 g 开头与 g 结尾，中间任意字元均可接受，所以，第 1, 14, 20 行是可接受的喔！ 这个 .* 的 RE 表示任意字元是很常见的，希望大家能够理解并且熟悉！ 再出一题，如果我想要找出‘任意数字’的行列呢？因为仅有数字，所以就成为：

[root@www ~]# grep -n '[0-9][0-9]*' regular_express.txt
5:However, this dress is about $ 3183 dollars.
15:You are the best is mean you are the no. 1.

虽然使用 grep -n '[0-9]' regular_express.txt 也可以得到相同的结果， 但鸟哥希望大家能够理解上面指令当中 RE 表示法的意义才好！

  • 例题五、限定连续 RE 字符范围 {}

在上个例题当中，我们可以利用 . 与 RE 字符及 * 来设定 0 个到无限多个重复字元， 那如果我想要限制一个范围区间内的重复字元数呢？举例来说，我想要找出两个到五个 o 的连续字串，该如何作？这时候就得要使用到限定范围的字符 {} 了。 但因为 { 与 } 的符号在 shell 是有特殊意义的，因此， 我们必须要使用跳脱字符 \ 来让他失去特殊意义才行。 至于 {} 的语法是这样的，假设我要找到两个 o 的字串，可以是：

[root@www ~]# grep -n 'o\{2\}' regular_express.txt
1:"Open Source" is a good mechanism to develop programs.
2:apple is my favorite food.
3:Football game is not use feet only.
9:Oh! The soup taste good.
18:google is the best tools for search keyword.
19:goooooogle yes!

这样看似乎与 ooo* 的字符没有什么差异啊？因为第 19 行有多个 o 依旧也出现了！ 好，那么换个搜寻的字串，假设我们要找出 g 后面接 2 到 5 个 o ，然后再接一个 g 的字串，他会是这样：

[root@www ~]# grep -n 'go\{2,5\}g' regular_express.txt
18:google is the best tools for search keyword.

嗯！很好！第 19 行终于没有被取用了(因为 19 行有 6 个 o 啊！)。 那么，如果我想要的是 2 个 o 以上的 goooo....g 呢？除了可以是 gooo*g ，也可以是：

[root@www ~]# grep -n 'go\{2,\}g' regular_express.txt
18:google is the best tools for search keyword.
19:goooooogle yes!

呵呵！就可以找出来啦～

小标题的图示 基础正规表示法字符汇整 (characters)

经过了上面的几个简单的范例，我们可以将基础的正规表示法特殊字符汇整如下：

RE 字符 意义与范例
^word 意义：待搜寻的字串(word)在行首！
范例：搜寻行首为 # 开始的那一行，并列出行号
grep -n '^#' regular_express.txt
word$ 意义：待搜寻的字串(word)在行尾！
范例：将行尾为 ! 的那一行列印出来，并列出行号
grep -n '!$' regular_express.txt
. 意义：代表‘一定有一个任意字元’的字符！
范例：搜寻的字串可以是 (eve) (eae) (eee) (e e)， 但不能仅有 (ee) ！亦即 e 与 e 中间‘一定’仅有一个字元，而空白字元也是字元！
grep -n 'e.e' regular_express.txt
\ 意义：跳脱字符，将特殊符号的特殊意义去除！
范例：搜寻含有单引号 ' 的那一行！
grep -n \' regular_express.txt
* 意义：重复零个到无穷多个的前一个 RE 字符
范例：找出含有 (es) (ess) (esss) 等等的字串，注意，因为 * 可以是 0 个，所以 es 也是符合带搜寻字串。另外，因为 * 为重复‘前一个 RE 字符’的符号， 因此，在 * 之前必须要紧接着一个 RE 字符喔！例如任意字元则为 ‘.*’ ！
grep -n 'ess*' regular_express.txt
[list] 意义：字元集合的 RE 字符，里面列出想要撷取的字元！
范例：搜寻含有 (gl) 或 (gd) 的那一行，需要特别留意的是，在 [] 当中‘谨代表一个待搜寻的字元’， 例如‘ a[afl]y ’代表搜寻的字串可以是 aay, afy, aly 即 [afl] 代表 a 或 f 或 l 的意思！
grep -n 'g[ld]' regular_express.txt
[n1-n2] 意义：字元集合的 RE 字符，里面列出想要撷取的字元范围！
范例：搜寻含有任意数字的那一行！需特别留意，在字元集合 [] 中的减号 - 是有特殊意义的，他代表两个字元之间的所有连续字元！但这个连续与否与 ASCII 编码有关，因此，你的编码需要设定正确(在 bash 当中，需要确定 LANG 与 LANGUAGE 的变数是否正确！) 例如所有大写字元则为 [A-Z]
grep -n '[0-9]' regular_express.txt
[^list] 意义：字元集合的 RE 字符，里面列出不要的字串或范围！
范例：搜寻的字串可以是 (oog) (ood) 但不能是 (oot) ，那个 ^ 在 [] 内时，代表的意义是‘反向选择’的意思。 例如，我不要大写字元，则为 [^A-Z]。但是，需要特别注意的是，如果以 grep -n [^A-Z] regular_express.txt 来搜寻，却发现该档案内的所有行都被列出，为什么？因为这个 [^A-Z] 是‘非大写字元’的意思， 因为每一行均有非大写字元，例如第一行的 "Open Source" 就有 p,e,n,o.... 等等的小写字
grep -n 'oo[^t]' regular_express.txt
\{n,m\} 意义：连续 n 到 m 个的‘前一个 RE 字符’
意义：若为 \{n\} 则是连续 n 个的前一个 RE 字符，
意义：若是 \{n,\} 则是连续 n 个以上的前一个 RE 字符！ 范例：在 g 与 g 之间有 2 个到 3 个的 o 存在的字串，亦即 (goog)(gooog)
grep -n 'go\{2,3\}g' regular_express.txt

再次强调：‘正规表示法的特殊字元’与一般在指令列输入指令的‘万用字元’并不相同， 例如，在万用字元当中的 * 代表的是‘ 0 ~ 无限多个字元’的意思，但是在正规表示法当中， * 则是‘重复 0 到无穷多个的前一个 RE 字符’的意思～使用的意义并不相同，不要搞混了！

举例来说，不支援正规表示法的 ls 这个工具中，若我们使用 ‘ls -l * ’ 代表的是任意档名的档案，而 ‘ls -l a* ’代表的是以 a 为开头的任何档名的档案， 但在正规表示法中，我们要找到含有以 a 为开头的档案，则必须要这样：(需搭配支援正规表示法的工具)

ls | grep -n '^a.*'
例题：
以 ls -l 配合 grep 找出 /etc/ 底下档案类型为连结档属性的档名
答：
由于 ls -l 列出连结档时标头会是‘ lrwxrwxrwx ’，因此使用如下的指令即可找出结果：
ls -l /etc | grep '^l'
若仅想要列出几个档案，再以‘ |wc -l ’ 来累加处理即可。

小标题的图示 sed 工具

在了解了一些正规表示法的基础应用之后，再来呢？呵呵～两个东西可以玩一玩的，那就是 sed 跟底下会介绍的 awk 了！ 这两个家伙可是相当的有用的啊！举例来说，鸟哥写的 logfile.sh 分析登录档的小程式 (第十九章会谈到)，绝大部分分析关键字的取用、统计等等，就是用这两个宝贝蛋来帮我完成的！那么你说，要不要玩一玩啊？^_^

我们先来谈一谈 sed 好了， sed 本身也是一个管线命令，可以分析 standard input 的啦！ 而且 sed 还可以将资料进行取代、删除、新增、撷取特定行等等的功能呢！很不错吧～ 我们先来了解一下 sed 的用法，再来聊他的用途好了！

[root@www ~]# sed [-nefr] [动作]
选项与参数：
-n  ：使用安静(silent)模式。在一般 sed 的用法中，所有来自 STDIN
      的资料一般都会被列出到荧幕上。但如果加上 -n 参数后，则只有经过
      sed 特殊处理的那一行(或者动作)才会被列出来。
-e  ：直接在指令列模式上进行 sed 的动作编辑；
-f  ：直接将 sed 的动作写在一个档案内， -f filename 则可以执行 filename 内的
      sed 动作；
-r  ：sed 的动作支援的是延伸型正规表示法的语法。(预设是基础正规表示法语法)
-i  ：直接修改读取的档案内容，而不是由荧幕输出。

动作说明：  [n1[,n2]]function
n1, n2 ：不见得会存在，一般代表‘选择进行动作的行数’，举例来说，如果我的动作
         是需要在 10 到 20 行之间进行的，则‘ 10,20[动作行为] ’

function 有底下这些咚咚：
a   ：新增， a 的后面可以接字串，而这些字串会在新的一行出现(目前的下一行)～
c   ：取代， c 的后面可以接字串，这些字串可以取代 n1,n2 之间的行！
d   ：删除，因为是删除啊，所以 d 后面通常不接任何咚咚；
i   ：插入， i 的后面可以接字串，而这些字串会在新的一行出现(目前的上一行)；
p   ：列印，亦即将某个选择的资料印出。通常 p 会与参数 sed -n 一起运作～
s   ：取代，可以直接进行取代的工作哩！通常这个 s 的动作可以搭配
      正规表示法！例如 1,20s/old/new/g 就是啦！
  • 以行为单位的新增/删除功能

sed 光是用看的是看不懂的啦！所以又要来练习了！先来玩玩删除与新增的功能吧！

范例一：将 /etc/passwd 的内容列出并且列印行号，同时，请将第 2~5 行删除！
[root@www ~]# nl /etc/passwd | sed '2,5d'
     1  root:x:0:0:root:/root:/bin/bash
     6  sync:x:5:0:sync:/sbin:/bin/sync
     7  shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
.....(后面省略).....

看到了吧？sed 的动作为 '2,5d' ，那个 d 就是删除！因为 2-5 行给他删除了，所以显示的资料就没有 2-5 行啰～ 另外，注意一下，原本应该是要下达 sed -e 才对，没有 -e 也行啦！同时也要注意的是， sed 后面接的动作，请务必以 '' 两个单引号括住喔！

如果题型变化一下，举例来说，如果只要删除第 2 行，可以使用‘ nl /etc/passwd | sed '2d' ’来达成， 至于若是要删除第 3 到最后一行，则是‘ nl /etc/passwd | sed '3,$d' ’的啦，那个钱字号‘ $ ’代表最后一行！

范例二：承上题，在第二行后(亦即是加在第三行)加上‘drink tea?’字样！
[root@www ~]# nl /etc/passwd | sed '2a drink tea'

     1  root:x:0:0:root:/root:/bin/bash
     2  bin:x:1:1:bin:/bin:/sbin/nologin
drink tea
     3  daemon:x:2:2:daemon:/sbin:/sbin/nologin
.....(后面省略).....

嘿嘿！在 a 后面加上的字串就已将出现在第二行后面啰！那如果是要在第二行前呢？‘ nl /etc/passwd | sed '2i drink tea' ’就对啦！就是将‘ a ’变成‘ i ’即可。 增加一行很简单，那如果是要增将两行以上呢？

范例三：在第二行后面加入两行字，例如‘Drink tea or .....’与‘drink beer?’
[root@www ~]# nl /etc/passwd | sed '2a Drink tea or ......\
> drink beer ?'

     1  root:x:0:0:root:/root:/bin/bash
     2  bin:x:1:1:bin:/bin:/sbin/nologin
Drink tea or ......
drink beer ?
     3  daemon:x:2:2:daemon:/sbin:/sbin/nologin
.....(后面省略).....

这个范例的重点是‘我们可以新增不只一行喔！可以新增好几行’但是每一行之间都必须要以反斜线‘ \ ’来进行新行的增加喔！所以，上面的例子中，我们可以发现在第一行的最后面就有 \ 存在啦！那是一定要的喔！

  • 以行为单位的取代与显示功能

刚刚是介绍如何新增与删除，那么如果要整行取代呢？看看底下的范例吧：

范例四：我想将第2-5行的内容取代成为‘No 2-5 number’呢？
[root@www ~]# nl /etc/passwd | sed '2,5c No 2-5 number'
     1  root:x:0:0:root:/root:/bin/bash
No 2-5 number
     6  sync:x:5:0:sync:/sbin:/bin/sync
.....(后面省略).....

透过这个方法我们就能够将资料整行取代了！非常容易吧！sed 还有更好用的东东！我们以前想要列出第 11~20 行， 得要透过‘head -n 20 | tail -n 10’之类的方法来处理，很麻烦啦～ sed 则可以简单的直接取出你想要的那几行！是透过行号来捉的喔！看看底下的范例先：

范例五：仅列出 /etc/passwd 档案内的第 5-7 行
[root@www ~]# nl /etc/passwd | sed -n '5,7p'
     5  lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
     6  sync:x:5:0:sync:/sbin:/bin/sync
     7  shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown

上述的指令中有个重要的选项‘ -n ’，按照说明文件，这个 -n 代表的是‘安静模式’！ 那么为什么要使用安静模式呢？你可以自行下达 sed '5,7p' 就知道了 (5-7 行会重复输出)！ 有没有加上 -n 的参数时，输出的资料可是差很多的喔！你可以透过这个 sed 的以行为单位的显示功能， 就能够将某一个档案内的某些行号捉出来查阅！很棒的功能！不是吗？

  • 部分资料的搜寻并取代的功能

除了整行的处理模式之外， sed 还可以用行为单位进行部分资料的搜寻并取代的功能喔！ 基本上 sed 的搜寻与取代的与 vi 相当的类似！他有点像这样：

sed 's/要被取代的字串/新的字串/g'

上表中特殊字体的部分为关键字，请记下来！至于三个斜线分成两栏就是新旧字串的替换啦！ 我们使用底下这个取得 IP 数据的范例，一段一段的来处理给您瞧瞧，让你了解一下什么是咱们所谓的搜寻并取代吧！

步骤一：先观察原始讯息，利用 /sbin/ifconfig  查询 IP 为何？
[root@www ~]# /sbin/ifconfig eth0
eth0      Link encap:Ethernet  HWaddr 00:90:CC:A6:34:84
          inet addr:192.168.1.100  Bcast:192.168.1.255  Mask:255.255.255.0
          inet6 addr: fe80::290:ccff:fea6:3484/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
.....(以下省略).....
# 因为我们还没有讲到 IP ，这里你先有个概念即可啊！我们的重点在第二行，
# 也就是 192.168.1.100 那一行而已！先利用关键字捉出那一行！

步骤二：利用关键字配合 grep 撷取出关键的一行资料

[root@www ~]# /sbin/ifconfig eth0 | grep 'inet addr'
          inet addr:192.168.1.100  Bcast:192.168.1.255  Mask:255.255.255.0
# 当场仅剩下一行！接下来，我们要将开始到 addr: 通通删除，就是像底下这样：
# inet addr:192.168.1.100  Bcast:192.168.1.255  Mask:255.255.255.0
# 上面的删除关键在于‘ ^.*inet addr: ’啦！正规表示法出现！ ^_^

步骤三：将 IP 前面的部分予以删除
[root@www ~]# /sbin/ifconfig eth0 | grep 'inet addr' | \
>  sed 's/^.*addr://g'

192.168.1.100  Bcast:192.168.1.255  Mask:255.255.255.0
# 仔细与上个步骤比较一下，前面的部分不见了！接下来则是删除后续的部分，亦即：
# 192.168.1.100  Bcast:192.168.1.255  Mask:255.255.255.0
# 此时所需的正规表示法为：‘ Bcast.*$ ’就是啦！

步骤四：将 IP 后面的部分予以删除
[root@www ~]# /sbin/ifconfig eth0 | grep 'inet addr' | \
>  sed 's/^.*addr://g' | sed 's/Bcast.*$//g'
192.168.1.100

透过这个范例的练习也建议您依据此一步骤来研究你的指令！就是先观察，然后再一层一层的试做， 如果有做不对的地方，就先予以修改，改完之后测试，成功后再往下继续测试。以鸟哥上面的介绍中， 那一大串指令就做了四个步骤！对吧！ ^_^

让我们再来继续研究 sed 与正规表示法的配合练习！假设我只要 MAN 存在的那几行资料， 但是含有 # 在内的注解我不想要，而且空白行我也不要！此时该如何处理呢？可以透过这几个步骤来实作看看：

步骤一：先使用 grep 将关键字 MAN 所在行取出来
[root@www ~]# cat /etc/man.config | grep 'MAN'
# when MANPATH contains an empty substring), to find out where the cat
# MANBIN                pathname
# MANPATH               manpath_element [corresponding_catdir]
# MANPATH_MAP           path_element    manpath_element
# MANBIN                /usr/local/bin/man
# Every automatically generated MANPATH includes these fields
MANPATH /usr/man

....(后面省略)....

步骤二：删除掉注解之后的资料！
[root@www ~]# cat /etc/man.config | grep 'MAN'| sed 's/#.*$//g'

MANPATH /usr/man
....(后面省略)....
# 从上面可以看出来，原本注解的资料都变成空白行啦！所以，接下来要删除掉空白行

[root@www ~]# cat /etc/man.config | grep 'MAN'| sed 's/#.*$//g' | \
> sed '/^$/d'
MANPATH /usr/man
MANPATH /usr/share/man
MANPATH /usr/local/man
....(后面省略)....
  • 直接修改档案内容(危险动作)

你以为 sed 只有这样的能耐吗？那可不！ sed 甚至可以直接修改档案的内容呢！而不必使用管线命令或资料流重导向！ 不过，由于这个动作会直接修改到原始的档案，所以请你千万不要随便拿系统设定档来测试喔！ 我们还是使用你下载的 regular_express.txt 档案来测试看看吧！

范例六：利用 sed 将 regular_express.txt 内每一行结尾若为 . 则换成 !
[root@www ~]# sed -i 's/\.$/\!/g' regular_express.txt
# 上头的 -i 选项可以让你的 sed 直接去修改后面接的档案内容而不是由荧幕输出喔！
# 这个范例是用在取代！请您自行 cat 该档案去查阅结果啰！

范例七：利用 sed 直接在 regular_express.txt 最后一行加入‘# This is a test’
[root@www ~]# sed -i '$a # This is a test' regular_express.txt

# 由于 $ 代表的是最后一行，而 a 的动作是新增，因此该档案最后新增啰！

sed 的‘ -i ’选项可以直接修改档案内容，这功能非常有帮助！举例来说，如果你有一个 100 万行的档案，你要在第 100 行加某些文字，此时使用 vim 可能会疯掉！因为档案太大了！那怎办？就利用 sed 啊！透过 sed 直接修改/取代的功能，你甚至不需要使用 vim 去修订！很棒吧！

总之，这个 sed 不错用啦！而且很多的 shell script 都会使用到这个指令的功能～ sed 可以帮助系统管理员管理好日常的工作喔！要仔细的学习呢！

大标题的图示 延伸正规表示法

事实上，一般读者只要了解基础型的正规表示法大概就已经相当足够了，不过，某些时刻为了要简化整个指令操作， 了解一下使用范围更广的延伸型正规表示法的表示式会更方便呢！举个简单的例子好了，在上节的例题三的最后一个例子中，我们要去除空白行与行首为 # 的行列，使用的是

grep -v '^$' regular_express.txt | grep -v '^#'

需要使用到管线命令来搜寻两次！那么如果使用延伸型的正规表示法，我们可以简化为：

egrep -v '^$|^#' regular_express.txt

延伸型正规表示法可以透过群组功能‘ | ’来进行一次搜寻！那个在单引号内的管线意义为‘或 or’啦！ 是否变的更简单呢？此外，grep 预设仅支援基础正规表示法，如果要使用延伸型正规表示法，你可以使用 grep -E ， 不过更建议直接使用 egrep ！直接区分指令比较好记忆！其实 egrep 与 grep -E 是类似命令别名的关系啦！

熟悉了正规表示法之后，到这个延伸型的正规表示法，你应该也会想到，不就是多几个重要的特殊符号吗？ ^_^y 是的～所以，我们就直接来说明一下，延伸型正规表示法有哪几个特殊符号？由于底下的范例还是有使用到 regular_express.txt ，不巧的是刚刚我们可能将该档案修改过了 @_@，所以，请重新下载该档案来练习喔！

RE 字符 意义与范例
+ 意义：重复‘一个或一个以上’的前一个 RE 字符
范例：搜寻 (god) (good) (goood)... 等等的字串。 那个 o+ 代表‘一个以上的 o ’所以，底下的执行成果会将第 1, 9, 13 行列出来。
egrep -n 'go+d' regular_express.txt
? 意义：‘零个或一个’的前一个 RE 字符
范例：搜寻 (gd) (god) 这两个字串。 那个 o? 代表‘空的或 1 个 o ’所以，上面的执行成果会将第 13, 14 行列出来。 有没有发现到，这两个案例( 'go+d' 与 'go?d' )的结果集合与 'go*d' 相同？ 想想看，这是为什么喔！ ^_^
egrep -n 'go?d' regular_express.txt
| 意义：用或( or )的方式找出数个字串
范例：搜寻 gd 或 good 这两个字串，注意，是‘或’！ 所以，第 1,9,14 这三行都可以被列印出来喔！那如果还想要找出 dog 呢？
egrep -n 'gd|good' regular_express.txt
egrep -n 'gd|good|dog' regular_express.txt
() 意义：找出‘群组’字串
范例：搜寻 (glad) 或 (good) 这两个字串，因为 g 与 d 是重复的，所以， 我就可以将 la 与 oo 列于 ( ) 当中，并以 | 来分隔开来，就可以啦！
egrep -n 'g(la|oo)d' regular_express.txt
()+ 意义：多个重复群组的判别
范例：将‘AxyzxyzxyzxyzC’用 echo 叫出，然后再使用如下的方法搜寻一下！
echo 'AxyzxyzxyzxyzC' | egrep 'A(xyz)+C'
上面的例子意思是说，我要找开头是 A 结尾是 C ，中间有一个以上的 "xyz" 字串的意思～

以上这些就是延伸型的正规表示法的特殊字元。另外，要特别强调的是，那个 ! 在正规表示法当中并不是特殊字元， 所以，如果你想要查出来档案中含有 ! 与 > 的字行时，可以这样：

grep -n '[!>]' regular_express.txt

这样可以了解了吗？常常看到有陷阱的题目写：‘反向选择这样对否？ '[!a-z]'？’， 呵呵！是错的呦～要 '[^a-z] 才是对的！至于更多关于正规表示法的进阶文章，请参考文末的参考资料(注2)

大标题的图示 文件的格式化与相关处理

接下来让我们来将文件进行一些简单的编排吧！底下这些动作可以将你的讯息进行排版的动作， 不需要重新以 vim 去编辑，透过资料流重导向配合底下介绍的 printf 功能，以及 awk 指令， 就可以让你的讯息以你想要的模样来输出了！试看看吧！

小标题的图示 格式化列印： printf

在很多时候，我们可能需要将自己的资料给他格式化输出的！ 举例来说，考试卷分数的输出，姓名与科目及分数之间，总是可以稍微作个比较漂亮的版面配置吧？ 例如我想要输出底下的样式：

Name     Chinese   English   Math    Average
DmTsai        80        60     92      77.33
VBird         75        55     80      70.00
Ken           60        90     70      73.33

上表的资料主要分成五个栏位，各个栏位之间可使用 tab 或空白键进行分隔。 请将上表的资料转存成为 printf.txt 档名，等一下我们会利用这个档案来进行几个小练习的。 因为每个栏位的原始资料长度其实并非是如此固定的 (Chinese 长度就是比 Name 要多)， 而我就是想要如此表示出这些资料，此时，就得需要列印格式管理员 printf 的帮忙了！ printf 可以帮我们将资料输出的结果格式化，而且而支援一些特殊的字符～底下我们就来看看！

[root@www ~]# printf '列印格式' 实际内容
选项与参数：
关于格式方面的几个特殊样式：
       \a    警告声音输出
       \b    倒退键(backspace)
       \f    清除荧幕 (form feed)
       \n    输出新的一行
       \r    亦即 Enter 按键
       \t    水平的 [tab] 按键
       \v    垂直的 [tab] 按键
       \xNN  NN 为两位数的数字，可以转换数字成为字元。
关于 C 程式语言内，常见的变数格式
       %ns   那个 n 是数字， s 代表 string ，亦即多少个字元；
       %ni   那个 n 是数字， i 代表 integer ，亦即多少整数位数；
       %N.nf 那个 n 与 N 都是数字， f 代表 floating (浮点)，如果有小数位数，
             假设我共要十个位数，但小数点有两位，即为 %10.2f 啰！

接下来我们来进行几个常见的练习。假设所有的资料都是一般文字 (这也是最常见的状态)，因此最常用来分隔资料的符号就是 [Tab] 啦！因为 [Tab] 按键可以将资料作个整齐的排列！那么如何利用 printf 呢？参考底下这个范例：

范例一：将刚刚上头资料的档案 (printf.txt) 内容仅列出姓名与成绩：(用 [tab] 分隔)
[root@www ~]# printf '%s\t %s\t %s\t %s\t %s\t \n' $(cat printf.txt)

Name     Chinese         English         Math    Average
DmTsai   80      60      92      77.33
VBird    75      55      80      70.00
Ken      60      90      70      73.33

由于 printf 并不是管线命令，因此我们得要透过类似上面的功能，将档案内容先提出来给 printf 作为后续的资料才行。 如上所示，我们将每个资料都以 [tab] 作为分隔，但是由于 Chinese 长度太长，导致 English 中间多了一个 [tab] 来将资料排列整齐！啊～结果就看到资料对齐结果的差异了！

另外，在 printf 后续的那一段格式中，%s 代表一个不固定长度的字串，而字串与字串中间就以 \t 这个 [tab] 分隔符号来处理！你要记得的是，由于 \t 与 %s 中间还有空格，因此每个字串间会有一个 [tab] 与一个空白键的分隔喔！

既然每个栏位的长度不固定会造成上述的困扰，那我将每个栏位固定就好啦！没错没错！这样想非常好！ 所以我们就将资料给他进行固定栏位长度的设计吧！

范例二：将上述资料关于第二行以后，分别以字串、整数、小数点来显示：

[root@www ~]# printf '%10s %5i %5i %5i %8.2f \n' $(cat printf.txt |\
> grep -v Name)
    DmTsai    80    60    92    77.33
     VBird    75    55    80    70.00
       Ken    60    90    70    73.33

上面这一串格式想必您看得很辛苦！没关系！一个一个来解释！上面的格式共分为五个栏位， %10s 代表的是一个长度为 10 个字元的字串栏位，%5i 代表的是长度为 5 个字元的数字栏位，至于那个 %8.2f 则代表长度为 8 个字元的具有小数点的栏位，其中小数点有两个字元宽度。我们可以使用底下的说明来介绍 %8.2f 的意义：

字元宽度： 12345678
%8.2f意义：00000.00

如上所述，全部的宽度仅有 8 个字元，整数部分占有 5 个字元，小数点本身 (.) 占一位，小数点下的位数则有两位。 这种格式经常使用于数值程式的设计中！这样了解乎？自己试看看如果要将小数点位数变成 1 位又该如何处理？

printf 除了可以格式化处理之外，他还可以依据 ASCII 的数字与图形对应来显示资料喔(注3)！ 举例来说 16 进位的 45 可以得到什么 ASCII 的显示图 (其实是字元啦)？

范例三：列出 16 进位数值 45 代表的字元为何？
[root@www ~]# printf '\x45\n'

E
# 这东西也很好玩～他可以将数值转换成为字元，如果你会写 script 的话，
# 可以自行测试一下，由 20~80 之间的数值代表的字元是啥喔！ ^_^

printf 的使用相当的广泛喔！包括等一下后面会提到的 awk 以及在 C 程式语言当中使用的荧幕输出， 都是利用 printf 呢！鸟哥这里也只是列出一些可能会用到的格式而已，有兴趣的话，可以自行多作一些测试与练习喔！ ^_^

Tips:
列印格式化这个 printf 指令，乍看之下好像也没有什么很重要的～ 不过，如果你需要自行撰写一些软体，需要将一些资料在荧幕上头漂漂亮亮的输出的话， 那么 printf 可也是一个很棒的工具喔！ 		鸟哥的图示
小标题的图示 awk：好用的资料处理工具

awk 也是一个非常棒的资料处理工具！相较于 sed 常常作用于一整个行的处理， awk 则比较倾向于一行当中分成数个‘栏位’来处理。因此，awk 相当的适合处理小型的数据资料处理呢！awk 通常运作的模式是这样的：

[root@www ~]# awk '条件类型1{动作1} 条件类型2{动作2} ...' filename

awk 后面接两个单引号并加上大括号 {} 来设定想要对资料进行的处理动作。 awk 可以处理后续接的档案，也可以读取来自前个指令的 standard output 。 但如前面说的， awk 主要是处理‘每一行的栏位内的资料’，而预设的‘栏位的分隔符号为 "空白键" 或 "[tab]键" ’！举例来说，我们用 last 可以将登入者的资料取出来，结果如下所示：

[root@www ~]# last -n 5 <==仅取出前五行
root     pts/1   192.168.1.100  Tue Feb 10 11:21   still logged in
root     pts/1   192.168.1.100  Tue Feb 10 00:46 - 02:28  (01:41)
root     pts/1   192.168.1.100  Mon Feb  9 11:41 - 18:30  (06:48)
dmtsai   pts/1   192.168.1.100  Mon Feb  9 11:41 - 11:41  (00:00)
root     tty1                   Fri Sep  5 14:09 - 14:10  (00:01)

若我想要取出帐号与登入者的 IP ，且帐号与 IP 之间以 [tab] 隔开，则会变成这样：

[root@www ~]# last -n 5 | awk '{print $1 "\t" $3}'

root    192.168.1.100
root    192.168.1.100
root    192.168.1.100
dmtsai  192.168.1.100
root    Fri

上表是 awk 最常使用的动作！透过 print 的功能将栏位资料列出来！栏位的分隔则以空白键或 [tab] 按键来隔开。 因为不论哪一行我都要处理，因此，就不需要有 "条件类型" 的限制！我所想要的是第一栏以及第三栏， 但是，第五行的内容怪怪的～这是因为资料格式的问题啊！所以啰～使用 awk 的时候，请先确认一下你的资料当中，如果是连续性的资料，请不要有空格或 [tab] 在内，否则，就会像这个例子这样，会发生误判喔！

另外，由上面这个例子你也会知道，在每一行的每个栏位都是有变数名称的，那就是 $1, $2... 等变数名称。以上面的例子来说， root 是 $1 ，因为他是第一栏嘛！至于 192.168.1.100 是第三栏， 所以他就是 $3 啦！后面以此类推～呵呵！还有个变数喔！那就是 $0 ，$0 代表‘一整列资料’的意思～以上面的例子来说，第一行的 $0 代表的就是‘root .... ’那一行啊！ 由此可知，刚刚上面五行当中，整个 awk 的处理流程是：

  1. 读入第一行，并将第一行的资料填入 $0, $1, $2.... 等变数当中；
  2. 依据 "条件类型" 的限制，判断是否需要进行后面的 "动作"；
  3. 做完所有的动作与条件类型；
  4. 若还有后续的‘行’的资料，则重复上面 1~3 的步骤，直到所有的资料都读完为止。

经过这样的步骤，你会晓得， awk 是‘以行为一次处理的单位’， 而‘以栏位为最小的处理单位’。好了，那么 awk 怎么知道我到底这个资料有几行？有几栏呢？这就需要 awk 的内建变数的帮忙啦～

变数名称 | 代表意义
NF | 每一行 ($0) 拥有的栏位总数
NR | 目前 awk 所处理的是‘第几行’资料
FS | 目前的分隔字元，预设是空白键

我们继续以上面 last -n 5 的例子来做说明，如果我想要：

  • 列出每一行的帐号(就是 $1)；
  • 列出目前处理的行数(就是 awk 内的 NR 变数)
  • 并且说明，该行有多少栏位(就是 awk 内的 NF 变数)

则可以这样：

Tips:
要注意喔，awk 后续的所有动作是以单引号‘ ' ’括住的，由于单引号与双引号都必须是成对的， 所以， awk 的格式内容如果想要以 print 列印时，记得非变数的文字部分，包含上一小节 printf 提到的格式中，都需要使用双引号来定义出来喔！因为单引号已经是 awk 的指令固定用法了！ 		鸟哥的图示
[root@www ~]# last -n 5| awk '{print $1 "\t lines: " NR "\t columes: " NF}'
root     lines: 1        columes: 10
root     lines: 2        columes: 10
root     lines: 3        columes: 10
dmtsai   lines: 4        columes: 10
root     lines: 5        columes: 9
# 注意喔，在 awk 内的 NR, NF 等变数要用大写，且不需要有钱字号 $ 啦！

这样可以了解 NR 与 NF 的差别了吧？好了，底下来谈一谈所谓的 "条件类型" 了吧！

  • awk 的逻辑运算字元

既然有需要用到 "条件" 的类别，自然就需要一些逻辑运算啰～例如底下这些：

运算单元 | 代表意义
> | 大于
< | 小于
>= | 大于或等于
<= | 小于或等于
== | 等于
!= | 不等于

值得注意的是那个‘ == ’的符号，因为：

  • 逻辑运算上面亦即所谓的大于、小于、等于等判断式上面，习惯上是以‘ == ’来表示；
  • 如果是直接给予一个值，例如变数设定时，就直接使用 = 而已。

好了，我们实际来运用一下逻辑判断吧！举例来说，在 /etc/passwd 当中是以冒号 ":" 来作为栏位的分隔， 该档案中第一栏位为帐号，第三栏位则是 UID。那假设我要查阅，第三栏小于 10 以下的数据，并且仅列出帐号与第三栏， 那么可以这样做：

[root@www ~]# cat /etc/passwd | \
> awk '{FS=":"} $3 < 10 {print $1 "\t " $3}'
root:x:0:0:root:/root:/bin/bash
bin      1
daemon   2
....(以下省略)....

有趣吧！不过，怎么第一行没有正确的显示出来呢？这是因为我们读入第一行的时候，那些变数 $1, $2... 预设还是以空白键为分隔的，所以虽然我们定义了 FS=":" 了， 但是却仅能在第二行后才开始生效。那么怎么办呢？我们可以预先设定 awk 的变数啊！ 利用 BEGIN 这个关键字喔！这样做：

[root@www ~]# cat /etc/passwd | \
> awk 'BEGIN {FS=":"} $3 < 10 {print $1 "\t " $3}'
root     0
bin      1
daemon   2
......(以下省略)......

很有趣吧！而除了 BEGIN 之外，我们还有 END 呢！另外，如果要用 awk 来进行‘计算功能’呢？以底下的例子来看， 假设我有一个薪资资料表档名为 pay.txt ，内容是这样的：

Name    1st     2nd     3th
VBird   23000   24000   25000
DMTsai  21000   20000   23000
Bird2   43000   42000   41000

如何帮我计算每个人的总额呢？而且我还想要格式化输出喔！我们可以这样考虑：

  • 第一行只是说明，所以第一行不要进行加总 (NR==1 时处理)；
  • 第二行以后就会有加总的情况出现 (NR>=2 以后处理)
[root@www ~]# cat pay.txt | \
> awk 'NR==1{printf "%10s %10s %10s %10s %10s\n",$1,$2,$3,$4,"Total" }
NR>=2{total = $2 + $3 + $4
printf "%10s %10d %10d %10d %10.2f\n", $1, $2, $3, $4, total}'
      Name        1st        2nd        3th      Total
     VBird      23000      24000      25000   72000.00
    DMTsai      21000      20000      23000   64000.00
     Bird2      43000      42000      41000  126000.00

上面的例子有几个重要事项应该要先说明的：

  • awk 的指令间隔：所有 awk 的动作，亦即在 {} 内的动作，如果有需要多个指令辅助时，可利用分号‘;’间隔， 或者直接以 [Enter] 按键来隔开每个指令，例如上面的范例中，鸟哥共按了三次 [enter] 喔！
  • 逻辑运算当中，如果是‘等于’的情况，则务必使用两个等号‘==’！
  • 格式化输出时，在 printf 的格式设定当中，务必加上 \n ，才能进行分行！
  • 与 bash shell 的变数不同，在 awk 当中，变数可以直接使用，不需加上 $ 符号。

利用 awk 这个玩意儿，就可以帮我们处理很多日常工作了呢！真是好用的很～ 此外， awk 的输出格式当中，常常会以 printf 来辅助，所以， 最好你对 printf 也稍微熟悉一下比较好啦！另外， awk 的动作内 {} 也是支援 if (条件) 的喔！ 举例来说，上面的指令可以修订成为这样：

[root@www ~]# cat pay.txt | \
> awk '{if(NR==1) printf "%10s %10s %10s %10s %10s\n",$1,$2,$3,$4,"Total"}
NR>=2{total = $2 + $3 + $4
printf "%10s %10d %10d %10d %10.2f\n", $1, $2, $3, $4, total}'

你可以仔细的比对一下上面两个输入有啥不同～从中去了解两种语法吧！我个人是比较倾向于使用第一种语法， 因为会比较有统一性啊！ ^_^

除此之外， awk 还可以帮我们进行回圈计算喔！真是相当的好用！不过，那属于比较进阶的单独课程了， 我们这里就不再多加介绍。如果你有兴趣的话，请务必参考延伸阅读中的相关连结喔 (注4)。

小标题的图示 档案比对工具

什么时候会用到档案的比对啊？通常是‘同一个套装软体的不同版本之间，比较设定档与原始档的差异’。 很多时候所谓的档案比对，通常是用在 ASCII 纯文字档的比对上的！那么比对档案的指令有哪些？最常见的就是 diff 啰！ 另外，除了 diff 比对之外，我们还可以藉由 cmp 来比对非纯文字档！同时，也能够藉由 diff 建立的分析档， 以处理补丁 (patch) 功能的档案呢！就来玩玩先！

  • diff

diff 就是用在比对两个档案之间的差异的，并且是以行为单位来比对的！一般是用在 ASCII 纯文字档的比对上。 由于是以行为比对的单位，因此 diff 通常是用在同一的档案(或软体)的新旧版本差异上！ 举例来说，假如我们要将 /etc/passwd 处理成为一个新的版本，处理方式为： 将第四行删除，第六行则取代成为‘no six line’，新的档案放置到 /tmp/test 里面，那么应该怎么做？

[root@www ~]# mkdir -p /tmp/test <==先建立测试用的目录
[root@www ~]# cd /tmp/test
[root@www test]# cp /etc/passwd passwd.old
[root@www test]# cat /etc/passwd | \

> sed -e '4d' -e '6c no six line' > passwd.new
# 注意一下， sed 后面如果要接超过两个以上的动作时，每个动作前面得加 -e 才行！
# 透过这个动作，在 /tmp/test  里面便有新旧的 passwd 档案存在了！

接下来讨论一下关于 diff 的用法吧！

[root@www ~]# diff [-bBi] from-file to-file

选项与参数：
from-file ：一个档名，作为原始比对档案的档名；
to-file   ：一个档名，作为目的比对档案的档名；
注意，from-file 或 to-file 可以 - 取代，那个 - 代表‘Standard input’之意。

-b  ：忽略一行当中，仅有多个空白的差异(例如 "about me" 与 "about     me" 视为相同
-B  ：忽略空白行的差异。
-i  ：忽略大小写的不同。

范例一：比对 passwd.old 与 passwd.new 的差异：
[root@www test]# diff passwd.old passwd.new
4d3    <==左边第四行被删除 (d) 掉了，基准是右边的第三行
< adm:x:3:4:adm:/var/adm:/sbin/nologin  <==这边列出左边(<)档案被删除的那一行内容
6c5    <==左边档案的第六行被取代 (c) 成右边档案的第五行

< sync:x:5:0:sync:/sbin:/bin/sync  <==左边(<)档案第六行内容
---
> no six line                      <==右边(>)档案第五行内容
# 很聪明吧！用 diff 就把我们刚刚的处理给比对完毕了！

用 diff 比对档案真的是很简单喔！不过，你不要用 diff 去比对两个完全不相干的档案，因为比不出个啥咚咚！ 另外， diff 也可以比对整个目录下的差异喔！举例来说，我们想要了解一下不同的开机执行等级 (runlevel) 内容有啥不同？假设你已经知道执行等级 3 与 5 的启动脚本分别放置到 /etc/rc3.d 及 /etc/rc5.d ， 则我们可以将两个目录比对一下：

[root@www ~]# diff /etc/rc3.d/ /etc/rc5.d/
Only in /etc/rc3.d/: K99readahead_later
Only in /etc/rc5.d/: S96readahead_later

我们的 diff 很聪明吧！还可以比对不同目录下的相同档名的内容，这样真的很方便喔～

  • cmp

相对于 diff 的广泛用途， cmp 似乎就用的没有这么多了～ cmp 主要也是在比对两个档案，他主要利用‘位元组’单位去比对， 因此，当然也可以比对 binary file 啰～(还是要再提醒喔， diff 主要是以‘行’为单位比对， cmp 则是以‘位元组’为单位去比对，这并不相同！)

[root@www ~]# cmp [-s] file1 file2
选项与参数：
-s  ：将所有的不同点的位元组处都列出来。因为 cmp 预设仅会输出第一个发现的不同点。

范例一：用 cmp 比较一下 passwd.old 及 passwd.new
[root@www test]# cmp passwd.old passwd.new

passwd.old passwd.new differ: byte 106, line 4

看到了吗？第一个发现的不同点在第四行，而且位元组数是在第 106 个位元组处！这个 cmp 也可以用来比对 binary 啦！ ^_^

  • patch

patch 这个指令与 diff 可是有密不可分的关系啊！我们前面提到，diff 可以用来分辨两个版本之间的差异， 举例来说，刚刚我们所建立的 passwd.old 及 passwd.new 之间就是两个不同版本的档案。 那么，如果要‘升级’呢？就是‘将旧的档案升级成为新的档案’时，应该要怎么做呢？ 其实也不难啦！就是‘先比较先旧版本的差异，并将差异档制作成为补丁档，再由补丁档更新旧档案’即可。 举例来说，我们可以这样做测试：

范例一：以 /tmp/test 内的 passwd.old 与 passwd.new  制作补丁档案
[root@www test]# diff -Naur passwd.old passwd.new > passwd.patch
[root@www test]# cat passwd.patch
--- passwd.old  2009-02-10 14:29:09.000000000 +0800 <==新旧档案的资讯
+++ passwd.new  2009-02-10 14:29:18.000000000 +0800
@@ -1,9 +1,8 @@   <==新旧档案要修改资料的界定范围，旧档在 1-9 行，新档在 1-8 行

 root:x:0:0:root:/root:/bin/bash
 bin:x:1:1:bin:/bin:/sbin/nologin
 daemon:x:2:2:daemon:/sbin:/sbin/nologin
-adm:x:3:4:adm:/var/adm:/sbin/nologin      <==左侧档案删除
 lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
-sync:x:5:0:sync:/sbin:/bin/sync           <==左侧档案删除
+no six line                               <==右侧新档加入
 shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
 halt:x:7:0:halt:/sbin:/sbin/halt
 mail:x:8:12:mail:/var/spool/mail:/sbin/nologin

一般来说，使用 diff 制作出来的比较档案通常使用副档名为 .patch 啰。至于内容就如同上面介绍的样子。 基本上就是以行为单位，看看哪边有一样与不一样的，找到一样的地方，然后将不一样的地方取代掉！ 以上面表格为例，新档案看到 - 会删除，看到 + 会加入！好了，那么如何将旧的档案更新成为新的内容呢？ 就是将 passwd.old 改成与 passwd.new 相同！可以这样做：

[root@www ~]# patch -pN < patch_file    <==更新
[root@www ~]# patch -R -pN < patch_file <==还原
选项与参数：
-p  ：后面可以接‘取消几层目录’的意思。
-R  ：代表还原，将新的档案还原成原来旧的版本。

范例二：将刚刚制作出来的 patch file 用来更新旧版资料
[root@www test]# patch -p0 < passwd.patch
patching file passwd.old
[root@www test]# ll passwd*
-rw-r--r-- 1 root root 1929 Feb 10 14:29 passwd.new
-rw-r--r-- 1 root root 1929 Feb 10 15:12 passwd.old <==档案一模一样！

范例三：恢复旧档案的内容
[root@www test]# patch -R -p0 < passwd.patch
[root@www test]# ll passwd*
-rw-r--r-- 1 root root 1929 Feb 10 14:29 passwd.new
-rw-r--r-- 1 root root 1986 Feb 10 15:18 passwd.old
# 档案就这样恢复成为旧版本啰

为什么这里会使用 -p0 呢？因为我们在比对新旧版的资料时是在同一个目录下， 因此不需要减去目录啦！如果是使用整体目录比对 (diff 旧目录 新目录) 时， 就得要依据建立 patch 档案所在目录来进行目录的删减啰！

更详细的 patch 用法我们会在后续的第五篇的原始码编译 (第二十二章)再跟大家介绍， 这里仅是介绍给你，我们可以利用 diff 来比对两个档案之间的差异， 更可进一步利用这个功能来制作修补档案 (patch file) ，让大家更容易进行比对与升级呢！很不赖吧！ ^_^

小标题的图示 档案列印准备： pr

如果你曾经使用过一些图形介面的文书处理软体的话，那么很容易发现，当我们在列印的时候， 可以同时选择与设定每一页列印时的标头吧！也可以设定页码呢！那么，如果我是在 Linux 底下列印纯文字档呢 可不可以具有标题啊？可不可以加入页码啊？呵呵！当然可以啊！使用 pr 就能够达到这个功能了。不过， pr 的参数实在太多了，鸟哥也说不完，一般来说，鸟哥都仅使用最简单的方式来处理而已。举例来说，如果想要列印 /etc/man.config 呢？

[root@www ~]# pr /etc/man.config

2007-01-06 18:24                 /etc/man.config                  Page 1

#
# Generated automatically from man.conf.in by the
# configure script.

.....以下省略......

上面特殊字体那一行呢，其实就是使用 pr 处理后所造成的标题啦！标题中会有‘档案时间’、‘档案档名’及‘页码’三大项目。 更多的 pr 使用，请参考 pr 的说明啊！ ^_^

大标题的图示 重点回顾
  • 正规表示法就是处理字串的方法，他是以行为单位来进行字串的处理行为；
  • 正规表示法透过一些特殊符号的辅助，可以让使用者轻易的达到‘搜寻/删除/取代’某特定字串的处理程序；
  • 只要工具程式支援正规表示法，那么该工具程式就可以用来作为正规表示法的字串处理之用；
  • 正规表示法与万用字元是完全不一样的东西！万用字元 (wildcard) 代表的是 bash 操作介面的一个功能， 但正规表示法则是一种字串处理的表示方式！
  • 使用 grep 或其他工具进行正规表示法的字串比对时，因为编码的问题会有不同的状态，因此， 你最好将 LANG 等变数设定为 C 或者是 en 等英文语系！
  • grep 与 egrep 在正规表示法里面是很常见的两支程式，其中， egrep 支援更严谨的正规表示法的语法；
  • 由于编码系统的不同，不同的语系 (LANG) 会造成正规表示法撷取资料的差异。因此可利用特殊符号如 [:upper:] 来替代编码范围较佳；
  • 由于严谨度的不同，正规表示法之上还有更严谨的延伸正规表示法；
  • 基础正规表示法的特殊字符有： *, ?, [], [-], [^], ^, $ 等！
  • 常见的正规表示法工具有： grep , sed, vim 等等
  • printf 可以透过一些特殊符号来将资料进行格式化输出；
  • awk 可以使用‘栏位’为依据，进行资料的重新整理与输出；
  • 文件的比对中，可利用 diff 及 cmp 进行比对，其中 diff 主要用在纯文字档案方面的新旧版本比对
  • patch 指令可以将旧版资料更新到新版 (主要亦由 diff 建立 patch 的补丁来源档案)
大标题的图示 本章习题
( 要看答案请将滑鼠移动到‘答：’底下的空白处，按下左键圈选空白处即可察看 )
  • 情境模拟题一：透过 grep 搜寻特殊字串，并配合资料流重导向来处理大量的档案搜寻问题。

    • 目标：正确的使用正规表示法；
    • 前提：需要了解资料流重导向，以及透过子指令 $(command) 来处理档名的搜寻；

    我们简单的以搜寻星号 (*) 来处理底下的任务：

    1. 利用正规表示法找出系统中含有某些特殊关键字的档案，举例来说，找出在 /etc 底下含有星号 (*) 的档案与内容：

      解决的方法必须要搭配万用字元，但是星号本身就是正规表示法的字符，因此需要如此进行：
      [root@www ~]# grep '\*' /etc/*
      你必须要注意的是，在单引号内的星号是正规表示法的字符，但我们要找的是星号，因此需要加上跳脱字符 (\)。但是在 /etc/* 的那个 * 则是 bash 的万用字元！ 代表的是档案的档名喔！不过由上述的这个结果中，我们仅能找到 /etc 底下第一层子目录的资料，无法找到次目录的资料， 如果想要连同完整的 /etc 次目录资料，就得要这样做：
      [root@www ~]# grep '\*' $(find /etc -type f)

    2. 但如果档案数量太多呢？如同上述的案例，如果要找的是全系统 (/) 呢？你可以这样做：
      [root@www ~]# grep '\*' $(find / -type f)
-bash: /bin/grep: Argument list too long
      真要命！由于指令列的内容长度是有限制的，因此当搜寻的对象是整个系统时，上述的指令会发生错误。那该如何是好？ 此时我们可以透过管线命令以及 xargs 来处理。举例来说，让 grep 每次仅能处理 10 个档名，此时你可以这样想：

      1. 先用 find 去找出档案；
      2. 用 xargs 将这些档案每次丢 10 个给 grep 来作为参数处理；
      3. grep 实际开始搜寻档案内容。

      所以整个作法就会变成这样：
      [root@www ~]# find / -type f | xargs -n 10 grep '\*'

    3. 从输出的结果来看，资料量实在非常庞大！那如果我只是想要知道档名而已呢？你可以透过 grep 的功能来找到如下的参数！
      [root@www ~]# find / -type f | xargs -n 10 grep -l '\*'

  • 情境模拟题二：使用管线命令配合正规表示法建立新指令与新变数。我想要建立一个新的指令名为 myip ， 这个指令能够将我系统的 IP 捉出来显示。而我想要有个新变数，变数名为 MYIP ，这个变数可以记录我的 IP 。

    处理的方式很简单，我们可以这样试看看：

    1. 首先，我们依据本章内的 ifconfig, sed 与 awk 来取得我们的 IP ，指令为：
      [root@www ~]# ifconfig eth0 | grep 'inet addr' | \
>  sed 's/^.*inet addr://g'| cut -d ' ' -f1
    2. 再来，我们可以将此指令利用 alias 指定为 myip 喔！如下所示：
      [root@www ~]# alias myip="ifconfig eth0 | grep 'inet addr' | \
>  sed 's/^.*inet addr://g'| cut -d ' ' -f1 "
    3. 最终，我们可以透过变数设定来处理 MYIP 喔！
      [root@www ~]# MYIP=$( myip )
    4. 如果每次登入都要生效，可以将 alias 与 MYIP 的设定那两行，写入你的 ~/.bashrc 即可！

简答题部分：
  • 我想要知道，在 /etc 底下，只要含有 XYZ 三个字元的任何一个字元的那一行就列出来，要怎样进行？
    grep [XYZ] /etc/*
  • 将 /etc/termcap 内容取出后，(1)去除开头为 # 的行 (2)去除空白行 (3)取出开头为英文字母的那几行 (4)最终统计总行数该如何进行？
    grep -v '^#' /etc/termcap | grep -v '^$' | grep '^[:alpha:]' | wc -l
大标题的图示 参考资料与延伸阅读
  • 注1：关于正规表示法与 POSIX 及特殊语法的参考网址可以查询底下的来源：
    维基百科的说明：http://en.wikipedia.org/wiki/Regular_expression
    ZYTRAX 网站介绍：http://zytrax.com/tech/web/regex.htm
  • 注2：其他关于正规表示法的网站介绍：
    洪朝贵老师的网页：http://www.cyut.edu.tw/~ckhung/b/re/index.php
    龙门少尉的窝：http://main.rtfiber.com.tw/~changyj/
    PCRE 官方网站：http://perldoc.perl.org/perlre.html
  • 注3：关于 ASCII 编码对照表可参考维基百科的介绍：
    维基百科 (ASCII) 条目： http://zh.wikipedia.org/w/index.php?title=ASCII&variant=zh-tw
  • 注4：关于 awk 的进阶文献，包括有底下几个连结：
    中研院计算中心 ASPAC 计划之 awk 程式介绍：http://phi.sinica.edu.tw/aspac/reports/94/94011/
    鸟哥备份：http://linux.vbird.org/linux_basic/0330regularex/awk.pdf
    这份文件写的非常棒！欢迎大家多多参考！
    Study Area：http://www.study-area.org/linux/system/linux_shell.htm
2002/07/29：第一次完成；
2003/02/10：重新编排与加入 FAQ ；
2005/01/28：重新汇整基础正规表示法的内容！重点在 regular_express.txt 的处理与练习上！
2005/03/30：修订了 grep -n 'goo*g' regular_express.txt 这一段
2005/05/23：修订了 grep -n '^[a-z]' regular_express.txt 所要撷取的是小写，之前写成大写，错了！
2005/08/22：加入了 awk, sed 等工具的介绍，还有 diff 与 cmp 等指令的说明！
2005/09/05：加入 printf 内，关于 \xNN 的说明！
2006/03/10：将原本的 sed 内的动作(action)中， s 由‘搜寻’改成‘取代’了！
2006/10/05：在 sed 当中多了一个 -i 的参数说明，也多了一个范例八可以参考。感谢讨论区的thyme兄！
2008/10/08：加入 grep 内的 --color=auto 说明！
2009/02/07：将旧的基于 FC4 版本的文章移动到此处
2009/02/10：重新排版，并且加入语系的说明，以及特殊 [:资料:] 的说明！更改不少范例的说明。
2009/05/14：感谢网友 Jack 的回报， cmp 应该是使用‘位元组 bytes’而非位元 bits，感谢 Jack 兄。
2009/08/26：加入情境模拟题目了！


鸟哥的 Linux 私房菜 -- 基础学习篇

为取得较佳浏览结果，请爱用 firefox 浏览本网页

第十三章、学习 Shell Scripts
最近更新日期：2009/02/18
如果你真的很想要走资讯这条路，并且想要管理好属于你的主机，那么，别说鸟哥不告诉你， 可以自动管理系统的好工具： Shell scripts！这家伙真的是得要好好学习学习的！ 基本上， shell script 有点像是早期的批次档，亦即是将一些指令汇整起来一次执行，但是 Shell script 拥有更强大的功能，那就是他可以进行类似程式 (program) 的撰写，并且不需要经过编译 (compile) 就能够执行， 真的很方便。加上我们可透过 shell script 来简化我们日常的工作管理， 而且，整个 Linux 环境中，一些服务 (services) 的启动都是透过 shell script 的， 如果你对于 script 不了解，嘿嘿！发生问题时，可真是会求助无门喔！所以，好好的学一学他吧！

1. 什么是 Shell Script
    1.1 干嘛学习 shell scripts
    1.2 第一支 script 的撰写与执行
    1.3 撰写 shell script 的良好习惯建立
 2. 简单的 shell script 练习
    2.1 简单范例： 对谈式脚本, 随日期变化, 数值运算
    2.2 script 的执行方式差异 (source, sh script, ./script)
 3. 善用判断式
    3.1 利用 test 指令的测试功能
    3.2 利用判断符号 [ ]
    3.3 Shell script 的预设变数($0, $1...)： shift
 4. 条件判断式
    4.1 利用 if .... then： 单层简单条件, 多重复杂条件, 检验$1内容, 网路状态, 退伍
    4.2 利用 case ..... esac 判断
    4.3 利用 function 功能
 5. 回圈 (loop)
    5.1 while...do...done, until...do...done (不定回圈)
    5.2 for...do...done (固定回圈)： 帐号检查, 网路状态 $(seq )
    5.3 for...do...done 的数值处理
 6. shell script 的追踪与 debug
7. 重点回顾
8. 本章习题
9. 参考资料与延伸阅读
10. 针对本文的建议：http://phorum.vbird.org/viewtopic.php?t=23886
大标题的图示 什么是 Shell scripts

什么是 shell script (程式化脚本) 呢？就字面上的意义，我们将他分为两部份。 在‘ shell ’部分，我们在 十一章的 BASH 当中已经提过了，那是一个文字介面底下让我们与系统沟通的一个工具介面。那么‘ script ’是啥？ 字面上的意义， script 是‘脚本、剧本’的意思。整句话是说， shell script 是针对 shell 所写的‘剧本！’

什么东西啊？其实， shell script 是利用 shell 的功能所写的一个‘程式 (program)’，这个程式是使用纯文字档，将一些 shell 的语法与指令(含外部指令)写在里面， 搭配正规表示法、管线命令与资料流重导向等功能，以达到我们所想要的处理目的。

所以，简单的说， shell script 就像是早期 DOS 年代的批次档 (.bat) ，最简单的功能就是将许多指令汇整写在一起， 让使用者很轻易的就能够 one touch 的方法去处理复杂的动作 (执行一个档案 "shell script" ，就能够一次执行多个指令)。 而且 shell script 更提供阵列、回圈、条件与逻辑判断等重要功能，让使用者也可以直接以 shell 来撰写程式，而不必使用类似 C 程式语言等传统程式撰写的语法呢！

这么说你可以了解了吗？是的！ shell script 可以简单的被看成是批次档， 也可以被说成是一个程式语言，且这个程式语言由于都是利用 shell 与相关工具指令， 所以不需要编译即可执行，且拥有不错的除错 (debug) 工具，所以，他可以帮助系统管理员快速的管理好主机。

小标题的图示 干嘛学习 shell scripts

这是个好问题：‘我又干嘛一定要学 shell script ？我又不是资讯人，没有写程式的概念， 那我干嘛还要学 shell script 呢？不要学可不可以啊？’呵呵～如果 Linux 对你而言， 你只是想要‘会用’而已，那么，不需要学 shell script 也还无所谓，这部分先给他跳过去， 等到有空的时候，再来好好的瞧一瞧。但是，如果你是真的想要玩清楚 Linux 的来龙去脉， 那么 shell script 就不可不知，为什么呢？因为：

  • 自动化管理的重要依据：

    不用鸟哥说你也知道，管理一部主机真不是件简单的事情，每天要进行的任务就有： 查询登录档、追踪流量、监控使用者使用主机状态、主机各项硬体设备状态、 主机软体更新查询、更不要说得应付其他使用者的突然要求了。而这些工作的进行可以分为： (1)自行手动处理，或是 (2)写个简单的程式来帮你每日自动处理分析这两种方式，你觉得哪种方式比较好？ 当然是让系统自动工作比较好，对吧！呵呵～这就得要良好的 shell script 来帮忙的啦！

  • 追踪与管理系统的重要工作：

    虽然我们还没有提到服务启动的方法，不过，这里可以先提一下，我们 Linux 系统的服务 (services) 启动的介面是在 /etc/init.d/ 这个目录下，目录下的所有档案都是 scripts ； 另外，包括开机 (booting) 过程也都是利用 shell script 来帮忙搜寻系统的相关设定资料， 然后再代入各个服务的设定参数啊！举例来说，如果我们想要重新启动系统登录档， 可以使用：‘/etc/init.d/syslogd restart’，那个 syslogd 档案就是 script 啦！

    另外，鸟哥曾经在某一代的 Fedora 上面发现，启动 MySQL 这个资料库服务时，确实是可以启动的， 但是荧幕上却老是出现‘failure’！后来才发现，原来是启动 MySQL 那个 script 会主动的以‘空的密码’去尝试登入 MySQL ，但为了安全性鸟哥修改过 MySQL 的密码啰～当然就登入失败～ 后来改了改 script ，就略去这个问题啦！如此说来， script 确实是需要学习的啊！

  • 简单入侵侦测功能：

    当我们的系统有异状时，大多会将这些异状记录在系统记录器，也就是我们常提到的‘系统登录档’， 那么我们可以在固定的几分钟内主动的去分析系统登录档，若察觉有问题，就立刻通报管理员， 或者是立刻加强防火墙的设定规则，如此一来，你的主机可就能够达到‘自我保护’的聪明学习功能啦～ 举例来说，我们可以通过 shell script 去分析‘当该封包尝试几次还是连线失败之后，就予以抵挡住该 IP’之类的举动，例如鸟哥写过一个关于抵挡砍站软体的 shell script ， 就是用这个想法去达成的呢！

  • 连续指令单一化：

    其实，对于新手而言， script 最简单的功能就是：‘汇整一些在 command line 下达的连续指令，将他写入 scripts 当中，而由直接执行 scripts 来启动一连串的 command line 指令输入！’例如： 防火墙连续规则 (iptables)，开机载入程序的项目 (就是在 /etc/rc.d/rc.local 里头的资料) ，等等都是相似的功能啦！ 其实，说穿了，如果不考虑 program 的部分，那么 scripts 也可以想成‘仅是帮我们把一大串的指令汇整在一个档案里面， 而直接执行该档案就可以执行那一串又臭又长的指令段！’就是这么简单啦！

  • 简易的资料处理：

    由前一章正规表示法的 awk 程式说明中， 你可以发现， awk 可以用来处理简单的数据资料呢！例如薪资单的处理啊等等的。 shell script 的功能更强大，例如鸟哥曾经用 shell script 直接处理数据资料的比对啊， 文字资料的处理啊等等的，撰写方便，速度又快(因为在 Linux 效能较佳)，真的是很不错用的啦！

  • 跨平台支援与学习历程较短：

    几乎所有的 Unix Like 上面都可以跑 shell script ，连 MS Windows 系列也有相关的 script 模拟器可以用， 此外， shell script 的语法是相当亲和的，看都看的懂得文字 (虽然是英文)，而不是机器码， 很容易学习～这些都是你可以加以考量的学习点啊！

上面这些都是你考虑学习 shell script 的特点～此外， shell script 还可以简单的以 vim 来直接编写，实在是很方便的好东西！所以，还是建议你学习一下啦。

不过，虽然 shell script 号称是程式 (program) ，但实际上， shell script 处理资料的速度上是不太够的。因为 shell script 用的是外部的指令与 bash shell 的一些预设工具，所以，他常常会去呼叫外部的函式库，因此，运算速度上面当然比不上传统的程式语言。 所以啰， shell script 用在系统管理上面是很好的一项工具，但是用在处理大量数值运算上， 就不够好了，因为 Shell scripts 的速度较慢，且使用的 CPU 资源较多，造成主机资源的分配不良。还好， 我们通常利用 shell script 来处理伺服器的侦测，倒是没有进行大量运算的需求啊！所以不必担心的啦！

小标题的图示 第一支 script 的撰写与执行

如同前面讲到的，shell script 其实就是纯文字档，我们可以编辑这个档案，然后让这个档案来帮我们一次执行多个指令， 或者是利用一些运算与逻辑判断来帮我们达成某些功能。所以啦，要编辑这个档案的内容时，当然就需要具备有 bash 指令下达的相关认识。下达指令需要注意的事项在第五章的开始下达指令小节内已经提过，有疑问请自行回去翻阅。 在 shell script 的撰写中还需要用到底下的注意事项：

  1. 指令的执行是从上而下、从左而右的分析与执行；
  2. 指令的下达就如同第五章内提到的： 指令、选项与参数间的多个空白都会被忽略掉；
  3. 空白行也将被忽略掉，并且 [tab] 按键所推开的空白同样视为空白键；
  4. 如果读取到一个 Enter 符号 (CR) ，就尝试开始执行该行 (或该串) 命令；
  5. 至于如果一行的内容太多，则可以使用‘ \[Enter] ’来延伸至下一行；
  6. ‘ # ’可做为注解！任何加在 # 后面的资料将全部被视为注解文字而被忽略！

如此一来，我们在 script 内所撰写的程式，就会被一行一行的执行。现在我们假设你写的这个程式档名是 /home/dmtsai/shell.sh 好了，那如何执行这个档案？很简单，可以有底下几个方法：

  • 直接指令下达： shell.sh 档案必须要具备可读与可执行 (rx) 的权限，然后：
    • 绝对路径：使用 /home/dmtsai/shell.sh 来下达指令；
    • 相对路径：假设工作目录在 /home/dmtsai/ ，则使用 ./shell.sh 来执行
    • 变数‘PATH’功能：将 shell.sh 放在 PATH 指定的目录内，例如： ~/bin/

  • 以 bash 程式来执行：透过‘ bash shell.sh ’或‘ sh shell.sh ’来执行

反正重点就是要让那个 shell.sh 内的指令可以被执行的意思啦！ 咦！那我为何需要使用 ‘./shell.sh ’来下达指令？忘记了吗？回去第十一章内的指令搜寻顺序察看一下， 你就会知道原因了！同时，由于 CentOS 预设使用者家目录下的 ~/bin 目录会被设定到 $PATH 内，所以你也可以将 shell.sh 建立在 /home/dmtsai/bin/ 底下 ( ~/bin 目录需要自行设定) 。此时，若 shell.sh 在 ~/bin 内且具有 rx 的权限，那就直接输入 shell.sh 即可执行该脚本程式！

那为何‘ sh shell.sh ’也可以执行呢？这是因为 /bin/sh 其实就是 /bin/bash (连结档)，使用 sh shell.sh 亦即告诉系统，我想要直接以 bash 的功能来执行 shell.sh 这个档案内的相关指令的意思，所以此时你的 shell.sh 只要有 r 的权限即可被执行喔！而我们也可以利用 sh 的参数，如 -n 及 -x 来检查与追踪 shell.sh 的语法是否正确呢！ ^_^

  • 撰写第一支 script

在武侠世界中，不论是那个门派，要学武功要从扫地做起，那么要学程式呢？呵呵，肯定是由‘秀出 Hello World！’ 这个字眼开始的！OK！那么鸟哥就先写一支 script 给大家瞧一瞧：

[root@www ~]# mkdir scripts; cd scripts

[root@www scripts]# vi sh01.sh
#!/bin/bash
# Program:
#       This program shows "Hello World!" in your screen.
# History:
# 2005/08/23	VBird	First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
echo -e "Hello World! \a \n"
exit 0

在本章当中，请将所有撰写的 script 放置到你家目录的 ~/scripts 这个目录内， 未来比较好管理啦！上面的写法当中，鸟哥主要将整个程式的撰写分成数段，大致是这样：

  1. 第一行 #!/bin/bash 在宣告这个 script 使用的 shell 名称：
    因为我们使用的是 bash ，所以，必须要以‘ #!/bin/bash ’来宣告这个档案内的语法使用 bash 的语法！那么当这个程式被执行时，他就能够载入 bash 的相关环境设定档 (一般来说就是 non-login shell 的 ~/.bashrc)， 并且执行 bash 来使我们底下的指令能够执行！这很重要的！(在很多状况中，如果没有设定好这一行， 那么该程式很可能会无法执行，因为系统可能无法判断该程式需要使用什么 shell 来执行啊！)

  2. 程式内容的说明：
     整个 script 当中，除了第一行的‘ #! ’是用来宣告 shell 的之外，其他的 # 都是‘注解’用途！ 所以上面的程式当中，第二行以下就是用来说明整个程式的基本资料。一般来说， 建议你一定要养成说明该 script 的：1. 内容与功能； 2. 版本资讯； 3. 作者与联络方式； 4. 建档日期；5. 历史纪录 等等。这将有助于未来程式的改写与 debug 呢！

  3. 主要环境变数的宣告：
    建议务必要将一些重要的环境变数设定好，鸟哥个人认为， PATH 与 LANG (如果有使用到输出相关的资讯时) 是当中最重要的！ 如此一来，则可让我们这支程式在进行时，可以直接下达一些外部指令，而不必写绝对路径呢！比较好啦！

  4. 主要程式部分
    就将主要的程式写好即可！在这个例子当中，就是 echo 那一行啦！

  5. 执行成果告知 (定义回传值)
    是否记得我们在第十一章里面要讨论一个指令的执行成功与否，可以使用 $? 这个变数来观察～ 那么我们也可以利用 exit 这个指令来让程式中断，并且回传一个数值给系统。 在我们这个例子当中，鸟哥使用 exit 0 ，这代表离开 script 并且回传一个 0 给系统， 所以我执行完这个 script 后，若接着下达 echo $? 则可得到 0 的值喔！ 更聪明的读者应该也知道了，呵呵！利用这个 exit n (n 是数字) 的功能，我们还可以自订错误讯息， 让这支程式变得更加的 smart 呢！

接下来透过刚刚上头介绍的执行方法来执行看看结果吧！

[root@www scripts]# sh sh01.sh
Hello World !

你会看到荧幕是这样，而且应该还会听到‘咚’的一声，为什么呢？还记得前一章提到的 printf 吧？用 echo 接着那些特殊的按键也可以发生同样的事情～ 不过， echo 必须要加上 -e 的选项才行！呵呵！在你写完这个小 script 之后，你就可以大声的说：‘我也会写程式了’！哈哈！ 很简单有趣吧～ ^_^

另外，你也可以利用：‘chmod a+x sh01.sh; ./sh01.sh’来执行这个 script 的呢！

小标题的图示 撰写 shell script 的良好习惯建立

一个良好习惯的养成是很重要的～大家在刚开始撰写程式的时候，最容易忽略这部分， 认为程式写出来就好了，其他的不重要。其实，如果程式的说明能够更清楚，那么对你自己是有很大的帮助的。

举例来说，鸟哥自己为了自己的需求，曾经撰写了不少的 script 来帮我进行主机 IP 的侦测啊、 登录档分析与管理啊、自动上传下载重要设定档啊等等的，不过，早期就是因为太懒了， 管理的主机又太多了，常常同一个程式在不同的主机上面进行更改，到最后，到底哪一支才是最新的都记不起来， 而且，重点是，我到底是改了哪里？为什么做那样的修改？都忘的一干二净～真要命～

所以，后来鸟哥在写程式的时候，通常会比较仔细的将程式的设计过程给他记录下来，而且还会记录一些历史纪录， 如此一来，好多了～至少很容易知道我修改了哪些资料，以及程式修改的理念与逻辑概念等等， 在维护上面是轻松很多很多的喔！

另外，在一些环境的设定上面，毕竟每个人的环境都不相同，为了取得较佳的执行环境， 我都会自行先定义好一些一定会被用到的环境变数，例如 PATH 这个玩意儿！ 这样比较好啦～所以说，建议你一定要养成良好的 script 撰写习惯，在每个 script 的档头处记录好：

  • script 的功能；
  • script 的版本资讯；
  • script 的作者与联络方式；
  • script 的版权宣告方式；
  • script 的 History (历史纪录)；
  • script 内较特殊的指令，使用‘绝对路径’的方式来下达；
  • script 运作时需要的环境变数预先宣告与设定。

除了记录这些资讯之外，在较为特殊的程式码部分，个人建议务必要加上注解说明，可以帮助你非常非常多！ 此外，程式码的撰写最好使用巢状方式，在包覆的内部程式码最好能以 [tab] 按键的空格向后推， 这样你的程式码会显的非常的漂亮与有条理！在查阅与 debug 上较为轻松愉快喔！ 另外，使用撰写 script 的工具最好使用 vim 而不是 vi ，因为 vim 会有额外的语法检验机制，能够在第一阶段撰写时就发现语法方面的问题喔！

大标题的图示 简单的 shell script 练习

在第一支 shell script 撰写完毕之后，相信你应该具有基本的撰写功力了。 接下来，在开始更深入的程式概念之前，我们先来玩一些简单的小范例好了。 底下的范例中，达成结果的方式相当的多，建议你先自行撰写看看，写完之后再与鸟哥写的内容比对， 这样才能更加深概念喔！好！不啰唆，我们就一个一个来玩吧！

小标题的图示 简单范例

底下的范例在很多的脚本程式中都会用到，而底下的范例又都很简单！值得参考看看喔！

  • 对谈式脚本：变数内容由使用者决定

很多时候我们需要使用者输入一些内容，好让程式可以顺利运作。 简单的来说，大家应该都有安装过软体的经验，安装的时候，他不是会问你‘要安装到那个目录去’吗？ 那个让使用者输入资料的动作，就是让使用者输入变数内容啦。

你应该还记得在十一章 bash 的时候，我们有学到一个 read 指令吧？现在，请你以 read 指令的用途，撰写一个 script ，他可以让使用者输入：1. first name 与 2. last name， 最后并且在荧幕上显示：‘Your full name is: ’的内容：

[root@www scripts]# vi sh02.sh
#!/bin/bash
# Program:
#	User inputs his first name and last name.  Program shows his full name.
# History:
# 2005/08/23	VBird	First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH

read -p "Please input your first name: " firstname  # 提示使用者输入
read -p "Please input your last name:  " lastname   # 提示使用者输入
echo -e "\nYour full name is: $firstname $lastname" # 结果由荧幕输出

将上面这个 sh02.sh 执行一下，你就能够发现使用者自己输入的变数可以让程式所取用，并且将他显示到荧幕上！ 接下来，如果想要制作一个每次执行都会依据不同的日期而变化结果的脚本呢？

  • 随日期变化：利用 date 进行档案的建立

想像一个状况，假设我的伺服器内有资料库，资料库每天的资料都不太一样，因此当我备份时， 希望将每天的资料都备份成不同的档名，这样才能够让旧的资料也能够保存下来不被覆盖。 哇！不同档名呢！这真困扰啊？难道要我每天去修改 script ？

不需要啊！考虑每天的‘日期’并不相同，所以我可以将档名取成类似： backup.2009-02-14.data ， 不就可以每天一个不同档名了吗？呵呵！确实如此。那个 2009-02-14 怎么来的？那就是重点啦！接下来出个相关的例子： 假设我想要建立三个空的档案 (透过 touch) ，档名最开头由使用者输入决定，假设使用者输入 filename 好了，那今天的日期是 2009/02/14 ， 我想要以前天、昨天、今天的日期来建立这些档案，亦即 filename_20090212, filename_20090213, filename_20090214 ，该如何是好？

[root@www scripts]# vi sh03.sh
#!/bin/bash
# Program:
#	Program creates three files, which named by user's input
#	and date command.
# History:
# 2005/08/23	VBird	First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH

# 1. 让使用者输入档案名称，并取得 fileuser 这个变数；
echo -e "I will use 'touch' command to create 3 files." # 纯粹显示资讯
read -p "Please input your filename: " fileuser         # 提示使用者输入

# 2. 为了避免使用者随意按 Enter ，利用变数功能分析档名是否有设定？

filename=${fileuser:-"filename"}           # 开始判断有否设定档名

# 3. 开始利用 date 指令来取得所需要的档名了；
date1=$(date --date='2 days ago' +%Y%m%d)  # 前两天的日期
date2=$(date --date='1 days ago' +%Y%m%d)  # 前一天的日期
date3=$(date +%Y%m%d)                      # 今天的日期
file1=${filename}${date1}                  # 底下三行在设定档名

file2=${filename}${date2}
file3=${filename}${date3}

# 4. 将档名建立吧！
touch "$file1"                             # 底下三行在建立档案
touch "$file2"
touch "$file3"

上面的范例鸟哥使用了很多在十一章介绍过的概念： 包括小指令‘ $(command) ’的取得讯息、变数的设定功能、变数的累加以及利用 touch 指令辅助！ 如果你开始执行这个 sh03.sh 之后，你可以进行两次执行：一次直接按 [Enter] 来查阅档名是啥？ 一次可以输入一些字元，这样可以判断你的脚本是否设计正确喔！

  • 数值运算：简单的加减乘除

各位看官应该还记得，我们可以使用 declare 来定义变数的类型吧？ 当变数定义成为整数后才能够进行加减运算啊！此外，我们也可以利用‘ $((计算式)) ’来进行数值运算的。 可惜的是， bash shell 里头预设仅支援到整数的资料而已。OK！那我们来玩玩看，如果我们要使用者输入两个变数， 然后将两个变数的内容相乘，最后输出相乘的结果，那可以怎么做？

[root@www scripts]# vi sh04.sh
#!/bin/bash
# Program:
#	User inputs 2 integer numbers; program will cross these two numbers.
# History:
# 2005/08/23	VBird	First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
echo -e "You SHOULD input 2 numbers, I will cross them! \n"
read -p "first number:  " firstnu
read -p "second number: " secnu
total=$(($firstnu*$secnu))
echo -e "\nThe result of $firstnu x $secnu is ==> $total"

在数值的运算上，我们可以使用‘ declare -i total=$firstnu*$secnu ’ 也可以使用上面的方式来进行！基本上，鸟哥比较建议使用这样的方式来进行运算：

var=$((运算内容))

不但容易记忆，而且也比较方便的多，因为两个小括号内可以加上空白字元喔！ 未来你可以使用这种方式来计算的呀！至于数值运算上的处理，则有：‘ +, -, *, /, % ’等等。 那个 % 是取余数啦～举例来说， 13 对 3 取余数，结果是 13=4*3+1，所以余数是 1 啊！就是：

[root@www scripts]# echo $(( 13 % 3 ))
1

这样了解了吧？多多学习与应用喔！ ^_^

小标题的图示 script 的执行方式差异 (source, sh script, ./script)

不同的 script 执行方式会造成不一样的结果喔！尤其影响 bash 的环境很大呢！脚本的执行方式除了前面小节谈到的方式之外，还可以利用 source 或小数点 (.) 来执行喔！那么这种执行方式有何不同呢？当然是不同的啦！让我们来说说！

  • 利用直接执行的方式来执行 script

当使用前一小节提到的直接指令下达 (不论是绝对路径/相对路径还是 $PATH 内)，或者是利用 bash (或 sh) 来下达脚本时， 该 script 都会使用一个新的 bash 环境来执行脚本内的指令！也就是说，使用者种执行方式时， 其实 script 是在子程序的 bash 内执行的！我们在第十一章 BASH 内谈到 export 的功能时，曾经就父程序/子程序谈过一些概念性的问题， 重点在于：‘当子程序完成后，在子程序内的各项变数或动作将会结束而不会传回到父程序中’！ 这是什么意思呢？

我们举刚刚提到过的 sh02.sh 这个脚本来说明好了，这个脚本可以让使用者自行设定两个变数，分别是 firstname 与 lastname，想一想，如果你直接执行该指令时，该指令帮你设定的 firstname 会不会生效？看一下底下的执行结果：

[root@www scripts]# echo $firstname $lastname
    <==确认了，这两个变数并不存在喔！
[root@www scripts]# sh sh02.sh
Please input your first name: VBird <==这个名字是鸟哥自己输入的

Please input your last name:  Tsai

Your full name is: VBird Tsai      <==看吧！在 script 运作中，这两个变数有生效
[root@www scripts]# echo $firstname $lastname
    <==事实上，这两个变数在父程序的 bash 中还是不存在的！

上面的结果你应该会觉得很奇怪，怎么我已经利用 sh02.sh 设定好的变数竟然在 bash 环境底下无效！怎么回事呢？ 如果将程序相关性绘制成图的话，我们以下图来说明。当你使用直接执行的方法来处理时，系统会给予一支新的 bash 让我们来执行 sh02.sh 里面的指令，因此你的 firstname, lastname 等变数其实是在下图中的子程序 bash 内执行的。 当 sh02.sh 执行完毕后，子程序 bash 内的所有资料便被移除，因此上表的练习中，在父程序底下 echo $firstname 时， 就看不到任何东西了！这样可以理解吗？

图 2.2.1、sh02.sh 在子程序中运作

  • 利用 source 来执行脚本：在父程序中执行

如果你使用 source 来执行指令那就不一样了！同样的脚本我们来执行看看：

[root@www scripts]# source sh02.sh
Please input your first name: VBird
Please input your last name:  Tsai

Your full name is: VBird Tsai
[root@www scripts]# echo $firstname $lastname

VBird Tsai  <==嘿嘿！有资料产生喔！

竟然生效了！没错啊！因为 source 对 script 的执行方式可以使用底下的图示来说明！ sh02.sh 会在父程序中执行的，因此各项动作都会在原本的 bash 内生效！这也是为啥你不登出系统而要让某些写入 ~/.bashrc 的设定生效时，需要使用‘ source ~/.bashrc ’而不能使用‘ bash ~/.bashrc ’是一样的啊！

图 2.2.2、sh02.sh 在父程序中运作
大标题的图示 善用判断式

在第十一章中，我们提到过 $? 这个变数所代表的意义， 此外，也透过 && 及 || 来作为前一个指令执行回传值对于后一个指令是否要进行的依据。第十一章的讨论中，如果想要判断一个目录是否存在， 当时我们使用的是 ls 这个指令搭配资料流重导向，最后配合 $? 来决定后续的指令进行与否。 但是否有更简单的方式可以来进行‘条件判断’呢？有的～那就是‘ test ’这个指令。

小标题的图示 利用 test 指令的测试功能

当我要检测系统上面某些档案或者是相关的属性时，利用 test 这个指令来工作真是好用得不得了， 举例来说，我要检查 /dmtsai 是否存在时，使用：

[root@www ~]# test -e /dmtsai

执行结果并不会显示任何讯息，但最后我们可以透过 $? 或 && 及 || 来展现整个结果呢！ 例如我们在将上面的例子改写成这样：

[root@www ~]# test -e /dmtsai && echo "exist" || echo "Not exist"
Not exist  <==结果显示不存在啊！

最终的结果可以告知我们是‘exist’还是‘Not exist’呢！那我知道 -e 是测试一个‘东西’在不在， 如果还想要测试一下该档名是啥玩意儿时，还有哪些标志可以来判断的呢？呵呵！有底下这些东西喔！

测试的标志 | 代表意义
1. 关于某个档名的‘档案类型’判断，如 test -e filename 表示存在否
-e | 该‘档名’是否存在？(常用)
-f | 该‘档名’是否存在且为档案(file)？(常用)
-d | 该‘档名’是否存在且为目录(directory)？(常用)
-b | 该‘档名’是否存在且为一个 block device 装置？
-c | 该‘档名’是否存在且为一个 character device 装置？
-S | 该‘档名’是否存在且为一个 Socket 档案？
-p | 该‘档名’是否存在且为一个 FIFO (pipe) 档案？
-L | 该‘档名’是否存在且为一个连结档？
2. 关于档案的权限侦测，如 test -r filename 表示可读否 (但 root 权限常有例外)
-r | 侦测该档名是否存在且具有‘可读’的权限？
-w | 侦测该档名是否存在且具有‘可写’的权限？
-x | 侦测该档名是否存在且具有‘可执行’的权限？
-u | 侦测该档名是否存在且具有‘SUID’的属性？
-g | 侦测该档名是否存在且具有‘SGID’的属性？
-k | 侦测该档名是否存在且具有‘Sticky bit’的属性？
-s | 侦测该档名是否存在且为‘非空白档案’？
3. 两个档案之间的比较，如： test file1 -nt file2
-nt | (newer than)判断 file1 是否比 file2 新
-ot | (older than)判断 file1 是否比 file2 旧
-ef | 判断 file1 与 file2 是否为同一档案，可用在判断 hard link 的判定上。 主要意义在判定，两个档案是否均指向同一个 inode 哩！
4. 关于两个整数之间的判定，例如 test n1 -eq n2
-eq | 两数值相等 (equal)
-ne | 两数值不等 (not equal)
-gt | n1 大于 n2 (greater than)
-lt | n1 小于 n2 (less than)
-ge | n1 大于等于 n2 (greater than or equal)
-le | n1 小于等于 n2 (less than or equal)
5. 判定字串的资料
test -z string | 判定字串是否为 0 ？若 string 为空字串，则为 true
test -n string | 判定字串是否非为 0 ？若 string 为空字串，则为 false。 注： -n 亦可省略
test str1 = str2 | 判定 str1 是否等于 str2 ，若相等，则回传 true
test str1 != str2 | 判定 str1 是否不等于 str2 ，若相等，则回传 false
6. 多重条件判定，例如： test -r filename -a -x filename
-a | (and)两状况同时成立！例如 test -r file -a -x file，则 file 同时具有 r 与 x 权限时，才回传 true。
-o | (or)两状况任何一个成立！例如 test -r file -o -x file，则 file 具有 r 或 x 权限时，就可回传 true。
! | 反相状态，如 test ! -x file ，当 file 不具有 x 时，回传 true

OK！现在我们就利用 test 来帮我们写几个简单的例子。首先，判断一下，让使用者输入一个档名，我们判断：

  1. 这个档案是否存在，若不存在则给予一个‘Filename does not exist’的讯息，并中断程式；
  2. 若这个档案存在，则判断他是个档案或目录，结果输出‘Filename is regular file’或 ‘Filename is directory’
  3. 判断一下，执行者的身份对这个档案或目录所拥有的权限，并输出权限资料！

你可以先自行创作看看，然后再跟底下的结果讨论讨论。注意利用 test 与 && 还有 || 等标志！

[root@www scripts]# vi sh05.sh
#!/bin/bash
# Program:
#	User input a filename, program will check the flowing:
#	1.) exist? 2.) file/directory? 3.) file permissions
# History:
# 2005/08/25	VBird	First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH

# 1. 让使用者输入档名，并且判断使用者是否真的有输入字串？

echo -e "Please input a filename, I will check the filename's type and \
permission. \n\n"
read -p "Input a filename : " filename
test -z $filename && echo "You MUST input a filename." && exit 0
# 2. 判断档案是否存在？若不存在则显示讯息并结束脚本
test ! -e $filename && echo "The filename '$filename' DO NOT exist" && exit 0
# 3. 开始判断档案类型与属性
test -f $filename && filetype="regulare file"
test -d $filename && filetype="directory"
test -r $filename && perm="readable"
test -w $filename && perm="$perm writable"
test -x $filename && perm="$perm executable"

# 4. 开始输出资讯！
echo "The filename: $filename is a $filetype"
echo "And the permissions are : $perm"

如果你执行这个脚本后，他会依据你输入的档名来进行检查喔！先看是否存在，再看为档案或目录类型，最后判断权限。 但是你必须要注意的是，由于 root 在很多权限的限制上面都是无效的，所以使用 root 执行这个脚本时， 常常会发现与 ls -l 观察到的结果并不相同！所以，建议使用一般使用者来执行这个脚本试看看。 不过你必须要使用 root 的身份先将这个脚本搬移给使用者就是了，不然一般使用者无法进入 /root 目录的。 很有趣的例子吧！你可以自行再以其他的案例来撰写一下可用的功能呢！

小标题的图示 利用判断符号 [ ]

除了我们很喜欢使用的 test 之外，其实，我们还可以利用判断符号‘ [ ] ’(就是中括号啦) 来进行资料的判断呢！ 举例来说，如果我想要知道 $HOME 这个变数是否为空的，可以这样做：

[root@www ~]# [ -z "$HOME" ] ; echo $?

使用中括号必须要特别注意，因为中括号用在很多地方，包括万用字元与正规表示法等等，所以如果要在 bash 的语法当中使用中括号作为 shell 的判断式时，必须要注意中括号的两端需要有空白字元来分隔喔！ 假设我空白键使用‘□’符号来表示，那么，在这些地方你都需要有空白键：

[  "$HOME"  ==  "$MAIL"  ]
[□"$HOME"□==□"$MAIL"□]
 ↑       ↑  ↑       ↑
Tips:
你会发现鸟哥在上面的判断式当中使用了两个等号‘ == ’。其实在 bash 当中使用一个等号与两个等号的结果是一样的！ 不过在一般惯用程式的写法中，一个等号代表‘变数的设定’，两个等号则是代表‘逻辑判断 (是否之意)’。 由于我们在中括号内重点在于‘判断’而非‘设定变数’，因此鸟哥建议您还是使用两个等号较佳！ 		鸟哥的图示

上面的例子在说明，两个字串 $HOME 与 $MAIL 是否相同的意思，相当于 test $HOME = $MAIL 的意思啦！ 而如果没有空白分隔，例如 [$HOME==$MAIL] 时，我们的 bash 就会显示错误讯息了！这可要很注意啊！ 所以说，你最好要注意：

  • 在中括号 [] 内的每个元件都需要有空白键来分隔；
  • 在中括号内的变数，最好都以双引号括号起来；
  • 在中括号内的常数，最好都以单或双引号括号起来。

为什么要这么麻烦啊？直接举例来说，假如我设定了 name="VBird Tsai" ，然后这样判定：

[root@www ~]# name="VBird Tsai"

[root@www ~]# [ $name == "VBird" ]
bash: [: too many arguments

见鬼了！怎么会发生错误啊？bash 还跟我说错误是由于‘太多参数 (arguments)’所致！ 为什么呢？因为 $name 如果没有使用双引号刮起来，那么上面的判定式会变成：

[ VBird Tsai == "VBird" ]

上面肯定不对嘛！因为一个判断式仅能有两个资料的比对，上面 VBird 与 Tsai 还有 "VBird" 就有三个资料！ 这不是我们要的！我们要的应该是底下这个样子：

[ "VBird Tsai" == "VBird" ]

这可是差很多的喔！另外，中括号的使用方法与 test 几乎一模一样啊～ 只是中括号比较常用在条件判断式 if ..... then ..... fi 的情况中就是了。 好，那我们也使用中括号的判断来做一个小案例好了，案例设定如下：

  1. 当执行一个程式的时候，这个程式会让使用者选择 Y 或 N ，
  2. 如果使用者输入 Y 或 y 时，就显示‘ OK, continue ’
  3. 如果使用者输入 n 或 N 时，就显示‘ Oh, interrupt ！’
  4. 如果不是 Y/y/N/n 之内的其他字元，就显示‘ I don't know what your choice is ’
利用中括号、 && 与 || 来继续吧！
[root@www scripts]# vi sh06.sh

#!/bin/bash
# Program:
# 	This program shows the user's choice
# History:
# 2005/08/25	VBird	First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH

read -p "Please input (Y/N): " yn
[ "$yn" == "Y" -o "$yn" == "y" ] && echo "OK, continue" && exit 0
[ "$yn" == "N" -o "$yn" == "n" ] && echo "Oh, interrupt!" && exit 0
echo "I don't know what your choice is" && exit 0

由于输入正确 (Yes) 的方法有大小写之分，不论输入大写 Y 或小写 y 都是可以的，此时判断式内就得要有两个判断才行！ 由于是任何一个成立即可 (大小或小写的 y) ，所以这里使用 -o (或) 连结两个判断喔！ 很有趣吧！利用这个字串判别的方法，我们就可以很轻松的将使用者想要进行的工作分门别类呢！ 接下来，我们再来谈一些其他有的没有的东西吧！

小标题的图示 Shell script 的预设变数($0, $1...)

我们知道指令可以带有选项与参数，例如 ls -la 可以察看包含隐藏档的所有属性与权限。那么 shell script 能不能在脚本档名后面带有参数呢？很有趣喔！举例来说，如果你想要重新启动系统登录档的功能，可以这样做：

[root@www ~]# file /etc/init.d/syslog
/etc/init.d/syslog: Bourne-Again shell script text executable

# 使用 file 来查询后，系统告知这个档案是个 bash 的可执行 script 喔！
[root@www ~]# /etc/init.d/syslog restart

restart 是除新启动的意思，上面的指令可以‘重新启动 /etc/init.d/syslog 这支程式’的意思！ 唔！那么如果你在 /etc/init.d/syslog 后面加上 stop 呢？没错！就可以直接关闭该服务了！这么神奇啊？ 没错啊！如果你要依据程式的执行给予一些变数去进行不同的任务时，本章一开始是使用 read 的功能！但 read 功能的问题是你得要手动由键盘输入一些判断式。如果透过指令后面接参数， 那么一个指令就能够处理完毕而不需要手动再次输入一些变数行为！这样下达指令会比较简单方便啦！

script 是怎么达成这个功能的呢？其实 script 针对参数已经有设定好一些变数名称了！对应如下：

/path/to/scriptname  opt1  opt2  opt3  opt4
       $0             $1    $2    $3    $4

这样够清楚了吧？执行的脚本档名为 $0 这个变数，第一个接的参数就是 $1 啊～ 所以，只要我们在 script 里面善用 $1 的话，就可以很简单的立即下达某些指令功能了！除了这些数字的变数之外， 我们还有一些较为特殊的变数可以在 script 内使用来呼叫这些参数喔！

  • $# ：代表后接的参数‘个数’，以上表为例这里显示为‘ 4 ’；
  • $@ ：代表‘ "$1" "$2" "$3" "$4" ’之意，每个变数是独立的(用双引号括起来)；
  • $* ：代表‘ "$1c$2c$3c$4" ’，其中 c 为分隔字元，预设为空白键， 所以本例中代表‘ "$1 $2 $3 $4" ’之意。

那个 $@ 与 $* 基本上还是有所不同啦！不过，一般使用情况下可以直接记忆 $@ 即可！ 好了，来做个例子吧～假设我要执行一个可以携带参数的 script ，执行该脚本后荧幕会显示如下的资料：

  • 程式的档名为何？
  • 共有几个参数？
  • 若参数的个数小于 2 则告知使用者参数数量太少
  • 全部的参数内容为何？
  • 第一个参数为何？
  • 第二个参数为何
[root@www scripts]# vi sh07.sh
#!/bin/bash
# Program:
#	Program shows the script name, parameters...
# History:
# 2009/02/17	VBird	First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH

echo "The script name is        ==> $0"
echo "Total parameter number is ==> $#"
[ "$#" -lt 2 ] && echo "The number of parameter is less than 2.  Stop here." \
    && exit 0
echo "Your whole parameter is   ==> '$@'"
echo "The 1st parameter         ==> $1"
echo "The 2nd parameter         ==> $2"

执行结果如下：

[root@www scripts]# sh sh07.sh theone haha quot
The script name is        ==> sh07.sh            <==档名
Total parameter number is ==> 3                  <==果然有三个参数

Your whole parameter is   ==> 'theone haha quot' <==参数的内容全部
The 1st parameter         ==> theone             <==第一个参数
The 2nd parameter         ==> haha               <==第二个参数

  • shift：造成参数变数号码偏移

除此之外，脚本后面所接的变数是否能够进行偏移 (shift) 呢？什么是偏移啊？我们直接以底下的范例来说明好了， 用范例说明比较好解释！我们将 sh07.sh 的内容稍作变化一下，用来显示每次偏移后参数的变化情况：

[root@www scripts]# vi sh08.sh
#!/bin/bash
# Program:
#	Program shows the effect of shift function.
# History:
# 2009/02/17	VBird	First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH

echo "Total parameter number is ==> $#"
echo "Your whole parameter is   ==> '$@'"
shift   # 进行第一次‘一个变数的 shift ’

echo "Total parameter number is ==> $#"
echo "Your whole parameter is   ==> '$@'"
shift 3 # 进行第二次‘三个变数的 shift ’
echo "Total parameter number is ==> $#"
echo "Your whole parameter is   ==> '$@'"

这玩意的执行成果如下：

[root@www scripts]# sh sh08.sh one two three four five six <==给予六个参数
Total parameter number is ==> 6   <==最原始的参数变数情况
Your whole parameter is   ==> 'one two three four five six'
Total parameter number is ==> 5   <==第一次偏移，看底下发现第一个 one 不见了

Your whole parameter is   ==> 'two three four five six'
Total parameter number is ==> 2   <==第二次偏移掉三个，two three four 不见了
Your whole parameter is   ==> 'five six'

光看结果你就可以知道啦，那个 shift 会移动变数，而且 shift 后面可以接数字，代表拿掉最前面的几个参数的意思。 上面的执行结果中，第一次进行 shift 后他的显示情况是‘ one two three four five six’，所以就剩下五个啦！第二次直接拿掉三个，就变成‘ two three four five six ’啦！ 这样这个案例可以了解了吗？理解了 shift 的功能了吗？

上面这8个例子都很简单吧？几乎都是利用 bash 的相关功能而已～ 不难啦～底下我们就要使用条件判断式来进行一些分别功能的设定了，好好瞧一瞧先～

大标题的图示 条件判断式

只要讲到‘程式’的话，那么条件判断式，亦即是‘ if then ’这种判别式肯定一定要学习的！ 因为很多时候，我们都必须要依据某些资料来判断程式该如何进行。举例来说，我们在上头的 sh06.sh 范例中不是有练习当使用者输入 Y/N 时，必须要执行不同的讯息输出吗？简单的方式可以利用 && 与 || ，但如果我还想要执行一堆指令呢？那真的得要 if then 来帮忙啰～底下我们就来聊一聊！

小标题的图示 利用 if .... then

这个 if .... then 是最常见的条件判断式了～简单的说，就是当符合某个条件判断的时候， 就予以进行某项工作就是了。这个 if ... then 的判断还有多层次的情况！我们分别介绍如下：

  • 单层、简单条件判断式

如果你只有一个判断式要进行，那么我们可以简单的这样看：

if [ 条件判断式 ]; then
    当条件判断式成立时，可以进行的指令工作内容；
fi   <==将 if 反过来写，就成为 fi 啦！结束 if 之意！

至于条件判断式的判断方法，与前一小节的介绍相同啊！较特别的是，如果我有多个条件要判别时， 除了 sh06.sh 那个案例所写的，也就是‘将多个条件写入一个中括号内的情况’之外， 我还可以有多个中括号来隔开喔！而括号与括号之间，则以 && 或 || 来隔开，他们的意义是：

  • && 代表 AND ；
  • || 代表 or ；

所以，在使用中括号的判断式中， && 及 || 就与指令下达的状态不同了。举例来说， sh06.sh 里面的判断式可以这样修改：

[ "$yn" == "Y" -o "$yn" == "y" ]
上式可替换为
[ "$yn" == "Y" ] || [ "$yn" == "y" ]

之所以这样改，很多人是习惯问题！很多人则是喜欢一个中括号仅有一个判别式的原因。好了， 现在我们来将 sh06.sh 这个脚本修改成为 if ... then 的样式来看看：

[root@www scripts]# cp sh06.sh sh06-2.sh  <==用改的比较快！

[root@www scripts]# vi sh06-2.sh
#!/bin/bash
# Program:
#       This program shows the user's choice
# History:
# 2005/08/25    VBird   First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH

read -p "Please input (Y/N): " yn

if [ "$yn" == "Y" ] || [ "$yn" == "y" ]; then
    echo "OK, continue"
    exit 0
fi
if [ "$yn" == "N" ] || [ "$yn" == "n" ]; then
    echo "Oh, interrupt!"
    exit 0
fi
echo "I don't know what your choice is" && exit 0

不过，由这个例子看起来，似乎也没有什么了不起吧？ sh06.sh 还比较简单呢～ 但是如果以逻辑概念来看，其实上面的范例中，我们使用了两个条件判断呢！明明仅有一个 $yn 的变数，为何需要进行两次比对呢？ 此时，多重条件判断就能够来测试测试啰！

  • 多重、复杂条件判断式

在同一个资料的判断中，如果该资料需要进行多种不同的判断时，应该怎么作？举例来说，上面的 sh06.sh 脚本中，我们只要进行一次 $yn 的判断就好 (仅进行一次 if )，不想要作多次 if 的判断。 此时你就得要知道底下的语法了：

# 一个条件判断，分成功进行与失败进行 (else)
if [ 条件判断式 ]; then
    当条件判断式成立时，可以进行的指令工作内容；

else
    当条件判断式不成立时，可以进行的指令工作内容；
fi

如果考虑更复杂的情况，则可以使用这个语法：

# 多个条件判断 (if ... elif ... elif ... else) 分多种不同情况执行
if [ 条件判断式一 ]; then

    当条件判断式一成立时，可以进行的指令工作内容；
elif [ 条件判断式二 ]; then
    当条件判断式二成立时，可以进行的指令工作内容；
else
    当条件判断式一与二均不成立时，可以进行的指令工作内容；
fi

你得要注意的是， elif 也是个判断式，因此出现 elif 后面都要接 then 来处理！但是 else 已经是最后的没有成立的结果了， 所以 else 后面并没有 then 喔！好！我们来将 sh06-2.sh 改写成这样：

[root@www scripts]# cp sh06-2.sh sh06-3.sh
[root@www scripts]# vi sh06-3.sh
#!/bin/bash
# Program:
#       This program shows the user's choice
# History:
# 2005/08/25    VBird   First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH

read -p "Please input (Y/N): " yn

if [ "$yn" == "Y" ] || [ "$yn" == "y" ]; then
    echo "OK, continue"
elif [ "$yn" == "N" ] || [ "$yn" == "n" ]; then
    echo "Oh, interrupt!"
else
    echo "I don't know what your choice is"
fi

是否程式变得很简单，而且依序判断，可以避免掉重复判断的状况，这样真的很容易设计程式的啦！ ^_^！ 好了，让我们再来进行另外一个案例的设计。一般来说，如果你不希望使用者由键盘输入额外的资料时， 可以使用上一节提到的参数功能 ($1)！让使用者在下达指令时就将参数带进去！ 现在我们想让使用者输入‘ hello ’这个关键字时，利用参数的方法可以这样依序设计：

  1. 判断 $1 是否为 hello，如果是的话，就显示 "Hello, how are you ?"；
  2. 如果没有加任何参数，就提示使用者必须要使用的参数下达法；
  3. 而如果加入的参数不是 hello ，就提醒使用者仅能使用 hello 为参数。

整个程式的撰写可以是这样的：

[root@www scripts]# vi sh09.sh
#!/bin/bash
# Program:
#	Check $1 is equal to "hello"
# History:
# 2005/08/28	VBird	First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH

if [ "$1" == "hello" ]; then
    echo "Hello, how are you ?"
elif [ "$1" == "" ]; then
    echo "You MUST input parameters, ex> {$0 someword}"
else
    echo "The only parameter is 'hello', ex> {$0 hello}"
fi

然后你可以执行这支程式，分别在 $1 的位置输入 hello, 没有输入与随意输入， 就可以看到不同的输出啰～是否还觉得挺简单的啊！ ^_^。事实上， 学到这里，也真的很厉害了～好了，底下我们继续来玩一些比较大一点的计划啰～

我们在第十一章已经学会了 grep 这个好用的玩意儿，那么多学一个叫做 netstat 的指令，这个指令可以查询到目前主机有开启的网路服务埠口 (service ports)， 相关的功能我们会在伺服器架设篇继续介绍，这里你只要知道，我可以利用‘ netstat -tuln ’来取得目前主机有启动的服务， 而且取得的资讯有点像这样：

[root@www ~]# netstat -tuln
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address     Foreign Address   State
tcp        0      0 0.0.0.0:111       0.0.0.0:*         LISTEN
tcp        0      0 127.0.0.1:631     0.0.0.0:*         LISTEN
tcp        0      0 127.0.0.1:25      0.0.0.0:*         LISTEN
tcp        0      0 :::22             :::*              LISTEN
udp        0      0 0.0.0.0:111       0.0.0.0:*
udp        0      0 0.0.0.0:631       0.0.0.0:*
#封包格式           本地IP:埠口       远端IP:埠口       是否监听

上面的重点是‘Local Address (本地主机的IP与埠口对应)’那个栏位，他代表的是本机所启动的网路服务！ IP的部分说明的是该服务位于那个介面上，若为 127.0.0.1 则是仅针对本机开放，若是 0.0.0.0 或 ::: 则代表对整个 Internet 开放 (更多资讯请参考伺服器架设篇的介绍)。 每个埠口 (port) 都有其特定的网路服务，几个常见的 port 与相关网路服务的关系是：

  • 80: WWW
  • 22: ssh
  • 21: ftp
  • 25: mail
  • 111: RPC(远端程序呼叫)
  • 631: CUPS(列印服务功能)

假设我的主机有兴趣要侦测的是比较常见的 port 21, 22, 25及 80 时，那我如何透过 netstat 去侦测我的主机是否有开启这四个主要的网路服务埠口呢？由于每个服务的关键字都是接在冒号‘ : ’后面， 所以可以藉由撷取类似‘ :80 ’来侦测的！那我就可以简单的这样去写这个程式喔：

[root@www scripts]# vi sh10.sh
#!/bin/bash
# Program:
# 	Using netstat and grep to detect WWW,SSH,FTP and Mail services.
# History:
# 2005/08/28	VBird	First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH

# 1. 先作一些告知的动作而已～
echo "Now, I will detect your Linux server's services!"
echo -e "The www, ftp, ssh, and mail will be detect! \n"

# 2. 开始进行一些测试的工作，并且也输出一些资讯啰！
testing=$(netstat -tuln | grep ":80 ")   # 侦测看 port 80 在否？

if [ "$testing" != "" ]; then
    echo "WWW is running in your system."
fi
testing=$(netstat -tuln | grep ":22 ")   # 侦测看 port 22 在否？
if [ "$testing" != "" ]; then
    echo "SSH is running in your system."
fi
testing=$(netstat -tuln | grep ":21 ")   # 侦测看 port 21 在否？
if [ "$testing" != "" ]; then
    echo "FTP is running in your system."
fi
testing=$(netstat -tuln | grep ":25 ")   # 侦测看 port 25 在否？
if [ "$testing" != "" ]; then
    echo "Mail is running in your system."
fi

实际执行这支程式你就可以看到你的主机有没有启动这些服务啦！是否很有趣呢？ 条件判断式还可以搞的更复杂！举例来说，在台湾当兵是国民应尽的义务，不过，在当兵的时候总是很想要退伍的！ 那你能不能写个脚本程式来跑，让使用者输入他的退伍日期，让你去帮他计算还有几天才退伍？

由于日期是要用相减的方式来处置，所以我们可以透过使用 date 显示日期与时间，将他转为由 1970-01-01 累积而来的秒数， 透过秒数相减来取得剩余的秒数后，再换算为日数即可。整个脚本的制作流程有点像这样：

  1. 先让使用者输入他们的退伍日期；
  2. 再由现在日期比对退伍日期；
  3. 由两个日期的比较来显示‘还需要几天’才能够退伍的字样。

似乎挺难的样子？其实也不会啦，利用‘ date --date="YYYYMMDD" +%s ’转成秒数后，接下来的动作就容易的多了！如果你已经写完了程式，对照底下的写法试看看：

[root@www scripts]# vi sh11.sh
#!/bin/bash
# Program:
#	You input your demobilization date, I calculate how many days
#	before you demobilize.
# History:
# 2005/08/29	VBird	First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH

# 1. 告知使用者这支程式的用途，并且告知应该如何输入日期格式？
echo "This program will try to calculate :"
echo "How many days before your demobilization date..."
read -p "Please input your demobilization date (YYYYMMDD ex>20090401): " date2

# 2. 测试一下，这个输入的内容是否正确？利用正规表示法啰～
date_d=$(echo $date2 |grep '[0-9]\{8\}')   # 看看是否有八个数字
if [ "$date_d" == "" ]; then
    echo "You input the wrong date format...."
    exit 1
fi

# 3. 开始计算日期啰～
declare -i date_dem=`date --date="$date2" +%s`    # 退伍日期秒数
declare -i date_now=`date +%s`                    # 现在日期秒数
declare -i date_total_s=$(($date_dem-$date_now))  # 剩余秒数统计

declare -i date_d=$(($date_total_s/60/60/24))     # 转为日数
if [ "$date_total_s" -lt "0" ]; then              # 判断是否已退伍
    echo "You had been demobilization before: " $((-1*$date_d)) " ago"
else
    declare -i date_h=$(($(($date_total_s-$date_d*60*60*24))/60/60))
    echo "You will demobilize after $date_d days and $date_h hours."
fi

瞧一瞧，这支程式可以帮你计算退伍日期呢～如果是已经退伍的朋友， 还可以知道已经退伍多久了～哈哈！很可爱吧～脚本中的 date_d 变数宣告那个 /60/60/24 是来自于一天的总秒数 (24小时*60分*60秒) 。瞧～全部的动作都没有超出我们所学的范围吧～ ^_^ 还能够避免使用者输入错误的数字，所以多了一个正规表示法的判断式呢～ 这个例子比较难，有兴趣想要一探究竟的朋友，可以作一下课后练习题 关于计算生日的那一题喔！～加油！

小标题的图示 利用 case ..... esac 判断

上个小节提到的‘ if .... then .... fi ’对于变数的判断是以‘比对’的方式来分辨的， 如果符合状态就进行某些行为，并且透过较多层次 (就是 elif ...) 的方式来进行多个变数的程式码撰写，譬如 sh09.sh 那个小程式，就是用这样的方式来撰写的啰。 好，那么万一我有多个既定的变数内容，例如 sh09.sh 当中，我所需要的变数就是 "hello" 及空字串两个， 那么我只要针对这两个变数来设定状况就好了，对吧？那么可以使用什么方式来设计呢？呵呵～就用 case ... in .... esac 吧～，他的语法如下：

case  $变数名称 in   <==关键字为 case ，还有变数前有钱字号

  "第一个变数内容")   <==每个变数内容建议用双引号括起来，关键字则为小括号 )
    程式段
    ;;            <==每个类别结尾使用两个连续的分号来处理！
  "第二个变数内容")
    程式段
    ;;

  *)                  <==最后一个变数内容都会用 * 来代表所有其他值
    不包含第一个变数内容与第二个变数内容的其他程式执行段
    exit 1
    ;;
esac                  <==最终的 case 结尾！‘反过来写’思考一下！

要注意的是，这个语法以 case (实际案例之意) 为开头，结尾自然就是将 case 的英文反过来写！就成为 esac 啰！ 不会很难背啦！另外，每一个变数内容的程式段最后都需要两个分号 (;;) 来代表该程式段落的结束，这挺重要的喔！ 至于为何需要有 * 这个变数内容在最后呢？这是因为，如果使用者不是输入变数内容一或二时， 我们可以告知使用者相关的资讯啊！废话少说，我们拿 sh09.sh 的案例来修改一下，他应该会变成这样喔：

[root@www scripts]# vi sh09-2.sh
#!/bin/bash
# Program:
# 	Show "Hello" from $1.... by using case .... esac
# History:
# 2005/08/29	VBird	First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH

case $1 in
  "hello")
    echo "Hello, how are you ?"
    ;;
  "")
    echo "You MUST input parameters, ex> {$0 someword}"
    ;;
  *)   # 其实就相当于万用字元，0~无穷多个任意字元之意！
    echo "Usage $0 {hello}"
    ;;
esac

在上面这个 sh09-2.sh 的案例当中，如果你输入‘ sh sh09-2.sh test ’来执行， 那么荧幕上就会出现‘Usage sh09-2.sh {hello}’的字样，告知执行者仅能够使用 hello 喔～ 这样的方式对于需要某些固定字串来执行的变数内容就显的更加的方便呢！ 这种方式你真的要熟悉喔！这是因为系统的很多服务的启动 scripts 都是使用这种写法的， 举例来说，我们 Linux 的服务启动放置目录是在 /etc/init.d/ 当中，我已经知道里头有个 syslog 的服务，我想要重新启动这个服务，可以这样做：

/etc/init.d/syslog restart

重点是那个 restart 啦！如果你使用‘ less /etc/init.d/syslog ’去查阅一下，就会看到他使用的是 case 语法， 并且会规定某些既定的变数内容，你可以直接下达 /etc/init.d/syslog ， 该 script 就会告知你有哪些后续接的变数可以使用啰～方便吧！ ^_^

一般来说，使用‘ case $变数 in ’这个语法中，当中的那个‘ $变数 ’大致有两种取得的方式：

  • 直接下达式：例如上面提到的，利用‘ script.sh variable ’ 的方式来直接给予 $1 这个变数的内容，这也是在 /etc/init.d 目录下大多数程式的设计方式。

  • 互动式：透过 read 这个指令来让使用者输入变数的内容。

这么说或许你的感受性还不高，好，我们直接写个程式来玩玩：让使用者能够输入 one, two, three ， 并且将使用者的变数显示到荧幕上，如果不是 one, two, three 时，就告知使用者仅有这三种选择。

[root@www scripts]# vi sh12.sh
#!/bin/bash
# Program:
#	This script only accepts the flowing parameter: one, two or three.
# History:
# 2005/08/29	VBird	First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH

echo "This program will print your selection !"
# read -p "Input your choice: " choice # 暂时取消，可以替换！
# case $choice in                      # 暂时取消，可以替换！

case $1 in                             # 现在使用，可以用上面两行替换！
  "one")
    echo "Your choice is ONE"
    ;;
  "two")
    echo "Your choice is TWO"
    ;;
  "three")
    echo "Your choice is THREE"
    ;;
  *)
    echo "Usage $0 {one|two|three}"
    ;;
esac

此时，你可以使用‘ sh sh12.sh two ’的方式来下达指令，就可以收到相对应的回应了。 上面使用的是直接下达的方式，而如果使用的是互动式时，那么将上面第 10, 11 行的 "#" 拿掉， 并将 12 行加上注解 (#)，就可以让使用者输入参数啰～这样是否很有趣啊？

小标题的图示 利用 function 功能

什么是‘函数 (function)’功能啊？简单的说，其实， 函数可以在 shell script 当中做出一个类似自订执行指令的东西，最大的功能是， 可以简化我们很多的程式码～举例来说，上面的 sh12.sh 当中，每个输入结果 one, two, three 其实输出的内容都一样啊～那么我就可以使用 function 来简化了！ function 的语法是这样的：

function fname() {
    程式段
}

那个 fname 就是我们的自订的执行指令名称～而程式段就是我们要他执行的内容了。 要注意的是，因为 shell script 的执行方式是由上而下，由左而右， 因此在 shell script 当中的 function 的设定一定要在程式的最前面， 这样才能够在执行时被找到可用的程式段喔！好～我们将 sh12.sh 改写一下，自订一个名为 printit 的函数来使用喔：

[root@www scripts]# vi sh12-2.sh
#!/bin/bash
# Program:
#	Use function to repeat information.
# History:
# 2005/08/29	VBird	First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH

function printit(){
    echo -n "Your choice is "     # 加上 -n 可以不断行继续在同一行显示
}

echo "This program will print your selection !"
case $1 in
  "one")
    printit; echo $1 | tr 'a-z' 'A-Z'  # 将参数做大小写转换！

    ;;
  "two")
    printit; echo $1 | tr 'a-z' 'A-Z'
    ;;
  "three")
    printit; echo $1 | tr 'a-z' 'A-Z'
    ;;
  *)
    echo "Usage $0 {one|two|three}"
    ;;
esac

以上面的例子来说，鸟哥做了一个函数名称为 printit ，所以，当我在后续的程式段里面， 只要执行 printit 的话，就表示我的 shell script 要去执行‘ function printit .... ’ 里面的那几个程式段落啰！当然啰，上面这个例子举得太简单了，所以你不会觉得 function 有什么好厉害的， 不过，如果某些程式码一再地在 script 当中重复时，这个 function 可就重要的多啰～ 不但可以简化程式码，而且可以做成类似‘模组’的玩意儿，真的很棒啦！

Tips:
建议读者可以使用类似 vim 的编辑器到 /etc/init.d/ 目录下去查阅一下你所看到的档案， 并且自行追踪一下每个档案的执行情况，相信会更有心得！ 		鸟哥的图示

另外， function 也是拥有内建变数的～他的内建变数与 shell script 很类似， 函数名称代表示 $0 ，而后续接的变数也是以 $1, $2... 来取代的～ 这里很容易搞错喔～因为‘ function fname() { 程式段 } ’内的 $0, $1... 等等与 shell script 的 $0 是不同的。以上面 sh12-2.sh 来说，假如我下达：‘ sh sh12-2.sh one ’ 这表示在 shell script 内的 $1 为 "one" 这个字串。但是在 printit() 内的 $1 则与这个 one 无关。 我们将上面的例子再次的改写一下，让你更清楚！

[root@www scripts]# vi sh12-3.sh
#!/bin/bash
# Program:
#	Use function to repeat information.
# History:
# 2005/08/29	VBird	First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH

function printit(){
    echo "Your choice is $1"   # 这个 $1 必须要参考底下指令的下达
}

echo "This program will print your selection !"
case $1 in
  "one")
    printit 1  # 请注意， printit 指令后面还有接参数！

    ;;
  "two")
    printit 2
    ;;
  "three")
    printit 3
    ;;
  *)
    echo "Usage $0 {one|two|three}"
    ;;
esac

在上面的例子当中，如果你输入‘ sh sh12-3.sh one ’就会出现‘ Your choice is 1 ’的字样～ 为什么是 1 呢？因为在程式段落当中，我们是写了‘ printit 1 ’那个 1 就会成为 function 当中的 $1 喔～ 这样是否理解呢？ function 本身其实比较困难一点，如果你还想要进行其他的撰写的话。 不过，我们仅是想要更加了解 shell script 而已，所以，这里看看即可～了解原理就好啰～ ^_^

大标题的图示 回圈 (loop)

除了 if...then...fi 这种条件判断式之外，回圈可能是程式当中最重要的一环了～ 回圈可以不断的执行某个程式段落，直到使用者设定的条件达成为止。 所以，重点是那个‘条件的达成’是什么。除了这种依据判断式达成与否的不定回圈之外， 还有另外一种已经固定要跑多少次的回圈形态，可称为固定回圈的形态呢！底下我们就来谈一谈：

小标题的图示 while do done, until do done (不定回圈)

一般来说，不定回圈最常见的就是底下这两种状态了：

while [ condition ]  <==中括号内的状态就是判断式
do            <==do 是回圈的开始！

    程式段落
done          <==done 是回圈的结束

while 的中文是‘当....时’，所以，这种方式说的是‘当 condition 条件成立时，就进行回圈，直到 condition 的条件不成立才停止’的意思。还有另外一种不定回圈的方式：

until [ condition ]
do

    程式段落
done

这种方式恰恰与 while 相反，它说的是‘当 condition 条件成立时，就终止回圈， 否则就持续进行回圈的程式段。’是否刚好相反啊～我们以 while 来做个简单的练习好了。 假设我要让使用者输入 yes 或者是 YES 才结束程式的执行，否则就一直进行告知使用者输入字串。

[root@www scripts]# vi sh13.sh
#!/bin/bash
# Program:
#	Repeat question until user input correct answer.
# History:
# 2005/08/29	VBird	First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH

while [ "$yn" != "yes" -a "$yn" != "YES" ]
do
    read -p "Please input yes/YES to stop this program: " yn
done
echo "OK! you input the correct answer."

上面这个例题的说明是‘当 $yn 这个变数不是 "yes" 且 $yn 也不是 "YES" 时，才进行回圈内的程式。’ 而如果 $yn 是 "yes" 或 "YES" 时，就会离开回圈啰～那如果使用 until 呢？呵呵有趣啰～ 他的条件会变成这样：

[root@www scripts]# vi sh13-2.sh
#!/bin/bash
# Program:
#	Repeat question until user input correct answer.
# History:
# 2005/08/29	VBird	First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH

until [ "$yn" == "yes" -o "$yn" == "YES" ]
do
    read -p "Please input yes/YES to stop this program: " yn
done
echo "OK! you input the correct answer."

仔细比对一下这两个东西有啥不同喔！ ^_^再来，如果我想要计算 1+2+3+....+100 这个数据呢？ 利用回圈啊～他是这样的：

[root@www scripts]# vi sh14.sh
#!/bin/bash
# Program:
#	Use loop to calculate "1+2+3+...+100" result.
# History:
# 2005/08/29	VBird	First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH

s=0  # 这是加总的数值变数
i=0  # 这是累计的数值，亦即是 1, 2, 3....
while [ "$i" != "100" ]
do
    i=$(($i+1))   # 每次 i 都会增加 1
    s=$(($s+$i))  # 每次都会加总一次！

done
echo "The result of '1+2+3+...+100' is ==> $s"

嘿嘿！当你执行了‘ sh sh14.sh ’之后，就可以得到 5050 这个数据才对啊！这样了呼～ 那么让你自行做一下，如果想要让使用者自行输入一个数字，让程式由 1+2+... 直到你输入的数字为止， 该如何撰写呢？应该很简单吧？答案可以参考一下习题练习里面的一题喔！

小标题的图示 for...do...done (固定回圈)

相对于 while, until 的回圈方式是必须要‘符合某个条件’的状态， for 这种语法，则是‘ 已经知道要进行几次回圈’的状态！他的语法是：

for var in con1 con2 con3 ...
do

    程式段
done

以上面的例子来说，这个 $var 的变数内容在回圈工作时：

  1. 第一次回圈时， $var 的内容为 con1 ；
  2. 第二次回圈时， $var 的内容为 con2 ；
  3. 第三次回圈时， $var 的内容为 con3 ；
  4. ....

我们可以做个简单的练习。假设我有三种动物，分别是 dog, cat, elephant 三种， 我想每一行都输出这样：‘There are dogs...’之类的字样，则可以：

[root@www scripts]# vi sh15.sh

#!/bin/bash
# Program:
# 	Using for .... loop to print 3 animals
# History:
# 2005/08/29	VBird	First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH

for animal in dog cat elephant
do
    echo "There are ${animal}s.... "
done

等你执行之后就能够发现这个程式运作的情况啦！让我们想像另外一种状况，由于系统上面的各种帐号都是写在 /etc/passwd 内的第一个栏位，你能不能透过管线命令的 cut 捉出单纯的帐号名称后，以 id 及 finger 分别检查使用者的识别码与特殊参数呢？由于不同的 Linux 系统上面的帐号都不一样！此时实际去捉 /etc/passwd 并使用回圈处理，就是一个可行的方案了！程式可以如下：

[root@www scripts]# vi sh16.sh
#!/bin/bash
# Program
#       Use id, finger command to check system account's information.
# History
# 2009/02/18    VBird   first release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
users=$(cut -d ':' -f1 /etc/passwd)  # 撷取帐号名称
for username in $users               # 开始回圈进行！
do
        id $username
        finger $username
done

执行上面的脚本后，你的系统帐号就会被捉出来检查啦！这个动作还可以用在每个帐号的删除、重整上面呢！ 换个角度来看，如果我现在需要一连串的数字来进行回圈呢？举例来说，我想要利用 ping 这个可以判断网路状态的指令， 来进行网路状态的实际侦测时，我想要侦测的网域是本机所在的 192.168.1.1~192.168.1.100，由于有 100 台主机， 总不会要我在 for 后面输入 1 到 100 吧？此时你可以这样做喔！

[root@www scripts]# vi sh17.sh
#!/bin/bash
# Program
#       Use ping command to check the network's PC state.
# History
# 2009/02/18    VBird   first release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
network="192.168.1"              # 先定义一个网域的前面部分！
for sitenu in $(seq 1 100)       # seq 为 sequence(连续) 的缩写之意
do
    # 底下的程式在取得 ping 的回传值是正确的还是失败的！

        ping -c 1 -w 1 ${network}.${sitenu} &> /dev/null && result=0 || result=1
    # 开始显示结果是正确的启动 (UP) 还是错误的没有连通 (DOWN)
        if [ "$result" == 0 ]; then
                echo "Server ${network}.${sitenu} is UP."
        else
                echo "Server ${network}.${sitenu} is DOWN."
        fi
done

上面这一串指令执行之后就可以显示出 192.168.1.1~192.168.1.100 共 100 部主机目前是否能与你的机器连通！ 如果你的网域与鸟哥所在的位置不同，则直接修改上头那个 network 的变数内容即可！其实这个范例的重点在 $(seq ..) 那个位置！那个 seq 是连续 (sequence) 的缩写之意！代表后面接的两个数值是一直连续的！ 如此一来，就能够轻松的将连续数字带入程式中啰！

最后，让我们来玩判断式加上回圈的功能！我想要让使用者输入某个目录档名， 然后我找出某目录内的档名的权限，该如何是好？呵呵！可以这样做啦～

[root@www scripts]# vi sh18.sh
#!/bin/bash
# Program:
#	User input dir name, I find the permission of files.
# History:
# 2005/08/29	VBird	First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH

# 1. 先看看这个目录是否存在啊？
read -p "Please input a directory: " dir
if [ "$dir" == "" -o ! -d "$dir" ]; then
    echo "The $dir is NOT exist in your system."
    exit 1
fi

# 2. 开始测试档案啰～
filelist=$(ls $dir)        # 列出所有在该目录下的档案名称

for filename in $filelist
do
    perm=""
    test -r "$dir/$filename" && perm="$perm readable"
    test -w "$dir/$filename" && perm="$perm writable"
    test -x "$dir/$filename" && perm="$perm executable"
    echo "The file $dir/$filename's permission is $perm "
done

呵呵！很有趣的例子吧～利用这种方式，你可以很轻易的来处理一些档案的特性呢。接下来，让我们来玩玩另一种 for 回圈的功能吧！主要用在数值方面的处理喔！

小标题的图示 for...do...done 的数值处理

除了上述的方法之外，for 回圈还有另外一种写法！语法如下：

for (( 初始值; 限制值; 执行步阶 ))
do

    程式段
done

这种语法适合于数值方式的运算当中，在 for 后面的括号内的三串内容意义为：

  • 初始值：某个变数在回圈当中的起始值，直接以类似 i=1 设定好；
  • 限制值：当变数的值在这个限制值的范围内，就继续进行回圈。例如 i<=100；
  • 执行步阶：每作一次回圈时，变数的变化量。例如 i=i+1。

值得注意的是，在‘执行步阶’的设定上，如果每次增加 1 ，则可以使用类似‘i++’的方式，亦即是 i 每次回圈都会增加一的意思。好，我们以这种方式来进行 1 累加到使用者输入的回圈吧！

[root@www scripts]# vi sh19.sh
#!/bin/bash
# Program:
# 	Try do calculate 1+2+....+${your_input}
# History:
# 2005/08/29	VBird	First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH

read -p "Please input a number, I will count for 1+2+...+your_input: " nu

s=0
for (( i=1; i<=$nu; i=i+1 ))
do
    s=$(($s+$i))
done
echo "The result of '1+2+3+...+$nu' is ==> $s"

一样也是很简单吧！利用这个 for 则可以直接限制回圈要进行几次呢！

大标题的图示 shell script 的追踪与 debug

scripts 在执行之前，最怕的就是出现语法错误的问题了！那么我们如何 debug 呢？有没有办法不需要透过直接执行该 scripts 就可以来判断是否有问题呢？呵呵！当然是有的！我们就直接以 bash 的相关参数来进行判断吧！

[root@www ~]# sh [-nvx] scripts.sh
选项与参数：
-n  ：不要执行 script，仅查询语法的问题；
-v  ：再执行 sccript 前，先将 scripts 的内容输出到荧幕上；
-x  ：将使用到的 script 内容显示到荧幕上，这是很有用的参数！

范例一：测试 sh16.sh 有无语法的问题？
[root@www ~]# sh -n sh16.sh
# 若语法没有问题，则不会显示任何资讯！

范例二：将 sh15.sh 的执行过程全部列出来～

[root@www ~]# sh -x sh15.sh
+ PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:/root/bin
+ export PATH
+ for animal in dog cat elephant
+ echo 'There are dogs.... '
There are dogs....
+ for animal in dog cat elephant
+ echo 'There are cats.... '
There are cats....
+ for animal in dog cat elephant
+ echo 'There are elephants.... '
There are elephants....

请注意，上面范例二中执行的结果并不会有颜色的显示！鸟哥为了方便说明所以在 + 号之后的资料都加上颜色了！ 在输出的讯息中，在加号后面的资料其实都是指令串，由于 sh -x 的方式来将指令执行过程也显示出来， 如此使用者可以判断程式码执行到哪一段时会出现相关的资讯！这个功能非常的棒！透过显示完整的指令串， 你就能够依据输出的错误资讯来订正你的脚本了！

熟悉 sh 的用法，将可以使你在管理 Linux 的过程中得心应手！至于在 Shell scripts 的学习方法上面，需要‘多看、多模仿、并加以修改成自己的样式！’ 是最快的学习手段了！网路上有相当多的朋友在开发一些相当有用的 scripts ，若是你可以将对方的 scripts 拿来，并且改成适合自己主机的样子！那么学习的效果会是最快的呢！

另外，我们 Linux 系统本来就有很多的服务启动脚本，如果你想要知道每个 script 所代表的功能是什么？ 可以直接以 vim 进入该 script 去查阅一下，通常立刻就知道该 script 的目的了。 举例来说，我们之前一直提到的 /etc/init.d/syslog ，这个 script 是干嘛用的？ 利用 vi 去查阅最前面的几行字，他出现如下资讯：

# description: Syslog is the facility by which many daemons use to log \
# messages to various system log files.  It is a good idea to always \
# run syslog.
### BEGIN INIT INFO
# Provides: $syslog
### END INIT INFO

简单的说，这个脚本在启动一个名为 syslog 的常驻程式 (daemon)，这个常驻程式可以帮助很多系统服务记载她们的登录档 (log file)， 我们的 Linux 建议你一直启动 syslog 是个好主意！嘿嘿！简单的看看您就知道啥是啥啦！

另外，本章所有的范例都可以在 http://linux.vbird.org/linux_basic/0340bashshell-scripts/scripts-v3.tar.bz2 里头找到喔！加油～

大标题的图示 重点回顾
  • shell script 是利用 shell 的功能所写的一个‘程式 (program)’，这个程式是使用纯文字档，将一些 shell 的语法与指令(含外部指令)写在里面， 搭配正规表示法、管线命令与资料流重导向等功能，以达到我们所想要的处理目的
  • shell script 用在系统管理上面是很好的一项工具，但是用在处理大量数值运算上， 就不够好了，因为 Shell scripts 的速度较慢，且使用的 CPU 资源较多，造成主机资源的分配不良。
  • 在 Shell script 的档案中，指令的执行是从上而下、从左而右的分析与执行；
  • shell script 的执行，至少需要有 r 的权限，若需要直接指令下达，则需要拥有 r 与 x 的权限；
  • 良好的程式撰写习惯中，第一行要宣告 shell (#!/bin/bash) ，第二行以后则宣告程式用途、版本、作者等
  • 对谈式脚本可用 read 指令达成；
  • 要建立每次执行脚本都有不同结果的资料，可使用 date 指令利用日期达成；
  • script 的执行若以 source 来执行时，代表在父程序的 bash 内执行之意！
  • 若需要进行判断式，可使用 test 或中括号 ( [] ) 来处理；
  • 在 script 内，$0, $1, $2..., $@ 是有特殊意义的！
  • 条件判断式可使用 if...then 来判断，若是固定变数内容的情况下，可使用 case $var in ... esac 来处理
  • 回圈主要分为不定回圈 (while, until) 以及固定回圈 (for) ，配合 do, done 来达成所需任务！
  • 我们可使用 sh -x script.sh 来进行程式的 debug
大标题的图示 本章习题
( 要看答案请将滑鼠移动到‘答：’底下的空白处，按下左键圈选空白处即可察看 )
底下皆为实作题，请自行撰写出程式喔！
  • 请建立一支 script ，当你执行该 script 的时候，该 script 可以显示： 1. 你目前的身份 (用 whoami ) 2. 你目前所在的目录 (用 pwd)
    #!/bin/bash
    echo -e "Your name is ==> $(whoami)"
    echo -e "The current directory is ==> $(pwd)"
  • 请自行建立一支程式，该程式可以用来计算‘你还有几天可以过生日’啊？
    #!/bin/bash
    read -p "Pleas input your birthday (MMDD, ex> 0709): " bir
    now=`date +%m%d`
    if [ "$bir" == "$now" ]; then
    echo "Happy Birthday to you!!!"
    elif [ "$bir" -gt "$now" ]; then
    year=`date +%Y`
    total_d=$(($((`date --date="$year$bir" +%s`-`date +%s`))/60/60/24))
    echo "Your birthday will be $total_d later"
    else
    year=$((`date +%Y`+1))
    total_d=$(($((`date --date="$year$bir" +%s`-`date +%s`))/60/60/24))
    echo "Your birthday will be $total_d later"
    fi
  • 让使用者输入一个数字，程式可以由 1+2+3... 一直累加到使用者输入的数字为止。
    #!/bin/bash
    read -p "Please input an integer number: " number
    i=0
    s=0
    while [ "$i" != "$number" ]
    do
    i=$(($i+1))
    s=$(($s+$i))
    done
    echo "the result of '1+2+3+...$number' is ==> $s"
  • 撰写一支程式，他的作用是: 1.) 先查看一下 /root/test/logical 这个名称是否存在； 2.) 若不存在，则建立一个档案，使用 touch 来建立，建立完成后离开； 3.) 如果存在的话，判断该名称是否为档案，若为档案则将之删除后建立一个目录，档名为 logical ，之后离开； 4.) 如果存在的话，而且该名称为目录，则移除此目录！
    #!/bin/bash
    if [ ! -e logical ]; then
    touch logical
    echo "Just make a file logical"
    exit 1
    elif [ -e logical ] && [ -f logical ]; then
    rm logical
    mkdir logical
    echo "remove file ==> logical"
    echo "and make directory logical"
    exit 1
    elif [ -e logical ] && [ -d logical ]; then
    rm -rf logical
    echo "remove directory ==> logical"
    exit 1
    else
    echo "Does here have anything?"
    fi
  • 我们知道 /etc/passwd 里面以 : 来分隔，第一栏为帐号名称。请写一只程式，可以将 /etc/passwd 的第一栏取出，而且每一栏都以一行字串‘The 1 account is "root" ’来显示，那个 1 表示行数。
    #!/bin/bash
    accounts=`cat /etc/passwd | cut -d':' -f1`
    for account in $accounts
    do
    declare -i i=$i+1
    echo "The $i account is \"$account\" "
    done
大标题的图示 参考资料与延伸阅读
  • 卧龙小三大师的文件：http://linux.tnc.edu.tw/techdoc/shell/book1.html
2002/06/27：第一次完成
2003/02/10：重新编排与加入 FAQ
2005/08/29：将旧的文章移动到 这里 了。
2005/08/29：呼呼～加入了一些比较有趣的练习题～比第一版要难的多～大家多多玩一玩喔～
2009/02/10：将旧的基于 FC4 版本的文章移动到此处
2009/02/17：加入 shift 的介绍
2009/02/18：加入了一些额外的练习，包括 for 的 ping 处理！


鸟哥的 Linux 私房菜 -- Linux 帐号管理

为取得较佳浏览结果，请爱用 firefox 浏览本网页

第十四章、Linux 帐号管理与 ACL 权限设定
最近更新日期：2009/09/09
要登入 Linux 系统一定要有帐号与密码才行，否则怎么登入，您说是吧？不过， 不同的使用者应该要拥有不同的权限才行吧？我们还可以透过 user/group 的特殊权限设定， 来规范出不同的群组开发专案呢～在 Linux 的环境下，我们可以透过很多方式来限制使用者能够使用的系统资源， 包括 十一章、bash 提到的 ulimit 限制、还有特殊权限限制，如 umask 等等。 透过这些举动，我们可以规范出不同使用者的使用资源。另外，还记得系统管理员的帐号吗？对！ 就是 root 。请问一下，除了 root 之外，是否可以有其他的系统管理员帐号？ 为什么大家都要尽量避免使用数字型态的帐号？如何修改使用者相关的资讯呢？这些我们都得要了解了解的！

1. Linux 的帐号与群组
    1.1 使用者识别码： UID 与 GID
    1.2 使用者帐号：/etc/passwd 档案结构, /etc/shadow 档案结构
    1.3 关于群组： /etc/group 档案结构, 有效与初始群组, groups, newgrp, /etc/gshadow
 2. 帐号管理
    2.1 新增与移除使用者： useradd, useradd 参考档, passwd, chage, usermod, userdel
    2.2 使用者功能：finger, chfn, chsh, id
    2.3 新增与移除群组：groupadd, groupmod, groupdel, gpasswd 群组管理员
    2.4 帐号管理实例
 3. 主机的细部权限规划：ACL 的使用
    3.1 什么是 ACL
    3.2 如何启动 ACL
    3.3 ACL 的设定技巧： setfacl, getfacl, ACL 的设定(user, group mask, default)
 4. 使用者身份切换
    4.1 su
    4.2 sudo： sudo 指令, visudo (/etc/sudoers) ( 帐号, 群组, 限制指令, 别名, 时间间隔, 配合 su )
 5. 使用者的特殊 shell 与 PAM 模组
    5.1 特殊的 shell :/sbin/nologin, nologin.txt
    5.2 PAM 模组简介
    5.3 PAM 模组设定语法：验证类别(type)、控制标准(flag)、模组与参数
    5.4 常用模组简介： securetty, nologin, pam_cracklib, login流程
    5.5 其他相关档案： limits.conf,
 6. Linux 主机上的使用者讯息传递
    6.1 查询使用者： w, who, last, lastlog
    6.2 使用者对谈： write, mesg, wall
    6.3 使用者邮件信箱： mail
 7. 手动新增使用者
    7.1 一些检查工具：pwck, pwconv, pwunconv, chpasswd
    7.2 特殊帐号，如纯数字帐号的手工建立
    7.3 大量建置帐号范本(适用 passwd --stdin 选项)
    7.4 大量建置帐号的范例(适用于连续数字，如学号)
 8. 重点回顾
9. 本章习题
10. 参考资料与延伸阅读
11. 针对本文的建议：http://phorum.vbird.org/viewtopic.php?t=23887
大标题的图示 Linux 的帐号与群组

管理员的工作中，相当重要的一环就是‘管理帐号’啦！因为整个系统都是你在管理的， 并且所有一般用户的帐号申请，都必须要透过你的协助才行！所以你就必须要了解一下如何管理好一个伺服器主机的帐号啦！ 在管理 Linux 主机的帐号时，我们必须先来了解一下 Linux 到底是如何辨别每一个使用者的！

小标题的图示 使用者识别码： UID 与 GID

虽然我们登入 Linux 主机的时候，输入的是我们的帐号，但是其实 Linux 主机并不会直接认识你的‘帐号名称’的，他仅认识 ID 啊 (ID 就是一组号码啦)。 由于电脑仅认识 0 与 1，所以主机对于数字比较有概念的；至于帐号只是为了让人们容易记忆而已。 而你的 ID 与帐号的对应就在 /etc/passwd 当中哩。

Tips:
如果你曾经在网路上下载过 tarball 类型的档案， 那么应该不难发现，在解压缩之后的档案中，档案拥有者的栏位竟然显示‘不明的数字’？奇怪吧？这没什么好奇怪的，因为 Linux 说实在话，他真的只认识代表你身份的号码而已！ 		鸟哥的图示

那么到底有几种 ID 呢？还记得我们在第六章内有提到过， 每一个档案都具有‘拥有人与拥有群组’的属性吗？没错啦～每个登入的使用者至少都会取得两个 ID ，一个是使用者 ID (User ID ，简称 UID)、一个是群组 ID (Group ID ，简称 GID)。

那么档案如何判别他的拥有者与群组呢？其实就是利用 UID 与 GID 啦！每一个档案都会有所谓的拥有者 ID 与拥有群组 ID ，当我们有要显示档案属性的需求时，系统会依据 /etc/passwd 与 /etc/group 的内容， 找到 UID / GID 对应的帐号与群组名称再显示出来！我们可以作个小实验，你可以用 root 的身份 vi /etc/passwd ，然后将你的一般身份的使用者的 ID 随便改一个号码，然后再到你的一般身份的目录下看看原先该帐号拥有的档案，你会发现该档案的拥有人变成了 ‘数字了’呵呵！这样可以理解了吗？来看看底下的例子：

# 1. 先察看一下，系统里面有没有一个名为 dmtsai 的用户？
[root@www ~]# grep 'dmtsai' /etc/passwd
dmtsai:x:503:504::/home/dmtsai:/bin/bash   <==是有这个帐号喔！
[root@www ~]# ll -d /home/dmtsai
drwx------ 4 dmtsai dmtsai 4096 Feb  6 18:25 /home/dmtsai
# 瞧一瞧，使用者的栏位正是 dmtsai 本身喔！

# 2. 修改一下，将刚刚我们的 dmtsai 的 503 UID 改为 2000 看看：
[root@www ~]# vi /etc/passwd
....(前面省略)....
dmtsai:x:2000:504::/home/dmtsai:/bin/bash <==修改一下特殊字体部分，由 503 改过来
[root@www ~]# ll -d /home/dmtsai
drwx------ 4 503 dmtsai 4096 Feb  6 18:25 /home/dmtsai
# 很害怕吧！怎么变成 503 了？因为档案只会记录数字而已！
# 因为我们乱改，所以导致 503 找不到对应的帐号，因此显示数字！

# 3. 记得将刚刚的 2000 改回来！
[root@www ~]# vi /etc/passwd
....(前面省略)....
dmtsai:x:503:504::/home/dmtsai:/bin/bash <==赶紧改回来！

你一定要了解的是，上面的例子仅是在说明 UID 与帐号的对应性，在一部正常运作的 Linux 主机环境下，上面的动作不可随便进行， 这是因为系统上已经有很多的资料被建立存在了，随意修改系统上某些帐号的 UID 很可能会导致某些程序无法进行，这将导致系统无法顺利运作的结果。 因为权限的问题啊！所以，了解了之后，请赶快回到 /etc/passwd 里面，将数字改回来喔！

Tips:
举例来说，如果上面的测试最后一个步骤没有将 2000 改回原本的 UID，那么当 dmtsai 下次登入时将没有办法进入自己的家目录！ 因为他的 UID 已经改为 2000 ，但是他的家目录 (/home/dmtsai) 却记录的是 503 ，由于权限是 700 ， 因此他将无法进入原本的家目录！是否非常严重啊？ 		鸟哥的图示
小标题的图示 使用者帐号

Linux 系统上面的使用者如果需要登入主机以取得 shell 的环境来工作时，他需要如何进行呢？ 首先，他必须要在电脑前面利用 tty1~tty7 的终端机提供的 login 介面，并输入帐号与密码后才能够登入。 如果是透过网路的话，那至少使用者就得要学习 ssh 这个功能了 (伺服器篇再来谈)。 那么你输入帐号密码后，系统帮你处理了什么呢？

  1. 先找寻 /etc/passwd 里面是否有你输入的帐号？如果没有则跳出，如果有的话则将该帐号对应的 UID 与 GID (在 /etc/group 中) 读出来，另外，该帐号的家目录与 shell 设定也一并读出；

  2. 再来则是核对密码表啦！这时 Linux 会进入 /etc/shadow 里面找出对应的帐号与 UID，然后核对一下你刚刚输入的密码与里头的密码是否相符？

  3. 如果一切都 OK 的话，就进入 Shell 控管的阶段啰！

大致上的情况就像这样，所以当你要登入你的 Linux 主机的时候，那个 /etc/passwd 与 /etc/shadow 就必须要让系统读取啦 (这也是很多攻击者会将特殊帐号写到 /etc/passwd 里头去的缘故)，所以呢，如果你要备份 Linux 的系统的帐号的话，那么这两个档案就一定需要备份才行呦！

由上面的流程我们也知道，跟使用者帐号有关的有两个非常重要的档案，一个是管理使用者 UID/GID 重要参数的 /etc/passwd ，一个则是专门管理密码相关资料的 /etc/shadow 啰！那这两个档案的内容就非常值得进行研究啦！ 底下我们会简单的介绍这两个档案，详细的说明可以参考 man 5 passwd 及 man 5 shadow (注1)。

  • /etc/passwd 档案结构

这个档案的构造是这样的：每一行都代表一个帐号，有几行就代表有几个帐号在你的系统中！ 不过需要特别留意的是，里头很多帐号本来就是系统正常运作所必须要的，我们可以简称他为系统帐号， 例如 bin, daemon, adm, nobody 等等，这些帐号请不要随意的杀掉他呢！ 这个档案的内容有点像这样：

Tips:
鸟哥在接触 Linux 之前曾经碰过 Solaris 系统 (1999 年)，当时鸟哥啥也不清楚！由于‘听说’Linux 上面的帐号越复杂会导致系统越危险！所以鸟哥就将 /etc/passwd 上面的帐号全部删除到只剩下 root 与鸟哥自己用的一般帐号！结果你猜发生什么事？那就是....呼叫升阳的工程师来维护系统 @_@！糗到一个不行！大家不要学啊！ 		鸟哥的图示
[root@www ~]# head -n 4 /etc/passwd
root:x:0:0:root:/root:/bin/bash  <==等一下做为底下说明用
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin

我们先来看一下每个 Linux 系统都会有的第一行，就是 root 这个系统管理员那一行好了， 你可以明显的看出来，每一行使用‘:’分隔开，共有七个咚咚，分别是：

  1. 帐号名称：
    就是帐号啦！用来对应 UID 的。例如 root 的 UID 对应就是 0 (第三栏位)；

  2. 密码：
    早期 Unix 系统的密码就是放在这栏位上！但是因为这个档案的特性是所有的程序都能够读取，这样一来很容易造成密码资料被窃取， 因此后来就将这个栏位的密码资料给他改放到 /etc/shadow 中了。所以这里你会看到一个‘ x ’，呵呵！

  3. UID：
    这个就是使用者识别码啰！通常 Linux 对于 UID 有几个限制需要说给您了解一下：

    id 范围 该 ID 使用者特性
    0
    (系统管理员)     		当 UID 是 0 时，代表这个帐号是‘系统管理员’！ 所以当你要让其他的帐号名称也具有 root 的权限时，将该帐号的 UID 改为 0 即可。 这也就是说，一部系统上面的系统管理员不见得只有 root 喔！ 不过，很不建议有多个帐号的 UID 是 0 啦～
    1~499
    (系统帐号)     		保留给系统使用的 ID，其实除了 0 之外，其他的 UID 权限与特性并没有不一样。预设 500 以下的数字让给系统作为保留帐号只是一个习惯。

    由于系统上面启动的服务希望使用较小的权限去运作，因此不希望使用 root 的身份去执行这些服务， 所以我们就得要提供这些运作中程式的拥有者帐号才行。这些系统帐号通常是不可登入的， 所以才会有我们在第十一章提到的 /sbin/nologin 这个特殊的 shell 存在。

    根据系统帐号的由来，通常系统帐号又约略被区分为两种：
    1~99：由 distributions 自行建立的系统帐号；
    100~499：若使用者有系统帐号需求时，可以使用的帐号 UID。
    500~65535
    (可登入帐号)     		给一般使用者用的。事实上，目前的 linux 核心 (2.6.x 版)已经可以支援到 4294967295 (2^32-1) 这么大的 UID 号码喔！

    上面这样说明可以了解了吗？是的， UID 为 0 的时候，就是 root 呦！所以请特别留意一下你的 /etc/passwd 档案！

  4. GID：
    这个与 /etc/group 有关！其实 /etc/group 的观念与 /etc/passwd 差不多，只是他是用来规范群组名称与 GID 的对应而已！

  5. 使用者资讯说明栏：
    这个栏位基本上并没有什么重要用途，只是用来解释这个帐号的意义而已！不过，如果您提供使用 finger 的功能时， 这个栏位可以提供很多的讯息呢！本章后面的 chfn 指令会来解释这里的说明。

  6. 家目录：
    这是使用者的家目录，以上面为例， root 的家目录在 /root ，所以当 root 登入之后，就会立刻跑到 /root 目录里头啦！呵呵！ 如果你有个帐号的使用空间特别的大，你想要将该帐号的家目录移动到其他的硬碟去该怎么作？ 没有错！可以在这个栏位进行修改呦！预设的使用者家目录在 /home/yourIDname

  7. Shell：
    我们在第十一章 BASH 提到很多次，当使用者登入系统后就会取得一个 Shell 来与系统的核心沟通以进行使用者的操作任务。那为何预设 shell 会使用 bash 呢？就是在这个栏位指定的啰！ 这里比较需要注意的是，有一个 shell 可以用来替代成让帐号无法取得 shell 环境的登入动作！那就是 /sbin/nologin 这个东西！这也可以用来制作纯 pop 邮件帐号者的资料呢！

  • /etc/shadow 档案结构

我们知道很多程式的运作都与权限有关，而权限与 UID/GID 有关！因此各程式当然需要读取 /etc/passwd 来了解不同帐号的权限。 因此 /etc/passwd 的权限需设定为 -rw-r--r-- 这样的情况， 虽然早期的密码也有加密过，但却放置到 /etc/passwd 的第二个栏位上！这样一来很容易被有心人士所窃取的， 加密过的密码也能够透过暴力破解法去 try and error (试误) 找出来！

因为这样的关系，所以后来发展出将密码移动到 /etc/shadow 这个档案分隔开来的技术， 而且还加入很多的密码限制参数在 /etc/shadow 里头呢！在这里，我们先来了解一下这个档案的构造吧！ 鸟哥的 /etc/shadow 档案有点像这样：

[root@www ~]# head -n 4 /etc/shadow
root:$1$/30QpE5e$y9N/D0bh6rAACBEz.hqo00:14126:0:99999:7:::  <==底下说明用
bin:*:14126:0:99999:7:::
daemon:*:14126:0:99999:7:::
adm:*:14126:0:99999:7:::

基本上， shadow 同样以‘:’作为分隔符号，如果数一数，会发现共有九个栏位啊，这九个栏位的用途是这样的：

  1. 帐号名称：
    由于密码也需要与帐号对应啊～因此，这个档案的第一栏就是帐号，必须要与 /etc/passwd 相同才行！

  2. 密码：
    这个栏位内的资料才是真正的密码，而且是经过编码的密码 (加密) 啦！ 你只会看到有一些特殊符号的字母就是了！需要特别留意的是，虽然这些加密过的密码很难被解出来， 但是‘很难’不等于‘不会’，所以，这个档案的预设权限是‘-rw-------’或者是‘-r--------’，亦即只有 root 才可以读写就是了！你得随时注意，不要不小心更动了这个档案的权限呢！

    另外，由于各种密码编码的技术不一样，因此不同的编码系统会造成这个栏位的长度不相同。 举例来说，旧式的 DES 编码系统产生的密码长度就与目前惯用的 MD5 不同(注2)！MD5 的密码长度明显的比较长些。由于固定的编码系统产生的密码长度必须一致，因此‘当你让这个栏位的长度改变后，该密码就会失效(算不出来)’。 很多软体透过这个功能，在此栏位前加上 ! 或 * 改变密码栏位长度，就会让密码‘暂时失效’了。

  3. 最近更动密码的日期：
    这个栏位记录了‘更动密码那一天’的日期，不过，很奇怪呀！在我的例子中怎么会是 14126 呢？呵呵，这个是因为计算 Linux 日期的时间是以 1970 年 1 月 1 日作为 1 而累加的日期，1971 年 1 月 1 日则为 366 啦！ 得注意一下这个资料呦！上述的 14126 指的就是 2008-09-04 那一天啦！了解乎？ 而想要了解该日期可以使用本章后面 chage 指令的帮忙！至于想要知道某个日期的累积日数， 可使用如下的程式计算：
    [root@www ~]# echo $(($(date --date="2008/09/04" +%s)/86400+1))
14126
    上述指令中，2008/09/04 为你想要计算的日期，86400 为每一天的秒数， %s 为 1970/01/01 以来的累积总秒数。 由于 bash 仅支援整数，因此最终需要加上 1 补齐 1970/01/01 当天。

  4. 密码不可被更动的天数：(与第 3 栏位相比)
    第四个栏位记录了：这个帐号的密码在最近一次被更改后需要经过几天才可以再被变更！如果是 0 的话， 表示密码随时可以更动的意思。这的限制是为了怕密码被某些人一改再改而设计的！如果设定为 20 天的话，那么当你设定了密码之后， 20 天之内都无法改变这个密码呦！

  5. 密码需要重新变更的天数：(与第 3 栏位相比)
    经常变更密码是个好习惯！为了强制要求使用者变更密码，这个栏位可以指定在最近一次更改密码后， 在多少天数内需要再次的变更密码才行。你必须要在这个天数内重新设定你的密码，否则这个帐号的密码将会‘变为过期特性’。 而如果像上面的 99999 (计算为 273 年) 的话，那就表示，呵呵，密码的变更没有强制性之意。

  6. 密码需要变更期限前的警告天数：(与第 5 栏位相比)
    当帐号的密码有效期限快要到的时候 (第 5 栏位)，系统会依据这个栏位的设定，发出‘警告’言论给这个帐号，提醒他‘再过 n 天你的密码就要过期了，请尽快重新设定你的密码呦！’，如上面的例子，则是密码到期之前的 7 天之内，系统会警告该用户。

  7. 密码过期后的帐号宽限时间(密码失效日)：(与第 5 栏位相比)
    密码有效日期为‘更新日期(第3栏位)’+‘重新变更日期(第5栏位)’，过了该期限后使用者依旧没有更新密码，那该密码就算过期了。 虽然密码过期但是该帐号还是可以用来进行其他工作的，包括登入系统取得 bash 。不过如果密码过期了， 那当你登入系统时，系统会强制要求你必须要重新设定密码才能登入继续使用喔，这就是密码过期特性。

    那这个栏位的功能是什么呢？是在密码过期几天后，如果使用者还是没有登入更改密码，那么这个帐号的密码将会‘失效’， 亦即该帐号再也无法使用该密码登入了。要注意密码过期与密码失效并不相同。

  8. 帐号失效日期：
    这个日期跟第三个栏位一样，都是使用 1970 年以来的总日数设定。这个栏位表示： 这个帐号在此栏位规定的日期之后，将无法再使用。 就是所谓的‘帐号失效’，此时不论你的密码是否有过期，这个‘帐号’都不能再被使用！ 这个栏位会被使用通常应该是在‘收费服务’的系统中，你可以规定一个日期让该帐号不能再使用啦！

  9. 保留：
    最后一个栏位是保留的，看以后有没有新功能加入。

举个例子来说好了，假如我的 dmtsai 这个使用者的密码栏如下所示：

dmtsai:$1$vyUuj.eX$omt6lKJvMcIZHx4H7RI1V.:14299:5:60:7:5:14419:

这表示什么呢？先要注意的是 14299 是 2009/02/24 。所以 dmtsai 这个使用者的密码相关意义是：

  • 由于密码几乎仅能单向运算(由明码计算成为密码，无法由密码反推回明码)，因此由上表的资料我们无法得知 dmstai 的实际密码明文；

  • 此帐号最近一次更动密码的日期是 2009/02/24 (14299)；

  • 能够再次修改密码的时间是 5 天以后，也就是 2009/03/01 以前 dmtsai 不能修改自己的密码；如果使用者还是尝试要更动自己的密码，系统就会出现这样的讯息：
    You must wait longer to change your password
passwd: Authentication token manipulation error
    画面中告诉我们：你必须要等待更久的时间才能够变更密码之意啦！

  • 由于密码过期日期定义为 60 天后，亦即累积日数为： 14299+60=14359，经过计算得到此日数代表日期为 2009/04/25。 这表示：‘使用者必须要在 2009/03/01 到 2009/04/25 之间的 60 天限制内去修改自己的密码，若 2009/04/25 之后还是没有变更密码时，该密码就宣告为过期’了！

  • 警告日期设为 7 天，亦即是密码过期日前的 7 天，在本例中则代表 2009/04/19 ~ 2009/04/25 这七天。 如果使用者一直没有更改密码，那么在这 7 天中，只要 dmtsai 登入系统就会发现如下的讯息：
    Warning: your password will expire in 5 days

  • 如果该帐号一直到 2009/04/25 都没有更改密码，那么密码就过期了。但是由于有 5 天的宽限天数， 因此 dmtsai 在 2009/04/30 前都还可以使用旧密码登入主机。 不过登入时会出现强制更改密码的情况，画面有点像底下这样：
    You are required to change your password immediately (password aged)
WARNING: Your password has expired.
You must change your password now and login again!
Changing password for user dmtsai.
Changing password for dmtsai
(current) UNIX password:
    你必须要输入一次旧密码以及两次新密码后，才能够开始使用系统的各项资源。如果你是在 2009/04/30 以后尝试以 dmtsai 登入的话，那么就会出现如下的错误讯息且无法登入，因为此时你的密码就失效去啦！
    Your account has expired; please contact your system administrator

  • 如果使用者在 2009/04/25 以前变更过密码，那么第 3 个栏位的那个 14299 的天数就会跟着改变，因此， 所有的限制日期也会跟着相对变动喔！^_^

  • 无论使用者如何动作，到了 14419 (大约是 2009/07/24 左右) 该帐号就失效了～

透过这样的说明，您应该会比较容易理解了吧？由于 shadow 有这样的重要性，因此可不能随意修改喔！ 但在某些情况底下你得要使用各种方法来处理这个档案的！举例来说，常常听到人家说：‘我的密码忘记了’， 或者是‘我的密码不晓得被谁改过，跟原先的不一样了’，这个时候怎么办？

  • 一般用户的密码忘记了：这个最容易解决，请系统管理员帮忙， 他会重新设定好你的密码而不需要知道你的旧密码！利用 root 的身份使用 passwd 指令来处理即可。

  • root 密码忘记了：这就麻烦了！因为你无法使用 root 的身份登入了嘛！ 但我们知道 root 的密码在 /etc/shadow 当中，因此你可以使用各种可行的方法开机进入 Linux 再去修改。 例如重新开机进入单人维护模式(第二十章)后，系统会主动的给予 root 权限的 bash 介面， 此时再以 passwd 修改密码即可；或以 Live CD 开机后挂载根目录去修改 /etc/shadow，将里面的 root 的密码栏位清空， 再重新开机后 root 将不用密码即可登入！登入后再赶快以 passwd 指令去设定 root 密码即可。
Tips:
曾经听过一则笑话，某位老师主要是在教授 Linux 作业系统，但是他是兼任的老师，因此对于该系的电脑环境不熟。 由于当初安装该电脑教室 Linux 作业系统的人员已经离职且找不到联络方式了，也就是说 root 密码已经没有人晓得了！ 此时该老师就对学生说：‘在 Linux 里面 root 密码不见了，我们只能重新安装’...感觉有点无力～ 又是个被 Windows 制约的人才！ 		鸟哥的图示
小标题的图示 关于群组： 有效与初始群组、groups, newgrp

认识了帐号相关的两个档案 /etc/passwd 与 /etc/shadow 之后，你或许还是会觉得奇怪， 那么群组的设定档在哪里？还有，在 /etc/passwd 的第四栏不是所谓的 GID 吗？那又是啥？ 呵呵～此时就需要了解 /etc/group 与 /etc/gshadow 啰～

  • /etc/group 档案结构

这个档案就是在记录 GID 与群组名称的对应了～鸟哥测试机的 /etc/group 内容有点像这样：

[root@www ~]# head -n 4 /etc/group
root:x:0:root
bin:x:1:root,bin,daemon
daemon:x:2:root,bin,daemon
sys:x:3:root,bin,adm

这个档案每一行代表一个群组，也是以冒号‘:’作为栏位的分隔符号，共分为四栏，每一栏位的意义是：

  1. 群组名称：
    就是群组名称啦！

  2. 群组密码：
    通常不需要设定，这个设定通常是给‘群组管理员’使用的，目前很少有这个机会设定群组管理员啦！ 同样的，密码已经移动到 /etc/gshadow 去，因此这个栏位只会存在一个‘x’而已；

  3. GID：
    就是群组的 ID 啊。我们 /etc/passwd 第四个栏位使用的 GID 对应的群组名，就是由这里对应出来的！

  4. 此群组支援的帐号名称：
    我们知道一个帐号可以加入多个群组，那某个帐号想要加入此群组时，将该帐号填入这个栏位即可。 举例来说，如果我想要让 dmtsai 也加入 root 这个群组，那么在第一行的最后面加上‘,dmtsai’，注意不要有空格， 使成为‘ root:x:0:root,dmtsai ’就可以啰～

谈完了 /etc/passwd, /etc/shadow, /etc/group 之后，我们可以使用一个简单的图示来了解一下 UID / GID 与密码之间的关系， 图示如下。其实重点是 /etc/passwd 啦，其他相关的资料都是根据这个档案的栏位去找寻出来的。 下图中， root 的 UID 是 0 ，而 GID 也是 0 ，去找 /etc/group 可以知道 GID 为 0 时的群组名称就是 root 哩。 至于密码的寻找中，会找到 /etc/shadow 与 /etc/passwd 内同帐号名称的那一行，就是密码相关资料啰。

帐号相关档案之间的 UID/GID 与密码相关性示意图
图 1.3.1 、帐号相关档案之间的 UID/GID 与密码相关性示意图

至于在 /etc/group 比较重要的特色在于第四栏啦，因为每个使用者都可以拥有多个支援的群组，这就好比在学校念书的时候， 我们可以加入多个社团一样！ ^_^。不过这里你或许会觉得奇怪的，那就是：‘假如我同时加入多个群组，那么我在作业的时候，到底是以那个群组为准？’ 底下我们就来谈一谈这个‘有效群组’的概念。

  • 有效群组(effective group)与初始群组(initial group)

还记得每个使用者在他的 /etc/passwd 里面的第四栏有所谓的 GID 吧？那个 GID 就是所谓的‘初始群组 (initial group) ’！也就是说，当使用者一登入系统，立刻就拥有这个群组的相关权限的意思。 举例来说，我们上面提到 dmtsai 这个使用者的 /etc/passwd 与 /etc/group 还有 /etc/gshadow 相关的内容如下：

[root@www ~]# usermod -G users dmtsai  <==先设定好次要群组
[root@www ~]# grep dmtsai /etc/passwd /etc/group /etc/gshadow
/etc/passwd:dmtsai:x:503:504::/home/dmtsai:/bin/bash
/etc/group:users:x:100:dmtsai  <==次要群组的设定
/etc/group:dmtsai:x:504:       <==因为是初始群组，所以第四栏位不需要填入帐号
/etc/gshadow:users:::dmtsai    <==次要群组的设定
/etc/gshadow:dmtsai:!::

仔细看到上面这个表格，在 /etc/passwd 里面，dmtsai 这个使用者所属的群组为 GID=504 ，搜寻一下 /etc/group 得到 504 是那个名为 dmtsai 的群组啦！这就是 initial group。因为是初始群组， 使用者一登入就会主动取得，不需要在 /etc/group 的第四个栏位写入该帐号的！

但是非 initial group 的其他群组可就不同了。举上面这个例子来说，我将 dmtsai 加入 users 这个群组当中，由于 users 这个群组并非是 dmtsai 的初始群组，因此， 我必须要在 /etc/group 这个档案中，找到 users 那一行，并且将 dmtsai 这个帐号加入第四栏， 这样 dmtsai 才能够加入 users 这个群组啊。

那么在这个例子当中，因为我的 dmtsai 帐号同时支援 dmtsai 与 users 这两个群组， 因此，在读取/写入/执行档案时，针对群组部分，只要是 users 与 dmtsai 这两个群组拥有的功能， 我 dmtsai 这个使用者都能够拥有喔！这样了呼？不过，这是针对已经存在的档案而言， 如果今天我要建立一个新的档案或者是新的目录，请问一下，新档案的群组是 dmtsai 还是 users ？呵呵！这就得要检查一下当时的有效群组了 (effective group)。

  • groups: 有效与支援群组的观察

如果我以 dmtsai 这个使用者的身份登入后，该如何知道我所有支援的群组呢？ 很简单啊，直接输入 groups 就可以了！注意喔，是 groups 有加 s 呢！结果像这样：

[dmtsai@www ~]$ groups
dmtsai users

在这个输出的讯息中，可知道 dmtsai 这个用户同时属于 dmtsai 及 users 这个两个群组，而且， 第一个输出的群组即为有效群组 (effective group) 了。 也就是说，我的有效群组为 dmtsai 啦～此时，如果我以 touch 去建立一个新档，例如： ‘ touch test ’，那么这个档案的拥有者为 dmtsai ，而且群组也是 dmtsai 的啦。

[dmtsai@www ~]$ touch test
[dmtsai@www ~]$ ll
-rw-rw-r-- 1 dmtsai dmtsai 0 Feb 24 17:26 test

这样是否可以了解什么是有效群组了？通常有效群组的作用是在新建档案啦！那么有效群组是否能够变换？

  • newgrp: 有效群组的切换

那么如何变更有效群组呢？就使用 newgrp 啊！不过使用 newgrp 是有限制的，那就是你想要切换的群组必须是你已经有支援的群组。举例来说， dmtsai 可以在 dmtsai/users 这两个群组间切换有效群组，但是 dmtsai 无法切换有效群组成为 sshd 啦！使用的方式如下：

[dmtsai@www ~]$ newgrp users
[dmtsai@www ~]$ groups
users dmtsai
[dmtsai@www ~]$ touch test2
[dmtsai@www ~]$ ll
-rw-rw-r-- 1 dmtsai dmtsai 0 Feb 24 17:26 test
-rw-r--r-- 1 dmtsai users  0 Feb 24 17:33 test2

此时，dmtsai 的有效群组就成为 users 了。 我们额外的来讨论一下 newgrp 这个指令，这个指令可以变更目前使用者的有效群组， 而且是另外以一个 shell 来提供这个功能的喔，所以，以上面的例子来说， dmtsai 这个使用者目前是以另一个 shell 登入的，而且新的 shell 给予 dmtsai 有效 GID 为 users 就是了。如果以图示来看就是如下所示：

newgrp 的运作示意图
图 1.3.2 、newgrp 的运作示意图

虽然使用者的环境设定(例如环境变数等等其他资料)不会有影响，但是使用者的‘群组权限’将会重新被计算。 但是需要注意，由于是新取得一个 shell ，因此如果你想要回到原本的环境中，请输入 exit 回到原本的 shell 喔！

既然如此，也就是说，只要我的用户有支援的群组就是能够切换成为有效群组！好了， 那么如何让一个帐号加入不同的群组就是问题的所在啰。你要加入一个群组有两个方式，一个是透过系统管理员 (root) 利用 usermod 帮你加入，如果 root 太忙了而且你的系统有设定群组管理员，那么你可以透过群组管理员以 gpasswd 帮你加入他所管理的群组中！详细的作法留待下一小节再来介绍啰！

  • /etc/gshadow

刚刚讲了很多关于‘有效群组’的概念，另外，也提到 newgrp 这个指令的用法， 但是，如果 /etc/gshadow 这个设定没有搞懂得话，那么 newgrp 是无法动作的呢！ 鸟哥测试机的 /etc/gshadow 的内容有点像这样：

[root@www ~]# head -n 4 /etc/gshadow
root:::root
bin:::root,bin,daemon
daemon:::root,bin,daemon
sys:::root,bin,adm

这个档案内同样还是使用冒号‘:’来作为栏位的分隔字元，而且你会发现，这个档案几乎与 /etc/group 一模一样啊！是这样没错～不过，要注意的大概就是第二个栏位吧～第二个栏位是密码栏， 如果密码栏上面是‘!’时，表示该群组不具有群组管理员！至于第四个栏位也就是支援的帐号名称啰～ 这四个栏位的意义为：

  1. 群组名称
  2. 密码栏，同样的，开头为 ! 表示无合法密码，所以无群组管理员
  3. 群组管理员的帐号 (相关资讯在 gpasswd 中介绍)
  4. 该群组的所属帐号 (与 /etc/group 内容相同！)

以系统管理员的角度来说，这个 gshadow 最大的功能就是建立群组管理员啦！ 那么什么是群组管理员呢？由于系统上面的帐号可能会很多，但是我们 root 可能平时太忙碌，所以当有使用者想要加入某些群组时， root 或许会没有空管理。此时如果能够建立群组管理员的话，那么该群组管理员就能够将那个帐号加入自己管理的群组中！ 可以免去 root 的忙碌啦！不过，由于目前有类似 sudo 之类的工具， 所以这个群组管理员的功能已经很少使用了。我们会在后续的 gpasswd 中介绍这个实作。

大标题的图示 帐号管理

好啦！既然要管理帐号，当然是由新增与移除使用者开始的啰～底下我们就分别来谈一谈如何新增、 移除与更改使用者的相关资讯吧～

小标题的图示 新增与移除使用者： useradd, 相关设定档, passwd, usermod, userdel

要如何在 Linux 的系统新增一个使用者啊？呵呵～真是太简单了～我们登入系统时会输入 (1)帐号与 (2)密码， 所以建立一个可用的帐号同样的也需要这两个资料。那帐号可以使用 useradd 来新建使用者，密码的给予则使用 passwd 这个指令！这两个指令下达方法如下：

  • useradd
[root@www ~]# useradd [-u UID] [-g 初始群组] [-G 次要群组] [-mM]\
>  [-c 说明栏] [-d 家目录绝对路径] [-s shell] 使用者帐号名
选项与参数：
-u  ：后面接的是 UID ，是一组数字。直接指定一个特定的 UID 给这个帐号；
-g  ：后面接的那个群组名称就是我们上面提到的 initial group 啦～
      该群组的 GID 会被放置到 /etc/passwd 的第四个栏位内。
-G  ：后面接的群组名称则是这个帐号还可以加入的群组。
      这个选项与参数会修改 /etc/group 内的相关资料喔！
-M  ：强制！不要建立使用者家目录！(系统帐号预设值)
-m  ：强制！要建立使用者家目录！(一般帐号预设值)
-c  ：这个就是 /etc/passwd 的第五栏的说明内容啦～可以随便我们设定的啦～
-d  ：指定某个目录成为家目录，而不要使用预设值。务必使用绝对路径！
-r  ：建立一个系统的帐号，这个帐号的 UID 会有限制 (参考 /etc/login.defs)
-s  ：后面接一个 shell ，若没有指定则预设是 /bin/bash 的啦～
-e  ：后面接一个日期，格式为‘YYYY-MM-DD’此项目可写入 shadow 第八栏位，
      亦即帐号失效日的设定项目啰；
-f  ：后面接 shadow 的第七栏位项目，指定密码是否会失效。0为立刻失效，
      -1 为永远不失效(密码只会过期而强制于登入时重新设定而已。)

范例一：完全参考预设值建立一个使用者，名称为 vbird1
[root@www ~]# useradd vbird1
[root@www ~]# ll -d /home/vbird1
drwx------ 4 vbird1 vbird1 4096 Feb 25 09:38 /home/vbird1
# 预设会建立使用者家目录，且权限为 700 ！这是重点！

[root@www ~]# grep vbird1 /etc/passwd /etc/shadow /etc/group
/etc/passwd:vbird1:x:504:505::/home/vbird1:/bin/bash
/etc/shadow:vbird1:!!:14300:0:99999:7:::
/etc/group:vbird1:x:505:    <==预设会建立一个与帐号一模一样的群组名

其实系统已经帮我们规定好非常多的预设值了，所以我们可以简单的使用‘ useradd 帐号 ’来建立使用者即可。 CentOS 这些预设值主要会帮我们处理几个项目：

  • 在 /etc/passwd 里面建立一行与帐号相关的资料，包括建立 UID/GID/家目录等；
  • 在 /etc/shadow 里面将此帐号的密码相关参数填入，但是尚未有密码；
  • 在 /etc/group 里面加入一个与帐号名称一模一样的群组名称；
  • 在 /home 底下建立一个与帐号同名的目录作为使用者家目录，且权限为 700

由于在 /etc/shadow 内仅会有密码参数而不会有加密过的密码资料，因此我们在建立使用者帐号时， 还需要使用‘ passwd 帐号 ’来给予密码才算是完成了使用者建立的流程。如果由于特殊需求而需要改变使用者相关参数时， 就得要透过上述表格中的选项来进行建立了，参考底下的案例：

范例二：假设我已知道我的系统当中有个群组名称为 users ，且 UID 700 并不存在，
        请用 users 为初始群组，以及 uid 为 700 来建立一个名为 vbird2 的帐号
[root@www ~]# useradd -u 700 -g users vbird2
[root@www ~]# ll -d /home/vbird2
drwx------ 4 vbird2 users 4096 Feb 25 09:59 /home/vbird2

[root@www ~]# grep vbird2 /etc/passwd /etc/shadow /etc/group
/etc/passwd:vbird2:x:700:100::/home/vbird2:/bin/bash
/etc/shadow:vbird2:!!:14300:0:99999:7:::
# 看一下，UID 与 initial group 确实改变成我们需要的了！

在这个范例中，我们建立的是指定一个已经存在的群组作为使用者的初始群组，因为群组已经存在， 所以在 /etc/group 里面就不会主动的建立与帐号同名的群组了！ 此外，我们也指定了特殊的 UID 来作为使用者的专属 UID 喔！了解了一般帐号后，我们来瞧瞧那啥是系统帐号 (system account) 吧！

范例三：建立一个系统帐号，名称为 vbird3
[root@www ~]# useradd -r vbird3
[root@www ~]# ll -d /home/vbird3
ls: /home/vbird3: No such file or directory  <==不会主动建立家目录

[root@www ~]# grep vbird3 /etc/passwd /etc/shadow /etc/group
/etc/passwd:vbird3:x:100:103::/home/vbird3:/bin/bash
/etc/shadow:vbird3:!!:14300::::::
/etc/group:vbird3:x:103:

我们在谈到 UID 的时候曾经说过一般帐号应该是 500 号以后，那使用者自己建立的系统帐号则一般是由 100 号以后起算的。 所以在这里我们加上 -r 这个选项以后，系统就会主动将帐号与帐号同名群组的 UID/GID 都指定小于 500 以下， 在本案例中则是使用 100(UID) 与 103(GID) 啰！此外，由于系统帐号主要是用来进行运作系统所需服务的权限设定， 所以系统帐号预设都不会主动建立家目录的！

由这几个范例我们也会知道，使用 useradd 建立使用者帐号时，其实会更改不少地方，至少我们就知道底下几个档案：

  • 使用者帐号与密码参数方面的档案：/etc/passwd, /etc/shadow
  • 使用者群组相关方面的档案：/etc/group, /etc/gshadow
  • 使用者的家目录：/home/帐号名称

那请教一下，你有没有想过，为何‘ useradd vbird1 ’会主动在 /home/vbird1 建立起使用者的家目录？家目录内有什么资料且来自哪里？为何预设使用的是 /bin/bash 这个 shell ？为何密码栏位已经都规范好了 (0:99999:7 那一串)？呵呵！这就得要说明一下 useradd 所使用的参考档案啰！

  • useradd 参考档

其实 useradd 的预设值可以使用底下的方法呼叫出来：

[root@www ~]# useradd -D
GROUP=100		<==预设的群组
HOME=/home		<==预设的家目录所在目录
INACTIVE=-1		<==密码失效日，在 shadow 内的第 7 栏
EXPIRE=			<==帐号失效日，在 shadow 内的第 8 栏
SHELL=/bin/bash		<==预设的 shell
SKEL=/etc/skel		<==使用者家目录的内容资料参考目录
CREATE_MAIL_SPOOL=yes   <==是否主动帮使用者建立邮件信箱(mailbox)

这个资料其实是由 /etc/default/useradd 呼叫出来的！你可以自行用 vim 去观察该档案的内容。搭配上头刚刚谈过的范例一的运作结果，上面这些设定项目所造成的行为分别是：

  • GROUP=100：新建帐号的初始群组使用 GID 为 100 者

    系统上面 GID 为 100 者即是 users 这个群组，此设定项目指的就是让新设使用者帐号的初始群组为 users 这一个的意思。 但是我们知道 CentOS 上面并不是这样的，在 CentOS 上面预设的群组为与帐号名相同的群组。 举例来说， vbird1 的初始群组为 vbird1 。怎么会这样啊？这是因为针对群组的角度有两种不同的机制所致， 这两种机制分别是：

    • 私有群组机制：系统会建立一个与帐号一样的群组给使用者作为初始群组。 这种群组的设定机制会比较有保密性，这是因为使用者都有自己的群组，而且家目录权限将会设定为 700 (仅有自己可进入自己的家目录) 之故。使用这种机制将不会参考 GROUP=100 这个设定值。代表性的 distributions 有 RHEL, Fedora, CentOS 等；

    • 公共群组机制：就是以 GROUP=100 这个设定值作为新建帐号的初始群组，因此每个帐号都属于 users 这个群组， 且预设家目录通常的权限会是‘ drwxr-xr-x ... username users ... ’，由于每个帐号都属于 users 群组，因此大家都可以互相分享家目录内的资料之故。代表 distributions 如 SuSE等。

    由于我们的 CentOS 使用私有群组机制，因此这个设定项目是不会生效的！不要太紧张啊！

  • HOME=/home：使用者家目录的基准目录(basedir)

    使用者的家目录通常是与帐号同名的目录，这个目录将会摆放在此设定值的目录后。所以 vbird1 的家目录就会在 /home/vbird1/ 了！很容易理解吧！

  • INACTIVE=-1：密码过期后是否会失效的设定值

    我们在 shadow 档案结构当中谈过，第七个栏位的设定值将会影响到密码过期后， 在多久时间内还可使用旧密码登入。这个项目就是在指定该日数啦！如果是 0 代表密码过期立刻失效， 如果是 -1 则是代表密码永远不会失效，如果是数字，如 30 ，则代表过期 30 天后才失效。

  • EXPIRE=：帐号失效的日期

    就是 shadow 内的第八栏位，你可以直接设定帐号在哪个日期后就直接失效，而不理会密码的问题。 通常不会设定此项目，但如果是付费的会员制系统，或许这个栏位可以设定喔！

  • SHELL=/bin/bash：预设使用的 shell 程式档名

    系统预设的 shell 就写在这里。假如你的系统为 mail server ，你希望每个帐号都只能使用 email 的收发信件功能， 而不许使用者登入系统取得 shell ，那么可以将这里设定为 /sbin/nologin ，如此一来，新建的使用者预设就无法登入！ 也免去后续使用 usermod 进行修改的手续！

  • SKEL=/etc/skel：使用者家目录参考基准目录

    这个咚咚就是指定使用者家目录的参考基准目录啰～举我们的范例一为例， vbird1 家目录 /home/vbird1 内的各项资料，都是由 /etc/skel 所复制过去的～所以呢，未来如果我想要让新增使用者时，该使用者的环境变数 ~/.bashrc 就设定妥当的话，您可以到 /etc/skel/.bashrc 去编辑一下，也可以建立 /etc/skel/www 这个目录，那么未来新增使用者后，在他的家目录下就会有 www 那个目录了！这样了呼？

  • CREATE_MAIL_SPOOL=yes：建立使用者的 mailbox

    你可以使用‘ ll /var/spool/mail/vbird1 ’看一下，会发现有这个档案的存在喔！这就是使用者的邮件信箱！

除了这些基本的帐号设定值之外， UID/GID 还有密码参数又是在哪里参考的呢？那就得要看一下 /etc/login.defs 啦！ 这个档案的内容有点像底下这样：

MAIL_DIR        /var/spool/mail	<==使用者预设邮件信箱放置目录

PASS_MAX_DAYS   99999	<==/etc/shadow 内的第 5 栏，多久需变更密码日数
PASS_MIN_DAYS   0	<==/etc/shadow 内的第 4 栏，多久不可重新设定密码日数
PASS_MIN_LEN    5	<==密码最短的字元长度，已被 pam 模组取代，失去效用！
PASS_WARN_AGE   7	<==/etc/shadow 内的第 6 栏，过期前会警告的日数

UID_MIN         500	<==使用者最小的 UID，意即小于 500 的 UID 为系统保留
UID_MAX       60000	<==使用者能够用的最大 UID
GID_MIN         500	<==使用者自订群组的最小 GID，小于 500 为系统保留
GID_MAX       60000	<==使用者自订群组的最大 GID

CREATE_HOME     yes	<==在不加 -M 及 -m 时，是否主动建立使用者家目录？
UMASK           077     <==使用者家目录建立的 umask ，因此权限会是 700
USERGROUPS_ENAB yes     <==使用 userdel 删除时，是否会删除初始群组
MD5_CRYPT_ENAB yes      <==密码是否经过 MD5 的加密机制处理

这个档案规范的资料则是如下所示：

  • mailbox 所在目录：
    使用者的预设 mailbox 档案放置的目录在 /var/spool/mail，所以 vbird1 的 mailbox 就是在 /var/spool/mail/vbird1 啰！

  • shadow 密码第 4, 5, 6 栏位内容：
    透过 PASS_MAX_DAYS 等等设定值来指定的！所以你知道为何预设的 /etc/shadow 内每一行都会有‘ 0:99999:7 ’的存在了吗？^_^！不过要注意的是，由于目前我们登入时改用 PAM 模组来进行密码检验，所以那个 PASS_MIN_LEN 是失效的！

  • UID/GID 指定数值：
    虽然 Linux 核心支援的帐号可高达 232 这么多个，不过一部主机要作出这么多帐号在管理上也是很麻烦的！ 所以在这里就针对 UID/GID 的范围进行规范就是了。上表中的 UID_MIN 指的就是可登入系统的一般帐号的最小 UID ，至于 UID_MAX 则是最大 UID 之意。

    要注意的是，系统给予一个帐号 UID 时，他是 (1)先参考 UID_MIN 设定值取得最小数值； (2)由 /etc/passwd 搜寻最大的 UID 数值， 将 (1) 与 (2) 相比，找出最大的那个再加一就是新帐号的 UID 了。我们上面已经作出 UID 为 700 的 vbird2 ， 如果再使用‘ useradd vbird4 ’时，你猜 vbird4 的 UID 会是多少？答案是： 701 。 所以中间的 505~699 的号码就空下来啦！

    而如果我是想要建立系统用的帐号，所以使用 useradd -r sysaccount 这个 -r 的选项时，就会找‘比 500 小的最大的那个 UID + 1 ’就是了。 ^_^

  • 使用者家目录设定值：
    为何我们系统预设会帮使用者建立家目录？就是这个‘CREATE_HOME = yes’的设定值啦！这个设定值会让你在使用 useradd 时， 主动加入‘ -m ’这个产生家目录的选项啊！如果不想要建立使用者家目录，就只能强制加上‘ -M ’的选项在 useradd 指令执行时啦！至于建立家目录的权限设定呢？就透过 umask 这个设定值啊！因为是 077 的预设设定，因此使用者家目录预设权限才会是‘ drwx------ ’哩！

  • 使用者删除与密码设定值：
    使用‘USERGROUPS_ENAB yes’这个设定值的功能是： 如果使用 userdel 去删除一个帐号时，且该帐号所属的初始群组已经没有人隶属于该群组了， 那么就删除掉该群组，举例来说，我们刚刚有建立 vbird4 这个帐号，他会主动建立 vbird4 这个群组。 若 vbird4 这个群组并没有其他帐号将他加入支援的情况下，若使用 userdel vbird4 时，该群组也会被删除的意思。 至于‘MD5_CRYPT_ENAB yes’则表示使用 MD5 来加密密码明文，而不使用旧式的 DES(注2) 。

现在你知道啦，使用 useradd 这支程式在建立 Linux 上的帐号时，至少会参考：

  • /etc/default/useradd
  • /etc/login.defs
  • /etc/skel/*

这些档案，不过，最重要的其实是建立 /etc/passwd, /etc/shadow, /etc/group, /etc/gshadow 还有使用者家目录就是了～所以，如果你了解整个系统运作的状态，也是可以手动直接修改这几个档案就是了。 OK！帐号建立了，接下来处理一下使用者的密码吧！

  • passwd

刚刚我们讲到了，使用 useradd 建立了帐号之后，在预设的情况下，该帐号是暂时被封锁的， 也就是说，该帐号是无法登入的，你可以去瞧一瞧 /etc/shadow 内的第二个栏位就晓得啰～ 那该如何是好？怕什么？直接给他设定新密码就好了嘛！对吧～设定密码就使用 passwd 啰！

[root@www ~]# passwd [--sdtin]  <==所有人均可使用来改自己的密码
[root@www ~]# passwd [-l] [-u] [--sdtin] [-S] \
>  [-n 日数] [-x 日数] [-w 日数] [-i 日期] 帐号 <==root 功能
选项与参数：
--stdin ：可以透过来自前一个管线的资料，作为密码输入，对 shell script 有帮助！
-l  ：是 Lock 的意思，会将 /etc/shadow 第二栏最前面加上 ! 使密码失效；
-u  ：与 -l 相对，是 Unlock 的意思！
-S  ：列出密码相关参数，亦即 shadow 档案内的大部分资讯。
-n  ：后面接天数，shadow 的第 4 栏位，多久不可修改密码天数
-x  ：后面接天数，shadow 的第 5 栏位，多久内必须要更动密码
-w  ：后面接天数，shadow 的第 6 栏位，密码过期前的警告天数
-i  ：后面接‘日期’，shadow 的第 7 栏位，密码失效日期

范例一：请 root 给予 vbird2 密码
[root@www ~]# passwd vbird2
Changing password for user vbird2.
New UNIX password: <==这里直接输入新的密码，荧幕不会有任何反应
BAD PASSWORD: it is WAY too short <==密码太简单或过短的错误！
Retype new UNIX password:  <==再输入一次同样的密码
passwd: all authentication tokens updated successfully.  <==竟然还是成功修改了！

root 果然是最伟大的人物！当我们要给予使用者密码时，透过 root 来设定即可。 root 可以设定各式各样的密码，系统几乎一定会接受！所以您瞧瞧，如同上面的范例一，明明鸟哥输入的密码太短了， 但是系统依旧可接受 vbird2 这样的密码设定。这个是 root 帮忙设定的结果，那如果是使用者自己要改密码呢？ 包括 root 也是这样修改的喔！

范例二：用 vbird2 登入后，修改 vbird2 自己的密码
[vbird2@www ~]$ passwd   <==后面没有加帐号，就是改自己的密码！
Changing password for user vbird2.
Changing password for vbird2
(current) UNIX password: <==这里输入‘原有的旧密码’
New UNIX password: <==这里输入新密码
BAD PASSWORD: it is based on a dictionary word <==密码检验不通过，请再想个新密码
New UNIX password: <==这里再想个来输入吧
Retype new UNIX password: <==通过密码验证！所以重复这个密码的输入
passwd: all authentication tokens updated successfully. <==有无成功看关键字

passwd 的使用真的要很注意，尤其是 root 先生啊！鸟哥在课堂上每次讲到这里，说是要帮自己的一般帐号建立密码时， 有一小部分的学生就是会忘记加上帐号，结果就变成改变 root 自己的密码，最后.... root 密码就这样不见去！唉～ 要帮一般帐号建立密码需要使用‘ passwd 帐号 ’的格式，使用‘ passwd ’表示修改自己的密码！拜托！千万不要改错！

与 root 不同的是，一般帐号在更改密码时需要先输入自己的旧密码 (亦即 current 那一行)，然后再输入新密码 (New 那一行)。 要注意的是，密码的规范是非常严格的，尤其新的 distributions 大多使用 PAM 模组来进行密码的检验，包括太短、 密码与帐号相同、密码为字典常见字串等，都会被 PAM 模组检查出来而拒绝修改密码，此时会再重复出现‘ New ’这个关键字！ 那时请再想个新密码！若出现‘ Retype ’才是你的密码被接受了！重复输入新密码并且看到‘ successfully ’这个关键字时才是修改密码成功喔！

Tips:
与一般使用者不同的是， root 并不需要知道旧密码就能够帮使用者或 root 自己建立新密码！ 但如此一来有困扰～就是如果你的亲密爱人老是告诉你‘我的密码真难记，帮我设定简单一点的！’时， 千万不要妥协啊！这是为了系统安全... 		鸟哥的图示

为何使用者要设订自己的密码会这么麻烦啊？这是因为密码的安全性啦！如果密码设定太简单， 一些有心人士就能够很简单的猜到你的密码，如此一来人家就可能使用你的一般帐号登入你的主机或使用其他主机资源， 对主机的维护会造成困扰的！所以新的 distributions 是使用较严格的 PAM 模组来管理密码，这个管理的机制写在 /etc/pam.d/passwd 当中。而该档案与密码有关的测试模组就是使用：pam_cracklib.so，这个模组会检验密码相关的资讯， 并且取代 /etc/login.defs 内的 PASS_MIN_LEN 的设定啦！关于 PAM 我们在本章后面继续介绍，这里先谈一下， 理论上，你的密码最好符合如下要求：

  • 密码不能与帐号相同；
  • 密码尽量不要选用字典里面会出现的字串；
  • 密码需要超过 8 个字元；
  • 密码不要使用个人资讯，如身份证、手机号码、其他电话号码等；
  • 密码不要使用简单的关系式，如 1+1=2， Iamvbird 等；
  • 密码尽量使用大小写字元、数字、特殊字元($,_,-等)的组合。

为了方便系统管理，新版的 passwd 还加入了很多创意选项喔！鸟哥个人认为最好用的大概就是这个‘ --stdin ’了！ 举例来说，你想要帮 vbird2 变更密码成为 abc543CC ，可以这样下达指令呢！

范例三：使用 standard input 建立用户的密码
[root@www ~]# echo "abc543CC" | passwd --stdin vbird2
Changing password for user vbird2.
passwd: all authentication tokens updated successfully.

这个动作会直接更新使用者的密码而不用再次的手动输入！好处是方便处理，缺点是这个密码会保留在指令中， 未来若系统被攻破，人家可以在 /root/.bash_history 找到这个密码呢！所以这个动作通常仅用在 shell script 的大量建立使用者帐号当中！要注意的是，这个选项并不存在所有 distributions 版本中， 请使用 man passwd 确认你的 distribution 是否有支援此选项喔！

如果你想要让 vbird2 的密码具有相当的规则，举例来说你要让 vbird2 每 60 天需要变更密码， 密码过期后 10 天未使用就宣告密码失效，那该如何处理？

范例四：管理 vbird2 的密码使具有 60 天变更、10 天密码失效的设定
[root@www ~]# passwd -S vbird2
vbird2 PS 2009-02-26 0 99999 7 -1 (Password set, MD5 crypt.)
# 上面说明密码建立时间 (2009-02-26)、0 最小天数、99999 变更天数、7 警告日数
# 与密码不会失效 (-1) 。

[root@www ~]# passwd -x 60 -i 10 vbird2
[root@www ~]# passwd -S vbird2
vbird2 PS 2009-02-26 0 60 7 10 (Password set, MD5 crypt.)

那如果我想要让某个帐号暂时无法使用密码登入主机呢？举例来说， vbird2 这家伙最近老是胡乱在主机乱来， 所以我想要暂时让她无法登入的话，最简单的方法就是让她的密码变成不合法 (shadow 第 2 栏位长度变掉)！ 处理的方法就更简单的！

范例五：让 vbird2 的帐号失效，观察完毕后再让她失效
[root@www ~]# passwd -l vbird2
[root@www ~]# passwd -S vbird2
vbird2 LK 2009-02-26 0 60 7 10 (Password locked.)
# 嘿嘿！状态变成‘ LK, Lock ’了啦！无法登入喔！
[root@www ~]# grep vbird2 /etc/shadow
vbird2:!!$1$50MnwNFq$oChX.0TPanCq7ecE4HYEi.:14301:0:60:7:10::
# 其实只是在这里加上 !! 而已！

[root@www ~]# passwd -u vbird2
[root@www ~]# grep vbird2 /etc/shadow
vbird2:$1$50MnwNFq$oChX.0TPanCq7ecE4HYEi.:14301:0:60:7:10::
# 密码栏位恢复正常！

是否很有趣啊！您可以自行管理一下你的帐号的密码相关参数喔！接下来让我们用更简单的方法来查阅密码参数喔！

  • chage

除了使用 passwd -S 之外，有没有更详细的密码参数显示功能呢？有的！那就是 chage 了！ 他的用法如下：

[root@www ~]# chage [-ldEImMW] 帐号名
选项与参数：
-l ：列出该帐号的详细密码参数；
-d ：后面接日期，修改 shadow 第三栏位(最近一次更改密码的日期)，格式 YYYY-MM-DD
-E ：后面接日期，修改 shadow 第八栏位(帐号失效日)，格式 YYYY-MM-DD
-I ：后面接天数，修改 shadow 第七栏位(密码失效日期)
-m ：后面接天数，修改 shadow 第四栏位(密码最短保留天数)
-M ：后面接天数，修改 shadow 第五栏位(密码多久需要进行变更)
-W ：后面接天数，修改 shadow 第六栏位(密码过期前警告日期)

范例一：列出 vbird2 的详细密码参数
[root@www ~]# chage -l vbird2
Last password change                               : Feb 26, 2009
Password expires                                   : Apr 27, 2009
Password inactive                                  : May 07, 2009
Account expires                                    : never
Minimum number of days between password change     : 0
Maximum number of days between password change     : 60
Number of days of warning before password expires  : 7

我们在 passwd 的介绍中谈到了处理 vbird2 这个帐号的密码属性流程，使用 passwd -S 却无法看到很清楚的说明。如果使用 chage 那可就明白多了！如上表所示，我们可以清楚的知道 vbird2 的详细参数呢！ 如果想要修改其他的设定值，就自己参考上面的选项，或者自行 man chage 一下吧！^_^

chage 有一个功能很不错喔！如果你想要让‘使用者在第一次登入时， 强制她们一定要更改密码后才能够使用系统资源’，可以利用如下的方法来处理的！

范例二：建立一个名为 agetest 的帐号，该帐号第一次登入后使用预设密码，
        但必须要更改过密码后，使用新密码才能够登入系统使用 bash 环境
[root@www ~]# useradd agetest
[root@www ~]# echo "agetest" | passwd --stdin agetest
[root@www ~]# chage -d 0 agetest
# 此时此帐号的密码建立时间会被改为 1970/1/1 ，所以会有问题！

范例三：尝试以 agetest 登入的情况
You are required to change your password immediately (root enforced)
WARNING: Your password has expired.
You must change your password now and login again!
Changing password for user agetest.
Changing password for agetest
(current) UNIX password:  <==这个帐号被强制要求必须要改密码！

非常有趣吧！你会发现 agetest 这个帐号在第一次登入时可以使用与帐号同名的密码登入， 但登入时就会被要求立刻更改密码，更改密码完成后就会被踢出系统。再次登入时就能够使用新密码登入了！ 这个功能对学校老师非常有帮助！因为我们不想要知道学生的密码，那么在初次上课时就使用与学号相同的帐号/密码给学生， 让她们登入时自行设定她们的密码，如此一来就能够避免其他同学随意使用别人的帐号，也能够保证学生知道如何更改自己的密码！

  • usermod

所谓这‘人有失手，马有乱蹄’，您说是吧？所以啰，当然有的时候会‘不小心’在 useradd 的时候加入了错误的设定资料。或者是，在使用 useradd 后，发现某些地方还可以进行细部修改。 此时，当然我们可以直接到 /etc/passwd 或 /etc/shadow 去修改相对应栏位的资料， 不过，Linux 也有提供相关的指令让大家来进行帐号相关资料的微调呢～那就是 usermod 啰～

[root@www ~]# usermod [-cdegGlsuLU] username
选项与参数：
-c  ：后面接帐号的说明，即 /etc/passwd 第五栏的说明栏，可以加入一些帐号的说明。
-d  ：后面接帐号的家目录，即修改 /etc/passwd 的第六栏；
-e  ：后面接日期，格式是 YYYY-MM-DD 也就是在 /etc/shadow 内的第八个栏位资料啦！
-f  ：后面接天数，为 shadow 的第七栏位。
-g  ：后面接初始群组，修改 /etc/passwd 的第四个栏位，亦即是 GID 的栏位！
-G  ：后面接次要群组，修改这个使用者能够支援的群组，修改的是 /etc/group 啰～
-a  ：与 -G 合用，可‘增加次要群组的支援’而非‘设定’喔！
-l  ：后面接帐号名称。亦即是修改帐号名称， /etc/passwd 的第一栏！
-s  ：后面接 Shell 的实际档案，例如 /bin/bash 或 /bin/csh 等等。
-u  ：后面接 UID 数字啦！即 /etc/passwd 第三栏的资料；
-L  ：暂时将使用者的密码冻结，让他无法登入。其实仅改 /etc/shadow 的密码栏。
-U  ：将 /etc/shadow 密码栏的 ! 拿掉，解冻啦！

如果你仔细的比对，会发现 usermod 的选项与 useradd 非常类似！ 这是因为 usermod 也是用来微调 useradd 增加的使用者参数嘛！不过 usermod 还是有新增的选项， 那就是 -L 与 -U ，不过这两个选项其实与 passwd 的 -l, -u 是相同的！而且也不见得会存在所有的 distribution 当中！接下来，让我们谈谈一些变更参数的实例吧！

范例一：修改使用者 vbird2 的说明栏，加上‘VBird's test’的说明。
[root@www ~]# usermod -c "VBird's test" vbird2
[root@www ~]# grep vbird2 /etc/passwd
vbird2:x:700:100:VBird's test:/home/vbird2:/bin/bash

范例二：使用者 vbird2 密码在 2009/12/31 失效。
[root@www ~]# usermod -e "2009-12-31" vbird2
[root@www ~]# grep vbird2 /etc/shadow
vbird2:$1$50MnwNFq$oChX.0TPanCq7ecE4HYEi.:14301:0:60:7:10:14609:

范例三：我们建立 vbird3 这个系统帐号时并没有给予家目录，请建立他的家目录
[root@www ~]# ll -d ~vbird3
ls: /home/vbird3: No such file or directory  <==确认一下，确实没有家目录的存在！
[root@www ~]# cp -a /etc/skel /home/vbird3
[root@www ~]# chown -R vbird3:vbird3 /home/vbird3
[root@www ~]# chmod 700 /home/vbird3
[root@www ~]# ll -a ~vbird3
drwx------  4 vbird3 vbird3 4096 Sep  4 18:15 .  <==使用者家目录权限
drwxr-xr-x 11 root   root   4096 Feb 26 11:45 ..
-rw-r--r--  1 vbird3 vbird3   33 May 25  2008 .bash_logout
-rw-r--r--  1 vbird3 vbird3  176 May 25  2008 .bash_profile
-rw-r--r--  1 vbird3 vbird3  124 May 25  2008 .bashrc
drwxr-xr-x  3 vbird3 vbird3 4096 Sep  4 18:11 .kde
drwxr-xr-x  4 vbird3 vbird3 4096 Sep  4 18:15 .mozilla
# 使用 chown -R 是为了连同家目录底下的使用者/群组属性都一起变更的意思；
# 使用 chmod 没有 -R ，是因为我们仅要修改目录的权限而非内部档案的权限！

  • userdel

这个功能就太简单了，目的在删除使用者的相关资料，而使用者的资料有：

  • 使用者帐号/密码相关参数：/etc/passwd, /etc/shadow
  • 使用者群组相关参数：/etc/group, /etc/gshadow
  • 使用者个人档案资料： /home/username, /var/spool/mail/username..

整个指令的语法非常简单：

[root@www ~]# userdel [-r] username
选项与参数：
-r  ：连同使用者的家目录也一起删除

范例一：删除 vbird2 ，连同家目录一起删除
[root@www ~]# userdel -r vbird2

这个指令下达的时候要小心了！通常我们要移除一个帐号的时候，你可以手动的将 /etc/passwd 与 /etc/shadow 里头的该帐号取消即可！一般而言，如果该帐号只是‘暂时不启用’的话，那么将 /etc/shadow 里头帐号失效日期 (第八栏位) 设定为 0 就可以让该帐号无法使用，但是所有跟该帐号相关的资料都会留下来！ 使用 userdel 的时机通常是‘你真的确定不要让该用户在主机上面使用任何资料了！’

另外，其实使用者如果在系统上面操作过一阵子了，那么该使用者其实在系统内可能会含有其他档案的。 举例来说，他的邮件信箱 (mailbox) 或者是例行性工作排程 (crontab, 十六章) 之类的档案。 所以，如果想要完整的将某个帐号完整的移除，最好可以在下达 userdel -r username 之前， 先以‘ find / -user username ’查出整个系统内属于 username 的档案，然后再加以删除吧！

小标题的图示 使用者功能

不论是 useradd/usermod/userdel ，那都是系统管理员所能够使用的指令， 如果我是一般身份使用者，那么我是否除了密码之外，就无法更改其他的资料呢？ 当然不是啦！这里我们介绍几个一般身份使用者常用的帐号资料变更与查询指令啰！

  • finger

finger 的中文字面意义是：‘手指’或者是‘指纹’的意思。这个 finger 可以查阅很多使用者相关的资讯喔！ 大部分都是在 /etc/passwd 这个档案里面的资讯啦！我们就先来检查检查使用者资讯吧！

[root@www ~]# finger [-s] username
选项与参数：
-s  ：仅列出使用者的帐号、全名、终端机代号与登入时间等等；
-m  ：列出与后面接的帐号相同者，而不是利用部分比对 (包括全名部分)

范例一：观察 vbird1 的使用者相关帐号属性
[root@www ~]# finger vbird1
Login: vbird1                           Name: (null)
Directory: /home/vbird1                 Shell: /bin/bash
Never logged in.
No mail.
No Plan.

由于 finger 类似指纹的功能，他会将使用者的相关属性列出来！如上表所示，其实他列出来的几乎都是 /etc/passwd 档案里面的东西。列出的资讯说明如下：

  • Login：为使用者帐号，亦即 /etc/passwd 内的第一栏位；
  • Name：为全名，亦即 /etc/passwd 内的第五栏位(或称为注解)；
  • Directory：就是家目录了；
  • Shell：就是使用的 Shell 档案所在；
  • Never logged in.：figner 还会调查使用者登入主机的情况喔！
  • No mail.：调查 /var/spool/mail 当中的信箱资料；
  • No Plan.：调查 ~vbird1/.plan 档案，并将该档案取出来说明！

不过是否能够查阅到 Mail 与 Plan 则与权限有关了！因为 Mail / Plan 都是与使用者自己的权限设定有关， root 当然可以查阅到使用者的这些资讯，但是 vbird1 就不见得能够查到 vbird3 的资讯， 因为 /var/spool/mail/vbird3 与 /home/vbird3/ 的权限分别是 660, 700 ，那 vbird1 当然就无法查阅的到！ 这样解释可以理解吧？此外，我们可以建立自己想要执行的预定计划，当然，最多是给自己看的！可以这样做：

范例二：利用 vbird1 建立自己的计划档
[vbird1@www ~]$ echo "I will study Linux during this year." > ~/.plan
[vbird1@www ~]$ finger vbird1
Login: vbird1                           Name: (null)
Directory: /home/vbird1                 Shell: /bin/bash
Never logged in.
No mail.
Plan:
I will study Linux during this year.

范例三：找出目前在系统上面登入的使用者与登入时间
[vbird1@www ~]$ finger
Login     Name       Tty      Idle  Login Time   Office     Office Phone
root      root       tty1           Feb 26 09:53
vbird1               tty2           Feb 26 15:21

在范例三当中，我们发现输出的资讯还会有 Office, Office Phone 等资讯，那这些资讯要如何记录呢？ 底下我们会介绍 chfn 这个指令！来看看如何修改使用者的 finger 资料吧！

  • chfn

chfn 有点像是： change finger 的意思！这玩意的使用方法如下：

[root@www ~]# chfn [-foph] [帐号名]
选项与参数：
-f  ：后面接完整的大名；
-o  ：您办公室的房间号码；
-p  ：办公室的电话号码；
-h  ：家里的电话号码！

范例一：vbird1 自己更改一下自己的相关资讯！
[vbird1@www ~]$ chfn
Changing finger information for vbird1.
Password:                        <==确认身份，所以输入自己的密码
Name []: VBird Tsai test         <==输入你想要呈现的全名
Office []: Dic in Ksu. Tainan    <==办公室号码
Office Phone []: 06-2727175#356  <==办公室电话
Home Phone []: 06-1234567        <==家里电话号码

Finger information changed.
[vbird1@www ~]$ grep vbird1 /etc/passwd
vbird1:x:504:505:VBird Tsai test,Dic in Ksu. Tainan,06-2727175#356,06-1234567:
/home/vbird1:/bin/bash
# 其实就是改到第五个栏位，该栏位里面用多个‘ , ’分隔就是了！

[vbird1@www ~]$ finger vbird1
Login: vbird1                           Name: VBird Tsai test
Directory: /home/vbird1                 Shell: /bin/bash
Office: Dic in Ksu. Tainan              Office Phone: 06-2727175#356
Home Phone: 06-1234567
On since Thu Feb 26 15:21 (CST) on tty2
No mail.
Plan:
I will study Linux during this year.
# 就是上面特殊字体呈现的那些地方是由 chfn 所修改出来的！

这个指令说实在的，除非是你的主机有很多的用户，否则倒真是用不着这个程式！这就有点像是 bbs 里头更改你‘个人属性’的那一个资料啦！不过还是可以自己玩一玩！尤其是用来提醒自己相关资料啦！ ^_^

  • chsh

这就是 change shell 的简写！使用方法就更简单了！

[vbird1@www ~]$ chsh [-ls]
选项与参数：
-l  ：列出目前系统上面可用的 shell ，其实就是 /etc/shells 的内容！
-s  ：设定修改自己的 Shell 啰

范例一：用 vbird1 的身份列出系统上所有合法的 shell，并且指定 csh 为自己的 shell
[vbird1@www ~]$ chsh -l
/bin/sh
/bin/bash
/sbin/nologin  <==所谓：合法不可登入的 Shell 就是这玩意！
/bin/tcsh
/bin/csh       <==这就是 C shell 啦！
/bin/ksh
# 其实上面的资讯就是我们在 bash 中谈到的 /etc/shells 啦！

[vbird1@www ~]$ chsh -s /bin/csh; grep vbird1 /etc/passwd
Changing shell for vbird1.
Password:  <==确认身份，请输入 vbird1 的密码
Shell changed.
vbird1:x:504:505:VBird Tsai test,Dic in Ksu. Tainan,06-2727175#356,06-1234567:
/home/vbird1:/bin/csh

[vbird1@www ~]$ chsh -s /bin/bash
# 测试完毕后，立刻改回来！

[vbird1@www ~]$ ll $(which chsh)
-rws--x--x 1 root root 19128 May 25  2008 /usr/bin/chsh

不论是 chfn 与 chsh ，都是能够让一般使用者修改 /etc/passwd 这个系统档的！所以你猜猜，这两个档案的权限是什么？ 一定是 SUID 的功能啦！看到这里，想到前面！ 这就是 Linux 的学习方法～ ^_^

  • id

id 这个指令则可以查询某人或自己的相关 UID/GID 等等的资讯，他的参数也不少，不过， 都不需要记～反正使用 id 就全部都列出啰～ ^_^

[root@www ~]# id [username]

范例一：查阅 root 自己的相关 ID 资讯！
[root@www ~]# id
uid=0(root) gid=0(root) groups=0(root),1(bin),2(daemon),3(sys),4(adm),6(disk),
10(wheel) context=root:system_r:unconfined_t:SystemLow-SystemHigh
# 上面资讯其实是同一行的资料！包括会显示 UID/GID 以及支援的所有群组！
# 至于后面那个 context=... 则是 SELinux 的内容，先不要理会他！

范例二：查阅一下 vbird1 吧～
[root@www ~]# id vbird1
uid=504(vbird1) gid=505(vbird1) groups=505(vbird1) context=root:system_r:
unconfined_t:SystemLow-SystemHigh

[root@www ~]# id vbird100
id: vbird100: No such user  <== id 这个指令也可以用来判断系统上面有无某帐号！
小标题的图示 新增与移除群组

OK！了解了帐号的新增、删除、更动与查询后，再来我们可以聊一聊群组的相关内容了。 基本上，群组的内容都与这两个档案有关：/etc/group, /etc/gshadow。 群组的内容其实很简单，都是上面两个档案的新增、修改与移除而已， 不过，如果再加上有效群组的概念，那么 newgrp 与 gpasswd 则不可不知呢！

  • groupadd
[root@www ~]# groupadd [-g gid] [-r] 群组名称
选项与参数：
-g  ：后面接某个特定的 GID ，用来直接给予某个 GID ～
-r  ：建立系统群组啦！与 /etc/login.defs 内的 GID_MIN 有关。

范例一：新建一个群组，名称为 group1
[root@www ~]# groupadd group1
[root@www ~]# grep group1 /etc/group /etc/gshadow
/etc/group:group1:x:702:
/etc/gshadow:group1:!::
# 群组的 GID 也是会由 500 以上最大 GID+1 来决定！

曾经有某些版本的教育训练手册谈到，为了让使用者的 UID/GID 成对，她们建议新建的与使用者私有群组无关的其他群组时，使用小于 500 以下的 GID 为宜。 也就是说，如果要建立群组的话，最好能够使用‘ groupadd -r 群组名’的方式来建立啦！ 不过，这见仁见智啦！看你自己的抉择啰！

  • groupmod

跟 usermod 类似的，这个指令仅是在进行 group 相关参数的修改而已。

[root@www ~]# groupmod [-g gid] [-n group_name] 群组名
选项与参数：
-g  ：修改既有的 GID 数字；
-n  ：修改既有的群组名称

范例一：将刚刚上个指令建立的 group1 名称改为 mygroup ， GID 为 201
[root@www ~]# groupmod -g 201 -n mygroup group1
[root@www ~]# grep mygroup /etc/group /etc/gshadow
/etc/group:mygroup:x:201:
/etc/gshadow:mygroup:!::

不过，还是那句老话，不要随意的更动 GID ，容易造成系统资源的错乱喔！

  • groupdel

呼呼！ groupdel 自然就是在删除群组的啰～用法很简单：

[root@www ~]# groupdel [groupname]

范例一：将刚刚的 mygroup 删除！
[root@www ~]# groupdel mygroup

范例二：若要删除 vbird1 这个群组的话？
[root@www ~]# groupdel vbird1
groupdel: cannot remove user's primary group.

为什么 mygroup 可以删除，但是 vbird1 就不能删除呢？原因很简单，‘有某个帐号 (/etc/passwd) 的 initial group 使用该群组！’ 如果查阅一下，你会发现在 /etc/passwd 内的 vbird1 第四栏的 GID 就是 /etc/group 内的 vbird1 那个群组的 GID ，所以啰，当然无法删除～否则 vbird1 这个使用者登入系统后， 就会找不到 GID ，那可是会造成很大的困扰的！那么如果硬要要删除 vbird1 这个群组呢？ 你‘必须要确认 /etc/passwd 内的帐号没有任何人使用该群组作为 initial group ’才行喔！所以，你可以：

  • 修改 vbird1 的 GID ，或者是：
  • 删除 vbird1 这个使用者。

  • gpasswd：群组管理员功能

如果系统管理员太忙碌了，导致某些帐号想要加入某个专案时找不到人帮忙！这个时候可以建立‘群组管理员’喔！ 什么是群组管理员呢？就是让某个群组具有一个管理员，这个群组管理员可以管理哪些帐号可以加入/移出该群组！ 那要如何‘建立一个群组管理员’呢？就得要透过 gpasswd 啰！

# 关于系统管理员(root)做的动作：
[root@www ~]# gpasswd groupname
[root@www ~]# gpasswd [-A user1,...] [-M user3,...] groupname
[root@www ~]# gpasswd [-rR] groupname
选项与参数：
    ：若没有任何参数时，表示给予 groupname 一个密码(/etc/gshadow)
-A  ：将 groupname 的主控权交由后面的使用者管理(该群组的管理员)
-M  ：将某些帐号加入这个群组当中！
-r  ：将 groupname 的密码移除
-R  ：让 groupname 的密码栏失效

# 关于群组管理员(Group administrator)做的动作：
[someone@www ~]$ gpasswd [-ad] user groupname
选项与参数：
-a  ：将某位使用者加入到 groupname 这个群组当中！
-d  ：将某位使用者移除出 groupname 这个群组当中。

范例一：建立一个新群组，名称为 testgroup 且群组交由 vbird1 管理：
[root@www ~]# groupadd testgroup  <==先建立群组
[root@www ~]# gpasswd testgroup   <==给这个群组一个密码吧！
Changing the password for group testgroup
New Password:
Re-enter new password:
# 输入两次密码就对了！
[root@www ~]# gpasswd -A vbird1 testgroup  <==加入群组管理员为 vbird1
[root@www ~]# grep testgroup /etc/group /etc/gshadow
/etc/group:testgroup:x:702:
/etc/gshadow:testgroup:$1$I5ukIY1.$o5fmW.cOsc8.K.FHAFLWg0:vbird1:
# 很有趣吧！此时 vbird1 则拥有 testgroup 的主控权喔！身份有点像板主啦！

范例二：以 vbird1 登入系统，并且让他加入 vbird1, vbird3 成为 testgroup 成员
[vbird1@www ~]$ id
uid=504(vbird1) gid=505(vbird1) groups=505(vbird1) ....
# 看得出来，vbird1 尚未加入 testgroup 群组喔！

[vbird1@www ~]$ gpasswd -a vbird1 testgroup
[vbird1@www ~]$ gpasswd -a vbird3 testgroup
[vbird1@www ~]$ grep testgroup /etc/group
testgroup:x:702:vbird1,vbird3

很有趣的一个小实验吧！我们可以让 testgroup 成为一个可以公开的群组，然后建立起群组管理员， 群组管理员可以有多个。在这个案例中，我将 vbird1 设定为 testgroup 的群组管理员，所以 vbird1 就可以自行增加群组成员啰～呼呼！然后，该群组成员就能够使用 newgrp 啰～

小标题的图示 帐号管理实例

帐号管理不是随意建置几个帐号就算了！有时候我们需要考量到一部主机上面可能有多个帐号在协同工作！ 举例来说，在大学任教时，我们学校的专题生是需要分组的，这些同一组的同学间必须要能够互相修改对方的资料档案， 但是同时这些同学又需要保留自己的私密资料，因此直接公开家目录是不适宜的。那该如何是好？ 为此，我们底下提供几个例子来让大家思考看看啰：

任务一：单纯的完成上头交代的任务，假设我们需要的帐号资料如下，你该如何实作？

帐号名称 | 帐号全名 | 支援次要群组 | 是否可登入主机 | 密码
myuser1 | 1st user | mygroup1 | 可以 | password
myuser2 | 2nd user | mygroup1 | 可以 | password
myuser3 | 3rd user | 无额外支援 | 不可以 | password

处理的方法如下所示：

# 先处理帐号相关属性的资料：
[root@www ~]# groupadd mygroup1
[root@www ~]# useradd -G mygroup1 -c "1st user" myuser1
[root@www ~]# useradd -G mygroup1 -c "2nd user" myuser2
[root@www ~]# useradd -c "3rd user" -s /sbin/nologin myuser3

# 再处理帐号的密码相关属性的资料：
[root@www ~]# echo "password" | passwd --stdin myuser1
[root@www ~]# echo "password" | passwd --stdin myuser2
[root@www ~]# echo "password" | passwd --stdin myuser3

要注意的地方主要有：myuser1 与 myuser2 都有支援次要群组，但该群组不见得会存在，因此需要先手动建立他！ 然后 myuser3 是‘不可登入系统’的帐号，因此需要使用 /sbin/nologin 这个 shell 来给予，这样该帐号就无法登入啰！ 这样是否理解啊！接下来再来讨论比较难一些的环境！如果是专题环境该如何制作？

任务二：我的使用者 pro1, pro2, pro3 是同一个专案计划的开发人员，我想要让这三个用户在同一个目录底下工作， 但这三个用户还是拥有自己的家目录与基本的私有群组。假设我要让这个专案计划在 /srv/projecta 目录下开发， 可以如何进行？

# 1. 假设这三个帐号都尚未建立，可先建立一个名为 projecta 的群组，
#    再让这三个用户加入其次要群组的支援即可：
[root@www ~]# groupadd projecta
[root@www ~]# useradd -G projecta -c "projecta user" pro1
[root@www ~]# useradd -G projecta -c "projecta user" pro2
[root@www ~]# useradd -G projecta -c "projecta user" pro3
[root@www ~]# echo "password" | passwd --stdin pro1
[root@www ~]# echo "password" | passwd --stdin pro2
[root@www ~]# echo "password" | passwd --stdin pro3

# 2. 开始建立此专案的开发目录：
[root@www ~]# mkdir /srv/projecta
[root@www ~]# chgrp projecta /srv/projecta
[root@www ~]# chmod 2770 /srv/projecta
[root@www ~]# ll -d /srv/projecta
drwxrws--- 2 root projecta 4096 Feb 27 11:29 /srv/projecta

由于此专案计划只能够给 pro1, pro2, pro3 三个人使用，所以 /srv/projecta 的权限设定一定要正确才行！ 所以该目录群组一定是 projecta ，但是权限怎么会是 2770 呢还记得第七章谈到的 SGID 吧？为了让三个使用者能够互相修改对方的档案， 这个 SGID 是必须要存在的喔！如果连这里都能够理解，嘿嘿！您的帐号管理已经有一定程度的概念啰！ ^_^

但接下来有个困扰的问题发生了！假如任务一的 myuser1 是 projecta 这个专案的助理，他需要这个专案的内容， 但是他‘不可以修改’专案目录内的任何资料！那该如何是好？你或许可以这样做：

  • 将 myuser1 加入 projecta 这个群组的支援，但是这样会让 myuser1 具有完整的 /srv/projecta 的使用权限， myuser1 是可以删除该目录下的任何资料的！这样是有问题的；
  • 将 /srv/projecta 的权限改为 2775 ，让 myuser1 可以进入查阅资料。但此时会发生所有其他人均可进入该目录查阅的困扰！ 这也不是我们要的环境。

真要命！传统的 Linux 权限无法针对某个个人设定专属的权限吗？其实是可以啦！接下来我们就来谈谈这个功能吧！

大标题的图示 主机的细部权限规划：ACL 的使用

从第六章开始，我们就一直强调 Linux 的权限概念是非常重要的！ 但是传统的权限仅有三种身份 (owner, group, others) 搭配三种权限 (r,w,x) 而已，并没有办法单纯的针对某一个使用者或某一个群组来设定特定的权限需求，例如前一小节最后的那个任务！ 此时就得要使用 ACL 这个机制啦！这玩意挺有趣的，底下我们就来谈一谈：

小标题的图示 什么是 ACL

ACL 是 Access Control List 的缩写，主要的目的是在提供传统的 owner,group,others 的 read,write,execute 权限之外的细部权限设定。ACL 可以针对单一使用者，单一档案或目录来进行 r,w,x 的权限规范，对于需要特殊权限的使用状况非常有帮助。

那 ACL 主要可以针对哪些方面来控制权限呢？他主要可以针对几个项目：

  • 使用者 (user)：可以针对使用者来设定权限；
  • 群组 (group)：针对群组为对象来设定其权限；
  • 预设属性 (mask)：还可以针对在该目录下在建立新档案/目录时，规范新资料的预设权限；

好了，再来看看如何让你的档案系统可以支援 ACL 吧！

小标题的图示 如何启动 ACL

由于 ACL 是传统的 Unix-like 作业系统权限的额外支援项目，因此要使用 ACL 必须要有档案系统的支援才行。目前绝大部分的档案系统都有支援 ACL 的功能，包括 ReiserFS, EXT2/EXT3, JFS, XFS 等等。在我们的 CentOS 5.x 当中，预设使用 Ext3 是启动 ACL 支援的！至于察看你的档案系统是否支援 ACL 可以这样看：

[root@www ~]# mount  <==直接查阅挂载参数的功能
/dev/hda2 on / type ext3 (rw)
/dev/hda3 on /home type ext3 (rw)
# 其他项目鸟哥都将他省略了！假设我们只要看这两个装置。但没有看到 acl 喔！

[root@www ~]# dumpe2fs -h /dev/hda2  <==由 superblock 内容去查询
....(前面省略)....
Default mount options:    user_xattr acl
....(后面省略)....

由 mount 单纯去查阅不见得可以看到实际的项目，由于目前新的 distributions 常常会主动加入某些预设功能， 如上表所示，其实 CentOS 5.x 在预设的情况下 (Default mount options:) 就帮你加入 acl 的支援了！ 那如果你的系统预设不会帮你加上 acl 的支援呢？那你可以这样做：

[root@www ~]# mount -o remount,acl /
[root@www ~]# mount
/dev/hda2 on / type ext3 (rw,acl)
# 这样就加入了！但是如果想要每次开机都生效，那就这样做：

[root@www ~]# vi /etc/fstab
LABEL=/1   /   ext3    defaults,acl    1 1

如果你不确定或者是不会使用 dumpe2fs 观察你的档案系统，那么建议直接将上述的 /etc/fstab 里面的内容修改一下即可！

小标题的图示 ACL 的设定技巧： getfacl, setfacl

好了，让你的 filesystem 启动 ACL 支援后，接下来该如何设定与观察 ACL 呢？ 很简单，利用这两个指令就可以了：

  • getfacl：取得某个档案/目录的 ACL 设定项目；
  • setfacl：设定某个目录/档案的 ACL 规范。

先让我们来瞧一瞧 setfacl 如何使用吧！

  • setfacl 指令用法
[root@www ~]# setfacl [-bkRd] [{-m|-x} acl参数] 目标档名
选项与参数：
-m ：设定后续的 acl 参数给档案使用，不可与 -x 合用；
-x ：删除后续的 acl 参数，不可与 -m 合用；
-b ：移除所有的 ACL 设定参数；
-k ：移除预设的 ACL 参数，关于所谓的‘预设’参数于后续范例中介绍；
-R ：递回设定 acl ，亦即包括次目录都会被设定起来；
-d ：设定‘预设 acl 参数’的意思！只对目录有效，在该目录新建的资料会引用此预设值

上面谈到的是 acl 的选项功能，那么如何设定 ACL 的特殊权限呢？特殊权限的设定方法有很多， 我们先来谈谈最常见的，就是针对单一使用者的设定方式：

# 1. 针对特定使用者的方式：
# 设定规范：‘ u:[使用者帐号列表]:[rwx] ’，例如针对 vbird1 的权限规范 rx ：
[root@www ~]# touch acl_test1
[root@www ~]# ll acl_test1
-rw-r--r-- 1 root root 0 Feb 27 13:28 acl_test1
[root@www ~]# setfacl -m u:vbird1:rx acl_test1
[root@www ~]# ll acl_test1
-rw-r-xr--+ 1 root root 0 Feb 27 13:28 acl_test1
# 权限部分多了个 + ，且与原本的权限 (644) 看起来差异很大！但要如何查阅呢？

[root@www ~]# setfacl -m u::rwx acl_test1
[root@www ~]# ll acl_test1
-rwxr-xr--+ 1 root root 0 Feb 27 13:28 acl_test1
# 无使用者列表，代表设定该档案拥有者，所以上面显示 root 的权限成为 rwx 了！

上述动作为最简单的 ACL 设定，利用‘ u:使用者:权限 ’的方式来设定的啦！设定前请加上 -m 这个选项。 如果一个档案设定了 ACL 参数后，他的权限部分就会多出一个 + 号了！但是此时你看到的权限与实际权限可能就会有点误差！ 那要如何观察呢？就透过 getfacl 吧！

  • getfacl 指令用法
[root@www ~]# getfacl filename
选项与参数：
getfacl 的选项几乎与 setfacl 相同！所以鸟哥这里就免去了选项的说明啊！

# 请列出刚刚我们设定的 acl_test1 的权限内容：
[root@www ~]# getfacl acl_test1
# file: acl_test1   <==说明档名而已！
# owner: root       <==说明此档案的拥有者，亦即 ll 看到的第三使用者栏位
# group: root       <==此档案的所属群组，亦即 ll 看到的第四群组栏位
user::rwx           <==使用者列表栏是空的，代表档案拥有者的权限
user:vbird1:r-x     <==针对 vbird1 的权限设定为 rx ，与拥有者并不同！
group::r--          <==针对档案群组的权限设定仅有 r
mask::r-x           <==此档案预设的有效权限 (mask)
other::r--          <==其他人拥有的权限啰！

上面的资料非常容易查阅吧？显示的资料前面加上 # 的，代表这个档案的预设属性，包括档名、档案拥有者与档案所属群组。 底下出现的 user, group, mask, other 则是属于不同使用者、群组与有效权限(mask)的设定值。 以上面的结果来看，我们刚刚设定的 vbird1 对于这个档案具有 r 与 x 的权限啦！这样看的懂吗？ 如果看的懂的话，接下来让我们在测试其他类型的 setfacl 设定吧！

# 2. 针对特定群组的方式：
# 设定规范：‘ g:[群组列表]:[rwx] ’，例如针对 mygroup1 的权限规范 rx ：
[root@www ~]# setfacl -m g:mygroup1:rx acl_test1
[root@www ~]# getfacl acl_test1
# file: acl_test1
# owner: root
# group: root
user::rwx
user:vbird1:r-x
group::r--
group:mygroup1:r-x  <==这里就是新增的部分！多了这个群组的权限设定！
mask::r-x
other::r--

基本上，群组与使用者的设定并没有什么太大的差异啦！如上表所示，非常容易了解意义。不过，你应该会觉得奇怪的是， 那个 mask 是什么东西啊？其实他有点像是‘有效权限’的意思！他的意义是： 使用者或群组所设定的权限必须要存在于 mask 的权限设定范围内才会生效，此即‘有效权限 (effective permission)’ 我们举个例子来看，如下所示：

# 3. 针对有效权限 mask 的设定方式：
# 设定规范：‘ m:[rwx] ’，例如针对刚刚的档案规范为仅有 r ：
[root@www ~]# setfacl -m m:r acl_test1
[root@www ~]# getfacl acl_test1
# file: acl_test1
# owner: root
# group: root
user::rwx
user:vbird1:r-x        #effective:r-- <==vbird1+mask均存在者，仅有 r 而已！
group::r--
group:mygroup1:r-x     #effective:r--
mask::r--
other::r--

您瞧，vbird1 与 mask 的集合发现仅有 r 存在，因此 vbird1 仅具有 r 的权限而已，并不存在 x 权限！这就是 mask 的功能了！我们可以透过使用 mask 来规范最大允许的权限，就能够避免不小心开放某些权限给其他使用者或群组了。 不过，通常鸟哥都是将 mask 设定为 rwx 啦！然后再分别依据不同的使用者/群组去规范她们的权限就是了。

例题：
将前一小节任务二中 /srv/projecta 这个目录，让 myuser1 可以进入查阅，但 myuser1 不具有修改的权力。
答：
由于 myuser1 是独立的使用者与群组，而 /srv 是附属于 / 之下的，因此 /srv 已经具有 acl 的功能。 透过如下的设定即可搞定：
# 1. 先测试看看，使用 myuser1 能否进入该目录？
[myuser1@www ~]$ cd /srv/projecta
-bash: cd: /srv/projecta: Permission denied  <==确实不可进入！

# 2. 开始用 root 的身份来设定一下该目录的权限吧！
[root@www ~]# setfacl -m u:myuser1:rx /srv/projecta
[root@www ~]# getfacl /srv/projecta
# file: srv/projecta
# owner: root
# group: projecta
user::rwx
user:myuser1:r-x  <==还是要看看有没有设定成功喔！
group::rwx
mask::rwx
other::---

# 3. 还是得要使用 myuser1 去测试看看结果！
[myuser1@www ~]$ cd /srv/projecta
[myuser1@www projecta]$ ll -a
drwxrws---+ 2 root projecta 4096 Feb 27 11:29 .  <==确实可以查询档名
drwxr-xr-x  4 root root     4096 Feb 27 11:29 ..

[myuser1@www projecta]$ touch testing
touch: cannot touch `testing': Permission denied <==确实不可以写入！
请注意，上述的 1, 3 步骤使用 myuser1 的身份，2步骤才是使用 root 去设定的！

上面的设定我们就完成了之前任务二的后续需求喔！这么简单呢！接下来让我们来测试一下，如果我用 root 或者是 pro1 的身份去 /srv/projecta 增加档案或目录时，该档案或目录是否能够具有 ACL 的设定？ 意思就是说，ACL 的权限设定是否能够被次目录所‘继承？’先试看看：

[root@www ~]# cd /srv/projecta
[root@www ~]# touch abc1
[root@www ~]# mkdir abc2
[root@www ~]# ll -d abc*
-rw-r--r-- 1 root projecta    0 Feb 27 14:37 abc1
drwxr-sr-x 2 root projecta 4096 Feb 27 14:37 abc2

你可以明显的发现，权限后面都没有 + ，代表这个 acl 属性并没有继承喔！如果你想要让 acl 在目录底下的资料都有继承的功能，那就得如下这样做了！

# 4. 针对预设权限的设定方式：
# 设定规范：‘ d:[ug]:使用者列表:[rwx] ’

# 让 myuser1 在 /srv/projecta 底下一直具有 rx 的预设权限！
[root@www ~]# setfacl -m d:u:myuser1:rx /srv/projecta
[root@www ~]# getfacl /srv/projecta
# file: srv/projecta
# owner: root
# group: projecta
user::rwx
user:myuser1:r-x
group::rwx
mask::rwx
other::---
default:user::rwx
default:user:myuser1:r-x
default:group::rwx
default:mask::rwx
default:other::---

[root@www ~]# cd /srv/projecta
[root@www projecta]# touch zzz1
[root@www projecta]# mkdir zzz2
[root@www projecta]# ll -d zzz*
-rw-rw----+ 1 root projecta    0 Feb 27 14:57 zzz1
drwxrws---+ 2 root projecta 4096 Feb 27 14:57 zzz2
# 看吧！确实有继承喔！然后我们使用 getfacl 再次确认看看！

[root@www projecta]# getfacl zzz2
# file: zzz2
# owner: root
# group: projecta
user::rwx
user:myuser1:r-x
group::rwx
mask::rwx
other::---
default:user::rwx
default:user:myuser1:r-x
default:group::rwx
default:mask::rwx
default:other::---

透过这个‘针对目录来设定的预设 ACL 权限设定值’的项目，我们可以让这些属性继承到次目录底下呢！ 非常方便啊！那如果想要让 ACL 的属性全部消失又要如何处理？透过‘ setfacl -b 档名 ’即可啦！ 太简单了！鸟哥就不另外介绍了！请自行测试测试吧！

大标题的图示 使用者身份切换

什么？在 Linux 系统当中还要作身份的变换？这是为啥？可能有底下几个原因啦！

  • 使用一般帐号：系统平日操作的好习惯
    事实上，为了安全的缘故，一些老人家都会建议你，尽量以一般身份使用者来操作 Linux 的日常作业！等到需要设定系统环境时， 才变换身份成为 root 来进行系统管理，相对比较安全啦！避免作错一些严重的指令，例如恐怖的‘ rm -rf / ’(千万作不得！)

  • 用较低权限启动系统服务
    相对于系统安全，有的时候，我们必须要以某些系统帐号来进行程序的执行。 举例来说， Linux 主机上面的一套软体，名称为 apache ，我们可以额外建立一个名为 apache 的使用者来启动 apache 软体啊，如此一来，如果这个程序被攻破，至少系统还不至于就损毁了～

  • 软体本身的限制
    在远古时代的 telnet 程式中，该程式预设是不许使用 root 的身份登入的，telnet 会判断登入者的 UID， 若 UID 为 0 的话，那就直接拒绝登入了。所以，你只能使用一般使用者来登入 Linux 伺服器。 此外， ssh (注3) 也可以设定拒绝 root 登入喔！那如果你有系统设定需求该如何是好啊？就变换身份啊！

由于上述考量，所以我们都是使用一般帐号登入系统的，等有需要进行系统维护或软体更新时才转为 root 的身份来动作。 那如何让一般使用者转变身份成为 root 呢？主要有两种方式喔：

  • 以‘ su - ’直接将身份变成 root 即可，但是这个指令却需要 root 的密码，也就是说，如果你要以 su 变成 root 的话，你的一般使用者就必须要有 root 的密码才行；

  • 以‘ sudo 指令 ’执行 root 的指令串，由于 sudo 需要事先设定妥当，且 sudo 需要输入使用者自己的密码， 因此多人共管同一部主机时， sudo 要比 su 来的好喔！至少 root 密码不会流出去！

底下我们就来说一说 su 跟 sudo 的用法啦！

小标题的图示 su

su 是最简单的身份切换指令了，他可以进行任何身份的切换唷！方法如下：

[root@www ~]# su [-lm] [-c 指令] [username]
选项与参数：
-   ：单纯使用 - 如‘ su - ’代表使用 login-shell 的变数档案读取方式来登入系统；
      若使用者名称没有加上去，则代表切换为 root 的身份。
-l  ：与 - 类似，但后面需要加欲切换的使用者帐号！也是 login-shell 的方式。
-m  ：-m 与 -p 是一样的，表示‘使用目前的环境设定，而不读取新使用者的设定档’
-c  ：仅进行一次指令，所以 -c 后面可以加上指令喔！

上表的解释当中有出现之前第十一章谈过的 login-shell 设定档读取方式，如果你忘记那是啥东西， 请先回去第十一章瞧瞧再回来吧！这个 su 的用法当中，有没有加上那个减号‘ - ’差很多喔！ 因为涉及 login-shell 与 non-login shell 的变数读取方法。这里让我们以一个小例子来说明吧！

范例一：假设你原本是 vbird1 的身份，想要使用 non-login shell 的方式变成 root
[vbird1@www ~]$ su       <==注意提示字元，是 vbird1 的身份喔！
Password:                <==这里输入 root 的密码喔！
[root@www vbird1]# id    <==提示字元的目录是 vbird1 喔！
uid=0(root) gid=0(root) groups=0(root),1(bin),...   <==确实是 root 的身份！
[root@www vbird1]# env | grep 'vbird1'
USER=vbird1
PATH=/usr/local/bin:/bin:/usr/bin:/home/vbird1/bin  <==这个影响最大！
MAIL=/var/spool/mail/vbird1                         <==收到的 mailbox 是 vbird1
PWD=/home/vbird1                                    <==并非 root 的家目录
LOGNAME=vbird1
# 虽然你的 UID 已经是具有 root 的身份，但是看到上面的输出讯息吗？
# 还是有一堆变数为原本 vbird1 的身份，所以很多资料还是无法直接利用。
[root@www vbird1]# exit   <==这样可以离开 su 的环境！

单纯使用‘ su ’切换成为 root 的身份，读取的变数设定方式为 non-login shell 的方式，这种方式很多原本的变数不会被改变， 尤其是我们之前谈过很多次的 PATH 这个变数，由于没有改变成为 root 的环境 (一堆 /sbin, /usr/sbin 等目录都没有被包含进来)， 因此很多 root 惯用的指令就只能使用绝对路径来执行咯。其他的还有 MAIL 这个变数，你输入 mail 时， 收到的邮件竟然还是 vbird1 的，而不是 root 本身的邮件！是否觉得很奇怪啊！所以切换身份时，请务必使用如下的范例二：

范例二：使用 login shell 的方式切换为 root 的身份并观察变数
[vbird1@www ~]$ su -
Password:   <==这里输入 root 的密码喔！
[root@www ~]# env | grep root
USER=root
MAIL=/var/spool/mail/root
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin
PWD=/root
HOME=/root
LOGNAME=root
# 了解差异了吧？下次变换成为 root 时，记得最好使用 su - 喔！
[root@www ~]# exit   <==这样可以离开 su 的环境！

上述的作法是让使用者的身份变成 root 并开始操作系统，如果想要离开 root 的身份则得要利用 exit 离开才行。 那我如果只是想要执行‘一个只有 root 才能进行的指令，且执行完毕就恢复原本的身份’呢？那就可以加上 -c 这个选项啰！ 请参考底下范例三！

范例三：vbird1 想要执行‘ head -n 3 /etc/shadow ’一次，且已知 root 密码
[vbird1@www ~]$ head -n 3 /etc/shadow
head: cannot open `/etc/shadow' for reading: Permission denied
[vbird1@www ~]$ su - -c "head -n 3 /etc/shadow"
Password: <==这里输入 root 的密码喔！
root:$1$/30QpEWEBEZXRD0bh6rAABCEQD.BAH0:14126:0:99999:7:::
bin:*:14126:0:99999:7:::
daemon:*:14126:0:99999:7:::
[vbird1@www ~]$ <==注意看，身份还是 vbird1 喔！继续使用旧的身份进行系统操作！

由于 /etc/shadow 权限的关系，该档案仅有 root 可以查阅。为了查阅该档案，所以我们必须要使用 root 的身份工作。 但我只想要进行一次该指令而已，此时就使用类似上面的语法吧！好，那接下来，如果我是 root 或者是其他人， 想要变更成为某些特殊帐号，可以使用如下的方法来切换喔！

范例四：原本是 vbird1 这个使用者，想要变换身份成为 dmtsai 时？
[vbird1@www ~]$ su -l dmtsai
Password: <==这里输入 dmtsai 的密码喔！
[dmtsai@www ~]$ su -
Password: <==这里输入 root 的密码喔！
[root@www ~]# id sshd
uid=74(sshd) gid=74(sshd) groups=74(sshd) ... <==确实有存在此人
[root@www ~]# su -l sshd
This account is currently not available.      <==竟然说此人无法切换？
[root@www ~]# finger sshd
Login: sshd                             Name: Privilege-separated SSH
Directory: /var/empty/sshd              Shell: /sbin/nologin
[root@www ~]# exit    <==离开第二次的 su
[dmtsai@www ~]$ exit  <==离开第一次的 su
[vbird1@www ~]$ exit  <==这才是最初的环境！

su 就这样简单的介绍完毕，总结一下他的用法是这样的：

  • 若要完整的切换到新使用者的环境，必须要使用‘ su - username ’或‘ su -l username ’， 才会连同 PATH/USER/MAIL 等变数都转成新使用者的环境；

  • 如果仅想要执行一次 root 的指令，可以利用‘ su - -c "指令串" ’的方式来处理；

  • 使用 root 切换成为任何使用者时，并不需要输入新使用者的密码；

虽然使用 su 很方便啦，不过缺点是，当我的主机是多人共管的环境时，如果大家都要使用 su 来切换成为 root 的身份，那么不就每个人都得要知道 root 的密码，这样密码太多人知道可能会流出去， 很不妥当呢！怎办？透过 sudo 来处理即可！

小标题的图示 sudo

相对于 su 需要了解新切换的使用者密码 (常常是需要 root 的密码)， sudo 的执行则仅需要自己的密码即可！ 甚至可以设定不需要密码即可执行 sudo 呢！由于 sudo 可以让你以其他用户的身份执行指令 (通常是使用 root 的身份来执行指令)，因此并非所有人都能够执行 sudo ， 而是仅有规范到 /etc/sudoers 内的用户才能够执行 sudo 这个指令喔！说的这么神奇，底下就来瞧瞧那 sudo 如何使用？

  • sudo 的指令用法

由于一开始系统预设仅有 root 可以执行 sudo ，因此底下的范例我们先以 root 的身份来执行，等到谈到 visudo 时，再以一般使用者来讨论其他 sudo 的用法吧！ sudo 的语法如下：

[root@www ~]# sudo [-b] [-u 新使用者帐号]
选项与参数：
-b  ：将后续的指令放到背景中让系统自行执行，而不与目前的 shell 产生影响
-u  ：后面可以接欲切换的使用者，若无此项则代表切换身份为 root 。

范例一：你想要以 sshd 的身份在 /tmp 底下建立一个名为 mysshd 的档案
[root@www ~]# sudo -u sshd touch /tmp/mysshd
[root@www ~]# ll /tmp/mysshd
-rw-r--r-- 1 sshd sshd 0 Feb 28 17:42 /tmp/mysshd
# 特别留意，这个档案的权限是由 sshd 所建立的情况喔！

范例二：你想要以 vbird1 的身份建立 ~vbird/www 并于其中建立 index.html 档案
[root@www ~]# sudo -u vbird1 sh -c "mkdir ~vbird1/www; cd ~vbird1/www; \
>  echo 'This is index.html file' > index.html"
[root@www ~]# ll -a ~vbird1/www
drwxr-xr-x 2 vbird1 vbird1 4096 Feb 28 17:51 .
drwx------ 5 vbird1 vbird1 4096 Feb 28 17:51 ..
-rw-r--r-- 1 vbird1 vbird1   24 Feb 28 17:51 index.html
# 要注意，建立者的身份是 vbird1 ，且我们使用 sh -c "一串指令" 来执行的！

sudo 可以让你切换身份来进行某项任务，例如上面的两个范例。范例一中，我们的 root 使用 sshd 的权限去进行某项任务！ 要注意，因为我们无法使用‘ su - sshd ’去切换系统帐号 (因为系统帐号的 shell 是 /sbin/nologin)， 这个时候 sudo 真是他 X 的好用了！立刻以 sshd 的权限在 /tmp 底下建立档案！查阅一下档案权限你就了解意义啦！ 至于范例二则更使用多重指令串 (透过分号 ; 来延续指令进行)，使用 sh -c 的方法来执行一连串的指令， 如此真是好方便！

但是 sudo 预设仅有 root 能使用啊！为什么呢？因为 sudo 的执行是这样的流程：

  1. 当使用者执行 sudo 时，系统于 /etc/sudoers 档案中搜寻该使用者是否有执行 sudo 的权限；
  2. 若使用者具有可执行 sudo 的权限后，便让使用者‘输入使用者自己的密码’来确认；
  3. 若密码输入成功，便开始进行 sudo 后续接的指令(但 root 执行 sudo 时，不需要输入密码)；
  4. 若欲切换的身份与执行者身份相同，那也不需要输入密码。

所以说，sudo 执行的重点是：‘能否使用 sudo 必须要看 /etc/sudoers 的设定值， 而可使用 sudo 者是透过输入使用者自己的密码来执行后续的指令串’喔！由于能否使用与 /etc/sudoers 有关， 所以我们当然要去编辑 sudoers 档案啦！不过，因为该档案的内容是有一定的规范的，因此直接使用 vi 去编辑是不好的。 此时，我们得要透过 visudo 去修改这个档案喔！

  • visudo 与 /etc/sudoers

从上面的说明我们可以知道，除了 root 之外的其他帐号，若想要使用 sudo 执行属于 root 的权限指令，则 root 需要先使用 visudo 去修改 /etc/sudoers ，让该帐号能够使用全部或部分的 root 指令功能。为什么要使用 visudo 呢？这是因为 /etc/sudoers 是有设定语法的，如果设定错误那会造成无法使用 sudo 指令的不良后果。因此才会使用 visudo 去修改， 并在结束离开修改画面时，系统会去检验 /etc/sudoers 的语法就是了。

一般来说，visudo 的设定方式有几种简单的方法喔，底下我们以几个简单的例子来分别说明：

  1. 单一使用者可进行 root 所有指令，与 sudoers 档案语法：

    假如我们要让 vbird1 这个帐号可以使用 root 的任何指令，那么可以简单的这样进行修改即可：
    [root@www ~]# visudo
....(前面省略)....
root    ALL=(ALL)       ALL  <==找到这一行，大约在 76 行左右
vbird1  ALL=(ALL)       ALL  <==这一行是你要新增的！
....(前面省略)....
    有趣吧！其实 visudo 只是利用 vi 将 /etc/sudoers 档案呼叫出来进行修改而已，所以这个档案就是 /etc/sudoerds 啦！ 这个档案的设定其实很简单，如上面所示，如果你找到 76 行 (有 root 设定的那行) 左右，看到的资料就是：
    使用者帐号  登入者的来源主机名称=(可切换的身份)  可下达的指令
root                         ALL=(ALL)           ALL   <==这是预设值
    上面这一行的四个元件意义是：

    1. 系统的哪个帐号可以使用 sudo 这个指令的意思，预设为 root 这个帐号；
    2. 当这个帐号由哪部主机连线到本 Linux 主机，意思是这个帐号可能是由哪一部网路主机连线过来的， 这个设定值可以指定用户端电脑(信任用户的意思)。预设值 root 可来自任何一部网路主机
    3. 这个帐号可以切换成什么身份来下达后续的指令，预设 root 可以切换成任何人；
    4. 可用该身份下达什么指令？这个指令请务必使用绝对路径撰写。 预设 root 可以切换任何身份且进行任何指令之意。

    那个 ALL 是特殊的关键字，代表任何身份、主机或指令的意思。所以，我想让 vbird1 可以进行任何身份的任何指令， 就如同上表特殊字体写的那样，其实就是复制上述预设值那一行，再将 root 改成 vbird1 即可啊！ 此时‘vbird1 不论来自哪部主机登入，他可以变换身份成为任何人，且可以进行系统上面的任何指令’之意。 修改完请储存后离开 vi，并以 vbird1 登入系统后，进行如下的测试看看：
    [vbird1@www ~]$ tail -n 1 /etc/shadow  <==注意！身份是 vbird1
tail: cannot open `/etc/shadow' for reading: Permission denied
# 因为不是 root 嘛！所以当然不能查询 /etc/shadow

[vbird1@www ~]$ sudo tail -n 1 /etc/shadow <==透过 sudo

We trust you have received the usual lecture from the local System
Administrator. It usually boils down to these three things:

    #1) Respect the privacy of others.  <==这里仅是一些说明与警示项目
    #2) Think before you type.
    #3) With great power comes great responsibility.

Password: <==注意啊！这里输入的是‘ vbird1 自己的密码 ’
pro3:$1$GfinyJgZ$9J8IdrBXXMwZIauANg7tW0:14302:0:99999:7:::
# 看！vbird1 竟然可以查询 shadow ！
    注意到了吧！vbird1 输入自己的密码就能够执行 root 的指令！所以，系统管理员当然要了解 vbird1 这个用户的‘操守’才行！否则随便设定一个使用者，他恶搞系统怎办？另外，一个一个设定太麻烦了， 能不能使用群组的方式来设定呢？参考底下的方式吧。

  2. 利用群组以及免密码的功能处理 visudo

    我们在本章前面曾经建立过 pro1, pro2, pro3 ，这三个用户能否透过群组的功能让这三个人可以管理系统？ 可以的，而且很简单！同样我们使用实际案例来说明：
    [root@www ~]# visudo  <==同样的，请使用 root 先设定
....(前面省略)....
%wheel     ALL=(ALL)    ALL <==大约在 84 行左右，请将这行的 # 拿掉！
# 在最左边加上 % ，代表后面接的是一个‘群组’之意！改完请储存后离开

[root@www ~]# usermod -a -G wheel pro1 <==将 pro1 加入 wheel 的支援
    上面的设定值会造成‘任何加入 wheel 这个群组的使用者，就能够使用 sudo 切换任何身份来操作任何指令’的意思。 你当然可以将 wheel 换成你自己想要的群组名。接下来，请分别切换身份成为 pro1 及 pro2 试看看 sudo 的运作。
    [pro1@www ~]$ sudo tail -n 1 /etc/shadow <==注意身份是 pro1
....(前面省略)....
Password:  <==输入 pro1 的密码喔！
pro3:$1$GfinyJgZ$9J8IdrBXXMwZIauANg7tW0:14302:0:99999:7:::

[pro2@www ~]$ sudo tail -n 1 /etc/shadow <==注意身份是 pro2
Password:
pro2 is not in the sudoers file.  This incident will be reported.
# 仔细看错误讯息他是说这个 pro2 不在 /etc/sudoers 的设定中！
    这样理解群组了吧？如果你想要让 pro3 也支援这个 sudo 的话，不需要重新使用 visudo ，只要利用 usermod 去修改 pro3 的群组支援，让 wheel 也支援 pro3 的话，那他就能够进行 sudo 啰！ 简单吧！不过，既然我们都信任这些 sudo 的用户了，能否提供‘不需要密码即可使用 sudo ’呢？ 就透过如下的方式：
    [root@www ~]# visudo  <==同样的，请使用 root 先设定
....(前面省略)....
%wheel     ALL=(ALL)   NOPASSWD: ALL <==大约在 87 行左右，请将 # 拿掉！
# 在最左边加上 % ，代表后面接的是一个‘群组’之意！改完请储存后离开
    重点是那个 NOPASSWD 啦！该关键字是免除密码输入的意思喔！

  3. 有限制的指令操作：

    上面两点都会让使用者能够利用 root 的身份进行任何事情！这样总是不太好～如果我想要让使用者仅能够进行部分系统任务， 比方说，系统上面的 myuser1 仅能够帮 root 修改其他使用者的密码时，亦即‘当使用者仅能使用 passwd 这个指令帮忙 root 修改其他用户的密码’时，你该如何撰写呢？可以这样做：
    [root@www ~]# visudo  <==注意是 root 身份
myuser1	ALL=(root)  /usr/bin/passwd  <==最后指令务必用绝对路径
    上面的设定值指的是‘myuser1 可以切换成为 root 使用 passwd 这个指令’的意思。其中要注意的是： 指令栏位必须要填写绝对路径才行！否则 visudo 会出现语法错误的状况发生！ 此外，上面的设定是有问题的！我们使用底下的指令操作来让您了解：
    [myuser1@www ~]$ sudo passwd myuser3  <==注意，身份是 myuser1
Password:  <==输入 myuser1 的密码
Changing password for user myuser3. <==底下改的是 myuser3 的密码喔！这样是正确的
New UNIX password:
Retype new UNIX password:
passwd: all authentication tokens updated successfully.

[myuser1@www ~]$ sudo passwd
Changing password for user root.  <==见鬼！怎么会去改 root 的密码？
    恐怖啊！我们竟然让 root 的密码被 myuser3 给改变了！下次 root 回来竟无法登入系统...欲哭无泪～怎办？ 所以我们必须要限制使用者的指令参数！修改的方法为将上述的那行改一改先：
    [root@www ~]# visudo  <==注意是 root 身份
myuser1	ALL=(root)  !/usr/bin/passwd, /usr/bin/passwd [A-Za-z]*, \
                    !/usr/bin/passwd root
    由于荧幕一行写不完，我将这行写成两行，所以上面第一行最后加上反斜线啰。加上惊叹号‘ ! ’代表‘不可执行’的意思。 因此上面这一行会变成：可以执行‘ passwd 任意字元’，但是‘ passwd ’与‘ passwd root ’这两个指令例外！ 如此一来 myuser1 就无法改变 root 的密码了！这样这位使用者可以具有 root 的能力帮助你修改其他用户的密码， 而且也不能随意改变 root 的密码！很有用处的！

  4. 透过别名建置 visudo：

    如上述第三点，如果我有 15 个用户需要加入刚刚的管理员行列，那么我是否要将上述那长长的设定写入 15 行啊？ 而且如果想要修改命令或者是新增命令时，那我每行都需要重新设定，很麻烦ㄟ！有没有更简单的方式？ 是有的！透过别名即可！我们 visudo 的别名可以是‘指令别名、帐号别名、主机别名’等。不过这里我们仅介绍帐号别名， 其他的设定值有兴趣的话，可以自行玩玩！

    假设我的 pro1, pro2, pro3 与 myuser1, myuser2 要加入上述的密码管理员的 sudo 列表中， 那我可以创立一个帐号别名称为 ADMPW 的名称，然后将这个名称处理一下即可。处理的方式如下：
    [root@www ~]# visudo  <==注意是 root 身份
User_Alias ADMPW = pro1, pro2, pro3, myuser1, myuser2
Cmnd_Alias ADMPWCOM = !/usr/bin/passwd, /usr/bin/passwd [A-Za-z]*, \
                      !/usr/bin/passwd root
ADMPW   ALL=(root)  ADMPWCOM
    我透过 User_Alias 建立出一个新帐号，这个帐号名称一定要使用大写字元来处理，包括 Cmnd_Alias(命令别名)、Host_Alias(来源主机名称别名) 都需要使用大写字元的！这个 ADMPW 代表后面接的那些实际帐号。 而该帐号能够进行的指令就如同 ADMPWCOM 后面所指定的那样！上表最后一行则写入这两个别名 (帐号与指令别名)， 未来要修改时，我只要修改 User_Alias 以及 Cmnd_Alias 这两行即可！设定方面会比较简单有弹性喔！

  5. sudo 的时间间隔问题：

    或许您已经发现了，那就是，如果我使用同一个帐号在短时间内重复操作 sudo 来运作指令的话， 在第二次执行 sudo 时，并不需要输入自己的密码！sudo 还是会正确的运作喔！为什么呢？ 第一次执行 sudo 需要输入密码，是担心由于使用者暂时离开座位，但有人跑来你的座位使用你的帐号操作系统之故。 所以需要你输入一次密码重新确认一次身份。

    两次执行 sudo 的间隔在五分钟内，那么再次执行 sudo 时就不需要再次输入密码了， 这是因为系统相信你在五分钟内不会离开你的作业，所以执行 sudo 的是同一个人！呼呼！真是很人性化的设计啊～ ^_^。不过如果两次 sudo 操作的间隔超过 5 分钟，那就得要重新输入一次你的密码了 (注4)

    另外要注意的是，因为使用一般帐号时，理论上不会使用到 /sbin, /usr/sbin 等目录内的指令，所以 $PATH 变数不会含有这些目录，因此很多管理指令需要使用绝对路径来下达比较妥当喔！

  6. sudo 搭配 su 的使用方式：

    很多时候我们需要大量执行很多 root 的工作，所以一直使用 sudo 觉得很烦ㄟ！那有没有办法使用 sudo 搭配 su ， 一口气将身份转为 root ，而且还用使用者自己的密码来变成 root 呢？是有的！而且方法简单的会让你想笑！ 我们建立一个 ADMINS 帐号别名，然后这样做：
    [root@www ~]# visudo
User_Alias  ADMINS = pro1, pro2, pro3, myuser1
ADMINS ALL=(root)  /bin/su -
    接下来，上述的 pro1, pro2, pro3, myuser1 这四个人，只要输入‘ sudo su - ’并且输入‘自己的密码’后， 立刻变成 root 的身份！不但 root 密码不会外流，使用者的管理也变的非常方便！ 这也是实务上面多人共管一部主机时常常使用的技巧呢！这样管理确实方便，不过还是要强调一下大前提， 那就是‘这些你加入的使用者，全部都是你能够信任的用户’！
大标题的图示 使用者的特殊 shell 与 PAM 模组

我们前面一直谈到的大多是一般身份使用者与系统管理员 (root) 的相关操作， 而且大多是讨论关于可登入系统的帐号来说。那么换个角度想，如果我今天想要建立的， 是一个‘仅能使用 mail server 相关邮件服务的帐号，而该帐号并不能登入 Linux 主机’呢？如果不能给予该帐号一个密码，那么该帐号就无法使用系统的各项资源，当然也包括 mail 的资源， 而如果给予一个密码，那么该帐号就可能可以登入 Linux 主机啊！呵呵～伤脑筋吧～ 所以，底下让我们来谈一谈这些有趣的话题啰！

另外，在本章之前谈到过 /etc/login.defs 档案中，关于密码长度应该预设是 5 个字串长度，但是我们上面也谈到，该设定值已经被 PAM 模组所取代了，那么 PAM 是什么？为什么他可以影响我们使用者的登入呢？这里也要来谈谈的！

小标题的图示 特殊的 shell, /sbin/nologin

在本章一开头的 passwd 档案结构里面我们就谈过系统帐号这玩意儿，这玩意儿的 shell 就是使用 /sbin/nologin ，重点在于系统帐号是不需要登入的！所以我们就给他这个无法登入的合法 shell。 使用了这个 shell 的用户即使有了密码，你想要登入时他也无法登入，因为会出现如下的讯息喔：

This account is currently not available.

我们所谓的‘无法登入’指的仅是：‘这个使用者无法使用 bash 或其他 shell 来登入系统’而已， 并不是说这个帐号就无法使用其他的系统资源喔！ 举例来说，各个系统帐号，列印工作由 lp 这个帐号在管理， WWW 服务由 apache 这个帐号在管理， 他们都可以进行系统程序的工作，但是‘就是无法登入主机’而已啦！^_^

换个角度来想，如果我的 Linux 主机提供的是邮件服务，所以说，在这部 Linux 主机上面的帐号， 其实大部分都是用来收受主机的信件而已，并不需要登入主机的呢！ 这个时候，我们就可以考虑让单纯使用 mail 的帐号以 /sbin/nologin 做为他们的 shell ， 这样，最起码当我的主机被尝试想要登入系统以取得 shell 环境时，可以拒绝该帐号呢！

另外，如果我想要让某个具有 /sbin/nologin 的使用者知道，他们不能登入主机时， 其实我可以建立‘ /etc/nologin.txt ’这个档案， 并且在这个档案内说明不能登入的原因，那么下次当这个使用者想要登入系统时， 荧幕上出现的就会是 /etc/nologin.txt 这个档案的内容，而不是预设的内容了！

例题：
当使用者尝试利用纯 mail 帐号 (例如 myuser3) 时，利用 /etc/nologin.txt 告知使用者不要利用该帐号登入系统。
答：
直接以 vi 编辑该档案，内容可以是这样：
[root@www ~]# vi /etc/nologin.txt
This account is system account or mail account.
Please DO NOT use this account to login my Linux server.
想要测试时，可以使用 myuser3 (此帐号的 shell 是 /sbin/nologin) 来测试看看！
[root@www ~]# su - myuser3
This account is system account or mail account.
Please DO NOT use this account to login my Linux server.
[root@www ~]#
结果会发现与原本的预设讯息不一样喔！ ^_^

小标题的图示 PAM 模组简介

在过去，我们想要对一个使用者进行认证 (authentication)，得要要求使用者输入帐号密码， 然后透过自行撰写的程式来判断该帐号密码是否正确。也因为如此，我们常常得使用不同的机制来判断帐号密码， 所以搞的一部主机上面拥有多个各别的认证系统，也造成帐号密码可能不同步的验证问题！ 为了解决这个问题因此有了 PAM (Pluggable Authentication Modules, 嵌入式模组) 的机制！

PAM 可以说是一套应用程式介面 (Application Programming Interface, API)，他提供了一连串的验证机制，只要使用者将验证阶段的需求告知 PAM 后， PAM 就能够回报使用者验证的结果 (成功或失败)。由于 PAM 仅是一套验证的机制，又可以提供给其他程式所呼叫引用，因此不论你使用什么程式，都可以使用 PAM 来进行验证，如此一来，就能够让帐号密码或者是其他方式的验证具有一致的结果！也让程式设计师方便处理验证的问题喔！ (注5)

PAM 模组与其他程式的相关性
图 5.2.1、 PAM 模组与其他程式的相关性

如上述的图示， PAM 是一个独立的 API 存在，只要任何程式有需求时，可以向 PAM 发出验证要求的通知， PAM 经过一连串的验证后，将验证的结果回报给该程式，然后该程式就能够利用验证的结果来进行可登入或显示其他无法使用的讯息。 这也就是说，你可以在写程式的时候将 PAM 模组的功能加入，就能够利用 PAM 的验证功能啰。 因此目前很多程式都会利用 PAM 喔！所以我们才要来学习他啊！

PAM 用来进行验证的资料称为模组 (Modules)，每个 PAM 模组的功能都不太相同。举例来说， 还记得我们在本章使用 passwd 指令时，如果随便输入字典上面找的到的字串， passwd 就会回报错误资讯了！这是为什么呢？这就是 PAM 的 pam_cracklib.so 模组的功能！他能够判断该密码是否在字典里面！ 并回报给密码修改程式，此时就能够了解你的密码强度了。

所以，当你有任何需要判断是否在字典当中的密码字串时，就可以使用 pam_cracklib.so 这个模组来验证！ 并根据验证的回报结果来撰写你的程式呢！这样说，可以理解 PAM 的功能了吧？没错！ PAM 的模组也是很重要的一环！

小标题的图示 PAM 模组设定语法

PAM 藉由一个与程式相同档名的设定档来进行一连串的认证分析需求。我们同样以 passwd 这个指令的呼叫 PAM 来说明好了。 当你执行 passwd 后，这支程式呼叫 PAM 的流程是：

  1. 使用者开始执行 /usr/bin/passwd 这支程式，并输入密码；
  2. passwd 呼叫 PAM 模组进行验证；
  3. PAM 模组会到 /etc/pam.d/ 找寻与程式 (passwd) 同名的设定档；
  4. 依据 /etc/pam.d/passwd 内的设定，引用相关的 PAM 模组逐步进行验证分析；
  5. 将验证结果 (成功、失败以及其他讯息) 回传给 passwd 这支程式；
  6. passwd 这支程式会根据 PAM 回传的结果决定下一个动作 (重新输入新密码或者通过验证！)

从上头的说明，我们会知道重点其实是 /etc/pam.d/ 里面的设定档，以及设定档所呼叫的 PAM 模组进行的验证工作！ 既然一直谈到 passwd 这个密码修改指令，那我们就来看看 /etc/pam.d/passwd 这个设定档的内容是怎样吧！

[root@www ~]# cat /etc/pam.d/passwd
#%PAM-1.0  <==PAM版本的说明而已！
auth       include      system-auth <==每一行都是一个验证的过程
account    include      system-auth
password   include      system-auth
验证类别   控制标准     PAM 模组与该模组的参数

在这个设定档当中，除了第一行宣告 PAM 版本之外，其他任何‘ # ’开头的都是注解，而每一行都是一个独立的验证流程， 每一行可以区分为三个栏位，分别是验证类别(type)、控制标准(flag)、PAM的模组与该模组的参数。 底下我们先来谈谈验证类别与控制标准这两项资料吧！

Tips:
你会发现在我们上面的表格当中出现的是‘ include (包括) ’这个关键字，他代表的是‘请呼叫后面的档案来作为这个类别的验证’， 所以，上述的每一行都要重复呼叫 /etc/pam.d/system-auth 那个档案来进行验证的意思！ 		鸟哥的图示
  • 第一个栏位：验证类别 (Type)

验证类别主要分为四种，分别说明如下：

  • auth
    是 authentication (认证) 的缩写，所以这种类别主要用来检验使用者的身份验证，这种类别通常是需要密码来检验的， 所以后续接的模组是用来检验使用者的身份。

  • account
    account (帐号) 则大部分是在进行 authorization (授权)，这种类别则主要在检验使用者是否具有正确的使用权限， 举例来说，当你使用一个过期的密码来登入时，当然就无法正确的登入了。

  • session
    session 是会议期间的意思，所以 session 管理的就是使用者在这次登入 (或使用这个指令) 期间，PAM 所给予的环境设定。 这个类别通常用在记录使用者登入与登出时的资讯！例如，如果你常常使用 su 或者是 sudo 指令的话， 那么应该可以在 /var/log/secure 里面发现很多关于 pam 的说明，而且记载的资料是‘session open, session close’的资讯！

  • password
    password 就是密码嘛！所以这种类别主要在提供验证的修订工作，举例来说，就是修改/变更密码啦！

这四个验证的类型通常是有顺序的，不过也有例外就是了。 会有顺序的原因是，(1)我们总是得要先验证身份 (auth) 后， (2)系统才能够藉由使用者的身份给予适当的授权与权限设定 (account)，而且(3)登入与登出期间的环境才需要设定， 也才需要记录登入与登出的资讯 (session)。如果在运作期间需要密码修订时，(4)才给予 password 的类别。这样说起来， 自然是需要有点顺序吧！

  • 第二个栏位：验证的控制旗标 (control flag)

那么‘验证的控制旗标(control flag)’又是什么？简单的说，他就是‘验证通过的标准’啦！ 这个栏位在管控该验证的放行方式，主要也分为四种控制方式：

  • required
    此验证若成功则带有 success (成功) 的标志，若失败则带有 failure 的标志，但不论成功或失败都会继续后续的验证流程。 由于后续的验证流程可以继续进行，因此相当有利于资料的登录 (log) ，这也是 PAM 最常使用 required 的原因。

  • requisite
    若验证失败则立刻回报原程式 failure 的标志，并终止后续的验证流程。若验证成功则带有 success 的标志并继续后续的验证流程。 这个项目与 required 最大的差异，就在于失败的时候还要不要继续验证下去？由于 requisite 是失败就终止， 因此失败时所产生的 PAM 资讯就无法透过后续的模组来记录了。

  • sufficient
    若验证成功则立刻回传 success 给原程式，并终止后续的验证流程；若验证失败则带有 failure 标志并继续后续的验证流程。 这玩意儿与 requisits 刚好相反！

  • optional
    这个模组控制项目大多是在显示讯息而已，并不是用在验证方面的。

如果将这些控制旗标以图示的方式配合成功与否的条件绘图，会有点像底下这样：

PAM 控制旗标所造成的回报流程
图 5.3.1、 PAM 控制旗标所造成的回报流程

程式运作过程中遇到验证时才会去呼叫 PAM ，而 PAM 验证又分很多类型与控制，不同的控制旗标所回报的讯息并不相同。 如上图所示， requisite 失败就回报了并不会继续，而 sufficient 则是成功就回报了也不会继续。 至于验证结束后所回报的资讯通常是‘succes 或 failure ’而已，后续的流程还需要该程式的判断来继续执行才行。

小标题的图示 常用模组简介

谈完了设定档的语法后，现在让我们来查阅一下 CentOS 5.x 提供的 PAM 预设档案的内容是啥吧！ 由于我们常常需要透过各种方式登入 (login) 系统，因此就来看看登入所需要的 PAM 流程为何：

[root@www ~]# cat /etc/pam.d/login
#%PAM-1.0
auth [user_unknown=ignore success=ok ignore=ignore default=bad] pam_securetty.so
auth       include      system-auth
account    required     pam_nologin.so
account    include      system-auth
password   include      system-auth
# pam_selinux.so close should be the first session rule
session    required     pam_selinux.so close
session    include      system-auth
session    required     pam_loginuid.so
session    optional     pam_console.so
# pam_selinux.so open should only be followed by sessions...
session    required     pam_selinux.so open
session    optional     pam_keyinit.so force revoke
# 我们可以看到，其实 login 也呼叫多次的 system-auth ，所以底下列出该设定档

[root@www ~]# cat /etc/pam.d/system-auth
#%PAM-1.0
# This file is auto-generated.
# User changes will be destroyed the next time authconfig is run.
auth     required     pam_env.so
auth     sufficient   pam_unix.so nullok try_first_pass
auth     requisite    pam_succeed_if.so uid >= 500 quiet
auth     required     pam_deny.so

account  required     pam_unix.so
account  sufficient   pam_succeed_if.so uid < 500 quiet
account  required     pam_permit.so

password requisite    pam_cracklib.so try_first_pass retry=3
password sufficient   pam_unix.so md5 shadow nullok try_first_pass use_authtok
password required     pam_deny.so

session  optional     pam_keyinit.so revoke
session  required     pam_limits.so
session  [success=1 default=ignore] pam_succeed_if.so service in crond quiet \
                      use_uid
session  required     pam_unix.so

上面这个表格当中使用到非常多的 PAM 模组，每个模组的功能都不太相同，详细的模组情报可以在你的系统中找到：

  • /etc/pam.d/*：每个程式个别的 PAM 设定档；
  • /lib/security/*：PAM 模组档案的实际放置目录；
  • /etc/security/*：其他 PAM 环境的设定档；
  • /usr/share/doc/pam-*/：详细的 PAM 说明文件。

例如鸟哥使用未 update 过的 CentOS 5.2 ，pam_nologin 说明文件档在： /usr/share/doc/pam-0.99.6.2/txts/README.pam_nologin。你可以自行查阅一下该模组的功能。 鸟哥这里仅简单介绍几个较常使用的模组，详细的资讯还得要您努力查阅参考书呢！ ^_^

  • pam_securetty.so：
    限制系统管理员 (root) 只能够从安全的 (secure) 终端机登入；那什么是终端机？例如 tty1, tty2 等就是传统的终端机装置名称。那么安全的终端机设定呢？ 就写在 /etc/securetty 这个档案中。你可以查阅一下该档案， 就知道为什么 root 可以从 tty1~tty7 登入，但却无法透过 telnet 登入 Linux 主机了！

  • pam_nologin.so：
    这个模组可以限制一般使用者是否能够登入主机之用。当 /etc/nologin 这个档案存在时，则所有一般使用者均无法再登入系统了！若 /etc/nologin 存在，则一般使用者在登入时， 在他们的终端机上会将该档案的内容显示出来！所以，正常的情况下，这个档案应该是不能存在系统中的。 但这个模组对 root 以及已经登入系统中的一般帐号并没有影响。

  • pam_selinux.so：
    SELinux 是个针对程序来进行细部管理权限的功能，SELinux 这玩意儿我们会在第十七章的时候再来详细谈论。由于 SELinux 会影响到使用者执行程式的权限，因此我们利用 PAM 模组，将 SELinux 暂时关闭，等到验证通过后， 再予以启动！

  • pam_console.so：
    当系统出现某些问题，或者是某些时刻你需要使用特殊的终端介面 (例如 RS232 之类的终端连线设备) 登入主机时， 这个模组可以帮助处理一些档案权限的问题，让使用者可以透过特殊终端介面 (console) 顺利的登入系统。

  • pam_loginuid.so：
    我们知道系统帐号与一般帐号的 UID 是不同的！一般帐号 UID 均大于 500 才合理。 因此，为了验证使用者的 UID 真的是我们所需要的数值，可以使用这个模组来进行规范！

  • pam_env.so：
    用来设定环境变数的一个模组，如果你有需要额外的环境变数设定，可以参考 /etc/security/pam_env.conf 这个档案的详细说明。

  • pam_unix.so：
    这是个很复杂且重要的模组，这个模组可以用在验证阶段的认证功能，可以用在授权阶段的帐号授权管理， 可以用在会议阶段的登录档记录等，甚至也可以用在密码更新阶段的检验！非常丰富的功能！ 这个模组在早期使用得相当频繁喔！

  • pam_cracklib.so：
    可以用来检验密码的强度！包括密码是否在字典中，密码输入几次都失败就断掉此次连线等功能，都是这模组提供的！ 这玩意儿很重要！

  • pam_limits.so：
    还记得我们在十一章谈到的 ulimit 吗？ 其实那就是这个模组提供的能力！还有更多细部的设定可以参考： /etc/security/limits.conf 内的说明。

了解了这些模组的大致功能后，言归正传，讨论一下 login 的 PAM 验证机制流程是这样的：

  1. 验证阶段 (auth)：首先，(a)会先经过 pam_securetty.so 判断，如果使用者是 root 时，则会参考 /etc/securetty 的设定； 接下来(b)经过 pam_env.so 设定额外的环境变数；再(c)透过 pam_unix.so 检验密码，若通过则回报 login 程式；若不通过则(d)继续往下以 pam_succeed_if.so 判断 UID 是否大于 500 ，若小于 500则回报失败，否则再往下 (e)以 pam_deny.so 拒绝连线。

  2. 授权阶段 (account)：(a)先以 pam_nologin.so 判断 /etc/nologin 是否存在，若存在则不许一般使用者登入； (b)接下来以 pam_unix 进行帐号管理，再以 (c) pam_succeed_if.so 判断 UID 是否小于 500 ，若小于 500 则不记录登录资讯。(d)最后以 pam_permit.so 允许该帐号登入。

  3. 密码阶段 (password)：(a)先以 pam_cracklib.so 设定密码仅能尝试错误 3 次；(b)接下来以 pam_unix.so 透过 md5, shadow 等功能进行密码检验，若通过则回报 login 程式，若不通过则 (c)以 pam_deny.so 拒绝登入。

  4. 会议阶段 (session)：(a)先以 pam_selinux.so 暂时关闭 SELinux；(b)使用 pam_limits.so 设定好使用者能够操作的系统资源； (c)登入成功后开始记录相关资讯在登录档中； (d)以 pam_loginuid.so 规范不同的 UID 权限；(e)开启 pam_selinux.so 的功能。

总之，就是依据验证类别 (type) 来看，然后先由 login 的设定值去查阅，如果出现‘ include system-auth ’ 就转到 system-auth 档案中的相同类别，去取得额外的验证流程就是了。然后再到下一个验证类别，最终将所有的验证跑完！ 就结束这次的 PAM 验证啦！

经过这样的验证流程，现在你知道为啥 /etc/nologin 存在会有问题，也会知道为何你使用一些远端连线机制时， 老是无法使用 root 登入的问题了吧？没错！这都是 PAM 模组提供的功能啦！

例题：
为什么 root 无法以 telnet 直接登入系统，但是却能够使用 ssh 直接登入？
答：
一般来说， telnet 会引用 login 的 PAM 模组，而 login 的验证阶段会有 /etc/securetty 的限制！ 由于远端连线属于 pts/n (n 为数字) 的动态终端机介面装置名称，并没有写入到 /etc/securetty ， 因此 root 无法以 telnet 登入远端主机。至于 ssh 使用的是 /etc/pam.d/sshd 这个模组， 你可以查阅一下该模组，由于该模组的验证阶段并没有加入 pam_securetty ，因此就没有 /etc/securetty 的限制！故可以从远端直接连线到伺服器端。

另外，关于 telnet 与 ssh 的细部说明，请参考鸟哥的 Linux 私房菜伺服器篇

小标题的图示 其他相关档案

除了前一小节谈到的 /etc/securetty 会影响到 root 可登入的安全终端机， /etc/nologin 会影响到一般使用者是否能够登入的功能之外，我们也知道 PAM 相关的设定档在 /etc/pam.d ， 说明文件在 /usr/share/doc/pam-(版本) ，模组实际在 /lib/security/ 。那么还有没有相关的 PAM 档案呢？ 是有的，主要都在 /etc/security 这个目录内！我们底下介绍几个可能会用到的设定档喔！

  • limits.conf

我们在第十一章谈到的 ulimit 功能中， 除了修改使用者的 ~/.bashrc 设定档之外，其实系统管理员可以统一藉由 PAM 来管理的！ 那就是 /etc/security/limits.conf 这个档案的设定了。这个档案的设定很简单，你可以自行参考一下该档案内容。 我们这里仅作个简单的介绍：

范例一：vbird1 这个用户只能建立 100MB 的档案，且大于 90MB 会警告
[root@www ~]# vi /etc/security/limits.conf
vbird1	soft		fsize		 90000
vbird1	hard		fsize		100000
#帐号   限制依据	限制项目 	限制值
# 第一栏位为帐号，或者是群组！若为群组则前面需要加上 @ ，例如 @projecta
# 第二栏位为限制的依据，是严格(hard)，还是仅为警告(soft)；
# 第三栏位为相关限制，此例中限制档案容量，
# 第四栏位为限制的值，在此例中单位为 KB。
# 若以 vbird1 登入后，进行如下的操作则会有相关的限制出现！

[vbird1@www ~]$ ulimit -a
....(前面省略)....
file size               (blocks, -f) 90000
....(后面省略)....

[vbird1@www ~]$ dd if=/dev/zero of=test bs=1M count=110
File size limit exceeded
[vbird1@www ~]$ ll -k test
-rw-rw-r-- 1 vbird1 vbird1 90000 Mar  4 11:30 test
# 果然有限制到了

范例二：限制 pro1 这个群组，每次仅能有一个使用者登入系统 (maxlogins)
[root@www ~]# vi /etc/security/limits.conf
@pro1   hard   maxlogins   1
# 如果要使用群组功能的话，这个功能似乎对初始群组才有效喔！
# 而如果你尝试多个 pro1 的登入时，第二个以后就无法登入了。
# 而且在 /var/log/secure 档案中还会出现如下的资讯：
# pam_limits(login:session): Too many logins (max 1) for pro1

这个档案挺有趣的，而且是设定完成就生效了，你不用重新启动任何服务的！ 但是 PAM 有个特殊的地方，由于他是在程式呼叫时才予以设定的，因此你修改完成的资料， 对于已登入系统中的使用者是没有效果的，要等他再次登入时才会生效喔！另外， 上述的设定请在测试完成后立刻注解掉，否则下次这两个使用者登入就会发生些许问题啦！ ^_^

  • /var/log/secure, /var/log/messages

如果发生任何无法登入或者是产生一些你无法预期的错误时，由于 PAM 模组都会将资料记载在 /var/log/secure 当中，所以发生了问题请务必到该档案内去查询一下问题点！举例来说， 我们在 limits.conf 的介绍内的范例二，就有谈到多重登入的错误可以到 /var/log/secure 内查阅了！ 这样你也就知道为何第二个 pro1 无法登入啦！^_^

大标题的图示 Linux 主机上的使用者讯息传递

谈了这么多的帐号问题，总是该要谈一谈，那么如何针对系统上面的使用者进行查询吧？ 想几个状态，如果你在 Linux 上面操作时，刚好有其他的使用者也登入主机，你想要跟他对谈，该如何是好？ 你想要知道某个帐号的相关资讯，该如何查阅？呼呼！底下我们就来聊一聊～

小标题的图示 查询使用者： w, who, last, lastlog

如何查询一个使用者的相关资料呢？这还不简单，我们之前就提过了 id, finger 等指令了，都可以让您了解到一个使用者的相关资讯啦！那么想要知道使用者到底啥时候登入呢？ 最简单可以使用 last 检查啊！这个玩意儿我们也在 第十一章 bash 提过了， 您可以自行前往参考啊！简单的很。

Tips:
早期的 Red Hat 系统的版本中， last 仅会列出当月的登入者资讯，不过在我们的 CentOS 5.x 版以后， last 可以列出从系统建立之后到目前为止的所有登入者资讯！这是因为登录档轮替的设定不同所致。 详细的说明可以参考后续的第十九章登录档简介。 		鸟哥的图示

那如果你想要知道目前已登入在系统上面的使用者呢？可以透过 w 或 who 来查询喔！如下范例所示：

[root@www ~]# w
 13:13:56 up 13:00,  1 user,  load average: 0.08, 0.02, 0.01
USER   TTY    FROM            LOGIN@   IDLE   JCPU   PCPU WHAT
root   pts/1  192.168.1.100   11:04    0.00s  0.36s  0.00s -bash
vbird1 pts/2  192.168.1.100   13:15    0.00s  0.06s  0.02s w
# 第一行显示目前的时间、开机 (up) 多久，几个使用者在系统上平均负载等；
# 第二行只是各个项目的说明，
# 第三行以后，每行代表一个使用者。如上所示，root 登入并取得终端机名 pts/1 之意。

[root@www ~]# who
root     pts/1        2009-03-04 11:04 (192.168.1.100)
vbird1   pts/2        2009-03-04 13:15 (192.168.1.100)

另外，如果您想要知道每个帐号的最近登入的时间，则可以使用 lastlog 这个指令喔！ lastlog 会去读取 /var/log/lastlog 档案，结果将资料输出如下表：

[root@www ~]# lastlog
Username    Port   From           Latest
root        pts/1  192.168.1.100  Wed Mar  4 11:04:22 +0800 2009
bin                                        **Never logged in**
....(中间省略)....
vbird1      pts/2  192.168.1.100  Wed Mar  4 13:15:56 +0800 2009
....(以下省略)....

这样就能够知道每个帐号的最近登入的时间啰～ ^_^

小标题的图示 使用者对谈： write, mesg, wall

那么我是否可以跟系统上面的使用者谈天说地呢？当然可以啦！利用 write 这个指令即可。 write 可以直接将讯息传给接收者啰！举例来说，我们的 Linux 目前有 vbird1 与 root 两个人在线上， 我的 root 要跟 vbird1 讲话，可以这样做：

[root@www ~]# write 使用者帐号 [使用者所在终端介面]

[root@www ~]# who
root     pts/1    2009-03-04 11:04 (192.168.1.100)
vbird1   pts/2    2009-03-04 13:15 (192.168.1.100)  <==有看到 vbird1 在线上

[root@www ~]# write vbird1 pts/2
Hello, there:
Please don't do anything wrong...  <==这两行是 root 写的资讯！
# 结束时，请按下 [crtl]-d 来结束输入。此时在 vbird1 的画面中，会出现：

Message from root@www.vbird.tsai on pts/1 at 13:23 ...
Hello, there:
Please don't do anything wrong...
EOF

怪怪～立刻会有讯息回应给 vbird1 ！不过......当时 vbird1 正在查资料，哇！ 这些讯息会立刻打断 vbird1 原本的工作喔！所以，如果 vbird1 这个人不想要接受任何讯息，直接下达这个动作：

[vbird1@www ~]$ mesg n
[vbird1@www ~]$ mesg
is n

不过，这个 mesg 的功能对 root 传送来的讯息没有抵挡的能力！所以如果是 root 传送讯息， vbird1 还是得要收下。 但是如果 root 的 mesg 是 n 的，那么 vbird1 写给 root 的资讯会变这样：

[vbird1@www ~]$ write root
write: root has messages disabled

了解乎？如果想要解开的话，再次下达‘ mesg y ’就好啦！想要知道目前的 mesg 状态，直接下达‘ mesg ’即可！了呼？ 相对于 write 是仅针对一个使用者来传‘简讯’，我们还可以‘对所有系统上面的使用者传送简讯 (广播)’哩～ 如何下达？用 wall 即可啊！他的语法也是很简单的喔！

[root@www ~]# wall "I will shutdown my linux server..."

然后你就会发现所有的人都会收到这个简讯呢！

小标题的图示 使用者邮件信箱： mail

使用 wall, write 毕竟要等到使用者在线上才能够进行，有没有其他方式来联络啊？ 不是说每个 Linux 主机上面的使用者都具有一个 mailbox 吗？ 我们可否寄信给使用者啊！呵呵！当然可以啊！我们可以寄、收 mailbox 内的信件呢！ 一般来说， mailbox 都会放置在 /var/spool/mail 里面，一个帐号一个 mailbox (档案)。 举例来说，我的 vbird1 就具有 /var/spool/mail/vbird1 这个 mailbox 喔！

那么我该如何寄出信件呢？就直接使用 mail 这个指令即可！这个指令的用法很简单的，直接这样下达：‘ mail username@localhost -s "邮件标题" ’即可！ 一般来说，如果是寄给本机上的使用者，基本上，连‘ @localhost ’都不用写啦！ 举例来说，我以 root 寄信给 vbird1 ，信件标题是‘ nice to meet you ’，则：

[root@www ~]# mail vbird1 -s "nice to meet you"
Hello, D.M. Tsai
Nice to meet you in the network.
You are so nice.  byebye!
.    <==这里很重要喔，结束时，最后一行输入小数点 . 即可！
Cc:  <==这里是所谓的‘副本’，不需要寄给其他人，所以直接 [Enter]
[root@www ~]#  <==出现提示字元，表示输入完毕了！

如此一来，你就已经寄出一封信给 vbird1 这位使用者啰，而且，该信件标题为： nice to meet you，信件内容就如同上面提到的。不过，你或许会觉得 mail 这个程式不好用～ 因为在信件编写的过程中，如果写错字而按下 Enter 进入次行，前一行的资料很难删除ㄟ！ 那怎么办？没关系啦！我们使用资料流重导向啊！呵呵！利用那个小于的符号 ( < ) 就可以达到取代键盘输入的要求了。也就是说，你可以先用 vi 将信件内容编好， 然后再以 mail vbird1 -s "nice to meet you" < filename 来将档案内容传输即可。

例题：
请将你的家目录下的环境变数档 (~/.bashrc) 寄给自己！
答：
mail -s "bashrc file content" vbird < ~/.bashrc

刚刚上面提到的是关于‘寄信’的问题，那么如果是要收信呢？呵呵！同样的使用 mail 啊！ 假设我以 vbird1 的身份登入主机，然后输入 mail 后，会得到什么？

[vbird1@www ~]$ mail
Mail version 8.1 6/6/93.  Type ? for help.
"/var/spool/mail/vbird1": 1 message 1 new
>N  1 root@www.vbird.tsai   Wed Mar  4 13:36  18/663   "nice to meet you"
&  <==这里可以输入很多的指令，如果要查阅，输入 ? 即可！

在 mail 当中的提示字元是 & 符号喔，别搞错了～输入 mail 之后，我可以看到我有一封信件， 这封信件的前面那个 > 代表目前处理的信件，而在大于符号的左边那个 N 代表该封信件尚未读过， 如果我想要知道这个 mail 内部的指令有哪些，可以在 & 之后输入‘ ? ’，就可以看到如下的画面：

& ?
    Mail   Commands
t <message list>                type messages
n                               goto and type next message
e <message list>                edit messages
f <message list>                give head lines of messages
d <message list>                delete messages
s <message list> file           append messages to file
u <message list>                undelete messages
R <message list>                reply to message senders
r <message list>                reply to message senders and all recipients
pre <message list>              make messages go back to /usr/spool/mail
m <user list>                   mail to specific users
q                               quit, saving unresolved messages in mbox
x                               quit, do not remove system mailbox
h                               print out active message headers
!                               shell escape
cd [directory]                  chdir to directory or home if none given

<message list> 指的是每封邮件的左边那个数字啦！而几个比较常见的指令是：

指令 | 意义
h | 列出信件标头；如果要查阅 40 封信件左右的信件标头，可以输入‘ h 40 ’
d | 删除后续接的信件号码，删除单封是‘ d10 ’，删除 20~40 封则为‘ d20-40 ’。 不过，这个动作要生效的话，必须要配合 q 这个指令才行(参考底下说明)！
s | 将信件储存成档案。例如我要将第 5 封信件的内容存成 ~/mail.file:‘s 5 ~/mail.file’
x | 或者输入 exit 都可以。这个是‘不作任何动作离开 mail 程式’的意思。 不论你刚刚删除了什么信件，或者读过什么，使用 exit 都会直接离开 mail，所以刚刚进行的删除与阅读工作都会无效。 如果您只是查阅一下邮件而已的话，一般来说，建议使用这个离开啦！除非你真的要删除某些信件。
q | 相对于 exit 是不动作离开， q 则会进行两项动作： 1. 将刚刚删除的信件移出 mailbox 之外； 2. 将刚刚有阅读过的信件存入 ~/mbox ，且移出 mailbox 之外。鸟哥通常不很喜欢使用 q 离开， 因为，很容易忘记读过什么咚咚～导致信件给他移出 mailbox 说～

由于读过的信件若使用‘ q ’来离开 mail 时，会将该信件移动到 ~/mbox 中，所以你可以这样想像： /var/spool/mail/vbird1 为 vbird1 的‘新件匣’，而 /home/vbird1/mbox 则为‘收件匣’的意思。 那如何读取 /home/vbird1/mbox 呢？就使用‘mail -f /home/vbird1/mbox’即可。

大标题的图示 手动新增使用者

一般来说，我们不很建议大家使用手动的方式来新增使用者，为什么呢？ 因为使用者的建立涉及到 GID/UID 等权限的关系，而且，与档案/目录的权限也有关系， 使用 useradd 可以帮我们自动设定好 UID/GID 家目录以及家目录相关的权限设定， 但是，手动来增加的时候，有可能会忘东忘西，结果导致一些困扰的发生。

不过，要了解整个系统，最好还是手动来修改过比较好，至少我们的帐号问题可以完全依照自己的意思去修订， 而不必迁就于系统的预设值啊！但是，还是要告诫一下朋友们，要手动设定帐号时， 您必须要真的很了解自己在作什么，尤其是与权限有关的设定方面喔！好吧！底下就让我们来玩一玩啰～ ^_^

小标题的图示 一些检查工具

既然要手动修改帐号的相关设定档，那么一些检查群组、帐号相关的指令就不可不知道啊～ 尤其是那个密码转换的 pwconv 及 pwuconv 这两个玩意～可重要的很呢！底下我们稍微介绍一下这些指令吧！

  • pwck

pwck 这个指令在检查 /etc/passwd 这个帐号设定档内的资讯，与实际的家目录是否存在等资讯， 还可以比对 /etc/passwd /etc/shadow 的资讯是否一致，另外，如果 /etc/passwd 内的资料栏位错误时，会提示使用者修订。 一般来说，我只是利用这个玩意儿来检查我的输入是否正确就是了。

[root@www ~]# pwck
user adm: directory /var/adm does not exist
user uucp: directory /var/spool/uucp does not exist
user gopher: directory /var/gopher does not exist

瞧！上面仅是告知我，这些帐号并没有家目录，由于那些帐号绝大部分都是系统帐号， 确实也不需要家目录的，所以，那是‘正常的错误！’呵呵！不理他。 ^_^。 相对应的群组检查可以使用 grpck 这个指令的啦！

  • pwconv

这个指令主要的目的是在‘将 /etc/passwd 内的帐号与密码，移动到 /etc/shadow 当中！’ 早期的 Unix 系统当中并没有 /etc/shadow 呢，所以，使用者的登入密码早期是在 /etc/passwd 的第二栏，后来为了系统安全，才将密码资料移动到 /etc/shadow 内的。使用 pwconv 后，可以：

  • 比对 /etc/passwd 及 /etc/shadow ，若 /etc/passwd 内存在的帐号并没有对应的 /etc/shadow 密码时，则 pwconv 会去 /etc/login.defs 取用相关的密码资料，并建立该帐号的 /etc/shadow 资料；

  • 若 /etc/passwd 内存在加密后的密码资料时，则 pwconv 会将该密码栏移动到 /etc/shadow 内，并将原本的 /etc/passwd 内相对应的密码栏变成 x ！

一般来说，如果您正常使用 useradd 增加使用者时，使用 pwconv 并不会有任何的动作，因为 /etc/passwd 与 /etc/shadow 并不会有上述两点问题啊！ ^_^。不过，如果手动设定帐号，这个 pwconv 就很重要啰！

  • pwunconv

相对于 pwconv ， pwunconv 则是‘将 /etc/shadow 内的密码栏资料写回 /etc/passwd 当中， 并且删除 /etc/shadow 档案。’这个指令说实在的，最好不要使用啦！ 因为他会将你的 /etc/shadow 删除喔！如果你忘记备份，又不会使用 pwconv 的话，粉严重呢！

  • chpasswd

chpasswd 是个挺有趣的指令，他可以‘读入未加密前的密码，并且经过加密后， 将加密后的密码写入 /etc/shadow 当中。’这个指令很常被使用在大量建置帐号的情况中喔！ 他可以由 Standard input 读入资料，每笔资料的格式是‘ username:password ’。 举例来说，我的系统当中有个使用者帐号为 dmtsai ，我想要更新他的密码 (update) ， 假如他的密码是 abcdefg 的话，那么我可以这样做：

[root@www ~]# echo "dmtsai:abcdefg" | chpasswd -m

神奇吧！这样就可以更新了呢！在预设的情况中， chpasswd 使用的是 DES 加密方法来加密， 我们可以使用 chpasswd -m 来使用 CentOS 5.x 预设的 MD5 加密方法。这个指令虽然已经很好用了，不过 CentOS 5.x 其实已经提供了‘ passwd --stdin ’的选项，老实说，这个 chpasswd 可以不必使用了。但考虑其他版本不见得会提供 --stdin 给 passwd 这个指令，所以您还是得要了解一下这个指令用途！

小标题的图示 特殊帐号，如纯数字帐号的手工建立

在我们了解了 UID/GID 与帐号的关系之后，基本上，您应该了解了，为啥我们不建议使用纯数字的帐号了！因为很多时候，系统会搞不清楚那组数字是‘帐号’还是‘ UID ’，这不是很好啦～也因此，在早期某些版本底下，是没有办法使用数字来建立帐号的。例如在 Red Hat 9 的环境中， 使用‘ useradd 1234 ’他会显示‘ useradd: invalid user name '1234' ’了解了吗？

Tips:
在较新的 distribution 当中，纯数字的帐号已经可以被 useradd 建立了。不过鸟哥还是非常不建议使用纯数字帐号。 例如在 setfacl 的设定值中，若使用‘ setfacl -m u:501:rwx filename ’那个 501 代表的是 UID 还是帐号？ 因为 setfacl 的设定是支援使用 UID 或帐号的，纯数字帐号很容易造成系统的误解！ 		鸟哥的图示

不过，有的时候，长官的命令难为啊 @_@ 有时还是得要建立这方面的帐号的，那该如何是好？ 呵呵！当然可以手动来建立这样的帐号啦！不过，为了系统安全起见，鸟哥还是不建议使用纯数字的帐号的啦！ 因此，底下的范例当中，我们使用手动的方式来建立一个名为 normaluser 的帐号， 而且这个帐号属于 normalgroup 这个群组。OK！那么整个步骤该如何是好呢？ 由前面的说明来看，您应该了解了帐号与群组是与 /etc/group, /etc/shadow, /etc/passwd, /etc/gshadow 有关，因此，整个动作是这样的：

  1. 先建立所需要的群组 ( vi /etc/group )；
  2. 将 /etc/group 与 /etc/gshadow 同步化 ( grpconv )；
  3. 建立帐号的各个属性 ( vi /etc/passwd )；
  4. 将 /etc/passwd 与 /etc/shadow 同步化 ( pwconv )；
  5. 建立该帐号的密码 ( passwd accountname )；
  6. 建立使用者家目录 ( cp -a /etc/skel /home/accountname )；
  7. 更改使用者家目录的属性 ( chown -R accountname.group /home/accountname )。
够简单的咯吧！让我们来玩一玩啰～
1. 建立群组 normalgroup ，假设 520 这个 GID 没有被使用！并且同步化 gshadow
[root@www ~]# vi /etc/group
# 在最后一行加入底下这一行！
normalgroup:x:520:
[root@www ~]# grpconv
[root@www ~]# grep 'normalgroup' /etc/group /etc/gshadow
/etc/group:normalgroup:x:520:
/etc/gshadow:normalgroup:x::
# 最后确定 /etc/group, /etc/gshadow 都存在这个群组才行！搞定群组啰！

2. 建立 normaluser 这个帐号，假设 UID 700 没被使用掉！
[root@www ~]# vi /etc/passwd
# 在最后一行加入底下这一行！
normaluser:x:700:520::/home/normaluser:/bin/bash

3. 同步化密码，并且建立该使用者的密码
[root@www ~]# pwconv
[root@www ~]# grep 'normaluser' /etc/passwd /etc/shadow
/etc/passwd:normaluser:x:700:520::/home/normaluser:/bin/bash
/etc/shadow:normaluser:x:14307:0:99999:7:::
# 确定 /etc/passwd, /etc/shadow 都含有 normaluser 的资讯了！但是密码还不对～
[root@www ~]# passwd normaluser
Changing password for user normaluser.
New UNIX password:
Retype new UNIX password:
passwd: all authentication tokens updated successfully.

4. 建立使用者家目录，并且修订权限！
[root@www ~]# cp -a /etc/skel /home/normaluser
[root@www ~]# chown -R normaluser:normalgroup /home/normaluser
[root@www ~]# chmod 700 /home/normaluser

别怀疑！这样就搞定了一个帐号的设定了！ 从此以后，你可以建立任何名称的帐号啰～不过，还是不建议您设定一些很怪很怪的帐号名称啦！

小标题的图示 大量建置帐号范本(适用 passwd --stdin 选项)

由于 CentOS 5.x 的 passwd 已经提供了 --stdin 的功能，因此如果我们可以提供帐号密码的话， 那么就能够很简单的建置起我们的帐号密码了。底下鸟哥制作一个简单的 script 来执行新增用户的功能喔！

[root@www ~]# vi account1.sh
#!/bin/bash
# 这支程式用来建立新增帐号，功能有：
# 1. 检查 account1.txt 是否存在，并将该档案内的帐号取出；
# 2. 建立上述档案的帐号；
# 3. 将上述帐号的密码修订成为‘强制第一次进入需要修改密码’的格式。
# 2009/03/04    VBird
export PATH=/bin:/sbin:/usr/bin:/usr/sbin

# 检查 account1.txt 是否存在
if [ ! -f account1.txt ]; then
        echo "所需要的帐号档案不存在，请建立 account1.txt ，每行一个帐号名称"
        exit 1
fi

usernames=$(cat account1.txt)

for username in $usernames
do
        useradd $username                         <==新增帐号
        echo $username | passwd --stdin $username <==与帐号相同的密码
        chage -d 0 $username                      <==强制登入修改密码
done

接下来只要建立 account1.txt 这个档案即可！鸟哥建立这个档案里面共有十行，你可以自行建立该档案！ 内容每一行一个帐号。注意，最终的结果会是每个帐号具有与帐号相同的密码，且初次登入后， 必须要重新设定密码后才能够再次登入使用系统资源！

[root@www ~]# vi account1.txt
std01
std02
std03
std04
std05
std06
std07
std08
std09
std10

[root@www ~]# sh account1.sh
Changing password for user std01.
passwd: all authentication tokens updated successfully.
....(后面省略)....

这支简单的脚本你可以在按如下的连结下载：

  • http://linux.vbird.org/linux_basic/0410accountmanager/account1.sh

另外，鸟哥的 script 是在 zh_TW.big5 的语系下建立的，如果你需要转成万国码 (utf8) 的编码格式， 请下载上述档案后，利用第十章谈到的 iconv 来处理语系的问题！

小标题的图示 大量建置帐号的范例(适用于连续数字，如学号)

前一小节的内容已经可以满足很多朋友的帐号建置方法了，不过，某些时候上述的 script 还是很麻烦！ 因为需要手动编辑 account1.txt 嘛！如果是类似学校单位这种学号非常类似的帐号时，有没有更快的方案？ 此外，如果需要每个班级同属于一个群组，不同班级的群组不同，又该如何建置？这是比较麻烦啦！

目前很多网站都有提供大量建立帐号的工具，例如台南县网中心的卧龙大师：

  • http://news.ols3.net/techdoc/old/howtouse_cmpwd101.htm

提供的好用的 cmpwd 程式，但是小三大师的程式仅供学术单位使用，一般个人是无权使用的(参考上述连结的授权)。 不过，其实我们也可以利用简单的 script 来帮我们达成喔！例如底下这支程式， 他的执行结果与小三大师提供的程式差不多啦～但是因为我是直接以 useradd 来新增的， 所以，即使不了解 UID ，也是可以适用的啦～整支程式的特色是：

  • 预设不允许使用纯数字方式建立帐号；
  • 可加入年级来区分帐号；
  • 可设定帐号的起始号码与帐号数量；
  • 有两种密码建立方式，可以与帐号相同或程式自行以乱数建立密码档。

执行方法也简单的要命～请自行参考的啦！不再多说～使用时请注意，不要在公家使用的主机上面进行测试，因为..... 这支程式会大量建立帐号嘛！^_^

#!/bin/bash
#
# 这支程式主要在帮您建立大量的帐号之用，更多的使用方法请参考：
# http://linux.vbird.org/linux_basic/0410accountmanager.php#manual_amount
#
# 本程式为鸟哥自行开发，在 CentOS 5.x 上使用没有问题，
# 但不保证绝不会发生错误！使用时，请自行负担风险～
#
# History:
# 2005/09/05    VBird   刚刚才写完，使用看看先～
# 2009/03/04    VBird   加入一些语系的修改与说明，修改密码产生方式 (用 openssl)
export LANG=zh_TW.big5
export PATH=/sbin:/usr/sbin:/bin:/usr/bin
accountfile="user.passwd"

# 1. 进行帐号相关的输入先！
echo ""
echo "例如我们昆山四技的学号为： 4960c001 到 4960c060 ，那么："
echo "帐号开头代码为         ：4"
echo "帐号层级或年级为       ：960c"
echo "号码数字位数为(001~060)：3"
echo "帐号开始号码为         ：1"
echo "帐号数量为             ：60"
echo ""
read -p "帐号开头代码 ( Input title name, ex> std )======> " username_start
read -p "帐号层级或年级 ( Input degree, ex> 1 or enter )=> " username_degree
read -p "号码部分的数字位数 ( Input \# of digital )======> " nu_nu
read -p "起始号码 ( Input start number, ex> 520 )========> " nu_start
read -p "帐号数量 ( Input amount of users, ex> 100 )=====> " nu_amount
read -p "密码标准 1) 与帐号相同 2)乱数自订 ==============> " pwm
if [ "$username_start" == "" ]; then
        echo "没有输入开头的代码，不给你执行哩！" ; exit 1
fi
# 判断数字系统
testing0=$(echo $nu_nu     | grep '[^0-9]' )
testing1=$(echo $nu_amount | grep '[^0-9]' )
testing2=$(echo $nu_start  | grep '[^0-9]' )
if [ "$testing0" != "" -o "$testing1" != "" -o "$testing2" != "" ]; then
        echo "输入的号码不对啦！有非为数字的内容！" ; exit 1
fi
if [ "$pwm" != "1" ]; then
        pwm="2"
fi

# 2. 开始输出帐号与密码档案！
[ -f "$accountfile" ] && mv $accountfile "$accountfile"$(date +%Y%m%d)
nu_end=$(($nu_start+$nu_amount-1))
for (( i=$nu_start; i<=$nu_end; i++ ))
do
        nu_len=${#i}
        if [ $nu_nu -lt $nu_len ]; then
                echo "数值的位数($i->$nu_len)已经比你设定的位数($nu_nu)还大！"
                echo "程式无法继续"
                exit 1
        fi
        nu_diff=$(( $nu_nu - $nu_len ))
        if [ "$nu_diff" != "0" ]; then
                nu_nn=0000000000
                nu_nn=${nu_nn:1:$nu_diff}
        fi
        account=${username_start}${username_degree}${nu_nn}${i}
        if [ "$pwm" == "1" ]; then
                password="$account"
        else
                password=$(openssl rand -base64 6)
        fi
        echo "$account":"$password" | tee -a "$accountfile"
done

# 3. 开始建立帐号与密码！
cat "$accountfile" | cut -d':' -f1 | xargs -n 1 useradd -m
chpasswd < "$accountfile"
pwconv
echo "OK！建立完成！"

如果有需要建立同一班级具有同一群组的话，可以先使用 groupadd 建立群组后， 将该群组加入‘ cat "$accountfile" | cut -d':' -f1 | xargs -n 1 useradd -m -g groupname ’那行！这支脚本可以在底下连结下载：

  • http://linux.vbird.org/linux_basic/0410accountmanager/account2.sh

如果仅是测试而已，想要将刚刚建立的使用者整个删除，则可以使用如下的脚本来进行删除！

[root@www ~]# vi delaccount2.sh
#!/bin/bash
usernames=$(cat user.passwd | cut -d ':' -f 1)
for username in $usernames
do
    echo "userdel -r $username"
    userdel -r $username
done
[root@www ~]# sh delaccount2.sh

总之，帐号管理是很重要的！希望上面的说明能够对大家有点帮助啦！

大标题的图示 重点回顾
  • Linux 作业系统上面，关于帐号与群组，其实记录的是 UID/GID 的数字而已；
  • 使用者的帐号/群组与 UID/GID 的对应，参考 /etc/passwd 及 /etc/group 两个档案
  • /etc/passwd 档案结构以冒号隔开，共分为七个栏位，分别是‘帐号名称、密码、UID、GID、全名、家目录、shell’
  • UID 只有 0 与非为 0 两种，非为 0 则为一般帐号。一般帐号又分为系统帐号 (1~499) 即可登入者帐号 (大于 500)
  • 帐号的密码已经移动到 /etc/shadow 档案中，该档案权限为仅有 root 可以更动。该档案分为九个栏位，内容为‘ 帐号名称、加密密码、密码更动日期、密码最小可变动日期、密码最大需变动日期、密码过期前警告日数、密码失效天数、 帐号失效日、保留未使用’
  • 使用者可以支援多个群组，其中在新建档案时会影响新档案群组者，为有效群组。而写入 /etc/passwd 的第四个栏位者， 称为初始群组。
  • 与使用者建立、更改参数、删除有关的指令为：useradd, usermod, userdel等，密码建立则为 passwd；
  • 与群组建立、修改、删除有关的指令为：groupadd, groupmod, groupdel 等；
  • 群组的观察与有效群组的切换分别为：groups 及 newgrp 指令；
  • useradd 指令作用参考的档案有： /etc/default/useradd, /etc/login.defs, /etc/skel/ 等等
  • 观察使用者详细的密码参数，可以使用‘ chage -l 帐号 ’来处理；
  • 使用者自行修改参数的指令有： chsh, chfn 等，观察指令则有： id, finger 等
  • ACL 可进行单一个人或群组的权限管理，但 ACL 的启动需要有档案系统的支援；
  • ACL 的设定可使用 setfacl ，查阅则使用 getfacl ；
  • 身份切换可使用 su ，亦可使用 sudo ，但使用 sudo 者，必须先以 visudo 设定可使用的指令；
  • PAM 模组可进行某些程式的验证程序！与 PAM 模组有关的设定档位于 /etc/pam.d/* 及 /etc/security/*
  • 系统上面帐号登入情况的查询，可使用 w, who, last, lastlog 等；
  • 线上与使用者交谈可使用 write, wall，离线状态下可使用 mail 传送邮件！
大标题的图示 本章习题
  • 情境模拟题一：想将本伺服器的帐号分开管理，分为单纯邮件使用，与可登入系统帐号两种。其中若为纯邮件帐号时， 将该帐号加入 mail 为初始群组，且此帐号不可使用 bash 等 shell 登入系统。若为可登入帐号时， 将该帐号加入 youcan 这个次要群组。

    • 目标：了解 /sbin/nologin 的用途；
    • 前提：可自行观察使用者是否已经建立等问题；
    • 需求：需已了解 useradd, groupadd 等指令的用法；

    解决方案如下：

    1. 预先察看一下两个群组是否存在？
      [root@www ~]# grep mail /etc/group
[root@www ~]# grep youcan /etc/group
[root@www ~]# groupadd youcan
      可发现 youcan 尚未被建立，因此如上表所示，我们主动去建立这个群组啰。

    2. 开始建立三个邮件帐号，此帐号名称为 pop1, pop2, pop3 ，且密码与帐号相同。可使用如下的程式来处理：
      [root@www ~]# vim popuser.sh
#!/bin/bash
for username in pop1 pop2 pop3
do
    useradd -g mail -s /sbin/nologin -M $username
    echo $username | passwd --stdin $username
done
[root@www ~]# sh popuser.sh

    3. 开始建立一般帐号，只是这些一般帐号必须要能够登入，并且需要使用次要群组的支援！所以：
      [root@www ~]# vim loginuser.sh
#!/bin/bash
for username in youlog1 youlog2 youlog3
do
    useradd -G youcan -s -m $username
    echo $username | passwd --stdin $username
done
[root@www ~]# sh loginuser.sh

    4. 这样就将帐号分开管理了！非常简单吧！
简答题部分
  • root 的 UID 与 GID 是多少？而基于这个理由，我要让 test 这个帐号具有 root 的权限，应该怎么作？
    root 的 UID 与 GID 均为 0 ，所以要让 test 变成 root 的权限，那么就将 /etc/passwd 里面， test 的 UID 与 GID 栏位变成 0 即可！
  • 假设我是一个系统管理员，我有一个用户最近不乖，所以我想暂时将他的帐号停掉， 让他近期无法进行任何动作，等到未来他乖一点之后，我再将他的帐号启用，请问：我可以怎么作比较好？？
    由于这个帐号是暂时失效的，所以不能使用 userdel 来删除，否则很麻烦！那么应该如何设定呢？再回去瞧一瞧 /etc/shadow 的架构，可以知道有这几个可使用的方法：
    • 将 /etc/passwd 的 shell 栏位写成 /sbin/nologin ，即可让该帐号暂时无法登入主机；
    • 将 /etc/shadow 内的密码栏位，增加一个 * 号在最前面，这样该帐号亦无法登入！
    • 将 /etc/shadow 的第八个栏位关于帐号取消日期的那个，设定小于目前日期的数字，那么他就无法登入系统了！
  • 我在使用 useradd 的时候，新增的帐号里面的 UID, GID 还有其他相关的密码控制，都是在哪几个档案里面设定的？
    在 /etc/login.defs 还有 /etc/default/useradd 里面规定好的！
  • 我希望我在设定每个帐号的时候( 使用 useradd )，预设情况中，他们的家目录就含有一个名称为 www 的子目录，我应该怎么作比较好？
    由于使用 useradd 的时候，会自动以 /etc/skel 做为预设的家目录，所以，我可以在 /etc/skel 里面新增加一个名称为 www 的目录即可！
  • 简单说明系统帐号与一般使用者帐号的差别？
    一般而言，为了让系统能够顺利以较小的权限运作，系统会有很多帐号， 例如 mail, bin, adm 等等。而为了确保这些帐号能够在系统上面具有独一无二的权限， 一般来说 Linux 都会保留一些 UID 给系统使用。在 CentOS 5.x 上面，小于 500 以下的帐号 (UID) 即是所谓的 System account。
  • 简单说明，为何 CentOS 5.x 建立使用者时，他会主动的帮使用者建立一个群组，而不是使用 /etc/default/useradd 的设定？
    不同的 linux distributions 对于使用者 group 的建立机制并不相同。主要的机制分为：
    • Public group schemes: 使用者将会直接给予一个系统指定的群组，一般来说即是 users ， 可以 SuSE Server 9 为代表；
    • Private group schemes: 系统会建立一个与帐号一样的群组名称！以 CentOS 5.x 为例！
  • 如何建立一个使用者名称 alex, 他所属群组为 alexgroup, 预计使用 csh, 他的全名为 "Alex Tsai"， 且他还得要加入 users 群组当中！
    groupadd alexgroup
    useradd -c "Alex Tsai" -g alexgroup -G users -m alex
    务必先建立群组，才能够建立使用者喔！
  • 由于种种因素，导致你的使用者家目录以后都需要被放置到 /account 这个目录下。 请问，我该如何作，可以让使用 useradd 时，预设的家目录就指向 /account ？
    最简单的方法，编辑 /etc/default/useradd ，将里头的 HOME=/home 改成 HOME=/account 即可。
  • 我想要让 dmtsai 这个使用者，加入 vbird1, vbird2, vbird3 这三个群组，且不影响 dmtsai 原本已经支援的次要群组时，该如何动作？
    usermod -a -G vbird1,vbird2,vbird3 dmtsai
大标题的图示 参考资料与延伸阅读
  • 注1：最完整与详细的密码档说明，可参考各 distribution 内部的 man page。 本文中以 CentOS 5.x 的‘ man 5 passwd ’及‘ man 5 shadow ’的内容说明；
  • 注2：MD5与DES均为加密的机制，详细的解释可参考维基百科的说明：
    MD5：http://zh.wikipedia.org/wiki/MD5
    DES：http://en.wikipedia.org/wiki/Data_Encryption_Standard
    在早期的 Linux 版本中，主要使用 DES 加密演算法，近期则使用 MD5 作为预设演算法。
  • 注3：telnet 与 ssh 都是可以由远端用户主机连线到 Linux 伺服器的一种机制！详细资料可查询鸟站文章： 远端连线伺服器：http://linux.vbird.org/linux_server/0310telnetssh.php
  • 注4：详细的说明请参考 man sudo ，然后以 5 作为关键字搜寻看看即可了解。
  • 注5：详细的 PAM 说明可以参考如下连结：
    维基百科：http://en.wikipedia.org/wiki/Pluggable_Authentication_Modules
    Linux-PAM网页： http://www.kernel.org/pub/linux/libs/pam/
2002/05/15：第一次完成
2003/02/10：重新编排与加入 FAQ
2005/08/25：加入一个大量建置帐号的实例，简单说明一下而已！
2005/08/29：将原本的旧文放置到 此处
2005/08/31：因为 userconf 已经不再这么好用了，使用指令模式比较简单，所以，将他拿掉了～
2005/09/05：终于将大量建置帐号的那支程式写完了～真是高兴啊！
2006/03/02：更新使用者 UID 号码，由 65535 升级到 2^32-1 这么大！
2007/04/15：原本写的 /etc/pam.d/limits.conf 错了！应该是 /etc/security/limits.conf 才对！
2008/04/28：sudo 关于密码重新输入的部分写错了！已经更新，在这里查阅看看。感谢网友 superpmo 的告知！
2009/02/18：将基于 FC4 版本的旧文章移动到 此处。
2009/02/26：加入 chage 以及‘ chage -d 0 帐号’的功能！
2009/02/27：加入 acl 的控制项目！
2009/03/04：加入一个简单的帐号新增范例，以及修改原本的帐号新增范例！
2009/04/28：取消 sudo 内的 -c 选项功能说明！之前说的是错的～
2009/09/09：加入一些模拟题，修改一些语词的用法。


鸟哥的 Linux 私房菜 -- Quota, Software RAID, LVM, iSCSI

为取得较佳浏览结果，请爱用 firefox 浏览本网页
鸟哥的 Linux 私房菜馆 | Linux 基础文件 | Linux 架站文件 | Linux 企业运用 | 安全管理 | 新手讨论 |

第十五章、磁碟配额(Quota)与进阶档案系统管理
最近更新日期：2009/09/10
如果您的 Linux 伺服器有多个用户经常存取资料时，为了维护所有使用者在硬碟容量的公平使用，磁碟配额 (Quota) 就是一项非常有用的工具！另外，如果你的用户常常抱怨磁碟容量不够用，那么更进阶的档案系统就得要学习学习。 本章我们会介绍磁碟阵列 (RAID) 及逻辑卷轴档案系统 (LVM)，这些工具都可以帮助你管理与维护使用者可用的磁碟容量喔！

1. 磁碟配额 (Quota) 的应用与实作
    1.1 什么是 Quota：一般用途, 限制, 规范 (inode/block, soft/hard, grace time)
    1.2 一个 Quota 的实作范例
    1.3 实作 Quota 流程-1：档案系统支援 (/etc/fstab, /etc/mtab)
    1.4 实作 Quota 流程-2：建立 quota 记录档 (quotacheck)
    1.5 实作 Quota 流程-3：启动、关闭与限制值设定 (quotaon, quotaoff, edquota)
    1.6 实作 Quota 流程-4：Quota 限制值的报表 (quota, repquota)
    1.7 实作 Quota 流程-5：测试与管理 (测试, warnquota, setquota)
    1.8 不更动既有系统的 Quota 实例
 2. 软体磁碟阵列 (Software RAID)
    2.1 什么是 RAID： RAID-0, RAID-1, RAID0+1, RAID-5, Spare disk
    2.2 software, hardware RAID
    2.3 软体磁碟阵列的设定： mdadm --create
    2.4 模拟 RAID 错误的救援模式： mdadm --manage
    2.5 开机自动启动 RAID 并自动挂载
    2.6 关闭软体 RAID(重要！)
 3. 逻辑卷轴管理员 (Logical Volume Manager)
    3.1 什么是 LVM： PV, PE, VG, LV 的意义
    3.2 LVM 实作流程： PV 阶段, VG 阶段, LV 阶段, 档案系统阶段
    3.3 放大 LV 容量： resize2fs
    3.4 缩小 LV 容量
    3.5 LVM 的系统快照： 建立, 还原, 用于测试环境
    3.6 LVM 相关指令汇整与 LVM 的关闭
 4. 重点回顾
5. 本章习题
6. 参考资料与延伸阅读
7. 针对本文的建议：http://phorum.vbird.org/viewtopic.php?t=23888
大标题的图示 磁碟配额 (Quota) 的应用与实作

Quota 这个玩意儿就字面上的意思来看，就是有多少‘限额’的意思啦！如果是用在零用钱上面， 就是类似‘有多少零用钱一个月’的意思之类的。如果是在电脑主机的磁碟使用量上呢？以 Linux 来说，就是有多少容量限制的意思啰。我们可以使用 quota 来让磁碟的容量使用较为公平， 底下我们会介绍什么是 quota ，然后以一个完整的范例来介绍 quota 的实作喔！

小标题的图示 什么是 Quota

在 Linux 系统中，由于是多人多工的环境，所以会有多人共同使用一个硬碟空间的情况发生， 如果其中有少数几个使用者大量的占掉了硬碟空间的话，那势必压缩其他使用者的使用权力！ 因此管理员应该适当的限制硬碟的容量给使用者，以妥善的分配系统资源！避免有人抗议呀！

举例来说，我们使用者的预设家目录都是在 /home 底下，如果 /home 是个独立的 partition ， 假设这个分割槽有 10G 好了，而 /home 底下共有 30 个帐号，也就是说，每个使用者平均应该会有 333MB 的空间才对。 偏偏有个使用者在他的家目录底下塞了好多只影片，占掉了 8GB 的空间，想想看，是否造成其他正常使用者的不便呢？ 如果想要让磁碟的容量公平的分配，这个时候就得要靠 quota 的帮忙啰！

  • Quota 的一般用途

quota 比较常使用的几个情况是：

  • 针对 WWW server ，例如：每个人的网页空间的容量限制！
  • 针对 mail server，例如：每个人的邮件空间限制。
  • 针对 file server，例如：每个人最大的可用网路硬碟空间 (教学环境中最常见！)

上头讲的是针对网路服务的设计，如果是针对 Linux 系统主机上面的设定那么使用的方向有底下这一些：

  • 限制某一群组所能使用的最大磁碟配额 (使用群组限制)：
    你可以将你的主机上的使用者分门别类，有点像是目前很流行的付费与免付费会员制的情况， 你比较喜好的那一群的使用配额就可以给高一些！呵呵！ ^_^...

  • 限制某一使用者的最大磁碟配额 (使用使用者限制)：
    在限制了群组之后，你也可以再继续针对个人来进行限制，使得同一群组之下还可以有更公平的分配！

  • 以 Link 的方式，来使邮件可以作为限制的配额 (更改 /var/spool/mail 这个路径)：
    如果是分为付费与免付费会员的‘邮件主机系统’，是否需要重新再规划一个硬碟呢？ 也不需要啦！直接使用 Link 的方式指向 /home (或者其他已经做好的 quota 磁碟) 就可以啦！ 这通常是用在原本磁碟分割的规划不好，但是却又不想要更动原有主机架构的情况中啊！

大概有这些实际的用途啦！

  • Quota 的使用限制

虽然 quota 很好用，但是使用上还是有些限制要先了解的：

  • 仅能针对整个 filesystem：
    quota 实际在运作的时候，是针对‘整个 filesystem’进行限制的， 例如：如果你的 /dev/sda5 是挂载在 /home 底下，那么在 /home 底下的所有目录都会受到限制！

  • 核心必须支援 quota ：
    Linux 核心必须有支援 quota 这个功能才行：如果你是使用 CentOS 5.x 的预设核心， 嘿嘿！那恭喜你了，你的系统已经预设有支援 quota 这个功能啰！如果你是自行编译核心的， 那么请特别留意你是否已经‘真的’开启了 quota 这个功能？否则底下的功夫将全部都视为‘白工’。

  • Quota 的记录档：
    目前新版的 Linux distributions 使用的是 Kernel 2.6.xx 的核心版本，这个核心版本支援新的 quota 模组，使用的预设档案 (aquota.user, aquota.group )将不同于旧版本的 quota.user, quota.group ！ (多了一个 a 呦！) 而由旧版本的 quota 可以藉由 convertquota 这个程式来转换呢！

  • 只对一般身份使用者有效：
    这就有趣了！并不是所有在 Linux 上面的帐号都可以设定 quota 呢，例如 root 就不能设定 quota ， 因为整个系统所有的资料几乎都是他的啊！ ^_^

所以啰，你不能针对‘某个目录’来进行 Quota 的设计，但你可以针对‘某个档案系统 (filesystem) ’来设定。 如果不明白目录与挂载点还有档案系统的关系，请回到第八章去瞧瞧再回来！

  • Quota 的规范设定项目：

quota 这玩意儿针对整个 filesystem 的限制项目主要分为底下几个部分：

  • 容量限制或档案数量限制 (block 或 inode)：

    我们在第八章谈到档案系统中，说到档案系统主要规划为存放属性的 inode 与实际档案资料的 block 区块，Quota 既然是管理档案系统，所以当然也可以管理 inode 或 block 啰！ 这两个管理的功能为：

    • 限制 inode 用量：可以管理使用者可以建立的‘档案数量’；
    • 限制 block 用量：管理使用者磁碟容量的限制，较常见为这种方式。

  • 柔性劝导与硬性规定 (soft/hard)：

    既然是规范，当然就有限制值。不管是 inode/block ，限制值都有两个，分别是 soft 与 hard。 通常 hard 限制值要比 soft 还要高。举例来说，若限制项目为 block ，可以限制 hard 为 500MBytes 而 soft 为 400MBytes。这两个限值的意义为：

    • hard：表示使用者的用量绝对不会超过这个限制值，以上面的设定为例， 使用者所能使用的磁碟容量绝对不会超过 500Mbytes ，若超过这个值则系统会锁住该用户的磁碟使用权；

    • soft：表示使用者在低于 soft 限值时 (此例中为 400Mbytes)，可以正常使用磁碟，但若超过 soft 且低于 hard 的限值 (介于 400~500Mbytes 之间时)，每次使用者登入系统时，系统会主动发出磁碟即将爆满的警告讯息， 且会给予一个宽限时间 (grace time)。不过，若使用者在宽限时间倒数期间就将容量再次降低于 soft 限值之下， 则宽限时间会停止。

  • 会倒数计时的宽限时间 (grace time)：

    刚刚上面就谈到宽限时间了！这个宽限时间只有在使用者的磁碟用量介于 soft 到 hard 之间时，才会出现且会倒数的一个咚咚！ 由于达到 hard 限值时，使用者的磁碟使用权可能会被锁住。为了担心使用者没有注意到这个磁碟配额的问题， 因此设计了 soft 。当你的磁碟用量即将到达 hard 且超过 soft 时，系统会给予警告，但也会给一段时间让使用者自行管理磁碟。 一般预设的宽限时间为七天，如果七天内你都不进行任何磁碟管理，那么 soft 限制值会即刻取代 hard 限值来作为 quota 的限制。

    以上面设定的例子来说，假设你的容量高达 450MBytes 了，那七天的宽限时间就会开始倒数， 若七天内你都不进行任何删除档案的动作来替你的磁碟用量瘦身， 那么七天后你的磁碟最大用量将变成 400MBytes (那个 soft 的限制值)，此时你的磁碟使用权就会被锁住而无法新增档案了。

整个 soft, hard, grace time 的相关性我们可以用底下的图示来说明：

soft, hard, grace time 的相关性
图 1.1.1、soft, hard, grace time 的相关性

图中的长条图为使用者的磁碟容量，soft/hard 分别是限制值。只要小于 400M 就一切 OK ， 若高于 soft 就出现 grace time 并倒数且等待使用者自行处理，若到达 hard 的限制值， 那我们就搬张小板凳等着看好戏啦！嘿嘿！^_^！这样图示有清楚一点了吗？

小标题的图示 一个 Quota 实作范例

坐而言不如起而行啊，所以这里我们使用一个范例来设计一下如何处理 Quota 的设定流程。

  • 目的与帐号：现在我想要让我的专题生五个为一组，这五个人的帐号分别是 myquota1, myquota2, myquota3, myquota4, myquota5，这五个用户的密码都是 password ，且这五个用户所属的初始群组都是 myquotagrp 。 其他的帐号属性则使用预设值。

  • 帐号的磁碟容量限制值：我想让这五个用户都能够取得 300MBytes 的磁碟使用量(hard)，档案数量则不予限制。 此外，只要容量使用率超过 250MBytes ，就予以警告 (soft)。

  • 群组的限额：由于我的系统里面还有其他用户存在，因此我仅承认 myquotagrp 这个群组最多仅能使用 1GBytes 的容量。 这也就是说，如果 myquota1, myquota2, myquota3 都用了 280MBytes 的容量了，那么其他两人最多只能使用 (1000MB - 280x3 = 160MB) 的磁碟容量啰！这就是使用者与群组同时设定时会产生的后果。

  • 宽限时间的限制：最后，我希望每个使用者在超过 soft 限制值之后，都还能够有 14 天的宽限时间。

好了，那你怎么规范帐号以及相关的 Quota 设定呢？首先，在这个小节我们先来将帐号相关的属性与参数搞定再说吧！

# 制作帐号环境时，由于有五个帐号，因此鸟哥使用 script 来建立环境！
[root@www ~]# vi addaccount.sh
#!/bin/bash
# 使用 script 来建立实验 quota 所需的环境
groupadd myquotagrp
for username in myquota1 myquota2 myquota3 myquota4 myquota5
do
    useradd -g myquotagrp $username
    echo "password" | passwd --stdin $username
done

[root@www ~]# sh addaccount.sh

接下来，就让我们来实作 Quota 的练习吧！

小标题的图示 实作 Quota 流程-1：档案系统支援

前面我们就谈到，要使用 Quota 必须要核心与档案系统支援才行！假设你已经使用了预设支援 Quota 的核心， 那么接下来就是要启动档案系统的支援啦！不过，由于 Quota 仅针对整个档案系统来进行规划，所以我们得先查一下， /home 是否是个独立的 filesystem 呢？

[root@www ~]# df -h /home
Filesystem     Size  Used Avail Use% Mounted on
/dev/hda3      4.8G  740M  3.8G  17% /home  <==鸟哥主机的 /home 确实是独立的！

[root@www ~]# mount | grep home
/dev/hda3 on /home type ext3 (rw)

从上面的资料来看，鸟哥这部主机的 /home 确实是独立的 filesystem，因此可以直接限制 /dev/hda3 。 如果你的系统的 /home 并非独立的档案系统，那么可能就得要针对根目录 (/) 来规范了！不过，不太建议在根目录设定 Quota。 此外，由于 VFAT 档案系统并不支援 Linux Quota 功能，所以我们得要使用 mount 查询一下 /home 的档案系统为何？ 看起来是 Linux 传统的 ext2/ext3 ，这种档案系统肯定有支援 Quota 啦！没问题！

如果只是想要在这次开机中实验 Quota ，那么可以使用如下的方式来手动加入 quota 的支援：

[root@www ~]# mount -o remount,usrquota,grpquota /home
[root@www ~]# mount | grep home
/dev/hda3 on /home type ext3 (rw,usrquota,grpquota)
# 重点就在于 usrquota, grpquota ！注意写法！

事实上，当你重新挂载时，系统会同步更新 /etc/mtab 这个档案， 所以你必须要确定 /etc/mtab 已经加入 usrquota, grpquota 的支援到你所想要设定的档案系统中。 另外也要特别强调，使用者与群组的 quota 档案系统支援参数分别是：usrquota, grpquota ！千万不要写错了！这一点非常多初接触 Quota 的朋友常常搞错。

不过手动挂载的资料在下次重新挂载就会消失，因此最好写入设定档中啊！在鸟哥这部主机的案例中， 我可以直接修改 /etc/fstab 成为底下这个样子：

[root@www ~]# vi /etc/fstab
LABEL=/home   /home  ext3   defaults,usrquota,grpquota  1 2
# 其他项目鸟哥并没有列出来！重点在于第四栏位！于 default 后面加上两个参数！

[root@www ~]# umount /home
[root@www ~]# mount -a
[root@www ~]# mount | grep home
/dev/hda3 on /home type ext3 (rw,usrquota,grpquota)

还是要再次的强调，修改完 /etc/fstab 后，务必要测试一下！若有发生错误得要赶紧处理！ 因为这个档案如果修改错误，是会造成无法开机完全的情况啊！切记切记！最好使用 vim 来修改啦！ 因为会有语法的检验，就不会让你写错字了！启动档案系统的支援后，接下来让我们建立起 quota 的记录档吧！

小标题的图示 实作 Quota 流程-2：建立 quota 记录档

其实 Quota 是透过分析整个档案系统中，每个使用者(群组)拥有的档案总数与总容量， 再将这些资料记录在该档案系统的最顶层目录，然后在该记录档中再使用每个帐号(或群组)的限制值去规范磁碟使用量的。 所以啦，建置这个 Quota 记录档就显的非常的重要。扫瞄有支援 Quota 参数 (usrquota, grpquota) 的档案系统， 就使用 quotacheck 这个指令！这个指令的语法如下：

  • quotacheck ：扫瞄档案系统并建立 Quota 的记录档
[root@www ~]# quotacheck [-avugfM] [/mount_point]
选项与参数：
-a  ：扫瞄所有在 /etc/mtab 内，含有 quota 支援的 filesystem，加上此参数后，
      /mount_point 可不必写，因为扫瞄所有的 filesystem 了嘛！
-u  ：针对使用者扫瞄档案与目录的使用情况，会建立 aquota.user
-g  ：针对群组扫瞄档案与目录的使用情况，会建立 aquota.group
-v  ：显示扫瞄过程的资讯；
-f  ：强制扫瞄档案系统，并写入新的 quota 设定档 (危险)
-M  ：强制以读写的方式扫瞄档案系统，只有在特殊情况下才会使用。

quotacheck 的选项你只要记得‘ -avug ’一起下达即可！那个 -f 与 -M 是在档案系统可能已经启动 quota 了， 但是你还想要重新扫瞄档案系统时，系统会要求你加入那两个选项啦 (担心有其他人已经使用 quota 中)！平时没必要不要加上那两个项目。好了，那就让我们来处理我们的任务吧！

# 针对整个系统含有 usrquota, grpquota 参数的档案系统进行 quotacheck 扫瞄
[root@www ~]# quotacheck -avug
quotacheck: Scanning /dev/hda3 [/home] quotacheck: Cannot stat old user quota
file: No such file or directory <==有找到档案系统，但尚未制作记录档！
quotacheck: Cannot stat old group quota file: No such file or directory
quotacheck: Cannot stat old user quota file: No such file or directory
quotacheck: Cannot stat old group quota file: No such file or directory
done  <==上面三个错误只是说明记录档尚未建立而已，可以忽略不理！
quotacheck: Checked 130 directories and 107 files <==实际搜寻结果
quotacheck: Old file not found.
quotacheck: Old file not found.
# 若执行这个指令却出现如下的错误讯息，表示你没有任何档案系统有启动 quota 支援！
# quotacheck: Can't find filesystem to check or filesystem not mounted with
# quota option.

[root@www ~]# ll -d /home/a*
-rw------- 1 root root 8192 Mar  6 11:58 /home/aquota.group
-rw------- 1 root root 9216 Mar  6 11:58 /home/aquota.user
# 在鸟哥的案例中，/home 独立的档案系统，因此搜寻结果会将两个记录档放在
# /home 底下。这两个档案就是 Quota 最重要的资讯了！

这个指令只要进行到这里就够了，不要反覆的进行！因为等一下我们会启动 quota 功能，若启动后你还要进行 quotacheck ， 系统会担心破坏原有的记录档，所以会产生一些错误讯息警告你。如果你确定没有任何人在使用 quota 时， 可以强制重新进行 quotacheck 的动作。强制执行的情况可以使用如下的选项功能：

# 如果因为特殊需求需要强制扫瞄已挂载的档案系统时
[root@www ~]# quotacheck -avug -mf
quotacheck: Scanning /dev/hda3 [/home] done
quotacheck: Checked 130 directories and 109 files
# 资料要简洁很多！因为有记录档存在嘛！所以警告讯息不会出现！

这样记录档就建立起来了！你不用手动去编辑那两个档案～因为那两个档案是 quota 自己的资料档，并不是纯文字档啦！ 且该档案会一直变动，这是因为当你对 /home 这个档案系统进行操作时，你操作的结果会影响磁碟吧！ 所以当然会同步记载到那两个档案中啦！所以要建立 aquota.user, aquota.group，记得使用的是 quotacheck 指令！ 不是手动编辑的喔！

小标题的图示 实作 Quota 流程-3：Quota 启动、 关闭与限制值设定

制作好 Quota 设定档之后，接下来就是要启动 quota 了！启动的方式很简单！使用 quotaon ，至于关闭就用 quotaoff 即可

  • quotaon ：启动 quota 的服务
[root@www ~]# quotaon [-avug]
[root@www ~]# quotaon [-vug] [/mount_point]
选项与参数：
-u  ：针对使用者启动 quota (aquota.user)
-g  ：针对群组启动 quota (aquota.group)
-v  ：显示启动过程的相关讯息；
-a  ：根据 /etc/mtab 内的 filesystem 设定启动有关的 quota ，若不加 -a 的话，
      则后面就需要加上特定的那个 filesystem 喔！

# 由于我们要启动 user/group 的 quota ，所以使用底下的语法即可
[root@www ~]# quotaon -auvg
/dev/hda3 [/home]: group quotas turned on
/dev/hda3 [/home]: user quotas turned on

# 特殊用法，假如你的启动 /var 的 quota 支援，那么仅启动 user quota 时
[root@www ~]# quotaon -uv /var

这个‘ quotaon -auvg ’的指令几乎只在第一次启动 quota 时才需要进行！因为下次等你重新启动系统时， 系统的 /etc/rc.d/rc.sysinit 这个初始化脚本就会自动的下达这个指令了！因此你只要在这次实例中进行一次即可， 未来都不需要自行启动 quota ，因为 CentOS 5.x 系统会自动帮你搞定他！

  • quotaoff ：关闭 quota 的服务
[root@www ~]# quotaoff [-a]
[root@www ~]# quotaoff [-ug] [/mount_point]
选项与参数：
-a  ：全部的 filesystem 的 quota 都关闭 (根据 /etc/mtab)
-u  ：仅针对后面接的那个 /mount_point 关闭 user quota
-g  ：仅针对后面接的那个 /mount_point 关闭 group quota

这个指令就是关闭了 quota 的支援！我们这里需要练习 quota 实作，所以这里请不要关闭他喔！ 接下来让我们开始来设定使用者与群组的 quota 限额吧！

  • edquota ：编辑帐号/群组的限值与宽限时间

edquota 是 edit quota 的缩写，所以就是用来编辑使用者或者是群组限额的指令啰。我们先来看看 edquota 的语法吧， 看完后再来实际操作一下。

[root@www ~]# edquota [-u username] [-g groupname]
[root@www ~]# edquota -t  <==修改宽限时间
[root@www ~]# edquota -p 范本帐号 -u 新帐号
选项与参数：
-u  ：后面接帐号名称。可以进入 quota 的编辑画面 (vi) 去设定 username 的限制值；
-g  ：后面接群组名称。可以进入 quota 的编辑画面 (vi) 去设定 groupname 的限制值；
-t  ：可以修改宽限时间。
-p  ：复制范本。那个 范本帐号 为已经存在并且已设定好 quota 的使用者，
      意义为‘将 范本帐号 这个人的 quota 限制值复制给 新帐号 ’！

好了，先让我们来看看当进入 myquota1 的限额设定时，会出现什么画面：

范例一：设定 dmtsai 这个使用者的 quota 限制值
[root@www ~]# edquota -u myquota1
Disk quotas for user myquota1 (uid 710):
  Filesystem    blocks  soft   hard  inodes  soft  hard
  /dev/hda3         80     0      0      10     0     0

上头第一行在说明针对哪个帐号 (myquota1) 进行 quota 的限额设定，第二行则是标头行，里面共分为七个栏位， 七个栏位分别的意义为：

  1. 档案系统 (filesystem)：说明该限制值是针对哪个档案系统 (或 partition)；
  2. 磁碟容量 (blocks)：这个数值是 quota 自己算出来的，单位为 Kbytes，请不要更动他；
  3. soft：磁碟容量 (block) 的 soft 限制值，单位亦为 KB
  4. hard：block 的 hard 限制值，单位 KB；
  5. 档案数量 (inodes)：这是 quota 自己算出来的，单位为个数，请不要更动他；
  6. soft：inode 的 soft 限制值；
  7. hard：inode 的 hard 限制值；

当 soft/hard 为 0 时，表示没有限制的意思。好，依据我们的范例说明，我们需要设定的是 blocks 的 soft/hard ，至于 inode 则不要去更动他！因此上述的画面我们将他改成如下的模样：

Tips:
在 edquota 的画面中，每一行只要保持七个栏位就可以了，并不需要排列整齐的！ 		鸟哥的图示
Disk quotas for user myquota1 (uid 710):
  Filesystem    blocks    soft    hard  inodes  soft  hard
  /dev/hda3         80  250000  300000      10     0     0
# 鸟哥使用 1000 去近似 1024 的倍数！比较好算啦！然后就可以储存后离开啰！

设定完成之后，我们还有其他 5 个用户要设定，由于设定值都一样，此时可以使用 quota 复制喔！

# 将 myquota1 的限制值复制给其他四个帐号
[root@www ~]# edquota -p myquota1 -u myquota2
[root@www ~]# edquota -p myquota1 -u myquota3
[root@www ~]# edquota -p myquota1 -u myquota4
[root@www ~]# edquota -p myquota1 -u myquota5

这样就方便多了！然后，赶紧更改一下群组的 quota 限额吧！

[root@www ~]# edquota -g myquotagrp
Disk quotas for group myquotagrp (gid 713):
  Filesystem    blocks    soft     hard  inodes  soft  hard
  /dev/hda3        400  900000  1000000      50     0     0
# 记得，单位为 KB 喔！

最后，将宽限时间给他改成 14 天吧！

# 宽限时间原本为 7 天，将他改成 14 天吧！
[root@www ~]# edquota -t
Grace period before enforcing soft limits for users:
Time units may be: days, hours, minutes, or seconds
  Filesystem         Block grace period     Inode grace period
  /dev/hda3                14days                  7days
# 原本是 7days ，我们将他给改为 14days 喔！

透过这个简单的小步骤，我们已经将使用者/群组/宽限时间都设定妥当！接下来就是观察到底设定有没有生效啦！

小标题的图示 实作 Quota 流程-4：Quota 限制值的报表

quota 的报表主要有两种模式，一种是针对每个个人或群组的 quota 指令，一个是针对整个档案系统的 repquota 指令。 我们先从较简单的 quota 来介绍！你也可以顺道看看你的设定值对不对啊！

  • quota ：单一用户的 quota 报表
[root@www ~]# quota [-uvs] [username]
[root@www ~]# quota [-gvs] [groupname]
选项与参数：
-u  ：后面可以接 username ，表示显示出该使用者的 quota 限制值。若不接 username
      ，表示显示出执行者的 quota 限制值。
-g  ：后面可接 groupname ，表示显示出该群组的 quota 限制值。
-v  ：显示每个用户在 filesystem 的 quota 值；
-s  ：使用 1024 为倍数来指定单位，会显示如 M 之类的单位！

# 直接使用 quota 去显示出 myquota1 与 myquota2 的限额
[root@www ~]# quota -uvs myquota1 myquota2
Disk quotas for user myquota1 (uid 710):
   Filesystem  blocks  quota  limit   grace   files   quota   limit   grace
    /dev/hda3      80   245M   293M              10       0       0
Disk quotas for user myquota2 (uid 711):
   Filesystem  blocks  quota  limit   grace   files   quota   limit   grace
    /dev/hda3      80   245M   293M              10       0       0
# 这个指令显示出来的资料跟 edquota 几乎是一模一样的！只是多了个 grace 项目。
# 你会发现 grace 底下没有任何资料，这是因为我们的使用量 (80) 尚未超过 soft

# 显示出 myquotagrp 的群组限额
[root@www ~]# quota -gvs myquotagrp
Disk quotas for group myquotagrp (gid 713):
   Filesystem  blocks  quota  limit   grace   files   quota   limit   grace
    /dev/hda3     400   879M   977M              50       0       0

由于使用常见的 K, M, G 等单位比较好算，因此上头我们使用了‘ -s ’的选项，就能够以 M 为单位显示了。 不过由于我们使用 edquota 设定限额时，使用的是近似值 (1000) 而不是实际的 1024 倍数， 所以看起来会有点不太一样喔！由于 quota 仅能针对某些用户显示报表，如果要针对整个 filesystem 列出报表时， 那个可爱的 repquota 就派上用场啦！

  • repquota ：针对档案系统的限额做报表
[root@www ~]# repquota -a [-vugs]
选项与参数：
-a  ：直接到 /etc/mtab 搜寻具有 quota 标志的 filesystem ，并报告 quota 的结果；
-v  ：输出的资料将含有 filesystem 相关的细部资讯；
-u  ：显示出使用者的 quota 限值 (这是预设值)；
-g  ：显示出个别群组的 quota 限值。
-s  ：使用 M, G 为单位显示结果

# 查询本案例中所有使用者的 quota 限制情况：
[root@www ~]# repquota -auvs
*** Report for user quotas on device /dev/hda3    <==针对 /dev/hda3
Block grace time: 14days; Inode grace time: 7days <==block 宽限时间为 14 天
                        Block limits                File limits
User            used    soft    hard  grace    used  soft  hard  grace
----------------------------------------------------------------------
root      --    651M       0       0              5     0     0
myquota1  --      80    245M    293M             10     0     0
myquota2  --      80    245M    293M             10     0     0
myquota3  --      80    245M    293M             10     0     0
myquota4  --      80    245M    293M             10     0     0
myquota5  --      80    245M    293M             10     0     0

Statistics:  <==这是所谓的系统相关资讯，用 -v 才会显示
Total blocks: 9
Data blocks: 2
Entries: 22
Used average: 11.000000

根据这些资讯，您就可以知道目前的限制情况啰！ ^_^！怎样， Quota 很简单吧！你可以赶紧针对你的系统设定一下磁碟使用的规则，让你的用户不会抱怨磁碟怎么老是被耗光！

小标题的图示 实作 Quota 流程-5：测试与管理

Quota 到底有没有效果？测试看看不就知道了？让我们使用 myquota1 去测试看看，如果建立一个大档案时， 整个系统会便怎样呢？

# 测试一：利用 myquota1 的身份，建置一个 270MB 的大档案，并观察 quota 结果！
[myquota1@www ~]# dd if=/dev/zero of=bigfile bs=1M count=270
hda3: warning, user block quota exceeded.
270+0 records in
270+0 records out
283115520 bytes (283 MB) copied, 3.20282 seconds, 88.4 MB/s
# 注意看，我是使用 myquota1 的帐号去进行 dd 指令的喔！不要恶搞啊！
# 然后你可以发现出现一个 warning 的讯息喔！接下来看看报表。

[root@www ~]# repquota -auv
*** Report for user quotas on device /dev/hda3
Block grace time: 14days; Inode grace time: 7days
                        Block limits                File limits
User            used    soft    hard  grace    used  soft  hard  grace
----------------------------------------------------------------------
myquota1  +-  276840  250000  300000 13days      11     0     0
# 这个指令则是利用 root 去查阅的！
# 你可以发现 myquota1 的 grace 出现！并且开始倒数了！

# 测试二：再建立另外一个大档案，让总容量超过 300M ！
[myquota1@www ~]# dd if=/dev/zero of=bigfile2 bs=1M count=300
hda3: write failed, user block limit reached.
dd: writing `bigfile2': Disk quota exceeded <==看！错误讯息不一样了！
23+0 records in  <==没办法写入了！所以只记录 23 笔
22+0 records out
23683072 bytes (24 MB) copied, 0.260081 seconds, 91.1 MB/s

[myquota1@www ~]# du -sk
300000  .  <==果然是到极限了！

此时 myquota1 可以开始处理他的档案系统了！如果不处理的话，最后宽限时间会归零，然后出现如下的画面：

[root@www ~]# repquota -au
*** Report for user quotas on device /dev/hda3
Block grace time: 00:01; Inode grace time: 7days
                        Block limits                File limits
User            used    soft    hard  grace    used  soft  hard  grace
----------------------------------------------------------------------
myquota1  +-  300000  250000  300000   none      11     0     0
# 倒数整个归零，所以 grace 的部分就会变成 none 啦！不继续倒数

其实倒数归零也不会有什么特殊的意外啦！别担心！只是如果你的磁碟使用量介于 soft/hard 之间时， 当倒数归零那么 soft 的值会变成严格限制，此时你就没有多余的容量可以使用了。如何解决？ 就登入系统去删除档案即可啦！没有想像中那么可怕啦！问题是，使用者通常傻傻分不清楚到底系统出了什么问题， 所以我们可能需要寄送一些警告信 (email) 给用户比较妥当。那么如何处理呢？透过 warnquota 来处置即可。

  • warnquota ：对超过限额者发出警告信

warnquota字面上的意义就是 quota 的警告 (warn) 嘛！那么这东西有什么用呢？他可以依据 /etc/warnquota.conf 的设定，然后找出目前系统上面 quota 用量超过 soft (就是有 grace time 出现的那些家伙) 的帐号，透过 email 的功能将警告信件发送到使用者的电子邮件信箱。 warnquota 并不会自动执行，所以我们需要手动去执行他。单纯执行‘ warnquota ’之后，他会发送两封信出去， 一封给 myquota1 一封给 root ！

[root@www ~]# warnquota
# 完全不会出现任何讯息！没有讯息就是‘好讯息’！ ^_^

[root@www ~]# mail
 N329 root@www.vbird.tsai   Fri Mar  6 16:10  27/1007  "NOTE: ....
& 329   <==因为新信件在第 329 封之故
From root@www.vbird.tsai  Fri Mar  6 16:10:18 2009
Date: Fri, 6 Mar 2009 16:10:17 +0800
From: root <root@www.vbird.tsai>
Reply-To: root@myhost.com
Subject: NOTE: You are exceeding your allocated disk space limits
To: myquota1@www.vbird.tsai
Cc: root@www.vbird.tsai   <==注意这三行，分别是标题、收件者与副本 (CC)。

Your disk usage has exceeded the agreed limits on this server <==问题说明
Please delete any unnecessary files on following filesystems:

/dev/hda3  <==底下这几行为发生磁碟‘爆表’的资讯啦！
                        Block limits               File limits
Filesystem           used    soft    hard  grace    used  soft  hard  grace
/dev/hda3      +-  300000  250000  300000 13days      12     0     0

root@localhost  <==这个是警告讯息发送者的‘签名资料’啦！

& exit  <==离开 mail 程式！

执行 warnquota 可能也不会产生任何讯息以及信件，因为只有当使用者的 quota 有超过 soft 时， warnquota 才会发送警告信啦！那么上表的内容中，包括标题、资讯内容说明、签名档等资料放在哪里呢？ 刚刚不是讲过吗？ /etc/warnquota 啦！因为上述的资料是英文，不好理解吗？没关系，你可以自己转成中文喔！ 所以你可以这样处理的：

[root@www ~]# vi /etc/warnquota.conf
# 先找到底下这几行的设定值：
SUBJECT   = NOTE: You are exceeding your allocated disk space limits <==第10行
CC_TO     = "root@localhost"                                         <==第11行
MESSAGE   = Your disk usage has exceeded the agreed limits\          <==第21行
 on this server|Please delete any unnecessary files on following filesystems:|
SIGNATURE = root@localhost                                           <==第25行

# 可以将他改成如下的模样啊！
SUBJECT   = 注意：你在本系统上拥有的档案容量已经超过最大容许限额
CC_TO     = "root@localhost"  <==除非你要寄给其他人，否则这个项目可以不改
MESSAGE   = 你的磁碟容量已经超过本机的容许限额，|\
  请在如下的档案系统中，删除不必要的档案：|
SIGNATURE = 你的系统管理员 (root@localhost)
# 在 MESSAGE 内的 | 代表断行的意思，反斜线则代表连接下一行；

如果你重复执行 warnquota ，那么 myquota1 就会收到类似如下的信件内容：

Subject: 注意：你在本系统上拥有的档案容量已经超过最大容许限额
To: myquota1@www.vbird.tsai
Cc: root@www.vbird.tsai

你的磁碟容量已经超过本机的容许限额，
  请在如下的档案系统中，删除不必要的档案：

/dev/hda3

Filesystem           used    soft    hard  grace    used  soft  hard  grace
/dev/hda3      +-  300000  250000  300000   none      11     0     0

你的系统管理员 (root@localhost)

不过这个方法并不适用在 /var/spool/mail 也爆表的 quota 控管中，因为如果使用者在这个 filesystem 的容量已经爆表，那么新的信件当然就收不下来啦！此时就只能等待使用者自己发现并跑来这里删除资料， 或者是请求 root 帮忙处理啰！知道了这玩意儿这么好用，那么我们怎么让系统自动的执行 warnquota 呢？ 你可以这样做：

[root@www ~]# vi /etc/cron.daily/warnquota
/usr/sbin/warnquota
# 你没有看错！只要这一行，且将执行档以绝对路径的方式写入即可！

[root@www ~]# chmod 755 /etc/cron.daily/warnquota

那么未来每天早上 4:02am 时，这个档案就会主动被执行，那么系统就能够主动的通知磁碟配额爆表的用户啰！ 您瞧瞧！这玩意儿是否很好用啊！至于为何要写入上述的档案呢？留待下一章工作排程时我们再来加强介绍啰！

  • setquota ：直接于指令中设定 quota 限额

如果你想要使用 script 的方法来建立大量的帐号，并且所有的帐号都在建立时就给予 quota ，那该如何是好？ 其实有两个方法可以考虑：

  • 先建立一个原始 quota 帐号，再以‘ edquota -p old -u new ’写入 script 中；
  • 直接以 setquota 建立用户的 quota 设定值。

不同于 edquota 是呼叫 vi 来进行设定，setquota 直接由指令输入所必须要的各项限制值。 他的语法有点像这样：

[root@www ~]# setquota [-u|-g] 名称 block(soft) block(hard) \
>  inode(soft) inode(hard) 档案系统

# 观察原始的 myquota5 限值，并给予 soft/hard 分别为 100000/200000
[root@www ~]# quota -uv myquota5
Disk quotas for user myquota5 (uid 714):
   Filesystem blocks  quota  limit  grace files  quota  limit  grace
    /dev/hda3     80 250000 300000           10      0      0

[root@www ~]# setquota -u myquota5 100000 200000 0 0 /home

[root@www ~]# quota -uv myquota5
Disk quotas for user myquota5 (uid 714):
   Filesystem blocks  quota  limit  grace files  quota  limit  grace
    /dev/hda3     80 100000 200000           10      0      0
# 看吧！真的有改变过来！这就是 quota 的简单脚本设定语法！

小标题的图示 不更动既有系统的 quota 实例

想一想，如果你的主机原先没有想到要设定成为邮件主机，所以并没有规划将邮件信箱所在的 /var/spool/mail/ 目录独立成为一个 partition ，然后目前你的主机已经没有办法新增或分割出任何新的分割槽了。那我们知道 quota 是针对整个 filesystem 进行设计的，因此，你是否就无法针对 mail 的使用量给予 quota 的限制呢？

此外，如果你想要让使用者的邮件信箱与家目录的总体磁碟使用量为固定，那又该如何是好？ 由于 /home 及 /var/spool/mail 根本不可能是同一个 filesystem (除非是都不分割，使用根目录，才有可能整合在一起)， 所以，该如何进行这样的 quota 限制呢？

其实没有那么难啦！既然 quota 是针对整个 filesystem 来进行限制，假设你又已经有 /home 这个独立的分割槽了， 那么你只要：

  1. 将 /var/spool/mail 这个目录完整的移动到 /home 底下；
  2. 利用 ln -s /home/mail /var/spool/mail 来建立连结资料；
  3. 将 /home 进行 quota 限额设定

只要这样的一个小步骤，嘿嘿！您家主机的邮件就有一定的限额啰！当然啰！您也可以依据不同的使用者与群组来设定 quota 然后同样的以上面的方式来进行 link 的动作！嘿嘿嘿！就有不同的限额针对不同的使用者提出啰！很方便吧！ ^_^

Tips:
朋友们需要注意的是，由于目前新的 distributions 大多有使用 SELinux 的机制， 因此你要进行如同上面的目录搬移时，在许多情况下可能会有使用上的限制喔！或许你得要先暂时关闭 SELinux 才能测试， 也或许你得要自行修改 SELinux 的规则才行喔！ 		鸟哥的图示
大标题的图示 软体磁碟阵列 (Software RAID)

在过去鸟哥还年轻的时代，我们能使用的硬碟容量都不大，几十 GB 的容量就是大硬碟了！但是某些情况下，我们需要很大容量的储存空间， 例如鸟哥在跑的空气品质模式所输出的资料档案一个案例通常需要好几 GB ，连续跑个几个案例，磁碟容量就不够用了。 此时我该如何是好？其实可以透过一种储存机制，称为磁碟阵列 (RAID) 的就是了。这种机制的功能是什么？他有哪些等级？什么是硬体、软体磁碟阵列？Linux 支援什么样的软体磁碟阵列？ 底下就让我们来谈谈！

小标题的图示 什么是 RAID

磁碟阵列全名是‘ Redundant Arrays of Inexpensive Disks, RAID ’，英翻中的意思是：容错式廉价磁碟阵列。 RAID 可以透过一个技术(软体或硬体)，将多个较小的磁碟整合成为一个较大的磁碟装置； 而这个较大的磁碟功能可不止是储存而已，他还具有资料保护的功能呢。整个 RAID 由于选择的等级 (level) 不同，而使得整合后的磁碟具有不同的功能， 基本常见的 level 有这几种(注1)：

  • RAID-0 (等量模式, stripe)：效能最佳

这种模式如果使用相同型号与容量的磁碟来组成时，效果较佳。这种模式的 RAID 会将磁碟先切出等量的区块 (举例来说， 4KB)， 然后当一个档案要写入 RAID 时，该档案会依据区块的大小切割好，之后再依序放到各个磁碟里面去。由于每个磁碟会交错的存放资料， 因此当你的资料要写入 RAID 时，资料会被等量的放置在各个磁碟上面。举例来说，你有两颗磁碟组成 RAID-0 ， 当你有 100MB 的资料要写入时，每个磁碟会各被分配到 50MB 的储存量。RAID-0 的示意图如下所示：

RAID-0 的磁碟写入示意图
图 2.1.1、 RAID-0 的磁碟写入示意图

上图的意思是，在组成 RAID-0 时，每颗磁碟 (Disk A 与 Disk B) 都会先被区隔成为小区块 (chunk)。 当有资料要写入 RAID 时，资料会先被切割成符合小区块的大小，然后再依序一个一个的放置到不同的磁碟去。 由于资料已经先被切割并且依序放置到不同的磁碟上面，因此每颗磁碟所负责的资料量都降低了！照这样的情况来看， 越多颗磁碟组成的 RAID-0 效能会越好，因为每颗负责的资料量就更低了！ 这表示我的资料可以分散让多颗磁碟来储存，当然效能会变的更好啊！此外，磁碟总容量也变大了！ 因为每颗磁碟的容量最终会加总成为 RAID-0 的总容量喔！

只是使用此等级你必须要自行负担资料损毁的风险，由上图我们知道档案是被切割成为适合每颗磁碟分割区块的大小， 然后再依序放置到各个磁碟中。想一想，如果某一颗磁碟损毁了，那么档案资料将缺一块，此时这个档案就损毁了。 由于每个档案都是这样存放的，因此 RAID-0 只要有任何一颗磁碟损毁，在 RAID 上面的所有资料都会遗失而无法读取。

另外，如果使用不同容量的磁碟来组成 RAID-0 时，由于资料是一直等量的依序放置到不同磁碟中，当小容量磁碟的区块被用完了， 那么所有的资料都将被写入到最大的那颗磁碟去。举例来说，我用 200G 与 500G 组成 RAID-0 ， 那么最初的 400GB 资料可同时写入两颗磁碟 (各消耗 200G 的容量)，后来再加入的资料就只能写入 500G 的那颗磁碟中了。 此时的效能就变差了，因为只剩下一颗可以存放资料嘛！

  • RAID-1 (映射模式, mirror)：完整备份

这种模式也是需要相同的磁碟容量的，最好是一模一样的磁碟啦！如果是不同容量的磁碟组成 RAID-1 时，那么总容量将以最小的那一颗磁碟为主！这种模式主要是‘让同一份资料，完整的保存在两颗磁碟上头’。举例来说，如果我有一个 100MB 的档案，且我仅有两颗磁碟组成 RAID-1 时， 那么这两颗磁碟将会同步写入 100MB 到他们的储存空间去。 因此，整体 RAID 的容量几乎少了 50%。由于两颗硬碟内容一模一样，好像镜子映照出来一样， 所以我们也称他为 mirror 模式啰～

RAID-1 的磁碟写入示意图
图 2.1.2、 RAID-1 的磁碟写入示意图

如上图所示，一份资料传送到 RAID-1 之后会被分为两股，并分别写入到各个磁碟里头去。 由于同一份资料会被分别写入到其他不同磁碟，因此如果要写入 100MB 时，资料传送到 I/O 汇流排后会被复制多份到各个磁碟， 结果就是资料量感觉变大了！因此在大量写入 RAID-1 的情况下，写入的效能可能会变的非常差 (因为我们只有一个南桥啊！)。 好在如果你使用的是硬体 RAID (磁碟阵列卡) 时，磁碟阵列卡会主动的复制一份而不使用系统的 I/O 汇流排，效能方面则还可以。 如果使用软体磁碟阵列，可能效能就不好了。

由于两颗磁碟内的资料一模一样，所以任何一颗硬碟损毁时，你的资料还是可以完整的保留下来的！ 所以我们可以说， RAID-1 最大的优点大概就在于资料的备份吧！不过由于磁碟容量有一半用在备份， 因此总容量会是全部磁碟容量的一半而已。虽然 RAID-1 的写入效能不佳，不过读取的效能则还可以啦！这是因为资料有两份在不同的磁碟上面，如果多个 processes 在读取同一笔资料时， RAID 会自行取得最佳的读取平衡。

  • RAID 0+1，RAID 1+0

RAID-0 的效能佳但是资料不安全，RAID-1 的资料安全但是效能不佳，那么能不能将这两者整合起来设定 RAID 呢？ 可以啊！那就是 RAID 0+1 或 RAID 1+0。所谓的 RAID 0+1 就是： (1)先让两颗磁碟组成 RAID 0，并且这样的设定共有两组； (2)将这两组 RAID 0 再组成一组 RAID 1。这就是 RAID 0+1 啰！反过来说，RAID 1+0 就是先组成 RAID-1 再组成 RAID-0 的意思。

RAID-0+1 的磁碟写入示意图
图 2.1.3、 RAID-0+1 的磁碟写入示意图

如上图所示，Disk A + Disk B 组成第一组 RAID 0，Disk C + Disk D 组成第二组 RAID 0， 然后这两组再整合成为一组 RAID 1。如果我有 100MB 的资料要写入，则由于 RAID 1 的关系， 两组 RAID 0 都会写入 100MB，但由于 RAID 0 的关系，因此每颗磁碟仅会写入 50MB 而已。 如此一来不论哪一组 RAID 0 的磁碟损毁，只要另外一组 RAID 0 还存在，那么就能够透过 RAID 1 的机制来回复资料。

由于具有 RAID 0 的优点，所以效能得以提升，由于具有 RAID 1 的优点，所以资料得以备份。 但是也由于 RAID 1 的缺点，所以总容量会少一半用来做为备份喔！

  • RAID 5：效能与资料备份的均衡考量

RAID-5 至少需要三颗以上的磁碟才能够组成这种类型的磁碟阵列。这种磁碟阵列的资料写入有点类似 RAID-0 ， 不过每个循环的写入过程中，在每颗磁碟还加入一个同位检查资料 (Parity) ，这个资料会记录其他磁碟的备份资料， 用于当有磁碟损毁时的救援。RAID-5 读写的情况有点像底下这样：

RAID-5 的磁碟写入示意图
图 2.1.4、 RAID-5 的磁碟写入示意图

如上图所示，每个循环写入时，都会有部分的同位检查码 (parity) 被记录起来，并且记录的同位检查码每次都记录在不同的磁碟， 因此，任何一个磁碟损毁时都能够藉由其他磁碟的检查码来重建原本磁碟内的资料喔！不过需要注意的是， 由于有同位检查码，因此 RAID 5 的总容量会是整体磁碟数量减一颗。以上图为例， 原本的 3 颗磁碟只会剩下 (3-1)=2 颗磁碟的容量。而且当损毁的磁碟数量大于等于两颗时，这整组 RAID 5 的资料就损毁了。 因为 RAID 5 预设仅能支援一颗磁碟的损毁情况。

在读写效能的比较上，读取的效能还不赖！与 RAID-0 有的比！不过写的效能就不见得能够增加很多！ 这是因为要写入 RAID 5 的资料还得要经过计算同位检查码 (parity) 的关系。由于加上这个计算的动作， 所以写入的效能与系统的硬体关系较大！尤其当使用软体磁碟阵列时，同位检查码是透过 CPU 去计算而非专职的磁碟阵列卡， 因此效能方面还需要评估。

另外，由于 RAID 5 仅能支援一颗磁碟的损毁，因此近来还有发展出另外一种等级，就是 RAID 6 ，这个 RAID 6 则使用两颗磁碟的容量作为 parity 的储存，因此整体的磁碟容量就会少两颗，但是允许出错的磁碟数量就可以达到两颗了！ 也就是在 RAID 6 的情况下，同时两颗磁碟损毁时，资料还是可以救回来！

  • Spare Disk：预备磁碟的功能：

当磁碟阵列的磁碟损毁时，就得要将坏掉的磁碟拔除，然后换一颗新的磁碟。换成新磁碟并且顺利启动磁碟阵列后， 磁碟阵列就会开始主动的重建 (rebuild) 原本坏掉的那颗磁碟资料到新的磁碟上！然后你磁碟阵列上面的资料就复原了！ 这就是磁碟阵列的优点。不过，我们还是得要动手拔插硬碟，此时通常得要关机才能这么做。

为了让系统可以即时的在坏掉硬碟时主动的重建，因此就需要预备磁碟 (spare disk) 的辅助。 所谓的 spare disk 就是一颗或多颗没有包含在原本磁碟阵列等级中的磁碟，这颗磁碟平时并不会被磁碟阵列所使用， 当磁碟阵列有任何磁碟损毁时，则这颗 spare disk 会被主动的拉进磁碟阵列中，并将坏掉的那颗硬碟移出磁碟阵列！ 然后立即重建资料系统。如此你的系统则可以永保安康啊！若你的磁碟阵列有支援热拔插那就更完美了！ 直接将坏掉的那颗磁碟拔除换一颗新的，再将那颗新的设定成为 spare disk ，就完成了！

举例来说，鸟哥之前所待的研究室有一个磁碟阵列可允许 16 颗磁碟的数量，不过我们只安装了 10 颗磁碟作为 RAID 5。 每颗磁碟的容量为 250GB，我们用了一颗磁碟作为 spare disk ，并将其他的 9 颗设定为一个 RAID 5， 因此这个磁碟阵列的总容量为： (9-1)*250G=2000G。运作了一两年后真的有一颗磁碟坏掉了，我们后来看灯号才发现！ 不过对系统没有影响呢！因为 spare disk 主动的加入支援，坏掉的那颗拔掉换颗新的，并重新设定成为 spare 后， 系统内的资料还是完整无缺的！嘿嘿！真不错！

  • 磁碟阵列的优点

说的口沫横飞，重点在哪里呢？其实你的系统如果需要磁碟阵列的话，其实重点在于：

  • 资料安全与可靠性：指的并非资讯安全，而是当硬体 (指磁碟) 损毁时，资料是否还能够安全的救援或使用之意；
  • 读写效能：例如 RAID 0 可以加强读写效能，让你的系统 I/O 部分得以改善；
  • 容量：可以让多颗磁碟组合起来，故单一档案系统可以有相当大的容量。

尤其资料的可靠性与完整性更是使用 RAID 的考量重点！毕竟硬体坏掉换掉就好了，软体资料损毁那可不是闹着玩的！ 所以企业界为何需要大量的 RAID 来做为档案系统的硬体基准，现在您有点了解了吧？

小标题的图示 software, hardware RAID

为何磁碟阵列又分为硬体与软体呢？所谓的硬体磁碟阵列 (hardware RAID) 是透过磁碟阵列卡来达成阵列的目的。 磁碟阵列卡上面有一块专门的晶片在处理 RAID 的任务，因此在效能方面会比较好。在很多任务 (例如 RAID 5 的同位检查码计算) 磁碟阵列并不会重复消耗原本系统的 I/O 汇流排，理论上效能会较佳。此外目前一般的中高阶磁碟阵列卡都支援热拔插， 亦即在不关机的情况下抽换损坏的磁碟，对于系统的复原与资料的可靠性方面非常的好用。

不过一块好的磁碟阵列卡动不动就上万元台币，便宜的在主机板上面‘附赠’的磁碟阵列功能可能又不支援某些高阶功能， 例如低阶主机板若有磁碟阵列晶片，通常仅支援到 RAID0 与 RAID1 ，鸟哥喜欢的 RAID 5 并没有支援。 此外，作业系统也必须要拥有磁碟阵列卡的驱动程式，才能够正确的捉到磁碟阵列所产生的磁碟机！

由于磁碟阵列有很多优秀的功能，然而硬体磁碟阵列卡偏偏又贵的很～因此就有发展出利用软体来模拟磁碟阵列的功能， 这就是所谓的软体磁碟阵列 (software RAID)。软体磁碟阵列主要是透过软体来模拟阵列的任务， 因此会损耗较多的系统资源，比如说 CPU 的运算与 I/O 汇流排的资源等。不过目前我们的个人电脑实在已经非常快速了， 因此以前的速度限制现在已经不存在！所以我们可以来玩一玩软体磁碟阵列！

我们的 CentOS 提供的软体磁碟阵列为 mdadm 这套软体，这套软体会以 partition 或 disk 为磁碟的单位，也就是说，你不需要两颗以上的磁碟，只要有两个以上的分割槽 (partition) 就能够设计你的磁碟阵列了。此外， mdadm 支援刚刚我们前面提到的 RAID0/RAID1/RAID5/spare disk 等！ 而且提供的管理机制还可以达到类似热拔插的功能，可以线上 (档案系统正常使用) 进行分割槽的抽换！ 使用上也非常的方便呢！

另外你必须要知道的是，硬体磁碟阵列在 Linux 底下看起来就是一颗实际的大磁碟，因此硬体磁碟阵列的装置档名为 /dev/sd[a-p] ，因为使用到 SCSI 的模组之故。至于软体磁碟阵列则是系统模拟的，因此使用的装置档名是系统的装置档， 档名为 /dev/md0, /dev/md1...，两者的装置档名并不相同！不要搞混了喔！因为很多朋友常常觉得奇怪， 怎么他的 RAID 档名跟我们这里测试的软体 RAID 档名不同，所以这里特别强调说明喔！

小标题的图示 软体磁碟阵列的设定

软体磁碟阵列的设定很简单呢！简单到让你很想笑喔！因为你只要使用一个指令即可！那就是 mdadm 这个指令。 这个指令在建立 RAID 的语法有点像这样：

[root@www ~]# mdadm --detail /dev/md0
[root@www ~]# mdadm --create --auto=yes /dev/md[0-9] --raid-devices=N \
> --level=[015] --spare-devices=N /dev/sdx /dev/hdx...
选项与参数：
--create ：为建立 RAID 的选项；
--auto=yes ：决定建立后面接的软体磁碟阵列装置，亦即 /dev/md0, /dev/md1...
--raid-devices=N ：使用几个磁碟 (partition) 作为磁碟阵列的装置
--spare-devices=N ：使用几个磁碟作为备用 (spare) 装置
--level=[015] ：设定这组磁碟阵列的等级。支援很多，不过建议只要用 0, 1, 5 即可
--detail ：后面所接的那个磁碟阵列装置的详细资讯

上面的语法中，最后面会接许多的装置档名，这些装置档名可以是整颗磁碟，例如 /dev/sdb ， 也可以是分割槽，例如 /dev/sdb1 之类。不过，这些装置档名的总数必须要等于 --raid-devices 与 --spare-devices 的个数总和才行！鸟哥利用我的测试机来建置一个 RAID 5 的软体磁碟阵列给您瞧瞧！ 首先，将系统里面过去练习过而目前用不到的分割槽通通删除掉：

[root@www ~]# fdisk -l
Disk /dev/hda: 41.1 GB, 41174138880 bytes
255 heads, 63 sectors/track, 5005 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes

   Device Boot      Start         End      Blocks   Id  System
/dev/hda1   *           1          13      104391   83  Linux
/dev/hda2              14        1288    10241437+  83  Linux
/dev/hda3            1289        1925     5116702+  83  Linux
/dev/hda4            1926        5005    24740100    5  Extended
/dev/hda5            1926        2052     1020096   82  Linux swap / Solaris
/dev/hda6            2053        2302     2008093+  83  Linux
/dev/hda7            2303        2334      257008+  82  Linux swap / Solaris
/dev/hda8            2335        2353      152586   83  Linux
/dev/hda9            2354        2366      104391   83  Linux

[root@www ~]# df
Filesystem           1K-blocks      Used Available Use% Mounted on
/dev/hda2              9920624   3858800   5549756  42% /
/dev/hda1               101086     21408     74459  23% /boot
tmpfs                   371332         0    371332   0% /dev/shm
/dev/hda3              4956316   1056996   3643488  23% /home
# 从上面可以发现，我的 /dev/hda6~/dev/hda9 没有用到！将他删除看看！

[root@www ~]# fdisk /dev/hda
Command (m for help): d
Partition number (1-9): 9

Command (m for help): d
Partition number (1-8): 8

Command (m for help): d
Partition number (1-7): 7

Command (m for help): d
Partition number (1-6): 6

Command (m for help): p

Disk /dev/hda: 41.1 GB, 41174138880 bytes
255 heads, 63 sectors/track, 5005 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes

   Device Boot      Start         End      Blocks   Id  System
/dev/hda1   *           1          13      104391   83  Linux
/dev/hda2              14        1288    10241437+  83  Linux
/dev/hda3            1289        1925     5116702+  83  Linux
/dev/hda4            1926        5005    24740100    5  Extended
/dev/hda5            1926        2052     1020096   82  Linux swap / Solaris

Command (m for help): w

[root@www ~]# partprobe
# 这个动作很重要！还记得吧！将核心的 partition table 更新！

底下是鸟哥希望做成的 RAID 5 环境：

  • 利用 4 个 partition 组成 RAID 5；
  • 每个 partition 约为 1GB 大小，需确定每个 partition 一样大较佳；
  • 利用 1 个 partition 设定为 spare disk
  • 这个 spare disk 的大小与其他 RAID 所需 partition 一样大！
  • 将此 RAID 5 装置挂载到 /mnt/raid 目录下

最终我需要 5 个 1GB 的 partition 。由于鸟哥的系统仅有一颗磁碟，这颗磁碟剩余容量约 20GB 是够用的， 分割槽代号仅使用到 5 号，所以要制作成 RAID 5 应该是不成问题！接下来就是连续的建置流程啰！

  • 建置所需的磁碟装置

如前所述，我需要 5 个 1GB 的分割槽，请利用 fdisk 来建置吧！

[root@www ~]# fdisk /dev/hda
Command (m for help): n
First cylinder (2053-5005, default 2053): <==直接按下 [enter]
Using default value 2053
Last cylinder or +size or +sizeM or +sizeK (2053-5005, default 5005): +1000M
# 上述的动作请作五次！

Command (m for help): p

Disk /dev/hda: 41.1 GB, 41174138880 bytes
255 heads, 63 sectors/track, 5005 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes

   Device Boot      Start         End      Blocks   Id  System
/dev/hda1   *           1          13      104391   83  Linux
/dev/hda2              14        1288    10241437+  83  Linux
/dev/hda3            1289        1925     5116702+  83  Linux
/dev/hda4            1926        5005    24740100    5  Extended
/dev/hda5            1926        2052     1020096   82  Linux swap / Solaris
/dev/hda6            2053        2175      987966   83  Linux
/dev/hda7            2176        2298      987966   83  Linux
/dev/hda8            2299        2421      987966   83  Linux
/dev/hda9            2422        2544      987966   83  Linux
/dev/hda10           2545        2667      987966   83  Linux
# 上面的 6~10 号，就是我们需要的 partition 啰！

Command (m for help): w

[root@www ~]# partprobe

  • 以 mdadm 建置 RAID

接下来就简单啦！透过 mdadm 来建立磁碟阵列先！

[root@www ~]# mdadm --create --auto=yes /dev/md0 --level=5 \
> --raid-devices=4 --spare-devices=1 /dev/hda{6,7,8,9,10}
# 详细的参数说明请回去前面看看啰！这里我透过 {} 将重复的项目简化！

[root@www ~]# mdadm --detail /dev/md0
/dev/md0:                                        <==RAID 装置档名
        Version : 00.90.03
  Creation Time : Tue Mar 10 17:47:51 2009       <==RAID 被建立的时间
     Raid Level : raid5                          <==RAID 等级为 RAID 5
     Array Size : 2963520 (2.83 GiB 3.03 GB)     <==此 RAID 的可用磁碟容量
  Used Dev Size : 987840 (964.85 MiB 1011.55 MB) <==每个装置的可用容量
   Raid Devices : 4                              <==用作 RAID 的装置数量
  Total Devices : 5                              <==全部的装置数量
Preferred Minor : 0
    Persistence : Superblock is persistent

    Update Time : Tue Mar 10 17:52:23 2009
          State : clean
 Active Devices : 4                              <==启动的(active)装置数量
Working Devices : 5                              <==可动作的装置数量
 Failed Devices : 0                              <==出现错误的装置数量
  Spare Devices : 1                              <==预备磁碟的数量

         Layout : left-symmetric
     Chunk Size : 64K      <==就是图2.1.4内的小区块

           UUID : 7c60c049:57d60814:bd9a77f1:57e49c5b <==此装置(RAID)识别码
         Events : 0.2

    Number   Major   Minor   RaidDevice State
       0       3        6        0      active sync   /dev/hda6
       1       3        7        1      active sync   /dev/hda7
       2       3        8        2      active sync   /dev/hda8
       3       3        9        3      active sync   /dev/hda9

       4       3       10        -      spare   /dev/hda10
# 最后五行就是这五个装置目前的情况，包括四个 active sync 一个 spare ！
# 至于 RaidDevice  指的则是此 RAID 内的磁碟顺序

由于磁碟阵列的建置需要一些时间，所以你最好等待数分钟后再使用‘ mdadm --detail /dev/md0 ’去查阅你的磁碟阵列详细资讯！ 否则有可能看到某些磁碟正在‘spare rebuilding’之类的建置字样！透过上面的指令， 你就能够建立一个 RAID5 且含有一颗 spare disk 的磁碟阵列啰！非常简单吧！ 除了指令之外，你也可以查阅如下的档案来看看系统软体磁碟阵列的情况：

[root@www ~]# cat /proc/mdstat
Personalities : [raid6] [raid5] [raid4]
md0 : active raid5 hda9[3] hda10[4](S) hda8[2] hda7[1] hda6[0]    <==第一行
      2963520 blocks level 5, 64k chunk, algorithm 2 [4/4] [UUUU] <==第二行

unused devices: <none>

上述的资料比较重要的在特别指出的第一行与第二行部分(注2)：

  • 第一行部分：指出 md0 为 raid5 ，且使用了 hda9, hda8, hda7, hda6 等四颗磁碟装置。每个装置后面的中括号 [] 内的数字为此磁碟在 RAID 中的顺序 (RaidDevice)；至于 hda10 后面的 [S] 则代表 hda10 为 spare 之意。

  • 第二行：此磁碟阵列拥有 2963520 个block(每个 block 单位为 1K)，所以总容量约为 3GB， 使用 RAID 5 等级，写入磁碟的小区块 (chunk) 大小为 64K，使用 algorithm 2 磁碟阵列演算法。 [m/n] 代表此阵列需要 m 个装置，且 n 个装置正常运作。因此本 md0 需要 4 个装置且这 4 个装置均正常运作。 后面的 [UUUU] 代表的是四个所需的装置 (就是 [m/n] 里面的 m) 的启动情况，U 代表正常运作，若为 _ 则代表不正常。

这两种方法都可以知道目前的磁碟阵列状态啦！

  • 格式化与挂载使用 RAID

接下来就是开始使用格式化工具啦！这部分就简单到爆！不多说了，直接进行吧！

[root@www ~]# mkfs -t ext3 /dev/md0
# 有趣吧！是 /dev/md0 做为装置被格式化呢！

[root@www ~]# mkdir /mnt/raid
[root@www ~]# mount /dev/md0 /mnt/raid
[root@www ~]# df
Filesystem     1K-blocks      Used Available Use% Mounted on
/dev/hda2        9920624   3858820   5549736  42% /
/dev/hda1         101086     21408     74459  23% /boot
tmpfs             371332         0    371332   0% /dev/shm
/dev/hda3        4956316   1056996   3643488  23% /home
/dev/md0         2916920     69952   2698792   3% /mnt/raid
# 看吧！多了一个 /dev/md0 的装置，而且真的可以让你使用呢！还不赖！

小标题的图示 模拟 RAID 错误的救援模式

俗话说‘天有不测风云、人有旦夕祸福’，谁也不知道你的磁碟阵列内的装置啥时会出差错，因此， 了解一下软体磁碟阵列的救援还是必须的！底下我们就来玩一玩救援的机制吧！首先来了解一下 mdadm 这方面的语法：

[root@www ~]# mdadm --manage /dev/md[0-9] [--add 装置] [--remove 装置] \
> [--fail 装置]
选项与参数：
--add ：会将后面的装置加入到这个 md 中！
--remove ：会将后面的装置由这个 md 中移除
--fail ：会将后面的装置设定成为出错的状态

  • 设定磁碟为错误 (fault)

首先，我们来处理一下，该如何让一个磁碟变成错误，然后让 spare disk 自动的开始重建系统呢？

# 0. 先复制一些东西到 /mnt/raid 去，假设这个 RAID 已经在使用了
[root@www ~]# cp -a /etc /var/log /mnt/raid
[root@www ~]# df /mnt/raid ; du -sm /mnt/raid/*
Filesystem   1K-blocks      Used Available Use% Mounted on
/dev/md0       2916920    188464   2580280   7% /mnt/raid
118     /mnt/raid/etc <==看吧！确实有资料在里面喔！
8       /mnt/raid/log
1       /mnt/raid/lost+found

# 1. 假设 /dev/hda8 这个装置出错了！实际模拟的方式：
[root@www ~]# mdadm --manage /dev/md0 --fail /dev/hda8
mdadm: set /dev/hda8 faulty in /dev/md0

[root@www ~]# mdadm --detail /dev/md0
....(前面省略)....
          State : clean, degraded, recovering
 Active Devices : 3
Working Devices : 4
 Failed Devices : 1  <==出错的磁碟有一个！
  Spare Devices : 1
....(中间省略)....
    Number   Major   Minor   RaidDevice State
       0       3        6        0      active sync   /dev/hda6
       1       3        7        1      active sync   /dev/hda7
       4       3       10        2      spare rebuilding   /dev/hda10
       3       3        9        3      active sync   /dev/hda9

       5       3        8        -      faulty spare   /dev/hda8
# 看到没！这的动作要快做才会看到！ /dev/hda10 启动了而 /dev/hda8 死掉了

[root@www ~]# cat /proc/mdstat
Personalities : [raid6] [raid5] [raid4]
md0 : active raid5 hda9[3] hda10[4] hda8[5](F) hda7[1] hda6[0]
      2963520 blocks level 5, 64k chunk, algorithm 2 [4/3] [UU_U]
      [>.......]  recovery =  0.8% (9088/987840) finish=14.3min speed=1136K/sec

上面的画面你得要快速的连续输入那些 mdadm 的指令才看的到！因为你的 RAID 5 正在重建系统！ 若你等待一段时间再输入后面的观察指令，则会看到如下的画面了：

# 2. 已经藉由 spare disk 重建完毕的 RAID 5 情况
[root@www ~]# mdadm --detail /dev/md0
....(前面省略)....
    Number   Major   Minor   RaidDevice State
       0       3        6        0      active sync   /dev/hda6
       1       3        7        1      active sync   /dev/hda7
       2       3       10        2      active sync   /dev/hda10
       3       3        9        3      active sync   /dev/hda9

       4       3        8        -      faulty spare   /dev/hda8

[root@www ~]# cat /proc/mdstat
Personalities : [raid6] [raid5] [raid4]
md0 : active raid5 hda9[3] hda10[2] hda8[4](F) hda7[1] hda6[0]
      2963520 blocks level 5, 64k chunk, algorithm 2 [4/4] [UUUU]

看吧！又恢复正常了！真好！我们的 /mnt/raid 档案系统是完整的！并不需要卸载！很棒吧！

  • 将出错的磁碟移除并加入新磁碟

首先，我们再建立一个新的分割槽，这个分割槽要与其他分割槽一样大才好！然后再利用 mdadm 移除错误的并加入新的！

# 3. 建立新的分割槽
[root@www ~]# fdisk /dev/hda
Command (m for help): n
First cylinder (2668-5005, default 2668): <==这里按 [enter]
Using default value 2668
Last cylinder or +size or +sizeM or +sizeK (2668-5005, default 5005): +1000M

Command (m for help): w

[root@www ~]# partprobe
# 此时系统会多一个 /dev/hda11 的分割槽喔！

# 4. 加入新的拔除有问题的磁碟
[root@www ~]# mdadm --manage /dev/md0 --add /dev/hda11 --remove /dev/hda8
mdadm: added /dev/hda11
mdadm: hot removed /dev/hda8

[root@www ~]# mdadm --detail /dev/md0
....(前面省略)....
       0       3        6        0      active sync   /dev/hda6
       1       3        7        1      active sync   /dev/hda7
       2       3       10        2      active sync   /dev/hda10
       3       3        9        3      active sync   /dev/hda9

       4       3       11        -      spare   /dev/hda11

嘿嘿！你的磁碟阵列内的资料不但一直存在，而且你可以一直顺利的运作 /mnt/raid 内的资料，即使 /dev/hda8 损毁了！然后透过管理的功能就能够加入新磁碟且拔除坏掉的磁碟！注意，这一切都是在上线 (on-line) 的情况下进行！ 所以，您说这样的咚咚好不好用啊！ ^_^

小标题的图示 开机自动启动 RAID 并自动挂载

新的 distribution 大多会自己搜寻 /dev/md[0-9] 然后在开机的时候给予设定好所需要的功能。不过鸟哥还是建议你， 修改一下设定档吧！ ^_^。software RAID 也是有设定档的，这个设定档在 /etc/mdadm.conf ！这个设定档内容很简单， 你只要知道 /dev/md0 的 UUID 就能够设定这个档案啦！这里鸟哥仅介绍他最简单的语法：

[root@www ~]# mdadm --detail /dev/md0 | grep -i uuid
        UUID : 7c60c049:57d60814:bd9a77f1:57e49c5b
# 后面那一串资料，就是这个装置向系统注册的 UUID 识别码！

# 开始设定 mdadm.conf
[root@www ~]# vi /etc/mdadm.conf
ARRAY /dev/md0 UUID=7c60c049:57d60814:bd9a77f1:57e49c5b
#     RAID装置      识别码内容

# 开始设定开机自动挂载并测试
[root@www ~]# vi /etc/fstab
/dev/md0    /mnt/raid    ext3    defaults     1 2

[root@www ~]# umount /dev/md0; mount -a
[root@www ~]# df /mnt/raid
Filesystem           1K-blocks      Used Available Use% Mounted on
/dev/md0               2916920    188464   2580280   7% /mnt/raid
# 你得确定可以顺利挂载，并且没有发生任何错误！

如果到这里都没有出现任何问题！接下来就请 reboot 你的系统并等待看看能否顺利的启动吧！ ^_^

小标题的图示 关闭软体 RAID(重要！)

除非你未来就是要使用这颗 software RAID (/dev/md0)，否则你势必要跟鸟哥一样，将这个 /dev/md0 关闭！ 因为他毕竟是我们在这个测试机上面的练习装置啊！为什么要关掉他呢？因为这个 /dev/md0 其实还是使用到我们系统的磁碟分割槽， 在鸟哥的例子里面就是 /dev/hda{6,7,8,9,10,11}，如果你只是将 /dev/md0 卸载，然后忘记将 RAID 关闭， 结果就是....未来你在重新分割 /dev/hdaX 时可能会出现一些莫名的错误状况啦！所以才需要关闭 software RAID 的步骤！ 那如何关闭呢？也是简单到爆炸！(请注意，确认你的 /dev/md0 确实不要用且要关闭了才进行底下的玩意儿)

# 1. 先卸载且删除设定档内与这个 /dev/md0 有关的设定：
[root@www ~]# umount /dev/md0
[root@www ~]# vi /etc/fstab
/dev/md0    /mnt/raid     ext3    defaults      1 2
# 将这一行删除掉！或者是注解掉也可以！

# 2. 直接关闭 /dev/md0 的方法！
[root@www ~]# mdadm --stop /dev/md0
mdadm: stopped /dev/md0  <==不啰唆！这样就关闭了！

[root@www ~]# cat /proc/mdstat
Personalities : [raid6] [raid5] [raid4]
unused devices: <none>  <==看吧！确实不存在任何阵列装置！

[root@www ~]# vi /etc/mdadm.conf
ARRAY /dev/md0 UUID=7c60c049:57d60814:bd9a77f1:57e49c5b
# 一样啦！删除他或是注解他！
Tips:
在这个练习中，鸟哥使用同一颗磁碟进行软体 RAID 的实验。不过朋友们要注意的是，如果真的要实作软体磁碟阵列， 最好是由多颗不同的磁碟来组成较佳！因为这样才能够使用到不同磁碟的读写，效能才会好！ 而资料分配在不同的磁碟，当某颗磁碟损毁时资料才能够藉由其他磁碟挽救回来！这点得特别留意呢！ 		鸟哥的图示
大标题的图示 逻辑卷轴管理员 (Logical Volume Manager)

想像一个情况，你在当初规划主机的时候将 /home 只给他 50G ，等到使用者众多之后导致这个 filesystem 不够大， 此时你能怎么作？多数的朋友都是这样：再加一颗新硬碟，然后重新分割、格式化，将 /home 的资料完整的复制过来， 然后将原本的 partition 卸载重新挂载新的 partition 。啊！好忙碌啊！若是第二次分割却给的容量太多！导致很多磁碟容量被浪费了！ 你想要将这个 partition 缩小时，又该如何作？将上述的流程再搞一遍！唉～烦死了，尤其复制很花时间ㄟ～有没有更简单的方法呢？ 有的！那就是我们这个小节要介绍的 LVM 这玩意儿！

LVM 的重点在于‘可以弹性的调整 filesystem 的容量！’而并非在于效能与资料保全上面。 需要档案的读写效能或者是资料的可靠性，请参考前面的 RAID 小节。 LVM 可以整合多个实体 partition 在一起， 让这些 partitions 看起来就像是一个磁碟一样！而且，还可以在未来新增或移除其他的实体 partition 到这个 LVM 管理的磁碟当中。 如此一来，整个磁碟空间的使用上，实在是相当的具有弹性啊！ 既然 LVM 这么好用，那就让我们来瞧瞧这玩意吧！

小标题的图示 什么是 LVM： PV, PE, VG, LV 的意义

LVM 的全名是 Logical Volume Manager，中文可以翻译作逻辑卷轴管理员。之所以称为‘卷轴’可能是因为可以将 filesystem 像卷轴一样伸长或缩短之故吧！LVM 的作法是将几个实体的 partitions (或 disk) 透过软体组合成为一块看起来是独立的大磁碟 (VG) ，然后将这块大磁碟再经过分割成为可使用分割槽 (LV)， 最终就能够挂载使用了。但是为什么这样的系统可以进行 filesystem 的扩充或缩小呢？其实与一个称为 PE 的项目有关！ 底下我们就得要针对这几个项目来好好聊聊！

  • Physical Volume, PV, 实体卷轴

我们实际的 partition 需要调整系统识别码 (system ID) 成为 8e (LVM 的识别码)，然后再经过 pvcreate 的指令将他转成 LVM 最底层的实体卷轴 (PV) ，之后才能够将这些 PV 加以利用！ 调整 system ID 的方是就是透过 fdisk 啦！

  • Volume Group, VG, 卷轴群组

所谓的 LVM 大磁碟就是将许多 PV 整合成这个 VG 的东西就是啦！所以 VG 就是 LVM 组合起来的大磁碟！这么想就好了。 那么这个大磁碟最大可以到多少容量呢？这与底下要说明的 PE 有关喔～因为每个 VG 最多仅能包含 65534 个 PE 而已。 如果使用 LVM 预设的参数，则一个 VG 最大可达 256GB 的容量啊！(参考底下的 PE 说明)

  • Physical Extend, PE, 实体延伸区块

LVM 预设使用 4MB 的 PE 区块，而 LVM 的 VG 最多仅能含有 65534 个 PE ，因此预设的 LVM VG 会有 4M*65534/(1024M/G)=256G。 这个 PE 很有趣喔！他是整个 LVM 最小的储存区块，也就是说，其实我们的档案资料都是藉由写入 PE 来处理的。 简单的说，这个 PE 就有点像档案系统里面的 block 大小啦。 这样说应该就比较好理解了吧？所以调整 PE 会影响到 VG 的最大容量喔！

  • Logical Volume, LV, 逻辑卷轴

最终的 VG 还会被切成 LV，这个 LV 就是最后可以被格式化使用的类似分割槽的咚咚了！那么 LV 是否可以随意指定大小呢？ 当然不可以！既然 PE 是整个 LVM 的最小储存单位，那么 LV 的大小就与在此 LV 内的 PE 总数有关。 为了方便使用者利用 LVM 来管理其系统，因此 LV 的装置档名通常指定为‘ /dev/vgname/lvname ’的样式！

此外，我们刚刚有谈到 LVM 可弹性的变更 filesystem 的容量，那是如何办到的？其实他就是透过‘交换 PE ’来进行资料转换， 将原本 LV 内的 PE 移转到其他装置中以降低 LV 容量，或将其他装置的 PE 加到此 LV 中以加大容量！ VG、LV 与 PE 的关系有点像下图：

PE 与 VG 的相关性图示
图 3.1.1、PE 与 VG 的相关性图示

如上图所示，VG 内的 PE 会分给虚线部分的 LV，如果未来这个 VG 要扩充的话，加上其他的 PV 即可。 而最重要的 LV 如果要扩充的话，也是透过加入 VG 内没有使用到的 PE 来扩充的！

  • 实作流程

透过 PV, VG, LV 的规划之后，再利用 mkfs 就可以将你的 LV 格式化成为可以利用的档案系统了！而且这个档案系统的容量在未来还能够进行扩充或减少， 而且里面的资料还不会被影响！实在是很‘福气啦！’那实作方面要如何进行呢？很简单呢！ 整个流程由基础到最终的结果可以这样看：

LVM 各元件的实现流程图示
图 3.1.2、 LVM 各元件的实现流程图示

如此一来，我们就可以利用 LV 这个玩意儿来进行系统的挂载了。不过，你应该要觉得奇怪的是， 那么我的资料写入这个 LV 时，到底他是怎么写入硬碟当中的？ 呵呵！好问题～其实，依据写入机制的不同，而有两种方式：

  • 线性模式 (linear)：假如我将 /dev/hda1, /dev/hdb1 这两个 partition 加入到 VG 当中，并且整个 VG 只有一个 LV 时，那么所谓的线性模式就是：当 /dev/hda1 的容量用完之后，/dev/hdb1 的硬碟才会被使用到， 这也是我们所建议的模式。

  • 交错模式 (triped)：那什么是交错模式？很简单啊，就是我将一笔资料拆成两部分，分别写入 /dev/hda1 与 /dev/hdb1 的意思，感觉上有点像 RAID 0 啦！如此一来，一份资料用两颗硬碟来写入，理论上，读写的效能会比较好。

基本上，LVM 最主要的用处是在实现一个可以弹性调整容量的档案系统上， 而不是在建立一个效能为主的磁碟上，所以，我们应该利用的是 LVM 可以弹性管理整个 partition 大小的用途上，而不是着眼在效能上的。因此， LVM 预设的读写模式是线性模式啦！ 如果你使用 triped 模式，要注意，当任何一个 partition ‘归天’时，所有的资料都会‘损毁’的！ 所以啦，不是很适合使用这种模式啦！如果要强调效能与备份，那么就直接使用 RAID 即可， 不需要用到 LVM 啊！

小标题的图示 LVM 实作流程

LVM 必需要核心有支援且需要安装 lvm2 这个软体，好佳在的是， CentOS 与其他较新的 distributions 已经预设将 lvm 的支援与软体都安装妥当了！所以你不需要担心这方面的问题！用就对了！

鸟哥使用的测试机又要出动了喔！刚刚我们才练习过 RAID，必须要将一堆目前没有用到的分割槽先杀掉， 然后再重建新的分割槽。并且由于鸟哥仅有一个 40GB 的磁碟，所以底下的练习都仅针对同一颗磁碟来作的。 我的要求有点像这样：

  • 先分割出 4 个 partition ，每个 partition 的容量均为 1.5GB 左右，且 system ID 需要为 8e；
  • 全部的 partition 整合成为一个 VG，VG 名称设定为 vbirdvg；且 PE 的大小为 16MB；
  • 全部的 VG 容量都丢给 LV ，LV 的名称设定为 vbirdlv；
  • 最终这个 LV 格式化为 ext3 的档案系统，且挂载在 /mnt/lvm 中

鸟哥就不仔细的介绍实体分割了，请您自行参考第八章的 fdisk 来达成底下的范例：(注意：修改系统识别码请使用 t 这个 fdisk 内的指令来处理即可)

[root@www ~]# fdisk /dev/hda  <==其他流程请自行参考第八章处理
[root@www ~]# partprobe       <==别忘记这个动作了！粉重要！
[root@www ~]# fdisk -l
Disk /dev/hda: 41.1 GB, 41174138880 bytes
255 heads, 63 sectors/track, 5005 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes

   Device Boot      Start         End      Blocks   Id  System
/dev/hda1   *           1          13      104391   83  Linux
/dev/hda2              14        1288    10241437+  83  Linux
/dev/hda3            1289        1925     5116702+  83  Linux
/dev/hda4            1926        5005    24740100    5  Extended
/dev/hda5            1926        2052     1020096   82  Linux swap / Solaris
/dev/hda6            2053        2235     1469916   8e  Linux LVM
/dev/hda7            2236        2418     1469916   8e  Linux LVM
/dev/hda8            2419        2601     1469916   8e  Linux LVM
/dev/hda9            2602        2784     1469916   8e  Linux LVM

上面的 /dev/hda{6,7,8,9} 这四个分割槽就是我们的实体分割槽！也就是底下会实际用到的资讯！ 注意看，那个 8e 的出现会导致 system 变成‘ Linux LVM ’哩！其实没有设定成为 8e 也没关系， 不过某些 LVM 的侦测指令可能会侦测不到该 partition 就是了！接下来，就一个一个的处理各流程吧！

  • PV 阶段

要建立 PV 其实很简单，只要直接使用 pvcreate 即可！我们来谈一谈与 PV 有关的指令吧！

  • pvcreate ：将实体 partition 建立成为 PV ；
  • pvscan ：搜寻目前系统里面任何具有 PV 的磁碟；
  • pvdisplay ：显示出目前系统上面的 PV 状态；
  • pvremove ：将 PV 属性移除，让该 partition 不具有 PV 属性。

那就直接来瞧一瞧吧！

# 1. 检查有无 PV 在系统上，然后将 /dev/hda6~/dev/hda9 建立成为 PV 格式
[root@www ~]# pvscan
  No matching physical volumes found <==找不到任何的 PV 存在喔！

[root@www ~]# pvcreate /dev/hda{6,7,8,9}
  Physical volume "/dev/hda6" successfully created
  Physical volume "/dev/hda7" successfully created
  Physical volume "/dev/hda8" successfully created
  Physical volume "/dev/hda9" successfully created
# 这个指令可以一口气建立这四个 partition 成为 PV 啦！注意大括号的用途

[root@www ~]# pvscan
  PV /dev/hda6         lvm2 [1.40 GB]
  PV /dev/hda7         lvm2 [1.40 GB]
  PV /dev/hda8         lvm2 [1.40 GB]
  PV /dev/hda9         lvm2 [1.40 GB]
  Total: 4 [5.61 GB] / in use: 0 [0   ] / in no VG: 4 [5.61 GB]
# 这就分别显示每个 PV 的资讯与系统所有 PV 的资讯。尤其最后一行，显示的是：
# 整体 PV 的量 / 已经被使用到 VG 的 PV 量 / 剩余的 PV 量

# 2. 更详细的列示出系统上面每个 PV 的个别资讯：
[root@www ~]# pvdisplay
  "/dev/hda6" is a new physical volume of "1.40 GB"
  --- NEW Physical volume ---
  PV Name               /dev/hda6  <==实际的 partition 装置名称
  VG Name                          <==因为尚未分配出去，所以空白！
  PV Size               1.40 GB    <==就是容量说明
  Allocatable           NO         <==是否已被分配，结果是 NO
  PE Size (KByte)       0          <==在此 PV 内的 PE 大小
  Total PE              0          <==共分割出几个 PE
  Free PE               0          <==没被 LV 用掉的 PE
  Allocated PE          0          <==尚可分配出去的 PE 数量
  PV UUID               Z13Jk5-RCls-UJ8B-HzDa-Gesn-atku-rf2biN
....(底下省略)....
# 由于 PE 是在建立 VG 时才给予的参数，因此在这里看到的 PV 里头的 PE 都会是 0
# 而且也没有多余的 PE 可供分配 (allocatable)。

讲是很难，作是很简单！这样就将 PV 建立了两个啰！简单到不行吧！ ^_^！继续来玩 VG 去！

  • VG 阶段

建立 VG 及 VG 相关的指令也不少，我们来看看：

  • vgcreate ：就是主要建立 VG 的指令啦！他的参数比较多，等一下介绍。
  • vgscan ：搜寻系统上面是否有 VG 存在？
  • vgdisplay ：显示目前系统上面的 VG 状态；
  • vgextend ：在 VG 内增加额外的 PV ；
  • vgreduce ：在 VG 内移除 PV；
  • vgchange ：设定 VG 是否启动 (active)；
  • vgremove ：删除一个 VG 啊！

与 PV 不同的是， VG 的名称是自订的！我们知道 PV 的名称其实就是 partition 的装置代号， 但是这个 VG 名称则可以随便你自己取啊！在底下的例子当中，我将 VG 名称取名为 vbirdvg 。建立这个 VG 的流程是这样的：

[root@www ~]# vgcreate [-s N[mgt]] VG名称 PV名称
选项与参数：
-s ：后面接 PE 的大小 (size) ，单位可以是 m, g, t (大小写均可)

# 1. 将 /dev/hda6-8 建立成为一个 VG，且指定 PE 为 16MB 喔！
[root@www ~]# vgcreate -s 16M vbirdvg /dev/hda{6,7,8}
  Volume group "vbirdvg" successfully created

[root@www ~]# vgscan
  Reading all physical volumes.  This may take a while...
  Found volume group "vbirdvg" using metadata type lvm2
# 确实存在这个 vbirdvg 的 VG 啦！

[root@www ~]# pvscan
  PV /dev/hda6   VG vbirdvg   lvm2 [1.39 GB / 1.39 GB free]
  PV /dev/hda7   VG vbirdvg   lvm2 [1.39 GB / 1.39 GB free]
  PV /dev/hda8   VG vbirdvg   lvm2 [1.39 GB / 1.39 GB free]
  PV /dev/hda9                lvm2 [1.40 GB]
  Total: 4 [5.57 GB] / in use: 3 [4.17 GB] / in no VG: 1 [1.40 GB]
# 嘿嘿！发现没！有三个 PV 被用去，剩下一个 /dev/hda9 的 PV 没被用掉！

[root@www ~]# vgdisplay
  --- Volume group ---
  VG Name               vbirdvg
  System ID
  Format                lvm2
  Metadata Areas        3
  Metadata Sequence No  1
  VG Access             read/write
  VG Status             resizable
  MAX LV                0
  Cur LV                0
  Open LV               0
  Max PV                0
  Cur PV                3
  Act PV                3
  VG Size               4.17 GB   <==整体的 VG 容量有这么大
  PE Size               16.00 MB  <==内部每个 PE 的大小
  Total PE              267       <==总共的 PE 数量共有这么多！
  Alloc PE / Size       0 / 0
  Free  PE / Size       267 / 4.17 GB
  VG UUID               4VU5Jr-gwOq-jkga-sUPx-vWPu-PmYm-dZH9EO
# 最后那三行指的就是 PE 能够使用的情况！由于尚未切出 LV，因此所有的 PE
# 均可自由使用。

这样就建立一个 VG 了！假设我们要增加这个 VG 的容量，因为我们还有 /dev/hda9 嘛！此时你可以这样做：

# 2. 将剩余的 PV (/dev/hda9) 丢给 vbirdvg 吧！
[root@www ~]# vgextend vbirdvg /dev/hda9
  Volume group "vbirdvg" successfully extended

[root@www ~]# vgdisplay
....(前面省略)....
  VG Size               5.56 GB
  PE Size               16.00 MB
  Total PE              356
  Alloc PE / Size       0 / 0
  Free  PE / Size       356 / 5.56 GB
  VG UUID               4VU5Jr-gwOq-jkga-sUPx-vWPu-PmYm-dZH9EO
# 基本上，不难吧！这样就可以抽换整个 VG 的大小啊！

我们多了一个装置喔！接下来为这个 vbirdvg 进行分割吧！透过 LV 功能来处理！

  • LV 阶段

创造出 VG 这个大磁碟之后，再来就是要建立分割区啦！这个分割区就是所谓的 LV 啰！假设我要将刚刚那个 vbirdvg 磁碟，分割成为 vbirdlv ，整个 VG 的容量都被分配到 vbirdlv 里面去！先来看看能使用的指令后，就直接工作了先！

  • lvcreate ：建立 LV 啦！
  • lvscan ：查询系统上面的 LV ；
  • lvdisplay ：显示系统上面的 LV 状态啊！
  • lvextend ：在 LV 里面增加容量！
  • lvreduce ：在 LV 里面减少容量；
  • lvremove ：删除一个 LV ！
  • lvresize ：对 LV 进行容量大小的调整！
[root@www ~]# lvcreate [-L N[mgt]] [-n LV名称] VG名称
[root@www ~]# lvcreate [-l N] [-n LV名称] VG名称
选项与参数：
-L  ：后面接容量，容量的单位可以是 M,G,T 等，要注意的是，最小单位为 PE，
      因此这个数量必须要是 PE 的倍数，若不相符，系统会自行计算最相近的容量。
-l  ：后面可以接 PE 的‘个数’，而不是数量。若要这么做，得要自行计算 PE 数。
-n  ：后面接的就是 LV 的名称啦！
更多的说明应该可以自行查阅吧！ man lvcreate

# 1. 将整个 vbirdvg 通通分配给 vbirdlv 啊，要注意， PE 共有 356 个。
[root@www ~]# lvcreate -l 356 -n vbirdlv vbirdvg
  Logical volume "vbirdlv" created
# 由于本案例中每个 PE 为 16M ，因此上述的指令也可以使用如下的方式来建立：
# lvcreate -L 5.56G -n vbirdlv vbirdvg

[root@www ~]# ll /dev/vbirdvg/vbirdlv
lrwxrwxrwx 1 root root 27 Mar 11 16:49 /dev/vbirdvg/vbirdlv ->
/dev/mapper/vbirdvg-vbirdlv
# 看见了没有啊！这就是我们最重要的一个玩意儿了！

[root@www ~]# lvdisplay
  --- Logical volume ---
  LV Name                /dev/vbirdvg/vbirdlv  <==这个才是 LV 的全名！
  VG Name                vbirdvg
  LV UUID                8vFOPG-Jrw0-Runh-ug24-t2j7-i3nA-rPEyq0
  LV Write Access        read/write
  LV Status              available
  # open                 0
  LV Size                5.56 GB               <==这个 LV 的容量这么大！
  Current LE             356
  Segments               4
  Allocation             inherit
  Read ahead sectors     auto
  - currently set to     256
  Block device           253:0

如此一来，整个 partition 也准备好啦！接下来，就是针对这个 LV 来处理啦！要特别注意的是， VG 的名称为 vbirdvg ， 但是 LV 的名称必须使用全名！亦即是 /dev/vbirdvg/vbirdlv 才对喔！ 后续的处理都是这样的！这点初次接触 LVM 的朋友很容易搞错！

  • 档案系统阶段

这个部分鸟哥我就不再多加解释了！直接来进行吧！

# 1. 格式化、挂载与观察我们的 LV 吧！
[root@www ~]# mkfs -t ext3 /dev/vbirdvg/vbirdlv <==注意 LV 全名！
[root@www ~]# mkdir /mnt/lvm
[root@www ~]# mount /dev/vbirdvg/vbirdlv /mnt/lvm
[root@www ~]# df
Filesystem           1K-blocks      Used Available Use% Mounted on
/dev/hda2              9920624   3858984   5549572  42% /
/dev/hda3              4956316   1056996   3643488  23% /home
/dev/hda1               101086     21408     74459  23% /boot
tmpfs                   371332         0    371332   0% /dev/shm
/dev/mapper/vbirdvg-vbirdlv
                       5741020    142592   5306796   3% /mnt/lvm
[root@www ~]# cp -a /etc /var/log /mnt/lvm

其实 LV 的名称建置成为 /dev/vbirdvg/vbirdlv 是为了让使用者直觉式的找到我们所需要的资料， 实际上 LVM 使用的装置是放置到 /dev/mapper/ 目录下的！所以你才会看到上表当中的特殊字体部分。 透过这样的功能，我们现在已经建置好一个 LV 了！你可以自由的应用 /mnt/lvm 内的所有资源！

小标题的图示 放大 LV 容量

我们不是说 LVM 最大的特色就是弹性调整磁碟容量吗？好！那我们就来处理一下，如果要放大 LV 的容量时， 该如何进行完整的步骤呢？其实一点都不难喔！你只要这样做即可：

  1. 用 fdisk 设定新的具有 8e system ID 的 partition
  2. 利用 pvcreate 建置 PV
  3. 利用 vgextend 将 PV 加入我们的 vbirdvg
  4. 利用 lvresize 将新加入的 PV 内的 PE 加入 vbirdlv 中
  5. 透过 resize2fs 将档案系统的容量确实增加！

其中最后一个步骤最重要！我们在第八章当中知道， 整个档案系统在最初格式化的时候就建立了 inode/block/superblock 等资讯，要改变这些资讯是很难的！ 不过因为档案系统格式化的时候建置的是多个 block group ，因此我们可以透过在档案系统当中增加 block group 的方式来增减档案系统的量！而增减 block group 就是利用 resize2fs 啦！所以最后一步是针对档案系统来处理的， 前面几步则是针对 LVM 的实际容量大小！

# 1. 处理出一个 3GB 的新的 partition ，在鸟哥的系统中应该是 /dev/hda10
[root@www ~]# fdisk /dev/hda <==其他的动作请自行处理
[root@www ~]# partprobe
[root@www ~]# fdisk -l
   Device Boot      Start         End      Blocks   Id  System
....(中间省略)....
/dev/hda10           2785        3150     2939863+  8e  Linux LVM
# 这个就是我们要的新的 partition 啰！

# 2. 建立新的 PV：
[root@www ~]# pvcreate /dev/hda10
  Physical volume "/dev/hda10" successfully created
[root@www ~]# pvscan
  PV /dev/hda6    VG vbirdvg   lvm2 [1.39 GB / 0    free]
  PV /dev/hda7    VG vbirdvg   lvm2 [1.39 GB / 0    free]
  PV /dev/hda8    VG vbirdvg   lvm2 [1.39 GB / 0    free]
  PV /dev/hda9    VG vbirdvg   lvm2 [1.39 GB / 0    free]
  PV /dev/hda10                lvm2 [2.80 GB]
  Total: 5 [8.37 GB] / in use: 4 [5.56 GB] / in no VG: 1 [2.80 GB]
# 可以看到 /dev/hda10 是新加入并且尚未被使用的喔！

# 3. 加大 VG ，利用 vgextend 功能！
[root@www ~]# vgextend vbirdvg /dev/hda10
  Volume group "vbirdvg" successfully extended
[root@www ~]# vgdisplay
  --- Volume group ---
  VG Name               vbirdvg
  System ID
  Format                lvm2
  Metadata Areas        5
  Metadata Sequence No  4
  VG Access             read/write
  VG Status             resizable
  MAX LV                0
  Cur LV                1
  Open LV               1
  Max PV                0
  Cur PV                5
  Act PV                5
  VG Size               8.36 GB
  PE Size               16.00 MB
  Total PE              535
  Alloc PE / Size       356 / 5.56 GB
  Free  PE / Size       179 / 2.80 GB
  VG UUID               4VU5Jr-gwOq-jkga-sUPx-vWPu-PmYm-dZH9EO
# 不但整体 VG 变大了！而且剩余的 PE 共有 179 个，容量则为 2.80G

# 4. 放大 LV 吧！利用 lvresize 的功能来增加！
[root@www ~]# lvresize -l +179 /dev/vbirdvg/vbirdlv
  Extending logical volume vbirdlv to 8.36 GB
  Logical volume vbirdlv successfully resized
# 这样就增加了 LV 了喔！lvresize 的语法很简单，基本上同样透过 -l 或 -L 来增加！
# 若要增加则使用 + ，若要减少则使用 - ！详细的选项请参考 man lvresize 啰！

[root@www ~]# lvdisplay
  --- Logical volume ---
  LV Name                /dev/vbirdvg/vbirdlv
  VG Name                vbirdvg
  LV UUID                8vFOPG-Jrw0-Runh-ug24-t2j7-i3nA-rPEyq0
  LV Write Access        read/write
  LV Status              available
  # open                 1
  LV Size                8.36 GB
  Current LE             535
  Segments               5
  Allocation             inherit
  Read ahead sectors     auto
  - currently set to     256
  Block device           253:0

[root@www ~]# df /mnt/lvm
Filesystem           1K-blocks      Used Available Use% Mounted on
/dev/mapper/vbirdvg-vbirdlv
                       5741020    261212   5188176   5% /mnt/lvm

看到了吧？最终的结果中 LV 真的有放大到 8.36GB 喔！但是档案系统却没有相对增加！ 而且，我们的 LVM 可以线上直接处理，并不需要特别给他 umount 哩！真是人性化！ 但是还是得要处理一下档案系统的容量啦！开始观察一下档案系统，然后使用 resize2fs 来处理一下吧！

# 5.1 先看一下原本的档案系统内的 superblock 记录情况吧！
[root@www ~]# dumpe2fs /dev/vbirdvg/vbirdlv
dumpe2fs 1.39 (29-May-2006)
....(中间省略)....
Block count:              1458176    <==这个filesystem的 block 总数
....(中间省略)....
Blocks per group:         32768      <==多少个 block 设定成为一个 block group
Group 0: (Blocks 0-32767)            <==括号内为 block 的号码
....(中间省略)....
Group 44: (Blocks 1441792-1458175)   <==这是本系统中最后一个 group
....(后面省略)....

# 5.2 resize2fs 的语法
[root@www ~]# resize2fs [-f] [device] [size]
选项与参数：
-f      ：强制进行 resize 的动作！
[device]：装置的档案名称；
[size]  ：可以加也可以不加。如果加上 size 的话，那么就必须要给予一个单位，
          譬如 M, G 等等。如果没有 size 的话，那么预设使用‘整个 partition’
          的容量来处理！

# 5.3 完整的将 LV 的容量扩充到整个 filesystem 吧！
[root@www ~]# resize2fs /dev/vbirdvg/vbirdlv
resize2fs 1.39 (29-May-2006)
Filesystem at /dev/vbirdvg/vbirdlv is mounted on /mnt/lvm; on-line resizing
Performing an on-line resize of /dev/vbirdvg/vbirdlv to 2191360 (4k) blocks.
The filesystem on /dev/vbirdvg/vbirdlv is now 2191360 blocks long.
# 可怕吧！这一版的 lvm 竟然还可以线上进行 resize 的功能哩！真好！

[root@www ~]# df /mnt/lvm
Filesystem           1K-blocks      Used Available Use% Mounted on
/dev/mapper/vbirdvg-vbirdlv
                       8628956    262632   7931368   4% /mnt/lvm
[root@www ~]# ll /mnt/lvm
drwxr-xr-x 105 root root 12288 Mar 11 16:59 etc
drwxr-xr-x  17 root root  4096 Mar 11 14:17 log
drwx------   2 root root 16384 Mar 11 16:59 lost+found
# 刚刚复制进去的资料可还是存在的喔！并没有消失不见！

嘿嘿！真的放大了吧！而且如果你已经有填资料在 LVM 磁区当中的话！这个资料是不会死掉的喔！还是继续存在原本的磁区当中啦！ 整个动作竟然这么简单就完成了！原本的资料还是一直存在而不会消失～您说， LVM 好不好用啊！

此外，如果你再以 dumpe2fs 来检查 /dev/vbirdvg/vbirdlv 时，就会发现后续的 Group 增加了！ 如果还是搞不清楚什么是 block group 时，请回到第八章看一下该章内图1.3.1的介绍吧！

小标题的图示 缩小 LV 容量

上一小节我们谈到的是放大容量，现在来谈到的是缩小容量喔！假设我们想将 /dev/hda6 抽离出来！ 那该如何处理啊？就让上一小节的流程倒转过来即可啊！我们就直接来玩吧！

# 1. 先找出 /dev/hda6 的容量大小，并尝试计算档案系统需缩小到多少
[root@www ~]# pvdisplay
  --- Physical volume ---
  PV Name               /dev/hda6
  VG Name               vbirdvg
  PV Size               1.40 GB / not usable 11.46 MB
  Allocatable           yes (but full)
  PE Size (KByte)       16384
  Total PE              89
  Free PE               0
  Allocated PE          89
  PV UUID               Z13Jk5-RCls-UJ8B-HzDa-Gesn-atku-rf2biN
# 从这里可以看出 /dev/hda6 有多大，而且含有 89 个 PE 的量喔！
# 那如果要使用 resize2fs 时，则总量减去 1.40GB 就对了！

[root@www ~]# pvscan
  PV /dev/hda6    VG vbirdvg   lvm2 [1.39 GB / 0    free]
  PV /dev/hda7    VG vbirdvg   lvm2 [1.39 GB / 0    free]
  PV /dev/hda8    VG vbirdvg   lvm2 [1.39 GB / 0    free]
  PV /dev/hda9    VG vbirdvg   lvm2 [1.39 GB / 0    free]
  PV /dev/hda10   VG vbirdvg   lvm2 [2.80 GB / 0    free]
  Total: 5 [8.36 GB] / in use: 5 [8.36 GB] / in no VG: 0 [0   ]
# 从上面可以发现如果扣除 /dev/hda6 则剩余容量有：1.39*3+2.8=6.97

# 2. 就直接降低档案系统的容量吧！
[root@www ~]# resize2fs /dev/vbirdvg/vbirdlv 6900M
resize2fs 1.39 (29-May-2006)
Filesystem at /dev/vbirdvg/vbirdlv is mounted on /mnt/lvm; on-line resizing
On-line shrinking from 2191360 to 1766400 not supported.
# 容量好像不能够写小数点位数，因此 6.9G 是错误的，鸟哥就使用 6900M 了。
# 此外，放大可以线上直接进行，缩小档案系统似乎无法支援！所以要这样做：

[root@www ~]# umount /mnt/lvm
[root@www ~]# resize2fs /dev/vbirdvg/vbirdlv 6900M
resize2fs 1.39 (29-May-2006)
Please run 'e2fsck -f /dev/vbirdvg/vbirdlv' first.
# 他要我们先进行磁碟检查！不啰唆！那就直接进行吧！

[root@www ~]# e2fsck -f /dev/vbirdvg/vbirdlv
e2fsck 1.39 (29-May-2006)
Pass 1: Checking inodes, blocks, and sizes
Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
/dev/vbirdvg/vbirdlv: 2438/1087008 files (0.1% non-contiguous),

[root@www ~]# resize2fs /dev/vbirdvg/vbirdlv 6900M
resize2fs 1.39 (29-May-2006)
Resizing the filesystem on /dev/vbirdvg/vbirdlv to 1766400 (4k) blocks.
The filesystem on /dev/vbirdvg/vbirdlv is now 1766400 blocks long.
# 再来 resize2fs 一次就能够成功了！如上所示啊！

[root@www ~]# mount /dev/vbirdvg/vbirdlv /mnt/lvm
[root@www ~]# df /mnt/lvm
Filesystem           1K-blocks      Used Available Use% Mounted on
/dev/mapper/vbirdvg-vbirdlv
                       6955584    262632   6410328   4% /mnt/lvm

然后再来就是将 LV 的容量降低！要注意的是，我们想要抽离的是 /dev/hda6，这个 PV 有 89 个 PE (上面的 pvdisplay 查询到的结果)。所以要这样进行：

# 3. 降低 LV 的容量，同时我们知道 /dev/hda6 有 89 个 PE
[root@www ~]# lvresize -l -89 /dev/vbirdvg/vbirdlv
  WARNING: Reducing active and open logical volume to 6.97 GB
  THIS MAY DESTROY YOUR DATA (filesystem etc.)
Do you really want to reduce vbirdlv? [y/n]: y
  Reducing logical volume vbirdlv to 6.97 GB
  Logical volume vbirdlv successfully resized
# 会有警告讯息！但是我们的实际资料量还是比 6.97G 小，所以就 y 下去吧！

[root@www ~]# lvdisplay
  --- Logical volume ---
  LV Name                /dev/vbirdvg/vbirdlv
  VG Name                vbirdvg
  LV UUID                8vFOPG-Jrw0-Runh-ug24-t2j7-i3nA-rPEyq0
  LV Write Access        read/write
  LV Status              available
  # open                 1
  LV Size                6.97 GB
  Current LE             446
  Segments               5
  Allocation             inherit
  Read ahead sectors     auto
  - currently set to     256
  Block device           253:0

很简单吧！这样就将 LV 缩小了！接下来就要将 /dev/hda6 移出 vbirdvg 这个 VG 之外啰！ 我们得要先确定 /dev/hda6 里面的 PE 完全不被使用后，才能够将 /dev/hda6 抽离！ 所以得要这样进行：

# 4.1 先确认 /dev/hda6 是否将 PE 都移除了！
[root@www ~]# pvdisplay
  --- Physical volume ---
  PV Name               /dev/hda6
  VG Name               vbirdvg
  PV Size               1.40 GB / not usable 11.46 MB
  Allocatable           yes (but full)
  PE Size (KByte)       16384
  Total PE              89
  Free PE               0
  Allocated PE          89
  PV UUID               Z13Jk5-RCls-UJ8B-HzDa-Gesn-atku-rf2biN
....(中间省略)....

  --- Physical volume ---
  PV Name               /dev/hda10
  VG Name               vbirdvg
  PV Size               2.80 GB / not usable 6.96 MB
  Allocatable           yes
  PE Size (KByte)       16384
  Total PE              179
  Free PE               89
  Allocated PE          90
  PV UUID               7MfcG7-y9or-0Jmb-H7RO-5Pa5-D3qB-G426Vq
# 搞了老半天，没有被使用的 PE 竟然在 /dev/hda10 ！此时得要搬移 PE 啰！

[root@www ~]# pvmove /dev/hda6 /dev/hda10
# pvmove 来源PV 目标PV ，可以将 /dev/hda6 内的 PE 通通移动到 /dev/hda10
# 尚未被使用的 PE 去 (Free PE)。

# 4.2 将 /dev/hda6 移出 vbirdvg 中！
[root@www ~]# vgreduce vbirdvg /dev/hda6
  Removed "/dev/hda6" from volume group "vbirdvg"

[root@www ~]# pvscan
  PV /dev/hda7    VG vbirdvg   lvm2 [1.39 GB / 0    free]
  PV /dev/hda8    VG vbirdvg   lvm2 [1.39 GB / 0    free]
  PV /dev/hda9    VG vbirdvg   lvm2 [1.39 GB / 0    free]
  PV /dev/hda10   VG vbirdvg   lvm2 [2.80 GB / 0    free]
  PV /dev/hda6                 lvm2 [1.40 GB]
  Total: 5 [8.37 GB] / in use: 4 [6.97 GB] / in no VG: 1 [1.40 GB]

[root@www ~]# pvremove /dev/hda6
  Labels on physical volume "/dev/hda6" successfully wiped

很有趣吧！这样你的档案系统以及实际的 LV 与 VG 通通变小了，而且那个 /dev/hda6 还真的可以拿出来！ 可以进行其他的用途啦！非常简单吧！

小标题的图示 LVM 的系统快照

现在你知道 LVM 的好处咯，未来如果你有想要增加某个 LVM 的容量时，就可以透过这个放大、缩小的功能来处理。 那么 LVM 除了这些功能之外，还有什么能力呢？其实他还有一个重要的能力，那就是系统快照 (snapshot)。 什么是系统快照啊？快照就是将当时的系统资讯记录下来，就好像照相记录一般！ 未来若有任何资料更动了，则原始资料会被搬移到快照区，没有被更动的区域则由快照区与档案系统共享。 用讲的好像很难懂，我们用图解说明一下好了：

LVM 系统快照区域的备份示意图
图 3.5.1、LVM 系统快照区域的备份示意图(虚线为档案系统，长虚线为快照区)

左图为最初建置系统快照区的状况，LVM 会预留一个区域 (左图的左侧三个 PE 区块) 作为资料存放处。 此时快照区内并没有任何资料，而快照区与系统区共享所有的 PE 资料， 因此你会看到快照区的内容与档案系统是一模一样的。 等到系统运作一阵子后，假设 A 区域的资料被更动了 (上面右图所示)，则更动前系统会将该区域的资料移动到快照区， 所以在右图的快照区被占用了一块 PE 成为 A，而其他 B 到 I 的区块则还是与档案系统共用！

照这样的情况来看，LVM 的系统快照是非常棒的‘备份工具’，因为他只有备份有被更动到的资料， 档案系统内没有被变更的资料依旧保持在原本的区块内，但是 LVM 快照功能会知道那些资料放置在哪里， 因此‘快照’当时的档案系统就得以‘备份’下来，且快照所占用的容量又非常小！所以您说，这不是很棒的工具又是什么？

那么快照区要如何建立与使用呢？首先，由于快照区与原本的 LV 共用很多 PE 区块，因此快照区与被快照的 LV 必须要在同一个 VG 上头。但是我们刚刚将 /dev/hda6 移除 vbirdvg 了，目前 vbirdvg 剩下的容量为 0 ！因此，在这个小节里面我们得要再加入 /dev/hda6 到我们的 VG 后， 才能继续建立快照区啰！底下的动作赶紧再来玩玩看！

  • 快照区的建立

底下的动作主要再增加需要的 VG 容量，然后再透过 lvcreate -s 的功能建立快照区

# 1. 先观察 VG 还剩下多少剩余容量
[root@www ~]# vgdisplay
  --- Volume group ---
  VG Name               vbirdvg
....(其他省略)....
  VG Size               6.97 GB
  PE Size               16.00 MB
  Total PE              446
  Alloc PE / Size       446 / 6.97 GB
  Free  PE / Size       0 / 0  <==没有多余的 PE 可用！

# 2. 将刚刚移除的 /dev/hda6 加入这个 VG 吧！
[root@www ~]# pvcreate /dev/hda6
  Physical volume "/dev/hda6" successfully created
[root@www ~]# vgextend vbirdvg /dev/hda6
  Volume group "vbirdvg" successfully extended
[root@www ~]# vgdisplay
  --- Volume group ---
  VG Name               vbirdvg
....(其他省略)....
  VG Size               8.36 GB
  PE Size               16.00 MB
  Total PE              535
  Alloc PE / Size       446 / 6.97 GB
  Free  PE / Size       89 / 1.39 GB  <==多出了 89 个 PE 可用啰！

# 3. 利用 lvcreate 建立系统快照区，我们取名为 vbirdss，且给予 60 个 PE
[root@www ~]# lvcreate -l 60 -s -n vbirdss /dev/vbirdvg/vbirdlv
  Logical volume "vbirdss" created
# 上述的指令中最重要的是那个 -s 的选项！代表是 snapshot 快照功能之意！
# -n 后面接快照区的装置名称， /dev/.... 则是要被快照的 LV 完整档名。
# -l 后面则是接使用多少个 PE 来作为这个快照区使用。

[root@www ~]# lvdisplay
  --- Logical volume ---
  LV Name                /dev/vbirdvg/vbirdss
  VG Name                vbirdvg
  LV UUID                K2tJ5E-e9mI-89Gw-hKFd-4tRU-tRKF-oeB03a
  LV Write Access        read/write
  LV snapshot status     active destination for /dev/vbirdvg/vbirdlv
  LV Status              available
  # open                 0
  LV Size                6.97 GB    <==被快照的原 LV 磁碟容量
  Current LE             446
  COW-table size         960.00 MB  <==快照区的实际容量
  COW-table LE           60         <==快照区占用的 PE 数量
  Allocated to snapshot  0.00%
  Snapshot chunk size    4.00 KB
  Segments               1
  Allocation             inherit
  Read ahead sectors     auto
  - currently set to     256
  Block device           253:1

您看看！这个 /dev/vbirdvg/vbirdss 快照区就被建立起来了！而且他的 VG 量竟然与原本的 /dev/vbirdvg/vbirdlv 相同！也就是说，如果你真的挂载这个装置时，看到的资料会跟原本的 vbirdlv 相同喔！我们就来测试看看：

[root@www ~]# mkdir /mnt/snapshot
[root@www ~]# mount /dev/vbirdvg/vbirdss /mnt/snapshot
[root@www ~]# df
Filesystem           1K-blocks      Used Available Use% Mounted on
/dev/hda2              9920624   3859032   5549524  42% /
/dev/hda3              4956316   1056996   3643488  23% /home
/dev/hda1               101086     21408     74459  23% /boot
tmpfs                   371332         0    371332   0% /dev/shm
/dev/mapper/vbirdvg-vbirdlv
                       6955584    262632   6410328   4% /mnt/lvm
/dev/mapper/vbirdvg-vbirdss
                       6955584    262632   6410328   4% /mnt/snapshot
# 有没有看到！这两个咚咚竟然是一模一样喔！我们根本没有动过
# /dev/vbirdvg/vbirdss 对吧！不过这里面会主动记录原 vbirdlv 的内容！

[root@www ~]# umount /mnt/snapshot
# 最后将他卸载！我们准备来玩玩有趣的东西！

  • 利用快照区复原系统

首先，我们来玩一下，如何利用快照区复原系统吧！不过你要注意的是，你要复原的资料量不能够高于快照区所能负载的实际容量。由于原始资料会被搬移到快照区， 如果你的快照区不够大，若原始资料被更动的实际资料量比快照区大，那么快照区当然容纳不了，这时候快照功能会失效喔！ 所以上面的案例中鸟哥才给予 60 个 PE (共 900MB) 作为快照区存放资料用。

我们的 /mnt/lvm 已经有 /mnt/lvm/etc, /mnt/lvm/log 等目录了，接下来我们将这个档案系统的内容作个变更， 然后再以快照区资料还原看看：

# 1. 先将原本的 /dev/vbirdvg/vbirdlv 内容作些变更，增增减减一些目录吧！
[root@www ~]# df /mnt/lvm
Filesystem           1K-blocks      Used Available Use% Mounted on
/dev/mapper/vbirdvg-vbirdlv
                       6955584    262632   6410328   4% /mnt/lvm

[root@www ~]# ll /mnt/lvm
drwxr-xr-x 105 root root 12288 Mar 11 16:59 etc
drwxr-xr-x  17 root root  4096 Mar 11 14:17 log
drwx------   2 root root 16384 Mar 11 16:59 lost+found

[root@www ~]# rm -r /mnt/lvm/log
[root@www ~]# cp -a /boot /lib /sbin /mnt/lvm
[root@www ~]# ll /mnt/lvm
drwxr-xr-x   4 root root  4096 Dec 15 16:28 boot
drwxr-xr-x 105 root root 12288 Mar 11 16:59 etc
drwxr-xr-x  14 root root  4096 Sep  5  2008 lib
drwx------   2 root root 16384 Mar 11 16:59 lost+found
drwxr-xr-x   2 root root 12288 Sep  5  2008 sbin
# 看起来资料已经不一样了！

[root@www ~]# lvdisplay /dev/vbirdvg/vbirdss
  --- Logical volume ---
  LV Name                /dev/vbirdvg/vbirdss
  VG Name                vbirdvg
....(中间省略)....
  Allocated to snapshot  12.22%
....(底下省略)....
# 从这里也看得出来，快照区已经被使用了 12.22% ！因为原始的档案系统有异动过！

# 2. 利用快照区将原本的 filesystem 备份
[root@www ~]# mount /dev/vbirdvg/vbirdss /mnt/snapshot
[root@www ~]# df
Filesystem           1K-blocks      Used Available Use% Mounted on
/dev/mapper/vbirdvg-vbirdlv
                       6955584    370472   6302488   6% /mnt/lvm
/dev/mapper/vbirdvg-vbirdss
                       6955584    262632   6410328   4% /mnt/snapshot
# 看吧！两者确实不一样了！开始将快照区内容复制出来吧！

[root@www ~]# mkdir -p /backups <==确认真的有这个目录！
[root@www ~]# cd /mnt/snapshot
[root@www snapshot]# tar -jcv -f /backups/lvm.tar.bz2 *
# 此时你就会有一个备份资料，亦即是 /backups/lvm.tar.bz2 了！

为什么要备份呢？为什么不可以直接格式化 /dev/vbirdvg/vbirdlv 然后将 /dev/vbirdvg/vbirdss 直接复制给 vbirdlv 呢？ 要知道 vbirdss 其实是 vbirdlv 的快照，因此如果你格式化整个 vbirdlv 时，原本的档案系统所有资料都会被搬移到 vbirdss。 那如果 vbirdss 的容量不够大 (通常也真的不够大)，那么部分资料将无法复制到 vbirdss 内，资料当然无法全部还原啊！ 所以才要在上面表格中制作出一个备份档案的！了解乎？

而快照还有另外一个功能，就是你可以比对 /mnt/lvm 与 /mnt/snapshot 的内容，就能够发现到最近你到底改了啥咚咚！ 这样也是很不赖啊！您说是吧！ ^_^！接下来让我们准备还原 vbirdlv 的内容吧！

# 3. 将 vbirdss 卸载并移除 (因为里面的内容已经备份起来了)
[root@www ~]# umount /mnt/snapshot
[root@www ~]# lvremove /dev/vbirdvg/vbirdss
Do you really want to remove active logical volume "vbirdss"? [y/n]: y
  Logical volume "vbirdss" successfully removed

[root@www ~]# umount /mnt/lvm
[root@www ~]# mkfs -t ext3 /dev/vbirdvg/vbirdlv
[root@www ~]# mount /dev/vbirdvg/vbirdlv /mnt/lvm
[root@www ~]# tar -jxv -f /backups/lvm.tar.bz2 -C /mnt/lvm
[root@www ~]# ll /mnt/lvm
drwxr-xr-x 105 root root 12288 Mar 11 16:59 etc
drwxr-xr-x  17 root root  4096 Mar 11 14:17 log
drwx------   2 root root 16384 Mar 11 16:59 lost+found
# 是否与最初的内容相同啊！这就是透过快照来还原的一个简单的方法啰！

  • 利用快照区进行各项练习与测试的任务，再以原系统还原快照

换个角度来想想，我们将原本的 vbirdlv 当作备份资料，然后将 vbirdss 当作实际在运作中的资料， 任何测试的动作都在 vbirdss 这个快照区当中测试，那么当测试完毕要将测试的资料删除时，只要将快照区删去即可！ 而要复制一个 vbirdlv 的系统，再作另外一个快照区即可！这样是否非常方便啊？ 这对于教学环境中每年都要帮学生制作一个练习环境主机的测试，非常有帮助呢！

Tips:
以前鸟哥老是觉得使用 LVM 的快照来进行备份不太合理，因为还要制作一个备份档！后来仔细研究并参考徐秉义老师的教材(注3)后，才发现 LVM 的快照实在是一个棒到不行的工具！尤其是在虚拟机器当中建置多份给同学使用的测试环境， 你只要有一个基础的环境保持住，其他的环境使用快照来提供即可。即时同学将系统搞烂了，你只要将快照区删除， 再重建一个快照区！这样环境就恢复了！天呐！实在是太棒了！ ^_^ 		鸟哥的图示
# 1. 建立一个大一些的快照区，让我们将 /dev/hda6 的 PE 全部给快照区！
[root@www ~]# lvcreate -s -l 89 -n vbirdss /dev/vbirdvg/vbirdlv
  Logical volume "vbirdss" created

[root@www ~]# lvdisplay /dev/vbirdvg/vbirdss
  --- Logical volume ---
  LV Name                /dev/vbirdvg/vbirdss
  VG Name                vbirdvg
  LV UUID                as0ocQ-KjRS-Bu7y-fYoD-1CHC-0V3Y-JYsjj1
  LV Write Access        read/write
  LV snapshot status     active destination for /dev/vbirdvg/vbirdlv
  LV Status              available
  # open                 0
  LV Size                6.97 GB
  Current LE             446
  COW-table size         1.39 GB
  COW-table LE           89
  Allocated to snapshot  0.00%
  Snapshot chunk size    4.00 KB
  Segments               1
  Allocation             inherit
  Read ahead sectors     auto
  - currently set to     256
  Block device           253:1
# 如何！这个快照区不小吧！

# 2. 隐藏 vbirdlv 挂载 vbirdss
[root@www ~]# umount /mnt/lvm
[root@www ~]# mount /dev/vbirdvg/vbirdss /mnt/snapshot
[root@www ~]# df /mnt/snapshot
Filesystem           1K-blocks      Used Available Use% Mounted on
/dev/mapper/vbirdvg-vbirdss
                       7192504    265804   6561340   4% /mnt/snapshot

# 3. 开始恶搞！
[root@www ~]# rm -r /mnt/snapshot/etc /mnt/snapshot/log
[root@www ~]# cp -a /boot /lib /sbin /mnt/snapshot/
[root@www ~]# ll /mnt/snapshot
drwxr-xr-x  4 root root  4096 Dec 15 16:28 boot
drwxr-xr-x 14 root root  4096 Sep  5  2008 lib
drwx------  2 root root 16384 Mar 11 16:59 lost+found
drwxr-xr-x  2 root root 12288 Sep  5  2008 sbin  <==与原本资料有差异了

[root@www ~]# mount /dev/vbirdvg/vbirdlv /mnt/lvm
[root@www ~]# ll /mnt/lvm
drwxr-xr-x 105 root root 12288 Mar 11 16:59 etc
drwxr-xr-x  17 root root  4096 Mar 11 14:17 log
drwx------   2 root root 16384 Mar 11 16:59 lost+found
# 不论你在快照区恶搞啥咚咚，原本的 vbirdlv 里面的资料安好如初啊！
# 假设你将 vbirdss 搞烂了！里面的资料不再需要！那该如何是好？

# 4. 还原原本快照区的资料，回到与原档案系统相同的资讯
[root@www ~]# umount /mnt/snapshot
[root@www ~]# lvremove /dev/vbirdvg/vbirdss
Do you really want to remove active logical volume "vbirdss"? [y/n]: y
  Logical volume "vbirdss" successfully removed

[root@www ~]# lvcreate -s -l 89 -n vbirdss /dev/vbirdvg/vbirdlv
[root@www ~]# mount /dev/vbirdvg/vbirdss /mnt/snapshot
[root@www ~]# ll /mnt/snapshot
drwxr-xr-x 105 root root 12288 Mar 11 16:59 etc
drwxr-xr-x  17 root root  4096 Mar 11 14:17 log
drwx------   2 root root 16384 Mar 11 16:59 lost+found
# 资料这样就复原了！

老实说，上面的测试有点无厘头～因为快照区损毁了就删除再建一个就好啦！何必还要测试呢？ 不过，为了让您了解到快照区也能够这样使用，上面的测试还是需要存在的啦！未来如果你有接触到虚拟机器， 再回到这里来温习一下肯定会有收获的！

小标题的图示 LVM 相关指令汇整与 LVM 的关闭

好了，我们将上述用过的一些指令给他汇整一下，提供给您参考参考：

任务 | PV 阶段 | VG 阶段 | LV 阶段
搜寻(scan) | pvscan | vgscan | lvscan
建立(create) | pvcreate | vgcreate | lvcreate
列出(display) | pvdisplay | vgdisplay | lvdisplay
增加(extend) |  | vgextend | lvextend (lvresize)
减少(reduce) |  | vgreduce | lvreduce (lvresize)
删除(remove) | pvremove | vgremove | lvremove
改变容量(resize) |  |  | lvresize
改变属性(attribute) | pvchange | vgchange | lvchange

至于档案系统阶段 (filesystem 的格式化处理) 部分，还需要以 resize2fs 来修订档案系统实际的大小才行啊！ ^_^ 。至于虽然 LVM 可以弹性的管理你的磁碟容量，但是要注意，如果你想要使用 LVM 管理您的硬碟时，那么在安装的时候就得要做好 LVM 的规划了， 否则未来还是需要先以传统的磁碟增加方式来增加后，移动资料后，才能够进行 LVM 的使用啊！

会玩 LVM 还不行！你必须要会移除系统内的 LVM 喔！因为你的实体 partition 已经被使用到 LVM 去， 如果你还没有将 LVM 关闭就直接将那些 partition 删除或转为其他用途的话，系统是会发生很大的问题的！ 所以啰，你必须要知道如何将 LVM 的装置关闭并移除才行！会不会很难呢？其实不会啦！ 依据以下的流程来处理即可：

  1. 先卸载系统上面的 LVM 档案系统 (包括快照与所有 LV)；
  2. 使用 lvremove 移除 LV ；
  3. 使用 vgchange -a n VGname 让 VGname 这个 VG 不具有 Active 的标志；
  4. 使用 vgremove 移除 VG：
  5. 使用 pvremove 移除 PV；
  6. 最后，使用 fdisk 修改 ID 回来啊！

好吧！那就实际的将我们之前建立的所有 LVM 资料给删除吧！

[root@www ~]# umount /mnt/lvm
[root@www ~]# umount /mnt/snapshot
[root@www ~]# lvremove /dev/vbirdvg/vbirdss  <==先处理快照
Do you really want to remove active logical volume "vbirdss"? [y/n]: y
  Logical volume "vbirdss" successfully removed
[root@www ~]# lvremove /dev/vbirdvg/vbirdlv  <==再处理原系统
Do you really want to remove active logical volume "vbirdlv"? [y/n]: y
  Logical volume "vbirdlv" successfully removed

[root@www ~]# vgchange -a n vbirdvg
  0 logical volume(s) in volume group "vbirdvg" now active

[root@www ~]# vgremove vbirdvg
  Volume group "vbirdvg" successfully removed

[root@www ~]# pvremove /dev/hda{6,7,8,9,10}
  Labels on physical volume "/dev/hda6" successfully wiped
  Labels on physical volume "/dev/hda7" successfully wiped
  Labels on physical volume "/dev/hda8" successfully wiped
  Labels on physical volume "/dev/hda9" successfully wiped
  Labels on physical volume "/dev/hda10" successfully wiped

最后再用 fdisk 将磁碟的 ID 给他改回来 82 就好啦！整个过程就这样的啦！ ^_^

大标题的图示 重点回顾
  • Quota 可公平的分配系统上面的磁碟容量给使用者；分配的资源可以是磁碟容量(block)或可建立档案数量(inode)；
  • Quota 的限制可以有 soft/hard/grace time 等重要项目；
  • Quota 仅能针对整个 filesystem 进行限制，不是针对目录喔！
  • Quota 的使用必须要核心与档案系统均支援。档案系统的参数必须含有 usrquota, grpquota
  • Quota 实作的指令有 quotacheck, quotaon, edquota, repquota 等指令；
  • 磁碟阵列 (RAID) 有硬体与软体之分，Linux 作业系统可支援软体磁碟阵列，透过 mdadm 套件来达成；
  • 磁碟阵列建置的考量依据为‘容量’、‘效能’、‘资料可靠性’等；
  • 磁碟阵列所建置的等级常见有的 raid0, raid1, raid0+1, raid5 及 raid6
  • 硬体磁碟阵列的装置档名与 SCSI 相同，至于 software RAID 则为 /dev/md[0-9]
  • 软体磁碟阵列的状态可藉由 /proc/mdstat 档案来了解；
  • LVM 强调的是‘弹性的变化档案系统的容量’；
  • 与 LVM 有关的元件有： PV/VG/PE/LV 等元件，可以被格式化者为 LV
  • LVM 拥有快照功能，快照可以记录 LV 的资料内容，并与原有的 LV 共享未更动的资料，备份与还原就变的很简单；
  • Ext3 透过 resize2fs 指令，可以弹性的调整档案系统的大小
大标题的图示 本章习题
( 要看答案请将滑鼠移动到‘答：’底下的空白处，按下左键圈选空白处即可察看 )
  • 情境模拟题一：由于 LVM 可以弹性调整 filesystem 的大小，但是缺点是可能没有加速与硬体备份(与快照不同)的功能。 而磁碟阵列则具有效能与备份的功能，但是无法提供类似 LVM 的优点。在此情境中，我们想利用‘在 RAID 上面建置 LVM’的功能，以达到两者兼顾的能力。

    • 目标：测试在 RAID 磁碟上面架构 LVM 系统；
    • 需求：需要具有磁碟管理的能力，包括 RAID 与 LVM；
    • 前提：将本章与之前章节练习所制作的分割槽全部删除，剩下预设的分割槽即可。

    那要如何处理呢？如下的流程一个步骤一个步骤的实施看看吧：

    1. 复原系统时，你必须要：

      • 利用 umount 先卸载之前挂载的档案系统；
      • 修改 /etc/fstab 里面的资料，让开机不会自动挂载；
      • 利用 fdisk 将该分割槽删除。

      最终你的系统应该会只剩下如下的模样：
      [root@www ~]# fdisk -l
   Device Boot      Start         End      Blocks   Id  System
/dev/hda1   *           1          13      104391   83  Linux
/dev/hda2              14        1288    10241437+  83  Linux
/dev/hda3            1289        1925     5116702+  83  Linux
/dev/hda4            1926        9382    59898352+   5  Extended
/dev/hda5            1926        2052     1020096   82  Linux swap / Solaris

    2. 建立 RAID ，假设我们利用五个 1GB 的分割槽建立 RAID-5 ，且具有一个 spare disk ， 那么你应该要如何进行？首先，请自行使用 fdisk 建置好如下的分割槽状态：
      [root@www ~]# fdisk -l
....(前面省略)....
/dev/hda6            2053        2175      987966   83  Linux
/dev/hda7            2176        2298      987966   83  Linux
/dev/hda8            2299        2421      987966   83  Linux
/dev/hda9            2422        2544      987966   83  Linux
/dev/hda10           2545        2667      987966   83  Linux
      接下来开始建立 RAID 吧！建立的方法可以如下简单处理即可：
      [root@www ~]# mdadm --create --auto=yes /dev/md0 --level=5  \
> --raid-devices=4 --spare-devices=1 /dev/hda{6,7,8,9,10}
      若无出现任何错误讯息，此时你已经具有 /dev/md0 这个磁碟阵列装置了！接下来让我们处理 LVM 吧！

    3. 开始处理 LVM ，现在我们假设所有的参数都使用预设值，包括 PE ，然后 VG 名为 raidvg ，LV 名为 raidlv ，底下为基本的流程：
      [root@www ~]# pvcreate /dev/md0                  <==建立 PV
[root@www ~]# vgcreate raidvg /dev/md0           <==建立 VG
[root@www ~]# lvcreate -L 2.82G -n raidlv raidvg <==建立 LM
[root@www ~]# lvdisplay
  --- Logical volume ---
  LV Name                /dev/raidvg/raidlv
  VG Name                raidvg
  LV UUID                zQsKqW-8Bt2-kpJF-8rCI-Cql1-XQYT-jw1mfH
  LV Write Access        read/write
  LV Status              available
  # open                 0
  LV Size                2.82 GB
  Current LE             722
  Segments               1
  Allocation             inherit
  Read ahead sectors     auto
  - currently set to     256
  Block device           253:0
      这样就搞定了 LVM 了！而且这个 LVM 是架构在 /dev/md0 上面的喔！然后就是档案系统的建立与挂载了！

    4. 尝试建立成为 Ext3 档案系统，且挂载到 /mnt/raidlvm 目录下：
      [root@www ~]# mkfs -t ext3 /dev/raidvg/raidlv
[root@www ~]# mkdir /mnt/raidlvm
[root@www ~]# mount /dev/raidvg/raidlv /mnt/raidlvm

    5. 上述就是 LVM 架构在 RAID 上面的技巧，之后的动作都能够使用本章的其他管理方式来管理， 包括 RAID 热拔插机制、LVM 放大缩小机制等等。测试完毕之后请务必要关闭本题所建立的各项资讯。
      [root@www ~]# umount /mnt/raidlvm         <==卸载档案系统
[root@www ~]# lvremove /dev/raidvg/raidlv <==移除 LV
[root@www ~]# vgchange -a n raidvg        <==让 VG 不活动
[root@www ~]# vgremove raidvg             <==移除 VG
[root@www ~]# pvremove /dev/md0           <==移除 PV
[root@www ~]# mdadm --stop /dev/md0       <==关闭 /dev/md0 RAID
[root@www ~]# fdisk /dev/hda              <==还原原本的分割槽
简答题部分：
  • 在前一章的第一个大量新增帐号范例中， 如果我想要让每个用户均具有 soft/hard 各为 40MB/50MB 的容量时，应该如何修改这个 script ？
    你得先要依据本章的作法，先将 /home 制作好 quota 的环境然后， 你可以在 do...done 内的最后一行，新增一行内容为：
    setquota -u $username 40000 50000 0 0 /home
    这样就可以在制作用户时，指定更新密码且给予 quota 的限制！
  • 如果我想要让 RAID 具有保护资料的功能，防止因为硬体损毁而导致资料的遗失，那我应该要选择的 RAID 等级可能有哪些？ (请以本章谈到的等级来思考即可)
    具有备份资料的有： RAID-1, RAID-5, RAID-6
  • 在预设的 LVM 设定中，请问 LVM 能否具有‘备份’的功能？
    是有的，就是那个快照 (snopshot) 的功能，此功能即可进行资料的备份！
  • LVM 内的 LV 据说仅能达到 256 GB 的容量，请问如何克服此一容量问题？
    LV 的容量与 PE 这个资料有关，由于预设 PE 为 4MB ，所以才会有此限制。 若要修改这个限制值，则需要在建置 VG 时就给予 -s 的选项来进行 PE 数值的设定。 若给到 PE = 16MB 时，则 LV 的最大总量就能够达到 1TB 的容量了。
  • 如果你的电脑主机有提供 RAID 0 的功能，你将你的三颗硬碟全部在 BIOS 阶段使用 RAID 晶片整合成为一颗大磁碟， 则此磁碟在 Linux 系统当中的档名为何？
    由于硬体磁碟阵列是在 BIOS 阶段完成的，因此 Linux 系统会捉到一个完整的大的 RAID 磁碟， 此磁碟的档名就会是‘ /dev/sda ’！
大标题的图示 参考资料与延伸阅读
  • 注1：若想对 RAID 有更深入的认识，可以参考底下的连结与书目：
    http://www.tldp.org/HOWTO/Software-RAID-HOWTO.html
    杨振和、‘作业系统导论：第十一章’、学贯出版社，2006
  • 注2：详细的 mdstat 说明也可以参考如下网页：
    http://linux-raid.osdl.org/index.php/Mdstat
  • 注3：徐秉义老师在网管人杂志 (http://www.babyface.idv.tw/NetAdmin/) 的投稿文章：
    磁碟管理：SoftRAID 与 LVM 综合实做应用 (上)
    http://www.babyface.idv.tw/NetAdmin/16200705SoftRAIDLVM01/
    磁碟管理：SoftRAID 与 LVM 综合实做应用 (下)
    http://www.babyface.idv.tw/NetAdmin/18200707SoftRAIDLVM02/
2002/07/14：第一次完成
2003/02/10：重新编排与加入 FAQ
2003/09/02：加入 quotacheck 发生错误时的解决方法。
2005/09/06：将旧的文章移动到 此处 。
2005/09/06：进行版面风格的转换，并且进行资料的查询，加入 repquota 的简单说明而已！
2009/03/04：将原本旧的基于 FC4 的文件移动到 此处 。
2009/03/06：加入 warnquota 这玩意儿！挺有趣的哩！
2009/03/12：加入了 software RAID 与 LVM 的加强说明，尤其是 LVM 的快照 (snapshot) 的说明！
2009/09/10：修改一些字样之外，增加情境模拟，以及后续的简答题部分题目。


鸟哥的 Linux 私房菜 -- 例行性工作排程的建立

为取得较佳浏览结果，请爱用 firefox 浏览本网页
鸟哥的 Linux 私房菜馆 | Linux 基础文件 | Linux 架站文件 | Linux 企业运用 | 安全管理 | 新手讨论 |

第十六章、例行性工作排程 (crontab)
最近更新日期：2009/09/11
学习了基础篇也一阵子了，你会发现到为什么系统常常会主动的进行一些任务？这些任务到底是谁在设定工作的？ 如果你想要让自己设计的备份程式可以自动的在系统底下执行，而不需要手动来启动他，又该如何处置？ 这些例行的工作可能又分为‘单一’工作与‘循环’工作，在系统内又是哪些服务在负责？ 还有还有，如果你想要每年在老婆的生日前一天就发出一封信件提醒自己不要忘记，可以办的到吗？ 嘿嘿！这些种种要如何处理，就看看这一章先！

1. 什么是例行性工作排程
    1.1 Linux 工作排程的种类： at, crontab
    1.2 Linux 上常见的例行性工作
 2. 仅执行一次的工作排程
    2.1 atd 的启动与 at 运作的方式： /etc/at.deny
    2.2 实际运作单一工作排程： at, atq & atrm, batch
 3. 循环执行的例行性工作排程
    3.1 使用者的设定： /etc/cron.deny, crontab
    3.2 系统的设定档： /etc/crontab
    3.3 一些注意事项
 4. 可唤醒停机期间的工作任务
    4.1 什么是 anacron
    4.2 anacron 与 /etc/anacrontab
 5. 重点回顾
6. 本章习题
7. 针对本文的建议：http://phorum.vbird.org/viewtopic.php?t=23889
大标题的图示 什么是例行性工作排程

每个人或多或少都有一些约会或者是工作，有的工作是例行性的， 例如每年一次的加薪、每个月一次的工作报告、每周一次的午餐会报、每天需要的打卡等等； 有的工作则是临时发生的，例如刚好总公司有高官来访，需要你准备演讲器材等等！ 用在生活上面，例如每年的爱人的生日、每天的起床时间等等、还有突发性的电脑大降价 (啊！真希望天天都有！) 等等啰。

像上面这些例行性工作，通常你得要记录在行事历上面才能避免忘记！不过，由于我们常常在电脑前面的缘故， 如果电脑系统能够主动的通知我们的话，那么不就轻松多了！嘿嘿！这个时候 Linux 的例行性工作排程就可以派上场了！ 在不考虑硬体与我们伺服器的连结状态下，我们的 Linux 可以帮你提醒很多任务，例如：每一天早上 8:00 钟要伺服器连接上音响，并启动音乐来唤你起床；而中午 12:00 希望 Linux 可以发一封信到你的邮件信箱，提醒你可以去吃午餐了； 另外，在每年的你爱人生日的前一天，先发封信提醒你，以免忘记这么重要的一天。

那么 Linux 的例行性工作是如何进行排程的呢？所谓的排程就是将这些工作安排执行的流程之意！ 咱们的 Linux 排程就是透过 crontab 与 at 这两个东西！这两个玩意儿有啥异同？就让我们来瞧瞧先！

小标题的图示 Linux 工作排程的种类： at, cron

从上面的说明当中，我们可以很清楚的发现两种工作排程的方式：

  • 一种是例行性的，就是每隔一定的周期要来办的事项；
  • 一种是突发性的，就是这次做完以后就没有的那一种 (电脑大降价...)

那么在 Linux 底下如何达到这两个功能呢？那就得使用 at 与 crontab 这两个好东西啰！

  • at ：at 是个可以处理仅执行一次就结束排程的指令，不过要执行 at 时， 必须要有 atd 这个服务 (第十八章) 的支援才行。在某些新版的 distributions 中，atd 可能预设并没有启动，那么 at 这个指令就会失效呢！不过我们的 CentOS 预设是启动的！

  • crontab ：crontab 这个指令所设定的工作将会循环的一直进行下去！ 可循环的时间为分钟、小时、每周、每月或每年等。crontab 除了可以使用指令执行外，亦可编辑 /etc/crontab 来支援。 至于让 crontab 可以生效的服务则是 crond 这个服务喔！

底下我们先来谈一谈 Linux 的系统到底在做什么事情，怎么有若干多的工作排程在进行呢？然后再回来谈一谈 at 与 crontab 这两个好东西！

小标题的图示 Linux 上常见的例行性工作

如果你曾经使用过 Linux 一阵子了，那么你大概会发现到 Linux 会主动的帮我们进行一些工作呢！ 比方说自动的进行线上更新 (on-line update)、自动的进行 updatedb (第七章谈到的 locate 指令) 更新档名资料库、自动的作登录档分析 (所以 root 常常会收到标题为 logwatch 的信件) 等等。这是由于系统要正常运作的话， 某些在背景底下的工作必须要定时进行的缘故。基本上 Linux 系统常见的例行性任务有：

  • 进行登录档的轮替 (log rotate)：
    Linux 会主动的将系统所发生的各种资讯都记录下来，这就是登录档 (第十九章)。 由于系统会一直记录登录资讯，所以登录档将会越来越大！我们知道大型档案不但占容量还会造成读写效能的困扰， 因此适时的将登录档资料挪一挪，让旧的资料与新的资料分别存放，则比较可以有效的记录登录资讯。这就是 log rotate 的任务！这也是系统必要的例行任务；

  • 登录档分析 logwatch 的任务：
    如果系统发生了软体问题、硬体错误、资安问题等，绝大部分的错误资讯都会被记录到登录档中， 因此系统管理员的重要任务之一就是分析登录档。但你不可能手动透过 vim 等软体去检视登录档，因为资料太复杂了！ 我们的 CentOS 提供了一只程式‘ logwatch ’来主动分析登录资讯，所以你会发现，你的 root 老是会收到标题为 logwatch 的信件，那是正常的！你最好也能够看看该信件的内容喔！

  • 建立 locate 的资料库：
    在第七章我们谈到的 locate 指令时， 我们知道该指令是透过已经存在的档名资料库来进行系统上档名的查询。我们的档名资料库是放置到 /var/lib/mlocate/ 中。 问题是，这个资料库怎么会自动更新啊？嘿嘿！这就是系统的例行性工作所产生的效果啦！系统会主动的进行 updatedb 喔！

  • whatis 资料库的建立：
    与 locate 资料库类似的，whatis 也是个资料库，这个 whatis 是与 man page 有关的一个查询指令，不过要使用 whatis 指令时， 必须要拥有 whatis 资料库，而这个资料库也是透过系统的例行性工作排程来自动执行的哩！

  • RPM 软体登录档的建立：
    RPM (第二十三章) 是一种软体管理的机制。由于系统可能会常常变更软体， 包括软体的新安装、非经常性更新等，都会造成软体档名的差异。为了方便未来追踪，系统也帮我们将档名作个排序的记录呢！ 有时候系统也会透过排程来帮忙 RPM 资料库的重新建置喔！

  • 移除暂存档：
    某些软体在运作中会产生一些暂存档，但是当这个软体关闭时，这些暂存档可能并不会主动的被移除。 有些暂存档则有时间性，如果超过一段时间后，这个暂存档就没有效用了，此时移除这些暂存档就是一件重要的工作！ 否则磁碟容量会被耗光。系统透过例行性工作排程执行名为 tmpwatch 的指令来删除这些暂存档呢！

  • 与网路服务有关的分析行为：
    如果你有安装类似 WWW 伺服器软体 (一个名为 apache 的软体)，那么你的 Linux 系统通常就会主动的分析该软体的登录档。 同时某些凭证与认证的网路资讯是否过期的问题，我们的 Linux 系统也会很亲和的帮你进行自动检查！

其实你的系统会进行的例行性工作与你安装的软体多寡有关，如果你安装过多的软体，某些服务功能的软体都会附上分析工具， 那么你的系统就会多出一些例行性工作啰！像鸟哥的主机还多加了很多自己撰写的分析工具，以及其他第三方协力软体的分析软体， 嘿嘿！俺的 Linux 工作量可是非常大的哩！因为有这么多的工作需要进行，所以我们当然得要了解例行性工作的处理方式啰！

大标题的图示 仅执行一次的工作排程

首先，我们先来谈谈单一工作排程的运作，那就是 at 这个指令的运作！

小标题的图示 atd 的启动与 at 运作的方式

要使用单一工作排程时，我们的 Linux 系统上面必须要有负责这个排程的服务，那就是 atd 这个玩意儿。 不过并非所有的 Linux distributions 都预设会把他打开的，所以呢，某些时刻我们必须要手动将他启用才行。 启用的方法很简单，就是这样：

[root@www ~]# /etc/init.d/atd restart
正在停止 atd:                          [  确定  ]
正在启动 atd:                          [  确定  ]

# 再设定一下开机时就启动这个服务，免得每次重新开机都得再来一次！
[root@www ~]# chkconfig atd on

重点是那个‘正在启动(或 starting)’项目的 OK 啦！那表示启动是正常的！这部份我们在第十八章会谈及。 如果您真的有兴趣，那么可以自行到 /etc/init.d/atd 这个 shell script 内去瞧一瞧先！ ^_^。 至于那个 chkconfig ，你也可以使用 man 先查阅一下啊！我们第十八章再介绍啦！

  • at 的运作方式

既然是工作排程，那么应该会有产生工作的方式，并且将这些工作排进行程表中啰！OK！那么产生工作的方式是怎么进行的？ 事实上，我们使用 at 这个指令来产生所要运作的工作，并将这个工作以文字档的方式写入 /var/spool/at/ 目录内，该工作便能等待 atd 这个服务的取用与执行了。就这么简单。

不过，并不是所有的人都可以进行 at 工作排程喔！为什么？因为安全的理由啊～ 很多主机被所谓的‘绑架’后，最常发现的就是他们的系统当中多了很多的怪客程式 (cracker program)， 这些程式非常可能运用工作排程来执行或搜集系统资讯，并定时的回报给怪客团体！ 所以啰，除非是你认可的帐号，否则先不要让他们使用 at 吧！那怎么达到使用 at 的列管呢？

我们可以利用 /etc/at.allow 与 /etc/at.deny 这两个档案来进行 at 的使用限制呢！ 加上这两个档案后， at 的工作情况其实是这样的：

  1. 先找寻 /etc/at.allow 这个档案，写在这个档案中的使用者才能使用 at ，没有在这个档案中的使用者则不能使用 at (即使没有写在 at.deny 当中)；

  2. 如果 /etc/at.allow 不存在，就寻找 /etc/at.deny 这个档案，若写在这个 at.deny 的使用者则不能使用 at ，而没有在这个 at.deny 档案中的使用者，就可以使用 at 咯；

  3. 如果两个档案都不存在，那么只有 root 可以使用 at 这个指令。

透过这个说明，我们知道 /etc/at.allow 是管理较为严格的方式，而 /etc/at.deny 则较为松散 (因为帐号没有在该档案中，就能够执行 at 了)。在一般的 distributions 当中，由于假设系统上的所有用户都是可信任的， 因此系统通常会保留一个空的 /etc/at.deny 档案，意思是允许所有人使用 at 指令的意思 (您可以自行检查一下该档案)。 不过，万一你不希望有某些使用者使用 at 的话，将那个使用者的帐号写入 /etc/at.deny 即可！ 一个帐号写一行。

小标题的图示 实际运作单一工作排程

单一工作排程的进行就使用 at 这个指令啰！这个指令的运作非常简单！将 at 加上一个时间即可！基本的语法如下：

[root@www ~]# at [-mldv] TIME
[root@www ~]# at -c 工作号码
选项与参数：
-m  ：当 at 的工作完成后，即使没有输出讯息，亦以 email 通知使用者该工作已完成。
-l  ：at -l 相当于 atq，列出目前系统上面的所有该使用者的 at 排程；
-d  ：at -d 相当于 atrm ，可以取消一个在 at 排程中的工作；
-v  ：可以使用较明显的时间格式列出 at 排程中的工作列表；
-c  ：可以列出后面接的该项工作的实际指令内容。

TIME：时间格式，这里可以定义出‘什么时候要进行 at 这项工作’的时间，格式有：
  HH:MM				ex> 04:00
    在今日的 HH:MM 时刻进行，若该时刻已超过，则明天的 HH:MM 进行此工作。
  HH:MM YYYY-MM-DD		ex> 04:00 2009-03-17
    强制规定在某年某月的某一天的特殊时刻进行该工作！
  HH:MM[am|pm] [Month] [Date]	ex> 04pm March 17
    也是一样，强制在某年某月某日的某时刻进行！
  HH:MM[am|pm] + number [minutes|hours|days|weeks]
    ex> now + 5 minutes	ex> 04pm + 3 days
    就是说，在某个时间点‘再加几个时间后’才进行。

老实说，这个 at 指令的下达最重要的地方在于‘时间’的指定了！鸟哥喜欢使用‘ now + ... ’ 的方式来定义现在过多少时间再进行工作，但有时也需要定义特定的时间点来进行！底下的范例先看看啰！

范例一：再过五分钟后，将 /root/.bashrc 寄给 root 自己
[root@www ~]# at now + 5 minutes  <==记得单位要加 s 喔！
at> /bin/mail root -s "testing at job" < /root/.bashrc
at> <EOT>   <==这里输入 [ctrl] + d 就会出现 <EOF> 的字样！代表结束！
job 4 at 2009-03-14 15:38
# 上面这行资讯在说明，第 4 个 at 工作将在 2009/03/14 的 15:38 进行！
# 而执行 at 会进入所谓的 at shell 环境，让你下达多重指令等待运作！

范例二：将上述的第 4 项工作内容列出来查阅
[root@www ~]# at -c 4
#!/bin/sh               <==就是透过 bash shell 的啦！
# atrun uid=0 gid=0
# mail     root 0
umask 22
....(中间省略许多的环境变数项目)....
cd /root || {           <==可以看出，会到下达 at 时的工作目录去执行指令
         echo 'Execution directory inaccessible' >&2
         exit 1
}

/bin/mail root -s "testing at job" < /root/.bashrc
# 你可以看到指令执行的目录 (/root)，还有多个环境变数与实际的指令内容啦！

范例三：由于机房预计于 2009/03/18 停电，我想要在 2009/03/17 23:00 关机？
[root@www ~]# at 23:00 2009-03-17
at> /bin/sync
at> /bin/sync
at> /sbin/shutdown -h now
at> <EOT>
job 5 at 2009-03-17 23:00
# 您瞧瞧！ at 还可以在一个工作内输入多个指令呢！不错吧！

事实上，当我们使用 at 时会进入一个 at shell 的环境来让使用者下达工作指令，此时，建议你最好使用绝对路径来下达你的指令，比较不会有问题喔！由于指令的下达与 PATH 变数有关， 同时与当时的工作目录也有关连 (如果有牵涉到档案的话)，因此使用绝对路径来下达指令，会是比较一劳永逸的方法。 为什么呢？举例来说，你在 /tmp 下达‘ at now ’然后输入‘ mail root -s "test" < .bashrc ’， 问一下，那个 .bashrc 的档案会是在哪里？答案是‘ /tmp/.bashrc ’！因为 at 在运作时，会跑到当时下达 at 指令的那个工作目录的缘故啊！

有些朋友会希望‘我要在某某时刻，在我的终端机显示出 Hello 的字样’，然后就在 at 里面下达这样的资讯‘ echo "Hello" ’。等到时间到了，却发现没有任何讯息在荧幕上显示，这是啥原因啊？这是因为 at 的执行与终端机环境无关，而所有 standard output/standard error output 都会传送到执行者的 mailbox 去啦！所以在终端机当然看不到任何资讯。那怎办？没关系， 可以透过终端机的装置来处理！假如你在 tty1 登入，则可以使用‘ echo "Hello" > /dev/tty1 ’来取代。

Tips:
要注意的是，如果在 at shell 内的指令并没有任何的讯息输出，那么 at 预设不会发 email 给执行者的。 如果你想要让 at 无论如何都发一封 email 告知你是否执行了指令，那么可以使用‘ at -m 时间格式 ’来下达指令喔！ at 就会传送一个讯息给执行者，而不论该指令执行有无讯息输出了！ 		鸟哥的图示

at 有另外一个很棒的优点，那就是‘背景执行’的功能了！什么是背景执行啊？很难了解吗？其实与 bash 的 nohup (第十七章) 类似啦！ 鸟哥提我自己的几个例子来给您听听，您就了了！

  • 离线继续工作的任务：鸟哥初次接触 Unix 为的是要跑空气品质模式， 那是一种大型的程式，这个程式在当时的硬体底下跑，一个案例要跑 3 天！由于鸟哥也要进行其他研究工作，因此常常使用 Windows 98 来连线到 Unix 工作站跑那个 3 天的案例！结果你也该知道， Windows 98 连开三天而不当机的机率是很低的～@_@～ 而当机时，所有在 Windows 上的连线都会中断！包括鸟哥在跑的那个程式也中断了～呜呜～明明再三个钟头就跑完的程式， 由于当机害我又得跑 3 天！

  • 另一个常用的时刻则是例如上面的范例三，由于某个突发状况导致你必须要进行某项工作时，这个 at 就很好用啦！

由于 at 工作排程的使用上，系统会将该项 at 工作独立出你的 bash 环境中， 直接交给系统的 atd 程式来接管，因此，当你下达了 at 的工作之后就可以立刻离线了， 剩下的工作就完全交给 Linux 管理即可！所以啰，如果有长时间的网路工作时，嘿嘿！ 使用 at 可以让你免除网路断线后的困扰喔！ ^_^

  • at 工作的管理

那么万一我下达了 at 之后，才发现指令输入错误，该如何是好？就将他移除啊！利用 atq 与 atrm 吧！

[root@www ~]# atq
[root@www ~]# atrm [jobnumber]

范例一：查询目前主机上面有多少的 at 工作排程？
[root@www ~]# atq
5       2009-03-17 23:00 a root
# 上面说的是：‘在 2009/03/17 的 23:00 有一项工作，该项工作指令下达者为
# root’而且，该项工作的工作号码 (jobnumber) 为 5 号喔！

范例二：将上述的第 5 个工作移除！
[root@www ~]# atrm 5
[root@www ~]# atq
# 没有任何资讯，表示该工作被移除了！

如此一来，你可以利用 atq 来查询，利用 atrm 来删除错误的指令，利用 at 来直接下达单一工作排程！很简单吧！ 不过，有个问题需要处理一下。如果你是在一个非常忙碌的系统下运作 at ， 能不能指定你的工作在系统较闲的时候才进行呢？可以的，那就使用 batch 指令吧！

  • batch：系统有空时才进行背景任务

其实 batch 是利用 at 来进行指令的下达啦！只是加入一些控制参数而已。这个 batch 神奇的地方在于：他会在 CPU 工作负载小于 0.8 的时候，才进行你所下达的工作任务啦！ 那什么是负载 0.8 呢？这个负载的意思是： CPU 在单一时间点所负责的工作数量。不是 CPU 的使用率喔！ 举例来说，如果我有一只程式他需要一直使用 CPU 的运算功能，那么此时 CPU 的使用率可能到达 100% ， 但是 CPU 的工作负载则是趋近于‘ 1 ’，因为 CPU 仅负责一个工作嘛！如果同时执行这样的程式两支呢？ CPU 的使用率还是 100% ，但是工作负载则变成 2 了！了解乎？

所以也就是说，当 CPU 的工作负载越大，代表 CPU 必须要在不同的工作之间进行频繁的工作切换。 这样的 CPU 运作情况我们在第零章有谈过，忘记的话请回去瞧瞧！因为一直切换工作，所以会导致系统忙碌啊！ 系统如果很忙碌，还要额外进行 at ，不太合理！所以才有 batch 指令的产生！

那么 batch 如何下达指令呢？很简单啊！与 at 相同啦！例如下面的范例：

范例一：同样是机房停电在 2009/3/17 23:00 关机，但若当时系统负载太高，则暂缓执行
[root@www ~]# batch 23:00 2009-3-17
at> sync
at> sync
at> shutdown -h now
at> <EOT>
job 6 at 2009-03-17 23:00

[root@www ~]# atq
6       2009-03-17 23:00 b root
[root@www ~]# atrm 6

你会发现其实 batch 也是使用 atq/atrm 来管理的！这样了解乎？

大标题的图示 循环执行的例行性工作排程

相对于 at 是仅执行一次的工作，循环执行的例行性工作排程则是由 cron (crond) 这个系统服务来控制的。刚刚谈过 Linux 系统上面原本就有非常多的例行性工作，因此这个系统服务是预设启动的。另外， 由于使用者自己也可以进行例行性工作排程，所以啰， Linux 也提供使用者控制例行性工作排程的指令 (crontab)。 底下我们分别来聊一聊啰！

小标题的图示 使用者的设定

使用者想要建立循环型工作排程时，使用的是 crontab 这个指令啦～不过，为了安全性的问题， 与 at 同样的，我们可以限制使用 crontab 的使用者帐号喔！使用的限制资料有：

  • /etc/cron.allow：
    将可以使用 crontab 的帐号写入其中，若不在这个档案内的使用者则不可使用 crontab；

  • /etc/cron.deny：
    将不可以使用 crontab 的帐号写入其中，若未记录到这个档案当中的使用者，就可以使用 crontab 。

与 at 很像吧！同样的，以优先顺序来说， /etc/cron.allow 比 /etc/cron.deny 要优先， 而判断上面，这两个档案只选择一个来限制而已，因此，建议你只要保留一个即可， 免得影响自己在设定上面的判断！一般来说，系统预设是保留 /etc/cron.deny ， 你可以将不想让他执行 crontab 的那个使用者写入 /etc/cron.deny 当中，一个帐号一行！

当使用者使用 crontab 这个指令来建立工作排程之后，该项工作就会被纪录到 /var/spool/cron/ 里面去了，而且是以帐号来作为判别的喔！举例来说， dmtsai 使用 crontab 后， 他的工作会被纪录到 /var/spool/cron/dmtsai 里头去！但请注意，不要使用 vi 直接编辑该档案， 因为可能由于输入语法错误，会导致无法执行 cron 喔！另外， cron 执行的每一项工作都会被纪录到 /var/log/cron 这个登录档中，所以啰，如果你的 Linux 不知道有否被植入木马时，也可以搜寻一下 /var/log/cron 这个登录档呢！

好了，那么我们就来聊一聊 crontab 的语法吧！

[root@www ~]# crontab [-u username] [-l|-e|-r]
选项与参数：
-u  ：只有 root 才能进行这个任务，亦即帮其他使用者建立/移除 crontab 工作排程；
-e  ：编辑 crontab 的工作内容
-l  ：查阅 crontab 的工作内容
-r  ：移除所有的 crontab 的工作内容，若仅要移除一项，请用 -e 去编辑。

范例一：用 dmtsai 的身份在每天的 12:00 发信给自己
[dmtsai@www ~]$ crontab -e
# 此时会进入 vi 的编辑画面让您编辑工作！注意到，每项工作都是一行。
0   12  *  *  * mail dmtsai -s "at 12:00" < /home/dmtsai/.bashrc
#分 时 日 月 周 |<==============指令串========================>|

预设情况下，任何使用者只要不被列入 /etc/cron.deny 当中，那么他就可以直接下达‘ crontab -e ’去编辑自己的例行性命令了！整个过程就如同上面提到的，会进入 vi 的编辑画面， 然后以一个工作一行来编辑，编辑完毕之后输入‘ :wq ’储存后离开 vi 就可以了！ 而每项工作 (每行) 的格式都是具有六个栏位，这六个栏位的意义为：

代表意义 | 分钟 | 小时 | 日期 | 月份 | 周 | 指令
数字范围 | 0-59 | 0-23 | 1-31 | 1-12 | 0-7 | 呀就指令啊

比较有趣的是那个‘周’喔！周的数字为 0 或 7 时，都代表‘星期天’的意思！另外， 还有一些辅助的字符，大概有底下这些：

特殊字符 代表意义
* 代表任何时刻都接受的意思！举例来说，范例一内那个日、月、周都是 * ， 就代表着‘不论何月、何日的礼拜几的 12:00 都执行后续指令’的意思！
, 代表分隔时段的意思。举例来说，如果要下达的工作是 3:00 与 6:00 时，就会是：
0 3,6 * * * command
时间参数还是有五栏，不过第二栏是 3,6 ，代表 3 与 6 都适用！
- 代表一段时间范围内，举例来说， 8 点到 12 点之间的每小时的 20 分都进行一项工作：
20 8-12 * * * command
仔细看到第二栏变成 8-12 喔！代表 8,9,10,11,12 都适用的意思！
/n 那个 n 代表数字，亦即是‘每隔 n 单位间隔’的意思，例如每五分钟进行一次，则：
*/5 * * * * command
很简单吧！用 * 与 /5 来搭配，也可以写成 0-59/5 ，相同意思！

我们就来搭配几个例子练习看看吧！底下的案例请实际用 dmtsai 这个身份作看看喔！后续的动作才能够搭配起来！

例题：
假若你的女朋友生日是 5 月 2 日，你想要在 5 月 1 日的 23:59 发一封信给他，这封信的内容已经写在 /home/dmtsai/lover.txt 内了，该如何进行？
答：
直接下达 crontab -e 之后，编辑成为：
59 23 1 5 * mail kiki < /home/dmtsai/lover.txt
那样的话，每年 kiki 都会收到你的这封信喔！（当然啰，信的内容就要每年变一变啦！）

例题：
假如每五分钟需要执行 /home/dmtsai/test.sh 一次，又该如何？
答：
同样使用 crontab -e 进入编辑：
*/5 * * * * /home/dmtsai/test.sh

那个 crontab 每个人都只有一个档案存在，就是在 /var/spool/cron 里面啊！ 还有建议您：‘指令下达时，最好使用绝对路径，这样比较不会找不到执行档喔！’

例题：
假如你每星期六都与朋友有约，那么想要每个星期五下午 4:30 告诉你朋友星期六的约会不要忘记，则：
答：
还是使用 crontab -e 啊！
30 16 * * 5 mail friend@his.server.name < /home/dmtsai/friend.txt

真的是很简单吧！呵呵！那么，该如何查询使用者目前的 crontab 内容呢？我们可以这样来看看：

[dmtsai@www ~]$ crontab -l
59 23 1 5 * mail kiki < /home/dmtsai/lover.txt
*/5 * * * * /home/dmtsai/test.sh
30 16 * * 5 mail friend@his.server.name < /home/dmtsai/friend.txt

# 注意，若仅想要移除一项工作而已的话，必须要用 crontab -e 去编辑～
# 如果想要全部的工作都移除，才使用 crontab -r 喔！
[dmtsai@www ~]$ crontab -r
[dmtsai@www ~]$ crontab -l
no crontab for dmtsai

看到了吗？ crontab ‘整个内容都不见了！’所以请注意：‘如果只是要删除某个 crontab 的工作项目，那么请使用 crontab -e 来重新编辑即可！’如果使用 -r 的参数，是会将所有的 crontab 资料内容都删掉的！千万注意了！

小标题的图示 系统的设定档： /etc/crontab

这个‘ crontab -e ’是针对使用者的 cron 来设计的，如果是‘系统的例行性任务’时， 该怎么办呢？是否还是需要以 crontab -e 来管理你的例行性工作排程呢？当然不需要，你只要编辑 /etc/crontab 这个档案就可以啦！有一点需要特别注意喔！那就是 crontab -e 这个 crontab 其实是 /usr/bin/crontab 这个执行档，但是 /etc/crontab 可是一个‘纯文字档’喔！你可以 root 的身份编辑一下这个档案哩！

基本上， cron 这个服务的最低侦测限制是‘分钟’，所以‘ cron 会每分钟去读取一次 /etc/crontab 与 /var/spool/cron 里面的资料内容 ’，因此，只要你编辑完 /etc/crontab 这个档案，并且将他储存之后，那么 cron 的设定就自动的会来执行了！

Tips:
在 Linux 底下的 crontab 会自动的帮我们每分钟重新读取一次 /etc/crontab 的例行工作事项，但是某些原因或者是其他的 Unix 系统中，由于 crontab 是读到记忆体当中的，所以在你修改完 /etc/crontab 之后，可能并不会马上执行， 这个时候请重新启动 crond 这个服务吧！‘/etc/init.d/crond restart’ 		鸟哥的图示

废话少说，我们就来看一下这个 /etc/crontab 的内容吧！

[root@www ~]# cat /etc/crontab
SHELL=/bin/bash                     <==使用哪种 shell 介面
PATH=/sbin:/bin:/usr/sbin:/usr/bin  <==执行档搜寻路径
MAILTO=root                         <==若有额外STDOUT，以 email将资料送给谁
HOME=/                              <==预设此 shell 的家目录所在

# run-parts
01  *  *  *  *   root      run-parts /etc/cron.hourly   <==每小时
02  4  *  *  *   root      run-parts /etc/cron.daily    <==每天
22  4  *  *  0   root      run-parts /etc/cron.weekly   <==每周日
42  4  1  *  *   root      run-parts /etc/cron.monthly  <==每个月 1 号
分 时 日 月 周 执行者身份  指令串

看到这个档案的内容你大概就了解了吧！呵呵，没错！这个档案与将刚刚我们下达 crontab -e 的内容几乎完全一模一样！只是有几个地方不太相同：

  • MAILTO=root：

    这个项目是说，当 /etc/crontab 这个档案中的例行性工作的指令发生错误时，或者是该工作的执行结果有 STDOUT/STDERR 时，会将错误讯息或者是荧幕显示的讯息传给谁？预设当然是由系统直接寄发一封 mail 给 root 啦！不过， 由于 root 并无法在用户端中以 POP3 之类的软体收信，因此，鸟哥通常都将这个 e-mail 改成自己的帐号，好让我随时了解系统的状况！例如： MAILTO=dmtsai@my.host.name

  • PATH=....：

    还记得我们在第十一章的 BASH 当中一直提到的执行档路径问题吧！ 没错啦！这里就是输入执行档的搜寻路径！使用预设的路径设定就已经很足够了！

  • 01 * * * * root run-parts /etc/cron.hourly：

    这个 /etc/crontab 里面预设定义出四项工作任务，分别是每小时、每天、每周及每个月分别进行一次的工作！ 但是在五个栏位后面接的并不是指令，而是一个新的栏位，那就是‘执行后面那串指令的身份’为何！这与使用者的 crontab -e 不相同。由于使用者自己的 crontab 并不需要指定身份，但 /etc/crontab 里面当然要指定身份啦！以上表的内容来说，系统预设的例行性工作是以 root 的身份来进行的。

    那么后面那串指令是什么呢？你可以使用‘ which run-parts ’搜寻看看，其实那是一个 bash script 啦！如果你直接进入 /usr/bin/run-parts 去看看， 会发现这支指令会将后面接的‘目录’内的所有档案捉出来执行！这也就是说‘ 如果你想让系统每小时主动帮你执行某个指令，将该指令写成 script，并将该档案放置到 /etc/cron.hourly/ 目录下即可’的意思！

    现在你知道系统是如何进行他预设的一堆例行性工作排程了吗？如果你下达‘ ll /etc/cron.daily ’就可以看到一堆档案， 那些档案就是系统提供的 script ，而这堆 scripts 将会在每天的凌晨 4:02 开始运作！这也是为啥如果你是夜猫族， 就会发现奇怪的是，Linux 系统为何早上 4:02 开始会很忙碌的发出一些硬碟跑动的声音！因为他必须要进行 makewhatis, updatedb, rpm rebuild 等等的任务嘛！

由于 CentOS 提供的 run-parts 这个 script 的辅助，因此 /etc/crontab 这个档案里面支援两种下达指令的方式， 一种是直接下达指令，一种则是以目录来规划，例如：

  • 指令型态
    01 * * * * dmtsai mail -s "testing" kiki < /home/dmtsai/test.txt
    以 dmtsai 这个使用者的身份，在每小时执行一次 mail 指令。

  • 目录规划
    */5 * * * * root run-parts /root/runcron
    建立一个 /root/runcron 的目录，将要每隔五分钟执行的‘可执行档’都写到该目录下， 就可以让系统每五分钟执行一次该目录下的所有可执行档。

好！你现在大概了解了这一个咚咚吧！OK！假设你现在要作一个目录，让系统可以每 2 分钟去执行这个目录下的所有可以执行的档案，你可以写下如下的这一行在 /etc/crontab 中：

*/2 * * * * root run-parts /etc/cron.min

当然啰， /etc/cron.min 这个目录是需要存在的喔！那如果我需要执行的是一个‘程式’而已， 不需要用到一个目录呢？该如何是好？例如在侦测网路流量时，我们希望每五分钟侦测分析一次， 可以这样写：

*/5 * * * * root /bin/mrtg /etc/mrtg/mrtg.cfg

如何！建立例行性命令很简单吧！如果你是系统管理员而且你的工作又是系统维护方面的例行任务时， 直接修改 /etc/crontab 这个档案即可喔！又便利，又方便管理呢！

小标题的图示 一些注意事项

有的时候，我们以系统的 cron 来进行例行性工作的建立时，要注意一些使用方面的特性。 举例来说，如果我们有四个工作都是五分钟要进行一次的，那么是否这四个动作全部都在同一个时间点进行？ 如果同时进行，该四个动作又很耗系统资源，如此一来，每五分钟不是会让系统忙得要死？ 呵呵！此时好好的分配一些执行时间就 OK 啦！所以，注意一下：

  • 资源分配不均的问题

当大量使用 crontab 的时候，总是会有问题发生的，最严重的问题就是‘系统资源分配不均’的问题， 以鸟哥的系统为例，我有侦测主机流量的资讯，包括：

  • 流量
  • 区域内其他 PC 的流量侦测
  • CPU 使用率
  • RAM 使用率
  • 线上人数即时侦测

如果每个流程都在同一个时间启动的话，那么在某个时段时，我的系统会变的相当的繁忙， 所以，这个时候就必须要分别设定啦！我可以这样做：

[root@www ~]# vi /etc/crontab
1,6,11,16,21,26,31,36,41,46,51,56 * * * * root  CMD1
2,7,12,17,22,27,32,37,42,47,52,57 * * * * root  CMD2
3,8,13,18,23,28,33,38,43,48,53,58 * * * * root  CMD3
4,9,14,19,24,29,34,39,44,49,54,59 * * * * root  CMD4

看到了没？那个‘ , ’分隔的时候，请注意，不要有空白字元！（连续的意思）如此一来， 则可以将每五分钟工作的流程分别在不同的时刻来工作！则可以让系统的执行较为顺畅呦！

  • 取消不要的输出项目

另外一个困扰发生在‘ 当有执行成果或者是执行的项目中有输出的资料时，该资料将会 mail 给 MAILTO 设定的帐号 ’，好啦，那么当有一个排程一直出错（例如 DNS 的侦测系统当中，若 DNS 上层主机挂掉，那么你就会一直收到错误讯息！）怎么办？呵呵！还记得十一章谈到的资料流重导向吧？ 直接以‘命令重导向’将输出的结果输出到 /dev/null 这个垃圾桶当中就好了！

  • 安全的检验

很多时候被植入木马都是以例行命令的方式植入的，所以可以藉由检查 /var/log/cron 的内容来视察是否有‘非您设定的 cron 被执行了？’这个时候就需要小心一点啰！

  • 周与日月不可同时并存

另一个需要注意的地方在于：‘你可以分别以周或者是日月为单位作为循环，但你不可使用“几月几号且为星期几”的模式工作’。 这个意思是说，你不可以这样编写一个工作排程：

30 12 11 9 5 root echo "just test"   <==这是错误的写法

本来你以为九月十一号且为星期五才会进行这项工作，无奈的是，系统可能会判定每个星期五作一次，或每年的 9 月 11 号分别进行，如此一来与你当初的规划就不一样了～所以啰，得要注意这个地方！上述的写法是不对的喔！

大标题的图示 可唤醒停机期间的工作任务

如果你的 Linux 主机是作为 24 小时全天、全年无休的伺服器之用，那么你只要有 atd 与 crond 这两个服务来管理你的例行性工作排程即可。如果你的伺服器并非 24 小时无间断的开机，那么你该如何进行例行性工作？ 举例来说，如果你每天晚上都要关机，等到白天才启动你的 Linux 主机时，由于 CentOS 预设的工作排程都在 4:02am 每天进行，唔！如此一来不就一堆系统例行工作都没有人在做了！那可怎么办？此时就得要 anacron 这家伙了！

小标题的图示 什么是 anacron

anacron 并不是用来取代 crontab 的，anacron 存在的目的就在于我们上头提到的，在处理非 24 小时一直启动的 Linux 系统的 crontab 的执行！所以 anacron 并不能指定何时执行某项任务， 而是以天为单位或者是在开机后立刻进行 anacron 的动作，他会去侦测停机期间应该进行但是并没有进行的 crontab 任务，并将该任务执行一遍后，anacron 就会自动停止了。

由于 anacron 会以一天、七天、一个月为期去侦测系统未进行的 crontab 任务，因此对于某些特殊的使用环境非常有帮助。 举例来说，如果你的 Linux 主机是放在公司给同仁使用的，因为周末假日大家都不在所以也没有必要开启， 因此你的 Linux 是周末都会关机两天的。但是 crontab 大多在每天的凌晨以及周日的早上进行各项任务， 偏偏你又关机了，此时系统很多 crontab 的任务就无法进行。 anacron 刚好可以解决这个问题！

那么 anacron 又是怎么知道我们的系统啥时关机的呢？这就得要使用 anacron 读取的时间记录档 (timestamps) 了！ anacron 会去分析现在的时间与时间记录档所记载的上次执行 anacron 的时间，两者比较后若发现有差异， 那就是在某些时刻没有进行 crontab 啰！此时 anacron 就会开始执行未进行的 crontab 任务了！ 所以 anacron 其实也是透过 crontab 来运作的！因此 anacron 运作的时间通常有两个，一个是系统开机期间运作，一个是写入 crontab 的排程中。 这样才能够在特定时间分析系统未进行的 crontab 工作嘛！了解乎！

小标题的图示 anacron 与 /etc/anacrontab

anacron 其实是一支程式并非一个服务！这支程式在 CentOS 当中已经进入 crontab 的排程喔！ 不相信吗？你可以这样追踪看看：

[root@www ~]# ll /etc/cron*/*ana*
-rwxr-xr-x 1 root root 379 Mar 28  2007 /etc/cron.daily/0anacron
-rwxr-xr-x 1 root root 381 Mar 28  2007 /etc/cron.monthly/0anacron
-rwxr-xr-x 1 root root 380 Mar 28  2007 /etc/cron.weekly/0anacron
# 刚好是每天、每周、每月有排程的工作目录！查阅一下每天的任务

[root@www ~]# cat /etc/cron.daily/0anacron
if [ ! -e /var/run/anacron.pid ]; then
    anacron -u cron.daily
fi
# 所以其实也仅是执行 anacron -u 的指令！因此我们得来谈谈这支程式！

基本上， anacron 的语法如下：

[root@www ~]# anacron [-sfn] [job]..
[root@www ~]# anacron -u [job]..
选项与参数：
-s  ：开始一连续的执行各项工作 (job)，会依据时间记录档的资料判断是否进行；
-f  ：强制进行，而不去判断时间记录档的时间戳记；
-n  ：立刻进行未进行的任务，而不延迟 (delay) 等待时间；
-u  ：仅更新时间记录档的时间戳记，不进行任何工作。
job ：由 /etc/anacrontab 定义的各项工作名称。

所以我们发现其实 /etc/cron.daily/0anacron 仅进行时间戳记的更新，而没有进行任何 anacron 的动作！ 在我们的 CentOS 中，anacron 的进行其实是在开机完成后才进行的一项工作任务，你也可以将 anacron 排入 crontab 的排程中。但是为了担心 anacron 误判时间参数，因此 /etc/cron.daily/ 里面的 anacron 才会在档名之前加个 0 (0anacron)，让 anacron 最先进行！就是为了让时间戳记先更新！以避免 anacron 误判 crontab 尚未进行任何工作的意思。

接下来我们看一下 /etc/anacrontab 的内容好了：

[root@www ~]# cat /etc/anacrontab
SHELL=/bin/sh
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root

1       65      cron.daily     run-parts /etc/cron.daily
7       70      cron.weekly    run-parts /etc/cron.weekly
30      75      cron.monthly   run-parts /etc/cron.monthly
天数   延迟时间 工作名称定义   实际要进行的指令串
# 天数单位为天；延迟时间单位为分钟；工作名称定义可自订；
# 指令串则通常与 crontab 的设定相同！

[root@www ~]# more /var/spool/anacron/*
::::::::::::::
/var/spool/anacron/cron.daily
::::::::::::::
20090315
::::::::::::::
/var/spool/anacron/cron.monthly
::::::::::::::
20090301
::::::::::::::
/var/spool/anacron/cron.weekly
::::::::::::::
20090315
# 上面则是三个工作名称的时间记录档以及记录的时间戳记

由于 /etc/cron.daily 内的任务比较多，因此我们使用每天进行的任务来解释一下 anacron 的运作情况好了。 anacron 若下达‘ anacron -s cron.daily ’时，他会这样运作的：

  1. 由 /etc/anacrontab 分析到 cron.daily 这项工作名称的天数为 1 天；
  2. 由 /var/spool/anacron/cron.daily 取出最近一次执行 anacron 的时间戳记；
  3. 由上个步骤与目前的时间比较，若差异天数为 1 天以上 (含 1 天)，就准备进行指令；
  4. 若准备进行指令，根据 /etc/anacrontab 的设定，将延迟 65 分钟
  5. 延迟时间过后，开始执行后续指令，亦即‘ run-parts /etc/cron.daily ’这串指令；
  6. 执行完毕后， anacron 程式结束。

所以说，时间戳记是非常重要的！anacron 是透过该记录与目前的时间差异，了解到是否应该要进行某项任务的工作！ 举例来说，如果我的主机在 2009/03/15(星期天) 18:00 关机，然后在 2009/03/16(星期一) 8:00 开机，由于我的 crontab 是在早上 04:00 左右进行各项任务，由于该时刻系统是关机的，因此时间戳记依旧为 20090315 (旧的时间)， 但是目前时间已经是 20090316 (新的时间)，因此 run-parts /etc/cron.daily 就会在开机过 65 分钟后开始运作了。

所以啰， anacron 并不需要额外的设定，使用预设值即可！只是我们的 CentOS 只有在开机时才会执行 anacron 就是了。如果要确定 anacron 是否开机时会主动的执行，你可以下达下列指令：

[root@www ~]# chkconfig --list anacron
anacron      0:off   1:off   2:on    3:on    4:on    5:on    6:off
# 详细的 chkconfig 说明我们会在后续章节提到，注意看 3, 5
# 的项目，都是 on ！那就是有启动啦！开机时才会执行的意思！

现在你知道为什么隔了一阵子才将 CentOS 开机，开机过后约 1 小时左右系统会有一小段时间的忙碌！而且硬碟会跑个不停！那就是因为 anacron 正在执行过去 crontab 未进行的各项工作排程啦！这样对 anacron 有没有概念了呢？ ^_^

大标题的图示 重点回顾
  • 系统可以透过 at 这个指令来排程单一工作的任务！‘at TIME’为指令下达的方法，当 at 进入排程后， 系统执行该排程工作时，会到下达时的目录进行任务；
  • at 的执行必须要有 atd 服务的支援，且 /etc/at.deny 为控制是否能够执行的使用者帐号；
  • 透过 atq, atrm 可以查询与删除 at 的工作排程；
  • batch 与 at 相同，不过 batch 可在 CPU 工作负载小于 0.8 时才进行后续的工作排程；
  • 系统的循环例行性工作排程使用 cron 这个服务，同时利用 crontab -e 及 /etc/crontab 进行排程的安排；
  • crontab -e 设定项目分为六栏，‘分、时、日、月、周、指令’为其设定依据；
  • /etc/crontab 设定分为七栏，‘分、时、日、月、周、执行者、指令’为其设定依据；
  • anacron 配合 /etc/anacrontab 的设定，可以唤醒停机期间系统未进行的 crontab 任务！
大标题的图示 本章习题
( 要看答案请将滑鼠移动到‘答：’底下的空白处，按下左键圈选空白处即可察看 )
简答题：
  • 今天假设我有一个指令程式，名称为： ping.sh 这个档名！我想要让系统每三分钟执行这个档案一次， 但是偏偏这个档案会有很多的讯息显示出来，所以我的 root 帐号每天都会收到差不多四百多封的信件，光是收信就差不多快要疯掉了！ 那么请问应该怎么设定比较好呢？
    这个涉及资料流重导向的问题，我们可以将他导入档案或者直接丢弃！如果该讯息不重要的话， 那么就予以丢弃，如果讯息很重要的话，才将他保留下来！假设今天这个命令不重要， 所以将他丢弃掉！因此，可以这样写：
    */3 * * * * root /usr/local/ping.sh > /dev/null 2>&1
  • 您预计要在 2010 年的 2 月 14 日寄出一封给 kiki ，只有该年才寄出！该如何下达指令？
    at 1am 2010-02-14
  • 下达 crontab -e 之后，如果输入这一行，代表什么意思？
    * 15 * * 1-5 /usr/local/bin/tea_time.sh
    在每星期的 1~5 ，下午 3 点的每分钟，共进行 60 次 /usr/local/bin/tea_time.sh 这个档案。 要特别注意的是，每个星期 1~5 的 3 点都会进行 60 次ㄟ！很麻烦吧～是错误的写法啦～ 应该是要写成：
    30 15 * * 1-5 /usr/local/bin/tea_time.sh
  • 我用 vi 编辑 /etc/crontab 这个档案，我编辑的那一行是这样的：
    25 00 * * 0 /usr/local/bin/backup.sh
    这一行代表的意义是什么？
    这一行代表......没有任何意义！因为语法错误！您必须要了解，在 /etc/crontab 当中每一行都必须要有使用者才行！所以，应该要将原本那行改成：
    25 00 * * 0 root /usr/local/bin/backup.sh
  • 请问，您的系统每天、每周、每个月各有进行什么工作？
    因为 CentOS 系统预设的例行性命令都放置在 /etc/cron.* 里面，所以，你可以自行去： /etc/cron.daily/, /etc/cron.week/, /etc/cron.monthly/ 这三个目录内看一看， 就知道啦！ ^_^
  • 每个星期六凌晨三点去系统搜寻一下内有 SUID/SGID 的任何档案！并将结果输出到 /tmp/uidgid.files
    vi /etc/crontab
    0 3 * * 6 root find / -perm +6000 > /tmp/uidgid.files
2002/05/30：第一次完成
2003/02/10：重新编排与加入 FAQ
2005/09/07：将旧的文章移动到 此处 。
2005/09/07：呼呼！终于完成风格啰～同时加入一些习题练习。
2009/03/12：将旧的文件移动到此处。
2009/03/14：加入 batch 这个项目的说明！与 at 有关！
2009/03/15：加入了 anacron 这玩意的简单说明！
2009/09/11：稍微修订一下说明语气与连结资料。


鸟哥的 Linux 私房菜 -- 程序管理与 SELinux 初探

为取得较佳浏览结果，请爱用 firefox 浏览本网页
鸟哥的 Linux 私房菜馆 | Linux 基础文件 | Linux 架站文件 | Linux 企业运用 | 安全管理 | 新手讨论 |

第十七章、程序管理与 SELinux 初探
最近更新日期：2009/09/11
一个程式被载入到记忆体当中运作，那么在记忆体内的那个资料就被称为程序(process)。程序是作业系统上非常重要的概念， 所有系统上面跑的资料都会以程序的型态存在。那么系统的程序有哪些状态？不同的状态会如何影响系统的运作？ 程序之间是否可以互相控管等等的，这些都是我们所必须要知道的项目。 另外与程序有关的还有 SELinux 这个加强档案存取安全性的咚咚，也必须要做个了解呢！

1. 什么是程序 (Process)
    1.1 程序与程式 (process & program)： 子程序与父程序, fork-and-exec, 系统服务
    1.2 Linux 的多人多工环境
 2. 工作管理 (job control)
    2.1 什么是工作管理
    2.2 job control 的管理：&, [ctrl]-z, jobs, fg, bg, kill
    2.3 离线管理问题： nohup
 3. 程序管理
    3.1 程序的观察： ps (ps -l, ps aux, zombie), top, pstree
    3.2 程序的管理： signal, kill, killall
    3.3 关于程序的执行顺序： priority, nice, renice
    3.4 系统资源的观察： free, uname, uptime, netstat, dmesg, vmstat
 4. 特殊档案与程序
    4.1 具有 SUID/SGID 权限的指令执行状态
    4.2 /proc/* 代表的意义
    4.3 查询已开启档案或已执行程序开启之档案： fuser, lsof, pidof
 5. SELinux 初探
    5.1 什么是 SELinux： 目标, DAC, MAC
    5.2 SELinux 的运作模式： 元件, 安全性本文, domain/type
    5.3 SELinux 的启动、关闭与观察： getenforce, sestatus, 启动与关闭, setenforce
    5.4 SELinux 网路服务运作范例： 启动 (ps -Z), 错误情况, 解决 (chcon, restorecon)
    5.5 SELinux 所需的服务： setroubleshoot, sealert, auditd, audit2why
    5.6 SELinux 的政策与规则管理： seinfo, sesearch, getsebool, setsebool, semanage
 6. 重点回顾
7. 本章习题
8. 参考资料与延伸阅读
9. 针对本文的建议：http://phorum.vbird.org/viewtopic.php?t=23890
大标题的图示 什么是程序 (process)

由前面一连几个章节的资料看来，我们一直强调在 Linux 底下所有的指令与你能够进行的动作都与权限有关， 而系统如何判定你的权限呢？当然就是第十四章帐号管理当中提到的 UID/GID 的相关概念，以及档案的属性相关性啰！再进一步来解释，你现在大概知道，在 Linux 系统当中：‘触发任何一个事件时，系统都会将他定义成为一个程序，并且给予这个程序一个 ID ，称为 PID，同时依据启发这个程序的使用者与相关属性关系，给予这个 PID 一组有效的权限设定。’ 从此以后，这个 PID 能够在系统上面进行的动作，就与这个 PID 的权限有关了！

看这个定义似乎没有什么很奇怪的地方，不过，您得要了解什么叫做‘触发事件’才行啊！ 我们在什么情况下会触发一个事件？而同一个事件可否被触发多次？呵呵！来了解了解先！

小标题的图示 程序与程式 (process & program)

我们如何产生一个程序呢？其实很简单啦，就是‘执行一个程式或指令’就可以触发一个事件而取得一个 PID 啰！我们说过，系统应该是仅认识 binary file 的，那么当我们要让系统工作的时候，当然就是需要启动一个 binary file 啰，那个 binary file 就是程式 (program) 啦！

那我们知道，每个程式都有三组人马的权限，每组人马都具有 r/w/x 的权限，所以：‘不同的使用者身份执行这个 program 时，系统给予的权限也都不相同！’举例来说，我们可以利用 touch 来建立一个空的档案，当 root 执行这个 touch 指令时，他取得的是 UID/GID = 0/0 的权限，而当 dmtsai (UID/GID=501/501) 执行这个 touch 时，他的权限就跟 root 不同啦！我们将这个概念绘制成图示来瞧瞧如下：

程式被载入成为程序以及相关资料的示意图
图 1.1.1、程式被载入成为程序以及相关资料的示意图

如上图所示，程式一般是放置在实体磁碟中，然后透过使用者的执行来触发。触发后会载入到记忆体中成为一个个体，那就是程序。 为了作业系统可管理这个程序，因此程序有给予执行者的权限/属性等参数，并包括程式所需要的指令码与资料或档案资料等， 最后再给予一个 PID 。系统就是透过这个 PID 来判断该 process 是否具有权限进行工作的！他是很重要的哩！

举个更常见的例子，我们要操作系统的时候，通常是利用连线程式或者直接在主机前面登入，然后取得我们的 shell 对吧！那么，我们的 shell 是 bash 对吧，这个 bash 在 /bin/bash 对吧，那么同时间的每个人登入都是执行 /bin/bash 对吧！不过，每个人取得的权限就是不同！也就是说，我们可以这样看：

程式与程序之间的差异
图 1.1.2、程式与程序之间的差异

也就是说，当我们登入并执行 bash 时，系统已经给我们一个 PID 了，这个 PID 就是依据登入者的 UID/GID (/etc/passwd) 来的啦～以上面的图 1.1.2 配合图 1.1.1 来做说明的话，我们知道 /bin/bash 是一个程式 (program)，当 dmtsai 登入后，他取得一个 PID 号码为 2234 的程序，这个程序的 User/Group 都是 dmtsai ，而当这个程式进行其他作业时，例如上面提到的 touch 这个指令时， 那么由这个程序衍生出来的其他程序在一般状态下，也会沿用这个程序的相关权限的！

让我们将程式与程序作个总结：

  • 程式 (program)：通常为 binary program ，放置在储存媒体中 (如硬碟、光碟、软碟、磁带等)， 为实体档案的型态存在；

  • 程序 (process)：程式被触发后，执行者的权限与属性、程式的程式码与所需资料等都会被载入记忆体中， 作业系统并给予这个记忆体内的单元一个识别码 (PID)，可以说，程序就是一个正在运作中的程式。

  • 子程序与父程序：

在上面的说明里面，我们有提到所谓的‘衍生出来的程序’，那是个啥咚咚？这样说好了，当我们登入系统后，会取得一个 bash 的 shell ，然后，我们用这个 bash 提供的介面去执行另一个指令，例如 /usr/bin/passwd 或者是 touch 等等，那些另外执行的指令也会被触发成为 PID ，呵呵！那个后来执行指令才产生的 PID 就是‘子程序’了，而在我们原本的 bash 环境下，就称为‘父程序’了！借用我们在 十一章 Bash 谈到的 export 所用的图示好了：

程序相关系之示意图
图 1.1.3、程序相关系之示意图

所以你必须要知道，程式彼此之间是有相关性的！以上面的图示来看，连续执行两个 bash 后，第二个 bash 的父程序就是前一个 bash。因为每个程序都有一个 PID ，那某个程序的父程序该如何判断？就透过 Parent PID (PPID) 来判断即可。此外，由十一章的 export 内容我们也探讨过环境变数的继承问题，子程序可以取得父程序的环境变数啦！ 让我们来进行底下的练习，以了解什么是子程序/父程序。

例题：
请在目前的 bash 环境下，再触发一次 bash ，并以‘ ps -l ’这个指令观察程序相关的输出资讯。
答：
直接执行 bash ，会进入到子程序的环境中，然后输入 ps -l 后，出现：
F S   UID   PID  PPID  C PRI  NI ADDR SZ WCHAN  TTY          TIME CMD
4 S     0  8074  8072  2  76   0 -  1287 wait   pts/1    00:00:00 bash
0 S     0  8102  8074  4  76   0 -  1287 wait   pts/1    00:00:00 bash
4 R     0  8118  8102  0  78   0 -  1101 -      pts/1    00:00:00 ps
有看到那个 PID 与 PPID 吗？第一个 bash 的 PID 与第二个 bash 的 PPID 都是 8074 啊， 因为第二个 bash 是来自于第一个所产生的嘛！另外，每部主机的程式启动状态都不一样， 所以在你的系统上面看到的 PID 与我这里的显示一定不同！那是正常的！详细的 ps 指令我们会在本章稍后介绍， 这里你只要知道 ps -l 可以查阅到相关的程序资讯即可。

很多朋友常常会发现：‘咦！明明我将有问题的程序关闭了，怎么过一阵子他又自动的产生？ 而且新产生的那个程序的 PID 与原先的还不一样，这是怎么回事呢？’不要怀疑，如果不是 crontab 工作排程的影响，肯定有一支父程序存在，所以你杀掉子程序后， 父程序就会主动再生一支！那怎么办？正所谓这：‘擒贼先擒王’，找出那支父程序，然后将他删除就对啦！

  • fork and exec：程序呼叫的流程

其实子程序与父程序之间的关系还挺复杂的，最大的复杂点在于程序互相之间的呼叫。在 Linux 的程序呼叫通常称为 fork-and-exec 的流程 (注1)！程序都会藉由父程序以复制 (fork) 的方式产生一个一模一样的子程序， 然后被复制出来的子程序再以 exec 的方式来执行实际要进行的程式，最终就成为一个子程序的存在。 整个流程有点像底下这张图：

程序使用 fork and exec 呼叫的情况示意图
图 1.1.4、程序使用 fork and exec 呼叫的情况示意图

(1)系统先以 fork 的方式复制一个与父程序相同的暂存程序，这个程序与父程序唯一的差别就是 PID 不同！ 但是这个暂存程序还会多一个 PPID 的参数，PPID 如前所述，就是父程序的程序识别码啦！然后(2)暂存程序开始以 exec 的方式载入实际要执行的程式，以上述图示来讲，新的程式名称为 qqq ，最终子程序的程式码就会变成 qqq 了！ 这样了解乎！

  • 系统或网路服务：常驻在记忆体的程序

如果就我们之前学到的一些指令资料来看，其实我们下达的指令都很简单，包括用 ls 显示档案啊、用 touch 建立档案啊、rm/mkdir/cp/mv 等指令管理档案啊、chmod/chown/passwd 等等的指令来管理权限等等的，不过， 这些指令都是执行完就结束了。也就是说，该项指令被触发后所产生的 PID 很快就会终止呢！ 那有没有一直在执行的程序啊？当然有啊！而且多的是呢！

举个简单的例子来说好了，我们知道系统每分钟都会去扫瞄 /etc/crontab 以及相关的设定档， 来进行工作排程吧？那么那个工作排程是谁负责的？当然不是鸟哥啊！ 呵呵！是 crond 这个程式所管理的，我们将他启动在背景当中一直持续不断的运作， 套句以前 DOS 年代常常说的一句话，那就是‘常驻在记忆体当中的程序’啦！

常驻在记忆体当中的程序通常都是负责一些系统所提供的功能以服务使用者各项任务，因此这些常驻程式就会被我们称为：服务 (daemon)。系统的服务非常的多， 不过主要大致分成系统本身所需要的服务，例如刚刚提到的 crond 及 atd ，还有 syslog 等等的。还有一些则是负责网路连线的服务，例如 Apache, named, postfix, vsftpd... 等等的。这些网路服务比较有趣的地方，在于这些程式被执行后，他会启动一个可以负责网路监听的埠口 (port) ，以提供外部用户端 (client) 的连线要求。

小标题的图示 Linux 的多人多工环境

我们现在知道了，其实在 Linux 底下执行一个指令时，系统会将相关的权限、属性、程式码与资料等均载入记忆体， 并给予这个单元一个程序识别码 (PID)，最终该指令可以进行的任务则与这个 PID 的权限有关。根据这个说明，我们就可以简单的了解，为什么 Linux 这么多用户，但是却每个人都可以拥有自己的环境了吧！^_^ ！底下我们来谈谈 Linux 多人多工环境的特色：

  • 多人环境：

Linux 最棒的地方就在于他的多人多工环境了！那么什么是‘多人多工’？在 Linux 系统上面具有多种不同的帐号， 每种帐号都有都有其特殊的权限，只有一个人具有至高无上的权力，那就是 root (系统管理员)。除了 root 之外，其他人都必须要受一些限制的！而每个人进入 Linux 的环境设定都可以随着每个人的喜好来设定 (还记得我们在第十一章 BASH 提过的 ~/.bashrc 吧？对了！就是那个光！)！现在知道为什么了吧？因为每个人登入后取得的 shell 的 PID 不同嘛！

  • 多工行为：

我们在第零章谈到 CPU 的速度，目前的 CPU 速度可高达几个 GHz。 这代表 CPU 每秒钟可以运作 109 这么多次指令。我们的 Linux 可以让 CPU 在各个工作间进行切换， 也就是说，其实每个工作都仅占去 CPU 的几个指令次数，所以 CPU 每秒就能够在各个程序之间进行切换啦！ 谁叫 CPU 可以在一秒钟进行这么多次的指令运作。

CPU 切换程序的工作，与这些工作进入到 CPU 运作的排程 (CPU 排程，非 crontab 排程) 会影响到系统的整体效能！ 目前 Linux 使用的多工切换行为是非常棒的一个机制，几乎可以将 PC 的性能整个压榨出来！ 由于效能非常好，因此当多人同时登入系统时，其实会感受到整部主机好像就为了你存在一般！ 这就是多人多工的环境啦！(注2)

  • 多重登入环境的七个基本终端视窗：

在 Linux 当中，预设提供了六个文字界面登入视窗，以及一个图形界面，你可以使用 [Alt]+[F1].....[F7] 来切换不同的终端机界面，而且每个终端机界面的登入者还可以不同人！ 很炫吧！这个东西可就很有用啦！尤其是在某个程序死掉的时候！

其实，这也是多工环境下所产生的一个情况啦！我们的 Linux 预设会启动六个终端机登入环境的程式，所以我们就会有六个终端机介面。 您也可以减少啊！就是减少启动的终端机程式就好了。详细的资料可以先查阅 /etc/inittab 这个档案，未来我们在开机管理流程 (第二十章) 会再仔细的介绍的！

  • 特殊的程序管理行为：

以前的鸟哥笨笨的，总是以为使用 Windows 98 就可以啦！后来，因为工作的关系，需要使用 Unix 系统，想说我只要在工作机前面就好，才不要跑来跑去的到 Unix 工作站前面去呢！所以就使用 Windows 连到我的 Unix 工作站工作！好死不死，我一个程序跑下来要 2~3 天，唉～偏偏常常到了第 2.5 天的时候， Windows 98 就给他挂点去！当初真的是给他怕死了～

后来因为换了新电脑，用了随机版的 Windows 2000 ，呵呵，这东西真不错 (指对单人而言) ，在当机的时候， 他可以仅将错误的程序踢掉，而不干扰其他的程序进行，呵呵！ 从此以后，就不用担心会当机连连啰！不过，2000 毕竟还不够好，因为有的时候还是会死当！

那么 Linux 会有这样的问题吗？老实说， Linux 几乎可以说绝对不会当机的！因为他可以在任何时候， 将某个被困住的程序杀掉，然后再重新执行该程序而不用重新开机！够炫吧！那么如果我在 Linux 下以文字界面登入，在荧幕当中显示错误讯息后就挂了～动都不能动，该如何是好！？ 这个时候那预设的七个视窗就帮上忙啦！你可以随意的再按 [Alt]+[F1].....[F7] 来切换到其他的终端机界面，然后以 ps -aux 找出刚刚的错误程序，然后给他 kill 一下，哈哈，回到刚刚的终端机界面！恩～棒！又回复正常啰！

为什么可以这样做呢？我们刚刚不是提过吗？每个程序之间可能是独立的，也可能有相依性， 只要到独立的程序当中，删除有问题的那个程序，当然他就可以被系统移除掉啦！^_^

  • bash 环境下的工作管理 (job control)

我们在上一个小节有提到所谓的‘父程序、子程序’的关系，那我们登入 bash 之后， 就是取得一个名为 bash 的 PID 了，而在这个环境底下所执行的其他指令， 就几乎都是所谓的子程序了。那么，在这个单一的 bash 介面下，我可不可以进行多个工作啊？ 当然可以啦！可以‘同时’进行喔！举例来说，我可以这样做：

[root@www ~]# cp file1 file2 &

在这一串指令中，重点在那个 & 的功能，他表示将 file1 这个档案复制为 file2 ，且放置于背景中执行， 也就是说执行这一个命令之后，在这一个终端介面仍然可以做其他的工作！而当这一个指令 (cp file1 file2) 执行完毕之后，系统将会在你的终端介面显示完成的消息！很便利喔！

  • 多人多工的系统资源分配问题考虑：

多人多工确实有很多的好处，但其实也有管理上的困扰，因为使用者越来越多， 将导致你管理上的困扰哩！另外，由于使用者日盛，当使用者达到一定的人数后， 通常你的机器便需要升级了，因为 CPU 的运算与 RAM 的大小可能就会不敷使用！

举个例子来说，鸟哥之前的网站管理的有点不太好，因为使用了一个很复杂的人数统计程式， 这个程式会一直去取用 MySQL 资料库的资料，偏偏因为流量大，造成 MySQL 很忙碌。 在这样的情况下，当鸟哥要登入去写网页资料，或者要去使用讨论区的资源时， 哇！慢的很！简直就是‘龟速’啊！后来终于将这个程式停止不用了， 以自己写的一个小程式来取代，呵呵！这样才让 CPU 的负载 (loading) 整个降下来～ 用起来顺畅多了！ ^_^

大标题的图示 工作管理 (job control)

这个工作管理 (job control) 是用在 bash 环境下的，也就是说：‘当我们登入系统取得 bash shell 之后，在单一终端机介面下同时进行多个工作的行为管理 ’。举例来说，我们在登入 bash 后， 想要一边复制档案、一边进行资料搜寻、一边进行编译，还可以一边进行 vi 程式撰写！ 当然我们可以重复登入那六个文字介面的终端机环境中，不过，能不能在一个 bash 内达成？ 当然可以啊！就是使用 job control 啦！ ^_^

小标题的图示 什么是工作管理？

从上面的说明当中，你应该要了解的是：‘进行工作管理的行为中， 其实每个工作都是目前 bash 的子程序，亦即彼此之间是有相关性的。 我们无法以 job control 的方式由 tty1 的环境去管理 tty2 的 bash ！’ 这个概念请你得先建立起来，后续的范例介绍之后，你就会清楚的了解啰！

或许你会觉得很奇怪啊，既然我可以在六个终端介面登入，那何必使用 job control 呢？ 真是脱裤子放屁，多此一举啊！不要忘记了呢，我们可以在 /etc/security/limits.conf (第十四章) 里面设定使用者同时可以登入的连线数，在这样的情况下，某些使用者可能仅能以一个连线来工作呢！ 所以啰，你就得要了解一下这种工作管理的模式了！此外，这个章节内容也会牵涉到很多的资料流重导向，所以，如果忘记的话， 务必回到第十一章 BASH Shell 看一看喔！

由于假设我们只有一个终端介面，因此在可以出现提示字元让你操作的环境就称为前景 (foreground)，至于其他工作就可以让你放入背景 (background) 去暂停或运作。要注意的是，放入背景的工作想要运作时， 他必须不能够与使用者互动。举例来说， vim 绝对不可能在背景里面执行 (running) 的！因为你没有输入资料他就不会跑啊！ 而且放入背景的工作是不可以使用 [ctrl]+c 来终止的’！

总之，要进行 bash 的 job control 必须要注意到的限制是：

  • 这些工作所触发的程序必须来自于你 shell 的子程序(只管理自己的 bash)；
  • 前景：你可以控制与下达指令的这个环境称为前景的工作 (foreground)；
  • 背景：可以自行运作的工作，你无法使用 [ctrl]+c 终止他，可使用 bg/fg 呼叫该工作；
  • 背景中‘执行’的程序不能等待 terminal/shell 的输入(input)

接下来让我们实际来管理这些工作吧！

小标题的图示 job control 的管理

如前所述，bash 只能够管理自己的工作而不能管理其他 bash 的工作，所以即使你是 root 也不能够将别人的 bash 底下的 job 给他拿过来执行。此外，又分前景与背景，然后在背景里面的工作状态又可以分为‘暂停 (stop)’与‘运作中 (running)’。那实际进行 job 控制的指令有哪些？底下就来谈谈。

  • 直接将指令丢到背景中‘执行’的 &

如同前面提到的，我们在只有一个 bash 的环境下，如果想要同时进行多个工作， 那么可以将某些工作直接丢到背景环境当中，让我们可以继续操作前景的工作！那么如何将工作丢到背景中？ 最简单的方法就是利用‘ & ’这个玩意儿了！举个简单的例子，我们要将 /etc/ 整个备份成为 /tmp/etc.tar.gz 且不想要等待，那么可以这样做：

[root@www ~]# tar -zpcf /tmp/etc.tar.gz /etc &
[1] 8400  <== [job number] PID
[root@www ~]# tar: Removing leading `/' from member names
# 在中括号内的号码为工作号码 (job number)，该号码与 bash 的控制有关。
# 后续的 8400 则是这个工作在系统中的 PID。至于后续出现的资料是 tar 执行的资料流，
# 由于我们没有加上资料流重导向，所以会影响画面！不过不会影响前景的操作喔！

仔细的瞧一瞧，我在输入一个指令后，在该指令的最后面加上一个‘ & ’代表将该指令丢到背景中， 此时 bash 会给予这个指令一个‘工作号码(job number)’，就是那个 [1] 啦！至于后面那个 8400 则是该指令所触发的‘ PID ’了！而且，有趣的是，我们可以继续操作 bash 呢！很不赖吧！ 不过，那么丢到背景中的工作什么时候完成？完成的时候会显示什么？如果你输入几个指令后，突然出现这个资料：

[1]+  Done                    tar -zpcf /tmp/etc.tar.gz /etc

就代表 [1] 这个工作已经完成 (Done) ，该工作的指令则是接在后面那一串指令列。 这样了解了吧！另外，这个 & 代表：‘将工作丢到背景中去执行’喔！ 注意到那个‘执行’的字眼！此外，这样的情况最大的好处是： 不怕被 [ctrl]+c 中断的啦！ 此外，将工作丢到背景当中要特别注意资料的流向喔！包括上面的讯息就有出现错误讯息，导致我的前景被影响。 虽然只要按下 [enter] 就会出现提示字元。但如果我将刚刚那个指令改成：

[root@www ~]# tar -zpcvf /tmp/etc.tar.gz /etc &

情况会怎样？在背景当中执行的指令，如果有 stdout 及 stderr 时，他的资料依旧是输出到荧幕上面的， 所以，我们会无法看到提示字元，当然也就无法完好的掌握前景工作。同时由于是背景工作的 tar ， 此时你怎么按下 [ctrl]+c 也无法停止荧幕被搞的花花绿绿的！所以啰，最佳的状况就是利用资料流重导向， 将输出资料传送至某个档案中。举例来说，我可以这样做：

[root@www ~]# tar -zpcvf /tmp/etc.tar.gz /etc > /tmp/log.txt 2>&1 &
[1] 8429
[root@www ~]#

呵呵！如此一来，输出的资讯都给他传送到 /tmp/log.txt 当中，当然就不会影响到我们前景的作业了。 这样说，您应该可以更清楚资料流重导向的重要性了吧！^_^

Tips:
工作号码 (job number) 只与你这个 bash 环境有关，但是他既然是个指令触发的咚咚，所以当然一定是一个程序， 因此你会观察到有 job number 也搭配一个 PID ！ 		鸟哥的图示
  • 将‘目前’的工作丢到背景中‘暂停’：[ctrl]-z

想个情况：如果我正在使用 vi ，却发现我有个档案不知道放在哪里，需要到 bash 环境下进行搜寻，此时是否要结束 vi 呢？呵呵！当然不需要啊！只要暂时将 vi 给他丢到背景当中等待即可。 例如以下的案例：

[root@www ~]# vi ~/.bashrc
# 在 vi 的一般模式下，按下 [ctrl]-z 这两个按键
[1]+  Stopped                 vim ~/.bashrc
[root@www ~]#   <==顺利取得了前景的操控权！
[root@www ~]# find / -print
....(输出省略)....
# 此时荧幕会非常的忙碌！因为荧幕上会显示所有的档名。请按下 [ctrl]-z 暂停
[2]+  Stopped                 find / -print

在 vi 的一般模式下，按下 [ctrl] 及 z 这两个按键，荧幕上会出现 [1] ，表示这是第一个工作， 而那个 + 代表最近一个被丢进背景的工作，且目前在背景下预设会被取用的那个工作 (与 fg 这个指令有关 )！而那个 Stopped 则代表目前这个工作的状态。在预设的情况下，使用 [ctrl]-z 丢到背景当中的工作都是‘暂停’的状态喔！

  • 观察目前的背景工作状态： jobs
[root@www ~]# jobs [-lrs]
选项与参数：
-l  ：除了列出 job number 与指令串之外，同时列出 PID 的号码；
-r  ：仅列出正在背景 run 的工作；
-s  ：仅列出正在背景当中暂停 (stop) 的工作。

范例一：观察目前的 bash 当中，所有的工作，与对应的 PID
[root@www ~]# jobs -l
[1]- 10314 Stopped                 vim ~/.bashrc
[2]+ 10833 Stopped                 find / -print

如果想要知道目前有多少的工作在背景当中，就用 jobs 这个指令吧！一般来说，直接下达 jobs 即可！ 不过，如果你还想要知道该 job number 的 PID 号码，可以加上 -l 这个参数啦！ 在输出的资讯当中，例如上表，仔细看到那个 + - 号喔！那个 + 代表预设的取用工作。 所以说：‘目前我有两个工作在背景当中，两个工作都是暂停的， 而如果我仅输入 fg 时，那么那个 [2] 会被拿到前景当中来处理’！

其实 + 代表最近被放到背景的工作号码， - 代表最近最后第二个被放置到背景中的工作号码。 而超过最后第三个以后的工作，就不会有 +/- 符号存在了！

  • 将背景工作拿到前景来处理：fg

刚刚提到的都是将工作丢到背景当中去执行的，那么有没有可以将背景工作拿到前景来处理的？ 有啊！就是那个 fg (foreground) 啦！举例来说，我们想要将上头范例当中的工作拿出来处理时：

[root@www ~]# fg %jobnumber
选项与参数：
%jobnumber ：jobnumber 为工作号码(数字)。注意，那个 % 是可有可无的！

范例一：先以 jobs 观察工作，再将工作取出：
[root@www ~]# jobs
[1]- 10314 Stopped                 vim ~/.bashrc
[2]+ 10833 Stopped                 find / -print
[root@www ~]# fg      <==预设取出那个 + 的工作，亦即 [2]。立即按下[ctrl]-z
[root@www ~]# fg %1   <==直接规定取出的那个工作号码！再按下[ctrl]-z
[root@www ~]# jobs
[1]+  Stopped                 vim ~/.bashrc
[2]-  Stopped                 find / -print

经过 fg 指令就能够将背景工作拿到前景来处理啰！不过比较有趣的是最后一个显示的结果，我们会发现 + 出现在第一个工作后！ 怎么会这样啊？这是因为你刚刚利用 fg %1 将第一号工作捉到前景后又放回背景，此时最后一个被放入背景的将变成 vi 那个指令动作， 所以当然 [1] 后面就会出现 + 了！了解乎！另外，如果输入‘ fg - ’ 则代表将 - 号的那个工作号码拿出来，上面就是 [2]- 那个工作号码啦！

  • 让工作在背景下的状态变成运作中： bg

我们刚刚提到，那个 [ctrl]-z 可以将目前的工作丢到背景底下去‘暂停’， 那么如何让一个工作在背景底下‘ Run ’呢？我们可以在底下这个案例当中来测试！ 注意喔！底下的测试要进行的快一点！^_^

范例一：一执行 find / -perm +7000 > /tmp/text.txt 后，立刻丢到背景去暂停！
[root@www ~]# find / -perm +7000 > /tmp/text.txt
# 此时，请立刻按下 [ctrl]-z 暂停！
[3]+  Stopped                 find / -perm +7000 > /tmp/text.txt

范例二：让该工作在背景下进行，并且观察他！！
[root@www ~]# jobs ; bg %3 ; jobs
[1]-  Stopped                 vim ~/.bashrc
[2]   Stopped                 find / -print
[3]+  Stopped                 find / -perm +7000 > /tmp/text.txt
[3]+ find / -perm +7000 > /tmp/text.txt &  <==用 bg%3 的情况！
[1]+  Stopped                 vim ~/.bashrc
[2]   Stopped                 find / -print
[3]-  Running                 find / -perm +7000 > /tmp/text.txt &

看到哪里有差异吗？呼呼！没错！就是那个状态列～以经由 Stopping 变成了 Running 啰！ 看到差异点，嘿嘿！指令列最后方多了一个 & 的符号啰！ 代表该工作被启动在背景当中了啦！ ^_^

  • 管理背景当中的工作： kill

刚刚我们可以让一个已经在背景当中的工作继续工作，也可以让该工作以 fg 拿到前景来， 那么，如果想要将该工作直接移除呢？或者是将该工作重新启动呢？这个时候就得需要给予该工作一个讯号 (signal) ，让他知道该怎么作才好啊！此时， kill 这个指令就派上用场啦！

[root@www ~]# kill -signal %jobnumber
[root@www ~]# kill -l
选项与参数：
-l  ：这个是 L 的小写，列出目前 kill 能够使用的讯号 (signal) 有哪些？
signal ：代表给予后面接的那个工作什么样的指示啰！用 man 7 signal 可知：
  -1 ：重新读取一次参数的设定档 (类似 reload)；
  -2 ：代表与由键盘输入 [ctrl]-c 同样的动作；
  -9 ：立刻强制删除一个工作；
  -15：以正常的程序方式终止一项工作。与 -9 是不一样的。

范例一：找出目前的 bash 环境下的背景工作，并将该工作‘强制删除’。
[root@www ~]# jobs
[1]+  Stopped                 vim ~/.bashrc
[2]   Stopped                 find / -print
[root@www ~]# kill -9 %2; jobs
[1]+  Stopped                 vim ~/.bashrc
[2]   Killed                  find / -print
# 再过几秒你再下达 jobs 一次，就会发现 2 号工作不见了！因为被移除了！

范例：找出目前的 bash 环境下的背景工作，并将该工作‘正常终止’掉。
[root@www ~]# jobs
[1]+  Stopped                 vim ~/.bashrc
[root@www ~]# kill -SIGTERM %1
# -SIGTERM 与 -15 是一样的！您可以使用 kill -l 来查阅！

特别留意一下， -9 这个 signal 通常是用在‘强制删除一个不正常的工作’时所使用的， -15 则是以正常步骤结束一项工作(15也是预设值)，两者之间并不相同呦！举上面的例子来说， 我用 vi 的时候，不是会产生一个 .filename.swp 的档案吗？ 那么，当使用 -15 这个 signal 时， vi 会尝试以正常的步骤来结束掉该 vi 的工作， 所以 .filename.swp 会主动的被移除。但若是使用 -9 这个 signal 时，由于该 vi 工作会被强制移除掉，因此， .filename.swp 就会继续存在档案系统当中。这样您应该可以稍微分辨一下了吧？

其实， kill 的妙用是很无穷的啦！他搭配 signal 所详列的资讯 (用 man 7 signal 去查阅相关资料) 可以让您有效的管理工作与程序 (Process)，此外，那个 killall 也是同样的用法！ 至于常用的 signal 您至少需要了解 1, 9, 15 这三个 signal 的意义才好。 此外， signal 除了以数值来表示之外，也可以使用讯号名称喔！ 举例来说，上面的范例二就是一个例子啦！至于 signal number 与名称的对应， 呵呵，使用 kill -l 就知道啦(L的小写)！

另外， kill 后面接的数字预设会是 PID ，如果想要管理 bash 的工作控制，就得要加上 %数字 了， 这点也得特别留意才行喔！

小标题的图示 离线管理问题

要注意的是，我们在工作管理当中提到的‘背景’指的是在终端机模式下可以避免 [crtl]-c 中断的一个情境， 并不是放到系统的背景去喔！所以，工作管理的背景依旧与终端机有关啦！ 在这样的情况下，如果你是以远端连线方式连接到你的 Linux 主机，并且将工作以 & 的方式放到背景去， 请问，在工作尚未结束的情况下你离线了，该工作还会继续进行吗？答案是‘否’！不会继续进行，而是会被中断掉。

那怎么办？如果我的工作需要进行一大段时间，我又不能放置在背景底下，那该如何处理呢？ 首先，你可以参考前一章的 at 来处理即可！因为 at 是将工作放置到系统背景， 而与终端机无关。如果不想要使用 at 的话，那你也可以尝试使用 nohup 这个指令来处理喔！这个 nohup 可以让你在离线或登出系统后，还能够让工作继续进行。他的语法有点像这样：

[root@www ~]# nohup [指令与参数]   <==在终端机前景中工作
[root@www ~]# nohup [指令与参数] & <==在终端机背景中工作

有够好简单的指令吧！上述指令需要注意的是， nohup 并不支援 bash 内建的指令，因此你的指令必须要是外部指令才行。 我们来尝试玩一下底下的任务吧！

# 1. 先编辑一支会‘睡着 500 秒’的程式：
[root@www ~]# vim sleep500.sh
#!/bin/bash
/bin/sleep 500s
/bin/echo "I have slept 500 seconds."

# 2. 丢到背景中去执行，并且立刻登出系统：
[root@www ~]# chmod a+x sleep500.sh
[root@www ~]# nohup ./sleep500.sh &
[1] 5074
[root@www ~]# nohup: appending output to ‘nohup.out’ <==会告知这个讯息！
[root@www ~]# exit

如果你再次登入的话，再使用 ps -l 去查阅你的程序，会发现 sleep500.sh 还在执行中喔！并不会被中断掉！ 这样了解意思了吗？由于我们的程式最后会输出一个讯息，但是 nohup 与终端机其实无关了， 因此这个讯息的输出就会被导向‘ ~/nohup.out ’，所以你才会看到上述指令中，当你输入 nohup 后， 会出现那个提示讯息啰。

如果你想要让在背景的工作在你登出后还能够继续的执行，那么使用 nohup 搭配 & 是不错的运作情境喔！ 可以参考看看！

大标题的图示 程序管理

本章一开始就提到所谓的‘程序’的概念，包括程序的触发、子程序与父程序的相关性等等， 此外，还有那个‘程序的相依性’以及所谓的‘僵尸程序’等等需要说明的呢！为什么程序管理这么重要呢？这是因为：

  • 首先，本章一开始就谈到的，我们在操作系统时的各项工作其实都是经过某个 PID 来达成的 (包括你的 bash 环境)， 因此，能不能进行某项工作，就与该程序的权限有关了。
  • 再来，如果您的 Linux 系统是个很忙碌的系统，那么当整个系统资源快要被使用光时， 您是否能够找出最耗系统的那个程序，然后删除该程序，让系统恢复正常呢？
  • 此外，如果由于某个程式写的不好，导致产生一个有问题的程序在记忆体当中，您又该如何找出他，然后将他移除呢？
  • 如果同时有五六项工作在您的系统当中运作，但其中有一项工作才是最重要的， 该如何让那一项重要的工作被最优先执行呢？

所以啰，一个称职的系统管理员，必须要熟悉程序的管理流程才行，否则当系统发生问题时，还真是很难解决问题呢！ 底下我们会先介绍如何观察程序与程序的状态，然后再加以程序控制啰！

小标题的图示 程序的观察

既然程序这么重要，那么我们如何查阅系统上面正在运作当中的程序呢？很简单啊！ 利用静态的 ps 或者是动态的 top，还能以 pstree 来查阅程序树之间的关系喔！

  • ps ：将某个时间点的程序运作情况撷取下来
[root@www ~]# ps aux  <==观察系统所有的程序资料
[root@www ~]# ps -lA  <==也是能够观察所有系统的资料
[root@www ~]# ps axjf <==连同部分程序树状态
选项与参数：
-A  ：所有的 process 均显示出来，与 -e 具有同样的效用；
-a  ：不与 terminal 有关的所有 process ；
-u  ：有效使用者 (effective user) 相关的 process ；
x   ：通常与 a 这个参数一起使用，可列出较完整资讯。
输出格式规划：
l   ：较长、较详细的将该 PID 的的资讯列出；
j   ：工作的格式 (jobs format)
-f  ：做一个更为完整的输出。

鸟哥个人认为 ps 这个指令的 man page 不是很好查阅，因为很多不同的 Unix 都使用这个 ps 来查阅程序状态， 为了要符合不同版本的需求，所以这个 man page 写的非常的庞大！因此，通常鸟哥都会建议你，直接背两个比较不同的选项， 一个是只能查阅自己 bash 程序的‘ ps -l ’一个则是可以查阅所有系统运作的程序‘ ps aux ’！注意，你没看错，是‘ ps aux ’没有那个减号 (-) ！先来看看关于自己 bash 程序状态的观察：

  • 仅观察自己的 bash 相关程序： ps -l
范例一：将目前属于您自己这次登入的 PID 与相关资讯列示出来(只与自己的 bash 有关)
[root@www ~]# ps -l
F S   UID   PID  PPID  C PRI  NI ADDR SZ WCHAN  TTY          TIME CMD
4 S     0 13639 13637  0  75   0 -  1287 wait   pts/1    00:00:00 bash
4 R     0 13700 13639  0  77   0 -  1101 -      pts/1    00:00:00 ps

系统整体的程序运作是非常多的，但如果使用 ps -l 则仅列出与你的操作环境 (bash) 有关的程序而已， 亦即最上层的父程序会是你自己的 bash 而没有延伸到 init 这支程序去！那么 ps -l 秀出来的资料有哪些呢？ 我们就来观察看看：

  • F：代表这个程序旗标 (process flags)，说明这个程序的总结权限，常见号码有：
    • 若为 4 表示此程序的权限为 root ；
    • 若为 1 则表示此子程序仅进行复制(fork)而没有实际执行(exec)。

  • S：代表这个程序的状态 (STAT)，主要的状态有：
    • R (Running)：该程式正在运作中；
    • S (Sleep)：开程式目前正在睡眠状态(idle)，但可以被唤醒(signal)。
    • D ：不可被唤醒的睡眠状态，通常这支程式可能在等待 I/O 的情况(ex>列印)
    • T ：停止状态(stop)，可能是在工作控制(背景暂停)或除错 (traced) 状态；
    • Z (Zombie)：僵尸状态，程序已经终止但却无法被移除至记忆体外。

  • UID/PID/PPID：代表‘此程序被该 UID 所拥有/程序的 PID 号码/此程序的父程序 PID 号码’

  • C：代表 CPU 使用率，单位为百分比；

  • PRI/NI：Priority/Nice 的缩写，代表此程序被 CPU 所执行的优先顺序，数值越小代表该程序越快被 CPU 执行。详细的 PRI 与 NI 将在下一小节说明。

  • ADDR/SZ/WCHAN：都与记忆体有关，ADDR 是 kernel function，指出该程序在记忆体的哪个部分，如果是个 running 的程序，一般就会显示‘ - ’ / SZ 代表此程序用掉多少记忆体 / WCHAN 表示目前程序是否运作中，同样的， 若为 - 表示正在运作中。

  • TTY：登入者的终端机位置，若为远端登入则使用动态终端介面 (pts/n)；

  • TIME：使用掉的 CPU 时间，注意，是此程序实际花费 CPU 运作的时间，而不是系统时间；

  • CMD：就是 command 的缩写，造成此程序的触发程式之指令为何。

所以你看到的 ps -l 输出讯息中，他说明的是：‘bash 的程式属于 UID 为 0 的使用者，状态为睡眠 (sleep)， 之所以为睡眠因为他触发了 ps (状态为 run) 之故。此程序的 PID 为 13639，优先执行顺序为 75 ， 下达 bash 所取得的终端介面为 pts/1 ，运作状态为等待 (wait) 。’这样已经够清楚了吧？ 您自己尝试解析一下那么 ps 那一行代表的意义为何呢？ ^_^

接下来让我们使用 ps 来观察一下系统内所有的程序状态吧！

  • 观察系统所有程序： ps aux
范例二：列出目前所有的正在记忆体当中的程序：
[root@www ~]# ps aux
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root         1  0.0  0.0   2064   616 ?        Ss   Mar11   0:01 init [5]
root         2  0.0  0.0      0     0 ?        S<   Mar11   0:00 [migration/0]
root         3  0.0  0.0      0     0 ?        SN   Mar11   0:00 [ksoftirqd/0]
.....(中间省略).....
root     13639  0.0  0.2   5148  1508 pts/1    Ss   11:44   0:00 -bash
root     14232  0.0  0.1   4452   876 pts/1    R+   15:52   0:00 ps aux
root     18593  0.0  0.0   2240   476 ?        Ss   Mar14   0:00 /usr/sbin/atd

你会发现 ps -l 与 ps aux 显示的项目并不相同！在 ps aux 显示的项目中，各栏位的意义为：

  • USER：该 process 属于那个使用者帐号的？
  • PID ：该 process 的程序识别码。
  • %CPU：该 process 使用掉的 CPU 资源百分比；
  • %MEM：该 process 所占用的实体记忆体百分比；
  • VSZ ：该 process 使用掉的虚拟记忆体量 (Kbytes)
  • RSS ：该 process 占用的固定的记忆体量 (Kbytes)
  • TTY ：该 process 是在那个终端机上面运作，若与终端机无关则显示 ?，另外， tty1-tty6 是本机上面的登入者程序，若为 pts/0 等等的，则表示为由网路连接进主机的程序。
  • STAT：该程序目前的状态，状态显示与 ps -l 的 S 旗标相同 (R/S/T/Z)
  • START：该 process 被触发启动的时间；
  • TIME ：该 process 实际使用 CPU 运作的时间。
  • COMMAND：该程序的实际指令为何？

一般来说，ps aux 会依照 PID 的顺序来排序显示，我们还是以 13639 那个 PID 那行来说明！该行的意义为‘ root 执行的 bash PID 为 13639，占用了 0.2% 的记忆体容量百分比，状态为休眠 (S)，该程序启动的时间为 11:44 ， 且取得的终端机环境为 pts/1 。’与 ps aux 看到的其实是同一个程序啦！这样可以理解吗？ 让我们继续使用 ps 来观察一下其他的资讯吧！

范例三：以范例一的显示内容，显示出所有的程序：
[root@www ~]# ps -lA
F S   UID   PID  PPID  C PRI  NI ADDR SZ WCHAN  TTY          TIME CMD
4 S     0     1     0  0  76   0 -   435 -      ?        00:00:01 init
1 S     0     2     1  0  94  19 -     0 ksofti ?        00:00:00 ksoftirqd/0
1 S     0     3     1  0  70  -5 -     0 worker ?        00:00:00 events/0
....(以下省略)....
# 你会发现每个栏位与 ps -l 的输出情况相同，但显示的程序则包括系统所有的程序。

范例四：列出类似程序树的程序显示：
[root@www ~]# ps axjf
 PPID   PID  PGID   SID TTY      TPGID STAT   UID   TIME COMMAND
    0     1     1     1 ?           -1 Ss       0   0:01 init [5]
.....(中间省略).....
    1  4586  4586  4586 ?           -1 Ss       0   0:00 /usr/sbin/sshd
 4586 13637 13637 13637 ?           -1 Ss       0   0:00  \_ sshd: root@pts/1
13637 13639 13639 13639 pts/1    14266 Ss       0   0:00      \_ -bash
13639 14266 14266 13639 pts/1    14266 R+       0   0:00          \_ ps axjf
.....(后面省略).....

看出来了吧？其实鸟哥在进行一些测试时，都是以网路连线进主机来测试的，所以啰，你会发现其实程序之间是有相关性的啦！ 不过，其实还可以使用 pstree 来达成这个程序树喔！以上面的例子来看，鸟哥是透过 sshd 提供的网路服务取得一个程序， 该程序提供 bash 给我使用，而我透过 bash 再去执行 ps axjf ！这样可以看的懂了吗？其他各栏位的意义请 man ps (虽然真的很难 man 的出来！) 啰！

范例五：找出与 cron 与 syslog 这两个服务有关的 PID 号码？
[root@www ~]# ps aux | egrep '(cron|syslog)'
root   4286  0.0  0.0  1720   572 ?      Ss  Mar11   0:00 syslogd -m 0
root   4661  0.0  0.1  5500  1192 ?      Ss  Mar11   0:00 crond
root  14286  0.0  0.0  4116   592 pts/1  R+  16:15   0:00 egrep (cron|syslog)
# 所以号码是 4286 及 4661 这两个啰！就是这样找的啦！

除此之外，我们必须要知道的是‘僵尸 (zombie) ’程序是什么？ 通常，造成僵尸程序的成因是因为该程序应该已经执行完毕，或者是因故应该要终止了， 但是该程序的父程序却无法完整的将该程序结束掉，而造成那个程序一直存在记忆体当中。 如果你发现在某个程序的 CMD 后面还接上 <defunct> 时，就代表该程序是僵尸程序啦，例如：

apache  8683  0.0  0.9 83384 9992 ?   Z  14:33   0:00 /usr/sbin/httpd <defunct>

当系统不稳定的时候就容易造成所谓的僵尸程序，可能是因为程式写的不好啦，或者是使用者的操作习惯不良等等所造成。 如果你发现系统中很多僵尸程序时，记得啊！要找出该程序的父程序，然后好好的做个追踪，好好的进行主机的环境最佳化啊！ 看看有什么地方需要改善的，不要只是直接将他 kill 掉而已呢！不然的话，万一他一直产生，那可就麻烦了！ @_@

事实上，通常僵尸程序都已经无法控管，而直接是交给 init 这支程式来负责了，偏偏 init 是系统第一支执行的程式， 他是所有程式的父程式！我们无法杀掉该程式的 (杀掉他，系统就死掉了！)，所以啰，如果产生僵尸程序， 而系统过一阵子还没有办法透过核心非经常性的特殊处理来将该程序删除时，那你只好透过 reboot 的方式来将该程序抹去了！

  • top：动态观察程序的变化

相对于 ps 是撷取一个时间点的程序状态， top 则可以持续侦测程序运作的状态！使用方式如下：

[root@www ~]# top [-d 数字] | top [-bnp]
选项与参数：
-d  ：后面可以接秒数，就是整个程序画面更新的秒数。预设是 5 秒；
-b  ：以批次的方式执行 top ，还有更多的参数可以使用喔！
      通常会搭配资料流重导向来将批次的结果输出成为档案。
-n  ：与 -b 搭配，意义是，需要进行几次 top 的输出结果。
-p  ：指定某些个 PID 来进行观察监测而已。
在 top 执行过程当中可以使用的按键指令：
    ? ：显示在 top 当中可以输入的按键指令；
    P ：以 CPU 的使用资源排序显示；
    M ：以 Memory 的使用资源排序显示；
    N ：以 PID 来排序喔！
    T ：由该 Process 使用的 CPU 时间累积 (TIME+) 排序。
    k ：给予某个 PID 一个讯号  (signal)
    r ：给予某个 PID 重新制订一个 nice 值。
    q ：离开 top 软体的按键。

其实 top 的功能非常多！可以用的按键也非常的多！可以参考 man top 的内部说明文件！ 鸟哥这里仅是列出一些鸟哥自己常用的选项而已。接下来让我们实际观察一下如何使用 top 与 top 的画面吧！

范例一：每两秒钟更新一次 top ，观察整体资讯：
[root@www ~]# top -d 2
top - 17:03:09 up 7 days, 16:16,  1 user,  load average: 0.00, 0.00, 0.00
Tasks:  80 total,   1 running,  79 sleeping,   0 stopped,   0 zombie
Cpu(s):  0.5%us,  0.5%sy,  0.0%ni, 99.0%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st
Mem:    742664k total,   681672k used,    60992k free,   125336k buffers
Swap:  1020088k total,       28k used,  1020060k free,   311156k cached
    <==如果加入 k 或 r 时，就会有相关的字样出现在这里喔！
  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
14398 root      15   0  2188 1012  816 R  0.5  0.1   0:00.05 top
    1 root      15   0  2064  616  528 S  0.0  0.1   0:01.38 init
    2 root      RT  -5     0    0    0 S  0.0  0.0   0:00.00 migration/0
    3 root      34  19     0    0    0 S  0.0  0.0   0:00.00 ksoftirqd/0

top 也是个挺不错的程序观察工具！但不同于 ps 是静态的结果输出， top 这个程式可以持续的监测整个系统的程序工作状态。 在预设的情况下，每次更新程序资源的时间为 5 秒，不过，可以使用 -d 来进行修改。 top 主要分为两个画面，上面的画面为整个系统的资源使用状态，基本上总共有六行，显示的内容依序是：

  • 第一行(top...)：这一行显示的资讯分别为：
    • 目前的时间，亦即是 17:03:09 那个项目；
    • 开机到目前为止所经过的时间，亦即是 up 7days, 16:16 那个项目；
    • 已经登入系统的使用者人数，亦即是 1 user项目；
    • 系统在 1, 5, 15 分钟的平均工作负载。我们在第十六章谈到的 batch 工作方式为负载小于 0.8 就是这个负载啰！代表的是 1, 5, 15 分钟，系统平均要负责运作几个程序(工作)的意思。 越小代表系统越闲置，若高于 1 得要注意你的系统程序是否太过繁复了！

  • 第二行(Tasks...)：显示的是目前程序的总量与个别程序在什么状态(running, sleeping, stopped, zombie)。 比较需要注意的是最后的 zombie 那个数值，如果不是 0 ！好好看看到底是那个 process 变成僵尸了吧？

  • 第三行(Cpus...)：显示的是 CPU 的整体负载，每个项目可使用 ? 查阅。需要特别注意的是 %wa ，那个项目代表的是 I/O wait， 通常你的系统会变慢都是 I/O 产生的问题比较大！因此这里得要注意这个项目耗用 CPU 的资源喔！ 另外，如果是多核心的设备，可以按下数字键‘1’来切换成不同 CPU 的负载率。

  • 第四行与第五行：表示目前的实体记忆体与虚拟记忆体 (Mem/Swap) 的使用情况。 再次重申，要注意的是 swap 的使用量要尽量的少！如果 swap 被用的很大量，表示系统的实体记忆体实在不足！

  • 第六行：这个是当在 top 程式当中输入指令时，显示状态的地方。

至于 top 下半部分的画面，则是每个 process 使用的资源情况。比较需要注意的是：

  • PID ：每个 process 的 ID 啦！
  • USER：该 process 所属的使用者；
  • PR ：Priority 的简写，程序的优先执行顺序，越小越早被执行；
  • NI ：Nice 的简写，与 Priority 有关，也是越小越早被执行；
  • %CPU：CPU 的使用率；
  • %MEM：记忆体的使用率；
  • TIME+：CPU 使用时间的累加；

top 预设使用 CPU 使用率 (%CPU) 作为排序的重点，如果你想要使用记忆体使用率排序，则可以按下‘M’， 若要回复则按下‘P’即可。如果想要离开 top 则按下‘ q ’吧！如果你想要将 top 的结果输出成为档案时， 可以这样做：

范例二：将 top 的资讯进行 2 次，然后将结果输出到 /tmp/top.txt
[root@www ~]# top -b -n 2 > /tmp/top.txt
# 这样一来，嘿嘿！就可以将 top 的资讯存到 /tmp/top.txt 档案中了。

这玩意儿很有趣！可以帮助你将某个时段 top 观察到的结果存成档案，可以用在你想要在系统背景底下执行。 由于是背景底下执行，与终端机的荧幕大小无关，因此可以得到全部的程序画面！那如果你想要观察的程序 CPU 与记忆体使用率都很低，结果老是无法在第一行显示时，该怎办？我们可以仅观察单一程序喔！如下所示：

范例三：我们自己的 bash PID 可由 $$ 变数取得，请使用 top 持续观察该 PID
[root@www ~]# echo $$
13639  <==就是这个数字！他是我们 bash 的 PID
[root@www ~]# top -d 2 -p 13639
top - 17:31:56 up 7 days, 16:45,  1 user,  load average: 0.00, 0.00, 0.00
Tasks:   1 total,   0 running,   1 sleeping,   0 stopped,   0 zombie
Cpu(s):  0.0%us,  0.0%sy,  0.0%ni,100.0%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st
Mem:    742664k total,   682540k used,    60124k free,   126548k buffers
Swap:  1020088k total,       28k used,  1020060k free,   311276k cached

  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
13639 root      15   0  5148 1508 1220 S  0.0  0.2   0:00.18 bash

看到没！就只会有一支程序给你看！很容易观察吧！好，那么如果我想要在 top 底下进行一些动作呢？ 比方说，修改 NI 这个数值呢？可以这样做：

范例四：承上题，上面的 NI 值是 0 ，想要改成 10 的话？
# 在范例三的 top 画面当中直接按下 r 之后，会出现如下的图样！
top - 17:34:24 up 7 days, 16:47,  1 user,  load average: 0.00, 0.00, 0.00
Tasks:   1 total,   0 running,   1 sleeping,   0 stopped,   0 zombie
Cpu(s):  0.0%us,  0.0%sy,  0.0%ni, 99.5%id,  0.0%wa,  0.0%hi,  0.5%si,  0.0%st
Mem:    742664k total,   682540k used,    60124k free,   126636k buffers
Swap:  1020088k total,       28k used,  1020060k free,   311276k cached
PID to renice: 13639  <==按下 r 然后输入这个 PID 号码
  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
13639 root      15   0  5148 1508 1220 S  0.0  0.2   0:00.18 bash

在你完成上面的动作后，在状态列会出现如下的资讯：

Renice PID 13639 to value: 10   <==这是 nice 值
  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND

接下来你就会看到如下的显示画面！

top - 17:38:58 up 7 days, 16:52,  1 user,  load average: 0.00, 0.00, 0.00
Tasks:   1 total,   0 running,   1 sleeping,   0 stopped,   0 zombie
Cpu(s):  0.0%us,  0.0%sy,  0.0%ni,100.0%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st
Mem:    742664k total,   682540k used,    60124k free,   126648k buffers
Swap:  1020088k total,       28k used,  1020060k free,   311276k cached

  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
13639 root      26  10  5148 1508 1220 S  0.0  0.2   0:00.18 bash

看到不同处了吧？底线的地方就是修改了之后所产生的效果！一般来说，如果鸟哥想要找出最损耗 CPU 资源的那个程序时，大多使用的就是 top 这支程式啦！然后强制以 CPU 使用资源来排序 (在 top 当中按下 P 即可)， 就可以很快的知道啦！ ^_^。多多爱用这个好用的东西喔！

  • pstree
[root@www ~]# pstree [-A|U] [-up]
选项与参数：
-A  ：各程序树之间的连接以 ASCII 字元来连接；
-U  ：各程序树之间的连接以万国码的字元来连接。在某些终端介面下可能会有错误；
-p  ：并同时列出每个 process 的 PID；
-u  ：并同时列出每个 process 的所属帐号名称。

范例一：列出目前系统上面所有的程序树的相关性：
[root@www ~]# pstree -A
init-+-acpid
     |-atd
     |-auditd-+-audispd---{audispd}  <==这行与底下一行为 auditd 分出来的子程序
     |        `-{auditd}
     |-automount---4*[{automount}]   <==预设情况下，相似的程序会以数字显示
....(中间省略)....
     |-sshd---sshd---bash---pstree   <==就是我们指令执行的那个相依性！
....(底下省略)....
# 注意一下，为了节省版面，所以鸟哥已经删去很多程序了！

范例二：承上题，同时秀出 PID 与 users
[root@www ~]# pstree -Aup
init(1)-+-acpid(4555)
        |-atd(18593)
        |-auditd(4256)-+-audispd(4258)---{audispd}(4261)
        |              `-{auditd}(4257)
        |-automount(4536)-+-{automount}(4537) <==程序相似但 PID 不同！
        |                 |-{automount}(4538)
        |                 |-{automount}(4541)
        |                 `-{automount}(4544)
....(中间省略)....
        |-sshd(4586)---sshd(16903)---bash(16905)---pstree(16967)
....(中间省略)....
        |-xfs(4692,xfs)   <==因为此程序拥有者并非执行 pstree 者！所以列出帐号
....(底下省略)....
# 在括号 () 内的即是 PID 以及该程序的 owner 喔！不过，由于我是使用
# root 的身份执行此一指令，所以属于 root 的程序就不会显示出来啦！

如果要找程序之间的相关性，这个 pstree 真是好用到不行！直接输入 pstree 可以查到程序相关性，如上表所示，还会使用线段将相关性程序连结起来哩！ 一般连结符号可以使用 ASCII 码即可，但有时因为语系问题会主动的以 Unicode 的符号来连结， 但因为可能终端机无法支援该编码，或许会造成乱码问题。因此可以加上 -A 选项来克服此类线段乱码问题。

由 pstree 的输出我们也可以很清楚的知道，所有的程序都是依附在 init 这支程序底下的！ 仔细看一下，这支程序的 PID 是一号喔！因为他是由 Linux 核心所主动呼叫的第一支程式！所以 PID 就是一号了。 这也是我们刚刚提到僵尸程序时有提到，为啥发生僵尸程序需要重新开机？ 因为 init 要重新启动，而重新启动 init 就是 reboot 啰！

如果还想要知道 PID 与所属使用者，加上 -u 及 -p 两个参数即可。我们前面不是一直提到， 如果子程序挂点或者是老是砍不掉子程序时，该如何找到父程序吗？呵呵！用这个 pstree 就对了！ ^_^

小标题的图示 程序的管理

程序之间是可以互相控制的！举例来说，你可以关闭、重新启动伺服器软体，伺服器软体本身是个程序， 你既然可以让她关闭或启动，当然就是可以控制该程序啦！那么程序是如何互相管理的呢？其实是透过给予该程序一个讯号 (signal) 去告知该程序你想要让她作什么！因此这个讯号就很重要啦！

我们也在本章之前的 bash 工作管理当中提到过， 要给予某个已经存在背景中的工作某些动作时，是直接给予一个讯号给该工作号码即可。那么到底有多少 signal 呢？ 你可以使用 kill -l (小写的 L ) 或者是 man 7 signal 都可以查询到！主要的讯号代号与名称对应及内容是：

代号 | 名称 | 内容
1 | SIGHUP | 启动被终止的程序，可让该 PID 重新读取自己的设定档，类似重新启动
2 | SIGINT | 相当于用键盘输入 [ctrl]-c 来中断一个程序的进行
9 | SIGKILL | 代表强制中断一个程序的进行，如果该程序进行到一半， 那么尚未完成的部分可能会有‘半产品’产生，类似 vim会有 .filename.swp 保留下来。
15 | SIGTERM | 以正常的结束程序来终止该程序。由于是正常的终止， 所以后续的动作会将他完成。不过，如果该程序已经发生问题，就是无法使用正常的方法终止时， 输入这个 signal 也是没有用的。
17 | SIGSTOP | 相当于用键盘输入 [ctrl]-z 来暂停一个程序的进行

上面仅是常见的 signal 而已，更多的讯号资讯请自行 man 7 signal 吧！一般来说，你只要记得‘1, 9, 15’这三个号码的意义即可。那么我们如何传送一个讯号给某个程序呢？就透过 kill 或 killall 吧！底下分别来看看：

  • kill -signal PID

kill 可以帮我们将这个 signal 传送给某个工作 (%jobnumber) 或者是某个 PID (直接输入数字)。 要再次强调的是： kill 后面直接加数字与加上 %number 的情况是不同的！ 这个很重要喔！因为工作控制中有 1 号工作，但是 PID 1 号则是专指‘ init ’这支程式！你怎么可以将 init 关闭呢？ 关闭 init ，你的系统就当掉了啊！所以记得那个 % 是专门用在工作控制的喔！ 我们就活用一下 kill 与刚刚上面提到的 ps 来做个简单的练习吧！

例题：
以 ps 找出 syslog 这个程序的 PID 后，再使用 kill 传送讯息，使得 syslog 可以重新读取设定档。
答：
由于需要重新读取设定档，因此 signal 是 1 号。至于找出 syslog 的 PID 可以是这样做：
ps aux | grep 'syslog' | grep -v 'grep'| awk '{print $2}'
接下来则是实际使用 kill -1 PID，因此，整串指令会是这样：
kill -SIGHUP $(ps aux|grep 'syslog'|grep -v 'grep'|awk '{print $2}')
如果要确认有没有重新启动 syslog ，可以参考登录档的内容，使用如下指令查阅：
tail -5 /var/log/messages
如果你有看到类似‘Mar 19 15:08:20 www syslogd 1.4.1: restart’之类的字样，就是表示 syslogd 在 3/19 有重新启动 (restart) 过了！

了解了这个用法以后，如果未来你想要将某个莫名其妙的登入者的连线删除的话，就可以透过使用 pstree -p 找到相关程序， 然后再以 kill -9 将该程序删除，该条连线就会被踢掉了！这样很简单吧！

  • killall -signal 指令名称

由于 kill 后面必须要加上 PID (或者是 job number)，所以，通常 kill 都会配合 ps, pstree 等指令，因为我们必须要找到相对应的那个程序的 ID 嘛！但是，如此一来，很麻烦～有没有可以利用‘下达指令的名称’来给予讯号的？举例来说，能不能直接将 syslog 这个程序给予一个 SIGHUP 的讯号呢？可以的！用 killall 吧！

[root@www ~]# killall [-iIe] [command name]
选项与参数：
-i  ：interactive 的意思，互动式的，若需要删除时，会出现提示字元给使用者；
-e  ：exact 的意思，表示‘后面接的 command name 要一致’，但整个完整的指令
      不能超过 15 个字元。
-I  ：指令名称(可能含参数)忽略大小写。

范例一：给予 syslogd 这个指令启动的 PID 一个 SIGHUP 的讯号
[root@www ~]# killall -1 syslogd
# 如果用 ps aux 仔细看一下，syslogd 才是完整的指令名称。但若包含整个参数，
# 则 syslogd -m 0 才是完整的呢！

范例二：强制终止所有以 httpd 启动的程序
[root@www ~]# killall -9 httpd

范例三：依次询问每个 bash 程式是否需要被终止运作！
[root@www ~]# killall -i -9 bash
Kill bash(16905) ? (y/N) n <==这个不杀！
Kill bash(17351) ? (y/N) y <==这个杀掉！
# 具有互动的功能！可以询问你是否要删除 bash 这个程式。要注意，若没有 -i 的参数，
# 所有的 bash 都会被这个 root 给杀掉！包括 root 自己的 bash 喔！ ^_^

总之，要删除某个程序，我们可以使用 PID 或者是启动该程序的指令名称， 而如果要删除某个服务呢？呵呵！最简单的方法就是利用 killall ， 因为他可以将系统当中所有以某个指令名称启动的程序全部删除。 举例来说，上面的范例二当中，系统内所有以 httpd 启动的程序，就会通通的被删除啦！ ^_^

小标题的图示 关于程序的执行顺序

我们知道 Linux 是多人多工的环境，由 top 的输出结果我们也发现， 系统同时间有非常多的程序在运行中，只是绝大部分的程序都在休眠 (sleeping) 状态而已。 想一想，如果所有的程序同时被唤醒，那么 CPU 应该要先处理那个程序呢？也就是说，那个程序被执行的优先序比较高？ 这就得要考虑到程序的优先执行序 (Priority) 与 CPU 排程啰！

Tips:
CPU 排程与前一章的例行性工作排程并不一样。 CPU 排程指的是每支程序被 CPU 运作的演算规则， 而例行性工作排程则是将某支程式安排在某个时间再交由系统执行。 CPU 排程与作业系统较具有相关性！ 		鸟哥的图示
  • Priority 与 Nice 值

我们知道 CPU 一秒钟可以运作多达数 G 的微指令次数，透过核心的 CPU 排程可以让各程序被 CPU 所切换运作， 因此每个程序在一秒钟内或多或少都会被 CPU 执行部分的指令码。如果程序都是集中在一个伫列中等待 CPU 的运作， 而不具有优先顺序之分，也就是像我们去游乐场玩热门游戏需要排队一样，每个人都是照顺序来！ 你玩过一遍后还想再玩 (没有执行完毕)，请到后面继续排队等待。情况有点像底下这样：

并没有优先顺序的程序伫列示意图
图 3.3.1、并没有优先顺序的程序伫列示意图

上图中假设 pro1, pro2 是紧急的程序， pro3, pro4 是一般的程序，在这样的环境中，由于不具有优先顺序， 唉啊！pro1, pro2 还是得要继续等待而没有优待呢！如果 pro3, pro4 的工作又臭又长！那么紧急的 pro1, pro2 就得要等待个老半天才能够完成！真麻烦啊！所以啰，我们想要将程序分优先顺序啦！如果优先序较高则运作次数可以较多次， 而不需要与较慢优先的程序抢位置！我们可以将程序的优先顺序与 CPU 排程进行如下图的解释：

具有优先顺序的程序伫列示意图
图 3.3.2、具有优先顺序的程序伫列示意图

如上图所示，具高优先权的 pro1, pro2 可以被取用两次，而较不重要的 pro3, pro4 则运作次数较少。 如此一来 pro1, pro2 就可以较快被完成啦！要注意，上图仅是示意图，并非较优先者一定会被运作两次啦！ 为了要达到上述的功能，我们 Linux 给予程序一个所谓的‘优先执行序 (priority, PRI)’， 这个 PRI 值越低代表越优先的意思。不过这个 PRI 值是由核心动态调整的， 使用者无法直接调整 PRI 值的。先来瞧瞧 PRI 曾在哪里出现？

[root@www ~]# ps -l
F S   UID   PID  PPID  C PRI  NI ADDR SZ WCHAN  TTY          TIME CMD
4 S     0 18625 18623  2  75   0 -  1514 wait   pts/1    00:00:00 bash
4 R     0 18653 18625  0  77   0 -  1102 -      pts/1    00:00:00 ps

由于 PRI 是核心动态调整的，我们使用者也无权去干涉 PRI ！那如果你想要调整程序的优先执行序时，就得要透过 Nice 值了！Nice 值就是上表的 NI 啦！一般来说， PRI 与 NI 的相关性如下：

PRI(new) = PRI(old) + nice

不过你要特别留意到，如果原本的 PRI 是 50 ，并不是我们给予一个 nice = 5 ，就会让 PRI 变成 55 喔！ 因为 PRI 是系统‘动态’决定的，所以，虽然 nice 值是可以影响 PRI ，不过， 最终的 PRI 仍是要经过系统分析后才会决定的。另外， nice 值是有正负的喔，而既然 PRI 越小越早被执行， 所以，当 nice 值为负值时，那么该程序就会降低 PRI 值，亦即会变的较优先被处理。此外，你必须要留意到：

  • nice 值可调整的范围为 -20 ~ 19 ；
  • root 可随意调整自己或他人程序的 Nice 值，且范围为 -20 ~ 19 ；
  • 一般使用者仅可调整自己程序的 Nice 值，且范围仅为 0 ~ 19 (避免一般用户抢占系统资源)；
  • 一般使用者仅可将 nice 值越调越高，例如本来 nice 为 5 ，则未来仅能调整到大于 5；

这也就是说，要调整某个程序的优先执行序，就是‘调整该程序的 nice 值’啦！那么如何给予某个程序 nice 值呢？有两种方式，分别是：

  • 一开始执行程式就立即给予一个特定的 nice 值：用 nice 指令；
  • 调整某个已经存在的 PID 的 nice 值：用 renice 指令。

  • nice ：新执行的指令即给予新的 nice 值
[root@www ~]# nice [-n 数字] command
选项与参数：
-n  ：后面接一个数值，数值的范围 -20 ~ 19。

范例一：用 root 给一个 nice 植为 -5 ，用于执行 vi ，并观察该程序！
[root@www ~]# nice -n -5 vi &
[1] 18676
[root@www ~]# ps -l
F S   UID   PID  PPID  C PRI  NI ADDR SZ WCHAN  TTY          TIME CMD
4 S     0 18625 18623  0  75   0 -  1514 wait   pts/1    00:00:00 bash
4 T     0 18676 18625  0  72  -5 -  1242 finish pts/1    00:00:00 vi
4 R     0 18678 18625  0  77   0 -  1101 -      pts/1    00:00:00 ps
# 原本的 bash PRI 为 75  ，所以 vi 预设应为 75。不过由于给予 nice  为 -5 ，
# 因此 vi 的 PRI 降低了！但并非降低到 70 ，因为核心还会动态调整！

[root@www ~]# kill -9 %1 <==测试完毕将 vi 关闭

就如同前面说的， nice 是用来调整程序的执行优先顺序！这里只是一个执行的范例罢了！ 通常什么时候要将 nice 值调大呢？举例来说，系统的背景工作中， 某些比较不重要的程序之进行：例如备份工作！由于备份工作相当的耗系统资源， 这个时候就可以将备份的指令之 nice 值调大一些，可以使系统的资源分配的更为公平！

  • renice ：已存在程序的 nice 重新调整
[root@www ~]# renice [number] PID
选项与参数：
PID ：某个程序的 ID 啊！

范例一：找出自己的 bash PID ，并将该 PID 的 nice 调整到 10
[root@www ~]# ps -l
F S   UID   PID  PPID  C PRI  NI ADDR SZ WCHAN  TTY          TIME CMD
4 S     0 18625 18623  0  75   0 -  1514 wait   pts/1    00:00:00 bash
4 R     0 18712 18625  0  77   0 -  1102 -      pts/1    00:00:00 ps

[root@www ~]# renice 10 18625
18625: old priority 0, new priority 10

[root@www ~]# ps -l
F S   UID   PID  PPID  C PRI  NI ADDR SZ WCHAN  TTY          TIME CMD
4 S     0 18625 18623  0  85  10 -  1514 wait   pts/1    00:00:00 bash
4 R     0 18715 18625  0  87  10 -  1102 -      pts/1    00:00:00 ps

如果要调整的是已经存在的某个程序的话，那么就得要使用 renice 了。使用的方法很简单， renice 后面接上数值及 PID 即可。因为后面接的是 PID ，所以你务必要以 ps 或者其他程序观察的指令去找出 PID 才行啊！

由上面这个范例当中我们也看的出来，虽然修改的是 bash 那个程序，但是该程序所触发的 ps 指令当中的 nice 也会继承而为 10 喔！了解了吧！整个 nice 值是可以在父程序 --> 子程序之间传递的呢！ 另外，除了 renice 之外，其实那个 top 同样的也是可以调整 nice 值的！

小标题的图示 系统资源的观察

除了系统的程序之外，我们还必须就系统的一些资源进行检查啊！举例来说，我们使用 top 可以看到很多系统的资源对吧！那么，还有没有其他的工具可以查阅的？ 当然有啊！底下这些工具指令可以玩一玩！

  • free ：观察记忆体使用情况
[root@www ~]# free [-b|-k|-m|-g] [-t]
选项与参数：
-b  ：直接输入 free 时，显示的单位是 Kbytes，我们可以使用 b(bytes), m(Mbytes)
      k(Kbytes), 及 g(Gbytes) 来显示单位喔！
-t  ：在输出的最终结果，显示实体记忆体与 swap 的总量。

范例一：显示目前系统的记忆体容量
[root@www ~]# free -m
          total       used    free   shared   buffers    cached
Mem:        725        666      59        0       132       287
-/+ buffers/cache:     245     479
Swap:       996          0     996

仔细看看，我的系统当中有 725MB 左右的实体记忆体，我的 swap 有 1GB 左右， 那我使用 free -m 以 MBytes 来显示时，就会出现上面的资讯。Mem 那一行显示的是实体记忆体的量， Swap 则是虚拟记忆体的量。 total 是总量， used 是已被使用的量， free 则是剩余可用的量。 后面的 shared/buffers/cached 则是在已被使用的量当中，用来作为缓冲及快取的量。

仔细的看到范例一的输出喔，我们的 Linux 测试用主机是很平凡的，根本没有什么工作， 但是，我的实体记忆体是几乎被用光光的情况呢！不过，至少有 132MB 用在缓冲记忆 (buffers) 工作， 287MB 则用在快取 (cached) 工作，也就是说，系统是‘很有效率的将所有的记忆体用光光’， 目的是为了让系统的存取效能加速啦！

很多朋友都会问到这个问题‘我的系统明明很轻松，为何记忆体会被用光光？’现在了了吧？ 被用光是正常的！而需要注意的反而是 swap 的量。一般来说， swap 最好不要被使用，尤其 swap 最好不要被使用超过 20% 以上， 如果您发现 swap 的用量超过 20% ，那么，最好还是买实体记忆体来插吧！ 因为， Swap 的效能跟实体记忆体实在差很多，而系统会使用到 swap ， 绝对是因为实体记忆体不足了才会这样做的！如此，了解吧！

Tips:
Linux 系统为了要加速系统效能，所以会将最常使用到的或者是最近使用到的档案资料快取 (cache) 下来， 这样未来系统要使用该档案时，就直接由记忆体中搜寻取出，而不需要重新读取硬碟，速度上面当然就加快了！ 因此，实体记忆体被用光是正常的喔！ 		鸟哥的图示
  • uname：查阅系统与核心相关资讯
[root@www ~]# uname [-asrmpi]
选项与参数：
-a  ：所有系统相关的资讯，包括底下的资料都会被列出来；
-s  ：系统核心名称
-r  ：核心的版本
-m  ：本系统的硬体名称，例如 i686 或 x86_64 等；
-p  ：CPU 的类型，与 -m 类似，只是显示的是 CPU 的类型！
-i  ：硬体的平台 (ix86)

范例一：输出系统的基本资讯
[root@www ~]# uname -a
Linux www.vbird.tsai 2.6.18-92.el5 #1 SMP Tue Jun 10 18:49:47 EDT 2008 i686
i686 i386 GNU/Linux

这个咚咚我们前面使用过很多次了喔！uname 可以列出目前系统的核心版本、 主要硬体平台以及 CPU 类型等等的资讯。以上面范例一的状态来说，我的 Linux 主机使用的核心名称为 Linux，而主机名称为 www.vbird.tsai，核心的版本为 2.6.18-92.el5 ，该核心版本建立的日期为 2008/6/10，适用的硬体平台为 i386 以上等级的硬体平台喔。

  • uptime：观察系统启动时间与工作负载

这个指令很单纯呢！就是显示出目前系统已经开机多久的时间，以及 1, 5, 15 分钟的平均负载就是了。还记得 top 吧？没错啦！这个 uptime 可以显示出 top 画面的最上面一行！

[root@www ~]# uptime
 15:39:13 up 8 days, 14:52,  1 user,  load average: 0.00, 0.00, 0.00
# top 这个指令已经谈过相关资讯，不再聊！

  • netstat ：追踪网路或插槽档

这个 netstat 也是挺好玩的，其实这个指令比较常被用在网路的监控方面，不过，在程序管理方面也是需要了解的啦！ 这个指令的执行如下所示：基本上， netstat 的输出分为两大部分，分别是网路与系统自己的程序相关性部分：

[root@www ~]# netstat -[atunlp]
选项与参数：
-a  ：将目前系统上所有的连线、监听、Socket 资料都列出来
-t  ：列出 tcp 网路封包的资料
-u  ：列出 udp 网路封包的资料
-n  ：不已程序的服务名称，以埠号 (port number) 来显示；
-l  ：列出目前正在网路监听 (listen) 的服务；
-p  ：列出该网路服务的程序 PID

范例一：列出目前系统已经建立的网路连线与 unix socket 状态
[root@www ~]# netstat
Active Internet connections (w/o servers) <==与网路较相关的部分
Proto Recv-Q Send-Q Local Address        Foreign Address      State
tcp        0    132 192.168.201.110:ssh  192.168.:vrtl-vmf-sa ESTABLISHED
Active UNIX domain sockets (w/o servers)  <==与本机的程序自己的相关性(非网路)
Proto RefCnt Flags       Type       State         I-Node Path
unix  20     [ ]         DGRAM                    9153   /dev/log
unix  3      [ ]         STREAM     CONNECTED     13317  /tmp/.X11-unix/X0
unix  3      [ ]         STREAM     CONNECTED     13233  /tmp/.X11-unix/X0
unix  3      [ ]         STREAM     CONNECTED     13208  /tmp/.font-unix/fs7100
....(中间省略)....

在上面的结果当中，显示了两个部分，分别是网路的连线以及 linux 上面的 socket 程序相关性部分。 我们先来看看网际网路连线情况的部分：

  • Proto ：网路的封包协定，主要分为 TCP 与 UDP 封包，相关资料请参考伺服器篇；
  • Recv-Q：非由使用者程式连结到此 socket 的复制的总 bytes 数；
  • Send-Q：非由远端主机传送过来的 acknowledged 总 bytes 数；
  • Local Address ：本地端的 IP:port 情况
  • Foreign Address：远端主机的 IP:port 情况
  • State ：连线状态，主要有建立(ESTABLISED)及监听(LISTEN)；

我们上看上面仅有一条连线的资料，他的意义是：‘透过 TCP 封包的连线，远端的 192.168.:vrtl.. 连线到本地端的 192.168.201.110:ssh ，这条连线状态是建立 (ESTABLISHED) 的状态！’至于更多的网路环境说明， 就得到鸟哥的另一本伺服器篇查阅啰！

除了网路上的连线之外，其实 Linux 系统上面的程序是可以接收不同程序所发送来的资讯，那就是 Linux 上头的插槽档 (socket file)。我们在第六章的档案种类有稍微提到 socket 档案， 但当时未谈到程序的概念，所以没有深入谈论。socket file 可以沟通两个程序之间的资讯，因此程序可以取得对方传送过来的资料。 由于有 socket file，因此类似 X Window 这种需要透过网路连接的软体，目前新版的 distributions 就以 socket 来进行视窗介面的连线沟通了。上表中 socket file 的输出栏位有：

  • Proto ：一般就是 unix 啦；
  • RefCnt：连接到此 socket 的程序数量；
  • Flags ：连线的旗标；
  • Type ：socket 存取的类型。主要有确认连线的 STREAM 与不需确认的 DGRAM 两种；
  • State ：若为 CONNECTED 表示多个程序之间已经连线建立。
  • Path ：连接到此 socket 的相关程式的路径！或者是相关资料输出的路径。

以上表的输出为例，最后那三行在 /tmp/.xx 底下的资料，就是 X Window 视窗介面的相关程序啦！ 而 PATH 指向的就是这些程序要交换资料的插槽档案啰！好！那么 netstat 可以帮我们进行什么任务呢？ 很多喔！我们先来看看，利用 netstat 去看看我们的哪些程序有启动哪些网路的‘后门’呢？

范例二：找出目前系统上已在监听的网路连线及其 PID
[root@www ~]# netstat -tlnp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address    Foreign Address  State   PID/Program name
tcp        0      0 127.0.0.1:2208   0.0.0.0:*        LISTEN  4566/hpiod
tcp        0      0 0.0.0.0:111      0.0.0.0:*        LISTEN  4328/portmap
tcp        0      0 127.0.0.1:631    0.0.0.0:*        LISTEN  4597/cupsd
tcp        0      0 0.0.0.0:728      0.0.0.0:*        LISTEN  4362/rpc.statd
tcp        0      0 127.0.0.1:25     0.0.0.0:*        LISTEN  4629/sendmail:
tcp        0      0 127.0.0.1:2207   0.0.0.0:*        LISTEN  4571/python
tcp        0      0 :::22            :::*             LISTEN  4586/sshd
# 除了可以列出监听网路的介面与状态之外，最后一个栏位还能够显示此服务的
# PID 号码以及程序的指令名称喔！例如最后一行的 4586 就是该 PID

范例三：将上述的本地端 127.0.0.1:631 那个网路服务关闭的话？
[root@www ~]# kill -9 4597
[root@www ~]# killall -9 cupsd

很多朋友常常有疑问，那就是，我的主机目前到底开了几个门(ports)！其实，不论主机提供什么样的服务， 一定必须要有相对应的 program 在主机上面执行才行啊！举例来说，我们鸟园的 Linux 主机提供的就是 WWW 服务，那么我的主机当然有一个程式在提供 WWW 的服务啊！那就是 Apache 这个软体所提供的啦！ ^_^。 所以，当我执行了这个程式之后，我的系统自然就可以提供 WWW 的服务了。那如何关闭啊？ 就关掉该程式所触发的那个程序就好了！例如上面的范例三所提供的例子啊！ ^_^

  • dmesg ：分析核心产生的讯息

系统在开机的时候，核心会去侦测系统的硬体，你的某些硬体到底有没有被捉到，那就与这个时候的侦测有关。 但是这些侦测的过程要不是没有显示在荧幕上，就是很飞快的在荧幕上一闪而逝！能不能把核心侦测的讯息捉出来瞧瞧？ 可以的，那就使用 dmesg 吧！

所有核心侦测的讯息，不管是开机时候还是系统运作过程中，反正只要是核心产生的讯息，都会被记录到记忆体中的某个保护区段。 dmesg 这个指令就能够将该区段的讯息读出来的！因为讯息实在太多了，所以执行时可以加入这个管线指令‘ | more ’来使画面暂停！

范例一：输出所有的核心开机时的资讯
[root@www ~]# dmesg | more

范例二：搜寻开机的时候，硬碟的相关资讯为何？
[root@www ~]# dmesg | grep -i hd
    ide0: BM-DMA at 0xd800-0xd807, BIOS settings: hda:DMA, hdb:DMA
    ide1: BM-DMA at 0xd808-0xd80f, BIOS settings: hdc:pio, hdd:pio
hda: IC35L040AVER07-0, ATA DISK drive
hdb: ASUS DRW-2014S1, ATAPI CD/DVD-ROM drive
hda: max request size: 128KiB
....(底下省略)....

由范例二就知道我这部主机的硬碟的格式是什么了吧！没错啦！还可以查阅能不能找到网路卡喔！网路卡的代号是 eth ，所以，直接输入 dmesg | grep -i eth 试看看呢！

  • vmstat ：侦测系统资源变化

如果你想要动态的了解一下系统资源的运作，那么这个 vmstat 确实可以玩一玩！vmstat 可以侦测‘ CPU / 记忆体 / 磁碟输入输出状态 ’等等，如果你想要了解一部繁忙的系统到底是哪个环节最累人， 可以使用 vmstat 分析看看。底下是常见的选项与参数说明：

[root@www ~]# vmstat [-a] [延迟 [总计侦测次数]] <==CPU/记忆体等资讯
[root@www ~]# vmstat [-fs]                      <==记忆体相关
[root@www ~]# vmstat [-S 单位]                  <==设定显示数据的单位
[root@www ~]# vmstat [-d]                       <==与磁碟有关
[root@www ~]# vmstat [-p 分割槽]                <==与磁碟有关
选项与参数：
-a  ：使用 inactive/active(活跃与否) 取代 buffer/cache 的记忆体输出资讯；
-f  ：将开机到目前为止，系统复制 (fork) 的程序数；
-s  ：将一些事件 (开机至目前为止) 导致的记忆体变化情况列表说明；
-S  ：后面可以接单位，让显示的资料有单位。例如 K/M 取代 bytes 的容量；
-d  ：列出磁碟的读写总量统计表
-p  ：后面列出分割槽，可显示该分割槽的读写总量统计表

范例一：统计目前主机 CPU 状态，每秒一次，共计三次！
[root@www ~]# vmstat 1 3
procs -----------memory---------- ---swap-- -----io---- --system-- -----cpu------
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 0  0     28  61540 137000 291960    0    0     4     5   38   55  0  0 100  0  0
 0  0     28  61540 137000 291960    0    0     0     0 1004   50  0  0 100  0  0
 0  0     28  61540 137000 291964    0    0     0     0 1022   65  0  0 100  0  0

利用 vmstat 甚至可以进行追踪喔！你可以使用类似‘ vmstat 5 ’代表每五秒钟更新一次，且无穷的更新！直到你按下 [ctrl]-c 为止。如果你想要即时的知道系统资源的运作状态，这个指令就不能不知道！那么上面的表格各项栏位的意义为何？ 基本说明如下：

  • 记忆体栏位 (procs) 的项目分别为：
    r ：等待运作中的程序数量；b：不可被唤醒的程序数量。这两个项目越多，代表系统越忙碌 (因为系统太忙，所以很多程序就无法被执行或一直在等待而无法被唤醒之故)。

  • 记忆体栏位 (memory) 项目分别为：
    swpd：虚拟记忆体被使用的容量； free：未被使用的记忆体容量； buff：用于缓冲记忆体； cache：用于快取记忆体。 这部份则与 free 是相同的。

  • 记忆体置换空间 (swap) 的项目分别为：
    si：由磁碟中将程序取出的量； so：由于记忆体不足而将没用到的程序写入到磁碟的 swap 的容量。 如果 si/so 的数值太大，表示记忆体内的资料常常得在磁碟与主记忆体之间传来传去，系统效能会很差！

  • 磁碟读写 (io) 的项目分别为：
    bi：由磁碟写入的区块数量； bo：写入到磁碟去的区块数量。如果这部份的值越高，代表系统的 I/O 非常忙碌！

  • 系统 (system) 的项目分别为：
    in：每秒被中断的程序次数； cs：每秒钟进行的事件切换次数；这两个数值越大，代表系统与周边设备的沟通非常频繁！ 这些周边设备当然包括磁碟、网路卡、时间钟等。

  • CPU 的项目分别为：
    us：非核心层的 CPU 使用状态； sy：核心层所使用的 CPU 状态； id：闲置的状态； wa：等待 I/O 所耗费的 CPU 状态； st：被虚拟机器 (virtual machine) 所盗用的 CPU 使用状态 (2.6.11 以后才支援)。

由于鸟哥的机器是测试机，所以并没有什么 I/O 或者是 CPU 忙碌的情况。如果改天你的伺服器非常忙碌时， 记得使用 vmstat 去看看，到底是哪个部分的资源被使用的最为频繁！一般来说，如果 I/O 部分很忙碌的话，你的系统会变的非常慢！ 让我们再来看看，那么磁碟的部分该如何观察：

范例二：系统上面所有的磁碟的读写状态
[root@www ~]# vmstat -d
disk- ------------reads------------ ------------writes----------- -----IO------
       total merged sectors      ms  total merged sectors      ms    cur    sec
ram0       0      0       0       0      0      0       0       0      0      0
....(中间省略)....
hda   144188 182874 6667154 7916979 151341 510244 8027088 15244705      0    848
hdb        0      0       0       0      0      0       0       0      0      0

详细的各栏位就请诸位大德查阅一下 man vmstat 啰！反正与读写有关啦！这样了解乎！

大标题的图示 特殊档案与程序

我们在第七章曾经谈到特殊权限的 SUID/SGID/SBIT ，虽然第七章已经将这三种特殊权限作了详细的解释，不过，我们依旧要来探讨的是，那么到底这些权限对于你的‘程序’是如何影响的？ 此外，程序可能会使用到系统资源，举例来说，磁碟就是其中一项资源。哪天你在 umount 磁碟时，系统老是出现‘ device is busy ’的字样～到底是怎么回事啊？我们底下就来谈一谈这些和程序有关系的细节部分：

小标题的图示 具有 SUID/SGID 权限的指令执行状态

SUID 的权限其实与程序的相关性非常的大！为什么呢？先来看看 SUID 的程式是如何被一般使用者执行，且具有什么特色呢？

  • SUID 权限仅对二进位程式(binary program)有效；
  • 执行者对于该程式需要具有 x 的可执行权限；
  • 本权限仅在执行该程式的过程中有效 (run-time)；
  • 执行者将具有该程式拥有者 (owner) 的权限。

所以说，整个 SUID 的权限会生效是由于‘具有该权限的程式被触发’，而我们知道一个程式被触发会变成程序， 所以啰，执行者可以具有程式拥有者的权限就是在该程式变成程序的那个时候啦！第七章我们还没谈到程序的概念， 所以你或许那时候会觉得很奇怪，为啥执行了 passwd 后你就具有 root 的权限呢？不都是一般使用者执行的吗？ 这是因为你在触发 passwd 后，会取得一个新的程序与 PID，该 PID 产生时透过 SUID 来给予该 PID 特殊的权限设定啦！ 我们使用 dmtsai 登入系统且执行 passwd 后，透过工作控制来理解一下！

[dmtsai@www ~]$ passwd
Changing password for user dmtsai.
Changing password for dmtsai
(current) UNIX password: <==这里按下 [ctrl]-z 并且按下 [enter]
[1]+  Stopped                 passwd

[dmtsai@www ~]$ pstree -u
init-+-acpid
....(中间省略)....
     |-sshd---sshd---sshd(dmtsai)---bash-+-more
     |                                   |-passwd(root)
     |                                   `-pstree
....(底下省略)....

从上表的结果我们可以发现，底线的部分是属于 dmtsai 这个一般帐号的权限，特殊字体的则是 root 的权限！ 但你看到了， passwd 确实是由 bash 衍生出来的！不过就是权限不一样！透过这样的解析， 你也会比较清楚为何不同程式所产生的权限不同了吧！这是由于‘SUID 程式运作过程中产生的程序’的关系啦！

那么既然 SUID/SGID 的权限是比较可怕的，您该如何查询整个系统的 SUID/SGID 的档案呢？ 应该是还不会忘记吧？使用 find 即可啊！

find / -perm +6000
小标题的图示 /proc/* 代表的意义

其实，我们之前提到的所谓的程序都是在记忆体当中嘛！而记忆体当中的资料又都是写入到 /proc/* 这个目录下的，所以啰，我们当然可以直接观察 /proc 这个目录当中的档案啊！ 如果你观察过 /proc 这个目录的话，应该会发现他有点像这样：

[root@www ~]# ll /proc
dr-xr-xr-x  5 root      root              0 Mar 11 08:46 1
dr-xr-xr-x  5 root      root              0 Mar 11 00:46 10
dr-xr-xr-x  5 root      root              0 Mar 11 00:46 11
....(中间省略)....
-r--r--r--  1 root      root              0 Mar 20 12:11 uptime
-r--r--r--  1 root      root              0 Mar 20 12:11 version
-r--r--r--  1 root      root              0 Mar 20 12:11 vmstat
-r--r--r--  1 root      root              0 Mar 20 12:11 zoneinfo

基本上，目前主机上面的各个程序的 PID 都是以目录的型态存在于 /proc 当中。 举例来说，我们开机所执行的第一支程式 init 他的 PID 是 1 ， 这个 PID 的所有相关资讯都写入在 /proc/1/* 当中！若我们直接观察 PID 为 1 的资料好了，他有点像这样：

[root@www ~]# ll /proc/1
dr-xr-xr-x 2 root root 0 Mar 12 11:04 attr
-r-------- 1 root root 0 Mar 17 14:32 auxv
-r--r--r-- 1 root root 0 Mar 17 14:32 cmdline  <==就是指令串
-rw-r--r-- 1 root root 0 Mar 17 14:32 coredump_filter
-r--r--r-- 1 root root 0 Mar 17 14:32 cpuset
lrwxrwxrwx 1 root root 0 Mar 17 14:32 cwd -> /
-r-------- 1 root root 0 Mar 17 14:32 environ  <==一些环境变数
lrwxrwxrwx 1 root root 0 Mar 17 14:32 exe -> /sbin/init  <==实际执行的指令
....(以下省略)....

里面的资料还挺多的，不过，比较有趣的其实是两个档案，分别是：

  • cmdline：这个程序被启动的指令串；
  • environ：这个程序的环境变数内容。

很有趣吧！如果你查阅一下 cmdline 的话，就会发现：

[root@www ~]# cat /proc/1/cmdline
init [5]

就是这个指令、选项与参数启动 init 的啦！这还是跟某个特定的 PID 有关的内容呢，如果是针对整个 Linux 系统相关的参数呢？那就是在 /proc 目录底下的档案啦！相关的档案与对应的内容是这样的： (注3)

档名 | 档案内容
/proc/cmdline | 载入 kernel 时所下达的相关参数！查阅此档案，可了解系统是如何启动的！
/proc/cpuinfo | 本机的 CPU 的相关资讯，包含时脉、类型与运算功能等
/proc/devices | 这个档案记录了系统各个主要装置的主要装置代号，与 mknod 有关呢！
/proc/filesystems | 目前系统已经载入的档案系统啰！
/proc/interrupts | 目前系统上面的 IRQ 分配状态。
/proc/ioports | 目前系统上面各个装置所配置的 I/O 位址。
/proc/kcore | 这个就是记忆体的大小啦！好大对吧！但是不要读他啦！
/proc/loadavg | 还记得 top 以及 uptime 吧？没错！上头的三个平均数值就是记录在此！
/proc/meminfo | 使用 free 列出的记忆体资讯，嘿嘿！在这里也能够查阅到！
/proc/modules | 目前我们的 Linux 已经载入的模组列表，也可以想成是驱动程式啦！
/proc/mounts | 系统已经挂载的资料，就是用 mount 这个指令呼叫出来的资料啦！
/proc/swaps | 到底系统挂载入的记忆体在哪里？呵呵！使用掉的 partition 就记录在此啦！
/proc/partitions | 使用 fdisk -l 会出现目前所有的 partition 吧？在这个档案当中也有纪录喔！
/proc/pci | 在 PCI 汇流排上面，每个装置的详细情况！可用 lspci 来查阅！
/proc/uptime | 就是用 uptime 的时候，会出现的资讯啦！
/proc/version | 核心的版本，就是用 uname -a 显示的内容啦！
/proc/bus/* | 一些汇流排的装置，还有 USB 的装置也记录在此喔！

其实，上面这些档案鸟哥在此建议您可以使用 cat 去查阅看看，不必深入了解， 不过，观看过档案内容后，毕竟会比较有感觉啦！如果未来您想要自行撰写某些工具软体， 那么这个目录底下的相关档案可能会对您有点帮助的喔！

小标题的图示 查询已开启档案或已执行程序开启之档案

其实还有一些与程序相关的指令可以值得参考与应用的，我们来谈一谈：

  • fuser：藉由档案(或档案系统)找出正在使用该档案的程序

有的时候我想要知道我的程序到底在这次启动过程中开启了多少档案，可以利用 fuser 来观察啦！ 举例来说，你如果卸载时发现系统通知：‘ device is busy ’，那表示这个档案系统正在忙碌中， 表示有某支程序有利用到该档案系统啦！那么你就可以利用 fuser 来追踪啰！fuser 语法有点像这样：

[root@www ~]# fuser [-umv] [-k [i] [-signal]] file/dir
选项与参数：
-u  ：除了程序的 PID 之外，同时列出该程序的拥有者；
-m  ：后面接的那个档名会主动的上提到该档案系统的最顶层，对 umount 不成功很有效！
-v  ：可以列出每个档案与程序还有指令的完整相关性！
-k  ：找出使用该档案/目录的 PID ，并试图以 SIGKILL 这个讯号给予该 PID；
-i  ：必须与 -k 配合，在删除 PID 之前会先询问使用者意愿！
-signal：例如 -1 -15 等等，若不加的话，预设是 SIGKILL (-9) 啰！

范例一：找出目前所在目录的使用 PID/所属帐号/权限 为何？
[root@www ~]# fuser -uv .
                     USER        PID ACCESS COMMAND
.:                   root      20639 ..c.. (root)bash

看到输出的结果没？他说‘.’底下有个 PID 为 20639 的程序，该程序属于 root 且指令为 bash 。 比较有趣的是那个 ACCESS 的项目，那个项目代表的意义为：

  • c ：此程序在当前的目录下(非次目录)；
  • e ：可被触发为执行状态；
  • f ：是一个被开启的档案；
  • r ：代表顶层目录 (root directory)；
  • F ：该档案被开启了，不过在等待回应中；
  • m ：可能为分享的动态函式库；

那如果你想要查阅某个档案系统底下有多少程序正在占用该档案系统时，那个 -m 的选项就很有帮助了！ 鸟哥的测试主机仅有分割出 /, /boot, /home ，所以无法进行测试。不过好在还有个 /proc 的虚拟档案系统， 让我们来了解一下这个 /proc 的档案系统有多少程序正在利用他吧！

范例二：找到所有使用到 /proc 这个档案系统的程序吧！
[root@www ~]# fuser -uv /proc
# 不会显示任何资料，因为没有任何程序会去使用 /proc 这个目录啊！
# 会被用到的是 /proc 底下的档案啦！所以你应该要这样做：

[root@www ~]# fuser -mvu /proc
                     USER        PID ACCESS COMMAND
/proc:               root       4289 f.... (root)klogd
                     root       4555 f.... (root)acpid
                     haldaemon  4758 f.... (haldaemon)hald
                     root       4977 F.... (root)Xorg
# 有这几支程序在进行 /proc 档案系统的存取喔！这样清楚了吗？

既然可以针对整个档案系统，那么能不能仅针对单一档案啊？当然可以啰！看一下底下的案例先：

范例三：找到 /var 底下属于 FIFO 类型的档案，并且找出存取该档案的程序
[root@www ~]# find /var -type p
/var/gdm/.gdmfifo     <==我们针对这玩意即可！
/var/run/autofs.fifo-misc
/var/run/autofs.fifo-net

[root@www ~]# fuser -uv /var/gdm/.gdmfifo
                     USER        PID ACCESS COMMAND
/var/gdm/.gdmfifo:   root       4892 F.... (root)gdm-binary

范例四：同范例三，但试图删除该 PID？且‘不要’删除喔！
[root@www ~]# fuser -ki /var/gdm/.gdmfifo
/var/gdm/.gdmfifo:    4892
Kill process 4892 ? (y/N) n

如何？很有趣的一个指令吧！透过这个 fuser 我们可以找出使用该档案、目录的程序，藉以观察的啦！ 他的重点与 ps, pstree 不同。 fuser 可以让我们了解到某个档案 (或档案系统) 目前正在被哪些程序所利用！

  • lsof ：列出被程序所开启的档案档名

相对于 fuser 是由档案或者装置去找出使用该档案或装置的程序，反过来说， 如何查出某个程序开启或者使用的档案与装置呢？呼呼！那就是使用 lsof 啰～

[root@www ~]# lsof [-aUu] [+d]
选项与参数：
-a  ：多项资料需要‘同时成立’才显示出结果时！
-U  ：仅列出 Unix like 系统的 socket 档案类型；
-u  ：后面接 username，列出该使用者相关程序所开启的档案；
+d  ：后面接目录，亦即找出某个目录底下已经被开启的档案！

范例一：列出目前系统上面所有已经被开启的档案与装置：
[root@www ~]# lsof
COMMAND PID  USER   FD  TYPE  DEVICE   SIZE     NODE NAME
init      1  root  cwd   DIR     3,2   4096        2 /
init      1  root  rtd   DIR     3,2   4096        2 /
init      1  root  txt   REG     3,2  38620  1426405 /sbin/init
....(底下省略)....
# 注意到了吗？是的，在预设的情况下， lsof 会将目前系统上面已经开启的
# 档案全部列出来～所以，画面多的吓人啊！您可以注意到，第一个档案 init 执行的
# 地方就在根目录，而根目录，嘿嘿！所在的 inode 也有显示出来喔！

范例二：仅列出关于 root 的所有程序开启的 socket 档案
[root@www ~]# lsof -u root -a -U
COMMAND     PID USER   FD   TYPE     DEVICE SIZE   NODE NAME
udevd       400 root    3u  unix 0xedd4cd40        1445 socket
auditd     4256 root    7u  unix 0xedd4c380        9081 socket
audispd    4258 root    0u  unix 0xedd4c1e0        9080 socket
# 注意到那个 -a 吧！如果你分别输入 lsof -u root 及 lsof -U ，会有啥资讯？
# 使用 lsof -u root -U 及 lsof -u root -a -U ，呵呵！都不同啦！
# -a 的用途就是在解决同时需要两个项目都成立时啊！ ^_^

范例三：请列出目前系统上面所有的被启动的周边装置
[root@www ~]# lsof +d /dev
COMMAND     PID      USER   FD   TYPE     DEVICE SIZE  NODE NAME
init          1      root   10u  FIFO       0,16       1147 /dev/initctl
udevd       400      root    0u   CHR        1,3       1420 /dev/null
udevd       400      root    1u   CHR        1,3       1420 /dev/null
udevd       400      root    2u   CHR        1,3       1420 /dev/null
# 看吧！因为装置都在 /dev 里面嘛！所以啰，使用搜寻目录即可啊！

范例四：秀出属于 root 的 bash 这支程式所开启的档案
[root@www ~]# lsof -u root | grep bash
bash   20639 root  cwd    DIR    3,2    4096    648321 /root
bash   20639 root  rtd    DIR    3,2    4096         2 /
bash   20639 root  txt    REG    3,2  735004   1199424 /bin/bash
bash   20639 root  mem    REG    3,2   46680     64873 /lib/libnss_files-2.5.so
....(底下省略)....

这个指令可以找出您想要知道的某个程序是否有启用哪些资讯？例如上头提到的范例四的执行结果呢！ ^_^

  • pidof ：找出某支正在执行的程式的 PID
[root@www ~]# pidof [-sx] program_name
选项与参数：
-s  ：仅列出一个 PID 而不列出所有的 PID
-x  ：同时列出该 program name 可能的 PPID 那个程序的 PID

范例一：列出目前系统上面 init 以及 syslogd 这两个程式的 PID
[root@www ~]# pidof init syslogd
1 4286
# 理论上，应该会有两个 PID 才对。上面的显示也是出现了两个 PID 喔。
# 分别是 init 及 syslogd 这两支程式的 PID 啦。

很简单的用法吧，透过这个 pidof 指令，并且配合 ps aux 与正规表示法，就可以很轻易的找到您所想要的程序内容了呢。

大标题的图示 SELinux 初探

在进入了 CentOS 5.x 之后，SELinux 已经是个非常完备的核心模组了！CentOS 5.x 提供了很多管理 SELinux 的指令与机制， 因此在整体架构上面比以前的版本要单纯且容易操作管理！所以，在这一版以后，我们建议大家千万不要关掉 SELinux 这玩意儿！ 让我们来仔细的玩玩这家伙吧！

小标题的图示 什么是 SELinux

什么是 SELinux 呢？其实他是‘ Security Enhanced Linux ’的缩写，字面上的意义就是安全强化的 Linux 之意！那么所谓的‘安全强化’是强化哪个部分？ 是网路资安还是权限管理？底下就让我们来谈谈吧！

  • 当初设计的目标：避免资源的误用

SELinux 是由美国国家安全局 (NSA) 开发的，当初开发这玩意儿的目的是因为很多企业界发现， 通常系统出现问题的原因大部分都在于‘内部员工的资源误用’所导致的，实际由外部发动的攻击反而没有这么严重。 那么什么是‘员工资源误用’呢？举例来说，如果有个不是很懂系统的系统管理员为了自己设定的方便，将网页所在目录 /var/www/html/ 的权限设定为 drwxrwxrwx 时，你觉得会有什么事情发生？

现在我们知道所有的系统资源都是透过程序来进行存取的，那么 /var/www/html/ 如果设定为 777 ， 代表所有程序均可对该目录存取，万一你真的有启动 WWW 伺服器软体，那么该软体所触发的程序将可以写入该目录， 而该程序却是对整个 Internet 提供服务的！只要有心人接触到这支程序，而且该程序刚好又有提供使用者进行写入的功能， 那么外部的人很可能就会对你的系统写入些莫名其妙的东西！那可真是不得了！一个小小的 777 问题可是大大的！

为了控管这方面的权限与程序的问题，所以美国国家安全局就着手处理作业系统这方面的控管。 由于 Linux 是自由软体，程式码都是公开的，因此她们便使用 Linux 来作为研究的目标， 最后更将研究的结果整合到 Linux 核心里面去，那就是 SELinux 啦！所以说， SELinux 是整合到核心的一个模组喔！ 更多的 SELinux 相关说明可以参考：

  • http://www.nsa.gov/research/selinux/

这也就是说：其实 SELinux 是在进行程序、档案等细部权限设定依据的一个核心模组！ 由于启动网路服务的也是程序，因此刚好也能够控制网路服务能否存取系统资源的一道关卡！ 所以，在讲到 SELinux 对系统的存取控制之前，我们得先来回顾一下之前谈到的系统档案权限与使用者之间的关系。 因为先谈完这个你才会知道为何需要 SELinux 的啦！

  • 传统的档案权限与帐号关系：自主式存取控制, DAC

我们第十四章的内容，知道系统的帐号主要分为系统管理员 (root) 与一般用户，而这两种身份能否使用系统上面的档案资源则与 rwx 的权限设定有关。 不过你要注意的是，各种权限设定对 root 是无效的。因此，当某个程序想要对档案进行存取时， 系统就会根据该程序的拥有者/群组，并比对档案的权限，若通过权限检查，就可以存取该档案了。

这种存取档案系统的方式被称为‘自主式存取控制 (Discretionary Access Control, DAC)’，基本上，就是依据程序的拥有者与档案资源的 rwx 权限来决定有无存取的能力。 不过这种 DAC 的存取控制有几个困扰，那就是：

  • root 具有最高的权限：如果不小心某支程序被有心人士取得， 且该程序属于 root 的权限，那么这支程序就可以在系统上进行任何资源的存取！真是要命！

  • 使用者可以取得程序来变更档案资源的存取权限：如果你不小心将某个目录的权限设定为 777 ，由于对任何人的权限会变成 rwx ，因此该目录就会被任何人所任意存取！

这些问题是非常严重的！尤其是当你的系统是被某些漫不经心的系统管理员所掌控时！她们甚至觉得目录权限调为 777 也没有什么了不起的危险哩...

  • 以政策规则订定特定程序读取特定档案：委任式存取控制, MAC

现在我们知道 DAC 的困扰就是当使用者取得程序后，他可以藉由这支程序与自己预设的权限来处理他自己的档案资源。 万一这个使用者对 Linux 系统不熟，那就很可能会有资源误用的问题产生。为了避免 DAC 容易发生的问题，因此 SELinux 导入了委任式存取控制 (Mandatory Access Control, MAC) 的方法！

委任式存取控制 (MAC) 有趣啦！他可以针对特定的程序与特定的档案资源来进行权限的控管！ 也就是说，即使你是 root ，那么在使用不同的程序时，你所能取得的权限并不一定是 root ， 而得要看当时该程序的设定而定。如此一来，我们针对控制的‘主体’变成了‘程序’而不是使用者喔！ 此外，这个主体程序也不能任意使用系统档案资源，因为每个档案资源也有针对该主体程序设定可取用的权限！ 如此一来，控制项目就细的多了！但整个系统程序那么多、档案那么多，一项一项控制可就没完没了！ 所以 SELinux 也提供一些预设的政策 (Policy) ，并在该政策内提供多个规则 (rule) ，让你可以选择是否启用该控制规则！

在委任式存取控制的设定下，我们的程序能够活动的空间就变小了！举例来说， WWW 伺服器软体的达成程序为 httpd 这支程式， 而预设情况下， httpd 仅能在 /var/www/ 这个目录底下存取档案，如果 httpd 这个程序想要到其他目录去存取资料时， 除了规则设定要开放外，目标目录也得要设定成 httpd 可读取的模式 (type) 才行喔！限制非常多！ 所以，即使不小心 httpd 被 cracker 取得了控制权，他也无权浏览 /etc/shadow 等重要的设定档喔！

小标题的图示 SELinux 的运作模式

再次的重复说明一下，SELinux 是透过 MAC 的方式来控管程序，他控制的主体是程序， 而目标则是该程序能否读取的‘档案资源’！所以先来说明一下这些咚咚的相关性啦！(注4)

  • 主体 (Subject)：
    SELinux 主要想要管理的就是程序，因此你可以将‘主体’跟本章谈到的 process 划上等号；

  • 目标 (Object)：
    主体程序能否存取的‘目标资源’一般就是档案系统。因此这个目标项目可以等档案系统划上等号；

  • 政策 (Policy)：
    由于程序与档案数量庞大，因此 SELinux 会依据某些服务来制订基本的存取安全性政策。这些政策内还会有详细的规则 (rule) 来指定不同的服务开放某些资源的存取与否。在目前的 CentOS 5.x 里面仅有提供两个主要的政策，分别是：

    • targeted：针对网路服务限制较多，针对本机限制较少，是预设的政策；
    • strict：完整的 SELinux 限制，限制方面较为严格。

    建议使用预设的 targeted 政策即可。

  • 安全性本文 (security context)：
    我们刚刚谈到了主体、目标与政策面，但是主体能不能存取目标除了政策指定之外，主体与目标的安全性本文必须一致才能够顺利存取。 这个安全性本文 (security context) 有点类似档案系统的 rwx 啦！安全性本文的内容与设定是非常重要的！ 如果设定错误，你的某些服务(主体程序)就无法存取档案系统(目标资源)，当然就会一直出现‘权限不符’的错误讯息了！
SELinux 运作的各元件之相关性
图 5.2.1、SELinux 运作的各元件之相关性(本图参考小州老师的上课讲义)

上图的重点在‘主体’如何取得‘目标’的资源存取权限！ 由上图我们可以发现，主体程序必须要通过 SELinux 政策内的规则放行后，就可以与目标资源进行安全性本文的比对， 若比对失败则无法存取目标，若比对成功则可以开始存取目标。问题是，最终能否存取目标还是与档案系统的 rwx 权限设定有关喔！如此一来，加入了 SELinux 之后，出现权限不符的情况时，你就得要一步一步的分析可能的问题了！

  • 安全性本文 (Security Context)

CentOS 5.x 已经帮我们制订好非常多的规则了，这部份你只要知道如何开启/关闭某项规则的放行与否即可。 那个安全性本文比较麻烦！因为你可能需要自行设定档案的安全性本文呢！为何需要自行设定啊？ 举例来说，你不也常常进行档案的 rwx 的重新设定吗？这个安全性本文你就将他想成 SELinux 内必备的 rwx 就是了！这样比较好理解啦。

安全性本文存在于主体程序中与目标档案资源中。程序在记忆体内，所以安全性本文可以存入是没问题。 那档案的安全性本文是记录在哪里呢？事实上，安全性本文是放置到档案的 inode 内的，因此主体程序想要读取目标档案资源时，同样需要读取 inode ， 这 inode 内就可以比对安全性本文以及 rwx 等权限值是否正确，而给予适当的读取权限依据。

那么安全性本文到底是什么样的存在呢？我们先来看看 /root 底下的档案的安全性本文好了。 观察安全性本文可使用‘ ls -Z ’去观察如下：(注意：你必须已经启动了 SELinux 才行！若尚未启动，这部份请稍微看过一遍即可。底下会介绍如何启动 SELinux 喔！)

[root@www ~]# ls -Z
drwxr-xr-x  root root root:object_r:user_home_t   Desktop
-rw-r--r--  root root root:object_r:user_home_t   install.log
-rw-r--r--  root root root:object_r:user_home_t   install.log.syslog
# 上述特殊字体的部分，就是安全性本文的内容！

如上所示，安全性本文主要用冒号分为三个栏位，这三个栏位的意义为：

Identify:role:type
身份识别:角色:类型

这三个栏位的意义仔细的说明一下吧：

  • 身份识别 (Identify)：

    相当于帐号方面的身份识别！主要的身份识别则有底下三种常见的类型：

    • root：表示 root 的帐号身份，如同上面的表格显示的是 root 家目录下的资料啊！
    • system_u：表示系统程序方面的识别，通常就是程序啰；
    • user_u：代表的是一般使用者帐号相关的身份。

    你会发现身份识别中，除了 root 之外，其他的识别后面都会加上‘ _u ’的字样呢！ 这个身份识别重点再让我们了解该资料为何种身份所有哩～ 而系统上面大部分的资料都会是 system_u 或 root 啦！至于如果是在 /home 底下的资料，那么大部分应该就会是 user_u 啰！

  • 角色 (Role)：

    透过角色栏位，我们可以知道这个资料是属于程序、档案资源还是代表使用者。一般的角色有：

    • object_r：代表的是档案或目录等档案资源，这应该是最常见的啰；
    • system_r：代表的就是程序啦！不过，一般使用者也会被指定成为 system_r 喔！

    你也会发现角色的栏位最后面使用‘ _r ’来结尾！因为是 role 的意思嘛！

  • 类型 (Type) ：(最重要！)

    在预设的 targeted 政策中， Identify 与 Role 栏位基本上是不重要的！重要的在于这个类型 (type) 栏位！ 基本上，一个主体程序能不能读取到这个档案资源，与类型栏位有关！而类型栏位在档案与程序的定义不太相同，分别是：

    • type：在档案资源 (Object) 上面称为类型 (Type)；
    • domain：在主体程序 (Subject) 则称为领域 (domain) 了！

    domain 需要与 type 搭配，则该程序才能够顺利的读取档案资源啦！

  • 程序与档案 SELinux type 栏位的相关性

那么这三个栏位如何利用呢？首先我们来瞧瞧主体程序在这三个栏位的意义为何！透过身份识别与角色栏位的定义， 我们可以约略知道某个程序所代表的意义喔！基本上，这些对应资料在 targeted 政策下的对应如下：

身份识别 | 角色 | 该对应在 targeted 的意义
root | system_r | 代表供 root 帐号登入时所取得的权限
system_u | system_r | 由于为系统帐号，因此是非交谈式的系统运作程序
user_u | system_r | 一般可登入使用者的程序啰！

但就如上所述，其实最重要的栏位是类型栏位，主体与目标之间是否具有可以读写的权限，与程序的 domain 及档案的 type 有关！这两者的关系我们可以使用达成 WWW 伺服器功能的 httpd 这支程式与 /var/www/html 这个网页放置的目录来说明。 首先，看看这两个咚咚的安全性本文内容先：

[root@www ~]# ll -Zd /usr/sbin/httpd /var/www/html
-rwxr-xr-x  root root system_u:object_r:httpd_exec_t   /usr/sbin/httpd
drwxr-xr-x  root root system_u:object_r:httpd_sys_content_t /var/www/html
# 两者的角色栏位都是 object_r ，代表都是档案！而 httpd 属于 httpd_exec_t 类型，
# /var/www/html 则属于 httpd_sys_content_t 这个类型！

httpd 属于 httpd_exec_t 这个可以执行的类型，而 /var/www/html 则属于 httpd_sys_content_t 这个可以让 httpd 领域 (domain) 读取的类型。文字看起来不太容易了解吧！我们使用图示来说明这两者的关系！

主体程序取得的 domain 与目标档案资源的 type 相互关系
图 5.2.2、主体程序取得的 domain 与目标档案资源的 type 相互关系

上图的意义我们可以这样看的：

  1. 首先，我们触发一个可执行的目标档案，那就是具有 httpd_exec_t 这个类型的 /usr/sbin/httpd 档案；
  2. 该档案的类型会让这个档案所造成的主体程序 (Subject) 具有 httpd 这个领域 (domain)， 我们的政策针对这个领域已经制定了许多规则，其中包括这个领域可以读取的目标资源类型；
  3. 由于 httpd domain 被设定为可以读取 httpd_sys_content_t 这个类型的目标档案 (Object)， 因此你的网页放置到 /var/www/html/ 目录下，就能够被 httpd 那支程序所读取了；
  4. 但最终能不能读到正确的资料，还得要看 rwx 是否符合 Linux 权限的规范！

上述的流程告诉我们几个重点，第一个是政策内需要制订详细的 domain/type 相关性；第二个是若档案的 type 设定错误， 那么即使权限设定为 rwx 全开的 777 ，该主体程序也无法读取目标档案资源的啦！不过如此一来， 也就可以避免使用者将他的家目录设定为 777 时所造成的权限困扰。

小标题的图示 SELinux 的启动、关闭与观察

并非所有的 Linux distributions 都支援 SELinux 的，所以你必须要先观察一下你的系统版本为何！ 鸟哥这里介绍的 CentOS 5.x 本身就有支援 SELinux 啦！所以你不需要自行编译 SELinux 到你的 Linux 核心中！ 目前 SELinux 支援三种模式，分别如下：

  • enforcing：强制模式，代表 SELinux 运作中，且已经正确的开始限制 domain/type 了；
  • permissive：宽容模式：代表 SELinux 运作中，不过仅会有警告讯息并不会实际限制 domain/type 的存取。这种模式可以运来作为 SELinux 的 debug 之用；
  • disabled：关闭，SELinux 并没有实际运作。

那你怎么知道目前的 SELinux 模式呢？就透过 getenforce 吧！

[root@www ~]# getenforce
Enforcing  <==诺！就显示出目前的模式为 Enforcing 啰！

另外，我们又如何知道 SELinux 的政策 (Policy) 为何呢？这时可以使用 sestatus 来观察：

[root@www ~]# sestatus [-vb]
选项与参数：
-v  ：检查列于 /etc/sestatus.conf 内的档案与程序的安全性本文内容；
-b  ：将目前政策的规则布林值列出，亦即某些规则 (rule) 是否要启动 (0/1) 之意；

范例一：列出目前的 SELinux 使用哪个政策 (Policy)？
[root@www ~]# sestatus
SELinux status:                 enabled    <==是否启动 SELinux
SELinuxfs mount:                /selinux   <==SELinux 的相关档案资料挂载点
Current mode:                   enforcing  <==目前的模式
Mode from config file:          enforcing  <==设定档指定的模式
Policy version:                 21
Policy from config file:        targeted   <==目前的政策为何？

如上所示，目前是启动的，而且是 Enforcing 模式，而由设定档查询得知亦为 Enforcing 模式。 此外，目前的预设政策为 targeted 这一个。你应该要有疑问的是， SELinux 的设定档是哪个档案啊？ 其实就是 /etc/selinux/config 这个档案喔！我们来看看内容：

[root@www ~]# vi /etc/selinux/config
SELINUX=enforcing     <==调整 enforcing|disabled|permissive
SELINUXTYPE=targeted  <==目前仅有 targeted 与 strict
  • SELinux 的启动与关闭

上面是预设的政策与启动的模式！你要注意的是，如果改变了政策则需要重新开机；如果由 enforcing 或 permissive 改成 disabled ，或由 disabled 改成其他两个，那也必须要重新开机。这是因为 SELinux 是整合到核心里面去的， 你只可以在 SELinux 运作下切换成为强制 (enforcing) 或宽容 (permissive) 模式，不能够直接关闭 SELinux 的！ 同时，由 SELinux 关闭 (disable) 的状态到开启的状态也需要重新开机啦！所以，如果刚刚你发现 getenforce 出现 disabled 时， 请到上述档案修改成为 enforcing 吧！

所以，如果你要启动 SELinux 的话，请将上述的 SELINUX=enforcing 设定妥当，并且指定 SELINUXTYPE=targeted 这一个设定， 并且到 /boot/grub/menu.lst 这个档案去，看看核心有无关闭 SELinux 了呢？

[root@www ~]# vi /boot/grub/menu.lst
default=0
timeout=5
splashimage=(hd0,0)/grub/splash.xpm.gz
hiddenmenu
title CentOS (2.6.18-92.el5)
        root (hd0,0)
        kernel /vmlinuz-2.6.18-92.el5 ro root=LABEL=/1 rhgb quiet selinux=0
        initrd /initrd-2.6.18-92.el5.img
# 如果要启动 SELinux ，则不可以出现 selinux=0 的字样在 kernel 后面！

请注意到上面特殊字体的那一行，确认 kernel 后面不可以接‘ selinux=0 ’这个项目！因为 selinux=0 指定给核心时， 则核心会自动的忽略 /etc/selinux/config 的设定值，而直接略过 SELinux 的载入，所以你的 SELinux 模式就会变成 disabled 啦！因为我们要启动，所以这里得要确认不存在 selinux=0 才行喔！切记切记！ 如果一切设定妥当，接下来就是 reboot 重新开机吧！

不过你要注意的是，如果从 disable 转到启动 SELinux 的模式时， 由于系统必须要针对档案写入安全性本文的资讯，因此开机过程会花费不少时间在等待重新写入 SELinux 安全性本文 (有时也称为 SELinux Label) ，而且在写完之后还得要再次的重新开机一次喔！你必须要等待粉长一段时间！ 等到下次开机成功后，再使用 getenforce 或 sestatus 来观察看看有否成功的启动到 Enforcing 的模式啰！

如果你已经在 Enforcing 的模式，但是可能由于一些设定的问题导致 SELinux 让某些服务无法正常的运作， 此时你可以将 Enforcing 的模式改为宽容 (permissive) 的模式，让 SELinux 只会警告无法顺利连线的讯息， 而不是直接抵挡主体程序的读取权限。让 SELinux 模式在 enforcing 与 permissive 之间切换的方法为：

[root@www ~]# setenforce [0|1]
选项与参数：
0 ：转成 permissive 宽容模式；
1 ：转成 Enforcing 强制模式

范例一：将 SELinux 在 Enforcing 与 permissive 之间切换与观察
[root@www ~]# setenforce 0
[root@www ~]# getenforce
Permissive
[root@www ~]# setenforce 1
[root@www ~]# getenforce
Enforcing

不过请注意， setenforce 无法在 Disabled 的模式底下进行模式的切换喔！

小标题的图示 SELinux 网路服务运作范例

由于 CentOS 5.x 预设使用 targeted 这个政策，而这个政策主要是在管理网路服务，本机端的程序则比较不受 SELinux 的管制。 既然上头我们曾经举过 /usr/sbin/httpd 这个程式来当作范例，那么我们就使用 WWW 伺服器来说明一下 SELinux 的运作方式吧。

  • 网路服务的启动与观察

首先，让我们启动 httpd 这支服务吧！要记得的是，一般服务启动的脚本会在 /etc/init.d/ 底下， 所以我们可以这样启动与观察：

# 1. 先启动这个网路服务吧！
[root@www ~]# /etc/init.d/httpd start
正在启动 httpd:          [  确定  ]

# 2. 观察有无此程序，并且观察此程序的 SELinux 安全性本文资料
[root@www ~]# pstree | grep httpd
     |-httpd---8*[httpd]   <==httpd 会产生很多子程序来负责网路服务喔！

[root@www ~]# ps aux -Z |grep http
root:system_r:httpd_t root   24089 0.2 1.2 22896 9256 ? Ss 16:06 0:00 /usr/sbin/httpd
root:system_r:httpd_t apache 24092 0.0 0.6 22896 4752 ? S  16:06 0:00 /usr/sbin/httpd
root:system_r:httpd_t apache 24093 0.0 0.6 22896 4752 ? S  16:06 0:00 /usr/sbin/httpd
....(后面省略)....

ps -Z 这个‘ -Z ’的选项可以让我们查阅程序的安全性本文！其他相关的程序说明请自行查阅本章上面各节的内容。 我们可以发现这整个程序的 domain 是 httpd_t 这个咚咚喔！再来我们来处理一下首页的资料先。 由于首页是放置到 /var/www/html，且档名应该要是‘ index.html ’，因此我们可以这样简单的制作首页：

[root@www ~]# echo "This is my first web page." > /var/www/html/index.html

接下来，如果你在浏览器上面输入‘ http://127.0.0.1 ’应该会看到如下的画面才对！

httpd 顺利运作时，能够看到的首页画面
图 5.4.1、httpd 顺利运作时，能够看到的首页画面

此时你的浏览器会透过 httpd 这个程序拥有的 httpd_t 这个 domain 去读取 /var/www/html/index.html 这个档案的！ 先来看看这个档案的权限与 SELinux 的安全性本文资料：

[root@www ~]# ll -Z /var/www/html/index.html
-rw-r--r-- root root root:object_r:httpd_sys_content_t /var/www/html/index.html

权限是 apache 可以读取的 r 标志，而 SELinux 则是 httpd_sys_content_t 的类型 (type)，也是 httpd_t 能读取的哩！ 那么为何 httpd_t 可以读取呢？因为 targeted 政策里面有设定嘛！关于政策设定的查询我们可以在后续跟大家作介绍， 这里先了解一下即可。

  • 错误的 SELinux 安全性本文

让我们来了解一下什么是错误的安全性本文设定好了！现在，我们将重要的网页资料在 root 的家目录底下制作！ 设定如下：

# 1. 先在 root 的家目录建置所需的首页：
[root@www ~]# echo "My 2nd web page..." > index.html

# 2. 将首页 index.html ‘搬移’到 /var/www/html 目录去：
[root@www ~]# rm /var/www/html/index.html
[root@www ~]# mv index.html /var/www/html
# 这个测试的重点在 mv 这个指令的处理上！务必使用 mv 喔！

等到上述的动作都做完后，如果在浏览器输入 http://127.0.0.1/index.html ，你应该会想到画面会出现我们想要的‘ My 2nd web page...’才对，但是结果却变成：

错误的安全性本文所造成的困扰
图 5.4.2、错误的安全性本文所造成的困扰

记得要在网址列指定 index.html 否则出现的会变成欢迎首页的画面。而荧幕上出现的错误讯息是没有权限 (You don't have permission...)。看看这个 /var/www/html/index.html 的权限吧！

[root@www ~]# ll -Z /var/www/html/index.html
-rw-r--r-- root root root:object_r:user_home_t /var/www/html/index.html

你会发现，权限是对的 (apache 使用者依旧可以读取)，但是安全性本文内容却是使用者家目录呢！ 真是要命！这个使用者家目录预设可不能给 httpd_t 这个 domain 读取的！所以就产生错误啦！那该如何处置呢？

  • 重设 SELinux 安全性本文

既然安全性本文是错的，那么就将他改回来即可嘛！怎么修改呢？可以透过两个指令喔！首先我们使用 chcon 来处理：

[root@www ~]# chcon [-R] [-t type] [-u user] [-r role] 档案
[root@www ~]# chcon [-R] --reference=范例档 档案
选项与参数：
-R  ：连同该目录下的次目录也同时修改；
-t  ：后面接安全性本文的类型栏位！例如 httpd_sys_content_t ；
-u  ：后面接身份识别，例如 system_u；
-r  ：后面街角色，例如 system_r；
--reference=范例档：拿某个档案当范例来修改后续接的档案的类型！

范例一：将刚刚的 index.html 类型改为 httpd_sys_content_t 的类型
[root@www ~]# chcon -t httpd_sys_content_t /var/www/html/index.html
[root@www ~]# ll -Z /var/www/html/index.html
-rw-r--r--  root root root:object_r:httpd_sys_content_t /var/www/html/index.html
# 瞧！这样就改回来啦！

范例二：以 /etc/passwd 为依据，将 index.html 修改成该类型
[root@www ~]# ll -Z /etc/passwd
-rw-r--r--  root root system_u:object_r:etc_t          /etc/passwd

[root@www ~]# chcon --reference=/etc/passwd /var/www/html/index.html
[root@www ~]# ll -Z /var/www/html/index.html
-rw-r--r--  root root root:object_r:etc_t /var/www/html/index.html
# 看看！是否与上面的 /etc/passwd 相同了！不过，这又是错误的安全性本文！
# 先不要急着修改！我们来进行底下的另外一个指令处置看看！

chcon 是透过直接指定的方式来处理安全性本文的类型资料。那我们知道其实系统预设的目录都有特殊的 SELinux 安全性本文， 举例来说， /var/www/html 原本就是 httpd 可以读取的目录嘛！既然如此，那有没有可以使用预设的安全性本文来还原的方式？ 有的，那就是 restorecon 这玩意儿：

[root@www ~]# restorecon [-Rv] 档案或目录
选项与参数：
-R  ：连同次目录一起修改；
-v  ：将过程显示到荧幕上

范例一：将刚刚错误的 index.html 以预设的安全性本文改正过来
[root@www ~]# restorecon -Rv /var/www/html/index.html
restorecon reset /var/www/html/index.html context system_u:object_r:etc_t:s0->
system_u:object_r:httpd_sys_content_t:s0
# 上面这两行其实是同一行喔！表示将 index.html 由 etc_t 改为 httpd_sys_content_t

然后回到刚刚图 5.4.2 给他重读一下，嘿嘿！又可以看到正确的内容啦！这个过程完全没有动到 rwx 权限， 因为该权限本来就是对的！而错的部分是在于 SELinux 的安全性本文当中那个类型 (type) 设定错误！ 而设定错误的原因很可能是因为该档案由其他位置复制或移动过来所导致的！因此， 你得要善用 restorecon 以及 chcon 来处理这方面的问题喔！

小标题的图示 SELinux 所需的服务

由于 SELinux 是整合到核心的一个核心功能，因此你几乎不需要启动什么额外的服务来开启 SELinux 的。 开机完成后， SELinux 就启动了。不过，你刚刚也发现到当我们复制或移动某些资料到特定的目录时， 可能由于没有注意到修改 SELinux 的安全性本文内容，结果导致网路服务无法顺利运行的问题！ 有没有什么方法可以记录当发生 SELinux 错误时，将那些有用的资讯记录下来，并且提供解决的方案呢？ 此时就得要底下的几个服务的辅助啰！

  • setroubleshoot --> 错误讯息写入 /var/log/messages

几乎所有 SELinux 相关的程式都会以 se 为开头，这个服务也是以 se 为开头！而 troubleshoot 大家都知道是错误克服， 因此这个 setroubleshoot 自然就得要启动他啦！这个服务会将关于 SELinux 的错误讯息与克服方法记录到 /var/log/messages 里头，所以你一定得要启动这个服务才好。那如何在开机的时候就启动 setroubleshoot 呢？这样处理先：

[root@www ~]# chkconfig --list setroubleshoot
setroubleshoot  0:off  1:off  2:off 3:on  4:on  5:on  6:off
# 我们的 Linux 运作模式是在 3 或 5 号，因此这两个要 on 即可。

[root@www ~]# chkconfig setroubleshoot on
# 关于 chkconfig 我们会在后面章节介绍， --list 是列出目前的执行等级是否有启动，
# 如果加上 on ，则是在开机时启动，若为 off 则开机时不启动。

这支服务预设几乎都会启动啦！除非你看到 3:off 或 5:off 时，才需要以‘ chkconfig setroubleshoot on ’ 去设定一下。那么如果有发生错误时，讯息像什么呢？我们刚刚不是以浏览器浏览 index.html 并导致错误吗？ 那就将该错误捉来瞧瞧！

[root@www ~]# cat /var/log/messages | grep setroubleshoot
Mar 23 17:18:44 www setroubleshoot: SELinux is preventing the httpd from using
potentially mislabeled files (/var/www/html/index.html). For complete SELinux
messages. run sealert -l 6c028f77-ddb6-4515-91f4-4e3e719994d4

上面的错误讯息可是同一行喔！大纲说的是‘SElinux 被用来避免 httpd 读取到错误的安全性本文， 想要查阅完整的资料，请执行 sealert -l 6c02...’没错！你注意到了！重点就是 sealert -l 啦！ 上面提供的资讯并不完整，想要更完整的说明得要靠 sealert 配合侦测到的错误代码来处理。 实际处理后会像这样：

[root@www ~]# sealert -l 6c028f77-ddb6-4515-91f4-4e3e719994d4
Summary:

SELinux is preventing the httpd from using potentially mislabeled files
(/var/www/html/index.html). <==就是刚刚 /var/log/messages 的讯息

Detailed Description:       <==底下是更完整的描述！要看！

SELinux has denied httpd access to potentially mislabeled file(s)
(/var/www/html/index.html). This means that SELinux will not allow httpd to use
these files. It is common for users to edit files in their home directory or tmp
directories and then move (mv) them to system directories. The problem is that
the files end up with the wrong file context which confined applications are not
allowed to access.

Allowing Access:            <==若要允许存取，你需要进行的动作！

If you want httpd to access this files, you need to relabel them using
restorecon -v '/var/www/html/index.html'. You might want to relabel the entire
directory using restorecon -R -v '/var/www/html'.
....(底下省略)....

重点就是上面特殊字体显示的地方！你只要照着‘Allowing Access’里面的提示去进行处理， 就能够完成你的 SELinux 类型设定了！比对刚刚我们上个小节提到的 restorecon 与 chcon 你就能够知道， setroubleshoot 提供的讯息有多有效了吧！

  • auditd --> 详细资料写入 /var/log/audit/audit.log

audit 是稽核的意思，这个 auditd 会将 SELinux 发生的错误资讯写入 /var/log/audit/audit.log 中！ 与上个服务相同的，你最好在开机时就设定这服务为启动的模式，因此可以照样造句：

[root@www ~]# chkconfig --list auditd
auditd      0:off  1:off  2:on   3:on   4:on   5:on   6:off

[root@www ~]# chkconfig auditd on
# 若 3:off 及 5:off 时，才需要进行！

与 setroubleshoot 不同的是， auditd 会将许多的 SELinux 资讯都记录下来，不只是错误讯息而已， 因此登录档 /var/log/audit/audit.log 非常的庞大！要直接到这档案里面去搜寻资料是挺累人的～ 还好，SELinux 有提供一个 audit2why 的指令来让我们查询错误讯息的回报呢！那么这个指令如何使用呢？ 可以这样用的：

[root@www ~]# audit2why < /var/log/audit/audit.log
# 意思是，将登录档的内容读进来分析，并输出分析的结果！结果有点像这样：
type=AVC msg=audit(1237799959.349:355): avc:  denied  { getattr } for  pid=24094
comm="httpd" path="/var/www/html/index.html" dev=hda2 ino=654685 scontext=root:s
ystem_r:httpd_t:s0 tcontext=root:object_r:user_home_t:s0 tclass=file
    Was caused by:
       Missing or disabled TE allow rule.
       Allow rules may exist but be disabled by boolean settings; check boolean
settings.
       You can see the necessary allow rules by running audit2allow with this
audit message as input.

audit2why 的用法与输出结果如上，比较有趣的是那个 AVC ，AVC 是 access vector cache 的缩写， 目的是记录所有与 SELinux 有关的存取统计资料。输出的资讯当中，会有谈到产生错误的问题为何，如上表特殊字体部分， 你会发现错误讯息主要告知 type 不符，所以导致错误的发生啊！不过，就鸟哥来看，我个人觉得 setroubleshoot 比较好用呢！ 这两个好东西都可以帮助你解决 SELinux 的错误，因此，请务必至少要学会其中一项错误分析的方法喔！

小标题的图示 SELinux 的政策与规则管理

现在你应该知道，一个主体程式能否读取到目标档案资源的重点在于 SELinux 的政策以及政策内的各项规则， 然后再透过该规则的定义去处理各目标档案的安全性本文，尤其是‘类型’的部分。现在我们也知道可以透过 sestatus 与 getenforce 去取得目前的 SELinux 状态。 但是，能不能知道更详细的政策说明与规则项目呢？底下我们就来了解了解！

  • 政策查阅

CentOS 5.x 预设使使用 targeted 政策，那么这个政策提供多少相关的规则呢？此时可以透过 seinfo 来查询喔！

[root@www ~]# seinfo [-Atrub]
选项与参数：
-A  ：列出 SELinux 的状态、规则布林值、身份识别、角色、类别等所有资讯
-t  ：列出 SELinux 的所有类别 (type) 种类
-r  ：列出 SELinux 的所有角色 (role) 种类
-u  ：列出 SELinux 的所有身份识别 (user) 种类
-b  ：列出所有规则的种类 (布林值)

范例一：列出 SELinux 在此政策下的统计状态
[root@www ~]# seinfo
Statistics for policy file: /etc/selinux/targeted/policy/policy.21
Policy Version & Type: v.21 (binary, MLS) <==列出政策所在档与版本

   Classes:            61    Permissions:       220
   Types:            1521    Attributes:        155
   Users:               3    Roles:               6
   Booleans:          213    Cond. Expr.:       190
   Sensitivities:       1    Categories:       1024
   Allow:           86561    Neverallow:          0
   Auditallow:         34    Dontaudit:        5460
   Role allow:          5    Role trans:          0
....(底下省略)....
# 从上面我们可以看到这个政策是 targeted ，此政策的安全性本文类别有 1521 个；
# 而针对网路服务的规则 (Booleans) 共制订了 213 条规则！

范例二：列出与 httpd 有关的规则 (booleans) 有哪些？
[root@www ~]# seinfo -b | grep httpd
Rule loading disabled
   allow_httpd_mod_auth_pam
   allow_httpd_bugzilla_script_anon_write
   httpd_enable_ftp_server
....(底下省略)....
# 你可以看到，有非常多的与 httpd 有关的规则订定呢！

从上面我们可以看到与 httpd 有关的布林值，同样的，如果你想要找到有 httpd 字样的安全性本文类别时， 就可以使用‘ seinfo -t | grep httpd ’来查询了！如果查询到相关的类别或者是布林值后，想要知道详细的规则时， 就得要使用 sesearch 这个指令了！

[root@www ~]# sesearch [-a] [-s 主体类别] [-t 目标类别] [-b 布林值]
选项与参数：
-a  ：列出该类别或布林值的所有相关资讯
-t  ：后面还要接类别，例如 -t httpd_t
-b  ：后面还要接布林值的规则，例如 -b httpd_enable_ftp_server

范例一：找出目标档案资源类别为 httpd_sys_content_t 的有关资讯
[root@www ~]# sesearch -a -t httpd_sys_content_t
Found 74 av rules:
   allow readahead_t httpd_sys_content_t : file { ioctl read getattr lock };
   allow readahead_t httpd_sys_content_t : dir { ioctl read getattr lock search };
....(底下省略)....
# ‘ allow  主体程序安全性本文类别  目标档案安全性本文类别 ’
# 如上，说明这个类别可以被那个主题程序的类别所读取，以及目标档案资源的格式。

范例二：找出主体程序为 httpd_t 且目标档案类别为 httpd 相关的所有资讯
[root@www ~]# sesearch -s httpd_t -t httpd_* -a
Found 163 av rules:
....(中间省略)....
   allow httpd_t httpd_sys_content_t : file { ioctl read getattr lock };
   allow httpd_t httpd_sys_content_t : dir { ioctl read getattr lock search };
   allow httpd_t httpd_sys_content_t : lnk_file { ioctl read getattr lock };
....(后面省略)....
# 从上面的资料就可以看出当程序为 httpd_t 这个类别，是可以读取
# httpd_sys_content_t 的！

你可以很轻易的查询到某个主体程序 (subject) 可以读取的目标档案资源 (Object) ， 从我们上面的练习，我们也可以很轻松的就知道，为何 httpd_t 可以读取 httpd_sys_content_t 啰！ 那如果是布林值呢？里面又规范了什么？让我们来看看先：

范例三：我知道有个布林值为 httpd_enable_homedirs ，请问该布林值规范多少规则？
[root@www ~]# sesearch -b httpd_enable_homedirs -a
Found 21 av rules:
   allow httpd_t user_home_dir_t : dir { getattr search };
   allow httpd_t cifs_t : file { ioctl read getattr lock };
   allow httpd_t cifs_t : dir { ioctl read getattr lock search };
....(后面省略)....

从这个布林值的设定我们可以看到里面规范了非常多的主体程序与目标档案资源的放行与否！ 所以你知道了，实际规范这些规则的，就是布林值的项目啦！那也就是我们之前所说的一堆规则是也！ 你的主体程序能否对某些目标档案进行存取，与这个布林直非常有关系喔！因为布林值可以将规则设定为启动 (1) 或者是关闭 (0) 啦！

由 seinfo 与 sesearch 的输出资讯，我们也会得到实际的政策资料都是放置到 /etc/selinux/targeted/policy/ 底下， 事实上，所有与 targetd 相关的资讯都是放置到 /etc/selinux/targeted 里面的呢！包括安全性本文相关的资讯。 这部分等一下谈到安全性本文的预设值修改时，我们再来讨论。

  • 布林值的查询与修改

上面我们透过 sesearch 知道了，其实 Subject 与 Object 能否有存取的权限，是与布林值有关的， 那么系统有多少布林值可以透过 seinfo -b 来查询，但，每个布林值是启动的还是关闭的呢？这就来查询看看吧：

[root@www ~]# getsebool [-a] [布林值条款]
选项与参数：
-a  ：列出目前系统上面的所有布林值条款设定为开启或关闭值

范例一：查询本系统内所有的布林值设定状况
[root@www ~]# getsebool -a
NetworkManager_disable_trans --> off
allow_console_login --> off
allow_cvs_read_shadow --> off
allow_daemons_dump_core --> on
....(底下省略)....
# 您瞧！这就告诉你目前的布林值状态啰！

那么如果查询到某个布林值，并且以 sesearch 知道该布林值的用途后，想要关闭或启动他，又该如何处置？

[root@www ~]# setsebool [-P] 布林值=[0|1]
选项与参数：
-P  ：直接将设定值写入设定档，该设定资料未来会生效的！

范例一：查询 httpd_enable_homedirs 是否为关闭，若不为关闭，请关闭他！
[root@www ~]# getsebool httpd_enable_homedirs
httpd_enable_homedirs --> on  <==结果是 on ，依题意给他关闭！

[root@www ~]# setsebool -P httpd_enable_homedirs=0
[root@www ~]# getsebool httpd_enable_homedirs
httpd_enable_homedirs --> off

这个 setsebool 最好记得一定要加上 -P 的选项！因为这样才能将此设定写入设定档！ 这是非常棒的工具组！你一定要知道如何使用 getsebool 与 setsebool 才行！

  • 预设目录的安全性本文查询与修改

还记得我们在使用 restorecon 时谈到每个目录或档案都会有预设的安全性本文吗？ 会制订目录的安全性本文，是因为系统的一些服务所放置档案的目录已经是确定的，当然有预设的安全性本文管理上较方便。 那你如何查询这些目录的预设安全性本文呢？就得要使用 semanage 啰！

[root@www ~]# semanage {login|user|port|interface|fcontext|translation} -l
[root@www ~]# semanage fcontext -{a|d|m} [-frst] file_spec
选项与参数：
fcontext ：主要用在安全性本文方面的用途， -l 为查询的意思；
-a ：增加的意思，你可以增加一些目录的预设安全性本文类型设定；
-m ：修改的意思；
-d ：删除的意思。

范例一：查询一下 /var/www/html 的预设安全性本文设定为何！
[root@www ~]# semanage fcontext -l
SELinux fcontext    type          Context
....(前面省略)....
/var/www(/.*)?      all files     system_u:object_r:httpd_sys_content_t:s0
....(后面省略)....

从上面的说明，我们知道其实 semanage 可以处理非常多的任务，不过，在这个小节我们主要想了解的是每个目录的预设安全性本文。 如上面范例一所示，我们可以查询的到每个目录的安全性本文啦！而目录的设定可以使用正规表示法去指定一个范围。那么如果我们想要增加某些自订的目录的安全性本文呢？ 举例来说，我想要制订 /srv/samba 成为 public_content_t 的类型时，应该如何指定呢？

范例二：利用 semanage 设定 /srv/samba 目录的预设安全性本文为 public_content_t
[root@www ~]# mkdir /srv/samba
[root@www ~]# ll -Zd /srv/samba
drwxr-xr-x  root root root:object_r:var_t    /srv/samba
# 如上所示，预设的情况应该是 var_t 这个咚咚的！

[root@www ~]# semanage fcontext -l | grep '/srv'
/srv/.*                     all files   system_u:object_r:var_t:s0
/srv/([^/]*/)?ftp(/.*)?     all files   system_u:object_r:public_content_t:s0
/srv/([^/]*/)?www(/.*)?     all files   system_u:object_r:httpd_sys_content_t:s0
/srv/([^/]*/)?rsync(/.*)?   all files   system_u:object_r:public_content_t:s0
/srv/gallery2(/.*)?         all files   system_u:object_r:httpd_sys_content_t:s0
/srv                        directory   system_u:object_r:var_t:s0 <==看这里！
# 上面则是预设的 /srv 底下的安全性本文资料，不过，并没有指定到 /srv/samba 啦

[root@www ~]# semanage fcontext -a -t public_content_t "/srv/samba(/.*)?"
[root@www ~]# semanage fcontext -l | grep '/srv/samba'
/srv/samba(/.*)?            all files   system_u:object_r:public_content_t:s0

[root@www ~]# cat /etc/selinux/targeted/contexts/files/file_contexts.local
# This file is auto-generated by libsemanage
# Please use the semanage command to make changes
/srv/samba(/.*)?    system_u:object_r:public_content_t:s0
# 其实就是写入这个档案的啰！ ^_^

[root@www ~]# restorecon -Rv /srv/samba* <==尝试恢复预设值
[root@www ~]# ll -Zd /srv/samba
drwxr-xr-x  root root system_u:object_r:public_content_t /srv/samba/
# 有预设值，以后用 restorecon 来修改比较简单！

semanage 的功能很多，不过鸟哥主要用到的仅有 fcontext 这个项目的动作而已。如上所示， 你可以使用 semanage 来查询所有的目录预设值，也能够使用他来增加预设值的设定！如果您学会这些基础的工具， 那么 SELinux 对你来说，也不是什么太难的咚咚啰！

大标题的图示 重点回顾
  • 程式 (program)：通常为 binary program ，放置在储存媒体中 (如硬碟、光碟、软碟、磁带等)，为实体档案的型态存在；
  • 程序 (process)：程式被触发后，执行者的权限与属性、程式的程式码与所需资料等都会被载入记忆体中， 作业系统并给予这个记忆体内的单元一个识别码 (PID)，可以说，程序就是一个正在运作中的程式。
  • 程式彼此之间是有相关性的，故有父程序与子程序之分。而 Linux 系统所有程序的父程序就是 init 这个 PID 为 1 号的程序。
  • 在 Linux 的程序呼叫通常称为 fork-and-exec 的流程！程序都会藉由父程序以复制 (fork) 的方式产生一个一模一样的子程序， 然后被复制出来的子程序再以 exec 的方式来执行实际要进行的程式，最终就成为一个子程序的存在。
  • 常驻在记忆体当中的程序通常都是负责一些系统所提供的功能以服务使用者各项任务，因此这些常驻程式就会被我们称为：服务 (daemon)。
  • 在工作管理 (job control) 中，可以出现提示字元让你操作的环境就称为前景 (foreground)，至于其他工作就可以让你放入背景 (background) 去暂停或运作。
  • 与 job control 有关的按键与关键字有： &, [ctrl]-z, jobs, fg, bg, kill %n 等；
  • 程序管理的观察指令有： ps, top, pstree 等等；
  • 程序之间是可以互相控制的，传递的讯息 (signal) 主要透过 kill 这个指令在处理；
  • 程序是有优先顺序的，该项目为 Priority，但 PRI 是核心动态调整的，使用者只能使用 nice 值去微调 PRI
  • nice 的给予可以有： nice, renice, top 等指令；
  • vmstat 为相当好用的系统资源使用情况观察指令；
  • SELinux 当初的设计是为了避免使用者资源的误用，而 SELinux 使用的是 MAC 委任式存取设定；
  • SELinux 的运作中，重点在于主体程序 (Subject) 能否存取目标档案资源 (Object) ，这中间牵涉到政策 (Policy) 内的规则， 以及实际的安全性本文类别 (type)；
  • 安全性本文的一般设定为：‘Identify:role:type’其中又以 type 最重要；
  • SELinux 的模式有： enforcing, permissive, disabled 三种，而启动的政策 (Policy) 主要是 targeted
  • SELinux 启动与关闭的设定档在： /etc/selinux/config
  • SELinux 的启动与观察： getenforce, sestatus 等指令
  • 重设 SELinux 的安全性本文可使用 restorecon 与 chcon
  • 在 SELinux 有启动时，必备的服务至少要启动 setroubleshoot 这个！
  • 若要管理预设的 SELinux 布林值，可使用 getsebool, setsebool 来管理！
大标题的图示 本章习题
( 要看答案请将滑鼠移动到‘答：’底下的空白处，按下左键圈选空白处即可察看 )
  • 情境模拟题一：透过一个网路程式 vsftpd 的服务，来了解到程序与 SELinux 的相关限制行为：

    • 目标：了解软体、程式、程序、优先执行绪、网路程序与 SELinux 的相关性
    • 需求：已经知道如何安装软体，否则就得要连上 Internet 才能进行 vsftpd 服务的安装；

    底下的流程先看看即可，很多资料如果当初忘记安装的话，可能会无法进行。没关系！后续的文章看完后，第二次读到这里后， 你就会知道如何处理了。

    1. 先察看有无安装 vsftpd 这个软体，如果有的话那就 OK ～没有的话，可能需要线上安装才行：
      [root@www ~]# rpm -q vsftpd
vsftpd-2.0.5-12.el5   <==出现这个才是对的！若没有出现，就是没安装

# 如果没有安装的话，你又已经有 IP 可以上网了，那么就这样安装：
[root@www ~]# yum install vsftpd

    2. 启动 vsftpd 这个服务：
      [root@www ~]# /etc/init.d/vsftpd start

    3. 假设 vsftpd 这个服务并不是那么重要，因此我想要在这次启动期间，让 vsftpd 的优先执行绪较不优先 10 分， 可以这么做：
      [root@www ~]# pstree -p | grep vsftpd
        |-vsftpd(2377)   <==找到了 PID 为 2377 喔！
[root@www ~]# renice 10 2377
[root@www ~]# top -p grep 2377 <==重点是在观察！

    4. vsftpd 是个网路服务，他到底是启动哪个埠口？可以这样观察：
      [root@www ~]# netstat -tlunp | grep vsftpd
tcp  0 0 0.0.0.0:21     0.0.0.0:*  LISTEN   2377/vsftpd
# 这样的答案够明显了吗？

    5. vsftpd 提供网路的 FTP 功能，有个使用者名为 vbird ，他却无法登入自己的帐号！这是什么原因呢？ 由于 CentOS 的预设 vsftpd 是能够允许一般用户登入自己家目录的，因此无法登入的可能原因是权限还是 SELinux 呢？ 我们可以这样测试看看：
      # 1. 先用 vbird 的身份登入 vsftpd 看看：
[root@www ~]# ftp localhost
Connected to www.vbird.tsai.
Name (localhost:root): vbird
331 Please specify the password.
Password: <==这里输入 vbird 的密码喔！
500 OOPS: cannot change directory:/home/vbird
Login failed.  <==见鬼了！竟然无法登入自己的家目录 /home/vbird 哩！
ftp> bye

[root@www ~]# ls -ld /home/vbird
drwx------ 4 vbird vbird 4096  8月 18 18:22 /home/vbird
# 权限明明是对的嘛！怎么会无法切换？

# 2. 看看登录档有没有什么重要讯息的说明：
[root@www ~]# tail /var/log/messages
Sep 11 16:57:31 www setroubleshoot: SELinux is preventing the ftp daemon from
reading users home directories (/). For complete SELinux messages. run
sealert -l b8bdaf2d-b083-4e28-9465-91fae8df63b1

# 3. 照著作一下：
[root@www ~]# sealert -l b8bdaf2d-b083-4e28-9465-91fae8df63b1
Summary:
SELinux is preventing the ftp daemon from reading users home directories (/).
....(中间省略)....

The following command will allow this access:
setsebool -P ftp_home_dir=1
....(底下省略)....

    6. 好了，现在让我们处理一下上面的 vsftpd 相关的规则吧！因为是规则挡住了用户的登入了！：
      [root@www ~]# setsebool -P ftp_home_dir=1

[root@www ~]# ftp localhost
Connected to www.vbird.tsai.
Name (localhost:root): vbird
331 Please specify the password.
Password:
230 Login successful.  <==看吧！顺利登入啰！
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> bye
简答题部分：
  • 简单说明什么是程式 (program) 而什么是程序 (process)？
    程式 (program) 是系统上面可以被执行的档案，由于 Linux 的完整档名 (由 / 写起) 仅能有一个， 所以 program 的档名具有单一性。当程式被执行后，就会启动成程序 (process)， 一个 program 可以被不同的使用者或者相同的使用者重复的执行成为多个程序， 且该程式所造成的程序还因为不同的使用者，而有不同的权限，且每个 process 几乎都是独立的。
  • 我今天想要查询 /etc/crontab 与 crontab 这个程式的用法与写法，请问我该如何线上查询？
    查询 crontab 指令可以使用 man crontab 或 info crontab ，至于查询 /etc/crontab ，则可以使用 man 5 crontab 啰！
  • 我要如何查询 crond 这个 daemon 的 PID 与他的 PRI 值呢？
    ps aux | grep crond 即可查到！
  • 我要如何修改 crond 这个 PID 的优先执行序？
    先以 ps aux 找到 crond 的 PID 后，再以： renice -n number PID 来调整！
  • 我是一般身份使用者，我是否可以调整不属于我的程序的 nice 值？此外，如果我调整了我自己的程序的 nice 值到 10 ，是否可以将他调回 5 呢？
    不行！一般身份使用者仅能调整属于自己的 PID 程序，并且，只能将 nice 值一再地调高，并不能调低，所以调整为 10 之后，就不能降回 5 啰！
  • 我要怎么知道我的网路卡在开机的过程中有没有被捉到？
    可以使用 dmesg 来视察！
大标题的图示 参考资料与延伸阅读
  • 注1：关于 fork-and-exec 的说明可以参考如下网页与书籍：
    吴贤明老师维护的网站：http://nmc.nchu.edu.tw/linux/process.htm
    杨振和、作业系统导论、第三章、学贯出版社
  • 注2：对 Linux 核心有兴趣的话，可以先看看底下的连结：
    http://www.linux.org.tw/CLDP/OLD/INFO-SHEET-2.html
    http://oreilly.com/catalog/linuxkernel/chapter/ch10.html
  • 注3：来自 Linux Journal 的关于 /proc 的说明：http://www.linuxjournal.com/article/177
  • 注4：关于 SELinux 相关的网站与文件资料：
    美国国家安全局的 SELinux 简介：http://www.nsa.gov/research/selinux/
    小州老师在 SA 的简报资料：http://kenduest.sayya.org/blog/kenduest-data/2008/10/selinux_sa.pdf
    小州老师上课的讲义：http://kenduest.sayya.org/blog/kenduest-data/2008/5/kenduest-UNIX-selinux-2008-05-15.pdf
    陈永升、‘企业级Linux 系统管理宝典’、学贯行销股份有限公司
    Fedora SELinux 说明：http://fedoraproject.org/wiki/SELinux/SecurityContext
    美国国家安全局对 SELinux 的白皮书：http://www.nsa.gov/research/_files/selinux/papers/module/t1.shtml
    徐秉义老师的 SELinux 设定范例：http://kate.babyface.com.tw/NetAdmin/24200801SELinux/
2002/06/28：第一次完成
2003/02/10：重新编排与加入 FAQ
2005/09/07：将旧的文章移动到 此处 。
2005/09/18：哈哈，终于将这篇写完啰。新增了一些简单的小指令啦。
2009/03/15：将旧的基于 FC4 的文章移动到此处。
2009/03/19：调整 sar 成为 vmstat ，因为 vmstat 是预设有安装的分析工具！
2009/09/11：加入了 nohup 的说明啰！并加入了情境模拟题


鸟哥的 Linux 私房菜 -- 认识 Linux 系统服务的 daemons

为取得较佳浏览结果，请爱用 firefox 浏览本网页
鸟哥的 Linux 私房菜馆 | Linux 基础文件 | Linux 架站文件 | Linux 企业运用 | 安全管理 | 新手讨论 |

第十八章、认识系统服务 (daemons)
最近更新日期：2009/09/14
在 Unix-Like 的系统中，你会常常听到 daemon 这个字眼！那么什么是传说中的 daemon 呢？这些 daemon 放在什么地方？他的功能是什么？该如何启动这些 daemon ？又如何有效的将这些 daemon 管理妥当？此外，要如何视察这些 daemon 开了多少个 ports ？又这些 ports 要如何关闭？还有还有，晓得你系统的这些 port 各代表的是什么服务吗？ 这些都是最基础需要注意的呢！尤其是在架设网站之前，这里的观念就显的更重要了。

1. 什么是 daemon 与服务 (service)
    1.1 daemon 的主要分类： stand alone, super daemon, 工作形态, 命名规则
    1.2 服务与埠口的对应： /etc/services
    1.3 daemon 的启动脚本与启动方式： 设定档, stand alone, service, super daemon
 2. 解析 super daemon 的设定档
    2.1 预设值设定档：xinetd.conf： 重要参数说明
    2.2 一个简单的 rsync 范例设定
 3. 服务的防火墙管理 xinetd, TCP Wrappers
    3.1 /etc/hosts.allow, /etc/hosts.deny 管理： ldd, 设定档语法
    3.2 TCP Wrappers 特殊功能
 4. 系统开启的服务
    4.1 观察系统启动的服务
    4.2 设定开机后立即启动服务的方法： chkconfig, ntsysv
    4.3 CentOS 5.x 预设启动的服务简易说明
 5. 重点回顾
6. 本章习题
7. 参考资料与延伸阅读
8. 针对本文的建议：http://phorum.vbird.org/viewtopic.php?t=23894
大标题的图示 什么是 daemon 与服务 (service)

我们在第十七章就曾经谈过‘服务’这东西！ 当时的说明是‘常驻在记体体中的程序，且可以提供一些系统或网路功能，那就是服务’。而服务一般的英文说法是‘ service ’。

但如果你常常上网去查看一些资料的话，尤其是 Unix-Like 的相关作业系统，应该常常看到‘请启动某某 daemon 来提供某某功能’，唔！那么 daemon 与 service 有关啰？否则为什么都能够提供某些系统或网路功能？此外，这个 daemon 是什么东西呀？ daemon 的字面上的意思就是‘守护神、恶魔？’还真是有点奇怪呦！^_^""！

简单的说，系统为了某些功能必须要提供一些服务 (不论是系统本身还是网路方面)，这个服务就称为 service 。 但是 service 的提供总是需要程式的运作吧！否则如何执行呢？所以达成这个 service 的程式我们就称呼他为 daemon 啰！ 举例来说，达成循环型例行性工作排程服务 (service) 的程式为 crond 这个 daemon 啦！这样说比较容易理解了吧！

Tips:
你不必去区分什么是 daemon 与 service ！事实上，你可以将这两者视为相同！因为达成某个服务是需要一支 daemon 在背景中运作， 没有这支 daemon 就不会有 service ！所以不需要分的太清楚啦！ 		鸟哥的图示

一般来说，当我们以文字模式或图形模式 (非单人维护模式) 完整开机进入 Linux 主机后， 系统已经提供我们很多的服务了！包括列印服务、工作排程服务、邮件管理服务等等； 那么这些服务是如何被启动的？他们的工作型态如何？底下我们就来谈一谈啰！

小标题的图示 daemon 的主要分类

如果依据 daemon 的启动与管理方式来区分，基本上，可以将 daemon 分为可独立启动的 stand alone ， 与透过一支 super daemon 来统一管理的服务这两大类，这两类 daemon 的说明如下：

  • stand_alone：此 daemon 可以自行单独启动服务

就字面上的意思来说，stand alone 就是‘独立的启动’的意思。这种类型的 daemon 可以自行启动而不必透过其他机制的管理； daemon 启动并载入到记忆体后就一直占用记忆体与系统资源。最大的优点就是：因为是一直存在记忆体内持续的提供服务， 因此对于发生用户端的要求时，stand alone 的 daemon 回应速度较快。常见的 stand alone daemon 有 WWW 的 daemon (httpd)、FTP 的 daemon (vsftpd) 等等。

  • super daemon： 一支特殊的 daemon 来统一管理

这一种服务的启动方式则是藉由一个统一的 daemon 来负责唤起服务！这个特殊的 daemon 就被称为 super daemon 。 早期的 super daemon 是 inetd 这一个，后来则被 xinetd 所取代了。这种机制比较有趣的地方在于， 当没有用户端的要求时，各项服务都是未启动的情况，等到有来自用户端的要求时， super daemon 才唤醒相对应的服务。当用户端的要求结束后，被唤醒的这个服务也会关闭并释放系统资源。

这种机制的好处是： (1)由于 super daemon 负责唤醒各项服务，因此 super daemon 可以具有安全控管的机制，就是类似网路防火墙的功能啦！ (2)由于服务在用户端的连线结束后就关闭，因此不会一直占用系统资源。但是缺点是什么呢？ 因为有用户端的连线才会唤醒该服务，而该服务载入到记忆体的时间需要考虑进去，因此服务的反应时间会比较慢一些啦！ 常见的 super daemon 所管理的服务例如 telnet 这个玩意儿就是啦！

Super daemon 的运作示意图
图 1.1.1、Super daemon 的运作示意图

如上所示，Super daemon 是常驻在记忆体中的， Program 1, 2, 3 则是启动某些服务的程式 (未被启动状态)。当有用户端的要求时， Super daemon 才会去触发相关的程式载入成为 daemon 而存在于记忆体中，此时，用户端的要求才会被 Super daemon 导向 Daemon 1 去达成连线！当用户端的要求结束时，Daemon 1 将会被移除，图中实线的连线就会中断啰！

  • 窗口类型的解说

那么这两种启动的方式哪一个比较好呢？见仁见智啦！而且还要看该主机的工作负荷与实际的用途说！ 例如当你的主机是用来作为 WWW 伺服器的，那么 httpd 自然就以 stand alone 的启动方式较佳！事实上，我们常常开玩笑的说明 stand alone 与 super daemon 的情况，可以银行的窗口来作为说明的范例喔！

  • 个别窗口负责单一服务的 stand alone：

    在银行里面，假设有一种单一服务的窗口，例如存钱窗口，所以当你需要存钱的时候，直接前往该窗口，就有‘专人’为你服务啦！ 这就是 stand alone 的情况。

  • 统一窗口负责各种业务的 super daemon：

    在银行里面假设还有另外一种复合型态的统一窗口，同时提供转帐、资金调度、提款等等的业务，那当你需要其中一项业务的时候， 就需要前往该窗口。但是坐在窗口的这个营业员，拿到你的需求单之后，往后面一丢‘喂！那个转帐的仁兄！该你的工作了’ 那么那个仁兄就开始工作去！然而里头还有资金调度与提款等负责业务的仁兄呢？他们在干嘛？嘿嘿！看看报、喝喝茶啰！

    那么这里就会引出另外一个问题啦！假设银行今天的人潮特别的汹涌，所以这个窗口后面除了你之外还有很多的人！ 那么想一想，这个窗口是要‘一个完成再来下一个’还是‘全部都把你们的单据拿来，我全部处理掉’呢？呵呵！ 是不是不太一样？基本上，针对这种 super daemon 的处理模式有两种，分别是这样：

    • multi-threaded (多重执行绪)：
      就是我们提到的，全部的客户之要求都给他拿来，一次给他交办下去，所以一个服务同时会负责好几个程序。

    • single-threaded (单一执行绪)：
      这个就是目前我们‘人类的银行’最常见的方式啦，不论如何，反正一个一个来，第一个没有处理完之前，后面的请排队！嘿嘿！ 所以如果 client 的要求突然大增的话，那么这些晚到的 client 可得等上一等！

    单执行与多重执行的 super daemon 运作方式
    图 1.1.2、单执行与多重执行的 super daemon 运作方式

    如上所示，左侧为多重执行的方式， daemon 会一直被触发多支程序来提供不同 client 的服务，所以不论你是第几个登入者， 都可以享用 daemon 的服务。至于右侧则是单一执行的方式，仅会有一支 daemon 被唤醒，第一个用户达成连线后， 后续想要连线的用户就得要等待，因此她们的连线不会成功的。

另外，需要注意的是，既然银行里头有这两种窗口同时存在，所以啰，在 Linux 系统里面，这两种 daemon 的启动方式也是可以同时存在的啦！也就是说，某些服务可以使用 stand alone 来启动，而有些其他的服务则可以使用 xinetd 这个 super daemon 来管理，大致的情况就是这样啦！了乎！

  • daemon 工作形态的类型

如果以 daemon 提供服务的的工作状态来区分，又可以将 daemon 分为两大类，分别是：

  • signal-control
    这种 daemon 是透过讯号来管理的，只要有任何用户端的需求进来，他就会立即启动去处理！例如印表机的服务 (cupsd)。

  • interval-control
    这种 daemon 则主要是‘每隔一段时间就主动的去执行某项工作’，所以，你要作的是在设定档指定服务要进行的时间与工作， 该服务在指定的时间才会去完成工作。我们在第十六章提到的 atd 与 crond 就属于这种类型的 daemon 啦 (每分钟侦测一次设定档)

另外，如果你对于开发程式很有兴趣的话，那么可以自行查阅一下‘ man 3 daemon ’看看系统对于 daemon 的详细说明吧！ ^_^。

  • daemon 的命名规则

每一个服务的开发者，当初在开发他们的服务时，都有特别的故事啦！不过，无论如何，这些服务的名称被建立之后，被挂上 Linux 使用时，通常在服务的名称之后会加上一个 d ，例如例行性命令的建立的 at, 与 cron 这两个服务， 他的程式档名会被取为 atd 与 crond，这个 d 代表的就是 daemon 的意思。所以，在第十七章中，我们使用了 ps 与 top 来观察程序时，都会发现到很多的 {xxx}d 的程序，呵呵！通常那就是一些 daemon 的程序啰！

小标题的图示 服务与埠口的对应

从第十七章与前一小节对服务的说明后，你应该要知道的是， 系统所有的功能都是某些程序所提供的，而程序则是透过触发程式而产生的。同样的，系统提供的网路服务当然也是这样的！ 只是由于网路牵涉到 TCP/IP 的概念，所以显的比较复杂一些就是了。

玩过网际网路 (Internet) 的朋友应该知道 IP 这玩意儿，大家都说 IP 就是代表你的主机在网际网路上面的‘门牌号码’。 但是你的主机总是可以提供非常多的网路服务而不止一项功能而已，但我们仅有一个 IP 呢！当用户端连线过来我们的主机时， 我们主机是如何分辨不同的服务要求呢？那就是透过埠号 (port number) 啦！埠号简单的想像，他就是你家门牌上面的第几层楼！ 这个 IP 与 port 就是网际网路连线的最重要机制之一啰。我们拿底下的网址来说明：

  • http://ftp.isu.edu.tw/
  • ftp://ftp.isu.edu.tw/

有没有发现，两个网址都是指向 ftp.isu.edu.tw 这个义守大学的 FTP 网站，但是浏览器上面显示的结果却是不一样的？ 是啊！这是因为我们指向不同的服务嘛！一个是 http 这个 WWW 的服务，一个则是 ftp 这个档案传输服务，当然显示的结果就不同了。

port 与 daemon 的对应
图 1.2.1、 port 与 daemon 的对应，用户端连线协定不同，服务导向埠号亦不同

事实上，为了统一整个网际网路的埠号对应服务的功能，好让所有的主机都能够使用相同的机制来提供服务与要求服务， 所以就有了‘通讯协定’这玩意儿。也就是说，有些约定俗成的服务都放置在同一个埠号上面啦！举例来说， 网址列上面的 http 会让浏览器向 WWW 伺服器的 80 埠号进行连线的要求！而 WWW 伺服器也会将 httpd 这个软体启动在 port 80， 这样两者才能够达成连线的！

嗯！那么想一想，系统上面有没有什么设定可以让服务与埠号对应在一起呢？那就是 /etc/services 啦！

[root@www ~]# cat /etc/services
....(前面省略)....
ftp             21/tcp
ftp             21/udp          fsp fspd
ssh             22/tcp                          # SSH Remote Login Protocol
ssh             22/udp                          # SSH Remote Login Protocol
....(中间省略)....
http            80/tcp          www www-http    # WorldWideWeb HTTP
http            80/udp          www www-http    # HyperText Transfer Protocol
....(底下省略)....
# 这个档案的内容是以底下的方式来编排的：
# <daemon name>   <port/封包协定>   <该服务的说明>

像上面说的是，第一栏为 daemon 的名称、第二栏为该 daemon 所使用的埠号与网路资料封包协定， 封包协定主要为可靠连线的 TCP 封包以及较快速但为非连线导向的 UDP 封包。 举个例子说，那个远端连线机制使用的是 ssh 这个服务，而这个服务的使用的埠号为 22 ！就是这样啊！

Tips:
请特别注意！虽然有的时候你可以藉由修改 /etc/services 来更改一个服务的埠号，不过并不建议如此做， 因为很有可能会造成一些协定的错误情况！这里特此说明一番呦！(除非你要架设一个地下网站，否则的话，使用 /etc/services 原先的设定就好啦！) 		鸟哥的图示
小标题的图示 daemon 的启动脚本与启动方式

提供某个服务的 daemon 虽然只是一支程式而已，但是这支 daemon 的启动还是需要执行档、设定档、执行环境等等， 举例来说，你可以查阅一下 httpd 这个程式 (man httpd) ，里面可谈到不少的选项与参数呢！此外，为了管理上面的方便， 所以通常 distribution 都会记录每一支 daemon 启动后所取得程序的 PID 在 /var/run/ 这个目录下呢！ 还有还有，在启动这些服务之前，你可能也要自行处理一下 daemon 能够顺利执行的环境是否正确等等。鸟哥这里要讲的是， 要启动一支 daemon 考虑的事情很多，并非单纯执行一支程式就够了。

为了解决上面谈到的问题，因此通常 distribution 会给我们一个简单的 shell script 来进行启动的功能。 该 script 可以进行环境的侦测、设定档的分析、PID 档案的放置，以及相关重要交换档案的锁住 (lock) 动作， 你只要执行该 script ，上述的动作就一口气连续的进行，最终就能够顺利且简单的启动这个 daemon 啰！ 这也是为何我们会希望你可以详细的研究一下第十三章的原因啊。

OK！那么这些 daemon 的启动脚本 (shell script) 放在哪里啊？还有， CentOS 5.x 通常将 daemon 相关的档案放在哪里？ 以及某些重要的设定档又是放置到哪里？基本上是放在这些地方：

  • /etc/init.d/* ：启动脚本放置处
    系统上几乎所有的服务启动脚本都放置在这里！事实上这是公认的目录，我们的 CentOS 实际上放置在 /etc/rc.d/init.d/ 啦！ 不过还是有设定连结档到 /etc/init.d/ 的！既然这是公认的目录，因此建议您记忆这个目录即可！啰

  • /etc/sysconfig/* ：各服务的初始化环境设定档
    几乎所有的服务都会将初始化的一些选项设定写入到这个目录下，举例来说，登录档的 syslog 这支 daemon 的初始化设定就写入在 /etc/sysconfig/syslog 这里呢！而网路的设定则写在 /etc/sysconfig/network 这个档案中。 所以，这个目录内的档案也是挺重要的；

  • /etc/xinetd.conf, /etc/xinetd.d/* ：super daemon 设定档
    super daemon 的主要设定档 (其实是预设值) 为 /etc/xinetd.conf ，不过我们上面就谈到了， super daemon 只是一个统一管理的机制，他所管理的其他 daemon 的设定则写在 /etc/xinetd.d/* 里头喔！

  • /etc/* ：各服务各自的设定档
    第六章就讲过了，大家的设定档都是放置在 /etc/ 底下的喔！

  • /var/lib/* ：各服务产生的资料库
    一些会产生资料的服务都会将他的资料写入到 /var/lib/ 目录中。举例来说，资料库管理系统 MySQL 的资料库预设就是写入 /var/lib/mysql/ 这个目录下啦！

  • /var/run/* ：各服务的程序之 PID 记录处
    我们在第十七章谈到可以使用讯号 (signal) 来管理程序， 既然 daemon 是程序，所以当然也可以利用 kill 或 killall 来管理啦！不过为了担心管理时影响到其他的程序， 因此 daemon 通常会将自己的 PID 记录一份到 /var/run/ 当中！例如登录档的 PID 就记录在 /var/run/syslogd.pid 这个档案中。如此一来， /etc/init.d/syslog 就能够简单的管理自己的程序啰。

上面谈到的部分是设定档，那么 stand alone 与 super daemon 所管理的服务启动方式怎么作呢？他是这样做的喔：

  • Stand alone 的 /etc/init.d/* 启动

刚刚谈到了几乎系统上面所有服务的启动脚本都在 /etc/init.d/ 底下，这里面的脚本会去侦测环境、搜寻设定档、 载入 distribution 提供的函数功能、判断环境是否可以运作此 daemon 等等，等到一切都侦测完毕且确定可以运作后， 再以 shell script 的 case....esac 语法来启动、关闭、 观察此 daemon 喔！我们可以简单的以 /etc/init.d/syslog 这个登录档启动脚本来进行说明：

[root@www ~]# /etc/init.d/syslog
用法: /etc/init.d/syslog {start|stop|status|restart|condrestart}
# 什么参数都不加的时候，系统会告诉你可以用的参数有哪些，如上所示。

范例一：观察 syslog 这个 daemon 目前的状态
[root@www ~]# /etc/init.d/syslog status
syslogd (pid 4264) 正在执行...
klogd (pid 4267) 正在执行...
# 代表 syslog 管理两个 daemon ，这两个 daemon 正在运作中啦！

范例二：重新让 syslog 读取一次设定档
[root@www ~]# /etc/init.d/syslog restart
正在关闭核心记录器:          [  确定  ]
正在关闭系统记录器:          [  确定  ]
正在启动系统记录器:          [  确定  ]
正在启动核心记录器:          [  确定  ]
[root@www ~]# /etc/init.d/syslog status
syslogd (pid 4793) 正在执行...
klogd (pid 4796) 正在执行...
# 因为重新启动过，所以 PID 与第一次观察的值就不一样了！这样了解乎？

由于系统的环境都已经帮你制作妥当，所以利用 /etc/init.d/* 来启动、关闭与观察，就非常的简单！话虽如此， CentOS 还是有提供另外一支可以启动 stand alone 服务的脚本喔，那就是 service 这个程式。 其实 service 仅是一支 script 啦，他可以分析你下达的 service 后面的参数，然后根据你的参数再到 /etc/init.d/ 去取得正确的服务来 start 或 stop 哩！他的语法是这样的啦：

[root@www ~]# service [service name] (start|stop|restart|...)
[root@www ~]# service --status-all
选项与参数：
service name：亦即是需要启动的服务名称，需与 /etc/init.d/ 对应；
start|...   ：亦即是该服务要进行的工作。
--status-all：将系统所有的 stand alone 的服务状态通通列出来

范例三：重新启动 crond 这支 daemon ：
[root@www ~]# service crond restart
[root@www ~]# /etc/init.d/crond restart
# 这两种方法随便你用哪一种来处理都可以！不过鸟哥比较喜欢使用 /etc/init.d/*

范例四：显示出目前系统上面所有服务的运作状态
[root@www ~]# service --status-all
acpid (pid 4536) 正在执行...
anacron 已停止
atd (pid 4694) 正在执行...
....(底下省略)....

这样就将一堆服务的运作状态列出，你也可以根据这个输出的结果来查询你的某些服务是否正确运作了啊！^_^！ 其实，在上面的范例当中，启动方式以 service 这个程式，或者直接去到 /etc/init.d/ 底下启动，都一样啦！自行去解析 /sbin/service 就知道为啥了！ ^_^

Tips:
事实上，在 Linux 系统中，要‘开或关某个 port ’，就是需要‘ 启动或关闭某个服务’啦！因此，你可以找出某个 port 对应的服务，程式对应的服务， 进而启动或关闭他，那么那个经由该服务而启动的 port ，自然就会关掉了！ 		鸟哥的图示
  • Super daemon 的启动方式

其实 Super daemon 本身也是一支 stand alone 的服务，看图 1.1.1 就知道啦！因为 super daemon 要管理后续的其他服务嘛，他当然自己要常驻在记忆体中啦！所以 Super daemon 自己启动的方式与 stand alone 是相同的！ 但是他所管理的其他 daemon 就不是这样做啰！必须要在设定档中设定为启动该 daemon 才行。设定档就是 /etc/xinetd.d/* 的所有档案。那如何得知 super daemon 所管理的服务是否有启动呢？你可以这样做：

[root@www ~]# grep -i 'disable' /etc/xinetd.d/*
....(前面省略)....
/etc/xinetd.d/rsync:          disable = yes
/etc/xinetd.d/tcpmux-server:  disable = yes
/etc/xinetd.d/time-dgram:     disable = yes
/etc/xinetd.d/time-stream:    disable = yes

因为 disable 是‘取消’的意思，因此如果‘ disable = yes ’则代表取消此项服务的启动，如果是‘ disable = no ’ 才是有启动该服务啦！假设我想要启动如上的 rsync 这个服务，那么你可以这样做：

# 1. 先修改设定档成为启动的模样：
[root@www ~]# vim /etc/xinetd.d/rsync
# 请将 disable 那一行改成如下的模样 (原本是 yes 改成 no 就对了)
service rsync
{
        disable = no
....(后面省略)....

# 2. 重新启动 xinetd 这个服务
[root@www ~]# /etc/init.d/xinetd restart
正在停止 xinetd:             [  确定  ]
正在启动 xinetd:             [  确定  ]

# 3. 观察启动的埠口
[root@www ~]# grep 'rsync' /etc/services  <==先看看埠口是哪一号
rsync           873/tcp               # rsync
rsync           873/udp               # rsync
[root@www ~]# netstat -tnlp | grep 873
tcp    0 0 0.0.0.0:873      0.0.0.0:*     LISTEN      4925/xinetd
# 注意看！启动的服务并非 rsync 喔！而是 xinetd ，因为他要控管 rsync 嘛！
# 若有疑问，一定要去看看图 1.1.1 才行！

也就是说，你先修改 /etc/xinetd.d/ 底下的设定档，然后再重新启动 xinetd 就对了！而 xinetd 是一个 stand alone 启动的服务！这部份得要特别留意呢！

大标题的图示 解析 super daemon 的设定档

前一小节谈到的 super daemon 我们现在知道他是一支总管程序，这个 super daemon 是 xinetd 这一支程序所达成的。 而且由图 1.1.1 我们知道这个 xinetd 可以进行安全性或者是其他管理机制的控管， 由图 1.1.2 则可以了解 xinetd 也能够控制连线的行为。这些控制的手段都可以让我们的某些服务更为安全， 资源管理更为合理。而由于 super daemon 可以作这样的管理，因此一些对用户端开放较多权限的服务 (例如 telnet)， 或者本身不具有管理机制或防火墙机制的服务，就可以透过 xinetd 来管理啊！

既然这家伙这么重要，那么底下我们就来谈谈 xinetd 这个服务的预设设定档 /etc/xinetd.conf ，以及各个设定项目的意义啰！

小标题的图示 预设值设定档：xinetd.conf

先来看一看预设的 /etc/xinetd.conf 这个档案的内容是什么吧！

[root@www ~]# vim /etc/xinetd.conf
defaults
{
# 服务启动成功或失败，以及相关登入行为的记录档
        log_type        = SYSLOG daemon info  <==登录档的记录服务类型
        log_on_failure  = HOST   <==发生错误时需要记录的资讯为主机 (HOST)
        log_on_success  = PID HOST DURATION EXIT <==成功启动或登入时的记录资讯
# 允许或限制连线的预设值
        cps         = 50 10 <==同一秒内的最大连线数为 50 个，若超过则暂停 10 秒
        instances   = 50    <==同一服务的最大同时连线数
        per_source  = 10    <==同一来源的用户端的最大连线数
# 网路 (network) 相关的预设值
        v6only          = no <==是否仅允许 IPv6 ？可以先暂时不启动 IPv6 支援！
# 环境参数的设定
        groups          = yes
        umask           = 002
}

includedir /etc/xinetd.d <==更多的设定值在 /etc/xinetd.d 那个目录内

为什么 /etc/xinetd.conf 可以称为预设值的设定档呢？因为如果你有启动某个 super daemon 管理的服务， 但是该服务的设定值并没有指定上述的那些项目，那么该服务的设定值就以上述的预设值为主！ 至于上述的预设值会将 super daemon 管理的服务设定为：‘一个服务最多可以有 50 个同时连线， 但每秒钟发起的“新”连线最多仅能有 50 条，若超过 50 条则该服务会暂停 10 秒钟。同一个来源的用户最多仅能达成 10 条连线。 而登入的成功与失败所记录的资讯并不相同。’这样说，可以比较清楚了吧？ ^_^ 至于更多的参数说明，我们会在底下再强调的！

既然这只是个预设参数档，那么自然有更多的服务参数档案啰～没错～而所有的服务参数档都在 /etc/xinetd.d 里面，这是因为上表当中的最后一行啊！这样了了吧！ ^_^。那么每个参数档案的内容是怎样呢？一般来说，他是这样的：

service  <service_name>
{
       <attribute>   <assign_op>   <value>   <value> ...
       .............
}

第一行一定都有个 service ，至于那个 <service_name> 里面的内容，则与 /etc/services 有关，因为他可以对照着 /etc/services 内的服务名称与埠号来决定所要启用的 port 是哪个啊！ 然后相关的参数就在两个大刮号中间。attribute 是一些 xinetd 的管理参数， assign_op 则是参数的设定方法。 assign_op 的主要设定形式为：

= ： 表示后面的设定参数就是这样啦！
+= ： 表示后面的设定为‘在原来的设定里头加入新的参数’
-= ： 表示后面的设定为‘在原来的参数舍弃这里输入的参数！’

用途不太相同，敬请留意呦！好了！底下再来说一说那些 attribute 与 value ！

attribute (功能) | 说明与范例
一般设定项目：服务的识别、启动与程式
disable
(启动与否)
  • 设定值：[yes|no]，预设 disable = yes
disable 为取消的意思，此值可设定该服务是否要启动。预设所有的 super daemon 管理的服务都不启动的。 若要启动就得要设定为‘ disable = no ’
id
(服务识别)
  • 设定值：[服务的名称]
虽然服务在设定档开头‘ service 服务名称’已经指定了，不过有时后会有重复的设定值，此时可以用 id 来取代服务名称。 你可以参考一下 /etc/xinetd.d/time-stream 来思考一下原理。
server
(程式档名)
  • 设定值：[program 的完整档名]
这个就是指出这个服务的启动程式！例如 /usr/bin/rsync 为启动 rsync 服务的指令，所以这个设定值就会成为： ‘ server = /usr/bin/rsync ’
server_args
(程式参数)
  • 设定值：[程式相关的参数]
这里应该输入的就是你的 server 那里需要输入的一些参数啦！例如 rsync 需要加入 --daemon ， 所以这里就设定：‘ server_args = --daemon ’。与上面 server 搭配，最终启动服务的方式‘/usr/bin/rsync --daemon’
user
(服务所属UID)
  • 设定值：[使用者帐号]
如果 xinetd 是以 root 的身份启动来管理的，那么这个项目可以设定为其他使用者。此时这个 daemon 将会以此设定值指定的身份来启动该服务的程序喔！举例来说，你启动 rsync 时会以这个设定值作为该程序的 UID。
group | 跟 user 的意思相同！此项目填入群组名称即可。
一般设定项目：连线方式与连线封包协定
socket_type
(封包类型)
  • 设定值：[stream|dgram|raw]，与封包有关
stream 为连线机制较为可靠的 TCP 封包，若为 UDP 封包则使用 dgram 机制。raw 代表 server 需要与 IP 直接对谈！举例来说 rsync 使用 TCP ，故设定为‘socket_type = stream ’
protocol
(封包类型)
  • 设定值：[tcp|udp]，通常使用 socket_type 取代此设定
使用的网路通讯协定，需参考 /etc/protocols 内的通讯协定，一般使用 tcp 或 udp。由于与 socket_type 重复， 因此这个项目可以不指定。
wait
(连线机制)
  • 设定值：[yes(single)|no(multi)]，预设 wait = no
这就是我们刚刚提到的 Multi-threaded 与 single-threaded ！一般来说，我们希望大家的要求都可以同时被启用，所以可以设定‘ wait = no ’ 此外，一般 udp 设定为 yes 而 tcp 设定为 no。
instances
(最大连线数)
  • 设定值：[数字或 UNLIMITED]
这个服务可接受的最大连线数量。如果你只想要开放 30 个人连线 rsync 时，可在设定档内加入：‘ instances = 30 ’
per_source
(单一用户来源)
  • 设定值：[一个数字或 NULIMITED]
如果想要控制每个来源 IP 仅能有一个最大的同时连线数，就指定这个项目吧！例如同一个 IP 最多只能连 10 条连线‘ per_source = 10 ’
cps
(新连线限制)
  • 设定值：[两个数字]
为了避免短时间内大量的连线要求导致系统出现忙碌的状态而有这个 cps 的设定值。第一个数字为一秒内能够接受的最多新连线要求， 第二个数字则为，若超过第一个数字那暂时关闭该服务的秒数。
一般设定项目：登录档的记录
log_type
(登录档类型)
  • 设定值：[登录项目 等级]
当资料记录时，以什么登录项目记载？且需要记载的等级为何(预设为 info 等级)。这两个设定值得要看过下一章登录档后才会知道哩！这边你先有印象即可。
log_on_success
log_on_failure
(登录状态)
  • 设定值：[PID,HOST,USERID,EXIT,DURATION]
在‘成功登入’或‘失败登入’之后，需要记录的项目：PID 为纪录该 server 启动时候的 process ID ， HOST 为远端主机的 IP、USERID 为登入者的帐号、EXIT 为离开的时候记录的项目、DURATION 为该使用者使用此服务多久？
进阶设定项目：环境、网路埠口与连线机制等
env
(额外变数设定)
  • 设定值：[变数名称=变数内容]
这一个项目可以让你设定环境变数，环境变数的设定规则可以参考第十一章。
port
(非正规埠号)
  • 设定值：[一组数字(小于 65534)]
这里可以设定不同的服务与对应的 port ，但是请记住你的 port 与服务名称必须与 /etc/services 内记载的相同才行！不过，若服务名称是你自订的，那么这个 port 就可以随你指定
redirect
(服务转址)
  • 设定值：[IP port]
将 client 端对我们 server 的要求，转到另一部主机上去！呵呵！这个好玩呦！ 例如当有人要使用你的 ftp 时，你可以将他转到另一部机器上面去！那个 IP_Address 就代表另一部远端主机的 IP 啰！
includedir
(呼叫外部设定)
  • 设定值：[目录名称]
表示将某个目录底下的所有档案都给他塞进来 xinetd.conf 这个设定里头！这东西有用多了， 如此一来我们可以一个一个设定不同的项目！而不需要将所有的服务都写在 xinetd.conf 当中！你可以在 /etc/xinetd.conf 发现这个设定呦！
安全控管项目：
bind
(服务介面锁定)
  • 设定值：[IP]
这个是设定‘允许使用此一服务的介面卡’的意思！举个例子来说，你的 Linux 主机上面有两个 IP ，而你只想要让 IP1 可以使用此一服务，但 IP2 不能使用此服务，这里就可以将 IP1 写入即可！那么 IP2 就不可以使用此一 server 啰
interface
  • 设定值：[IP]
与 bind 相同
only_from
(防火墙机制)
  • 设定值：[0.0.0.0, 192.168.1.0/24, hostname, domainname]
这东西用在安全机制上面，也就是管制‘只有这里面规定的 IP 或者是主机名称可以登入！’如果是 0.0.0.0 表示所有的 PC 皆可登入，如果是 192.168.1.0/24 则表示为 C class 的网域！亦即由 192.168.1.1 ~ 192.168.1.255 皆可登入！另外，也可以选择 domain name ，例如 .dic.ksu.edu.tw 就可以允许昆山资传系网域的 IP 登入你的主机使用该 server ！
no_access
(防火墙机制)
  • 设定值：[0.0.0.0, 192.168.1.0/24, hostname, domainname]
跟 only_from 差不多啦！就是用来管理可否进入你的 Linux 主机启用你的 server 服务的管理项目！ no_access 表示‘不可登入’的 PC 啰！
access_times
(时间控管)
  • 设定值：[00:00-12:00, HH:MM-HH:MM]
这个项目在设定‘该服务 server 启动的时间’，使用的是 24 小时的设定！例如你的 ftp 要在 8 点到 16 点开放的话，就是： 08:00-16:00。
umask
  • 设定值：[000, 777, 022]
还记得在第七章提到的 umask 这个东西吗？呵呵！没错！ 就是那个鬼玩意儿啰！可以设定使用者建立目录或者是档案时候的属性！系统建议值是 022 。

OK！我们就利用上面这些参数来架构出我们所需要的一些服务的设定吧！参考看看底下的设定方法啰！ ^_^

小标题的图示 一个简单的 rsync 范例设定

我们知道透过 super daemon 控管的服务可以多一层管理的手续来达成类似防火墙的机制， 那么该如何仔细的设定这些类似防火墙机制的设定参数呢？底下我们使用 rsync 这个可以进行远端镜射 (mirror) 的服务来说明。 rsync 可以让两部主机上面的某个目录一模一样，在远端异地备援系统上面是挺好用的一个机制。 而且预设一装好 CentOS 就已经存在这玩意儿了！那就来瞧瞧预设的 rsync 设定档吧！

[root@www ~]# vim /etc/xinetd.d/rsync
service rsync  <==服务名称为 rsync
{
        disable = no                     <==预设是关闭的！刚刚被我们打开了
        socket_type     = stream         <==使用 TCP 的连线机制之故
        wait            = no             <==可以同时进行大量连线功能
        user            = root           <==启动服务为 root 这个身份
        server          = /usr/bin/rsync <==就是这支程式启动 rsync 的服务啰
        server_args     = --daemon       <==这是必要的选项啊！
        log_on_failure  += USERID        <==登入错误时，额外记录使用者 ID
}

能不能修改 user 成为其他身份呢？由于在 /etc/services 当中规定 rsync 使用的埠口号码为 873 ，这个埠口小于 1024 ，所以理论上启动这个埠口的身份一定要是 root 才行！这里 user 就请您先别乱改啰！ 由于鸟哥的测试主机在安装时已经有捉到网路卡，目前有两个介面，一个是 192.168.1.100 ，一个则是 127.0.0.1， 假设我将 192.168.1.100 设计为对外网域， 127.0.0.1 为内部网域，且内外网域的分别权限设定为：

  • 对内部 127.0.0.1 网域开放较多权限的部分：
    • 这里的设定值需绑在 127.0.0.1 这个介面上；
    • 对 127.0.0.0/8 开放登入权限；
    • 不进行任何连线的限制，包括总连线数量与时间；
    • 但是 127.0.0.100 及 127.0.0.200 不允许登入 rsync 服务。

  • 对外部 192.168.1.100 网域较多限制的设定：
    • 对外设定绑住 192.168.1.100 这个介面；
    • 这个介面仅开放 140.116.0.0/16 这个 B 等级的网域及 .edu.tw 网域可以登入；
    • 开放的时间为早上 1-9 点以及晚上 20-24 点两个时段；
    • 最多允许 10 条同时连线的限制。
Tips:
有资讯背景的朋友当然知道 127.0.0.1 是内部回圈测试用的 IP ，用他来设计网路是没有意义的。 不过，我们这里仅是作一个设计的介绍，而且我们尚未谈到伺服器篇的网路部分，所以大家先这样实际测试吧！ ^_^ 		鸟哥的图示

在这样的规划情况下，我们可以将刚刚上头的 /etc/xinetd.d/rsync 这个档案修改成为：

[root@www ~]# vim /etc/xinetd.d/rsync
# 先针对对内的较为松散的限制来设定：
service rsync
{
        disable = no                        <==要启动才行啊！
        bind            = 127.0.0.1         <==服务绑在这个介面上！
        only_from       = 127.0.0.0/8       <==只开放这个网域的来源登入
        no_access       = 127.0.0.{100,200} <==限制这两个不可登入
        instances       = UNLIMITED         <==取代 /etc/xinetd.conf 的设定值
        socket_type     = stream            <==底下的设定则保留
        wait            = no
        user            = root
        server          = /usr/bin/rsync
        server_args     = --daemon
        log_on_failure  += USERID
}

# 再针对外部的连线来进行限制呢！
service rsync
{
        disable = no
        bind            = 192.168.1.100
        only_from       = 140.116.0.0/16
        only_from      += .edu.tw           <==因为累加，所以利用 += 设定
        access_times    = 01:00-9:00 20:00-23:59 <==时间有两时段，有空格隔开
        instances       = 10                <==只有 10 条连线
        socket_type     = stream
        wait            = no
        user            = root
        server          = /usr/bin/rsync
        server_args     = --daemon
        log_on_failure  += USERID
}

在上面这个设定档中，鸟哥共写了两段 service rsync 的设定，一段针对内部网域一段针对外部网域， 如果设计完毕你将他重新启动后，就会出现如下的状态喔！

# 0. 先看看原本的 873 状态为何！
[root@www ~]# netstat -tnlp | grep 873
tcp    0 0 0.0.0.0:873      0.0.0.0:*     LISTEN      4925/xinetd
# 仔细看，仅针对 0.0.0.0 这个全域网域监听而已哩！

# 1. 重新启动 xinetd 吧！不是启动 rsync 喔！别搞错。
[root@www ~]# /etc/init.d/xinetd restart
[root@www ~]# netstat -tnlp | grep 873
tcp    0 0 192.168.1.100:873     0.0.0.0:*       LISTEN    7227/xinetd
tcp    0 0 127.0.0.1:873         0.0.0.0:*       LISTEN    7227/xinetd
# 有没有看到两个介面啊～而且， PID 会是同一个呢！

如同上面的设定，我们就可以将某个系统服务针对不同的用户端来源指定不同的使用权限！这样子系统服务可以安全多了！ 如果未来你的某些服务想要使用这个咚咚来设定也是 OK 的喔！更多的设定资料就有待您自己的理解了。

大标题的图示 服务的防火墙管理 xinetd, TCP Wrappers

一般来说，系统的防火墙分析主要可以透过封包过滤或者是透过软体分析，我们的 Linux 预设有提供一个软体分析的工具， 那就是 /etc/hosts.deny, /etc/hosts.allow 这两个可爱的设定档！另外，如果有安装 tcp wrappers 套件时， 我们甚至可以加上一些额外的追踪功能呢！底下就让我们分别来谈谈这些玩意儿吧！

小标题的图示 /etc/hosts.allow, /etc/hosts.deny 管理

我们在前面几章知道了要管制 at 的使用可以透过修订 /etc/at.{allow|deny} 来管理，至于 crontab 则是使用 /etc/cron.{allow|deny} 来管理的。那么有没有办法透过个什么机制，就能够管理某些程式的网路使用呢？ 就有点像管理某些程式是否能够接受或者是拒绝来自网际网路的连线的意思啦！有的！那就是 /etc/hosts.{allow|deny} 啰。

任何以 xinetd 管理的服务，都可以透过 /etc/hosts.allow, /etc/hosts.deny 来设定防火墙。那么什么是防火墙呢？简单的说，就是针对来源 IP 或网域进行允许或拒绝的设定， 以决定该连线是否能够成功达成连接的一种方式就是了。其实我们刚刚修改 /etc/xinetd.d/rsync 里头的 no_access, only_from 也可以进行这方面的防火墙设定。不过，使用 /etc/hosts.allow, /etc/hosts.deny 则更容易集中控管，在设定与查询方面也较为方便！ 那么就让我们谈谈这两个档案的设定技巧吧！

其实 /etc/hosts.allow 与 /etc/hosts.deny 也是 /usr/sbin/tcpd 的设定档，而这个 /usr/sbin/tcpd 则是用来分析进入系统的 TCP 网路封包的一个软体，TCP 是一种连线导向的网路连线封包，包括 www, email, ftp 等等都是使用 TCP 封包来达成连线的喔。 所以啰，顾名思义，这个套件本身的功能就是在分析 TCP 网路资料封包啦！而 TCP 封包的档头主要记录了来源与目主机的 IP 与 port ，因此藉由分析 TCP 封包并搭配 /etc/hosts.{allow,deny} 的规则比对，就可以决定该连线是否能够进入我们的主机啦。 所以啦，我们要使用 TCP Wrappers 来控管的就是：

  1. 来源 IP 或/与 整个网域的 IP 网段；
  2. port (就是服务啦，前面有谈到启动某个埠口是 daemon 的责任啊)

基本上只要一个服务受到 xinetd 管理，或者是该服务的程式支援 TCP Wrappers 函式的功能时，那么该服务的防火墙方面的设定就能够以 /etc/hosts.{allow,deny} 来处理啰。换个方式来说，只要不支援 TCP Wrappers 函式功能的软体程式就无法使用 /etc/hosts.{allow,deny} 的设定值啦，这样说，有没有比较清楚啊。不过，那要如何得知一个服务的程式有没有支援 TCP Wrappers 呢，你可以这样简单的处理喔。

范例一：测试一下达成 sshd 及 httpd 这两个程式有无支援 TCP Wrappers 的功能
[root@www ~]# ldd $(which sshd httpd)
/usr/sbin/sshd:
        libwrap.so.0 => /usr/lib64/libwrap.so.0 (0x00002abcbfaed000)
        libpam.so.0 => /lib64/libpam.so.0 (0x00002abcbfcf6000)
....(中间省略)....
/usr/sbin/httpd:
        libm.so.6 => /lib64/libm.so.6 (0x00002ad395843000)
        libpcre.so.0 => /lib64/libpcre.so.0 (0x00002ad395ac6000)
....(底下省略)....
# 重点在于软体有没有支援 libwrap.so 那个函式库啰

ldd (library dependency discovery) 这个指令可以查询某个程式的动态函式库支援状态，因此透过这个 ldd 我们可以轻松的就查询到 sshd, httpd 有无支援 tcp wrappers 所提供的 libwrap.so 这个函式库档案。从上表的输出中我们可以发现， sshd 有支援但是 httpd 则没有支援。因此我们知道 sshd 可以使用 /etc/hosts.{allow,deny} 进行类似防火墙的抵挡机制，但是 httpd 则没有此项功能喔！

  • 设定档语法

这两个档案的设定语法都是一样的，基本上，看起来应该像这样：

<service(program_name)> : <IP, domain, hostname> : <action>
<服务   (亦即程式名称)> : <IP 或领域 或主机名称> : < 动作 >
# 上头的 < > 是不存在于设定档中的喔！

重点是两个，第一个是找出你想要管理的那个程式的档名，第二个才是写下来你想要放行或者是抵挡的 IP 或网域呢。 那么程式的档名要如何写呢？其实就是写下档名啦！举例来说上面我们谈到过 rsync 设定档内不是有 server 的参数吗？ rsync 设定档内 /usr/bin/rsync 为其参数值，那么在我们这里就得要写成 rsync 即可喔！依据 rsync 的设定档资料，我们将抵挡的 127.0.0.100, 127.0.0.200, 及放行的 140.116.0.0/16 写在这哩，内容有点像这样：

Tips:
关于 IP, 网域, 网段, 还有相关的网路知识，在这个基础篇当中我们不会谈到，你只要记得底下写的 140.116.0.0/255.255.0.0 代表一个网域就是了。详细的资料请先自行参考伺服器架设篇的内容！ 		鸟哥的图示
[root@www ~]# vim /etc/hosts.deny
rsync : 127.0.0.100 127.0.0.200 : deny

当然也可以写成两行，亦即是：

[root@www ~]# vim /etc/hosts.deny
rsync : 127.0.0.100       : deny
rsync : 127.0.0.200       : deny

这样一来，对方就无法以 rsync 进入你的主机啦！方便吧！不过，既然如此，为什么要设定成 /etc/hosts.allow 及 /etc/hosts.deny 两个档案呢？其实只要有一个档案存在就够了， 不过，为了设定方便起见，我们存在两个档案，其中需要注意的是：

  • 写在 hosts.allow 当中的 IP 与网段，为预设‘可通行’的意思，亦即最后一个栏位 allow 可以不用写；
  • 而写在 hosts.deny 当中的 IP 与网段则预设为 deny ，第三栏的 deny 亦可省略；
  • 这两个档案的判断依据是： (1) 以 /etc/hosts.allow 为优先，而 (2) 若分析到的 IP 或网段并没有记录在 /etc/hosts.allow ，则以 /etc/hosts.deny 来判断。

也就是说， /etc/hosts.allow 的设定优先于 /etc/hosts.deny 啰！基本上，只要 hosts.allow 也就够了，因为我们可以将 allow 与 deny 都写在同一个档案内，只是这样一来似乎显得有点杂乱无章，因此，通常我们都是：

  1. 允许进入的写在 /etc/hosts.allow 当中；
  2. 不许进入的则写在 /etc/hosts.deny 当中。

此外，我们还可以使用一些特殊参数在第一及第二个栏位喔！内容有：

  • ALL：代表全部的 program_name 或者是 IP 都接受的意思，例如 ALL: ALL: deny
  • LOCAL：代表来自本机的意思，例如： ALL: LOCAL: allow
  • UNKNOWN：代表不知道的 IP 或者是 domain 或者是服务时；
  • KNOWN：代表为可解析的 IP, domain 等等资讯时；

再强调一次，那个 service_name 其实是启动该服务的程式，举例来说， /etc/init.d/sshd 这个 script 里面， 实际上启动 ssh 服务的是 sshd 这个程式，所以，你的 service_name 自然就是 sshd 啰！ 而 /etc/xinetd.d/telnet (你的系统可能尚未安装) 内有个 server 的设定项目， 那个项目指到 in.telnetd 这个程式来启动的喔！要注意的很！(请分别使用 vi 进这两支 scripts 查阅) 好了，我们还是以 rsync 为例子来说明好了，现在假设一个比较安全的流程来设定，就是：

  1. 只允许 140.116.0.0/255.255.0.0 与 203.71.39.0/255.255.255.0 这两个网域，及 203.71.38.123 这个主机可以进入我们的 rsync 伺服器；
  2. 此外，其他的 IP 全部都挡掉！
这样的话，我可以这样设定：
[root@www ~]# vim /etc/hosts.allow
rsync:  140.116.0.0/255.255.0.0
rsync:  203.71.39.0/255.255.255.0
rsync:  203.71.38.123
rsync:  LOCAL

[root@www ~]# vim /etc/hosts.deny
rsync: ALL  <==利用 ALL 设定让所有其他来源不可登入
小标题的图示 TCP Wrappers 特殊功能

那么有没有更安全的设定？例如，当有其他人扫瞄我的 rsync port 时，我就将他的 IP 记住，以做为未来的查询与认证之用呢？ 是有的！只是，那就得要有额外的动作参数加在第三栏了，而且你还需要安装了 TCP Wrappers 软体才行。要确定有没有安装 TCP Wrappers 可以使用‘ rpm -q tcp_wrappers ’来查询喔。至于更加细部的主要动作则有：

  • spawn (action)
    可以利用后续接的 shell 来进行额外的工作，且具有变数功能，主要的变数内容为： %h (hostname), %a (address), %d (daemon)等等；

  • twist (action)
    立刻以后续的指令进行，且执行完后终止该次连线的要求 (DENY)

为了达成追踪来源目标的相关资讯的目的，此时我们需要 safe_finger 这个指令的辅助才行。而且我们还希望用户端的这个恶意者能够被警告。 整个流程可以是这样的：

  1. 利用 safe_finger 去追踪出对方主机的资讯 (包括主机名称、使用者相关资讯等)；
  2. 将该追踪到的结果以 email 的方式寄给我们本机的 root ；
  3. 在对方荧幕上面显示不可登入且警告他已经被记录的讯息

由于是抵挡的机制，因此我们这个 spawn 与 twist 的动作大多是写在 /etc/hosts.deny 档案中的。我们将上述的动作写成类似如下的东东：

[root@www ~]# vim /etc/hosts.deny
rsync : ALL: spawn (echo "security notice from host $(/bin/hostname)" ;\
    echo; /usr/sbin/safe_finger @%h ) | \
    /bin/mail -s "%d-%h security" root & \
    : twist ( /bin/echo -e "\n\nWARNING connection not allowed.\n\n" )

上面其实是针对一个 rsync 所写的资讯，你可以看到上面这四行共有三个冒号来隔开成四个咚咚，这四个咚咚的意义是：

  1. rsync： 指的就是 rsync 这个服务的程式啰；

  2. ALL： 指的是来源，这个范围指的当然是全部的所有来源啰，因为是 ALL 嘛！

  3. spawn (echo "security notice from host $(/bin/hostname)" ; echo ; /usr/sbin/safe_finger @%h ) | /bin/mail -s "%d-%h security" root &： 由于要将一些侦测的资料送给 root 的邮件信箱，因此需要使用资料流汇整的括号( )，括号内的重点在于 safe_finger 的项目，他会侦测到用户端主机的相关资讯，然后使用管线命令将这些资料送给 mail 处理， mail 会将该资讯以标头为 security 的字样寄给 root 啦！由于 spawn 只是中间的过程，所以还能够有后续的动作哩！

  4. twist ( /bin/echo -e "\n\nWARNING connection not allowed.\n\n" )： 这个动作会将 Warning 的字样传送到用户端主机的荧幕上！ 然后将该连线中断。

在上面的例子中，第三行的 root 那个帐号，可以写成你的个人帐号或者其他 e-mail ，这样就能够寄到你常用的 email 啰， 这样也比较好管理啰。如此一来，当未经允许的电脑尝试登入你的主机时，对方的荧幕上就会显示上面的最后一行，并且将他的 IP 寄到 root ( 或者是你自己的信箱 )那里去！

大标题的图示 系统开启的服务

好了，现在假设你已经知道了 daemons 的启动档案放置的目录，也知道了服务与 port 的对应，那么要如何查询目前系统上面已经启动了的服务呢？不要再打混了！已经学过了 ps 与 top 应该要会应用才对耶！没错，可以使用 ps 与 top 来找寻已经启动了的服务的程序与他的 PID 呢！不过，我们怎么知道该服务启动的 port 是哪一个？呵呵！好问题！可以直接使用 netstat 这个网路状态观察指令来检查我们的 port 呢！甚至他也可以帮我们找到该 port 的程序呢 (PID)！这个指令的相关用途，我们在 第十七章程序管理已经谈过了，不清楚的话请回去查一查先～这里仅介绍如何使用喔～

小标题的图示 观察系统启动的服务

观察系统已启动的服务方式很多，不过，我们最常使用 netstat 来观察。基本上，以 ps 来观察整个系统上面的服务是比较妥当的，因为他可以将全部的 process 都找出来。不过，我们比较关心的还是在于有启动网路监听的服务啊， 所以鸟哥会比较喜欢使用 netstat 来查阅啦。

范例一：找出目前系统开启的‘网路服务’有哪些？
[root@www ~]# netstat -tulp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address       Foreign Address State  PID/Program name
tcp        0      0 www.vbird.tsai:2208 *:*             LISTEN 4575/hpiod
tcp        0      0 *:737               *:*             LISTEN 4371/rpc.statd
tcp        0      0 *:sunrpc            *:*             LISTEN 4336/portmap
tcp        0      0 www.vbird.tsai:ipp  *:*             LISTEN 4606/cupsd
tcp        0      0 www.vbird.tsai:smtp *:*             LISTEN 4638/sendmail: acce
tcp        0      0 *:ssh               *:*             LISTEN 4595/sshd
udp        0      0 *:filenet-tms       *:*                    4755/avahi-daemon:
....(底下省略)....
# 看一下上头， Local Address 的地方会出现主机名称与服务名称的，要记得的是，
# 可以加上 -n 来显示 port number ，而服务名称与 port 对应则在 /etc/services

范例二：找出所有的有监听网路的服务 (包含 socket 状态)：
[root@www ~]# netstat -lnp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address  Foreign Address  State   PID/Program name
tcp        0      0 127.0.0.1:2208 0.0.0.0:*        LISTEN  4575/hpiod
....(中间省略)....
Active UNIX domain sockets (only servers)
Proto RefCnt Flags   Type   State     I-Node PID/Program name Path
....(中间省略)....
unix  2      [ ACC ] STREAM LISTENING 10624  4701/xfs         /tmp/.font-unix/fs7100
unix  2      [ ACC ] STREAM LISTENING 12824  5015/Xorg        /tmp/.X11-unix/X0
unix  2      [ ACC ] STREAM LISTENING 12770  4932/gdm-binary  /tmp/.gdm_socket
....(以下省略)....
# 仔细的瞧一瞧啊，除了原有的网路监听 port 之外，还会有 socket 显示在上面，
# 我们可以清楚的知道有哪些服务被启动呢！

范例三：观察所有的服务状态
[root@www ~]# service --status-all
# 这个指令有趣喔！本章之前有谈过这指令，自行查询啰！

利用 netstat 可以取得很多跟网路有关的服务资讯，透过这个指令，我们可以轻易的了解到网路的状态， 并且可以透过 PID 与 kill 的相关功能，将有问题的资料给他剔除说～ 当然啦，要更详细的取得 PPID 的话，才能够完全的抵挡有问题的程序啦！

另外，除了已经存在系统当中的 daemon 之外，如何在一开机就完整的启动我们所需要的服务呢？ 底下我们就来谈一谈 chkconfig 及 ntsysv 这两个好用的东西！

小标题的图示 设定开机后立即启动服务的方法

就如同上面提到的，我们使用 netstat 仅能观察到目前已经启动的 daemon ，使用 service 这个指令或者是‘ /etc/init.d/* start ’的方法则仅能在目前的环境下立即启动某个服务而已。 那么重新开机后呢？该服务是否还是继续的自动启动？这个时候我们就得要了解一下，到底我的 Linux 主机是怎么开机的呢？

  1. 打开电脑电源，开始读取 BIOS 并进行主机的自我测试；
  2. 透过 BIOS 取得第一个可开机装置，读取主要开机区 (MBR) 取得开机管理程式；
  3. 透过开机管理程式的设定，取得 kernel 并载入记忆体且侦测系统硬体；
  4. 核心主动呼叫 init 程式；
  5. init 程式开始执行系统初始化 (/etc/rc.d/rc.sysinit)
  6. 依据 init 的设定进行 daemon start (/etc/rc.d/rc[0-6].d/*)
  7. 载入本机设定 (/etc/rc.d/rc.local)

关于更多开机流程的详细说明，我们会在第二十章时再来跟大家说明。 由上面的流程你可以看到系统服务在开机时就可以被启动的地方是在第六个步骤，而事实上第六个步骤就是以不同的执行等级呼叫不同的服务啦！ 那么什么叫做执行等级呢？

我们在启动 Linux 系统时，可以进入不同的模式喔，这模式我们称为执行等级 (run level)。不同的执行等级有不同的功能与服务， 目前你先知道正常的执行等级有两个，一个是具有 X 视窗介面的 run level 5 ，另一个则是纯文字介面的 run level 3。 由于预设我们是以图形介面登入系统的，因此可以想像得到的是，我们应该是在 run level 5 的环境中啦！ 那你怎么知道 run level 5 有哪些服务预设可以启动呢？这就得要使用特殊的指令来查询啊！

  • chkconfig： 管理系统服务预设开机启动与否
[root@www ~]# chkconfig --list [服务名称]
[root@www ~]# chkconfig [--level [0123456]] [服务名称] [on|off]
选项与参数：
--list ：仅将目前的各项服务状态列出来
--level：设定某个服务在该 level 下启动 (on) 或关闭 (off)

范例一：列出目前系统上面所有被 chkconfig 管理的服务
[root@www ~]# chkconfig --list |more
NetworkManager  0:off   1:off   2:off   3:off   4:off   5:off   6:off
acpid           0:off   1:off   2:off   3:on    4:on    5:on    6:off
....(中间省略)....
yum-updatesd    0:off   1:off   2:on    3:on    4:on    5:on    6:off

xinetd based services:  <==底下为 super daemon 所管理的服务
        chargen-dgram:  off
        chargen-stream: off
....(底下省略)....
# 你可以发现上面的表格有分为两个区块，一个具有 1, 2, 3 等数字，一个则被 xinetd
# 管理。没错！从这里我们就能够发现服务有 stand alone 与 super daemon 之分。

范例二：显示出目前在 run level 3 为启动的服务
[root@www ~]# chkconfig --list | grep '3:on'

范例三：让 atd 这个服务在 run level 为 3, 4, 5 时启动：
[root@www ~]# chkconfig --level 345 atd on

瞧！ chkconfig 是否很容易管理我们所需要的服务呢？真的很方便啦～ 你可以轻松的透过 chkconfig 来管理 super daemon 的服务喔！另外，你得要知道的是， chkconfig 仅是设定开机时预设会启动的服务而已， 所以该服务目前的状态如何是不知道的。我们举个底下的例子来说明好了：

范例四：先观察 httpd ，再观察预设有无启动，之后以 chkconfig 设定为预设启动
[root@www ~]# /etc/init.d/httpd status
httpd 已停止  <==根本就没有启动

[root@www ~]# chkconfig --list httpd
httpd           0:off   1:off   2:off   3:off   4:off   5:off   6:off
# 原因是预设并没有启动啊！

[root@www ~]# chkconfig httpd on; chkconfig --list httpd
httpd           0:off   1:off   2:on    3:on    4:on    5:on    6:off
# 已经设定为‘开机预设启动’了，再来观察看看到底该服务启动没？

[root@www ~]# /etc/init.d/httpd status
httpd 已停止
# 哈！竟然还是没有启动喔！怎么会这样啊？

上面的范例四并没有启动 httpd 的原因很简单，因为我们并没有使用 /etc/init.d/httpd start 嘛！我们仅是设定开机时启动而已啊！那我们又没有重新开机，所以当然使用 chkconfig 并不会导致该服务立即被启动！也不会让该服务立即被关闭，而是只有在开机时才会被载入或取消载入而已喔。而既然 chkconfig 可以设定开机是否启动，那么我们能不能用来管理 super daemon 的启动与关闭呢？非常好！我们就来试看看底下的案例：

范例五：查阅 rsync 是否启动，若要将其关闭该如何处理？
[root@www ~]# /etc/init.d/rsync status
-bash: /etc/init.d/rsync: No such file or directory
# rsync 是 super daemon 管理的，所以当然不可以使用 stand alone 的启动方式来观察

[root@www ~]# netstat -tlup | grep rsync
tcp  0 0 192.168.201.110:rsync  *:*     LISTEN     4618/xinetd
tcp  0 0 www.vbird.tsai:rsync   *:*     LISTEN     4618/xinetd

[root@www ~]# chkconfig --list rsync
rsync           on   <==预设启动呢！将它处理成预设不启动吧

[root@www ~]# chkconfig rsync off; chkconfig --list rsync
rsync           off  <==看吧！关闭了喔！现在来处理一下 super daemon 的东东！

[root@www ~]# /etc/init.d/xinetd restart; netstat -tlup | grep rsync

最后一个指令你会发现原本 rsync 不见了！这样是否很轻易的就能够启动与关闭你的 super daemon 管理的服务呢！

  • ntsysv： 类图形介面管理模式

基本上， chkconfig 真的已经很好用了，不过，我们的 CentOS 还有提供一个更不错用的， 那就是 ntsysv 了！注意喔， chkconfig 很多的 distributions 都存在，但是 ntsysv 则是 Red Hat 系统特有的！

[root@www ~]# ntsysv [--level <levels>]
选项与参数：
--level ：后面可以接不同的 run level ，例如 ntsysv --level 35

一般我们都是直接输入 ntsysv 即可进入管理画面了，整个画面如下图所示：

ntsysv 的执行示意图
图 4.2.1、 ntsysv 的执行示意图

上图中的中间部分是每个服务预设开机是否会启动的设定值，若中括号内出现星号 (*) 代表预设开机会启动，否则就是不会在开机时启动啦。 你可以使用上下键来移动中括号内的游标到你想要变更的那个服务上头，然后按下空白键就能够选取或取消啰。如果一切都选择完毕后， 你可以使用 [tab] 按键来移动游标到 [OK] [Cancel] 等按钮上面，当然啦，按下 [Ok] 就是确认你的选取会生效啰。 总结一下上述的按钮功能：

  • 上下键： 可以在中间的方框当中，在各个服务之间移动；
  • 空白键： 可以用来选择你所需要的服务，前面的 [*] 会有 * 出现；
  • tab 键： 可以在方框、OK、Cancel 之间移动；
  • [F1]键： 可以显示该服务的说明
ntsysv 的执行示意图
图 4.2.2、 ntsysv 的执行示意图

上图是鸟哥将游标游动到 atd 这个服务上头后，再按下 [F1] 所出现的结果，所以啰，你可以透过 ntsysv 去观察预设开机启动的服务， 还能够查阅该服务的基本功能为何，这样就能够稍微厘清一下该服务是否需要存在啰！这样理解了吧！

  • chkconfig： 设定自己的系统服务
[root@www ~]# chkconfig [--add|--del] [服务名称]
选项与参数：
--add ：增加一个服务名称给 chkconfig 来管理，该服务名称必须在 /etc/init.d/ 内
--del ：删除一个给 chkconfig 管理的服务

现在你知道 chkconfig 与 ntsysv 是真好用的东西，那么如果我自己写了一个程式并且想要让该程式成为系统服务好让 chkconfig 来管理时， 可以怎么进行呢？只要将该服务加入 init 可以管理的 script 当中，亦即是 /etc/init.d/ 当中即可。 举个例子，我们在 /etc/init.d/ 里面建立一个 myvbird 档案，该档案仅是一个简单的服务范例，基本上，没有任何用途.... 对于该档案的必须性是这样的：

  • myvbird 将在 run level 3 及 5 启动；
  • myvbird 在 /etc/rc.d/rc[35].d 当中启动时，以 80 顺位启动，以 70 顺位结束。

关于所谓的顺位问题，我们会在第二十章介绍，这里你先看看即可。 你该如何进行呢？可以这样做：

[root@www ~]# vim /etc/init.d/myvbird
#!/bin/bash
# chkconfig: 35 80 70
# description: 没啥！只是用来作为练习之用的一个范例
echo "Nothing"

这个档案很好玩喔！你可以参考你自己系统上面的档案；基本上，比较重要的是第二行，他的语法是： ‘ chkconfig: [runlevels] [启动顺位] [停止顺位] ’其中， runlevels 为不同的 run level 状态，启动顺位 (start number) 与 结束顺位 (stop number) 则是在 /etc/rc.d/rc[35].d 内建立以 S80myvbird 及 K70myvbird 为档名的设定方式！

[root@www ~]# chkconfig --list myvbird
service myvbird supports chkconfig, but is not referenced in any
runlevel (run 'chkconfig --add myvbird')
# 尚未加入 chkconfig 的管理机制中！所以需要再动点手脚

[root@www ~]# chkconfig --add myvbird; chkconfig --list myvbird
myvbird         0:off   1:off   2:off   3:on    4:off   5:on    6:off
# 看吧！加入了 chkconfig 的管理当中了！
# 很有趣吧！如果要将这些资料都删除的话，那么就下达这样的情况：

[root@www ~]# chkconfig --del myvbird
[root@www ~]# rm /etc/init.d/myvbird

chkconfig 真的是个不错用的工具吧！尤其是当你想要自己建立自己的服务时！ ^_^

小标题的图示 CentOS 5.x 预设启动的服务简易说明

随着 Linux 上面软体支援性越来越多，加上自由软体蓬勃的发展，我们可以在 Linux 上面用的 daemons 真的越来越多了。所以，想要写完所有的 daemons 介绍几乎是不可能的，因此，鸟哥这里仅介绍几个很常见的 daemons 而已， 更多的资讯呢，就得要麻烦你自己使用 ntsysv 或者是 vi /etc/init.d/* 里面的档案去瞧一瞧啰～ ^_^！ 底下的建议主要是针对 Linux 单机伺服器的角色来说明的，不是桌上型的环境喔！

CentOS 5.x 预设启动的服务内容
服务名称 | 功能简介
acpid | (系统)进阶电源管理的介面，这是一个新的电源管理模组， 可以监听来自核心层的电源相关事件而予以回应。 CentOS 的设定档在 /etc/acpi/events/power.conf 中，预设仅有当你按下 power 按钮时，系统会自动关机喔！(注1)
anacron (可关闭) | (系统)与循环型的工作排程 cron 有关，可在排程过期后还可以唤醒来继续执行， 设定档在 /etc/anacrontab。详情请参考第十六章的说明。
apmd (可关闭) | (系统)设定档在 /etc/sysconfig/apmd ，也是电源管理模组啦！ 可侦测电池电量，当电池电力不足时，可以自动关机以保护电脑主机。
atd | (系统)单一的例行性工作排程，详细说明请参考第十六章。 抵挡机制的设定档在 /etc/at.{allow,deny} 喔！
auditd | (系统)还记得前一章的 SELinux 所需服务吧？ 这就是其中一项，可以让系统需 SELinux 稽核的讯息写入 /var/log/audit/audit.log 中。若此服务没有启动，则讯息会传给 syslog 管理。
autofs (可关闭) | (系统)可用来自动挂载来自网路上的其他伺服器所提供的网路磁碟机 (一般是 NFS)。 不过我们是单机系统，所以目前还没必要这个服务。
avahi-daemon (可关闭) | (系统)也是一个用户端的服务，可以透过 Zeroconf 自动的分析与管理网路。 Zeroconf 较常用在笔记型电脑与行动装置上，所以我们可以先关闭他啦！(注2)
bluetooth (可关闭) | (系统)用在蓝芽装置的搜寻上，如果 Linux 是当作伺服器使用时， 这个服务可以暂时关闭也没关系！
cpuspeed | (系统)可以用来管理 CPU 的频率功能。若系统闲置时，此项功能可以自动的降低 CPU 频率来节省电量与降低 CPU 温度喔！
crond | (系统)系统设定档为 /etc/crontab，详细资料可参考第十六章的说明。
cups (可关闭) | (网路)用来管理印表机的服务，可以提供网路连线的功能，有点类似列印伺服器的功能哩！ 你可以在 Linux 本机上面以浏览器的 http://localhost:631 来管理印表机喔！由于我们目前没有印表机，所以可以暂时关闭他。
firstboot (可关闭) | (系统)还记得系统第一次进入图形介面还需要进行一些额外的设定吗？ 就是这个服务的帮忙啦！既然已经安装妥当，现在你可以将这个服务关闭啰。
gpm | (系统)在 tty1~tty6 的环境下你竟然可以使用滑鼠功能来复制贴上，就是这个 gpm 提供的能力啦！
haldaemon (可关闭) | (系统)通常用在桌上型电脑的环境中，可侦测类似 usb 的装置呢！ 不过，如果是伺服器环境，这个服务倒是可以关闭啦！如果是桌上型电脑，那最好可以启动啰！(注3)
hidd (可关闭) | (系统)也是蓝芽服务的功能啦！可以提供键盘、滑鼠等蓝芽装置的侦测哩！ 须搭配 bluetooth。伺服器环境倒是不需要此项服务。
hplip (可关闭) | (系统)主要是针对 HP 的印表机功能所开发的脚本服务，如果你的环境中并没有 HP 相关设备，这个服务就给他关闭吧！
ip6tables (可关闭) | (网路)是针对本机的防火墙功能！这个防火墙主要是针对 IPv6 的版本， 如果你的网路环境并没有 IPv6 的设备，那么这个服务是可以关闭的。
iptables | (网路)本机防火墙功能，是核心支援的呢！所以功能与效能都非常棒！当然不能够取消啊！ 只是设定上就得要努力研究啦！我们会在伺服器篇介绍网路相关资讯的。
irqbalance | (系统)如果你的系统是多核心的硬体，那么这个服务要启动， 因为它可以自动的分配系统中断 (IRQ) 之类的硬体资源。
isdn (可关闭) | (网路)ISDN 是一种宽频设备 (数据机的一种) ，但是在台湾我们比较常使用 ADSL 及光纤设备， 所以这个服务是可以关闭啦。
kudzu (可关闭) | (系统)如果你有增加新的硬体时，这个服务可以在开机时自动的侦测硬体， 并且会自动的呼叫相关的设定软体，方便你在开机时就处理好你的硬体啊！
lm_sensors (可关闭) | (系统)这个服务可以帮你侦测主机板的相关侦测晶片，举例来说， 某些主机板会主动的侦测 CPU 温度、频率、电压等，这个 lm_sensors 能够将这些温度、频率等数据显示出来喔！ 我们会在第二十一章谈这玩意儿。
lvm2-monitor | (系统)我们已经谈过 LVM 啰！所以我们当然要启动这个服务比较妥当。
mcstrans | (系统)与 SELinux 有关的服务，最好也启动啊！
mdmonitor (可关闭) | (系统)可以侦测所有软体的状态，暂时似乎也不需要启动这个服务哩！
messagebus (可关闭) | (系统)可用来沟通各个软体之间的讯息，有点类似剪贴簿的感觉。 不过在伺服器环境则没有强烈需求就是了。
microcode_ctl (可关闭) | (系统)Intel 的 CPU 会提供一个外挂的微指令集提供系统运作， 不过，如果你没有下载 Intel 相关的指令集档案，那么这个服务不需要启动的，也不会影响系统运作。(注4)
netfs (可关闭) | (网路)可以进行网路磁碟机 (NFS, SMB/CIFS) 的挂载与卸载功能。 目前我们尚未使用网路，因此这个服务可以先关闭。
network | (网路)提供网路设定的功能，所以一定要启动的啦！
nfslock (可关闭) | (网路)NFS 为一种 Unix like 的网路磁碟机，但在进行档案的分享时， 为了担心同一档案多重编辑的问题，所以会有这个锁住 (lock) 的服务！可以避免同一个档案被两个不同的人编辑时所造成的档案错误问题。
pcscd (可关闭) | (系统)智慧卡侦测的服务，可以关闭他啦。
portmap | (网路)用在远端程序呼叫的服务，很多服务都使用这个玩意儿来辅助连线的， 因此建议不要取消他，除非你确定你的系统没有使用到任何的 RPC 服务喔！
readahead_early readahead_later (可关闭) | (系统)在系统开机的时候可以先将某些程式载入到记忆体中，以方便快速的载入， 可加快一些启动的速度。
restorecond | (系统)利用 /etc/selinux/restorecond.conf 的设定来判断当新建档案时，该档案的 SELinux 类型应该如何还原。需要注意的是，如果你的系统有很多非正规的 SELinux 档案类型设定时，这个 daemon 最好关闭，否则他会将你设定的 type 修改回预设值。
rpcgssd rpcidmapd (可关闭) | (网路)与 NFS 有关的用户端功能，在你还没有玩到网路阶段时， 这两个咚咚也能够先取消啦！
sendmail | (网路)这就是电子邮件的软体啊！我们想要拥有可寄信的功能时， 这个服务可不能关闭。不过，预设这个服务仅能支援本机的功能，无法收受来自网际网路的邮件喔！
setroubleshoot | (系统)一定要启动啊！因为这玩意儿可以将你的 SELinux 相关讯息记录在 /var/log/messages 里面，非常有帮助喔！
smartd | (系统)这个服务可以自动的侦测硬碟状态，如果硬碟发生问题的话， 还能够自动的回报给系统管理员，是个非常有帮助的服务喔！不可关闭他啊！
sshd | (网路)这个是远端连线伺服器的软体功能， 这个通讯协定比 telnet 好的地方在于 sshd 在传送资料时可以进行加密喔！这个服务不要关闭他啦！
syslog | (系统)这个服务可以记录系统所产生的各项讯息， 包括 /var/log/messages 内的几个重要的登录档啊。
xfs (可关闭) | (系统)这个是 X Font Server，主要提供图形介面的字型的一个服务， 如果你不启动 X 视窗的话，那么这个服务可以启动。但是如果你有需要用到 X 时，一定要启动这玩意儿，否则图形介面是无法启动的喔。
xinetd | (系统)就是 super daemon 啊，不必讲了吧 ^_^
yum-updatesd | (系统)可以透过 yum 的功能进行软体的线上升级机制， 若有升级的软体释出时，就能够以邮件或者是 syslog 来通知系统管理原来手动升级啊。

上面的服务是 CentOS 5.x 预设有启动的，这些预设启动的服务很多是针对桌上型电脑所设计的，所以啰，如果你的 Linux 主机用途是在伺服器上面的话，那么有很多服务是可以关闭的啦！如果你还有某些不明白的服务想要关闭的， 请务必要搞清楚该服务的功能为何喔！举例来说，那个 syslog 就不能关闭，如果你关掉他的话，系统就不会记录登录档， 那你的系统所产生的警告讯息就无法记录起来，你将无法进行 debug 喔。

底下鸟哥继续说明一些可能在你的系统当中的服务，只是预设并没有启动这个服务就是了。只是说明一下， 各服务的用途还是需要您自行查询相关的文章啰。

其他服务的简易说明
服务名称 | 功能简介
dovecot | (网路)可以设定 POP3/IMAP 等收受信件的服务，如果你的 Linux 主机是 email server 才需要这个服务，否则不需要启动他啦！
httpd | (网路)这个服务可以让你的 Linux 伺服器成为 www server 喔！
named | (网路)这是领域名称伺服器 (Domain Name System) 的服务， 这个服务非常重要，但是设定非常困难！目前应该不需要这个服务啦！
nfs | (网路)这就是 Network Filesystem，是 Unix-Like 之间互相作为网路磁碟机的一个功能。
ntpd | (网路)服务的全名是 Network Time Protocol ，这个服务可以用来进行网路校时， 让你系统的时间永远都是正确的哩！
smb | (网路)这个服务可以让 Linux 模拟成为 Windows 上面的网路上的芳邻。 如果你的 Linux 主机想要做为 Windows 用户端的网路磁碟机伺服器，这玩意儿得要好好玩一玩。
squid | (网路)作为代理伺服器的一个服务，可作为一个区域网路的防火墙之用。
vsftpd | (网路)作为档案传输伺服器 (FTP) 的服务。
大标题的图示 重点回顾
  • 服务 (daemon) 主要可以分为 stand alone (服务可单独启动) 及 super daemon (透过 xinetd 统一管理的服务) 两种。
  • super daemon 由于是经过一个统一的 xinetd 来管理，因此可以具有类似防火墙管理功能。此外，管理的连线机制又可以分为 multi-threaded 及 single-threaded。
  • 启动 daemon 的程式通常最末会加上一个 d ，例如 sshd, vsftpd, httpd 等
  • stand alone daemon 启动的脚本放置到 /etc/init.d/ 这个目录中，super daemon 的设定档在 /etc/xinetd.d/* 内， 而启动的方式则为 /etc/init.d/xientd restart
  • 立即启动 stand alone daemon 的方法亦可以使用 service 这个指令
  • Super daemon 的设定档 /etc/xinetd.conf ，个别 daemon 设定档则在 /etc/xinetd.d/* 内。在设定档内还可以设定连线用户端的连线与否， 具有类似防火墙的功能喔。
  • 若想要统一管理防火墙的功能，可以透过 /etc/hosts.{allow,deny} ，若有安装 TCP Wrappers 时，还能够使用额外的 spawn 功能等
  • 若想要设定开机时启动某个服务时，可以透过 chkconfig, ntsysv 等指令。
  • 一些不需要的服务可以关闭喔！
大标题的图示 本章习题
( 要看答案请将滑鼠移动到‘答：’底下的空白处，按下左键圈选空白处即可察看 )
  • 情境模拟题一：透过安装、设定、启动、观察与管理防火墙等机制，完整的了解一个服务的启动与观察现象。

    • 目标：了解 daemon 的控管机制，以 super daemon 为例；
    • 前提：需要对本章已经了解，尤其是 super daemno 部分；
    • 需求：最好已经连上 Internet ，因为会动用到安装软体

    在本情境中，我们使用 telnet 这个服务来观察，假设最终我们只开放 .edu.tw 的网域来使用本机的 telnet 服务喔！ 可以这样做看看：

    1. 先看看 telnet 伺服器有没有安装。 telnet 伺服器在 CentOS 上面指的是 telnet-server 这支程式，所以可以这样看看：
      [root@www ~]# rpm -q telnet-server
package telnet-server is not installed

[root@www ~]# yum install telnet-server
==============================================================
 Package          Arch    Version         Repository    Size
==============================================================
Installing:
 telnet-server    i386    1:0.17-39.el5   base          35 k

Transaction Summary
==============================================================
Install      1 Package(s)
Update       0 Package(s)
Remove       0 Package(s)

Total download size: 35 k
Is this ok [y/N]: y
Downloading Packages:
telnet-server-0.17-39.el5.i386.rpm          |  35 kB     00:00
warning: rpmts_HdrFromFdno: Header V3 DSA signature: NOKEY, key ID e8562897
Importing GPG key 0xE8562897 "CentOS-5 Key (CentOS 5 Official Signing Key)
<centos-5-key@centos.org>" from /etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-5
Is this ok [y/N]: y
Running rpm_check_debug
Running Transaction Test
Finished Transaction Test
Transaction Test Succeeded
Running Transaction
  Installing     : telnet-server           [1/1]

Installed: telnet-server.i386 1:0.17-39.el5
Complete!

    2. 如果已经安装了，那么直接来察看一下设定档，看看 telnet 是 stand alone 还是 super daemon 呢？最简单的方法就是 chkconfig 了！
      [root@www ~]# chkconfig --list telnet
telnet          off  <==只有 on 或 off 者为 super daemon

[root@www ~]# ll /etc/xinetd.d/telnet
-rw-r--r-- 1 root root 305 Dec  1  2007 /etc/xinetd.d/telnet
# 看吧！果然是 super daemon 哩！

[root@www ~]# grep '^telnet' /etc/services
telnet          23/tcp
telnet          23/udp
      由上面可以看到， telnet 是 super daemon ，而起启动的埠口在 port 23 这个地方。

    3. 如果要启动的话，可以这样来处置喔：
      [root@www ~]# chkconfig telnet on; chkconfig --list telnet
telnet          on
[root@www ~]# /etc/init.d/xinetd restart
正在停止 xinetd:                       [  确定  ]
正在启动 xinetd:                       [  确定  ]

[root@www ~]# netstat -tlnp | grep xinetd
tcp  0  0 0.0.0.0:23   0.0.0.0:*     LISTEN      2487/xinetd
# 确认一下，确实有启动 port 23 喔！ ^_^

    4. 现在假设我们仅要针对 .edu.tw 来开放，至于其他的来源则予以关闭。我们这里选择 /etc/hosts.{allow,deny} 来处理，你必须要这样做：
      # 1. 先找到 telnet 的主程式是哪一支？
[root@www ~]# grep server /etc/xinetd.d/telnet
        server          = /usr/sbin/in.telnetd

# 2. 开始指定开放的网域：
[root@www ~]# vim /etc/hosts.allow
in.telnetd : .edu.tw

[root@www ~]# vim /etc/hosts.deny
in.telnetd: ALL
      简单！搞定！ ^_^
简答题部分：
  • 使用 netstat -tul 与 netstat -tunl 有什么差异？为何会这样？
    使用 n 时， netstat 就不会使用主机名称与服务名称 (hostname & service_name) 来显示， 取而代之的则是以 IP 及 port number 来显示的。IP 的分析与 /etc/hosts 及 /etc/resolv.conf 有关， 这个在未来伺服器篇才会提到。至于 port number 则与 /etc/services 有关，请自行参考喔！ ^_^
  • 你能否找出来，启动 port 3306 这个埠口的服务为何？
    透过搜寻 /etc/services 内容，得到 port 3306 为 mysql 所启动的埠口喔！查询 google， 可得到 mysql 为一种网路资料库系统软体。
  • 你可以透过哪些指令查询到目前系统预设开机会启动的服务？
    本章提到的 chkconfig 以及 ntsysv 都可以查阅的到！
  • 承上，那么哪些服务‘目前’是在启动的状态？
    可以透过 services --status-all，或者是透过 netstat -anl 等方式。也可以透过 pstree 去查询喔！ 只是相关对应的服务 daemon 档名就得要个别查询了。
  • tcp wrappers 软体功能与 xinetd 的功能中，可以使用哪两个档案进行网路防火墙的控管？
    /etc/hosts.{allow,deny}
大标题的图示 参考资料与延伸阅读
  • 注1：进阶电源管理介面设定 (Advanced Configuration and Power Interface, ACPI) 官网 http://acpid.sourceforge.net/
  • 注2：Zeroconf 自动网路管理机制 http://www.zeroconf.org/
  • 注3：桌上型电脑的自动硬体侦测服务 http://www.freedesktop.org/wiki/Software/hal
  • 注4：CPU 微指令集载入服务的说明 http://www.urbanmyth.org/microcode/
2002/07/10：第一次完成
2003/02/11：重新编排与加入 FAQ
2005/10/03：将原本旧版的资料移动到 此处 。
2005/10/12：经过一段时间的修订，将原本在 系统设定工具 的内容移动到此，并新增完毕！
2009/03/25：将原本旧的基于 FC4 的资料移动到此处。
2009/04/02：加入一些预设启动的服务说明。
2009/09/14：加入情境模拟，并且修订课后练习题的部分了。


鸟哥的 Linux 私房菜 -- 登录档的分析啦！

为取得较佳浏览结果，请爱用 firefox 浏览本网页
鸟哥的 Linux 私房菜馆 | Linux 基础文件 | Linux 架站文件 | Linux 企业运用 | 安全管理 | 新手讨论 |

第十九章、认识与分析登录档
最近更新日期：2009/09/14
当你的 Linux 系统出现不明原因的问题时，很多人都告诉你，你要查阅一下登录档才能够知道系统出了什么问题了，所以说， 了解登录档是很重要的事情呢。登录档可以记录系统在什么时间、哪个主机、哪个服务、出现了什么讯息等资讯， 这些资讯也包括使用者识别资料、系统故障排除须知等资讯。如果你能够善用这些登录档资讯的话，你的系统出现错误时， 你将可以在第一时间发现，而且也能够从中找到解决的方案，而不是昏头转向的乱问人呢。 此外，登录档所记录的资讯量是非常大的，要人眼分析实在很困难。此时利用 shell script 或者是其他软体提供的分析工具来处理复杂的登录档，可以帮助你很多很多喔！

1. 什么是登录档： 登录档的重要性, 常见档名, 服务与程式
2. syslogd ：记录登录档的服务
    2.1 登录档内容的一般格式
    2.2 syslog 的设定档： /etc/syslog.conf, 预设的 syslog.conf 内容
    2.3 登录档的安全性设置
    2.4 登录档伺服器的设定
 3. 登录档的轮替 (logrotate)
    3.1 logrotate 的设定档
    3.2 实际测试 logrotate 的动作
    3.3 自订登录档的轮替功能
 4. 分析登录档
    4.1 CentOS 预设提供的 logwatch
    4.2 鸟哥自己写的登录档分析工具：
 5. 本章习题练习
6. 针对本文的建议：http://phorum.vbird.org/viewtopic.php?t=23895
大标题的图示 什么是登录档

‘详细而确实的分析以及备份系统的登录档’是一个系统管理员应该要进行的任务之一。 那么什么是登录档呢？简单的说，就是记录系统活动资讯的几个档案， 例如：何时、何地 (来源 IP)、何人 (什么服务名称)、做了什么动作 (讯息登录啰)。 换句话说就是：记录系统在什么时候由哪个程序做了什么样的行为时，发生了何种的事件等等。

要知道的是，我们的 Linux 主机在背景之下有相当多的 daemons 同时在工作着，这些工作中的程序总是会显示一些讯息， 这些显示的讯息最终会被记载到登录档当中啦。也就是说，记录这些系统的重要讯息就是登录档的工作啦！

登录档的重要性

为什么说登录档很重要，重要到系统管理员需要随时注意他呢？我们可以这么说：

  • 解决系统方面的错误：

    用 Linux 这么久了，你应该偶而会发现系统可能会出现一些错误，包括硬体捉不到或者是某些系统程式无法顺利运作的情况。 此时你该如何是好？由于系统会将硬体侦测过程记录在登录档内，你只要透过查询登录档就能够了解系统作了啥事！ 并且由第十七章我们也知道 SELinux 与登录档的关系更加的强烈！所以啰，查询登录档可以克服一些系统问题啦！

  • 解决网路服务的问题：

    你可能在做完了某些网路服务的设定后，却一直无法顺利启动该服务，此时该怎办？去庙里面拜拜抽签吗？ 三太子大大可能无法告诉你要怎么处理呢！由于网路服务的各种问题通常都会被写入特别的登录档， 其实你只要查询登录档就会知道出了什么差错，还不需要请示三太子大大啦！举例来说，如果你无法启动邮件伺服器 (sendmail)， 那么查询一下 /var/log/maillog 通常可以得到不错的解答！

  • 过往事件记录簿：

    这个东西相当的重要！例如：你发现 WWW 服务 (apache 软体) 在某个时刻流量特别大，你想要了解为什么时， 可以透过登录档去找出该时段是哪些 IP 在连线与查询的网页资料为何，就能够知道原因。 此外，万一哪天你的系统被入侵，并且被利用来攻击他人的主机，由于被攻击主机会记录攻击者，因此你的 IP 就会被对方记录。这个时候你要如何告知对方你的主机是由于被入侵所导致的问题， 并且协助对方继续往恶意来源追查呢？呵呵！此时登录档可是相当重要的呢！
Tips:
所以我们常说‘天助自助者’是真的啦！你可以透过 (1)察看荧幕上面的错误讯息与 (2)登录档的错误资讯，几乎可以解决大部分的 Linux 问题！ 		鸟哥的图示
Linux 常见的登录档档名

登录档可以帮助我们了解很多系统重要的事件，包括登入者的部分资讯，因此登录档的权限通常是设定为仅有 root 能够读取而已。 而由于登录档可以记载系统这么多的详细资讯，所以啦，一个有经验的主机管理员会随时随地查阅一下自己的登录档， 以随时掌握系统的最新脉动！那么常见的几个登录档有哪些呢？一般而言，有下面几个：

  • /var/log/cron：
    还记得第十六章例行性工作排程吧？你的 crontab 排程有没有实际被进行？ 进行过程有没有发生错误？你的 /etc/crontab 是否撰写正确？在这个登录档内查询看看。

  • /var/log/dmesg：
    记录系统在开机的时候核心侦测过程所产生的各项资讯。由于 CentOS 预设将开机时核心的硬体侦测过程取消显示， 因此额外将资料记录一份在这个档案中；

  • /var/log/lastlog：
    可以记录系统上面所有的帐号最近一次登入系统时的相关资讯。第十四章讲到的 lastlog 指令就是利用这个档案的记录资讯来显示的。

  • /var/log/maillog 或 /var/log/mail/*：
    记录邮件的往来资讯，其实主要是记录 sendmail (SMTP 协定提供者) 与 dovecot (POP3 协定提供者) 所产生的讯息啦。 SMTP 是发信所使用的通讯协定， POP3 则是收信使用的通讯协定。 sendmail 与 dovecot 则分别是两套达成通讯协定的软体。

  • /var/log/messages：
    这个档案相当的重要，几乎系统发生的错误讯息 (或者是重要的资讯) 都会记录在这个档案中； 如果系统发生莫名的错误时，这个档案是一定要查阅的登录档之一。

  • /var/log/secure：
    基本上，只要牵涉到‘需要输入帐号密码’的软体，那么当登入时 (不管登入正确或错误) 都会被记录在此档案中。 包括系统的 login 程式、图形介面登入所使用的 gdm 程式、 su, sudo 等程式、还有网路连线的 ssh, telnet 等程式， 登入资讯都会被记载在这里；

  • /var/log/wtmp, /var/log/faillog：
    这两个档案可以记录正确登入系统者的帐号资讯 (wtmp) 与错误登入时所使用的帐号资讯 (faillog) ！ 我们在第十一章谈到的 last 就是读取 wtmp 来显示的， 这对于追踪一般帐号者的使用行为很有帮助！

  • /var/log/httpd/*, /var/log/news/*, /var/log/samba/*：
    不同的网路服务会使用它们自己的登录档案来记载它们自己产生的各项讯息！上述的目录内则是个别服务所制订的登录档。

常见的登录档就是这几个，但是不同的 Linux distributions ，通常登录档的档名不会相同 (除了 /var/log/messages 之外 )。所以说，你还是得要查阅你 Linux 主机上面的登录档设定资料， 才能知道你的登录档主要档名喔！

登录档所需相关服务 (daemon) 与程式

那么这些登录档是怎么产生的呢？基本上有两种方式，一种是由软体开发商自行定义写入的登录档与相关格式， 例如 WWW 软体 apache 就是这样处理的。另一种则是由 Linux distribution 提供的登录档管理服务来统一管理。 你只要将讯息丢给这个服务后，他就会自己分门别类的将各种讯息放置到相关的登录档去！CentOS 提供 syslogd 这个服务来统一管理登录档喔！

除了这个 syslogd 之外，我们的核心也需要额外的登录服务来记录核心产生的各项资讯， 这个专门记录核心资讯的登录档服务就是 klogd 啦。所以说，登录档所需的服务主要就是 syslogd 与 klogd 这两者。

不过要注意的是，如果你任凭登录档持续记录的话，由于系统产生的资讯天天都有，那么你的登录档的容量将会长大到无法无天～ 如果你的登录档容量太大时，可能会导致大档案读写效率不佳的问题 (因为要从磁碟读入记忆体，越大的档案消耗记忆体量越多)。 所以啰，你需要对登录档备份与更新。那...需要手动处理喔？当然不需要，我们可以透过 logrotate (登录档轮替) 这玩意儿来自动化处理登录档容量与更新的问题喔！

所谓的 logrotate 基本上，就是将旧的登录档更改名称，然后建立一个空的登录档，如此一来， 新的登录档将重新开始记录，然后只要将旧的登录档留下一阵子，嗯！那就可以达到将登录档‘轮转’的目的啦！ 此外，如果旧的纪录 (大概要保存几个月吧！) 保存了一段时间没有问题，那么就可以让系统自动的将他砍掉， 免得占掉很多宝贵的硬碟空间说！

总结一下，针对登录档所需的功能，我们需要的服务与程式有：

  • syslogd：主要登录系统与网路等服务的讯息；
  • klogd：主要登录核心产生的各项资讯；
  • logrotate：主要在进行登录档的轮替功能。

由于我们着眼点在于想要了解系统上面软体所产生的各项资讯，因此本章主要针对 syslogd 与 logrotate 来介绍。 接着下来我们来谈一谈怎么样规划这两个玩意儿。就由 syslogd 这支程式先谈起吧！毕竟得先有登录档，才可以进行 logrotate 呀！您说是吧！

大标题的图示 syslogd ：记录登录档的服务

刚刚提到说 Linux 的登录档主要是由 syslogd 在负责，那么你的 Linux 是否有启动 syslogd 呢？而且是否有设定开机时启动呢？呵呵！检查一下先：

[root@www ~]# ps aux | grep syslog
USER   PID %CPU %MEM  VSZ  RSS TTY  STAT START  TIME COMMAND
root  4294  0.0  0.0 1716  568 ?    Ss   Mar31  0:00 syslogd -m 0
# 瞧！确实有启动的！

[root@www ~]# chkconfig --list syslog
syslog    0:off  1:off  2:on   3:on   4:on   5:on   6:off
# 预设情况下，文字介面与图形介面 (3, 5) 都有启动喔！

看到 syslog 这个服务名称了吧？所以知道他已经在系统中工作啰！好了，既然本章主要是讲登录档，那么你知道登录档的内容是如何展现的？ syslog 的设定档在哪里？如何设定？如果你的 Linux 主机想要当作整个区网的登录档伺服器时，又该如何设定？ 底下就让我们来玩玩这玩意！

小标题的图示 登录档内容的一般格式

一般来说，系统产生的讯息经过 syslog 而记录下来的资料中，每条讯息均会记录底下的几个重要资料：

  • 事件发生的日期与时间；
  • 发生此事件的主机名称；
  • 启动此事件的服务名称 (如 samba, xinetd 等) 或函式名称 (如 libpam ..)；
  • 该讯息的实际资料内容。

当然，这些资讯的‘详细度’是可以修改的，而且，这些资讯可以作为系统除错之用呢！ 我们拿登录时一定会记载帐号资讯的 /var/log/secure 为例好了：

[root@www ~]# cat /var/log/secure
1 Mar 14 15:38:00 www atd[18701]: pam_unix(atd:session): session opened for
  user root by (uid=0)
2 Mar 14 15:38:00 www atd[18701]: pam_unix(atd:session): session closed for
  user root
3 Mar 16 16:01:51 www su: pam_unix(su-l:auth): authentication failure; logn
  ame=vbird uid=500 euid=0 tty=pts/1 ruser=vbird rhost=  user=root
4 Mar 16 16:01:55 www su: pam_unix(su-l:session): session opened for user
  root by vbird(uid=500)
5 Mar 16 16:02:22 www su: pam_unix(su-l:session): session closed for user root
  |--日期/时间---|-H-|-----服务与相关函数-------|--讯息说明------>

我们拿第一笔资料来说明好了，该资料是说：‘在三月14日 (Mar 14) 的下午 15:38 分，由 www 这部主机的 atd [PID 为 18701] 传来的消息，这个消息是透过 pam_unix 这个模组所提出的。讯息内容为 root (uid=0) 这个帐号已经开启 atd 的活动了。’有够清楚吧！ 那请您自行翻译一下后面的 4 条讯息内容是什么喔！

其实还有很多的资讯值得查阅的呢！尤其是 /var/log/messages 的内容。记得一个好的系统管理员， 要常常去‘巡视’登录档的内容喔！尤其是发生底下几种情况时：

  • 当你觉得系统似乎不太正常时；
  • 某个 daemon 老是无法正常启动时；
  • 某个使用者老是无法登入时；
  • 某个 demon 执行过程老是不顺畅时；

还有很多啦！反正觉得系统不太正常，就得要查询查询登录档就是了。

Tips:
提供一个鸟哥常做的检查方式。当我老是无法成功的启动某个服务时，我会在最后一次启动该服务后，立即检查登录档， 先 (1)找到现在时间所登录的资讯‘第一栏位’； (2)找到我想要查询的那个服务‘第三栏位’， (3)最后再仔细的查阅第四栏位的资讯，来藉以找到错误点。 		鸟哥的图示
小标题的图示 syslog 的设定档：/etc/syslog.conf

什么？登录档还有设定档？喔！不是啦～是 syslogd 这个 daemon 的设定档啦！ 我们现在知道 syslogd 可以负责主机产生的各个资讯的登录，而这些资讯本身是有‘严重等级’之分的， 而且，这些资料最终要传送到哪个档案去是可以修改的呢，所以我们才会在一开头的地方讲说， 每个 Linux distributions 放置的登录档档名可能会有所差异啊！

基本上， syslog 针对各种服务与讯息记录在某些档案的设定档就是 /etc/syslog.conf， 这个档案规定了‘(1)什么服务 (2)的什么等级讯息 (3)需要被记录在哪里(装置或档案)’ 这三个咚咚，所以设定的语法会是这样：

服务名称[.=!]讯息等级		讯息记录的档名或装置或主机
# 底下以 mail 这个服务产生的 info 等级为例：
mail.info			/var/log/maillog_info
# 这一行说明：mail 服务产生的大于等于 info 等级的讯息，都记录到
# /var/log/maillog_info 档案中的意思。

我们将上面的资料简单的分为三部分来说明：

  • 服务名称

syslog 本身有规范一些服务，你可以透过这些服务来储存系统的讯息。syslog 认识的服务主要有底下这些： (可使用 man 3 syslog 查询到相关的资讯)

服务类别 | 说明
auth (authpriv) | 主要与认证有关的机制，例如 login, ssh, su 等需要帐号/密码的咚咚；
cron | 就是例行性工作排程 cron/at 等产生讯息记录的地方；
daemon | 与各个 daemon 有关的讯息；
kern | 就是核心 (kernel) 产生讯息的地方；
lpr | 亦即是列印相关的讯息啊！
mail | 只要与邮件收发有关的讯息纪录都属于这个；
news | 与新闻群组伺服器有关的东西；
syslog | 就是 syslogd 这支程式本身产生的资讯啊！
user, uucp, local0 ~ local7 | 与 Unix like 机器本身有关的一些讯息。

上面谈到的都是 syslog 自行制订的服务名称，软体开发商可以透过呼叫上述的服务名称来记录他们的软体。 举例来说， sendmail 与 postfix 及 dovecot 都是与邮件有关的软体，这些软体在设计登录档记录时，都会主动呼叫 syslogd 内的 mail 服务名称 (LOG_MAIL)，所以上述三个软体 (sendmail, postfix, dovecot) 产生的讯息在 syslog 看起来，就会‘是 mail ’类型的服务了。我们可以将这个概念绘制如底下的图示来理解：

syslog 所制订的服务名称与软体呼叫的方式
图 2.2.1、 syslog 所制订的服务名称与软体呼叫的方式

另外，每种服务所产生的资料量其实差异是很大的，举例来说， mail 的登录档讯息多的要命， 每一封信件进入后， mail 至少需要记录‘寄信人的资讯；与收信者的讯息’等等； 而如果是用来做为工作站主机的，那么登入者 (利用 login 登录主机处理事情) 的数量一定不少，那个 authpriv 所管辖的内容可就多的要命了。

为了让不同的资讯放置到不同的档案当中，好让我们分门别类的进行登录档的管理， 所以啰，将各种类别的服务之登录档，记录在不同的档案里面，就是我们 /etc/syslog.conf 所要作的规范了！

  • 讯息等级

同一个服务所产生的讯息也是有差别的，有启动时仅通知系统而已的一般讯息 (information)， 有出现还不至于影响到正常运作的警告讯息 (warn) ，还有系统硬体发生严重错误时，所产生的重大问题讯息 (error 等等)； 讯息到底有多少种严重的等级呢？基本上，syslog 将讯息分为七个主要的等级，依序是这样的(由不重要排列到重要讯息等级)：

等级 | 等级名称 | 说明
1 | info | 仅是一些基本的讯息说明而已；
2 | notice | 比 info 还需要被注意到的一些资讯内容；
3 | warning (warn) | 警示的讯息，可能有问题，但是还不至于影响到某个 daemon 运作的资讯；基本上， info, notice, warn 这三个讯息都是在告知一些基本资讯而已，应该还不至于造成一些系统运作困扰；
4 | err (error) | 一些重大的错误讯息，例如设定档的某些设定值造成该服务服法启动的资讯说明， 通常藉由 err 的错误告知，应该可以了解到该服务无法启动的问题呢！
5 | crit | 比 error 还要严重的错误资讯，这个 crit 是临界点 (critical) 的缩写，这个错误已经很严重了喔！
6 | alert | 警告警告，已经很有问题的等级，比 crit 还要严重！
7 | emerg (panic) | 疼痛等级，意指系统已经几乎要当机的状态！ 很严重的错误资讯了。通常大概只有硬体出问题，导致整个核心无法顺利运作，就会出现这样的等级的讯息吧！

除了这些有等级的讯息外，还有两个特殊的等级，那就是 debug(错误侦测等级) 与 none (不需登录等级) 两个，当我们想要作一些错误侦测，或者是忽略掉某些服务的资讯时， 就用这两个咚咚吧！

特别留意一下在讯息等级之前还有 [.=!] 的连结符号喔！他代表的意思是这样的：

  • . ：代表‘比后面还要高的等级 (含该等级) 都被记录下来’的意思，例如： mail.info 代表只要是 mail 的资讯，而且该资讯等级高于 info (含 info 本身)时，就会被记录下来的意思。
  • .=：代表所需要的等级就是后面接的等级而已， 其他的不要！
  • .!：代表不等于， 亦即是除了该等级外的其他等级都记录。

一般来说，我们比较常使用的是‘.’这个连结符号啦！^_^

  • 讯息记录的档名或装置或主机

再来则是这个讯息要放置在哪里的纪录了。通常我们使用的都是记录的档案啦！但是也可以输出到装置呦！ 例如印表机之类的！也可以记录到不同的主机上头去呢！底下就是一些常见的放置处：

  • 档案的绝对路径：通常就是放在 /var/log 里头的档案啦！
  • 印表机或其他：例如 /dev/lp0 这个印表机装置
  • 使用者名称：显示给使用者啰！
  • 远端主机：例如 @www.vbird.tsai 当然啦，要对方主机也能支援才行！
  • *：代表‘目前在线上的所有人’，类似 wall 这个指令的意义！

  • syslog.conf 语法练习

基本上，整个 syslog 的设定档就只是这样而已，底下我们来思考一些例题，好让你可以更清楚的知道如何设定 syslogd 啊！

例题：
如果我要将我的 mail 相关的资料给他写入 /var/log/maillog 当中，那么在 /etc/syslog.conf 的语法如何设计？
答：
基本的写法是这样的：
mail.info　　　/var/log/maillog
注意到上面喔，当我们的等级使用 info 时，那么‘任何大于 info 等级(含 info 这个等级)之上的讯息， 都会被写入到后面接的档案之中！’这样可以了解吗？也就是说，我们可以将所有 mail 的登录资讯都纪录在 /var/log/maillog 里面的意思啦！

例题：
我要将新闻群组资料 (news) 及例行性工作排程 (cron) 的讯息都写入到一个称为 /var/log/cronnews 的档案中，但是这两个程序的警告讯息则额外的记录在 /var/log/cronnews.warn 中， 那该如何设定我的 syslog.conf 呢？
答：
很简单啦！既然是两个程序，那么只好以分号来隔开了，此外，由于第二个指定档案中，我只要记录警告讯息， 因此设定上需要指定‘.=’这个符号，所以语法成为了：
news.*;cron.*　　　　　/var/log/cronnews
news.=warn;cron.=warn　/var/log/cronnews.warn
上面那个‘.=’就是在指定等级的意思啦！由于指定了等级，因此，只有这个等级的讯息才会被纪录在这个档案里面呢！ 此外你也必须要注意，news 与 cron 的警告讯息也会写入 /var/log/cronnews 内喔！

例题：
我的 messages 这个档案需要记录所有的资讯，但是就是不想要记录 cron, mail 及 news 的资讯，那么应该怎么写才好？
答：
可以有两种写法，分别是：
*.*;news,cron,mail.none　　　　　　/var/log/messages
*.*;news.none;cron.none;mail.none　/var/log/messages
使用‘,’分隔时，那么等级只要接在最后一个即可，如果是以‘;’来分的话， 那么就需要将服务与等级都写上去啰！这样会设定了吧！

  • CentOS 5.x 预设的 syslog.conf 内容

了解语法之后，我们来看一看 syslog 有哪些系统服务已经在记录了呢？就是瞧一瞧 /etc/syslog.conf 这个档案的预设内容啰！ (注意！如果需要将该行做为注解时，那么就加上 # 符号就可以啦)

# 来自 CentOS 5.x 的相关资料
[root@www ~]# vim /etc/syslog.conf
  1 #kern.*                                              /dev/console
  2 *.info;mail.none;news.none;authpriv.none;cron.none   /var/log/messages
  3 authpriv.*                                           /var/log/secure
  4 mail.*                                              -/var/log/maillog
  5 cron.*                                               /var/log/cron
  6 *.emerg                                              *
  7 uucp,news.crit                                       /var/log/spooler
  8 local7.*                                             /var/log/boot.log
  9 news.=crit                                         /var/log/news/news.crit
 10 news.=err                                          /var/log/news/news.err
 11 news.notice                                        /var/log/news/news.notice

上面总共仅有十一行设定值，每一行的意义是这样的：

  1. #kern.*：只要是核心产生的讯息，全部都送到 console(终端机) 去。console 通常是由外部装置连接到系统而来， 举例来说，很多封闭型主机 (没有键盘、荧幕的系统) 可以透过连接 RS232 连接口将讯息传输到外部的系统中， 例如以笔记型电脑连接到封闭主机的 RS232 插口。这个项目通常应该是用在系统出现严重问题而无法使用预设的荧幕观察系统时， 可以透过这个项目来连接取得核心的讯息。(注1)

  2. *.info;mail.none;news.none;authpriv.none;cron.none：由于 mail, news, authpriv, cron 等类别产生的讯息较多， 且已经写入底下的数个档案中，因此在 /var/log/messages 里面就不记录这些项目。除此之外的其他讯息都写入 /var/log/messages 中。这也是为啥我们说这个 messages 档案很重要的缘故！

  3. authpriv.*：认证方面的讯息均写入 /var/log/secure 档案；

  4. mail.*：邮件方面的讯息则均写入 /var/log/maillog 档案；

  5. cron.*：例行性工作排程均写入 /var/log/cron 档案；

  6. *.emerg：当产生最严重的错误等级时，将该等级的讯息以 wall 的方式广播给所有在系统登入的帐号得知， 要这么做的原因是希望在线的使用者能够赶紧通知系统管理员来处理这么可怕的错误问题。

  7. uucp,news.crit：uucp 是早期 Unix-like 系统进行资料传递的通讯协定，后来常用在新闻群组的用途中。 news 则是新闻群组。当新闻群组方面的资讯有严重错误时就写入 /var/log/spooler 档案中；

  8. local7.*：将本机开机时应该显示到荧幕的讯息写入到 /var/log/boot.log 档案中；

  9. 后面的 news.=crit、news.=err、news.notice 则主要在分别记录新闻群组产生的不同等级的讯息。

在上面的第四行关于 mail 的记录中，在记录的档案 /var/log/maillog 前面还有个减号‘ - ’是干嘛用的？由于邮件所产生的讯息比较多，因此我们希望邮件产生的讯息先储存在速度较快的记忆体中 (buffer) ，等到资料量够大了才一次性的将所有资料都填入磁碟内，这样将有助于登录档的存取性能。 只不过由于讯息是暂存在记忆体内，因此若不正常关机导致登录资讯未回填到登录档中，可能会造成部分资料的遗失。

此外，每个 Linux distributions 的 syslog.conf 设定差异是颇大的，如果你想要找到相对应的登录资讯时， 可得要查阅一下 /etc/syslog.conf 这个档案才行！否则可能会发生分析到错误的资讯喔！举例来说， 鸟哥有自己写一支分析登录档的 script，这个 script 是依据 Red Hat 系统预设的登录档所写的，因此不同的 distributions 想要使用这支程式时，就得要自行设计与修改一下 /etc/syslog.conf 才行喔！否则就可能会分析到错误的资讯啰。 那么如果你有自己的需要而得要修订登录档时，该如何进行？

  • 自行增加登录档档案功能

如果你有其他的需求，所以需要特殊的档案来帮你记录时，呵呵！别客气，千万给他记录在 /etc/syslog.conf 当中，如此一来，你就可以重复的将许多的资讯记录在不同的档案当中，以方便你的管理呢！ 让我们来作个练习题吧！如果你想要让‘所有的资讯’都额外写入到 /var/log/admin.log 这个档案时， 你可以怎么作呢？先自己想一想，并且作一下，再来看看底下的作法啦！

# 1. 先设定好所要建立的档案设置！
[root@www ~]# vim /etc/syslog.conf
# Add by VBird 2009/04/08       <==再次强调，自己修改的时候加入一些说明
*.info      /var/log/admin.log  <==有用的是这行啦！

# 2. 重新启动 syslog 呢！
[root@www ~]# /etc/init.d/syslog restart
[root@www ~]# ll /var/log/admin.log
-rw------- 1 root root 118 Apr  8 13:50 /var/log/admin.log
# 瞧吧！建立了这个登录档出现啰！

很简单吧！如此一来，所有的资讯都会写入 /var/log/admin.log 里面了！

小标题的图示 登录档的安全性设置

好了，由上一个小节里面我们知道了 syslog.conf 的设定，也知道了登录档内容的重要性了， 所以，如果幻想你是一个很厉害的骇客，想利用他人的电脑干坏事，然后又不想留下证据， 你会怎么作？对啦！就是离开的时候将屁股擦干净，将所有可能的讯息都给他抹煞掉， 所以第一个动脑筋的地方就是登录档的清除工作啦～ 如果你的登录档不见了，那该怎办？

Tips:
哇！鸟哥教人家干坏事……喂！不要乱讲话～俺的意思是，如果改天你发现你的登录档不翼而飞了， 或者是发现你的登录档似乎不太对劲的时候，最常发现的就是网友常常会回报说，他的 /var/log 这个目录‘不见了！’不要笑！这是真的事情！请记得，‘赶快清查你的系统！’ 		鸟哥的图示

伤脑筋呢！有没有办法防止登录档被删除？或者是被 root 自己不小心变更呢？有呀！拔掉网路线或电源线就好了……呵呵！ 别担心，基本上，我们可以透过一个隐藏的属性来设定你的登录档，成为‘ 只可以增加资料，但是不能被删除 ’的状态，那么或许可以达到些许的保护！不过，如果你的 root 帐号被破解了，那么底下的设定还是无法保护的，因为你要记得‘ root 是可以在系统上面进行任何事情的 ’，因此，请将你的 root 这个帐号的密码设定的安全一些！千万不要轻忽这个问题呢！

Tips:
为什么登录档还要防止被自己 (root) 不小心所修改过呢？ 鸟哥在教 Linux 的课程时，我的学生常常会举手说：‘老师，我的登录档不能记录资讯了！糟糕！是不是被入侵了啊？’ 怪怪！明明是电脑教室的主机，使用的是 Private IP 而且学校计中还有抵挡机制，不可能被攻击吧？ 查询了才知道原来同学很喜欢使用‘ :wq ’来离开 vim 的环境，但是 syslog 的登录档只要‘被编辑过’就无法继续记录！ 所以才会导致不能记录的问题。此时你得要 (1)改变使用 vim 的习惯； (2)重新启动 syslog 让他再继续提供服务才行喔！ 		鸟哥的图示

既然如此，那么我们就来处理一下隐藏属性的东东吧！我们在第七章谈到过 lsattr 与 chattr 这两个东西啦！如果将一个档案以 chattr 设定 i 这个属性时，那么该档案连 root 都不能杀掉！而且也不能新增资料，嗯！真安全！但是，如此一来登录档的功能岂不是也就消失了？ 因为没有办法写入呀！所以啰，我们要使用的是 a 这个属性！你的登录档如果设定了这个属性的话，那么 他将只能被增加，而不能被删除！嗯！ 这个项目就非常的符合我们登录档的需求啦！因此，你可以这样的增加你的登录档的隐藏属性。

Tips:
请注意，底下的这个 chattr 的设定状态：‘仅适合已经对 Linux 系统很有概念的朋友’来设定， 对于新手来说，建议你直接使用系统的预设值就好了，免得到最后登录档无法写入～ 那就比较糗一点！ @_@ 		鸟哥的图示
[root@www ~]# chattr +a /var/log/messages
[root@www ~]# lsattr /var/log/messages
-----a------- /var/log/messages

加入了这个属性之后，你的 /var/log/messages 登录档从此就仅能被增加，而不能被删除，直到 root 以‘ chattr -a /var/log/messages ’取消这个 a 的参数之后，才能被删除或移动喔！

虽然，为了你登录档的资讯安全，这个 chattr 的 +a 旗标可以帮助你维护好这个档案， 不过，如果你的系统已经被取得 root 的权限，而既然 root 可以下达 chattr -a 来取消这个旗标， 所以啰，还是有风险的啦！此外，前面也稍微提到，新手最好还是先不要增加这个旗标， 很容易由于自己的忘记，导致系统的重要讯息无法记录呢。

基本上，鸟哥认为，这个旗标最大的用处除了在保护你登录档的资料外， 他还可以帮助你避免掉不小心写入登录档的状况喔。要注意的是，当‘ 你不小心 "手动" 更动过登录档后，例如那个 /var/log/messages ， 你不小心用 vi 开启他，离开却下达 :wq 的参数，呵呵！那么该档案未来将不会再继续进行登录动作！ ’这个问题真的很常发生！由于你以 vi 储存了登录档，则 syslogd 会误判为该档案已被更动过， 将导致 syslogd 不再写入该档案新的内容～很伤脑筋的！

要让该登录档可以继续写入，你只要重新启动 syslog (/etc/init.d/syslog restart) 即可。 不过，总是比较麻烦。所以啊，如果你针对登录档下达 chattr +a 的参数，嘿嘿！ 未来你就不需要害怕不小心更动到该档案了！因为无法写入嘛！除了可以新增之外～ ^_^

不过，也因为这个 +a 的属性让该档案无法被删除与修改，所以啰，当我们进行登录档案轮替时 (logrotate) ，将会无法移动该登录档的档名呢！所以会造成很大的困扰。这个困扰虽然可以使用 logrotate 的设定档来解决，但是，还是先将登录档的 +a 旗标拿掉吧！

[root@www ~]# chattr -a /var/log/messages
小标题的图示 登录档伺服器的设定

我们在之前稍微提到的，在 syslog.conf 档案当中，可以将登录资料传送到印表机或者是远端主机上面去。这样做有什么意义呢？ 如果你将登录资讯直接传送到印表机上面的话，那么万一不小心你的系统被 cracker 所入侵， 他也将你的 /var/log/ 砍掉了，怎么办？没关系啊！反正你已经将重要资料直接以印表机记录起来了， 嘿嘿！他是无法逃开的啦！^_^

再想像一个环境，你的办公室内有十部 Linux 主机，每一部负责一个网路服务， 你为了要了解每部主机的状态，因此，你常常需要登入这十部主机去查阅你的登录档～ 哇！光用想的，每天要进入十部主机去查资料，想到就烦～没关系～这个时候我们可以让某一部主机当成 ‘登录档伺服器’，用他来记录所有的十部 linux 主机的资讯，嘿嘿！这样我就直接进入一部主机就可以了！ 省时又省事，真方便～

那要怎么达到这样的功能呢？很简单啦，我们 CentOS 5.x 预设的 syslog 本身就已经具有这个登录档伺服器的功能了， 只是预设并没有启动该功能而已。你可以透过 man syslogd 去查询一下相关的选项就能够知道啦！ 既然是登录档伺服器，那么我们的 Linux 主机当然会启动一个埠口来监听了，那个预设的埠口就是 UDP 的 514 喔！

登录档伺服器的架构
图 2.4.1、登录档伺服器的架构

如上图所示，伺服器会启动监听的埠口，用户端则将登录档再转出一份送到伺服器去。 而既然是登录档‘伺服器’，所以当然有伺服器与用户端 (client) 啰！这两者的设定分别是这样的：

# 1. Server 端：修改 syslogd 的启动设定档，通常在 /etc/sysconfig 内！
[root@www ~]# vim /etc/sysconfig/syslog
# 找到底下这一行：
SYSLOGD_OPTIONS="-m 0"
# 改成底下这样子！
SYSLOGD_OPTIONS="-m 0 -r"

# 2. 重新启动与观察 syslogd 喔！
[root@www ~]# /etc/init.d/syslog restart
[root@www ~]# netstat -lunp | grep syslog
Proto Recv-Q Send-Q Local Address  Foreign Address State   PID/Program name
udp        0      0 0.0.0.0:514    0.0.0.0:*               13981/syslogd
# 嘿嘿！你的登录档主机已经设定妥当啰！很简单吧！

透过这个简单的动作，你的 Linux 主机已经可以接收来自其他主机的登录资讯了！ 当然啦，你必须要知道网路方面的相关基础，这里鸟哥只是先介绍， 未来了解了网路相关资讯后，再回头来这里瞧一瞧先！ ^_^

至于 client 端的设定就简单多了！只要指定某个资讯传送到这部主机即可！ 举例来说，我们的登录档伺服器 IP 为 192.168.1.100 ，而 client 端希望所有的资料都送给主机， 所以，可以在 /etc/syslog.conf 里面新增这样的一行：

[root@www ~]# vim /etc/syslog.conf
*.*       @192.168.1.100

再重新启动 syslog 后，立刻就搞定了！而未来主机上面的登录档当中，每一行的‘主机名称’就会显示来自不同主机的资讯了。 很简单吧！ ^_^。接下来，让我们来谈一谈，那么如何针对登录档来进行轮转 (rotate) 呢？

大标题的图示 登录档的轮替(logrotate)

假设我们已经将登录资料写入了记录档中了，也已经利用 chattr 设定了 +a 这个属性了，那么该如何进行 logrotate 的工作呢？这里请特别留意的是：‘syslog 利用的是 daemon 的方式来启动的， 当有需求的时候立刻就会被执行的，但是 logrotate 却是在规定的时间到了之后才来进行登录档的轮替， 所以这个 logrotate 程序当然就是挂在 cron 底下进行的呦！’ 仔细看一下 /etc/cron.daily/ 里面的档案，嘿嘿～看到了吧！ /etc/cron.daily/logrotate 就是记录了每天要进行的登录档轮替的行为啦！ ^_^！底下我们就来谈一谈怎么样设计这个 logrotate 吧！

小标题的图示 logrotate 的设定档

既然 logrotate 主要是针对登录档来进行轮替的动作，所以啰，他当然必须要记载‘ 在什么状态下才将登录档进行轮替’的设定啊！那么 logrotate 这个程式的参数设定档在哪里呢？呵呵！那就是：

  • /etc/logrotate.conf
  • /etc/logrotate.d/

那个 logrotate.conf 才是主要的参数档案，至于 logrotate.d 是一个目录， 该目录里面的所有档案都会被主动的读入 /etc/logrotate.conf 当中来进行！另外，在 /etc/logrotate.d/ 里面的档案中，如果没有规定到的一些细部设定，则以 /etc/logrotate.conf 这个档案的规定来指定为预设值！

好了，刚刚我们提到 logrotate 的主要功能就是将旧的登录档案移动成旧档， 并且重新建立一个新的空的档案来记录，他的执行结果有点类似底下的图示：

登录档进行 logrotate 的结果
图 3.1.1、 登录档进行 logrotate 的结果

由上面的图示我们可以清楚的知道，当第一次执行完 rotate 之后，原本的 messages 会变成 messages.1 而且会制造一个空的 messages 给系统来储存登录档。而第二次执行之后，则 messages.1 会变成 messages.2 而 messages 会变成 messages.1 ，又造成一个空的 messages 来储存登录档！那么如果我们仅设定保留三个登录档而已的话，那么执行第四次时，则 messages.3 这个档案就会被删除，并由后面的较新的保存登录档所取代！基本的工作就是这样啦！

那么多久进行一次这样的 logrotate 工作呢？这些都记录在 logrotate.conf 里面，我们来看一下预设的 logrotate 的内容吧！

[root@www ~]# vim /etc/logrotate.conf
# 底下的设定是 "logrotate 的预设设定值" ，如果个别的档案设定了其他的参数，
# 则将以个别的档案设定为主，若该档案没有设定到的参数则以这个档案的内容为预设值！

weekly    <==预设每个礼拜对登录档进行一次 rotate 的工作
rotate 4  <==保留几个登录档呢？预设是保留四个！
create    <==由于登录档被更名，因此建立一个新的来继续储存之意！
#compress <==被更动的登录档是否需要压缩？如果登录档太大则可考虑此参数启动

include /etc/logrotate.d
# 将 /etc/logrotate.d/ 这个目录中的所有档案都读进来执行 rotate 的工作！

/var/log/wtmp {       <==仅针对 /var/log/wtmp 所设定的参数
    monthly           <==每个月一次，取代每周！
    minsize 1M        <==档案容量一定要超过 1M 后才进行 rotate (略过时间参数)
    create 0664 root utmp <==指定新建档案的权限与所属帐号/群组
    rotate 1          <==仅保留一个，亦即仅有 wtmp.1 保留而已。
}
# 这个 wtmp 可记录登入者与系统重新开机时的时间与来源主机及登入期间的时间。
# 由于具有 minsize 的参数，因此不见得每个月一定会进行一次喔！要看档案容量。
# 由于仅保留一个登录档而已，不满意的话可以将他改成 rotate 5 吧！

由这个档案的设定我们可以知道 /etc/logrotate.d 其实就是由 /etc/logrotate.conf 所规划出来的目录，所以，其实我们可以将所有的资料都给他写入 /etc/logrotate.conf 即可，但是这样一来这个档案就实在是太复杂了，尤其是当我们使用很多的服务在系统上面时， 每个服务都要去修改 /etc/logrotate.conf 的设定也似乎不太合理～ 所以，如果独立出来一个目录，那么每个以 RPM 打包方式所建立的服务的登录档轮替设定， 就可以独自成为一个档案，并且放置到 /etc/logrotate.d/ 当中即可，真是方便又合理的做法啊！ ^_^

一般来说，这个 /etc/logrotate.conf 是‘预设的轮替状态’而已， 我们的各个服务都可以拥有自己的登录档轮替设定，你也可以自行修改成自己喜欢的样式啊！ 例如，如果你的系统的空间够大，并且担心除错以及骇客的问题，那么可以：

  • 将 rotate 4 改成 rotate 9 左右，以保存较多的备份档案；
  • 大部分的登录档不需要 compress 啰！但是空间太小就需要 compress ！尤其是很占硬碟空间的 httpd 更需要 compress 的！

好了，上面我们大致介绍了 /var/log/wtmp 这个档案的设定，现在你知道了 logrotate.conf 的设定语法是：

登录档的绝对路径档名 ... {
    个别的参数设定值，如 monthly, compress 等等
}

底下我们再以 /etc/logrotate.d/syslog 这个轮替 syslog 服务的档案，来看看该如何设定他的 rotate 呢？

[root@www ~]# vi /etc/logrotate.d/syslog
/var/log/messages /var/log/secure /var/log/maillog /var/log/spooler \
/var/log/boot.log /var/log/cron {
  sharedscripts
  postrotate
    /bin/kill -HUP `cat /var/run/syslogd.pid 2> /dev/null` 2> /dev/null || true
    /bin/kill -HUP `cat /var/run/rsyslogd.pid 2> /dev/null` 2> /dev/null || true
  endscript
}

在上面的语法当中，我们知道正确的 logrotate 的写法为：

  • 档名：被处理的登录档绝对路径档名写在前面，可以使用空白字元分隔多个登录档；
  • 参数：上述档名进行轮替的参数使用 { } 包括起来；
  • 执行脚本：可呼叫外部指令来进行额外的命令下达，这个设定需与 sharedscripts .... endscript 设定合用才行。至于可用的环境为：
    • prerotate：在启动 logrotate 之前进行的指令，例如修改登录档的属性等动作；
    • postrotate：在做完 logrotate 之后启动的指令，例如重新启动 (kill -HUP) 某个服务！
    • Prerotate 与 postrotate 对于已加上特殊属性的档案处理上面，是相当重要的执行程序！

那么 /etc/logrotate.d/syslog 内设定的六个档案的轮替功能就变成了：

  • 该设定只对 /var/log/ 内的 messages, secure, maillog, spooler, boot.log, cron 有效；
  • 登录档轮替每周一次、保留四个、且轮替下来的登录档不进行压缩(未更改预设值)；
  • 轮替完毕后 (postrotate) 取得 syslog 的 PID 后，以 kill -HUP 重新启动 syslogd

假设我们有针对 /var/log/messages 这个档案增加 chattr +a 的属性时， 依据 logrotate 的工作原理，我们知道，这个 /var/log/messages 将会被更名成为 /var/log/messages.1 才是。但是由于加上这个 +a 的参数啊，所以更名是不可能成功的！ 那怎么办呢？呵呵！就利用 prerotate 与 postrotate 来进行登录档轮替前、后所需要作的动作啊！ 果真如此时，那么你可以这样修改一下这个档案喔！

[root@www ~]# vi /etc/logrotate.d/syslog
/var/log/messages /var/log/secure /var/log/maillog /var/log/spooler \
/var/log/boot.log /var/log/cron {
  sharedscripts
  prerotate
    /usr/bin/chattr -a /var/log/messages
  endscript
  sharedscripts
  postrotate
    /bin/kill -HUP `cat /var/run/syslogd.pid 2> /dev/null` 2> /dev/null || true
    /bin/kill -HUP `cat /var/run/rsyslogd.pid 2> /dev/null` 2> /dev/null || true
    /usr/bin/chattr +a /var/log/message
  endscript
}

看到否？就是先给他去掉 a 这个属性，让登录档 /var/log/messages 可以进行轮替的动作， 然后执行了轮替之后，再给他加入这个属性！请特别留意的是，那个 /bin/kill -HUP ... 的意义，这一行的目的在于将系统的 syslogd 重新以其参数档 (syslog.conf) 的资料读入一次！也可以想成是 reload 的意思啦！ 由于我们建立了一个新的空的纪录档，如果不执行此一行来重新启动服务的话， 那么记录的时候将会发生错误呦！(请回到第十七章读一下 kill 后面的 signal 的内容说明)

小标题的图示 实际测试 logrotate 的动作

好了，设定完成之后，我们来测试看看这样的设定是否可行呢？给他执行底下的指令：

[root@www ~]# logrotate [-vf] logfile
选项与参数：
-v  ：启动显示模式，会显示 logrotate 运作的过程喔！
-f  ：不论是否符合设定档的资料，强制每个登录档都进行 rotate 的动作！

范例一：执行一次 logrotate 看看整个流程为何？
[root@www ~]# logrotate -v /etc/logrotate.conf
reading config file /etc/logrotate.conf <==读取主要设定档
including /etc/logrotate.d              <==呼叫外部的设定
reading config file acpid               <==就是外部设定啊！
....(中间省略)....
Handling 21 logs                        <==共有 21 个登录档被记录
....(中间省略)....
rotating pattern: /var/log/messages /var/log/secure /var/log/maillog \
/var/log/spooler /var/log/boot.log /var/log/cron  weekly (4 rotations)
empty log files are rotated, old logs are removed
considering log /var/log/messages       <==开始处理 messages
  log does not need rotating            <==因为时间未到，不需要更动！
....(底下省略)....

范例二：强制进行 logrotate 的动作
[root@www ~]# logrotate -vf /etc/logrotate.conf
....(前面省略)....
rotating log /var/log/messages, log->rotateCount is 4
renaming /var/log/messages.4 to /var/log/messages.5 (rotatecount 4, logstart 1, i 4),
renaming /var/log/messages.3 to /var/log/messages.4 (rotatecount 4, logstart 1, i 3),
renaming /var/log/messages.2 to /var/log/messages.3 (rotatecount 4, logstart 1, i 2),
renaming /var/log/messages.1 to /var/log/messages.2 (rotatecount 4, logstart 1, i 1),
renaming /var/log/messages.0 to /var/log/messages.1 (rotatecount 4, logstart 1, i 0),
old log /var/log/messages.0 does not exist
....(底下省略)....
# 看到否？整个 rotate 的动作就是这样一步一步进行的～

[root@www ~]# ll /var/log/messages*; lsattr /var/log/messages
-rw------- 1 root root    63 Apr  8 15:19 /var/log/messages
-rw------- 1 root root   670 Apr  8 14:22 /var/log/messages.1
-rw------- 1 root root 24984 Apr  1 19:26 /var/log/messages.2
-rw------- 1 root root  1911 Mar 28 11:32 /var/log/messages.3
-rw------- 1 root root 25193 Mar 22 04:02 /var/log/messages.4
-----a------- /var/log/messages <==主动加入 a 的隐藏属性啰！

上面那个 -f 具有‘强制执行’的意思，如果一切的设定都没有问题的话，那么理论上，你的 /var/log 这个目录就会起变化啰！而且应该不会出现错误讯息才对！嘿嘿！这样就 OK 了！很棒不是吗？！

由于 logrotate 的工作已经加入 crontab 里头了！所以现在每天系统都会自动的给他查看 logrotate 啰！不用担心的啦！只是要注意一下那个 /var/log/messages 里头是否常常有类似底下的字眼：

Apr 8 15:19:47 www syslogd 1.4.1: restart (remote reception).

这说明的是 syslogd 重新启动的时间啦 (就是因为 /etc/logrotate.d/syslog 的设定之缘故！) 底下我们来进行一些例题的练习，让你更详细的了解 logrotate 的功用啊！

小标题的图示 自订登录档的轮替功能

假设前提是这样的，前一小节当中，假设你已经建立了 /var/log/admin.log 这个档案， 现在，你想要将该档案加上 +a 这个隐藏标签，而且设定底下的相关资讯：

  • 登录档轮替一个月进行一次；
  • 该登录档若大于 10MB 时，则主动进行轮替，不需要考虑一个月的期限；
  • 保存五个备份档案；
  • 备份档案需要压缩

那你可以怎么样设定呢？呵呵～很简单啊！看看底下的动作吧！

# 1. 先建立 +a 这个属性啊！
[root@www ~]# chattr +a /var/log/admin.log
[root@www ~]# lsattr /var/log/admin.log
-----a------- /var/log/admin.log
[root@www ~]# mv /var/log/admin.log /var/log/admin.log.1
mv: cannot move `/var/log/admin.log' to `/var/log/admin.log.1':
Operation not permitted
# 这里确定了加入 a 的隐藏属性！所以 root 无法移动此登录档！

# 2. 开始建立 logrotate 的设定档，增加一个档案在 /etc/logrotate.d 内就对了！
[root@www ~]# vi /etc/logrotate.d/admin
# This configuration is from VBird 2009/04/08
/var/log/admin.log {
        monthly   <==每个月进行一次
        size=10M  <==档案容量大于 10M 则开始处置
        rotate 5  <==保留五个！
        compress  <==进行压缩工作！
        sharedscripts
        prerotate
                /usr/bin/chattr -a /var/log/admin.log
        endscript
        sharedscripts
        postrotate
                /usr/bin/killall -HUP syslogd
                /usr/bin/chattr +a /var/log/admin.log
        endscript
}

# 3. 测试一下 logrotate 相关功能的资讯显示：
[root@www ~]# logrotate -v /etc/logrotate.conf
....(前面省略)....
rotating pattern: /var/log/admin.log  10485760 bytes (5 rotations)
empty log files are rotated, old logs are removed
considering log /var/log/admin.log
  log does not need rotating
not running prerotate script, since no logs will be rotated
not running postrotate script, since no logs were rotated
....(底下省略)....
# 因为还不足一个月，档案也没有大于 10M，所以不需进行轮替！

# 4. 测试一下强制 logrotate 与相关功能的资讯显示：
[root@www ~]# logrotate -vf /etc/logrotate.d/admin
reading config file /etc/logrotate.d/admin
reading config info for /var/log/admin.log

Handling 1 logs

rotating pattern: /var/log/admin.log  forced from command line (5 rotations)
empty log files are rotated, old logs are removed
considering log /var/log/admin.log
  log needs rotating
rotating log /var/log/admin.log, log->rotateCount is 5
renaming /var/log/admin.log.5.gz to /var/log/admin.log.6.gz (rotatecount 5, logstart 1, i 5),
old log /var/log/admin.log.5.gz does not exist
renaming /var/log/admin.log.4.gz to /var/log/admin.log.5.gz (rotatecount 5, logstart 1, i 4),
old log /var/log/admin.log.4.gz does not exist
renaming /var/log/admin.log.3.gz to /var/log/admin.log.4.gz (rotatecount 5, logstart 1, i 3),
old log /var/log/admin.log.3.gz does not exist
renaming /var/log/admin.log.2.gz to /var/log/admin.log.3.gz (rotatecount 5, logstart 1, i 2),
old log /var/log/admin.log.2.gz does not exist
renaming /var/log/admin.log.1.gz to /var/log/admin.log.2.gz (rotatecount 5, logstart 1, i 1),
old log /var/log/admin.log.1.gz does not exist
renaming /var/log/admin.log.0.gz to /var/log/admin.log.1.gz (rotatecount 5, logstart 1, i 0),
old log /var/log/admin.log.0.gz does not exist
log /var/log/admin.log.6.gz doesn't exist -- won't try to dispose of it
running prerotate script
renaming /var/log/admin.log to /var/log/admin.log.1
running postrotate script
compressing log with: /bin/gzip

[root@www ~]# lsattr /var/log/admin.log*
-----a------- /var/log/admin.log
------------- /var/log/admin.log.1.gz  <==有压缩过喔！

看到了吗？透过这个方式，我们可以建立起属于自己的 logrotate 设定档案， 很简便吧！尤其是要注意的， /etc/syslog.conf 与 /etc/logrotate.d/* 档案常常要搭配起来，例如刚刚我们提到的两个案例中所建立的 /var/log/admin.log 就是一个很好的例子～建立后，还要使用 logrotate 来轮替啊！ ^_^

大标题的图示 分析登录档

登录档的分析是很重要的！你可以自行以 vi 进入登录档去查阅相关的资讯。而系统也提供一些软体可以让你从登录档中取得资料， 例如之前谈过的 last, lastlog, dmesg 等等指令。不过，这些资料毕竟都非常的分散，如果你想要一口气读取所有的登录资讯， 其实有点困扰的。不过，好在 CentOS 有提供 logwatch 这个登录档分析程式，你可以藉由该程式来了解登录档资讯。 此外，鸟哥也依据 Red Hat 系统的 syslog 写了一支小程式给大家使用喔！

小标题的图示 CentOS 预设提供的 logwatch

虽然有一些有用的系统指令，不过，要了解系统的状态，还是得要分析整个登录档才行～ 事实上，目前已经有相当多的登录档分析工具，例如 CentOS 5.x 上面预设的 logwatch 这个套件所提供的分析工具， 他会每天分析一次登录档案，并且将资料以 email 的格式寄送给 root 呢！ 你也可以直接到 logwatch 的官方网站上面看看：

  • http://www.logwatch.org/

logwatch 分析的结果如下所示：

[root@www ~]# mail
Mail version 8.1 6/6/93.  Type ? for help.
"/var/spool/mail/root": 433 messages 433 new
>N  1 logwatch@www.vbird.t  Fri Sep  5 11:42  43/1542  "Logwatch for www.vbird.tsai (Linux)"
 N  2 logwatch@www.vbird.t  Sat Sep  6 15:34  92/2709  "Logwatch for www.vbird.tsai (Linux)"
 N  3 logwatch@www.vbird.t  Mon Sep  8 15:26  43/1542  "Logwatch for www.vbird.tsai (Linux)"
....(中间省略)....
 N431 logwatch@www.vbird.t  Wed Apr  8 04:02  53/1772  "Logwatch for www.vbird.tsai (Linux)"
& 431
Message 431:
From root@www.vbird.tsai  Wed Apr  8 04:02:05 2009
Date: Wed, 8 Apr 2009 04:02:05 +0800
To: root@www.vbird.tsai
From: logwatch@www.vbird.tsai
Subject: Logwatch for www.vbird.tsai (Linux)
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Type: text/plain; charset="iso-8859-1"

# 先会说明分析的日期与相关的分析期间！
 ################### Logwatch 7.3 (03/24/06) ####################
        Processing Initiated: Wed Apr  8 04:02:05 2009
        Date Range Processed: yesterday
                              ( 2009-Apr-07 )
                              Period is day.
      Detail Level of Output: 0
              Type of Output: unformatted
           Logfiles for Host: www.vbird.tsai
  ##################################################################

# 底下则是依据各种服务来进行各项分析！先是登入者的 ssh 服务分析
 --------------------- SSHD Begin ------------------------

 Users logging in through sshd:
    root:
       192.168.100.101: 1 time
       192.168.100.254: 1 time

 ---------------------- SSHD End -------------------------

# 磁碟容量分析！可以避免你的系统使用过量磁碟，导致的系统不稳问题！
 --------------------- Disk Space Begin ------------------------

 Filesystem            Size  Used Avail Use% Mounted on
 /dev/hda2             9.5G  3.8G  5.3G  42% /
 /dev/hda3             4.8G  1.1G  3.5G  23% /home
 /dev/hda1              99M   21M   73M  23% /boot

 ---------------------- Disk Space End -------------------------
 ###################### Logwatch End #########################

由于鸟哥的测试用主机尚未启动许多服务，所以分析的项目很少。若你的系统已经启动许多服务的话， 那么分析的项目理应会多很多才对。

小标题的图示 鸟哥自己写的登录档分析工具：

虽然已经有了类似 logwatch 的工具，但是鸟哥自己想要分析的资料毕竟与对方不同～ 所以啰，鸟哥就自己写了一支小程式 (shell script 的语法) 用来分析自己的登录档， 这支程式分析的登录档资料其实是固定的，包括有：

  • /var/log/secure
  • /var/log/messages
  • /var/log/maillog

当然啦，还不只这些啦，包括各个主要常见的服务，如 pop3, mail, ftp, su 等会使用到 pam 的服务， 都可以透过鸟哥写的这个小程式来分析与处理呢～整个资料还会输出一些系统资讯。如果你想要使用这个程式的话， 欢迎下载：

  • http://linux.vbird.org/download/index.php?action=detail&fileid=69

安装的方法也很简单，只要将上述档案下载并解压缩后，就会得到一个名为 logfile 的目录， 将此目录移动到 /usr/local/virus/ 目录下并修改一下： /usr/local/virus/logfile.sh 档案， 里面的 email 与相关的资讯只要修改一下，你就可以使用啦～啊！还要记得，将这支程式的执行写入 /etc/crontab 当中喔！ 可以在每天的 12:10am 执行这支小程式啦！ ^_^

[root@www ~]# mkdir /usr/local/virus
[root@www ~]# tar -zxvf logfile-0.1-4-2.tgz -C /usr/local/virus
[root@www ~]# cd /usr/local/virus/logfile
[root@www ~]# vi logfile.sh
email="root@localhost" <==大约在 93 行左右，请填入你的 email ，否则保留预设值
basedir="/usr/local/virus/logfile" <==保留预设值，除非你的执行目录不同与此！

[root@www ~]# sh logfile.sh
# 开始尝试分析系统的登录档，依据你的登录档大小，分析的时间不固定！

[root@www ~]# vi /etc/crontab
10 0 * * * root /usr/local/virus/logfile/logfile.sh
# 增加这一行！让系统在每天的凌晨自己进行登录档分析！

[root@www ~]# mail
# 自己找到刚刚输出的结果，该结果的输出有点像底下这样：

# 先进行程式的宣告！你也可以在底下的连结找到一些错误回报！
##########################################################
欢迎使用本程式来查验您的登录档
本程式目前版本为： Version 0.1-4-2
程式最后更新日期为： 2006-09-22
若在您的系统中发现本程式有问题, 欢迎与我联络！
鸟哥的首页 http://linux.vbird.org
问题回报： http://phorum.vbird.org/viewtopic.php?t=3425
##########################################################

# 先看看你的硬体与作业系统的相关情况，尤其是 partition 的使用量更需要随时注意！
=============== 系统汇整 =================================
核心版本  : Linux version 2.6.18-92.el5 (mockbuild@builder16.centos.org)
CPU 资讯  : Intel(R) Celeron(TM) CPU
          : 1200.062 MHz
主机名称  : www.vbird.tsai
统计日期  : 2009/April/08 17:00:59 ( Wednesday )
分析的日期: Apr  8
已开机期间: 7 days, 22:46,
目前主机挂载的 partitions
       Filesystem            Size  Used Avail Use% Mounted on
       /dev/hda2             9.5G  3.8G  5.3G  42% /
       /dev/hda3             4.8G  1.1G  3.5G  23% /home
       /dev/hda1              99M   21M   73M  23% /boot
       tmpfs                 363M     0  363M   0% /dev/shm

# 这个程式会将针对 internet 与内部监听的埠口分开来显示！
================= Ports 的相关分析资讯 =======================
主机启用的 port 与相关的 process owner：
仅对本机介面开放的 ports (PID|owner|command)
       tcp 25|(root)|sendmail: accepting connections
       tcp 631|(root)|cupsd
       tcp 2207|(root)|python ./hpssd.py
       tcp 2208|(root)|./hpiod
对外部介面开放的 ports (PID|owner|command)
       tcp 22|(root)|/usr/sbin/sshd
       tcp 111|(rpc)|portmap
       tcp 737|(root)|rpc.statd
       udp 111|(rpc)|portmap
       udp 514|(root)|syslogd -m 0 -r
       udp 631|(root)|cupsd
       udp 731|(root)|rpc.statd
       udp 734|(root)|rpc.statd
       udp 5353|(avahi)|avahi-daemon: running [www.local]
       udp 32768|(avahi)|avahi-daemon: running [www.local]
       udp 32769|(avahi)|avahi-daemon: running [www.local]

# 以下针对有启动的服务个别进行分析！
================= SSH 的登录档资讯汇整 =======================
今日没有使用 SSH 的纪录

================= Sednamil 的登录档资讯汇整 ==================
您的主机有进行 SASL 身份认证的功能

今日没有 sendmail 的相关资讯

================= 全部的登录档资讯汇整 =======================
1. 重要的登录记录档 ( Secure file )
   说明：已经取消了 pop3 的资讯！
Apr  8 15:46:22 www su: session opened for user vbird by root(uid=0)
Apr  8 15:47:02 www su: session closed for user vbird

2. 使用 last 这个指令输出的结果

wtmp begins Wed Apr  8 15:19:47 2009

3. 将特重要的 /var/log/messages 列出来瞧瞧！
   已经取消 crond 与 snmpd 的讯息
Apr  8 15:19:47 www syslogd 1.4.1: restart (remote reception).
Apr  8 15:34:25 www syslogd 1.4.1: restart (remote reception).

目前鸟哥都是透过这支程式去分析自己管理的主机，然后再据以了解系统状况，如果有特殊状况则即时进行系统处理！ 而且鸟哥都是将上述的 email 调整成自己可以在 Internet 上面读到的邮件，这样我每天都可以收到正确的登录档分析资讯哩！

大标题的图示 重点回顾
  • 登录档可以记录一个事件的何时、何地、何人、何事等四大资讯，故系统有问题时务必查询登录档；
  • 系统的登录档预设都集中放置到 /var/log/ 目录内，其中又以 messages 记录的资讯最多！
  • 登录档记录的主要服务与程式为： syslogd, klogd, log
  • syslogd 的设定档在 /etc/syslog.conf ，内容语法为：‘ 服务.等级 记载装置或档案’
  • syslogd 本身有提供登录档伺服器的功能，透过修改 /etc/sysconfig/syslog 内容即可达成；
  • logrotate 程式利用 crontab 来进行登录档的轮替功能；
  • logrotate 的设定档为 /etc/logrotate.conf ，而额外的设定则可写入 /etc/logrotate.d/* 内；
  • logwatch 为 CentOS 5 预设提供的一个登录档分析软体。
大标题的图示 本章习题
( 要看答案请将滑鼠移动到‘答：’底下的空白处，按下左键圈选空白处即可察看 )
实作题：
  • 请在你的 CentOS 5.x 上面，依照鸟哥提供的 logfile.sh 去安装，并将结果取出分析看看。

简答题部分：
  • syslogd 可以作为登录档伺服器，请以 man page 的方式配合 network 关键字，查出 syslogd 需要加上什么选项就能够成为登录档伺服器？
    透过 man syslogd ，查询到 -r 的选项。
  • 如果你想要将 auth 这个服务的结果中，只要讯息等级高于 warn 就给予发送 email 到 root 的信箱，该如何处理？
    利用 vim 去编辑 /etc/syslog.conf 档案，内容为
    auth.warn root
  • 启动系统登录资讯时，需要启动哪两个 daemon 呢？
    syslogd 记录系统软体， klogd 记录核心资讯。
  • syslogd 以及 logrotate 个别透过什么机制来执行？
    syslogd 为 super daemon 的机制； logrotate 则是透过 crontab 来执行的！只是个指令而已。
大标题的图示 参考资料与延伸阅读
  • 注1：关于 console 的说明可以参考底下的连结：
    http://en.wikipedia.org/wiki/Console
    http://publib.boulder.ibm.com/infocenter/systems/index.jsp?topic=/com.ibm.aix.files/doc/aixfiles/console.htm
2002/06/24：第一次完成
2003/02/11：重新编排与加入 FAQ
2005/10/12：旧的文章已经被移动到 此处。
2005/10/24：终于写完了～啊！怎么写这么久？？
2006/07/23：修改了 /etc/logrotate.d/syslog 的设定资料
2009/03/31：将旧的基于 FC4 版本的资料移动至 此处
2009/09/14：加入了一些例题而已。这一篇太简单了～想不到什么好的题目说～


鸟哥的 Linux 私房菜 -- 开机关机流程与 Loader

为取得较佳浏览结果，请爱用 firefox 浏览本网页
鸟哥的 Linux 私房菜馆 | Linux 基础文件 | Linux 架站文件 | Linux 企业运用 | 安全管理 | 新手讨论 |

第二十章、开机流程、模组管理与 Loader
最近更新日期：2009/09/14
系统开机其实是一项非常复杂的程序，因为核心得要侦测硬体并载入适当的驱动程式后， 接下来则必须要呼叫程序来准备好系统运作的环境，以让使用者能够顺利的操作整部主机系统。 如果你能够理解开机的原理，那么将有助于你在系统出问题时能够很快速的修复系统喔！ 而且还能够顺利的配置多重作业系统的多重开机问题。为了多重开机的问题，你就不能不学学 grub 这个 Linux 底下优秀的开机管理程式 (boot loader)。 而在系统运作期间，你也得要学会管理核心模组呢！

1. Linux 的开机流程分析
    1.1 开机流程一览
    1.2 BIOS, boot loader 与 kernel 载入
    1.3 第一支程式 init 及设定档 /etc/inittab 与 runlevel
    1.4 init 处理系统初始化流程 (/etc/rc.d/rc.sysinit)
    1.5 启动系统服务与相关启动设定档 (/etc/rc.d/rc N & /etc/sysconfig)
    1.6 使用者自订开机启动程序 (/etc/rc.d/rc.local)
    1.7 根据 /etc/inittab 之设定，载入终端机或 X-Window 介面
    1.8 开机过程会用到的主要设定档： /etc/modprobe.conf, /etc/sysconfig/*
    1.9 Run level 的切换： runlevel, init
 2. 核心与核心模组
    2.1 核心模组与相依性： depmod
    2.2 核心模组的观察： lsmod, modinfo
    2.3 核心模组的载入与移除：insmod, modprobe, rmmod
    2.4 核心模组的额外参数设定：/etc/modprobe.conf
 3. Boot loader: Grub
    3.1 boot loader 的两个 stage
    3.2 grub 的设定档 /boot/grub/menu.lst 与选单类型： 磁碟代号, menu.lst
    3.3 initrd 的重要性与建立新 initrd 档案： mkinitrd
    3.4 测试与安装 grub： grub-install, grub shell
    3.5 开机前的额外功能修改
    3.6 关于核心功能当中的 vga 设定
    3.7 BIOS 无法读取大硬碟的问题
    3.8 为个别选单加上密码： grub-md5-crypt
 4. 开机过程的问题解决
    4.1 忘记 root 密码的解决之道
    4.2 init 设定档错误
    4.3 BIOS 磁碟对应的问题 (device.map)
    4.4 因档案系统错误而无法开机
    4.5 利用 chroot 切换到另一颗硬碟工作
 5. 重点回顾
6. 本章习题
7. 参考资料与延伸阅读
8. 针对本文的建议：http://phorum.vbird.org/viewtopic.php?t=23891
大标题的图示 Linux 的开机流程分析

开机不是只要按一下电源钮而关机只要关掉电源钮就可以了吗？有何大学问？话是这样没错啦，但是由于 Linux 是一套多人多工的作业系统，你难保你在关机时没有人在线上，如果你关机的时候碰巧一大群人在线上工作， 那会让当时在线上工作的人马上断线的！那不是害死人了！一些资料可是无价之宝哩！

另外 Linux 在执行的时候，虽然你在画面上只会看到黑压压的一片，完全没有任何画面， 但其实他是有很多的程序在背景底下执行的，例如登录档管控程式、前面提到的例行性工作排程等， 当然还有一大堆网路服务，如邮件伺服器、WWW 伺服器等等。你如果随便关机的话， 是很容易伤害硬碟及资料传输的动作的！所以在 Linux 下关机可是一门大学问喔。

小标题的图示 开机流程一览

既然开机是很严肃的一件事，那我们就来了解一下整个开机的过程吧！ 好让大家比较容易发现开机过程里面可能会发生问题的地方，以及出现问题后的解决之道！ 不过，由于开机的过程中，那个开机管理程式 (Boot Loader) 使用的软体可能不一样，例如目前各大 Linux distributions 的主流为 grub，但早期 Linux 预设是使用 LILO ，台湾地区则很多朋友喜欢使用 spfdisk 。 但无论如何，我们总是得要了解整个 boot loader 的工作情况，才能了解为何进行多重开机的设定时， 老是听人家讲要先安装 Windows 再安装 Linux 的原因～

假设以个人电脑架设的 Linux 主机为例 (先回到第零章计算机概论看看相关的硬体常识喔)， 当你按下电源按键后电脑硬体会主动的读取 BIOS 来载入硬体资讯及进行硬体系统的自我测试， 之后系统会主动的去读取第一个可开机的装置 (由 BIOS 设定的) ，此时就可以读入开机管理程式了。

开机管理程式可以指定使用哪个核心档案来开机，并实际载入核心到记忆体当中解压缩与执行， 此时核心就能够开始在记忆体内活动，并侦测所有硬体资讯与载入适当的驱动程式来使整部主机开始运作， 等到核心侦测硬体与载入驱动程式完毕后，一个最阳春的作业系统就开始在你的 PC 上面跑了。

主机系统开始运作后，此时 Linux 才会呼叫外部程式开始准备软体执行的环境， 并且实际的载入所有系统运作所需要的软体程式哩！最后系统就会开始等待你的登入与操作啦！ 简单来说，系统开机的经过可以汇整成底下的流程的：

  1. 载入 BIOS 的硬体资讯与进行自我测试，并依据设定取得第一个可开机的装置；
  2. 读取并执行第一个开机装置内 MBR 的 boot Loader (亦即是 grub, spfdisk 等程式)；
  3. 依据 boot loader 的设定载入 Kernel ，Kernel 会开始侦测硬体与载入驱动程式；
  4. 在硬体驱动成功后，Kernel 会主动呼叫 init 程式，而 init 会取得 run-level 资讯；
  5. init 执行 /etc/rc.d/rc.sysinit 档案来准备软体执行的作业环境 (如网路、时区等)；
  6. init 执行 run-level 的各个服务之启动 (script 方式)；
  7. init 执行 /etc/rc.d/rc.local 档案；
  8. init 执行终端机模拟程式 mingetty 来启动 login 程式，最后就等待使用者登入啦；

大概的流程就是上面写的那个样子啦，你会发现 init 这个家伙占的比重非常重！ 所以我们才会在第十七章的 pstree 指令中谈到这家伙。 那每一个程序的内容主要是在干嘛呢？底下就分别来谈一谈吧！

小标题的图示 BIOS, boot loader 与 kernel 载入

我们在第三章曾经谈过简单的开机流程与 MBR 的功能， 当时为了多重开机而进行的简短的介绍。现在你已经有足够的 Linux 基础了，所以底下让我们来加强说明啦！

  • BIOS, 开机自我测试与 MBR

我们在第零章的计算机概论就曾谈过电脑主机架构， 在个人电脑架构下，你想要启动整部系统首先就得要让系统去载入 BIOS (Basic Input Output System)，并透过 BIOS 程式去载入 CMOS 的资讯，并且藉由 CMOS 内的设定值取得主机的各项硬体设定， 例如 CPU 与周边设备的沟通时脉啊、开机装置的搜寻顺序啊、硬碟的大小与类型啊、 系统时间啊、各周边汇流排的是否启动 Plug and Play (PnP, 随插即用装置) 啊、 各周边设备的 I/O 位址啊、以及与 CPU 沟通的 IRQ 岔断等等的资讯。

在取得这些资讯后，BIOS 还会进行开机自我测试 (Power-on Self Test, POST) (注1)。 然后开始执行硬体侦测的初始化，并设定 PnP 装置，之后再定义出可开机的装置顺序， 接下来就会开始进行开机装置的资料读取了 (MBR 相关的任务开始)。

由于我们的系统软体大多放置到硬碟中嘛！所以 BIOS 会指定开机的装置好让我们可以读取磁碟中的作业系统核心档案。 但由于不同的作业系统他的档案系统格式不相同，因此我们必须要以一个开机管理程式来处理核心档案载入 (load) 的问题， 因此这个开机管理程式就被称为 Boot Loader 了。那这个 Boot Loader 程式安装在哪里呢？就在开机装置的第一个磁区 (sector) 内，也就是我们一直谈到的 MBR (Master Boot Record, 主要开机记录区)。

那你会不会觉得很奇怪啊？既然核心档案需要 loader 来读取，那每个作业系统的 loader 都不相同， 这样的话 BIOS 又是如何读取 MBR 内的 loader 呢？很有趣的问题吧！其实 BIOS 是透过硬体的 INT 13 中断功能来读取 MBR 的，也就是说，只要 BIOS 能够侦测的到你的磁碟 (不论该磁碟是 SATA 还是 IDE 介面)，那他就有办法透过 INT 13 这条通道来读取该磁碟的第一个磁区内的 MBR 啦！(注2) 这样 boot loader 也就能够被执行啰！

Tips:
我们知道每颗硬碟的第一个磁区内含有 446 bytes的 MBR 区域，那么如果我的主机上面有两颗硬碟的话， 系统会去哪颗硬碟的 MBR 读取 boot loader 呢？这个就得要看 BIOS 的设定了。 基本上，我们常常讲的‘系统的 MBR’其实指的是 第一个开机装置的 MBR 才对！ 所以，改天如果你要将开机管理程式安装到某颗硬碟的 MBR 时， 要特别注意当时系统的‘第一个开机装置’是哪个，否则会安装到错误的硬碟上面的 MBR 喔！重要重要！ 		鸟哥的图示
  • Boot Loader 的功能

刚刚说到 Loader 的最主要功能是要认识作业系统的档案格式并据以载入核心到主记忆体中去执行。 由于不同作业系统的档案格式不一致，因此每种作业系统都有自己的 boot loader 啦！用自己的 loader 才有办法载入核心档案嘛！那问题就来啦，你应该有听说过多重作业系统吧？也就是在一部主机上面安装多种不同的作业系统。 既然你 (1)必须要使用自己的 loader 才能够载入属于自己的作业系统核心，而 (2)系统的 MBR 只有一个，那你怎么会有办法同时在一部主机上面安装 Windows 与 Linux 呢？

这就得要回到第八章的磁碟档案系统去回忆一下档案系统功能了。 其实每个档案系统 (filesystem, 或者是 partition) 都会保留一块开机磁区 (boot sector) 提供作业系统安装 boot loader ， 而通常作业系统预设都会安装一份 loader 到他根目录所在的档案系统的 boot sector 上。如果我们在一部主机上面安装 Windows 与 Linux 后，该 boot sector, boot loader 与 MBR 的相关性会有点像下图：

boot loader 安装在 MBR, boot sector 与作业系统的关系
图 1.2.1、 boot loader 安装在 MBR, boot sector 与作业系统的关系

如上图所示，每个作业系统预设是会安装一套 boot loader 到他自己的档案系统中 (就是每个 filesystem 左下角的方框)，而在 Linux 系统安装时，你可以选择将 boot loader 安装到 MBR 去，也可以选择不安装。 如果选择安装到 MBR 的话，那理论上你在 MBR 与 boot sector 都会保有一份 boot loader 程式的。 至于 Windows 安装时，他预设会主动的将 MBR 与 boot sector 都装上一份 boot loader！所以啦， 你会发现安装多重作业系统时，你的 MBR 常常会被不同的作业系统的 boot loader 所覆盖啦！ ^_^

我们刚刚提到的两个问题还是没有解决啊！虽然各个作业系统都可以安装一份 boot loader 到他们的 boot sector 中， 这样作业系统可以透过自己的 boot loader 来载入核心了。问题是系统的 MBR 只有一个哩！ 你要怎么执行 boot sector 里面的 loader 啊？这个我们得要回忆一下第三章约略提过的 boot loader 的功能了。boot loader 主要的功能如下：

  • 提供选单：使用者可以选择不同的开机项目，这也是多重开机的重要功能！
  • 载入核心档案：直接指向可开机的程式区段来开始作业系统；
  • 转交其他 loader：将开机管理功能转交给其他 loader 负责。

由于具有选单功能，因此我们可以选择不同的核心来开机。而由于具有控制权转交的功能，因此我们可以载入其他 boot sector 内的 loader 啦！不过 Windows 的 loader 预设不具有控制权转交的功能，因此你不能使用 Windows 的 loader 来载入 Linux 的 loader 喔！这也是为啥第三章谈到 MBR 与多重开机时，会特别强调先装 Windows 再装 Linux 的缘故。 我们将上述的三个功能以底下的图示来解释你就看的懂了！(与第三章的图示也非常类似啦！)

开机管理程式的选单功能与控制权转交功能示意图
图 1.2.2、 开机管理程式的选单功能与控制权转交功能示意图

如上图所示，我的 MBR 使用 Linux 的 grub 这个开机管理程式，并且里面假设已经有了三个选单， 第一个选单可以直接指向 Linux 的核心档案并且直接载入核心来开机；第二个选单可以将开机管理程式控制权交给 Windows 来管理，此时 Windows 的 loader 会接管开机流程，这个时候他就能够启动 windows 了。第三个选单则是使用 Linux 在 boot sector 内的开机管理程式，此时就会跳出另一个 grub 的选单啦！了解了吗？

而最终 boot loader 的功能就是‘载入 kernel 档案’啦！

  • 载入核心侦测硬体与 initrd 的功能

当我们藉由 boot loader 的管理而开始读取核心档案后，接下来， Linux 就会将核心解压缩到主记忆体当中， 并且利用核心的功能，开始测试与驱动各个周边装置，包括储存装置、CPU、网路卡、音效卡等等。 此时 Linux 核心会以自己的功能重新侦测一次硬体，而不一定会使用 BIOS 侦测到的硬体资讯喔！也就是说，核心此时才开始接管 BIOS 后的工作了。 那么核心档案在哪里啊？一般来说，他会被放置到 /boot 里面，并且取名为 /boot/vmlinuz 才对！

[root@www ~]# ls --format=single-column -F /boot
config-2.6.18-92.el5      <==此版本核心被编译时选择的功能与模组设定档
grub/                     <==就是开机管理程式 grub 相关资料目录
initrd-2.6.18-92.el5.img  <==虚拟档案系统档！
System.map-2.6.18-92.el5  <==核心功能放置到记忆体位址的对应表
vmlinuz-2.6.18-92.el5     <==就是核心档案啦！最重要者！

从上表我们也可以知道此版本的 Linux 核心为 2.6.18-92.el5 这个版本！为了硬体开发商与其他核心功能开发者的便利， 因此 Linux 核心是可以透过动态载入核心模组的 (就请想成驱动程式即可)，这些核心模组就放置在 /lib/modules/ 目录内。 由于模组放置到磁碟根目录内 (要记得 /lib 不可以与 / 分别放在不同的 partition ！)， 因此在开机的过程中核心必须要挂载根目录，这样才能够读取核心模组提供载入驱动程式的功能。 而且为了担心影响到磁碟内的档案系统，因此开机过程中根目录是以唯读的方式来挂载的喔。

一般来说，非必要的功能且可以编译成为模组的核心功能，目前的 Linux distributions 都会将他编译成为模组。 因此 USB, SATA, SCSI... 等磁碟装置的驱动程式通常都是以模组的方式来存在的。 现在来思考一种情况，假设你的 linux 是安装在 SATA 磁碟上面的，你可以透过 BIOS 的 INT 13 取得 boot loader 与 kernel 档案来开机，然后 kernel 会开始接管系统并且侦测硬体及尝试挂载根目录来取得额外的驱动程式。

问题是，核心根本不认识 SATA 磁碟，所以需要载入 SATA 磁碟的驱动程式， 否则根本就无法挂载根目录。但是 SATA 的驱动程式在 /lib/modules 内，你根本无法挂载根目录又怎么读取到 /lib/modules/ 内的驱动程式？是吧！非常的两难吧！在这个情况之下，你的 Linux 是无法顺利开机的！ 那怎办？没关系，我们可以透过虚拟档案系统来处理这个问题。

虚拟档案系统 (Initial RAM Disk) 一般使用的档名为 /boot/initrd ，这个档案的特色是，他也能够透过 boot loader 来载入到记忆体中， 然后这个档案会被解压缩并且在记忆体当中模拟成一个根目录， 且此模拟在记忆体当中的档案系统能够提供一支可执行的程式，透过该程式来载入开机过程中所最需要的核心模组， 通常这些模组就是 USB, RAID, LVM, SCSI 等档案系统与磁碟介面的驱动程式啦！等载入完成后， 会帮助核心重新呼叫 /sbin/init 来开始后续的正常开机流程。

BIOS 与 boot loader 及核心载入流程示意图
图 1.2.3、 BIOS 与 boot loader 及核心载入流程示意图

如上图所示，boot loader 可以载入 kernel 与 initrd ，然后在记忆体中让 initrd 解压缩成为根目录， kernel 就能够藉此载入适当的驱动程式，最终释放虚拟档案系统，并挂载实际的根目录档案系统， 就能够开始后续的正常开机流程。更详细的 initrd 说明，你可以自行使用 man initrd 去查阅看看。 底下让我们来了解一下 CentOS 5.x 的 initrd 档案内容有什么吧！ ^_^

# 1. 先将 /boot/initrd 复制到 /tmp/initrd 目录中，等待解压缩：
[root@www ~]# mkdir /tmp/initrd
[root@www ~]# cp /boot/initrd-2.6.18-92.el5.img /tmp/initrd/
[root@www ~]# cd /tmp/initrd
[root@www initrd]# file initrd-2.6.18-92.el5.img
initrd-2.6.18-92.el5.img: gzip compressed data, ...
# 原来是 gzip 的压缩档！因为是 gzip ，所以副档名给他改成 .gz 吧！

# 2. 将上述的档案解压缩：
[root@www initrd]# mv initrd-2.6.18-92.el5.img initrd-2.6.18-92.el5.gz
[root@www initrd]# gzip -d initrd-2.6.18-92.el5.gz
[root@www initrd]# file initrd-2.6.18-92.el5
initrd-2.6.18-92.el5: ASCII cpio archive (SVR4 with no CRC)
# 搞了老半天，原来还是 cpio 的指令压缩成的档案啊！解压缩看看！

# 3. 用 cpio 解压缩
[root@www initrd]# cpio -ivcdu < initrd-2.6.18-92.el5
[root@www initrd]# ll
drwx------ 2 root root    4096 Apr 10 02:05 bin
drwx------ 3 root root    4096 Apr 10 02:05 dev
drwx------ 2 root root    4096 Apr 10 02:05 etc
-rwx------ 1 root root    1888 Apr 10 02:05 init
-rw------- 1 root root 5408768 Apr 10 02:00 initrd-2.6.18-92.el5
drwx------ 3 root root    4096 Apr 10 02:05 lib
drwx------ 2 root root    4096 Apr 10 02:05 proc
lrwxrwxrwx 1 root root       3 Apr 10 02:05 sbin -> bin
drwx------ 2 root root    4096 Apr 10 02:05 sys
drwx------ 2 root root    4096 Apr 10 02:05 sysroot
# 看！是否很像根目录！尤其也是有 init 这个执行档！务必看一下权限！
# 接下来看看 init 这个档案内有啥咚咚？

# 4. 观察 init 档案内较重要的执行项目
[root@www initrd]# cat init
#!/bin/nash                  <==使用类似 bash 的 shell 来执行
mount -t proc /proc /proc    <==挂载记忆体的虚拟档案系统
....(中间省略)....
echo Creating initial device nodes
mknod /dev/null c 1 3        <==建立系统所需要的各项装置！
....(中间省略)....
echo "Loading ehci-hcd.ko module"
insmod /lib/ehci-hcd.ko      <==载入各项核心模组，就是驱动程式！
....(中间省略)....
echo Creating root device.
mkrootdev -t ext3 -o defaults,ro hdc2 <==尝试挂载根目录啦！
....(底下省略)....

嘿嘿！透过上述执行档的内容，我们可以知道 initrd 有载入模组并且尝试挂载了虚拟档案系统。 接下来就能够顺利的运作啦！那么是否一定需要 initrd 呢？

例题：
是否没有 initrd 就无法顺利开机？
答：
不见得的！需要 initrd 最重要的原因是，当开机时无法挂载根目录的情况下， 此时就一定需要 initrd ，例如你的根目录在特殊的磁碟介面 (USB, SATA, SCSI) ， 或者是你的档案系统较为特殊 (LVM, RAID) 等等，才会需要 initrd。

如果你的 Linux 是安装在 IDE 介面的磁碟上，并且使用预设的 ext2/ext3 档案系统， 那么不需要 initrd 也能够顺利的开机进入 Linux 的！

在核心完整的载入后，您的主机应该就开始正确的运作了，接下来，就是要开始执行系统的第一支程式： /sbin/init。

小标题的图示 第一支程式 init 及设定档 /etc/inittab 与 runlevel

在核心载入完毕、进行完硬体侦测与驱动程式载入后，此时你的主机硬体应该已经准备就绪了 (ready) ， 此时核心会主动的呼叫第一支程式，那就是 /sbin/init 啰。这也是为啥第十七章的 pstree 指令介绍时，你会发现 init 的 PID 号码是一号啦。 /sbin/init 最主要的功能就是准备软体执行的环境，包括系统的主机名称、网路设定、语系处理、档案系统格式及其他服务的启动等。 而所有的动作都会透过 init 的设定档，亦即是 /etc/inittab 来规划，而 inittab 内还有一个很重要的设定项目，那就是预设的 runlevel (开机执行等级) 啦！

  • Run level：执行等级有哪些？

那么什么是 run level 呢？他有什么功用啊？其实很简单啦， Linux 就是藉由设定 run level 来规定系统使用不同的服务来启动，让 Linux 的使用环境不同。基本上，依据有无网路与有无 X Window 而将 run level 分为 7 个等级，分别是：

  • 0 - halt (系统直接关机)
  • 1 - single user mode (单人维护模式，用在系统出问题时的维护)
  • 2 - Multi-user, without NFS (类似底下的 runlevel 3，但无 NFS 服务)
  • 3 - Full multi-user mode (完整含有网路功能的纯文字模式)
  • 4 - unused (系统保留功能)
  • 5 - X11 (与 runlevel 3 类似，但加载使用 X Window)
  • 6 - reboot (重新开机)

由于 run level 0, 4, 6 不是关机、重新开机就是系统保留的，所以：‘ 您当然不能将预设的 run level 设定为这三个值 ’， 否则系统就会不断的自动关机或自动重新开机.... 好了，那么我们开机时，到底是如何取得系统的 run level 的？当然是 /etc/inittab 所设定的啰！ 那么 /etc/inittab 到底有什么资讯呢？我们先来看看这个档案的内容好了：

  • /etc/inittab 的内容与语法
[root@www ~]# vim /etc/inittab
id:5:initdefault:                 <==预设的 runlevel 设定, 此 runlevel 为 5

si::sysinit:/etc/rc.d/rc.sysinit  <==准备系统软体执行的环境的脚本执行档

# 7 个不同 run level 的，需要启动的服务的 scripts 放置路径：
l0:0:wait:/etc/rc.d/rc 0    <==runlevel 0 在 /etc/rc.d/rc0.d/
l1:1:wait:/etc/rc.d/rc 1    <==runlevel 1 在 /etc/rc.d/rc1.d/
l2:2:wait:/etc/rc.d/rc 2    <==runlevel 2 在 /etc/rc.d/rc2.d/
l3:3:wait:/etc/rc.d/rc 3    <==runlevel 3 在 /etc/rc.d/rc3.d/
l4:4:wait:/etc/rc.d/rc 4    <==runlevel 4 在 /etc/rc.d/rc4.d/
l5:5:wait:/etc/rc.d/rc 5    <==runlevel 5 在 /etc/rc.d/rc5.d/
l6:6:wait:/etc/rc.d/rc 6    <==runlevel 6 在 /etc/rc.d/rc6.d/

# 是否允许按下 [ctrl]+[alt]+[del] 就重新开机的设定项目：
ca::ctrlaltdel:/sbin/shutdown -t3 -r now

# 底下两个设定则是关于不断电系统的 (UPS)，一个是没电力时的关机，一个是复电的处理
pf::powerfail:/sbin/shutdown -f -h +2 "Power Failure; System Shutting Down"
pr:12345:powerokwait:/sbin/shutdown -c "Power Restored; Shutdown Cancelled"

1:2345:respawn:/sbin/mingetty tty1  <==其实 tty1~tty6 是由底下这六行决定的。
2:2345:respawn:/sbin/mingetty tty2
3:2345:respawn:/sbin/mingetty tty3
4:2345:respawn:/sbin/mingetty tty4
5:2345:respawn:/sbin/mingetty tty5
6:2345:respawn:/sbin/mingetty tty6

x:5:respawn:/etc/X11/prefdm -nodaemon <==X window 则是这行决定的！

让我们解析一下这个档案吧！首先，这个档案的语法是利用冒号 (:) 将设定分隔成为四个栏位，每个栏位的意义与说明如下：

[设定项目]:[run level]:[init 的动作行为]:[指令项目]
  1. 设定项目：最多四个字元，代表 init 的主要工作项目，只是一个简单的代表说明。

  2. run level：该项目在哪些 run level 底下进行的意思。如果是 35 则代表 runlevel 3 与 5 都会执行。

  3. init 的动作项目：主要可以进行的动作项目意义有：
    inittab 设定值 | 意义说明
    initdefault | 代表预设的 run level 设定值
    sysinit | 代表系统初始化的动作项目
    ctrlaltdel | 代表 [ctrl]+[alt]+[del] 三个按键是否可以重新开机的设定
    wait | 代表后面栏位设定的指令项目必须要执行完毕才能继续底下其他的动作
    respawn | 代表后面栏位的指令可以无限制的再生 (重新启动)。举例来说， tty1 的 mingetty 产生的可登入画面， 在你登出而结束后，系统会再开一个新的可登入画面等待下一个登入。
    更多的设定项目请参考 man inittab 的说明。

  4. 指令项目：亦即应该可以进行的指令，通常是一些 script 啰。

  • init 的处理流程

事实上 /etc/inittab 的设定也有点类似 shell script 啦，因为该档案内容的设定也是一行一行的从上往下处理的， 因此我们可以知道 CentOS 的 init 依据 inittab 设定的处理流程会是：

  1. 先取得 runlevel 亦即预设执行等级的相关等级 (以鸟哥的测试机为例，为 5 号)；
  2. 使用 /etc/rc.d/rc.sysinit 进行系统初始化
  3. 由于 runlevel 是 5 ，因此只进行‘l5:5:wait:/etc/rc.d/rc 5’，其他行则略过
  4. 设定好 [ctrl]+[alt]+[del] 这组的组合键功能
  5. 设定不断电系统的 pf, pr 两种机制；
  6. 启动 mingetty 的六个终端机 (tty1 ~ tty6)
  7. 最终以 /etc/X11/perfdm -nodaemon 启动图形介面啦！

现在你可以知道为啥 [ctrl]+[alt]+[del] 可以重新开机而我们预设提供 6 个虚拟终端机 (tty1~tty6) 给你使用了吧！由于整个设定都是依据 /etc/inittab 来决定的，因此如果你想要修改任何细节的话， 可以这样做喔：

  • 如果不想让使用者利用 [crtl]+[alt]+[del] 来重新启动系统，可以将‘ ca::ctrlaltdel:/sbin/shutdown -t3 -r now ’加上注解 (#) 来取消该设定

  • 规定开机的预设 run level 是纯文字的 3 号或者是具有图形介面的 5 号 ，可经由 ‘ id:5:initdefault: ’那个数字来决定！ 以鸟哥自己这个档案为例，我是使用预设的图形介面。如果你想要关闭图形介面的话，将该行 5 改成 3 即可。

  • 如果不想要启动六个终端机 (tty1~tty6)，那么可以将‘ 6:2345:respawn:/sbin/mingetty tty6’关闭数个。但务必至少启动一个喔！

所以说，你现在会自行修改登入时的预设 run level 设定值了吗？够简单的吧？ 一般来说，我们预设都是 3 或者是 5 来作为预设的 run level 的。但有时后可能需要进入 run level 1， 也就是单人维护模式的环境当中。这个 run level 1 有点像是 Windows 系统当中的‘安全模式’啦， 专门用来处理当系统有问题时的操作环境。此外，当系统发现有问题时，举例来说，不正常关机造成 filesystem 的不一致现象时，系统会主动的进入单人维护模式呢！

好了， init 在取得 run level 之后，接下来要干嘛？ 上面 /etc/inittab 档案内容不是有提到 sysinit 吗？准备初始化系统了吧！

小标题的图示 init 处理系统初始化流程 (/etc/rc.d/rc.sysinit)

还记得上面提到 /etc/inittab 里头有这一句‘ si::sysinit:/etc/rc.d/rc.sysinit ’吧？ 这表示：‘我开始载入各项系统服务之前，得先做好整个系统环境，我主要利用 /etc/rc.d/rc.sysinit 这个 shell script 来设定好我的系统环境的。’够清楚了吧？ 所以，我想要知道到底 CentOS 开机的过程当中帮我进行了什么动作，就得要仔细的分析 /etc/rc.d/rc.sysinit 啰。

Tips:
老实说，这个档案的档名在各不同的 distributions 当中都不相同， 例如 SuSE server 9 就使用 /etc/init.d/boot 与 /etc/init.d/rc 来进行的。 所以，你最好还是自行到 /etc/inittab 去察看一下系统的工作喔！ ^_^ 		鸟哥的图示

如果你使用 vim 去查阅过 /etc/rc.d/rc.sysinit 的话，那么可以发现他主要的工作大抵有这几项：

  1. 取得网路环境与主机类型：
    读取网路设定档 /etc/sysconfig/network ，取得主机名称与预设通讯闸 (gateway) 等网路环境。
  2. 测试与挂载记忆体装置 /proc 及 USB 装置 /sys：
    除挂载记忆体装置 /proc 之外，还会主动侦测系统上是否具有 usb 的装置， 若有则会主动载入 usb 的驱动程式，并且尝试挂载 usb 的档案系统。
  3. 决定是否启动 SELinux ：
    我们在第十七章谈到的 SELinux 在此时进行一些检测， 并且检测是否需要帮所有的档案重新编写标准的 SELinux 类型 (auto relabel)。
  4. 启动系统的乱数产生器
    乱数产生器可以帮助系统进行一些密码加密演算的功能，在此需要启动两次乱数产生器。
  5. 设定终端机 (console) 字形：
  6. 设定显示于开机过程中的欢迎画面 (text banner)；
  7. 设定系统时间 (clock) 与时区设定：需读入 /etc/sysconfig/clock 设定值
  8. 周边设备的侦测与 Plug and Play (PnP) 参数的测试：
    根据核心在开机时侦测的结果 (/proc/sys/kernel/modprobe ) 开始进行 ide / scsi / 网路 / 音效 等周边设备的侦测，以及利用以载入的核心模组进行 PnP 装置的参数测试。
  9. 使用者自订模组的载入
    使用者可以在 /etc/sysconfig/modules/*.modules 加入自订的模组，则此时会被载入到系统当中
  10. 载入核心的相关设定：
    系统会主动去读取 /etc/sysctl.conf 这个档案的设定值，使核心功能成为我们想要的样子。
  11. 设定主机名称与初始化电源管理模组 (ACPI)
  12. 初始化软体磁碟阵列：主要是透过 /etc/mdadm.conf 来设定好的。
  13. 初始化 LVM 的档案系统功能
  14. 以 fsck 检验磁碟档案系统：会进行 filesystem check
  15. 进行磁碟配额 quota 的转换 (非必要)：
  16. 重新以可读写模式挂载系统磁碟：
  17. 启动 quota 功能：所以我们不需要自订 quotaon 的动作
  18. 启动系统虚拟乱数产生器 (pseudo-random)：
  19. 清除开机过程当中的暂存档案：
  20. 将开机相关资讯载入 /var/log/dmesg 档案中。

在 /etc/rc.d/rc.sysinit 将基本的系统设定资料都写好了，也将系统的资料设定完整！ 而如果你想要知道到底开机的过程中发生了什么事情呢？那么就执行‘ dmesg ’吧。 另外，基本上，在这个档案当中所进行的很多工作的预设设定档，其实都在 /etc/sysconfig/ 当中呢！ 所以，请记得将 /etc/sysconfig/ 内的档案好好的瞧一瞧喔！ ^_^

在这个过程当中，比较值得注意的是自订模组的载入！在 CentOS 当中，如果我们想要载入核心模组的话， 可以将整个模组写入到 /etc/sysconfig/modules/*.modules 当中，在该目录下， 只要记得档名最后是以 .modules 结尾即可。 这个过程是非必要的，因为我们目前的预设模组实在已经很够用了，除非是您的主机硬体实在太新了， 非要自己载入新的模组不可，否则，在经过 /etc/rc.d/rc.sysinit 的处理后， 你的主机系统应该是已经跑得很顺畅了啦！就等着你将系统相关的服务与网路服务启动啰！

小标题的图示 启动系统服务与相关启动设定档 (/etc/rc.d/rc N & /etc/sysconfig)

载入核心让整个系统准备接受指令来工作，再经过 /etc/rc.d/rc.sysinit 的系统模组与相关硬体资讯的初始化后，你的 CentOS 系统应该已经顺利工作了。 只是，我们还得要启动系统所需要的各项‘服务’啊！这样主机才能提供我们相关的网路或者是主机功能嘛！ 这个时候，依据我们在 /etc/inittab 里面提到的 run level 设定值，就可以来决定启动的服务项目了。 举例来说，使用 run level 3 当然就不需要启动 X Window 的相关服务啰，您说是吧？

那么各个不同的 run level 服务启动的各个 shell script 放在哪？还记得 /etc/inittab 里面提到的：

l0:0:wait:/etc/rc.d/rc 0
l1:1:wait:/etc/rc.d/rc 1
l2:2:wait:/etc/rc.d/rc 2
l3:3:wait:/etc/rc.d/rc 3
l4:4:wait:/etc/rc.d/rc 4
l5:5:wait:/etc/rc.d/rc 5  <==本例中，以此项目来解释
l6:6:wait:/etc/rc.d/rc 6

上面提到的就是各个 run level 要执行的各项脚本放置处啦！主要是透过 /etc/rc.d/rc 这个指令来处理相关任务！ 由于鸟哥使用预设的 runlevel 5 ，因此我们主要针对上述特殊字体那行来解释好了： /etc/rc.d/rc 5 的意义是这样的 (建议您自行使用 vim 去观察一下 /etc/rc.d/rc 这个档案，你会更有概念！)：

  • 透过外部第一号参数 ($1) 来取得想要执行的脚本目录。亦即由 /etc/rc.d/rc 5 可以取得 /etc/rc5.d/ 这个目录来准备处理相关的脚本程式；
  • 找到 /etc/rc5.d/K??* 开头的档案，并进行‘ /etc/rc5.d/K??* stop ’的动作；
  • 找到 /etc/rc5.d/S??* 开头的档案，并进行‘ /etc/rc5.d/S??* start ’的动作；

透过上面的说明我们可以知道所有的项目都与 /etc/rc5.d/ 有关，那么我们就来瞧瞧这个目录下有些什么玩意儿吧！

[root@www ~]# ll /etc/rc5.d/
lrwxrwxrwx 1 root root 16 Sep  4  2008 K02dhcdbd -> ../init.d/dhcdbd
....(中间省略)....
lrwxrwxrwx 1 root root 14 Sep  4  2008 K91capi -> ../init.d/capi
lrwxrwxrwx 1 root root 23 Sep  4  2008 S00microcode_ctl -> ../init.d/microcode_ctl
lrwxrwxrwx 1 root root 22 Sep  4  2008 S02lvm2-monitor -> ../init.d/lvm2-monitor
....(中间省略)....
lrwxrwxrwx 1 root root 17 Sep  4  2008 S10network -> ../init.d/network
....(中间省略)....
lrwxrwxrwx 1 root root 11 Sep  4  2008 S99local -> ../rc.local
lrwxrwxrwx 1 root root 16 Sep  4  2008 S99smartd -> ../init.d/smartd
....(底下省略)....

在这个目录下的档案很有趣，主要具有几个特点：

  • 档名全部以 Sxx 或 Kxx ，其中 xx 为数字，且这些数字在档案之间是有相关性的！
  • 全部是连结档，连结到 stand alone 服务启动的目录 /etc/init.d/ 去

我们在第十八章谈过服务的启动主要是以‘/etc/init.d/服务档名 {start,stop}’来启动与关闭的，那么透过刚刚 /etc/rc.d/rc 程式的解说，我们可以清楚的了解到了 /etc/rc5.d/[SK]xx 其实就是跑到 /etc/init.d/ 去找到相对应的服务脚本， 然后分别进行 start (Sxx) 或 stop (Kxx) 的动作而已啦！举例来说，以上述的表格内的 K91capi 及 S10network 为例好了， 透过 /etc/rc.d/rc 5 的执行，这两个档案会这样进行：

  • /etc/rc5.d/K91capi stop --> /etc/init.d/capi stop
  • /etc/rc5.d/S10network start --> /etc/init.d/network start

所以说，你有想要启动该 runlevel 时就执行的服务，那么利用 Sxx 并指向 /etc/init.d/ 的特定服务启动脚本后， 该服务就能够在开机时启动啦！就这么简单！问题是，你需要自行处理这个 K, S 开头的连结档吗？ 并不需要的，第十八章谈到的 chkconfig 就是在负责处理这个连结档啦！这样有没有跟第十八章的观念串在一起了呢？ ^_^

那么为什么 K 与 S 后面要有数字呢？因为各不同的服务其实还是互有关系的。举例来说，如果要启动 WWW 服务，总是得要有网路吧？所以 /etc/init.d/network 就会比较先被启动啦！那么您就会知道在 S 或者是 K 后面接的数字是啥意思了吧？嘿嘿，那就是执行的顺序啦！那么哪个档案被最后执行呢？ 看到最后一个被执行的项目是啥？没错，就是 S99local ，亦即是： /etc/rc.d/rc.local 这个档案啦！

小标题的图示 使用者自订开机启动程序 (/etc/rc.d/rc.local)

在完成预设 runlevel 指定的各项服务的启动后，如果我还有其他的动作想要完成时，举例来说， 我还想要寄一封 mail 给某个系统管理帐号，通知他，系统刚刚重新开机完毕，那么是否应该要制作一个 shell script 放置在 /etc/init.d/ 里面，然后再以连结方式连结到 /etc/rc5.d/ 里面呢？呵呵！当然不需要！还记得上一小节提到的 /etc/rc.d/rc.local 吧？ 这个档案就可以执行您自己想要执行的系统指令了。

也就是说，我有任何想要在开机时就进行的工作时，直接将他写入 /etc/rc.d/rc.local ， 那么该工作就会在开机的时候自动被载入喔！而不必等我们登入系统去启动呢！ 是否很方便啊！一般来说，鸟哥就很喜欢把自己制作的 shell script 完整档名写入 /etc/rc.d/rc.local ，如此一来，开机就会将我的 shell script 执行过，真是好棒那！

小标题的图示 根据 /etc/inittab 之设定，载入终端机或 X-Window 介面

在完成了系统所有服务的启动后，接下来 Linux 就会启动终端机或者是 X Window 来等待使用者登入啦！ 实际参考的项目是 /etc/inittab 内的这一段：

1:2345:respawn:/sbin/mingetty tty1
2:2345:respawn:/sbin/mingetty tty2
3:2345:respawn:/sbin/mingetty tty3
4:2345:respawn:/sbin/mingetty tty4
5:2345:respawn:/sbin/mingetty tty5
6:2345:respawn:/sbin/mingetty tty6
x:5:respawn:/etc/X11/prefdm -nodaemon

这一段代表，在 run level 2, 3, 4, 5 时，都会执行 /sbin/mingetty 这个咚咚， 而且执行六个，这也是为何我们 Linux 会提供‘六个纯文字终端机’的设定所在啊！ 因为 mingetty 就是在启动终端机的指令说。

要注意的是那个 respawn 的 init 动作项目，他代表‘当后面的指令被终止 (terminal) 时， init 会主动的重新启动该项目。’这也是为何我们登入 tty1 终端机介面后，以 exit 离开后， 系统还是会重新显示等待使用者输入的画面的原因啊！

如果改天您不想要有六个终端机时，可以取消某些终端机介面吗？当然可以啊！ 就将上面表格当中的某些项目注解掉即可！例如不想要 tty5 与 tty6 ，就将那两行注解， 则下次重新开机后，您的 Linux 就只剩下‘ F1 ~ F4 ’有效而已，这样说，可以了解吧！！^_^

至于如果我们使用的是 run level 5 呢？那么除了这六个终端机之外， init 还会执行 /etc/X11/prefdm -nodaemon 那个指令喔！该指令我们会在第二十四章、X Window 再来详谈！ 他主要的功能就是在启动 X Window 啦！

小标题的图示 开机过程会用到的主要设定档

我们在 /sbin/init 的运作过程中有谈到许多执行脚本，包括 /etc/rc.d/rc.sysinit 以及 /etc/rc.d/rc 等等， 其实这些脚本都会使用到相当多的系统设定档，这些开机过程会用到的设定档则大多放置在 /etc/sysconfig/ 目录下。 同时，由于核心还是需要载入一些驱动程式 (核心模组)，此时系统自订的装置与模组对应档 (/etc/modprobe.conf) 就显的挺重要了喔！

  • 关于模组： /etc/modprobe.conf

还记得我们在 /etc/rc.d/rc.sysinit 当中谈到的载入使用者自订模组的地方吗？就是在 /etc/sysconfig/modules/ 目录下啊！ 虽然核心提供的预设模组已经很足够我们使用了，但是，某些条件下我们还是得对模组进行一些参数的规划， 此时就得要使用到 /etc/modprobe.conf 啰！举例来说，鸟哥的 CentOS 主机的 modprobe.conf 有点像这样：

[root@www ~]# cat /etc/modprobe.conf
alias eth0 8139too               <==让 eth0 使用 8139too 的模组
alias scsi_hostadapter pata_sis
alias snd-card-0 snd-trident
options snd-card-0 index=0       <==额外指定 snd-card-0 的参数功能
options snd-trident index=0

这个档案大多在指定系统内的硬体所使用的模组啦！这个档案通常系统是可以自行产生的，所以你不必手动去订正他！ 不过，如果系统捉到错误的驱动程式，或者是你想要使用更新的驱动程式来对应相关的硬体配备时， 你就得要自行手动的处理一下这个档案了。

以上表的第一行为例，鸟哥使用螃蟹卡 (Realtek 的晶片组) 来作为我的网路卡，那螃蟹卡使用的模组就是 8139too 啦！这样看的懂了吧？当我要启动网路卡时，系统会跑到这个档案来查阅一下，然后载入 8139too 驱动程式来驱动网路卡啰！更多的相关说明，请 man modprobe.conf 喔！

  • /etc/sysconfig/*

不说您也知道，整个开机的过程当中，老是读取的一些服务的相关设定档都是记录在 /etc/sysconfig 目录下的！那么该目录底下有些啥玩意儿？我们找几个重要的档案来谈谈：

  • authconfig：
    这个档案主要在规范使用者的身份认证的机制，包括是否使用本机的 /etc/passwd, /etc/shadow 等， 以及 /etc/shadow 密码记录使用何种加密演算法，还有是否使用外部密码伺服器提供的帐号验证 (NIS, LDAP) 等。 系统预设使用 MD5 加密演算法，并且不使用外部的身份验证机制；

  • clock：
    此档案在设定 Linux 主机的时区，可以使用格林威治时间(GMT)，也可以使用台湾的本地时间 (local)。基本上，在 clock 档案内的设定项目‘ ZONE ’所参考的时区位于 /usr/share/zoneinfo 目录下的相对路径中。而且要修改时区的话，还得将 /usr/share/zoneinfo/Asia/Taipei 这个档案复制成为 /etc/localtime 才行！

  • i18n：
    i18n 在设定一些语系的使用方面，例如最麻烦的文字介面下的日期显示问题！ 如果你是以中文安装的，那么预设语系会被选择 zh_TW.UTF8 ，所以在纯文字介面之下， 你的档案日期显示可能就会呈现乱码！这个时候就需要更改一下这里啦！更动这个 i18n 的档案，将里面的 LC_TIME 改成 en 即可！

  • keyboard & mouse：
    keyboard 与 mouse 就是在设定键盘与滑鼠的形式；

  • network：
    network 可以设定是否要启动网路，以及设定主机名称还有通讯闸 (GATEWAY) 这两个重要资讯呢！

  • network-scripts/：
    至于 network-scripts 里面的档案，则是主要用在设定网路卡～ 这部份我们在伺服器架设篇才会提到！

总而言之一句话，这个目录下的档案很重要的啦！开机过程里面常常会读取到的！

小标题的图示 Run level 的切换

在我们完成上面的所有资讯后，其实整个 Linux 主机就已经在等待我们使用者的登入啦！ 但是，相信您应该还是会有一点疑问的地方，那就是：‘我该如何切换 run level 呢？’会不会很难啊？不会啦！很简单～但是依据执行的时间而有不同的方式啊！

事实上，与 run level 有关的启动其实是在 /etc/rc.d/rc.sysinit 执行完毕之后。也就是说，其实 run level 的不同仅是 /etc/rc[0-6].d 里面启动的服务不同而已。不过，依据开机是否自动进入不同 run level 的设定，我们可以说：

  1. 要每次开机都执行某个预设的 run level ，则需要修改 /etc/inittab 内的设定项目， 亦即是‘ id:5:initdefault: ’里头的数字啊；

  2. 如果仅只是暂时变更系统的 run level 时，则使用 init [0-6] 来进行 run level 的变更。 但下次重新开机时，依旧会是以 /etc/inittab 的设定为准。

假设原本我们是以 run level 5 登入系统的，但是因为某些因素，想要切换成为 run level 3 时， 该怎么办呢？很简单啊，执行‘ init 3 ’即可切换。但是 init 3 这个动作到底做了什么呢？ 我们不是说了吗？事实上，不同的 run level 只是载入的服务不同罢了， 亦即是 /etc/rc5.d/ 还有 /etc/rc3.d 内的 Sxxname 与 Kxxname 有差异而已。 所以说，当执行 init 3 时，系统会：

  • 先比对 /etc/rc3.d/ 及 /etc/rc5.d 内的 K 与 S 开头的档案；
  • 在新的 runlevel 亦即是 /etc/rc3.d/ 内有多的 K 开头档案，则予以关闭；
  • 在新的 runlevel 亦即是 /etc/rc3.d/ 内有多的 S 开头档案，则予以启动；

也就是说，两个 run level 都存在的服务就不会被关闭啦！如此一来，就很容易切换 run level 了， 而且还不需要重新开机呢！真方便。那我怎么知道目前的 run level 是多少呢？ 直接在 bash 当中输入 runlevel 即可啊！

[root@www ~]# runlevel
N 5
# 左边代表前一个 runlevel ，右边代表目前的 runlevel。
# 由于之前并没有切换过 runlevel ，因此前一个 runlevel 不存在 (N)

# 将目前的 runlevel 切换成为 3 (注意， tty7 的资料会消失！)
[root@www ~]# init 3
NIT: Sending processes the TERM signal
Applying Intel CPU microcode update:        [  OK  ]
Starting background readahead:              [  OK  ]
Starting irqbalance:                        [  OK  ]
Starting httpd:                             [  OK  ]
Starting anacron:                           [  OK  ]
# 这代表，新的 runlevel 亦即是 runlevel3 比前一个 runlevel 多出了上述 5 个服务

[root@www ~]# runlevel
5 3
# 看吧！前一个是 runlevel 5 ，目前的是 runlevel 3 啦！

那么你能不能利用 init 来进行关机与重新开机呢？可以的啦！利用‘ init 0 ’就能够关机， 而‘ init 6 ’就能够重新开机！为什么？往前翻一下 runlevel 的定义即可了解吧！

大标题的图示 核心与核心模组

谈完了整个开机的流程，您应该会知道，在整个开机的过程当中，是否能够成功的驱动我们主机的硬体配备， 是核心 (kernel) 的工作！而核心一般都是压缩档，因此在使用核心之前，就得要将他解压缩后， 才能载入主记忆体当中。

另外，为了应付日新月异的硬体，目前的核心都是具有‘可读取模组化驱动程式’的功能， 亦即是所谓的‘ modules (模组化)’的功能啦！所谓的模组化可以将他想成是一个‘外挂程式’， 该外挂程式可能由硬体开发厂商提供，也有可能我们的核心本来就支援～不过，较新的硬体， 通常都需要硬体开发商提供驱动程式模组啦！

那么核心与核心模组放在哪？

  • 核心： /boot/vmlinuz 或 /boot/vmlinuz-version；
  • 核心解压缩所需 RAM Disk： /boot/initrd (/boot/initrd-version)；
  • 核心模组： /lib/modules/version/kernel 或 /lib/modules/$(uname -r)/kernel；
  • 核心原始码： /usr/src/linux (要安装才会有！否则预设不安装的！)

如果该核心被顺利的载入系统当中了，那么就会有几个资讯纪录下来：

  • 核心版本： /proc/version
  • 系统核心功能： /proc/sys/kernel

问题来啦，如果我有个新的硬体，偏偏我的作业系统不支援，该怎么办？很简单啊！

  • 重新编译核心，并加入最新的硬体驱动程式原始码；
  • 将该硬体的驱动程式编译成为模组，在开机时载入该模组

上面第一点还很好理解，反正就是重新编译核心就是了。不过，核心编译很不容易啊！ 我们会在后续章节约略介绍核心编译的整个程序。比较有趣的则是将该硬体的驱动程式编译成为模组啦！ 关于编译的方法，可以参考后续的第二十二章、原始码与 tarball的介绍。 我们这个章节仅是说明一下，如果想要载入一个已经存在的模组时，该如何是好？

小标题的图示 核心模组与相依性

既然要处理核心模组，自然就得要了解了解我们核心提供的模组之间的相关性啦！ 基本上，核心模组的放置处是在 /lib/modules/$(uname -r)/kernel 当中，里面主要还分成几个目录：

arch	：与硬体平台有关的项目，例如 CPU 的等级等等；
crypto	：核心所支援的加密的技术，例如 md5 或者是 des 等等；
drivers	：一些硬体的驱动程式，例如显示卡、网路卡、PCI 相关硬体等等；
fs	：核心所支援的 filesystems ，例如 vfat, reiserfs, nfs 等等；
lib	：一些函式库；
net	：与网路有关的各项协定资料，还有防火墙模组 (net/ipv4/netfilter/*) 等等；
sound	：与音效有关的各项模组；

如果要我们一个一个的去检查这些模组的主要资讯，然后定义出他们的相依性， 我们可能会疯掉吧！所以说，我们的 Linux 当然会提供一些模组相依性的解决方案啰～ 对啦！那就是检查 /lib/modules/$(uname -r)/modules.dep 这个档案啦！他记录了在核心支援的模组的各项相依性。

那么这个档案如何建立呢？挺简单！利用 depmod 这个指令就可以达到建立该档案的需求了！

[root@www ~]# depmod [-Ane]
选项与参数：
-A  ：不加任何参数时， depmod 会主动的去分析目前核心的模组，并且重新写入
      /lib/modules/$(uname -r)/modules.dep 当中。若加入 -A 参数时，则 depmod
      会去搜寻比 modules.dep 内还要新的模组，如果真找到新模组，才会更新。
-n  ：不写入 modules.dep ，而是将结果输出到荧幕上(standard out)；
-e  ：显示出目前已载入的不可执行的模组名称

范例一：若我做好一个网路卡驱动程式，档名为 a.ko，该如何更新核心相依性？
[root@www ~]# cp a.ko /lib/modules/$(uname -r)/kernel/drivers/net
[root@www ~]# depmod

以上面的范例一为例，我们的 Linux kernel 2.6.x 版本的核心模组副档名一定是 .ko 结尾的， 当你使用 depmod 之后，该程式会跑到模组标准放置目录 /lib/modules/$(uname -r)/kernel ， 并依据相关目录的定义将全部的模组捉出来分析，最终才将分析的结果写入 modules.dep 档案中的呐！ 这个档案很重要喔！因为他会影响到本章稍后会介绍的 modprobe 指令的应用！

小标题的图示 核心模组的观察

那你到底晓不晓得目前核心载入了多少的模组呢？粉简单啦！利用 lsmod 即可！

[root@www ~]# lsmod
Module                  Size  Used by
autofs4                24517  2
hidp                   23105  2
....(中间省略)....
8139too                28737  0
8139cp                 26305  0
mii                     9409  2 8139too,8139cp <==mii 还被 8139cp, 8139too 使用
....(中间省略)....
uhci_hcd               25421  0  <==底下三个是 USB 相关的模组！
ohci_hcd               23261  0
ehci_hcd               33357  0

使用 lsmod 之后，系统会显示出目前已经存在于核心当中的模组，显示的内容包括有：

  • 模组名称(Module)；
  • 模组的大小(size)；
  • 此模组是否被其他模组所使用 (Used by)。

也就是说，模组其实真的有相依性喔！举上表为例， mii 这个模组会被 8139too 所使用。 简单的说，就是‘当你要载入 8139too 时，需要先载入 mii 这个模组才可以顺利的载入 8139too’的意思。 那么除了显示出目前的模组外，我还可以查阅每个模组的资讯吗？举例来说，我们知道 8139too 是螃蟹卡的驱动程式，那么 mii 是什么咚咚？就用 modinfo 来观察吧！

[root@www ~]# modinfo [-adln] [module_name|filename]
选项与参数：
-a  ：仅列出作者名称；
-d  ：仅列出该 modules 的说明 (description)；
-l  ：仅列出授权 (license)；
-n  ：仅列出该模组的详细路径。

范例一：由上个表格当中，请列出 mii 这个模组的相关资讯：
[root@www ~]# modinfo mii
filename:       /lib/modules/2.6.18-92.el5/kernel/drivers/net/mii.ko
license:        GPL
description:    MII hardware support library
author:         Jeff Garzik <jgarzik@pobox.com>
srcversion:     16DCEDEE4B5629C222C352D
depends:
vermagic:       2.6.18-92.el5 SMP mod_unload 686 REGPARM 4KSTACKS gcc-4.1
# 可以看到这个模组的来源，以及该模组的简易说明！(是硬体支援函式库)

范例二：我有一个模组名称为 a.ko ，请问该模组的资讯为？
[root@www ~]# modinfo a.ko
....(省略)....

事实上，这个 modinfo 除了可以‘查阅在核心内的模组’之外，还可以检查‘某个模组档案’， 因此，如果你想要知道某个档案代表的意义为何，利用 modinfo 加上完整档名吧！ 看看就晓得是啥玩意儿啰！ ^_^

小标题的图示 核心模组的载入与移除

好了，如果我想要自行手动载入模组，又该如何是好？有很多方法啦，最简单而且建议的，是使用 modprobe 这个指令来载入模组， 这是因为 modprobe 会主动的去搜寻 modules.dep 的内容，先克服了模组的相依性后， 才决定需要载入的模组有哪些，很方便。至于 insmod 则完全由使用者自行载入一个完整档名的模组， 并不会主动的分析模组相依性啊！

[root@www ~]# insmod [/full/path/module_name] [parameters]

范例一：请尝试载入 cifs.ko 这个‘档案系统’模组
[root@www ~]# insmod /lib/modules/$(uname -r)/kernel/fs/cifs/cifs.ko
[root@www ~]# lsmod | grep cifs
cifs                  212789  0

他立刻就将该模组载入啰～但是 insmod 后面接的模组必须要是完整的‘档名’才行！那如何移除这个模组呢？

[root@www ~]# rmmod [-fw] module_name
选项与参数：
-f  ：强制将该模组移除掉，不论是否正被使用；
-w  ：若该模组正被使用，则 rmmod 会等待该模组被使用完毕后，才移除他！

范例一：将刚刚载入的 cifs 模组移除！
[root@www ~]# rmmod cifs

范例二：请载入 vfat 这个‘档案系统’模组
[root@www ~]# insmod /lib/modules/$(uname -r)/kernel/fs/vfat/vfat.ko
insmod: error inserting '/lib/modules/2.6.18-92.el5/kernel/fs/vfat/vfat.ko':
-1 Unknown symbol in module
# 无法载入 vfat 这个模组啊！伤脑筋！

使用 insmod 与 rmmod 的问题就是，你必须要自行找到模组的完整档名才行，而且如同上述范例二的结果， 万一模组有相依属性的问题时，你将无法直接载入或移除该模组呢！所以近年来我们都建议直接使用 modprobe 来处理模组载入的问题，这个指令的用法是：

[root@www ~]# modprobe [-lcfr] module_name
选项与参数：
-c  ：列出目前系统所有的模组！(更详细的代号对应表)
-l  ：列出目前在 /lib/modules/`uname -r`/kernel 当中的所有模组完整档名；
-f  ：强制载入该模组；
-r  ：类似 rmmod ，就是移除某个模组啰～

范例一：载入 cifs 模组
[root@www ~]# modprobe cifs
# 很方便吧！不需要知道完整的模组档名，这是因为该完整档名已经记录到
# /lib/modules/`uname -r`/modules.dep 当中的缘故啊！如果要移除的话：
[root@www ~]# modprobe -r cifs

使用 modprobe 真的是要比 insmod 方便很多！因为他是直接去搜寻 modules.dep 的纪录， 所以啰，当然可以克服模组的相依性问题，而且还不需要知道该模组的详细路径呢！ 好方便！ ^_^

例题：
尝试使用 modprobe 载入 vfat 这个模组，并且观察该模组的相关模组是哪个？
答：
我们使用 modprobe 来载入，再以 lsmod 来观察与 grep 撷取关键字看看：
[root@www ~]# modprobe vfat
[root@www ~]# lsmod | grep vfat
vfat                   15809  0
fat                    51165  1 vfat <==原来就是 fat 这个模组啊！

[root@www ~]# modprobe -r vfat <==测试完移除此模组

小标题的图示 核心模组的额外参数设定： /etc/modprobe.conf

这个档案我们之前已经谈过了，这里只是再强调一下而已，如果您想要修改某些模组的额外参数设定， 就在这个档案内设定吧！我们假设一个案例好了，假设我的网路卡 eth0 是使用 ne ， 但是 eth1 同样也使用 ne ，为了避免同一个模组会导致网路卡的错乱， 因此，我可以先找到 eth0 与 eth1 的 I/O 与 IRQ ，假设：

  • eth0 ： I/O (0x300) 且 IRQ=5
  • eth1 ： I/O (0x320) 且 IRQ=7

则：

[root@www ~]# vi /etc/modprobe.conf
alias eth0 ne
alias eth1 ne
options eth0 io=0x300 irq=5
options eth1 io=0x320 irq=7

嘿嘿！如此一来，我的 Linux 就不会捉错网路卡的对应啰！因为被我强制指定某个 I/O 咯嘛！ ^_^

大标题的图示 Boot Loader: Grub

在看完了前面的整个开机流程，以及核心模组的整理之后，你应该会发现到一件事情， 那就是‘ boot loader 是载入核心的重要工具’啊！没有 boot loader 的话，那么 kernel 根本就没有办法被系统载入的呢！所以，底下我们会先谈一谈 boot loader 的功能， 然后再讲一讲现阶段 Linux 里头最主流的 grub 这个 boot loader 吧！

小标题的图示 boot loader 的两个 stage

我们在第一小节开机流程的地方曾经讲过，在 BIOS 读完资讯后，接下来就是会到第一个开机装置的 MBR 去读取 boot loader 了。这个 boot loader 可以具有选单功能、直接载入核心档案以及控制权移交的功能等， 系统必须要有 loader 才有办法载入该作业系统的核心就是了。但是我们都知道， MBR 是整个硬碟的第一个 sector 内的一个区块，充其量整个大小也才 446 bytes 而已。 我们的 loader 功能这么强，光是程式码与设定资料不可能只占不到 446 bytes 的容量吧？那如何安装？

为了解决这个问题，所以 Linux 将 boot loader 的程式码执行与设定值载入分成两个阶段 (stage) 来执行：

  • Stage 1：执行 boot loader 主程式：
    第一阶段为执行 boot loader 的主程式，这个主程式必须要被安装在开机区，亦即是 MBR 或者是 boot sector 。但如前所述，因为 MBR 实在太小了，所以，MBR 或 boot sector 通常仅安装 boot loader 的最小主程式， 并没有安装 loader 的相关设定档；

  • Stage 2：主程式载入设定档：
    第二阶段为透过 boot loader 载入所有设定档与相关的环境参数档案 (包括档案系统定义与主要设定档 menu.lst)， 一般来说，设定档都在 /boot 底下。

那么这些设定档是放在哪里啊？这些与 grub 有关的档案都放置到 /boot/grub 中，那我们就来看看有哪些档案吧！

[root@www ~]# ls -l /boot/grub
-rw-r--r--  device.map              <==grub 的装置对应档(底下会谈到)
-rw-r--r--  e2fs_stage1_5           <==ext2/ext3 档案系统之定义档
-rw-r--r--  fat_stage1_5            <==FAT 档案系统之定义档
-rw-r--r--  ffs_stage1_5            <==FFS 档案系统之定义档
-rw-------  grub.conf               <==grub 在 Red Hat 的设定档
-rw-r--r--  iso9660_stage1_5        <==光碟机档案系统定义档
-rw-r--r--  jfs_stage1_5            <==jfs 档案系统定义档
lrwxrwxrwx  menu.lst -> ./grub.conf <==其实 menu.lst 才是设定档！
-rw-r--r--  minix_stage1_5          <==minix 档案系统定义档
-rw-r--r--  reiserfs_stage1_5       <==reiserfs 档案系统定义档
-rw-r--r--  splash.xpm.gz           <==开机时在 grub 底下的背景图示
-rw-r--r--  stage1                  <==stage 1 的相关说明
-rw-r--r--  stage2                  <==stage 2 的相关说明
-rw-r--r--  ufs2_stage1_5           <==UFS 的档案系统定义档
-rw-r--r--  vstafs_stage1_5         <==vstafs 档案系统定义档
-rw-r--r--  xfs_stage1_5            <==xfs 档案系统定义档

从上面的说明你可以知道 /boot/grub/ 目录下最重要的就是设定档 (menu.lst) 以及各种档案系统的定义！ 我们的 loader 读取了这种档案系统定义资料后，就能够认识档案系统并读取在该档案系统内的核心档案啰。 至于 grub 的设定档档名，其实应该是 menu.lst 的，只是在 Red Hat 里面被定义成为 /boot/grub.conf 而已。 鸟哥建议您还是记忆 menu.lst 比较好喔！

所以从上面的档案来看， grub 认识的档案系统真的非常多喔！正因为如此，所以 grub 才会取代 Lilo 这个老牌的 boot loader 嘛！好了，接下来就来瞧瞧设定档内有啥设定值吧！

小标题的图示 grub 的设定档 /boot/grub/menu.lst 与选单类型

grub 是目前使用最广泛的 Linux 开机管理程式，旧的 Lilo 这个开机管理程式现在已经很少见了， 所以本章才会将 Lilo 的介绍舍弃的说。grub 的优点挺多的，包括有：

  • 认识与支援较多的档案系统，并且可以使用 grub 的主程式直接在档案系统中搜寻核心档名；
  • 开机的时候，可以‘自行编辑与修改开机设定项目’，类似 bash 的指令模式；
  • 可以动态搜寻设定档，而不需要在修改设定档后重新安装 grub 。亦即是我们只要修改完 /boot/grub/menu.lst 里头的设定后，下次开机就生效了！

上面第三点其实就是 Stage 1, Stage 2 分别安装在 MBR (主程式) 与档案系统当中 (设定档与定义档) 的原因啦！ 好了，接下来，让我们好好了解一下 grub 的设定档： /boot/grub/menu.lst 这玩意儿吧！ 要注意喔，那个 lst 是 LST 的小写，不要搞错啰！

  • 硬碟与分割槽在 grub 中的代号

安装在 MBR 的 grub 主程式，最重要的任务之一就是从磁碟当中载入核心档案， 以让核心能够顺利的驱动整个系统的硬体。所以啰， grub 必须要认识硬碟才行啊！那么 grub 到底是如何认识硬碟的呢？ 嘿嘿！ grub 对硬碟的代号设定与传统的 Linux 磁碟代号可完全是不同的！grub 对硬碟的识别使用的是如下的代号：

(hd0,0)

够神了吧？跟 /dev/hda1 风马牛不相干～怎么办啊？其实只要注意几个东西即可，那就是：

  • 硬碟代号以小括号 ( ) 包起来；
  • 硬碟以 hd 表示，后面会接一组数字；
  • 以‘搜寻顺序’做为硬碟的编号，而不是依照硬碟排线的排序！(这个重要！)
  • 第一个搜寻到的硬碟为 0 号，第二个为 1 号，以此类推；
  • 每颗硬碟的第一个 partition 代号为 0 ，依序类推。

所以说，第一颗‘搜寻到的硬碟’代号为：‘(hd0)’，而该颗硬碟的第一号分割槽为‘(hd0,0)’，这样说了解了吧？ 反正你要记得，在 grub 里面，他开始的数字是 0 而不是 1 就是了！

Tips:
在较旧的主机板上面，通常第一颗硬碟会插在 IDE 1 的 master 上，就会是 /dev/hda，所以常常我们可能会误会 /dev/hda 就是 (hd0)，其实不是喔！要看你的 BIOS 设定值才行！有的主机板 BIOS 可以调整开机的硬碟搜寻顺序，那么就要注意了，因为 grub 的硬碟代号可能会跟着改变呐！留意留意！ 		鸟哥的图示

所以说，整个硬碟代号为：

硬碟搜寻顺序 | 在 Grub 当中的代号
第一颗 | (hd0) (hd0,0) (hd0,1) (hd0,4)....
第二颗 | (hd1) (hd1,0) (hd1,1) (hd1,4)....
第三颗 | (hd2) (hd2,0) (hd2,1) (hd2,4)....

这样应该比较好看出来了吧？第一颗硬碟的 MBR 安装处的硬碟代号就是‘(hd0)’， 而第一颗硬碟的第一个分割槽的 boot sector 代号就是‘(hd0,0)’第一颗硬碟的第一个逻辑分割槽的 boot sector 代号为‘(hd0,4)’了了吧！

例题：
假设你的系统仅有一颗 SATA 硬碟，请说明该硬碟的第一个逻辑分割槽在 Linux 与 grub 当中的档名与代号：
答：
因为是 SATA 磁碟，加上使用逻辑分割槽，因此 Linux 当中的档名为 /dev/sda5 才对 (1~4 保留给 primary 与 extended 使用)。 至于 grub 当中的磁碟代号则由于仅有一颗磁碟，因此代号会是‘ (hd0,4) ’才对。

  • /boot/grub/menu.lst 设定档：

了解了 grub 当中最麻烦的硬碟代号后，接下来，我们就可以瞧一瞧设定档的内容了。先看一下鸟哥的 CentOS 内的 /boot/grub/menu.lst 好了：

[root@www ~]# vim /boot/grub/menu.lst
default=0     <==预设开机选项，使用第 1 个开机选单 (title)
timeout=5     <==若 5 秒内未动键盘，使用预设选单开机
splashimage=(hd0,0)/grub/splash.xpm.gz <==背景图示所在的档案
hiddenmenu    <==读秒期间是否显示出完整的选单画面(预设隐藏)
title CentOS (2.6.18-92.el5)    <==第一个选单的内容
        root (hd0,0)
        kernel /vmlinuz-2.6.18-92.el5 ro root=LABEL=/1 rhgb quiet
        initrd /initrd-2.6.18-92.el5.img

在 title 以前的四行，都是属于 grub 的整体设定，包括预设的等待时间与预设的开机项目， 还有显示的画面特性等等。至于 title 后面才是指定开机的核心档案或者是 boot loader 控制权。 在整体设定方面的项目主要常见的有：

  • default=0
    这个必须要与 title 作为对照，在设定档里面有几个 title ，开机的时候就会有几个选单可以选择。 由于 grub 启始号码为 0 号，因此 default=0 代表使用‘第一个 title 项目’来开机的意思。 default 的意思是，如果在读秒时间结束前都没有动到键盘， grub 预设使用此 title 项目 (在此为 0 号) 来开机。

  • timeout=5
    开机时会进行读秒，如果在 5 秒钟内没有按下任何按键，就会使用上面提到的 default 后面接的那个 title 项目来开机的意思。如果你觉得 5 秒太短，那可以将这个数值调大 (例如 30 秒) 即可。此外，如果 timeout=0 代表直接使用 default 值进行开机而不读秒，timeout=-1 则代表直接进入选单不读秒了！

  • splashimage=(hd0,0)/grub/splash.xpm.gz
    有没有发现你的 CentOS 在开机的时候背景不是黑白而是有色彩变化的呢？那就是这个档案提供的背景图示啦(注3)！不过这个档案的实际路径写法怎么会是这样啊？很简单啊～上述的意思是：在 (hd0,0) 这个分割槽内的最顶层目录中，底下的 grub/splash.xpm.gz 那个档案的意思。 由于鸟哥将 /boot 这个目录独立成为 /dev/hda1 ，因此这边就会写成‘在 /dev/hda1 里面的 grub/splash.xpm.gz ’的意思啦！想一想，如果你的 /boot 目录并没有独立成为一个分割槽， 这里会写成如何？

  • hiddenmenu
    这个说的是，开机时是否要显示选单？目前 CentOS 预设是不要显示选单， 如果您想要显示选单，那就将这个设定值注解掉！

整体设定的地方大概是这样，而底下那个 title 则是显示开机的设定项目。如同前一小节提到的，开机时可以选择 (1)直接指定核心档案开机或 (2)将 boot loader 控制权转移到下个 loader (此过程称为 chain-loader)。每个 title 后面接的是‘该开机项目名称的显示’，亦即是在选单出现时，选单上面的名称而已。 那么这两种方式的设定有啥不同呢？

  1. 直接指定核心开机

    既然要指定核心开机，所以当然要找到核心档案啦！此外，有可能还需要用到 initrd 的 RAM Disk 设定档。但是如前说的， 尚未开机完成，所以我们必须要以 grub 的硬碟识别方式找出完整的 kernel 与 initrd 档名才行。 因此，我们可能需要有底下的方式来设定才行！
    1. 先指定核心档案放置的 partition，再读取档案 (目录树)，
   最后才加入档案的实际档名与路径 (kernel 与 initrd)；
   鸟哥的 /boot 为 /dev/hda1 ，因此核心档案的设定则成为：
root    (hd0,0)          <==代表核心档案放在那个 partition 当中
kernel  /vmlinuz-2.6.18-92.el5 ro root=LABEL=/1 rhgb quiet
initrd  /initrd-2.6.18-92.el5.img
    上面的 root, kernel, initrd 后面接的参数的意义说明如下：

    root ：代表的是‘核心档案放置的那个 partition 而不是根目录’喔！不要搞错了！ 以鸟哥的案例来说，我的根目录为 /dev/hda2 而 /boot 独立为 /dev/hda1 ，因为与 /boot 有关， 所以磁碟代号就会成为 (hd0,0) 啰。

    kernel ：至于 kernel 后面接的则是核心的档名，而在档名后面接的则是核心的参数。 由于开机过程中需要挂载根目录，因此 kernel 后面接的那个 root=LABEL=/1 指的是‘Linux 的根目录在哪个 partition ’的意思。 还记得第八章谈过的 LABEL 挂载功能吧？ 是的，这里使用 LABEL 来挂载根目录。至于 rhgb 为色彩显示而 quiet 则是安静模式 (荧幕不会输出核心侦测的资讯)。

    initrd ：就是前面提到的 initrd 制作出 RAM Disk 的档案档名啦！
    2. 直接指定 partition 与档名，不需要额外指定核心档案所在装置代号
kernel  (hd0,0)/vmlinuz-2.6.18-92.el5 ro root=LABEL=/1 rhgb quiet
initrd  (hd0,0)/initrd-2.6.18-92.el5.img
    老实说，鸟哥比较喜欢这种样式的档名写法，因为这样我们就能够知道核心档案是在哪个装置内的某个档名， 而不会去想到我们的根目录 (/, root) 啦！让我们来想想 /boot 有独立分割与无独立分割的情况吧！

    例题：
    我的系统分割是： /dev/hda1 (/), /dev/hda2 (swap) 而已，且我的核心档案为 /boot/vmlinuz，请问 grub 的 menu.lst 内该如何撰写核心档案位置？
    答：
    我们使用叠代的方式来了解一下好了。由于核心档名为 /boot/vmlinuz，转成装置档名与代号会成为如下的过程：
    原始档案：  /boot/vmlinuz ↓
Linux 装置：(/dev/hda1)/boot/vmlinuz ↓
grub  装置：(hd0,0)/boot/vmlinuz
    所以最终的 kernel 写法会变成：
    kernel (hd0,0)/boot/vmlinuz root=/dev/hda1 ...

    例题：
    同上，只是我的分割情况变成： /dev/sda1 (/boot), /dev/sda5 (/) 时？
    答：
    由于 /boot 被独立出来了，所以情况会不一样喔！如下所示：
    原始档案：  /boot/vmlinuz ↓
Linux 装置：(/dev/sda1)/vmlinuz ↓
grub  装置：(hd0,0)/vmlinuz
    所以最终的 kernel 写法会变成：
    kernel (hd0,0)/vmlinuz root=/dev/sda5 ...

  2. 利用 chain loader 的方式转交控制权

    所谓的 chain loader (开机管理程式的链结) 仅是在将控制权交给下一个 boot loader 而已， 所以 grub 并不需要认识与找出 kernel 的档名 ，‘ 他只是将 boot 的控制权交给下一个 boot sector 或 MBR 内的 boot loader 而已 ’ 所以通常他也不需要去查验下一个 boot loader 的档案系统！

    一般来说， chain loader 的设定只要两个就够了，一个是预计要前往的 boot sector 所在的分割槽代号， 另一个则是设定 chainloader 在那个分割槽的 boot sector (第一个磁区) 上！假设我的 Windows 分割槽在 /dev/hda1 ，且我又只有一颗硬碟，那么要 grub 将控制权交给 windows 的 loader 只要这样就够了：
    [root@www ~]# vi /boot/grub/menu.lst
....前略....
title Windows partition
    root (hd0,0)    <==设定使用此分割槽
    chainloader +1  <== +1 可以想成第一个磁区，亦即是 boot sector
    上面的范例中，我们可以很简单的这样想：那个 (hd0,0) 就是 Windows 的 C 槽所在磁碟， 而 chainloader +1 就是让系统载入该分割槽当中的第一个磁区 (就是 boot sector) 内的开机管理程式。 不过，由于 Windows 的开机碟需要设定为活化 (active) 状态，且我们的 grub 预设会去检验该分割槽的档案系统。 因此我们可以重新将上面的范例改写成这样：
    [root@www ~]# vi /boot/grub/menu.lst
....前略....
title Windows partition
    rootnoverify (hd0,0)   <==不检验此分割槽
    chainloader +1
    makeactive             <==设定此分割槽为开机碟(active)
    grub 的功能还不止此，他还能够隐藏某些分割槽。举例来说，我的 /dev/hda5 是安装 Linux 的分割槽， 我不想让 Windows 能够认识这个分割槽时，你可以这样做：
    [root@www ~]# vi /boot/grub/menu.lst
....前略....
title Windows partition
    hide (hd0,4)           <==隐藏 (hd0,4) 这个分割槽
    rootnoverify (hd0,0)
    chainloader +1
    makeactive
小标题的图示 initrd 的重要性与建立新 initrd 档案

我们在本章稍早之前‘ boot loader 与 kernel 载入’的地方已经提到过 initrd 这玩意儿，他的目的在于提供开机过程中所需要的最重要核心模组，以让系统开机过程可以顺利完成。 会需要 initrd 的原因，是因为核心模组放置于 /lib/modules/$(uname -r)/kernel/ 当中， 这些模组必须要根目录 (/) 被挂载时才能够被读取。但是如果核心本身不具备磁碟的驱动程式时， 当然无法挂载根目录，也就没有办法取得驱动程式，因此造成两难的地步。

initrd 可以将 /lib/modules/.... 内的‘开机过程当中一定需要的模组’包成一个档案 (档名就是 initrd)， 然后在开机时透过主机的 INT 13 硬体功能将该档案读出来解压缩，并且 initrd 在记忆体内会模拟成为根目录， 由于此虚拟档案系统 (Initial RAM Disk) 主要包含磁碟与档案系统的模组，因此我们的核心最后就能够认识实际的磁碟， 那就能够进行实际根目录的挂载啦！所以说：‘initrd 内所包含的模组大多是与开机过程有关，而主要以档案系统及硬碟模组 (如 usb, SCSI 等) 为主’的啦！

一般来说，需要 initrd 的时刻为：

  • 根目录所在磁碟为 SATA、USB 或 SCSI 等连接介面；
  • 根目录所在档案系统为 LVM, RAID 等特殊格式；
  • 根目录所在档案系统为非传统 Linux 认识的档案系统时；
  • 其他必须要在核心载入时提供的模组。
Tips:
之前鸟哥忽略 initrd 这个档案的重要性，是因为鸟哥很穷... ^_^。因为鸟哥的 Linux 主机都是较早期的硬体， 使用的是 IDE 介面的硬碟，而且并没有使用 LVM 等特殊格式的档案系统，而 Linux 核心本身就认识 IDE 介面的磁碟， 因此不需要 initrd 也可以顺利开机完成的。自从 SATA 硬碟流行起来后，没有 initrd 就没办法开机了！ 因为 SATA 硬碟使用的是 SCSI 模组来驱动的，而 Linux 预设将 SCSI 功能编译成为模组.... 		鸟哥的图示

一般来说，各 distribution 提供的核心都会附上 initrd 档案，但如果你有特殊需要所以想重制 initrd 档案的话， 可以使用 mkinitrd 来处理的。这个档案的处理方式很简单， man mkinitrd 就知道了！ ^_^。 我们还是简单的介绍一下去！

[root@www ~]# mkinitrd [-v] [--with=模组名称] initrd档名 核心版本
选项与参数：
-v  ：显示 mkinitrd 的运作过程
--with=模组名称：模组名称指的是模组的名字而已，不需要填写档名。举例来说，
       目前核心版本的 ext3 档案系统模组为底下的档名：
       /lib/modules/$(uname -r)/kernel/fs/ext3/ext3.ko
       那你应该要写成： --with=ext3 就好了 (省略 .ko)
initrd档名：你所要建立的 initrd 档名，尽量取有意义又好记的名字。
核心版本  ：某一个核心的版本，如果是目前的核心则是‘ $(uname -r) ’

范例一：以 mkinitrd 的预设功能建立一个 initrd 虚拟磁碟档案
[root@www ~]# mkinitrd -v initrd_$(uname -r) $(uname -r)
Creating initramfs
Looking for deps of module ehci-hcd
Looking for deps of module ohci-hcd
....(中间省略)....
Adding module ehci-hcd  <==最终加入 initrd 的就是底下的模组
Adding module ohci-hcd
Adding module uhci-hcd
Adding module jbd
Adding module ext3
Adding module scsi_mod
Adding module sd_mod
Adding module libata
Adding module pata_sis

[root@www ~]# ll initrd_*
-rw------- 1 root root 2406443 Apr 30 02:55 initrd_2.6.18-92.el5
# 由于目前的核心版本可使用 uname -r 取得，因此鸟哥使用较简单的指令来处理啰～
# 此时 initrd 会被建立起来，你可以将他移动到 /boot 等待使用。

范例二：增加 8139too 这个模组的 initrd 档案
[root@www ~]# mkinitrd -v --with=8139too initrd_vbirdtest $(uname -r)
....(前面省略)....
Adding module mii
Adding module 8139too  <==看到没！这样就加入了！

initrd 建立完成之后，同时核心也处理完毕后，我们就可以使用 grub 来建立选单了！底下继续瞧一瞧吧！

小标题的图示 测试与安装 grub

如果你的 Linux 主机本来就是使用 grub 作为 loader 的话，那么你就不需要重新安装 grub 了， 因为 grub 本来就会主动去读取设定档啊！您说是吧！但如果你的 Linux 原来使用的并非 grub ， 那么就需要来安装啦！如何安装呢？首先，你必须要使用 grub-install 将一些必要的档案复制到 /boot/grub 里面去，你应该这样做的：

Tips:
安装些什么呢？因为 boot loader 有两个 stage ，而设定档得要放置到适当的地方。 这个 grub-install 就是在安装设定档 (包括档案系统定义档与 menu.lst 等等) 而已！ 如果要将 grub 的 stage1 主程式安装起来，就得要使用 grub shell 的功能喔！本章稍后会介绍。 		鸟哥的图示
[root@www ~]# grub-install [--root-directory=DIR] INSTALL_DEVICE
选项与参数：
--root-directory=DIR 那个 DIR 为实际的目录，使用 grub-install 预设会将
  grub 所有的档案都复制到 /boot/grub/* ，如果想要复制到其他目录与装置去，
  就得要用这个参数。
INSTALL_DEVICE 安装的装置代号啦！

范例一：将 grub 安装在目前系统的 MBR 底下，我的系统为 /dev/hda：
[root@www ~]# grub-install /dev/hda
# 因为原本 /dev/hda 就是使用 grub ，所以似乎不会出现什么特别的讯息。
# 如果去查阅一下 /boot/grub 的内容，会发现所有的档案都更新了，因为我们重装了！

范例二：我的 /home 为独立的 /dev/hda3 ，如何安装 grub 到 /dev/hda3 (boot sector)
[root@www ~]# grub-install --root-directory=/home /dev/hda3
Probing devices to guess BIOS drives. This may take a long time.
Installation finished. No error reported.
This is the contents of the device map /home/boot/grub/device.map.
Check if this is correct or not. If any of the lines is incorrect,
fix it and re-run the script `grub-install'.

(fd0)   /dev/fd0
(hd0)   /dev/hda   <==会给予装置代号的对应表！

[root@www ~]# ll /home/boot/grub/
-rw-r--r-- 1 root root     30 Apr 30 11:12 device.map
-rw-r--r-- 1 root root   7584 Apr 30 11:12 e2fs_stage1_5
....(底下省略)....
# 看！档案都安装进来了！但是注意到，我们并没有设定档喔！那要自己建立！

所以说， grub-install 是安装 grub 相关的档案 (例如档案系统定义档) 到你的装置上面去等待在开机时被读取，但还需要设定好设定档 (menu.lst) 后，再以 grub shell 来安装 grub 主程式到 MBR 或者是 boot sector 上面去喔！好了，那我们来思考一下想要安装的资料。

例题：
我预计开机时要直接显示选单，且选单倒数为 30 秒。另外，在原本的 menu.lst 当中新增三个开机选单，分别如下说明：
  1. 假设 /dev/hda1 内含有 boot loader ，此 loader 如何取得控制权？
  2. 如何重新读取 MBR 内的 loader ？
  3. 利用你原本的系统核心档案，建立一个可强制进入单人维护模式的选单
答：
第一点很简单，就利用上一小节的说明来处理即可。至于第二点，MBR 的读取读的是整颗硬碟的第一个磁区， 因此 root (hd0) 才是对的。第三点则与核心的后续参数有关。整个档案可以被改写成这样：
[root@www ~]# vim /boot/grub/menu.lst
default=0
timeout=30
splashimage=(hd0,0)/grub/splash.xpm.gz
#hiddenmenu
title CentOS (2.6.18-92.el5)
        root (hd0,0)
        kernel /vmlinuz-2.6.18-92.el5 ro root=LABEL=/1 rhgb quiet
        initrd /initrd-2.6.18-92.el5.img
title /dev/hda1 boot sector  <==本例中的第一个新增选单
        root (hd0,0)
        chainloader +1
title MBR loader             <==新增的第二个选单
        root (hd0)           <==MBR 为整颗磁碟的第一个磁区，所以用整颗磁碟的代号
        chainloader +1
title single user mode       <==新增的第三个选单(其实由原本的title复制来的)
        root (hd0,0)
        kernel /vmlinuz-2.6.18-92.el5 ro root=LABEL=/1 rhgb quiet single
        initrd /initrd-2.6.18-92.el5.img
下次开机时，你就会发现有四个选单可以选择，而预设会以第一个选单来开机喔！

我们已经将设定档处理完毕，但是你要知道的是，我们并不知道 /dev/hda1 到底有没有包含 grub 的主程式， 因此我们想要将 grub 主程式再次的安装到 /dev/hda1 的 boot sector ，也想要重新安装 grub 到 MBR 上面去。 此时我们就得要使用 grub shell 啰！整个安装与 grub shell 的动作其实很简单， 如果您有兴趣研究的话，可以使用 info grub 去查阅～鸟哥这里仅介绍几个有用的指令而已。

  • 用‘ root (hdx,x) ’选择含有 grub 目录的那个 partition 代号；
  • 用‘ find /boot/grub/stage1 ’看看能否找到安装资讯档案；
  • 用‘ find /boot/vmlinuz ’看看能否找到 kernel file (不一定要成功！)；
  • 用‘ setup (hdx,x) ’或‘ setup (hdx) ’将 grub 安装在 boot sector 或 MBR；
  • 用‘ quit ’来离开 grub shell ！

由于我们最需要安装的就是那个 stage1 啦！那才是 grub 的主程式嘛！而且设定档通常与主程式摆在同一个目录下。 因此我们需要使用 root (hd0,0) 去找到 /boot/grub/stage1 喔！接下来，请用 grub 来进入 grub shell 吧！进入 grub 后，会出现一个‘ grub> ’的提示字元啊！

[root@www ~]# grub

# 1. 先设定一下含有 grub 目录的那个 partition 啊！
grub> root (hd0,0)
 Filesystem type is ext2fs, partition type 0x83
# 鸟哥主机的分割中，/boot/grub 在 /boot 的分割槽，亦即是 /dev/hda1 内喔！
# 另外， grub 也能够分辨出该分割槽的档案系统 (ext2)。

# 2. 搜寻一下，是否存在 stage1 这个资讯档案？
grub> find /boot/grub/stage1
 (hd0,2)
# 见鬼！怎么会只有一个！我们明明有 /boot/grub 与 /home/boot/grub 啊！
# 因为 /boot 是独立的，因此要找到该档名就得要用如下的方式：

grub> find /grub/stage1
 (hd0,0)
# 这样就能够找到啰！要特别注意 grub 找到不是目录树，而是装置内的档案。

# 3. 搜寻一下是否可以找到核心？ /boot/vmlinuz-2.6.18-92.el5 ？
grub> find /boot/vmlinuz-2.6.18-92.el5
Error 15: File not found
grub> find /vmlinuz-2.6.18-92.el5
 (hd0,0)
# 再次强调，因为 /boot/ 是独立的，因此就会变成上头的模样啰！

# 4. 将主程式安装上去吧！安装到 MBR 看看！
grub> setup (hd0)
 Checking if "/boot/grub/stage1" exists... no <==因为 /boot 是独立的
 Checking if "/grub/stage1" exists... yes     <==所以这个档名才是对的！
 Checking if "/grub/stage2" exists... yes
 Checking if "/grub/e2fs_stage1_5" exists... yes
 Running "embed /grub/e2fs_stage1_5 (hd0)"...  15 sectors are embedded.
succeeded
 Running "install /grub/stage1 (hd0) (hd0)1+15 p (hd0,0)/grub/stage2
/grub/grub.conf"... succeeded  <==将 stage1 程式安装妥当啰！
Done.
# 很好！确实有装起来～这样 grub 就在 MBR 当中了！

# 5. 那么重复安装到我的 /dev/hda1 呢？亦即是 boot sector 当中？
grub> setup (hd0,0)
 Checking if "/boot/grub/stage1" exists... no
 Checking if "/grub/stage1" exists... yes
 Checking if "/grub/stage2" exists... yes
 Checking if "/grub/e2fs_stage1_5" exists... yes
 Running "embed /grub/e2fs_stage1_5 (hd0,0)"... failed (this is not fatal)
 Running "embed /grub/e2fs_stage1_5 (hd0,0)"... failed (this is not fatal)
 Running "install /grub/stage1 (hd0,0) /grub/stage2 p /grub/grub.conf "...
succeeded
Done.
# 虽然无法将 stage1_5 安装到 boot sector 去，不过，还不会有问题，
# 重点是最后面那个 stage1 要安装后，显示 succeeded 字样就可以了！

grub> quit

如此一来，就已经将 grub 安装到 MBR 及 /dev/hda1 的 boot sector 里面去了！ 而且读取的是 (hd0,0) 里面的 /grub/menu.lst 那个档案喔！真是很重要啊！重要到不行！

最后总结一下：

  1. 如果是从其他 boot loader 转成 grub 时，得先使用 grub-install 安装 grub 设定档；
  2. 开始编辑 menu.lst 这个重要的设定档；
  3. 透过 grub 来将主程式安装到系统中，如 MBR 的 (hd0) 或 boot sector 的 (hd0,0) 等等。
小标题的图示 开机前的额外功能修改

事实上，上一个小节设定好之后，你的 grub 就已经在你的 Linux 系统上面了，而且同时存在于 MBR 与 boot sector 当中呢！所以，我们已经可以重新开机来查阅看看啦！ 另外，如果你正在进行开机，那么请注意，我们可以在预设选单 (鸟哥的范例当中是 30 秒) 按下任意键， 还可以进行 grub 的‘线上编修’功能喔！真是棒啊！先来看看开机画面吧！

grub 开机画面示意图
图 3.5.1、grub 开机画面示意图

由于鸟哥将隐藏选单的功能取消了，因此你会直接看到这四个选单，同时会有读秒的咚咚在倒数。 选单部分的画面其实就是 title 后面的文字啦！你现在知道如何修改 title 后面的文字了吧！ ^_^。 如果你使用上下键去选择第二 (/dev/hda1 boot sector) 或第三 (MBR loader) 时，会发现同样的画面重复出现！ 这是因为那两个是 loader 移交而已嘛！而我们都使用相同的 grub 与相同的 menu.lst 设定档！ 因此这个画面就会重复出现了！这样了解乎？

另外，如果你再仔细看的话，会发现到上图中底部还有一些细部的选项，似乎有个 'e' edit 的样子！ 没错～ grub 支援线上编修指令喔！这是个很有用的功能！假如刚刚你将 menu.lst 的内容写错了，导致出现无法开机的问题时， 我们可以查阅该 title 选单的内容并加以修改喔！举例来说，我想要知道第一个选单的实际内容时，将反白光棒移动到第一个选单， 再按下 'e' 会进入如下画面：

grub 单一选单内容
图 3.5.2、grub 单一选单内容

哈哈！这不就是我们在 menu.lst 里面设定的东西吗？没错！此时你还可以继续进一步修改喔！ 注意看到上图最底下的说明，你还可以使用：

  • e：进入 grub shell 的编辑画面；
  • o：在游标所在行底下再新增一行；
  • d：将游标所在行删除。

我们说过， grub 是可以直接使用核心档案来开机的，所以，如果您很清楚的知道你的根目录 (/) 在那个 partition ，而且知道你的核心档案档名 (通常都会有个 /boot/vmlinuz 连结到正确的档名)， 那么直接在图三的画面当中，以上述的 o, d, e 三个按键来编修，成为类似底下这样：

grub edit 的线上编修功能
图 3.5.3、grub edit 的线上编修功能

按下 [Enter] 按键后，然后输入 b 来 boot ，就可以开机啦！所以说，万一你的 /boot/grub/menu.lst 设定错误，或者是因为安装的缘故，或者是因为核心档案的缘故，导致无法顺利开机时，记得啊，可以在 grub 的选单部分， 使用 grub shell 的方式去查询 (find) 或者是直接指定核心档案，就能够开机啦！ ^_^

另外，很多时候我们的 grub 可能会发生错误，导致‘连 grub 都无法启动’，那么根本就无法使用 grub 的线上编修功能嘛！怎么办？没关系啊！我们可以利用具有 grub 开机的 CD 来开机， 然后再以 CD 的 grub 的线上编修，嘿嘿！同样可以使用硬碟上面的核心档案来开机啦！很好玩吧！ ^_^

小标题的图示 关于核心功能当中的 vga 设定

事实上，你的 tty1~tty6 除了 80x24 的解析度外，还能够有其他解析度的支援喔！但前提之下是你的核心必须支援 FRAMEBUFFER_CONSOLE 这个核心功能选项才行。如何确定有没有支援呢？你可以查阅 /boot/config-2.6.18-92.el5 这个档案，然后这样搜寻：

[root@www ~]# grep 'FRAMEBUFFER_CONSOLE' /boot/config-2.6.18-92.el5
CONFIG_FRAMEBUFFER_CONSOLE=y
# 这个项目如果出现 y 那就是有支援啦！如果被注解或是 n ，那就是没支援啦！

那么如何调整 tty1 ~ tty6 终端机的解析度呢？先参考底下的表格再说 (此为十进位数值)：

彩度\解析度 | 640x480 | 800x600 | 1024x768 | 1280x1024 | bit
256 | 769 | 771 | 773 | 775 | 8 bit
32768 | 784 | 787 | 790 | 793 | 15 bit
65536 | 785 | 788 | 791 | 794 | 16 bit
16.8M | 786 | 789 | 792 | 795 | 32 bit

假设你想要将你的终端机荧幕解析度调整到 1024x768 ，且色彩深度为 15bit 色的时候，就得要指定 vga=790 那个数字！ 举例来说，鸟哥的 tty1 就想要这样的解析度时，你可以这样做：

[root@www ~]# vim /boot/grub/menu.lst
....(前面省略)....
title CentOS (2.6.18-92.el5)
        root (hd0,0)
        kernel /vmlinuz-2.6.18-92.el5 ro root=LABEL=/1 rhgb quiet vga=790
        initrd /initrd-2.6.18-92.el5.img
....(后面省略)....

重新开机并选择此选单进入 Linux，你跑到 tty1 去看看，嘿嘿！就已经是 1024x768 的解析度啰！ 只是字会变的很小，但是画面的范围会加大就是了。不过，某些版本支援的是 16 进位制，所以还需要修改一下格式呢！ 一般使用上表当中的值应该就可以了。不过，由于不同的作业系统与硬体可能会有不一样的情况，因此， 上面的值不见得一定可以在您的机器上面测试成功，建议您可以分别设定看看哩～以找出可以使用的值！ ^_^

小标题的图示 BIOS 无法读取大硬碟的问题

现今的硬碟容量越来越大，如果你使用旧的主机板来安插大容量硬碟时，可能由于系统 BIOS 或者是其他问题， 导致 BIOS 无法判断该硬碟的容量，此时你的系统读取可能会有问题。为什么呢？

我们在本章一开始的开机流程讲过，当进入 Linux 核心功能后，他会主动的再去侦测一下整个系统， 因此 BIOS 捉不到的硬体在 Linux 核心反而可能会可以捉到而正常使用。举例来说，过去很多朋友常常会发现， ‘我的系统使用 DVD 开机安装时，可以顺利的安装好 Linux ，但是第一次开机时， 荧幕只出现黑压压的一片，且出现 grub> 的字样，而无法进入 Linux 系统中’，这又是怎么一回事？

  • 在安装的过程中，由于是使用 DVD 或 CD 开机，因此载入 Linux 核心不成问题，而核心会去侦测系统硬体，因此可以捉到 BIOS 捉不到的硬碟，此时你确实可以安装 Linux 在大容量的硬碟上，且不会出现任何问题。

  • 但是在进入硬碟开机时，由于 kernel 与 initrd 档案都是透过 BIOS 的 INT 13 通道读取的， 因此你的 kernel 与 initrd 如果放置在 BIOS 无法判断的磁区中，当然就无法被系统载入，而仅会出现 grub shell (grub>) 等待你的处理而已。

更多 grub 错误的代码查询可以到底下的连结查阅：

  • http://orgs.man.ac.uk/documentation/grub/grub_toc.html#SEC_Contents

现在你知道问题所在啦！那就是 BIOS 无法读取大容量磁碟内的 kernel 与 initrd 档案。 那如何解决呢？很简单啦！就让 kernel 与 initrd 档案放置在大硬碟的最前头，由于 BIOS 至少可以读到大磁碟的 1024 磁柱内的资料，因此就能够读取核心与虚拟档案系统的档案啰。那如何让 kernel 与 initrd 放置到整颗硬碟的最前面呢？简单的要命吧！就建立 /boot 独立分割槽，并将 /boot 放置到最前面即可！更多其他的解决方案可参考文后的延伸阅读(注4)

万一你已经安装了 Linux 且发生了上述的问题，那该怎办？你可以这样作的：

  • 最简单的做法，就是直接重灌，并且制作出 /boot 挂载的 partition ，同时确认该 partition 是在 1024 cylinder 之前才行。

  • 如果实在不想重灌，没有关系，利用我们刚刚上头提到的 grub 功能，额外建立一个可开机软碟， 或者是直接以光碟机开机，然后以 grub 的编写能力进入 Linux 。

  • 另外的办法其实是骗过 BIOS ，直接将硬碟的 cylinder, head, sector 等等资讯直接写到 BIOS 当中去，如此一来你的 BIOS 可能就可以读得到与支援的到你的大硬碟了。

不过，鸟哥还是建议您可以重新安装，并且制作出 /boot 这个 partition 啦！ ^_^！这也是为啥这次更版中， 鸟哥特别强调要分割出 /boot 这个分割槽的原因啊！

小标题的图示 为个别选单加上密码

想像一个环境，如果你管理的是一间电脑教室，这间电脑教室因为可对外开放，但是你又担心某些 partition 被学生不小心的弄乱，因此你可能会想要将某些开机选单作个保护。这个时候，为每个选单作个加密的密码就是个可行的方案啦！ 那如何在开机的过程里面提供密码保护呢？首先，你必须要建立密码，而且还需要是加密过后的喔！ 否则人家跑到 /boot/grub/menu.lst 不就可以探查到你的开机密码了？那如何建立加密的密码呢？ 我们可以透过 grub 提供的 md5 编码来处理的，如下所示：

[root@www ~]# grub-md5-crypt
Password: <==输入密码
Retype password: <==再输入一次
$1$kvlI0/$byrbNgkt/.REKPQdfg287. <==这就是产生的 md5 密码！

上面产生的最后一行，由 $ 开始到 . 结束的那行，就是你的密码经过 md5 编码过后的咚咚！ 将这个密码复制下来吧！假设我们要将第一个选项加入这个密码，而第四个选项加入另外的密码， 那你应该要这样做：

[root@www ~]# vim /boot/grub/menu.lst
....(前面省略)....
title CentOS (2.6.18-92.el5)
        password --md5 $1$kvlI0/$byrbNgkt/.REKPQdfg287.
        root (hd0,0)
        kernel /vmlinuz-2.6.18-92.el5 ro root=LABEL=/1 rhgb quiet vga=790
        initrd /initrd-2.6.18-92.el5.img
....(中间省略)....
title single user mode
        password --md5 $1$GFnI0/$UuiZc/7snugLtVN4J/WyM/
        root (hd0,0)
        kernel /vmlinuz-2.6.18-92.el5 ro root=LABEL=/1 rhgb quiet single
        initrd /initrd-2.6.18-92.el5.img

上表的案例中，我们两个选单进入的密码并不相同，可以进行同学的分类啦！不过这样也造成一个问题， 那就是一定要输入密码才能够进入开机流程，如果你在远端使用 reboot 重新开机，并且主机前面并没有任何人的话.... 你的主机并不会主动进入开机程序喔！ ^_^

你必须要注意的是：password 这个项目一定要在 title 底下的第一行。 不过，此项功能还是可能被破解的，因为使用者可以透过编辑模式 (e) 进入选单，并删除密码栏位并按下 b 就能够进行开机流程了！真糟糕！那怎办？只好透过整体的 password (放在所有的 title 之前) ， 然后在 title 底下的第一行设定 lock ，那使用者想要编辑时，也得要输入密码才行啊！设定有点像这样：

[root@www ~]# vim /boot/grub/menu.lst
default=0
timeout=30
password --md5 $1$kvlI0/$byrbNgkt/.REKPQdfg287.  <==放在整体设定处
splashimage=(hd0,0)/grub/splash.xpm.gz
#hiddenmenu
title CentOS (2.6.18-92.el5)
        lock  <==多了锁死的功能
        root (hd0,0)
        kernel /vmlinuz-2.6.18-92.el5 ro root=LABEL=/1 rhgb quiet vga=790
        initrd /initrd-2.6.18-92.el5.img

那么重新开机后，画面会像这样：

grub 加密的示意图
图 3.8.1、 grub 加密的示意图

你可以看到最下方仅出现 p 的功能，由于 2, 3, 4 选单并没有使用 lock ，因此这三个选单使用者还是可以执行开机程序， 但是第一个选单由于有 lock 项目，因此除非你输入正确的密码，否则第一个选单是无法被载入执行的。 另外，这个项目也能够避免你的 menu.lst 在开机的过程中被乱改，是具有保密 menu.lst 的功能啦！ 与刚刚的选单密码功能不同。

大标题的图示 开机过程的问题解决

很多时候，我们可能因为做了某些设定，或者是因为不正常关机 (例如未经通知的停电等等) 而导致系统的 filesystem 错乱，此时，Linux 可能无法顺利开机成功，那怎么办呢？难道要重灌？当然不需要啦！ 进入 run level 1 (单人维护模式) 去处理处理，应该就 OK 的啦！底下我们就来谈一谈如何处理几个常见的问题！

小标题的图示 忘记 root 密码的解决之道

大家都知道鸟哥的记忆力不佳，容易忘东忘西的，那如果连 root 的密码都忘记了，怎么办？ 其实在 Linux 环境中 root 密码忘记时还是可以救回来的！只要能够进入并且挂载 / ， 然后重新设定一下 root 的密码，就救回来啦！这是因为开机流程中，若强制核心进入 runlevel 1 时， 预设是不需要密码即可取得一个 root 的 shell 来救援的。整个动作有点像这样：

  1. 重新开机！一定要重新开机！怎么重开都没关系；

  2. 在开机进入 grub 选单后， (1)在你要进入的选单上面点 'e' 进入详细设定； (2)将光棒移动到 kernel 上方并点 'e' 进入编辑画面； (3)然后出现如下画面来处理：
    grub edit> kernel /vmlinuz-2.6.18-92.el5 ro root=LABEL=/ rhgb quiet single
    重点就是那个特殊字体的咚咚啦！按下 [enter] 再按下 b 就能够开机进入单人维护模式了。

  3. 进入单人维护模式后，系统会以 root 的权限直接给你一个 shell ，此时你就能够执行‘ passwd ’这个指令来重建 root 的密码啦！然后直接‘ init 5 ’就可以切换成为 X 视窗介面啰！就是这么简单。
小标题的图示 init 设定档错误

前一个 root 密码挽救的方法其实可以用在很多地方，唯一一个无法挽救的情况，那就是 /etc/inittab 这个档案设定错误导致的无法开机！根据开机流程，我们知道 runlevel 0~6 都会读取 /etc/inittab 设定档， 因此你使用 single mode (runlevel 1) 当然也是要读取 /etc/inittab 来进行开机的。那既然无法进入单人维护模式， 就表示这题无解啰？非也非也，既然预设的 init 无法执行，那我们就告诉核心不要执行 init ，改呼叫 bash 啊！ 可以略过 init 吗？可以的，同样在开机进入 grub 后，同样在 grub edit 的情况下这样做：

grub edit> kernel /vmlinuz-2.6.18-92.el5 ro root=LABEL=/ rhgb quiet init=/bin/bash

因为我们指定了核心呼叫的第一支程式 (init) 变成 /bin/bash，因此 /sbin/init 就不会被执行。 又根据开机流程的说明，我们知道此时虽然可以利用 root 取得 bash 来工作，但此时 (1)除了根目录外，其他的目录都没有被挂载； (2)根目录被挂载成为唯读状态。因此我们还需要进行一些动作才行！如下所示：

直接进入 bash 的环境
图 4.2.1、 略过 init 的程序，直接进入 bash shell

鸟哥仅下达两个指令，‘ mount -o remount,rw / ’用途是将根目录重新挂载成为可读写，至于‘ mount -a ’则是参考 /etc/fstab 的内容重新挂载档案系统！ 此时你又可以开机进行救援的工作了！只是救援完毕后，你得要使用‘ reboot ’重新开机一次才行！

小标题的图示 BIOS 磁碟对应的问题 (device.map)

由于目前硬碟很便宜啊，所以很多朋友就想说：‘那我能不能将 Windows 安装在 /dev/hda 而 Linux 安装在 /dev/hdb ， 然后调整 BIOS 的开机装置顺序，如此则两套系统各有各的 loader 安装在个别硬碟的 MBR 当中了！’。 这个想法非常好，如此一来两者就不会互相干扰，因为每颗磁碟的 MBR 个别有不同作业系统的 loader 嘛！ 问题是，grub 对磁碟的装置代号使用的是侦测到的顺序啊！ 也就是说，你调整了 BIOS 磁碟开机顺序后，你的 menu.lst 内的装置代号就可能会对应到错误的磁碟上了！啊！真想哭！

没关系的，我们可以透过 /boot/grub/device.map 这个档案来写死每个装置对 grub 磁碟代号的对应喔！ 举例来说，鸟哥的这个档案内容如下：

[root@www ~]# cat /boot/grub/device.map
(fd0)   /dev/fd0
(hd0)   /dev/hda

如果你不清楚如何处理的话，也可以利用 grub-install 的功能喔！例如：

[root@www ~]# grub-install --recheck /dev/hda1

这样 device.map 就会主动的被更新了！这样了解乎？

小标题的图示 因档案系统错误而无法开机

如果因为设定错误导致无法开机时，要怎么办啊？这就更简单了！最容易出错的设定而导致无法顺利开机的步骤，通常就是 /etc/fstab 这个档案了，尤其是使用者在实作 Quota 时，最容易写错参数， 又没有经过 mount -a 来测试挂载，就立刻直接重新开机，真要命！无法开机成功怎么办？ 这种情况的问题大多如下面的画面所示：

档案系统错误的示意图
图 4.4.1、 档案系统错误的示意图

看到最后两行，他说可以输入 root 的密码继续加以救援喔！那请输入 root 的密码来取得 bash 并以 mount -o remount,rw / 将根目录挂载成可读写后，继续处理吧！其实会造成上述画面可能的原因除了 /etc/fstab 编辑错误之外，如果你曾经不正常关机后，也可能导致档案系统不一致 (Inconsistent) 的情况， 也有可能会出现相同的问题啊！如果是磁区错乱的情况，请看到上图中的第二行处， fsck 告知其实是 /dev/md0 出错， 此时你就应该要利用 fsck 去检测 /dev/md0 才是！等到系统发现错误，并且出现‘clear [Y/N]’时，输入‘ y ’吧！

这个 fsck 的过程可能会很长，而且如果你的 partition 上面的 filesystem 有过多的资料损毁时， 即使 fsck 完成后，可能因为伤到系统槽，导致某些关键系统档案资料的损毁，那么依旧是无法进入 Linux 的。此时，就好就是将系统当中的重要资料复制出来，然后重新安装，并且检验一下， 是否实体硬碟有损伤的现象才好！不过一般来说，不太可能会这样啦～ 通常都是 fsck 处理完毕后，就能够顺利再次进入 Linux 了。

小标题的图示 利用 chroot 切换到另一颗硬碟工作

仔细检查一下，你的 Linux 里面应该会有一个名为 chroot 的指令才对！这是啥？ 这是‘ change root directory ’的意思啦！意思就是说，可以暂时将根目录移动到某个目录下， 然后去处理某个问题，最后再离开该 root 而回到原本的系统当中。

举例来说，补习班中心最容易有两三个 Linux 系统在同一个主机上面，假设我的第一个 Linux 无法进入了，那么我可以使用第二个 Linux 开机，然后在第二个 Linux 系统下将第一个 Linux 挂载起来， 最后用 chroot 变换到第一个 Linux ，就能够进入到第一个 Linux 的环境当中去处理工作了。

你同样也可以将你的 Linux 硬碟拔到另一个 Linux 主机上面去，然后用这个 chroot 来切换， 以处理你的硬碟问题啊！那怎么做啊？粉简单啦！

  1. 用尽任何方法，进入一个完整的 Linux 系统 ( run level 3 或 5 )；

  2. 假设有问题的 Linux 磁碟在 /dev/hdb1 上面，且他整个系统的排列是：
        挂载点   装置档名
    /     → /dev/hdb1
    /var  → /dev/hdb2
    /home → /dev/hdb3
    /usr  → /dev/hdb5
    若如此的话，那么在我目前的这个 Linux 底下，我可以建立一个目录，然后可以这样做：
        挂载点           装置档名
    /chroot/      → /dev/hdb1
    /chroot/var/  → /dev/hdb2
    /chroot/home/ → /dev/hdb3
    /chroot/usr/  → /dev/hdb5
  3. 全部挂载完毕后，再输入‘ chroot /chroot ’嘿嘿！你就会发现，怎么根目录 (/) 变成那个 /dev/hdb1 的环境啦！这样说明，了了吗？ ^_^
大标题的图示 重点回顾
  • Linux 不可随意关机，否则容易造成档案系统错乱或者是其他无法开机的问题；
  • 开机流程主要是：BIOS、MBR、Loader、kernel+initrd、/sbin/init 等流程
  • Loader 具有提供选单、载入核心档案、转交控制权给其他 loader 等功能。
  • boot loader 可以安装在 MBR 或者是每个分割槽的 boot sector 区域中
  • initrd 可以提供核心在开机过程中所需要的最重要的模组，通常与磁碟及档案系统有关的模组；
  • init 的设定档为 /etc/initab ，此档案内容可以设定预设 runlevle、系统初始化脚本、不同执行等级的服务启动等；
  • 额外的装置与模组对应，可写入 /etc/modprobe.conf 中；
  • 核心模组的管理可使用 lsmod, modinfo, rmmod, insmod, modprobe 等指令；
  • modprobe 主要参考 /lib/modules/$(uanem -r)/modules.dep 的设定来载入与卸载核心模组；
  • grub 的设定档与相关档案系统定义档大多放置于 /boot/grub 目录中，设定档名为 menu.lst
  • grub 对磁碟的代号设定与 Linux 不同，主要透过侦测的顺序来给予设定。如 (hd0) 及 (hd0,0) 等。
  • menu.lst 内每个选单与 titile 有关，而直接指定核心开机时，至少需要 kernel 及 initrd 两个项目
  • menu.lst 内设定 loader 控制权移交时，最重要者为 chainloader +1 这个项目。
  • 若想要重建 initrd ，可使用 mkinitrd 处理
  • 重新安装 grub 到 MBR 或 boot sector 时，可以利用 grub shell 来处理。
  • 若想要进入救援模式，可于开机选单过程中，在 kernel 的项目后面加入‘ single ’或‘ init=/bin/bash ’等方式来进入救援模式。
  • 我们可以对 grub 的个别选单给予不同的密码。
大标题的图示 本章习题
( 要看答案请将滑鼠移动到‘答：’底下的空白处，按下左键圈选空白处即可察看 )
  • 情境模拟题一：利用救援光碟来处理系统的错误导致无法开机的问题。

    • 目标：了解救援光碟的功能；
    • 前提：了解 grub 的原理，并且知道如何使用 chroot 功能；
    • 需求：打字可以再加快一点啊！ ^_^

    这个部分鸟哥就不捉图了，请大家自行处理啰～假设你的系统出问题而无法顺利开机，此时拿出原版光碟，然后重新以光碟来启动你的系统。 然后你应该要这样作的：

    1. 利用光碟开机时，到了看到 boot: 的阶段，按下 [F5] 之后会看到可以输入的选项，此时请输入：
      boot: linux rescue
      就能够进入救援模式的侦测了！

    2. 然后请选择语系与键盘对应，这个与安装过程是一模一样啦！所以选择‘ English ’与‘ us ’即可！

    3. 接下来会问你是否需要启动网路，因为我们的系统是出问题要处理，所以不需要启动网路啦！选择‘ No’即可；

    4. 然后就进入救援光碟模式的档案系统搜寻了！这个救援光碟会去找出目前你的主机里面与 CentOS 5.x 相关的作业系统， 并将该作业系统汇整成为一个 chroot 的环境等待你的处置！但是他会有三个模式可以选择，分别是‘continue’继续成为可读写挂载； ‘Read-Only’将侦测到的作业系统变成唯读挂载；‘Skip’略过这次的救援动作。在这里我们选择‘ Continue ’吧！

    5. 然后系统会将侦测到的资讯通知你！一般来说，可能会在荧幕上显示类似这样的讯息：‘ chroot /mnt/sysimage’此时请按下 OK 吧！

    6. 按下 OK 后，系统会丢给你一个 shell 使用，先用 df 看一下挂载情况是否正确？ 若不正确请手动挂载其他未被挂载的 partition 。等到一切搞定后，利用 chroot /mnt/sysimage 来转成你原本的作业系统环境吧！等到你将一切出问题的地方都搞定，请 reboot 系统，且取出光碟，用硬碟开机吧！
简答题部分：
  • 如何察看与修改 runlevel 呢？
    察看很简单，只要输入‘ runlevel ’就可以得知。而如果要修改目前的 runlevel ， 可以直接输入 init [level] 例如要去到 runlevel 3 可以：‘ init 3 ’即可。 如果想要每次开机都设定固定的 runlevel ，那么可以修改 /etc/inittab 这个档案！ 将里面这一行改成：‘id:3:initdefault:’即可。
  • 我有个朋友跟我说，他想要让一个程式在 Linux 系统下一开机就启动，但是在关机前会自动的先结束该程式，我该怎么建议他？
    由于 /etc/rc.d/rc[0-6].d 里面有的 Sxxname 与 Kxxname 可以设定开机启动与关机结束的事项！所以我就可以轻易的写一个 script 放在 /etc/rc.d/init.d 里面，并连结到我的 run-level 里头，就可以让他自由自在的启动与结束了！
  • 万一不幸，我的一些模组没有办法让 Linux 的核心捉到，但是偏偏这个核心明明就有支援该模组， 我要让该模组在开机的时候就被载入，那么应该写入那个档案？
    应该写入 /etc/modprobe.conf (kernel 2.6.x) 或者是 /etc/modules.conf (kernel 2.4.x) 这个档案，他是模组载入相关的地方呢！当然，也可以写入 /etc/sysconfig/modules/* 里面。
  • 如何在 grub 开机过程当中，指定以‘ run level 1 ’来开机？
    在开机进入 boot loader 之后，利用 grub shell 的功能，亦即输入‘ e ’进入编辑模式， 然后在 kernel 后面增加：
    kernel (hd0,0)/boot/vmlinuz ro root=/dev/hda1 .... single
    那个 single 也可以改成 1 ，就能够进入。同样的，若使用 lilo 时，按下 tab 按键后， 输入
    label_name -s
    就能够进入 run level 1 啰！
  • 由于一些无心之过，导致系统开机时，只要执行 init 就会产生错误而无法继续开机， 我们知道可以在开机的时候，不要以 init 载入系统，可以转换第一支执行程式， 假设我第一支执行程式想要改为 /bin/bash ，好让我自行维护系统(不同于 run level 1 喔！)， 该如何进行此一工作？
    在开机的过程当中，进入 lilo 或 grub 的画面后，在 kernel 的参数环境下，加入 init=/bin/bash 来取代 /sbin/init ，则可略过 init 与 /etc/inittab 的设定项目，不过，您必须相当熟悉 grub 与 lilo 的设定才行喔！ ^_^
  • 在 CentOS 当中，我们如何自动可载入的模组？
    可以经由设定 /etc/modprobe.conf 或者是将自行做好的设定档写入到 /etc/sysconfig/modules/ 目录中， 并且将档名取为 filename.modules ，注意喔，档案结果务必是 .modules 才行。 相关资讯可以参考 /etc/rc.d/rc.sysinit 喔！
  • 如果你不小心先安装 Linux 再安装 Windows 导致 boot loader 无法找到 Linux 的开机选单，该如何挽救？
    方法有很多，例如：
    (1)藉助第三方软体，安装类似 spfdisk 的软体在 MBR 里面，因为他同时认识 Linux 与 Windows ，所以就可以用他来进入 Linux 啦！
    (2)或者使用类似 KNOPPIX 的 Live CD 以光碟开机进入 Linux 之后，再以 chroot 软体切换根目录 (/)，然后重新安装 grub 等 boot loader ，同样也可以重新让两个作业系统存在啦！
    总之，只要你知道 MBR / Super block / boot loader 之间的相关性，怎么切换都可能啊！ ^_^
大标题的图示 参考资料与延伸阅读
  • 注1：BIOS 的 POST 功能解释：http://en.wikipedia.org/wiki/Power-on_self-test
  • 注2：BIOS 的 INT 13 硬体中断解释：http://en.wikipedia.org/wiki/INT_13
  • 注3：关于 splash 的相关说明：http://ruslug.rutgers.edu/~mcgrof/grub-images/
  • 注4：一些 grub 出错时的解决之道：
    http://wiki.linuxquestions.org/wiki/GRUB_boot_menu
    http://forums.gentoo.org/viewtopic.php?t=122656&highlight=grub+error+collection
  • info grub
  • GNU 官方网站关于 grub 的说明文件：
    http://www.gnu.org/software/grub/manual/html_node/
  • 纯文字荧幕解析度的修改方法：
    http://phorum.study-area.org/viewtopic.php?t=14776
2003/02/10：第一次完成
2005/09/19：将旧的文章移动到 此处 。
2005/09/26：将 核心编译 一文订为进阶篇，不一定要学啦！但是核心模组不可不题，所以，新增一小节！
2005/09/28：终于给他完成去！好累～
2005/10/09：加上参考文献资料，以及修改一些些 kernel 开机时， grub 的 vga 设定值的解说。
2005/11/09：加上了关于较大硬碟所产生的困扰！
2006/08/21：MBR 应该只有 512 bytes ，结果误植为 512 Kbytes ，抱歉！
2007/06/27：新增 initrd 的说明，请参考这里。
2009/04/09：将旧的基于 FC4 的文章移动到此处。
2009/04/10：取消了 LILO 的 boot loader 说明！毕竟这玩意儿已经退流行！所以不再强调！有需要请查询此处。
2009/04/30：修订完毕，加强 init=/bin/bash 的说明，以及 grub 的密码管理！
2009/09/14：加入情境模拟，并根据讨论区 linuxfans 兄的建议，修改了一些地方！详情请参考讨论区建议！


鸟哥的 Linux 私房菜 -- 第二十一章、系统设定工具(网路与印表机)与硬体侦测

为取得较佳浏览结果，请爱用 firefox 浏览本网页
鸟哥的 Linux 私房菜馆 | Linux 基础文件 | Linux 架站文件 | Linux 企业运用 | 安全管理 | 新手讨论 |

第二十一章、系统设定工具(网路与印表机)与硬体侦测
最近更新日期：2009/09/15
除了手动设定之外，其实系统提供了一个名为 setup 的指令给系统管理员使用喔！这个指令还能够设定网路呢。 此外，我们也应该要知道如何在 Linux 底下连接印表机吧！否则一些资料怎么印出来？ 另外，如果你的主机板支援 CPU 温度侦测的话，我们还能够利用 lm_sensors 这个软体功能来侦测硬体的电压、风扇转速、 CPU 温度等资讯呢！

1. CentOS 系统设定工具： setup
    1.1 使用者身份验证设定
    1.2 网路设定项目(手动设定IP与自动取得)
    1.3 防火墙设定
    1.4 键盘形式设定
    1.5 系统服务的启动与否设定
    1.6 系统时钟的时区设定
    1.7 X 视窗介面解析度设定
 2. 利用 CUPS 设定 Linux 印表机
    2.1 Linux 的列印元件 (列印工作、伫列、服务与印表机)
    2.2 CUPS 支援的连线模式
    2.3 以 Web 介面控管网路印表机
    2.4 以 Web 介面控管 USB 本机印表机
    2.5 将 Linux 本机印表机开放成为网路印表机
    2.6 手动设定印表机： lpadmin, lpstat, lpr, lp, lpq, lprm
 3. 硬体资料收集与驱动，及 lm_sensors
    3.1 硬体资讯的收集与分析： lspci, lsusb, iostat...
    3.2 驱动 USB 装置
    3.3 使用 lm_sensors 取得温度、电压等资讯： sensors-detect, sensors
    3.4 udev与 hal 简介
 4. 重点回顾
5. 本章习题
6. 参考资料与延伸阅读
7. 针对本文的建议：http://phorum.vbird.org/viewtopic.php?t=23898
大标题的图示 CentOS 系统设定工具： setup

系统设定除了使用手动的方式编辑设定档之外 (例如 /etc/inittab, /etc/fstab 等)，其实在 Red Hat 系统的 RHEL, CentOS 及 Fedora 还有提供一支综合程式来管理的，那就是 setup 这个指令的功能啰！老实说， setup 其实只有在 Red Hat 的系列才有， 在其他的 Linux distributions 并不存在，因此，鸟哥并没有很要求一定要学会这家伙的。 只不过，setup 还是挺好用的，所以我们还是来玩玩吧！

这个 setup 的处理方法非常的简单，就是利用 root 的身份下达这个指令，如果你已经使用远端操作系统的话， 记得最好切换一下语系成为英文语系 (比较不会出现边框是乱码的情况) ，结果就会出现如下的画面了。

setup 的指令执行画面示意图
图1.0、 setup 的指令执行画面示意图

如上图所示，那就是 setup 提供的各项系统设定功能。这个画面的使用方式其实在图中的最底下一行有说明了， 可以利用 [tab] 按键在三个画面中切换，使用 Run Tool 可以开始设定该项目，使用 Quit 可以离开 setup 指令。 那么上面的主选单部分有哪些功能呢？这些设定的基本功能是这样的：

  • Authentication configuration：
    这是与使用者身份认证有关的设定，包括本机的帐号与利用远端伺服器提供的帐号来登入本机等功能的设定；

  • Firewall configuration：
    简单的设定 (1)防火墙与 (2)SELinux 的启动模式 (Disable, Enforcing, Permissive)。 SELinux 请参考第十七章的说明， 防火墙则请参考伺服器篇的解释了。这个地方的设定比较简单， 有时候可能会让你自己搞不清楚设定值的意义。所以，还是手动处理比较妥当；

  • Keyboard configuration：
    就是键盘按键的对应表。注意，这个设定仅与 tty 介面有关，至于 X Window 则不是以这个为设定值；

  • Network configuration：
    设定网路参数的地方，包括 IP, network, netmask, dns 等等，不过， 还需要看完伺服器篇关于网路基础的介绍后， 才能够比较了解设定值的意义啦！

  • System services：
    其实就是第十八章提到的 ntsysv 的内容喔～亦即设定一些系统服务是否在开机时启动的地方；

  • Timezone configuration：
    安装的时候不是可以透过全世界地图挑选时区吗？ 这个就是在安装完毕后重新选择时区的地方；

  • X configuration：
    设定 X Window 相关的设定，例如解析度啦等等的。我们会在第二十四章再提到 X Window 方面的基础知识。

底下我们就来约略的介绍一下这些玩意儿吧！除了网路 IP 的设定外，其余的部分鸟哥会很快的带过去而已。 毕竟 setup 仅是一个统整的工具，每个设定项目其实都牵涉到各自的基础功能，那些基础功能还得要持续摸索的...

小标题的图示 使用者身份验证设定

在按下了‘ Authentication configuration ’项目后，会出现如下画面：

Setup 指令的使用者身份认证机制
图 1.1.1、Setup 指令的使用者身份认证机制

我们的 Linux 除了使用自己提供的使用者密码验证机制之外，还能够使用其他外部身份验证伺服器所提供的各项验证功能喔。 在上面图示的左侧 User Information 的地方指的是：我们系统上的使用者可以使用什么方式对外取得帐号资讯， 也就是说，这部主机除了 /etc/passwd 的帐号之外，还能够使用其他的帐号来登入系统的。我们支援的帐号管理伺服器主要有 LDAP, NIS, Winbind 等。

至于右侧的 Authentication 则是登入时需要提供的身份验证码 (密码) 所使用的机制为何。 在预设的情况下，我们身份验证仅参考本机的 /etc/passwd, /etc/shadow 而已，而且使用 MD5 的密码验算机制， 因此上图右侧的部分仅会有最上方两个而已。事实上，这个部分的设定主要是修改了 /etc/sysconfig/authconfig ，同时还加入了各个伺服器的用户端程式设定功能哩。

你一定会问，那么什么时候可以用到这个机制呢？思考一下，如果你的网路环境是电脑教室， 你希望每个同学都能够有自己的帐号来登入每部主机。此时，你会希望每部主机都帮同学建立同一个帐号吗？ 那如果每一个同学都想要修改密码，那就糟了！因为每部主机都得要重新修改密码才行啊！这个时候帐号管理伺服器就很重要了。 他的功能有点像底下这样：

身份管理伺服器的功能示意图
图 1.1.2、身份管理伺服器的功能示意图

如上图所示，我 vbird 想要登入某一部主机时，这部主机会向外要求帐号资讯，就是最上方那部伺服器。 此时，你只要在最上方的伺服器上将该帐号设定好，并且在每部主机都利用 NIS 或 LDAP 功能来指定身份查询的方向， 那么 vbird 就能够使用同一组帐号密码来登入每部主机了，这样管理是否很方便呢？因为只要管理一部伺服器即可嘛！ 我们在伺服器篇谈到 NIS 时再来实作这个环境喔！

Tips:
其实 NIS 与 LDAP 等等的，都是一种网路通讯协定，我们可以透过网路通讯协定来进行资料的传输。 使用者帐号资讯当然也能够透过这个机制来管理啰！有兴趣的朋友请继续阅读鸟哥写的伺服器篇啰～ ^_^ 		鸟哥的图示
小标题的图示 网路设定项目(手动设定IP与自动取得)

网路其实是又可爱又麻烦的玩意儿，如果你是网路管理员，那么你必须要了解区域网路内的 IP, gateway, netmask 等参数，如果还想要连上 Internet ，那么就得要理解 DNS 代表的意义为何。如果你的单位想要拥有自己的网域名称， 那么架设 DNS 伺服器则是不可或缺的。总之，要设定网路伺服器之前，你得要先理解网路基础就是了！ 没有人愿意自己的伺服器老是被攻击或者是网路问题层出不穷吧！^_^

但鸟哥这里的网路介绍仅止于当你是一部单机的 Linux 用户端，而非伺服器！所以你的各项网路参数只要找到网路管理员， 或者是找到你的 ISP (Internet Service Provider) ，向他询问网路参数的取得方式以及实际的网路参数即可。 通常网路参数的取得方式在台湾常见的有底下这几种：

  1. 手动设定固定 IP ：

    常见于学术网路的伺服器设定、公司行号内的特定座位等。这种方式你必须要取得底下的几个参数才能够让你的 Linux 上网的：

    • IP
    • 子网路遮罩(netmask)
    • 通讯闸(gateway)
    • DNS 主机的 IP (通常会有两个，若记不住的话，硬背 168.95.1.1 即可)

  2. 网路参数可自动取得：

    常见于 IP 分享器后端的主机，或者是利用电视线路的缆线上网 (cable modem)，或者是学校宿舍的网路环境等。 这种网路参数取得方式就被称为 dhcp ，你啥事都不需要知道，只要知道设定上网方式为 dhcp 即可。

  3. 透过 ADSL 宽频拨接：

    不论你的 IP 是固定的还是每次拨接都不相同 (被称为浮动式 IP)，只要是透过宽频数据机‘拨接上网’的，就是使用这种方式。 拨接上网虽然还是使用网路卡连接到数据机上，不过，系统最终会产生一个替代数据机的网路介面 (ppp0) ， 那个 ppp0 也是一个实体网路介面啦！

了解了网路参数的取得方法后，你还得要知道一下我们透过啥硬体连上 Internet 的呢？其实就是网路卡嘛。 目前的主流网卡为使用乙太网路协定所开发出来的乙太网卡 (Ethernet)，因此我们 Linux 就称呼这种网路介面为 ethN (N 为数字)。 举例来说，鸟哥的这部测试机上面有一张乙太网卡，因此鸟哥这部主机的网路介面就是 eth0 啰 (第一张为 0 号开始)。

好了，那就让我们透过 setup 来设定网路吧！按下‘ Network Configuration ’会出现如下画面：

setup 的网路介面选择示意图
图 1.2.1 、 setup 的网路介面选择示意图

上图中那个 eth1.bak 是系统捉错的档案，因为这个程式会跑到 /etc/sysconfig/network-scripts/ 目录下找出档名为 ifcfg-ethN 的档案内容来显示的。因为鸟哥仅有一张网卡，因此那个 eth1 不要理会他！直接点选 eth0 之后就会产生如下的画面：

网路介面的各项网路参数设定示意图
图 1.2.2 、 网路介面的各项网路参数设定示意图

上图中那个 Name 与 Device 名称最好要相同，尽量不要修改他！这里的设定是这样的：

  1. 如果你是使用手动设定的话，‘ Use DHCP ’一定不能勾选，然后将底下的 Static IP, Netmask, Default gateway IP 设定值填上去即可。这三个设定值请洽你的网路管理员喔。

  2. 如果你是使用 DHCP 的自动取得 IP 方式，勾选‘ Use DHCP ’后，将后面的三个设定清空，这样就设定好网路参数了；

如果你是使用 ADSL 拨接的话，那么上面的设定项目就不适用了。 你得要使用 (1)adsl-setup 来进行设定，然后再以 (2)adsl-start 来启动 ADSL 拨接， 详细的方法我们会在伺服器篇再来介绍的。上面谈的都是 IP 的取得方式，并没有谈到主机名称解析的部分 (DNS)。 只有手动设定者才需要进行 DNS IP 的设定，使用 dhcp 及 adsl-start 者都不需要进行底下的动作啦！ 假设你的 DNS IP 为中华电信的 168.95.1.1 时，那就得这样设定：

[root@www ~]# vim /etc/resolv.conf
nameserver 168.95.1.1

重点是 nameserver 后面加上你的 DNS IP 即可！一切设定都妥当之后，你还得要进行一个任务，那就是重新启动网路看看啰！ 重新启动网路的方法很简单，这样做即可：

[root@www ~]# /etc/init.d/network restart
Shutting down interface eth0:               [  OK  ]
Shutting down loopback interface:           [  OK  ]
Bringing up loopback interface:             [  OK  ]
Bringing up interface eth0:                 [  OK  ]

由于网路涉及的范围相当的广泛，还包括如何进行网路除错的工作等，鸟哥将这部份写在伺服器篇了，所以这里不再多费唇舌。 假设你现在已经连上 Internet 了，那么防火墙的设定则不可不知啊！底下就来谈谈。

小标题的图示 防火墙设定

防火墙的认识是非常困难的，因为你必须要有很强的网路基础概念才行。CentOS 提供的这个简单的设定其实有时候反而会让我们困扰不已。基本上，这里仅是介绍‘你可以这样做’，但并不代表‘你必须这样做’！ 所以，有兴趣的还是得要再继续钻研网路技术喔！ ^_^。好了，在按下 Firewall configuration 后，会出现如下画面：

setup 进入防火墙设定示意图
图 1.3.1 、 setup 进入防火墙设定示意图

上图中主要出现两个部分，一个是关于 SELinux 的部分，一个则是防火墙的部分。SELinux 我们在第十七章介绍过了，这里不再浪费篇幅。 请依据你的需求设定 Enforcing, Permissive 或 Disabled 吧！(当然最好还是务必要启动 SELinux 啦！)

防火墙的部分，由于我们安装时建议不要启动防火墙， 因此上图你会看到‘ Disabled ’的部分被选择了。但是由于现在你的系统已经上网了 (假设已经上网了)， 那么你务必要启动防火墙来管理网路才好。由于预设你的防火墙会开放远端主机对你的登入连线， 因此最好使用 Customize (客户设定) 来改变设定比较好喔！按下‘ Customize ’会出现如下图示：

客制化防火墙抵挡机制的示意图
图 1.3.2 、 客制化防火墙抵挡机制的示意图

这个地方不是三言两语讲的完的！包括信任网域，以及允许进入的伺服器封包～很是麻烦。基本上，你只要这样想就好了：

  • Trusted Devices：这是信任网域， 如果你有两张网路卡，一张是 eth0 对内，一张是对外，假设是 eth1 ，那么如果你想要让 eth0 的进出封包都是为信任，那么这里就可以将 eth0 勾选。不过，要非常非常注意， 接到外部网域 (Internet) 的那张网路卡，千万不能勾选，否则大家就都能够透过那张网卡连到你的主机上！ 在预设的情况中，这里都不要选择任何介面啦！

  • MASQUERADE Devices：这个是‘封包伪装’的功能， 亦即是进行 IP 分享器的功能啦！如果你的 Linux 主机是作为类似 IP 分享器的功能， 那么对外那张网路卡就得要启动 MASQUERADE 才行！因为我们尚未谈到网路伺服器，因此这里可千万不要随意选择。

  • Allow incoming：这里提到的就是各个服务的内部项目， 举例来说，你的 Linux 有提供 WWW 服务，又希望大家都能够来查阅， 那么这个时候就可以在 WWW 那个项目前面勾选啦！你要注意到的是，预设 Linux 都会开放 ssh 这个服务 (如上图)， 记得先将他取消勾选喔！因为这个 ssh 现在很容易被攻击！所以不要开放人家使用这个服务连线到你的主机上。

基本上，这个动作仅是在建立 /etc/sysconfig/iptables 这个档案而已。 而这个档案预设是不存在的 (因为我们没有启动防火墙啊！) 。这里你先有个概念即可，因为，我们未来会介绍以 shell script 的方式建立属于您自己的防火墙系统，细节我们会在伺服器篇慢慢作介绍的啊！

如果你已经有网路了，记得在这个项目的设定中，于图 1.3.1 选择防火墙为‘ Enable ’的状态，按下‘ Customize ’进入图 1.3.2 当中取消 ssh 的勾选，最后再回到 1.3.1 当中按下‘ OK ’来启动 Linux 用户端的防火墙设定吧！ 这样你的系统就具有最起码的防火墙功能啰！ ^_^

小标题的图示 键盘形式设定

某些情况底下你的键盘可能会发生一些对应错误的情况，举例来说，使用的键盘并非台湾常见的 104 按键导致很多英文对应不起来。 此时你可以使用 setup 来修改喔！按下‘ Keyboard configuration ’会出现如下的画面：

键盘形式选择
图 1.4.1 、键盘形式选择

其实这个档案就仅会修改 /etc/sysconfig/keyboard 啦！很简单的设定项目。

小标题的图示 系统服务的启动与否设定

我们在第十八章谈过系统服务的启动与关闭， 当时介绍过 ntsysv 吧？没错～这个 System services 的项目就是会呼叫出 ntsysv 这支程式来处理服务的设定啦！详细的设定请回第十八章参考吧！这里不再浪费篇幅啰！ 因为....鸟哥实在太会碎碎念了，再加上图示，唔！好占篇幅～ @_@

小标题的图示 系统时钟的时区设定

我们知道地球是圆的，所以想要看王建民在纽约投球都得要三更半夜才有办法看的到！这也就是说， 其实在同一个时间点全世界的时钟指的时间都不相同啊！我们的 Linux 是支援多国语系的国际化作业系统， 所以你可以将这部主机拿到任何地方且不需要修改系统时钟，因为系统会主动的依据你提供的时区来变化时间的。 当你将笔记型电脑带到美国纽约并且想要变更成为美国时间时，可以按下‘ Timezone configuration ’的项目：

setup 的时区选择
图 1.6.1 、 setup 的时区选择

如上图所示，你在上半部画面中，可以使用键盘方向键来选择正确的位置，然后再用 [tab] 移动到 [OK] 即可！ 时区的设定，其实就是找出与 /etc/sysconfig/clock 有关的设定项目而已。实际上，上面图示出现的咚咚，就与 /usr/share/zoneinfo/ 目录内的资料有关而已。

小标题的图示 X 视窗介面解析度设定

X Window System 我们会在第二十四章再来详细说明，这里仅是告知一下， 如果你想要变更你的 X 视窗介面的解析度时，就可以使用这个项目了。不过要注意的是，这个项目的执行不可以使用类似 ssh 通讯协定连线后，在远端主机上执行这个设定项目。因为这个项目的执行会产生一个新的 X 终端机在 tty7 或 tty8 上头， 因此，你如果使用远端连线机制的话，会看不到画面的啦！理解乎？

在你点选了‘ X configuration ’之后，就会出现如下的图样。其中以硬体及设定两个页面较常被变更。 先来瞧瞧图示吧：

setup 的 X 解析度设定
图 1.7.1 、 setup 的 X 解析度设定

如上所示，由于视窗解析度的范围与荧幕的支援有关，因此你必须要先处理荧幕的更新频率后才能够修改视窗解析度。 所以我们会先处理‘硬体’部分，鸟哥的荧幕是旧式的 4:3 传统荧幕，所以选择 1024x768 ，如果你的荧幕是新型的宽荧幕， 那么请自行挑选适当的解析度吧。处理完毕后就能够开始设定视窗解析度了，如下所示：

setup 的 X 解析度设定
图 1.7.2 、 setup 的 X 解析度设定

如上图所示，此时会出现可调整的解析度啦！整理整理就能够显示出你想要的视窗解析度。 其实这些设定都是修改 /etc/X11/xorg.conf 这个设定档啦！等到了第二十四章时，我们再来详细的谈谈这玩意吧！ 至于关于 X 方面的登录档则在 /var/log/Xorg.0.log 啰！

鸟哥个人认为，这个 setup 的工具是很好用的～只是，如果能够完全清楚整个系统架构的话， 再来玩这个小程式会比较好啦！ ^_^。另外，原本的旧版 CentOS 还有提供印表机的设定功能，不过由于新版的资料已经转由 CUPS 负责列印， 而列印可以使用浏览器介面来显示，因此就取消了这个 setup 的元件啦！底下我们就来玩玩如何简单的设定你的印表机吧！

大标题的图示 利用 CUPS 设定 Linux 印表机

印表机对于日常生活来说，很重要吧！呵呵～没错啊！尤其我们的 Linux 主机如果未来还要作为 Printing server 的话，那么自然就得要先建立好印表机的连线啦！在本章里面我们仅谈论一下如何让你的 Linux 可以连接到印表机， 让你的 Linux 可以顺利的将文件资料列印出来啦！现在就来谈谈先！

小标题的图示 Linux 的列印元件 (列印工作、伫列、服务与印表机)
  • 硬体支援度

要谈论 Linux 的列印，首先就得要知道 Linux 底下整个列印的行为是怎样的一个流程呢？而且， 也得要了解一下你的硬体是否支援列印工作嘛！在硬体部分，你必须要在 BIOS 将印表机的支援启动才行！ 不过，这大概都属于旧式印表机才需要的动作啦！为啥呢？因为现在印表机大部分都是 USB 或者是网路印表机了， 根本不需要使用 25 针序列埠的支援！

Tips:
为什么会谈到 25 针序列埠以及 BIOS 的支援呢？这是因为鸟哥曾经发生过一件糗事。 由于鸟哥常用旧型主机的关系，所以总喜欢先在 BIOS 里面将没用到的装置项目全部取消 (disable)， 所以没有接印表机的情况下，当然连印表机的序列埠 (Parallel) 也关闭了。没想到后来为了测试印表机的连线取得一台旧式印表机， 要命啊！连续测试两天的时间却无法顺利的列印出正确的文件资讯！最后才想到可能是 BIOS 内部的问题。 进入 BIOS 将印表机支援启动成为 EPP/SPP 之后，俺的 Linux 就能够顺利的捉到印表机并进行列印～真想哭啊！ 不是感动的想哭，是气的想哭！ 		鸟哥的图示

除了主机本身的支援之外，你的印表机也必须要能够支援 Linux 才行！其实并不是 Linux 的问题啦！而是印表机制造商必须要能够提供给 Linux 用的驱动程式，这样你的 Linux 才能够使用该型号的印表机。 老实说，鸟哥是 HP 印表机的爱好者，因为 HP 印表机对 Linux 的支援非常好！但是另一牌的 L 开头的印表机总是很慢或者不推出给 Linux 用的驱动程式，所以该牌的印表机很难安装在 Linux 主机上！真困扰。

Tips:
因为鸟哥过去所待的研究室大多购买 HP 的印表机，所以测试印表机时完全没有出现任何问题。 但是某天在家里使用鸟嫂购买的 L 牌的事务机时，连忙了三天却都无法连接到该印表机来顺利输出。 最终查询 Linux 印表机支援网站，才发现该型号的事务机根本没有推出给 Linux 用的驱动程式， 所以就无法顺利使用该印表机～最终...鸟哥就放弃该测试了～唉！真浪费时间！ 		鸟哥的图示

那到底你该如何确认你的印表机有支援 Linux 呢？或者是，如果你想要购买新的印表机时， 如何查询该印表机能否在 Linux 上面安装呢？很简单，直接到底下的网站去查询一下即可喔！

  • http://www.linuxfoundation.org/en/OpenPrinting

举例来说，鸟哥现在的研究室有一部 HP 的 LaserJet P2015dn 印表机，我想要知道这部印表机对 Linux 的支援度好不好， 那就先进入上述的网站连结，出现如下的画面：

印表机支援网站的主画面
图 2.1.1 、 印表机支援网站的主画面

在如上画面中请按下‘ Printers ’来观察印表机的特色吧！会出现如下画面：

选择印表机示意图
图 2.1.2 、 选择印表机示意图

在上图中填入正确的厂牌 (HP) 以及正确的印表机型号 (LaserJet P2015dn) 后，请按下‘ Show ’那个按钮， 该网站就会从资料库内捉出支援度的情况给你看，如下图所示：

鸟哥的印表机对 Linux 的支援度
图 2.1.3 、 鸟哥的印表机对 Linux 的支援度

在显示的画面中，你最要注意的是那个企鹅数量啦！如果达到 3 只，那就代表支援度是非常完美的。 两支企鹅是可接受的范围内。如果是小于一只企鹅时，那么该印表机对 Linux 的支援可能就是比较差的喔！ 还好，鸟哥这部含有网路功能的印表机还有两只企鹅的支援，等一下应该能够顺利安装到俺的 Linux 测试机上吧！

  • 列印元件

你有没有发现，在印表机还没有启动电源的情况底下，其实我们还是可以透过软体来将某个工作列印出来的， 只是该项工作就会被放入到等待的环境中 (伫列) 。为什么会这样呢？这是因为整个列印的行为被区分为许多部分， 每个部分都可以单独存在的啦！我们将整个部分绘制成下图来瞧瞧：

列印行为之各元件示意图
图 2.1.4、 列印行为之各元件示意图

我们大概可以将上图区分为几个部分来说明：

  • 列印工作：

    例如 Open Office 这类较大型的办公室软体中，可以利用内建的程式产生列印的动作。 我们也可以使用类似 lpr 这类指令列程式来直接列印某个档案。列印软体产生的列印动作，就是产生一个列印的工作 (job)， 这个列印工作就会进入排队等待 (伫列, queue) 的环境中，等待列印服务来进行输出。

  • 列印伫列：

    这是放置列印工作的重要项目！这个列印伫列与列印服务有关。一般来说，列印伫列会以印表机的名字来命名， 让大家知道你的列印工作将要使用哪部印表机输出之故。当列印工作放置到伫列后，就开始等待列印服务的取用与输出了。

  • 列印服务：

    就是实际负责沟通伫列内的列印工作与印表机的服务啦！列印服务其实就是将伫列内的列印工作，将她的资料转成印表机认识的格式后， 直接交给印表机来输出而已。但是列印服务必须要认识与沟通印表机，因此他就得要连上印表机与驱动印表机才行。 目前常见的列印服务有 CUPS 与 LPRng ，不过以 CUPS 为主流啦！

    一般我们说的印表机驱动程式，其实就是将列印工作的资料转成印表机格式啦！ 而目前常见的印表机格式为使用 Postscript 的列印格式，Linux 预设的 CUPS 本身就支援这种列印格式，因此， 只要你购买的印表机有支援 postscript ，那么安装起来应该是很轻松的才是。我们在上面提到的印表机支援网站中， 里面的驱动程式很多就是 postscript 印表机描述档案 (Postscript Printer Description (注1))

    那万一没有 PPD 档案呢？没关系，我们可以透过印表机制作商提供的其他定义档 (例如 Ghostscript) 来解释列印工作的资料， 让印表机认识该格式后，就能够顺利列印了！这也就是说，其实印表机驱动程式就是将资料转成印表机认识的格式后， 就能够加以输出了。而常见的格式为 Postscript 及 Ghostscript 啰！

    那么这些列印的 PPD 驱动程式档放在哪里呢？其实就放在 /usr/share/cups/model/ 底下啦！ CentOS 已经提供一些预设的驱动程式了，如果想要取得更新的 PPD 驱动程式档，请参考上面的印表机网站， 从那上头来下载即可呦！若想要直接下载全部的 PPD 档案，可以参考连结： http://www.linuxprinting.org/download/PPD/
Tips:
为什么需要列印伫列 (queue) 呢？因为印表机只能够给单一任务进行列印，没办法像 CPU 可以交错运作的！ 所以列印工作就得要排队等待印表机的列印，而印表机得要将前一份工作列印完毕后才能够列印下一份工作！ 否则如果是交错列印，那印出的东西不就混杂在一起了？这样说了解吗？ ^_^ 		鸟哥的图示
小标题的图示 CUPS 支援的连线模式

如果你的印表机具有网路卡，那么你当然可以使用网路连线到你的印表机上面啰！不过，这种印表机提供什么服务呢？ 也就是说，你可以使用什么连线协定来连上印表机呢？常见的印表机连线分享方式有底下这些：

  • socket
    资料透过 internet socket(埠口)来传送，一般为 port 9100 或 35。如果想要进行资料的传输与列印，可以透过在浏览器上面输入： socket://host-printer:9100/ 来进行。不过，这种模式不常用就是了。

  • LPD (Line Pritner Daemon)
    LPD 是较早之前的列印服务，刚刚上头提到的 LPRng 就是使用这种方式的连线啦！ LPD 主要是利用序列埠来达成列印的需求，印表机名称就是 LPT1/LPT2... 等等。 目前还是可以在比较早期的 Linux distributions 看到这种列印方式。

  • IPP (Internet Printing Protocol)
    这是目前比较流行的印表机列印协定，我们的 CUPS 预设也是支援这种协定啊！当启动 IPP 时，印表机会启动 port 631 ，列印的资料就是透过这个 port 来进行传送的。另外，如果你的印表机或者 Linux 主机启动了 ipp 之后， 嘿嘿！你可以直接使用浏览器，输入： ipp://printer_IP/printername，或者是： http:/printer_IP:631 就能够直接线上处理印表机的设定了！方便的很啊！

  • SMB (Server Message Block)
    这家伙就是网路上的芳邻啦！协定使用的是： smb://user:password@host/printer 。

CentOS 5.x 预设提供的就是 CUPS 的 IPP 协定喔！而且 CUPS 预设开机就启动了， 因此，你可以随时随地的以 Web 介面设定自己的印表机呢！真是非常方便！ 那如果你的印表机是透过线材 (USB/序列埠) 连上主机的呢？那就得要考虑底下的连接介面啰！

  • parallel ：平行序列埠啊，就是 25 针那种玩意儿！他是连接到 /dev/lp[0-2] 等装置。 在 CUPS 里面的装置使用格式为： parallel:/dev/lp0；

  • USB ：一般越来越常见的 USB 印表机啊！ CUPS 使用的格式为： usb:/dev/usb/lp0 。
小标题的图示 以 Web 介面控管网路印表机

事实上，管理 Linux 的印表机是非常简单的一件事情，因为你只要启动 CUPS 之后，再以浏览器介面来管理即可。 不过，在预设的情况底下，要进行浏览器介面的管理动作时，你必须要：

  • 必须要启动 CUPS 这个服务 (/etc/init.d/cups start)
  • 具有 root 的权限 (需要 root 的密码来设定)；
  • 预设仅能在本机 (localhost) 管理，无法使用远端连线连到此 Linux 管理；

如果你想要在区域网路内将印表机的控制权挪出来给其他用户管理时，就得要修改 CUPS 的设定了。 在这里，我们先以本机的方式来处理印表机的连线喔！首先，鸟哥以具有网路卡的印表机 HP LaserJet P2015dn 这部为例 (因为鸟哥也只有这部印表机具有网卡啊！)，这部印表机的 IP 为 192.168.201.253，而鸟哥 Linux 测试机 IP 为 192.168.201.250。然后，你可以这样做：

  • 确认印表机存在且支援 CUPS 认识的相关协定

如果想要加入 CUPS 的网路印表机，那么你的印表机当然就得要支援 CUPS 认识的通讯协定啰！如何确定呢？ 首先，你必须要依照你印表机所提供的手册去设定好 IP ，以鸟哥上面的环境来说，我的印表机 IP 为 192.168.201.253 ， 因此我可以这样确定该印表机是否存在喔：

# 1. 先确定 IP 是否正确：
[root@www ~]# ping -c 3 192.168.201.253
PING 192.168.201.253 (192.168.201.253) 56(84) bytes of data.
64 bytes from 192.168.201.253: icmp_seq=1 ttl=255 time=0.464 ms
64 bytes from 192.168.201.253: icmp_seq=2 ttl=255 time=0.313 ms
64 bytes from 192.168.201.253: icmp_seq=3 ttl=255 time=0.356 ms

--- 192.168.201.253 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2000ms
rtt min/avg/max/mdev = 0.313/0.377/0.464/0.067 ms
# 重点是有没有出现回应的时间参数，亦即是 time 那个栏位喔！

# 2. 使用 nmap 测试印表机有没有出现列印相关的服务埠口：
[root@www ~]# nmap 192.168.201.253
Starting Nmap 4.11 ( http://www.insecure.org/nmap/ ) at 2009-05-27 22:07 CST
Interesting ports on 192.168.201.253:
Not shown: 1676 closed ports
PORT     STATE SERVICE
80/tcp   open  http
139/tcp  open  netbios-ssn
515/tcp  open  printer
9100/tcp open  jetdirect
MAC Address: 00:18:FE:9E:4C:58 (Unknown)

Nmap finished: 1 IP address (1 host up) scanned in 3.875 seconds
# 鸟哥这部印表机仅支援 LPD 服务 (515) 以及 HP 独家的服务 (9100)

这样就确定我的印表机实际存在，且这部印表机仅支援 HP 独家的网路服务 (port 9100) 以及旧版的 LPD 服务而已， 这个资讯很重要，因为等一下我们使用 CUPS 连线时，就得要使用这个 LPD 的服务喔！另外，请特别给他留意一下， 那个 nmap 是个可以扫瞄主机埠口的软体 (port scan) ，这个软体其实是骇客软体，他预设并没有安装到 CentOS 上， 但是你可以使用‘ yum install nmap ’来安装他。请注意，因为这个软体可以是恶意攻击的，因此千万不要用来查阅别人的主机，否则恐怕会有违法之虞喔！！

接下来，让我们来了解一下，系统有没有 CUPS 的支援吧！

  • 查询你 Linux 主机是否启动 CUPS 服务

再来查看看你的主机是否已经启动了 CUPS 呢？使用 netstat 这个指令看看：

[root@www ~]# netstat -tlunp | grep 631
tcp  0  0 127.0.0.1:631     0.0.0.0:*         LISTEN      4231/cupsd
udp  0  0 0.0.0.0:631       0.0.0.0:*                     4231/cupsd

确实有启动 631 埠口以及 cupsd 的服务。接下来，我们可以直接连上 CUPS 了！请打开浏览器， 然后在网址列输入‘ http://localhost:631 ’即可！因为浏览器要连接的并非正规的 WWW 服务埠口， 因此就得要加上冒号 (:) 来指定埠口连接！顺利的话，应该可以出现如下画面：

CUPS 进站画面
图 2.3.1、 CUPS 进站画面

主画面主要可以分为上下两个按钮列来说明，其中又以下方的按钮列为常见的操作项目。我们会用到的按钮大概就是：

  • Add Printer：新增印表机，就是从这个按钮开始的！
  • Manage Jobs：列印工作管理，如果有列印工作要取消的，这个就对了！
  • Manage Printers：管理印表机，包括是否启动或者是删除印表机等。

不啰唆，赶紧来新增印表机看看！按下‘ Add Printer ’项目吧：

CUPS 新增印表机的画面示意图
图 2.3.2、 CUPS 新增印表机的画面示意图

上面图示中，最重要的其实是那个‘ Name ’的项目，那就是你印表机的伫列名称！未来所有列印的工作都是放在该名称底下排队的！ 鸟哥的这个印表机名称比较复杂啦！你可以取个比较简单的名字，以后比较容易使用指令列软体来列印啦！ 至于位置 (Location) 与描述 (Description) 都是这个印表机的说明，可写可不写！写完后按下‘ continue ’吧！

选择印表机所提供的服务项目
图 2.3.3、选择印表机所提供的服务项目

接下来则是选择这个印表机伫列所连线的印表机提供什么服务的列印功能？你可以看到前一小节我们使用 nmap 的时候就发现 port 9100 就是 HP JetDirect ，因此我们可以选择上图的第一个项目。 由于这部印表机也提供 port 515 的 LPD 服务，因此你也可以选择上图的‘ LPD/LPR Host or Printer ’项目。 不过，在这里鸟哥选择的是第一项啦！选择完毕后再按下‘ Continue ’进入印表机的实体位置项目，如下图：

填写印表机的实际连线方式，要填正确！
图 2.3.4、填写印表机的实际连线方式，要填正确！

上图有提供很多范例，我们由于使用到 port 9100 ，因此使用的就是 socket:// 那个范例使用的状态。 填写正确的位置后，接下来按下‘ Continue ’来继续选择印表机的型号吧！

选择印表机的实际型号(驱动程式确认)
图 2.3.5、选择印表机的实际型号(驱动程式确认)

如上图所示，我们选择的是 HP 的厂牌！厂牌选择完毕后会出现如下图的型号选择：

选择印表机的实际型号(驱动程式确认)
图 2.3.6、选择印表机的实际型号(驱动程式确认)

但上图中我们并没有看到 P2015dn 这部印表机的型号！那怎办？没关系，可以连线到 http://www.linuxfoundation.org/en/OpenPrinting 网站下载适当的驱动程式后， 按下上图中的‘浏览’按钮来选择该档案即可。不过，从该网站的介绍中，可以发现鸟哥的这部印表机似乎使用预设的 Postscript 驱动程式即可，该网站也没有提供这部印表机的驱动程式啊！那怎办？没关系，在 /usr/share/cups/model/ 目录下就有预设的驱动程式啦！所以请按下‘浏览’来处理一下！

选择驱动程式档案
图 2.3.7、选择驱动程式档案

如上图所示，选择正确的驱动程式，然后再按下‘开启’按钮，最后按下‘ Add Printer ’按钮就可以进入管理员密码输入画面：

输入管理员帐号密码(预设用 root)
图 2.3.8、输入管理员帐号密码(预设用 root)

到此为止我们的印表机设定就 OK 了！如果你回到 CUPS 的进站画面，并且点选 Printers 之后，就会出现如下的印表机画面：

印表机的控制画面
图 2.3.9、印表机的控制画面

上面画面中的按钮都看的懂吧？其中比较重要的是那个‘ Set As Default ’项目， 那就是设定为‘预设印表机’，当你产生列印工作后，该工作预设就会丢给这个 hp_lj_p2015dn 的伫列来处理的意思喔。 接下来，当然就是按下‘ Print Test Page ’看看能否列印出正确的画面啰！如果可以顺利的列印，恭喜您！ 印表机设定成功！

小标题的图示 以 Web 介面控管 USB 本机印表机

上一小节提到的是网路印表机，那如果你的印表机是一般普通的具有 USB 介面的印表机呢？ 由于印表机的装置档名为 /dev/usb/lp0 开始的名称，既然已经知道印表机名称了，那么我们先来注意看看 USB 是否有捉到该印表机， 由于我们的 Linux 已经能够处理随插即用 (PnP) 的装置，因此直接执行 ls 去查阅档名是否存在即可：

[root@www ~]# ll /dev/usb/lp0
crw-rw---- 1 root lp 180, 0 Jun  1 22:32 /dev/usb/lp0
# 这个档案会被自动的建立起来，你不需要手动建立这个档案喔！

老实说，除非你的 USB 印表机是非常冷门的机种，否则，我们的 CUPS 应该已经自动的捉到并且设定好该印表机啰！ 以鸟哥为例，鸟哥办公室的事务机为 HP Diskjet F380 ，如果使用列出 USB 装置的 lsusb 时，可以看到：

[root@www ~]# lsusb
Bus 001 Device 001: ID 03f0:5511 Hewlett-Packard Deskjet F300 series
Bus 002 Device 001: ID 0000:0000
Bus 002 Device 002: ID 0d62:a100 Darfon Electronics Corp. Benq Mouse

接下来，同样的我们使用 CUPS 的 Web 介面来设定一下这部印表机吧！在网址列输入 http://localhost:631 之后再按下‘Manage Printers’会出现如下画面：

由 HAL 机制顺利取得的 USB 印表机
图 2.4.1 、由 HAL 机制顺利取得的 USB 印表机

由上图我们可以发现 CUPS 已经捉到了印表机了！连驱动程式都安装妥当！这是怎么回事啊？ 这是因为 CentOS 提供了 HAL 的机制来处理 PnP 装置的缘故。关于 HAL 的机制我们会在下一小节再来讨论。 不过由于这个装置使用的是 HAL 提供的装置档名，我们如果想要使用 /dev/usb/lp0 来作为印表机的输出档名的话， 那么就自己来建立一个印表机的伫列吧！同样的在 CUPS 画面中按下‘ Add Printer ’来新增一个印表机：

输入伫列名称
图 2.4.2 、 输入伫列名称

指向第一个 USB 装置处
图 2.4.3 、指向第一个 USB 装置处

如上图所示，你要指定的是那个有 #1 的位置，那就是我们的第一个 USB 插槽位置喔！

选择印表机的驱动程式
图 2.4.4 、选择印表机的驱动程式

最终结果
图 2.4.5 、最终结果

如上图所示，最后就会多出一个名为 deskjet_f380 的印表机名称，接下来当然就是‘ Print Test Page ’测试看看能否列印啰。 如果能够列印得出来，那就是设定妥当了。所以说， USB 印表机的设定要简单太多啰！ ^_^

小标题的图示 将 Linux 本机印表机开放成为网路印表机

想像一个状况，你仅有 USB 印表机安装在 Linux 上头，整个办公室或实验室里面仅有这部印表机。 虽然你可以加装列印伺服器来使 USB 印表机变成网路印表机，但总是得多花钱啊！ 有没有办法可以让你的本机印表机变成网路印表机呢？有的，那就是修改 CUPS 的设定即可。如何修改呢？ 我们还是透过 CUSP 的浏览器介面来处理即可喔！选择‘Administration’会出现如下画面(在画面的最右边)：

勾选可让 CUPS 成为列印伺服器的功能
图 2.5.1 、勾选可让 CUPS 成为列印伺服器的功能

如上图所示，在箭头指定的地方进行勾选即可。勾选完毕后按下‘ Change Settings ’就能够让你的 CUPS 变成列印伺服器！ 而你原本的印表机就会成为：‘ipp://你的IP:631/printers/印表机伫列名称’，举例来说，鸟哥这部 Laserjet p2015dn 在网路上看到的就会是：‘ipp://192.168.201.250/printers/hp_lj_p2015dn’的名称啊！ 你可以在其他用户端电脑上面以这个 URI 来进行连线哩！

小标题的图示 手动设定印表机

事实上我们刚刚在上面所进行的各项动作大多是在修改 /etc/cups/ 里面的几个档案而已啊！几个重要的档案为：

  • /etc/cups/printers.conf：印表机的设定值，都写在这个档案中；
  • /etc/cups/cupsd.conf：CUPS 的主要设定档，包括做为伺服器之用途的设定。
  • /etc/cups/ppd/*.ppd：就是各个印表机的驱动程式 (PPD 设定档)；

既然只是改了这几个设定档，你当然也可以使用 vim 去编辑，不过，因为涉及硬体连线的问题， 因此还是建议使用 web 介面来进行修改啦。不过，某些时候如果你没有浏览器介面时，那么使用终端机介面的指令来修改也是可以的。 我们底下只以鸟哥办公室拥有的这一部 HP P2015dn 的雷射印表机来作为范例喔！

  • 1. 下载合适的 PPD 驱动程式定义档

首先你必须要前往印表机网站下载你的印表机驱动程式定义档。鸟哥之前已经查询过，这部印表机使用预设的 PPD 档案即可。 所以鸟哥这部印表机的驱动程式定义档基本上在： /usr/share/cups/model/postscript.ppd.gz 。 如果你有自己下载自己印表机的驱动程式时，请将你下载的档案放置到 /usr/share/cups/model/ 目录下， 因为后续要操作的指令会到此目录中找寻驱动程式定义档喔！

  • 2. 启动 CUPS 以及印表机

接下来请确定你的 CUPS 是有启动的，而且印表机也已经打开电源了。启动 CUPS 的方法与检查是否启动 CUPS 的操作如下：

# 1. 重新启动 CUPS 的方法！
[root@www ~]# /etc/init.d/cups restart
正在停止 cups:                  [  确定  ]
正在启动 cups:                  [  确定  ]

[root@www ~]# netstat -tlunp | grep 631
tcp   0  0 0.0.0.0:631       0.0.0.0:*      LISTEN      4939/cupsd
tcp   0  0 :::631            :::*           LISTEN      4939/cupsd
udp   0  0 0.0.0.0:631       0.0.0.0:*                  4939/cupsd
# 因为 CUPS 启动的网路服务埠口就是 port 631 ！所以确定是启动的！

# 2. 确认印表机提供的服务为何
[root@www ~]# nmap 192.168.201.253
Starting Nmap 4.11 ( http://www.insecure.org/nmap/ ) at 2009-06-03 00:43 CST
Interesting ports on 192.168.201.253:
Not shown: 1676 closed ports
PORT     STATE SERVICE
80/tcp   open  http
139/tcp  open  netbios-ssn
515/tcp  open  printer
9100/tcp open  jetdirect
# 再次强调，鸟哥这部印表机仅有提供 HP 自家的印表机协定 9100 埠口！

从上面的输出可以很清楚的看到鸟哥的印表机与 Linux 上面的 CUPS 都有顺利的运作中！其中还是要强调， 你千万不要拿 nmap 去扫瞄别人家的系统！很可怕的！而由于上面输出的结果，我们也知道鸟哥这部印表机在网路上的连线方式为： socket://192.168.201.253:9100 的样式喔！这个地方也请先记录下来。

  • 3. 使用 lpadmin 进行印表机的建立与删除

指令设定/删除印表机的方式就是透过 lpadmin 这个指令啊！这个指令的语法是这样的：

[root@www ~]# lpadmin [-p 自订伫列名] [-v URI] [-m PPD] [-E] <==建立印表机
[root@www ~]# lpadmin [-d 已存在的伫列名]  <==设定成为预设印表机
[root@www ~]# lpadmin [-x 已存在的伫列名]  <==删除此一印表机伫列
选项与参数：
-p ：后面接的就是印表机的伫列名称，这个名称可自订，但还是定为有意义较佳。
-v ：后面接的就是装置的相关位置，常见的装置有：
     序列埠      ： parallel:/dev/lp0
     USB         ： usb:/dev/usb/lp0
     网路印表机  ： ipp://192.168.201.253/
     提供特殊插槽： socket://192.168.201.253:9100
-m ：后面接的通常就是 PPD 的定义档，注意，要放置到 /usr/share/cups/model/ 底下！
-E ：作为可接受 (accept) 此列印工作之意！

# 1. 先列出本机上面所有已经存在的印表机吧！
[root@www ~]# lpstat -a
Deskjet_F300_series accepting requests since Tue Jun  2 00:48:59 2009
deskjet_f380 accepting requests since Mon Jun  1 23:34:21 2009
hp_lj_p2015dn accepting requests since Tue Jun  2 00:22:31 2009

# 2. 删除所有已经存在的印表机吧！
[root@www ~]# lpadmin -x Deskjet_F300_series
[root@www ~]# lpadmin -x deskjet_f380
[root@www ~]# lpadmin -x hp_lj_p2015dn
[root@www ~]# lpstat -a
lpstat: No destinations added.
# 这样就确定没有任何存在的印表机啰！

# 3. 加入 hp_p2015 印表机，印表机参数如前面两小节所示：
[root@www ~]# lpadmin -p hp_p2015 -v socket://192.168.201.253:9100 \
> -m postscript.ppd.gz -E

# 4. 因为仅有一部印表机，因此让此印表机成为预设列印印表机
[root@www ~]# lpadmin -d hp_p2015

其实这个 lpadmin 指令只是在更新 /etc/cups/ 目录里面的两个资料而已， 一个是 /etc/cups/printers.conf ，这个档案主要是规范了印表机的相关装置、是否接受列印工作、 印表机的伫列名称、页面的限制等等，反正就是整个印表机的规范就是了。 至于这个印表机相关的 PPD 档案则是以印表机的伫列名称连结到 /etc/cups/ppd/ 目录下。 不相信吗？让我们来瞧瞧 printers.conf 的档案内容吧！

[root@www ~]# cat /etc/cups/printers.conf
# Printer configuration file for CUPS v1.2.4
# Written by cupsd on 2009-06-03 01:06
<DefaultPrinter hp_p2015>                <==这就是印表机伫列名称
Info hp_p2015
DeviceURI socket://192.168.201.253:9100  <==就是印表机所在的装置位置
State Idle
StateTime 1243962326
Accepting Yes
Shared Yes
JobSheets none none
QuotaPeriod 0
PageLimit 0
KLimit 0
OpPolicy default
ErrorPolicy stop-printer
</Printer>

[root@www ~]# ll /etc/cups/ppd
-rw-r--r-- 1 root root 7714 Jun  3 01:05 hp_p2015.ppd
# 这就是刚刚捉过来的，给 hp_p2015 用的印表机定义档！

  • 4. 印表机状态的观察

设定完印表机后，来观察一下目前的印表机状态吧！底下的 lpstat 是个不错用的观察指令喔！

[root@www ~]# lpstat [-adprt]
选项与参数：
-a  ：列出目前可以接受列印工作的印表机伫列名称；
-d  ：列出目前系统的预设印表机 (未指定列印伫列时，预设输出的印表机)；
-p  ：列出每部印表机目前的工作状态，包含工作的 ID；
-r  ：列出目前 CUPS 服务是否有在运作？
-t  ：列出目前列印系统中更为详细的资讯说明，很适合查询喔！

# 1. 列出目前系统上面所有的印表机伫列与接受工作与否的情形
[root@www ~]# lpstat -a
hp_p2015 accepting requests since Wed Jun  3 01:05:26 2009
# 有一部名为 hp_p2015 的印表机，从 2009/6/3 开始接受列印工作之意！

# 2. 列出目前的‘列印系统’状态，不止包括印表机而已。
[root@www ~]# lpstat -t
scheduler is running   <==CUPS 这个服务有在运作的意思
system default destination: hp_p2015  <==预设的印表机为这一部 hp_2015
device for hp_p2015: socket://192.168.201.253:9100 <==这部印表机的装置位址
hp_p2015 accepting requests since Wed Jun  3 01:05:26 2009
printer hp_p2015 is idle.  enabled since Wed Jun  3 01:05:26 2009
# 这部印表机目前是发呆 (Idle) 的状态，但可接受列印工作！

如果不清楚你的印表机状态，使用 lpstat 就能够看的清楚啰～接下来，让我们开始来使用列印指令产生列印工作吧！

  • 5. 利用 lpr 与 lp 来产生列印工作

如果你没有浏览器或者是说，你没有图形介面的软体时，可以透过 lpr 或者是 lp 这两个指令来列印某些档案或资料流重导向的东东。底下的测试会实际列印出资料来，因此，建议你可以先将印表机电源关闭， 让 CUPS 可以接受列印伫列的工作，却无法输出到印表机，这样也方便我们后续管理指令的查询！ 所以，请将印表机的电源关闭先。来看看这两个指令如何操作吧！

[root@www ~]# lpr [-P printer伫列] [-#  列印份数] -U [username] file
选项与参数：
-P  ：若没有预设印表机 (default) 或者想要由不同印表机输出时，可用 -P 指定印表机
-#  ：如果这份文件你想要列印多个副本时，用这个 -# 加上份数就对了！
-U  ：有些印表机有限制可使用的使用者帐号，此时就得要使用这个选项；

# 1. 指定 hp_p2015 这部印表机来列印 /etc/passwd 这个档案
[root@www ~]# lpr -P hp_p2015 /etc/passwd

# 2. 关闭印表机后，将 /root/ 底下的档案档名输出到这部印表机
[root@www ~]# ll /root | lpr -P hp_p2015

要注意的是，因为鸟哥有指定预设印表机，因此上面的范例中，即使没有加上 [-P hp_p2015] 这个项目时，依旧能够顺利的列印。但如果你没有指定预设印表机，那么就一定要加上这个项目， 否则 lpr 会不知到要将资料输出到哪里去喔！看完了 lpr ，再来聊聊 lp 这个指令的用法吧：

[root@www ~]# lp [-d printer伫列] [-n 列印份数] file
选项与参数：
-d  ：后面接的是印表机的伫列名称。如果有多部印表机才需要指定；
-n  ：就是列印的份数啊！

# 1. 列印出 2 份 /etc/issue 资料
[root@www ~]# lp -d hp_p2015 -n 2 /etc/issue
request id is hp_p2015-11 (1 file(s))  <==以 hp_p2015 来列印，工作号码为 11
  • 6. 列印工作的观察 (lpq) 与删除 (lprm)

我们已经有产生三个工作，但是第一个工作有顺利的列印 (印表机是开启的)，因此还有两个工作尚未完成才对！ 那我们如何知道还有哪些列印工作在伫列内呢？可以使用底下的指令来观察喔！

[root@www ~]# lpq [-al] [-P 列印伫列]
选项与参数：
-a  ：列出所有印表机上面在伫列当中的工作情况；
-l  ：用其他较长格式来输出列印的相关资讯 (拥有者与档案大小等等)
-P  ：后面接特定的印表机，与 -a 不同。

# 1. 显示出目前所有印表机的工作伫列状况
[root@www ~]# lpq -a
Rank    Owner   Job     File(s)               Total Size
active  root    10      (stdin)               1024 bytes
1st     root    11      issue                 1024 bytes
# 上面的意思是，有 2 份工作，第一个工作为来自 stdin 的资料流，列印号码为 10 ，
# 整份列印资料占去 1024 bytes 。同理，第二份工作为档案，档名为 issue。

# 2. 用更详细的资讯显示列印工作
[root@www ~]# lpq -l -P hp_p2015
hp_p2015 is ready and printing

root: active                  [job 10 localhost]
        (stdin)                       1024 bytes

root: 1st                     [job 11 localhost]
        2 copies of issue             1024 bytes
# 你可以看到， issue 会被列印两份的资料！

如果这些列印工作你想要取消呢？那就使用 lprm 吧！

[root@www ~]# lprm [-P printer伫列] job_id
选项与参数：
-P  ：后面直接指定某部印表机的某个工作号码。注意，那个 job_id
      就是刚刚我们使用 lpq 查看到的那个 Job 的号码啦！

# 1. 将使用 lpq 看到的第 11 号列印工作取消！
[root@www ~]# lprm 11
[root@www ~]# lpq -a
Rank    Owner   Job     File(s)               Total Size
active  root    10      (stdin)               1024 bytes
# 瞧！只剩下一个工作而已啰！

整个指令模式处理印表机的任务大约到此为止，其他的，还是使用 Web 介面去管理比较方便啦！

  • 7. 一个简单的练习

假设你目前的 CentOS 主机上面接着一台 USB 介面的印表机，这台 USB 介面的印表机是 Samsung 的 ML-1210 印表机， 请问，您可以如何安装这部印表机？

  1. 先下载 PPD 定义档，档名为： Samsung-ML-1210-gdi.ppd 到 /usr/share/cups/model/ 当中；
  2. 加入印表机，使用下列方法：
    [root@www ~]# lpadmin -p samsung -v usb:/dev/usb/lp0 \
> -m Samsung-ML-1210-gdi.ppd -E
  3. 开始给他测试练习一下：‘ lpr -P samsung /etc/passwd ’如果有东西印出来，那就是 OK 啦！

另外，如果老是看到荧幕前面显示：‘ Printer not connected; will retry in 30 seconds...’， 很有可能是因为我们的装置代号输入错误，请使用‘ lpstat -t ’查阅一下是否正确的设定好了？ 基本上，安装一部 Linux 有支援的印表机，真的是快速啦！

大标题的图示 硬体资料收集与驱动，及 lm_sensors

‘工欲善其事，必先利其器’，这是一句大家耳熟能详的古人名言，在我们的资讯设备上面也是一样的啊！ 如同前面小节谈到的，如果你的印表机本身就没有提供给 Linux 系统用的驱动程式，那么我们就不要浪费时间在该印表机设备上了。 同理可证，如果我们想要好好的使用 Linux 安装在自己的主机上面，那么主机上面的硬体资讯最好还是能够了解一下的好。 现在一般主机板也都有提供 CPU 电压与温度的侦测，那我们也能够透过 lm_sensors 这个软体来取得该数据喔！ 底下就让我们来玩玩吧！

小标题的图示 硬体资讯的收集与分析

现在我们知道系统硬体是由作业系统核心所管理的，由第二十章的开机流程分析中，我们也知道 Linux kernel 在开机时就能够侦测主机硬体并载入适当的模组来驱动硬体了。 而核心所侦测到的各项硬体装置，后来就会被记录在 /proc 与 /sys 当中了。 包括 /proc/cpuinfo, /proc/partitions, /proc/interrupts 等等。 更多的 /proc 内容介绍，先回到第十七章的程序管理瞧一瞧先！

Tips:
其实核心所侦测到的硬体可能并非完全正确喔！因为他仅是‘使用最适当的模组来驱动这个硬体’而已， 所以有时候难免会误判啦 (虽然机率非常之低)！那你可能想要以最新最正确的模组来驱动你的硬体， 此时，重新编译核心是一条可以达成的道路。不过，现在的 Linux 系统并没有很建议你一定要重新编译核心就是了。 		鸟哥的图示

那除了直接呼叫出 /proc 底下的档案内容之外，其实 Linux 有提供几个简单的指令来将核心所侦测到的硬体叫出来的～ 常见的指令有底下这些：

  • fdisk：第八章曾经谈过，可以使用 fdisk -l 将分割表列出；
  • hdparm：第八章谈过的，可观察硬碟的资讯与测试读写速度；
  • dmesg：第十七章谈过， 观察核心运作过程当中所显示的各项讯息记录；
  • vmstat：第十七章谈过，可分析系统 (CPU/RAM/IO) 目前的状态；
  • lspci：列出整个 PC 系统的 PCI 介面装置！很有用的指令；
  • lsusb：列出目前系统上面各个 USB 埠口的状态，与连接的 USB 装置；
  • iostat：与 vmstat 类似，可即时列出整个 CPU 与周边设备的 Input/Output 状态。

lspci, lsusb, iostat 是本章新谈到的指令，尤其如果你想要知道主机板与各周边相关设备时，那个 lspci 真是不可多得的好工具！而如果你想要知道目前 USB 插槽的使用情况以及侦测到的 USB 装置， 那个 lsusb 则好用到爆！至于 iostat 则是一个即时分析软体，与 vmstat 有异曲同工之妙！ 既然本节是想要使用 lm_sensors 分析各元件的温度与电压，那么这几个指令得要来使用看看才行啊！ ^_^

基本上，想要知道你 Linux 主机的硬体配备，最好的方法还是直接拆开机壳去察看上面的资讯 (这也是为何第零章会谈计概啊)！ 如果环境因素导致您无法直接拆开主机的话，那么直接 lspci 是很棒的一的方法：

  • lspci
[root@www ~]# lspci [-vvn]
选项与参数：
-v  ：显示更多的 PCI 介面装置的详细资讯；
-vv ：比 -v 还要更详细的细部资讯；
-n  ：直接观察 PCI 的 ID 而不是厂商名称

范例一：查阅您系统内的 PCI 装置：
[root@www ~]# lspci
00:00.0 Host bridge: Silicon Integrated Systems [SiS] 630 Host (rev 30)
00:00.1 IDE interface: Silicon Integrated Systems [SiS] 5513 [IDE] (rev d0)
00:01.0 ISA bridge: Silicon Integrated Systems [SiS] SiS85C503/5513 (LPC Bridge)
00:01.2 USB Controller: Silicon Integrated Systems [SiS] USB 1.1 Controller (rev 07)
00:01.3 USB Controller: Silicon Integrated Systems [SiS] USB 1.1 Controller (rev 07)
00:01.4 Multimedia audio controller: Silicon Integrated Systems [SiS] SiS PCI Audio
Accelerator (rev 02)
00:02.0 PCI bridge: Silicon Integrated Systems [SiS] Virtual PCI-to-PCI bridge (AGP)
00:0e.0 Ethernet controller: Realtek Semiconductor Co., Ltd. RTL-8139/8139C/8139C+ (rev 10)
01:00.0 VGA compatible controller: Silicon Integrated Systems [SiS] 630/730 PCI/AGP
VGA Display Adapter (rev 21)
# 不必加任何的参数，就能够显示出目前主机上面的各个 PCI 介面的装置呢！

不必加上任何选项，就能够显示出目前的硬体配备为何。上面就是鸟哥的测试机所使用的主机配备。 包括使用 SIS 这家公司推出的 630 主机板晶片组，使用 USB 驱动为 1.1 版的控制器， 内建 SIS 的音效卡，使用内建整合的 SIS 的 AGP 显示卡，以及网路卡为螃蟹卡 (型号为 RTL-8139)。 您瞧瞧！很清楚，不是嘛。

由于目前的主机配备实在太高档了，因此很多朋友学习 Linux 时，习惯以类似 Virtualbox 或 VMWare 等虚拟机器进行模拟，此时你得要特别注意，你的硬体配备将是 Virtualbox 或 VMWare 模拟出来的，并不是原本的主机配备喔！实在是由于讨论区太多网友发问类似‘我的螃蟹卡为何捉不到’等问题， 询问后，才发现他使用 VMWare 模拟硬体。此时你就得要使用 lspci 去列出 Linux 核心捉到的硬体， 而不是你原本的硬体啦！注意注意！

如果你还想要了解某个设备的详细资讯时，可以加上 -v 或 -vv 来显示更多的资讯喔！ 举例来说，鸟哥想要知道那个乙太网路卡更详细的资讯时，可以使用如下的选项来处理：

[root@www ~]# lspci -s 00:0e.0 -vv

-s 后面接的那个怪东西每个设备的汇流排、插槽与相关函数功能啦！那个是我们硬体侦测所得到的数据啰！ 你可以对照底下这个档案来了解该串数据的意义：

  • /usr/share/hwdata/pci.ids

其实那个就是 PCI 的标准 ID 与厂牌名称的对应表啦！ 此外，刚刚我们使用 lspci 时，其实所有的资料都是由 /proc/bus/pci/ 目录下的资料所取出的呢！了解了吧！ ^_^

  • lsusb

刚刚谈到的是 PCI 介面装置，如果是想要知道系统接了多少个 USB 装置呢？那就使用 lsusb 吧！ 这个指令也是很简单的！

[root@www ~]# lsusb [-t]
选项与参数：
-t  ：使用类似树状目录来显示各个 USB 埠口的相关性

范例一：列出目前鸟哥的测试用主机 USB 各埠口状态
[root@www ~]# lsusb
Bus 001 Device 001: ID 0000:0000
Bus 002 Device 001: ID 0000:0000
Bus 002 Device 002: ID 0d62:a100 Darfon Electronics Corp. Benq Mouse
# 如上所示，鸟哥的主机有两个 USB 控制器 (bus)，而 Bus 002 有接了一个设备，
# 该设备的 ID 是 0d62:a100，对应的厂商与产品为 Benq 的滑鼠。

确实非常清楚吧！其中比较有趣的就属那个 ID 号码与厂商型号对照了！那也是写入在 /usr/share/hwdata/pci.ids 的东西，你也可以自行去查询一下喔！更多资讯我们留待下一小节再来讨论吧！

  • iostat

刚刚那个 lspci 找到的是目前主机上面的硬体配备，那么整部机器的储存设备， 主要是硬碟对吧！请问，您硬碟由开机到现在，已经存取多少资料呢？这个时候就得要 iostat 这个指令的帮忙了！ 不过，预设 CentOS 并没有安装这个软体，因此你必须要先安装他才行！如果你已经有网路了， 那么使用‘ yum install sysstat ’先来安装此软体吧！否则无法进行如下的测试喔！

[root@www ~]# iostat [-c|-d] [-k|-m] [-t] [间隔秒数] [侦测次数]
选项与参数：
-c  ：仅显示 CPU 的状态；
-d  ：仅显示储存设备的状态，不可与 -c 一起用；
-k  ：预设显示的是 block ，这里可以改成 K bytes 的大小来显示；
-m  ：与 -k 类似，只是以 MB 的单位来显示结果。
-t  ：显示日期出来；

范例一：显示一下目前整个系统的 CPU 与储存设备的状态
[root@www ~]# iostat
Linux 2.6.18-92.el5 (www.vbird.tsai)    06/03/2009

avg-cpu:  %user   %nice %system %iowait  %steal   %idle
           0.35    0.31    0.25    0.03    0.00   99.06

Device:            tps   Blk_read/s   Blk_wrtn/s   Blk_read   Blk_wrtn
hda               0.29         3.46         4.01    1116645    1295796
# 瞧！上面数据总共分为上下两部分，上半部显示的是 CPU 的当下资讯；
# 下面数据则是显示储存装置 /dev/hda 的相关数据，他的数据意义：
# tps       ：平均每秒钟的传送次数！与资料传输‘次数’有关，非容量！
# kB_read/s ：开机到现在平均的读取单位；
# kB_wrtn/s ：开机到现在平均的写入单位；
# kB_read   ：开机到现在，总共读出来的档案单位；
# kB_wrtn   ：开机到现在，总共写入的档案单位；

范例二：每两秒钟侦测一次，并且共侦测三次储存装置
[root@www ~]# iostat -d 2 3
Linux 2.6.18-92.el5 (www.vbird.tsai)    06/03/2009

Device:            tps   Blk_read/s   Blk_wrtn/s   Blk_read   Blk_wrtn
hda               0.29         3.46         4.01    1116645    1296276

Device:            tps   Blk_read/s   Blk_wrtn/s   Blk_read   Blk_wrtn
hda               0.00         0.00         0.00          0          0

Device:            tps   Blk_read/s   Blk_wrtn/s   Blk_read   Blk_wrtn
hda               0.00         0.00         0.00          0          0
# 仔细看一下，如果是有侦测次数的情况，那么第一次显示的是‘从开机到现在的数据’，
# 第二次以后所显示的资料则代表两次侦测之间的系统传输值！举例来说，上面的资讯中，
# 第二次显示的资料，则是两秒钟内(本案例)系统的总传输量与平均值。

透过 lspci 及 iostat 可以约略的了解到目前系统的状态啊！ 还有目前的主机硬体资料呢！知道这些资讯后，我们就可以来玩一些比较不一样的东西啰！ ^_^

小标题的图示 驱动 USB 装置

在现在的电脑里面，你或许真的无法想像没有 USB 介面装置的主机～ 因为不论我们的键盘、滑鼠、印表机、扫描器、随身碟等等，几乎都是使用到 USB 来作为传输的介面的。 所谓这 USB (Universal Serial Bus) 最早是在 1994 年被发展出来，到 1996 年前后发展出 version 1.0 ，当时的速度大约在 12Mbit/second，到了 2000 年发展出 version 2.0 ，这一版的速度则提高到 480Mbit/second， 这也是目前使用最广泛的一个速度。2008 年则释出 USB 3.0，这一版的速度比 2.0 要快十倍喔！ 不过目前市面上的产品还是非常的少见。(注2)

USB 有很多的优点啦，包括他是可以延伸的，每个 USB port 都可以最多接到 127 个装置！ 速度又快，又具有 Plug and Play (随插即用) 的优点，所以近期以来被用来作为携带式装置的主要资料传输介面呢！

  • 关于 USB 的晶片版本

目前 USB 1.1版本的控制器主要有两种规格，分别是：

  • OHCI (Open Host Controller Interface)：主要由 Compaq 所发展，包括 Compaq, SiS, ALi 等等厂商发展的晶片都是用这个模组；

  • UHCI (Universal Host Controller Interface)：主要由 Intel 所发展， 包括 Intel, VIA 等等厂商发展的晶片都是使用这个模组。

由于我们的 Linux 会将这两种 USB 的驱动程式载入，因此不论你的 USB 是使用哪种晶片，我们的 Linux 都可以顺利的侦测到并且正确的驱动的啦！至于 USB 2.0 在 Linux 上都以 Enahnced Host Controller Interface (EHCI) 来驱动的。我们使用 lsmod 来找一下 hci 这个关键字看看，鸟哥的测试主机驱动了多少 USB 模组了呢？

[root@www ~]# lsmod | grep hci
Module                  Size  Used by
uhci_hcd               25421  0
ohci_hcd               23261  0
ehci_hcd               33357  0
# 三个模组都有载入，再来找一下 ehci_hcd 的说明看看：

[root@www ~]# modinfo ehci_hcd
filename:       /lib/modules/2.6.18-92.el5/kernel/drivers/usb/host/ehci-hcd.ko
license:        GPL
author:         David Brownell
description:    10 Dec 2004 USB 2.0 'Enhanced' Host Controller (EHCI) Driver
srcversion:     006DD5CF82C35E943696BE7
....(底下省略)....

  • 启动 USB 的随身碟或快闪碟

我们之前谈过 USB 的磁碟代号是： /dev/sd[a-p] 之类的，类似 SCSI 硬碟的代号， 这是因为 USB 的磁碟装置使用 SCSI 相关的装置代号，因此，如果您要使用 USB 随身碟的话，嘿嘿！那么您的 Linux 主机就得要支援 SCSI 装置才行～

此外，为了让 USB 磁碟装置顺利的被使用，因此，有时候还得要启动 usb-storage 模组才行～ 所以啰，光是有 USB 的 uhci 模组还不行，还得要配合 usb-storage 啦～ 而一般 USB 的装置都会被主动的侦测，核心也会主动的载入 USB 装置的驱动模组， 所以你应该不需要手动载入 usb-storage 才是。不过，如果老是无法驱动时，那么不妨手动载入 usb-storage 试看看。

顺利载入各个需要的模组之后，直接下达 fdisk -l 应该就可以看到您的 USB 随身碟的装置代号才是！一般来说，如果是第一个 USB 磁碟装置的话， 应该可以看到一个名为 /dev/sda1 的装置，使用 mount 将他挂载起来即可啊！

在这里要强调的是，如果你是使用类似笔记型电脑的 2.5 吋硬碟作为随身硬碟的话，由于他就是硬碟的规格， 因此你可以看到一个完整的 /dev/sda 之类的磁碟资讯，你也可以进行额外的分割。但如果是快闪碟的话， 快闪碟并不是传统的硬碟，他并不是使用磁碟读取头与磁碟盘来记录资料，因此你只能使用 /dev/sda1 之类的档名来挂载， 理论上是无法进行额外分割的喔！这部份要特别强调一下。

  • 启动 USB 印表机

要驱动 USB 印表机也很简单啊！只要做好 USB 印表机的装置代号即可！反正我们的 usb 模组已经载入了嘛！ 目前的 CentOS 5.x 会主动的帮我们建立印表机的装置档名，所以底下的动作我们根本不需要进行。 不过如果你的 Linux 是较老式的系统，那可能得要使用 mknod 来建立起 USB 印表机才行。 透过核心装置代码(注3)的查询，我们知道 USB 印表机的主要/次要装置代码为 180 /0~15， 所以，建立的方法为：

# 假设你已经有 /dev/usb/lp0 ，那我们来尝试建立 /dev/usb/lp1 看看
[root@www ~]# mkdir -p /dev/usb
[root@www ~]# mknod /dev/usb/lp1 c 180 1
[root@www ~]# chown root:lp /dev/usb/lp1
[root@www ~]# chmod 660 /dev/usb/lp1
[root@www ~]# ls -l /dev/usb/lp1
crw-rw---- 1 root lp 180, 1 Jun  3 14:27 /dev/usb/lp1
[root@www ~]# echo "testing" > /dev/usb/lp1

在我们一般的生活当中，最常见的两种 USB 装置就是随身碟与印表机了， 所以鸟哥在这里仅就这两种装置来介绍启动的方法，如果您还有其他的 USB 装置要驱动的话， 请参考底下这一篇的内容啊！

  • http://www.linux-usb.org/USB-guide/book1.html
小标题的图示 使用 lm_sensors 取得温度、电压等资讯

玩电脑硬体的朋友们一定都听过所谓的‘超频’这玩意儿，所谓的‘超频’就是让系统原有的运作时脉增加， 让 CPU/PCI/VGA 前端汇流排速度提升到非正规的频率，以取得较高的电脑效能。 这在早期对于单价还是很贵的电脑来说，可以让我们花比较少的钱去获得比较高效能的电脑哩！ 不过，超频要注意的地方可不少，包括电压不可高出 CPU 的负荷、CPU 风扇必须要强有力， 避免因为温度过高导致系统当机等等。

不过现今的电脑速度已经够快了，我们的 Linux 主机也实在不建议您超频，因为整体效能可能增加不了多少， 但是却会让您的主机寿命减少、系统不稳定呢！而由早期超频的‘技术培养’过程当中，我们知道‘CPU 的温度、系统的相关电压’ 是影响主机是否稳定的一项重要指标喔！所以啰，如果能够随时掌握温度、电压， 其实对于系统还是有一定程度的监控啦。

其实各大主要主机板商与晶片组，都会有温度、电压的侦测器在主机内，这个我们可以在主机板操作手册或者是在 BIOS 内的‘ Monitor ’项目找到相关的温度、电压资料。在 Windows 系统当中，厂商有推出相关的软体来侦测，那么在 Linux 当中呢？呵呵！也是有啊！那就是 lm_sensors 这套好用的东西了！

目前较新的 Linux distributions 都预设会帮忙安装这套软体，但如果你的 Linux 是比较早期的版本，那么就只好请您自行前往 http://www.lm-sensors.org/ 官方网站直接下载 tarball 并且安装他啰～

  • 侦测主机板的型号

由于 lm_sensors 主要是依据‘主机板晶片组的型号，带入相关的模组后，再侦测其温度、电压’的， 如果该主机板晶片组并不是 lm_sensors 所支援的模组，那自然就无法找出该晶片组的温压啰～ 所以啦，我们在使用 lm_sensors 之前，必须要确定主机板是有提供温度、电压的， 再来，必须要载入主机板的驱动模组，然后才有办法使用 lm_sensors 来进行侦测。

好消息是， lm_sensors 本来就提供我们一个不错的主机板晶片组侦测程式， 那就是 sensors-detect 这个指令。侦测到主机板晶片组后，将该资讯写入设定档当中， 就可以使用 sensors 指令直接读取目前的 CPU、机壳、电源、风扇等等的资讯了！ 直接来作看看吧！

[root@www ~]# sensors-detect
# sensors-detect revision 1.413 (2006/01/19 20:28:00)
....(中间省略)....
It is generally safe and recommended to accept the default answers to all
questions, unless you know what you're doing. <==就一直接受就对了！

 We can start with probing for (PCI) I2C or SMBus adapters.
 You do not need any special privileges for this.
 Do you want to probe now? (YES/no): y
Probing for PCI bus adapters...
Use driver `i2c-sis630' for device 00:00.0: Silicon Integrated Systems SIS630
Probe succesfully concluded.
# 接下来的行为当中，反正你就一直按 Enter 就可以了！让他自动去侦测！

To make the sensors modules behave correctly, add these lines to
/etc/modprobe.conf:

#----cut here----
# I2C module options
alias char-major-89 i2c-dev
#----cut here----

To load everything that is needed, add this to some /etc/rc* file:

#----cut here----
# I2C adapter drivers
modprobe i2c-sis630
modprobe i2c-isa
# I2C chip drivers
modprobe eeprom
modprobe it87
# sleep 2 # optional
/usr/bin/sensors -s # recommended
#----cut here----

Do you want to generate /etc/sysconfig/lm_sensors? (YES/no):
Copy prog/init/lm_sensors.init to /etc/rc.d/init.d/lm_sensors
for initialization at boot time.

上面就进行好型号的侦测，并且主动的建立了 /etc/sysconfig/lm_sensors 的参数设定档。不过我们依旧需要进行一些额外的处理！ 包括让系统开机主动载入模组的功能！这样我们就能够直接使用 lm_sensors 来侦测而不需要手动载入侦测模组啊！ 你可以这样做：

[root@www ~]# vi /etc/modprobe.conf
alias char-major-89 i2c-dev
# 将刚刚侦测到的模组给他写入到这个档案当中！

[root@www ~]# vi /etc/rc.d/rc.local
# I2C adapter drivers
modprobe i2c-sis630
modprobe i2c-isa
# I2C chip drivers
modprobe eeprom
modprobe it87
sleep 2s
/usr/bin/sensors -s

[root@www ~]# chkconfig --list  lm_sensors
lm_sensors      0:off   1:off   2:on    3:on    4:on    5:on    6:off
# 确定 lm_sensors 预设开机会启动即可！此时你可以重新 reboot ，
# 或者执行上述的 modprobe 之后，在进行底下的侦测啰！

  • 利用 sensors 侦测温度、电压等硬体参数

侦测的指令就是 sensors 啊！直接动作吧！

[root@www ~]# sensors
it87-isa-0290  <==使用到的模组功能！
Adapter: ISA adapter
VCore 1:   +1.55 V  (min =  +1.42 V, max =  +1.57 V)
VCore 2:   +1.09 V  (min =  +2.40 V, max =  +2.61 V)   ALARM
+3.3V:     +1.25 V  (min =  +3.14 V, max =  +3.47 V)   ALARM
+5V:       +2.69 V  (min =  +4.76 V, max =  +5.24 V)   ALARM
+12V:      +5.82 V  (min = +11.39 V, max = +12.61 V)   ALARM
-12V:     -17.05 V  (min = -12.63 V, max = -11.41 V)   ALARM
-5V:       -7.40 V  (min =  -5.26 V, max =  -4.77 V)   ALARM
Stdby:     +2.07 V  (min =  +4.76 V, max =  +5.24 V)   ALARM
VBat:      +0.40 V
fan1:        0 RPM  (min =    0 RPM, div = 2)
fan2:        0 RPM  (min = 3000 RPM, div = 2)          ALARM
fan3:     2689 RPM  (min = 3000 RPM, div = 2)
M/B Temp:    +33°C  (low  =   +15°C, high =   +40°C)   sensor = diode
CPU Temp:    +37°C  (low  =   +15°C, high =   +45°C)   sensor = thermistor
Temp3:        -5°C  (low  =   +15°C, high =   +45°C)   sensor = disabled
# 你可以发现一大堆的错误讯息！没关系的！这是因为鸟哥的主机板太旧，
# 导致 lm_sensors 误判，所以输出的结果就会有点差异！至少转速与温度是正常的啦！

基本上，只要这样的步骤，您的主机就可以主动的侦测温度与电压，还有风扇转速等等资讯。 不过，事实上，由于主机板设计的不同，所以侦测的结果很有可能是有误差的。以鸟哥的情况来说， 我所使用的主机板型号是太旧了，lm_sensors 确实捉到错误的资讯啊！此时或许就需要进行调校了。 调校的步骤很简单，先确定使用 sensors 显示的结果每个项目代表的意义 (可以参考 BIOS 硬体侦测结果的顺序来排列) ，然后进入 /etc/sensors.conf 进行修改即可。

如果想要以图表输出的话，那么不妨搭配 MRTG 来进行网页绘图～ 这部分网路上面文章就比较多一点，也可以先参考鸟哥的一篇旧文章：

  • http://linux.vbird.org/linux_security/old/04mrtg.php
小标题的图示 udev 与 hal 简介

从上面的介绍中，我们不难发现目前新的 Linux distributions 大多能够类似视窗作业系统，就是能够即时的侦测随插即用硬体！ 例如 USB 介面的各项硬体设备等等。那我们也知道其实所有的硬体都是档案，这些装置档案必须要使用 mknod 才能建立的！ 那到底 (1)硬体如何侦测与 (2)装置档案如何主动建立呢？这就与 udev 及 HAL 这两个东西有关了。

事实上，系统所有的硬体应该都是给核心管理的，但我们知道作业系统在记忆体内是受保护的，使用者根本无权使用作业系统核心。 为了解决这个问题于是有 udev 的产生。这个 udev 是个使用者层级软体，他可以让使用者自行处理 /dev 底下的装置！ 如此一来就能够解决一般用户在使用类似 USB 时，需要额外硬体的问题。(注4)

但我们如何知道系统上面多了个硬体呢？这时候就得要硬体抽象层 (Hardware Abstraction Layer, HAL) 的辅助了。 HAL 可以将系统目前的所有硬体进行快照，并持续检视这个快照的内容(注5)。如果有新的 PnP 硬体插入时， HAL 就会发现目前的硬体与快照不同，此时就会通知 udev 进行新的装置的建置了！如此一来，两者的配合就能够让你的装置 PnP 啰！

目前这两个咚咚在 CentOS 上面都会是启动的，其中 udev 是在 /etc/rc.d/rc.sysinit 就启动了， 而 hal 则是在 /etc/init.d/haldaemon 这个服务才启动。让我们检查看看是否真的有启动啊！

[root@www ~]# pstree -p | egrep '(udevd|hal)'
        |-hald(4814)---hald-runner(4815)-+-hald-addon-acpi(4822)
        |                                |-hald-addon-keyb(4827)
        |                                `-hald-addon-stor(4837)
        |-udevd(401)
# 确实有启动喔！一个是 udevd 一个是 hald 啦！

老实说，如果你已经启动了这两个家伙，那么其他的事不需要进行，交给这两个小玩意儿自己处理即可。 但如果你想要多了解 udev 是如何进行装置的建立时，那么我们可以来玩玩底下的咚咚。

  • 自订装置名称进行装置建立

假设你想要将你的随身碟取名为较有趣的装置，不想再使用类似 /dev/sda1 之类的名称时，可以怎么作呢？ 我们可以透过更改 udev 的规则 (rule) 来使用 mknod 建立不同名称的装置档案。举例来说， 鸟哥这部测试机的硬碟使用为 /dev/hda ，因此第一个 USB 快闪碟装置应该是 /dev/sda1 才对！ 如果你的系统使用 SATA 磁碟，那么你的快闪碟可能就得要由 /dev/sdb1 开始编号起来了。

udev 建立装置档案的规则放置到 /etc/udev/rules.d/ 目录下，在该目录下的档案可以依序进行处理的。 以最简单的语法来看，在该目录下可以使用的变数与对应可以是：

KERNEL=="核心能够分析到的档名", NAME="你要使用的装置档名"

当然还有很多语法，不过这里我们先不介绍，有兴趣的查一下本文最后的连结去看看吧！ 假设鸟哥的 /dev/sda1 要取名字成为 /dev/vbirdusb ，你可以这样做：

# 1. 先在规则目录下新增一个档案，档名设定为 99-vbirdusb.rules 好了
[root@www ~]# cd /etc/udev/rules.d/
[root@www rules.d]# vi 99-vbirdusb.rules
KERNEL=="sda1", NAME="vbirdusb"
# 上面这一行就足够啦！注意，档名前的 /dev 不需要写入！

# 2. 插入一支随身碟，然后检查看看：
[root@www rules.d]# ll /dev/sda* /dev/vbirdusb
brw-r----- 1 root disk 8, 0 Jun  3 16:43 /dev/sda
brw-r----- 1 root disk 8, 1 Jun  3 16:43 /dev/vbirdusb
# 唔！ /dev/sda1 不见了！取而代之的是 /dev/vbirdusb 啦！

[root@www rules.d]# mount /dev/vbirdusb /mnt
[root@www rules.d]# df
Filesystem           1K-blocks      Used Available Use% Mounted on
....(中间省略)....
/dev/vbirdusb           976064    192784    783280  20% /mnt
# 很有趣吧！装置名称被鸟哥改过了！

虽然这样很具有个性化的需求，不过总是不太可靠～万一哪天忘记自己有进行这些动作，偏偏用核心预设的档名去处理时， 会发生很多不明的错误啊！所以将刚刚建立的资料反向删除回来吧！

# 1. 先卸载系统吧！
[root@www ~]# umount /dev/vbirdusb

# 2. 拔除随身碟，并将规则档删除！
[root@www ~]# rm /etc/udev/rules.d/99-vbirdusb.rules

# 3. 再插入随身碟，测试一下档名有没有恢复正常？
[root@www ~]# ll /dev/sda*
brw-r----- 1 root disk 8, 0 Jun  3 16:50 /dev/sda
brw-r----- 1 root disk 8, 1 Jun  3 16:50 /dev/sda1
# 看起来，档名确实恢复正常啰！
大标题的图示 重点回顾
  • CentOS 提供了好用的 setup 功能，可以帮忙设定 (1)认证方式 (2)防火墙设定 (3)键盘格式设定 (4)网路设定 (5)系统预设启动的服务设定 (6)时区设定 (7)X 解析度与硬体设定 等功能；
  • 网际网路 (Internet) 就是 TCP/IP ，而 IP 的取得需与 ISP 要求。一般常见的取得 IP 的方法有：(1)手动直接设定 (2)自动取得 (dhcp) (3)拨接取得 (4)cable宽频 等方式。
  • 主机的网路设定要成功，必须要有底下的资料：(1)IP (2)Netmask (3)gateway (4)DNS 伺服器 等项目；
  • DNS 伺服器 IP 的指定，需写入 /etc/resolv.conf 这个档案中；
  • 预设 Linux 的列印服务使用 CUPS ，更早之前则是使用 lpd 这个服务；
  • Linux 支援的印表机网站查询： http://www.linuxfoundation.org/en/OpenPrinting
  • 列印元件主要有：列印指令、列印工作、列印伫列、列印服务、印表机
  • 网路印表机的格式主要有： ipp, smb 等类别；
  • CUPS 可使用 http://localhost:631 来连接，然后使用浏览器介面来管理！
  • PPD 指的是 postscript 列印定义档，可视为印表机的驱动程式；
  • 指令列管理印表机的方式主要透过： lpadmin, lpstat, lpq, lprm 等指令。至于产生列印工作的指令则为 lpr, lp
  • 本章新增硬体资讯的收集指令有： lspci, lsusb, iostat 等；
  • USB 的驱动模组主要有 OHCI 与 UHCI，至于 USB 2.0 则使用 EHCI。
  • lm_sensors 可用来侦测主机板的温度、电压、风扇转速等功能；
  • 动态管理硬体，透过使用者层级的管理方式，主要透过 udev 与 HAL 的管理！
大标题的图示 本章习题
( 要看答案请将滑鼠移动到‘答：’底下的空白处，按下左键圈选空白处即可察看)
简答题部分：
  • 如果你硬是要建立一个不存在的印表机装置档案，例如： /dev/usb/lp8，该如何处置？
    首先，必须要查阅得该装置的主要装置代号，亦即 180，至于次要代号则是 8 ， 再使用 mknod 来建立，因此，需要这样做：
    mknod /dev/usb/lp8 c 180 8
    chown root:lp /dev/usb/lp8
    chmod 660 /dev/usb/lp8
  • 如果你想要知道整个系统的周边硬体装置，可以使用哪个指令查询？
    lspci 可以查询到，更可使用 lspci -v 来查询更详细资讯。
  • 承上题，那么如果单纯只想要知道 USB 装置呢？又该如何查询？
    lsusb就可以查询的到！
  • 试说明 (1)列印工作 (2)列印伫列 (3)列印指令 (4)列印服务 (5)印表机之间的相关性。
    列印指令可以产生列印工作，列印工作会在列印伫列里面排队等待被列印。在伫列内的资料于列印服务有启动的环境下， 该资料可以被转成印表机可读的格式，最终列印服务会将伫列工作转成适合的资料交给印表机列印出来。 详细资料可参考图 2.1.4 的说明。
  • 说出三种以上目前常见的网路列印通讯协定。
    例如 IPP, LPD, SMB 等均是列印的通讯协定。
  • 如何使用 lm_sensors 侦测主机内的温度，详细说明整个步骤？
    • 先确定您的主机板具有温度与电压等侦测晶片，可使用 lspci 检查晶片组；
    • 开机进入 BIOS 后，查询一下是否具有硬体侦测温度、电压的项目，将输出的项目顺序记一下；
    • 确定 Linux 已经安装了 lm_sensors，再使用 sensors-detect 检查所需要的设定项目；
    • 依据上个步骤，设定 /etc/modprobe.conf 及 /etc/rc.d/rc.local 两个档案；
    • 使用 chkconfig 让 lm_sensors 开机启动，并且重新开机 (reboot)；
    • 开始使用 sensors 进行侦测，也可以尝试修改 /etc/sensors.conf 的内容，以符合实际状况。
  • (挑战题)如果你的网路设定妥当了，但是却老是发现网路不通，你觉得应该如何进行测试？
    (1)先检查硬体，每个环节 (网卡、hub/switch、路由器等) 的灯号是否有亮？有亮再进行下个动作；
    (2)使用 ifconfig 检查 IP 与 netmask 的资料是否正确，若正确才可进行下一步；
    (3)使用 route 看看 default gateway 是否正确，若正确再进行下一步；
    (4)使用 ping -c 3 [gateway IP] ，若有回应才进行下一步；
    (5)使用 ping -c 3 [外部IP，例如 168.95.1.1] ，若有回应则 IP 正常，若无回应，请检查 gateway 的设定
    (6)使用 dig www.google.com 看看能否找到 IP ，找不到则请检查 /etc/resolv.conf 的设定。
大标题的图示 参考资料与延伸阅读
  • 注1：PPD 的解释：http://en.wikipedia.org/wiki/PostScript_Printer_Description
  • 注2：USB 的相关解释与书籍
    维基百科的解释：http://en.wikipedia.org/wiki/Universal_Serial_Bus
    USB 的线上书籍：http://www.linux-usb.org/USB-guide/book1.html
    Linux USB ：http://www.linux-usb.org/
  • 注3：核心代码的相关网页：http://www.kernel.org/pub/linux/docs/device-list/devices.txt
  • 注4：关于 udev 的简单说明：
    核心网站的说明：http://kernel.org/pub/linux/utils/kernel/hotplug/udev.html
    linuxjournal 的说明：http://www.linuxjournal.com/article/7316
  • 注5：hal 的官网 http://www.freedesktop.org/wiki/Software/hal
  • LM_sensors 官方网站：http://www.lm-sensors.org/
2005/10/25：准备准备～写一些跟硬体比较有关系的资料！
2005/11/08：准备完毕 USB 与 lm_sensors 的部分了～啊！拖了真久～还有 RAID 的说明也差不多哩！
2005/11/09：加入了 FC4 的 setup 指令，尤其是印表机的部分，可以参考参考！
2005/11/10：终于将 iSCSI 的装置写好了～这部份真的是很有趣！不过，一般使用者可能碰不到就是了。
2005/11/13：终于将 CUPS 架构设定好自己的 Printer 部分了！
2005/11/14：连同 LVM 也大致的给他写完了！那个 resize2fs 指令确实有趣！
2005/11/25：加入一个简单的练习题～利用 dd 配合 resize2fs 来制作备份的资料！
2009/04/30：将 LVM 移动到 第十五章 ，且拿掉 iSCSI 的说明了。
2009/04/30：将旧的基于 FC4 撰写的版本移动到 此处 。
2009/06/03：加入 udev 与 hal 的简单说明！
2009/09/15：简单修订一些语句，修改章节的习题，并没有改到什么重要的资讯。


鸟哥的 Linux 私房菜 -- 原始码与 Tarball 软体管理员

为取得较佳浏览结果，请爱用 firefox 浏览本网页
鸟哥的 Linux 私房菜馆 | Linux 基础文件 | Linux 架站文件 | Linux 企业运用 | 安全管理 | 新手讨论 |

第二十二章、软体安装：原始码与 Tarball
最近更新日期：2009/09/15
我们在第一章、Linux是什么当中提到了 GNU 计划与 GPL 授权所产生的自由软体与开放源码等咚咚。不过，前面的章节都还没有提到真正的开放源码是什么的讯息！在这一章当中，我们将藉由 Linux 作业系统里面的执行档，来理解什么是可执行的程式，以及了解什么是编译器。另外，与程式息息相关的函式库 (library) 的资讯也需要了解一番！不过，在这个章节当中，鸟哥并不是要你成为一个开放源码的程式设计师， 而是希望你可以了解如何将开放源码的程式设计、加入函式库的原理、透过编译而成为可以执行 的 binary program，最后该执行档可被我们所使用的一连串过程！

了解上面的咚咚有什么好处呢？因为在 Linux 的世界里面，由于客制化的关系，有时候我们需要自行安装软体在自己的 Linux 系统上面，所以如果你有简单的程式编译概念，那么将很容易进行软体的安装。 甚至在发生软体编译过程中的错误时，你也可以自行作一些简易的修订呢！而最传统的软体安装过程， 自然就是由原始码编译而来的啰！所以，在这里我们将介绍最原始的软体管理方式：使用 Tarball 来安装与升级管理我们的软体喔！

1. 开放源码的软体安装与升级简介
    1.1 什么是开放源码、编译器与可执行档
    1.2 什么是函式库
    1.3 什么是 make 与 configure
    1.4 什么是 Tarball 的软体
    1.5 如何安装与升级软体
 2. 使用传统程式语言进行编译的简单范例
    2.1 单一程式：印出 Hello World
    2.2 主、副程式连结：副程式的编译
    2.3 呼叫外部函式库：加入连结的函式库
    2.4 gcc 的简易用法 (编译、参数与链结)
 3. 用 make 进行巨集编译
    3.1 为什么要用 make
    3.2 makefile 的基本语法与变数
 4. Tarball 的管理与建议
    4.1 使用原始码管理软体所需要的基础软体
    4.2 Tarball 安装的基本步骤
    4.3 一般 Tarball 软体安装的建议事项 (如何移除？升级？)
    4.4 一个简单的范例、利用 ntp 来示范
    4.5 利用 patch 更新原始码
 5. 函式库管理
    5.1 动态与静态函式库
    5.2 ldconfig 与 /etc/ld.so.conf
    5.3 程式的动态函式库解析： ldd
 6. 检验软体的正确性
    6.1 md5sum / sha1sum
 7. 重点回顾
8. 课后练习
9. 参考资料与延伸阅读
10. 针对本文的建议：http://phorum.vbird.org/viewtopic.php?t=23892
大标题的图示 开放源码的软体安装与升级简介

如果鸟哥想要在我的 Linux 伺服器上面跑网页伺服器 (WWW server) 这项服务，那么我应该要做些什么事呢？当然就一定需要‘安装网页伺服器的软体’啰！如果鸟哥的伺服器上面没有这个软体的话，那当然也就无法启用 WWW 的服务啦！所以啦，想要在你的 Linux 上面进行一些有的没的功能，学会‘如何安装软体’是很重要的一个课题！

咦！安装软体有什么难的？在 W 牌的作业系统上面安装软体时，不是只要一直给他按 ‘下一步’就可以安装妥当了吗？话是这样说没错啦，不过，也由于如此，所以在 Windows 系统上面的软体都是一模一样的，也就是说，你‘无法修改该软体的原始程式码’，因此， 万一你想要增加或者减少该软体的某些功能时，大概只能求助于当初发行该软体的厂商了！(这就是所谓的商机吗？)

或许你会说：‘唉呦！我不过是一般人，不会用到多余的功能，所以不太可能会更动到程式码的部分吧？’ 如果你这么想的话，很抱歉～是有问题的！怎么说呢？像目前网路上面的病毒、黑客软体、臭虫程式等等， 都可能对你的主机上面的某些软体造成影响，导致主机的当机或者是其他资料损毁等等的伤害。 如果你可以藉由安全资讯单位所提供的修订方式进行修改， 那么你将可以很快速的自行修补好该软体的漏洞，而不必一定要等到软体开发商提供修补的程式包哩！要知道，提早补洞是很重要的一件事。

Tips:
并不是软体开发商故意要搞出一个有问题的软体，而是某些程式码当初设计时可能没有考量周全， 或者是程式码与作业系统的权限设定并不相同，所导致的一些漏洞。当然，也有可能是 cracker 透过某些攻击程式测试到程式的不周全所致。 无论如何，只要有网路存在的一天，可以想像的到，程式的漏洞永远补不完！但能补多少就补多少吧！ 		鸟哥的图示

这样说可以了解 Linux 的优点了吗？没错！因为 Linux 上面的软体几乎都是经过 GPL 的授权，所以每个软体几乎均提供原始程式码， 并且你可以自行修改该程式码，以符合你个人的需求呢！很棒吧！这就是开放源码的优点啰！不过，到底什么是开放源码？ 这些程式码是什么咚咚？又 Linux 上面可以执行的相关软体档案与开放源码之间是如何转换的？不同版本的 Linux 之间能不能使用同一个执行档？或者是该执行档需要由原始程式码的部分重新进行转换？ 这些都是需要厘清观念的。底下我们先就原始程式码与可执行档来进行说明。

小标题的图示 什么是开放源码、编译器与可执行档

在讨论程式码是什么之前，我们先来谈论一下什么是可执行档？我们说过，在 Linux 系统上面，一个档案能不能被执行看的是有没有可执行的那个权限 (具有 x permission)，不过，Linux 系统上真正认识的可执行档其实是二进位档案 ( binary program)，例如 /usr/bin/passwd, /bin/touch 这些个档案即为二进位程式码。

或许你会说 shell scripts 不是也可以执行吗？其实 shell scripts 只是利用 shell (例如 bash) 这支程式的功能进行一些判断式，而最终执行的除了 bash 提供的功能外，仍是呼叫一些已经编译好的二进位程式来执行的呢！ 当然啦， bash 本身也是一支二进位程式啊！那么我怎么知道一个档案是否为 binary 呢？还记得我们在第七章里面提到的 file 这个指令的功能吗？对啦！用他就是了！我们现在来测试一下：

# 先以系统的档案测试看看：
[root@www ~]# file /bin/bash
/bin/bash: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), for GNU/
Linux 2.6.9, dynamically linked (uses shared libs), for GNU/Linux 2.6.9, stripped

# 如果是系统提供的 /etc/init.d/syslog 呢？
[root@www ~]# file /etc/init.d/syslog
/etc/init.d/syslog: Bourne-Again shell script text executable

看到了吧！如果是 binary 而且是可以执行的时候，他就会显示执行档类别 (ELF 32-bit LSB executable)， 同时会说明是否使用动态函式库 (shared libs)，而如果是一般的 script ，那他就会显示出 text executables 之类的字样！

Tips:
事实上，syslog 的资料显示出 Bourne-Again ... 那一行，是因为你的 scripts 上面第一行有宣告 #!/bin/bash 的缘故，如果你将 script 的第一行拿掉，那么不管 /etc/init.d/syslog 的权限为何，他其实显示的是 ASCII 文字档的资讯喔！ 		鸟哥的图示

既然 Linux 作业系统真正认识的其实是 binary program，那么我们是如何做出这样的一支 binary 的程式呢？首先，我们必须要写程式，用什么东西写程式？就是一般的文书处理器啊！鸟哥都喜欢使用 vim 来进行程式的撰写，写完的程式就是所谓的原始程式码啰！ 这个程式码档案其实就是一般的纯文字档。 在完成这个原始码档案的编写之后，再来就是要将这个档案‘编译’成为作业系统看的懂得 binary program 啰！而要编译自然就需要‘编译器’来动作， 经过编译器的编译与连结之后，就会产生一支可以执行的 binary program 啰。

举个例子来说，在 Linux 上面最标准的程式语言为 C ，所以我使用 C 的语法进行原始程式码的书写，写完之后，以 Linux 上标准的 C 语言编译器 gcc 这支程式来编译，就可以制作一支可以执行的 binary program 啰。整个的流程有点像这样：

利用 gcc 编译器进行程式的编译流程示意图
图 1.1.1、利用 gcc 编译器进行程式的编译流程示意图"

事实上，在编译的过程当中还会产生所谓的目标档 (Object file)，这些档案是以 *.o 的副档名样式存在的！至于 C 语言的原始码档案通常以 *.c 作为副档名。此外，有的时候，我们会在程式当中‘引用、呼叫’ 其他的外部副程式，或者是利用其他软体提供的‘函数功能’，这个时候，我们就必须要在编译的过程当中， 将该函式库给他加进去，如此一来，编译器就可以将所有的程式码与函式库作一个连结 (Link) 以产生正确的执行档啰。

总之，我们可以这么说：

  • 开放源码：就是程式码，写给人类看的程式语言，但机器并不认识，所以无法执行；
  • 编译器：将程式码转译成为机器看的懂得语言，就类似翻译者的角色；
  • 可执行档：经过编译器变成二进位程式后，机器看的懂所以可以执行的档案。
小标题的图示 什么是函式库

在前一小节的图1.1.1示意图中，在编译的过程里面有提到函式库这东西。 什么是函式库呢？先举个例子来说：我们的 Linux 系统上通常已经提供一个可以进行身份验证的模组， 就是在第十四章提到的 PAM 模组。这个 PAM 提供的功能可以让很多的程式在被执行的时候，除了可以验证使用者登入的资讯外， 还可以将身份确认的资料记录在登录档里面，以方便系统管理员的追踪！

既然有这么好用的功能，那如果我要编写具有身份认证功能的程式时，直接引用该 PAM 的功能就好啦，如此一来，我就不需要重新设计认证机制啰！也就是说，只要在我写的程式码里面，设定去呼叫 PAM 的函式功能，我的程式就可以利用 Linux 原本就有的身份认证的程序咯！除此之外，其实我们的 Linux 核心也提供了相当多的函式库来给硬体开发者利用喔。

函式库又分为动态与静态函式库，这两个咚咚的分别我们在后面的小节再加以说明。 这里我们以一个简单的流程图，来示意一支有呼叫外部函式库的程式的执行情况。

程式执行时引用外部动态函式库的示意图
图 1.2.1、程式执行时引用外部动态函式库的示意图

很简单的示意图啊！^_^！而如果要在程式里面加入引用的函式库，就需要如图 1.1.1 所示， 亦即在编译的过程当中，就需要加入函式库的相关设定啰。 事实上， Linux 的核心提供很多的核心相关函式库与外部参数， 这些核心功能在设计硬体的驱动程式的时候是相当有用的资讯，这些核心相关资讯大多放置在 /usr/include, /lib, /usr/lib 里面哩！我们在本章的后续小节再来探讨。反正我们可以简单的这么想：

  • 函式库：就类似副程式的角色，可以被呼叫来执行的一段功能函数。
小标题的图示 什么是 make 与 configure

事实上，使用类似 gcc 的编译器来进行编译的过程并不简单，因为一套软体并不会仅有一支程式， 而是有一堆程式码档案。所以除了每个主程式与副程式均需要写上一笔编译过程的指令外，还需要写上最终的连结程序。 程式码小的时候还好，如果是类似 WWW 伺服器软体 (例如 Apache) ，或者是类似核心的原始码，动则数百 MBytes 的资料量，编译指令会写到疯掉～这个时候，我们就可以使用 make 这个指令的相关功能来进行编译过程的指令简化了！

当执行 make 时，make 会在当时的目录下搜寻 Makefile (or makefile) 这个文字档，而 Makefile 里面则记录了原始码如何编译的详细资讯！ make 会自动的判别原始码是否经过变动了，而自动更新执行档，是软体工程师相当好用的一个辅助工具呢！

咦！make 是一支程式，会去找 Makefile ，那 Makefile 怎么写？ 通常软体开发商都会写一支侦测程式来侦测使用者的作业环境， 以及该作业环境是否有软体开发商所需要的其他功能，该侦测程式侦测完毕后，就会主动的建立这个 Makefile 的规则档案啦！通常这支侦测程式的档名为 configure 或者是 config 。

咦！那为什么要侦测作业环境呢？在第一章当中， 不是曾经提过其实每个 Linux distribution 都使用同样的核心吗？但你得要注意， 不同版本的核心所使用的系统呼叫可能不相同，而且每个软体所需要的相依的函式库也不相同， 同时，软体开发商不会仅针对 Linux 开发，而是会针对整个 Unix-Like 做开发啊！ 所以他也必须要侦测该作业系统平台有没有提供合适的编译器才行！所以当然要侦测环境啊！ 一般来说，侦测程式会侦测的资料大约有底下这些：

  • 是否有适合的编译器可以编译本软体的程式码；
  • 是否已经存在本软体所需要的函式库，或其他需要的相依软体；
  • 作业系统平台是否适合本软体，包括 Linux 的核心版本；
  • 核心的表头定义档 (header include) 是否存在 (驱动程式必须要的侦测)。

至于 make 与 configure 运作流程的相关性，我们可以使用底下的图示来示意一下啊！ 下图中，你要进行的任务其实只有两个，一个是执行 configure 来建立 Makefile ， 这个步骤一定要成功！成功之后再以 make 来呼叫所需要的资料来编译即可！非常简单！

透过 configure 与 make 进行编译示意图
图 1.3.1、透过 configure 与 make 进行编译示意图

由于不同的 Linux distribution 的函式库档案所放置的路径，或者是函式库的档名订定， 或者是预设安装的编译器，以及核心的版本都不相同，因此理论上，你无法在 CentOS 5.x 上面编译出 binary program 后，还将他拿到 SuSE 上面执行，这个动作通常是不可能成功的！ 因为呼叫的目标函式库位置可能不同 (参考图1.2.1) ， 核心版本更不可能相同！所以能够执行的情况是微乎其微！所以同一套软体要在不同的平台上面执行时， 必须要重复编译！所以才需要原始码嘛！了解乎！

详细的 make 用法与 Makefile 规则，在后续的小节里面再探讨啰！

小标题的图示 什么是 Tarball 的软体

从前面几个小节的说明来看，我们知道所谓的原始程式码，其实就是一些写满了程式码的纯文字档案。 那我们在第九章压缩指令的介绍当中， 也了解了纯文字档在网路上其实是很浪费频宽的一种档案格式！ 所以啦，如果能够将这些原始码透过档案的打包与压缩技术来将档案的数量与容量减小， 不但让使用者容易下载，软体开发商的网站频宽也能够节省很多很多啊！这就是 Tarball 档案的由来啰！

Tips:
想一想，一个核心的原始码档案大约要 300~500 MB 以上，如果每个人都去下载这样的一个核心档案， 呵呵！那么网路频宽不被吃的死翘翘才怪呢！ 		鸟哥的图示

所谓的 Tarball 档案，其实就是将软体的所有原始码档案先以 tar 打包，然后再以压缩技术来压缩，通常最常见的就是以 gzip 来压缩了。因为利用了 tar 与 gzip 的功能，所以 tarball 档案一般的副档名就会写成 *.tar.gz 或者是简写为 *.tgz 啰！不过，近来由于 bzip2 的压缩率较佳，所以 Tarball 渐渐的以 bzip2 的压缩技术来取代 gzip 啰！因此档名也会变成 *.tar.bz2 之类的哩。所以说， Tarball 是一个软体包， 你将他解压缩之后，里面的档案通常就会有：

  • 原始程式码档案；
  • 侦测程式档案 (可能是 configure 或 config 等档名)；
  • 本软体的简易说明与安装说明 (INSTALL 或 README)。

其中最重要的是那个 INSTALL 或者是 README 这两个档案，通常你只要能够参考这两个档案， Tarball 软体的安装是很简单的啦！我们在后面的章节会再继续介绍 Tarball 这个玩意儿。

小标题的图示 如何安装与升级软体

将原始码作了一个简单的介绍，也知道了系统其实认识的可执行档是 binary program 之后，好了，得要聊一聊，那么怎么安装与升级一个 Tarball 的软体？为什么要安装一个新的软体呢？当然是因为我们的主机上面没有该软体啰！那么， 为何要升级呢？原因可能有底下这些：

  • 需要新的功能，但旧有主机的旧版软体并没有，所以需要升级到新版的软体；
  • 旧版本的软体上面可能有资安上的顾虑，所以需要更新到新版的软体；
  • 旧版的软体执行效能不彰，或者执行的能力不能让管理者满足。

在上面的需求当中，尤其需要注意的是第二点，当一个软体有安全上的顾虑时，千万不要怀疑， 赶紧更新软体吧！否则造成网路危机，那可不是闹着玩的！那么更新的方法有哪些呢？ 基本上更新的方法可以分为两大类，分别是：

  • 直接以原始码透过编译来安装与升级；
  • 直接以编译好的 binary program 来安装与升级。

上面第一点很简单，就是直接以 Tarball 在自己的机器上面进行侦测、编译、 安装与设定等等动作来升级就是了。不过，这样的动作虽然让使用者在安装过程当中具有很高的弹性， 但毕竟是比较麻烦一点，如果 Linux distribution 厂商能够针对自己的作业平台先进行编译等过程，再将编译好的 binary program 释出的话，那由于我的系统与该 Linux distribution 的环境是相同的，所以他所释出的 binary program 就可以在我的机器上面直接安装啦！省略了侦测与编译等等繁杂的过程呢！

这个预先编译好程式的机制存在于很多 distribution 喔，包括有 Red Hat 系统 (含 Fedora/CentOS 系列) 发展的 RPM 软体管理机制与 yum 线上更新模式； Debian 使用的 dpkg 软体管理机制与 APT 线上更新模式等等。

由于 CentOS 系统是依循标准的 Linux distribution，所以可以使用 Tarball 直接进行编译的安装与升级， 当然也可以使用 RPM 相关的机制来进行安装与升级啰！本章节主要针对 Tarball ，至于 RPM 则留待下个章节再来介绍呢！

好了，那么一个软体的 Tarball 是如何安装的呢？基本流程是这样的啦：

  1. 将 Tarball 由厂商的网页下载下来；
  2. 将 Tarball 解开，产生很多的原始码档案；
  3. 开始以 gcc 进行原始码的编译 (会产生目标档 object files)；
  4. 然后以 gcc 进行函式库、主、副程式的连结，以形成主要的 binary file；
  5. 将上述的 binary file 以及相关的设定档安装至自己的主机上面。

上面第 3, 4 步骤当中，我们可以透过 make 这个指令的功能来简化他， 所以整个步骤其实是很简单的啦！只不过你就得需要至少有 gcc 以及 make 这两个软体在你的 Linux 系统里面才行喔！ 详细的过程以及需要的软体我们在后面的章节继续来介绍的啦！

大标题的图示 使用传统程式语言进行编译的简单范例

经过上面的介绍之后，你应该比较清楚的知道原始码、编译器、函式库与执行档之间的相关性了。 不过，详细的流程可能还是不很清楚，所以，在这里我们以一个简单的程式范例来说明整个编译的过程喔！赶紧进入 Linux 系统，实地的操作一下底下的范例呢！

小标题的图示 单一程式：印出 Hello World

我们以 Linux 上面最常见的 C 语言来撰写第一支程式！第一支程式最常作的就是..... 在荧幕上面印出‘Hello World！’的字样～当然， 这里我们是以简单的 C 语言来撰写，如果你对于 C 有兴趣的话，那么请自行购买相关的书籍喔！ ^_^ 好了，不啰唆，立刻编辑第一支程式吧！

Tips:
请先确认你的 Linux 系统里面已经安装了 gcc 了喔！如果尚未安装 gcc 的话，请先参考下一节的 RPM 安装法，先安装好 gcc 之后，再回来阅读本章。 如果你已经有网路了，那么直接使用‘ yum groupinstall "Development Tools" ’ 预先安装好所需的所有软体即可。 rpm 与 yum 均会在下一章介绍。 		鸟哥的图示
  • 编辑程式码，亦即原始码
[root@www ~]# vim hello.c   <==用 C 语言写的程式副档名建议用 .c
#include <stdio.h>
int main(void)
{
        printf("Hello World\n");
}

上面是用 C 语言的语法写成的一个程式档案。第一行的那个‘ # ’并不是注解喔！如果你担心输入错误， 请到底下的连结下载这个档案：

  • http://linux.vbird.org/linux_basic/0520source/hello.c
  • 开始编译与测试执行
[root@www ~]# gcc hello.c
[root@www ~]# ll hello.c a.out
-rwxr-xr-x 1 root root 4725 Jun  5 02:41 a.out   <==此时会产生这个档名
-rw-r--r-- 1 root root   72 Jun  5 02:40 hello.c

[root@www ~]# ./a.out
Hello World  <==呵呵！成果出现了！

在预设的状态下，如果我们直接以 gcc 编译原始码，并且没有加上任何参数，则执行档的档名会被自动设定为 a.out 这个档案名称！ 所以你就能够直接执行 ./a.out 这个执行档啦！上面的例子很简单吧！那个 hello.c 就是原始码，而 gcc 就是编译器，至于 a.out 就是编译成功的可执行 binary program 啰！ 咦！那如果我想要产生目标档 (object file) 来进行其他的动作，而且执行档的档名也不要用预设的 a.out ，那该如何是好？其实你可以将上面的第 2 个步骤改成这样：

[root@www ~]# gcc -c hello.c
[root@www ~]# ll hello*
-rw-r--r-- 1 root root  72 Jun  5 02:40 hello.c
-rw-r--r-- 1 root root 868 Jun  5 02:44 hello.o  <==就是被产生的目标档

[root@www ~]# gcc -o hello hello.o
[root@www ~]# ll hello*
-rwxr-xr-x 1 root root 4725 Jun  5 02:47 hello  <==这就是可执行档！ -o 的结果
-rw-r--r-- 1 root root   72 Jun  5 02:40 hello.c
-rw-r--r-- 1 root root  868 Jun  5 02:44 hello.o

[root@www ~]# ./hello
Hello World

这个步骤主要是利用 hello.o 这个目标档制作出一个名为 hello 的执行档，详细的 gcc 语法我们会在后续章节中继续介绍！透过这个动作后，我们可以得到 hello 及 hello.o 两个档案， 真正可以执行的是 hello 这个 binary program 喔！ 或许你会觉得，咦！只要一个动作作出 a.out 就好了，干嘛还要先制作目标档再做成执行档呢？ 呵呵！透过下个范例，你就可以知道为什么啦！

小标题的图示 主、副程式连结：副程式的编译

如果我们在一个主程式里面又呼叫了另一个副程式呢？这是很常见的一个程式写法， 因为可以简化整个程式的易读性！在底下的例子当中，我们以 thanks.c 这个主程式去呼叫 thanks_2.c 这个副程式，写法很简单：

  • 撰写所需要的主、副程式
# 1. 编辑主程式：
[root@www ~]# vim thanks.c
#include <stdio.h>
int main(void)
{
        printf("Hello World\n");
        thanks_2();
}
# 上面的 thanks_2(); 那一行就是呼叫副程式啦！

[root@www ~]# vim thanks_2.c
#include <stdio.h>
void thanks_2(void)
{
        printf("Thank you!\n");
}

上面这两个档案你可以到底下下载：

  • http://linux.vbird.org/linux_basic/0520source/thanks.c
  • http://linux.vbird.org/linux_basic/0520source/thanks_2.c
  • 进行程式的编译与连结 (Link)
# 2. 开始将原始码编译成为可执行的 binary file ：
[root@www ~]# gcc -c thanks.c thanks_2.c
[root@www ~]# ll thanks*
-rw-r--r-- 1 root root  76 Jun  5 16:13 thanks_2.c
-rw-r--r-- 1 root root 856 Jun  5 16:13 thanks_2.o  <==编译产生的！
-rw-r--r-- 1 root root  92 Jun  5 16:11 thanks.c
-rw-r--r-- 1 root root 908 Jun  5 16:13 thanks.o    <==编译产生的！
[root@www ~]# gcc -o thanks thanks.o thanks_2.o
[root@www ~]# ll thanks*
-rwxr-xr-x 1 root root 4870 Jun  5 16:17 thanks     <==最终结果会产生这玩意儿

# 3. 执行一下这个档案：
[root@www ~]# ./thanks
Hello World
Thank you!

知道为什么要制作出目标档了吗？由于我们的原始码档案有时并非仅只有一个档案，所以我们无法直接进行编译。 这个时候就需要先产生目标档，然后再以连结制作成为 binary 可执行档。另外，如果有一天，你更新了 thanks_2.c 这个档案的内容，则你只要重新编译 thanks_2.c 来产生新的 thanks_2.o ，然后再以连结制作出新的 binary 可执行档即可！而不必重新编译其他没有更动过的原始码档案。 这对于软体开发者来说，是一个很重要的功能，因为有时候要将偌大的原始码全部编译完成，会花很长的一段时间呢！

此外，如果你想要让程式在执行的时候具有比较好的效能，或者是其他的除错功能时， 可以在编译的过程里面加入适当的参数，例如底下的例子：

[root@www ~]# gcc -O -c thanks.c thanks_2.c  <== -O 为产生最佳化的参数

[root@www ~]# gcc -Wall -c thanks.c thanks_2.c
thanks.c: In function 'main':
thanks.c:5: warning: implicit declaration of function 'thanks_2'
thanks.c:6: warning: control reaches end of non-void function
# -Wall 为产生更详细的编译过程资讯。上面的讯息为警告讯息 (warning)
# 所以不用理会也没有关系！

至于更多的 gcc 额外参数功能，就得要 man gcc 啰～呵呵！可多的跟天书一样～

小标题的图示 呼叫外部函式库：加入连结的函式库

刚刚我们都仅只是在荧幕上面印出一些字眼而已，如果说要计算数学公式呢？例如我们想要计算出三角函数里面的 sin (90度角)。要注意的是，大多数的程式语言都是使用径度而不是一般我们在计算的‘角度’， 180 度角约等于 3.14 径度！嗯！那我们就来写一下这个程式吧！

[root@www ~]# vim sin.c
#include <stdio.h>
int main(void)
{
        float value;
        value = sin ( 3.14 / 2 );
        printf("%f\n",value);
}

上面这个档案的内容可以在底下取得！

  • http://linux.vbird.org/linux_basic/0520source/sin.c

那要如何编译这支程式呢？我们先直接编译看看：

[root@www ~]# gcc sin.c
sin.c: In function 'main':
sin.c:5: warning: incompatible implicit declaration of built-in function 'sin'
/tmp/ccsfvijY.o: In function `main':
sin.c:(.text+0x1b): undefined reference to `sin'
collect2: ld returned 1 exit status
# 注意看到上面最后一行，会有个错误讯息，代表没有成功！

特别注意上面的错误讯息，唉啊！怎么没有编译成功？它说的是‘undefined reference to sin’，说的是‘没有 sin 的相关定义参考值！’，为什么会这样呢？这是因为 C 语言里面的 sin 函示是写在 libm.so 这个函式库中，而我们并没有在原始码里面将这个函式库功能加进去， 所以当然就需要在编译与连结的时候将这个函式库给他连结进执行档里面啊！我们可以这样做：

  • 编译时加入额外函式库连结的方式：
[root@www ~]# gcc sin.c -lm -L/lib -L/usr/lib  <==重点在 -lm
[root@www ~]# ./a.out                          <==尝试执行新档案！
1.000000

特别注意，使用 gcc 编译时所加入的那个 -lm 是有意义的，他可以拆开成两部份来看：

  • -l ：是‘加入某个函式库(library)’的意思，
  • m ：则是 libm.so 这个函式库，其中， lib 与副档名(.a 或 .so)不需要写

所以 -lm 表示使用 libm.so (或 libm.a) 这个函式库的意思～至于那个 -L 后面接的路径呢？这表示： ‘我要的函式库 libm.so 请到 /lib 或 /usr/lib 里面搜寻！’

上面的说明很清楚了吧！不过，要注意的是，由于 Linux 预设是将函式库放置在 /lib 与 /usr/lib 当中，所以你没有写 -L/lib 与 -L/usr/lib 也没有关系的！不过，万一哪天你使用的函式库并非放置在这两个目录下，那么 -L/path 就很重要了！否则会找不到函式库喔！

除了连结的函式库之外，你或许已经发现一个奇怪的地方，那就是在我们的 sin.c 当中第一行‘ #include <stdio.h>’，这行说的是要将一些定义资料由 stdio.h 这个档案读入，这包括 printf 的相关设定。这个档案其实是放置在 /usr/include/stdio.h 的！那么万一这个档案并非放置在这里呢？那么我们就可以使用底下的方式来定义出要读取的 include 档案放置的目录：

[root@www ~]# gcc sin.c -lm -I/usr/include

-I/path 后面接的路径( Path )就是设定要去搜寻相关的 include 档案的目录啦！不过，同样的，预设值是放置在 /usr/include 底下，除非你的 include 档案放置在其他路径，否则也可以略过这个项目！

透过上面的几个小范例，你应该对于 gcc 以及原始码有一定程度的认识了，再接下来，我们来稍微整理一下 gcc 的简易使用方法吧！

小标题的图示 gcc 的简易用法 (编译、参数与链结)

前面说过， gcc 为 Linux 上面最标准的编译器，这个 gcc 是由 GNU 计划所维护的，有兴趣的朋友请自行前往参考。既然 gcc 对于 Linux 上的 Open source 是这么样的重要，所以底下我们就列举几个 gcc 常见的参数，如此一来大家应该更容易了解原始码的各项功能吧！

# 仅将原始码编译成为目标档，并不制作连结等功能：
[root@www ~]# gcc -c hello.c
# 会自动的产生 hello.o 这个档案，但是并不会产生 binary 执行档。

# 在编译的时候，依据作业环境给予最佳化执行速度
[root@www ~]# gcc -O hello.c -c
# 会自动的产生 hello.o 这个档案，并且进行最佳化喔！

# 在进行 binary file 制作时，将连结的函式库与相关的路径填入
[root@www ~]# gcc sin.c -lm -L/usr/lib -I/usr/include
# 这个指令较常下达在最终连结成 binary file 的时候，
# -lm 指的是 libm.so 或 libm.a 这个函式库档案；
# -L 后面接的路径是刚刚上面那个函式库的搜寻目录；
# -I 后面接的是原始码内的 include 档案之所在目录。

# 将编译的结果输出成某个特定档名
[root@www ~]# gcc -o hello hello.c
# -o 后面接的是要输出的 binary file 档名

# 在编译的时候，输出较多的讯息说明
[root@www ~]# gcc -o hello hello.c -Wall
# 加入 -Wall 之后，程式的编译会变的较为严谨一点，
# 所以警告讯息也会显示出来！

比较重要的大概就是这一些。另外，我们通常称 -Wall 或者 -O 这些非必要的参数为旗标 (FLAGS)，因为我们使用的是 C 程式语言，所以有时候也会简称这些旗标为 CFLAGS ，这些变数偶尔会被使用的喔！尤其是在后头会介绍的 make 相关的用法时，更是重要的很呐！ ^_^

大标题的图示 用 make 进行巨集编译

在本章一开始我们提到过 make 的功能是可以简化编译过程里面所下达的指令，同时还具有很多很方便的功能！那么底下咱们就来试看看使用 make 简化下达编译指令的流程吧！

小标题的图示 为什么要用 make

先来想像一个案例，假设我的执行档里面包含了四个原始码档案，分别是 main.c haha.c sin_value.c cos_value.c 这四个档案，这四个档案的目的是：

  • main.c ：主要的目的是让使用者输入角度资料与呼叫其他三支副程式；
  • haha.c ：输出一堆有的没有的讯息而已；
  • sin_value.c ：计算使用者输入的角度(360) sin 数值；
  • cos_value.c ：计算使用者输入的角度(360) cos 数值。

这四个档案你可以到 http://linux.vbird.org/linux_basic/0520source/main.tgz 来下载。由于这四个档案里面包含了相关性，并且还用到数学函式在里面，所以如果你想要让这个程式可以跑， 那么就需要这样编译：

# 1. 先进行目标档的编译，最终会有四个 *.o 的档名出现：
[root@www ~]# gcc -c main.c
[root@www ~]# gcc -c haha.c
[root@www ~]# gcc -c sin_value.c
[root@www ~]# gcc -c cos_value.c

# 2. 再进行连结成为执行档，并加入 libm 的数学函式，以产生 main 执行档：
[root@www ~]# gcc -o main main.o haha.o sin_value.o cos_value.o \
> -lm -L/usr/lib -L/lib

# 3. 本程式的执行结果，必须输入姓名、360 度角的角度值来计算：
[root@www ~]# ./main
Please input your name: VBird  <==这里先输入名字
Please enter the degree angle (ex> 90): 30   <==输入以 360 度角为主的角度
Hi, Dear VBird, nice to meet you.    <==这三行为输出的结果喔！
The Sin is:  0.50
The Cos is:  0.87

编译的过程需要进行好多动作啊！而且如果要重新编译，则上述的流程得要重新来一遍，光是找出这些指令就够烦人的了！ 如果可以的话，能不能一个步骤就给他完成上面所有的动作呢？那就利用 make 这个工具吧！ 先试看看在这个目录下建立一个名为 makefile 的档案，内容如下：

# 1. 先编辑 makefile 这个规则档，内容只要作出 main 这个执行档
[root@www ~]# vim makefile
main: main.o haha.o sin_value.o cos_value.o
    gcc -o main main.o haha.o sin_value.o cos_value.o -lm
# 注意：第二行的 gcc 之前是 <tab> 按键产生的空格喔！

# 2. 尝试使用 makefile 制订的规则进行编译的行为：
[root@www ~]# rm -f main *.o   <==先将之前的目标档去除
[root@www ~]# make
cc    -c -o main.o main.c
cc    -c -o haha.o haha.c
cc    -c -o sin_value.o sin_value.c
cc    -c -o cos_value.o cos_value.c
gcc -o main main.o haha.o sin_value.o cos_value.o -lm
# 此时 make 会去读取 makefile 的内容，并根据内容直接去给他编译相关的档案啰！

# 3. 在不删除任何档案的情况下，重新执行一次编译的动作：
[root@www ~]# make
make: `main' is up to date.
# 看到了吧！是否很方便呢！只会进行更新 (update) 的动作而已。

或许你会说：‘如果我建立一个 shell script 来将上面的所有动作都集结在一起，不是具有同样的效果吗？’呵呵！ 效果当然不一样，以上面的测试为例，我们仅写出 main 需要的目标档，结果 make 会主动的去判断每个目标档相关的原始码档案，并直接予以编译，最后再直接进行连结的动作！ 真的是很方便啊！此外，如果我们更动过某些原始码档案，则 make 也可以主动的判断哪一个原始码与相关的目标档档案有更新过， 并仅更新该档案，如此一来，将可大大的节省很多编译的时间呢！要知道，某些程式在进行编译的行为时，会消耗很多的 CPU 资源呢！所以说， make 有这些好处：

  • 简化编译时所需要下达的指令；
  • 若在编译完成之后，修改了某个原始码档案，则 make 仅会针对被修改了的档案进行编译，其他的 object file 不会被更动；
  • 最后可以依照相依性来更新 (update) 执行档。

既然 make 有这么多的优点，那么我们当然就得好好的了解一下 make 这个令人关心的家伙啦！而 make 里面最需要注意的大概就是那个规则档案，也就是 makefile 这个档案的语法啦！所以底下我们就针对 makefile 的语法来加以介绍啰。

小标题的图示 makefile 的基本语法与变数

make 的语法可是相当的多而复杂的，有兴趣的话可以到 GNU (注1) 去查阅相关的说明，鸟哥这里仅列出一些基本的规则，重点在于让读者们未来在接触原始码时，不会太紧张啊！ 好了，基本的 makefile 规则是这样的：

标的(target): 目标档1 目标档2
<tab>   gcc -o 欲建立的执行档 目标档1 目标档2

那个标的 (target) 就是我们想要建立的资讯，而目标档就是具有相关性的 object files ，那建立执行档的语法就是以 <tab> 按键开头的那一行！特别给他留意喔，‘命令列必须要以 tab 按键作为开头’才行！他的规则基本上是这样的：

  • 在 makefile 当中的 # 代表注解；
  • <tab> 需要在命令行 (例如 gcc 这个编译器指令) 的第一个字元；
  • 标的 (target) 与相依档案(就是目标档)之间需以‘:’隔开。

同样的，我们以刚刚上一个小节的范例进一步说明，如果我想要有两个以上的执行动作时， 例如下达一个指令就直接清除掉所有的目标档与执行档，该如何制作呢？

# 1. 先编辑 makefile 来建立新的规则，此规则的标的名称为 clean ：
[root@www ~]# vi makefile
main: main.o haha.o sin_value.o cos_value.o
    gcc -o main main.o haha.o sin_value.o cos_value.o -lm
clean:
    rm -f main main.o haha.o sin_value.o cos_value.o

# 2. 以新的标的 (clean) 测试看看执行 make 的结果：
[root@www ~]# make clean  <==就是这里！透过 make 以 clean 为标的
rm -rf main main.o haha.o sin_value.o cos_value.o

如此一来，我们的 makefile 里面就具有至少两个标的，分别是 main 与 clean ，如果我们想要建立 main 的话，输入‘make main’，如果想要清除有的没的，输入‘make clean’即可啊！而如果想要先清除目标档再编译 main 这个程式的话，就可以这样输入：‘make clean main’，如下所示：

[root@www ~]# make clean main
rm -rf main main.o haha.o sin_value.o cos_value.o
cc    -c -o main.o main.c
cc    -c -o haha.o haha.c
cc    -c -o sin_value.o sin_value.c
cc    -c -o cos_value.o cos_value.c
gcc -o main main.o haha.o sin_value.o cos_value.o -lm

这样就很清楚了吧！但是，你是否会觉得，咦！ makefile 里面怎么重复的资料这么多啊！没错！所以我们可以再藉由 shell script 那时学到的‘变数’来更简化 makefile 喔：

[root@www ~]# vi makefile
LIBS = -lm
OBJS = main.o haha.o sin_value.o cos_value.o
main: ${OBJS}
        gcc -o main ${OBJS} ${LIBS}
clean:
        rm -f main ${OBJS}

与 bash shell script 的语法有点不太相同，变数的基本语法为：

  1. 变数与变数内容以‘=’隔开，同时两边可以具有空格；
  2. 变数左边不可以有 <tab> ，例如上面范例的第一行 LIBS 左边不可以是 <tab>；
  3. 变数与变数内容在‘=’两边不能具有‘:’；
  4. 在习惯上，变数最好是以‘大写字母’为主；
  5. 运用变数时，以 ${变数} 或 $(变数) 使用；
  6. 在该 shell 的环境变数是可以被套用的，例如提到的 CFLAGS 这个变数！
  7. 在指令列模式也可以给予变数。

由于 gcc 在进行编译的行为时，会主动的去读取 CFLAGS 这个环境变数，所以，你可以直接在 shell 定义出这个环境变数，也可以在 makefile 档案里面去定义，更可以在指令列当中给予这个咚咚呢！例如：

[root@www ~]# CFLAGS="-Wall" make clean main
# 这个动作在上 make 进行编译时，会去取用 CFLAGS 的变数内容！

也可以这样：

[root@www ~]# vi makefile
LIBS = -lm
OBJS = main.o haha.o sin_value.o cos_value.o
CFLAGS = -Wall
main: ${OBJS}
    gcc -o main ${OBJS} ${LIBS}
clean:
    rm -f main ${OBJS}

咦！我可以利用指令列进行环境变数的输入，也可以在档案内直接指定环境变数，那万一这个 CFLAGS 的内容在指令列与 makefile 里面并不相同时，以那个方式输入的为主？呵呵！问了个好问题啊！ 环境变数取用的规则是这样的：

  1. make 指令列后面加上的环境变数为优先；
  2. makefile 里面指定的环境变数第二；
  3. shell 原本具有的环境变数第三。

此外，还有一些特殊的变数需要了解的喔：

  • $@：代表目前的标的(target)

所以我也可以将 makefile 改成：

[root@www ~]# vi makefile
LIBS = -lm
OBJS = main.o haha.o sin_value.o cos_value.o
CFLAGS = -Wall
main: ${OBJS}
    gcc -o $@ ${OBJS} ${LIBS}   <==那个 $@ 就是 main ！
clean:
    rm -f main ${OBJS}

这样是否稍微了解了 makefile (也可能是 Makefile) 的基本语法？这对于你未来自行修改原始码的编译规则时，是很有帮助的喔！^_^！

大标题的图示 Tarball 的管理与建议

在我们知道了原始码的相关资讯之后，再来要了解的自然就是如何使用具有原始码的 Tarball 来建立一个属于自己的软体啰！从前面几个小节的说明当中，我们晓得其实 Tarball 的安装是可以跨平台的，因为 C 语言的程式码在各个平台上面是可以共通的， 只是需要的编译器可能并不相同而已。例如 Linux 上面用 gcc 而 Windows 上面也有相关的 C 编译器啊～所以呢，同样的一组原始码，既可以在 CentOS Linux 上面编译，也可以在 SuSE Linux 上面编译，当然，也可以在大部分的 Unix 平台上面编译成功的！

如果万一没有编译成功怎么办？很简单啊，透过修改小部分的程式码 (通常是因为很小部分的异动而已) 就可以进行跨平台的移植了！也就是说，刚刚我们在 Linux 底下写的程式‘理论上，是可以在 Windows 上面编译的！’这就是原始码的好处啦！所以说，如果朋友们想要学习程式语言的话， 鸟哥个人是比较建议学习‘具有跨平台能力的程式语言’，例如 C 就是很不错的一个！

唉啊！又扯远了～赶紧拉回来继续说明我们的 Tarball 啦！

小标题的图示 使用原始码管理软体所需要的基础软体

从原始码的说明我们晓得要制作一个 binary program 需要很多咚咚的呢！这包括底下这些基础的软体：

  • gcc 或 cc 等 C 语言编译器 (compiler)：

    没有编译器怎么进行编译的动作？所以 C compiler 是一定要有的。不过 Linux 上面有众多的编译器，其中当然以 GNU 的 gcc 是首选的自由软体编译器啰！事实上很多在 Linux 平台上面发展的软体的原始码，原本就是以 gcc 为底来设计的呢。

  • make 及 autoconfig 等软体：

    一般来说，以 Tarball 方式释出的软体当中，为了简化编译的流程，通常都是配合前几个小节提到的 make 这个指令来依据目标档案的相依性而进行编译。但是我们也知道说 make 需要 makefile 这个档案的规则，那由于不同的系统里面可能具有的基础软体环境并不相同， 所以就需要侦测使用者的作业环境，好自行建立一个 makefile 档案。这个自行侦测的小程式也必须要藉由 autoconfig 这个相关的软体来辅助才行。

  • 需要 Kernel 提供的 Library 以及相关的 Include 档案：

    从前面的原始码编译过程，我们晓得函式库 (library) 的重要性，同时也晓得有 include 档案的存在。很多的软体在发展的时候都是直接取用系统核心提供的函式库与 include 档案的，这样才可以与这个作业系统相容啊！尤其是在‘驱动程式方面的模组 ’，例如网路卡、音效卡、USB 等驱动程式在安装的时候，常常是需要核心提供的相关资讯的。在 Red Hat 的系统当中 (包含 Fedora/CentOS 等系列) ，这个核心相关的功能通常都是被包含在 kernel-source 或 kernel-header 这些软体名称当中，所以记得要安装这些软体喔！

虽然 Tarball 的安装上面相当的简单，如同我们前面几个小节的例子，只要顺着开发商提供的 README 与 INSTALL 档案所载明的步骤来进行，安装是很容易的。但是我们却还是常常会在 BBS 或者是新闻群组当中发现这些留言：‘我在执行某个程式的侦测档案时，他都会告诉我没有 gcc 这个软体，这是怎么回事？’还有：‘我没有办法使用 make 耶！这是什么问题？’呵呵！ 这就是没有安装上面提到的那些基础软体啦！

咦！为什么使用者不安装这些软体啊？这是因为目前的 Linux distribution 大多已经偏向于桌上型电脑的使用 (非伺服器端)，他们希望使用者能够按照厂商自己的希望来安装相关的软体即可， 所以通常‘预设’是没有安装 gcc 或者是 make 等软体的。所以啦，如果你希望未来可以自行安装一些以 Tarball 方式释出的软体时，记得请自行挑选想要安装的软体名称喔！例如在 CentOS 或者是 Red Hat 当中记得选择 Development Tools 以及 Kernel Source Development 等相关字眼的软体群集呢。

那万一我已经安装好一部 Linux 主机，但是使用的是预设值所安装的软体，所以没有 make, gcc 等咚咚，该如何是好？呵呵！问题其实不大啦，目前使用最广泛的 CentOS/Fedora 或者是 Red Hat 大多是以 RPM (下一章会介绍) 来安装软体的，所以，你只要拿出当初安装 Linux 时的原版光碟，然后以下一章介绍的 RPM 来一个一个的加入到你的 Linux 主机里面就好啦！很简单的啦！ 尤其现在又有 yum 这玩意儿，更方便呐！

在 CentOS 当中，如果你已经有网路可以连上 Internet 的话，那么就可以使用下一章会谈到的 yum 啰！ 透过 yum 的软体群组安装功能，你可以这样做：

  • 如果是要安装 gcc 等软体发展工具，请使用‘ yum groupinstall "Development Tools" ’
  • 若待安装的软体需要图形介面支援，一般还需要‘ yum groupinstall "X Software Development" ’
  • 若安装的软体较旧，可能需要‘ yum groupinstall "Legacy Software Development" ’

大概就是这样，更多的资讯请参考下一章的介绍喔。

小标题的图示 Tarball 安装的基本步骤

我们提过以 Tarball 方式释出的软体是需要重新编译可执行的 binary program 的。而 Tarball 是以 tar 这个指令来打包与压缩的档案，所以啦，当然就需要先将 Tarball 解压缩，然后到原始码所在的目录下进行 makefile 的建立，再以 make 来进行编译与安装的动作啊！所以整个安装的基础动作大多是这样的：

  1. 取得原始档：将 tarball 档案在 /usr/local/src 目录下解压缩；
  2. 取得步骤流程：进入新建立的目录底下，去查阅 INSTALL 与 README 等相关档案内容 (很重要的步骤！)；
  3. 相依属性软体安装：根据 INSTALL/README 的内容察看并安装好一些相依的软体 (非必要)；
  4. 建立 makefile：以自动侦测程式 (configure 或 config) 侦测作业环境，并建立 Makefile 这个档案；
  5. 编译：以 make 这个程式并使用该目录下的 Makefile 做为他的参数设定档，来进行 make (编译或其他) 的动作；
  6. 安装：以 make 这个程式，并以 Makefile 这个参数设定档，依据 install 这个标的 (target) 的指定来安装到正确的路径！

注意到上面的第二个步骤，通常在每个软体在释出的时候，都会附上 INSTALL 或者是 README 这种档名的说明档，这些说明档请‘确实详细的’ 阅读过一遍，通常这些档案会记录这个软体的安装要求、软体的工作项目、 与软体的安装参数设定及技巧等，只要仔细的读完这些档案，基本上，要安装好 tarball 的档案，都不会有什么大问题啰。

至于 makefile 在制作出来之后，里头会有相当多的标的 (target)，最常见的就是 install 与 clean 啰！通常‘make clean’代表着将目标档 (object file) 清除掉，‘make’则是将原始码进行编译而已。 注意喔！编译完成的可执行档与相关的设定档还在原始码所在的目录当中喔！因此，最后要进行‘make install’来将编译完成的所有咚咚都给他安装到正确的路径去，这样就可以使用该软体啦！

OK！我们底下约略提一下大部分的 tarball 软体之安装的指令下达方式：

  1. ./configure
    这个步骤就是在建立 Makefile 这个档案啰！通常程式开发者会写一支 scripts 来检查你的 Linux 系统、相关的软体属性等等，这个步骤相当的重要， 因为未来你的安装资讯都是这一步骤内完成的！另外，这个步骤的相关资讯应该要参考一下该目录下的 README 或 INSTALL 相关的档案！

  2. make clean
    make 会读取 Makefile 中关于 clean 的工作。这个步骤不一定会有，但是希望执行一下，因为他可以去除目标档案！因为谁也不确定原始码里面到底有没有包含上次编译过的目标档案 (*.o) 存在，所以当然还是清除一下比较妥当的。 至少等一下新编译出来的执行档我们可以确定是使用自己的机器所编译完成的嘛！

  3. make
    make 会依据 Makefile 当中的预设工作进行编译的行为！编译的工作主要是进行 gcc 来将原始码编译成为可以被执行的 object files ，但是这些 object files 通常还需要一些函式库之类的 link 后，才能产生一个完整的执行档！使用 make 就是要将原始码编译成为可以被执行的可执行档，而这个可执行档会放置在目前所在的目录之下， 尚未被安装到预定安装的目录中；

  4. make install
    通常这就是最后的安装步骤了，make 会依据 Makefile 这个档案里面关于 install 的项目，将上一个步骤所编译完成的资料给他安装到预定的目录中，就完成安装啦！

请注意，上面的步骤是一步一步来进行的，而其中只要一个步骤无法成功，那么后续的步骤就完全没有办法进行的！ 因此，要确定每一的步骤都是成功的才可以！举个例子来说，万一今天你在 ./configure 就不成功了，那么就表示 Makefile 无法被建立起来，要知道，后面的步骤都是根据 Makefile 来进行的，既然无法建立 Makefile，后续的步骤当然无法成功啰！

另外，如果在 make 无法成功的话，那就表示原始档案无法被编译成可执行档，那么 make install 主要是将编译完成的档案给他放置到档案系统中的，既然都没有可用的执行档了，怎么进行安装？ 所以啰，要每一个步骤都正确无误才能往下继续做！此外，如果安装成功， 并且是安装在独立的一个目录中，例如 /usr/local/packages 这个目录中好了，那么你就必需手动的将这个软体的 man page 给他写入 /etc/man.config 里面去。

小标题的图示 一般 Tarball 软体安装的建议事项 (如何移除？升级？)

或许你已经发现了也说不定，那就是为什么前一个小节里面， Tarball 要在 /usr/local/src 里面解压缩呢？基本上，在预设的情况下，原本的 Linux distribution 释出安装的软体大多是在 /usr 里面的，而使用者自行安装的软体则建议放置在 /usr/local 里面。这是考量到管理使用者所安装软体的便利性。

怎么说呢？我们晓得几乎每个软体都会提供线上说明的服务，那就是 info 与 man 的功能。在预设的情况下， man 会去搜寻 /usr/local/man 里面的说明文件， 因此，如果我们将软体安装在 /usr/local 底下的话，那么自然安装完成之后， 该软体的说明文件就可以被找到了。此外，如果你所管理的主机其实是由多人共同管理的， 或者是如同学校里面，一部主机是由学生管理的，但是学生总会毕业吧？ 所以需要进行交接，如果大家都将软体安装在 /usr/local 底下，那么管理上不就显的特别的容易吗！

所以啰，通常我们会建议大家将自己安装的软体放置在 /usr/local 下，至于原始码 (Tarball)则建议放置在 /usr/local/src (src 为 source 的缩写)底下啊。

再来，让我们先来看一看 Linux distribution 预设的安装软体的路径会用到哪些？我们以 apache 这个软体来说明的话 (apache 是 WWW 伺服器软体，详细的资料请参考伺服器架设篇。你的系统不见得有装这个软体)：

  • /etc/httpd
  • /usr/lib
  • /usr/bin
  • /usr/share/man

我们会发现软体的内容大致上是摆在 etc, lib, bin, man 等目录当中，分别代表‘设定档、函式库、执行档、线上说明档’。 好了，那么你是以 tarball 来安装时呢？如果是放在预设的 /usr/local 里面，由于 /usr/local 原本就预设这几个目录了，所以你的资料就会被放在：

  • /usr/local/etc
  • /usr/local/bin
  • /usr/local/lib
  • /usr/local/man

但是如果你每个软体都选择在这个预设的路径下安装的话， 那么所有的软体的档案都将放置在这四个目录当中，因此，如果你都安装在这个目录下的话， 那么未来再想要升级或移除的时候，就会比较难以追查档案的来源啰！ 而如果你在安装的时候选择的是单独的目录，例如我将 apache 安装在 /usr/local/apache 当中，那么你的档案目录就会变成：

  • /usr/local/apache/etc
  • /usr/local/apache/bin
  • /usr/local/apache/lib
  • /usr/local/apache/man

呵呵！单一软体的档案都在同一个目录之下，那么要移除该软体就简单的多了！ 只要将该目录移除即可视为该软体已经被移除啰！以上面为例，我想要移除 apache 只要下达‘rm -rf /usr/local/apache’ 就算移除这个软体啦！当然啰，实际安装的时候还是得视该软体的 Makefile 里头的 install 资讯才能知道到底他的安装情况为何的。因为例如 sendmail 的安装就很麻烦......

这个方式虽然有利于软体的移除，但不晓得你有没有发现，我们在执行某些指令的时候，与该指令是否在 PATH 这个环境变数所记录的路径有关，以上面为例，我的 /usr/local/apache/bin 肯定是不在 PATH 里面的，所以执行 apache 的指令就得要利用绝对路径了，否则就得将这个 /usr/local/apache/bin 加入 PATH 里面。另外，那个 /usr/local/apache/man 也需要加入 man page 搜寻的路径当中啊！

除此之外， Tarball 在升级的时候也是挺困扰的，怎么说呢？我们还是以 apache 来说明好了。WWW 伺服器为了考虑互动性，所以通常会将 PHP+MySQL+Apache 一起安装起来 (详细的资讯请参考伺服器架设篇) ，果真如此的话，那么每个软体在安装的时候‘都有一定的顺序与程序！’ 因为他们三者之间具有相关性，所以安装时必需要三者同时考虑到他们的函式库与相关的编译参数。

假设今天我只要升级 PHP 呢？有的时候因为只有涉及动态函式库的升级，那么我只要升级 PHP 即可！其他的部分或许影响不大。但是如果今天 PHP 需要重新编译的模组比较多，那么可能会连带的，连 Apache 这个程式也需要重新编译过才行！真是有点给他头痛的！没办法啦！使用 tarball 确实有他的优点啦，但是在这方面，确实也有他一定的伤脑筋程度。

由于 Tarball 在升级与安装上面具有这些特色，亦即 Tarball 在反安装上面具有比较高的难度 (如果你没有好好规划的话～)，所以，为了方便 Tarball 的管理，通常鸟哥会这样建议使用者：

  1. 最好将 tarball 的原始资料解压缩到 /usr/local/src 当中；

  2. 安装时，最好安装到 /usr/local 这个预设路径下；

  3. 考虑未来的反安装步骤，最好可以将每个软体单独的安装在 /usr/local 底下；

  4. 为安装到单独目录的软体之 man page 加入 man path 搜寻：
    如果你安装的软体放置到 /usr/local/software/ ，那么 man page 搜寻的设定中，可能就得要在 /etc/man.config 内的 40~50 行左右处，写入如下的一行：
    MANPATH /usr/local/software/man
    这样才可以使用 man 来查询该软体的线上文件啰！
小标题的图示 一个简单的范例、利用 ntp 来示范

读万卷书不如行万里路啊！所以当然我们就来给他测试看看，看你是否真的了解了如何利用 Tarball 来安装软体呢？我们利用时间伺服器 (network time protocol) ntp 这个软体来测试安装看看。先请到 http://www.ntp.org/downloads.html 这个目录去下载档案，请下载最新版本的档案即可。或者直接到鸟哥的网站下载 2009/05 公告释出的稳定版本：

http://linux.vbird.org/linux_basic/0520source/ntp-4.2.4p7.tar.gz

假设我对这个软体的要求是这样的：

  • 假设 ntp-4.2.4p7.tar.gz 这个档案放置在 /root 这个目录下；
  • 原始码请解开在 /usr/local/src 底下；
  • 我要安装到 /usr/local/ntp 这个目录中；

那么你可以依照底下的步骤来安装测试看看 (如果可以的话，请你不要参考底下的文件资料， 先自行安装过一遍这个软体，然后再来对照一下鸟哥的步骤喔！)。

  • 解压缩下载的 tarball ，并参阅 README/INSTALL 档案
[root@www ~]# cd /usr/local/src   <==切换目录
[root@www src]# tar -zxvf /root/ntp-4.2.4p7.tar.gz  <==解压缩到此目录
ntp-4.2.4p7/         <==会建立这个目录喔！
ntp-4.2.4p7/libopts/
....(底下省略)....
[root@www src]# cd ntp-4.2.4p7/
[root@www ntp-4.2.4p7]# vi INSTALL  <==记得 README 也要看一下！
# 特别看一下 28 行到 54 行之间的安装简介！可以了解如何安装的流程喔！
  • 检查 configure 支援参数，并实际建置 makefile 规则档
[root@www ntp*]# ./configure --help | more  <==查询可用的参数有哪些
  --prefix=PREFIX         install architecture-independent files in PREFIX
  --enable-all-clocks     + include all suitable non-PARSE clocks:
  --enable-parse-clocks   - include all suitable PARSE clocks:
# 上面列出的是比较重要的，或者是你可能需要的参数功能！

[root@www ntp*]# ./configure --prefix=/usr/local/ntp \
>  --enable-all-clocks --enable-parse-clocks  <==开始建立makefile
checking for a BSD-compatible install... /usr/bin/install -c
checking whether build environment is sane... yes
....(中间省略)....
checking for gcc... gcc           <==也有找到 gcc 编译器了！
....(中间省略)....
config.status: creating Makefile  <==现在知道这个重要性了吧？
config.status: creating config.h
config.status: executing depfiles commands

一般来说 configure 设定参数较重要的就是那个 --prefix=/path 了，--prefix 后面接的路径就是‘这个软体未来要安装到那个目录去？’如果你没有指定 --prefix=/path 这个参数，通常预设参数就是 /usr/local 至于其他的参数意义就得要参考 ./configure --help 了！ 这个动作完成之后会产生 makefile 或 Makefile 这个档案。当然啦，这个侦测检查的过程会显示在荧幕上， 特别留意关于 gcc 的检查，还有最重要的是最后需要成功的建立起 Makefile 才行！

  • 最后开始编译与安装噜！
[root@www ntp*]# make clean; make
[root@www ntp*]# make check
[root@www ntp*]# make install
# 将资料给他安装在 /usr/local/ntp 底下

整个动作就这么简单，你完成了吗？完成之后到 /usr/local/ntp 你发现了什么？

小标题的图示 利用 patch 更新原始码

我们在本章一开始介绍了为何需要进行软体的升级，这是很重要的喔！那假如我是以 Tarball 来进行某个软体的安装，那么是否当我要升级这个软体时，就得要下载这个软体的完整全新的 Tarball 呢？举个例子来说，鸟哥帮昆山资传系架了个讨论区在 http://www.dic.ksu.edu.tw/phpbb3 这个网址，这个讨论区是以 phpBB 这个软体来架设的，而鸟哥的讨论区版本为 phpbb3.0.4.tar.gz ，目前 (2009/06) 最新释出的版本则是 phpbb3.0.5.tar.gz 。那我是否需要下载全新的 phpbb3.0.5.tar.gz 这个档案来更新原本的旧程式呢？

事实上，当我们发现一些软体的漏洞，通常是某一段程式码写的不好所致。因此， 所谓的‘更新原始码’常常是只有更改部分档案的小部分内容而已。既然如此的话， 那么我们是否可以就那些被更动的档案来进行修改就可以咯？也就是说， 旧版本到新版本间没有更动过的档案就不要理他，仅将有修订过的档案部分来处理即可。

这有什么好处呢？首先，没有更动过的档案的目标档 (object file) 根本就不需要重新编译，而且有更动过的档案又可以利用 make 来自动 update (更新)，如此一来，我们原先的设定 (makefile 档案里面的规则) 将不需要重新改写或侦测！可以节省很多宝贵的时间呢 (例如后续章节会提到的核心的编译！)

从上面的说明当中，我们可以发现，如果可以将旧版的原始码资料改写成新版的版本， 那么就能直接编译了，而不需要将全部的新版 Tarball 重新下载一次呢！可以节省频宽与时间说！那么如何改写原始码？ 难道要我们一个档案一个档案去参考然后修订吗？当然没有这么没人性！

我们在第十二章、正规表示法的时候有提到一个比对档案的指令，那就是 diff，这个指令可以将‘两个档案之间的差异性列出来’呢！那我们也知道新旧版本的档案之间， 其实只有修改一些程式码而已，那么我们可以透过 diff 比对出新旧版本之间的文字差异，然后再以相关的指令来将旧版的档案更新吗？ 呵呵！当然可以啦！那就是 patch 这个指令啦！很多的软体开发商在更新了原始码之后，几乎都会释出所谓的 patch file，也就是直接将原始码 update 而已的一个方式喔！我们底下以一个简单的范例来说明给你了解喔！

关于 diff 与 patch 的基本用法我们在第十二章都谈过了，所以这里不再就这两个指令的语法进行介绍， 请回去参阅第十二章的内容。这里我们来举个案例解释一下好了。假设我们刚刚计算三角函数的程式 (main) 历经多次改版， 0.1 版仅会简单的输出， 0.2 版的输出就会含有角度值，因此这两个版本的内容不相同。如下所示，两个档案的意义为：

  • http://linux.vbird.org/linux_basic/0520source/main-0.1.tgz ：main 的 0.1 版；
  • http://linux.vbird.org/linux_basic/0520source/main_0.1_to_0.2.patch ：main 由 0.1 升级到 0.2 的 patch file；

请您先下载这两个档案，并且解压缩到你的 /root 底下。你会发现系统产生一个名为 main-0.1 的目录。 该目录内含有五个档案，就是刚刚的程式加上一个 Makefile 的规则档案。你可以到该目录下去看看 Makefile 的内容， 在这一版当中含有 main 与 clean 两个标的功能而已。至于 0.2 版则加入了 install 与 uninstall 的规则设定。 接下来，请看一下我们的作法啰：

  • 测试旧版程式的功能
[root@www ~]# tar -zxvf main-0.1.tgz
[root@www ~]# cd main-0.1
[root@www main-0.1]# make clean main
[root@www main-0.1]# ./main
version 0.1
Please input your name: VBird
Please enter the degree angle (ex> 90): 45
Hi, Dear VBird, nice to meet you.
The Sin is:  0.71
The Cos is:  0.71

与之前的结果非常类似，只是鸟哥将 Makefile 直接给您了！但如果你下达 make install 时，系统会告知没有 install 的 target 啊！而且版本是 0.1 也告知了。那么如何更新到 0.2 版呢？透过这个 patch 档案吧！这个档案的内容有点像这样：

  • 查阅 patch file 内容
[root@www main-0.1]# vim ~/main_0.1_to_0.2.patch
diff -Naur main-0.1/cos_value.c main-0.2/cos_value.c
--- main-0.1/cos_value.c        2009-06-09 22:52:33.000000000 +0800
+++ main-0.2/cos_value.c        2009-06-12 00:45:10.000000000 +0800
@@ -6,5 +6,5 @@
 {
        float value;
....(底下省略)....

上面表格内有个底线的部分，那代表使用 diff 去比较时，被比较的两个档案所在路径，这个路径非常的重要喔！ 因为 patch 的基本语法如下：

patch -p数字 < patch_file

特别留意那个‘ -p数字’，那是与 patch_file 里面列出的档名有关的资讯。假如在 patch_file 第一行写的是这样：

*** /home/guest/example/expatch.old

那么当我下达‘ patch -p0 < patch_file ’时，则更新的档案是‘ /home/guest/example/expatch.old ’，如果‘ patch -p1 < patch_file’，则更新的档案为‘home/guest/example/expatch.old’，如果‘patch -p4 < patch_file’则更新‘expatch.old’，也就是说， -pxx 那个 xx 代表‘拿掉几个斜线(/)’的意思！这样可以理解了吗？ 好了，根据刚刚上头的资料，我们可以发现比较的档案是在 main-0.1/xxx 与 main-0.2/xxx ， 所以说，如果你是在 main-0.1 底下，并且想要处理更新时，就得要拿掉一个目录 (因为并没有 main-0.2 的目录存在， 我们是在当前的目录进行更新的！)，因此使用的是 -p1 才对喔！所以：

  • 更新原始码，并且重新编译程式！
[root@www main-0.1]# patch -p1 < ../main_0.1_to_0.2.patch
patching file cos_value.c
patching file main.c
patching file Makefile
patching file sin_value.c
# 请注意，鸟哥目前所在目录是在 main-0.1 底下喔！注意与 patch 档案的相对路径！
# 虽然有五个档案，但其实只有四个档案有修改过喔！上面显示有改过的档案！

[root@www main-0.1]# make clean main
[root@www main-0.1]# ./main
version 0.2
Please input your name: VBird
Please enter the degree angle (ex> 90): 45
Hi, Dear VBird, nice to meet you.
The sin(45.000000) is:  0.71
The cos(45.000000) is:  0.71
# 你可以发现，输出的结果中版本变了，输出资讯多了括号 () 喔！

[root@www main-0.1]# make install   <==将他安装到 /usr/local/bin 给大家用
cp -a main /usr/local/bin
[root@www main-0.1]# main           <==直接输入指令可执行！
[root@www main-0.1]# make uninstall <==移除此软体！
rm -f /usr/local/bin/main

很有趣的练习吧！所以你只要下载 patch file 就能够对你的软体原始码更新了！只不过更新了原始码并非软体就更新！你还是得要将该软体进行编译后，才会是最终正确的软体喔！ 因为 patch 的功能主要仅只是更新原始码档案而已！切记切记！此外，如果你 patch 错误呢？没关系的！我们的 patch 是可以还原的啊！透过‘ patch -R < ../main_0.1_to_0.2.patch ’就可以还原啦！很有趣吧！

例题：
如果我有一个很旧版的软体，这个软体已经更新到很新的版本，例如核心，那么我可以使用 patch file 来更新吗？
答：
这个问题挺有趣的，首先，你必须要确定旧版本与新版本之间‘确实有释出 patch file ’才行，以 kernel 2.2.xx 及 2.4.xx 来说，这两者基本上的架构已经不同了，所以两者间是无法以 patch file 来更新的。不过， 2.4.xx 与 2.4.yy 就可以更新了。不过，因为 kernel 每次推出的 patch 档案都仅针对前一个版本而已，所以假设要由 kernel 2.4.20 升级到 2.4.26 ，就必须要使用 patch 2.4.21, 2.4.22, 2.4.23, 2.4.24, 2.4.25, 2.4.26 六个档案来‘依序更新’才行喔！当然，如果有朋友帮你比对过 2.4.20 与 2.4.26 ，那你自然就可以使用该 patch file 来直接一次更新啰！

大标题的图示 函式库管理

在我们的 Linux 作业系统当中，函式库是很重要的一个项目。 因为很多的软体之间都会互相取用彼此提供的函式库来进行特殊功能的运作， 例如很多需要验证身份的程式都习惯利用 PAM 这个模组提供的验证机制来实作，而很多网路连线机制则习惯利用 SSL 函式库来进行连线加密的机制。所以说，函式库的利用是很重要的。不过， 函式库又依照是否被编译到程式内部而分为动态与静态函式库，这两者之间有何差异？哪一种函式库比较好？ 底下我们就来谈一谈先！

小标题的图示 动态与静态函式库

首先我们要知道的是，函式库的类型有哪些？依据函式库被使用的类型而分为两大类，分别是静态 (Static) 与动态 (Dynamic) 函式库两类。底下我们来谈一谈这两种类行的函式库吧！

  • 静态函式库的特色：
  • 副档名：(副档名为 .a)
    这类的函式库通常副档名为 libxxx.a 的类型；

  • 编译行为：
    这类函式库在编译的时候会直接整合到执行程式当中，所以利用静态函式库编译成的档案会比较大一些喔；

  • 独立执行的状态：
    这类函式库最大的优点，就是编译成功的可执行档可以独立执行，而不需要再向外部要求读取函式库的内容 (请参照动态函式库的说明)。

  • 升级难易度：
    虽然执行档可以独立执行，但因为函式库是直接整合到执行档中， 因此若函式库升级时，整个执行档必须要重新编译才能将新版的函式库整合到程式当中。 也就是说，在升级方面，只要函式库升级了，所有将此函式库纳入的程式都需要重新编译！

  • 动态函式库的特色：
  • 副档名：(副档名为 .so)
    这类函式库通常副档名为 libxxx.so 的类型；

  • 编译行为：
    动态函式库与静态函式库的编译行为差异挺大的。 与静态函式库被整个捉到程式中不同的，动态函式库在编译的时候，在程式里面只有一个‘指向 (Pointer)’的位置而已。也就是说，动态函式库的内容并没有被整合到执行档当中，而是当执行档要使用到函式库的机制时， 程式才会去读取函式库来使用。由于执行档当中仅具有指向动态函式库所在的指标而已， 并不包含函式库的内容，所以他的档案会比较小一点。

  • 独立执行的状态：
    这类型的函式库所编译出来的程式不能被独立执行， 因为当我们使用到函式库的机制时，程式才会去读取函式库，所以函式库档案‘必须要存在’才行，而且，函式库的‘所在目录也不能改变’，因为我们的可执行档里面仅有‘指标’亦即当要取用该动态函式库时， 程式会主动去某个路径下读取，呵呵！所以动态函式库可不能随意移动或删除，会影响很多相依的程式软体喔！

  • 升级难易度：
    虽然这类型的执行档无法独立运作，然而由于是具有指向的功能， 所以，当函式库升级后，执行档根本不需要进行重新编译的行为，因为执行档会直接指向新的函式库档案 (前提是函式库新旧版本的档名相同喔！)。

目前的 Linux distribution 比较倾向于使用动态函式库，因为如同上面提到的最重要的一点， 就是函式库的升级方便！由于 Linux 系统里面的软体相依性太复杂了，如果使用太多的静态函式库，那么升级某一个函式库时， 都会对整个系统造成很大的冲击！因为其他相依的执行档也要同时重新编译啊！ 这个时候动态函式库可就有用多了，因为只要动态函式库升级就好，其他的软体根本无须变动。

那么这些函式库放置在哪里呢？绝大多数的函式库都放置在：/usr/lib, /lib 目录下！ 此外，Linux 系统里面很多的函式库其实 kernel 就提供了，那么 kernel 的函式库放在哪里？呵呵！就是在 /lib/modules 里面啦！里面的资料可多着呢！不过要注意的是， 不同版本的核心提供的函式库差异性是挺大的，所以 kernel 2.4.xx 版本的系统不要想将核心换成 2.6.xx 喔！ 很容易由于函式库的不同而导致很多原本可以执行的软体无法顺利运作呢！

小标题的图示 ldconfig 与 /etc/ld.so.conf

在了解了动态与静态函式库，也知道我们目前的 Linux 大多是将函式库做成动态函式库之后，再来要知道的就是，那有没有办法增加函式库的读取效能？ 我们知道记忆体的存取速度是硬碟的好几倍，所以，如果我们将常用到的动态函式库先载入记忆体当中 (快取, cache)，如此一来，当软体要取用动态函式库时，就不需要从头由硬碟里面读出啰！ 这样不就可以增进动态函式库的读取速度？没错，是这样的！这个时候就需要 ldconfig 与 /etc/ld.so.conf 的协助了。

如何将动态函式库载入快取记忆体当中呢？

  1. 首先，我们必须要在 /etc/ld.so.conf 里面写下‘ 想要读入快取记忆体当中的动态函式库所在的目录’，注意喔， 是目录而不是档案；
  2. 接下来则是利用 ldconfig 这个执行档将 /etc/ld.so.conf 的资料读入快取当中；
  3. 同时也将资料记录一份在 /etc/ld.so.cache 这个档案当中呐！
使用 ldconfig 预载入动态函式库到记忆体中
图 5.2.1、使用 ldconfig 预载入动态函式库到记忆体中

事实上， ldconfig 还可以用来判断动态函式库的连结资讯呢！赶紧利用 CentOS 来测试看看。假设你想要将目前你系统下的 MySQL 函式库加入到快取当中时，可以这样做：

[root@www ~]# ldconfig [-f conf] [ -C cache]
[root@www ~]# ldconfig [-p]
选项与参数：
-f conf ：那个 conf 指的是某个档案名称，也就是说，使用 conf 作为 libarary
      函式库的取得路径，而不以 /etc/ld.so.conf 为预设值
-C cache：那个 cache 指的是某个档案名称，也就是说，使用 cache 作为快取暂存
      的函式库资料，而不以 /etc/ld.so.cache 为预设值
-p	：列出目前有的所有函式库资料内容 (在 /etc/ld.so.cache 内的资料！)

范例一：假设我的 MySQL 资料库函式库在 /usr/lib/mysql 当中，如何读进 cache ？
[root@www ~]# vi /etc/ld.so.conf
include ld.so.conf.d/*.conf
/usr/lib/mysql   <==这一行新增的啦！

[root@www ~]# ldconfig  <==画面上不会显示任何的资讯，不要太紧张！正常的！

[root@www ~]# ldconfig -p
530 libs found in cache `/etc/ld.so.cache'
        libz.so.1 (libc6) => /usr/lib/libz.so.1
        libxslt.so.1 (libc6) => /usr/lib/libxslt.so.1
....(底下省略)....
#       函式库名称 => 该函式库实际路径

透过上面的动作，我们可以将 MySQL 的相关函式库给他读入快取当中，这样可以加快函式库读取的效率呢！ 在某些时候，你可能会自行加入某些 Tarball 安装的动态函式库，而你想要让这些动态函式库的相关连结可以被读入到快取当中， 这个时候你可以将动态函式库所在的目录名称写入 /etc/ld.so.conf 当中，然后执行 ldconfig 就可以啦！

小标题的图示 程式的动态函式库解析： ldd

说了这么多，那么我如何判断某个可执行的 binary 档案含有什么动态函式库呢？很简单，利用 ldd 就可以晓得了！例如我想要知道 /usr/bin/passwd 这个程式含有的动态函式库有哪些，可以这样做：

[root@www ~]# ldd [-vdr] [filename]
选项与参数：
-v ：列出所有内容资讯；
-d ：重新将资料有遗失的 link 点秀出来！
-r ：将 ELF 有关的错误内容秀出来！

范例一：找出 /usr/bin/passwd 这个档案的函式库资料
[root@www ~]# ldd /usr/bin/passwd
....(前面省略)....
        libaudit.so.0 => /lib/libaudit.so.0 (0x00494000)     <==SELinux
        libselinux.so.1 => /lib/libselinux.so.1 (0x00101000) <==SELinux
        libc.so.6 => /lib/libc.so.6 (0x00b99000)
        libpam.so.0 => /lib/libpam.so.0 (0x004ab000)         <==PAM 模组
....(底下省略)....
# 我们前言的部分不是一直提到 passwd 有使用到 pam 的模组吗！怎么知道？
# 利用 ldd 察看一下这个档案，看到 libpam.so 了吧？这就是 pam 提供的函式库

范例二：找出 /lib/libc.so.6 这个函式的相关其他函式库！
[root@www ~]# ldd -v /lib/libc.so.6
        /lib/ld-linux.so.2 (0x00ab3000)
        linux-gate.so.1 =>  (0x00636000)

        Version information:  <==使用 -v 选项，增加显示其他版本资讯！
        /lib/libc.so.6:
                ld-linux.so.2 (GLIBC_PRIVATE) => /lib/ld-linux.so.2
                ld-linux.so.2 (GLIBC_2.3) => /lib/ld-linux.so.2
                ld-linux.so.2 (GLIBC_2.1) => /lib/ld-linux.so.2

未来如果你常常升级安装 RPM 的软体时 (下一章节会介绍)，应该常常会发现那个‘ 相依属性’的问题吧！没错！我们可以先以 ldd 来视察‘相依函式库’之间的相关性！以先取得了解！ 例如上面的例子中，我们检查了 libc.so.6 这个在 /lib 当中的函式库，结果发现他其实还跟 ld-linux.so.2 有关！所以我们就需要来了解一下，那个档案到底是什么软体的函式库呀？使用 -v 这个参数还可以得知该函式库来自于哪一个软体！像上面的资料中，就可以得到该 libc.so.6 其实可以支援 GLIBC_2.1 等的版本！

大标题的图示 检验软体正确性

前面提到很多升级与安装需要注意的事项，因为我们需要克服很多的程式漏洞，所以需要前往 Linux distribution 或者是某些软体开发商的网站，下载最新并且较安全的软体档案来安装才行。 好了，那么‘有没有可能我们下载的档案本身就有问题？’ 是可能的！因为 cracker 无所不在，很多的软体开发商已经公布过他们的网页所放置的档案曾经被窜改过！ 那怎么办？连下载原版的资料都可能有问题了？难道没有办法判断档案的正确性吗？

这个时候我们就要透过每个档案独特的指纹验证资料了！因为每个档案的内容与档案大小都不相同， 所以如果一个档案被修改之后，必然会有部分的资讯不一样！利用这个咚咚，我们可以使用 MD5 这个指纹验证机制来判断该档案有没有被更动过！ 举个例子来说，台湾高速网路中心所提供的 CentOS 5.3 原版光碟下载点：

http://ftp.twaren.net/Linux/CentOS/5.3/isos/i386/

同时提供了 CentOS 5.3 所有光碟/DVD 的 ISO 档案 MD5 编码，透过这个编码的比对， 我们就可以晓得下载的档案是否有问题。那么万一 CentOS 提供的光碟映象档被下载之后，让有心人士偷偷修改过，再转到 Internet 上面流传，那么你下载的这个档案偏偏不是原厂提供的，呵呵！ 你能保证该档案的内容完全没有问题吗？当然不能对不对！是的，这个时候就有 md5sum 与 sha1sum 这个档案指纹的咚咚出现啦！说说他的用法吧！

小标题的图示 md5sum / sha1sum

目前有多种机制可以计算档案的指纹码，我们选择使用较为广泛的 MD5 与 SHA1 加密机制来处理。 同样的，我们以高速电脑中心谈到的 CentOS 5.3 的网路安装映像档来处理试看看好了。 在上面的连结网址上面，你会看到几个档案：

  • CentOS-5.3-i386-netinstall.iso：CentOS 5.3 的网路安装映像档；
  • md5sum.txt： MD5 指纹编码
  • sha1sum.txt： SHA1 指纹编码

如果你下载了 CentOS-5.3-i386-netinstall.iso 后，再以 md5sum 与 sha1sum 去检验这个档案时， 档案所回传的指纹码应该要与网站上面提供的档案指纹码相同才对！我们由网站上面提供的指纹码知道这个映像档的指纹为：

  • MD5 : 6ae4077a9fc2dcedca96013701bd2a43
  • SHA1: a0c640ae0c68cc0d9558cf4f8855f24671b3dadb
[root@www ~]# md5sum/sha1sum [-bct] filename
[root@www ~]# md5sum/sha1sum [--status|--warn] --check filename
选项与参数：
-b ：使用 binary 的读档方式，预设为 Windows/DOS 档案型态的读取方式；
-c ：检验档案指纹；
-t ：以文字型态来读取档案指纹。

范例一：将刚刚的档案下载后，测试看看指纹码
[root@www ~]# wget \
> http://ftp.twaren.net/Linux/CentOS/5.3/isos/i386/CentOS-5.3-i386-netinstall.iso
[root@www ~]# md5sum CentOS-5.3-i386-netinstall.iso
6ae4077a9fc2dcedca96013701bd2a43  CentOS-5.3-i386-netinstall.iso
[root@www ~]# sha1sum CentOS-5.3-i386-netinstall.iso
a0c640ae0c68cc0d9558cf4f8855f24671b3dadb  CentOS-5.3-i386-netinstall.iso
# 看！显示的编码是否与上面相同呢？赶紧测试看看！

一般而言，每个系统里面的档案内容大概都不相同，例如你的系统中的 /etc/passwd 这个登入资讯档与我的一定不一样，因为我们的使用者与密码、 Shell 及家目录等大概都不相同，所以由 md5sum 这个档案指纹分析程式所自行计算出来的指纹表当然就不相同啰！

好了，那么如何应用这个东西呢？基本上，你必须要在你的 Linux 系统上为你的这些重要的档案进行指纹资料库的建立 (好像在做户口调查！)，将底下这些档案建立资料库：

  • /etc/passwd
  • /etc/shadow( 假如你不让使用者改密码了 )
  • /etc/group
  • /usr/bin/passwd
  • /sbin/portmap
  • /bin/login ( 这个也很容易被骇！ )
  • /bin/ls
  • /bin/ps
  • /usr/bin/top

这几个档案最容易被修改了！因为很多木马程式执行的时候，还是会有所谓的‘执行序, PID’为了怕被 root 追查出来，所以他们都会修改这些检查排程的档案，如果你可以替这些档案建立指纹资料库 (就是使用 md5sum 检查一次，将该档案指纹记录下来，然后常常以 shell script 的方式由程式自行来检查指纹表是否不同了！)，那么对于档案系统会比较安全啦！

大标题的图示 重点回顾
  • 原始码其实大多是纯文字档，需要透过编译器的编译动作后，才能够制作出 Linux 系统能够认识的可执行的 binary file ；
  • 开放原始码可以加速软体的更新速度，让软体效能更快、漏洞修补更即时；
  • 在 Linux 系统当中，最标准的 C 语言编译器为 gcc ；
  • 在编译的过程当中，可以藉由其他软体提供的函式库来使用该软体的相关机制与功能；
  • 为了简化编译过程当中的复杂的指令输入，可以藉由 make 与 makefile 规则定义，来简化程式的更新、编译与连结等动作；
  • Tarball 为使用 tar 与 gzip/bzip2 压缩功能所打包与压缩的，具有原始码的档案；
  • 一般而言，要使用 Tarball 管理 Linux 系统上的软体，最好需要 gcc, make, autoconfig, kernel source, kernel header 等前驱软体才行，所以在安装 Linux 之初，最好就能够选择 Software development 以及 kernel development 之类的群组；
  • 函式库有动态函式库与静态函式库，动态函式库在升级上具有较佳的优势。动态函式库的副档名为 *.so 而静态则是 *.a ；
  • patch 的主要功能在更新原始码，所以更新原始码之后，还需要进行重新编译的动作才行；
  • 可以利用 ldconfig 与 /etc/ld.so.conf 来制作动态函式库的连结与快取！
  • 透过 MD5 的编码可以判断下载的档案是否为原本厂商所释出的档案。
大标题的图示 本章习题
实作题部分：
  • 请前往企鹅游戏网站 http://xpenguins.seul.org/ 下载 xpenguins-2.2.tar.gz 原始码档案，并安装该软体。安装完毕之后，请在 GNOME 图形介面执行 xpenguins ， 看看有没有出现如同官网上面出现的小企鹅？

情境模拟题部分：
  • 请依照底下的方式来建置你的系统的重要档案指纹码，并每日比对此重要工作。

    1. 将 /etc/{passwd,shadow,group} 以及系统上面所有的 SUID/SGID 档案建立档案列表，该列表档名为‘ important.file ’；
      [root@www ~]# ls /etc/{passwd,shadow,group} > important.file
[root@www ~]# find /bin /sbin /usr/sbin /usr/bin -perm +6000 \
> >> important.file

    2. 透过这个档名列表，以名为 md5.checkfile.sh 的档名去建立指纹码，并将该指纹码档案‘ finger1.file ’设定成为不可修改的属性；
      [root@www ~]# vim md5.checkfile.sh
#!/bin/bash
for filename in $(cat important.file)
do
        md5sum $filename >> finger1.file
done

[root@www ~]# sh md5.checkfile.sh
[root@www ~]# chattr +i finger1.file

    3. 透过相同的机制去建立后续的分析资料为 finger_new.file ，并将两者进行比对，若有问题则提供 email 给 root 查阅：
      [root@www ~]# vim md5.checkfile.sh
#!/bin/bash
if [ "$1" == "new" ]; then
    for filename in $(cat important.file)
    do
        md5sum $filename >> finger1.file
    done
    echo "New file finger1.file is created."
    exit 0
fi
if [ ! -f finger1.file ]; then
    echo "file: finger1.file NOT exist."
    exit 1
fi

[ -f finger_new.file ] && rm finger_new.file
for filename in $(cat important.file)
do
    md5sum $filename >> finger_new.file
done

testing=$(diff finger1.file finger_new.file)
if [ "$testing" != "" ]; then
    diff finger1.file finger_new.file | mail -s 'finger trouble..' root
fi

[root@www ~]# vim /etc/crontab
30 2 * * * root cd /root; sh md5.checkfile.sh
      如此一来，每天系统会主动的去分析你认为重要的档案之指纹资料，然后再加以分析，看看有没有被更动过。 不过，如果该变动是正常的，例如 CentOS 自动的升级时，那么你就得要删除 finger1.file ， 再重新建置一个新的指纹资料库才行！否则你会每天收到有问题信件的回报喔！
大标题的图示 参考资料与延伸阅读
  • 注1：GNU 的 make 网页：http://www.gnu.org/software/make/manual/make.html
  • 几种常见加密机制的全名：
    md5 (Message-Digest algorithm 5) http://en.wikipedia.org/wiki/MD5
    sha (Secure Hash Algorithm) http://en.wikipedia.org/wiki/SHA_hash_functions
    des (Data Encryption Standard) http://en.wikipedia.org/wiki/Data_Encryption_Standard
  • 洪朝贵老师的 C 程式语言：http://www.cyut.edu.tw/~ckhung/b/c/
2002/08/21：第一次完成
2003/02/11：重新编排与加入 FAQ
2004/03/25：原本是 Tarball 与 RPM ，本日开始将 Tarball 与 RPM 分开说明与讲解(后续会花好几天喔！)，
           最重要的是 Source code 的说明，并提到相关的 gcc compile 功能等等！
2004/04/10：经历了当兵中的无奈生活，终于将这篇给他完工了～(当时的鸟哥在将军渔港与青山港～)
2005/09/30：旧版文章 (Tarball 与 RPM 的简单说明) 移动到 此处 。
2005/10/01：将风格作个转变之外，也将一些测试移转到 FC4 上面进行！
2008/01/10：感谢网友 ayttk 的说明，原本的 make 语法网页已经移动到其他地方了，请参考 这里。
2009/06/04：将基于 FC4 撰写的文章移动到 此处
2009/06/20：增加一个小练习，需要使用到 X software development 的软体群组喔！
2009/09/15：加入一个情境模拟，其实有点功力练功练功而已的习题啰！


鸟哥的 Linux 私房菜 -- RPM 与 SRPM 软体管理员

为取得较佳浏览结果，请爱用 firefox 浏览本网页
鸟哥的 Linux 私房菜馆 | Linux 基础文件 | Linux 架站文件 | Linux 企业运用 | 安全管理 | 新手讨论 |

第二十三章、软体安装： RPM, SRPM 与 YUM 功能
最近更新日期：2009/09/18
虽然使用原始码进行软体编译可以具有客制化的设定，但对于 Linux distribution 的发布商来说，则有软体管理不易的问题， 毕竟不是每个人都会进行原始码编译的。如果能够将软体预先在相同的硬体与作业系统上面编译好才发布的话， 不就能够让相同的 distribution 具有完全一致的软体版本吗？如果再加上简易的安装/移除/管理等机制的话， 对于软体控管就会简易的多。有这种东西吗？有的，那就是 RPM 与 YUM 这两个好用的咚咚。 既然这么好用，我们当然不能错过学习机会啰！赶紧来参详参详！

1. 软体管理员简介
    1.1 Linux 界的两大主流: RPM 与 DPKG
    1.2 什么是 RPM 与 SRPM
    1.3 什么是 i386, i586, i686, noarch, x86_64
    1.4 RPM 的优点
    1.5 RPM 属性相依的克服方式： YUM 线上升级
 2. RPM 软体管理程式： rpm
    2.1 RPM 预设安装的路径
    2.2 RPM 安装 (install)
    2.3 RPM 升级与更新 (upgrade/freshen)
    2.4 RPM 查询 (query)
    2.5 RPM 验证与数位签章 (Verify/signature)
    2.6 RPM 反安装与重建资料库 (erase/rebuilddb)
 3. SRPM 的使用： rpmbuild
    3.1 利用预设值安装 SRPM 档案 (--rebuid/--recompile)
    3.2 SRPM 使用的路径与需要的软体
    3.3 设定档的主要内容 (*.spec)
    3.4 SRPM 的编译指令 (-ba/-bb)
    3.5 一个打包自己软体的范例
 4. YUM 线上升级机制
    4.1 利用 yum 进行查询、安装、升级与移除功能
    4.2 yum 的设定档
    4.3 yum 的软体群组功能
    4.4 全系统自动升级
 5. 管理的抉择：RPM 还是 Tarball
6. 重点回顾
7. 本章习题
8. 参考资料与延伸阅读
9. 针对本文的建议：http://phorum.vbird.org/viewtopic.php?t=23893
大标题的图示 软体管理员简介

在前一章我们提到以原始码的方式来安装软体，也就是利用厂商释出的 Tarball 来进行软体的安装。不过，你应该很容易发现，那就是每次安装软体都需要侦测作业系统与环境、设定编译参数、实际的编译、 最后还要依据个人喜好的方式来安装软体到定位。这过程是真的很麻烦的，而且对于不熟整个系统的朋友来说，还真是累人啊！

那有没有想过，如果我的 Linux 系统与厂商的系统一模一样，那么在厂商的系统上面编译出来的执行档， 自然也就可以在我的系统上面跑啰！也就是说，厂商先在他们的系统上面编译好了我们使用者所需要的软体， 然后将这个编译好的可执行的软体直接释出给使用者来安装，如此一来，由于我们本来就使用厂商的 Linux distribution ，所以当然系统 (硬体与作业系统) 是一样的，那么使用厂商提供的编译过的可执行档就没有问题啦！ 说的比较白话一些，那就是利用类似 Windows 的安装方式，由程式开发者直接在已知的系统上面编译好，再将该程式直接给使用者来安装，如此而已。

那么如果在安装的时候还可以加上一些与这些程式相关的资讯，将他建立成为资料库，那不就可以进行安装、反安装、 升级与验证等等的相关功能啰 (类似 Windows 底下的‘新增移除程式’)？确实如此，在 Linux 上面至少就有两种常见的这方面的软体管理员，分别是 RPM 与 Debian 的 dpkg 。我们的 CentOS 主要是以 RPM 为主，但也不能不知道 dpkg 啦！所以底下就来约略介绍一下这两个玩意儿。

小标题的图示 Linux 界的两大主流: RPM 与 DPKG

由于自由软体的蓬勃发展，加上大型 Unix-Like 主机的强大效能，让很多软体开发者将他们的软体使用 Tarball 来释出。 后来 Linux 发展起来后，由一些企业或社群将这些软体收集起来制作成为 distributions 以发布这好用的 Linux 作业系统。但后来发现到，这些 distribution 的软体管理实在伤脑筋， 如果软体有漏洞时，又该如何修补呢？使用 tarball 的方式来管理吗？又常常不晓得到底我们安装过了哪些程式？ 因此，一些社群与企业就开始思考 Linux 的软体管理方式。

如同刚刚谈过的方式，Linux 开发商先在固定的硬体平台与作业系统平台上面将需要安装或升级的软体编译好， 然后将这个软体的所有相关档案打包成为一个特殊格式的档案，在这个软体档案内还包含了预先侦测系统与相依软体的脚本， 并提供记载该软体提供的所有档案资讯等。最终将这个软体档案释出。用户端取得这个档案后，只要透过特定的指令来安装， 那么该软体档案就会依照内部的脚本来侦测相依的前驱软体是否存在，若安装的环境符合需求，那就会开始安装， 安装完成后还会将该软体的资讯写入软体管理机制中，以达成未来可以进行升级、移除等动作呢。

目前在 Linux 界软体安装方式最常见的有两种，分别是：

  • dpkg：
    这个机制最早是由 Debian Linux 社群所开发出来的，透过 dpkg 的机制， Debian 提供的软体就能够简单的安装起来，同时还能提供安装后的软体资讯，实在非常不错。 只要是衍生于 Debian 的其他 Linux distributions 大多使用 dpkg 这个机制来管理软体的， 包括 B2D, Ubuntu 等等。

  • RPM：
    这个机制最早是由 Red Hat 这家公司开发出来的，后来实在很好用，因此很多 distributions 就使用这个机制来作为软体安装的管理方式。包括 Fedora, CentOS, SuSE 等等知名的开发商都是用这咚咚。

如前所述，不论 dpkg/rpm 这些机制或多或少都会有软体属性相依的问题，那该如何解决呢？ 其实前面不是谈到过每个软体档案都有提供相依属性的检查吗？那么如果我们将相依属性的资料做成列表， 等到实际软体安装时，若发生有相依属性的软体状况时，例如安装 A 需要先安装 B 与 C ，而安装 B 则需要安装 D 与 E 时，那么当你要安装 A ，透过相依属性列表，管理机制自动去取得 B, C, D, E 来同时安装， 不就解决了属性相依的问题吗？

没错！您真聪明！目前新的 Linux 开发商都有提供这样的‘线上升级’机制，透过这个机制， 原版光碟就只有第一次安装时需要用到而已，其他时候只要有网路，你就能够取得原本开发商所提供的任何软体了呢！ 在 dpkg 管理机制上就开发出 APT 的线上升级机制，RPM 则依开发商的不同，有 Red Hat 系统的 yum ， SuSE 系统的 Yast Online Update (YOU)， Mandriva 的 urpmi 软体等。

distribution 代表 | 软体管理机制 | 使用指令 | 线上升级机制(指令)
Red Hat/Fedora | RPM | rpm, rpmbuild | YUM (yum)
Debian/Ubuntu | DPKG | dpkg | APT (apt-get)

我们这里使用的是 CentOS 系统嘛！所以说：使用的软体管理机制为 RPM 机制，而用来作为线上升级的方式则为 yum ！底下就让我们来谈谈 RPM 与 YUM 的相关说明吧！

小标题的图示 什么是 RPM 与 SRPM

RPM 全名是‘ RedHat Package Manager ’简称则为 RPM 啦！顾名思义，当初这个软体管理的机制是由 Red Hat 这家公司发展出来的。 RPM 是以一种资料库记录的方式来将你所需要的软体安装到你的 Linux 系统的一套管理机制。

他最大的特点就是将你要安装的软体先编译过， 并且打包成为 RPM 机制的包装档案，透过包装好的软体里头预设的资料库记录， 记录这个软体要安装的时候必须具备的相依属性软体，当安装在你的 Linux 主机时， RPM 会先依照软体里头的资料查询 Linux 主机的相依属性软体是否满足， 若满足则予以安装，若不满足则不予安装。那么安装的时候就将该软体的资讯整个写入 RPM 的资料库中，以便未来的查询、验证与反安装！这样一来的优点是：

  1. 由于已经编译完成并且打包完毕，所以软体传输与安装上很方便 (不需要再重新编译)；
  2. 由于软体的资讯都已经记录在 Linux 主机的资料库上，很方便查询、升级与反安装

但是这也造成些许的困扰。由于 RPM 档案是已经包装好的资料，也就是说， 里面的资料已经都‘编译完成’了！所以，该软体档案几乎只能安装在原本预设的硬体与作业系统版本中。 也就是说，你的主机系统环境必须要与当初建立这个软体档案的主机环境相同才行！ 举例来说，rp-pppoe 这个 ADSL 拨接软体，他必须要在 ppp 这个软体存在的环境下才能进行安装！如果你的主机并没有 ppp 这个软体，那么很抱歉，除非你先安装 ppp 否则 rp-pppoe 就是不让你安装的 (当然你可以强制安装，但是通常都会有点问题发生就是了！)。

所以，通常不同的 distribution 所释出的 RPM 档案，并不能用在其他的 distributions 上。举例来说，Red Hat 释出的 RPM 档案，通常无法直接在 SuSE 上面进行安装的。更有甚者，相同 distribution 的不同版本之间也无法互通，例如 CentOS 4.x 的 RPM 档案就无法直接套用在 CentOS 5.x ！因此，这样可以发现这些软体管理机制的问题是：

  1. 软体档案安装的环境必须与打包时的环境需求一致或相当；
  2. 需要满足软体的相依属性需求；
  3. 反安装时需要特别小心，最底层的软体不可先移除，否则可能造成整个系统的问题！

那怎么办？如果我真的想要安装其他 distributions 提供的好用的 RPM 软体档案时？ 呵呵！还好，还有 SRPM 这个东西！SRPM 是什么呢？顾名思义，他是 Source RPM 的意思，也就是这个 RPM 档案里面含有原始码哩！特别注意的是，这个 SRPM 所提供的软体内容‘并没有经过编译’， 他提供的是原始码喔！

通常 SRPM 的副档名是以 ***.src.rpm 这种格式来命名的。不过，既然 SRPM 提供的是原始码，那么为什么我们不使用 Tarball 直接来安装就好了？这是因为 SRPM 虽然内容是原始码， 但是他仍然含有该软体所需要的相依性软体说明、以及所有 RPM 档案所提供的资料。同时，他与 RPM 不同的是，他也提供了参数设定档 (就是 configure 与 makefile)。所以，如果我们下载的是 SRPM ，那么要安装该软体时，你就必须要：

  • 先将该软体以 RPM 管理的方式编译，此时 SRPM 会被编译成为 RPM 档案；
  • 然后将编译完成的 RPM 档案安装到 Linux 系统当中

怪了，怎么 SRPM 这么麻烦呐！还要重新编译一次，那么我们直接使用 RPM 来安装不就好了？通常一个软体在释出的时候，都会同时释出该软体的 RPM 与 SRPM 。我们现在知道 RPM 档案必须要在相同的 Linux 环境下才能够安装，而 SRPM 既然是原始码的格式，自然我们就可以透过修改 SRPM 内的参数设定档，然后重新编译产生能适合我们 Linux 环境的 RPM 档案，如此一来，不就可以将该软体安装到我们的系统当中，而不必与原作者打包的 Linux 环境相同了？这就是 SRPM 的用处了！

档案格式 | 档名格式 | 直接安装与否 | 内含程式类型 | 可否修改参数并编译
RPM | xxx.rpm | 可 | 已编译 | 不可
SRPM | xxx.src.rpm | 不可 | 未编译之原始码 | 可
Tips:
为何说 CentOS 是‘社群维护的企业版’呢？ Red Hat 公司的 RHEL 释出后，连带会将 SRPM 释出。 社群的朋友就将这些 SRPM 收集起来并重新编译成为所需要的软体，再重复释出成为 CentOS，所以才能号称与 Red Hat 的 RHEL 企业版同步啊！真要感谢 SRPM 哩！如果你想要理解 CentOS 是如何编译一支程式的， 也能够透过学习 SRPM 内含的编译参数，来学习的啊！ 		鸟哥的图示
小标题的图示 什么是 i386, i586, i686, noarch, x86_64

从上面的说明，现在我们知道 RPM 与 SRPM 的格式分别为：

xxxxxxxxx.rpm   <==RPM 的格式，已经经过编译且包装完成的 rpm 档案；
xxxxx.src.rpm   <==SRPM的格式，包含未编译的原始码资讯。

那么我们怎么知道这个软体的版本、适用的平台、编译释出的次数呢？只要透过档名就可以知道了！例如 rp-pppoe-3.1-5.i386.rpm 这的档案的意义为：

rp-pppoe -        3.1    -     5        .i386        .rpm
软体名称   软体的版本资讯 释出的次数 适合的硬体平台 副档名

除了后面适合的硬体平台与副档名外，主要是以‘-’来隔开各个部分，这样子可以很清楚的发现该软体的名称、 版本资讯、打包次数与操作的硬体平台！好了，来谈一谈每个不同的地方吧：

  • 软体名称：
    当然就是每一个软体的名称了！上面的范例就是 rp-pppoe 。

  • 版本资讯：
    每一次更新版本就需要有一个版本的资讯，否则如何知道这一版是新是旧？这里通常又分为主版本跟次版本。以上面为例，主版本为 3 ，在主版本的架构下更动部分原始码内容，而释出一个新的版本，就是次版本啦！以上面为例，就是 1 啰！

  • 释出版本次数：
    通常就是编译的次数啦！那么为何需要重复的编译呢？这是由于同一版的软体中，可能由于有某些 bug 或者是安全上的顾虑，所以必须要进行小幅度的 patch 或重设一些编译参数。 设定完成之后重新编译并打包成 RPM 档案！因此就有不同的打包数出现了！

  • 操作硬体平台：
    这是个很好玩的地方，由于 RPM 可以适用在不同的操作平台上，但是不同的平台设定的参数还是有所差异性！ 并且，我们可以针对比较高阶的 CPU 来进行最佳化参数的设定，这样才能够使用高阶 CPU 所带来的硬体加速功能。 所以就有所谓的 i386, i586, i686, x86_64 与 noarch 等的档案名称出现了！

    平台名称 | 适合平台说明
    i386 | 几乎适用于所有的 x86 平台，不论是旧的 pentum 或者是新的 Intel Core 2 与 K8 系列的 CPU 等等，都可以正常的工作！那个 i 指的是 Intel 相容的 CPU 的意思，至于 386 不用说，就是 CPU 的等级啦！
    i586 | 就是针对 586 等级的电脑进行最佳化编译。那是哪些 CPU 呢？包括 pentum 第一代 MMX CPU， AMD 的 K5, K6 系列 CPU (socket 7 插脚) 等等的 CPU 都算是这个等级；
    i686 | 在 pentun II 以后的 Intel 系列 CPU ，及 K7 以后等级的 CPU 都属于这个 686 等级！ 由于目前市面上几乎仅剩 P-II 以后等级的硬体平台，因此很多 distributions 都直接释出这种等级的 RPM 档案。
    x86_64 | 针对 64 位元的 CPU 进行最佳化编译设定，包括 Intel 的 Core 2 以上等级 CPU ，以及 AMD 的 Athlon64 以后等级的 CPU ，都属于这一类型的硬体平台。
    noarch | 就是没有任何硬体等级上的限制。一般来说，这种类型的 RPM 档案，里面应该没有 binary program 存在， 较常出现的就是属于 shell script 方面的软体。

    受惠于目前 x86 系统的支援方面，新的 CPU 都能够执行旧型 CPU 所支援的软体，也就是说硬体方面都可以向下相容的， 因此最低等级的 i386 软体可以安装在所有的 x86 硬体平台上面，不论是 32 位元还是 64 位元。但是反过来说就不行了。举例来说，目前硬体大多是 64 位元的等级，因此你可以在该硬体上面安装 x86_64 或 i386 等级的 RPM 软体。但在你的旧型主机，例如 P-III/P-4 32 位元机器上面，就不能够安装 x86_64 的软体！

根据上面的说明，其实我们只要选择 i386 版本来安装在你的 x86 硬体上面就肯定没问题。但是如果强调效能的话， 还是选择搭配你的硬体的 RPM 档案吧！毕竟该软体才有针对你的 CPU 硬体平台进行过参数最佳化的编译嘛！

小标题的图示 RPM 的优点

由于 RPM 是透过预先编译并打包成为 RPM 档案格式后，再加以安装的一种方式，并且还能够进行资料库的记载。 所以 RPM 有以下的优点：

  • RPM 内含已经编译过的程式与设定档等资料，可以让使用者免除重新编译的困扰；
  • RPM 在被安装之前，会先检查系统的硬碟容量、作业系统版本等，可避免档案被错误安装；
  • RPM 档案本身提供软体版本资讯、相依属性软体名称、软体用途说明、软体所含档案等资讯，便于了解软体；
  • RPM 管理的方式使用资料库记录 RPM 档案的相关参数，便于升级、移除、查询与验证。

为什么 RPM 在使用上很方便呢？我们前面提过， RPM 这个软体管理员所处理的软体，是由软体提供者在特定的 Linux 作业平台上面将该软体编译完成并且打包好。那使用者只要拿到这个打包好的软体， 然后将里头的档案放置到应该要摆放的目录，不就完成安装啰？对啦！就是这样！

但是有没有想过，我们在前一章里面提过的，有些软体是有相关性的，例如要安装网路卡驱动程式，就得要有 kernel source 与 gcc 及 make 等软体。那么我们的 RPM 软体是否一定可以安装完成呢？如果该软体安装之后，却找不到他相关的前驱软体， 那不是挺麻烦的吗？因为安装好的软体也无法使用啊！

为了解决这种具有相关性的软体之间的问题 (就是所谓的软体相依属性)，RPM 就在提供打包的软体时，同时加入一些讯息登录的功能，这些讯息包括软体的版本、 打包软体者、相依属性的其他软体、本软体的功能说明、本软体的所有档案记录等等，然后在 Linux 系统上面亦建立一个 RPM 软体资料库，如此一来，当你要安装某个以 RPM 型态提供的软体时，在安装的过程中， RPM 会去检验一下资料库里面是否已经存在相关的软体了， 如果资料库显示不存在，那么这个 RPM 档案‘预设’就不能安装。呵呵！没有错，这个就是 RPM 类型的档案最为人所诟病的‘软体的属性相依’问题啦！

小标题的图示 RPM 属性相依的克服方式： YUM 线上升级

为了重复利用既有的软体功能，因此很多软体都会以函式库的方式释出部分功能，以方便其他软体的呼叫应用， 例如 PAM 模组的验证功能。此外，为了节省使用者的资料量，目前的 distributions 在释出软体时， 都会将软体的内容分为一般使用与开发使用 (development) 两大类。所以你才会常常看到有类似 pam-x.x.rpm 与 pam-devel-x.x.rpm 之类的档名啊！而预设情况下，大部分的 software-devel-x.x.rpm 都不会安装，因为终端用户大部分不会去开发软体嘛！

因为有上述的现象，因此 RPM 软体档案就会有所谓的属性相依的问题产生 (其实所有的软体管理几乎都有这方面的情况存在)。 那有没有办法解决啊？前面不是谈到 RPM 软体档案内部会记录相依属性的资料吗？那想一想，要是我将这些相依属性的软体先列表， 在有要安装软体需求的时候，先到这个列表去找，同时与系统内已安装的软体相比较，没安装到的相依软体就一口气同时安装起来， 那不就解决了相依属性的问题了吗？有没有这种机制啊？有啊！那就是 YUM 机制的由来！

CentOS 先将释出的软体放置到 YUM 伺服器内，然后分析这些软体的相依属性问题，将软体内的记录资讯写下来 (header)。 然后再将这些资讯分析后记录成软体相关性的清单列表。这些列表资料与软体所在的位置可以称呼为容器 (repository)。 当用户端有软体安装的需求时，用户端主机会主动的向网路上面的 yum 伺服器的容器网址下载清单列表， 然后透过清单列表的资料与本机 RPM 资料库已存在的软体资料相比较，就能够一口气安装所有需要的具有相依属性的软体了。 整个流程可以简单的如下图说明：

YUM 使用的流程示意图
图 1.5.1、YUM 使用的流程示意图

当用户端有升级、安装的需求时， yum 会向容器要求清单的更新，等到清单更新到本机的 /var/cache/yum 里面后， 等一下更新时就会用这个本机清单与本机的 RPM 资料库进行比较，这样就知道该下载什么软体。接下来 yum 会跑到容器伺服器 (yum server) 下载所需要的软体，然后再透过 RPM 的机制开始安装软体啦！这就是整个流程！ 谈到最后，还是需要动到 RPM 的啦！所以下个小节就让我们来谈谈 RPM 这咚咚吧！

Tips:
为什么要做出‘容器’呢？由于 yum 伺服器提供的 RPM 档案内容可能有所差异，举例来说，原厂释出的资料有 (1)原版资料； (2)更新资料 (update)； (3)特殊资料 (例如第三方协力软体，或某些特殊功能的软体)。 这些软体档案基本上不会放置到一起，那如何分辨这些软体功能呢？就用‘容器’的概念来处理的啦！ 不同的‘容器’网址，可以放置不同的软体功能之意！ 		鸟哥的图示
大标题的图示 RPM 软体管理程式： rpm

RPM 的使用其实不难，只要使用 rpm 这个指令即可！鸟哥最喜欢的就是 rpm 指令的查询功能了，可以让我很轻易的就知道某个系统有没有安装鸟哥要的软体呢！此外， 我们最好还是得要知道一下，到底 RPM 类型的档案他们是将软体的相关档案放置在哪里呢？还有，我们说的那个 RPM 的资料库又是放置在哪里呢？

小标题的图示 RPM 预设安装的路径

一般来说，RPM 类型的档案在安装的时候，会先去读取档案内记载的设定参数内容，然后将该资料用来比对 Linux 系统的环境，以找出是否有属性相依的软体尚未安装的问题。例如 Openssh 这个连线软体需要透过 Openssl 这个加密软体的帮忙，所以得先安装 openssl 才能装 openssh 的意思。那你的环境如果没有 openssl ， 你就无法安装 openssh 的意思啦。

若环境检查合格了，那么 RPM 档案就开始被安装到你的 Linux 系统上。安装完毕后，该软体相关的资讯就会被写入 /var/lib/rpm/ 目录下的资料库档案中了。 上面这个目录内的资料很重要喔！因为未来如果我们有任何软体升级的需求，版本之间的比较就是来自于这个资料库， 而如果你想要查询系统已经安装的软体，也是从这里查询的！同时，目前的 RPM 也提供数位签章资讯， 这些数位签章也是在这个目录内记录的呢！所以说，这个目录得要注意不要被删除了啊！

那么软体内的档案到底是放置到哪里去啊？当然与档案系统有关对吧！我们在第六章的目录配置谈过每个目录的意义， 这里再次的强调啰：

/etc | 一些设定档放置的目录，例如 /etc/crontab
/usr/bin | 一些可执行档案
/usr/lib | 一些程式使用的动态函式库
/usr/share/doc | 一些基本的软体使用手册与说明档
/usr/share/man | 一些 man page 档案

好了，底下我们就来针对每个 RPM 的相关指令来进行说明啰！

小标题的图示 RPM 安装 (install)

因为安装软体是 root 的工作，因此你得要是 root 的身份才能够操作 rpm 这指令的。 用 rpm 来安装很简单啦！假设我要安装一个档名为 rp-pppoe-3.5-32.1.i386.rpm 的档案，那么我可以这样：

[root@www ~]# rpm -i rp-pppoe-3.5-32.1.i386.rpm

不过，这样的参数其实无法显示安装的进度，所以，通常我们会这样下达安装指令：

[root@www ~]# rpm -ivh package_name
选项与参数：
-i ：install 的意思
-v ：察看更细部的安装资讯画面
-h ：以安装资讯列显示安装进度

范例一：安装 rp-pppoe-3.5-32.1.i386.rpm
[root@www ~]# rpm -ivh rp-pppoe-3.5-32.1.i386.rpm
Preparing...     ####################################### [100%]
   1:rp-pppoe    ####################################### [100%]

范例二、一口气安装两个以上的软体时：
[root@www ~]# rpm -ivh a.i386.rpm b.i386.rpm *.rpm
# 后面直接接上许多的软体档案！

范例三、直接由网路上面的某个档案安装，以网址来安装：
[root@www ~]# rpm -ivh http://website.name/path/pkgname.rpm

另外，如果我们在安装的过程当中发现问题，或者已经知道会发生的问题， 而还是‘执意’要安装这个软体时，可以使用如下的参数‘强制’安装上去：

rpm 安装时常用的选项与参数说明
可下达的选项 | 代表意义
--nodeps | 使用时机：当发生软体属性相依问题而无法安装，但你执意安装时 危险性： 软体会有相依性的原因是因为彼此会使用到对方的机制或功能，如果强制安装而不考虑软体的属性相依， 则可能会造成该软体的无法正常使用！
--replacefiles | 使用时机： 如果在安装的过程当中出现了‘某个档案已经被安装在你的系统上面’的资讯，又或许出现版本不合的讯息 (confilcting files) 时，可以使用这个参数来直接覆盖档案。 危险性： 覆盖的动作是无法复原的！所以，你必须要很清楚的知道被覆盖的档案是真的可以被覆盖喔！否则会欲哭无泪！
--replacepkgs | 使用时机： 重新安装某个已经安装过的软体！如果你要安装一堆 RPM 软体档案时，可以使用 rpm -ivh *.rpm ，但若某些软体已经安装过了， 此时系统会出现‘某软体已安装’的资讯，导致无法继续安装。此时可使用这个选项来重复安装喔！
--force | 使用时机：这个参数其实就是 --replacefiles 与 --replacepkgs 的综合体！
--test | 使用时机： 想要测试一下该软体是否可以被安装到使用者的 Linux 环境当中，可找出是否有属性相依的问题。范例为： rpm -ivh pkgname.i386.rpm --test
--justdb | 使用时机： 由于 RPM 资料库破损或者是某些缘故产生错误时，可使用这个选项来更新软体在资料库内的相关资讯。
--nosignature | 使用时机： 想要略过数位签章的检查时，可以使用这个选项。
--prefix 新路径 | 使用时机： 要将软体安装到其他非正规目录时。举例来说，你想要将某软体安装到 /usr/local 而非正规的 /bin, /etc 等目录， 就可以使用‘ --prefix /usr/local ’来处理了。
--noscripts | 使用时机：不想让该软体在安装过程中自行执行某些系统指令。 说明： RPM 的优点除了可以将档案放置到定位之外，还可以自动执行一些前置作业的指令，例如资料库的初始化。 如果你不想要让 RPM 帮你自动执行这一类型的指令，就加上他吧！

一般来说，rpm 的安装选项与参数大约就是这些了。通常鸟哥建议直接使用 -ivh 就好了， 如果安装的过程中发现问题，一个一个去将问题找出来，尽量不要使用‘ 暴力安装法 ’，就是透过 --force 去强制安装！ 因为可能会发生很多不可预期的问题呢！除非你很清楚的知道使用上面的参数后，安装的结果是你预期的！

例题：
在没有网路的前提下，你想要安装一个名为 pam-devel 的软体，你手边只有原版光碟，该如何是好？
答：
你可以透过挂载原版光碟来进行资料的查询与安装。请将原版光碟放入光碟机，底下我们尝试将光碟挂载到 /media 当中， 并据以处理软体的下载啰：
  • 挂载光碟，使用： mount /dev/cdrom /media
  • 找出档案的实际路径：find /media -name 'pam-devel*'
  • 测试此软体是否具有相依性： rpm -ivh pam-devel... --test
  • 直接安装： rpm -ivh pam-devel...
  • 卸载光碟： umount /dev/cdrom
在鸟哥的系统中，刚好这个软体并没有属性相依的问题，因此最后一个步骤可以顺利的进行下去呢！

小标题的图示 RPM 升级与更新 (upgrade/freshen)

使用 RPM 来升级真是太简单了！就以 -Uvh 或 -Fvh 来升级即可，而 -Uvh 与 -Fvh 可以用的选项与参数，跟 install 是一样的。不过， -U 与 -F 的意义还是不太一样的，基本的差别是这样的：

-Uvh | 后面接的软体即使没有安装过，则系统将予以直接安装； 若后面接的软体有安装过旧版，则系统自动更新至新版；
-Fvh | 如果后面接的软体并未安装到你的 Linux 系统上，则该软体不会被安装；亦即只有已安装至你 Linux 系统内的软体会被‘升级’！

由上面的说明来看，如果你想要大量的升级系统旧版本的软体时，使用 -Fvh 则是比较好的作法，因为没有安装的软体才不会被不小心安装进系统中。但是需要注意的是，如果你使用的是 -Fvh ，偏偏你的机器上尚无这一个软体，那么很抱歉，该软体并不会被安装在你的 Linux 主机上面，所以请重新以 ivh 来安装吧！

通常有的朋友在进行整个作业系统的旧版软体修补时，喜欢这么进行：

  1. 先到各发展商的 errata 网站或者是国内的 FTP 映像站捉下来最新的 RPM 档案；
  2. 使用 -Fvh 来将你的系统内曾安装过的软体进行修补与升级！(真是方便呀！)

所以，在不晓得 yum 功能的情况下，你依旧可以到 CentOS 的映设站台下载 updates 资料，然后利用上述的方法来一口气升级！ 当然啰，升级也是可以利用 --nodeps/--force 等等的参数啦！

小标题的图示 RPM 查询 (query)

RPM 在查询的时候，其实查询的地方是在 /var/lib/rpm/ 这个目录下的资料库档案啦！另外， RPM 也可以查询未安装的 RPM 档案内的资讯喔！那如何去查询呢？ 我们先来谈谈可用的选项有哪些？

[root@www ~]# rpm -qa                              <==已安装软体
[root@www ~]# rpm -q[licdR] 已安装的软体名称       <==已安装软体
[root@www ~]# rpm -qf 存在于系统上面的某个档名     <==已安装软体
[root@www ~]# rpm -qp[licdR] 未安装的某个档案名称  <==查阅RPM档案
选项与参数：
查询已安装软体的资讯：
-q  ：仅查询，后面接的软体名称是否有安装；
-qa ：列出所有的，已经安装在本机 Linux 系统上面的所有软体名称；
-qi ：列出该软体的详细资讯 (information)，包含开发商、版本与说明等；
-ql ：列出该软体所有的档案与目录所在完整档名 (list)；
-qc ：列出该软体的所有设定档 (找出在 /etc/ 底下的档名而已)
-qd ：列出该软体的所有说明档 (找出与 man 有关的档案而已)
-qR ：列出与该软体有关的相依软体所含的档案 (Required 的意思)
-qf ：由后面接的档案名称，找出该档案属于哪一个已安装的软体；
查询某个 RPM 档案内含有的资讯：
-qp[icdlR]：注意 -qp 后面接的所有参数以上面的说明一致。但用途仅在于找出
        某个 RPM 档案内的资讯，而非已安装的软体资讯！注意！

在查询的部分，所有的参数之前都需要加上 -q 才是所谓的查询！查询主要分为两部分， 一个是查已安装到系统上面的的软体资讯，这部份的资讯都是由 /var/lib/rpm/ 所提供。另一个则是查某个 rpm 档案内容， 等于是由 RPM 档案内找出一些要写入资料库内的资讯就是了，这部份就得要使用 -qp (p 是 package 的意思)。 那就来看看几个简单的范例吧！

范例一：找出你的 Linux 是否有安装 logrotate 这个软体？
[root@www ~]# rpm -q logrotate
logrotate-3.7.4-8
[root@www ~]# rpm -q logrotating
package logrotating is not installed
# 注意到，系统会去找是否有安装后面接的软体名称。注意，
# 不必要加上版本喔！至于显示的结果，一看就知道有没有安装啦！

范例二：列出上题当中，属于该软体所提供的所有目录与档案：
[root@www ~]# rpm -ql logrotate
/etc/cron.daily/logrotate
/etc/logrotate.conf
....(以下省略)....
# 可以看出该软体到底提供了多少的档案与目录，也可以追踪软体的资料。

范例三：列出 logrotate 这个软体的相关说明资料：
[root@www ~]# rpm -qi logrotate
Name        : logrotate             Relocations: (not relocatable)
Version     : 3.7.4                      Vendor: CentOS
Release     : 8                      Build Date: Sun 02 Dec 2007 08:38:06 AM CST
Install Date: Sat 09 May 2009 11:59:05 PM CST    Build Host: builder6
Group       : System Environment/Base  Source RPM: logrotate-3.7.4-8.src.rpm
Size        : 53618                     License: GPL
Signature   : DSA/SHA1, Sun 02 Dec 2007 09:10:01 AM CST, Key ID a8a447dce8562897
Summary     : Rotates, compresses, removes and mails system log files.
Description :
The logrotate utility is designed to simplify the administration of
log files on a system which generates a lot of log files.  Logrotate
allows for the automatic rotation compression, removal and mailing of
log files.  Logrotate can be set to handle a log file daily, weekly,
monthly or when the log file gets to a certain size.  Normally,
logrotate runs as a daily cron job.

Install the logrotate package if you need a utility to deal with the
log files on your system.
# 列出该软体的 information (资讯)，里面的资讯可多着呢，包括了软体名称、
# 版本、开发商、SRPM档案名称、打包次数、简单说明资讯、软体打包者、
# 安装日期等等！如果想要详细的知道该软体的资料，用这个参数来了解一下

范例四：分别仅找出 logrotate 的设定档与说明档
[root@www ~]# rpm -qc logrotate
[root@www ~]# rpm -qd logrotate

范例五：若要成功安装 logrotate ，他还需要什么档案的帮忙？
[root@www ~]# rpm -qR logrotate
/bin/sh
config(logrotate) = 3.7.4-8
libc.so.6
....(以下省略)....
# 由这里看起来，呵呵～还需要很多档案的支援才行喔！

范例六：由上面的范例五，找出 /bin/sh 是那个软体提供的？
[root@www ~]# rpm -qf /bin/sh
bash-3.2-21.el5
# 这个参数后面接的可是‘档案’呐！不像前面都是接软体喔！
# 这个功能在查询系统的某个档案属于哪一个软体所有的。

范例七：假设我有下载一个 RPM 档案，想要知道该档案的需求档案，该如何？
[root@www ~]# rpm -qpR filename.i386.rpm
# 加上 -qpR ，找出该档案需求的资料！

常见的查询就是这些了！要特别说明的是，在查询本机上面的 RPM 软体相关资讯时， 不需要加上版本的名称，只要加上软体名称即可！因为他会由 /var/lib/rpm 这个资料库里面去查询， 所以我们可以不需要加上版本名称。但是查询某个 RPM 档案就不同了，我们必须要列出整个档案的完整档名才行～ 这一点朋友们常常会搞错。底下我们就来做几个简单的练习吧！

例题：
  1. 我想要知道我的系统当中，以 c 开头的软体有几个，如何实做？
  2. 我的 WWW 伺服器为 Apache ，我知道他使用的 RPM 软体档名为 httpd 。现在，我想要知道这个软体的所有设定档放置在何处，可以怎么作？
  3. 承上题，如果查出来的设定档案已经被我改过，但是我忘记了曾经修改过哪些地方，所以想要直接重新安装一次该软体，该如何作？
  4. 如果我误砍了某个重要档案，例如 /etc/crontab，偏偏不晓得他属于哪一个软体，该怎么办？
答：
  1. rpm -qa | grep ^c | wc -l
  2. rpm -qc httpd
  3. 假设该软体在网路上的网址为：
    http://web.site.name/path/httpd-x.x.xx.i386.rpm
    则我可以这样做：
    rpm -ivh http://web.site.name/path/httpd-x.x.xx.i386.rpm --replacepkgs
  4. 虽然已经没有这个档案了，不过没有关系，因为 RPM 有记录在 /var/lib/rpm 当中的资料库啊！所以直接下达：
    rpm -qf /etc/crontab
    就可以知道是那个软体啰！重新安装一次该软体即可！

小标题的图示 RPM 验证与数位签章 (Verify/signature)

验证 (Verify) 的功能主要在于提供系统管理员一个有用的管理机制！作用的方式是‘使用 /var/lib/rpm 底下的资料库内容来比对目前 Linux 系统的环境下的所有软体档案 ’也就是说，当你有资料不小心遗失， 或者是因为你误杀了某个软体的档案，或者是不小心不知道修改到某一个软体的档案内容， 就用这个简单的方法来验证一下原本的档案系统吧！好让你了解这一阵子到底是修改到哪些档案资料了！验证的方式很简单：

[root@www ~]# rpm -Va
[root@www ~]# rpm -V  已安装的软体名称
[root@www ~]# rpm -Vp 某个 RPM 档案的档名
[root@www ~]# rpm -Vf 在系统上面的某个档案
选项与参数：
-V  ：后面加的是软体名称，若该软体所含的档案被更动过，才会列出来；
-Va ：列出目前系统上面所有可能被更动过的档案；
-Vp ：后面加的是档案名称，列出该软体内可能被更动过的档案；
-Vf ：列出某个档案是否被更动过～

范例一：列出你的 Linux 内的 logrotate 这个软体是否被更动过？
[root@www ~]# rpm -V logrotate
# 如果没有出现任何讯息，恭喜你，该软体所提供的档案没有被更动过。
# 如果有出现任何讯息，才是有出现状况啊！

范例二：查询一下，你的 /etc/crontab 是否有被更动过？
[root@www ~]# rpm -Vf /etc/crontab
S.5....T  c /etc/crontab
# 瞧！因为有被更动过，所以会列出被更动过的资讯类型！

好了，那么我怎么知道到底我的档案被更动过的内容是什么？例如上面的范例二。呵呵！简单的说明一下吧！ 例如，我们检查一下 logrotate 这个软体：

[root@www ~]# rpm -ql logrotate
/etc/cron.daily/logrotate
/etc/logrotate.conf
/etc/logrotate.d
/usr/sbin/logrotate
/usr/share/doc/logrotate-3.7.4
/usr/share/doc/logrotate-3.7.4/CHANGES
/usr/share/man/man8/logrotate.8.gz
/var/lib/logrotate.status
# 呵呵！共有八个档案啊！请修改 /etc/logrotate.conf 内的 rotate 变成 5

[root@www ~]# rpm -V logrotate
..5....T  c /etc/logrotate.conf

你会发现在档名之前有个 c ，然后就是一堆奇怪的文字了。那个 c 代表的是 configuration ， 就是设定档的意思。至于最前面的八个资讯是：

  • S ：(file Size differs) 档案的容量大小是否被改变
  • M ：(Mode differs) 档案的类型或档案的属性 (rwx) 是否被改变？如是否可执行等参数已被改变
  • 5 ：(MD5 sum differs) MD5 这一种指纹码的内容已经不同
  • D ：(Device major/minor number mis-match) 装置的主/次代码已经改变
  • L ：(readLink(2) path mis-match) Link 路径已被改变
  • U ：(User ownership differs) 档案的所属人已被改变
  • G ：(Group ownership differs) 档案的所属群组已被改变
  • T ：(mTime differs) 档案的建立时间已被改变

所以，如果当一个设定档所有的资讯都被更动过，那么他的显示就会是：

SM5DLUGT c filename

至于那个 c 代表的是‘ Config file ’的意思，也就是档案的类型，档案类型有底下这几类：

  • c ：设定档 (config file)
  • d ：文件资料档 (documentation)
  • g ：鬼档案～通常是该档案不被某个软体所包含，较少发生！(ghost file)
  • l ：授权档案 (license file)
  • r ：读我档案 (read me)

经过验证的功能，你就可以知道那个档案被更动过。那么如果该档案的变更是‘预期中的’， 那么就没有什么大问题，但是如果该档案是‘非预期的’，那么是否被入侵了呢？呵呵！得注意注意啰！ 一般来说，设定档 (configure) 被更动过是很正常的，万一你的 binary program 被更动过呢？ 那就得要特别特别小心啊！

Tips:
虽说家丑不可外扬，不过有件事情还是跟大家分享一下的好。鸟哥之前的主机曾经由于安装一套软体，导致被攻击成为跳板。 会发现的原因是系统中只要出现 *.patch 的副档名时，使用 ls -l 就是显示不出来该档名 (该档名确实存在)。 找了好久，用了好多工具都找不出问题，最终利用 rpm -Va 找出来，原来好多 binary program 被更动过，连 init 都被恶搞！此时，赶紧重新安装 Linux 并移除那套软体，之后就比较正常了。所以说，这个 rpm -Va 是个好功能喔！ 		鸟哥的图示
  • 数位签章 (digital signature)

谈完了软体的验证后，不知道你有没有发现一个问题，那就是，验证只能验证软体内的资讯与 /var/lib/rpm/ 里面的资料库资讯而已，如果该软体档案所提供的资料本身就有问题，那你使用验证的手段也无法确定该软体的正确性啊！ 那如何解决呢？在 Tarball 与档案的验证方面，我们可以使用前一章谈到的 md5 指纹码来检查， 不过，连指纹码也可能会被窜改的嘛！那怎办？没关系，我们可以透过数位签章来检验软体的来源的！

就像你自己的签名一样，我们的软体开发商原厂所推出的软体也会有一个厂商自己的签章系统！ 只是这个签章被数位化了而已。厂商可以数位签章系统产生一个专属于该软体的签章，并将该签章的公钥 (public key) 释出。 当你要安装一个 RPM 档案时：

  1. 首先你必须要先安装原厂释出的公钥档案；
  2. 实际安装原厂的 RPM 软体时， rpm 指令会去读取 RPM 档案的签章资讯，与本机系统内的签章资讯比对，
  3. 若签章相同则予以安装，若找不到相关的签章资讯时，则给予警告并且停止安装喔。

我们 CentOS 使用的数位签章系统为 GNU 计划的 GnuPG (GNU Privacy Guard, GPG)(注1)。 GPG 可以透过杂凑运算，算出独一无二的专属金钥系统或者是数位签章系统，有兴趣的朋友可以参考文末的延伸阅读， 去了解一下 GPG 加密的机制喔！这里我们仅简单的说明数位签章在 RPM 档案上的应用而已。 而根据上面的说明，我们也会知道首先必须要安装原厂释出的 GPG 数位签章的公钥档案啊！CentOS 的数位签章位于：

[root@www ~]# ll /etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-5
-rw-r--r-- 1 root root 1504  6月 19  2008 /etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-5
[root@www ~]# cat /etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-5
-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: GnuPG v1.2.6 (GNU/Linux)

mQGiBEWfB6MRBACrnYW6yKMT+MwJlCIhoyTxGf3mAxmnAiDEy6HcYN8rivssVTJk
....(中间省略)....
-----END PGP PUBLIC KEY BLOCK-----

从上面的输出，你会知道该数位签章码其实仅是一个乱数而已，这个乱数对于数位签章有意义而已， 我们看不懂啦！那么这个档案如何安装呢？透过底下的方式来安装即可喔！

[root@www ~]# rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-5

由于不同版本 GPG 金钥档案放置的位置可能不同，不过档名大多是以 GPG-KEY 来说明的， 因此你可以简单的使用 locate 或 find 来找寻，如以下的方式来搜寻即可：

[root@www ~]# locate GPG-KEY
[root@www ~]# find /etc -name '*GPG-KEY*'

那安装完成之后，这个金钥的内容会以什么方式呈现呢？基本上都是使用 pubkey 作为软体的名称的！ 那我们先列出金钥软体名称后，再以 -qi 的方式来查询看看该软体的资讯为何：

[root@www ~]# rpm -qa | grep pubkey
gpg-pubkey-e8562897-459f07a4
[root@www ~]# rpm -qi gpg-pubkey-e8562897-459f07a4
Name        : gpg-pubkey        Relocations: (not relocatable)
Version     : e8562897               Vendor: (none)
Release     : 459f07a4           Build Date: Wed 27 May 2009 10:07:26 PM CST
Install Date: Wed 27 May 2009 10:07:26 PM CST   Build Host: localhost
Group       : Public Keys        Source RPM: (none)
Size        : 0                     License: pubkey
Signature   : (none)
Summary     : gpg(CentOS-5 Key <centos-5-key@centos.org>)
Description :
-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: rpm-4.4.2 (beecrypt-4.1.2)
....(底下省略)....

重点就是最后面出现的那一串乱码啦！那可是作为数位签章非常重要的一环哩！ 如果你忘记加上数位签章，很可能很多原版软体就不能让你安装啰～除非你利用 rpm 时选择略过数位签章的选项。

小标题的图示 RPM 反安装与重建资料库 (erase/rebuilddb)

反安装就是将软体解除安装啦！要注意的是，‘解安装的过程一定要由最上层往下解除’，以 rp-pppoe 为例，这一个软体主要是依据 ppp 这个软体来安装的，所以当你要解除 ppp 的时候，就必须要先解除 rp-pppoe 才行！否则就会发生结构上的问题啦！这个可以由建筑物来说明， 如果你要拆除五、六楼，那么当然要由六楼拆起，否则先拆的是第五楼时，那么上面的楼层难道会悬空？

移除的选项很简单，就透过 -e 即可移除。不过，很常发生软体属性相依导致无法移除某些软体的问题！ 我们以底下的例子来说明：

# 1. 找出与 pam 有关的软体名称，并尝试移除 pam 这个软体：
[root@www ~]# rpm -qa | grep pam
pam-devel-0.99.6.2-3.27.el5
pam_passwdqc-1.0.2-1.2.2
pam_pkcs11-0.5.3-23
pam_smb-1.1.7-7.2.1
pam-0.99.6.2-3.27.el5
pam_ccreds-3-5
pam_krb5-2.2.14-1
[root@www ~]# rpm -e pam
error: Failed dependencies:  <==这里提到的是相依性的问题
        libpam.so.0 is needed by (installed) coreutils-5.97-14.el5.i386
        libpam.so.0 is needed by (installed) libuser-0.54.7-2.el5.5.i386
....(以下省略)....

# 2. 若仅移除 pam-devel 这个之前范例安装上的软体呢？
[root@www ~]# rpm -e pam-devel  <==不会出现任何讯息！
[root@www ~]# rpm -q pam-devel
package pam-devel is not installed

从范例一我们知道 pam 所提供的函式库是让非常多其他软体使用的，因此你不能移除 pam ，除非将其他相依软体一口气也全部移除！你当然也能加 --nodeps 来强制移除， 不过，如此一来所有会用到 pam 函式库的软体，都将成为无法运作的程式，我想，你的主机也只好准备停机休假了吧！ 至于范例二中，由于 pam-devel 是依附于 pam 的开发工具，你可以单独安装与单独移除啦！

由于 RPM 档案常常会安装/移除/升级等，某些动作或许可能会导致 RPM 资料库 /var/lib/rpm/ 内的档案破损。果真如此的话，那你该如何是好？别担心，我们可以使用 --rebuilddb 这个选项来重建一下资料库喔！ 作法如下：

[root@www ~]# rpm --rebuilddb   <==重建资料库
大标题的图示 SRPM 的使用 ： rpmbuild

谈完了 RPM 类型的软体之后，再来我们谈一谈包含了 Source code 的 SRPM 该如何使用呢？假如今天我们由网路上面下载了一个 SRPM 的档案，该如何安装他？又，如果我想要修改这个 SRPM 里面原始码的相关设定值，又该如何订正与重新编译呢？ 此外，最需要注意的是，新版的 rpm 已经将 RPM 与 SRPM 的指令分开了，SRPM 使用的是 rpmbuild 这个指令，而不是 rpm 喔！如果你是 Red Hat 7.3 以前的用户，那么请使用 rpm 来替代 rpmbuild 啦！

小标题的图示 利用预设值安装 SRPM 档案 (--rebuid/--recompile)

假设我下载了一个 SRPM 的档案，又不想要修订这个档案内的原始码与相关的设定值， 那么我可以直接编译并安装吗？当然可以！利用 rpmbuild 配合选项即可。选项主要有底下两个：

--rebuild | 这个选项会将后面的 SRPM 进行‘编译’与‘打包’的动作，最后会产生 RPM 的档案，但是产生的 RPM 档案并没有安装到系统上。当你使用 --rebuild 的时候，最后通常会发现一行字体： Wrote: /usr/src/redhat/RPMS/i386/pkgname.i386.rpm 这个就是编译完成的 RPM 档案啰！这个档案就可以用来安装啦！安装的时候请加绝对路径来安装即可！
--recompile | 这个动作会直接的‘编译’‘打包’并且‘安装’啰！请注意， rebuild 仅‘编译并打包’而已，而 recompile 不但进行编译跟打包，还同时进行‘安装’了！

不过，要注意的是，这两个选项都没有修改过 SRPM 内的设定值，仅是透过再次编译来产生 RPM 可安装软体档案而已。 一般来说，如果编译的动作顺利的话，那么编译过程所产生的中间暂存档都会被自动删除，如果发生任何错误， 则该中间档案会被保留在系统上，等待使用者的除错动作！那么，该如何除错呢？如果想要自行除错， 或者是想要修改 SRPM 内的设定值时，就得要知道利用 SRPM 的时候，系统会动用到哪些重要的目录了！ 底下我们就来谈一谈当处理 SRPM 时，系统会使用到的目录。

小标题的图示 SRPM 使用的路径与需要的软体

SRPM 既然含有 source code ，那么其中必定有设定档啰，所以首先我们必需要知道，这个 SRPM 在进行编译的时候会使用到哪些目录呢？这样一来才能够来修改嘛！你可以到你的 /usr/src 这个目录里面去查看一下，通常每个 distribution 提供的目录都不太相同，以 CentOS 5.x 为例，他是以 /usr/src/redhat/ 为工作目录， Openlinux 则是以 /usr/src/openlinux 为工作目录！无论如何，反正就是在 /usr/src 这个目录下就对了！好了，既然我们是 CentOS ， 请到 /usr/src/redhat 里头去看一看呦：

/usr/src/redhat/SPECS | 这个目录当中放置的是该软体的设定档，例如这个软体的资讯参数、设定项目等等都放置在这里；
/usr/src/redhat/SOURCES | 这个目录当中放置的是该软体的原始档 (*.tar.gz 的档案) 以及 config 这个设定档；
/usr/src/redhat/BUILD | 在编译的过程中，有些暂存的资料都会放置在这个目录当中；
/usr/src/redhat/RPMS | 经过编译之后，并且顺利的编译成功之后，将打包完成的档案放置在这个目录当中。里头有包含了 i386, i586, i686, noarch.... 等等的次目录。
/usr/src/redhat/SRPMS | 与 RPMS 内相似的，这里放置的就是 SRPM 封装的档案啰！有时候你想要将你的软体用 SRPM 的方式释出时， 你的 SRPM 档案就会放置在这个目录中了。

此外，在编译的过程当中，可能会发生不明的错误，或者是设定的错误，这个时候就会在 /tmp 底下产生一个相对应的错误档，你可以根据该错误档进行除错的工作呢！ 等到所有的问题都解决之后，也编译成功了，那么刚刚解压缩之后的档案，就是在 /usr/src/redhat/SPECS, SOURCES, BUILD 等等的档案都会被杀掉，而只剩下放置在 /usr/src/redhat/RPMS 底下的档案了！

由于 SRPM 需要重新编译，而编译的过程当中，我们至少需要有 make 与其相关的程式，及 gcc, c, c++ 等其他的编译用的程式语言来进行编译，更多说明请参考第二十二章原始码所需基础软体吧。 所以，如果你在安装的过程当中没有选取软体开发工具之类的软体， 呵呵！得重新拿出你的光碟，然后再安装喔！哈哈！只是得要克服一大堆的属性相依的问题就是了～ 这问题待会儿可以使用 yum 来处理，你当然也可以先使用‘ yum groupinstall "Development Tools" ’来安装开发软体。 鸟哥这里假设你已经安装了该软体群组啰。

例题：
尝试使用 --rebuild 选项制作出一个 RPM 软体档案，可以到国家高速网路中心下载 rp-pppoe 这个 SRPM 软体档案， 你可以到 http://ftp.twaren.net/Linux/CentOS/5/os/SRPMS/ 找到这个软体来下载。 鸟哥这里使用 CentOS 5.3 的 rp-pppoe-3.5-32.1.src.rpm 为例喔。
答：
假设你已经将 rp-pppoe 软体下载到 /root 底下，那接下来可以简单的使用底下的方式来重新编译：
[root@www ~]# rpmbuild --rebuild rp-pppoe-3.5-32.1.src.rpm
正在安装 rp-pppoe-3.5-32.1.src.rpm
警告：使用者 mockbuild 不存在 - 现使用 root 代替
....(中间省略)....
已写入：/usr/src/redhat/RPMS/i386/rp-pppoe-3.5-32.1.i386.rpm
已写入：/usr/src/redhat/RPMS/i386/rp-pppoe-debuginfo-3.5-32.1.i386.rpm
正在执行 (%clean)：/bin/sh -e /var/tmp/rpm-tmp.69789
+ umask 022
+ cd /usr/src/redhat/BUILD
+ cd rp-pppoe-3.5
+ rm -rf /var/tmp/rp-pppoe-3.5-32.1-root
+ exit 0
正在执行 (--clean)：/bin/sh -e /var/tmp/rpm-tmp.69789
+ umask 022
+ cd /usr/src/redhat/BUILD
+ rm -rf rp-pppoe-3.5
+ exit 0

[root@www ~]# ll /usr/src/redhat/RPMS/i386/
-rw-r--r-- 1 root root 105443  6月 27 02:51 rp-pppoe-3.5-32.1.i386.rpm
-rw-r--r-- 1 root root  18756  6月 27 02:51 rp-pppoe-debuginfo-3.5-32.1.i386.rpm
其实整个过程与 Tarball 的方式差不多，也是编译后变成 binary program，接着再以 RPM 的机制封装起来啦。 重点在上面特殊字体的部分，记得要察看一下喔！若一切正常，则会看到 exit 0 的字样，且会主动的删除 (rm) 很多中间暂存档哩。

小标题的图示 设定档的主要内容 (*.spec)

除了使用 SRPM 内预设的参数来进行编译之外，我们还可以修改这些参数后再重新编译喔！那该如何处理呢？ 首先我们必须要将 SRPM 内的档案安置到 /usr/src/redhat/ 内的相关目录，然后再去修改设定档即可啊！ 我们就拿刚刚上头那个 rp-pppoe 来说明好了，假设我们已经将该档案放置到 /root 中啦，然后：

[root@www ~]# rpm -i rp-pppoe-3.5-32.1.src.rpm
# 过程不会显示任何东西，他只会将 SRPM 的档案解开后，放置到 /usr/src/redhat/

[root@www ~]# find /usr/src/redhat/ -type f
/usr/src/redhat/SOURCES/rp-pppoe-3.5-firewall.patch  <==补丁档
/usr/src/redhat/SOURCES/adsl-stop                    <==CentOS 提供的脚本
/usr/src/redhat/SOURCES/rp-pppoe-3.5.tar.gz          <==原始码啦！
/usr/src/redhat/SOURCES/rp-pppoe-3.5-buildroot.patch <==补丁档
/usr/src/redhat/SOURCES/adsl-start                   <==CentOS 提供的脚本
/usr/src/redhat/SOURCES/adsl-connect
/usr/src/redhat/SOURCES/adsl-setup
/usr/src/redhat/SOURCES/adsl-status
/usr/src/redhat/SOURCES/rp-pppoe-3.4-redhat.patch    <==补丁档
/usr/src/redhat/SPECS/rp-pppoe.spec                  <==重要设定档！
# 主要含有原始码与一个重要的设定档啊！ rp-pppoe.spec ！

好了，来看看我们的设定参数档，亦即是在 /usr/src/redhat/SPECS 内的 *.spec 档案啰！

[root@www ~]# cd /usr/src/redhat/SPECS
[root@www SPECS]# vi rp-pppoe.spec
# 1. 首先，这个部分在介绍整个软体的基本相关资讯！不论是版本还是释出次数等。
Summary: A PPP over Ethernet client (for xDSL support).
Name: rp-pppoe
Version: 3.5
Release: 32.1
License: GPL
Group: System Environment/Daemons
Url: http://www.roaringpenguin.com/pppoe/
Source: http://www.roaringpenguin.com/rp-pppoe-%{version}.tar.gz
Source1: adsl-connect
Source2: adsl-setup
....(中间省略)....

# 2. 这部分则是在设定相依属性需求的地方！
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root

Prereq: /sbin/chkconfig  <==需要的前驱程式有哪些！
Prereq: /sbin/service
Prereq: fileutils

Requires: ppp >= 2.4.2         <==需要的软体又有哪些！
Requires: initscripts >= 5.92
Requires: iproute >= 2.6

BuildRequires: libtool   <==还需要哪些工具软体？
BuildRequires: autoconf
BuildRequires: automake

%description             <==此软体的描述啦！
PPPoE (Point-to-Point Protocol over Ethernet) is a protocol used by
many ADSL Internet Service Providers. This package contains the
Roaring Penguin PPPoE client, a user-mode program that does not
require any kernel modifications. It is fully compliant with RFC 2516,
the official PPPoE specification.

# 3. 编译前的预处理，以及编译过程当中所需要进行的指令，都写在这里
#    尤其 %build 底下的资料，几乎就是 makefile 里面的资讯啊！
%prep  <==这部份在预先 (pre) 进行处理，大致就是 patch 软体啊！
%setup -q
%patch0 -p1 -b .config
%patch1 -p1 -b .buildroot
%patch2 -p1 -b .ipchains

%build <==这部分就是在实际编译啰！
cd src
autoconf
CFLAGS="-D_GNU_SOURCE" %configure
make

install -m 0755 %{SOURCE1} scripts
install -m 0755 %{SOURCE2} scripts
install -m 0755 %{SOURCE3} scripts
install -m 0755 %{SOURCE4} scripts
install -m 0755 %{SOURCE5} scripts

%install  <==这就是安装过程！
rm -rf %{buildroot}

mkdir -p %{buildroot}/sbin
make -C src install RPM_INSTALL_ROOT=%{buildroot}
....(中间省略)....

# 4. 这里列出，这个软体释出的档案有哪些的意思！
%files   <==这个软体提供的档案有哪些？需要记录在资料库内！
%defattr(-,root,root)
%doc doc/LICENSE scripts/adsl-connect scripts/adsl-setup scripts/adsl-init
%doc scripts/adsl-start scripts/adsl-status scripts/adsl-stop
%doc configs
%config(noreplace) %{_sysconfdir}/ppp/pppoe-server-options
%config(noreplace) %{_sysconfdir}/ppp/firewall*
/sbin/*
%{_sbindir}/*
%{_mandir}/man?/*

# 5. 列出这个软体的更改历史纪录档！
%changelog
* Wed Jul 12 2006 Jesse Keating <jkeating@redhat.com> - 3.5-32.1
- rebuild
....(中间省略)....
* Wed May 31 2000 Than Ngo <than@redhat.de>
- adopted for Winston.

要注意到的是 rp-pppoe.sepc 这个档案，这是主要的将 SRPM 编译成 RPM 的设定档，他的基本规则可以这样看：

  1. 整个档案的开头以Summary为开始，这部份的设定都是最基础的说明内容；
  2. 然后每个不同的段落之间，都以%来做为开头，例如%prep与%install等；

我们来谈一谈几个常见的 SRPM 设定段落：

  • 系统整体资讯方面：

刚刚你看到的就有底下这些重要的咚咚啰：

参数 | 参数意义
Summary | 本软体的主要说明，例如上表中说明了本软体是针对 xDSL 的拨接用途啦！
Name | 本软体的软体名称 (最终会是 RPM 档案的档名构成之一)
Version | 本软体的版本 (也会是 RPM 档名的构成之一)
Release | 这个是该版本打包的次数说明 (也会是 RPM 档名的构成之一)。由于我们想要动点手脚，所以上头的档案中， 这个部分请修改为 32.2.vbird 看看
License | 这个软体的授权模式，我们是使用 GPL 啦！
Group | 这个软体的发展团体名称；
Url | 这个原始码的主要官方网站；
Source | 这个软体的来源，如果是网路上下载的软体，通常一定会有这个资讯来告诉大家这个原始档的来源！ 此外，还有来自开发商自己提供的原始档资料喔！例如上面的 adsl-start 等程式。
Patch | 就是作为补丁的 patch file 啰！
BuildRoot | 设定作为编译时，该使用哪个目录来暂存中间档案 (如编译过程的目标档案/连结档案等档)。
ExclusiveArch | 这个是说明这个软体的适合安装的硬体，通常预设为 i386，当然，你也可以调整为 i586 啦等等的！ 由于我们的系统是新的 CPU 架构，这里我们修改内容成为‘ExclusiveArch: i686’来玩玩看。
上述为必须要存在的项目，底下为可使用的额外设定值
Requires | 如果你这个软体还需要其他的软体的支援，那么这里就必需写上来，则当你制作成 RPM 之后，系统就会自动的去检查啦！这就是‘相依属性’的主要来源啰！
Prereq | 这个软体需要的前驱程式为何！这里指的是‘程式’而 Requires 指的是‘软体’！
BuildRequires | 编译过程中所需要的软体。Requires 指的是‘安装时需要检查’的，因为与实际运作有关，这个 BuildRequires 指的是‘编译时’所需要的软体，只有在 SRPM 编译成为 RPM 时才会检查的项目。
Packager | 这个软体是经由谁来打包的呢？
Vender | 发展的厂商哪；

上面几个资料通常都必需要写啦！但是如果你的软体没有相依属性的关系时，那么就可以不需要那个 Requires 啰！ 根据上面的设定，最终的档名就会是‘{Name}-{Version}-{Release}.{ExclusiveArch}.rpm’的样式， 以我们上面的设定来说，档名应该会是‘rp-pppoe-3.5-32.2.vbird.i686.rpm’的样子啰！

  • %description：

将你的软体做一个简短的说明！这个也是必需要的。还记得使用‘ rpm -qi 软体名称 ’会出现一些基础的说明吗？ 上面这些东西包括 Description 就是在显示这些重要资讯的啦！所以，这里记得要详加解释喔！

  • %prep：

pre 这个关键字原本就有‘在...之前’的意思，因此这个项目在这里指的就是‘尚未进行设定或安装之前，你要编译完成的 RPM 帮你事先做的事情’，就是 prepare 的简写啰！那么他的工作事项主要有：

  1. 进行软体的补丁 (patch) 等相关工作；
  2. 寻找软体所需要的目录是否已经存在？确认用的！
  3. 事先建立你的软体所需要的目录，或者事先需要进行的任务；
  4. 如果待安装的Linux系统内已经有安装的时候可能会被覆盖掉的档案时，那么就必需要进行备份(backup)的工作了！

在本案例中，你会发现程式会使用 patch 去进行补丁的动作啦！

  • %setup：

这个项目就是在进行类似解压缩之类的工作！这个项目一定要写喔！不然你的 tarball 原始码是无法被解压缩的哩！切记切记！

  • %build：

build 就是建立啊！所以当然啰，这个段落就是在谈怎么 make 编译成为可执行的程式啰！ 你会发现在此部分的程式码方面，就是 ./configure, make 等项目哩！

  • %install：

编译完成 (build) 之后，就是要安装啦！安装就是写在这里，也就是类似 Tarball 里面的 make install 的意思啰！

  • %clean：

编译与安装完毕后，必须要将一些暂存在 BuildRoot 内的资料删除才好， 因此这个时候这个 clean 的项目就重要啦！这有点像是 make clean 的感觉～保持系统的干爽嘛！

  • %files：

这个软体安装的档案都需要写到这里来，当然包括了‘目录’喔！所以连同目录请一起写到这个段落当中！以备查验呢！^_^ ！此外，你也可以指定每个档案的类型，包括文件档 (%doc 后面接的) 与设定档 (%config 后面接的) 等等。

  • %changelog：

这个项目主要则是在记录这个软体曾经的更新纪录啰！星号 (*) 后面应该要以时间，修改者， email 与软体版本来作为说明， 减号 (-) 后面则是你要作的详细说明啰！在这部份鸟哥就新增了两行，内容如下：

%changelog
* Wed Jul 01 2009 VBird Tsai <vbird@mail.vbird.idv.tw> - 3.5-32.2.vbird
- only rebuild this SRPM to RPM

* Wed Jul 12 2006 Jesse Keating <jkeating@redhat.com> - 3.5-32.1
....(底下省略)....

修改到这里也差不多了，您也应该要了解到这个 rp-pppoe.spec 有多么重要！我们用 rpm -q 去查询一堆资讯时， 其实都是在这里写入的！这样了解否？接下来，就让我们来了解一下如何将 SRPM 给他编译出 RPM 来吧！

小标题的图示 SRPM 的编译指令 (-ba/-bb)

要将在 /usr/src/redhat 底下的资料编译或者是单纯的打包成为 RPM 或 SRPM 时，就需要 rpmbuild 指令与相关选项的帮忙了！我们只介绍两个常用的选项给您了解一下：

[root@www ~]# rpmbuild -ba rp-pppoe.spec  <==编译并同时产生 RPM 与 SRPM 档案
[root@www ~]# rpmbuild -bb rp-pppoe.spec  <==仅编译成 RPM 档案

这个时候系统就会这样做：

  1. 先进入到 BUILD 这个目录中，亦即是： /usr/src/redhat/BUILD 这个目录；

  2. 依照 *.spec 档案内的 Name 与 Version 定义出工作的目录名称，以我们上面的例子为例，那么系统就会在 BUILD 目录中先删除 rp-pppoe-3.5 的目录，再重新建立一个 rp-pppoe-3.5 的目录，并进入该目录；

  3. 在新建的目录里面，针对 SOURCES 目录下的来源档案，也就是 *.spec 里面的 Source 设定的那个档案，以 tar 进行解压缩，以我们这个例子来说，则会在 /usr/src/redhat/BUILD/rp-pppoe-3.5 当中，将 /usr/src/redhat/SOURCES/rp-pppoe-3.5.tar.gz 进行解压缩啦！

  4. 再来开始 %build 及 %install 的设定与编译！

  5. 最后将完成打包的档案给他放置到该放置的地方去，如果你的规定的硬体是在 i386 的系统，那么最后编译成功的 *.i386.rpm档案就会被放置在 /usr/src/redhat/RPMS/i386 里面啰！如果是 i686 那么自然就是 /usr/src/redhat/RPMS/i686 目录下啰！

整个步骤大概就是这样子！最后的结果资料会放置在 RPMS 那个目录底下就对啦！我们这个案例中想要同时打包 RPM 与 SRPM ， 因此请您自行处理一下‘ rpmbuild -ba rp-pppoe.spec ’吧！

[root@www ~]# cd /usr/src/redhat/SPECS
[root@www SPECS]# rpmbuild -ba rp-pppoe.spec
....(以上省略)....
正在处理档案：rp-pppoe-debuginfo-3.5-32.2.vbird
已写入：/usr/src/redhat/SRPMS/rp-pppoe-3.5-32.2.vbird.src.rpm
已写入：/usr/src/redhat/RPMS/i386/rp-pppoe-3.5-32.2.vbird.i386.rpm
已写入：/usr/src/redhat/RPMS/i386/rp-pppoe-debuginfo-3.5-32.2.vbird.i386.rpm
正在执行 (%clean)：/bin/sh -e /var/tmp/rpm-tmp.10628
+ umask 022
+ cd /usr/src/redhat/BUILD
+ cd rp-pppoe-3.5
+ rm -rf /var/tmp/rp-pppoe-3.5-32.2.vbird-root
+ exit 0

[root@www SPECS]# find /usr/src/redhat -name 'rp-pppoe*rpm'
/usr/src/redhat/RPMS/i386/rp-pppoe-3.5-32.2.vbird.i386.rpm
/usr/src/redhat/RPMS/i386/rp-pppoe-debuginfo-3.5-32.2.vbird.i386.rpm
/usr/src/redhat/SRPMS/rp-pppoe-3.5-32.2.vbird.src.rpm
# 上面分别是 RPM 与 SRPM 的档案档名！

老实说，应该会出现 i686 的档名才对！不过，可能是原始码本身没有支援 i686 之类的语法吧！ 所以仅出现 i386 的档名而已。另外，你可以看到档名确实是如同我们之前谈到的喔！ 那你可以自行制作出有你特殊名称的档名啰 (例如上面的 vbird 啰)。

小标题的图示 一个打包自己软体的范例

这个就有趣了！我们自己来编辑一下自己制作的 RPM 怎么样？会很难吗？完全不会！ 我们这里就举个例子来玩玩吧！还记得我们在前一章谈到 Tarball 与 make 时，曾经谈到的 main 这个程式吗？现在我们将这个程式加上 Makefile 后， 将他制作成为 main-0.1.i386.rpm 好吗？那该如何进行呢？底下就让我们来处理处理吧！

  • 制作原始码档案 tarball 产生：

请将前一章你曾经处理过的 main.tgz 再次的捉下来一次，我们将这个档案放置到 /root 底下， 并且在 /usr/local/src 底下建立一个名为 main-0.1 的目录来解压缩喔！

[root@www ~]# mkdir /usr/local/src/main-0.1
[root@www ~]# tar -zxvf main.tgz -C /usr/local/src/main-0.1
[root@www ~]# cd /usr/local/src/main-0.1
[root@www main-0.1]# vim Makefile  <==建立原始码所需 make 规则
LIBS = -lm
OBJS = main.o haha.o sin_value.o cos_value.o
main: ${OBJS}
    gcc -o main ${OBJS} ${LIBS}
clean:
    rm -f main ${OBJS}
install:
    install -m 755 main $(RPM_INSTALL_ROOT)/usr/local/bin/main
# 记得 gcc 与 rm 之前是使用 <tab> 按键作出来的空白喔！

[root@www main-0.1]# cd ..
[root@www src]# tar -zcvf main-0.1.tar.gz main-0.1
# 此时会产生 main-0.1.tar.gz ，将他挪到 /usr/src/redhat/SOURCES 底下：
[root@www src]# cp main-0.1.tar.gz /usr/src/redhat/SOURCES

这个时候在 /usr/src/redhat 底下的原始码就建立成功了！接下来就是 spec 档案的建立啰！

  • 建立 *.spec 的设定档

这个档案的建置是所有 RPM 制作里面最重要的课题！你必须要仔细的设定他，不要随便处理！仔细看看吧！

[root@www ~]# cd /usr/src/redhat/SPECS
[root@www SPECS]# vim main.spec
Summary:   calculate sin and cos value.
Name:      main
Version:   0.1
Release:   1
License:   GPL
Group:     VBird's Home
Source:    main-0.1.tar.gz   <==记得要写正确的 Tarball 档名喔！
Url:       http://linux.vbird.org
Packager:  VBird
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root

%description
This package will let you input your name and calculate sin cos value.

%prep
%setup -q

%build
make

%install
rm -rf %{buildroot}
mkdir -p %{buildroot}/usr/local/bin
make install RPM_INSTALL_ROOT=%{buildroot}   <==这项目也很重要！

%files
/usr/local/bin/main

%changelog
* Wed Jul 01 2009 VBird Tsai <vbird@mail.vbird.idv.tw> 0.1
- build the program
  • 编译成为 RPM 与 SRPM

老实说，那个 spec 档案建置妥当后，后续的动作就简单的要命了！开始来编译吧！

[root@www SPECS]# rpmbuild -ba main.spec
....(前面省略)....
已写入：/usr/src/redhat/SRPMS/main-0.1-1.src.rpm
已写入：/usr/src/redhat/RPMS/i386/main-0.1-1.i386.rpm
已写入：/usr/src/redhat/RPMS/i386/main-debuginfo-0.1-1.i386.rpm

很快的，我们就已经建立了几个 RPM 档案啰！接下来让我们好好测试一下打包起来的成果吧！

  • 安装/测试/实际查询
[root@www ~]# rpm -ivh /usr/src/redhat/RPMS/i386/main-0.1-1.i386.rpm
正在准备…             ########################################### [100%]
   1:main                   ########################################### [100%]

[root@www ~]# rpm -ql main
/usr/local/bin/main   <==自己尝试执行 main 看看！

[root@www ~]# rpm -qi main
Name        : main              Relocations: (not relocatable)
Version     : 0.1                    Vendor: (none)
Release     : 1                  Build Date: 西元2009年07月02日 (周四)
Install Date: 西元2009年07月02日 Build Host: www.vbird.tsai
Group       : VBird's Home       Source RPM: main-0.1-1.src.rpm
Size        : 3360                  License: GPL
Signature   : (none)
Packager    : VBird
URL         : http://linux.vbird.org
Summary     : calculate sin and cos value.
Description :
This package will let you input your name and calculate sin cos value.
# 看到没？属于你自己的软体喔！真是很愉快的啦！

用很简单的方式，就可以将自己的软体或者程式给他修改与设定妥当！以后你就可以自行设定你的 RPM 啰！当然，也可以手动修改你的 SRPM 的来源档内容啰！

大标题的图示 YUM 线上升级机制

我们在本章一开始的地方谈到过 yum 这玩意儿，这个 yum 是透过分析 RPM 的标头资料后， 根据各软体的相关性制作出属性相依时的解决方案，然后可以自动处理软体的相依属性问题，以解决软体安装或移除与升级的问题。 详细的 yum 伺服器与用户端之间的沟通，可以再回到前面的部分查阅一下图 1.5.1 的说明。

由于 distribution 必须要先释出软体，然后将软体放置于 yum 伺服器上面，以提供用户端来要求安装与升级之用的。 因此我们想要使用 yum 的功能时，必须要先找到适合的 yum server 才行啊！而每个 yum server 可能都会提供许多不同的软体功能，那就是我们之前谈到的‘容器’啦！因此，你必须要前往 yum server 查询到相关的容器网址后，再继续处理后续的设定事宜。

事实上 CentOS 在释出软体时已经制作出多部映射站台 (mirror site) 提供全世界的软体更新之用。 所以，理论上我们不需要处理任何设定值，只要能够连上 Internet ，就可以使用 yum 啰！底下就让我们来玩玩看吧！

小标题的图示 利用 yum 进行查询、安装、升级与移除功能

yum 的使用真是非常简单，就是透过 yum 这个指令啊！那么这个指令怎么用呢？ 用法很简单，就让我们来简单的谈谈：

  • 查询功能：yum [list|info|search|provides|whatprovides] 参数

如果想要查询利用 yum 来查询原版 distribution 所提供的软体，或已知某软体的名称，想知道该软体的功能， 可以利用 yum 相关的参数为：

[root@www ~]# yum [option] [查询工作项目] [相关参数]
选项与参数：
[option]：主要的选项，包括有：
  -y ：当 yum 要等待使用者输入时，这个选项可以自动提供 yes 的回应；
  --installroot=/some/path ：将该软体安装在 /some/path 而不使用预设路径
[查询工作项目] [相关参数]：这方面的参数有：
  search  ：搜寻某个软体名称或者是描述 (description) 的重要关键字；
  list    ：列出目前 yum 所管理的所有的软体名称与版本，有点类似 rpm -qa；
  info    ：同上，不过有点类似 rpm -qai 的执行结果；
  provides：从档案去搜寻软体！类似 rpm -qf 的功能！

范例一：搜寻磁碟阵列 (raid) 相关的软体有哪些？
[root@www ~]# yum search raid
....(前面省略)....
mdadm.i386 : mdadm controls Linux md devices (software RAID arrays)
lvm2.i386 : Userland logical volume management tools
....(后面省略)....
# 在冒号 (:)  左边的是软体名称，右边的则是在 RPM 内的 name 设定 (软体名)
# 瞧！上面的结果，这不就是与 RAID 有关的软体吗？如果想了解 mdadm 的软体内容呢？

范例二：找出 mdadm 这个软体的功能为何
[root@www ~]# yum info mdadm
Installed Packages      <==这说明该软体是已经安装的了
Name   : mdadm          <==这个软体的名称
Arch   : i386           <==这个软体的编译架构
Version: 2.6.4          <==此软体的版本
Release: 1.el5          <==释出的版本
Size   : 1.7 M          <==此软体的档案总容量
Repo   : installed      <==容器回报说已安装的
Summary: mdadm controls Linux md devices (software RAID arrays)
Description:            <==看到否？这就是 rpm -qi 嘛！
mdadm is used to create, manage, and monitor Linux MD (software RAID)
devices.  As such, it provides similar functionality to the raidtools
package.  However, mdadm is a single program, and it can perform
almost all functions without a configuration file, though a configuration
file can be used to help with some common tasks.
# 不要跟我说，上面说些啥？自己找字典翻一翻吧！拜托拜托！

范例三：列出 yum 伺服器上面提供的所有软体名称
[root@www ~]# yum list
Installed Packages <==已安装软体
Deployment_Guide-en-US.noarch            5.2-9.el5.centos       installed
Deployment_Guide-zh-CN.noarch            5.2-9.el5.centos       installed
Deployment_Guide-zh-TW.noarch            5.2-9.el5.centos       installed
....(中间省略)....
Available Packages <==还可以安装的其他软体
Cluster_Administration-as-IN.noarch      5.2-1.el5.centos       base
Cluster_Administration-bn-IN.noarch      5.2-1.el5.centos       base
....(底下省略)....
# 上面提供的意义为：‘ 软体名称   版本   在那个容器内 ’

范例四：列出目前伺服器上可供本机进行升级的软体有哪些？
[root@www ~]# yum list updates  <==一定要是 updates 喔！
Updated Packages
Deployment_Guide-en-US.noarch            5.2-11.el5.centos      base
Deployment_Guide-zh-CN.noarch            5.2-11.el5.centos      base
Deployment_Guide-zh-TW.noarch            5.2-11.el5.centos      base
....(底下省略)....
# 上面就列出在那个容器内可以提供升级的软体与版本！

范例五：列出提供 passwd 这个档案的软体有哪些
[root@www ~]# yum provides passwd
passwd.i386 : The passwd utility for setting/changing passwords using PAM
passwd.i386 : The passwd utility for setting/changing passwords using PAM
# 找到啦！就是上面的这个软体提供了 passwd 这个程式！

透过上面的查询，你应该大致知道 yum 如何用在查询上面了吧？那么实际来应用一下：

例题：
利用 yum 的功能，找出以 pam 为开头的软体名称有哪些？而其中尚未安装的又有哪些？
答：
可以透过如下的方法来查询：
[root@www ~]# yum list pam*
Installed Packages
pam.i386                  0.99.6.2-3.27.el5      installed
pam_ccreds.i386           3-5                    installed
pam_krb5.i386             2.2.14-1               installed
pam_passwdqc.i386         1.0.2-1.2.2            installed
pam_pkcs11.i386           0.5.3-23               installed
pam_smb.i386              1.1.7-7.2.1            installed
Available Packages <==底下则是‘可升级’的或‘未安装’的
pam.i386                  0.99.6.2-4.el5         base
pam-devel.i386            0.99.6.2-4.el5         base
pam_krb5.i386             2.2.14-10              base
如上所示，所以可升级者有 pam, pam_krb5 这两个软体，完全没有安装的则是 pam-devel 这个软体啰！

  • 安装/升级功能：yum [install|update] 软体

既然可以查询，那么安装与升级呢？很简单啦！就利用 install 与 update 这两项工作来处理即可喔！

[root@www ~]# yum [option] [查询工作项目] [相关参数]
选项与参数：
  install ：后面接要安装的软体！
  update  ：后面接要升级的软体，若要整个系统都升级，就直接 update 即可

范例一：将前一个练习找到的未安装的 pam-devel 安装起来
[root@www ~]# yum install pam-devel
Setting up Install Process
Parsing package install arguments
Resolving Dependencies  <==先检查软体的属性相依问题
--> Running transaction check
---> Package pam-devel.i386 0:0.99.6.2-4.el5 set to be updated
--> Processing Dependency: pam = 0.99.6.2-4.el5 for package: pam-devel
--> Running transaction check
---> Package pam.i386 0:0.99.6.2-4.el5 set to be updated
filelists.xml.gz          100% |=========================| 1.6 MB    00:05
filelists.xml.gz          100% |=========================| 138 kB    00:00
-> Finished Dependency Resolution

Dependencies Resolved

=============================================================================
 Package                 Arch       Version          Repository        Size
=============================================================================
Installing:
 pam-devel               i386       0.99.6.2-4.el5   base              186 k
Updating:
 pam                     i386       0.99.6.2-4.el5   base              965 k

Transaction Summary
=============================================================================
Install      1 Package(s)  <==结果发现要安装此软体需要升级另一个相依的软体
Update       1 Package(s)
Remove       0 Package(s)

Total download size: 1.1 M
Is this ok [y/N]: y  <==确定要安装！
Downloading Packages: <==先下载！
(1/2): pam-0.99.6.2-4.el5 100% |=========================| 965 kB    00:05
(2/2): pam-devel-0.99.6.2 100% |=========================| 186 kB    00:01
Running rpm_check_debug
Running Transaction Test
Finished Transaction Test
Transaction Test Succeeded
Running Transaction <==开始安装！
  Updating  : pam                          ######################### [1/3]
  Installing: pam-devel                    ######################### [2/3]
  Cleanup   : pam                          ######################### [3/3]

Installed: pam-devel.i386 0:0.99.6.2-4.el5
Updated: pam.i386 0:0.99.6.2-4.el5
Complete!

有没有很高兴啊！你不必知道软体在哪里，你不必手动下载软体，你也不必拿出原版光碟出来 mount 之后查询再安装！全部不需要，只要有了 yum 这个家伙，你的安装、升级再也不是什么难事！ 而且还能主动的进行软体的属性相依处理流程，如上所示，一口气帮我们处理好了所有事情！ 是不是很过瘾啊！而且整个动作完全免费！够酷吧！

  • 移除功能：yum [remove] 软体

那能不能用 yum 移除软体呢？将刚刚的软体移除看看，会出现啥状况啊？

[root@www ~]# yum remove pam-devel
Setting up Remove Process
Resolving Dependencies  <==同样的，先解决属性相依的问题
--> Running transaction check
---> Package pam-devel.i386 0:0.99.6.2-4.el5 set to be erased
--> Finished Dependency Resolution

Dependencies Resolved

=============================================================================
 Package                 Arch       Version          Repository        Size
=============================================================================
Removing:
 pam-devel               i386       0.99.6.2-4.el5   installed         495 k

Transaction Summary
=============================================================================
Install      0 Package(s)
Update       0 Package(s)
Remove       1 Package(s)  <==还好，并没有属性相依的问题，单纯移除一个软体

Is this ok [y/N]: y
Downloading Packages:
Running rpm_check_debug
Running Transaction Test
Finished Transaction Test
Transaction Test Succeeded
Running Transaction
  Erasing   : pam-devel                    ######################### [1/1]

Removed: pam-devel.i386 0:0.99.6.2-4.el5
Complete!

连移除也这么简单！看来，似乎不需要 rpm 这个指令也能够快乐的安装所有的软体了！ 虽然是如此，但是 yum 毕竟是架构在 rpm 上面所发展起来的，所以，鸟哥认为你还是得需要了解 rpm 才行！不要学了 yum 之后就将 rpm 的功能忘记了呢！切记切记！

小标题的图示 yum 的设定档

虽然 yum 是你的主机能够连线上 Internet 就可以直接使用的，不过，由于 CentOS 的映射站台可能会选错， 举例来说，我们在台湾，但是 CentOS 的映射站台却选择到了大陆北京或者是日本去，有没有可能发生啊！ 有啊！鸟哥教学方面就常常发生这样的问题，要知道，我们连线到大陆或日本的速度是非常慢的呢！那怎办？ 当然就是手动的修改一下 yum 的设定档就好啰！

在台湾，CentOS 的映射站台主要有高速网路中心与义首大学，鸟哥近来比较偏好高速网路中心， 似乎更新的速度比较快，而且连接台湾学术网路也非常快速哩！因此，鸟哥底下建议台湾的朋友使用高速网路中心的 ftp 主机资源来作为 yum 伺服器来源喔！目前高速网路中心对于 CentOS 所提供的相关网址如下：

  • http://ftp.twaren.net/Linux/CentOS/5/

如果你连接到上述的网址后，就会发现里面有一堆连结，那些连结就是这个 yum 伺服器所提供的容器了！ 所以高速网路中心也提供了 addons, centosplus, extras, fasttrack, os, updates 等容器，最好认的容器就是 os (系统预设的软体) 与 updates (软体升级版本) 啰！由于鸟哥在我的测试用主机是利用 i386 的版本， 因此那个 os 再点进去就会得到如下的可提供安装的网址：

  • http://ftp.twaren.net/Linux/CentOS/5/os/i386/

为什么在上述的网址内呢？有什么特色！最重要的特色就是那个‘ repodata ’的目录！该目录就是分析 RPM 软体后所产生的软体属性相依资料放置处！因此，当你要找容器所在网址时， 最重要的就是该网址底下一定要有个名为 repodata 的目录存在！那就是容器的网址了！ 其他的容器正确网址，就请各位看倌自行寻找一下喔！现在让我们修改设定档吧！

[root@www ~]# vi /etc/yum.repos.d/CentOS-Base.repo
[base]
name=CentOS-$releasever - Base
mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=os
#baseurl=http://mirror.centos.org/centos/$releasever/os/$basearch/
gpgcheck=1
gpgkey=http://mirror.centos.org/centos/RPM-GPG-KEY-CentOS-5

如上所示，鸟哥仅列出 base 这个容器内容而已，其他的容器内容请自行查阅啰！上面的资料需要注意的是：

  • [base]：代表容器的名字！中刮号一定要存在，里面的名称则可以随意取。但是不能有两个相同的容器名称， 否则 yum 会不晓得该到哪里去找容器相关软体清单档案。

  • name：只是说明一下这个容器的意义而已，重要性不高！

  • mirrorlist=：列出这个容器可以使用的映射站台，如果不想使用，可以注解到这行；

  • baseurl=：这个最重要，因为后面接的就是容器的实际网址！ mirrorlist 是由 yum 程式自行去捉映射站台， baseurl 则是指定固定的一个容器网址！我们刚刚找到的网址放到这里来啦！

  • enable=1：就是让这个容器被启动。如果不想启动可以使用 enable=0 喔！

  • gpgcheck=1：还记得 RPM 的数位签章吗？这就是指定是否需要查阅 RPM 档案内的数位签章！

  • gpgkey=：就是数位签章的公钥档所在位置！使用预设值即可

了解这个设定档之后，接下来让我们修改整个档案的内容，让我们这部主机可以直接使用高速网路中心的资源吧！ 修改的方式鸟哥仅列出 base 这个容器项目而已，其他的项目请您自行依照上述的作法来处理即可！

[root@www ~]# vi /etc/yum.repos.d/CentOS-Base.repo
[base]
name=CentOS-$releasever - Base
baseurl=http://ftp.twaren.net/Linux/CentOS/5/os/i386/
gpgcheck=1
gpgkey=http://mirror.centos.org/centos/RPM-GPG-KEY-CentOS-5
# 底下其他的容器项目，请自行到高速网路中心去查询后自己处理！

接下来当然就是给他测试一下啰！如何测试呢？再次使用 yum 即可啊！

范例一：列出目前 yum server 所使用的容器有哪些？
[root@www ~]# yum repolist all
repo id         repo name                  status
addons          CentOS-5 - Addons          enabled
base            CentOS-5 - Base            enabled
c5-media        CentOS-5 - Media           disabled
centosplus      CentOS-5 - Plus            disabled
extras          CentOS-5 - Extras          enabled
updates         CentOS-5 - Updates         enabled
# 上面最右边有写 enabled 才是有启动的！由于 /etc/yum.repos.d/
# 有多个设定档，所以你会发现还有其他的容器存在。

  • 修改容器产生的问题与解决之道

由于我们是修改系统预设的设定档，事实上，我们应该要在 /etc/yum.repos.d/ 底下新建一个档案， 该副档名必须是 .repo 才行！但因为我们使用的是指定特定的映射站台，而不是其他软体开发生提供的容器， 因此才修改系统预设设定档。但是可能由于使用的容器版本有新旧之分，你得要知道， yum 会先下载容器的清单到本机的 /var/cache/yum 里面去！那我们修改了网址却没有修改容器名称 (中刮号内的文字)， 可能就会造成本机的清单与 yum 伺服器的清单不同步，此时就会出现无法更新的问题了！

那怎么办啊？很简单，就清除掉本机上面的旧资料即可！需要手动处理吗？不需要的， 透过 yum 的 clean 项目来处理即可！

[root@www ~]# yum clean [packages|headers|all]
选项与参数：
 packages：将已下载的软体档案删除
 headers ：将下载的软体档头删除
 all     ：将所有容器资料都删除！

范例一：删除已下载过的所有容器的相关资料 (含软体本身与清单)
[root@www ~]# yum clean all
小标题的图示 yum 的软体群组功能

透过 yum 来线上安装一个软体是非常的简单，但是，如果要安装的是一个大型专案呢？ 举例来说，鸟哥使用预设安装的方式安装了测试机，这部主机就只有 GNOME 这个视窗管理员， 那我如果想要安装 KDE 呢？难道需要重新安装？当然不需要，透过 yum的软体群组功能即可！ 来看看指令先：

[root@www ~]# yum [群组功能] [软体群组]
选项与参数：
   grouplist   ：列出所有可使用的‘套件组’，例如 Development Tools 之类的；
   groupinfo   ：后面接 group_name，则可了解该 group 内含的所有套件名；
   groupinstall：这个好用！可以安装一整组的套件群组，相当的不错用！
   groupremove ：移除某个套件群组；

范例一：查阅目前容器与本机上面的可用与安装过的软体群组有哪些？
[root@www ~]# yum grouplist
Installed Groups:
   Office/Productivity
   Editors
   System Tools
....(中间省略)....
Available Groups:
   Tomboy
   Cluster Storage
   Engineering and Scientific
....(以下省略)....

你会发现系统上面的软体大多是群组的方式一口气来提供安装的！还记全新安装 CentOS 时， 不是可以选择所需要的软体吗？而那些软体不是利用 GNOME/KDE/X Window ... 之类的名称存在吗？ 其实那就是软体群组啰！如果你执行上述的指令后，在‘Available Groups’底下应该会看到一个 ‘XFCE-4.4’的软体群组，想知道那是啥吗？就这样做：

[root@www ~]# yum groupinfo XFCE-4.4
Setting up Group Process

Group: XFCE-4.4
 Description: This group contains the XFCE desktop environment.
 Mandatory Packages:
   xfce4-session
....(中间省略)....
 Default Packages:
   xfce4-websearch-plugin
....(中间省略)....
 Optional Packages:
   xfce-mcs-manager-devel
   xfce4-panel-devel
....(以下省略)....

你会发现那就是一个桌面环境 (desktop environment) ，也就是一个视窗管理员啦！ 至于底下就列出主要的与选择性 (optional) 的软体名称啰！让我们直接安装看看：

[root@www ~]# yum groupinstall XFCE-4.4

你会发现系统进行了一大堆软体的安装！那就是啦！整个安装 XFCE 这个视窗介面所需的所有软体！ 这个咚咚真是非常的方便呢！这个功能请一定要记下来，对你未来安装软体是非常有帮助的喔！ ^_^

小标题的图示 全系统自动升级

我们可以手动选择是否需要升级，那能不能让系统自动升级，让我们的系统随时保持在最新的状态呢？ 当然可以啊！透过‘ yum -y update ’来自动升级，那个 -y 很重要，因为可以自动回答 yes 来开始下载与安装！ 然后再透过 crontab 的功能来处理即可！假设我每天在台湾时间 3:00am 网路频宽比较轻松的时候进行升级， 你可以这样做的：

[root@www ~]# vim /etc/crontab
....(前面省略并保留设定值)....
0  3 * * * root /usr/bin/yum -y update

从此你的系统就会自动升级啦！很棒吧！此外，你还是得要分析登录档与收集 root 的信件的， 因为如果升级的是核心软体 (kernel)，那么你还是得要重新开机才会让安装的软体顺利运作的！ 所以还是得分析登录档，若有新核心安装，就重新开机，否则就让系统自动维持在最新较安全的环境吧！ 真是轻松愉快的管理啊！

大标题的图示 管理的抉择：RPM 还是 Tarball

这一直是个有趣的问题：‘如果我要升级的话，或者是全新安装一个新的软体， 那么该选择 RPM 还是 Tarball 来安装呢？’，事实上考虑的因素很多，不过鸟哥通常是这样建议的：

  1. 优先选择原厂的 RPM 功能：

    由于原厂释出的软体通常具有一段时间的维护期，举例来说， RHEL 与 CentOS 每一个版本至少提供五年以上的更新期限。这对于我们的系统安全性来说，实在是非常好的选项！ 何解？既然 yum 可以自动升级，加上原厂会持续维护软体更新，那么我们的系统就能够自己保持在软体最新的状态， 对于资安来说当然会比较好一些的！ 此外，由于 RPM 与 yum 具有容易安装/移除/升级等特点，且还提供查询与验证的功能，安装时更有数位签章的保护， 让你的软体管理变的更轻松自在！因此，当然首选就是利用 RPM 来处理啦！

  2. 选择软体官网释出的 RPM 或者是提供的容器网址：

    不过，原厂并不会包山包海，因此某些特殊软体你的原版厂商并不会提供的！举例来说 CentOS 就没有提供 NTFS 的相关模组。此时你可以自行到官网去查阅，看看有没有提供相对到你的系统的 RPM 档案， 如果有提供容器网址，那就更好啦！可以修改 yum 设定档来加入该容器，就能够自动安装与升级该软体！ 你说方不方便啊！

  3. 利用 Tarball 安装特殊软体：

    某些特殊用途的软体并不会特别帮你制作 RPM 档案的，此时建议你也不要妄想自行制作 SRPM 来转成 RPM 啦！ 因为你只有区区一部主机而已，若是你要管理相同的 100 部主机，那么将原始码转制作成 RPM 就有价值！ 单机版的特殊软体，例如学术网路常会用到的 MPICH/PVM 等平行运算函式库，这种软体建议使用 tarball 来安装即可， 不需要特别去搜寻 RPM 啰！

  4. 用 Tarball 测试新版软体：

    某些时刻你可能需要使用到新版的某个软体，但是原版厂商仅提供旧版软体，举例来说，我们的 CentOS 主要是定位于企业版，因此很多软体的要求是‘稳’而不是‘新’，但你就是需要新软体啊！ 然后又担心新软体装好后产生问题，回不到旧软体，那就惨了！此时你可以用 tarball 安装新软体到 /usr/local 底下， 那么该软体就能够同时安装两个版本在系统上面了！而且大多数软体安装数种版本时还不会互相干扰的！ 嘿嘿！用来作为测试新软体是很不错的呦！只是你就得要知道你使用的指令是新版软体还是旧版软体了！

所以说，RPM 与 Tarball 各有其优缺点，不过，如果有 RPM 的话，那么优先权还是在于 RPM 安装上面，毕竟管理上比较便利，但是如果软体的架构差异性太大， 或者是无法解决相依属性的问题，那么与其花大把的时间与精力在解决属性相依的问题上，还不如直接以 tarball 来安装，轻松又惬意！

大标题的图示 重点回顾
  • 为了避免使用者自行编译的困扰，开发商自行在特定的硬体与作业系统平台上面预先编译好软体， 并将软体以特殊格式封包成档案，提供终端用户直接安装到固定的作业系统上，并提供简单的查询/安装/移除等流程。 此称为软体管理员。常见的软体管理员有 RPM 与 DPKG 两大主流。
  • RPM 的全名是 RedHat Package Manager，原本是由 Red Hat 公司所发展的，流传甚广；
  • RPM 类型的软体中，所含有的软体是经过编译后的 binary program ，所以可以直接安装在使用者端的系统上， 不过，也由于如此，所以 RPM 对于安装者的环境要求相当严格；
  • RPM 除了将软体安装至使用者的系统上之外，还会将该软体的版本、名称、档案与目录配置、系统需求等等均记录于资料库 (/var/lib/rpm) 当中，方便未来的查询与升级、移除；
  • RPM 可针对不同的硬体等级来加以编译，制作出来的档案可于副档名 (i386, i586, i686, x86_64) 来分辨；
  • RPM 最大的问题为软体之间的相依性问题；
  • SRPM 为 Source RPM ，内含的档案为 Source code 而非为 binary file ，所以安装 SRPM 时还需要经过 compile ，不过，SRPM 最大的优点就是可以让使用者自行修改设定参数 (makefile/configure 的参数) ，以符合使用者自己的 Linux 环境；
  • RPM 软体的属性相依问题，已经可以藉由 yum 或者是 APT 等方式加以克服。 CentOS 使用的就是 yum 机制。
  • yum 伺服器提供多个不同的容器放置个别的软体，以提供用户端分别管理软体类别。
大标题的图示 本章习题
  • 情境模拟题一：实际安装 php, php-mysql, php-devel, httpd-devel 等软体的方式

    • 目标：利用 rpm 查询软体是否已安装，利用 yum 进行线上查询；
    • 目标：你的 Linux 必须要已经接上 Internet 才行；
    • 需求：最好了解磁碟容量是否够用，以及如何启动服务等。

    这个模拟题的目的是想要安装一套较为完整的 WWW 伺服器，便且此伺服器可以支援外挂的其他网页伺服器模组。 所以需要安装的就会有网页程式语言 php 与资料库软体 MySQL ，以及未来开发用的 php-devel, httpd-devel 等软体。 整个流程会有点像这样：

    1. 检查所需要的软体是否存在？最好直接使用 rpm ，因为可以直接取得 RPM 的资料库内容：
      [root@www ~]# rpm -q httpd httpd-devel php php-devel php-mysql
httpd-2.2.3-22.el5.centos
package httpd-devel is not installed  <==没有安装的软体！
php-5.1.6-23.el5
package php-devel is not installed    <==没有安装的软体！
package php-mysql is not installed    <==没有安装的软体！
      经过上面的分析，我们知道 httpd-devel, php-devel, php-mysql 等软体并没有安装！那么该如何安装 可以使用 yum 直接线上安装。不过我们必须要先有网路才行！

    2. 确认网路的可行性：
      [root@www ~]# ifconfig eth0
eth0      Link encap:Ethernet  HWaddr 08:00:27:11:3B:75
          inet addr:192.168.201.201  Bcast:192.168.201.255  Mask:255.255.255.0
....(底下省略)....
# 你可以看到我们的主机是有 IP 存在的！再来看看有没有路由设定存在？

[root@www ~]# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
192.168.201.0   0.0.0.0         255.255.255.0   U     0      0        0 eth0
0.0.0.0         192.168.201.254 0.0.0.0         UG    0      0        0 eth0
# 确实是有路由器 (Gateway) 存在的！那么该路由器是否设定正确呢？

[root@www ~]# ping -c 2 192.168.201.254
PING 192.168.201.254 (192.168.201.254) 56(84) bytes of data.
64 bytes from 192.168.201.254: icmp_seq=1 ttl=64 time=0.325 ms
64 bytes from 192.168.201.254: icmp_seq=2 ttl=64 time=0.281 ms
# 路由器有回应！表示可以连接到路由器！那么 TCP/IP 设好了，
# 但是主机名称解析器统 (DNS) 该如何处理？

[root@www ~]# dig www.google.com

; <<>> DiG 9.3.4-P1 <<>> www.google.com
;; global options:  printcmd
....(中间省略)....
;; QUESTION SECTION:
;www.google.com.                        IN      A
....(中间省略)....
;; ANSWER SECTION:
www.google.com.         522933  IN      CNAME   www.l.google.com.
www.l.google.com.       107     IN      A       72.14.203.103
....(中间省略)....
;; Query time: 5 msec
;; SERVER: 120.114.150.1#53(120.114.150.1)
;; WHEN: Fri Sep 18 13:14:45 2009
;; MSG SIZE  rcvd: 340
# 确实有查到 Google 的 IP ，且是由 120.114.150.1 那部 DNS 主机帮忙解析的！
    3. 网路设定妥当之后，那我们就能够直接使用 yum 啰！可以这样直接进行安装的：
      [root@www ~]# yum install httpd httpd-devel php php-devel php-mysql
      然后接着一步一步进行安装即可。

简答题部分：
  • 如果你曾经修改过 yum 设定档内的容器设定 (/etc/yum.repos.d/*.repo) ，导致下次使用 yum 进行安装时老是发现错误， 此时你该如何是好？
    先确认你的设定档确实是正确的，如果没问题，可以将 yum 的快取清除，使用‘yum clean all’即可。 事实上， yum 的所有快取、下载软体、下载软体的表头资料，都放置于 /var/cache/yum/ 目录下。
  • 简单说明 RPM 与 SRPM 的异同？
    RPM 档案是由程式打包者 (通常是由 distribution 的开发商) 藉由程式的原始码，在特定的平台上面所编译成功的 binary program 的资料，并将该资料制作成为 RPM 的格式，以方便相同软、硬体平台的使用者之安装使用。 在安装时显的很简单，因为程式打包者的平台与使用者所使用的平台预设为相同。
    至于 SRPM 则是藉由与 RPM 相同的设定档资料，不过将原始码直接包在 SRPM 档案当中，而不经过编译。 因为 SRPM 所内含的资料为原始码，所以安装时必须要再经过编译的行为才能成为 RPM 并提供使用者安装。
  • 假设我想要安装一个软体，例如 pkgname.i386.rpm ，但却老是发生无法安装的问题，请问我可以加入哪些参数来强制安装他？
    可以加入 --nodeps 等参数。例如 rpm -ivh --nodeps pkgname.i386.rpm
  • 承上题，你认为强制安装之后，该软体是否可以正常执行？为什么？
    一般来说，应该是‘不能执行’的，因为该软体具有相依属性的问题， 某些时刻该软体的程式可能需要呼叫外部的函式库，但函式库可能未安装，因此当然无法执行成功。
  • 有些人使用 OpenLinux 3.1 Server 安装在自己的 P-166 MMX ，却发现无法安装，在查询了该原版光碟的内容，发现里面的档案名称为 ***.i686.rpm 。请问，无法安装的可能原因为何？
    因为 P-166MMX 为 i586 的硬体平台，而 OpenLinux 为针对 i686 的硬体平台进行最佳化， 因此很可能由于下达的参数无法支援的问题，导致无法安装成功。
  • 请问我使用 rpm -Fvh *.rpm 及 rpm -Uvh *.rpm 来升级时，两者有何不同？
    -Uvh 后面接的软体，如果原本未安装，则直接安装，原本已安装时，则直接升级；
    -Fvh 后面接的软体，如果原本未安装，则不安装，原本已安装时，则直接升级；
  • 假设有一个厂商推出软体时，自行处理了数位签章，你想要安装他们的软体所以需要使用数位签章，假设数位签章的档名为 signe， 那你该如何安装？
    rpm --import signe
  • 承上，假设该软体厂商提供了 yum 的安装网址为： http://their.server.name/path/ ，那你该如何处理 yum 的设定档？
    可以自行取个档名，在此例中我们使用‘ vim /etc/yum.repos.d/their.repo ’，副档名要正确！ 内容有点像这样即可：
    [their]
name=their server name
baseurl=http://their.server.name/path/
enable=1
gpgcheck=0
    然后使用 yum 去安装该软体看看。
大标题的图示 参考资料与延伸阅读
  • 注1：GNU Privacy Guard (GPG) 官方网站的介绍：http://www.gnupg.org/
  • RPM 包装档案管理程式：http://www.study-area.org/tips/rpm.htm
  • 中文 RPM HOW-TO：http://www.linux.org.tw/CLDP/RPM-HOWTO.html
  • RPM 的使用：http://linux.tnc.edu.tw/techdoc/rpm-howto.htm
  • 大家来作 RPM ：http://freebsd.ntu.edu.tw/bsd/4/3/2/29.html
  • 一本 RPM 的原文书：http://linux.tnc.edu.tw/techdoc/maximum-rpm/rpmbook/
  • 台湾网路危机处理小组：http://www.cert.org.tw/
2002/08/21：第一次完成
2003/02/11：重新编排与加入 FAQ
2004/04/11：已经完成了 Source code 与 Tarball ，开始进行 RPM 与 SRPM 的介绍！(需要耗时多日啊！因为又要进兵营去了！)
2004/04/20：终于给他熬出来啦！又是过了两个休假期间～啊！给我退伍令、其余免谈！
2005/10/02：旧版的 SRPM 资料已经移动到 此处 。
2005/10/03：旧版的针对 Red Hat 与 Mandriva 的版本移动到 此处 。
2005/10/03：将原本去年的版本改为 FC4 为范例的模样！
2009/06/20：原本的针对 FC4 写的旧版文章移动到此处。
2009/09/18：加入了简单的情境模拟，也加入了一些关于 yum 的习题喔！


鸟哥的 Linux 私房菜 -- X Window 简易设定档设定

为取得较佳浏览结果，请爱用 firefox 浏览本网页
鸟哥的 Linux 私房菜馆 | Linux 基础文件 | Linux 架站文件 | Linux 企业运用 | 安全管理 | 新手讨论 |

第二十四章、 X Window 设定介绍
最近更新日期：2009/08/07
在 Linux 上头的图形介面我们称之为 X Window System，简称为 X 或 X11 啰！ 为何称之为系统呢？这是因为 X 视窗系统又分为 X server 与 X client ，既然是 Server/Client (主从架构) 这就表示其实 X 视窗系统是可以跨网路且跨平台的！X 视窗系统对于 Linux 来说仅是一个软体， 只是这个软体日趋重要喔！因为 Linux 是否能够在桌上型电脑上面流行，与这个 X 视窗系统有关啦！ 好在，目前的 X 视窗系统整合到 Linux 已经非常优秀了，而且也能够具有 3D 加速的功能， 只是，我们还是得要了解一下 X 视窗系统才好，这样如果出问题，我们才有办法处理啊！

1. 什么是 X Window System
    1.1 X Window 的发展简史
    1.2 主要元件： X Server/X Client/Window Manager/Display Manager
    1.3 X Window 的启动流程：startx, xinit
    1.4 X 启动流程测试
    1.5 我是否需要启用 X Window System
 2. X Server 设定档解析与设定
    2.1 解析 xorg.conf 设定
    2.2 X Font Server (XFS) 与加入额外中文字形：chkfontpath, fc-cache
    2.3 设定档重建与显示器参数微调：透过 gtf 调整解析度
 3. 显示卡驱动程式安装范例
    3.1 NVidia
    3.2 ATI (AMd)
    3.3 Intel
 4. 重点回顾
5. 本章习题
6. 参考资料与延伸阅读
7. 针对本文的建议：http://phorum.vbird.org/viewtopic.php?t=23897
大标题的图示 什么是 X Window System

Unix Like 作业系统不是只能进行伺服器的架设而已，在美编、排版、制图、多媒体应用上也是有其需要的。 这些需求都需要用到图形介面 (Graphical User Interface, GUI) 的操作的， 所以后来才有所谓的 X Window System 这玩意儿。那么为啥图形视窗介面要称为 X 呢？因为就英文字母来看 X 是在 W(indow) 后面，因此，人们就戏称这一版的视窗介面为 X 啰 (有下一版的新视窗之意)！

事实上， X Window System 是个非常大的架构，他还用到网路功能呢！也就是说，其实 X 视窗系统是能够跨网路与跨作业系统平台的！ 而鸟哥这个基础篇是还没有谈到伺服器与网路主从式架构，因此 X 在这里并不容易理解的。不过，没关系！ 我们还是谈谈 X 怎么来的，然后再来谈谈这 X 视窗系统的元件有哪些，慢慢来，应该还是能够理解 X 的啦！

小标题的图示 X Window 的发展简史

X Window 系统最早是由 MIT (Massachusetts Institute of Technology, 麻省理工学院) 在 1984 年发展出来的， 当初 X 就是在 Unix 的 System V 这个作业系统版本上面开发出来的。在开发 X 时，开发者就希望这个视窗介面不要与硬体有强烈的相关性，这是因为如果与硬体的相关性高，那就等于是一个作业系统了， 如此一来的应用性会比较局限。因此 X 在当初就是以应用程式的概念来开发的，而非以作业系统来开发。

由于这个 X 希望能够透过网路进行图形介面的存取，因此发展出许多的 X 通讯协定，这些网路架构非常的有趣， 所以吸引了很多厂商加入研发，因此 X 的功能一直持续在加强！一直到 1987 年更改 X 版本到 X11 ，这一版 X 取得了明显的进步， 后来的视窗介面改良都是架构于此一版本，因此后来 X 视窗也被称为 X11 。这个版本持续在进步当中，到了 1994 年发布了新版的 X11R6 ，后来的架构都是沿用此一释出版本，所以后来的版本定义就变成了类似 1995 年的 X11R6.3 之类的样式。 (注1)

1992 年 XFree86 (http://www.xfree86.org/) 计划顺利展开， 该计划持续在维护 X11R6 的功能性，包括对新硬体的支援以及更多新增的功能等等。当初定名为 XFree86 其实是根据‘ X + Free software + x86 硬体 ’而来的呢。早期 Linux 所使用的 X Window 的主要核心都是由 XFree86 这个计划所提供的，因此，我们常常将 X 系统与 XFree86 挂上等号的说。

不过由于一些授权的问题导致 XFree86 无法继续提供类似 GPL 的自由软体，后来 Xorg 基金会就接手 X11R6 的维护！ Xorg (http://www.x.org/) 利用当初 MIT 发布的类似自由软体的授权， 将 X11R6 拿来进行维护，并且在 2004 年发布了 X11R6.8 版本，更在 2005 年后发表了 X11R7.x 版。 现在我们 CentOS 5.x 使用的 X 就是 Xorg 提供的 X11R7 喔！ 而这个 X11R6/X11R7 的版本是自由软体，因此很多组织都利用这个架构去设计他们的图形介面喔！包括 Mac OS X v10.3 也曾利用过这个架构来设计他们的视窗呢！我们的 CentOS 也是利用 Xorg 提供的 X11 啦！

从上面的说明，我们可以知道的是：

  • 在 Unix Like 上面的图形使用者介面 (GUI) 被称为 X 或 X11；
  • X11 是一个‘软体’而不是一个作业系统；
  • X11 是利用网路架构来进行图形介面的执行与绘制；
  • 较著名的 X 版本为 X11R6 这一版，目前大部分的 X 都是这一版演化出来的 (包括 X11R7)；
  • 现在大部分的 distribution 使用的 X 都是由 Xorg 基金会所提供的 X11 软体；
  • X11 使用的是 MIT 授权，为类似 GPL 的自由软体授权方式。
小标题的图示 主要元件： X Server/X Client/Window Manager/Display Manager

如同前面谈到的，X Window system 是个利用网路架构的图形使用者介面软体，那到底这个架构可以分成多少个元件呢？ 基本上是分成 X Server 与 X Client 两个元件而已喔！其中 X Server 在管理硬体，而 X Client 则是应用程式。 在运作上，X Client 应用程式会将所想要呈现的画面告知 X Server ，最终由 X server 来将结果透过他所管理的硬体绘制出来！ 整体的架构我们大约可以使用如下的图示来作个介绍：(注2)

X Window System 的架构
图 1.2.1、 X Window System 的架构 (注2)

上面的图示非常有趣喔！我们在用户端想要取得来自伺服器的图形资料时，我们用户端使用的当然是用户端的硬体设备啊， 所以，X Server 的重点就是在管理用户端的硬体，包括接受键盘/滑鼠等设备的输入资讯， 并且将图形绘制到荧幕上 (请注意上图的所有元件之间的箭头指示)。但是到底要绘制个啥东西呢？ 绘图总是需要一些数据才能绘制吧？此时 X Client (就是 X 应用程式) 就很重要啦！他主要提供的就是告知 X Server 要绘制啥东西。那照这样的想法来思考，我们是想要取得远端伺服器的绘图数据来我们的电脑上面显示嘛！ 所以啰，远端伺服器提供的是 X client 软体啊！

底下就让我们来更深入的聊一聊这两个元件吧！

  • X Server：硬体管理、荧幕绘制与提供字型功能：

既然 X Window System 是要显示图形介面，因此理所当然的需要一个元件来管理我主机上面的所有硬体设备才行！ 这个任务就是 X Server 所负责的。而我们在 X 发展简史当中提到的 XFree86 计划及 Xorg 基金会，主要提供的就是这个 X Server 啦！那么 X Server 管理的设备主要有哪些呢？其实与输入/输出有关喔！包括键盘、滑鼠、手写板、显示器 (monitor) 、荧幕解析度与色彩深度、显示卡 (包含驱动程式) 与显示的字型等等，都是 X Server 管理的。

咦！显示卡、荧幕以及键盘滑鼠的设定，不是在开机的时候 Linux 系统以 /etc/sysconfig 目录下的 keyboard/mouse 等设定档就设好了吗？为何 X Server 还要重新设定啊？这是因为 X Window 在 Linux 里面仅能算是‘一套很棒的软体’， 所以 X Window 有自己的设定档，你必须要针对他的设定档设定妥当才行。也就是说， Linux 的设定与 X Server 的设定不一定要相同的！因此，你在 Linux 的 run level 3 想要玩图形介面时，就得要载入 X Window 需要的驱动程式才行～总之， X Server 的主要功能就是在管理‘主机’上面的显示硬体与驱动程式。

既然 X Window System 是以透过网路取得图形介面的一个架构，那么用户端是如何取得伺服器端提供的图形画面呢？ 由于伺服器与用户端的硬体不可能完全相同，因此我们用户端当然不可能使用到伺服器端的硬体显示功能！ 举例来说，你的用户端电脑并没有 3D 影像加速功能，那么你的画面可能呈现出伺服器端提供的 3D 加速吗？ 当然不可能吧！所以啰 X Server 的目的在管理用户端的硬体设备！也就是说：‘每部用户端主机都需要安装 X Server，而伺服器端则是提供 X Client 软体， 以提供用户端绘图所需要的数据资料’。

X Server / X Client 的互动并非仅有 client --> server，两者其实有互动的！从上图 1.2.1 我们也可以发现， X Server 还有一个重要的工作，那就是将来自输入装置 (如键盘、滑鼠等) 的动作告知 X Client， 你晓得， X Server 既然是管理这些周边硬体，所以，周边硬体的动作当然是由 X Server 来管理的， 但是 X Server 本身并不知道周边设备这些动作会造成什么显示上的效果， 因此 X Server 会将周边设备的这些动作行为告知 X Client ，让 X Client 去伤脑筋。

  • X Client：负责 X Server 要求的‘事件’之处理：

前面提到的 X Server 主要是管理显示介面与在荧幕上绘图，同时将输入装置的行为告知 X Client， 此时 X Client 就会依据这个输入装置的行为来开始处理，最后 X Client 会得到‘ 嗯！这个输入装置的行为会产生某个图示’，然后将这个图示的显示资料回传给 X Server ， X server 再根据 X Client 传来的绘图资料将他描图在自己的荧幕上，来得到显示的结果。

也就是说， X Client 最重要的工作就是处理来自 X Server 的动作，将该动作处理成为绘图资料， 再将这些绘图资料传回给 X Server 啰！由于 X Client 的目的在产生绘图的数据，因此我们也称呼 X Client 为 X Application (X 应用程式)。而且，每个 X Client 并不知道其他 X Client 的存在， 意思是说，如果有两个以上的 X client 同时存在时，两者并不知道对方到底传了什么数据给 X Server ， 因此 X Client 的绘图常常会互相重叠而产生困扰喔！

举个例子来说，当我们在 X Window 的画面中，将滑鼠向右移动，那他是怎么告知 X Server 与 X Client 的呢？ 首先， X server 会侦测到滑鼠的移动，但是他不知道应该怎么绘图啊！此时，他将滑鼠的这个动作告知 X Client， X Client 就会去运算，结果得到，嘿嘿！其实要将滑鼠指标向右移动几个位素，然后将这个结果告知 X server ， 接下来，您就会看到 X Server 将滑鼠指标向右移动啰～

这样做有什么好处啊？最大的好处是， X Client 不需要知道 X Server 的硬体配备与作业系统！因为 X Client 单纯就是在处理绘图的资料而已，本身是不绘图的。所以，在用户端的 X Server 用的是什么硬体？用的是哪套作业系统？伺服器端的 X Client 根本不需要知道～相当的先进与优秀～对吧！ ^_^ 整个运作流程可以参考下图：用户端用的是什么作业系统在 Linux 主机端是不在乎的！

X Server 用户端的作业系统与 X client 的沟通示意
图 1.2.2、 X Server 用户端的作业系统与 X client 的沟通示意

  • X Window Manager：特殊的 X Client ，负责管理所有的 X client 软体

刚刚前面提到，X Client 的主要工作是将来自 X Server 的资料处理成为绘图数据，再回传给 X server 而已， 所以 X client 本身是不知道他在 X Server 当中的位置、大小以及其他相关资讯的。这也是上面我们谈到的， X client 彼此不知道对方在荧幕的哪个位置啊！为了克服这个问题，因此就有 Window Manager (WM, 视窗管理员) 的产生了。 视窗管理员也是 X client ，只是他主要在负责全部 X client 的控管，还包括提供某些特殊的功能，例如：

  • 提供许多的控制元素，包括工作列、背景桌面的设定等等；
  • 管理虚拟桌面 (virtual desktop)；
  • 提供视窗控制参数，这包括视窗的大小、视窗的重叠显示、视窗的移动、视窗的最小化等等。

我们常常听到的 KDE, GNOME, XFCE 还有阳春到爆的 twm 等等，都是一些视窗管理员的专案计划啦！ 这些专案计划中，每种视窗管理员所用以开发的显示引擎都不太相同，所著重的方向也不一样， 因此我们才会说，在 Linux 底下，每套 Window Manager 都是独特存在的，不是换了桌面与显示效果而已， 而是连显示的引擎都不会一样喔！底下是这些常见的视窗管理员全名与连结：

  • GNOME (GNU Network Object Model Environment)：http://www.gnome.org/
  • KDE (K Desktop Enviroment)：http://kde.org/
  • twm (Tab Window Manager)：http://xwinman.org/vtwm.php
  • XFCE (XForms Common Environment)：http://www.xfce.org/

由于 Linux 越来越朝向 Desktop 桌上型电脑使用方向走，因此视窗管理员的角色会越来越重要！ 目前我们 CentOS 预设提供的有 GNOME 与 KDE ，这两个视窗管理员上面还有提供非常多的 X client 软体， 包括办公室生产力软体 (Open Office) 以及常用的网路功能 (firefox 浏览器、 Thunderbird 收发信件软体) 等。 现在使用者想要接触 Linux 其实真的越来越简单了，如果不要架设伺服器，那么 Linux 桌面的使用与 Windows 系统可以说是一模一样的！不需要学习也能够入门哩！ ^_^

那么你知道 X Server / X client / window manager 的关系了吗？我们举 CentOS 预设的 GNOME 为例好了， 由于我们要在本机端启动 X Window system ，因此，在我们的 CentOS 主机上面必须要有 Xorg 的 X server 核心， 这样才能够提供荧幕的绘制啊～然后为了让视窗管理更方便，于是就加装了 GNOME 这个计划的 window manager ， 然后为了让自己的使用更方便，于是就在 GNOME 上面加上更多的视窗应用软体，包括输入法等等的， 最后就建构出我们的 X Window System 啰～ ^_^！所以你也会知道，X server/X client/Window Manager 是同时存在于我们一部 Linux 主机上头的啦！

  • Display Manager：提供登入需求

谈完了上述的资料后，我们得要了解一下，那么我如何取得 X Window 的控制？在本机的文字介面底下你可以输入 startx 来启动 X 系统，此时由于你已经登入系统了，因此不需要重新登入即可取得 X 环境。但如果是 runlevel 5 的环境呢？你会发现在 tty7 的地方有个可以让你使用图形介面登入 (输入帐号密码) 的咚咚，那个是啥？ 是 X Server/X client 还是什么的？其实那是个 Display Manager 啦！这个 display manager 最大的任务就是提供登入的环境， 并且载入使用者选择的 Window Manager 与语系等资料喔！

几乎所有的大型视窗管理员专案计划都会提供 display manager 的，在 CentOS 上面我们主要利用的是 GNOME 的 GNOME Display Manager (gdm) 这支程式来提供 tty7 的图形介面登入喔！至于登入后取得的视窗管理员， 则可以在 gdm 上面进行选择的！我们在第五章介绍的登入环境， 那个环境其实就是 gdm 提供的啦！再回去参考看看图示吧！ ^_^！所以说，并非 gdm 只能提供 GNOME 的登入而已喔！

小标题的图示 X Window 的启动流程

现在我们知道要启动 X Window System 时，必须要先启动管理硬体与绘图的 X Server ，然后才载入 X Client 。 基本上，目前都是使用 Window Manager 来管理视窗介面风格的。那么如何取得这样的视窗系统呢？ 你可以透过登入本机的文字介面后，输入 startx 来启动 X 视窗；也能够透过 display manager (如果有启动 runlevel 5) 提供的登入画面，输入你的帐号密码来登入与取得 X 视窗的！

问题是，你的 X server 设定档为何？如何修改解析度与显示器？你能不能自己设定预设启动的视窗管理员？ 如何设定预设的使用者环境 (与 X client 有关) 等等的，这些资料都需要透过了解 X 的启动流程才能得知！ 所以，底下我们就来谈谈如何启动 X 的流程吧！ ^_^

  • 在文字介面启动 X ：透过 startx 指令

我们都知道 Linux 是个多人多工的作业系统，所以啦，X 视窗也是可以根据不同的使用者而有不同的设定！ 这也就是说，每个用户启动 X 时， X server 的解析度、启动 X client 的相关软体及 Window Manager 的选择可能都不一样！ 但是，如果你是首次登入 X 呢？也就是说，你自己还没有建立自己的专属 X 画面时，系统又是从哪里给你这个 X 预设画面呢？而如果你已经设定好相关的资讯，这些资讯又是存放于何处呢？

事实上，当你在纯文字介面且并没有启动 X 视窗的情况下来输入 startx 时，这个 startx 的作用就是在帮你设定好上头提到的这些动作啰！ startx 其实是一个 shell script ，他是一个比较亲和的程式，会主动的帮忙使用者建立起他们的 X 所需要引用的设定档而已。你可以自行研究一下 startx 这个 script 的内容，鸟哥在这里仅就 startx 的作用作个介绍。

startx 最重要的任务就是找出使用者或者是系统预设的 X server 与 X client 的设定档，而使用者也能够使用 startx 外接参数来取代设定档的内容。这个意思是说：startx 可以直接启动，也能够外接参数，例如底下格式的启动方式：

[root@www ~]# startx [X client 参数] -- [X server 参数]

# 范例：以色彩深度为 16 bit 启动 X
[root@www ~]# startx  --  -depth 16

startx 后面接的参数以两个减号‘--’隔开，前面的是 X Client 的设定，后面的是 X Server 的设定。 上面的范例是让 X server 以色彩深度 16 bit 色 (亦即每一像素占用 16 bit ，也就是 65536 色) 显示， 因为色彩深度是与 X Server 有关的，所以参数当然是写在 -- 后面啰，于是就成了上面的模样！

你会发现，鸟哥上面谈到的 startx 都是提到如何找出 X server / X client 的设定值而已！ 没错，事实上启动 X 的是 xinit 这支程式， startx 仅是在帮忙找出设定值而已！那么 startx 找到的设定值可用顺序为何呢？基本上是这样的：

  • X server 的参数方面：
    1. 使用 startx 后面接的参数；
    2. 若无参数，则找寻使用者家目录的档案，亦即 ~/.xserverrc
    3. 若无上述两者，则以 /etc/X11/xinit/xserverrc
    4. 若无上述三者，则单纯执行 /usr/bin/X (此即 X server 执行档)

  • X client 的参数方面：
    1. 使用 startx 后面接的参数；
    2. 若无参数，则找寻使用者家目录的档案，亦即 ~/.xinitrc
    3. 若无上述两者，则以 /etc/X11/xinit/xinitrc
    4. 若无上述三者，则单纯执行 xterm (此为 X 底下的终端机软体)

根据上述的流程找到启动 X 时所需要的 X server / X client 的参数，接下来 startx 会去呼叫 xinit 这支程式来启动我们所需要的 X 视窗系统整体喔！接下来当然就是要谈谈 xinit 啰～

  • 由 startx 呼叫执行的 xinit

事实上，当 startx 找到需要的设定值后，就呼叫 xinit 实际启动 X 的。他的语法是：

[root@www ~]# xinit [client option] -- [server or display option]

那个 client option 与 server option 如何下达呢？其实那两个咚咚就是由刚刚 startx 去找出来的啦！ 在我们透过 startx 找到适当的 xinitrc 与 xserverrc 后，就交给 xinit 来执行。 在预设的情况下 (使用者尚未有 ~/.xinitrc 等档案时)，你输入 startx ， 就等于进行 xinit /etc/X11/xinit/xinitrc -- /etc/X11/xinit/xserverrc 这个指令一般！但由于 xserverrc 也不存在，参考上一小节的参数搜寻顺序， 因此实际上的指令是：xinit /etc/X11/xinit/xinitrc -- /usr/bin/X，这样了了吗？

那为什么不要直接执行 xinit 而是使用 startx 来呼叫 xinit 呢？这是因为我们必须要取得一些参数嘛！ startx 可以帮我们快速的找到这些参数而不必手动输入的。因为单纯只是执行 xinit 的时候，系统的预设 X Client 与 X Server 的内容是这样的：(注3)

xinit xterm  -geometry  +1+1  -n  login  -display  :0 --  X  :0

在 X client 方面：那个 xterm 是 X 视窗底下的虚拟终端机，后面接的参数则是这个终端机的位置与登入与否。 最后面会接一个‘ -display :0 ’表示这个虚拟终端机是启动在‘第 :0 号的 X 显示介面’的意思。至于 X Server 方面， 而我们启动的 X server 程式就是 X 啦！其实 X 就是 Xorg 的连结档，亦即是 X Server 的主程式啰！ 所以我们启动 X 还挺简单的～直接执行 X 而已，同时还指定 X 启动在第 :0 个 X 显示介面。 如果单纯以上面的内容来启动你的 X 系统时，你就会发现 tty7 有画面了！只是.....很丑～因为我们还没有启动 window manager 啊！

从上面的说明我们可以知道， xinit 主要在启动 X server 与载入 X client ，但这个 xinit 所需要的参数则是由 startx 去帮忙找寻的。因此，最重要的当然就是 startx 找到的那些参数啦！ 所以呢，重点当然就是 /etc/X11/xinit/ 目录下的 xinitrc 与 xserverrc 这两个档案的内容是啥啰～ 虽然 xserverrc 预设是不存在的。底下我们就分别来谈一谈这两个档案的主要内容与启动的方式～

  • 启动 X server 的档案： xserverrc

X 视窗最先需要启动的就是 X server 啊，那 X server 启动的脚本与参数是透过 /etc/X11/xinit/ 里面的 xserverrc 。不过我们的 CentOS 5.x 根本就没有 xserverrc 这个档案啊！ 那使用者家目录目前也没有 ~/.xserverrc ，这个时候系统会怎么做呢？其实就是执行 /usr/bin/X 这个指令啊！ 这个指令也是系统最原始的 X server 执行档啰。

在启动 X Server 时，Xorg 会去读取 /etc/X11/xorg.conf 这个设定档。针对这个设定档的内容， 我们会在下个小节介绍。如果一切顺利，那么 X 就会顺利的在 tty7 的环境中启动了 X 。 单纯的 X 启动时，你只会看到画面一片漆黑，然后中心有个滑鼠的游标而已～

由前一小节的说明中，你可以发现到其实 X 启动的时候还可以指定启动的介面喔！那就是 :0 这个参数，这是啥？ 事实上我们的 Linux 可以‘同时启动多个 X’喔！第一个 X 的画面会在 :0 亦即是 tty7 ，第二个 X 则是 :1 亦即是 tty8 。 后续还可以有其他的 X 存在的。因此，上一小节我们也有发现， xterm 在载入时，也必须要使用 -display 来说明， 这个 X 应用程式是需要在哪个 X 载入的才行呢！其中比较有趣的是， X server 未注明载入的介面时，预设是使用 :0 ～ 但是 X client 未注明时，则无法执行喔！

启动了 X server 后，接下来就是载入 X client 到这个 X server 上面啦！

  • 启动 X Client 的档案： xinitrc

假设你的家目录并没有 ~/.xinitrc ，则此时 X Client 会以 /etc/X11/xinit/xinitrc 来作为启动 X Client 的预设脚本。xinitrc 这个档案会将很多其他的档案参数引进来， 包括 /etc/X11/xinit/xinitrc-common 与 /etc/X11/xinit/Xclients 还有 /etc/sysconfig/desktop 。你可以参考 xinitrc 后去搜寻各个档案来了解彼此的关系。

不过分析到最后，其实最终就是载入 KDE 或者是 GNOME 而已。你也可以发现最终在 XClient 档案当中会有两个指令的搜寻， 包括 startkde 与 gnome-session 这两个，这也是 CentOS 预设会提供的两个主要的 Window Manager 啰。 而你也可以透过修改 /etc/sysconfig/desktop 内的 DESKTOP=GNOME 或 DESKTOP=KDE 来决定预设使用哪个视窗管理员的。 如果你并没有安装这两个大家伙，那么 X 就会去使用阳春的 twm 这个视窗管理员来管理你的环境啰。

Tips:
不论怎么说，鸟哥还是希望大家可以透过解析 startx 这个 script 的内容去找到每个档案， 再根据分析每个档案来找到您 distributions 上面的 X 相关档案～ 毕竟每个版本的 Linux 还是有所差异的～ 		鸟哥的图示

另外，如果有特殊需求，你当然可以自订 X client 的参数！这就得要修改你家目录下的 ~/.xinitrc 这个档案啰。 不过要注意的是，如果你的 .xinitrc 设定档里面有启动的 x client 很多的时候，千万注意将除了最后一个 window manager 或 X Client 之外，都放到背景里面去执行啊！举例来说，像底下这样：

       xclock -geometry 100x100-5+5 &
       xterm -geometry 80x50-50+150 &
       exec /usr/bin/twm

意思就是说，我启动了 X ，并且同时启动 xclock / xterm / twm 这三个 X clients 喔！ 如此一来，你的 X 就有这三个咚咚可以使用了！如果忘记加上 & 的符号，那就..... 会让系统等待啊，而无法一次就登入 X 呢！

  • X 启动的埠口

好了，根据上面的说明，我们知道要在文字介面底下启动 X 时，直接使用 startx 来找到 X server 与 X client 的参数或设定档， 然后再呼叫 xinit 来启动 X 视窗系统。xinit 先载入 X server 到预设的 :0 这个显示介面 (预设在 tty7)，然后再载入 X client 到这个 X 显示介面上。而 X client 通常就是 GNOME 或 KDE ，这两个设定也能够在 /etc/sysconfig/desktop 里面作好设定。最后我们想要了解的是，既然 X 是可以跨网路的，那 X 启动的埠口是几号？

其实，CentOS 由于考虑 X 视窗是在本机上面运作，因此将埠口改为插槽档 (socket) 了，因此你无法观察到 X 启动的埠口的。事实上， X server 应该是要启动一个 port 6000 来与 X client 进行沟通的！ 由于系统上面也可能有多个 X 存在，因此我们就会有 port 6001, port 6002... 等等。这也就是说：

X 视窗系统 | 显示介面号码 | 预设终端机 | 网路监听埠口
第一个 X | hostname:0 | tty7 | port 6000
第二个 X | hostname:1 | tty8 | port 6001

在 X Window System 的环境下，我们称 port 6000 为第 0 个显示介面，亦即为 hostname:0 ， 那个主机名称通常可以不写，所以就成了 :0 即可。在预设的情况下，第一个启动的 X (不论是启动在第几个 port number) 是在 tty7 ，亦即按下 [ctrl]+[Alt]+[F7] 那个画面。 而起动的第二个 X (注意到了吧！可以有多个 X 同时启动在您的系统上呢) 则预设在 tty8 亦即 [ctrl]+[Alt]+[F8] 那个画面呢！很神奇吧！ ^_^

如前所述，因为主机上的 X 可能有多个同时存在，因此，当我们在启动 X Server / Client 时， 应该都要注明该 X Server / Client 主要是提供或接受来自哪个 display 的 port number 才行。

小标题的图示 X 启动流程测试

好了，我们可以针对 X Server 与 X client 的架构来做个简单的测试喔！ 由于鸟哥不知道你到底有没有启动过 X ，因此底下鸟哥将这个练习指定于第二个 X ，亦即是 :1 这个显示位置来显示喔！ 而且，底下的指令都是在 tty1 的地方执行的，至于底下的画面则是在 tty8 的地方展现。 因此，请自行切换 tty1 下达指令与 tty8 查阅结果啰！(如果是 CentOS 之类的 Red Hat 系统，请务必要启动 xfs 这个服务喔！)

1. 先来启动第一个 X 在 :1 画面中：
[root@www ~]# X :1 &
单纯启动 X server的情况
图 1.4.1 、 单纯启动 X server的情况

上述的 X 是大写，那个 :1 是写在一起的，至于 & 则是放到背景去执行。此时系统会主动的跳到第二个图形介面终端机，亦即 tty8 上喔！所以如果一切顺利的话，你应该可以看到一个 X 的滑鼠游标可以让你移动了(如上图所示)。 该画面就是 X Server 启动的画面啰！丑丑的，而且没有什么 client 可以用啊！ 接下来，请按下 [ctrl]+[alt]+[F1] 回到刚刚下达指令的终端机：

2. 输入数个可以在 X 当中执行的虚拟终端机
[root@www ~]# xterm -display :1  &
[root@www ~]# xterm -display :1  &
在 X 上面启动 xterm 终端机显示的结果
图 1.4.2 、 在 X 上面启动 xterm 终端机显示的结果

那个 xterm 是必须要在 X 底下才能够执行的终端机介面。加入的参数 -display 则是指出这个 xterm 要在那个 display 使用的。这两个指令请不要一次下完！先执行一次，然后按下 [ctrl]+[alt]+[F8] 去到 X 画面中，你会发现多了一个终端机啰～ 不过，可惜的是，你无法看到终端机的标题、也无法移动终端机，当然也无法调整终端机的大小啊！我们回到刚刚的 tty1 然后再次下达 xterm 指令，理论上应该多一个终端机，去到 tty8 查阅一下。唉～没有多出一个终端机啊？ 这是因为两个终端机重叠了～我们又无法移动终端机，所以只看到一个。 接下来，请再次回到 tty1 去下达指令吧！

3. 在输入不同的 X client 观察观察，分别去到 tty8 观察喔！
[root@www ~]# xclock -display :1  &
[root@www ~]# xeyes -display :1  &
分别启动 xclock 时钟与 xeyes 眼睛的结果
图 1.4.3 、 分别启动 xclock 时钟与 xeyes 眼睛的结果

跟前面一样的，我们又多执行了两个 X client ，其中 xclock 会显示时钟，而 xeyes 则是会出现一双大眼睛来盯着游标！ 你可以移动一下游标就可以发现眼睛的焦聚会跑啊 ^_^！不过，目前的四个 X client 通通不能够移动与放大缩小！ 如此一来，你怎么在 xterm 底下下达指令啊？当然就很困扰～所以让我们来载入最阳春的视窗管理员吧！

4. 输入可以管理的 window manager
[root@www ~]# twm -display :1  &
视窗管理员 twm 的功能显示
图 1.4.4 、 视窗管理员 twm 的功能显示

回到 tty1 后，用最简单的 twm 这个视窗管理员来管理我们的 X 吧！输入之后，去到 tty8 看看，用滑鼠移动一下终端机看看？可以移动了吧？也可以缩小放大视窗啰～同时也出现了标题提示啰～也看到两个终端机啦！ 现在终于知道视窗管理员的重要性了吧？ ^_^！在黑荧幕地方按下滑鼠右键，就会出现类似上面画面最右边的选单， 你就可以进行额外的管理啰～玩玩看先！

5. 将所有刚刚建立的 X 相关工作全部杀掉！
[root@www ~]# kill %6
[root@www ~]# kill %5
[root@www ~]# kill %4
[root@www ~]# kill %3
[root@www ~]# kill %2
[root@www ~]# kill %1

很有趣的一个小实验吧～透过这个实验，你应该会对 X server 与 Window manager 及 tty7 以后的终端介面使用方式有比较清楚的了解～加油！

小标题的图示 我是否需要启用 X Window System

谈了这么多 X 视窗系统方面的资讯后，再来聊聊，那么你的 Linux 主机是否需要预设就启动 X 视窗呢？ 一般来说，如果你的 Linux 主机定位为网路伺服器的话，那么由于 Linux 里面的主要服务的设定档都是纯文字的格式档案， 相当的容易设定的，所以啊，根本就是不需要 X Window 存在呢！因为 X Window 仅是 Linux 系统内的一个软体而已啊！

但是万一你的 Linux 主机是用来作为你的桌上电脑用的，那么 X Window 对你而言，就是相当重要的一个咚咚了！因为我们日常使用的办公室软体，都需要使用到 X Window 图形的功能呢！此外，以鸟哥的例子来说，俺之前接触到的数值分析模式，需要利用图形处理软体来将资料读取出来， 所以在那部 Linux 主机上面，我一定需要 X Window 的。

回归到主题上面，除了主机的用途决定你是否需要启用 X Window 之外， 主机的‘配备’也是你必须要考虑的一项决定性因素。因为 X Window 如果要美观，可能需要功能较为强大的 KDE 或 GNOME 等视窗管理员的协助，但是这两个庞然大物对于系统的要求又很高，除了 CPU 等级要够，RAM 要足之外，显示卡的等级也不能太差～所以，早期的主机可能对于 X Window 就没有办法具有很好的执行效率了。

也就是说，你如果想要玩 X Window 的话，特别需要考虑到这两点：

  • 稳定性：

    X Window 仅是 Linux 上面的一个软体，虽然目前的 X window 已经整合得相当好了，但任何程式的设计都或多或少会有些臭虫， X 当然也不例外。此外，在你的 Linux 伺服器上面启用 X 系统的话，自然多一组程序的启用 (X Window 会启动多个程序来执行各项任务) ，系统的不确定性当然可能会增加一些。 因此，鸟哥不是很建议对 Internet 开放的伺服器启动 X Window 的啦！

  • 效能：

    无论怎么说，程式在跑总是需要系统资源的，所以，多启用了 X 就会造成一些系统资源的损耗。 此外，上面也稍稍提到，某些 X 的软体是相当耗费系统资源的呢！所以，启动 X 可能会让你的可用系统资源 (尤其是记忆体) 降低很多，可能会造成系统效能较低落的问题。
Tips:
鸟哥刚开始接触 Linux (大约是在 1999 年左右)时，由于不熟，通常都是预设给他启用 X Window 在我的主机上面的。 不过，那个时候的图形介面与 Linux kernel 的整合度比较差， 老是挂点去，是常常造成主机上面的网路服务无法顺畅的原因之一呢！ 		鸟哥的图示

就鸟哥的使用经验来看， GNOME 速度稍微快一点， KDE 的介面感觉比较具有亲和力！不过，总体而言， 这个 X Window System 的速度其实并不是那么棒！如果你有其他图形介面的需求时，可以使用 yum 去安装一下 XFCE 这一套，XFCE 是比较轻量级的视窗管理员，据说使用上速度比 GNOME 还快些。 最近很火红的 Ubuntu 的分支之一 Xubuntu 据说就是使用这套视窗管理员喔！试看看吧！ ^_^

大标题的图示 X Server 设定档解析与设定

从前面的说明来看，我们知道一个 X 视窗系统能不能成功启动，其实与 X Server 有很大的关系的。因为 X Server 负责的是整个画面的描绘，所以没有成功启动 X Server 的话，即使有启动 X Client 也无法将图样显示出来啊。所以，底下我们就针对 X Server 的设定档来做个简单的说明，好让大家可以成功的启动 X Window System 啊。

基本上， X Server 管理的是显示卡、荧幕解析度、滑鼠按键对应等等，尤其是显示卡晶片的认识，真是重要啊。 此外，还有显示的字体也是 X Server 管理的一环。基本上，X server 的设定档都是预设放置在 /etc/X11 目录下，而相关的显示模组或上面提到的总总模组，则主要放置在 /usr/lib/xorg/modules 底下。比较重要的是字型档与晶片组，她们主要放置在:

  • 提供的荧幕字型: /usr/share/X11/fonts/
  • 显示卡的晶片组: /usr/lib/xorg/modules/drivers/

在 CentOS 底下，我们可以透过 chkfontpath 这个指令来取得目前系统有的字型档案目录。 这些都要透过一个统一的设定档来规范，那就是 X server 的设定档啦。这个设定档的档名就是 /etc/X11/xorg.conf 喔！

小标题的图示 解析 xorg.conf 设定

如同前几个小节谈到的，在 Xorg 基金会里面的 X11 版本为 X11R7.xx ，那如果你想要知道到底你用的 X Server 版本是第几版，可以使用 X 指令来检查喔！(你必须以 root 的身分执行下列指令)

[root@www ~]# X -version
X Window System Version 7.1.1
Release Date: 12 May 2006
X Protocol Version 11, Revision 0, Release 7.1.1
Build Operating System: Linux 2.6.18-53.1.14.el5PAE i686 Red Hat, Inc.
Current Operating System: Linux localhost.localdomain 2.6.18-128.1.14.el5 #1
SMP Wed Jun 17 06:40:54 EDT 2009 i686
Build Date: 21 January 2009
Build ID: xorg-x11-server 1.1.1-48.52.el5
        Before reporting problems, check http://wiki.x.org
        to make sure that you have the latest version.
Module Loader present

由上面的几个关键字我们可以知道，目前鸟哥的这部测试机使用的 X server 是 Xorg 计划所提供的 X11R7 版， 若有问题则可以到 http://wiki.x.org 去查询～因为是 Xorg 这个 X server ，因此我们的设定档档名为 /etc/X11/xorg.conf 这一个哩。所以，理解这个档案的内容对于 X server 的功能来说，是很重要的。

注意一下，在修改这个档案之前，务必将这个档案给她备份下来，免的改错了什么东西导致连 X server 都无法启动的问题啊。这个档案的内容是分成数个段落的，每个段落以 Section 开始，以 EndSection 结束， 里面含有该 Section (段落) 的相关设定值，例如:

Section  "section name"
…… <== 与这个 section name 有关的设定项目
……
EndSection

至于常见的 section name 主要有:

  1. Module: 被载入到 X Server 当中的模组 (某些功能的驱动程式)；
  2. InputDevice: 包括输入的 1. 键盘的格式 2. 滑鼠的格式，以及其他相关输入设备；
  3. Files: 设定字型所在的目录位置等；
  4. Monitor: 监视器的格式， 主要是设定水平、垂直的更新频率，与硬体有关；
  5. Device: 这个重要，就是显示卡晶片组的相关设定了；
  6. Screen: 这个是在荧幕上显示的相关解析度与色彩深度的设定项目，与显示的行为有关；
  7. ServerLayout: 上述的每个项目都可以重覆设定，这里则是此一 X server 要取用的哪个项目值的设定啰。

好了，直接来看看这个档案的内容吧！这个档案预设的情况是取消很多设定值的，所以你的设定档可能不会看到这么多的设定项目。 不要紧的，后续的章节会交代如何设定这些项目的喔！

[root@www ~]# cd /etc/X11
[root@www X11]# cp -a xorg.conf xorg.conf.20090713  <== 有备份有保佑
[root@www X11]# vim xorg.conf
Section "Module"
        Load  "dbe"
        Load  "extmod"
        Load  "record"
        Load  "dri"
        Load  "xtrap"
        Load  "glx"
        Load  "vnc"
EndSection
# 上面这些模组是 X Server 启动时，希望能够额外获得的相关支援的模组。
# 关于更多模组可以搜寻一下 /usr/lib/xorg/modules/extensions/ 这个目录

Section "InputDevice"
        Identifier  "Keyboard0"
        Driver      "kbd"
        Option      "XkbModel" "pc105"
        Option      "XkbLayout" "us"  <==注意，是 us 美式键盘对应
EndSection
# 这个玩意儿是键盘的对应设定资料，重点在于 XkbLayout 那一项，
# 如果没有问题的话，我们台湾地区应该都是使用美式键盘对应按钮的。
# 特别注意到 Identifier (定义) 那一项，那个是在说明，我这个键盘的设定档，
# 被定义为名称是 Keyboard0 的意思，这个名称最后会被用于 ServerLayout 中

Section "InputDevice"
        Identifier  "Mouse0"
        Driver      "mouse"
        Option      "Protocol" "auto"
        Option      "Device" "/dev/input/mice"
        Option      "ZAxisMapping" "4 5 6 7" <==滚轮支援
EndSection
# 这个则主要在设定滑鼠功能，重点在那个 Protocol 项目，
# 那个是可以指定滑鼠介面的设定值，我这里使用的是自动侦测！不论是 USB/PS2。

Section "Files"
        RgbPath      "/usr/share/X11/rgb"
        ModulePath   "/usr/lib/xorg/modules"
        FontPath     "unix/:7100"  <==使用另外的服务来提供字型定义
        FontPath     "built-ins"
EndSection
# 我们的 X Server 很重要的一点就是必须要提供字型，这个 Files
# 的项目就是在设定字型，当然啦，你的主机必须要有字型档才行。一般字型档案在：
# /usr/share/X11/fonts/ 目录中。至于那个 Rgb 是与色彩有关的项目。
# 相关的字型说明我们会在下一小节的 xfs 在跟大家报告。

Section "Monitor"
        Identifier   "Monitor0"
        VendorName   "Monitor Vendor"
        ModelName    "Monitor Model"
        HorizSync    30.0 - 80.0
        VertRefresh  50.0 - 100.0
EndSection
# 荧幕监视器的设定仅有一个地方要注意，那就是垂直与水平的更新频率。
# 在上面的 HorizSync 与 VerRefresh 的设定上，要注意，不要设定太高，
# 这个玩意儿与实际的监视器功能有关，请查询你的监视器手册说明来设定吧！
# 传统 CRT 荧幕设定太高的话，据说会让 monitor 烧毁呢，要很注意啊。

Section "Device"   <==显示卡的驱动程式项目
        Identifier  "Card0"
        Driver      "vesa"  <==实际的驱动程式喔！
        VendorName  "Unknown Vendor"
        BoardName   "Unknown Board"
        BusID       "PCI:0:2:0"
EndSection
# 这地方重要了，这就是显示卡的晶片模组载入的设定区域。由于鸟哥使用 Virtualbox
# 模拟器模拟这个测试机，因此这个地方显示的驱动程式为通用的 vesa 模组。
# 更多的显示晶片模组可以参考 /usr/lib/xorg/modules/drivers/

Section "Screen"    <==与显示的画面有关，解析度与色彩深度
        Identifier "Screen0"
        Device     "Card0"     <==使用哪个显示卡来提供显示
        Monitor    "Monitor0"  <==使用哪个监视器
        SubSection "Display"   <==此阶段的附属设定项目
                Viewport   0 0
                Depth     16   <==就是色彩深度
        Modes    "1024x768" "800x600" "640x480" <==解析度
        EndSubSection
        SubSection "Display"
                Viewport   0 0
                Depth     24
        Modes    "1024x768" "800x600"
        EndSubSection
EndSection
# Monitor 与实际的显示器有关，而 Screen 则是与显示的画面解析度、色彩深度有关。
# 我们可以设定多个解析度，实际应用时可以让使用者自行选择想要的解析度来呈现。
# 不过，为了避免困扰，鸟哥通常只指定一到两个解析度而已。

Section "ServerLayout"   <==实际选用的设定值
        Identifier     "X.org Configured"
        Screen      0  "Screen0" 0 0              <==解析度等
        InputDevice    "Mouse0" "CorePointer"     <==滑鼠
        InputDevice    "Keyboard0" "CoreKeyboard" <==键盘
EndSection
# 我们上面设定了这么多的项目之后，最后整个 X Server 要用的项目，
# 就通通一骨脑的给他写入这里就是了，包括键盘、滑鼠以及显示介面啊。
# 其中 screen 的部分还牵涉到显示卡、监视器荧幕等设定值呢！

上面设定完毕之后，就等于将整个 X Server 设定妥当了，很简单吧。 如果你想要更新其他的例如显示晶片的模组的话，就得要去硬体开发商的网站下载原始档来编译才行。 设定完毕之后，你就可以启动 X Server 试看看啰。基本上，如果你的 Files 那个项目用的是直接写入字型的路径， 那就不需要启动 XFS (X Font Server)，如果是使用 font server 时，就要先启动 xfs ：

# 1. 启动 xfs 服务：
[root@www ~]# /etc/init.d/xfs start

# 2. 测试 X server 的设定档是否正常：
[root@www ~]# startx  <==直接在 runlevel 3 启动 X 看看
[root@www ~]# X :1    <==在 tty8 单独启动 X server 看看

当然，你也可以利用 init 5 这个指令直接切换到图形介面的登入来试看看啰。

Tips:
经由讨论区网友的说明，如果你发现明明有捉到显示卡驱动程式却老是无法顺利启动 X 的话，可以尝试去官网取得驱动程式来安装， 也能够将‘Device’阶段的‘Driver’修改成预设的‘Driver "vesa"’，使用该驱动程式来暂时启动 X 内的显示卡喔！ 		鸟哥的图示
小标题的图示 X Font Server (XFS) 与加入额外中文字形

与 X 有关的设定档主要是 /etc/X11/xorg.conf 这个主设定档，但是刚刚上头解析这个档案时，在 Files 的部分我们还提到了 X Font Server (XFS) 这个服务喔！这个是啥咚咚？这个服务的目的在提供 X server 字型库啦！ 也就是说， X server 所使用的字型其实是 XFS 这个服务所提供的，因此没有启动 XFS 服务时，你的 X server 是无法顺利启动的喔！所以，我们当然就来瞧瞧这玩意儿的功能啰！

这个 XFS 的主设定档在 /etc/X11/fs/config ，而字型档则在 /usr/share/X11/fonts/ ，这里再次给他强调一下。 至于启动的脚本则在 /etc/init.d/xfs 啰！好，那我们就先来瞧瞧主设定档的内容是怎样的设定吧！

[root@www ~]# vi /etc/X11/fs/config
client-limit = 10  <==最多允许几个 X server 向我要求字型(因为跨网路)
clone-self = on    <==与效能有关，若 xfs 达到限制值，启动新的 xfs
catalogue = /usr/share/X11/fonts/misc:unscaled,
        /usr/share/X11/fonts/75dpi:unscaled,
        /usr/share/X11/fonts/100dpi:unscaled,
        /usr/share/X11/fonts/Type1,
        /usr/share/X11/fonts/TTF,
        /usr/share/fonts/default/Type1,
# 上面这些咚咚，就是字型档案的所在！如果你有新字型，可以放置在该目录。

default-point-size = 120            <==预设字型大小，单位为 1/10 点字 (point)
default-resolutions = 75,75,100,100 <==这个则是显示的字型像素 (pixel)
deferglyphs = 16                    <==延迟显示的字型，此为 16 bits 字型
use-syslog = on                     <==启动支援错误登录
no-listen = tcp                     <==启动 xfs 于 socket 而非 TCP

上面这个档案的设定重点在 catalogue 那个设定项目当中。你可以使用 chkfontpath 这个指令来列出目前支援的字型档案，也可以直接修改呢！

另外，虽然目前的 CentOS 已经是支援多国语系了，因此你可以直接在安装完毕后就看到中文， 不过预设的中文字形可能让你不太满意～此时，你可以选择额外的中文字形显示喔。比较有名的中文字形除了预设提供的文鼎字型外， 还有一种台北字型 (taipeifonts)，不过这种字形是 Big5 编码的，因此预设并没有在你的字型支援之中 (因为目前大多使用万国码来显示中文了)。如果你想要测试一下这种字形，除了自行下载字型档之外， 我们可以使用 CentOS 提供的软体来处理喔！看看底下的作法吧：

# 1. 先安装中文字形软体，亦即 fonts-chinese 这个软体名
[root@www ~]# yum install fonts-chinese

# 2. 查阅 taipei 字型的所在目录位置：
[root@www ~]# rpm -ql fonts-chinese | grep taipei
/usr/share/fonts/chinese/misc/taipei16.pcf.gz  <==重点在目录！
/usr/share/fonts/chinese/misc/taipei20.pcf.gz
/usr/share/fonts/chinese/misc/taipei24.pcf.gz

# 3. 建立字型档的目录架构
[root@www ~]# cd /usr/share/fonts/chinese/misc
[root@www ~]# mkfontdir
# 这个指令在建置 fonts.dir 这个档案，提供字型档案目录的说明。

# 4. 将上述的目录加入 xfs 的支援之中：
[root@www ~]# chkfontpath -a /usr/share/fonts/chinese/misc/
[root@www ~]# chkfontpath
....(前面省略)....
/usr/share/fonts/chinese/misc:unscaled
/usr/share/fonts/chinese/misc  <==这两行会被新增出来！
[root@www ~]# /etc/init.d/xfs restart

# 5. 在 X window 底下启动终端机，测试一下有没有捉到该字型？
[root@www ~]# xlsofnts | grep taipei
# 如果顺利的话，你会看到有几个 taipeiXX 的字样在荧幕上出现！

这个时候的 X server 已经有新支援的中文字形了，很简单吧！不过如果你想要让 X client 可以使用额外的字型的话，还得要使用 fontconfig 的软体提供的 fc-cache 来建立字型快取档才行 (注4)！

  • 让视窗管理员可以使用额外的字型

如果想要使用额外的字型的话，你可以自行取得某些字型来处理的。鸟哥这边从 Windows 取得三个档案来作为测试，这边得注明一下是纯粹的测试，测试完毕后档案就给她拿掉了， 并没有持续使用喔！并没有想要违法的意思啦～大家参考看看就好了。这三个档案分别是 kaiu.ttf simsun.ttc times.ttf，代表的是中楷体、明体、times and Romans 三种字体。 那就来看看如何增加字型吧！(假设上述的三个字体档是放置在 /root 中)

# 1. 将上述的三个档案放置到系统设定目录，亦即底下的目录中：
[root@www ~]# cd /usr/share/fonts/
[root@www ~]# mkdir windows
[root@www ~]# cp /root/*.tt[fc] /usr/share/fonts/windows

# 2. 使用 fc-cache 将上述的档案加入字型的支援中：
[root@www ~]# fc-cache -f -v
....(前面省略)....
/usr/share/fonts/windows: caching, 4 fonts, 0 dirs
....(中间省略)....
fc-cache: succeeded
# -v 仅是列出目前的字型资料， -f 则是强制重新建立字型快取！

# 3. 透过 fc-list 列出已经被使用的档案看看：
[root@www ~]# fc-list : file  <==找出被快取住的档名
....(前面省略)....
/usr/share/fonts/windows/kaiu.ttf:
/usr/share/fonts/windows/times.ttf:
/usr/share/fonts/windows/simsun.ttc:
....(后面省略)....

透过 fc-cache 以及 fc-list 去确认过字型确实存在后，就能够使用视窗管理员的功能去检查字型档了。 以 GNOME 为例，在‘系统’-->‘偏好设定’-->‘字型’点选后，就会出现可以调整的字型， 接下来你就会发现多出了‘楷体_GB2312、宋体、新宋体’等字体可以选择啰！试看看吧！鸟哥调整成为‘Times and Roman’ 出现如下图的结果呢！参考看看：

中文字形的调整结果
图 2.2.1、中文字形的调整结果
小标题的图示 设定档重建与显示器参数微调

如果你修改 xorg.conf 结果改错了，导致无法顺利的启动 X server 时，偏偏又忘记制作备份档！该如何是好？ 没关系，我们的 Xorg 有提供不错的工具可以处理。同时 CentOS 也有提供相关的设定指令， 那就是在第二十一章提到的 setup 这个指令啦！ 详细的设定请自行前往参考，在这里我们要介绍的是使用 Xorg 重新制作出设定档啦！你可以使用 root 的身份这样执行：

[root@www ~]# Xorg -configure :1

此时 X 会主动的以内建的模组进行系统硬体的探索，并将硬体与字型的侦测结果写入 /root/xorg.conf.new 这个档案里面去，这就是 xorg.conf 的重制结果。不过，这个新建的档案不见得真的能够启动 X server ， 所以我们必须要使用底下的指令来测试一下这个新的设定档是否能够顺利的运作：

[root@www ~]# X -config /root/xorg.conf.new :1

因为鸟哥不知道你到底是在 runlevel 几号，因此上述的测试通通是在 tty8 的终端机上面显示 (display 1)， 这样就能够避免切换到不同的 runlevel 啰～如果一切顺利的话，你就可以将 /root/xorg.conf.new 复制成为 /etc/X11/xorg.conf 覆盖掉修改错误的档案，然后重新启动 X ，嘿嘿！应该就能够顺利的救回来你的 X Window System 啰！

  • 关于荧幕解析度与更新率

有些朋友偶而会这样问：‘我的显示器明明还不错，但是荧幕解析度却永远只能达到 800x600 而已， 这该如何处理？’，荧幕的解析度应该与显示卡相关性不高，而是与显示器的更新频率有关！ 所谓的更新频率，指的是在一段时间内荧幕重新绘制画面的速度。举例来说， 60Hz 的更新频率， 指的是每秒钟画面更新 60 次的意思。那么关于显示器的更新频率该如何调整呢？ 你得先去找到你的显示器的使用说明书 (或者是网站会有规格介绍)，取得最高的更新率后，接下来选择你想要的解析度， 然后透过这个 gtf 的指令功能来调整：

[root@www ~]# gtf 水平像素 垂直像素 更新频率 [-xv]
选项与参数：
水平像素：就是解析度的 X 轴
垂直像素：就是解析度的 Y 轴
更新频率：与显示器有关，一般可以选择 60, 75, 80, 85 等频率
-x      ：使用 Xorg 设定档的模式输出，这是预设值
-v      ：显示侦测的过程

# 1. 使用 1024x768 的解析度，75 Hz 的更新频率来取得显示器内容
[root@www ~]# gtf 1024 768 75 -x
# 1024x768 @ 75.00 Hz (GTF) hsync: 60.15 kHz; pclk: 81.80 MHz
Modeline "1024x768_75.00"  81.80  1024 1080 1192 1360  768 769 772 802  -HSync +Vsync
# 重点是 Modeline 那一行！那行给他抄下来

# 2. 将上述的资料输入 xorg.conf 内的 Monitor 项目中：
[root@www ~]# vim /etc/X11/xorg.conf
Section "Monitor"
    Identifier   "Monitor0"
    VendorName   "Monitor Vendor"
    ModelName    "Monitor Model"
    Modeline "1024x768_75.00"  81.80  1024 1080 1192 1360  768 769 772 802  -HSync +Vsync
EndSection
# 就是新增上述的那行特殊字体部分到 Monitor 的项目中即可。

然后重新启动你的 X ，这样就能够选择新的解析度啰！那如何重新启动 X 呢？两个方法， 一个是‘ init 3 ; init 5 ’从文字模式与图形模式的执行等级去切换，另一个比较简单， 如果原本就是 runlevel 5 的话，那么在 X 的画面中按下‘ [alt] + [crtl] + [backspace] ’三个组合按键， 就能够重新启动 X 视窗啰！

大标题的图示 显示卡驱动程式安装范例

虽然你的 X 视窗系统已经顺利的启动了，也调整到你想要的解析度了，不过在某些场合底下，你想要使用显示卡提供的 3D 加速功能时，却发现 X 提供的预设的驱动程式并不支援！此时真是欲哭无泪啊～那该如何是好？没关系，安装官方网站提供的驱动程式即可！ 目前 (2009) 世界上针对 x86 提供显示卡的厂商最大的应该是 Nvidia / AMD (ATI) / Intel 这三家 (没有照市占率排列)， 所以底下鸟哥就针对这三家的显示卡驱动程式安装，作个简单的介绍吧！

由于硬体驱动程式与核心有关，因此你想要安装这个驱动程式之前，请务必先参考第二十二章与第二十三章的介绍，才能够顺利的编译出显示卡驱动程式喔！ 建议可以直接使用 yum 去安装‘ Development Tools ’这个软体群组以及 kernel-devel 这个软体即可。

小标题的图示 NVidia

虽然 Xorg 已经针对 NVidia 公司的显示卡驱动程式提供了 nv 这个模组，不过这个模组无法提供很多额外的功能。 因此，如果你想要使用新的显示卡功能时，就得要额外安装 NVidia 提供的给 Linux 的驱动程式才行。 你可以这样作的：

  • 下载驱动程式

建议你可以到 NVidia 的官网 (http://www.nvidia.com.tw) 自行去下载最新的驱动程式，你也可以到底下的连结直接查阅给 Linux 用的驱动程式：

  • http://www.nvidia.com.tw/object/unix_tw.html

请自行选择与你的系统相关的环境。鸟哥选择自己的测试机是 Intel Core2 架构，因此选择 Linux AMD64/EM64T 的驱动程式版本，这个版本的驱动程式档名为： NVIDIA-Linux-x86_64-xxx.yy.zz-pkg2.run ，其中的 xxx.yy.z 就是驱动程式的版本号码。我将这个档案放置到 /root家目录中。

  • 开始安装驱动程式

安装过程有点像这样 (档名依照你的环境去下载与执行)：

[root@www ~]# sh NVIDIA-Linux-x86_64-185.18.14-pkg2.run
NVidia 驱动程式安装示意
图 3.1.1、NVidia 驱动程式安装示意

上面说的是授权，你必须要接受 (Accept) 才能继续。

NVidia 驱动程式安装示意
图 3.1.2、NVidia 驱动程式安装示意

我们不预期 NVidia 会帮我们编译好核心模组，因此这里选择 No ，让我们自己编译模组吧！

NVidia 驱动程式安装示意
图 3.1.3、NVidia 驱动程式安装示意

直接按下 OK 来继续下一步即可。

NVidia 驱动程式安装示意
图 3.1.4、NVidia 驱动程式安装示意

开始进行核心模组的编译！这个过程不会太久～

NVidia 驱动程式安装示意
图 3.1.5、NVidia 驱动程式安装示意

是否要安装额外的 OpenGL 函式库？要啊！就选择 Yes 吧！

NVidia 驱动程式安装示意
图 3.1.6、NVidia 驱动程式安装示意

这个时候开始安装显示卡的驱动程式，会花费一段时间喔！然后出现下图：

NVidia 驱动程式安装示意
图 3.1.7、NVidia 驱动程式安装示意

让这支安装程式主动的去修改 xorg.conf 吧！比较轻松愉快！就按下 Yes 即可。

NVidia 驱动程式安装示意
图 3.1.8、NVidia 驱动程式安装示意

最后按下 OK 就结束安装啰！这个时候如果你去查阅一下 /etc/X11/xorg.conf 的内容，会发现 Device 的 Driver 设定会成为 nvidia 而不是原本的 nv 喔！这样就搞定啰！很简单吧！ 而且这个时候你的 /usr/lib64/xorg/modules/drivers 目录内，会多出一个 nvidia_drv.so 的驱动程式档案啰！ 同时这个软体还提供了一支很有用的程式来帮助我们进行驱动程式升级喔！

[root@www ~]# nvidia-installer --update
# 可以进行驱动程式的升级检查喔！

好啰，那你就赶紧试看看新的显示卡晶片的功能吧。而如果有什么疑问的话，查阅一下 /var/log/nvidia 开头的登录档看看吧！ ^_^

小标题的图示 ATI (AMD)

ATI 已经被 AMD 收购了，而 AMD 在近期已经宣布了 ATI 的显示卡驱动程式要开放成为 Open source ， 这代表未来你可以很轻松的就取得 ATI 的显示卡驱动程式而不必要重新安装的。不过，就如同前面提到的， 若你需要某些特殊功能，建议还是手动安装一下官方提供的驱动程式吧！你必须要到 AMD 的网站去下载 ATI 显示卡驱动程式哩！ 你可以到 http://www.amdtaiwan.com.tw/ 选择‘ATI 驱动程式’的连结去选择你的显示卡驱动程式版本，也可以点选底下的连结：

  • http://ati.amd.com/support/driver.html

然后去选择你的作业系统与显示卡的型号来下载。鸟哥使用另一部含有 ATI 显示卡的主机来安装驱动程式， 该主机使用的是 Randon HD 3200 的显示卡晶片，最后下载的档案是： ati-driver-installer-9-6-x86.x86_64.run。 要安装这个驱动程式的方法与 NVidia 的方式很像的，同样的直接执行该档案即可：

[root@www ~]# sh ati-driver-installer-9-6-x86.x86_64.run
ATI 显示卡驱动程式安装示意
图 3.2.1、ATI 显示卡驱动程式安装示意

选择安装吧！

ATI 显示卡驱动程式安装示意
图 3.2.2、ATI 显示卡驱动程式安装示意

这里的目的是让我们确定一下，是否真的是安装在 x86_64 的硬体上面而已！按下 OK 去！

ATI 显示卡驱动程式安装示意
图 3.2.3、ATI 显示卡驱动程式安装示意

看完授权之后，直接给他 Exit 离开授权说明，然后会出现接受与否的字样：

ATI 显示卡驱动程式安装示意
图 3.2.4、ATI 显示卡驱动程式安装示意

要安装啊！所以当然就是 Yes 下去喔！

ATI 显示卡驱动程式安装示意
图 3.2.5、ATI 显示卡驱动程式安装示意

最后选择预设安装即可！不需要使用专家安装啦！这样就安装完毕了！也是非常快速吧！最后就会在 /usr/lib64/xorg/modules/drivers/ 里面出现 fglrx_drv.so 这个新的驱动程式啦！ 与 Nvidia 相同的， ATI 也提供一支名为 aticonfig 的指令来帮忙设定 xorg.conf ，你可以直接输入‘ aticonfig -v ’来看看处理的方式即可。然后你就可以重新启动 X 来看看新的驱动程式功能啰！非常简单吧！

小标题的图示 Intel

老实说，由于 Intel 针对 Linux 的图形介面驱动程式已经开放成为 Open source 了，所以理论上你不需要重新安装 Intel 的显示卡驱动程式的。除非你想要使用比预设的更新的驱动程式，那么才需要重新安装底下的驱动程式。 Intel 对 Linux 的显示卡驱动程式已经有独立的网站在运作，如下的连结就是安装的说明网页：

  • http://intellinuxgraphics.org/install.html

其实 Intel 的显示卡用的地方非常的多喔！因为只要是整合型主机板晶片组，用的是 Intel 的晶片时， 通常都整合了 Intel 的显示卡啰～鸟哥使用的一组 cluster 用的就是 Intel 的晶片，所以啰～ 这家伙也是用的到的啦！

一般来说， Intel 的显示卡都常常会使用 i810 等驱动程式，而不是这个较新的 intel 驱动程式！ 你可以察看一下你系统是否有存在这些档案：

[root@www ~]# locate libdrm
/usr/lib/libdrm.so.2        <==32位元的函式库
/usr/lib/libdrm.so.2.0.0
/usr/lib64/libdrm.so.2      <==64位元放置位置不同！
/usr/lib64/libdrm.so.2.0.0
/usr/lib64/xorg/modules/linux/libdrm.so

[root@www ~]# locate intel | grep xorg
/usr/lib64/xorg/modules/drivers/intel_drv.so
# 上面这个就是 Intel 的显示卡驱动程式了！

呼呼！我们的 CentOS 有提供新的 Intel 显示卡驱动程式啦！所以不需要重新安装说～ 只是可能需要修改 xorg.conf 这个设定档的内容。基本上，要修改的地方有：

[root@www ~]# vi /etc/X11/xorg.conf
Section "Device"
        Identifier  "Videocard0"
        Driver      "intel"  <==原本可能会是使用 i810 喔
EndSection

Section "Module"
        ....(中间省略)....
        Load  "glx"    <==这两个很重要！务必要载入！
        Load  "dri"
        ....(中间省略)....
EndSection

Section "DRI"          <==这三行是新增的！让大家都能使用 DRI
       Mode 0666       <==基本上，就是权限的设定
EndSection

如果一切顺利的话，接下来就是重新启动 X 啰～使用新的 Intel 驱动程式吧！加油啰！

大标题的图示 重点回顾
  • Unix Like 作业系统上面的 GUI 使用的是最初由 MIT 所开发的 X window system，在 1987 释出 X11 版，并于 1994 更改为 X11R6 ，故此 GUI 介面也被称为 X 或 X11
  • X window system 的 X server 最初由 XFree86 计划所开发，后来则由 Xorg 基金会所持续开发；
  • X window system 主要分为 X server 与 X client ，其中 X Server 在管理硬体，而 X Client 则是应用程式。
  • 在运作上，X Client 应用程式会将所想要呈现的画面告知 X Server ，最终由 X server 来将结果透过他所管理的硬体绘制出来！
  • 每一支 X client 都不知道对方的存在，必须要透过特殊的 X client ，称为 Window Manager 的， 来管理各视窗的重叠、移动、最小化等工作。
  • startx 可以侦测 X server / X client 的启动脚本，并呼叫 xinit 来分别执行；
  • X 可以启动多个，各个 X 显示的位置使用 -display 来处理，显示位置为 :0, :1...
  • Xorg 是一个 X server ，设定档位于 /etc/X11/xorg.conf ，里面含有 Module, Files, Monitor, Device 等设定阶段
  • 字型管理为 X server 的重点，目前字型管理可由 xfs 及 fontconfig 来处理

大标题的图示 本章习题
( 要看答案请将滑鼠移动到‘答：’底下的空白处，按下左键圈选空白处即可察看 )
  • 在 X 设定没问题的情况下，你在 Linux 主机如何取得视窗介面？
    如果是在 run level 3 ，可以使用 startx 进入，至于 run level 5 ，则直接进入 tty7 即可使用 display manager 登入 X Window 系统。
  • 利用 startx 可以在 run level 3 的环境下进入 X Window 系统。请问 startx 的主要功能？
    整个 X 视窗系统的重点在启动 X server 并载入 X client ，而执行 X server/X client 呼叫的任务为 xinit ，startx 只是一个较为亲和的脚本程式，可以搜寻系统上面的 X server / X client 设定值， 以提供 xinit 来执行而已。
  • 如何知道你系统当中 X 系统的版本与计划？
    最简单可以利用 root 的身份下达 X -version 即可知道！
  • 要了解为何 X 系统可以允许不同硬体、主机、作业系统之间的沟通，需要知道 X server / X client 的相关知识。 请问 X Server / X client / Window manager 的主要用途功能？
    X Server 主要负责荧幕的绘制，以及周边输入装置如滑鼠、键盘等资料的收集，并回报给 X Client ； X Client 主要负责资料的运算，收到来自 X Server 的资料后，加以运算得到图形的数据，并回传给 X Server， 让 X server 自行绘制图形。至于 Window manager 是一个比较特殊的 X Client ，他可以管理更多控制元素， 最重要的地方还是在于视窗的大小、重叠、移动等等的功能。
  • 如何重新启动 X
    最简单在 X Window System 下，直接按下 [alt]+[ctrl]+[backspace<--] 即可， 也可以 init 3 再 init 5，也可以关闭 X 后，再 startx 启动等等。
  • 试说明 ~/.xinitrc 这个档案的用途？
    当我们要启动 X 时，必须要启动 X Client 软体端。这个 ~/.xinitrc 即是在客制化自己的 X Client ， 你可以在这个档案内输入你自己的 X Client 。若无此档案，则预设以 /etc/X11/xinit/xinitrc 替代。
  • 我在 CentOS 的系统中，预设使用 GNOME 登入 X 。但我想要改以 KDE 登入，该怎么办？
    首先你必须要已经安装 KDE 环境 (参考前一章的 yum grouplist 功能)，然后可以藉由修改 /etc/sysconfig/desktop 内的设定值即可。但如果你不是 root 无法修订该档案时， 亦可以在自己的家目录参考 /etc/X11/xinit/xinitrc 的内容自行制作 ~/.xinitrc 档案来修改！
  • X Server 的 port 预设开放在？
    X port 预设开放在 port 6000 ，而且称此一显示为 :0
  • Linux 主机是否可以有两个以上的 X
    是的！可以！第一个 X 通常在 tty7 ，第二个在 tty8 ，第三个在 tty9 ，依序类推。 第几个是以启动的顺序来定义，并非 :0 , :1 的意思～
  • X Server 的设定档是 xorg.conf，在该档案中， Section Files 干嘛用的？
    相当重要！是设定显示字型用的。而字型一般放置目录在 /usr/lib/xorg/modules/fonts/ 当中。
  • 我发现我的 X 系统键盘所输入的字母老是打不出我所需要的单字，可能原因该如何修订？
    应该是键盘符号对应表跑掉了。可以修改 xorg.conf 档案内， 关于 Keyboard 的 Option XkbLayout 项目，将他改为 us 即可！
  • 当我的系统内有安装 GNOME 及 KDE 两个 X Widnow Manager ，我原本是以 KDE 为预设的 WM， 若想改为 GNOME 时，应该如何修改？
    修改 /etc/sysconfig/desktop 内部，成为 GNOME 即可！
大标题的图示 参考资料与延伸阅读
  • 注1：维基百科对 X Window 的介绍：http://en.wikipedia.org/wiki/X_Window_System
  • 注2：X Server/X client 与网路相关性的参考图示：
    http://en.wikipedia.org/wiki/File:X_client_sever_example.svg
  • 注3：系统的 man page： man xinit 、 man Xorg 、 man startx
  • 注4：一些与中文字型有关的网页连结：
    洪朝贵老师主笔的字型设定：http://www.cyut.edu.tw/~ckhung/b/gnu/font.php
    李果正先生的 GNU/Linux 初探第十六章：http://edt1023.sayya.org/node17.html
    EricCheng 的 fontconfig 软体简介：http://fractal.csie.org/~eric/wiki/Fontconfig
  • X 相关的官方网站： X.org 官方网站 (http://www.x.org/)、 XFree86 官方网站 (http://www.xfree86.org/)
2003/02/12：第一次完成
2005/06/29：将旧的文章移动到 这里 。如果你需要旧版的 xf86config 与相关的工具，则请前往该旧文章查阅！
2005/07/11：经历了许多的时间，将主机的设定档重复改了改，终于完成一些简单的 X 测试！
2006/11/07：经由网友x1215 这一篇的介绍，得知该网站，赶紧去处理！
2009/07/03：将旧版基于 FC4 的版本移动到此处
2009/07/15：奋战好几天，将驱动程式安装加上，同时加入字型管理功能。
2009/07/28：网友 LazyBug Chan 兄热情回报，使用 XFCE 的 Ubuntu 是 Xubuntu 这个分支！感谢回报！
2009/08/07：加入 Window Manger 的全名与连结


鸟哥的 Linux 私房菜 -- 浅谈备份策略

为取得较佳浏览结果，请爱用 firefox 浏览本网页
鸟哥的 Linux 私房菜馆 | Linux 基础文件 | Linux 架站文件 | Linux 企业运用 | 安全管理 | 新手讨论 |

第二十五章、 Linux 备份策略
最近更新日期：2009/09/18
万一不幸你的 Linux 被骇客入侵了、或是你的 Linux 系统由于硬体关系 (不论是天灾还是人祸) 而挂掉了！这个时候，请问如何快速的回复你的系统呢？呵呵！当然啰，如果有备份资料的话， 那么回复系统所花费的时间与成本将降低相当的多！平时最好就养成备份的习惯， 以免突然间的系统损毁造成手足无措！此外，哪些档案最需要备份呢？又，备份是需要完整的备份还是仅备份重要资料即可？ 嗯！确实需要考虑看看呦！

1. 备份要点
    1.1 备份资料的考量
    1.2 哪些 Linux 资料具有备份的意义
    1.3 备份用储存媒体的选择
 2. 备份的种类、频率与工具的选择
    2.1 完整备份之累积备份 (Incremental backup), 使用软体
    2.2 完整备份之差异备份 (Differential backup)
    2.3 关键资料备份
 3. VBird 的备份策略与 scripts
    3.1 每周系统备份的 script
    3.2 每日备份资料的 script
    3.3 远端备援的 script
 4. 灾难复原的考量
5. 重点回顾
6. 本章习题
7. 参考资料与延伸阅读
8. 针对本文的建议：http://phorum.vbird.org/viewtopic.php?t=23896
大标题的图示 备份要点

备份是个很重要的工作，很多人总是在系统损毁的时候才在哀嚎说：‘我的资料啊！天那...！’此时才会发现备份资料的可爱！ 但是备份其实也非常可怕！因为你的重要资料都在备份档里面，如果这个备份被窃取或遗失，其实对你的系统资安影响也非常大！ 同时，备份使用的媒体选择也非常多样，但是各种储存媒体各有其功能与优劣，所以当然得要选择啰！闲话少说，来谈谈备份吧！

小标题的图示 备份资料的考量

老实说，备份是系统损毁时等待救援的救星！因为你需要重新安装系统时， 备份的好坏会影响到你系统复原的进度！不过，我们想先知道的是，系统为什么会损毁啊？是人为的还是怎样产生的啊？ 事实上，系统有可能由于不预期的伤害而导致系统发生错误！ 什么是不预期的伤害呢？这是由于系统可能因为不预期的硬体损坏，例如硬碟坏掉等等，或者是软体问题导致系统出错， 包括人为的操作不当或是其他不明因素等等所致。底下我们就来谈谈系统损坏的情况与为何需要备份吧！

  • 造成系统损毁的问题-硬体问题

基本上，‘电脑是一个相当不可靠的机器’这句话在大部分的时间内还是成立的！ 常常会听到说‘要电脑正常的工作，最重要的是要去拜拜！’嘿嘿！不要笑！这还是真的哩！ 尤其是在日前一些电脑周边硬体的生产良率 (就是将硬体产生出来之后，经过测试， 发现可正常工作的与不能正常工作的硬体总数之比值) 越来越差的情况之下，电脑的不稳定状态实在是越来越严重了！

举个例子来说，鸟哥曾经同时买过同一厂牌的 30GB 硬碟三颗，回来之后经过一个星期，嘿嘿！挂掉了两颗！ 其中一颗是有坏轨，另外一颗是‘完全死掉’，拿去公司要求修理，结果呢？嗯！店家直接拿了一颗新的给我， 害我吓一跳，店家的工程师说‘唉呀！目前这个牌子的良率太差了，所以代理商为了怕麻烦，都会直接拿新的替换给我们啦！’ 要晓得的是，当初那一颗完全死掉的硬碟，是我用来备份我的主机资料的.... 好在当时我将备份的资料放在三四个地方，还好...

一般来说，会造成系统损毁的硬体元件应该要算硬碟吧！因为其他的元件坏掉时，虽然会影响到系统的运作， 不过至少我们的资料还是存在硬碟当中的啊！为了避免这个困扰，于是乎有可备份用的 RAID1, RAID5 等磁碟阵列的应用啊！但是如果是 RAID 控制晶片坏掉呢？这就麻烦了～所以说，如果有 RAID 系统时， 鸟哥个人还是觉得需要进行额外的备份才好的！如果资料够重要的话。

  • 造成系统损毁的问题-软体问题

根据分析，其实系统的软体伤害最严重的就属使用者的操作不当啦！像最近这几天才在鸟园讨论区发现， 有网友手滑了一下，结果在指令列输入了‘ rm -rf /home ’，这造成什么后果？就造成使用者家目录被删光光～ 因为当时下达指令的身份是 root 啊～会欲哭无泪喔！为了避免这方面的‘手滑’问题，备份是重要的！

软体伤害除了来自主机上的使用者操作不当之外，最常见的可能是资安攻击事件了。 假如你的 Linux 系统上面某些 Internet 的服务软体是最新的！这也意味着可能是‘相对最安全的’， 但是，这个世界目前的闲人是相当多的，你不知道什么时候会有所谓的‘骇客软体’被提供出来，万一你在 Internet 上面的服务程序被攻击，导致你的 Linux 系统全毁，这个时候怎么办？当然是要复原系统吧？

那如何复原被伤害的系统呢？‘重新安装就好啦！’或许你会这么说， 但是，像鸟哥管理的几个网站的资料，尤其是 MySQL 资料库的资料，这些都是弥足珍贵的经验资料， 万一被损毁而救不回来的时候，不是很可惜吗？这个还好哩，万一你是某家银行的话， 那么资料的损毁可就不是能够等闲视之的！关系的可是数千甚至上万人的身家财产！这就是备份的重要性了！ 他可以最起码的稍微保障我们的资料有另外一份 copy 的备援以达到‘安全回复’的基本要求！

  • 主机角色不同，备份任务也不同

由于软硬体的问题都可能造成系统的损毁，所以备份当然就很重要啦！问题是，每一部主机都需要备份吗？ 多久备份一次呢？要备份什么资料呢？

如果是针对个人桌上型电脑使用的资料，那么 Norton 的‘ Ghost ’应该算是一套好到不行的备份大师了！ 最主要是 Ghost 可以针对整个 partition 来进行备份，所以啰，我们可以将 Windows 系统当中的整个 C 或者是整个 D 槽完整的备份下来。甚至在还原方面也是非常的快速，而且操作简便！ 另外，由于个人桌上型电脑所使用的资料量通常不大，所以当 ghost 完成之后，通常只要将资料烧录到光碟片当中，大约只要一至两片的光碟片也就绰绰有余啰！ 那么将光碟片保存好，这就是最简易的资料备份模式啰！ 此外，由于个人的资料变动性不大，所以资料的备份频率方面也不需要非常的频繁！

但是，万一你的主机有提供 Internet 方面的服务呢？又该如何备份啊？举个例子来说，像是我们 Study Area 团队的讨论区网站 http://phorum.study-area.org 提供的是类似 BBS 的讨论文章， 虽然资料量不大，但是由于讨论区的文件是天天在增加的，每天都有相当多的资讯流入， 由于某些资讯都是属于重要的人物之留言，这个时候，我们能够让机器死掉吗？或者是能够一季三个月才备份一次吗？ 这个备份频率需求的考量是非常重要的！

再提到 2002 年左右鸟哥的讨论区曾经挂点的问题，以及 2003 年初 Study-Area 讨论区挂点的问题，讨论区一旦挂点的话，该资料库内容如果损毁到无法救回来， 嘿嘿！要晓得讨论区可不是一个人的心血耶！有的时候 (像 Study-Area 讨论区) 是一群热心 Linux 的朋友们互相建立交流起来的资料流通网，如果死掉了，那么不是让这些热血青年的热情付之一炬了吗？ 所以啰，建立备份的策略 (频率、媒体、方法等) 是相当的重要的。

  • 备份因素考量

由于电脑 (尤其是目前的电脑，操作频率太高、硬体良率太差、使用者操作习惯不良、 ‘某些’作业系统的当机率太高....) 的稳定性较差，所以啰！备份的工作就越来越重要了！ 那么一般我们在备份时考虑的因素有哪些呢？

  • 备份哪些档案：
    哪些资料对系统或使用者来说是重要的？那些资料就是值得备份的资料！例如 /etc/* 及 /home/* 等。

  • 选择什么备份的媒介：
    是可读写光碟、另一颗硬碟、同一颗硬碟的不同 partition、还是使用网路备援系统？ 哪一种的速度最快，最便宜，可将资料保存最久？这都可以考虑的。

  • 考虑备份的方式：
    是以完整备份(类似 ghost)来备份所有资料，还是使用差异备份仅备份有被更动过的资料即可？

  • 备份的频率：
    例如 MySQL 资料库是否天天备份、若完整备份，需要多久进行一次？

  • 备份使用的工具为何：
    是利用 tar 、 cpio 、 dd 还是 dump 等等的备份工具？

底下我们就来谈一谈这些问题的解决之道吧！ ^_^

小标题的图示 哪些 Linux 资料具有备份的意义

一般来说，鸟哥比较喜欢备份最重要的档案而已 (关键资料备份)，而不是整个系统都备份起来 (完整备份, Full backup)！那么哪些档案是有必要备份的呢？具有备份意义的档案通常可以粗分为两大类，一类是系统基本设定资讯、一类则是类似网路服务的内容资料。 那么各有哪些档案需要备份的呢？我们就来稍微分析一下。

  • 作业系统本身需要备份的档案：

这方面的档案主要跟‘帐号与系统设定档’有关系！ 主要有哪些帐号的档案需要备份呢？就是 /etc/passwd, /etc/shadow, /etc/group, /etc/gshadow, /home 底下的使用者家目录等等， 而由于 Linux 预设的重要参数档都在 /etc/ 底下，所以只要将这个目录备份下来的话， 那么几乎所有的设定档都可以被保存的！

至于 /home 目录是一般用户的家目录，自然也需要来备份一番！再来，由于使用者会有邮件吧！所以呢，这个 /var/spool/mail/ 内容也需要备份呦！另外，由于如果你曾经自行更动过核心，那么 /boot 里头的资讯也就很重要啰！所以啰，这方面的资料你必须要备份的档案为：

  • /etc/ 整个目录
  • /home 整个目录
  • /var/spool/mail
  • /boot
  • /root
  • 如果你自行安装过其他的套件，那么 /usr/local/ 或 /opt 也最好备份一下！

  • 网路服务的资料库方面：

这部份的资料可就多而且复杂了，首先是这些网路服务软体的设定档部分， 如果你的网路软体安装都是以原厂提供的为主，那么你的设定档案大多是在 /etc 底下，所以这个就没啥大问题！但若你的套件大多来自于自行的安装，那么 /usr/local 这个目录可就相当的重要了！

再来，每种服务提供的资料都不相同，这些资料很多都是人们提供的！举例来说，你的 WWW 伺服器总是需要有人提供网页档案吧？否则浏览器来是要看啥咚咚？你的讨论区总是得要写入资料库系统吧？ 否则讨论的资料如何更新与记载？所以，使用者主动提供的档案，以及服务运作过程会产生的资料， 都需要被考虑来备份。若我们假设我们提供的服务软体都是使用原厂的 RPM 安装的！所以要备份的资料档案有：

  • 软体本身的设定档案，例如：/etc/ 整个目录，/usr/local/ 整个目录
  • 软体服务提供的资料，以 WWW 及 MySQL 为例：
    WWW 资料：/var/www 整个目录或 /srv/www 整个目录，及系统的使用者家目录
    MySQL ： /var/lib/mysql 整个目录
  • 其他在 Linux 主机上面提供的服务之资料库档案！

  • 推荐需要备份的目录：

由上面的介绍来看的话，如果你的硬体或者是由于经费的关系而无法全部的资料都予以备份时， 鸟哥建议你至少需要备份这些目录呦！

  • /boot
  • /etc
  • /home
  • /root
  • /usr/local(或者是 /opt 及 /srv 等)
  • /var(注：这个目录当中有些暂存目录则可以不备份！)

  • 不需要备份的目录：

有些资料是不需要备份的啦！例如我们在第六章档案权限与目录配置里头提到的 /proc 这个目录是在记录目前系统上面正在跑的程序，这个资料根本就不需要备份的呢！此外，外挂的机器，例如 /mnt 或 /media 里面都是挂载了其他的硬碟装置、光碟机、软碟机等等，这些也不需要备份吧？ 所以啰！底下有些目录可以不需要备份啦！

  • /dev ：这个随便你要不要备份
  • /proc：这个真的不需要备份啦！
  • /mnt 与 /media：如果你没有在这个目录内放置你自己系统的东西，也不需要备份
  • /tmp ：干嘛存暂存档！不需要备份！
小标题的图示 备份用储存媒体的选择

用来储存备份资料的媒体非常的多样化，那该如何选择呢？在选择之前我们先来讲个小故事先！

  • 一个实际发生的故事

在备份的时候，选择一个‘资料存放的地方’也是很需要考虑的一个因素！ 什么叫做资料存放的地方呢？讲个最简单的例子好了，我们知道说，较为大型的机器都会使用 tape 这一种磁带机来备份资料，而如果是一般个人电脑的话，很可能是使用类似 Mo 这一种可读写式光碟片来存取资料！但是你不要忘记了几个重要的因素，那就是万一你的 Linux 主机被偷了呢？

这不是不可能的，之前鸟哥在成大念书时，隔壁校区的研究室曾经遭小偷， 里面所有的电脑都被偷走了！包括‘Mo 片’，当他们发现的时候，一开始以为是硬体被偷走了，还好， 他们都有习惯进行备份，但是很不幸的，这一次连‘备份的 MO 都被拿走了！’怎么办？！只能道德劝说小偷先生能够良心发现的将硬碟拿回来啰！唉～真惨....

  • 异地备援系统

这个时候，所谓的‘异地备援系统’就显的相当的重要了！ 什么是异地备援呀！说的太文言了！呵！简单的说，就是将你的系统资料‘备份’到其他的地方去， 例如说我的机器在台南，但是我还有另一部机器在高雄老家，这样的话， 我可以将台南机器上面重要的资料都给他定期的自动的透过网路传输回去！ 也可以将家里重要的资料给他丢到台南来！这样的最大优点是可以在台南的机器死掉的时候， 即使是遭小偷，也可以有一个‘万一’的备份所在！

有没有缺点啊？有啊！缺点就是～频宽严重的不足！ 在这种状态下，所能采取的策略大概就是‘仅将最重要的资料给他传输回去啰！’ 至于一些只要系统从新安装就可以回复的咚咚！那就没有这个必要了！当然啰，如果你的网路是属于 T1 专线的话，那么完整备份将资料丢到另一地去，也是很可行的啦！只是鸟哥没有那么好命...

  • 储存媒体的考量

在此同时，我们再来谈一谈，那么除了异地备援这个‘相对较为安全的备份’方法之外， 还有没有其他的方法可以储存备份的呢？毕竟这种网路备援系统实在是太耗频宽了！如果像我们一般家用的 ADSL 根本就是吃不消！那么怎么办？喔～那就只好使用近端的装置来备份啰！ 这也是目前我们最常见到的备份方法！例如一般我们使用的 Tape, Mo, Zip, CD-RW, DVD-RW 还有备份用抽取式硬碟与携带式硬碟等等！ 那么在选择上需要注意些什么呢？需要注意的地方有几点：

  • 备份速度要求 -- 思考硬碟用途：

    ‘备份’在 Linux 主机上面也是蛮耗系统资源的！因为需要将系统的资料拷贝到其他装置上面去，这个时候 I/O 与 CPU 的负载都会大！你总不希望系统就这样给他挂点吧！此外，有些系统的资料实在太多咯， 怎么样也备份不完！所以啰，越快的储存装置是越好的！如果你是个重视速度甚于一切的人， 那么我觉得抽取式硬碟是个不错的方式，只不过.....目前我知道的抽取式硬碟都需要冷开机才行，不太符合 Linux 主机 24 小时全年无休的状态....

    但是硬碟真的越来越大、越来越便宜了，不使用速度快的硬碟来备份实在很可惜～ 加上目前的火线 (IEEE 1394) 以及 USB 2.0 外接式硬碟盒技术已经相当的成熟， 传输速度又快，又可以直接热拔插 (Plug and Play)，接上 USB 硬碟， 整个复制一下，传输速度理论上可达 480Mbps (约 60 MBytes/second) ，快的哩！ 复制完毕，又可以将硬碟带走，不需要与主机放置在一起，还可以避免同时被偷，真是不错。

    但是，硬碟还是有一定的困扰，那就是‘不接电源的硬碟需要很好很好的保养’。 我们知道电脑最好的保养就是常常开机去运作一下，免得长期不开机，造成受潮而损坏。 这个携带式硬碟只是偶而才会连上主机来进行备份的资料，除非你额外购买一部防潮箱来放置硬碟， 否则很容易损坏！所以，近年来速度越来越快的 DVD-RW 就变的很方便啰！至于磁带 (tape)，在速度上完全是落后的.....

    至于使用直接安装在主机上的第二颗硬碟来备份，类似 RAID 或者是安装一颗备份的硬碟在 Linux 系统当中，这个方案也很好， 而且速度上绝对是最具优势的！但是就如同我们刚刚提到的，万一你的机器被偷了，连带的， 这颗备份的硬碟自然也就不见了.....

  • 储存容量 -- 磁带备份考量：

    这也是一个需要考量的因素！而且常常是最大考量的因素呢！虽然目前硬碟越来越便宜， 但是毕竟就如同前面说的，抽取式硬碟需要将系统冷开机，而建构在系统内的硬碟又同时具有不安全的成分在， 携带式硬碟可能又有不容易保存的特性，这个时候一个大容量的替代方案就显的很重要了！虽然 CD-RW 与 DVD-RW 可以提供不错的速度，但是其容量毕竟不足 (虽然有高达几十 GB 的蓝光 DVD 可用，但目前 (2009) 尚未普及， 光碟片太贵了！) 所以说，具有大容量的 tape (磁带容量最小的一款也可以到达 8 GB 左右！) 就相当的具有这方面的优势了！而且携带方便，存放也容易！更可以带着走～～

  • 经费与资料可靠性 -- DVD 的使用，可保存 10 年左右：

    在经费不短缺的情况下，我们当然会建议你上面的几个装置都买一买， 然后分别在不同的时间进行不同的备份作业 (底下我们有些建议的啦！^_^) ！但是如果经费也是需要考量的话，那么磁带机这个目前还算贵重的物品可能暂时还动不到！ 这个时候近来渐渐便宜的 DVD-RW 就显的活跃的多了！而且光碟片也可以保存很久的ㄋㄟ～ 当然，目前应该不会有人以软碟来备份了吧！呵呵！软碟可是相当不安全的。

无论如何，如果经费允许的话， Tape 备份资料真的是一个不错的点子！因为他的高容量让我好满意！ 再来，如果经费稍微短缺的话，那么 DVD-RW 经常性的将资料烧录下来，这也是蛮好的，尤其 DVD 片又不占空间！再来，如果还是没有办法，那么一颗内建在 Linux 的硬碟用来备份也是不错的！ 什么！连备份的硬碟都没有，唉！怎么跟我一样～这个时候没办法啦，用原来的安装系统的硬碟，多留一个 partition 用来当作备份之用吧 (这也是目前鸟哥常用的方法之一！)底下我们来看一看一些常见的装置代号！

  • 光碟机： /dev/cdrom (其实应该是 /dev/sdX 或 /dev/hdX)
  • 磁带机： /dev/st0 (SCSI 介面), /dev/ht0 (IDE 介面)
  • 软碟机： /dev/fd0, /dev/fd1
  • 硬碟机： /dev/hd[a-d][1-16] (IDE), /dev/sd[a-p][1-16] (SCSI/SATA)
  • 外接式 USB 硬碟机： /dev/sd[a-p][1-16] (与 SCSI 相同)
  • 印表机： /dev/lp[0-2]

特别留意的是磁带机呦！如果你有钱的话，那么买一部磁带机是相当不错的建议！没钱的话，买 IDE 或 SATA 介面的硬碟也很不错！！ ^_^

大标题的图示 备份的种类、频率与工具的选择

讲了好多口水了，还是没有讲到重点，真是的....好了，再来提到那个备份的种类，因为想要选择什么储存媒体与相关备份工具， 都与备份使用的方式有关！那么备份有哪些方式呢？一般可以粗略分为‘累积备份’与‘差异备份’这两种 (注1)。当然啦，如果你在系统出错时想要重新安装到更新的系统时，仅备份关键资料也就可以了！

小标题的图示 完整备份之累积备份 (Incremental backup)

备份不就是将重要资料复制出来即可吗？干嘛需要完整备份 (Full backup) 呢？如果你的主机是负责相当重要的服务， 因此如果有不明原因的当机事件造成系统损毁时，你希望在最短的时间内复原系统。此时，如果仅备份关键资料时， 那么你得要在系统出错后，再去找新的 Linux distribution 来安装，安装完毕后还得要考虑到资料新旧版本的差异问题， 还得要进行资料的移植与系统服务的重新建立等等，等到建立妥当后，还得要进行相关测试！ 这种种的工作可至少得要花上一个星期以上的工作天才能够处理妥当！所以，仅有关键资料是不够的！

  • 还原的考量

但反过来讲，如果是完整备份的话呢？若硬体出问题导致系统损毁时，只要将完整备份拿出来，整个给他倾倒回去硬碟， 所有事情就搞定了！有些时候 (例如使用 dd 指令) 甚至连系统都不需要重新安装！反正整个系统都给他倒回去，连同重要的 Linux 系统档案等，所以当然也就不需要重新安装啊！因此，很多企业用来提供重要服务的主机都会使用完整备份， 若所提供的服务真的非常重要时，甚至会再架设一部一模一样的机器呢！如此一来， 若是原本的机器出问题，那就立刻将备份的机器拿出来接管！以使企业的网路服务不会中断哩！

那你知道完整备份的定义了吧？没错！完整备份就是将根目录 (/) 整个系统通通备份下来的意思！ 不过，在某些场合底下，完整备份也可以是备份一个档案系统 (filesystem)！例如 /dev/sda1 或 /dev/md0 或 /dev/myvg/mylv 之类的档案系统就是了。

  • 累积备份的原则

虽然完整备份在还原方面有相当良好的表现，但是我们都知道系统用的越久，资料量就会越大！如此一来， 完整备份所需要花费的时间与储存媒体的使用就会相当麻烦～所以，完整备份并不会也不太可能每天都进行的！ 那你想要每天都备份资料该如何进行呢？有两种方式啦，一种是本小节会谈到的累积备份，一种则是下个小节谈到的差异备份。

所谓的累积备份，指的是在系统在进行完第一次完整备份后，经过一段时间的运作， 比较系统与备份档之间的差异，仅备份有差异的档案而已。而第二次累积备份则与第一次累积备份的资料比较， 也是仅备份有差异的资料而已。如此一来，由于仅备份有差异的资料，因此备份的资料量小且快速！备份也很有效率。 我们可以从下图来说明：

累积备份 (incremental backup) 操作示意图
图 2.1.1、 累积备份 (incremental backup) 操作示意图

假如我在星期一作好完整备份，则星期二的累积备份是系统与完整备份间的差异资料；星期三的备份是系统与星期二的差异资料， 星期四的备份则是系统与星期三的差异资料。那你得要注意的是，星期二的资料是完整备份加第一次累积备份， 星期三的资料是完整备份加第一次累积与第二次累积备份，星期四的资料则是星期一的完整备份加第一次加第二次加第三次累积备份。 由于每次都仅与前一次的备份资料比较而已，因此备份的资料量就会少很多！

那如何还原？经过上面的分析，我们也会知道累积备份的还原方面比较麻烦！ 假设你的系统在星期五的时候挂点了！那你要如何还原？首先，你必须要还原星期一的完整备份，然后还原星期二的累积备份， 再依序还原星期三、星期四的累积备份才算完全复原！那如果你是经过了九次的累积备份，就得要还原到第九次的阶段， 才是最完整的还原程序！

  • 累积备份使用的备份软体

完整备份常用的工具有 dd, cpio, dump/restore 等等。因为这些工具都能够备份装置与特殊档案！ dd 可以直接读取磁碟的磁区 (sector) 而不理会档案系统，是相当良好的备份工具！不过缺点就是慢很多！ cpio 是能够备份所有档名，不过，得要配合 find 或其他找档名的指令才能够处理妥当。以上两个都能够进行完整备份， 但累积备份就得要额外使用脚本程式来处理。可以直接进行累积备份的就是 dump 这个指令啰！详细的指令与参数用法， 请前往第九章查阅，这里仅列出几个简单的范例而已。

# 1. 用 dd 来将 /dev/sda 备份到完全一模一样的 /dev/sdb 硬碟上：
[root@www ~]# dd if=/dev/sda of=/dev/sdb
# 由于 dd 是读取磁区，所以 /dev/sdb 这颗磁碟可以不必格式化！非常的方便！
# 只是你会等非常非常久！因为 dd 的速度比较慢！

# 2. 使用 cpio 来备份与还原整个系统，假设储存媒体为 SATA 磁带机：
[root@www ~]# find / -print | cpio -covB > /dev/st0  <==备份到磁带机
[root@www ~]# cpio -iduv < /dev/st0                  <==还原

假设 /home 为一个独立的档案系统，而 /backupdata 也是一个独立的用来备份的档案系统，那如何使用 dump 将 /home 完整的备份到 /backupdata 上呢？可以像底下这样进行看看：

# 1. 完整备份
[root@www ~]# dump -0u -f /backupdata/home.dump /home

# 2. 第一次进行累积备份
[root@www ~]# dump -1u -f /backupdata/home.dump.1 /home

除了这些指令之外，其实 tar 也可以用来进行完整备份啦！举例来说，/backupdata 是个独立的档案系统， 你想要将整个系统通通备份起来时，可以这样考虑：将不必要的 /proc, /mnt, /tmp 等目录不备份，其他的资料则予以备份：

[root@www ~]# tar --exclude /proc --exclude /mnt --exclude /tmp \
> --exclude /backupdata -jcvp -f /backupdata/system.tar.bz2 /
小标题的图示 完整备份之差异备份 (Differential backup)

差异备份与累积备份有点类似，也是需要进行第一次的完整备份后才能够进行。只是差异备份指的是：每次的备份都是与原始的完整备份比较的结果。所以系统运作的越久，离完整备份时间越长， 那么该次的差异备份资料可能就会越大！差异备份的示意图如下所示：

差异备份 (differential backup) 操作示意图
图 2.2.1、 差异备份 (differential backup) 操作示意图

差异备份常用的工具与累积备份差不多！因为都需要完整备份嘛！如果使用 dump 来备份的话，那么每次备份的等级 (level) 就都会是 level 1 的意思啦！当然啦，你也可以透过 tar 的 -N 选项来备份喔！如下所示：

[root@www ~]# tar -N '2009-06-01' -jpcv -f /backupdata/home.tar.bz2 /home
# 只有在比 2009-06-01 还要新的档案，在 /home 底下的档案才会被打包进 home.bz2 中！
# 有点奇怪的是，目录还是会被记录下来，只是目录内的旧档案就不会备份。

此外，你也可以透过 rsync 来进行镜像备份喔！ 这个 rsync 可以对两个目录进行镜像 (mirror) ，算是一个非常快速的备份工具！简单的指令语法为：

[root@www ~]# rsync -av 来源目录 目标目录

# 1. 将 /home/ 镜像到 /backupdata/home/ 去
[root@www ~]# rsync -av /home /backupdata/
# 此时会在 /backupdata 底下产生 home 这个目录来！
[root@www ~]# rsync -av /home /backupdata/
# 再次进行会快很多！如果资料没有更动，几乎不会进行任何动作！

根据分析 (注2) ，差异备份所使用的磁碟容量可能会比累积备份来的大，但是差异备份的还原较快， 因为只需要还原完整备份与最近一次的差异备份即可。无论如何，请依据你自己的喜好来选择备份的方式吧！

小标题的图示 关键资料备份

完整备份虽然有许多好处，但就是需要花费很多时间！所以，如果在主机提供的服务并不是一定要 24 小时提供的前提下， 我们可以仅备份重要的关键资料即可。由于主机即使当机个一两天可能也不会影响到你的正常生活时， 仅备份关键资料就好啦！不需要整个系统都备份。仅备份关键资料是有许多好处的！ 由于完整备份可能是在系统运作期间进行，不但会花费非常多时间，而且如果备份当时系统已经被攻破， 那你备份的资料是有问题的，那还原回去也是有问题的系统啊！

如果仅是备份关键资料而已，那么由于系统的绝大部分执行档都可以后来重新安装，因此若你的系统不是因为硬体问题， 而是因为软体问题而导致系统被攻破或损毁时，直接捉取最新的 Linux distribution ，然后重新安装， 然后再将系统资料 (如帐号/密码与家目录等等) 与服务资料 (如 www/email/crontab/ftp 等等) 一个一个的填回去！ 那你的系统不但保持在最新的状态，同时也可以趁机处理一下与重新温习一下系统设定！是很不错的呦！

不过，备份关键资料最麻烦的地方其实就是在还原啦！上述的还原方式是你必须要很熟悉系统运作， 否则还原得要花费很多时间的！尤其近来的 Linux 强调安全性，所以加入 SELinux 了，你如果要从旧版的 Linux 升级到新版时， 原本若没有 SELinux 而换成新版则需要启动 SELinux 时，那个除错的时间会花很长一段日子哩！ 鸟哥认为这是仅备份关键资料的一些优缺点啦～

备份关键资料鸟哥最爱使用 tar 来处理了！如果想要分门别类的将各种不同的服务在不同的时间备份使用不同档名， 配合 date 指令是非常好用的工具！例如底下的案例是依据日期来备份 mysql 的资料库喔！

[root@www ~]# tar -jpcvf mysql.`date +%Y-%m-%d`.tar.bz2 /var/lib/mysql

备份是非常重要的工作，你可不希望想到才进行吧？交给系统自动处理就对啦！请自己撰写 script ， 配合 crontab 去执行吧！这样子，备份会很轻松喔！

大标题的图示 鸟哥的备份策略

每部主机的任务都不相同，重要的资料也不相同，重要性也不一样，因此，每个人的备份思考角度都不一样！ 有些备份策略是非常有趣的，包括使用多个磁带机与磁带来自动备份企业资料哩 (注3) 。

就鸟哥的想法来说，鸟哥并没有想要将整个系统完整的备份下来，因为太耗时间了！而且就鸟哥的立场而言，似乎也没有这个必要， 所以通常鸟哥只备份较为重要的档案而已！不过，由于鸟哥需要备份 /home 与网页资料，如果天天都备份，我想，系统迟早会受不了 (因为这两个部分就已经占去数 10 GB 的硬碟空间...)，所以鸟哥就将我的备份分为两大部分，一个是每日备份经常性变动的重要资料， 一个则是每周备份就不常变动的资讯。这个时候我就写了两个简单的 scripts ，分别来储存这些资料。

所以针对鸟哥的‘鸟站’来说，我的备份策略是这样的：

  1. 主机硬体：使用一个独立的 filesystem 来储存备份资料，此 filesystem 挂载到 /backup 当中；
  2. 每日进行：目前仅备份 MySQL 资料库；
  3. 每周进行：包括 /home, /var, /etc, /boot, /usr/local 等目录与特殊服务的目录；
  4. 自动处理：这方面利用 /etc/crontab 来自动提供备份的进行；
  5. 异地备援：每月定期的将资料分别 (a)烧录到光碟上面 (b)使用网路传输到另一部机器上面。

那就来看看鸟哥是怎么备份的吧！ ^_^

小标题的图示 每周系统备份的 script

底下提供鸟哥的备份的 scripts ，希望对大家有点帮助！鸟哥假设你已经知道如何挂载一个新的 filesystem 到 /backup 去，所以格式化与挂载这里就不再强调啰。

[root@www ~]# vi /backup/backupwk.sh
#!/bin/bash
# ====================================================================
# 使用者参数输入位置：
# basedir=你用来储存此脚本所预计备份的资料之目录(请独立档案系统)
basedir=/backup/weekly  <==您只要改这里就好了！

# ====================================================================
# 底下请不要修改了！用预设值即可！
PATH=/bin:/usr/bin:/sbin:/usr/sbin; export PATH
export LANG=C

# 设定要备份的服务的设定档，以及备份的目录
named=$basedir/named
postfixd=$basedir/postfix
vsftpd=$basedir/vsftp
sshd=$basedir/ssh
sambad=$basedir/samba
wwwd=$basedir/www
others=$basedir/others
userinfod=$basedir/userinfo
# 判断目录是否存在，若不存在则予以建立。
for dirs in $named $postfixd $vsftpd $sshd $sambad $wwwd $others $userinfod
do
    [ ! -d "$dirs" ] && mkdir -p $dirs
done

# 1. 将系统主要的服务之设定档分别备份下来，同时也备份 /etc 全部。
cp -a /var/named/chroot/{etc,var}	$named
cp -a /etc/postfix /etc/dovecot.conf	$postfixd
cp -a /etc/vsftpd/*			$vsftpd
cp -a /etc/ssh/*			$sshd
cp -a /etc/samba/*			$sambad
cp -a /etc/{my.cnf,php.ini,httpd}	$wwwd
cd /var/lib
  tar -jpc -f $wwwd/mysql.tar.bz2 	mysql
cd /var/www
  tar -jpc -f $wwwd/html.tar.bz2 	html cgi-bin
cd /
  tar -jpc -f $others/etc.tar.bz2	etc
cd /usr/
  tar -jpc -f $others/local.tar.bz2	local

# 2. 关于使用者参数方面
cp -a /etc/{passwd,shadow,group}	$userinfod
cd /var/spool
  tar -jpc -f $userinfod/mail.tar.bz2	mail
cd /
  tar -jpc -f $userinfod/home.tar.bz2	home
cd /var/spool
  tar -jpc -f $userinfod/cron.tar.bz2	cron at

[root@www ~]# chmod 700 /backup/backupwk.sh
[root@www ~]# /backup/backupwk.sh  <==记得自己试跑看看！

上面的 script 主要均使用 CentOS 5.x (理论上， Red Hat 系列的 Linux 都是用) 预设的服务与目录， 如果你有设定某些服务的资料在不同的目录时，那么上面的 script 是还需要修改的！不要只是拿来用而已喔！ 上面 script 可以在底下的连结取得。

  • http://linux.vbird.org0580backup/backupwk-0.1.sh
小标题的图示 每日备份资料的 script

再来，继续提供一下每日备份资料的脚本程式！请注意，鸟哥这里仅有提供 MySQL 的资料库备份目录， 与 WWW 的类似留言版程式使用的 CGI 程式与写入的资料而已。 如果你还有其他的资料需要每日备份，请自行照样造句啰！ ^_^

[root@www ~]# vi /backup/backupday.sh
#!/bin/bash
# =========================================================
# 请输入，你想让备份资料放置到那个独立的目录去
basedir=/backup/daily/  <==你只要改这里就可以了！

# =========================================================
PATH=/bin:/usr/bin:/sbin:/usr/sbin; export PATH
export LANG=C
basefile1=$basedir/mysql.$(date +%Y-%m-%d).tar.bz2
basefile2=$basedir/cgi-bin.$(date +%Y-%m-%d).tar.bz2
[ ! -d "$basedir" ] && mkdir $basedir

# 1. MysQL (资料库目录在 /var/lib/mysql)
cd /var/lib
  tar -jpc -f $basefile1 mysql

# 2. WWW 的 CGI 程式 (如果有使用 CGI 程式的话)
cd /var/www
  tar -jpc -f $basefile2 cgi-bin

[root@www ~]# chmod 700 /backup/backupday.sh
[root@www ~]# /backup/backupday.sh  <==记得自己试跑看看！

上面的脚本可以在底下的连结取得。这样一来每天的 MySQL 资料库就可以自动的被记录在 /backup/daily/ 目录里头啦！而且还是档案名称会自动改变的呦！呵呵！我很喜欢！OK！再来就是开始让系统自己跑啦！ 怎么跑？就是 /etc/crontab 呀！提供一下我的相关设定呦！

  • http://linux.vbird.org0580backup/backupday.sh
[root@www ~]# vi /etc/crontab
# 加入这两行即可 (请注意你的档案目录！不要照抄呦！)
30 3 * * 0 root /backup/backupwk.sh
30 2 * * * root /backup/backupday.sh

这样系统就会自动的在每天的 2:30 进行 MySQL 的备份，而在每个星期日的 3:30 进行重要档案的备份！呵呵！你说，是不是很容易呢！但是请千万记得呦！还要将 /backup/ 当中的资料 copy 出来才行耶！否则整部系统死掉的时候...那可不是闹着玩的！ 所以鸟哥大约一个月到两个月之间，会将 /backup 目录内的资料使用 DVD 复制一下，然后将 DVD 放置在家中保存！这个 DVD 很重要的喔！不可以遗失，否则系统的重要资料 (尤其是帐号资讯) 流出去可不是闹着玩的！

Tips:
有些时候，你在进行备份时，被备份的档案可能同时间被其他的网路服务所修改喔！ 举例来说，当你备份 MySQL 资料库时，刚好有人利用你的资料库发表文章，此时， 可能会发生一些错误的讯息。要避免这类的问题时，可以在备份前，将该服务先关掉， 备份完成后，再启动该服务即可！感谢讨论区 duncanlo 提供这个方法！ 		鸟哥的图示
小标题的图示 远端备援的 script

如果你有控管两部以上的 Linux 主机时，那么互相将对方的重要资料保存一份在自己的系统中也是个不错的想法！ 那怎么保存啊？使用 USB 复制来去吗？当然不是啦！你可以透过网路来处置啦！我们假设你已经有一部主机， 这部主机的 IP 是 192.168.1.100 ，而且这部主机已经提供了 FTP 与 sshd 这两个网路服务， 同时你已经做好了 FTP 的帐号，sshd 帐号的免密码登入功能等 (这部分请参考伺服器篇的介绍)，接下来你可以这样做：

  • 使用 FTP 上传备份资料

假设你要上传的资料是将 /backup/weekly/ 目录内的档案统整为一个 /backup/weekly.tar.bz2 ， 并且上传到伺服器端的 /home/backup/ 底下，使用的帐号是 dmtsai ，密码是 dmtsai.pass 。 那么你可以这样做看看：

[root@www ~]# vi /backup/ftp.sh
#!/bin/bash
# ===========================================
# 先输入系统所需要的资料
host="192.168.1.100"		# 远端主机
id="dmtsai"			# 远端主机的 FTP 帐号
pw='dmtsai.pass'		# 该帐号的密码
basedir="/backup/weekly"	# 本地端的欲被备份的目录
remotedir="/home/backup"	# 备份到远端的何处？

# ===========================================
backupfile=weekly.tar.bz2
cd $basedir/..
  tar -jpc -f $backupfile $(basename $basedir)

ftp -n "$host" > ${basedir}/../ftp.log 2>&1 <<EOF
user $id $pw
binary
cd $remotedir
put $backupfile
bye
EOF
  • 使用 rsync 上传备份资料

另一个更简单的方法就是透过 rsync ，但是你必须要在你的伺服器上面取得某个帐号使用权后， 并让该帐号可以不用密码即可登入才行！这部分得要先参考伺服器篇的远端连线伺服器才行！ 假设你已经设定好 dmtsai 这个帐号可以不用密码即可登入远端伺服器，而同样的你要让 /backup/weekly/ 整个备份到 /home/backup/weekly 底下时，可以简单这样做：

[root@www ~]# vi /backup/rsync.sh
#!/bin/bash
remotedir=/home/backup/
basedir=/backup/weekly
host=127.0.0.1
id=dmtsai

# 底下为程式阶段！不需要修改喔！
rsync -av -e ssh $basedir ${id}@${host}:${remotedir}

由于 rsync 可以透过 ssh 来进行镜像备份，所以没有变更的档案将不需要上传的！相当的好用呢！ 好了！大家赶紧写一个适合自己的备份 script 来进行备份的行为吧！重要重要喔！

大标题的图示 灾难复原的考量

之所以要备份当然就是预防系统挂点啦！如果系统真的挂点的话，那么你该如何还原系统呢？

  • 硬体损毁，且具有完整备份的资料时

由于是硬体损毁，所以我们不需要考虑系统软体的不稳定问题，所以可以直接将完整的系统复原回去即可。 首先，你必须要先处理好你的硬体，举例来说，将你的硬碟作个适当的处理，譬如建置成为磁碟阵列之类的。 然后依据你的备份状态来复原。举例来说，如果是使用差异备份，那么将完整备份复原后， 将最后一次的差异备份复原回去，你的系统就恢复了！非常简单吧！

  • 由于软体的问题产生的被攻破资安事件

由于系统的损毁是因为被攻击，此时即使你恢复到正常的系统，那么这个系统既然会被攻破， 没道理你还原成旧系统就不会被再次攻破！所以，此时完整备份的复原可能不是个好方式喔！最好是需要这样进行啦：

  1. 先拔除网路线，最好将系统进行完整备份到其他媒体上，以备未来查验
  2. 开始查阅登录档，尝试找出各种可能的问题
  3. 开始安装新系统 (最好找最新的 distribution)
  4. 进行系统的升级，与防火墙相关机制的制订
  5. 根据 2 的错误，在安装完成新系统后，将那些 bug 修复
  6. 进行各项服务与相关资料的恢复
  7. 正式上线提供服务，并且开始测试

软体资安事件造成的问题可大可小，一般来说，标准流程都是建议你将出问题的系统备份下来， 如果被追踪到你的主机曾经攻击过别人的话，那么你至少可以拿出备份资料来佐证说，你是被攻击者， 而不是主动攻击别人的坏人啊！然后，记得一定要找出问题点并予以克服，不然的话，你的系统将一再地被攻击啊！ 那样可就伤脑筋啰～

大标题的图示 重点回顾
  • 备份是系统损毁时等待救援的救星，但造成系统损毁的因素可能有硬体与软体等原因。
  • 由于主机的任务不同，备份的资料与频率等考量参数也不相同。
  • 常见的备份考虑因素有：关键档案、储存媒体、备份方式(完整/关键)、备份频率、使用的备份工具等。
  • 常见的关键资料有：/etc, /home, /var/spool/mail, /boot, /root 等等
  • 储存媒体的选择方式，需要考虑的地方有：备份速度、媒体的容量、经费与媒体的可靠性等。
  • 与完整备份有关的备份策略主要有：累积备份与差异备份。
  • 累积备份可具有较小的储存资料量、备份速度快速等。但是在还原方面则比差异备份的还原慢。
  • 完整备份的策略中，常用的工具有 dd, cpio, tar, dump 等等。
大标题的图示 本章习题
( 要看答案请将滑鼠移动到‘答：’底下的空白处，按下左键圈选空白处即可察看 )
  • 挑战题：尝试将你在学习本书所进行的各项任务备份下来，然后删除你的系统，接下来重新安装最新的 CentOS 5.x ， 再将你备份的资料复原回来，看看能否成功的让你的系统回复到之前的状态呢？

  • 挑战题：查询一下何谓企鹅龙软体，讨论一下该软体的还原机制是属于累积备份？还是完整备份？

  • 常用的完整备份 (full backup) 工具指令有哪些？
    dump + restore, dd, cpio 搭配 find 等软体。
  • 你所看到的常见的储存设备有哪些？
    Floppy, Mo, Zip, CD-RW, DVD-RW, 外接式 USB 硬碟, Tape, 外接式储存阵列 (RAID)，额外的储存架构，如 SAN, NAS 等。
大标题的图示 参考资料与延伸阅读
  • 注1：维基百科的备份说明：http://en.wikipedia.org/wiki/Incremental_backup
  • 注2：关于 differential 与 incremental 备份的优缺点说明：
    http://www.backupschedule.net/databackup/differentialbackup.html
  • 注3：一些备份计划的实施：http://en.wikipedia.org/wiki/Backup_rotation_scheme
2002/07/06：第一次完成
2003/02/12：重新编排与加入 FAQ
2005/10/25：旧版的资料已经移动到 此处 。
2005/10/25：主要是增加了一些简单的说明，以及将一些不合时宜的资料拿掉而已！
2009/07/15：将原本的基于 FC4 的文章移动到 此处。
2009/09/18：加入简单的几个题目练习


鸟哥的 Linux 私房菜 -- Linux 核心编译

为取得较佳浏览结果，请爱用 firefox 浏览本网页
鸟哥的 Linux 私房菜馆 | Linux 基础文件 | Linux 架站文件 | Linux 企业运用 | 安全管理 | 新手讨论 |

第二十六章、Linux 核心编译与管理
最近更新日期：2009/09/18
我们说的 Linux 其实指的就是核心 (kernel) 而已。这个核心控制你主机的所有硬体并提供系统所有的功能， 所以说，他重不重要啊！我们开机的时候其实就是利用开机管理程式载入这个核心档案来侦测硬体， 在核心载入适当的驱动程式后，你的系统才能够顺利的运作。现今的系统由于强调线上升级机制，因此非常不建议自订核心编译！ 但是，如果你想要将你的 Linux 安装到 USB 随身碟、想要将你的 Eee PC 小笔电安装自己的 Linux ， 想让你的 Linux 可以驱动你的小家电，此时，核心编译就是相当重要的一个任务了！ 这一篇比较进阶，如果你对系统移植没有兴趣的话，这一篇可以先略过喔！ ^_^

1. 编译前的任务：认识核心与取得核心原始码
    1.1 什么是核心 (Kernel)
    1.2 更新核心的目的
    1.3 核心的版本
    1.4 核心原始码的取得方式：distributions 预设、最新、patch
    1.5 核心原始码的解压缩/安装/观察
 2. 核心编译的前处理与核心功能选择
    2.1 硬体环境检视与核心功能要求
    2.2 保持干净原始码： make mrproper
    2.3 开始挑选核心功能： make XXconfig
    2.4 核心功能细项选择
        a. 一般设定(General setup)：附加版本名称、IPC 通讯、程序相关等
        b. 核心模组与 block layer 支援
        c. CPU 的类型与功能选择(含虚拟化技术)
        d. 电源管理功能
        e. 一些汇流排 (bus) 的选项
        f. 编译后执行档的格式
        g. 核心的网路功能
        h. 各项装置的驱动程式
        i. 档案系统的支援
        j. 核心骇客、资讯安全、密码应用
        k. 虚拟化与函式库
 3. 核心的编译与安装
    3.1 编译核心与核心模组
    3.2 实际安装模组
    3.3 开始安装新核心与多重核心选单 (grub)
 4. 额外(单一)核心模组编译
    4.1 编译前注意事项
    4.2 单一模组编译
    4.3 核心模组管理
 5. 重点回顾
6. 本章习题
7. 参考资料与延伸阅读
8. 针对本文的建议：http://phorum.vbird.org/viewtopic.php?t=23899
大标题的图示 编译前的任务：认识核心与取得核心原始码

我们在第一章里面就谈过 Linux 其实指的是核心！这个‘核心 (kernel)’是整个作业系统的最底层，他负责了整个硬体的驱动，以及提供各种系统所需的核心功能，包括防火墙机制、是否支援 LVM 或 Quota 等档案系统等等，这些都是核心所负责的！所以啰，在第二十章的开机流程中，我们也会看到 MBR 内的 loader 载入核心档案来驱动整个系统的硬体呢！ 也就是说，如果你的核心不认识某个最新的硬体，那么该硬体也就无法被驱动，你当然也就无法使用该硬体啰！

小标题的图示 什么是核心 (Kernel)

这已经是整个 Linux 基础的最后一篇了，所以，底下这些资料你应该都要‘很有概念’才行～ 不能只是‘好像有印象’～好了，那就复习一下核心的相关知识吧！

  • Kernel

还记得我们在第十一章的 BASH shell 提到过：电脑真正在工作的东西其实是‘硬体’， 例如数值运算要使用到 CPU、资料储存要使用到硬碟、图形显示会用到显示卡、音乐发声要有音效晶片、连接 Internet 可能需要网路卡等等。那么如何控制这些硬体呢？那就是核心的工作了！也就是说，你所希望电脑帮你达成的各项工作， 都需要透过‘核心’的帮助才行！当然啰，如果你想要达成的工作是核心所没有提供的， 那么你自然就没有办法透过核心来控制电脑使他工作啰！

举例来说，如果你想要有某个网路功能 (例如核心防火墙机制) ，但是你的核心偏偏忘记加进去这项功能， 那么不论你如何‘卖力’的设定该网路套件，很抱歉！不来电！换句话说，你想要让电脑进行的工作，都必须要‘核心有支援’才可以！这个标准不论在 Windows 或 Linux 这几个作业系统上都相同！如果有一个人开发出来一个‘全新的硬体’，目前的核心不论 Windows 或 Linux 都不支援，那么不论你用什么系统，哈哈！这个硬体都是英雄无用武之地啦！ 那么是否了解了‘核心’的重要了呢？所以我们才需要来了解一下如何编译我们的核心啦！

那么核心到底是什么啊？其实核心就是系统上面的一个档案而已， 这个档案包含了驱动主机各项硬体的侦测程式与驱动模组。在第二十章的开机流程分析中，我们也提到这个档案被读入主记忆体的时机， 当系统读完 BIOS 并载入 MBR 内的开机管理程式后，就能够载入核心到记忆体当中。然后核心开始侦测硬体， 挂载根目录并取得核心模组来驱动所有的硬体，之后呼叫 /sbin/init 就能够依序启动所有系统所需要的服务了！

这个核心档案通常被放置成 /boot/vmlinuz ，不过也不见得， 因为一部主机上面可以拥有多个核心档案，只是开机的时候仅能选择一个来载入而已。 甚至我们也可以在一个 distribution 上面放置多个核心，然后以这些核心来做成多重开机呢！

  • 核心模组 (kernel module) 的用途

既然核心档案都已经包含了硬体侦测与驱动模组，那么什么是核心模组啊？要注意的是， 现在的硬体更新速度太快了，如果我的核心比较旧，但我换了新的硬体，那么，这个核心肯定无法支援！ 怎么办？重新拿一个新的核心来处理吗？开玩笑～核心的编译过程可是很麻烦的～

所以啰，为了这个缘故，我们的 Linux 很早之前就已经开始使用所谓的模组化设定了！ 亦即是将一些不常用的类似驱动程式的咚咚独立出核心，编译成为模组，然后， 核心可以在系统正常运作的过程当中载入这个模组到核心的支援。如此一来， 我在不需要更动核心的前提之下，只要编译出适当的核心模组，并且载入他，呵呵！我的 Linux 就可以使用这个硬体啦！简单又方便！

那我的模组放在哪里啊？可恶！怎么会问这个傻问题呢？当然一定要知道的啦！就是 /lib/modules/$(uname -r)/kernel/ 当中啦！

  • 自制核心 - 核心编译

刚刚上面谈到的核心其实是一个档案，那么这个档案怎么来的？当然是透过原始码 (source code) 编译而成的啊！因为核心是直接被读入到主记忆体当中的，所以当然要将他编译成为系统可以认识的资料才行！也就是说， 我们必须要取得核心的原始码，然后利用第二十二章 Tarball 安装方式提到的编译概念来达成核心的编译才行啊！(这也是本章的重点啊！ ^_^)

  • 关于驱动程式 - 是厂商的责任还是核心的责任？

现在我们知道硬体的驱动程式可以编译成为核心模组，所以可以在不改变核心的前提下驱动你的新硬体。 但是，很多朋友还是常常感到困惑，就是 Linux 上面针对最新硬体的驱动程式总是慢了几个脚步， 所以觉得好像 Linux 的支援度不足！其实不可以这么说的，为什么呢？因为在 Windows 上面，对于最新硬体的驱动程式需求，基本上，也都是厂商提供的驱动程式才能让该硬体工作的， 因此，在这个‘驱动程式开发’的工作上面来说，应该是属于硬体发展厂商的问题， 因为他要我们买他的硬体，自然就要提供消费者能够使用的驱动程式啦！

所以，如果大家想要让某个硬体能够在 Linux 上面跑的话，那么似乎可以发起一人一信的方式，强烈要求硬体开发商发展 Linux 上面的驱动程式！这样一来，也可以促进 Linux 的发展呢！

小标题的图示 更新核心的目的

除了 BIOS 之外，核心是作业系统中最早被载入到记忆体的咚咚， 他包含了所有可以让硬体与软体工作的资讯，所以，如果没有搞定核心的话， 那么你的系统肯定会有点小问题！好了，那么是不是将‘所有目前核心有支援的东西都给他编译进去我的核心中， 那就可以支援目前所有的硬体与可执行的工作啦！’！

这话说的是没错啦，但是你是否曾经看过一个为了怕自己今天出门会口渴、会饿、会冷、会热、会被车撞、 会摔跤、会被性骚扰，而在自己的大包包里面放了大瓶矿泉水、便当、厚外套、短裤、防撞钢梁、止滑垫、 电击棒....等一大堆东西，结果却累死在半路上的案例吗？当然有！但是很少啦！我相信不太有人会这样做！ (会这么做的人通常都已经在医院了～) 取而代之的是会看一下天气，冷了就只带外套， 热了就只带短衣、如果穿的漂亮一点又预计晚点回家就多带个电击棒、 出远门到没有便利商店的地方才多带矿泉水....

说这个干什么！对啦！就是要你了解到，核心的编译重点在于‘你要你的 Linux 作什么？’，是啦！如果没有必要的工作，就干脆不要加在你的核心当中了！这样才能让你的 Linux 跑得更稳、更顺畅！这也是为什么我们要编译核心的最主要原因了！

  • Linux 核心特色，与预设核心对终端用户的角色

Linux 的核心有几个主要的特色，除了‘Kernel 可以随时、随各人喜好而更动’之外，Kernel 的‘版本更动次数太频繁’也是一个特点！所以啰，除非你有特殊需求， 否则一次编译成功就可以啦！不需要随时保持最新的核心版本，而且也没有必要 (编译一次核心要粉久的ㄋㄟ！) 。话说到这里又突然想到今天看到的一篇文章，大意是说老板想要雇用的人会希望是 Linux 的老手，因为他们比较容易了解问题的所在，除此之外，如果有任何问题发生，由于其使用 Linux 是可以随时修补漏洞的！但是如果是 Windows 的话，就得要将机器关闭，直到 MS 推出修补套件后才能再启用～

那么是否‘我就一定需要在安装好了 Linux 之后就赶紧给他编译核心呢？’， 老实说，‘并不需要的’！这是因为几乎每一个 distribution 都已经预设编译好了相当大量的模组了， 所以使用者常常或者可能会使用到的资料都已经被编译成为模组，也因此，呵呵！ 我们使用者确实不太需要重新来编译核心！尤其是‘一般的使用者， 由于系统已经将核心编译的相当的适合一般使用者使用了，因此一般入门的使用者，基本上， 不太需要编译核心’。

  • 核心编译的可能目的

OK！那么鸟哥闲闲没事干跑来写个什么东西？既然都不需要编译核心还写编译核心的分享文章， 鸟哥卖弄才学呀？很抱歉，鸟哥虽然是个‘不学有术’的混混，却也不会平白无故的写东西请您来指教～ 当然是有需要才会来编译核心啦！编译核心的时机可以归纳为几大类：

  • 新功能的需求：
    我需要新的功能，而这个功能只有在新的核心里面才有，那么为了获得这个功能，只好来重新编译我的核心了。例如 iptables 这个防火墙机制只有在 2.4.xx 以后的版本里面才有，而新开发的主机板晶片组， 很多也需要新的核心推出之后，才能正常而且有效率的工作！

  • 原本核心太过臃肿：
    如果你是那种对于系统‘稳定性’很要求的人，对于核心多编译了很多莫名其妙的功能而不太喜欢的时候， 那么就可以重新编译核心来取消掉该功能啰；

  • 与硬体搭配的稳定性：
    由于原本 Linux 核心大多是针对 Intel 的 CPU 来作开发的，所以如果你的 CPU 是 AMD 的系统时，有可能 (注意！只是有可能，不见得一定会如此) 会让系统跑得‘不太稳！’。此外，核心也可能没有正确的驱动新的硬体，此时就得重新编译核心来让系统取得正确的模组才好。

  • 其他需求 (如嵌入式系统)：
    就是你需要特殊的环境需求时，就得自行设计你的核心啰！( 像是一些商业的套装软体系统，由于需要较为小而美的作业系统， 那么他们的核心就需要更简洁有力了！)

另外，需要注意重新编译核心虽然可以针对你的硬体作最佳化的步骤 (例如刚刚提到的 CPU 的问题！) ，不过由于这些最佳化的步骤对于整体效能的影响是很小很小的， 因此如果是为了增加效能来编译核心的话，基本上，效益不大！然而，如果是针对‘系统稳定性’来考量的话， 那么就有充分的理由来支持你重新编译核心啰！

‘如果系统已经运行很久了，而且也没有什么大问题， 加上我又不增加冷门的硬体设备，那么建议就不需要重新编译核心了’， 因为重新编译核心的最主要目的是‘想让系统变的更稳！’既然你的 Linux 主机已经达到这个目的了，何必再编译核心？不过，就如同前面提到的， 由于预设的核心不见得适合你的需要，加上预设的核心可能并无法与你的硬体配备相配合， 此时才开始考虑重新编译核心吧！

Tips:
早期鸟哥是强调最好重新编译核心的一群啦！不过，最近这个想法改变了～ 既然原本的 distribution 都已经帮我们考虑好如何使用核心了，那么， 我们也不需要再重新的编译核心啦！尤其是 distribution 都会主动的释出新版的核心 RPM 版本， 所以，实在不需要自己重新编译的！当然啦，如同前面提到的， 如果你有特殊需求的话，那就另当别论噜！ ^_^ 		鸟哥的图示

由于‘核心的主要工作是在控制硬体！’所以编译核心之前， 请先了解一下你的硬体配备，与你这部主机的未来功能！由于核心是‘越简单越好！’所以只要将这部主机的未来功能给他编进去就好了！ 其他的就不用去理他啦！

小标题的图示 核心的版本

核心的版本问题，我们在第一章已经谈论过， 主要的版本定义为：‘[主].[次].[释出]-[修改]’的样式。 你只要知道 2.6.x 是稳定版本，2.5.x 是测试用版本即可。 我们要使用最新的核心来重新编译核心时，大多就是使用那种偶数的核心版本啦！不过这里还是要再提一遍！就是‘ 2.4.x 与 2.6.x 是两个具有相当大差异的核心版本， 两者之间使用到的函式库基本上已经不相同了，所以在升级之前，如果你的核心原本是 2.4.xx 版，那么就升级到 2.4.xx 版本的最新版，不要由 2.4.xx 直接升级到 2.6.xx 版，否则到时可能会欲哭无泪～～’， 这个问题在讨论区一再地被提起！这里再次说明！

Tips:
为什么不能从 2.4 升级到 2.6 呢？其实还是可以啦！只是过程很复杂！ 我们知道软体 (packages) 是架构在系统核心上面来进行编译、安装与执行的， 也就是说，这些 packages 与核心之间，是有相关性的！这些 packages 会用到很多核心提供的功能。 但是不同的[主][次]版本之间，他们提供的功能架构差异太大，因此，若你由 2.4 升级到 2.6 的话， 那么绝大部分的软体‘都需要重新再编译！’这样了解为何不要在不同的版本间升级了吧？ 		鸟哥的图示

此外，2.4.xx 与 2.6.xx 的比较中，并不是 2.6.xx 就一定比 2.4.xx 还要新，因为这两种版本同时在进行维护与升级的工作！如果有兴趣的话，可以前往 Linux 核心网站 http://www.kernel.org 一看究竟，你就可以了解目前的核心变动情况了！

基本上，目前最新的 distributions ，包括 CentOS, FC, SuSE, Mandriva 等等，都使用 2.6 的核心， 所以，你可以直接由 http://www.kernel.org 下载最新的 2.6.xx 版本的核心来尝试编译啊！目前 (2009/07/27) 鸟哥可以查到的最新版本是 2.6.30 ， 底下我们将主要以这个版本来测试。另外，由于较新的核心版本可能会多出一些选项， 因此若有不同的项目也没有关系！稍微查看一下说明内容就可以了解啦！

小标题的图示 核心原始码的取得方式

既然核心是个档案，要制作这个档案给系统使用则需要编译，既然要有编译，当然就得要有原始码啊！ 那么原始码怎么来？基本上，依据你的 distributions 去挑选的核心原始码来源主要有：

  • 原本 distribution 提供的核心原始码档案

事实上，各主要 distributions 在推出他们的产品时，其实已经都附上了核心原始码了！ 以我们的 CentOS 5.x 为例，你可以在国家高速网路中心网站下载相关的核心 SRPM 的档案！ 由于 CentOS 5.x 一直有在进行更新动作，因此你也可以在 update 的目录底下找到核心原始码喔！如下连结所示：

  • 原始推出核心码：http://ftp.twaren.net/Linux/CentOS/5/os/SRPMS/
  • 更新码：http://ftp.twaren.net/Linux/CentOS/5/updates/SRPMS/

你或许会说：既然要重新编译，那么干嘛还要使用原本 distributions 释出的原始码啊？真没创意～ 话不是这么说，因为原本的 distribution 释出的原始码当中，含有他们设定好的预设设定值， 所以，我们可以轻易的就了解到当初他们是如何选择与核心及模组有关的各项设定项目的参数值， 那么就可以利用这些可以配合我们 Linux 系统的预设参数来加以修改，如此一来， 我们就可以‘修改核心，调整到自己喜欢的样子’啰！而且编译的难度也会比较低一点！

  • 取得最新的稳定版核心原始码

虽然使用 distribution 释出的核心 source code 来重新编译比较方便，但是，如此一来， 新硬体所需要的新驱动程式，也就无法藉由原本的核心原始码来编译啊！ 所以啰，如果是站在要更新驱动程式的立场来看，当然使用最新的核心可能会比较好啊！

Linux 的核心目前是由其发明者 Linus Torvalds 所属团队在负责维护的，而其网站在底下的站址上，在该网站上可以找到最新的 kernel 资讯！不过，美中不足的是目前的核心越来越大了 (linux-2.6.30.3.tar.bz2 这一版，这一个档案大约 57MB 了！)，所以如果你的 ISP 连外很慢的话，那么使用台湾的映射站台来下载不失为一个好方法：

  • 核心官网：http://www.kernel.org/
  • 交大资科：ftp://linux.cis.nctu.edu.tw/kernel/linux/kernel/
  • 国高中心：ftp://ftp.twaren.net/pub/Unix/Kernel/linux/kernel/

  • 保留原本设定：利用 patch 升级核心原始码

如果 (1)你曾经自行编译过核心，那么你的系统当中应该已经存在前几个版本的核心原始码， 以及上次你自行编译的参数设定值才对； (2)如果你只是想要在原本的核心底下加入某些特殊功能， 而该功能已经针对核心原始码推出 patch 补丁档案时。那你该如何进行核心原始码的更新，以便后续的编译呢？

其实每一次核心释出时，除了释出完整的核心压缩档之外，也会释出‘该版本与前一版本的差异性 patch 档案’， 关于 patch 的制作我们已经在第二十二章当中提及， 你可以自行前往参考。这里仅是要提供给你的资讯是，每个核心的 patch 仅有针对前一版的核心来分析而已， 所以，万一你想要由 2.6.27 升级到 2.6.30 的话，那么你就得要下载 patch-2.6.28, patch-2.6.29, patch-2.6.30 等档案，然后‘依序’一个一个的去进行 patch 的动作后， 才能够升级到 2.6.30 喔！这个重要！不要忘记了。

但是，如果你想要升级 2.6.30 的修改版本到 2.6.30.3 时，由于修改版本是针对 2.6.30 来制作的， 因此你只要下载 patch-2.6.30.3 来直接将 2.6.30 升级至 2.6.30.3 即可。但反过来说，如果你要从 2.6.30.2 升级到 2.6.30.3 呢？很抱歉的是，并没有 2.6.30.2 到 2.6.30.3 的补丁档案，所以你必须要将 2.6.30.2 还原至 2.6.30， 然后才能使用 patch-2.6.30.3 来升级 2.6.30 喔！注意这个差异！

同样的，如果是某个硬体或某些非官方认定的核心添加功能网站所推出的 patch 档案时，你也必须要了解该 patch 档案所适用的核心版本，然后才能够进行 patch ，否则容易出现重大错误喔！这个项目对于某些商业公司的工程师来说是很重要的。 举例来说，鸟哥的一个高中同学在业界服务，他主要是进行类似 Eee PC 开发的计划，然而该计划的硬体是该公司自行推出的！ 因此，该公司必须要自行搭配核心版本来设计他们自己的驱动程式，而该驱动程式并非 GPL 授权，因此他们就得要自行将驱动程式整合进核心！如果改天他们要将这个驱动程式释出，那么就得要利用 patch 的方式， 将硬体驱动程式档案释出，我们就得要自行以 patch 来更新核心啦！

在进行完 patch 之后，你可以直接检查一下原本的设定值，如果没有问题， 就可以直接编译，而不需要再重新的选择核心的参数值，这也是一个省时间的方法啊！ 至于 patch file 的下载，同样是在 kernel 的相同目录下，寻找档名是 patch 开头的就是了。

小标题的图示 核心原始码的解压缩/安装/观察

由于鸟哥是比较喜欢直接由核心官网取得原始核心的家伙，所以，底下的动作是使用 2.6.30.3 这个版本的核心来安装的！ 如果你想要使用 distributions 提供的 SRPM 来处理的话，得自行找到 SRPM 的相关安装方法来处理啰！ 其实看一下第二十二章就知道该如何处理啦。 总之，本章的核心原始码是由底下的连结取得的：

  • ftp://linux.cis.nctu.edu.tw/kernel/linux/kernel/v2.6/linux-2.6.30.3.tar.bz2

  • 核心原始码的解压缩与放置目录

鸟哥这里假设你也是下载上述的连结内的档案，然后该档案放置到 /root 底下。由于 2.6.x 核心原始码一般建议放置于 /usr/src/kernels/ 目录底下，因此你可以这样处理：

[root@www ~]# tar -jxvf linux-2.6.30.3.tar.bz2 -C /usr/src/kernels/

此时会在 /usr/src/kernels 底下产生一个新的目录，那就是 linux-2.6.30.3 这个目录啰！ 我们在下个小节会谈到的各项编译与设定，都必须要在这个目录底下进行才行喔！好了，那么这个目录底下的相关档案有啥咚咚？ 底下就来谈谈：

  • 核心原始码下的次目录

在上述核心目录下含有哪些重要资料呢？基本上有底下这些东西：

  • arch ：与硬体平台有关的项目，大部分指的是 CPU 的类别，例如 x86, x86_64, Xen 虚拟支援等；
  • block ：与区块装置较相关的设定资料，区块资料通常指的是大量储存媒体！还包括类似 ext3 等档案系统的支援是否允许等。
  • crypto ：核心所支援的加密的技术，例如 md5 或者是 des 等等；
  • Documentation ：与核心有关的一堆说明文件，若对核心有极大的兴趣，要瞧瞧这里！
  • drivers ：一些硬体的驱动程式，例如显示卡、网路卡、PCI 相关硬体等等；
  • firmware ：一些旧式硬体的微指令码 (韧体) 资料；
  • fs ：核心所支援的 filesystems ，例如 vfat, reiserfs, nfs 等等；
  • include ：一些可让其他程序呼叫的标头 (header) 定义资料；
  • init ：一些核心初始化的定义功能，包括挂载与 init 程式的呼叫等；
  • ipc ：定义 Linux 作业系统内各程序的沟通；
  • kernel ：定义核心的程序、核心状态、执行绪、程序的排程 (schedule)、程序的讯号 (signle) 等
  • lib ：一些函式库；
  • mm ：与记忆体单元有关的各项资料，包括 swap 与虚拟记忆体等；
  • net ：与网路有关的各项协定资料，还有防火墙模组 (net/ipv4/netfilter/*) 等等；
  • security ：包括 selinux 等在内的安全性设定；
  • sound ：与音效有关的各项模组；
  • virt ：与虚拟化机器有关的资讯，目前核心支援的是 KVM (Kernel base Virtual Machine)

这些资料先大致有个印象即可，至少未来如果你想要使用 patch 的方法加入额外的新功能时， 你要将你的原始码放置于何处？这里就能够提供一些指引了。当然，最好还是跑到 Documentation 那个目录底下去瞧瞧正确的说明， 对你的核心编译会更有帮助喔！

大标题的图示 核心编译的前处理与核心功能选择

什么？核心编译还要进行前处理？没错啦！事实上，核心的目的在管理硬体与提供系统核心功能，因此你必须要先找到你的系统硬体， 并且规划你的主机未来的任务，这样才能够编译出适合你这部主机的核心！所以，整个核心编译的重要工作就是在‘挑选你想要的功能’。 底下鸟哥就以自己的一部主机软/硬体环境来说明，解释一下如何处理核心编译啰！

小标题的图示 硬体环境检视与核心功能要求

鸟哥的一部主机硬体环境如下 (透过 /proc/cpuinfo 及 lspci 观察)：

  • CPU：AMD 的 Athlon64 3000+ (旧式，不含虚拟化功能)
  • 主机板晶片组： ALi M1689 K8 北桥 及 M5249, M1563 南桥晶片 (较冷门的硬体)
  • 显示卡： AGP 8X 的 NVidia GeForce 6600LE
  • 记忆体： 2.0GB 记忆体
  • 硬碟： WD 2.5GB 硬碟，使用 ALi, ULi 5289 SATA 介面
  • 电源控制器： ALi M7101 Power Management Controller (PMU)
  • 网路卡： 3Com 3c905C-TX/TX-M (对外)
  • 网路卡： Realtek Semiconductor RTL-8139/8139C/8139C+

硬体大致如上，至于这部主机的需求，是希望做为未来在鸟哥上课时，可以透过虚拟化功能来处理学生的练习用虚拟机器。 这部主机也是鸟哥用来放置学校上课教材的机器，因此，这部主机的 I/O 需求须要好一点，未来还需要开启防火墙、 WWW 伺服器功能、FTP 伺服器功能等，基本上，用途就是一部小型的伺服器环境啰。大致上需要这样的功能啦！

小标题的图示 保持干净原始码： make mrproper

了解了硬体相关的资料后，我们还得要处理一下核心原始码底下的残留档案才行！假设我们是第一次编译， 但是我们不清楚到底下载下来的原始码当中有没有保留目标档案 (*.o) 以及相关的设定档存在， 此时我们可以透过底下的方式来处理掉这些编译过程的目标档案以及设定档：

[root@www linux-2.6.30.3]# make mrproper

请注意，这个动作会将你以前进行过的核心功能选择档案也删除掉， 所以几乎只有第一次执行核心编译前才进行这个动作，其余的时刻，你想要删除前一次编译过程的残留资料， 只要下达：

[root@www linux-2.6.30.3]# make clean

因为 make clean 仅会删除类似目标档之类的编译过程产生的中间档案，而不会删除设定档！ 很重要的！千万不要搞乱了喔！好了，既然我们是第一次进行编译，因此，请下达‘make mrproper’吧！

小标题的图示 开始挑选核心功能： make XXconfig

不知道你有没有发现 /boot/ 底下存在一个名为 config-xxx 的档案？那个档案其实就是核心功能列表档！ 我们底下要进行的动作，其实就是作出该档案！而我们后续小节所要进行的编译动作，其实也就是透过这个档案来处理的！ 核心功能的挑选，最后会在 /usr/src/kernels/linux-2.6.30.3/ 底下产生一个名为 .config 的隐藏档， 这个档案就是 /boot/config-xxx 的档案啦！那么这个档案如何建立呢？你可以透过非常多的方法来建立这个档案！ 常见的方法有：(注1)

  • make menuconfig
    最常使用的，是文字模式底下可以显示类似图形介面的方式，不需要启动 X Window 就能够挑选核心功能选单！

  • make oldconfig
    透过使用已存在的 ./.config 档案内容，使用该档案内的设定值为预设值，只将新版本核心内的新功能选项列出让使用者选择， 可以简化核心功能的挑选过程！对于作为升级核心原始码后的功能挑选来说，是非常好用的一个项目！

  • make xconfig
    透过以 Qt 为图形介面基础功能的图形化介面显示，需要具有 X window 的支援。例如 KDE 就是透过 Qt 来设计的 X Window，因此你如果在 KDE 画面中，可以使用此一项目。

  • make gconfig
    透过以 Gtk 为图形介面基础功能的图形化介面显示，需要具有 X window 的支援。例如 GNOME 就是透过 Gtk 来设计的 X Window，因此你如果在 GNOME 画面中，可以使用此一项目。

  • make config
    最旧式的功能挑选方法，每个项目都以条列式一条一条的列出让你选择，如果设定错误只能够再次选择，很不人性化啊！

大致的功能选择有上述的方法，不过鸟哥个人比较偏好 make menuconfig 这个项目啦！如果你喜欢使用图形介面， 然后使用滑鼠去挑选所需要的功能时，也能使用 make xconfig 或 make gconfig ，不过需要有相关的图形介面支援！ 如果你是升级核心原始码并且需要重新编译，那么使用 make oldconfig 会比较适当！好了，那么如何选择呢？ 以 make menuconfig 来说，出现的画面会有点像这样：

make menuconfig 核心功能挑选选单示意图
图 2.3.1 、 make menuconfig 核心功能挑选选单示意图

看到上面的图示之后，你会发现画面主要分为两大部分，一个是大框框内的反白光柱，另一个则是底下的小框框， 里面有 select, exit 与 help 三个选项的内容。这几个元件的大致用法如下：

  • ‘左右方向键’：可以移动最底下的 <Select>, <Exit>, <Help>项目；
  • ‘上下方向键’：可以移动上面大框框部分的反白光柱，若该行有箭头 (--->) 则表示该行内部还有其他细项需要来设定的意思；
  • 选定项目：以‘上下键’选择好想要设定的项目之后，并以‘左右键’选择 <Select> 之后， 按下‘ Enter ’就可以进入该项目去作更进一步的细部设定啰；
  • 可挑选之功能：在细部项目的设定当中，如果前面有 [ ] 或 < > 符号时，该项目才可以选择， 而选择可以使用‘空白键’来选择；
  • 若为 [*] <*> 则表示编译进核心；若为 <M> 则表示编译成模组！ 尽量在不知道该项目为何时，且有模组可以选，那么就可以直接选择为模组啰！
  • 当在细项目选择 <Exit> 后，并按下 Enter ，那么就可以离开该细部项目啰！

基本上建议只要‘上下左右的方向键、空白键、Enter’这六个按键就好了！不要使用 Esc ，否则一不小心就有可能按错的！另外，关于整个核心功能的选择上面，建议你可以这样思考：

  • ‘肯定’核心一定要的功能，直接编译进核心内；
  • ‘可能在未来会用到’的功能，那么尽量编译成为模组；
  • ‘不知道那个东西要干嘛的，看 help 也看不懂’的话，那么就保留预设值，或者将他编译成为模组；

总之，尽量保持核心小而美，剩下的功能就编译成为模组，尤其是‘需要考虑到未来扩充性’， 像鸟哥之前认为螃蟹卡就够我用的了，结果，后来竟然网站流量大增，鸟哥只好改换 3Com 的网路卡。 不过，我的核心却没有相关的模组可以使用～因为.....鸟哥自己编译的核心忘记加入这个模组了。 最后，只好重新编译一次核心的模组，呵呵！真是惨痛的教训啊！

小标题的图示 核心功能细项选择

由上面的图示当中，我们知道核心的可以选择的项目有很多啊！光是第一面，就有 16 个项目，每个项目内还有不同的细项！哇！真是很麻烦啊～每个项目其实都可能有 <Help> 的说明，所以，如果看到不懂的项目，务必要使用 Help 查阅查阅！ 好了，底下我们就一个一个项目来看看如何选择吧！

  • General setup

与 Linux 最相关的程序互动、核心版本说明、是否使用发展中程式码等资讯都在这里设定的。 这里的项目主要都是针对核心与程式之间的相关性来设计的，基本上，保留预设值即可！ 不要随便取消底下的任何一个项目，因为可能会造成某些程式无法被同时执行的困境喔！ 不过底下有非常多新的功能，如果你有不清楚的地方，可以按 <Help> 进入查阅，里面会有一些建议！ 你可以依据 Help 的建议来选择新功能的启动与否！

[ ] Prompt for development and/or incomplete code/drivers
    # 这个建议不要选择，因为我们不是核心专家，不需要使用发展中或不完整的程式码！
(vbird)  Local version - append to kernel release
[*] Automatically append version information to the version string
    # 我希望我的核心版本成为 2.6.30.3.vbird ，那这里可以就这样设定！
    Kernel compression mode (Bzip2)  --->
    # 建议选择成为 Bzip2 即可，因为压缩比较佳！
[*] Support for paging of anonymous memory (swap)
    # 任何人均可存取 swap 是合理的！所以这里务必要勾选！
[*] System V IPC
    # IPC 是 Inter Process Communication (程序通讯) 缩写，与程序沟通有关，要选！
[*] BSD Process Accounting
[ ]   BSD Process Accounting version 3 file format
    # 与标准 Unix (BSD) 的程序支援有关，但不要支援 version 3 ，可能有相容性问题
[ ] Export task/process statistics through netlink (EXPERIMENTAL)
    # 这个额外的进阶选项可以将他取消的！
[*] Auditing support
[*]   Enable system-call auditing support
    # 上面这两个是额外核心功能 (如 SELinux) 载入时所需要的设定！务必选择
    RCU Subsystem  --->
      RCU Implementation (Classic RCU)  --->
    # 选择标准 RCU 即可，不需要使用大量 CPU 的整合功能。
<M> Kernel .config support
[ ]   Enable access to .config through /proc/config.gz (NEW)
    # 让 .config 这个核心功能列表可以写入实际的核心档案中！
(17) Kernel log buffer size (16 => 64KB, 17 => 128KB)
[ ] Control Group support (NEW)  --->
    # 整合 CPU 或分离装置的功能，属于进阶设定，我们先不要使用这功能。
[*] Create deprecated sysfs layout for older userspace tools (NEW)
    # 如果使用支援旧式装置，如 /sys/devices 者，这里要勾选！但如果是 2008
    # 年后的 distribution ，这里可能需要取消喔！ CentOS 5.x 要选的！
-*- Kernel->user space relay support (formerly relayfs)
-*- Namespaces support
[*]   UTS namespace (NEW)
[*]   IPC namespace (NEW)
    # 使用 uname 时，会输出较多的资讯，所以可以尝试选择看看。
[*] Initial RAM filesystem and RAM disk (initramfs/initrd) support
()    Initramfs source file(s)
    # 这是一定要的！因为要支援开机时载入 initail RAM disk 嘛！
[*] Optimize for size
    # 可以减低核心的档案大小，其实是 gcc 参数使用 -Os 而不是 -O2
[ ] Configure standard kernel features (for small systems)  --->
    # 给嵌入式系统使用的，我们用 PC ，所以这里不选。
[ ] Strip assembler-generated symbols during link (NEW)
[ ] Disable heap randomization (NEW)
    # 2000 年后推出的版本，可以取消这个项目！
    Choose SLAB allocator (SLAB)  --->
[*] Profiling support (EXPERIMENTAL)
[ ] Activate markers (NEW)
<M> OProfile system profiling (EXPERIMENTAL)
[ ]   OProfile AMD IBS support (EXPERIMENTAL) (NEW)
[*] Kprobes

  • loadable module + block layer

要让你的核心能够支援动态的核心模组，那么底下的第一个设定就得要启动才行！至于第二个 block layer 则预设是启动的， 你也可以进入该项目的细项设定，选择其中你认为需要的功能即可！

[*] Enable loadable module support  ---> <==底下为细项
  --- Enable loadable module support
  [ ]   Forced module loading     <==大概就是这个不要选，其他的都选起来！
  [*]   Module unloading
  [*]   Module versioning support
  [*]   Source checksum for all module
================================================================================
-*- Enable the block layer  --->  <==看吧！预设就是已经选择了！底下为细项
  [ ]   Block layer data integrity support  <==特殊储存装置支援，可以不选
        IO Schedulers  --->
         <*> Anticipatory I/O scheduler  <==较复杂的一种I/O排程
         <*> Deadline I/O scheduler      <==较适用于 database 的载入
         <*> CFQ I/O scheduler           <==较适用于 desktop 的环境
             Default I/O scheduler (Deadline)  ---> <==适用于鸟哥环境

  • CPU 的类型与功能选择

进入‘Processor type and features’后，请挑选你主机的实际 CPU 形式。鸟哥这里使用的是 Athlon 64 的 CPU， 而且鸟哥的主机还有启动 Xen 这个虚拟化的服务 (在一部主机上面同时启动多个作业系统)，因此，所以底下的选择是这样的：

[*] Tickless System (Dynamic Ticks)    <==可增加些许省电功能
[ ] High Resolution Timer Support
[*] Symmetric multi-processing support <==多核心 CPU 环境必选
[ ] Support sparse irq numbering
[*] Enable MPS table                   <==让多 CPU 支援 ACPI
[ ] Support for extended (non-PC) x86 platforms
[*] Single-depth WCHAN output
[*] Paravirtualized guest support  --->  <==支援半虚拟化功能
     --- Paravirtualized guest support <==底下为 Xen 与 KVM 两种虚拟机器支援！
     [*]   Xen guest support
     (32)    Maximum allowed size of a domain in gigabytes
     [*]     Enable Xen debug and tuning parameters in debugfs
     [*]   KVM paravirtualized clock
     [*]   KVM Guest support
     -*-   Enable paravirtualization code
================================================================================
[ ] paravirt-ops debugging (NEW)  <==不需要具有 debug 的功能
[ ] Memtest
    Processor family (Opteron/Athlon64/Hammer/K8)  ---> <==要选对啊！
[*] AMD IOMMU support <==启动 AMD 的 IOMMU 功能！
(8) Maximum number of CPUs
[ ] SMT (Hyperthreading) scheduler support <==Intel CPU 的超执行绪功能
[*] Multi-core scheduler support <==多核心功能的支援
    Preemption Model (No Forced Preemption (Server))  --->
    # 这是与程序有关的设定项目，鸟哥这里建立 Server 主机，因此选这项！
    # 如果是桌上型电脑的使用，建议进入选择 desktop 项目。
[ ] Reroute for broken boot IRQs
[*] Machine Check Exception <==可将核心侦测之错误回报到终端机显示！
[*]   Intel MCE features (NEW)
[*]   AMD MCE features (NEW)
< > Dell laptop support
<M> /dev/cpu/microcode - microcode support
[ ]   Intel microcode patch loading support
[*]   AMD microcode patch loading support
<M> /dev/cpu/*/msr - Model-specific register support
<*> /dev/cpu/*/cpuid - CPU information support
< > /sys/kernel/debug/x86/cpu/* - CPU Debug support
[ ] Numa Memory Allocation and Scheduler Support
    Memory model (Sparse Memory)  --->
[*] Sparse Memory virtual memmap <==可强化些许核心效能
[ ] Allow for memory hot-add
[*] Add LRU list to track non-evictable pages
(65536) Low address space to protect from user allocation
[ ] Check for low memory corruption
[*] Reserve low 64K of RAM on AMI/Phoenix BIOSen <==重新侦测 BIOS 资讯
[*] MTRR (Memory Type Range Register) support
    # 可以让 CPU 具有读取记忆体特殊区块的能力，尤其在高效能的显示卡方面，
    # 可以增进不少效能。这个项目会产生 /proc/mtrr ，X 会读取这个咚咚喔。
[*]   MTRR cleanup support
(0)     MTRR cleanup enable value (0-1)
(1)     MTRR cleanup spare reg num (0-7)
[ ]   x86 PAT support
[ ] EFI runtime service support
[*] Enable seccomp to safely compute untrusted bytecode
    Timer frequency (300 HZ)  --->
    # 这个项目则与核心针对某个事件立即回应的速度有关。Server 用途可以调整到
    # 300Hz 即可，如果是桌上型电脑使用，需要调整高一点，例如 1000Hz 较佳！
[*] kexec system call
[ ] kernel crash dumps
-*- Support for hot-pluggable CPUs
[ ] Compat VDSO support  <==旧式功能，可以不要选择
[ ] Built-in kernel command line <==正常开机选单 (grub) 环境，不需要此项功能

  • 电源管理功能

如果选择了‘Power management and ACPI options’之后，就会进入系统的电源管理机制中。 其实电源管理机制还需要搭配主机板以及 CPU 的相关省电功能，才能够实际达到省电的效率啦！ 不论是 Server 还是 Desktop 的使用，在目前电力不足的情况下，能省电就加以省电吧！

[*] Power Management support
[ ]   Power Management Debug Support
[*] Suspend to RAM and standby
[ ] Hibernation (aka 'suspend to disk')
[*] ACPI (Advanced Configuration and Power Interface) Support  --->
    # 这是个较新的电源管理模组，由于选择后会增加核心约 70K ，所以
    # 对嵌入式系统来说，可能需要考虑考虑。至于 desktop/server 当然就选择啊
    --- ACPI (Advanced Configuration and Power Interface) Support
    [ ]   Deprecated /proc/acpi files
    [*]   Deprecated power /proc/acpi directories
    [*]   Future power /sys interface
    [*]   Deprecated /proc/acpi/event support
    <M>   AC Adapter
    <M>   Battery
    <M>   Button
    -M-   Video
    <*>   Fan
    <*>   Processor
    <*>     Thermal Zone
    [ ]   Debug Statements
    <M>   PCI slot detection driver
    <M>   Smart Battery System
================================================================================
    CPU Frequency scaling  --->
    # 可以经过核心修改 CPU 的运作频率，在说明档当中也提及，还需要启动底下的
    # dynamic cpufreq governor 才可以顺利的启动这个项目。
    [*] CPU Frequency scaling
    [*]   Enable CPUfreq debugging
    <M>   CPU frequency translation statistics
    [*]     CPU frequency translation statistics details
          Default CPUFreq governor (userspace)  --->
    -*-   'performance' governor
    <M>   'powersave' governor
    <M>   'userspace' governor for userspace frequency scaling
    <M>   'ondemand' cpufreq policy governor
    -*-   'conservative' cpufreq governor
          *** CPUFreq processor drivers ***
    <M>   ACPI Processor P-States driver
    <*>   AMD Opteron/Athlon64 PowerNow!  <==因为我们是 AMD 的 CPU 啊！
    <M>   Intel Enhanced SpeedStep (deprecated)
    < >   Intel Pentium 4 clock modulation
================================================================================
-*- CPU idle PM support
    Memory power savings  --->

  • 一些汇流排 (bus) 的选项

这个项目则与汇流排有关啦！分为最常见的 PCI 与 PCI-express 的支援，还有笔记型电脑常见的 PCMCIA 插卡啊！要记住的是，那个 PCI-E 的介面务必要选取！不然你的新显示卡可能会捉不到！

[*] PCI support
[*]   Support mmconfig PCI config space access
[*] PCI Express support
<M>   PCI Express Hotplug driver
[*]   Root Port Advanced Error Reporting support
-*- Message Signaled Interrupts (MSI and MSI-X)
[*] Enable deprecated pci_find_* API
[ ] PCI Debugging
<M> PCI Stub driver
[*] Interrupts on hypertransport devices
[*] PCI IOV support  <==与虚拟化有关！请加选此项！
< > PCCard (PCMCIA/CardBus) support  ---> <==鸟哥的主机不是 notebook，所以不选。
<*> Support for PCI Hotplug  --->  <==不关机情况下，热拔插 PCI 装置
    --- Support for PCI Hotplug
    <M>   Fake PCI Hotplug driver
    <M>   ACPI PCI Hotplug driver
    <M>     ACPI PCI Hotplug driver IBM extensions
    [ ]   CompactPCI Hotplug driver
    <M>   SHPC PCI Hotplug driver

  • 编译后执行档的格式

选择‘Executable file formats / Emulations’会见到如下选项。 底下的选项必须要勾选才行喔！因为是给 Linux 核心运作执行档之用的资料。通常是与编译行为有关啦！

[*] Kernel support for ELF binaries
[ ] Write ELF core dumps with partial segments
<*> Kernel support for MISC binaries
[*] IA32 Emulation  <==因为我们这里是 64 位元，因此 32 位元为模拟结果
<M>   IA32 a.out support

  • 核心的网路功能

这个‘Networking support’项目是相当重要的选项，因为他还包含了防火墙相关的项目！就是未来在伺服器篇会谈到的防火墙 iptables 这个资料啊！所以，千万注意了！在这个设定项目当中，很多东西其实我们在基础篇还没有讲到， 因为大部分的参数都与网路、防火墙有关！由于防火墙是在启动网路之后再设定即可，所以绝大部分的内容都可以被编译成为模组，而且也建议你编成模组！有用到再载入到核心即可啊！

--- Networking support
      Networking options  --->
      # 就是这个光啊！里面的资料全部都是重要的防火墙项目！尽量编成模组啰！
      # 至于不晓得功能的部分，就尽量保留预设值即可！
      <*> Packet socket          <==网路封包，当然要选择啊！
      [*]   Packet socket: mmapped IO
      <*> Unix domain sockets    <==Unix 插槽档，也一定要选择啊！
      <*> Transformation user configuration interface
      <M> PF_KEY sockets
      [*] TCP/IP networking      <==能不选择 TCP/IP 吗？
      [*]   IP: multicasting
      [*]   IP: advanced router
             Choose IP: FIB lookup algorithm (FIB_HASH)  --->
      [*]   IP: policy routing
      [*]   IP: equal cost multipath
      [*]   IP: verbose route monitoring
      [ ]   IP: kernel level autoconfiguration
      <M>   IP: tunneling
      <M>   IP: GRE tunnels over IP
      [*]     IP: broadcast GRE over IP
      [*]   IP: multicast routing
      [*]     IP: PIM-SM version 1 support
      [*]     IP: PIM-SM version 2 support
      [*]   IP: TCP syncookie support (disabled per default)
      <M>   IP: AH transformation
      <M>   IP: ESP transformation
      <M>   IP: IPComp transformation
      <M>   IP: IPsec transport mode
      <M>   IP: IPsec tunnel mode
      <*>   IP: IPsec BEET mode
      -*-   Large Receive Offload (ipv4/tcp)
      <M>   INET: socket monitoring interface
      [*]   TCP: advanced congestion control  ---> <==内部细项全为模组
      <M>   The IPv6 protocol  ---> <==除必选外，内部细项全为模组
      [*]   NetLabel subsystem support
      -*- Security Marking
      [*] Network packet filtering framework (Netfilter)  --->
      # 这个就是我们一直讲的防火墙部分！里面细项几乎全选择成为模组！
          --- Network packet filtering framework (Netfilter)
          [ ]   Network packet filtering debugging  <==debug 部分不选！
          [*]   Advanced netfilter configuration
          [*]     Bridged IP/ARP packets filtering
                Core Netfilter Configuration  --->
          <M>   IP virtual server support  --->
                IP: Netfilter Configuration  --->
                IPv6: Netfilter Configuration  --->
          <M>   Ethernet Bridge tables (ebtables) support  --->
          # 上面的细项，除了必选外其他的都编成模组喔！原始没选的也请选为模组
================================================================================
      <M> Asynchronous Transfer Mode (ATM)
      <M>   Classical IP over ATM
      [ ]     Do NOT send ICMP if no neighbour
      <M>   LAN Emulation (LANE) support
      < >     Multi-Protocol Over ATM (MPOA) support
      <M>   RFC1483/2684 Bridged protocols
      [ ]     Per-VC IP filter kludge
      <M> 802.1d Ethernet Bridging
      <M> 802.1Q VLAN Support
      [ ]   GVRP (GARP VLAN Registration Protocol) support
      <M> DECnet Support
      <M> ANSI/IEEE 802.2 LLC type 2 Support
      [ ]   IPX: Full internal IPX network (NEW)
      <M> Appletalk protocol support
      < >   Appletalk interfaces support
      <M> Phonet protocols family
      [*] QoS and/or fair queueing  ---> <==内容同样全为模组！
      [ ] Data Center Bridging support
          Network testing  ---> <==保留成模组预设值
================================================================================
# 底下的则是一些特殊的网路设备，例如红外线啊、蓝芽啊！
# 如果不清楚的话，就使用模组吧！除非你真的知道不要该项目！
[ ]   Amateur Radio support  --->
< >   CAN bus subsystem support  --->
< >   IrDA (infrared) subsystem support  --->
<M>   Bluetooth subsystem support  --->
      # 这个是蓝芽支援，同样的，里面除了必选之外，其他通通挑选成为模组！
[*]   Wireless  --->
      # 这个则是无线网路设备，里面保留预设值，但可编成模组的就选模组
<M>   WiMAX Wireless Broadband support  --->
      # 新一代的无线网路，也请勾选成为模组！
{M}   RF switch subsystem support  --->

  • 各项装置的驱动程式

进入‘Device Drivers’这个是所有硬体装置的驱动程式库！哇！光是看到里面这么多内容，鸟哥头都昏了～ 不过，为了你自己的主机好，建议你还是得要一个项目一个项目的去挑选挑选才行～ 这里面的资料就与你主机的硬体有绝对的关系了！

在这里面真的很重要，因为很多资料都与你的硬体有关。核心推出时的预设值是比较符合一般状态的， 所以很多资料其实保留预设值就可以编的很不错了！不过，也因为较符合一般状态， 所以核心额外的编译进来很多跟你的主机系统不符合的资料，例如网路卡装置～ 你可以针对你的主机板与相关硬体来进行编译。不过，还是要记得有‘未来扩充性’的考量！ 之前鸟哥不是谈过吗，我的网路卡由螃蟹卡换成 3Com 时，核心捉不到～ 因为...鸟哥并没有将 3Com 的网路卡编译成为模组啊！ @_@

    Generic Driver Options  --->    <==与韧体有关，保留预设值即可
<*> Connector - unified userspace <-> kernelspace linker  --->
    # 与使用者/核心层级的资讯沟通有关，务必要选择啊！
<M> Memory Technology Device (MTD) support  --->
    # 例如快闪记忆体(拇指碟之类)之支援，通常与嵌入式系统有关！
    # 但由于我们也会用到随身碟，所以里面的资料全编为模组！
<M> Parallel port support  --->
    # 平行序列埠的支援，例如早期的 25 针印表机与 9 针滑鼠等，细项全编为模组！
-*- Plug and Play support  --->     <==不啰唆！当然要选择这个项目！
[*] Block devices  --->   <==区块装置，就是一些储存媒体！细项内容请全编为模组
[*] Misc devices  --->    <==一些较冷门的设备，建议还是全部编为模组！
<*> ATA/ATAPI/MFM/RLL support  ---> <==IDE 介面相关的晶片组！
    # 这个其实与主机板的南桥晶片有关！由于鸟哥的主机为 ALi 的板子，所以：
    <*>   ALI M15x3 chipset support
    # 除了可以保留预设值之外，你也可以将没用到的驱动程式取消选择。较重要的还有：
    [ ]   Support for SATA (deprecated; conflicts with libata SATA driver)
    # 这个一定不能选！因为 SATA 的模组是在 SCSI 中！
    <*>   Include IDE/ATAPI CDROM support
    # IDE 的 CDROM 最好直接编译进核心！
    # 其余的驱动程式鸟哥几乎都选择成为模组了！没用到的晶片也将 * 也改成 M 哩！
================================================================================
    SCSI device support  --->
    # 这部份是 SCSI 储存媒体的驱动程式！请一定要选择！因为：
    # 1. 因为 USB 装置用的就是模拟 SCSI 啊！
    # 2. 因为 SATA 的设定项目就在这里面！
    <M> RAID Transport Class
    {M} SCSI device support
    [*] legacy /proc/scsi/ support
        *** SCSI support type (disk, tape, CD-ROM) ***
    <M> SCSI disk support   <==几乎全编为模组即可！
    <M> SCSI tape support
    <M> SCSI OnStream SC-x0 tape support
    <M> SCSI CDROM support
    [*]   Enable vendor-specific extensions (for SCSI CDROM)
    <M> SCSI generic support
    <M> SCSI media changer support
    <M> SCSI Enclosure Support
        *** Some SCSI devices (e.g. CD jukebox) support multiple LUNs ***
    [*] Probe all LUNs on each SCSI device
    [*] Verbose SCSI error reporting (kernel size +=12K)
    [*] SCSI logging facility
    [*] Asynchronous SCSI scanning
        SCSI Transports  --->         <==细项保留预设值
    [*] SCSI low-level drivers  --->  <==主要是磁碟阵列卡，细项可全选为模组
    <M> SCSI Device Handlers  --->    <==细项全选为模组
    < > OSD-Initiator library
================================================================================
<M> Serial ATA (prod) and Parallel ATA (experimental) drivers  --->
    # SATA 之类的磁碟驱动程式！这里的模组与 SCSI 模组是有相依属性的关系！
    # 底下的细项全部选择模组，尤其是 ALi 的这个项目，对鸟哥来说，是一定要勾选的
    <M>     ALi PATA support
[*] Multiple devices driver support (RAID and LVM)  --->
    # RAID 与 LVM 怎可不选！我们第十五章才讲过这东西！细项均保留预设值即可
[ ] Fusion MPT device support  --->
    # 一种高阶的 SCSI 控制器，可选可不选！因为鸟哥这里不会用到，所以不选！
    IEEE 1394 (FireWire) support  --->
    # 这个就是俗称的‘火线’，许多外接式设备可能会用这个介面，因此，
    # 在此部分内的细项部分，请务必设定为模组喔！不要忘了！
<M> I2O device support  --->       <==细项亦全选为模组！
[ ] Macintosh device drivers  ---> <==我们是 PC ，所以不需支援麦金塔周边
[*] Network device support  --->   <==网路设备的支援是必选！
    --- Network device support
    [*]   Enable older network device API compatibility
    <M>   Intermediate Functional Block support
    <M>   Dummy net driver support
    <M>   Bonding driver support
    <M>   EQL (serial line load balancing) support
    <M>   Universal TUN/TAP device driver support
    <M>   Virtual ethernet pair device
    <M>   General Instruments Surfboard 1000
    < >   ARCnet support  ---> <==较早期的网卡规格，可不选择！
    {M}   PHY Device support and infrastructure  ---> <==细项全为模组
    [*]   Ethernet (10 or 100Mbit)  --->
    [*]   Ethernet (1000 Mbit)  --->
    [*]   Ethernet (10000 Mbit)  --->
    # 上面三个乙太网路网卡支援，不论是否用的到，细项请全编为模组来待命吧！
    < >   Token Ring driver support  ---> <==IBM 的 LAN ，可不选！
          Wireless LAN  --->
          WiMAX Wireless Broadband devices  --->
          USB Network Adapters  --->
          # 上面三个为现阶段很热门的无线网路设备，所以全部内容的细项全选择
          # 为模组！免得未来你的主机加上新的无线设备时会找不到驱动程式！
    [ ]   Wan interfaces support  ---> <==WAN 的广域网路设备应该就不用选择了！
    [ ]   ATM drivers  ---> <==高阶的 ATM 设备也不用选吧！
    <*>   Xen network device frontend driver
    <*>   FDDI driver support
    <M>     Digital DEFTA/DEFEA/DEFPA adapter support
    [ ]       Use MMIO instead of PIO (NEW)
    <M>     SysKonnect FDDI PCI support
    <M>   PLIP (parallel port) support
    <M>   PPP (point-to-point protocol) support
    [*]     PPP filtering
    <M>     PPP support for async serial ports
    <M>     PPP support for sync tty ports
    <M>     PPP Deflate compression
    <M>     PPP BSD-Compress compression
    <M>     PPP over ATM
    # 如果你有 ADSL 拨接的话，呵呵！PPP 的装置也要选择上喔！
    <M>   SLIP (serial line) support
    [*]     CSLIP compressed headers
    [*]   Keepalive and linefill
    [ ]   Six bit SLIP encapsulation
    [*]   Fibre Channel driver support
================================================================================
[ ] ISDN support  --->
< > Telephony support  --->
    # 这两个设备没用到，所以也可以不要选择！
    Input device support  --->
    # 这里面含有滑鼠、键盘、摇杆、触控版等输入装置，尽量全选为模组吧！
    Character devices  --->
    # 周边元件设备部分，也全选为模组吧！
{M} I2C support  --->
    # 还记得我们去侦测主机板的温度与压力吧？呵呵！那就是透过核心的这个 I2C
    # 的模组功能！ALi 预设没有被编入核心，所以请进入选择成模组！
[ ] SPI support  --->
[ ] GPIO Support  --->
< > Dallas's 1-wire support  --->
-*- Power supply class support  --->
    # 绝大部分都没有用到的咚咚，所以保留预设值，不选择！
<M> Hardware Monitoring support  --->
    # 硬体侦测器的支援，记得也要挑选，然后内容全为模组！
-*- Generic Thermal sysfs driver  --->
[*] Watchdog Timer Support  ---> <==需搭配 watchdog 服务
    # 若搭配 watchdog 服务，可以设定在某些特定状况下重新启动主机！
    Sonics Silicon Backplane  --->
    Multifunction device drivers  --->
    # 鸟哥没有这样的设备，所以也没有选择！
[ ] Voltage and Current Regulator Support  --->
    Multimedia devices  --->
    # 一堆多媒体装置如影像撷取卡、FM 广播音效卡。但如果你的 Linux 是桌上型电脑，
    # 里面需要挑选成模组较佳！因为一大堆多媒体介面卡！
    Graphics support  --->  <==这就重要了！显示卡选择！
    # 嘿嘿！重点之一，显示卡的晶片组～刚刚前面提到的都是主机板的对显示卡的
    # 汇流排支援 (PCI-E 与 AGP) ，这里则是针对显示卡晶片！鸟哥的显示卡是 NVidia
    # 的，所以将他选择即可！其他的可以编成模组！
<M> Sound card support  --->
    # 音效卡部分，也全部选择成为模组啦！反正编成模组又不用钱～
[*] HID Devices  ---> <==人机介面装置，保留预设值即可(也可不选)
[*] USB support  --->
    # 不能不选的 USB ，内容也全部是模组即可！尤其底下这三个：
    <M>     EHCI HCD (USB 2.0) support
    <M>     OHCI HCD support
    <M>     UHCI HCD (most Intel and VIA) support
<M> MMC/SD/SDIO card support  --->  <==多媒体介面卡，保留预设值
< > Sony MemoryStick card support (EXPERIMENTAL)  --->
-*- LED Support  --->
[ ] Accessibility support  --->
<M> InfiniBand support  ---> <==高阶网路设备
[*] EDAC - error detection and reporting  --->
<M> Real Time Clock  ---> <==内容选为模组吧！
[ ] DMA Engine support  --->
[ ] Auxiliary Display support  --->
< > Userspace I/O drivers  --->
[*] Xen memory balloon driver
[*]   Scrub pages before returning them to system
<*> Xen filesystem
[*]   Create compatibility mount point /proc/xen
[ ] Staging drivers  --->
[ ] X86 Platform Specific Device Drivers  --->
    # 一堆笔记型电脑的驱动，可以不选啦！

底下则与 Firmware Drivers 有关喔！基本上，都保留预设值就好了！

<M> BIOS Enhanced Disk Drive calls determine boot disk
[ ]   Sets default behavior for EDD detection to off (NEW)
<M> BIOS update support for DELL systems via sysfs
<M> Dell Systems Management Base Driver
[*] Export DMI identification via sysfs to userspace
[*] iSCSI Boot Firmware Table Attributes
<M>   iSCSI Boot Firmware Table Attributes module

  • 档案系统的支援

档案系统的支援也是很重要的一项核心功能！因为如果不支援某个档案系统，那么我们的 Linux kernel 就无法认识，当然也就无法使用啦！例如 Quota, NTFS 等等特殊的 filesystem 。 这部份也是有够麻烦～因为涉及核心是否能够支援某些档案系统，以及某些作业系统支援的 partition table 项目。在进行选择时，也务必要特别的小心在意喔！ 尤其是我们常常用到的网路作业系统 (NFS/Samba 等等)，以及基础篇谈到的 Quota 等， 你都得要勾选啊！否则是无法被支援的。比较有趣的是 NTFS 在这一版的核心里面竟然有支援可写入的项目， 着实让鸟哥吓了一跳了！^_^

<*> Second extended fs support
[*]   Ext2 extended attributes
[*]     Ext2 POSIX Access Control Lists
[*]     Ext2 Security Labels
[*]   Ext2 execute in place support
<*> Ext3 journalling file system support <==建议这里直接编进核心
[ ]   Default to 'data=ordered' in ext3 (legacy option)
[*]   Ext3 extended attributes
[*]     Ext3 POSIX Access Control Lists
[*]     Ext3 Security Labels
<M> The Extended 4 (ext4) filesystem
[*]   Enable ext4dev compatibility
[*]   Ext4 extended attributes (NEW)
[*]     Ext4 POSIX Access Control Lists
[*]     Ext4 Security Labels
# 上面是传统的 EXT2/EXT3 及进阶的 EXT4 支援！除了 EXT4 外，其他编入核心吧！
================================================================================
[ ] JBD (ext3) debugging support
[ ] JBD2 (ext4) debugging support (NEW)
<M> Reiserfs support
[ ]   Enable reiserfs debug mode (NEW)
[ ]   Stats in /proc/fs/reiserfs (NEW)
[ ]   ReiserFS extended attributes (NEW)
< > JFS filesystem support
<M> XFS filesystem support
[*]   XFS Quota support
[*]   XFS POSIX ACL support
[*]   XFS Realtime subvolume support
< > OCFS2 file system support
[*] Dnotify support
[*] Inotify file change notification support
[*]   Inotify support for userspace
[*] Quota support
[ ]   Report quota messages through netlink interface
[*]   Print quota warnings to console (OBSOLETE)
< > Old quota format support
<*> Quota format v2 support
<M> Kernel automounter support
<M> Kernel automounter version 4 support (also supports v3)
< > FUSE (Filesystem in Userspace) support
# XFS 以及 Reiserfs 与 Quota 建议也是选择起来放啦！
================================================================================
    Caches  --->
    CD-ROM/DVD Filesystems  --->  <==CD内的档案格式，预设值即可
    DOS/FAT/NT Filesystems  --->  <==有支援 NTFS ，要进入挑挑！
      <M> MSDOS fs support
      <M> VFAT (Windows-95) fs support
      (950) Default codepage for FAT    <==支援繁体中文
      (utf8) Default iocharset for FAT  <==支援万国码
      <M> NTFS file system support
      [ ]   NTFS debugging support (NEW)
      [*]   NTFS write support
================================================================================
    Pseudo filesystems  --->        <==类似 /proc ，保留预设值
[*] Miscellaneous filesystems  ---> <==其他档案系统的支援，保留预设值
[*] Network File Systems  --->      <==网路档案系统！很重要！也要挑挑！
    --- Network File Systems
    <M>   NFS client support
    [*]     NFS client support for NFS version 3
    [*]       NFS client support for the NFSv3 ACL protocol extension
    <M>   NFS server support
    [*]     NFS server support for NFS version 3
    [*]       NFS server support for the NFSv3 ACL protocol extension
    < >   SMB file system support (OBSOLETE, please use CIFS)
    <M>   CIFS support (advanced network filesystem, SMBFS successor)
# 最重要就这几项，其他保留预设值即可！
================================================================================
    Partition Types  --->          <==分割类型，也是保持预设值即可！
-*- Native language support  --->  <==选择预设的语系
    --- Native language support
    (utf8) Default NLS Option
    <*>   Traditional Chinese charset (Big5)
    # 除了上述这两个之外，其他的请选择成为模组即可！

  • 核心骇客、资讯安全、密码应用

再接下来有个‘Kernel hacking’的项目，那是与核心开发者比较有关的部分，这部分建议保留预设值即可， 应该不需要去修改他！除非你想要进行核心方面的研究喔。然后底下有个‘ Security Options ’，那是属于资讯安全方面的设定， 包括 SELinux 这个细部权限强化模组也在这里编入核心的！这部分可以作一些额外的设定。 另外还有‘ Cryptographic API ’这个密码应用程式介面工具选项，也是可以保留预设值啦！ 我们来看看有什么比较特殊的地方吧！

Security options  --->
[*] Enable access key retention support
[*]   Enable the /proc/keys file by which keys may be viewed
[*] Enable different security models
[ ] Enable the securityfs filesystem
[*] Socket and Networking Security Hooks
[*]   XFRM (IPSec) Networking Security Hooks
[ ] Security hooks for pathname based access control
[ ] File POSIX Capabilities
[ ] Root Plug Support
[*] NSA SELinux Support
[*]   NSA SELinux boot parameter
(1)     NSA SELinux boot parameter default value
[*]   NSA SELinux runtime disable
[*]   NSA SELinux Development Support
[*]   NSA SELinux AVC Statistics
(1)   NSA SELinux checkreqprot default value
[ ]   NSA SELinux maximum supported policy format version
[ ] Simplified Mandatory Access Control Kernel Support
[ ] TOMOYO Linux Support
[ ] Integrity Measurement Architecture(IMA)
# 基本上，这部分保留预设值就对了！你也会发现 NSA 的资料都是直接编进核心！
================================================================================
Cryptographic API  --->
# 基本上，除了底下这两个编译进核心之外，其他的通通选择成为模组吧！
{*}   MD5 digest algorithm
{*}   SHA1 digest algorithm

在密码应用程式介面方面，一般我们使用的帐号密码登入利用的就是 MD5 这个加密机制，要让核心有支援才行啊！几乎所有的项目都给他做成模组即可！ 不过 MD5 与 SHA1 必须要直接由核心支援比较好！

  • 虚拟化与函式库

虚拟化是近年来非常热门的一个议题，因为电脑的能力太强，所以时常闲置在那边， 此时，我们可以透过虚拟化技术在一部主机上面同时启动多个作业系统来运作，这就是所谓的虚拟化。 Linux 核心已经主动的纳入虚拟化功能喔！而 Linux 认可的虚拟化使用的机制为 KVM (Kernel base Virtual Machine)。 至于常用的核心函式库也可以全部编为模组啰！

[*] Virtualization  --->
    --- Virtualization
    <M>   Kernel-based Virtual Machine (KVM) support
    <M>     KVM for Intel processors support
    <M>     KVM for AMD processors support
    [ ]     KVM trace support (NEW)
    <M>   Virtio balloon driver (EXPERIMENTAL)
================================================================================
Library routines  --->
    {M} CRC-CCITT functions
    {M} CRC16 functions
    {M} CRC calculation for the T10 Data Integrity Field
    {M} CRC ITU-T V.41 functions
    -*- CRC32 functions
    <M> CRC7 functions
    {*} CRC32c (Castagnoli, et al) Cyclic Redundancy-Check

最后，还有底下这两个项目，这两个项目与核心功能无关，但是与挑选时的设定档案有关：

Load an Alternate Configuration File
Save an Alternate Configuration File

这两个项目分别是储存刚刚做好的所有项目的设定资料，另一个则是将来自其他人作的选择给他读入！ 事实上，刚刚我们所做的设定只要在离开时选择 SAVE ，那么这些项目 通通会记录到目前这个目录下的 .config 档案内。 而我们也可以使用上面提到的 Save Configuration 这个项目来将刚刚做完的设定储存成另外的档案， 做成这个档案的好处是，你可以在下次在其他版本的核心作选择时，直接以 Load 来将这个档案的设定项目读入，这样可以减少你还要重新挑选一遍的困境啊！

要请你注意的是，上面的资料主要是适用在鸟哥的个人机器上面的， 目前鸟哥比较习惯使用原本 distributions 提供的预设核心，因为他们也会主动的进行更新， 所以鸟哥就懒的自己重编核心了～ ^_^

此外，因为鸟哥重视的地方在于‘网路伺服器’上面，所以里头的设定少掉了相当多的个人桌上型 Linux 的硬体编译！所以，如果你想要编译出一个适合你的机器的核心， 那么可能还有相当多的地方需要来修正的！不论如何，请随时以 Help 那个选项来看一看内容吧！反正 Kernel 重编的机率不大！花多一点时间重新编译一次！ 然后将该编译完成的参数档案储存下来，未来就可以直接将该档案叫出来读入了！ 所以花多一点时间安装一次就好！那也是相当值得的！

大标题的图示 核心的编译与安装

将最复杂的核心功能选择完毕后，接下来就是进行这些核心、核心模组的编译了！而编译完成后，当然就是需要使用噜～ 那如何使用新核心呢？就得要考虑 grub 这个玩意儿啦！底下我们就来处理处理：

小标题的图示 编译核心与核心模组

核心与核心模组需要先编译起来，而编译的过程其实非常简单，你可以先使用‘ make help ’去查阅一下所有可用编译参数， 就会知道有底下这些基本功能：

[root@www linux-2.6.30.3]# make vmlinux  <==未经压缩的核心
[root@www linux-2.6.30.3]# make modules  <==仅核心模组
[root@www linux-2.6.30.3]# make bzImage  <==经压缩过的核心(预设)
[root@www linux-2.6.30.3]# make all      <==进行上述的三个动作

我们常见的在 /boot/ 底下的核心档案，都是经过压缩过的核心档案，因此，上述的动作中比较常用的是 modules 与 bzImage 这两个，其中 bzImage 第三个字母是英文大写的 I 喔！bzImage 可以制作出压缩过后的核心， 也就是一般我们拿来进行系统开机的资讯啰！所以，基本上我们会进行的动作是：

[root@www linux-2.6.30.3]# make clean    <==先清除暂存档
[root@www linux-2.6.30.3]# make bzImage  <==先编译核心
[root@www linux-2.6.30.3]# make modules  <==再编译模组

上述的动作会花费非常长的时间，编译的动作依据你选择的项目以及你主机硬体的效能而不同。 最后制作出来的资料是被放置在 /usr/src/kernels/linux-2.6.30.3/ 这个目录下，还没有被放到系统的相关路径中喔！在上面的编译过程当中，如果有发生任何错误的话， 很可能是由于核心项目的挑选选择的不好，可能你需要重新以 make menuconfig 再次的检查一下你的相关设定喔！ 如果还是无法成功的话，那么或许将原本的核心资料内的 .config 档案，复制到你的核心原始档目录下， 然后据以修改，应该就可以顺利的编译出你的核心了。最后注意到，下达了 make bzImage 后，最终的结果应该会像这样：

Root device is (8, 1)
Setup is 12696 bytes (padded to 12800 bytes).
System is 2207 kB
CRC 7701ab0e
Kernel: arch/x86/boot/bzImage is ready  (#1)
[root@www linux-2.6.30.3]# ll arch/x86/boot/bzImage
-rw-r--r-- 1 root root 2272432  7月 30 13:35 arch/x86/boot/bzImage

可以发现你的核心已经编译好而且放置在 /usr/src/kernels/linux-2.6.30.3/arch/x86/boot/bzImage 里面啰～那个就是我们的核心档案！最重要就是他啦！我们等一下就会安装到这个档案哩！ 然后就是编译模组的部分啰～ make modules 进行完毕后，就等着安装啦！ ^_^

小标题的图示 实际安装模组

安装模组前有个地方得要特别强调喔！我们知道模组是放置到 /lib/modules/$(uname -r) 目录下的，那如果同一个版本的模组被反覆编译后来安装时，会不会产生冲突呢？举例来说，鸟哥这个 2.6.30.3 的版本第一次编译完成且安装妥当后，发现有个小细节想要重新处理，因此又重新编译过一次，那两个版本一模一样时， 模组放置的目录会一样，此时就会产生冲突了！如何是好？有两个解决方法啦：

  • 先将旧的模组目录更名，然后才安装核心模组到目标目录去；
  • 在 make menuconfig 时，那个 General setup 内的 Local version 修改成新的名称。

鸟哥建议使用第二个方式，因为如此一来，你的模组放置的目录名称就不会相同，这样也就能略过上述的目录同名问题啰！ 好，那么如何安装模组到正确的目标目录呢？很简单，同样使用 make 的功能即可：

[root@www linux-2.6.30.3]# make modules_install
[root@www linux-2.6.30.3]# ll /lib/modules/
drwxr-xr-x 3 root root 4096  7月 30 14:31 2.6.30.3vbird

看到否，最终会在 /lib/modules 底下建立起你这个核心的相关模组喔！不错吧！模组这样就已经处理妥当啰～ 接下来，就是准备要进行核心的安装了！哈哈！又跟 grub 有关啰～

小标题的图示 开始安装新核心与多重核心选单 (grub)

现在我们知道核心档案放置在 /usr/src/kernels/linux-2.6.30.3/arch/x86/boot/bzImage ，但是其实系统核心理论上都是摆在 /boot 底下，且为 vmlinuz 开头的档名。 此外，我们也晓得一部主机是可以做成多重开机系统的！这样说，应该知道鸟哥想要干嘛了吧？ 对啦！我们将同时保留旧版的核心，并且新增新版的核心在我们的主机上面。

  • 移动核心到 /boot 且保留旧核心档案

保留旧核心有什么好处呢？最大的好处是可以确保系统能够顺利开机啦！因为核心虽然被编译成功了， 但是并不保证我们刚刚挑选的核心项目完全适合于目前这部主机系统， 可能有某些地方我们忘记选择了，这将导致新核心无法顺利驱动整个主机系统，更差的情况是， 你的主机无法成功开机成功！此时，如果我们保留旧的核心，呵呵！若新核心测试不通过，就用旧核心来启动啊！嘿嘿！ 保证比较不会有问题嘛！新核心通常可以这样作的：

[root@www ~]# cp /usr/src/kernels/linux-2.6.30.3/arch/x86/boot/bzImage \
> /boot/vmlinuz-2.6.30.3vbird  <==实际核心
[root@www ~]# cp /usr/src/kernels/linux-2.6.30.3/.config \
> /boot/config-2.6.30.3vbird   <==建议设定档也复制备份

  • 建立相对应的 Initial Ram Disk (initrd)

还记得第二十章谈过的 initrd 这个玩意儿吧！ 由于鸟哥的系统使用 SATA 磁碟，加上刚刚 SATA 磁碟支援的功能并没有直接编译到核心去，所以当然要使用 initrd 来载入才行！ 使用如下的方法来建立 initrd 吧！记得搭配正确的核心版本喔！

[root@www ~]# mkinitrd -v /boot/initrd-2.6.30.3vbird.img  2.6.30.3vbird
....(前面省略)....
Adding module ehci-hcd
Adding module ohci-hcd
Adding module uhci-hcd
....(后面省略)....

  • 编辑开机选单 (grub)

鸟哥这部测试机之前是使用 Xen 的核心来启动的，但因为 Xen 核心的制作比较复杂，本章并没有实作出 Xen 虚拟机器的核心。 底下鸟哥使用的是刚刚编译成功的核心来进行开机选单的设定，你会看到的设定档与你的环境可能会有不一样喔！ 那就来看看吧！

[root@www ~]# vim /boot/grub/menu.lst
default=0
timeout=10
splashimage=(hd0,0)/boot/grub/splash.xpm.gz
#hiddenmenu
title CentOS (2.6.18-128.2.1.el5xen)
        root (hd0,0)
        kernel /boot/xen.gz-2.6.18-128.2.1.el5
        module /boot/vmlinuz-2.6.18-128.2.1.el5xen ro root=LABEL=/ rhgb quiet
        module /boot/initrd-2.6.18-128.2.1.el5xen.img
title CentOS testing kernel from vbird
        root (hd0,0)
        kernel /boot/vmlinuz-2.6.30.3vbird ro root=LABEL=/ rhgb
        initrd /boot/initrd-2.6.30.3vbird.img

新增上述的特殊字体到你的设定档当中。另外，你会发现我上头的 default 并没有修改到最新的那个核心的选单上， 因为我必须要测试一下新核心能否顺利开机！如果顺利开机且运作没有问题后，那么才来修订这个 default 的值吧！

  • 重新以新核心开机、测试、修改

如果上述的动作都成功后，接下来就是重新开机并选择新核心来启动系统啦！如果系统顺利启动之后，你使用 uname -a 会出现类似底下的资料：

[root@www ~]# uname -a
Linux www.vbird.tsai 2.6.30.3vbird #1 SMP Thu Jul 30 13:34:31
CST 2009 x86_64 x86_64 x86_64 GNU/Linux

包括核心版本与支援的硬体平台都是 OK 的！嘿嘿！那你所编译的核心就是差不多成功的啦！ 如果运作一阵子后，你的系统还是稳定的情况下，那就能够将 default 值使用这个新的核心来作为预设开机啰！ 这就是核心编译！那你也可以自己处理嵌入式系统的核心编译啰！ ^_^

大标题的图示 额外(单一)核心模组编译

我们现在知道核心所支援的功能当中，有直接编译到核心内部的，也有使用外挂模组的，外挂模组可以简单的想成就是驱动程式 啦！那么也知道这些核心模组依据不同的版本，被分别放置到 /lib/modules/$(uname -r)/kernel/ 目录中，各个硬体的驱动程式则是放置到 /lib/modules/$(uname -r)/kernel/drivers/ 当中！换个角度再来思考一下，如果刚刚我自己编译的资料中，有些驱动程式忘记编译成为模组了，那是否需要重新进行上述的所有动作？ 又如果我想要使用硬体厂商释出的新驱动程式，那该如何是好？

小标题的图示 编译前注意事项

由于我们的核心原本就有提供很多的核心工具给硬体开发商来使用， 而硬体开发商也需要针对核心所提供的功能来设计他们的驱动程式模组，因此， 我们如果想要自行使用硬体开发商所提供的模组来进行编译时，就需要使用到核心所提供的原始档当中， 所谓的标头档案 (header include file) 来取得驱动模组所需要的一些函式库或标头的定义啦！ 也因此我们常常会发现到，如果想要自行编译核心模组时，就得要拥有核心原始码嘛！

那核心原始码我们知道他是可能放置在 /usr/src/ 底下，早期的核心原始码被要求一定要放置到 /usr/src/linux/ 目录下，不过，如果你有多个核心在一个 Linux 系统当中，而且使用的原始码并不相同时， 呵呵～问题可就大了！所以，在 2.6 版以后，核心使用比较有趣的方法来设计他的原始码放置目录， 那就是以 /lib/modules/$(uname -r)/build 及 /lib/modules/$(uname -r)/source 这两个连结档来指向正确的核心原始码放置目录。如果以我们刚刚由 kernel 2.6.30.3 建立的核心模组来说， 那么他的核心模组目录底下有什么咚咚？

[root@www ~]# ll -h /lib/modules/2.6.30.3vbird/
lrwxrwxrwx  1 root root   31  7月 30 14:29 build -> /usr/src/kernels/linux-2.6.30.3
drwxr-xr-x 10 root root 4.0K  7月 30 14:30 kernel
-rw-r--r--  1 root root 337K  7月 30 14:31 modules.alias
-rw-r--r--  1 root root   69  7月 30 14:31 modules.ccwmap
-rw-r--r--  1 root root 224K  7月 30 14:31 modules.dep
....(中间省略)....
lrwxrwxrwx  1 root root   31  7月 30 14:29 source -> /usr/src/kernels/linux-2.6.30.3

比较有趣的除了那两个连结档之外，还有那个 modules.dep 档案也挺有趣的， 那个档案是记录了核心模组的相依属性的地方，依据该档案，我们可以简单的使用 modprobe 这个指令来载入模组呢！至于核心原始码提供的标头档，在上面的案例当中， 则是放置到 /usr/src/kernels/linux-2.6.30.3/include/ 目录中，当然就是藉由 build/source 这两个连结档案来取得目录所在的啦！^_^

由于核心模组的编译其实与核心原本的原始码有点关系的，因此如果你需要重新编译模组时， 那除了 make, gcc 等主要的编译软体工具外，你还需要的就是 kernel-devel 这个软体！记得一定要安装喔！而如果你想要在预设的核心底下新增模组的话，那么就得要找到 kernel 的 SRPM 档案了！ 将该档案给他安装，并且取得 source code 后，才能够顺利的编译喔！

小标题的图示 单一模组编译

想像两个情况：

  • 如果我的预设核心忘记加入某个功能，而且该功能可以编译成为模组，不过， 预设核心却也没有将该项功能编译成为模组，害我不能使用时，该如何是好？

  • 如果 Linux 核心原始码并没有某个硬体的驱动程式 (module) ，但是开发该硬体的厂商有提供给 Linux 使用的驱动程式原始码，那么我又该如何将该项功能编进核心模组呢？

很有趣对吧！不过，在这样的情况下其实没有什么好说的，反正就是 ‘去取得原始码后，重新编译成为系统可以载入的模组’啊！很简单，对吧！^_^！ 但是，上面那两种情况的模组编译行为是不太一样的，不过，都是需要 make, gcc 以及核心所提供的 include 标头档与函式库等等。

  • 硬体开发商提供的额外模组

很多时候，可能由于核心预设的核心驱动模组所提供的功能你不满意，或者是硬体开发商所提供的核心模组具有更强大的功能， 又或者该硬体是新的，所以预设的核心并没有该硬体的驱动模组时，那你只好自行由硬体开发商处取得驱动模组， 然后自行编译啰！

如果你的硬体开发商有提供驱动程式的话，那么真的很好解决，直接下载该原始码，重新编译， 将他放置到核心模组该放置的地方后就能够使用了！举个例子来说，为了省电，鸟哥在 2009 年初买了整合型主机板来架设家用的伺服器，没想到 CentOS 5.1 以前的版本对鸟哥新买的主机板内建网卡支援度不足， 使用的网卡驱动程式 r8169 有问题！搜寻了 google 才发现大家都有这个问题。解决方法就是到 Realtek 官网下载网卡驱动程式来编译即可。

  • Realtek 的 r8168 网卡驱动程式：http://www.realtek.com.tw/downloads/
  • 选择‘Communications Network ICs’-->‘Network Interface Controlllers’--> ‘10/100/1000M Gigabit Ethernet’--> ‘PCI Express’--> ‘Software’就能够下载了！

你可以利用各种方法将他下载后，假设这个档案放置到 /root ，那么直接将他解压缩吧！ 之后就可以读一读 INSTALL/README ，然后找一下 Makefile ，就能够编译了。整体流程有点像这样：

# 1. 将档案解压缩：
[root@www ~]# cd /usr/local/src
[root@www src]# tar -jxvf /root/r8168-8.013.00.tar.bz2
[root@www src]# cd r8168-8.013.00/

# 2. 开始进行编译与安装：
[root@www r8168-8.013.00]# vi readme  <==注意查一下该档案内容
[root@www r8168-8.013.00]# make clean modules
[root@www r8168-8.013.00]# ll src/*.ko  <==建立底下的模组档！
-rw-r--r-- 1 root root 112216  7月 31 01:11 src/r8168.ko
[root@www r8168-8.013.00]# make install
install -m 744 -c r8168.ko /lib/modules/2.6.30.3vbird/kernel/drivers/net/
# 重点在上面这行！会发现模组已经被移动到核心模组目录！

4. 更新模组相依属性！
[root@www r8168-8.013.00]# depmod -a

有趣吧！透过这样的动作，我们就可以轻易的将模组编译起来，并且还可以将他直接放置到核心模组目录中， 同时以 depmod 将模组建立相关性，未来就能够利用 modprobe 来直接取用啦！ 但是需要提醒你的是，当自行编译模组时， 若你的核心有更新 (例如利用自动更新机制进行线上更新) 时，则你必须要重新编译该模组一次， 重复上面的步骤才行！因为这个模组仅针对目前的核心来编译的啊！对吧！

  • 利用旧有的核心原始码进行编译

如果你后来发现忘记加入某个模组功能了，那该如何是好？其实如果仅是重新编译模组的话， 那么整个过程就会变的非常简单！我们先到目前的核心原始码所在目录下达 make menuconfig ， 然后将 NTFS 的选项设定成为模组，之后直接下达：

make fs/ntfs/

那么 ntfs 的模组 (ntfs.ko) 就会自动的被编译出来了！ 然后将该模组复制到 /lib/modules/2.6.30.3vbird/kernel/fs/ntsf/ 目录下， 再执行 depmod -a ，呵呵～就可以在原来的核心底下新增某个想要加入的模组功能啰～ ^_^

小标题的图示 核心模组管理

核心与核心模组是分不开的，至于驱动程式模组在编译的时候，更与核心的原始码功能分不开～ 因此，你必须要先了解到：核心、核心模组、驱动程式模组、核心原始码与标头档案的相关性， 然后才有办法了解到为何编译驱动程式的时候老是需要找到核心的原始码才能够顺利编译！ 然后也才会知道，为何当核心更新之后，自己之前所编译的核心模组会失效～

此外，与核心模组有相关的，还有那个很常被使用的 modprobe 指令， 以及开机的时候会读取到的模组定义资料档案 /etc/modprobe.conf ， 这些资料你也必须要了解才行～相关的指令说明我们已经在第二十章内谈过了， 你应该要自行前往了解喔！ ^_^

大标题的图示 重点回顾
  • 其实核心就是系统上面的一个档案而已，这个档案包含了驱动主机各项硬体的侦测程式与驱动模组；
  • 上述的核心模组放置于：/lib/modules/$(uname -r)/kernel/
  • ‘驱动程式开发’的工作上面来说，应该是属于硬体发展厂商的问题
  • 一般的使用者，由于系统已经将核心编译的相当的适合一般使用者使用了，因此一般入门的使用者，基本上，不太需要编译核心
  • 编译核心的一般目的：新功能的需求、原本的核心太过臃肿、与硬体搭配的稳定性、其他需求(如嵌入式系统)
  • 编译核心前，最好先了解到您主机的硬体，以及主机的用途，才能选择好核心功能；
  • 编译前若想要保持核心原始码的干净，可使用 make mrproper 来清除暂存档与设定档；
  • 挑选核心功能与模组可用 make 配合：menuconfig, oldconfig, xconfig, gconfig 等等
  • 核心功能挑选完毕后，一般常见的编译过程为：make bzImage, make modules
  • 模组编译成功后的安装方式为： make modules_install
  • 核心的安装过程中，需要移动 bzImage 档案、建立 initrd 档案、编辑 /boot/grub/menu.lst 等动作；
  • 我们可以自行由硬体开发商之官网下载驱动程式来自行编译核心模组！
大标题的图示 本章习题
( 要看答案请将滑鼠移动到‘答：’底下的空白处，按下左键圈选空白处即可察看)
  • 简单说明核心编译的步骤为何？
    1. 先下载核心原始码，可以从 http://www.kernel.org 或者是 distributions 的 SRPM 来着手；
    2. 以下以 Tarball 来处理，解开原始码到 /usr/src/kernels 目录下；
    3. 先进行旧资料删除的动作：‘make mrproper’；
    4. 开始挑选核心功能，可以利用‘make menuconfig’、‘make oldconfig’、‘make gconfig’等等；
    5. 清除过去的中间暂存档资料：‘make clean’
    6. 开始核心档案与核心模组的编译：‘make bzImage’、‘make modules’
    7. 开始核心模组的安装：‘make modules_install’
    8. 开始核心档案的安装，可以使用的方式有：‘make install’或者是透过手动的方式复制核心档案到 /boot/grub 当中；
    9. 建立 initrd 档案；
    10. 修改 /boot/grub/menu.lst 档案；
  • 如果你利用新编译的核心来操作系统，发现系统并不稳定，你想要移除这个自行编译的核心该如何处理？
    首先，可以将原始码删除：rm -rf /usr/src/kernels/linux-2.6.30
    再者，删除掉核心模组的目录： rm -rf /lib/modules/2.6.30
    最后删除掉 /boot/ 内的核心档案与 initrd 档案，以及 /boot/grub/menu.lst 内的 title 设定即可。
大标题的图示 参考资料与延伸阅读
  • 注1：透过在 /usr/src/kernels/linux-2.6.30.3 底下的 README 以及‘ make help ’可以得到相当多的解释
  • 核心编译的功能：可以用来测试 CPU 效能喔！因为 compile 非常耗系统资源！
  • http://lxr.xensource.com/lxr/source/README?a=x86_64
2002/05/29：第一次完成
2003/02/11：重新编排与加入 FAQ
2004/06/11：原本的 2.4.xx 版本核心被移动到 此处
2005/11/15：原本的模组管理已经先移动到开机流程管理那一篇啰！
2005/12/05：经过将近一个月，呵呵！终于给他整理出来这一篇了～真难得～
2007/06/27：增加了 initrd 的简单说明，详细还是得看 loader 那一章。
2009/07/21：将基于 FC4 所撰写的文章移动到此处
2009/08/03：原本的 KDE/GNOME 使用的引擎写错了！ KDE 用 Qt ，而 GNOME 是用 Gtk ！非常感谢 Chua Tze An 兄提供的指正！
2009/09/18：加入两个简单的题目，给大家思考一下而已。


鸟哥的 Linux 私房菜 -- 一个简单的 spfdisk 分割硬碟实例

为取得较佳浏览结果，请爱用 firefox 浏览本网页
鸟哥的 Linux 私房菜馆 | Linux 基础文件 | Linux 架站文件 | Linux 企业运用 | 安全管理 | 新手讨论 |

一个简单的 SPFdisk 分割实例
最近更新日期：2005/06/12
磁碟分割是个很重要的学习知识！尤其是在您原本的硬碟空间不足了，或者是新增硬碟了， 或者是为了增加磁碟效能而必须要规划出比较适当大小的磁碟空间等等。 市面上很多工具可以让我们来进行磁碟的分割的，不过，都需要钱～ 当然，您也可以使用 Linux 的 fdisk 程式，不过，纯文字介面的方式，可能您也不容易学～ 相较之下，由台湾人自行开发的 spfdisk (special fdisk) 程式，不但纯中文介面， 使用图形介面的显示，耗用的系统资源又少！还可以作为开机管理程式！太完美了！赶紧来看看！

1. 什么是硬碟分割？
2. SPFdisk
    2.1 删除原有分割
    2.2 建立主要分割磁区
    2.3 储存分割表
    2.4 格式化硬碟
 3. 针对本文的建议：http://phorum.vbird.org/viewtopic.php?t=23875
大标题的图示 什么是硬碟分割(Partition)
在开始进行 Linux 之前，应该有很多的工作要做的！最重要的就如同前面‘Linux 主机规划’当中说的，要如何规划硬碟呢？！到底要如何分割硬碟才好！是要将 swap （虚拟记忆体）规划的大一点比较好？或者是只要一个根目录就可以了呢？另外，如果我的硬碟上面已经有 Windows 系统，我又不想要将 Windows 杀掉，想使用多重开机来安装我的多个作业系统，那要怎么做呢？！况且，由于 DOS 的 fdisk 不认识 Linux 的档案格式，那么我要如何将 Linux 完全的从我的硬碟中移除呢？！呵呵！ 这里就来说一下该如何是好吧！

由于不同的作业系统所使用的档案系统架构(file system)并不相同，有些甚至是不相容的，例如 Windows 所使用的是 FAT 表，而 Linux 所使用的是 ext2 这个档案格式，这两种格式完全不相同，在 Linux 底下还可以藉由编辑核心来支援 Windows 的 FAT 档案格式，但是 Windows 则完全无法读取 Linux 的档案格式了！此外， Windows 使用的磁碟分割工具 fdisk ，很抱歉的，并不认识 Linux 的 ext2 这个档案格式，所以如果您有一棵已经安装有 Linux 系统的硬碟，呵呵，使用 Windows 的 fdisk 是完全无法分割这块硬碟的！

那么到底什么是硬碟分割呢？真的要将硬碟用刀子割一割吗？！不是这样的，实际上，硬碟是以 sectors(磁区), cylinder(磁柱), partitions(分割槽) 这些东西来作为储存的单位，而最底层的实体硬碟单位就是 sectors 了，通常一个 sector 大约是 512 bytes 左右。不过，在磁碟进行格式化的时候，可以将数个 sector 格式化成为一个逻辑磁区(logical block)，通称为 block。blocks 为一个档案系统(filesystem)存取的最小量。 那么 partition 是什么？简单的来说，你知道你的 Windows 有所谓的 C:, D: 是吧！其实他们是同一颗硬碟，只是利用‘磁碟分割表’(partition table)来将实体的硬碟规划出不同的区块。

举个例子说，假设你的硬碟总共有 1024 个 cylinder （利用 blocks 结合而成的硬碟计算单位）， 那么你在这块硬碟的档头地方 （就是磁碟分割表，可以想成要读取一块硬碟时最先读取的地方）如果写入你的 partitions 共有两块，一块是 primary 一块是 extended ，而且 extended 也只规划成一个 logical ，那么你的硬碟就是只有两个槽啦（对于系统来说，真正能使用的有 Primary 与 Logical 的磁区， Extended 并无法直接使用的！需要再加以规划成为 Logical 才行！ ) ，而且在 partition table 也会记录 primary 是由‘第 n1 个 cylinder 到第 n2 个 cylinder ’，所以啰，这样子一来，当系统要去读取 primary （就是 c 槽）的时后，就只会在！n1~n2 之间的实体硬碟当中活动啰！

基本上， Windows 98 系统中的 Fdisk 这支程式仅支援一个 primary 与一个 extended ，其中， extended 可以再细分成多个 logical 的硬碟槽。NT 很抱歉，小弟不熟，所以就不提了！那么 Linux 呢？嗯！基本上最多可以有 4 个 primary 的硬碟，而可以支援到 3 个 primary 与一个 extended ，其中， extended 若再细分成 logical 的话，则全部 primary + extended + logical 应该可以支援到 64 个之多。底下我们将以 spfdisk 这个全中文介面的 fdisk 磁碟分割工具来介绍如何分割硬碟！(注：更多详细的磁碟与磁碟分割资讯，可以参考 SPFdisk 的官方网站喔！ 在最底下的参考资料当中有提供连结呢！)
大标题的图示 硬碟分割 ==> SPFdisk
SPFdisk 是一套由国人开发完成的全中文介面的硬碟分割工具，他要比微软出的 Fdisk 功能强多了， 他的好处有：
  • 全中文介面让你一定可以看的懂之外，简单的类图形介面可以让你轻易的进行硬碟分割；
  • 除此之外，这套软体的‘DOS工具’内的‘格式化工具’格式化硬碟的速度真是 DOS 比不上的， 我格式化一个 30GB 的硬碟不用十秒就可以格式化完全！
另外，其他的优点我在此也不多说了，若有需要你可以自行自一些搜寻网站下载最新的程式， 或从 这里 下载鸟哥有的程式，不过可能旧一点。

另外，由于 DOS 的 Fdisk 并不认识 Linux 的分割表，所以用 DOS 的 Fdisk 是无法将 Linux 的分割表去除的。因此，你要删除 Linux 的分割表，只有两个比较快的方法，一个是以 Linux 直接再分割，一个则是使用 SPfdisk 分割啦！
Tips:
由于您正在阅读的这个页面的影像档案很大，有时候会有没办法显示的情况发生， 这时请在画面上‘按滑鼠右键’，再选择‘显示图片’这个选项，即可显示画面啦！ 		鸟哥的图示
硬碟分割主要可分为下面几个步骤：
  1. 将旧有的分割表删除；
  2. 建立新的主分割及扩充分割（若有需要的话）；
  3. 贮存分割表；
  4. 以 DOS 工具格式化已分割的硬碟。
小标题的图示 1. 删除原有的分割：
假设你的主机中没有任何系统存在，则请以 Windows98 制作开机片后，将 spfdisk 拷贝至开机片。以此磁片开机之后，执行：
A:\>spfdisk
会出现如下欢迎画面。

按任意键后出现下面画面：

以方向键移动游标至‘硬碟分割工具’按 Enter 键后会出现画面如下：

这是向你询问是否需要使用 FAT32 的档案系统，由于 Windows 98 支援的长档名及相关的档案型态是以 FAT32 为准，所以当然按 ‘Y’！按了 Y 之后会出现硬碟的资讯，如下所示：

因为我是在我原有的机器上执行这个程式，所以会有两颗硬碟，如果你的系统只有一颗硬碟的话， 则只会显示你有的硬碟资料，在上图中，1.19GB 的硬碟其总磁柱仅有 621 单位，比可开机磁区范围（0 ~ 1023）小得多，所以可以随意分割。将游标以方向键移动至 1.19GB 这颗硬碟后，按 Enter ：

因为这颗硬碟之前被我灌过 Linux ，所以会显示 Linux 的磁区划分情况。上面的意义为：
  • 启动：由于系统开机时会去先去找分割表， 由分割表所设定的‘可开机磁区’进行开机程序， 因此若这个磁区为开机磁区，则‘启动’项目会有一个心型的符号存在！
  • 起始磁柱与结束磁柱：这一个被分割的磁区的开始与结束磁区。
  • MBytes：这个磁区的硬碟容量。
  • 系统 ID 与系统种类：这一个分割表的类型。因为这是 Linux 的分割类型，所以其 ID 显示为 83，若是 FAT32 的话，则为 0b。
将游标以方向键移动至这个磁区后，按 Enter ：

在这个画面中，将游标以方向键移动至‘删除分割’这个项目，并按下 Enter ：

出现此画面后，确定要删除这个分割就按‘[Y]是’这个项目。

删除分割之后你的硬碟中就没有分割表的存在了，所以这个硬碟的系统种类则变成了 未规划。
小标题的图示 2. 建立主要分割磁区：
在上面的画面中，按下 Enter 键，会出现下面画面。

由于这一颗硬碟的分割表被删除了，所以‘系统ID’与‘删除分割’被取消了。这时按下‘建立分割’会出现如下画面：

然后选择‘建立主分割’，那何谓主分割与扩充分割呢？所谓的主分割在 windows 系统下即是 ‘C槽’ 啦！ 但是扩充分割并非‘逻辑分割’，这里要注意一下， 所谓的‘逻辑分割’是包含在扩充分割中的，例如当你的扩充分割共有 10GB 但是你想将之分为两槽，则可以使用逻辑分割将扩充分割分为两槽， 这两槽即称为‘逻辑分割’。所以这里要注意啦，建立扩充分割的时候就要选择‘配置整个区域’啦！ 好！下一步按下‘建立主分割’：

这里会问你是否要将整个硬碟分割为仅有一个磁碟区？由于我们要将硬碟分为两槽， 所以这里当然选择‘[N]否’啦！

由于你选择了‘不要配置整个区域为一块磁区’，所以这时程式要你输入你所需要的磁区。 通常在第一步是输入‘启始磁柱’，这时只要按 Enter 就可以啦，然后会要你输入‘结束磁柱’， 结束磁柱的输入方法有两种模式，一种是输入磁柱区，一种是输入你所需要的 MB 数，通常我是输入 MB 数啦，例如如上所示，我所需要的空间大小是 600MB ， 所以输入‘+600’即可，而如果你的硬碟很大，你要输入 4GB 时，则需要输入 ‘+4000’，以此类推！输入‘+600’并按 Enter 之后出现如下画面。

这时出现了你刚刚划分的硬碟资讯啦，由于我们是划分为 DOS 分割区，所以系统种类是 FAT-32 ，而 ID 则为 0b 。至于另外尚未划分的就会显示为 <未规划> 啦！如果你还需要再继续划分的话，这时将游标移动至 <未规划> 的那一个磁区按 Enter 后选择‘扩充分割’即可继续划分。如果划分完毕之后， 当然就是贮存分割表啰。这里注意一下，因为刚刚的动作均尚未完成贮存的工作，所以要反悔还来得及！
小标题的图示 3. 贮存分割表：
接下来要做贮存的动作了，按下‘Esc’键 （键盘左上角那个键）后会出现如下画面：

按‘[Y]是’，将刚分割好的分割表贮存至硬碟中！ 然后出现如下画面：

这里的动作是连续的：
  1. 程式会先跟你确认你的硬碟有没有错误，这里还可以反悔。
  2. 然后程式会问你是否需要使用破坏贮存，一般来说是需要使用‘破坏贮存’的， 因为需要将你的硬碟划分完全啦！所以要按 [Y]；
  3. 为了可以让你以后回复分割情况，所以你可以选择 ‘建立 UNDO’档，所谓的 UNDO 档即是记录你之前硬碟分割表资讯的档案啦。
这样一来你的硬碟就划分完毕而且贮存啦！这时要做的就是重新开机并格式化硬碟。格式化硬碟可以使用 DOS 的 Format ，当然也可以使用 spfdisk 的内建功能喔！
小标题的图示 4. 格式化硬碟：
再进入刚刚你划分完毕的那个硬碟区，按下 Enter 之后会出现一串选单，然后最下方的选单为 ‘DOS 工具’，选择这一项并按 Enter 后，会出现另一个选单：

在这个次选单中的第二项即是快速格式化，这个格式化的动作非常的快喔！比 DOS 的格式化快多了！不过，这里也必须指出一个问题，那就是若你的硬碟有坏轨的话，那最好还是使用 DOS 的 format 比较完整一点。

大标题的图示 参考资料
  • SPFdisk http://spfdisk.sourceforge.net/
    事实上， SFPdisk 能作的事情还很多，包括最为人所熟知的 boot loader 的应用！ 建议您一定要到 SPFdisk 的官方网站上面瞧一瞧喔！ ^_^
2002/04/09：第一次完成吧？
2003/02/03：重新编排
2005/06/12：将旧文移动到 这里 。并且约略编排了一下版面！
2005/07/18：原本文章当中的 cluster 为错误的，应该是 cylinder 才对～


鸟哥的 Linux 私房菜 -- 一些 Linux 系统的基础问题

为取得较佳浏览结果，请爱用 firefox 浏览本网页
鸟哥的 Linux 私房菜馆 | Linux 基础文件 | Linux 架站文件 | Linux 企业运用 | 安全管理 | 新手讨论 |

一些 Linux 系统的基础问题
最近更新日期：2005/05/23
一些基础的 Linux 问题与讨论：
注意：如果您有更好的试题，或者是有相关的资料要提供给 VBird 的话，我也会尽快的将他写到网页中的！感谢感谢！！ ^_^ ..
一、什么是 Linux 呢？！
  1. 试说明 Unix 与 Linux 的历史？
  2. 简单说明 GNU General Public License （GPL）的精神：
  3. 什么是 Linux Distribution？
  4. 市面上众多的 Linux 版本当中，有何异同？
  5. Linu Kernel 的功能：
  6. 试说明 Linux Kernel 与使用者之间的相关性？
  7. 试说明什么是 GUI
  8. Linux 的优点：
  9. Linux 是多人多工的环境，请问何谓多工(Multitask)与多人(Multiuser)：
二、Linux 的安装与认识 Linux 支援的硬体
  1. 一般而言， Linux 需要的配备并不需要太高档，但 Open Linux Server 3.1.1 需要？
  2. 什么是 IDE 界面，一般而言，普通 PC 允许几个 IDE 界面与装置？
  3. IDE2 的 master 之第一个 logical 磁碟中，其装置代号（档案名称）为何？
  4. 在硬碟分割 (Partition)时，最多有几个 primary + extended ？
  5. 若在分割的时候，在 IDE1 的 slave 硬碟中，分割‘六个有用’的磁区（具有 filesystem 的），此外，有两个 primary 的磁区！请问六个磁区的代号？
  6. 一般而言安装 Linux 至少要有哪两个 partition 呢？
  7. 一般而言，在 RAM 为 64MB 或 128 MB 的系统中， swap 要开多大？
  8. 光碟机与软碟机的代号（装置档案名称）？
  9. 网路卡（Network Interface Card, NIC）的代号？
  10. 预设的 Linux 档案格式为何？又，目前常用的 Journalling 档案格式为何？
  11. 安装 Linux 的主要流程？
  12. 什么是 GMT 时间？台北时间差几个钟头？
  13. Tap, SCSI 硬碟, RAID, printer 的装置代号？
其他注意事项：
  • 要玩 X-window 时，至少需要具有 4-8 MB 的 VGA RAM 才好！
  • 第一次使用与安装 Linux 时，请尽量的安装‘所有套件！’
  • 若具有安装与使用经验之后，则安装的时候，仅选择您所预计需要开放的服务之套件即可！
  • 特别留意硬体对于 Linux distribution 的支援度！可以参考一下如下的网页：

    • http://www.linux.org.tw/hardware/index.php3
  • 制作 Install 之软碟开机片：

    • 将可开机光碟放入 Windows 系统下，并执行光碟机中的档案(假设光碟代号为 E:)
      E:\col\tools\rawrite\rawrite2
      Enter disk image source filename: E:\col\launch\floppy\install.144
      Enter target disketie derive: A:
  • 制作软碟开机片的一般方法：

    • mkbootdisk --device /dev/fd0 `uname -r`
三、简易 KDE 的使用( X-Window)
  1. 若以 X-Window 为预设的登入方式，那请问如何进入 Virtual console 呢？
  2. 如何修改进入 Linux 时候的 run-level ？又 run-level 0, 1, 3, 5 各代表什么意思？
  3. XFree86 在 X-Window 中的角色为何？
  4. XFree86 的主要设定档在哪里？
  5. KDE 预设提供多少个 Virtual desktops ？
四、线上求助 ( Help )
  1. 在 Linux 系统中，安装的套件 (RPM安装) 预设的文件资料放在那个目录底下？
  2. 查看 Linux 系统的线上求助可以使用什么指令？
  3. 使用 man 来查询线上求助的时候，若要查询类似参数档(如/etc/passwd)需如何？
  4. 使用 man 查询 command 的所有相关指令时，需要下什么参数？
  5. man page 的 man path 变数，记录在那个档案中呢？！
五、vi 的使用
  1. 在 linux 底下最常使用的文书编辑器为 vi ，请问如何进入编辑模式？
  2. 如何由编辑模式跳回一般模式？
  3. 若上下左右键无法使用时，请问如何在一般模式移动游标？
  4. 若 [pagedown] [ pageup] 在一般模式无法使用时，如何往前或往后翻一页？
  5. 如何到本档案的最后一行、第一行；本行的第一个字元、最后一个字元？
  6. 如何删除一行、n行；如何删除一个字元？
  7. 如何复制一行、n行并加以贴上？
  8. 如何搜寻 string 这个字串？
  9. 如何取代 word1 成为 word2，而若需要使用者确认机制，又该如何？
  10. 如何读取一个档案 filename 进来目前这个档案？
  11. 如何另存新档成为 newfilename？
  12. 如何存档、离开、存档后离开、强制存档后离开？
  13. 如何设定与取消行号？
六、档案与目录管理
  1. 请问底下的目录与主要放置什么资料？
  2. ‘旧的’ Unix 系统与 Linux 系统的‘档名’最多可以容许几个字元？
  3. 什么是绝对路径与相对路径，要由 /usr/share/doc 进入到 /usr/share/man 由相对路径与绝对路径的写法各为何？
  4. 在非为根目录的任何一个目录中，下达 ls –al 时，均会有‘.’及‘..’这两个目录，请问分别代表什么？
  5. 显示、变换目录的时候，使用什么指令？
  6. 新增目录、移除目录移动目录与拷贝目录有什么指令可用？
  7. 如何查看一个档案的‘内容’（不要使用 vi 的情况下）
  8. 什么是 hard link 与 soft link 的档案？有何不同？
  9. 如何在 root 的家目录下建立一个 /bin 的连结捷径
  10. 若有一个连结档为 testing 连结到 test1.sh ，请问 copy testing 到 /tmp 底下，‘cp testing /tmp’则 /tmp/testing 这个档案会是：(1) 连结档，连结到 test1.sh ；(2) 一般档案，为内容与 test1.sh 相同？
  11. 当一个档案属性为 –rwxrwxrwt 则表示这个档案的意义为？
  12. 我需要将一个档案的属性改为 –rwxr-xr-- 请问该如何下达指令？
  13. 在 /usr/bin/passwd 这个档案的属性为 –r-s--x--x 请问代表什么意思(s)
  14. 如何改出 –rwxr-sr-x 与 –rwxr-xr-t这个属性？
  15. 如何查看一个档案的类型 (type) 例如纯文字档、执行档与 setuid 档案等？
  16. 若一个使用者的 umask 为 033 ，请问他建立一个新的目录与档案时的预设属性为？
  17. 若我需要更改一个档案的拥有者与群组，该用什么指令？
  18. 如何将一个档案的修改日期改成目前的时间？
  19. 如何搜寻一个档案？
  20. Linux 预设的档案系统为何？此外，常用的 Journalling 档案格式有哪些？
  21. less 跟 more 有什么不同？
  22. 在比较两个档案的异同时，常使用的是 diff 与 cmp ，请教两者有何不同？
六.1、磁碟挂载与虚拟记忆体问题
  1. 我要如何查看 Linux 系统当中所有已经挂载的硬碟容量与 inodes ？
  2. 我要如何查看目前所在目录的所有档案占用的硬碟空间，此外，如何仅输出结果？
  3. 如果磁区 /dev/hda3 有问题，偏偏他是被挂载上的，请问我要如何修理此一磁区？
  4. 承上题，那么有问题的档案将被移动到那个目录下？
  5. 试说明新增一个 partition 在 /dev/hdb 当中，且为 hdb5时，并挂载上 /disk2 ，需要哪些步骤？
  6. 如何新增加 64MB 的虚拟记忆体 swap ？
  7. 如果要设定一个新挂载上的磁区，令他可以在开机的时候被挂载上，应该编辑哪一个档案？
  8. 简易说明 quota 的设置流程？
七、BASH SHELL
  1. 简单说明 bash shell 的功能特征：
  2. 在设定变数中，主要的规则为何？
  3. 显示环境变数与所有变数的指令为何？
  4. 在环境变数当中，‘使用者家目录、主机名称’的变数名称为：
  5. 如何让一个变数可以持续到下一个程序 (PID) 去？
  6. 在变数的设定当中，双引号与单引号有何不同？
  7. Command1 `command2` 这个指令代表什么意思？
  8. 在命令重导向当中， > 与 >> 有什么不同？
  9. 若要将错误的输出导向‘不见了’的装置，该如何是好？
  10. 在管线指令中，我要将 last 输出的结果显示 root 的‘登入次数’， 如何做？
  11. 如何设定一个变数名称为 name ，使其显示为‘ VBird’s testing variable. ’？
  12. 请问 bash shell 的环境变数与自己的个人变数可以登入便设定的档案？
  13. 如何查询曾经操作过的指令？如何执行第 26 个操作过的指令？上一个操作过的指令？
  14. 如何设定命令别名？使 lm 与 ls –al|more 功能相同
  15. 如何将 /bin 的所有资讯输出到 /home/testing.dat 这个档案？
  16. 在上一题中，若还要输出到荧幕上，要如何是好？
  17. 执行 find ，并将正确的结果输出到 right 而错误结果输出到 error 当中？
  18. 如何在指令列模式中将 /root/.bashrc 的资料加在 /home/col/.bashrc 当中？
  19. 不要显示执行的结果要如何是好？
  20. 列出这个月曾经登入主机的使用者资讯即可，不需要重复？
  21. 万用字元当中， *, ?, [] 各代表什么意思？
七.1、SHELL SCRIPTS
  1. 什么是 shell scripts ？ scripts 有何功用？
  2. 要撰写可以经由键盘输入的 scripts 时，常使用到的指令？
  3. 在 shell script 当中，在控制式中， && 与 || 代表什么意思？
  4. 在使用回圈的时候，常使用到的控制式为哪三个？
  5. 执行 scripts 的方法有哪两种？
  6. 如何宣告一个变数成为整数型态？
  7. 为何在 shell script 前面都要宣告 shell 呢？
  8. 在判断式中，如何判断一个档名是否存在？
  9. 在执行一个 scripts 时，在 scripts 内的变数， $0, $1 代表什么？
  10. 若要写一个既定的 parameter （如 start ），用哪一个判断式较简单？
  11. 如何印出目前系统中的所有帐号，并加以排序且输出到 /tmp/account 中？
  12. 如何在不执行 scripts 的情况中 debug ？
八、基本帐号管理
  1. 如何新增一个使用者 username，且该使用者没有家目录？
  2. Linux 使用者的帐号、密码与群组的名称档案放在哪里？
  3. 建立新使用者的预设家目录内容在那个目录中？
  4. 建立一个新使用者时，其使用到的相关档案有哪些？
  5. root 的 UID 与 GID 各为何？
  6. 如何让一个使用者不能登入主机，但是可以收信？
  7. 试说明一个使用者登入系统的流程？
  8. 在 /etc/shadow 当中的日期设定中，其数字代表的意义为何？
  9. 如何变更使用者的一些属性？
  10. 如何视察一个使用者 username 所拥有的群组呢？
  11. 试说明如何手动增加一个使用者 username 与群组 groupname？
  12. 试说明 /etc/passwd 这个档案的内容与格式：
  13. 使用 id 这个指令时，可以显示什么讯息资料？
  14. 可以控制使用者使用主机资源的预设档案在哪里？
  15. 基本的压缩指令有哪些？
九、开机程序
  1. 试说明开机流程：
  2. 开机时后的载入讯息可以看哪里？
  3. 改变 run-level 或关机的指令
  4. 改变登入 Linux 时候预设的 run-level 要改那个档案？
十、程序与资源管理
  1. 如何查看目前的程序？
  2. 如何查看目前的记忆体使用状况？
  3. 目前的工作如何丢到背景中？
  4. 如何取得目前背景中的工作，且将他拉回前景中？
  5. 如何设定一个程序在开始执行时候的优先值？
  6. 什么指令可以修改一个正在执行的程式之 nice 值？
  7. 在例行性命令中，使用的两支 demane 是什么？
  8. 使用 crontab 这个‘指令’的时候，如何可以查看目前的工作与删除目前的工作？
  9. 常用的 kill 指令之 signal 当中， 1, 9, 15 代表什么？
来看看解答啰：
请注意：这些解答是 VBird 自己查书或者是实际操作所得到的答案，如果您发现这些答案是‘错误的’请赶快跟 VBird 联络，好让我将资料赶快的订正！感谢大家的热情支持啰！
一、什么是 Linux 呢？！
  • 试说明 Unix 与 Linux 的历史？
    • Multics 系统：由Bell（贝尔实验室）、MIT（麻省理工学院）与GE（美国通用电器）合作开发的一个系统；
    • 1969：K. Thompson 替 DEC 公司写了一个简单的 file system 系统，此为 Unix 的前身，但是 Unix 一词尚未出现
    • 1973：由 Bell 的 D. Richie 以 C 语言改写了 Thompson 的小系统，全部以 ASCII 档案进行改写，方便于应用！此时为第一次出现 Unix 这个作业系统的名词，不过，由于 Unix 乃针对不同的硬体而设定，因此仅出现在大型的 Server 上面看到！经过数年后，有底下几种版本：
        • 1. System V  来自于 ATT 公司；
        2. BSD  来自于加州理工学院；
        3. AIX  来自于 IBM 公司
    • 1979：Richard Stallman 倡导 Open source 精神；
    • 1984：GNU 与 Free Software Foundation (FSF)由 R. Stallman 倡导；
    • 1986：Xfree86 出现在 Unix 上面，且在 1994 年整合于 Linux 中！
    • 1991：芬兰大学生 Linus Torvalds在网路上首次公告 0.02 版的 Linux Kernel ，称为 hobby。
  • 简单说明 GNU General Public License （GPL）的精神：
    • GPL 的授权之软体，乃为自由软体（Freeware），任何人皆可拥有他；
    • 开发 GPL 的团体(或商业企业)可以经由该软体的服务来取得服务的费用；
    • 经过 GPL 授权的软体，其属于 Open source 的情况，所以应该公布其原始码；
    • 任何人皆可修改经由 GPL 授权过的软体，使符合自己的需求；
    • 经过修改过后 Open source 应该回馈给 Linux 社群。

      • (PS. Open source 最大的优点为多人维护， debugs 的速度较快，程式亦较为安全，但是缺点则是缺乏‘专人’维护！)
  • 什么是 Linux Distribution？

    • 基本上 Linux 是在 1991 年由芬兰大学生 Linus Torvalds 写的一个核心作业系统，最早仅只是核心而已，后来由于此一核心不但可以适合于主流 PC 的 x86 架构，并且稳定，因此有相当多的团队加入研究开发，后来某些公司将一些套件加入此一核心中，变成为完整的‘安装光碟’，亦即是 Linux Distribution 了！所以才会有这么多的 Linux 版本，各版本之间没有所谓的谁优谁劣，而是个有其优缺点！看你适合哪一款，就用那一款吧！
    开发商针对 Linux Kernel 进行开发，并加入适合该 Kernel 的套件（如 ftp, apache, mail 等等），及配合开发商本身的支援软体，而制作出来的可安装光碟即可称为 distribution。
  • 市面上众多的 Linux 版本当中，有何异同？

    • 唯一相同的地方在于 Linux 的‘Kernel’，目前 ( 2002/06/29 ) Kernel 发展至 2.4.xx 版本，至于不同点则是 Linux 开发商自行加入或者是研发的软体。
  • Linu Kernel 的功能：
    • System call interface
    • Process control
    • Memory management
    • File System management
    • Device drivers
    简单的说，任何跟系统硬体资源有关的都是 Linux Kernel 管辖的范围，所以编辑核心的时候，将核心编的越小越好！
  • 试说明 Linux Kernel 与使用者之间的相关性？

    • 硬体<=>Kernel (Modules Loader)<=>Shell ( Terminal or GUI )<=>Users
  • 试说明什么是 GUI

    • GUI 为 Graphical User Interface 的简写，即为使用者图形界面，目前我们在 Linux 上面的 GUI 一般称为 X-Window ，而其核心为 Xfree86 这个 X-Server ！请注意，这个 Xfree86 最大的功能即是在控制‘显示卡、硬体周边’等跟 Window 有关的界面，所以 X-Window 无法启动时，通常是 Xfree86 这个 X-Window 的核心驱动程式设定不完全有关！
  • Linux 的优点：

    • 最大的优点来自于其良好的资源分配！所以具有：
    • 良好的多人多工环境，资源分配平均；
    • 除了免费之外，线上更新速度快，除错与安全性均较佳；
    • 为 Open source 的授权，故而具有 open source 的所有优缺点；
    • 网路功能强大。
  • Linux 是多人多工的环境，请问何谓多工(Multitask)与多人(Multiuser)：
    • Multitask 指的是多工环境，在 Linux 系统下， CPU 与其他例如网路资源可以同时进行多项工作， Linux 最大的特色之一即在于其多工时，资源分配较为平均！
    • Multiuser 指的是 Linux 允许多人同时连上主机之外，每个使用者皆有其各人的使用环境，并且可以同时使用系统的资源！
二、Linux 的安装与认识 Linux 支援的硬体
  • 一般而言， Linux 需要的配备并不需要太高档，但 Open Linux Server 3.1.1 需要？
    • CPU 需要在 PII, PIII, P4 或 K7, K8 以上等级；
    • RAM 至少需要 64 MB，
    • 硬碟至少 550 MB，全部安装则需要 1.7GB
  • 什么是 IDE 界面，一般而言，普通 PC 允许几个 IDE 界面与装置？
    • IDE 为用来传输硬碟资料的一个汇流界面；
    • 共有 IDE1, IDE2 ，分别有 master 与 slave 所以共四个 IDE 装置支援！
  • IDE2 的 master 之第一个 logical 磁碟中，其装置代号（档案名称）为何？

    • /dev/hdc5
  • 在硬碟分割 (Partition)时，最多有几个 primary + extended ？

    • Primary + Extended 共四个，其中 Extended 通常只有一个！ ( 更详细的硬碟与 MBR 可以参考 这里 这篇讨论 )
  • 若在分割的时候，在 IDE1 的 slave 硬碟中，分割‘六个有用’的磁区（具有 filesystem 的），此外，有两个 primary 的磁区！请问六个磁区的代号？
    • /dev/hdb1(primary)
    • /dev/hdb2(primary)
    • /dev/hdb3(extended)
    • /dev/hda5(logical 底下皆为 logical)
    • /dev/hda6
    • /dev/hda7
    • /dev/hda8

      • 请注意，5-8 这四个 logical 相加的总和为 3！
  • 一般而言安装 Linux 至少要有哪两个 partition 呢？
    • 根目录 / (root)
    • 虚拟记忆体 Swap
  • 一般而言，在 RAM 为 64MB 或 128 MB 的系统中， swap 要开多大？

    • 约两倍的 RAM ，亦即为 128 MB 或 256 MB ，可获得较佳效能！
  • 光碟机与软碟机的代号（装置档案名称）？
    • /dev/cdrom
    • /dev/fd0
  • 网路卡（Network Interface Card, NIC）的代号？
    • /dev/eth0
  • 预设的 Linux 档案格式为何？又，目前常用的 Journalling 档案格式为何？
    • Ext2
    • Ext3, Reseifs
  • 安装 Linux 的主要流程？
    • BIOS（决定由 cdrom 或 floppy 开机，并载入PC硬体资讯）
    • 载入 install kernel loader ：
    • 收集硬体资讯
    • Hard Disk 之 Partition
    • Formation
    • Softpackage 的选择
    • 开始安装！
  • 什么是 GMT 时间？台北时间差几个钟头？

    • GMT 时间指的是格林威治时间，为标准的时间，而台北时间较 GMT 快了 8 小时！
  • Tap, SCSI 硬碟, RAID, printer 的装置代号？
    • Tap      : /dev/ht0 (IDE), /dev/st0 (SCSI);
    • SCSI H.D.: /dev/sd[a-p],
    • RAID     : /dev/md[0-15];
    • printer  : /dev/lp[0-2]
三、简易 KDE 的使用( X-Window)
  • 若以 X-Window 为预设的登入方式，那请问如何进入 Virtual console 呢？

    • 可以按下 [Ctrl] + [Alt] + [F1] ~ [F6] 进入 Virtual console ( 共六个 )；
    而按下 [Ctrl] + [Alt] + [F8] 可回到 X-Window 的 desktop 中！
  • 如何修改进入 Linux 时候的 run-level ？又 run-level 0, 1, 3, 5 各代表什么意思？
    • 修改 /etc/inittab 里头的设定即可；
    • 0：关机(如 init 0 )；

      • 1：单人维护模式，没有网路功能；
      3：纯文字介面登入，多人多工环境；
      5：X-Window 登入模式，多人多工模式。
  • XFree86 在 X-Window 中的角色为何？

    • 基本角色是控制显示相关硬体的核心角色，也可以说程式 X-Window 的 Server ，此外， KDE 这个 Window management 则是 X-Window 的 Client 呦！因此， XFree86 若死掉了，那么 KDE 就无法被启动！
  • XFree86 的主要设定档在哪里？

    • 就是在 /etc/X11/XF86Config-4 这个档案！
  • KDE 预设提供多少个 Virtual desktops ？

    • 预设是提供四个，就是在进入 KDE 之后，最下方的 bar 上面有 1,2,3,4 那个字样的那个咚咚！
四、线上求助 ( Help )
  • 在 Linux 系统中，安装的套件 (RPM安装) 预设的文件资料放在那个目录底下？

    • /usr/share/doc
  • 查看 Linux 系统的线上求助可以使用什么指令？

    • man command
    info command
  • 使用 man 来查询线上求助的时候，若要查询类似参数档(如/etc/passwd)需如何？

    • man 5 passwd 或是例如 syslog.conf 则： man 5 syslog.conf 那个 5 即是大部分的 config 档案的查询。
  • 使用 man 查询 command 的所有相关指令时，需要下什么参数？

    • man –k command 例如 man –k passwd
  • man page 的 man path 变数，记录在那个档案中呢？！

    • /etc/man.conf
五、vi 的使用
  • 在 linux 底下最常使用的文书编辑器为 vi ，请问如何进入编辑模式？
    • 在一般模式底下输入： i, I, a, A 为在本行当中输入新字元；（出现 –Insert- ）
    • 在一般模式当中输入： o, O 为在一个新的一行输入新字元；
    • 在一般模式当中输入： r, R 为取代字元！（左下角出现 –Replace-）
  • 如何由编辑模式跳回一般模式？

    • [Esc]
  • 若上下左右键无法使用时，请问如何在一般模式移动游标？

    • h, j, k, l
  • 若 [pagedown] [ pageup] 在一般模式无法使用时，如何往前或往后翻一页？

    • [Ctrl] + [f]
    [Ctrl] + [b]
  • 如何到本档案的最后一行、第一行；本行的第一个字元、最后一个字元？

    • G, 1G, 0, $
  • 如何删除一行、n行；如何删除一个字元？

    • dd, ndd, x 或 X （dG 及 d1G 分别表示删除到页首及页尾）
  • 如何复制一行、n行并加以贴上？

    • yy, nyy, p 或 P
  • 如何搜寻 string 这个字串？
    • ?string (往前搜寻)
    • /string (往后搜寻)
  • 如何取代 word1 成为 word2，而若需要使用者确认机制，又该如何？
    • :1,$s/word1/word2/g 或
    • :1,$s/word1/word2/gc （需要使用者确认）
  • 如何读取一个档案 filename 进来目前这个档案？

    • :r filename
  • 如何另存新档成为 newfilename？

    • :w newfilename
  • 如何存档、离开、存档后离开、强制存档后离开？

    • :w； :q： :wq； :wq!
  • 如何设定与取消行号？

    • :set nu
    :set nonu
六、档案与目录管理
  • 请问底下的目录与主要放置什么资料？
    • /etc/：几乎系统的所有设定档案均在此，尤其 passwd, shadow
    • /etc/rc.d/init.d：系统开机的时候载入服务的 scripts 的摆放地点
    • /boot：开机设定档，也是预设摆放核心 vmlinuz 的地方
    • /usr/bin, /bin：一般执行档摆放的地方
    • /usr/sbin, /sbin：系统管理员常用指令集
    • /dev：摆放所有系统装置档案的目录
    • /var/log：摆放系统登录档案的地方
  • ‘旧的’ Unix 系统与 Linux 系统的‘档名’最多可以容许几个字元？

    • 14, 255
  • 什么是绝对路径与相对路径，要由 /usr/share/doc 进入到 /usr/share/man 由相对路径与绝对路径的写法各为何？
    • 绝对路径绝对由 / 开始写起，相对路径则非由 / 写起；
    • cd /usr/share/man ; cd ../man
  • 在非为根目录的任何一个目录中，下达 ls –al 时，均会有‘.’及‘..’这两个目录，请问分别代表什么？
    • .  ：代表本目录
    • .. ：代表上层目录
  • 显示、变换目录的时候，使用什么指令？

    • ls, pwd 为显示； 变换目录用 cd
  • 新增目录、移除目录移动目录与拷贝目录有什么指令可用？
    • 新增： mkdir 目录,
    • 移除： rmdir 目录(但是该目录内必须要已经清空了), rm –rf 目录,
    • 移动： mv directory1 directory2
    • 拷贝： cp –r directory1 directory2
  • 如何查看一个档案的‘内容’（不要使用 vi 的情况下）

    • cat, tac, more, less, head, tail, nl, od(查看二进位制)
  • 什么是 hard link 与 soft link 的档案？有何不同？
    • Hard Links：在做成 hard link 档案时，系统会占用掉一个 inode ，由连结档案可发现其 link 栏位多使用了一个 inode ，当原始档案被删除的时候，该原始档案的内容将继续保留在其他的 Hard Links 档案中；但所有 Link 占用的硬碟总量仅占一个档案的容量大小！(但 Hard link 不能连结不同 filesystem 的档案)
    • Soft Links：类似捷径，当原始档被删除，soft link 档案将找不到原始档了！
  • 如何在 root 的家目录下建立一个 /bin 的连结捷径

    • ln –s /bin /root/bin
  • 若有一个连结档为 testing 连结到 test1.sh ，请问 copy testing 到 /tmp 底下，‘cp testing /tmp’则 /tmp/testing 这个档案会是：(1) 连结档，连结到 test1.sh ；(2) 一般档案，为内容与 test1.sh 相同？

    • 答案为 (2)
  • 当一个档案属性为 –rwxrwxrwt 则表示这个档案的意义为？

    • 任何人皆可读取、可写入，但是不可删除该档案(或目录)，除了 root 与档案或目录拥有者有权可以删除。
  • 我需要将一个档案的属性改为 –rwxr-xr-- 请问该如何下达指令？

    • chmod 754 filename, chmod u=rwx,g=rx,o=r filename
  • 在 /usr/bin/passwd 这个档案的属性为 –r-s--x--x 请问代表什么意思(s)

    • 那个 s 代表为 SUID ，当使用者使用这个档案进行工作的时候，将会具有该档案拥有者的权限！
  • 如何改出 –rwxr-sr-x 与 –rwxr-xr-t这个属性？

    • chmod 2755 filename, chmod 1755 filename
  • 如何查看一个档案的类型 (type) 例如纯文字档、执行档与 setuid 档案等？

    • file filename
  • 若一个使用者的 umask 为 033 ，请问他建立一个新的目录与档案时的预设属性为？
    • 目录：744 ? -rwx-r--r--
    • 档案：644 ? -rw-r--r--
  • 若我需要更改一个档案的拥有者与群组，该用什么指令？

    • chown, chgrp
  • 如何将一个档案的修改日期改成目前的时间？

    • touch filename
  • 如何搜寻一个档案？

    • which (仅用于指令搜寻), whereis, locate, find
  • Linux 预设的档案系统为何？此外，常用的 Journalling 档案格式有哪些？

    • Ext2, Journalling 有 ext3 及 Reiserfs 等
  • less 跟 more 有什么不同？

    • less 可以翻页，但是 more 不行！
  • 在比较两个档案的异同时，常使用的是 diff 与 cmp ，请教两者有何不同？

    • diff 为一行一行比较， cmp 为一个字元(character)一个字元比较
六.1、磁碟挂载与虚拟记忆体问题
  • 我要如何查看 Linux 系统当中所有已经挂载的硬碟容量与 inodes ？

    • df –k, df –i,
  • 我要如何查看目前所在目录的所有档案占用的硬碟空间，此外，如何仅输出结果？

    • du -k, du –i, du -s
  • 如果磁区 /dev/hda3 有问题，偏偏他是被挂载上的，请问我要如何修理此一磁区？

    • umount /dev/hda3
    fsck /dev/hda3
  • 承上题，那么有问题的档案将被移动到那个目录下？

    • lost+found
  • 试说明新增一个 partition 在 /dev/hdb 当中，且为 hdb5时，并挂载上 /disk2 ，需要哪些步骤？
    • fdisk /dev/hdb   按 n 新增，按 e 新增 extended ，再按 n 新增 logical
    • mke2fs –b 2048 /dev/hdb5
    • mkdir /disk2
    • mount –t ext2 /dev/hdb5 /disk2
  • 如何新增加 64MB 的虚拟记忆体 swap ？
    • dd if=/dev/zero of=/tmp/swap bs=4k count=16384
    • mkswap /tmp/swap
    • swapon /tmp/swap
  • 如果要设定一个新挂载上的磁区，令他可以在开机的时候被挂载上，应该编辑哪一个档案？
    • 先 /etc/fstab
    • 再 mount –a
  • 简易说明 quota 的设置流程？
    • 编辑 /etc/fstab， 加入 usrquota and/or grpquota
    • reboot
    • quotacheck –avug  (会产生 aquota.user(group))
    • quotaon –aug
    • edquota –u username
    • edquota –g groupname
    • repquota –vu /dev/hd[a-d][1-16]
七、BASH SHELL
  • 简单说明 bash shell 的功能特征：
    • 命令记忆功能 ~/.bash_history
    • 命令别名功能 alias
    • shell scripts 功能
    • 命令与档案名称补全功能 <tab>
    • 工作控制功能 jobs
  • 在设定变数中，主要的规则为何？
    1. 变数与变数内容以等号来连结；
    2. 等号两边不能直接接空白字元；
    3. 变数名称只能是英文字母与数字，但是数字不能是开头字元；
    4. 若有空白字元可以使用双引号‘ " ’或单引号‘ ' ’来将变数内容结合起来，但须要特别留意，双引号内可以保有变数，但是单引号则仅为一般字元；
    5. 必要时需要以跳脱字元‘ \ ’来将特殊符号（如 Enter, $, \, 空白字元, ' 等）变成一般符号；
    6. 若该变数为扩增变数内容时，则需以双引号及 $变数名称如：‘ "$PATH":/home’继续累加内容；
    7. 若该变数需要在其他子程序执行，则需要以 export 来使变数可以动作，如‘export PATH’；
    8. 通常大写字元为系统预设变数，自行设定变数可以使用小写字元，方便判断（纯粹依照使用者兴趣与嗜好）；
    9. 取消变数的方法为：‘unset 变数名称’
  • 显示环境变数与所有变数的指令为何？

    • env, set,
  • 在环境变数当中，‘使用者家目录、主机名称’的变数名称为：

    • HOME, HOSTNAME
  • 如何让一个变数可以持续到下一个程序 (PID) 去？

    • export variable
  • 在变数的设定当中，双引号与单引号有何不同？

    • 双引号里面可以包含变数，单引号谨代表一般字元！
  • Command1 `command2` 这个指令代表什么意思？

    • 在这一行当中， command2 会先执行，而输出的结果会给 command1 当作参数。
    cd /lib/modules/`uname -r`/kernel 是最常使用的一例
  • 在命令重导向当中， > 与 >> 有什么不同？

    • >  会将导向的 file 覆盖，
    >> 则是增加！
  • 若要将错误的输出导向‘不见了’的装置，该如何是好？

    • command 2> /dev/null
  • 在管线指令中，我要将 last 输出的结果显示 root 的‘登入次数’， 如何做？

    • last | grep root | cut –d “ “ –f 1 | wc -l
  • 如何设定一个变数名称为 name ，使其显示为‘ VBird’s testing variable. ’？
    • name=VBird\’s\ testing\ variable.
    • name=”VBird’s testing variables.”
    • echo $name
  • 请问 bash shell 的环境变数与自己的个人变数可以登入便设定的档案？
    • Open Linux：

      • /etc/profile, /etc/config.d/shells/bashrc, ~/.profile, ~/.bashrc,
    • Red Hat ：

      • /etc/profile, ~/.bash_profile, ~/.bashrc,
  • 如何查询曾经操作过的指令？如何执行第 26 个操作过的指令？上一个操作过的指令？
    • history
    • !26
    • !!
  • 如何设定命令别名？使 lm 与 ls –al|more 功能相同

    • alias lm=’ls –al|more’
  • 如何将 /bin 的所有资讯输出到 /home/testing.dat 这个档案？

    • ls –al /bin 1> /home/testing.dat
  • 在上一题中，若还要输出到荧幕上，要如何是好？

    • ls –al /bin | tee /home/testing.dat
  • 执行 find ，并将正确的结果输出到 right 而错误结果输出到 error 当中？

    • find / -name test 1> right 2>error
  • 如何在指令列模式中将 /root/.bashrc 的资料加在 /home/col/.bashrc 当中？

    • cat /root/.bashrc >> /home/col/.bashrc
  • 不要显示执行的结果要如何是好？

    • command  > /dev/null 2>$1
  • 列出这个月曾经登入主机的使用者资讯即可，不需要重复？

    • last | cut –d” “ –f1 | sort | uniq
  • 万用字元当中， *, ?, [] 各代表什么意思？
    • * 代表 0 到无限多个字元；
    • ? 代表一个任意字元；
    • [] 代表一个字元，这个字元在某一个限制范围内。
七.1、SHELL SCRIPTS
  • 什么是 shell scripts ？ scripts 有何功用？
    • 简单的说， scripts 就是一个内部含有多个或复杂的 command 的纯文字档案；
    • scripts 可以进行 program 的功能，但速度上较 C 慢了点！
  • 要撰写可以经由键盘输入的 scripts 时，常使用到的指令？

    • read  variable
  • 在 shell script 当中，在控制式中， && 与 || 代表什么意思？

    • 分别代表‘和(同时成立)’及‘或(仅其一成立就成立)’的意思！
  • 在使用回圈的时候，常使用到的控制式为哪三个？

    • for, while, until
  • 执行 scripts 的方法有哪两种？
    • 使用 sh script 或
    • 以 chmod 增加 scripts 的属性为可执行， chmod 777 script 并执行 scripts。
  • 如何宣告一个变数成为整数型态？

    • declare  -i  variable
  • 为何在 shell script 前面都要宣告 shell 呢？

    • 宣告 shell 方能让 script 了解该内容需要以何种 shell 来执行！目前 Linux 通常宣告 /bin/bash 这个 shell ，然而若在非 shell 环境中，又没有宣告 shell 类型时，可能会造成 script 无法执行的情况。
  • 在判断式中，如何判断一个档名是否存在？

    • if [ -e filename ] 若存在则回传值为真！
  • 在执行一个 scripts 时，在 scripts 内的变数， $0, $1 代表什么？
    • $0 代表 scripts 的档名；
    • $1 代表第一个 parameter，例如 /etc/rc.d/init.d/xinetd start 那个 start 的变数即为 $1
  • 若要写一个既定的 parameter （如 start ），用哪一个判断式较简单？

    • 可以使用 case …. Esac 的语法较为简单。
  • 如何印出目前系统中的所有帐号，并加以排序且输出到 /tmp/account 中？

    • cut -d ‘:’ -f 1 /etc/passwd | sort > /tmp/account
  • 如何在不执行 scripts 的情况中 debug ？

    • sh -n scripts
八、基本帐号管理
  • 如何新增一个使用者 username，且该使用者没有家目录？

    • useradd -M username
  • Linux 使用者的帐号、密码与群组的名称档案放在哪里？
    • /etc/passwd
    • /etc/shadow
    • /etc/group
  • 建立新使用者的预设家目录内容在那个目录中？

    • /etc/skel
  • 建立一个新使用者时，其使用到的相关档案有哪些？
    • /etc/default/useradd,
    • /etc/login.defs,
    • /etc/skel/
    • /etc/passwd,
    • /etc/shadow
  • root 的 UID 与 GID 各为何？

    • 皆为 0
  • 如何让一个使用者不能登入主机，但是可以收信？

    • 将 /etc/passwd 最后一栏代表 shell 的名称改为 /bin/false
  • 试说明一个使用者登入系统的流程？
    1. 登入：使用 /bin/login 程式，并输入 ID 与 passwd ；
    2. 确认密码：搜寻 /etc/passwd, /etc/shadow 确认密码！并取得使用者的相关讯息。
    3. 查核 pam 登入模组：这个需要视主机的设定而定！
    4. 取得并执行 shell ：由 /etc/passwd 取得 shell 之后，并执行 shell ，以 bash 为例，将读入： /ete/profile ? ~/.bash_profile ( 或 .bash_login 或 .profile ) ? ~/.bashrc ? 登出的时候执行 ~/.bash_logout
  • 在 /etc/shadow 当中的日期设定中，其数字代表的意义为何？

    • 由 1970 年开始计算，故 1970 年 一月一日为 1 ，2002 年 1 月 1 日为11689
  • 如何变更使用者的一些属性？

    • usermod, chfn, chsh, passwd
  • 如何视察一个使用者 username 所拥有的群组呢？

    • groups username
  • 试说明如何手动增加一个使用者 username 与群组 groupname？
    1. 先看看 /etc/skel 当中，预设要给 user 的家目录内容；
    2. 新增 group ： groupadd groupname
    3. 新增 user ：useradd -m -g groupname username
    4. 给予密码： passwd username
  • 试说明 /etc/passwd 这个档案的内容与格式：

    • 帐号; 密码; UID; GID; 说明的内容; 家目录; SHELL
  • 使用 id 这个指令时，可以显示什么讯息资料？

    • UID, GID 跟 GROUP
  • 可以控制使用者使用主机资源的预设档案在哪里？

    • /etc/security/limits.conf
  • 基本的压缩指令有哪些？

    • tar, gzip, compress
九、开机程序
  • 试说明开机流程：
    1. BIOS
    2. MBR ( boot loader )
    3. Loader ( lilo or grub, stage 1 and stage 2 )
    4. Kernel loader ( /boot/vmlinuz )
    5. init process ( 读取 /etc/inittab 取得 run-level )
    6. 开始执行 /etc/rc.d 内的 scripts
    7. 执行 /etc/modules.conf 内部的额外 kernel 模组
    8. 执行 /etc/rc.d/rc[1-6].d 的这些 run-level 内的 scripts ！
    9. 执行 /bin/login 等待使用者登入！
  • 开机时后的载入讯息可以看哪里？

    • dmesg
    grep “kernel” /var/log/messages
  • 改变 run-level 或关机的指令

    • shutdown,
    halt,
    reboot,
    init or telinit
  • 改变登入 Linux 时候预设的 run-level 要改那个档案？

    • /etc/inittab
十、程序与资源管理
  • 如何查看目前的程序？

    • ps, top,
  • 如何查看目前的记忆体使用状况？

    • free, top,
  • 目前的工作如何丢到背景中？

    • [Ctrl] + z
  • 如何取得目前背景中的工作，且将他拉回前景中？

    • jobs  及 fg %number
  • 如何设定一个程序在开始执行时候的优先值？

    • nice –n [number] [command]
  • 什么指令可以修改一个正在执行的程式之 nice 值？

    • top, renice
  • 在例行性命令中，使用的两支 demane 是什么？

    • atd,
    crond
  • 使用 crontab 这个‘指令’的时候，如何可以查看目前的工作与删除目前的工作？

    • 编辑： crontab –e,
    查看： crontab –l,
    删除： crontab –r
  • 常用的 kill 指令之 signal 当中， 1, 9, 15 代表什么？
    • 1  重新读取一次 config file
    • 9  强制删除此一执行程序
    • 15 terminal结束的意思！
2002/06/28：首次将所有的问题独立出来喔！
2005/05/23：接到网友来信指正， init 0 为‘关机’，并非之前写的‘重新开机’喔！！


鸟哥的 Linux 私房菜 -- 伺服器架设篇目录

为取得较佳浏览结果，请爱用 firefox 浏览本网页

鸟哥的 Linux 私房菜 -- 伺服器架设篇目录
特别强调
底下这些文件主要是针对 Linux 的网路伺服器架设来书写的，鸟哥主要以使用 RPM 安装的 CentOS 作为基础的作业系统， CentOS 是属于 Red Hat 系统的作业系统，所以理论上 RHEL, CentOS, Fedora 等版本都适用的啦！ 为什么要使用预设的套件管理方式来安装所有的伺服器呢？这是因为大多数的 Linux 开发商都会有所谓的线上升级系统， 包括 CentOS/Fedora 的 yum ，以及 SuSE 的 YOU ，还有 Debian 的 apt 等等， 因为有线上‘自动升级’，所以当然会比您自己手动使用 Tarball 的安装方式来的方便且安全！ 因为你的系统上头所有的资料可以在第一时间内‘自动’修补完毕嘛！

要架设好一部 Linux 主机实在很简单，只要按照鸟哥网站上的步骤，一步一步的慢慢设定下去， 铁定可以完成您的设定的！但是，要维护好一部 Linux 主机，却是很困难的！您必须要熟悉 Linux 的系统架构、网路的基本知识如协定、IP、路由、DNS 等等的基础知识才行！

无论如何，您要开始‘伺服器架设篇’之前，请务必先读完‘Linux 基础篇’的文章才行！ 否则几乎就如同上面提到的，维护这样的一部 Linux 主机，是很花时间的！没有这个认知，那就不要架站吧！免得毒害其他的同袍呐！

在架站的过程当中，无论出现任何问题，第一个步骤就是察看登录档 (log file)，那是克服问题的地方！

第一部份：架站前的进修专区
第二部分：主机的简易防火措施
第三部分：区域网路内与小型企业常见伺服器架设
第四部分：一些旧资料
大标题的图示 第一部份：架站前的进修专区
架站需要很强的 Linux 基础概念以及网路基础知识，否则的话，当网路断断续续的时候，您永远也不会知道是哪里出问题！ 而当某个伺服器软体出问题的时候，您永远也不晓得是发生了什么事情！老人家说‘对症下药才有效’， 随便吃药是不可能‘无病强身’的！因此，对于网路伺服器来说最重要的基础档案权限、程序之启动关闭与管理、 Bash shell 之操作与 script 、使用者帐号的管理等等，您都必须要具备最基础的认知才行， 否则，网路真的不好碰！

在这一篇当中，鸟哥会介绍一下架设伺服器之前你必须要具备的基础观念，以及重要的网路基础， 当然啦，一大堆的网路指令是需要熟悉的。这些网路指令不是要你背起来， 而是希望在你需要的时候可以很快速的查阅到如何使用的说！ 无论如何，请您务必在架站前‘读过 Linux 基础篇’及‘ 读过网路基础篇’的文章，否则大家很难跟您讨论呢！ 这个部分鸟哥放在最前面，希望大家‘务必’要查看这些资料啊！

序言 2003/07/14 | 先来谈一谈架站篇的内容吧！得了解一下这个篇幅当中主要在介绍些什么？ 还有，您要如何进入伺服器的架设状况呢？！有些事情还是得了解的啦！
架站之前所需 的技能分析 2006/02/08 | 架站之前您至少需要学会什么咚咚呢？可能要知道的有‘什么是群组、使用者与其他类群组？’ ‘什么是档案的权限与树状目录？’‘什么是 Shell 与 Shell Scripts ？’‘什么是服务？’以及其他林林总总需要了解的事项， 不知道这些东西，那就不要想架站啦！否则....怎么翘辫子的都不晓得哩！
简易网路基础架构 2006/07/12 | 要进入多样化的网路世界之前，请先了解一下网路的基础架构吧！例如：什么是 IP？ 一个资料封包传送到 Internet 上面的时候，他的程序是如何进行的？什么是 TCP 封包？另外， Hub 与 Switch 哪一个比较好？为什么呢？嘿嘿！这个在架站之前都必须要先了解一下， 否则怎么架站呀！？而且了解整个网路架构之后，比较容易网路除错呦！
区域网路架构简介 2006/07/15 | 在了解了基本的 网路架构 之后，再来就是将你家的电脑全部连在一起好做成一个 LAN 啦！那你预计有几台 PC 在你的 Linux 主机附近？要怎么连接这些不同的电脑才行？需要哪些网路参数？ 该如何挑选你的网路硬体装置及一些线材的选择？另外，先将你的 Windows 电脑的网路设定搞定吧！呵呵！来这里查看看吧！
连上 Internet 2006/07/24 | 如何连上 Internet 呢？ Linux 的网路相关设定档案有哪些？使用 ADSL 拨接、Cable moden 的上网方式、以及固定 IP 的上网方式是怎样的一个状态？！此外，万一你是 ADSL 拨接的，而你的网路断线了， 要如何随时让 Linux 自行侦测，并且让他自行重新拨接呢？来这里看看我们是怎样做的吧！！
Linux 网路功能 2006/08/02 | 嘿嘿！已经可以连接上网路了吗？如果可以的话，那就恭喜你啰！那么赶快来试一试 Linux 的网路功能吧！先利用 ping, ifconfig, route, traceroute 来看看你的网路结构；再利用 telnet, ftp, ncftp 来试试看 Linux 强大的网路功能哩！此外，我们还有文字界面的浏览器 lynx 呦！另外，嘻嘻！还有 wget 这个好用的下载软体呢！还要介绍怎么查询其他 Internet 上面的主机 IP 呦！
Linux 网路侦错 2006/08/04 | 了解了基础的网路功能之后，现在要来解决你无法连上 Internet 的困扰啰！对！没错！不要怀疑，就是一些 FAQ 问题的总整理啦！呵呵！如果你一直无法连接上 Internet 的话，这里面的资料或许会对你有启发的作用呢！赶快来除虫吧！
大标题的图示 第二部分：主机的简易防火措施
有很多团体做过许多作业系统安全性侦测的研究，他们发现一部没有经过更新与保护的 Linux/Windows 主机 (不论是一般个人电脑还是伺服器)，只要一接上 Internet 几乎可以在三小时以内就被入侵或被当成跳板！ 您瞧瞧，这是啥世界啊～所以说，要好好的保护好您自己的伺服器主机才行喔！那应该要如何保护你的伺服器主机呢？ 基本上，你最要知道的是你的伺服器开了多少网路服务，而这些服务会启动什么埠口？ 根据这层关系来关闭一些不必要的网路服务。再者，利用线上更新系统让你的 Linux 随时保持在最新的软体的状态， 这个小动作可以预防绝大部分的入侵攻击，可以说是最重要的一步了！最后才是架设基础防火墙。

因为 Linux 的功能太强了，如果你不好好的保护好你的主机，要是被入侵并且被当成跳板，这可能会让您吃上官司的！ 不要小看这层动作喔！虽然被入侵后只要将就系统移除并且重灌后，你的伺服器主机就能够‘短暂’的恢复正成， 不过如过您的一些操作习惯不改的话，呵呵，并不是重灌就能够让你的伺服器主机活的好好的喔！ 所以啰，我们在架站之前，基本的网路防备措施还是得来了解一下，免得三不五时要重灌、重灌、重灌、、、、

限制对外埠口 port 2006/08/08 | 在上网之前，最起码要知道你的 port 目前开放了哪些呢？ 最重要的工作就是，将所有的 port 都给他关闭 (反正我们还没有提到架站的部分) ，那么这些关闭 port 的地方在哪里？要如何关闭？每个 port 对应的服务是什么？在哪里可以查询到？来这儿瞧一瞧！
Linux 网路套件升级 2006/08/16 | 晓得你能上网之后的第一件工作吗？不是查资料！不是申请 DNS ，也不是去看新闻，而是去‘更新你的套件！’这个相当的重要， 请您立刻更新你的套件版本，否则....嘿嘿....怎么被怪客入侵的都不晓得呢！
简易 Router 架设 2006/08/30 | 这个可就有趣啦！我们要介绍一下如何在 Linux 这个系统当中， 让他可以当作一个高贵的 Router 哩！这个应该很适合小型的企业内部来使用！用 486 的电脑就可以达成啰！同时我们也会介绍动态路由软体 zebra 哩！
认识网路安全 2006/09/06 | 好了！好不容易，连那个 Router 都是属于内部网路的延伸，现在终于来到要进入 Network 架设安全的网站啦！ 不过，在这个时候可得先来了解一下，嘿嘿嘿嘿！我们的 Internet 到底有多危险哪？！这才是进入网路的第一课呢！会架设网站没啥了不起， 但是会架设一个‘安全的网站’，哇！那可真是了不起呀！在这一小节当中， 我们会约略的谈一谈网路安全的几个基础概念而已，比较重要的是： ‘如何恢复一部被入侵的主机’！
防火墙与 NAT 2006/09/15 | 好了，目前你的所有的内部电脑都可以上网啰！这个时候， 请特别留意你的‘防火墙’啰！我们这里选择 iptables 与 TCP_Wrappers 来进行我们的防火墙规划设定，嗯！ 这个防火墙真的很简单，所以还要再加强其他的考虑呦！
申请合法的主机名称 2006/09/16 | 要架站吗？嘿嘿！当然就需要让你的主机有一个‘合法’的名字啰！ 那么如何‘建立一个合法的名字呢’？最简单的方式就是向 ISP 申请主机名称的对应了！而主机名称的对应有静态与动态两种，我们这里会介绍 www.no-ip.org 的申请方式，当然不会放过 .idv.tw 的申请流程啰！
大标题的图示 第三部分：区域网路内与小型企业常见的伺服器架设
在开始实际 Linux 的网路伺服器架设之前，切记前面两篇的内容都已经阅读过，并且已经强化您主机的网路安全后，才开始架设吧！ 在这一篇当中我们会介绍区域网路内常见的 DHCP, NFS, NIS, SSH, vsFTP, SAMBA 等伺服器，当然啦，常见的网际网路伺服器如： WWW, email, DNS 等也不会放过的！这些伺服器的设定以及未来的应用是非常好玩的，不过如果前面两篇您没有预先读过， 那么您的伺服器被入侵也是一个可以‘预期’的后果！所以啰，看完前两篇后，仔细的开始瞧一瞧这一篇的伺服器吧！ ^_^

远端连线伺服器 telnet, ssh, rsh, vnc, xdmcp 2006/09/19 | Linux 由于安全性的考量，所以目前已经预设不开放 telnet 啰，好了，那么如果你还想要开放 telnet 怎么办？又！如果要开放 SSH 又要怎么办，又！如果要针对这两个咚咚来设定安全机制，又要怎么做？！鸟哥来提供几个小建议吧！ 还有，有了 sftp 干嘛需要开放 FTP 呢？
NFS 伺服器 2006/09/22 | 最简单的伺服器架设之一就是 NFS 了！架设真的是很简单！不过，这个 NFS 有什么用途呀！呵呵！他就是 Linux <-> Linux 档案传送之间最简便的方式之一了！ 架设简单，使用也很简单，不过，就是有点危险～所以，我们只要对内部开放就好了呦！
NIS 伺服器 2006/10/11 | NIS 是什么东西呢？假如我有好几部l Linux 主机，而这几部 Linux 主机的‘帐号与密码其实都一样’啊！这样的架构其实在一般的企业界是很常见的，果真如此的话，如果每一部 Linux 主机都要设定帐号密码，会疯掉，此时就需要 NIS 的帮忙啦！NIS 可以让网域当中所有使用者的帐号与密码都放置在一部 NIS server 当中，至于其他的 Linux 主机就做为 NIS Client ，当有用户要登入 NIS client 时，那么 NIS client 就会向 NIS server 要求读取帐号与密码的资料，如此一来，只要在 NIS server 上面进行帐号与密码的管理即可啰！
DHCP 伺服器 2006/12/06 | DHCP 就是分配‘动态 IP ’的协定啦！那么如果你的内部网路还蛮大的， 而且你又不想一个一个的去设定你的 Client( 客户 ) 的电脑，那么使用 DHCP 实在是一个很方便的事情！不过，由于 Client 端每次开机都要搜寻一次 DHCP ，所以开机速度很慢，建议内部电脑不多的时候， 还是手动设定比较好ㄋㄟ～
DNS 伺服器 2006/10/20 | 可以的话，最好是不要架设 DNS 啦！一者，很难设定的好，二者， 又有安全性上面的顾虑，所以，非必要，鸟哥个人认为，还是不要设定 DNS 伺服器的好！但是，很多时候，偏偏没有 DNS 在管理主机名称上面，又很麻烦！唉！ 当真是两难呐！我们这里会先提一个观念：‘我要架站，是否一定需要架设 DNS 伺服器？’这个观念相当的重要，很多人都被市面上的书误导了～再者，才是简易的 DNS 设定啦！
WWW 伺服器 2006/11/10 | 目前最热门的网页伺服器之一，就是 LAMP 啰，什么是 LAMP 呢？呐！简单的说，也没有什么了不起，不过是 Linux + Apache + MySQL + PHP 啰！这里我们除了介绍最简单的 RPM 方式安装的 LAMP 伺服器，如果要升级！哇！可累了～要使用 tarball ㄋㄟ！此外，还会介绍 2.xx 版的 Apache 喔！
Mail 伺服器 2006/11/30 | 在这个邮件伺服器的架设中，我们首先谈论 Mail 与 DNS 的重要相关性，然后依序介绍 Mail Server 的相关名词，以及 Mail Server 的运作基本流程与协定，也会谈到相关的 Relay 与邮件认证机制等项目， 这些项目对于未来邮件主机的管理与设定是重要的，请不要忽略了这方面问题的讨论喔。 在这篇新文章中，我们将 sendmail 与 postfix 合在一起讲了，因为目前 Postfix 这个伺服器的设定上面具有比较佳的亲和力， 所以 sendmail 我们仅作个简单的介绍，主要在以 Postfix 为主的邮件主机架设喔！
SAMBA 伺服器 2006/12/29 | Linux 对 Linux 使用的是 NFS ，那么 Windows 对 Windows 使用的是 NetBEUI ，好了，那么 Linux 对 Windows 用的是什么？没办法，配合 Windows ，所以我们使用的也是 NetBEUI 啰！而使用的套件就是 SAMBA 啦！
vsFTPd 档案伺服器 2006/12/20 | vsftpd 是 very secure FTP daemon 的意思，这是个较为简单但比较强调安全议题的一个 FTP 伺服器软体说。虽然功能比较简单，不过该有的也都有了， 用 vsftpd 来架设一部提供校内共同分享资料的 FTP 伺服器真的是简单啊！ 所以，那就赶紧来瞧瞧先！
NTP 时间伺服器 2006/12/08 | NTP 的全名是‘Network Time Protocol’，主要的功能就是让 Client 端的电脑可以透过 NTP 这个协定来进行网路校时的工作啊！什么时候需要网路校时呢？呵呵！像鸟哥的 Cluster 就需要时间同步的说～
简易 Proxy 伺服器 2003/09/16 | 代理伺服器这个东西对于大企业可了不得啰！可以提升内部的网路的速度呢！虽然是有点奇怪的说法， 不过，他确实可以‘假象’的提升企业内部的网路工作效率，嘿嘿，废话不多说，赶快来看看怎样架设吧！
简易 APT Server 2003/08/27 | APT (Advanced Package Tool) 是由 debian 这个 distribution 所发展的一个套件管理工具，不过因为太好用了，所以很多机构就将他设计成为可以符合其他 distribution 做为网路更新的一项利器！在这个章节当中，我们要介绍如何在 Red Hat 9 上面建置一个 ATP 伺服器，并且提供 Mandrake 的更新给 Client 端来更新使用！
OpenWebMail 2004/08/26 | 使用 Webmail 可以避免大部分的病毒信呢！所以这个小东西有越来越热门的趋势！ 在这里，我们使用台湾人自己写的一套自由软体：OpenWebMail 来架设我们的 MUA ！ 很不错的东西！赶紧来看看先！
平行计算电脑的建置 Cluster Server 2003/05/12 | 当您想要使用电脑来进行大量的计算时，呵呵！这个平行计算电脑的架构就显得相当的重要啦！基本上， Cluster (丛集电脑) 的解释相当的紊乱，我们这里主要以‘平行计算’的功能来做为 cluster 的说明！什么是平行计算呢？当你需要使用数值模式(一些很庞大的程式，会使用到很大量的 CPU 运算功能)，那么越多颗 CPU 来分担这样的工作，自然运算的速度就越快了！而这个将运算资料同时丢给很多颗 CPU 来跑得功能，就是我们简称的平行运算啦！
课后练习的参考解答 | 每个章节虽然不见得会有课后练习，不过还是有很多的练习题啊！这些练习题真的可以尝试作作看，对于新手来说， 这个练习题绝对会有帮助的！我这里仅列出鸟哥自己的解答，解答的比较粗浅，不过，还是可以做为读者参考的依据咯！
大标题的图示 第四部分：一些旧资料
一些比较老旧的资料啦！仅供参考而已～

内容大纲 | 主要内容说明
Red Hat 6.x 旧文件 1999~2001 | 这些是早期针对Red Hat 6.x所写的伺服器设定文章，当时写的简单到不行， 很多地方甚至可能是有错误的！所以，除非您的系统是Red Hat 6.x版，否则不要再看啦！...
伺服器篇第一版 2002~2005 | 这些文件则是鸟哥的伺服器篇第一版的内容，写成的时间大约是2003年，但是直到2005年都还有在进行修改～ 这些文章与书籍内的就非常相近了！列出来主要是让大家容易查阅与对照啦！...
伺服器篇第二版 2005~2008 | 这个部分则是第二版的内容，不过目前站上的资料还没有开始进行修改，所以这部份还没有开始进行汇整啰～


鸟哥的 Linux 私房菜 -- 架站前技能分析

为取得较佳浏览结果，请爱用 firefox 浏览本网页

架站之前所需的技能分析
切换解析度为 800x600
最近更新日期：2006/06/06
很多刚接触 Linux 的朋友常常会问的一句话就是：‘我学 Linux 就是为了架站，既然只是为了架站，为什么我还要学习 Linux 的其他功能？例如：例行性工作排程、Bash Shell 、干嘛去认识所有的登录档等等，我又用不到！此外，既然有好用的 Web 介面的 Server 架设软体，可以简单的将网站架设起来，为什么我还要去学习 vi 手动的去编辑一些设定档？干嘛还需要去理解他的原理？’ 上面这些话对于刚刚学会架设网站的人来说，真是替他们道出了一个新手的心声啊！ 不过，对于任何一个曾经有过架设公开网站的朋友来说，上面这些话，真的是会害死人～

要知道，‘架站容易维护难’啊！更深一层来说，‘维护还好、除错更难啊！’ 架设一个网站有什么难的？即使您完全没有摸过 Linux ，只要参考鸟哥的书籍或者是网站，而且一步一步照着做， 包准您一个下午就可以架设完成五个以上的网站了！所以说，架站有什么难的？ 但是，要晓得的是，这样的一个网站，多则三天，少则数小时，立刻就会被入侵了！ 此外，被入侵之后，或许可以藉由一些工具来帮您将 root 的密码救回来，可惜的是，这样的一个网站还是有被做为中继站的危险存在的！此外，如果您使用工具 (例如 Webmin) 却怎么也架设不起来某个网站时，要怎么解决？如果您不懂该 Server 的运作原理与 Linux 系统的除错讯息，那么难道只能无语问苍天？不要怀疑这种情况的可能性，参考一下 BBS 上面的留言就可以很清楚的知道这种情况的存在有越来越明显的趋势呢！

所以说，架站之前还是有一些基本的技能需要学会的！而且这些技能是‘一旦学会之后，真正是终身受用啊！’ 只要花一个学期(三~六个月)就能学会一辈子可以使用的技能，这个学习的投资报酬率真是太高了！ 所以，一开始的学习不要觉得苦，那真的是值得的喔！^_^

1. 前言
2. 基本架站流程
    2.1 了解网路基础
    2.2 了解架站的目的
    2.3 Linux 安装硬碟规划
    2.4 了解欲架设的网站服务原理
    2.5 服务的套件安装、漏洞修补、套件升级...
    2.6 主机设定、启动、观察与除错
    2.7 用户端设定、观察与除错
    2.8 安全性设定
    2.9 服务日志、登录档与备份管理
    2.10 小结语
 3. 自我评估是否已经具有架站的能力
4. 课后练习
5. 针对本文的建议：http://phorum.vbird.org/viewtopic.htm?t=23676
大标题的图示 前言
如果有人问你：‘Linux 最强大的功能是什么’？ 大概大家都会回答‘是网路功能啊！’， 接下来，如果对方再问：‘所以学 Linux 就是为了架站啰？’ 呵呵！这个问题可就见仁见智啰！说穿了， Linux 其实就是一套非常稳定的作业系统，那么任何工作只要能在 Linux 这个作业系统上面跑，那他就是 Linux 可以达成的功能之一啰！所以 Linux 的作用实在不止于网路伺服器的架设呐。

举例来说，在 Linux 上面开发跨平台的程式 (program) 诸如大型的数值模式，由于 Linux 的稳定与完善的资源分配功能，使得在 Linux 上面开发出来的程式运作的又快又稳定。此外，诸如 KDE, GNOME 等漂亮的图形介面，搭配诸如 Open Office 等办公室软体，Linux 立刻摇身一变而成为优秀的的办公室桌面电脑了 (Desktop)。所以说，千万不要小看了 Linux 的多样功能呐。

不过，不管怎么说， Linux 的强大网路功能确实是造成 Linux 能够在伺服器领域内占有一席之地的重要项目。 既然如此，我们就好好的来探索一下 Linux 的网路世界吧！首先， Linux 到底可以达成哪些网路功能呢？这可就多着咯！不论是 WWW, Mail, FTP, DNS, 或者是 DHCP, NAT 与 Router 等等，Linux 系统都可以达到，而且，只要一部 Linux 就能够达到上面所有的功能了！当然，那是在不考虑网路安全与效能的情况下，您可以使用一部 Linux 主机来达成所有的网路功能。

‘哇！Linux 有那么多的功能啊！那么我可以轻轻松松的就架设好一部以 Linux 为作业系统的伺服器吗？！’呵呵！很可惜，答案是‘否’！ 您无法轻松的就完成一部‘堪称完美’的伺服器架设，而是必需要很用心， 并且学习很多相关的概念与操作方法后，才能够架设好一部完美的伺服器。什么！要很用心啊！使用 Windows 作业系统随随便便就可以架设好好几个伺服器了，那么我干嘛要花时间去学习 Linux 来架设伺服器呢？

唉！这真是伤脑筋呐！‘谁说使用 Windows 架设伺服器就很简单’的？ 就鸟哥的感觉来说，架设 Windows 伺服器一点也不轻松。为什么呢？
  1. 授权模式
    首先，在尚未进入伺服器设定之前，您必需就‘授权模式’进行深入的研究，因为， 不同的使用者数量将会影响到您的伺服器的‘价格！’，光是这一点，就可能让鸟哥一个头两三个大了～ 因为，玩工程的，对于‘价格’这东西，总是缺乏一点概念啊～

  2. 图形介面的设定比较好？
    好了，经过了授权模式的洗礼之后，再来进入到伺服器的设定方面，呵呵！这个部分可就容易的多了吧！没错， 确实是按几下滑鼠按钮就可以架设好一两个伺服器了。不过‘万一’该伺服器架设完成后， 并不符合您当初的要求时该怎么办？不会发生这样的事情吗？当然会发生啦！因为 Windows 为了达成所谓的‘亲和性与便利性’，所以在您的设定过程中他会‘很亲和的自动帮您加入某些参数’， 不过可惜的是，这些参数并不见得适合每个人，所以有时候您必需要自行修改这些设定值。偏偏 Windows 伺服器大部分的设定档都是一些特殊格式，您无法使用简易的文书编辑器去修改～

  3. 除错的登录档资料分析
    再者更遗憾的是，如果伺服器设定出了点小问题，总是无法达成您的要求，设定也都看过了， 那么要如何除错呢？如果您没有网路的基本概念，以及 Windows 相关的登录档案管理技巧，呵呵！即使 Windows 在设定上做了很多的简化，我想， 您依旧无法设定出适合您自己的伺服器的啦！
所以说，不管是 Windows 还是 Linux ，其实，要架设好一部堪称完美的伺服器，‘基本功课’还是得做的，这包括了：
  1. 该作业系统的简易操作，以及登录分析、帐号管理、文书编辑器的使用等等的技巧；
  2. 网路的基本概念；
  3. 防火墙方面的相关知识等等。
而且，每一个项目里面所需要学习的技巧可多着呢！‘什么？要学的东西那么多啊！’是啊！ 所以，不要以为资讯管理人员整天闲闲没事干的呐，大家可是天天在出卖知识的，同时， 还得天天应付随时可能会发生的各种漏洞与网路攻击手法呢！真不是人干的工作～～

这么说的话，架站真的是挺难的喔！事实上，架站其实蛮简单的哩！咦！～怎么又说架站简单了？ 不是说架站难吗？呵呵！其实‘架站很难’是由于朋友们学习的角度有点偏差的原因啦！ 还记得当初进入理工学院的时候，天天在念的东西是基础物理、基础化学、工程数学与流体力学等基础科目， 这些科目花了我们一至两学期的时间，而且内容还很难呐～都是一大堆的理论背不完。 怪了？我们进理工学院是为了求取更高深的知识，那么这些基础知识学了有什么用呐？ 呵呵！更高深的知识都是建构在这些基本科目的理论上面的，所以 万一您基础的科目没有读好，那么专业科目里面提到的基本理论怎么可能听的懂？

这样说应该就不难了解了吧！没错！认识作业系统与该作业系统的基本操作，还有那个重要的网路基础， 就是我们在架站前的‘基础科目’啦！所以说，在进入 Linux 的伺服器世界之前，真的不能够略过网路基础的相关知识，同时， Linux 系统的基本技能也必需要能够理解呐！

好了，或许您还是对于 Linux 系统里面‘什么是很重要的知识’不甚了解， 果真如此的话，那么我们就举个简单的例子来说明一下啰！底下列出一般的架站流程， 我们由架设伺服器的流程当中，来看一看什么是重要的 Linux 相关技能吧！ ^_^。
Tips:
在这一章当中，鸟哥不再就 linux 基础指令进行解析，因为在 ‘鸟哥的 Linux 私房菜 -- 基础学习篇’里面已经详细的介绍过了！ 如果持续的介绍指令，简直是浪费篇幅～所以底下仅介绍一个 Linux 基础学习重要性的分析喔！ 		鸟哥的图示
大标题的图示 基本架站流程：
虽然不同的 Server 提供的服务并不相同，而且每种服务的原理也不见得都一样， 不过，每种伺服器由规划、架设到后续的安全维护，其实整个流程是大同小异的。 所以，底下我们就整个伺服器的简易架设流程当中来分析一下， 为什么了解作业系统的基础对于网站维护是相当重要的呢？

首先，先来分析一下，如果你要架设一个网站时，架设的基础流程是怎样的一回事。大致的流程有点像底下这样：
  1. 了解网路基础 ：
    既然要架设网站，如果对于网站最基本的网路基础知识无法具备的话， 那么.....当然无法管理好网站啦！举个例子来说，不论何种作业系统， 常常会使用到所谓的‘网域’的概念，当您发现一个设定为 192.168.1.0/255.255.255.0 时，晓得那是什么鬼东西吗？ 如果不知道的话，呵呵！绝对无法设定好网站的啦！

  2. 了解架站的目的：
    想要架站，架什么站？架这个站后，要不要对 Internet 开放？要不要提供什么服务给其他外面 (指 Internet 上的用户) 的使用者？提供这些服务时，需不需要做限制 (例如限制使用者可以使用的硬碟空间或网页、邮件的最大容量)？ 如果要做限制时，需要怎么样选购您的主机硬体？要进行这些规划时，都需要知道架站的目的呢。 不过，如果架站只是为了‘练功’而已，呵呵！那就不需要考虑太多了～

  3. Linux 安装硬碟规划
    好了，不论您的网站规模有多大，只要是对 Internet 开放的网站，几乎一定都需要硬碟的啊！因为网站的资料需要有地方可以储存呐！ 那么您要如何选购硬碟？还有，硬碟应该进行怎样的分割 (Partition) 比较好？举个例子来说，如果您想要架设邮件主机，那么硬碟应该如何规划呢？给您猜～

  4. 了解欲架设的网站服务原理
    这个与刚刚第一点有点类似，也是属于基本原理方面啦！举个例子来说，当您晓得了 Mail Server 的运作原理，自然就比较容易架设成功，此外，也比较容易进行除错！

  5. 服务的套件安装、漏洞修补、套件升级...
    好不容易决定了硬碟的规划，并且 partition 与 Linux 这个作业系统都安装好了，接下来自然就是安装我们所想要架设的伺服器软体啦！例如：如果要架设 Mail Server ，那么 Sendmail 或者是 Postfix 这两个邮件伺服器软体就派上用场啦！咦！ 有两种邮件伺服器软体啊？呵呵！当然不止～邮件软体可多的很呢！那我要选择哪一个邮件伺服器软体？ 需要考虑安全性、架设的便利性、以及执行的效能与稳定性等等！呵呵！累了吧！

  6. 主机设定、启动、观察与除错
    在完成了 Linux 安装，并且将伺服器软体安装好了之后，再来当然就是设定啰！ 这个部分就是我们常常看到的一些文件说的比较多的部分啦！在主机的设定当中，其实设定项目并不难， 了不起都是照着文件设定就可以了！不过，由于每个人的主机环境不一样 (例如安装的套件版本啦, Linux distribution 的不同啦, 编译器的不同啦，这些都是主机环境的一环！)， 所以同样的一份设定在不同的机器上，嘿嘿，可能不会一定百分之百能执行的呐！ 这个时候，观察主机的登录档与相关的讯息，并加以进行错误克服 (debug) 的动作可就相当的重要了呢！这也是大家常常会忽略的部分。

  7. 用户端设定、观察与除错
    这部份也是需要的，因为有的伺服器需要用户端也进行设定才行！例如邮件主机加上身份认证功能时， 就需要在用户端上面设定好身份认证的确认啰！

  8. 安全性设定
    网路安全是很重要的，问题是，要怎么样达成网路安全的相关设定呢？ 有哪些档案、套件、指令与资料可以查寻？

  9. 服务日志、登录档与备份管理
    呵呵！毕竟没有人敢说‘我的网路是绝对安全的， 我的硬体是绝对没有问题的！’既然如此的话，备份就成了重要的课题了！ 问题是，如何备份呢？使用什么指令来备份？使用什么媒体来备份？需不需要手动来备份？ 还是交给系统自行每日、每周自动备份？这都是挺重要的！
整个伺服器的架设流程大概就如同上面所提的几个步骤啰！那么每个步骤底下与 Linux 系统基本操作有关的资料有哪些呢？我们就分项目来谈一谈吧！

小标题的图示 了解网路基础
既然是要架设网站，那么网站最基本的知识，就是那个 OSI 七层协定，至少就需要了解一下啰！虽然只是一个 OSI 七层协定，但这里面包含了：
  • 硬体与设备的等级与好坏：例如网路线有哪些等级？CAT 5 是目前常见的 RJ-45 接头的网路线等级，为什么要选择这种网路线？啊什么是 RJ-45 的接头？如果这个都不知道的话，那么要如何自己将所有的电脑接起来呢？ 呵呵！很难吧！所以，这种基本的硬体配备的选择需要有一定程度的认知喔；

  • TCP/IP 与封包的概念：例如 IP, Netmask, Broadcast 的概念与书写的格式等；

  • 路由 (route)：您的资料封包是如何传送到 Server 上的呢？资料在 Internet 上面是怎么跑的呢？！

  • 领域名称系统 (Domain Name System, DNS )： 常常会听到‘主机名称’吧！是否我自己设定一个主机名称，大家就可以通过 Internet 连接到我的主机了？当然不是！还需要透过上层 DNS 主机的授权喔！那么如何授权？

  • 各种网路设备的选择与搭配：例如什么是 Hub/Switch ？该如何选择？以及什么是下行/上行 2M/128Kbits ？什么是平行线与跳线等等；
还有我们最关心的，网路频宽到底是由哪一个设备所限制，以及在区域网路内的布线该如何配置。 哇！说起来好像很麻烦！其实只要稍微深入了解一下基本的原理，就可以约略的厘清您一些网路概念了。 这对于您未来架设防火墙以及维护网站，尤其是发生问题后的问题认定与除错，都有很大的关系呐！ 事实上，不论您是使用什么作业系统来架设您的网站，这个网路基础的部分都是一定要了解的！ 通常不了解网路基础的朋友，在架设网站的时候，最容易发生一些基础设定的错误了！ 所以，这部份的学习千万不能省略啊！

对于网路基础的问题当中，一个最常见的经典案例是： ‘192.168.1.0/24’是什么东西？呵呵！这东西代表的是一个‘网域’， 这个网域起始到结束的 IP 范围是多少您看得出来吗？这种表示方法在各种伺服器的架设中很常见到， 如果您不了解的话，呵呵！当然无法进行伺服器的架设啰 ( 注：各种作业系统均会出现这样的设定值喔 )。还有，如果您的主机明明就可以使用 ping 这个指令去接触远方的主机 (ping IP)，但是就是无法使用 ping hostname 去接触远方的主机，请问，这个原因是什么呢？了解网路基础的朋友一看就知道几乎是 DNS 出问题了，不晓得的朋友就是想破头也得不到答案～

其实这些概念说难不难，但是至少一定得需要学习过呐！ 而且，这些知识在您学会之后，未来再接触到其他不同的作业系统时，可让您学习的过程‘顺畅无比’呐！ 因为那是最最基本的理论，各个作业系统都是建构在这些网路基础上面，所以，当您换了另外一套作业系统后， 基本上只有指令的下达方式不一样而已，基本原理是一样的呐！所以说，学习的过程当然会顺畅到底啰！ ^_^。

而且，网路基础会影响到您的网路设定是否正确，这真的很重要呐，因为，如果您的网路不通， 那么即使伺服器架设成功了，别人可以看的到吗？所以说，要架站，真的得对网路基础的部分下一些功夫才行的。 关于网路基础这部份的介绍我们会在下一章网路基础时再详加说明喔！

小标题的图示 了解架站的目的
架站的目的与您的主机规划是一体两面的！因为我们必需要了解主机未来的用途与使用的用户端数目， 才能够开始选择硬体与分配网路频宽，并且规划我们的 Linux 系统啊！所以说，了解架站目的是很重要的！举几个例子来说好了：

  • 如果我们的主机是学校单位提供同学们邮件与 WWW 个人网页的功能，而全校有 5000 多位同学，那么硬体应该如何选择？还有，如果需要对每个同学进行网页空间与邮件容量的限制时， 硬碟又该如何分割？
    • 在这个例子当中，您必需要了解邮件与 WWW 个人网页的资料所放置的目录在哪里？而由于主机有进行硬碟的容量限制，因此， quota 的原理与设定的技巧就不能不知道啦！此外，既然是架站嘛！申请一个‘合法’的主机名称就显的相当的重要，另外， DNS 里面的 MX 标志对于邮件主机的用途也需要特别去了解呢！

  • 如果我们的主机仅提供研究室不到十个人的服务，且服务仅开放档案伺服器 (File Server) ，那么硬体又该如何选择，此外，是否需要注册一个合法的主机名称呢？
    • 因为仅开放档案伺服器，那么这部主机应该是在内部了，所以，当然就不是很需要一个合法的主机名称了！ 不过，因为仍然有对区域网路提供档案伺服器的功能，因此，硬碟的容量也不能太小，此外， 为避免未来使用者的抱怨，也需要预留空间来进行 quota 与增加硬碟等工作呢！

  • 如果我们的主机主要的目的是进行数值模式的运算 (就是有点像是超级电脑在算军事或者天文物理现象的模式)， 那么应该要考虑的是否反而就是在系统安全性与资料传输的速率上面？
    • 当然啦！这样的一个系统最主要的目的就在于‘稳定性’与‘速度’上面了！因此，您就需要了解 核心 (Kernel) 的编译技巧， 此外，由于不同的套件在设计最佳化的时候，通常都使用较为常见的 Linux distribution ，因此，对于 Linux distribution 的选择可又重要的多了呢！

    由上面的例子来看，不同功能的主机在硬体配备与软体规划上面是不一样的！所以，在进行 Linux 主机的规划之前，建议一定要了解这个主机的功能，甚至最好还能预设一些未来可能加入的功能规划呢！ 那我怎么知道我的主机要有什么样的功能？又什么样的功能可以满足我的需求呢？这当然是需要经验的！ 呵呵！这又得要回到刚刚前一个主题啰！至少需要了解到网路的基础， 这样就能够知道您应该架设什么样的网站啦！

    举个例子来说，如果您只是想要让 Linux 达成频宽分享而已，那么 Router 或者是 NAT 的设定即可满足你的需求， 万一您还需要了解每个使用者经常使用的网站，那么最好就是搭配 Proxy 以及分析软体来分析。然而 NAT 不需要很好的硬体配备即可达成，Proxy 如果要效能好一点，就必需要比较高档的硬体来搭配～咦！我怎么知道的？ 这当然是鸟哥已经较为熟悉每种服务所使用的硬体状态与他的服务原理啊。 所以啰！在主机的规划之前，务必要先了解主机的架设目的喔！

    那么这部份与 Linux 基础有何关系？！关系大了！
    1. 必需熟悉 Linux 的档案配置与架构：

      例如 /boot 放置的是开机核心资料、 /usr 放置的是预设的系统程式以及原始档与一些 man page 、/home 是一般身份用户的预设家目录所在、 /var 则是登录档、暂存档、 邮件信箱档案等放置的目录、/tmp 是任何人皆可使用的暂存目录等等，您必需要熟悉 Linux 各个目录的用途， 这样在未来进行硬碟的规划时，才能够符合需求！

      举例来说，因为磁碟配额 (Quota) 仅能针对整个 partition 来动作，而如果您想让每个使用者有两种 quota 数值 (例如每人拥有邮件 20MB 以及 WWW 10MB 的硬碟空间) ，就必需要预设针对 /home 与 /var/spool/mail 规划出两个独立的 partition 才行啊！当然啦，使用连结档 (link file) 也是一个可行的方案，不过， 您就得要预留一些硬碟空间来预备使用呐！

    2. 硬碟的代号：

      硬碟的代号真的是挺重要的，因为在 Linux 底下，每一个装置都以档案来表示的！ 因此，您必需要了解到硬碟与排线的接法对于硬碟在 Linux 系统中的代号的关系。例如：

         Master | Slave
      IDE 1 | /dev/hda | /dev/hdb
      IDE 2 | /dev/hdc | /dev/hdd

      上面的磁碟代号只与 IDE 介面的装置有关，什么是 IDE 介面啊！就是目前所谓的 Ultra DMA 66/100/133 的硬碟啊，或者是光碟机与烧录机，这些装置均可直接以主机板上面的 IDE 排线接在一起说。还有，目前主流的硬碟已经变成 SATA 介面了，这种 SATA 介面可以模拟成为 IDE 介面，因此，您的 IDE 装置还可能具有 /dev/hde, /dev/hdf 等等呢！ 若是使用 SATA 介面的话，那么该硬碟的代号就可能变成 /dev/sda 之类的档名。

      不过，万一您使用的不是 IDE 装置呢？例如 SCSI 介面的硬碟！那么就得由 /dev/sda 开始算起了！同时，目前很常见的 USB 介面的随身碟或者是 USB 的外接式硬碟，他的代号也是 /dev/sda 开始算起喔！除了这些基本概念外，在硬碟的 partition (分割) 部分，例如第一个 IDE 插槽的硬碟分割成为五个分割槽，此时，您必需要了解什么是 Primary 与 Extended 及 Logical 等磁碟分割槽的概念才行！必需清楚的知道一个硬碟最多只能有一个 Extended ，而 Primary + Extended 最多只能有四个！至于 Logical 则是由 Extended 再分割出来的。

      每一颗硬碟分割出来的 partition 代号为 /dev/hd[a-d][1-63] ，亦即原本的硬碟代号后面加上一组数字就是了。 举例来说， IDE1 的 Master 的第一个 partition 即是： /dev/hda1 ， 由于 1-4 号是保留给 Primary 与 Extended 分割槽的，因此，第一个由 Extended 分割出来的 Logical 代号则为 /dev/hda5 (注意：这里举例的是第一个 IDE 的 Master 硬碟接法)。这些部分在‘鸟哥的 Linux 私房菜 -- 基础学习篇’ 有详细的说明，如果您还是不了解，可得赶紧回去翻一翻啊！因为这很重要的！
    还不止此呐，上面这些动作的判断尚包含了： Linux 系统档案的树状目录、 档案所在目录的搜寻方法、 磁碟配额 (Quota) 的设定、 文书编辑器 vi 的使用、 核心的编译技巧、 硬碟的安装与维护等等，所以啰， 基础的文件还是需要阅读过的呐！

    小标题的图示 Linux 安装硬碟规划
    OK！了解了架站目的，也知道硬体应该是如何搭配之后，接下来，自然就是安装 Linux distribution 了！到底选择哪一套 distribution 好呢？是 Fedora/SuSE/Mandriva 还是.....这个时候您就需要清楚的了解到 Linux 其实就是一个‘Kernel’啰！而目前 (2007/01) 的 Kernel 最常用的就是 2.6 这个版本，如果您使用较旧的 Linux distribution 例如 Red Hat 9 时，那么 Kernel 版本是较为早期的 2.4 版，这个时候，在新版的 2.6 核心上面开发出来的各种类软体就无法在 Red Hat 9 的系统上面动作了， 而且，不同核心的函式库也不相同啊！ 所以说，选择 Linux distribution 时，需要知道该 distribution 的核心版本才好。

    一般来说，我们会建议大家不要使用太冷门的 distribution ，因为，支援度可能会比较不够好！所以，目前较为推荐的还是台湾地区比较多人使用的 Red Hat 系统 (Red Hat/Fedora/CentOS 均是 Red Hat 系统)，以及操作介面良好的 SuSE ， 还有 Mandriva 也不错啊！

    选择了 distribution 后，当然要开始安装了！安装的第一个要件就是刚刚上个步骤的规划， 因为上面提过了，所以这里我们就不再谈规划的工作了。规划完成之后，再来就是整个安装的流程了。 安装流程最重要的大概有三个地方：
    1. 硬碟的 partition 与挂载：

      除了硬碟的代号需要特别留意之外，当然磁碟分割也不能不清楚啊！磁碟分割方面，需要学习的有 fdisk 这个重要的分割程式。 在分割完成之后，接下来就需要格式化硬碟啦！格式化就需要了解 mke2fs 这个指令的用法了！ 再来，格式化完成后，就需要与挂载点 (目录咯！) 搭配来挂载！挂载使用的指令为 mount。 而挂载前，想要检查一下该 partition 有没有问题，就需要使用 fsck 来检测，另外，记得啊！使用 fsck 时，要被检查的 partition 请务必给他卸载啊 (使用 umount)。

      还有还有，如果要让某些 partition 在开机的时候就自动挂载，要记得写入 /etc/fstab 当中，或者是将指令完整的写到 /etc/rc.d/rc.local 当中。哇！这么多指令怎么看的懂？呵呵！这时又得要知道 man 这个好用的指令的！ 这部份硬碟的管理真的很重要的！不要忽略了！

    2. 套件的选择与安装：

      好了，将硬碟整理好之后，终于要将 Linux 安装上来了！这个时候请特别留意，因为 Linux 提供了图形介面与文字介面的预设登入 (run level)， 事实上，图形介面挺容易造成系统的资源损耗，因此伺服器上面较少使用图形介面喔！ 所以，通常鸟哥都是不安装图形介面的套件的啦！再来，为了未来的升级与重新安装套件的便利性， 所以，在选择套件时，请务必将底下几个套件选择进来：

      • make
      • gcc
      • kernel-source 及 (或) kernel-header 及 (或) kernel-devel

      因为 make 与 gcc 是编译套件所必需要的软体，至于 kernel-devel 则是一些驱动程式在编译时会使用到的一些函式库或系统资料， 这些东西对于桌上型电脑并不很重要，因此在各大 distribution 的预设套件上面‘都没有安装’， 所以，您需要自行挑选啊！这些套件通常都会放在 Software develop 或者 Utility 的项目当中，请仔细的选择喔！

    3. 开机的设定 ( Grub/Lilo ) ：

      在我们进入系统之前，主机会先读取 BIOS 的资讯，然后会读取第一块硬碟的主要开机磁区 (Master Boot Recorder, MBR)，这个动作是为了让我们的主机了解资料格式， 以顺利的将系统的资料读取进来啊！而在这个 MBR 上面的程式，就被称为开机管理程式了！在 Linux 上面主要的开机管理程式有 Grub 与 Lilo 这两支，他们的运作方式有点不太相同！ LILO 是直接将所有的资讯都给他写入 MBR 里面，所以如果您设定完成设定档 /etc/lilo.conf 之后，还得将 LILO 重新安装到 MBR 当中。至于 Grub 则是使用类似指向 (point) 的功能，将开机资讯导向设定档 /boot/grub/menu.lst 当中！ 这两个管理程式各有优缺点，可依照个人喜好来选择安装。

      另外，其实我们的主机是可以达成所谓的‘多重开机’的系统的！也就是一部主机上面可以有多个作业系统，包括 Windows 与多个 Linux 。如果要达成多个系统在同一部主机上面的话，您又得要必须了解 MBR 与 Super Block 的异同点才行！这都是需要学习的呢！
    真的很不容易喔！安装一部好的 Linux 主机，最大的重点就在于硬碟的 partition 了！硬碟分割的考量会影响到您的主机未来的扩充性与实用性，还有‘安全性！’呢！所有的种种都需要有一定程度的 Linux 概念才行呐！

    小标题的图示 了解欲架设的网站服务原理
    事实上，了解每种服务的运作原理，对于您未来在进行除错 (debug) 是相当的有用的啊！而且，在主机的规划上面也会有一定程度的帮助。举例来说好了，在 Linux 上面很有名气的档案伺服器 SAMBA ，他的运作原理主要是 NetBIOS over TCP/IP ，而如果您了解最原始的 NetBIOS 是无法跨网域的，亦即无法跨路由器 (Router) 的，那么就比较容易了解为何 Windows 的网路上的芳邻显示的电脑数量只有区域网路内部这么多而已！

    另外，如果您熟悉 FTP 的运作模式时，才有可能会了解‘被动式’与‘主动式’连线对于 FTP 主机的设定其实是‘大有关系’的！或许在这里您完全不晓得鸟哥在谈些什么 (因为这些基础知识在后续的章节才会陆续的提及啊！这里还没有讲到啦！) ，只不过，请大家先有个概念，理解服务 (Services) 的运作流程，将有助于您未来的架设与维护喔！所以，这一部份也不要忽略了！

    这还只是各个伺服器的服务原理呢！如果是在 Linux 上面运作呢？那么您至少就得要了解‘什么是 daemon ？’而 daemons 的形式有所谓的 stand alone 以及 super daemon 的管理！这两种形式有什么差别？每种 daemon 管控的 port number 是否相同？如果需要更改 daemon 的 port number ，应该要改 /etc/services 这个档案，您是否了解如何去修改？还有还有，除了伺服器才需要的 daemon 之外，其实我们 Linux 主机里面本来就有很多 daemon 存在，例如几乎一定要存在的 crond, syslogd, atd 等等，这都是需要了解的基本知识！

    小标题的图示 服务的套件安装、 漏洞修补、套件升级...
    好了，假设您已经将网路硬体配置搞定了，主机也规划好了，并且也已经可以连上 Internet 了，此外，也已经知道了该伺服器的服务原理，那么再来当然就是：‘ 我的主机上面是否有我要架设的伺服器软体了？’举个例子， 如果我问你，你的 Linux 主机上面有没有 Apache 这个 WWW 伺服器的软体呢？聪明的管理员大概已经想到了使用 RPM 来寻找，而如果不是使用 RPM 来管理软体的系统管理员，也会立刻想到 locate, find, which 等等的指令来搜寻相关的档案或指令，例如 Apache 的主要设定档是 httpd.conf ，那么只要找到该档案，就能够了解是否已经安装了这个套件～因此，立刻使用 locate httpd.conf 即可发现啦！

    好了，假设您的主机并没有安装 Apache 这个套件，那么您要如何安装呢？ 这个时候就需要考虑到‘套件管理员’这咚咚了！目前 Linux 上面的套件管理员大多使用 RPM 与 Tarball 这两个咚咚！使用 RPM 最大的优点是方便管理！因为所有的档案与资讯都有纪录，所以在搜寻、升级、反安装上面都相当的容易！ 不过，却也因为相依属性的问题常常导致新手无法立刻进入状况！此外，RPM 有版本方面的问题，不同的 Linux distribution 上面的 RPM 还不能互相挪用呐！呵呵！真是苦恼～

    如果您对于 RPM 的相依属性有相当大的反感程度，那么使用原始码 (source code) 来进行编译则是一个不错的思考方向。在系统上面能够执行的档案属于 Binary (二进位档) ，那么这些 binary 是怎么来的呢？！我们以 Linux 常见的 binary 制作方法：使用 gcc 来编译的动作来说明好了。要制作 binary file 之前，首先就必须要撰写程式码，这些程式码大多是以文书编辑器编辑而成的 ASCII 格式档案，这就是通称的‘Source code’咯。然后这些程式码必需要经过编译器 (compiler) 编译成为我们的系统认识的 binary 可执行档才行！在编译的过程中，可能还会使用到很多的函式库 (library) 呢！需要注意的是，目前 linux 上常见的编译器就有 gcc, g77 等，您的原始码必须要针对这些编译器的语法进行撰写才行！

    一般来说，当套件释出时，大多采用原始码的方式释出的，但是因为原始码所占用的档案空间比较大， 因此常常会加以压缩之后，才放上网站上供人下载，那就是所谓的 Tarball 了！因此，您必须要了解 tar, gzip, bzip, compress 等指令的用法才能够解开 Tarball 的档案！此外，由于 Tarball 是原始码，因此您还必须要有 compiler 以及相关的 make 与 Kernel 相关的函式库，才能够成功的将这个套件给他编译成为可以在您的系统上面跑的 binary file ！使用 Tarball 的安装方式，最大的优点是具有弹性！ 您可以将套件安装在任何您想安装的目录，还可以自行加入一些额外的参数来设定该套件呢！ 不过，还是有缺点的啦！那就是当平台不一样时，可能由于某些函式库无法找到， 或者是使用者的基本知识不足，就无法成功的将 Tarball 编译成功！另外，用 Tarball 安装时，某些特殊的套件很难进行反安装的动作呐！ 造成升级与移除上的困扰！

    反正 RPM 与 Tarball 是各有优缺点啦，鸟哥个人比较偏向于使用系统预设的 RPM 来进行伺服器的设定，不过，由于并非每个 Linux distributions 都适合某个套件的 RPM 参数，所以，这个时候我就会开始考虑使用 Tarball 了！无论如何， 既然您要架设伺服器，就必须要有该伺服器的套件在您的系统上面，那么学习上面这两个套件管理员，是必要的动作！

  • 漏洞修补的重要性：
    • 很多的新手在架设好了伺服器之后， 就以为‘万事 OK ’了！ 所以就不再继续的监视网路上面公布的套件漏洞资讯！事实上这是很危险的！因为目前由于 Internet 的发达，网路的危险性其实是越来越严重的！稍一不小心，您的主机可能就会立刻的‘中标’。 为了随时修补漏洞，您应该要熟悉如何进行套件的升级！一般来说，使用 RPM 安装的套件就以 RPM 的方式来升级，使用 Tarball 的话，比较麻烦， 需要先移除后再进行升级！无论如何，套件的升级是系统管理员经常要进行的工作！

    目前各大版本的 Linux distributions 都有释出线上自动更新的机制，包括 Red Hat 的 up2date, CentOS/Fedora 的 yum, SuSE 的 YOU，以及 Debian 的 APT 等等，都值得您花时间去学习的， 因为可以让您的主机变的更加的安全喔！
    Tips:
    程式设计师所撰写的程式并非十全十美的，所以，总是可能有些地方没有设计好， 因此就造成所谓的‘程式漏洞’啰。程式漏洞所造成的问题有大有小， 小问题可能是造成主机的当机，大问题则可能造成主机的机密资料外流， 或者主机的操控权被 cracker 取得。在现今网路发达的年代， 程式的漏洞问题是造成主机被攻击、入侵的最主要因素之一了。 因此，快速、有效的针对程式漏洞进行修补，是一个很重要的维护课题。     		鸟哥的图示
    小标题的图示 主机设定、启动、观察与除错
    在所有的前置作业都完成之后，终于可以来到‘主机设定’的地方了！ 所以您看看，要设定一部堪称完美的主机，前置作业就得学会这么多的基础功夫呐！ 并不简单喔！好好的用功学习吧！主机的设定大致的流程是这样的：
    1. 找出设定档：

      主机设定第一个步骤就是需要‘找到主要设定档’，因为不论您使用的是 RPM 还是 Tarball， 由于都是同一个套件，所以设定档的档名是不变的！举例来说， Apache 的设定档档名都是 httpd.conf ，而 SAMBA 的设定档档名都是 smb.conf ，您必须找到该设定档之后才能够进行设定啊！所以，熟悉 locate, rpm, find, grep 等指令就显的很重要了！

    2. 编辑设定档：

      既然要设定，当然就需要编辑啦！既然要编辑，那么 Unix Like 标准的文书处理器 vi 是否学会了呢？ vi 是学 Linux 过程中相当重要的一课！如果不会 vi ，那么学习 Linux 之路就会显的跌跌撞撞呢！此外，设定档的内容该如何编辑呢？例如 httpd.conf 里面有些虚拟主机的设定项目，要如何设定呐？！要了解这里面的设定项目，您就必须要学会使用 man, info 等指令，也需要知道套件的文件资料 (documentation) 放置在我们系统的 /usr/share/doc 里面说！如果您知道如何快速的查阅设定项目，那么设定档的编辑对您而言， 就简单的很呐！

    3. 启动伺服器：

      设定完成伺服器的设定档之后，再来就是需要启动伺服器啦！ 而且，如果您在伺服器启动之后进行设定档的修改，也需要重新启动伺服器才行喔！ 要启动伺服器，您就必须要了解什么是 daemons ，而 daemons 又有 super daemon, stand alone 两种模式，在 Linux 预设的路径当中， stand alone 的服务在 /etc/init.d/* 这个目录当中，而里面的档案是以 BASH shell script 写成的，所以除了了解 daemon 之外，您还必须要熟悉 shell script 的相关语法才行！另外，如果是 super daemon 的话，必须知道启动伺服器的设定档会放置 /etc/xinetd.d 里面，启动的话，则是重新启动 /etc/init.d/xinetd 这个 super daemon 才行！

      万一您的伺服器软体是以 Tarball 安装的，那么启动的时候可能是直接执行 binary file ，如此一来，就没有 shell script 帮助您启动、关闭、 重新读取设定档等伺服器启动的动作！当真如此的话，您就必须要以 程序 (process) 与讯号 (signal) 的方法使伺服器动作了！这部份您就必须要熟悉 ps, top, kill 以及 signal number 的意义等等！很重要的呐，尤其是当您想要将目前某个连线中断时， netstat 配合 kill 的用法是很重要的。

    4. 观察启动的状态：

      虽然似乎已经启动了伺服器，但是启动后的伺服器就一定能够正常的运作吗？ 如何观察他是否正常的运作呢！？首先，您就必须要具有 PID 的概念，利用 netstat 观察 PID 与 port number 的讯息，来观察伺服器是否正确的在工作呢？！还有，任何系统资讯都会 记录到登录档 (log files) 里面去，所以，启动完伺服器后，到该伺服器的登录档当中察看一下资讯，是相当正确的一个行为！例如启动 DNS 之后，虽然观察 port 确定有启动，但是其实伺服器可能是不正常的启动，此时就必须要观察 /var/log/messages 的内容来判定 DNS 的设定是否正确说～ 而既然要观察登录档，那么 linux 主机上面控制登录档的 syslogd 这个 daemon 就不能不知道啊！您必须要了解 syslogd 的设定档在 /etc/syslog.conf ，并且可以搭配 logrotate 来进行登录档的轮替！

    5. Server 与 Client 的权限问题：

      好了，伺服器已经正常的启动了！观察所有的状态也都没有问题！那么我总可以对 Client 进行正确的服务了吧？‘错！’您还尚未考虑到‘权限’的概念呐！举个例子来说，架设过 WWW 主机的朋友大概都知道如果需要开放个人家目录的首页时，将该使用者的家目录设定权限为 755 是必须的！因为如此一来，启动 Apache 程序 owner 才能够进入该目录进行浏览的动作！ 为了要了解权限的概念，您必须至少具有 UID, GID 等 Linux 系统上面的帐号概念， 而每个帐号的特殊参数在 /etc/passwd 与 /etc/shadow 也是必须要知道的！此外，每个档案或目录具有十个属性的特征也是最基础的观念， 真的重要呐这一部分！而如果要让使用者管理系统的话，身份转换成为系统管理员 (root) 也是必须的！如此您就必须要教育使用者了解 su 及 sudo 的用法！再来，为了预防系统被破坏，适时的减少 SUID 与 SGID 等特殊权限的 binary file 则显的相当的重要！咦！这些东西都不懂～那....不要架站喔！ ^_^

    6. 设定开机启动该伺服器：

      终于将伺服器设定好，启动正确，对于 Client 端的权限与服务也设定妥当， 再来就是要进行一开机就将伺服器载入记忆体的动作了。如何进行这个动作呢？在 Red Hat/SuSE/Mandriva 有 chkconfig 可以辅助， Red Hat 更有 ntsysv 可以达成简单的设定！然而，如果是其他的 Linux distributions 呢？那么就得了解正常的开关机程序，这里面包含了 Run Level 的观念，Run Level 的读取档案在 /etc/inittab 里头呢！还得要了解 /etc/rc.d/ 里面的目录与 /etc/rc.d/rc.local 这个档案的用途才行！一般来说，我们使用 Tarball 的套件想要在开机时就启动，都会藉由 /etc/rc.d/rc.local 这个档案来达成！呵呵！很重要吧！
    经过上面的流程，您就可以知道啦，架设好一部主机需要知道：(1)各个 process 与 signal 的观念；(2)帐号与群组的观念与相关性；(3)档案与目录的权限，这当然包含与帐号相关的特性； (4)套件管理员的学习；(5)BASH 的语法与 shell scripts 的语法，还有那个很重要的 vi 啰！：(6)开机的流程分析，以及记录登录档的设定与分析；(7)还得知道类似 quota 以及连结档等等的概念。要知道的真的很多，而且还是不能省略的步骤喔！

    小标题的图示 用户端设定、观察与除错
    一般来说，目前的伺服器大多只要针对 Server 设定好即可， Client 端我们不太需要去管理的。不过，某些特殊的套件，例如 SSH, Mail, SAMBA, NAT 等等，就必须要连同 client 的权限与设定一起包含进去设定呢！ 如果您是一个系统管理员的话，那么‘教育 Client 端的使用者，正确的使用网路与主机提供的服务’就是一个相当重要的工作了！

    最常发生的错误在于 Client 端架设了‘个人防火墙’，这部份相当的恼人～那我怎么知道 Client 端的服务要求被防火墙给他中断呢？这当然可以由 Server 以 netstat 来简略的检查，当然，到 Client 端视查一下使用者的使用习性与作业系统，也是一个可行的方案。不过，总体来说， 教育您的 Client 使用者具有最最基础的 Linux 帐号、群组、档案权限等概念，才是一个彻底解决问题的方法说！尤其是 Client 端的使用者在使用类似 SAMBA (网路芳邻) 进行资料存取时，最容易发生权限观念这样的错误了！

    总之，系统管理员对于 Client 端的使用者还是有一定程度的责任与义务的，至少我们要进行好教育的任务！

    小标题的图示 安全性设定
    前面说过，网路的安全有越来越需要注意的趋势。所以，架设一个相对安全的网站是很重要的！ 那么如何架设好一个相对安全的网站呢？您至少需要有这样的概念：
    1. 严格规范使用者的密码设定规则：
      ‘猜密码’仍是一个不可忽视的入侵手段！例如 SSH 如果对 Internet 开放的话，您又没有将 root 的登入权限关闭，那么对方将可能以 root 尝试登入您的 Linux 主机， 这个时候对方最重要的步骤就是猜出您 root 的密码了！如果您 root 的密码设定成‘1234567’哈哈！想不被入侵都很难～ 所以当然需要严格的规范使用者密码的设定了！那么如何规范严格的密码规则呢？可以藉由 (1)修改 /etc/login.defs 档案里面的规则，以让使用者需要每半年更改一次密码，且密码长度需要长于 8 个字元呢！(2)利用 /etc/security/limits.conf 来规范每个使用者的相关权限，让您的 Linux 可以较为安全一点点～(3)利用 pam 模组来额外的进行密码的验证工作。

    2. 利用 Super daemon 与 TCP Wrappers 管理服务权限：
      如果您使用 xinetd 这个 super daemon ，或者是直接使用 tcp wrappers 的函式库，那么您将可以直接使用 /etc/hosts.allow 以及 /etc/hosts.deny 来管理是否能够登入系统的某个 daemon 的权限！在 hosts.allow(deny) 里面，能够限制的有 IP, 网段, 网域等等的设定，如此一来，可以让您的 daemon 提供有限的信任网域，毕竟是安全一些的！

    3. 利用 netfilter 防火墙：
      除了 /etc/hosts.allow(deny) 之外，利用防火墙机制 iptables 来设定您的主机单机防火墙是很重要的！ 如果您的核心是 2.4.xx 以上版本(包含 2.6)的话(利用 uname 查询核心版本)，防火墙机制为 iptables ，如果是 2.2.xx 的话，则是使用 ipchains 。如果不是因为特殊需求的话，目前我们大概都会建议大家使用 iptables 这个机制，因为不但设定较为简单，而且功能更为强大！

    4. 持续进行套件修补：
      让我们做一个简单的想法：‘架设了防火墙，是否就安全无虞了’？ 如果您的答案为‘是’，那么仔细的观察一下底下的说法吧！如果您的主机有开放 WWW 也就是 port 80 ，既然要开放 port 80 ，当然防火墙就必须要开放 Client 登入。也就是说，虽然您架设了防火墙，可以抵挡非 port 80 以外的连线，不过， 不论来自何方的连线，只要连接到您的 port 80 ，那么该连线就会予以通过！好啦，万一这个 www 软体被侦测出有漏洞的话，由于您的 port 80 是允许大家登入的，结果呢？呵呵！当然别人就可以利用 WWW 的漏洞成功的入侵您的主机了！这样说可以理解为什么系统管理员需要常常更新套件以修补漏洞了吧？ ^_^
    无论如何，以现今的网路功能及维护来看， 架设一个‘功能性强’的主机，还不如架设一个‘稳定且安全的主机’比较好一点！ 因此，对于主机的安全要求就需要严格的要求啦！就鸟哥的观点来看， 如果您的主机是用来替你赚钱的，例如某些研究单位的大型 Cluster 运算主机，那么即使架设一个甚至让您觉得很不方便的防火墙系统，都是合理的手段！ 因为主机被入侵就算了，若资料被窃取，呵呵！那可不是闹着玩的！

    小标题的图示 服务日志、登录档与备份管理
    除了安全性之外，主机也可能因为硬体问题或者是人为使用不当而产生错误讯息等问题！这些讯息会放置在 /var/log 里面，不过，还是得视 syslogd 这个 daemon 的设定档 /etc/syslog.conf 的设定而定喔！这些登录档的资讯是相当重要的，他可以记录曾经发生过的事情， 如果再经由系统管理员自行写的分析软体，那么就可以很轻松的管理好主机了！ 也可以在最短的时间内发现主机的可能漏洞呢！不可说不重要啊！

    我们常常说主机的服务越单纯越好，原因是什么呢？如果哪一天我们发现主机的登录档有点问题， 要来进行入侵管道的查询，万一主机的服务过多，很难追查出到底是哪一个 daemon 造成主机的问题啊！如果主机的服务很单纯，分析登录档也会比较轻松呢！ 此外，系统管理员最好有制作工作日志的习惯，可以让您未来管理主机比较容易快速的进入状况！ 总之，要良好的管理主机，利用主机的工作排程(crontab)也是很重要的喔！

    当然啦，主机随时的给他备份是一个很良好的行为，要怎么备份呢？ 您必须要了解主机的相关资讯，例如邮件主机，您可能就得备份 /etc 与 /home 及 /var/spool/mail 等目录，而如果是 WWW 主机，就得找到 WWW 主页的目录，才能进行备份呐！要用什么工具呢？可以选择 tar 或者是 cpio 等工具，当然，您还得配合备份的媒体，例如抽取式硬碟啊、可烧录光碟啊等等的媒体说！

    小标题的图示 小结语
    由上面的整个架站流程来看，由规划到安装、主机设定、帐号与档案权限管理、 后续安全性维护与管理以及重要的备份工作等等，必需要每个环节都很清楚， 才能够设定出一个较为稳定而可正常工作的伺服器。而上面的每一个工作都涉及到相当多的 Linux 基础操作与相关的概念，所以说， 想要学架站，真的真的不能省略了 Linux 的基础学习， 这也是为什么我们一再强调 Linux 新手不要一头栽入想要单纯架设伺服器的迷思当中呐！ 如果您对于上面谈到的几个基础概念不是很清楚的话，那么建议您由底下的两个网站学起：
    • http://www.study-area.org
    • http://linux.vbird.org
    在这一本书当中，鸟哥并没有再花篇幅再继续介绍一些 Linux 的基础指令以及相关的设定， 这一本书本来就定位在已经具有 Linux 知识的朋友的工具书，所以，对于尚未接触过 Linux 的朋友来说，这部份其实并不适合您！建议您还是得要重头学起呐！若想要一本 Linux 基础知识的工具书在手边，也可以考虑鸟哥前一本著作 ‘鸟哥的 Linux 私房菜 -- 基础学习篇’喔！ (好像有点老王卖瓜了喔！ ^_^ )大家加油的啦！
    大标题的图示 自我评估是否已经具有架站的能力
    由前一节的内容介绍中，不难知道要架设一个堪称完美的网站， 得事前花诺大的心力来培养您自己的‘能力’才行！说实在的，架站实在不能贪图‘便利’， 因为越是‘便利自己’就越是‘便利 Cracker 的入侵’啊！此外，上面谈到的都属于技术层面的部分喔！ 要有架站的能力，不只有‘技术’就可以了喔！还需要其他心理层面的辅助呢！ @_@ 咦！搞什么～架站还需要心理层面的因素？我们是在玩心理战是吧？！

    这里要请您特别注意的一点是，如果您架了一个网站，一般来说，您自然就是系统管理员 (root) 的身份了。而要晓得的是，在 Linux 系统当中， root 具有‘至高无上’的权力， 他可以进行任何系统的设定，也可以察看任何使用者的档案或邮件或什么机密文件等等的， 还可以让使用者寄出、寄入的邮件都送一份到自己的信箱去！所以，如果身为 root ，还拥有‘极高度的偷窥欲望’时，那么您的 user 岂不是毫无秘密可言？换个角度来想，如果您是一般的 user ，而您的 root 却拥有很高的偷窥欲，我想，您应该也不见得会有多快乐吧？ 就好像在家里被人家装了针孔式摄影机一样，感觉绝对不可能太好！所以，要成为 root 之前，您必须做好心理建设，那就是拥有相当高水准的‘道德感’。

    一般来说，网管人员需要什么能力呢？我想， 架几个站跟作一个称职的网管人员，相差是甚远的！架站，说真的，是一件很简单的事情， 看著书本一步一步的作上去，一定可以成功的！但是，很多人都只晓得 ‘如何架站’却不知到 ‘如何维护一个网站的安全’！基本上， 维护一个已经架设好的网站的正常运作，真的要比架设一个网站难的多了！您得要随时知道您的系统状况， 随时注意是否有新的套件漏洞而去修补他，随时要注意各种服务的登录档案(logfile)以了解系统的运作情况！ 得知道发生问题的时候，到底问题点是在哪一个！比如说当机了，那么您知道当机的原因吗？ 即使不知道，也可得需要约略猜得出来才行。而，如果安全出了问题，被入侵了，除了 format + 重灌之外，可有办法在不移除系统的情况下修补漏洞？ 这些都是网管人员需要学习的，而且，通常都是需要经验的累积才会知道问题的所在！ 此外，保持身心的活力以随时注意线上公布的安全防备资讯等等！都需要具备的！

    此外，最严重的问题是，网管人员其实最需要的是 ‘道德感与责任感’！您可要晓得您的机器上所有人的隐私都在您的监控之下， 如果您本身就已经有偷窥欲了，可知道这有多可怕吗？另外，如果没有责任感的人作为一个网管， 可能会疯掉，因为不论何时何地，只要是你监控的主机出了问题，嘿嘿嘿嘿，你一定是第一个被想到的人物， 所以，你得随时随地做好可能随时会被召唤回主机跟前的心理准备！更可笑的是，如果你服务的人群中， 有几个连开机的时候软碟机塞了一块不可开机的软碟，导致无法正常开机， 也都会跟你抱怨说‘唉呦！您经手的电脑怎么这么烂，动不动就不能开机’的时候， 您得要有容人的雅量，说说冷笑话解解闷吧！总之，网管人员并不是只要会架站就可以了， ‘道德感’‘责任感’还有‘耐心’呵呵！套一句现在人喜欢说的口头禅‘这是一定要的啦！’

    那么网管人员是什么？ 前一阵子看到了报纸的一篇报导， 内容大概是说：台湾的网路管理人员对于‘网路安全性防护’的认知不够，或许是防火墙机制建立不完整， 或者是认为骇客不会入侵小型网站，所以在不甚了解的情况下，被所谓的‘中东骇客组织’所入侵， 然后以台湾被入侵的电脑为跳板，去攻击宾拉登的仇敌美国，然后引起美国高度的不满。由于台湾的立场有点得罪不得美国 ( 这边不提及政治因素，反正目前的情况是这样。 ) ，所以一接到美国来的抗议信函就很棘手。 这只是一个事件问题，不过这个事件问题也点出了一个重点，就是我们的网路资讯可能真的是蛮发达的， 不过，管理网路的人员可能在认知的程度上就有点参差不齐了！网路安全是蛮重要的，只是， 大家常常会忘记他！个人认为，网管是蛮重要的角色，应该不能等闲视之才对。

    好了，如果您了解了上面小弟所想要表达的意念之后，来评估看看您是否适合当一个称职的网管人员吧！
    1. 是否具有 Linux 的基础概念：
      这当然包含很多部分，例如帐号管理、BASH、权限的概念、Process 与 signal 的概念、简易的硬体与 Linux 相关性 (如 mount)的认识、登录档案的解析、daemon 的认识等等，都需要有一定程度的了解；

    2. 是否具备基础网路知识：
      没有网路知识想要架站，那是天方夜谭！请确认您已经熟悉 IP, Netmask, route, DNS, daemon 与 port, TCP 封包的概念等基本知识；

    3. 是否已经身心活化了：
      网管人员必须要随时注意网站的相关资讯，这包括网站套件的漏洞修补、 网路上公告的网路安全通报等等，还有，得要每日分析主机的登录档， 您是否已经具备了随时注意这些资讯的‘耐心’呢？

    4. 是否具有道德感与责任感：
      如果还是具有一点点的偷窥欲，再加油吧！^_^ ，另外，如果老板想要请您‘偷窥’时，请想尽任何方法，让他理解这么做是多么的可笑～
    当然，一再强调的，架设一个 Linux 伺服器是很简单的，但是维护的工作除了身心已经活化， 并且还要拥有高标准的道德感，否则.....倒站可能是可以预见的一个后果.....

    大标题的图示 课后练习：
    • 请简述进行网站架设前，应该具备何种基本技能？
      1. Linux 系统操作上，至少需要了解帐号管理、档案属性与权限、程序与资源管理、 硬体如硬碟之挂载与软体套件之安装如RPM套件管理员等等，而 vi 与 Shell 亦是不可忽略之基本技能，更重要者，日志的管理以及系统服务的原理(如 stand alone 与 super deamon 服务启动的方式差异等)亦需同时厘清，以方便未来架设网站时除错的技巧；
      2. 在网路的基础知识上，TCP/IP 的观念以及路由的概念相当的重要，此外，DNS 的概念也很重要。
      3. 在心态的调整上面，系统管理员需要的道德感以及使命感需要较高的标准。
    • 如果我有一颗硬碟在 A 主机上面安装了 Linux 之后，拿到另一台配备相同的 B 主机上面去进行开机，结果竟然无法顺利开机，您认为可能的原因是什么？
      • 由于配备相同，所以排除硬体的问题，不过，考虑到 IDE 排线与 partition 的代号，以及 /etc/fstab 的对应，所以应该是由于 IDE 插槽放置错误所致(Linux 系统下，每个 IDE 插槽对应的 partition 名称皆不相同喔！)。此外， 上次不正常关机也可能造成硬碟损害而无法开机成功！
    • 一般来说，在 Linux 系统上，使用者预设的家目录在那个目录下？另外，新增一个使用者时， 该使用者预设的家目录内容来自那个目录下？
      • 在 /etc/default/useradd 这个档案里面会规范使用者的预设家目录以及预设家目录的内容，一般来说，使用者预设家目录在 /home ，至于家目录内的档案则复制来源在 /etc/skel 里面。
    • 磁碟配额 ( quota ) 能否针对某个特定的目录进行限制？Quota 有什么较为特殊的使用限制？
      • Quota 目前仅能针对整个 partition 进行限额配置，如果该特定目录是一个 partition 那就可以进行 quota 设定，否则无法针对特定目录！此外， Quota 除了特定目录以及需要 ext2, ext3 等磁碟格式才支援之外，也需要核心的支援喔！
    • 在 Linux 系统下，要寻找一个档名为 vbird.document 的档案，可以使用什么指令进行搜寻？ 又，如果要寻找在一天内更动过的档案，又该如何进行？
      • 如果是执行档可以使用 which command 来搜寻，如果是档案，就必须要使用 locate vbird.document 或 whereis vbird.document 或 find / -name vbird.document 。如果要找到一天内更动过的档案，可以使用 find 配合参数，如：‘ find / -ctime 1’。
    • 在 Linux 系统中，常见的套件管理员有 RPM 与 Tarball ，请分别说明这两个套件管理员的优缺点。
      • RPM 套件管理员在安装套件的时候，会将该套件的档案名称、套件功能与讯息等等资讯记录于 /var/lib/rpm 目录内，由于有这些套件的资本资讯，因此在系统内很容易进行 RPM 的升级、安装、移除等动作。不过，由于 RPM 档案之间的相依性相当的强，因此常常会有版本不合或者是欠缺某样前驱套件的问题发生。

      至于 Tarball 则是原始码，使用者可以自行设定套件的编译参数，以符合自己的 Linux 平台。此外，由于 Tarball 是原始码，因此需要在您的系统上面进行编译，编译的过程中需要 gcc, make, 以及 kernel-devel 等套件，还有您所想要安装的套件所需要的前驱套件也同时需要先安装后，才能进行 Tarball 的安装。注意，几乎每个 Tarball 以 tar 程式解开后，在新增的目录下均会有 README 以及 INSTALL 档案，请务必先查阅过后才进行编译工作。
    • 如果我下载了一个档名为 httpd-2.0.52.tar.gz 的档案，一般来说，这个档案代表的意义为何？我该如何让这个档案能够在我的 Linux 系统上面安装？
      • 由于附档名是 .tar.gz 或者是 .tgz 的档案，所以可以认定该档案为一个 Tarball 的档案。至于档名的配置方面，httpd 为套件名称，2.0.52 则通常为该套件的版本名称了！那如何安装？由于该档案为 httpd 这个套件，且格式为 Tarball ，所以您必须要：
      1. 系统上面务必具有 tar, make, gcc 等相关的编译套件；
      2. 使用 tar 解开 httpd-2.0.52.tar.gz 之后，务必进入该目录内读取 REAME 或/与 INSTALL 档案，以了解是否还需要其他的相关套件的搭配安装；
      3. 以 ./configure --help 查阅一下是否有相关可以加入或者取消的编译内容；
      4. 使用 make 读取 Makefile 来编译程式；
      5. 使用 make install 来安装程式！
    • 我以原始码的方式进行一个套件的安装，但是在分析系统的时候，分析程式一直告诉我找不到 cc 这个指令，请问这是什么问题？为何需要 cc ？又，我该如何解决这个问题，好让套件可以顺利的被安装在我的 Linux 上面？
      • 如前面几个题目所说的，因为是原始码，所以还需要编译程式来将该原始码编译成为可以在您的 Linux 系统上面跑的 binary 档案，在 Linux 上头预设的编译程式就是 gcc 这个编译器(compiler)。如果您在安装 Linux 的时候，使用 Linux Installer 预设的套件选择，那通常会没有安装 gcc 以及 make 等套件，此时，请拿出您的原版光碟，以 mount 指令挂载后，使用 RPM 将一个一个相关的套件安装即可(过程会蛮复杂的！)^_^
    • 我发现我的 Linux 系统怪怪的，似乎有什么不知名的程序在记忆体当中跑，我该如何将这个不知名的程序捉出来，并且将他移除？
      • 如果要捉出程序(process)的话，可以使用 ps -aux 或者是直接输入 top 来查询 process 的 ID (PID)，找到 PID 号码后，再以 kill -9 PID 来删除该程序即可。
    • 我总是无法编辑某个档案，您认为应该是什么问题造成的？那又要怎么解决？
      • 无法编辑某个档案，可以先使用 file 这个指令来查询一下该档案的格式，例如想察看 /etc/shadow 的格式，可以下达： ‘file /etc/shadow’，如果是文字档，却还是无法编辑，那么最可能发生的原因就是‘权限’的问题了。可以使用 ls -l filename 察看档案权限，再以 chmod 或 chown 来修订该档案的权限。此外，该档案也可能含有隐藏属性，可以使用 lsattr filename 查阅，再以 chattr 来修订隐藏属性。
    • 什么是 UID 与 GID ？UID 有哪些等级？
      • 在 Linux 系统下，使用者与群组其实都是以‘ID(数字)’的格式来设定的，所以使用者与群组其实都是 UID 或 GID (User ID 与 Group ID)，Linux 对于档案权限也都是使用 UID/GID 来分辨。不过人类习惯使用文字来记忆，所以才会有 /etc/passwd 与 /etc/group 来转译 ID 与 User 及 Group 之间，这也才会发生为何在 Internet 上面捉下来的 Tarball 解开之后，往往会有档案拥有人与群组为数字的型态，因为您 Linux 系统上面的 /etc/passwd 与 /etc/group 没有相关的对应文字说。至于 UID 的等级主要有两种，分别是超级管理员(root)，其 UID 为 0，其他非为 0 的 UID 基本上身份是相同的！不过 Linux 通常会将小于 500 的 UID 保留给系统使用。
    • 使用者的家目录参数、UID、GID以及其他相关参数，还有密码档案，放置在哪些档案里面？
      • 放置在 /etc/passwd 与 /etc/shadow 当中。当然还有 /etc/login.defs 喔！
    • 您认为一个称职的网管人员应该具备什么能力？
      • 能力需求相当高，如了(1)作业系统的基础知识(不论是 Linux/Unix/MAC/MS)；(2)网路基础的知识；(3)个别 Internet Services 的运作知识之外，还需要(4)身心保持在备战状态，以及(5)具有相当高程度的道德感、责任感与使命感。
    • 我要启动一个系统预设的 Service，请问我可能可以由执行或修改哪些目录底下的档案来启动？
      • 如果是 stand alone 的服务，可以经由 /etc/rc.d/init.d/* 里面的档案，如 /etc/rc.d/init.d/syslog start；
      如果是 Super daemon 的服务，就必须(1)先到 /etc/xinetd.d 或者是 /etc/inetd.conf 修改相关档案或参数； (2)以 /etc/rc.d/init.d/xinetd restart 来启动。
    • 我要关掉 cron 这个服务，应该怎么关掉他？如果正常的方法无法关闭这个服务，可以使用什么方法来关闭？
      • 因为 cron 是一个 stand alone 的服务，所以可以使用 /etc/rc.d/init.d/cron stop 来关闭；如果还是无法正常关闭，可以使用 ps -aux | grep cron 捉出该程序的 PID ，然后以 kill -9 PID 来关闭。
    • 如果一开机就要执行某个程式，应该要将该程式写入那个档案里面？
      • 可以直接在 /etc/rc.d/rc[run-level].d 里面加入 S 开头的档案，不过，更简单的作法是直接将该程式写入 /etc/rc.d/rc.local ，不过，请注意该程式必须要具有可执行的权限，且 rc.local 也必须要是可执行喔！
    2003/07/30：第一次完成日期！
    2003/08/19：加入了课后练习，如果您无法回答上面的问题.....不要怀疑，赶紧回去参考 Linux 基础篇！
    2003/09/06：加入课后练习的参考用解答
    2006/02/07：将原本的旧文移到此处
    2006/06/06：将 SATA 介面的硬碟代号再次做个修订！目前 SATA 的格式有分两种呢！
    2007/01/02：将一些排版重整，将一些日期方面的资料重整，将课后练习补上来
    2003/07/30以来统计人数


鸟哥的 Linux 私房菜 -- 简易网路基础概念

为取得较佳浏览结果，请爱用 firefox 浏览本网页

网路基础概念
切换解析度为 800x600
最近更新日期：2007/10/21
在金庸的小说里面提到了‘欲练神功，挥刀自宫’才能练成无敌的葵花宝典， 另外，金大侠也提到太极拳的学习到最后需要将所学的忘光光，此时才能‘无招胜有招’。 呵呵～这跟 Linux 有啥关系呐？在前一章我们不是提到关于‘架站前的技巧分析’吗？里面提到在 Linux 里面想要玩架站， 最重要的是得要搞熟 Linux 相关的操作技巧，这些技巧在一开始时真的得要花很多时间去熟悉， 真的会让人觉得好像已经‘自宫’的样子！不过，别担心， 等您花时间学习过后，肯定让您忘不了了！因为那时您已经‘无招胜有招’啦！ 发生问题时，肯定会依循之前学习到的一贯解决方法去搜寻、解答！很重要的！

在这一章里面，我们得要来谈的就是另一个‘神功’啦！那就是网路基础。 网路基础真的很重要的，包括乙太网路硬体的了解可以让您知道如何查出有问题的地方，进一步解决他； 了解网路协定(IP)与路由(route)让您可以完整的设定好您的网路架构，更可进一步进行子网路的划分， 以建立更小而美的网路环境！当然还有不可不提的 OSI 网路七层协定，真是重要啊！ 不过，在这一章鸟哥以较为口语的方式来介绍这些基础网路架构，希望能带给朋友们快速了解网路是啥。 当然，想要更了解网路相关功能的话，文末的参考资料可以参考看看喔！ ^_^

1. 网路 (Network)
    1.1 什么是网路
    1.2 乙太网路
    1.3 OSI 七层协定
 2. IP 与 MAC
    2.1 传输单位与 MAC
    2.2 IP 的组成
    2.3 网域的概念与 IP 的分级
    2.4 Netmask 的用途与子网路的切分
    2.5 IP 的种类与取得方式
    2.6 IP 封包的表头
 3. 网路层之路由概念
    3.1 什么是路由
    3.2 观察主机的路由
 4. 常见的通讯协定
    4.1 TCP 协定： 通讯埠口与 Socket, 封包的传送, 三向交握
    4.2 UDP 协定
    4.3 ICMP 协定
    4.4 MTU 的限制
    4.5 封包过滤的防火墙概念
 5. 连上 Internet 前的准备事项
    5.1 什么是主机名称与 DNS
    5.2 一组可以连上 Internet 的必要网路参数
 6. 重点回顾
7. 课后练习
8. 参考资料
9. 针对本文的建议：http://phorum.vbird.org/viewtopic.htm?t=25884
大标题的图示 网路(Network)
Linux 这个作业系统的优势之一就是在 (Network) 功能啦！这包含他的高稳定度系统资源分配， 以及较为安全的网路防备能力！所以很多人都喜欢拿他来进行网路伺服器的架设。 然而，这些网路功能的优点却同时也是缺点，怎么说呢？因为 Linux 网路功能太强了， 所以一旦被 Cracker (网路怪客) 入侵的话，嘿嘿嘿嘿！会遇上什么灾难你可能也想像不到！ 所以啰，上网之前，请先注意：‘我的网路做好安全防护了吗？’

再者，相对于视窗作业系统来说， Linux 的设定确实会让使用者花费比较多的心力， 毕竟当初它是一群工程师由于本身兴趣而设计出来的，所以依旧具有相当麻烦的设定工作需要作！ 这个时候，如果没有一些网路基础方面的认知的话，那么在 Linux 上面设定网路或者是进行网路除错将是您一生当中最大的梦魇......。 所以，这里有几件事情要请您好好的来参考一下：
  • 熟悉 Linux 操作与 Linux 基础：
    还是要一再地不断强调，如果您确定您只是想要‘Linux 能正常运作就好’那一类型的使用者，那么真的不要再往下看了，因为主机后续的维护问题会很大， 倒不如花个小钱，请个专家来帮您搞定即可！而如果您确定您是‘想要更了解 Linux 的使用者，并且想要熟悉架设网站’， 那么请不要再在网路上询问：‘为何我不能使用 FTP 传送资料到主机上？’ 或者是‘为何我不能建立个人网页’之类的傻问题，因为这仅仅牵涉到‘ 档案权限与属性 ’的概念而已，而这些概念都是 Linux 基础里头相当重要的功课！此外，由于远端操控 Linux 主机时，几乎都是使用文字界面来工作，所以不懂 bash shell ？ 哈哈！那么想要干嘛都码不可能！

  • 花几晚的时间将网路基础看一看：
    这一个章节旨在引导网路新鲜人快速进入网路的世界，所以鸟哥写的比较浅显一些些， 基本上，还有一堆网路硬体与通讯协定并没有被包含在这篇短文里头。 如果您的求知欲已经高过本章节，那么请自行到书局寻找适合您自己的书籍来阅读！ 当然，您也可以在网际网路上面找到您所需要的资料。 在本章最后的参考资料可以瞧一瞧呐！

  • 随时掌握主机资讯：
    这是最麻烦的一点了！因为大家还是常常认为‘我的网站这么小，没有人会注意的啦！’唉！ 说过若干次了，就是因为有这种心理存在，我们才会常常听到 ‘奇怪！我在早上刚安装完毕，怎么下午就无法以 root 的身份登入了！’ 请随时注意您主机的资讯，好好的爱护他吧！
好了，底下我们就得要来谈一谈一些重要的网路基础概念了，清醒了没？ 赶紧清醒清醒，准备要好好用功啦！ ^_^

小标题的图示 什么是网路
我们都知道，网路就是几部电脑主机或者是网路印表机之类的周边设备， 透过网路线或者是无线网路的技术，将这些主机与设备连接起来， 使得资料可以透过网路媒体(网路线以及其他网路卡等硬体)来传输的一种方式。 请您想像一下，如果您家里面只有电脑、印表机、传真机等机器，却没有网路连接这些硬体， 那么使用上会不会很麻烦？如果将这个场景移到需要工作的办公室时， 电脑的资料无法使用网路连接到印表机来列印，那是否很伤脑筋呢？ 对吧！光用想的就觉得很麻烦吧！不幸的是，这些麻烦事在 1970 年代以前，确实是存在的啊！

各自为政的‘硬体与软体’技术发展
在 1970 年代前后，为了解决这个烦人的资料传输问题，各主要资讯相关的公司都在研究独自的网路连接技术， 以使自家的产品可以在办公室的环境底下组织起来。其中比较有名的就是全录公司的 Ethernet 技术， 以及 IBM 研发的 Token-Ring 技术了。但是这些技术有个很大的问题，那就是这些技术彼此不认识对方的网路技术， 也就是说，万一你的办公室购买了整合 Ethernet 技术的电脑主机，但是其他的电脑却是使用 IBM 的机器时， 想要在这两者之间进行资料的沟通，在早期来说那是不可能的。

以‘软体’技术将硬体整合
但是，这些硬体的技术出现之后，还是对企业造成一定程度的困扰，怎么说呢？ 因为一个公司不太可能仅会使用一家厂商所推出的资讯产品吧！所以啰，这么多的硬体技术又该如何整合呐？ 举例来说， IBM 不可能不用自己的 Token-Ring 技术，当然也不会将该技术用在其他公司的硬体上面， 所以，这些厂商当然只会针对自家的硬体来进行网路传输软体的撰写啰。那么当许多不同公司的产品在自己企业内时， 您该如何将这些咚咚整合在一起呢？伤脑筋是吧！

所以在 1960 年代末期美国国防部就开始研究一个 可以在这些不同的网路硬体上面运作的软体技术， 使得不同公司的电脑或资料可以透过这个软体来达成资料沟通。这个研究由美国国防部尖端研究企画署 ( Defense Advanced Research Project Agency, DARPA )负责，他们将该网路系统称为 ARPANET， 这个咚咚就是目前熟知的 TCP/IP 技术的雏形了！在 1975 年左右， ARPANET 已可以在常见的 Ethernet 与 Token-Ring 等硬体平台底下互通资料了。DARPA 在 1980 年正式推出 TCP/IP 技术后， 由于想要推展此项技术，因此与柏克莱 (Berkeley) 大学合作，将 TCP/IP 植入著名的 BSD Unix 系统内， 由于大学乃是未来人才资料库的培养处，所以， TCP/IP 这个技术便吸引越来越多使用者的投入， 而这种连接网路的技术也被称之为 Internet 。

没有任何王法的 Internet
现在我们知道 Internet 就是使用 TCP/IP 的网路连接技术所串联起来的一个网路世界， 而这个 Internet 在 1980 年代之后由于浏览器图形介面的兴起，因此快速的蔓延在电脑世界中。 但是， Internet 有没有人在管理啊？呵呵！很不巧的是， Internet 是一个管理相当松散的所在。 只要你能够使用任何支援 TCP/IP 技术的硬体与作业系统，并且实际连接上网路后， 你就进入 Internet 的世界了。在该世界当中，没有任何王法的保护，您的实际资料如果接上 Internet ， 在任何时刻都需要自己保护自己，免得中了‘流弹’而受伤啊！

为什么说 Internet 没有王法呢？这是因为 Internet 仅是提供一个网路的连接介面， 所以您只要连接上 Internet 后，全世界都可以任你遨游，不过也因为如此，‘跨海’而来的攻击就成了简单的事件， 简单说，台湾的法律仅适用台湾地区对吧？但是电脑怪客可以在国外透过 Internet 对你的主机进行攻击， 我们的法律可管不到国外地区啊！虽然可以透过很多国际管道来寻求协助，不过，还是很难协助你缉拿凶手的啊。 因此啰，在你的主机要连上 Internet 之前，请先询问自己，真的有需要连上 Internet 吗？^_^

软硬体标准制定的成功带来的影响
现在我们常常听到‘你要上网啊！？那你要去买网路卡喔！还得要连接到 Internet 才行啊！’ 这个网路卡就是市面上随处可见的一个介面卡而已，至于 Internet 则是去向 Hinet/Seed net 或 其他网路服务提供公司 (Internet Service Provider, ISP) 申请的帐号密码。 问题是，是否就仅有网路卡与 Internet 才能上网啊？呵呵！当然不是！网路的硬体与软体可多着那！ 不过，最成功的却是乙太网路 (Ethernet) 与 Internet ，这是为什么呢？这两者的技术比较好吗？ 当然不是！这是因为这两者都被‘标准’所支援的缘故。

乙太网路最初是由全录 (Xerox PARC) 所建构出来的，而后透过 DEC, Intel 与 Xerox 合作将乙太网路标准化。 再经由 IEEE (Institute of Electrical and Electronic Engineers) 这个国际著名的专业组织利用一个 802 的专案制定出标准，之后有 19 家公司宣布支援 IEEE 所发布的 802.3 标准， 并且到了 1989 年国际标准组织 ISO (International Organization for Standard) 将乙太网路编入 IS88023 标准， 呵呵！这表示乙太网路已经是一项公认的标准介面了，如此一来，大家都可以依据这个标准来设定与开发自己的硬体， 只要硬体符合这个标准，理论上，他就能够加入乙太网路的世界，所以，购买乙太网路时， 仅需要查看这个乙太网路卡支援哪些标准就能够知道这个硬体的功能有哪些， 而不必知道这个乙太网路卡是由哪家公司所制造的呐。

Tips:
标准真的是个很重要的东西，真要感谢这些维护标准的专业组织。当有公司想要开发新的硬体时， 它可以参考标准组织所发布与维护的文件资料，透过这些文件资料后，该公司就知道要制作的硬体需要符合哪些标准， 同时也知道如何设计这些硬体，让它可以‘相容’于目前的机器，让使用者不会无所适从啊。 包括软体也有标准，早期 Linux 在开发时就是透过了解 POSIX 这个标准来设计核心的， 也使得 Linux 上面可以执行大多数的标准介面软体呢！您说，标准是否真的很重要啊！ 		鸟哥的图示
当然啦，乙太网路的成功除了加入成为国际标准之外，他持续发展成为星型连线也是一个相当重要的影响。 之后 Novell 的 NetWare 这个网路作业系统支援乙太网路，加上 NetWare 的强大功能与支援 IBM 的个人电脑， 都导致乙太网路的流行！直到现在，乙太网路是整个办公室与家庭内部的相当重要的一项硬体配备呢！ 他也是等同于基本网路设备的同义字了呐！ ^_^

除了硬体之外，TCP/IP 这个 Internet 的通讯协定也是有标准的，那就是底下的网站所提供的基本文件∶
  • http://www.rfc-editor.org/
透过这些文件的辅助，任何人只要会写程式语言的话，就有可能发展出自己的 TCP/IP 软体， 并且连接上 Internet 。早期的 Linux 为了要连接上 Internet ，Linux 团队就自己撰写出 TCP/IP 的程式码， 透过的就是这些基础文件的标准依据啊！举例来说∶ RFC1122 这个建议文件就指出一些基本需求， 让人们可以了解啊！

透过这些软硬体的标准以及实际上很多公司的支援，让现今的网路世界很容易就串接在一起。 而目前我们最常谈到的就是上面提到的咚咚，硬体就属‘乙太网路’最为常见， 软体当然就是 TCP/IP 这个 Internet 最通用的通讯协定啰。那么乙太网路是啥？ 为什么有高速乙太网路、超高速乙太网路？ TCP/IP 是啥？ 通讯协定是啥？浏览器又是啥？他们之间的关系是怎样？这些东西我们就慢慢来了解一下啰。

小标题的图示 乙太网路
在目前的网路社会当中，常见的网路硬体包括有最常见的乙太网路，当然还有速度算是最快的光纤网路， 别忘了还有蓝芽无线技术以及 ATM (Asynchronous Transfer Mode, 可不是自动提款机啊！！) 等硬体。会有这么多网路硬体的原因有很多， 只要是将各个网路硬体的使用场合分类吧！举例来说，一般家庭使用的网路速度并不需要太高， 若使用光纤网路，贵的哩！用不起～而企业场合如果仅使用乙太网路作为整合介面， 又可能造成频宽的不足！所以啰，这些硬体各有其优缺点啦！

因此，在谈乙太网路之前您必须要了解的是，整个网路世界并非仅有乙太网路这个硬体介面， 只是由于个人电脑的成功以及相关作业系统的支援度，加上乙太网路加入成为标准， 使得乙太网路成为目前最为热门的网路硬体技术。 因此，我们当然得就乙太网路来聊一聊啦！事实上，整个乙太网路的发展建议您可以直接参考风信子与张民人先生翻译的 ‘Switched & Fast 乙太网路’一书，该书内容相当的有趣，挺适合阅读的呐。 底下我们仅做个简单的介绍而已说。

就像前一小节提到的，乙太网路最早是由全录这家公司为了自家的硬体设备而发展起来的， 经由发明者 Metcalfe 大力推动乙太网路成为业界的标准后， 再经由 3Com 发展大量的乙太网路硬体，配合越来越流行的相容于 IBM 的个人电脑， 以及支援网路的作业系统的流行，最后使得大家都参与乙太网路这个介面的发展呐， 也由于多数公司的量产，使得乙太网路设备越来越便宜。早期的一张 10/100 Mbps 的网路卡要价上千元， 目前最便宜的只要 150 台币就能购买到了！

乙太网路的速度
前面说到，乙太网路的流行除了相关的硬体以及作业系统的流行之外，‘标准’也是一个很重要的因素。 早先 IEEE 所制订的乙太网路标准为 802.3 的 IEEE 10BASE5 ， 这个标准主要的定义是：‘10 代表传输速度为 10Mbps， BASE 表至采用基频信号来进行传输，至于 5 则是指每个网路节点之间最长可达 500 公尺。’ 网路的传输资讯就是 0 与 1 啊，因此，资料传输的单位为每秒多少 bit ， 亦即是 M bits/second, Mbps 的意思。那么为何制订成为 10Mbps 呢？ 这是因为早期的网路线压制的方法以及相关的制作方法，还有乙太网路卡制作的技术并不是很好， 加上当时的资料传输需求并没有像现在这么高，所以 10Mbps 已经可以符合大多数人的需求了。

当时的网路线使用的是旧式的同轴电缆线，这种线路在现在几乎已经看不到了。 取而代之的是类似传统电话线的双绞线 (Twisted Pair Ethernet) ， IEEE 并将这种线路的乙太网路传输方法制订成为 10BASE-T 的标准。 10BASE-T 使用的是 10 Mbps 全速运作且采用无遮蔽式双绞线 (UTP) 的网路线。此外， 10BASE-T 的 UTP 网路线可以使用星形连线(star)， 也就是以一个集线器为中心来串连各网路设备的一个方法， 有点类似底下的图示：

星形连线图示
图一、星形连线 (star) 简易图示

不同于早期以一条同轴电缆线连结所有的电脑的 bus 连线， 透过星形连线的帮助，我们可以很简单的加装其他的设备或者是移除其他设备， 而不会受到其他装置的影响，这对网路设备的扩充性与除错来说，都是一项相当棒的设计！ 也因此 10BASE-T 让乙太网路设备的销售额大幅提升啊！

后来 IEEE 更制订了 802.3u 这个支援到 100Mbps 传输速度的 100BASE-T 标准，这个标准与 10BASE-T 差异不大， 只是双绞线线材制作需要更精良，同时也已经支援使用了四对绞线的网路线了， 也就是目前很常见的八蕊网路线呐！这种网路线我们常称为等级五 (Category 5, CAT5) 的网路线。 这种传输速度的乙太网路就被称为 Fast ethernet 。至于目前我们常常听到的 Gigabit 网路速度 1000 Mbps 又是什么呐？那就是 Gigabit ethernet 哩！只是 Gigabit ethernet 的网路线就需要更加的精良。

为什么每当传输速度增加时，网路线的要求就更严格呢？ 这是因为当传输速度增加时，线材的电磁效应相互干扰会增强， 因此在网路线的制作时就得需要特别注意线材的质料以及内部线蕊心之间的缠绕情况配置等， 以使电子流之间的电磁干扰降到最小，才能使传输速度提升到应有的 Gigabit 。 所以说，在乙太网路世界当中，如果您想要提升原有的 fast ethernet 到 gigabit ethernet 的话， 除了网路卡 (Network Internet Card, NIC) 需要升级之外，主机与主机之间的网路线， 以及连接主机线路的集线器/交换器等，都必须要提升到可以支援 gigabit 速度等级的设备才行喔！

乙太网路的网路线接头
前面提到，网路的速度与线材是有一定程度的相关性的，那么线材的接头又是怎样呢？ 目前在乙太网路上最常见到的接头就是 RJ-45 的网路接头，共有八蕊的接头，有点像是胖了的电话线接头， 如下所示：
RJ-45 接头示意图
图二、RJ-45 接头示意图

而 RJ-45 接头又因为每条蕊线的对应不同而分为 568A 与 568B 接头， 这两款接头内的蕊线对应如下表：

接头名称 | 1 2 3 4 5 6 7 8
568A | 白绿 绿 白橙 蓝 白蓝 橙 白棕 棕
568B | 白橙 橙 白绿 蓝 白蓝 绿 白棕 棕

事实上，虽然目前的乙太网路线有八蕊且两两成对，但实际使用的只有 1,2,3,6 蕊而已， 其他的则是某些特殊用途的场合才会使用到。但由于主机与主机的连线以及主机与集线器的连线时， 所使用的网路线脚位定义并不相同，因此由于接头的不同网路线又可分为两种：
  • 平行线：两边接头同为 568A 或同为 568B 时称为平行线，用在连结主机网路卡与集线器之间的线材；
  • 跳线：一边为 568A 一边为 568B 的接头时称为跳线，用在直接连结两部主机的网路卡。
而不同等级的线材除了针对线材材质的电阻等规格加以规范之外，有时为了更好的电磁效应屏蔽功能， 会将四对蕊线以金属薄膜包覆，以提供更佳的抗干扰能力。 没有屏蔽的我们就称为无遮蔽双绞线(UTP)， 有屏蔽的就被称为有遮蔽双绞线(sheild Twisted Pair, STP)。 STP 的网路线由于加上屏蔽物质，所以较硬、较贵也较不易布线，不过优点则是对于电磁效应屏蔽较佳。 那么网路线如何选择？以目前来说，由于我们想到达到 Gigabit Ethernet 的网路速度， 所以必须使用 CAT 5e 以上等级包含 CAT 6 的网路线材才行！那么如何区分？ 其实在网路线上面的缆线表面都会写上这条网路线的相关规范，看一看就知道啦！ 而且还得要看看该条线段是‘跳线’还是‘平行线’喔！

资料在乙太网路间的传送 (MAC)
接下来要谈的是那么乙太网路到底是如何传输资料的呢？ 由于目前办公室内部的乙太网路多是利用集线器以及交换器(Hub/Switch)做为中心， 利用星形连线达成网路环境的一种方式，因此网路线是一个很重要的媒体喔！ 那么网路线里头最多就是电子讯号在跑嘛(就是 0 与 1 啊)！而如果同时有两部电脑要使用这个网路线时， 怎么可能同时发出两个电子讯号出来呢？这个时候是会发生讯号碰撞的问题的， 因此，网路共享媒体(包括网路线、集线器等)在单一时间点内， 仅能被一部主机所使用这个概念必须要先了解才行。

为了杜绝这种讯号碰撞产生的问题，所以乙太网路在发展时就使用一种名为 CSMA/CD (Carrier-Sense Multiple Access with Collision Detection) 的技术。 这种技术的特点就是当节点想要在网路媒体上面传输资料时， 会先侦测该媒体上面是否有其他的节点正在使用，确定没有其他节点在使用该媒体时，该节点才会开始传送资料。 并且，当节点开始传送资料时，节点也能够同时侦测是否有发生碰撞的现象。 (注：任何一个具有 MAC 的网路媒体接在该网路上面，就称为一个节点"node"， 所以，一部主机就是一个 node ！) 不过，事实上在这样的共享媒体环境下，当网路相当忙碌时， 资料的碰撞 (collision) 还是会发生的啦！

再来，我们还是得要知道一下‘那电子讯号由一部主机发出后，这个讯号怎么知道要传到哪里去？’ 既然有来源也有目标，那当然就得需要一个可以判别讯号来源与等待接受的主机的相关资讯啰？ 没错！在乙太网路内，我们就是以 MAC (Media Access Control, 媒体存取控制)来管理资料传送的。 而 MAC 其实就是一个讯框( frame )， 你可以把他想成是一个在网路线上面传递的包裹， 而这个包裹是整个网路硬体上面传送资料的最小单位了。 也就是说，网路线可想成是一条‘一次仅可通过一个人’的独木桥， 而 MAC 就是在这个独木桥上面动的人啦！那 MAC 又该如何判断这独木桥的两端分别是何处呢？ 这就得要看一看 MAC 这个讯框的内容了：

乙太网路的 MAC 讯框
图三、乙太网路的 MAC 讯框

在这个 MAC 当中，最重要的就是那个 6 Bytes 的目的与来源位址了！ 事实上，在所有的乙太网路卡当中都有一个独一无二的网路卡卡号， 那就是上头的‘目的与来源位址’，这个位址是硬体位址( hardware address )， 共有 6 bytes ，分别由 00:00:00:00:00:00 到 FF:FF:FF:FF:FF:FF， 这 6 bytes 当中，前 3bytes 为厂商的代码，后 3bytes 则是该厂商自行设定的装置码了。 在 Linux 当中，你可以使用 ifconfig 这个指令来查阅你的网路卡卡号喔！ 不过，由于 MAC 主要是与网路卡卡号有关，所以我们也常常将 MAC 作为网路卡卡号的代称。 特别注意，在这个 MAC 的传送中，他仅在区域网路内生效， 如果跨过不同的网域 (这个后面 IP 的部分时会介绍)，那么来源与目的的位址就会跟着改变了。 这是因为变成不同网路卡之间的交流了嘛！所以卡号当然不同了！如下所示：

在不同主机间持续传送相同资料
图四、在不同主机间持续传送相同资料的 MAC 讯框变化

例如上面的图示，我的资料要由电脑 A 通过 B 后才送达 C ，而 B 电脑有两块网路卡， 其中 MAC-2 与 A 电脑的 MAC-1 互通，至于 MAC-3 则与 C 电脑的 MAC-4 互通。 但是 MAC-1 不能与 MAC-3 与 MAC-4 互通，为啥？因为 MAC-1 这块网路卡并没有与 MAC-3 及 MAC-4 使用同样的 switch/hub 相接嘛！所以，资料的流通会变成：
  1. 先由 MAC-1 传送到 MAC-2 ，此时来源是 MAC-1 而目的地是 MAC-2；
  2. B 电脑接收后，察看该讯框，发现目标其实是 C 电脑，而为了与 C 电脑沟通， 所以他会将讯框内的来源 MAC 改为 MAC-3 ，而目的改为 MAC-4 ，如此就可以直接传送到 C 电脑了。
也就是说，只要透过 B (就是路由器) 才将封包送到另一个网域 (IP 部分会讲) 去的时候， 那么讯框内的硬体位址就会被改变，然后才能够在同一个网域里面直接进行 frame 的流通啊！

另外，这个 MAC 讯框可以容纳多大的资料啊？？在正规的乙太网路当中， 就如同上图三所标示的，一个讯框标准容量最大可达 1500Bytes， 也就是说，在整条网路上面，一个讯框最大就仅能达到 1500bytes。 那如果我有 100M Bytes 的资料要传送怎办呢？那您的作业系统会主动的将该 100M bytes 的资料拆解成为多个 1500bytes 的讯框后，传送到目的地，再重新组合成为原本 100Mbytes 的档案！ 这里也就可以解释，为什么网路共享媒体一次只能有一部主机使用， 但是区域网路内的两部电脑却可以同时下载档案？这是因为‘每次要发出一个讯框时， 都需要进行 CSMA/CD 的监听，而刚刚成功发出讯框的那部主机， 也需要再使用 CSMA/CD 来跟大家抢。’ 所以啰，谁能抢到呢？有时后因为网路太忙碌，那么 frame 与 frame 就可能会碰撞啦。

在早期 10/100 Mbps 的年代，这个 1500 bytes 的网路媒体传输数值还没有多大的影响， 但到了 gigabit 的年代，如果使用的还是 1500 bytes 时，大型的档案将会被拆解成多个 frame ， 而多个 frame 就意味着主机需要进行多次资料的拆解，网路也需要进行多次的传输。 如果可以将这个 MAC 的资料存放处加大的话，那么不就可以节省系统资源， 并且网路传递的次数也会降低，呵呵！没错～在这样的思考逻辑下，于是目前的 Gigabit Ethernet 通常都已经支援大的讯框架构，那就是 Jumbo Frame 啰～ 一般来说，只要是 Gigabit 乙太网路卡都会支援 Jumbo frame 的 (请参考文末的参考文献连结)， 他的大小通常是定义在 9000 bytes 的， 不过其他的乙太网路媒体可就不一定了。由于网路媒体支援 Jumbo frame 后， 他的效能是会有所改善的，所以挑选乙太网路媒体时，记得查阅一下该媒体的说明喔！
Tips:
由于网路卡卡号是跟着网路卡走的，并不会因为重灌作业系统而改变， 所以防火墙软体大多也能够针对网路卡来进行抵挡的工作喔！ 不过抵挡网卡仅能在区域网路内进行而已，因为 MAC 不能跨 router 嘛！！ 		鸟哥的图示
共不共享很重要，集线器还是交换器？
刚刚我们上面提到了，当一个很忙碌的网路在运作时，网路共享媒体就可能会发生碰撞的情况， 这是因为 CSMA/CD 的缘故。那我们也知道在一个星形连线当中， 正中央的那个设备是集线器或交换器来连接各 PC 的。 那么 Hub 与 Switch 有啥不同啊？其实，那个 Hub 就是网路共享媒体， Hub 仅是将所有来自 PC 的 frame 再次送出去给所有的 PC 而已，所以他是个共享媒体。

Switch 则不然喔！Switch 内部具有微处理器以及记忆体，这个记忆体可以记录每个 switch port 与其连接的 PC 的 MAC 位址，所以，当来自 switch 两端的 PC 要互传资料时， 每个 frame 将不会透过 CSMA/CD 的监听，而是透过 switch 直接将该 frame 送到目标主机上头去呐！ 也就是说， switch 不是个共享媒体，且 switch 的每个埠口 (port) 都具有独立的频宽喔！ 举例来说，10/100 的 Hub 上连结 5 部主机，那么整个 10/100Mbps 是分给这五部主机的， 所以这五部主机总共只能使用 10/100Mbps 而已。那如果是 switch 呢？由于‘每个 port 都具有 10/100Mbps 的频宽’， 所以就看您当时的传输行为是如何啰！举例来说，如果是底下的状况时，每个连线都是 10/100 Mbps 的。

Switch 的频宽简介
图五、Switch 的频宽简介

A 传送到 D 与 B 传送到 C 都独自拥有 10/100Mbps 的频宽，两边并不会互相影响！ 不过，如果是 A 与 D 都传给 C 时，由于 C port 就仅有 10/100Mbps ，等于 A 与 D 都需要抢 C 节点的 10/100Mbps 来用的意思。 总之，你就是得要记得的是，switch 已经克服了封包碰撞的问题，因为他有个 switch port 对应 MAC 的相关功能， 所以 switch 并非共享媒体喔！同时需要记得的是，现在的 switch 规格很多， 在选购的时候，千万记得选购可以支援全双工/半双工，以及支援 Jumbo frame 的为佳！

那什么是全双工/半双工(full-duplex, half-duplex)？ 前面谈到网路线时，我们知道八蕊的网路线实际上仅有两对被使用，一对是用在传送，另一对则是在接收。 如果两端的 PC 同时支援全双工时，那表示 Input/Output 均可达到 10/100Mbps， 亦即资料的传送与接收同时均可达到 10/100bps 的意思，总频宽则可达到 20/200Mbps 啰 (其实是有点语病的，因为 Input 可达 10/100Mbps， output 可达 10/100Mbps ， 而不是 Input 可直接达到 20/200Mbps 喔！)如果您的网路环境想要达到全双工时， 使用共享媒体的 Hub 是不可能的，因为网路线脚位的关系，无法使用共享媒体来达到全双工的！ 如果你的 switch 也支援全双工模式，那么在 switch 两端的 PC 才能达到全双工喔！

一些常见的乙太网路技术
如果您常常在网路上搜寻一些硬体资讯时，或者是常常跑到资讯卖场去看看新鲜货时， 应该会注意到一些网路硬体，尤其是越来越普及的 switch 这玩意儿的相关硬体资讯吧！ 而且，我们知道网路线因为接头的关系而有平行线与跳线，这两种网路线使用的时机并不相同， 那么你是否一定需要购买特殊的线段才能够连结 PC 与 switch 呢？呵呵！不需要～ 因为现在的硬体实在太聪明了！底下的功能您应该都可以在新的硬体上面发现的！

自动协调速度机制：
我们都知道现在的乙太网路卡是可以向下支援的，亦即是 Gigabit 网路卡可以与早期的 10/100Mbps 网路卡连结而不会发生问题。但是，此时的网路速度是怎样判定呢？ 早期的 switch/hub 必须要手动切换速度才行，新的 hub/switch 因为有支援 auto-negotiation 又称为 N-Way 的功能，他可自动的协调出最高的传输速度来沟通喔！如果有 Gigabit 与 10/100Mbps 在 switch 上面， 则 N-Way 会先使用最高的速度 (gigabit) 测试是否能够全部支援，如果不行的话，就降速到下一个等级亦即 100 Mbps 的速度来运作的！

Auto MDI/MDIX：
那么我们是否需要自行分辨平行线与跳线呢？不需要啦！因为 switch 若含有auto MDI/MDIX 的功能时， 会自动分辨网路线的脚位来调整连线的，所以您就不需要管你的网路线是跳线还是平行线啰！方便吧！ ^_^

讯号衰减造成的问题
由于电子讯号是会衰减的，所以当网路线过长导致电子讯号衰减的情况严重时， 就会导致连线品质的不良了。因此，连结各个节点的网路线长度是有限制的喔！ 不过，一般来说，现今的乙太网路 CAT5 等级的网路线大概都可以支援到 100 公尺的长度， 所以应该无庸担心才是呐！

但是，造成讯号衰减的情况并非仅有网路线长度而已！如果您的网路线折得太严重(例如在门边常常被门板压，导致变形) ，或者是自行压制网路线接头，但是接头部分的八蕊蕊线缠绕度不足导致电磁干扰严重， 或者是网路线放在户外风吹日晒导致脆化的情况等等，都会导致电子讯号传递的不良而造成连线品质恶劣， 此时常常就会发现偶而可以连线、有时却又无法连线的问题了！因此，当您需要针对企业内部来架设整体的网路时， 注意结构化布线可是很重要的喔！

结构化布线
所谓的结构化布线指的是将各个网路的元件分别拆开，分别安装与布置到企业内部， 则未来想要提升网路硬体等级或者是移动某些网路设备时，只需要更动类似配线盘的机柜处， 以及末端的墙上预留孔与主机设备的连线就能够达到目的了。例如底下的图示：

结构化布线简易图示
图六、结构化布线简易图示

在墙内的布线需要很注意，因为可能一布线完成后就使用 5-10 年以上喔！ 那您需要注意的仅有末端墙上的预留孔以及配线端部分。 事实上，光是结构化布线所需要选择的网路媒体与网路线的等级， 还有机柜、机架，以及美化与隐藏网路线的材料等等的挑选，以及实际施工所需要注意的事项， 还有所有硬体、施工所需要注意的标准规范等等， 已经可以写满厚厚一本书，而鸟哥这里的文章旨在介绍一个中小企业内部主机数量较少的环境， 所以仅提到最简单的以一个或两个交换器 (swtich) 串接所有网路设备的小型星形连线状态而已， 如果您有需要相关硬体结构化布线的资讯，可以参考风信子兄翻译的‘Swtich and Fast 乙太网路’一书的后半段！至于网路上的高手吗？您可以前往酷学园请教 ZMAN 大哥喔！
小标题的图示 OSI 七层协定
目前我们的主机只要能够取得正确的 IP 与相关参数设定时，你就可以连上 Internet 了， 根本不管你的网路硬体是乙太网路还是光纤网路。而且，你主机的作业系统是啥， Internet 也是不管的！ 这是为什么呢？因为网路的传输是有分层架构的，每个分层 (layer) 是可以独立的。 同时每个分层都有独自的标准可供依循，例如在网路媒体的硬体部分就可以参考 IEEE 的 802.3 的标准！ 如此一来，大家都可以在自己的分层当中找到相关的标准来设定自己的资料，如此网路连结就变的更容易了。 关于网路的分层我们最喜欢拿 OSI (Open system Interconnection) 七层协定来说明喔！ 事实上， OSI 七层协定只是一个参考的模型 (model)，不过，由于 OSI 所定义出来的七层协定相当良好， 所以拿来当作网路连线解释真是太棒了！底下就来说说吧！

分层 | 负责内容
Layer 1 实体层 Physical Layer, PHY | 在这个层级当中主要定义了最基础的网路硬体标准，包括各种网路线、各种无线连线方式，各种设备规范、 以及各种接头的规则，还有传输讯号的电压等等，反正与硬体有关的标准大多都在这个层级当中定义的！
Layer 2 资料连接层 Data-Link Layer | 由于传送资料的网路媒体是以电子讯号进行传送，所以我们的资料要使用这样的讯号传送时， 就需要制订各种网路型态的讯框 (frame) 了，才能确保资料可以在不同的网路媒体进行传送的动作。 所以，在这一层当中就制订了 frame 的格式以及通过网路的方式。 包括讯框的资料格式、错误控制、流量控制、检查资料传输错误的方法等等，都在这里控制。 既然与讯框有关，当然这个层级就与前面提到的 MAC 有很强烈的相关性啰！ 但我们知道事实上目前的 Internet 使用的其实是 IP 来进行连线的啊！但硬体资料却是由讯框所传送的。 为了要将两者对应 (MAC 与 IP 的对应)，就必须要经由 Address Resolution Protocol (ARP) 这个协定来帮忙解析出对应才行！
Layer 3 网路层 Network Layer | 这一层是我们最感兴趣的啰～因为我们提及的 IP (Internet Protocol) 就是在这一层定义的， 同时也定义出电脑之间的连线建立、终止与维持等，资料封包 (packet) 的传输路径选择等等， 因此这个层级当中最重要的除了 IP 之外，就是封包能否到达目的地的路由 (route) 概念了！ 此外，这一个网路层可以涵盖实体层与资料连结层，通常我们不需要设定硬体与相关 MAC 的资料， 就是因为网路层已经 (有点类似) 隐藏了底下两层，让我们只要设定好 IP 就能够上网呐！ IP 与 route 的部分我们会在下一小节加以介绍的。
Layer 4 传送层 Transport Layer | 这一个分层定义了发送端与接收端的连线技术(如 TCP 技术)， 同时包括该技术的封包格式，资料封包的传送、流程的控制、传输过程的侦测检查与复原重新传送等等， 以确保各个资料封包可以正确无误的到达目的端。
Layer 5 会谈层 Session Layer | 在这个层级当中主要定义了两个位址之间的连线通道之连接与挂断，此外，亦可建立应用程式之对谈、 提供其他加强型服务如网路管理、签到签退、对谈之控制等等。如果说传送层是在判断资料封包是否可以正确的到达目标， 那么会谈层则是在确定网路服务建立连线的确认，例如三向交握。这部分我们会在底下的 TCP 技术当中做个说明。
Layer 6 表现层 Presentation Layer | 我们在应用程式上面所制作出来的资料格式不一定符合网路传输的标准编码格式的！ 所以，在这个层级当中，主要的动作就是：将来自本地端应用程式的资料格式转换(或者是重新编码)成为网路的标准格式， 然后再交给底下传送层等的协定来进行处理。所以，在这个层级上面主要定义的是网路服务(或程式)之间的资料格式的转换， 包括资料的加解密也是在这个分层上面处理。
Layer 7 应用层 Application Layer | 完全与程式有关的啰，包括定义出档案的读取、复制、开启、关闭等等， 常见的程式包括有浏览器、资料库处理系统与电子邮件系统等等。

事实上，在上述的七层协定当中，前两层(实体与资料连接层)主要就是由一些硬体标准所规范出来的， 像我们前一小节提到的乙太网路之 MAC 讯框相关的格式，以及一些类似乙太网路线接头规范、 CSMA/CD 的技术等等，都是在前两层进行规范的。

至于网路层与传送层则与 TCP/IP 有关。我们知道目前的 Internet 相关的 IP 与 TCP 封包格式是由 Internet Network Information Center (INTERNIC) 所统一整理与维护的，至于 TCP/IP 的标准则主要以 Request For Comment (RFC) 技术报告的形式公开。 而会谈、表现与应用层则主要与作业系统及应用程式有关了。

那么这七层到底是如何运作的呢？我们以常见的 WWW 浏览器来进行说明好了。 假设你想要由奇摩雅虎(tw.yahoo.com)下载一个大于 10Mbytes 的档案， 那么你必须要由你的主机打开浏览器，并且输入相关的网址列后才能开始下载，对吧！ 不过，我们知道由于网路媒体的关系，标准乙太网路的硬体最大仅能支援 1500 bytes 的讯框大小， 而我要去奇摩雅虎时，必须要知道奇摩雅虎那部主机的 IP 才行，而我们的浏览器使用的是 TCP 的封包格式。这样一层一层下来，你可以将各个分层想成是一个一个的大袋子， 而且每个袋子都必须要包含在下一个袋子内，例如 IP 的袋子必须要装在 MAC 讯框的袋子内。
  • 所以，由于最后被传送的袋子(实体层)的限制，我必须要将 10Mbytes 的档案先切成数个小包， 然后将这些小包给他包到 TCP 的袋子内，这个袋子记载了我的资料内容。
  • 然后这个袋子还要装到 IP 这个袋子内，IP 这个袋子会记录我的住址以及要传送到的目的地的住址，
  • 最后再将这个 IP 的袋子装到 MAC 的讯框袋子内， 这个袋子就记录了可以在同一区域内传递袋子的网卡卡号了。
之后这个 MAC 的大袋子就会被带到下个传递点去， 当然啦， MAC 这个袋子的传递是需要符合 CSMA/CD 以及乙太网路的相关定义的喔！ 当传到目的地后，对方会一个袋子一个袋子的解开，最后拿到他们的资料。不过，由于我的 10Mbytes 已经被分成多个小袋子了，所以每个小袋子内需要有序号，这样当所有的小袋子都到达目的地后， 对方才可以依照这些序号将所有小袋子内的资料给他整合成为原来的资料啊！

所以啊，这些分层可以使用底下的图示来看：

OSI 七层协定的相关性
图七、OSI 七层协定的相关性

例题一：请找出您 Linux 主机上面的网路卡硬体位址(Hardware Address, 或 MAC)， 如果已经连上网路的话，请找出您区域网路内其他电脑的网路卡卡号。

答：
    在 Linux 底下网路卡的装置代号一般是 eth0 ，所以想要了解您的网路卡卡号时，可以使用： ‘ ifconfig eth0 ’这个指令来查阅，在出现的资料中第一行最右边搜寻 HWaddr 的后面接的那串咚咚，就是你的卡号。 至于其他的卡号与 IP 的对应方面，直接输入‘ arp -n ’应该就可以查阅的到相关的对应表啰！ 更多说明请先使用 man 来查询，后续章节我们也会继续加以介绍的。
大标题的图示 IP 与 MAC
我们现在知道要有网路的话，必须要有网路相关的硬体，而目前最常见的网路硬体介面为乙太网路， 包括网路线、网路卡、Hub/Switch 等等。而乙太网路上面的传输使用网路卡卡号为基准的 MAC 讯框， 配合 CSMA/CD 的监听技术来传送讯框，这是硬体部分。那么在软体部分，我们知道 Internet 其实就是 TCP/IP 这个通讯协定的通称，Internet 是由 INTERNIC 所统一管理的， 但其实他仅是负责分配 Internet 上面的 IP 以及提供相关的 TCP/IP 技术文件而已， 另外，在 TCP/IP 上面还有很多的应用程式，包括 FTP, HTTP, EMAIL 等等的技术！ 底下我们就先来谈一谈最底层的 MAC 与 IP 吧！

小标题的图示 传输单位与 MAC
想一想，如果没有电的话，我们的网路是否能够通行无阻？当然不行！ 因为网路其实就是电子讯号的传送啊！如果没有电，当然就没有办法传送讯息了。而电子讯号只有 0 跟 1 啊，所以在网路单位的计算上，一般通常是以二进位的 bit 为单位的。那么这个 bit 与我们通常用来计算档案大小的单位 bytes 有什么关连性？其实：
    1byte = 8bits
所以啦，一般来说，我们看到的网路提供者 (Internet Services Provider, ISP) 所宣称他们的 ADSL 传输速度可以达到 下行/上行 2Mbps/128Kbps ( Kbits per second) 时，那个 Kb 指的可不是 bytes 而是 bits 喔！所以 2M/128K 在实际的档案大小传输速度上面，最大理论的传输为 256KBps/16 KBps(KBytes per second)，所以正常下载的速度约在每秒 100~200 KBytes 之间呐！ 同样的道理，在网路卡或者是一些网路媒体的广告上面，他们都会宣称自己的产品可以自动辨识传输速度为 10/100 Mbps ( Mega-bits per second)，呵呵！该数值还是得再除以 8 才是我们一般常用的档案容量计算的单位 bytes 喔！这样可以了解传输单位的意义了吗？！

那么 MAC 呢？MAC 是 Media Access Control (媒体存取控制)，我们在前小节的 图三已经介绍过该讯框的资料格式， 且 MAC 常用来做为硬体位址 (Hardware address) 的代称。我们自己主机上面的 MAC 很好解决， 假设您的网路卡仅有一张，则 Linux 系统内网卡的代号预设由 eth0 开始编号， 因此当你输入 ifconfig eth0 这个指令时，就会出现如下的讯息了：
在 Linux 环境下
[root@linux ~]# ifconfig eth0
eth0      Link encap:Ethernet  HWaddr 00:01:03:43:E5:34
          inet addr:192.168.1.100   Bcast:192.168.1.255   Mask:255.255.255.0
          inet6 addr: fe80::201:3ff:fe43:e534/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
.....

在 Windows 环境下
C:\Documents and Settings\admin..> ipconfig /all
....
        Physical Address. . . . . . . . . : 00-01-03-43-E5-34
....
事实上，这个 MAC 几乎都是焊死在网路卡上面的，所以不能够被修改。 不过，近来有些笔记型电脑上面的网路卡可以透过软体来进行 MAC 的修改啰～ 好，在我们的主机上网路卡可以透过 ifconfig 来查询到 MAC ，但我们知道讯框是在两张网路卡之间传讯的， 那我如何知道其他主机的网路卡卡号呢？此时就得要透过 ARP (Address Resolution Protocol) 的帮忙了。 由于 TCP/IP 的通讯协定内大多仅需要了解 IP 即可，但讯框却是透过 MAC 来传递， 因此 IP 与 MAC 就得要透过一个解析的功能啰！那就是 ARP 啦！

当我们的主机想要找出目标 IP 时，就会对整个区域网路进行广播封包(broadcast)的传送， 这个广播封包可以对所有区域网路内的电脑要求回报他的 IP 与 MAC ， 当目标 IP 看到这个广播封包时，就会回应您主机相关的 MAC 资讯，如果非目标主机接到这个封包， 就会主动的忽略！如此一来，你就可以取得目标主机的 MAC 啰！ 而这个目标主机的 MAC 就会被记录到你的主机内的 ARP table (ARP table 在记忆体中)， 不过还是要再次的提醒， MAC 是不能跨路由的，请参考图四的相关说明喔！ 如果想要查阅你的 ARP 记录，可以使用 arp 这个指令即可。
[root@linux ~]# arp -[nd] hostname
[root@linux ~]# arp -s hostname(IP) Hardware_address
参数：
-n ：将主机名称以 IP 的型态显示
-d ：将 hostname 的 hardware_address 由 ARP table 当中删除掉
-s ：设定某个 IP 或 hostname 的 MAC 到 ARP table 当中
范例一：
[root@linux ~]# arp -n
Address            HWtype  HWaddress           Flags Mask    Iface
192.168.1.100      ether   00:01:03:01:02:03      C          eth0
192.168.1.240      ether   00:01:03:01:DE:0A      C          eth0
192.168.1.254      ether   00:01:03:55:74:AB      C          eth0
范例二：
[root@linux ~]# arp -s 192.168.1.100  01:00:2D:23:A1:0E
# 这个指令的目的在建立静态 ARP
如同上面的表格，我主机上面的 ARP 记录着这么多的 IP 与 MAC 的对应， 这个 ARP 的好处可多了！由于有记录 MAC 与 IP 的对应，因此当下回我的资料又传送到同一部主机时， 我的主机会主动的传送到同一个 MAC 去，而不需要再次透过 broadcast 来查询 MAC， 所以省去了很多网路延迟的时间喔！此外，特别注意的是， ARP table 是动态的资讯，他会随时随着您的网域里面电脑的 IP 更动而变化，所以，即使您常常更动您的电脑 IP，不要担心，因为 ARP table 会自动的重新对应 IP 与 MAC 的表格内容！但如果你有特殊需求的话， 也可以利用‘ arp -s ’这个参数来定义静态的 ARP 对应喔！

小标题的图示 IP 的组成
好了，接下来可以开始介绍那个可爱的 TCP/IP 里头的 IP 啦！这个 IP 是 Internet Protocol 的缩写，他的功能有点像是‘门牌号码’，主要是在网路层( Layer 3 )的功能， 那么这个 IP 有哪些重要的地方需要了解的呢？底下我们就来谈一谈吧！

IP 是一种资料封包的格式，这个 IP 资料封包最大可以到达 65535 bytes ， 然而就如同图三乙太网路讯框的资料所示， 由于标准乙太网路讯框可包含的资料最大仅达 1500 bytes ， 并且依照不同的网路媒体而有不同的 MAC 讯框大小，我们前面也谈到的 OSI 七层协定当中， 由于 IP 封包必须要放到 MAC 讯框当中，因此 IP 封包在 Internet 上面应该是不可能达到 65535 bytes 这个值的(因为必须小于 MAC 讯框所能容许的最大值)。另外， 由于网路连线过程当中封包所经过的网路媒体各不相同，因此 MAC 讯框大小当然也不同， 而为了让 IP 封包可以适用在所有的网路媒体讯框当中，因此， IP 封包是可以被‘重组的’！

我们知道 MAC 讯框表头 (将他想成是一个信封袋外面的记录资料) 当中最重要的就是网路卡卡号 (hardware address) 这个咚咚！(参考图三 )，那么 IP 表头最重要的是什么呢？呵呵！那就是 IP 位址 (address) 了！目前我们在 Internet 上面使用的 IP 协定是第四版，通称为 IPv4 ，这个版本的 IP 位址主要是由 32 bits 的资料所组成的一组数据，也就是 32 个 0 跟 1 所组成的数据资料，因为只有零跟一，所以 IP 的组成当然就是电脑认识的二进位的表示方式了。

不过，因为人类对于二进位实在是不怎么熟悉，所以为了顺应人们对于十进位的依赖性，因此，就将 32 bits 的 IP 分成四小段，每段含有 8 个 bits ，将 8 个 bits 计算成为十进位，并且每一段中间以小数点隔开，那就成了目前大家所熟悉的 IP 的书写模样了。如下所示：
IP 的表示式：
00000000.00000000.00000000.00000000   ==> 0.0.0.0
11111111.11111111.11111111.11111111   ==> 255.255.255.255
所以 IP 最小可以由 0.0.0.0 一直到 255.255.255.255 哩！事实上， IP 的组成当中，除了以 32 bits 的组成方式来说明外，还具有所谓的‘网域’的概念存在。底下就来谈一谈什么是网域吧！

小标题的图示 网域的概念与 IP 的分级
事实上在 IP 的 32 bits 资料中，主要分为 HOST_ID 与 Net_ID 两部份，我们先以 192.168.0.0 ~ 192.168.0.255 这个 C Class 的网域当作例子来说明好了：
192.168.0.0~192.168.0.255 这个 C Class 的说明：
11000000.10101000.00000000.00000000
11000000.10101000.00000000.11111111
|----------Net_ID---------|-host--|
在 C Class 的范例当中，前面三组数字 (192.168.0) 称为网域号码 (Net_ID) ，最后面一组数字则称为 主机号码 (Host_ID)。同一个网域当中的定义是‘在同一个物理网段内，主机的 IP 具有相同的 Net_ID ，并且具有独特的 Host_ID’，那么这些 IP 群就是同一个网域内的 IP 网段啦！
Tips:
什么是物理网段呢？当所有的主机都是使用同一个网路媒体串在一起， 这个时候这些主机在实体装置上面其实是连线在一起的，那么就可以称为这些主机在同一个物理网段内了！ 同时并请注意，同一个物理网段之内，可以依据不同的 IP 的设定，而设定成多个‘IP 网段’喔！ 		鸟哥的图示
上面例子当中的 192.168.0.1, 192.168.0.2, ...., 192.168.0.255 这些 IP 就是同一个网域内的 IP 群(同一个网域也称为同一个网段！)，请注意，同一个 Net_ID 内，不能具有相同的 Host_ID ，否则就会发生 IP 冲突，可能会造成两部主机都没有办法使用网路的问题！ 那么同一个网域该怎么设定，与将 IP 设定在同一个网域之内有什么好处呢？
  • 在同一个网段内，Net_ID 是不变的，而 Host_ID 则是不可重复，此外， Host_ID 在二进位的表示法当中，不可同时为 0 也不可同时为 1 ，例如上面的例子当中， 192.168.0.0 ( Host_ID 全部为 0 )以及 192.168.0.255 ( Host_ID 全部为 1 ) 不可用来作为网段内主机的 IP 设定，也就是说，这个网段内可用来设定主机的 IP 是由 192.168.0.1 到 192.168.0.254；

  • 在同一个网域之内，每一部主机都可以透过 MAC 讯框的格式传递资料， 并透过 ARP 协定与广播封包 (broadcast) 取得 MAC 与 IP 的对应后，直接利用 MAC 讯框传递资料。

  • 在同一个物理网段之内，如果两部主机设定成不同的 IP 网段，则两部主机无法直接以 MAC 讯框格式进行资料的传递，因为广播封包无法查询到 MAC 与 IP 的对应。

  • 当 Host_ID 所占用的位元越大，亦即 Host_ID 数量越多时，表示同一个网域内可用以设定主机的 IP 数量越多。
所以说，贵单位公司内的电脑群，或者是您宿舍或家里面的所有电脑，当然都设定在同一个网域内是最方便的， 因为如此一来每一部电脑都可以直接透过 MAC 来进行资料的交流，而不必经由 Router ( 路由器 ) 来进行封包的转递呢！( Router 这部份在后续才会提及！ )。

IP 的分级
好了，现在我们知道 Net_ID 越大时，表示 Host_ID 越少，亦即网域内可以分配的 IP 数量就越少了！ 咦！这表示 Net_ID 是有分级的喔！是啊！没错～刚刚上面那个 192.168.0.0~192.168.0.255 称为 Class C， 那还有哪些等级啊？目前 Internet 将 IP 简单的分类成为三种常见的等级，亦即所谓的 A, B, C class， 他们代表的意义如下：
以二进位说明 Network 第一个数字的定义：
A Class : 0xxxxxxx.xxxxxxxx.xxxxxxxx.xxxxxxxx  ==> NetI_D 的开头是 0
          |--net--|---------host------------|
B Class : 10xxxxxx.xxxxxxxx.xxxxxxxx.xxxxxxxx  ==> NetI_D 的开头是 10
          |------net-------|------host------|
C Class : 110xxxxx.xxxxxxxx.xxxxxxxx.xxxxxxxx  ==> NetI_D 的开头是 110
          |-----------net-----------|-host--|

三种分级在十进位的表示：
A Class :   0.xx.xx.xx ~ 126.xx.xx.xx
B Class : 128.xx.xx.xx ~ 191.xx.xx.xx
C Class : 192.xx.xx.xx ~ 223.xx.xx.xx
在上表中，可能您会觉得很奇怪，咦！那个 127.xx.xx.xx 怎么不见了？！他应该也是 A Class 的一段吧？！没错，是不见了， 因为这个网段被拿去给作业系统做为内部回圈网路 ( loopback ) 之用了！在各个作业系统当中，不管该主机的硬体有没有网路卡， 为了让作业确认自己的网路没有问题，所以将 127.xx.xx.xx 这个 A Class 的网段拿到作业系统当中，来做为内部的回路测试！所以啦，这个 127.0.0.1 就不可以用来做为其他网路卡的网路网域之设定喔。

小标题的图示 Netmask 的用途与子网路的切分
在上一小节当中提到的 A, B, C 三个层级的网域是由 IP 协定预设分配的，在这样的层级当中，我们可以发现 A Class 可以用于设定电脑主机的 IP 数量 ( Host ) 真的是很多，在同一个 A Class 的网域内，主机的数量可以达到‘ 256 X 256 X 256 - 2(Host_ID 全为 0 或 1 ) = 16777214’，不过， 这样的设定情况对于一般网路的效能却是不太好的！为什么呢？

让我们回到前面乙太网路的 MAC 运作模式那个小节，我们知道在共享媒体上面， 每当任何一部主机想要使用该网路媒体时，就得要利用 CSMA/CD 的方式去进行网路监听的工作，此时对于这么大的一个网路架构来说，每部主机要发出 MAC 讯框前要进行的这个 CSMA/CD 实在会造成系统上面很严重的停顿问题啊！ 因为封包碰撞 (collision) 以及在进行 MAC 与 IP 对应的广播 (broadcast) 时， 要回应的主机数量也真是太多了点吧！ 如此一来，整个网路的效能将会变的很糟糕！所以，一般来说，我们最多都仅设定 C Class 做为整个区域网路的架构，其实就连 C Class 也都太大了！不过不打紧，只要记得一个网域内不要超过 30 部以上的主机数量，那样网路的效能就会比较好一点～

其实，除了 C Class 之外，我们还是可以继续将网路切的更细的！上个小节我们提到 IP 这个 32 bits 的数值中分为 Net_ID 与 Host_ID，其中 C Class 的 Net_ID 占了 24 bits ，而其实我们还可以将这样的网域切的更细，就是让第一个 Host_ID 被拿来作为 Net_ID ，所以，整个 Net_ID 就有 25 bits ，至于 Host_ID 则减少为 7 bits 。在这样的情况下，原来的一个 C Class 的网域就可以被切分为两个子网域，而每个子网域就有‘ 256/2 - 2 = 126 ’个可用的 IP 了！这样一来，在这个网域当中的主机在进行逻辑广播时，回应的主机数量就少了一半， 当然对于网路的效能多多少少有点好处的啦！

好了，知道了子网路切分的大致情况后，现在要谈的是，那么到底是什么参数来达成子网路的切分呢？呵呵！那就是 Netmask ( 子网路遮罩 ) 的用途啦！这个 Netmask 是用来定义出网域的最重要的一个参数了！不过他也最难理解了～ @_@。为了帮助大家比较容易记忆住 Netmask 的设定依据，底下我们介绍一个比较容易记忆的方法。同样以 192.168.0.0~192.168.0.255 这个网域为范例好了，如下所示，这个 IP 网段可以分为 Net_ID 与 Host_ID，既然 Net_ID 是不可变的，那就假设他所占据的 bits 已经被用光了 ( 全部为 1 )，而 Host_ID 是可变的，就将他想成是保留着 ( 全部为 0 )，所以， Netmask 的表示就成为：
192.168.0.0~192.168.0.255 这个 C Class 的 Netmask 说明
11000000.10101000.00000000.00000000
11000000.10101000.00000000.11111111
|----------Net_ID---------|-host--|
11111111.11111111.11111111.00000000  <== Netmask 二进位
  255   .  255   .  255   .   0      <== Netmask 十进位
将他转成十进位的话，就成为‘255.255.255.0’啦！ 这样记忆简单多了吧！照这样的记忆方法，那么 A, B, C Class 的 Netmask 表示就成为这样：
Class A, B, C 三个等级的 Netmask 表示方式：
A Class : 11111111.00000000.00000000.00000000 ==> 255.  0.  0.  0
B Class : 11111111.11111111.00000000.00000000 ==> 255.255.  0.  0
C Class : 11111111.11111111.11111111.00000000 ==> 255.255.255.  0
所以说， 192.168.0.0~192.168.0.255 这个 C Class 的网域中，他的 Netmask 就是 255.255.255.0 了！再来，我们刚刚提到了当 Host_ID 全部为 0 以及全部为 1 的时后该 IP 是不可以使用的，因为 Host_ID 全部为 0 的时后，表示 IP 是该网段的 Network ，至于全部为 1 的时后就表示该网段最后一个 IP ，也称为 Broadcast ，所以说，在 192.168.0.0 ~ 192.168.0.255 这个 IP 网段里面的相关网路参数就有：
Netmask:   255.255.255.0   <==网域定义中，最重要的参数
Network:   192.168.0.0     <==第一个 IP
Broadcast: 192.168.0.255   <==最后一个 IP
可用以设定成为主机的 IP 数：
192.168.0.1 ~ 192.168.0.254
一般来说，如果我们知道了 Network 以及 Netmask 之后，就可以定义出该网域的所有 IP 了！因为由 Netmask 就可以推算出来 Broadcast 的 IP 啊！因此，我们常常会以 Network 以及 Netmask 来表示一个网域，例如这样的写法：
Network/Netmask
192.168.0.0/255.255.255.0
192.168.0.0/24    <==因为 Net_ID 共有 24 个 bits
另外，既然 Netmask 里面的 Net_ID 都是 1 ，那么 C Class 共有 24 bits 的 Net_ID ，所以啦，就有类似上面 192.168.0.0/24 这样的写法啰！这就是一般网域的表示方法。好了，刚刚提到 C Class 还可以继续进行子网域 ( Subnet ) 的切分啊，以 192.168.0.0/24 这个情况为例，他要如何再细分为两个子网域呢？我们已经知道 Host_ID 可以拿来当作 Net_ID，那么 Net_ID 使用了 25 bits 时，就会如下所示：
原本的 C Class 的 Net_ID 与 Host_ID 的分别
11000000.10101000.00000000.00000000      Network:   192.168.0.0
11000000.10101000.00000000.11111111      Broadcast: 192.168.0.255
|----------Net_ID---------|-host--|

切成两个子网路之后的 Net_ID 与 Host_ID 为何？
11000000.10101000.00000000.0 0000000  多了一个 Net_ID 了, 为0
11000000.10101000.00000000.1 0000000  多了一个 Net_ID 了, 为1
|----------Net_ID-----------|-host--|

第一个子网路
Network:   11000000.10101000.00000000.0 0000000   192.168.0.0
Broadcast: 11000000.10101000.00000000.0 1111111   192.168.0.127
           |----------Net_ID-----------|-host-|
Netmask:   11111111.11111111.11111111.1 0000000   255.255.255.128
所有 IP 与网域表示式：
192.168.0.0/25 或 192.168.0.0/255.255.255.128

第二个子网路
Network:   11000000.10101000.00000000.1 0000000   192.168.0.128
Broadcast: 11000000.10101000.00000000.1 1111111   192.168.0.255
           |----------Net_ID-----------|-host-|
Netmask:   11111111.11111111.11111111.1 0000000   255.255.255.128
所有 IP 与网域表示式：
192.168.0.128/25 或 192.168.0.128/255.255.255.128
所以说，当再细分下去时，就会得到两个子网域，而两个子网域还可以再细分下去喔 (Net_ID 用掉 26 bits ....)。呵呵！如果您真的能够理解 IP, Network, Broadcast, Netmask 的话，恭喜您，未来的伺服器学习之路已经顺畅了一半啦！ ^_^

例题二：请试着计算出 172.16.0.0/23 这个网域的 Netmask, Network, Broadcast 等参数

答：
    由于 172.16.xxx.xxx 是在 Class B 的等级当中，亦即 172.16.0.0/16 才对。不过题目中询问的是 172.16.0.0/23， 等于是向 Host_ID 借了 7 个 bits 用在 Net_ID 当中。所以整个 IP 的位址会变成这样：
    预设：       172  .  16    .0000000 0.00000000
          |----Net_ID--------------|--Host---|
Network:     172  .  16    .0000000 0.00000000   172.16.0.0
Broadcast:   172  .  16    .0000000 1.11111111   172.16.1.255
Netmask:  11111111.11111111.1111111 0.00000000   255.255.254.0
     鸟哥在这里有偷懒，因为这个 IP 段的前 16 个 bits 不会被改变，所以并没有计算成二进位( 172.16 )， 真是不好意思啊～至于粗体部分则是代表 host_ID 啊！

小标题的图示 IP 的种类与取得方式
接下来要跟大家谈一谈也是很容易造成大家困扰的一个部分，那就是 IP 的种类！很多朋友常常听到什么‘真实IP, 实体 IP, 虚拟 IP, 假的 IP....’烦都烦死了～其实不要太紧张啦！实际上，在 IPv4 里面就只有两种 IP 的类别，分别是：
  • Public IP : 公共 IP ，经由 INTERNIC 所统一规划的 IP， 有这种 IP 才可以连上 Internet ；

  • Private IP : 私有 IP 或保留 IP，不能直接连上 Internet 的 IP ， 主要用于区域网路内的主机连线规划。
早在 IPv4 规划的时候就担心 IP 会有不足的情况，而且为了应付某些私有网路的网路设定，于是就有了私有 IP ( Private IP ) 的产生了。私有 IP 也分别在 A, B, C 三个 Class 当中各保留一段作为私有 IP 网段，那就是：
  • A Class：10.0.0.0    - 10.255.255.255
  • B Class：172.16.0.0  - 172.31.255.255
  • C Class：192.168.0.0 - 192.168.255.255
由于这三个 Class 的 IP 是预留使用的，所以并不能直接作为 Internet 上面的连接之用，不然的话，到处都有相同的 IP 啰！那怎么行！网路岂不混乱？所以啰，这三个 IP 网段就只做为内部私有网域的 IP 沟通之用，也就是说，他有底下的几个限制：
  • 私有位址的路由资讯不能对外散播 （就是内部网路咯）；
  • 使用私有位址作为来源或目的地址的封包，不能透过 Internet 来转送 （呵呵！当然啰！不然网路会混乱）；
  • 关于私有位址的参考纪录(如DNS)，只能限于内部网路使用（一样的原理啦！）
这个私有 IP 有什么好处呢？呵呵！由于他的私有路由不能对外直接提供资讯，所以呢， 你的内部网路将不会直接被 Internet 上面的 Cracker 所攻击！但是，你也就无法以私有 IP 来‘直接上网’啰！所以相当适合一些尚未具有 Public IP 的企业内部用来规划其网路之设定之用！否则当你随便指定一些可能是 Public IP 的网段来规划你企业内部的网路设定时，万一哪一天真的连上 Internet 了，那么启不是可能会造成跟 Internet 上面的 Public IP 相同了吗？ 这可不是闹着玩的，要将你原先规划的 IP 网段整个重新调整过呢！哈哈！累死了！

那么万一你又要将这些私有 IP 送上 Internet 呢？呵呵！这个简单，设定一个简单的防火墙加上 NAT ( Network Address Transfer ) 主机设定，你就可以透过 IP 伪装(不要急，这个在后面也会提到！)来使你的私有 IP 的电脑也可以连上 Internet 啰(虽然不是真的直接，但是很像‘直接上网’呢！)

特殊的 loopback IP 网段
好了，那么除了这个预留的 IP 网段的问题之外，还有没有什么其他的怪东西呢？呵呵！ 当然是有啦！不然鸟哥干嘛花时间来唬 XX 呢！？没错，还有一个奇怪的 A Class 的网域，那就是 lo 这个奇怪的网域啦( 注意：是小写的 o 而不是零喔！ )这个 lo 的网路是当初被用来作为测试作业系统内部回圈所用的一个网域， 同时也能够提供给系统内部原本就需要使用网路介面的服务(daemon)所使用。

简单的说，如果你没有安装网路卡在的机器上面， 但是你又希望可以测试一下在你的机器上面设定的伺服器环境到底可不可以顺利运作，这个时候怎么办， 嘿嘿！就是利用这个所谓的内部回圈网路啦！这个网段在 127.0.0.0/8 这个 A Class ，而且预设的主机 ( localhost ) 的 IP 是 127.0.0.1 呦！所以啰，当你启动了你的 WWW 伺服器，然后在你的主机的 X-Window 上面执行 http://localhost 就可以直接看到你的主页啰！而且不需要安装网路卡呢！测试很方便吧！

此外，你的内部使用的 mail 怎么运送邮件呢？例如你的主机系统如何 mail 给 root 这个人呢？嘿嘿！也就是使用这一个内部回圈啦！当要测试你的 TCP/IP 封包与状态是否正常时，可以使用这个呦！( 所以哪一天有人问你嘿！你的主机上面没有网路卡， 那么你可以测试你的 WWW 伺服器设定是否正确吗？这个时候可得回答：当然可以啰！使用 127.0.0.1 这个 Address 呀！ ^_^... )

IP 的取得方式
谈完了 IP 的种类与等级还有相关的子网域概念后，接下来我们得来了解一下，那么主机的 IP 是如何设定的呢？ 基本上，主机的 IP 与相关网域的设定方式主要有：
  • 固定制手动设定(static)： 我们可以取得固定的 Public IP ，取得的管道可以是学术网路、或者是向 ISP 注册固定的 Public IP。不过，在使用固定的 Public IP 时，你必须要手动的在你的作业系统设定好网路参数；

  • 宽频拨接制(ADSL)： 除了上述的方法之外，传统的以数据机拨接，以及目前很流行的 ADSL 拨接，都是另一个取得 Public IP 的方法。 早期的拨接制 ADSL 所取得的 IP 通常是由 ISP 随机提供，因此每次拨接所取得的 IP 可能都不固定， 所以也有人称这种取得 IP 的方式为浮动式 IP 取得方式。不过近来由于个人用户架站风行， 为因应用户的需求，某些 ISP 也提供很多不同的 IP 分配机制。 包括 hinet, seednet 等等都有提供 ADSL 拨接后取得固定 IP 的方式喔！ 详情请向您的 ISP 洽询。

  • 缆线(Cable modem)： 利用单向或者是双向 Cable 也可以向 ISP 注册取得 Public IP；
请记得，IP 就只有 Public 与 Private IP 这两种，而由于取得 IP 的方法不同，可能又有人喜欢宣称浮动式、固定制、动态等等的 IP ， 这很容易造成刚刚接触网路的朋友们的困扰！所以这里仅告诉大家记得‘Public 与 Private IP’而已！你只要记得他就对了！其他的，以后自然就会理解的啦！^_^
小标题的图示 IP 封包的表头
现在我们知道 IP 这个资料封包 (packet) 是需要放置在 MAC 讯框里面的，所以当然不能比 MAC 所能容许的最大资料量还大！但是 IP 封包其实可以到 65535 bytes 那么大的呐！ 那么 IP 封包除了资料之外，他的表头资料 (head) 是长怎样呢？ 在图三的 MAC 讯框表头里面最重要的莫过于那个网路卡硬体位址， 那么在 IP 表头里面当然就以来源与目标的 IP 位址为最重要啰！ 除此之外， IP 表头里面还含有哪些重要资料呢？如底下所示：(下图第一行为每个栏位的 bit 数)

4 bits 4 bits 8 bits 3 bits 13 bits
Version | IHL | Type of Service | Total Length
Identification |  |  | Flags | Fragmentation Offset
Time To Live |  | Protocol | Header Checksum
Source Address
Destination Address
Options |  |  |  | Padding
Data
图八、IP 封包的表头资料

在上面的图示中有个地方要注意，那就是‘每一行所占用的位元数为 32 bits’， 也就是说， IP 封包的表头资料是 32 bits 的倍数喔！那各个表头的内容分别介绍如下：
  • Version(版本)
    宣告这个 IP 封包的版本，例如目前惯用的还是 IPv4 这个版本，在这里宣告的。

  • IHL(Internet Header Length, IP表头的长度)
    告知这个 IP 封包的表头长度，使用的单位应该是字组 (word) ，一个字组为 4bytes 大小喔。

  • Type of Service(服务类型)
    这个项目的内容为‘PPPDTRUU’，表示这个 IP 封包的服务类型，主要分为：
    PPP：表示此 IP 封包的优先度； D：若为 0 表示一般延迟(delay)，若为 1 表示为低延迟；
    T：若为 0 表示为一般传输量 (throughput)，若为 1 表示为高传输量；
    R：若为 0 表示为一般可靠度(reliability)，若为 1 表示高可靠度。
    UU：保留尚未被使用。
    我们前面谈到 gigabit 乙太网路时曾提到 Jumbo frame 对吧！可以提高 MTU， 由于 gigabit 乙太网路的种种相关规格可以让这个 IP 封包加速且降低延迟， 某些特殊的标志就是在这里说明的。

  • Total Length(总长度)
    指这个 IP 封包的总容量，包括表头与内容 (Data) 部分。最大可达 65535 bytes。

  • Identification(辨别码)
    我们前面提到 IP 袋子必须要放在 MAC 袋子当中。不过，如果 IP 袋子太大的话， 就得先要将 IP 再重组成较小的袋子然后再放到 MAC 当中。而当 IP 被重组时， 每个来自同一笔资料的小 IP 就得要有个识别码以告知接收端这些小 IP 其实是来自同一个封包才行。 也就是说，假如 IP 封包其实是 65536 那么大 (前一个 Total Length 有规定)， 那么这个 IP 就得要再被分成更小的 IP 分段后才能塞进 MAC 讯框中。那么每个小 IP 分段是否来自同一个 IP 资料，呵呵！这里就是那个识别码啦！

  • Flags(特殊旗标)
    这个地方的内容为‘0DM’，其意义为：
    D：若为 0 表示可以分段，若为 1 表示不可分段
    M：若为 0 表示此 IP 为最后分段，若为 1 表示非最后分段。

  • Fragment Offset(分段偏移)
    表示目前这个 IP 分段在原始的 IP 封包中所占的位置。 就有点像是序号啦，有这个序号才能将所有的小 IP 分段组合成为原本的 IP 封包大小嘛！ 透过 Total Length, Identification, Flags 以及这个 Fragment Offset 就能够将小 IP 分段在收受端组合起来啰！

  • Time To Live(TTL, 存活时间)
    表示这个 IP 封包的存活时间，范围为 0-255。当这个 IP 封包通过一个路由器时， TTL 就会减一，当 TTL 为 0 时，这个封包将会被直接丢弃。说实在的，要让 IP 封包通过 255 个路由器，还挺难的～ ^_^

  • Protocol Number(协定代码)
    由于网路上面的封包协定太多了，每个协定都是装在 IP 当中的， 所以 IP 当然就得在表头上面告知收受端，这个 IP 内含有的资料是什么协定才行。 一般常见的网路协定如下所示：
    IP 内的号码 | 协定名称(全名)
    1 | ICMP (Internet Control Message Protocol)
    2 | IGMP (Internet Group Management Protocol)
    3 | GGP (Gateway-to-Gateway Protocol)
    4 | IP (IP in IP encapsulation)
    6 | TCP (Transmission Control Protocol)
    8 | EGP (Exterior Gateway Protocol)
    17 | UDP (User Datagram Protocol)
    当然啦，我们比较常见到的还是那个 TCP, UDP, ICMP 说！

  • Header Checksum(表头检查码)
    用来检查这个 IP 表头的错误检验之用。

  • Source Address
    还用讲吗？当然是来源的 IP 位址，相关的 IP 我们之前提过啰！

  • Destination Address
    有来源还需要有目标才能传送，这里就是目标的 IP 位址。

  • Options (其他参数)
    这个是额外的功能，提供包括安全处理机制、路由纪录、时间戳记、 严格与宽松之来源路由等。

  • Padding(补齐项目)
    由于 Options 的内容不一定有多大，但是我们知道 IP 每个资料都必须要是 32 bits， 所以，若 Options 的资料不足 32 bits 时，则由 padding 主动补齐。

你只要知道 IP 表头里面还含有： TTL, Protocol, 来源 IP 与目标 IP 也就够了！ 而这个 IP 表头的来源与目标 IP ，以及那个判断通过多少路由器的 TTL ，就能了解到这个 IP 将被如何传送到目的端呐。下一节我们将介绍一下那么 IP 封包是如何被传送到目的地？
大标题的图示 网路层之路由概念
我们在前面两个小节提到了乙太网路在物理网段内可以使用 MAC 的讯框资料直接在两张网路卡之间传递资料， 那在前一节提到的 IP 相关概念里面，也知道在 Internet 的环境中，同一个网域 (Net_ID 相同的网段) 内可以直接使用广播的方式以 ARP 协定来取得 IP 与 MAC 的对应，好让我们的资料可以在同一个网域内进行传输。 好了，那问题来了，如果我想要向非同一个网域的主机要求资料呢？这个时候封包要如何传递？ 呵呵～这可就需要路由(route)的帮忙啦！这个也是在网路层 (Layer 3) 里面的重要概念喔！

小标题的图示 什么是路由
什么是‘非同一个网域’呢？刚刚上一小节提到的 IP 应该还没有忘记吧？ 所谓的非同一个网域就是 Network/Netmask 不在同一个位址， 也就是两部主机间的 Net_ID 不相同的意思。例如参考底下的练习：

例题三：请问 192.168.10.100/25 与 192.168.10.200/25 是否在同一个网域内？

答：
    如果经过计算，会发现 192.168.10.100 的 Network 为 192.168.10.0 ，但是 192.168.10.200 的 Network 却是 192.168.10.128，由于 Net_ID 不相同，所以当然不在同一个网段内！ 关于 Network 与 Netmask 的算法则请参考上一小节。

那么万一两部不在同一个网段内的主机想要互通资讯时，该如何做？ 此时就得要经过 IP 的路径选择 (routing) 功能啦！我们以下面图示的例子来做说明。 下列图示当中共有两个不同的网段，分别是 Network A 与 Network B，这两个网段是经由一部路由器 (Server A) 来进行资料转递的，好了，那么当 PC01 这部主机想要传送资料到 PC11 时， 他的 IP 封包该如何传输呢？
简易的路由示意图
图九、简易的路由示意图

我们知道 Network A(192.168.0.0/24) 与 Network B(192.168.1.0/24) 是不同网段， 所以 PC01 与 PC11 是不能互通资料的。不过， PC01 与 PC11 是如何知道他们两个不在同一个网段内？ 呵呵！这当然是透过 Net_ID 来发现的！那么当主机想要传送资料时，他主要的参考是啥？ 很简单！是‘路由表 (route table)’，每部主机都有自己的路由表’， 让我们来看一看预设的情况下， PC01 要如何将资料传送到 PC02 呢？
  1. 当 PC01 有 IP 封包需要传送时，主机会查阅 IP 封包表头的目标 IP 位址；

  2. PC01 主机会分析自己的路由表，当发现目标 IP 与本机 IP 的 Net_ID 相同时(同一网域)， 则 PC01 会参考本身的 ARP 记录，而直接利用 MAC 来互相传递资讯。

  3. 但在本案例中， PC01 与 PC11 并非同一网域，因此 PC01 会分析路由表当中是否有相符合的路由设定， 如果没有的话，就直接将该 IP 封包送到预设路由器 (default gateway) 上头去， 在本案例当中 default gateway 则是 Server A 这一部。

  4. 当 IP 封包被送至 Server A 之后，Server A 同样分析该 IP 封包的目标位址， 然后检查 Server A 自己的路由设定，注意，通常 Server A 这个作为路由器的主机， 都会拥有两个以上的介面来沟通不同的网域的。在这个案例当中， Server A 会发现这个 IP 目标是 192.168.1.11 ，刚好是 Network B 这个相同网段的区域， 因此 Server A 会直接以 MAC 讯框将资料送给 PC11 去。
Tips:
Gateway / Router ：网关/路由器的功能就是在负责不同网域之间的封包转递 ( IP Forwarder )，由于路由器具有 IP Forwarder 的功能，并且具有管理路由的能力， 所以可以将来自不同网域之间的封包进行转递的功能。此外，您的主机与您主机设定的 Gateway 必定是在同一个网段内喔！ 		鸟哥的图示

大致的情况就是这样，所以啦，每一部主机里面都会存在着一个路由表 ( Route table )，资料的传递将依据这个路由表进行传送！而一旦封包已经经由路由表的规则传送出去后， 那么主机本身就已经不再管封包的流向了，因为该封包的流向将是下一个主机 (也就是那部 Router )来进行传送，而 Router 在传送时，也是依据 Router 自己的路由表来判断该封包应该经由哪里传送出去的！例如底下的图例：
路由的概念
图十、路由的概念

PC 01 要将资料送到 Server Bingo 去，则依据自己的路由表，将该封包送到 Server A 去，Server A 再继续送到 Server B ，然后在一个一个的接力给他送下去，最后总是可以到达 Server Bingo 的。

当然，上面的案例是一个很简单的路由概念，事实上， Internet 上面的路由协定与变化是相当复杂的，因为 Internet 上面的路由并不是静态的，他可以随时因为环境的变化而修订每个封包的传送方向。 举例来说，数年前在新竹因为土木施工导致台湾西部整个网路缆线的中断。 不过南北的网路竟然还是能通，为什么呢？因为路由已经判断出西部缆线的终止， 因此他自动的导向台湾东部的花莲路线，虽然如此一来绕了一大圈，而且造成网路的大塞车， 不过封包还是能通就是了！这个例子仅是想告诉大家，我们上面提的路由仅是一个很简单的静态路由情况， 如果想要更深入的了解 route ，请自行参考相关书籍喔！ ^_^ 。

此外，在属于 Public 的 Internet 环境中，由于最早时的 IP 分配都已经配置妥当， 所以各单位的路由一经设定妥当后，上层的路由则无须担心啊！ IP 的分配可以参考底下的网页：
  • 台湾地区 IP 核发情况：http://rms.twnic.net.tw/twnic/User/Member/Search/main7.jsp?Order=inet_aton(Startip)
  • 全球 IPv4 的统计：http://www.twnic.net.tw/ipstats/ipv4stats.htm
小标题的图示 观察主机的路由
既然路由是这么的重要，而且‘路由一旦设定错误， 将会造成某些封包完全无法正确的送出去！’ 所以我们当然需要好好的来观察一下我们主机的路由表啦！还是请再注意一下， 每一部主机都有自己的路由表喔！观察路由表的指令很简单，就是 route ，这个指令挺难的，我们在后面章节再继续的介绍，这里仅说明一些比较简单的用法：
[root@linux ~]# route [-n]
参数：
-n ： 将主机名称以 IP 的方式显示
范例：

[root@linux ~]# route
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref  Use Iface
192.168.0.0     *               255.255.255.0   U     0      0      0 eth0
127.0.0.0       *               255.0.0.0       U     0      0      0 lo
default         192.168.0.254   0.0.0.0         UG    0      0      0 eth0

[root@linux ~]# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref  Use Iface
192.168.0.0     0.0.0.0         255.255.255.0   U     0      0      0 eth0
127.0.0.0       0.0.0.0         255.0.0.0       U     0      0      0 lo
0.0.0.0         192.168.0.254   0.0.0.0         UG    0      0      0 eth0

# 上面输出的资料共有八个栏位，您需要注意的有几个地方：
# Destination ：其实就是 Network 的意思；
# Gateway     ：就是该介面的 Gateway 那个 IP 啦！若为 0.0.0.0 表示不需要额外的 IP；
# Genmask     ：就是 Netmask 啦！与 Destination 组合成为一部主机或网域；
# Flags       ：共有多个旗标可以来表示该网域或主机代表的意义：
#               U：代表该路由可用；
#               G：代表该网域需要经由 Gateway 来帮忙转递；
#               H：代表该行路由为一部主机，而非一整个网域；
# Iface       ：就是 Interface (介面) 的意思。
在上面的例子当中，鸟哥是以 PC 01 这部主机的路由状态来进行说明。由于 PC 01 为 192.168.0.0/24 这个网域，所以主机已经建立了这个网域的路由了，那就是‘ 192.168.0.0 * 255.255.255.0 ... ’那一行所显示的讯息！当您下达 route 时， 荧幕上说明了这部机器上面共有三个路由规则，第一栏为‘目的地的网域’，例如 192.168.0.0 就是一个网域咯，最后一栏显示的是 ‘要去到这个目的地要使用哪一个网路介面！’例如 eth0 就是网路卡的装置代号啦。如果我们要传送的封包在路由规则里面的 192.168.0.0/255.255.255.0 或者 127.0.0.0/255.0.0.0 里面时，因为第二栏 Gateway 为 * ，所以就会直接以后面的网路介面来传送出去，而不透过 Gateway 咯！

万一我们要传送的封包目的地 IP 不在路由规则里面，那么就会将封包传送到‘default’所在的那个路由规则去，也就是 192.168.0.254 那个 Gateway 喔！所以，几乎每一部主机都会有一个 default gateway 来帮他们负责所有非网域内的封包转递！这是很重要的概念喔！^_^！ 关于更多的路由功能与设定方法，我们在后面的‘简易 Router 架设’ 当中会再次的提及呢！

大标题的图示 常见的通讯协定
终于给他来到了封包格式的地方了！上面的咚咚大多是在网路最底层的基础知识， 得自行好好的理解理解！第一次看不懂没关系，多看几次，或者是未来有些网路经验后再回来这个章节好好看一看！ 假设您已经知道了网路最底层的 IP 以及相关的参数的意义，那么应该知道的是， 网路层的协定只是提供路由的判断以确定封包的传送路径， 但是这些协定并没有管理可能由于网路媒体的损坏问题，或者是网路的负荷过重以及其他不可预期的情况， 而造成封包损毁或者被丢弃的状态。为了使封包的传送过程中更具有稳定性与可靠性， 我们就得提供一套机制来让资料可以没有错误的到达到目的地。

在 TCP/IP 这个协定组合当中，TCP ( Transmission Control Protocol ) 就是用来做为传送的一个协定，当然啦，还有一个 UDP 的协定呢！在 TCP 这个协定当中， 他提供了较为稳定而且可靠的连线状态，至于 UDP 则是一个比较没有这么可靠的连线型态了。 除了这个 TCP 与 UDP 之外，其他相关的网路协定请参考前一小节 IP 封包内的 Protocol 说明。 底下我们就来分别谈一谈重要的 TCP/UDP/ICMP 吧！

小标题的图示 TCP 协定
在前几个小节内谈到的 IP 与路由的相关说明中，我们知道 IP 与路由仅能将资料封包传送到正确的目标而已， 但是这个目的地是否真的能够收下来这个封包？那可就不一定了。要确认该资料能否正确的被目的端所接收， 就必须要在资料封包上面多加一些参数来判断才行。

在前面的 OSI 七层协定当中，在网路层的 IP 之上则是传送层，而传送层的资料打包成什么？ 最常见的就是 TCP 封包了。这个 TCP 封包资料必须要能够放到 IP 的资料袋当中才行喔！ 所以，我们可以将 MAC, IP 与 TCP 的封包资料这样看：
各封包之间的相关性
图十一、各封包之间的相关性

所以说，IP 除了表头之外的 Data 内容其实就是 TCP 封包的表头与内容；而 MAC 的 Data 内容， 就是一个完整的 IP 封包资料！这也是我们上头提到的，最终还是得以 MAC 能够支援的最大容许容量， 才能够决定 IP 与 TCP 封包是否需要再进行分段的工作。那么既然 MAC 与 IP 都有表头资料， 想当然尔，TCP 也有表头资料来记录该封包的相关资讯啰？？没错啦～ TCP 封包的表头是长这个样子的：

4 bits 6 bits 6 bits 8 bits 8 bits
Source Port |  |  | Destination Port
Sequence Number
Acknowledge Number
Data Offset | Reserved | Code | Window
Checksum |  |  | Urgent Pointer
Options |  |  | Padding
Data
图十二、TCP 封包的表头资料

上图就是一个 TCP 封包的表头资料，各个项目以 Source Port, Destination Port 及 Code 算是比较重要的项目，底下我们就分别来谈一谈各个表头资料的内容吧！
  • Source Port & Destination Port ( 来源埠口 & 目标埠口 )
    什么是埠口(port)？我们知道 IP 封包的传送主要是藉由 IP 位址连接两端， 但是到底这个连线的通道是连接到哪里去呢？没错！就是连接到 port 上头啦！ 举例来说，鸟站 (http://linux.vbird.org) 有开放 WWW 伺服器， 这表示鸟站的主机必须要启动一个可以让 client 端连接的端口，这个端口就是 port ， 中文翻译成为埠口。同样的，用户端想要连接到鸟哥的鸟站时，就必须要在 client 主机上面启动一个 port ，这样这两个主机才能够利用这条‘通道’来传递封包资料喔！ 这个目标与来源 port 的纪录，可以说是 TCP 封包上最重要的参数了！ 下个小单元我们还会继续介绍。

  • Sequence Number ( 封包序号 )
    由于 TCP 封包必须要带入 IP 封包当中，所以如果 TCP 资料太大时(大于 IP 封包的容许程度)， 就得要进行分段。这个 Sequence Number 就是记录每个封包的序号， 可以让收受端重新将 TCP 的资料组合起来。

  • Acknowledge Number ( 回应序号 )
    为了确认主机端确实有收到我们 client 端所送出的封包资料，我们 client 端当然希望能够收到主机方面的回应，那就是这个 Acknowledge Number 的用途了。 当 client 端收到这个确认码时，就能够确定之前传递的封包已经被正确的收下了。

  • Data Offset (资料补偿)
    在图十二倒数第二行有个 Options 栏位对吧！那个 Options 的栏位长度是非固定的， 而为了要确认整个 TCP 封包的大小，就需要这个标志来说明整个封包区段的起始位置。

  • Reserved (保留)
    未使用的保留栏位。

  • Code (Control Flag, 控制标志码)
    当我们在进行网路连线的时候，必须要说明这个连线的状态，好让接收端了解这个封包的主要动作。 这可是一个非常重要的控制码喔！这个栏位共有 6 个 bits ，分别代表 6 个控制码，若为 1 则为启动。分别说明如下：

    • URG(Urgent)：若为 1 则代表该封包为紧急封包， 接收端应该要紧急处理，且图十二当中的 Urgent Pointer 栏位也会被启用。

    • ACK(Acknowledge)：若为 1 代表这个封包为回应封包， 则与上面提到的 Acknowledge Number 有关。

    • PSH(Push function)：若为 1 时， 代表要求对方立即传送缓冲区内的其他对应封包，而无须等待缓冲区满了才送。

    • RST(Reset)：如果 RST 为 1 的时候， 表示连线会被马上结束，而无需等待终止确认手续。这也就是说，这是个强制结束的连线， 且发送端已断线。

    • SYN(Synchronous)：若为 1 ， 表示发送端希望双方建立同步处理，也就是要求建立连线。通常带有 SYN 标志的封包表示‘主动’要连接到对方的意思。

    • FIN(Finish)：若为 1 ，表示传送结束， 所以通知对方资料传毕，是否同意断线，只是发送者还在等待对方的回应而已。

    其中比较常见到的应该是 ACK/SYN/FIN 等，这三个控制码是务必要记下来的， 这样未来在谈到防火墙的时候，您才会比较清楚为啥每个 TCP 封包都有所谓的‘状态’条件！ 那就是因为连线方向的不同所致啊！底下我们会进一步讨论喔！

  • Window (滑动视窗)
    主要是用来控制封包的流量的，可以告知对方目前本身有的缓冲器容量(Receive Buffer) 还可以接收封包。当 Window=0 时，代表缓冲器已经额满，所以应该要暂停传输资料。 Window 的单位是 byte。

  • Checksum(确认检查码)
    当资料要由发送端送出前，会进行一个检验的动作，并将该动作的检验值标注在这个栏位上； 而接收者收到这个封包之后，会再次的对封包进行验证，并且比对原发送的 Checksum 值是否相符，如果相符就接受，若不符就会假设该封包已经损毁，进而要求对方重新发送此封包！

  • Urgent Pointer(紧急资料)
    这个栏位是在 Code 栏位内的 URG = 1 时才会产生作用。可以告知紧急资料所在的位置。

  • Options(任意资料)
    目前此栏位仅应用于表示接收端可以接收的最大资料区段容量，若此栏位不使用， 表示可以使用任意资料区段的大小。这个栏位较少使用。

  • Padding(补足栏位)
    如同 IP 封包需要有固定的 32bits 表头一样， Options 由于栏位为非固定， 所以也需要 Padding 栏位来加以补齐才行。同样也是 32 bits 的整数。

通讯埠口与 Socket
在刚刚上头提到的 TCP 表头资料后，您大概也清楚了要建立一个 TCP 封包时所需要检验的相关参数可不少啊！其中最重要的就属通讯埠口 (port) 了。 这个 port 主要是由主机的程式所触发的，网路上面的其他 client 端， 可以通过这个埠口直接与启动该 port 的程式相互沟通， 而达到资料传输的目的。我们都知道二进位程式 (binary program) 才是真的主机认识的程式指令， 那么我们要启动网路服务时，其实也就是启动一个 program 就是了。但是网路上面如何与您的 program 互通资料呢？就是透过在网路介面上面的 port 来达成的啦。

不过，必须要注意的是 port 的沟通是双向的， 举例来说，当我们要使用浏览器连接到奇摩雅虎查阅资料时， 我们必须要使用 client 端主机的浏览器连接到 Yahoo 主机的 WWW 伺服器软体上面。 由于是透过网路介面，所以我们的浏览器也必须要启动一个 port 并且透过这个 port 连接到 Yahoo 主机的 WWW port 上头去，然后透过 TCP 封包上头各项参数的确认后， 才能够建立连线，并进一步开始传输资料啊！

现在来想一想，我们的主机上面有多少网路介面的 port 可用呢？ 基本上就有 65536 (216)。那我们连线到 Yahoo 时， 是连线到 Yahoo 主机的那个 port 啊？如果不知道几号 port ，那又该如何建立起这个连线呢？ 所以啰，Internet 上面已经有很多规范好的固定 port (well-known port) 在提供使用者建立伺服器时启用的 port number 啦。这些 port number 通常小于 1024 ， 且是提供给许多知名的网路服务软体用的。在我们的 Linux 环境下， 各网路服务与 port number 的对应预设给他写在 /etc/services 档案内喔！ 不过如果是 client 端的话，由于 client 端都是主动向 server 端要资料， 所以 client 端的 port number 就使用随机取一个大于 1024 以上且没有在用的 port number 来进行连线了。底下鸟哥列出几个常见的 port number 与网路服务的对应：

连接埠口 | 服务名称与内容
20 | FTP-data，档案传输协定所使用的主动资料传输埠口
21 | FTP，档案传输协定的命令通道
22 | SSH，较为安全的远端连线伺服器
23 | Telnet，早期的远端连线伺服器软体
25 | SMTP，简单邮件传递协定，用在作为 mail server 的埠口
53 | DNS，用在作为名称解析的领域名称伺服器
80 | WWW，这个重要吧！就是全球资讯网伺服器
110 | POP3，邮件收信协定，办公室用的收信软体都是透过他
443 | https，有安全加密机制的WWW伺服器

另外一点比较值得注意的是，小于 1023 以下的埠口要启动时， 启动者的身份必须要是 root 才行！这个限制挺重要的，大家不要忘记了喔！

曾经有一个朋友问过我说：‘一部主机上面这么多服务，那我们跟这部主机进行连线时， 该主机怎么知道我们要的资料是 WWW 还是 FTP 啊？！’呵呵！这就是 port 的不同的结果啦！因为每种 Client 软体他们所需要的资料都不相同，例如上面提到的浏览器( Netscape 以及 IE ) 他们所需要的资料是 WWW ，所以该软体预设就会向主机的 80 port 索求资料；而如果您是使用 cuteftp 来进行与主机的 FTP 资料索求时， cuteftp 这个 Client 软体当然预设就是向主机的 FTP 相关埠口 ( 预设就是 port 21 ) 进行连接的动作啦！所以当然就可以正确无误的取得 Client 端所需要的资料了

举个例子来说，一部主机就好像是一间多功能银行，该银行内的每个负责不同业务的窗口就好像是通讯埠口， 而我们民众就好像是 Client 端来的封包。当您进入银行想要缴纳信用卡帐单时， 一到门口服务人员就会指示您直接到该窗口去缴纳，当然，如果您是要领钱，服务人员就会请您到领钱的窗口去填写资料， 您是不会跑错的对吧！ ^_^。万一跑错了怎么办？呵呵！当然该窗口就会告诉您‘我不负责这个业务，您请回去！’， 呵呵！所以该次的连线就会‘无法成功’咯！

谈过了通讯埠口后，再来聊一聊每个封包的基本内容有哪些资料呢？这就得要谈论到 Socket Pair ( 成对的端口 )了！ 当本机发送出封包时，主机是根据 IP 封包内的 IP 位址来判别来源与目的地的行进路线， 并且，也需要 TCP 封包内的 port number 来告知 Client 与 Server 是以哪一个埠口来进行连线的对吧！ 所以呢，一个连线过程所包含的底下这些咚咚就称为成对插槽 (socket pair) 了：
  • 来源 IP ( Source Address )
  • 目的 IP ( Destination Address )
  • 来源埠口 ( Source Port )
  • 目的埠口 ( Destination Port )
这四个封包的基本资讯是相当重要的！您得必须要了解喔！

封包的传送
OK，从前面这样一路看下来，相信您对于 OSI 七层协定当中的 MAC 讯框与 IP 封包有一定程度的了解了， 也知道七层协定必须要在不同的主机之间一再地拿出来察看，因为 Internet 是用 IP 来传递封包资料， 而实体线路则是使用 MAC 讯框。那我们也了解 TCP 封包的表头资料后，再来就是要了解一下， 那我如何利用 TCP 这个传送层的协定来进行实际的封包接收呢？ 当然是得要透过 TCP 表头的 Sequence Number 来组合收集大的 TCP 封包， 也必须要透过 Code (Control Flags) 来了解到这个封包的特性才行。 说穿了，我们可以使用信封袋来说明，实际的内容 (data) 是在信封袋当中的， 而信封的外面的资讯就是各个封包的表头资料啦！

那么如何藉由 TCP 的表头来确认这个封包有实际被对方接收，并进一部与对方主机达成连线？ 我们以底下的图示来作为说明。

三向交握之封包连接模式
图十三、封包连接模式之三向交握

在上面的封包连接模式当中，在建立连线之前都必须要通过三个确认的动作， 所以这种连线方式也就被称为三向交握(Three-way handshake)。 那么我们将整个流程依据上面的 A, B, C, D 四个阶段来说明一下：
  • A:封包发起
    当用户端想要对伺服器端连线时，就必须要送出一个要求连线的封包， 此时用户端必须随机取用一个大于 1024 以上的埠口来做为程式沟通的介面。 然后在 TCP 的表头当中，必须要带有 SYN 的主动连线(SYN=1)，并且记下发送出连线封包给伺服器端的序号 (Sequence number = 10001 ) 。

  • B:封包接收与确认封包传送
    当伺服器接到这个封包，并且确定要接收这个封包后，就会开始制作一个同时带有 SYN=1, ACK=1 的封包， 其中那个 acknowledge 的号码是要给 client 端确认用的，所以该数字会比(A 步骤)里面的 Sequence 号码多一号 (ack = 10001+1 = 10002)， 那我们伺服器也必须要确认用户端确实可以接收我们的封包才行，所以也会发送出一个 Sequence (seq=20001) 给用户端，并且开始等待用户端给我们伺服器端的回应喔！

  • C:回送确认封包
    当用户端收到来自伺服器端的 ACK 数字后 (10002) 就能够确认之前那个要求封包被正确的收受了， 接下来如果用户端也同意与伺服器端建立连线时，就会再次的发送一个确认封包 (ACK=1) 给伺服器，亦即是 acknowledge = 20001+1 = 20002 啰。

  • D:取得最后确认
    若一切都顺利，在伺服器端收到带有 ACK=1 且 ack=20002 序号的封包后，就能够建立起这次的连线了。
也就是说，你必须要了解‘网路是双向的’这个事实！ 所以不论是伺服器端还是用户端，都必须要透过一次 SYN 与 ACK 来建立连线， 所以总共会进行三次的交谈！ 在设定防火墙或者是追踪网路连线的问题时，这个‘双向’的概念最容易被忽略， 而常常导致无法连线成功的问题啊！切记切记！

在建立了连线之后，该次连线通道就可以在用户端与伺服器端建立起一对 socket pair ， 然后通过该 socket pair 进行 TCP 封包的 PSH、FIN 等资料传输与连线中断等动作啰！
小标题的图示 UDP 协定
UDP 的全名是：‘User Datagram Protocol, 用户资料流协定’，UDP 与 TCP 不一样， UDP 不提供可靠的传输模式，因为他不是连线导向的一个机制，这是因为在 UDP 的传送过程中，接受端在接受到封包之后，不会回覆回应封包 ( ACK ) 给发送端，所以封包并没有像 TCP 封包有较为严密的验证机制。至于 UDP 的表头资料如下表所示：

16 bits 16 bits
Source Port | Destination Port
Message Length | Checksum
Data
图十四、UDP 封包的表头资料

TCP 封包确实是比较可靠的，因为通过三向交握嘛！不过，也由于三向交握的缘故， TCP 封包的传输速度会较慢。 至于 UDP 封包由于不需要确认对方是否有正确的收到资料，故表头资料较少，也因为如此所以 UDP 就可以在 Data 处填入更多的资料了。同时 UDP 比较适合需要即时反应的一些资料流，例如即时通讯软体或者是影像即时传送软体等， 就可以使用这类的封包传送说。也就是说， UDP 传输协定并不考虑连线要求、连线终止与流量控制等特性， 所以使用的时机是当资料的正确性不很重要时，例如上面提到的即时通讯软体啊！

另外，很多的软体其实是同时提供 TCP 与 UDP 的传输协定的，举例来说，查询主机名称的 DNS 服务就同时提供了 UDP/TCP 协定。由于 UDP 较为快速，所以我们 client 端可以先使用 UDP 来与伺服器连线。 但是当使用 UDP 连线却还是无法取得正确的资料时，便转换为较为可靠的 TCP 传输协定来进行资料的传输啰。 这样可以同时兼顾快速与可靠的传输说！

小标题的图示 ICMP 协定
ICMP 的全称是‘ Internet Control Message Protocol, 网际网路讯息控制协定 ’。 基本上，ICMP 是一个错误侦测与回报的机制，最大的功能就是可以确保我们网路的连线状态与连线的正确性！ 同样的，ICMP 封包也是必须要装在 IP 封包的 Data 内才行喔！ 因为在 Internet 上面有传输能力的就是 IP 封包啦！ ICMP 有相当多的类别可以侦测与回报，底下是比较常见的几个 ICMP 的类别 (Type)：

类别代号 | 类别名称与意义
0 | Echo Reply (代表一个回应信息)
3 | Destination Unreachable (表示目的地不可到达)
4 | Source Quench (当 router 的负载过高时，此类别码可用来让发送端停止发送讯息)
5 | Redirect (用来重新导向路由路径的资讯)
8 | Echo Request (请求回应讯息)
11 | Time Exceeded for a Datagram (当资料封包在某些路由传送的现象中造成逾时状态，此类别码可告知来源该封包已被忽略的讯息)
12 | Parameter Problem on a Datagram (当一个 ICMP 封包重复之前的错误时，会回覆来源主机关于参数错误的讯息)
13 | Timestamp Request (要求对方送出时间讯息，用以计算路由时间的差异，以满足同步性协定的要求)
14 | Timestamp Reply (此讯息纯粹是回应 Timestamp Request 用的)
15 | Information Request (在 RARP 协定应用之前，此讯息是用来在开机时取得网路信息)
16 | Information Reply (用以回应 Infromation Request 讯息)
17 | Address Mask Request (这讯息是用来查询子网路 mask 设定信息)
18 | Address Mask Reply (回应子网路 mask 查询讯息的)

那么我们是如何利用 ICMP 来检验网路的状态呢？最简单的指令就是 ping 与 traceroute 了， 这两个指令可以透过 ICMP 封包的辅助来确认与回报网路主机的状态。在设定防火墙的时候， 我们最容易忽略的就是这个 ICMP 的封包了，因为只会记住 TCP/UDP 而已～事实上， ICMP 封包可以帮助连线的状态回报，除了上述的 8 可以考虑关闭之外，基本上， ICMP 封包也不应该全部都挡掉喔！

小标题的图示 MTU 的限制
我们在本章的第一部份谈到 MAC 时，不是有提到标准乙太网路封包的资讯容量大约在 1500bytes 吗？ 所以 IP 封包、TCP 封包以及其他相关的封包，如果能够控制在 1500 bytes 内的话， 那么 IP 封包将不需要重组成可以放进 MAC 讯框的分段了！

让我们来想一个小案例，假设你的资料量大到 60000 bytes 好了，如果你使用的传输协定为 TCP 封包， 万一你没有考虑到 MAC 讯框的大小，而让整笔资料放到可以容纳最大 65535 bytes 的 IP 封包内， 此时 IP 封包已经建立好成为内含 60000 bytes 的资料包了，但是再往下到达资料连接层时，唉～ 这个 IP 封包就得要进行重组，好让 IP 封包可以放到 MAC 讯框当中！您说，这个时候不是又得让系统多进行一段手续， 而导致网路效能的低落吗？

此时，如果能够规范 TCP 以及 IP 在包起来时就考虑讯框的最大容量时， 不就可以减少很多资料重组的问题啰？呵呵呵呵！没错啊！ 那就是最大传输单元 (Maximum Transmission Unit, MTU) 这个设定值的重要性啊！

一般来说，我们的 Gigabit 网路卡已经可以支援 Jumbo frame ，所以 MTU 值都可以到达 9000 bytes 左右， 不过，不建议您设定 MTU 成为 9000 喔！为什么呢？因为我们的封包总是需要在 Internet 上面跑吧？ 您无法确认所有的网路媒体都是支援那么大的 MTU 对吧！ 如果您的 9000 bytes 封包通过一个不支援 Jumbo frame 的网路媒体时， 好一点的是该网路媒体 (例如 router ) 会主动的帮您重组封包而进行传送， 差一点的可能就直接回报这个封包无效而丢弃了～那个时候可就糗大啰～ 所以， MTU 设定为 9000 这种事情，大概仅能在内部网路的环境作作～ 举例来说，很多的内部丛集系统 (cluster) 就将他们的内部网路环境 MTU 设定为 9000， 但是对外的介面卡可还是原本的标准 1500 喔！ ^_^

也就是说，不论您的网路媒体支援 MTU 到多大，您必须要考量到您的封包需要传到目的地时， 所需要经过的所有网路媒体，然后再来决定您的 MTU 设定才行。
Tips:
事实上，MTU 不会刚好等于 1500 呐！这是因为不论是 IP 封包或者是 TCP 封包都会有表头资料， 这些表头资料都会占用去一些位元容量，所以 MTU 就会比标准乙太网路容量的 1500 小一些。 		鸟哥的图示
小标题的图示 封包过滤的防火墙概念
由上面的说明当中，我们知道资料的传送其实就是封包的发出与接受的动作啦！并且不同的封包上面都有不一样的表头 ( header )，此外，封包上面通常都会具有四个基本的资讯，那就是 socket pair 里面提到的‘来源与目的 IP 以及来源与目的端的 port number’ 。当然啦，如果是可靠性连线的 TCP 封包，还包含 Control Flag 里面的 SYN/ACK 等等重要的资讯呢！好了，开始动一动脑筋， 有没有想到‘网路防火墙’的字眼啊？ 网路防火墙可以抵挡掉一些可能有问题的封包，那么在 Linux 系统上面是怎么挡掉封包的呢？其实说来也是很简单，既然封包的表头上面已经有这么多的重要资讯， 那么我就利用一些防火墙机制与软体来进行封包表头的分析，并且设定分析的规则，当发现某些特定的 IP 、特定的埠口或者是特定的封包资讯(SYN/ACK等等)，那么就将该封包给他丢弃， 那就是最基本的防火墙原理了！

举例来说，大家都知道 Telnet 这个伺服器是挺危险的，而 Telnet 使用的 port number 为 23 ，所以，当我们使用软体去分析要送进我们主机的封包时， 只要发现该封包的目的地是我们主机的 port 23 ，就将该封包丢掉去！那就是最基本的防火墙案例啦！ 更多的防火墙资讯我们会在后头的‘简易防火墙’与 ‘认识网路安全’当中进行更多的说明喔！

大标题的图示 连上 Internet 前的准备事项
讲了这么多，其实我们最需要的仅是‘连接上 Internet ’啦！那么在 Internet 上面其实使用的是 TCP/IP 这个通讯协定，所以我们就需要 Public IP 来连接上 Internet 啊！您说对吧～ 不过，您有没有发现一件事，那就是‘为啥我不知道 Yahoo 的主机 IP ，但是俺的主机却可以连到 Yahoo 主机上？’ 如果您有发现这个问题的话，哈哈！您可以准备开始设定网路啰～ ^_^

小标题的图示 什么是主机名称与 DNS
除了上面提到的最基本的网路基础概念之外，这里还必须要先谈一个基本的观念， 否则后续的主机名称查询设定挺难说明白的！好了，我们知道电脑在网路上面要找寻主机的时后，是利用 IP 来定址，而以 TCP/UDP/ICMP 等资料来进行传送的，并且传送的过程中还会去检验封包的资讯。 总归一句话，网路是靠 TCP/IP 家族来达成的，所以必须要知道 IP 之后，电脑才能够连上网路以及传送资料。

问题是，电脑网路是依据人类的需要来建立的，不过人类对于 IP 这一类的数字并不具有敏感性，即使 IP 已经被简化为十进位了，但是人类就是对数字没有办法啊！怎么办？没关系，反正电脑都有主机名称嘛！ 那么我就将主机名称与他的 IP 对应起来，未来要连接上该电脑时，只要知道该电脑的主机名称就好了，因为 IP 已经对应到主机名称了嘛！所以人类也容易记忆文字类的主机名称，电脑也可以藉由对应来找到他必须要知道的 IP ，啊！真是皆大欢喜啊！

这个主机名称 (Hostname) 对应 IP 的系统，就是鼎鼎有名的 Domain Name System (DNS) 咯！也就是说， DNS 这个服务的最大功能就是在进行‘主机名称与该主机的 IP 的对应’的一项协定。 DNS 在网路环境当中是相当常被使用到的一项协定喔！举个例子来说，像鸟哥我常常会连到奇摩雅虎的 WWW 网站去看最新的新闻，那么我一定需要将奇摩雅虎的 WWW 网站的 IP 背下来吗？！天呐， 鸟哥的忘性这么好，怎么可能将 IP 背下来？！不过，如果是要将奇摩站的主机名称背下来的话， 那就容易的多了！不就是 http://tw.yahoo.com 吗？！而既然电脑主机只认识 IP 而已， 因此当我在浏览器上面输入了‘http://tw.yahoo.com’的时后，我的电脑首先就会藉由向 DNS 主机查询 tw.yahoo.com 的 IP 后，再将查询到的 IP 结果回应给我的浏览器， 那么我的浏览器就可以藉由该 IP 来连接上主机啦！

发现了吗？我的电脑必须要向 DNS 主机查询 Hostname 对应 IP 的资讯 喔！那么那部 DNS 主机的 IP 就必须要在我的电脑里面设定好才行，并且必须要是输入 IP 喔，不然我的电脑怎么连到 DNS 主机去要求资料呢？呵呵！在 Linux 里面，DNS 主机 IP 的设定就是在 /etc/resolv.conf 这个档案里面啦！

目前各大 ISP 都有提供他们的 DNS 主机 IP 给他们的用户，好设定客户自己电脑的 DNS 查询主机， 不过，如果您忘记了或者是您使用的环境中并没有提供 DNS 主机呢？呵呵！没有关系， 那就设定 Hinet 那个最大的 DNS 主机吧！ IP 是 168.95.1.1 咯！要设定好 DNS 之后，未来上网浏览时，才能使用主机名称喔！不然就得一定需要使用 IP 才能上网呢！DNS 是很重要的，他的原理也顶复杂的，更详细的原理我们在后面的 ‘DNS 伺服器架设’里面进行更多更详细的说明喔！这里仅提个大纲！

小标题的图示 一组可以连上 Internet 的必要网路参数
从上面的所有说明当中，我们知道一部主机要能够使用网路，必须要有 IP ，而 IP 的设定当中，就必须要有 IP, Network, Broadcast, Netmask 等参数，此外，还需要考虑到路由里面的 Default Gateway 才能够正确的将非同网域的封包给他传送出去。 此外，考虑到主机名称与 IP 的对应，所以您还必须要给予系统一个 DNS 主机的 IP 才行～ 所以说，一组合理的网路设定需要哪些资料呢？呵呵！就是：
  • IP
  • Netmask
  • Network
  • Broadcast
  • Gateway
  • DNS
没错！就是这些资料！如果您是使用 ADSL 拨接来上网的话，上面这些资料都是由 ISP 直接给您的，那您只要使用拨接程式进行拨接到 ISP 的工作之后， 这些资料就自动的在您的主机上面设定完成了！但是如果是固定制 ( 如学术网路 ) 的话，那么就得自行使用上面的参数来设定您的主机啰！缺一不可呢！以 192.168.0.0/24 这个 C Class 为例的话，那么您就必须要在您的主机上面设定好底下的参数：
  • IP: 由 192.168.0~192.168.0.254
  • Netmask: 255.255.255.0
  • Network: 192.168.0.0
  • Broadcast: 192.168.0.255
  • Gateway: 每个环境都不同，请自行询问网路管理员
  • DNS: 也可以直接设定成 168.95.1.1
大标题的图示 重点回顾：
  • 只要是能够连接上 Internet 的主机，都有危险，不要以为小网站就不会被 cracker 所破解；
  • 虽然目前的网路媒体多以乙太网路为标准，但网路媒体不只有乙太网路而已；
  • Internet 主要是由 Internet Network Information Center (INTERNIC) 所维护，但其仅维护一些技术文件的推展；
  • 乙太网路的标准相当多，速度的定义亦不相同，购买时需要特别留意其速度标准。
  • 乙太网路的 RJ-45 网路线，由于 568A/568B 接头的不同而又分为平行线与跳线；
  • 网路媒体都有其最大可接受的封包量，在乙太网路上可接收的封包为 MAC (Media Access Control) 讯框
  • 乙太网路上最重要的传输资料为 Carrier Sence Multiple Access with Collision Detect (CSMA/CD) 技术， 至于传输过程当中，最重要的 MAC 讯框内以硬体位址 (hardware address) 资料最为重要；
  • 乙太网路的交换技术 (switch) 已经可以克服 CSMA/CD 所发生的封包碰撞情况，因为 switch 为非共享媒体
  • 透过八蕊的网路线 (Cat 5 以上等级)，现在的乙太网路可以支援全双工模式；
  • OSI 七层协定为一个网路模型 ( model ) ，并非硬性规定。这七层协定可以协助软硬体开发有一个基本的准则， 且每一分层各自独立，方便使用者开发；
  • 现今的网路基础是架构在 TCP/IP 这个通讯协定上面；
  • 资料连接层里重要的资讯为 MAC (Media Access Control)，亦可称为硬体位址，而 ARP Table 可以用来对应 MAC 与软体位址 ( IP ) ；
  • 网路的传输单位使用 bit 而不是 byte ；
  • 在网路媒体方面， Hub 为共享媒体，因此可能会有封包碰撞的问题，至于 Switch 由于加入了 switch port 与 MAC 的对应，因此已经克服了封包碰撞的问题，也就是说，Switch 并不是共享媒体；
  • IP 为 32 bits 所组成的，为了适应人类的记忆，因此转成四组十进位的数据；
  • IP 主要分为 Net ID 与 Host ID 两部份，加上 Netmask 这个参数后，可以设定‘网域’的概念；
  • 所谓的同一网域指的是 Net_ID 相同，但 Host_ID 不同的环境下；
  • 根据 IP 网域的大小，可将 IP 的等级分为 A, B, C 三种常见的等级；
  • Loopback 这个网段在 127.0.0.0/8 ，用在每个作业系统内部的回圈测试中。
  • 网域可继续分成更小的网域 (subnetwork)，主要是透过将 Host_ID 借位成为 Net_ID 的技术；
  • 若 IP 封包大于 MAC 可接受的最大值时，就得将该 IP 封包重组分段；
  • IP 只有两种，就是 Public IP 与 Private IP ，中文应该翻译为 公共 IP 与 私有(或保留) IP，私有 IP 与私有路由不可以直接连接到 Internet 上；
  • 每一部主机都有自己的路由表，这个路由表规定了封包的传送途径，在路由表当中，最重要者为预设的通讯闸 ( Gateway/Router )；
  • TCP 协定的表头资料当中，那个 Code (control flags) 所带有的 ACK, SYN, FIN 等为常见的旗标， 可以控制封包的连线成功与否；
  • TCP 与 IP 的 IP address/Port 可以组成一对 socket pair
  • 网路连线都是双向的，在 TCP 的连线当中，需要进行用户端与伺服器端两次的 SYN/ACK 封包发送与确认， 所以一次 TCP 连线确认时，需要进行三向交握的流程；
  • UDP 通讯协定由于不需要连线确认，因此适用于快速即时传输且不需要资料可靠的软体中，例如即时通讯；
  • ICMP 封包最主要的功能在回报网路的侦测状况，故不要使用防火墙将他完全挡掉；
  • MTU 可以用来规范各种封包打包时的最大单位，单位为 byte。
  • 一般来说，一部主机里面的网路参数应该具备有：IP, Netmask, Network, Broadcast, Gateway 等；
  • 目前常见的资料封包格式有 TCP/UDP/ICMP 等，TCP 为较可靠的封包格式， 透过多种确认手段来使封包可以准确的到达目的地，至于 UDP 则略过这些确认手续，因此传送速度较快。
  • 在主机的 port 当中，只有 root 可以启用小于 1023 以下的 port ；
  • DNS 主要的目的在于进行 Hostname 对应 IP 的功能；
大标题的图示 课后练习：
  • 请简述 OSI 网路七层协定每一层的功能；
    • 请参考本章第一节的相关内容。
  • 在 ISP 提供的网路服务中，他们提到传输速度为 1.5M/382K ，请问这个数据的单位为何？
    数据单位为 bits/second, 与惯用的 bytes 差 8 倍。
  • 什么是 MAC ( Media Access Control ) ，MAC 主要的功能是什么？
    • Media Access Control 的缩写，为乙太网路硬体讯框的规格，乙太网路就是以 MAC 讯框进行资料的传送。 目前 MAC 也常被用为乙太网路卡卡号的代称。
  • 什么是封包碰撞？为什么会发生封包碰撞？
    • 当主机要使用网路时，必须要先进行 CSMA/CD 监听网路，如果(1)网路使用频繁 (2)网路间隔太大， 则可能会发生监听时均显示无主机使用，但发出封包后却发生同步发送封包的情况，此时两个封包就会产生碰撞， 造成资料损毁。
  • ARP Table 的作用为何？如何在我的 Linux 察看我的 ARP 表格？
    • ARP 协定主要在分析 MAC 与 IP 的对应，而解析完毕后的资料会存在系统的记忆体中， 下次要传送到相同的 IP 时，就会主动的直接以该 MAC 传送，而不发送广播封包询问整个网域了。
    利用 arp -n 即可
  • 简略说明 Netmask 的作用与优点；
    • Netmask 可以用来区分网域，且 Netmask 可以有效的增加网路的效率，这是因为 Netmask 可以定义出一个网域的大小，那么 broadcast 的时间就可以降低很多！一般来说， 我们如果要将一个大网域再细分为小网域，也需要藉由 Netmask 来进行 subnet 的切割。
  • 我有一组网域为： 192.168.0.0/28 ，请问这个网域的 Network, Netmask, Broadcast 各为多少？而可以使用的 IP 数量与范围各是多少？
    • 因为共有 28 个 bits 是不可动的，所以 Netmask 位址的最后一个数字为 11110000，也就是 (128+64+32+16=240) ，所以：
    Network：192.168.0.0
    Netmask：255.255.255.240
    Broadcast：192.168.0.15
    IP：由 192.168.0.1 ~ 192.168.0.14 共 14 个可用 IP 喔！
  • 承上题，如果网域是 192.168.0.128/29 呢？
    • 因为是 29 个 bits 不可动，所以最后一个 Netmask 的位址为： 11111000 也就是 (128+64+32+16+8=248)，所以：
    Network：192.168.0.128
    Netmask：255.255.255.248
    Broadcast：192.168.0.135
    IP：由 192.168.0.129 ~ 192.168.0.134 共 6 个可用的 IP 喔！
  • 我要将 192.168.100.0/24 这个 C Class 的网域分为 4 个子网域，请问这四个子网域要如何表示？
    • 既然要分为四个网域，也就是还需要藉助 Netmask 的两个 bits (2的2次方为4啊！)，所以 Netmask 会变成 255.255.255.192 ，每个子网域会有 256/4=64 个 IP ，而必须要扣除 Network 与 Broadcast ，所以每个子网域会有 62 个可用 IP 喔！因此，四个子网域的表示方法为：
    192.168.100.0/26, 192.168.100.64/26, 192.168.100.128/26, 192.168.100.192/26。
  • 如何观察 Linux 主机上面的路由资讯 ( route table )？
    • 路由资讯的观察可以下达 route 来直接察看！或者是下达 route -n 亦可
  • TCP 封包上面的 SYN 与 ACK 标志代表的意义为何？
    • SYN 代表该封包为该系列连线的第一个封包，亦即是主动连线的意思；
    ACK 则代表该封包为确认封包，亦即是回应封包！
  • 什么是三向交握？在哪一种封包格式上面才会有三向交握？
    • 使用 TCP 封包才会有三向交握。TCP 封包的三向交握是一个确认封包正确性的重要步骤，通过 SYN, SYN/ACK, ACK 三个封包的确认无误后，才能够建立连线。至于 UDP 封包则没有三向交握喔！
  • 参考合勤科技网页上的说明 (http://www.zyxel.com.tw/product/category.htm?indexFlagvalue=1028014886 ) 试说明何谓有网管？无网管的 switch ？此外，这些 switch 的硬体应算在 OSI 七层协定的第几层？
    • 有网管者，会在 switch 内部加入其他的小型 OS，藉以控管 IP 或 MAC 的流通； 通常基础的 switch 仅达控管 MAC ，故为 OSI 第二层(资料连接层)
  • 为何 ISP 有时后会谈到‘申请固定 8 个 IP ，其中只有 5 个可以用’，你觉得问题出在哪里？ 如果以网域的观念来看，他的 netmask 会是多少？
    • 因为如果是一个网域的话，那么八个 IP 前后(Host_ID 全为 0 与 1 的条件)为 Network 及 Broadcast ， 加上一个在 ISP 处的 Gateway ，所以仅有 5 个可以用。因为有 8 个 IP ，所以其 netmask 后八 bits 为 11111000 ，故为 255.255.255.248。
  • Internet 协定中共包含 "Network Access Layer", "Internet Layer", "Transport Layer", "Application Layer"， 请将这四层与 OSI 七层协定的内容进行连结 (自行上网查询相关文章说明)；
    • Network Access Layer: 涵盖 Data-Link 及 Physical Layer
    Internet Layer: 也是 Network Layer
    Transport Layer: 也是 Transport Layer
    Application Layer: 涵盖 Application Layer, Persentatin Layer, Session Layer.
  • 请自行上网查询关于 NetBIOS 这个通讯协定的相关理论基础，并请说明 NetBIOS 是否可以跨路由？
    • 请自行参考网中人的网路基础文章
  • 什么是 Socket pair ？包含哪些基本资料？
    • 由 IP 封包的 IP address 与 TCP 封包的 port number 达成，分别为目的端的 IP/port 与本地端的 IP/port。
  • 分别说明 568A 及 568B 这两种 RJ-45 接头的蕊线颜色排列顺序；
    • 568A: 白绿　绿　白橙　蓝　白蓝　橙　白棕　棕
    568B:白橙　橙　白绿　蓝　白蓝　绿　白棕　棕
  • IP 有一段 A Class 的网段分给系统做为测试用，请问该网段为？设定的名称为？
    • 127.0.0.0/8, loopback
  • ICMP 这个协定最主要的目的为？同时做为‘回应’的类别为第几类？
    • 做为网路检测之用，为第 8 类 (echo request)
  • IP 封包表头有个 TTL 的标志，请问该标志的基本说明为何？其数据有何特性？
    • 为该封包的存活时间，该时间每经过一个 node 都会减少一，当 TTL 为 0 时，该封包会被路由器所丢弃。 该数据最大为 255。
  • 在 Linux 当中，如何查询每个 port number 对于服务的对应 (filename)
    • /etc/services 档案中有纪录
  • 什么是星形连线？优点为何？
    • 利用一 hub/switch 连结所有的网路设备的一种连线方式，最大的好处是，每个‘网路设备与 switch 之间’都是独立的， 所以所以每个主机故障时均不会影响其他主机的连线。
  • 请说明 CSMA/CD 的运作原理？
    发送流程
    1. 主机欲使用网路时，会先监听网路，若网路没有被使用时，才会准备传送，否则继续监听；
    2. 当资料传送钟，发现有碰撞情况时，则会重新监听网路，并且重新发送一次该封包；
    3. 若重复发生碰撞 16 次，则网路会瘫痪；
    接收流程
    1. 主机如果没有在传送资料，则会监听网路，并且主动在接收的状态下；
    2. 若接收到一个封包，并且该表头所载 MAC 为本身的网卡卡号，则开始接收该封包，否则将该封包丢弃；
    3. 接收过程当中如果发生封包碰撞，则会通知原发送主机碰撞的资料；
    4. 封包接收完毕后，会以 MAC 表头所载长度同时分析本封包长度，若发生问题，则会通知对方重新传送。
  • TCP/IP 这两个通讯协定必须要在一起才能生效，为什么？
    • 因为 IP 协定仅定位出 IP 的所在处与路由，并没有沟通协调的能力， 至于 TCP 封包则具有目的端、本地端程式之间沟通的能力，但无法直接传送封包。 故 TCP/IP 常会放在一起讲。
大标题的图示 参考资料
特别感谢：
本文在 2002/07 发出之后，收到相当多朋友的关心，也从而发现了自己误会的一些基础的网路理论，真的是感谢好朋友 Netman 兄与 ZMAN 兄的指导！这篇短文在 2003/08/03 做了相当大幅度的修订，与原来的文章 ( 上次更新日期 2002/09 ) 已经有一定程度的差异了，希望网友们如果有时间的话，能够再次的阅读， 以厘清一些基本概念喔！
  • Study Area 之网路基础：http://www.study-area.org/network/network.htm
  • Request For Comment (RFC) 技术文件：ftp://nic.merit.edu/internet/documents/rfc
  • Request For Comment (RFC) 技术文件：http://www.rfc-editor.org/
  • Hub 与 Switch 的迷思：http://www.study-area.org/tips/hub_switch.htm
  • BBS 上的问答收集
  • Robert Breyer & Sean Riley 着、风信子、张民人译，‘Switched & Fast 乙太网路’， 旗标出版社
  • 粘添寿着，‘Internet 网路原理与实务’，旗标出版社。
  • Phil Dykstra, Gigabit Ethernet Jumbo Frames： http://sd.wareonearth.com/~phil/jumbo.html
  • 台湾地区 IP 核发情况：http://rms.twnic.net.tw/twnic/User/Member/Search/main7.jsp?Order=inet_aton(Startip)
  • 全球 IPv4 的统计：http://www.twnic.net.tw/ipstats/ipv4stats.htm
  • 维基百科：http://en.wikipedia.org/wiki/IPv4
2002/07/18：第一次完成日期！
2002/09/26：修改了部分可能引起误解的文章部分！
2003/08/03：重新编排版面，并且重新检视文章内容，修订文章！
2003/08/20：增加重点回顾与课后练习
2003/09/06：加入参考用解答
2004/03/16：修订 N-Way 的错误，订正为 Auto MDI/MDIX 的功能！
2006/02/09：将旧的文章移动到 此处
2006/07/12：参考了粘教授与风信子兄的书籍，修改了很多基础资料喔！还有重点整理，不过，练习尚未更新
2006/07/16：加入习题练习啰！
2007/10/21：图14那个 UDP 的表头资料中，16 bits 误植为 16 bytes，感谢讨论区 ricky.liu 的告知！
2008/04/21：经由网友 chyanlong 兄的指点，IHL 的大小单位误植为 byte，应该是字组 (word) 才对。
2002/07/18以来统计人数


鸟哥的 Linux 私房菜 -- 区域网路架构简介与 Linux 版本选择

为取得较佳浏览结果，请爱用 firefox 浏览本网页

区域网路架构简介与 Linux 版本选择
切换解析度为 800x600
最近更新日期：2006/07/13
在前一章‘网路基础’当中， 我们介绍了比较多理论方面的网路相关资讯，也大略的介绍了一些简单的网路连线媒体需要注意的事项。 在这一章当中，我们将会继续讨论在一个小型企业或家庭里面的小型区域网路规划， 以让您的所有电脑主机都可以直接利用乙太网路进行资料的连接啊！ 一般来说，内部区域网路都希望直接使用私有 IP 来设定沟通环境， 直接以简单的星形连线做为网路施工的主要类型，底下就分别来谈一谈如何规划您主机在星形连线所应该要放置的状态， 以及主机应该使用何种版本的 Linux distribution 较佳呢？

1. 区域网路的连线
    1.1 什么是区域网路？
    1.2 区域网路的布线规划
    1.3 网路媒体选购建议
    1.4 内部连线的网路参数与通讯协定
 2. Linux distributions 的选择
    2.1 主机硬体的选择
    2.2 distributions
 3. Windows 个人电脑网路设定范例
4. 针对本文的建议：http://phorum.vbird.org/viewtopic.htm?p=112104
大标题的图示 区域网路的连线
谈完了网路基础后， 现在就让我们实际的来将家里或者小型企业内部的全部电脑给他连接起来吧！ 当然啦，我们这里主要介绍的是小型区域网路的架构，如果是比较大型的企业内部， 那么将‘配线盘、线路设计、墙上网路孔’分别拆开施工的结构化布线会比较妥当， 不过，结构化布线并非本文所想要讨论的，如果您的企业有需求的话，可以向专业人士寻求协助， 举例来说，酷学园(http://phorum.study-area.org)的 ZMAN 兄就是一位很棒的网路布线专家。 无论如何，先来将所有的网路硬体连线起来吧！

小标题的图示 什么是区域网路
区域网路 (Local Area Network, LAN) 顾名思义就是在我们所属区域的所有网路嘛！ 如果由前一章网路基础提到的相关网域概念来看的话， 我们可以说区域网路就是在同一个网域内所有连线主机及网路媒体的统称。 此外，区域网路通常是在同一个物理网段以内的，虽然藉由网路位址的设定可以规范出许多不同的 IP 网段， 不过，通常我们还是会称这样的环境为区域网路的。

总之，区域网路就是在您主机附近的网路环境，通常是在同一个物理网段内，IP 网段通常也在同一网域内。 比如说大学的学生宿舍内的网路环境，其实都是透过整栋大楼的 switch 集中连线， 所以是在同一个物理网段内，就常被称为区域网路啰。

相对于区域网路而言，区域网路外的环境就可以被称为广域网路 (Wide Area Network, WAN)。这也是为什么在您家里的数据机上面的网路插孔上，总是有着 LAN 与 WAN 这两个插孔与灯号的存在啊！ ^_^

由前一章我们知道 Internet 其实就是由 INTERNIC 所维护的一个架构松散的连线介面 ( 其实也不能说是维护，只是 INTERNIC 有提供一些技术文件以及 Public IP 申请的相关资讯公布而已 )， 任何人只要能够取得 Public IP 就可以连上 Internet 啰，同时 Internet 上头也是没有王法的地方， 要特别留意您的连线啊！OK，那什么是 Intranet ？相对于 Internet 是没有专属维护者的介面而言， Intranet 则是专属的私人网域，只是这个网域使用的是类似 Internet 的连线架构， 例如使用私有 IP 架设 TCP/IP 区域网路的环境就能够被称为是 Intranet 啰。

如果要定义的更为狭义的话，我们可以说，区域网路就是在同一个物理网段的环境内， 使用私有 IP 或者是区域网路适用的通讯协定所串起来的一个网路环境。 既然区域网路常常使用私有 IP ，那么区域网路可否连上 Internet 啊？‘当然可以’！ 简单的话，可以使用 IP 分享器来取得 Public IP 上网，复杂的话， 可以使用 Linux 主机架设 NAT (Network Address Translation) 伺服器来转址， 就能上网啦！由于私有 IP 不会与 public IP 冲突， 并且也可以避免直接与 Internet 的资料互通，可以减少很多被主动攻击的情况。 所以啊，您的区域网路最好还是设定私有 IP 比较妥当呐！

小标题的图示 区域网路的布线规划
记得以前听 ZMAN 大哥某场演讲的时候提到，网路布线是‘数十年大计’中最重要的一环， 因为‘伺服器主机能力不够时换主机就好了，Switch 交换力不足时换 switch 就好了， 但如果布线不良，难道要拆掉房子将管线挖出来重新安装设定？’所以说， 最初规划的布线严谨度真的会影响到未来网路的分布情况啊！所以说， 如果您的企业‘整栋大楼需要重新布线’时，真的非常建议您务必要找寻专业网路布线专家帮忙设计规划， 因为连一个小小的机柜配线箱都有大学问～设计的好的话，每部独立的主机要改线路、 要换插孔都变的很简单！而且主机到墙上插孔的距离也会变的很短，维护也会很方便！线段也会很美观！ 当然啦，如此一来，网路线材的选择也就不能够用太差的！而且网路布线经过折角区时， 也需要特别留意施工呐。

但是本文讨论的是一些比较小的区域网路环境，这样的环境可以是在一间办公室内而已， 所以我们这里谈到的大多是比较单纯的布线状态，并没有考虑到办公室外部的环境， 所以参考本文时，请特别留意这种差异性喔！

在这样单纯的环境中，我们可以利用一个以 switch 为中心来串连所有设备的星形连线 (star topology) 架构来设计我们的区域网路啊！在这样的环境中您需要担心的是‘ 那我的 Linux 伺服器要放在那个地方？’ 会考虑 Linux 伺服器是因为鸟哥假设你需要在你的区域网路内架设对 Internet 开放网路的服务！ 而 Linux 是否具有 Public IP 对于主机的维护与设定的复杂度有很大的影响，所以当然需要考量啰！ 底下鸟哥以目前在台湾挺流行的 ADSL 利用电话线路上网的环境来说明几种连线状态：

Linux 主机直接连到 Internet 的环境：
在底下的环境当中，鸟哥假设我们仅有一条 ADSL 的对外连线，也就是说， 我们的 Linux 与一般 PC (不论何种作业系统) 都是透过同一条线连到 Internet 上面去的。

让 Linux 与一般 PC 在同等地位：

如果您使用的 ADSL 是多 IP 的条件 (例如拨接可以给予 2-8 个 IP 的情况)， 那么最简单的方式就是如下图一的连线模式：

Linux 伺服器取得 public IP 的连线方式之一
图一、Linux 伺服器取得 public IP 的连线方式之一(具有多个可用 IP 情况)

在这种连线模式当中， Linux 与一般 PC 或印表机都是同等地位，并没有谁比较‘大尾！’^_^ 如果不急着连上 Internet 时，那么每个设备都给予一个同网域的私有 IP 就可以进行网路连线的工作了， 您也可以很快乐的使用印表机或者是网路上的芳邻等等工作。 此外， Linux 伺服器也可以作为内部的档案伺服器或者是印表机伺服器等等。

当需要连上 Internet 时，每部电脑 (包括 PC 与 Linux 主机) 都可以直接透过拨接连上， 而由于拨接是在每部机器上面‘额外增加一个实体的 ppp0 介面’，因此， 拨接上网之后每部主机还是可以使用原有的区域网路内的各项服务，而无须更动原本设定妥当的私有 IP 。 这样的情况对于一般家庭使用者来说，可以算是最佳的解决方案啦！因为如果您的 Linux 主机挂点时， 其他个人的 PC 是不会被影响的！

不过这样的环境对于小型企业主来说，却不好管理。因为无法掌握每个员工实际上网的情况， 而且对于防火墙来说，‘根本就是一个没有防火墙的环境’，所以， 是没有办法对员工进行任何实际网路的掌控的，并且由于网路内外部 (LAN 与外部环境) 并没有明确的分开，网管人员对于进入用户端的封包是没有任何管理的能力， 所以对于网路安全来说，是很难管控的一种环境啊！因此对于企业来说，不建议这种环境。

让 Linux 与一般 PC 分开：

如果您有多个可用的 public IP ，并且您的 Linux 伺服器主要是提供 Internet 的 WWW 或 mail 服务， 而不是作为内部的档案伺服器之用，那么将 Linux 伺服器与内部的网域分开也是个可行的方法， 而且 Linux 拥有 public IP，在设定与维护上面也不困难，如下所示：

Linux 伺服器取得 public IP 的连线方式之一
图二、Linux 伺服器取得 public IP 的连线方式之二(具有多个可用 IP 情况)

所有的 LAN 内的电脑与相关设备都会在同一个网域内，所以在 LAN 内的传输速度是没有问题的， 此外，这些电脑要连出至 Internet 时，必须要透过 IP 分享器， 所以您也可以在 IP 分享器上面设定简单的防火墙规则， 如果 IP 分享器可以换更高阶的设备时，那么您就可以在该设备上面架设规则较为完整的防火墙， 对于内部主机有相当程度的管理，并且好维护啊！

让 Linux 直接管理 LAN：

如果您不想要购买 IP 分享器的话，那么直接利用 Linux 伺服器来管理就好了啊！ 没错啊！那么你可以这样布线：

让 Linux 管理 LAN 的布线情况
图三、让 Linux 管理 LAN 的布线情况

这种情况下，不论你有多少个 IP 都可以适用的，尤其是当你只有一个 public IP 时，就非得使用这种方式不可了。 让 Linux 作为 IP 分享器的功能相当的简单，同时 Linux 必须具备两张网路卡，分别是对外与对内， 由于 Linux 依旧具有 public IP ，所以在伺服器的设定与维护上相当的简单， 同时 Linux 伺服器可以做为内部网域对外的防火墙之用，由于 Linux 防火墙的效能挺不错 加上设定也很简单，功能却也是很不错的！因此，网路管理人员也较能进行较完善的掌控， 并且， Linux 伺服器也要比高阶的硬体防火墙便宜多了！ ^_^ 鸟哥个人是比较喜好这种方式的连线啦！

不过，我们都知道‘伺服器提供的网路服务越单纯越好’， 因为这样一来主机的资源可以完全被某个程式所使用，不会互相影响，而且当主机被攻击时， 也比较能够立即了解是那个环节出了问题。但是如同图三的状况来说的话， 由于内部的 LAN 是需要通过 Linux 才能连线出去，所以 Linux 挂点时，整个对外连线就挂了， 此外， Linux 的服务可能就太复杂了点，可能会造成维护上的困难度。 但对于小型区网来说，图三这种架构还是可以应付的来的啦！

Linux 主机放在 LAN 里面：
瞎密？我们的 Linux 主机放在 LAN 里面？有没有搞错啊？没搞错啊～ 比较大型的企业通常会将他们的伺服器主机放置在机房内，主要是在 LAN 的环境下， 再透过防火墙的封包重新导向的功能，将来自 Internet 的封包先经过防火墙后才进入到伺服器， 如此一来可在防火墙端就砍掉一堆莫名其妙的侦测与攻击，当然会比较安全啊！ 这种架构还依防火墙的多寡而又可分为非军事区(DMZ)的配置，不过，太麻烦了～不建议初学者直接使用。 底下我们仅介绍较简单的架构来说明：

Linux 主机放在 LAN 里面的布线情况
图四、Linux 主机放在 LAN 里面的布线情况

这里我们以一个较简单的图示来说明，所以利用的还是 IP 分享器，可能的话， 您可以将 IP 分享器换成 Linux 主机来架设防火墙，也是一个不错的选择啊！ 反正现在电脑天天在升级，升级后的旧配备其实就可以作为 Linux 防火墙之用了！ 反正防火墙又不需要什么硬碟与强效的显示或者 CPU， 只要有不错的网路介面就能够达到不错的防火墙效能了。

不过这里得再次的强调， Linux 伺服器主机若放在 LAN 里面，则当你要对 Internet 提供网路服务时， 防火墙的规则将变的相当复杂，因为需要进行封包转递的任务，在某些比较麻烦的协定当中， 可能会造成设定方面的困扰。所以，在您初接触 Linux 伺服器时， 不建议新手使用这种连线架构，避免由于失去信心而没有动力学习～(@_@)。

每种连线的方式都有其适用的使用者群，所以没有那个是比较好的， 完全是看您自己的网路环境而定喔！了解了简单的网路布线方式后， 底下我们来谈一谈几个常见的网路元件的名词吧！
  • Node (节点)：
    连接在网路上的， 具有网路卡卡号的设备都可以是节点。 包括伺服器、工作站、路由器与网路印表机等等，都是一个节点； 如同网路基础内谈到的， IP 封包内会有个 TTL 的封包存活时间，该时间与封包经过的节点数有关呐！

  • Client (用户端)：
    向主机端主动发出连线要求的就称为 Client 。

  • Server (伺服器端)：
    在网路上面提供网路相关服务的， 可以回应用户端的连线要求者，就可以称为是伺服器了。不过 client/Server 的架构当中， 每部主机的身份可能随时会改变啊！举例来说，当 mail server 要传送资料时， 必须要向 DNS 主机询问目标 email 的 IP 位址，此时 mail server 反而是 client 端呐！

  • Interface (网路介面)：
    网路介面除了实体网路卡之外， 透过点对点 (point to point) 连线方式所建立的 PPP0 介面也是一个实际的介面。 此外，每张网路卡上面都可以设定多个 IP ，那些多的 IP 则设定在虚拟的网路介面上！

  • Network Interface Card, NIC(网路卡)： 可以说是最重要的网路元件了！因为所有想要连上乙太网路的主机都需要有乙太网路卡！

  • Workstation (工作站)：
    没有对 Internet 提供网路服务， 但是提供使用者登入进行学术研究，例如数值模式模拟、大型程式编译与开发等等的高阶主机， 都可以被称为工作站。
OK！我们现在知道要连上乙太网路组成的区域网路，就得要有网路卡、网路线、网路集中媒体(hub/switch)、 连上 Internet 的数据机等等，在这里鸟哥将防火墙、路由器等等设备归类为主机， 因为基本上，这些元件内部一定会含有一个网路卡，只是作业系统的精简程度与软体功能的不同就是了。 那么这些所需要的网路硬体又该如何挑选呢？

小标题的图示 网路媒体选购建议
在开始底下的介绍之前，您必须要对于跳线、平行线、RJ-45 网路线、Hub/Switch 的优劣等等有一定程度的了解，请再前往网路基础看一看。 此外，不在我们区域网路内的设备，例如数据机，那就得向您的 ISP 询问了！一般来说， 数据机是中华电信提供给用户的，然而由于‘中华电信因为不同批次安装的数据机模组不同， 所以会有不一样的连接与线材处理方式！’例如早期的数据机 (有的朋友会称 ADSL 数据机为小乌龟) 连接到电脑的网路卡是使用跳线，但是近期的数据机却使用的是一般的平行线！所以请特别向您的 ISP 询问才行。底下主要针对区域网路内的网路媒体来进行介绍与说明。

网路卡：
目前常见的 ADSL 拨接与固定制，以及 Cable Modem 的连线上网方式都需要藉由乙太网路卡的辅助， 我们也知道乙太网路卡的规格实在太多了，所以底下我们就简单的来作个说明吧！

一般来说，目前的新主机几乎都是内建 gigabit 的乙太网路卡了，所以您不需要额外购买网路卡。 不过，这种内建的网路卡通常晶片的启动驱动程式比较麻烦，您必须要先参考他官方网站所提供的驱动程式安装手册后， 才能够顺利的驱动哪！如果想要额外购买网路卡的话，以现在的网路速度与连线品质来看， 一般家庭使用 10/100 Mbps 应该是足够了，不过如果有特殊需求的话，买个 10/100/1000 Mbps 的超高速乙太网路卡也不错喔！

如果是想要作为 Linux 伺服器的话，那么您的网路卡可能必须要购买好一点的。 举例来说，某些主机板内建便宜的 gigabit 网路介面，但越便宜的网路介面可能会造成损耗较多的 CPU 资源， 如果能够购买类似 Intel/3Com 等知名品牌的 gigabit 介面卡，不但传输较为稳定， 并且可以降低系统资源的耗费，是有一定程度的帮助的。另外，如果强调高速的话， 甚至可以选用 PCI-Express 的网路卡，而不使用传统的 PCI 介面。因为 PCI-Express 的传输频宽更高。

不过，如果是一般家用，或者是准备用来作为学习机之用的主机，那么万一网路卡晶片无法驱动时， 请先买个螃蟹卡 (晶片是 Real Tek 8139) 来作为练习之用， 因为 Linux 本身就支援 Real Tek 8139 的晶片，您不需要额外的驱动程式，这样会方便学习啊！ 而且该网路卡也很便宜(大卖场一片不到 300 块台币)。
Tips:
如果要玩 Linux 又想比较顺畅的玩弄 Linux 时，请不要坚持使用 Linux 捉不到的网路卡！否则那份失望的心情 ......会让您失去很多很多的耐性与信心啊～

螃蟹卡最好认的地方在于其晶片上面有个类似螃蟹的 Logo ，以前鸟哥曾经在大卖场上面逛大街时， 还‘踢飞’过一整排螃蟹卡～便宜到都放在地上而已～ @_@ 		鸟哥的图示
Switch/Hub：
就如同网路基础里面曾经谈到的， Hub 是共享媒体而 Switch 是具有独立频宽的非共享媒体。因此以效能以及速度来看，当然是 switch 比较好用啊！ 不过，如果您是一般家庭用户，只是要作简单的上网等工作，是没有必要购买太好的集线器的， 建议使用一般大卖场可以买到的 5 port 的集线器即可 (差不多500块台币的就不错了)。

不过如果你常常在区网内传送大量的资料，例如一次传输就得要传送 GBytes 的资料时， 那么网路的整体速度需要很详细的考虑喔！包括网路卡最好使用 gigabit ， 当然中间的连线设备最好买支援到 gigabit 速度的 switch 啦！因为 10/100/1000Mbps 的 switch 要比 10/100Mbps 的设备快上十倍，速度可是差很多的啊！如果您的设备还需要更快时， 例如鸟哥之前服务的实验室内部的 cluster (丛集式电脑群) ，则购买的 switch 甚至需要支援 Jumbo frame 这种支援大讯框的硬体架构才行，否则速度上不来啊！

购买 switch/hub 时，注意到该硬体是否具有 N-Way (自动协调速度机制) 以及 Auto MDI/MDI-x (自动跳线机制)， 这样可以不需要考虑手动切换速度以及网路线购置错误的问题。不过，以目前的消费水准来说， 建议添购时，直接购买 gigabit 的 switch 吧，扩充性会比较好呐！

网路线：
在所有串连网路的设备当中，网路线是最重要，但是却也最容易被忽略～ 除了网路线的等级会影响到连线速度外，网路线所在处是否容易被压折？ 是否容易有讯号衰减？自己压制的 RJ-45 接头是否通过测试？网路线是否缠绕情况严重？ 都会影响到网路的传输优劣！ 所以，虽然我们常常讲要确认主机与 Switch 是否有连接成功可以看 switch 上的灯号， 但是很多时候虽然灯号是亮的，不过由于网路线折损严重的问题，也会导致连线品质不良喔！

一般来说，‘个体户’与小型企业通常网路线是直接放在外部的，这种情况您发现网路怪怪的时， 可以直接更换线路，不过，如果是如同中大型企业将网路线直接埋在墙内， 或者是在管线当中，发现问题时，真的很麻烦～所以才需要专业人才的辅助啊！
Tips:
一般来说，越高等级的网路线，最好不要自行制作，因为一个小小的 RJ-45 接头的压制， 由于蕊线裸露程度的不同，就会影响到电子屏蔽效应的优劣了。Cat 5 等级的线材还可以自行压制， 比他还高等级的，最好还是买现成的吧！ ^_^ 		鸟哥的图示
无线网路相关设备：
现在的网路环境除了传统的乙太网路之外，其实还有一个也是很常见的喔，那就是无线网路啦！ 无线网路会流行主要的原因除了笔记型电脑能力越来越强，使得很多朋友直接以笔记型电脑取代桌上型电脑之外， 无线网路的速度目前已经可以达到 54Mbps 那么快了，对于一般只是上网看新闻与聊天的上班族来说， 这样的速度实在是非常快了 (一般的 ADSL 仅是 2M/256K bps 而已)， 所以要买无线网路设备 (含基地台与在 client 端的无线网卡) 来做成区域网路， 其实也是可以啦！而且还可以省去网路线的施工呢！

不过，无线网路最大的问题常常在于‘无线的安全性’方面，因为是无线的设备， 所以‘基地台如果没有做好防备措施的话，常常会导致 LAN 内的主机资料被窃取’， 这可是非常大的问题喔！可千万不要小看这个问题，吃上官司常常是由于忘记网路安全啊！ 记得购买无线网路基地台时，注意他可否‘限制 MAC ’，如此一来，至少可以锁网卡， 只让指定的网卡可以使用您的无线基地台，比较安全啦！

关于其他配件：
事实上，整个网路环境可不止上头提到的这些咚咚而已，还包括硬体防火墙、路由器、桥接器等等的， 当然，这些设备贵的话也有上百万的，但您的环境是否需要用到这么好的设备，那就见仁见智啊～此外， 为了环境的美观与生活的便利，您总不希望走在路上被网路线所绊倒，也不希望因为网路线绊倒你导致网路媒体掉落， 结果........损失了一堆 $$ 吧～所以啰，在网路线的转角处必须特别注意线材的保护， 在平面地上则需要特别使用压条给予固定，在牵线施工的时候尽量让线材沿着墙角或者是墙面上的既有物品， 如此则除了保持工作场所的美观之外，还能够增加工作场所的安全性啊！ ^_^

此外，‘电脑上网的速度并非完全取决于网路频宽’举例来说， 玩线上游戏时，大家都以为网路频宽需要很高规格，其实....根本不需要！因为 3D 连线游戏最主要的速度瓶颈应该是在于‘3D 显示’而不是网路。这是因为网路仅传送一些数据给您的主机， 而您的主机再在自己的硬碟里面将图形取出，并且使用 3D 绘图卡将画面绘制到您的荧幕上。 所以，显示速度或者是 CPU 不够力时，才会发生连线游戏的顿点。否则就是连线游戏伺服器本身的负载 (loading) 太大，导致主机回应有较多延迟，就产生 lag (顿点) 的问题啦！

另外，包括您主机使用的资料是否具有快速的传输介面也有关。举例来说，如果您的主机使用 USB 1.1 (最大传输 12Mbps)，但网路速度可达 10/100/1000Mbps ，那当您要在远端使用这部电脑的 USB 装置内的资料时，最大速度会是‘ 12Mbps ’，也就是最慢的那一个元件。所以啊， 网路速度慢的时候， 不要以为只要增加网路频宽就好了，要确切的找出问题啊！ ^_^

事实上，选购网路媒体所需要考量的参数实在太多了，并且没有一定的依据， 完全与使用者的使用环境与未来功能性有关。不过，如果着眼在单纯的硬体速度上面的话， 那么选购时考量‘我的网路速度可接受的最低速度为何？’去考虑吧！ 如果行有余力的话，再来考虑‘我的环境需要多稳定的设备来达成？’ 其他的，那就得要靠您自己摸索啰！ ^_^

小标题的图示 内部连线的网路参数与通讯协定
除非您已经具有相当熟练的 Linux 系统与伺服器架设维护经验， 否则不建议您使用上面图四所介绍的连线模式， 对于初接触 Linux 伺服器架设与维护的朋友来说， 将您的连线模式设定成图三应该是个不错的选择， 除了可以让您简单的就将伺服器架设成功之外，也可以让您以 Linux 做为内部 LAN 的防火墙管理中心， 对于未来的学习成长方面较有帮助啊！ ^_^

在图三的环境下， Linux 必须要具有 router (路由器) 的能力，所以当然必须就要有两个介面， 一个介面与 Internet 沟通，另一个介面则与内部的 LAN 沟通。 那么为什么鸟哥说的是‘两个网路介面’而不是 ‘两张网路卡’呢？原因很简单， 因为一张网路卡可以设定多个 IP 啊！因此，在 Linux 当中一张网路卡可以具有一个以上的 IP 呢！由于一个 IP 即为一个网路介面，因此只要两个网路介面 ( 不论有几张网路卡 ) 即可进行 NAT 的设定啦！所以自然一个网路卡即可啰！不过，鸟哥个人还是比较喜欢并且建议两张网路卡的啦， 将内外网路环境完整的分开，让您的内部网路效能较佳一点！

关于与 Internet 的连线方面，目前在台湾最常见的有电话专线的 ADSL 连线模式、 利用电视缆线搭设单向或双向的 Cable Modem ，以及例如学术网路的固定 IP 的专线等等。 这些连线的方式我们将在后续章节继续介绍的。至于内部的 LAN 我们则建议使用 Private IP 来设定喔！ 鸟哥通常喜欢使用 192.168.1.0/24 这个 Class C 的网域，没什么特殊原因，只是因为....我喜欢！ ^_^ 在选定了 Private IP 的网段后，您必须要有‘IP, Network, Netmask, Broadcast, Default gateway 以及 DNS 伺服器的 IP’等等的设定值。 假设我 Linux 主机的对内 IP 为 192.168.1.2 ，则 在图三内的 LAN 内的 PC 之网路相关设定参数则为：
  • IP:设定为 192.168.1.1~192.168.1.254 ，但 IP 不可重复；
  • Netmask：255.255.255.0
  • Network：192.168.1.0、Broadcast：192.168.1.255
  • Default Gateway：192.168.1.2 (路由器的 IP )
  • DNS：暂时使用 168.95.1.1
安装什么通讯协定

什么是通讯协定呢？简单的说，通讯协定就是一些标准与规则。一个社会要能够正常的运作， 必须要有一套标准与公正的游戏规则，大家都遵循这个规则，那么这个社会才能够没有问题的营运下去， 所以我们才会有警察、司法、检调单位等等来维护我们的公正性。同样的，在网路的社会中， 要让资料能够透过网路媒体传送，那么硬体制造商、软体开发商，就必须要共同遵循同一套标准， 这样整个网路社会才能够正常无误的进行资料的传递。

目前网路社会最通用的通讯协定就是 TCP/IP 了！TCP/IP 订定了 IP 基础与路由协定等资讯，让我们的网路世界可以互通有无，此外，在区域网路内部， 由于是小型的网域，事实上还可以透过简单的通讯协定来达到资料传输的目的，例如 NetBEUI 就是一个常见的简易通讯协定。 在 Linux 系统当中，只要将网路参数设定妥当，那么 TCP/IP 就已经被启用了，所以您不需要额外的再安装其他的通讯协定。不过，如果您需要将你的 Linux 系统中的硬碟空间分享给同网域的 Windows PC 时，那么就需要额外的加装 SAMBA 这个伺服器软体才行。相关的 SAMBA 资料我们会在后面的章节提及。反正不管怎么说，目前 Internet 就是经由 TCP/IP 来进行连接的，而 Linux 本身就支援了 TCP/IP ，所以不需要额外的安装有的没的说！

至于在 Windows 部分就比较麻烦一点，因为在较大型的企业当中，还需要额外的考虑到 Windows Server 所提供的服务，那么在 Windows Clients 端就得要相应的启动某些通讯协定才行。一般来说，在 Windows Client 系统里面，最常见的两个通讯协定就是 TCP/IP 以及 NetBEUI 这两个通讯协定了。如果您只想让 Windows 与 Linux 能够藉由网路上的芳邻互通有无，那么启动 TCP/IP 也就够了 ( 因为 SAMBA 是藉由 NetBIOS over TCP/IP 来达成资料传输的 ) ，不过，也可以同时启动 NetBEUI 这个通讯协定就是了。相关的说明可以参考 网路基础 以及后续的 SAMBA 伺服器等章节。

大标题的图示 Linux distributions 的选择
在‘鸟哥的 Linux 私房菜 -- 基础学习篇’当中我们提到过 Linux distributions 可是多的跟什么一样，那么你该如何选择你的 Linux distributions ？基本上，哪一套 Linux distribution 鸟哥觉得都差不多，但是每一套 Linux distributions 当初推出的预设使用群与他的理念可能不太相同， 就导致不一样的 distributions 的用途差异了。并且由于您所需要的软体以及新添购硬体的支援度等等， 也会让您的 distributions 挑选有些难度喔！

小标题的图示 主机硬体的选择
主机的功能与硬体的选择可以是息息相关的。怎么说呢？ 因为老旧的硬体无法提供高效能的环境，所以对于需要强效的 Proxy, WWW (MySQL) 等伺服器， 老旧的主机可能就无法提供有效的环境了。不过，如果是不需要很好性能的防火墙、 DHCP 主机与 NAT 伺服器时，那么目前被淘汰掉的 P-III 等级的主机就非常足够了！ 像卧龙小三大师就曾使用赛阳 400 等级的 CPU 做成流量不大的 WWW 主机， 所以，旧式主机可不要随便丢弃啊！

如果是像防火墙、NAT 主机、DHCP 主机等等，那么一般的 P-166 等级左右的主机系统， 配合一张 10/100 Mbps 的网路卡就很不错了！不过如果 LAN 与 WAN 的流量太大的话， 那么最好考虑 P-III 等级的主机，并且配合一张更好的网路卡，这样在效能上应该会比较好。

如果像是 WWW, Proxy, mail server 等需要常常读取硬碟资料的伺服器， 则除了主机系统最好要到 P-III 以上等级，网路卡不能太烂之外，硬碟的效能最好也必须要好一些。 而且 partition 的情况也必须要特别注意，最好将常常被存取的档案资料独立到一颗硬碟中， 可能的话，甚至可以组成 RAID (磁碟阵列) 来负责资料存取，让系统效能可以不被某些元件限制。 此外，记忆体的容量也需要特别留意，如果太小的话，可能会造成系统的效能不彰。 反正如果要架设好一点的主机，那就得要各个元件都加以考虑喔！

省不省电有所谓
前两年出产的处理器与相关的个人电脑零件，很多都非常的‘耗电’， 您或许觉得‘耗电’又没有什么了不起，一部冷气机的耗电量都要比电脑来的大！ 是没错啦，不过，如果仔细想一想若一部用来作为单纯的 IP 分享器的个人电脑主机， 偏偏他的耗电量高达 200W 的话，以一度电 2.4 元新台币来计算，假设这部主机是全年无休的， 一年可得花费 4200 左右的新台币啊！如果以 IP 分享器来说，鸟哥是没有计算过 IP 分享器的耗电量， 不过，应该不会超过 50W 吧？如此计算一下，相差 4 倍！您觉得如何呢？

对于一般家庭只有一部主机的情况来说，这问题不大啦！一年仅消耗 4200 左右，还可以接受。 但对于企业主来说，如果他需要 50-100 部主机呢？这可不是不可能的事吧！所以计算一下， 哗！一年要花 21 至 42 万新台币啊！而且这还不包括机房的空调冷却系统。现在看一看，觉得害怕了吧！ 所以说，选购硬体时，除了要考虑机器的性能以及功能需求之外，耗电量能省则省吧！ ^_^

虚拟化技术
现在的主机动不动就给他‘双核心’，也就是说在一部主机上面的一颗 CPU 上内建两个实际的运算单元， 简单的说，双核心就是表示您的主机上面有两颗 CPU 啦！那我们知道简单的服务其实并不会太消耗系统资源的， 所以，绝大部分的时间 CPU 都是在休眠的状态。那我们也知道最好每部主机仅负责一个网路服务， 环境与除错上会比较单纯，对吧！综合这么多的因素，您会想，如果我要安装五种网路服务， 就得要五部主机，而这五部主机却偏偏都在‘休眠’的状态，咦！好像很浪费喔！

这就是后来虚拟化技术发展的因素之一啦！所谓的虚拟化，其实就是在你一部实体主机里面， 安装多个作业系统，而且这些作业系统都是同时存在，且不互相干扰的。 举例来说， VMWare (http://www.vmware.com/) 就是一个很知名的虚拟化主机的软体，他可以在 Windows 作业系统里面开启另一个作业系统， 也可在 Linux 里面开启另一个作业系统。这可不是‘多重作业系统’喔！因为多重作业系统指的是‘ 你的主机同时安装多个作业系统在不同的 partition ， 而开机时可以选择不同的作业系统操作’的意思， 与虚拟化‘可以在一部主机上面同时开启多个可独立运作的作业系统 ’是不一样的！

既然您的 Linux 主机是多核心系统，表示 CPU 资源比较多，可以负荷的工作比较多， 加上目前有的虚拟技术，所以您可以在一部主机上面安装多个作业系统， 这些作业系统可以独立运作，而且，虚拟主机的每个作业系统与看起来就与单一主机没有两样， 呵呵呵呵！这么一来，不但不需要太多主机就能够达到您的多网路服务要求， 而且管理上也没有任何的不方便，当然，因为主机少了，电费的节省也是当然的啦！您说是吧！ ^_^

在 Linux 上面使用的虚拟化技术有很多，不过目前比较受瞩目的当属 Xen 这个玩意儿了， 据说很多预计要推出的新版 Linux distributions 已经预设要内建 Xen 的功能了， 嘿嘿！看来，以后大家可以用一部主机建立多个可同步运作的系统啦！^_^
  • Xen 网站：http://www.xensource.com/
小标题的图示 distributions
需要特别留意的是，旧的 distribution 是不支援很多新的硬体，包括 PCI-Express, SATA 以及很多新的网路晶片。所以，如果您的主机是新的，那么不要想用旧式的 distribution 来安装， 否则，真麻烦喔～因为您必须要自行加上很多的驱动程式！真麻烦～

另外，您可以将目前的 distribution 分成两大类，一类是多功能新鲜货，例如 Fedora ， 一种是强调性能稳定但软体功能较旧的企业用途货，包括 RHEL, CentOS, SuSE 及 B2D 等！ B2D 是台南县网中心卧龙小三大师所提倡的一个计划，最初的构想是想建立一个台湾的中文化 Linux distributions，并且不只是中文化而已，还希望能够提供全国中小学教师快速且安全的建立网路环境的构想下， 所发展的一个优秀的计划！目前这个计划发展的很不错的啊！ 很着重我们台湾使用者的想法喔！^_^。只是 B2D 使用的是 Debian 这个 distribution，在软体安装上面与一般常见的 RPM 不太相同，好在目前 B2D也有使用 APT 来进行网路安装与升级，可以解决软体安装方面的困扰。

一般来说，我们会建议您如果想要架设伺服器时，尽量选择‘稳定性较高的企业版’较佳， 因为功能新且强的版本例如 Fedora 由于太强调新鲜货，所以核心与软体的变动情况较为频繁， 那就很容易造成一些困扰，因为很多使用者自行安装的软体可能无法在新的核心上面跑， 所以，只要核心一升级，哇！很多需要编译的软体就都需要再重新编译过， 那么对强调‘永续服务的网路环境’来说，不就会造成不良的影响了吗？您说是吧！

由于鸟哥用惯了 RPM 以及 Red Hat 系统的关系，所以在这里推荐您使用 RHEL/CentOS/SuSE 这几个 Linux distributions，因为他够稳定，而且设定上面不难， 而且有新的 distribution 推出，因此适合新硬体架构， 不过，里面的软体版本可能就不会是最新的，这点您可能就得要自行设法啰！ 比较特别的是 CentOS，他不但标榜完全相同于 RHEL ，并且可以直接透过 yum 这个软体进行完整版本的升级，例如由 CentOS 4.2 升级到 CentOS 4.3 只要下达一个指令即可， 既不会影响到原有的设定，升级时所花费的时间又短，所以， 目前鸟哥都是以这个版本来进行伺服器的架设啊！

在后面的许多文章说明中，鸟哥将主要以 CentOS 这个版本来进行说明， 此外，也会加入 SuSE 的用法，不过，基本上， CentOS 既然是 Red Hat 系统， 所以后续的说明在 RHEL/Fedora/CentOS 其实都适用啦！您别担心啊！ ^_^

大标题的图示 Windows 个人电脑网路设定范例
我们这本书谈论的是以 Linux 主机提供的伺服器为主，所以关于 LAN 里面的 Windows 我都将他假设为 Client ，并且不提供网路服务，所以都先以固定的 Private IP 来设定 Windows 作业系统，如果您的 LAN 有其他的考量，那么底下的设定就看看就好 ^_^。

我们在 Windows 系统上所需要的网路参数除了 IP, netmask, DNS 之外，还需要‘工作群组, workgroup’与 ‘电脑名称, Netbios name’等等的设定，此外，我们也可以加上 LAN 里面很常见的 NetBIOS ( NetBEUI ) 这个通讯协定呐。因此，除非你确定您的网域内还有其他的工作站， 否则‘请只要安装 TCP/IP 以及 NetBEUI 这两个协定就好了！’ 安装太多反而会有问题呢！底下我们假设你的网路卡都安装好了，并且直接以 Windows XP 这个作业系统来介绍。 没办法，因为 Windows 2000 与 windows 98 以前的版本都已经不太被 Microsoft 支援了， 所以也只好以这个 XP 版本来说明啰。

与网路有关的设定参数：
  • IP: 192.168.1.13
  • Netmask: 255.255.255.0
  • DNS: 168.95.1.1
  • Gateway: 192.168.1.2
  • 工作群组： birdhouse
  • 电脑名称： bird3
详细的设定流程：
  1. 先到‘开始’==> ‘设定’==> ‘控制台’==> ‘网路连线’==> 选择‘区域连线’该项后，会出现如下图示：

    区域连线状态

  2. 上面画面当中选择‘内容’进入设定画面中：

    区域网路连线内容

  3. 接下来，选择‘连线后，将图示显示在通知区域内’， 并且双击‘Internet Protocol (TCP/IP)’该项目：

    TCP/IP

  4. 上面的设定不需要再谈了吧？！请填入您的网路参数，并且按下确定即可！ 好了，设定完成之后，再来需要编辑您的网路识别喔！选择 ‘开始’==> ‘控制台’==> 双击‘系统’之后出现下图：

    网路识别

  5. 在上面的图示当中，如果网路识别是不对的，那么就可以按下 ‘变更’来重新输入，如下所示：

    网路识别

    输入正确之后，只要重新开机，那么就可以使用区域网路啰！
基本上， Windows 的网路参数设定是相当的简单的！鸟哥这里仅介绍修改 IP 与相关网路参数的方式而已。 未来如果还需要搭配 DHCP 主机、NAT 主机等等伺服器的设定时，会再次的提醒使用者 Windows 的设定资讯喔！尤其是 SAMBA 主机的设定中， Windows 的网路识别就显的相当的重要呢！

2002/07/22：初次完成了区域网路架设的基本架构
2003/08/17：将整个文章重新修订，移除一些已经在 网路基础 里面谈过的内容，并且新增了表头的说明。
2003/08/20：加入课后练习了。
2003/09/19：加入参考用解答咯！
2005/05/05：将原本介绍平行线与跳线的 N-Way 错误，订正为 auto MDI/MDI-x
2006/07/13：将旧的文章移动到 此处。
2006/07/14：加入 Linux distribution 的说明，并且重新校稿更新内容，如布线部分。
2006/07/15：取消 Windows 2000, 98。
2002/07/21以来统计人数


鸟哥的 Linux 私房菜 -- 连上 Internet 的方法与步骤

为取得较佳浏览结果，请爱用 firefox 浏览本网页

连上 Internet
切换解析度为 800x600
最近更新日期：2006/07/24
呼呼！终于要来到修改 Linux 网路参数的章节了！在前面的 网路基础 章节内我们知道了主机要连上 Internet 需要一些正确的网路参数设定，这些设定在 Windows 系统上面的修改则在 区域网路的架构 里面进行了说明。在这一章当中，我们则主要以固定 IP 的设定方式来修改 Linux 的网路参数，同时，也会介绍如何使用 ADSL 的拨接方式来上网，此外，因为 Cable modem 使用者也不在少数，所以我们也说明一下 Cable modem 在 Linux 下的设定方式喔！ 最后，由于笔记型电脑使用者大增，由于笔记型电脑常使用无线网路，因此本文也加入了无线网路的连线介绍啊！

1. Linux 连上 Internet 前的注意事项
    1.1 Linux 的网路卡
    1.2 编译网路卡驱动程式
    1.3 Linux 网路相关设定档案
 2. 连上 Internet 的方法
    2.1 固定 IP 的上网方式 (适用学术网路、ADSL 固定制)
    2.2 可自动取得 IP 的环境 (适用 Cable modem、IP 分享器的环境)
    2.3 ADSL 拨接上网 (适用 ADSL 拨接)
 3. 无线网路--以笔记型电脑为例
    3.1 无线网路所需要的硬体
    3.2 网路安全方面
    3.3 开始连线
 4. 常见问题说明
    4.1 内部网域使用某些连线服务(如 FTP, POP3)所遇到的连线延迟问题
    4.2 网址列无法解析问题
    4.3 预设路由的问题
 5. 重点回顾
6. 课后练习
7. 参考资料
8. 针对本文的建议：http://phorum.vbird.org/viewtopic.htm?p=112420
大标题的图示 Linux 连上 Internet 前的注意事项：
要连上 Internet 时，由前几章的资料来说，我们知道需要设定一组网路参数， 包括 IP, netmask, network, broadcast, gateway 以及 DNS 主机的 IP 等等， 那我们也知道，其实整个主机最重要的设定，就是‘先要驱动网路卡’，否则主机连网路卡都捉不到时， 怎么设定 IP 参数都是没有用的，您说是吧！所以底下我们就来谈一谈， 您要如何确定网路卡已经被捉到，而 Linux 主机的网路参数又该如何设定？

小标题的图示 Linux 的网路卡
在 Linux 里面的各项装置几乎都是以档案名称来取代的，例如 /dev/hda 代表 IDE1 介面的第一个 master 硬碟等等。 不过，网路卡的代号 (Network Interface Card, NIC) 却是以模组对应装置名称来代替的， 而预设的网路卡代号为 eth0 ，第二张网路卡则为 eth1 ，以此类推。

我们知道网路卡其实是硬体，所以当然需要核心支援才能驱动他。 一般来说，目前新版的 Linux distributions 预设可以支援的网路卡晶片组数量已经很完备了， 包括大厂的 3COM, Intel 以及初阶的 RealTek, D-Link 等网路卡晶片都已经被支援， 所以使用者可以很轻易的设定好他们的网路卡。不过，万一您的网路卡晶片组开发商不愿意释出开放源 (Open Source) 的硬体驱动程式，或者是该网路卡太新了，使得 Linux 核心来不及支援时， 那么您就得要透过：
  • 重新编译核心
  • 编译网路卡的核心模组
好让核心可以支援网路卡这块硬体啦！但是，重编核心或编译网路卡核心模组都不是简单的工作， 而且有时原始码又可能无法在每部主机上面编译成功，所以万一您的网路卡真的不被预设的 Linux 网路晶片所支援，那么鸟哥真的建议直接换一块被 Linux 支援的网路卡吧，例如很便宜的螃蟹卡！ 免得花了太多时间在硬体确认上面，划不来的！ ^_^

如果您是照鸟哥推荐的，使用 RLT 8139 晶片 ( RealTek 8139 ) 的网路卡 ( 就是螃蟹卡 ) ，那您应该在安装 Linux 的时候就已经捉到网路卡了，那真是恭喜您啦！ 因为您的网路卡应该已经可以正常的工作啰！那如果在安装的时候并没有捉到网路卡呢？ 该如何是好？那也不用担心，因为您也可以事后才安装网路卡的驱动程式呀！不过，因为 Linux 并不像 Windows 是那样的随插即用，所以需要动一些手术的！

另外，其实有的时候 Linux 的预设网路卡模组可能无法完全 100% 的发挥网路卡的功能的， 所以，有的时候您还是得必须要自行编译网路卡的模组才行喔！当然， 那个网路卡的模组就得要自行由网路卡开发商的官方网站下载了！不过，如果您的网路卡是自行编译安装的， 那么每次重新安装其他版本的核心时，您都必须要自行重新手动编译过该模组。 因为模组与核心是有相关性的啊！

好了，假设您的网路卡已经在主机上面，不论是内建的还是自行安插到 PCI 或 PCI-x 或 PCI-E 的介面上， 那么如何确认该网路卡有被核心捉到呢？很简单啊！就利用 dmesg 来查阅即可：
[root@linux ~]# dmesg | grep -in eth
117:divert: not allocating divert_blk for non-ethernet device lo
171:divert: allocating divert_blk for eth0
227:divert: not allocating divert_blk for non-ethernet device sit0
228:eth0: no IPv6 routers present

[root@linux ~]# dmesg | cat -n | less
#...前面省略...
   169  3c59x: Donald Becker and others. www.scyld.com/network/vortex.html
   170  0000:00:08.0: 3Com PCI 3c905C Tornado at 0xe800. Vers LK1.1.19
   171  divert: allocating divert_blk for eth0
#...后面省略...
透过这个 dmesg 可以发现系统在开机时确实有捉到网路卡，然后透过搜寻行号，就能够找到该网路卡的驱动模组； 当然，您也可以透过 lspci 来查阅网路卡的相关模组呐！ 另外，您也可以透过这个 dmesg 了解到该张网路卡的代号喔！举例来说，鸟哥上面这个讯息就显示： 我的这张网路卡代号是 eth0
[root@linux ~]# lspci
00:08.0 Ethernet controller: 3Com Corporation 3c905C-TX/TX-M [Tornado] (rev 74)
看到了吧？鸟哥的某一部主机就是使用 3Com 的网路卡啊！Linux 系统本身就内建了 3c905C 这个驱动程式， 所以鸟哥根本不需要自行安装驱动程式呐！真是高兴！ ^_^ 那么这个 3c905 的驱动程式放在哪里啊？就是核心模组啊！在这个地方：
[root@linux ~]# cd /lib/modules/`uname -r`/kernel/drivers/net
[root@linux net]# modinfo 3c59x.ko
filename:       3c59x.ko
author:         Donald Becker <becker@scyld.com>
description:    3Com 3c59x/3c9xx ethernet driver LK1.1.19 10 Nov 2002
license:        GPL
version:        LK1.1.19 DBFD1C112761D573276AC45
parm:           debug:3c59x debug level (0-6)
.....以下省略.....
你可以先以 lsmod 查询各个相关的模组后，再到这个地方来检查，或者是直接以上面这个目录下的档案， 配合 lsmod 所显示出来的各个模组名称相对应，以取得各个网路卡的模组名称说！这样了解吗？ OK 那你如何知道你的网路卡卡号呢？很简单啊！不管有没有启动你的网路卡，都可以使用： ‘ ifconfig eth0 ’来查询你的网卡卡号。 如果网路卡已经安装好了，那么请前往固定 IP 上网方式去设定 ifcfg-eth0 这个档案 (如果是新增的网卡，这个档案可能不会存在喔！，需要自己建立)。 好了，万一你的网路卡无法被驱动，不过好在官方有提供相关的原始码时， 您就可以自行编译啦！

小标题的图示 编译网路卡驱动程式
如果你买到的网路卡实在太新，导致 Linux 预设核心不支援， 或者您实在是很想要一些官方网站提供的驱动程式的新功能， 那实在就得要自行编译核心啦！ 事实上，如果您要新添购硬体时，请先查阅一下硬体包装上面是否提及支援 Linux 的字样， 因为有些硬体厂商在推出新硬体时，常常会漏掉 Linux 驱动程式的撰写， 如果包装上面有提到支援的话，那么至少您会获得官方网站所提供的驱动程式原始码啊！ ^_^

鸟哥以我们实验室内一部 P-4 内建 Gigabit 乙太网路卡的 CentOS Linux 系统来作介绍， 这部主机的内建乙太网路使用的是 Marvell 的 88E8001 晶片，鸟哥到他们网站上面找到了一个 2006/04 释出的最新驱动程式来安装，该原始的档案名称为 install-8_40.tar.bz2 ，看到 .tar.bz2 就应该知道他是属于原始码，虽然鸟哥这部主机已经正确的捉到网路卡了， 不过，我们还是来更新一下让这个模组成为最新的驱动程式吧！ ^_^

另外，记得啊，要编译就得要有 gcc, make, kernel-devel 等套件才行喔！不要说你忘了！ 赶紧回到基础篇里面看看先！ 假设您已经：
  • 前往官方网站取得驱动程式的原始码了；
  • 已经在您的系统上面安装了 gcc, make, kernel-devel 等套件；
那接下来的编译步骤是这样的：
  1. 解压缩与编译：

    假设您下载下来的档案放置在 /root 内的话，那么使用 root 的身份进行如下工作吧：
    [root@linux ~]# cd /usr/src
[root@linux src]# ln -s kernels/2.6.9-34.0.1.EL-smp-i686/ linux
[root@linux src]# cd ~
    上面这个步骤很重要！因为驱动程式的模组都会需要找到核心的包含档案与相关函式库， 而一般来说， Linux kernel 2.6 以后的版本，则都会预设将核心原始码放在 /usr/src/kernels/(version) 这个目录内，但一般程式却是假设核心原始码在 /usr/src/linux，因此我们必须要先作个手术，将原始码与 /usr/src/linux 作个连结啊！请注意，那个原始码请依照您的核心版本与 Linux distribution 之公布为准。
    [root@linux ~]# tar -jxvf install-8_40.tar.bz2
[root@linux ~]# cd DriverInstall
# 此时在该目录下有个 README 的档案，记得看一看，这个档案内会说明很多资讯，
# 包括如何编译，以及这个模组所支援的晶片组哩！
[root@linux DriverInstall]# ./install.sh
    这个模组写的比较人性化，因为他有给予一个可直接安装测试的 script， 所以我们可以直接执行这个指令即可，很单纯吧！ ^_^ 。不过记得， 这些动作请在主机前进行。因为这个 script 会主动的重新启动网路卡喔！ 所以如果你是在网路上连线到此主机上面动作的话，嘿嘿！那可是会失败的！ 这个指令会有很多的选项在里面，请依序选择：
    • 1) installation
    • y(install)
    然后这个 script 便会主动的进行编译、模组卸除以及模组安装到 /lib/modules/`uname -r`/kernel/drivers/net 这个目录中， 并且尝试载入这个模组，以及启动网路卡喔！如果一切无误，您就会看到如下画面：
     eth0: network connection up using port A
     speed:           1000
     autonegotiation: yes
     duplex mode:     full
     flowctrl:        symmetric
     role:            slave
     irq moderation:  disabled
     scatter-gather:  enabled
     tx-checksum:     enabled
     rx-checksum:     enabled
     rx-polling:      enabled
    这样就算安装妥当啰！很简单吧！ ^_^

  2. 模组之测试与处理

    事实上，刚刚我们那个模组其实已经主动的载入到我们的系统当中了， 不过，如果您所取得的原始码并没有附上这么一支人性化的 script 的话，那么您就得要自行进行底下的动作了。
    [root@linux ~]# ls -l
drwxr-xr-x  2 root root   4096 Jul 20 11:57 sk98lin
[root@linux ~]# ls -l sk98lin
-rw-r--r--  1 root root 2666344 Jul 20 11:57 sk98lin.ko
# 上面那个目录假设是我编译出来的模组，里面还会有一个档案喔！那个档案就是
# sk98lin.ko ，要注意，新的 2.6 版的核心模组副档名都变成 .ko 的格式了！

[root@linux ~]# cp -a sk98lin /lib/modules/`uname -r`/kernel/drivers/net
# 注意啊！整个网路卡驱动模组就是放在上面的目录中，不要写错了。

[root@linux ~]# depmod -a
# 将所有的模组进行重新分析的工作！建立关连档案

[root@linux ~]# lsmod | grep 'sk98lin'
# 先确认‘sk98lin’这个模组不存在，然后就可以开始测试：

[root@linux ~]# modprobe sk98lin
[root@linux ~]# lsmod | grep 'sk98lin'
# 如果有相关的字样跑出来时，就表示这个模组可以顺利的被载入啦！
    如果可以顺利载入的话，恭喜您，您所自行编译的驱动程式已经搞定啦！ 不过，当有新版本的核心释出时，您也安装了新版的核心，那么上面的动作您就得要再进行一次， 为什么呢？想一想，刚刚您将编译出来的驱动程式模组放在哪里？ 然后编译的时候参考的核心原始码又是在哪里？那您就会晓得‘为什么’了！ ^_^

  3. 设定开机自动启动网路卡模组

    我们前面提到，Linux 的网路卡其实仅是一个代号，并不是类似硬碟的装置档案，所以， 我们必须要指定这个代号与模组的对应才行，在 CentOS (Red Hat 系统) 的对应是使用 /etc/modprobe.conf ，至于旧版的 2.4 核心中，则使用的是 /etc/modules.conf ，注意一下您的核心版本。 鸟哥的 CentOS 4.3 使用的是 /etc/modprobe.conf ，所以我就得这么做：
    [root@linux ~]# vi /etc/modprobe.conf
# 修改或增加底下这一行吧！
alias eth0 sk98lin

[root@linux ~]# sync; reboot
    为了测试一下刚刚的设定是否会生效，通常鸟哥都会尝试一次重新开机， 然后开机完成之后观察一下是否有正确的启动网路卡，并观察一下模组载入的情况， 如果一切都顺利，那就太完美了！

  4. 尝试设定 IP

    等到一切就绪之后，总得试看看这样的网路卡模组是否可以顺利的设定好 IP 吧？ 所以我们先手动给他一个私有 IP 看看先：
    [root@linux ~]# ifconfig eth0 192.168.1.100
[root@linux ~]# ifconfig
eth0      Link encap:Ethernet  HWaddr 00:01:BA:77:16:52
          inet addr:192.168.1.100  Bcast:192.168.1.255  Mask:255.255.255.0
.....以下省略.....
    嘿嘿！真的设定妥当哩！然后利用 ping 这个指令去 ping 一下网域内的其他电脑， 看看能不能有回应，就知道您的网路卡是否 OK 的啦！通常是没有问题的啦！
小标题的图示 Linux 网路相关设定档案
要开始玩 Linux 网路之前，请您务必了解 Linux 网路相关设定档案放置的目录与档名！这真的很重要！因为在 Linux 底下修改 IP 只要动到一个档案即可，修改主机名称也只要一个档案，所以只要将这些档案名称记起来，呵呵！ 未来在进行网路的测试与修订时，真的会事半功倍～完全不需要什么 linuxconf, webmin 等额外工具的帮助， 真的很简单啦！底下赶紧来说一说与 Linux 网路最相关的几个档案档名与他的用途！
  • /etc/sysconfig/network
    这个档案主要的功能在于设定‘主机名称( HOSTNAME )与启动 Network 与否’！一般来说，如果您变动过这个档案内的主机名称时，请务必重新开机 (reboot)， 因为这样才会让系统上面所有的程式都使用最新设定的主机名称喔！( 在 SuSEL 上面，主机名称是记录在 /etc/HOSTNAME 里面的！)

  • /etc/sysconfig/network-scrips/ifcfg-eth0
    这个档案的内容即是设定网路卡参数的档案啦！里面可以设定‘network, IP, netmask, broadcast, gateway, 开机时的 IP 取得方式( DHCP, static ), 是否在开机的时候启动’等等。至于 ifcfg-eth0 指的是第一块网路卡，而第二块网路卡为 ifcfg-eth1 以此类推。(在 SuSE 上面则是使用 /etc/sysconfig/network/ifcfg-eth0 )。

  • /etc/modprobe.conf
    如果硬体要能动作，当然要核心有支援才行！同时，我们也可以利用外挂的核心模组 (可以将他想成是驱动程式) 来驱动硬体，而开机时用来设定载入核心模组的档案就是 modprobe.conf 啦。一般来说，目前的 distributions 通常使用模组的方式来编译网路卡驱动程式，所以， 当您安装完毕后，您的网路卡与模组对应通常已经写到这个档案当中啰！

  • /etc/resolv.conf
    我们在网路基础里面稍微提到的 DNS 功能是什么？对啦， 就是进行主机名称与 IP 的对应！而 resolv.conf 就是设定 DNS IP (名称解析伺服器) 的档案， 常常有人提到‘咦！我已经可以 ping 到外部电脑的公共 IP 了，为何输入网址却无法连线？’ 通常发生的错误就是这个档案里面的设定不正确啦！请注意！ 通常这个档案可以输入中华电信的 DNS ( 168.95.1.1 )！

  • /etc/hosts
    这个档案可以记录电脑的 IP 对应主机的名称或者主机的别名！特别留意的是， 在区域网路内有些服务需要反查 Client 的身份，此时就会动用到主机名称对应 IP 的资料。 但是因为区域网路内使用私有保留 IP ，当然无法进行 Hostname 对应 IP 的行为， 这个时候该服务就会呆呆的等待 30~60 秒～如果可以避过这个反查，或者是直接告诉主机 Hostname 与 IP 的对应，那么就可以节省这个反查的时间了！所以，如此一来省去反查的时间，就可以改善 LAN 内的连线速度了！这个 hosts 就是用来设定 Hostname 对应 IP 的啦！ 更多的资讯请查阅后续伺服器章节 DNS 伺服器的介绍。

  • /etc/services
    这个档案则是记录架构在 TCP/IP 上面的总总协定，包括 http, ftp, ssh, telnet 等等服务所定义的 port number ，都是这个档案所规划出来的。如果您想要自订一个新的协定与 port 的对应，就得要改这个档案了；

  • /etc/protocols
    这个档案则是在定义出 IP 封包协定的相关资料，包括 ICMP/TCP/UDP 这方面的封包协定的定义等。
大概知道上面这几个档案后，未来要修改网路参数时，那就太简单了！ 至于网路方面的启动指令的话，可以记得几个简单的指令即可喔！
  • /etc/init.d/network restart
    这个 script 最重要！因为可以一口气重新启动整个网路的参数！ 他会主动的去读取所有的网路设定档，所以可以很快的恢复系统预设的参数值。

  • ifup eth0 (ifdown eth0)
    启动或者是关闭某张网路介面。可以透过这个简单的 script 来处理喔！ 这两个 script 会主动到 /etc/sysconfig/network-scripts/ 目录下， 读取适当的设定档来处理啊！ (例如 ifcfg-eth0)。
大概您只要只到这些基本的指令与档案，哈哈！网路参数的设定就太简单啦！ 不过，最好您还是要了解 shell script ，比较好！因为可以追踪整个网路的设定条件。 why ？这是因为每个 distributions 的设定资料可能都不太相同，不过却都以 /etc/init.d/network 作为启动的 script ， 因此，您只要了解到该档案的内容，很容易就追踪得出来您的设定档所需要的内容呢！对吧！

大标题的图示 连上 Internet 的方法：
在前一章区域网路的简易设定里面，我们知道了连上 Internet 的方法有好多种，不过在现今的台湾，主要的连线方法其实是以 (1)学术网路、(2)ADSL 固接与拨接、(3)Cable modem 等方式为主， 此外，由于目前使用 Linux notebook 的使用者大增，而 Notebook 通常是以无线网路来连线的， 所以鸟哥在这里也尝试使用一款无线网路来进行连线设定。 至于传统的 56 Kbps 拨接则因为速度较慢且使用度越来越低，所以在这里就不多做介绍了。

另外请特别留意，底下的说明全部都是假设您的网路卡已经正常驱动的情况下，所以， 万一您的网路卡还是无法启动时，看是要(1)参考前面的说明重新编译一个模组，还是(2)早点放弃， 赶紧买张便宜的网路卡来安装与设定，那就完全依照您的需求啦！

小标题的图示 固定 IP 上网方式
所谓的固定 IP 就是指在您的网路参数当中，你只要输入既定的 IP 参数即可。那么这个既定的 IP 来自哪里呢？ 一般来说，他可能来自于：
  • 学术网路：由学校单位直接给予的一组 IP 网路参数；
  • 固定制 ADSL：向 ISP 申请的一组固定 IP 的网路参数；
  • 企业内部或 IP 分享器内部的区域网路：例如企业内使用私有 IP 作为区域网路的连线之用时， 那么我们的 Linux 当然也就需要向企业的网管人员申请一组固定的 IP 网路参数啰！
这样清楚吗？也就是说，我们取得的固定 IP 参数并非一定是 public IP 喔！反正就是一组可接受的固定 IP 就是了！ 所以在架设您的环境之前，请先注意所有网路参数的来源正确性啊！ 好了，那么现在假设我的 Linux 主机需要的参数如下所示：
Hostname  centos.dm.tsai

IP:       192.168.1.13
Netmask   255.255.255.0
Network   192.168.1.0
Broadcast 192.168.1.255
Gateway   192.168.1.2

DNS IP    168.95.1.1
底下我们就分别针对上面的各项设定来进行档案的重新修改啰！
  1. 修改主机名称： /etc/sysconfig/network
    修改主机名称真的是很简单！直接在档案内修订即可！
    [root@linux ~]# vi /etc/sysconfig/network
NETWORKING=yes
HOSTNAME=centos.dm.tsai
    够简单吧！这样就将主机名称改好了！记得：如果您曾经更动过这个档案， 最好重新开机，以使所有的服务都可以使用到新主机名称。

  2. 设定网路参数： /etc/sysconfig/network-scripts/ifcfg-eth0
    请记得，这个 ifcfg-eth0 与档案内的 DEVICE 名称设定需相同，并且，在这个档案内的所有设定， 基本上就是 bash 的变数设定规则啦！
    [root@linux ~]# vi /etc/sysconfig/network-scripts/ifcfg-eth0
DEVICE=eth0                <== 网路卡代号，必须要 ifcfg-eth0 相对应
BOOTPROTO=static           <== 开机协定，有 dhcp 及 static 这里是 static
BROADCAST=192.168.1.255    <== 就是广播位址啰
HWADDR=00:40:D0:13:C3:46   <== 就是网路卡位址
IPADDR=192.168.1.13        <== 就是 IP 啊
NETMASK=255.255.255.0      <== 就是子遮罩网路
NETWORK=192.168.1.0        <== 就是网域啊！该网段的第一个 IP
GATEWAY=192.168.1.2        <== 就是预设路由！
ONBOOT=yes                 <== 是否开机启动的意思
MTU=1500                   <== 就是最大传输单元的设定值。
#GATEWAYDEV=eth0           <== 主要路由的装置为那个，通常不用设定
    上面的资料很好理解吧！请注意每个变数(左边的英文)都应该要大写！ 否则我们的 script 会误判！关于 IP 的四个参数 (IPADDR, NETMASK, NETWORK, BROADCAST) 鸟哥在这里就不再多说， 要谈的是几个重要的设定值：

    • DEVICE：这个设定值后面接的装置代号需要与档名 (ifcfg-eth0) 那个装置代号相同才行！否则会显示找不到装置名称！

    • BOOTPROTO：启动该网路介面时，使用何种协定？ 如果是手动给予 IP 的环境，请输入 static 或 none ，如果是自动取得 IP 的时候， 请输入 dhcp (不要写错字！)

    • GATEWAY：代表的是‘整个主机系统的 default gateway’， 所以，设定这个项目时，请特别留意！不要有重复设定的情况发生喔！也就是当您有 ifcfg-eth0, ifcfg-eth1.... 等多个档案，只要在其中一个档案设定 GATEWAY 即可

    • GATEWAYDEV：如果您不是使用固定的 IP 作为 Gateway ， 而是使用网路装置作为 Gateway (通常 Router 最常有这样的设定)，那也可以使用 GATEWAYDEV 来设定通讯闸装置呢！不过这个设定项目很少使用就是了！

    • HWADDR：这个东西就是网路卡的卡号了！有啥用途呢？ 记得以前我们常常在讲，如果有两块一模一样的网路卡存在时，例如在一部主机上面安装两张螃蟹卡， 由于是相同的晶片，所以在 /etc/modprobe.conf 内无法指定出明确的 eth0 与 eth1 的对应 (因为模组使用相同嘛！)，那么哪一张才是 eth0 ？呵呵！大家有福了！ 利用 HWADDR 指定网路卡的卡号，就能够明白的定义出不同网卡的代号啦！很方便吧！

    事实上，如果您想要了解每个变数的项目代表的意义时，建议可以参考 /sbin/ifup 这个 script 的内容， 这个 script 对于每个项目的应用都记录的挺清楚的！ ^_^

  3. 启动与关闭网卡：
    启动与关闭的方式有两种，底下分别介绍：
    [root@linux ~]# ifup eth0
[root@linux ~]# ifdown eth0
# 上面的作法是针对 eth0 来进行启动 (ifup) 与关闭 (ifdown) ；

[root@linux ~]# /etc/init.d/network restart
# 针对这部主机的所有网路介面 (包含 lo) 与通讯闸进行重新启动，
# 所以网路会停顿再开喔！
    就样就能够启动网路卡了！再来赶紧测试观察看看，我们可以直接下达 ifconfig 以及使用 ping 来检查看看喔！
    [root@linux ~]# ifconfig eth0
eth0      Link encap:Ethernet  HWaddr 00:40:D0:13:C3:46
          inet addr:192.168.1.13  Bcast:192.168.1.255  Mask:255.255.255.0
          inet6 addr: fe80::240:d0ff:fe13:c346/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:229458 errors:16 dropped:0 overruns:0 frame:0
          TX packets:117415 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:345006035 (329.0 MiB)  TX bytes:7177543 (6.8 MiB)
          Interrupt:5 Base address:0x3e00
# 记得啊！有出现上头那个 IP 的资料才是正确的启动；
# 另外，也注意一下那个 MTU 的数值呐！ ^_^

[root@linux ~]# ping -c 3 192.168.1.2
PING 192.168.1.2 (192.168.1.2) 56(84) bytes of data.
64 bytes from 192.168.1.2: icmp_seq=0 ttl=64 time=0.216 ms
64 bytes from 192.168.1.2: icmp_seq=1 ttl=64 time=0.227 ms
64 bytes from 192.168.1.2: icmp_seq=2 ttl=64 time=0.222 ms

--- 192.168.1.2 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2000ms
rtt min/avg/max/mdev = 0.216/0.221/0.227/0.017 ms, pipe 2
# 注意啊！有出现 ttl 才是正确的回应！如果出现‘ Destination Host Unreachable ’
# 表示没有成功的连线到您的 GATEWAY 那表示出问题啦！赶紧检查有无设定错误。
    一般来说，到此为止您的 IP 设定已经成功啦！不过，偶而您会发现无法找到 yahoo.com.tw 的 IP 那！ 那表示您必须要进行底下的工作！

  4. 设定 DNS 的 IP： /etc/resolv.conf
    这个档案重要啦！他会影响到您是否可以查询到主机名称与 IP 的对应喔！ 通常如下的设定就 OK 了！
    [root@linux ~]# vi /etc/resolv.conf
nameserver 168.95.1.1
nameserver 139.175.10.20
    我们以中华电信与 SeedNet 在南部的 DNS 主机之 IP 作为设定的方式！ 请注意一下，如果您不知道您的最接近的 DNS 主机的 IP ，那么直接输入 nameserver 168.95.1.1 这个中华电信的 DNS 主机即可！不过如果您公司内部有设定防止 DNS 的要求封包的防火墙规则时， 那么您就得要请教贵公司的网管单位告知您的 DNS IP 设定啦！然后赶紧测试看看：
    [root@linux ~]# nslookup tw.yahoo.com
Server:         168.95.1.1
Address:        168.95.1.1#53

Non-authoritative answer:
tw.yahoo.com    canonical name = tw.yahoo-ap1.akadns.net.
Name:   tw.yahoo-ap1.akadns.net
Address: 202.43.195.52
    仔细观察，得要出现有 IP 的字样，才算是设定成功喔！

上面这几个步骤需要一步一步来，如果前面失败，后面就不可能成功的！ 所以请不要尚未启动网路前，就使用 nslookup 去追查 IP ，那是‘查不到的’啦！ 注意流程啊！得要网路好了，才能够处理其他在网路上面的 DNS 资料，您说是吧！ ^_^

小标题的图示 可自动取得 IP 的环境
可自动取得 IP 的环境是怎么回事啊？不是很简单吗？当您在 IP 分享器后头的主机在设定时， 不是都会选择‘自动取得 IP ’吗？那就是可自动取得 IP 的环境啦！那么这个自动取得是怎么回事啊？ 也不难了解啦，其实就是‘有一部主机提供 DHCP 服务给整个网域内的电脑’就是了！ 例如 IP 分享器就可能是一部 DHCP 主机。那么 DHCP 是啥？ 他是：Dynamic Host Configuration Protocol 的简写，顾名思义， 他可以‘动态的调整主机的网路参数’的意思。详细的 DHCP 功能我们会在后面的章节说明的。

好了，那么这个方法适合哪些连线的方式呢？大致有这些：
  • Cable Modem：就是使用电视缆线进行网路回路连线的方式啊！ 这个方式属于媒体共享式，在社区内比较常见；
  • ADSL 多 IP 的 DHCP 制：就鸟哥所知， SeedNet 有推出一种专案， 可以让 ADSL 用户以 DHCP 的方式来自动取得 IP ，不需要拨接。那使用的也是这种方法！
  • IP 分享器或 NAT 有架设 DHCP 服务时：当您的主机位于 IP 分享器的后端，或者是您的 LAN 当中有 NAT 主机且 NAT 主机有架设 DHCP 服务时， 那取得 IP 的方法也是这样喔！
反正可以自动取得 IP 的条件下，大多数都是使用底下的方法啦！ 请先参考前一小节固定 IP 的连线方法设定好步骤 1~4 的所有项目， 其中第2个步骤需要改成底下的样子：
[root@linux ~]# vi /etc/sysconfig/network-scripts/ifcfg-eth0
DEVICE=eth0
ONBOOT=yes
BOOTPROTO=dhcp
没盖你喔！只要这三个项目即可，其他的都给他注解 (#) 掉！避免互相干扰！然后给他重新启动网路：
[root@linux ~]# /etc/init.d/network restart
我们区域网路内的 IP 分享器或 DHCP 主机，就会立刻帮您的 Linux 主机做好网路参数的规划， 包括 IP 参数与 GATEWAY 等，就通通设定妥当啦！很方便也很简单吧！
Tips:
有些版本会主动的修改 /etc/resolv.conf 这个档案，所以您必须要随时注意一下这个档案的内容， 另外， CentOS 会主动的建立一个说明文件资料在 /etc/dhclient-eth0.conf ，您也可以自行瞧一瞧去！ 		鸟哥的图示
小标题的图示 ADSL 拨接上网
终于来到台湾最热门的 ADSL 拨接上网的介绍啦！来谈一谈如何在 Linux 上拨接上网吧！ 要拨接上网时，可以使用 rp-pppoe 这套软体来帮忙，所以，您必须要确认你的 Linux distributions 上面已经存在这个玩意儿了！(注： SuSE 使用的是其他的软体，您应该要自行使用 yast 来设定即可。) CentOS 本身就含有 rp-pppoe ，请使用原版光碟，或者是使用 yum 来进行安装吧！
[root@linux ~]# rpm -q rp-pppoe
rp-pppoe-3.5-22    <==您瞧瞧！确实有安装喔！
当然，很多 distributions 都已经将拨接这个动作归类到图形介面里面去了， 所以可能没有提供 rp-pppoe 这个咚咚，没关系，您可以到底下的网站去取得的：
  • http://www.roaringpenguin.com/pppoe/
  • http://freshmeat.net/projects/rp-pppoe/
然后再自行手动安装即可。如何安装的过程鸟哥在这里就不谈了，请自行前往基础篇的原始码与 Tarball查阅相关资料吧。 另外请注意，虽然整个连线是由主机的乙太网路卡连接到 ADSL 数据机上，然后再透过电话线路连线到 ISP 的机房去，最后在主机上以 rp-pppoe 拨接达成连线。但是 rp-pppoe 使用的是 Point to Point (ppp) 的点对点协定所产生的网路介面，因此当您顺利的拨接成功之后， 会多产生一个实体网路介面‘ ppp0 ’喔！ 而由于 ppp0 是架构在乙太网路上的，所以 eth0 也不能关掉啊！注意注意！因此，拨接成功后就会有：
  • 内部回圈测试用的lo介面；
  • 网路卡 eth0 这个介面；
  • 拨接之后产生的经由 ISP 对外连接的 ppp0 介面。
上头这三个介面是完全独立的，互不相干，所以关于 eth0 您可以这样思考：
  • 这张网路卡 (假设是 eth0) 有接内部网路(LAN)：
    如果是这样的话，那么您的 IP 设定参数： /etc/sysconfig/network-scripts/ifcfg-eth0 应该要给予一个私有 IP 以使内部的 LAN 也可以透过 eth0 来进行连线啊！所以我会这样设定：
    [root@linux ~]# vi /etc/sysconfig/network-scripts/ifcfg-eth0
DEVICE=eth0
BOOTPROTO=static
BROADCAST=192.168.1.255
IPADDR=192.168.1.13
NETMASK=255.255.255.0
NETWORK=192.168.1.0
ONBOOT=yes
    并请记得一件事情，那就是：‘千万不要有 GATEWAY 的设定！’， 否则 ppp0 拨接成功后又会产生另一个 default gateway ，就会造成问题了！

  • 没有内部网域：
    如果这部 Linux 主机是直接连接到 ADSL 上头，并没有任何内部主机与其连线， 也就是说，您的 eth0 有没有 IP 都没有关系时，那么上面的设定当中的那个‘ ONBOOT=yes ’ 直接改成‘ ONBOOT=no ’就好了！
至于其他的档案请参考前两小节固定 IP 的连线方法上面的步骤1, 3, 4 设定好！步骤 2 则依照刚刚提到的是否有接 LAN 的情况来设定，然后就可以开始准备拨接了！ 当然啦，拨接之前，请确认您的 ADSL 数据机 (小乌龟) 已经与主机连线妥当， 也取得帐号与密码，也安装好了 rp-pppoe ，然后就来处理吧！
  1. 关闭接在 ADSL 数据机上面的那张网卡
    说实在的，鸟哥比较建议将内外网域分的清清楚楚比较好，所以，通常我都是主机上面接两块网路卡， 一张对内一张对外，对外的那张网卡在拨接前先关闭，虽然没有关闭也不打紧， 不过曾有网友回报，如果不关闭时，有时候(机率很低)会无法拨接成功！假设连接到 ADSL 的网卡是 eth0 ，那么关闭很简单吧？
    [root@linux ~]# ifdown eth0
[root@linux ~]# ifconfig eth0 down
    这样就可以啦！

  2. 设定帐号与密码之连线设定
    假设 rp-pppoe 设定好了，如果您的版本没有 rp-pppoe 的话，请自行安装。 关于安装的方法可以参考本章最后的参考资料。然后就开始如下的设定：
    [root@linux ~]# adsl-setup
Welcome to the ADSL client setup.  First, I will run some checks on
your system to make sure the PPPoE client is installed properly...

LOGIN NAME
Enter your Login Name (default root): T1234567
# 注意啊！这个帐号名称是 ISP 给的，其中如果是 SeedNet ，输入如上，
# 如果是 Hinet 的话，就得要输入 username@hinet.com.tw ，后面的主机名也要写。

INTERFACE
Enter the Ethernet interface connected to the ADSL modem
For Solaris, this is likely to be something like /dev/hme0.
For Linux, it will be ethX, where 'X' is a number.
(default eth0): eth0
# 就是连接到 ADSL 数据机的那张网卡代号

Do you want the link to come up on demand, or stay up continuously?
If you want it to come up on demand, enter the idle time in seconds
after which the link should be dropped.  If you want the link to
stay up permanently, enter 'no' (two letters, lower-case.)
NOTE: Demand-activated links do not interact well with dynamic IP
addresses.  You may have some problems with demand-activated links.
Enter the demand value (default no): <==这里按 Enter 确定不要即可

DNS
Enter the DNS information here: 168.95.1.1
Enter the secondary DNS server address here: 139.175.10.20
# 这两个设定会影响 /etc/resolv.conf 的内容喔！

PASSWORD
Please enter your Password: <==这里则是输入您 ISP 给的密码
Please re-enter your Password: <==再一次密码

USERCTRL
Please enter 'yes' (two letters, lower-case.) if you want to allow
normal user to start or stop DSL connection (default yes): no
# 不让使用者可以启动或关闭 ADSL 的设定比较好吧！

The firewall choices are:
0 - NONE: This script will not set any firewall rules.  You are responsible
          for ensuring the security of your machine.  You are STRONGLY
          recommended to use some kind of firewall rules.
1 - STANDALONE: Appropriate for a basic stand-alone web-surfing workstation
2 - MASQUERADE: Appropriate for a machine acting as an Internet gateway
                for a LAN
Choose a type of firewall (0-2): 0
# 先不要密码！后面我们会使用 Linux 本机的防火墙！

Start this connection at boot time
Do you want to start this connection at boot time?
Please enter no or yes (default no):yes
# 是否要开机的时候就拨接？

Ethernet Interface: eth0
User name:          T1234567
Activate-on-demand: No
Primary DNS:        168.95.1.1
Secondary DNS:      139.175.10.20
Firewalling:        NONE
User Control:       no
Accept these settings and adjust configuration files (y/n)? y
# 如果没有问题就按下 y 开始写入设定档吧！
Adjusting /etc/sysconfig/network-scripts/ifcfg-ppp0
Adjusting /etc/resolv.conf
  (But first backing it up to /etc/resolv.conf.bak)
Adjusting /etc/ppp/chap-secrets and /etc/ppp/pap-secrets
  (But first backing it up to /etc/ppp/chap-secrets.bak)
  (But first backing it up to /etc/ppp/pap-secrets.bak)
# 上面的档案很简单吧！
# ifcfg-ppp0  ：亦即是 ppp0 这个网路介面的设定档案；
# resolv.conf ：这个档案会被备份后，然后以刚刚我们上面输入的资料取代；
# pap-secrets, chap-secrets：我们输入的密码就放在这里！
    哈哈！这样设定就成功啦！很简单吧！唯一需要注意的是在上面的 username 那个地方，千万注意， 因为 hinet 与 seednet 的设定是不一样的！千万小心呢！否则会无法连上线呦！此外， 由于我们在未来还会有 firewall 的建置，所以这里不太需要使用到防火墙啦！否则也可能无法连上 Internet 呦！另外，注意一下，我们上面使用 adsl-setup 的设定，其实最主要是修改两个档案， 分别是 /etc/ppp/pppoe.conf 这个主要设定档，以及 /etc/ppp/chap-secrets 这个密码储存档！ 仔细去察看一下 chap-secrets 这个档案的内容，您就可以知道您的密码是否输入错误了！ ^_^

  3. 开始拨接上网
    拨接很简单啊！
    [root@linux ~]# adsl-start
....Connect!
    这样就是显示连上 Internet 啦！通常比较容易出问题的地方在于硬体的连线情况， 请先确认所有的硬体连线没有问题喔！通常，如果您使用小乌龟 (ATU-R) 时， 请使用跳线连接网路卡与 ATU-R。另外一个容易出错的地方在于输入的帐号与密码， 帐号与密码都是您的 ISP 给您的，并且注意大小写(可以到 /etc/ppp/chap-secrets 察看一下是否设定错误？)

  4. 察看 IP 啦！
    直接使用 ifconfig ppp0 看看能否得到您的 IP 呢？没错！那就是啦！ ^_^
    [root@linux ~]# ifconfig ppp0
ppp0      Link encap:Point-to-Point Protocol
          inet addr:211.74.249.38  P-t-P:172.16.11.8  Mask:255.255.255.255
          UP POINTOPOINT RUNNING NOARP MULTICAST  MTU:1492  Metric:1
          RX packets:8356088 errors:0 dropped:0 overruns:0 frame:0
          TX packets:8532063 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:10
  5. 特殊状况：
    或许您会发现使用 rp-pppoe 拨接之后，您的 /var/log/messages 老是出现这样的讯息：
    [root@linux ~]# more /var/log/messages
May 10 18:02:22 testing pppoe[8527]: Bogus PPPoE length field (50)
    这是什么问题啊？在 RP-PPPOE 的官方讨论区上面提过，这个问题是由于 ISP 提供的讯息长度超过 rp-pppoe 预设的检查长度才会发生的一个警告讯息，事实上这个讯息并不重要，不用理会他也没有关系， 不会影响到 Internet 的运作。但是，这样的讯息在 /var/log/messages 里面每一分钟就出现一次， 实在很讨厌！怎么办，可以将他拿掉吗？！当然可以！您可以下载新的 Tarball 来重新编译过！ 详细的步骤是这样的：

    步骤一：下载新的 tarball (鸟哥这里以 3.5 版为例)：
    到底下的网站下载新的版本：
    http://www.roaringpenguin.com/pppoe/#download

    步骤二：在 /usr/local/src 底下解开档案，则造成 /usr/local/src/rp-pppoe-3.5/ 目录

    步骤三：到 /usr/local/src/rp-pppoe-3.5/src 底下去，修改这四个档案：
    * discovery.c
    * pppoe.c
    * pppoe-server.c
    * relay.c
    找到这四个档案内容如下代码：
      /* Check length */
    if (ntohs(packet.length) + HDR_SIZE > len) {
        syslog(LOG_ERR, "Bogus PPPoE length field (%u)",
               (unsigned int) ntohs(packet.length));
        return;
    }
    将他修改成为如下：
        /* Check length */
    if (ntohs(packet.length) + HDR_SIZE > len) {
        /* syslog(LOG_ERR, "Bogus PPPoE length field (%u)",
               (unsigned int) ntohs(packet.length)); */
        return;
    }
    请注意，上面每个档案都有多个同样的字串，请依序一个一个都修改掉才行！还没完喔！再到 pppoe.c 找到底下的字眼：
        if (plen + HDR_SIZE > len) {
        syslog(LOG_ERR, "Bogus length field in session packet %d (%d)",
               (int) plen, (int) len);
        return;
    }
    请将他改成：
        if (plen + HDR_SIZE > len) {
        /* syslog(LOG_ERR, "Bogus length field in session packet %d (%d)",
               (int) plen, (int) len); */
        return;
    }
    步骤四：然后开始编译与安装吧！
    [root@linux ~]# cd /usr/local/src/rp-pppoe-3.5/src
[root@linux src]# ./configure
[root@linux src]# make
[root@linux src]# make install
    当然，您得先移除 rp-pppoe 才行喔！ ^_^

    步骤五：利用 adsl-setup ,adsl-start 再重新设定与启动看看吧！
很快的，这样您就已经做好 ADSL 拨接上网的动作了！很快乐吧！ 但是不要忘记了，现在您的主机可是没有任何防备的喔！所以，赶紧往下两节读一读去啊！ ^_^

大标题的图示 无线网路--以笔记型电脑为例
除了使用实体 RJ-45 线路来连接主机之外，由于现在笔记型电脑渐渐广为使用， 因此在笔记型电脑上面的无线网路 (Wireless) 也越来越重要啰～针对无线网路所提出的标准中， 以 IEEE 802.11b 及 802.11g 较为重要，其中 802.11g 这个标准的传输速度已经可以达到 54Mbps 的水准， 等于是快速乙太网路 (fast ethernet, 10/100 Mbps) 的一半了，比起以前的 11Mbps (802.11b) 要快的多！所以也渐渐的成为移动式装置之一的笔记型电脑常用的网路连线方式之一。

小标题的图示 无线网路所需要的硬体
我们知道在 RJ-45 的乙太网路环境中，以 switch/hub 以及网路卡与网路线最重要， 该架构中主要以 switch/hub 串接所有的网路设备。那么在无线网路中，当然也需要一个接收讯号的装置， 那就是无线基地台 (Wireless Access Point, 简称 AP) 了！ 另一个装置当然就是安装在电脑主机上面的无线网卡啰！

其实无线基地台本身就是个 IP 分享器了，他本身会有两个介面，一个可以与外部的 IP 做沟通， 另外一个则是作为 LAN 内部其他主机的 GATEWAY 啰！那其他主机上面只要安装了无线网卡， 并且顺利的连上 AP 后，自然就可以透过 AP (以 AP 为路由器) 来连上 Internet 啦！ 整个传输的情况可以用下图来示意：
无线网路的连线图示
图一、无线网路的连线图示

在上图中，我们假设 PC A 与 PC B 这两部主机都有安装无线网卡，因此他们可以扫瞄到区域网路内的 AP 存在，所以可以透过这个 AP 来连上 Internet 啊。在不考虑内部 LAN 连线的情况下， AP 如何连上 Internet 呢？虽然每部 AP 的控制介面都不相同，不过绝大部分的 AP 都是提供 Web 介面来设定的，因此您可以参考每部 AP 的说明书来进行设定， 在这里鸟哥就不多说了。

鸟哥底下将会以一般家庭常用的小型 AP 与无线网卡来说明一个案例， 鸟哥手边有的笔记型电脑是旧式的 MiTac 内有赛扬 366 CPU 及 192 MB 的记忆体， USB 版本为 1.1 ，够旧了吧！所以鸟哥额外加了扩充卡 (PCMCIA) 让 USB 提升到 2.0 版， 选择的 AP 为 PCi 这家公司制造的 BLW-54PM 无线基地台， 而无线网卡则是使用 USB 2.0 介面的 PCi 公司制造的 GW-US54Mini ， 会选择这个装置主要是因为 PCi 这一款无线网卡装置有支援 Linux 系统， 所以很容易被 Linux 捉到，较容易安装使用啦！ ^_^

小标题的图示 网路安全方面
如果您留心一下上面的图一，那么就可以发现一件事情，那就是：‘如果 AP 不设定任何连线限制，那任何拥有无线网卡的主机都可以透过这个 AP 连接上您的 LAN ’， 要知道，通常我们都会认为 LAN 是信任网域，所以内部是没有防火墙的， 亦即是不设防的状态，呵呵！如果刚好有人拿着笔记型电脑经过您的 AP 可 以接收讯号的范围，那么他就可以轻易的透过您的 AP 连接上你的 LAN ，并且可以透过你的 AP 连上 Internet ，如果他刚好是个喜欢搞破坏的 cracker ， 哈哈！那么当他使用您的 AP 去攻击别人时，最后被发现的跳板是谁？？当然是您的 AP！ 那是谁会吃上官司？够清楚了吧？而且您内部主机的资料也很有可能被窃取啊！

所以啦，‘无线网路的安全性一定是具有很大的漏洞的’， 没办法，因为无线网路的传输并不是透过实体的网路线，而是透过无线讯号，实体网路线很好控制， 无线讯号您如何侦测啊？对吧！因此，请您务必在您的 AP 上面进行好连线的限制设定， 一般可以这样做限制的：
  • 在 AP 上面使用网卡卡号 (MAC) 来作为是否可以存取 AP 的限制：
    如此一来，就只有你允许的网路卡才能够存取你的 AP ，当然会安全不少。不过这个方法有个问题， 那就是当有其他主机想要透过这个 AP 连线时，你就得要手动的登入 AP 去进行 MAC 的设定， 在经常有变动性装置的环境中 (例如公司行号)，这个方法比较麻烦～

  • 设定你的 AP 连线加密机制与金钥：
    另一个比较可行的办法就是设定连线时所需要的验证金钥！ 这个金钥不但可以在网路连线的资料当中加密，使得即使您的资料被窃听， 对方也是仅能得到一堆乱码，同时由于 client 端也需要知道金钥并且在连线阶段输入金钥， 因此也可以被用来限制可连线的用户啊！
当然，上面两种方法您可以同时设定，亦即不但需要连线的金钥，而且在 AP 处也设定能够存取的 MAC 网卡， 嘿嘿！这样一来，就更安全的多了！更多的 AP 安全方面的概念，可以参考底下这一篇文章的介绍：
  • 无线网路安全白皮书(三)：
    http://www.cert.org.tw/document/column/show.htm?key=61
关于 ESSID/SSID ：
想一想，如果您有两部 AP 在同一个区域网路内，那么请问一下， 当你的无线网卡在上网时，他会透过哪一个 AP 连线出去呢？很困扰，对吧！ 其实每部 AP 都会有一个连线的名字，那就是 ESSID ，这个 ESSID 可以提供给 client 端， 当 client 端需要进行无线连线时，他必须要说明他要利用哪一部 AP ，那个 ESSID 就是那时需要输入的资料了！在鸟哥的案例当中，我将我的 AP 设定为 BLW-VBIRD 这个名字， 并且给予一个金钥密码，设定的方法如同下图所示：

无线网路 AP 的金钥设定项目
图二、无线网路 AP 的金钥设定项目

如上图，在登入了 AP 的设定项目后，依序 (1)先选择无线网路，然后在右边的视窗当中 (2)取消 AutoLink 的设定，然后 (3)输入您的 SSID 识别码 (就是 ESSID)，最后再进入 (4)密码设定的项目啰！在按下‘设定加密’之后，他就会出现如下的画面：

无线网路 AP 的金钥设定项目
图三、无线网路 AP 的金钥设定项目

我们先选择 (1)加密的方式，在这里可以选择简单的 WEP 加密方式即可，然后 (2)输入加密的金钥长度，选择最长的吧！这个长度需要输入 26 个字元呐！之后当然就得 (3)输入 26 个密码 (金钥) 啰～在这里鸟哥随便先填一个，您可别真的跟鸟哥填一样的密码啊！ 填完之后就 (4)按下套用设定，最后才 (5)关闭，关闭回到前一个画面后， 给他按下‘储存设定’，如下图所示：

无线网路 AP 的金钥设定项目
图四、无线网路 AP 的金钥设定项目

这个时候在画面当中的‘加密机制’才会正式的启动啊！这个时候我们就会有底下两个资料：
  • ESSID 为 BLW-VBIRD
  • KEY 为 12345678901234567890123456
这两个资料很重要喔！我们底下会仔细的来说明啊！
小标题的图示 开始连线
OK！底下我们就来谈一谈，那么您的笔记型电脑如何透过无线网路实际的上线呢？ 首先当然就是需要安装驱动程式啦！再来则是需要让网卡代号与模组对上关系， 然后设定了网路卡设定档后，才能够连上 Internet 啦！底下我们就一个一个步骤来说明吧！
  1. 取得驱动程式并实际安装：

    鸟哥在这个案例当中使用的 USB 无线网卡的驱动程式，并没有在 CentOS 的预设核心内支援， 所以我必须要自行安装他的驱动程式才行！先来察看一下我们的主机是否有捉到这个 USB 的硬体装置呢？
    [root@linux ~]# dmesg | grep usb
usb 4-1: new high speed USB device using address 2
# 这里是说，有个高速 USB 装置使用第二个 USB 位址的意思。
# 既然知道这个位址，我们来查一查这个装置的内容吧！

[root@linux ~]# cat /proc/bus/usb/devices
T:  Bus=04 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#=  2 Spd=480 MxCh= 0
D:  Ver= 2.00 Cls=ff(vend.) Sub=ff Prot=ff MxPS=64 #Cfgs=  1
P:  Vendor=14ea ProdID=ab13 Rev=43.30
S:  Manufacturer=PCI
S:  Product=USB2.0 WLAN
.....后面省略.....
# 比较重要的就是上面的那个装置码以及厂商与产品代码了！
# 先给他抄写下来，因为等一下我们进行模组编译时会用到！
    呵呵！真的有捉到！那么就得要实际的来进行驱动程式的安装啰！ 这个驱动程式的下载可以前往他的官方网站： http://www.planex.com.tw/download/wireless/gw-us54mini.htm 来下载， 鸟哥下载的是 zd1211 的驱动程式，版本是 V1.2.0.0 ，这个版本在编译时， 似乎还是没有做得很好，所以我们依旧得要进行一些小手术来修订才行喔！ 假设您将下载的 tarball 解压缩到 /root/zd1211 档案当中了，那么如何编译呢？
    [root@linux ~]# cd zd1211
# 这个目录下有个 README 的档案，请记得好好查阅一下喔！

[root@linux zd1211]# cd zdsta
[root@linux zdsta]# vi Makefile
# 先修改底下这一行，应该是在第 15 行的地方，这里需要与你的核心对应喔！
# 我这里是使用 CentOS 4.3 并且升级过核心作为范例的！
KERNEL_SOURCE=/lib/modules/2.6.9-34.0.2.EL/build

[root@linux zdsta]# vi src/zdusb.h
# 很奇怪，我的 CentOS 4.3 不支援太长的型号名称，所以需要做个修改，
# 大约在第 16 行的地方，找到下列的字：
#define PRODUCT_GW-US54MINI    0xAB13
# 将他改成下列的模样：
#define PRODUCT_US54MINI    0xAB13
# 顺便仔细看一下第 15, 16 行，有没有发现版本与型号最右侧，
# 与我们刚刚使用 cat /proc/bus/usb/devices 的内容相同啊！ ^_^

[root@linux zdsta]# vi src/zdusb.c
# 找到 63 行左右的地方，如下所示：
    { USB_DEVICE(VENDOR_PLANEX, PRODUCT_GW-US54MINI )  },
# 将他改成与上述档案相同的型号资料啊！
    { USB_DEVICE(VENDOR_PLANEX, PRODUCT_US54MINI )  },
    这样就做好了编译前准备，先注意一下，在编译的过程当中会出现很多的 warning ， 不过并不会影响最终的结果，所以就不要理他没关系啊！
    [root@linux zdsta]# make
# 编译完成后会产生 zd1211.ko 的模组档案喔！
[root@linux zdsta]# make install
# 可以将模组安装到核心模组放置的地方去了！

  2. 测试模组，并且对应网路卡与模组：(modprobe 与 iwconfig)

    编译好模组后当然就是要测试看看的啦！这个时候请这样做：
    [root@linux ~]# modprobe zd1211
[root@linux ~]# lsmod | grep zd1211
zd1211                226768  0
# 是的！有啊！确实有载入啊！

[root@linux ~]# iwconfig
eth1      802.11b/g NIC  ESSID:""
          Mode:Managed  Frequency=2.462GHz  Access Point: 00:00:00:00:00:00
          Bit Rate:1Mb/s
          Retry:off   RTS thr=2432 B   Fragment thr:off
          Encryption key:off
          Power Management:off
    这个 iwconfig 是用在作为无线网路设定之用的一个指令，与 ifconfig 类似！ 不过，当我们使用 iwconfig 时，如果有发现上述的字样，那就代表该网路介面使用的是无线网卡的意思啊！ 所以，俺的无线网卡代号是 eth1 喔！之后，我将这个模组与网卡的代号写入 /etc/modprobe.conf 当中吧！
    [root@linux ~]# vi /etc/modprobe.conf
alias eth1 zd1211
将上面这一行新增到您的 Linux 当中啊！

  3. 利用 iwlist 侦测 AP ：

    好了，接下来要干嘛？当然是看看我们的无线网卡是否能够找到 AP 啊！ 所以，首先我们要启动无线网卡，就利用 ifconfig 即可：
    [root@linux ~]# ifconfig eth1 up
    启动网卡后才能以这个网卡来搜寻整个区域内的无线基地台啊！接下来， 直接使用 iwlist 来使用这个无线网卡搜寻看看吧！
    [root@linux ~]# iwlist eth1 scanning
eth1      Scan completed :
          Cell 01 - Address: 00:90:CC:D6:A4:1C
                    ESSID:"BLW-VBIRD"
                    Mode:Master
                    Frequency:2.437GHz (Channel 6)
                    Quality:8/92  Signal level=54/154  Noise level=0/154
                    Encryption key:on
                    Bit Rate:1Mb/s
                    Bit Rate:2Mb/s
                    Bit Rate:5.5Mb/s
                    Bit Rate:11Mb/s
                    Bit Rate:6Mb/s
                    Bit Rate:9Mb/s
                    Bit Rate:12Mb/s
                    Bit Rate:18Mb/s
                    Bit Rate:24Mb/s
                    Bit Rate:36Mb/s
                    Bit Rate:48Mb/s
                    Bit Rate:54Mb/s
    注意到上头的显示喔！有显示 ESSID 没错吧！这个东西等一下可是需要设定的喔！ 其实接下来我们可以直接使用手动的方式来启动我们的无线网卡的连线喔！
    [root@linux ~]# iwconfig eth1 essid "BLW-VBIRD"  \
> key "12345678901234567890123456"

[root@linux ~]# iwconfig eth1
eth1      802.11b/g NIC  ESSID:"BLW-VBIRD"
          Mode:Managed  Frequency=2.437GHz  Access Point: 00:90:CC:D6:A4:1C
          Bit Rate:11Mb/s
          Retry:off   RTS thr=2432 B   Fragment thr:off
          Encryption key:****-****-****-****-****-****-**   Security mode:open
          Power Management:off
    如果顺利出现上面的资料，那就表示您的无线网卡已经与 AP 接上线了～ 不过有个地方比较奇怪，怎么最高传输速率仅有 11Mb/s 啊？太低了～ 没关系，我们可以在底下进行处理的。 再来则是设定网路卡的设定档啰！^_^

  4. 设定网路卡设定档 (ifcfg-ethn)

    因为我们的网路卡使用的代号是 eth1 ，所以也是需要在 /etc/sysconfig/network-scripts 设定好相对应的档案才行啊！而由于我们的这块卡其实是无线网卡， 所以很多设定值都与原本的乙太网路卡不同，详细的各项变数设定您可以自行参考一下底下的档案：
    /etc/sysconfig/network-scripts/ifup-wireless
    至于我的网路卡设定是这样的：
    [root@linux ~]# cd /etc/sysconfig/network-scripts
[root@linux network-scripts]# vi ifcfg-eth1
DEVICE=eth1
BOOTPROTO=dhcp
ONBOOT=no
TYPE=wireless
ESSID=BLW-VBIRD
MODE=Managed
RATE=54M      <== 可以严格指定传输的速率，要与上面 iwconfig 相同，单位 b/s
KEY=12345678901234567890123456
    要注意的是那个 ONBOOT=no 的设定，如果您想要每次开机时无线，网卡都会自动启动， 那就将他设定为 yes 吧！否则就设定为 no 啰！要启动再以 ifup eth1 来启动即可！ 呼呼！到此为止，您的无线网卡已经可以顺利的给他启动了喔！很快乐吧！ ^_^
    Tips:
    其实上面那个设定档的内容都是在规划出 iwconfig 的参数而已， 所以您除了可以查阅 ifup-wireless 的内容外，可以 man iwconfig ， 会知道的更详细喔！而最重要的参数当然就是 ESSID 及 KEY 啰！ ^_^     		鸟哥的图示
  5. 启动与观察无线网卡

    要启动就用 ifup eth1 来启动，很简单啦！要观察就用 iwconfig 及 ifconfig 分别观察， 底下您自己瞧瞧就好啊！ ^_^
    [root@linux ~]# ifup eth1
# 如果上面的测试都没有问题的话，那么建议您继续底下的动作

[root@linux ~]# iwconfig eth1
eth1      802.11b/g NIC  ESSID:"BLW-VBIRD"
          Mode:Managed  Frequency=2.437GHz  Access Point: 00:90:CC:D6:A4:1C
          Bit Rate:54Mb/s
          Retry:off   RTS thr=2432 B   Fragment thr:off
          Encryption key:****-****-****-****-****-****-**   Security mode:open
          Power Management:off

[root@linux ~]# vi /etc/rc.d/rc.local
# 加入底下这段：
/sbin/ifconfig eth1 up
整个流程就是这么简单喔！不过，如果您的笔记型电脑已经有支援 802.11g/b 的无线网卡时， 比如说使用 Intel 规格的迅驰 (Centrino) 笔记型电脑，那除了上面在载入模组的地方不一样， 因为 CentOS 4.3 本身就有支援 Centrino 的模组，那就是 ipw2200/ipw2100 ， 所以您可以直接跳到第二步，甚至可能在安装的时候系统就主动的帮您安装好这个无线网卡了呢！ 那您就可以直接前往第三步骤开始设计您的 AP 与无线网卡的连线啰！ ^_^。在本章结尾的参考资料处， 鸟哥还是列出许多与无线网卡有关的连结，您可以自行前往查阅与您的无线网卡有关的资讯喔！ ^_^
大标题的图示 常见问题说明
其实这个小节也很重要的！因为可以让您在念完理论后，了解一下如何利用那些概念来查询您的网路设定问题喔！ 底下我们就针对几个常见的问题来说说看吧！

小标题的图示 内部网域使用某些连线服务(如 FTP, POP3)所遇到的连线延迟问题
您或许曾经听过这样的问题：‘我在我的虚拟网域内有几部电脑， 这几部电脑明明都是在同一个网域之内，而且系统通通没有问题，为什么我使用 pop3 或者是 ftp 连上我的 Linux 主机会停顿好久才连上？’

由于网路在连线时，两部主机之间会互相询问对方的主机名称，以确认对方的身份。 在目前的网际网路上面，我们大多使用 Domain Name System (DNS) 系统做为主机名称与 IP 对应的查询，那就是我们在上面提到的 /etc/resolv.conf 档案内设定的 IP 由来， 如果没有指定正确的 DNS IP 的话，那么我们就无法查询到主机名称与 IP 的对应了。

公开的网际网路可以这样设定，但是如果是我们内部网域的私有 IP 主机呢？ 因为是私有 IP 的主机，所以当然无法使用 /etc/resolv.conf 的设定来查询到这部主机的名称啊！ 那怎么办？要知道，如果两部主机之间无法查询到正确的主机名称与 IP 的对应， 那么将‘可能’发生持续查询主机名称对应的动作，这个动作一般需要持续 30-60 秒，因此，您的该次连线将会持续检查主机名 30 秒钟，也就会造成奇怪的 delay 的情况。

这个问题最常发生在内部的 LAN ，例如使用 192.168.10.1 的主机连线到 192.168.10.2 的主机。 这个问题虽然可以透过修改软体的设定来略过主机名称的检查，但是绝大多数的软体都是预设启用这个机制的， 因此，内部主机‘老是连线时期很慢，连线成功后速度就会恢复正常’ 时，通常就是这个问题啦！尤其是在 FTP 及 POP3 等网路连线软体上最常见。

那么如何避过这个情况？最简单的方法就是‘给予内部的主机每部主机一个名称与 IP 的对应’即可。举例来说，我们知道每部主机都有一个主机名称为 localhost ，对应到 127.0.0.1 ，为什么呢？因为这个 127.0.0.1 与 localhost 的对应就被写到 /etc/hosts 内嘛！ 当我们需要主机名称与 IP 的对应时，系统就会先到 /etc/hosts 找寻对应的设定值， 如果找不到，才会使用 /etc/resolv.conf 的设定去网际网路找。这样说，您明白了吧？ 也就是说，只要修改了 /etc/hosts，加入每部主机与 IP 的对应， 就能够避过主机名称的检查啰！

了解了吗？所以说，您就要将您的 私有 IP 的电脑与电脑名称写入您的 /etc/hosts 当中了！好了！那么这个咚咚的内容如何呢？ 我们来看一看原本的设定内容吧！
[root@linux ~]# cat /etc/hosts
# Do not remove the following line, or various programs
# that require network functionality will fail.
127.0.0.1               localhost.localdomain   localhost
# 主机的 IP             主机的名称              主机的别名
在上面的情况中很容易就发现了设定的方法了吧！很简单吧！没错！那就是 IP 对应主机名称啦！ 那么现在知道为什么我们给他 ping localhost 的时候，位址会写出 127.0.0.1 了吧！ 那就是写在这个档案中的啦！而且 localhost 那一行不能拿掉呦！ 否则系统的某些服务可能就会无法被启动！好了！那么将我区域网路内的所有的电脑 IP 都给他写进去！并且，每一部给他取一个您喜欢的名字， 即使与 client 的电脑名称设定不同也没关系啦！ 以鸟哥为例，如果我还额外加设了 DHCP 的时候，那么我就干脆将所有的 C Class 的所有网段全部给他写入 /etc/hosts 当中，有点像底下这样：
[root@linux ~]# vi /etc/hosts
# Do not remove the following line, or various programs
# that require network functionality will fail.
127.0.0.1               localhost.localdomain   localhost
192.168.1.1　　linux001
192.168.1.2　　linux002
192.168.1.3　　linux003
.........
.........
192.168.1.255　linux255
如此一来，不论我哪一部电脑连上来，不论是在同一个网段的哪一个 IP ， 我都可以很快速的追查到！嘿嘿！那么区内网路互连的时候，就不会多等个好几时秒钟啰！

小标题的图示 网址列无法解析问题
很多朋友常问的一个问题‘咦！我可以拨接上网了，也可以 ping 到奇摩雅虎的 IP ，但为何就是无法直接以网址连上 Internet 呢！’嘿！被气死！ 前面不是一直强调那个 DNS 解析的问题吗？对啦！就是名称解析不对啦！赶快改一下 /etc/resolv.conf 这个档案吧！改成上层 ISP 给您的 DNS 主机的 IP 就可以啦！例如 Hinet 的 168.95.1.1 及 Seednet 的 139.175.10.20 啰！例如底下的范例(这个范例就可以照抄了！ ^_^)：
[root@linux ~]# vi /etc/resolv.conf
nameserver 168.95.1.1
nameserver 139.175.10.20
朋友们常常会在这个地方写错，因为很多书上都说这里要设定成为 NAT 主机的 IP ， 那根本就是不对的！您应该要将所有管理的电脑内，关于 DNS 的设定都直接使用上面的设定值即可！ 除非您的上层环境有使用防火墙，那才另外考量！

小标题的图示 预设路由的问题
记得我们在前两章提到的网路基础当中，不是讲了很多预设路由 (default gateway) 相关的说明吗？ 预设路由通常仅有一个，用来做为同一网域的其他主机传递非本网域的封包闸道。 但我们也知道在每个网路设定档案 (/etc/sysconfig/network-scripts/ifcfg-ethx) 内部都可以指定‘ GATEWAY ’这个参数，若这个参数重复设定的话，那可就麻烦啦！

举例来说，您的 ifcfg-eth0 用来做为内部网域的沟通，所以您在该档案内设定 GATEWAY 为您自己的 IP ， 但是该主机为使用 ADSL 拨接，所以当拨接成功后会产生一个 ppp0 的介面，这个 ppp0 介面也有自己的 default gateway ，好了，那么当你要将封包传送到 Yahoo 这个非为本网域的主机时， 这个封包是要传到 eth0 还是 ppp0 呢？因为两个都有 default gateway 啊！

没错！很多朋友就是这里搞不懂啦！常常会错乱～所以，请注意， 您的 default gateway 应该只能有一个， 如果是拨接，请不要在 ifcfg-eth0 当中指定 GATEWAY或 GATEWAYDEV 等变数，重要重要！

更多的网路除错请参考后续章节Linux 网路侦错 的说明。

大标题的图示 重点回顾
  • Linux 网路卡的预设代号为 eth0, eth1 等等；
  • Linux 内的网路卡代号为一个代号，并非为装置档案。欲对应装置代号时， 可在 /etc/modprobe.conf 内制作好网卡代号与驱动模组的对应。
  • 若要取得网路卡的完整功能，有时需要自行由网卡开发商的官方网站下载适合的原始码来安装。 编译与安装模组前必须先确定 gcc, make, kernel-devel (核心原始码) 已经安装完毕。
  • 内部网域的私有 IP 之主机的‘ IP 与主机名称的对应’，最好还是写入 /etc/hosts ， 可以克服很多软体的 IP 反查所花费的等待时间。
  • 在 Red Hat base 的 Linux distributions 当中，网路设定档案大多放置于 /etc/sysconfig/network-scripts/ 目录下，尤其是该目录下的 ifcfg-eth0 可设定网路参数；
  • 在 ifcfg-eth0 当中，可以指定 MTU 以设定网路卡的最大传输单元，也可以利用 HWADDR 指定出所需要设定的网卡；
  • 在 GATEWAY 这个参数的设定上面，务必检查妥当，仅设定一个 GATEWAY 即可。
  • 可以使用 /etc/init.d/network restart 来重新启动整个系统的网路介面。
  • 若使用 DHCP 协定时，则请将 GATEWAY 取消设定，避免重复出现多个 default gateway ，反而造成无法连线的状况。
  • 拨接后可以产生一个新的实体介面，名称为 ppp0
  • 主机名称与 IP 的对应，通常使用 DNS 系统，该系统以 /etc/resolv.conf 做为伺服器 IP 设定的档案。
  • 无线网卡与无线基地台之间的连线由于是透过无线介面，所以需要特别注意网路安全；
  • 常见的无线基地台(AP)的连线防护，主要利用控制登入者的 MAC 或者是加上连线加密机制的金钥等方法；
  • 设定网路卡可以使用 ifconfig 这个指令，而设定无线网卡则需要 iwconfig ，至于扫瞄基地台， 可以使用 iwlist 这个指令。
大标题的图示 课后练习
  • 我要如何确定我在 Linux 系统上面的网路卡已经被 Linux 捉到并且驱动了？
    • 网路卡能不能被捉到可以使用‘ dmesg|grep eth ’来判断，有没有驱动则可以使用 lsmod 看看模组有没有载入核心！最后，以 ifconfig eth0 192.168.0.10 测试看看！
  • 假设我的网路参数为：IP 192.168.100.100, Netmask 255.255.255.0, 请问我要如何在 Linux 上面设定好这些网路参数 (未提及的网路参数请自行定义！)？请使用手动与档案设定方法分别说明。
    • 手动设定为：‘ ifconfig eth0 192.168.100.100 netmask 255.255.255.0 up ’
    档案设定为：vi /etc/sysconfig/network-scripts/ifcfg-eth0 ，内容为：
    DEVICE=eth0
    ONBOOT=yes
    BOOTPROTO=static
    IPADDR=192.168.100.100
    NETMASK=255.255.255.0
    NETWORK=192.168.100.0
    BROADCAST=192.168.100.255 要启动则使用 ifup eth0 即可！
  • 我要将我的 Linux 主机名称改名字，步骤应该如何(更改那个档案？如何启用？)？
    • Linux 主机名称在 /etc/sysconfig/network 这个档案里面的‘HOSTNAME=主机名称’来设定，先以 vi 来修改，改完后可以使用 /etc/init.d/network restart 不过建议直接 reboot 启动主机名称！
  • /etc/resolv.conf 与 /etc/hosts 的功能为何？
    • 以主机名称寻找 IP 的方法， /etc/resolv.conf 内填写 DNS 主机名称，至于 /etc/hosts 则直接填写主机名称对应的 IP 即可！ 其中 /etc/hosts 对于内部私有 IP 的主机名称查询非常有帮助！
  • 我使用 ADSL 拨接连上 Internet ，请问拨接成功之后，我的 Linux 上面会有几个网路介面 (假设我只有一个网路卡)？
    • 因为拨接是使用 PPP (点对点)协定，所以拨接成功后会多出一个 ppp0 的介面，此外，系统原本即有 eth0 及 lo 这两个介面，所以共有三个介面。
  • 在 Linux 上面进行 ADSL 拨接应该使用什么软体？
    • 其实软体非常多，尤其是图形介面的拨接软体，多的很！ 不过，依旧请爱用 rp-pppoe ，官方网站： http://www.roaringpenguin.com/pppoe/
  • 一般来说，如果我拨接成功，也取得了 ppp0 这个介面，但是却无法对外连线成功， 您认为应该是哪里出了问题？该如何解决？
    • 因为拨接成功了，表示物理对外连线没有问题，那么可能的问题应该是发生在 Gateway 上面了！确认的方法请使用 route -n 查阅路由资讯，然后修订 /etc/sysconfig/network-scripts/ifcfg-eth0 吧！
  • 如果您的区域网路环境内有可以控管的无线 AP 时，请自行查出如何以 MAC 的方式管理可登入的用户， 并将您的无线 AP 做好连线加密的金钥设定。
    • 请自行测试！谢谢！
  • 如果一部主机上面插了两张相同晶片的网路卡，代表两者使用的模组为同一个，此时可能会造成网卡代号的误判； 请问您如何克服这个问题？让网卡代号不会变动？
    • 以现在的方法来讲，其实我们可以透过指定 Hardware Address(硬体位址，通称为 MAC) 来指定网卡代号与 MAC 的对应。 这个设定值可以在 ifcfg-ethx 里面以 HWADDR 这个设定项目来指定的。
  • 如何在 Linux 上面的文字介面搜寻您所在区域的无线 AP ？
    • 透过直接使用‘ iwlist ethx scanning ’这个指令来指定某个无线网卡的搜寻！ 然后再以 iwconfig 来进行网卡的设定即可！
  • 请依序说明：如果您想要新增一块新的网路卡在您的主机上，并给予一个固定的私有 IP ，应如何进行？
    • 先关掉主机的 power ，然后拆掉机壳，装上网路卡；
    • 开机完成后，以 dmesg | grep eth 查询是否可捉到该网路卡，若无法捉到，请编译模组，若可捉到，找出网卡代号， 并且将该模组与网卡代号写入 /etc/modprobe.conf 当中，以利未来开机时可自动达成对应；
    • 利用‘ ifconfig "网卡代号" ’来查询 MAC 为何？
    • 开始在 /etc/sysconfig/network-scripts 内建立 ifcfg-"网卡代号" 档案，同时给予 HWADDR 的对应；
    • 启动 /etc/init.d/network restart 测试是否能成功！
  • 如果您想要登入某个区域的无线 AP ，您应该向该处所至少申请哪些资料？
    • 无线网路的技术相当多且复杂，所以需要取得的参数都不尽相同。不过，至少您还是得要取得 ESSID 以及 KEY 密码，这样才能够连线登入该 AP 当中。
大标题的图示 参考资料：
  • rp-pppoe 官方网站：http://www.roaringpenguin.com/pppoe/
  • rp-pppoe 的安装方法：http://linux.vbird.org0130internet_connect/0130internet_connect.htm#connect_adsl
  • 无线网路安全白皮书(三)：http://www.cert.org.tw/document/column/show.htm?key=61
  • GW-US54Mini 驱动程式下载：http://www.planex.com.tw/download/wireless/gw-us54mini.htm
  • Intel Centrino 的无线网卡相关模组资讯：
    http://ipw2100.sourceforge.net/
    http://ipw2200.sourceforge.net/
  • HP 的许多无线网路的计划连结：http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/
2002/07/24：首次释出日期
2003/08/18：重新校正，并且修正部分书写方式
2003/08/20：新增课后练习部分
2003/09/19：加入 前往参考用解答
2006/07/17：将原本旧文章移动到 此处
2002/07/24以来统计人数


鸟哥的 Linux 私房菜 -- Linux 常用网路指令介绍

为取得较佳浏览结果，请爱用 firefox 浏览本网页

Linux 常用网路指令介绍
切换解析度为 800x600
最近更新日期：2006/08/02
Linux 的网路功能相当的强悍，一时之间我们也无法完全的介绍所有的网路指令， 这个章节主要的目的在介绍一些常见的网路指令而已。至于每个指令的详细用途将在后续伺服器架设时， 依照指令的相关性来进行说明。当然，在这个章节的主要目的是在于将所有的指令汇整在一起，比较容易了解啦！ 还有，这一章鸟哥新增了一些封包撷取的指令，若不熟悉没关系，先放着，全部读完后再回来这一章仔细练习啊！

1. 网路参数设定指令：
    1.1 ifconfig, ifup, ifdown
    1.2 route
    1.3 ip
    1.4 iwlist, iwconfig
    1.5 dhclient
 2. 网路侦错与观察指令
    2.1 ping：用 ping 追踪最大 MTU 数值
    2.2 traceroute
    2.3 netstat
    2.4 host
    2.5 nslookup
 3. 远端连线指令
    3.1 telnet
    3.2 ftp
    3.3 lftp
    3.4 gaim：图形介面的即时通讯软体
 4. 文字介面网页浏览
    4.1 lynx
    4.2 wget
 5. 封包撷取功能
    5.1 tcpdump
    5.2 ethereal
    5.3 nc, netcat
 6. 重点回顾
7. 课后练习：
8. 参考资料
9. 针对本文的建议：http://phorum.vbird.org/viewtopic.htm?t=26123
大标题的图示 网路参数设定指令：
任何时刻如果你想要做好你的网路参数设定，包括 IP 参数、路由参数与无线网路等等， 就得要了解底下这些相关的指令才行！其中以 route 及 ip 这两支指令算是较重要的喔！ ^_^ 当然，比较早期的用法，我们都是使用 ifconfig 的啦！
  • ifconfig：查询、设定网路卡与 IP 网域等相关参数；
  • ifup, ifdown：这两个档案是 script ，透过更简单的方式来启动网路介面；
  • route：查询、设定路由表 (route table)
  • ip：复合式的指令，可以直接修改上述提到的功能；
小标题的图示 ifconfig, ifup, ifdown
这三个指令的用途都是在启动网路介面，不过， ifup 与 ifdown 仅能就 /etc/sysconfig/network-scripts 内的 ifcfg-ethx (x 为数字) 进行启动或关闭的动作，并不能直接修改网路参数，除非手动调整 ifcfg-ethx 档案才行。至于 ifconfig 则可以直接手动给予某个介面 IP 或调整其网路参数！ 底下我们就分别来谈一谈先！

  • ifconfig
    ifconfig 主要是可以手动的启动、观察与修改网路介面的相关参数，可以修改的参数很多啊， 包括 IP 参数以及 MTU 等等都可以修改，他的语法如下：
    [root@linux ~]# ifconfig {interface} {up|down}  <== 观察与启动介面
[root@linux ~]# ifconfig interface {options}    <== 设定与修改介面
参数：
interface：网路卡介面代号，包括 eth0, eth1, ppp0 等等
options  ：可以接的参数，包括如下：
    up, down ：启动 (up) 或关闭 (down) 该网路介面(不涉及任何参数)
    mtu      ：可以设定不同的 MTU 数值，例如 mtu 1500 (单位为 byte)
    netmask  ：就是子遮罩网路；
    broadcast：就是广播位址啊！
范例：

范例一：观察所有的网路介面(直接输入 ifconfig)
[root@linux ~]# ifconfig
eth0      Link encap:Ethernet  HWaddr 00:0F:EA:A3:06:A2
          inet addr:192.168.10.100  Bcast:192.168.10.255  Mask:255.255.255.0
          inet6 addr: fe80::20f:eaff:fe73:682/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:3439 errors:0 dropped:0 overruns:0 frame:0
          TX packets:2735 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:646935 (631.7 KiB)  TX bytes:562313 (549.1 KiB)
          Interrupt:209 Memory:fb000000-0
    一般来说，直接输入 ifconfig 就会列出目前已经被启动的卡， 不论这个卡是否有给予 IP ，都会被显示出来。而如果是输入 ifconfig eth0 ， 则会秀出这张介面的相关资料，而不管该介面是否有启动。所以如果您想要知道某张网路卡的 Hardware Address，直接输入‘ ifconfig "网路介面代号" ’即可喔！ ^_^！ 至于上表出现的各项资料是这样的(资料排列由上而下、由左而右)：
    • eth0：就是网路卡的代号，也有 lo 这个 loopback ；
    • HWaddr：就是网路卡的硬体位址，俗称的 MAC 是也；
    • inet addr：IPv4 的 IP 位址，后续的 Bcase, Mask 分别代表的是 Broadcast 与 netmask 喔！
    • inet6 addr：是 IPv6 的版本的 IP ，我们没有使用，所以略过；
    • MTU：就是 MTU 啊！
    • RX：那一行代表的是网路由启动到目前为止的封包接收情况， packets 代表封包数、errors 代表封包发生错误的数量、 dropped 代表封包由于有问题而遭丢弃的数量等等
    • TX：与 RX 相反，为网路由启动到目前为止的传送情况；
    • collisions：代表封包碰撞的情况，如果发生太多次， 表示您的网路状况不太好；
    • txqueuelen：代表用来传输资料的缓冲区的储存长度；
    • RX bytes, TX bytes：总传送、接收的位元组总量
    • Interrupt, Memory：网路卡硬体的资料， IRQ 岔断与记忆体位址；
    透过观察上述的资料，大致上可以了解到您的网路情况，尤其是那个 RX, TX 内的 error 数量， 以及是否发生严重的 collision 情况，都是需要注意的喔！ ^_^
    范例二：暂时修改网路介面
[root@linux ~]# ifconfig eth0 192.168.100.100
# 如果不加任何其他参数，则系统会依照该 IP 所在的 class 范围，
# 自动的计算出 netmask 以及 network, broadcast 等 IP 参数；

[root@linux ~]# ifconfig eth0 192.168.100.100 netmask 255.255.255.128 \
> mtu 8000
# 设定网路介面，同时设定 MTU 的数值！

[root@linux ~]# ifconfig eth0 mtu 9000
# 仅修改该介面的 MTU 数值，其他的保持不动！

[root@linux ~]# ifconfig eth0:0 192.168.50.50
# 仔细看那个介面， eth0:0 喔！那就是在该网路介面上，再模拟一个网路介面，
# 亦即是在一张网路卡上面设定多个 IP 的意思啦！

[root@linux ~]# ifconfig
eth0      Link encap:Ethernet  HWaddr 00:0F:EA:A3:06:A2
          inet addr:192.168.10.100  Bcast:192.168.10.255  Mask:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:3669 errors:0 dropped:0 overruns:0 frame:0
          TX packets:2892 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:667547 (651.9 KiB)  TX bytes:584799 (571.0 KiB)
          Interrupt:209 Memory:fb000000-0

eth0:0    Link encap:Ethernet  HWaddr 00:0F:EA:A3:06:A2
          inet addr:192.168.200.2  Bcast:192.168.200.255  Mask:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          Interrupt:209 Memory:fb000000-0
# 仔细看，是否与硬体有关的资讯都相同啊！没错！因为是同一张网卡嘛！

[root@linux ~]# ifconfig eth0:0 down
# 关掉 eth0:0 这个介面。如果想要启动 eth1 ，并且不给予任何网路参数，
# ifconfig eth1 up 就可以达到了！

[root@linux ~]# /etc/init.d/network restart
# 刚刚设定的资料全部失效，会以 ifcfg-ethx 的设定为主！
    呵呵！使用 ifconfig 可以暂时手动来设定或修改某个介面卡的相关功能， 并且也可以透过 eth0:0 这种虚拟的网路介面来设定好一张网路卡上面的多个 IP 喔！ 手动的方式真是简单啊！并且设定错误也不打紧，因为我们可以利用 /etc/init.d/network restart 来重新启动整个网路介面，那么之前手动的设定资料会全部都失效喔！另外， 要启动某个网路介面，但又不让他具有 IP 参数时，直接给他 ifconfig eth0 up 即可！ 这个动作经常在无线网卡当中会进行， 因为我们必须要启动无线网卡让他去侦测 AP 存在与否啊！

  • ifup, ifdown
    即时的手动修改一些网路介面参数，可以利用 ifconfig 来达成，如果是要直接以设定档， 亦即是在 /etc/sysconfig/network-scripts 里面的 ifcfg-ethx 等档案的设定参数来启动的话， 那就得要透过 ifdown 或 ifup 来达成了。
    [root@linux ~]# ifup   {interface}
[root@linux ~]# ifdown {interface}

[root@linux ~]# ifup eth0
    ifup 与 ifdown 真是太简单了！这两支程式其实是 script 而已，他会直接到 /etc/sysconfig/network-scripts 目录下搜寻对应的设定档，例如 ifup eth0 时，他会找出 ifcfg-eth0 这个档案的内容，然后来加以设定。 关于 ifcfg-eth0 的设定则请参考前一章连上 Internet 的说明。

    不过，由于这两支程式主要是搜寻设定档 (ifcfg-ethx) 来进行启动与关闭的， 所以在使用前请确定 ifcfg-ethx 是否真的存在于正确的目录内，否则会启动失败喔！ 另外，如果以 ifconfig eth0 .... 来设定或者是修改了网路介面后， 那就无法再以 ifdown eth0 的方式来关闭了！因为 ifdown 会分析比对目前的网路参数与 ifcfg-eth0 是否相符，不符的话，就会放弃该次动作。因此，使用 ifconfig 修改完毕后，应该要以 ifconfig eth0 down 才能够关闭该介面喔！

    • 小标题的图示 路由修改 route
    我们在网路基础的时候谈过关于路由的问题， 两部主机之间一定要有路由才能够互通 TCP/IP 的协定，否则就无法进行连线啊！ 一般来说，只要有网路介面，该介面就会产生一个路由，例如在鸟哥实验室内部的主机有一个 eth0 及 lo ， 所以：
    [root@linux ~]# route [-nee]
[root@linux ~]# route add [-net|-host] [网域或主机] netmask [mask] [gw|dev]
[root@linux ~]# route del [-net|-host] [网域或主机] netmask [mask] [gw|dev]
观察的参数：
   -n  ：不要使用通讯协定或主机名称，直接使用 IP 或 port number；
   -ee ：使用更详细的资讯来显示
增加 (add) 与删除 (del) 路由的相关参数：
   -net    ：表示后面接的路由为一个网域；
   -host   ：表示后面接的为连接到单部主机的路由；
   netmask ：与网域有关，可以设定 netmask 决定网域的大小；
   gw      ：gateway 的简写，后续接的是 IP 的数值喔，与 dev 不同；
   dev     ：如果只是要指定由那一块网路卡连线出去，则使用这个设定，后面接 eth0 等

范例一：单纯的观察路由状态
[root@linux ~]# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
192.168.10.0    0.0.0.0         255.255.255.0   U     0      0        0 eth0
169.254.0.0     0.0.0.0         255.255.0.0     U     0      0        0 eth0
0.0.0.0         192.168.10.30   0.0.0.0         UG    0      0        0 eth0

[root@linux ~]# route
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
192.168.10.0    *               255.255.255.0   U     0      0        0 eth0
169.254.0.0     *               255.255.0.0     U     0      0        0 eth0
default         server.cluster  0.0.0.0         UG    0      0        0 eth0
    由上面的例子当中仔细观察 route 与 route -n 的输出结果，你可以发现有加 -n 参数的主要是显示出 IP ，至于使用 route 而已的话，显示的则是‘主机名称’喔！ 也就是说，在预设的情况下， route 会去找出该 IP 的主机名称，如果找不到呢？ 就会显示的钝钝的(有点小慢)，所以说，鸟哥通常都直接使用 route -n 啦！ 由上面看起来，我们也知道 default = 0.0.0.0/0.0.0.0 ， 而上面的资讯有哪些你必须要知道的呢？
    • Destination, Genmask：这两个玩意儿就是分别是 network 与 netmask 啦！所以这两个咚咚就组合成为一个完整的网域啰！
    • Gateway：该网域是通过那个 gateway 连接出去的？ 如果显示 0.0.0.0 表示该路由是直接由本机传送，亦即可以透过区域网路的 MAC 直接传讯； 如果有显示 IP 的话，表示该路由需要经过路由器 (通讯闸) 的帮忙才能够传送出去。
    • Flags：总共有多个旗标，代表的意义如下：
      • U (route is up)：该路由是启动的；
      • H (target is a host)：目标是一部主机 (IP) 而非网域；
      • G (use gateway)：需要透过外部的主机 (gateway) 来转递封包；
      • R (reinstate route for dynamic routing)：使用动态路由时，恢复路由资讯的旗标；
      • D (dynamically installed by daemon or redirect)：已经由服务或转 port 功能设定为动态路由
      • M (modified from routing daemon or redirect)：路由已经被修改了；
      • ! (reject route)：这个路由将不会被接受(用来抵挡不安全的网域！)
    • Iface：这个路由传递封包的介面。
    此外，观察一下上面的路由排列顺序喔，依序是由小网域 (192.168.10.0/24 是 Class C)，逐渐到大网域 (169.254.0.0/16 Class B) 最后则是预设路由 (0.0.0.0/0.0.0.0)。 然后当我们要判断某个网路封包应该如何传送的时候，该封包会经由这个路由的过程来判断喔！ 举例来说，我上头仅有三个路由，若我有一个传往 192.168.10.20 的封包要传递，那首先会找 192.168.10.0/24 这个网域的路由，找到了！所以直接由 eth0 传送出去；

    如果是传送到 Yahoo 的主机呢？ Yahoo 的主机 IP 是 202.43.195.52，我通过判断 1)不是 192.168.10.0/24， 2)不是 169.254.0.0/16 结果到达 3)0/0 时，OK！传出去了，透过 eth0 将封包传给 192.168.10.30 那部 gateway 主机啊！所以说，路由是有顺序的。

    因此当你重复设定多个同样的路由时， 例如在你的主机上的两张网路卡设定为相同网域的 IP 时，会出现什么情况？会出现如下的情况：
    Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
192.168.10.0    0.0.0.0         255.255.255.0   U     0      0        0 eth0
192.168.10.0    0.0.0.0         255.255.255.0   U     0      0        0 eth1
    也就是说，由于路由是依照顺序来排列与传送的， 所以不论封包是由那个介面 (eth0, eth1) 所接收，都会由上述的 eth0 传送出去， 所以，在一部主机上面设定两个相同网域的 IP 本身没有什么意义！有点多此一举就是了。 除非是类似虚拟主机 (Xen, VMware 等软体) 所架设的多主机时，才会有这个必要～
    范例二：路由的增加与删除
[root@linux ~]# route del -net 169.254.0.0 netmask 255.255.0.0 dev eth0
# 上面这个动作可以删除掉 169.254.0.0/16 这个网域！
# 请注意，在删除的时候，需要将路由表上面出现的资讯都写入
# 包括  netmask , dev 等等参数喔！注意注意

[root@linux ~]# route add -net 192.168.100.0 \
> netmask 255.255.255.0 dev eth0
# 透过 route add 来增加一个路由！请注意，这个路由必须要能够与你互通。
# 举例来说，如果我下达底下的指令就会显示错误：
# route add -net 192.168.200.0 netmask 255.255.255.0 gw 192.168.200.254
# 因为我的环境内仅有 192.168.10.100 这个 IP ，所以不能与 192.168.200.254
# 这个网段直接使用 MAC 互通！这样说，可以理解喔！？

[root@linux ~]# route add default gw 192.168.10.30
# 增加预设路由的方法！请注意，只要有一个预设路由就够了喔！
# 在这个地方如果您随便设定后，记得使用底下的指令重新设定你的网路
# /etc/init.d/network restart
    如果是要进行路由的删除与增加，那就得要参考上面的例子了， 其实，使用 man route 里面的资料就很丰富了！仔细查阅一下啰！ 你只要记得，当出现‘SIOCADDRT: Network is unreachable’ 这个错误时，肯定是由于 gw 后面接的 IP 无法直接与您的网域沟通 (Gateway 并不在你的网域内)， 所以，赶紧检查一下是否输入错误啊！加油吧！

    小标题的图示 ip
    ip 是个指令喔！并不是那个 TCP/IP 的 IP 啦！这个 ip 指令的功能可多了！ 基本上，他就是整合了 ifconfig 与 route 这两个指令啰～不过， ip 可以达成的功能却又多更多！ 真是个相当厉害的指令。如果您有兴趣的话，请自行 vi /sbin/ifup ，就知道整个 ifup 就是利用 ip 这个指令来达成的。好了，如何使用呢？让我们来瞧一瞧先！
    [root@linux ~]# ip [option] [动作] [指令]
参数：
option ：设定的参数，主要有：
    -s ：显示出该装置的统计数据(statistics)，例如总接受封包数等；
动作：亦即是可以针对哪些网路参数进行动作，包括有：
    link  ：关于装置 (device) 的相关设定，包括 MTU, MAC 位址等等
    addr/address ：关于额外的 IP 协定，例如多 IP 的达成等等；
    route ：与路由有关的相关设定
    由上面的语法我们可以知道， ip 除了可以设定一些基本的网路参数之外，还能够进行额外的 IP 协定， 包括多 IP 的达成，真是太完美了！底下我们就分三个部分 (link, addr, route) 来介绍这个 ip 指令吧！

  • 关于装置介面 (device) 的相关设定： ip link
    • ip link 可以设定与装置 (device) 有关的相关设定，包括 MTU 以及该网路介面的 MAC 等等， 当然也可以启动 (up) 或关闭 (down) 某个网路介面啦！整个语法是这样的：
    [root@linux ~]# ip [-s] link show  <== 单纯的查阅该装置相关的资讯
[root@linux ~]# ip link set [device] [动作与参数]
参数：
show：仅显示出这个装置的相关内容，如果加上 -s 会显示更多统计数据；
set ：可以开始设定项目， device 指的是 eth0, eth1 等等介面代号；
动作与参数：包括有底下的这些动作：
   up|down  ：启动 (up) 或关闭 (down) 某个介面，其他参数使用预设的乙太网路；
   address  ：如果这个装置可以更改 MAC 的话，用这个参数修改！
   name     ：给予这个装置一个特殊的名字；
   mtu      ：就是最大传输单元啊！

范例一：显示出所有的介面资讯
[root@linux ~]# ip link show
1: lo: <LOOPBACK,UP,10000> mtu 16436 qdisc noqueue
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: eth0: <BROADCAST,MULTICAST,UP,10000> mtu 1500 qdisc pfifo_fast qlen 1000
    link/ether 00:50:fc:22:9a:cb brd ff:ff:ff:ff:ff:ff
3: sit0: <NOARP> mtu 1480 qdisc noop
    link/sit 0.0.0.0 brd 0.0.0.0

[root@linux ~]# ip -s link show eth0
2: eth0: <BROADCAST,MULTICAST,UP,10000> mtu 1500 qdisc pfifo_fast qlen 1000
    link/ether 00:50:fc:22:9a:cb brd ff:ff:ff:ff:ff:ff
    RX: bytes  packets  errors  dropped overrun mcast
    484011792  2247372  0       0       0       0
    TX: bytes  packets  errors  dropped carrier collsns
    2914104290 2867753  0       0       0       0
    使用 ip link show 可以显示出整个装置介面的硬体相关资讯，如上所示，包括网卡位址(MAC)、MTU等等， 比较有趣的应该是那个 sit0 的介面了，那个 sit0 的介面是用在 IPv4 及 IPv6 的封包转换上的， 对于我们仅使用 IPv4 的网路是没有作用的。 lo 及 sit0 都是主机内部所自行设定的。 而如果加上 -s 的参数后，则这个网路卡的相关统计资讯就会被列出来， 包括接收 (RX) 及传送 (TX) 的封包数量等等，详细的内容与 ifconfig 所输出的结果相同的。
    范例二：启动、关闭与设定装置的相关资讯
[root@linux ~]# ip link set eth0 up
# 启动 eth0 这个装置介面；

[root@linux ~]# ip link set eth0 down
# 阿就关闭啊！简单的要命～

[root@linux ~]# ip link set eth0 mtu 1000
# 更改 MTU 的值，达到 1000 bytes，单位就是 bytes 啊！
    更新网路卡的 MTU 使用 ifconfig 也可以达成啊！没啥了不起，不过，如果是要更改‘网路卡代号、 MAC 位址的资讯’的话，那可就得使用 ip 啰～不过，设定前得要先关闭该网路卡，否则会不成功。 如下所示：
    范例三：修改网路卡代号、MAC 等参数
[root@linux ~]# ip link set eth0 name vbird
SIOCSIFNAME: Device or resource busy
# 因为该装置目前是启动的，所以不能这样做设定。你应该要这样做：

[root@linux ~]# ip link set eth0 down       <==关闭介面
[root@linux ~]# ip link set eth0 name vbird <==重新设定
[root@linux ~]# ip link show                <==观察一下
2. vbird: <BROADCAST,MILTICASE> mtu 900 qdisc pfifo_fast qlen 1000
    link/ehter 00:40:d0:13:c3:46 brd ff:ff:ff:ff:ff:ff
# 怕了吧！连网路卡代号都可以改变！不过，玩玩后记得改回来啊！
# 因为我们的 ifcfg-eth0 还是使用原本的装置代号！避免有问题，要改回来
[root@linux ~]# ip link set vbird name eth0 <==介面改回来

[root@linux ~]# ip link set eth0 address aa:aa:aa:aa:aa:aa
[root@linux ~]# ip link show eth0
# 如果你的网路卡支援硬体位址 (MAC) 可以更改的话，
# 那么上面这个动作就可以更改你的网路卡位址了！厉害吧！
# 不过，还是那句老话，测试完之后请立刻改回来啊！
    在这个装置的硬体相关资讯设定上面，包括 MTU, MAC 以及传输的模式等等，都可以在这里设定。 有趣的是那个 address 的项目，那个项目后面接的可是硬体位址 (MAC) 而不是 IP 喔！ 很容易搞错啊！切记切记！更多的硬体参数可以使用 man ip 查阅一下与 ip link 有关的设定。

  • 关于额外的 IP 相关设定： ip address
    • 如果说 ip link 是与 OSI 七层协定 的第二层资料连阶层有关的话，那么 ip address (ip addr) 就是与第三层网路层有关的参数啦！ 主要是在设定与 IP 有关的各项参数，包括 netmask, broadcast 等等。
    [root@linux ~]# ip address show   <==就是查阅 IP 参数啊！
[root@linux ~]# ip address [add|del] [IP参数] [dev 装置名] [相关参数]
参数：
show    ：单纯的显示出介面的 IP 资讯啊；
add|del ：进行相关参数的增加 (add) 或删除 (del) 设定，主要有：
    IP 参数：主要就是网域的设定，例如 192.168.100.100/24 之类的设定喔；
    dev    ：这个 IP 参数所要设定的介面，例如 eth0, eth1 等等；
    相关参数：主要有底下这些：
        broadcast：设定广播位址，如果设定值是 + 表示‘让系统自动计算’
        label    ：亦即是这个装置的别名，例如 eth0:0 就是了！
        scope    ：这个介面的领域，通常是这几个大类：
                   global ：允许来自所有来源的连线；
                   site   ：仅支援 IPv6 ，仅允许本主机的连线；
                   link   ：仅允许本装置自我连线；
                   host   ：仅允许本主机内部的连线；
                   所以当然是使用 global 啰！预设也是 global 啦！

范例一：显示出所有的介面之 IP 参数：
[root@linux ~]# ip address show
1: lo: <LOOPBACK,UP,10000> mtu 16436 qdisc noqueue
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,10000> mtu 1500 qdisc pfifo_fast qlen 1000
    link/ether 00:50:fc:22:9a:cb brd ff:ff:ff:ff:ff:ff
    inet 192.168.1.2/24 brd 192.168.1.255 scope global eth0
    inet6 fe80::250:fcff:fe22:9acb/64 scope link
       valid_lft forever preferred_lft forever
3: sit0: <NOARP> mtu 1480 qdisc noop
    link/sit 0.0.0.0 brd 0.0.0.0
    看到上面那个特殊的字体吗？没错！那就是 IP 参数啦！也是 ip address 最主要的功能。 底下我们进一步来新增虚拟的网路介面试看看：
    范例二：新增一个介面，名称假设为 eth0:vbird
[root@linux ~]# ip address add 192.168.50.50/24 broadcast + \
> dev eth0 label eth0:vbird
[root@linux ~]# ip address show eth0
2: eth0:  mtu 1500 qdisc pfifo_fast qlen 1000
    link/ether 00:40:d0:13:c3:46 brd ff:ff:ff:ff:ff:ff
    inet 192.168.1.100/24 brd 192.168.1.255 scope global eth0
    inet 192.168.50.50/24 brd 192.168.50.255 scope global eth0:vbird
    inet6 fe80::240:d0ff:fe13:c346/64 scope link
       valid_lft forever preferred_lft forever
# 看到上面的特殊字体了吧？多出了一行新的介面，且名称是 eth0:vbird
# 至于那个 broadcast + 也可以写成 broadcast 192.168.50.255 啦！
[root@linux ~]# ifconfig
eth0:vbir Link encap:Ethernet  HWaddr 00:40:D0:13:C3:46
          inet addr:192.168.50.50  Bcast:192.168.50.255  Mask:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          Interrupt:5 Base address:0x3e00
# 如果使用 ifconfig 就能够看到这个怪东西了！可爱吧！ ^_^

范例三：将刚刚的介面删除
[root@linux ~]# ip address del 192.168.50.50/24 dev eth0
# 删除就比较简单啊！ ^_^

  • 关于路由的相关设定： ip route
    • 呵呵，这个项目当然就是路由的观察与设定啰！事实上， ip route 的功能几乎与 route 这个指令差不多，但是，他还可以进行额外的参数设计，例如 MTU 的规划等等，相当的强悍啊！
    [root@linux ~]# ip route show  <==单纯的显示出路由的设定而已
[root@linux ~]# ip route [add|del] [IP或网域] [via gateway] [dev 装置]
参数：
show ：单纯的显示出路由表，也可以使用 list ；
add|del ：增加 (add) 或删除 (del) 路由的意思。
    IP或网域：可使用 192.168.50.0/24 之类的网域或者是单纯的 IP ；
    via     ：从那个 gateway 出去，不一定需要；
    dev     ：由那个装置连出去，这就需要了！
    mtu     ：可以额外的设定 MTU 的数值喔！

范例一：显示出目前的路由资料
[root@linux ~]# ip route show
192.168.1.0/24 dev eth0  proto kernel  scope link  src 192.168.1.2
169.254.0.0/16 dev eth1  scope link
default via 192.168.1.254 dev eth1
    如上表所示，最简单的功能就是显示出目前的路由资讯，其实跟 route 这个指令相同啦！ 指示必须要注意几个小东西：
    • proto：此路由的路由协定，主要有 redirect, kernel, boot, static, ra 等， 其中 kernel 指的是直接由核心判断自动设定。
    • scope：路由的范围，主要是 link ，亦即是与本装置有关的直接连线。
    再来看一下如何进行路由的增加与删除吧！
    范例二：增加路由，主要是本机直接可沟通的网域
[root@linux ~]# ip route add 192.168.5.0/24 dev eth0
# 针对本机直接沟通的网域设定好路由，不需要透过外部的路由器
[root@linux ~]# ip route show
192.168.5.0/24 dev eth0  scope link
....以下省略....

范例三：增加可以通往外部的路由，需透过 router 喔！
[root@linux ~]# ip route add 192.168.10.0/24 via 192.168.5.100 dev eth0
[root@linux ~]# ip route show
192.168.5.0/24 dev eth0  scope link
....其他省略....
192.168.10.0/24 via 192.168.5.100 dev eth0
# 仔细看喔，因为我有 192.168.5.0/24 的路由存在 (我的网卡直接联系)，
# 所以才可以将 192.168.10.0/24 的路由丢给 192.168.5.100
# 那部主机来帮忙传递喔！与之前提到的 route 指令是一样的限制！

范例四：增加预设路由
[root@linux ~]# ip route add default via 192.168.1.2 dev eth0
# 那个 192.168.1.2 就是我的预设路由器 (gateway) 的意思啊！ ^_^
# 真的记得，只要一个预设路由就 OK ！

范例五：删除路由
[root@linux ~]# ip route del 192.168.10.0/24
[root@linux ~]# ip route del 192.168.5.0/24

    事实上，这个 ip 的指令实在是太博大精深了！刚接触 Linux 网路的朋友，可能会看到有点晕～ 不要紧啦！您先会使用 ifconfig, ifup , ifdown 与 route 即可， 等以后有经验了之后，再继续回来玩 ip 这个好玩的指令吧！ ^_^ 有兴趣的话，也可以自行参考 ethtool 这个指令喔！ (man ethtool)。

    小标题的图示 iwlist, iwconfig
    这两个指令您必须要有无线网卡才能够进行喔！这两个指令的用途是这样的：
    • iwlist：利用无线网卡进行无线 AP 的侦测与取得相关的资料；
    • iwconfig：设定无线网卡的相关参数。
    这两个指令的应用我们在前一章里面的 无线网卡设定 谈了很多了，所以这里我们不再详谈，有兴趣的朋友应该先使用 man iwlist 与 man iwconfig 了解一下语法， 然后再到前一章的无线网路小节查一查相关的用法，就了解了啦！ ^_^

    小标题的图示 dhclient
    如果你是使用 DHCP 协定在区域网路内取得 IP 的话，那么是否一定要去编辑 ifcfg-eth0 内的 BOOTPROTO 呢？ 嘿嘿！有个更快速的作法，那就是利用 dhclient 这个指令～因为这个指令才是真正发送 dhcp 要求工作的程式啊！那要如何使用呢？很简单！如果不考虑其他的参数，使用底下的方法即可：
    [root@linux ~]# dhclient eth0
    够简单吧！这样就可以立刻叫我们的网路卡以 dhcp 协定去尝试取得 IP 喔！ 不过在 SuSE distribution 里面，他仅有 dhcpcd 这支程式，他与 dhclient 是相同的咚咚啦！ ^_^

    大标题的图示 网路侦错与观察指令：
    在网路的互助论坛中，最常听到的一句话就是：‘高手求救！我的 Linux 不能连上网路了！’我的天呐！不能上网路的原因多的很！而要完全搞懂也不是一件简单的事情呢！ 不过，事实上我们可以自己使用测试软体来追踪可能的错误原因，而很多的网路侦测指令其实在 Linux 里头已经都预设存在了，只要您好好的学一学基本的侦测指令，那么一些朋友在告诉您如何侦错的时候， 您应该就立刻可以知道如何来搞定他啰！好了，底下我们就简单的来谈一谈几个很基本的网路常用的侦错指令啦！

    小标题的图示 ping
    这个 ping 是很重要的指令，ping 主要透过 ICMP 封包 来进行整个网路的状况报告，当然啦，最重要的就是那个 ICMP type 0, 8 这两个类型， 分别是要求回报与主动回报网路状态是否存在的特性。要特别注意的是， ping 还是需要透过 IP 封包来传送 ICMP 封包的， 而 IP 封包里面有个相当重要的 TTL (Time To Live) 属性，这是很重要的一个路由特性， 详细的 IP 与 ICMP 表头资料请参考网路基础的详细介绍。
    [root@linux ~]# ping [-bcstnM] IP
参数：
-b ：后面接的是 broadcast 的 IP，用在你‘需要对整个网域的主机进行 ping ’时；
-c ：后面接的是执行 ping 的次数，例如 -c 5 ；
-n ：不进行 IP 与主机名称的反查，直接使用 IP ；
-s ：发送出去的 ICMP 封包大小，预设为 56(bytes)，再加 8 bytes 的 ICMP 表头资料
-t ：TTL 的数值，预设是 255，每经过一个节点就会少一；
-M [do|dont] ：主要在侦测网路的 MTU 数值大小，两个常见的项目是：
   do  ：代表传送一个 DF (Don't Fragment) 旗标，让封包不能重新拆包与打包；
   dont：代表不要传送 DF 旗标，表示封包可以在其他主机上拆包与打包

范例一：侦测一下 168.95.1.1 这部 DNS 主机是否存在？
[root@linux ~]# ping -c 3 168.95.1.1
PING 168.95.1.1 (168.95.1.1) 56(84) bytes of data.
64 bytes from 168.95.1.1: icmp_seq=0 ttl=243 time=9.16 ms
64 bytes from 168.95.1.1: icmp_seq=1 ttl=243 time=8.98 ms
64 bytes from 168.95.1.1: icmp_seq=2 ttl=243 time=8.80 ms

--- 168.95.1.1 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2002ms
rtt min/avg/max/mdev = 8.807/8.986/9.163/0.164 ms, pipe 2
    ping 最简单的功能就是传送 ICMP 封包去要求对方主机回应是否存在于网路环境中， 上面的回应讯息当中，几个重要的项目是这样的：
    • 64 bytes：表示这次传送的 ICMP 封包大小为 64 bytes 这么大，这是预设值， 在某些特殊场合中，例如要搜索整个网路内最大的 MTU 时，可以使用 -s 2000 之类的数值来取代；
    • icmp_seq=0：ICMP 所侦测进行的次数，第一次编号为 0 ；
    • ttl=243：TTL 与 IP 封包内的 TTL 是相同的，每经过一个带有 MAC 的节点 (node) 时，例如 router, bridge 时， TTL 就会减少一，预设的 TTL 为 255 ， 你可以透过 -t 150 之类的方法来重新设定预设 TTL 数值；
    • time=9.16 ms：回应时间，单位有 ms(0.001秒)及 us(0.000001秒)， 一般来说，越小的回应时间，表示两部主机之间的网路连线越良好！
    如果你忘记加上 -c 3 这样的规定侦测次数，那就得要使用 [ctrl]-c 将他结束掉了！
    范例二：针对整个网域进行 ping 的追查
[root@linux ~]# ping -c 3 -b 192.168.10.255
WARNING: pinging broadcast address          <==会告知危险喔！
PING 192.168.10.255 (192.168.10.255) 56(84) bytes of data.
64 bytes from 192.168.10.100: icmp_seq=1 ttl=64 time=0.177 ms
64 bytes from 192.168.10.20: icmp_seq=1 ttl=64 time=0.179 ms (DUP!)
64 bytes from 192.168.10.10: icmp_seq=1 ttl=64 time=0.302 ms (DUP!)
64 bytes from 192.168.10.40: icmp_seq=1 ttl=64 time=0.304 ms (DUP!)
# 当要针对整部主机作 ping 的侦测时，可以利用 -b 这个参数。
# 请特别注意，当使用 ping -b 时，会对整个网域进行侦测喔！没事别乱用。
# 例如上面的范例中，区网内的 192.168.10.20... 等主机会被侦测到。
    如果想要了解区网内有多少部主机存活着，那么使用 ping -b broadcast 就能够知道了！ 而不必一部一部主机来侦测啊！方便～另外也特别注意一下， 如果您的主机与待侦测主机并不在同一个网域内， 那么 TTL 预设使用 255 ，如果是同一个网域内，那么 TTL 预设则使用 64 喔！ 看看上面的输出即可了解。

    用 ping 追踪最大 MTU 数值

    我们由前几章的网路基础里面谈到加大讯框 (frame) 时， 对于网路效能是有帮助的，因为封包打包的次数会减少，加上如果整个传输的媒体都能够接受这个 frame 而不需要重新进行封包的拆解与重组的话，那么效能当然会更好，那个修改 frame 大小的参数就是 MTU 啦！好了，现在我们知道网路卡的 MTU 可以透过 ifconfig 或者是 ip 等来达成， 那么追踪整个网路传输的最大 MTU 时，又该如何查询？呵呵！最简单的方法当然是透过 ping 传送一个大封包， 并且不许中继的路由器或 switch 将该封包重组，那就能够处理啦！没错！可以这样的：
    范例三：找出最大的 MTU 数值
[root@linux ~]# ping -c 2 -s 1000 -M do 192.168.10.10
PING 192.168.10.10 (192.168.10.10) 1000(1028) bytes of data.
1008 bytes from 192.168.10.10: icmp_seq=1 ttl=64 time=0.424 ms
# 如果有回应，那就是可以接受这个封包，如果无回应，那就表示这个 MTU 太大了。

[root@linux ~]# ping -c 2 -s 8000 -M do 192.168.10.10
PING 192.168.10.10 (192.168.10.10) 8000(8028) bytes of data.
ping: local error: Message too long, mtu=1500
# 这个错误讯息是说，本地端的 MTU 才到 1500 而已，你要侦测 8000 的 MTU
# 根本就是无法达成的！那要如何是好？用前一小节介绍的 ip link 来进行 MTU 设定吧！
    不过，你需要知道的是，由于 IP 封包表头 (不含 options) 就已经占用了 20 bytes ，再加上 ICMP 的表头有 8 bytes ，所以当然你在使用 -s size 的时候，那个封包的大小就得要先扣除 (20+8=28) 的大小了。 因此如果要使用 MTU 为 1500 时，就得要下达‘ ping -s 1472 -M do xx.yy.zz.ip ’才行啊！ 另外，由于本地端的网路卡 MTU 也会影响到侦测，所以如果想要侦测整个传输媒体的 MTU 数值， 那么每个可以调整的主机就得要先使用 ifcofig 或 ip 先将 MTU 调大，然后再去进行侦测， 否则就会出现像上面提供的案例一样，可能会出现‘Message too long, mtu=1500’之类的字样喔！ 至于如果侦测完毕后，想要调整最佳化的 MTU ，那么请参考前一章节的内容来调整啰！ ^_^

    不过这个 MTU 不要随便调整啊！除非真的有问题。通常调整 MTU 的时间是在这个时候：
    • 因为全部的主机群都是在内部的区网，例如丛集架构 (cluster) 的环境下， 由于内部的网路节点都是我们可以控制的，因此可以透过修改 MTU 来增进网路效能；
    • 因为作业系统预设的 MTU 与您的网域不符，导致某些网站可以顺利连线，某些网站则无法连线。 以 Windows 作业系统作为连线分享的主机时，在 Client 端挺容易发生这个问题；
    如果是要连上 Internet 的主机，注意不要随便调整 MTU ，因为我们无法知道 Internet 上面的每部机器能够支援的 MTU 到多大，因为......不是我们能够管的到的嘛！ ^_^

    另外，其实每种连线方式都有不同的 MTU 值，常见的各种介面的 MTU 值分别为∶

    网路介面 | MTU
Ethernet | 1500
PPPoE | 1492
Dial-up(Modem) | 576

    网路上也有免费帮忙查询 MTU 与传输相关资料的网站，例如底下这个网站：
    • http://forums.speedguide.net:8117/
    连接上这个网站之前，请先取消您浏览器上的代理伺服器 (Proxy) 的设定，才能显示出正确的讯息。 如果在 Windows 的系统上面想要修改 MTU 值的话，那就得要修改 Windows 的登录档， 在 Windows 上面对于 MTU 的侦测与修改的详细作法可以参考微软的官方网站：
    • http://www.microsoft.com/taiwan/msclub/member/TIPS/Spring_2001/tip1to3/tip1to3_2.htm
    小标题的图示 traceroute
    我们前面谈到的指令大多数都是针对主机的网路参数设定所需要的，而 ping 是两部主机之间的回声与否判断， 那么有没有指令可以追踪两部主机之间通过的各个节点 (node) 通讯状况的好坏呢？ 举例来说，如果我们连线到 yahoo 的速度比平常慢，你觉得是 (1)自己的网路环境有问题？ (2)还是外部的 Internet 有问题？如果是 (1) 的话，我们当然需要检查自己的网路环境啊， 看看是否又有谁中毒了？但如果是 Internet 的问题呢？那只有‘等等等’啊！ 判断是 (1) 还是 (2) 就得要使用 traceroute 这个指令啦！
    [root@linux ~]# traceroute [-nwig] IP
参数：
-n ：可以不必进行主机的名称解析，单纯用 IP ，速度较快！
-w ：若对方主机在几秒钟内没有回声就宣告不治...预设是 5 秒
-i ：用在比较复杂的环境，如果你的网路介面很多很复杂时，才会用到这个参数；
     举例来说，你有两条 ADSL 可以连接到外部，那你的主机会有两个 ppp，
     你可以使用 -i 来选择是 ppp0 还是 ppp1 啦！
-g ：与 -i 的参数相仿，只是 -g 后面接的是 gateway 的 IP 就是了。

范例一：
[root@linux ~]# traceroute -n tw.yahoo.com
traceroute to tw.yahoo-ap1.akadns.net (203.84.202.164), 30 hops max, 38 byte packets
 1  61.59.121.1  42.174 ms  41.690 ms  41.058 ms
 2  139.175.172.2  40.962 ms  41.978 ms  40.973 ms
 3  192.72.122.130  40.983 ms  41.930 ms  41.003 ms
 4  139.175.58.210  42.956 ms  41.997 ms  42.337 ms
 5  139.175.58.153  47.591 ms  47.972 ms  48.748 ms
 6  139.175.56.30  48.193 ms  47.970 ms  47.986 ms
 7  139.175.57.94  47.959 ms  47.951 ms  47.985 ms
 8  139.175.56.138  48.363 ms  47.586 ms  47.995 ms
 9  139.175.58.42  49.256 ms  50.668 ms  47.490 ms
10  61.58.33.133  201.882 ms  201.565 ms  200.973 ms
11  61.58.33.50  199.910 ms  199.019 ms  198.961 ms
12  203.84.200.226  202.391 ms  202.567 ms  209.283 ms
    这个 traceroute 挺有意思的，这个指令会针对欲连接的目的地之所有 router 进行 ICMP 的逾时等待， 例如上面的例子当中，由鸟哥的主机连接到 Yahoo 时，他会经过 12 个节点，traceroute 会主动的对这 12 个节点做 ICMP 的回声等待，并侦测回覆的时间，每个节点会侦测三次。 所以像上头显示的结果，发现每个节点其实回覆的时间大约在 200 ms 以内，算是还可以的 Internet 环境了。 而且由上面的资讯来看，可以看出在 61.58.33.133 这个节点后的传输延迟较久，至于之前的 9 个节点则有不错的表现。透过这种解析，可以让您了解到这条连线是那个环节出了问题喔。

    另外，如果在预设的 5 秒钟之内 traceroute 听不到节点的回声，那么荧幕上就会跑出一个‘ * ’的符号， 告知该节点无法有顺利的回应。由于我们的 traceroute 用的是 ICMP 封包，有些防火墙或者主机可能会将 ICMP 可通过的权力拿掉，因此就会造成等不到回声的状态！另外，有些 gateway 本来就不支援 traceroute 的功能，因此也会产生那个‘ * ’的状况。所以分析时得要注意一下呐！

    小标题的图示 netstat
    如果你觉得你的某个网路服务明明就启动了，但是就是无法造成连线的话，那么应该怎么办？ 首先你应该要查询一下自己的网路介面所监听的埠口 (port) 来看看是否真的有启动， 因为有时候荧幕上面显示的 [OK] 并不一定是 OK 啊！ ^_^
    [root@linux ~]# netstat -[rn]       <==与路由有关的参数
[root@linux ~]# netstat -[antulpc]  <==与网路介面有关的参数
参数：
与路由 (route) 有关的参数说明：
-r  ：列出路由表(route table)，功能如同 route 这个指令；
-n  ：不使用主机名称与服务名称，使用 IP 与 port number ，如同 route -n
与网路介面有关的参数：
-a  ：列出所有的连线状态，包括 tcp/udp/unix socket 等；
-t  ：仅列出 TCP 封包的连线；
-u  ：仅列出 UDP 封包的连线；
-l  ：仅列出有在 Listen (监听) 的服务之网路状态；
-p  ：列出 PID 与 Program 的档名；
-c  ：可以设定几秒钟后自动更新一次，例如 -c 5 每五秒更新一次网路状态的显示；

范例一：列出目前的路由表状态，且以 IP 及 port number 显示：
[root@linux ~]# netstat -rn
Kernel IP routing table
Destination     Gateway         Genmask         Flags   MSS Window  irtt Iface
192.168.10.0    0.0.0.0         255.255.255.0   U         0 0          0 eth0
169.254.0.0     0.0.0.0         255.255.0.0     U         0 0          0 eth0
0.0.0.0         192.168.10.30   0.0.0.0         UG        0 0          0 eth0
# 其实这个参数就跟 route -n 一模一样，对吧！这不是 netstat 的主要功能啦！

范例二：列出目前的所有网路连线状态，使用 IP 与 port number
[root@linux ~]# netstat -an
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address               Foreign Address             State
tcp        0      0 0.0.0.0:25                  0.0.0.0:*                   LISTEN
tcp        0      0 :::22                       :::*                        LISTEN
tcp        0      0 ::ffff:192.168.10.100:25    ::ffff:192.168.10.200:57509 TIME_WAIT
tcp        0     52 ::ffff:192.168.10.100:22    ::ffff:192.168.10.210:1504  ESTABLISHED
udp        0      0 127.0.0.1:53                0.0.0.0:*
Active UNIX domain sockets (servers and established)
Proto RefCnt Flags       Type       State         I-Node Path
unix  2      [ ACC ]     STREAM     LISTENING     4792   public/cleanup
unix  2      [ ACC ]     STREAM     LISTENING     4799   private/rewrite
......(底下省略)......
    netstat 的输出主要分为两大部分，分别是 TCP/IP 的网路介面部分，以及传统的 Unix socket 部分。 还记得我们在基础篇里面曾经谈到档案的类型吗？那个 socket 与 FIFO 档案还记得吧？ 那就是在 Unix 介面用来做为程式资料交流的介面了，也就是上头表格内看到的 Active Unix domain sockets 的内容啰～

    通常鸟哥都是建议加上‘ -n ’这个参数的，因为可以避过主机名称与服务名称的反查，直接以 IP 及埠口号码 (port number) 来显示，显示的速度上会快很多！至于在输出的讯息当中， 我们先来谈一谈关于网路连线状态的输出部分，他主要是分为底下几个大项：
    • Proto：该连线的封包协定，主要为 TCP/UDP 等封包；
    • Recv-Q：非由使用者程式连接所复制而来的总 bytes 数；
    • Send-Q：由远端主机所传送而来，但不具有 ACK 标志的总 bytes 数， 意指主动连线 SYN 或其他标志的封包所占的 bytes 数；
    • Local Address：本地端的位址，可以是 IP (-n 参数存在时)， 也可以是完整的主机名称。如上表我们看到的 IP 格式有两种，一种是 IPv4 的标准， 亦即是四组十进位的数字后面加上冒号‘:’后，接着 port number 。一种是 IPv6 ， 前面的 IP 加上很多冒号‘:’的格式。我们可以由这个显示的资料看出这个服务是开放在哪一个介面， 例如上表当中， port 22 是开放在 0.0.0.0 ，亦即是所有介面都可以连到 port 22 ， 至于 port 53 则仅开放在本机的 127.0.0.1 这个介面而已，所以是不对外部介面开放的意思。
    • Foreign Address：远端的主机 IP 与 port number
    • stat：状态列，主要的状态含有：
      • ESTABLISED：已建立连线的状态；
      • SYN_SENT：发出主动连线 (SYN 标志) 的连线封包；
      • SYN_RECV：接收到一个要求连线的主动连线封包；
      • FIN_WAIT1：该插槽服务(socket)已中断，该连线正在断线当中；
      • FIN_WAIT2：该连线已挂断，但正在等待对方主机回应断线确认的封包；
      • TIME_WAIT：该连线已挂断，但 socket 还在网路上等待结束；
      • LISTEN：通常用在服务的监听 port ！可使用‘ -l ’参数查阅。
    基本上，我们常常谈到的 netstat 的功能，就是在观察网路的连线状态了，而网路连线状态中， 又以观察‘我目前开了多少的 port 在等待用户端的连线’以及 ‘目前我的网路连线状态中，有多少连线已建立或产生问题’最常见。 那你如何了解与观察呢？通常鸟哥是这样处理的：
    范例三：秀出目前已经启动的网路服务
[root@linux ~]# netstat -tulnp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address   Foreign Address  State    PID/Program name
tcp        0      0 0.0.0.0:25      0.0.0.0:*        LISTEN   2141/master
tcp        0      0 :::22           :::*             LISTEN   1924/sshd
tcp        0      0 :::25           :::*             LISTEN   2141/master
udp        0      0 127.0.0.1:53    0.0.0.0:*                 1911/named
# 上面最重要的其实是那个 -l 的参数，因为可以仅列出有在 Listen 的 port
    你可以在上面的范例当中发现，我的网路连线仅有对外开放 port 25 以及 port 22 而已 (因为针对 0.0.0.0 开放)， 至于 port 53 则仅针对内部的 127.0.0.1 来开放，所以是不对 Internet 开放这个服务的喔！ 而其中 port 22,25 都是使用 TCP 封包，至于 port 53 则是开放在 UDP 封包的状态！ 再仔细的看，每一行输出的最右边，你可以发现鸟哥的主机 port 22 是由 sshd 这支程式所启动的， 并且他的 PID 是 1924 ，看到这边，聪明的您应该知道，‘那我如何关闭这个 port ’吧？使用 kill 或 killall 即可啊！ ^_^
    范例四：观察本机上头所有的网路连线状态
[root@linux ~]# netstat -atunp
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address     Foreign Address     State       PID/Program name
tcp        0      0 0.0.0.0:25        0.0.0.0:*           LISTEN      2141/master
tcp        0      0 :::22             :::*                LISTEN      1924/sshd
tcp        0      0 :::25             :::*                LISTEN      2141/master
tcp        0     68 192.168.1.100:22  192.168.1.210:1504  ESTABLISHED 30417/sshd:
udp        0      0 127.0.0.1:53      0.0.0.0:*                       1911/named
    看到上头的特殊字体吧？那代表目前已经建立连线的一条网路连线，他是由远端主机 192.168.1.210 启动一个大于 1024 的埠口向本地端主机 192.168.1.100 的 port 22 进行连线的一条连线， 你必须要想起来的是：‘Client 端是随机取一个大于 1024 以上的 port 进行连线’，此外‘只有 root 可以启动小于 1023 以下的 port ’，那就看的懂上头那条连线啰！如果这条连线你想要砍掉他的话， 看到最右边的 30417/sshd 了没？ kill 会用吧！ ^_^

    至于传统的 Unix socket 的资料，记得使用 man netstat 查阅一下吧！ 这个 Unix socket 通常是用在一些仅在本机上运作的程式所开启的插槽介面档， 例如 X Window 不都是在本机上运作而已吗？那何必启动网路的 port 呢？当然可以使用 Unix socket 啰，另外，例如 Postfix 这一类的网路伺服器，由于很多动作都是在本机上头来完成的， 所以以会占用很多的 Unix socket 喔！

    例题一：请说明服务名称与 port number 的对应在 Linux 当中，是用那个档案来设定对应的？

    答：
      /etc/services

    小标题的图示 host
    这个指令可以用来查出某个主机名称的 IP 喔！举例来说，我们想要知道 tw.yahoo.com 的 IP 时， 可以这样做：
    [root@linux ~]# host [-a] hostname [server]
参数：
-a ：列出该主机详细的各项主机名称设定资料
[server] ：可以使用非为 /etc/resolv.conf 的 DNS 主机来查询。

范例一：列出 tw.yahoo.com 的 IP
[root@linux ~]# host tw.yahoo.com
tw.yahoo.com is an alias for tw.yahoo-ap1.akadns.net.
tw.yahoo-ap1.akadns.net has address 202.43.195.52
    瞧！IP 是 202.43.195.52 啊！很简单就可以查询到 IP 了！ 那么这个 IP 是向谁查询的呢？其实就是写在 /etc/resolv.conf 那个档案内的 DNS 主机啦！如果不想要使用该档案内的主机来查询，也可以这样做：
    [root@linux ~]# host tw.yahoo.com 168.95.1.1
Using domain server:
Name: 168.95.1.1
Address: 168.95.1.1#53
Aliases:

tw.yahoo.com is an alias for tw.yahoo-ap1.akadns.net.
tw.yahoo-ap1.akadns.net has address 202.43.195.52
    会告诉我们所使用来查询的主机是哪一部呐！这样就够清楚了吧？至于更详细的 host 用法，我们会在 DNS 主机 那个章节再来好好聊一聊吧！

    小标题的图示 nslookup
    这玩意儿的用途与 host 基本上是一样的，就是用来作为 IP 与主机名称对应的检查， 同样是使用 /etc/resolv.conf 这个档案来作为 DNS 伺服器的来源选择。
    [root@linux ~]# nslookup [-query=[type]] [hostname|IP]
参数：
-query=type：查询的类型，除了传统的 IP 与主机名称对应外，DNS 还有很多资讯，
             所以我们可以查询很多不同的资讯，包括 mx, cname 等等，
             例如： -query=mx 的查询方法！

范例一：找出 www.google.com.tw 的 IP
[root@linux ~]# nslookup www.google.com.tw
Server:         168.95.1.1
Address:        168.95.1.1#53

Non-authoritative answer:
www.google.com.tw       canonical name = www.google.com.
www.google.com  canonical name = www.l.google.com.
Name:   www.l.google.com
Address: 64.233.189.104

范例二：找出 168.95.1.1 的主机名称
[root@linux ~]# nslookup 168.95.1.1
Server:         168.95.1.1
Address:        168.95.1.1#53

1.1.95.168.in-addr.arpa name = dns.hinet.net.
    如何，看起来与 host 差不多吧！不过，这个 nslookup 还可以由 IP 找出主机名称喔！ 例如那个范例二，他的主机名称是： dns.hinet.net 哩！目前大家都建议使用 dig 这个指令来取代 nslookup ，我们会在 DNS 伺服器 那时再来好好谈一谈吧！

    大标题的图示 远端连线指令：
    啥是远端连线呢？其实就是在不同的电脑之间进行登入的情况啦！ 我们可以透过 telnet, ssh 或者是 ftp 等协定来进行远端主机的登入， 底下我们就分别来介绍一下这些基本的指令吧！另外，相关的伺服器我们则会在后续进行说明的。

    小标题的图示 telnet
    telnet 是早期我们在个人电脑上面要连结到伺服器主机上工作时，最重要的一个软体了！ 他不但可以直接连接到伺服器上头，还可以用来连结 BBS 呢！非常棒！ 不过， telnet 本身的资料在传送的时候是使用明码 (原始的资料，没有加密) ， 所以资料在 Internet 上面跑的时候，会比较危险一点 (就怕被别人监听啊)。 更详细的资料我们会在‘远端连线伺服器’章节内做介绍的。
    [root@linux ~]# telnet [host|IP] [port]

范例一：连结到成大梦之大地这个 BBS 站
[root@linux ~]# telnet bbs.dorm.ncku.edu.tw
bbs.ccns.ncku.edu.tw ⊙ 梦之大地 逼逼ㄟ四 ⊙ 140.116.250.3 [DreamBBS Ver.040223]
欢迎光临【 梦之大地 逼逼ㄟ四 】。系统负载：0.16 0.16 0.16 [负载正常]
  ╭─┼────┼─╮        ╭╮          ┌┤梦之大地├─────────┐
  ╭──┬──┬──╮╭───┴┴──┬╮  │                              │
  ╰──┴──┴──╯                │    │ 梦之大地由                   │
  ╭────────╮            ╭─╯    │    【电脑网路爱好社．CCNS】  │
   ╭───┬───╮       ╭──╯        │                     维护管理 │
           │      │   ╭─╯              │                              │
   ╰───┴───╯ ╰┴───────╯  └─────────┤By BenHe├┘

  ┌┤本站站长群├────────┐          ╭              ╭    ╭    ╮
  │站长: billcho                 │  ╭───┼────╮╭─┼─╭┼──┼╮
  │系统: cat                     │          │              │    │    ││
  │站务: muwell  ianwolf         │        ╭╯╮            │    │    ││
  │      renn999 GG              │      ╭╯  ╰╮          │    │    │╯
  │                              │    ╭╯      ╰╮        │╭  │
  └───────────────┘  ╰╯          ╰─╯╰─┴╯  ╰───╯
参观用帐号：guest，申请新帐号：new。目前线上人数 [2183/5000] 人。
请输入代号：
    如上所示，我们可以透过 telnet 轻易的连结到 BBS 上面， 而如果您的主机有开启 telnet 服务的话， 同样的利用‘ telnet IP ’并且输入帐号与密码之后，就能够登入主机了。 另外，在 Linux 上的 telnet 软体还提供了 Kerberos 的认证方式，有兴趣的话请自行参阅 man telnet 的说明。

    除了连结到伺服器以及连结到 BBS 站之外， telnet 还可以用来连结到某个 port (服务) 上头呐！ 举例来说，我们可以用 telnet 连接到 port 110 ，看看这个 port 是否有正确的启动呢？
    范例二：侦测本机端的 110 这个 port 是否正确启动？
[root@linux ~]# telnet localhost 110
Trying 127.0.0.1...
telnet: connect to address 127.0.0.1: Connection refused
# 如果出现这样的讯息，代表这个 port 没有启动或者是这个连线有问题，
# 因为您看到那个 refused 嘛！

[root@linux ~]# telnet localhost 25
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
220 vbird.vbird.idv.tw ESMTP Postfix
ehlo localhost
250-linux.dm.tsai
250-PIPELINING
250-SIZE 10240000
250-VRFY
250-ETRN
250 8BITMIME
quit
221 Bye
Connection closed by foreign host.
    瞧！根据输出的结果，我们就能够知道这个通讯协定 (port number 提供的通讯协定功能) 是否有成功的启动呐！ 而在每个 port 所监听的服务都有其特殊的指令，例如上述的 port 25 就是在本机介面所提供的电子邮件服务， 那个服务所支援的指令就如同上面使用的资料一样，但是其他的 port 就不见得支援这个‘ ehlo ’的命令， 因为不同的 port 有不同的程式嘛！所以当然支援的命令就不同啰！ 与 mail server 有关的 telnet 用法，我们将在邮件伺服器内提到喔！

    小标题的图示 ftp
    常常会听到‘FTP’这个咚咚吧！举例来说，如果你想要下载 Linux 的光碟烧录映象档时，要去哪里下载啊？ 不是说要去义守大学吗？也可以到成大或昆山科大等等的 FTP 网站，嘿嘿！没错～那就是 FTP 提供者啦！ 那我们要如何去下载呢？当然就是透过 ftp 的用户端软体了。在 Linux 底下，我们可以透过 ftp 这个软体， 也可以透过下一小节会提到的 lftp 说～
    [root@linux ~]# ftp [-p] [host|IP] [port]
参数：
-p ：启动被动式模式 (passive, PASV)；

范例一：连线到义守大学去看看
[root@linux ~]# ftp ftp.isu.edu.tw
Connected to ftp.isu.edu.tw (140.127.177.17).
220-欢迎光临义守大学档案伺服器
220-
220-本站提供以下软体可供下载：
220-*******************************************************************************
220-/pub/BeOS/       BeOS 作业系统
220-/pub/Linux/      Linux 作业系统
....(其他省略)....
220-*******************************************************************************
Name (ftp.isu.edu.tw:dmtsai): anonymous
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp>
ftp> help         <==提供更多的可用指令，可以常参考！
ftp> cd /pub      <==变换目录到 /pub 当中
ftp> dir          <==显示远端主机的目录内容
ftp> get file     <==下载 file 这个档案
ftp> mget file    <==下载 file 这个目录或档案
ftp> put file     <==上传 file 这个档案到伺服器上
ftp> delete file  <==删除主机上的 file 这个档案
ftp> mkdir dir    <==建立 dir 这个目录
ftp> lcd /home    <==切换‘本地端主机’的工作目录
ftp> passive      <==启动或关闭 passive 模式
ftp> binary       <==资料传输模式设定为 binary 格式
    FTP 其实算是一个很麻烦的协定，因为他使用两个 port 分别进行命令与资料的交流， 详细的资料我们会在后续的 FTP 伺服器内详谈，这里我们先单纯的介绍一下如何使用 ftp 这个软体。 首先我们当然是需要登入啰，所以在上头的表格当中我们当然需要填入帐号与密码了。 不过由于义守大学提供匿名登入，而匿名登入者的帐号就是‘ anonymous ’所以直接填写那个帐号即可。 如果是私人的 FTP 时，才需要提供一组完整的帐号与密码啦！

    登入 FTP 主机后，就能够使用 ftp 软体的功能进行上传与下载的动作， 几个常用的 ftp 内指令如上表，不过，鸟哥建议您可以连到大学的 FTP 网站后， 使用 help (或问号 ?) 来参考可用的指令，然后尝试下载以测试使用一下这个指令吧！ 这样以后没有浏览器的时候，你也可以到 ftp 下载了呢！不错吧！ ^_^

    另外，如果由于某些理由，让你的 FTP 主机的 port 开在非正规的埠口时， 那你就可以利用底下的方式来连接到该部主机喔！
    [root@linux ~]# ftp hostname 318
# 假设对方主机的 ftp 服务开启在 318 这个 port 啊！
    小标题的图示 lftp
    早期当我们要登入提供匿名登入的主机时，很多时候都是使用 ncftp 这个软体， 不过，现在有更棒的选择，那就是 lftp 啦！这个软体甚至可以在 ftp 里面使用类似 bash 的指令功能， 实在是非常的完美！而整个使用的方法与上面提到的 ftp 又非常类似呐！
    [root@linux ~]# lftp [-p port] [-u user[,pass]] [host|IP]
参数：
-p  ：后面可以直接接上远端 FTP 主机提供的 port
-u  ：后面则是接上 帐号与密码 ，就能够连接上远端主机了
      如果没有加帐号密码， lftp 预设会使用 anonymous 尝试匿名登入

范例一：利用 lftp 登入义守大学
[root@linux ~]# lftp ftp.isu.edu.tw
lftp ftp.isu.edu.tw:~>
# 瞧！一下子就登入了！很快乐吧！ ^_^
    至于登入 FTP 主机后，一样可以使用‘help’来显示出可以执行的指令， 与 ftp 很类似啦！不过多了书签的功能，而且也非常的类似 bash 那！很不错呦！ 除了这个好用的文字介面的 FTP 软体之外，事实上还有很多图形介面的好用软体呢！ 最常见的就是 gftp 了～不但是图形介面，而且与 cute ftp 简直就是像到不行！非常的容易上手喔！ CentOS 本身就有提供 gftp 了，你可以拿出原版的光碟来安装，然后进入 X Window 后， 启动一个 shell ，输入‘ gftp ’就能够发现他的好用啦！底下我们在来介绍一下即时通讯吧！

    小标题的图示 gaim
    我想，现在应该大家都知道什么是 MSN, 雅虎即时通以及其他的通讯软体吧？ 那么要连上这些伺服器时，该怎么处理哪？很简单，在 X Window 底下使用 gaim 就好了！ 简直简单到不行～ ^_^ 请先进入 X Window 系统，然后开启一个终端机视窗，接着直接输入 gaim (请注意您必须已经安装了 gaim 了) 然后就会出现如下的视窗啦：

    gaim 使用范例图
    图一、gaim 使用范例图

    在输入你的帐号与密码，并选择相对应的即时通讯伺服器 (如 MSN 或 Yahoo 即时通) ，就可以进入到如下画面：

    gaim 使用范例图
    图二、gaim 使用范例图

    若一切都没有问题后，按下‘登入’嘿嘿～您就可以在 Linux 上头使用即时通讯软体啦！方便的很哩！ ^_^

    大标题的图示 文字介面网页浏览
    什么？文字界面竟然有浏览器！别逗了好不好？呵呵！谁有那个时间在逗您呦！真的啦！有这个东西， 是在文字界面下上网浏览的好工具！分别是 lynx 及 wget 这两个宝贝蛋，但是，您必需要确定您已经安装了这两个套件才行。 底下就让我们来聊一聊这两个好用的家伙吧！

    小标题的图示 lynx
    这个指令可以让我们来浏览网页，但鸟哥认为，这个档案最大的功能是在‘ 查阅 Linux 本机上面以 HTML 语法写成的文件资料 (document)’ 怎么说呢？如果你曾经到 Linux 本机底下的 /usr/share/doc 这个目录看过文件资料的话， 就会常常发现一些网页档案，使用 vi 去查阅时，老是看到一堆 HTML 的语法！有碍阅读啊～ 这时候使用 lynx 就是个好方法啦！可以看的清清楚楚啊！ ^_^
    [root@linux ~]# lynx [options] [website]
参数：
options 指的是一些惯用的参数，可以使用 man lynx 查阅，常见的有：
-anonymous ：预设使用匿名登入；
-assume_charset=big5 ：设定预设的语系资料为 big5 ，用在中文网页很方便

范例一：浏览 Linux kernel 网站
[root@linux ~]# LANG=zh_TW.big5
[root@linux ~]# lynx http://www.kernel.org
    输入 LANG=zh_TW.big5 是当您想要浏览中文网站时，那么终端机就得要有相对应的显示编码才行， 否则会有一堆乱码产生啊！当我直接输入 lynx 网站网址后，就会出现如下的图示：

    lynx 使用范例图
    图三、lynx 使用范例图

    在特殊字体的部分是我们可以使用 <tab> 按键来进行‘超连结’的按钮啦～而上图最底下一行则显示出一些热键， 你可以按上述的热键来参考一些常见的指令功能。不过有些地方您还是得要知道才行：
    • 进入画面之后，由于是文字型态，所以编排可能会有点位移！不过不打紧！不会影响我们看咚咚！
    • 这个时候可以使用‘上下键’来让游标在上面的选项当中(如信箱、书签等等的)，按下 Enter 就进入该页面
    • 可以使用‘左右键’来移动‘上一页或下一页’
    • 可以藉由修改 /etc/lynx.cfg 来设定显示的字元编码 (台湾地区可以选择 Big5 编码)
    • 其他的设定可以使用上面的范例当中，最底下那一行的说明喔！
    • 一些常见功能：
      • h：Help, 求助功能. 线上说明书.
      • g：Goto URL, 按 g 后输入网页位址(URL) 如:http://www.abc.edu/等
      • d：download, 下载档案.
      • q：Quit, 跳离 lynx !
      • Ctrl+C ：强迫切断 lynx 的执行.
      • 方向键:
        • 上 ：移动游标至本页中 "上一个可连结点" .
        • 下 ：移动游标至本页中 "下一个可连结点" .
        • 左 ：back. 跳回上一页.
        • 右 ：进入反白游标所连结之网页.
        • ENTER 同 "右" 键.
    至于如果是浏览 Linux 本机上面的网页档案，那就可以使用如下的方式：
    [root@linux ~]# cd /usr/share/doc/samba-3.0.10/htmldocs
[root@linux htmldocs]# lynx index.html
    在鸟哥的 CentOS 4.3 当中，有这么一个档案，我就可以利用 lynx 来取出察看呐！ 显示的结果有点像底下这样：

    lynx 使用范例图
    图四、lynx 使用范例图

    当然啦！因为您的环境可能是在 Linux 本机的 tty1~tty6 ，所以无法显示出中文， 这个时候你就得要设定为：‘LANG=en_US’之类的语系设定才行喔！ 而如果你常常需要浏览中文语系的网页，那就可以直接修改设定档，例如 /etc/lynx.cfg 这个档案内：
    [root@linux ~]# vi /etc/lynx.cfg
CHARACTER_SET:utf-8            <==约在 399 行
#ASSUME_CHARSET:iso-8859-1     <==约在 414 行
#PREFERRED_LANGUAGE:en         <==约在 542 行

# 你可以将他改成如下所示：
CHARACTER_SET:big5
ASSUME_CHARSET:big5
PREFERRED_LANGUAGE:zh_TW
    另外，如果某些时刻你必须上网点选某个网站以自动取得更新时，举例来说，早期的自动线上更新主机名称系统， 仅支援网页更新，那你如何进行更新呢？嘿嘿！可以使用 lynx 喔！利用 -dump 这个参数处理先：
    [root@linux ~]# lynx -dump \
> http://some.site.name/web.htm?name=user&password=pw > testfile
    上面的网站后面有加个问号 (?) 对吧？后面接的则是利用网页的‘ GET ’功能取得的各项变数资料， 利用这个功能，我们就可以直接点选到该网站上啰！非常的方便吧！而且会将执行的结果输出到 testfile 档案中，不过如果网站提供的资料是以‘ POST ’为主的话，那鸟哥就不知道如何搞定了。 关于 GET 与 POST 的相关资讯我们会在 WWW 伺服器当中再次的提及的！别紧张啊！

    小标题的图示 wget
    如果说 lynx 是在进行网页的‘浏览’，那么 wget 就是在进行‘网页资料的取得’。 举例来说，我们的 Linux 核心是放置在 www.kernel.ort 内，主要同时提供 ftp 与 http 来下载。 我们知道可以使用 lftp 来下载资料，但如果想要用浏览器来下载呢？ 那就利用 wget 吧！
    [root@linux ~]# wget [option] [网址]
参数：
若想要连线的网站有提供帐号与密码的保护时，可以利用这两个参数来输入喔！
--http-user=usrname
--http-password=password
--quiet ：不要显示 wget 在抓取资料时候的显示讯息
更多的参数请自行参考 man wget 吧！ ^_^

范例一：请下载 2.6.17 版的核心
[root@linux ~]# wget  \
> http://www.kernel.org/pub/linux/kernel/v2.6/linux-2.6.17.tar.gz
--16:06:10--  http://www.kernel.org/pub/linux/kernel/v2.6/linux-2.6.17.tar.gz
           => `linux-2.6.17.tar.gz'
Resolving www.kernel.org... 204.152.191.37, 204.152.191.5
Connecting to www.kernel.org|204.152.191.37|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 51,700,445 (49M) [application/x-gzip]

 3% [==>                        ] 1,890,568    220.69K/s    ETA 04:12
    您瞧瞧～很可爱吧！不必透过浏览器，只要知道网址后，立即可以进行档案的下载， 又快速又方便，还可以透过 proxy 的帮助来下载呢！透过修改 /etc/wgetrc 来设定你的代理伺服器：
    [root@linux ~]# vi /etc/wgetrc
#http_proxy = http://proxy.yoyodyne.com:18023/  <==找到底下这几行，大约在 78 行后；
#ftp_proxy = http://proxy.yoyodyne.com:18023/
#use_proxy = on

# 将他改成类似底下的模样，记得，你必须要有可接受的 proxy 主机才行！
http_proxy = http://proxy.ncku.edu.tw:3128/
use_proxy = no
    大标题的图示 封包撷取功能
    很多时候由于我们的网路连线出现问题，使用类似 ping 的软体功能却又无法找出问题点， 最常见的是因为路由与 IP 转递后所产生的一些困扰 (请参考防火墙与 NAT 主机部分)， 这个时候要怎么办？最简单的方法就是‘分析封包的流向’啰！ 透过分析封包的流向，我们可以了解一条连线应该是如何进行双向的连线的动作， 也就会清楚的了解到可能发生的问题所在了！底下我们就来谈一谈这个 tcpdump 与图形介面的封包分析软体吧！

    小标题的图示 tcpdump
    说实在的，对于 tcpdump 这个软体来说，你甚至可以说这个软体其实就是个骇客软体， 因为他不但可以分析封包的流向，连封包的内容也可以进行‘监听’， 如果你使用的传输资料是明码的话，不得了，在 router 上面就可能被人家监听走了！ 很可怕呐！所以，我们也要来了解一下这个软体啊！(注：这个 tcpdump 必须使用 root 的身份执行)
    [root@linux ~]# tcpdump [-nn] [-i 介面] [-w 储存档名] [-c 次数] [-Ae]
                        [-qX] [-r 档案] [所欲撷取的资料内容]
参数：
-nn：直接以 IP 及 port number 显示，而非主机名与服务名称
-i ：后面接要‘监听’的网路介面，例如 eth0, lo, ppp0 等等的介面；
-w ：如果你要将监听所得的封包资料储存下来，用这个参数就对了！后面接档名
-c ：监听的封包数，如果没有这个参数， tcpdump 会持续不断的监听，
     直到使用者输入 [ctrl]-c 为止。
-A ：封包的内容以 ASCII 显示，通常用来捉取 WWW 的网页封包资料。
-e ：使用资料连接层 (OSI 第二层) 的 MAC 封包资料来显示；
-q ：仅列出较为简短的封包资讯，每一行的内容比较精简
-X ：可以列出十六进位 (hex) 以及 ASCII 的封包内容，对于监听封包内容很有用
-r ：从后面接的档案将封包资料读出来。那个‘档案’是已经存在的档案，
     并且这个‘档案’是由 -w 所制作出来的。
所欲撷取的资料内容：我们可以专门针对某些通讯协定或者是 IP 来源进行封包撷取，
     那就可以简化输出的结果，并取得最有用的资讯。常见的表示方法有：
     'host foo', 'host 127.0.0.1' ：针对单部主机来进行封包撷取
     'net 192.168' ：针对某个网域来进行封包的撷取；
     'src host 127.0.0.1' 'dst net 192.168'：同时加上来源(src)或目标(dst)限制
     'tcp port 21'：还可以针对通讯协定侦测，如 tcp, udp, arp, ether 等
     还可以利用 and 与 or 来进行封包资料的整合显示呢！

范例一：以 IP 与 port number 捉下 eth0 这个网路卡上的封包，持续 3 秒
[root@linux ~]# tcpdump -i eth0 -nn
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 96 bytes
01:33:40.41 IP 192.168.1.100.22 > 192.168.1.11.1190: P 116:232(116) ack 1 win 9648
01:33:40.41 IP 192.168.1.100.22 > 192.168.1.11.1190: P 232:364(132) ack 1 win 9648
<==按下 [ctrl]-c 之后结束
6680 packets captured              <==捉下来的封包数量
14250 packets received by filter   <==由过滤所得的总封包数量
7512 packets dropped by kernel     <==被核心所丢弃的封包
    如果你是第一次看 tcpdump 的 man page 时，肯定一个头两个大，因为 tcpdump 几乎都是分析封包的表头资料，使用者如果没有简易的网路封包基础，要看懂粉难呐！ 所以，至少您得要回到网路基础里面去将 TCP 封包的表头资料理解理解才好啊！ ^_^！至于那个范例一所产生的输出范例中，我们可以约略区分为数个栏位， 我们以范例一当中那个特殊字体行来说明一下：
    • 01:33:40.41：这个是此封包被撷取的时间，‘时:分:秒’的单位；
    • IP：透过的通讯协定是 IP ；
    • 192.168.1.100.22 > ：传送端是 192.168.1.100 这个 IP，而传送的 port number 为 22，您必须要了解的是，那个大于 (>) 的符号指的是封包的传输方向喔！
    • 192.168.1.11.1190：接收端的 IP 是 192.168.1.11， 且该主机开启 port 1190 来接收；
    • P 116:232(116)：这个封包带有 PUSH 的资料传输标志， 且传输的资料为整体资料的 116~232 byte，所以这个封包带有 116 bytes 的资料量；
    • ack 1 win 9648：ACK与 Window size 的相关资料。
    最简单的说法，就是该封包是由 192.168.1.100 传到 192.168.1.11，透过的 port 是由 22 到 1190 ， 且带有 116 bytes 的资料量，使用的是 PUSH 的旗标，而不是 SYN 之类的主动连线标志。 呵呵！不容易看的懂吧！所以说，上头才讲请务必到 TCP 表头资料的部分去瞧一瞧的啊！

    再来，一个网路状态很忙的主机上面，你想要取得某部主机对你连线的封包资料而已时， 使用 tcpdump 配合管线命令与正规表示法也可以，不过，毕竟不好捉取！ 我们可以透过 tcpdump 的表示法功能，就能够轻易的将所需要的资料独立的取出来。 在上面的范例一当中，我们仅针对 eth0 做监听，所以整个 eth0 介面上面的资料都会被显示到荧幕上， 不好分析啊！那么我们可以简化吗？例如只取出 port 21 的连线封包，可以这样做：
    [root@linux ~]# tcpdump -i eth0 -nn port 21
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 96 bytes
01:54:37.96 IP 192.168.1.11.1240 > 192.168.1.100.21: . ack 1 win 65535
01:54:37.96 IP 192.168.1.100.21 > 192.168.1.11.1240: P 1:21(20) ack 1 win 5840
01:54:38.12 IP 192.168.1.11.1240 > 192.168.1.100.21: . ack 21 win 65515
01:54:42.79 IP 192.168.1.11.1240 > 192.168.1.100.21: P 1:17(16) ack 21 win 65515
01:54:42.79 IP 192.168.1.100.21 > 192.168.1.11.1240: . ack 17 win 5840
01:54:42.79 IP 192.168.1.100.21 > 192.168.1.11.1240: P 21:55(34) ack 17 win 5840
    瞧！这样就仅提出 port 21 的资讯而已，且仔细看的话，你会发现封包的传递都是双向的， client 端发出‘要求’而 server 端则予以‘回应’，所以，当然是有去有回啊！ 而我们也就可以经过这个封包的流向来了解到封包运作的过程。 举例来说：
    1. 我们先在一个终端机视窗输入‘ tcpdump -i lo -nn ’ 的监听，
    2. 再另开一个终端机视窗来对本机 (127.0.0.1) 登入‘ssh localhost’
    那么输出的结果会是如何？
    [root@linux ~]# tcpdump -i lo -nn
 1 tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
 2 listening on lo, link-type EN10MB (Ethernet), capture size 96 bytes
 3 11:02:54.253777 IP 127.0.0.1.32936 > 127.0.0.1.22: S 933696132:933696132(0)
   win 32767 <mss 16396,sackOK,timestamp 236681316 0,nop,wscale 2>
 4 11:02:54.253831 IP 127.0.0.1.22 > 127.0.0.1.32936: S 920046702:920046702(0)
   ack 933696133 win 32767 <mss 16396,sackOK,timestamp 236681316 236681316,nop,
   wscale 2>
 5 11:02:54.253871 IP 127.0.0.1.32936 > 127.0.0.1.22: . ack 1 win 8192 <nop,
   nop,timestamp 236681316 236681316>
 6 11:02:54.272124 IP 127.0.0.1.22 > 127.0.0.1.32936: P 1:23(22) ack 1 win 8192
   <nop,nop,timestamp 236681334 236681316>
 7 11:02:54.272375 IP 127.0.0.1.32936 > 127.0.0.1.22: . ack 23 win 8192 <nop,
   nop,timestamp 236681334 236681334>
    上表显示的头两行是 tcpdump 的基本说明，然后：
    • 第 3 行显示的是‘来自 client 端，带有 SYN 主动连线的封包’，
    • 第 4 行显示的是‘来自 server 端，除了回应 client 端之外(ACK)，还带有 SYN 主动连线的标志；
    • 第 5 行则显示 client 端回应 server 确定连线建立 (ACK)
    • 第 6 行以后则开始进入资料传输的步骤。
    从第 3-5 行的流程来看，熟不熟悉啊？没错！那就是 三向交握 的基础流程啦！够有趣吧！ 不过 tcpdump 之所以被称为骇客软体之一可不止上头介绍的功能呐！ 上面介绍的功能可以用来作为我们主机的封包连线与传输的流程分析， 这将有助于我们了解到封包的运作，同时了解到主机的防火墙设定规则是否有需要修订的地方。

    更神奇的使用要来啦！如果我们使用 tcpdump 在 router 上面监听‘明码’的传输资料时， 例如 FTP 传输协定，你觉得会发生什么问题呢？ 我们先在主机端下达‘ tcpdump -i lo port 21 -nn -X ’然后再以 ftp 登入本机，并输入帐号与密码， 结果你就可以发现如下的状况：
    [root@linux ~]# tcpdump -i lo -nn -X 'port 21'
    0x0000:  4500 0048 2a28 4000 4006 1286 7f00 0001  E..H*(@.@.......
    0x0010:  7f00 0001 0015 80ab 8355 2149 835c d825  .........U!I.\.%
    0x0020:  8018 2000 fe3c 0000 0101 080a 0e2e 0b67  .....<.........g
    0x0030:  0e2e 0b61 3232 3020 2876 7346 5450 6420  ...a220.(vsFTPd.
    0x0040:  322e 302e 3129 0d0a                      2.0.1)..

    0x0000:  4510 0041 d34b 4000 4006 6959 7f00 0001  E..A.K@.@.iY....
    0x0010:  7f00 0001 80ab 0015 835c d825 8355 215d  .........\.%.U!]
    0x0020:  8018 2000 fe35 0000 0101 080a 0e2e 1b37  .....5.........7
    0x0030:  0e2e 0b67 5553 4552 2064 6d74 7361 690d  ...gUSER.dmtsai.
    0x0040:  0a                                       .

    0x0000:  4510 004a d34f 4000 4006 694c 7f00 0001  E..J.O@.@.iL....
    0x0010:  7f00 0001 80ab 0015 835c d832 8355 217f  .........\.2.U!.
    0x0020:  8018 2000 fe3e 0000 0101 080a 0e2e 3227  .....>........2'
    0x0030:  0e2e 1b38 5041 5353 206d 7970 6173 7377  ...8PASS.mypassw
    0x0040:  6f72 6469 7379 6f75 0d0a                 ordisyou..
    上面的输出结果已经被简化过了，你必须要自行在你的输出结果当中搜寻相关的字串才行。 从上面输出结果的特殊字体中，我们可以发现‘该 FTP 软体使用的是 vsftpd ，并且使用者输入 dmtsai 这个帐号名称，且密码是 mypasswordisyou’ 嘿嘿！你说可不可怕啊！如果使用的是明码的方式来传输你的网路资料？ 所以我们才常常在讲啊，网路是很不安全低！

    另外你得了解，为了让网路介面可以让 tcpdump 监听，所以执行 tcpdump 时网路介面会启动在 ‘错乱模式 (promiscuous)’，所以你会在 /var/log/messages 里面看到很多的警告讯息， 通知你说你的网路卡被设定成为错乱模式！别担心，那是正常的。 至于更多的应用，请参考 man tcpdump 啰！

    例题：如何使用 tcpdump 监听 (1)来自 eth0 介面卡且 (2)通讯协定为 port 22 ，(3)目标来源为 192.168.1.100 的封包资料？

    答：
      tcpdump -i eth0 -nn 'port 22 and src host 192.168.1.100'

    小标题的图示 ethereal
    除了 tcpdump 这个软体之外，其实你还可以使用 ethereal 这个好用的网路流量分析软体呐！ ethereal 分为文字介面与图形介面，文字介面的用法与 tcpdump 相当的类似，不过他的指令名称为 tethereal 就是了。因为用法差不多，所以建议您直接使用 man tethereal 查阅吧！ 在 CentOS 上原本就有 ethereal 了，所以请拿出光碟来安装即可喔！ 需要安装 ethereal 与 ethereal-gnome 才行呐！

    启动的方法很简单，你必须要在 X Window 底下，先开启一个终端机，然后直接输入 ethereal 后， 就会出现如下的画面了：

    ethereal 使用范例图
    图五、ethereal 使用范例图

    简单的作法，你可以点选如上图显示的那个按钮，会出现挑选监听的介面视窗，如下所示：

    ethereal 使用范例图
    图六、ethereal 使用范例图

    你应该选择要监听的介面，在这里因为是测试用的，所以鸟哥使用的是 lo 这个内部介面， 你当然应该要选择你自己的网路介面才是。然后按下 start 后，就会出现开始侦测的画面了：

    ethereal 使用范例图
    图七、ethereal 使用范例图

    在这个画面当中你可以看到很多类型的封包协定，在等你处理完毕后，就可以按下‘stop’结束监听， 而开始进入如下的封包分析画面。

    ethereal 使用范例图
    图八、ethereal 使用范例图

    封包分析画面共分为三大区块，如上图所示，第一区块主要显示的是封包的标头资料， 内容就有点类似 tcpdump 的显示结果，第二区块则是详细的表头资料， 包括讯框的内容、通讯协定的内容以及 socket pair 等等资讯。 第三区块则是 16 进位与 ASCII 码的显示结果。透过这个 ethereal 您就可以一口气得到所需要的所有封包内容啦！ 而且还是图形介面的，很方便吧！透过在第一区块选择不同的封包，就能够查阅每个封包的资料内容啰！

    小标题的图示 nc, netcat
    这个 nc 可以用来作为某些服务的检测，因为他可以连接到某个 port 来进行沟通， 此外，还可以自行启动一个 port 来倾听其他用户的连线呐！非常的不错用！ 如果在编译的时候给予‘GAPING_SECURITY_HOLE’参数的话，嘿嘿！ 这个软体还可以用来取得用户端的 bash 哩！可怕吧！我们的 CentOS 比较人性化，并没有给予上面的参数，所以我们不能够用来作为骇客软体～ 但是用来取代 telnet 也是个很棒的功能了！(有的系统将执行档改名为 netcat 啦！)
    [root@linux ~]# nc [IP|host] [port]
[root@linux ~]# nc -l -p [port]
参数：
-l ：作为监听之用，亦即开启一个 port 来监听用户的连线；
-p ：开启的这个 port number

范例一：连接本地端的 port 25 查阅相关讯息
[root@linux ~]# nc localhost 25
localhost.localdomain [127.0.0.1] 25 (smtp) open
220 pc.dm.tsai ESMTP Postfix
ehlo localhost
250-pc.dm.tsai
250-PIPELINING
250-SIZE 40000000
250-ETRN
quit
221 Bye
    这个最简单的功能与 telnet 几乎一样吧！可以去检查某个服务啦！不过，更神奇的在后面， 我们可以建立两个连线来传讯喔！举个例子来说，我们先在 client 端的地方启动一个 port 来进行倾听：
    范例二：启动一个 port 来监听使用者的连线要求
[root@linux ~]# nc -l -p 20000
# 启动一个 port 20000  在主机上，如果此时使用 netstat -tlnp
# 就可以看到系统上多出来一个 port 20000 在倾听使用者的连线喔！
    然后在主机端的地方，也利用 nc 来连线到用户端，并且输入一些指令看看喔！
    [root@linux ~]# nc localhost 20000
   <==这里可以开始输入字串了！
    此时，在主机端我们可以打入一些字，你会发现在 client 端会同时出现你输入的字眼呐！ 如果你同时给予一些额外的参数，例如利用标准输入与输出 (stdout, stdin) 的话， 那么就可以透过这个连线来作很多事情了！ 当然 nc 的功能不只如此，你还可以发现很多的用途喔！ 请自行到您主机内的 /usr/share/doc/nc-1.10/scripts 目录下看看这些 script ，有帮助的呐！ 不过，如果你需要额外的编译出含有 GAPING_SECURITY_HOLE 功能， 以使两端连线可以进行额外指令的执行时，就得要自行下载原始码来编译了！

    大标题的图示 重点回顾
    • 修改网路介面的硬体相关参数，可以使用 ifconfig 这个指令，包括 MTU 等等；
    • ifup 与 ifdown 其实只是 script ，在使用时，会主动去 /etc/sysconfig/network-scripts 下找到相对应的装置设定档，才能够正确的启动与关闭；
    • 路由的修改与查阅可以使用 route 来查询，此外， route 亦可进行新增、删除路由的工作；
    • ip 指令可以用来作为整个网路环境的设定，利用 ip link 可以修改‘网路装置的硬体相关功能’， 包括 MTU 与 MAC 等等，可以使用 ip address 修改 TCP/IP 方面的参数，包括 IP 以及网域参数等等， ip route 则可以修改路由！
    • ping 主要是透过 ICMP 封包来进行网路环境的检测工作，并且可以使用 ping 来查询整体网域可接受最大的 MTU 值；
    • 侦察每个节点的连线状况，可以使用 traceroute 这个指令来追踪！
    • netstat 除了可以观察本机的启动介面外，还可以观察 Unix socket 的传统插槽介面资料；
    • host 与 nslookup 预设都是透过 /etc/resolv.conf 内设定的 DNS 主机来进行主机名称与 IP 的查询；
    • lftp 可以用来匿名登入远端的 FTP 主机；
    • telnet 不只用来进行 BBS 的登入，也可以用来作为某些埠口的连线测试；
    • lynx 主要的功能是‘浏览’，包括本机上 HTML 语法的档案， wget 则主要在用来下载 WWW 的资料；
    • 撷取封包以分析封包的流向，可使用 tcpdump ，至于图形介面的 ethereal 则可以进行更为详细的解析。
    • 透过 tcpdump 分析三向交握，以及分析明码传输的资料，可发现网路加密的重要性。
    • nc 可用来取代 telnet 进行某些服务埠口的检测工作，同时若自行编译 nc 时，可额外的执行 -e 参数。
    大标题的图示 课后练习
    • 暂时将你的 eth0 这张网路卡的 IP 设定为 192.168.1.100 ，如何进行？
      • ifconfig eth0 192.168.1.100
    • 我要增加一个路由规则，以 eth0 连接 192.168.100.100/24 这个网域，应该如何下达指令？
      • route add -net 192.l68.100.0 netmask 255.255.255.0 dev eth0
    • 我的网路停顿的很厉害，尤其是连接到 tw.yahoo.com 的时候，那么我应该如何检查那个环节出了问题？
      • traceroute tw.yahoo.com
    • 我发现我的 Linux 主机上面有个连线很怪异，想要将他断线，应该如何进行？
      • 以 root 的身份进行‘netstat -anp |more’查出该连线的 PID，然后以‘ kill -9 PID ’踢掉该连线。
    • 您如何知道 green.ev.ncku.edu.tw 这部主机的 IP ？
      • 方法很多，可以利用 host green.ev.ncku.edu.tw 或 dig green.ev.ncku.edu.tw 或 nslookup green.ev.ncku.edu.tw 等方法找出
    • 请找出您的机器上面最适当的 MTU 应该是多少？
      • 请利用‘ping -c 3 -M do -s MTU yourIP ’找出您的 IP 的 MTU 数值。 事实上，你还可以先以 ip 设定网路卡较大的 MTU 后，在进行上述的动作，才能够找出网域内适合的 MTU。
    • 如何在终端机介面上面进行 WWW 浏览？又该如何下载 WWW 上面提供的档案？
      • 要浏览可以使用 lynx ，至于要下载则使用 wget 这个软体。
    • 在终端机介面中，如何连接 bbs.sayya.org 这个 BBS ？
      • 利用 telnet bbs.sayya.org 即可连接上
    • 请自行以 tcpdump 观察本机端的 ssh 连线时，三向交握的内容
    • 请自行回答：为何使用明码传输的网路连线资料较为危险？并自行以软体将封包取出，并与同学讨论封包的资讯
    • 请自行至 Internet 下载 nc(netcat) 的原始码，并且编译成为具有 GAPING_SECURITY_HOLE 的参数， 然后建立一条连线使用 -e /bin/bash 尝试将本地端的 bash 丢给目的端执行 (特殊功能，可让 client 取得来自主机的 bash)。
    大标题的图示 参考资料
    • 查询 MTU 的网站： http://forums.speedguide.net:8117/
    • 在 Windows 底下修改 MTU 的方法： http://www.microsoft.com/taiwan/msclub/member/TIPS/Spring_2001/tip1to3/tip1to3_2.htm
    • 本章各指令的 man page 说明文件
    2002/07/31：第一次完成日期！
    2003/08/19：重新编排版面，加入 jmcce 的安装以及 MTU 的相关说明
    2003/08/20：加入课后练习去
    2003/09/19：加入参考用解答咯！
    2005/03/24：route 的指令参数写错了！已经订正！
    2006/07/24：将旧的文章移动到 此处
    2006/07/24：拿掉相关性不高的 JMCCE 中文终端机； 将 Windows 系统的 MTU 检测修改方法移除。 也拿掉 ncftp 的说明
    2006/08/02：修改了很多部分，加入一些封包侦测的功能程式，tcpdump, nc 等指令！
    2002/07/31以来统计人数


鸟哥的 Linux 私房菜 -- Linux 网路侦测功能

为取得较佳浏览结果，请爱用 firefox 浏览本网页

Linux 网路侦错
切换解析度为 800x600
最近更新日期：2006/08/04
Linux 最强的，也是最让人称道的地方，就是他的网路功能了，不论是 Mail server、Web server、Proxy server 等等，都好好用喔！但是，我们也常在网路上看到一堆常见的问题，就是在问‘我的 Linux 没有办法连上网路，该如何是好....’等等的问题，问来问去的重点大概都是一样的状况！伤脑筋！那鸟哥就把一些在 Linux 上面可能会发生的网路问题把他整理一下，看看您是不是有这方面的问题，参考看看吧！

1. 无法连线原因分析
    1.1 硬体问题
    1.2 软体问题
    1.3 问题的处理
 2. 处理流程
    2.1 步骤一：网路卡工作确认
    2.2 步骤二：区域网路内各项连接设备检测
    2.3 步骤三：取得正确的 IP 参数
    2.4 步骤四：确认路由表的规则
    2.5 步骤五：主机名称与 IP 查询的 DNS 错误
    2.6 步骤六：Linux 的 NAT 伺服器或 IP 分享器出问题
    2.7 步骤七：Internet 的问题
    2.8 步骤八：主机的问题
 3. 课后练习
4. 针对本文的建议：http://phorum.vbird.org/viewtopic.htm?t=26155
大标题的图示 无法连线原因分析
老是看到有朋友在网路上哀嚎说：‘我的网路不通啊！’还有比较奇怪的是‘啊怎么网路时通时不通’之类的问题， 这类的问题其实主要可以归类为硬体问题与软体设定问题，硬体的问题比较麻烦，因为需要透过一些专门的装置来分析硬体； 至于软体方面，绝大部分都是设定错误或者是观念错误而已，比较好处理啦！ OK！我们先来看看网路在哪里可能会出问题吧！

小标题的图示 硬体问题
在网路基础章节当中我们曾提到很多的网路基础概念， 以及一些简单的硬体维护问题。以一个简单的星形连线来说，我们可以假设他的架构如同下图所示：

区域网路的连线状态示意图
图一、区域网路的连线状态示意图

在上面的图示当中，"Linux PC3" 要连到 Internet 上面去的话，需要透过网路线、 交换器、 NAT 主机 (Linux 伺服器或 IP 分享器)、ADSL 数据机，以及 Internet 上面的所有媒体设备 (包括路由器、桥接器、其他网路线等等)； 那么哪些地方可能会出问题啊？
  1. 网路线材的问题：

    在上面的图示中，可以发现，其实网路周边设备中，使用最多的就是网路线啦！ 要注意网路线分成平行线与跳线 (RJ-45接头) ，而并不是所有的设备都支援自动分辨跳线与平行线的功能的！ 所以你必须要了解到你的设备 (Hub/Switch/数据机) 所支援的网路线；另外， 如果你的网路线是接在门缝处或者是容易凹折处，那很有可能具有被压毁的情况， 所以您需要注意一下这些事情：

    • 网路线被截断；
    • 网路线过度扭曲变形造成讯号不良；
    • 自制网路接头 ( 如RJ-45跳线头 ) 品质不良；
    • 网路接头与设备 ( 如 Hub )接触不良；

  2. 网路卡、Hub 及 Router 等网路设备的问题：

    另外，还有一些网路设备也会有问题，常见的问题如下：

    • 网路卡不稳定、品质不佳，或者与整体系统的相容度不佳；
    • 各网路设备的接头不佳，接触不良，造成讯号衰减；
    • 由于网路设备所在环境恶劣 (例如过热) 导致的当机问题；
    • 各网路设备使用方法不良，造成设备功能衰减；

  3. 设备配置的规则：

    在各个设备的配置上是有一定的规则的，而最容易发生的问题就是太长的网路线会造成讯号的衰减， 导致网路连线的时间太长甚至无法连线。我们曾在网路基础当中谈过乙太网路最长的支援距离， 还有一些其他网路媒体配置的问题您必须晓得的：

    • 使用错误的网路线，最常发生在平行线与跳线的分别！
    • 架设的网路线过长，导致讯号衰减太严重。例如乙太网路 CAT5e 的线理论限制长度大概是在 90 公尺左右，若两个设备 (Hub/主机之间) 长度大于 90 公尺时，自然就容易出现讯号发生问题了！
    • 其他杂讯的干扰，最常发生在网路线或者网路设备旁边有太强的磁波；
    • 区域网路上面，节点或者其他的设备太多，过去我们常以所谓的 543 原则来说明：
      • 5个网段(segment)。所谓segment就在物理连接上最接近的一组电脑， 在一个BNC网段里面最多只能接30台电脑，且网线总长不能超过185m。
      • 4个增益器(repeater)。也就是将信号放大的装置。
      • 3个电脑群体(population)。这个不好理解，也就是说前面所说的5个segment之中， 只能有3个可以装电脑，其它两个不行。
上述是一些最常见的硬体问题，当然啦，有的时候是设备本身就有问题， 而我们在网路基础里面谈到的那个很重要的‘ 网路布线 ’的情况，也是造成网路停顿或通顺与否的重要原因呐！所以，硬体问题的判断比较困难点。 好～底下我们再来聊一聊软体设定的相关问题。

小标题的图示 软体问题
所谓的软体问题，绝大部分就是 IP 设定错误啊，路由不对啊，还有 DNS 的 IP 设定错误等等的， 这些问题都是属于软体设定啦！只要将设定改一改，利用一些侦测软体查一查， 就知道问题出在哪里了！基本的问题有：
  1. 网路卡的 IP 设定错误：
    例如：同一个 IP 在同一个网段中出现造成 IP 冲突、子遮罩网路设定错误、网路卡的驱动程式使用错误、 网路卡的 IRQ、 I/O Address 的设定冲突等等；

  2. 路由的问题 (route table)：
    最常见的就是预设路由 (default gateway) 设定错误了！或者是路由介面不符所导致的问题， 使得资料封包没有办法顺利的送出去。

  3. 通讯协定不相符：
    最常发生在不同的作业系统之间的通讯传输，例如早期 Windows 98 与 Windows 2000 之间的‘网芳’ 若要达成沟通，则 Windows 98 必须要加装 NetBEUI 这个通讯协定才行。又例如两部 Linux 主机要透过 NFS 通讯协定传输资料时，两边都得要支援 portmap 这个启动 RPC 协定的程式才行！ 这些通讯协定我们都会在后面的章节分别介绍的啦！

  4. 网路负荷的问题 (loading)：
    当同时有大量的资料封包涌进 Server 或者是 Hub 或者是同一个网域中， 就有可能造成网路的停顿甚至挂点！另外，如果区网内有人使用 BT (P2P 软体) 或者是有人中毒导致蠕虫充满整个区网，也会造成网路的停顿问题；

  5. 其他问题：
    例如：一些 port 被防火墙挡住了，造成无法执行某些网路资源；应用程式本身的 Bug 问题；应用程式中使用者的网路设定错误；以及不同的作业系统的相容性问题等等。
小标题的图示 问题的处理
既然问题发生了，就要去处理他啊！那如何处理呢？以上面的星形连线图示为例，把握两个原则：
  • 先由自身的环境侦测起，可以由自身 PC 上的网路卡查起，到网路线、到 Hub 再到 ATU-R 等等的硬体先检查完。在这个步骤当中，最好用的软体就是 ping ， 而你最好能有两部以上的主机来进行连线的测试；
  • 确定硬体没问题了，再来思考软体的设定问题！
实际上，如果网路不通时，你可以依序这样处理：
  1. 了解问题：这个问题是刚刚发生？还是因为之前我做了什么动作而导致无法连线？
  2. 确认 IP：先看看自己的网卡有无驱动？能否取得正确的 IP 来连线？
  3. 确认区网连线：利用 ping 来沟通两部主机，确定网路线与中继的 hub/switch 工作正常；
  4. 确认对外连线：看主机或 IP 分享器能否依据 连上 Internet 那一章的方法顺利取得 IP 参数，并以 ping 的方法确定对外连线是可以成功的；
  5. 确认 DNS 查询：利用 nslookup 或 host 或 dig 检查 www.google.com 看看；
  6. 确认 Internet 节点：可以利用 traceroute 检查各节点是否没问题？
  7. 确认对方伺服器正常服务：是否对方伺服器忙线中？或他的机器挂了？
  8. 确认我方伺服器：是否某些服务没有正确启动？可利用 netstat 检查， 是否某些安全机制的套件没有开放，例如 SELinux 这项机制；
  9. 防火墙或权限的问题：是否由于权限设定错误所致？ 是否由于您的机器有防火墙忘记启用可连线的埠口所致？这个可以透过 tcpdump 来处理！
透过这些处理动作后，一般来说，应该都可以解决您无法上网的问题了！ 当然啦，如果是硬体的问题，那么鸟哥也无法帮你，你可能最需要的是...... ‘送修吧孩子！’
大标题的图示 处理流程
既然知道上面已经谈到的几个小重点了，接下来当然是一个一个的给他处理掉啊！ 底下我们就得要一步一脚印的开始检查的流程啊！

小标题的图示 步骤一：网路卡工作确认
其实，网路一出问题的时候，您应该从自己可以检查的地方检查起，因此， 最重要的地方就是检查您的网路卡是否有工作的问题啦！检查网路卡是否正常工作的方法如下：
  1. 确定网路卡已经驱动成功：
    如果网路卡没有驱动成功，其他的，免谈！！所以你当然需要驱动你的网路卡才行！ 确认网路卡是否被驱动，可以利用 lspci 先看看有没有捉到 Ethernet 字样的显示资讯，再以 dmesg 来检查是否被核心侦测到，最后使用 lsmod 看看有没有相对应的模组已被载入。 整个步骤可以参考‘连上 Internet - Linux 网路卡’那一个小节， 这里鸟哥不再说明了！ ^_^！不过你要注意的是，如果上述的检测方式都无法发现你的网路卡模组， 那肯定就是核心与核心模组不支援你的网路卡啊！那该怎办？参考 ‘连上 Internet之网卡编译’就对了！

  2. 确定可以手动直接建立 IP 参数：
    在顺利的载入网路卡的模组，并且‘取得网路卡的代号’之后，我们可以利用 ifconfig 或 ip 来直接给予该网路卡一个网路位址试看看！ 看能否给予 IP 设定呢？例如：
    [root@linux ~]# ifconfig eth0 192.168.1.100
    来直接建立该网路卡的 IP ，然后直接输入 ifconfig 看能否查阅到刚刚设定好的参数即可。 如果可以建立起该 IP ，就以 ping 来检测看看：
    [root@linux ~]# ping 192.168.1.100
    如果有回应的话，那表示这个网卡的设定应该是没有问题了！ 再来则是开始检测一下区域网路内的各个连接硬体啦！
Tips:
事实上要再次的重申，如果您的主机捉不到您主机上的网路卡 (通常是内建的网路晶片)， 那么最好买一张便宜的螃蟹卡先来凑合着用，‘先求有！再求完美’， 不要一开始就挑战自己的耐心啊！拜托拜托！ 		鸟哥的图示
小标题的图示 步骤二：区域网路内各项连接设备检测
在确认完了最重要的网路卡设定之后，并且确定网路卡是正常的之后， 再接着下来则是区域网路内的网路连接情况了！假设您是按照 图一所设定的星形连线区域网路架构，那么你必须要知道整个‘网域’的概念！
  1. 关于网域的概念：
    你得清楚的知道图一中各主机与伺服器可以互相沟通是因为他们在‘同一个网域里面’， 所以，你要知道所谓的 192.168.1.0/24 这种网域的表达方式所代表的意义， 且子遮罩网路 (Netmask) 的意义也得了解。如果忘记了，请回去网路基础再翻一翻。

  2. 关于 Gateway 与 DNS 的设定：
    Gateway 与 DNS (在 /etc/sysconfig/network-scripts/ifcfg-eth0, /etc/resolv.conf 的设定) 最容易被搞混～ 这两个并非是填写你的 Linux 主机的 IP 喔！应该是要填写 IP 分享器 (或 NAT 主机) 的 IP 在 Gateway 中， 填写 168.95.1.1 在 DNS 的 IP 设定当中！不能够搞错啊！如果还是不清楚？回去网路基础看看吧！

  3. 关于 Windows 端的工作群组与电脑名称：
    假如您还需要资源分享，那么您就必须在 windows 系统中开放档案分享， 并且建议所有的电脑将‘工作群组’设定相同，但‘电脑名称’则不能相同！
假设你的区网内所有的主机 IP 都设定正确了，那么接下来你就可以使用 ping 来测试两部区网内主机的连线， 这个连线的动作可以让你测试两部主机间的各项设备，包括网路线、Hub/Switch 等等的咚咚！ 如果无法测试成功，那就请了解一下：
  1. IP 参数是否设定正确：
    再次强调，先决定 IP 是对的！鸟哥在上课的时候常常发现同学无法连到我的主机上， 一经使用 ifconfig 才发现他们与我的 IP 不在同一个网段内，就是会有这样的情况发生啊！唉～

  2. 连线的线材问题：
    包括我们前面提到的网路线本身折损、过度缠绕造成的讯号衰减问题等等， 另外，有些比较旧的 Hub/Switch 或者是 ATU-R (ADSL 数据机，俗称的小乌龟是也) 由于没有 Auto MDI/MDIX 的功能，所以无法自动的分辨跳线与否， 那么当你插错网路线的时候，也就无法接通啦！这样了解乎？另外，早期我们常常会说， 最简单判断每部主机是否顺利连接到 Hub/Switch 可以透过连接到 Switch 上的灯号来判断， 不过，由于有时候网路线本身讯号不良，虽然灯号还是会亮，不过就是无法连接到 Switch 的情况 (鸟哥自己就曾发生过啊！)，此时，跟朋友借一条 OK 的网路线来测试看看吧！

  3. 网卡或 Hub/Switch 本身出问题：
    有一次鸟哥无法在外部连接到鸟哥的主机，怀疑是挂点了，结果冲到主机所在办公室察看，咦！ 主机是好好的嘛！那怎么会无法连线呢？原因是.......室内环境通风不良，加上 Switch 所在处温度过高， 加上那部旧的 switch ‘刚好’风扇坏了，哈！就这样‘ switch 当机 ’ 在重新启动 switch (拔掉再插上电源线) 后就正常了。所以啰，很多情况都是会发生的， 而区域网路内的环境也很容易影响到连线品质啊！
确定自己主机的 IP 与网卡没有问题，加上内部区网透过 ping 也测试过没有问题， 接下来就是要‘取得可以对外连线的 IP 参数’啦！这个重要！

小标题的图示 步骤三：取得正确的 IP 参数
什么叫‘取得正确的 IP 参数’啊？还记得我们谈过如果要顺利的连接上 Internet 的话， 必须要可以跟 public IP 进行沟通才行，而与 public IP 取得沟通的方法，在台湾比较常见的有 ADSL, Cable modem, 学术网路, 电话拨接等等，在 CentOS 当中，我们可以透过修改 /etc/sysconfig/network-scripts/ifcfg-eth0，或者是利用 rp-pppoe 来进行拨接， 无论如何，你就是得要连接到某个 ISP 去就是了～在你确认所有的区网没有问题之后， 参考一下连上 Internet 那一章的介绍， 连上之后，立即以 ifconfig 看看有没有捉到正确的 IP 啊？ 在台湾如果使用 ADSL 连线的话，你应该可以顺利的取得一组正确的 Public IP 参数的！
Tips:
曾有国外的华人朋友来信说到，他们使用 ADSL 拨接之后竟然取得一组 Private IP ， 害他们没有办法架站！他们想请问这样的情况是否合理。如果您熟悉路由相关的概念之后， 当然会知道：‘这当然合理！’，因为你取得的 IP 只是为了要连接到 ISP 去而已， 而 ISP 与你的主机当然可以透过 Private IP 来连线啊！如果是这样的话，那么您就肯定无法架站了！ ^_^ 		鸟哥的图示
另外，最常发现无法顺利取得 IP 的错误就是‘BOOTPROTO’这个设定值设定错了！ 因为 static 与 hdcp 协定所产生的 IP 要求是不一样的啊！还记得吧！ 要特别留在 ifcfg-eth0 里面的设定参数喔！另外，如果你是使用 ADSL 拨接的， 但是老是无法拨接成功，那么建议你可以这样试看看：
  • 将 ADSL 的数据机 (ATU-R) 整个关机，将 Switch/Hub 也关掉电源；
  • 静待十分钟，等这些设备比较‘凉快’一点后，再重新插上电源；
  • 将 Linux 连接到 ADSL 的那块网卡 (假设为 eth0) 在 ifcfg-eth0 内，‘ONBOOT’设定为 no， 重新启动网路 (/etc/init.d/network restart)，然后再执行 adsl-start
  • 如果还是无法拨接成功，并且你已经确认内部网域没有问题，那请中华电信的工程人员来帮忙您处理吧！
因为很多时候都是由于网路媒体过热，也有可能主机内部的一些网路参数有点问题， 所以，干脆就不要启动网卡，让 adsl-start 自动去启动网卡即可！ 如果顺利取得 IP 后，却还是无法顺利连到 Internet 上面时，你觉得还有哪些地方需要处理的呢？

小标题的图示 步骤四：确认路由表的规则
如果你已经顺利取得正确的 IP 参数的话，那么接下来就是测试一下是否可以连上 Internet 啊！ 鸟哥建议你可以尝试使用 ping 来连连看 Hinet 的 DNS 主机，也就是 168.95.1.1 那部机器啦！
[root@linux ~]# ping -c 3 168.95.1.1
如果有回应，那就表示你的网路‘基本上已经没有问题，可以连到 Internet 了！’， 那如果没有回应呢？明明取得了正确的 IP 却无法连接到外部的主机，肯定有鬼！呵呵！没错！ 还记得我们在网域内资料的传输可以直接透过 MAC 来传送， 但如果不在区网内的资料，则需要透过路由，尤其是那个预设路由 (default route) 来帮忙转递封包吧！ 所以说，如果你的 public IP 无法连接到外部 (例如 168.95.1.1) ，可能的问题就出在路由与防火墙上面了。 假设你没有启动防火墙，那问题就缩小到剩下路由啰～

那路由的问题如何检查？就用 route -n 来检查啊！

例题：假设有个使用 ADSL 拨接的 Linux 主机，他的路由表如下，你觉得出了什么问题？
Destination     Gateway       Genmask         Flags Metric Ref    Use Iface
59.104.200.1    0.0.0.0       255.255.255.255 UH    0      0        0 ppp0
192.168.1.0     0.0.0.0       255.255.255.0   U     0      0        0 eth0
169.254.0.0     0.0.0.0       255.255.0.0     U     0      0        0 eth0
127.0.0.0       0.0.0.0       255.0.0.0       U     0      0        0 lo
0.0.0.0         192.168.1.2   0.0.0.0         UG    0      0        0 eth0
答：
    仔细看到上面的路由输出，第一条是 ppp0 产生的 public IP 介面，第二条是 eth0 的内部网域介面， 在看到最后一条的 0.0.0.0/0.0.0.0 这个预设路由，竟然是内部网域的 eth0 为 gateway ？ 这不合理，最大的问题应该是出在 ifcfg-eth0 里面不小心设定了‘GATEWAY=192.168.1.2’ 所致，解决的方法为：

    1. 取消 ifcfg-eth0 内 GATEWAY=192.168.1.2 那一行，(该行亦可能出现在 /etc/sysconfig/network 内)
    2. 重新启动网路 /etc/init.d/network restart
    3. 重新进行拨接： adsl-stop; adsl-start

另外一个可能发生的情况，就是：‘忘记设定预设路由’啦！ 例如使用 ifconfig 手动重新设定过网路卡的 IP 之后，其实路由规则是会被更新的， 所以预设路由可能就会不见了！那个时候你就得要利用 route add 来增加预设路由啰！

小标题的图示 步骤五：主机名称与 IP 查询的 DNS 错误
如果你发现可以 ping 到 168.95.1.1 这个 Internet 上面的主机，却无法使用浏览器在网址列浏览 http://www.google.com 的话，那肯定 99% 以上问题是来自于 DNS 解析的困扰！ 解决的方法就是直接到 /etc/resolv.conf 去看看设定值对不对啊！ 一般常见的内容是这样的：
[root@linux ~]# vi /etc/resolv.conf
nameserver 168.95.1.1
nameserver 139.175.10.20
最常见的错误是‘那个 nameserver 的拼字写错了！’真是最常见的问题～～另外，如果 client 端是 Windows 系统呢？常常初学者会搞错的地方就是在 windows 的设定了！要注意： Windows 端的 DNS 设定与主机端 /etc/resolv.conf 的内容相同即可！ 很多初学者都以为 TCP/IP 内的 DNS 主机是填上自己的 Linux 主机，这是不对的 (除非您自己的 Linux 上面有 DNS 服务) ！您只要填上您的 ISP 给您的 DNS 主机 IP 位置就可以了

小标题的图示 步骤六：Linux 的 NAT 伺服器或 IP 分享器出问题
NAT 伺服器最简单的功能就是 IP 分享器啦！NAT 主机一定是部路由器，所以你必须要在 Linux 上面观察好正确的路由资讯。否则肯定有问题。另外， NAT 主机上面的防火墙设定是否合理？ IP 分享器上面是否有设定抵挡的机制等等，都会影响到对外连线是否能够成功的问题点。 关于 NAT 与防火墙我们会在后续的章节继续介绍的啦！

小标题的图示 步骤七：Internet 的问题
Internet 也会出问题喔！当然啦～没有任何东西是不会出问题的！ 举例来说，好几年前台湾西岸因为施工的关系，导致南北网路骨干缆线被挖断， 结果导致整个 Internet 流量的大塞车！这就是 Internet 的问题～还有，数年前 Study Area 网站放置的地点由于路由器设定出了点差错， 结果导致连线速度的缓慢。这都不是主机本身出问题，而是 Internet 上面某个节点出了状况。 想要确认是否问题来自 Internet 的话，就使用 traceroute 吧！ 查察看问题是来自那个地方再说！

小标题的图示 步骤八：主机的问题
如果上述的处理都 OK ，却无法登入某部主机时，我想，最大的问题就是出现在主机的设定啦！ 这包括有：
  • 主机并没有开放该项服务：例如主机关闭了 telnet ，那你使用 telnet 去连线，是无法连接上的啦！
  • 主机的权限设定错误：例如你将某个目录设定为 drwx------ ，该目录拥有者为 root ， 你却将该目录开放给 WWW 来浏览，由于 WWW 无法进入该目录，所以当然无法正确的给用户端浏览啊！ 这是最典型的权限设定错误的情况啊！
  • 安全机制设定错误：例如 SELinux 是用来更细微控管主机存取的一种核心机制， 如果你没有设定好就启用的话，那么主机的服务很多都‘无法顺利的启用’， 关闭 SELinux 就好了。而其他例如 /etc/hosts.deny, PAM 模组等等， 都可能造成使用者无法登入的问题！这就不是网路问题，而是主机造成连线无法成功！
  • 防火墙问题：防火墙设定错误也是一个很常见的问题，你可以使用 tcpdump 来追踪封包的流向， 以顺利的了解防火墙是否设定错误。
基本上，一个网路环境的检测工作可不是三言两语就讲的完的～而且常常牵涉到很多经验的问题～ 请您常常到一些讲座的场合去听听看大家的经验，去 google 看看人家的解决方法， 都有助于让你更轻易的解决网路问题的喔！ ^_^
大标题的图示 课后练习
  • 以图一的星形连线为例，你的 Linux PC 3 可以 ping 到 Windows PC1 ，但是反过来， Windows PC1 无法 ping 到 Linux PC3，你觉得原因可能发生在哪里？
    由于两边已经可以用 ping 进行连线，所以硬体应该是没有问题了。 而 Linux --> Windows 没问题， Windows --> Linux 有问题，可能是由于 Linux 主机上面的防火墙所致。 可以使用 iptables -L -n 去查阅一下防火墙的设定规则。详细的防火墙请参考后续的章节。
2002/07/31：第一次完成日期！
2003/08/19：重新修订一些资料，与前面的章节比较好配合！
2006/08/04：将旧的文章移动到 此处
2002/07/31以来统计人数


鸟哥的 Linux 私房菜 -- 限制 Linux 对外的埠口 port limit

为取得较佳浏览结果，请爱用 firefox 浏览本网页

主机基本安全之一：限制 Linux 对外连线的埠口
切换解析度为 800x600
最近更新日期：2006/08/08
为什么我们的主机会回应网路上面的一些要求封包呢？例如我们设定了一部 WWW 主机后，当有来自 Internet 的 WWW 要求时，我们的主机就会予以回应，这是因为我们的主机有启用了 WWW 的监听埠口 (port) 啊！这里就要特别留意了，当我们启用了一个 daemon 时，就可能会造成主机的 Port 在进行 Listen 的动作，此时该 daemon 就是已经对网路上面提供服务了！万一这个 daemon 有漏洞，因为他提供 Internet 的服务，所以就容易被 Internet 上面的 cracker 所入侵了！所以说，仔细的检查自己系统上面的 port 到底开了多少个，并且予以严格的管理， 才能够降低被入侵的可能性啊！

1. Linux 的埠口 (port)
    1.1 什么是 port ？
    1.2 观察 port： netstat, nmap
 2. port 的启动与关闭
    2.1 stand alone 与 super daemon
    2.2 设定开机时启动服务
    2.3 安全性的考量
 3. 课后练习
4. 针对本文的建议：http://phorum.vbird.org/viewtopic.htm?p=112964
大标题的图示 Linux 的埠口 (port)
我们在网路基础的通讯协定那个小节曾经谈到 TCP 封包表头最重要的就是来源与目标的埠口 (port) 了，若再加上来源与目标的 IP 就可成为一组 Socket pair ，这个 port 就是用在网路连线时提供连线接口的咚咚啰，在开始这一节之前，请您先前往网路基础那一章再瞧一瞧先。 除了这个之外，还有没有其他需要注意的事项呢？底下我们就来谈一谈先！

小标题的图示 什么是 port
你或许常常会在网路上听说‘我的主机开了多少的 port ，会不会被入侵呀？’ 或者是说‘开那个 port 会比较安全？又，我的服务应该对应什么 port 呀？’呵呵！很神奇吧！怎么一部主机上面有这么多的奇怪的 port 呢？

其实也不怎么难啦！在网路基础里面我们曾经介绍过很多的网路概念， 所以你会知道要达成一条 server/client 的连线，需要一组 Socket pair 来建立连线， 这也就是说，网路连线是‘双向’的。 此外，既然我们想要连线到主机端，那么主机势必得要启动一个大家都知道的 port 在‘监听’吧， 否则如何达成连线呢？您说是吧！另外， client 端是否要启用固定的 port 来连线？ 当然不需要啊～那共有多少 port 呢？底下我们就先来谈一谈。
  • 主机端的监听 (Listen)：
    想一想，你要如何连上 Yahoo 的网站去看新闻？首先当然是要打开浏览器，然后输入 Yahoo 的网址，之后我们的浏览器就会连接到 Yahoo 的 WWW 网站去要求资料了。既然如此的话，那么那部 Yahoo 的 WWW 主机当然就得要启动 WWW 的服务啦， 然后我们的浏览器才能够连接到该服务。这也就是说‘主机所启用的 port 其实是由某些网路服务 (program) 所启动的’。而为了连接上的方便，因此很多服务所开启的 port 是固定的，例如 WWW 开启在 port 80 ，mail 开启在 port 25 等等；

  • 用户端的 port：
    用户端启动的 port 是随机产生的， 主要是开启在大于 1024 以上的埠口，这个 port 也是由某些软体所产生的，例如上面提到的例子， 我们的浏览器想要连接到 Yahoo 的 WWW 主机，那么浏览器就得要启用一个 port 来与主机进行连线， 以组成一组 Socket pair 来传输资料嘛！
所谓的‘监听’是某个服务程式会一直常驻在记忆体当中，所以该程式启动的 port 就会一直存在。 至于 port 在传输过程中的判断，那就由 TCP/UDP 等通讯协定的表头资料来记录的啊， 我们的主机透过分析 TCP/UDP 的表头资料就能够了解到该连线所需要连接的软体是那个， 而给予正确的资料回应。所以，一部主机上面当然可以同时启动很多不同的服务啊！ ^_^。

还有上面提到的一些重点你也得再了解一下，那就是：
  • 共 65536 个 port：
    预设的情况下，我们的主机会有 65536 个 port，而这些 port 又分成两个部分，以 port 1024 作区隔：

  • 只有 root 才能启动的保留的 port：
    在小于 1023 (连同 1023) 的埠口，都是需要以 root 的身份才能启动的， 这些 port 主要是用于一些常见的通讯服务，在 Linux 系统下，常见的协定与 port 的对应是记录在 /etc/services 里面的。 一般来说，这些 port 最好保留给一些预设的服务来使用，不要自己随意使用到这些 port， 因为这些 port 是目前 Internet 上面所惯用的，所以一些程式开发者在进行软体的开发时， 就能够针对这些 well know 的埠口直接来开发，大家也比较容易使用伺服器的功能啊！

  • 大于 1024 用于 client 端的 port：
    在大于 1024 以上的 port 主要是作为 client 端的软体启动的 port 。这些 port 几乎都是依序随机使用的， 例如前面谈到的浏览器，就是使用大于 1024 以上的 port。那如果用到 port 65535 后， 系统会主动再由前面没有使用到的埠口 (如 1024) 再重新依序使用。

  • 是否需要三向交握：
    建立可靠的连线服务需要使用到 TCP 协定，也就需要所谓的 三向交握了， 如果是非可靠的连线服务，例如 DNS ，那只要使用 UDP 协定即可。

  • 通讯协定启用在非正规的 port：
    我们知道浏览器预设会连接到 WWW 主机的 port 80，那么你的 WWW 是否可以启动在非 80 的其他埠口？ 当然可以啊！你可以透过 WWW 软体的设定功能将该软体使用的 port 启动在非正规的埠口， 只是如此一来，您的用户端要连接到你的主机时，就得要在浏览器的地方额外指定你所启用的非正规的埠口才行。 这个启动在非正规的埠口功能，常常被用在一些所谓的地下网站啦！^_^。另外， 某些软体预设就启动在大于 1024 以上的埠口，如 MySQL 资料库软体就启动在 3306。

  • 所谓的 port 的安全性：
    事实上，没有所谓的 port 的安全性！因为‘Port 的启用是由服务软体所造成的’， 也就是说，真正影响网路安全的并不是 port ，而是启动 port 的那个软体 (程式)！ 或许你偶而会听到：‘没有修补过漏洞的 bind 8.x 版，很容易被黑客所入侵，请尽快升级到 bind 9.x 以后版本’，所以啰，对安全真正有危害的是‘某些不安全的服务’ 而不是‘开了哪些 port ’才是！因此，没有必要的服务就将他关闭吧！ 尤其某些网路服务还会启动一些 port 哩！另外，那些已启动的软体也需要持续的保持更新喔！
小标题的图示 观察 port
好了，我们现在知道这个 port 是什么鬼东西了，再来就是要去‘看他到底在干啥？’没错！ 再来就是要来了解一下，我们的主机到底是开了多少的 port 呢？如同我们前面说的， 您得要先了解一下，我们的‘服务’跟‘ port ’对应的档案是哪一个？再提醒一次呦！是‘ /etc/services ’啦！ 而常用来观察 port 的则有底下两个程式：
  • netstat：在本机上面以自己的程式监测自己的 port；
  • nmap：透过网路的侦测软体辅助，可侦测非本机上的其他网路主机，但有违法之虞。
见他的大头王！怎么使用 nmap 会违法？呵呵！由于 nmap 的功能太强大了，所以很多 cracker (怪客，网路上面的闲人) 会直接以他来侦测别人的主机，这个时候就可能造成违法啦！ 只要您使用 nmap 的时候不要去侦测别人的电脑主机，那么就不会有问题啦！ 底下我们分别来说一说这两个宝贝吧！

  • netstat
    在做为主机的 Linux 系统中，开启的网路服务越少越好！ 因为较少的服务可以较容易除错 (debug) 与了解安全漏洞，并可避免不必要的入侵管道！ 所以，这个时候请了解一下您的系统当中有没有哪些服务被开启了呢？ 要了解自己的系统当中的服务项目，最简便的方法就是使用 netstat 了！这个东西不但简单 (每一部 Linux 机器当中预设都会安装的程式喔！) ，而且功能也是很不错的。 这个指令的使用方法在 Linux 常用网路功能指令介绍当中提过了， 底下我们仅提供如何使用这个工具的方法啰！

    列出在监听的网路服务：
    列出网路服务的方式简单，如下所示：
    [root@linux ~]# netstat -tunl
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address       Foreign Address     State
tcp        0      0 0.0.0.0:25          0.0.0.0:*           LISTEN
tcp        0      0 :::80               :::*                LISTEN
tcp        0      0 :::22               :::*                LISTEN
tcp        0      0 :::25               :::*                LISTEN
    上面说明了我的主机有启动 port 25, 80, 22 等，而且观察各连线介面，可发现这三个 port 都有对外提供连线的能力喔！

    列出已连线的网路连线状态：
    如果仅是要列出网路介面上已经连线的或者是一些连线过程挂断、连接程序的网路状态， 可以使用如下的方式来处理：
    [root@linux ~]# netstat -tun
Active Internet connections (w/o servers)
Proto Recv-Q Send-Q Local Address        Foreign Address      State
tcp        0      0 192.168.10.100:25    192.168.10.5:3151    TIME_WAIT
tcp        0      0 192.168.10.100:22    192.168.10.150:1832  ESTABLISHED
    从上面的资料来看，我的主机 (192.168.10.100) 目前仅有一条已建立的连线， 那就是与 192.168.10.150 那部主机连接的连线，并且连线方线是由对方连接到我主机的 port 22 来取用我主机的服务呐！至于那个 TIME_WAIT 则是在等待该连线挂断啦！

    删除已建立或在监听当中的连线：
    如果想要将已经建立，或者是正在监听当中的网路服务关闭的话，最简单的方法当然就是找出该连线的 PID， 然后将他 kill 掉即可啊！例如下面的范例：
    [root@linux ~]# netstat -tunp
Active Internet connections (w/o servers)
Proto Recv-Q Send-Q Local Address     Foreign Address      State       PID/P name
tcp        0     68 192.168.10.100:22 192.168.10.150:1832  ESTABLISHED 13247/sshd
    如上面的范例，我们可以找出来该连线是由 sshd 这个程式来启用的，并且他的 PID 是 13247， 希望你不要心急的用 killall 这个指令，否则容易删错人 (因为你的主机里面可能会有多个 sshd 存在)， 应该要使用 kill 这个指令才对喔！
    [root@linux ~]# kill -9 13247
  • nmap
    如果你要侦测的设备并没有自己的作业系统，举例来说，你想要了解一下公司的网路印表机是否有开放某些协定时， 那该如何处理啊？现在你知道 netstat 可以用来查阅本机上面的许多监听中的通讯协定， 那例如网路印表机这样的非本机的设备，要如何查询啊？呵呵！用 nmap 就对了！

    nmap 的套件说明之名称为：‘Network exploration tool and security scanner’，顾名思义， 这个东西是被系统管理员用来管理系统安全性查核的工具！他的具体描述当中也提到了， nmap 可以经由程式内部自行定义的几个 port 对应的指纹资料，来查出该 port 的服务为何，所以我们也可以藉此了解我们主机的 port 到底是干嘛用的！如果您是安装 Linux 是 Red Hat 系统的话，那么这个 nmap 套件应该已经安装妥当了，万一没有这个套件的话，也可以来到底下的网站下载：
    • http://insecure.org/nmap/
    [root@linux ~]# nmap [扫瞄类型] [扫瞄参数] [hosts 位址与范围]
参数：
[扫瞄类型]：主要的扫瞄类型有底下几种：
    -sT：扫瞄 TCP 封包已建立的连线 connect() ！
    -sS：扫瞄 TCP 封包带有 SYN 标签的资料
    -sP：以 ping 的方式进行扫瞄
    -sU：以 UDP 的封包格式进行扫瞄
    -sO：以 IP 的协定 ( protocol ) 进行主机的扫瞄
[扫瞄参数]：主要的扫瞄参数有几种：
    -PT：使用 TCP 里头的 ping 的方式来进行扫瞄，可以获知目前有几部电脑存活(较常用)
    -PI：使用实际的 ping (带有 ICMP 封包的) 来进行扫瞄
    -p ：这个是 port range ，例如 1024-, 80-1023, 30000-60000 等等的使用方式
[Hosts 位址与范围]：这个有趣多了，有几种类似的类型
    192.168.0.100  ：直接写入 HOST IP 而已，仅检查一部；
    192.168.0.0/24 ：为 C Class 的型态，
    192.168.*.*　　：嘿嘿！则变为 B Class 的型态了！扫瞄的范围变广了！
    192.168.0.0-50,60-100,103,200 ：这种是变形的主机范围啦！很好用吧！

范例一：使用预设参数扫瞄本机所启用的 port
[root@linux ~]# nmap localhost
PORT     STATE SERVICE
22/tcp   open  ssh
25/tcp   open  smtp
80/tcp   open  http
139/tcp  open  netbios-ssn
# 在预设的情况下， nmap 仅会扫瞄 TCP 的协定喔！
    nmap 的用法很简单呐！就直接在指令后面接上 IP 或者是主机名称即可。不过，在预设的情况下 nmap 仅会帮你分析 TCP 这个通讯协定而已，像上面这个例子，他只会帮我列出 4 个已经开启的 TCP 的埠口号码， 但优点是顺道也将开启该埠口的服务也列出来了，真是好！ ^_^！那如果想要同时分析 TCP/UDP 这两个常见的通讯协定呢？可以这样做：
    [root@linux ~]# nmap -sTU localhost
PORT      STATE         SERVICE
22/tcp    open          ssh
25/tcp    open          smtp
80/tcp    open          http
137/udp   open|filtered netbios-ns
138/udp   open|filtered netbios-dgm
139/tcp   open          netbios-ssn
    嘿嘿！与前面的范例比较一下，你会发现这次多了两个 UDP 的埠口，分别是 137 与 138 ， 这样分析好多了吧！然后，如果你想要了解一下到底有几部主机活在你的网路当中时， 则可以这样做：
    [root@linux ~]# nmap -sP 192.168.10.0/24
Host 192.168.10.171 appears to be up.
MAC Address: 00:01:E6:B3:AA:CC (Hewlett-Packard Company)
Host 192.168.10.174 appears to be up.
MAC Address: 00:04:75:FF:CC:DD (3 Com)
Host 192.168.10.175 appears to be up.
MAC Address: 00:0C:6E:BA:11:22 (Asustek Computer)
    看到否？你的环境当中有三部主机活着呐！并且该 IP 所对应的 MAC 也会被记录下来， 很不错吧！如果你还想要将各个主机的启动的 port 作一番侦测的话，那就得要使用：
    [root@linux ~]# nmap 192.168.10.0/24
    之后你就会看到一堆 port number 被输出到荧幕上啰～如果想要随时记录整个网段的主机是否不小心开放了某些服务， 嘿嘿！利用 nmap 配合资料流重导向 (>, >> 等) 来输出成为档案， 那随时可以掌握住您区域网路内每部主机的服务启动状况啊！ ^_^

    请特别留意，这个 nmap 的功能相当的强大，也是因为如此， 所以很多刚在练习的黑客会使用这个软体来侦测别人的电脑，这个时候请您特别留意， 目前很多的人已经都有‘特别的方式’来进行登录的工作！例如以 TCP_Wrappers (/etc/hosts.allow, /etc/hosts.deny) 的功能来记录曾经侦测过该 port 的 IP！ 这个软体用来‘侦测自己机器的安全性’是很不错的一个工具，但是如果用来侦测别人的主机， 可是会‘吃上官司’的！特别留意！！
    • 大标题的图示 Port 的启动与关闭
    现在你知道其实 port 是由某些程式所启动的，所以要关闭某些 port 时，那就直接将某个程式给他关闭就是了！ 那关闭的方法你当然可以使用 kill ，不过，毕竟不是正统的解决之道，因为 kill 这个指令通常具有强制关闭某些程式的功能，但我们想要正常的关闭该程式啊！ 所以，就利用系统给我们的 script 来关闭就好了啊。 在此同时，我们就得再来稍微复习一下，一般传统的服务有哪几种类型？

    小标题的图示 stand alone 与 super daemon
    我们在鸟哥的 Linux 私房菜 -- 基础学习篇内谈到， 在一般正常的 Linux 系统环境下，服务的启动与管理主要有两种方式：
    • stand alone
      顾名思义，stand alone 就是直接执行该服务的执行档，让该执行档直接载入到记忆体当中运作， 用这种方式来启动可以让该服务具有较快速回应的优点。一般来说，这种服务的启动 script 都会放置到 /etc/init.d/ 这个目录底下，所以你通常可以使用：‘ /etc/init.d/sshd restart ’之类的方式来启动这种服务；

    • Super daemon
      用一个超级服务作为总管，以管理一些网路服务。在 CentOS 4.x 里面使用的则是 xinetd 这个 super daemon 啊！这种方式启动的网路服务虽然在回应上速度会比较慢， 不过，可以透过 super daemon 额外提供一些控管，例如控制何时启动、何时可以进行连线、 那个 IP 可以连进来、是否允许同时连线等等。通常设定档放置在 /etc/xinetd.d/ 当中，但设定完毕后需要重新以‘ /etc/init.d/xinetd restart ’重新来启动才行！
    关于更详细的服务说明，请参考基础篇的 认识服务 一文， 鸟哥在这里不再赘述。好，那么如果我想要将我系统上面的 port 25 关掉的话， 那应该如何关闭呢？最简单的作法就是先找出那个 port 25 的启动程式喔！
    [root@linux ~]# netstat -tnlp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State   PID/Program name
tcp        0      0 127.0.0.1:25  0.0.0.0:*       LISTEN  2030/master
tcp        0      0 :::22         :::*            LISTEN  1961/sshd
# 咦！怎么会是 master 这个玩意儿？用 which 这个指令还找不到这个 master
# 那怎办？没关系，我们可以透过 locate 配合正规表示法找到这个指令的！

[root@linux ~]# locate master | grep '/master$'
/usr/libexec/postfix/master
# 嘿嘿！那个正规表示法就可以找到上述的输出结果，然后再由 rpm 来处理！

[root@linux ~]# rpm -qf /usr/libexec/postfix/master
postfix-2.2.2-2
# 找到了！就是这个套件！所以将他关闭的方法可能就是：

[root@linux ~]# rpm -qc postfix | grep init
/etc/rc.d/init.d/postfix
[root@linux ~]# /etc/init.d/postfix stop
    透过上面的这个分析的流程，你可以利用系统提供的很多方便的工具来达成某个服务的关闭！ 为啥这么麻烦？不是利用 kill -9 2030 就可以删掉该服务了吗？ 是没错啦！不过，你知道该服务是做啥用的吗？你知道将他关闭之后，你的系统会出什么问题吗？ 如果不知道的话，那么利用上面的流程不就可以找出该服务套件，再利用 rpm 查询功能， 不就能够知道该服务的作用了？所以说，这个方式还是对您会有帮助的啦！ 底下请您试着将您 CentOS 或者是其他版本的 Linux 的 Telnet 打开试看看。

    例题：我们知道系统的 Telnet 服务通常是以 super daemon 来控管的，请您启动您系统的 telnet 试看看。

    答：
    1. 要启动 telnet 首先必须要已经安装了 telnet 的伺服器才行，所以请先以 rpm 查询看看是否有安装 telnet-server 呢？ ‘rpm -qa | grep telnet-server’如果没有安装的话，请利用原版光碟来安装，或者使用‘yum install telnet-server’ 安装一下先；
    2. 由于是 super daemon 控管，所以请编辑 /etc/xinetd.d/telnet 这个档案，将其中的‘disable = yes’改成 ‘disable = no’之后以‘/etc/init.d/xinetd restart’重新启动 super daemon 吧！
    3. 利用 netstat -tnlp 察看是否有启动 port 23 呢？

    小标题的图示 设定开机时启动服务
    如果刚刚你已经利用类似前一节的方法将一些服务关闭了，但是下次再重新开机后，咦！ 怎么那些被关闭的服务又‘春风吹又生’的给他‘长’出来了？呵呵～没错啊， 因为前一节的作法是可以立即将某个服务关闭，但是却不会影响到开机时是否会启动与否的设定。 唉～伤脑筋～

    如果你想要在开机的时候就启动或不启动某项服务时，那就得要了解一下 基础学习篇里面谈到的开机流程管理 的内容啦！ 在 Unix like 的系统当中我们都是透过 run level 来设定某些执行等级需要启动的服务， 以 Red Hat 系统来说，这些 run level 启动的资料都是放置在 /etc/rc.d/rc[0-6].d/ 里面的，那如何管理该目录下的 script 呢？ 手动处理吗？会疯掉的呐！所以你必须要熟悉 chkconfig 或 Red Hat 系统的 ntsysv 这几个指令才行！
    Tips:
    这几个指令不熟吗？这个时候鸟哥不得不说了：‘有 man 堪用直需用，莫待无 man 空自猜’赶紧给他 man 下去啦！     		鸟哥的图示
    例题：(1)如何查阅 portmap 这个程式一开机就执行？ (2)如果开机就执行，如何将他改为开机时不要启动？ (3)如何立即关闭这个 portmap 服务？

    答：
    1. 可以透过‘ chkconfig --list | grep portmap ’与‘ runlevel ’确认一下你的环境与 portmap 是否启动？
    2. 如果有启动，可透过‘ chkconfig --level 35 portmap off ’来设定开机时不要启动；
    3. 可以透过‘ /etc/init.d/portmap stop ’来立即关闭他！

    聪明的你一定会问说：‘鸟哥，你的意思是只要将系统所有的服务都关闭，那系统就会安全啰？’ 当然....不是！因为‘很多的系统服务是必须要存在的，否则系统将会出问题’ 举例来说，那个保持系统可以具有工作排程的 crond 服务就一定要存在，而那个记录系统状况的 syslogd 也当然要存在～否则怎知道系统出了啥问题？ 底下鸟哥列出几个常见的必须要存在的系统服务给大家参考参考先！这些服务请不要关闭啊！

    服务名称 | 服务内容
acpid | 新版的电源管理模组，通常建议开启，不过，某些笔记型电脑可能不支援此项服务，那就得关闭
atd | 在管理单一预约命令执行的服务，应该要启动的
crond | 在管理工作排程的重要服务，请务必要启动啊！
iptables | Linux 内建的防火墙软体，这个也可以启动啦！
keytables | 如果你的键盘非正规的格式时，这个服务的启动或许可以帮助你喔！
network | 这个重要了吧？要网路就要有他啊！
sshd | 这是系统预设会启动的，可以让你在远端以文字型态的终端机登入喔！
syslog | 系统的登录档记录，很重要的，务必启动啊！
xinetd | 就是那个 super daemon 嘛！所以也要启动啦！
xfs | 用来管理 X Window 字形资料的服务，如果你会需要 X Window 时，这个服务要启动。

    没错！不要怀疑！只要这些就可以啦！这几个服务是必须要启动的！ 至于其他服务则都先不用启动！例如 sendmail 啦！其他林林总总的资料，都先摆着！ 我们会在后续的章节当中提到如何启动这些服务的啦！

    小标题的图示 安全性的考量
    我们的 Linux distribution 很好心的帮使用者想到很多了，所以在一安装完毕之后， 系统会开启一堆有的没有的网路服务，例如那个 portmap 之类的咚咚，以及网路印表机的 cups 服务等等， 这些东西你或许知道或许不知道，不过他就是有开启～但我们的主机明明就是用来做为伺服器的， 所以这些本来预计要给 client 使用的服务其实有点‘多此一举’的感觉～ 所以啦，请你将他关闭吧！就利用 ntsysv 或 chkconfig 来关闭他！ 只留下前一节咱们建议的那些服务就好了～其他的以后再说啊！

    不过要记得， ntsysv 及 chkconfig 都是在管理开机是否启动某些服务的 script 而已， 所以使用 chkconfig 管理完毕后，请记得最好使用 reboot 来完整的重新载入这些服务， 然后以‘ netstat -tunpl ’来看看是否有什么其他的网路服务在启动啊？ 如果有的话，在一样一样的将他关闭吧！ ^_^
    大标题的图示 课后练习
    • 如何观察您 Linux 主机上面已经有多少 port 被打开了？
      • 1. 如果是 Linux 这个作业系统上面的话，可以利用‘ netstat -tunlp ’观察已经在监听的 port 与服务的对应；
      2. 如果是想要查阅所有的 port (包含已建立的连线)，可以使用‘ netstat -tunp ’来查阅；
      3. 如果不在 Linux 本机上，可以用‘ nmap IP ’来处理啊！
    • 如何观察程序？
      • 利用‘ ps -aux ’或‘ top ’都可以，另外，‘ pstree -p ’则可以了解所有的程序相依性，而‘ lsof ’ 则可以察看所有程序所开的档案喔！
    • 请问 LISTEN 的 port 与 daemon 的关系为何？
      • 正在 LISTEN 当中的埠口均是由某些服务(daemons)所启动的，所以要启动埠口就得启用某个服务， 要了解某个埠口是由那个 daemon 所启动的，就利用 netstat -tulp 来查阅。
    • 请问 stand alone 与 super daemon 各是什么？
      • Linux 系统的服务有独立启动(stand alone)及超级服务员(super daemon)两种启动的方式。挂在 super daemon 底下的服务可以经由 super daemon 的控管，以加强一些安全功能，不过由于还要经过 super daemon 的管理，所以服务的连接速度上会比 stand alone 慢一点。
    • 请问您的 Linux 主机 (不论是那个 distributions ) 有关 daemon 启动与关闭的 scripts 与档案放置在那个目录下？
      • 各个 daemons 的启动与关闭的 scripts 是放置在 /etc/init.d/ 内， Red Hat 系统则是放到 /etc/rc.d/init.d 里面，至于 super daemon 的控管参数档案则在 /etc/xinetd.d 里面！
    • 为什么阻断式服务 (DDoS) 会造成系统的当机与网路瘫痪？试由三向交握的角度来探讨。
      • 所谓的阻断式服务是利用三向交握程序的漏洞，多个 cient 端持续发送 tcp 封包的连线要求， 但却不理会 server 端的 SYN/ACK 的封包，导致 server 端会持续启动很多的 port 在等待 client 端的回应， 那我们知道一般 port 有 65536 个，万一用完了，那系统网路就瘫痪了！所以 DDoS 会造成系统网路瘫痪的问题。 另外，由于多个 client 同时要求，所以网路频宽也会被用光！
    2002/08/02：首次完成释出
    2003/08/21：重新编辑，并且加入课后练习。
    2003/09/19：加入参考用解答了。
    2006/08/08：将旧的文章移动到 此处
    2002/08/02以来统计人数


鸟哥的 Linux 私房菜 -- Linux 的网路线上升级

为取得较佳浏览结果，请爱用 firefox 浏览本网页

主机基本安全之二： Linux 线上自动升级
切换解析度为 800x600
最近更新日期：2006/09/10
在现在的 Internet 上面，Cracker 实在是太多了！这些 Cracker 会利用已经存在的系统漏洞，来进行侦测、入侵您的主机， 因此，除了未来架设防火墙之外，最重要的 Linux 日常管理工作，莫过于套件的升级了！ 不过，经由每日观察网路安全通报所告知的套件漏洞，以及等待各大 distribution 针对这些漏洞来提供 RPM 档案，以使 Client 来升级的过程中，实在是有点缓慢啊！因此， 目前就有很多线上直接更新的机制出现了！有了这些线上直接更新 RPM 的手段与方法，我们系统管理员在管理主机系统上面，可就轻松的多啰！赶紧来看看吧！

1. 为何需要进行软体升级
    1.1 如何进行软体升级
    1.2 各种 distributions 的自动升级机制
 2. CentOS 的 yum 自动升级
    2.1 yum 的设定档
    2.2 yum 的安装、升级、移除、查询等功能与安装套件群组
    2.3 不同版本间的升级： CentOS 4.2 to 4.3, FC1 to CentOS 4.3
 3. Debian 的 apt 自动升级：以 B2D 为例
    3.1 APT 的设定档
    3.2 实际使用 APT： apt-get, apt-cache
 4. 重点回顾
5. 课后练习
6. 参考资料
7. 针对本文的建议：http://phorum.vbird.org/viewtopic.htm?t=26298
大标题的图示 为何需要进行软体升级
很多朋友在网路上面常常会这样留言： ‘大家好，我的 Linux 好像怪怪的，因为没有办法以 root 的身份登入了’， 呵呵！几乎可以直接告诉这位朋友：‘你的系统被入侵了’！嗄～真假？早上才装好，下午被入侵？ 没错啊～但～对方是如何办到的呢？

在前一章我们不是有提到‘网路连线的 port 其实是由软体所开启的’， 所以，如果该软体本身就有问题的话，那么当然你的系统就容易被攻破了！ 咦！那自由软体干嘛开发出有问题的程式啊？这是因为程式是人写出来的， 在设计之初有些奇怪的用法可能没有考虑到，或者是某些安全问题没有考虑到， 而造成程式的疏失。当这样的程式发布后，很多人会针对这些程式进行检验，如果发现问题就会回报给社群。 那么当回报后直到程式更新之前，总会有一段空窗期，这期间可能就会有些 cracker 开发出具有攻击码的程式， 如果这些攻击程式散布出来的话，那么随便一个小朋友拿到这样的程式，就能攻击你啦！

这个问题并非仅存在于某个单一作业系统，而是所有的作业系统都存在这样的问题， 而且套件的漏洞倒不是一定是会被利用来进行入侵，有的时候，某些套件的漏洞可能导致您 Linux 主机的运行不良或者是容易产生系统当机等等的问题呢！所以，一个好的 Linux 主机， 他的套件最好是随时保持在较新的版本上面，这样还是比较好一点的啦！关于安全漏洞的通报您可以参考底下的网站：
  • 台湾电脑危机处理小组(TWCERT)：http://www.cert.org.tw/
  • Red Hat 的官方说明：http://www.redhat.com/apps/support/errata/
所以啊，并不是有防火墙就万事 OK ！你还必须要更新你的软体才行， 通常建议你，安装 Linux 完毕后的第一项工作那就是..... 立刻进行整体软体的升级！
Tips:
事实上，自由软体的安全性还是比较好的！因为有太多人帮忙检验程式码与更新程式码， 并且，万一程式真的有问题，在发现问题到推出修补程式的期间是比较短的， 也就是说，攻击者可以利用的时间相对缩短，当然使用自由软体的我们就比较安全啦！ ^_^ 		鸟哥的图示
小标题的图示 如何进行软体升级
还记得你是如何安装你 Linux 上面的软体吗？不就是 rpm, tarball 与 dpkg 吗？ 所以啰，你的软体如果想要升级，那就得依据当时你安装该软体的方式来进行升级啊！ 而每种方式都有其适用性：
  • RPM：这是目前最常见于 Linux distribution 当中的套件安装管理方式， 包括 CentOS / Fedora / SuSE / Red Hat / Mandriva 等等，都是使用这个方式来管理的；

  • Tarball：利用软体的官方网站所释出的原始码在您的系统上面编译与安装， 一般来说，由于软体是直接在自己的机器上面编译的，所以效能会比较好一些。 不过，升级的时候就比较麻烦，因为又得要下载新的原始码并且重新编译一次。 这种安装模式常见于某些特殊软体 (没有包含在 distribution 当中)，或者是 Gentoo 这个强调效能的 distribution；

  • dpkg：是 debian 这个 distribution 所使用的套件管理方式，与 RPM 很类似，都是透过预先编译的处理，可以让 end user 直接使用来升级与安装。
举例来说，如果你的系统是 CentOS ，我们知道他使用的是 RPM 类型的套件管理模式，那如果你想要安装 B2D 的软体怎办？要注意， B2D 是使用 debian 的 dpkg 来管理套件的，两者并不相同啊！要互相安装太难了！ 所以说，要升级的话，得先了解到你系统上的套件安装与管理的方法才行。

不过，有个特殊案例，那就是旧版本的 Linux (例如 Red Hat 9) 的软体升级该如何是好？ 由于旧版本的软体支援度本来就比较差，商业公司或者是社群也没有这么多心力放在旧版本的支援上， 所以，你这个时候可以选择： (1)升级到较新的版本，例如 CentOS 4.3 或者是 SuSE 10 等等，或者是 (2)利用 Tarball 来自行升级核心与软体 。不过，比较建议升级到新版本啦，因为要自行以手动方式由 Tarball 安装到最新的版本，实在是很费时费力，而且还得要常常查阅官方网站所推出的最新消息， 漏过一则都可能发生无法预期的状况。

但不管怎么说，单纯使用 RPM / Tarball / dpkg 的方式来安装与升级软体时， 你都必须要由原版光碟或者是由官方网站下载可安装的套件档案，然后再手动来实际安装到你的系统上。 如此一来，你还是得要盯着官方网站提供的资讯，才能够在第一时间进行升级的动作。 唉！怎么这么麻烦？

我们都晓得在 Windows 的环境下，他有提供一个 Live update 的项目可以自动的线上升级， 甚至很多的防毒软体与防木马软体也都有推出即时的线上更新，如此一来可以让您的软体维持在最新版的状况， 真是好啊！咦！那我们的 Linux 是否有这样的功能？如果有的话，那么系统自动进行软体升级， 不就可以轻松又快乐了？没错！确实是这样的！所以就让我们来谈一谈 Linux 的线上升级机制吧！

小标题的图示 各种 distributions 的自动升级机制
在 Linux 最常见的套件安装方式： RPM / Tarball / dpkg 当中，Tarball 由于取得的是原始码， 所以要用 Tarball 来作线上自动更新是不太可能进行的，所以仅能用 RPM 或 dpkg 这两种套件管理的方式来进行线上更新了。

但 RPM 与 dpkg 不是有所谓的相依属性吗？ 这倒不需要担心呐！因为我们的 RPM 与 dpkg 套件档案都有一些套件的基本资讯， 并同时记录了套件的相依属性 (记得使用 rpm -q 的查询吗)， 所以当分析这些基本资讯并使用一些机制将这些相依资讯记录下来后， 再透过一些额外的网路功能，就能够自动的分析你的系统与修补套件之间的差异， 并可进一步帮你分析所需要升级与相依属性的套件，就可达成自动升级的理想啦！

由于各家 distributions 在管理系统上都有自己独特的想法，所以在分析 RPM 或 dpkg 套件与方式上面就有所不同， 也就有底下这些不同的线上升级机制啦：
  • yum：
    CentOS 与 Fedora 所常用的自动升级机制，透过 FTP 或 WWW 来进行线上升级以及线上直接安装套件；

  • up2date：
    这是 Red Hat 所使用的自动升级机制，需要注册才能使用，并且依据付费与否而管制其流量；

  • apt：
    最早由 debian 这个 distribution 所发展，现在 B2D 也是使用 apt ，同时由于 apt 的可移植性， 所以只要你的 RPM 可以使用 apt 来管理的话，就可以自行建立 apt 伺服器来提供其他使用者进行线上安装与升级。

  • you：
    所谓的 Yast Online Update (YOU) 是由 SuSE 所自行开发出来的线上安装升级方式， 经过注册取得一组帐号密码后，就能够使用 you 的机制来进行线上升级。不过如果是免费的版本， 则仅有 60 天的试用期！

  • urpmi：
    这个则是 Mandriva 所提供的线上升级机制！
讲了这些升级机制并且与 distribution 作了对应，你就该了解到：‘每个 distribution 可以使用的线上升级机制都不相同’的啊！所以请参考你的 distribution 所提供的文件来进行线上升级的设定喔！否则就得要自行手动下载安装了！ @_@

底下鸟哥以 CentOS 4.3 提供的 yum 线上升级架构来进行说明，同时亦简单的介绍一下 B2D 这个 distribution 的 APT 来说明说明！ ^_^！那为什么不选择其他的版本来介绍呢？ 就如同区域网路那个章节里面的 distribution 选择提到的， 越稳定的版本就不容易发生程式臭虫，不断升级的情况就比较不会发生，所以，鸟哥这里再次的说明一下， 如果要做为主机伺服器之用的话，尽量选择较稳定且支援较多的版本，例如 CentOS, SuSE, Red Hat, B2D 及 debian 等 distribution 啊！
大标题的图示 CentOS 的 yum 自动升级
我们知道 CentOS 主要是以 RPM 来作为套件的管理机制，那么 RPM 本身就有一些表头资料记录了这个套件本身的资讯， 包括了相依属性之类的讯息等等， yum 这个咚咚就是藉由分析这些 RPM 套件的表头资料，并且将这些表头资料事先记录下来， 当使用者要求升级或者是安装的时候， yum 就会透过分析这些表头资料来决定下载的档案， 这些下载的档案当然包括了相依属性的套件了，所以说，yum 已经主动克服了套件之间的属性相依问题啰！很棒吧！

那么 yum 是如何动作的呢？基本上是这样的：
  • 先由设定档判断 yum server 所在处；
  • 连接到 yum server 后，先下载新的 RPM 档案的表头资料；
  • 分析比较使用者所欲安装/升级的档案，并提供使用者确认；
  • 下载使用者选择的档案到系统中的 /var/cache/yum ，并进行实际安装；
所以说，找到合适的 yum server 是挺重要的一件事啊！

小标题的图示 yum 的设定档
基本上，在你一安装完 CentOS 之后，系统就主动的帮你建立好 CentOS 的 yum server 设定了， 他的设定档在：
  • /etc/yum.conf
  • /etc/yum.repos.d/CentOS-Base.repo
其中，那个 yum.conf 是主要设定档，可以设定一些环境参数之类的，至于 CentOS-Base.repo 则是主要的 yum server 选择的资料，你可以直接修改 CentOS-Base.repo 这个档案即可。 另外，台湾地区的 CentOS 镜像站台 (mirror) 可以选择义守大学的 FTP 网站， 例如底下的连结：
  • http://ftp.isu.edu.tw/pub/Linux/CentOS/
截至目前为止 (2006/09/xx)，最新的 CentOS 是 4.4 版，所以上头这个连结你可以进入 4.4 那个目录， 就能够看到很多 CentOS 提供的各项套件资料了。其中比较重要的两个目录是：‘ o s’以及‘ update ’ ，分别是基础套件以及修补过后的套件啦！既然知道了台湾地区的 FTP 网站后，自然就不需要连接到美国去下载档案， 那么连线下载的速度当然就会比较快啦！不过，你就得要自行修改修改设定档了！

不过 CentOS 官方网站则是建议使用国码来作为镜相网站的选择依据， 如此一来在大版本相同的环境下 (4.3 -> 4.4) 咱们的 CentOS 是可以自动升级到不同版本中的！ 所以，鸟哥的设定档是改成这个样子的：
[root@linux ~]# vi /etc/yum.repos.d/CentOS-Base.repo
[base]
name=CentOS-$releasever - Base
mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch
&repo=os&cc=tw
# 注意！上面两行是同一行！
gpgcheck=1
gpgkey=http://mirror.centos.org/centos/RPM-GPG-KEY-centos4

#released updates
[update]
name=CentOS-$releasever - Updates
mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch
&repo=updates&cc=tw
# 注意！上面两行是同一行！
gpgcheck=1
gpgkey=http://mirror.centos.org/centos/RPM-GPG-KEY-centos4
......(底下省略).....
主要是将 mirrorlist 那个变数的最后面加上国码‘&cc=tw’就可以了！如果未来有较新的版本时， 那么你的 yum 就能够自动升级啰！另外，除了 [base] 与 [update] 之外，其实 CentOS 还提供很多的额外套件， 这包括了： addons, extras, centosplus, contrib 等等，这些资料你也可以加入到设定档当中， 来帮助你容易安装某些非正规支援的套件资料啊！ ^_^

另外最要注意的是，在设定档当中所指定的镜像站台 (mirror) 离你越近越好，而且频宽越大越好， 这样你就可以比较方便快速的下载啊！而且，你必须已经成功的连结到该镜像站台才行， 否则在执行 yum 时会发生某些问题喔！另外，你必须是 root 的身份才能使用 yum 啊！ 也就是说：
  • 你必须使用 root 的身份来执行 yum ；
  • 设定档内指定的镜像站台必须能与你进行网路连接；
  • 镜像站台频宽越大越好，所以选择离你越近的镜像站越好！
小标题的图示 yum 的安装、升级、移除、查询等功能
yum 可不止能够线上自动升级而已，他还可以作查询、套件群组的安装、整体版本的升级等等，好用的哩！ 先来谈论一下 yum 这个 client 端的指令用法吧：
[root@linux ~]# yum [option] [工作项目] [套件]
参数：
option：主要的参数，包括有：
   -y ：当 yum 询问使用者的意见时，主动回答 yes 而不需要由键盘输入；
   --installroot=/some/path ：安装在其他的路径，而不在目前目录树的架构中；
        对于建立虚拟机器相当有帮助！不过，一般使用者应该用不到。
[工作项目]：由于不同的使用条件，而有一些选择的项目，包括：
   install ：指定安装的套件名称，所以后面需接‘ 套件名称 ’
   update  ：进行整体升级的行为；当然也可以接某个套件，仅升级一个套件；
   remove  ：移除某个套件，后面需接套件名称；
   search  ：搜寻某个套件或者是重要关键字；
   list    ：列出目前 yum 所管理的所有的套件名称与版本，有点类似 rpm -qa；
   info    ：同上，不过有点类似 rpm -qai 的执行结果；
   clean   ：下载的档案被放到 /var/cache/yum ，可使用 clean 将他移除，
             可清除的项目：packages | headers | metadata | cache 等；
另外，在[工作项目]部分还可以具有整个群组套件的安装方式，如下所示：
   grouplist   ：列出所有可使用的‘套件组’，例如 Development Tools 之类的；
   groupinfo   ：后面接 group_name，则可了解该 group 内含的所有套件名；
   groupinstall：这个好用！可以安装一整组的套件群组，相当的不错用！
                 更常与 --installroot=/some/path 共用来安装新系统
   groupupdate ：升级整个套件群组；
   groupremove ：移除某个套件群组；

范例一：搜寻 CentOS 的更新主机上是否有 RAID 磁碟阵列相关套件？
[root@linux ~]# yum search raid
.....前面省略.....
mdadm.i386                               1.6.0-3                base
Matched from:
mdadm controls Linux md devices (software RAID arrays)
mdadm is used to create, manage, and monitor Linux MD (software RAID)
.....后面省略.....
# 看到否？输出资料的特殊字体那一行就显示了你可以安装的套件名称然后你可以这样：

[root@linux ~]# yum info mdadm
Name   : mdadm
Arch   : i386
Version: 1.6.0
Release: 3
Size   : 84 k
Repo   : base
Summary: mdadm controls Linux md devices (software RAID arrays)
Description:
.....后面省略.....
# 瞧一瞧啊！套件的版本名称、资料大小、还有该套件出处 (base)！
# 需要注意看的是 Summary 与 Description 这两个注意事项内容！
yum 真是个很好用的东西，他可以直接查询是否有某些特殊的套件， 你可以利用‘ yum search "一些关键字" ’或者是‘ yum list ’列出所有的套件名称， 然后再以正规表示法取得关键字，或者是‘ yum list "套件名称" ’ 就能够知道该套件的用途， 最后再决定要不要安装啊！上面的范例一就是在找出磁碟阵列的管理软体， 如果确定要安装时，那就可以这样处理：
范例二：安装某个套件吧！以 mdadm 为例：
[root@linux ~]# rpm -q mdadm
package mdadm is not installed
# 鸟哥的主机并没有安装这个玩意儿～所以底下开始安装先！

[root@linux ~]# yum install mdadm
Setting up Install Process
Setting up repositories
update                    100% |=========================|  951 B    00:00
base                      100% |=========================| 1.1 kB    00:00
addons                    100% |=========================|  951 B    00:00
extras                    100% |=========================| 1.1 kB    00:00
# 上面这个阶段在读取 RPM 档案的档头资料；

--> Populating transaction set with selected packages. Please wait.
---> Downloading header for mdadm to pack into transaction set.
mdadm-1.6.0-3.i386.rpm    100% |=========================| 8.2 kB    00:00
---> Package mdadm.i386 0:1.6.0-3 set to be updated
--> Running transaction check
# 上面这个阶段则是在下载档案以及准备更新的阶段

Dependencies Resolved
=============================================================================
 Package                 Arch       Version          Repository        Size
=============================================================================
Installing:
 mdadm                   i386       1.6.0-3          base               84 k

Transaction Summary
=============================================================================
Install      1 Package(s)
Update       0 Package(s)
Remove       0 Package(s)
Total download size: 84 k
Is this ok [y/N]: y
# 至于这个阶段则在分析相依属性，并且让使用者确认下载开始

wnloading Packages:
(1/1): mdadm-1.6.0-3.i386 100% |=========================|  84 kB    00:00
Running Transaction Test
Finished Transaction Test
Transaction Test Succeeded
Running Transaction
  Installing: mdadm                        ######################### [1/1]

Installed: mdadm.i386 0:1.6.0-3
Complete!
# 最终则下载与安装的结果！
瞧！经过 yum 我们可以很轻松的就安装好一个软体，并且这个软体已经主动的帮我们做好相依属性的克服了， 真是方便到爆！另外，你必须要知道，刚刚那个被下载安装的 mdadm 档案被放置到 /var/cache/yum 里面去了， 如果你要节省硬碟空间的话那么可以在安装完毕后将该档案移除，就用：
[root@linux ~]# yum clean packages
Cleaning up Packages
2 packages removed
这样就能够清除掉已下载的档案啰～节省一下硬碟空间啊！OK～那如何进行整体的更新呢？ 比如说鸟哥刚刚装完了 CentOS 4.3 ，但这个版本已经推出若干时间，所以也已经作了很多更新了， 那鸟哥如何整体更新啊？很简单，就用如下的指令：
[root@linux ~]# yum -y update
加一个‘ -y ’的参数可以让系统自动帮你回答‘ yes ’，在背景处理时会比较方便一点。 如果你是第一次执行，那就会发现：哇！怎么下载的资料量到达数百 MB 之谱！没错啊！ 所以记得 /var/ 这个目录的容量要给大一点才行！ 否则就会出现无法完整下载所有更新档案的问题啊！ @_@

  • 安装套件群组的功能
    什么是‘套件群组’呢？还记得在安装的时候有出现套件选择的地方吧？ 在那个时候你选择的资料可不是‘套件名称’喔，而是一堆‘套件群组’，举例来说， 你会看到‘KDE 桌面环境’之类的，而不是每个 KDE 桌面的各项套件名称，对吧！那个咚咚就是‘套件群组’啦！ 由于各大 distributions 预设都没有选择发展工具 (Development Tools)， 这些工具包含了 gcc, kernel-devel 等等，那么你如何使用 yum 一口气安装呢？ 看看底下的范例：
    范例三：查询与安装‘套件群组’
[root@linux ~]# yum grouplist
Installed Groups:
   Administration Tools
   Authoring and Publishing
   Compatibility Arch Support
.....中间省略.....
Available Groups:
   Development Tools
   XFCE-4.2
.....中间省略.....
Done
# 看到没！上面就列出来你已经安装的套件群组，还有尚可安装的其他套件群组，
# 真是非常的方便！那么如何知道 Development Tools 里面有啥咚咚？

[root@linux ~]# yum groupinfo "Development Tools"
Group: Development Tools
 Required Groups:         <==所需要的相依属性资料
   Development Libraries
 Default Metapkgs:        <==预设内部所需要的中继套件
   Emacs
 Optional Metapkgs:       <==最好还含有这些套件较佳
   Ruby
   XEmacs
.....中间省略.....
 Mandatory Packages:      <==一些所需要的套件资料
   pkgconfig
   gcc-ppc32
   make
   gcc
   autoconf
.....中间省略.....
 Default Packages:
   gcc-g77
   cscope
.....中间省略.....
 Optional Packages
   dejagnu
   ElectricFence
   gcc-gnat
.....中间省略.....
# 总共会列出来这个‘套件群组’内含有的各项资料，如果你需要安装的话，就可以：

[root@linux ~]# yum groupinstall "Development Tools"
    利用这个‘ yum groupinstall "套件群组名" ’可以让你一口气安装很多的套件， 而不必担心某个套件忘记装了！实在是很不错啦～而且利用 groupinfo 的功能你也可以发现一些不错的套件资料， 如此一来，你就可以更方便的管理你的 Linux 系统了，很不错吧！

    例题：请设定一下工作排程，让你的 centOS 可以每天自动更新系统

    答：
      可以使用‘ crontab -e ’来动作，也可以编辑‘ vi /etc/crontab ’来动作， 由于这个更新是系统方面的，所以鸟哥习惯使用 vi /etc/crontab 来进行指令的说明。 其实内容很简单：
      40 5 * * * root yum -y update && yum clean packages
      这样就可以自动更新了， 时间订在每天的凌晨 5:40 ，并且更新完成后会主动的将下载的套件资料移除喔！

    • 小标题的图示 不同版本间的升级
    什么！不同的版本之间可以直接‘网路’升级了喔？没错！而且整个流程还挺简单的， 升级完成之后，绝大部分的服务都还不会有困扰！真是很不错啊！那什么是‘不同版本？’举例来说， CentOS 4.2 升级到 CentOS 4.3 算是一种，而 Fedora Core 1 升级到 CentOS 4.3 则又是另外一种， 同样是 CentOS 的升级比较容易，尤其 4.3 本来就是架构在 4.2 上面持续发展的结果； 不过如果是 Fedora Core 的话，可能就比较麻烦一点点。底下我们分别谈一谈这两种方式的升级吧！

  • CentOS 4.2 升级到 CentOS 4.3
    在 CentOS 的发展理念当中，如果推出了 4.3 ，那么 4.2 以前的 4.x 版本就不会继续发展， 所以使用者必须要将原本的 4.2 直接提升到 4.3 才行。那么需要作些什么动作呢？ 不需要啊！只要修改一下 yum 的设定档就好了。首先，同样需要找到最近的镜像站台， 我们依旧以义守大学的 FTP 网站来提供所需要的套件资料，修改成这样：
    1. 先修改 /etc/yum.conf
[root@linux ~]# vi /etc/yum.conf
.....前面省略.....
# 直接在档案的最底下加入这一行来增加一些额外的功能：
plugins=1

2. 再修改 /etc/yum.repos.d/CentOS-Base.repo
[root@linux ~]# vi /etc/yum.repos.d/CentOS-Base.repo
# 内容与‘ yum 的设定档’说明相同，请回到本小节的最前面查阅该设定
    因为 /etc/yum.repos.d/CentOS-Base.repo 的内容与前面相同， 所以鸟哥在这里不再浪费篇幅，请往前翻阅吧！设定好了之后，接下来给他进行：
    [root@linux ~]# yum upgrade
    记得是‘ upgrade ’而不是‘ update ’喔！两者用法不同啊！ 然后接下来就是一段时间的等待啊！没办法，因为从网路上面捉资料下来是需要时间的！ 还好鸟哥的环境是在学术网路内，所以连结同样是学术网路的义守大学还挺快的就是了！ ^_^！ 整个升级的时间大约花费 20 分钟以内，升级完毕之后，重新开机瞧一瞧登入画面！哇！变成 CentOS 4.3 了， 真是快速又方便！而且原本有启动的服务几乎没有任何问题，同样可以正常的启动呐！^_^

    上面的动作你可以参考底下这一篇官方说明文件：
    • http://www.centos.org/modules/news/article.htm?storyid=118
  • Fedora Core Release 1 升级到 CentOS 4.3
    如果你使用的是旧版的 Linux distributions ，例如 Fedora core release 1, Red Hat 9 等等的系统， 这些系统已经旧到没有什么更新的软体出来，所以如果套件有臭虫而需要更新时， 你可能就得要使用 Tarball 的方式手动的给他‘ configure, make, make install ’等等的， 好累啊～那如果我安装 CentOS 呢？如果需要主动重新安装的话，那旧的资料不是会不见吗？ 又得要备份，重新处理等等的，还是很累啊！

    没关系！有 yum 就搞定了！你可以将你的 FC1 升级到 CentOS 4.3 了，而且是‘线上更新’喔！ 厉害吧！不过，因为 FC1 使用的核心是 2.4 版，但 CentOS 4.3 使用的是新的 2.6.x ， 这两种核心可不能互相更新啊！所以啰，我们还需要一些额外的动作来进行升级，而不像前面 CentOS 4.2 升级到 4.3 那么简单！鸟哥底下的动作是参考这几篇：
    • twu2 兄提供的不同版本间升级：http://phorum.study-area.org/viewtopic.htm?t=28648
    • CentOS 官方网站提供的一些升级建议：
      http://www.centos.org/modules/newbb/viewtopic.htm?topic_id=428&forum=6
      http://www.centos.org/modules/newbb/viewtopic.htm?topic_id=382
    鸟哥底下以 FC1 为例来进行整个升级的动作，不过你得要了解的是，每个人的 Linux 都不相同， 因此虽然鸟哥实作是成功的，不过不代表你的环境一定会成功， 所以，重点是....‘请做好备份！’ 以免升级不成功时，导致整个资料的损毁，那就得不偿失了！
    0. 前处理：先准备好你的资料，以及删除不需要的资料
[root@linux ~]# yum clean packages headers
# 先删除原本的 yum  资料，因为 FC1 使用的也是 yum ，
# 所以最好先将之前 FC1 的 yum 资料删除，比较不会有问题；
    在这个步骤当中，你最好先将一些重要资料备份起来，包括 /etc 与 /home 整个目录， 还有其他你有开启的服务的资料，包括 MySQL 或者是 WWW 的网页资料等，请自行备份喔。 另外，我们的 yum 预设是将下载的套件通通放置到 /var/cache/yum 当中，所以你的 /var 目录所在 partition 的容量也需要至少 1GB 以上的容量，而且安装软体所在目录 /usr 所在的 partition 最好也能够有 2GB 以上的空间，否则容易出现空间不足的错误讯息而无法继续。

    那如果真的空间不足怎么办？你可以将一些不需要的套件先移除啊！举例来说， 你可以利用‘ yum groupremove "Development Tools" ’之类的指令先将这些不是必备的套件群组移除， 以及其他 X 相关的套件也可以先移除，等到升级完毕后再以 yum 来重新安装即可， 这样可以节省很多升级时分析相依属性所花费掉的时间喔！

    同时你得要确认你的镜像站台，以及 CentOS 的数位签章档案已经安装到 RPM 资料库当中才行， 同样的，鸟哥还是以义守大学的 FTP 站为主要的来源镜像站，但是你必须要先取得一些 RPM 相关的档案， 这些档案由于会与 FC1 原本的套件产生不相符合的特性，所以需要先捉下来并且强制安装才行！ 请你自行连上：
    • http://ftp.isu.edu.tw/pub/Linux/CentOS/
    然后选择最新的版本，例如鸟哥使用 4.3 (2006/08/10 以前) 这个版本，所以直接点选他， 然后依序选择‘os’->‘i386’->‘CentOS’->‘RPMS’，然后下载底下这些档案 (注：套件的版本号码可能会有些不同喔！)：
    • centos-release-4-3.2.i386.rpm
    • centos-yumconf-4-4.5.noarch.rpm
    • kernel-2.6.9-34.EL.i686.rpm
    • udev-039-10.12.EL4.i386.rpm
    假设我的这些档案捉下来后放到 /root 下，那接下来的动作是：
    1. 安装升级所需要的 RPM 档案：
[root@linux ~]# rpm --import  \
> http://ftp.isu.edu.tw/pub/Linux/CentOS/4.3/os/i386/RPM-GPG-KEY-centos4
[root@linux ~]# rpm -Uvh centos-release-4-3.2.i386.rpm
[root@linux ~]# rpm -Uvh centos-yumconf-4-4.5.noarch.rpm
[root@linux ~]# rpm -ivh --force --nodeps kernel-2.6.9-34.EL.i686.rpm
# 在这个动作时，由于我们的核心并非是 CentOS ，所以这个动作会发生一些错误，
# 先不要理他，待会儿的动作再重新处理即可。
[root@linux ~]# rpm -ivh --force --nodeps udev-039-10.12.EL4.i386.rpm
    由于 kernel 2.6 使用的装置管理是以 udev 这个套件来处理的，与原本的 kernel 2.4 并不相同， 为了避免使用者进行错误的安装，所以 yum 会主动的分析核心与装置管理套件的差异， 如果两者无法配合就产生错误讯息且强制中断 yum ，那结果就是导致无法以 yum 进行升级啦！ 要躲过这个困扰，你就得要先手动的安装上头那几个 RPM 档案。同时安装 kernel 的过程当中会发生错误讯息， 先不要理他，等到后续步骤再来重新处理即可！ 既然 kernel 2.6 会与 2.4 版冲突，而鸟哥的原本的 FC1 本来就有 2.4 版的核心嘛！ 那即使安装了新的 kernel-2.6.9-34.EL.i686.rpm 核心，但核心版本冲突的问题还是没有解决的， 所以啊，你就得要这样做了：
    2. 移除会有冲突的 2.4 版核心，连同其原始码
[root@linux ~]# rpm -qa | grep kernel
kernel-2.4.22-1.2197.nptl
kernel-2.4.22-1.2115.nptl
kernel-2.4.22-1.2199.nptl
kernel-source-2.4.22-1.2197.nptl
kernel-source-2.4.22-1.2199.nptl
.....其他省略.....
[root@linux ~]# rpm -e kernel-source-2.4.22-1.2199.nptl
[root@linux ~]# rpm -e kernel-source-2.4.22-1.2197.nptl
[root@linux ~]# rpm -e kernel-2.4.22-1.2115.nptl
[root@linux ~]# rpm -e kernel-2.4.22-1.2197.nptl
[root@linux ~]# rpm -e kernel-2.4.22-1.2199.nptl
# 反正就是找到核心与核心原始码的套件后，就将他移除！记得套件名为：
# kernel 与 kernel-source  ，其他的不用动！
[root@linux ~]# rpm --rebuilddb
    将一些旧版本的核心给他移除后，你的系统就只有剩下刚刚安装的那个 CentOS 的新核心， 所以核心版本的冲突当然就不存在了。要注意的是，你现在绝不可重新开机，否则你的系统就挂了！ 因为没有核心了喔！切记切记！然后开始要设定好升级时要使用的 yum 设定档了！
    3. 规范设定档
[root@linux ~]# vi /etc/yum.upgrade
[main]
cachedir=/var/cache/yum
debuglevel=2
logfile=/var/log/yum.log
pkgpolicy=newest
distroverpkg=fedora-release
installonlypkgs=kernel kernel-smp kernel-hugemem kernel-unsupported
tolerant=1
exactarch=1
plugins=1

[upgrade]
name=CentOS-4.3 - upgrade
baseurl=http://ftp.isu.edu.tw/pub/Linux/CentOS/4.3/os/i386/

[update]
name=CentOS-4.3 - Updates
baseurl=http://ftp.isu.edu.tw/pub/Linux/CentOS/4.3/updates/i386/
    设定档里面先只要有这两个项目即可，因为我们仅注视在整体版本的升级， 所以其他的额外功能部分先不要理他！以后再来处理即可啊！接下来就准备要升级了！这样做吧：
    4. 开始升级的动作：
[root@linux ~]# yum -y -t -c /etc/yum.upgrade upgrade
    理论上，如果你的 FC1 没有安装什么奇怪的软体，而且‘硬碟空间也足够’ ，那么 yum 应该会开始帮你一个一个的下载软体并且分析属性相依问题后，就开始进行安装的步骤。 不过，如果发现一些软体冲突的问题时，那么你就得要先以 rpm -e 将旧的软体先移除， 等到升级完毕后再安装回来即可。只不过这个动作将依你的环境而有所不同。 鸟哥的 FC1 实在是旧的可以，所以很多软体都有冲突，因此事先移除了很多的套件， 忙了快要半小时后，系统才顺利的开始进行安装。由于鸟哥主机所在环境的网路下载的速度尚可而已， 所以由开始下载到升级完毕，大概花了一个半小时左右！ @_@
    5. 重新安装核心，并处理 RPM 资料库与更新其他套件
[root@linux ~]# rpm -ivh --force --nodeps kernel-2.6.9-34.EL.i686.rpm
[root@linux ~]# rpm --rebuilddb
[root@linux ~]# yum update
    透过这三个指令我们可以再将刚刚没有完成的核心安装一遍，同时再以新的 yum 来进行升级， 这个时候我们的系统应该是很 OK 的啦！不过，有的小问题，那就是‘开机的设定档还没有更新’喔！ 所以你还得要这样做：
    6. 设定开机设定档
[root@linux ~]# vi /boot/grub/menu.lst
default=0
timeout=10
splashimage=(hd0,0)/boot/grub/splash.xpm.gz
title CentOS (2.6.9-34.0.2)
        root (hd0,0)
        kernel /boot/vmlinuz-2.6.9-34.0.2.EL ro root=/dev/hda1 hdd=ide-scsi rhgb
        initrd /boot/initrd-2.6.9-34.0.2.EL.img
title CentOS (2.6.9-34.EL)
        root (hd0,0)
        kernel /boot/vmlinuz-2.6.9-34.EL ro root=/dev/hda1 hdd=ide-scsi rhgb
        initrd /boot/initrd-2.6.9-34.EL.img
    在今日 (2006/08/10) 能够安装的最新核心版本是 2.6.9-34.0.2.EL ，所以上面的第一个 title 才会是这样的设定资料，要记得与你的环境符合啊(如果你不是使用 4.3 来升级)！如果忘记上面各项资料的意义， 请参考‘鸟哥的 Linux 私房菜 基础篇 boot loader ’的介绍啊！ 如果设定好了这个开机资讯，嘿嘿！请重新开机试看看吧！ ^_^

    基本上这样已经处理完毕了！也就是说，你的系统应该是由 FC1 顺利的转成 CentOS 4.3 才对！ 不过，有些小细节你依旧需要注意喔：
    • 观察您的系统是否有启动原有的服务，亦可利用 chkconfig --list；
    • 如果你的旧系统曾有使用 tarball 的方式来安装软体，则升级完毕后你必须要重新安装一次该软体；
    • 系统可能会产生很多的 .rpmnew 的档案，请使用 locate 搜寻，并且重新处理设定档。
    毕竟之前的版本太旧了，所以 RPM 升级时会将新套件的设定档存成 *.rpmnew ， 你最好不要使用旧的设定档，而是以新的设定档来重新修改比较好！这样服务的运作应该会比较顺畅一些啊！ 到此为止，恭喜您啊！ ^_^
    • 大标题的图示 Debian 的 apt 自动升级：以 B2D 为例
    APT 最早是 debian 这个社群的 Linux distribution 用来作为套件管理的一项机制， 后来实在很方便又好用，所以就被利用来做为其他 distributions 的线上升级管理机制了！ 所以你会在很多地方看到有 FC 系列的 APT 伺服器、或者是自订的 APT 伺服器等等的。 这个 APT 的使用与 yum 很类似呐！同样也是透过套件的表头分析后，然后与系统本身资料比对， 因此同样也克服了属性相依的困扰了，非常方便！底下我们就分别来谈一谈吧！

    小标题的图示 APT 的设定档
    如同前面提到的 yum 一样，既然是线上升级，那么我们自然得要找到相对应的伺服器啰！ 而一般有提供 apt 服务的 distributions 事实上他们都已经做好设定档内相关的伺服器选择了， 例如 B2D 就是一个例子。不过， 如果你是使用类似 Red Hat 9, Fedora Core Release 等版本的话， 可能由于种种原因让你不能将该主机升级到类似 CentOS 等较新的版本时，那你就可以尝试到底下的网站找找看 APT 主机了：
    • http://apt.freshrpms.net/
    找到属于你的 Linux 版本后，安装 apt 就可以使用 apt 伺服器所提供的套件升级机制啰！ 底下赶紧谈一谈，那么如何处理 APT 的设定档呢？ APT 的设定档都放在 /etc/apt 目录下，而在该目录下，规范 APT 主机的设定则放到 /etc/apt/sources.list 当中。 以 B2D 为例，他的 sources.list 是这样的：
    1. 先处理 APT 伺服器来源的设定资料：
[root@linux ~]# vi /etc/apt/sources.list
deb ftp://debian.tnc.edu.tw/pub/debian/ stable main non-free contrib
deb http://security.debian.org/ sarge/updates main contrib non-free
deb ftp://debian.tnc.edu.tw/pub1 b2d/
deb http://ftp2.de.debian.org/debian-volatile sarge/volatile main
# 上面的格式是这样的：
# <deb 的标头格式> <APT伺服器网址> <相对网址路径> <目录一> <目录二> ...
    其实设定档的内容很简单，第一个栏位指的是‘用哪一种套件管理员’的意思，主要有 deb 以及 rpm 还有 rpm-src 等，deb 是 debian 专属的套件管理方式啦！ ^_^！第二栏以后就得要一起看才行！ 以上表的第一行为例，其实他是说，提供 deb 的网址有三个，分别是：
    • ftp://debian.tnc.edu.tw/pub/debian/stable/main
    • ftp://debian.tnc.edu.tw/pub/debian/stable/non-free
    • ftp://debian.tnc.edu.tw/pub/debian/stable/contrib
    这样看懂了吗？第二栏与第三栏要加在一起，那就是个完整的伺服器网址！ 后面接的几个资料则是在该网址底下的数个目录，那就很容易看懂了吧！ ^_^ 应该是不难啦～如果您是使用 b2d 的话，那恭喜你！不用修改就能用 apt 啰！ ^_^
    Tips:
    事实上， /etc/apt/apt.conf 还可以提供其他额外的设定喔，例如使用 Proxy 以及规范下载后的套件在安装完毕后应该进行的处理步骤，举例来说，是否需要将该套件移除！ 你应该要使用 man apt.conf 查询一下该档案的用法喔！     		鸟哥的图示
    小标题的图示 实际使用 APT
    APT 的使用也实在是很简单！只要利用 apt-get 即可！不过，不同于 yum 每次都会进行 RPM 档案表头的分析， APT 则是将套件表头的下载与实际的安装分成两个动作分别执行，先来谈一谈 apt-get 这个指令的用法吧！
    [root@linux ~]# apt-get [-qy] [-c config_file] [更新项目] [套件名称]
参数：
-q ：不要在荧幕上输出讯息，常用在背景环境的执行当中喔！
-y ：自动在进行 apt-get 时回答 y 的回应；
-c ：后面接的是设定档，一般系统会主动的以 /etc/apt 内的设定档为依据。
[更新项目]：要 apt-get 进行的工作，主要有这几项：
   update      ：就是更新伺服器与用户端的套件表头清单，这个动作务必要进行！
   install     ：后面需要加上要安装的套件名称才行！
   upgrade     ：进行‘已安装套件’的完整升级，不过未安装套件则不予安装；
   dist-upgrade：以 upgrade 相似，但是当新版本的套件有其他相依属性的套件加入时，
                 单纯的 upgrade 将无法进行安装，此时就得要使用 dist-upgrade 了！
   clean       ：清除已经下载到 /var/cache/apt/archives/ 的套件档案。
   remove      ：移除某个套件啊！

范例一：进行套件标头更新后，进行整体套件的更新动作
[root@linux ~]# apt-get update
下载:1 ftp://debian.tnc.edu.tw stable/main Packages [3349kB]
下载:2 http://ftp2.de.debian.org sarge/volatile/main Packages [3893B]
.....中间省略.....
读取 3868kB 用了 24s (159kB/s)
读取套件清单中... 完成

[root@linux ~]# apt-get dist-upgrade
读取套件清单中... 完成
了解套件依存关系中... 完成
筹画升级套件中...完成
下列的套件都将被【删除】：
  blt-common ettercap-plugins libgdbmg1-dev
下列的【新】套件都将被安装：
  dictionaries-common ettercap-common .....后面省略.....
下列的套件都将维持旧版本:
  fontconfig libxft-dev libxft2 libxft2-dbg .....后面省略.....
下列的套件都将更新:
  apache apache-common apache-utils apache2 .....后面省略.....
更新 105 个套件，新安装 32 个套件，删除 3 个套件，另不更新 7 个套件。
需要下载 122MB 的档案。
解压缩后将消耗 39.6MB 的空间。
继续执行吗？ 是按 [Y] 键，否按 [n] 键 y
下载:1 ftp://debian.tnc.edu.tw stable/main libc6-dev 2.3.2.ds1-22sarge3 [2535kB]
下载:2 http://security.debian.org sarge/updates/main login 1:4.0.3-31sarge8 [576kB]
.....中间省略.....
读取 122MB 用了 11m47s (172kB/s)
正在预先设定套件 ...
(正在读取资料库 ... 系统目前总共安装有 112550 个档案和目录。)
正预备替换 libc6-dev 2.3.2.ds1-22 (使用 .../libc6-dev_2.3.2.ds1-22sarge3_i386.deb)
正在解压缩替换的套件档 libc6-dev ...
.....中间省略.....
Please *restart* your Apache2 !
Y/N ?
y
.....中间省略.....

[root@linux ~]# apt-get clean
# 这个动作会将刚刚下载的几个 deb 的套件给他移除！节省硬碟空间！
    请记得，那个 update 的参数并不是在进行更新， 而是在进行伺服器与用户端的套件表头清单更新而已， 但这个动作相当重要，如果你没有作这个动作的话，你的套件就不会更新了！ 在 apt-get update 后，再使用 apt-get dist-upgrade 这样就能够将整个系统给他升级了！很快乐吧！不过，由于我们没有加上‘-y’这个参数， 所以在上表当中，我们会老是需要输入一些有的没有的指令， 这样的话，就不适合作为背景的自动升级了！所以，如果你想要在背景以 crontab 的方法自动的帮你升级的话，在 B2D 的环境下使用：
    [root@linux ~]# vi /etc/crontab
40 5 * * * root /usr/bin/apt-get update && /usr/bin/apt-get -y dist-upgrade
    这样每天的凌晨 5:40 就会自动的进行整体升级，而且会主动的克服相依属性的问题喔！ 另外，除了完整的将套件给他全部升级之外，我们还可以利用 apt 伺服器的功能来进行查询的动作喔！ 这个时候就得要 apt-cache 来帮忙了！
    [root@linux ~]# apt-cache [搜寻项目]
参数：
[搜寻项目]：apt-cache 可以搜寻 apt 所列出的套件标头资料喔！可用项目有：
pkgnames：列出本系统上面的所有套件名称！！有点类似 (rpm -qa)；
dump    ：列出所有的套件标头以及其相关的相依属性套件！
search  ：后面可接要搜寻的字串，例如 apt-cache search postfix
show    ：后面接套件名称，可以显示出该套件的主要内容的描述！
showpkg ：列出后面所接套件的相依属性以该其套件提供的相关功能！
depends ：可以列出与后面所接套件有相依属性或者是冲突的相关资料！

范例一：找出与 grep  有关的套件
[root@linux ~]# apt-cache search grep
.....前面省略.....
grep - GNU grep, egrep and fgrep
grep-dctrl - Grep Debian package information
.....后面省略.....

[root@linux ~]# apt-cache show grep
Package: grep
Essential: yes
Priority: required
Section: base
Installed-Size: 660
Maintainer: Ryan M. Golbeck <rmgolbeck@debian.org>
Architecture: i386
Version: 2.5.1.ds1-4
Provides: rgrep
Pre-Depends: libc6 (>= 2.3.2.ds1-4)
Conflicts: rgrep
Filename: pool/main/g/grep/grep_2.5.1.ds1-4_i386.deb
Size: 170290
MD5sum: 68196ad14b098b0eb4b91f4a7cfa8ff2
Description: GNU grep, egrep and fgrep
 'grep' is a utility to search for text in files; it can be used from the
 command line or in scripts.  Even if you don't want to use it, other packages
 on your system probably will.

[root@linux ~]# apt-cache depends grep
grep
  特别依存关系: libc6
  冲突: <rgrep>
    瞧！利用 apt-cache 就能够找到很多有用的资讯！包括利用 show 这个参数也能够将该套件重要的项目给他列出来！ 以上面的 grep 这个套件为例， apt-cache 就列出很多例如版本资讯、冲突资讯 (conflicts) 等等， 尤其是描述 (Description) 的部分，就更可以让使用者了解该套件的用途了！ ^_^！另外， 那个 depends 则可以特别列出与该套件有冲突或者是相依属性的档案名称！也是个很有帮助的参数喔！ 至于如果你想要安装一个套件的话，例如 zlibc 这个套件时，就可以这样做：
    [root@linux ~]# apt-get install zlibc
    如同前面提到的，如果你原本的系统并不是使用 apt 来进行线上升级的机制，而你想要使用 apt 的话， 目前很多伺服器都有提供相对应版本的升级，其中以 RPM 套件管理的 Red Hat 与 Fedora 最常见！ 台湾杨锦昌老师也提供了完整的 APT 教学，您可以看看：
    • http://163.19.59.1/~linux/student_samba/apt/apt_server.html
    当然，还是那句老话，除非您的主机上面有专属的软体需要该版本的 distribution 才能执行， 当转成其他版本可能会发生无法执行的困扰时，那你只好使用旧版的 distribution， 并且找到对应的 APT 或 yum 伺服器，或者是‘你自己建立一个 APT/yum 伺服器’来提供自己升级！ 比较能够免除一些程式臭虫的困扰。如果没有以上的困扰，那就直接升级到比较新的版本吧！ ‘比较新的版本不一定比较好，不过，在大部分的情况下， 较新版本对硬体的支援以及安全性方面，都会比较好一些。’但是，如果你的主机明明运作的很好， 短期你也不需要什么新硬体的增加，而且你自己有在注意各个套件的安全性时，那不需要升级也是没有问题的啦！
    大标题的图示 重点回顾
    • 由于程式是由人所撰写的，因此程式在执行的过程中难免可能会出现一些安全性的问题或者是程式臭虫的问题。 所以，绝大部分的情况下，将套件保持在最新的版本较能够避免被 cracker 所入侵的问题
    • 绝大部分的自由软体之维护的人员比专属软体还要多，所以程式发生臭虫后的除错与更新时间较快速！！
    • 你不一定要将你的 distribution 更新到最新，不过，更新到最新可以保有较佳的硬体支援与网路安全。
    • 由于 distribution 发展的不同，基本的套件安装可以分为 rpm, dpkg 及 tarball 三种常见模式；
    • 各个 distribution 均有推出自家的线上升级机制，如 CentOS 的 yum, Debian 的 apt, Red Hat 的 up2date 以及 SuSE 的 YOU 等等。各种版本均不可混用。
    • yum 这个升级方案在使用时，会主动的 (1)下载表头资料与 (2)进行使用者所需要的更新动作；
    • apt-get 必须要使用 apt-get update 更新表头资料后，才能够进行使用者所要求的动作！
    • 线上升级机制常常需要使用到 crontab 的工作排程支援；
    大标题的图示 课后练习
    • 请找到您的 distribution 所提供的线上升级机制，立刻进行全部更新的动作。
    • 请前往台湾电脑危机处理小组注册，并取得各项危险通告的电子邮件通知！
    • 在 RPM base 的系统当中，如果升级的套件所含有的设定档在系统当中已经被更动过，则该设定档会如何被安装到系统中？
      • 如果设定档已经被改过，则更新的设定档会被储存成为 *.rpmnew 的副档名。 并建议使用者应该要将旧的设定档备份，然后以新的设定档来进行重新设定。对于该软体的执行稳定性会较佳。
    • 承上题，如何找出系统上面含有被更动过的设定档？以 rpm base 的系统为例？
      • 你可以利用‘ locate rpmnew ’来找出已经安装的新版本设定档，并据以处理该资料； 也可以利用 rpm -Va 来观察系统上面所有的已经被更动过的档案资料！
    • 请找出 CentOS 内的 "Development Tools" 相关的资料，如果您尚未安装，请安装他！
      • 利用‘ yum grouplist ’找出相关的套件群组，利用‘ yum groupinfo "Develop Tools" ’找出该套件是否为您所需要， 最后用‘ yum groupinstall "Develop Tools" ’安装即可！
    • 你在进行 CentOS 安装时，选择的是预设安装，装完毕后才发现没有 gcc 这个编译器。 请问你如何安装 gcc ？
      • 可以使用‘ yum search gcc ’找出所需要的套件，然后用‘ yum install xxx ’来安装即可！
    大标题的图示 参考资料
    • 台湾电脑危机处理小组(TWCERT)：http://www.cert.org.tw/
    • Red Hat 的官方说明：http://www.redhat.com/apps/support/errata/
    • APT 官方网站：http://apt.freshrpms.net/
    • Rondo 的 APT 实做：http://163.19.59.1/~linux/student_samba/apt/apt_server.html
    • APT Server：http://install.opennms.org/apt/
    • 由 Red Hat 9 升级到 CentOS 4.1：http://www.owlriver.com/tips/centos-31-ex-rhl-9/
    • twu2 兄提供的不同版本间升级：http://phorum.study-area.org/viewtopic.htm?t=28648
    • CentOS 官方网站提供的一些升级建议：
      http://www.centos.org/modules/newbb/viewtopic.htm?topic_id=428&forum=6
      http://www.centos.org/modules/newbb/viewtopic.htm?topic_id=382
    • SuSE 的 YOU 自动升级机制须知：
      http://support.novell.com/linux/registration/
      http://support.novell.com/techcenter/articles/RegandUpdate_SLE10.html
    2002/08/02：第一次完成日期！
    2003/06/29：加入自己写的自动更新 RPM 的 bash scripts 功能！
    2003/07/01：重新编写一些内容介绍，此外，由于 Red Hat 6.x 有点老旧了，已经将 up2date 关于 Red Hat 6.x 以前的资料消除了！
    2003/08/22：加入 Mandrake 的 urpmi 以及 APT Client 的设定方法
    2006/08/08：将旧的文章移动到 此处。
    2006/08/09：由于已经有这么多的线上升级机制，所以鸟哥自己写的 bash shell 不需要使用的啦！将他取消了！
    2006/08/10：需要付费的 up2date 也取消了，有需要的话请自行前往旧文章处查阅啦！
    2006/08/11：连 Mandriva 所需要的 urpmi 也拿掉了先！ ^_^
    2006/09/10：本来 yum 的设定档当中是以义守大学的 FTP 设定为主，改为 CentOS 建议的国码为主！
    2002/08/02以来统计人数


鸟哥的 Linux 私房菜 -- 架设 Router

为取得较佳浏览结果，请爱用 firefox 浏览本网页

路由器 Router 设定
切换解析度为 800x600
最近更新日期：2006/08/30
我们在 网路基础 里面提到 路由 (route) 是一个重要的概念，他可以控制我们的资料封包的走向！ 此外，如果同一个网域里面有太多的电脑数量需要来广播的话，效能一定不会太好，所以才会有 Netmask 对吧！今天我们换个角度来想一想，如果说我的网域内真的有太多的电脑数量了， 那么将整个网域切割成较小的数个子网域 (Subnet) 会是一个比较好的作法，不过， 因为网域与网域之间的封包不可以直接互通资料，所以这个时候我们就需要使用 Router (路由器) 来帮忙封包的传送了！

1. 路由
    1.1 路由表
    1.2 IP Alias 的测试功能
    1.3 重复路由的问题
 2. 路由器架设
    2.1 什么是路由器
    2.2 何时需要路由器？
    2.3 静态路由之路由器
    2.4 动态路由之路由器设定：zebra
 3. ARP Proxy 让路由器两端在同一网域
4. 重点回顾
5. 课后练习
6. 参考资料
7. 针对本文的建议：http://phorum.vbird.org/viewtopic.htm?t=26428
大标题的图示 路由
我们在网路基础里面谈到过路由的相关概念， 他最大的功能就是在帮我们规划网路封包的传递方式与方向。 至于路由的观察则可以使用 route 或者是 netstat 来查阅与设定。 好了，那么路由的形式有哪些？您又该如何确认路由是否正确呢？

小标题的图示 路由表
如同前面网路基础谈到的，每一部主机都有自己的路由表， 也就是说，您必须要透过你自己的路由表来传递你主机的封包到下一个路由器上头。 若传送出去后，该封包就得要透过下一个路由器的路由表来传送了，此时与你自己主机的路由表就没有关系啦！ 所以说，如果网路上面的某一部路由器设定错误，那.....封包的流向就会发生很大的问题。 我们就得要透过 traceroute 来尝试了解一下每个 router 的封包流向啰。

OK！那你自己主机的路由表到底有哪些部分呢？我们以底下这个路由表来说明：
[root@linux ~]# route -n
Kernel IP routing table
Destination  Gateway     Genmask        Flags Metric Ref  Use Iface
192.168.1.0  0.0.0.0     255.255.255.0  U     0      0      0 eth0 <== 1
127.0.0.0    0.0.0.0     255.0.0.0      U     0      0      0 lo   <== 2
0.0.0.0      192.168.1.2 0.0.0.0        UG    0      0      0 eth1 <== 3
首先，我们得知道在 Linux 系统下的路由表是由小网域排列到大网域， 例如上面的路由表当中，路由是由‘ 192.168.1.0/24 --> 127.0.0.0/8 --> 0.0.0.0/0 (预设路由) ’来排列的。 而当主机的网路封包需要传送时，就会查阅上述的三个路由规则来了解如何将该封包传送出去。

你会不会觉得奇怪，为什么会有这几个路由呢？其实路由表主要有这几种情况来设计的：
  • 依据介面而存在的路由：
    例如 192.168.1.0/24 这个路由的存在是由于鸟哥的这部主机上面拥有 192.168.1.11 这个 IP 的关系！ 也就是说，你主机上面有几个网路介面的存在时，该网路介面就会存在一个路由才对。 所以说，万一你的主机有两个网路介面时，例如 192.168.1.11, 192.168.2.11 时，那路由至少就会有：
    [root@linux ~]# route -n
Kernel IP routing table
Destination  Gateway     Genmask        Flags Metric Ref  Use Iface
192.168.1.0  0.0.0.0     255.255.255.0  U     0      0      0 eth0
192.168.2.0  0.0.0.0     255.255.255.0  U     0      0      0 eth1
.....以下省略.....

  • 手动或预设路由(default route)：
    你可以使用 route 这个指令手动的给予额外的路由设定，例如那个预设路由 (0.0.0.0/0) 就是额外的路由。 使用 route 这个指令时，最重要的一个概念是：‘你所规划的路由必须要是你的装置 (如 eth0) 或 IP 可以直接沟通 (broadcast) 的情况’才行。举例来说，以上述的环境来看， 我的环境里面仅有 192.168.1.11 及 192.168.2.11 ，那我如果想要连接到 192.168.100.254 这个路由器时， 下达：
    [root@linux ~]# route add -net 192.168.100.0  \
> netmask 255.255.255.0 gw 192.168.100.254
SIOCADDRT: Network is unreachable
    看吧！系统就会回应没有办法连接到该网域，因为我们的网路介面与 192.168.100.0/24 根本就没有关系嘛！ 那如果 192.168.100.254 真的是在我们的实体网路连接上，那其实你应该是这样做：
    [root@linux ~]# route add -net 192.168.100.0  \
> netmask 255.255.255.0 dev eth0
[root@linux ~]# route -n
Kernel IP routing table
Destination    Gateway      Genmask        Flags Metric Ref Use Iface
192.168.100.0  0.0.0.0      255.255.255.0  U     0      0     0 eth0
192.168.1.0    0.0.0.0      255.255.255.0  U     0      0     0 eth0
0.0.0.0        192.168.1.2  0.0.0.0        UG    0      0     0 eth1
    这样你的主机就会直接用 eth0 这个装置去尝试连接 192.168.100.254 了！ 另外，上面路由输出的重点其实是那个‘Flags 的 G ’了！因为那个 G 代表使用外部的装置作为 Gateway 的意思！而那个 Gateway (192.168.1.2) 必须要在我们的已存在的路由环境中。 这可是很重要的概念喔！ ^_^

  • 动态路由：
    除了上面这两种可以直接使用指令的方法来增加路由规则之外， 还有一种透过路由器与路由器之间的协商以达成动态路由的环境， 不过，那就需要额外的软体支援了，例如： zebra (http://www.zebra.org/) 或 CentOS 上面的 Quagga (http://www.quagga.net/) 这几个软体了！
事实上，在 Linux 的路由规则都是透过核心来达成的， 所以这些路由表的规则都是在核心功能内啊！也就是在记忆体当中喔！ ^_^

小标题的图示 IP Alias 的测试用途
我们在 Linux 常用指令里面谈过 eth0:0 这个装置吧？ 这个装置可以在原本的 eth0 上面模拟出一个虚拟介面出来，以让我们原本的网路卡具有多个 IP ， 具有多个 IP 的功能就被称为 IP Alias 了。而这个 eth0:0 的装置可以透过 ifconfig 或 ip 这两个指令来达成， 关于这两个指令的用途请翻回去之前的章节阅读，这里不再浪费篇幅啊！

那你或许会问啊：‘这个 IP Alias 有啥用途啊？’好问题！这个 IP Alias 最大的用途就是可以让你用来‘应急’！ 怎么说呢？我们就来聊一聊他的几个常见的用途好了：
  • 测试用：
    怎么说用来测试呢？举例来说，现在使用 IP 分享器的朋友很多吧， 那 IP 分享器通常使用 WWW 介面来提供设定。那这个 IP 分享器通常会给予一个私有 IP 亦即是 192.168.0.1 来让使用者开启 WWW 介面的浏览。问题来了，那你要如何连接上这部 IP 分享器呢？ 嘿嘿！在不更动既有的网路环境下，你可以直接利用：
    [root@linux ~]# ifconfig [device] [ IP ] netmask [netmask ip] [up|down]
[root@linux ~]# ifconfig eth0:0 192.168.0.100 netmask 255.255.255.0 up
    来建立一个虚拟的网路介面，这样就可以立刻连接上 IP 分享器了。

  • 在一个实体网域中含有多个 IP 网域：
    另外，如果像是在补习班或者是学校单位的话， 由于原本的主机网路设定最好不要随便修改，那如果要让同学们大家互通所有的电脑资讯时， 就可以让每个同学都透过 IP Alias 来设定同一网域的 IP ， 如此大家就可以在同一个网段内进行各项网路服务的测试了，很不错吧！

  • 既有设备无法提供更多实体网卡时：
    如果你的这部主机需要连接多个网域，但该设备却无法提供安装更多的网卡时， 你只好勉为其难的使用 IP Alias 来提供不同网段的连线服务了！
不过，你需要知道的是：所有的 IP Alias 都是由实体网卡模拟来的， 所以当要启动 eth0:0 时，eth0 必须要先被启动才行。而当 eth0 被关闭后， 所以 eth0:n 的模拟网卡将同时也被关闭。这得先要了解才行，否则常常会搞错启动的装置啊！ 在路由规则的设定当中，常常需要进行一些测试，那这个 IP Alias 就派的上用场了。 尤其是学校单位的练习环境当中！ ^_^！

基本上，除非有特殊需求，否则建议你要有多个 IP 时，最好在不同的网卡上面达成， 如果你真的要使用 IP Alias 时，那么如何在开机的时候就启动 IP alias 呢？有两个简单的方法可以使用：
  • 透过 /etc/rc.d/rc.local：
    将‘ifconfig eth0:n ....’的指令写入 /etc/rc.d/rc.local 当中，这样开机的时候就能够启动这个虚拟介面， 不过这方法有个弱点，就是当使用类似‘ /etc/init.d/network restart ’的指令时，该介面可能就会被取消。

  • 透过 /etc/sysconfig/network-scripts/ifcfg-eth0:0：
    举例来说，你可以透过底下这个方法来建立一个虚拟装置的设定档案：
    [root@linux ~]# cd /etc/sysconfig/network-scripts
[root@linux network-scripts]# vi ifcfg-eth0:0
DEVICE=eth0:0            <==相当重要！一定要与档名相同的装置代号！
ONBOOT=yes
BOOTPROTO=static
IPADDR=192.168.0.100
NETMASK=255.255.255.0
NETWORK=192.168.0.0
BROADCAST=192.168.0.255

[root@linux network-scripts]# ifup eth0:0
[root@linux network-scripts]# ifdown eth0:0
    关于装置的设定档案内的更多参数说明，请参考连上 Internet 一文的相关说明，在此不再叙述！使用这个方法有个好处，就是当你使用‘ /etc/init.d/network restart ’时， 系统依旧会使用你的 ifcfg-eth0:0 档案内的设定值来启动你的虚拟网卡喔！另外， 不论 ifcfg-eth0:0 内的 ONBOOT 设定值为何，只要 ifcfg-eth0 这个实体网卡的设定档中， ONBOOT 为 yes 时，开机就会将全部的 eth0:n 都启动。
透过这两个简单的方法，你就可以在开机的时候启动你的虚拟介面而取得多个 IP 在同一张网卡上了。 不过依旧要注意的是，如果你的 eth0 是使用 DHCP 来取得 IP 参数的话，那么由于 ifup 及 /etc/init.d/network 这两个 script 内程式码撰写的方式，将会导致 ifcfg-eth0:0 这个设定档不会被使用到喔！ 所以当你使用 DHCP 来取得 eth0 的 IP 时，你只好使用手动方式 (用 ifconfig) 来设定你的 IP Alias 了。

小标题的图示 重复路由的问题
很多朋友可能都有一个可爱的想法，那就是：‘我可不可以利用两张网卡， 利用两个相同网域的 IP 来增加我这部主机的网路流量’？事实上这是一个可行的方案， 不过必须要透过许多的设定来达成，若您有需求的话，可以参考网中人大哥写的这一篇：
  • 频宽负载平衡 (http://www.study-area.org/tips/multipath.htm)
如果只是单纯的以为设定好两张网卡的 IP 在同一个网域而已，那您可就大错特错了～ 为什么呢？还记得我们在路由表规则里面提过网路封包的传递主要是依据主机内的路由表规则吧！ 那如果你有两张网路卡时，假设：
  • eth0 : 192.168.0.100
  • eth1 : 192.168.0.200
那你的路由规则会是如何呢？理论上会变成这样：
[root@linux ~]# route -n
Kernel IP routing table
Destination     Gateway   Genmask         Flags Metric Ref   Use Iface
192.168.0.0     0.0.0.0   255.255.255.0   U     0      0       0 eth1
192.168.0.0     0.0.0.0   255.255.255.0   U     0      0       0 eth0
也就是说，当要传送到 192.168.0.0/24 的网域时，都只会透过第一条规则 ，也就是透过 eth1 来传出去，而不管是由 eth0 还是由 eth1 进来的网路封包都会透过 eth1 来回传，这可能会造成一些问题， 尤其是一些防火墙的规则方面，很可能会发生一些严重的错误， 如此一来，根本没有办法达成负载平衡，也不会有增加网路流量的效果！ 更惨的是，还可能发生封包传递错误的情况呐！所以说，同一部主机上面设定相同网域的 IP 时， 得要特别留意你的路由规则，一般来说， 不应该设定同一的网段的不同 IP 在同一部主机上面。 例如上面的案例就是一个不好的示范啊！
大标题的图示 路由器架设
在同一的区域网路里面可以透过广播 (broadcast) 了解到 MAC 与 IP 的解析，然后透过 MAC 对 MAC 来传送资料封包， 在不同的网域里头就得要透过路由器的帮忙。那么什么是路由器？他的主要功能是什么？ 底下我们就来聊一聊！

小标题的图示 什么是路由器
既然主机想要将资料传送到不同的网域时得透过路由器的帮忙，所以啦，路由器的主要功能就是： ‘转递网路封包’啰！ 也就是说，路由器会分析来源端封包的 IP 表头，找出目标的 IP 后，透过路由器本身的路由表 (routing table) 将这个封包向下一个目标 (next hop) 传送。这就是路由器的功能。

那么路由器的功能可以如何达成呢？目前有两种方法可以达成：
  • 硬体功能：例如 Cisco, IBM, 3Com 等公司都有生产硬体路由器，这些路由器内有嵌入式的作业系统， 可以负责不同网域间的封包转译与转递等功能；
  • 软体功能：例如 Linux 这个作业系统的核心就有提供封包转递的能力。
高阶的路由器可以连结不同的硬体设备，并且可以转译很多不同的封包格式，通常....价格也不便宜啊！ 在这个章节里面，我们并没有要探讨这么高阶的咚咚，仅讨论在乙太网路里头最简单的路由器功能： 连接两个不同的网域。嘿嘿！这个功能 Linux 就可以达成了！ 就如同路由表是由 Linux 的核心功能所提供的，这个转递封包的能力也是 Linux 核心所提供， 那如何启动这个封包转递呢？很简单啊，只要这样做即可：
[root@linux ~]# echo "1" > /proc/sys/net/ipv4/ip_forward
上面这个动作就在打开 Linux 核心的封包转递能力。你可以将上述的指令写入 /etc/rc.d/rc.local 当中， 以使 Linux 可以在开机的时候就启动封包转递的功能， 也可以透过修改 /etc/sysctl.conf 来达成开机启动封包转递：
[root@linux ~]# vi /etc/sysctl.conf
# 将底下这个设定值修改正确即可！
net.ipv4.ip_forward = 1

[root@linux ~]# sysctl -p  <==立刻让该设定生效
sysctl 这个指令是在核心工作时用来直接修改核心参数的一个指令，更多的功能可以参考 man sysctl 查询。 不要怀疑！只要这个动作，你的 Linux 就具有最简单的路由器功能了。 而由于 Linux 路由器的路由表设定方法的不同，通常路由器规划其路由的方式就有两种：
  • 静态路由：直接以类似 route 这个指令来直接设定路由表到核心功能当中，设定值只要与网域环境相符即可。 不过，当你的网域有变化时，路由器就得要重新设定；

  • 动态路由：透过类似 zebra 软体的功能，这些软体可以安装在 Linux 路由器上， 而这些软体可以动态的侦测网域的变化，而直接修改 Linux 核心的路由表资讯， 你无须手动以 route 来修改你的路由表资讯喔！
了解了路由器之后，接下来你可能需要了解到什么是 NAT (Network Address Translation, 网路位址转译) 主机， NAT 是啥？其实 IP 分享器就是最简单的 NAT 主机啦！嘿嘿，了解了吗？没错， NAT 可以达成 IP 分享的功能， 而 NAT 本身就是一个路由器，但 NAT 比路由器多了一个‘ IP 转换’的功能。怎么说呢？
  • 一般来说，路由器会有两个网路介面，透过路由器本身的 IP 转递功能让两个网域可以互相沟通网路封包。 那如果两个介面一边是公共 IP (public IP) 但一边是私有 IP (private IP) 呢？ 由于私有 IP 不能直接与公共 IP 沟通其路由资讯，此时就得要额外的‘ IP 转译’功能了；

  • Linux 的 NAT 主机可以透过修改封包的 IP 表头资料之来源或目标 IP ，让来自私有 IP 的封包可以转成 NAT 主机的公共 IP ，就可以连上 Internet ！
所以说， 当路由器两端的网域分别是 Public 与 Private IP 时，才需要 NAT 的功能！ NAT 功能我们会在防火墙时谈及，这个章节仅谈论一下路由器而已啊！ ^_^

小标题的图示 何时需要路由器？
一般来说，电脑数量小于数十部的小型企业是无须路由器的，只需要利用 hub/switch 串接各部电脑， 然后透过单一线路连接到 Internet 上即可。不过，如果是超过数百部电脑的大型企业环境， 由于他们的环境通常需要考虑如下的状况，因此才需要路由器的架设：
  • 实体线路之布线及效能的考量：
    在一栋大楼的不同楼层要串接所有的电脑可能有点难度，那可以透过每个楼层架设一部路由器， 并将每个楼层路由器相连接，就能够简单的管理各楼层的网路； 此外，如果各楼层不想架设路由器，而是直接以网路线串接各楼层的 hub/switch 时， 那由于同一网域的资料是透过广播来传递的，那当整个大楼的某一部电脑在广播时， 所有的电脑将会予以回应，哇！会造成大楼内网路效能的问题；所以架设路由器将实体线路分隔， 就有助于这方面的网路效能；

  • 部门独立与保护资料的考量：
    在阅读过网路基础章节后，您就会晓得， 只要实体线路是连接在一起的，那么当资料透过广播时，你就可以透过类似 tcpdump 的指令来监听封包资料， 并且予以窃取～所以，如果你的部门之间的资料可能需要独立， 或者是某些重要的资料必须要在公司内部也予以保护时，可以将那些重要的电脑放到一个独立的实体网域， 并额外加设防火墙、路由器等连接上公司内部的网域。
路由器就只是一个设备，要如何使用端看您的网路环境的规划！上面仅是举出一些应用案例。 底下我们先就架设一个静态路由的路由器来玩一玩吧！

小标题的图示 静态路由之路由器
假设在贵公司的网路环境当中，除了一般职员的工作用电脑是直接连接到对外的路由器来连结 Internet， 在内部其实还有一个部门需要较安全的独立环境，因此这部份的网路规划可能是这样的情况：

静态路由之路由器架构示意图
图一、静态路由之路由器架构示意图

以上图的架构来说，这家公司主要有两个 C class 的网域，分别是 192.168.0.0/24 及 192.168.10.0/24 ， 其中 192.168.0.0/24 是用来做为一般员工连接网际网路用的，至于 192.168.10.0/24 则是给特殊的部门用的。PC1 代表的是一般员工的电脑， PC2 及 PC3, PC4 则是特殊部门的工作用电脑， Linux Router 则是这个特殊部门用来连接到公司内部网域的路由器。在这样的架构下， 该特殊部门的封包就能够具有基础的保护了。

由图一你也不难发现，只要是具有路由器功能的设备 (Router A, Linux Router) 都会具有两个以上的介面， 分别用来沟通不同的网域，同时该路由器也都会具有一个预设路由啊！ ^_^！ 另外，你还可以加上一些防火墙的软体在 Linux Router 上， 以保护 PC2~PC4 的内部电脑呢！

在 Router A 的部分，由于他具有 Public 与 Private IP ，所以这部 Router 必须要具有 NAT 的功能， 这个未来我们再介绍。今日的重点就在于 Linux Router 那个玩意儿！在该主机下， 最好配备两张网卡，一张给 192.168.0.100，另一张给 192.168.10.254 这个 IP。 这部 Linux Router 的设定简单的要命喔！你可以这样做的：

  • Linux Router
    在这部主机内需要有两张网卡，鸟哥在这里将他定义为：
    • eth0: 192.168.10.254
    • eth1: 192.168.0.100
    那如何设定呢？这样做就对了：
    1. 先处理 eth0
[root@linux ~]# vi /etc/sysconfig/network-scripts/ifcfg-eth0
DEVICE=eth0
BOOTPROTO=static
BROADCAST=192.168.10.255
IPADDR=192.168.10.254
NETMASK=255.255.255.0
NETWORK=192.168.10.0
ONBOOT=yes

2. 再先处理 eth1
[root@linux ~]# vi /etc/sysconfig/network-scripts/ifcfg-eth1
DEVICE=eth1
BOOTPROTO=static
BROADCAST=192.168.0.255
IPADDR=192.168.0.100
NETMASK=255.255.255.0
NETWORK=192.168.0.0
GATEWAY=192.168.0.254    <==这个设定值很重要喔！
ONBOOT=yes

3. 启动 IP 转递
[root@linux ~]# echo "1" > /proc/sys/net/ipv4/ip_forward
# 上述指令如果没有问题，将他加入 /etc/rc.d/rc.local 当中去！

4. 重新启动网路，并且观察路由
[root@linux ~]# /etc/init.d/network restart
[root@linux ~]# route -n
Kernel IP routing table
Destination     Gateway        Genmask         Flags Metric Ref Use Iface
192.168.0.0     0.0.0.0        255.255.255.0   U     0      0     0 eth1
192.168.10.0    0.0.0.0        255.255.255.0   U     0      0     0 eth0
127.0.0.0       0.0.0.0        255.0.0.0       U     0      0     0 lo
0.0.0.0         192.168.0.254  0.0.0.0         UG    0      0     0 eth1
    有够简单吧！这样你的 Linux Router 就 OK 了呐！接下来则是 PC2 来作为范例。

  • 受保护的网域，以 PC2 为例：
    不论你的 PC2 是哪一种作业系统，你的环境都应该是这样的：
    • IP: 192.168.10.20
    • netmask: 255.255.255.0
    • network: 192.168.10.0
    • broadcast: 192.168.10.255
    • gateway: 192.168.10.254
    以 Linux 作业系统为例，并且 PC2 仅有 eth0 一张网卡时，他的设定是这样的：
    [root@linux ~]# vi /etc/sysconfig/network-scripts/ifcfg-eth0
DEVICE=eth0
BOOTPROTO=static
BROADCAST=192.168.10.255
IPADDR=192.168.10.20
NETMASK=255.255.255.0
NETWORK=192.168.10.0
GATEWAY=192.168.10.254   <==这个设定最重要啦！
ONBOOT=yes

[root@linux ~]# /etc/init.d/network restart
[root@linux ~]# route -n
Kernel IP routing table
Destination   Gateway         Genmask         Flags Metric Ref  Use Iface
192.168.10.0  0.0.0.0         255.255.255.0   U     0      0      0 eth0
127.0.0.0     0.0.0.0         255.0.0.0       U     0      0      0 lo
0.0.0.0       192.168.10.254  0.0.0.0         UG    0      0      0 eth0
  • Router A 的新增路由规则：
    在这样的架构下，您的 PC2 已经可以连接上 Internet 了！只不过，当封包由 Internet 传回来时， 由于 Router A 并没有连接到 192.168.10.0/24 网域的路由规则，所以该封包‘会遗失’喔！那就麻烦了～ 所以，你的 Router A 必须要额外增加一条规则，这条规则是‘将目标为 192.168.10.0/24 的封包传送给 192.168.0.100 去处理’，假设 Router A 为 Linux 系统时，那他应该要这样：
    [root@linux ~]# route add -net 192.168.10.0 netmask 255.255.255.0 \
>  gw 192.168.0.100

[root@linux ~]# route -n
Destination   Gateway        Genmask         Flags Metric Ref  Use Iface
192.168.10.0  192.168.0.100  255.255.255.0   UG    0      0      0 eth0
# 你应该会发现上头这一条规则存在才行！
    如此一来，你的 Router A 及 Linux Router 之间就可以沟通，并且可以传递 192.168.10.0/24 的网域呐！

  • PC1 直接与 PC2 的沟通方式：
    在图一当中，你会发现那个 PC1 必须要将预设路由设定为 192.168.0.254 ， 所以当 PC1 要与 PC2 沟通时，封包将由：

    PC1 --> Router A --> Linux Router --> PC2

    不过，在图一当中我们知道其实 PC1 与 PC2 同时接到 Linux Router 上嘛！ 所以 PC1 其实可以直接加入一条路由规则，规定当 192.168.10.0/24 的封包目标时， 他可以直接传到 Linux Router 上即可，那可以这样做：
    [root@linux ~]# route add -net 192.168.10.0 netmask 255.255.255.0 \
>  gw 192.168.0.100
    最后只要 PC2 使用 ping 可以连到 PC1，同样的， PC1 也可以 ping 到 PC2 的话， 就表示你的设定是 OK 的啦！嘿嘿！搞定！而透过这样的设定方式，您也可以发现到一件事， 那就是：‘路由是双向的，你必须要了解出去的路由与回来时的规则’。 举例来说，在预设的情况下 (Router A 与 PC1 都没有额外的路由设定时)，其实封包是可以由 PC2 连线到 PC1 的，但是 PC1 却没有相关的路由可以回应到 PC2 ～所以上头才会要您在 Router A 或者是 PC1 上面设定额外的路由规则啊！这样说，了了吧？ ^_^

    所以说，用 Linux 作一个静态路由的 Router 很简单吧！以上面的案例来说，你在 Linux Router 上面几乎没有作什么额外的工作，只要将网路 IP 与网路介面对应好启动，然后加上 IP Forward 的功能， 让你的 Linux 核心支援封包转递，然后其他的工作咱们的 Linux kernel 就主动帮你搞定了！ 真是好简单！ ^_^

    不过这里必须要提醒的是，如果你的 Linux Router 有设定防火墙的话， 而且还有设定类似 NAT 主机的 IP 伪装技术，那可得特别留意，因为还可能会造成路由误判的问题～ 上述的 Linux Router 当中‘并没有使用到任何 NAT 的功能’喔！特别给他留意到！

    • 小标题的图示 动态路由之路由器设定：zebra
    如前所述，系统管理员可以利用 route 这个指令手动的将路由规则加入核心当中，这个方式称为静态路由。 动态路由同样是将路由规则加入核心当中，只是这个加入的动作交由软体服务 (daemon) 自动来执行， 在 Linux 上面常见的路由服务就是 zebra 这个套件所提供的。

    动态路由通常是用在路由器与路由器之间的沟通，所以要让您的路由器具有动态路由的功能， 你必须要了解到对方路由器上面所提供的动态路由协定才行，这样两部路由器才能够透过该协定来沟通彼此的路由规则。 目前常见的动态路由协定有：RIPv1, RIPv2, OSPF, BGP 等等， zebra 都有支援这些路由协定喔！

    在 CentOS 上头，我们使用 quagga 这个套件来提供 zebra ，因为 quagga 是更新 zebra 而来的， 事实上，你可以说， quagga 就是 zebra 啦！赶紧安装他先：
    [root@linux ~]# yum install quagga
[root@linux ~]# ls -l /etc/quagga
-rw-r--r--  1 root   root      410 Jun  2 02:38 ripd.conf.sample
-rw-r-----  1 quagga quagga     30 Aug 29 10:50 zebra.conf
-rw-r--r--  1 root   root      373 Jun  2 02:38 zebra.conf.sample
.....其他省略.....
    这个套件所提供的各项动态路由协定都放置到 /etc/quagga/ 目录内，底下我们以较为简单的 RIPv2 协定来处理动态路由， 不过你得要注意的是，不论你要启动什么动态路由协定，那个 zebra 都必须要先启动才行！ 这是因为：
    • zebra 这个 daemon 的功能在更新核心的路由规则；
    • RIP 这个 daemon 则是在向附近的其他 Router 沟通协调路由规则的传送与否。
    而各个路由服务的设定档都必须要以 /etc/quagga/*.conf 的档名来储存才行，如上表我们可以发现 zebra 这个服务是有设定好了，不过 ripd 的档名却不是 .conf 结尾。所以我们必须要额外作些设定才行。 而假设我们的网路连结如下图二所示：

    动态路由的简易图示
    图二、动态路由的简易图示

    这两部 Linux Router 分别负责不同的网域，且可以透过 192.168.0.0/24 这个网域来沟通。 在没有设定额外路由规则的情况下，那个 PC1 与 PC2 是无法沟通的！另外， zebra 必须要同时安装在两部 Linux Router 上头才行， 而且我们只要设定好这两部主机的网路介面 (eth0, eth1) 后，不需要手动输入额外的路由设定喔！可以透过 RIP 这个路由协定来搞定的！

  • 设定 zebra
    我们先设定图二右手边那一部 Linux Router，关于 zebra.conf 你可以这样设定的：
    1. 先设定 zebra 并且启动 zebra
[root@linux ~]# vi /etc/quagga/zebra.conf
hostname linux.router1  <==给予这个路由器一个主机名称，随便取！
password linux1         <==给予一个密码！
enable password iinux1  <==将这个密码生效！
log file zebra.log      <==将所有 zebra 产生的资讯存到登录档中

[root@linux ~]# /etc/init.d/zebra start
[root@linux ~]# netstat -tunlp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address   Foreign Address   State   PID/Program name
tcp        0      0 127.0.0.1:2601  0.0.0.0:*         LISTEN  6422/zebra
    仔细看，由于 zebra 这个服务的任务主要是在修改 Linux 系统核心内的路由， 所以他仅监听本机介面而已，并不会监听外部的介面才对！另外，在 zebra.conf 这个档案当中， 我们所设定的那个密码是有作用的喔！可以让我们登入 zebra 这套软体呢！ 好了，我们来查一查这个 2601 的 port 是否正确的启动的呢？
    [root@linux ~]# telnet localhost 2601
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.

Hello, this is Quagga (version 0.98.3).
Copyright 1996-2005 Kunihiro Ishiguro, et al.

User Access Verification

Password: <==在这里输入刚刚你设定的密码啊！
linux.router1> <==在这边输入‘ ? ’就能够知道有多少指令可使用
  echo      Echo a message back to the vty
  enable    Turn on privileged mode command
  exit      Exit current mode and down to previous mode
  help      Description of the interactive help system
  list      Print command list
  quit      Exit current mode and down to previous mode
  show      Show running system information
  terminal  Set terminal line parameters
  who       Display who is on vty
linux.router1> list
  echo .MESSAGE
  enable
  exit
  help
  list
  quit
  show debugging zebra
  show history
  show interface [IFNAME]
  show ip forwarding
  show ip route
....其他省略....
linux.router1> show ip route
Codes: K - kernel route, C - connected, S - static, R - RIP, O - OSPF,
       I - ISIS, B - BGP, > - selected route, * - FIB route

K>* 0.0.0.0/0 via 192.168.0.254, eth0
C>* 127.0.0.0/8 is directly connected, lo
C>* 192.168.0.0/24 is directly connected, eth0
C>* 192.168.10.0/24 is directly connected, eth1
linux.router1> exit
Connection closed by foreign host.
    仔细看到，我们登入这个 zebra 的软体之后，可以输入‘help’或问号‘?’， zebra 就会显示出你能够执行的指令有哪些，比较常用的当然是查询路由规则啰！ 以‘ show ip route ’来查阅，结果可以发现目前的介面与预设路由都被显示出来了， 显示的结果当中，K 代表以 router 这个指令直接加入核心的路由规则，C 则代表你的网路介面相关的路由规则。

    事实上，如果你还想要增加额外的静态路由的话，也可以透过 zebra 而不必使用 route 指令呢！ 例如想要增加 10.0.0.0/24 给 eth0 来处理的话，可以这样做：
    [root@linux ~]# vi /etc/quagga/zebra.conf
# 新增底下这一行喔！
ip route 10.0.0.0/24 eth0

[root@linux ~]# /etc/init.d/zebra restart
[root@linux ~]# telnet localhost 2601
User Access Verification

Password: <==这里输入密码
linux.router1> show ip route
Codes: K - kernel route, C - connected, S - static, R - RIP, O - OSPF,
       I - ISIS, B - BGP, > - selected route, * - FIB route

K>* 0.0.0.0/0 via 192.168.0.254, eth0
S>* 10.0.0.0/24 [1/0] is directly connected, eth0
C>* 127.0.0.0/8 is directly connected, lo
C>* 192.168.0.0/24 is directly connected, eth0
C>* 192.168.10.0/24 is directly connected, eth1
    嘿嘿！立刻就会多出一笔路由的规则，而且最右边会显示 S，亦即是静态路由 (Static route) 的意思。 如此一来，我们系统管理员可就轻松多了！ 设定完 zebra 之后，接下来我们可以开始看看 ripd 这个服务啰！

  • 设定 ripd 服务
    ripd 这个服务可以在两部 Router 之间进行路由规则的交换与沟通， 当然啦，如果你的环境里面有类似 Cisco 或者是其他有提供 RIP 协定的路由器的话， 那么你当然也是可以透过这个 RIP 让您的 Linux Router 与其他硬体路由器互相沟通的呐！ 闲话少说，来设定 ripd 吧！
    [root@linux ~]# vi /etc/quagga/ripd.conf
hostname linux.router1  <==这里是设定 Router 的主机名称而已
password linux1         <==设定好你自己的密码喔！
router rip              <==启动 Router 的 rip 功能
network 192.168.0.0/24  <==针对这个网域来进行监听的动作！
network eth0            <==针对这个介面来进行监听的动作
network 192.168.10.0/24 <==针对这个网域来进行监听的动作！
network eth1            <==针对这个介面来进行监听的动作
version 2               <==启动的是 RIPv2 的服务
log stdout              <==直接在荧幕输出标准输出的资料

[root@linux ~]# /etc/init.d/ripd start

[root@linux ~]# netstat -tulnp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address  Foreign Address State  PID/Program name
tcp        0      0 0.0.0.0:2602   0.0.0.0:*       LISTEN 21373/ripd
    基本上，这样就设定完成一部路由器的 RIP 动态路由协定了！在上头 ripd.conf 的设定当中， 他会主动以 eth0 及 192.168.0.0/24 这个网域的功能来进行搜索，如此一来，未来你进行任何路由规则的变动， 或者是整个网域的主机 IP 进行更动，你将不需要重新到每部 Router 上更动！ 因为这些路由器会自动的更新他们自己的规则喔！嘿嘿！接下来，同样的动作请你到 图二左边那部 Linux Router 上面设定一下！ 因为整个设定的流程都一样，所以这里鸟哥就省略啦！

  • 检查 RIP 协定的沟通结果
    在两部 Linux Router 都设定妥当之后，你可以登入 zebra 去看这两部主机的路由更新结果喔！ 举例来说，鸟哥登入图二右边那部 Linux Router 后，并且登入 zebra ， 观察路由会是这样的情况：
    [root@linux ~]# telnet localhost 2601
User Access Verification

Password: <==不要忘记了密码啊！
linux.router1> show ip route
Codes: K - kernel route, C - connected, S - static, R - RIP, O - OSPF,
       B - BGP, > - selected route, * - FIB route

K>* 0.0.0.0/0 via 192.168.0.254, eth0
C>* 127.0.0.0/8 is directly connected, lo
C>* 192.168.0.0/24 is directly connected, eth0
R>* 192.168.5.0/24 [120/2] via 192.168.0.200, eth0, 00:06:48
C>* 192.168.10.0/24 is directly connected, eth1
    如果你有看到上述的字体，嘿嘿！那就是成功啦！那个最左边的 R 代表的是透过 RIP 通讯协定所设定的路由规则啦！ 如此一来，咱们的路由器设定就搞定啰～

    透过这个 zebra 以及 RIPv2 的路由协定的辅助，我们可以轻松的就将路由规则分享到附近区网的其他路由器上头， 比起单纯使用 route 去修改 Linux 的核心路由表，这个动作当然要快速很多！ 不过，如果是很小型的网路环境，那么不要使用这个 zebra 啊！因为有点多此一举的感觉。 如果您的企业环境真的有够大，那么玩一玩这个 zebra 配合一些动态路由协定，嘿嘿！也是可行的啦！
    • 大标题的图示 ARP Proxy 让路由器两端在同一网域
    如果你一开始设计的网路环境就是同一个 C class 的网域，例如 192.168.10.0/24 ， 后来因为某些因素必须要将某些主机搬到比较内部的环境中，例如图一的 PC2 ~ PC4 。 然后又因为某些因素，所以你不能变更 PC2 ~ PC4 的 IP ，也就是说，有点像底下这样的图示：

    路由器两边是同一网域的特殊状况
    图三、路由器两边是同一网域的特殊状况

    初次见面～看到眼睛快要掉下来哩！怎么会两边的主机都在同一个网域内？而且还被规定不能够更改原先的 IP 设定， .....真是一个头两个大啊～如此一来，在 Linux Router 两边要如何制作路由啊？好问题！真是好问题～ 因为 OSI 第三层网路层的路由是一条一条去设定比对的，所以如果两块网卡上面都是同一个网域的 IP 时， 就会发生错误。那如何处理啊？

    既然 OSI 第三层无法解决，那么可否以第二层的资料连接层来处理？看倌应该还记得 OSI 第二层最重要的就是那个 ARP 协定， 他可以用来进行 IP 与 MAC 的对应。那么由图三我们知道 PC1 要与 PC2 等主机沟通时，都需要透过 Linux Router ， 那有没有办法透过 ARP 告知整个网域内的电脑，要传送到 PC2~PC4 的封包都需要经过 Linux Router 呢？ 呵呵！好想法。你可以这样想：

    路由器两边是同一网域的特殊状况
    图四、路由器两边是同一网域的特殊状况

    也就是说：
    1. 当 Linux Router 的 eth1 那个网域主机想要连接到 PC2~PC4 的主机时，由 Linux Router 负责接收；
    2. 当 Linux Router 要传送资料到 PC2~PC4 时，务必要由 eth0 来传送；
    3. 当 Linux Router 要传送的资料为 192.168.10.0/24 ，但并非 PC2~PC4 时，需由 eth1 传送；
    4. 当 Linux Router 的 eth0 那个网域主机想要连接到 PC1 时，由 Lniux Router 负责接收。
    要达到 (1) 与 (4) 的要求并不难，我们可以透过 ARP Proxy 这玩意儿，啥是 ARP Proxy 呢？就是在 Linux Router 上面预先规定‘将 192.168.10.20, 192.168.10.30, 192.168.10.40 这三个 IP 的 MAC 都对应到 Linux Router 上！’由于是区域网路内，因此都是透过广播的方式达到 ARP 协定所需要的 IP 与 MAC 的对应，所以啦，每一部在 eth1 那端的主机都会‘误判’那三个 IP 是 Linux Router 所拥有， 这样就能够让封包传给 Linux Router 啦！

    再接下来，咱们的 Linux Router 必须要额外指定路由，设定：
    • 若目标是 PC2 ~ PC4 时，该路由必须要由 eth0 发送出去才行，
    • 若目标不为 PC2 ~ PC4 ，且目标在 192.168.10.0/24 的网域时，需由 eth0 发送出去才行。
    也就是说，你必须要指定路由规则当中，那个 PC2~PC4 具有优先选择权，然后其他的同网域封包才由 eth1 来传送。 这样就能够达成我们所想要的结局啦！^_^！看样子似乎很难，其实设定方面还挺简单的，你可以透过 arp 以及 route 这两个指令来达成喔！
    1. 先设定 ARP Proxy ，告知 eth1 所在网域 IP 与 MAC 的对应
[root@linux ~]# arp -i eth1 -s 192.168.10.20 00:11:12:13:14:15 pub
[root@linux ~]# arp -i eth1 -s 192.168.10.30 00:11:12:13:14:15 pub
[root@linux ~]# arp -i eth1 -s 192.168.10.40 00:11:12:13:14:15 pub
# 看图四的说明，我这里假设 eth1 的 MAC 是 00:11:12:13:14:15 啦！
[root@linux ~]# arp -i eth0 -s 192.168.10.50 00:01:02:03:04:05 pub
# 看图四的说明，我这里假设 eth0 的 MAC 是 00:01:02:03:04:05 啦！

[root@linux ~]# arp -n
Address             HWtype  HWaddress      Flags Mask       Iface
192.168.10.20       *       *              MP               eth1
192.168.10.30       *       *              MP               eth1
192.168.10.40       *       *              MP               eth1
192.168.10.50       *       *              MP               eth0
# 瞧！有三个 IP 都变成属于俺的 eth1 的啦！然后一个属于 eth0

2. 开始处理路由，需要清除掉 eth0 的路由，并且增加 PC2~PC4 的单机路由
[root@linux ~]# route del -net 192.168.10.0 netmask 255.255.255.0 eth0
[root@linux ~]# route add -host 192.168.10.20 eth0
[root@linux ~]# route add -host 192.168.10.30 eth0
[root@linux ~]# route add -host 192.168.10.40 eth0
# 这样就设定妥当啦！将你的路由规划好啰！

[root@linux ~]# route -n
Kernel IP routing table
Destination     Gateway  Genmask         Flags Metric Ref    Use Iface
192.168.10.20   0.0.0.0  255.255.255.255 UH    0      0        0 eth0
192.168.10.30   0.0.0.0  255.255.255.255 UH    0      0        0 eth0
192.168.10.40   0.0.0.0  255.255.255.255 UH    0      0        0 eth0
192.168.10.0    0.0.0.0  255.255.255.0   U     0      0        0 eth1
# 看到上面这一行，虽然我的两块网卡都是在 192.168.10.0/24 ，
# 不过真正针对整个网域传送的，仅有 eth1 那一块的意思！
    瞧！这样一来，你的 PC1 就可以 ping 到 PC2~PC4 的主机了！资料的传输上面也没有问题。 这个作法是相当有帮助的呐！对于预设架构不想更动的环境来说。 ^_^！ 不过，由这个案例你也可以清楚的知道，能不能连线其实与路由的关系才大哩！ 而路由是双向的，你必须要考量到这个封包如何回来的问题喔！
    大标题的图示 重点回顾
    • 网路卡的代号为 eth0, eth1, eth2...，而第一张网路卡的第一个虚拟介面为 eth0:0 ...
    • 网路卡的参数可使用 ifconfig 直接设定，亦可使用设定档如 /etc/sysconfig/network-scripts/ifcfg-ethn 来设定；
    • 路由是双向的，所以由网路封包发送处发送到目标的路由规划，必须要考虑回程时是否具有相对的路由， 否则该封包可能会‘遗失’；
    • 每部主机都有自己的路由表，此路由表 (routing table) 是作为封包传送时的路径依据；
    • 每部可对外 Internet 传送封包的主机，其路由资讯中应有一个预设路由 (default gateway)；
    • 要让 Linux 作为 Router 最重要的是启动核心的 IP Forward 功能；
    • 重复路由可能会让你的网路封包传递到错误的方向；
    • 动态路由通常是用在两个 Router 之间沟通彼此的路由规则用的，常见的 Linux 上的动态路由套件为 zebra ；
    • arp proxy 可以透过 arp 与 route 的功能，让路由器两端都在同一个网段内；
    • 一般来说，路由器上都会有两个以上的网路介面
    • 事实上，Router 除了作为路由转换之外，在 Router 上面架设防火墙，亦可在企业内部再分隔出多个需要安全 (Security) 的单位资料的区隔！
    大标题的图示 课后练习
    • 请问您如何将您的 eth0 这个介面修改成为 192.168.100.2 在网域 192.168.100.0/25 之内的网路参数内容？
      • 因为 192.168.100.0/25 的 netmask 为 255.255.255.128 ，所以可以这样做：
      ifconfig eth0 192.168.100.2 netmask 255.255.255.128 up
      这样即可！如果尚须其他的参数，则需要以档案形式来下达，如 vi /etc/sysconfig/network-scripts/ifcfg-eth0，并修改为：
      DEVICE=eth0
      ONBOOT=yes
      BOOTPROTO=static
      IPADDR=192.168.100.2
      NETMASK=255.255.255.128
      NETWORK=192.168.100.0
      BROADCAST=192.168.100.127
    • 请手动设定 eth0:1 这个虚拟介面，使成为网路参数： 192.168.200.2, 网域在 192.168.200.0/24。
      • ifconfig eth0:1 192.168.200.2 up
    • 如何观察路由表？
      • route -n 即可查阅！注意到 0.0.0.0 那个目标(default gateway)。
    • 如何启动 Linux 的 IP Forward 功能？
      • 直接以‘echo "1" > /proc/sys/net/ipv4/ip_forward ’即可！
    • 假设您是一个学校单位的资讯管理员，学校内有 200 部电脑，奉上面大头的旨意，必须要将 200 部电脑分为 4 个 Subnet ，请问您应该如何布线(请画出示意图)？而这 4 个 Subnet 的网路参数如何选择(请自行选择)？而是否需要 Router ？如果需要的话，假设每个 Router 仅能有两个网路实体介面，那么该如何布线？(注：不要使用虚拟介面)
    • 假设你想要连接到 168.95.1.1 ，那么你该如何判断你经过‘多少个’节点？
      • 可以使用 traceroute 168.95.1.1 来分析每个节点的传送资讯，也可以透过 ping 168.95.1.1 所回传的那个 ttl 值判断节点数量。
    • 万一您的网路有点停顿，发现可能是网路上某个节点出现问题，您应该如何确认是哪一部 Router 出问题？
      • 就利用 traceroute 吧！
    大标题的图示 参考资料
    • 动态路由套件 Quagga: http://www.quagga.net
    • 动态路由套件 zebra: http://www.zebra.org
    • 网中人写的‘频宽负载平衡’：http://www.study-area.org/tips/multipath.htm
    • Ben 哥写的‘实作 Linux 动态路由’：http://linux.vbird.org/somepaper/20060714-linux_cisco_route.pdf
    • quagga 官方操作文件：http://www.quagga.net/docs/quagga.pdf
    • 酷学园的 ARP Proxy：http://phorum.study-area.org/viewtopic.htm?t=5619
    • 酷学园 ericshei 的 ARP Proxy 分享：http://phorum.study-area.org/viewtopic.htm?t=22943
    2002/08/09：第一次完成日期！
    2003/08/22：重新编辑文章，并增加重点回顾与课后练习
    2006/08/21：将旧的文章移动到 此处。
    2006/08/30：加入了 zebra 以及 ARP Proxy 等与 Router 比较相关的议题！
    2002/08/08以来统计人数


鸟哥的 Linux 私房菜 -- 认识网路安全

为取得较佳浏览结果，请爱用 firefox 浏览本网页

认识网路安全
切换解析度为 800x600
最近更新日期：2006/09/06
在介绍了‘网路基础’、‘限制连线 port number ’、‘网路升级套件’之后，再来准备要上 Internet 了吗？！如果只是想要上 Internet 去浏览，那么自然没有问题，如果是想要对 Internet 开放网路服务，那么最好还是先认识一下网路安全会比较好一些。什么？套件也更新了， port 也关闭了，还需要认识什么网路安全啊？！呵呵！当然啦！因为难保我们的主机不会被新的套件漏洞以及阻断式攻击 (DoS)所困扰啊！在这个章节里面，我们会稍微介绍一些基础的网路防护观念，尤其是系统管理员应该要做的事情呐！

1. 网路封包连线进入主机的流程
    1.1 封包进入主机的流程
    1.2 主机能作的保护：权限设定、套件更新、SELinux
 2. 主机的细部权限规划：ACL 的使用
    2.1 什么是 ACL ？
    2.2 如何启动 ACL？
    2.3 ACL 的设定技巧： getfacl , setfacl
 3. 一些常见的攻击手法与主机的保护方式
4. 被入侵后的修复工作
    4.1 网管人员的额外技巧与任务
    4.2 入侵恢复工作
 5. 重点回顾
6. 课后练习
7. 参考资料
8. 针对本文的建议：http://phorum.vbird.org/viewtopic.htm?p=114062
大标题的图示 网路封包连线进入主机的流程
在这一章当中，我们要讨论的是，当来自一个网路上的连线要求想进入我们的主机时， 这个网路封包在进入主机实际取得资料的整个流程是如何？了解了整个流程之后， 你才会发现：原来系统操作的基本概念是如此的重要！ 而你也才会了解要如何保护你的主机安全呐！闲话少说，咱们赶紧来瞧一瞧先。

小标题的图示 封包进入主机的流程
在网路基础章节当中我们谈到过目前的网路架构主要是 TCP/IP 为主， 而绝大部分的网路连线是双向的，其中又以 TCP 封包为代表。 另外，根据 Server/Client 的连线方向与 TCP/IP 的概念，我们会知道建立一条可靠的网路连线需要一组 Socket Pair 的辅助， 亦即成对的来源与目标之 IP 与 port 啰，以使连线的两端可以顺利的连接到相对的应用软体上。

上面谈到的这些都是属于网路的基础概念，在这里我们要谈的是，那么要让这个 TCP 封包顺利的进入到 Linux 主机上， 然后使用 port 所对应的软体来存取系统的档案系统资源时，还得要经过哪些关卡呢？ 举例来说，如果你的 Linux 主机有开启 WWW 的 port 80 网路服务，而 port 80 是由一个名称为 httpd 的程式所启动的，这个程式的设定档为 httpd.conf ，那么 Client 的连线要进入到你 Linux 主机的 WWW 时， 会经过什么阶段呢？基本上，会经过如下图的几个阶段：

网路封包进入本机的流程顺序
图一、网路封包进入本机的流程顺序

  1. 封包过滤防火墙：IP Filtering 或 Net Filter
    要进入 Linux 本机的封包都会先通过 Linux 核心的预设防火墙，就是称为 IP Filter 或 Net Filter 的咚咚， 简单的说，就是 iptables 这个软体所提供的防火墙功能。iptables 这个 Linux 预设的防火墙软体可以针对网路封包的 IP, port, MAC, 以及连线状态如 SYN, ACK 等资料进行分析， 以过滤不受欢迎的网路封包呢！举例来说，如果有个 IP 为 aaa.bbb.ccc.ddd 是个恶意网站来源， 那你就可以透过 iptables 抵挡来自该 IP 的网路封包的连线，以达到基本的主机防火墙功能。 这部份我们会在下一章深入了解。

  2. 第二层防火墙：TCP Wrappers
    通过 IP Filter 之后，网路封包会开始接受 Super daemons 及 TCP_Wrappers 的检验，那个是什么呢？ 呵呵！说穿了就是 /etc/hosts.allow 与 /etc/hosts.deny 的设定档功能啰。 这个功能也是针对 TCP 的 Header 进行再次的分析，同样你可以设定一些机制来抵制某些 IP 或 Port ，好让来源端的封包被丢弃或通过检验；

  3. 服务 (daemon) 的功能：
    前面这两个动作基本上是 Linux 预设的功能，而这第三个步骤就是属于软体功能了。 举例来说，你可以在 httpd.conf 这个设定档之内规范某些 IP 来源不能使用 httpd 这个服务来取得主机的资料， 那么即使该 IP 通过前面两层的过滤，他依旧无法取得主机的资源喔！但要注意的是， 如果 httpd 这支程式本来就有问题的话，那么 client 端将可直接利用 httpd 软体的漏洞来入侵主机，而不需要取得主机内 root 的密码！因此， 要小心这些启动在网际网路上面的软体喔！ 所以前一章网路升级套件是很重要的！

  4. 使用主机的档案系统资源：
    想一想，你使用浏览器连接到 WWW 主机最主要的目的是什么？当然就是读取主机的 WWW 资料啦！ 那 WWW 资料是啥？就是档案啊！^_^！所以，最终网路封包其实是要向主机要求档案系统的资料啦。 我们这里假设你要使用 httpd 这支程式来取得系统的档案资料，但 httpd 预设是由一个系统帐号名称为 httpd 来启动的，所以：你的网页资料的权限当然就是要让 httpd 这支程式可以读取才行啊！如果你前面三关的设定都 OK ，最终权限设定错误， 使用者依旧无法浏览你的网页资料的。
在这些步骤之外，我们的 Linux 以及相关的软体都可能还会支援登录档记录的功能， 为了记录历史历程，以方便管理者在未来的错误查询与入侵侦测，良好的分析登录档的习惯是一定要建立的， 尤其是 /var/log/messages 与 /var/log/secure 这些个档案！ 虽然各大主要 Linux distribution 大多有推出适合他们自己的登录档分析套件，例如 CentOS 的 logwatch ，不过毕竟该套件并不见得适合所有的 distributions ，所以鸟哥尝试自己写了一个 logfile.sh 的 shell script，您可以在底下的网址下载该程式：
  • http://linux.vbird.org/download/index.htm?action=detail&fileid=60
好了，那么根据这些流程，你觉得我们可以如何保护自己的主机呢？

小标题的图示 主机能作的保护： 权限设定、套件更新、SELinux
在基础篇里面的前面几章我们谈到很多关于档案权限方面的注意事项， 关于目录最重要的是那个 w (可写入)的权限，至于对档案来说，那个 r (可读取) 也是非常重要的！而由前一小节的图一我们也知道网路服务其实就是提供主机的档案资源给 client 端来查阅就是了。

根据这样的说法，你可以知道，如果你有某些不想要被读取的资料在主机上面的话， 那么将该资料的权限设定为不能被某些网路服务读取的情况， 就能达到最基础的保护了。所以您说档案权限重不重要啊！很重要的！不是吗？

  • 权限的重要性
    鸟哥常常在上课的时候会开玩笑，说如果你只要下达一个指令，那你的系统就得要重新安装了！ 那就是：‘chmod -R 777 /’，这个指令可是‘极度危险’的喔！为何呢？因为系统上面本来就有很多需要被保护的资料， 例如 /etc/shadow 以及 /etc/passwd 等，尤其是 shadow 密码档案。虽然里头是加密过的资料， 不过别忘了，现在的 PC 速度实在太快了，而网路上又有太多暴力破解密码的软体， 如果你的 /etc/shadow 被取得后，嘿嘿！你的密码其实就算‘公开了’。那万一你有开放某些网路服务的话， 例如可连线登入的 ssh 服务或 mail 服务，那任何人都可以使用你的主机来登入， 或者是利用你的主机来收你主机上的其他使用者的信，唉！糗大了！

    再者，很多朋友在主机上面常常喜欢建立权限为 drwxrwxrwx 的目录来提供使用者上传资料， 这实在是很危险ㄟ！如果使用者的功力够高的话，他可以在网路软体如 httpd 的使用上， 来建立一些危险的 script 在你的 drwxrwxrwx 的目录中，那如果你不小心进入到该目录， 又不小心执行了该恶意使用者所建立的 script ，恭喜您～中标！

    另外，如果你是学校老师，为了公平与同学本身的权益起见，你会希望同学们所上传的资料不会被其他同学所窃取。 那么你该如何进行权限的规范？如果单纯的让学生通通上传到单一目录，并且没有指定特殊的权限时， 不但某些同学的资料可能会被窃取与复制，更惨的是，可能资料会被某些恶意同学所删除！ 那可就麻烦了！所以，权限的设定真的很重要啦！

    而除了传统的权限之外，事实上目前 Linux 支援一种称为 ACL 的额外权限控制方式， 也支援更强化安全的 SELinux ，这两个小东西我们会在本章的后面部分继续介绍。

  • 严格的密码的重要性：
    很多使用者为了方便记忆，老是跟系统管理员说：‘喂！我的密码可不可以简单一点啊？ 太麻烦的我都记不住！’如果您是那个可怜的系统管理员，你该如何回应？ 如果你大开方便之门，未来可是后患无穷的！举例来说，如果你的 mail server 上面某个使用者帐号为 alex 好了，那么他的 email address 将会是：‘ alex@your.host.name ’， 那这个使用者由于使用习惯不良，他将他的 mail address 留在 Internet 上，所以很多人都知道这个 address。

    知道就知道，会有什么了不起吗？呵呵！了不起的很！如果有个坏家伙，他想要偷偷的收取 alex 的信， 那他就在他的收信软体上面偷偷填上你的主机，然后偷偷输入帐号 alex 并且输入密码为 alex ， 如果你真的帮 alex 这个使用者建立同名的密码，哈哈！系啊(请台语发音，谢谢)！这个 alex 永远都收不到他的信了！

    这算还好呐！如果你有开放远端连线登入的服务，那么坏家伙就可以利用 alex 这个帐号与密码来登入你的主机， 如果你没有做好权限规划的话，哇！整部主机的资料被偷光光！那可有的瞧的了！ 所以，您说密码不重要吗？我可不认为！

  • 套件更新的重要性：
    很多朋友由于网路文章的关系，可能会拿比较旧的 Linux distribution 来作为架站的平台， 举例来说，使用 Red Hat 9 来架站的朋友想必还是不少的。如果你真的利用旧的版本来进行网站的架设， 而且还对 Internet 开放服务的话，那么你的主机将会在不到一天的时间内被‘绑架’的！ 为什么呢？因为套件软体都是可能有漏洞的，如果你没有补洞的话.....

    有些朋友认为：‘我的密码设定的严格一点，应该就好了吧？’真的吗？让我们瞧一瞧图一的流程， 第三个步骤是否使用到 httpd 这个程式的功能了，万一这个程式有问题怎么办？ 举例来说，酷学园的朋友曾经在他举办的研讨会当中露一手如何绑架没有修补漏洞的 Linux 系统， 利用的就是 httpd 这个软体的漏洞，整个入侵的过程没有花费一分钟以上！ 而且他取到的可是 root 的权限呐！不是什么阿猫阿狗的喔！ 而且他完全没有输入任何密码，使用的入侵程式则是由 Internet 上面取得的。

    在上头这个例子鸟哥不是要说该朋友的功力，而是要提醒大家，套件修补的重要性！ 要取得破解程式的管道实在太多了，但如果你都有在最短的时间内取得套件的更新的话， 那么至少该破解程式对你的系统就不会生效！你的主机自然就会比较安全些。 而这个问题在所有的作业系统上面都是存在的！ Windows 系统也是每个月必须要推出他们的套件程式修补， 否则一样会被攻击或入侵啊！不过 Linux 的套件漏洞修补要快多了！

  • SELinux
    在最新的 Linux 2.6 版核心上所发展的 distributions 目前预设都会启动一个名为 SELinux 的核心模组， 这个 SELinux 必须要在开机载入核心时就得要载入，那这个玩意儿是啥咚咚？ SELinux 是 Security Enhanced Linux (安全加强的 Linux) 的缩写， 他并不是一个防火墙的软体，而是一个‘针对档案系统权限作更细部规划的一个模组’。

    传统的 Linux 权限是分为三种身份 (owner, group, others) 以及三种权限 (r, w, x)， 但事实上，这三种身份的三种权限组合并无法有效的管理所有系统上的 daemon 存取资料时所需要的行为。 因此美国国家安全局便发展出这个可以更细部规划档案权限功能的 SELinux 了。

    由于 SELinux 主要是进行档案系统的细部权限设定，所以想要使用 SELinux 的配置时， 需要对 Linux 的档案系统以及基础的作业系统概念要很清楚，否则将会使得很多的网路服务无法正确的启用系统资源， 导致你的主机很多服务无法存取系统资料！因此，对于我们刚接触到 Linux 架站的朋友来说， 建议你先关闭 SELinux ，等到两三年后对于 Linux 有很深的概念后， 再来尝试配置 SELinux 这个有趣的咚咚！

    也就是说，如果你没有关闭 SELinux 的话，那么你就得要针对 SELinux 进行档案权限的额外配置， 否则你的网路服务就不可能会正常的启动！那么如何关闭 SELinux 呢？你可以这样做：
    1. 先关闭 /etc/selinux/config 的内容
[root@linux ~]# vi /etc/selinux/config
# 将底下的设定值改成这样：
SELINUX=disabled

2. 修改开机时 grub 的设定档
[root@linux ~]# vi /boot/grub/menu.lst
.....省略.....
    kernel /boot/vmlinuz-2.6.9 ro root=/dev/hda1 rhgb selinux=0
.....省略.....

3. 重新开机
[root@linux ~]# sync; reboot
    因为 SELinux 必须要在开机的时候载入，同样的，要卸载也必须要重新开机才行！ 因此，如果你使用的是您 distributions 的预设安装，那么几乎 SELinux 都是预设启动的！ 你可以依据上述的几个步骤将 SELinux 取消后，重新开机即可。如果对于 SELinux 有兴趣的话， 底下的连结可以参考看看：
    • http://fedora.redhat.com/docs/selinux-faq-fc5/
    • http://selinux.sourceforge.net/
    • http://www.redhat.com/docs/manuals/enterprise/RHEL-4-Manual/selinux-guide/index.html
    • 大标题的图示 主机的细部权限规划：ACL 的使用
    在前一小节当中我们提到 Linux 系统的权限是很重要的，偏偏传统的权限仅有三种身份、三种权限而已， 配合 chmod, umask, chown, chgrp 等指令来进行使用者与群组相关权限的设定。如果要进行比较复杂的权限设定时， 例如某个目录要开放给某个特定的使用者来使用时，传统的 owner,group,others 的权限方法可能就无法满足了。 不过还好，我们有 ACL 这个玩意儿可以使用！这玩意挺有趣的，底下我们就来谈一谈：

    小标题的图示 什么是 ACL？
    ACL 是 Access Control List 的缩写，主要的目的是在提供传统的 owner,group,others 的 read,write,execute 权限之外的细部权限设定。ACL 可以针对单一使用者， 单一档案或目录来进行 r,w,x 的权限规范，对于需要特殊权限的使用状况非常有帮助。

    由于 ACL 是传统的 Unix-like 作业系统权限的额外支援项目，因此要使用 ACL 必须要有档案系统的支援才行。 目前绝大部分的档案系统都有支援 ACL 的功能，包括 ReiserFS, EXT2/EXT3, JFS, XFS 等等。 在 SuSE 这个版本当中，预设是有启动 ACL 控制的，不过在 CentOS 则预设没有启动 ACL。 所以等一下要使用 ACL 的功能时，你必须要先启动你系统 filesystem 的支援才行喔！

    那 ACL 主要可以针对哪些方面来控制权限呢？他主要可以针对几个项目：
    • 使用者 (user)：可以针对使用者来设定权限；
    • 群组 (group)：针对群组为对象来设定其权限；
    • 预设属性 (mask)：还可以针对在该目录下在建立新档案/目录时，规范新资料的预设权限；
    好了，再来看看如何让你的档案系统可以支援 ACL 吧！

    小标题的图示 如何启动 ACL
    要让你的档案系统支援 ACL 非常的简单！假如要让你的 /home 支援 ACL 的话，可以直接这样做：
    [root@linux ~]# mount -o remount,acl /home
[root@linux ~]# mount | grep /home
/dev/hda5 on /home type ext3 (rw,acl)
    看到那个出现的 ACL 了吧！那就对了～如果没有出现这一行，你的档案系统是无法支援 ACL 的， 那下一节的练习您可就无能为力了～那如果想要一开机就让你的档案系统支援 ACL 呢？ 呵呵！修改 /etc/fstab 就对了！将他改成类似底下的模样：
    [root@linux ~]# vi /etc/fstab
/dev/hda5  /home   ext3   defaults,acl   1 2
    加入那一段特殊字体的资料，那么下次开机就能够支援 ACL 了！很简单吧！ ^_^

    小标题的图示 ACL 的设定技巧： getfacl, setfacl
    好了，让你的 filesystem 启动 ACL 支援后，接下来该如何设定与观察 ACL 呢？ 很简单，利用这两个指令就可以了：
    • getfacl：取得某个档案/目录的 ACL 设定项目；
    • setfacl：设定某个目录/档案的 ACL 规范。
    先让我们来瞧一瞧 setfacl 如何使用吧！
    [root@linux ~]# setfacl [-mxdb] 设定值
参数：
-m  ：设定一个 ACL 规范；
-x  ：取消一个 ACL 规范；
-b  ：全部的 ACL 规范都移除；
-d  ：设定预设的 ACL 规范，仅能针对目录使用。
    最常用的就是那个 -m 的参数啦！用来定义一笔 ACL 的设定规范说。那么 ACL 该如何设定呢？ 不同的使用者、群组与预设权限设定方法有点不同，不过，基本上有底下这三种简易的设定方法：
    1. 针对使用者
设定值的规范为： u:[使用者帐号列表]:[rwx]
例如针对 dmtsai 这个使用者来规范其权限为 rx ，则：
[root@linux ~]# setfacl -m u:dmtsai:rx somefilename

2. 针对群组来设定
设定值的规范为： g:[群组名]:[rwx]
例如针对 users 这个群组来规范其权限为 rw ，则：
[root@linux ~]# setfacl -m g:users:rw somefilename

3. 针对预设权限来规范，类似 umask 的功能
设定值的规范为： m:[rwx]
例如假设预设权限为 rwx，则：
[root@linux ~]# setfacl -m m:rwx somefilename
    了解了上面的设定方式后，现在让我们来实际操作一下吧！假设：
    • 你已经将 /home 这个独立的 partition 设定了 ACL 的支援了，
    • 并且在 /home 底下设定了一个名称为 project 的目录，
    • 该目录要给 eric 这个使用者，且属于 users 这个群组，预设权限应该是 770 ；
    • 有个使用者帐号名称为 jordan ，他属于 jordan 那个群组，但他想要进入到 project 那个目录来工作， 意思是说，jordan 在该目录下需有 w 的权限才行；
    • 有个使用者他是其他班级的老师，名称为 tip ，群组名亦为 tip ，他想要进入该目录查阅所有档案资料， 但是不能够进行删除与新增的工作，亦即他不能拥有 w 的权限。
    在传统的 Linux 档案权限中，要达成上述的功能时，你得要让 jordan 与 tip 这两个使用者加入 users 那个群组才行，但是 jordan 是希望可以在该目录内工作的，所以他必须要拥有 w 的权限， 而 tip 却仅能读取，所以他不能拥有 w 的权限！哇！如此一来，就无法完成上述的交代事项了！ 此时我们只好透过 ACL 来单独的针对 tip/jordan 这两个使用者来设定他的权限呐！整个流程可以是这样的：
    1. 建立该目录并规划好权限：
[root@linux ~]# mkdir /home/project
[root@linux ~]# chown eric:users /home/project
[root@linux ~]# chmod 770 /home/project
[root@linux ~]# ls -ld /home/project
drwxrwx---  2 eric users 4096 Sep  5 15:54 /home/project/
# 瞧！已经将需要的目录规划好了！使用者/群组与权限都OK了；

2. 建立 jordan 的使用权限(需要有 w)：
[root@linux ~]# cd /home
[root@linux home]# setfacl -m u:jordan:rwx project

[root@linux home]# getfacl project
# file: project    <==前面三行只是指出这个档名的传统 Linux 权限
# owner: eric
# group: users
user::rwx          <==注意看，这是针对‘预设使用者’的权限设定；
user:jordan:rwx    <==这是针对 jordan 的权限设定
group::rwx         <==这是针对‘预设群组’的权限设定
mask::rwx          <==这玩意儿则是预设属性啦！
other::---
# 上面这个输出共 8 行我们会在底下详细说明！

[root@linux home]# ls -ld project
drwxrwx---+ 2 eric users 4096 Sep  5 15:54 project
# 看看！多了一个 + 的标志喔！
    那个 getfacl 指令可以用来取得某个档名的 ACL 资料啦！至于输出的共 8 行资料你必须要这样看：
    • 第 1-3 行：前面三行会显示出这个档案的 Linux 传统属性，包括使用者、群组与档名，预设会用 # 开头作为说明；

    • 接下来的每一行的输出会以底下的格式来处理：
      针对的目标(使用者、群组等]:[各种帐号列表]:[rwx]
针对的目标主要有：
    user	使用者
    group	群组
    mask	预设权限
    other	非本群组的其他使用者
各种帐号列表中，如果没有任何资料，如 user::rwx ，则代表预设使用者帐号；
      主要有三个栏位，用‘ : ’来隔开三个栏位；

    • 第 4 行‘user::rwx’：由于使用者列表栏位中没有填写任何帐号，所以代表这个权限是针对预设使用者， 亦即是这个目录的拥有人 eric 啦，是 eric 的权限为‘ rwx ’的意思说！

    • 第 5 行‘user:jordan:rwx’：使用者 jordan 在这个目录下具有 rwx 的权限的意思啦！

    • 第 6 行‘group::rwx’：没有填写群组名称，所以同样是预设群组，亦即是那个 users 啰， 该群组的权限为‘rwx’啦；

    • 第 7 行‘mask::rwx’：预设的 mask 为 rwx 的意思，这个 mask 是有用途的！底下会说明。

    • 第 8 行‘other::---’：指的就是其他的未规定的使用者与群组的权限了
    好了，现在 jordan 这位朋友当他进入 /home/project 后，立刻就会拥有 rwx 的权限了！ 而不需要加入 users 这个群组呢！真是很方便吧！太好了！ 另外，你如何知道某个档名具有额外的 ACL 权限呢？可以参考上面最终的输出结果中， 会发现 /home/project 这个目录的权限项目竟然是出现‘ drwxrwx---+ ’呢！ 那个多出来的‘ + ’就是表示该档名有额外的 ACL 控制项目啦！ 那接下来如何处理 tip 呢？同样使用 ACL 来控制：
    3. 设定 tip 这个使用者的权限资料：
[root@linux home]# setfacl -m u:tip:rx project
[root@linux home]# getfacl project
# file: project
# owner: eric
# group: users
user::rwx
user:tip:r-x   <==瞧！多出来的咚咚啦！
user:jordan:rwx
group::rwx
mask::rwx
other::---
    如此一来， tip 这位使用者则仅能进入该目录去读取而已，而无法进行写入的动作呢！ 是否很方便啊！有了 ACL 的控制项目后，您就可以将你系统内的有需要使用到特殊权限设定的目录进行细部设定， 让你的系统变的更合理，更安全啊！

  • ACL 内的 mask 项目
    虽然这样就能够设定好一个 ACL 控制项目，不过你还需要了解到在 ACL 内的 mask 所代表的意义喔！ 在上面的那个小案例当中，我们并没有去设定这个 mask，mask 需要与使用者的权限进行逻辑运算 (AND) 后， 才是有效的权限呐(effective permission)！

    举例来说，如果你觉得你的目录要让所有的人都暂时仅能读取不能写入时，可以将 ACL 内的 mask 设定为 rx 即可， 那其他人就不需要再额外的设定了！看看底下这个例子：
    [root@linux ~]# cd /home
[root@linux home]# setfacl -m m:rx project
[root@linux home]# getfacl project
# file: project
# owner: eric
# group: users
user::rwx
user:tip:r-x
user:jordan:rwx        #effective:r-x
group::rwx             #effective:r-x
mask::r-x
other::---
    上面的输出全部都是 getfacl 的输出结果，鸟哥并没有加工啊！ ^_^！ 原本的 jordan 具有‘rwx’的权限，而 mask 仅有‘r-x’，两者去比较后 ‘两者都有的权限才会生效，就称为有效权限 (effective permission) 啰’！ 所以，jordan 则仅会有 rx 的权限而已啊！这样对 mask 的用法了了吗？
    • 大标题的图示 一些常见的攻击手法与主机的保护方式
    我们由图一了解到资料传送到本机时所需要经过的几道防线后， 现在您应该比较清楚为何我们常常在基础篇里面一直谈到设定正确的权限可以保护您的主机了吧？ 那么除了前面的谈到的主机基本保护之外， 通常人家是如何攻击你的 Linux 主机呢？底下我们就来谈一谈吧！ 先了解一下人家是如何攻击你的，我们才有办法想到如何防御，您说是吧？！

  • 取得帐号资讯后猜密码：
    由于很多人喜欢用自己的名字来作为帐号资讯，因此帐号的取得是很容易的！ 举例来说，如果你的朋友将你的 email address 不小心泄漏出去，例如： dmtsai@your.host.name 之类的样式， 那么人家就会知道你有一部主机，名称为 your.host.name，且在这部主机上面会有一个使用者帐号， 帐号名称为 dmtsai ，之后这个坏家伙再利用某些特殊软体例如 nmap 来进行你主机的 port scan 之后，嘿嘿！他就可以开始透过你主机有启动的软体功能来猜你这个帐号的密码了！

    另外，如果你常常观察你的主机登录档，那你也会发现如果你的主机有启动 Mail server 的服务时， 你的登录档就会常常出现有些怪家伙尝试以一些奇怪的常见帐号在试图猜测你的密码， 举例来说像：admin, administrator, webmaster .... 之类的帐号，尝试来窃取你的私人信件。 如果你的主机真的有这类的帐号，而且这类的帐号还没有良好的密码规划，那就容易‘中标’！ 唉！真是麻烦！所以我们常讲，系统帐号千万不能给予密码，容易被猜密码啊！

    这种猜密码的攻击方式算是最早期的入侵模式之一了，攻击者知道你的帐号，或者是可以猜出来你的系统有哪些帐号， 欠缺的就只是密码而已， 因此他会‘很努力的’去猜你的密码，此时，你的密码规划如果不好的话，很容易就被攻击了！ 主机也很容易被绑架啊！所以，良好的密码设置习惯是很重要的。

    不过这种攻击方式比较费时，因为目前很多软体都有密码输入次数的限制， 如果连续输入三次密码还不能成功的登入，那该次连线就会被断线！ 所以，这种攻击方式日益减少，目前偶而还会看到就是了！这也是初级 cracker 会使用的方式之一。 那我们要如何保护呢？基本方式是这样的：
    • 减少资讯的曝光机会：例如不要将 Email Address 随意散布到 Internet 上头；
    • 建立较严格的密码设定规则：包括 /etc/shadow, /etc/login.defs 等档案的设定， 建议您可以参考基础篇内的 帐号管理那一章来规范你的使用者密码变更时间等等， 如果主机够稳定且不会持续加入某些帐号时，也可以考虑使用 chattr 来限制帐号 (/etc/passwd, /etc/shadow) 的更改；
    • 完善的权限设定：由于这类的攻击方式会取得你的某个使用者帐号的登入权限， 所以如果你的系统权限设定得宜的话，那么攻击者也仅能取得一般使用者的权限而已， 对于主机的伤害比较有限啦！所以说，权限设定是重要的；
  • 利用系统的程式漏洞‘主动’攻击：
    由图一里面的第三个步骤中，我们知道如果你的主机有开放网路服务时， 就必须有启动某个网路软体嘛！我们也知道由于软体可能撰写方式的问题，可能产生一些会被 cracker 乱用的臭虫程式码，而这些臭虫程式码由于产生问题的大小，有分为 bug (臭虫，可能会造成系统的不稳定或当机) 与 Security (安全问题，程式码撰写方式会导致系统的使用权限被恶意者所掌握) 等问题。

    当程式的问题被公布后，某些较高阶的 cracker 会尝试撰写一些针对这个漏洞的攻击程式码， 并且将这个程式码放置到 cracker 常去的网站上面，藉以推销自己的‘功力’..... 鸟哥要提醒的是，这种程式码‘是很容易被取得的’。 当更多‘盈盈美黛子(台语，闲闲没事干之意)’取得这些程式码后，他可能会想要‘试一试这个攻击程式的威力’， 所以就拿来‘扫射’一番，如果你八字比较轻，或者当天星座学家说你比较倒楣时， 可能就会被不小心的攻击到......

    这种攻击模式是目前最常见的，因为攻击者只要拿到攻击程式就可以进行攻击了， ‘而且由攻击开始到取得你系统的 root 权限不需要猜密码， 不需要两分钟，就能够立刻入侵成功’，所以‘盈盈美黛子’们最爱的就是这个咚咚了。 但这个玩意儿本身是靠‘你主机的程式漏洞’来攻击的，所以，如果你的主机随时保持在即时更新的阶段， 或者是关闭大部分不需要的程式，那就可以躲避过这个问题。因此，你应该要这样做：
    • 关闭不需要的网路服务：开的 port 越少，可以被入侵的管道越少， 一部主机负责的服务越单纯，越容易找出问题点。看看前面谈到的 限制 Linux 的连线埠口 一章吧！
    • 随时保持更新：这个没话讲！一定要进行的！参考前一章 网路升级套件。
    • 关闭不需要的软体功能：举例来说，后面会提到的远端登入伺服器 SSH 可以提供 root 由远端登入，那么危险的事情当然要给他取消啊！^_^
  • 利用社交工程作欺骗：
    社交工程 (Social Engineering) 指的其实很简单，就是透过人与人的互动来达到‘入侵’的目的！ @_@！人与人的互动可以入侵你的主机？鸟哥在呼咙你吗？当然不是。

    近日在台湾的社会你不是常看到某些人会以‘退税、中奖、花小钱买贵重物品’等名义来欺骗善良老百姓， 让老百姓掏出口袋里的金钱给那些可恶的金光党吗？社交工程也是类似的方法。在大公司里面， 或许你可能会接到这样的电话：‘我是人事部门的经理，我的帐号为何突然间不能登入了？ 你给我看一看，恩？干脆直接帮我另建一个帐号，我告诉你我要的密码是....’。如果你一时不查给他帐号密码的话， 你的主机可能就这样被绑走了～

    社交工程的欺骗方法多的是，包括使用‘好心的 email 通知’、‘警告信函’、‘中奖单’等等， 在在都是要欺骗你的帐号密码，有的则利用钓鱼方式来欺骗你在某些恶意网站上面输入你的帐号密码， 很讨厌的啦！那要如何防范呢？
    • 追踪对谈者：不要一味的相信对方，你必须要有信心的向上呈报， 不要一时心慌就中了计！
    • 不要随意透露帐号/密码等资讯：最好不要随意在 Internet 上面填写这些资料， 真的很危险的！因为在 Internet 上面，你永远不知道对方荧幕前面坐着的是谁？
  • 利用程式功能的‘被动’攻击：
    啥？除了主动攻击之外，还有所谓的被动攻击喔？没错啊，‘系金ㄟ’！那如何作被动攻击呢？ 那就得要由‘恶意网站’讲起了。如果你喜欢上网随意浏览的话，那么有的时候可能会连上一些广告很多， 或者是一堆弹出式视窗的网站，这些网站有时还会很好心的‘提供你很多好用的软体自动下载与安装’的功能， 如果该网站是你所信任的，例如 Red Hat, CentOS, Windows 官网的话，那还好， 如果是一个你也不清楚他是干嘛的网站，那你是否要同意下载安装该软体？

    如果你常常在注意一些网路危机处理的相关新闻时，常会发现 Windows 的浏览器 (IE) 有问题， 有时则是全部的浏览器 (Firefox, Netscap, IE...) 都会出现问题。那你会不会觉得奇怪啊， 怎么‘浏览器也会有问题？’这是因为很多浏览器会主动的答应对方 WWW 主机所提供的各项程式功能， 或者是自动安装来自对方主机的软体，有时浏览器还可能由于程式发生安全问题， 让对方 WWW 浏览器得以传送恶意程式码给你的主机来执行，嘿嘿！中标！

    那你又会想啊，那我干嘛浏览那样的恶意网站？喝！总是会有些粗心大意的时候啊！ 如果你今天不小心收到一个 email ，里面告诉你你的银行帐号有问题， 希望你赶紧连上某个网页去看看你的帐号是否在有问题的行列中，你会不会去？ 如果今天有个网路消息说某某网页在提供大特价商品，那你会不会去碰碰运气？ 都是可能的啊！不过，这也就很容易被对方攻击到了。

    那如何防备啊？当然建立良好的习惯最重要了：
    • 随时更新主机上的所有套件：如果你的浏览器是没有问题的， 那对方传递恶意程式码时，你的浏览器就不会执行，那自然安全的多啊！
    • 较小化软体的功能：举例来说，让你的收信软体不要主动的下载档案， 让你的浏览器在安装某些软体时，要通过你的确认后才安装，这样就比较容易克服一些小麻烦；
    • 不要连接到不明的主机：其实鸟哥认为这个才最难！ 因为很多时候我们都用 google 在搜寻问题的解决之道啊，那你如何知道对方是否是骗人的？ 所以，前面两点防备还是很重要的！不要以为没有连接上恶意网站就不会有问题啊！
  • 蠕虫或木马的 rootkit：
    rootkit 意思是说可以取得 root 权限的一群工具组 (kit)，就如同前面主动攻击程式漏洞的方法一样， rootkit 主要也是透过主机的程式漏洞。不过， rootkit 也会透过社交工程让使用者下载、安装 rootkit 软体， 结果让 cracker 得以简单的绑架对方主机啊！

    rootkit 除了可以透过上述的方法来进行入侵之外，rootkit 还会伪装或者是进行自我复制， 举例来说，很多的 rootkit 本身就是蠕虫或者是木马间谍程式。蠕虫会让你的主机一直发送封包向外攻击， 结果会让你的网路频宽被吃光光，例如 2001-2003 年间的 Nimda, Code Red 等等；至于木马程式 (Trojan Horse) 则会对你的主机进行开启后门 (开一个 port 来让 cracker 主动的入侵)，结果就是....绑架、绑架、绑架！

    rootkit 其实挺不好追踪的，因为很多时候他会主动的去修改系统观察的指令， 包括 ls, top, netstat, ps, who, w, last, find 等等，让你看不到某些有问题的程式， 如此一来，你的 Linux 主机就很容易被当成是跳板了！有够危险！那如何防备呢？
    • 不要随意安装不明来源的档案或者是不明网站的档案资料；
    • 不要让系统有太多危险的指令：例如 SUID/SGID 的程式， 这些程式很可能会造成使用者不当的使用，而使得木马程式有机可趁！
    • 可以定时以 rkhunter 之类的软体来追查：有个网站提供 rootkit 程式的检查，你可以前往下载与分析你的主机：
      http://www.rootkit.nl/projects/rootkit_hunter.html
  • DoS 攻击法 ( Denial of Service )
    这类型的攻击中文翻译成‘阻断式攻击’，这种攻击法也很要命，而且方法有很多，最常见的就属 SYN Flood 攻击法了！还记得我们在网路基础里面提到的，当主机接收了一个带有 SYN 的 TCP 封包之后，就会启用对方要求的 port 来等待连线，并且发送出回应封包 (带有 SYN/ACK 旗标的 TCP 封包)，并等待 Client 端的再次回应。

    好了，在这个步骤当中我们来想一想，如果 cient 端在发送出 SYN 的封包后，却将来自 Server 端的确认封包丢弃，那么您的 Server 端就会一直空等，而且 Client 端可以透过软体功能，在短短的时间内持续发送出这样的 SYN 封包，那么您的 Server 就会持续不断的发送确认封包，并且开启大量的 port 在空等～呵呵！等到全部主机的 port 都启用完毕，那么.....系统就挂了！

    更可怕的是，通常攻击主机的一方不会只有一部！他会透过 Internet 上面的僵尸主机 (已经成为跳板，但网站主却没有发现的主机) 发动全体攻击，让你的主机在短时间内就立刻挂点。 这种 DoS 的攻击手法比较类似‘玉石俱焚’的手段， 他不是入侵您的系统，而是要让您的系统挂点呢！ 最常被用来作为阻断式服务的网路服务就是 WWW 了，因为 WWW 通常得对整个 Internet 开放服务。

    这种攻击方法也是最难处理的，因为要嘛就得要系统核心有支援自动抵挡 DoS 攻击的机制， 要嘛您就得要自行撰写侦测软体来判断！真是麻烦啊～而除非您的网站非常大， 并且‘得罪不少人’，否则应该不会被 DoS 攻击啦！ ^_^

  • 其他：
    上面提到的都是比较常见的攻击方法，是还有一些高竿的攻击法啦， 不过那些攻击法都需要有比较高的技术水准，例如 IP 欺骗。他可以欺骗你主机告知该封包来源是来自信任网域， 而且透过封包传送的机制，由攻击的一方持续的主动发送出确认封包与工作指令。 如此一来，你的主机可能就会误判该封包确实有回应，而且是来自内部的主机。

    不过我们知道网际网路是有路由的，而每部主机在每一个时段的 ACK 确认码都不相同， 所以这个方式要达成可以登入，会比较麻烦，所以说，不太容易发生在我们这些小型主机上面啦！ 不过你还是得要注意一下说：
    • 设定规则完善的防火墙：利用 Linux 内建的防火墙软体 iptables 建立较为完善的防火墙，可以防范部分的攻击行为；
    • 核心功能：这部份比较复杂，您必须要对系统核心有很深入的了解， 才有办法设定好你的核心网路功能。
    • 登录档与系统监控：你可以透过分析登录档来了解系统的状况， 另外也可以透过类似 MRTG 之类的监控软体 来即时了解到系统是否有异常，这些工作都是很好的努力方向！
  • 主机防护小结语：
    要让你的系统更安全，没有‘三两三’是没办法达成的！我们也一直鼓吹， ‘维护网站比架设网站还要重要’的观念！因为‘一人得道鸡犬升天’，同样的道理：‘一人中标全员挂点’， 不要以为你的主机没有啥重要资料，被入侵或被植入木马也没有关系， 因为我们的伺服器通常会对内部来源的主机规范的较为宽松，如果你的主机在公司内部， 但是不小心被入侵的话，那么贵公司的伺服器是否就会暴露在危险的环境当中了？

    另外，在蠕虫很‘发达’的年代，我们也会发现只要区域网路里面有一部主机中标， 整个区域网路就会无法使用网路了，因为频宽已经被蠕虫塞爆！ 如果老板发现他今天没有办法收信了，但无法收信的原因并非伺服器挂点， 而是因为内部人员的某部个人电脑中了蠕虫，而那部主机中蠕虫的原因只是因为该使用者不小心去看了一下色情网站， 你觉得老板会高兴的跟该员工一起看色情网站还是 fire 掉该人员？

    所以啊，主机防护还是很重要的！不要小看了！提供几个方向给大家思考看看吧：
    1. 建立完善的登入密码规则限制；
    2. 完善的主机权限设定；
    3. 设定自动升级与修补套件漏洞、及移除危险套件；
    4. 在每项系统服务的设定当中，强化安全设定的项目；
    5. 利用 iptables, TCP_Wrappers 强化网路防火墙；
    6. 利用主机监控软体如 MRTG 与 logwatch 来分析主机状况与登录档；
    • 大标题的图示 被入侵后的修复工作
    如果你的主机被入侵的话，而你也由于了解到主机监控的需要，所以在最短的时间内发现此一事件， 那么该如何针对这个被入侵的主机来修复？那如果你要修复的话，你这个网管人员还需要哪些额外的技能？ 底下我们就来谈一谈。

    小标题的图示 网管人员的额外技巧与任务
    从前一小节的分析当中，您会发现网管还真的是挺累的，他需要对于作业系统有一定程度的熟悉， 对于程序的运作 (process) 与权限概念，则需要更了解！否则就麻烦了！那除了作业系统的基本概念之外， 咱们网管还需要啥特殊技巧呢？当然需要啊！其实一部主机最常发生问题的状况， 都是由‘内部的网路误用所产生的’，所以啊，你只管好主机而已是‘没有办法杜绝问题’的啦！ 底下就来谈谈你还需要啥技巧呢？

  • 了解什么是需要保护的内容：
    我的天呐，还要知道什么是需要保护的呀？呵呵！没错，就是如此！由刚刚我们知道的主机入侵方法当中， 不难了解，只要有人坐在您的主机前面，那么任何事都有可能会发生！因此，如果您的主机相当的重要， 请‘不要让任何人靠近！’您可以参考一下汤姆克鲁斯在‘不可能的任务’里面要窃取一部电脑内的资料的困难度！ ^_^""
    • 硬体：能锁就锁吧！
    • 软体：还包含最重要的资料呢！
  • 预防黑客( Black hats )的入侵：
    这可不是开玩笑的，什么是黑客呀！这是因为原本在西部电影当中，坏人都是戴黑色帽子的， 所以之前的人们就称网路攻击者为 Black hats 啦！在预防这方面的攻击者时，除了严格管制网路的登入之外， 还需要特别控制原本您的主机中的人物！就我们小网站来说，不要以为好朋友就随便他啦！ 他说要指定密码是跟他的帐号相同比较好记，您就答应他！等到人家用他的密码登入您的主机，并破坏您的主机， 那可就得不偿失了！如果是大企业的话，那么员工使用网路时，也要分等级的呢！ ^_^

  • 主机环境安全化：
    没什么好讲的，除了多关心，还是多关心！仔细的分析登录档，常常上网看看最新的安全通告，这都是最基础的！ 还包含了以最快的速度更新有问题的套件！因为，越快更新您的套件，就越快可以杜绝黑客的入侵！

  • 防火墙规则的订定：
    这部份比较麻烦一些啦！因为您必需要不断的测试测试再测试！以取得最佳化的网路安全设定！ 怎么说呢？要晓得的是，如果您的防火墙规则订定得太多的时候， 那么一个资料封包就要经过越多的关卡才能完整的通过防火墙，以进入到主机内部！嘿嘿！ 这可是相当的花费时间的！会造成主机的效能不彰！特别留意这一点呢！

  • 即时维护您的主机：
    就像刚刚说的，您必需要随时维护您的主机，因为，防火墙不是一经设定之后就不用在再他了！ 因为，再严密的防火墙，也会有漏洞的！这些漏洞包括防火规则设定不良、利用较新的侦测入侵技术、 利用您的旧软体的服务漏洞等等！所以，必需要即时维护您的主机呀！这方面除了分析 log files 之外，也可以藉由即时侦测来进行这个工作！例如 PortSentry 就是蛮不错的一套软体呢！

  • 良好的教育训练课程：
    不是所有的人都是电脑网路高手，尤其虽然现在资讯爆炸但是仍然有很多的机会会遇到电脑白痴呀！ 这个时候，要晓得的是，我们对于内部网域通常没有太多的规范，那如果他用内部的电脑去做坏事怎么办？ 有时候还是无心的～挖哩～所以说，需要特别的教育训练课程呀！这也是公司需要网管的主因之一！

  • 完善的备份计划：
    天有不测风云，人有旦夕祸福呀！什么人都不知道什么时候会有大地震、我们也都不知道什么时候会突然的硬碟挂掉去～ 所以说，完善的备份计划是相当重要的！此外，大概没有人会说他的主机是 100% 的安全吧！ 那如果你的系统被入侵，造成资料的损毁时，你要如何复原你的主机啊？呵呵！一个良好的网站管理人员， 无时无刻都会进行重要资料的备份的！很重要啊！ 这一部份请参考一下基础学习篇之 Linux 主机备份的内容吧！ 本书后续的远端连线伺服器 SSH 章节内也会提到一个很棒的 rsync 工具，您可以瞧瞧！
    • 小标题的图示 入侵恢复工作
    所谓‘百密一疏’啊，人不是神，总会有考虑不周的情况，万一您的主机就因为这‘一疏’导致被入侵了， 那该怎么办？由上面的说明当中，我们知道‘木马’是很严重的，因为他会在您的系统下开个后门(Back door)让攻击者可以登入您的主机，而且还会窜改您 Linux 上面的程式，让您找不到该木马程式！怎么办？

    很多朋友都习惯‘反正只要将 root 的密码改回来就好了’ 这样的观点，事实上，那样一部主机还是有被做为中继站的危险啊！所以， 万一您的主机被入侵了，最好的方法还是‘重新安装Linux ’会比较干净！

    那该如何重新安装呢？很多朋友一再地安装，却一再地被入侵～为什么呢？因为他没有‘记取教训’啊！呵呵！ 底下我们就来谈一谈，一部被入侵的主机应该如何修复比较好？
    1. 立即拔除网路线：

      既然发现被入侵了，那么第一件事情就是拿掉网路功能！拿掉网路功能最简单的作法自然就是拔掉网路线了！ 事实上，拿掉网路线最主要的功能除了保护自己之外，还可以保护同网域的其他主机。怎么说呢？举个最近 (2003/08) 发病的疾风病毒好了，他会感染同网域之内的其他主机喔！所以，拔除网路线之后， 远端的攻击者立即就无法进入您的 Linux 主机，而且您还可以保护网域内的其他相关主机啊！

    2. 分析登录档资讯，搜寻可能的入侵途径：

      被入侵之后，决不是只要重新安装就好，还需要额外分析 ‘为什么我的主机这一次会被入侵，对方是如何入侵的？’， 如果您能够找出问题点，那么不但您的 Linux 功力立刻增强了，主机也会越来越安全喔！ 而如果您不知道如何找出被入侵的可能途径，那么重新安装后，下次还是可能被以同样的方法入侵啊！ 粉麻烦的啦！好了，那该如何找出入侵的途径呢？

      • 分析登录档：低级的 cracker 通常仅是利用工具软体来入侵您的系统，所以我们可以藉由分析一些主要的登录档来找出对方的 IP 以及可能有问题的漏洞。可以分析 /var/log/messages, /var/log/secure 还有利用 last 指令来找出上次登入者的资讯。

      • 检查主机开放的服务：很多 Linux 使用者常常不晓得自己的系统上面开了多少的服务？我们说过， 每个服务都有其漏洞或者是不应该启用的增强型或者是测试型功能，所以，找出您系统上面的服务， 并且检查一下每个服务是否有漏洞，或者是在设定上面有了缺失，然后一个一个的整理吧！

      • 查询 Internet 上面的安全通报： 透过安全通报来了解一下最新的漏洞资讯，说不定您的问题就在上面！

    3. 重要资料备份：

      主机被入侵后，显得问题相当的严重，为什么呢？因为主机上面有相当重要的资料啊！ 如果主机上面没有重要的资料，那么直接重新安装就好了！所以，被入侵之后，检查完了入侵途径， 再来就是要备份重要的资料了。好了，问个问题，什么是‘重要资料’？ who, ps, ls 等等指令是重要资料吗？还是 httpd.conf 等设定档是重要资料？又或者是 /etc/passwd, /etc/shadow 才是重要资料？

      呵呵！基本上，重要的资料应该是‘非 Linux 系统上面原有的资料’，例如 /etc/passwd, /etc/shadow, WWW 网页的资料, /home 里面的使用者重要档案等等，至于 /etc/*, /usr/, /var 等目录下的资料，就不见得需要备份了。 注意：不要备份一些 binary 执行档，因为 Linux 系统安装完毕后本来就有这些档案，此外， 这些档案也很有可能‘已经被窜改过了’，那备份这些资料，反而造成下次系统还是不干净！

    4. 重新全新安装：

      备份完了资料，再来就是重新安装 Linux 系统了。而在这次的安装中， 您最好选择适合您自己的安装套件即可，不要全部套件都给他安装上去啊！挺危险的！

    5. 套件的漏洞修补：

      记得啊，重新安装完毕之后，请立即更新您的系统套件，否则还是会被入侵的啦！鸟哥喜欢先在其他比较干净的环境下将 Internet 上面的漏洞修补套件下载下来，然后烧录起来，然后拿到自己的刚刚安装完成的系统上面，mount CD 之后全部给他更新，更新之后，并且设定了相关的防火墙机制，同时进行下一步骤‘ 关闭或移除不需要的服务’后，我才将网路线插上主机的网路卡上！ 因为鸟哥不敢确定在安装完毕后，连上 Internet 去更新套件的这段时间，会不会又受到入侵攻击说....

    6. 关闭或移除不需要的服务：

      这个重要性不需要再讲了吧？！启用越少的服务，系统当然可以被入侵的可能性就比较低。

    7. 资料回复与恢复服务设定：

      刚刚备份的资料要赶紧的复制回来系统，同时将系统的服务再次的重新开放，请注意， 这些服务的设定最好能够再次的确认一下，避免一些不恰当的设定参数在里头喔！

    8. 连上 Internet：

      所有的工作都进行的差不多了，那么才将刚刚拿掉的网路线接上来吧！恢复主机的运作了！
    经过这一连串的动作后，您的主机应该会恢复到比较干净的环境，此时还不能掉以轻心， 最好还是参考防火墙的设定，并且多方面的参考 Internet 上面一些老手的经验，好让您的主机可以更安全一些！
    大标题的图示 重点回顾
    • 要管制登入伺服器的来源主机，得要了解网路封包的特性，这主要包括 TCP/IP 的封包协定， 以及重要的 Socket Pair ，亦即来源与目标的 IP 与 port 等。在 TCP 封包方面，则还得了解 SYN/ACK 等封包状态；
    • TCP 封包要进入我们 Linux 本机，至少需要通过 IP Filter, super daemon/TCP Wrappers, Daemons, 密码验证功能 等等步骤；
    • 主机的基本保护之一，就是拥有正确的权限设定。而复杂的权限设定可以利用 ACL 或者是 SELinux 来辅助；
    • ACL 必须要让 Filesystem 支援，故可以在 /etc/fstab 内加入 acl 的控制参数；
    • 关闭 SELinux 可在 /etc/selinux/config 档案内设定，亦可在核心功能中加入 selinux=0 的项目；
    • ACL 主要可针对 user, group, mask 来设定，可针对单一个人帐号设定权限；
    • 设定 ACL 的方法为使用 setfacl, 查阅则以 getfacl 指令来动作；
    • ACL 内的 mask 是很重要的，必须与使用者的权限进行逻辑 AND 的运算，才会得到正确的最终权限；
    • rootkit 为一种取得 root 的工具组，您可以利用 rkhunter 来查询您主机是否被植入 rootkit；
    • 网管人员应该注意在员工的教育训练还有主机的完善备份方案上面；
    • 一些所谓的黑客软体，几乎都是透过您的 Linux 上面的套件漏洞来攻击 Linux 主机的；
    • 套件升级是预防被入侵的最有效方法之一；
    • 良好的登录档分析习惯可以在短时间内发现系统的漏洞，并加以修复。
    大标题的图示 课后练习
    • 我老是发现我的系统怪怪的，似乎有点停顿的模样，怀疑可能是 CPU 负荷太大，所以要去检查一下系统相关的资讯。请问，我该以什么指令去检查我的系统相关的资讯？
      • 可以使用 top, sar, free, ps -aux, uptime, last 等功能去查询系统的相关资讯喔！然后再以 kill 之类的指令删除；
    • 我怀疑我的系统上面有过多的具有 SUID 的档案存在，导致一般使用者可以随意的取得 root 的权限，请问，我要如何找出这些具有 SUID 权限的档案？
      • 因为 SUID 是 4000 这个权限的模样，所以我可以这样做：
      find / -perm +4000
    • 我由国内一些 ftp 网站上下载了 Red Hat 公司释出的套件，我想安装他，但又不知道该套件档案是否被修改过！ 请问我该如何确定这个套件的可用性？
      • 利用最简易的 MD5 编码来测试一下，例如‘ md5sum 套件名称’，再比对与原始套件释出的 MD5 数据是否相同！？
    • 如果我发现使用‘ setfacl -m u:dmtsai:rwx /path/to/file ’时，系统却显示‘setfacl: Operation not supported’， 你认为是哪里出问题？
      • 这是由于您的 filesystem 没有启用 ACL 支援，或者是系统的核心不支援。 请先使用 mount -o remount,acl /mount_point 测试看能否支援 ACL ，若不支援时，则可能是由于核心版本太旧了。
    • 如果要设定 dmtsai 可以使用 /home/project 这个目录 (假设 /home 已经支援 ACL)，在该目录内 dmtsai 可以拥有完整的权限。请问该如何设定该目录？
      • 除了使用 setfacl -m u:dmtsai:rwx /home/project 之外，还需要设定 setfacl -m m:rwx /home/project ， 因为 ACL 在目录方面，必须透过使用者权限及 mask 的逻辑运算后才能生效！
    • SELinux 是否为防火墙？
      • SELinux 并非防火墙，他是用来作为更细部权限设定的一个核心模组。
    • 良好的密码规划是防备主机的第一要务，请问 Linux 系统当中，关于密码相关的档案与规则设定在哪些档案里面？
      • 密码的设定规则在 /etc/login.defs 里面！至于密码档案在 /etc/shadow 内！
    • 简易说明，当一部主机被入侵之后，应该如何处理？
      • 找出问题、重新安装、漏洞修补、资料还原！请参考本章最后一节的说明。
    大标题的图示 参考资料
    • Fedora 的 SELinux FAQ：http://fedora.redhat.com/docs/selinux-faq/
    • SELinux 的发展网站：http://selinux.sourceforge.net/
    • Red Hat 之 RHEL 4 的 SELinux 指南：http://www.redhat.com/docs/manuals/enterprise/RHEL-4-Manual/selinux-guide/index.html
    • 美国国家安全局的 SELinux 简介：http://www.nsa.gov/selinux/
    • Rootkit hunter：http://www.rootkit.nl/projects/rootkit_hunter.html
    2002/08/12：第一次完成日期！
    2003/08/23：重新编排与增加重点回顾、课后练习
    2006/08/31：将旧的文章移动到此处。
    2006/09/06：增加 SELinux 的简单说明，增加 ACL 的控制项目！
    2002/08/12以来统计人数


鸟哥的 Linux 私房菜 -- Linux 防火墙与 NAT 主机

为取得较佳浏览结果，请爱用 firefox 浏览本网页

Linux 防火墙与 NAT 主机
切换解析度为 800x600
最近更新日期：2006/11/08
在谈完了基本的网路安全观念之后，这个章节主要就要针对‘防火墙’来进行介绍了！目前的防火墙机制主要是以 Linux Kernel 2.6 版的 iptables 为主的，而 iptables 可以使用指令来下达，也可以透过编写 shell script 来进行指令的整合。鸟哥本人比较习惯使用 scripts 来进行 iptables 的机制规划呢！除了 iptables 之外，事实上，比较简单的还有 TCP Wrappers 这个玩意儿，他则主要是针对某些服务来进行管理的呐！本章的内容主要就是在介绍这两个重要的防火墙软体了！

1. 本章的行前准备工作
2. 认识防火墙
    2.1 为何需要防火墙
    2.2 Linux 系统上防火墙的主要类别
    2.3 防火墙的一般线路布线与抵挡技巧
    2.4 防火墙的使用限制
 3. Linux 的封包过滤机制： iptables
    3.1 不同 Linux 核心版本的防火墙软体
    3.2 iptables 的表格与封包进入流程
    3.3 本机的 iptables 语法
        规则的清除与观察
        定义预设政策 (policy)
        封包的基础比对 IP/netmask I/O 装置
        TCP, UDP 的规则比对
        状态模组：MAC 与 RELATED
        ICMP 封包规则的比对
    3.4 防火墙的记录、回复与测试
    3.5 IPv4 的核心管理功能：/proc/sys/net/ipv4/*
 4. 本机防火墙的一个实例
    4.1 规则草拟
    4.2 实际设定
 5. NAT 主机的设定
    5.1 什么是 NAT？ SNAT？ DNAT？
    5.2 最阳春 NAT 主机： IP 分享功能
    5.3 iptables 的额外核心模组功能
    5.4 在防火墙后端之网路伺服器 DNAT 设定
 6. 重点回顾
7. 课后练习
8. 参考资料
9. 针对本文的建议：http://phorum.vbird.org/viewtopic.htm?p=114475
大标题的图示 本章的行前准备工作
由于这个章节里面谈到非常多的封包概念，包括 MAC, IP, TCP, UDP, ICMP 等协定， 以及如何抵挡外部 IP 来源的防火墙基础，还有 IP/netmask 的整体网域写法等等。 而鸟哥对于您学习防火墙的建议是希望你可以使用 shell script 来撰写脚本，如此一来可以让你的防火墙规则比较清晰一点。所以在您开始了解底下的资料之前， 希望你可以先阅读过相关的资料了：
  • 已经认识 Shell 以及 Shell script；
  • 已经阅读过网路基础那一个章节的内容；
  • 已经阅读过前一篇认识网路安全；
  • 已经阅读过 路由器那一章节的内容，了解路由的概念；
  • 最好拥有两部主机以上的小型区域网路环境，以方便测试防火墙；
  • Linux 主机上最好有两张网卡，可以进行多种测试，并架设 NAT 主机；
  • 使用 uname -r 确认你的核心是 2.4 或 2.6 版；
若准备妥当了，赶紧来开始进行吧！

大标题的图示 认识防火墙
网路安全除了随时注意套件的漏洞，以及网路上的安全通报之外，你最好能够依据自己的环境来订定防火墙机制， 这样对于你的网路环境，会比较有保障一点喔！那么什么是防火墙呢？ 其实防火墙就是在管制进入到我们网域内的主机(或者可以说是网域)的资料封包的一种机制， 例如我们在前一章节认识网路安全当中提到的 iptables 就是一种防火墙机制了。当然了，更广义的来说， 只要能够分析与过滤进出我们管理之网域的封包资料，就可以称为防火墙。

而这个防火墙又可以分为硬体防火墙与本机的软体防火墙。硬体防火墙是由厂商设计好的主机硬体， 这部硬体防火墙内的作业系统主要以提供封包资料的过滤机制为主，并将其他的功能拿掉。因为单纯作为防火墙功能而已， 因此封包过滤的速度与效率较佳。至于软体防火墙呢？那就是我们这个章节要来谈论的啊！ 软体防火墙本身就是在保护系统网路安全的一套软体(或称为机制)，例如 iptables 与 TCP Wrappers 都可以称为软体防火墙。

无论怎么分，反正防火墙就是用来保护我们网路安全的咚咚就对啦！呵呵！我们这个章节主要在介绍 Linux 系统本身提供的软体防火墙的功能，那就是 iptables 。至于 TCP Wrappers 请前往基础篇的 认识系统服务 参考参考喔！

小标题的图示 为何需要防火墙
基本上，如果你的系统 (1)已经关闭不需要而且危险的服务； (2)已经将整个系统的所有套件都保持在最新的状态； (3)权限设定妥当且定时进行备份工作； (4)已经教育使用者具有良好的网路、系统操作习惯。 那么你的系统实际上已经颇为安全了！要不要架设防火墙？那就见仁见智啰！

不过，毕竟网路的世界是很复杂的，而 Linux 主机也不是一个简单的东西， 说不定哪一天你在进行某个软体的测试时，主机突然间就启动了一个网路服务， 如果你没有管制该服务的使用范围，那么该服务就等于对所有 Internet 开放， 那就麻烦了！因为该服务可能可以允许任何人登入你的系统，那不是挺危险？

所以啰，防火墙能作什么呢？防火墙最大的功能就是帮助你‘限制某些服务的存取来源’！ 举例来说： (1)你可以限制档案传输服务 (FTP) 只在子网域内的主机才能够使用，而不对整个 Internet 开放； (2)你可以限制整部 Linux 主机仅可以接受客户端的 WWW 要求，其他的服务都关闭； (3)你还可以限制整部主机仅能主动对外连线，对我们主机主动连线的封包状态 (TCP 封包的 SYN flag) 就予以抵挡等等。 这些就是最主要的防火墙功能了！

所以鸟哥认为，防火墙最重要的任务就是在规划出：
  • 切割被信任(如子网域)与不被信任(如 Internet)的网段；
  • 划分出可提供 Internet 的服务与必须受保护的服务；
  • 分析出可接受与不可接受的封包状态；
当然啦，咱们 Linux 的 iptables 防火墙软体还可以进行更细部深入的 NAT (Network Address Translation) 的设定，并进行更弹性的 IP 封包伪装功能，不过，对于单一主机的防火墙来说， 最简单的任务还是上面那三项就是了！所以，你需不需要防火墙呢？理论上，当然需要！ 而且你必须要知道‘你的系统哪些资料与服务需要保护’，针对需要受保护的服务来设定防火墙的规则吧！ 底下我们先来谈一谈，那在 Linux 上头常见的防火墙类型有哪些？

小标题的图示 Linux 系统上防火墙的主要类别
除了以软体及硬体作为防火墙的分类之外，我们也可以使用 防火墙对于资料封包的取得方式来进行分类。主要可以分为两大类， 分别是代理伺服器 (Proxy) 以及 IP Filter。在代理伺服器方面， 由名称我们就可以知道，代理伺服器仅是代理 Client 端去向 Internet 要求资料，所以 Proxy 其实已经将可代理的协定限制的很少很少，并且由于内部与外部电脑的并不能直接互通， 所以可以达到良好的保护效果；另一种则是上面提到的 IP fileter 啦！利用封包过滤的方式来达到防火墙的目的！

  • IP filter (封包过滤机制)
    直接使用进入本机的 TCP/IP 上面的封包协定来进行过滤分析，例如利用 TCP/IP 封包表头的 IP 来源、 Port number 等资料进行过滤，以判断该封包是否能够进入本机取得本机资源。由于这种方式可以直接分析最底层的封包表头资料， 所以包括硬体位址(MAC), 软体位址 (IP), TCP, UDP, ICMP 等封包的资讯都可以进行过滤分析的功能， 因此用途非常的广泛。

    在 Linux 上面我们使用核心内建的 iptables 软体来作为防火墙封包过滤的机制， 由于 iptables 是核心内建的功能，因此他的效率非常的高！非常适合于一般小型环境的设定呢！ 他利用一些封包过滤的规则设定，来定义出什么资料可以接收，什么资料需要剔除，以达到保护主机的目的喔！

  • Proxy (代理伺服器)
    其实代理伺服器是一种网路服务 (service, daemon)，他可以‘代理’使用者的需求， 而代为前往伺服器取得相关的资料。就有点像底下这个图示吧：

    Proxy Server 的运作原理简介
    图一、Proxy Server 的运作原理简介

    以上图为例，当 Client 端想要前往 Internet 取得 WWW 的资料时，他取得资料的流程是这样的：
    1. 他会向 proxy server 要求资料，请 proxy 帮忙处理；
    2. Proxy 可以分析使用者的 IP 来源是否合法？使用者想要去的 WWW 伺服器是否合法？ 如果这个 client 的要求都合法的话，那么 Proxy 就会主动的帮忙 client 前往 WWW 伺服器取得资料；
    3. Internet 所回传的资料是传给 Proxy server 的喔，所以 WWW 伺服器上面看到的是 Proxy Server 的 IP 啰；
    4. 最后 Proxy 将 client 的要求传回给 client。
    这样了解了吗？没错， client 并没有直接连上 Internet ，所以在实线部分(步骤 1, 4)只要 Proxy 与 Client 可以连线就可以了！此时 client 甚至不需要拥有 public IP 哩！而当有人想要攻击 client 端的主机时， 除非他能够攻破 Proxy server ，否则是无法与 client 连线的啦！

    另外，一般 proxy 主机通常仅开放 port 80, 21, 20 等 WWW 与 FTP 的埠口而已， 而且通常 Proxy 就架设在 Router 上面，因此可以完整的掌控区域网路内的对外连线！ 让你的 LAN 变的更安全啊！更详细的 Proxy 设定我们会在后续的 代理伺服器 章节当中提及的！

    在这个章节中，我们先不谈 Proxy 这个东西，而是介绍过滤机制的 iptables 啰！

    • 小标题的图示 防火墙的一般线路布线与抵挡技巧
    由前面的说明当中，您应该可以了解到一件事，那就是防火墙除了可以‘ 保护防火墙机制 (iptables) 本身所在的那部主机’之外，还可以‘ 保护防火墙后面的主机或 PC’。呵呵！ 也就是说，防火墙除了可以防备主机被入侵之外， 他还可以架设在路由器上面藉以控管进出本地端网域 (LAN) 的网路封包。 这种规划对于内部私有网域的安全也有一定程度的保护作用呢！底下我们稍微谈一谈目前常见的防火墙配置吧：

  • 单一 Linux 主机兼任防火墙功能：
    防火墙除了可以作为 Linux 本机的基本防护之外，他还可以架设在路由器上面以管控整个区域网路的封包进出。 因此，在这类的防火墙上头通常至少需要有两个介面，将可信任的内部与不可信任的 Internet 分开， 所以可以分别设定两块网路介面的防火墙规则啦！整个环境如同下列图二所示。

    在图二中，由于防火墙是设定在所有网路封包都会经过的路由器上头， 因此这个防火墙可以很轻易的就掌控到区域网路内的所有封包， 而且你只要管理这部防火墙主机，就可以很轻易的将来自 Internet 的不良网路封包抵挡掉呐。 只要管理一部主机就能够造福整的 LAN 里面的 PC，很划算的啦。

    如果你想要将区域网路控管的更严格的话，那你甚至可以在这部 Linux 防火墙上面架设更严格的代理伺服器， 让用户端仅能连上你所开放的 WWW 伺服器而已，而且还可以透过代理伺服器的登录档分析功能， 明确的查出来那个使用者在某个时间点曾经连上哪些 WWW 伺服器，您瞧瞧！厉害吧！ 如果在这个防火墙上面再加装类似 MRTG 的流量监控软体，还能针对整个网域的流量进行监测。 这样配置的优点是：
    • 因为内外网域已经分开，所以安全维护在内部可以开放的权限较大！
    • 安全机制的设定可以针对 Linux 主机来维护即可！
    • 对外只看的到 Linux 主机，所以对于内部可以达到有效的安全防护！
    单一 Linux 防火墙主机
    图二、单一 Linux 防火墙主机

  • 单一 Linux 防火墙，但 LAN 内另设防火墙
    一般来说，我们的防火墙对于 LAN 的防备都不会设定的很严格，因为是我们自己的 LAN 嘛！所以是信任网域之一啰！不过，最常听到的入侵方法也是使用这样的一个信任漏洞！ 因为您不能保证所有使用企业内部电脑的使用者都是公司的员工，也无法保证您的员工不会‘搞破坏！’ 更多时候是由于某些外来访客利用移动式装置 (笔记型电脑) 连接到公司内部的无线网路来加以窃取企业内部的重要资讯。

    呵呵！所以，如果您有特别重要的部门需要更安全的保护网路环境，那么将 LAN 里 面再加设一个防火墙，将安全等级分类，那么将会让您的重要资料获得更佳的保护喔！ 整个架构有点像下图三所示。

    单一 Linux 防火墙主机，但 LAN 内另设防火墙
    图三、单一 Linux 防火墙主机，但 LAN 内另设防火墙

  • 在防火墙后端的主机设定
    还有一种更有趣的设定，那就是将提供网路服务的伺服器放在防火墙后面，这有什么好处呢？ 如下图四所示，Web, Mail 与 FTP 都是透过防火墙连到 Internet 上面去，所以， 底下这四部主机在 Internet 上面的 Public IP 都是一样的！ (这个观念我们会在本章底下的 NAT 主机的时候再次的强调)。 只是透过防火墙的封包分析后，将 WWW 的要求封包转送到 Web 主机，将 Mail 送给 Mail Server 去处理而已(透过 port 的不同来转递)。

    好了，因为四部主机在 Internet 上面看到的 IP 都相同，但是事实上却是四部不同的主机， 而当有攻击者想要入侵您的 FTP 主机好了，他使用各种分析方法去进攻的主机，其实是‘防火墙’那一部， 攻击者想要攻击您内部的主机，除非他能够成功的搞定您的防火墙，否则就很难入侵您的内部主机呢！

    而且，由于主机放置在两部防火墙中间，内部网路如果发生状况时 (例如某些使用者不良操作导致中毒啊、 被社交工程攻陷导致内部主机被绑架啊等等的) ，是不会影响到网路主机的正常运作的。 这种方式适用在比较大型的企业当中，因为对这些企业来说，网路主机能否提供正常稳定的服务是很重要的！

    不过，这种架构下所进行的设定就得包含 port 的转递，而且要有很强的逻辑概念， 可以厘清封包双向沟通时的流动方式。对于新手来说，设定上有一定的难度， 鸟哥个人不太建议新手这么做，还是等以后有经验之后再来玩这种架构吧！

    架设在防火墙后端的主机伺服器
    图四、架设在防火墙后端的主机伺服器

    通常像上图四的环境中，将网路伺服器独立放置在两个防火墙中间的网路， 我们称之为非军事区域 (DMZ)。 DMZ 的目的就如同前面提到的，重点在保护伺服器本身， 所以将 Internet 与 LAN 都隔离开来，如此一来不论是伺服器本身，或者是 LAN 被攻陷时， 另一个区块还是完好无缺的！

    好了，那么我们 Linux 防火墙软体 iptables 是可以进行封包过滤的，他可以分析网路封包的 socket pair ， 还可以分析不同网路协定的状态，例如 TCP 封包的旗标 (flags) ，甚至可以分析网路卡的卡号呢！ 经由分析这些资料后，咱们的 iptables 至少可以有底下这几种抵挡封包的方式：
    • 拒绝让 Internet 的封包进入 Linux 主机的某些 port
      这个应该不难了解吧！例如您的 port 20-21 这个 FTP 相关的 port ， 您只要开放给内部网路的话，所以不对 Internet 开放，那么当 Internet 来的封包想要进入您的 port 20-21 的话，就可以将该资料封包丢掉！因为我们可以分析的到该封包所带有的 port 号码呀！

    • 拒绝让某些来源 IP 的封包进入
      例如您已经发现某个 IP 主要都是来自攻击行为的主机，那么只要来自该 IP 的资料封包，就将他丢弃！这样也可以达到基础的安全呦！

    • 拒绝让带有某些特殊旗标( flag )的封包进入
      最常拒绝的就是带有 SYN 的主动连线的旗标了！只要一经发现，嘿嘿！您就可以将该封包丢弃呀！

    • 分析硬体位址(MAC)来提供服务
      如果您的区域网路里面有比较捣蛋的但是又具有比较高强的网路功力的高手时，如果您使用 IP 来抵挡他使用网路的权限，而他却懂得反正换一个 IP 就好了，都在同一个网域内嘛！ 同样还是在搞破坏～怎么办？没关系，我们可以锁死他的网路卡硬体位址啊！因为 MAC 是焊在网路卡上面的，所以您只要分析到该使用者所使用的 MAC 之后，可以利用防火墙将该 MAC 锁住，呵呵！除非他能够一换再换他的网路卡来取得新的 MAC，否则换 IP 是没有用的啦！
    当然还有更多的使用技巧，你可以参考本章最后列出的参考资料， 里头有更多可用的小技巧喔。我们这里仅会真对简单的本机防火墙，以及作为类似 IP 分享器的 NAT 主机作简单的介绍而已啦！ ^_^！好了，开始来玩一玩那个 iptables 吧！

    • 小标题的图示 防火墙的使用限制
    什么？！设定防火墙之后还不安全啊？！那当然啦！谁说设定了防火墙之后您的系统就一定安全？ 防火墙虽然可以防止不受欢迎的封包进入我们的网路当中，不过，某些情况下， 他并不能保证我们的网路一定就很安全。举几个例子来谈一谈：
    • 防火墙并不能很有效的抵挡病毒或木马程式
      假设您已经开放了 WWW 的服务，那么您的 WWW 主机上面，防火墙一定得要将 WWW 服务的 port 开放给 Client 端登入才行吧！否则您的 WWW 主机设定了等于没有用对吧！也就是说，只要进入您的主机的封包是要求 WWW 资料的，就可以通过您的防火墙。那好了，‘万一您的 WWW 伺服器软体有漏洞，或者本身向您要求 WWW 服务的该封包就是病毒在侦测您的系统’时，您的防火墙可是一点办法也没有啊！ 因为本来设定的规则就是会让他通过啊。

    • 防火墙对于来自内部 LAN 的攻击较无承受力
      一般来说，我们对于 LAN 里面的主机都没有什么防火墙的设定，因为是我们自己的 LAN 啊，所以当然就设定为信任网域了！不过， LAN 里面总是可能有些网路小白啊，虽然他们不是故意要搞破坏， 但是他们就是不懂嘛！所以就乱用网路了。这个时候就很糟糕，因为防火墙对于内部的规则设定通常比较少， 所以就容易造成内部员工对于网路误用或滥用的情况。
    所以啦，在您的 Linux 主机实地上网之前，还是得先：
    • 关闭几个不安全的服务；
    • 升级几个可能有问题的套件；
    • 架设好最起码的安全防护--防火墙--
    其他相关的讯息请到 认识网路安全 里面去看一看怎么增加自身的安全吧！
    大标题的图示 Linux 的封包过滤机制：iptables
    上面谈了这么多，主要还是希望您能了解到防火墙是什么这个议题！而且也希望您知道防火墙并非万能的。 好了，那么底下我们终于可以来瞧一瞧，那目前我们的 2.6 版这个 Linux 核心到底使用什么核心功能来进行防火墙设定？

    小标题的图示 不同 Linux 核心版本的防火墙软体
    Linux 的防火墙为什么功能这么好？这是因为他本身就是由 Linux kernel 所提供， 由于直接经过核心来处理，因此效能非常好！不过，不同核心版本所使用的防火墙软体是不一样的！ 因为核心支援的防火墙是逐渐演进来的嘛！
    • Version 2.0：使用 ipfwadm 这个防火墙机制；
    • Version 2.2：使用的是 ipchains 这个防火墙机制；
    • Version 2.4 与 2.6 ：主要是使用 iptables 这个防火墙机制，不过在某些早期的 Version 2.4 版本的 distributions 当中，亦同时支援 ipchains (编译成为模组)，好让使用者仍然可以使用来自 2.2 版的 ipchains 的防火墙规划。不过，不建议在 2.4 以上的核心版本使用 ipchains 喔！
    因为不同的核心使用的防火墙机制不同，且支援的软体指令与语法也不相同， 所以在 Linux 上头设定属于你自己的防火墙规则时，要注意啊，先用 uname -r 追踪一下你的核心版本再说！ 如果你是安装 2004 年以后推出的 distributions ，那就不需要担心了，因为这些 distributions 几乎都使用 kernel 2.6 版的核心啊！ ^_^

    小标题的图示 iptables 的表格与封包进入流程
    前面的几个小节里面我们一直谈到：‘防火墙规则’，咦！啥是规则啊？因为 iptables 是利用封包过滤的机制， 所以他会分析封包的表头资料。根据表头资料与定义的‘规则’来决定该封包是否可以进入主机或者是被丢弃。 意思就是说：‘根据封包的分析资料 "比对" 你预先定义的规则内容， 若封包资料与规则内容相同则进行动作，否则就继续下一条规则的比对！’ 重点在那个‘比对与分析顺序’上。

    举个简单的例子，假设我预先定义 10 条防火墙规则好了，那么当 Internet 来了一个封包想要进入我的主机， 那么防火墙是如何分析这个封包的呢？我们以底下的图示来说明好了：

    封包过滤的规则动作及分析流程
    图五、封包过滤的规则动作及分析流程

    当一个网路封包要进入到主机之前，会先经由 NetFilter 进行检查，那就是 iptables 的规则了。 检查通过则接受 (ACCEPT) 进入本机取得资源，如果检查不通过，则可能予以丢弃 (DROP) ！ 上图五主要的目的在告知您：‘规则是有顺序的’！例如当网路封包进入 Rule 1 的比对时， 如果比对结果符合 Rule 1 ，此时这个网路封包就会进行 Action 1 的动作，而不会理会后续的 Rule 2, Rule 3.... 等规则的分析了。

    而如果这个封包并不符合 Rule 1 的比对，那就会进入 Rule 2 的比对了！如此一个一个规则去进行比对就是了。 那如果所有的规则都不符合怎办？此时就会透过预设动作 (封包政策, Policy) 来决定这个封包的去向。 所以啦，当您的规则顺序排列错误时，就会产生很严重的错误了。 怎么说呢？让我们看看底下这个例子：

    假设您的 Linux 主机提供了 WWW 的服务，那么自然就要针对 port 80 来启用通过的封包规则，但是您发现 IP 来源为 192.168.100.100 老是恶意的尝试入侵您的系统，所以您想要将该 IP 拒绝往来，最后，所有的非 WWW 的封包都给他丢弃，就这三个规则来说，您要如何设定防火墙检验顺序呢？
    1. Rule 1 先抵挡 192.168.100.100 ；
    2. Rule 2 再让要求 WWW 服务的封包通过；
    3. Rule 3 将所有的封包丢弃。
    这样的排列顺序就能符合您的需求，不过，万一您的顺序排错了，变成：
    1. Rule 1 先让要求 WWW 服务的封包通过；
    2. Rule 2 再抵挡 192.168.100.100 ；
    3. Rule 3 将所有的封包丢弃。
    此时，那个 192.168.100.100 ‘可以使用您的 WWW 服务’喔！因为只要他对您的主机送出 WWW 要求封包，就可以使用您的 WWW 主机功能了，因为您的规则顺序定义第一条就会让他通过， 而不去考虑第二条规则！这样可以理解规则顺序的意义了吗！现在再来想一想，如果 Rule 1 变成了‘将所有的封包丢弃’，Rule 2 才设定‘WWW 服务封包通过’，请问，我的 client 可以使用我的 WWW 服务吗？呵呵！答案是‘否～’想通了吗？ ^_^

  • iptables 的表格与链 (chain)
    事实上，那个图五所列出的规则仅是 iptables 众多表格当中的一个链 (chain) 而已。 什么是链呢？这得由 iptables 的名称说起。为什么称为 ip"tables" 呢？ 因为这个防火墙软体里面有多个表格 (table) ，每个表格都定义出自己的预设政策与规则， 且每个表格都用途都不相同。我们可以使用底下这张图来稍微了解一下：

    iptables 的表格示意图
    图六、iptables 的表格示意图

    刚刚图五的规则内容仅只是图六内的某个 chain 而已！ 而预设的情况下，咱们 Linux 的 iptables 至少就有三个表格，包括管理本机进出的 filter 、管理后端主机 (防火墙内部的其他电脑) 的 nat 、 管理特殊旗标使用的 mangle (较少使用) 。更有甚者，我们还可以自订额外的链呢！ 真是很神奇吧！每个表格与其中链的用途分别是这样的：
    • filter：主要跟 Linux 本机有关，这个是预设的 table 喔！
      • INPUT：主要与封包想要进入我们 Linux 本机有关；
      • OUTPUT：主要与我们 Linux 本机所要送出的封包有关；
      • FORWARD：这个咚咚与 Linux 本机比较没有关系，他可以封包‘转递’到后端的电脑中，与 nat 这个 table 相关性很高。

    • nat：这个表格主要在用作来源与目的之 IP 或 port 的转换， 与 Linux 本机较无关，主要与 Linux 主机后的区域网路内的电脑较有相关。
      • PREROUTING：在进行路由判断之前所要进行的规则(DNAT/REDIRECT)
      • POSTROUTING：在进行路由判断之后所要进行的规则(SNAT/MASQUERADE)
      • OUTPUT：与发送出去的封包有关

    • mangle：这个表格主要是与特殊的封包的路由旗标有关， 早期仅有 PREROUTING 及 OUTPUT 链，不过从 kernel 2.4.18 之后加入了 INPUT 及 FORWARD 链。 由于这个表格与特殊旗标相关性较高，所以像咱们这种单纯的环境当中，较少使用 mangle 这个表格。
    那么各个表格与链的相关性可以使用下图来表示：

    iptables 内建各表格与链的相关性
    图七、iptables 内建各表格与链的相关性

    上面的图示很复杂喔！不过基本上你依旧可以看出来，我们的 iptables 可以控制两种封包的流向：
    • 如上图的 A ，封包主要是要读取我们 Linux 本机内的资料，会经过 filter 的 INPUT 链， 而资料的输出则是经过 filter 的 OUTPUT 链；
    • 如上图的 B ，封包主要是要透过防火墙而去后端，也就是说，该封包的目标并非我们的 Linux 本机。 主要经过的链是 filter 的 FORWARD 以及 nat 的 POSTROUTING, PREROUTING。
    由于 mangle 这个表格很少被使用，如果将图七的 mangle 拿掉的话，那就容易看的多了：

    iptables 内建各表格与链的相关性(简图)
    图八、iptables 内建各表格与链的相关性(简图)

    透过图八你就可以更轻松的了解到，事实上与本机最有关的其实是 filter 这个表格内的 INPUT 与 OUTPUT 这两条链，如果你的 iptables 只是用来防备 Linux 主机本身的话，那 nat 的规则根本就不需要理他，直接设定为开放即可。

    不过，如果你的防火墙事实上是用来管制 LAN 内的其他主机的话，那么你就必须要再针对 filter 的 FORWARD 这条链，还有 nat 的 PREROUTING, POSTROUTING 以及 OUTPUT 进行额外的规则订定才行。 nat 表格的使用需要很清晰的路由概念才能够设定的好，建议新手先不要碰！ 最多就是先玩一玩最阳春的 nat 功能‘IP 分享器的功能’就好了！ ^_^！ 这部份我们在本章的最后一小节会介绍的啦！
    • 小标题的图示 本机的 iptables 语法
    理论上，当你安装好 Linux 之后，系统应该会主动的帮你启动一个阳春的防火墙规则才是。 不过如果您是依照鸟哥的建议来安装 Linux 时，那么安装完毕后，你的系统应该是没有防火墙的啦。 另外，某些早期的版本 (例如 Red Hat 9) 本身同时提供 iptables 及 ipchains 这两个防火墙模组， 不过这两个模组是无法同时存在的！所以你仅能启动其中一个，那当然是启动 iptables 才对啊！ 如果不小心启动了 ipchains 的话 (新版的 Linux 都不会有这个困扰) ，那请使用 rmmod 来移除吧！

    不过，在开始进行底下的练习之前，鸟哥这里有个很重要的事情要告知一下。 因为 iptables 的指令会将网路封包进行过滤及抵挡的动作，所以 请不要在远端主机上进行防火墙的练习，因为您很有可能一不小心将自己关在家门外！ 尽量在本机前面登入 tty1-tty6 终端机进行练习，否则常常会发生悲剧啊！ 鸟哥以前刚刚在玩 iptables 时，就常常因为不小心规则设定错误，导致常常要请远端的朋友帮忙重新开机...

    刚刚提到咱们的 iptables 至少有三个预设的 table (filter, nat, mangle)，较常用的是本机的 filter 表格， 这也是预设表格啦。另一个则是后端主机的 nat 表格，至于 mangle 较少使用，所以这个章节我们并不会讨论 mangle。 由于不同的 table 他们的链不一样，导致使用的指令语法或多或少都有点差异。 在这个小节当中，我们主要将针对 filter 这个预设表格的三条链来做介绍。底下就来玩一玩吧！
    Tips:
    防火墙的设定主要使用的就是 iptables 这个指令而已。而防火墙是系统管理员的主要任务之一， 且对于系统的影响相当的大，因此‘只能让 root 使用 iptables ’，不论是设定还是观察防火墙规则喔！     		鸟哥的图示
  • 规则的清除与观察
    如果你在安装的时候选择没有防火墙的话，那么 iptables 在一开始的时候应该是没有规则的，不过， 可能因为你在安装的时候就有选择系统自动帮您建立防火墙机制，那系统就会有预设的防火墙规则了！ 无论如何，我们先来看看目前本机的防火墙规则是如何吧！
    [root@linux ~]# iptables [-t tables] [-L] [-nv]
参数：
-t ：后面接 table ，例如 nat 或 filter ，若省略此项目，则使用预设的 filter
-L ：列出目前的 table 的规则
-n ：不进行 IP 与 HOSTNAME 的反查，显示讯息的速度会快很多！
-v ：列出更多的资讯，包括通过该规则的封包总位元数、相关的网路介面等

范例：列出 filter table 三条链的规则
[root@linux ~]# iptables -L -n
Chain FORWARD (policy ACCEPT)
target     prot opt source               destination

Chain INPUT (policy ACCEPT)
target     prot opt source               destination

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

范例：列出更多的资讯
[root@linux ~]# iptables -L -nv
Chain INPUT (policy ACCEPT 5748 packets, 746K bytes)
 pkts bytes target     prot opt in     out     source               destination
....底下省略....
    仔细看到上面表格的输出，因为没有加上 -t 的参数，所以预设就是 filter 这个表格内的 INPUT, OUTPUT, FORWARD 三条链的规则啰。由于没有规则嘛！所以每个链内部的规则都是空的。 同时注意一下，在每个 chain 后面括号内的 policy 项目，那就是‘预设动作(政策)’咯！以上面来看， 虽然我们启动了 iptables ，但是我们没有设定规则，然后政策又是 ACCEPT， 所以是‘任何封包都会接受’的意思喔！至于如果加上 -v 的参数时， 则连同该规则所通过的封包总位元数也会被列出来啊。底下则是 nat 表格的规则项目：
    [root@linux ~]# iptables -t nat -L -n
Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

Chain POSTROUTING (policy ACCEPT)
target     prot opt source               destination

Chain PREROUTING (policy ACCEPT)
target     prot opt source               destination
    瞧！与 fiter 表格一模一样吧！只是三条链的内容不同啰！要注意啊！ ^_^！ 以后当你设定每一条防火墙的规则时，记得瞧一瞧设定先！好，那如何清除规则？这样做就对了：
    [root@linux ~]# iptables [-t tables] [-FXZ]
参数：
-F ：清除所有的已订定的规则；
-X ：杀掉所有使用者 "自订" 的 chain (应该说的是 tables ）啰；
-Z ：将所有的 chain 的计数与流量统计都归零

范例：清除本机防火墙 (filter) 的所有规则
[root@linux ~]# iptables -F
[root@linux ~]# iptables -X
[root@linux ~]# iptables -Z
    由于这三个指令会将本机防火墙的所有规则都清除，但却不会改变预设政策 (policy) ， 所以如果你不是在本机下达这三行指令时，很可能你会被自己挡在家门外 (若 INPUT 设定为 DROP 时)！ 要小心啊！

    一般来说，我们在重新定义防火墙的时候，都会先将规则给他清除掉。还记得我们前面谈到的， 防火墙的‘规则顺序’是有特殊意义的，所以啰， 当然先清除掉规则，然后一条一条来设定会比较容易一点啦。底下就来谈谈定义预设政策吧！

  • 定义预设政策 (policy)
    清除规则之后，再接下来就是要设定规则的政策啦！还记得政策指的是什么吗？‘ 当您的封包不在您设定的规则之内时，则该封包的通过与否，以 Policy 的设定为准’，在本机方面的预设政策中，假设您对于内部的使用用者有信心的话， 那么 filter 内的 INPUT 链方面可以定义的比较严格一点，而 FORWARD 与 OUTPUT 则可以订定的松一些！通常鸟哥都是将 INPUT 的 policy 定义为 DROP 啦，其他两个则定义为 ACCEPT。 至于 nat table 则暂时不理会他。
    [root@linux ~]# iptables [-t nat] -P [INPUT,OUTPUT,FORWARD] [ACCEPT,DROP]
参数：
-P ：定义政策( Policy )。注意，这个 P 为大写啊！
ACCEPT ：该封包可接受
DROP   ：该封包直接丢弃，不会让 client 端知道为何被丢弃。

范例：将本机的 INPUT 设定为 DROP ，其他设定为 ACCEPT
[root@linux ~]# iptables -P   INPUT DROP
[root@linux ~]# iptables -P  OUTPUT ACCEPT
[root@linux ~]# iptables -P FORWARD ACCEPT
[root@linux ~]# iptables -L -n
Chain FORWARD (policy ACCEPT)
target     prot opt source               destination

Chain INPUT (policy DROP)
target     prot opt source               destination

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination
# 由于 INPUT 设定为 DROP 而又尚未有任何规则，所以上面的输出结果显示：
# 所有的封包都无法进入你的主机！是不通的防火墙设定！(网路连线是双向的)
    看到输出的结果了吧？INPUT 被修改设定了喔！其他的 nat table 三条链的设定也是一样的，例如：‘ iptables -t nat -P PREROUTING ACCEPT ’就设定了 nat table 的 PREROUTING 链为可接受的意思！预设政策设定完毕后，来谈一谈关于封包的基础比对设定吧。

  • 封包的基础比对 IP/netmask I/O 装置
    开始来进行封包的比对设定吧！我们先由最基础的 IP 与网域的特征谈起，再谈装置 (网路卡) 的限制等等。
    [root@linux ~]# iptables [-AI 链] [-io 网路介面] [-p 协定] \
> [-s 来源IP/网域] [-d 目标IP/网域] -j [ACCEPT|DROP]
参数：
-AI 链：针对某的链进行规则的 "插入" 或 "累加"
    -A ：新增加一条规则，该规则增加在原本规则的最后面。例如原本已经有四条规则，
         使用 -A 就可以加上第五条规则！
    -I ：插入一条规则。如果没有指定此规则的顺序，预设是插入变成第一条规则。
         例如原本有四条规则，使用 -I 则该规则变成第一条，而原本四条变成 2~5 号
    链 ：有 INPUT, OUTPUT, FORWARD 等，此链名称又与 -io 有关，请看底下。

-io 网路介面：设定封包进出的介面规范
    -i ：封包所进入的那个网路介面，例如 eth0, lo 等介面。需与 INPUT 链配合；
    -o ：封包所传出的那个网路介面，需与 OUTPUT 链配合；

-p 协定：设定此规则适用于哪种封包格式
   主要的封包格式有： tcp, udp, icmp 及 all 。

-s 来源 IP/网域：设定此规则之封包的来源项目，可指定单纯的 IP 或包括网域，例如：
   IP  ：192.168.0.100
   网域：192.168.0.0/24, 192.168.0.0/255.255.255.0 均可。
   若规范为‘不许’时，则加上 ! 即可，例如：
   -s ! 192.168.100.0/24 表示不许 192.168.100.0/24 之封包来源；

-d 目标 IP/网域：同 -s ，只不过这里指的是目标的 IP 或网域。

-j ：后面接动作，主要的动作有接受 (ACCEPT)、丢弃 (DROP) 及记录 (LOG)
    iptables 的基本参数就如同上面所示的，仅只谈到 IP 、网域与装置等等的资讯， 至于 TCP, UDP 封包特有的埠口 (port number) 与状态 (如 SYN 旗标) 则在下小节才会谈到。 好，先让我们来看看最基础的几个规则，例如开放 lo 这个本机的介面以及某个 IP 来源吧！
    范例一：所有的来自 lo 这个介面的封包，都予以接受
[root@linux ~]# iptables -A INPUT -i lo -j ACCEPT
# 仔细看上面并没有列出 -s, -d 等等的规则，这表示：不论封包来自何处或去到哪里，
# 只要是来自 lo 这个介面，就予以接受！这个观念挺重要的，就是
#‘没有设定的规定，则表示该规定完全接受’的意思！例如这个案例当中，
# 关于 -s, -d...等等的参数没有规定时

范例二：目标来自 192.168.0.1 这个 IP 的封包都予以接受
[root@linux ~]# iptables -A INPUT -i eth0 -s 192.168.0.1 -j ACCEPT
# 不管什么封包格式，只要来自 192.168.0.1 就予以接受。

范例三：目标来自 192.168.1.0/24 可接受，但 192.168.1.10 丢弃
[root@linux ~]# iptables -A INPUT -i eth0 -s 192.168.1.10 -j DROP
[root@linux ~]# iptables -A INPUT -i eth0 -s 192.168.1.0/24 -j ACCEPT
# 上述这两个范例很重要啊！因为有点关系！要先丢弃 192.168.1.10 才能接受该网域。

[root@linux ~]# iptables -L -n
Chain INPUT (policy DROP)
target     prot opt source               destination
ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0
ACCEPT     all  --  192.168.0.1          0.0.0.0/0
DROP       all  --  192.168.1.10         0.0.0.0/0
ACCEPT     all  --  192.168.1.0/24       0.0.0.0/0
# 瞧！刚刚的设定在这里已经生效啰！
    这就是最单纯、简单的防火墙规则的设定与观察方式。你在设定完毕后，都可以利用 iptables -L -n 或 iptables -L -v 来简单的查阅一下。而如果你想要记录某个规则的纪录怎么办？可以这样做：
    [root@linux ~]# iptables -A INPUT -s 192.168.2.200 -j LOG
[root@linux ~]# iptables -L -n
target prot opt source         destination
LOG    all  --  192.168.2.200  0.0.0.0/0   LOG flags 0 level 4
    看到输出结果的最左边，会出现的是 LOG 喔！只要有封包来自 192.168.2.200 这个 IP 时， 那么该封包的相关资讯就会被写入到核心讯息，亦即是 /var/log/messages 这个档案当中。 然后该封包会继续进行后续的规则比对。所以说， LOG 这个动作仅在进行记录而已，并不会影响到这个封包的其他规则比对的。 好了，接下来我们分别来看看 TCP,UDP 以及 ICMP 封包的其他规则比对吧！

  • TCP, UDP 的规则比对
    我们在网路基础谈过各种不同的封包格式， 在谈到 TCP 与 UDP 时，比较特殊的就是那个埠口 (port number)，在 TCP 方面则另外有所谓的连线封包状态， 包括最常见的 SYN 主动连线的封包格式。那么如何针对这两种封包格式进行防火墙规则的设定呢？你可以这样看：
    [root@linux ~]# iptables [-AI 链] [-io 网路介面] [-p tcp,udp] \
> [-s 来源IP/网域] [--sport 埠口范围] \
> [-d 目标IP/网域] [--dport 埠口范围] -j [ACCEPT|DROP]
参数：
--sport 埠口范围：限制来源的埠口号码，埠口号码可以是连续的，例如 1024:65535
--dport 埠口范围：限制目标的埠口号码。
    事实上就是多了那个 --sport 及 --dport 这两个玩意儿，重点在那个 port number 上面啦！ 底下让我们来进行几个小测试：
    范例一：想要连线进入本机 port 21 的封包都抵挡掉：
[root@linux ~]# iptables -A INPUT -i eth0 -p tcp --dport 21 -j DROP

范例二：想连到我这部主机的网芳 (upd port 137,138 tcp port 139,445) 就放行
[root@linux ~]# iptables -A INPUT -i eth0 -p udp --dport 137:138 -j ACCEPT
[root@linux ~]# iptables -A INPUT -i eth0 -p tcp --dport 139 -j ACCEPT
[root@linux ~]# iptables -A INPUT -i eth0 -p tcp --dport 445 -j ACCEPT
    瞧！你可以利用 UDP 与 TCP 协定所拥有的埠口号码来进行某些服务的开放或关闭喔！ 你还可以综合处理呢！例如：只要来自 192.168.1.0/24 的 1024:65535 埠口的封包， 只要想要连线到本机的 ssh port 就予以抵挡，可以这样做：
    [root@linux ~]# iptables -A INPUT -i eth0 -p tcp -s 192.168.1.0/24 \
> --sport 1024:65534 --dport ssh -j DROP
    注意啊！如果你有使用到 --sport 及 --dport 的参数时，就必须指定 udp 或 tcp 的封包格式才行！否则的话， iptables 的指令就会出现如下的错误：
    [root@linux ~]# iptables -A INPUT -i eth0 --dport 21 -j DROP
iptables v1.2.11: Unknown arg `--dport'
Try `iptables -h' or 'iptables --help' for more information.
    你应该会觉得很奇怪，怎么‘ --dport ’会是未知的参数 (arg) 呢？这是因为你没有加上 -p tcp 或 -p udp 的缘故啊！因为 port 是 TCP,UDP 特有的，其他类似 ICMP 则没有这种类的埠口资料啊！ 这样说，您可以理解吧！ ^_^

    除了埠口之外，在 TCP 还有特殊的旗标啊！最常见的就是那个主动连线的 SYN 旗标了。 我们在 iptables 里面还支援‘ --syn ’的处理方式，我们以底下的例子来说明好了：
    范例：将来自任何地方来源 port 1:1023 的主动连线到本机端的 1:1023 连线丢弃
[root@linux ~]# iptables -A INPUT -i eth0 -p tcp --sport 1:1023 \
> --dport 1:1023 --syn -j DROP
    一般来说，client 端启用的 port 都是大于 1024 以上的埠口，而 server 端则是启用小于 1023 以下的埠口在监听的。所以我们可以让来自远端的小于 1023 以下的埠口资料的主动连线都给他丢弃！ 但不适用在 FTP 的主动连线中！这部份我们未来在 FTP 章节当中再来谈吧！

  • 状态模组：MAC 与 RELATED
    在早期的 kernel 2.2 以前使用 ipchains 管理防火墙时，通常会让系统管理员相当头痛！ 因为 ipchains 没有所谓的封包状态模组，因此我们必须要针对封包的进、出方向进行管控。 举例来说，如果你想要连线到远端主机的 port 22 时，你必须要针对两条规则来设定：
    • 本机端的 1024:65535 到远端的 port 22 必须要放行 (OUTPUT 链)；
    • 远端主机 port 22 到本机的 1024:65535 必须放行 (INPUT 链)；
    这会很麻烦！因为如果你要连线到 10 部主机的 port 22 时，假设 OUTPUT 为预设开启 (ACCEPT)， 你依旧需要填写十行规则，让那十部远端主机的 port 22 可以连线到你的本地端主机上。 那如果开启全部的 port 22 呢？又担心某些恶意主机会主动以 port 22 连线到你的机器上！ 同样的道理，如果你要让本地端主机可以连到外部的 port 80 (WWW 服务)，那就更不得了～ 这就是网路连线是双向的一个很重要的概念！

    好在我们的 iptables 免除了这个困扰！他可以透过一个状态模组来分析 ‘这个想要进入的封包是否为刚刚我发出去的回应？’ 如果是刚刚我发出去的回应，那么就可以予以接受放行！哇！真棒！这样就不用管远端主机是否连线进来的问题了！ 那如何达到呢？看看底下的语法：
    [root@linux ~]# iptables -A INPUT -m state --state 状态
参数：
-m ：一些 iptables 的模组，主要常见的有：
     state ：状态模组
     mac   ：网路卡硬体位址 (hardware address)
--state ：一些封包的状态，主要有：
     INVALID    ：无效的封包，例如资料破损的封包状态
     ESTABLISHED：已经连线成功的连线状态；
     NEW        ：想要新建立连线的封包状态；
     RELATED    ：这个最常用！表示这个封包是与我们主机发送出去的封包有关

范例：只要已建立或相关封包就予以通过，只要是不合法封包就丢弃
[root@linux ~]# iptables -A INPUT -m state \
> --state RELATED,ESTABLISHED -j ACCEPT
[root@linux ~]# iptables -A INPUT -m state --state INVALID -j DROP
    所以说，如果你的 Linux 主机只想要作为 client 的用途，不许所有主动对你连线的来源， 那么你可以这样做即可：
    1. 清除所有已经存在的规则 (iptables -F...)
    2. 设定预设政策，除了 INPUT 预设为 DROP 其他为预设 ACCEPT；
    3. 开放本机的 lo 可以自由放行；
    4. 设定有相关的封包状态可以连线进入本机。
    这就是最最阳春的防火墙，你可以透过第二步骤抵挡所有远端的来源封包， 而透过第四步骤让你要求的远端主机回应封包可以进入， 加上让本机的 lo 这个内部回圈装置可以放行，嘿嘿！一部 client 专用的防火墙规则就 OK 了！ 你可以在某个 script 上面这样做即可：
    #!/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin; export PATH
iptables -F
iptables -X
iptables -Z
iptables -P   INPUT DROP
iptables -P  OUTPUT ACCEPT
iptables -P FORWARD ACCEPT
iptables -A INPUT -i lo -j ACCEPT
iptables -A INPUT -i eth0 -m state --state RELATED,ESTABLISHED -j ACCEPT
#iptables -A INPUT -i eth0 -s 192.168.1.0/24 -j ACCEPT
    那如果区域网路内有其他的主机时，再将上表最后一行的 # 取消，就可以接受来自本地 LAN 的其他主机的连线了。 而如果你担心某些 LAN 内的恶意来源主机会主动的对你连线时，那你还可以针对信任的本地端主机的 MAC 进行过滤！ 同样是使用状态模组！这次的状态则是 MAC 的比对。举例来说：
    范例一：针对区域网路内的 aa:bb:cc:dd:ee:ff 主机开放其连线
[root@linux ~]# iptables -A INPUT -m mac --mac-source aa:bb:cc:dd:ee:ff \
>  -j ACCEPT
参数：
--mac-source ：就是来源主机的 MAC 啦！
    透过这个玩意儿，你就可以定义更严格的 LAN 内的其他主机能否连线到你的主机的权限了！

  • ICMP 封包规则的比对
    在网路基础的 ICMP 协定当中我们知道 ICMP 的格式相当的多，而且很多 ICMP 封包的类型格式都是为了要用来进行网路检测用的！ 所以最好不要将所有的 ICMP 封包都丢弃！通常我们会把 ICMP type 8 (echo request) 拿掉而已， 让远端主机不知道我们是否存在，也不会接受 ping 的回应就是了。ICMP 封包格式的处理是这样的：
    [root@linux ~]# iptables -A INPUT -p icmp --icmp-type 类型 -j ACCEPT
参数：
--icmp-type ：后面必须要接 ICMP 的封包类型，也可以使用代号，
              例如 8  代表 echo request 的意思。

范例：让 0,3,4,11,12,14,16,18 的 ICMP type 可以进入本机：
[root@linux ~]# vi somefile
#!/bin/bash
icmp_type="0 3 4 11 12 14 16 18"
for typeicmp in $icmp_type
do
   iptables -A INPUT -i eth0 -p icmp --icmp-type $typeicmp -j ACCEPT
done

[root@linux ~]# sh  somefile
    这样就能够开放部分的 ICMP 封包格式进入本机进行网路检测的工作了！真好！不是嘛！^_^
    • 小标题的图示 防火墙的记录、回复与测试
    刚刚上面我们谈了很多的设定了，那么我该如何观察目前主机上面的防火墙规则呢？ 我们可以使用‘iptables -L -n ’来观察，不过，该指令所显示的资讯其实还是不太足够的。 这个时候，我们其实可以使用底下的两个指令来将目前主机上面的防火墙机制‘储存’下来， 在下次想要将这个规则‘回复’的时候，就能够直接利用指令将规则直接回复喔！
    [root@linux ~]# iptables-save > filename
[root@linux ~]# iptables-restore < filename
    一个是储存一个是回复！而在 Red Hat 系统的 RHEL,CentOS,Fedora 当中，如果你将那个 filename 档案存成‘ /etc/sysconfig/iptables ’，并且利用 chkconfig 将 iptables 在开机时预设启动的话，那么一开机系统就会主动的帮你把防火墙的规则给载入了就是！ 那么使用 iptables-save 所得到的结果会是如何呢？让我们来看看：
    [root@linux ~]# iptables-save
# Generated by iptables-save v1.2.11 on Mon Sep 11 17:47:35 2006
*filter    <==使用的 table
:INPUT DROP [7335:859454] <==三条预设的链与预设政策
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [16992:13134791]
-A INPUT -i lo -j ACCEPT  <==开始各个规则的设定
-A INPUT -m state --state RELATED -j ACCEPT
-A INPUT -m mac --mac-source 00:04:75:D0:A2:58 -j ACCEPT
-A INPUT -m state --state ESTABLISHED -j ACCEPT
-A INPUT -i eth0 -p icmp -m icmp --icmp-type 0 -j ACCEPT
-A INPUT -i eth0 -p icmp -m icmp --icmp-type 3 -j ACCEPT
....中间省略....
-A INPUT -i eth0 -p tcp -m tcp --dport 22 -j ACCEPT
COMMIT
# Completed on Mon Sep 11 17:47:35 2006
# 井号 (#) 是注解，星号 (*) 代表预设的 table，而冒号 (:) 代表各条链的预设政策；
# 后续的动作则是各个规则啦！
    你瞧到输出的结果啦！整个资料几乎就是类似手动在指令列模式输入的指令！ 比起 iptables -L -n 所得到的资讯要仔细的多。这也是 iptables 的特殊格式， 可以用在 iptables-restore 的指令读入呢！ 比起这种方式，鸟哥还是比较喜欢使用 script 来撰写自己的防火墙规则啦。 制订好规则后当然就是要测试啰！那么如何测试呢？
    1. 先由主机向外面主动连线试看看；
    2. 再由私有网域内的 PC 向外面主动连线试看看；
    3. 最后，由 Internet 上面的主机，主动连线到您的 Linux 主机试看看；
    一步一步作下来，看看问题出在哪里，然后多多的去改进、改良！基本上， 网路上目前很多的资料可以提供您不错的参考了！这一篇的设定写的是很简单， 大部分都还在介绍阶段而已！希望对大家有帮助！ 鸟哥在参考资料当中列出几个有用的防火墙网页， 希望大家有空真的要多多的去看看！会很有帮助的！

    小标题的图示 IPv4 的核心管理功能： /proc/sys/net/ipv4/*
    除了 iptables 这个防火墙软体之外，其实咱们 Linux kernel 2.6 提供很多核心预设的攻击抵挡机制喔！ 由于是核心的网路功能，所以相关的设定资料都是放置在 /proc/sys/net/ipv4/ 这个目录当中。 至于该目录下各个档案的详细资料，可以参考核心的说明文件：
    • /usr/src/linux-{version}/networking/ip-sysctl.txt
    上面的这个说明资料可以由 http://www.kernel.org 这个网站下载任何一个核心原始码后，解压缩就能够看到。 鸟哥这里也放一份备份：
    • http:/linux.vbird.org0250simple_firewall/ip-sysctl.txt
    有兴趣的话应该要自行去查一查比较好的喔！我们底下就拿几个简单的档案来作说明吧！

  • /proc/sys/net/ipv4/tcp_syncookies
    我们在前一章谈到所谓的阻断式服务 (DoS) 攻击法当中的一种方式，就是利用 TCP 封包的 SYN 三向交握原理所达成的， 这种方式称为 SYN Flooding 。那如何预防这种方式的攻击呢？我们可以启用核心的 SYN Cookie 模组啊！ 这个 SYN Cookie 模组可以在系统用来启动随机连线的埠口 (1024:65535) 即将用完时自动启动。

    当启动 SYN Cookie 时，主机在发送 SYN/ACK 确认封包前，会要求 Client 端在短时间内回覆一个序号， 这个序号包含许多原本 SYN 封包内的资讯，包括 IP、port 等。若 Client 端可以回覆正确的序号， 那么主机就确定该封包为可信的，因此会发送 SYN/ACK 封包，否则就不理会此一封包。

    透过此一机制可以大大的降低无效的 SYN 等待埠口，而避免 SYN Flooding 的 DoS 攻击说！ 那么如何启动这个模组呢？很简单，这样做即可：
    [root@linux ~]# echo "1" > /proc/sys/net/ipv4/tcp_syncookies
    但是这个设定值由于违反 TCP 的三向交握 (因为主机在发送 SYN/ACK 之前需要先等待 client 的序号回应)， 所以可能会造成某些服务的延迟现象，例如 SMTP (mail server)。 不过总的来说，这个设定值还是不错用的！ 只是不适合用在负载已经很高的伺服器内喔！ 因为负载太高的主机有时会让核心误判遭受 SYN Flooding 的攻击呢。

    如果是为了系统的 TCP 封包连线最佳化，则可以参考 tcp_max_syn_backlog, tcp_synack_retries, tcp_abort_on_overflow 这几个设定值的意义。

  • /proc/sys/net/ipv4/icmp_echo_ignore_broadcasts
    阻断式服务常见的是 SYN Flooding ，不过，我们知道系统其实可以接受使用 ping 的回应， 而 ping 的封包是可以给很大的！想像一个状况， 如果有个搞破坏的人使用 1000 台主机传送 ping 给你的主机，而且每个 ping 都高达数百 K bytes时， 你的网路频宽会怎样？要嘛就是频宽被吃光，要嘛可能系统会当机！ 这种方式分别被称为 ping flooding (不断发 ping) 及 ping of death (发送大的 ping 封包)。

    那如何避免呢？取消 ICMP 类型 8 的 ICMP 封包回应就是了。我们可以透过防火墙来抵挡， 这也是比较建议的方式。当然也可以让核心自动取消 ping 的回应。不过您必须要了解， 某些区域网路内常见的服务 (例如动态 IP 分配 DHCP 协定) 会使用 ping 的方式来侦测是否有重复的 IP ，所以你最好不要取消所有的 ping 回应比较好。

    核心取消 ping 回应的设定值有两个，分别是：/proc/sys/net/ipv4 内的 icmp_echo_ignore_broadcasts (仅有 ping broadcast 位址时才取消 ping 的回应) 及 icmp_echo_ignore_all (全部的 ping 都不回应)。鸟哥建议设定 icmp_echo_ignore_broadcasts 就好了。 你可以这么做：
    [root@linux ~]# echo "1" >  \
> /proc/sys/net/ipv4/icmp_echo_ignore_broadcasts
  • /proc/sys/net/ipv4/conf/网路介面/*
    咱们的核心还可以针对不同的网路介面进行不一样的参数设定喔！网路介面的相关设定放置在 /proc/sys/net/ipv4/conf/ 当中，每个介面都以介面代号做为其代表，例如 eth0 介面的相关设定资料在 /proc/sys/net/ipv4/conf/eth0/ 内。那么网路介面的设定资料有哪些比较需要注意的呢？ 大概有底下这几个：
    • rp_filter：称为逆向路径过滤 (Reverse Path Filtering)， 可以藉由分析网路介面的路由资讯配合封包的来源位址，来分析该封包是否为合理。举例来说，你有两张网卡，eth0 为 192.168.10.100/24 ，eth1 为 public IP 。那么当有一个封包自称来自 eth1 ，但是其 IP 来源为 192.168.10.200 ， 那这个封包就不合理，应予以丢弃。这个设定值建议可以启动的。

    • log_martians：这个设定资料可以用来启动记录不合法的 IP 来源， 举例来说，包括来源为 0.0.0.0、127.x.x.x、及 Class E 的 IP 来源，因为这些来源的 IP 不应该应用于 Internet 啊。 记录的资料预设放置到核心放置的登录档 /var/log/messages。

    • accept_source_route：或许某些路由器会启动这个设定值， 不过目前的设备很少使用到这种来源路由，你可以取消这个设定值。

    • accept_redirects：当你在同一个实体网域内架设一部路由器， 但这个实体网域有两个 IP 网域，例如 192.168.0.0/24, 192.168.1.0/24。此时你的 192.168.0.100 想要向 192.168.1.100 传送讯息时，路由器可能会传送一个 ICMP redirect 封包告知 192.168.0.100 直接传送资料给 192.168.1.100 即可，而不需透过路由器。因为 192.168.0.100 与 192.168.1.100确实是在同一个实体线路上 (两者可以直接互通)，所以路由器会告知来源 IP 使用最短路径去传递资料。但那两部主机在不同的 IP 段，却是无法实际传递讯息的！这个设定也可能会产生一些轻微的安全风险，所以建议关闭他。

    • send_redirects：与上一个类似，只是此值为发送一个 ICMP redirect 封包。 同样建议关闭。(事实上，鸟哥在某补教中心教同学架设路由器时，就曾经为了这个 ICMP redirect 的问题伤脑筋！ 其实关闭 redirect 的这两个项目即可啊！)
    要达成上面的功能你必须要这样做：
    [root@linux ~]# vi somefile
for i in /proc/sys/net/ipv4/conf/*/rp_filter; do
    echo "1" > $i
done
for i in /proc/sys/net/ipv4/conf/*/log_martians; do
    echo "1" > $i
done
for i in /proc/sys/net/ipv4/conf/*/accept_source_route; do
    echo "0" > $i
done
for i in /proc/sys/net/ipv4/conf/*/accept_redirects; do
    echo "0" > $i
done
for i in /proc/sys/net/ipv4/conf/*/send_redirects; do
    echo "0" > $i
done

[root@linux ~]# sh somefile
    • 大标题的图示 本机防火墙的一个实例
    介绍了这么多的防火墙语法与相关的注意事项后，终于要来架设防火墙了。如同前面谈到的， 你当然可以使用 iptables-save 的语法将相关的防火墙规则转存到 /etc/sysconfig/iptables 去， 然后透过 iptables-restore 或者是重新启动 iptables 来启用你的新防火墙规则。 不过鸟哥还是比较习惯使用 shell script 来撰写防火墙规则，而且此一特色还可以用在呼叫其他的 scripts ， 可以让防火墙规则具有较为灵活的使用方式。好了，那就来谈谈如何设定咱们的防火墙规则吧！

    小标题的图示 规则草拟
    鸟哥底下介绍的这个防火墙，其实可以用来作为路由器上的防火墙，也可以用来作为本机的防火墙。 假设硬体连线如同图二所示那样的环境， Linux 主机本身也是内部 LAN 的路由器！ 亦即是一个简单的 IP 分享器的功能啦！假设鸟哥网路介面有底下这些：
    • 外部网路使用 eth1 (如果是拨接，有可能是 ppp0，请针对您的环境来设定)；
    • 内部网路使用 eth0 ，且内部使用 192.168.1.0/24 这个 Class ；
    • 主机预设开放的服务有 WWW, SSH, SMTP 等等；
    由于希望将信任网域 (LAN) 与不信任网域 (Internet) 整个分开的完整一点， 所以希望你可以在 Linux 上面安装两块以上的实体网卡，将两块网卡接在不同的网域，这样可以避免很多问题。 至于最重要的防火墙规则是：‘关闭所有的连线，仅开放特定的服务’模式。 而且假设内部使用者已经受过良好的训练，因此在 filter table 的三条链个预设政策是：
    • INPUT 为 DROP
    • OUTPUT 及 FORWARD 为 ACCEPT
    为了未来修改的方便，鸟哥将整个 script 拆成三部分，分别是：
    • iptables.rule：设定最基本的规则，包括清除防火墙规则、载入模组、设定服务可接受等；
    • iptables.deny：设定抵挡某些恶意主机的进入；
    • iptables.allow：设定允许某些自订的后门来源主机！
    鸟哥底下预计提供的防火墙流程是这样的：

    防火墙规则的流程
    图九、防火墙规则的流程

    原则上，内部 LAN 主机与主机本身的开放度很高，因为 Output 与 Forward 是完全开放不理的！对于小家庭的主机是可以接受的，因为我们内部的电脑数量不多，而且人员都是熟悉的， 所以不需要特别加以控管！但是：‘在大企业的内部，这样的规划是很不合格的， 因为您不能保证内部所有的人都可以按照您的规定来使用 Network ！’也就是说‘家贼难防’呀！ 因此，连 Output 与 Forward 都需要特别加以管理才行！

    小标题的图示 实际设定
    事实上，我们在设定防火墙的时候，不太可能会一个一个指令的输入，通常是利用 shell scripts 来帮我们达成这样的功能呐！底下是利用上面的流程图所规划出来的防火墙 scripts，您可以参考看看， 但是您需要将环境修改成适合您自己的环境才行喔！
    [root@linux ~]# mkdir -p /usr/local/virus/iptables
[root@linux ~]# cd /usr/local/virus/iptables
[root@linux iptables]# vi iptables.rule
#!/bin/bash

# 请先输入您的相关参数，不要输入错误了！
  EXTIF="eth1"              # 这个是可以连上 Public IP 的网路介面
  INIF="eth0"               # 内部 LAN 的连接介面；若无请填 ""
  INNET="192.168.1.0/24"    # 内部 LAN 的网域，若没有内部 LAN 请设定为 ""
  export EXTIF INIF INNET

# 第一部份，针对本机的防火墙设定！###########################
# 1. 先设定好核心的网路功能：
  echo "1" > /proc/sys/net/ipv4/tcp_syncookies
  echo "1" > /proc/sys/net/ipv4/icmp_echo_ignore_broadcasts
  for i in /proc/sys/net/ipv4/conf/*/rp_filter; do
        echo "1" > $i
  done
  for i in /proc/sys/net/ipv4/conf/*/log_martians; do
        echo "1" > $i
  done
  for i in /proc/sys/net/ipv4/conf/*/accept_source_route; do
        echo "0" > $i
  done
  for i in /proc/sys/net/ipv4/conf/*/accept_redirects; do
        echo "0" > $i
  done
  for i in /proc/sys/net/ipv4/conf/*/send_redirects; do
        echo "0" > $i
  done

# 2. 清除规则、设定预设政策及开放 lo 与相关的设定值
  PATH=/sbin:/usr/sbin:/bin:/usr/bin; export PATH
  iptables -F
  iptables -X
  iptables -Z
  iptables -P INPUT   DROP
  iptables -P OUTPUT  ACCEPT
  iptables -P FORWARD ACCEPT
  iptables -A INPUT -i lo -j ACCEPT
  iptables -A INPUT -m state --state RELATED -j ACCEPT

# 3. 启动额外的防火墙 script 模组
  if [ -f /usr/local/virus/iptables/iptables.deny ]; then
        sh /usr/local/virus/iptables/iptables.deny
  fi
  if [ -f /usr/local/virus/iptables/iptables.allow ]; then
        sh /usr/local/virus/iptables/iptables.allow
  fi
  if [ -f /usr/local/virus/httpd-err/iptables.http ]; then
        sh /usr/local/virus/httpd-err/iptables.http
  fi
  iptables -A INPUT -m state --state ESTABLISHED -j ACCEPT

# 4. 允许某些类型的 ICMP 封包进入
  AICMP="0 3 3/4 4 11 12 14 16 18"
  for tyicmp in $AICMP
  do
     iptables -A INPUT -i $EXTIF -p icmp --icmp-type $tyicmp -j ACCEPT
  done

# 5. 允许某些服务的进入，请依照您自己的环境开启
# iptables -A INPUT -p TCP -i $EXTIF --dport  22  -j ACCEPT   # SSH
# iptables -A INPUT -p TCP -i $EXTIF --dport  25  -j ACCEPT   # SMTP
# iptables -A INPUT -p UDP -i $EXTIF --sport  53  -j ACCEPT   # DNS
# iptables -A INPUT -p TCP -i $EXTIF --sport  53  -j ACCEPT   # DNS
# iptables -A INPUT -p TCP -i $EXTIF --dport  80  -j ACCEPT   # WWW
# iptables -A INPUT -p TCP -i $EXTIF --dport 110  -j ACCEPT   # POP3
# iptables -A INPUT -p TCP -i $EXTIF --dport 443  -j ACCEPT   # HTTPS

# 第二部份，针对后端主机的防火墙设定！##############################
# 1. 先载入一些有用的模组
  modules="ip_tables iptable_nat ip_nat_ftp ip_nat_irc ip_conntrack
ip_conntrack_ftp ip_conntrack_irc"
  for mod in $modules
  do
        testmod=`lsmod | grep "${mod} "`
        if [ "$testmod" == "" ]; then
                modprobe $mod
        fi
  done

# 2. 清除 NAT table 的规则吧！
  iptables -F -t nat
  iptables -X -t nat
  iptables -Z -t nat
  iptables -t nat -P PREROUTING  ACCEPT
  iptables -t nat -P POSTROUTING ACCEPT
  iptables -t nat -P OUTPUT      ACCEPT

# 3. 开放成为路由器，且为 IP 分享器！
  if [ "$INIF" != "" ]; then
    iptables -A INPUT -i $INIF -j ACCEPT
    echo "1" > /proc/sys/net/ipv4/ip_forward
    if [ "$INNET" != "" ]; then
      for innet in $INNET
      do
        iptables -t nat -A POSTROUTING -s $innet -o $EXTIF -j MASQUERADE
      done
    fi
  fi
  # 如果你的 MSN 一直无法连线，或者是某些网站 OK 某些网站不 OK，
  # 可能是 MTU 的问题，那你可以将底下这一行给他取消注解来启动 MTU 限制范围
  # iptables -A FORWARD -p tcp -m tcp --tcp-flags SYN,RST SYN -m tcpmss \
  #          --mss 1400:1536 -j TCPMSS --clamp-mss-to-pmtu

# 4. 内部伺服器的设定：
# iptables -t nat -A PREROUTING -p tcp -i $EXTIF --dport 80  \
#          -j DNAT --to 192.168.1.210:80
    特别留意上面程式码的特殊字体部分，基本上，你只要修改一下最上方的介面部分， 应该就能够运作这个防火墙了。不过因为每个人的环境都不相同， 因此你在设定完成后，依旧需要测试一下才行喔！不然，出了问题不要怪我啊！.... 再来看一下关于 iptables.allow 的内容是如何？假如我要让一个 140.116.44.0/24 这个网域的所有主机来源可以进入我的主机的话，那么这个档案的内容可以写成这样：
    [root@linux iptables]# vi iptables.allow
#!/bin/bash
# 底下则填写你允许进入本机的其他网域或主机啊！
  iptables -A INPUT -i $EXTIF -s 140.116.44.0/24 -j ACCEPT

# 底下则是关于抵挡的档案设定法！
[root@linux iptables]# vi iptables.deny
#!/bin/bash
# 底下填写的是‘你要抵挡的那个咚咚！’
  iptables -A INPUT -i $EXTIF -s 140.116.44.254 -j DROP

[root@linux iptables]# chmod 700 iptables.*
    将这三个档案的权限设定为 700 且只属于 root 的权限后，就能够直接执行 iptables.rule 啰！ 不过要注意的是，在上面的案例当中，鸟哥预设将所有的服务的通道都是关闭的！ 所以你必须要到本机防火墙的第 5 步骤处将一些注解符号 (#) 解开才行。 同样的，如果有其他更多的 port 想要开启时，一样需要增加额外的规则才行喔！

    不过，还是如同前面我们所说的，这个 firewall 仅能提供基本的安全防护，其他的相关问题还需要再测试测试呢！ 此外，如果你希望一开机就自动执行这个 script 的话，请将这个档案的完整档名写入 /etc/rc.d/rc.local 当中，有点像底下这样：
    [root@linux ~]# vi /etc/rc.d/rc.local
.....其他省略.....
# 1. Firewall
/usr/local/virus/iptables/iptables.rule
.....其他省略.....
    上述三个档案请你不要在 Windows 系统上面编辑后传送到 Linux 上运作，因为 Windows 系统的断行字元问题， 将可能导致该档案无法执行。建议你直接到底下去下载，传送到 Linux 后可以利用 dos2unix 指令去转换断行字元！ 就不会有问题！
    • http://linux.vbird.org/download/index.htm?action=detail&fileid=43
    这就是一个最简单、阳春的防火墙。同时，这个防火墙还可以具有最阳春的 IP 分享器的功能呢！ 也就是在 iptables.rule 这个档案当中的第二部分了。 这部分我们在下一节会再继续介绍的。
    大标题的图示 NAT 主机的设定
    呼呼！终于来到这个地方了！我们准备要架设一个路由器的延伸伺服器，就称之为 NAT 主机。 NAT 是什么呢？简单的说，你可以称他为内部 LAN 主机的‘ IP 分享器’啦！

    NAT 的全名是 Network Address Translation，字面上的意思是‘网路位址的转换’。由字面上的意思我们来想一想， TCP/IP 的网路封包不是有 IP 位址吗？那 IP 位址不是有来源与目的吗？我们的 iptables 指令就能够修改 IP 封包的表头资料， 嘿嘿！连目标或来源的 IP 位址都可以修改呢！甚至连 TCP 封包表头的 port number 也能修改！真是有趣！

    NAT 主机的功能可以达到类似图二所介绍的类似 IP 分享的功能之外， 还可以达到类似图四所介绍的 DMZ (非军事区) 的功能！这完全取决于我们的 NAT 是修改： (1)来源 IP 还是 (2)目标 IP ！底下我们就来聊一聊吧！ ^_^

    小标题的图示 什么是 NAT？ SNAT？ DNAT？
    在谈到 NAT 的实际运作之前，让我们再来看一下比较简单的封包透过 iptables 而传送到后端主机的流程(请往前参考图八)。当网路布线如图二的架构， 若内部 LAN 有任何一部主机想要传送封包出去时，那么这个封包要如何透过 Linux 主机而传送出去？ 他是这样的：
    1. 先经过 NAT table 的 PREROUTING 链；
    2. 经由路由判断确定这个封包是要进入本机与否，若不进入本机，则下一步；
    3. 再经过 Filter table 的 FORWARD 链；
    4. 通过 NAT table 的 POSTROUTING 链，最后传送出去。
    NAT 主机的重点就在于上面流程的第 1,4 步骤，也就是 NAT table 的两条重要的链：PREROUTING 与 POSTROUTING。 那这两条链有什么重要的功能呢？重点在于修改 IP 嘛！但是这两条链修改的 IP 是不一样的！ POSTROUTING 在修改来源 IP ，PREROUTING 则在修改目标 IP 。 由于修改的 IP 不一样，所以就称为 来源 NAT (Source NAT, SNAT) 及目标 NAT (Destination NAT, DNAT)。我们先来谈一谈 IP 分享器功能的 SNAT 吧！

  • 来源 NAT, SNAT
    你应该有听说过 IP 分享器这个玩意儿，他可以让你家庭里的好几部主机同时透过一条 ADSL 网路连线到 Internet 上面， 例如图二连线的方式来说，那个 Linux 主机就是 IP 分享器啦！那么他是如何达到 IP 分享的功能？就是透过 NAT 表格的 POSTROUTING 来处理的。假设你的网路布线如图二所示， 那么 NAT 主机是如何处理这个封包的呢？

    SNAT 封包传送出去的示意图
    图十、SNAT 封包传送出去的示意图

    如上图所示，在用户端 192.168.1.100 这部主机要连线到 http://tw.yahoo.com 去时，他的封包表头会如何变化？
    1. 用户端所发出的封包表头中，来源会是 192.168.1.100 ，然后传送到 NAT 这部主机；
    2. NAT 这部主机的内部介面 (192.168.1.2) 接收到这个封包后，会主动分析表头资料， 因为表头资料显示目的并非 Linux 本机，所以开始经过路由， 将此封包转到可以连接到 Internet 的 Public IP 处；
    3. 由于 private IP 与 public IP 不能互通，所以 Linux 主机透过 iptables 的 NAT table 内的 Postrouting 链将封包表头的来源伪装成为 Linux 的 Public IP ，并且将两个不同来源 (192.168.1.100 及 public IP) 的封包对应写入暂存记忆体当中， 然后将此封包传送出去了；
    此时 Internet 上面看到这个封包时，都只会知道这个封包来自那个 Public IP 而不知道其实是来自内部啦。 好了，那么如果 Internet 回传封包呢？又会怎么作？

    SNAT 封包接收的示意图
    图十一、SNAT 封包接收的示意图

    4. 在 Internet 上面的主机接到这个封包时，会将回应资料传送给那个 Public IP 的主机；
    5. 当 Linux NAT 主机收到来自 Internet 的回应封包后，会分析该封包的序号，并比对刚刚记录到记忆体当中的资料， 由于发现该封包为后端主机之前传送出去的，因此在 NAT Prerouting 链中，会将目标 IP 修改成为后端主机，亦即那部 192.168.1.100，然后发现目标已经不是本机 (public IP)， 所以开始透过路由分析封包流向；
    6. 封包会传送到 192.168.1.2 这个内部介面，然后再传送到最终目标 192.168.1.100 机器上去！
    经过这个流程，您就可以发现到，所有内部 LAN 的主机都可以透过这部 NAT 主机连线出去， 而大家在 Internet 上面看到的都是同一个 IP (就是 NAT 那部主机的 public IP 啦！)， 所以，如果内部 LAN 主机没有连上不明网站的话，那么内部主机其实是具有一定程度的安全性的啦！ 因为 Internet 上的其他主机没有办法主动攻击你的 LAN 内的 PC 嘛！所以我们才会说， NAT 最简单的功能就是类似 IP 分享器啦！那也是 SNAT 的一种。
    Tips:
    NAT 主机与路由器有啥不同？基本上，NAT 主机一定是路由器，不过， NAT 主机由于会修改 IP 表头资料， 因此与单纯转递封包的路由器不同。最常见的 IP 分享器就是一个路由器，但是这个 IP 分享器一定会有一个 Public IP 与一个 Private IP，让 LAN 内的 Private IP 可以透过 IP 分享器的 Public IP 传送出去喔！ 至于路由器通常两边都是 Public IP 或同时为 Private IP。     		鸟哥的图示
  • 目标 NAT, DNAT
    SNAT 主要是应付内部 LAN 连接到 Internet 的使用方式，至于 DNAT 则主要用在内部主机想要架设可以让 Internet 存取的伺服器啦！ 就有点类似图四的 DMZ 内的主机啊！底下也先来谈一谈 DNAT 的运作吧！

    DNAT 的封包传送示意图
    图十二、DNAT 的封包传送示意图

    如上图十二所示，假设我的内部主机 192.168.1.210 启动了 WWW 服务，这个服务的 port 开启在 port 80 ， 那么 Internet 上面的主机 (61.xx.xx.xx) 要如何连接到我的内部伺服器呢？当然啦， 还是得要透过 Linux NAT 主机嘛！所以这部 Internet 上面的机器必须要连接到我们的 NAT 的 public IP 才行。
    1. 外部主机想要连接到目的端的 WWW 服务，则必须要连接到我们的 NAT 主机上头；
    2. 我们的 NAT 主机已经设定好要分析出 port 80 的封包，所以当 NAT 主机接到这个封包后， 会将目标 IP 由 public IP 改成 192.168.1.210 ，且将该封包相关资讯记录下来，等待内部伺服器的回应；
    3. 上述的封包在经过路由后，来到 private 介面处，然后透过内部的 LAN 传送到 192.168.1.210 上头！
    4. 192.186.1.210 会回应资料给 61.xx.xx.xx ，这个回应当然会传送到 192.168.1.2 上头去；
    5. 经过路由判断后，来到 NAT Postrouting 的链，然后透过刚刚第二步骤的记录，将来源 IP 由 192.168.1.210 改为 public IP 后，就可以传送出去了！ (类似图十的状态！)。
    其实整个步骤几乎就等于 SNAT 的反向传送哩！这就是 DNAT 啰！很简单吧！
    • 小标题的图示 最阳春 NAT 主机： IP 分享功能
    在 Linux 的 NAT 主机服务当中，最常见的就是类似图二的 IP 分享器功能了。 而由刚刚的介绍你也该知道，这个 IP 分享器的功能其实就是 SNAT 啦！作用就只是在 iptables 内的 NAT 表格当中，那个路由后的 POSTROUTING 链进行 IP 的伪装就是了。另外， 你也必须要了解，你的 NAT 主机必须要有一个 public IP 介面，以及一个内部 LAN 连接的 private IP 介面才行。

    同样的，我的假设是这样的：
    • 外部介面使用 eth1 ，这个介面具有 public IP 喔；
    • 内部介面使用 eth0 ，假设这个 IP 为 192.168.1.2 ；
    记住！当你利用前面几章谈到的资料来设定你的网路参数后，务必要进行路由的检测， 因为在 NAT 主机的设定方面，最容易出错的地方就是路由了！尤其是在拨皆产生 ppp0 这个对外介面的环境下， 这个问题最严重。反正你要记得：‘如果你的 public IP 取得的方式是拨接或 cable modem 时，你的设定档 /etc/sysconfig/network, ifcfg-eth0, ifcfg-eth1 等档案，千万不要设定 GATEWAY 啦！’否则就会出现两个 default gateway ，反而会造成问题。

    如果你刚刚已经下载了 iptables.rule ，那么该档案内已经含有 NAT 的脚本了！ 你可以看到该档案的第二部份关于 NAT 主机的部分，应该有看到底下这几行：
    iptables -A INPUT -i $INIF -j ACCEPT
# 这一行在让 NAT 主机可接受来自内部 LAN 的封包
echo "1" > /proc/sys/net/ipv4/ip_forward
# 上头这一行则是在让你的 Linux 具有 router 的能力
iptables -t nat -A POSTROUTING -s $innet -o $EXTIF -j MASQUERADE
# 这一行最关键！就是加入 nat table 封包伪装！
    重点在那个‘ MASQUERADE ’！这个设定值就是‘ IP 伪装成为封包出去 (-o) 的那块装置上的 IP ’！以上面的例子来说，就是 $EXTIF ，也就是 eth1 啦！ 所以封包来源只要来自 $innet (也就是内部 LAN 的其他主机) ，只要该封包可透过 eth1 传送出去， 那就会自动的修改 IP 的来源表头成为 eth1 的 public IP 啦！就这么简单！ 你只要将 iptables.rule 下载后，并设定好你的内、外网路介面， 执行 iptables.rule 后，你的 Linux 就拥有主机防火墙以及 NAT 主机的功能了！

  • LAN 内其他 PC 的设定
    上面提到的是 NAT 主机的设定，那么在 LAN 内的其他 PC 网路参数要如何设定呢？很简单啊， 只要记得底下的参数值即可：
    • NETWORK 为 192.168.1.0
    • NETMASK 为 255.255.255.0
    • BROADCAST 为 192.168.1.255
    • IP 可以设定 192.168.1.1 ~ 192.168.1.254 间，不可重复！
    • 通讯闸 (Gateway) 需要设定为 192.168.1.2 (NAT 主机的 Private IP)
    • DNS (/etc/resolv.conf) 需设定为 168.95.1.1 (Hinet) 或 139.175.10.20 (Seed Net)， 这个请依您的 ISP 而定；
    这样就搞定一部阳春的 NAT 主机了！简单的要命啊！
    事实上，除了 IP 伪装 (MASQUERADE) 之外，我们还可以直接指定修改 IP 封包表头的来源 IP 呢！ 举例来说，如下面这个例子：
    范例：将要由 eth1 传送出去的封包，封包来源改为 192.168.200.250
[root@linux ~]# iptables -t nat -A POSTROUTING -o eth1 \
>  -j SNAT --to 192.168.200.250

范例：同上，但封包来源为 192.168.200.210~220
[root@linux ~]# iptables -t nat -A POSTROUTING -o eth1 \
>  -j SNAT --to 192.168.200.210-192.168.200.210
    这样也可以修改网路封包的来源 IP 资料喔！不过，除非你使用的是固定 IP ， 且有多个 IP 可以对外连线，否则一般使用 IP 伪装即可，不需要使用到这个 SNAT 吧？ 当然，你也可能有自己的独特的环境啦！ ^_^

    • 小标题的图示 iptables 的额外核心模组功能
    如果你刚刚在 iptables.rule 内的第二部分有仔细看的话， 那有没有觉得很奇怪，为何我们需要载入一些有用的模组？举例来说， ip_nat_ftp 及 ip_net_irc ？ 这是因为很多通讯协定使用的封包传输比较特殊，尤其是 FTP 档案传输使用到两个 port 来处理资料！ 这个部分我们会在 FTP 章节再次的详谈，在这里你要先知道，我们的 iptables 提供很多好用的模组， 这些模组可以辅助封包的过滤用途，让我们可以节省很多 iptables 的规则拟定， 好棒的呐！ ^_^

    小标题的图示 在防火墙后端之网路伺服器 DNAT 设定
    既然可以做 SNAT 的 IP 分享功能，我们当然可以使用 iptables 做出 DMZ 啦！ 但是再次重申，不同的伺服器封包传输的方式可能有点差异，因此，建议新手不要玩这个咚咚！ 否则很容易导致某些服务无法顺利对 Internet 提供的问题。

    先来谈一谈，如果我想要处理 DNAT 的功能时， iptables 要如何下达指令？ 另外，你必须要知道的是， DNAT 用到的是 nat table 的 Prerouting 链喔！不要搞错了。
    范例：将连接到 eth1 介面的 port 80 传导到内部的 192.168.1.210
[root@linux ~]# iptables -t nat -A PREROUTING -p tcp -i eth1 \
> --dport 80 -j DNAT --to 192.168.1.210:80
    那个‘ -j DNAT --to IP[:port] ’就是精髓啦！代表从 eth1 这个介面传入的，且想要使用 port 80 的服务时， 将该封包重新传导到 192.168.1.210:80 的 IP 及 port 上面！可以同时修改 IP 与 port 呢！真方便。 其他还有一些较进阶的 iptables 使用方式，如下所示：
    -j REDIRECT --to-ports <port number>
# 这个也挺常见的，基本上，就是进行本机上面 port 的转换就是了！
# 不过，特别留意的是，这个动作仅能够在 nat table 的 PREROUTING 以及
# OUTPUT 链上面实行而已喔！

范例：将要求与 80 连线的封包转递到 8080 这个 port
[root@linux ~]# iptables -t nat -A PREROUTING -p tcp  --dport 80 \
> -j REDIRECT --to-ports 8080
# 这玩意最容易在您使用了非正规的 port 来进行某些 well known 的协定，
# 例如使用 8080 这个 port 来启动 WWW ，但是别人都以 port 80 来连线，
# 所以，您就可以使用上面的方式来将对方对您主机的连线传递到 8080 啰！
    至于更多的用途，那就有待你自己的发掘啰！ ^_^
    大标题的图示 重点回顾
    • 要拥有一部安全的主机，必须要有良好的主机权限设定；随时的更新套件；定期的重要资料备份；完善的员工教育训练。 仅有防火墙是不足够的；
    • 防火墙最大的功能就是帮助你‘限制某些服务的存取来源’，可以管制来源与目标的 IP ；
    • 防火墙依据封包抵挡的阶层，可以分为 Proxy 以及 IP Filter (封包过滤) 两种类型；
    • 为了将整个网路的信任 (LAN) 与不信任 (Internet) 网域完整切割，防火墙通常具有两个实体网路介面， 分别连结信任与不信任网域；
    • 在防火墙内，但不在 LAN 内的伺服器所在网域，通常被称为 DMZ (非军事区)，如图四所示；
    • 封包过滤机制的防火墙，通常至少可以分析 IP, port, flag (如 TCP 封包的 SYN), MAC 等等；
    • 防火墙对于病毒的抵挡并不敏感；
    • 防火墙对于来自内部的网路误用或滥用的抵挡性可能较不足；
    • 并不是架设防火墙之后，系统就一定很安全！还是需要更新套件漏洞以及管制使用者及权限设定等；
    • 核心 2.4 以后的 Linux 使用 iptables 作为防火墙的软体；
    • 防火墙的订定与‘规则顺序’有很大的关系；若规则顺序错误，可能会导致防火墙的失效；
    • iptables 的预设 table 共有三个，分别是 filter, nat 及 mangle ，惯用者为 filter (本机) 与 nat (后端主机)。
    • filter table 主要为针对本机的防火墙设定，依据封包流向又分为 INPUT, OUTPUT, FORWARD 三条链；
    • nat table 主要针对防火墙的后端主机，依据封包流向又分为 PREROUTING, OUTPUT, POSTROUTING 三条链， 其中 PREROUTING 与 DNAT 有关， POSTROUTING 则与 SNAT 有关；
    • iptables 的防火墙为规则比对，但所有规则都不符合时，则以预设政策 (policy) 作为封包的行为依据；
    • 核心本身有提供很多网路相关功能，针对 IPv4 之设定值都在 /proc/sys/net/ipv4/* 内；
    • iptables 的指令列当中，可以下达的参数相当的多，当下达 -j LOG 的参数时，则该封包的流程会被纪录到 /var/log/messages 当中；
    • 防火墙可以多重设定，例如虽然已经设定了 iptables ，但是仍然可以持续设定 TCP Wrappers ，因为谁也不晓得什么时候 iptables 会有漏洞～或者是规则规划不良！
    大标题的图示 课后练习
    • 为什么我架设了防火墙，我的主机还是可能中毒？
      • 防火墙不是万灵丹，他还是可能被病毒或者是木马程式所入侵的！ 此外，如果您的主机本身就已经提供了多个网路服务，则当该网路服务的套件有漏洞时， 防火墙仍然无法克服该服务的漏洞的！因此仍然需要持续的进行主机的监视工作
    • 请说明为何架设了防火墙，我的主机还是可能被入侵？入侵的依据可能是什么方法？
      • 因为防火墙仅是抵挡某些不受欢迎的封包，如果您有开放 WWW 的服务时，则要求您主机 port 80 的封包将可直接进入您的主机，万一 WWW 套件有漏洞时，那么就可能被入侵了！所以套件的更新很重要！
    • 我们知道核心为 2.4 的 Linux 使用的防火墙机制为 iptables ，请问，如何知道我的 Linux 核心版本？
      • 利用 uname -r 可以查得！
    • 请列出 iptables 预设的两个主要的 table ，以及各个 table 里面的 chains 与各个 chains 所代表的意义；
      • filter 为预设的 Table，里头预设的链有：
      • INPUT：为来自外部，想要进入主机的封包；
      • OUTPUT：为来自主机，想要离开主机的封包；
      • FORWARD：为主机内部网域与外部网域的封包(不论进或者出)，但该封包不会进入主机。
      还有 nat 这个 table：
      • PREROUTING：进行路由之前的封包传送过程
      • OUTPUT：离开主机的封包传送过程；
      • POSTROUTING：已经经过路由了，然后才进行的过滤规则。
    • 什么是 iptables 的预设政策 (Policy)？若我要针对 filter 的 INPUT 做成 DROP 的预设政策，指令如何下达？
      • 当封包的所有属性都不在防火墙的规则当中时，那么这个封包能否顺利的通过防火墙，则以 Policy 作为这个封包的最终动作了！
      iptables -P INPUT DROP
    • 假设今天我的 Linux 仅是作为 Client 之用，并没有对 Internet 进行任何服务， 那么您的防火墙规划应该如何设定比较好？！
      • 既然没有对 Internet 提供任何服务，那么(1)请将所有的对外埠口先关闭吧！(2)防火墙规则当中，最重要的是 INPUT 的 Policy 一定要 DROP ，然后将‘ iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT ’即可！
    • 我要将来自 192.168.1.50 这个 IP 来源的封包，只要是向我的 21~23 埠口要求的封包，就将他抵挡，应该如何下达 iptables 指令？
      • iptables -A INPUT -p tcp -s 192.168.1.50 --dport 21:23 -j DROP
    • 我要将我自己主机 ping 的回应功能取消，应该如何下达 iptables 的指令？
      • 因为 ping 能否回应用的是 icmp 的 type 8 (请参考网路基础内的 ICMP 相关内容)，所以我可以这样做：
      iptables -I INPUT -p icmp --icmp-type 8 -j DROP
    • 请说明为何这个指令是错误的？‘iptables -A INPUT -p udp --syn -s 192.168.0.20 -j DROP’？
      • 因为只有 TCP 封包才会具有 SYN 的标志， UDP 并没有 SYN 的标志啊！所以上面的指令是错误的
    • DNS 的要求是必须的，那么我该如何设定我的主机可以接受要求 DNS 的回应呢？
      • 因为 DNS 的来源是 port 53 ，因此要接受来自 port 53 的封包就成为了：
      iptables -A INPUT -p udp --sport 53 -j ACCEPT
      iptables -A INPUT -p tcp --sport 53 -j ACCEPT
    • 如何取消 iptables 在我的系统上面？
      • 先要清除规则后，才能够将 iptables 移除！不过，我们主要将规则清除即可！
      iptables -F; iptables -X; iptables -Z
      iptables -t nat -F; iptables -t nat -X; iptables -t nat -Z
    • 如何储存目前的防火墙机制，以及如何将上次储存下来的机制回复到目前的系统中？
      • 请利用 iptables-save 以及 iptables-restore 这两个指令，配合命令重导向即可！
    • 如果你的区网当中有个 PC 使用者老是连上 Internet 乱搞，你想要将他的 IP 锁住，但他总是有办法修改成其他 IP 来连外， 那你该怎么办？让他无法继续连外？
      • 可以利用封锁网路卡卡号 MAC 来处理！
    大标题的图示 参考资料
      中文网站：
    • http://www.study-area.org/linux/servers/linux_nat.htm
    • http://linux.tnc.edu.tw/techdoc/firewall/
    • http://www.linuxyes.com/tw/tutorial/iptables.html
      英文网站：
    • http://www.netfilter.org/
    • http://www.linuxguruz.org/iptables/
    • http://www.netfilter.org/documentation/HOWTO//packet-filtering-HOWTO.html
    • http://www.interhack.net/pubs/fwfaq/
      其他书籍与资料：
    • Robert L. Ziegler 着，朱亮恺等译，‘实战 Linux 防火墙--iptables 应用全搜录’，上奇出版社，2004。
    • 本机的核心文件：/usr/src/linux-{version}/networking/ip-sysctl.txt
    • iptables 的内建 tables 与各个 chain 的相关性： http://ebtables.sourceforge.net/br_fw_ia/bridge3b.png
    • 核心参数的相关说明：http://www.study-area.org/tips/adv-route/Adv-Routing-HOWTO-12.html
    • 使用 PPPoE 导致的 MTU 问题：http://www.akadia.com/services/pppoe_iptables.html
    2002/08/20：第一次完成日期！
    2003/08/25：重新设计内容，改写一些指令介绍，与前一篇‘认识网路安全’ 分的比较完整一点！
    2006/09/06：将旧的文章移动到此处
    2006/09/11：拿掉了已经在基础篇有介绍过的 认识服务之 TCP Wrappers。
    2006/09/13：加入 NAT 的说明了，将旧的 NAT 主机移动到 此处。
    2006/09/15：将 iptables.rule 的连结贴上去了！之前忘记修改该档案了～
    2006/11/08：因为 PPPoE 拨接与 Ethernet 的 MTU 不同，可能在某些情况下会导致使用者无法连线，更新了 iptables.rule 了。
    2002/08/20以来统计人数


鸟哥的 Linux 私房菜 -- 申请合法的主机名称

为取得较佳浏览结果，请爱用 firefox 浏览本网页

申请合法的主机名称
切换解析度为 800x600
最近更新日期：2006/09/16
呵呵！在您读完了网路基础，设定好了防火墙，解决了认识埠口的问题，并且架设了个人简易的防火墙之后， 总算是准备要开始来给他进入 Server 的架设了！伺服器架设的步骤里面，很重要的一点是‘您的主机名称必须要在 Internet 上面可以被查询’才好！由网路基础我们知道网路上的设备(主机或其他网路媒体)仅认识 IP ，但人类对于 IP 记忆力又不佳，所以才会以主机名称来取代 IP。不过， 您的主机名称要能够被查询到才有用啊！这个时候，一个‘合法’的主机名称就很重要了！那要合法的主机，就得要让 DNS 系统能够找的到您的主机啊！不过，如果我们的主机是使用拨接得到的不固定 IP 呢？又该如何申请 DNS 主机名称？那就得要使用动态 DNS 的系统啰！在这个章节中，我们主要在介绍 Client 端的设定，而不是在设定 DNS 主机喔！ ^_^

1. 本章的行前准备工作
2. 为何需要主机名称
    2.1 主机名称的由来
    2.2 重点在合法授权
    2.2 申请静态还是动态 DNS 主机名称
3. 注册一个合法的主机名称
    3.1 静态 DNS 注册：以 Hinet 为例
    3.2 动态 DNS 注册：以 no-ip 为例
 4. 课后练习
5. 参考资料
5. 针对本文的建议：http://phorum.vbird.org/viewtopic.htm?t=26634
大标题的图示 本章的行前准备工作
在这个章节当中，我们将会介绍如何申请一个合法的主机名称。目前 Internet 上面使用的主机名称都是透过所谓的 DNS 系统，而你想要取得一个 DNS 的主机名称，就必须要‘注册’，所谓的‘注册’就是要钱去申请啦！ 当然也有免费提供主机名称的服务啦！在这个章节当中鸟哥不会介绍如何架设一部 DNS 主机， 而是介绍如何利用注册或免费申请的方式来达成主机名称的取得。在这一章开始前，您最好先复习一下：
  • 因为需要安装软体，你需要知道原始码、tarball 及安装的流程；
  • 取得主机名称你需要知道网路基础章节内的 DNS 简介；
  • 由于谈到很多 IP 的观念，你必须要知道网路基础章节内的自动取得 IP 与固定 IP 的意义；
如果没问题的话，那就赶紧来玩玩！

大标题的图示 为何需要主机名称
如果你已经将网路基础那一章看完的话，应该会知道其实我们的 TCP/IP 环境只要有 IP 与正确的路由即可连线了。 那么你申请主机名称要干嘛？因为‘没办法啊！人脑太不中用了！’ 举例来说，你可以背出来我们常上去查资料的 www.google.com 的 IP 吗？报告！鸟哥没办法背出来～

因为 IP 是那么难背的东西，而且，如果您的 IP 又是类似拨接的不固定的 IP 时，那还更伤脑筋呢！ 因此我们才会习惯以熟悉的英文字串来做为主机名称， 然后让‘这个主机名称与 IP 达成对应’，那直接记忆主机名称就行了，反正 IP 的查询就交给电脑主机来做即可！ 在这样的想法下，我们当然就需要有主机名称啦！底下咱们就来谈一谈先！

小标题的图示 主机名称的由来
从上面的说明我们知道因为 IP 不好记，所以人类习惯使用主机名称来记忆与连上某部主机。 好在早期连上网路的电脑数量不多，所以在网路上的人们就想出一个简单的办法来进行主机名称与 IP 的对应，那就是‘在每部电脑的 /etc/hosts 里面设定好主机名称与 IP 的对应表’。那么未来人们就可以直接藉由主机名称来连接上某些网路上的主机啰！

然而因为科技的发达，连上 Internet 的人们越来越多，使用 /etc/hosts 的方法已经搞不定了(只要一部电脑上线，全部的 Internet 上面的所有电脑都要重新改写 /etc/hosts！不太好吧！) ，这个时候领域名称系统 ( Domain Name System, DNS ) 就适时的出现了！

DNS 利用类似树状目录的型态，将主机名称的管理分配在不同层级的 DNS 主机当中，经由分层管理，所以每一部主机的记忆的资讯就不会很多，而且异动上面也相当的容易修改！ 那么这个 DNS 的功能您知道了吗？对啦！就是‘将电脑主机的名称转译成 IP ’就是了！当然啰，他的额外功能还很多，关于 DNS 的详细的解析部分我们将在后续的 DNS 主机架设章节当中在持续的加强内容，总之， 他的最大功能就是‘让有意义的，人类较容易记忆的主机名称(英文字母) ，转译成为电脑所熟悉的 IP 位址！’

小标题的图示 重点在合法授权
很多朋友都认为：‘因为我想要架站，所以主机需要有个主机名称， 因此我就得要架设 DNS？’是这样吗？当然不是啰！DNS 是个很庞大的架构， 而且是串连在全球的网路当中，除非你经由‘注册’的手续来让 DNS 系统承认你的主机名称的存在， 否则你架设的 DNS 只能说是一个‘地下练习的测试站’而已啦！并没有用途的。

那我要如何加入 DNS 系统呢？很简单啦！首先你必须要选择一个注册单位， 并且检查出你想要注册的主机名称是否存在？主机名称是有意义的，并不是你可以随便注册的喔！ 举例来说，在台湾常见的个人网站注册主机名称为： *.idv.tw ，而公司行号则可能注册为 *.com.tw 了！这个得要特别留意。至于台湾地区的注册单位很多，你可以选择例如 Hinet 或 Seednet 之类的 ISP 来注册。当然，你也可以选择免费的 no-ip.org 来注册的。

但要请您特别注意的是，并不是所有的注册单位都提供单纯主机名称的对应功能， 所以要注册前，请‘货比三家’啊！鸟哥所申请的单位分别是国外的 .org 及台湾的 Hinet 两家， Hinet 有提供 .idv.tw 的主机名称对应，还不错。 当然你也可以使用免费的 no-ip.org 来进行主机名称的注册！

Tips:
在这个章节当中，鸟哥的讲解比较少，因为很多资料都与 DNS 伺服器篇 有重复，在这个章节当中鸟哥主要在介绍动态 IP 架站的一个简单主机名称申请方式啦！ ^_^ 		鸟哥的图示
小标题的图示 申请静态还是动态 DNS 主机名称
由上面的说明当中，我们可以很清楚的知道 DNS 系统最大的功能就是在主机名称对应 IP 的转译上面。当然啦，预设的 DNS 转译是用在‘固定 IP 对应主机名称’ 的方法上面的！夭寿喔！我们的小站很多都是以非固定 IP (很多人也称为浮动式 IP 、动态 IP 等等的名称) 来上网的，更有甚者， Hinet 的 ADSL 拨接都是 24 小时强制断线一次的，所以我们都得需要重新拨接上网， 而每次拨接成功后取得的 IP 可不见得相同啊，如此一来 IP 不是一直在变吗？ 那么我不就需要一直跟我上层 DNS 主机的管理员申请‘变更 IP ’吗？会不会太麻烦了点？

是很麻烦啊！所以现在为了解决这个问题，很多 ISP 提供了所谓的 动态 DNS 主机服务 的功能，他是这样做的：
  1. Client 端(就是您啦)每次开机或者是重新拨接，并取得一个新的 IP 之后，会向 DNS Server 端提出要求，希望 Server 端变更主机名称与 IP 的对应 (这个步骤在每个主要的 ISP 都有提供适当的 program 来提供给 client 使用)；

  2. Server 端接受 Client 端的要求之后，会先去查询 Client 提供的帐号密码是否正确， 正确之后就会立即修改 Server 本身对于您的主机名称的设定值。
所以啰，每次我们取得了新的 IP 之后，我们的主机名称对应的 IP 也会跟着在 DNS 系统上面更新， 如此一来，只要别人知道您的主机名称，不论您的 IP 为何，他一定可以连上您的主机 (因为 IP 跟着您的主机而变！) 这对于我们这种使用动态 IP 的人是很有帮助的！ (阿！真是造福我们这些穷苦人家的孩子呀！)

不过，还是需要注意的是，目前的主机名称申请很多是‘需要钱的’！如果您需要比较稳定的主机名称对应 IP 的服务，那么花点钱来注册还是必须的，不过，如果是实验性质的网站，那么也是可以申请免费的动态 DNS 系统喔！
大标题的图示 注册一个合法的主机名称
静态 DNS 主机注册：
好了，既然知道了 DNS 的用途，那么自然我们就需要来申请 DNS 啦！不然怎么架设网站呢？目前的静态 IP 对应主机名称的注册网站实在太多了，我们仅提出几个出来分享就是了！
  • 台湾网路资讯中心：http://www.twnic.net
  • 国外的领域名称系统：http://www.netsol.com/
  • 国外的领域名称系统：http://www.dotster.com/
动态 DNS 主机注册：
那么有没有免费的 DNS 系统呀！呵呵！当然有啰！我们要感谢造福我们这些穷苦人家的孩子的大好人～ 您可以在底下找到相关的资讯：
  • 国外的免费 DNS 系统：http://www.no-ip.com

小标题的图示 静态 DNS 注册：以 Hinet 为例
静态 DNS 的申请方式其实都差不多，都是需要：
  1. 先查询所想要注册的网域是否存在；
  2. 进入 ISP 去申请注册您所想要的主机名称；
  3. 缴费，并等待主机名称被启用。
我们以台湾蛮常见的 Hinet 这个 ISP 提供的‘个人网域, .idv.tw’注册方式来说明：

  1. 登入主画面，并查询欲注册网域是否存在

    直接连结到底下的网页去：http://nweb.hinet.net/ ，并在 whois 的画面当中(右上角)选择您想要注册的主机名称，按下‘Go’开始搜寻。

    利用 whois 查询欲注册网域是否存在
    图一、利用 whois 查询欲注册网域是否存在

  2. 逐步进行注册

    如果确认您的主机名称没有被注册掉，那么您就可以开始注册了！同样的在上面的网站连结当中， 选择‘个人网域名称’就可以开始申请了！请依序一步一步办理！这里不再说明了，反正都是中文， 看的懂得啦！ ^_^

    个人网域逐步注册的流程示意图
    图二、个人网域逐步注册的流程示意图

  3. 填写主机名称对应的 IP

    缴费完毕之后，我们就可以开始进行主机名称的填写了！在图二的图示中按下‘DNS 指定/异动’的项目， 并填入您的主机名称与密码，然后就会出现如下的画面了：

    主机名称与 IP 对应的填写范例
    图三、主机名称与 IP 对应的填写范例

    特别的给他留意，因为我们没有要架设 DNS 主机，所以当然最上方要选择‘主机’的项目， 然后您可以填入三部主机名称喔！当然，这三部主机名称可以通通指向同一个 IP ，也可以不同！ 随您的便呐！需要注意到的是，您的主机名称应该是‘othername.yourhost.idv.tw’后面的 yourhost.idv.tw 是不变的，前面的 othername 则可以自由选取呢！例如鸟哥上面的设定，后面均是 vbird.idv.tw ，而前面的名称就可以让我自由选择啦！

  4. 等待 DNS 启用

    在上图三当中按下‘填写完请按这里’后，就等着启用吧！不过设定成功到可以使用， 其实需要一定的时间的，以鸟哥为例，第一次申请之后，大约过了 20 小时该设定才正确的启动呢！请以请耐心等候啊！不要太着急啰！ ^_^

各家的领域名称注册流程都差不多，不过，金额是有点差异的，当然，服务也就有不同啊！鸟哥的 vbird.org 领域名称则是在 http://www.godaddy.com 注册的喔！如果您不想要使用 .idv.tw 来注册的话，那么国外的 ISP 提供的 DNS 也可以考虑看看说！

小标题的图示 动态 DNS 注册：以 no-ip 为例
如果你跟鸟哥一样使用 ADSL 拨接的方式来上网，这表示你的 IP 应该是不固定的！果真如此的话， 那想要架站就比较麻烦一点！因为上面利用 Hinet 注册的方式通常是给固定 IP 使用的， 你应该不会想要天天上去更新你的 IP 吧？此时这个 no-ip.com 所提供的免费动态 IP 对应主机名称的服务就很重要啦！我们先来申请一个主机名称来玩玩吧！ ^_^

  1. 登入主网页，并且注册一个新帐号

    你必须要连上 http://www.no-ip.com 这个网站， 然后在出现的画面当中选择‘ Sign-up Now ’那个项目：

    no-ip 网站的注册流程之一
    图四、 no-ip 网站的注册流程之一

  2. 开始填写识别资料

    因为 no-ip 会发给您一份密码，所以在出现的如下画面中，您必须要填写‘ 一个可以收到邮件的合法 Email ’，以及您的身份确认资料， 这很重要，因为后续的资料都是使用您注册时的这个咚咚呐！然后再按下最底下的‘SIGN UP NOW’即可！ 如果没有 Email 怎么办？现在免费的 email 这么多，随便申请一个吧！ ^_^

    no-ip 网站的注册流程之二
    图五、 no-ip 网站的注册流程之二

  3. 启用帐号

    在你申请注册一个新帐号后， no-ip 会发一封信给你，信件的内容有点像底下那样：

    no-ip 网站的注册流程之三
    图六、 no-ip 网站的注册流程之三

    你必须要按下上图第一个箭头所指的连结后，你的帐号才会正式的被启用的！ 而上图第二个连结则是在告知你可以到哪里去下载动态 DNS 的用户端软体喔！ 也就是说， no-ip 也有提供一个好用的软体给 client 端，让使用者可以‘自动更新主机名称与 IP 的对应’， 呵呵！很棒吧！

  4. 登入 no-ip 且设定主机名称与 IP 的对应

    让我们回到图四的地方察看一下，不是有可以输入帐号与密码的地方吗？ 请你填入你刚刚注册时所填写的 email 位址以及密码后，就能够登入你的 no-ip 帐号了。 在登入后的第一个画面左手边有点类似底下的图示：

    no-ip 网站的注册流程之四
    图七、 no-ip 网站的注册流程之四

    在你按下那个‘add’后，画面就会产生如下的变化：

    no-ip 网站的注册流程之五
    图八、 no-ip 网站的注册流程之五

    请依序填写你想要的主机名称、网域名称 (通常鸟哥都建议使用 no-ip.org 这一个领域名称！)， 还有你的 IP 后，咦！往下一看，竟然还有 MX 的纪录！这东西很重要！ 是用在做 mail server 时所需要的一项参数！你可以直接填写与你的完整主机名称相同的名字即可！ 填写完毕后，就按下‘Create Host’吧！如果该主机名称有被使用掉的话， 荧幕会出现警告讯息，此时请再选填另外的主机名称吧！ ^_^

    如果未来你想要修改或者是删除该主机名称时，可以按下图七内的 Manage 项目， 就能够进行删除与修订的工作啰！就这么简单呐！

  5. 设定自动更新主机名称与 IP 的对应

    如果系统重新开机，或者是重新拨接取得一个新的 IP 后，我们都要登入 no-ip 来修改的话， 那就太没有效率了！所以 no-ip 提供一个好用的用户端程式给使用者使用，就是在 图六 email 内的那个下载连结！你可以点选该下载连结， 在出现的视窗当中会有三种程式，包括‘ Windows, Mac, Linux/BSD/Unix ’， 我们当然是选择 Linux 那个项目啊！请自行下载并且将该程式移动到 Linux 主机上吧！

    整个安装与启用的流程式这样的：
    1. 编译与安装：
[root@linux ~]# cd /usr/local/src
[root@linux src]# tar -zxvf /root/noip-duc-linux.tar.gz
# 假设你将程式放置到 /root 底下时

[root@linux src]# cd noip-2.1.3
# 注意一下，这个目录里面有个档名为 README.FIRST 的档案，务必察看一下内容！
[root@linux noip-2.1.3]# make
[root@linux noip-2.1.3]# make install
# 这样会将主程式安装在 /usr/local/bin/noip2 而主参数档放在
# /usr/local/etc/no-ip2.conf 当中！然后你必须要开始回答一些问题：

Please select the Internet interface from this list.

By typing the number associated with it.
0       eth0
1       eth1
1      <==因为鸟哥的主机对外使用 eth1 介面

Please enter the login/email string for no-ip.com  kiki@gmail.com
Please enter the password for user 'kiki@gmail.com' ***
# 上面这两个是你刚刚注册时所填写的 email 与密码喔！

Only one host [tsai.no-ip.org] is registered to this account.
It will be used.
Do you wish to run something at successful update?[N] (y/N) n

mv /tmp/no-ip2.conf /usr/local/etc/no-ip2.conf
# 重点在此！刚刚你做的设定档被放到上面这个档案中了！
    这样就将你的 no-ip 制作完毕，而且也可以开始来执行啰！执行的方法也是很简单啦！
    2. noip2 的程式使用：
[root@linux ~]# /usr/local/bin/noip2
# 不要怀疑！这样输入后，你在 no-ip 上面注册的主机名称，
# 就开始可以自动的产生对应了！就这么简单！

[root@linux ~]# noip2 [-CS]
参数：
-C ：重新设定参数，亦即设定刚刚我们上面输入粗体字的咚咚！
     如果您有两个以上的 no-ip 主机名称时，就一定需要使用 noip2 -C
     来重新设定参数档案！
-S ：将目前的 noip2 的状况显示出来！

[root@linux ~]# noip2 -S
1 noip2 process active.

Process 4998, started as /usr/local/src/noip-2.1.3/noip2
Using configuration from /usr/local/etc/no-ip2.conf
Last IP Address set 61.xxx.111.ddd
Account kiki@gmail.com
configured for:
        host  tsai.no-ip.org
Address check every 1 minute, directly connected via /dev/eth1.
    嘿嘿！这样就成功了！而且每分钟 noip2 可以自动的去主网站上面进行更新呢！ 真是很不错！那如果想要一开机就启动 noip2 呢？这样做即可：
    3. 设定开机启动：
[root@linux ~]# vi /etc/rc.d/rc.local
# 加入底下这一行：
/usr/local/bin/noip2
大标题的图示 课后练习
  • 请简易说明 /etc/hosts 的用途；
    • 这个档案是早期用在进行主机名称与 IP 的解析的，目前比较常用在内部网域的名称解析上，可以加快内部网域的反查喔！
  • 请说明‘合法授权’的主机名称需要做什么？
    • 如果想要合法授权，就需要向上层 DNS 主机‘注册’才行！而且还要上层 DNS 主机管理员愿意将领域名称的解析权限授权给您啊！
  • 什么是动态 DNS 系统？(仅说明 client 端)
    • 因为我们的 Client 拨接时，得到的 IP 都不是固定的，所以无法以 DNS 系统进行固定 IP 对应主机名称的工作！ 此时就需要动态 DNS 系统了！以 DNS 主机提供的动态更新主机名称对应 IP 的机制，可以让我们的不同 IP 对应到同一个主机名称呐！
  • 如果您使用 adsl 拨接来上网设定伺服器，那么该申请哪一类型的主机名称？为什么？
    • 因为我是以 ADSL 上网拨接，所以 IP 是不固定的，此时需要申请动态 DNS 主机的主机名称，例如 no-ip.org 等等！
大标题的图示 参考资料
  • 台湾网路资讯中心：http://www.twnic.net/
  • 国外的领域名称系统：http://www.netsol.com/
  • 国外的领域名称系统：http://www.dotster.com/
  • 国外的免费 DNS 系统：http://www.no-ip.com
2002/08/05：第一次完成日期！
2003/08/26：修改篇名、增加一 no-ip 的设定方式！
2006/09/15：将旧的文章移动到 此处。
2002/08/05以来统计人数


鸟哥的 Linux 私房菜 -- 远端连线伺服器 Telnet/SSH/XDMCP/VNC/RSH

为取得较佳浏览结果，请爱用 firefox 浏览本网页

远端连线伺服器 Telnet / SSH / VNC / XDMCP / RSH
切换解析度为 800x600
最近更新日期：2006/09/19
一部连上 Internet 上面的您的个人主机，最重要的是什么呢？ 大概就是如何让您自己可以连线进入自己的主机，并且进行所谓的‘远端操控’了吧！ 也就是说，您可以在任何具有连上 Internet 的电脑中，以远端连线软体连上 Internet ，并藉由您主机上面的远端连线伺服器软体提供的功能，直接登入您的主机来进行操控的工作！此时，您将发现 Linux 有趣又好玩的地方啰！在早期的 Unix Like 机器当中，几乎都提供 Telnet 这个远端连线伺服器软体，不过， Telnet 本身是以‘明码’来传送您操作的资料，安全上面是值得来思考要不要开放呐！ 这个时候就有需要了解一下传送过程中以加密动作来传送资料封包的 SSH 这个远端连线伺服器软体啦！ 另外，除了纯文字介面登入主机来进行操控之外，在现在的 Linux distributions 当中， 还可以利用 X 相关的服务来帮助我们以图形介面登入喔！很棒吧！ ^_^

1. 本章的行前准备工作
2. 远端连线伺服器
    2.1 什么是远端连线伺服器
    2.2 有哪些可供登入的类型？
 3. Telnet 伺服器
    3.1 安装、启动与关闭服务
    3.2 好用的连线软体
    3.3 iptables, TCP_Wrappers, 纯建议
 4. SSH 伺服器
    4.1 连线加密技术简介
    4.2 启动 ssh 服务
    4.3 ssh 用户端连线： ssh, sftp, scp, putty 与 pietty, psftp, filezilla
    4.4 详细设定 sshd 伺服器：
    4.5 制作不用密码可立即登入的 ssh 用户： ssh-keygen
    4.6 安全设定：
 5. Xdmcp 服务的启用
    5.1 X Window 的 Server/Client 架构
    5.2 设定 XDMCP
    5.3 用户登入
    5.4 关闭 XDMCP
 6. VNC 伺服器
7. RSH 伺服器
    7.1 RSH Server：/etc/hosts.equiv, ~user/.rhosts
    7.2 RSH Client：rsh, rcp
 8. 以 rsync 进行同步镜相备份
9. 重点回顾
10. 课后练习
11.参考资源
12.针对本文的建议：http://phorum.vbird.org/viewtopic.htm?p=114550
大标题的图示 本章的行前准备工作
在这个章节当中我们会使用用户端的连线软体连线到主机端来操作主机，所以你必须要了解到你的主机防火墙必须要开放， 并且要取消 SELinux 才行！另外，登入时会分析到的 PAM 模组也需要进行了解呐！ 本章后半部会介绍 X Window 的远端登入，所以你也必须对于 X Server/client 的架构有点了解才行。
  • 了解网路基础，尤其网路是双向的；
  • 认识网路安全当中的取消 SELinux ，以及防火墙的基本概念；
  • 了解使用者与帐号的相关概念；
  • 认识 X Window System；
  • 由于很多远端连线伺服器软体系统预设并不安装，因此你必须要了解 RPM 及 yum 的使用。
大标题的图示 远端连线伺服器
远端连线伺服器对我们来说，可是一项很有用的工具啊！他可以让我们更方便的管理主机。 不过，方便是方便，安全性其实不很好的～所以，才要特别强调一下这个玩意儿啊！

小标题的图示 什么是远端连线伺服器
首先，我们要先来了解一下，什么是‘远端连线伺服器’？ 这个东西的功能为何？我想，您应该已经听过，一个良好的网路环境当中，一部开放到 Internet 上面的伺服器，基本上，他可以不需要荧幕、键盘、滑鼠等等的配备， 只要有基本的主机板、CPU、RAM、硬碟再加上一块好一点的网路卡，并且连上 Internet ！哈哈！那么您要操控这部主机的时候，只要透过网路连线进来，然后进行任何修改即可！ 嘿！所以啰，这个时候主机自然不需要周边设备啦！

以鸟哥个人为例，目前鸟哥管理大约七、八部左右的 Unix-Like 主机， 这些主机都不在同一个地方，分布在南台湾各处！那么当有新的套件的漏洞被发布， 或者是需要进行一些额外的设定的时候，是否鸟哥本人一定要到现场吗？当然不需要， 只要透过网路连线到该主机上面，就可以进行任何工作了！真的就好像在主机前面工作一般的轻松愉快！ ^_^！这就是远端连线伺服器啦！

远端连线伺服器的功能当然还不只如此！举个例子来说：当您的工作需要使用到 Linux 的强大的编译功能时，那么您一定需要 Linux 对吧！而且最好是运算速度快一点的主机， 这个时候您可以将您研究室最快的那一部主机开放出来，设定一下远端连线伺服器，让您的学生啦， 或者是研究室的同仁啦，可以透过这部机器帮他们进行研究的工作，这个时候，您的主机就可以让多人进行分享 Linux 运算的功能啦！

在早期的网路世界里，由于只有 Unix 机器，而且个人电脑还不流行的时候， 想要使用大型主机来进行数值程式的运算时(在我们工程界，比较常使用 Fortran 这一类的程式语言，至于 C 语言则较少碰～)，就需要向学校单位申请 Unix 工作站的帐号， 并且以远端连线程式连进主机，以使用 Unix 的资源来进行我们的数值模式运算！所以啦，那个远端连线伺服器的设定， 对于系统管理员是很重要的！尤其对于大型工作站类型的 Unix-Like 主机，由于很多人都需要使用到他的运算功能，或者是他的编译程式( compiler )来进行运算，这时的远端连线就更形重要啦！

那么是否每一部连上 Internet 上面的主机都应该要开放远端连线的功能呢？其实并不尽然， 还是需要针对您的主机来进行规划的，我们底下分伺服器与工作站来说明：

  • 伺服器类型( Server )的连线程式：
    • 在一般开放网际网路服务的伺服器中，由于开放的服务可能会有较为重要的资讯， 而远端连线程式连进主机之后，可以进行的工作又太多了(几乎就像在主机前面工作一般！)， 因此网际网路的远端连线程式通常仅针对少部分系统维护者开放而已！ 除非必要，否则 Server 类型的主机还真的不建议开放连线的服务呢！ 以鸟哥为例，我的主机提供了我们研究室使用 Mail 与 Internet 上面的 WWW 服务，如果还主动提供远端连线的话， 那么万一不小心被入侵，那可就伤脑筋了！因此，鸟哥仅开放‘很小部分的网域’让系统管理员连进来， 其他来源的 IP 一律抵挡！不许使用远端连线的功能呢！

  • 工作站类型( Workstation )的连线程式：
    • 至于工作站的情况就跟伺服器不太一样了！工作站常常仅针对内部的几个使用者开放而已， 通常是不希望连上 Internet 的啦！而且所谓的工作站自然就是用来做工的！ 例如鸟哥的其中一部 Linux 就是专门用来进行大型的数值模式计算模拟之用！ 这个时候的远端连线伺服器可能就得要对多人启动了！ 因为工作站的强大运算功能可以让很多人一同使用他的计算能力！而且也可以免除每部电脑都得要安装 compiler 的窘境！要知道，某些工程用的 compiler 是粉贵的～
    小标题的图示 有哪些可供登入的类型？
    那么目前远端连线伺服器的主要类型有哪些？如果以显示的类型来分类， 基本上有文字介面与图形介面两种。

    在文字类型登入方面的伺服器，主要有以‘明码’传送资料的 telnet 伺服器，及以加密技术进行封包加密来传送的 SSH 伺服器！虽然 telnet 可以支援的 client 端软体比较多，不过由于他是使用明码来传送资料， 您的资料很容易遭到有心人士的撷取！所以近来我们都呼吁大家多使用 SSH 这一种连线方式，而舍弃掉 telnet 这个比较不安全的咚咚啰！

    至于图形介面的伺服器，比较简单的有 Xdmcp ，架设 Xdmcp 很简单， 不过 client 端的软体比较少。另外一款目前很常见的伺服器，就是 VNC (Virtual Network Computing)， 透过 VNC server/client 软体来进行连接。图形介面最大的优点是‘图形’啊！ 不过，因为是透过图形来传送，传输的资料量相当的大，所以速度与安全性都有待考量。 因此，我们仅建议您将图形介面的远端登入伺服器开放在内部网域 (LAN) 就好了！

    那么什么是‘明码’与‘加密’的资料封包传送模式呢？ 为什么 telnet 使用明码就比较不安全？所谓的明码就是： ‘当我们的资料封包在网路上流窜时，该资料封包的内容为资料的原始格式’， 还记得我们在网路常用指令章节当中介绍的 tcpdump 吧？ 我们在 telnet 下达的指令与密码等等，都会以类似 ASCII 的格式传送到主机端， 而主机端就藉由这些资料来下达指令。如果这些资料封包在经过某些 broadcast 或者是 Router 时，被有心人士捉去，那么他将会完整的取得您的资料喔！ 所以啦，万一您的资料封包里面含有信用卡资料、密码、身份确认等重要资讯时，是否很危险呐？！ 因此，目前我们通常都希望使用可以将这些在网路上面跑的资料加密的技术，以增加资料在 Internet 上面传送的安全性啊！
    大标题的图示 Telnet 伺服器
    知道 telnet 是什么吗？咦！不就是连接 BBS 的工具吗？没错！他确实也是 BBS 软体类的一个伺服器啦！不过这里我们暂不玩弄 BBS ！ telnet 可以说是历史相当悠久的远端连线伺服器哩！而且支援他的软体也相当的多！例如知名的 netterm 就直接支援他啦！连线之后的界面也漂亮，在 client 端的中文传输与输入也没有问题！ 相当的不错用！不过，他最麻烦的地方就是.....比较不安全而已啦～

    底下我们谈一谈怎么启动与使用 telnet 伺服器吧！

    小标题的图示 安装、启动与关闭服务
  • 安装：
    • 近年来由于 telnet 是以明码在传输的问题，所以在新的 Linux 版本上面，已经都将 telnet 这个伺服器排除在‘先发名单’之外啦，也就是说，很多 Linux distributions 预设是不安装 telnet 的，不过，在每个主要的 Linux distributions 还是有提供 telnet 套件在光碟当中啦！所以您要拿出原版光碟，并且安装好他就可以用啦！如何确认是否已经安装了 telnet 呢？最简单的方法就是使用最广泛被使用的 RPM 啦！
    [root@linux ~]# rpm -qa | grep telnet
telnet-0.17-31.EL4.3
telnet-server-0.17-31.EL4.3
# 上面是 CentOS 4.x 预设的套件版本。如果是其他的 distribution，
# 档名可能会不太一样～可利用 yum 或 apt 等方式来安装喔！
    需要特别留意的是，如果要提供 telnet 连线服务，通常需要安装两个 RPM 喔：
    1. 一个是 telnet，这个套件提供的是 telnet 用户端的连线程式；
    2. 另一个是 telnet-server 套件，这个才是真正的 Telnet server 软体喔！
      3.
    如果找不到 telnet-server 的话，请拿出原版光碟来安装，或者直接使用 yum 吧！ 否则就无法进行下一步的设定啦！^_^

  • 启动与关闭：
    • 还记得‘鸟哥的 Linux 私房菜 -- 基础学习篇’里面的 ‘认识服务( daemon )’那个章节吧？ 要记得 super daemon 呦！因为我们的 telnet 就是挂在 super daemon 底下的一支服务而已！那个咚咚就是有名的 xinetd 啰！
    Tips:
    在某些旧版的套件上面也有使用 inetd 的，启动的方式有点不太一样，不过差异不大啦！ 只要懂得基本的常识，那么就不会有问题啰！所以鸟哥才会要大家先读完 Linux 基础篇 啦！     		鸟哥的图示
    启动的方式就是：
    1. 将 xinetd 里面关于 telnet 的项目开启，然后
    2. 重新启动一次 xinetd 就成功啦！
    那么如何开启 telnet 的项目呢？很简单，有两个方式：
    1. 使用 ntsysv 或 chkconfig：
      2. 还记得 Red Hat 系列(含 CentOS)的套件里面的 ntsysv 这个好用的东西吗？对了，在 CentOS 底下有这么一个好用的设定工具，您可以使用 ntsysv 出现的视窗之中，将 telnet 勾选起来，然后按下 OK 离开即可啰！

    2. 使用 vi 修改 /etc/xinetd.d/telnet 这个档案：
      3. 那么如果不是 Red Hat 系列的 Linux 系统呢？基本上， ntsysv 也只是修改 /etc/xinetd.d 这个目录下的资料而已，所以我们当然可以手动自己修改他啦！
      [root@linux ~]# vi /etc/xinetd.d/telnet
service telnet
{
        flags           = REUSE
        socket_type     = stream
        wait            = no
        user            = root
        server          = /usr/sbin/in.telnetd
        log_on_failure  += USERID
#       disable         = yes
        disable         = no
# 基本上，改上面这两行就够了！将 disable 设定成 no 表示要启动！
}
    设定完开启之后，自然就是要启动啦，刚刚提到 telnet 是挂在 xinetd 底下的，所以自然只要重新启动 xinetd 就能够将 /etc/xinetd.d/ 里头的设定重新读进来， 所以刚刚设定启动的 telnet 自然也就可以被启动啦！而启动的方式也有两种方式，其中 service 这个指令仅支援在 CentOS 与 Mandriva 底下，所以通常鸟哥还是以 /etc/init.d 底下的 scripts 为启动的主要方法啦！
    仅适合 Red Hat 系列 / Mandriva 系列的主机启动方式
[root@linux ~]# service xinetd restart
Stopping xinetd:                       [  OK  ]
Starting xinetd:                       [  OK  ]

适合各版本的主机启动方式
[root@linux ~]# /etc/init.d/xinetd restart
Stopping xinetd:                       [  OK  ]
Starting xinetd:                       [  OK  ]
# 某些版本并没有 restart 的选项，这个时候就需要：stop 再 start 啰！
    那么要看有没有启动服务呢？怎么看？其实也很简单啦，还记得我们在前几章提到的‘ 限制 Linux port 的连线 ’那一章吗？使用 netstat 就可以啦！
    [root@linux ~]# netstat -tlup
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address  Foreign Address   State   PID/Program name
tcp        0      0 *:telnet       *:*               LISTEN  23817/xinetd
    看到了吗？没错，那个 telnet 就是启动的项目啦！那么要如何关闭呢？呵呵！ 那就真的是太简单啦！就将刚刚的步骤再做一次，而将设定值转变一下即可！步骤如下啦！
    Tips:
    这里考一个问题，那个 port 对应的服务名称在哪一个档案里面查询到的呢？ 在每一个 Linux 系统都有的档案呦！忘记了呀！？再回到前面看看 限制 Linux port 的连线 ， 然后用 vi 去看看那一个档案的内容吧！ ^_^     		鸟哥的图示
    Step 1: 修改设定档
[root@linux ~]# vi /etc/xinetd.d/telnet
service telnet
{
        flags           = REUSE
        socket_type     = stream
        wait            = no
        user            = root
        server          = /usr/sbin/in.telnetd
        log_on_failure  += USERID
        disable         = yes  <== 就是这里啦！将他改成 yes 就是关闭！
}

Step 2: 重新启动 xinetd 这个 super daemon
[root@linux ~]# /etc/init.d/xinetd restart
    小标题的图示 好用的连线软体
    刚刚上面提到的都是在伺服器端的设定而已！那么在客户端有什么好用的软体可以连上 Server 的呢？最常见到的应该就是 netterm 这个鼎鼎大名的连线软体了吧！ 我想，只要玩过 BBS 的大概都晓得这个软体才对！所以这里就不提了！ 另外，目前几乎所有的作业系统都提供了 telnet 这个程式，这个程式可以直接轻易的就连上 telnet server 呢！例如您要在 Linux 上面连上自己的 telnet 伺服器，可以这样做：
    [root@linux ~]# telnet localhost
Trying 127.0.0.1...
Connected to localhost.localdomain (127.0.0.1).
Escape character is '^]'.
CentOS release 4.4 (Final)
Kernel 2.6.9-42.0.2.EL on an i686
login: dmtsai    <== 就是这里啦！请输入‘一般’帐号，不能用 root 喔！
Password:         <== 这里输入该帐号的密码！请注意，输入时，荧幕不会有任何资讯！
Last login: Fri Jul  1 09:31:21 from 127.0.0.1  <== 上次登入的资讯为何?
[dmtsai@linux ~]$ <== 这里就是已经登入的地方！亦即远端主机了！
[dmtsai@linux ~]$ exit    <== 这样就能够离开 telnet 与远端主机咯！
    这样就连线进来啦！很简单吧！那么在 Windows 的环境底下呢？同样的，也是可以使用 telnet 的程式连线到 Linux 的 telnet server 里面来！没有问题的啦！可以依序这样做：
    1. 按下 Windows 内的 ‘开始’
    2. 选择 ‘执行’
    3. 在出现的视窗中输入 ‘telnet your.IP.or.hostname’
    这样就可以进入 Linux 的环境中了！很方便吧！当然啦！您也可以使用类似 netterm 这个很棒的连线软体来连线的，这里我们就不示范啦！
    Tips:
    在 Linux tty1 ~ tty6 的终端机预设模式下，我们是没有办法看到中文的！ 除非安装某些特殊的中文介面才行！比如 JMCCE 之类的咚咚！ 因为不是很重要，所以鸟哥这里就不加介绍了。 ^_^     		鸟哥的图示
    另外，需要先留意的是，为了系统安全的考量，预设的 telnet 是‘不允许’使用 root 这个帐号登入的～ 这个很重要喔！您不要使用 root 尝试登入 telnet 啊！ ^_^
    小标题的图示 iptables, TCP_Wrappers, 纯建议
    telnet 这个伺服器方便归方便，但总是一个不太好的连线解决方案， 因为毕竟他是一个以‘明码’传输的协定，所以很不适合在 Internet 上面使用啦！ 你总不希望你的帐号密码在 Internet 上面被窃取吧？不过，如果 telnet 是启动在内部环境当中那就还好啦！ 尤其有些朋友因为旧软体的关系，还是需要使用到 telnet 来连线。那么我们就提一些基本的注意事项好了！

  • 以比较限制的设定档来规范连线的 IP ：
    • 事实上， xinetd 就已经提供些许的保护措施了， 您可以针对您主机的多重介面(有对内以及对外喔！)来提供不同保护等级的措施！ 底下列出一个范例，不过，更多的资讯请再回到‘鸟哥的 Linux 私房菜 -- 基础学习篇’当中去查阅一下 ‘认识服务 ’那一章里面的详细设定说明，或者直接 man xinetd.conf 吧！
    [root@linux ~]# vi /etc/xinetd.d/telnet
# This file had been modified by VBird 2002/11/04
# 首先为内部网路的参数设定
service telnet
{
        disable         = no
        bind            = 192.168.1.2
        only_from       = 192.168.1.0/24
        # 上面这两行说明仅提供内部网域！
        instance        = UNLIMITED
        nice            = 0
        flags           = REUSE
        socket_type     = stream
        wait            = no
        user            = root
        server          = /usr/sbin/telnetd
        server_args     = -a none
        log_on_failure  += USERID
}

# 再来则是针对外部网域的设定
service telnet
{
        disable         = no
        bind            = 140.116.142.196
        only_from       = 140.116.0.0/16
        no_access       = 140.116.32.{10,26}
        # 上面这三行设定外部较为严格的限制
        instance        = 10   <==最多允许同时 10 个连线
        umask           = 022
        nice            = 10
        flags           = REUSE
        socket_type     = stream
        wait            = no
        user            = root
        server          = /usr/sbin/telnetd
        server_args     = -a none
        log_on_failure  += USERID
}
  • root 不能直接以 telnet 连接上主机：
    • 既然 telnet 不是很安全，自然预设的情况之下就是无法允许 root 以 telnet 登入 Linux 主机的！但事实上， telnet 只是利用一些较为安全的机制 (其实就是 PAM 模组啦) 来防止 root 登入而已～所以啰，假如您确定您的环境够安全(例如您的主机并没有连上 Internet )，并且想要开放 root 以 telnet 登入 Linux 主机的话，请直接将 /etc/securetty 更改档名即可！
    [root@linux ~]# mv /etc/securetty /etc/securetty.bak
    这样一来，root 就可以登入啦！不过，相当的不建议这样做喔！毕竟不是很安全啦！此外，您也可以藉由修改 pam 模组来达成同样的功能！修改 /etc/pam.d/login 这个档案的第二行设定即可：
    [root@linux ~]# vi /etc/pam.d/login
#%PAM-1.0
#auth       required     pam_securetty.so  <== 就是这样一行，将他注解即可！
auth       required     pam_stack.so service=system-auth
auth       required     pam_nologin.so
account    required     pam_stack.so service=system-auth
password   required     pam_stack.so service=system-auth
# pam_selinux.so close should be the first session rule
session    required     pam_selinux.so close
session    required     pam_stack.so service=system-auth
session    required     pam_loginuid.so
session    optional     pam_console.so
# pam_selinux.so open should be the last session rule
session    required     pam_selinux.so multiple open
    如此一来， root 将可以直接进入 Linux 主机了！不过，既然我们可以透过 su 或 sudo 来切换身份， 那么干嘛还需要开放 root 用 telnet 登入主机呢？真是没必要～所以， 还是不建议如此做的！

  • 加上防火墙 iptables：
    • 针对 telnet 加设防火墙 iptables 是一个好主意！如果您已经参考了前面章节提到的‘ 简易防火墙架设 ’一文，并且使用里面的 scripts 的话，那么不用担心 telnet 啦！基本上，他原本就仅对内部开放 telnet ，外部是无法连上您的 telnet 的！但是，若是您自己设定了自己的防火墙机制之后，那么想要针对 192.168.0.0/24 这个网域，及 61.xxx.xxx.xxx 这个 IP 进行 telnet 的开放呢？可以增加这几行在您的 iptables 规则之内(请注意：防火墙的规则顺序是很重要的！所以再回头看看 简易防火墙架设 一文是有必要的！)
    iptables -A INPUT -p tcp -i $INIF  -s 192.168.0.0/24 --dport 23 -j ACCEPT
iptables -A INPUT -p tcp -i $EXTIF -s 61.xxx.xxx.xxx --dport 23 -j ACCEPT
iptables -A INPUT -p tcp -i $EXTIF                   --dport 23 -j DROP
    上面的规则中，$EXTIF 指的是对外的连线介面，$INIF 则是对内的介面。 第一、二行是针对来源的 IP 来开放 port 23 亦即是 telnet 的协定啦！ 而最后一行则是将其他的所有来源的，想要连上 telnet 的连线封包都丢掉的意思！怎么样！很简单吧！

  • 加上防火墙 /etc/hosts.allow(deny) 机制：
    • 防火墙的机制是越多越好！永远也不嫌多的啦！这里也可以使用 TCP_Wrappers 的机制呢！刚刚是开放了 192.168.0.0/24 这个网段，但是如果您只想要其中的 192.168.0.1 ~ 192.168.0.5 进入呢？而其他的 IP 只要一经连线，就会被记录该 IP ，以提供 root 查询呢？可以这样做：
    [root@linux ~]# vi /etc/hosts.allow
in.telnetd: 192.168.0.1, 192.168.0.2, 192.168.0.3, 192.168.0.4
in.telnetd: 192.168.0.5

[root@linux ~]# vi /etc/hosts.deny
in.telnetd : ALL : spawn (/bin/echo Security notice from `/bin/hostname`; \
/bin/echo; /usr/sbin/safe_finger @%h ) | \
/bin/mail -s "%d -%h security" root@localhost & \
: twist ( /bin/echo -e "\n\nWARNING connectin not allowed. \n\n\n" )
  • 建议事项：
    • 事实上， telnet 最大的不安全在于资料是以明码传输，所以在 Internet 这个大家都能够连上的地方来传输资料时，实在很不安全！所以：
    1. 非必要时，不要启动 telnet ，如果真的需要启动 telnet ，那么也请在启动并且使用完毕之后，立即将他关掉！
    2. 如果确定真的要启动 telnet 时，请确定好限制的连线范围，使用 iptables 来设定连线的限制区域；
    3. 加上 TCP_Wrappers 的辅助，加强防火墙的功能！
    4. 随时注意登录档案里面关于 login 的事项！并且不要让 root 能以 telnet 登入 Linux 主机！
    大标题的图示 SSH 伺服器
    既然 telnet 的资料在 Internet 上不是很安全，那么我又需要以远端连线服务来操控我的 Linux 主机，那么应该怎么办呀？最好的方法当然就是以较为安全的连线机制来解决连线的问题啰！ 那么该如何解决这样的问题呢？这也不难啦，使用 SSH 即可。那么 SSH 是什么呢？他有什么特异功能？

    简单的来说，SSH 是 Secure SHell protocol 的简写，他可以经由将连线的封包加密的技术， 来进行资料的传递，因此，资料当然就比较安全啰！这个 SSH 可以用来取代 Internet 上面较不安全的 finger, R Shell (rcp, rlogin, rsh 等指令), talk 及 telnet 等连线模式。底下我们将先简介一下 SSH 的连线模式，来说明为什么 SSH 会比较安全呢！

    特别注意：这个 SSH 协定，在预设的状态中，本身就提供两个伺服器功能：
    1. 一个就是类似 telnet 的远端连线使用 shell 的伺服器，亦即是俗称的 ssh ；
    2. 另一个就是类似 FTP 服务的 sftp-server ！提供更安全的 FTP 服务。

    小标题的图示 连线加密技术简介：
    什么是‘资料加密’呢？简单的说，就是将人们看的懂得电子资料，经过一些运算， 让这些资料变成没有意义的(至少对人类来说)咚咚，然后这个咚咚可以在网路上面传输， 而当使用者想要查阅这个资料时，再透过反向运算，将这些咚咚反推出原始的电子资料。 由于这些资料已经被重新处理过，所以，即使资料在 Internet 上被 cracker 监听而窃取，他们也不容易就推算得出来原始资料内容的。

    网路封包的加密技术通常是藉由所谓的‘一对公钥与私钥’ 亦即‘Public and Private 组合成的 key pair’ 来进行加密与解密的动作！如下图所示。主机端所要传给 client 端的资料，会先经由公钥加密后才到网路上传输。 而到达 client 端之后，再经由私钥将加密的资料解开来～由于在 Internet 上面跑的资料是加密过后的， 所以你的资料内容当然就比较安全啦！

    公钥与私钥在进行资料传输时的角色示意图
    图一、公钥与私钥在进行资料传输时的角色示意图

    Tips:
    资料加密的技术真的相当的多，也各有其优缺点，有的运算速度快， 但是不够安全；有的够安全，但是加密/解密的速度较慢～ 目前在 SSH 使用上，主要是利用 RSA/DSA/Diffie-Hellman 等机制喔！     		鸟哥的图示
    那么这些公钥与私钥是如何产生的呢？底下我们来谈一谈目前 SSH 的两种版本的连线模式啰！

  • SSH protocol version 1：
    • 每一部 SSH 伺服器主机都可以使用 RSA 加密方式来产生一个 1024-bit 的 RSA Key ， 这个 RSA 的加密方式，主要就是用来产生公钥与私钥的演算方法！这个 version 1 的整个连线的加密步骤可以简单的这么看：
    1. 当每次 SSH daemon (sshd) 启动时，就会产生一支 768-bit 的公钥(或称为 server key)存放在 Server 中；
    2. 若有 client 端的 ssh 连线需求传送来时，那么 Server 就会将这一支公钥传给 client ，此时 client 也会比对一下这支公钥的正确性。比对的方法为利用 /etc/ssh/ssh_known_hosts 或 ~/.ssh/known_hosts 档案内容。
    3. 在 Client 接受这个 768-bit 的 server key 之后，Client 自己也会随机产生一支 256-bit 的私钥(host key)，并且以加密的方式将 server key 与 host key 整合成一对完整的 Key pair，并且将这对 Key pair 也传送给 server ；
    4. 之后，Server 与 Client 在这次的连线当中，就以这一对 1024-bit 的 Key pair 来进行资料的传递！
    也就是说，Public Key 是放在 Server 上的，而 Client 端的软体必须要能接受 Public Key 以及计算出 Private Key 以组合成为一把独一无二的 key pair ，因为 Client 端每次的 256-bit 的 Key 是随机取的，所以您这次的连线与下次的连线的 Key 可能就会不一样啦！此外在 Client 端的使用者家目录下的 ~/.ssh/known_hosts 会记录曾经连线过的主机的 public key ，用以确认每次来自该主机的连线是正确的。 这个 ~/.ssh/known_hosts 档案的意义后续还会介绍的。
  • SSH protocol version 2：
    • 在 SSH version1 的连线过程当中，当 server 端接受 client 端的 private key 后，就不再针对该次连线的 key pair 进行检验。此时若有恶意的 cracker 针对该连线给予恶意的程式码时，由于主机端不会检验连线的正确性， 因此可能会接受该程式码，进一步造成系统被黑掉的问题。

    为了改正这个缺失，SSH version 2 多加了一个确认连线正确性的 Diffie-Hellman 机制， 在每次资料的传输当中 server 端都会以该机制检查资料的来源是否正确， 所以可以避免连线过程当中被插入恶意程式码的问题！ 也就是说， ssh version 2 是比较安全的喔！

    由于 SSH version 1 本身存在着的一些问题，因此，近来我们都希望大家使用 ssh version 2 的连线模式， 会比较安全一点。而连线版本的设定则需要在 ssh 主机端与客户端均设定好才行喔！

    小标题的图示 启动 SSH 服务：
    事实上，在我们使用的 Linux 系统当中，预设就已经含有 SSH 的所有需要的套件了！ 这包含了可以产生密码等协定的 OpenSSL 套件与 OpenSSH 套件，所以呢，要启动 SSH 真的是太简单了！就直接给他启动就是了！此外，在目前的 Linux Distributions 当中，都是预设启动 SSH 的， 所以一点都不麻烦，因为不用去设定，他就已经启动了！哇！真是爽快～无论如何， 我们还是得说一说这个启动的方式吧！直接启动就是以 SSH daemon ，简称为 sshd 来启动的，所以，手动可以这样启动：
    [root@linux ~]# /etc/init.d/sshd restart
[root@linux ~]# netstat -tlp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address  Foreign Address  State   PID/Program name
tcp        0      0 *:ssh          *:*              LISTEN  24266/sshd
    启动后，利用 netstat 查阅一下 sshd 这个程序是否正确的在 LISTEN 即可！当然，这个时候您的 SSH 伺服器设定值均是使用系统预设值， 能不能够仅用较安全的 version 2 ，则需要进一步的设定呢。 接下来，如果您想要在开机就启动 SSH 的话(预设也是启动的！)，可以利用 chkconfig 来设定开机启动即可。

    虽然新的 Linux distributions 都预设会有 SSH 存在的，但是较旧的版本就仅有 telnet 而已。 例如 Red Hat 6.x 之前的版本。那么如果您想要在旧的 distributions 当中安装 SSH 该如何是好？ 嘿嘿！可以参考一下鸟哥之前写过的一篇咚咚，有详细的说明 tarball 的安装流程哩！
      使用 Tarbal 安装 SSH 以及升级 SSH 可能会遇到的问题说明
      (http://linux.vbird.org0310telnetssh/0310telnetssh-2.htm)
    需要注意的是， SSH 不但提供了 shell 给我们使用，亦即是 ssh protocol 的主要目的，同时亦提供了一个较为安全的 FTP server ，亦即是 ssh-ftp server 给我们当成是 FTP 来使用！所以，这个 sshd 可以同时提供 shell 与 ftp 喔！而且都是架构在 port 22 上面的呢！所以，底下我们就来提一提，那么怎么样由 Client 端连接上 Server 端呢？同时，如何以 FTP 的服务来连接上 Server 并且使用 FTP 的功能呢？

    小标题的图示 ssh 用户端连线：
    由于 Linux 与 Windows 这两个用户端 Client 连线软体/指令并不一样，所以我们分别来介绍可以使用的指令：

  • Linux Client: ssh
    • SSH 在 client 端使用的是 ssh 这个指令，这个指令可以指定连线的版本 (version1, version2)， 还可以指定非正规的 ssh port (正规 ssh port 为 22)。不过，一般的用法可以使用底下的方式：
    1. 直接登入到对方主机的方法：
[root@linux ~]# ssh account@hostname
# 连接到我们自己本机上面的 ssh 服务！更多讯息，请 man ssh 喔！
[root@linux ~]# ssh dmtsai@localhost
The authenticity of host 'localhost (127.0.0.1)' can't be established.
RSA key fingerprint is f8:ae:67:0e:f0:e0:3e:bb:d9:88:1e:c9:2e:62:22:72.
Are you sure you want to continue connecting (yes/no)? yes
# 上面很重要喔！务必填入完整的 "yes" 而不是 Y 或 y 而已。
Warning: Permanently added 'localhost' (RSA) to the list of known hosts.
dmtsai@localhost's password: <== 在这里填入密码，同样的，荧幕不会有讯息的！
Last login: Fri Jul  1 14:23:27 2005 from localhost.localdomain
[dmtsai@linux ~]$      <== 瞧！已经登入啰～
[dmtsai@linux ~]$ exit <== 输入 exit 就能够离开对方主机啰！

2. 不登入对方主机，直接在对方主机执行指令的方法：
[root@linux ~]# ssh dmtsai@localhost date
dmtsai@localhost's password:
Tue Nov 22 11:57:27 CST 2005
[root@linux ~]#
# 看！身份还是 root 喔！只是以 dmtsai 的身份在远端主机上执行了一个指令而已！
    这里请特别留意的是，如果直接以‘ ssh hostname ’这个指令来连接进入 hostname 这个主机时，则进入 hostname 这个主机的‘帐号名称’将会是目前您所在的这个环境当中的使用者帐号！ 以上面为例，因为我是以 root 的身份在执行，所以如果我执行了‘ ssh host.domain.name ’时， 那么对方 host.domain.name 这部主机，就会以 root 的身份来让我进行密码确认的登入动作！

    因此，为了避免这样的麻烦，通常鸟哥都是以简单的 e-mail 的写法来登入远方的主机， 例如‘ssh user@hostname ’即表示， 鸟哥是以 user 这个帐号去登入 hostname 这部主机的意思。当然，也可以使用 -l username 这样的形式来书写！登入对方主机之后，其他的所有执行行为都跟在 Linux 主机内没有两样～所以，真的是很简单吧！ ^_^ 这样就可以达到远端控管主机的目的了！

    此外，在预设的情况下， SSH 是‘允许您以 root 的身份登入’喔 ！呵呵！更是爽快啦！要特别留意的是，当您要连接到对方的主机时，如果是首次连接，那么 Server 会问您，您的连线的 Key 尚未被建立，要不要接受 Server 传来的 Key ，并建立起连线呢？呵呵！这个时候请‘务必要输入 yes 而不是 y 或 Y’，这样程式才会接受喔！

  • 关于 Server Keys 的纪录资料： ~/.ssh/known_hosts
    • 如果您刚刚有研究过 SSH 的连线流程的话，会发现到当 client 端接受来自 server 端的 public key 之后，会主动的比对这支 Key 的正确性。而比对的档案是 ~/.ssh/known_hosts 。 若是接受到的这支 public key 并没有被纪录在这档案内，那么上面表格的讯息， 就是要您回答 yes/no 的那个讯息才会出现～而您回答 yes 之后，该 public key 资讯就会被记录起来，以留待下次登入同一部主机时的检查之用啊！ 如果 Server Key 与 ~/.ssh/known_hosts 比对成功， 那么您就会直接进入等待密码输入的画面， 那就不必每次都得要输入 (yes/no) 啰～

    不过，您或许也会发现一件事情啊，我们知道 SSH server 虽然使用 version 2 已经不会重复制造 server key (public key) 了，但是如果该主机重新安装过新的 linux distributions 时， 那把 server key 就会被改变啊！而 client 又会去比对这个 public key 与 ~/.ssh/known_hosts ， 此时 Client 就会发现两者不同了，于是乎产生如下的错误讯息了：
    [root@linux ~]# ssh dmtsai@localhost
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@    WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!     @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
Someone could be eavesdropping on you right now (man-in-the-middle attack)!
It is also possible that the RSA host key has just been changed.
The fingerprint for the RSA key sent by the remote host is
f8:ae:67:0e:f0:a0:3e:aa:d9:77:19:c9:2e:62:22:72.
Please contact your system administrator.
Add correct host key in /root/.ssh/known_hosts to get rid of this message.
Offending key in /root/.ssh/known_hosts:1
RSA host key for localhost has changed and you have requested strict checking.
Host key verification failed.
    这个错误讯息在告诉您，上次所登录的远端 SSH 主机的 Keys 已经被改过了(最可能的原因就是 Server 端重新开机/重新安装/更新套件等等啦！)， 所以无法继续登入～呵呵！这个时候怎么办？很简单啊！进入您的家目录的 ~/.ssh 里面，编辑一下 known_hosts ，将欲连接的主机名称的 Key 给他消除，就可以重新连线啦！
    [root@linux ~]# vi ~/.ssh/known_hosts
localhost ssh-rsa AAAAB3NzaC1yc2Euowireffodjoiwjefmoeiwhoqhwupoi
t[egmlomowimvoiweo6VpTHTw2/tENp4U7Wn8J6nxYWP36YziFgxtWu4MPSKaRmr
E4eUpR1G/zV3TkChRZY5hGUybAreupTVdxCZvJlYvNiejfijoejwiojfijeoiwx5
eRkzvSj7a19vELZ5f8XhzH62E=
    上面表格的内容其实是同一行的～那一行代表‘ localhost 这部主机，利用的是 ssh-rsa 连线机制， 而后续的资料则是那把 Server Key 的内容。’如果您确定这次的比对无法成功是正常的， 那么您可以将这一行给他删除，这样下次要再登入时，就又会再次的出现问 (yes/no) 的画面啊！

  • Linux Client: sftp
    • 那么如何使用 SSH FTP 的功能呢？也是很容易啦！就是使用 sftp 这支程式即可！而登入的方式与 ssh 相同，都是使用 sftp -l username hostname 或者直接以 sftp user@hosname 来书写！执行之后会有底下的模样：
    [root@linux ~]# sftp dmtsai@localhost
Connecting to localhost...
dmtsai@localhost's password: <== 这里请输入密码啊！
sftp> <== 这里就是在等待您输入 ftp 相关指令的地方了！
    进入到 sftp 之后，那就跟在一般 FTP 模式下的操作方法没有两样了！底下我们就来谈一谈， sftp 这个介面下的使用指令吧！

    针对远方主机(Server)之行为
    变换目录到 /etc/test 或其他目录 cd /etc/test
    cd PATH
    列出目前所在目录下的档名 ls
    dir
    建立目录 | mkdir directory
    删除目录 | rmdir directory
    显示目前所在的目录 | pwd
    更改档案或目录群组 | chgrp groupname PATH
    更改档案或目录拥有者 | chown username PATH
    更改档案或目录的权限 chmod 644 PATH
    其中，644 与权限有关！回去看基础篇！
    建立连结档 | ln oldname newname
    删除档案或目录 | rm PATH
    更改档案或目录名称 | rename oldname newname
    离开远端主机 | exit (or) bye (or) quit
    针对本机(Client)之行为(都加上 l, L 的小写 )
    变换目录到本机的 PATH 当中 | lcd PATH
    列出目前本机所在目录下的档名 | lls
    在本机建立目录 | lmkdir
    显示目前所在的本机目录 | lpwd
    针对资料上传/下载的行为
    将档案由本机上传到远端主机 put [本机目录或档案] [远端]
    put [本机目录或档案]
    如果是这种格式，则档案会放置到目前远端主机的目录下！
    将档案由远端主机下载回来 get [远端主机目录或档案] [本机]
    get [远端主机目录或档案]
    若是这种格式，则档案会放置在目前本机所在的目录当中！可以使用万用字元，例如：
    get *
    get *.rpm
    亦是可以的格式！

    就整体而言， sftp 在 Linux 底下，如果不考虑图形介面，那么他已经可以取代 FTP 了呢！因为所有的功能都已经涵盖啦！因此，在不考虑到图形介面的 FTP 软体时，可以直接关掉 FTP 的服务，而改以 sftp-server 来提供 FTP 的服务吧！ ^_^

  • Linux Client: scp
    • 如果我要在两个主机之间复制档案的话，除了 sftp 之外，还有没有更简单的方式？ 有的，那就是利用 scp 这个指令啦！这个指令的用法与 cp 很相像，不过， 在远端主机的目录写法，比较需要注意就是了。举例如下：
    1. 将资料由本机上传到远端主机上去
[root@linux ~]# scp /etc/crontab dmtsai@localhost:/home/dmtsai/
dmtsai@localhost's password: <== 这里请输入密码啊！
crontab                  100%  620     0.6KB/s   00:00
# 这个例子在说明，我将本机目录的 /etc/crontab 这个档案传送给 dmtsai
# 这个使用者，而这个使用者是在 "localhost" 那部主机上面喔！
# 仔细看一下，会有一个传输资料的讯息跑出来喔！

2. 将资料由远端主机下载到本机上！
[root@linux ~]# scp dmtsai@localhost:~/.bashrc .
# 这个例子则是在说明，我要将 localhost 那部机器上的 dmtsai 这个人，
# 他家目录下的 .bashrc 复制到我的机器上！
    也就是说，远端主机上的档案或目录要复制时，是以‘ hostname:PATH ’ 方式来书写的～不要写错了呦！而如果想要复制目录的话，那么可以加上 -r 的参数！

  • Windows Client: putty
    • 在 Linux 底下想要连接 SSH 伺服器，可以直接利用 ssh 这个指令 ，那么如果在 Windows 作业系统底下，又该如何连接到 SSH 伺服器呢？可以直接使用 putty 或 pietty 这种类型的连线软体呢，他也是免费的自由软体喔！取得的方式可以参考底下的网站：
    • putty 官方网站：http://www.chiark.greenend.org.uk/~sgtatham/putty/
    • pietty 官方网站：http://www.csie.ntu.edu.tw/~piaip/pietty/
    在 putty 的官方网站上有很多的 client 软体可以使用的，包括 putty/pscp/psftp 等等。 他们分别对应了 ssh/scp/sftp 这三个指令就是了。而上述的三个 putty/pscp/psftp 主要是在 Windows 上面连接到 Unix like 机器的 SSH 伺服器的 Client 软体呢。请自行下载该软体喔。

    事实上，鸟哥比较喜欢林弘德先生的 pietty，因为这个软体不但是完整支援 putty ，而且提供的文字编码较丰富， 实在很好用。在你下载了 pietty 后直接双击他， 会有类似底下的图示出现。

    pietty 的执行图示之一
    图二、pietty 的执行图示之一

    在上图 1 的地方请填写相关的主机名称或者是 IP ，2 当然务必选择 SSH 那一项， 至于 3 的地方，鸟哥比较喜欢选单出现的样式，所以我是选择选单啦！若没有问题，按下‘连线’后， 就会出现如下样式：

    pietty 的执行图示之一
    图三、pietty 的执行图示之一

    很像在主机前面工作吧！而且上头还有选单可以随时调整类似字形、字体、字元编码等等。 尤其是字元编码。有时候你会发现开启档案时，竟然画面当中会有乱码而不是正常的中文显示， 那就是编码的问题。要解决这个问题时，你必须要牢记：
    • 文字档案本身在存档时所挑选的语系；
    • Linux 主机本身所使用的语系 (可用 LANG 变数调整)；
    • pietty 所使用的语系。
    这三个咚咚的语系要完全相同时才会正确的显示出中文！千要要牢记啊！ 那如何调整 pietty 的中文编码呢？

    pietty 的执行图示之一
    图四、pietty 的执行图示之一

    在‘选项’的‘字元编码’里面可以挑选 big5 或者是 utf8 的中文编码， 让他符合你的 Linux 与档案所储存的资料格式，那就 OK 的啦！ ^_^！ 如果想要作更细部的设定时，可以选择图四上头最底下的那个‘详细设定’项目， 就会出现如下图示。其中更为重要的是‘键盘右侧的数字键想要生效’时， 可以按照下图的指示来启动数字键的功能：

    pietty 的执行图示之一
    图五、pietty 的执行图示之一

    如上图所示，在你输入‘Apply’之后，就可以自动的生效了！现在你可以按键盘右边的按钮了， 真方便。再来你可以调整 pietty 卷轴的记忆行数，这样当资料太多时，你依旧可以调整卷轴来查阅之前的资料。 设定的方法如下：

    pietty 的执行图示之一
    图六、pietty 的执行图示之一

    调整完了荧幕的大小之后，再来这是最重要的：‘您要以哪一个版本的 SSH 演算法登入？！’前面说过，我们预设是以 version2 来登入的，所以这里我们可以调整为 2 那个项目！这样每次登入都会以 version 2 的模式登入主机了！

    pietty 的执行图示之一
    图七、pietty 的执行图示之一

    整个 pietty 大致上的流程就是这样！如此一来，您就可以在 Windows 上面以 SSH 的协定，登入远端的 Linux 主机噜！粉方便吧！ ^_^ ！ 那么如果想要中文支援的话，目前 pietty 已经支援中文啦！您可以输入中文喔！不过需要修改一下字元集， 选择图四的‘选项’内的‘字型’，会出现如下图示：

    pietty 的执行图示之一
    图八、pietty 的执行图示之一

    将(1)字型设定为宋体 (2)字集设定为‘Big5’，如此一来，您的 pietty 就支援中文的输入啰！ ^_^
    那么上面我们作的这些设定值都记录在哪里啊？呵呵！都记录在 Windows 的登录档当中啊！ 您可以在 Windows 的系统当中，在‘开始’-->‘执行’后，出现的框框内输入‘regedit’， 之后会出现一个大视窗。请在左边的画面当中选择‘ HKEY_CURRENT_USER --> Software --> SimonTatham --> PuTTY --> Sessions’， 就可以看到您的设定值啰！ ^_^！ 这样，也就可以储存您的设定值啰～

  • Windows Client: psftp
    • 在 putty 的官方网站上也提供 psftp 这支程式。这一支程式的重点则是在于以 sftp 连线上 Server 。连线的方式可以直接点选 psftp 这个档案，让他直接启动，则会出现下面的图样：
    psftp: no hostname specified; use "open host.name" to connect
psftp>
    这个时候可以填入您要连接上去的主机名称，例如我的区域内网路 linux.dmtsai.tw 这个主机
    psftp: no hostname specified; use "open host.name" to connect
psftp> open test.linux.org
login as: dmtsai
Using username "dmtsai".
dmtsai@linux.dmtsai.tw's password:
Remote working directory is /home/dmtsai
psftp> <== 这里就在等待您输入 FTP 的指令了！
    呵呵！这样就登入主机啦！很简单吧！然后其他的使用方式跟前面提到的 sftp 一样哩！加油的使用吧！

  • Windows Client: Fliezilla
    • 那么 SSH 所提供的 sftp 功能只能利用纯文字介面的 psftp 来连线吗？有没有图形介面的软体呢？呵呵！当然有！ 那就是非常有用的 Filezilla 啰！Filezilla 是图形介面的一个 FTP 用户端软体，使用上非常的方便， 至于详细的安装与使用流程请参考 vsftpd 章节的说明喔！
    小标题的图示 详细设定 sshd 伺服器
    基本上，所有的 ssh 相关设定都放在 /etc/ssh/sshd_config 里面！不过，每个 Linux distribution 的预设设定都不太相同， 所以我们有必要来了解一下整个设定值的意义为何才好！
    [root@linux ~]# vi /etc/ssh/sshd_config
# 1. 关于 SSH Server 的整体设定，包含使用的 port 啦，以及使用的密码演算方式
# 先留意一下，在预设的档案内，只要是被注解的设定值(#)，即为‘预设值！’
Port 22
# SSH 预设使用 22 这个port，也可以使用多个port，即重复使用 port 这个设定项目！
# 例如想要开放 sshd 在 22 与 443 ，则多加一行内容为：
# Port 443
# 这样就好了！不过，不建议修改 port number 啦！

Protocol 1,2
# 选择的 SSH 协定版本，可以是 1 也可以是 2 ，
# 如果要同时支援两者，就必须要使用 2,1 这个分隔了(Protocol 1,2)！
# 目前我们会建议您，直接使用 Protocol 2 即可！

#ListenAddress 0.0.0.0
# 监听的主机介面卡！举个例子来说，如果您有两个 IP，
# 分别是 192.168.0.100 及 192.168.2.20 ，那么只想要
# 开放 192.168.0.100 时，就可以写如同下面的样式：
ListenAddress 192.168.0.100
# 只监听来自 192.168.0.100 这个 IP 的SSH连线。
# 如果不使用设定的话，则预设所有介面均接受 SSH

#PidFile /var/run/sshd.pid
# 可以放置 SSHD 这个 PID 的档案！左列为预设值

#LoginGraceTime 2m
# 当使用者连上 SSH server 之后，会出现输入密码的画面，在该画面中，
# 在多久时间内没有成功连上 SSH server ，就断线！若无单位则预设时间为秒！

#Compression yes
# 是否可以使用压缩指令？当然可以啰

# 2. 说明主机的 Private Key 放置的档案，预设使用下面的档案即可！
#HostKey /etc/ssh/ssh_host_key        # SSH version 1 使用的私钥
#HostKey /etc/ssh/ssh_host_rsa_key    # SSH version 2 使用的 RSA 私钥
#HostKey /etc/ssh/ssh_host_dsa_key    # SSH version 2 使用的 DSA 私钥
# 还记得我们在主机的 SSH 连线流程里面谈到的，这里就是 Host Key ～

# 2.1 关于 version 1 的一些设定！
#KeyRegenerationInterval 1h
# 由前面连线的说明可以知道， version 1 会使用 server 的 Public Key ，
# 那么如果这个 Public Key 被偷的话，岂不完蛋？所以需要每隔一段时间
# 来重新建立一次！这里的时间为秒！不过我们通常都仅使用 version 2 ，
# 所以这个设定可以被忽略喔！

#ServerKeyBits 768
# 没错！这个就是 Server key 的长度！用预设值即可。

# 3. 关于登录档的讯息资料放置与 daemon 的名称！
SyslogFacility AUTHPRIV
# 当有人使用 SSH 登入系统的时候，SSH会记录资讯，这个资讯要记录在什么 daemon name
# 底下？预设是以 AUTH 来设定的，即是 /var/log/secure 里面！什么？忘记了！
# 回到 Linux 基础 去翻一下。其他可用的 daemon name 为：DAEMON,USER,AUTH,
# LOCAL0,LOCAL1,LOCAL2,LOCAL3,LOCAL4,LOCAL5,

#LogLevel INFO
# 登录记录的等级！嘿嘿！任何讯息！同样的，忘记了就回去参考！

# 4. 安全设定项目！极重要！
# 4.1 登入设定部分
PermitRootLogin no
# 是否允许 root 登入！预设是允许的，但是建议设定成 no！

#UserLogin no
# 在 SSH 底下本来就不接受 login 这个程式的登入！

#StrictModes yes
# 当使用者的 host key 改变之后，Server 就不接受连线，可以抵挡部分的木马程式！

#RSAAuthentication yes    # 是否使用纯的 RSA 认证！？仅针对 version 1 ！
#PubkeyAuthentication yes # 是否允许 Public Key ？当然允许啦！仅针对 version 2

#AuthorizedKeysFile      .ssh/authorized_keys
# 上面这个在设定若要使用不需要密码登入的帐号时，那么那个帐号的存放档案所在档名！
# 这个设定值很重要喔！档名给他记一下！

# 4.2 认证部分
#RhostsAuthentication no
# 本机系统不使用 .rhosts，因为仅使用 .rhosts太不安全了，所以这里一定要设定为 no

#IgnoreRhosts yes
# 是否取消使用 ~/.ssh/.rhosts 来做为认证！当然是！

#RhostsRSAAuthentication no #
# 这个选项是专门给 version 1 用的，使用 rhosts 档案在 /etc/hosts.equiv
# 配合 RSA 演算方式来进行认证！不要使用啊！

#HostbasedAuthentication no
# 这个项目与上面的项目类似，不过是给 version 2 使用的！

#IgnoreUserKnownHosts no
# 是否忽略家目录内的 ~/.ssh/known_hosts 这个档案所记录的主机内容？
# 当然不要忽略，所以这里就是 no 啦！

PasswordAuthentication yes
# 密码验证当然是需要的！所以这里写 yes 啰！

#PermitEmptyPasswords no
# 若上面那一项如果设定为 yes 的话，这一项就最好设定为 no ，
# 这个项目在是否允许以空的密码登入！当然不许！

ChallengeResponseAuthentication no
# 允许任何的密码认证！所以，任何 login.conf 规定的认证方式，均可适用！
# 但目前我们比较喜欢使用 PAM 模组帮忙管理认证，因此这个选项可以设定为 no 喔！
UsePAM yes
# 利用 PAM 管理使用者认证有很多好处，可以记录与管理。
# 所以这里我们建议您使用 UsePAM 且 ChallengeResponseAuthentication 设定为 no

# 4.3 与 Kerberos 有关的参数设定！因为我们没有 Kerberos 主机，所以底下不用设定！
#KerberosAuthentication no
#KerberosOrLocalPasswd yes
#KerberosTicketCleanup yes
#KerberosTgtPassing no

# 4.4 底下是有关在 X-Window 底下使用的相关设定！
X11Forwarding yes
#X11DisplayOffset 10
#X11UseLocalhost yes

# 4.5 登入后的项目：
PrintMotd no
# 登入后是否显示出一些资讯呢？例如上次登入的时间、地点等等，预设是 yes
# 亦即是列印出 /etc/motd 这个档案的内容。但是，如果为了安全，可以考虑改为 no ！

PrintLastLog yes
# 显示上次登入的资讯！可以啊！预设也是 yes ！

KeepAlive yes
# 一般而言，如果设定这项目的话，那么 SSH Server 会传送KeepAlive 的讯息给
# Client端，以确保两者的连线正常！在这个情况下，任何一端死掉后，SSH可以立刻知道！
# 而不会有僵尸程序的发生！

UsePrivilegeSeparation yes
# 使用者的权限设定项目！就设定为 yes 吧！

MaxStartups 10
# 同时允许几个尚未登入的连线画面？当我们连上 SSH ，但是尚未输入密码时，
# 这个时候就是我们所谓的连线画面啦！在这个连线画面中，为了保护主机，
# 所以需要设定最大值，预设最多十个连线画面，而已经建立连线的不计算在这十个当中

# 4.6 关于使用者抵挡的设定项目：
DenyUsers *
# 设定受抵挡的使用者名称，如果是全部的使用者，那就是全部挡吧！
# 若是部分使用者，可以将该帐号填入！例如下列！
DenyUsers test

DenyGroups test
# 与 DenyUsers 相同！仅抵挡几个群组而已！

# 5. 关于 SFTP 服务的设定项目！
Subsystem       sftp    /usr/lib/ssh/sftp-server
    基本上，CentOS 预设的 sshd 服务已经算是挺安全的了，不过还不够！ 建议你 (1)将 root 的登入权限取消； (2)将 ssh 版本设定为 2 。 其他的设定值就请您依照自己的喜好来设定了。通常不建议进行随便修改啦！ 另外，如果您修改过上面这个档案(/etc/ssh/sshd_config)，那么就必需要重新启动一次 sshd 这个 daemon 才行！亦即是：
    • /etc/init.d/sshd restart
    小标题的图示 制作不用密码可立即登入的 ssh 用户：
    咦！既然 SSH 可以使用 Key 来比对资料，并且提供使用者资料的加密功能， 那么可不可能利用这个 Key 就提供使用者自己进入主机，而不需要输入密码呢？ 呵呵！好主意！我们可以将 Client 产生的 Key 给他拷贝到 Server 当中，所以， 以后 Client 登入 Server 时，由于两者在 SSH 要连线的讯号传递中，就已经比对过 Key 了， 因此，可以立即进入资料传输介面中，而不需要再输入密码呢！在实作上的步骤可以是：
    1. 首先，先在 Client 上面建立 Public Key 跟 Private Key 这两把钥匙，利用的指令为 ssh-keygen 这个命令；
    2. 再来，将 Private Key 放在 Client 上面的家目录，亦即 $HOME/.ssh/ ， 并且修改权限为仅有该 User 可读的状态；
    3. 最后，将那把 Public Key 放在任何一个您想要用来登入的主机的 Server 端的某 User 的家目录内之 .ssh/ 里面的认证档案即可完成整个程序。
    说是好像很困难的样子，其实步骤真的很简单，我们依序来进行作业好了！假设前提：
    • Server 部分为 linux.dmtsai.tw 这部 192.168.0.2 的主机，欲使用的 User 为 test 这个帐号；
    • Client 部分为 test2.dmtsai.tw 这部 192.168.0.100 PC 的 test2 这个帐号， 他要用来登入 192.168.0.2 这部主机的 test 这个帐号。
    1. 在 Client 端建立 Public 与 Private Key ：

      2. 建立的方法真的是简单到不行！直接在 192.168.0.100 这个 Client 上面，以 test2 这个帐号，使用 ssh-keygen 这个指令来进行 Key 的产生即可！不过，需要注意的是， version 1 与 version 2 使用的密码演算方式不同，此外， version 2 提供两个密码演算的方法，我们这里仅针对 version 2 的 RSA 这个演算方法进行说明！
      [test2@test2 ~]$ ssh-keygen -t rsa  <==这个步骤在产生 Key pair
Generating public/private rsa key pair.
Enter file in which to save the key (/home/test2/.ssh/id_rsa): <==这里按下Enter
Enter passphrase (empty for no passphrase): <==这里按 Enter
Enter same passphrase again:  <==再按一次 Enter
Your identification has been saved in /home/test2/.ssh/id_rsa. <==这是私钥
Your public key has been saved in /home/test2/.ssh/id_rsa.pub. <==这是公钥
The key fingerprint is:
c4:ae:d9:02:d1:ba:06:5d:07:e6:92:e6:6a:c8:14:ba test2@test2.linux.org
# 注意： -t 指的是‘使用何种密码演算方式？’由于我们使用 RSA ，
# 所以直接输入 -t rsa 即可建立两支 Keys ！
# 此外，建立的两把 Keys 都放置在家目录下的 .ssh 这个目录中！
# 察看一下这两把 Keys 吧！

[test2@test2 ~]$ ll ~/.ssh
total 12
-rw-------    1 test2    test2         887 Nov 12 22:36 id_rsa
-rw-r--r--    1 test2    test2         233 Nov 12 22:36 id_rsa.pub
-rw-r--r--    1 test2    test2         222 Oct 31 11:20 known_hosts
      请注意上面喔，我的身份是 test2 ，所以当我执行 ssh-keygen 时， 才会在我的家目录底下的 .ssh/ 这个目录里面产生所需要的两把 Keys ，分别是私钥(id_rsa)与公钥(id_rsa.pub)。另外一个要特别注意的就是那个 id_rsa 的档案权限啦！他必须要是 -rw------- 才好！否则内容被人家知道了，那么您的 Keys 不就有可能外泄了？所以请特别留意他的权限喔！ 那么那个 id_rsa.pub 则是‘公钥！’这个档案必须要被放置到 Server 端才行！

    2. 在 Client 端放置私钥：

      3. 在预设的条件中，我们的私钥必需要放置在家目录底下的 .ssh 里面，那么如果是 version 2 的 RSA 演算法，就需要放置在 $HOME/.ssh/id_rsa 当中！咦！刚好使用 ssh-keygen 就是已经产生在这个目录下了，所以自然就不需要去调整他了！以我的 test2.dmtsai.tw 来看，那么我的档案就会放置在 /home/test2/.ssh/id_rsa 这个档案就是私钥啦！

    3. 在 Server 端放置可以登入的公钥：

      4. 既然我们要让 test2 可以用 test 这个帐号登入 linux.dmtsai.tw 这部主机，那么这部主机自然需要保有 test2 的 public key 啰！对的！所以我们必需要将 Client 端建立的 id_rsa.pub 档案给他拷贝到 linux.dmtsai.tw 里头的 test 这个使用者的家目录之下！那么如果您还记得上面的 sshd_config 这个档案的设定的话，那么应该就记得‘ AuthorizedKeysFile ’这个设定吧！是的！ 在被登入的主机的某个帐号，他的公钥放置的档案名称预设就是这个项目所记载的！而他预设的档名就是 authorized_keys 这个档案名称啦！那么应该怎么做呢？
      1. 先在 Client 端以 sftp 将公钥丢到 test 上面去！
[test2@test2 ~]$ cd ~/.ssh
[test2@test2 .ssh]$ scp id_rsa.pub test@192.168.0.2:~/
test@192.168.0.2's password:
id_rsa.pub          100%  233     0.2KB/s   00:00

2. 到 Server 上面，将公钥转存到 authorized_keys 档案中！
[test@linux ~]$ cd ~/.ssh
[test@linux .ssh]$ cat ../id_rsa.pub >> authorized_keys
      请注意上面的机器！由于 authorized_keys 可以保存相当多的公钥内容，因此， 可以使用 >> 的方式来将 Client 端的公钥新增到该档案内！呵呵！做完这一步一后，未来 test2 就可以直接在 test2.dmtsai.tw 以
      [test2@test2 ~]$ ssh test@linux.dmtsai.tw
      这样就可以不需要输入密码啰！但是请注意， test 不能以 test2 登入 test2.linux.org 喔！
    很简单的步骤吧！这样一来，就可以不需密码的手续了！无论如何，您要记得的是：
    • Client 必须制作出 Public & Private 这两把 keys，且 Private 需放到 ~/.ssh/ 内；
    • Server 必须要有 Public Key ，且放置到使用者家目录下的 ~/.ssh/authorized_keys；
    未来，当您还想要登入其他的主机时，只要将您的 public key (就是 id_rsa.pub 这个档案) 给他 copy 到其他主机上面去，并且新增到某帐号的 ~/.ssh/authorized_keys 这个档案中！哈哈！成功！

    小标题的图示 安全设定：
    老实说，大家都被‘SSH 是个安全的服务’所欺骗了！其实 sshd 并不怎么安全的！翻开 openssh 的过去历史来看，确实有很多人是利用 ssh 的程式漏洞来取得远端主机 root 的权限，进一步黑掉对方的主机！

    sshd 之所谓的‘安全’其实指的是‘ sshd 的资料是加密过的，所以他的资料在 Internet 上面传递时是比较安全的。 至于 sshd 这个服务本身就不是那样安全了！所以说：‘非必要，不要将 sshd 对 Internet 开放可登入的权限，尽量局限在几个小范围内的 IP 或主机名称即可！ 这很重要的喔！

    好了，那么关于安全的设定方面，有没有什么值得注意的呢？当然是有啦！ 我们可以先建议几个项目吧！分别可以由：
    • /etc/ssh/sshd_config
    • /etc/hosts.allow, /etc/hosts.deny
    • iptables
    这三方面来着手进行！底下我们就说一说吧！

  • /etc/ssh/sshd_config
    • 一般而言，这个档案的预设项目就已经很完备了！所以，事实上是不太需要更动他的！ 但是，如果您有些使用者方面的顾虑，那么可以这样修正一些问题呢！
    • 禁止 root 的登入：
      任何时候，不许 root 以远端连线的方式登入，都会是一个好主意！所以这里蛮建议大家直接将 root 的登入权限拿掉吧！所以，可以修改 /etc/ssh/sshd_config 这个档案的内容为：
      [root@linux ~]# vi /etc/ssh/sshd_config
PermitRootLogin no     <== 将他改成 no 吧！
[root@linux ~]# /etc/init.d/sshd restart
      如此一来，以后 root 就不能以 ssh 登入啰！这样还是比较好的啦！ ^_^

    • 不许某个群组登入：
      有些特殊情况中，我们想要让使用者只能使用 sendmail, pop3, ftp 等，但是不希望他可以远端连线进来，那么您可以这样做：

      1. 将这些使用者都归纳在某一个特殊群组之下，例如 nossh 这个群组好了；
      2. 在 /etc/ssh/sshd_config 当中加入这一行：‘ DenyGroups nossh ’
      3. 重新启动 sshd ： /etc/init.d/sshd restart

      这样就OK啦！

    • 不许某个使用者登入：
      跟 DenyGroups 类似，使用 DenyUsers 即可！参考 sshd_config 的设定喔！
  • /etc/hosts.allow 及 /etc/hosts.deny
    • 简单的方法就是：
    [root@linux ~]# vi /etc/hosts.allow
sshd: 192.168.0.1, 192.168.0.2, 192.168.0.3, 192.168.0.4, 192.168.0.5: allow

[root@linux ~]# vi /etc/hosts.deny
sshd : ALL : spawn (/bin/echo Security notice from host `/bin/hostname`; \
/bin/echo; /usr/sbin/safe_finger @%h ) | \
/bin/mail -s "%d -%h security" root@localhost & \
: twist ( /bin/echo -e "\n\nWARNING connectin not allowed.". )
  • iptables
    • 多几层保护也很好的！所以也可以使用 iptables 喔！参考： 简易防火墙架设 一文啰！
    最后，‘鸟哥呼吁大家，不要开放 SSH 的登入权限给所有 Internet 上面的主机～’ 这很重要喔～因为如果对方可以 ssh 进入您的主机，那么......太危险了～
    大标题的图示 XDMCP 伺服器
    考虑一个情况，如果您的 Linux 主机上面主要是用来作为图形处理时，而且同时有多人需要用到那个功能， 那么一部 Linux 是否一次仅能提供一个人处理那个软体呢？嘿嘿！那可不一定喔！因为 Linux 有相当优秀的 X Window System 啊！

    小标题的图示 X Window 的 Server/Client 架构
    X Window System 的架构对于常常玩网路的朋友来说(这也包括鸟哥啦！ @_@)实在不太好理解～ 因为 X Window System 在运作的过程中，同样包含了 X Server 与 X Client 这两个东西， 但是他的作用却与网路主机的 Server/Client 架构大异其趣喔～先来说说 X Server/Client 所负责的东西：
    • X Server： 他主要负责的是荧幕画面的绘制与显示。 X Server 可以接收来自 X client 的数据， 将这些数据绘制呈现为图面在荧幕上。此外，我们移动滑鼠、点击资料、由键盘输入资料等等， 也会透过 X Server 来传达到 X Client 端，而由 X Client 来加以运算；

    • X Client： 他主要负责的是资料的运算。 X Client 在接受到 X Server 传来的资料后，会经由本身的运算，而得到滑鼠应该要如何移动、 点击的结果应该要出现什么样的资料、键盘输入的结果应该要如何呈现等等， 然后将这些结果告知 X Server ，让他自行去绘制到荧幕上。
    这样说可以理解吗？也就是说，我们移动滑鼠或敲打键盘时， X server 可以接受到这些硬体所输入的资料， 但他不知道应该要怎么作才好，就把这些资料告诉 X Client ，此时， X Client 就会将这些资料计算， 最后得到滑鼠应该要如何移动与键盘的资料应该要如何呈现，并将这些结果告知 X Server ， 而 X Server 就会经由 X Client 的告知，而将那些数据资料在荧幕上面呈现出来。

    事实上， X Server 与 X Client 通常是在同一部机器上面的， 例如我们在 Linux 上面执行有名的 KDE 这个桌面一样。 但是 X Server/Client 却不必然一定要在同一部机器上的， 也就是说，我们可以透过网路连接两部主机的 X 系统呢！ 这也是最早 X 系统开发时的概念。不过，这个时候的 X server 指的是哪一部呢？

    举个例子来说，我们可以在 Windows 系统上面执行一套 X Win32 的软体， 他可以连接到 Linux 的 X 上头而让使用者以图形介面登入 Linux 。 此时，因为‘X Win 32’主要是在荧幕上面显示，他的做用就是荧幕绘制，因此他是 X Server 。 不信的话，等一下我们测试底下的资料时，您会发现，启动 X win32 这套软体后， 在 Windows 系统上就会出现 port 6000 这个 X server 的 port 呢～而这个时候 X Win 32 软体其实就是连接到 Linux 的某个程序，我们等一下要介绍的 XDMCP 就是其中一种。 这个 XDMCP 可以将 X Win32 传送过来的资料运算成可以绘制的数据而回传给 X win 32 那套软体， 此时的 XDMCP 程序就是一个 X Client 啰～

    所以啦！如果您的 Windows 想要连接到 Linux 主机的话，那么 Windows 就得要有可以执行的 X Server 软体啦～ 而 Linux 主机则必须要启动一个可以接受 X Server 资料运算的 X Client 啦～ 就是这样说～

    但是，这样做有什么好处呢？呵呵～最大的好处就是，在伺服器上的 X Client 不需要知道 X Server 的硬体是什么～因为负责显示的是 X server 的事情，管理硬体的动作也是 X server 在做， 在主机上的 X Client 只是将这些滑鼠移动与点击还有键盘的输入等的资料在主机端运算后， 最后将结果传送给 X Server 显示而已。(当然啦， X Client 的运算内容还是会用到主机端的设定档与函式库就是了。)

    X server/client 的架构
    图九、X server/client 的架构

    那么什么时候会出现多使用者连入 X 主机的情况呢？以鸟哥的例子来说，我们实验室有一部 Linux 在进行数值模拟， 他输出的结果是 NetCDF 档案，我们必须使用 PAVE 这一套软体去处理这些资料， 以绘制等浓度图等等的。但是我们有两三个人同时都会使用到那个功能， 偏偏 Linux 主机是放在机架柜里面的，要我们挤在那个小小的空间前面‘站着’操作电脑， 可真是讨人厌啊～这个时候，我们就会架设图形介面的远端登入伺服器， 让我们可以‘多人同时以图形介面登入 Linux 主机’来操作我们自己的程序！ 很棒，不是吗？！

    小标题的图示 设定 XDMCP
    XDM 是 X Display Manager 的简称，他的功能是什么呢？ 简单的说，就是管理操控 X Server 的显示啦～他主要有两种管理方式， 如果 X Server/Client 在同一部机器上，那么启动 xdm 之后，就会产生一个 X server 了； 而如果 X server/client 不在同一部主机上面，那么启动 xdm 后，他就会透过网路去管理远端那部主机的 X server 了。而 XDMCP (X Display Manager Control Protocol) 就是负责监听来自网路上面对于 xdm 的要求的啦～

    由 X11 (CentOS 使用的是 Xorg 这个计划的 X11)提供的 display manager 为 xdm ，设定档在 /etc/X11/xdm/xdm-config ， 而著名的 KDE 与 GNOME 也都有自己的 display manager 管理程序，分别是 kdm 与 gdm ， 设定档则是 /etc/X11/xdm/kdmrc 与 /etc/X11/gdm/gdm.conf (不同的 distribution 这个档案放置的目录不太一样)。我们可以透过三者中任何一者的 display manager 的设定档来启动 xdmcp 这个协定呢～

    要启用 xdmcp 的功能真的很简单，如果您要启用 xdm 的话，修改 /etc/X11/xdm/xdm-config 这个档案， 找到底下这一行(一般在最后一行)：
    DisplayManager.requestPort:    0
    将他修改成为：
    !DisplayManager.requestPort:    0
    亦即是注解掉，然后再重新启动 xdm 就好了。而 kdm 与 gdm 的设定也类似，底下鸟哥主要以 kdm 来进行 xdmcp 的架设。不过要注意的是，即使在 Linux 主机端不启用 X Server (port 6000) 也是可以正确无误的提供 X 介面的登入的～就如同上面提到的概念一般～ 但是，如果要获得比较正确的讯息，那么还是建议您，启用 kdm 时一并正确的启动 X ， 只是安全性上面就要注意一些了！好了，多说无益，来实作吧！
    1. 先让 kdm 支援 xdmcp 模式
[root@linux ~]# cd /etc/X11/xdm
[root@linux xdm]# vi kdmrc
[Xdmcp]
Enable=1
# 大约是在 70 行左右。不要怀疑！真的只要这样就好了！

2. 让 client 可以透过 X 来登入系统！与权限有关的设定
[root@linux xdm]# vi Xaccess
*
# 为了安全性上面的需要，想要登入 X 的话，得要通过这个档案的验证才行。
# 找到上面这一行，如果没有这一行的话(整行只有一个 * )，
# 就自行加入。这表示‘不论来自哪里，我都接受 X 登入’的意思！

3. 启动 kdm 喔！
[root@linux xdm]# /etc/init.d/xfs start
# 就如同我们上面提到的， kdm 执行后，可能的话，会在本机端启动一个 X server 的，
# 而我们这一版的 Xorg 要顺利的启动，得要先启用 X font Server 才行，
# 否则的话，您就得要到 /etc/X11/Xorg.conf 里面去设定好每个字型的路径才行。
[root@linux xdm]# kdm
[root@linux xdm]# netstat -tlunp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address  Foreign Address  State  PID/Program name
tcp        0      0 0.0.0.0:6000   0.0.0.0:*        LISTEN 5920/X
tcp        0      0 :::6000        :::*             LISTEN 5920/X
udp        0      0 :::177         :::*                    5918/kdm
# 要看到有 177 的 udp port 出现才行～ 因为那是 xdmcp 协定的监听埠口。
# 不过，如果要看看是否有成功启动 X 的话，就得要查阅 6000 这个 port 啰～
# 如果没有看到 port 6000 的话，请查阅 /var/log/Xorg.0.log 喔！
# 如果想要设定开机就自动执行的话，可以利用 chkconfig 加入 xfs ，
# 也可以将 kdm 这个指令写到 /etc/rc.d/rc.local 这个档案中～
    虽然是非必备的，不过为了避免困扰，这里还是得要提醒大家。(因为 CentOS 不需要启动 X 就能够提供 xdmcp 登入) 鸟哥上面的测试是在 run level 为 3 的环境下，且整体在执行的时候， /var/log/messages 与 /var/log/Xorg.0.log 这两个档案内容中并没有 kdm 的相关错误讯息～ 很重要啊！因为某些套件如果没有成功的启动 X 时，他就无法提供登入呢～

    小标题的图示 用户端登入
  • 用户端是 Linux 主机：
    • 如果想要进行 XDMCP 提供的 X 介面的登入 Linux 主机时，在 Linux 底下可是容易的很～ 底下的流程是在‘用户端’执行的喔～不是刚刚那部 XDMCP 所在的 Linux 主机啦！
    0. 请务必要在 X Window 当中，进入 X Window 的方式有：
[root@client ~]# startx
# 或
[root@client ~]# init 5

1. 在 X Window 的画面当中，启用一个 shell ，然后输入：
[root@client ~]# xhost + 192.168.1.100
192.168.1.100 being added to access control list
# 假设我刚刚那部 Linux 主机的 IP 为 192.168.1.100
[root@client ~]# init 3   <== 关闭 X Server

2. 在文字介面下输入：
[root@client ~]# X -query 192.168.1.100
# 进入 X Window 啰！
    如果一切顺利的话，您应该就能够到 X Window 的画面底下去登入远端主机啰～

  • 用户端是 Windows 主机：
    • 如果想要进行 XDMCP 提供的 X 介面的登入 Linux 主机时，在 Windows 底下就得要使用其他软体来支援了。例如：
    • X-Win32 (http://www.starnet.com/evalkey/)
    • Exceed (http://www.hummingbird.com/products/nc/exceed/index.html?cks=y)
    这里鸟哥用 X-Win32 来进行测试。正个运作流程是这样的：
    1. 安装 X-Win32 ，很简单～就是直接执行下一步即可。比较可惜的是，这个软体目前没有中文支援喔！

    2. 直接在‘开始’-->‘程式集’-->‘X Win 32’执行‘X-Win32’这支程式～会出现如下图：

      X Win 32 执行范例
      图十、X Win 32 执行范例

      上面只是在告诉我们，这个软体需要注册。但是我们只是试用而已，所以可以直接按下 Evaluation 即可。 不过，试用版有连线三十分钟的限制就是了～@_@

    3. 在出现的视窗当中，当然要选择 XDMCP 这个模式啰～

      X Win 32 执行范例
      图 11 、X Win 32 执行范例

    4. 因为我们可以直接给予一个 X server 的 IP，所以这里我们可以选择‘Query’这个项目。 如果您是在 LAN 环境当中，而且 Client/Server 是在同一个网段时，其实可以选择 Broadcast 比较好用！无论如何，这里鸟哥先以 Query 来介绍。

      X Win 32 执行范例
      图 12 、X Win 32 执行范例

    5. 接下来的画面可以填入 IP 或主机名称啊！建议直接输入 IP 啦！

      X Win 32 执行范例
      图 13 、X Win 32 执行范例

    6. 接下来的画面只要填入一个简单的好记得名称即可！如果想要立即执行的话，那个‘Launch this session now’ 可以直接打勾喔！

      X Win 32 执行范例
      图 14 、X Win 32 执行范例

    7. 理论上，这样应该就可以立即的进行连线到 X Window Server 才对。不过，如果没有成功呢？ 没关系！我们可以重新来修改一下设定啊～如果执行了 X-Win32 之后，在工作列的右下角会出现 X 图示， 如下所示：

      X Win 32 执行范例
      图 15 、X Win 32 执行范例

      将滑鼠指标移动到 X 上头，按下右键，可以得到如下的选单出现：

      X Win 32 执行范例
      图 16 、X Win 32 执行范例

      在上图上面按下‘XConfig’就可以出现底下的图示：

      X Win 32 执行范例
      图 17 、X Win 32 执行范例

      然后选择我们刚刚设定好的那个 session ，按下‘Edit’，就可以开始修改刚刚的设定值啰～ 更多的选项请自行参考 X Win32 当中的说明。此时，我们可以在工作列的 X 上面，按下左键， 应该会出现所有可以用的 session ，请选择 linux.dmtsai.tw 那个 session ，如果一切顺利， 就会出现如下的画面：

      X Win 32 执行范例
      图 18 、X Win 32 执行范例

      输入帐号密码之后，嘿嘿！立刻就可以在 Windows 上面看到您 Linux 主机的 X Window 画面了～ 感动吧～ ^_^
    Tips:
    事实上，xdmcp 真的很容易设定的～鸟哥曾经以 gdm (设定档为 gdm.conf) 及 kdm 分别设定过， 执行上都没有问题。不过，需要特别留意的是，因为 X Window 执行的资料量实在是太大了， 所以，如果您在 Internet 上面使用 ADSL 传输的话，想要玩这个玩意儿～ 奉劝您：‘别想了～’这东西主要还是应用在内部网域当中的啦！     		鸟哥的图示
    小标题的图示 关闭 XDMCP
    如果想要关掉的话，就这样做：
    [root@linux xdm]# killall -9 kdm
[root@linux xdm]# /etc/init.d/xfs stop
    这样就可以将 xdmcp 给他关掉啰～ ^_^
    大标题的图示 VNC 伺服器
    虽然 xdmcp 就已经很好用了，不过，就以传输速度上来讲，他真的是慢啊～～ 这个时候，我们可以利用 VNC (Virtual Network Computing) 这个好用的咚咚来进一步设定我们的 X Window 登入系统喔。

    VNC 必须要透过 VNC Server 与 VNC client 软体的呼相搭配，就可以进行比较快速一点的资料传输。 而 VNC 如果想要漂亮的一点的话，也是需要搭配 xdmcp 的啦～因为如果是纯粹使用 VNC 连接到 Xorg (或 XFree86) 那个简单的画面，真的是....有点不好用～

    其实 VNC Server 会在主机多开一个程序在等待 Client 的登入要求， 等到 Client 登入之后，才去执行 Window manager 的启动。而这个 Window manager 的启动方式有很多种， 最阳春的就是利用 Xorg 预设的 twm 这个视窗管理程式，他真的是不好看～ 画面有点像这样：

    使用 twm 连线为 VNC Server 的执行范例
    图 19 、使用 twm 连线为 VNC Server 的执行范例

    真的不很好看喔～那怎么办？其实我们可以透过更改 VNC 的启动设定档： xstartup 来设定不同的 Window manager ， 另外，我们也可以透过启用 kdm 或 gdm 这两个好用的 display manager 来代为管理 Window manager 呢～ 鸟哥比较喜欢使用查询 (Query) XDMCP 的方式来启动 VNC ，而不是直接启动 startkde 这个程式的说～ 所以，底下我们就直接来设定可以连接到 xdmcp 上的 VNC Server 吧！
    1. 先让 kdm 支援 xdmcp 模式
[root@linux ~]# cd /etc/X11/xdm
[root@linux xdm]# vi kdmrc
[Xdmcp]
Enable=1

2. 让 client 可以透过 X 来登入系统！与权限有关的设定
[root@linux xdm]# vi Xaccess
*

3. 启动 kdm 喔！
[root@linux xdm]# /etc/init.d/xfs start
[root@linux xdm]# kdm
[root@linux xdm]# netstat -tlunp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address  Foreign Address  State  PID/Program name
tcp        0      0 0.0.0.0:6000   0.0.0.0:*        LISTEN 5920/X
tcp        0      0 :::6000        :::*             LISTEN 5920/X
udp        0      0 :::177         :::*                    5918/kdm
# 要看到有 177 的 udp port 与 port 6000 才行；
# 如果没有看到的话，就得要查询底下几个档案的内容，看看错误讯息了！
# a. 必须查阅 netstat -tlunp
# b. 必须查阅 /var/log/Xorg.log.0
# c. 必须查阅 /var/log/messages
# d. 必须查阅 /var/log/kdm.log

4. 用某身份建立 passfile 给 VNC 连线时使用
# 因为 VNC 开的每个 port 都是给某特定使用者登入的，因此，
# 每个 VNC server 都会启用自己的 port 呢～据说最大可开放到 10 个～
# 鸟哥这里假设利用 dmtsai 这个使用者来执行 VNC ，那么他就必须要有底下几个动作：
4.1 建立连线用密码
[root@linux xdm]# su dmtsai
[dmtsai@linux xdm]$ vncpasswd
Password: <== 这里请输入密码
Verify: <== 再输入一次～
# 特别注意，为了安全起见，密码的长度是有限制的！
# 至少要大于六个字元，且不能与帐号相同～
# 密码建立后，会在 /home/dmtsai/.vnc/passwd 这个档案中记录了你的密码～
# 同时，在这个目录下，还有设定档 xstartup 可以利用喔！ ^_^
4.2 修改设定档 xstartup
[dmtsai@linux xdm]$ vi /home/dmtsai/.vnc/xstartup
# 将这个档案内的所有资料通通给他注解掉～不需要保留～
4.3 离开此一身份使用者的画面
[dmtsai@linux xdm]$ exit

5. 修改 /etc/sysconfig/vncserver 档案内容
# 这个档案是 FC4 预设的启动 VNC 的读取档，所以我们可以修改他～
[root@linux xdm]# vi /etc/sysconfig/vncservers
# 将原本的资料改成这样：
VNCSERVERS="2:dmtsai"
VNCSERVERARGS[2]="-geometry 800x600 -query localhost"
# 意思是说，我们要启动一个 VNC 在 port 5900+2 即 5902 的意思，

6. 启动 VNC server
[root@linux xdm]# /etc/init.d/vncserver start
# 此时在 /home/dmtsai/.vnc/ 里面应该会有几个档案您应该要注意的，
# 最重要的就是 dmtasi.linux.dmtsai.tw:2.log 这个档案，档名的由来是：
# username.hostname.domainname:[port number].log ，因为我们是启用 5902 ，
# 所以就有 :2.log 的附档名啦～务必看到里面没有错误才行喔～
# 如果发现找不到/usr/X11R6/lib/X11/xserver/SecurityPolicy 的错误，先略过不要紧～

7. 查阅设定结果
[root@linux xdm]# netstat -tulnp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State    PID/Program name
tcp        0      0 0.0.0.0:5802  0.0.0.0:*       LISTEN   15287/Xvnc
tcp        0      0 0.0.0.0:5902  0.0.0.0:*       LISTEN   15287/Xvnc
tcp        0      0 0.0.0.0:6000  0.0.0.0:*       LISTEN   15019/X
tcp        0      0 0.0.0.0:6002  0.0.0.0:*       LISTEN   15287/Xvnc
tcp        0      0 :::6000       :::*            LISTEN   15019/X
tcp        0      0 :::6002       :::*            LISTEN   15287/Xvnc
udp        0      0 0.0.0.0:32924 0.0.0.0:*                15287/Xvnc
udp        0      0 :::177        :::*                     15017/kdm
    设定好像也很简单喔～那么鸟哥干嘛讲这么多原理？ 原因无他，因为希望大家可以在不同的 Linux distributions 也能够顺利的架设好 XDMCP 与 VNC ，如果您能够善用登录档的内容资讯， 那么应该会比较容易 debug 的啦～ ^_^

    另外，事实上启动 VNC 的 script 是由 vncserver 这个指令所启用的， 您也可以直接利用某个身份直接下达：
    [root@linux ~]# vncserver :3

You will require a password to access your desktops.

Password: <== 就输入密码吧！
Verify: <== 再输入密码吧！

New 'dmtsai.linux.dmtsai.tw:3 (dmtsai)' desktop is dmtsai.linux.dmtsai.tw:3

Starting applications specified in /root/.vnc/xstartup
Log file is /root/.vnc/dmtsai.linux.dmtsai.tw:3.log
    如此一来，就可以启用一个 port 为 5903 的 VNC 服务啰～ 您可以再度的去到 logfile 查一查啊～至于关闭的话，可以用：
    [root@linux ~]# vncserver -kill :3
    这样就能够关闭啰～呵呵！那么如果想要连接到 VNC Server 的话， 在 Linux 底下可以利用 KDE 的 krdc 这支远端连线程式，如果是 Windows 的话， 就得需要 VNC Client 啰～您可以前往底下的网站：
    • http://www.realvnc.com/download.html
    直接下载 Free Edition 来测试看看就好了。安装过程我们就不提了～ 安装完毕之后，直接执行‘开始’-->‘程式集’-->‘RealVNC’-->‘Run VNC viewer’后， 出现如下的视窗：

    VNC viewer 执行范例
    图 20 、VNC viewer 执行范例

    输入了您的主机 IP 与该 VNC 对应的 port 之后，会出现一个密码视窗：

    VNC viewer 执行范例
    图 21 、VNC viewer 执行范例

    记得啊～这里的密码指的是‘您利用 vncpasswd 所建立的密码’，而不是登入者的密码啊～ 按下 Enter 之后，如果顺利的话，就会出现如下的图示啰～

    VNC viewer 执行范例
    图 22 、VNC viewer 执行范例

    VNC viewer 执行范例
    图 23 、VNC viewer 执行范例

    很不错吧！ ^_^ 这样就能够在 Client 端登入 Linux 主机啰～ 而且还可以多人共用呢～真是棒～ ^_^。但是，如果您设定完毕之后， 在登录档老是出现这个咚咚： ‘XDMCP fatal error: Manager unwilling Host unwilling’， 就是 /etc/X11/xdm/Xaccess 这个档案的设定需要变更了！

    另外，有些朋友一定会觉得奇怪，那就是，为什么我的 VNC 伺服器的 server / client 端画面并不是同步的呢? 这是因为 Linux 本身提供多个 VNC server ，她们是各自独立的，所以当然就不会与 tty7 的画面同步了。 但是如果您想要与 Linux 的 tty7 同步的话，可以利用 VNC 释出的给 X Server 使用的模组来加以设定即可。 如果您是 CentOS 4.x 这个 distribution 的话，恭喜您，系统预设已经将 vnc.so 这个模组释出了，您可以查阅 /usr/X11R6/lib/modules/extensions/ 这个档案，即可知道有没有 vnc.so 这个模组。如果您没有这个模组的话， 请参考 http://phorum.study-area.org/viewtopic.htm?t=25713 这一篇文章的说明， 依序来设定吧!
    [root@linux ~]# vi /etc/X11/xorg.conf (或 XF86Config)
Section "Module"
    ....
        Load  "vnc"
EndSection
# 在 Module 这个 section 当中加入 vnc 这个模组即可
Section "Screen"
        Identifier "Screen0"
        Device     "Videocard0"
        Monitor    "Monitor0"
        Option     "passwordFile"  "/etc/vnc/passwd"
        DefaultDepth     16
    ......
EndSection
# 假设您的 vnc 密码档案放置在 /etc/vnc/passwd 里头，
# 这个时候就得要将密码档内容写到 Screen 这个 section 当中了
    此时给他重新启动一下 kdm 或者是重新进入 run level 5 的时候，您就会发现多了一个 port 5900 呢， 嘿嘿，准备同步登入吧 ^_^

    大标题的图示 RSH 伺服器
    什么是 RSH 伺服器呢？其实，这是早期的不同主机之间互相‘直接操作’对方资源的一个方法。 其实就好像使用‘ ssh dmtsai@localhost date ’之类的执行方法啦！ 我们可以透过 rsh 来操作对方主机啊。这个 RSH 就是被称为 R Shell 的咚咚啰～

    目前 RSH 很少被使用到一般的伺服器上面，尤其是对 Internet 开放的主机， 这是因为 RSH 的危险性很高！他不但是明码传输，而且一个设定不良，可能会让所有人都能使用 RSH 来登入主机！ 不过，RSH 却是操作丛集电脑 (cluster) 里面最常见的服务之一！

    所谓的丛集电脑，简单的说就是‘将很多部主机透过网路连结在一起， 以其中一部主机作为主要操控电脑 (或者称为 master) ，其他主机仅负责来自 master 的要求 (所以被称为 slave)；所有的电脑工作都是由 master 所掌控， slave 仅负责运算的部分。’ 这也就是说， slave 大概就仅提供 CPU 的运算单元，其他的事都是 master 负责来运作。 当然，我们也是只要操控 master 那部主要电脑而已。在这样的情况下， slave 接受 master 的指令， 最主要就是透过 RSH 啊！ (当然，也可以透过 SSH 配合金钥来达成这样的工作！)。 关于更多的 cluster 的介绍，可以参考一下鸟哥之前写的一篇小文章：
      http://linux.vbird.org0600cluster.htm
    至于 RSH server 与 Client 的互动可以使用下面的图示来查阅：

    RHS Server/Client 互动示意图
    图 24 、RHS Server/Client 互动示意图

    上图中在 RSH server 当中的几个设定档是这样的：
    • /etc/hosts：主要规范 RSH server/client 的主机名称与 IP 对应！
    • /etc/hosts.equiv：规范出哪一部 client 可以连上这部 RSH server；
    • ~user/.rhosts：规范出那个使用者可以不需要输入密码即可执行 RSH；
    • /etc/pam.d/rsh：规范 root 能否使用 RSH 的设定档。
    虽然 RSH 目前已经很少被使用，但是在内部主机的连线上面还是有他的存在的价值啦！ 因此，底下我们就来谈一谈如何玩弄这个 RSH 吧！

    小标题的图示 RSH Server
    其实 R Shell 有很多的工具与启动的 port ，常见的 R Shell 工具有 rexec, rlogin, rsh 等， 而这些工具都对应到不同的 port 上面，你可以到 /etc/services 上查阅一下 512, 513, 514 这三个 port 吧！

  • RSH Server 的启动：
    • 如图 24 所示，我们在 RSH Client 电脑上面想要使用 RSH Server 上头的资料时， 那么 RSH server 自然就得要启动 RSH 这项服务啰！那么如何启动呢？简单的很～ 就利用 super deamon 来启动， 我们需要有 rsh 及 rsh-server 两个套件才行！请自行安装吧！ 另外， rsh-server 共提供三个服务，分别是‘ rexec, rlogin, rsh ’，我们先单纯讨论 rsh 吧！ 安装完毕之后，直接启动即可：
    [root@linux ~]# vi /etc/xinetd.d/rsh
service shell
{
        disable                 = no
        socket_type             = stream
        wait                    = no
        user                    = root
        log_on_success          += USERID
        log_on_failure          += USERID
        server                  = /usr/sbin/in.rshd
}
# 没错！只要将 disable 改成 no  即可！

[root@linux ~]# /etc/init.d/xinetd restart

[root@linux ~]# netstat -tlnp | grep 514
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State  PID/Program name
tcp        0      0 0.0.0.0:514   0.0.0.0:*       LISTEN 23369/xinetd
# 有看到 514 的 port 出现就对了！
  • 设定可以使用 RSH 的来源主机与帐号： /etc/hosts, /etc/hosts.equiv, ~user/.rhosts
    • 假设我已经在 /etc/hosts 里面做好了我内部主机的 IP 与主机名称的对应了， 例如，我 192.168.1.2 机器的 /etc/hosts 里面是这样的：
    [root@linux ~]# vi /etc/hosts
127.0.0.1       localhost       localhost.localdomain
192.168.1.2     rsh.server      rshserver
192.168.1.100   rsh.client      rshclient
# 上面仅有两部主机，假设 RSH server 的 IP 是 192.168.1.2 啦！
    这个档案很重要，因为我们的 RSH 通常是利用主机名称来作为指令的下达的， 所以啰，您区域网路内的主机名称与 IP 必须要设定的能够对应的起来，否则问题就大了。 在上表当中，你会发现到，其实鸟哥的重点是那部 rsh.server 的机器， 当我想要让 192.168.1.100 亦即是 rsh.client 那部机器连进来 rsh.server 执行一些指令的话， 那我就得要启动权限才行！此时就得要 /etc/hosts.equiv 来处理了。这个档案的格式是这样的：
    [root@linux ~]# vi /etc/hosts.equiv
rsh.client dmtsai
# 这个档案的格式是 [hostname] [username]
# 将你要开放的使用者与某主机给他对应好写上去即可！
    这样就做好了设定了！未来任何想要登入这部 rsh.server 机器的主机，只要将他的主机名称与 IP 对应写入 /etc/hosts ，然后再将该主机名称写入 /etc/hosts.equiv ，就成功了！ 这个档案的设计只要是在规范‘可以不用输入密码就能够进入本机执行指令’的设定啦！ 但是请注意，‘在预设的情况下， root 是不允许使用 rsh 登入 rsh.server 机器的。’这个很重要！不要使用 root 一直测试啊！没有用的。 更多的 hosts.equiv 设定值，请参考 man hosts.equiv 啰！

    但你可能会发现一件事，那就是每部主机与使用者都需要配合的话，但 /etc/hosts.equiv 预设仅有 root 可修改， 如此一来实在不好管理！此时我们可以使用使用者家目录的档案来处理喔！那就是 ~/.rhosts 啰！ 这个档案的设定就更简单了！只要将使用者预计要登入的那部主机名称写入即可！
    [root@linux ~]# vi ~dmtsai/.rhosts
rsh.client
    这样就 OK 啦！意思是说，我这部 rsh.server 上有个 dmtsai 的使用者，他可以让 rsh.client 这个主机登入并且不需要密码即可进行 R Shell 的相关指令下达工作！ 同样的，如果我还想让其他使用者可以由不同的主机登入这部 rsh.server 进行 RSH 的话， 同样在他的家目录新增 .rhosts 这个档案即可！如果想要让未来新增的使用者都具有这个功能， 那就这样做：
    [root@linux ~]# vi /etc/skel/.rhosts
rsh.client
    未来新增使用者时，他们的家目录底下就会自动产生 .rhosts 的档案啰！ ^_^
  • 让 root 也可以使用 RSH ：
    • 先通知一声，鸟哥不建议您这样做！但是，如果万一您需要某些服务是 root 也需要的， 那或许就得要开放 root 使用 RSH 登入主机了。其实 root 不能使用 rsh 是因为 PAM 的问题而已，所以，你只要将 /etc/pam.d/rsh 这个档案注解掉一行即可：
    [root@linux ~]# vi /etc/pam.d/rsh
#%PAM-1.0
# For root login to succeed here with pam_securetty, "rsh" must be
# listed in /etc/securetty.
auth       required     pam_nologin.so
#auth       required    pam_securetty.so
auth       required     pam_env.so
auth       required     pam_rhosts_auth.so
account    required     pam_stack.so service=system-auth
session    required     pam_stack.so service=system-auth
    将上面这一行注解掉，立刻就能让 root 登入 rsh 主机啦！当然啦，如果您担心有问题， 那么修改另一个档案也可以：
    [root@linux ~]# vi /etc/securetty
.....(省略).....
rsh
    加入这一行也行！注意，上面这两个档案是具有相关性的，所以，您只要修改任何一个即可， 不必两个同时进行！然后将主机名称与 root 的对应写入 /etc/hosts.equiv 档案中即可！你的 root 就能够使用 rsh 啰！但是，鸟哥还是不很建议开放 root 使用 RSH 喔！注意注意！
    小标题的图示 RSH Client
    这个 RSH client 的指令 rsh 预设是不给 root 执行的！所以不要使用 root 来测试！ 另外， RSH Client 最好与 RSH server 具有相同的帐号来执行 rsh 比较不会有问题喔！

  • 测试 RSH ：
    • 接下来，当然要进行测试啰～请到 rsh.client 那部机器上面，使用 rsh 这个指令来下达指令吧！
    [dmtsai@rshclient ~]$ rsh [-l 远端帐号] [远端主机名] [远端主机指令]
参数：
-l   ：一般来说， server 与 client ‘要有相同的使用者帐号名称’比较好的！
       如果没有的话，那么您必须要指定 server 的使用者帐号名才行！
远端主机名  ：您要登入的那部 rsh.server 主机名称，记得与 /etc/hosts 相应！
远端主机指令：您要在远端机器上面下达什么指令？

范例一：在 rsh.server 上面下达 ls -l / 这个指令：
[dmtsai@rshclient ~]$ rsh rsh.server 'ls -l /'
.....输出省略.....
# 注意喔，我是使用 dmtsai 这个一般身份使用者，而且 rshserver rshclient
# 两部主机上面都有一个名为 dmtsai 的使用者帐号才行喔！至于那个 ls -l /
# 则是在 rsh.server 主机上面的指令！留意留意！
    一般来说，由于 RSH server/client 最好是要有相同的帐号，如此一来才能够避免很多不必要的权限问题( permission denied. )。所以说，通常 RSH 可能会搭配后续会继续谈到的 NIS/NFS 等伺服器才是！ 这样了呼？

    另外， rsh 后续的指令通常仅适合单一指令而已，所以如果你的指令串很长 (接了很多参数)， 那最好将那一整串指令用单引号括起来，可以避免指令下达错误的问题喔！ ^_^

  • 利用 rcp 复制：
    • 除了 rsh 可以在远端直接操控系统外，我们可以透过 rcp 来进行复制喔！其实这个 rcp 与 scp 几乎一模一样啦！ 而且 rcp 的参数几乎与 cp 一模一样哩！另外， rcp 也是透过 RSH 这个 514 的 port 来进行资料的传输的。 简单的说明如下：
    范例：先查阅远端主机有什么资料，然后将他复制过来：
[dmtsai@rshclient ~]# rsh rsh.server 'ls -l ~'
drwx------  3 dmtsai dmtsai     4096 Dec 27  2005 Desktop
-rw-r--r--  1 dmtsai dmtsai     3385 May 29 17:52 bashrc
drwx------  3 dmtsai dmtsai     4096 Mar  6  2006 mail
-rw-r--r--  1 dmtsai dmtsai   883888 May 29 17:51 netcdf.tar.gz
drwxr-xr-x  2 dmtsai dmtsai     4096 Jul 26 16:05 test
-rw-rw-r--  1 dmtsai dmtsai    34816 Mar 19  2006 testing.ppt

[dmtsai@rshclient ~]# rcp -r dmtsai@rsh.server:~/mail .
# 加上 -r 是为了要复制目录喔！否则的话，可以直接复制即可！
    再说一次，其实这个 RSH 目前仅有在某些特殊的场合才会用到了！ 例如未来流行的新资讯‘ Cluster ’！不过如果要玩 Cluster 的话， 得要加入 NIS/NFS 等伺服器哩！那就等您好好发展啦！ ^_^
    大标题的图示 以 rsync 进行同步镜相备份
    我们曾在基础篇里面谈过 Linux 的备份策略， 该篇曾介绍常用的备份指令，包括 tar, dd, cp 等等，不过当时并未介绍网路，所以有个很棒的网路工具没有介绍， 那就是这个地方要谈到的 rsync 啦！这个 rsync 可以作为一个相当棒的异地备援系统的备份指令喔！ 因为 rsync 可以达到类似‘镜相 (mirror) ’的功能呢！

    rsync 最早是想要取代 rcp 这个指令的，因为 rsync 不但传输的速度快，而且他在传输时， 可以比对本地端与远端主机欲复制的档案内容，而仅复制两端有差异的档案而已，所以传输的时间就相对的降低很多！ 此外， rsync 的传输方式至少可以透过三种方式来运作：
    • 在本机上直接运作，用法就与 cp 几乎一模一样，例如：
      rsync -av /etc /tmp (将 /etc/ 的资料备份到 /tmp/etc 内)

    • 透过 rsh 或 ssh 的通道在 server / client 之间进行资料传输，例如：
      rsync -av -e ssh user@rsh.server:/etc /tmp (将 rsh.server 的 /etc 备份到本地主机的 /tmp 内)

    • 直接透过 rsync 提供的服务 (daemon) 来传输，此时 rsync 主机需要启动 873 port：
      1. 你必须要在 server 端启动 rsync ， 看 /etc/xinetd.d/rsync 即可；
      2. 你必须编辑 /etc/rsyncd.conf 设定档；
      3. 你必须设定好 client 端连线的密码资料；
      4. 在 client 端可以利用：rsync -av user@hostname::/dir/path /local/path
    其实三种传输模式差异在于有没有冒号 (:) 而已，本地端传输不需要冒号，透过 ssh 或 rsh 时，就得要利用一个冒号 (:)， 如果是透过 rsync daemon 的话，就得要两个冒号 (::) ，应该不难理解啦！因为本地端处理很简单， 而我们的系统本来就有提供 ssh 的服务，所以，底下鸟哥将直接介绍利用 rsync 透过 ssh 来备份的动作喔。 不过，在此之前咱们先来看看 rsync 的语法吧！
    [root@linux ~]# rsync [-avrlptgoD] [-e ssh] [user@host:/dir] [/local/path]
参数：
-v ：观察模式，可以列出更多的资讯；
-q ：与 -v  相反，安静模式，输出的资讯比较少；
-r ：递回复制！可以针对‘目录’来处理！很重要！
-u ：仅更新 (update)，不会覆盖目标的新档案；
-l ：复制连结档的属性，而非连结的目标原始档案内容；
-p ：复制时，连同属性 (permission) 也保存不变！
-g ：保存原始档案的拥有群组；
-o ：保存原始档案的拥有人；
-D ：保存原始档案的装置属性 (device)
-t ：保存原始档案的时间参数；
-I ：忽略更新时间 (mtime) 的属性，档案比对上会比较快速；
-z ：加上压缩的参数！
-e ：使用的通道协定，例如使用 ssh 通道，则 -e ssh
-a ：相当于 -rlptgoD ，所以这个 -a 是最常用的参数了！
更多说明请参考 man rsync 的解说！

范例一：将 /etc 的资料备份到 /tmp 底下：
[root@linux ~]# rsync -av /etc /tmp
....前面输出省略....
sent 23007335 bytes  received 32280 bytes  5119914.44 bytes/sec
total size is 22870014  speedup is 0.99
# 第一次运作时会花比较久的时间，因为首次建立嘛！如果再次备份呢？

[root@linux ~]# rsync -av /etc /tmp
building file list ... done
sent 77105 bytes  received 20 bytes  154250.00 bytes/sec
total size is 22870014  speedup is 296.53
# 瞧！立刻就跑完了！传输的资料也很少！因为再次比对，仅有差异的档案会被复制。

范例二：利用 dmtsai 的身份，将 rsh.server 使用者家目录复制到 /tmp
[root@linux ~]# rsync -av -e ssh dmtsai@rsh.server:~ /tmp
The authenticity of host 'rsh.server (192.168.1.2)' can't be established.
RSA key fingerprint is 29:b8:a9:32:ea:d8:ff:97:6c:42:3b:aa:11:ab:55:dd.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added 'rsh.server' (RSA) to the list of known hosts.
dmtsai@rsh.server's password:
receiving file list ... done
....档案输出省略....
sent 8436 bytes  received 43224862 bytes  2789245.03 bytes/sec
total size is 43189031  speedup is 1.00

[root@linux ~]# ll -d /tmp/dmtsai
drwxr-xr-x  22 dmtsai dmtsai  4096 Sep 18 23:25 /tmp/dmtsai
# 瞧！这样就做好备份啦！很简单吧！
    你可以利用上面的范例二来做为备份 script 的参考！不过要注意的是， 因为 rsync 是透过 ssh 来传输资料的，所以你可以针对 dmtsai 这个家伙制作出免用密码登入的 ssh 金钥！ 如此一来往后异地备援系统就能够自动的以 crontab 来进行备份了！简单到爆！

    免密码的 ssh 帐号我们在上头已经讲过了，撰写 shell script 的能力也是必须要有的！ 利用 rsync 来进行你的备份工作吧！ ^_^！ 至于更多的 rsync 用法可以参考本章后面所列出的参考资料网站喔！

    大标题的图示 重点回顾：
    • 远端连线伺服器可以让使用者在任何一部电脑登入主机，以使用主机的资源或管理与维护主机；
    • 常见的远端登入服务有 rsh, telnet, ssh, vnc, 及 xdmcp 等；
    • telnet 与 rsh 都是以明码传输资料，当资料在 Internet 上面传输时较不安全；
    • telnet 与 rsh 预设无法让 root 的身份登入，不过可以藉由 pam 模组的修改而启用 root 登入功能；
    • ssh 由于使用金钥系统，因此资料在 Internet 上面传输时是加密过的，所以较为安全；
    • 但 ssh 还是属于比较危险的服务，请不要对整个 Internet 开放 ssh 的可登入权限，可利用 iptables 规范可登入范围；
    • ssh 的 public Key 是放在主机端，而 private key 是放在 client 端；
    • ssh 的连线机制有两种版本，建议使用可确认连线正确性的 version 2 ；
    • 使用 ssh 时，尽量使用类似 email 的方式来登入，亦即： ssh username@hostname
    • client 端可以比对 server 传来的 public key 的一致性，利用的档案为 ~user/.ssh/known_hosts；
    • ssh 的 client 端软体提供 ssh, scp, sftp 等程式；
    • 在 /etc/ssh/sshd_config 当中可以取消 root 的登入权限与修改支援的 ssh 金钥版本；
    • 制作不需要密码的 ssh 帐号可利用 ssh-keygen -t rsa 来制作 public, private Key pair；
    • 上述指令所制作出的 public key 必须要上传到 server 的 ~user/.ssh/authorized_keys 档案中；
    • 如果想以 X 图形系统登入 Linux 主机，则你必须要在 Client 主机启动 X server ， 需要在 Linux 主机启动 X client ；
    • Xdmcp 是透过 X display manager (xdm, gdm, kdm 等) 所提供的功能协定；
    • 若 client 端为 Linux 时，需要在 X 环境下以 xhost 增加可连接到本机 X Server 的 IP 才行；
    • 除了 Xdmcp 之外，我们可以利用 VNC 来进行 X 的远端登入架构；
    • VNC 预设开的 port number 为 5900 开始，每个 port 仅允许一个连线；
    • 控制 rsh client 是否可以连线进入的设定档在 /etc/hosts.equiv 或 ~username/.rhosts ；
    • rsh 支援的 client 端软体有 rsh, rlogin, rcp 等；
    • rsync 可透过 ssh 的服务通道或 rsync --daemon 的方式来连线传输，其主要功能可以透过类似镜像备份， 仅备份新的资料，因此传输备份速度相当快速！
    大标题的图示 课后练习
    • Telnet 与 SSH 都是远端连线伺服器，为何我们都会推荐使用 SSH 而避免使用 Telnet 呢？原因何在？
      • 因为 Telnet 除了使用‘明码’传送资料外，本身 telnet 就是很容易被入侵的一个伺服器，所以当然也就比较危险了。 至于 ssh 其实也不是很安全的！由台湾电脑危机处理小组的文件可以明显的发现 openssl + openssh 也是常常有漏洞在发布！不过，比起 telnet 来说，确实是稍微安全一些！
    • 请尝试说明 SSH 在 Server 与 Client 端连线时的封包加密机制；
      • 利用 key pair 来达到加密的机制：Server 提供 Public Key 给 Client 端演算 Private key ，以提供封包传送时的加密、解密！
    • 请问 SSH 的设定档是哪一个？如果我要修改让 root 无法使用 SSH 连线进入我的 SSH 主机，应该如何设定？又，如果要让 badbird 这个使用者无法登入 SSH 主机，该如何设定？
      • SSH 设定档档名为 sshd_config ，通常放置在 /etc/ssh/sshd_config 内；如果不想让 root 登入，可以修改 sshd_config 内的参数成为：‘PermitRootLogin no ’，并重新启动 ssh 来设定！如果要让 badbird 使用者无法登入，同样在 sshd_config 里面设定为：‘DenyUsers badbird’即可！
    • 在 Linux 上，预设的 Telnet 与 SSH 伺服器使用的埠口(port number)各为多少？
      • telnet 与 ssh 的埠口分别是：23 与 22！请参考 /etc/services 喔！
    • 如果发现我无法在 Client 端使用 ssh 程式登入我的 Linux 主机，但是 Linux 主机却一切正常，可能的原因为何？(防火墙、known_hosts...)
      • 无法登入的原因可能有很多，最好先查询一下 /var/log/messages 里面的错误讯息来判断，当然，还有其他可能的原因为：
      1. 被防火墙挡住了，请以 iptables -L -n 来察看，当然也要察看 /etc/hosts.deny；
      2. 可能由于主机重新开机过， public key 改变了，请修改您的 ~/ssh/known_hosts 里面的主机 IP ；
      3. 可能由于 /etc/ssh/sshd_config 里面的设定问题，导致您这个使用者无法使用；
      4. 在 /etc/passwd 里面，您的 user 不具有可以登入的 shell ；
      5. 其他因素(如帐号密码过期等等)
    • 既然 ssh 是比较安全的资料封包传送方式，那么我就可以在 Internet 上面开放我的 Linux 主机的 SSH 服务了吗？！请说明您选择的答案的原因！
      • 最好不要对 Internet 开放您的 SSH 服务，因为 SSH 的加密函式库使用的是 openssl ，一般 Linux distribution 使用的 SSH 则是 openssh ，这两个套件事实上仍有不少的漏洞被发布过，因此，最好不要对 Internet 开放，毕竟 SSH 对于主机的使用权限是很高的！
    • 如果我想要将 server 的重要资料备份到 backserver，如果可以使用 rsync 透过 ssh 的通道， 你可以请尝试这样做：
      1. 先在 server 上面以 root 建置 ssh 的 public 与 private key pair ；
      2. 将 public key 传送与设定到 backserver 上的某个使用者环境下；
      3. 在 backserver 上面制作好预计要存放备份资料的目录！重点在于‘权限’的设定上！
      4. 在 server 上面设定好 rsync 的备份 script ～
      5. 利用 crontab 每隔一段时间自动异地备份。
      请依照上述的作法在您的两部主机上面进行测试与实作。(未提供解答)
    大标题的图示 参考资源
    • OpenSSH 官方网站：http://www.openssh.com/
    • OpenSSL 官方网站：http://www.openssl.org/
    • putty 官方网站：http://www.chiark.greenend.org.uk/~sgtatham/putty/
    • pputty 中文网站：http://www.csie.ntu.edu.tw/~piaip/prjs/pputty/
    • man vncserver
    • man Xvnc
    • 使用 X 的 VNC Module：http://phorum.study-area.org/viewtopic.htm?t=25713
    • http://fedoranews.org/tchung/vnc/03.shtml
    • http://www.faqs.org/docs/Linux-HOWTO/XDMCP-HOWTO.html
    • man rsh
    • man rlogin
    • 酷学园：用 rsync 做备份：http://phorum.study-area.org/viewtopic.htm?t=15553
    • 卧龙小三的 rsync 介绍：http://linux.tnc.edu.tw/techdoc/rsync.htm
    • ADJ 实验室的 rsync + SSH：http://www.adj.idv.tw/server/linux_rsync.htm
    2002/11/14：第一次完成
    2003/03/08：加入标头说明，与修改部分内容，例如 Telnet 伺服器软体的安装等等，以及 SSH 的 putty 使用中文状态！
    2003/09/09：将本文进行一些修订，此外，加入了课后练习！
    2005/07/02：将旧的文章移动到 这里 。
    2005/07/07：好不容易将 VNC 还有 XDMCP 给他写了写～大家帮鸟哥参考看看啊～
    2005/07/09：加入了让 VNC 与 tty7 同步的 vnc.so 模组的说明
    2005/11/22：加入了 RSH 伺服器 的相关资料！
    2006/09/18：将 putty 的介绍转成 pietty 的介绍！因为 pietty 更好用！另外也将 rsh 重新改写一下，校稿过！
    2006/09/19：加入 rsync 的简易说明与操作！最文末的习题可以瞧一瞧！
    hint: 可以加入 RDP，那个 Windows 的远端桌面系统。
    2002/11/14以来统计人数


鸟哥的 Linux 私房菜 -- NFS 伺服器

为取得较佳浏览结果，请爱用 firefox 浏览本网页

NFS 伺服器
切换解析度为 800x600
最近更新日期：2009/07/04
NFS为 Network FileSystem 的简称，最早之前是由 Sun 这家公司所发展出来的，他的目的就是想让不同的机器、 不同的作业系统可以彼此分享个别的档案啦！目前在 Unix Like 当中用来做为 file server 是相当不错的一个方案喔！基本上， Unix Like 主机连接到另一部 Unix Like 主机来分享彼此的档案时，使用 NFS 要比 SAMBA 这个伺服器快速且方便的多了！此外， NFS 的设定真的很简单，几乎只要记得启动 Remote Procedure Call 这个咚咚 (RPC, 就是 portmap 这个套件啦！) 就一定可以架设的起来！真是不错啊！不过，如果要达成 Windows 与 Linux 之间的沟通，那么还是以 SAMBA 比较容易啊！无论如何， NFS 还是可以做为小公司或学校单位内部 Unix Like 机器共享 file 的一个 Server 喔！

1. 本章的行前准备工作
2. NFS 的由来与其功能
    2.1 什么是 NFS ( Network FileSystem )
    2.2 什么是 RPC ( Remote Procedure Call )
    2.3 NFS 启动的 RPC daemons
    2.4 NFS 的档案存取权限
 3. NFS Server 端的设定
    3.1 所需要的套件
    3.2 NFS 的套件结构
    3.3 /etc/exports 设定档的语法与参数
    3.4 启动 NFS： rpcinfo
    3.5 NFS 的连线观察： showmount, /var/lib/nfs/etab, exportfs
    3.6 NFS 的安全性
 4. NFS 用户端的设定
    4.1 远端 NFS 伺服器的挂载
    4.2 用户端可处理的挂载参数与开机挂载
    4.3 无法挂载的原因分析
    4.4 自动挂载 autofs 的使用
 5. 案例演练
6. 重点回顾
7. 课后练习
8. 参考资料
9. 针对本文的建议：http://phorum.vbird.org/viewtopic.htm?p=114695
大标题的图示 本章的行前准备工作
NFS 这个藉由网路分享档案系统的服务在架设的时候是很简单的，不过，他最大的问题在于‘权限’方面的概念！ 因为在用户端与伺服器端可能必须要具备相同的帐号才能够存取某些目录或档案。 另外，NFS 的启动需要透过所谓的远端程序呼叫 (RPC)，也就是说，我们并不是只要启动 NFS 就好了， 还需要启动 RPC 这个服务才行啊！因此，你必须要拥有的基础知识有：
  • 必须要了解档案系统的权限概念，可以参考 基础篇的 Linux 档案属性与目录配置
  • 了解网路基础，防火墙与关闭 SELinux 模组等等。
大标题的图示 NFS 的由来与其功能
在开始进行 NFS 的设定之前，我们得先来了解一下，什么是 NFS 呢？不然讲了一堆也没有用，对吧！ ^_^！ 底下就来谈一谈什么是 NFS ，且 NFS 的启动还需要什么样的协定啊！

小标题的图示 什么是 NFS (Network FileSystem)
NFS 就是 Network FileSystem 的缩写，最早之前是由 Sun 这家公司所发展出来的。 他最大的功能就是可以透过网路，让不同的机器、不同的作业系统、可以彼此分享个别的档案 (share files)。所以，您也可以简单的将他看做是一个档案伺服器 (file server) 呢！这个 NFS 伺服器可以让您的 PC 来将网路远端的 NFS 主机分享的目录，挂载到本地端的机器当中， 在本地端的机器看起来，那个远端主机的目录就好像是自己的一个磁碟分割槽一样 (partition)！使用上面相当的便利！

NFS 主机分享目录与 Client 挂载示意图
图一、NFS 主机分享目录与 Client 挂载示意图

就如同上面的图示一般，当我们的 NFS Server 设定好了分享出来的 /home/sharefile 这个目录后，其他的 NFS Client 端就可以将这个目录挂载到自己系统上面的某个挂载点 (挂载点可以自订)，例如前面图示中的 NFS client 1 与 NFS client 2 挂载的目录就不相同。我只要在 NFS client 1 系统中进入 /home/data/sharefile 内，就可以看到 NFS Server 系统内的 /home/sharefile 目录下的所有资料了 (当然，权限要足够啊！^_^)！这个 /home/data/sharefile 就好像 NFS client 1 自己机器里面的一个 partition 喔！只要权限对了，那么您可以使用 cp, cd, mv, rm... 等等磁碟或档案相关的指令！真是他X的方便呐！

好的，既然 NFS 是透过网路来进行资料的传输，那么经由 socket pair 的概念你会知道 NFS 应该会使用一些 port 吧？那么 NFS 使用哪个 port来进行传输呢？答案是....不知道！ @_@ ！ 因为 NFS 用来传输的 port 是随机选择小于 1024 以下的埠口来使用的。 咦！那用户端怎么知道你伺服器端使用那个 port 啊？此时就得要 远端程序呼叫 (Remote Procedure Call, RPC) 的协定来辅助啦！底下我们就来谈谈什么是 RPC？

小标题的图示 什么是 RPC (Remote Procedure Call)
因为 NFS 支援的功能相当的多，而不同的功能都会使用不同的程式来启动， 每启动一个功能就会启用一些 port 来传输资料，因此， NFS 的功能所对应的 port 才没有固定住， 而是采用随机取用一些未被使用的小于 1024 的埠口来作为传输之用。但如此一来又造成用户端想要连上伺服器时的困扰， 因为用户端得要知道伺服器端的相关埠口才能够连线吧！

此时我们就得需要远端程序呼叫 (RPC) 的服务啦！RPC 最主要的功能就是在指定每个 NFS 功能所对应的 port number ，并且回报给用户端，让用户端可以连结到正确的埠口上去。 那 RPC 又是如何知道每个 NFS 的埠口呢？这是因为当伺服器在启动 NFS 时会随机取用数个埠口，并主动的向 RPC 注册，因此 RPC 可以知道每个埠口对应的 NFS 功能，然后 RPC 又是固定使用 port 111 来监听用户端的需求并回报用户端正确的埠口， 所以当然可以让 NFS 的启动更为轻松愉快了！
Tips:
所以你要注意，要启动 NFS 之前，RPC 就要先启动了，否则 NFS 会无法向 RPC 注册。 另外，RPC 若重新启动时，原本注册的资料会不见，因此 RPC 重新启动后，他管理的所有程式都需要重新启动以重新向 RPC 注册。 		鸟哥的图示
NFS 与 RPC 服务及档案系统操作的相关性
图二、NFS 与 RPC 服务及档案系统操作的相关性

如上图所示，当用户端有 NFS 档案存取需求时，他会如何向伺服器端要求资料呢？
  1. 用户端会向伺服器端的 RPC (port 111) 发出 NFS 档案存取功能的询问要求；
  2. 伺服器端找到对应的已注册的 NFS daemon 埠口后，会回报给用户端；
  3. 用户端了解正确的埠口后，就可以直接与 NFS daemon 来连线。
由于 NFS 的各项功能都必须要向 RPC 来注册，如此一来 RPC 才能了解 NFS 这个服务的各项功能之 port number, PID, NFS 在主机所监听的 IP 等等，而用户端才能够透过 RPC 的询问找到正确对应的埠口。 也就是说，NFS 必须要有 RPC 存在时才能成功的提供服务， 因此我们称 NFS 为 RPC server 的一种。事实上，有很多这样的伺服器都是向 RPC 注册的， 举例来说，NIS (Network Information Service) 也是 RPC server 的一种呢。 此外，由图二你也会知道，不论是用户端还是伺服器端，要使用 NFS 时，两者都需要启动 RPC 才行喔！

更多的 NFS 相关协定资讯你可以参考底下网页：
  • http://www.faqs.org/rfcs/rfc1094.html
  • http://www.tldp.org/HOWTO/NFS-HOWTO/index.html
小标题的图示 NFS 启动的 RPC daemons
我们现在知道 NFS 伺服器在启动的时候就得要向 RPC 注册，所以 NFS 伺服器也被称为 RPC server 之一。 那么 NFS 伺服器主要的任务是进行档案系统的分享，档案系统的分享则与权限有关。 所以 NFS 伺服器启动时至少需要两个 daemons ，一个管理 client 端是否能够登入的问题， 一个管理 client 端能够取得的权限。如果你还想要管理 quota 的话，那么 NFS 还得要再载入其他的 RPC 程式就是了。我们以较单纯的 NFS 主机来说：
  • rpc.nfsd：
    这个 daemon 主要的功能就是在管理 Client 是否能够登入主机的权限啦，其中还包含这个登入者的 ID 的判别喔！

  • rpc.mountd
    这个 daemon 主要的功能，则是在管理 NFS 的档案系统哩！当 Client 端顺利的通过 rpc.nfsd 而登入主机之后，在他可以使用 NFS 伺服器提供的档案之前，还会经过档案使用权限 (就是那个 -rwxrwxrwx 与 owner, group 那几个权限啦) 的认证程序！他会去读 NFS 的设定档 /etc/exports 来比对 Client 的权限，当通过这一关之后 Client 就可以取得使用 NFS 档案的权限啦！ (注：这个也是我们用来管理 NFS 分享之目录的使用权限与安全设定的地方哩！)

  • rpc.lockd (非必要)
    这个玩意儿可以用在管理档案的锁定 (lock) 用途。为何档案需要‘锁定’呢？ 因为既然分享的 NFS 档案可以让用户端使用，那么当多个用户端同时尝试写入某个档案时， 就可能对于该档案造成一些问题啦！这个 rpc.lockd 则可以用来克服这个问题。 但 rpc.lockd 必须要同时在用户端与伺服器端都开启才行喔！此外， rpc.lockd 也常与 rpc.statd 同时启用。

  • rpc.statd (非必要)
    可以用来检查档案的一致性，与 rpc.lockd 有关！若发生因为用户端同时使用同一档案造成档案可能有所损毁时， rpc.statd 可以用来检测并尝试回复该档案。与 rpc.lockd 同样的，这个功能必须要在伺服器端与用户端都启动才会生效。
小标题的图示 NFS 的档案存取权限
不知道你有没有想过这个问题，在图一的环境下，假如我在 NFS client 1 上面以 dmtsai 这个使用者身份想要去存取 /home/data/sharefile/ 这个来自 NFS server 所提供的档案系统时， 请问 NFS server 所提供的档案系统会让我以什么身份去存取？是 dmtsai 还是？

为什么会这么问呢？这是因为 NFS 本身的服务并没有进行身份登入的识别， 所以说，当你在用户端以 dmtsai 的身份想要存取伺服器端的档案系统时， 伺服器端会以用户端的使用者 UID 与 GID 等身份来尝试读取伺服器端的档案系统。这时有个有趣的问题就产生啦！ 那就是如果用户端与伺服器端的使用者身份并不一致怎么办？

我们以底下这个图示来说明一下好了：

NFS 的伺服器端与用户端的使用者身份确认机制
图三、NFS 的伺服器端与用户端的使用者身份确认机制

当我以 dmtsai 这个一般身份使用者要去存取来自伺服器端的档案时，你要先注意到的是： 档案系统的 inode 所记录的属性为 UID, GID 而非帐号与群组名。 那一般 Linux 主机会主动的以自己的 /etc/passwd, /etc/group 来查询对应的使用者、群组名称。 所以当 dmtsai 进入到该目录后，会参照 NFS client 1 的使用者与群组名称。 但是由于该目录的档案主要来自 NFS server ，所以可能就会发现几个情况：
  • NFS server/NFS client 刚好有相同的帐号与群组
    则此时使用者可以直接以 dmtsai 的身份进行伺服器所提供的档案系统之存取。

  • NFS server 的 501 这个 UID 帐号对应为 vbird
    若 NFS 伺服器上的 /etc/passwd 里面 UID 501 的使用者名称为 vbird 时， 则用户端的 dmtsai 可以存取伺服器端的 vbird 这个使用者的档案喔！只因为两者具有相同的 UID 而已。这就造成很大的问题了！因为没有人可以保证用户端的 UID 所对应的帐号会与伺服器端相同， 那伺服器所提供的资料不就可能会被错误的使用者乱改？

  • NFS server 并没有 501 这个 UID
    另一个极端的情况是，在伺服器端并没有 501 这个 UID 的存在，则此时 dmtsai 的身份在该目录下会被压缩成匿名者， 一般 NFS 的匿名者会以 UID 为 65534 为其使用者，早期的 Linux distributions 这个 65534 的帐号名称通常是 nobody ，我们的 CentOS 则取名为 nfsnobody 。

  • 如果使用者身份是 root 时
    有个比较特殊的使用者，那就是每个 Linux 主机都有的 UID 为 0 的 root 。 想一想，如果用户端可以用 root 的身份去存取伺服器端的档案系统时，那伺服器端的资料哪有什么保护性？ 所以在预设的情况下， root 的身份会被主动的压缩成为匿名者。
总之，用户端使用者能做的事情是与 UID 及其 GID 有关的，那当用户端与伺服器端的 UID 及帐号的对应不一致时， 可能就会造成档案系统使用上的困扰，这个就是 NFS 档案系统在使用上面的一个很重要的地方！ 而在了解使用者帐号与 UID 及档案系统的关系之后，要实际在用户端以 NFS 取用伺服器端的档案系统时， 你还得需要具有：
  • NFS 伺服器有开放可写入的权限 (与 /etc/exports 设定有关)；
  • 实际的档案权限具有可写入 (w) 的权限。
当你满足了 (1)使用者帐号，亦即 UID 的相关身份； (2)NFS 伺服器允许有写入的权限； (3)档案系统确实具有 w 的权限时，你才具有该档案的可写入权限喔！ 尤其是身份 (UID) 确认的环节部分，最容易搞错啦！也因为如此， 所以 NFS 通常需要与 NIS 这一个可以确认用户端与伺服器端身份一致的服务搭配使用，以避免身份的错乱啊！ ^_^
大标题的图示 NFS Server 端的设定
既然要使用 NFS 的话，就得要安装 NFS 所需要的套件了！底下让我们查询一下系统有无安装所需要的套件， NFS 套件的架构以及如何设定 NFS 主机吧！ ^_^

小标题的图示 所需要的套件
以 CentOS 4.x 为例的话，要设定好 NFS 伺服器我们必须要有两个套件才行，分别是：
  • NFS 主程式：nfs-utils
  • RPC 主程式：portmap
  • portmap
    就如同刚刚提的到，我们的 NFS 其实可以被视为一个 RPC 程式，而要启动任何一个 RPC 程式之前，我们都需要做好 port 的对应 (mapping) 的工作才行，这个工作其实就是‘ portmap ’这个服务所负责的！也就是说， 在启动任何一个 RPC server 之前，我们都需要启动 portmap 才行！

  • nfs-utils
    就是提供 rpc.nfsd 及 rpc.mountd 这两个 NFS daemons 与其他相关 documents 与说明文件、执行档等的套件！这个就是 NFS 的主要套件啦！一定要有喔！

    好了，知道我们需要这两个套件之后，现在干嘛？赶快去您的系统先用 RPM 看一下有没有这两个套件啦！ 没有的话赶快用 RPM 或 yum 去安装喔！不然就玩不下去了！

    例题：
    请问我的主机是以 RPM 为套件管理的 Linux distribution ，例如 Red Hat, CentOS 与 SuSE 等版本，那么我要如何知道我的主机里面是否已经安装了 portmap 与 nfs 相关的套件呢？
    答：
      简单的使用 rpm -qa | grep nfs 与 rpm -qa | grep portmap 即可知道啦！如果没有安装的话， 在 CentOS 内可以使用‘ yum install nfs-utils ’来安装！

    • 小标题的图示 NFS 的套件结构
    NFS 这个咚咚真的是很简单，上面我们提到的 NFS 套件中，设定档只有一个，执行档也不多， 记录档也三三两两而已呐！赶紧先来看一看吧！ ^_^
    • /etc/exports
      这个档案就是 NFS 的主要设定档了！不过，系统并没有预设值，所以这个档案‘ 不一定会存在’，您可能必须要使用 vi 主动的建立起这个档案喔！我们等一下要谈的设定也仅只是这个档案而已呐！

    • /usr/sbin/exportfs
      这个是维护 NFS 分享资源的指令，我们可以利用这个指令重新分享 /etc/exports 变更的目录资源、将 NFS Server 分享的目录卸载或重新分享等等，这个指令是 NFS 系统里面相当重要的一个喔！至于指令的用法我们在底下会再介绍。

    • /usr/sbin/showmount
      这是另一个重要的 NFS 指令。exportfs 是用在 NFS Server 端，而 showmount 则主要用在 Client 端。这个 showmount 可以用来察看 NFS 分享出来的目录资源喔！

    • /var/lib/nfs/*tab
      在 NFS 伺服器的登录档都放置到 /var/lib/nfs/ 目录里面，在该目录下有两个比较重要的登录档， 一个是 etab ，主要记录了 NFS 所分享出来的目录的完整权限设定值；另一个 xtab 则记录曾经连结到此 NFS 主机的相关用户端资料。
    就说不难吧！主要就是这几个啰！

    小标题的图示 /etc/exports 设定档的语法与参数
    在开始 NFS 伺服器的设定之前，您必须要了解的是，NFS 会直接使用到核心功能，所以你的核心必须要有支援 NFS 才行。 万一如果你的核心版本小于 2.2 版，或者重新自行编译过核心的话，那么就得要很注意啦！ 因为你可能会忘记选择 NFS 的核心支援啊！

    还好，我们 CentOS 或者是其他版本的 Linux ，预设核心通常是支援 NFS 功能的， 所以你只要确认你的核心版本是目前新的 2.6.x 版，并且使用你的 distribution 所提供的核心， 那应该就不会有问题啦！

    至于 NFS 伺服器的架设实在很简单，你只要编辑好主要设定档 /etc/exports 之后， 先启动 portmap ，然后再启动 nfs ，你的 NFS 就成功了！ 不过这样的设定能否对用户端生效？那就得要考虑你权限方面的设定能力了。 废话少说，我们就直接来看看那个 /etc/exports 应该如何设定吧！ 某些 distributions 并不会主动提供 /etc/exports 档案，所以请您自行手动建立他吧。
    [root@linux ~]# vi /etc/exports
/tmp         192.168.1.0/24(ro)   localhost(rw)   *.ev.ncku.edu.tw(ro,sync)
# [分享目录] [第一部主机(权限)]   [可用主机名]    [可用万用字元]
    您看看，这个设定档有够简单吧！每一行最前面是要分享出来的目录，注意喔！是以目录为单位啊！ 然后这个目录可以依照不同的权限分享给不同的主机，像鸟哥上面的例子说明是： 要将 /tmp 分别分享给三个不同的主机或网域的意思。记得主机后面以小括号 () 设计权限参数， 若权限参数不止一个时，则以逗号 (,) 分开。且主机名与小括号是连在一起的喔！ 在这个档案内也可以利用 # 来注解呢。

    至于主机名称的设定主要有几个方式：
    • 可以使用完整的 IP 或者是网域，例如 192.168.1.10 或 192.168.1.0/24 ，或 192.168.1.0/255.255.255.0 都可以接受！

    • 可以使用主机名称，这个主机名称要在 /etc/hosts 内或使用 DNS 可以被找到才行啊！重点是可找到 IP 就是了。如果是主机名称的话，那么他可以支援万用字元，例如 * 或 ? 均可接受。
    至于权限方面 (就是小括号内的参数) 常见的参数则有：
    • rw：read-write，可读写的权限；

    • ro：read-only，唯读的权限；

    • sync：资料同步写入到记忆体与硬碟当中；

    • async：资料会先暂存于记忆体当中，而非直接写入硬碟！

    • no_root_squash：
      登入 NFS 主机使用分享目录的使用者，如果是 root 的话，那么对于这个分享的目录来说，他就具有 root 的权限！ 这个项目‘极不安全’，不建议使用！

    • root_squash：
      在登入 NFS 主机使用分享之目录的使用者如果是 root 时，那么这个使用者的权限将被压缩成为匿名使用者，通常他的 UID 与 GID 都会变成 nobody(nfsnobody) 那个系统帐号的身份；

    • all_squash：
      不论登入 NFS 的使用者身份为何， 他的身份都会被压缩成为匿名使用者，通常也就是 nobody(nfsnobody) 啦！

    • anonuid：
      anon 意指 anonymous (匿名者) 前面关于 *_squash 提到的匿名使用者的 UID 设定值，通常为 nobody(nfsnobody)，但是您可以自行设定这个 UID 的值！当然，这个 UID 必需要存在于您的 /etc/passwd 当中！

    • anongid：同 anonuid ，但是变成 group ID 就是了！
    这是几个比较常见的权限参数，如果你有兴趣玩其他的参数时，请自行 man exports 可以发现很多有趣的资料。 接下来我们利用上述的几个参数来实际思考一下几个有趣的小习题：

  • 思考一：让 root 保有 root 的权限
    我想将 /tmp 分享出去给大家使用，由于这个目录本来就是大家都可以读写的，因此想让所有的人都可以存取。 此外，我要让 root 写入的档案还是具有 root 的权限，那如何设计设定档？
    [root@linux ~]# vi /etc/exports
# 任何人都可以用我的 /tmp ，用万用字元来处理主机名称，重点在 no_root_squash
/tmp  *(rw,no_root_squash)
    参考前面的主机名称设定说明，我们可以利用万用字元的。这表示无论来自哪里都可以使用我的 /tmp 这个目录。 再次提醒，‘ *(rw,no_root_squash) ’这一串设定值中间是没有空白字元的喔！而 /tmp 与 *(rw,no_root_squash) 则是有空白字元来隔开的！特别注意到那个 no_root_squash 的功能！在这个例子中，如果你是用户端，而且您是以 root 的身份登入您的 Linux 主机，那么当您 mount 上我这部主机的 /tmp 之后，您在该 mount 的目录当中，将具有‘root 的权限！’

  • 思考二：同一目录针对不同范围开放不同权限
    我要将一个公共的目录 /home/public 公开出去，但是只有限定我的区域网路内 192.168.0.0/24 这个网域可以读写，其他人则只能读取：
    [root@linux ~]# vi /etc/exports
/tmp          *(rw,no_root_squash)
/home/public  192.168.0.0/24(rw)    *(ro)
# 继续累加在后面，注意，我有将主机与网域分为两段 (用空白隔开) 喔！
    上面的例子说的是，当我的 IP 是在 192.168.0.0/24 这个网段的时候，那么当我在 Client 端挂载了 Server 端的 /home/public 后，针对这个被我挂载的目录我就具有可以读写的权限～ 至于如果我不是在这个网段之内，那么这个目录的资料我就仅能读取而已，亦即为唯读的属性啦！

    需要注意的是，之前鸟哥将主机名称的万用字元与 IP 网段搞错了！ 万用字元仅能用在主机名称的分辨上面，IP 或网段就只能用 192.168.0.0/24 的状况， 不可以使用 192.168.0.* 喔！

  • 思考三：仅给某个单一主机使用的目录设定
    我要将一个私人的目录 /home/test 开放给 192.168.0.100 这个 Client 端的机器来使用，那么我就必需这么写：
    [root@linux ~]# vi /etc/exports
/tmp          *(rw,no_root_squash)
/home/public  192.168.0.0/24(rw)    *(ro)
/home/test    192.168.0.100(rw)
# 只要设定 IP 正确即可！
    这样就设定完成了！而且，只有 192.168.0.100 这部机器才能对 /home/test 这个目录进行存取喔！

  • 思考四：开放匿名登入的情况
    我要让 *.linux.org 网域的主机，登入我的 NFS 主机时，可以存取 /home/linux ，但是他们存资料的时候，我希望他们的 UID 与 GID 都变成 40 这个身份的使用者， 假设我 NFS 伺服器上的 UID 40 已经有设定妥当：
    [root@linux ~]# vi /etc/exports
/tmp          *(rw,no_root_squash)
/home/public  192.168.0.0/24(rw)    *(ro)
/home/test    192.168.0.100(rw)
/home/linux   *.linux.org(rw,all_squash,anonuid=40,anongid=40)
# 如果要开放匿名，那么重点是 all_squash，并且要配合 anonuid 喔！
    特别注意到那个 all_squash 与 anonuid, anongid 的功能！如此一来，当 test.linux.org 登入这部 NFS 主机，并且在 /home/linux 写入档案时，该档案的所有人与所有群组，就会变成 /etc/passwd 里面对应的 UID 为 40 的那个身份的使用者了！

    上面四个案例的权限如果依照前一小节的存取设定权限来思考的话， 那么权限会是什么情况呢？让我们来检查一下：

  • 用户端与主机端具有相同的 UID 与帐号：
    假设我在 192.168.0.100 登入这部 NFS (IP 假设为 192.168.0.2) 主机，并且我在 192.168.0.100 的帐号为 dmtsai 这个身份，同时，在这部 NFS 上面也有 dmtsai 这个帐号， 并具有相同的 UID ，果真如此的话，那么：
    1. 由于 192.168.0.2 这部 NFS 主机的 /tmp 权限为 -rwxrwxrwt ，所以我 (dmtsai 在 192.168.0.100 上面) 在 /tmp 底下具有存取的权限，并且写入的档案所有人为 dmtsai ；
    2. 在 /home/public 当中，由于我有读写的权限，所以如果在 /home/public 这个目录的权限对于 dmtsai 有开放写入的话，那么我就可以读写，并且我写入的档案所有人是 dmtsai 。但是万一 /home/public 对于 dmtsai 这个使用者并没有开放可以写入的权限时， 那么我还是没有办法写入档案喔！这点请特别留意！
    3. 在 /home/test 当中，我的权限与 /home/public 相同的状态！还需要 NFS 主机的 /home/test 对于 dmtsai 有开放权限；
    4. 在 /home/linux 当中就比较麻烦！因为不论您是何种 user ，您的身份一定会被变成 UID=40 这个帐号！所以，这个目录就必需要针对 UID = 40 的那个帐号名称，修改他的权限才行！
  • 用户端与主机端的帐号并未相同时：
    假如我在 192.168.0.100 的身份为 vbird ，但是 192.168.0.2 这部 NFS 主机却没有 vbird 这个帐号时，情况会变成怎样呢？
    1. 我在 /tmp 底下还是可以写入，但是写入的档案所有人变成 nobody 了；
    2. 我在 /home/public 里面是否可以写入，还需要视 /home/public 的权限而定，不过，反正我的身份就被变成 nobody 了就是；
    3. /home/test 的观点与 /home/public 相同！
    4. /home/linux 底下，我的身份就被变成 UID = 40 那个使用者就是了！
  • 当用户端的身份为 root 时：
    假如我在 192.168.0.100 的身份为 root 呢？ root 这个帐号每个系统都会有呀！权限变成怎样呢？
    1. 我在 /tmp 里面可以写入，并且由于 no_root_squash 的参数，改变了预设的 root_squash 设定值，所以在 /tmp 写入的档案所有人为 root 喔！
    2. 我在 /home/public 底下的身份还是被压缩成为 nobody 了！因为预设属性里面都具有 root_squash 呢！所以，如果 /home/public 有针对 nobody 开放写入权限时，那么我就可以写入，但是档案所有人变成 nobody 就是了！
    3. /home/test 与 /home/public 相同；
    4. /home/linux 的情况中，我 root 的身份也被压缩成为 UID = 40 的那个使用者了！
    这样的权限讲解之后，您可以了解了吗？这里是最重要的地方，如果这一关通过了，底下的咚咚就没有问题啦！ ^_^！ 当然啦，您还是得要回到前一小节NFS 的档案存取权限好好的瞧一瞧， 才能解决 NFS 的问题喔！
    • 小标题的图示 启动 NFS
    设定档搞定后，当然要开始来启动才行啊！而前面我们也提到过，NFS 的启动还需要 portmap 的协助才行啊！ 所以赶紧来启动吧！
    [root@linux ~]# /etc/init.d/portmap start
# 如果 portmap 本来就已经在执行了，那就不需要启动啊！

[root@linux ~]# /etc/init.d/nfs start
# 有时候可能会出现如下的警告讯息：
exportfs: /etc/exports [3]: No 'sync' or 'async' option specified
for export "192.168.0.100:/home/test".
  Assuming default behaviour ('sync').
# 上面的警告讯息仅是在告知因为我们没有指定 sync 或 async 的参数，
# 则 NFS 将预设会使用 sync 的资讯而已。你可以不理他，也可以加入 /etc/exports。

[root@linux ~]# vi /etc/exports
/tmp          *(rw,no_root_squash,sync)
/home/public  192.168.0.0/24(rw,sync)    *(ro,sync)
/home/test    192.168.0.100(rw,sync)
/home/linux   *.linux.org(rw,all_squash,anonuid=40,anongid=40,sync)

[root@linux ~]# /etc/init.d/nfs restart
    那个 portmap 根本就不需要设定！只要直接启动他就可以啦！启动之后，会出现一个 port 111 的 sunrpc 的服务，那就是 portmap 啦！至于 nfs 则会启动至少两个以上的 daemon 出现！然后就开始在监听 Client 端的需求啦！你必须要很注意荧幕上面的输出资讯， 因为如果设定档写错的话，荧幕上会显示出错误的地方喔！

    此外，如果你想要增加一些 NFS 伺服器的资料一致性功能时，可能需要用到 rpc.lockd 及 rpc.statd 等 RPC 服务， 那么或许你可以增加一个服务，那就是 nfslock
    [root@linux ~]# /etc/init.d/nfslock start
    启动之后，请赶快到 /var/log/messages 里面看看有没有被正确的启动呢？
    [root@linux ~]# vi /var/log/messages
Sep 22 00:01:37 linux nfs: Starting NFS services:  succeeded
Sep 22 00:01:37 linux nfs: rpc.rquotad startup succeeded
Sep 22 00:01:37 linux nfsd[1050]: nfssvc_versbits: +2 +3 +4
Sep 22 00:01:37 linux nfs: rpc.nfsd startup succeeded
Sep 22 00:01:37 linux nfs: rpc.mountd startup succeeded
Sep 22 00:01:37 linux rpcidmapd: rpc.idmapd -SIGHUP succeeded
    在确认没有问题之后，接下来我们来瞧一瞧那么 NFS 到底开了哪些埠口？
    [root@linux ~]# netstat -ultn
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address  Foreign Address State   PID/Program name
tcp        0      0 0.0.0.0:2049   0.0.0.0:*       LISTEN  -
tcp        0      0 0.0.0.0:803    0.0.0.0:*       LISTEN  1047/rpc.rquotad
tcp        0      0 0.0.0.0:111    0.0.0.0:*       LISTEN  32503/portmap
tcp        0      0 0.0.0.0:819    0.0.0.0:*       LISTEN  1064/rpc.mountd
udp        0      0 0.0.0.0:2049   0.0.0.0:*               -
udp        0      0 0.0.0.0:800    0.0.0.0:*               1047/rpc.rquotad
udp        0      0 0.0.0.0:816    0.0.0.0:*               1064/rpc.mountd
udp        0      0 0.0.0.0:111    0.0.0.0:*               32503/portmap
    注意看到上面喔！总共产生了好多的 port 喔！真是可怕！不过主要的埠口是：
    • portmap 启动的 port 在 111；
    • NFS 启动的 port 在 2049；
    • 其他 rpc.daemons 启动的 port 则是随机产生的，因此需向 port 111 注册。
    好了，那我怎么知道每个 RPC 服务的注册状况？没关系，你可以使用 rpcinfo 来处理的。
    [root@linux ~]# rpcinfo [-p] [IP|hostname]
参数：
-p ：显示出所有的 port 与 porgram 的资讯；

范例一：显示出目前这部主机的 RPC 状态
[root@linux ~]# rpcinfo -p localhost
   program vers proto   port
    100000    2   tcp    111  portmapper
    100000    2   udp    111  portmapper
    100011    1   udp    800  rquotad
    100011    2   udp    800  rquotad
    100011    1   tcp    803  rquotad
    100011    2   tcp    803  rquotad
    100003    2   udp   2049  nfs
    100003    3   udp   2049  nfs
    100003    2   tcp   2049  nfs
    100003    3   tcp   2049  nfs
    100005    1   udp    816  mountd
    100005    1   tcp    819  mountd
    100005    2   udp    816  mountd
    100005    2   tcp    819  mountd
    100005    3   udp    816  mountd
    100005    3   tcp    819  mountd
#         NFS版本       埠口  服务名称
    仔细瞧瞧，上面出现的资讯当中除了程式名称与埠口的对应可以与 netstat -tlunp 输出的结果作比对之外，还需要注意到 NFS 的版本支援！新的 NFS 版本传输速度较快， 由上表看起来，我们的 NFS 至少支援到第 3 版，应该还算合理啦！ ^_^！ 如果你的 rpcinfo 无法输出，那就表示注册的资料有问题啦！可能需要重新启动 portmap 与 nfs 喔！

    小标题的图示 NFS 的连线观察
    在你的 NFS 伺服器设定妥当之后，我们可以先自我测试一下是否可以连线喔！ 就是利用 showmount 这个指令来查阅！
    [root@linux ~]# showmount [-ae] [hostname|IP]
参数：
-a ：显示目前主机与用户端的 NFS 连线分享的状态；
-e ：显示某部主机的 /etc/exports 所分享的目录资料。

范例一：请显示出刚刚我们所设定好的相关 exports 资讯
[root@linux ~]# showmount -e localhost
Export list for localhost:
/tmp         *
/home/linux  *.linux.org
/home/public (everyone)
/home/test   192.168.0.100
    很简单吧！所以，当您要扫瞄某一部主机他提供的 NFS 分享的目录时，就使用 showmount -e IP (或hostname) 即可！非常的方便吧！这也是 NFS client 端最常用的指令喔！

    事实上 NFS 关于目录权限设定的资料非常之多！我们可以检查一下 /var/lib/nfs/etab 就知道了！
    [root@linux ~]# tail /var/lib/nfs/etab
/home/public    *(ro,sync,wdelay,hide,nocrossmnt,secure,root_squash,no_all_squash,
subtree_check,secure_locks,mapping=identity,anonuid=-2,anongid=-2)
# 上面是同一行，可以看出除了 ro, sync, root_squash 等等，
# 其实还有 anonuid 及 anongid 等等的设定！

/tmp    *(rw,sync,wdelay,hide,nocrossmnt,secure,no_root_squash,no_all_squash,subtr
ee_check,secure_locks,mapping=identity,anonuid=-2,anongid=-2)
# 同样的，在 /tmp 也有很多的权限相关的参数喔！
    上面仅仅是一个小范例，只是....怎么 anonuid 会是 -2 啊？ 其实那个数值是 65536-2 啦！所以得到 65534 ，比对 /etc/passwd ， 会发现 CentOS 出现的是 nfsnobody 啦！这个帐号在不同的版本都可能会不一样的！ 另外，如果有其他用户端挂载了你的 NFS 档案系统时， 那么该用户端与档案系统资讯就会被记录到 /var/lib/nfs/xtab 里头去的！

    另外，如果你想要重新处理 /etc/exports 档案，当重新设定完 /etc/exports 后需不需要重新启动 nfs ？ 不需要啦！如果重新启动 nfs 的话，要得要向 RPC 注册！很麻烦～ 这个时候我们可以透过 exportfs 这个指令来帮忙喔！
    [root@linux ~]# exportfs [-aruv]
参数：
-a ：全部挂载(或卸载) /etc/exports 档案内的设定
-r ：重新挂载 /etc/exports 里面的设定，此外，亦同步更新 /etc/exports
     及 /var/lib/nfs/xtab 的内容！
-u ：卸载某一目录
-v ：在 export 的时候，将分享的目录显示到荧幕上！

范例一：重新挂载一次 /etc/exports 的设定
[root@linux ~]# exportfs -arv
exporting 192.168.0.100:/home/test
exporting 192.168.0.0/24:/home/public
exporting *.linux.org:/home/linux
exporting *:/home/public
exporting *:/tmp

范例二：全部都卸载
[root@linux ~]# exportfs -auv
    要熟悉一下这个指令的用法喔！这样一来，就可以直接重新 exportfs 我们的记录在 /etc/exports 的目录资料啰！

    小标题的图示 NFS 的安全性
    在 NFS 的安全性上面，有些地方是你必须要知道的喔！底下我们分别来谈一谈：

  • 利用 iptables 做大范围连线的限制：
    假设我们的 NFS 主要是针对内部网路开放而已，而对于外部网路只有对成大的学术网路开放，亦即是 140.116.0.0/16 ，那么你可以在鸟哥于防火墙与 NAT 那个章节提供的 iptables.allow 内增加如下的语法：
    [root@linux ~]# vi /usr/local/virus/iptables/iptables.allow
iptables -A INPUT -i $EXTIF -p TCP -s 192.168.0.0/24 --dport 111 -j ACCEPT
iptables -A INPUT -i $EXTIF -p UDP -s 192.168.0.0/24 --dport 111 -j ACCEPT
iptables -A INPUT -i $EXTIF -p TCP -s 140.116.0.0/16 --dport 111 -j ACCEPT
iptables -A INPUT -i $EXTIF -p UDP -s 140.116.0.0/16 --dport 111 -j ACCEPT
    这样大致上就可以让 192.168.0.0/24 这个 C Class 的网域与 140.116.0.0/16 这个 B Class 的网域到您的主机里面来，而其他的连线就视您的原本的 iptables 的状态而定喔！

    那为什么是限制 port 111 而不是每个 RPC server 所开启的埠口呢？ 因为 RPC server 所开启的埠口都是随机产生的，要对他开放实在是... 而且用户端想要连上 NFS 伺服器之前，都是透过 port 111 来向 NFS 伺服器询问连线的埠口的， 所以当然先就 port 111 来进行限制啰！^_^

  • 利用 TCP Wrappers 限制
    但是不同的 RPC 毕竟提供的服务不一样，如果你想要针对某些服务来抵挡的话， 那可以透过 TCP Wrappers 这个根据 program name 来抵挡网路封包的咚咚啰！ 还记得我们刚刚使用过 rpcinfo 这个指令吧？ 不是会输出很多的 RPC program name 吗？没错！你可以这样做：
    [root@linux ~]# vi /etc/hosts.allow
# 让来自 140.116.44.0/255.255.255.0 的主机可以使用 mountd
mountd: 140.116.44.0/255.255.255.0

[root@linux ~]# vi /etc/hosts.deny
# 让所有人都不能使用 mountd
mountd: ALL
    为什么使用的是 mountd 呢？去到前一小节的 rpcinfo 指令处瞧一瞧， 你就会知道为何需要使用到 mountd 啰！^_^

  • 使用 /etc/exports 设定更安全的权限
    这就牵涉到您的逻辑思考了！怎么设定都没有关系，但是在‘便利’与‘安全’之间，要找到您的平衡点呐！善用 root_squash 及 all_squash 等功能，再利用 anonuid 等等的设定来规范登入您主机的使用者身份！应该还是有办法提供一个较为安全的 NFS 主机的！

    另外，当然啦，你的 NFS 伺服器的档案系统之权限设定也需要很留意！ 不要随便设定成为 -rwxrwxrwx ，这样会造成你的系统‘很大的困扰’的啊！

  • 更安全的 partition 规划：
    如果您的工作环境中，具有多部的 Linux 主机，并且预计彼此分享出目录时，那么在安装 Linux 的时候，最好就可以规划出一块 partition 作为预留之用。因为‘ NFS 可以针对目录来分享’，因此，您可以将预留的 partition 挂载在任何一个挂载点，再将该挂载点 (就是目录啦！)由 /etc/exports 的设定中分享出去，那么整个工作环境中的其他 Linux 主机就可以使用该 NFS 主机的那块预留的 partition 了！所以，在主机的规划上面，主要需要留意的只有 partition 而已。此外，由于分享的 partition 可能较容易被入侵，最好可以针对该 partition 设定比较严格的参数在 /etc/fstab 当中喔！

  • NFS 伺服器关机前的注意事项：
    需要注意的是，由于 NFS 使用的这个 RPC 在 client 端连上伺服器时，那么您的伺服器想要关机， 那可就会成为‘不可能的任务’！如果您的 Server 上面还有 Client 在连线，那么您要关机， 可能得要等到数个钟头才能够正常的关机成功！嗄！真的假的！不相信吗？不然您自个儿试试看！^_^！

    所以啰，建议您的 NFS Server 想要关机之前，能先‘关掉 portmap 与 nfs ’这两个东西！ 如果无法正确的将这两个 daemons 关掉，那么先以 netstat -utlp 找出 PID ，然后以 kill 将他关掉先！这样才有办法正常的关机成功喔！这个请特别特别的注意呢！

    当然啦，你也可以利用 showmount -a localhost 来查出来那个用户端还在连线？ 或者是查阅 /var/lib/nfs/rmtab 或 xtab 等档案来检查亦可。找到这些用户端后， 可以直接 call 他们啊！让他们能够帮帮忙先！ ^_^

    事实上，用户端以 NFS 连线到伺服器端时，如果他们可以下达一些比较不那么‘硬’的挂载参数时， 就能够减少这方面的问题喔！相关的安全性可以参考下一小节的 用户端可处理的挂载参数与开机挂载。
    • 大标题的图示 NFS 用户端的设定
    既然 NFS 伺服器最主要的工作就是分享档案系统给网路上其他的用户端，所以用户端当然得要挂载这个玩意儿啰！ 此外，主机端可以加设防火墙来保护自己的档案系统，那么用户端挂载该档案系统后，难道不需要保护自己？ 呵呵！所以底下我们要来谈一谈几个 NFS 用户端的课题。

    小标题的图示 远端 NFS 伺服器的挂载
    你要如何挂载 NFS 伺服器所提供的档案系统呢？基本上，可以这样做：
    1. 确认本地端已经启动了 portmap 服务！
    2. 扫瞄 NFS 伺服器分享的目录有哪些，并了解我们是否可以使用 (showmount)；
    3. 在本地端建立预计要挂载的挂载点目录 (mkdir)；
    4. 利用 mount 将远端主机直接挂载到相关目录。
    好，现在假设用户端在 192.168.0.100 这部机器上，而伺服器是 192.168.0.2 ， 那么赶紧来检查一下我们是否已经有 portmap 的启动，另外远端主机有什么可用的目录呢！
    [root@linux ~]# /etc/init.d/portmap start
[root@linux ~]# /etc/init.d/nfslock start
# 一般来说，系统预设会启动 portmap ，不过鸟哥之前关闭过，所以要启动。
# 另外，如果伺服器端有启动 nfslock 的话，用户端也要启动才能生效！

[root@linux ~]# showmount -e 192.168.0.2
Export list for 192.168.0.2:
/tmp         *
/home/linux  *.linux.org
/home/public (everyone)   <==这是等一下我们要挂载的目录
/home/test   192.168.0.100
    接下来我想要将远端主机的 /home/public 挂载到本地端主机的 /home/nfs/public ， 所以我就得要在本地端主机先建立起这个挂载点目录才行啊！然后就可以用 mount 这个指令直接挂载 NFS 的档案系统啰！
    [root@linux ~]# mkdir -p /home/nfs/public

[root@linux ~]# mount -t nfs 192.168.0.2:/home/public /home/nfs/public
# 注意一下挂载的语法！‘ -t nfs ’指定档案系统类型，
# IP:/dir 则是指定某一部主机的某个提供的目录！

[root@linux ~]# df
Filesystem    1K-blocks      Used Available Use% Mounted on
....中间省略....
192.168.0.2:/home/public
               10080512   2135072   7433344  23% /home/nfs/public
    先注意一下挂载 NFS 档案的格式范例喔！呵呵！这样就可以将资料挂载进来啦！请注意喔！ 以后，只要您进入您的目录 /home/nfs/public 就等于到了 192.168.0.2 那部远端主机的 /home/public 那个目录中啰！很不错吧！至于你在该目录下有什么权限？ 那就请您回去前一小节查一查权限的思考吧！ ^_^ ！那么如何将挂载的 NFS 目录卸载呢？就使用 umount 啊！
    [root@linux ~]# umount /home/nfs/public
    小标题的图示 用户端可处理的挂载参数与开机挂载
    瞧！用户端的挂载工作很简单吧！不过不晓得你有没有想过，如果你刚刚挂载到本机 /home/nfs/public 的档案系统当中，含有一支 script ，且这支 script 的内容为‘ rm -rf / ’且该档案权限为 555 ， 夭寿～如果你因为好奇给他执行下去，可有的你受的了～因为整个系统都会被杀光光！真可怜！

    所以说，除了 NFS 伺服器需要保护之外，我们取用人家的 NFS 档案系统也需要自我保护才行啊！ 那要如何自我保护啊？可以透过 mount 的指令参数喔！包括底下这些主要的参数可以尝试加入：

    参数 | 参数代表意义 | 系统预设值
suid nosuid | 晓得啥是 SUID 吧？如果挂载的 partition 上面有任何 SUID 的 binary 程式时， 你只要使用 nosuid 就能够取消 SUID 的功能了！嗄？不知道什么是 SUID ？那就不要学人家架站嘛！@_@！ 赶紧回去基础学习篇复习一下程序与资源管理啦！ | suid
rw ro | 你可以指定该 partition 是唯读 (ro) 或可读写喔！ | rw
dev nodev | 是否可以保留装置档案的特殊功能？一般来说只有 /dev 才会有特殊的装置，因此你可以选择 nodev 喔！ | dev
exec noexec | 是否具有执行 binary file 的权限？ 如果你想要挂载的仅是资料区 (例如 /home)，那么可以选择 noexec 啊！ | exec
user nouser | 是否允许使用者进行档案的挂载与卸载功能？ 如果要保护档案系统，最好不要提供使用者进行挂载与卸载吧！ | nouser
auto noauto | 这个 auto 指的是‘mount -a’时，会不会被挂载的项目。 如果你不需要这个 partition 随时被挂载，可以设定为 noauto。 | auto

    一般来说，如果你的 NFS 伺服器所提供的只是类似 /home 底下的个人资料， 应该不需要可执行、SUID 与装置档案，因此当你在挂载的时候，可以这样下达指令喔：
    [root@linux ~]# mount -t nfs -o nosuid,noexec,nodev,rw \
> 192.168.0.2:/home/public /home/nfs/public

[root@linux ~]# mount
192.168.0.2:/home/public on /home/nfs/public type nfs
(rw,noexec,nosuid,nodev,addr=192.168.0.2)
    这样一来你所挂载的这个档案系统就只能作为资料存取之用，相对来说，对于用户端是比较安全一些的。 所以说，这个 nosuid, noexec, nodev 等等的参数可得记得啊！

  • 关于 NFS 特殊的挂载参数
    除了上述的 mount 参数之外，其实针对 NFS 伺服器，咱们的 Linux 还提供不少有用的额外参数喔！ 因为 NFS 使用的是 RPC 服务，这个 RPC 必须要用户端与伺服器端两者都有启动 RPC 才能运作。 在一般的模式底下，你想要在用户端挂载伺服器端的 NFS 档案系统时，一次指令只能挂载一次， 如果该次挂载由于某些问题 (例如伺服器未开机、RPC忘记开等等) 导致无法顺利挂载时， 你只能等到连线逾时 (time out) 后，才能够继续工作。

    另外，当建立连线后，RPC 会不断的在用户端与伺服器两者之间进行呼叫， 此时如果有一部主机失去连线，那么 RPC 将会持续不断的呼叫，直到伺服器或用户端恢复连线为止。 此一行为将导致 RPC 服务出现延迟问题， 结果常常就造成你在执行 df 或者是 mount 等指令时，出现‘等等等等’的情况～ 这....真是要命！

    为了避免这些困扰，我们还有一些额外的 NFS 挂载参数可用！例如：

    参数 | 参数功能 | 预设参数
    fg
    bg     		当执行挂载时，该挂载的行为会在前景 (fg) 还是在背景 (bg) 执行？ 若在前景执行时，则 mount 会持续尝试挂载，直到成功或 time out 为止，若为背景执行， 则 mount 会在背景持续多次进行 mount ，而不会影响到前景的程序操作。 如果你的网路连线有点不稳定，或是伺服器常常需要开关机，那建议使用 bg 比较妥当。 fg
    soft
    hard     		上头不是谈到挂载时会使用 RPC 呼叫吗？ 如果是 hard 的情况，则当两者之间有任何一部主机离线，则 RPC 会持续的呼叫，直到对方恢复连线为止。 如果是 soft 的话，那 RPC 会在 time out 后‘重复’呼叫，而非‘持续’呼叫， 因此系统的延迟会比较不这么明显。同上，如果你的伺服器可能开开关关，建议用 soft 喔！ hard
    intr | 当你使用上头提到的 hard 方式挂载时，若加上 intr 这个参数， 则当 RPC 持续呼叫中，该次的呼叫是可以被中断的 (interrupted)。 | 没有
    rsize
    wsize     		读出(rsize)与写入(wsize)的区块大小 (block size)。 这个设定值可以影响用户端与伺服器端传输资料的缓冲记忆容量。一般来说， 如果在区域网路内 (LAN) ，并且用户端与伺服器端都具有足够的记忆体，那这个值可以设定大一点， 比如说 32768 (bytes) 等，提升缓冲记忆区块将可提升 NFS 档案系统的传输能力！ 但要注意设定的值也不要太大，最好是达到网路能够传输的最大值为限。 rsize=1024
    wsize=1024

    更多的参数可以参考 man nfs 的输出资料喔！ 通常如果你的 NFS 是用在高速运作的环境当中的话，那么可以建议加上这些参数的说：
    [root@linux ~]# mount -t nfs -o nosuid,noexec,nodev,rw \
> bg,soft,rsize=32768,wsize=32768 \
> 192.168.0.2:/home/public /home/nfs/public
    则当你的 192.168.0.2 这部伺服器因为某些因素而离线时，你的 NFS 可以继续在背景当中重复的呼叫！ 直到 NFS 伺服器再度上线为止。这对于系统的持续操作还是有帮助的啦！ 当然啦，那个 rsize 与 wsize 的大小则需要依据你的实际网路环境而定喔！

  • 将 NFS 开机即挂载
    要将 NFS 在开机的时候就挂载，该如何是好？就修改 /etc/fstab 即可啊！ 这个应该不用多说吧！你应该要了解的！举例来说，像上述的挂载方式的话，你就得要这样做：
    [root@linux ~]# vi /etc/fstab
192.168.0.2:/home/public   /home/nfs/public   nfs   nosuid,noexec,nodev,rw,
bg,soft,rsize=32768,wsize=32768   0   0
# 注意！上面的设定是同一行喔！不要搞错啰！ ^_^
    • 小标题的图示 无法挂载的原因分析
    如果用户端就是无法挂载伺服器端所分享的目录时，到底是发生什么问题？你可以这样分析看看：
    1. 使用者或用户端身份权限不符：
      以上面的例子来说明，我的 /home/test 只能提供 192.168.0.0/24 这个网域，所以如果我在 192.168.0.2 这部伺服器中，以 localhost (127.0.0.1) 来挂载时，就会无法挂载上，这个权限概念没问题吧！ 那么您可以试试看：
      [root@linux ~]# mount -t nfs localhost:/home/test /home/nfs
mount: localhost:/home/test failed, reason given by server: Permission denied
      看到 Permission denied 了吧？没错啦～权限不符啦！如果确定您的 IP 没有错误，那么请通知伺服器端， 请管理员将你的 IP 加入 /etc/exports 这个档案中。

    2. 伺服器或用户端某些服务未启动：
      这个最容易被忘记了！就是忘记了启动 portmap 这个服务啦！如果您发现您的 mount 的讯息是这样：
      [root@linux ~]# mount -t nfs localhost:/home/test /home/nfs
mount: RPC: Port mapper failure - RPC: Unable to receive

[root@linux ~]# mount -t nfs localhost:/home/test /home/nfs
mount: RPC: Program not registered
      要嘛就是 portmap 忘记开，要嘛就是伺服器端的 nfs 忘记开！解决的方法就是去启动这两个咚咚啦！

    3. 被防火墙档掉了：
      这个也很容易忘记了！那就是重新设定一下您的防火墙，这包含了两部份，包括 iptables 与 TCP_Wrappers ！因为我们启动了 portmap ，这个东西有两个资料需要分享出来，一个是 port 111 需要提供出去，因此您的 iptables 规则当中，需要开放这个 port 喔！
    小标题的图示 自动挂载 autofs 的使用
    在传统的 NFS 档案系统的使用当中，如果用户端要使用伺服器端所提供的 NFS 档案系统时， 要嘛就是得在 /etc/fstab 当中设定开机时挂载，要嘛就得要手动利用 mount 来挂载。 此外，用户端得要预先手动的建立好挂载点目录，然后挂载上来。

    不过有个小问题，我们知道 NFS 伺服器与用户端的连线或许可能不会永远存在， 而 RPC 这个服务又挺讨厌的，如果挂载了 NFS 伺服器后，任何一方离线都可能造成另外一方老是在等待逾时～ 而且，挂载的 NFS 档案系统可能又不是常常被使用，但若不挂载的话，有时候要使用又得通知系统管理员， 这又很不方便....啊！好讨厌的感觉啊～@_@

    换个思考的角度：
    • 可不可以让用户端在有使用到 NFS 档案系统的需求时才挂载？
    • 并且不需要事先建立挂载点？
    • 另外，当 NFS 档案系统使用完毕后，可不可以让 NFS 自动卸载，以避免可能的 RPC 错误？
    呵呵！好主意！在现在的 Linux 环境下这是可以达成的理想！用的就是 autofs 这个服务啦！

    autofs 可以预先定义好用户端‘预计挂载来自伺服器端的上层目录’，以及其相关的对应 NFS 伺服器分享目录。 至于在该目录底下的对应目录则可以不需要额外设定。讲这样或许你有点模糊，让我们拿底下这个图示来看看：

    自动挂载的设定档内容
    图四、自动挂载的设定档内容

    如上图所示，我们的 autofs 主要设定档为 /etc/auto.master，这个档案的内容很简单， 如上所示，我只要定义出最上层目录 (/home/nfs) 即可，至于后续的档案则是该目录底下各次目录的对应。 在 /etc/auto.nfs (这个档案的档名可自订) 里面则可以定义出每个次目录所欲挂载的远端伺服器目录！ 然后：‘当我们在用户端要使用 /home/nfs/public 的资料时，此时 autofs 才会去 192.168.0.2 挂载 /home/public ！’且‘当隔了 5 分钟没有使用该目录下的资料后， 则 /home/nfs/public 将会主动的卸载’。

    很不错用的一个工具吧！那就让我们在用户端来玩一玩吧！

  • 建立主要设定档 /etc/auto.master
    这个主要设定档的内容很简单，只要有预设目录及‘资料对应档’即可。 那个资料对应档的档名是可以自行设定的，在鸟哥这个例子当中我使用 /etc/auto.nfs 来命名。
    [root@linux ~]# vi /etc/auto.master
/home/nfs  /etc/auto.nfs

[root@linux ~]# mkdir /home/nfs
# 注意！此时 /home/nfs 内并没有其他的目录存在喔！

  • 建立资料对应档内的挂载资讯
    刚刚我们所指定的 /etc/auto.nfs 是自行设定的，所以这个档案是不存在的。 那么这个档案的格式是如何呢？你可以这样看：
    [本地端目录]  [-挂载参数]  [伺服器所提供的目录]
参数：
[本地端目录] ：指的就是在 /etc/auto.master 内指定的目录之次目录
[-挂载参数]  ：就是前一小节提到的 rw,bg,soft 等等的参数啦！可有可无；
[伺服器所提供的目录] ：例如 192.168.0.2:/home/public 等

[root@linux ~]# vi /etc/auto.nfs
public  -rw,bg,soft,rsize=32768,wsize=32768 192.168.0.2:/home/public
testing -rw,bg,soft,rsize=32768,wsize=32768 192.168.0.2:/home/test
temp    -rw,bg,soft,rsize=32768,wsize=32768 192.168.0.2:/tmp
# 参数部分，只要最前面加个 - 符号即可！
    这样就可以建立对应了！要注意的是，那些 /home/nfs/public 是不需要事先建立的！ 咱们的 autofs 会事情况来处理喔！好了，接下来让我们看看如何实际运作吧！

  • 实际运作与观察
    设定档设定妥当后，当然就是要启动 autofs 啦！
    [root@linux ~]# /etc/init.d/autofs start
    假设你目前并没有挂载任何来自 192.168.0.2 这部 NFS 伺服器的目录，好了， 让我们实际来观察看看，如果我要进入 /home/nfs/public 时，档案系统会如何变化呢？
    [root@linux ~]# mount; df
# 你不会看到任何跟 192.168.0.2 这部主机有关的 NFS 挂载资讯喔！

[root@linux ~]# cd /home/nfs/public

[root@linux public]# mount; df
192.168.0.2:/home/public on /home/nfs/public type nfs (rw,bg,soft,
rsize=32768,wsize=32768,addr=140.116.44.179)
# 上面的输出是同一行！瞧！突然出现这个玩意儿！

Filesystem 1K-blocks     Used Available Use% Mounted on
192.168.0.2:/home/public
            10080488  2144288   7424136  23% /home/nfs/public
# 档案的挂载也出现没错！

[root@linux public]# pwd
/home/nfs/public
# 这个目录突然被生出来了！ ^_^
    呵呵！真是好啊！如此一来，如果真的有需要用到该目录时，系统才会去相对的伺服器上面挂载！ 若是一阵子没有使用，那么该目录就会被卸载呢！这样就减少了很多不必要的使用时机啦！ 还不错用吧！ ^_^
    • 大标题的图示 案例演练
    假设环境：
    1. 假设我的 Linux 主机为 192.168.0.100 这一部；
    2. 预计将 /tmp 以可读写，并且不限制使用者身份的方式分享给所有 192.168.0.0/24 这个网域中的所有 Linux 工作站；
    3. 预计开放 /home/nfs 这个目录，使用的属性为唯读，可提供除了网域内的工作站外，向外亦提供资料内容；
    4. 预计开放 /home/upload 做为 192.168.0.0/24 这个网域的资料上传目录，其中，这个 /home/upload 的使用者及所属群组为 nfs-upload 这个名字，他的 UID 与 GID 均为 210；
    5. 预计将 /home/andy 这个目录仅分享给 192.168.0.50 这部 Linux 主机，以提供该主机上面 andy 这个使用者来使用，也就是说， andy 在 192.168.0.50 及 192.168.0.100 均有帐号，且帐号均为 andy ，所以预计开放 /home/andy 给 andy 使用他的家目录啦！
    实地演练：

    好了，那么请您先不要看底下的答案，先自己动笔或者直接在自己的机器上面动手作作看，等到得到您要的答案之后， 再看底下的说明吧！
    1. 首先，就是要建立 /etc/exports 这个档案的内容啰，您可以这样写吧！
      [root@linux ~]# vi /etc/exports
/tmp         192.168.0.0/24(rw,no_root_squash)
/home/nfs    192.168.0.0/24(ro)  *(ro,all_squash)
/home/upload 192.168.0.0/24(rw,all_squash,anonuid=210,anongid=210)
/home/andy   192.168.0.50(rw)

    2. 再来，就是要建立每个对应的目录的实际 Linux 权限了！我们一个一个来看：
      1. /tmp
[root@linux ~]# ll -d /tmp
drwxrwxrwt  5 root root 20480 Sep 22 22:52 /tmp

2. /home/nfs
[root@linux ~]# mkdir -p /home/nfs
[root@linux ~]# chmod 755 -R /home/nfs
# 修改较为严格的档案权限将目录与档案设定成唯读！不能写入的状态，会更保险一点！

3. /home/upload
[root@linux ~]# groupadd -g 210 nfs-upload
[root@linux ~]# useradd -g 210 -u 210 -M nfs-upload
# 先建立对应的帐号与群组名称及 UID 喔！
[root@linux ~]# mkdir -p /home/upload
[root@linux ~]# chown -R nfs-upload:nfs-upload /home/upload
# 修改拥有者！如此，则使用者与目录的权限都设定妥当啰！

4. /home/andy
[root@linux ~]# ll -d /home/andy
drwx------    3 andy     andy         4096 Oct 28 13:37 andy
      这样子一来，权限的问题大概就可以解决啰！

    3. 启动 portmap 与 nfs 服务：
      [root@linux ~]# /etc/init.d/portmap start
[root@linux ~]# /etc/init.d/nfs start
[root@linux ~]# /etc/init.d/nfslock start

    4. 在 192.168.0.50 这部机器上面演练一下：
      1. 确认远端伺服器的可用目录：
[root@linux ~]# /etc/init.d/portmap start
[root@linux ~]# /etc/init.d/nfslock start
[root@linux ~]# showmount -e 192.168.0.100
Export list for 192.168.0.100:
/tmp         192.168.0.*
/home/nfs    (everyone)
/home/upload 192.168.0.*
/home/andy   192.168.0.50

2. 建立挂载点：
[root@linux ~]# mkdir -p /home/zzz/tmp
[root@linux ~]# mkdir -p /home/zzz/nfs
[root@linux ~]# mkdir -p /home/zzz/upload
[root@linux ~]# mkdir -p /home/zzz/andy

3. 实际挂载：
[root@linux ~]# mount -t nfs 192.168.0.100:/tmp         /home/zzz/tmp
[root@linux ~]# mount -t nfs 192.168.0.100:/home/nfs    /home/zzz/nfs
[root@linux ~]# mount -t nfs 192.168.0.100:/home/upload /home/zzz/upload
[root@linux ~]# mount -t nfs 192.168.0.100:/home/andy   /home/zzz/andy
    整个步骤大致上就是这样呐！加油喔！
    大标题的图示 重点回顾
    • Network FileSystem (NFS) 可以让主机之间透过网路分享彼此的档案与目录；
    • NFS 主要是透过 RPC 来进行 file share 的目的，所以 Server 与 Client 的 RPC 一定要启动才行！
    • NFS 主机可以控制连线的 Client 端的登入与权限；
    • NFS 的设定档就是 /etc/exports 这个档案；
    • NFS 的权限可以观察 /var/lib/nfs/etab，至于的重要登录档可以参考 /var/lib/nfs/xtab 这个档案，还包含相当多有用的资讯在其中！
    • NFS 伺服器与用户端的使用者帐号名称、UID 最好要一致，可以避免权限错乱：
    • NFS 伺服器预设对用户端的 root 进行权限压缩，通常压缩其成为 nfsnobody 或 nobody。
    • NFS 主机要关机之前，请务必先关闭 portmap 与 nfs server ，否则关机无法顺利成功；
    • NFS 主机在更动 /etc/exports 这个档案之后，可以透过 exportfs 这个指令来重新挂载分享的目录！
    • 可以使用 rpcinfo 来观察 RPC program 之间的关系！！！
    • NFS 主机在设定之初，就必须要考虑到 client 端登入的权限问题，很多时候无法写入或者无法进行分享，主要是 Linux 实体档案的权限设定问题所致！
    • NFS 的防火墙设定可以透过控制 RPC 的主要 port ，亦即是 111 这个 port 来管理！此外，亦可透过 TCP_Wrappers 来管理！
    • NFS 用户端只要成功 mount NFS 主机分享的目录之后，使用上面就好像自己的 partition 一般；
    • NFS 用户端可以透过使用 showmount, mount 与 umount 来使用 NFS 主机提供的分享的目录！
    • NFS 亦可以使用挂载参数，如 bg, soft, rsize, wsize, nosuid, noexec, nodev 等参数， 来达到保护自己档案系统的目标！
    • 自动挂载的 autofs 服务可以在用户端需要 NFS 伺服器提供的资源时才挂载。
    • 本章与 LPI 之间的关系：
      在 LPI 网站 http://www.lpi.org 里面提到的，关于 NFS 的考试题库的地方，只有在 LPI level 1 的 102 ，里面的 topic 113 Networking Services ，第四点当中，简易的 NFS 设定。强调的是‘应试者需了解 NFS 的设定、启动与关闭的关系’至于会考的档案与指令可能有这些：
      • /etc/exports
      • /etc/fstab
      • mount
      • umount
    大标题的图示 课后练习
    • NFS 的主要设定档为何？而在该档案内主要设定项目为何？
      • 主要的设定档为 /etc/exports 而至于其设定的内容项目在每一行当中则为：
      1. 分享的目录
      2. 针对此分享目录开放的主机或 IP或网域
      3. 针对这部主机所开放的权限参数！
    • 在 NFS 主要的设定档当中仅有少许的参数说明，至于预设的参数说明则没有在该档案当中出现， 请问，如果要查阅更详细的分享出来的档案的属性，要看那个档案？/li>
      /var/lib/nfs/etab
    • 如果已经启动了 nfs 这个伺服器，但是却又修改过主要设定档，请问可以使用那个指令来重新挂载分享出来的目录与 client 端权限的设定值？
      • 透过使用 exportfs ，可以加上 -a 或者是 -rv 这两个参数来重新挂载！如 exportfs -rv
    • 在 client 端如果要挂载 NFS 所提供分享的档案，可以使用那个指令？
      • 那自然就是 mount 啦！还有卸载是 umount 喔！
    • 在 NFS 主要设定档当中，可以透过那个参数来控制不让 client 端以 root 的身份使用您所分享出来的目录与档案？
      • 可以在 /etc/exports 当中的参数项目，设定‘ root_squash ’来控制压缩 root 的身份喔！
    • 我在 client 端挂载了 NFS Server 的某个目录在我的 /home/data 底下，当我执行其中某个程式时，却发现我的系统被破坏了？您认为可能的原因为何？ 该如何克服这样的问题，尤其是当我的 Client 端主机其实是多人共用的环境， 怕其他的使用者也同样发生类似的问题呢？！
      • 可能由于您挂载进来的 NFS Server 的 partition 当中具有 SUID 的档案属性，而您不小心使用了该执行档，因此就可能会发生系统被破坏的问题了！
      • 可以将挂载进来的 NFS 目录的 SUID 功能取消！例如：
        mount -t nfs -o nosuid,ro server:/directory /your/directory
    大标题的图示 参考资料
    • http://www.faqs.org/rfcs/rfc1094.html
      鸟哥这里的备份：http://linux.vbird.org0330nfs/0330nfs_rpc.html
    • http://www.tldp.org/HOWTO/NFS-HOWTO/index.html
    • man exports
    • man autofs
    2002/11/17：第一次完成
    2003/03/09：修改部分内容，并且新增 LPI 相关性与重点整理部分！
    2003/09/10：又重新修改版面，以及新增主机的规划等部分。
    2006/09/19：将旧的文章移动到 此处
    2006/09/22：加入了 autofs 等等的资料喔！
    2007/02/27：原本 rsize 定义为 8192，但最近看一些文献，应该改为 32768 比较妥当。
    2009/07/04：在最后的案例演练部分， IP 不可使用星号 (*) 的万用字元！感谢讨论区网友acer07的回报！
    2002/11/17以来统计人数


鸟哥的 Linux 私房菜 -- NIS 伺服器

为取得较佳浏览结果，请爱用 firefox 浏览本网页

NIS 伺服器
切换解析度为 800x600
最近更新日期：2006/10/11
有没有想过，如果我有十部 Linux 主机，这十部主机仅负责不同的功能，事实上， 所有的主机帐号与对应的密码都相同！那么我是将帐号与密码分别设定置在十部电脑上面， 还是可以透过一部主机做为帐号管理的功能，然后其他的主机只要当用户用登入时， 就必须要到管理帐号的主机上面确认其帐号与密码呢？哪一个比较方便而且灵活？ 当然是找一个帐号管理的主机比较方便的多啦！如果有使用者要修改密码，不必要去到十部主机修改密码啦！ 只要到主要管理主机去修改，其他的主机根本就不需要更动！哈哈！轻松又愉快呢！这个功能的达成有很多的方式， 在这里，我们介绍一个很简单的方式，那就是 Network Information Service 这个 NIS 伺服器的架设啦！

1. 本章的行前准备工作
2. NIS 的由来与功能
    2.1 NIS 的主要功能
    2.2 NIS 的运作流程
 3. NIS server 端的设定
    3.1 所需要的套件
    3.2 NIS 的套件结构
    3.3 一个实作案例
    3.4 NIS master 的设定与启动
    3.5 NIS slave 的设定与启动 (optional)
    3.6 防火墙设置
 4. NIS client 端的设定
    4.1 NIS client 所需套件与套件结构
    4.2 NIS client 的设定与启动
    4.3 NIS client 端的检验： yptest, ypwhich, ypcat
    4.4 使用者参数修改： yppasswd, ypchfn, ypchsh
 5. NIS 与 NFS 的设定与丛集电脑运用
6. 指令对应资料
7. 重点回顾
8. 课后练习
9. 参考资料
10.针对本文的建议：http://phorum.vbird.org/viewtopic.htm?p=115269
大标题的图示 本章的行前准备工作
NIS 最大的用途在于提供用户端的使用者相关参数查询，举例来说，使用者的帐号、密码、UID、家目录、shell 等等的，都可以透过 NIS 伺服器来查询的。但 NIS 所能提供的也就是这样了，他并没有办法提供使用者家目录的空间， 因此，一般在高效能运算电脑当中，如果想要让所有的机器都拥有相同的帐号密码， 通常使用 NIS 提供身份验证，配合 NFS 提供所需要的磁碟空间的呐！ 因此在这一章开始前，你最好知道：
  • 了解网路基础，防火墙与关闭 SELinux 模组等等。
  • 一定要认识 NFS 伺服器；
  • 需要了解 RPC 这个玩意儿；
  • 需要了解使用者帐号相关知识，可以参考基础篇的使用者帐号管理章节。
  • 建立 NIS 资料库会使用到 make/Makefile 功能，请参考基础篇原始码与 tarball章节。
大标题的图示 NIS 的由来与功能
在一个大型的网域当中，如果有多部 Linux 主机，万一要每部主机都需要设定相同的帐号与密码时，还真是啰唆。 此时，如果能够有一部主控伺服器 (master server) 来管理网域中所有主机的帐号， 当其他的主机有使用者登入的需求时，才到这部主控伺服器上面要求相关的帐号、密码等使用者资讯资料， 如此一来，如果想要增加、修改、删除使用者资料，只要到这部主控伺服器上面处理即可， 这样就能够降低重复设定使用者帐号的步骤了。

这样的功能有很多的伺服器软体可以达成，这里我们要介绍的则是 Network Information Services (NIS server) 这个伺服器软体喔！底下就先来谈一谈这个 NIS 的相关功能吧！

小标题的图示 NIS 的主要功能
通常我们都会建议，一部 Linux 主机的功能越简单越好，也就是说，一部 Linux 就专门进行一项服务。这样有许多的好处，这包含功能简单所以系统资源得以完整运用， 并且在发生入侵或者是系统产生状况的时候，也比较容易追查问题所在。因此，一个公司内部常常会有好几部 Linux 主机，有的专门负责 WWW 、有的专门负责 Mail 、有的专门负责 SAMBA 等等的服务。

不过，这样虽然有分散风险、容易追踪问题的好处，但是，由于是同一个公司内的多部主机，所以事实上所有的 Linux 主机的帐号与密码都是一样的！哇！那如果公司里面有 100 的人的话， 我们就需要针对这么多部的主机去设定帐号密码了！而且，如果未来还有新进员工的话， 那么光是设定密码就会使系统管理员抓狂了！

这个时候，让我们换一个角度来思考：如果我设计了一部专门管理帐号与密码的主机，而其他的 Linux 主机当有用户端要登入的时候，就必须要到这部管理密码的主机来查寻使用者的帐号与密码， 如此一来，我要管理所有的 Linux 主机的帐号与密码，只要到那部主要主机上面去进行设定即可！ 包括新进人员的设定，反正其他的 Linux 主机都是向他查寻的嘛！没错！真是好～这个就是 Network Information Service, NIS 主机的主要功能啦！

事实上，Network Information Service 最早应该是称为 Sun Yellow Pages (简称 yp)，也就是 Sun 这家公司出的一个名为 Yellow Pages 的伺服器软体，请注意， NIS 与 YP 是一模一样的咚咚喔！这个 Yellow Pages 名字取的真是好！怎么说呢？知道黄页 (Yellow Pages) 是什么吗？就是我们家里的电话簿啦！ 今天如果你要查寻一家厂商的电话号码，通常就是直接去查黄页上面的纪录来取得电话号码啊！而这个 NIS 也一样，当使用者要登入时， Linux 系统就会到 NIS 主机上面去找寻这个使用的帐号与密码资讯来加以比对， 以提供使用者登入之用的检验啊！很棒吧！ ^_^

那么 NIS 主机提供了哪些资讯呢？还记得帐号与密码放置在哪里吧？NIS 就是提供那些资料啦！ 主要有底下这些基本的资料提供给有登入需求的主机喔：

伺服器端档案名称 | 档案内容
/etc/passwd | 提供使用者帐号、UID、GID、家目录所在、Shell 等等
/etc/group | 提供群组资料以及 GID 的对应，还有该群组的加入人员
/etc/hosts | 主机名称与 IP 的对应，常用于 private IP 的主机名称对应
/etc/services | 每一种服务 (daemons) 所对应的埠口 (port number)
/etc/protocols | 基础的 TCP/IP 封包协定，如 TCP, UDP, ICMP 等
/etc/netgroup | 网路群组的定义与使用 (NIS 可能会需要)
/etc/rpc | 每种 RPC 伺服器所对应的程式号码
/var/yp/ypservers | NIS 伺服器所提供的资料库

至少可以提供上述这些功能，当然啦，你也可以自行定义哪些资料库需要，哪些资料库不需要！

小标题的图示 NIS 的运作流程
由于 NIS 伺服器主要是提供使用者登入的资讯给用户端主机来查询之用，所以， NIS 伺服器所提供的资料当然就需要用到传输与读写比较快速的 "资料库" 档案系统， 而不是传统的纯文字资料。为了要达到这个目的，所以 NIS 伺服器就必须要将前一小节提到的那些档案制作成为资料库档案， 然后使用网路通讯协定让用户端主机来查询啰。至于所使用的通讯协定与前一章的 NFS 相同，都使用远端程序呼叫 (RPC) 这个玩意儿喔！

此外，如果在一个很大型的网域里面，万一所有的 Linux 主机都向同一部 NIS 伺服器要求使用者资料时， 这部 NIS 伺服器的负载 (loading) 可能会过大。甚至如果考虑到资料使用的风险， 要是这单一的一部 NIS 伺服器挂点时，那其他的 Linux 主机还要不要让 users 登入啊？ 所以啰，在较为大型的企业环境当中， NIS 伺服器可以使用 master/slave (主控/次要伺服器) 架构的。

Master NIS 伺服器提供系统管理者制作的资料库， slave 则取得来自 master 的资料，并藉以提供其他用户端的查询。 用户端可以向整个网域要求使用者资料的回应，master 与 slave 皆可回答， 由于 slave 的资料来自于 master ，所以使用者帐号资料本身是同步的！ 如此一方面可以分散 NIS 伺服器的负载， 而且也可以避免因 NIS 伺服器挂点而导致的无法登入的风险。

NIS 的运作流程
图一、NIS 的运作流程

整个 NIS 的运作就如同上图，首先必须要有 NIS server 的存在，之后才会有 NIS Client 的存在。 那么当使用者有登入的需求时，整个 NIS 的运作程序是：
  • 关于 NIS Server (master/slave) 的运作程序：
    1. NIS Master 先将本身的帐号密码相关档案制作成为资料库档案；
    2. NIS Master 可以主动的告知 NIS slave server 来更新；
    3. NIS slave 亦可主动的前往 NIS master server 取得更新后的资料库档案；
    4. 若有帐号密码的异动时，需要重新制作 database 与重新同步化 master/slave。

  • 关于当 NIS Client 有任何登入查询的需求时：
    1. NIS client 若有登入需求时，会先查询其本机的 /etc/passwd, /etc/shadow 等档案；
    2. 若在 NIS Client 本机找不到相关的帐号资料，才开始向整个 NIS 网域的主机广播查询；
    3. 每部 NIS server (不论 master/slave) 都可以回应，基本上是‘先回应者优先’。
从上面的流程当中，你会发现 NIS client 还是会先针对本机的帐号资料进行查询， 查不到才到 NIS server 上头寻找。因此，如果你的 NIS client 本身就有很多一般使用者的帐号时， 那跟 NIS server 所提供的帐号就可能产生一定程度的差异啰！ 所以，一般来说，在这样的环境下，NIS client 或 NIS slave server 会主动拿掉本机本身的一般使用者帐号，仅会保留系统所需要的 root 及系统所需帐号而已。 如此一来，一般使用者才都会经由 NIS master server 所控管啊！ ^_^

根据上面图一的说明，我们的 NIS 环境大致上需要设定的基本元件就有：
  • NIS Master server ：将档案建置成资料库，并提供 slave server 来更新；
  • NIS Slave server ：以 Master server 的资料库作为本身的资料库来源；
  • NIS client ：向 master/server 要求登入者的验证资料。
就让我们开始来玩一玩这个 NIS 的设定吧！
大标题的图示 NIS Server 端的设定
NIS 伺服器端主要在于提供资料库给用户端作为验证之用，并且伺服器端因为资料库的来源又可分为 master/slave 两大类。底下我们将会介绍这两种伺服器的安装方式哩！

小标题的图示 所需要的套件
由于 NIS 伺服器需要使用 RPC 协定，且 NIS 伺服器同时也可以当成用户端， 因此他需要的套件就有底下这几个：
  • yp-tools ：提供 NIS 相关的查寻指令功能
  • ypbind   ：提供 NIS Client 端的设定套件
  • ypserv   ：提供 NIS Server 端的设定套件
  • portmap  ：就是 RPC 一定需要的资料啊！
如果你是使用 Red Hat 的系统，例如我们的 CentOS 4.x 的话，那你可以利用‘ rpm -qa | grep '^yp' ’ 来检查是否有安装上述的套件。一般来说 yp-tools, ypbind 都会主动的安装，不过 ypserv 可能就不会安装了。 此时建议你直接使用‘ yum install ypserv ’来安装吧！立刻就装好了。底下立刻来设定啰！

小标题的图示 NIS 的套件结构
在 NIS 伺服器上最重要的就是 ypserv 这个套件了，而 ypserv 主要则是提供了底下这些重要资料：

设定档方面：
  • /etc/ypserv.conf：这是最主要的设定档， 可以规范 NIS 用户端是否可登入的权限。
  • /etc/hosts：非常重要！每一部主机都需要记录才行！！
  • /etc/netgroup：设定信任的主机与网域；
  • /var/yp/Makefile：与建立资料库有关的动作设定档；
  • /etc/sysconfig/network：可以在这个档案内指定 NIS 的网域 (nisdomainname)。
伺服器提供的主要服务方面：
  • /usr/sbin/ypserv：就是 NIS 伺服器的主要提供服务；
  • /usr/sbin/rpc.ypxfrd：用来作为 master/slave 主机之间传输资料库的服务；
  • /usr/sbin/rpc.yppasswdd：提供额外的 NIS 用户端之使用者密码修改服务， 透过这个服务， NIS 用户端可以直接修改在 NIS 伺服器上的密码。相关的使用程式则是 yppasswd 指令；
与资料库有关的指令方面：
  • /usr/sbin/yppush：master 主机将资料库直接送至 slave 的指令；
  • /usr/lib/yp/ypinit：建立资料库的指令，非常常用；
  • /usr/lib/yp/ypxfr：传送资料库的指令，在该目录下尚有 ypxfr_1perday, ypxfr_1perhour, ypxfr_2perday 等等。
小标题的图示 一个实作案例
如果您有观察过图一的话，你会发现到我们的 NIS 需要设定 Master/Slave 及 client 等， 鸟哥这里提供一个案例，里头就包括这三个元件啦！不过如果你的网域是比较小的环境， 那底下提供的 NIS slave server 你可以略过不看！鸟哥在这里的假设是这样的：
  • NIS 的网域名称为 vbirdnis
  • 整个内部的信任网域为 192.168.1.0/24
  • NIS master server 的 IP 为 192.168.1.2 ，主机名称为 master.vbirdnis
  • NIS slave server 的 IP 为 192.168.1.10，主机名称为 slave.vbirdnis
  • NIS client 的 IP 为 192.168.1.100，主机名称为 client.vbirdnis
底下我们就一个一个来设定吧！

小标题的图示 NIS master 的设定与启动
NIS 的设定真是很简单，首先，你必须要在 NIS master 这部伺服器上面搞定你的帐号与密码相关资料， 这包括 /etc/passwd, /etc/shadow, /etc/hosts, /etc/group .... 等等，都得要先搞定才行！ 详细的帐号相关资料请参考基础篇的帐号管理章节。 等到搞定之后你就可以继续 NIS 伺服器的设定了：

  • 设定 NIS 的网域名称 (NIS domain name)
    • 因为所有的 NIS server/client 都需要设定 NIS 领域名称才行，所以就设定吧！设定的方式很简单， 直接以 nisdomainname 这个指令来下达即可。(其实 nisdomainname 与 ypdomainname 及 domainname 都是一模一样的指令啦！你只要记住一个指令名称即可。请自行 man domainname 吧！)
    [root@linux ~]# nisdomainname [NIS 领域名称]
参数：
若没有加上领域名称，则会显示出目前的 NIS 领域；

[root@linux ~]# nisdomainname vbirdnis
[root@linux ~]# nisdomainname
vbirdnis  <==瞧！已经设定了 NIS 领域名称啰！
    如果确定每次开机时都需要启动这个 NIS 领域名称的话，直接写到 /etc/rc.d/rc.local 去：
    [root@linux ~]# vi /etc/rc.d/rc.local
# 加入底下这一行：
/bin/nisdomainname vbirdnis
    若是想要在启动 NIS 时就自动设定好 NIS 领域的话，可以利用 /etc/sysconfig/network 这个档案，写成如下所示的模样：
    [root@linux ~]# vi /etc/sysconfig/network
# 加入底下这一行：
NISDOMAIN=vbirdnis
    如此一来，你的伺服器就会在开机时，或者是在启动 NIS 相关服务时，就能够自行设定好 NIS 领域啰！

  • 主要设定档 /etc/ypserv.conf
    • 这个设定档就是 NIS 伺服器最主要的设定档啦！内容其实很简单，你可以保留预设值即可。 不过，也可以作一些更动啦！
    [root@linux ~]# vi /etc/ypserv.conf
dns: no
# NIS 伺服器的使用时机绝大部分都是在区域网路内而已，所以不需要 DNS 系统，
# 只要 /etc/hosts 设定正确即可！！

files: 30
# 预设会有 30 个资料库被读入记忆体当中，因为我们的帐号档案其实不多，
# 30 个已经足够使用了！

slp: no
slp_timeout: 3600
# 这两个与 SLP 服务有关，因为我们仅使用单纯的 NIS ，所以不需要启动。

xfr_check_port: yes
# 这个与 master/slave 有关，将同步更新的资料库比对所使用的埠口，
# 放置于小于 1024 的埠口内。

# 底下则是设定限制用户端或 slave server 查询的权限，利用冒号隔成四部分，分别为：
# [主机名称/IP] : [NIS网域名称] : [可用资料库名称] : [安全限制]
# [主机名称/IP]   ：可以使用 network/netmask 如 192.168.1.0/255.255.255.0
# [NIS网域名称]   ：例如本案例中的 vbirdnis
# [可用资料库名称]：就是由 NIS 制作出来的资料库名称；
# [安全限制]      ：包括没有限制 (none)、仅能使用 <1024 (port) 及拒绝 (deny)
# 一般来说，你可以依照我们的网域来设定成为底下的模样：
127.0.0.0/255.255.255.0   : * : * : none
192.168.1.0/255.255.255.0 : * : * : none
*                         : * : * : deny
# 星号 (*) 代表任何资料都接受的意思。上面三行的意思是，开放 lo 内部介面、
# 开放内部 LAN 网域，且杜绝所有其他来源的 NIS 要求的意思。

# 万一上面这三行权限相关的设定无法让你的 NIS 顺利的生效时，
# 你可以先将上面三行注解，然后加入底下这一行：
*                         : * : * : none
# 这样应该就能够让 NIS 顺利的连线了。
  • 设定主机名称 (/etc/hosts) 与建立信任群组 (/etc/netgroup)
    • 在 /etc/ypserv.conf 的设定当中我们谈到 NIS 大部分是给区域网路内的主机使用的， 所以当然就不需要 DNS 的设定了。不过，由于 NIS 使用到很多的主机名称， 所以你一定要设定好 /etc/hosts 对应，否则会无法成功连线 NIS ！ 这个很重要，绝大部分的朋友无法达成 NIS server/client 的连线都是这里出问题而已。 依据本案例的设定值，你应该这样做：
    [root@linux ~]# vi /etc/hosts
192.168.1.2    master.vbirdnis
192.168.1.10   slave.vbirdnis
192.168.1.100  client.vbirdnis
    注意！如果你的主机名称与 NIS 的主机名称不一样，那么在这个档案当中还是需要将你的主机名称给他设定进来！ 否则在后面资料库的设定时，肯定会发生问题。当然啦，你也可以直接在 /etc/sysconfig/network 当中直接重新设定主机名称，然后重新开机，或者是利用 hostname 这个指令重新设定你的主机名称也可以。

    除了这个设定之外，有时候你可能需要设定 /etc/netgroup ，虽然比较新的 distributions 都可以略过这个档案的检查了，不过建议您还是可以了解一下的啦！这个 /etc/netgroup 档案可以记录在我们网域里面被信任的群，这个档案的内容当中，每一行都有三个栏位，分别以逗号‘,’隔开，意义为：
    <host>,<user>,<domain>
主机,使用者帐号,领域名称
    事实上，如果这个档案是‘空的’的话，那么代表着‘全部的主机、帐号与领域名称都接受’的意思，因为我们已经在 /etc/ypserv.conf 里头设定好了关于安全的项目了，所以这个档案只要建立即可(本来是不存在的！)：
    [root@linux ~]# touch /etc/netgroup
  • 启动所有相关的服务
    • 接下来当然是先启动所有相关的服务啰，这包括 RPC, ypserv 以及 yppasswdd 啰！ 不过，如果你的 RPC 本来就已经启动的话，那就不要重新启动 portmap 了！
    [root@linux ~]# /etc/init.d/portmap start
[root@linux ~]# /etc/init.d/ypserv start
[root@linux ~]# /etc/init.d/yppasswdd start
    注意，主要的 NIS 服务是 ypserv ，不过，如果要提供 NIS 用户端的密码修改功能的话， 最好还是得要启动 yppasswdd 这个服务才好。在启动完毕后，我们可以利用 rpcinfo 来检查看看：
    [root@linux ~]# rpcinfo -p localhost
   program vers proto   port
    100000    2   tcp    111  portmapper
    100000    2   udp    111  portmapper
    100004    2   udp    942  ypserv
    100004    1   udp    942  ypserv
    100004    2   tcp    945  ypserv
    100004    1   tcp    945  ypserv
    100009    1   udp    950  yppasswdd

[root@linux ~]# rpcinfo -u localhost ypserv
program 100004 version 1 ready and waiting
program 100004 version 2 ready and waiting
    要出现上述的画面才表示正确的启动了 ypserv 喔！若有需要开机立即启动 ypserv 的话，请使用 chkconfig 来处理吧！

  • 建立资料库
    • 在完成了上面的所有步骤后，接下来我们得要开始将主机上面的帐号档案转成资料库档案啦！ 转换的动作直接透过 /usr/lib/yp/ypinit 这个指令来处理即可！整个步骤是这样做的：
    [root@linux ~]# /usr/lib/yp/ypinit -m
At this point, we have to construct a list of the hosts which will run NIS
servers.  master.vbirdnis is in the list of NIS server hosts.  Please continue
to add the names for the other hosts, one per line.  When you are done with the
list, type a <control D>.
        next host to add:  master.vbirdnis  <==这个地方系统会主动捉到
        next host to add:                   <==按下 [ctrl]-d
The current list of NIS servers looks like this:

master.vbirdnis

Is this correct?  [y/n: y] y
We need a few minutes to build the databases...
Building /var/yp/vbirdnis/ypservers...
Running /var/yp/Makefile...
gmake[1]: Entering directory `/var/yp/vbirdnis'
Updating passwd.byname...
....中间省略....
gmake[1]: Leaving directory `/var/yp/vbirdnis'

master.vbirdnis has been set up as a NIS master server.

Now you can run ypinit -s master.vbirdnis on all slave server.
    要注意出现的资讯当中，在告知你可以直接输入 [ctrl]-d 以结束的那个地方， 你的主机名称会主动的被捉出来，注意！这个主机名称务必需要在 /etc/hosts 可以被找到 IP 的对应， 否则会出现问题。另外，万一在执行 ypinit -m 时，出现如下的错误，那肯定就是有些资料没有被建立了！
    gmake[1]: *** No rule to make target `/etc/aliases', needed by
`mail.aliases'.  Stop.
gmake[1]: Leaving directory `/var/yp/vbirdnis'
make: *** [target] Error 2
Error running Makefile.
Please try it by hand.

[root@linux ~]# touch /etc/aliases
# 解决方法很简单呐！缺少什么档案，就 touch 他就是了！
[root@linux ~]# /usr/lib/yp/ypinit -m
# 然后再重新执行一次即可！
    如果是如下的错误，那可能是因为：
    • 你的 ypserv 没有顺利启动，请利用 rpcinfo 检查看看；
    • 你的主机名称没有对应好，请检查 /etc/hosts
    gmake[1]: Entering directory `/var/yp/vbirdnis'
Updating passwd.byname...
failed to send 'clear' to local ypserv: RPC: Program not
registeredUpdating passwd.byuid...
failed to send 'clear' to local ypserv: RPC: Program not
registeredUpdating group.byname...
....
    建立了资料库后，你必需要通知 ypserv 与 yppasswdd 这两支服务，告知资料库已经被更改了， 所以你可以这样做：
    [root@linux ~]# /etc/init.d/ypserv restart
[root@linux ~]# /etc/init.d/yppasswdd restart
    要注意啊，如果你的使用者密码有变动过，那么你就得要重新制作资料库，重新启动 ypserv 及 yppasswdd 喔！ 注意注意啊！

  • 与 slave server 及资料库有关的一些设定 (optional)
    • 当我们执行了 ypinit -m 之后，所有的主机上面的帐号相关档案会被转成资料库档案， 这些资料库会被放置到 /var/yp/"nisdomainname" 当中，我们的 nisdomainname 是 vbirdnis ， 所以被建立的资料库通通被放置到 /var/yp/vbirdnis/ 目录中啰！您可以自行去检查看看。

    事实上，我们的 ypinit 其实是透过 /var/yp/Makefile 来进行资料库的建立的呢！ 所以，我们当然也就可以藉由该档案内的功能来处理某些特定档案的更新啰！ 举例来说，若你仅修改了一个使用者的帐号参数而已，所以仅有 /etc/passwd 有被变更过， 那么如何仅针对这个档案进行资料库的更新呢？你可以这样做：
    [root@linux ~]# cd /var/yp
[root@linux yp]# make passwd
Updating passwd.byname...
Updating passwd.byuid...
    这样做就能够更新了，只不过更新后的资料库会被放置到 /var/yp 当中，而不是 /var/yp/vbirdnis 当中， 或许你还得需要手动移动一下该档案就是了。

    再者，如果你有 slave 伺服器的话，总是需要进行 master/slave 的同步化吧？ 那如何告知我们的 master 伺服器将资料库提供给 slave 呢？这个时候就得要修改 /var/yp/Makefile 啰！ 您可以自行进入该档案内查阅一些资料，不过，基本上你只要改一个地方就好了：
    [root@linux ~]# vi /var/yp/Makefile
# 找到底下这一行：
NOPUSH=true
# 将他改成这样：
NOPUSH=false
    这个设定值可以将资料库给他‘推 (push)’到其他的 slave 伺服器上头！接下来，你必需要告知 master 要推出去的资料库是给哪部伺服器？所以，你还得要修改这里：
    [root@linux ~]# vi /var/yp/ypservers
master.vbirdnis
slave.vbirdnis
# 增加上头这一行！
    你可以将所有的 slave 伺服器都加到 /var/yp/ypservers 档案当中，只要记得该伺服器的 IP 必需要在 /etc/hosts 内可以找到对应才行喔！如果你要提供 master/slave 伺服器的资料库档案传输时， 那么还需要启动 ypxfrd 这个服务才行！这个服务可以让 slave 伺服器主动连结上 ypxfrd 来更新资料库， 可以免除系统管理原自己手动更新啦！启动方式太简单了吧！
    [root@linux ~]# /etc/init.d/ypxfrd start
    做到这里就 OK 啦！您的 NIS Master 伺服器已经搞定啰！接下来，您就可以准备处理 slave 伺服器，或是直接处理 NIS client 端啰！此外，如果您的 master 机器想要直接将某些特定的资料库直接传给 slave 主机的话， 那么可以使用 yppush 这个指令喔！例如下列范例：
    [root@linux ~]# yppush -h slave.vbirdnis passwd.*
    如果 master/slave 的资料库不符合的话，那么该 passwd.byname 及 passwd.byuid 就会同步更新了！ 很简单吧！ ^_^！也就是说，您得先要制作资料库，然后再利用 yppush 来处理资料库的同步啊！ 亦即是：
    1. 先以 useradd username 或 passwd username 等制作出 master 上面的实体用户；
    2. 再以 make 或者直接以 /usr/lib/yp/ypinit -m 来制作出最新的资料库；
    3. 利用 yppush 这个指令功能来进行资料库的传输。
    如此一来，您就不需要进行 slave 上面的其他资料库处理啦！方便又简单！
    小标题的图示 NIS slave 的设定与启动 (optional)
    参考图一的 NIS 运作流程当中，我们知道由于 NIS 伺服器预设还是会先搜寻自己的 /etc/passwd, /etc/shadow 等资讯，因此你最好先将 NIS slave 的帐号与密码资料作个简单的修订，让他保留在比较干净的帐号资料，例如仅有系统帐号 (UID 小于 500 内的系统帐号) 就是一个不错的环境。这样可以避免 UID 重复出现的问题 (在 /etc/passwd 及 NIS 的环境中都出现相同的 UID ，但其相关参数却并相同时，可能有困扰)。

    NIS slave 的设定要比 NIS master 简单多了，事实上，很多设定都一样！你甚至可以复制 NIS master 的很多设定档哩！在你处理完 NIS slave 伺服器的帐号密码相关档案后，接下来你可以这样设定喔：

  • 设定网域
    • 同样的， NIS slave 也需要设定相同的网域，设定方式可以参考前一小节的介绍，我们这里很快的介绍一遍：
    1. 直接建立领域名称
[root@linux ~]# nisdomainname vbirdnis

2. 开机立即启动此一领域名称
[root@linux ~]# vi /etc/rc.d/rc.local
# 加入底下这一行：
/bin/nisdomainname vbirdnis

3. 预设在启动 ypserv 时，设定 NIS 领域名
[root@linux ~]# vi /etc/sysconfig/network
# 加入底下这一行：
NISDOMAIN=vbirdnis
  • 主要设定档 /etc/ypserv.conf
    • 这个设定档也是很简单的啦！可以与前面的 NIS master 相同即可。在鸟哥的这个例子当中， 我是直接在该档案加入这三行而已喔！
    [root@linux ~]# vi /etc/ypserv.conf
127.0.0.0/255.255.255.0   : * : * : none
192.168.1.0/255.255.255.0 : * : * : none
*                         : * : * : deny
  • /etc/hosts 及 /etc/netgroup
    • 这两个档案不陌生吧？直接设定他吧！
    [root@linux ~]# touch /etc/netgroup
[root@linux ~]# vi /etc/hosts
192.168.1.2    master.vbirdnis
192.168.1.10   slave.vbirdnis
192.168.1.100  client.vbirdnis
  • 启动所有服务及建立资料库
    • 还记得吧？我们需要 portmap 与 ypserv 喔！至于 yppasswdd 这个功能主要是在修改主控伺服器 (master) 上面的帐号密码，而 slave 只是在取得 master 的资料库而已，本身并不具备修改资料库的能力的， 所以 slave 当然就不需要这个东西啦！所以你可以这样设定：
    [root@linux ~]# /etc/init.d/portmap start
[root@linux ~]# /etc/init.d/ypserv start
    那如何取得来自 master 伺服器的资料库档案呢？还是一样得要透过 /usr/lib/yp/ypinit 这支程式啦！ 只是他的指令下达会变成这样喔：
    [root@linux ~]# /usr/lib/yp/ypinit -s master.vbirdnis
参数：
-s ：后面接预计取得的 master 主机名称！
We will need a few minutes to copy the data from master.vbirdnis.
Transferring hosts.byname...
Trying ypxfrd ... not running

Transferring services.byname...
Trying ypxfrd ... not running
....中间省略....
    虽然使用上头的指令事实上会出现有错误的资讯，就是那个‘Trying ypxfrd ... not running’的资讯， 但事实上资料库的转移还是成功的！不相信的话，你可以使用底下这个指令来测试一下资料库是否正确：
    [root@linux ~]# ypcat -h localhost passwd.byname
    如果有正确的输出帐号/密码资料的话，呵呵！那就是 OK 的啦！如此一来，您的 NIS slave 就启动 OK 啦！ 不过，由于您的 master 伺服器可能随时都会有帐号/密码的改变，所以你其实是可以使用 ypxfrd 这个服务来帮助资料库在 master/slave 间转移的！如果你有在 master 伺服器启动 ypxfrd 的话， 那么你可以在 slave 的工作排程上这样处理的：
    [root@linux ~]# vi /etc/crontab
# 在最后加入以 ypxfr 传输资料的 script 喔！
20    * * * * root /usr/lib/yp/ypxfr_1perhour
40    6 * * * root /usr/lib/yp/ypxfr_2perday
55 6,18 * * * root /usr/lib/yp/ypxfr_2perday
# 事实上，这三支程式只是利用 /usr/lib/yp/ypxfr 来进行资料库的更新，
# 不过鸟哥实际进行时，似乎有点小问题，或许需要修改一下上述三个档案，
# 我们以 /usr/lib/yp/ypxfr_1perhour 为例来说明好了：

[root@linux ~]# vi /usr/lib/yp/ypxfr_1perhour
# 找到这一行：
  $YPBINDIR/ypxfr $map
# 将他改成这样：
  $YPBINDIR/ypxfr $map -h master.vbirdnis
    Tips:
    事实上，如果 master 伺服器有启动 ypxfrd 的话，那么下达 ypinit -s master.vbirdnis 时， 就不会有错误讯息啰！ ^_^     		鸟哥的图示
    如此一来，系统将会针对不同的资料库来与 master 伺服器进行比对，若发现 master 的资料较新时，则会进行更新！很方便吧！当然啦，您也可以直接透过系统管理员执行 ypinit -s master.vbirdnis 来处理就是了。此外，直接利用 master 机器上的 yppush 也是个不错的思考方向！

  • 启动 ypbind ，让 slave 也可以查询帐号/密码
    • 如果你的 slave 并没有启动 ypbind 的话，那么 slave 将无法以 master 所提供的帐号来登入的！ 所以接下来，你必须要启动 ypbind 这个查询的功能，好让我们的 slave 伺服器也可以针对我们自己的 NIS 网域 (vbirdnis) 进行查询。 至于 ypbind 的启动方式则请参考下一小节的 NIS client 设定方式吧！

    至此为止，你就已经具有一部 NIS master 及多部 NIS slave 的伺服器啰！接下来就来玩玩 NIS client 吧！
    小标题的图示 防火墙设置
    又来到了防火墙的规划了！要注意的是，我们的 NIS 与 NFS 都是使用 RPC Server 的，所以啰，都可以直接管制 111 这个 port 即可！能够直接以 iptables 管理 111 这个 port ，例如仅允许 192.168.1.0/24 这个网域进来的话，可以在你的防火墙规则上面加上：
    /sbin/iptables -A -s 192.168.1.0/24 --dport 111 -j ACCEPT
/sbin/iptables -A --dport 111 -j DROP
    大标题的图示 NIS Client 端的设定
    我们知道网路连线是双向的，所以 NIS server 提供资料库档案，NIS client 当然也需要提供一些连线的软体啰！ 这个连线的软体就是 ypbind 啦！此外，如同图一的介绍，在 NIS client 端有登入需求时， NIS client 基本上还是先搜寻自己的 /etc/passwd, /etc/group 等资料后才再去找 NIS server 的资料库啊！ 所以 NIS client 最好能够将本身的帐号密码删除到仅剩下系统帐号，亦即 UID, GID 均小于 500 以下的帐号即可， 如此一来既可让系统执行无误，也能够让登入者的资讯完全来自 NIS server ，比较单纯啦！
    Tips:
    事实上，你想要让 NIS 伺服器写入的各项帐号资料都在 NIS server 的 /var/yp/Makefile 那个档案设定的！ 您可以进入该档案搜寻一下 UID 就知道了！ ^_^     		鸟哥的图示
    小标题的图示 NIS client 所需套件与套件结构
    NIS client 端所需要的套件仅有：
    • ypbind
    • yp-tools
    即可，yp-tools 提供查询的软体，至于 ypbind 则是与 ypserv 互相沟通的用户端连线软体啦！ 另外，在 CentOS 当中我们还有很多设定档是与认证有关的，包含 ypbind 的设定档时， 在设定 NIS client 你可能需要动到底下的档案：
    • /etc/sysconfig/network ：里头主要设定了 NIS 领域名称，让 ypbind 启动时可以设定好；
    • /etc/hosts ：很重要吧！至少需要有各个 NIS 伺服器的 IP 与主机名对应；
    • /etc/yp.conf ：这个则是 ypbind 的主要设定档，里面主要规范 NIS server ；
    • /etc/sysconfig/authconfig ：规范帐号登入时的允许认证机制；
    • /etc/pam.d/system-auth ：这个最容易忘记！因为帐号通常由 PAM 模组所管理， 所以你必须要在 PAM 模组内加入 NIS 的支援才行！
    • /etc/nsswitch.conf ：这个档案重要到不行！可以规范帐号密码与相关资讯的查询顺序，预设是 /etc/passwd 再 NIS 等等；
    另外， NIS 还提供了几个有趣的程式给 NIS 用户端来进行帐号相关参数的修改，例如密码、shell 等等， 主要有底下这几个指令：
    • /usr/bin/yppasswd ：更改你在 NIS database (NIS Server 所制作的资料库) 的密码
    • /usr/bin/ypchsh   ：同上，但是是更改 shell
    • /usr/bin/ypchfn   ：同上，但是是更改一些使用者的讯息！
    OK！那么底下就让我们开始来设定 NIS 用户端吧！^_^

    小标题的图示 NIS client 的设定与启动
    启动 NIS client 的设定就简单多了！最主要是加入 NIS domain 当中，然后再启动 ypbind 即可。 整个设定过程是这样的：

  • 设定好 NIS domain 以及 /etc/hosts 主机名对应
    • 设定 NIS domain 就利用 nisdomainname 来处理即可啊：
    1. 直接建立领域名称
[root@linux ~]# nisdomainname vbirdnis

2. 开机立即启动此一领域名称
[root@linux ~]# vi /etc/rc.d/rc.local
# 加入底下这一行：
/bin/nisdomainname vbirdnis

3. 预设在启动 ypbind 时，设定 NIS 领域名
[root@linux ~]# vi /etc/sysconfig/network
# 加入底下这一行：
NISDOMAIN=vbirdnis
    然后则是主机名称与 IP 的对应设定档，重要的很！
    [root@linux ~]# vi /etc/hosts
192.168.1.2    master.vbirdnis
192.168.1.10   slave.vbirdnis
192.168.1.100  client.vbirdnis
    这样就好了！继续下一步！

  • 启动 ypbind 来连结至 NIS server
    • 要启动 ypbind 必须要设定很多的档案，实在很麻烦～不过不打紧， CentOS 提供给我们一个工具‘authconfig’， 透过这个工具我们可以很快的将 ypbind 设定起来。你只要在终端机环境下下达 authconfig 就能够设定了。设定的方式如下所示：

    authconfig 的使用说明
    图二、authconfig 的使用说明

    系统原本就会有 MD5 及 Shadow 的加密编码，您只要选择上图的 NIS 项目，然后按下 OK 便进入到如下所示画面：

    authconfig 的使用说明
    图三、authconfig 的使用说明(续)

    在你输入了正确的 NIS 领域名称 (Domain) 以及正确的主机名称 (就是主控主机) ， 并且按下 OK 后，你的 CentOS 就会自动的帮你启动 portmap 以及 ypbind 这两支程式， 同时还会自动的使用 chkconfig 的功能帮您在开机时自动启动 portmap 及 ypbind 喔！ 真的是很方便吧！这样你就启动了 ypbind 了！很简单吧！

    如果你真的想要手动处理的话，那么你必须要手动的修改底下这些档案：
    • /etc/nsswitch.conf (修改许多主机验证功能的顺序)
    • /etc/sysconfig/authconfig (CentOS 的认证机制)
    • /etc/pam.d/system-auth (许多登入所需要的 PAM 认证过程)
    • /etc/yp.conf (亦即是 ypbind 的设定档)
    事实上， authconfig 指令也是在处理这些档案而已。 我们就来谈一谈这个小细节吧！
    1. /etc/nsswitch.conf
[root@linux ~]# vi /etc/nsswitch.conf
# 这个档案的内容有相当多，不过如果你只想要进行登入验证，可以这样：
passwd:     files nis
shadow:     files nis
group:      files nis
hosts:      files nis dns
# 亦即只要加入 nis 即可！这几个设定的意义是：
# 1. passwd: 就是使用者相关资讯查寻，分别为 /etc/passwd, nis
# 2. shadow: 就是使用者密码的查寻， /etc/shadow, nis
# 3. group:  就是使用者的群组资讯查寻， /etc/group, nis
# 4. hosts:  就是主机名称与IP对应的查寻，/etc/hosts, nis 及 /etc/resolv.conf

2. /etc/sysconfig/authconfig
[root@linux ~]# vi /etc/sysconfig/authconfig
USENIS=no
# 这个档案的内容很好修改！只要将上面 NIS 部分改成 yes 即可：
USENIS=yes

3. /etc/pam.d/system-auth
[root@linux ~]# vi /etc/pam.d/system-auth
# 这个部分也很重要！很容易忘记啦！修改 PAM 的设定档找到如下一行：
password    sufficient    /lib/security/$ISA/pam_unix.so nullok
use_authtok md5 shadow
# 上面可是同一行喔！将他改成：
password    sufficient    /lib/security/$ISA/pam_unix.so nullok
use_authtok md5 shadow nis

4. /etc/yp.conf
[root@linux ~]# vi /etc/yp.conf
# 这个是 ypbind 的主要设定档，主要语法是这样的：
# domain [NIS领域] server [主机名称]
# 或者是透过广播，适合用于大网域有多部 NIS 伺服器时：
# domain [NIS领域] broadcast
domain vbirdnis broadcast
    这样设定完成后，再给他启动 ypbind 即可：
    [root@linux ~]# /etc/init.d/portmap start
[root@linux ~]# /etc/init.d/ypbind start
    你可以手动处理，也可以直接使用 authconfig 啦！ 鸟哥这里倒是建议您可以直接使用 authconfig 比较简单啊！ ^_^！

    另外，那些手动处理的档案当中， /etc/nsswitch.conf 是很重要的，因为他规范了 Linux 本机要使用某些服务时，例如帐号/密码的资料、 主机名称的对应资料、port number 对应服务名称的资料等等，这些资料的搜寻顺序！ 更多的资料请自行进入该档案内查阅，我们也会在 DNS 伺服器章节再次提到这个档案的。

    至于其他两个设定档， /etc/sysconfig/authconfig, /etc/pam.d/system-auth 则是与使用者帐号的验证有关， 这是 CentOS (Red Hat 系统) 所惯用的设定档，如果没有修改设定的话，那么顺利启动 ypbind 也是无法登入的啦！ 这样说，可以了解吧！ ^_^
    小标题的图示 NIS client 端的检验： yptest, ypwhich, ypcat
    如何确定 NIS client 已经连上 NIS server 呢？简单的要命啊！你可以利用 id 这个指令直接检查 NIS server 有的，但是 NIS client 没有的帐号，如果有出现该帐号的相关 UID/GID 资讯时，那表示有连接上啊！ 除此之外，我们还可以透过 NIS 提供的相关检验功能来检查喔！底下分别来瞧一瞧：

  • 利用 yptest 检验资料库之测试：
    • 直接输入 yptest 即可检查相关的测试资料，如下所示：
    [root@linux ~]# yptest
Test 1: domainname
Configured domainname is "vbirdnis"

Test 2: ypbind
Used NIS server: master.vbirdnis

Test 3: yp_match
WARNING: No such key in map (Map passwd.byname, key nobody)
....中间省略....

Test 8: yp_maplist
hosts.byname
group.byname
passwd.byuid
group.bygid
passwd.byname
hosts.byaddr
....中间省略....

Test 9: yp_all
....中间省略....
1 tests failed
    从这个测试当中我们可以发现一些错误，重点在第九个步骤 yp_all 必须要有列出您 NIS server 上头的所有帐号资讯，如果有出现帐号相关资料的话，那么应该就算验证成功了！比较有问题的是第三步骤， 他会出现在 passwd.byname 当中找不到 nobody 的字样。这是因为早期的 nobody 之 UID 都设定在 65534 ，但 CentOS 则将 nobody 设定为系统帐号的 99 ，所以当然不会被记录， 也就出现这一个警告。不过，这个错误是可忽略的啦！ ^_^

  • 利用 ypwhich 检验资料库数量
    • 单纯使用 ypwhich 的时候显示的是‘NIS Client 的 domain’名称，而当加入 -x 这个参数时， 则是显示‘NIS Client 与 Server 之间沟通的资料库有哪些？’你可以这样测试哩！
    [root@linux ~]# ypwhich -x
Use "hosts"     for map "hosts.byname"
Use "group"     for map "group.byname"
Use "passwd"    for map "passwd.byname"
....以下省略....
    由上面我们可以很清楚的就看到相关的档案啦！这些资料库档案则是放置在我的 NIS Server 的 /var/yp/vbirdnis/* 里面啰！

  • 利用 ypcat 读取资料库内容
    • 除了 yptest 之外，你还可以直接利用 ypcat 读取资料库的内容喔！一般作法是这样：
    [root@linux ~]# ypcat [-h nisserver] [资料库名称]
参数：
-h nisserver ：如果有设定的话，指向某一部特定的 NIS 伺服器，
               如果没有指定的话，就以 ypbind 之设定为主；
资料库名称：亦即在 /var/yp/vbirdnis/ 内的档名啊！例如 passwd.byname

范例：读出 passwd.byname 的资料库内容
[root@linux ~]# ypcat passwd.byname
    这三个指令在进行 NIS Client 端的检验时，是相当有用的喔！不要忽略了他的存在啊！尤其是刚架设好 NIS Client 时，一定要使用 yptest 去检查看看有没有设定错误喔！根据荧幕显示的讯息去一个一个校正错误才行啊！

    小标题的图示 使用者参数修改： yppasswd, ypchfn, ypchsh
    好了，完成了上述的设定后，你的 NIS server/client 的帐号已经同步了！真是高兴不是吗？ 不过，还有个挺大的问题，那就是.... 使用者如何在 NIS client 修改他自己的登入参数，例如密码、shell 等等？ 因为 NIS client 是藉由资料库来取得使用者的帐号密码，那如何在 NIS 用户端处理帐号密码的订正？

    问的好！这也是为何我们需要在 NIS server 启动 yppasswdd 这支服务的主要用意！ 因为 yppasswdd 可以接收 NIS client 端传来的密码修改，藉此而处理 NIS server 的 /etc/passwd, /etc/shadow ， 然后 yppasswdd 还能够重建密码资料库，让 NIS server 同步更新资料库！真是很不错啊！ ^_^

    那该如何下达指令呢？很简单啊！透过 yppasswd, ypchsh, ypchfn 来处理即可。这三个指令的对应是：
    • yppasswd ：与 passwd 指令相同功能；
    • ypchfn ：与 chfn 相同功能；
    • ypchsh ：与 chsh 相同功能。
    因为功能相当，所以鸟哥这里仅说明一下 yppasswd 而已。假设你已经登入 NIS client 那部主机， 并且是以 nistest 这个使用者登入的，记住，这个使用者相关资料仅在 NIS server 上。 接下来，这个使用者可以下达 yppasswd ，如下所示：
    [nistest@linux ~]$ yppasswd
Changing NIS account information for nistest on master.vbirdnis.
Please enter old password:  <==这里输入旧密码
Changing NIS password for nistest on master.vbirdnis.
Please enter new password:  <==这里输入新密码
Please retype new password: <==再输入一遍

The NIS password has been changed on master.vbirdnis.
    嘿嘿！如何，这样就更新了 NIS server 上头的 /etc/shadow 以及 /var/yp/vbirdnis/passwd.by* 的资料库， 简单吧！一下子就同步化了。不过，如果要教育使用者使用 yppasswd 的话，他可能不太能适应， 不要紧，你可以透过修改 alias 或者是置换掉 /usr/bin/passwd 这支程式即可！

    大标题的图示 NIS 与 NFS 的设定与丛集电脑运用
    不晓得您有没有发现一件事情啊！那就是：我们的 NIS Server 设定的使用者家目录是在 /home 底下，例如 nistest 这个人的家目录在 /home/nistest (这个目录在 master.vbirdnis 这部主机上面才有)。问题是，当我们登入 NIS Client 主机时，那么我们取得的家目录资料还是在 /home/nistest ，不过事实上 NIS Client 主机并没有 /home/test 这个目录啊，也就是说：
    • nistest 这个使用者是在 NIS server 上面建立的，所以有 /home/nistest 这个目录；
    • 在 NIS Client 上面没有真正的 nistest 这个帐号，因为他是由 NIS server 上面取得的，所以自然也就没有 /home/nistest 这个目录在 NIS client 上面。
    这样会造成什么问题呢？呵呵！就是你的 nistest 这个使用者，登入 NIS client 的时候，‘会找不到自己的家目录’！ 真是糟糕～而且，因为我们的 NIS client 可能有很多部，要是每次登入 NIS Clients 主机的时候， 所拥有的家目录都是个别 NIS client 上面的目录，那么就没有达到 NIS 的功能啦！您说是吧！所以， 如果你需要‘同一个帐号登入的每个 NIS Client 所拥有的家目录都是相同的！’ 的一个情况，呵呵！就可以使用 NFS 来加以设定啦！详细的 NFS 设定我们之前已经提过了， 这里不在赘言，单纯谈一下简单的设定技巧：
    • 在 NIS Server 上面开放 /home 这个目录出来；
    • 在 NIS Client 上面， mount NIS 主机的 /home 到自己的 /home 里面去！
    • 如此一来，不论登入哪一部 NIS Server 或 client ，使用者都是进入到 NIS Server 的 /home 里面的家目录啰！
    事实上，使用者的资讯除了 /home 之外，像是 /var/spool/mail 以及 /var/spool/cron 也都是可能会有资料存放的目录，你的 NFS 主机应该也要提供这两个目录才好。 设定的方法也不难，我们就简单的谈一谈吧！
    1. 设定 NIS server 主机的 NFS 开放目录：
[root@linux ~]# vi /etc/exports
/home  192.168.1.0/24(rw,async)

[root@linux ~]# exportfs -rv
exporting 192.168.1.0/24:/home

[root@linux ~]# /etc/init.d/nfs start
[root@linux ~]# chkconfig --level 35 nfs on

2. 设定 NIS Client 的 mount 资料！
[root@linux ~]# mount -t nfs -o bg,soft 192.168.1.2:/home /home
# 如果这个指令没有问题，可以将他加入 /etc/rc.d/rc.local 当中啊！
    这样一来，您的 NIS Clients 就具有和 NIS Server 主机一模一样的家目录了！现在您可以立刻登入看看喔！

    事实上，现阶段由于个人电脑的相关设备不但便宜，而且运算效能并不比一般大型电脑慢， 因此很多人就在想：‘那我可否将许多个人电脑透过网路串接起来，让好几部个人电脑同步运作一个程式， 那么该程式就能够在很短的时间内运算出结果啰！’呵呵！这就是所谓的丛集式个人电脑 (PC cluster) 啦！

    要实作 PC cluster 需要很多元件的配合，作业系统也是一个很重要的参数！目前较常使用的当然就是 Linux 啦！ 不过我们知道 Linux 系统的运作需要用到使用者的相关参数，例如 UID, GID 等等，所以啰， 在 PC cluster 当中的每一部 Linux 的帐号密码以及‘档案系统 (filesystem) ’都需要相同才行！ 为何档案系统需要相同呢？因为你得要让每部主机都使用到相同的一支程式吧？所以啰， 这就需要 NIS 与 NFS 的同步配合了！

    由于‘预测’这个玩意儿越来越重要，比如说气象预报、空气品质预报等等， 而预测需要一个很庞大的模式来进行模拟的工作，这么庞大的模拟工作需要大量的运算， 在学校单位要买一部很贵的大型主机实在很不容易！不过，如果能够串接十部双核心的个人电脑的话， 那么可能只需要不到 20 万便能够组成相当于具有 20 颗 CPU 的大型主机的运算能力了！ 所以说，在未来 PC cluster 是一个可以发展的课题喔！

    鸟哥也有写过一篇不是很成熟的 PC cluster 简易架设，有兴趣的话请自行参考：
    • http://linux.vbird.org0600cluster.htm
    大标题的图示 指令对应资料
    咱们前面总共讲到 NIS master server, NIS slave server, NIS client 这三个元件， 偏偏每个元件所需要启动的服务以及可使用的指令都不相同， 所以这里鸟哥帮大家汇整一下几个常见的指令吧！ ^_^

    相关的动作 | NIS Master | NIS slave | NIS client
所需要启动的服务 | ypserv | ypserv ypbind | ypbind
使用者能够修改密码 | yppasswdd |  | yppasswd ypchfn ypchsh
资料库传输服务 | ypxfrd yppush | ypxfr |
资料库测试读取 |  | yptest ypwhich ypcat | yptest ypwhich ypcat
资料库的建立 | ypinit -m | ypinit -s server |
    大标题的图示 重点回顾
    • Network Information Service (NIS) 也可以称为 Sun Yellow Pages (yp)，主要是负责在网域当中帮忙 NIS Client 端查寻帐号与密码以及其他相关网路参数的服务；
    • NIS server 其实就是提供本身的 /etc/passwd, /etc/shadow, /etc/group, /etc/hosts 等帐号密码资料，以及相关的网路参数等，以提供网域当中 NIS Client 的搜寻之用；
    • NIS 为 server/client 架构，当 NIS client 有帐号登入需求时，该主机会 (1)先找自己的 /etc/passwd, (2)再前往 NIS server 搜寻相关帐号资料。
    • NIS 使用的套件就是 yp 这个套件，主要分为两部份， ypserv 用在 NIS Server，至于 ypbind 与 yp-tools 则用在 NIS Client 上面。
    • 为加快 NIS 查询的速度，因此 NIS server 会将本机的帐号资料制成传输较快的资料库档案， 并放置于 /var/yp/(nisdomainname)/ 目录当中；
    • 不论是 NIS 或者是 NFS 都是藉由 RPC Server 所启用的，因此都可以使用 rpcinfo 来查寻 NIS 是否已经启动，以及该 daemon 是否已经向 portmapper (RPC server) 注册了！
    • 在 NIS Server 的设定当中，最重要的一个步骤就是将帐号、密码、网路参数等 ASCII 格式档案转成资料库档案 (database file)，以提供 NIS client 的查寻！而启动 ASCII 转成 database 的程式可以使用 /usr/lib/yp/ypinit -m 或者到 /var/yp 底下执行 make 均可。
    • NIS client 端的设定当中，最重要的为 /etc/nsswitch.conf 及 /etc/sysconfig/authconfig 里面的设定，另外， CentOS 的 /etc/pam.d/system-auth 也很重要！；
    • 由于 NIS 通常使用于内部网域当中，因此 /etc/hosts 这个档案的设定相当重要！
    • 在 NIS master/slave server 当中，建立资料库的方法为 ypinit -m 及 ypinit -s；
    • 在 NIS master/slave server 当中，可以藉由 ypxfrd/ypxfr 以及 yppush 来进行主动的更新资料库；
    • 若想让使用者在任一部 NIS 管辖的主机登入都可以使用同一份家目录，则需开启 NFS 提供 /home 给所有的主机挂载使用；
    大标题的图示 课后练习
    • 请简单说明 NIS server 的功能与工作流程
      • 当您有多部具有相同帐号的 Linux 主机时，即可利用 NIS 所提供的服务，来利用一部 NIS 主机掌控所有的 linux 主机的登入时所需查阅的帐号与密码验证。流程如下：
      1. NIS Server 将自己系统内的 /etc/passwd, /etc/group, /etc/hosts 等制作成为 DBM 的资料库格式档案；
      2. NIS Client 若有用户登入的要求时，会前往 NIS Server 搜寻资料库里面的资料做为验证之用。
      3. 每次更动 NIS Server 上面的用户资料时，则 NIS Server 需要重新制作 DBM 资料库档案才行！
    • 请简单说明 NIS Server/client 的架构
      • NIS master/client 的特色为：
      1. NIS Server 的 master 先将自己的帐号、密码相关档案制作成为资料库档案(database file)；
      2. NIS Server 的 master 将自己的资料库档案传送到 slave 上面；
      3. NIS Server 的 slave 接收来自‘信任的 NIS Server master 主机’的资料后，更新自己的资料库，使自己的资料库与 master 主机的资料同步；
      4. 网域当中的所有 NIS Client 查寻 NIS Server 时，会找寻‘最先回应的那一部 NIS 主机的资料库内容’。
      也就是说，架设 slave NIS server 可以分担区域内 NIS 的工作！
    • NIS 启动之前需要先启动那个服务，否则就无法启动成功 (提示：RPC Server)
      • 因为 NIS 是 RPC Server 的一种，所以必须要启动 portmap 这个 daemon 才行！
    • 我的 NIS 网域名称为 bird ，另外，我主机的 IP 与主机名称为 192.168.5.1/bird.nis.org ，请问要这些资讯需要设定在 NIS Server 的哪些档案之内？
      • 网域名称可以直接手动下达‘ nisdomainname bird ’也可以写入 /etc/sysconfig/network 里面‘NISDOMAIN=bird’； IP 与 主机名称 需要写入在 /etc/hosts 里面。
    • /etc/nsswitch.conf 的功能为何？如果我想要让密码查寻先本地的密码档，再查寻 NIS ，需要如何设定？
      • 该档案的功能很多，在 DNS 方面，可以用来决定正、反解的顺序，至于密码则可以用来判断何者为先！如果需要先查本机再查 NIS 的密码时，需要的参数：
      passwd: files nis
      shadow: files nis
    • NIS Server 将密码等档案做成资料库以提供 NIS client 来查寻，那么请问使用什么动作后，可以将密码档案转成 NIS 的资料库格式档案？
      • /usr/lib/yp/ypinit -m
    • 如果我想要增加网域当中一个新的帐号：newaccount，并且这个 newaccount 可以让 NIS Client 查寻到他的帐号与密码，需要进行哪些步骤？
      1. 先登入 NIS Server 以 useradd newaccount 以及 passwd newaccount 来新增帐号；
      2. 制作密码资料库：‘/usr/lib/yp/ypinit -m’
      3. 重新启动：‘/etc/rc.d/init.d/ypserv restart ; /etc/rc.d/init.d/yppasswdd restart’。
    • 实作范例题：底下是我的网域参数特征：
      network/netmask:192.168.1.0/255.255.255.0
      NIS server : 192.168.1.100 (hostname: server.nis.test)
      NIS cient: 192.168.1.200 (hostname: client1.nis.test)
      NIS domain name: nis.test
      利用上面的参数来设定 NIS 架构，请一步一步的写下你的设定。
      • 请自行参考本章节的内容设定
    • 承上题：如果我的网域太大了，所以有一部 NIS slave 主机，这部主机的 IP 为 192.168.1.50 ，请问这部主机该如何设定？
      • 请参考本章节的 NIS slave server 的相关说明！
    大标题的图示 参考资料
    • Study Area 之 NIS 伺服器架设：http://www.study-area.org/linux/servers/linux_nfs.htm
    • NIS 官方网站：http://www.linux-nis.org/
    • NIS HOW-TO：http://www.linux-nis.org/nis-howto/HOWTO/index.html
    2003/05/06：第一次完成日期！
    2003/09/16：稍微加入一些资讯与微幅修改版面！
    2006/09/22：将旧的文章移动到 此处
    2006/10/11：啊！过了好久了！修改过程当中历经搬家，所以文章产生较慢啊！这次多加入 NIS slave server 说！
    2003/05/06以来统计人数


鸟哥的 Linux 私房菜 -- DHCP 伺服器

为取得较佳浏览结果，请爱用 firefox 浏览本网页

DHCP 伺服器
切换解析度为 800x600
最近更新日期：2006/12/06
如果您在工作单位使用的是笔记型电脑，而且常常要带着您的笔记型电脑到处跑，那么由前几章的‘ 连上 Internet ’设定当中，会发现，哇！ 我的网路卡参数要常常修改啊！而且，每到一个新的地方，就得问清楚该地的 Server 提供的网路参数才行！真是麻烦～～这个时候，动态主机设定协定 (DHCP) 可就大大的派上用场啦！DHCP 这个伺服器可以自动的分配 IP 与相关的网路参数给 Client 端，来提供 Client 端自动以主机提供的参数来设定他们的网路，如此一来，使用者只要将自己的 Notebook 设定好经由 DHCP 协定来取得网路参数后，一插上网路线，呵呵！马上就可以享受 Internet 的服务啦！很方便吧！所以得来瞧一瞧这个好用的协定喔！

1. 本章的行前准备工作
2. DHCP 运作的原理
    2.1 什么是 DHCP 协定
    2.2 DHCP 的运作方式
    2.3 何时需要架设 DHCP 伺服器
 3. DHCP 伺服器端的设定
    3.1 所需套件与套件结构
    3.2 主要设定档 /etc/dhcpd.conf 的语法
    3.3 一个区域网路的 DHCP 伺服器设定案例
    3.4 DHCP 伺服器的启动与观察
    3.5 内部主机的 IP 对应
 4. DHCP 用户端的设定
    4.1 Linux 用户端
    4.2 Windows 用户端
 5. 伺服器端资料查阅
    5.1 检查租约档案
    5.2 使用 ether-wake 实行远端自动开机 (remote boot)
 6. 重点回顾
7. 课后练习
8. 参考资料
9. 针对本文的建议：http://phorum.vbird.org/viewtopic.htm?p=117845
大标题的图示 本章的行前准备工作
由于 DHCP 必需要设定整个区域网路的网段规定，还有得要了解路由设定，以及一堆与网路有关的资讯等等， 所以你一定要熟悉网路基础。此外，由于 DHCP server 套件预设应该是不会安装啦，所以你也必需要了解如何使用 rpm 或者是 yum 等工具才行。
  • 务必了解网路基础相关的资料；
  • 也得了解一下 DNS 相关的议题；
  • 还有防火墙最好也能了解一番。
大标题的图示 DHCP 运作的原理
老规矩，在正式的进入 DHCP (Dynamic Host Configuration Protocol) 主机设定之前，我们先来认识一下 DHCP 这个协定吧！还有，需要了解的是，我们是否有需要‘一定’得设定 DHCP 这个伺服器呢？这里都需要厘清一下概念喔！

小标题的图示 什么是 DHCP 协定
在开始 DHCP 的说明之前，我们先来复习一下之前在网路基础里面提到的几个网路参数吧！ 要设定好一个网路的环境，使电脑可以顺利的连上 Internet ，那么您的电脑里面一定要有底下几个网路的参数才行，分别是：
    IP, netmask, network, broadcast, gateway, DNS IP
其中，那个 IP, netmask, network, broadcast 与 gateway 都可以在 /etc/sysconfig/network-scripts/ifcfg-eth[0-n] 这些档案里面设定，DNS 的位址则是在 /etc/resolv.conf 里头设定。呵呵！只要这几个项目设定正确，那么电脑应该就没问题的可以上网了！ 所以说，您家里面的 3, 4 部电脑，您都可以手动的来设定好您所需要的网路参数， 然后利用 NAT 主机的功能，就可以大摇大摆的连上 Internet 了！真是不错 ^_^，不是吗？

好了，现在让我们换一个大一些些的场景吧！假设您是学校宿舍的网路管理员，所管理的学生电脑大概有 100 部好了，那么您怎么设定好这 100 部的电脑呢？
  1. 直接每一部电脑都让您登门拜访手动的去设定好？
  2. 将所有的学生都集合起来，然后精神训话.....喔不！是直接教导一下怎么设定？还是
  3. 藉由一部主机来自动的分配所有的网路参数给宿舍内的任何一部电脑？
这三种解决方案所需要的时间都不相同，如果您选择的是(1)，那么鸟哥个人认为，您不是工作狂就是疯掉了， 因为所要花费的时间与您所得的薪水与付出的心力是完全不成比例的。如果选择是(2)那么很可能您会被挂上独裁者、 没良心的管理员的称号！如果是选择(3)呢？恭喜您！这个方案的管理时间花费最短，也是最不麻烦的作法啦！

呵呵！知道我要说些什么了吗？是的！这个 DHCP (Dynamic Host Configuration Protocol) 主机最主要的工作，就是在进行前面提到的第三个方案，也就是自动的将网路参数正确的分配给网域中的每部电脑， 让用户端的电脑可以在开机的时候就立即自动的设定好网路的参数值，这些参数值可以包括了 IP、netmask、network、gateway 与 DNS 的位址等等。如此一来，呵呵！身为管理员的您，只要注意到这一部提供网路参数的主机有没有挂掉就好了， 其他同学们的个人电脑，哈！您想都不必想要怎么去帮忙！因为 DHCP 主机已经完全都帮您搞定啦！ ^_^！ 阿！当管理员最大的幸福就是可以喝喝茶、聊聊天就能控管好一切的网路问题呢！

小标题的图示 DHCP 的运作方式
你必需要知道的是，DHCP 通常是用区域网路内的一个通讯协定，他主要藉由用户端传送广播封包给整个物理网段内的所有主机， 若区域网路内有 DHCP 主机时，才会回应用户端的 IP 参数要求。所以啰，DHCP 伺服器与用户端是应该要在同一个物理网段内的。 而用户端取得 IP 参数的程序可以简化如下：
  1. 用户端利用广播封包发送 DHCP 需求：
    若用户端设定使用 DHCP 取得 IP (在 Windows 内为‘自动取得 IP’)，则当用户端开机或者是重新启动网路卡时， 用户端主机会发送出 DHCP 要求给所有物理网段内的电脑。此封包的目标 IP 会是 255.255.255.255， 所以一般主机接收到这个封包后会直接予以丢弃，但若区域网路内有 DHCP 伺服器时会如何回应？

  2. DHCP 主机回应讯息：
    DHCP 主机在接收到这个用户端的需求后，针对这个用户端的硬体位址 (MAC) 与本身的设定资料来进行下列工作：

    • 到伺服器的登录档中寻找该用户之前是否曾经用过某个 IP ，若有且该 IP 目前无人使用，则提供此 IP 给用户端；
    • 若设定档针对该 MAC 提供额外的固定 IP (static IP) 时，则给予该 IP 的设定；
    • 若不符合上述两个条件，则随机取用目前没有被使用的 IP 给用户，并记录下来。

    此外，DHCP 伺服器还会提供一个租约时间给用户端，并等待用户端的回应。

  3. 用户端接受 DHCP 伺服器提供的参数并设定本身的网路环境：
    若一切安好，则用户端会接受该次取得的 IP 并开始处理本身的网路环境，包括改写 /etc/resolv.conf 等等； 并且会向 DHCP 伺服器发送一个确认封包，确认该参数已被接受。

  4. DHCP 伺服器记录该次租约行为：
    用户端回传讯息以建立租约行为后，该次租约会被记录到主机的登录档上头， 并且开始租约计时喔！那么该次租约何时会到期而被解约 (真可怕的字眼！) ？你可以这样想：

    • 用户端离线：不论是关闭网路介面 (ifdown)、重新开机 (reboot)、关机 (shutdown) 等行为，皆算是离线状态，这个时候 Server 端就会将该 IP 回收，并放到 Server 自己的备用区中，等待未来的使用；

    • 用户端租约到期：前面提到 DHCP server 端发放的 IP 有使用的期限，用户端使用这个 IP 到达期限规定的时间，而且没有重新提出 DHCP 的申请时，就需要将 IP 缴回去！这个时候就会造成断线，而用户也可以再向 DHCP 主机要求再次分配 IP 啰
以上就是 DHCP 这个协定在 Server 端与 Client 端的运作状态，由上面这个运作状态来看，我们可以晓得，只要 Server 端设定没有问题，加上 Server 与 Client 在硬体连线上面确定是 OK 的，那么 Client 就可以直接藉由 Server 来取得上网的网路参数，当然啦，只要我们这些管理员能够好好的、正确的管理好我们的 DHCP ，嘿嘿！那么上网的设定自然就变成一件很简单的事情啦！

  • DHCP 伺服器给予用户端的 IP 类型：
    • 在上面的步骤里面，注意到第二步骤了吗？就是伺服器会去比较用户端的 MAC 硬体位址，并判断该 MAC 是否需要给予一个固定的 IP 呢！所以啦，我们可以设定 DHCP 伺服器给予用户端的 IP 类型主要有两种：
    • 固定 (Static) IP：
      只要那个用户端电脑的网路卡不换掉，那么 MAC 肯定就不会改变，由于 DHCP 可以根据 MAC 来给予固定的 IP ，所以该电脑每次都能以一个固定的 IP 连上 Internet ！呵呵！ 这种情况比较适合当这部电脑需要用来做为提供区域内的一些网路服务的主机之用。那么如何在 Linux 上面知道您的 MAC 呢？很简单啦！有很多的方式，最简单的方式就是使用 ifconfig 及 arp 来进行：
      1. 观察自己的 MAC 可用 ifconfig：
[root@linux ~]# ifconfig eth0
eth0      Link encap:Ethernet  HWaddr 00:08:03:A3:E0:34
          inet addr:192.168.1.254  Bcast:192.168.1.255  Mask:255.255.255.0
          ....底下省略....

2. 观察别人的 MAC 可用 ping 配合 arp
[root@linux ~]# ping -c 1 192.168.1.101
[root@linux ~]# arp -n
Address        HWtype  HWaddress          Flags Mask   Iface
192.168.1.101  ether   00:08:75:A0:B2:78  C            eth0

    • 动态 (dynamic) IP：
      Client 端每次连上 DHCP 所取得的 IP 都不是固定的！都直接经由 DHCP 所随机由尚未被使用的 IP 中提供！
    除非您的区域网路内的电脑有可能用来做为主机之用，所以必需要设定成为固定 IP ，否则使用动态 IP 的设定比较简单，而且使用上面具有较佳的弹性。怎么说呢？假如您是一个 ISP 好了，而您只申请到 150 个 IP 来做为您的客户连线之用。那么您是否真的只能邀集到 150 的使用者？呵呵！当然不啰！我可以邀集 200 个使用者以上呢！

    为什么？这样想好了，我今天开了一家餐馆，里面只有 20 个座位，那么是否我一餐只能卖给 20 个人呢？当然不是啦！因为客人是人来人往的，有人先吃有人后吃，所以同样是 20 个座位，但是可以有 40 个人来吃我的简餐，因为来的时间不一样嘛！了解了吗？呵呵！对啦！您这个 ISP 虽然只有 150 个 IP 可以发放，但是因为您的使用者并非 24 小时都挂在线上的，所以您可以将这 150 个 IP 做良好的分配，让 200 个人来‘轮流使用’这 150 个 IP 哩！
    Tips:
    其实 IP 只有 Public IP 与 Private IP 两种，中文翻译成‘公共 IP’与‘私有 IP’这两个， 至于其他所谓的‘静态 IP’、‘实体 IP’、‘虚拟 IP’、‘浮动式 IP’等等，都是藉由一些 IP 取得的方式来分类的， 关于 IP 的种类我们在网路基础中谈过了，记得再好好的厘清一下观念喔！     		鸟哥的图示
    事实上现在主流的 ADSL 宽频拨接上网也有使用到‘静态 IP ’与‘固定 IP ’之类的概念喔！ 举例来说好了，hinet/seed net 等主要 ISP 都有提供所谓的：‘一个固定 IP 搭配 7~8 个浮动 IP ’的 ADSL 拨接功能，也就是说同样透过一条电话线拨接到 ISP ，但是其中一个拨接是可以取得固定的 IP 呢！ 而其他的则是非固定的 IP ，DHCP 的 static/dynamic 跟这个玩意儿有点类似啦！ ^_^

  • 关于租约所造成的问题：
    • 怪了！如果我们观察上面 DHCP 运作模式的第二个步骤，您会发现最后面 DHCP 伺服器还有给予还有一个租约期限！ 干嘛还要这样的一个期限呢？其实设定期限还是有个优点啦！最大的优点就是可以避免 IP 被某些使用者一直占用着，但该使用者却是 Idle (发呆) 的状态！

    举个例子来说，我们刚刚不是说到，我有 150 个 IP ，但是偏偏我有 200 个用户吗？我们以 2006 年的世界杯足球赛来说明好了。假设每个使用者都急着上网知道世足赛的消息， 那么某些热门对战时段网路将可能达到使用尖峰！也就是说，这 200 个人同时要来使用这 150 个 IP ，有可能吗？当然不可能！肯定会有 50 个人无法连线，因为‘很抱歉！目前系统正在忙线中，请您稍后再拨！’

    那怎么办？这个时候租约到期的方式就很有用处啦！那几个已经连线进来很久的人， 就会因为租约到期而被迫离线，这个时候该 IP 就会被释放出来，哈哈！大家赶快抢呀！先抢到先赢喔！ 所以，那 50 个人 (包括被迫离线的那个朋友) 只好继续的、努力的、加油的来进行 DHCP 的要求啰！ ^_^""

    虽然说是优点，但是其实如果站在使用者的角度来看，还是可能会造成公愤的！凭什么大家一起交钱， 我先连线进来就需要先被踢出去？～呵呵！所以啰，如果要当 ISP ，还是得要先规划好服务的方针才行呦！ 这样您可以了解租约到期的行为了吗？！ ^_^

    既然有租约时间，那么是否代表我用 DHCP 取得的 IP 就得要‘手动’的在某个时间点去重新取得新的 IP 呢？不需要的啦！因为目前的 DHCP 用户端程式大多会主动的依据租约时间去重新申请 IP (renew) 的！也就是说在租约到期前你的 DHCP 用户端程式就已经又重新申请更新租约时间了。所以除非 DHCP 主机挂点， 否则您所取得的 IP 应该是可以一直使用下去的！

  • 多部 DHCP 主机在同一物理网段的情况
    • 或许您曾经发现过一件事情，那就是当我的网域里面有两部以上的 DHCP 主机时， 到底哪一部主机会设定我的这部电脑所发出的 DHCP 要求？呵呵！很抱歉，俺也不晓得！ 因为在网路上面，很多时候都是‘先抢先赢’的， DHCP 的回应也是如此！当 Server1 先回应时，您使用的就是 Server1 所提供的网路参数内容，如果是 Server2 先回应，您就是使用 Server2 的参数来设定您的 PC ！不过，前提之下当然是这些电脑的‘物理连线’都是在一起的啊！

    小标题的图示 何时需要架设 DHCP 伺服器
    既然 DHCP 的好处是‘免用户端设定’，而且对于行动装置的上网方面非常的方便！那么是否代表你就得要架设一部 DHCP 呢？那可不一定！接下来要告知大家的是几个概念性的问题， 您倒不一定‘必需’遵守底下的一些概念呢！反正，自己的网域自己‘爽’就好啦！

  • 使用 DHCP 的几个时机
    • 在某些情况之下，倒是强烈的建议架设 DHCP 主机的！什么情况呢？例如：
    • 具有相当多行动装置的场合：
      例如您的公司内部很多笔记型电脑 (笔电) 使用的场合！因为这种笔电本身就是移动性的装置， 如果每到一个地方都要去问人家‘喂！您这边的网路参数是什么？’还得要担心是否会跟人家的 IP 相冲突等等的问题！这个时候，DHCP 可就是您的救星啰！

    • 区域内电脑数量相当的多时：
      另外一个情况就是您所负责的网域内电脑数量相当庞大时， 大到您没有办法一个一个的进行说明来设定他们自己的网路参数，这个时候为了省麻烦，还是架设 DHCP 来的方便呐！况且，维护一部您熟悉的 DHCP 主机，要比造访几十个不懂电脑的人要简单的多哩！^_^
  • 不建议使用 DHCP 主机的时机
    • 虽然 DHCP 有很多好处，但是您有没有发现一个步骤怪怪的呀！回头看一下那个步骤一， 用户端在开机的时候会主动的发送讯息给网域上的所有机器，这个时候，如果网域上就是没有 DHCP 主机呢？很抱歉，那么您的这部用户端电脑，‘仍然会持续的发送讯息！’ 真正的时间与次数我不晓得会有多久，不过，肯定会超过 30 秒以上， 甚至可以达到一分钟以上！哇！那么这段时间您能干嘛？呵呵！除了等、还是等！ 所以啰，如果电脑数不多，还是使用手动的方式来设定一下就好了！方便嘛！
    • 在您网域内的电脑，有很多机器其实是做为主机的用途，很少 Client 需求，那么似乎就没有必要架设 DHCP ；
    • 更极端的情况是，像一般家里，只有 3 ~ 4 部电脑，这个时候，架设 DHCP 只能拿来练练功力，事实上，并没有多大的效益；
    • 当您管理的网域当中，大多网路卡都属于老旧的型号，并不支援 DHCP 的协定时；
    • 很多使用者的资讯知识都很高，那么也没有需要架设 DHCP 啦。
    如前所述，上面的都是概念性的说法，事实上，一件事情的解决之道是有很多的方案的， 没有所谓的‘完全正确’的方案，只有‘相对可行、并且符合经济效益与功能’的方案！ 所以啰，架设任何网站之前，请先多评估评估呐！

    大标题的图示 DHCP 伺服器端的设定
    事实上，目前市面上的 IP 分享器已经便宜到爆了！而 IP 分享器本身就含有 DHCP 的功能， 所以如果你只是想要单纯的使用 DHCP 在你的区域网路当中而已，那么建议你直接购买一部 IP 分享器来使用即可， 因为至少他很省电。如果你还有其他考量的话，才来架设 DHCP 吧！底下我们以一个简单的范例来架设 DHCP 先。

    小标题的图示 所需套件与套件结构
    DHCP 的套件需求很简单，就是只要伺服器端软体即可。所需套件为：
    • dhcp
      提供整个 DHCP 伺服器的主要设定档与启动的 script 及执行档等等重要资料。
    真的只要一个套件就好了，而且没有什么很重大的相依性问题呢！请拿出你的原版光碟用 rpm 来安装， 或者直接用 yum 线上安装也可以！档案很小啦！至于整个套件的结构是这样的：
    • /etc/dhcpd.conf
      这个就是 dhcp 伺服器的主要设定档咯！在某些 Linux 版本上头这个档案可能不存在，所以如果你确定有安装 dhcp 套件却找不到这个档案时，请手动自行建立他即可。这个档案的设定很简单啦，我们底下主要就是在谈这个档案的设定而已哩。 不过设定档的实际位置还是得要参考 /etc/init.d/dhcpd 的规范才是。
      Tips:
      其实 dhcp 套件在释出的时候都会附上一个范例档案，你可以使用‘ rpm -ql dhcp ’来查询到 dhcpd.conf.sample 这个范例档案，然后将该档案复制成为 /etc/dhcpd.conf 后，再手动去修改 /etc/dhcpd.conf 即可，这样设定比较容易咯！       		鸟哥的图示
    • /usr/sbin/dhcpd
      启动整个 dhcp daemon 的执行档啊！其实最详细的执行方式应该要使用‘ man dhcpd ’来查阅一番的呢！^_^

    • /var/lib/dhcp/dhcpd.leases
      这档案颇有趣的！我们前面原理部分不是有提到‘租约’吗？DHCP 伺服器端与用户端租约建立的启始与到期日就是记录在这个档案当中的咯！
    就跟你说很简单吧！整个套件资料也不过才如此而已呢！

    小标题的图示 主要设定档 /etc/dhcpd.conf 的语法
    其实 DHCP 的设定很简单啊，只要将 dhcpd.conf 设定好就可以启动了。不过编辑这个档案时你必须要留意的是：
    • ‘ # ’为注解符号；
    • 除了括号那一行之外，其他的每一行后面都要以‘ ; ’做为结尾！这是最容易出错的地方。
    • 通常设定的项目都有独特的名称，以：‘ <参数代号> <设定内容> ’来处理，例如：
      default-lease-time 259200;
    • 某些设定项目必须以 option 来设定，基本方式为‘ option <参数代码> <设定内容> ’例如：
      option domain-name "your.domain.name";
    基本上，我们刚刚前面提过说， DHCP 的 IP 分配可分为给予动态 IP 与静态 IP ，其中又需要了解的是，如果需要设定静态 IP 的话，那么就必须要知道要设定成静态 IP 的那部电脑的硬体位址 (MAC) 才行，请使用 arp 及 ifconfig 来查知您的介面的 MAC 吧！此外，我们需要设定的项目大概有几项：
    • 整体设定 (Global)
      包括有租约期限、DNS 的 IP 位址、路由器的 IP 位址还有动态 DNS (DDNS) 更新的类型等等。 当静态 IP 及动态 IP 内没有规范到某些设定时，则以整体设定值为准。常使用参数有：
      • default-lease-time 时间：
        预设的租约时间，后面的时间参数预设单位为秒；
      • max-lease-time 时间：
        最大租约时间，当用户端超过租约时间却尚未更新 IP 时，最长可以使用该 IP 的时间；
      • option domain-name "领域名称"：
        如果你在 /etc/resolv.conf 里面设定了一个‘ search google.com ’的话，这表示当你要搜寻主机名称时， DNS 系统会主动帮你加上这个领域名称的意思。所以这个设定参数也会修改 /etc/resolv.conf 喔！
      • option domain-name-servers IP1, IP2：
        这个设定参数可以修改用户端的 /etc/resolv.conf 档案！就是 nameserver 所接的那个 DNS IP 啰！特别注意设定参数最末尾为‘servers’ (有 s 喔)；
      • ddns-update-style 类型：
        因为 DHCP 用户端所取得的 IP 通常是一直变动的， 所以某部主机的主机名称与 IP 的对应就很难处理。此时 DHCP 可以透过 ddns (请参考 合法主机名称 与 DNS 章节的说明) 来更新主机名与 IP 的对应。不过我们这里不谈这么复杂的东西，所以你可以将他设定为 none 喔。
      • option routers 路由器的位址：
        设定路由器的 IP 所在，记得那个‘ routers ’要加 s 才对！
      • option broadcasst-address 广播位址：
        设定广播位址而已。如果没有设定的话，系统应该会自动依据 class A, B, C 的原则来计算出广播位址吧！

    • 动态 IP 分配设定：
      用来设定随机给予 IP 的方式，只要给予网域 (network 以及 netmask) 配合 range 这个参数就能够给予限制的 IP 范围了。 设定方式并不怎么难啊。

    • 静态 IP 的设定方式：
      透过硬体位址 (MAC) 来处理 IP 的取得。使用的是 host 这个设定参数， 配合底下两个常见的参数值来处理：
      • hardware ethernet 硬体位址：
        利用网路卡上面的固定硬体位址来设定，亦即该设定仅针对这个硬体位址有效的意思；
      • fixed-address IP位址：
        给予一个固定的 IP 位址的意思。
    说再多也没有什么用啦！让我们实际来玩一个案例吧！你就知道该如何处理了。

    小标题的图示 一个区域网路的 DHCP 伺服器设定案例
    假设我的环境当中，Linux 伺服器除了 NAT 主机之外还得要负责其他伺服器，例如邮件伺服器的支援。 而在后端区域网路中则想要提供 DHCP 的服务。整个硬体配置的情况如同下图所示：

    区域网路的实体连接情况
    图一、区域网路的实体连接情况

    如上图所示，假设我的 Linux 有两块介面，其中 eth0 对内而 eth1 对外，至于其他的网路参数设计为：
    • 内部网段设定为 192.168.1.0/24 这一段，且 router 为 192.168.1.254 ，此外， DNS 主机的 IP 为中华电信的 168.95.1.1 及 Seednet 的 139.175.10.20 这两个；
    • 我想要让每个使用者预设租约为 3 天，最长为 6 天；
    • 只想要分配的 IP 只有 192.168.1.21 到 192.168.1.100 这几个，其他的 IP 则保留下来；
    • 我还有一部主机，他的 MAC 是‘ 00:40:95:30:43:B4 ’，我要给他的主机名称为 vbird-inside ，且 IP 为 192.168.1.5 这个。
    则我的设定档就会像底下这个样子了：
    [root@linux ~]# vi /etc/dhcpd.conf
# 1. 整体的环境设定
#    当底下的 subnet 与 host 没有设定时，以这里的设定值为准喔！
ddns-update-style               none;          <==不要更新 DDNS 的设定
default-lease-time              259200;        <==预设租约为 3 天
max-lease-time                  518400;        <==最大租约为 6 天
option routers                  192.168.1.254; <==这就是预设路由
option broadcast-address        192.168.1.255; <==这是广播位址啊
option domain-name-servers      168.95.1.1, 139.175.10.20;
# 上面是 DNS 的 IP 设定，这个设定值会修改用户端的 /etc/resolv.conf 档案内容！
# 此外，你可以设定多部 DNS 主机，不过必须要以逗号‘ , ’分隔开才行。

# 2. 关于动态分配的 IP
#     Network_IP↓        Netmask_IP↓
subnet 192.168.1.0 netmask 255.255.255.0 {
    range 192.168.1.21 192.168.1.100;      <==分配的 IP 范围
    option subnet-mask   255.255.255.0; <==可重复设定 netmask 位址
    option nis-domain    "vbird.tsai";  <==额外给的 NIS 相关参数
    option domain-name   "vbird.tsai";  <==在 /etc/resolv.conf 给一个搜寻领域

    # 3. 关于静态的 IP 啊！
    #    主机名称↓
    host vbird-inside {
        hardware ethernet    00:40:95:30:43:B4; <==用户端网卡 MAC
        fixed-address        192.168.1.5;       <==给予固定的 IP
    }
}
# 相关的设定参数意义，请查询前一小节的介绍，或者 man dhcpd.conf
    够简单吧！这样就设定好了！你可以复制上头的资料然后修改一下，让里头的 IP 参数符合你的环境， 就能够设定好你的 DHCP 伺服器了。接下来理论上你就能够启动 dhcp 了。不过，在某些早期的 Linux distribution 上面， 当你的 Linux 主机具有多个介面时，你的一个设定可能会让多个介面同时来监听，那就可能会发生错误了。

    举例来说，我们现在的设定是 192.168.1.0/24 这个在 eth0 上头的网域，假设你还有一个介面 eth1 在 192.168.2.0/24 好了， 那万一你的 DHCP 同时监听两块介面的话，想一想，如果 192.168.2.0/24 网域的用户端发送出 dhcp 封包的要求时， 他会取得什么 IP ？所以啰，我们就得要针对 dhcpd 这个执行档设定他监听的介面， 而不是针对所有的介面都监听啊！您说是吧！^_^！那如何处理呢？在 CentOS (Red Hat 系统) 可以这样做：
    [root@linux ~]# vi /etc/sysconfig/dhcpd
DHCPDARGS="eth0"
    这样做就好了，这是因为启动 dhcpd 的 script 会主动的呼叫这个参数档案。如果是在其他版本的 Linux 当中， 你可以直接修改 /etc/init.d/dhcpd 这个 script 档案内容，找到‘ daemon /usr/sbin/dhcpd ... ’那一行， 并新增网路卡代号即可，例如：
    [root@linux ~]# vi /etc/init.d/dhcpd
# 约在第 58 行左右会找到：
        daemon /usr/sbin/dhcpd ${DHCPDARGS} 2>/dev/null
    在上述的特殊字体部分，你可以持续加入想要增加的监听介面啦！更多的功能可以参考‘ man dhcpd ’的解释。 不过这个动作在较新的版本上面已经不需要了，因为新版本的 dhcp 会主动的分析伺服器的网段与实际的 dhcpd.conf 设定， 如果两者无法吻合，就会有错误提示，人性化多了。 ^_^！ 接下来我们可以开始启动 dhcp 试看看啰！

    小标题的图示 DHCP 伺服器的启动与观察
    开始来启动 dhcp 吧！另外你要注意的是：dhcpd 使用的埠口是 port 67 ，并且启动的结果会记录在 /var/log/messages 档案内，你最好能去观察一下 /var/log/messages 所显示的 dhcpd 相关资讯才好。
    1. 就启动吧！
[root@linux ~]# /etc/init.d/dhcpd start

2. 看看埠口启动的情况
[root@linux ~]# netstat -tlunp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address PID/Program name
udp        0      0 0.0.0.0:67    0.0.0.0:*       7294/dhcpd

3. 看看登录档的输出资讯
[root@linux ~]# tail -n 30 /var/log/messages
Dec 5 10:58 linux dhcpd: Internet Systems Consortium DHCP Server V3.0.1
Dec 5 10:58 linux dhcpd: Copyright 2004 Internet Systems Consortium.
Dec 5 10:58 linux dhcpd: All rights reserved.
Dec 5 10:58 linux dhcpd: For info, please visit http://www.isc.org/sw/dhcp/
Dec 5 10:58 linux dhcpd: Wrote 0 deleted host decls to leases file.
Dec 5 10:58 linux dhcpd: Wrote 0 new dynamic host decls to leases file.
Dec 5 10:58 linux dhcpd: Wrote 0 leases to leases file.
Dec 5 10:58 linux dhcpd: Listening on LPF/eth0/00:40:fa:25:2a:db/192.168.1/24
Dec 5 10:58 linux dhcpd: dhcpd startup succeeded
    看到这些就是成功的象征啦！恭喜你啊！真是‘福气啦！’不过，万一你看到的登录档是类似底下的模样呢？
    Dec 5 11:11 linux dhcpd: /etc/dhcpd.conf line 10: semicolon expected.
Dec 5 11:11 linux dhcpd: subnet
Dec 5 11:11 linux dhcpd: ^
Dec 5 11:11 linux dhcpd: Configuration file errors encountered -- exiting
    这表示应该是第 10 行左右有点问题，问题点应该是没有分号 (semicolon) 而已。而分号应该是在指数符号 (^) 指的地方， 也就是 subnet 附近而已，很容易分辨吧！那如果是出现如下的模样呢？
    ** You must add a ddns-update-style statement to /etc/dhcpd.conf.
   To get the same behaviour as in 3.0b2pl11 and previous
   versions, add a line that says "ddns-update-style ad-hoc;"
   Please read the dhcpd.conf manual page for more information. **
    这表示你忘记在 /etc/dhcpd.conf 里面加入 ddns-update-style 的参数宣告啦！ 瞧一瞧这个输出资讯，就能够晓得你的设定错误所在，根据错误来处理你的 dhcp 设定档吧！

    小标题的图示 内部主机的 IP 对应
    如果您有仔细的瞧过前几章的网路基础的话，那么应该还会记得那个 /etc/hosts 会影响内部电脑的连线速度很大吧！那么我现在使用 DHCP 之后，糟糕！我怎么知道哪一部 PC 连上我的主机，那要怎么填写 /etc/hosts 的内容呢？这真是太简单了！就将所有可能的电脑 IP 都加进去该档案呀！ ^_^ ！以鸟哥为例，在这个例子中，鸟哥的分配的 IP 至少有 192.168.1.5, 192.168.1.21 ~ 192.168.1.100 ，所以 /etc/hosts 可以写成：
    [root@linux ~]# vi /etc/hosts
127.0.0.1　　 localhost.localdomain localhost
192.168.1.254  vbird-server
192.168.1.5　  static-ip
192.168.1.21 　dynamic-021
192.168.1.22 　dynamic-022
.....
192.168.1.100  dynamic-100
    这样一来，所有可能连进来的 IP 都已经有纪录了，哈哈！当然没有什么大问题啰！ ^_^
    大标题的图示 DHCP 用户端的设定
    DHCP 的 Client 端，可以是 Windows 也可以是 Linux 呢！由于鸟哥的领域内刚好有两部 Client 端的电脑，一部为 Linux (CentOS 4.4) 另一部为 Windows xp ，这里就提一下，分别是怎样设定的呢？

    小标题的图示 Linux 用户端
    Linux 的网路参数设定还记得吧？不记得的话就得要打屁股了！在连上 Internet 章节内我们谈过自动取得 IP 的方式，设定真的很简单：
    [root@client ~]# vi /etc/sysconfig/network-scripts/ifcfg-eth0
DEVICE=eth0
BOOTPROTO=dhcp  <==就是他！指定这一个就对了！
ONBOOT=yes

[root@client ~]# /etc/init.d/network restart
    改完之后，就将我们的整个网路重新启动即可 (不要使用 ifdown 与 ifup ，因为还有预设路由要设定！) 。请注意，如果您是在远端进行这个动作，您的连线‘肯定会挂掉！’，因为网路卡被您关了嘛！ 呵呵！所以请在本机前面才进行喔！如果执行的结果有找到正确的 DHCP 主机，那么几个档案可能会被更动喔：
    1. DNS 的 IP 会被更动呢！查阅一下 resolv.conf 先：
[root@linux ~]# cat /etc/resolv.conf
; generated by /sbin/dhclient-script
search vbird.tsai          <==是否记得设定过 domain-name 呢？
nameserver 168.95.1.1      <==这就是我们原本的设定值。
nameserver 139.175.10.20

2. 观察一下路由啦！
[root@linux ~]# route -n
Kernel IP routing table
Destination     Gateway        Genmask        Flags  Iface
192.168.1.0     0.0.0.0        255.255.255.0  U      eth0
169.254.0.0     0.0.0.0        255.255.0.0    U      eth0
0.0.0.0         192.168.1.254  0.0.0.0        UG     eth0
# 嗯！没错！路由也被正确的捉到了！OK的啦！

3. 察看一下用户端的指令吧！
[root@linux ~]# netstat -tlunp
Proto Recv-Q Send-Q Local Address  Foreign Address State  PID/Program name
udp        0      0 0.0.0.0:68     0.0.0.0:*              3996/dhclient
# 你没看错！确实是有个小程式在监测 DHCP 的连线状态呐！

4. 看一看用户端租约所记载的资讯吧！
[root@linux ~]# cat /var/lib/dhcp/dhclient-eth0.leases
lease {
  interface "eth0";
  fixed-address 192.168.1.100;  <==这就是为啥我每次取得的 IP 是固定的。
  option subnet-mask 255.255.255.0;
  option routers 192.168.1.254;
  option dhcp-lease-time 259200;
  option dhcp-message-type 5;
  option domain-name-servers 168.95.1.1,139.175.10.20;
  option dhcp-server-identifier 192.168.1.254;
  option nis-domain "vbird.tsai";
  option broadcast-address 192.168.1.255;
  option domain-name "vbird.tsai";
  renew 3 2006/12/6 18:15:41;   <==下一次预计更新 (renew) 的时间点
  rebind 5 2006/12/8 05:26:26;
  expire 5 2006/12/8 14:26:26;
}
# 这个档案会记录该介面卡所曾经要求过的 DHCP 资讯喔！重要！
# 有没有看出来，他几乎就与你设定的 /etc/dhcpd.conf 类似？ ^_^

5. 额外看一下 NIS 的领域名称有没有设定妥当啊？
[root@linux ~]# nisdomainname
vbird.tsai   <==因为我们有设定 nis-domain 的项目啊！
    有没有发现其实你的用户端取得的资料都被记载在 /var/lib/dhcp/dhclient-eth0.leases 里头啊？ 如果你有多张网卡，那么每张网卡自己的 DHCP 要求就会被写入到不同档名的档案当中去！ 观察该档案就知道你的资料是如何啰！这可也是挺重要的呦！

    小标题的图示 Windows 用户端
    在 Windows 底下设定 DHCP 协定以取得 IP 实在是很简单喔！我们以目前最常用的 Windows XP 来说明的话， 你可以依据‘开始’-->‘设定’-->‘控制台’-->‘网路和网际网路连线’-->‘网路连线’-->‘区域连线’ 来开始一步一步的进行下面的动作喔：
    1. 在点选了上面的区域网路后，你的桌面上应该会出现如下的图示：

      区域网路的 DHCP 取得方式之设定
      图二、区域网路的 DHCP 取得方式之设定

    2. 在上图二的地方按下箭头所指的‘内容’处，就会出现如下画面啰：

      区域网路的 DHCP 取得方式之设定
      图三、区域网路的 DHCP 取得方式之设定

      在上面的画面当中，建议你可以在箭头所指的 1 处勾选那两个项目，如此一来在桌面最底下的右侧就会出现一个网路符号， 以后你就可以点选该图示来进入这个画面了！比较方便啦。然后在箭头 2 的地方勾选 Internet Protocol (TCP/IP) 的项目， 并点选‘内容’后，就可能进入到设定的画面。

    3. 接下来如下图所示，你只要勾选‘自动取得 IP 位址’那个项目，然后按下‘确定’并离开设定画面， 如此一来 Windows 就会开始自动取得 IP 的工作了。

      区域网路的 DHCP 取得方式之设定
      图四、区域网路的 DHCP 取得方式之设定

    4. 那你如何确认你的 IP 已经被顺利的取得呢？如果是在早期的 Windows 95 ，你可以使用一个名为‘ winipcfg ’ 来观察你的 IP 设定。不过在 windows 2000 以后，你可能需要使用命令提示字元来观察才行。你可以使用： ‘开始’-->‘程式集’-->‘附属应用程式’-->‘命令提示字元’来取出终端机，然后这样处理看看：
      C:\Documents and Settings\dmtsai> ipconfig /all
....前面省略....
Ethernet adapter 区域连线:

        Connection-specific DNS Suffix  . : vbird.tsai
        Physical Address. . . . . . . . . : 00-D0-18-AF-6E-81
        Dhcp Enabled. . . . . . . . . . . : Yes
        Autoconfiguration Enabled . . . . : Yes
        IP Address. . . . . . . . . . . . : 192.168.1.99
        Subnet Mask . . . . . . . . . . . : 255.255.255.0
        Default Gateway . . . . . . . . . : 192.168.1.254
        DHCP Server . . . . . . . . . . . : 192.168.1.254  <==这一部 DHCP 主机
        DNS Servers . . . . . . . . . . . : 168.95.1.1
                                            139.175.10.20
        Lease Obtained. . . . . . . . . . : 2006年12月5日 下午 10:22:37
        Lease Expires . . . . . . . . . . : 2006年12月8日 下午 10:22:37

C:\Documents and Settings\dmtsai> ipconfig /renew
# 这样可以立即要求更新 IP 资讯喔！
      这样就 OK 的啦！简单吧！
    大标题的图示 伺服器端资料查阅
    小标题的图示 检查租约档案
    用户端会主动的纪录租约资讯，那主机端更不能忘记记录啰！主机端是记录在这个地方：
    [root@linux ~]# cat /var/lib/dhcp/dhcpd.leases
lease 192.168.1.99 {  <==就是那部 Windows 的纪录
  starts 2 2006/12/05 14:23:37;
  ends 5 2006/12/08 14:23:37;
  binding state active;
  next binding state free;
  hardware ethernet 00-d0-18-af-6e-81;
  uid "\001\000\340\030\257n\003";
  client-hostname "vbird_work";
}
lease 192.168.1.100 { <==就是那部 Linux 的纪录
  starts 2 2006/12/05 15:37:33;
  ends 5 2006/12/08 15:37:33;
  binding state active;
  next binding state free;
  hardware ethernet 00:30:20:1d:c3:6e;
}
    从这个档案里面我们就知道有多少用户端已经向我们申请了 DHCP 的 IP 使用了呢！ 很容易了解吧！

    小标题的图示 使用 ether-wake 实行远端自动开机 (remote boot)
    既然已经知道用户端的 MAC 位址了，如果用户端的主机符合一些电源标准， 并且该用户端主机所使用之网路卡暨主机板支援网路唤醒的功能时，我们就可以透过网路来让用户端电脑开机了。 如果你有一部主机想要让他可以透过网路来启动时，你必须要在这部用户端电脑上进行：
    1. 首先你得要在 BIOS 里面设定‘网路唤醒’的功能，否则是没有用的喔！
    2. 再来你必须要让这部主机接上网路线，并且电源也是接通的。
    3. 将这部主机的 MAC 抄下来，然后关机等待网路唤醒。
    接下来请到永远开着的主机 DHCP 主机上面 (其实只要任何一部 Linux 主机均可！) ， 下载 ether-wake.c 这个档案：
      ftp://ftp.scyld.com/pub/diag/
    然后开始编译他：
    [root@linux ~]# gcc -O -Wall -o ether-wake ether-wake.c
    此时你的家目录下应该会有一个名为 ehter-wake 的档案，假设用户端主机的 MAC 为 11:22:33:44:55:66 好了， 那么你想要让这部主机被唤醒，就这样做吧：
    [root@linux ~]# ./ether-wake 11:22:33:44:55:66

# 更多功能可以这样查阅喔：
[root@linux ~]# ./ether-wake -u
    然后你就会发现，哈哈！那部用户端主机被启动了！以后如果你要连到区域网路内的话， 只要能够连上你的防火墙主机，然后透过这个 ether-wake 软体，就能够让你区域网路内的主机启动了， 控管上面就更加方便的啦！您说是吧！ ^_^
    大标题的图示 重点回顾
    • DHCP (Dynamic Host Configuration Protocol) 可以提供网路参数给用户端电脑，使其自动设定网路的功能；
    • 透过 DHCP 的统一管理，在同一网域当中就比较不容易出现 IP 冲突的情况发生；
    • DHCP 可以透过 MAC 的比对来提供 Static IP (或称为静态 IP)，否则通常提供用户端 dynamic IP (或称为动态 IP)；
    • DHCP 除了 Static IP 与 Dynamic IP 之外，还可以提供租约行为之设定；
    • 在租约期限到期之前，用户端 dhcp 软体即会主动的要求更新 (约 0.5, 0.85 倍租约时间左右)；
    • 用户端离线、不明原因的当机、超过租约期限等机会下，DHCP Server 与用户端的租约行为会终止！
    • DHCP 可以提供的 MAC 比对、Dynamic IP 的 IP 范围以及租约期限等等，都在 dhcpd.conf 这个档案当中设定的；
    • 一般的情况之下，使用者需要自行设定 dhcpd.leases 这个档案，不过，真正的租约档案记录是在 /var/lib/dhcp/dhcpd.leases 里面；
    • 新版的 DHCP 设定档 dhcpd.conf 中，需含有‘ ddns-update-style ’的参数设定；
    • 如果只是要单纯的 DHCP 服务，建议可以购买类似 IP 分享器的设备即可提供稳定且低耗电的网路服务。
    大标题的图示 课后练习
    • DHCP 的主要用途为何？
      • DHCP 主机的主要用途就是在于自动分配网路参数给 Client 端的电脑，以降低网域当中可能发生的 IP 冲突问题，以及减少网管人员到处检查错误的伤脑筋！
    • DHCP 主要的两种 IP 分配模式为何？
      • 主要的两种分配模式分别为 Dynamic IP 与 Static IP ， Static IP 透过 MAC 的比对，至于 Dynamic IP 则是直接取用网域中尚未被使用到的 IP 来进行 Client 端的分配。
    • 在有 DHCP 主机存在的网域当中，且 client 端亦使用 DHCP 来规划用户端的网路参数，那么请问，在该网域当中，Client 端是如何取得 IP 的呢？
      1. 首先， Client 端会发出一个 DHCP 要求封包；
      2. server 端接收到要求后，会主动的回应资讯给 Client ；
      3. Client 若接受该 DHCP 主机所提供的参数，则主机会记录下租约资讯，至于 client 端则开始以主机提供的参数设定其网路
    • DHCP 是如何发送 Static IP 的？可以使用何种指令取得该资讯？
      • DHCP 主要利用网路卡的硬体位址，亦即俗称的‘网路卡卡号’，也就是 MAC 来进行 Client 端的比对的，至于主动取得 Client 端的方式，可以透过 ping 以及 arp 来获得。
    • 在 DHCP 的租约档，亦即 /var/lib/dhcp/dhcpd.leases 当中，记录了什么资讯？
      • 这个档案主要记录了 Client 端连上 Server 端的纪录资料，他会被 DHCP 主机用来判定与 Client 端的租约行为喔！
    • DHCP 的登录档放置于何处？
      • 就是最重要的 /var/log/messages 这个档案啦(预设状况下！)
    大标题的图示 参考资料
    • Linux Magazine：http://www.linux-mag.com/2000-04/networknirvana_01.html
    • DHCP mini HOWTO：
      英文版：http://tldp.org/HOWTO/DHCP/index.html
      中文版：http://www.linux.org.tw/CLDP/MiniHOWTO/network/DHCP/
    • Internet Software consortium：http://www.isc.org/products/DHCP/
    • Study Area：http://www.study-area.org/linux/servers/linux_dhcp.htm
    • Study Area 网路开机(我本善良兄撰写)：http://www.study-area.org/tips/wol.htm
    2002/11/23：第一次完成
    2003/03/15：加入相关重点回顾、与练习题
    2003/09/10：修改版面去！
    2006/12/05：将旧的文章移动到此处
    2006/12/06：好累！怎么老是在说累～总之，完成啰～新增加 ether-wake 的网路唤醒功能。
    2002/11/24以来统计人数


鸟哥的 Linux 私房菜 -- DNS Server

为取得较佳浏览结果，请爱用 firefox 浏览本网页

DNS 伺服器
切换解析度为 800x600
最近更新日期：2007/06/25
我们知道电脑网路系统只认识所谓的 IP ，但是，您可能记得住网路上面所有主机的 IP 吗？ 就鸟哥来说，连自己的主机的 IP 都记不起来了，怎么可能连其他的主机 IP 都记的住！ 因为，人脑对于数字组成的 IP 的记忆实在是......不怎么样。 但是，相对来说，人们对于由文字所组成的主机名称那可以容易记忆的多了～ 所以，才会发展出可以经由主机名称( hostname )对应到电脑 IP 的一个模式，这样我们就可以轻轻松松的记住主机名称即可，电脑 IP 那就交给 Domain Name System ( DNS )去搞定吧！

那个 DNS 系统是由柏克莱大学发展的 bind 这个套件( Berkeley Internet Name Domain )所提供的啦！基本上，DNS 最主要的工作就是将 Hostname 对应到 IP 这个功能了，不过，要架设一个成功的 DNS 主机的话，还得要对于 DNS 的运作很清楚才行啊！否则架设的不对，还反而会造成大家的问题喔！这个章节当中， 要学会的资料其实还蛮多的，需要了解：什么是正解、什么是反解、什么是 Zone、客户端 ( Client ) 是经由什么咚咚来查询得到 IP 的呢？！以及 DNS 的授权问题等等。 哇！赶快清一清脑门，要好好的用功啰！ ^_^

1. 本章的行前准备工作
2. 什么是 DNS ：
    2.1 什么是 Domain Name System
    2.2 DNS 的查询过程
    2.3 关于‘授权’的意义
    2.4 网站代管还是自己设定 DNS
    2.5 正解与反解的 Zone 意义
 3. DNS 伺服器的套件、种类与 cache only 主机设定：
    3.1 架设 DNS 所需要的套件
    3.2 BIND 的预设路径设定与 chroot, /etc/sysconfig/named
    3.3 DNS 的 master/slave 架构
    3.3 单纯的 cache-only 与 forwarding DNS 主机设定
 4. DNS Master 伺服器机的详细设定
    4.1 一个简单案例说明
    4.2 /etc/named.conf 设定档
    4.3 最上层 DNS (root) 资料库档案的设定
    4.4 正解资料库档案的设定： 领域 RR, master/slave RR, 领域解析 NS, 正解标志
    4.5 反解资料库档案的设定： 反解 RR
    4.6 DNS 的启动与观察
    4.7 资料库的更新
    4.8 测试
 5. Master/Slave 架构的详细设定
    5.1 master DNS 权限的开放
    5.2 slave DNS 的设定
 6. Client 端的设定：
    6.1 相关设定档： /etc/hosts, /etc/resolv.conf, /etc/nsswitch.conf
    6.2 DNS 的查询指令： host, nslookup, dig
    6.3 Domain 的资讯查询： whois
 7. DNS 伺服器的进阶设定：
    7.1 子网域授权问题
    7.2 架设一个合法授权的 DNS 主机
    7.3 LAME Server 的问题
    7.4 利用 RNDC 指令管理 DNS 伺服器
    7.5 架设动态 DNS 主机：让你成为 ISP 啦！
 8. 重点回顾
9. 课后练习
10.参考资料
11.针对本文的建议：http://phorum.vbird.org/viewtopic.htm?p=115692
大标题的图示 本章的行前准备工作
人类的脑袋对于数字毕竟不比文字来的敏感，偏偏电脑的世界仅认识 0/1 而已。 为了将两者兜在一起于是有了主机名称与 IP 的对应啊～而这个对应的协定就是 DNS 了。 学习 DNS 你必需要对网路有一定的概念，尤其是主机名称的说明喔！
  • 了解网路基础，防火墙与关闭 SELinux 模组等等。
  • 由于你可能会手动修改 /etc/init.d/named ，所以 shell script 也要了解！
大标题的图示 什么是 DNS
目前的 Internet 世界最常用的还是所谓的 TCP/IP 协定，其中 IP 协定为第四版的 IPv4 。 不过，这个 IPv4 是由 32 个位元 (32 bits) 所组成，为了人脑已经转成四组十进位的数字了， 例如 123.234.56.78 这样的格式。当我们利用 Internet 传送资料的时候， 就需要这个 IP ，否则资料怎么知道要被送到哪里去？
Tips:
传送资料的方法有很多，不见得全部都是透过 IPv4 这个协定，例如在 LAN 里面常用的 NetBIOS 就是一例。 不过，在这里，我们不讨论其他的传输方法，专门探讨 IPv4 这个协定喔！ 		鸟哥的图示
然而人脑对于 IP 这种数字的玩意儿，记忆力实在是不怎么样。但是如上所说， 当我们需要资料传输时，又很需要对方的 IP ，怎么办？为了应付这个问题， 早期的朋友想到一个方法，那就是利用某些特定的档案将主机名称与 IP 作一个对应， 让主机名称与 IP 有关连性，如此一来，我们就可以透过主机名称来取得该主机的 IP 了！ 真是个好主意，因为人类对于名字的记忆力可就好多了！ ^_^y。

可惜的是，该方法还是有缺憾的，那就是主机名称与 IP 的对应无法自动于所有的电脑内更新， 且要加入该对应仅能向 INTERNIC 注册，若 IP 数量太多时，该档案会大到不像话，也就不利于主机同步化了。 而为了填补这个缺憾，柏克莱大学发展出另外一套阶层式管理主机名称对应 IP 的系统， 我们称他为 Berkeley Internet Name Domain, BIND ，这个系统可就优秀的多了～ 透过阶层式管理，可以轻松的进行维护的工作～太棒了！ 这也是目前全世界使用最广泛的领域名称系统(Domain Name System, DNS)哩～ 透过 DNS ，我们不需要知道主机的 IP ，只要知道该主机的名称，就能够轻易的连上该主机了！
Tips:
在底下的说明当中，我们有时会提到 DNS 有时会提到 BIND ，这有什么不同？ 由上面的说明里面，您可以了解到， DNS 是一种网际网路的通讯协定名称， 至于 Bind 则是提供这个 DNS 服务的套件～这样您了解了吗？！ 		鸟哥的图示
那么要立刻来架设 DNS 主机吗？当然不是～如同上面说的，网际网路上面， 资料的传输最重要的就是得要知道对方的 IP，如此才能达成连线。因此， 架设 DNS 就必须要了解整体网际网路的领域名称架构，否则，一旦 DNS 架设错误， 可能会造成您所管辖的主机无法正确的在 Internet 上头传输资料的问题！

所以，要设定 DNS 之前，您必须要就领域名称系统里面惯用的 FQDN、Hostname 与 IP 的查询流程， 正解与反解、合法授权的 DNS 主机之意义，以及 Zone 等等的知识作一个认识才行！ 这可是很重要的，不要轻忽他了！
Tips:
事实上，由于 IPv4 的 IP 数量已经不足了，为了应付未来的网路架构而开发了 IPv6 出来。 但是 IPv6 的‘数字数量’是比 IPv4 要多出好多好多的！可想像的到的是，那时 DNS 可就更重要了！@_@ 		鸟哥的图示
小标题的图示 什么是 Domain Name System：
DNS 的全名是‘ Domain name system ’， 中文译名为‘领域名称系统’， 这个咚咚的用途是什么哇！为什么我们的电脑或者是 Internet 一定需要他 (尤其是以 WWW 的方式来上网时) ？呵呵！ 他最大的用途就是‘造福懒惰与记忆性薄弱的人类～’ 哈哈！没错！为什么说他是造福人类呢？且听鸟哥娓娓道来：

  • /etc/hosts 的历史：
    如同前面以及网路基础章节当中谈到的，IPv4 的 IP 是由 32bits 所组成，转成十进位的话则是四组 0-255 的数字所组成的。 由于不容易记忆，因此就有了主机名称与 IP 对应的想法出来。也就是说， 只要输入一个‘电脑的名字’而我们的系统就会自动的将这个名字转成电脑了解的 IP ！嘿嘿！如此一来，我要记得‘名字’总是比 IP 容易的多了！

    依据这个想法而有了 /etc/hosts 这个档案！例如，只要您输入 ‘ ping -c 5 localhost ’ 您的 Linux 马上可以印出 127.0.0.1 这个 IP ， Why ？您去看一下 /etc/hosts 就知道为什么了！所以啰，只要将您常常上网的‘网址对应的 IP ’写到这个 /etc/hosts 底下，您的 IP 搜寻速度就会快上很多～
    Tips:
    再次强调，在您的私有网域内部，最好将所有的 IP 都写入这个档案中啦！     		鸟哥的图示
  • DNS 的历史：
    早期(大约20~30年前)的电脑可是贵重物资，一般人是可望而不可及的，因为电脑数量太少， 所以使用 /etc/hosts 来记忆这些 IP 与名称的对应还尚可应付。但是在现代， Internet 上面这么多主机，并且常常会突然的‘噗通’又多出一部主机来服务， 那么我们总不能一个一个的将他输入在 /etc/hosts 里面吧？对呀！真不聪明！ 而且也无法立刻让全世界的电脑都同步更新他们自己的 /etc/hosts 档案啊！ 所以后来的这个时候就有所谓的‘领域名称解析系统, DNS’出现啦！

    DNS 服务利用类似树状目录的型态，将主机名称的管理分配在不同层级的 DNS 伺服器当中，经由分层管理，所以每一部主机记忆的资讯就不会很多， 而且若有 IP 异动时也相当容易修改！那么这个 DNS 的功能您知道了吗？对啦！就是‘将电脑主机的名称转译成 IP ’就是了！当然啰，他的额外功能还很多！总之，他的最大功能就是‘ 让有意义的，人类较容易记忆的主机名称(英文字母)，转译成为电脑所熟悉的 IP 位址！ ’

    举个例子来说好了，奇摩雅虎的网站的 IP 是 202.43.195.52 ，所以您可以在您的浏览器上面输入‘ http://202.43.195.52 ’来连上奇摩雅虎！ 不过，我想没有几个人能够将这个 IP 背的起来的吧？反之，我们却都知道奇摩雅虎的网址为 tw.yahoo.com ，那么您只要输入‘ http://tw.yahoo.com ’就可以连上该主机啦！很容易记忆吧！
    /etc/hosts ：直接在 Client 端的档案内输入主机名称对应的 IP 来查询；
    DNS 系统 ：利用额外的DNS服务，让Client端可以透过名称解析来取得目的地主机的IP
  • Fully Qualified Domain Name ( FQDN )
    在提到名称与 IP 的解析流程之前，我们还必需来讨论一下‘什么是 domain name 与 host name？’也就是领域名称与主机名称。 在讨论这个主题之前，我们来聊一聊比较生活化的话题：
    • 网路世界其实有很多人自称为‘鸟哥’的，包括敝人在下小生我啦！那么你怎么知道此鸟哥非彼鸟哥呢？ 这个时候你可以利用每个鸟哥的所在地来作为区分啊，比如说台南的鸟哥与台北的鸟哥等。 那万一台南还有两个人自称鸟哥怎么办？没关系，你还可以依照乡镇来区分呢！比如说台南北区的鸟哥及台南中区的鸟哥。 如果将这个咚咚列出来，就有点像这样：
      鸟哥、北区、台南
      鸟哥、中区、台南
      鸟哥、台北
      ......
      是否就可以分辨他的不同点了呢？呵呵！没错！就是这样！

    • 另外一个例子可以使用电话号码来看，假如高雄有个 1234567 而台南也有个 1234567 ，那么(1)您在高雄直接拨接 1234567 时，他会直接挂入高雄的 1234567 电话中， (2)但如果您要拨到台南去，就得加入(06)这个区码才行！我们就是使用区码来做为辨识之用的！
    是否还不清楚鸟哥要说什么？我们常常会发现主机名称都是 www 的网站，例如 www.gov.tw, www.seednet.net, www.hinet.net 等等，那么我们怎么知道这些 www 名称的主机在不同的地方呢？就需要给他领域名称啰！也就是 gov.tw, seednet.net, hinet.net 等等的不同，所以即使您的主机名称相同，但是只要不是在同一个领域内， 那么就可以被接受啰！

    基本上，我们知道 DNS 是有层级之分的，那么每个层级的 Hostname 与 Domain name 可是不一样的咚咚ㄋㄟ～鸟哥使用我们的主机来加以说明，如下图所示：

    分层次的 DNS 架构
    图一、分层次的 DNS 架构 ( Hostname 与 Domain name )

    在上面的例子当中，由上向下数的第二层里面，那个 .tw 是 domain name ，而 com, edu, gov 则是主机的名称，而在这个主机的名称之管理下，还有其他更小网域的主机， 所以在第三层的时候，基本上，那个 edu.tw 就变成了 domain name 了！而成大与中山的 ncku, nsysu 则成为了 hostname 啰！

    呵呵！以此类推，最后得到我们的主机那个 aerosol 是主机名称，而 domain name 是由 ev.ncku.edu.tw 那个名字所决定的！自然，我们的主机就是让管理 ev.ncku.edu.tw 这个 domain name 的 DNS 伺服器所管理的啰！这样是否了解了 domain name 与 hostname 的不同了呢？
    • 小标题的图示 DNS 的查询过程：
    接下来我们要谈一谈，那么 DNS 的 (1)架构是怎样？ (2)查询原理是怎样？总是要先知道架构才能知道如何查询的呐！所以底下我们先来介绍一下整体的架构。

  • DNS 的架构：
    DNS 层阶概念示意图
    图二、DNS 层阶概念示意图

    上面就是一个简单的 DNS 阶层架构啰，在整个 DNS 系统的最上方一定是 . (小数点) 这个 root 的 DNS 主机，他底下管理的就只有 com, edu, gov, mil, org 与以国家为分类的第二层的主机名称了！这两者称为 Top Level Domains (TLDs) 喔！
    • 一般最上层领域名称 (Generic TLDs)：例如 .com, .org, .gov 等等；
    • 国码最上层领域名称 (Country code TLDs)：例如 .tw, .uk, .jp 等
    例如台湾地区最上层的领域名称是以 .tw 为开头，管理这个领域名称的这部机器的 IP 是在台湾，但是他的记录则是记录在 . (root)那部机器里面的！还有其他的国家的最上层如 .cn 指的是大陆， .de 指的是德国一样！那么每个国家之下记录的主要的下层有哪些领域呢？ 呵呵！主要就是有这六大类：

    名称 | 代表意义
    com | 公司、行号、企业
    org | 组织、机构
    edu | 教育单位
    gov | 政府单位
    net | 网路、通讯
    mil | 军事单位

    其实最早之前在 . (root)之下只有这六大类的 domain name ，但是网路成长的速度太快了，因此后来又多出这些以国码来分的 domain name ，如此一来，在该国家之内，只要向该国家申请 domain name 即可，不需要再到最上层去申请啰！也因此，在这些国码之下，还是有这六大类的 domain name 为主的哩！当然啦，在目前，由于网际网路持续的发烧，说实在的 domain name 实在是有点不太够用，所以又有相当多的领域名称被设计出来，例如目前台湾 ISP 提供的 .idv.tw 的个人网站啦！

    好了，再强调一次， DNS 系统是以所谓的阶层式的管理，所以，请注意喔！那个 .tw 只记录底下那一层的这数个主要的 domain 的主机而已！至于例如 edu.tw 底下还有个 ncku.edu.tw 这部机器，那就直接授权交给 edu.tw 那部机器去管理了！也就是说‘ 每个上一层的 DNS 主机，所记录的资讯，其实只有其下一层的主机名称而已！ ’至于再下一层，则直接‘授权’给下层的某部主机来管理啰！呵呵！所以您就应该会知道 DNS 到底是如何管理的吧！ ^_^

    会这样设定的原因不是没有道理的！ 这样设计的好处就是：每部机器管理的只有下一层的 hostname 对应 IP 而已，所以减少了管理上的困扰！而下层 Client 端如果有问题，只要询问上一层的 DNS server 即可！不需要跨越上层，除错上面也会比较简单呢！

  • DNS 的搜寻流程：
    刚刚说过 DNS 是以类似‘树状目录’ 的型态来进行名称的管理的！所以每一部 DNS 主机都‘仅管理下一层 DNS 主机的名称转译’而已， 至于下层的下层，则‘授权’给下层的 DNS 主机来管理啦！这样说好像很绕口，好吧！我们就以下图来说一说原理啰：

    DNS 主机查询流程示意图
    图三、DNS 主机查询流程示意图

    首先，当您在浏览器的网址列输入 http://aerosol.ev.ncku.edu.tw 时，您的电脑就会依据相关设定( 在 Linux 底下就是利用 /etc/resolv.conf 这个档案 ) 所提供的 DNS 的 IP 去进行连线查询，好了，由于目前最常见的 DNS 主机就属 Hinet 的 168.95.1.1 这个 DNS 了，所以我们就拿他来做例子吧！嗯！这个时候， hinet 的这部主机会这样工作：
    1. 先查看本身有没有纪录：
      刚刚说过啦，由于 DNS 是层阶式的架构，任何一部 DNS 都仅记录下一层里面的主机名称对应的 IP 而已，由于 hinet 并非学术网路里面的主机，所以自然也就没有办法直接提供给 client 端关于 aerosol.ev.ncku.edu.tw 这部机器的 IP 了，所以啦，一般而言，这个时候 168.95.1.1 就会向最顶层，也就是 . (root) 的主机查询 .tw 这部机器的位址；

    2. 向最顶层 ( root )查询：
      由于 168.95.1.1 没有纪录我们主机的 IP ，这个时候他就会向‘最顶层’的 . (root) 这部主机来查询 . (root) 的下一层，也就是 .tw 这部机器的资料了！这个时候， . (root) 就会告诉 168.95.1.1 说‘嘿！您要查 .tw 这个网域的管理者呀？我这里有 .tw 这个网域的管理的主机之 IP 资讯，您可以直接去找他！’；

    3. 向第二层查询：
      168.95.1.1 接着又到 .tw 去查询，而该部机器管理的又仅有 .edu.tw, .com.tw, gov.tw... 那几部主机，经过比对后发现我们要的是 .edu.tw 的网域，所以这个时候 .tw 又告诉 168.95.1.1 说：‘您要去管理 .edu.tw 这个网域的主机那里查询，我有他的 IP ！’；

    4. 向下层持续查询：
      好了，一步一步下来， .edu.tw 可以查到管理 .ncku.edu.tw 的主机 IP ； .ncku.edu.tw 可以查到管理 .ev.ncku.edu.tw 的主机 IP ，而最后我们 aerosol.ev.ncku.edu.tw 就可在管理 .ev.ncku.edu.tw 网域的那部主机的设定纪录当中查询到啦！

    5. 记录暂存记忆体：
      查到了 IP 之后，这部 168.95.1.1 的 DNS 机器总不会在下次有人查询 aerosol.ev.ncku.edu.tw 的时候再跑一次这样的流程吧！粉远粉累的呐！而且也很耗系统的资源与网路的频宽，所以呢， 168.95.1.1 这个 DNS 很聪明的会先记录一份 aerosol.ev.ncku.edu.tw 对应 IP 的资讯在自己的暂存记忆体当中，以方便下一次又有人对同一个主机名称的要求之查询！最后则将结果回报给 client 端！当然啦，那个记忆在 cache 当中的资料，其实是有时间性的，当过了 DNS 设定记忆的时间(通常可能是 24 小时)，那么该记录就会被释放喔！
    由这样的分层负责您发现了什么？嗯！那就是：
    • 当一个‘合法’的 DNS 主机里面的设定修改了之后，来自世界各地任何一个 DNS 的要求，都会正确无误的显示正确的主机名称对应 IP 的资讯，因为他们会一层一层的寻找下来，所以，要找您的主机名称对应的 IP 就一定得要透过您的上层 DNS 主机的纪录才行！所以只要您的主机名字是经过上层‘合法的 DNS’主机的设定的，那么就可以在 Internet 上面被查询到啦！呵呵！很简单维护吧，机动性也很高。

    • 在主机的暂存记忆体记录当中，由于是有时间性的，所以当您的主机名称在 DNS 当中被修改了之后，但是由于之前的旧资讯还记忆在其他的 DNS 主机的暂存记忆体里面，所以啦，可能在别人以非您的 DNS 主机来查询您的主机名称时，就会得到先前的旧资讯，这个时间差不多可能是 10 分钟到 2 天左右，这也是为什么我们常说当您修改了一个 domain name 之后，可能要 2 ~ 3 天后才能全面的启用的缘故啦！

    • 每一部可以记录主机名称与 IP 对应的 DNS 伺服器都可以随意更动他自己的资料库对应， 因此主机名称与网域名称在各个主机底下都不相同。举例来说， idv.tw 是仅有台湾才有这个 idv 的网域～ 因为这个 idv 是由 .tw 所管理的，所以只要台湾 .tw 维护小组同意，就能够建立该网域喔！
    好啦！既然 DNS 这么棒，然后我们又需要架站，所以需要一个主机的名称，因此， 那么我们需要架设 DNS 了吗？当然不是，为什么呢？ 刚刚鸟哥提到了很多次的‘合法’的字眼，因为他就牵涉到‘授权’的问题了！ 我们在前面的‘申请合法的主机名称’当中也提到， 只要主机名称合法即可，不见得需要架设 DNS 的啦！

  • DNS 使用的 port number ：
    好了，既然 DNS 系统使用的是网路的查询，那么自然需要有开 Listen 的 port 啰 ( 监听的埠号 )！没错！很合理！那么 DNS 使用的是那一个 port 呢？那就是 53 这个 port 啦！您可以到您的 Linux 底下的 /etc/services 这个档案看看！搜寻一下 domain 这个关键字，就可以查到 53 这个 port 啦！

    但是这里需要跟大家报告的是，通常， DNS 查询的时候，是以 udp 这个较快速的资料传输协定 (protocol) 来查询的，但是万一没有办法查询到完整的资讯时，就会再次的以 TCP 这个协定来重新查询的！所以启动 DNS 的 daemon (就是 named 啦) 时，会同时启动 TCP 及 udp 的 53 这个 port number 喔！
    • 小标题的图示 关于‘授权’的意义：
    很多朋友都认为‘ 架设 DNS 可以设定主机的名称，而我要架站需要主机有名字，因此一定需要架设 DNS ，只要有 DNS，我的主机就可以有名字了！ ’是这样吗？当然不是！这是错误的观念！怎么说呢？

    从上面图三的图示当中，您应该不难发现，当我要搜寻 aerosol.ev.ncku.edu.tw 主机时，就需要向管理 .ev.ncku.edu.tw 这个网域的那部机器查询才行，而要查询 .ev.ncku.edu.tw 则需要在 .ncku.edu.tw 上面询问才可以！这是因为‘上层 DNS 主机 .ncku.edu.tw 已经将 .ev.ncku.edu.tw 这个网域的管理权 "授权" 给 green.ev.ncku.edu.tw 这部机器，当有人要查询 .ev.ncku.edu.tw 这个网域的主机 IP 时， .ncku.edu.tw 将会把查询的任务直接转给 green.ev.ncku.edu.tw 去管理了！从此， .ncku.edu.tw 这个网域的管理主机，将不会再接管 ev.ncku.edu.tw 这个网域的名称管理！ ’是否很像人类社会的‘授权’的概念？

    也就是说，当您老板充分的‘授权’给您某项工作的时候，从此， 要进行该项工作的任何人，从老板那边知道您才是真正‘有权’的人之后，都必须要向您请示一样！ ^_^！所以啰，如果您要架设 DNS ，而且是可以连上 Internet 上面的 DNS 时，您就必须要透过‘上层 DNS 主机的授权’才行！这是很重要的观念喔！等一下我们在底下会介绍一个如何架设一个 ‘经过合法授权的 DNS 主机’哩！

    其实，如果将上面的话改换成：‘ 我要架站，所以我要让我的主机有一个合法的名字！ ’那样就合理了！怎么说呢？因为我可以请上层 DNS 帮我设定主机名称对应 IP 就可以啦！如此一来，要找我的 hostname 对应 IP 的人，都可以直接在我的上层 DNS 里面找到，根本不需要透过我的 Linux 主机呐！例如鸟哥研究室的 aerosol.ev.ncku.edu.tw 就可以在 green.ev.ncku.edu.tw 这部管理 DNS 的 server 上面找到ㄋㄟ～不必亲自来我的 aerosol.ev.ncku.edu.tw 上面找！

    也就是说，藉由 DNS 系统最大的功能‘主机名称转译成 IP ’ 这个动作，那么您只要向任何一个合法的 DNS 主机申请一个‘主机名称, hostname ’给您的 Linux 主机，让大家都可以藉由该 DNS 主机来查询到您的 Linux 之 IP ，就可以使用该主机名称来架站啦！就是这么简单！

    好了，那么您就应该知道了，要让您的主机名称对应 IP 且让 Internet 上面的电脑都可以查询的到，就需要：
    1. 上层 DNS 的授权让您设定 DNS 主机，或者是；
    2. 直接请上层 DNS 主机来帮您设定！
    这两种模式。举例来说，鸟哥的 Linux 教学网站主机名为 linux.vbird.org ，鸟哥是向上层 .org 的 ISP 注册了 vbird.org 的领域名称，但鸟哥申请的是自己管理 DNS 伺服器，所以我网站的资料库放在哪里呢？

    授权与资料库的差异
    图四、授权与资料库的差异

    看到了吗？vbird.org 是向上层 ISP 注册的，而 ISP 则是提供授权给鸟哥 (NS 的标志)， 至于鸟哥的 linux.vbird.org 则是直接记录在鸟哥的 DNS 伺服器上面。所以，万一鸟哥的 DNS 伺服器挂点， 那么虽然 ISP 有纪录 dns.vbird.org 这一部主机的 IP ，但是大家都无法查到 dns.vbird.org 的 IP 喔！ 为什么呢？瞧一瞧图三啊！因为授权的关系嘛！对于 NS 及 A 标志不熟没关系， 后面就会立刻讲到这个咚咚啰！

    那么哪种模式比较好呢？这没有一定的答案， 底下我们来谈一谈，您比较适合哪一种模式的设定呢？

    小标题的图示 网站代管还是自己设定 DNS：
    如果您曾经申请过 domain name 的话，例如向 Hinet 或 Seednet 等台湾各大主要 ISP 申请 domain name 的话，应该都会知道有两种主要的模式，就是刚刚上头提到的 DNS 授权，或者是直接交给 ISP 来管理。交给 ISP 管理的， 就可以称作是网域名称代管啦！当然啦，如果您是学校单位的话，或者是企业内部的小单位，那么就得请您向上层 DNS 主机的负责人要求啰！无论如何，您只能有两个选择就是了，要不就是请他帮忙您设定好 hostname 对应 IP ，要嘛就是请他直接将某个 domain name 段授权给您做为 DNS 的主要管理网域。

    那么我怎么知道那个方式对我比较好呢？请注意，由于 DNS 架设之后，会多出一个监听的 port ，所以理论上，是比较不安全的！因此，能不设当然就不要设定比较好啰！所以，这里的建议如下：

  • 需要架设 DNS 的时机：
    • 您所负责需要连上 Internet 的主机数量庞大：例如您一个人负责整个公司十几部的网路 Server ，而这些 Server 都是挂载您的公司网域之下的。这个时候想要不架设 DNS 也粉难啦！
    • 您可能需要时常修改您 Server 的名字，或者是您的 Server 有随时增加的可能性与变动性；
  • 不需要架设 DNS 的时机：
    • 网路主机数量很少：例如家里或公司只有需要一部 mail server 时；
    • 您可以直接请上层 DNS 主机管理员帮您设定好 Hostname 的对应时；
    • 您对于 DNS 的认知不足时，如果架设反而容易造成网路不通的情况；
    • 架设 DNS 的费用很高时！
    • 小标题的图示 正解与反解的 Zone 意义：
    讲了这许多，还得再提一提关于正解、反解与 Zone 的问题才行啊！

  • 什么是正解与反解？
    我们在前头的开宗明义当中就提到啦， DNS 系统本来最主要的功能就是在转译 hostname 与 IP 啰，由于电脑在网路上面其实认识的只是 IP 啦，所以，一般来说，我们称‘由 hostname 去寻找出 IP 的程序称为‘ 正解 ’’， 至于由 IP 去查询得到 hostname 那就被称为反解了！正反解的设定情况是差异性很大的！怎么说呢？
    • 正解：
      在正解的情况之下，我们可以透过主机分层设定的方式来查询 (例如前面的图三)，而因为是 Hostname 对应 IP ，所以即使在不同网段的 IP ，仍然可以写在同一个 domain 之中！例如鸟哥的主机是在学校里面 (140.116.xxx.xxx)，但是鸟哥申请的是 vbird.idv.tw 这个 domain 的名称，而很多朋友则是以 ISP 提供的 IP (例如 61.xxx.xxx.xxx) 来进行 *.idv.tw 的申请的！呵呵！那么一来，我的 vbird.idv.tw 就与大家的 *.idv.tw 在同一个 domain 的设定当中啰，但是这些主机却是在不同的网域之中喔 (140.116.xxx.xxx 不会跟 61.xxx.xxx.xxx 在同一个网段中吧！ ^_^) ！所以啰，任何一部 DNS 都可以将您的 IP 写入他们的正解当中啰！

    • 反解：
      但是反之则不行！怎么说呢？因为当初 IP 规划分配的时候，就必需要一个区域一个区域的划分的，所以当然不可能同一个网段的 IP 在不同的地方出现吧！因为这涉及到 TCP/IP 的协定与 router 的架构ㄋㄟ～因此，同一个 IP 网段的反解就真的得要透过上层 IP 网域的 DNS 伺服器设定才行了！所以由 IP 反查 hostname 的话，大部分的情况下就需要向直属的上层 IP 网域申请了！
    举个例子来说：我想要自己的领域名称的名字，所以我可以去外面的 ISP 申请注册一个合法的名字来架设我的 DNS ！从此之后，别人就可以经过我的 DNS 正解查询得到我的主机 IP。但是如果要由 IP 反查回 hostname 的话，我就‘一定必需要’请管理我主机所在网域的上层的 DNS 管理员来设定才行ㄋㄟ！这也是目前比较麻烦的地方，因为正解您可以自行设定， 但是反解则必需要请上层的管理员设定！如果是向 ISP 申请的 IP ，那就得向 ISP 申请反解名称改换，这个部分通常很麻烦～

  • 什么是 Zone ？
    知道正反解之后，再来要来知道一下，什么又是 Zone (区域) 呢？说的简单一点的话，一个正解或反解的设定就是一个 zone ，例如我要规范 vbird.idv.tw 这个 domain 的设定内容，那么他就是一个 zone ！通常，‘一个设定档就是一个 zone ’！ 如果以鸟哥的 vbird.idv.tw 这个例子来说，配合上面的 图三 来说明， 那鸟哥的 vbird.idv.tw 那部主机里面至少需要知道 . (root) 以及鸟哥自身的设定， 所以，这个 domain 的 DNS 设定档里面，必需要有：
    • hint( root ) 的设定；
    • vbird.idv.tw 这个 domain 的正解设定；
    • localhost 的正解设定(非必要)；
    • localhost 的反解设定(非必要)。
    那么我就有四个 zone 了！如果以我们系馆的 DNS 主机 green.ev.ncku.edu.tw 来说的话，他至少要有：
    • hint(root)；
    • ev.ncku.edu.tw 正解；
    • ev.ncku.edu.tw 反解以及 ；
    • localhost 正解；
    • localhost 反解。
    等五个 zone 的定义啰！嘿！您会发现，我没有 vbird.idv.tw 这个 domain 的反解设定～为什么呢？请参考上面的说明吧！因为反解需要要求 IP 协定的上层来设定才行！并且，需要特别留意的是，‘每一个 zone 都有一个设定档，而规定这些设定档档名的，就交给 /etc/named.conf 这个参数档来设定！’
    Tips:
    在新版的 Linux distribution 当中，为了安全性的考量， 所以将这个档案放置在 /var/named/chroot 当中喔！需要特别注意！     		鸟哥的图示
    也就是说， DNS server 使用的 bind 这个套件中，他的主要参数档是 /etc/named.conf ，而这个档案当中就是记录了每一个 zone 的设定档档名！实际上，主机名称与 IP 的对应就是记录在各个 zone 的设定档内～

  • 正反解一定要成套吗？
    好了，正反解需不需要成套产生，在这里不用多说明了吧？ ^_^！请注意喔，在很多的情况下，尤其是目前好多莫名其妙的领域名称产生出来， 所以，常常会只有正解的设定需求而已。不过也不需要太过担心啦， 因为通常在反查的情况中，如果您是使用目前台湾地区最流行的 ADSL 上网的话，那么 ISP 早就已经帮您设定好反解了！例如：211.74.253.91这个 seednet 的浮动式 IP 反查的结果会得到 91.253.74.211.in-addr.arpa 这样的主机名称！所以在一般我们自行申请领域名称的时候，您只要担心正解的设定即可！ 不然的话，反正反解的授权根本也不会开放给您，您自己设定得很高兴也没有用呀！ ^_^
    Tips:
    事实上，需要正反解成对的大概仅有 mail server 才需要吧！由于目前网路频宽老是被垃圾、广告邮件占光， 所以 Internet 的社会对于合法的 mail server 规定也就越来越严格。如果您想要架设 mail server 时， 最好具有固定 IP ，这样才能向你的 ISP 要求设定反解喔！以 hinet 为例的反解申请：
    http://hidomain.hinet.net/top1.html     		鸟哥的图示
    • 大标题的图示 DNS 伺服器的套件、种类与 cache only 主机设定：
    谈完了一些基础概念后，接下来让我们来聊一聊，那如何设定好 DNS 伺服器啊？ 这当然就得由套件安装谈起啦！赶紧来玩一玩吧！

    小标题的图示 架设 DNS 所需要的套件：
    终于废话都说完了！相信您大概也有点累的吧？鸟哥是蛮累的啦，因为手臂、 肩颈酸痛的毛病颇严重....咦！讲这个干嘛？ @_@ 好啦，我们终于要来安装 DNS 所需要的套件了！还记得前面提过的，我们要使用的 DNS 就是使用柏克莱大学发展出来的 BIND (Berkeley Internet Name Domain, BIND) 这个套件啦！那么怎么知道您安装了没？还记得 基础篇 里面的 RPM 吗？对啦！就是使用 RPM 来检验啰：
    [root@linux ~]# rpm -qa | grep bind
bind-utils-9.2.4-16.EL4    <==这个是用户端搜寻主机名称的相关指令
bind-9.2.4-16.EL4          <==这个才是 DNS 伺服器主程式
bind-chroot-9.2.4-16.EL4   <==将 bind 主程式关在家里面！ ^_^
    万一没装怎么办？嗄！还问我ㄌㄟ～赶快将您的原版光碟拿出来，然后将他安装上去先～不会安装？ 请自行拿出‘鸟哥的 Linux 私房菜 -- 基础学习篇’去观察一下 RPM 的用法吧！ 当然啦，更好的作法就是利用 yum install bind 即可啊！

    此外，那个 bind-chroot 是干嘛用的？所谓的 chroot 代表的是‘ change to root ’的意思， 那个 root 代表的是根目录。早期的 bind 预设将程序启动在 /var/named 当中，但是该程序可以在根目录到处转移， 因此若 bind 的程式有问题时，则该程序会造成整个系统的危害。为避免这个问题， 所以我们将某个目录指定为 bind 程式的根目录，由于是根目录， 所以 bind 便不能离开该目录！所以如果该程序被攻击，了不起也是在某个特定目录底下搞破坏而已。 CentOS 预设将 bind 锁在 /var/named/chroot 目录中喔！ ^_^

    小标题的图示 BIND 的预设路径设定与 chroot
    好了，现在我们知道 BIND 这个 DNS 伺服器的设定需要有
    • 本身的设定档：主要规范主机的设定、zone file 的所在、权限的设定等；
    • 资料库档案：记录主机名称与 IP 对应的等。
    其中 BIND 的设定档为 /etc/named.conf ，而在这个档案里面可以规范 zone file 的完整档名喔！ 也就是说，你的 zone file 其实是由 /etc/named.conf 所指定的，所以 zone file 档名可以随便取啦！ 只要 /etc/named.conf 内规范为正确即可。一般来说， CentOS 的预设目录是这样的：
    • /etc/named.conf ：这就是我们的设定档啦！
    • /etc/sysconfig/named ：是否启动 chroot 及额外的参数，就由这个档案控制；
    • /var/named/ ：资料库档案预设放置在这个目录
    • /var/run/named ：named 这支程式执行时预设放置 pid-file 在此目录内。
    不过，为了系统的安全性考量，一般来说目前各主要 distributions 都已经自动的将你的 bind 相关程式给他 chroot 了！ 那你如何知道你 chroot 所指定的目录在哪里呢？就是上面提到的那个 /etc/sysconfig/named 啦！ 你可以先查阅一下：
    [root@linux ~]# vi /etc/sysconfig/named
ROOTDIR=/var/named/chroot
    事实上里面有意义的就只有上面这一行，意思是说：‘我要将 named 给他 chroot ，并且变更的根目录为 /var/named/chroot ’喔！由于根目录已经被变更到 /var/named/chroot 了，但 bind 的相关程式是需要 /etc, /var/named, /var/run .... 等目录的，所以实际上咱们 bind 的相关程式所需要的所有资料会是在：
    • /var/named/chroot/etc/named.conf
    • /var/named/chroot/var/named/zone_file1
    • /var/named/chroot/var/named/zone_file.....
    • /var/named/chroot/var/run/named/...
    哇！真是好麻烦～不过，不要太担心！因为新版本的 distributions 通常帮您作好一些连结对应了！ 举例来说，你依旧可以使用 /etc/named.conf 来设定你的 DNS ，为什么呢？因为 CentOS 主动的帮你将 /var/named/chroot/etc/named.conf 连结到 /etc/named.conf 啰！ 另外，绝大部分预设的 zone file 资料库档案也都主动的帮你做好连结了！请自行进入 /var/named 去 ls 一下吧！ ^_^
    Tips:
    事实上， /etc/sysconfig/named 是由 /etc/init.d/named 启动时所读入的， 所以你也可以直接修改 /etc/init.d/named 这个 script 哩！     		鸟哥的图示
    另外你需要注意到的是 /var/run/named/ 这个目录是要让 bind 的程式 (named) 写入用的， 所以他的权限必需要让 named 这个使用者可以写入才行！这个可重要的很！

  • BIND 的升级：
    必须请大家注意的是，这个 DNS 的 53 port 其实也不是个很安全的咚咚，所以呢，非必要，其实是不太建议启用 DNS 的啦！不过，如果真的要安装的话，那么请随时注意您的 Linux distribution 是否有定时的公告的漏洞修补套件呢？这个真的很重要，因为鸟哥很久很久以前，就是被这个 port 53 给种植了一个蠕虫，真是讨厌的很！ @_@

    另外，旧版的使用者使用新的 9.x 版以后的 BIND 时，由于主动帮你设定好 chroot ， 你可能一开始会不太适应，不过，不建议你拿掉 chroot 的功能！毕竟 DNS 的 port 53 是需要 root 身份启动的， 具有一定的危险性，所以，给他 chroot 毕竟是比较妥当啦！您说是吧！
    • 小标题的图示 DNS 的 master/slave 架构
    在 DNS 的设定上面，基本上，您必须要已经很清楚 zone 是什么了，否则很难继续设定喔！会搞的一塌糊涂的～无论如何，您一定要知道的是， bind 的设定档，就是 /etc/named.conf。 不过，由于 chroot 的关系，这个档案也可能会在 /var/named/chroot/etc/ 当中， 另外，针对 DNS server 的类型大致上可以分为三类，分别是：

  • Master：
    这种类型的 DNS 本身含有领域名称的设定档 (就是有 Zone 啦！)， 这个设定档就是设定正解或者是反解的‘Database’啰！所以他本身是具有提供 Internet 查询所需的资料喔！例如我可以在我的主机上面设定提供 vbird.idv.tw 这个网域，那么我的主机就是 master 类型的主机啦！

  • Slave：
    假设你的 DNS 伺服器总共管理 50 部主机的 IP 与主机名称的对应好了， 同时假设你只有一部 DNS 伺服器时，那么万一由于网路问题或者是主机的软、硬体问题，导致这个服务终止了， 想一想，你那 50 部主机的 hostname 与 IP 的对应还能不能找的到？是吧！ 所以，一般来说， DNS 系统通常会建议您至少要有两部主机提供 DNS 的服务～

    不过，如果您有四部 DNS 主机提供这样的名称解析服务， 而且这四部是互相为备援的，也就是说，这四部主机的内容其实是一模一样的， 那么如果您要更动一个 IP 与名称的对应时，就必须要手动去修订四部主机的内容， 这样会不会很麻烦啊？！

    这个时候就有 slave 类型的 DNS 主机出现了！不过，slave主机必须要与 master 主机相互搭配喔！ 以上面的案例来说明，如果我必须要有四部主机提供 DNS 服务，且四部内容相同， 那么我只要指定一部主机为 Master ，其他三部为该 Master 的 Slave 主机， 那么当要修改一部名称对应时，我只要手动更改 master 那部机器的设定档，然后， 重新启动 BIND 这个服务后，呵呵！其他三部 slave 就会自动的被通知更新了！ 这样一来，在维护上面可就轻松写意的多了～
    Tips:
    如果您设定 Master/Slave 架构时，您的 Master 主机必须要限制 只有某些特定 IP 的主机能够取得您 Master 主机的正反解资料库权限才好！ 所以，上面才会提到 Master/Slave 必须要互相搭配才行！     		鸟哥的图示
    另外，既然我的所有 DNS 伺服器是需要同时提供 internet 上面的领域名称解析的服务， 所以不论是 Master 还是 Slave 主机，他都必须要可以同时提供 DNS 的服务才好！ 因为在 DNS 系统当中，领域名称的查询是‘先抢先赢’的状态， 我们不会晓得哪一部主机的资料会先被查询到的！ 为了提供良好的 DNS 服务，每部 DNS 主机都要能正常工作才好啊！ 而且，每一部 DNS 伺服器的资料库内容需要完全一致，否则就会造成用户端找到的 IP 是错误的！

  • Cache-only：
    这种类型的 DNS 主机没有自己的资料库，单纯仅帮助 Client 端向外部的 DNS 主机要求资料而已～简单的来说，他可以想成是一个‘代理人’的角色而已～ 通常设定在防火墙上面的呢！

    那么 Master/Slave 的资料更新到底是如何动作的呢？请注意，Slave 是需要更新来自 Master 的 DNS 资料啊！所以当然 Slave 在设定之初就需要存在 Master 才行喔！好了， Master 与 Slave 的资料同步动作可以由底下的图示来看：

    Master/Slave 的 DNS 主机资料同步过程
    图五、Master/Slave 的 DNS 主机资料同步过程

    整个更新的过程是这样的：
    1. Slave 判断是否需要更新(1.1)：
      我们可以在 Slave 设定好向 Master DNS 主机要求资料更新的周期时间，则每当到达更新时间时， Slave 会向 Master 索取是否需要更新资料，这个更新资料的判断则以 Serial number 是否不同来进行更新喔！

    2. Master 判断是否需要更新(1.2)：
      除了由 Slave 向 Master 的查询之外，Master 如果 DNS 资料经过变更，且想要 Slave 同步更新时，也可以主动的向 Slave 进行更新通知！

    3. 资料同步化(2)：
      最后当然就是资料由 Master 传送到 Slave 来更新 Slave 的 DNS 资料啰！
    如果您想要架设 Master/Slave 的 DNS 架构时，两部主机 (Master/Slave) 都需要您能够掌控才行！网路上很多的文件在这个地方都有点‘闪失’， 请特别的留意啊！

    底下我们就先来讲一个不需要资料库档案的 cache only 的 DNS 伺服器吧！

    • 小标题的图示 单纯的 cache-only 与 forwarding DNS 主机设定
  • 什么是 cache-only 与 forwarding DNS 的主机呢？
    • 在介绍怎么设定每一个正反解的 zone 之前，我们先来玩一个简单的 DNS 主机！就是 cache-only (仅快取) DNS server！顾名思义，这个 DNS server 只有 cache (快取) 的功能，也就是说，他本身并没有主机名称与 IP 正反解的设定档， 完全是由对外的查询来提供他的资料来源！

    至于 forwarding (转递) 的 DNS server 则是将用户端所需要查询的资讯转交给 forwarding DNS server 来代为查询， 等到查询结束后，我们的 DNS server 才将结果快取后回传给用户端。这两者的整个运作流程可以看成是这个样子：

    Cache-Only 与 Forwarding DNS 主机的运作流程
    图六、Cache-Only 与 Forwarding DNS 主机的运作流程

    观察一下图六上下两个图示，你可以发现 cache-only 需要知道 . (root) DNS 的位址， 所以 cache-only 必须要指定出 . (root) DNS 的资料库所在档案才行。至于 Forwarding DNS 主机， 他是直接将查询的资料丢给另一部上层 DNS 来查询，本身可以不必知道 . (root) DNS 的位址！ 一般来说，如果你的环境需要架设一个 cache-only 的 DNS server 时，其实可以直接使用 forwarding 的机制， 选择的那部 DNS 主机流量要能够负荷较大流量为佳！

    要注意的是，不论是 cache-only 还是 forwarding DNS 主机，他们本身都没有管理 zone (那个 root DNS 例外) 的设定档， 所以说，基本上这两个 DNS 主机只是作为一个中间传递资料的角色罢了！那么为什么要架设这样的一个 DNS 主机呢？闲闲没事干？当然不是！这是有原因的啦！底下说给您听啰！

  • 什么时候使用 cache-only DNS？
    • 在某些公司行号里头，为了预防员工利用公司的网路资源作自己的事情，所以都会针对 Internet 的连线作比较严格的限制。当然啦，连 port 53 这个 DNS 会用到的 port 也可能会被挡在防火墙之外的～这个时候， 您可以在‘防火墙的那部机器上面，加装一个 cache-only 的 DNS 服务！’这是什么意思呢？很简单啊！就是您自己利用自己的 防火墙主机上的 DNS 服务去帮您的 Client 端解译 hostname <--> IP 啰！因为防火墙主机 可以设定放行自己的 DNS 功能，而 Client 端就设定该防火墙 IP 为 DNS 主机的 IP 即可！ 哈哈！这样就可以取得主机名称与 IP 的转译啦！

    那如何在你的 Linux 主机上架设一个 cache-only 的 DNS 主机呢？ 其实真的很简单的啦！因为不需要设定正反解的 Zone ，所以只要设定一个档案 (就是 named.conf) 即可！真是快乐得不得了呐！ 另外，Cache-only 只要加上个 Forwarders 的设定即可指定 Forwarding 的资料， 所以底下我们将设定具有 Forwarding 的 cache-only DNS 伺服器吧！

    1. 编辑主要设定档 /etc/named.conf
      在这个档案中，主要是定义跟主机有关的事项，以及各个 Zone 的代表含意与档案，在鸟哥的这个案例当中， 因为使用了 forward 的机制，所以鸟哥的这个 cache-only DNS 伺服器并没有 Zone ，所以我们只要设定好跟主机有关的设定即可。设定这个档案的时候请注意：

      • 注解资料是以两条斜线‘ // ’来作设定的！
      • 每个段落之后都需要以‘ ; ’来做为结尾！

      那么您可以这样设定这个档案啦！
      [root@linux ~]# vi /etc/named.conf
// 虽然 CentOS 将这个档案放置到 /var/named/chroot/etc 当中，
// 不过他很好心的帮我们作了个连结，所以你还是可以直接编辑这个档案啦！
options {
        directory "/var/named";
        dump-file "/var/named/data/cache_dump.db";
        statistics-file "/var/named/data/named_stats.txt";
        pid-file "/var/run/named/named.pid";
        forward only;            //只允许 forward!
        forwarders {
                168.95.1.1;      //我这里使用 hinet 的 DNS ！
                139.175.10.20;   //这个是 seednet 的 DNS ！
        };
};
include "/etc/rndc.key";
      鸟哥在上头的设定当中含有 pid-file 的设定，所以得要特别注意了！因为 pid-file 所在的目录下，也就是那个 /var/run/named 目录，我的 bind 执行档程序的拥有人 (一般应该是 named 这个使用者) 必须要 能够写入！也就是说， /var/run/named 的 owner 必须 是 named 这个 user 才行喔！但由于我们有使用 chroot ， 因此实际的目录会是 /var/named/chroot/var/run/named 喔！所以你还得要这样确认：
      [root@linux ~]# ls -ald /var/named/chroot/var/run/named
drwxrwx---  2 named named 4096 Oct 12 11:48 /var/named/chroot/var/run/named
      我们仅动用到 option 这个参数而已，里面的设定值意义为：

      • pid-file
        指的是每一个 services 记录自己的 PID (Process ID) 的档案啰！这个档案通常用在重新启动或者是 reload 整个 services 最常被使用到的！因为可以使用 kill -1 PID 来重新启动啊！嗄！忘记什么是 PID ？赶快拿出基础篇复习一下！

      • forwarders
        (不要忘记那个 s 喔！)就是要设定往前寻找的那个‘合法’的 DNS 啰！每一个 forward 的主机之 IP 都需要有‘ ; ’来做为结尾！

      • forward only
        这个设定可以让您的 DNS 主机仅进行 forward 而已！是 Cache-Only 主机最常见的设定了！

      很简单吧！至于更多的参数我们会在后续篇幅当中慢慢介绍的。 这样就已经设定完成了最简单的 cache-only 的 DNS 主机了！

    2. 启动 named
      启动总不会忘记吧！？赶快去启动一下吧！
      [root@linux ~]# /etc/init.d/named start
Starting named:                     [  OK  ]

    3. 观察 port 的变化
      请特别的注意喔！并不是启动的时候显示 OK 你的 DNS 就会成功的！所以，还要赶快的来看一下您的 port 53 有没有启动ㄋㄟ～
      [root@linux ~]# netstat -utln
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address        Foreign Address     State
tcp        0      0 192.168.1.254:53     0.0.0.0:*           LISTEN
tcp        0      0 127.0.0.1:53         0.0.0.0:*           LISTEN
udp        0      0 192.168.1.254:53     0.0.0.0:*
udp        0      0 127.0.0.1:53         0.0.0.0:*
      特别需要留意的是，如果没有指定介面的话，那么所有的网路介面，包含 lo, eth0, ... 等介面都会被设定为可以接受 domain name 要求的回应介面！此外， 还记得我们在前面提到的，每个介面同时都会提供 TCP 与 UDP 封包的服务喔！ 这样看起来似乎真的有启动的样子，不过，我们还是得瞧一瞧设定方面有没有什么大问题呢？

    4. 检查 /var/log/messages 的内容讯息
      named 这个服务的记录档就直接给他放置在 /var/log/messages 里面啦，所以来看看里面的几行吧！
      [root@linux ~]# tail -n 15 /var/log/messages | grep named
Oct 16 15:08 linux named[76]: starting BIND 9.2.4 -u named -t /var/named/chroot
Oct 16 15:08 linux named[76]: using 1 CPU
Oct 16 15:08 linux named[76]: loading configuration from '/etc/named.conf'
Oct 16 15:08 linux named[76]: listening on IPv4 interface lo, 127.0.0.1#53
Oct 16 15:08 linux named[76]: listening on IPv4 interface eth0, 192.168.1.254#53
Oct 16 15:08 linux named[76]: command channel listening on 127.0.0.1#953
Oct 16 15:08 linux named[76]: command channel listening on ::1#953
Oct 16 15:08 linux named[76]: running
Oct 16 15:08 linux named: named startup succeeded
      Tips:
      如果你在 /var/log/messages 里面一直看到这样的错误资讯：
      couldn't add command channel 127.0.0.1#953: not found
      那表示你还必需要加入 rndc key ，请参考本章后面的 利用 RNDC 指令管理 DNS 伺服器 的介绍，将他加入你的 named.conf 中！       		鸟哥的图示
      由上面第一行出现的那个‘ -t ... ’可以了解到 chroot 的主要目录啦！你可以使用 man named 去查阅一番。 呵呵！看起来似乎是没有问题的样子了！那么就直接来测试看看吧！

    5. 测试：
      这部分请参考： Client 端的测试项目

  • 特别说明：Forwarders 的好处与问题分析
    • 关于 forwarder 的好处与坏处，其实有很多种的意见！大致的意见可分为这两派：
    • 利用 Forwarder 的功能来增进效能的理论：
      这些朋友们认为，当很多的下层 DNS 主机都使用 forwarder 时， 那么那个被设定为 forwarder 的主机，由于会记录很多的资讯记录(请参考图三的说明)， 因此，对于那些下层的 DNS 主机而言，会增快很多，亦即会节省很多的查询时间！基本上，这些基本的流程可以看成如下图所示：

      Forwarder 参数的运作说明
      图七、Forwarder 参数的运作说明

      所有的 cache-only 都设定 forwarder 为‘主 DNS 主机’那一部，则由于主 DNS 主机已经记录了较多的资讯了(每个人都来要求嘛！)所以，当其他人来要求相同的查询资料时，则主 DNS 那部机器将会直接由其 cache 当中读取，因此，查询效率就变快了！

    • 利用 Forwarder 反而会使整体的效能降低：
      但是另外一派则持相反的见解！这是因为当主 DNS 本身的‘业务量’就很繁忙的时候，那么您的 cache-only 主机还向他要求资料，那么因为他的资料传输量太大，频宽方面可能负荷不量，而太多的下层 DNS 又向他要求资料，所以他的查询速度会变慢！因为查询速度变慢了，而您的 cache-only 主机又是向他提出要求的，所以自然两边的查询速度就会同步下降！
    很多种说法啦！鸟哥本人也觉得很有趣哩！只是不知道哪一派较正确就是了 >_<"" ，不过可以知道的是，如果上层的 DNS 速度很快的话，那么他被设定为 forwarder 时，或许真的可以增加不少效能哩！
    大标题的图示 DNS 主机的详细设定：
    好了，经过上面的说明后，我们大概知道 DNS 的几个小细节是这样的：
    1. 主要设定档是 /etc/named.conf；
    2. 每个正解、反解都需要一个档案，而档案的档名是由 /etc/named.conf 所设定；
    3. 目前的 bind 程式已经进行 chroot 了，可以参考 /etc/sysconfig/named ；
    4. 当 DNS 查询时，若本身没有资料库，则前往 root (.) 或 forwarders 主机查询；
    5. DNS 伺服器的架设需要上层 DNS 的授权才可以成为合法的 DNS 伺服器。
    6. named 是否启动成功务必要查阅 /var/log/messages 内的资讯！
    其中第五点很重要，因为我们并没有向上层 ISP 注册合法的领域名称，所以我们当然就没有权利架设合法的 DNS 伺服器了。 而由于担心我们的 DNS 伺服器会与外部网际网路环境互相干扰，所以底下鸟哥将主要以一个 vbird.tsai 的领域名称来架设 DNS 伺服器，如此一来咱们就可以好好的玩一玩自己区域网路内的 DNS 啦！

    另外，那个 chroot 是很重要的观念，如果你是跳到这个地方来看或者是以前使用的是旧版的 bind 的话，那么请再次阅读一下前两小节谈到的 bind 的 chroot 部分喔！ 底下的文章就不再提及这些基础观念啦！

    小标题的图示 一个简单的案例说明
    假设鸟哥的这部 DNS 伺服器将针对 vbird.tsai 这个领域来设计，并且对应的反解为 192.168.1.0/24 这个网域，另外我也针对本机 localhost 以及 127.0.0.1 这个预设的领域来对应喔！此外， 当然要包含最上层 (root, .) 这个领域的主机名称资料库才行！ 所以我的设定档及正反解 zone 的资料库档案应该有：
    1. named.conf       ：设定档
    2. named.vbird.tsai ：vbird.tsai 的正解
    3. named.192.168.1  ：192.168.1.0/24 的反解
    4. named.root       ：root (.) 的资料库
    5. named.localhost  ：localhost 的正解
    6. named.127.0.0    ：127.0.0.1/24 的反解
    如果我还想要加入其他的领域，例如 niki.tsai 可不可以啊？当然可以啊！就再多一个资料库正解档案即可！ 还有，鸟哥上头这个设定资料为内部私有的，所以你可以完全照着玩！并不会影响到外部的网际网路啦！ 只是，你的 DNS 设定网际网路也查不到就是了～反正是练功嘛！^_^

    至于资料库的对应方面，鸟哥预计的规划是这样的：

    作业系统与 IP | 对应之主机名称 | 说明
OS: Linux IP: 192.168.1.254 | linux.vbird.tsai www.vbird.tsai ftp.vbird.tsai forum.vbird.tsai | 这部是主要的 DNS 伺服器，主要主机名称为 linux.vbird.tsai ，其他的三部主机名称为主机别名。
OS: Linux IP: 192.168.1.150 | slave.vbird.tsai | 主要作为 slave DNS 主机， 相关的 slave 设定将在下个小节才会介绍的啦！
OS: Windows XP IP: 192.168.1.100 | winxp.vbird.tsai | 某一部主机的 IP 与主机名称对应
OS: Sun IP: 192.168.1.200 | sun.vbird.tsai | 某一部主机，用来玩的而已！

    请特别留意啊，一个 IP 可以对应给多个主机名称，同样的，一个主机名称可以给予多个 IP 喔！ 主要是因为那部 linux.vbird.tsai 的机器未来的用途相当的多， 鸟哥希望那一部主机有多个名称，以方便未来额外的规划啊，所以就对该 IP 对应了四个主机名称啊！

    小标题的图示 /etc/named.conf 设定档
    这个设定档是整个 Linux 上 DNS 的核心啦！他最主要就是在：
    • 规范 DNS 伺服器的使用权限 (可否查询、forward 与否、master/slave 架构等)；
    • 设定出 zone (domain name) 以及 zone file 的所在；
    • 设定 DNS 本机管理介面以及其相关的金钥档案 (key file)。
    基本上，这个档案的内容主要就是分为上头的三大部分啦！至于设定方面你要注意的有：
    • 在整体伺服器的环境与使用权限方面，主要是透过 options {....} 这个设定来处理的；
    • 还是要注意，在 named.conf 当中注解使用 // ，而每一个设定项目最后需要分号 (;)
    我们刚刚规范的 zonefile 档名以及对应的 domain name 还没有忘记吧？那如何处理这个设定档呢？ 最简单的规划如下所示：
    [root@linux ~]# vi /etc/named.conf
// 先定义出整个 DNS 伺服器的相关环境，包括查询、档案放置目录等
options {
        directory       "/var/named";
        dump-file       "/var/named/data/cache_dump.db";
        statistics-file "/var/named/data/named_stats.txt";
        pid-file        "/var/run/named/named.pid";
        forwarders     { 168.95.1.1; 139.175.10.20; };
        allow-query    { any; };  // 是否允许被查询？当然要可以被查询；
        allow-transfer { none; }; // 是否允许传送 zone ，预设不可
};

// 关于 DNS 伺服器的一些加密资料，先忽略过去先！
include "/etc/rndc.key";

// 关于 root (.) 的设定喔：
zone "." {
        type hint;                // 特殊的类别！专给 root (.) 用的
        file "named.root";        // 就是档名的定义啦！
};

// 关于本机 localhost 的正反解
zone "localhost" {
        type master;
        file "named.localhost";
};
zone "0.0.127.in-addr.arpa" {
        type master;
        file "named.127.0.0";
};

// 这里规范出我们的 vbird.tsai 领域名
zone "vbird.tsai" {
        type master;
        file "named.vbird.tsai";
};
zone "1.168.192.in-addr.arpa" {
        type master;
        file "named.192.168.1";
};
    这是一个最基础的 named.conf 的内容，在 options 部分你得要知道的有这些设定值：

    options 内的相关参数说明
设定值 | 意义
directory | 这个设定值就是在指定你的 zone file 要放置到哪个目录啦！ 非常重要的设定值。与底下 zone 设定项目的 file 配合而成完整档名。
dump-file | 由图三我们知道 DNS 伺服器会将搜寻到的主机 IP 对应资料放置到快取记忆体中， 那如果你想要将目前的快取资料记录下来时，就用这个设定值指定档案
statistics-file | 我们 DNS 的一些统计资料，想要列出时就写入这个设定值指定的档名内
pid-file | 将 named 这个程式的 PID 记录下来的一个档案，这个档案通常可以在 named 启动、关闭时提供正确的 PID 啦！
forwarders | 前面谈到 cache-only 的 DNS 伺服器设定值已经谈过了，请前往参考。
allow-query | 是否允许用户端的查询。查询的重点就是读取资料库的内容， 既然要架设 DNS ，当然要允许用户端的查询啦。内容可以填写任何来源 (any) 或 IP 或网域 (IP/netmask) 的格式。
allow-transfer | 是否允许 slave DNS 的整个领域资料的传送？这个设定值与 master/slave DNS 伺服器之间的资料库传送有关。除非你有 slave DNS 伺服器，否则这里不要开放喔！

    在 options 之外就是每个正反解的档案啦！注意看到了没？每个正反解就是利用 zone 这个设定值来处理的啦！ 最常见的设定值其实只有上头那两个，分别是这样的意义：

    zone 内的相关参数说明
    设定值 | 意义
    type | 该 zone 的类型，主要的类型有： master, slave 及 hint。 其中需要注意最上层的 DNS (.) 使用的是 hint 的类型，然后 master 主机用 master 啊！ slave 主机就用 slave ㄇㄟ！
    file 就是 zone file 啦！那么完整的 zone file 在哪里啊？在这里：
      [chroot_dir]/[options 内的 directory]/[file 设定值]
    所以说，root (.) 设定档就在：
    /var/named/chroot/var/named/named.root
    反解 zone | 正解的 zone 很好理解，反解的 zone 怎么那么奇怪啊？就如同 linux.vbird.org 要追踪时是由 org -> vbird -> linux 一样，至于反解则例如 192.168.1.1: 192 -> 168 -> 1 -> 1。 由于 DNS 的领域名称都是由后往前找，且反解是个特殊的领域，所以必需要 将 IP 反过来写，同时在最后面加上‘ .in-addr.arpa ’来表示反解宣告！所以 192.168.1 这个 zone 就得要写成 1.168.192.in-addr.arpa

    所以我们才会说，你的 zone file 档名都是透过 named.conf 这个设定档来规范的啊！在设定完了 named.conf 后，接下来就是那五个 zone file 的设定了，底下咱们就一个一个资料库档案来设定设定先！

    小标题的图示 最上层 DNS (root) 资料库档案的设定
    为什么一定要有 root (.) 这个最顶层的 DNS 伺服器主机的对应呢？请回到图三的画面中， 一般来说，用户端使用我们 DNS 伺服器来查询时，如果查询的目标不在我们 DNS 本身的资料库档案时， 我们的 DNS 就得到 root 去询问啦！那么如果有设定 forwarders 呢？那么搜寻的问题就会丢给 forwarders 那部主机去处理。

    不管怎么说，我们的 DNS 伺服器最好还是得要有 root 主机的对应喔。那你怎么知道 root 那几部主机的 IP 啊？呵呵～鸟哥当然也不知道，不过掌管网际网路的 rs.internic.net 这个网站有提供啊！ 你可以使用浏览器利用 ftp 的通讯协定来下载：
    • ftp://rs.internic.net/domain/named.root
    这个档案的内容就是每一部最上层的 root (.) 的 IP 对应啦！如果你使用 vi 来查阅一下， 可以看到这个档案的内容有点类似这样：(你应该要将这个档案放置到 /var/named 当中喔！)
    [root@linux ~]# vi /var/named/chroot/var/named/named.root
; 抱歉，版权宣告部分先省略～
.                      3600000  IN  NS  A.ROOT-SERVERS.NET.
A.ROOT-SERVERS.NET.    3600000      A   198.41.0.4
;主机名称或领域名称    TTL          RR  相对应的资料
; 以下省略
    在这个档案当中有好几行，每两行成一对，另外，这个档案当中的注解使用的是分号 (;) 喔！与 /etc/named.conf 不一样！要注意喔！在上表当中鸟哥仅取两行作为范例， 每一行可以区分为四个栏位，这两行的意思是：
    1. root (.) 的名称伺服器主机 (Name server, NS) 在 A.ROOT-SERVERS.NET. 这部主机上；
    2. A.ROOT-SERVERS.NET. 这部主机的 IP (A) 为 198.41.0.4
    这两行有对应啊！看出来了没？那个 IN 代表的是使用那个 RR (Resource Record, 资源记录) 的意思， 至于 NS 与 A 我们将在下一小节介绍。那么那个 TTL 是啥？就是这笔记录会放置到 DNS 伺服器的快取多久啦！ 单位是秒啊～

    这个档案的内容你不要修改啊～因为这个内容是 Internet 上面通用的资料，一般来说，也不会常常变动， 所以不需要更动他，将他放置到正确的目录并改成你所指定的档名即可啊！接下来可以看看正解档案啦！

    小标题的图示 正解资料库档案的设定
    就如同案例设定当中提到的，我们共有两个正解档，分别是针对 localhost 以及 vbird.tsai 这两个领域名称。 在正反解的设定档当中可以简单的分成几部分来观察：
    1. 关于本领域的基础设定方面：例如快取记忆时间 (TTL) 、领域名称 (ORIGIN) 等等；
    2. 关于 master/slave 的认证方面 (SOA)；
    3. 关于本领域的领域名称伺服器所在主机名称与 IP 对应 (NS, A, PTR)；
    4. 其他正反解相关的资源记录 (RR)。
    首先先来谈谈比较简单的 localhost 这个领域的正解设定档，named.localhost 的内容有点像这样：
    [root@linux ~]# vi /var/named/chroot/var/named/named.localhost
; 1. 首先是主机相关的设定
$TTL    600

; 2. 关于 master/slave 的授权内容，如果没有 slave 主机，依旧要设定喔！
@    IN   SOA  localhost.   root.localhost.  (
               2006102001  ; Serial  仅作为序号而已
               28800       ; Refresh slave 伺服器的更新时间
               14400       ; Retry   当 slave 主机更新失败，多久再重新更新一次
               720000      ; Expire  重复 retry 多久后就宣告不治....不再更新
               86400 )     ; Minimum 可视为 TTL ，尤其是你没有设定 $TTL 时

; 3. 本领域的 DNS 伺服器的主机名称与 IP 的对应
@          IN   NS   localhost.  ; 特别留意最后面的那个小数点！
localhost. IN   A    127.0.0.1

; 4. 其他 RR 可以加入的地方。
    一般第一次看到这个档案的朋友都会很头痛～很多东西看不懂～其实将他拆成几个小部分来看，你就会看懂啦！ 底下我们就上面提到的四大部分分别来谈一谈先：

    关于本领域的一些设定值
设定值 | 说明
$TTL | 还记得图三的流程吧？当有外部 DNS 伺服器对你的 DNS 的这个领域进行查询时，这一笔记录会放置在对方 DNS 伺服器内几秒钟的意思。
$ORIGIN | 这个设定值可以重新指定 zone 的定义。在预设的情况下， 这个正反解资料库档案中的 zone 是由 /etc/named.conf 所指定的，就是 zone 那个参数的功能。 不过，这个 zone 是可以改的，就是用 $ORIGIN 来修订就是了。通常这个设定值不会用到的。

    我们前面讲到很多 DNS 快取 (cache) 的功能对吧！就是向外查询时所查询到的资料会暂存在自己的快取记忆体中。 那么这笔记录可以放在我的 DNS 主机内多久？那就是 "对方" 设定的 $TTL 这个变数的功能了。

    所以，当你的某个领域名称内的主机对应常常变动时，则这个 $TTL 应该要设定小一点， 免得你的变动总是无法被查询到 (因为对方可能会快取住你之前旧的资料！)。而如果你的 DNS 内容已经很稳定了， 那么这个数值可以设定大一点 (例如 86400 或三天)，如此一来外部的 DNS 才不会常常对你的 DNS 要求， 而造成你的 DNS 忙碌的问题。

    要注意的是，底下开始每一行的设定都会是这样的：
      [主机或领域名称] [TTL] IN [RR] [RR 内容]
    中括号的内容是你要了解的，尤其是各项资源记录标志 [RR] 这个项目！ 虽然我们在整体的设定当中可以直接指定 $TTL 了，不过针对每笔记录还可以自行设定 TTL 啦！ 但在这个设定当中， TTL 通常是省略掉的！ 此外，我们称 RR (Resource Record) 为标志或记录，各个 RR 的对应内容都不相同。 接下来让我们看一看 master/slave DNS 伺服器之间是如何进行 zone file 资料库的传输的？ 那就是 SOA 那一行的内容啰！

    关于 master/slave 授权方面的设定值
    符号与 RR 说明
    @ 这个符号代表 zone 的意思！ 以上面的 named.local 来说， 这个档案由 /etc/named.conf 定义出 zone 为 localhost. ，因此在本档案的 @ 就代表 localhost. 啰！
    . 这个点 (.) 很重要！因为他代表一个完整主机名称 (FQDN) 而不是仅有 hostname 而已。举例来说，如果你在本设定档上面规范一个主机名称为 www 时，那部主机的 FQDN 为 www.localhost. 如果你写出 www.localhost 时，由于末了没有那个小数点，则 zone 会主动加入该主机名称， 所以最终的 FQDN 会变成 www.localhost.localhost. 喔！
    SOA Start of Authority 的意思。 这个标志代表着 master/slave 相关的认证、授权资料。 不论你的 DNS 系统有没有设定 master/slave 的架构，都需要含有这个设定才好。 SOA 后面共带有三个参数，所以该行为：
      [zone] IN SOA [主机名] [管理员 email] ([五组更新时间参数])
    每个设定项目你可以这样看：
    • 主机名：就是 master DNS 的主机名称，通常填写本身主机名即可。还是要注意那个小数点的存在与否喔！非常重要！
    • 管理员 email：本来应该是 "root@localhost." 的，不过因为 @ 已经被作为特殊代号 (zone)， 所以就用小数点来取代，因此 email 就成为 "root.localhost." 啰！
    • (五组数字)：这五个数字分别代表 serial, refresh, retry, expire, ttl。
    至于那五个数字的意义是这样的：
    1. Serial ：只是一个序号，但这个序号可被用来作为 slave 与 master 更新的依据。 举例来说， master 序号为 100 但 slave 序号为 90 时，那么这个 zone file 的资料就会被传送到 slave 来更新了。 由于这个序号代表新旧资料，通常我们建议你可以利用日期来设定！举例来说，上面的资料是鸟哥在 2006/10/20 所写的第一次，所以鸟哥用 2006102001 作为序号代表！
    2. Refresh ：除了根据 Serial 来判断新旧之外，我们可以利用这个 refresh(更新) 命令 slave 多久进行一次主动更新；
    3. Retry ：如果到了 Refresh 的时间，但是 slave 却无法连接到 master 时， 那么在多久之后，slave 会再次的主动尝试与主机连线；
    4. Expire ：如果 slave 一直无法与 master 连接上，那么经过多久的时间之后， 则命令 slave 不要再连接 master 了！ 也就是说，此时我们假设 master DNS 可能遇到重大问题而无法上线，则等待系统管理员处理完毕后， 再重新来到 slave DNS 重新启动 bind 吧！
    5. Minimun ：这个就有点像是 TTL 啦！
    另外，这几个数字的大小是有限制的！你必需要了解喔：
    • Serial <= 2^32 = 4294967296
    • Refresh >= Retry * 2
    • Refresh + Retry < Expire
    • Expire >= Retry * 10
    • Expire >= 7Days

    老实说，初次设定 DNS 的朋友大概都会被那个小数点 (.) 玩死～其实你不要太紧张，只要记住：‘ 加上了 . 表示这个完整的主机名称，亦即是 "hostname + domain name" 了， 如果没有加上 . 的话，表示该名称仅为 "hostname" 而已！至于 SOA 的话，那五个数字通常你可以照抄啦！只要改序号 (Serial) 即可！

    接下来则是设定我们的 DNS 伺服器自己的领域与该领域的名称解析器 (name server, NS) 啰！

    DNS 自己的领域之名称解析器
    符号与 RR 说明
    NS 就是 name server 的缩写，这个标志的参数是：
      [zone] IN NS [主机名称]
    注意喔， NS 后面接的一定是主机名称喔！代表的意思是说：‘这个 zone 的查询请向后面这部主机要求’的意思。 所以，如果你这个 zone 有两部以上的 DNS 伺服器负责时，那就必需要写两个 NS 了！而 NS 后面接的主机名称必需要有 IP 的对应啊！因此就需要 A 这个标志了！
    A 是正解的符号，参数是：
      [hostname] IN A [IP]
    意思是说该部主机的 IP 对应之意！也是最常用的一个标志了！

    要注意喔，每个 zone 至少要一个 NS 才行！而那个 NS 后面的主机可能是你自己，也可能是你的子网域授权啊！ 你必需要很清楚知道 NS 的意义才行！上面三个部分是几乎所有正反解档案所必需要的标志， 而我们最单纯简单的 localhost 领域只要这样设定就妥当了！ 接下来让我们看一看 vbird.tsai 这个领域的主机名称资料库设定档吧！
    [root@linux ~]# vi /var/named/chroot/var/named/named.vbird.tsai
$TTL    600
@ IN SOA linux.vbird.tsai. root.linux ( 2006102001 28800 14400 720000 86400 )
; 本领域的 DNS 伺服器的主机名称与 IP 的对应
@          IN   NS     linux.vbird.tsai.
@          IN   NS     slave.vbird.tsai.
linux      IN   A      192.168.1.254
slave      IN   A      192.168.1.150
@          IN   MX 10  linux

; 其他 RR 可以加入的地方
www        IN   CNAME  linux
ftp        IN   CNAME  linux
forum      IN   CNAME  linux
winxp      IN   A      192.168.1.100
sun        IN   A      192.168.1.200
sun        IN   TXT    "The sun solaris OS"
sun        IN   HINFO  "Celeron 1G""Solaris 10"
    上面的表格当中，TTL 与 SOA 几乎都没变，不过你要特别注意 SOA 后面接的第二个参数也就是 email 的部分， 可以发现鸟哥仅写了个 root.linux 而已，因为最末了没有小数点，所以 DNS 会主动的加上 zone 嘛！ 所以 root.linux 相当于 root.linux.vbird.tsai 啰！^_^ ！另外，那五组数字只要用空白键隔开即可。

    至于本领域的解析器方面，鸟哥使用了两种写法，分别是 "linux.vbird.tsai." 及 "linux" ，注意到差异了？没错，就是那个小数点 (.) 啦！意义请自行参考前面提到的。 同时因为这个领域有两个 DNS 负责，因此在这边用了两个 NS 喔！ 我们这里再写出几个常见的正解标志啰：

    关于正解的其他 RR 标志
    符号与 RR | 说明
    MX 就是 Mail eXchanger(MX) 的简写，他的参数是这样写的：
      [hostname] IN MX [顺序] [主机名称]
    注意啰，这个 MX 与 mail server 有关，没有 mail server 的朋友可以省略这个标志，但是如果你的领域内有 mail server 时，就必需要设定这个 MX 才好。MX 的用途是在于‘邮件转递’或者是经由上层邮件主机备份的一个机制， 后面设定的那个主机名称通常是你的上游邮件主机，相关的意义我们会在 mail server 章节再跟大家详谈。 另外， MX 后面接的数值是越小越优先，而接的主机名称必需要具有 A 的标志才可以！

    如果你不知道如何设定，通常建议你直接设定成你的 mail server 主机名称即可
    CNAME 顾名思义，这个标志在建立‘主机别名’的啦！参数为：
      [hostname] IN CNAME [主机名称]
    注意一下， CNAME 后面接的是主机名称喔。因为有好几部主机名称都对应到同一个 IP 上头， 你当然可以针对每个主机名称给予一个 A ，不过如果未来要改 IP 时，你就得改好几个啦！ 此时改为 CNAME 来处理就很简单。如上表所示，如果我想要知道 ftp.vbird.tsai 的 IP 时， DNS 会先告知 ftp.vbird.tsai 属于 linux.vbird.tsai 的 CNAME ，然后再透过 linux.vbird.tsai 来得到正确的 IP。
    TXT | 这个东西在进行‘说明’而已！亦即是前面那部主机的一些资讯。 特别注意的是，没事的话，‘资讯不要写得太详细，有的时候甚至应该要写些错误的讯息！’ 为什么呢？如果写得太详细的话，那么那些个 cracker 不就很简单的就可以将您的网站资讯取得， 并进而入侵了吗？ @_@
    HINFO | 这个东西后面接两个咚咚，第一个接的是硬体的等级， 第二个接的则是作业系统，这两个咚咚最好不要用在公开的 DNS 主机上面，跟 TXT 一样的问题啦！如果要设定的话， 最好使用双引号分隔开来喔！

    这样应该就设定妥当啰。在 DNS 的正解部分，他的重要资讯特别的多，就是比较难设定的意思～ 所以，您需要特别留意每个设定值是否为正确喔！一般而言，我们会建议大家，设定完成并且执行完启动的 script ，千万要记得去 /var/log/messages 里头看一看有没有错误讯息喔！ 接下来让我们看看反解吧！

    小标题的图示 反解资料库档案的设定
    反解跟正解一样，还都需要 SOA 的标号，也需要 NS 这个咚咚，唯一不同的大概就是由 IP 对应成为 hostname 的不同了吧！
    [root@linux ~]# vi /var/named/chroot/var/named/named.127.0.0
$TTL    600
@ IN SOA localhost. root.localhost. ( 2006102001 28800 14400 720000 86400 )

; 本领域的 DNS 伺服器的主机名称与 IP 的对应
@          IN   NS   localhost.
1          IN   PTR  localhost.
    反解通常只有一个需要注意的地方，那就是 PTR，这是啥？

    关于反解的 RR 标志
    符号与 RR 说明
    PTR Pointer 的简写，他的参数是这样写的：
      [IP] IN PTR [主机名称]
    由于这个档案的 zone 为 127.0.0 ，所以我们只要加一个数字 (最后一个 IP 的数字) 就可以啦！而那个 1 表示的就成为了 127.0.0.1 啰！

    那么万一今天我们规划的是 B Class 的 zone 呢？例如 127.0 这样的 zone 呢？很简单啦！ 就填两个数字即可！也就是 0.1 啰！

    最重要的地方就是：后面的主机尽量使用完整 FQDN，亦即加上小数点 (.) ！为什么呢？因为反解的 zone 是 0.0.127.in-addr.arpa，所以如果你写成 localhost 时，你的这个 IP 对应的主机名称将会变成： localhost.0.0.127.in-addr.arpa 之类的怪异主机名称啊！

    至于 192.168.1.0/24 这个网域的 DNS 反解则成为：
    [root@linux ~]# vi /var/named/chroot/var/named/named.192.168.1
$TTL    600
@ IN SOA linux.vbird.tsai. root.linux.vbird.tsai. (
        2006102001 28800 14400 720000 86400 )

; 本领域的 DNS 伺服器的主机名称与 IP 的对应
@          IN   NS   linux.vbird.tsai.
@          IN   NS   slave.vbird.tsai.
254        IN   PTR  linux.vbird.tsai.
150        IN   PTR  slave.vbird.tsai.

; 其他 RR 可以加入的地方。
100        IN   PTR  winxp.vbird.tsai.
200        IN   PTR  sun.vbird.tsai.
    反解很简单吧！只要设定好 IP 对应的主机名称即可！再次强调要使用 FQDN 在反解当中喔！

    小标题的图示 DNS 的启动与观察
    DNS 的启动也太简单了吧？就直接利用系统提供的启动 script 即可！
    [root@linux ~]# /etc/init.d/named start  <==也可能是需要 restart 喔
    但是这个启动可不见得是成功的！你‘务必’要去 /var/log/messages 观察过才行！
    [root@linux ~]# tail -n 20 /var/log/messages | grep named
named[28]: starting BIND 9.2.4 -u named -t /var/named/chroot
# 由这个说明我们可以知道 chroot 的目录与 named 启动的参数等资料

named[28]: using 1 CPU
named[28]: loading configuration from '/etc/named.conf'
# 由这个说明，可知道主要的设定档是由哪里载入的！记得加上 chroot

named[28]: listening on IPv4 interface lo, 127.0.0.1#53
named[28]: listening on IPv4 interface eth0, 192.168.1.254#53
named[28]: command channel listening on 127.0.0.1#953
named[28]: command channel listening on ::1#953
# 由这边可以查出 DNS 相关的服务在哪几个介面有提供！
# 至于那个 command 我们将在后面再继续说明。

named[28]: zone 0.0.127.in-addr.arpa/IN: loaded serial 2006102001
named[28]: zone 1.168.192.in-addr.arpa/IN: loaded serial 2006102001
named[28]: zone localhost/IN: loaded serial 2006102001
named[28]: zone vbird.tsai/IN: loaded serial 2006102001
# 记得要有这些 loaded serial 的资料，并且不能出现任何错误喔！

named[28]: zone vbird.tsai/IN: sending notifies (serial 2006102001)
named[28]: zone 1.168.192.in-addr.arpa/IN: sending notifies (serial 2006102001)
# 这个则是对于外部有其他 slave DNS 时，会发送注意讯息的说明。
    Tips:
    如果你在 /var/log/messages 里面一直看到这样的错误资讯：
    couldn't add command channel 127.0.0.1#953: not found
    那表示你还必需要加入 rndc key ，请参考本章后面的 利用 RNDC 指令管理 DNS 伺服器 的介绍，将他加入你的 named.conf 中！     		鸟哥的图示
    在上述的输出资料当中因为资讯太长了，所以鸟哥将时间与主机的栏位拿掉了！上面是顺利启动时的状况， 如果出现问题怎办？通常出现问题的原因是因为：
    • 语法设定错误：
      这个问题好解决，因为在 /var/log/messages 里面有详细的说明，按照内容去修订即可；

    • 逻辑设定错误：
      这个就比较困扰了！为什么呢？因为他主要发生在您设定 DNS 主机的时候，考虑不周所产生的问题！例如忘记加上 (.) ， 系统不会显示错误讯息，但是却会造成查询的误判，而 MX 设定的主机名称错误，也不会出现有问题的讯息，但是 mail server 就是会收不到信等等～这些错误都需要很详细的 DNS client 的测试才能知道问题的所在。
    我们这里先就语法设定错误方面进行介绍，至于逻辑设定的问题，那个就需要多多的进行测试才能知道了～ 底下的错误讯息都会记录在 /var/log/messages 里面喔！
    named: /etc/named.conf:11: missing ';' before '}'
# 注意到上面提到的档案与数字吗？说明的是 /etc/named.conf 的第 11 行，
# 至于错误是因为缺少分号 (;) 所致！去修正一下即可。

dns_rdata_fromtext: named.vbird.tsai:5: near eol: unexpected end of input
zone vbird.tsai/IN: loading master file named.vbird.tsai: unexpected end of input
# 指的是 named.vbird.tsai 的第五行有问题，通常是 SOA 那五个数字没有完全！
# 赶紧去修订一下即可啊！

dns_rdata_fromtext: named.vbird.tsai:12: near 'linux': not a valid number
zone vbird.tsai/IN: loading master file named.vbird.tsai: not a valid number
# 说明第 12 行在 linux 附近需要有一个合法的数字！赶紧去瞧瞧改改即可！
    通常最大的问题是....打错字！为了避免让您打错字，上面几个档案鸟哥将他打包了， 你可以在下列的连结下载上述的档案喔！
    • http://linux.vbird.org0350dns/master_dns.tar.gz
    小标题的图示 资料库的更新
    再来谈一谈，那如果你的资料库需要更新时，应该做哪些举动啊？ 举例来说，你的某个主机 IP 或者主机名称要变更，也可能是新增某个主机名称与 IP 的对应呢！ 很简单啦，通常这样做就好了：
    1. 先针对要更改的那个 zone 的资料库档案去做更新，就是加入 RR 的标志即是！
    2. 更改该 zone file 的序号 (Serial) ，就是那个 SOA 的第一个数字， 因为这个数字会影响到 master/slave 的判定更新与否喔！
    3. 重新启动 named ，或者是让 named 重新读取设定档即可。
    就这么简单啊！不过大家常常会忘记第二个步骤啦！就是将序号变大啊！ 如果序号没有变大，那 master/slave 的资料库可能不会主动的更新， 会造成一些困扰喔！

    小标题的图示 测试
    在上面的设定都搞定，并且启动之后，你的 DNS 伺服器应该是已经妥当的在运作了。 那你怎么知道你的设定是否合理？当然要作测试喔！测试有两种方式，一种是藉由 client 端的查询功能， 目的是检验你的资料库设定有无错误；另外你也可以连上底下这个网站：
    • http://www.dnsreport.com/
    这个网站可以帮你检验你的 DNS 伺服器的主要设定是否有问题！不过，这个网站的检验主要是以合法授权的 zone 为主，我们自己乱搞的 DNS 是没有办法检查的啦！真是可惜～ 接下来，请查阅 在 Client 端的测试 吧！
    大标题的图示 Master/Slave 架构的详细设定：
    谈完了 Master DNS 伺服器之后，接下来让我们来了解一下 slave DNS 伺服器的架设方式吧！ 在架设之前，你应该要晓得为何需要 slave DNS 呢？
    • 为了不间断的提供 DNS 服务，你的领域至少需要有两部 DNS 伺服器来提供查询的功能；
    • 承上，这几部 DNS 伺服器应该要分散在两个以上的不同 IP 网域才好；
    • 为方便管理，通常除了一部主要 Master DNS 之外，其他的 DNS 会使用 slave 的模式；
    • slave DNS 伺服器本身并没有资料库，他的资料库是由 master DNS 所提供的；
    • master/slave DNS 必需要可以相互传输 zone file 的相关资讯才行，这部份需要 /etc/named.conf 之设定辅助。
    好了，那么让我们继续上一个案例的延续吧！前一小节是在 192.168.1.254 那部 master DNS 上面设定的， 底下的设定大部分都是在 192.168.1.150 那部 slave DNS 主机上设定的喔！假设我这部 slave.vbird.tsai 仅需要取得 vbird.tsai 以及 192.168.1 这两个领域，其他的例如 named.root, named.localhost 及 named.127.0.0 都需要自理喔！

    小标题的图示 master DNS 权限的开放
    我们在 /etc/named.conf 设定档当中的参数项目曾经设定过 allow-transfer ，并且设定所有人均不得使用 zone 的传送 (transfer)。但是我们的 master DNS 必须要让 slave DNS 可以进行 zone 的传送啊，因此你必须要针对 vbird.tsai 及 192.168.1 这两个 zone 来启用 allow-transfer 的设定项目才行。整个过程很简单：
    [root@linux ~]# vi /etc/named.conf
....前面省略....
zone "vbird.tsai" {
        type master;
        file "named.vbird.tsai";
        allow-transfer { 192.168.1.150; };
};
zone "1.168.192.in-addr.arpa" {
        type master;
        file "named.192.168.1";
        allow-transfer { 192.168.1.150; };
};
....后面省略....
    除此之外，在上头所列示的那两个资料库档案当中，你必须要填入所需要的 NS 标志才行！ 这部份我们已经在前一小节提过了，请你自行参考喔！ 设定完毕后请重新启动 named 啦！

    小标题的图示 slave DNS 的设定
    基本上， slave DNS 的 /etc/named.conf 与 master DNS 几乎一模一样啊！ 唯一的差异在于两个 zone 的类型 (type) 而已。设定方式唯一的差异在这里：
    [root@slave ~]# vi /etc/named.conf
....前面省略....
zone "vbird.tsai" {
        type slave;
        file "named.vbird.tsai";
        masters { 192.168.1.254; };
};
zone "1.168.192.in-addr.arpa" {
        type slave;
        file "named.192.168.1";
        masters { 192.168.1.254; };
};
....后面省略....
    你得要特别留意类型是 slave 之外，那个主机来源 (masters) 是有加 "s" 喔！ 这点很容易忘记啊！至于资料库档案里面，必须要存在的有：
    • named.root
    • named.localhost
    • named.127.0.0
    在 slave DNS 当中，这三个 zone 的类型分别是 hint 与 master ，所以当然要预设存在， 至于那个 named.vbird.tsai 及 named.192.168.1 就不要存在啦！ 因为这两个 zone file 是由 master DNS 主机传送过来的！只是你要注意 /var/named/chroot/var/named 这个目录的权限必须要是 named 这个使用者可以写入的状态！这很重要喔！
    [root@slave ~]# ls -l /var/named/chroot/var/named
-rw-r--r--  1 root  root   229 Oct 18 14:44 named.127.0.0
-rw-r--r--  1 root  root   675 Oct 18 13:44 named.localhost
-rw-r--r--  1 root  root  2517 Oct 18 00:34 named.root
# 注意，只要三个档案即可，其他两个 named.vbird.tsai 与
# named.192.168.1 不可以存在！否则会有问题啊！

[root@slave ~]# ls -ld /var/named/chroot/var/named
drwxr-x---  4 named named 4096 Oct 19 01:17 /var/named/chroot/var/named
# 注意到，这个目录的使用者必须要是 named ，然后分数至少得 750 才行！
    在这个最重要的权限问题处理完毕之后，接下来你可以在 slave DNS 这部伺服器上面启动 DNS 啦！
    [root@slave ~]# /etc/init.d/named start

[root@slave ~]# tail -n 20 /var/log/messages
zone 1.168.192.in-addr.arpa/IN: transferred serial 2006102001
transfer of '1.168.192.in-addr.arpa/IN' from 192.168.1.254#53: end of transfer
zone 1.168.192.in-addr.arpa/IN: sending notifies (serial 2006102001)
zone vbird.tsai/IN: transferred serial 2006102001
transfer of 'vbird.tsai/IN' from 192.168.1.254#53: end of transfer
zone vbird.tsai/IN: sending notifies (serial 2006102001)
# 理论上，你应该会看到如上的输出资讯才对！系统会告知 zone file 的传输结果

[root@slave ~]# ls -l /var/named/chroot/var/named
-rw-r--r--  1 root  root   229 Oct 18 14:44 named.127.0.0
-rw-------  1 named named  472 Oct 19 01:29 named.192.168.1
-rw-r--r--  1 root  root   675 Oct 18 13:44 named.localhost
-rw-r--r--  1 root  root  2517 Oct 18 00:34 named.root
-rw-------  1 named named  580 Oct 19 01:29 named.vbird.tsai
    您瞧！如此一来您的 zone file 就会主动的被建立起来喔！未来如果你的 master DNS 要更新资料库时， 只要修改过序号，并重新启动 named 后，这部 slave DNS 就会跟着更新啦！啊！真是‘福气啦！’！！

    不过，如果你发现到启动 slave DNS 时，你的登录资讯竟然是这样：
    1  dumping master file: tmp-XXXXEnDd9D: open: permission denied
2  transfer of 'vbird.tsai/IN' from 192.168.1.254#53: failed while receiving
   responses: permission denied
3  transfer of 'vbird.tsai/IN' from 192.168.1.254#53: end of transfer
    如果出现类似这样的三行时，不必怀疑啦！肯定是权限错误啦！ 请再次检查你的资料库档案所放置的目录权限是否可以让 named 写入啊！处理处理就好了！ 至于上述的相关档案可以在这里下载：
    • http://linux.vbird.org0350dns/slave_dns.tar.gz
    大标题的图示 Client 端的设定：
    说完了在 DNS Server 端的设定，接下来，我们再来聊一聊关于 Client 端的设定与测试吧！

    小标题的图示 相关设定档
    从前面的说明里面，我们晓得主机名称对应到 IP 有两种方法，早期的方法是直接写在档案里面来对应， 后来比较新的方法则是透过 DNS 架构！那么这两种方法分别使用什么设定档？可不可以同时存在？ 若同时存在时，那个方法优先？嗯！我们先来谈一谈几个设定档吧！
    • /etc/hosts ：刚刚上面就提过了，这个是最早的 hostname 对应 IP 的档案；
    • /etc/resolv.conf ：这个重要！就是 DNS 主机的 IP；
    • /etc/nsswitch.conf：这个档案则是在‘决定’先要使用 /etc/hosts 还是 /etc/resolv.conf 的设定！
    一般而言， Linux 的预设主机名称与 IP 的对应搜寻都以 /etc/hosts 为优先， 为什么呢？您可以查看一下 /etc/nsswitch.conf ，并找到 hosts 的项目：
    [root@linux ~]# vi /etc/nsswitch.conf
hosts:      files dns
    上面那个 files 就是使用 /etc/hosts 而最后的 dns 则是使用 /etc/resolv.conf 的 DNS 主机 IP 搜寻啦！因此，您可以先以 /etc/hosts 来设定 IP 对应ㄋㄟ！ 当然啦，您也可以将他调换过来，不过，总是 /etc/hosts 比较简单，所以将他摆在前面比较好啦！

    好啦，既然我们是要进行 DNS 测试的，那么 /etc/resolv.conf 的内容，自然就要填写我们自己的 IP 啰！所以您应该这样写：
    [root@linux ~]# vi /etc/resolv.conf
nameserver 192.168.1.254
nameserver 168.95.1.1
nameserver 139.175.10.20
    DNS 主机的 IP 可以设定多个，这可以让您的个人电脑有备援的功能！举例来说， 我上面共设定了三部主机作为我的 DNS 查询，当 192.168.1.254 那部主机挂点时， 我的 Client 电脑会立刻以第二部主机作为 DNS 查询的主要主机。所以， 通常我们都会建议人家在这个档案内可以设定三个左右的 DNS 主机名称！以保不时之需啊～

    另外，上面三个 DNS 的 IP 那个会先被使用？当然是照顺序来的～ 所以会先以 192.168.1.254 那部主机来查询，若 192.168.1.254 挂了，才会使用 168.95.1.1 那部来查询。

    Tips:
    尽量不要超过三部以上的 DNS IP ，因为 DNS 的查询也是要时间的，假设现在你无法连接到 DNS 主机是因为你自己的网路问题，而你设定了 10 部 DNS IP 在 /etc/resolv.conf 当中，那么你的 Linux 就会花费 10 倍的时间去进行每一次无法成功的主机名称与 IP 的对应喔！     		鸟哥的图示
    Tips:
    在自家设的没有经过合法授权的 DNS 最好不要以 Internet 上面已经存在的领域名称来练习架设！ 举例来说，假设今天你以 192.168.1.254 那部机器来架设 *.yahoo.com 的领域， 因为我将 192.168.1.254 放置在第一位，导致每次的查询其实 yahoo.com 这个领域的资料都是直接由 192.168.1.254 所提供，这很不好～因为可能会造成您的用户端的不便～     		鸟哥的图示
    好了，我们要测试我们的 DNS 主机设定是否正确啰！

    小标题的图示 DNS 的查询指令： host, nslookup, dig
    测试 DNS 的程式有很多，我们先来使用最简单的 host 吧！然后还有 nslookup 及 dig 哩！

  • host
    • 语法：
[root@linux ~]# host [-a] [FQDN] [server]
[root@linux ~]# host -l [domain] [server]
参数说明：
-a ：代表列出该主机所有的相关资讯，包括 IP、TTL 等等
-l ：若后面接的那个 domain 设定允许 allow-transfer 时，则列出该 domain
     所管理的所有主机名称对应资料！
server：这个参数可有可无，当想要利用非 /etc/resolv.conf 内的 DNS 主机
        来查询主机名称与 IP 的对应时，就可以利用这个参数了！

范例一：强制以 192.168.1.254 这部 DNS 主机来查询
[root@linux ~]# host www.vbird.tsai 192.168.1.254
Using domain server:
Name: 192.168.1.254
Address: 192.168.1.254#53  <==这里重要！告知这笔记录是哪部 DNS 伺服器去找的！
Aliases:

www.vbird.tsai is an alias for linux.vbird.tsai.
linux.vbird.tsai has address 192.168.1.254
    有注意到上面输出的特殊字体部分吗？很多朋友在测试自己的 DNS 时，常常会‘指定到错误的 DNS 查询主机’了～ 因为他们的 /etc/reslov.conf 忘记改，所以老是找不到自己设定的资料库 IP 资料。所以你要仔细看啊！
    范例二：找出我们自己这个 vbird.tsai 领域的所有主机对应
[root@linux ~]# host -l vbird.tsai 192.168.1.254
Using domain server:
Name: 192.168.1.254
Address: 192.168.1.254#53
Aliases:

vbird.tsai name server linux.vbird.tsai.
vbird.tsai name server slave.vbird.tsai.
linux.vbird.tsai has address 192.168.1.254
slave.vbird.tsai has address 192.168.1.150
....后面省略....
    上面的资讯可就熟悉多了吧？！没错！那就是我们在 named.vbird.tsai 里面的设定值啊！ 不过，并不是所有的 domain 都可以作这样的事情～举例来说，如果我们下达：
    [root@linux ~]# host -l yahoo.com
Host yahoo.com not found: 5(REFUSED)
; Transfer failed.
    这样的回应是因为在对方的 /etc/named.conf 里面并没有设定 allow-transfer 那个设定选项的原因啊！ 至于 host -a 的输出资讯与 dig 是一模一样的，所以我们先不介绍，在 dig 处再详细说明。

  • nslookup
    • 语法：
[root@linux ~]# nslookup [FQDN] [server]
[root@linux ~]# nslookup
参数说明：
1. 可以直接在 nslookup 加上待查询的主机名称或者是 IP ，[server] 可有可无；
2. 如果在 nslookup 后面没有加上任何主机名称或 IP ，那将进入 nslookup 的查询功能
   在 nslookup 的查询功能当中，可以输入其他参数来进行特殊查询，例如：
   set type=any ：列出所有的资讯‘正解方面设定档’
   set type=mx  ：列出与 mx 相关的资讯！

范例一：直接搜寻 winxp.vbird.tsai 的 IP 资讯
[root@linux ~]# nslookup winxp.vbird.tsai 192.168.1.254
Server:         192.168.1.254
Address:        192.168.1.254#53 <==同样的，请注意搜寻的 DNS IP 喔！

Name:   winxp.vbird.tsai
Address: 192.168.1.100
    nslookup 可单纯的将 hostname 与 IP 对应列出而已，不过，还是会将查询的 DNS 主机的 IP 列出来的！ 如果想要知道更多详细的参数，那可以直接进入 nslookup 这个软体的操作画面中，如下范例：
    [root@linux ~]# nslookup  <==进入 nslookup 查询画面
> 192.168.1.254          <==执行反解的查询
> www.vbird.tsai         <==执行正解的查询
# 上面这两个仅列出正反解的资讯，没有啥了不起的地方啦！
> tw.yahoo.com           <==执行非本机上的查询
Server:         192.168.1.254
Address:        192.168.1.254#53

Non-authoritative answer:
# 注意这边，因为不是自己的资料库，所以是未认证过的资料(可能是快取)
tw.yahoo.com    canonical name = tw.yahoo-ap1.akadns.net.
tw.yahoo-ap1.akadns.net canonical name = vip1.tw.tpe.yahoo.com.
Name:   vip1.tw.tpe.yahoo.com
Address: 202.43.195.52
> set type=any           <==变更查询，不是仅有 A，全部资讯都列出来
> sun.vbird.tsai
Server:         192.168.1.254
Address:        192.168.1.254#53

Name:   sun.vbird.tsai
Address: 192.168.1.200
sun.vbird.tsai  text = "The sun solaris OS" <==看吧！更多资讯跑出来！
sun.vbird.tsai  hinfo = "Celeron 1G" "Solaris 10"
> exit <==离开吧！皮卡丘
    在上面的案例当中，请注意，如果您在 nslookup 的查询画面当中，输入 set type=any 或其他参数， 那么就无法再进行反解的查询了！这是因为 any 或者是 mx 等等的标志都是记录在正解 zone 当中的缘故！

  • dig
    • 语法：
[root @test root]# dig [@server] [FQDN] [type]
参数说明：
@server ：如果不想以 /etc/resolv.conf 来作为 DNS 主机，则可在此填入其他的 IP
type    ：预设是查询 A 标志，你可以在这里入其他的标志，如 mx, ns 等。
          此功能亦可使用 [-t type] 来处理。

范例一：查询 linux.vbird.tsai 吧！
[root@linux ~]# dig @192.168.1.254 linux.vbird.tsai
; <<>> DiG 9.2.4 <<>> @192.168.1.254 linux.vbird.tsai
; (1 server found)
;; global options:  printcmd
;; Got answer:
;; -;>>HEADER<<- opcode: QUERY, status: NOERROR, id: 8977
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 2, ADDITIONAL: 1

;; QUESTION SECTION:
;linux.vbird.tsai.              IN      A

;; ANSWER SECTION:
linux.vbird.tsai.       600     IN      A       192.168.1.254

;; AUTHORITY SECTION:
vbird.tsai.             600     IN      NS      slave.vbird.tsai.
vbird.tsai.             600     IN      NS      linux.vbird.tsai.

;; ADDITIONAL SECTION:
slave.vbird.tsai.       600     IN      A       192.168.1.150

;; Query time: 4 msec
;; SERVER: 192.168.1.254#53(192.168.1.254)
;; WHEN: Thu Oct 19 15:34:23 2006
;; MSG SIZE  rcvd: 100
    在这个范例当中，我们可以看到整个显示出的讯息包括有几个部分：
    • HEADER(标题)：显示查询的内容有哪些，包括一个 query, 一个 answer 及两个验证部分。
    • QUESTION(问题)：显示所要查询的内容，因为我们是查询 linux.vbird.tsai 所以这里自然就是显示这个讯息。
    • ANSWER(回应)：依据刚刚的 QUESTION 去查询所得到的结果，因为在我们的设定当中仅有设定了 A 的标签，所以这里自然就....
    • AUTHORITY(验证)：由这里我们可以查阅 vbird.tsai 这个领域是由 linux.vbird.tsai 及 slave.vbird.tsai 来设定的～里面那个 600 是什么呢？很简单，他就是我们所设定的 ttl 那个数值啦！
    范例二：查询 vbird.tsai 这个领域的 MX 吧！
[root@linux ~]# dig @192.168.1.254 vbird.tsai mx
; <<>> DiG 9.2.4 <<>> @192.168.1.254 vbird.tsai mx
; (1 server found)
;; global options:  printcmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 3390
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 2, ADDITIONAL: 2

;; QUESTION SECTION:
;vbird.tsai.                    IN      MX  <==瞧！要求的资料不一样了喔！

;; ANSWER SECTION:
vbird.tsai.             600     IN      MX      10 linux.vbird.tsai.

;; AUTHORITY SECTION:
vbird.tsai.             600     IN      NS      slave.vbird.tsai.
vbird.tsai.             600     IN      NS      linux.vbird.tsai.

;; ADDITIONAL SECTION:
linux.vbird.tsai.       600     IN      A       192.168.1.254
slave.vbird.tsai.       600     IN      A       192.168.1.150

;; Query time: 4 msec
;; SERVER: 192.168.1.254#53(192.168.1.254)
;; WHEN: Thu Oct 19 15:45:58 2006
;; MSG SIZE  rcvd: 116
    由于 dig 的输出资讯实在是太丰富了，又分成多个部分去进行回报，因此很适合作为 DNS 追踪回报的一个指令呢！ 你可以透过这个指令来了解一下你所设定的 DNS 资料库是否正确，并进行除错喔！ ^_^
    小标题的图示 Domain 的资讯查询： whois
    whois
    [root@linux ~]# whois [domainname]  <==注意啊！是 domain 而不是 hostnam
[root@linux ~]# whois redhat.com
Registrant:
Red Hat, Inc.
   P.O. Box 13588
   Research Triangle Park, NC 27709
   US

   Domain Name: REDHAT.COM

   Administrative Contact, Technical Contact:
      Network, Operations               noc@REDHAT.COM
      Red Hat, Inc.
      1801 Varsity Drive
      ATTN Domain Administrator
      Raleigh, NC 27606
      US
      919.754.3700 fax: 919-754-3704

   Record expires on 25-May-2011.
   Record created on 26-May-1994.
   Database last updated on 19-Oct-2006 03:58:04 EDT.

   Domain servers in listed order:

   NS3.REDHAT.COM               66.187.229.10
   NS2.REDHAT.COM               66.187.224.210
   NS1.REDHAT.COM               66.187.233.210
    whois 这个指令可以查询到当初注册这个 domain 的使用者的相关资讯。不过， 由于近年来很多网路资讯安全的问题，这个 whois 所提供的资讯真的是太详细了， 为了保护使用者的隐私权，所以，目前这个 whois 所查询到的资讯已经不见得是完全正确的了～ 而且，在显示出 whois 的资讯之前，还会有一段宣告事项的告知呢～ ^_^y

    如果使用 whois 来检查鸟哥所注册的合法 domain 会是如何呢？看看：
    [root@linux ~]# whois vbird.idv.tw
[查询 whois.twnic.net]
[whois.twnic.net]
Domain Name: vbird.idv.tw

   Contact:
      Der-Min Tsai
      vbird@aerosol.ev.ncku.edu.tw

   Record expires on 2008-09-17 (YYYY-MM-DD)
   Record created on 2002-09-13 (YYYY-MM-DD)

Registrar: HINET
    呵呵！这个 domain 会在 2008/09/17 失效的意思啦！报告完毕！

    无论如何，我们都可以透过 nslookup, host, dig 等等的指令来查询主机名称与 IP 的对应， 这些指令的用法可以请您以 man command 来查询更多的用法喔！
    大标题的图示 DNS 伺服器的进阶设定：
    其实， DNS 主机的运作原理与架设方式的变化，真的很高深莫测的！在这里， 我们额外的提出一些比较进阶的内容给大家参考参考，例如子网域的授权问题， 以及架设一个合法授权的 DNS 主机。

    小标题的图示 子网域授权问题
    好了，那么万一我的网路很大，我只想要负责上层的 DNS 而已， 下层希望直接交给各单位的负责人来负责，要怎么设定呢？ 举个例子来说，以成大为例，成大计中仅管理各个系所的的主机 IP 而已，由于各个系所的主机数量可能很大，如果每个人都要请计中来设定， 那么管理员可能会疯掉，而且在实际设计上也不太人性化。

    所以啰，计中就将各个 subdomain (子网域) 的管理权交给各个系所的主机管理员去管理，如此一来， 各系所的设定上面会比较灵活，且上层 DNS 主机也不用太麻烦呐！

    好了，那么如何开放子网域授权呢？我们以刚刚在 master 上面建立的 vbird.tsai 这个 zone 为例， 假设今天你是个 ISP ，有个人想要跟你申请 domain name ，他要的 domain 是‘ niki.vbird.tsai ’， 那你该如何处理？其实只要指定 NS 就好了啦！如下所示：

  • 上层主机端 vbird.tsai 的设定：
    • 上层 DNS 主机的设定其实很简单啦！只要将子网域开放出来给别人使用就对了！ 怎么设定呢？您可以直接修改前面谈到的 named.vbird.tsai ，使他变成如下所示：
    [root@linux ~]# vi /var/named/chroot/var/named/named.vbird.tsai
# 在这个档案的最下方增加这两行：
niki        IN  NS  niki.vbird.tsai.
niki        IN  A   192.168.100.100
    直接将 niki.vbird.tsai. 这个网域的 NS 权限 (name server) 转给 niki.vbird.tsai. 这部主机来管理，并同时列出 niki.vbird.tsai 的正解资讯！ 那么未来当有人要查询类似 www.niki.vbird.tsai 时，我们的 linux.vbird.tsai. 会直接将查询的权限丢给 niki.vbird.tsai 去处理喔！

  • 下游主机 niki.vbird.tsai 的设定：
    • 这个设定就简单啦！直接参考一下我们上面写的资料，跟着设定，但是您的 domain name 变成 niki.vbird.tsai 就是了！简单的很呐！所以鸟哥就不再多说了～
    小标题的图示 架设一个合法的授权的 DNS 主机：
    好啦！现在您应该知道什么是‘经上游授权的合法 DNS 主机’了吧？！ 没错！就是上游的 DNS 主机将子网域的查核权开放给您来设定就对啦！嗯！虽然知道原理， 但是那么我要如何来架设一个合法的 DNS 主机呢？好让我自己管理自己的 domain ！举例来说，鸟哥的 vbird.idv.tw 就是鸟哥自己管理的哩～底下我们就来谈一谈，如何向 ISP 申请一个合法授权的 DNS 主机，或者是合法的主机名称啊！

  • 申请一个合法的 domain name ...就是要花钱！
    • 既然是要建立一个合法的 domain name server ，自然就要向合法的 DNS 主机申请授权啰！ 目前您可以到底下的地方去申请喔！
    • http://www.twnic.net/index3.htm
    其实台湾地区的一些 domain 已经不再于 TWNIC 受理了，所以您连上上述的网站之后， 可以点选里头相关的连结到各大 ISP 去注册！例如鸟哥就注册了 vbird.idv.tw 这个网域！ 现在鸟哥就以 Hinet 的注册做为说明吧
    1. 进入主画面：
      直接连结到底下的网页去： http://nweb.hinet.net

    2. 选择需要的网域名称，并查询该网域是否已存在：
      因为网域必需是独一无二的，所以您必需使用该网页当中提供的查询功能， 去查询一下您想要的网域是否已经被注册了呢？一定要没有被注册的网域才可以喔！

    3. 逐步进行注册：
      你可以选择很多种类的领域来注册，如果想要注册个人网站，请按下图八所指的 (1) 处， 如果想要注册类似 vbird.tw 这种网域的话，则可以选择 (2) 所指的那个项目。 然后以该网站提供的功能一步一步的往下去进行，例如以鸟哥的‘个人网址’之注册为例， 按下个人网址之后，会出现流程步骤为：
      以 Hinet 网站为依据介绍注册 domain 的方法
      图八、以 Hinet 网站为依据介绍注册 domain 的方法

      请依序一步一步的将他完成，最后你会得到一组帐号密码，就能够修改自己的领域啦！

    4. 选择网站代管或架设 DNS 模式：
      还记得前面提到的观念吧？对啦！我们可以直接请 ISP 帮我们设定好 host 对应 IP 就好(最多三部)，当然也可以自行设定一下我们所需要的 DNS 主机啦！如果未来您可能会架设 mail server ，所以还是自行设定 DNS 主机好了！你可以选择图八在 (3) 所指的‘DNS异动与查询’项目， 会出现下面图示。记得选择‘DNS’及填写您的 hostname 与正确的 IP 即可喔！注意： 要填选这个项目，最好您的 IP 是固定制的，浮动制的 IP 不建议用这个选项！
      以 Hinet 网站为依据介绍注册 domain 的方法
      图九、以 Hinet 网站为依据介绍注册 domain 的方法
  • 以 DNS 主机的详细设定 之设定内容来设定您的主机：
    如果您已经以 DNS 主机的方式申请了一个 domain name ，那么您就必须要设定您的 DNS 主机了！ 请注意，这个情况之下，您只要设定您的注册的网域的正解即可！ 反解部分则先不要理会，当然，如果您有办法的话，最好还是请上层的 ISP 帮您设定啰！

  • 测试：
    设定一部合法的 DNS 完毕后，建议你可以到这个网站去查询一下你的设定是否妥当：
    • http://www.dnsreport.com/
    如此一来，您的 DNS 主机上面设定的任何资讯，都可以透过 Internet 上面的任何一部主机来查询到喔！够棒吧！心动了吗？赶快去试看看吧！ ^_^
    • 小标题的图示 LAME Server 的问题：
    或许你曾经在 /var/log/messages 里面看到类似这样的讯息：
    [root@linux ~]# more /var/log/messages
1 Oct  5 05:02:30 test named[432]: lame server resolving '68.206.244.205.
  in-addr.arpa' (in '206.244.205.in-addr.arpa'?): 205.244.200.3#53
2 Oct  5 05:02:31 test named[432]: lame server resolving '68.206.244.205.
  in-addr.arpa' (in '206.244.205.in-addr.arpa'?): 206.105.201.35#53
3 Oct  5 05:02:41 test named[432]: lame server resolving '68.206.244.205.
  in-addr.arpa' (in '206.244.205.in-addr.arpa'?): 205.244.112.20#53
    这是什么东西呐？！根据官方提供的文件资料来看 ( 在您的 CentOS 4.x 的系统下，请察看这个档案‘/usr/share/doc/bind-9.2.4/arm/Bv9ARM.ch06.html’ )，当我们的 DNS 主机在向外面的 DNS 系统查询某些正反解时，可能由于 ‘对方’ DNS 主机的设定错误，导致无法解析到预期的正反解结果，这个时候就会发生所谓的 lame server 的错误！

    那么这个错误会让我们的 DNS 主机发生什么严重的后果吗？既然仅是对方的设定错误， 所以自然就不会影响我们的 DNS 主机的正常作业了。 只是我们的 DNS 主机在查询时，会发生无法正确解析的警告讯息而已， 这个讯息虽然不会对我们的 Linux 主机发生什么困扰，不过，对于系统管理员来说， 要天天查询的 /var/log/messages 档案竟然有这么多的登录资讯，这是很讨厌的一件事！

    好了，我们知道 lame server 是对方主机的问题，对我们主机没有影响， 但是却又不想要让该讯息出现在我们的登录档 /var/log/messages 当中， 怎么达到这样的功能呢？呵呵！就直接利用 BIND 这个套件所提供的登录档参数啊！ 动作很简单，在您的 /etc/named.conf 档案当中的最底下，加入这个参数即可：
    1. 修改 /etc/named.conf
[root@linux ~]# vi /etc/named.conf
// 加入底下这个参数：
logging {
        category lame-servers { null; };
};

2. 重新启动 bind
[root@linux ~]# /etc/init.d/named restart
    基本上，那个 logging 是主机的登录档记录的一个设定项目，因为我们不要 lame server 的资讯， 所以才将他设定为无 (null) ，这样就改完了！ 记得重新启动 named 之后，还是要察看一下 /var/log/messages 喔！ 以确定 named 的正确启动与否！然后，嘿嘿，以后就不会看到 lame server 咯！

    小标题的图示 利用 RNDC 指令管理 DNS 伺服器
    不知道您会不会觉得很奇怪，那就是为啥启动 DNS 后，在 /var/log/messages 老是看到这一句话：
    command channel listening on 127.0.0.1#953
    而且在本机端的 TCP port 953 还多了个 named 所启动的服务，那是啥？那就是所谓的 rndc 了。这个 rndc 是 BIND version 9 以后所提供的功能啦，他可以让你很轻松的管理你自己的 DNS 伺服器喔！ 包括可以检查已经存在 DNS 快取当中的资料、重新更新某个 zone 而不需要重新启动整个 DNS ， 以及检查 DNS 的状态与统计资料等等的，挺有趣的！

    不过，因为 rndc 可以很深入的管理你的 DNS 伺服器，所以当然要进行一些控管啦！ 控管的方式是经过 rndc 的设定来建立一支金钥 (rndc key)，并将这支金钥相关的资讯写入你的 named.conf 设定档当中，重新启动 DNS 后，你的 DNS 就能够藉由 rndc 这个指令来管理啰！ 事实上，新版的 distributions 通常已经帮你主动的建立好 rndc key 了，所以你不需要忙碌～ 不过，如果你还是在登录档当中发现一些错误，例如：
    couldn't add command channel 127.0.0.1#953: not found
    那就表示你 DNS 的 rndc key 没有设定好啦！那要如何设定好？很简单～ 只要先建立一把 rndc key ，然后加到 named.conf 当中去即可！ 你可以使用 bind 提供的指令来进行这样的工作喔！
    1. 先建立 rndc key 的相关资料吧！
[root@linux ~]# rndc-confgen
# Start of rndc.conf
key "rndc-key" {
        algorithm hmac-md5;
        secret "aoIyK4uoiR1hEqedk2D2lw==";
};

options {
        default-key "rndc-key";
        default-server 127.0.0.1;
        default-port 953;
};
# End of rndc.conf
# 上面的输出请将他贴到 rndc.conf 档案当中吧！
# Use with the following in named.conf, adjusting the allow list as needed:
# key "rndc-key" {
#       algorithm hmac-md5;
#       secret "aoIyK4uoiR1hEqedk2D2lw==";
# };
#
# controls {
#       inet 127.0.0.1 port 953
#               allow { 127.0.0.1; } keys { "rndc-key"; };
# };
# End of named.conf
# 至于上面的 key 及 controls 的项目则贴到 named.conf 当中去！
# 请注意，这个 rndc-confgen 是利用乱数计算出加密的那把 key ，
# 所以每次执行的结果都不一样。所以上述的资料与你的荧幕会有点不同。

2. 建立 rndc.conf 档案
[root@linux ~]# vi /etc/rndc.conf
# 在这个档案当中将原本的资料全部删除，并将刚刚得到的结果给他贴上去
key "rndc-key" {
        algorithm hmac-md5;
        secret "aoIyK4uoiR1hEqedk2D2lw==";
};

options {
        default-key "rndc-key";
        default-server 127.0.0.1;
        default-port 953;
};
[root@linux ~]# chmod 640 /etc/rndc.conf  <==必需要设定好权限！
[root@linux ~]# chown root.named /etc/rndc.conf

3. 修改 named.conf
[root@linux ~]# vi /var/named/chroot/etc/named.conf
# 找到如下的这一行：
include "/etc/rndc.key";

# 将上述资料删除！因为该资料是旧的！然后加入这一段：
key "rndc-key" {
      algorithm hmac-md5;
      secret "aoIyK4uoiR1hEqedk2D2lw==";
};

controls {
      inet 127.0.0.1 port 953
              allow { 127.0.0.1; } keys { "rndc-key"; };
};

[root@linux ~]# /etc/init.d/named restart
    建立了rndc key 并且启动 DNS ，同时你的系统也已经有 port 953 之后，我们就可以在本机执行 rndc 这个指令了。这个指令的用法请直接输入 rndc 来查询即可：
    [root@linux ~]# rndc
Usage: rndc [-c config] [-s server] [-p port]
        [-k key-file ] [-y key] [-V] command

command is one of the following:

  reload        Reload configuration file and zones.
  stats         Write server statistics to the statistics file.
  dumpdb        Dump cache(s) to the dump file (named_dump.db).
  flush         Flushes all of the server's caches.
  status        Display status of the server.
# 其他就给他省略啦！请自行输入这个指令来参考啰！
    那如何使用呢？我们举几个小例子来说明吧！
    范例一：将目前 DNS 伺服器的状态显示出来
[root@linux ~]# rndc status
number of zones: 6           <==这部 DNS 管理的 zone 数量
debug level: 0               <==是否具有 debug 及 debug 的等级
xfers running: 0
xfers deferred: 0
soa queries in progress: 0
query logging is OFF         <==是否将查询的资料记录下来？
server is up and running     <==主机目前正在运作当中

范例二：将目前系统的 DNS 统计资料记录下来
[root@linux ~]# rndc stats
# 此时，预设会在 /var/named/chroot/var/named/data 内产生新档案，你可以去查阅：
[root@linux ~]# cat /var/named/chroot/var/named/data/named_stats.txt
+++ Statistics Dump +++ (1161322745)
success 22
referral 0
nxrrset 0
nxdomain 3
recursion 6
failure 0
--- Statistics Dump --- (1161322745)

范例三：将目前快取记忆体当中的资料记录下来
[root@linux ~]# rndc dumpdb
# 与 stats 类似，会将 cache 的资料放置成为一个档案，你可以去查阅：
# /var/named/chroot/var/named/data/cache_dump.db
    如果你在执行 rndc 指令时老是出现如下错误：
    rndc: connection to remote host closed
This may indicate that the remote server is using an older version of
the command protocol, this host is not authorized to connect,
or the key is invalid.
    这表示您的 /etc/rndc.conf 与 /var/named/chroot/etc/rndc.key 内金钥的编码不同所致。 请你自行以上述的 rndc-confgen 的方式自行处理你的 rndc key ，并重新启动 named 即可啊！ 用这东西管理，你就不需要每次都重新启动 named 啰！ ^_^

    小标题的图示 架设动态 DNS 主机： 让你成为 ISP 啦！
    什么是动态 DNS (Dynamic DNS, DDNS) 主机呢？还记得我们在 合法的 DNS 主机 里面提到，如果我们本身是以拨接制的 ADSL 连上 Internet 时， 我们的 IP 通常是 ISP 随机提供的，因此每次上网的 IP 都不固定，所以， 我们没有办法以上面的 DNS 设定来给予这种连上 Internet 的方法一个适当的主机名称。

    也因此，如果我们想要利用这种没有固定 IP 的连线方法架设网站时，就得要有特殊的管道了～ 其中之一的方法就是利用 Internet 上面已经提供的免费动态 IP 对应主机名称的服务！ 例如： http://www.no-ip.org 。

    提供这样的服务利用的是什么原理呢？基本上， DNS 主机还是得要提供 Internet 相关的 zone 的主机名称与 IP 的对应资料才行，所以，DDNS 主机 就必须要提供一个机制，让用户端可以透过这个机制来修改他们在 DDNS 主机上面的 zone file 内的资料才行。

    那会不会很难啊？不会啊！我们的 BIND 9 就有提供类似的机制啦！那就是利用 update-policy 这个选项，配合认证用的 key 来进行资料档案的更新。简单的说， 1) 我们的 DDNS 主机先提供 Client 一把 Key (就是认证用的资料， 你可以将他想成是帐号与密码的概念)， 2) Client 端利用这把 Key ，并配合 BIND 9 的 nsupdate 指令， 就可以连上 DDNS 主机，并且修改主机上面的 Zone file 内的对应表了。感觉上很像很简单喔！ 没错啊！架设上真的很简单的～底下我们就来尝试设定一下喔：

  • DDNS Server 端的设定：
    • 假设我有一个朋友，他使用的 Linux 主机的 IP 是会随时变动的，但是他想要架设 Web 网站， 所以他向我申请了一个领域名称，那就是 web.vbird.tsai ，此时我必需要给他一把金钥， 并且设定我的 named.conf 让 vbird.tsai 这个 zone 能够接受来自用户端的资料更新才行！ 首先来建立这把金钥吧！
    [root@linux ~]# dnssec-keygen -a [演算法] -b [密码长度] -n [类型] 名称
参数：
-a ：后面接的 [type] 为演算方式的意思，主要有 RSAMD5, RSA, DSA, DH
     与 HMAC-MD5 等。建议你可以使用常见的 HMAC-MD5 来演算密码；
-b ：你的密码长度为多少？通常给予 128 位元就可以了；
-n ：后面接的则是用户端能够更新的类型，主要有底下两种，建议给 HOST 即可：
     ZONE：用户端可以更新任何标志及整个 ZONE；
     HOST：用户端仅可以针对他的主机名称来更新。

[root@linux ~]# mkdir -p /var/named/keys; cd /var/named/keys
[root@linux keys]# dnssec-keygen -a HMAC-MD5 -b 128 -n HOST web
Kweb.+157+50096
[root@linux keys]# ls -l K*
-rw-------  1 root root 47 Oct 20 14:20 Kweb.+157+50096.key
-rw-------  1 root root 81 Oct 20 14:20 Kweb.+157+50096.private
# 上面那把是公钥，下面那把则是私钥档案！

[root@linux keys]# cat Kweb.+157+50096.key
web. IN KEY 512 3 157 +j8TSooNNIUPb3OR9Rh53Q==
# 注意到最右边的那个密码长度，等一下我们要复制的仅有那个地方！
    接下来你必需要：将公钥的密码复制到 /etc/named.conf 当中，将私钥传给你的 web.vbird.tsai 那部主机上！好了，那就开始来修改 named.conf 内的相关设定吧！
    [root@linux ~]# vi /etc/named.conf
// 先在任意地方加入这个 Key 的相关密码资讯！
key "web" {
    algorithm hmac-md5;
    secret "+j8TSooNNIUPb3OR9Rh53Q==";
};

// 然后将你原本的 zone 加入底下这一段宣示
zone "vbird.tsai" {
        type master;
        file "named.vbird.tsai";
        allow-transfer { 192.168.1.150; };
        update-policy {
                grant web name web.vbird.tsai. A;
        };
};

[root@linux ~]# chown named /var/named/chroot/var/named
[root@linux ~]# /etc/init.d/named restart
    注意到上头的 grant web name web.vbird.tw. A; 那一行， grant 后面接的就是 key 的名称，也就是说，我这把 web 的 key 在这个 zone (vbird.tsai) 里面可以修改主机名称 web.vbird.tsai 的 A 的标志，亦即是修改主机的 IP 对应啦！语法也就是： grant [key_name] name [hostname] 标签 也就是说，我的一把 key 其实可以给予多种权限喔！就看您如何规范了。

    设定好之后，由于未来用户端传来的资讯是由我们主机的 named 所写入， 写入的目录在 /var/named/chroot/var/named/ 当中，所以你必需要修改一下权限喔！ 给他重新启动 DNS，然后观察一下 /var/log/messages 里面有没有错误即可！ 如此一来，DDNS 主机端就设定妥当啰！

  • Client 端的更新：
    接下来则是 DDNS Client 端的更新了。首先，您必须要由 Server 端取得刚刚建立的那两个档案， 请将刚刚建立的 Kweb.+157+50096.key 及 Kweb.+157+50096.private 利用 SSH 的 sftp 传送到用户端， 亦即是那部 web.vbird.tsai 主机上头， 假设你已经将这两个档案放置到 /usr/local/ddns 里面去，然后测试看看：
    [root@web ~]# cd /usr/local/ddns
[root@web ddns]# nsupdate -k Kweb.+157+50096.key
> server 192.168.1.254
> update delete web.vbird.tsai                   <==删除原有的
> update add web.vbird.tsai 600 A 192.168.1.222  <==更新到最新的
> send
> 最后在此按下 [ctrl]+D 即可
    请注意到‘ update add web.vbird.tsai 600 A 192.168.1.222 ’这行， 他的意义说的是，新增一笔资料， ttl 是 600 ，给予 A 的标签， 对应到 192.168.1.222 的意思～ 至于 nsupdate -k 后面加的则是我们在 Server 端产生的那个 key 档案！

    然后您就会发现到在 DNS 主机端的 /var/named/chroot/var/named/ 里面多出一个暂存档，那就是 named.vbird.tsai.jnl 当然，/var/named/chroot/var/named/named.vbird.tsai 就会随着用户端的要求而更新资料喔！

    由于手动更新好像挺麻烦的，我们就让 Client 自动更新吧！利用底下这个 script 即可！
    [root@web ~]# vi /usr/local/ddns/ddns_update.sh
#!/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin
export PATH

# 0. keyin your parameters
basedir="/usr/local/ddns"                  # 基本工作目录
keyfile="$basedir"/"Kvbird.+157+05841.key" # 将档名填进去吧！
ttl=600                                    # 你可以指定 ttl 的时间喔！
outif="ppp0"                               # 对外的连线介面！
hostname="web.vbird.tsai"                  # 你向 ISP 取得的那个主机名称啦！
servername="192.168.1.254"                 # 就是你的 ISP 啊！

# Get your new IP
newip=`ifconfig "$outif" | grep 'inet addr' | \
        awk '{print $2}' | sed -e "s/addr\://"`
checkip=`echo $newip | grep "^[0-9]"`
if [ "$checkip" == "" ]; then
        echo "$0: The interface can't connect internet...."
        exit 1
fi

# create the temporal file
tmpfile=$basedir/tmp.txt
cd $basedir
echo "server $servername"                       >  $tmpfile
echo "update delete $hostname A "               >> $tmpfile
echo "update add    $hostname $ttl A $newip"    >> $tmpfile
echo "send"                                     >> $tmpfile

# send your IP to server
nsupdate -k $keyfile -v $tmpfile
    您只要将上述的程式里面，特殊字体的部分给他修改一下，就能够以 /etc/crontab 的方式在您的系统内自动执行了！这支程式你也可以在底下的连结下载：
    • http://linux.vbird.org0350dns/ddns_update.sh
    利用 BIND 9 所提供的这个服务，我们只要具有一组固定的 IP ，并向 ISP 申请一个合法授权的 domain name， 就可以提供不论是固定或者是非固定的 IP 使用者，一个合法的主机名称了！ 并且，使用者也可以自行透过 nsupdate 来修改自己的 IP 对应！以让自己的主机 IP 永远与主机名称保持正确的对应！这对只有拨接制上网的用户来说，真是方便啊！
    • 大标题的图示 重点回顾：
    • 在 Internet 当中，任何一部合法的主机都具有独一无二的主机名称，这个主机名称包含了 hostname 与 domain name ，并称为 Fully Qualified Domain Name (FQDN)；
    • 为了克服人类对于 IP 不易记忆的困扰，而有名称解析器的产生，首先是 /etc/hosts ，而后则是 DNS 系统的产生；
    • 目前 Unix Like 的机器当中，都是以 BIND 这个柏克莱大学发展的套件来架设 DNS 伺服器；
    • DNS 是个协定的名称，BIND 则是一个套件，这个套件提供的程式为 named ！
    • 在 DNS 当中，每一笔记录我们就称他为 RR (Resource Record)。
    • 在 DNS 系统中，正解为由 hostname 找 IP ，而反解则是由 IP 找 hostname ，至于 zone 则是一个或者是部分网域的设定值；
    • 在 bind 9 之后，预设的情况下 named 已经作了 chroot 的动作。
    • DNS 伺服器的类型主要分为 master, slave 以及只进行快取记录的 cache-only 的 DNS 主机；
    • Master/Slave 架构下的 DNS 主机系统，不论是 Master/Slave 主机均需要能够正确的提供 hostname 与 IP 的对应才行。
    • Slave 主机本身并没有自行设定 zone file ，其 zone file 是由 Master 主机传送而来，因此， master 主机必须要针对 slave 主机开放 allow-transfer 的设定项目才行。
    • 整个 DNS 搜寻的流程当中，若找不到本身的资料，则会向 root(.) 要求资料；
    • bind 的设定档为 /etc/named.conf ，而 named.conf 可以规范出正反解 zone 的档案所在；
    • 正解的纪录(record)主要有：SOA, A, MX, NS, CNAME, TXT 及 HINFO 等；
    • 反解的纪录主要有： SOA, PTR 等；
    • 在 client 端设定 DNS 查询顺序与相关功能的几个重要档案为： /etc/nsswitch.conf, /etc/hosts, /etc/resolv.conf 等；
    • DNS 查询的指令主要有： host, nslookup, dig, whois 等等；
    • 在载入了 named 这个 daemon 之后，请务必前往 /var/log/messages 察看此 daemon 的成功与否。
    • CentOS (Red Hat 系统) 的 /etc/sysconfig/named 可以指定 chroot 的目录或取消 chroot 的功能等等。
    • Cache only DNS 伺服器常被使用于防火墙上，用来代理内部 LAN 的主机名称解析要求！
    • 本章与 LPI 考试的关系：
      在 LPI 网站 http://www.lpi.org 里面提到的，关于 NFS 的考试题库的地方，只有在 LPI level 1 的 102 ，里面的 topic 113 Networking Services ，第五点当中，简易的 DNS 设定。强调的是‘应试者需了解何谓正、反解、Zone 与 cache-only 的 DNS 主机’至于会考的档案与指令可能有这些：
      • /etc/hosts
      • /etc/nsswitch.conf
      • /etc/resolv.conf
      • /etc/named.boot(V4)及 /etc/named.conf(V8)
      • named (这个 daemon )
    大标题的图示 课后练习
    • 为何要有 DNS 系统：
      最主要的功能其实在于 Hostname 对应 IP 的查询，可以让我们人类以电脑主机名称连上 Internet ，而不必背诵 IP 哩！
    • 那么请教 Unix Like 系统当中，主要使用那个套件做为 DNS 主机的架设，同时，他又是使用那个 daemon 来启动 DNS 系统？
      在 Unix Like 系统当中，使用 BIND 这个套件做为 DNS 的架设，至于 daemon 则是使用 named 这个 daemon ！
    • 最早的 Internet 其实是为了政府人员可以连上网路以进行资源的分享，另外，则是电子邮件的使用。 而在早期使用的重要档案只有 /etc/hosts 这个，请教这个 hosts 档案的内容含有什么项目？
      这个档案的‘格式’为‘ [IP] [主机名称] [主机别名(aliase)]’，而，这个档案里面放置了至少一行，也就是：
      127.0.0.1 localhost localhost.localdomain
      另外，也可以将经常连接的主机 IP 与 HOSTNAME 的对应给他写进来！
    • 请说明 DNS 的三种类型与相关的内容：
      DNS 主机主要分为： master, slave 与 cache-only 三种类型！在 master 当中，master 主机里面即有设定 DNS 资料档案，例如在 /var/named 里面的正反解档案。至于 slave 的 DNS 主机则主要在进行 master 主机的资料备份，同时也提供 Internet 上面的查询功能。使用 master/slave 的最大优点在于“单点维护”的能力！ 利用修改 master 即可让 slave 的资料同时更新，减少人力的浪费。至于 cache-only 仅进行快取的纪录，本身并无资料库档案！
    • 正解档案(forward)反解档案(reverse)与内部回圈使用的档案(loopback)主要的纪录功能为：
      正解档在设定 hostname 对应到 IP 的纪录，主要的纪录有 A, NS, SOA, MX, CNAME 等等； 反解档主要设定 IP 对应到 Hostname 的纪录，主要的纪录为 SOA, NS 与 PTR 等。 内部回圈则是 localhost 与 127.0.0.1 的对应啦！
    • 在主要的 DNS 设定档 /etc/named.conf 当中，有一个较为特殊的档案，他的类型为 hint ，请问这个档案的功能为何？
      这个档案主要是由 rs.internic.net 所下载下来的，主要记录了 root (.) 这个 zone 的 IP ！可以让我们的 DNS Server 在找不到资料库时，可以到这个 root 去查询资料！
    • 在 client 端搜寻 HOSTNAME 对应到 IP 的查询时，最重要的档案，以及该档案的主要用途为何？
      /etc/nsswitch.conf ：可以用来设定查询主机名称的顺序！例如先查询 /etc/hosts 再查询 DNS 系统；
      /etc/hosts ：最早的名称解析器；
      /etc/resolv.conf：这就是 DNS 系统的 resolver (解析器)了。
    • 一般来说，在 Client 端使用的查询 HOSTNAME 的指令大多使用什么？
      nslookup ：可以用来收集一部主机的相关资讯；
      dig：可以用来收集详细的主机资讯；
      whois ：可以用来收集详尽的 DNS 主机资讯。
      host 则较为简单喔！
    • 请问 named 重要的资讯登录在在那个档案中？
      在 /var/log/messages 当中
    大标题的图示 参考资源：
    • BIND 官方网站：http://www.isc.org/products/BIND/
    • Study Area 学习网站：http://www.study-area.org/linux/servers/linux_dns.htm
    • 优客笔记：http://turtle.ee.ncku.edu.tw/~tung/dns/dnsintro.html
    • lame server 的简易说明：http://linux.cvf.net/lame_server.html
    • DDNS 架设：http://www.study-area.org/tips/ddns.htm
    • Hinet 反解申请单：http://hidomain.hinet.net/top1.html
    • 合法 DNS 伺服器设定的检查网站：http://www.dnsreport.com/
    • 对于想要架设内外部不同 DNS 查询功能的朋友来说，可以参考 view 这个参数，请参考：
      http://www.study-area.org/tips/bind9_view.htm
    • 来自 Red Hat 公司的一份教学：
      http://www.redhat.com/magazine/026dec06/features/dns/?sc_cid=bcm_edmsept_007
    2002/12/10：首次完成
    2003/03/10：修改部分内容，并且新增 LPI 相关性与重点整理部分！
    2003/09/10：修改了部分的版面，并将 slave DNS 的错误修订完毕！
    2003/10/08：新增了 lame server 的说明，与解决之道！
    2004/10/29：新增了 rndckey 的说明与解决之道！
    2004/10/30：新增了 Master/Slave 的架构设定
    2004/10/31：新增了 动态 DNS 主机的设定 。
    2005/07/19：增加了 SOA 内五个数字的大小
    2006/10/17：将之前的旧文章移动到此处
    2006/10/20：终于～不容易～将一些资料给他修订完毕啦！
    2007/06/25：小州大大来信告知 Forwarding 与 cache-only 的介绍可以加以修改。已经处理成为这样。
    2002/12/10 以来统计人数


鸟哥的 Linux 私房菜 -- WWW 伺服器 Apache

为取得较佳浏览结果，请爱用 firefox 浏览本网页

WWW 伺服器
切换解析度为 800x600
最近更新日期：2006/11/10
我们最常讲的‘架站’其实就是架设一个 Web 网站啦！那么什么是 Web 呢？那就是全球资讯广播的意思 (World Wide Web)，或者也可以称之为互连网吧！这个是我们目前的人类最常使用的 Internet 的协定之一啦！通常说的上网就是使用 WWW 来查询使用者所需要的资讯啰！^_^！目前的 WWW 伺服器主要分为两大阵营，分别是 Unix-Like 上面的 Apache 与 Windows 上面的 IIS ，就以效能价格比来说，当然是 Linux 上面的 Apache 最棒啦！至于 WWW 伺服器的类型可以分为静态与动态，而这些动态的网站里面，很多都是以目前的当红炸子鸡 Linux + Apache + MySQL + PHP 架设而成的，简称为 LAMP 的咯！这种动态 WWW 主机很有趣喔！他可以沟通 Server 与 Client 端的资料呢！赶紧来进入这个 LAMP 的世界吧！

1. 本章的行前准备工作
2. WWW 的简史、资源以及伺服器软体
    2.1 WWW 的简史、HTML与标准制订 (W3C)
    2.2 WWW 主机与浏览器所提供的资源设定
    2.3 WWW 伺服器的类型：WWW 平台、网页程式语言与资料库(LAMP)
    2.4 加密的网页资料 (SSL) 及第三方公正单位
    2.5 用户端常见的浏览器
 3. WWW (Apache) 伺服器基本设定
    3.1 LAMP 所需套件与其结构
    3.2 httpd.conf 的基本设定
        针对主机环境的设定项目
        针对中文 big5 编码语系
        首页权限相关设定 (DocumentRoot 与 Directory)
    3.3 PHP 等额外设定档
    3.4 Apache 的启动与 PHP 的测试
    3.5 MySQL 资料库的启动与测试
        启动 MySQL (设定 MySQL root 密码与新增 MysQL 用户帐号)
        效能调校 /etc/my.cnf
        MysQL root 密码忘记的紧急处理
    3.6 开始网页设计及安装架站软体，如 phpBB2
 4. Apache 伺服器的进阶设定
    4.1 启动用户的个人网站(权限是重点)
    4.2 启动某个目录的 CGI (perl) 程式执行权限
    4.3 找不到网页时的显示讯息通知
    4.4 浏览权限的设定动作 (order, limit)
    4.5 主机状态说明网页
    4.6 .htaccess 与认证网页设定
    4.7 虚拟主机的设定
    4.8 防火墙与 SELinux
 5. 登录档分析以及 PHP 强化模组等套件说明
    5.1 PHP 强化模组 (eaccelerator) 与 Apache 简易效能测试
    5.2 syslog 与 logrotate
    5.3 webalizer
    5.4 awstats
 6. 建立 SSL (https) 网站
7. 一些安全性管理的网页
    7.1 让 SSH 可以使用后门连线
    7.2 防砍站软体
 8. 重点回顾
9. 课后练习
10. 参考资料
11.针对本文的建议：http://phorum.vbird.org/viewtopic.htm?p=116564
大标题的图示 本章的行前准备工作
WWW 伺服器能否提供浏览器来浏览其实与档案系统有很深的关系，如果你对于 Linux 档案的权限概念不足的话， 那么即使你架设好一部 WWW 伺服器，您网站的资料也可能不能够被使用者所浏览的。 此外，由于 Linux 的 WWW 伺服器含有很多的外挂模组，所以你可能会需要自行进行一些原始码的编译行为。 而你的 WWW 伺服器很可能同时管理多部主机名称的，所以 DNS 以及网路基础的部分也要很清楚的！ 所以，您最好已经具有如下的基础：
  • 基础学习篇内的档案与目录管理以及档案属性与目录配置等部分；
  • 基础学习篇内的原始码的编译与相关意义；
  • DNS 伺服器的原理与设定技巧；
  • 网路基础概念；
  • 务必要关闭 SELinux ，否则 Apache 肯定无法顺利提供浏览资料。
大标题的图示 WWW 的简史、资源以及伺服器软体
你知道目前 (2006) 网路为什么会这么流行吗？其实都是 WWW 造成的啦。早在 1993 年左右，鸟哥初次接触到网路， 当时的网路较热门的大概就是一些资源下载的 FTP 网站以及很多文字热烈讨论的 BBS 站了。 资料虽然丰富，不过，总是觉得少了点什么。后来上了研究所，为了课业需要， 经常连上台湾的学术网路 (TANET) 进行一些学术资料的检索，当时大约是 1996 年左右。 因为上网就是要找资料而已，所以就慢慢的很少使用网路了。

过了几年后，再次使用图形介面的作业系统，竟然发现只要点几个小按钮，就会有很多网路上花花绿绿的文字与图案， 有的网站甚至提供影音的特效，当时真是相当的讶异！不过，由于图形影像的视觉方面要比 BBS 纯文字的资料吸引人，自然造成很多人喜欢流连在网际网路上，人潮多当然就有商机！由于奇货可居，才有后来 90 年代末期的浏览器大战， 这个商业大战也造成后来 WWW 标准不被某些浏览器所支援的后果。

这些年由于搜寻引擎、个人网志 (blog) 的流行，又将网际网路推向另一个新境界！啊！ 要学的东西真是很多啊～～@_@。底下让我们来了解了解什么是 WWW 以及他所需要的伺服器软体， 还有一些浏览器相关的资讯吧！

小标题的图示 WWW 的简史、HTML 与标准制订 (W3C)
众所皆知的，目前网际网路社会上最热门的协定就是 TCP/IP 了，而 TCP/IP 的应用方面则有 mail, dns, ftp, telnet 与 www 等等，其中造成 TCP/IP 大流行的应属 mail 与 www，尤其是 WWW 这个玩意儿。 WWW 是 Word Wide Web 的缩写，其中 Web 有广播网的意思存在， 所以简称为全球资讯网的就是了。WWW 可以结合文字、图形、影像以及声音等多媒体， 并透过超连结 (Hyper Text) 的方式将资讯以 Internet 传递到世界各处去。

与其他的伺服器类似的，你要连结上 WWW 网站时，该网站必需要提供一些资料， 而你的用户端则必需要使用可以解析这些资料的软体来处理，那就是浏览器啦！ 简单的来说，你可以这样瞧一瞧 WWW server/client 的相关性：

WWW 主机与用户端的连线相关性
图一、WWW 主机与用户端的连线相关性

也就是说，你的 WWW 伺服器不但需要一个可让用户端浏览器浏览的平台，还需要提供用户端一些资料才行！ 那这些可供查询的资料有哪些类型？最主要的其实是超文件标签语言 (Hyper Text Markup Language, HTML)。 其实超文件标签语言大多只是一些纯文字资料，然而透过浏览器对于一些标签 (<tag>) 的解释后， 就能够得到不同的文字格式、颜色显示等等。你可以使用任何一个浏览器连结到搜寻大师 http://www.google.com 网站，然后在其上的页面上按下滑鼠右键， 选择察看原始码，你就能发现该网页是如何写成的了。
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
       "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <==HTML的标准版本宣告
<html>
<head>
.....一些标头资料，例如 title 等等......
</head>
<body>
.....实际的资料放置位置......
</body>
</html>
HTML 之所以被称为标签语言就如同上面的表格所示，他是由很多 <tag> 所组成的，主要分为两大区块， 一个是与标头有关的 <head> 区块，包括该网页所使用的编码格式与抬头等等。另一部份则是 <body> 所含有的实际网页内容资料啦。关于 HTML 不在本文的介绍内，你可以在市面上找到很多相关的书籍。而除了 HTML 之外， 目前的标签语言还包括了 XHTML, CSS 风格语法等等，都值得参考喔。

知道了 WWW 的 server/client 架构后，再来我们要讨论的是，那 WWW 是怎么来的啊？ 伯纳斯-李 (Tim Berners-Lee) 在 1980 年代为了更有效率的让欧洲核子物理实验室的科学家可以分享及更新他们的研究成果， 于是他发展出一个超文件传输协定 (Hyper Text Transport Protocol, HTTP)。 如同前面提到的，在这个协定上面的伺服器需要软体，而用户端则需要浏览器来解析伺服器所提供的资料。 那么这些软体怎么来的？

为了让 HTTP 这个协定得以顺利的应用，大约在 90 年代初期由伊利诺大学的国家超级电脑应用中心 (NCSA, http://www.ncsa.uiuc.edu/) 开发出伺服器 HTTPd (HTTP daemon 之意)。HTTPd 为自由软体，所以很快的领导了 WWW 伺服器市场。 后来网景通讯 (Netscape) 开发出更强大的伺服器与相对应的用户端浏览器，那就是大家曾经熟悉的 Netscape 这套软体啦。这套软体分为伺服器与浏览器，其中浏览器相对便宜，不过伺服器可就贵的吓人了。 所以，在伺服器市场上主要还是以 HTTPd 为主的。

后来由于 HTTPd 这个伺服器一直没有妥善的发展，于是一群社群朋友便发起一个计划， 这个计划主要在改善原本的 HTTPd 伺服器软体，他们称这个改良过的软体为 Apache ， 取其‘一个修修改改的伺服器 (A patch server)’的双关语！ ^_^！这个 Apache 在 1996 年以后便成为 WWW 伺服器上市占率最高的软体了 (http://httpd.apache.org/)。

虽然 WWW 越来越重要，但相对的来说，用户端如果没有浏览器的话那么他们当然就无法去浏览 WWW 伺服器所提供的资料。为了抢占浏览器的市占率，于是在 90 年代末期微软将 IE 浏览器内建在 Windows 作业系统内，此一决定也让当时相当广泛使用的 Netscape 浏览器 (Navigator) 市占率急速下降。 后来网景公司在 1998 年左右将浏览器的原始码部分开放成为自由软体，采用 Mozilla 通用授权 (MPL) 。

Mozilla (http://www.mozilla.org/) 这个计划所开发的软体可不止浏览器而已，还包括邮件处理软体及网页编辑软体等等。 当然啦，其中最出名的就是浏览器软体‘火狐狸 (firefox)’啦！那这玩意儿与 IE 有啥不同？ 由于 IE 是整合在 Windows 作业系统核心内， 加上改版的幅度太慢，甚至 IE 使用的 HTML 标准语法解析行为都是微软自订的标准， 并不全然符合网际网路上的标准规范 (W3C, http://www.w3.org/)，导致伺服器端所提供的资料并无法在所有的浏览器上都显示出相同的样式， 而且用户端也容易受到网路攻击。

firefox (http://moztw.org/) 的发展就标榜小而美，因此程式相当的小，所以执行效能上面非常的快速，此外，对于超文件的解析上面， firefox 主要依据 w3c 所制订的标准来发展的，所以任何以 w3c 的标准开发的网站，在 firefox 上面就能够得到设计者所希望的样式！目前 firefox 已经针对市面上最常见到的 Windows/Linux/Unix 等作业系统来进行支援，大家可以多多使用喔！^_^

由上面的介绍我们可以知道：
  • WWW 是依据 HTTP 这个协定而来的，分为伺服器端与用户端；
  • Apache 是一个伺服器端的软体，主要依据 NCSA 的 HTTPd 伺服器发展而来，为自由软体；
  • Mozilla 是一个自由软体的开发计划，其中 firefox 浏览器是相当成功的作品。
  • 在撰写自己的网页资料时，尽量使用 W3C 所发布的标准，这样在所有的浏览器上面才能够顺利的显示出你想要的样子。
小标题的图示 WWW 主机与浏览器所提供的资源设定
由前面的说明我们可以知道其实 WWW 伺服器的重点是提供一些资料，这些资料必需要是用户端的浏览器可以支援显示才行。 那么这些资料是什么类型啊？很简单啊，当然就是档案啰。如此说来，我们必需要在伺服器端先将资料档案写好， 并且放置在某个特殊的目录底下，这个目录就是我们整个网站的首页了！ 一般来说，这个目录很可能是在 /var/www/html/ 或者是 /srv/www/。我们的 CentOS 预设在 /var/www/html 喔。

好了，那么浏览器如何取得这个目录内的资料呢？你必需要在浏览器的‘网址列’输入所需要的网址才行。 不过，现今的浏览器功能实在很多，他不只可以连上 WWW ，还可以连上类似 FTP 之类的网路通讯协定。 所以你得要在网址列输入正确的网址，这个网址包括这样：
    <协定>://<主机位址或主机名称>[:port]/<目录资源>
上头就是我们常常听到的 URL (Uniform Resource Locator) 啦！他可以这样看的：

  • 协定：
    • 比较常见的协定有 http, https, ftp, telnet 等等，还有类似 news, gopher 等。 这个协定在告知浏览器‘请你利用此一协定连接到主机端’的意思。举例来说，如果你下达： http://ftp.isu.edu.tw 这表示浏览器要连结到 义守大学的 http (亦即 port 80) 的意思。如果是 ftp://ftp.isu.edu.tw 则代表连结到义守大学的 ftp (port 21) 啦！ 因为使用的协定不同，所以当然回应的资料也不相同的。不过， 万一对方伺服器的埠口启动在非正规的埠号，例如将 http 启动在 port 81 时，那你就得要这样写： http://hostname:81/ 。

  • 主机位址或主机名称：
    • 就是主机在网际网路所在的 IP 位置。如果是主机名称的话，当然得要透过名称解析器啰！ 一般来说，虽然使用 IP 就能够架设 WWW 网站，不过建议您还是申请一个好记又合法的主机名称比较好！

  • 目录资源：：
    • 刚刚不是提到首页的目录吗？在首页目录下的相对位置就是这个目录资源啦。 举例来说，鸟哥的网站 www 资料放置在我主机的 /var/www/html/ 当中，所以说：
    • http://linux.vbird.org --> /var/www/html/
    • http://linux.vbird.org/linux_basic/index.htm --> /var/www/html/linux_basic/index.htm
    另外，通常首页目录底下会有个特殊的档案名称，例如 index.html 或 index.??? 等。举例来说，如果你直接按下： http://linux.vbird.org 会发现其实与 http://linux.vbird.org/index.htm 是一样的！ 这是因为 WWW 伺服器会主动的以该目录下的‘首页’来显示啦！
    所以啦，我们的伺服器会由于浏览器传来的要求协定不同而给予不一样的回应资料。 那你了解到网址列的意义了吗？^_^！再来，如果浏览器是以 http://hostname 的型态来向伺服器要资料时， 那么浏览器与伺服器端是如何传递资料的呢？基本上有这几种方法：
    • GET
      就是直接向 WWW 伺服器要求网址列上面的资源，这也是最常见的。此外，使用 GET 的方式可以直接在网址列输入变数喔。举例来说，鸟哥的讨论区有一篇提问的智慧， 他的网址是：‘http://phorum.vbird.org/viewtopic.htm?t=96’，发现那个 ?t=96 了吗？ t 就是变数， 96 就是这个变数的内容。如果你将问号后面的资料拿掉时，瞧瞧会出现什么后果？ 这么说，您可以明白 GET 的处理了吧？

    • POST
      这也是用户端向主机端提出的要求，只是这个要求里面含有比较多的资料就是了。 举例来说，讨论区里面不是常常有留言的选项吗，如果你选择留言的话不是会在浏览器冒出一个框框让你填入资料吗！ 当按下传送后，那些框框内的资料就会被浏览器包起来传送至 WWW 伺服器了。 POST 与 GET 不相同喔， GET 可以在网址列取得用户端所要求的变数，不过 POST 就不是使用网址列的功能了。

    • HEAD
      主机端回应给 Client 端的一些资料档头而已；

    • OPTIONS
      主机端回应给 Client 端的一些允许的功能与方法；

    • DELETE
      删除某些资源的举动。
    常见的是 GET 这个项目啦！如果有大量资料由用户端上传到 WWW 伺服器端时，才会使用到 POST 这个项目。 你还是得需要注意一下这些举动，因为后续的登录档分析内容都是使用这种动作来分析的呦！

    小标题的图示 WWW 伺服器的类型：WWW 平台、网页程式语言与资料库(LAMP)
    前面我们提到 WWW 伺服器软体的研发，以目前来说，市占率较高的应该是 Apache 与 IIS 这两个玩意儿， Apache 是自由软体，可以在任何作业系统上面安装的，至于 IIS 则是 Windows 家族开发出来的， 仅能在 Windows 作业系统上面安装与执行。由于作业系统平台不一样，所以其上安装的软体当然也不相同。 底下就让我们来聊一聊目前网站的一些特色吧！

    目前 Internet 上头提供 WWW 资料的主机大致上我们可以粗分为两种：

  • 仅提供使用者浏览的静态网页：
    • 这种类型的网站大多是提供‘静态’的网页，或许有提供一些动画图示，但基本上就仅止于此啦！ 因为他仅提供你来浏览，Server 不需要与 Client 端互动，所以你可以到该网站上去浏览， 但是无法进行进行资料的上传喔！目前主要的免费虚拟主机大多是这种类型，所以，你只要依照 HTML 的语法写好你的网页，并且上传到该网站空间上，那么你的资料就可以让大家浏览了！

  • 提供使用者互动介面的动态网站：
    • 这种类型的网站可以让伺服器与使用者互动，常见的例如讨论区论坛与留言版，包括一些部落格也都是属于这类型。 这类型的网站需要的技术程度比较高，因为他是藉由‘网页程式语言’来达成与使用者互动的行为， 常见的例如 PHP 网页程式语言，配合 MySQL 资料库系统来进行资料的读、写。整个互动可以使用下图来说明：

    动态网站的网页程式语言与资料库介面
    图二、动态网站的网页程式语言与资料库介面

    这就是所谓的主机端工作任务介面 (Server Side Include, SSI)，因为不论你要求的资料是什么， 其实都是透过伺服器端同一支网页程式在负责将资料读出或写入资料库，处理完毕后将结果传给用户端的一种方式， 变动的是资料库内的资料，网页程式其实并没有任何改变的。这部份的网页程式包括 PHP, ASP, Perl.... 很多啦！

    另外一种互动式的动态网页主要是在用户端达成的！举例来说，我们可以透过利用所谓的 Java scripts 这种语法， 将可执行的程式 (java script) 传送给用户端，用户端的浏览器如果有提供 java script 的功能， 那么该程式就可以在用户端的电脑上面运作了。由于程式是在用户端电脑上执行， 因此如果伺服器端所制作的程式是恶意的，那么用户端的电脑就可能会遭到破坏。 这也是为啥很多浏览器都已经将一些危险的 java script 关闭的原因。

    另外一种可在用户端执行的就是 flash 动画格式，在这种动画格式内还可以进行程式设计， 因此用户端只要拥有可以执行 flash 动画的软体，那就可以利用这个软体来达到互动式的对谈。 这些都算是动态网站所提供的功能喔！
    从上面的说明你可以知道动态网站是目前比较热门的，像是近两年来如同雨后春笋一般冒出来的个人部落格 (blog) 就是很经典的动态网站之一。而由图二我们也知道要做成这样的动态网站你必需要有：
    • 支援的作业系统：让所需要的软体都能够安装执行啊；
    • 可运作的 WWW 伺服器：例如 Apache 与 IIS 等 WWW 伺服器平台软体；
    • 网页程式语言：包括 perl, PHP, JSP, CGI, ASP 等等都算是啦！
    • 资料储存之资料库系统：包括 MySQL, MSSQL, PostgreSQL 以及甲骨文 (Oracle) 等等。
    在整个平台设计上面，目前常见的有两大系统，一个是 Linux 作业系统上面，搭配 Apache + MySQL + PHP 等而达成， 这个系统被称为 LAMP 。另一个则是微软的 IIS + MSSQL + ASP (.NET) 伺服器。 在能见度与市占率方面，应该还是以 LAMP 为主吧！ ^_^！上面这三个小东西让我们来谈谈先：

  • Apache (http://www.apache.org)
    • 我们前面提到，1995 年以前就有很多的 WWW 伺服器软体，其中以 HTTPd 占有率较高。 后来 HTTPd 经过多次臭虫的修订后，才在 1995 年后发布 Apache (A patche server) 的啦！这东西就是主要提供 WWW 的伺服器平台，后面谈到的 MySQL 及 PHP 两个咚咚都需要用这玩意儿来处理。

  • PHP (http://www.htm.net/)
    • 按照官方的说法来说，PHP 是一个工具，他可以被用来建立动态网页，PHP 程式码可以直接在 HTML 网页当中嵌入， 就像你在编辑 HTML 网页一样的简单。所以说， PHP 是一种‘程式语言’，这种程式语言可以直接在网页当中编写， 不需要经过编译即可进行程式的执行。由于具有：自由软体、跨平台、容易学习及执行效能高等优点， 目前是很热门的一个设计网页的咚咚喔！你可以在市面上找到很多相关的书籍来参考的。

  • MySQL (http://www.mysql.org/)
    • 传统的档案读取是很麻烦的，如果你只要读取该档案当中的一小部分，系统还是会将整个档案读出来， 若又有多人同时读取同一个档案时，那就会造成效能与系统上的问题，所以才会有资料库系统的推出。 资料库其实是一种特殊格式的档案，这种档案必需要透过特殊介面 (资料库软体) 来进行读写。由于这个特殊介面已经针对资料的查询、写入做过最佳化设计， 因此很适合多人同时写入与查询的工作。

    针对资料库的语法有所谓的 SQL 标准语法，任何根据这种资料检索语法发展出来的资料库，就称为 SQL 资料库。 比较知名的自由软体资料库系统有 MySQL 及 PostgreSQL ，其中 MySQL 的使用率又比较高一些。 MysQL 可以透过网页程式语言来进行读写的工作，因此很适合例如讨论区、论坛等的设计， 甚至很多商业网站的重要资料也是透过 MySQL 这个资料库软体来存取的呢！
    Tips:
    事实上，如果光学会 Linux 与架站，对您自己的竞争力还是不够的， 可以的话，多学一些 MySQL 的 SQL 语法，以及类似 PHP, JSP 等网页程式语言， 对您的未来是很有帮助的喔！ ^_^！对于 MySQL 有兴趣的话，可以看看这里：
    http://linux.tnc.edu.tw/techdoc/mysql/mysql_doc/manual_toc.html     		鸟哥的图示
    小标题的图示 加密的网页资料 (SSL) 及第三方公正单位
    关于 HTTP 这个传输协定当中，你必需要知道的是：‘这个传输协定传输资料是以明码传送的’， 所以你的任何资料封包只要被监听窃取的话，那么该资料就等于是别人的啦！那想一想， 你有过上线刷卡的经验吗？上线刷卡只要输入你信用卡的卡号与相关的截止日期后，就能够进行交易了。 那如果你的资料在 Internet 上面跑时是明码的情况下，真要命！那你的信用卡不就随时可能会被盗用？

    虽然大多数 Internet 上面的 WWW 网站所提供的资料是可以随意浏览的，不过如同上面提到的， 一些物流交易网站的资料以及关于你个人的重要机密资料当然就不能这样随意传送啦！ 这个时候就有需要用到 https://hostname 这种连线的方式啦！这种方式是透过 SSL 加密的机制喔！

  • Secure Socket Layer (SSL)
    • 还记得我们在 SSH 伺服器当中介绍过他连线的机制吧？ 就是利用非配对的 key pair (Public + Private kye) 来组成金钥，然后透过公钥加密后传输， 传输到目标主机后再以私钥来解密，如此一来资料在 Internet 上面跑就以加密的方式， 想当然尔，这些资料自然就比较安全啦！SSL 就是利用在 WWW 传输上面的加密方式啦！

    当浏览器端与 WWW 伺服器端同时支援 SSL 的传输协定时，在连线阶段浏览器与伺服器就会产生那把重要的金钥！ 产生金钥后就能够利用浏览器来传送与接收加密过的重要资料啦！要达成这样的机制， 你的 WWW 伺服器必需要启动 https 这个重要的传输协定，而浏览器则必需要在网址列输入 https:// 开头的网址，那两者才能够进行沟通与连线。要注意的是，在某些很旧的浏览器上面是不支援 SSL 的， 所以在那些旧的浏览器上就无法达成 https 的连线啦！

  • Certificate Authorities (CA)
    • 想一想 SSL 这个机制有什么问题？他的问题就是：‘那把 Public key 是伺服器产生的’！ 这是什么问题？因为 public key 是伺服器产生的，所以那个伺服器如果是诈骗集团所造假产生的网站， 那么你连上去后，即使是加密的资料，到了对方的主机上还是会被解开啊！那就麻烦了～ 这个时候就有第三方公正单位来帮忙啦！

    所谓的 CA 就是一个公认的公正单位，你可以向其注册一个 public key (讲到注册你就要知道.... 这东西是要钱的意思！)， 那么当用户端的浏览器在浏览时，该浏览器会主动的向 CA 单位确认该 public key 是否为合法注册过的， 如果是的话，那么该次连线才会建立，如果不是呢？那么浏览器就会发出警告讯息，告知使用者应避免建立连线啊。 所以说，如此一来 WWW 伺服器不但有公正单位的背书，使用者在建立连线时也比较有保障！
    更多关于 SSL 以及 CA 的介绍，可以约略参考一下：
    • SSL ： http://www.modssl.org/
    • CA 组织之一：https://digitalid.verisign.com/server/apacheNotice.htm
    小标题的图示 用户端常见的浏览器
    咱们前面谈到 WWW 伺服器是 Server/Client 的架构，而用户端使用的软体就是浏览器啊！ 目前比较知名的浏览器主要有两款，包括 Windows 内建的 IE 这玩意儿，另一个则是自由软体 firefox (火狐狸) 。

    由于浏览器可以连结到网际网路上，所以浏览器也有可能被入侵！ 其中由于 IE 直接内嵌至 Windows 的核心当中，所以如果 IE 有漏洞时，对于系统的损害是很大的！ 所以无论如何，请记得‘务必要随时更新到最新版本的浏览器’才行。建议您可以使用 firefox 这个小巧玲珑的浏览器啊！

    除了视窗介面的浏览器软体之外，其实还有两个可以在文字介面底下进行浏览与网页下载的程式， 分别是：
    • lynx：文字介面的浏览器；
    • wget：文字介面下使用来撷取档案的指令。
    这两个指令我们已经在常用网路指令章节谈过了， 请自行前往参考喔！
    大标题的图示 WWW (Apache) 伺服器基本设定
    从前面的说明当中，我们知道在 Linux 上面要达成网页伺服器 (WWW) 需要 Apache 这套伺服器软体呐！ 不过 Apache 仅能提供最基本的静态网站资料而已，想要达成动态网站的话，那么最好还是需要 PHP 与 MySQL 的支援才好。所以底下我们将会以 LAMP (Linux + Apache + MySQL + PHP) 作为安装与设定的介绍， 加油吧！ ^_^

    小标题的图示 LAMP 所需套件与其结构
    既然我们已经是 Linux 作业系统，而且使用的是号称完全相容于 Red Hat Enterprise Linux 的 CentOS 版本， 那当然只要利用 CentOS 本身提供的 Apache, PHP, MySQL 即可！不建议您自行利用 tarball 安装你的 LAMP 伺服器。因为自行安装不但手续麻烦，而且也不见得比系统预设的套件稳定。 除非您有特殊的需求 (例如你的某些 Apache 外挂程式需要较高的版本，或者是 PHP, MysQL 有特殊版本的需求)， 否则请使用 yum 来进行套件的安装即可。

    那么我们的 LAMP 需要哪些东西呢？你必需要知道的是，PHP 是挂在 Apache 底下执行的， 而我们要用网页的 PHP 程式控制 MySQL 时，你的 PHP 就得要支援 MySQL 的模组才行！ 所以你至少需要底下几个套件：
    • httpd
    • mysql
    • mysql-server
    • php
    • php-devel (这个与 PHP 加速软体有关)
    • php-mysql
    要注意， Apache 目前有几种主要版本，包括 1.3.x, 2.0.x, 以及 2.2.x 等等，在 1.3.x 以前的版本通常取名为 apache ，2.x 以后则称为 httpd 啰！请与您的 distribution 比较看看先。至于 CentOS 4.x 则是提供 Apache 2.0.x 这个版本啦。 如果你没有安装的话，请直接使用 yum 或者是原本光碟来安装先：
    [root@linux ~]# yum install httpd mysql-server php php-devel php-mysql
    先来了解一下 Apache 2.0.x 这个版本的相关结构，这样才能够知道如何处理我们的网页资料啊！
    • /etc/httpd/conf/httpd.conf (主要设定档)
      最主要的设定档，其实整个 Apache 也不过就是这个设定档啦！里面真是包山包海啊！ 不过很多其他的 distribution 都将这个档案拆成数个小档案分别管理不同的参数。 但是主要设定档还是以这个档名为主的！你只要找到这个档名就知道如何设定啦！

    • /etc/httpd/conf.d/*.conf (很多的额外参数档，副档名是 .conf)
      这是 CentOS 的特色之一，如果你不想要修改原始设定档 httpd.conf 的话，那么可以将你自己的额外参数档独立出来， 例如你想要有自己的额外设定值，可以将他写入 /etc/httpd/conf.d/vbird.conf (注意，副档名一定是 .conf 才行) 而启动 Apache 时，这个档案就会被读入主要设定档当中了！这有什么好处？好处就是当你系统升级的时候， 你几乎不需要更动原本的设定档，只要将你自己的额外参数档复制到正确的地点即可！ ^_^！维护更方便啦！

    • /usr/lib/httpd/modules/
      Apache 支援很多的模组，所有你想要使用的模组预设是放置在这个目录当中的！

    • /var/www/html/
      这就是我们 CentOS 预设的‘首页’所在目录啦！当你输入‘http://localhost’时所显示的资料所在。

    • /var/www/error/
      如果因为主机设定错误，或者是浏览器端要求的资料错误时，在浏览器上出现的错误讯息就以这个目录的预设讯息为主！

    • /var/www/icons/
      这个目录提供 Apache 预设给予的一些小图示，你可以随意使用啊！当你输入‘http://localhost/icons/’ 时所显示的资料所在。

    • /var/www/cgi-bin/
      预设给一些可执行的 CGI (网页程式) 程式放置的目录；当你输入‘http://localhost/cgi-bin/’ 时所显示的资料所在。

    • /var/log/httpd/
      预设的 Apache 登录档都放在这里，对于流量比较大的网站来说，这个目录要很小心， 因为以鸟哥网站的流量来说，一个星期的登录档资料可以大到 500MBytes 至 1GBytes 左右，所以你务必要修改一下你的 logrotate 让登录档被压缩，否则.....

    • /usr/sbin/apachectl
      这个就是 Apache 的主要执行档，这个执行档其实是 shell script 而已， 他可以主动的侦测系统上面的一些设定值，好让你启动 Apache 时更简单！

    • /usr/sbin/httpd
      呵呵！这个才是主要的 Apache 二进位执行档啦！

    • /usr/bin/htpasswd (Apache 密码保护)
      在某些网页当你想要登入时你需要输入帐号与密码对吧！那 Apache 本身就提供一个最基本的密码保护方式， 该密码的产生就是透过这个指令来达成的！相关的设定方式我们会在 WWW 进阶设定当中说明的。

    至于 MySQL 方面，你需要知道的几个重要目录与档案有：
    • /etc/my.cnf
      这个是 MySQL 的设定档，包括你想要进行 MySQL 资料库的最佳化，或者是针对 MySQL 进行一些额外的参数指定， 都可以在这个档案里面达成的！

    • /var/lib/mysql/
      这个目录则是 MySQL 资料库放置的所在处啦！当你有启动任何 MySQL 的服务时， 请务必记得在备份时，这个目录也要完整的备份下来才行啊！
    另外，在 PHP 方面呢，你应该也要知道几个档案喔：
    • /usr/lib/httpd/modules/libphp4.so
      PHP 这个套件提供给 Apache 使用的模组！这也是我们能否在 Apache 网页上面设计 PHP 程式语言的最重要的咚咚！ 务必要存在才行！

    • /etc/httpd/conf.d/php.conf
      那你要不要手动将该模组写入 httpd.conf 当中？不需要的，因为系统主动将 PHP 设定参数写入这个档案中了！ 而这个档案会在 Apache 重新启动时被读入，所以 OK 的啦！

    • /etc/php.ini
      就是 PHP 的主要设定档，包括你的 PHP 能不能允许使用者上传档案？能不能允许某些低安全性的标志等等， 都在这个设定档当中设定的啦！

    • /etc/php.d/mysql.ini, /usr/lib/php4/mysql.so
      你的 PHP 是否可以支援 MySQL 介面呢？就看这两个东西啦！这两个咚咚是由 php-mysql 套件提供的呢！

    • /usr/bin/phpize, /usr/include/php/
      如果你未来想要安装类似 PHP 加速器以让浏览速度加快的话，那么这个档案与目录就得要存在， 否则加速器软体可无法编译成功喔！这两个资料也是 php-devel 套件所提供的啦！
    基本上我们所需要的几个套件他的结构就是这样啦！上面提到的是 Red Hat 系统 (RHEL, CentOS, FC) 所需的资料， 如果是 SuSE 或其他版本的资料，请依照您的 distribution 管理套件的指令 (rpm 或 dpkg) 去查询一下， 应该就能够知道各个重要资料放置在哪里啦！这些资料很重要，你必需要对放置的地点有点概念才行喔！

    小标题的图示 httpd.conf 的基本设定
    在开始设定 Apache 之前，你要知道由于主机名称对于 WWW 是有意义的，所以虽然利用 IP 也能架设 WWW 伺服器， 不过建议您还是申请一个合法的主机名称比较好。 如果是暂时测试用的主机所以没有主机名称时，那么至少在你的 /etc/hosts 内需要有一行：
    [root@linux ~]# vi /etc/hosts
127.0.0.1   localhost.localdomain localhost
    这样在启动你的 Apache 时才不会发生找不到完整主机名称 (FQDN) 的错误讯息。此外， Apache 只是个伺服器平台而已，你还需要了解 HTML 以及相关的网页设计语法， 如此才能丰富你的网站。对于想要设计网页的朋友来说，应用软体或许是很好入门， 不过想要完整的了解网站设计的技巧，还是研究一下基础的 HTML 或 CSS 比较妥当。 台湾有个不错的网站介绍给你：
      网站建置百宝箱： http://dob.tnc.edu.tw/
    你可以在上头发现不少的网页制作范例，包括一些特殊的功能喔！如果你真的对于一些基础语法有兴趣， 并且也想要开发一些所谓的‘无障碍网页空间’的话，那么可以造访一下 http://www.w3c.org 所列举的标准语法，或者是行政院的无障碍网页空间申请规范 (http://enable.nat.gov.tw/) 相信会有所收获的啦！

    终于要来谈一谈如何设定 Apache 这个 httpd.conf 设定档了！再次强调，每个 distribution 的这个档案内容都不很相同，所以你必需要自行找出相关的设定档才行喔！那么这个 httpd.conf 的设定为何呢？他的基本设定是这样的：
    <设定项目>
    此设定项目内的相关参数
    ...........
</设定项目>
    举例来说，如果你想要针对我们的首页 /var/www/html/ 这个目录提供一些额外的功能，那么：
    <Directory "/var/www/html">
    Options Indexes
    ...........
</Directory>
    几乎都是这样的设定方式喔！特别留意的是，如果你有额外的设定时，不能随便在 httpd.conf 里头找地方写入！否则如果刚好写在 <Directory>...</Directory> 里面，呼呼！ 那么就会发生错误啦！需要前前后后的找一找喔！好啦，底下咱们先来聊一聊 Apache 主机的基础设定吧！
    Tips:
    事实上在 Apache 的网页有提供很多详细的文件资料，真的是很详细啦！ 鸟哥在底下仅是介绍一些惯用的设定项目的意义而已。有兴趣的话，请务必要前往查阅：
    Apache 2.0 核心文件：http://httpd.apache.org/docs/2.0/mod/core.html     		鸟哥的图示
  • 针对主机环境的设定项目
    • Apache 针对主机的设定项目方面，包括回应给用户端的主机版本、主机名称、主机设定档顶层目录等。 底下咱们就来谈一谈：
    [root@linux ~]# vi /etc/httpd/conf/httpd.conf
ServerTokens OS
# 这个项目在告知用户端 WWW 伺服器的版本与作业系统。不需要更动他。
# 如果你不想要告知太多主机的资讯，这个项目将 OS 改成 Minor 吧！

ServerRoot "/etc/httpd"
# 这个是设定档的最顶层目录，通常使用绝对路径。底下某些设定资料使用相对路径时，
# 就是与这个设定值有关的下层目录啦！不需要更动他。

PidFile run/httpd.pid
# 放置 PID 的档案，可方便 Apache 软体的管理啦！只有相对路径吧！
# 考虑 ServerRoot 设定值，所以档案在 /etc/httpd/run/httpd.pid ！

Timeout 120
# 持续连线阶段如果等待超过 120 秒则该次连线就中断。
# 一般来说，此数值在 300 秒左右即可，不需要修改这个原始值啦。

KeepAlive On    <==最好将预设的 Off 改为 On 啦！
# 是否允许持续性的连线，亦即一个 TCP 连线可以具有多个档案资料传送的要求。
# 举例来说，如果你的网页内含很多图档，那么这一次连线就会将所有的资料送完，
# 而不必每个图档都需要进行一次 TCP 连线。预设为 Off 请改为 On 较佳。

MaxKeepAliveRequests 500  <==可以将原本的 100 改为 500 或更高
# 与上个设定值 KeepAlive 有关，当 KeepAlive 设定为 On 时，则这个数值可决定
# 该次连线能够传输的最大传输数量。为了增进效能则可以改大一点！0 代表不限制。

KeepAliveTimeout 15
# 在允许 KeepAlive 的条件下，则该次连线在最后一次传输后等待延迟的秒数。
# 当超过上述秒数则该连线将中断。设定 15 差不多啦！如果设定太高 (等待时间较长)，
# 在较忙碌的系统上面将会有较多的 Apache 程序占用资源，可能有效能方面的困扰。

<IfModule prefork.c>
StartServers       8
MinSpareServers    5
MaxSpareServers   20
ServerLimit      256
MaxClients       256
MaxRequestsPerChild  4000
</IfModule>
<IfModule worker.c>
StartServers         2
MaxClients         150
MinSpareThreads     25
MaxSpareThreads     75
ThreadsPerChild     25
MaxRequestsPerChild  0
</IfModule>
# 上面这一串其实是两个与伺服器连线资源有关的设定项目。预设的项目对于一般
# 小型网站来说已经很够用了，不过如果你的流量比较大时，或许可以修订一下呢！
# 这两个模组都是用在提供使用者连线的资源 (process)，设定的数量越大时，
# 代表系统会启动比较多的程序来提供 Apache 的服务，反应速度就比较快。
# a. 针对模组来说：
#    worker 模组占用的记忆体较小，对于流量较大的网站来说，是一个比较好的选择
#    profork 虽然占用较大的记忆体，不过速度与 worker 差异不大，并且 prefork
#    记忆体使用设计较为优秀，可以在很多无法提供 debug 的平台上面进行自我除错
# b. 细部设定的内容方面：(以 Prefork 为例， worker 意义相同)
#    StartServers 代表启动 Apache 时就启动的 process 数量
#    MinSpareServers, MaxSareServers 代表最大与最小的备用程序数量
#    MaxClients 最大的同时连线数量，也就是 process 数不会超过此一数量。
#         假设有 10 个人连上来，则 apache 的程序数应有 15-30 个之意。
#    MaxRequestsPerChild 每个程序能够提供的最大传输次数要求。举例来说，
#         如果有个使用者连上伺服器后(一个 process)，却要求数百个网页，
#         当他的要求数量超过此一数值，则该程序会被丢弃，另外切换一个新程序。
#         这个设定可以有效的控管每个 process 在系统上的‘存活时间’。
# 除非你的网站流量特别大，否则上面的预设值已经够你使用的了。而如果你的记忆体
# 不够大的话，那么 MaxClients 反而要调小一点，例如 150 ，否则效能不佳。

Listen 80
# 与监听介面有关，预设开放在所有的网路介面啊！也可修改埠口，如 8080

LoadModule access_module modules/mod_access.so
.....(底下省略).....
# 载入模组的设定项目。Apache 提供很多有用的模组给我们使用了！

Include conf.d/*.conf
# 因为这一行，所以放置到 /etc/httpd/conf.d/*.conf 的设定都会被读入

User apache
Group apache
# 前面提到的 prework, worker 等模组所启动的 process 之拥有者与群组设定。
# 这个设定很重要，因为未来你提供的网页档案能不能被浏览都与这个身份有关啊！

ServerAdmin dmtsai@linux.vbird.tsai  <==改成你自己的 email 吧
# 系统管理员的 email ，当网站出现问题时，错误讯息显示的联络信箱。

ServerName linux.vbird.tsai    <==自行设定好自己的主机名称较佳！
# 设定主机名称，如果没有指定的话，预设会以你的 hostname 为依据。
# 千万记得，你填入的这个主机名称要找的到 IP 喔！(DNS 或 /etc/hosts)

UseCanonicalName Off
# 是否使用标准主机名称？如果你的主机有多个主机名称，若这个设定为 On，
# 那么 Apache 只接受上头 servername 指定的主机名称连线而已。请使用 Off。
    在基本设定项目比较有趣的在于系统的效能议题啦！初次接触的朋友可能会觉得很好奇，怎么两个多执行绪模组 (worker 与 prefork) 有个 MaxClients 的设定，那么那个 MaxKeepAliveRequests 又是什么？ 你可以这么想：
    • MaxClients 控制可以‘同时连上 WWW 伺服器的总连线要求’数量，亦即想成最高即时线上人数啦；
    • MaxKeepAliveRequests 则是每个 Clients 的该次连线中，可以要求的最高传输资料量。
    这样说的话，对于连线有没有较清楚的概念啰？不过你要注意的是，那个 MaxClients 的数量不是越高越好， 因为他会消耗实体记忆体，所以如果你设定太高导致超出实体记忆体能够容许的范围， 那么效能反而会降低 (因为系统会使用速度较慢的 swap 啊！)，此外， MaxClients 也在 Apache 编译时就指定最大值了，所以你也无法超出系统最大值，除非....你重新编译 Apache 啦！

    那，apache 到底是使用那个模组啊？prefork 还是 worker ？事实上 CentOS 将这两个模组分别放到不同的执行档当中，分别是：
    • /usr/sbin/httpd：使用 prefork 模组；
    • /usr/sbin/httpd.worker：使用 worker 模组。
    那如何决定你使用的是哪一支程式？你可以去查阅一下 /etc/sysconfig/httpd ， 就能够知道系统预设提供 prefork 模组，但你可以透过修改 /etc/sysconfig/httpd 来使用 worker 模组的。 如果你很有好奇心，那么可以分别试着启动这两种模组啊！ ^_^

  • 针对中文 big5 编码语系
    • 目前的网际网路传输的资料编码多是以万国码 (UTF-8) 为主，不过在台湾还是有相当多的网站使用的是 Big5 的繁体中文编码的啊！如果你的 Apache 预设是以 UTF-8 编码来传输资料，但你 WWW 的资料却是 big5 ， 那么用户端将会看到‘乱码’！虽然可以透过调整浏览器的编码来让资料正确显示，不过总是觉得很讨厌。 此时，你应该可以调整一下底下的两个参数的喔！
    [root@linux ~]# vi /etc/httpd/conf/httpd.conf
# 先确定有底下这几行，理论上，应该都会有这几行啦！
AddLanguage zh-TW .zh-tw
AddCharset  Big5        .Big5       .big5

# 找到底下这一行，应该是在 730 行左右
AddDefaultCharset UTF-8
# 你有两种作法，一种是‘直接指定由 WWW 宣告 Big5 编码，而不用网页表头的宣告’：
AddDefaultCharset Big5
# 另一种则是不要宣告预设语系，由网页表头宣告的啦！直接注解起来即可
# AddDefaultCharset Big5

# 找到底下这一行(大约在 711 行)，这一行在设定显示语系的优先顺序
LanguagePriority en ca ....(中间省略).... sv zh-CN zh-TW
# 将语系处理的优先顺序中，以中文为优先吧！
LanguagePriority zh-TW en ca ....(中间省略).... sv zh-CN
    你必须要注意的是，如果你已经在用户端浏览器上面浏览过非 Big5 的网页， 那么你修改过这个设定值后，仍然要将浏览器的快取 (cache) 清除才行！否则仍然会看到乱码！网友们已经回报过很多次了， 这不是 Apache 的问题，而是用户端浏览器的快取所产生的啦！记得处理处理！

    另外，有没有‘ AddDefaultCharset Big5 ’这一个设定值的存在是差很多的！ 如果你指定这个设定项目后，代表‘由 WWW 发送到用户端的网页预设将都以 Big5 编码为主’， 所以如果你在 /var/www/html/ 内的网页资料有 big5, utf8 不同编码的话，那么使用 utf8 编码的网页将会在浏览器上面显示乱码！最好的作法是将该设定值注解掉，然后再你的网页上面写入：
    <html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=big5" >
    ....其他省略....
    这样一来你的网页就会向浏览器说明编码的格式，嘿嘿！就可以正确的显示出中文了！

  • 首页权限相关设定 (DocumentRoot 与 Directory)
    • 开头的时候不是讲过 CentOS 的 Apache 预设首页放置在 /var/www/html 这个目录吗？ 为什么呢？因为 DocumentRoot 这个设定值的关系啦！此外，由于 Apache 允许 Internet 对我们的资料进行浏览， 所以你当然必须要针对可被浏览的目录进行权限的相关设定，那就是 <Directory> 这个设定值的重要特色！先让我们来看看预设的主网页设定吧！
    [root@linux ~]# vi /etc/httpd/conf/httpd.conf
DocumentRoot "/var/www/html"  <==可以改成你放置首页的目录！
# 这个设定值重要到不行，因为他规范了 WWW 伺服器主网页所放置的‘目录’所在。
# 这个设定值是可以被随意更动的，不过更动之后你必须要针对该目录进行权限设定，
# 也就是底下要讲到的 Directory 这个设定值来规范目录的权限才行喔！

<Directory />
    Options FollowSymLinks
    AllowOverride None
</Directory>
# 这个设定值是针对 WWW 伺服器的‘预设环境’而来的，因为针对‘/’的设定嘛！
# 建议可以设定的严格一点，就是保留上述的预设设定即可 (已经很严格了！)

<Directory "/var/www/html">
    Options Indexes FollowSymLinks  <==建议拿掉 Indexes 比较妥当！
    AllowOverride None
    Order allow,deny
    Allow from all
</Directory>
    这个地方则是针对 /var/www/html 这个目录来设定权限啦！就是咱们首页所在目录的权限。 主要的几个设定项目的意义是这样的：
    1. Options：
      表示这个目录内能够进行的动作，亦即是权限设定啦！主要的设定值：
      • Indexes：
        如果在此目录下找不到‘首页档案’时， 就显示整个目录下的档案名称，‘首页档案’与 DirectoryIndex 设定值有关。
      • FollowSymLinks：
        让在此目录下的连结档可以连结出此目录外。 一般来说被 chroot 的程式将无法离开其目录，也就是说预设的情况下，你在 /var/www/html 底下的连结档只要连结到非此目录的其他地方，则该连结档预设是失效的。 但使用此设定即可让连结档有效的离开本目录。
      • ExecCGI：
        让此目录具有执行 CGI 程式的权限，非常重要！举例来说，目前常见的 OpenWebMail 使用了很多的 perl 的程式， 你要让 openwebmail 可以执行，就得要在 openwebmail 程式所在目录 拥有 ExecCGI 的权限。注意，不要让所有目录均可使用 ExecCGI ！
      • Includes：
        让一些 Server-Side Include 程式可以运作。建议可以加上去！
      • MultiViews：
        这玩意儿有点像是多国语言的支持，与语系资料 (LanguagePriority) 有关。最常见在错误讯息的回报内容，在同一部主机当中， 可以依据用户端的语系而给予不同的语言显示呢！预设在错误回报讯息当中存在， 你可以检查一下 /var/www/error/ 目录下的资料喔！

    2. AllowOverride：
      表示是否允许额外设定档 .htaccess 的权限复写？我们可以在 httpd.conf 内设定好所有的权限，不过如此一来若使用者自己的个人网页想要修改权限时将会对管理员造成困扰。因此 Apache 预设可以让使用者以目录底下的 .htaccess 档案内复写 <Directory> 内的权限设定。 这个项目则是在规定 .htaccess 可以复写的权限类型有哪些。常见的有：
      • ALL：全部的权限均可被复写；
      • AuthConfig：仅有网页认证 (帐号密码) 可复写；
      • Indexes：仅允许 Indexes 方面的复写；
      • Limits：允许使用者利用 Allow, Deny 与 Order 管理可浏览的权限；
      • None：不可复写，亦即 .htaccess 档案失效去！
      这部份我们在进阶设定时会再讲到的！

    3. Order：
      决定是否可被浏览的权限设定啦！主要有两种方式：
      • deny,allow：以 deny 优先处理，但没有写入规则的则预设为 allow 喔。
      • allow,deny：以 allow 为优先处理，但没有写入规则的则预设为 deny 喔。
      所以在预设的环境中，因为是 allow,deny 所以预设为 deny (不可浏览)， 不过在下一行有个 Allow from all ，allow 优先处理，因此全部(all) 用户端皆可浏览啦！这部份我们会在进阶安全设定当中再提及低。
    除了这些资料之外，你还得要知道的是底下这个玩意儿：
    [root@linux ~]# vi /etc/httpd/conf/httpd.conf
DirectoryIndex index.html index.html.var  <==可能需要修改的项目！
# 如果用户端在网址列只输入到目录，例如 http://localhost/ 时，那么 Apache
# 将拿出那个档案来显示？这个档案也被称为预设的首页啦！一般来说是以
# index.* 为档名开头，但 Windows 则以 default.asp 之类的档名为开头的。
# 如果你想要让类似 index.pl 或 index.cgi 也可以是首页，那可以改成：
# DirectoryIndex index.html index.htm index.cgi index.htm3 ...
# 这个项目与刚刚谈到的 Options 里面的 Indexes 有关喔！

Alias /icons/ "/var/www/icons/"
<Directory "/var/www/icons">
    Options Indexes MultiViews
    AllowOverride None
    Order allow,deny
    Allow from all
</Directory>
# 这个 Alias 很有趣的！是制作出类似连结档的东西啦！
# 当你输入 http://localhost/icons 时，其实你的 /var/www/html 并没有 icons
# 那个目录，不过由于 Alias 的关系，会让该网址直接连结到 /var/www/icons/ 下。
# 这里面预设有很多 Apache 提供的小图示喔！而因为设定了一个新的可浏览目录，
# 所以你瞧，多了个 <Directory> 来规定权限了吧！ ^_^

ScriptAlias /cgi-bin/ "/var/www/cgi-bin/"
<Directory "/var/www/cgi-bin">
    AllowOverride None
    Options None
    Order allow,deny
    Allow from all
</Directory>
# 与上面的 icons 类似，不过这边却是以 ScriptAlias 为设定值！
# 这个设定值可以指定该目录底下为‘具有 ExecCGI ’能力的目录所在喔！
# 所以你可以将类似 Open webmail 的程式给他放置到 /var/www/cgi-bin 内，
# 就不必额外设定其他的目录来放置你的 CGI 程式喔！
    这样大概就 OK 了啦！接下来准备一下看看还有哪些额外的设定档需要处理的呢？

    小标题的图示 PHP 等额外设定档
    约略谈了谈 httpd.conf 之后，你应该会发现一件事情，那就是‘我们怎么没有讲到 PHP 这个模组的设定啊？’ 不是不讲啦！而是因为目前 Apache 很聪明的将一些重要模组给他拆出来放置到 /etc/httpd/conf.d/ 这个目录下了， 所以我们必须要到该目录下才能了解到某些模组是否有被加入啊！底下先来瞧瞧吧！
    [root@linux ~]# cd /etc/httpd/conf.d
[root@linux conf.d]# ll *.conf
-rw-r--r--  1 root root 448 Sep 21 20:13 php.conf
-rw-r--r--  1 root root 299 Aug 13 16:33 welcome.conf
# 如果你是按照刚刚鸟哥说的几个模组去安装的，那么这个目录下至少会有这两个资料，
# 一个是规范 PHP 设定，一个则是规范‘如果首页不存在时的欢迎画面’啰。
    我们主要来看看关于 PHP 的设定档吧：
    [root@linux ~]# vi /etc/httpd/conf.d/php.conf
LoadModule     php4_module modules/libphp4.so
AddType        application/x-httpd-php .htm
DirectoryIndex index.htm
    这三行分别代表载入 PHP 模组、增加附档名为 .htm 的档案处理方式，以及将 index.htm 增加成为首页档名。所以如果你在 /var/www/html 这个首页目录内新增一个档名为 index.htm 时，他可以被使用为首页显示啦！基本上你不需要进行任何修改，这个档案就能够让你的 Apache 支援 PHP 模组与语法了！

    另外你也必须要知道 PHP 的设定档是在 /etc/php.ini ，这个档案内容有某些地方可以进行一些小修改， 也有某些地方你必须要特别留意，免得被用户端误用你的 PHP 资源：
    [root@linux ~]# vi /etc/php.ini
register_globals = Off
# 这个项目请确定为 Off (预设就是 Off)，因为如果设定为 On 时，
# 虽然程式执行比较不容易出状况，但是很容易不小心就被攻击。

log_errors = On
ignore_repeated_errors = On
ignore_repeated_source = On
# 这三个设定项目可以决定是否要将 PHP 程式的错误记录起来，
# 建议将将重复的错误资料忽略掉，否则在很忙碌的系统上，
# 这些错误资料将可能造成你的登录档暴增，导致效能不佳 (或当机)

display_errors = Off
display_startup_errors = Off
# 当你的程式发生问题时，是否要在浏览器上头显示相关的错误讯息 (包括部分程式码)
# 强烈的建议设定为 Off 。不过如果是尚未开放的 WWW 伺服器，为了你的 debug
# 容易，可以暂时的将他设定为 On ，如此一来你的程式问题会在浏览器上面
# 直接显示出来，你不需要进入 /var/log/httpd/error_log 登录当中查阅。
# 但程式完成后，记得将此设定值改为 Off 喔！重要重要！
    如果你想要提供 Apache 的说明文件给自己的 WWW 伺服器的话， 可以安装一下 httpd-manual 这个套件，你就会发现在这个目录当中又会新增档案 (manual.conf) ，而且从此你可以使用 http://localhost/manual 来登入 Apache 的使用手册呢！真方便！ 有兴趣的话可以参考与安装底下这些套件喔：
    • httpd-manual：提供 Apache 参考文件的一个套件；
    • mrtg：利用类似绘图软体自动产生主机流量图表的套件；
    • mod_perl：让你的 WWW 伺服器支援 perl 写的网页程式(例如 webmail 程式)；
    • mod_python：让你的 WWW 伺服器支援 python 写的网页程式。
    • mod_ssl：让你的 WWW 可以支援 https 这种加密过后的传输模式。
    perl 与 python 是与 PHP 类似的咚咚，都是一些很常用在网页的程式语言！ 例如知名的 OpenWebMail (http://turtle.ee.ncku.edu.tw/~tung/openwebmail/) 就是利用 perl 写成的。要让你的 WWW 支援该程式语言， 你就得要安装这些东西啦！(但不是所有的套件都安装！请安装你需要的即可！)

    小标题的图示 Apache 的启动与 PHP 的测试
    OK！终于设定好一些资料啰，接下来就是要启动 Apache 啦！启动的方法简单到不行，用传统的方式来处理：
    [root@linux ~]# /etc/init.d/httpd start  <==启动啦！
[root@linux ~]# /etc/init.d/httpd stop   <==关闭 WWW 啦！
    另外，其实 Apache 也自行提供一支 script 可以让我们来简单的使用，那就是 apachectl 这支程式啦！
    [root@linux ~]# /usr/sbin/apachectl start  <==启动啦！
[root@linux ~]# /usr/sbin/apachectl stop   <==关闭 WWW 啦！
    几乎是一模一样的咚咚啦！你只要记得其中一个即可。一般建议你可以稍微记一下 apachectl 这支程式， 因为很多认证考试会考，而且他也是 Apache 预设提供的一个管理指令说！好了，来看看有没有启动成功？
    [root@linux ~]# netstat -tunl | grep ':80'
tcp   0      0 :::80    :::*    LISTEN
# 看看， port 80 启动了！接下来看看登录档先！

[root@linux ~]# tail /var/log/httpd/error_log
[Mon Nov 06 00:38:42 2006] [notice] Apache/2.0.52 (CentOS) configured
-- resuming normal operations
    这样应该就成功启动了 Apache 啰！接下来测试看看能不能看到网页呢？ 首先看看 /var/www/html 有没有资料？咦？没有～没关系，因为 CentOS 帮我们造了一个测试页了， 所以你还是在浏览器上面输入你这部主机的 IP 看看先：

    Apache 主网页的测试画面
    图三、Apache 主网页的测试画面

    如果看到这一页，恭喜您，你的 Apache 已经顺利启动了！你可以快快乐乐的开始制作您自己的专属网页！ 但如果想要知道有没有成功的驱动 PHP 模组，那你最好先到 /var/www/html 目录下去建立一个简单的档案：
    [root@linux ~]# vi /var/www/html/phpinfo.htm
<?php
phpinfo();
?>
    那个‘ <?php ... ?> ’是 PHP 模组的网页嵌入式程式语法，在这中间的就是 PHP 的程式码啦。 那个‘ phpinfo() ’是特殊的 PHP 函数，可以显示出目前你 WWW 伺服器内 PHP 模组的相关核心资料。 写完之后立刻以浏览器再查阅这个档案看看：

    Apache 网页的 PHP 测试画面
    图四、Apache 网页的 PHP 测试画面

    注意看网址的部分喔！档名不要写错了！而且这个档案仅是在作为测试之用，事实上内容提供的资料还挺机密的， 所以测试完毕后请将这个档案删除吧！从底下的画面你可以知道 PHP 模组的版本以及 Apache 相关的重要资料啦！自己仔细瞧瞧吧！ ^_^！如此一来，你的 Apache 与 PHP 就 OK 的啦！

    那万一测试失败怎么办？常见的错误问题以及解决之道可以参考：
    • 网路问题：虽然在本机上没有问题， 但不代表网路一定是通的！请确认一下网路状态！例如 Route table, 拨接情况等等；
    • 网页问题：例如鸟哥第一次以 Tarball 安装好之后，竟然发现无法显示主机的首页！后来才发现是主机的首页设定错误！ 导致找不到网页，这个时候，请特别留意浏览器上面的显示讯息，里面包含了无法连进来主机的问题！ 请提供这样的讯息到讨论区，大家才知道问题出在哪里呐！
    • 权限问题：例如你刚刚在 httpd.conf 上面的 user 设定为 apache 了，但偏偏要被浏览的目录权限为 750 ，自然就无法让人家连线进去啦！
    • 问题的解决之道：如果还是没有办法连接上来你的 Linux Apache 主机，那么请：
      1. 察看 /var/log/httpd/error_log 这个档案吧！他应该可以告诉你很多的资讯喔！
      2. 另外，也要仔细的察看一下你的浏览器上面显示的资讯，这样才能够知道问题出在哪里！ ^_^
      3. 另一个可能则是防火墙啦！察看一下 iptables 的讯息！也可能是 SELinux 忘记关！
    小标题的图示 MySQL 资料库的启动与测试
    虽然我们已经启动了基本的 Apache 以及 PHP 模组了，不过，那个重要的资料库尚未启动吧？没错～ 在这个小节里面我们就来启动一下 MySQL 吧！在启动 MySQL 前其实系统并没有帮我们建立任何的资料库。 当你初次启动 MySQL 后，系统才会针对资料库进行初始化的建立啊。不相信的话你可以先看看 /var/lib/mysql 这个目录，里面其实没有任何资料的啦。

  • 启动 MySQL (设定 MySQL root 密码与新增 MysQL 用户帐号)
    • 首先得要启动 MySQL 才行，启动的方法还是很简单啊！
    [root@linux ~]# /etc/init.d/mysqld start
# 如果是初次使用这个指令来启动，你的 /var/lib/mysql 会建立资料库。

[root@linux ~]# netstat -tuln | grep ':3306'
tcp  0      0 0.0.0.0:3306   0.0.0.0:*   LISTEN

# 底下在测试看能否以手动的方式连上 MySQL 资料库！
[root@linux ~]# mysql -u root
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 2 to server version: 4.1.20

Type 'help;' or '\h' for help. Type '\c' to clear the buffer.

mysql> quit
Bye
    MySQL 预设监听的埠口在 3306 号，从上面看来我们的 MySQL 似乎是启动了， 不过刚刚初始化的 MySQL 资料库并没有任何密码， 所以很可能我们的资料库是会被使用者搞烂掉的～所以你最好对 MySQL 设定一下密码才好。 另外，上面那个 root 与我们 Linux 帐号的 root 是完全无关的！因为 MySQL 资料库软体也是个多人的操作环境，在该软体内有个管理者恰好帐号也是 root 而已。

    那么如何针对 MySQL 这个软体内的 root 这个管理者设定他的密码呢？你可以这样做：
    [root@linux ~]# mysqladmin -u root password 'your.password'
# 从此以后 MySQL 的 root 帐号就需要密码了！如下所示：

[root@linux ~]# mysql -u root -p
Enter password:  <==你必须要在这里输入刚刚建立的密码！
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 4 to server version: 4.1.20

Type 'help;' or '\h' for help. Type '\c' to clear the buffer.

mysql>quit
    如此一来 MySQL 资料库会比较安全些啦！其实更好的作法是分别建立不同的使用者管理不同的资料库。 举例来说，如果你要给予 dmtsai 这个使用者一个 MySQL 的资料库使用权， 假设你要给他的资料库名称为 dmtsai ，那么你可以这样做：
    [root@linux ~]# mysql -u root -p
Enter password:  <==如前所述，你必须要输入密码嘛！
mysql> create database dmtsai;  <==注意每个指令后面都要加上分号 (;)
Query OK, 1 row affected (0.01 sec)

mysql> grant all privileges on dmtsai.* to dmtsai@localhost
identified by 'your.password' ;
Query OK, 0 rows affected (0.00 sec)

mysql> show databases;
+----------+
| Database |
+----------+
| dmtsai   |  <==看见没？多一个这个资料库啦！
| mysql    |  <==主要用来记录 MySQL 的帐号、主机等等重要资讯的主要资料库！
| test     |
+----------+
3 rows in set (0.00 sec)

mysql> exit
    然后你可以利用‘ mysql -u dmtsai -p ’这个指令来尝试登入 MySQL 试看看，嘿嘿！就知道 dmtsai 这个使用者在 MySQL 里面拥有一个名称为 dmtsai 的资料库啦！其他更多的用法就得请您自行参考 SQL 相关的语法啰！不在本文的讨论范围啦！

  • 效能调校 /etc/my.cnf
    • 由于 MySQL 这个资料库系统如果在很多使用者同时连线时，可能会造成某些效能方面的瓶颈， 不过，我们可以透过简单的设定来进一步处理 MySQL 资料库呢！相关的资料鸟哥是参考这一篇简单的中文说明：
    • http://parus1974.wordpress.com/2005/02/27/mysql再调整
    [root@linux ~]# vi /etc/my.cnf
[mysqld]
default-storage-engine=innodb
# 关于目录资料与语系的设定等等；
datadir                 = /var/lib/mysql
socket                  = /var/lib/mysql/mysql.sock
default-character-set   = utf8   <==每个人的编码都不相同，不要随意跟我一样
port                    = 3306
skip-locking
# 关于记忆体的设定，注意，记忆体的简单计算方式为：
# key_buffer + (sort_buffer + read_buffer ) * max_connection
# 且总量不可高于实际的实体记忆体量！所以，我底下的资料应该是 OK 的
# 128 + (2+2)*150 = 728MB
key_buffer              = 128M
sort_buffer_size        = 2M
read_buffer_size        = 2M
join_buffer_size        = 2M
max_connections         = 150
max_connect_errors      = 10
read_rnd_buffer_size    = 4M
max_allowed_packet      = 4M
table_cache             = 1024
myisam_sort_buffer_size = 32M
thread_cache            = 16
query_cache_size        = 16M
tmp_table_size          = 64M
# 由连线到确定断线的时间，原本是 28800 (sec) ，约 8 小时，我将他改为 20 分钟！
wait_timeout            = 1200
thread_concurrency      = 8
old_passwords=1
innodb_data_file_path = ibdata1:10M:autoextend
innodb_buffer_pool_size = 128M
innodb_additional_mem_pool_size = 32M
innodb_thread_concurrency = 16

[mysql.server]
user=mysql
basedir=/var/lib

[mysqld_safe]
err-log=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid
    你要注意的是，因为鸟哥的主机上面假设记忆体有 2GB 啊！所以跟记忆体相关的资料才会写很大！ 请依照你实际拥有的记忆体量来处理喔！还得加上你的 Apache 本身的记忆体用量！ 所以.....如果你的网站流量很大的话，在校能测试上面要很注意啊！

  • MysQL root 密码忘记的紧急处理
    • 如果你不小心忘记 MySQL 的密码怎么办？网路上有一些工具可以让你去处理 MySQL 资料库的挽回。 如果你的资料库内容并不是很重要，删除也无所谓的话 (测试中 @_@)，那么可以将 MySQL 关闭后， 将 /var/lib/mysql 那个目录整个删除掉，然后再重新启动 MySQL ，那么 MySQL 资料库会重建， 你的 root 又没有密码啦！

    不过，这个方法仅适合你的资料库并不重要的时候，如果资料库很重要..... 那千万不要随便删除啊！
    小标题的图示 开始网页设计及安装架站软体，如 phpBB2
    基础的 Apache 架设完毕之后，基本上，你就可以开始设计你想要的网站啰！ 编写网页的工具很多，请自行寻找吧！不过你必须要知道的是：
    • 预设的首页在 /var/www/html/ 目录喔，你应该将所有的 WWW 资料都搬到该目录底下才对！
    • 如果首页想要建立在其他地方，你应该要修改 DocumentRoot 那个参数 (httpd.conf)
    • 如果你需要安装一些 CGI 程式的话，建议你将他安装到 /var/www/cgi-bin/ 底下， 如此一来你不需要额外设定 httpd.conf 即可顺利启动 CGI 程式；
    • 注意你的资料权限！务必要让 Apache 的程序使用者 (预设是 apache) 能够浏览！
    • 不要将重要资料或者隐私资料放置到 /var/www/html/ 首页内！
    • 尽量将你的首页档案档名取为 index.html 或 index.htm ！
    除了这些基本的项目之外，其实你可以使用网际网路上面人家已经做好的 PHP 程式架站机喔！ 譬如说讨论区软体 phpBB2 这个玩意儿，完整的架站软体 PHPNuke 以及部落格软体 lifetype 等等。 但这些架站机都需要 PHP 与资料库的支援，所以你必需要将上述介绍的 LAMP 完整的安装好才行。 如果你不喜欢自己写网页的话，那么这些有用的架站软体就够你瞧的啰！鸟哥列出几个连结给你玩一玩先！
    • phpBB 官方网站：http://www.htmbb.com/
    • phpBB 正体中文网站‘竹猫星球’：http://phpbb-tw.net
    • 鸟哥的简易 phpBB2 安装法：http://linux.vbird.org/apache_packages/
    • Lifetype 部落格架设软体中文支援站：http://www.lifetype.org.tw/
    • Lifetype 部落格架设软体官网：http://www.lifetype.net/
    • PHP-Nuke 官方网站：http://phpnuke.org/
    • xoops 官方网站：http://www.xoops.org/
    不过请注意，这些软体由于是公开的，所以有些怪叔叔可能会据以乱用或乱改， 因此可能会有一些 bug 会出现！因此，你必需要取得最新的版本来玩才行， 而且架设之后还得要持续的观察是否有更新的版本出现，随时去更新到最新版本才行喔！ 免得后患无穷～
    大标题的图示 Apache 伺服器的进阶设定
    事实上刚刚上头的基本设定已经很足够朋友们架设 WWW 伺服器所需了！不过，还有很多可以玩玩的地方， 例如个人用户首页、虚拟主机以及认证保护的网页等等。底下我们分别来谈一谈啰！ ^_^

    小标题的图示 启动用户的个人网站 (权限是重点)
    每一部主机都有一个首页，但是如果每个个人用户都想要有可以自己完全控管的首页时， 那该如何设计？呵呵！Apache 早就帮我们想到了！不过新版的设定档内常常是预设将这个功能取消的， 所以你必需要自行修订呢！
    [root@linux ~]# vi /etc/httpd/conf/httpd.conf
# 找到如下的设定项目，大约在 340 行左右：
<IfModule mod_userdir.c>
    UserDir disable
    #UserDir public_html
</IfModule>
# 将他改成如下的情况喔！
<IfModule mod_userdir.c>
    #UserDir disable
    UserDir public_html
</IfModule>

# 重新启动一下先！
[root@linux ~]# /etc/init.d/httpd restart
    这只是个范例，Apache 预设的个人首页是放置在家目录下的 public_html/ 目录下！假如 dmtsai 的家目录在 /home/dmtsai，那么他的个人首页预设在 /home/dmtsai/public_html/ 啰！你当然可以修改这个目录名称， 只要将上表的 UserDir 内容改掉即可。例如改为 www 时，使用者的个人首页则放在家目录下的 www 目录中。 设定完毕后得要重新启动你的 apache 喔！

    例题：
    如何让未来所有‘新增’的使用者预设家目录下都有个 www 的目录？
    答：
      因为新增使用者时所参考的家目录在 /etc/skel 目录内，所以你可以直接 mkdir /etc/skel/www 即可。

    好了，假设你的主机有个 dmtsai 的用户，那么这家伙怎么建立他的个人首页？ 我们这样测试一下好了！(底下的工作请以你的一般身份使用者处理)：
    [dmtsai@linux ~]$ cd ~
[dmtsai@linux ~]$ mkdir public_html
[dmtsai@linux ~]$ chmod 755 public_html
[dmtsai@linux ~]$ chmod 755 ~
[dmtsai@linux ~]$ cd public_html
[dmtsai@linux public_html]$ echo "Test your home" >> index.html
    由于 CentOS 预设的使用者家目录权限是 drwx------ ，这个权限将无法让 Apache 的程序浏览啊！ 所以你至少要让你的家目录与 public_html 目录的权限成为 drwxr-xr-x 才行！这个很重要啊！ 那么未来只要你在浏览器的网址列这样输入：
      http://你的主机名称/~dmtsai/
    就可以看到你的使用者个人网页啰！之后让使用者自己去设计他的网站吧！ 现在你知道那个毛毛虫 (~) 的意义了吧？ ^_^！不过，多这个毛毛虫就很讨厌～ 我可不可以将使用者的个人网站设定成为：
      http://你的主机名称/dmtsai/
    是可以啦！最简单的方法是这样的：
    [root@linux ~]# cd /var/www/html
[root@linux html]# ln -s /home/dmtsai/public_html dmtsai
    由于我们首页的‘ Options ’内有 FollowSymLinks 这个参数的原因，所以可以直接使用连结档即可。 另外我们也可以使用 Apache 提供的别名功能 (Alias)，例如这样做：
    [root@linux ~]# vi /etc/httpd/conf/httpd.conf
# 找个不与人家设定值有干扰的地方加入这个设定项目：
Alias /dmtsai/ "/home/dmtsai/public_html/"
<Directory "/home/dmtsai/public_html">
    Options FollowSymLinks
    AllowOverride None
    Order allow,deny
    Allow from all
</Directory>

[root@linux ~]# apachectl restart
    这样就 OK 的啦！ ^_^

    小标题的图示 启动某个目录的 CGI (perl) 程式执行权限
    在前几个小节里面我们有谈到如果你想要 Apache 可以执行 perl 之类的网页程式时， 你就得需要安装一些额外的模组才行。其中 mod_perl 与 mod_python 这两个套件建议您最好安装一下啦！然后我们也提到想要执行 CGI 程式就得到 /var/www/cgi-bin/ 目录下去执行。如果你想要在其他目录底下执行 CGI 是否可以？当然行啊！

  • 利用新目录下的 Options 参数设定：
    • 假设想要执行 CGI 的程式附档名为 .cgi 或 .pl ，且放置的目录在 /var/www/html/cgi/ 时， 你可以这样做：
    [root@linux ~]# vi /etc/httpd/conf/httpd.conf
# 找到底下这一行，大约在 807 行左右啦：
#AddHandler cgi-script .cgi
# 将他改成底下的模样，让附档名为 .pl 的档案也能执行喔！
AddHandler cgi-script .cgi .pl

# 然后加入底下这几行来决定开放某个目录的 CGI 执行权限。
<Directory "/var/www/html/cgi">
    Options ExecCGI
    AllowOverride None
    Order allow,deny
    Allow from all
</Directory>

[root@linux ~]# apachectl restart
    接下来只要让你的 CGI 程式具有 x 权限，那么他就可以执行啦！举例来说，你的档案在 /var/www/html/cgi/index.cgi 的话，那么：
    [root@linux ~]# chmod a+x /var/www/html/cgi/index.cgi
    然后在网址列输入：http://主机名称或 IP/cgi/index.cgi 即可执行该档案啦！

  • 使用 ScriptAlias 的功能：
    • 你可以直接利用档名的别名来处理！更简单呢：
    [root@linux ~]# vi /etc/httpd/conf/httpd.conf
# 同样的你要先确认这一行是存在的！
AddHandler cgi-script .cgi .pl

# 然后加入底下这几行来决定开放某个目录的 CGI 执行权限。
ScriptAlias /cgi/ "/var/www/html/cgi/"

[root@linux ~]# apachectl restart
    这个方法比较棒啦！因为该目录不需要在 Apache 首页底下也可以成功的啦！
    这两个方法你可以随意取一个来处理即可！不需要两个都进行啦！

    小标题的图示 找不到网页时的显示讯息通知
    如果你的 /var/www/html/cgi 目录底下没有任何首页档案 (index.???) 时，那当使用者在网址列输入‘ http://your.hostname/cgi ’，请问结果会显示出什么呢？可能有两个：
    • 如果你的 Options 里面有设定 Indexes 的话，那么该目录下的所有档案都会被列出来，提供类似 FTP 的连结页面。
    • 如果没有指定 Indexes 的话，那么错误讯息通知就会被显示出来。
    事实上 CentOS 所提供的 Apache 已经规范好一些简单的错误资料网页了，你可以到 /var/www/error/ 目录下瞧瞧就晓得。不过该目录下的档案并没有中文讯息，所以.....真要命！至于 Apache 的错误讯息设定在这里：
    [root@linux ~]# vi /etc/httpd/conf/httpd.conf
# 大约在 886 行左右，预设就是注解掉的！
#    ErrorDocument 403 /error/HTTP_FORBIDDEN.html.var
#    ErrorDocument 404 /error/HTTP_NOT_FOUND.html.var
#    ErrorDocument 405 /error/HTTP_METHOD_NOT_ALLOWED.html.var
#    ErrorDocument 408 /error/HTTP_REQUEST_TIME_OUT.html.var
....后面省略....
    虽然 Apache 有提供这些资料了，不过 CentOS 预设是将那些资料注解掉的！因为我们使用中文语系， 该资料并没有中文资讯，所以注解掉反而对我们的处理有帮助呢！ ^_^ 由于你的网站可能会因为一些档名的变更或者是重新编写的原因，因此旧的网页档名就不存在。 但用户端可能保留的还是旧的连结，此时我们就得要很好心的告知使用者该网页找不到的原因才好。 你可以这样做：
    [root@linux ~]# vi /etc/httpd/conf/httpd.conf
# 找到底下这一段，看看这些简单的范例先：
#ErrorDocument 500 "The server made a boo boo."
#ErrorDocument 404 /missing.html
#ErrorDocument 404 "/cgi-bin/missing_handler.pl"
#ErrorDocument 402 http://www.example.com/subscription_info.html

# 假设未来提供使用者相关资讯的地方为 missing.html 这个档案，所以你应该要：
ErrorDocument 404 /missing.html

[root@linux ~]# apachectl restart
    上面那个档案 /missing.html 必需要放置在你的首页目录下，亦即是 /var/www/html/missing.html 啦！ 要提醒你的是：‘你的所有设定档当中 (包括 /etc/httpd/conf.d/*.conf) 只能存在一个 ErrorDocument 404 ... 的设定值，否则将以较晚出现的设定为主’ 所以你得先搜寻一下，尤其是很多 Linux 版本的 Apache 并没有将预设的错误讯息注解呢。 至于那个 404 是啥意思？他的意义是这样的：
    • 100-199：一些基本的讯息
    • 200-299：用户端的要求已成功的达成
    • 300-399：Client 的需求需要其他额外的动作，例如 redirected 等等
    • 400-499：Client 的要求没有办法完成(例如找不到网页)
    • 500-599：主机的设定错误问题
    好了，接下来让我们编辑一下那个 missing.html 的档案吧！ ^_^
    [root@linux ~]# vi /var/www/html/missing.html
<html>
<head>
        <meta http-equiv="Content-Type" content="text/html; charset=big5">
        <title>错误讯息通知</title>
<head>
<body>
        <font size=+2 face="楷体_GB2312">您输入的网页找不到！</font><br />
        <hr />
        亲爱的网友，您所输入的网址并不存在我们的伺服器当中，
        有可能是因为该网页已经被管理原删除，
        或者是您输入了错误的网址。请再次查明后在填入网址啰！
        感谢您常常来玩！ ^_^<br />
        <hr />
        若有任何问题，欢迎联络管理员<a
    href="mailto:root@localhost">root@localhost</a>。
</body>
</html>
    现在你如果在网址列随便输入一个主机上不存在的网址，就会出现如下的画面啰：

    错误讯息的通知显示网页
    图五、错误讯息的通知显示网页

    当然啦，您可以自行设定出符合你网页风格的资料啦！例如鸟哥的网站上面就列出一些基本的连结， 帮助网友们可以顺利的取得他们想要的资料啊！这也是很重要的功能呢！^_^

    小标题的图示 浏览权限的设定动作 (order, limit)
    咱们的 Apache 设定档内就可以指定限制浏览来源的动作了！我们可以针对来源 IP 或网域来限制呢！ 就以 Order 这个限制配合 Allow 及 Deny 来处理即可。再次的强调一下：
    • Order deny,allow：以 deny 优先处理，但没有写入规则的则预设为 allow 。常用于：拒绝所有，开放特定的条件；
    • Order allow,deny：以 allow 为优先处理，但没有写入规则的则预设为 deny。 常用于：开放所有，拒绝特定的条件。
    • 如果 allow 与 deny 的规则当中有重复的，则以预设的情况 (Order 的规范) 为主。
    举例来说，如果我们的首页想要让 192.168.1.11 及政府部门无法连线，其他的则可以连线， 由上面的说明你可以知道是开放所有拒绝特定的条件，所以你可以这样做设定：
    [root@linux ~]# vi /etc/httpd/conf/httpd.conf
<Directory "/var/www/html">
    Options FollowSymLinks
    AllowOverride None
    Order allow,deny
    allow from all
    deny from 192.168.1.11
    deny from .gov.tw
</Directory>
    注意一下，因为 Order 是‘ allow,deny ’，所以所有规则当中属于 allow 的都会被优先提到最上方， 为了避免这个设计上的困扰，所以建议你直接将 allow 的规则写在最上方。 而由于规则当中 192.168.1.11 隶属于 all 当中 (all 代表所有的嘛！)，因此这个设定项目则为预设值， 亦即为 deny 啦！那个 .gov.tw 的设定项目也一样。如果是底下的模样：
    [root@linux ~]# vi /etc/httpd/conf/httpd.conf
# 底下可是个错误的示范，请仔细看下个段落的详细说明喔！
<Directory "/var/www/html">
    Options FollowSymLinks
    AllowOverride None
    Order deny,allow
    deny from 192.168.1.11
    deny from .gov.tw
    allow from all
</Directory>
    虽然 deny 会先挪到上方来处理，不过因为 192.168.1.11 是在 all 的范围内，所以发生重复， 因此这个设定值将会以预设的 allow 为主，因此就无法限制住这个 192.168.1.11 的存取啦！ 这边很容易搞错的呐！鸟哥也是常常搞到头昏脑胀的～

    例题：
    如果有个应该要保护的内部目录，假设在 /var/www/html/lan/ ， 我仅要让 192.168.1.0/24 这个网域可以浏览的话，那么你应该要如何设定的好？
    答：
      这个案例当中有点像是‘拒绝所有连线，仅接受特定连线’的样子，因此可以使用 deny,allow 那个情况， 所以你可以这样做：
      <Directory "/var/www/html/lan">
    Options FollowSymLinks
    AllowOverride None
    Order deny,allow
    deny from all
    allow from 192.168.1.0/24
</Directory>

    事实上，如果想要让某个网域或者是 IP 无法浏览的话，最好还是利用 iptables 来处理比较妥当。 不过如果仅是某些重要目录不想让人家来查阅的话，那么这个 allow, deny 与 order 的设定资料可就很值得参考了。

    而除了这个 order 设定值之外，我们还有个限制用户端能进行的动作的设定喔！ 那就是 Limit 这个设定啦！举例来说，如果我们想要让使用者在 /var/www/html/lan 这个目录下仅能进行最阳春的 GET, POST, OPTIONS 的功能，除了这几个之外的其他功能通通不允许， 那么你可以这样做：
    [root@linux ~]# vi /etc/httpd/conf/httpd.conf
<Directory "/var/www/html/lan">
    AllowOverride none
    Options FllowSymLinks

    # 先允许能够进行 GET, POST 与 OPTIONS 啦！
    <Limit GET POST OPTIONS>
        Order allow,deny
        Allow from all
    </Limit>

    # 再规定除了这三个动作之外，其他的动作通通不允许啦！
    <LimitExcept GET POST OPTIONS>
        Order deny,allow
        Deny from all
    </LimitExcept>
</Directory>
    透过 Limit 与 LimitExcept 就能够处理用户端能够进行的动作啦！也就有办法针对你的资料进行细部保护啰。 不过这些保护真的很细部，一般小网站大致上用不到 Limit 这个玩意儿说。

    小标题的图示 主机状态说明网页
    既然已经安装好了 WWW 主机，除了提供服务之外，重要的是要如何维护啰！嘿嘿！ 那么是否一定要额外安装其他的套件才能知道目前的主机状态呢？当然不需要啦！我们可以透过 Apache 提供的特别功能来查询主机目前的状态！那就是 mod_status 这个模组啰！ 这个模组预设是关闭的，你必须要修改设定档来启动他才行。
    [root@linux ~]# vi /etc/httpd/conf/httpd.conf
# 先确定底下这几个项目真的有存在才行！
LoadModule status_module modules/mod_status.so <==大约在 166 行，就是模组的载入

ExtendedStatus On  <==大约在 201 行，你可以将他打开，资讯会比较多！

# 底下的资料则大约在 934 行左右，你可以将他修改成为这样：
<Location /server-status>
    SetHandler server-status
    Order deny,allow
    Deny from all
    Allow from 192.168.1.0/24
    Allow from 127.0.0.1
</Location>

[root@linux ~]# apachectl restart
    接下来你只要在你的网址列输入主机名称后面加上 http://hostname/server-status 即可发现如下的模样：
    主机的目前状况回报网页
    图六、主机的目前状况回报网页

    输出的结果包括目前的时间以及 Apache 重新启动的时间，还有目前已经启动的程序等等， 还有网页最下方会显示每个程序的用户端与伺服器端的连线状态。虽然显示的状况挺阳春，不过该有的也都有了， 可以让你约略了解一下主机的状况啰。要注意喔，可查阅者 (allow from 的参数) 还是需要限制的比较严格一点啦！

    小标题的图示 .htaccess 与认证网页设定
    对于保护 Apache 本身的资料方面，除了上述的 Order 以及 Limit 之外，还有什么方式呢？ 因为 Order 与 Limit 主要是针对 IP 网域或者是主机名称来管理，那如果我们用户端是使用拨接方式取得 IP ， 那么 IP 会一直变动的，如此一来那个保护的目录使用者也就不能在任何地方进入了，会造成一些困扰。

    此时如果能够使用密码保护的方式，让使用者可以输入帐号/密码即可取得浏览的权限的话， 那用户端就不用受到那个 order 的 Allow, deny 的限制啦！真好～ 呵呵！Apache 确实刚好有提供一个简单的认证功能，让我们可以轻松愉快的就设定好保护的网页呢！
    Tips:
    什么是受保护的资料呢？举例来说，学校老师们可能会提供一些教学教材或者是习题给同学， 这些资料不想给所有人取得，那么就可以将这些资料放在特定的受保护的目录中。还有例如某些重要的 Apache 主机分析的资料 (本章后面提及的一些分析工具)，这些资料建置的方法需要启用 CGI 程式， 而 CGI 程式的执行是有风险的，而且那些分析所得的资料也很重要。 此时，该程式与输出结果就需要放在受保护的目录啦！     		鸟哥的图示
    那么那个认证网页如何搞定？简单的说，他要这样处理：
    1. 建立受保护的目录：既然我们是‘按了某个连结进入某个目录之后，才会出现对话视窗’， 那么首先当然就是要有那个设定为认证网页的‘目录’啰！请注意，是要目录才行喔！
    2. 设定 Apache 所需参数：然后，在对话视窗中，既然我们需要输入 ID 与密码，那么自然就需要密码档啰！ 另外，虽然 Apache 有支援 LDAP 及 MySQL 等等的认证机制，不过我们这里并不讨论其他的认证机制， 完全使用 Apache 的预设功能而已，所以，底下我们会使用基本 (Basic) 的认证模式喔！
    3. 建立密码档案：处理完基本的设定后，再来则是建立登入时所需要的帐号与密码！
    4. 最后，重新启动 Apache 就 OK 啦！
    其中，第二个步骤会比较有趣，我们说过，任何的设定资料都可以直接写到 httpd.conf 这个设定档当中， 所以设定保护目录的参数资料确实可以写入 httpd.conf 当中。不过，想一想，如果你的 Apache 主机有 30 个使用者具有个人首页，然后他们都需要制作保护目录，那个 httpd.conf 只有身为 root 的你才能够修改， 更可怕的是‘每次改完都需要重新启动 Apache’～请问，你的时间精力是否会受到‘很严厉的考验？’

    所以啦，如果我们能够透过外部的档案来取代设定 httpd.conf 内的参数，那么是否会比较好？ 而且最好能够该档案设定即生效，不需要重新启动 Apache 的话，那就更好啦！因为如此一来， 你就可以交给使用者自行管理他们的认证网页啰！呵呵～ 透过 httpd.conf 内的 AllowOverride 参数，配合 .htaccess 这个档案的设定就 OK 搞定！ 这个设定项目与设定档 httpd.conf 的关系可以这样看：

    .htaccess 与主要设定档 httpd.conf 的相关性
    图七、.htaccess 与主要设定档 httpd.conf 的相关性

    也就是说：
    • 你必需要在 httpd.conf 这个主设定档当中先以 AllowOverride 指定某个目录下的 .htaccess 能够进行取代的参数为何？一般有 AuthConfig, Options 等等，考虑到系统资料的安全，建议提供 AuthConfig 的项目就好了。设定完毕后请重新启动 Apache。
    • 在该目录底下务必要存在 .htaccess 这个档案，透过这个档案即可修改 httpd.conf 内的设定啊！
    • .htaccess 设定完‘立刻生效’，不需要重新启动 Apache ，因为该档案的内容是‘当有用户端浏览到该目录时， 该档案才会被使用来取代原有的设定。
    既然 .htaccess 的用途比较广，所以底下我们不介绍 httpd.conf 的认证参数了， 请您自行测试测试即可。底下主要以 .htaccess 档案的设定为主喔！赶紧来看看吧！

  • 1. 建立保护目录的资料
    • 假设我要将受保护的资料放置到 /var/www/html/protect 当中，记得，这个目录要让 Apache 可以浏览到才行。 所以你可以立刻将一些重要的资料给他搬一到这里来。我们先这样测试一下吧！建立个简单的测试网页即可。
    [root@linux ~]# mkdir /var/www/html/protect
[root@linux ~]# vi /var/www/html/protect/index.html
<html>
<head><title>这是个测试网页啊！</title></head>
<body>看到这个画面了吗？如果看到的话，表示你可以顺利进入本受保护网页啦！
</body></html>
  • 2. 以 root 的身份处理 httpd.conf 的设定资料
    • 这个动作是仅有 root 能作的啦！你要开始编辑 httpd.conf ，让受保护的那个目录可以使用 .htaccess 啊！
    [root@linux ~]# vi /etc/httpd/conf/httpd.conf
# 确定底下这几行是存在的！
AccessFileName .htaccess
<Files ~ "^\.ht">
    Order allow,deny
    Deny from all
</Files>

# 在某个不受影响的地方加入这一段：
<Directory "/var/www/html/protect">
    AllowOverride AuthConfig
    Order allow,deny
    Allow from all
</Directory>

[root@linux ~]# apachectl restart  <==重新启动，不要忘记了！
    这样就设定妥当了，很简单吧！再接下来要准备 .htaccess 的建立了。

  • 3. 建立保护目录下的 .htaccess 档案：只要有权限建立者即可进行
    • 要注意，这个档案是在保护目录底下喔！不要放错地方啦！所以你要这样做：
    [root@linux ~]# cd /var/www/html/protect
[root@linux ~]# vi .htaccess
# 只要加入底下这几行即可
AuthName     "Protect test by .htaccess"
Authtype     Basic
AuthUserFile /var/www/apache.passwd
require user test
    这些参数的意义是这样的：
    • AuthName：在出现要你输入帐号与密码的对话视窗中，出现的‘提示字元’就是了；
    • AuthType：认证的类型，我们这里仅列出 Apache 预设的类型，亦即是‘basic’的啦
    • AuthUserFile：这个保护目录所使用的帐号密码设定档。 也就是说，这个档案是随便你设定的，当然啦，所以使用者当然可以自行设定帐号与密码啰。 档案内的帐号不限在 /etc/passwd 出现的使用者！另外，这个档案不要放置在 Apache 可以浏览的目录内，所以我将他放置在首页之外！避免被不小心窃取。
    • require：后面接可以使用的帐号。假如 /var/www/apache.passwd 内有三个帐号， 分别是 test, test1, test2 ，那我这里只写了 test ，因此 test1, test2 将无法登入此目录。 如果要让该密码档内的使用者都能够登入，就改成‘require valid-user’即可啊！
    设定好就立刻生效了，不需要重新启动任何东西啊！

  • 4. 建立密码档案 htpasswd (只要有权限即可执行)
    • Apache 预设读取的帐号/密码设定资料是由 htpasswd 所建立的，这个指令的语法是这样的：
    [root@linux ~]# htpasswd [-c] 密码档档名 使用者帐号
参数：
-c ：建立后面的密码档案。如果该档案已经存在，则原本的资料会被删除！
     所以如果只是要新增使用者(档案已存在时)，不必加上 -c 的参数！

1. 建立 apache.passwd ，帐号为 test
[root@linux ~]# htpasswd -c /var/www/apache.passwd test
New password:  <==这里输入一次密码，注意，荧幕不会有任何讯息。
Re-type new password:  <==这里再输入一次
Adding password for user test

[root@linux ~]# cat /var/www/apache.passwd
test:FIquw/..iS4yo   <==您瞧瞧！已经建立一个新使用者！

2. 在已存在的 apache.passwd 内增加 test1 这个帐号：
[root@linux ~]# htpasswd /var/www/apache.passwd test1
    再次强调，这个档案档名需要与 .htaccess 内的 AuthUserFile 相同，且不要放在浏览器可以浏览到的目录！ 这样就算设定完毕啦！你可以使用浏览器在网址列输入：‘http://your.hostname/protect’试看看，结果会如何？
    最后测试的结果会像底下这个样子：

    受保护模式的授权画面
    图八、受保护模式的授权画面

    如果你曾经浏览过这个目录了，当时可能尚未制作保护的档案，或者是档案设计错误，导致你曾经可以浏览该网页， 则该网页会被你的浏览器快取 (cache) 起来，所以可登入的画面会一再地出现而不会跑出需要认证的对话视窗。 此时你应该要：
    • 务必将全部的浏览器都关闭，再重新启动浏览器。因为你成功的登入该目录后， 该登入的资讯会快取在这次的连线上喔！
    • 可以将浏览器上头的‘reload (重新读取)’按下去，让浏览器重新读取一次； 否则快取不会更新。
    • 可以将浏览器的快取资料全部清除，关闭浏览器后再重新启动浏览器看看。
    如果还是一直出问题，那就只好前往登录档 (/var/log/httpd/error_log) 察看错误资讯啰。 常见的错误只是打错字啦！@_@

    小标题的图示 虚拟主机的设定
    接下来我们要谈的是‘主机代管’......瞎密？不是啦～是一个称为虚拟主机的东西啦～ 这东西很有用喔！他可以让你的一部 Apache 看起来像有多个‘主站首页’的感觉啦！

  • 什么是虚拟主机 (Virtual Host)
    • 所谓的虚拟主机，基本上就是‘让你的一部主机上面，有好多个 "主网页" 存在，也就是说，硬体实际上只有一部主机，但是由网站网址上来看，则似乎有多部主机存在的样子！’。 举个例子来说好了，鸟哥提供的网站主要有主要学习网站以及新手讨论区，分别在底下的连结：
    • 主网站：http://linux.vbird.org
    • 讨论区：http://phorum.vbird.org
    这两个连结你给他点下去，会发现其实是不同的资料内容，不过，如果你用 dig 之类的软体来查验 IP 的话，会发现这两个网址都指向同一个 IP ㄟ！怎么会这样？没错啊！这就是虚拟主机的主要功能！ 他可以让你的多个主机名称对应到不同的主网页目录 (DocumentRoot 参数)， 所以看起来会像有多部实际主机的模样啦！这样说，了解虚拟主机了吗？

  • 架设的大前提
    • 那么要架设虚拟主机需要什么咚咚呢？以刚刚鸟哥的网站的结果为例，我必需要有多个主机名称对应到同一个 IP 去， 所以说，你必需先拥有多个主机名称才行。要如何拥有多个主机名称？那就是：
    • 向 ISP 申请多个合法的主机名称，而不自己架设 DNS；
    • 自行设定经过合法授权的 DNS 主机来设定自己所需要的主机名称。
    相关的 DNS 申请与设定技巧我们在前几章都谈过了，您可得自行去瞧瞧先！

  • 架设范例练习：
    • 我们在 DNS 章节里面不是有设定了多个主机名称吗？ 那些主机名称就是为了要在这里实作用的啦！ ^_^！你得要注意的是，我的每个主机名称都必需要对应到某个主网页目录， 底下则是鸟哥的一个简单范例：

    主机名称 | 对应的主目录
linux.vbird.tsai | /var/www/html
www.vbird.tsai | /var/www/www
phorum.vbird.tsai | /var/www/phorum

    接下来就是开始设定啰！要告诉你的是，建议你将虚拟主机的设定建立一个新的档案在 /etc/httpd/conf.d/*.conf 当中，因为如此一来你的虚拟主机设定档就可以进行搬移， 修改的时候也不会影响到原有的 httpd.conf 的资料！而因为 httpd.conf 内有个 Include 的参数将 /etc/httpd/conf.d/*.conf 的档案都读入设定档当中，所以设定上面就变的很轻便， 备份与升级的时候也比较容易处理嘛！不啰唆，赶紧来实验一下先！
    1. 先建立所需要的目录：
[root@linux ~]# mkdir /var/www/www
[root@linux ~]# mkdir /var/www/phorum
[root@linux ~]# echo "www.vbird.tsai" > /var/www/www/index.html
[root@linux ~]# echo "phorum.vbird.tsai" > /var/www/phorum/index.html
# 原有的首页 (/var/www/html) 就不更动了！另建两个不同的首页内容，可供测试用。

2. 开始编辑设定档，这里鸟哥用额外的档案来设定喔！
[root@linux ~]# vi /etc/httpd/conf.d/virtual.conf
# 底下这一行在规定‘本机任何介面的 port 80 所指定的虚拟主机’的意思。
NameVirtualHost *:80

# 先针对两个多出来的可浏览目录进行权限方面的规范啊！
<Directory "/var/www/www">
    Options FollowSymLinks
    AllowOverride None
    Order allow,deny
    Allow from all
</Directory>
<Directory "/var/www/phorum">
    Options FollowSymLinks
    AllowOverride None
    Order allow,deny
    Allow from all
</Directory>

# 针对三部主机的 DocumentRoot 进行定！
<VirtualHost *:80>
    ServerName    linux.vbird.tsai
    DocumentRoot  /var/www/html
</VirtualHost>
<VirtualHost *:80>
    ServerName    www.vbird.tsai
    DocumentRoot  /var/www/www
    CustomLog     /var/log/httpd/www.access_log combined
    # 不同的主页可以指定不同的登录档资讯，这样比较好 debug 与分析啦！
</VirtualHost>
<VirtualHost *:80>
    ServerName    phorum.vbird.tsai
    DocumentRoot  /var/www/phorum
</VirtualHost>

[root@linux ~]# apachectl restart
    你要注意的只有几点：
    1. 在虚拟主机的设定上还有很多的可用的功能，不过，最低的限度是需要有 ServerName 及 DocumentRoot 这两个即可！
    2. 使用了虚拟主机后，原本的主机名称 (linux.vbird.tsai) 也要同时写入虚拟主机的对应中， 否则这个主机名称可能会不知道被丢到哪里去喔！
    3. 在 www.vbird.tsai 这个主机当中多了个 CustomLog ，表示任何向 www.vbird.tsai 要求资料的记录都会改写入 /var/log/httpd/www.access_log 而不是预设的 /var/log/httpd/access_log。 但这个新增的登录档必需要加入 logrotate 的管理当中才行喔！否则登录档会大到‘爆表’
    接下来，只要你用户端的浏览器可以找到这三个主机名称并连线到正确的 IP 去， 你这个 Apache 就可以同时提供三个网站的站址了，很方便吧！^_^。

  • 虚拟主机常见用途
    • 虚拟主机为什么会这么热门啊？这是因为他可以进行底下的任务：
    • 主机代管：
      如果你有一部很快速的电脑，配合你的网路频宽又大的话，那么你可以用这个虚拟主机的技术来‘拉客’喔！ 因为毕竟不是所有公司都有维护伺服器的能力，如果你能够提供合理的流量、亲和的资料传输介面、 稳定的提供服务，并且给予类似 MySQL 资料库的支援，那么当然有可能进行‘主机代管’的业务啊！ 您说是吧！ ^_^

    • 伺服器资料备援系统：
      你可以在两个地方放置两部主机，主机内的网页资料是一模一样的 (这个可以使用 rsync 来达成的) ，那么你将可以利用 Apache 的虚拟主机功能， 配合 DNS 的 IP 指向设定，让某一部主机挂点时，另外一部主机立刻接管 WWW 的要求！ 让你的 WWW 伺服器不会有任何断线的危机啊！ ^_^ (注：当 A 伺服器挂点时， 赶紧设定 DNS ，让原本 A 的 IP 指定给 B，则任何向该 IP 要求的 WWW 将会被导向 B， B 有 A 的备份资料以及虚拟主机设定，搞定！)

    • 将自己的资料分门别类：
      如果野心没有这么大的话，那么如果你有几个不同的资料类型时，也可以利用虚拟主机将各种资料分门别类啦！ 例如将部落格指向 blog.vbird.tsai ，将讨论区指向 phorum.vbird.tsai ，将教学资料指向 teach.vbird.tsai 等等，这样的网址就很容易让用户端了解啦！您说是吧！ ^_^
    小标题的图示 防火墙与 SELinux
    一句老话啦！就是‘如果你的 Server 不能动，但是确定设定都没有问题， 那么除了持续查询 log file 之外，最大的可能就是防火墙挡住了！’ 这句话应该没有什么太大的疑问才对～所以呢，万一你的 Apache 不能动，那么请看看你的防火墙设定规则吧！因为防火墙我们已经提过了，请参考‘简易防火墙设定’一文，这里不再赘述！

    另外，Apache 由于太出名了，很多人有在使用这一套东西，所以可能发布的漏洞也不少。 因此，你应该要保持随时更新这套系统在最新的版本上才好！最好是要使用 yum 来自动线上更新啦！

    最后，如果你没有针对 SELinux 彻头彻尾的设定 Apache 能够读取的档案系统的话， 理论上，你的 Apache 应该是无法提供正确的浏览的。 所以啰，请先将 SELinux 关闭啦！不然的话，花个几个月好好的研究一下 SELinux 吧！ ^_^
    大标题的图示 登录档分析以及 PHP 强化模组等套件说明
    除了这些基本的 Apache 使用方式之外，我们还有哪些事情可以玩的？ 当然还有很多啦！包括有趣的 PHP 效能强化模组、登录档分析以了解整个 Apache 的使用情况等等！ 让我们来瞧一瞧！

    小标题的图示 PHP 强化模组 (eaccelerator) 与 Apache 简易效能测试
    虽然 PHP 网页程式标榜的是速度快速，不过因为 PHP 毕竟是先将一些可用函数先编译成为模组， 然后当网页使用到该 PHP 程式的时候，再由呼叫 PHP 模组来达成程式所需要的行为。 由于多了一道手续，所以他的执行效能还是有别于传统编译的程式语言啰。

    那么如果我们可以将 PHP 程式预先转换成为可直接执行的 binary file ，那么不就可以直接读取进而加快速度吗？ 没错！是这样～这东西称为预编器～其中有一套软体称为 eaccelerator ，eaccelerator 可以将您的 PHP 程式与 PHP 核心及相关函式库预先编译后暂存下来，以提供未来使用时可以直接执行，加上他可以优化您的 PHP 程式，因此，可以让您的 PHP 网页速度增快不少喔！ eaccelerator 的官方网站在底下：
      http://eaccelerator.net/HomeUk
    整个安装的流程很简单啦！你先将这个软体的原始码下载下来，我这里假设你将他下载到 /root 目录下， 另外你必需要确定你有安装 php-devel, autoconf, automake, m4, libtool 等套件才行！ 那就赶紧来安装吧！ (鸟哥是以 0.9.5 这一版为范例的喔！)
    1. 解压缩档案：
[root@linux ~]# cd /usr/local/src
[root@linux src]# tar -jxvf /root/eaccelerator-0.9.5.tar.bz2
[root@linux src]# cd eaccelerator-0.9.5/

2. 利用 phpize 进行 PHP 程式的预处理
[root@linux eaccelerator-0.9.5]# phpize
# 过程会出现一些警告资讯，不要理他没关系！
[root@linux eaccelerator-0.9.5]# ./configure --enable-eaccelerator=shared \
> --with-php-config=/usr/bin/php-config
[root@linux eaccelerator-0.9.5]# make

3. 将他整个安装起来！
[root@linux eaccelerator-0.9.5]# make install
# 此时这个新编译的模组会被放置到 /usr/lib/php4/eaccelerator.so 当中啊！
    将模组处理完毕之后接下来就是要让 PHP 使用这个模组啦！如何进行呢？
    1. 预先载入这个 PHP 的模组：
[root@linux ~]# vi /etc/ld.so.conf
# 新增加这一行即可！
/usr/lib/php4

[root@linux ~]# ldconfig
# 关于 ld.so.conf 以及 ldconfig 我们在基础篇谈过了，请自行参考喔！

2. 修改 php.ini 喔！
[root@linux ~]# vi /etc/php.ini
# 在这个档案的最底下加入这几行：
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; http://eaccelerator.net/HomeUk ;
; 2006/11/08 VBird               ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
extension="eaccelerator.so"
eaccelerator.shm_size="16"
eaccelerator.cache_dir="/tmp/eaccelerator"
eaccelerator.enable="1"
eaccelerator.optimizer="1"
eaccelerator.check_mtime="1"
eaccelerator.debug="0"
eaccelerator.filter=""
eaccelerator.shm_max="0"
eaccelerator.shm_ttl="0"
eaccelerator.shm_prune_period="0"
eaccelerator.shm_only="0"
eaccelerator.compress="1"
eaccelerator.compress_level="9"

3. 建立 eaccelerator 的暂存资料，重点在于权限要设定正确！
[root@linux ~]# mkdir /tmp/eaccelerator
[root@linux ~]# chmod 777 /tmp/eaccelerator
[root@linux ~]# apachectl restart
    基本上这样就设定妥当啦！要注意的是：‘因为你的 eaccelerator 是根据目前这一版的 PHP 核心所编译出来的，所以未来如果你的 Linux distribution 有释出新版的 PHP 时，你也顺利更新到新版的 PHP 了，那你的这个 eaccelerator 就必需要自行手动再更新一次， 以配合到正确的 PHP 版本，否则这个模组将不会正确运作。’！很重要喔！

    那如何确认这个模组有正确的在运作呢？你可以利用我们在启动 PHP 那个小节内谈到的 phpinfo() 这个函式来查阅，透过浏览器你应该会看到如下的画面：

    确定 eaccelerator 有运作的画面
    图九、确定 eaccelerator 有运作的画面

    如果你的 eaccelerator 没有启动的话，那就看不到图九的画面啦！藉由这个动作来测试测试吧！ ^_^！ 接下来我们利用 Apache 提供的一个小程式来测试一下我们网站的效能吧！这个程式叫做 ab ， 他可以主动的向主机重复要求多笔资料来确认主机的效能喔！
    [root@linux ~]# ab [-dSk] [-c number] [-n number] 网页档名
参数：
-d ：不要显示 saved table 的百分比资料；通常不要那个资料，所以会加 -d
-k ：还记得上面的 KeepAlive 吧！加入 -k 才会以这样的功能测试；
-S ：不显示长讯息，仅显示类似 min/avg/max 的简短易懂讯息！
-c ：同时有多少个‘同时连线’的设定(可想成同时连线的 IP )
-n ：同一个连线建立几个要求通道！(可想成同一个 IP 要求的几条连线)
更多的讯息请自行 man ab 喔！

# 针对我们刚刚测试时的 phpinfo.htm 这个档案来测试！
[root@linux ~]# ab -dSk -c100 -n100 http://localhost/phpinfo.htm
This is ApacheBench, Version 2.0.41-dev <$Revision: 1.141 $> apache-2.0
Copyright (c) 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Copyright (c) 1998-2002 The Apache Software Foundation, http://www.apache.org/
....中间省略....
Total transferred:      4549407 bytes
HTML transferred:       4532922 bytes
Requests per second:    125.21 [#/sec] (mean)
Time per request:       798.628 [ms] (mean)
Time per request:       7.986 [ms] (mean, across all concurrent requests)
Transfer rate:          5562.04 [Kbytes/sec] received
....底下省略....
    根据这个软体的输出你会知道每秒钟的传输速率、最大传输速度等等，可以约略知道一下基本效能啦！ 不过鸟哥这个程式是在自己机器上面测试的，速度快是正常的！你可以在网路的另一头来测试一下说！ (注：这个 ab 程式对于读取 MySQL 之类的网页似乎没有办法成功的完成测试的样子， 你应该以较单纯的网页来测试吧！)

    小标题的图示 syslog 与 logrotate
    请特别注意，我们的 Apache 登录档主要记录两个东西，分别是：
    • /var/log/httpd/access_log ：用户端正常要求的记录资讯
    • /var/log/httpd/error_log ：使用者错误要求的资料，包括主机设定错误的资讯等。
    那个 /var/log/httpd/error_log 可以让你处理很多设定错误的情况，包括网页找不到、 档案权限设定错误、密码档案档名填错等等。至于 access_log 则可以让你分析那个网页最热门！ ^_^！ 不过你可得注意的是：‘在稍有规模的网站下，Apache 的登录档每周记录量甚至可达 1GB 以上’的纪录。以鸟哥的主网站来说，一个星期逼近 1GB 的登录档是合理的.....

    不过，因为登录档是纯文字资讯，所以如果能够给予压缩的话，那么备份下来的登录档将可以减少到数十MB而已， 这样可大大的减少了空间的浪费啊！如果你是使用预设的 Apache 来处理你的伺服器时， 那么系统已经作了一个 logrotate 给你使用了，如果你是使用 Tarball 自己安装的， 那么.....你就得要自行手动建立底下这个档案啦！鸟哥底下是以 CentOS 4.x 提供的档案来作说明的：
    [root@linux ~]# vi /etc/logrotate.d/httpd
/var/log/httpd/*log {
    missingok
    notifempty
    sharedscripts
    postrotate
        /bin/kill -HUP `cat /var/run/httpd.pid 2>/dev/null` 2> /dev/null || true
    endscript
    compress   <==建议加上这一段，让你的备份登录档可以被压缩
}
    为什么这里很重要呢？鸟哥的主机曾经发生过一件事情，就是....突然 WWW 效能变很差！ 后来追踪的原因竟然是..... /var/ 的空间被用完了！而耗掉这个 partition 的元凶竟然是 Apache 的登录档！ 当时 /var/ 仅给 5GB ，而每个星期的登录档就上达 1GB 以上，备份四个星期的结果， /var/ 想不爆掉也很难～ 所以啦，建议你的 /var 要给个 10GB 以上才好呐！而且备份登录档也要压缩才好呐！
    Tips:
    关于 syslog 与 logrotate 的详细说明请参考基础篇的内容喔！或者是到底下的连结：
    http://linux.vbird.org/linux_basic/0570syslog.htm     		鸟哥的图示
    此外，透过分析登录档其实我们可以知道我们的网站到底是哪一个网页最热门？ 也且也能知道用户端是来自哪里呢！目前针对 Apache 有很多的分析软体， 我们底下仅介绍两个常见的分析软体给大家呦！

    小标题的图示 webalizer
    事实上，CentOS 4.x 预设就提供了 webalizer 这个分析软体了！你只要将这套软体安装上来就是了。 如果你不是使用 CentOS 呢？没关系，官方网站上也可以下载，安装也很简单！
    • 官方网站：http://www.mrunix.net/webalizer/
    • 设定难度：简单，极适合新手架设
    • 软体特色：大致上，所有分析的内容他都有了！虽然图表比较没有那么炫...
    • 授权模式：GPL
    CentOS 4.x 提供的这个软体设定档在 /etc/webalizer.conf ，而且他设定每天会分析一次 WWW 的登录档， 不过这个软体预设会将输出的结果放置到 /var/www/usage ，并且这个目录仅有本机可以查阅， 鸟哥并不喜欢这样的设定。我们刚刚不是有建立一个保护目录 /var/www/html/protect 吗？ 这个目录的功能来啦！鸟哥预计将 webalizer 的输出资料放置到 /var/www/html/protect/webalizer 底下去， 所以知道密码的都能够查阅呢！整个动作是这样的：
    1. 先处理设定档，指定一下我们要输出的目录即可：
[root@linux ~]# vi /etc/webalizer.conf
# 确定一下底下这几行是正确的！其他的则保留预设值
LogFile        /var/log/httpd/access_log
OutputDir      /var/www/html/protect/webalizer
Incremental    yes

2. 建立该保护目录的资料：
[root@linux ~]# cp -a /var/www/usage/ /var/www/html/protect/webalizer
[root@linux ~]# rm /etc/httpd/conf.d/webalizer.conf
[root@linux ~]# apachectl restart  <==取消系统预设的 webalizer 目录

3. 开始测试执行 webalizer 的分析工作
[root@linux ~]# webalizer
    现在请你在浏览器上面输入： http://your.hostname/protect/webalizer ，看看输出的结果是如何吧！ 结果应该会如下所示：

    webalizer 分析工具所得的分析画面
    图十、webalizer 分析工具所得的分析画面

    在上图当中的箭头处你还可以点选喔，点选后会告知你当月的各项分析结果，很不错吧！

    小标题的图示 awstats
    除了 webalizer 之外，我们其实还可以透过 awstats 这个厉害到不行的 perl 的程式来进行资料分析， 由于这个软体是以 perl 来执行的，所以请确定你的 mod_perl 已经安装且 CGI 的执行权限已经启动了！ 这个套件的特色是：
    • 官方网站：http://awstats.sourceforge.net/
    • 设定难度：较难，需要有点技巧！
    • 软体特色：中文化的很完整，而且该有的都有了，相当炫的一个分析利器！
    • 授权模式：GPL
    这套软体不但可以由系统的 cron 来进行分析，甚至还提供浏览器直接以 CGI 的方式来即时更新登录档呐！ 真是厉害厉害！鸟哥个人是比较不喜欢使用浏览器来线上更新分析的结果， 因为在你更新分析结果时，怎么知道系统会不会很忙碌？如果系统正在忙碌中， 这套软体的分析可也是很耗费系统资源的呐！所以建议直接以 crontab 的方式来处理即可。

    目前官方网站不但提供 tarball 甚至也提供 RPM 来给使用者下载了！真是方便啊！ 但是您还是要注意的，这个软体曾经因为安全性的问题导致很多网站的挂点， 所以建议您还是把这个软体的输出结果放置在受保护的目录中喔！底下鸟哥以 6.5 这个 RPM 版本来说明， 请你自行到官方网站下载吧！台湾地区可以到这个地方下载的： (建议您可以自行前往官方网站下载最新版本的软体较佳！)
      http://nchc.dl.sourceforge.net/sourceforge/awstats/awstats-6.5-1.noarch.rpm
    假设你将这个 RPM 档案放置到 /root 当中，那么自己 rpm -ivh filename 去安装他吧！ 不要跟我说你不会 RPM ～鸟哥是会昏倒的～ @_@ 由于这个 RPM 档案将 awstats 的资料通通放置到 /usr/local/awstats 当中去了！ 为了自己网页设定上的方便，建议你是可以这样做的：
    1. 先将 awstats 提供的 Apache 设定资料给他复制到 conf.d 下
[root@linux ~]# cp /usr/local/awstats/tools/httpd_conf  \
> /etc/httpd/conf.d/awstats.conf
[root@linux ~]# vi /etc/httpd/conf.d/awstats.conf
Alias /awstatsclasses "/usr/local/awstats/wwwroot/classes/"
Alias /awstatscss "/usr/local/awstats/wwwroot/css/"
Alias /awstatsicons "/usr/local/awstats/wwwroot/icon/"
Alias /awstats/ "/usr/local/awstats/wwwroot/cgi-bin/"
<Directory "/usr/local/awstats/wwwroot">
    Options +ExecCGI
    AllowOverride AuthConfig  <==这里改成这样，因为要保护！
    Order allow,deny
    Allow from all
</Directory>
[root@linux ~]# apachectl restart
    awstats 还真的挺贴心的，因为他释出的文件当中就有关于 Apache 的设定资料， 我们直接将他放到 conf.d/ 那个目录下并且更名后，重新启动 Apache 就生效了！真方便。 再来则是要针对我们的 WWW 登录档来设定啦！设定档其实是在 /etc/awstats 目录下， 在该目录下有个范例档为 awstats.model.conf，其实这个设定档‘档名’格式为：
      awstats.主机名称.conf
    因为鸟哥这部主机名称为 linux.vbird.tsai ，所以假设主机名称为 linux ，所以档名就应该是 awstats.linux.conf 啰！请你将他复制一个新档，然后这样做：
    [root@linux ~]# cd /etc/awstats
[root@linux awstats]# cp awstats.model.conf awstats.linux.conf
[root@linux awstats]# vi awstats.linux.conf
# 找到底下这几行，并且修改一下内容啊：
LogFile="/var/log/httpd/access_log"  <==确定登录档所在的位置
LogType=W                            <==针对 WWW 的登录档分析
SiteDomain="linux.vbird.tsai"        <==主机的 hostname
HostAliases="localhost 127.0.0.1 REGEX[myserver\.com$] www.vbird.tsai"
DirCgi="/awstats"                    <==能够执行 awstats 的目录
DirIcons="/awstatsicons"             <==awstats 一些小图示的目录
Lang="tw"                            <==重要！这是语系！
    接着开始测试一下是否可以产生正确的分析资料出来？
    [root@linux awstats]# cd /usr/local/awstats/wwwroot/cgi-bin
[root@linux cgi-bin]# perl awstats.pl -config=linux -update \
> -output > index.html
# 那个 -config 后面接的就是 awstats.linux.conf 的意思！会产生 index.html
Update for config "/etc/awstats/awstats.linux.conf"   <==请确定设定档无误
With data in log file "/var/log/httpd/access_log"...  <==请确定登录档无误
Phase 1 : First bypass old records, searching new record...
Searching new records from beginning of log file...
Phase 2 : Now process new records (Flush history on disk after 20000 hosts)...
Jumped lines in file: 0
Parsed lines in file: 498
 Found 0 dropped records,
 Found 0 corrupted records,
 Found 0 old records,
 Found 498 new qualified records.

[root@linux cgi-bin]# ls -l
awstats112006.linux.txt <==刚刚才建立的重要资料档！
awstats.pl              <==就是刚刚我们下达的执行档！
index.html              <==重要输出首页档案
    接下来让我们赶紧来建立保护目录的 .htaccess 档案吧！请注意，鸟哥这里假设你已经有密码档了， 所以直接建立档案即可啊！
    [root@linux ~]# cd /usr/local/awstats/wwwroot
[root@linux wwwroot]# vi .htaccess
AuthName     "Protect awstats data"
Authtype     Basic
AuthUserFile /var/www/apache.passwd
require      valid-user
    之后，只要你输入‘http://192.168.1.254/awstats/index.html’，就能够看到输出的图表了！ 图表有点像这样：

    awstats 分析工具所得的分析画面
    图十一、awstats 分析工具所得的分析画面

    事实上，资料非常的多，你可以自行查阅输出的结果。在上图当中的箭头处， 你还可以自己选择曾有的月份资料来进行显示！最后，将分析的动作规定在每天三点的时候跑， 你可以这样做：
    [root@linux ~]# vi /usr/local/awstats/wwwroot/cgi-bin/awstats.sh
cd /usr/local/awstats/wwwroot/cgi-bin
perl awstats.pl -config=linux -update -output > index.html

[root@linux ~]# chmod 755 /usr/local/awstats/wwwroot/cgi-bin/awstats.sh
[root@linux ~]# vi /etc/crontab
0 3 * * * root /usr/local/awstats/wwwroot/cgi-bin/awstats.sh
    这样你就知道你的主机到底有多受欢迎啰！ ^_^！ 另外，再次千万拜托！这个软体所在的目录务必要制作密码保护！不要随意释放出来！ 甚至上面提供的一些目录的连结你都可以根据自己的主机与喜好来重新修改， 会比较安全的啦！

    大标题的图示 建立 SSL (https) 网站
    了解了一堆 Apache 的功能之后，你要知道 Apache 的这个 http 传输协定是‘明码传送’的， 也就是说，如果你的资料在 Internet 上面跑的时候被监听，那你的资料可就很麻烦啦！ 举例来说，我们不是有透过 .htaccess 来加密码保护吗？但是你使用浏览器的时候，还是得输入帐号密码吧？ 这个资料也许在传输的时候会被窃取喔！

    那怎么办？我们不是在最前面的地方谈过，有个 https 是利用 SSL 来加密传输的吗？ 这个传输的方式就很像 SSH 的连线方式，透过 public key 与 private key 这一对 key pair 来加解密， 那就 OK 的啦！

    不过，与 SSH 不同的是， SSH 通常是管理员本身就允许某些人来登入使用的，而用户端也是有特殊需求才会到该主机， 所以 public key 的建置可以直接由伺服器来管理即可。 WWW 伺服器就不一样了，因为 WWW 伺服器提供的资料是给 Internet 上面所有的人浏览的，那么‘为了保护浏览者的机密资料，因此 WWW 伺服器的 public key 有必要经过第三方公正单位的验证’来处理，如此一来用户端才能确保这部 WWW 伺服器是安全无虞的。

    所以我们可以说，apache 加上 SSL 并提供公正单位 (Certificate Authorities, CA) 注册所得的凭证， 是建立你自己 WWW 伺服器具有公信力的一个方式。不过，因为向 CA 单位注册是需要钱的， 所以除非您的 WWW 伺服器真的是应用在商业行为上面，否则并不需要向 CA 来注册申请凭证的啦。 那如果我自己想要建立加密的网页 (https) 的话，怎么注册我的 public key ？ 没关系，我们可以‘向自己注册’！只是如此一来，除非用户端相信你的主机， 否则通常对方可能会拒绝连线啦！ ^_^

    那如何达成上述的功能呢？你可能要这样：
    1. 先以类似 openssl 的指令制作出一把 public key ；
    2. 将这把 key 向本机注册 (你也可以向 CA 单位注册！)
    3. 设定 Aapche ，让注册的凭证可以生效；
    4. 你更可以限制某些目录只能由 https 来进行连线浏览。
    那如何达成这些动作呢？也不难，事实上 CentOS 4.x 已经利用一个 mod_ssl 帮我们制作好那把 key 以及凭证了！ 你只要安装好这个模组后，可以发现几个咚咚：
    • /etc/httpd/conf.d/ssl.conf ：提供给 Apache 读取的设定档；
    • /etc/httpd/conf/ssl.csr/server.csr ：用来申请凭证的档案 (Certificate Signing Request)
    • /etc/httpd/conf/ssl.crt/server.crt ：就是那个凭证档案！
    • /etc/httpd/conf/ssl.key/server.key ：就是那把 public key 啰！
    如果你要向 CA 单位申请凭证的话，那么就需要制作出 ssl.csr 那个档案，然后 CA 单位审核通过后会给你一个 *.crt 的档案，那就是凭证！不过因为我们是向自己注册，所以只需要 ssl.key 以及 ssl.crt 这两个档案即可， 而这两个档案都是由 openssl 这个指令所制作出来的啦！

  • 测试 CentOS 4.x 所提供的凭证
    • 你得先确定你已经安装了 mod_ssl 了，如果还没有安装，请使用 yum install mod_ssl 即可安装完毕。 然后重新启动 apache ，接下来就能够测试啦！使用浏览器连接到你的主机上， 记得使用的网址是：‘https://your.hostname/’才是喔！之后你会发现这样的画面：

    CentOS 预设凭证
    图十二、CentOS 预设凭证

    哇哈哈！凭证不成功是怎样？没办法，因为这个凭证并非向 CA 单位注册的嘛！如果你确认这个凭证是 OK 的， 那你可以选择‘永久接受此凭证’，未来再进入这个网站时就不会出现这个警告讯息。 如果只是这次想要连线，那就选择‘此次连线内暂时接受’吧！不然就不要接受啰。当然，你可以按下箭头所指处， 看一看这个凭证先：

    CentOS 预设凭证
    图十三、CentOS 预设凭证

    如果你不在乎认证的资讯，那么此时你的 https 传输协定已经搞定了！不需要往下继续处理。 如果你想要提供你自己主机的认证凭证，那就继续往下看吧！

  • 建立自己本机的凭证吧！
    • 如果你想要拥有自己的凭证，那就需要作出自己主机的 public key 以及凭证档案，可以这样做：

  • 建立 public key
    • public key 是放置在 /etc/httpd/conf/ssl.key 目录下的，整个建立的方法真简单：
    # 先将旧的档案备份下来：
[root@linux ~]# cd /etc/httpd/conf/ssl.key
[root@linux ssl.key]# mv server.key server.key.raw

# 开始作一支新的 public key 吧！
[root@linux ssl.key]# openssl [动作] -out filename [bits]
参数说明：
[动作]：主要的动作有：
        genrsa ：建立 RSA 加密的 public key
        req    ：建立凭证要求档或者是凭证档案
-out  ：后面加上输出的档名，就是那把 key name
bits  ：用在 genrsa，加密的金钥长度！
-x509 ：X.509 Certificate Data Management.，一种验证的管理方式

建立一支长度为 1024 bits 的 public key ，注意档名！
[root@linux ssl.key]# openssl genrsa -out server.key 1024
Generating RSA private key, 1024 bit long modulus
...................................................++++++
..........++++++
e is 65537 (0x10001)
    这个时候这把 public key 就建好啦！粉简单啦！

  • 建立凭证档案
    • 凭证档案是放置到 /etc/httpd/conf/ssl.crt 目录下的，所以你应该要这样做：
    [root@linux ~]# cd /etc/httpd/conf/ssl.crt
[root@linux ssl.crt]# mv server.crt server.crt.raw
[root@linux ssl.crt]# openssl req -new -x509 -key ../ssl.key/server.key \
> -out server.crt -days 365 -set_serial 123 <==每次序号都得不同！
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [GB]:TW
State or Province Name (full name) [Berkshire]:Taiwan
Locality Name (eg, city) [Newbury]:Tainan
Organization Name (eg, company) [My Company Ltd]:VBird
Organizational Unit Name (eg, section) []:VBird
Common Name (eg, your name or your server's hostname) []:linux.vbird.tsai
Email Address []:vbird@linux.vbird.tsai
    因为你注册的时候需要填写很多的资料，上头就是在输入你的资料啊！等到输入都没有错误后，就可以开始让 Apache 支援啦！

  • 设定 Apache 的支援
    • 其实 mod_ssl 提供的 /etc/httpd/conf.d/ssl.conf 已经足够啦！ 在那个档案里面比较重要的是这些东西：
    [root@linux ~]# vi /etc/httpd/conf.d/ssl.conf
Listen 443
<VirtualHost _default_:443>
#DocumentRoot "/var/www/html"
#ServerName www.example.com:443
SSLEngine on
SSLCipherSuite ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP
SSLCertificateFile /etc/httpd/conf/ssl.crt/server.crt
SSLCertificateKeyFile /etc/httpd/conf/ssl.key/server.key
</VirtualHost>

参数：
Listen                ：监听的 port ，这是预设值，最好不要改！
SSLEngine             ：是否支援 SSL ，要设成 On 喔！
SSLCipherSuite        ：允许 client 端的连线要求机制！
SSLCertificateFile    ：凭证档案
SSLCertificateKeyFile ：public key 啊！

[root@linux ~]# apachectl restart
    用预设值即可！接下来你就可以检查看看你的凭证了！同样的在浏览器的网址列以 https 输入网址，结果会是如何？

    CentOS 预设凭证
    图十四、CentOS 预设凭证

    上图中的组织等单位，就变成自己啰！真是有趣吧！ ^_^
  • 将 http 与 https 的网页分开
    • 刚刚我们处理的是 Apache 的 SSL ，也就是说原本的 WWW 资料可以分别使用 http 及 https 来浏览。 那我可不可以将这两个传输协定分开呢？举例来说，主网页 (http) 在 /var/www/html 底下， 但 https 则仅能在 /var/www/www 目录中。是可以的，同样透过虚拟主机来处理即可！很简单喔！
    [root@linux ~]# vi /etc/httpd/conf.d/ssl.conf
# 找到底下这两行，并且将他改掉！
DocumentRoot "/var/www/www"
ServerName *:443    <==意思是说，任何主机名称都是到上述的目录去！

[root@linux ~]# apachectl restart
    Ya！从此你的 https 与 http 是看到不同的地方啰！这样说，可以理解吧！ ^_^
    大标题的图示 一些安全性管理的网页
    还有一些可以玩的东西喔！让你的 Apache 可以负责一些小程式的处理！ 来瞧一瞧吧！

    小标题的图示 让 SSH 可以使用后门连线
    我们在 SSH 章节里面曾经谈到 SSH 最好不要对整个 Internet 开放对吧！所以你最好只要针对几个网域或者是 IP 开放他们能够以 ssh 登入你的伺服器啦。那么我能不能透过 WWW 网页填写一些重要的资料，让我可以修改主机的防火墙？ 然后我可以进入我的 Linux 主机呢？呵呵～是可以的！不过，你就得要自己小心啦！ 因为既然你可以透过这个网页来填写你的 IP ， 那么如果这个网页被其他人浏览了，那就危险啦！所以，这个网页的资料请将他放置到受保护的目录喔！ 这个网页档案资料的下载点在：
      http://linux.vbird.org/download/index.htm?action=detail&fileid=71
    假设你的保护目录在 /var/www/html/protect ，那么请到该目录下，然后将取得的 tarball 解压缩， 例如：‘ tar -zxvf apache.ssh.tgz ’，这样就 OK 啦！ 请特别注意，鸟哥的这个 PHP 网页其实写的很阳春，而且利用到很多 apache 的权限， 因此这个网页所在的目录其实权限是开放很大的！所以，你必需要很清楚的知道如何设定权限方面的问题才行。 基本的功能是这样的：
    • 假设你的 Apache 所设定的保护目录或 SSL 的目录在 $protectdir 当中，在预设的状态下鸟哥将他指定到 /var/www/html/protect 这个目录喔；
    • 整个资料被鸟哥通通放置到 $protectdir/ssh 目录下；
    • $protectdir/ssh/index.htm 就是主程式，就是要有他才行！这个档案请使用 vi 进去修改， 在该档案开头的四行请自行改写成你所需要的帐号/密码相关资料；
    • $protectdir/ssh/temp/ 是网页会主动改写的目录，请让他可以被 apache.apache 这个 owner.group 所写入才行！ 而在这个目录下还有两个档案， ip.new 及 iptables.ssh.sh 也需要是 apache.apache 的权限！
    • $protectdir/ssh/temp/ip.sh 是用来判断是否需要加入防火墙功能的一个 script， 这个档案也需要修改，请你修改这个档案内的 basedir 那个变数即可。然后， 请你将他放置到 /etc/crontab 的执行当中，每 3 或 5 分钟执行一次，例如‘*/3 * * * * root $protectdir/ssh/temp/ip.sh ’ 注意，那个 $protectdir 请填写正确的目录，例如 /var/www/html/protect ！
    • 开启浏览器，填入‘http://your.host/protect/ssh/’就会出现网页啦！请自行测试先！
    如此一来，系统每 3 分钟会主动去执行 IP 的检查，所以如果你在该网页填写了你的 IP ， 则 3 分钟内系统会将该笔资料加入防火墙内，如此一来你就可以利用该 IP 登入 ssh 这个服务了！ 再说一遍，这个程式仅是提供给您暂时测试用的，有需要才下载去使用， 否则不要随意将他放置到 Internet 上面啊！鸟哥不保证执行的后果喔！

    小标题的图示 防砍站软体
    几个比较知名的网站管理员大概都有这样的困扰，那就是网站常被砍站软体所强力下载，结果造成主机的 CPU loading 过重，最后竟然会导致死掉～唉！真是的～人怕出名猪怕肥呐！先来解释一下什么是砍站吧！

    所谓的‘砍站’，就是以类似多点连线下载的持续性讯息传递软体进行网站资料的下载，而且， 一启用该软体，该软体就将‘整个网站’的内容都给他 download 下来，很厉害吧！没错！是很厉害，但是却也害死人了～怎么说呢？

    因为这种软体常常会为了加快 download 的速度，所以采用多点连线的方式，也就是会持续不断的向 Server 发出要求封包，而由于这些封包并不见得能够成功的让 Server 把资料传导给 Client 端，常常会无法投递就是啦！这样的结果就是.....造成 Server 要一直不断的回应，又无法正确的回应出去， 此外，要求太过频繁，结果主机应接不暇，最后....就当机了...真的是林老师ㄌㄟ～

    我们这个小站的主机古早以前，就是因为这样的原因，导致服务常常断断续续的，并且，由于 CPU loading 太高，结果让正常连线进来看资料的网友没有足够的资源，因此网页开启的速度就变的很慢～唉～ 这些砍站的人，也太不道德啦！

    由于这种砍站软体真的很麻烦，一不注意马上就又会被砍站而当机，三天两头就要重新开机一次，完全让 Linux 的稳定性无法发挥！真是气死了～后来，鸟哥就自行写了一个 scripts 来挡这样的 IP ！我的作法是这样的：
    1. 由于砍站软体会多点连续下载，因此，同一个 IP 在同一个时间内，会有相当多的连线发生；
    2. 由于他是重复不断的要求连线，因此刚刚建立的连线在达成下载的目的后，会立刻死掉， 而又多生出其他的连线出来，因此，这个时候他的连线情况就变的相当的不正常了！
    3. 由于某些较旧的砍站软体并不会‘欺骗’主机，所以，会在主机的登录档里面记录住 Teleport 的标记！
    4. 既然如此的话，那么我就让我的主机每分钟去检查两个东西(1)先检查 log file ，如果有发现到相关的 Teleport 字词，就将该 IP 抵挡掉；(2)使用 netstat 来检查同一个 IP 的同时连线，如果该连线超过一个值(例如同时有 12 个连线)的话，那么就将该 IP 抵挡掉！
    5. 此外，由于上面的方案可能会将 Proxy 的 Client 端也同时抵挡掉，真是可怜啊！ 这个时候，这支程式就会主动的将(1)的情况的主机抵挡 3 天，至于(2)的情况则抵挡2小时！ 过了该抵挡的时限后，该 IP 即可又连上我们的主机了！
    大致上就是这样吧！这样的一程式需要与 iptables 相互配合，所以，请先查阅一下简易防火墙设定那一篇文章，然后再来下载这支程式吧！ 这支程式您可以在底下的网址下载喔！
      http://linux.vbird.org/download/index.htm?action=detail&fileid=47
    详细的安装步骤鸟哥已经以中文写在该档案里面了，所以请先查看一下该档案的前面说明部分吧！此外， Study Area 的 netman 大哥也已经开发了一套很棒的防砍站的程式了！ 在防堵砍站的原理上面是完全相同的，不过写法可能不是很雷同就是了！如果有需要的话，也可以前往 Study-Area 搜寻一下啰！
      http://phorum.study-area.org/viewtopic.htm?t=13643
    大标题的图示 重点回顾
    • WWW 的传输协定使用 HTTP (Hyper Text Transport Protocol) ，最早是由欧洲核子物理实验室的伯纳斯-李所发展的；
    • WWW 在 server/client 端主要传递的讯息资料以 HTML (Hyper Text Markup Language) 语法为主；
    • http://www.w3c.org 为制订与发布 WWW 标准语法的组织，您撰写网页最好依据该站之标准为宜；
    • Apache 是达成 WWW 伺服器的一项软体，至于用户端的浏览则使用浏览器，目前可使用 firefox
    • 浏览器可达成的主机连结不止 http，可在网址列输入对应的‘协定://主机[:port]/资源’即可取得不同的资料；
    • 若要 WWW 伺服器可以达成与使用者资讯互动，尚须要网页程式语言 (如PHP, perl 等) 以及资料库软体 (如 MySQL, portgresql 等)；
    • 因为 http 使用的是明码传送，目前 WWW 可利用 SSL 等机制来进行资料加密的传输；
    • Apache 的设定档其实只有 httpd.conf 而已，其他的设定档都是被 Include 进来的；
    • Apache 的首页目录以 DocumentRoot 决定，首页档案则以 DirectoryIndex 决定；
    • Apache 可以透过虚拟主机的设定以指定不同主机名称到不同的 DocumentRoot 下；
    • Apache 是多执行绪的软体，可以启动多个程序来负责 WWW。主要的模组有 prefork 及 worker， 至于最大可连线的数量则以 MaxClients 来决定。
    • 若要正确的让浏览器显示网页的编码格式，最好在网页上宣告语系，并将 Apache 的设定档 httpd.conf 内的 AddDefaultCharset 设定值取消；
    • 在 Apache 可浏览的目录权限设定上 (Options 参数)，最好将 Indexes拿掉；
    • 透过 AllowOverride 与 .htaccess 可让使用者在自己管理的目录下制订自己的风格；
    • Apache 本身提供一个 apachectl 的 script 让使用者得以快速管理其 apache 的服务；
    • Apache 分析的资料如果比较重要时，务必以 SSL 或者是保护目录来保护。
    大标题的图示 课后练习
    • 请问 LAMP 这个伺服器代表什么意思？
      • 这个名词代表了 Linux + Apache + MySQL + PHP 这个 WWW 伺服器的组成！
    • Apache 的设定档档名一般为何？
      • Apache 的设定档档名为 httpd.conf ，不过，由于 httpd.conf 内容参数可以使用‘ include "额外设定档名"’，所以也可能具有其他的额外设定档喔！
    • 在 Apache 的设定档当中，哪一个参数是用来设定‘主网页’的？
      • 设定主网页的参数为：DocumentRoot 喔！后面接的是主网页放置的‘目录’！
    • 哪一个指令用来重新启动与关闭 Apache ？(请以 Apache 本身提供的功能来说明)
      • 其实不论是 RPM 还是 Tarball 都是使用 apachectl 这个档案来启动 apache 的，不过 RPM 已经将该档案整合到 /etc/init.d/httpd 里面去而已
    • 当我使用 ps -aux 的时候，发现好多的 httpd... 的程序，这是正常的吗？ 最多可以有几个程序是在那个档案的那个参数所设定的？！
      • 由于 Apache 预设为多执行绪，所以启动多个 processes 是正常的。至于启动几个 process 则由很多设定所处理， 包括 MinSpareServers, MaxSpareServers, MaxClients 等等。
    • 又，呈上题，这些程序 (process) 的 owner 与 group 是谁？该察看那个设定档的那个参数？
      • 同样察看 httpd.conf 里面的 User 与 Group 这两个设定值！
    • 如果今天我以 http://your.ip 结果却发现浏览器出现类似 FTP 的画面(会列出该目录下的所有档案)，这是什么原因造成的？该如何避免？
      • 这是由于在 httpd.conf 里面，针对该目录的设定参数‘ Options ’当中，设定了 Indexes 这个设定值，导致当找不到主页时(通常是 index.html)，就会将该目录下的所有档案秀出来！解决的方法就是拿掉 Options 里面的 Indexes 设定值即可！
    • 在 Apache 里面 .htaccess 这个档案的功能为何？
      • 可以用来取代 httpd.conf 里面的设定参数！创造属于使用者自己的 Apache 风格！
    • 若你之前浏览过网页，但显示的资料并非正确的中文。后来按照上文的说明修改了中文的设定，却还是无法看到中文。 请问可能的原因为何？
      • 由于你曾经浏览过该网站的网页，所以该网页会被你的浏览器所暂存 (cache)，因此你应该可以这样做：
      • 在同一页面下按下‘ reload ’来重新载入；
      • 清除掉所有的浏览器快取；
      • 将原本的网页在伺服器端改名，并让浏览器浏览新的网页名称。
    • PHP 的程式码一定要使用 <?php 程式码 ?> 吗？有没有替代方案？
      预设的情况下，你应该要输入 <?php ?> 才能写入 PHP 的程式。不过早期的程式或许都以 <? ?> 来撰写的。 如果想要让该种方式生效的话，你可以进入 /etc/php.ini 档案中，修改‘short_open_tag = On’这个设定项目即可。
    大标题的图示 参考资料
    • 葛林.穆迪着，杜默译，‘Linux传奇’，时报出版；
    • WWW 发展者蒂姆·伯纳斯－李的生平简介： http://zh.wikipedia.org/wiki/蒂姆·伯纳斯－李
    • W3C 标准制订与公布网站：http://www.w3c.org
    • Apache 官方网站： http://www.apache.org/
    • Mozilla 官方网站： http://www.mozilla.org/
    • PHP 官方网站： http://www.htm.net/
    • MySQL 官方网站： http://www.mysql.org/
    • MySQL 中文使用手册： http://linux.tnc.edu.tw/techdoc/mysql/mysql_doc/manual_toc.html
    • Apache 1.3 版的 Tarball 安装方式：http://linux.vbird.org0360apache/0360apache-1.htm
    • Apache 2.0 的说明文件： http://httpd.apache.org/docs/2.0/mod/core.html
    • 林彦明的 Apache SSL 实战演练：http://www.vbird.org/somepaper/20060310-https.pdf
    2003/01/14：第一次完成
    2003/01/18：新增问题讨论：关于中文的说明
    2003/01/21：新增问题讨论：关于 PHP 无法使用的问题说明
    2003/04/28：加入砍站软体的程式说明
    2003/04/29：加入 PHP 原始码程式优化模组 MM Cache 说明。
    2003/05/07：加入 ab 这个效能测试的说明！
    2003/05/30：使用 Tarball 安装时常常发生一些困扰，加入 User/Group 的设定说明！
    2003/09/10：将原本在 2002/12 安装 Tarball 的套件更新为目前 2003/09 最新的版本来安装喔！
    2003/10/02：加入一些问题的克服之道喔！
    2004/03/25：修订2004/03/25：修订 MySQL 安装的流程！第四步骤加入权限的修订！
    2004/09/03：修改了 MMCache 的主网页。
    2006/10/21：将旧的文章移动到 此处
    2006/11/09：花了很多时间修改，不再提供 tarball 的安装需求了！
    2006/11/10：预先释出版本，包括修改 MM Cache 成为 eaccelerator、增加 SSL 修改 awstats 之安装等。
    2003/01/14以来统计人数


鸟哥的 Linux 私房菜 -- Mail Server

为取得较佳浏览结果，请爱用 firefox 浏览本网页

Mail 伺服器
切换解析度为 800x600
最近更新日期：2007/02/27
在这个邮件伺服器的架设中，我们首先谈论 Mail 与 DNS 的重要相关性，然后依序介绍 Mail Server 的相关名词，以及 Mail Server 的运作基本流程与协定，也会谈到相关的 Relay 与邮件认证机制等项目， 这些项目对于未来邮件主机的管理与设定是重要的，请不要忽略了这方面问题的讨论喔。 在这篇文章中，我们将 sendmail 与 postfix 合在一起讲了，因为目前 Postfix 这个伺服器的设定上面具有比较佳的亲和力， 所以 sendmail 我们仅作个简单的介绍，主要在以 Postfix 为主的邮件主机架设喔！

1. 本章的行前准备工作
2. 邮件伺服器的功能与运作原理
    2.1 电子邮件的功能与问题
    2.2 Mail server 与 DNS 之间的关系
    2.3 邮件传输所需要的元件 (MTA, MUA, MDA) 以及相关协定
    2.4 使用者收信时伺服器端所提供的相关协定
    2.5 Relay 与认证机制的重要性
    2.6 电子邮件的资料内容
    2.7 邮件伺服器架设前提
 3. Sendmail 伺服器的简易架设介绍
    3.1 所需要的套件与套件结构
    3.2 开放 sendmail 的监听介面与收信主机名称设定
    3.3 开放使用 MTA Relay 权限设定 /etc/mail/access
 4. 用 Postfix 达成 MTA 功能
    4.1 Postfix 的产生
    4.2 所需要的套件与套件结构
    4.3 让 Postfix 可监听 Internet 来收发信件
    4.4 信件传送流程与收信、relay 等重要观念
    4.5 设定邮件主机使用权限与过滤机制 /etc/postfix/access
    4.6 设定邮件别名
    4.7 邮件转递 ~/.forward
    4.8 察看信件伫列资讯
    4.9 设定 relay 的进阶功能
 5. 让你的 MTA 接受 MUA 的读信要求：POP/IMAP等协定
6. 用户端的收发信软体 (MUA)
    6.1 Linux mail
    6.2 Linux telnet
    6.3 Thunderbird 好用的跨平台 (Windows/Linux X) 软体
 7. 邮件主机的进阶设定：
    7.1 一些设定档所需要注意的‘权限’问题
    7.2 简单的广告信抵挡机制： postgrey 的动作
    7.3 关于黑名单的抵挡机制
    7.4 开放 SMTP 身份认证之 relay 机制
    7.5 基础的邮件过滤机制
    7.6 非固定 IP 也可以有春天： relayhost
    7.7 邮件扫瞄器：amavisd-new+f-port+spamassanssin (广告信自动学习)
    7.8 其他设定小技巧
 8. 其他应用说明
    8.1 问题检查
    8.2 哪些资料要备份
    8.3 quota 与目录移转
 9. 重点回顾
10.课后练习
11.参考资料
12.针对本文的建议：http://phorum.vbird.org/viewtopic.htm?p=117550
大标题的图示 本章的行前准备工作
玩过邮件主机的朋友都很清楚，在现在的环境当中想要搞定 Mail server 是很难的一件事情， 因为目前网路社会的广告信、垃圾信、病毒信实在是多的不像话，所以各主要的 ISP 对于邮件控管上面越来越严格， 因此如果你没有好好的规划好一些防备的工作，以及一些事前考虑规划的动作， 那么由你的邮件主机寄出去的信件很可能老是无法到达目标主机的！而且很重要的一件事情是， 邮件主机与 DNS 是不可分割的，尤其是 DNS 的 MX 标志，还有正反解的结果。无论如何，想要搞定 Mail server 你必需要：
  • 你一定要知道 DNS 的相关意义， 否则你的邮件主机肯定会发生不明原因的错误！
  • 网路基础也很重要，尤其是一些传输与检查方面的动作；
  • 正规表示法你最好要熟悉一些，因为很多邮件过滤机制是用他来处理的。
  • 套件与行程管理也要熟悉，因为 mail server 应用很多额外的程式来管理邮件。
  • 无论如何都要强调的，防火墙设定要正确， SELinux 记得先关闭！
大标题的图示 邮件伺服器的功能与运作原理
电子邮件是个啥玩意儿？他是利用网路传递一些资讯给远端主机的一种资讯传递行为，虽然讯息文字是很冷很硬的电脑文字， 确实比不上手写信件来的让人觉得温暖，不过，对于具有时效性的资讯来说，电子邮件可是个不可多得的好帮手！ 但是，电子邮件系统蓬勃发展的现在却被某些少部分的特定人士所乱用，导致垃圾信件、色情广告信件等等的泛滥！ 真是啊～伤脑筋～底下我们就先来谈一谈这个电子邮件相关的功能吧！

小标题的图示 电子邮件的功能与问题
在目前的社会当中，没有电子邮件 (e-mail) 似乎是蛮奇怪的一件事！可以说，现在 e-mail 已经成为一个很普遍的人与人之间的沟通管道了， 电子邮件可以很快速的帮你将文件或讯息传送到地球上的任何一个有网路存在的角落，当然， 你也可以在任何有网路的地方，连上 Internet 去收取你的信件！很快乐不是吗？

不过，遗憾的是，只要是有人类的地方，就会有很多你意想不到的事情会出现了，当然 e-mail 也不例外，怎么说呢？ 我们来慢慢的分析一下电子邮件产生的一些问题吧：
  • 夹带病毒的电子邮件问题：
    你可以常常听到电子邮件可能夹带病毒对吧！没错，利用电子邮件以及人们对于电子邮件的漫不经心的态度， 使得以电子邮件为媒介的电脑病毒更容易‘深入人群’当中呐！这个问题造成大大小小的伤害， 如果发生在大企业当中，那可真是受不了那～哪个主管受的了一天到晚电脑重新安装的～ 而且万一中毒的是大型主机，光是资料的损毁就可能让公司倒闭了....

  • 怪客透过邮件程式入侵：
    只要是开放给 Internet 用的程式就没有绝对安全的，只要在 Internet 上面跑的资料就没有绝对保密的！ 你可以轻易的使用怪客软体 (Cracker) 就可以取得使用者在利用 e-mail 传送过程当中所输入的帐号与密码， 若经过分析之后，还可能破解对方的邮件主机～哇！真是乱可怕一把的！

  • 广告信与垃圾信等：
    这个可说是目前各大 ISP 心中永远的痛～这些垃圾信件可以占掉很多那少的可怜的频宽， 使得正常使用者连线速度与品质下降，更可能造成网路的停顿～当然，常常收到垃圾信件的你，大概也不好过吧！

  • 主机被大量不明信件塞爆：
    万一你没有将邮件主机设定好，嘿嘿！送信者可以藉由你主机收信的功能，发送大量的信件， 让你‘一次收个够！’灌爆你的主机硬碟，想要不当机都粉难～

  • 真实社会的讨厌情事：
    ‘黑函’！听到会不会很害怕？当然很害怕啦！偏偏，使用 e-mail 就可以作很多的坏事～这真是太不道德了～

  • 不实的信件内容：
    只要注意到消基会的讯息就可以知道啦，不明来源的电子邮件说的内容，不要轻易的相信！ 因为很多可是以讹传讹，结果，大家都被耍了的～例如，你的朋友收到一封信，认为‘哇！这是大事情’， 所以在没有求证的情况下，将信‘转寄’给你看，嘿！你的朋友寄给你的，当然要相信他啦！ 立刻再转寄，如此一再地循环，嘿嘿！这个错误内容的讯息马上就让大家知道， 更可怕的是‘还会让大家接受～’所以，看到任何讯息时，请千万要记得求证一下呐！
可怕吧！电子邮件会衍生出这么多的问题说～另外，这个 email 伺服器的设定与管理真的是网管人员心中永远的痛！ 为什么呢？因为人都是想要越便利越简单越好，但越便利越不管制的邮件主机就越容易被攻击或遭利用！ 反过来说，如果你针对邮件主机管得太严厉，那就不太人性化，相信至少您的主管可能就不太满意， 怎么办？

呵呵！没错啦！邮件主机就是这么回事，让人又爱又怕的一个玩意儿，搞定他，恭喜您啊一切顺利圆满！ 搞不定他，主机被当成垃圾信件转运站事小，丢掉工作那可是‘兹事体大’呦！ 就因为他是这么重要又难以搞定，所以我们可得好好的学学他呐！

小标题的图示 Mail server 与 DNS 之间的关系
既然要使用 e-mail ，当然就需要邮件伺服器啰 (Mail Server)！不然你的信要怎样寄出去呢？事实上， mail server 的原理说难不难，但是说简单吗～似乎又有点难以理解ㄋㄟ～，所以， 底下我们要来谈一谈他的原理部分，然后再针对主机的设定来进行说明咯！我们首先要讲的就是‘ Mail server 系统与 DNS 系统有什么关连性？’ 这个部分新手最容易被搞混哩，是否要架设 mail server 就‘宿命’的一定得架设 DNS server 在你的主机上面吗？

  • Mail server 与合法的主机名称
    • 事实上目前已经没有人会使用 IP 来寄信了，我们通常接收到的 email 都是使用‘帐号@主机名称’的方式来处理的， 所以说，你的邮件伺服器‘就一定要有一个合法注册过的主机名称’才可以。为什么呢？ 因为邮件伺服器就是一部电脑主机嘛！这部电脑主机是利用 TCP/IP 来进行网路资料的传输， 所以当然需要有 IP 。不过因为网路使用泛滥的种种因素，导致我们不允许直接利用主机的 IP 来寄信了！ 因此，你想要架设 mail server 就‘必需’要有合法的主机名称啰。

    OK！既然我只要一个合法的主机名称即可，那么表示我不需要架设一部 DNS 主机啰？ 是的，你可以这样认为！只要你拥有合法的主机名称，亦即在 DNS 的查询系统当中你的主机名称拥有一个 A 的标志， 理论上你的 mail server 就可以架设成功 (相关的 DNS 与合法主机名称的注册请参考前面章节的说明)。 只不过由于目前网际网路上面的广告信、垃圾信与病毒信等占用了太多的频宽， 导致整个网路社会花费过多的成本在消耗这些垃圾资料。 所以为了杜绝可恶的垃圾信件，目前的大型邮件主机供应商 (ISP) 都会针对不明来源的邮件加以限制， 这也就是说‘想要架设一部简单可以运作的 mail server 越来越难了’。

  • DNS 的反解也很重要！
    • 对于一般的伺服器来说，我们只要使用正解让用户端可以正确的找到我们伺服器的 IP 即可架站， 举例来说 WWW 伺服器就是这样。不过，由于目前收信端的邮件主机会针对邮件来源的 IP 进行反解， 而如果你的网路环境是由拨接取得非固定的 IP 时，该种 IP 在 ISP 方面通常会主动的以 xxx.dynamic.xxx 之类的主机名称来管理，偏偏这样的主机名称会被主要的大型邮件伺服器 (例如 hotmail, yahoo 等) 视为垃圾信件， 所以你的邮件主机所发出的信件将可能被丢弃，那可就伤脑筋了！

    所以啊，如果你想要架设一部 Mail server 的话，请‘务必’向您的上层 ISP 申请 IP 反解的对应， 不要再使用预设的反解主机名称，否则很容易导致您的邮件主机所发出的信件会在 Internet 上面流浪啊！
    Tips:
    其实你还是可以不用申请 IP 的反解，不过就得要利用所谓的 relayhost 或者是 smarthost 来处理邮件转递的问题， 这个部分又涉及到上层 ISP 的问题，挺复杂！我们会在后续作说明！     		鸟哥的图示
  • 需要 DNS 的 MX 及 A 标志啊！
    • 那么我们的邮件伺服器系统到底是如何使用 DNS 的资讯来进行邮件的传递的？ 还记得在 DNS 章节里面谈到的 MX 这个标志吗？当时我们仅说过这个 MX 代表的是 Mail eXchanger， 当一封邮件要传送出去时，邮件主机会先分析那封信的‘目标主机的 DNS ’，先取得 MX 标志， 注意，MX 标志可能会有多部主机喔！然后以最优先 MX 主机为准将信发送出去。 看不懂吗？没关系，我们以底下这个 DNS 范例来说：
    xyz.com.vbird  IN  MX 10 mail.xyz.com.vbird
xyz.com.vbird  IN  MX 20 mail2.xyz.com.vbird
xyz.com.vbird  IN  A     aaa.bbb.ccc.ddd
    假如上述的 DNS 设定是正常的，那么：
    • 当有一封信要传给 user@xyz.com.vbird 时，由于 MX 标志最低者优先，所以该封信会先传送到 mail.xyz.com.vbird 那部主机。
    • 如果 mail.xyz.com.vbird 由于种种原因，导致无法收下该封信时，该封信将以次要 MX 主机来传送，那就是传送到 mail2.xyz.com.vbird 那部主机上头；
    • 如果两部 MX 主机都无法负责的话，那么该封信会直接以 A 的标志，亦即直接传送到 aaa.bbb.ccc.ddd 那个 IP 上头去， 也就是 xyz.com.vbird 本身啦！
    在这个过程当中，你必需要注意到：mail.xyz.com.vbird 及 mail2.xyz.com.vbird 必需要是可以帮 xyz.com.vbird 转信的主机才行，也就是说，那两部主机通常是你公司的最上游的邮件主机， 并不是你随意填写的！那两部主机还需要针对你的 xyz.com.vbird 来设定‘邮件转递’才行！ 否则你的信会被踢掉的。

    由于现在的很多邮件主机会去搜寻 MX 这个标志来判断目标邮件主机是否为合法，所以你要架设 Mail server 虽然不必自行设定 DNS 伺服器，不过你最好要申请一个 MX 的标志才行。此外，MX 标志一定要设定正确，否则你的信件将可能会直接被 MX 主机踢掉。为了要设定 MX 但是我们没有上层邮件伺服器时，所以你可以指定 MX 为自己，利用自己当 MX 主机即可。

    那么你或许会想，这个 MX 有啥好处啊？一般来说，如果目标主机挂点时，你的邮件通常会直接退还给原发信者， 但如果有 MX 主机时，这部 MX 主机会先将该封信放在他的伫列 (queue) 当中，等到你的目标主机重新提供邮件服务后， MX 主机会将你的信件传送给目标主机，如此一来你的信件就比较不会遗失啊！这样说，您可以了解吧！ ^_^

  • Email 的位址
    • 刚刚上头说过 email 通常是‘帐号@主机名称’的方式来处理，举例来说鸟哥的 linux.vbird.tsai 主机上面有个 dmtsai 的使用者，则我的 email 将会成为：‘dmtsai@linux.vbird.tsai’，当有人要寄信给我时， 他会分析 @ 后面的主机名称，亦即 linux.vbird.tsai 的 MX/A 标志等等，然后再透过刚刚说明的流程来传出信件。 而当我的 linux.vbird.tsai 收到这封信时，他会将信放到 dmtsai 的信箱当中啦！底下我们就来谈一谈这个流程吧！
    小标题的图示 邮件传输所需要的元件 (MTA, MUA, MDA) 以及相关协定
    在开始介绍邮件的传送过程之前，我们先来想一想，你是如何寄出电子邮件的？ 假设你要寄信给一个使用者，他的电子邮件是‘a_user@gmail.com’好了，也就是说， 你要寄一封信到 gmail.com 这个主机上的意思。 那你的桌上型电脑 (举例来说， Windows 系统) 是否能够将这封信‘直接’透过网路送给 gmail.com 那个主机上？ 当然不行啦！你得要设定帮你转信的邮件主机才行！也就是说，你必需要先向某一部邮件主机注册， 以取得一个合法的电子邮件使用权限后，才能够发送邮件出去的。

    所以说，你要寄出一封信件时是需要很多介面的帮忙的，底下列出一个简单的图示来说明：

    电子邮件传送的流程示意图
    图一、电子邮件传送的流程示意图

    我们先来解释一些专有名词吧！然后再来说明传送的流程：
    • MUA (Mail User Agent)：
      顾名思义 MUA 就是‘邮件使用者代理人’的意思，因为除非你可以直接利用类似 telnet 之类的软体登入邮件主机来主动发出信件，否则您就得要透过 MUA 来帮你送信到邮件主机上头去。 最常见的 MUA 像是 Mozilla 推出的 Thunderbird (雷鸟) 自由软体， 或者是 Linux 桌面 KDE 常见的 Kmail ，及 Windows 内件的 Outlook Express (OE) 等。 MUA 主要的功能就是收受邮件主机的电子邮件，以及提供使用者浏览与编写邮件的功能！

    • MTA (Mail Transfer Agent)：
      MUA 帮用户传送邮件到邮件主机上，那这部邮件主机如果能够帮用户将这封信寄出去，那他就是一部邮件传送主机 (MTA) 啦！这个 MTA 就是‘邮件传送代理人’的意思。也来顾名思义一下，既然是‘传送代理人’， 那么使用者寄出的信，与使用者要收信时，就是找他 (MTA) 就对啦！基本上， MTA 的功能有这些：

      1. 收受信件：使用简单邮件传送协定(SMTP)
        MTA 主机最主要的功能就是：将来自用户端或者是其他 MTA 的来信收下来，这个时候 MTA 使用的是 Simple Mail Transfer Protocol (SMTP)，他使用的是 port 25 啦！

      2. 转递信件：
        如果该封信件的目的地并不是本身的用户，且该封信的相关资料符合使用 MTA 的权力， 那么咱们的 MTA 就会将该封信再传送到下一部主机上。这即是所谓的转递 (Relay) 的功能。

      3. 回应使用者的收信要求：POP 或 IMAP 协定
        使用者可以透过 MTA 主机提供的邮政服务协定 (Post Office Protocol, POP) 来收下自己的信件， 也可以透过 IMAP (Internet Message Access Protocol) 协定将自己的信件保留在邮件主机上面， 并进一步建立邮件资料匣等进阶工作。

      总之，我们一般提到的 Mail Server 就是 MTA 啦！而严格来说， MTA 其实仅是指 SMTP 这个协定而已。 而达成 MTA 的 SMTP 功能的主要套件包括老牌的 sendmail ，后起之秀的 postfix ，还有 qmail 等等。 底下我们来看看，那么在 MTA 上头还有哪些重要的功能。

    • MDA (Mail Delivery Agent)：
      字面上的意思是‘邮件递送代理人’的意思。事实上，这个 MDA 是挂在 MTA 底下的一个小程式， 最主要的功能就是：分析由 MTA 所收到的信件表头或内容等资料， 来决定这封邮件的去向。所以说，上面提到的 MTA 的信件转递功能，其实是由 MDA 达成的。 举例来说，如果 MTA 所收到的这封信目标是自己，那么 MDA 会将这封信给他转到使用者的信箱 (Mailbox) 去， 如果不是呢？那就准备要转递出去了。此外，MDA 还有分析与过滤邮件的功能喔！举例来说：

      1. 过滤垃圾信件：
        可以根据该封邮件的表头资料，或者是特定的信件内容来加以分析过滤。例如某个广告信的主题都是固定的， 如‘AV情色...’等等，那就可以透过 MDA 来过滤并去除该邮件。

      2. 自动回覆：
        如果您出差了导致某一段时间内无法立即回信时，就可以透过 MDA 的功能让邮件主机可以自动发出回覆信件， 如此您的朋友就不会认为你太大牌！^_^

      各主要的 MTA 程式 (sendmail,postfix...) 都有自己的 MDA 功能，不过有些外挂的程式功能更强大， 举例来说 procmail 就是一个过滤的好帮手，另外 Mailscanner + Spamassassion 也是可以使用的一些 MDA 喔。

    • Mailbox：
      就是电子邮件信箱嘛！简单的说，就是某个帐号专用的信件收受档案啰。我们的 Linux 系统预设的信箱都是放在 /var/spool/mail/使用者帐号 中！ 若 MTA 所收到的信件是本机的使用者，MDA 就会将信件送到该 mailbox 当中去啰！
    好了，那么来想一想，你如何透过 MUA 来将信件送到对方的邮件信箱 (Mailbox) 去呢？
    • Step 0：取得某部 MTA 的使用权限：
      就如图一所示，我们本地端的 MUA 想要使用 MTA 来传出信件时， 当然需要取得 MTA 的使用权限。通常就是说：我们必须要向 MTA 注册一组可使用 email 的帐号与密码才行。

    • Step 1：使用者在 MUA 上编写信件后，传送至 MTA 上头：
      使用者在 MUA 上面编写信件，信件的资料主要有：
      • 信件标头：包括寄件者的 email 以及收件者的 email 位址，还有该封信件的主旨 (subject) 等；
      • 信件内容：就是你要跟对方说明的内容啦！
      编写完毕之后只要按下传送钮，该封信就会送至你的 MTA 主机上面了，注意：是你的 MTA 而不是对方的 MTA ！ 如果你确定可以使用该部 MTA 主机，那么你的这封信就会被放置到 MTA 的伫列 (queue) 当中并等待传送出去了。

    • Step 2.1：如果该封信的目标是本地端 MTA 自己的帐号
      你是可以寄信给你自己的，所以如果你的 MTA 收到该封信件的目标是自己的用户时，那就会透过 MDA 将这封信送到 Mailbox 去啰！

    • Step 2.2：如果该封信目的为其他 MTA ，则开始转递 (Relay) 的流程：
      那如果这封信的目标是其他的主机呢？这个时候我们的 MTA 就会开始分析该封信是否具有合法的使用权限， 若具有使用权限时，则我们的 MDA 会开始进行邮件转递，亦即该封信件会透过我们的 MTA 向下一部 MTA 的 smtp (port 25) 发送出去。如果该封信件顺利的发送出去了，那么该封信件就会由伫列当中移除掉了。

    • Step 3：对方 MTA 主机收受信件
      如果一切都没有问题的话，远端的 MTA 会收到我们 MTA 所发出的那封信，并将该信件放置到正确的使用者信箱当中， 等待使用者登入来读取或下载。
    在这整个过程当中，你会发现你的信件是由我们的 MTA 帮忙发送出去的，此时 MTA 提供的协定是简单邮件传输协定 (Simple Mail Transfer Protocol, smtp)， 并且该封信最终是停留在对方主机的 MTA 上头！并不是你朋友的 MUA 上头啊！
    Tips:
    为何特别强调这一点？因为以前有个朋有跟我说：‘鸟哥啊，你要寄 email 给我的时候记得跟我讲， 那我下班前将电脑开着，以免你信寄不到我的信箱’，此时额头三条线突然跑出来～很不好意思～ 所以这里才要特别强调，你的 MUA 不必开着啦！要收信时再打开即可。     		鸟哥的图示
    了解了传送信件时 MTA 需要启动 smtp (port 25) 之后，再来我们得要谈谈那这封信件对方要如何接收啊？

    小标题的图示 使用者收信时伺服器端所提供的相关协定
    那使用者如果想要收信时，当然也可以透过 MUA 直接来连线取得自己的邮件信箱内的资料啊！ 整个过程有点像底下这样：

    电子邮件收信时的流程示意图
    图二、电子邮件收信时的流程示意图

    使用者的 MUA 会透过两种基本协定来进行信件的收受喔：POP3 及 IMAP。 我们先谈一谈 POP3 的收信方式吧：
    1. MUA 透过 POP3 (Post Office Protocol version 3) 的协定连接到 MTA 的 port 110， 并且输入帐号与密码来取得正确的认证与授权；
    2. MTA 确认该使用者帐号/密码没有问题后，会前往该使用者的 Mailbox (/var/spool/mail/使用者帐号) 取得使用者的信件并传送给使用者的 MUA 软体上；
    3. 当所有的信件传送完毕后，使用者的 mailbox 内的资料将会被删除！
    在上述的流程当中我们知道 MTA 主机必须要启动 POP3 这个协定才行，不过这个协定的收件方式比较有趣， 因为使用者收信是由第一封信件开始收下直到最后一封信件传输完毕为止。 不过由于某些 MUA 程式撰写的问题， 若有些邮件有病毒的可能性时，透过防毒软体将可能导致该 MUA 软体的断线！ 如此一来由于传输没有完毕，因此 MTA 主机并不会将使用者的信件删除。 此时如果使用者又再一次的按下接收按键，呵呵！原来已接收的信件又会重复收到，而没有收到的还是收不到！

    这个时候或许你可以透过登入主机利用 mail 这个指令来处理你有问题的邮件， 或许换一种 MUA 也是个不错的思考方向，又或者暂时将防毒软体关掉也是可以考虑的手段之一。 转头过来想一想，因为 POP3 的协定预设会将信件删除，那如果我今天在办公室将我的信收到办公室的电脑中， 当我回家时再度启动 MUA 时，是否能够收到已经被接收的信件？当然不行，对吧！

    或许你需要更有帮助的协定，亦即 IMAP (Internet Messages Access Protocol) ， 这个协定可以让你将 mailbox 的资料转存到你主机上的家目录，亦即 /home/帐号/ 那个目录下， 那你不但可以建立邮件资料匣，也可以针对信件分类管理，而且在任何一个可连上网路的地方你只要登入主机， 原本的信件就还是存在呐！真是好啊！

    不过，使用 IMAP 时，使用者的目录最好能够加点限制，例如利用 quota 来管理使用者的硬碟使用权限， 否则因为信件都在主机上头，如果使用者过多且误用时，你的硬碟空间会被吃光光喔！注意注意！

    OK！透过上面的说明你要知道，要架设一部可以使用 MUA 进行收发信件的 MTA 伺服器，你至少也需要启动 SMTP 以及 POP3 这两个协定才行！而这两个协定的启动程式并不相同， 所以架设上还是得要小心注意啊！

    小标题的图示 Relay 与认证机制的重要性
    当你需要 MTA 帮你将信寄送到下一部 MTA 去时，这个动作就称为邮件转递 (Relay) 啰，那就是图一当中的 Step 2.2 那个动作啦。 那么我们来想一想，如果‘所有的人都可以藉由这一部 MTA 帮忙进行 Relay 时， 这个情况称之为 Open Relay 的动作’。当你的 MTA 发生 Open Relay 时，会有什么问题？ 问题可就大了！

    当你的 MTA 由于设定不良的关系导致具有 Open Relay 的状况，加上你的 MTA 确实是连上网际网路时， 由于网际网路上面用 port scan 软体的闲人太多，你的 MTA 具有 Open Relay 的功能这件事情， 将会在短时间内就被很多人察觉，此时那些不法的广告信、色情垃圾信业者将会利用你的这部 Open Relay MTA 发送他们的广告，所以你会发生的问题至少有：
    • 你主机所在的网域正常使用的连线速度将会变慢，因为网路频宽都被广告、垃圾信吃光了；
    • 你的主机可能由于大量发送信件导致主机资源被耗尽，容易产生不明原因当机之类的问题；
    • 你的 MTA 将会被网际网路社会定义为‘黑名单’，从此很多正常的邮件就会无法收发；
    • 你 MTA 所在的这个 IP 将会被上层 ISP 所封锁，直到你解决这个 Open Relay 的问题为止；
    • 某些用户将会对你的能力产生质疑，对您公司或者是你个人将会有信心障碍！甚至可能流失客源；
    • 如果你的 MTA 被利用来发黑函，你是找不到原发信者的，所以你这部 MTA 将会被追踪为最终站！
    问题很大呦！所以啊，目前所有的 distributions 都一样，几乎都将 MTA 预设启动为仅监听内部回圈介面 (lo) 而已，而且也将 Open Relay 的功能取消了。既然取消 Open Relay 的功能，那么怎么使用这部 MTA 的 Relay 来帮忙转信啊？呵呵！所以我们在上头才会一直说，你‘必需’取得合法使用该 MTA 的权限啊！ 这也就是说，设定谁可以使用 Relay 的功能就是我们管理员的任务啦！通常设定 Relay 的方法有这几种：
    • 规定某一个特定用户端的 IP 或网段，例如规定内部 LAN 的 192.168.1.0/24 可使用 Relay；
    • 若用户端的 IP 不固定时 (例如拨接取得的非固定 IP) 可以利用认证机制来处理。
    认证机制上面常见的有 SMTP 邮件认证机制，以及 SMTP after POP 两种，不论是哪一种机制， 基本上都是透过让使用者输入认证用的帐号与密码，来确定他有合法使用该 MTA 的权限， 然后针对通过认证者开启 Relay 的支援就是了。 如此一来你的 MTA 不再启动 Open Relay ，并且用户端还是可以正常的利用认证机制来收发信件， 身为管理员的你可就轻松多啰！ ^_^

    小标题的图示 电子邮件的资料内容
    看过上头的资料后，您应该对于 Mail server 有一些程度的认识了。再来要谈的是， 那么一封 email 的内容有哪些部分呢？就跟人类社会的邮件有信封袋以及内部的信纸一样， email 也有所谓的标头 (header) 以及内容 (body) 两部份喔！

    email 的标头部分会有几个重要资讯，包括：这封信来自那个 MTA、是由谁所发送出来的、要送给谁、 主旨为何等等，至于内容则是发信者所填写的一些说明啰。如果你使用 dmtsai 的身份下达这个指令：
    [dmtsai@linux ~]$ echo "HaHa.." | mail -s "from vbird" dmtsai
    然后将自己的信箱内容叫出来，如下所示：
    [dmtsai@linux ~]$ cat /var/spool/mail/dmtsai
From dmtsai@localhost  Tue Nov 21 00:33:29 2006   <==发信者 email
Return-Path: <dmtsai@localhost>                   <==之前的 MTA 来源
X-Original-To: dmtsai                             <==原收件者的资讯
Delivered-To: dmtsai@localhost                    <==最终此邮件转递给谁
Received: by localhost (Postfix, from userid 500) <==上一个 MTA 来源
        id 7A9C3A26B8; Tue, 21 Nov 2006 00:33:29 +0800 (CST)
To: dmtsai@localhost                              <==收件者信箱
Subject: from vbird                               <==主旨
Message-Id: <20061120163329.7A9C3A26B8@localhost> <==给 MTA 看的 ID
Date: Tue, 21 Nov 2006 00:33:29 +0800 (CST)
From: dmtsai@localhost (VBird)                    <==发信者 email
底下为信件内容
HaHa..
    由原本的信件内容上面我们可以看到确实是两部份，在标头部分记录了比较详细的收、发件者资料， 以及相关的来源、目标之 MTA 资讯等等。但你要注意的是，那个‘Received:...’那一行资料是‘会变动的’， 如同前面谈到的 MX 标志，如果一封信由 MUA 传送到 MTA 在由 MTA 传送到 MX 主机后，才传送到最终的 MTA 时， 那么这个 Received: 的资料将会记录每一部经手过的 MTA 资讯喔！ 所以你可以藉着这个记录资料慢慢的找回这封信的传递方向呢！

    此外，这个邮件的标头以及内容的分析部分，你还可以藉由某些分析软体来进行过滤， 这部份我们将在后头再慢慢的介绍给大家了解喔！ ^_^！您先知道一封邮件至少有这些资料， 以后咱们再慢慢的解释啰！

    小标题的图示 邮件伺服器架设前提
    前面谈到 mail server 与 DNS 系统有很大的相关性，所以如果你想要架设一部可以连上 Internet 的邮件伺服器时， 你必需要已经取得合法的 A 与 MX 主机名称，而且最好反解也已经向您的 ISP 申请修改设定了， 这可是个大前提！不要忽略他！在底下的练习当中鸟哥以之前 DNS 章节内的设定为依据， 主要的参数是这样的：
    • 邮件主机的主要名称为： linux.vbird.tsai
    • 邮件主机尚有别名为 www.vbird.tsai 及 ftp.vbird.tsai 也可以收发信件；
    • 此邮件主机已有 MX 设定，直接指向自己 (linux.vbird.tsai)
    • 这个 linux.vbird.tsai 有个 A 的标志指向 192.168.1.254。
    在实际的邮件伺服器设定当中，上述的几个标志是很重要的，请自行参考 DNS 章节的介绍吧！

    大标题的图示 Sendmail 伺服器的简易架设介绍
    可达成上述 MTA 功能的软体非常的多，不过在常见的 Linux distributions 上头则主要以数十年老牌子的 sendmail (http://www.sendmail.org) 以及近期以来很热门的 Postfix (http://www.postfix.org) 为主， 咱们的 CentOS 4.x 两种软体都有提供，不过主要是以 sendmail 为预设的 MTA 软体，所以我们首先会来介绍一下如何在 CentOS 4.x 上面开放 sendmail 监听所有介面的方法，然后再仔细的聊一聊如何设定 Postfix 吧！

    小标题的图示 所需要的套件与套件结构
    既然 CentOS 预设是以 sendmail 为主要的 MTA 软体，而我们的 Linux 又需要 MTA 来监听 lo 这个介面， 所以 sendmail 当然是已经安装好了！但是 sendmail 还需要很多额外的套件来辅助处理， 所以你至少也需要底下几个套件才行：
    • sendmail：提供主要的 sendmail 程式与设定档；
    • sendmail-cf：提供 sendmail.cf 这个设定档的预设整合资料；
    • m4：辅助将 sendmail-cf 的资料转成实际可使用的设定档。
    这三个套件是有相关性的啦，不过如果你在安装的时候没有选择完整安装所以套件时，sendmail-cf 可能没有安装， 所以请自行利用 rpm 以及 yum 检查看看，并自行安装好他吧！

    几乎所有的 sendmail 相关设定档都在 /etc/mail/ 目录下，主要的设定档基本上有这些：
    • /etc/mail/sendmail.cf (/usr/sbin/sendmail 的设定档)
      这就是 sendmail 的设定档！所有跟 sendmail 有关的设定都是靠他来完成的！不过，这个设定档的内容真不是给人看的， 鸟哥也老是看的‘雾煞煞’搞不懂！所以建议您不要随意手动修改这个档案啊！咦！设定档又不给人改， 那怎么处理额外的设定项目啊？ 就交给程式帮我们修改啊！所以才需要 sendmail-cf 这个套件嘛！看下去就知道了。

    • /usr/share/sendmail-cf/cf/*.mc
      这些档案是 sendmail.cf 这个设定档的预设参数资料，上面不是说不要直接手动修改 sendmail.cf 吗， 那如果你想要处理 sendmail.cf 的话，就得要透过这个目录下的参数档案来预先准备设定资料啰！ 当然啦，这些预设参数资料档案必需要透过 m4 那个程式来转换才行喔！

    • /etc/mail/sendmail.mc (由 m4 指令转换)
      是的是的！就是他！我们利用 m4 那个指令并通过指定的预设参数档案来重建 sendmail.cf ， 就是藉由这个档案来设定处理的！那我们应该要如何透过这个档案来重建 sendmail.cf 呢？ 简单的说，你可以参考底下这张图：

      利用 m4 来转换重建 sendmail.cf
      图三、利用 m4 来转换重建 sendmail.cf

      透过 m4 来处理即可，我们要作的就是修改 sendmail.mc 就好了，较为简单。

    • /etc/mail/local-host-names
      你的 MTA 能不能将信收下来与这个设定有关，鸟哥的范例当中主机名称有三个 (linux.vbird.tsai, www.vbird.tsai, ftp.vbird.tsai)，这三个主机名称得都要写入这个档案当中才行喔！ 否则将会造成例如： dmtsai@linux.vbird.tsai 可以收信，但是 dmtsai@www.vbird.tsai 却不能收信的现象， 虽然这两个 email 位址都是传送到同一部主机，不过你的 MTA 能不能收下该位址的信件，是需要设定的喔！

    • /etc/mail/access.db (/etc/mail/access, 利用 makemap 处理)
      用来设定是否可以 Relay 或者是能否接收信件的资料库档案！由于这个档案是资料库， 所以我们必需要‘修改 /etc/main/access 并使用 makemap 这个指令来建立 access.db 档案’才行！ 这个档案很重要的，我们内部 LAN 可以使用这个设定档来开放 Relay 的权限呢！

    • /etc/aliases.db (/etc/aliases, 利用 newaliases 处理)
      我们可以建立‘信箱别名’喔！假设你有一个使用者帐号为 dmtsai ，他还想要使用 dermintsai 这个帐号来收信， 你不需要再建立一个 dermintsai 的帐号，直接在这个档案里面设定一个别名，让寄给 dermintsai 的信件直接丢到 dmtsai 的信箱去即可！由于是资料库，所以你是需要‘修改 /etc/aliases 并透过 newaliases 来重建该档案’才行喔！

    • /var/spool/mqueue/ (可用 mailq 观察)
      这个就是 sendmail 的邮件伫列，当一封信被 MTA 收下后，就会被放置到这里来等待 MDA 的处理。 如果该封信件是本机帐号，那么就会被挪到 /var/spool/mail/使用者帐号 去，然后移除该封信件。 如果该封信件需要 Relay ，那么当信件传送到下一部 MTA 后，信件资料就会自伫列中移除。 不过当一封信暂时寄不出去时，该信件就会先被储放在这里，并等待继续尝试送出去。 如果你想要知道目前伫列内储放的信件资料，可以输入 mailq 来查阅喔！
    好了，再来让我们修改 sendmail 这个 MTA ，让她可以连上 Internet 吧！

    小标题的图示 开放 sendmail 的监听介面与收信主机名称设定
    事实上我们的 CentOS 预设已经启动了 sendmail 了，只是他只会接受来自本机的 MTA 要求！ 不相信吗？做一下底下的练习吧！

    例题：
    请列出目前你的主机上面，所有在监听 tcp/udp 当中的埠口与服务的对应资料
    答：
      直接利用 netstat 就能够列出来了，鸟哥的主机可以列出这些资料：
      netstat -tulnp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address  Foreign Address  State   PID/Program name
tcp        0      0 0.0.0.0:22     0.0.0.0:*        LISTEN  16856/sshd
tcp        0      0 127.0.0.1:25   0.0.0.0:*        LISTEN  8036/sendmail: acce

    在上面的例题当中你可以发现到 port 25 是由 sendmail 所启动的，而且‘只监听 127.0.0.1 这个 lo 介面’喔！ 所以我们的重点当然就是如何将监听的介面开启到整个 Internet 上，否则他是无法接收来自 Internet 的信件的啦！ 我们知道设定档在 /etc/mail/sendmail.cf ，但不要手动改他，你应该要修改的是 sendmail.mc 这个档案啦！ 这个档案的设定项目基本语法是这样的：
      设定元件(`设定项目', `参数一', `参数二')
    每个设定项目与参数左边使用的是数字键1左边那个按钮 (quote) ，右边则是单引号，别搞错喔！ 这个档案的设定项目你可以参考底下的网页说明：
    • http://linux.vbird.org0380sendmail.htm
    • http://www.sendmail.org/m4/readme.html
    我们这里只要改一个地方即可，其他的可以使用预设值就好了喔！
    1. 修改 sendmail.mc 的参数
[root@linux ~]# vi /etc/mail/sendmail.mc
# 找到底下这一行：
DAEMON_OPTIONS(`Port=smtp,Addr=127.0.0.1, Name=MTA')dnl
# 将他改成这样即可：
DAEMON_OPTIONS(`Port=smtp,Addr=0.0.0.0, Name=MTA')dnl

2. 备份旧的设定档资料
[root@linux ~]# cd /etc/mail
[root@linux mail]# mv sendmail.cf sendmail.cf.back1

3. 开始建立新的 sendmail.cf 设定档
[root@linux mail]# m4 sendmail.mc > sendmail.cf
    当你处理完毕之后，重新启动 sendmail 并检查一下 smtp 的监听埠口看看：
    [root@linux ~]# /etc/init.d/sendmail restart

[root@linux ~]# netstat -tlunp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address  Foreign Address  State   PID/Program name
tcp        0      0 0.0.0.0:25     0.0.0.0:*        LISTEN  8517/sendmail: acce
    瞧！监听的介面终于对整个 Internet 开放了！这个时候理论上你的 MTA 已经开始运作啰！ 而我们的 MTA 既然已经针对 Internet 来监听了，所以自然你的主机名称得要设定正确才行！ 否则主机预设只会接受‘localhost’这个主机名称的信件而已呐！我们可以这样做：
    [root@linux ~]# vi /etc/mail/local-host-names
linux.vbird.tsai
www.vbird.tsai
ftp.vbird.tsai

[root@linux ~]# /etc/init.d/sendmail restart
    改写完毕后记得要重新启动 sendmail 才会正式的生效喔！ 每一行有一个主机名称！请记住，未来如果您的主机新增了不同的主机名称， 并且你希望该主机名称可以用来收发信件，那么要修改 local-host-names ！那么什么时候不要将所有的主机名称都给他写到这个 local-host-names 里面去呢？

    由于目前的广告信件实在是太多了，他们会主动的在 Internet 上面搜寻一些主机名称， 然后随机四处发送垃圾邮件。如果您的主机有四个名称，每个主机名称都写到 local-host-names 去的话，很可能一封广告信您会‘收到四次’，因为四个主机名称嘛！所以啰！ 有的时候还是不要让全部的主机名称都可以收信是比较好的呐！

    小标题的图示 开放使用 MTA Relay 权限设定 /etc/mail/access
    根据图一的流程分析当中，我们知道一个 MTA 最主要的功能就是‘收信’与‘信件转递, Relay’， 上一个小节提到收信的部分主要与监听介面以及主机名称有关，那能否使用 Relay 的能力呢？ 这就是我们所需要了解的啦！

    在 Sendmail 的预设情况下只有 sendmail 伺服器本机 (localhost) 可以进行信件转递的功能， 其他任何用户端都无法使用这部 MTA 的！也就是说，除非你在这部 MTA 上面使用 mail 这个指令， 或者是使用 X Window 内的 MUA 来发信，其他的非本机用户都没有 relay 的能力。 哇！那么这部 MTA 还有啥用途啊？所以啊， 我们必须要针对用户端的 Relay 功能进行开放才行！这个设定得要很小心， 免得你的 MTA 变成 Open Relay 的不良状态啊！

    sendmail 使用 /etc/mail/access 这个档案来设定开放 Relay 或者是抵挡 Relay 的功能， 这个档案内的格式基本上是这样的：
      规范的范围或规则             Sendmail的动作
      IP/部分IP/主机名/Email等     RELAY/DISCARD/REJECT
    在这两个栏位之间最好使用<tab>按键来作为分隔，假设我要让内部的 192.168.1.0/24 这个网域， 还有 140.116.44.202 这部主机，以及在教育部 (ncku.edu.tw) 所管辖的领域之主机名称都能使用这部 MTA 的话， 你可以这样设定的：
    [root@linux ~]# vi /etc/mail/access
localhost.localdomain           RELAY
localhost                       RELAY
127.0.0.1                       RELAY
192.168.1                       RELAY
140.116.44.202                  RELAY
.edu.tw                         RELAY

[root@linux ~]# cd /etc/mail
[root@linux mail]# makemap hash access.db < access
# 上面这个动作在‘制作出 hash 格式的资料库’，请 man makemap 即可了解。
    做了这个动作后，整个内部网域以及外部的其他固定 IP 主机就能够使用你的 MTA 来进行 Relay 啰！不过非固定 IP 还是会有点困扰就是了。不过不打紧，我们还可以利用其他认证方式来开放使用权限的。 更多的 access 用法我们将在 Postfix 的章节当中进行介绍呐！ 在这里你先知道可以这样玩即可喔！ ^_^

    Sendmail 的设定到此后，你的 MTA 已经可以收受信件，也可以接受内部或特定 IP 的 Relay 信件， 其他更多的设定方式则可以参考 sendmail 的官方网站吧！当然啦，由于 postfix 本来就是用于相容 sendmail 的， 所以底下继续介绍的 postfix 的相关设定方法，你也可以用在 sendmail 上头呐！ 重复的不再说！赶紧继续看下去吧！
    大标题的图示 用 Postfix 达成 MTA 功能
    Sendmail 真是个很棒的 MTA 伺服器，不过他也有若干的缺点，包括早期的程式漏洞问题导致的主机安全性缺失； 还有 sendmail 将所有的功能都统合在 /usr/sbin/sendmail 这个程式当中，导致程式太大可能会有效能方面的疑虑； 以及完全不具有亲和力的设定档 sendmail.cf .....，所以后来才会有这个小巧效能又棒的 postfix 出来啊！

    小标题的图示 Postfix 的产生
    Postfix 是由 Wietse Zweitze Venema 先生(http://www.porcupine.org/wietse)所发展的。早期的 mail server 都是使用 sendmail 架设的，还真的是‘仅此一家，绝无分号！’！不过，Venema 博士觉得 sendmail 虽然很好用，但是毕竟不够安全，尤其效能上面并不十分的理想，最大的困扰是....sendmail 的设定档 sendmail.cf 真的是太难懂了！对于网管人员来说，要设定好 sendmail.cf 这个档案，真不是人作的工作。

    为了改善这些问题， Venema 博士就在 1998 年利用他老大在 IBM 公司的第一个休假年进行一个计划：‘ 设计一个可以取代 sendmail 的软体套件，可以提供网站管理员一个更快速、 更安全、而且完全相容于 sendmail 的 mail server 软体！’这个计划还真的成功了！ 而且也成功的使用在 IBM 内部，在 IBM 内可以说是完全取代了 sendmail 这个邮件伺服器！在这个计划成功之后， Venema 博士也在 1998 年首次释出这个自行发展的邮件伺服器，并定名为 VMailer。

    不过， IBM 的律师却发现一件事，那就是 VMailer 这个名字与其他已注册的商标很类似， 这样可能会引起一些注册上面的困扰。为了避免这个问题，所以 Venema 博士就将这个邮件软体名称改为 Postfix ！‘Post 为在什么什么之后’的意思，‘fix 则是修订’的意思，所以 postfix 有 ‘在修订之后’的意思。

    鸟哥个人认为， Venema 先生最早的构想并不是想要‘创造一个全新的 Mail server 软体，而是想要制造一个可以完全相容于 sendmail 的软体’，所以， Venema 先生认为他自行发展的软体应该是‘改良 sendmail 的缺失’，所以才称为 Postfix 吧！取其意为： ‘在 sendmail 之后的改良的邮件伺服器软体！’

    所以啦， Postfix 设计的理念上面，主要是针对‘想要完全相容于 sendmail’所设计出来的一款‘内在部分完全新颖’的一个邮件伺服器软体。就是由于这个理念，因此 Postfix 改善了 sendmail 安全性上面的问题，改良了 mail server 的工作效率， 且让设定档内容更具亲和力！因此，你可以轻易的由 sendmail 转换到 Postfix 上面！这也是当初 Venema 博士的最初构想啊！

    就是基于这个构想，所以， Postfix 在外部设定档案的支援度，与 sendmail 几乎没有两样，同样的支援 aliases 这个档案，同样的支援 ~/.forward 这个档案，也同样的支援 SASL 的 SMTP 邮件认证功能等等！ 所以，呵呵！赶紧来学一学怎样架设 Postfix 这个相当出色的邮件伺服器吧！ ^_^

    小标题的图示 所需要的套件与套件结构
    相对于 sendmail 还需要 m4 以及 sendmail-cf ， Postfix 要简单太多了！你只要安装 postfix 即可。 不过我们的 CentOS 虽然同时提供 sendmail 与 postfix ，不过鸟哥极不建议这两者并存喔！ 因此你在安装完 postfix 之后，记得将 sendmail 给他移除一下比较妥当一些些！ 所以你可以这样做：
    [root@linux ~]# /etc/init.d/sendmail stop
[root@linux ~]# yum install postfix
[root@linux ~]# rpm -e sendmail
[root@linux ~]# /etc/init.d/postfix start
    因为 Linux 系统至少需要一个 MTA 来让系统内部的帐号可以传送邮件，所以你必须要先安装 postfix 后才可以移除 sendmail 喔！顺序可不要搞错了！否则会跑出一堆相依属性的问题哩！ 那么 postfix 有哪些重要的设定档呢？他主要的设定档都在 /etc/postfix/ 当中， 详细的档案内容就让我们来谈谈：
    • /etc/postfix/main.cf
      这就是主要的 postfix 设定档啰，几乎所有的设定参数都是在这个档案内规范的！ 这个档案预设就是一个完整的说明档了，你可以参考这个档案的内容就设定好属于你的 postfix MTA 呢！ 只要修改过这个档案，记得要重新启动 postfix 喔！

    • /etc/postfix/master.cf
      主要规定了 postfix 每个程序的运作参数，也是很重要的一个设定档。 不过这个档案预设已经很 OK 了，通常不需要更改他。

    • /etc/postfix/access (利用 postmap 处理)
      与 sendmail 的 /etc/mail/access 具有相同的用途，可以设定开放 Relay 或拒绝连线的来源或目标位址等资讯。 不过这个档案要生效还需要在 /etc/postfix/main.cf 启动这个档案的用途才行。 且设定完毕后需要以 postmap 来处理成为资料库档案呢！

    • /etc/aliases (利用 postalias 或 newaliases 均可)
      不同的 distributions 这个档案放置的目录可能不太一样，在 CentOS 当中为了完全相容于 sendmail 与 postfix ， 所以这个档案预设放在 /etc/ 当中，其他版本则可能放置到 /etc/postfix 目录中喔！ 这个档案的用法与 sendmail 完全相同喔！
    至于常见的执行档则有底下这些：
    • /usr/sbin/postconf (查阅 postfix 的设定资料)
      这个指令可以列出目前你的 postfix 的详细设定资料，包括系统预设值也会被列出来， 所以资料量相当的庞大！如果你在 main.cf 里面曾经修改过某些预设参数的话，想要仅列出非预设值的设定资料， 则可以使用‘postconf -n’这个参数即可。

    • /usr/sbin/postfix (主要的 daemon 指令)
      此为 postfix 的主要执行档，你可以简单的使用他来启动或重新读取设定档：
      [root@linux ~]# postfix check   <==检查 postfix 相关的档案、权限等是否正确！
[root@linux ~]# postfix start   <==开始 postfix 的执行
[root@linux ~]# postfix stop    <==关闭 postfix
[root@linux ~]# postfix flush   <==强制将目前正在邮件伫列的邮件寄出！
[root@linux ~]# postfix reload  <==重新读入设定档，也就是 /etc/postfix/main.cf
      要注意的是，每次更动过 main.cf 后，务必重新启动 postfix ，可简单的使用‘postfix reload’即可。

    • /usr/sbin/postalias
      设定别名资料库的指令，因为 MTA 读取资料库格式的档案效能较佳，所以我们都会将 ASCII 格式的档案重建为资料库。 在 postfix 当中，这个指令主要在转换 /etc/aliases 成为 /etc/aliases.db 啰！用法为：
      [root@linux ~]# postalias hash:/etc/aliases
# hash 为一种资料库的格式，然后那个 /etc/aliases.db 就会自动被更新啰！
    • /usr/sbin/postcat
      主要用在检查放在 queue (伫列) 当中的信件内容。由于伫列当中的信件内容是给 MTA 看的， 所以格式并不是一般我们人类看的懂的文字资料。所以这个时候你得要用 postcat 才可以看出该信件的内容。 在 /var/spool/postfix 内有相当多的目录，假设内有一个档案名为 /deferred/abcfile ， 那你可以利用底下的方式来查询该档案的内容喔：
      [root@linux ~]# postcat /var/spool/postfix/deferred/abcfile
    • /usr/sbin/postmap
      这个指令的用法与 postalias 类似，不过他主要在转换 access 这个档案的资料库啦！用法为：
      [root@linux ~]# postmap hash:/etc/postfix/access
    • /usr/sbin/postqueue
      类似 mailq 的输出结果，例如你可以输入‘postqueue -p’看看就知道了！
    整个 postfix 的套件结构大致上是这个样子的，接下来让我们先来简单的处理一下 postfix 的收发信件功能吧！

    小标题的图示 让 Postfix 可监听 Internet 来收发信件
    同样的，咱们 CentOS 4.x 的 postfix 依旧预设仅支援本机介面的 smtp 服务而已， 所以如果你要对整个 Internet 开放的话，就得要努力的搞定几个简单的设定啰！ 而几乎所有的设定你都可已经由 /etc/postfix/main.cf 这个档案搞定！这个档案的内容你需要注意的是：
    • ‘#’符号是注解的意思；
    • 所有设定值以类似‘变数’的设定方法来处理，例如 myhostname = linux.vbird.tsai ，请注意等号的两边要给予空白字元喔，且第一个字元不可以是空白，亦即‘my..’要由行首写起；
    • 可以使用‘ $ ’来延伸使用变数设定，例如 myorigin = $myhostname，会等于 myorigin = linux.vbird.tsai；
    • 如果该变数支援两个以上的资料，则使用空白字元来分隔，不过建议使用逗号加空白字元‘, ’来处理。 例如： mydestination = $myhostname, $mydomain, www.vbird.tsai，意指 mydestination 支援三个资料内容之意。
    • 可使用多行来表示同一个设定值，只要在第一行最后有逗号，且第二行开头为空白字元， 即可将资料延伸到第二行继续书写；
    • 若重复设定某一项目，则以较晚出现的设定值为准！
    要让你的 postfix 可以收发信件时，你必需要启动的设定资料有底下这些喔：

  • myhostname：设定主机名称，需使用 FQDN 喔
    • 这个设定项目在于设定你的主机名称，且这个设定值被后续很多其他的参数所引用，所以必须要设定正确才行。 你应该要设定成为完整的主机名称。在鸟哥的这个练习当中，我们的主机名称为 linux.vbird.tsai， 所以请设定好他吧：
    [root@linux ~]# vi /etc/postfix/main.cf
myhostname = linux.vbird.tsai
    除了这个设定值之外，还有一个 mydomain 的设定项目，这个项目预设会取 myhostname 拿掉第一个‘.’以前的主机名称， 而设定出 domain name 。举例来说上头设定完毕后，预设的 mydomain 就是 vbird.tsai 啰！你也可以自行设定他。 基本上这两个设定值只是被用来引用的，你只要设定正确即可。

  • myorigin ：发信时所显示的‘发信源主机’项目
    • 这个项目在设定‘邮件标头上面的 mail from 的那个位址’， 也就是代表本 MTA 传出去的信件将以此设定值为准喔！如果你在本机寄信时忘记加上 Mail from 字样的话， 那么就以此值为准了。预设这个项目以 $myhostname 为主的，所以：
    myorigin = $myhostname
  • inet_interfaces ：设定 postfix 的监听介面 (极重要)
    • 在预设的情况下你的 Postfix 只会监听本机介面的 lo (127.0.0.1) 而已，如果你想要监听整个 Internet 的话， 请开放成为对外的介面，或者是开放给全部的介面，常见的设定方法为：
    inet_interfaces = all
    由于如果有重复设定项目时，会以最晚出现的设定值为准，所以当你设定为‘inet_interfaces = all’时，请将 inet_interfaces = localhost 那一行注解掉啊！

  • mydestination ：设定‘能够收信的主机名称’ (极重要)
    • 这个设定项目很重要喔！他就像 sendmail 内的 local-host-names 一样， 你的主机能够收下来的信件中，Mail to 写的主机名称必须要在这个设定值当中出现才行。 在我们这个练习当中这部主机有三个名字，linux.vbird.tsai, www.vbird.tsai 及 ftp.vbird.tsai 都需要写入喔！
    mydestination = $myhostname, localhost.$mydomain, localhost,
     www.vbird.tsai, ftp.vbird.tsai
    瞧见否？如果想要将同一个设定写成两行时，前一行最后最好使用逗号‘ , ’来隔开较佳。 因为 $myhostname 已经是 linux.vbird.tsai 了，所以不必改写。另外，如果你对 sendmail 的 local-host-names 情有独钟而想要继续使用该档案时，可以这样做：
    mydestination = /etc/postfix/local-host-names
    然后在该档案内加入所有你想要加入的主机名称即可！一般来说，不建议你额外建立 local-host-names 这个档案啦， 直接写入 main.cf 即可说！特别留意的是，如果你的 DNS 里头的设定有 MX 标志的话，那么请将 MX 指向的那个主机名称一定要写在这个 mydestination 内， 否则很容易出现错误讯息喔！特别的给他注意这一点！ 一般来说，使用者最常发生错误的地方就在这个设定里头呢！

  • mynetworks_style ：设定‘信任网域’的一项指标
    • 这个设定值在规定‘与主机在同一个网域的可信任用户端’的意思！举例来说，鸟哥的主机 IP 是 192.168.1.254，如果我相信整个区域网路内 (192.168.1.0/24) 的用户的话，那我可规定此设定值为‘ subnet ’呐！ 不过，一般来说，因为底下的 mynetworks 会取代这个设定值， 所以不设定也没有关系喔！如果要设定的话， 最好设定成为 host 即可 (亦即仅信任这部 MTA 主机而已)。
    mynetworks_style = host
  • mynetworks ：规定信任的用户端 (极重要)
    • 你的 MTA 能不能帮忙进行 Relay 与这个设定值最有关系！举例来说，我要开放本机与内部网域的 IP 时， 就可以这样进行设定：
    mynetworks = 127.0.0.0/8, 192.168.1.0/24
    还记得我们在 sendmail 内是以 access 来进行 relay 的设定吧？ 那如果你想要延续这个档案的设定呢？那鸟哥可以建议你将上述的资料改写成这样：
    mynetworks = 127.0.0.0/8, 192.168.1.0/24, hash:/etc/postfix/access
    然后你只要再建立 access 之后重整成资料库后，嘿嘿！就能够设定 Relay 的用户啰！

  • relay_domains ：规范可以帮忙 relay 的下一部 MTA 主机位址
    • 相对于 mynetworks 是针对‘信任的用户端’而设定的，这个 relay_domains 则可以视为‘针对下游 MTA 主机’而设定的。举例来说，如果你这部主机是 mail.kiki.vbird.tsai 的 MX 主机时， 那你就得要在 relay_domains 设定针对整个 kiki.vbird.tsai 这个领域的目标信件进行转递才行。 在预设的情况下，这个设定值是 $mydestination 而已啦。

    你必需要注意的‘Postfix 预设并不会转递 MX 主机的信件’，意思就是说：如果你有两部主机，一部是上游的 MTAup ，一部是下游的 MTAdown ，而 MTAdown 规范的 MX 主机是 MTAup，由 DNS 的 MX 设定值与信件传递方向我们知道任何想要寄给 MTAdown 主机的信件， 都会先经过 MTAup 来转递才行！此时如果那部 MTAup 没有开启帮 MTAdown 进行 relay 的权限时， 那么任何传给 MTAdown 的信件将‘全部都被 MTAup 所退回’！从此 MTAdown 就无法收到任何信件了。

    上一段的说明请您特别再想一想，因为如果你在大公司服务而且你的公司上、下游均有 mail server 时， 并且也有设定 MX 的状况下，嘿嘿！这个 relay_domains 就很重要啦！上游的 MTA 主机必需要启动这个设定。 一般来说除非你是某部 MTA 主机的 MX 源头，否则这个设定项目可以忽略不设定他。 而如果你想要帮你的用户端转递信件到某部特定的 MTA 主机时，这个设定项目也是可以设定的啦。 预设请您保留预设值即可。
    relay_domains = $mydestination
  • alias_maps ：设定邮件别名
    • 只要指定到正确的档案去即可，这个设定值可以保留预设值啊：
    alias_maps = hash:/etc/aliases
alias_database = hash:/etc/aliases
    在了解上述的设定后，以鸟哥的范例来看的话，我有更动过的设定值以及相关档案是这样处理的：
    [root@linux ~]# vi /etc/postfix/main.cf
myhostname = linux.vbird.tsai
myorigin = $myhostname
inet_interfaces = all
mydestination = $myhostname, localhost.$mydomain, localhost,
     www.vbird.tsai, ftp.vbird.tsai
mynetworks = 127.0.0.0/8, 192.168.1.0/24, hash:/etc/postfix/access
relay_domains = $mydestination
# 其他的设定值就先保留预设值即可啊！

[root@linux ~]# postmap hash:/etc/postfix/access
[root@linux ~]# postalias hash:/etc/aliases
    然后准备来启动啦！你可以这样处理喔：
    1. 先检查设定档的语法是否有错误
[root@linux ~]# postfix check   <==如果没有出现任何讯息，表示没有问题。

2. 启动与观察 port number
[root@linux ~]# /etc/init.d/postfix restart
[root@linux ~]# netstat -tlunp | grep ':25'
tcp  0   0 0.0.0.0:25    0.0.0.0:*   LISTEN   20850/master
    很简单吧！这样就设定妥当了，你的 Postfix 已经可以开放用户端进行转递，并且也可以收受信件啰！ 不过，到底在预设的情况下我们的 postfix 可以收下哪些信件？又可以针对哪些设定值的内容进行转递呢？ 这就得要参考下一小节的说明了。

    小标题的图示 信件传送流程与收信、relay 等重要观念
    我想，您对于 MTA 的设定与收发信件应该有一定程度的概念了，不过要妥善设定好你的 MTA 时， 尤其是想要了解到整部 MTA 是如何收、发信件时，你最好还是要知道‘我这部 MTA 如何接受来源主机所传来的信件，以及将信件转递到下一部主机去’的整个流程啊。 一般来说一封邮件传送会经过许多的流程为：
    1. 送信端与收信端两部主机间会先经过一个握手 (ehlo) 的阶段，此时送信端被记录为发信来源(而不是 mail from)。 通过握手后就可以进行信件标头 (header) 的传送；

    2. 此时收信端主机会分析标头的资讯，若信件之 Mail to: 主机名称为收信端主机，且该名称符合 mydestination 的设定，则该信件会开始被收下至伫列，并进一步送到 mailbox 当中； 若不符合 mydestination 的设定，则终止连线且不会进行信件内容 (body) 的传送；

    3. 若 Mail to: 主机名称非为收信端本身，则开始进行转递 (relay) 的分析。

    4. 转递过程首先分析该信件的来源是否符合信任的用户端 (这个用户端为步骤 1 所记录的发信主机喔) ，亦即来源是否符合 mynetworks 的设定值， 若符合则开始收下信件至伫列中，并等待 MDA 将信件再转递出去，若不符 mynetworks 则继续下一步；

    5. 分析信件来源或目标是否符合 relay_domains 的设定，若符合则信件将被收下至伫列，并等待 MDA 将信件再转递出去；

    6. 若这封信的标头资料都不合乎上述的规范，则终止连线，并不会接受信件的内容资料的。
    整个流程有点像底下这样：

    邮件传输方向
    图四、邮件传输方向

    也就是说标头分析通过后，你的信件内容才会开始上传到主机的伫列，然后透过 MDA 来处理该信件的流向。 而不是将信件完整的传送到主机后才开始分析的喔！这个得要特别注意呐！而透过上述的流程后， 在暂不考虑 access 以及 MDA 的分析机制中，一部 MTA 想要正确的收、发信件时，电子邮件必需要符合：
    • 收信方面：必需符合底下需求：
      1. 发信端必需符合 $inet_interfaces 的设定；
      2. 信件标头之收件者主机名称必需符合 $mydestination 的设定， 或者收件主机名称需要符合 $virtual_maps (与虚拟主机有关) 的设定；

    • 转递方面：必需符合底下需求：
      1. 发信端必需符合 $inet_interfaces 的设定；
      2. 发信端来源必需为 $mynetworks 的设定；发信端来源或信件标头之收件者主机名称符合 $relay_domains 之设定内容。
    同样的原理与想法你可以将他用在 sendmail 的设定当中喔！ ^_^！不过很多垃圾信却是藉由这个预设的收发管道来发送， 怎么说呢？请看底下的分析：

    例题：
    在我的主机上面竟然发现这样的广告信，那就是‘利用我的主机发送广告信给我自己！’ 为什么这样也可以呢？
    答：
      首先，你必需要熟悉一下上述的流程，在第 2 个步骤当中我们知道，当主机收到一封信且这封信的目标是自己， 并且也符合 mydestination 的设定时，该信件就会被收下来而不必验证用户端是否来自于 mynetworks 了。 所以说，任何人都可以用这个流程来寄信给你啊。不过，你的 MTA 并不是 open relay 啦， 不会帮人家发送广告信的，不用担心。

    例题：
    我的主机明明没有 Open relay ，但很多其他的 MTA 管理员发信给我，说我的主机的某个帐号持续发送广告信， 但是我的主机明明没有那个帐号啊！这是怎么回事？
    答：
      仔细看一下流程的步骤 1 与 2 ，确认该封信能否被收下来与发信端及收信端主机名称有关。 而我们知道在邮件的 header 里面还有一个 mail from 的标头设定项目，这个标头设定是我们在查阅邮件时看到的‘回邮位址’， 这个资料是可以伪造的！而且他与收发信件的资料无关！所以，您应该要告知对方 MTA 管理员， 请他提供详细的 log 资料，才能够判断该封信是否由你的主机所发送出去的。

      一般来说，目前的广告业者很多都是利用这种欺敌的方式来处理的，所以您必需要请对方提供详细的 log file 资料以供查验才行喔！

    小标题的图示 设定邮件主机使用权限与过滤机制 /etc/postfix/access
    基本上，指定了 Postfix 的 mynetworks 就能够让使用者 relay 了，不过如果你依照鸟哥上述的方式来设定你的 mynetworks 的话，那么我们还可以利用 access 这个档案来额外管理我们的信件过滤呢！ 基本的 access 语法再说明一次：
      规范的范围或规则             Postfix 的动作
      IP/部分IP/主机名/Email等     ACCEPT/REJECT
    假设你想要让 140.116.44.202 还有 .edu.tw 可以使用这部 MTA 来转递信件，且不许 av.com 以及 192.168.100.0/24 这个网域的使用时，可以这样做：
    [root@linux ~]# vi /etc/postfix/access
140.116.44.202		ACCEPT
.edu.tw			ACCEPT
av.com			REJECT
192.168.100		REJECT
# ACCEPT 表示可接受，而 REJECT 则表示拒绝。

[root@linux ~]# postmap hash:/etc/postfix/access
    用这个档案设定最大的好处是，你不必重新启动 postfix ，只要将资料库建立好，立刻就生效了！ 不过这个档案的进阶设定还需要 main.cf 内的其他规范有设定才行！如果只是之前 $mynetworks 的设定值时， 你只能利用上述的方式来开放 relay 的能力。不过，至少他可以让我们的设定简化啰！ ^_^

    小标题的图示 设定邮件别名
    想一想，你的主机里面不是有很多系统帐号吗？例如 named, apache, mysql...， 那么以这些帐号执行的程式若有讯息发生时，他会将该讯息以 email 的方式传给谁？ 原则上是传给 root 这个管理员。不过，为啥会传给 root 啊？这是因为其他的系统帐号并没有密码可登入， 自然也没有接收邮件的必要。所以若有邮件就给系统管理员啰。不过，咱们的 MTA 怎么知道这些信件要传给 root ？ 这就得要 aliases 这个邮件别名设定档来处理啦！

    在你的 /etc/aliases 档案内，你会发现类似底下的字样：
    [root@linux ~]# vi /etc/aliases
mailer-daemon:  postmaster
postmaster:     root
bin:            root
daemon:         root
adm:            root
....底下省略....
    左边是‘别名’右边是‘实际存在的使用者帐号或者是 email address’！就是透过这个设定值， 所以让我们可以将所有系统帐号所属的信件通通丢给 root 啊！好，我们现在将他扩大化，假如你的 MTA 内有一个实际的帐号名称为 dmtsai ，这个使用者还想要使用 dermintsai 这个名称来收他的信件， 那么你可以这样做：
    [root@linux ~]# vi /etc/aliases
dermintsai:     dmtsai
# 左边是你额外所设定的，右边则是实际接收这封信的帐号！

[root@linux ~]# postalias hash:/etc/aliases
    从此之后不论是 dmtsai@linux.vbird.tsai 还是 dermintsai@linux.vbird.tsai 都会将信件丢到 /var/spool/mail/dmtsai 这个信箱当中喔！很方便吧！

  • 让系统管理员的一般帐号可接收 root 的信
    • 假设你是系统管理员，而你常用的一般帐号为 dmtsai ，但是系统出错时的重要信件都是寄给 root 啊， 偏偏 root 的信件不能被直接读取....所以说，如果能够将‘给 root 的信也转寄一份给 dmtsai ’的话， 那就太好了！可以达到吗？当然可以！你可以这样做：
    [root@linux ~]# vi /etc/aliases
root:		root,dmtsai
# 信件会传给 root 与 dmtsai 这两个帐号！

root:		dmtsai
# 从此 root 收不到信了，都由 dmtsai 来接受！

[root@linux ~]# postalias hash:/etc/aliases
    上面那两行你可以择一使用，看看 root 要不要保留他的信件都可以的！其实这样一来， 你的 dmtsai 可以收到 root 的信，且 root 自己也可以‘备份’一份在他的信箱内，比较安全啦！

  • 发送群组寄信功能
    • 想像一个情况，如果你是学校的老师，你虽然只带一班，但是‘每年都一班’时，如果有一天你要将信发给所有的学生， 那在写 email 的标头时，可能就会头昏昏的了！这个时候你可以这样做： (假设主机上学生的帐号为 std001, std002... )
    [root@linux ~]# vi /etc/aliases
student95:	std001,std002,std003,std004...

[root@linux ~]# postalias hash:/etc/aliases
    如此一来只要寄信到这部主机的 student95 这个不存在的帐号时， 该封信就会被分别存到各个帐号里头去，管理上面是否很方便啊！ ^_^

    事实上，邮件别名除了填写自己主机上面的实体用户之外，其实你可以填写外部主机的 email 喔！ 例如你要将本机的 dermintsai 那个不存在的用户的信件除了传给 dmtsai 之外，还要外传到 dmtsai@mail.kiki.vbird.tsai 时，可以这样做：
    [root@linux ~]# vi /etc/aliases
dermintasi:	dmtsai,dmtsai@mail.kiki.vbird.tsai

[root@linux ~]# postalias hash:/etc/aliases
    很方便吧！更多的功能就期待您自行发掘啰！

    小标题的图示 邮件转递 ~/.forward
    虽然 /etc/aliases 可以帮我们达到邮件别名设定的好处，不过 /etc/aliases 是只有 root 才能修改的档案权限， 那我们一般使用者如果也想要进行邮件转递时，那该如何是好？没关系，可以透过自己家目录下的 .forward 这个档案喔！ 举例来说，我的 dmtsai 这个帐号所接收到的信件除了自己要保留一份之外，还要传给本机上的 vbird 以及 dmtsai@mail.kiki.vbird.tsai 时，那你可以这样做设定：
    [dmtsai@linux ~]$ vi .forward
# 注意！我的身份现在是 dmtsai 这个一般身份，而且在他的家目录下！
dmtsai
vbird
dmtsai@mail.kiki.vbird.tsai

[dmtsai@linux ~]$ chmod 644 .forward
    记得这个档案内容是一行一个帐号 (或 email) ，而且权限方面非常重要：
    • 该档案所在使用者家目录权限，其 group、other 不可以有写入权限。
    • .forward 档案权限，其 group、other 不可以有写入权限。
    如此一来这封信就会开始转递啰！有趣吧！ ^_^

    小标题的图示 察看信件伫列资讯
    说实话，设定到此为止咱们的 postfix 应该可以应付一般小型企业之 mail server 的用途了！ 不过，有的时候毕竟因为网路的问题或者是对方主机的问题，可能导致某些信件无法送出而被暂存在伫列中， 那我们如何了解伫列当中有哪些邮件呢？还有，在伫列当中等待送出的信件是如何送出的呢？
    • 如果该封信在五分钟之内无法寄出，则通常系统会发出一封‘警告信’给原发信者， 告知该封邮件尚无法被寄送出去，不过，系统仍会持续的尝试寄出该封邮件；
    • 如果在四小时候仍无法寄出，系统会再次的发出警告信给原发信者；
    • 如果持续进行五天都无法将信件送出，那么该封邮件就会退回给原发信者了！
    当然啦，某些 MTA 已经取消了警告信的寄发，不过原则上，如果信件无法即时寄出去的话 MTA 还是会努力尝试 5 天的，如果接下来的 5 天都无法送出时，才会将原信件退回给发信者。 一般来说，如果 MTA 设定正确且网路没有问题时，应该是不可能会有信件被放在伫列当中而传不出去的， 所以如果发现有信件在伫列时，当然得要仔细的瞧一瞧啰！检查伫列内容的方法可以使用 mailq ， 也可以使用 postqueue -p 来检查的：
    [root@linux ~]# postqueue -p
Mail queue is empty
    若您的邮件如此显示时，恭喜您，没有什么问题邮件在伫列当中。不过如果你将 postfix 关闭， 并尝试发一封信给任何人，那就可能会出现如下的画面啦：
    [root@linux ~]# /etc/init.d/postfix stop
[root@linux ~]# echo "test" | mail -s "testing queue" root
[root@linux ~]# postqueue -p
postqueue: warning: Mail system is down -- accessing queue directly
-Queue ID- --Size-- ----Arrival Time---- -Sender/Recipient-------
9C2D1A26AC       71 Thu Nov 23 14:59:31  root
                                         root

-- 0 Kbytes in 1 Request.
# 第一行就说明了无法寄出的原因为 Mail system is down 啦！
# 然后才出现无法寄出的信件资讯！包括来源与目标喔！
    输出的资讯主要为：
    • Queue ID：表示此封邮件伫列的代表号 (ID)，这个号码是给 MTA 看的，我们看不懂不要紧；
    • Size ：这封信有多大容量 (bytes) 的意思；
    • Arrival Time：这封信什么时候进入伫列的，并且可能会说明无法立即传送出去的原因；
    • Sender/Recipient：送信与收信者的电子邮件啰！
    事实上这封信是放置在 /var/spool/postfix 里面，由于信件内容已经编码为给 MTA 看的资料排列， 所以你可以使用 postcat 来读出原信件的内容喔！例如这样做 (注意看档名与 Queue ID 的对应！)：
    [root@linux ~]# cd /var/spool/postfix/maildrop
[root@linux maildrop]# postcat 9C2D1A26AC  <==这个档名就是 Queue ID
*** ENVELOPE RECORDS 9C2D1A26AC *** <==说明伫列的编号啊
sender_fullname: root               <==底下两个为发信者大名与 email
sender: root
recipient: root                     <==收信者为谁的意思啊！
*** MESSAGE CONTENTS 9C2D1A26AC *** <==底下则是信件的内容喔！
To: root
Subject: testing queue

test
*** HEADER EXTRACTED 9C2D1A26AC ***
*** MESSAGE FILE END 9C2D1A26AC ***
    如此一来你就知道目前我们的 MTA 主机有多少未送出的信件，还有未送出信件的内容你也可以追踪的到了！ 很不错，对吧！不过，如果你想要我们的 postfix 立刻尝试将这些在伫列当中的信件寄出去，那又该如何是好？ 你有几个作法啦，可以重新启动 postfix ，也可以透过 postfix 的动作来处理，例如：
    [root@linux ~]# /etc/init.d/postfix restart
[root@linux ~]# postfix flush
    鸟哥个人比较建议使用 postfix flush 啰！自行参考看看先！ ^_^

    小标题的图示 设定 relay 的进阶功能 smtpd_recipient_restrictions
    我们在前几节介绍过一封邮件进入 MTA 时该信件是否会被接受的几个大原则， 还有与 postfix 设定值相关的几个重要参数。事实上一封邮件在 postfix 里面能否被转递 (relay) 与 /etc/postfix/main.cf 里面的 smtpd_recipient_restrictions 这个设定值有关啦！ 这个设定值预设不存在于 main.cf 当中，你可以使用‘ man 5 postconf ’找到这个设定值的说明。

    smtpd_recipient_restrictions 就字面上的意思来说是‘SMTPD 这个 daemon 的接受者 (就是自己啊) 之限制’， 所以这个设定项目可以指定‘当要 relay 时，MTA 应该要参考什么设定值；以及当要接受本机信件时， 应该要参考哪些设定项目’的意思， 在预设的情况下这个设定值只有两个项目，分别是‘ permit_mynetworks, reject_unauth_destination ’， 是有‘顺序’之分的喔！

    上述的预设参数值最终造成前面提到的信件传送流程啦！ 不过有时你可能需要添加几个新功能，举例来说，你想要让 Internet 上面的任何一个 IP 都可以透过你的 MTA 来寄信时，那得要开启所谓的 SMTP 认证机制，此时你就得要将该认证机制写入这个设定参数当中才行！ 另外，如果你想要拒绝黑名单的来源与目标主机，那也是得要在这个参数后面加入额外的资料啊！ 总之，你需要对这个参数很了解就是了！更多相关的功能我们会在后续加以介绍的啦！

    大标题的图示 让你的 MTA 接受 MUA 的读信要求：POP/IMAP等协定
    不管你的 MTA 使用的是 sendmail 还是 postfix ，你还是得要配合 POP3/IMAP 这个提供使用者端来收信的协定才行！ 在早期的系统当中， POP3 使用的是 imap 这个套件提供的功能，不过近来提供此一协定的套件很多， 每种系统都可能不太相同。举例来说，咱们的 CentOS (Red Hat 系统) 使用的是鸽舍 (dovecot) 软体套件， 至于 SuSE 则提供 qpopper 这个套件说。

    启动单纯的 POP3 是很简单的啦，你得要先确定已经安装了 dovecot 这个软体。 而这个软体的设定档只有一个，就是 /etc/dovecot.conf 。我们仅要启动 pop3 而已， 所以可以这样设定即可：
    [root@linux ~]# vi /etc/dovecot.conf
# 找到底下这一行，大约是在第 14 行左右的地方
#protocols = imap imaps
# 将他改成底下这个样子：
protocols = pop3

# 找到底下这一行，大约是在第 22 行左右的地方
pop3_listen = [::]
# 如果只想要接受 IPv4 的位址，将他改成底下这个样子：
pop3_listen = *
    改完之后你就可以启动 dovecot 啰！并且检查看看 port 110 有没有启动啊？
    [root@linux ~]# /etc/init.d/dovecot start
[root@linux ~]# netstat -tlnp | grep ':110'
tcp 0  0 0.0.0.0:110   0.0.0.0:*  LISTEN   25335/dovecot
    耶！搞定！这样就可以提供使用者来收发信件啦！真是不错啊！不过记得喔，我们只提供基本的明码 pop3 传输而已， 如果想要启动其他如 pop3s (传输加密机制) 协定时，就得要额外的设定啰！ 接下来让我们看看用户端如何使用我们的邮件伺服器吧～ ^_^

    大标题的图示 用户端的收发信软体 (MUA)
    设定 Mail server 不是拿来好看的，当然是要好好的应用他啰！应用 mail server 有两种主要的方式， 你可以直接登入 Linux 主机来操作 MTA ，当然也可以透过用户端的 MUA 软体来收发信件， 底下我们分别介绍这两种方式啰！

    小标题的图示 Linux mail
    在 Unix like 的作业系统当中都会存有一支可以进行收发信件的软体，那就是‘ mail ’这个指令。 这个指令是由 mailx 这个套件所提供的，所以您得要先安装这个套件才行。 另外，由于 mail 是 Linux 系统的功能，所以即使你的 port 25 (smtp) 没有启动， 他还是可以使用的，只是该封邮件就只会被放到伫列，而无法寄出去啰！^_^！底下我们来谈一谈最简单的 mail 用法吧

  • 用 mail 直接编辑文字邮件与寄信
    mail 的用法很简单，就是利用‘ mail [email address] ’的方式来将信件寄出去， 那个 [email address] 可以是对外的邮件位址，也可以是本机的帐号。如果是本机帐号的话，可以直接加帐号名称即可。 例如：‘ mail root ’或‘ mail somebody@his.host.name ’。如果是对外寄信的时候， 信件预设的‘ Mail from ’就会填写 main.cf 内那个 myorigin 变数的主机名称啰！ 先来试看看吧！寄给 dmtsai@linux.vbird.tsai 先：
    [root@linux ~]# mail dmtsai@linux.vbird.tsai
Subject: Just test        <==这里填写信件标题
This is a test email.     <==底下为信件的内容！
bye bye !
.                         <==注意，这一行只有小数点！代表结束输入之意！
Cc:                       <==密件副本啦！
    这样就可以将信件寄出去了！另外，早期的 mail server 是可以接受 IP 寄信的，举例来说： mail dmtsai@[192.168.1.254] ，记得 IP 要用中括号包起来。不过由于受到垃圾邮件的影响， 现在这种方式几乎都无法成功的将信件寄出了。

  • 利用已经处理完毕的‘纯文字档’寄出信件
    这可不是‘附件夹带’的方式！因为在 mail 这个程式里面编辑信件是个很痛苦的差事， 你不能够按上下左右键来回到刚刚边极有错误的地方，很伤脑筋。此时我们可以透过标准输入来处理！ 如果你忘记‘ < ’代表的意义，请回到基础学习篇书中的 Bash shell 章节好好瞧瞧先。 举例来说你要将家目录的 .bashrc 寄给别人，可以这样做：
    [root@linux ~]# mail -s 'My bashrc' dmtsai < ~/.bashrc
  • 开始接收信件
    寄信还比较简单，那么收信呢？同样的收信还是使用 mail。直接在提示字元之后输入 mail 时，会主动的捉取使用者在 /var/spool/mail 底下的邮件信箱 (mailbox)，例如我 dmtsai 这个帐号在输入 mail 后，就会将 /var/spool/mail/dmtsai 这个档案的内容读出来并显示到荧幕上，结果如下：
    [root@linux ~]# mail
Mail version 8.1 6/6/93.  Type ? for help.
"/var/spool/mail/dmtsai": 1 message 1 unread
>U  1 root@linux.vbird.tsai  Fri Nov 24 11:34  32/764   "My bashrc"
&  <==这个是 mail 软体的提示字元，可以输入 ? 来察看可用指令
    在上面的话面中，显示 dmtsai 有一封信，且会附上该信件的发信者与标题及收信时间等。 你可以用的指令有这些：
    • 读信： (直接按 Enter 或输入数字后 enter)
      有看到‘>’那个符号吧！那表示目前 mail 所在的邮件栏位，你可以直接输入 Enter 即可看到该封信件的内容！ 另外，你也可以在‘&’之后的游标位置输入号码，就可以看该封信件的内容了！ (注：如果持续按 Enter ，则会自‘ > ’符号所在的邮件逐次向后读取每封信件内容！)

    • 显示标题： (直接数入 h 或输入 h 数字)
      如果要重新显示每封信的标题，可以输入 h 即可；

    • 回覆邮件： (直接输入 R )
      如果要回覆目前‘ > ’符号所在的邮件， 直接按下‘R’即可进入刚刚前面介绍过的 mail 文字编辑画面啰！你可以编辑信件后传回去啰！

    • 删除邮件： (输入 d 数字)
      按下‘ d## ’即可删除邮件！例如我要删除掉第 2 封邮件，可以输入‘d2’如果是要删除第10-50封邮件，可以输入‘d10-50’来删除喔！ 请记得，如果有删除邮件的话，离开 mail box 时，要使用‘q’才行！

    • 储存邮件到档案： (输入 s 数字 档名)
      如果要将邮件资料存下来，可以输入‘ s ## filename’，例如我要将上面第一封邮件存下来，可以输入‘ s 1 uuencode ’即可将第一封邮件内容存成 uuencode 这个档案！

    • 离开 mail： (输入 q 或 x )
      要离开 mail 可以输入 q 或者是 x ，请注意‘输入 x 可以在不更动 mail box 的情况下离开 mail 程式，不管你刚刚有没有使用 d 删除资料；使用 q 才会将删除的资料移除，并且会将所有已读过的信件内容转存到你家目录下的 mbox 档案！’也就是说，如果你不想更动 mail box 那就使用 x 或 exit 离开，如果想要使刚刚移除的动作生效，就要使用 q 啦！不过，使用 q 之后，只有未读的信件才会保留在 /var/spool/mail/accout 里面，其他已读的资料都会被存入 ~/mbox 当中！例如 /home/dmtsai/mbox 为储存 dmtsai 已读过的信件！

    • 请求协助：
      关于 mail 更详细的用法可以输入 help 就可以显现目前的 mail 所有功能！
    上面是简易的 mail 收信功能！不过，如果离开 mail 时按下 q ，不是会有信件转存到 ~/mbox 这个邮件信箱吗？那么我要如何读取这个档案内的信件资料呢？可以简单的使用这个方式来读取：
    [root@linux ~]# mail -f ~/mbox
  • 以‘附件夹带’的方式寄信
    前面提到的都是信件的内容，那么有没有可能以‘附件’的方式来传递档案？ 是可以的，不过你需要 uuencode 这个指令的帮忙，在 CentOS 当中这个指令属于 sharutils ，请先利用 yum 来安装他吧！接下来你可以这样使用：
    [root@linux ~]# [利用 uuencode 编码 ] | [利用 mail 寄出去]
[root@linux ~]# uuencode [实际档案] [信件中的档名] | mail -s '标题' email

范例一：将 ~/.bashrc 以附件夹带的方式寄给 dmtsai
[root@linux ~]# uuencode ~/.bashrc bashrc | mail -s 'test encode' dmtsai
    这样就能寄出去了，不过，如果收下这封信件呢？同样的我们得要透过解码器来解码啊！ 你得先将该档案存下来，然后这样做：
    [root@linux ~]# mail
Mail version 8.1 6/6/93.  Type ? for help.
"/var/spool/mail/dmtsai": 2 messages 2 unread
>U  1 root@linux.vbird.tsai  Fri Nov 24 11:34  32/764   "My bashrc"
 U  2 root@linux.vbird.tsai  Fri Nov 24 11:52  24/904   "test encode"
& s 2 test_encode
"test_encode" [New file]
& exit

[root@linux ~]# uudecode test_encode -o decode
                             加密档         输出档
    虽然 mail 这个指令不是挺好用的，不过至少他可以提供我们在 Linux 纯文字模式下的一个简单的收发信件功能！ 我们最好还是熟悉一下吧！ ^_^

    • 小标题的图示 Linux telnet
    刚刚的 mail 也算是一支简单的软体在进行收发信件，那如果你想要直接透过 smtp 以及 pop3 来收发信件呢？ 其实你可以透过 telnet 的功能来直接连线到该服务上头！ 不过，因为完全得要敲击指令来处理，所以底下的练习真的仅做为参考用啦！
    先来练习寄信看看：
[root@linux ~]# telnet localhost 25
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
220 linux.vbird.tsai ESMTP Postfix
ehlo localhost   <==进行握手！很重要！
250-linux.vbird.tsai  <==底下为本 SMTP 服务所提供的功能
250-PIPELINING
250-SIZE 10240000     <==单封信件的最大容量！
250-VRFY
250-ETRN
250 8BITMIME
mail from: "VBird"<dmtsai@linux.vbird.tsai> <==设定来源位址
250 Ok
rcpt to: <root@linux.vbird.tsai>            <==设定收信位址
250 Ok
data                                        <==确定内容撰写开始
354 End data with <CR><LF>.<CR><LF>
This is a test mail    <==开始写内容啦！
Just test ! bye bye!
.                      <==离开不要忘记的一个小数点！
250 Ok: queued as CC8CFA26AC
quit
    这样就能够将信放置到伫列当中，并且等待寄出啦！比较麻烦的是你必需要手动输入 header 与 body 的所有项目， 包括‘mail from:’‘rcpt to:’等等，且在这两个设定值后方的 email 必需要以括号圈起来，例如：
      MAIL FROM: usersname<userid@hostname.domainname>
      MAIL FROM: "users name"<userid@hostname.domainname>
    另外许多 MTA 目前都会限制再使用 MAIL FROM 时要先使用 HELO或者是 EHLO 先打招呼过，要不然会不允许进行后续沟通。 好了，那么直接收信呢？可以这样做！
    [root@linux ~]# telnet localhost 110
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
+OK dovecot ready.
user dmtsai         <==输入你的帐号啊！
+OK
pass your_password  <==输入你的密码啊！
+OK Logged in.
list                <==列出你有的信件啊！
+OK 3 messages:       <==底下为信件的资料，共有三封
1 912
2 1016
3 675
.
retr 2              <==开始接收第二封信件内容之意
+OK 1016 octets
....信件内容输出省略....
quit                <==离开 telnet 啰
+OK Logging out.
    这样就能够透过 telnet 连线到本机上头进行收、发信件的功能了！不过，真是不好用啊！ 所以我们底下来介绍一个可以跨平台的视窗介面软体，学这一套就好了， 因为他是跨平台，所以您可以在任何作业系统上面使用这套好用的咚咚呐！

    小标题的图示 Thunderbird 好用的跨平台 (Windows/Linux X) 软体
    自由软体最大的好处之一就是该软体大多可以进行移植，也就是在任何作业系统上面几乎都能够执行该软体的意思。 因此学习自由软体的好处就是，你不必因为转换作业系统而学习不同的操作环境！ 邮件使用者介面软体 (MUA) 也有自由软体了！那就是 Mozilla 基金会推出的 ThunderBird (雷鸟) 这个好用的咚咚， 你可以在底下的网址上面找到繁体中文的套件：
    • http://moztw.org/thunderbird/
    有鉴于目前用户端还是以 Windows 作业系统为大宗，所以底下的说明主要是在 Windows XP (sp2) 上头的安装与设定为主。虽然目前 (2006/12) 最新的 Thunderbird 已经出到 1.5.x 了， 不过繁体中文版更新的速度似乎无法跟的上，所以鸟哥底下以可以捉到的最新繁体中文版， 亦即 1.0.6 这个版本来作为介绍啰。

    在你下载原始的安装档案后，直接双击下载的档案就会进入安装的画面了。 安装真是太简单了！就是一直给他‘下一步’而已，最后有个‘马上执行 Thunderbird ’， 你可以选择他，然后就会出现是否要汇入‘Outlook Express’或者是‘Outlook’等其他邮件代理人程式已经建立的帐号资料， 如果您从未建立过帐号资料，那么这个地方可以略过，如果你要将系统上面已经存在的 OE 资料给他转移到雷鸟上， 就选择汇入吧！不过鸟哥这里假设从来没有使用过 OE，所以选择不汇入任何资料。

    Thunderbird 的使用
    图五、Thunderbird 的使用

    Tips:
    事实上 Outlook Express 这个 Windows 预设的邮件收发软体在比较大量的邮件收发过程当中， 偶而会出现一些错误的问题，尤其是档案大于 2GB 以上以及常常删除一些无用的信件， 却忘记进行 OE 所谓的‘压缩’时，会造成挺严重的错误，最严重的情况下您所有的信件都可能会遗失。 使用上必需要特别小心一些操作行为。您可以玩一玩雷鸟，比较一下两者的差异喔！     		鸟哥的图示
    由于 Thunderbird 可以提供多种资讯的下载，所以我们必须要自行指定所需要的帐号资料才行。 如下图所示，我们指定的是 Email 的帐号喔！点选他，然后给他下一步吧！

    Thunderbird 的使用
    图六、Thunderbird 的使用

    首先要你填写的并不是实际的帐号资料，而是你想要‘收信者看到的属于你的资讯’而已。 在‘大名’的部分可填写你的昵称或实际大名；在 Email 位址则请填写希望对方‘回信时的 email ’。 其实这里就是邮件 Header 部分的‘ Mail from: "大名"<email> ’啦！ 你得要注意的是，如果 email 填写错误，收件者直接‘回信’时，将无法寄达正确的地方喔！

    Thunderbird 的使用
    图七、Thunderbird 的使用

    再来才是重要的收、发信件的邮件主机所在处，你可以在收件伺服器及伺服器名称部分填写主机名称， 当然也可以直接填写 IP 的啦！一般在 LAN 内的 private IP 鸟哥都使用 IP 来填写而已说！ ^_^

    Thunderbird 的使用
    图八、Thunderbird 的使用

    你要用什么帐号来收信啊？这里真的不能写错了喔！

    Thunderbird 的使用
    图九、Thunderbird 的使用

    底下的帐号名称其实只是一个提醒的名字而已，所以你可以直接使用 email 来作为这个帐号的提示名称即可。

    Thunderbird 的使用
    图十、Thunderbird 的使用

    如果如下所示，一切都没有问题时，就按下那个‘立即下载邮件’并且按下‘完成’吧！

    Thunderbird 的使用
    图十一、Thunderbird 的使用

    最终结果终于出现啦！就是底下的样子！左边是一些信匣，右边上方则是各个信件的标头， 右边下方则是实际的信件内容啊！

    Thunderbird 的使用
    图十二、Thunderbird 的使用

    更多的 Thunderbird 使用就请自行参考线上的说明文件来玩玩吧！ 不会很难啦！与常用 Outlook express 的朋友来说，你会觉得他根本与 OE 就是一模一样嘛！ 操作操作也就熟悉啰！ ^_^

    大标题的图示 邮件主机的进阶设定：
    Sendmail 常常被传成‘安全性很差的邮件伺服器！’当然， Sendmail 官方网站也很不满的回应说‘ 其实， Sendmail 的问题来自于一些"该死的"档案权限设定错误的状况！ ’也就是说，其实 sendmail 常常会因为‘系统管理员’设定档案或者目录不良的情况下，导致 Mail Server 发生问题啰！其实不止 sendmail ，绝大部分的网路伺服器都有这个问题啊！ 所以，底下我们就来说一说与 Mail server 有关的安全性与其他相关的安全方面设定吧！

    小标题的图示 一些设定档所需要注意的‘权限’问题
    这部份我们以 Sendmail 官方网站的建议来说明喔！其实也适用于 postfix 的啦！ 其中，大部分是在于‘目录与档案权限’的设定要求上面：
    • 请确定 /etc/aliases 这个档案的权限，仅能由系统信任的帐号来修改，通常其权限为 644 ；
    • 请确定 Mail server 读取的资料库 (多半在 /etc/mail/ 或 /etc/postfix/ 底下的 *.db 档案)，例如 mailertable, access, virtusertable 等等，仅能由系统信任的使用者读取，其他一概不能读取，通常权限为 640 ；
    • 系统的伫列目录 (/var/spool/mqueue 或 /var/spool/postfix) 仅允许系统读取，通常权限为 700 ；
    • 请确定 ~/.forward 这个档案的权限也不能设定成为任何人均可查阅的权限，否则您的 e-mail 资料可能会被窃取～
    • 总之，一般用户能够不用 ~/.forward 与 aliases 的功能，就不要使用！
    不过整体的使用上还是需要身为网站管理员的您多费心啊！

    小标题的图示 简单的广告信抵挡机制： postgrey 的动作
    早期的广告信很多都是藉由僵尸电脑 (已经被当作跳板但管理员却没有发现或没有处理的主机) 来发送的， 这些僵尸电脑所发送的信件有个很明显的特色，就是‘他只会尝试传送该封电子邮件一次， 不论有无成功，该封信就算发出去了，故该信件将被移出伫列中。’ 不过，合法的 mail server 运作流程就如之前分析的一般，在邮件无法顺利寄出时该邮件会暂时放置到伫列中一段时间， 并一直尝试将信件寄出的动作，预设直到五天后若还是无法寄出才会将信件退回。

    根据这个合法与非法的邮件伺服器运作流程而发展出一套所谓的曙光 (postgrey) 软体， 您可以参考底下的几个说明来处理这个软体：
    • http://isg.ee.ethz.ch/tools/postgrey/
    • http://www.postfix.org/SMTPD_POLICY_README.html
    基本上 postgrey 主要的功能是在记录发信来源而已，若发信来源同一封信第一次寄来时， postgrey 预设会抵挡他，并且将来源位址记录起来，在约 5 分钟后，若该信件又传来一次时， 则该信件会被收下来。如此则可以杜绝非发邮件伺服器单次发送的问题喔！ ^_^！ 但对于你确定合法的主机则可以开放所谓的‘白名单 (whitelist) ’来优先通过而不抵挡。 所以说，他主要是这样进行的：(参考http://projects.puremagic.com/greylisting/whitepaper.html)
    1. 确认发信来源是否在白名单中，若是则予以通过；
    2. 确认收信者是否在白名单中，若是则予以通过；
    3. 确定这封信是否已经被记录起来呢？放行的依据是：
      • 若无此信件的记录，则将发信位址记录起来，并将信件退回；
      • 若有此信件的记录，但是记录的时间尚未超过指定的时间 (预设 5 分钟) ，则依旧退回信件；
      • 若有信件的记录，且记录时间已超过指定的时间，则予以通过；
    整个过程简单的来说就是这样而已。不过为了要快速的达成 postgrey 的‘记录’能力，所以资料库系统又是不可避免的东西。 且 postgrey 是由 perl 写成的，你可能也需要加入很多相依的 perl 模组才行。 总的来说，你需要的软体至少要有：
    • BerkeleyDB： 包括 db4, db4-utils, db4-devel 等套件：
    • Perl： 使用 yum install perl 即可；
    • Perl 模组： perl-Net-DNS 是 CentOS 本身有提供的，其他没有提供的可以到 http://rpmfind.net/去搜寻下载。
    除了可以使用 yum 来安装的套件之外，其他的套件鸟哥底下作了连结，你可以直接下载看看：
    • ftp://rpmfind.net/linux/dag/redhat/el4/en/i386/dag/RPMS/perl-BerkeleyDB-0.31-1.el4.rf.i386.rpm
    • ftp://rpmfind.net/linux/dag/redhat/el4/en/i386/dag/RPMS/perl-IO-Multiplex-1.08-3.el4.rf.noarch.rpm
    • ftp://rpmfind.net/linux/dag/redhat/el4/en/i386/dag/RPMS/perl-Net-Server-0.94-1.el4.rf.noarch.rpm
    • http://www.lfarkas.org/linux/packages/centos-4/i386/RPMS/postgrey-1.27-0.noarch.rpm
    将下载的这四个 RPM 给他使用 rpm -ivh *.rpm 就能够一口气的安装上去了。然后你就可以尝试启动 postgrey 看看啰：
    [root@linux ~]# /etc/init.d/postgrey start
[root@linux ~]# netstat -anlp | grep grey
unix  2 ...中间省略...    /var/spool/postfix/postgrey/socket
    由于 postfix 必需要连结到 postgrey 来进行一些名单的确认，然而两者连结的方式除了网路 IP 之外， 传统的 Unix socket 也是可以连结上的！由于传统 socket 不需要额外启动网路连线的埠口， 鸟哥认为这样也比较符合本机独自的操作，所以我们使用这一版 postgrey 的预设 unix socket 来连接啰。 接下来我们必需要修改 postfix 的 main.cf 了！请你这样做吧：
    [root@linux ~]# vi /etc/postfix/main.cf
# 如果你曾经设定过底下这个设定值，请找到他来修改！否则请自行增加底下的字样：
smtpd_recipient_restrictions =
     permit_mynetworks
     reject_unauth_destination
     check_policy_service unix:/var/spool/postfix/postgrey/socket
# 重点是最后面那一行！就是指定使用 unix socket 来连接到 postgrey 之意。
# 后续我们还有一些广告信的抵挡机制，特别建议您将这个 postgrey 的设定值写在最后，
# 因为他可以算是我们最后一个检验的机制喔！

[root@linux ~]# /etc/init.d/postfix restart
[root@linux ~]# chkconfig postgrey on
    然后你可以自己从外部主机寄一封信给自己这部邮件伺服器看看，记得去登录档内查一查 (/var/log/maillog)， 应该会出现类似的字眼：

    Nov 27 15:17:09 linux postfix/smtpd[16132]: NOQUEUE: reject: RCPT from sun.linux.tsai[192.168.1.101]: 450 <dmtsai@linux.vbird.tsai>: Recipient address rejected: Greylisted, see http://isg.ee.ethz.ch/tools/postgrey/help/linux.vbird.tsai.html; from=<dmtsai@sun.vbird.tsai> to=<dmtsai@linux.vbird.tsai> proto=ESMTP helo=<sun.vbird.tsai>

    这表示 postgrey 已经开始顺利运作了！并且来源主机的相关记录也已经记载在 /var/spool/postfix/postgrey/ 目录下啰！如此一来您的 postfix 将可以透过 postgrey 来挡掉一些莫名其妙的广告信啰！

    不过 postgrey 也是有缺点的，怎么说呢？因为 postgrey 预设会先将信件退回去， 所以你的信件就可能会发生延迟的问题，延迟的时间可能是数分钟到数小时， 端看你的 MTA 设定而定。如果你想要让‘某些信任的邮件主机不需要经过 postgrey 的抵挡机制’时， 就得要开放白名单啰！

    白名单的开启也很简单啊，直接编写 /etc/postfix/postgrey_whitelist_clients 这个档案即可。 假设你要让鸟哥的邮件主机可以自由的将信寄到你的 MTA 的话，那么你可以在这个档案内加入这一行：
    [root@linux ~]# vi /etc/postfix/postgrey_whitelist_clients
mail.vbird.idv.tw
sun.linux.tsai
# 将主机名称写进去吧！

[root@linux ~]# /etc/init.d/postgrey restart
    如果你还有更多信任的主机的话，将他写入这个档案当中！那他就可以略过 postgrey 的分析啰！ 更进阶的用法就得要靠您自己去发掘啰！ ^_^

    小标题的图示 关于黑名单的抵挡机制
    还记得前面讲到的 Open Relay 的问题吧？你的主机可千万不能成为 Open Relay 的状况，否则对你的网路与‘信用’影响很大喔！一般来说，只要是 Open Relay 的邮件主机都会被列入黑名单当中， 例如台湾地区的学术网路黑名单以及网际网路社会上提供的黑名单资料库：
    • http://140.111.1.22/tanet/spam.html
    • http://cbl.abuseat.org/
    既然黑名单资料库里面的 mail server 本身就是有问题的邮件主机，那么当黑名单里面的主机想要跟我的 mail server 连线时，我当然可以‘合理的怀疑该信件是有问题的！’您说是吧！ 所以来自黑名单或者是要送至黑名单的信件最好是不要接受啦！

    您当然可以自行前往该网站将有问题的主机列表给他加入自己的邮件主机抵挡机制当中， 不过就是不太人性化！既然网际网路社会已经提供了黑名单资料库了，我们就可以利用这个资料库来抵挡嘛！ 在决定是否进行 Relay 之前，先要求我们的 postfix 前往追踪黑名单的资料库， 若目标的 IP 或主机名称是黑名单的一员，则我们就将该信件拒绝啰！

    Postfix 设定黑名单检验真的很简单，你只要这样做即可：
    [root@linux ~]# vi /etc/postfix/main.cf
smtpd_recipient_restrictions =
     permit_mynetworks
     reject_unauth_destination
     reject_rbl_client cbl.abuseat.org
     reject_rbl_client bl.spamcop.net
     reject_rbl_client cblless.anti-spam.org.cn
     reject_rbl_client sbl-xbl.spamhaus.org
     check_policy_service unix:/var/spool/postfix/postgrey/socket

[root@linux ~]# /etc/init.d/postfix restart
    上表当中的特殊字体部分‘reject_rbl_client’是 postfix 内的一个设定项目， 后面可以接网际网路上提供的黑名单！您得要注意的是，这个黑名单资料库可能会持续的变动， 请您先以 dig 的方式检查每个资料库是否真的存在，如果存在才加以设定在您的主机上头啊！ (因为网际网路上头很多文献所提供的黑名单资料库似乎已经不再持续服务的样子！)

  • 检查你的邮件伺服器是否在黑名单当中？
    • 既然黑名单资料库所记录的是不受欢迎的来源与目标 MTA ，那么您的 MTA 当然最好不要在该资料库中嘛！ 同时这些资料库通常也都有提供检测的功能，所以你也可以用该功能来检查你的主机是否‘记录有案’呢？ 你可以这样处理的：
    1. 是否已在黑名单资料库中：
      确认的方法很简单，直接到‘http://cbl.abuseat.org/lookup.cgi ’输入您的主机名称或者是 IP ，就可以检查是否已经在黑名单当中；

    2. 是否具有 Open Relay：
      如果要测试你的主机有没有 Open Relay ，直接到‘http://140.111.1.22/tanet/spam.html ’这个网页， 在这个网页的最下方可以输入你的 IP 来检查，注意喔，不要使用别人的 email IP 呐！ 此时该主机会发出一封 mail 的测试信看看你的 mail server 会不会主动的代转， 然后将结果回报给您。要注意的是，回传的网页可能有编码的问题，如果出现乱码时，请调整为 big5 编码即可。

    3. 如何移除：
      如果被检查出，您的主机已经在黑名单当中，那么请立刻将 Open Relay 的功能关闭，改善你的 Mail Server 之后，你可能还要到各个主要的 Open Relay 网站进行移除的工作。如果是学术网路的话， 请与您单位的管理员联络。至于一般常见的黑名单资料库则通常会主动的帮您移除，只不过需要一些时间的测试就是了。
    总之您必须要确定你不在黑名单当中，且最好将黑名单的来源给拒绝掉！搞定！ ^_^

    小标题的图示 开放 SMTP 身份认证之 relay 机制
    在图一的流程当中，由 MUA 透过 MTA 来寄发信件时 (具有 Relay 的动作时) ，理论上 MTA 必需要开放用户端来源才行，这就是为啥我们必需要在 main.cf 里头设定 smtpd_recipient_restrictions 那个设定项目的原因了！不过人总有不方便的时候，举例来说， 如果你使用的是拨接制的 ADSL 所以每次取得的 IP 都非固定，那如何使用你的 MTA ？ 很麻烦，对吧！这个时候 SMTP 认证或许有点帮助。

    关于 SMTP 认证的使用前面已经稍微提过了，重点在于 MUA 想要使用 MTA 来进行 relay 的时候，MTA 会要求 MUA 来输入认证用的帐号与密码，以取得使用的权限就是了。 咱们的 CentOS 已经有提供内建的认证模组，那就是 Cyrus SASL 这个套件的帮忙啦！

    Cyrus SASL (http://cyrusimap.web.cmu.edu/) 是 Cyrus Simple Authentication and Security Layer 的缩写，他是一个辅助的套件。 在 SMTP 认证方面， Cyrus 主要提供了 saslauthd 这个服务来进行帐号密码的比对动作！ 也就是说：当有任何人想要进行邮件转递功能时， Postfix 会联络 saslauthd 请其代为检查帐号密码，若比对通过则允许用户端开始转寄信件。

    好了，如果你想要使用最简单的方式来进行 SMTP 认证功能的话，在 CentOS 当中你应该要这样做：
    1. 安装 cyrus-sasl, cyrus-sasl-devel, cyrus-sasl-plain, cyrus-sasl-md5 等套件；
    2. 启动 saslauthd 这个服务；
    3. 设定 main.cf 让 postfix 可以与 saslauthd 联系；
    4. 用户端必需要在寄信时设定‘邮件主机认证’功能。
    如此一来用户端才能够启动 SMTP AUTH 喔！关于软体安装方面，请使用 yum 直接安装吧！ 不再多啰唆！底下我们由启动 saslauthd 这个服务开始吧！

  • 启动 saslauthd 服务
    • saslauthd 是 Cyrus-SASL 提供的一个帐号密码比对管理机制，虽然他只能利用简单的 PLAIN 机制进行密码验证， 不过在设定上较为简单。 saslauthd 可以连结很多帐号密码管理机制，包括 LDAP, PAM, SASLDB2 以及 SQL 资料库系统等等。如果我们想要直接使用 Linux 系统上面的使用者资讯， 也就是 /etc/passwd, /etc/shadow 所记载的帐号密码相关资讯时，可以使用‘ shadow ’这个机制， 当然也能使用‘ pam ’啦！更多的 saslauthd 连线至主机的机制请‘ man saslauthd ’来查阅吧。

    saslauthd 的启动真是好简单，首先你必需要选择密码管理机制，这个可以使用底下的方式处理：
    1. 先了解你的 saslauthd 有支援哪些密码管理机制：
[root@linux ~]# saslauthd -v
saslauthd 2.1.19
authentication mechanisms: getpwent kerberos5 pam rimap shadow ldap
# 上列的特殊字体部分就是有支援的！我们要用 Linux 本机的使用者资讯，
# 所以用 shadow  即可。

2. 设定实际使用的机制
[root@linux ~]# vi /etc/sysconfig/saslauthd
MECH=shadow
# 这也是预设值，有的朋友喜欢 pam 机制，也可以啦！

3. 那就启动吧！
[root@linux ~]# /etc/init.d/saslauthd start
[root@linux ~]# chkconfig saslauthd on
    之后我们必需要告知 Cyrus 这个咚咚使用的服务为 saslauthd 才行，设定的方法很简单：
    [root@linux ~]# vi /usr/lib/sasl2/smtpd.conf
log_level: 3                <==登录档资讯等级的设定，设定 3 即可
pwcheck_method: saslauthd   <==就是选择什么服务来负责密码的比对啊
mech_list: PLAIN LOGIN      <==那么支援的机制有哪些之意！
    因为 saslauthd 预设就仅支援明码传输而已，我们可以使用 mech_list 列出特定支援的机制。 而且 saslauthd 是个很简单的帐号密码管理服务，你几乎不需要进行什么额外的设定， 直接启动他就生效了！真是好方便！ ^_^

  • main.cf 的设定项目：
    • 那我们的 postfix 该如何处理呢？其实设定真的很简单，只要这样做就好了：
    [root@linux ~]# vi /etc/postfix/main.cf
# 在本档案最后面增加这些设定资料：
smtpd_sasl_auth_enable = yes
smtpd_sasl_security_options = noanonymous
broken_sasl_auth_clients = yes
# 然后找到跟 relay 有关的设定项目，增加一段允许 SMTP 认证的字样：
smtpd_recipient_restrictions =
     permit_mynetworks
     permit_sasl_authenticated
     reject_unauth_destination
     reject_rbl_client cbl.abuseat.org
     reject_rbl_client bl.spamcop.net
     reject_rbl_client cblless.anti-spam.org.cn
     reject_rbl_client sbl-xbl.spamhaus.org
     check_policy_service unix:/var/spool/postfix/postgrey/socket

[root@linux ~]# /etc/init.d/postfix restart
    各个项目的意义是这样的：
    • smtpd_sasl_auth_enable
      就是设定是否要启动 sasl 认证的意思，如果设定启动后 postfix 会主动去载入 cyrus sasl 的函式库， 而该函式库会依据 /usr/lib/sasl2/smtpd.conf 的设定来连结到正确的管理帐号与密码的服务， 那就是咱们的 saslauthd 啰！

    • smtpd_sasl_security_options
      这个项目指的是‘要取消哪些登入的方式’的意思。我们可以取消匿名登入的可能性， 所以设定为 noanonymous 即可。由于 saslauthd 使用的是 plaintext ，所以你可不能设定 noplaintext 喔！ 留意留意！

    • broken_sasl_auth_clients
      这个是针对早期非正规 MUA 的设定项目，因为早期软体开发商在开发 MUA 时没有参考通讯协定标准， 所以造成在 SMTP 认证时可能会发生的一些困扰。这些有问题的 MUA 例如 MS 的 outlook express 第四版就是这样！ 后来的版本应该没有这个问题。所以这个设定值你也可以不要设定！

    • smtpd_recipient_restrictions
      最重要的就是这里啦！我们的 sasl 认证可以放在第二行，在区域网路这个可信任区域的后面加以认证。 上表的设定意义是：区域网路内的 MUA 不需要认证也能够进行 relay ，而非区网内的其他来源才需要进行 SMTP 认证之意。
    设定完毕也重新启动 postfix 之后，我们先来测试看看是否真的提供认证了？
    [root@linux ~]# telnet localhost 25
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
220 vbird.vbird.idv.tw ESMTP Postfix
ehlo localhost
250-linux.vbird.tsai
250-PIPELINING
250-SIZE 10240000
250-VRFY
250-ETRN
250-AUTH LOGIN PLAIN     <==你必需要看到底下这两行才算数啊！
250-AUTH=LOGIN PLAIN
250 8BITMIME
quit
221 Bye

  • 用户端的设定
    • 用户端也需要设定向 MTA 主机发送 SMTP 认证的功能才行！作法很简单啦，我们依旧以 Thunderbird 来作为介绍，请打开 thunderbird ，选择‘工具’-->‘帐号设定’后会出现如下画面：

    用户端认证机制所需要启动的项目
    图十三、用户端认证机制所需要启动的项目

    记得在上图 2 所指的地方，将使用者帐号及密码项目勾选，并且不使用安全连线 (因为 saslauthd 仅支援明码认证而已) ，这样就 OK 啦！然后你尝试寄出一封信看看，瞧瞧是否有顺利的通过认证啊？ 记得此用户端不要在区域网路内，否则将不会经过认证的阶段，因为我们的设定以信任网域为优先嘛！
    如果一切都顺利的话，那么当用户端以 SMTP 来验证时，你的登录档应该会出现类似底下的讯息才是：
    [root@linux ~]# tail -n 100 /var/log/maillog | grep PLAIN
Nov 28 15:27:21 linux postfix/smtpd[23060]: EFCC9A26CB: client=unknown
[192.168.100.25], sasl_method=PLAIN, sasl_username=dmtsai

    小标题的图示 基础的邮件过滤机制
    在整封信的传送流程当中，用户端若通过主机的重重限制后，最终应该可以到达邮件伫列当中。 而由伫列当中要送出去或者是直接送到 mailbox 就得要透过 MDA 的处理。MDA 可以加挂很多机制呢！ 尤其是他可以过滤某些特殊字眼的广告信件或病毒信件呢！ MDA 可以透过分析整封信件的内容 (包括标头以及内文) 来撷取有问题的关键字，然后决定这封信的‘命运’说！

    咱们的 postfix 已经有内建可以分析标头或者是内文的过滤机制了，那就是 /etc/postfix/ 目录下的 header_checks 以及 body_checks 这两个档案啊！在预设的情况下这两个档案不会被 postfix 使用， 你必需要用底下的设定来启用他：
    [root@linux ~]# vi /etc/postfix/main.cf
header_checks = regexp:/etc/postfix/header_checks
body_checks = regexp:/etc/postfix/body_checks
# 那个 regexp 代表的是‘使用正规表示法’的意思啦！

[root@linux ~]# touch /etc/postfix/header_checks
[root@linux ~]# touch /etc/postfix/body_checks
[root@linux ~]# /etc/init.d/postfix restart
    接下来你必需要自行处理 header_checks 以及 body_checks 的规则设定，在设定前请您确认‘ 你对于正规表示法是熟悉的 ’才行！因为很多资讯都必需要透过正规表示法来处理啦！然后开始设定的依据是：
    • 只要是 # 代表该行为注解，系统或直接略过；
    • 在预设的规则当中，大小写是视为相同的；
    • 规则的设定方法为：
        /规则/   动作   显示在登录档里面的讯息
      请注意，要使用两个斜线‘ / ’将规则包起来喔！举个例子来说明：例如我想要 (1)抵挡掉标题为 A funny game 的信件，(2)并且在登录档里面显示 drop header deny，则可以在 header_chekcs 档案中可以这样写：
        /^Subject:.*A funny game/   DISCARD  drop header deny
    • 关于动作有底下几个动作：
      • REJECT ：将该封信件退回给原发信者；
      • WARN ：将信件收下来，但是将该封信的基本资料记录在登录档内；
      • DISCARD：将该封信件丢弃，并不给予原发信者回应！
    鸟哥自己有作一些规则的比对，只不过.....效能不好！如果您有兴趣的话，可以自行下载来看看， 不过，使用的后果请自行评估！因为每个人的环境都不一样嘛！
    • header: http://linux.vbird.org0380mail/header_checks
    • body: http://linux.vbird.org0380mail/body_checks
    记得，如果你自行修改过这两个档案后，务必要检查一下语法才行！
    [root@linux ~]# postmap -q - regexp:/etc/postfix/body_checks \
>  < /etc/postfix/body_checks
    如果没有出现任何错误，那就表示您的设定值应该没有问题啦！

  • PROCMAIL
    • 除了这两个设定之外，还有没有基础过滤分面的 MDA 机制呢？有的！那就是 procmail 啰～ Procmail 基本上就与上头提到的 body_checks 相仿，同样是用来分析邮件之用的， 所以你也需要设定规则啊！首先你得要安装 procmail ，咱们的 CentOS 已经有内建的套件了， 请使用 yum install procmail 自行安装好他。

    那么 procmail 的过滤规则在哪里呢？预设就是 /etc/procmailrc 啰！这个档案的设定方式是这样的：
    1. 一组规则设定至少共含有三行，如下所示：
:0b                         <==设定过滤机制所要检查的信件部分
* ^Subject:.*A funny game   <==就是检查的规则部分
/dev/null                   <==如果符合上述规定，则进行的动作

参数说明：
a. 关于检查邮件的部分(第一行)，flags 包含有：
    H : Header 的检查
    B : Body 的检查
    h : 提供 Header 的资料，进入 pipe 、 file 及 mail 等的检查
    b : 提供 Body 的资料进入 pipe, file 及 mail 等的检查！
b. 关于检查内容的部分：
    ! : 这是反向选择的意思
    < : 检查 mail 的总长度是否小于设定值 ( bytes )
    > : 与 < 相反的选择啰！
c. 关于动作的部分
    | : 开始启用后续的 shell 程式工作！
d. 其他的环境变数部分：
    PATH　　　　搜寻执行档的路径
    SENDMAIL　　那个 /usr/sbin/sendmail 啰！
    LOGFILE　　 登录档！通常设定在 /var/log/procmail.log
e. 与 Regular express 相关的部分：
    ^ : 开始(同一行最左边)字元
    $ : 本行的结束字元(最右边)的比对
    . : 除了新增一行之外的任何字元！
    \ : 跳脱字元
更详细的内容请务必参考：
man procmailrc
man procmailex
    网路上已经有很多前辈提供了他们自行分析的规则，比如说卧龙大师：
      ftp://ftp.tnc.edu.tw/pub/Sysop/MAIL/procmailrc
    您可以经上述的网页资料捉到你的 /etc/procmailrc 当中，然后在 main.cf 里头增加这一句：
    [root@linux ~]# vi /etc/postfix/main.cf
mailbox_command = /usr/bin/procmail

[root@linux ~]# /etc/init.d/postfix restart

    透过这种基础的邮件分析可以捉取一些有问题的邮件，不过对于目前垃圾邮件的抵挡方面还是很有限！ 此外，由于这些分析机制都直接读取信件来处理与分析，这些机制通常都很耗系统资源！ 如果你的信件越大流量越大，那么你的系统花费在‘分析邮件’上面的时间会花去很多资源， 所以你的硬体得要很好，否则当有大型邮件进来时，邮件主机会跑得喘嘘嘘！ 所以目前要不要启动这些过滤机制.....见仁见智啰！

    小标题的图示 非固定 IP 也可以有春天： relayhost
    我们上面提到，如果你要架设一部合法的 MTA 最好还是得要申请固定的 IP 以及正确对应的反解比较恰当。 但如果你一定要用浮动 IP 来架设你的 MTA 的话，也不是不可以啦，只不过你就得要透过上层 ISP 所提供的 relay 权限啰！这是怎么回事啊？让我们来看看一个实际的案例：

    利用 ISP 的 MTA 进行邮件转递
    图十四、利用 ISP 的 MTA 进行邮件转递

    理论上，由于我们是向 ISP 申请 IP 的，所以我们的 IP 对于 ISP 的 MTA 来说，应该都符合 relay 的要件。 那如果我利用这个 IP 来架设一个 mail server ，并且让这个 mail server 的主机名称对应为 DDNS 的情况，则我的 IP 与主机名称对应得宜，所以当然可以架设各种网站伺服器。如果没有设定以 ISP 的 MTA 作为 relay 的情况下，目标 MTA 会反解析我们的 IP ，若得到此 IP 为非合法的主机名称时， 该信件原则上是会被退件的。

    那如果我以 ISP 的 MTA 来作为 relay 主机时，因为我们所在的 IP 本来就能够使用 ISP MTA 的 relay 功能， 所以图十四的第一步是没问题的。然后当 ISP 的 MTA 在进行 Relay 而将信件寄出去时， 目标 MTA 所看到的来源端是‘ISP 的 IP’而不是我们原本的发信源！ 如此一来当然我们的 MTA 就能够架设起来啰！

    不过想要以此架构来架设你的 MTA 仍有许多需要注意的地方：
    • 你还是得要有一个合法的主机名称，若要省钱，可以使用 DDNS 来处理；
    • 你上层的 ISP 所提供的 MTA 必需要有提供你所在 IP 的 relay 权限；
    • 你不能使用自订的内部 DNS 架构了，因为所有 relay 的信都会被送至 ISP 的 MTA
    尤其是最后一点，因为所有外送的信件全部都会被送到 ISP 处，所以像我们之前自己玩的 vbird.tsai 这种非合法的领域资料就没用了！为什么呢？你想想看，如果你要将信件送给 mail.vbird.tsai ， 但由于上述的功能，所以这封信会被传到 ISP 的 MTA 来处理，但 ISP 的 MTA 会不会认识你的 vbird.tsai ？这样说，可以理解了吧？

    说是挺难的，做起来却很简单，只要在 main.cf 里面加设一段资料即可。 假设你的环境是台湾地区的 hinet 所提供的用户，而 hinet 提供的邮件主机为 ms1.hinet.net ， 则你可以直接这样设定：
    [root@linux ~]# vi /etc/postfix/main.cf
# 加入底下这一行就对啦！注意那个中括号！
relayhost = [ms1.hinet.net]

[root@linux ~]# /etc/init.d/postfix restart
    之后你只要尝试寄一封信出去看看，就会了解这封信是如何寄送的了。看一下登录档的内容会像这样：
    [root@linux ~]# tail -n 20 /var/log/maillog
Nov 28 18:42:30 linux postfix/smtp[23673]: 515E8A26CE: to=<someone@合法的主机>,
relay=ms1.hinet.net[168.95.4.10], delay=1, status=sent (250 SAA09090 Message
accepted for delivery)
    是吧！经由上层 ISP 来转寄啦！如此一来，你的 MTA 感觉上就似乎是部合法的 MTA 啰！ 不过，可别利用这个权限来滥发广告信啊！因为您所透过的那个 ISP 邮件主机可是有记录你的 IP 来源， 如果你乱来的话，后果可是不堪设想喔！切记切记！

    小标题的图示 邮件扫瞄器： amavisd-new+f-port+spamassanssin
    事实上，到目前为止之前的设定应该可以满足一般 50 人以下的小企业环境了， 甚至再多一点人也没有问题的。不过如果人数多了，各种奇怪的信件也会跟着多起来， 这是因为总是会有人不小心将他的 email address 放在网际网路上，如果被邮件位址搜寻机器人捉到的话， 你的 email 将会出现在广告信发送商的名单中....

    为了避免这个问题，很多朋友是将他的信箱分为两个，一个直接放在 Internet 上，另一个则作为自己日常业务之用。另外有的朋友则使用类似底下所提供的邮件位址表示方式：
      dmtsai{at}linux{dot}vbird{dot}tsai
    这种格式对于网路机器人 (就是一种可以自动上网搜寻关键字的软体程式啰！) 的搜寻会造成困扰， 因为那些机器人程式用以判断是否为邮件位址是依据‘ @ ’来判别的啊！ 所以说，不要泄漏你个人的 email 是很重要的一件事啊！
    Tips:
    你可以自己测试看看，如果申请了一个免费信箱，但不要将他公布，那个信箱肯定不会收到任何广告信。 但你一旦用那个信箱来申请一些个人资料而公布在 Internet 上面时，呼呼！不超过一个星期， 该信箱肯定会收到很多广告信！使用上要特别留意喔！     		鸟哥的图示
    既然广告信在短期内不可能有个长足的解决方案，那至少我们可以直接在 mail server 端就将广告信与病毒信给他捉出来吧？如此就可以避免掉使用者必需要自己分析广告信与垃圾信等所花费的时间了。 底下提供几个好东西来帮忙处理主机端的信件资料喔：
    • amavisd-new：
      官方网站：http://www.ijs.si/software/amavisd/
      说明：这个软体主要是介于 MTA 与邮件分析软体之间的一个介面，他可以将位于伫列的邮件捉出来给分析软体分析， 通常是需要安装的，尤其他可以支援 postfix 呐！

    • f-port：
      官方网站：http://www.f-prot.com/
      说明：是一种防毒软体，具有自动更新病毒码的能力；

    • SpamAssassin：
      官方网站：http://spamassassin.apache.org/index.html
      说明：具有自动学习的广告信分析软体，不过如果自动学习的规定太严格，有时会发生误判。
    接下来就让我们的 postfix 支援这三个东西吧！不过你得要注意的是， f-port 与 SapmAssisin 是独立运作的软体， 那 postfix 为了要使用这两个软体的分析功能，就得要透过 amavisd-new 这个介面工具来传送信件资讯啰！ 详细的作法请参考上头提供的官方网站，或者是参考讨论区的几篇文章也不错：
    • TWU2 兄提供的好文章：http://phorum.study-area.org/viewtopic.htm?t=38649
    • kevin1005 提供的好文章：http://phorum.vbird.org/viewtopic.htm?t=25760
    • johntino 提供的好文章：http://phorum.vbird.org/viewtopic.htm?t=15862
    当然网路上还有很多好文章，大家可以多多搜寻一番。

  • amavisd-new 的安装与设定：
    • 虽然你可以自行使用 tarball 来安装，不过我们也可以在 http://rpmfind.net/ 找到给 RHEL 4 使用的版本。既然 CentOS 与 RHEL 使用的套件均相同， 没有道理我们不能安装！是吧！^_^。所以底下的套件请先由 http://rpmfind.net/ 网站捉下来吧！然后再开始安装去。 要注意的是，由于 amavisd-new 用 perl 写成的，他需要很多 perl 的模组，且由于要分析信件内容， 所以也需要很多解压缩软体来解析信件内的压缩档，因此才会需要这么多的软体安装～ @_@：

    与 Perl 模组有关的套件：
  • ftp://rpmfind.net/linux/dag/redhat/el4/en/i386/dag/RPMS/perl-Archive-Tar-1.30-1.el4.rf.noarch.rpm
  • ftp://rpmfind.net/linux/dag/redhat/el4/en/i386/dag/RPMS/perl-Archive-Zip-1.16-1.2.el4.rf.noarch.rpm
  • ftp://rpmfind.net/linux/dag/redhat/el4/en/i386/dag/RPMS/perl-BerkeleyDB-0.31-1.el4.rf.i386.rpm
  • ftp://rpmfind.net/linux/dag/redhat/el4/en/i386/dag/RPMS/perl-Compress-Zlib-1.42-1.el4.rf.i386.rpm
  • ftp://rpmfind.net/linux/dag/redhat/el4/en/i386/dag/RPMS/perl-Convert-BinHex-1.119-2.2.el4.rf.noarch.rpm
  • ftp://rpmfind.net/linux/dag/redhat/el4/en/i386/dag/RPMS/perl-Convert-UUlib-1.051-1.2.el4.rf.i386.rpm
  • ftp://rpmfind.net/linux/dag/redhat/el4/en/i386/dag/RPMS/perl-Convert-TNEF-0.17-3.2.el4.rf.noarch.rpm
  • ftp://rpmfind.net/linux/dag/redhat/el4/en/i386/dag/RPMS/perl-IO-Multiplex-1.08-3.el4.rf.noarch.rpm
  • ftp://rpmfind.net/linux/dag/redhat/el4/en/i386/dag/RPMS/perl-IO-stringy-2.110-1.2.el4.rf.noarch.rpm
  • ftp://rpmfind.net/linux/dag/redhat/el4/en/i386/dag/RPMS/perl-MIME-tools-5.420-1.el4.rf.noarch.rpm
  • ftp://rpmfind.net/linux/dag/redhat/el4/en/i386/dag/RPMS/perl-Net-Server-0.94-1.el4.rf.noarch.rpm
  • ftp://rpmfind.net/linux/dag/redhat/el4/en/i386/dag/RPMS/perl-Unix-Syslog-0.100-1.2.el4.rf.i386.rpm
  • ftp://rpmfind.net/linux/dag/redhat/el4/en/i386/dag/RPMS/amavisd-new-2.4.3-1.el4.rf.i386.rpm

    与压缩及解压缩软体有关的套件：
  • ftp://rpmfind.net/linux/dag/redhat/el4/en/i386/dag/RPMS/arc-5.21j-0.2.el4.rf.i386.rpm
  • ftp://rpmfind.net/linux/dag/redhat/el4/en/i386/dag/RPMS/cabextract-1.2-1.el4.rf.i386.rpm
  • ftp://rpmfind.net/linux/dag/redhat/el4/en/i386/dag/RPMS/freeze-2.5-2.2.el4.rf.i386.rpm
  • ftp://rpmfind.net/linux/dag/redhat/el4/en/i386/dag/RPMS/lzo-1.08-4.2.el4.rf.i386.rpm
  • ftp://rpmfind.net/linux/dag/redhat/el4/en/i386/dag/RPMS/lzop-1.01-1.2.el4.rf.i386.rpm
  • ftp://rpmfind.net/linux/dag/redhat/el4/en/i386/dag/RPMS/nomarch-1.4-1.el4.rf.i386.rpm
  • ftp://rpmfind.net/linux/dag/redhat/el4/en/i386/dag/RPMS/ripole-0.2.0-1.2.el4.rf.i386.rpm
  • ftp://rpmfind.net/linux/dag/redhat/el4/en/i386/dag/RPMS/unarj-2.63-0.a.2.el4.rf.i386.rpm
  • ftp://rpmfind.net/linux/dag/redhat/el4/en/i386/dag/RPMS/unrar-3.6.8-1.el4.rf.i386.rpm
  • ftp://rpmfind.net/linux/dag/redhat/el4/en/i386/dag/RPMS/zoo-2.10-2.2.el4.rf.i386.rpm
    您可能先要以 yum 的方式来安装 ncompress, perl-Net-DNS, perl-TimeDate, perl-MailTools, perl-Digest-SHA1, perl-Digest-HMAC, perl-Time-HiRes, spamassassin 这几套软体，然后将上列的软体全部放在同一个目录下，以 rpm -Uvh *.rpm 来安装上述的所有套件！但安装时如果出现如下画面：
    warning: amavisd-new-2.4.3-1.el4.rf.i386.rpm: V3 DSA signature: NOKEY, key ID 6b
Preparing...                ########################################### [100%]
        package perl-BerkeleyDB-0.31-1.el4.rf is already installed
    ....
    这表示某些套件已经被安装了！你不应该还安装他！那么请自行将这些已安装的套件档案移出目前目录， 再执行一次 rpm -Uvh *.rpm 就能够安装啰！如果还是出现某些相依属性的问题，要嘛就以 yum 来安装， 要嘛就以 http://rpmfind.net 网站搜寻适当的 RPM 档案来安装， 安装完毕后就准备来设定一下啰！

    要开始设定 amavisd-new 之前，请务必先查阅一下 /usr/share/doc/amavisd-new-2.4.3/README.postfix 这个档案的内容， 里面有很详尽的设定说明喔！然后这个 amavisd-new 的设定档只有 /etc/amavisd.conf 而已， 预设的情况下该档案内容含有很多的病毒搜寻引擎，不过我们仅有 f-port 这个扫毒软体而已， 所以里面需要进行很多修改喔！基本内容的修改如下：
    [root@linux ~]# vi /etc/amavisd.conf
# 首先是关于系统设定的部分，包括主机与领域名称等的设定：
$mydomain = 'vbird.tsai';          <==约在第 20 行，填写你的领域名；
$MYHOME = '/var/amavis';           <==约在第 22 行，这是 amavis 的预设家目录之意
$inet_socket_port = 10024;         <==约在第 51 行，预设启动的 port 啦！
$myhostname = 'linux.vbird.tsai';  <==约在第113 行，改成你的主机名称
$notify_method  = 'smtp:[127.0.0.1]:10025';  <==约在第116 行，设定连接的埠口
$forward_method = 'smtp:[127.0.0.1]:10025';  <==约在第117 行，同上

# 2. 底下这几行约在第 118 行之后，用来作为找到病毒或广告信后的动作！
# 如果你害怕不小心将重要档案删除了，建议你先改成 D_BOUNCE 预先处理
$final_virus_destiny      = D_BOUNCE;  <==找到病毒时的动作
$final_banned_destiny     = D_BOUNCE;  <==找到禁止项目的动作
$final_spam_destiny       = D_PASS;    <==找到广告信的动作
$final_bad_header_destiny = D_PASS;    <==找到不良信件标头的动作
# 可以处理的动作主要有：
#   D_PASS    无论邮件的内容是否有问题，该邮件都会传给收件者
#   D_DISCARD 邮件被丢弃，而且不会告知收件者与寄件者；
#   D_BOUNCE  邮件不会传给收件者，但无法传递的讯息会告知寄件者；
#   D_REJECT  邮件不会传给收件者，但寄件者会收到拒绝的讯息。
# 鸟哥在这里由于担心误删一些资料，所以除了病毒与禁止项目会回传错误给寄件者外，
# 其他两个先预设可以通过。等到未来邮件伺服器使用者觉得可以接受后，
# 某些部分 (如病毒) 就可以改为 D_DISCARD 来直接丢弃了！

# 3. 再来则是决定病毒扫瞄的引擎，底下分别是主要与次要扫毒程式
@av_scanners = (                <==大约在 309 行，里面的项目全部注解；
....中间省略....
);
# 因为所有的病毒扫瞄引擎都没有安装嘛！

@av_scanners_backup = (         <==大约在 626 行，只要剩下底下这些
  ['FRISK F-Prot Antivirus', ['f-prot','f-prot.sh'],
    '-dumb -archive -packed {}', [0,8], [3,6],
    qr/Infection: (.+)|\s+contains\s+(.+)$/ ],
....中间省略....
);
    amavisd-new 大致上就解决到这里，现在还无法启动他，因为我们要先安装 f-port 才行呐！ 赶紧下一动作吧！

  • 安装与设定 f-port ：
    • f-port 是一个扫毒软体，他的版本非常的多，其中只有一个是免费的个人版本， 请到底下的连结去下载，不要下载错档案了喔！
      http://www.f-prot.com/download/trial_forms/linux-ws-rpm.html
    建议你直接下载 RPM 档案，然后直接安装他就好了！安装后 f-port 会立即主动进行线上更新， 所以请你在安装的时候确定你的网路是正常的。而所有 f-port 的资料都会被放置到 /usr/local/f-prot/ 目录下。 该目录下的 README 以及相关连结可以瞧一瞧。安装完毕后检查看看能否工作：
    [root@linux ~]# f-prot -verno
F-PROT ANTIVIRUS
Program version: 4.6.6
Engine version: 3.16.14

VIRUS SIGNATURE FILES
SIGN.DEF created 29 November 2006
SIGN2.DEF created 29 November 2006
MACRO.DEF created 27 November 2006
# 若出现如上的版本宣告，这表示 f-prot (注意档名) 可以顺利运作。

[root@linux ~]# f-prot /etc/crontab
# 如果有出现扫瞄的字样，就表示这个软体可以开始进行扫瞄的工作啦！
    其实这也就是说， f-port 这套软体的扫瞄程式‘ f-prot ’可以在 Linux 上面扫瞄各种档案的意思！ 不过，我们的重点是利用他来进行邮件扫瞄就是了。至于线上更新病毒码部分，你可以手动线上更新， 也可以进入工作排程来自动更新喔：
    1. 手动即时线上更新方式：
[root@linux ~]# /usr/local/f-prot/tools/check-updates.pl

2. 自动更新排程：
[root@linux ~]# vi /etc/crontab
27 4,16 * * * root /usr/local/f-prot/tools/check-updates.pl -cron -quiet
    如此一来我们的 f-port 每天可以进行两次线上更新的动作呢！很不错吧！

  • 测试 amavisd-new 与病毒扫瞄程式的搭配：
    • 完成上述的设定后，我们可以先来测试看看 amavisd-new 与 f-port 扫毒程式的搭配情况。 你可以直接这样做：
    [root@linux ~]# amavisd debug
....前面省略....
# 底下在说明此软体所监听的介面与 port 还有执行者的 UID/GID 等
Nov 30 14:51:53 linux amavisd[3457]: Net::Server: Binding to TCP port 10024 on
host 127.0.0.1
Nov 30 14:51:53 linux amavisd[3457]: Net::Server: Setting gid to "102 102"
Nov 30 14:51:53 linux amavisd[3457]: Net::Server: Setting uid to "101"
Nov 30 14:51:53 linux amavisd[3457]: Net::Server: Setting up serialization via
flock

# 底下在说明各个模组是否有被顺利的载入
Nov 30 14:51:54 linux amavisd[3457]: Module Amavis::Conf   2.072
Nov 30 14:51:54 linux amavisd[3457]: Module Archive::Tar   1.30
Nov 30 14:51:54 linux amavisd[3457]: Module Archive::Zip   1.16
....中间省略....

# 底下则是在说明载入哪些资料
Nov 30 14:51:54 linux amavisd[3457]: Amavis::DB code      loaded
Nov 30 14:51:54 linux amavisd[3457]: Amavis::Cache code   loaded
....中间省略....
Nov 30 14:51:54 linux amavisd[3457]: ANTI-VIRUS code      loaded
Nov 30 14:51:54 linux amavisd[3457]: ANTI-SPAM code       loaded
Nov 30 14:51:54 linux amavisd[3457]: ANTI-SPAM-SA code    loaded
Nov 30 14:51:54 linux amavisd[3457]: Unpackers code       loaded

# 这里说明的是一些档案解压缩的功能啰！
Nov 30 14:51:54 linux amavisd[3457]: Found $file   at /usr/bin/file
Nov 30 14:51:54 linux amavisd[3457]: No $dspam,    not using it
Nov 30 14:51:54 linux amavisd[3457]: Internal decoder for .mail
Nov 30 14:51:54 linux amavisd[3457]: Internal decoder for .asc
....中间省略....
Nov 30 14:51:54 linux amavisd[3457]: Found secondary av scanner FRISK
F-Prot Antivirus at /usr/local/bin/f-prot <==这行重要！说明有找到 f-port
Nov 30 14:51:54 linux amavisd[3457]: SpamControl: initializing Mail::SpamAssassin
Nov 30 14:51:56 linux amavisd[3457]: SpamControl: init_pre_fork done
....后面省略....
# 最后按下 [ctrl]-c 来结束这个 debug 的画面喔！
    看起来应该是没有问题啦！然后赶紧给他启动这个服务吧！
    [root@linux ~]# /etc/init.d/amavisd start

# 测试一下 amavisd 启动的 port 10024 是否顺利运作中？
[root@linux ~]# telnet 127.0.0.1 10024
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
220 [127.0.0.1] ESMTP amavisd-new service ready
ehlo localhost
250-[127.0.0.1]
250-VRFY
250-PIPELINING
250-SIZE
250-ENHANCEDSTATUSCODES
250-8BITMIME
250-DSN
250 XFORWARD NAME ADDR PROTO HELO
quit
221 2.0.0 [127.0.0.1] amavisd-new closing transmission channel
Connection closed by foreign host.
    如果一切都顺利的话，你可以将这个服务给他写入开机自动执行中！‘ chkconfig amavisd on ’ 这样就好啦！准备设定一下让 postfix 来支援 amavisd-new 的伫列分析工作吧！

  • 设定 Postfix 使支援 amavisd-new 的分析工作：
    • 这个设定项目需要的资讯比较多，有两个档案要修改，先改 master.cf 吧！
    [root@linux ~]# vi /etc/postfix/master.cf
# 这几行专门为了病毒、广告信作的连结！
# ====================================================================
# service type  private unpriv  chroot  wakeup  maxproc command + args
#               (yes)   (yes)   (yes)   (never) (100)
# ====================================================================
smtp-amavis unix -      -       n        -       2    smtp
    -o smtp_data_done_timeout=1200
    -o smtp_send_xforward_command=yes
    -o disable_dns_lookups=yes
    -o max_use=20

127.0.0.1:10025 inet n  -       n        -       -    smtpd
    -o content_filter=
    -o smtpd_restriction_classes=
    -o smtpd_delay_reject=no
    -o smtpd_client_restrictions=permit_mynetworks,reject
    -o smtpd_helo_restrictions=
    -o smtpd_sender_restrictions=
    -o smtpd_recipient_restrictions=permit_mynetworks,reject
    -o smtpd_data_restrictions=reject_unauth_pipelining
    -o smtpd_end_of_data_restrictions=
    -o mynetworks=127.0.0.0/8
    -o smtpd_error_sleep_time=0
    -o smtpd_soft_error_limit=1001
    -o smtpd_hard_error_limit=1000
    -o smtpd_client_connection_count_limit=0
    -o smtpd_client_connection_rate_limit=0
    -o smtpd_milters=
    -o local_header_rewrite_clients=
    -o local_recipient_maps=
    -o relay_recipient_maps=
    这几行给他设定好，然后再来处理 main.cf 这个档案啰！
    [root@linux ~]# vi /etc/postfix/main.cf
content_filter = smtp-amavis:[127.0.0.1]:10024

[root@linux ~]# /etc/init.d/postfix restart
    嘿嘿！然后开始就能够帮你分析病毒信啦！就是这么简单呐！

  • 广告信的抵挡：
    • 我们有使用 spamassassin 这个自动学习抵挡广告信的机制，这个玩意儿主要是透过分析信件内容， 只要信件内容的某一部份符合 spamassassin (简称 SA) 的规范，则该信件可给予一个分数。 将该信件的所有分数总和起来，若分数高于我们所规定的预设分数，则该信件可以被视为广告信。 这个分数如果设定太低，则很多合法的信件都会不小心被视为广告信，如果设定太高，可能又会捉不到广告信。 真是两难。这个分数的设定值预设是在：
    [root@linux ~]# vi /etc/amavisd.conf
$sa_tag_level_deflt  = 5.0;    <==大约在第 61 行，将 2 改成 5 吧！

[root@linux ~]# vi /etc/mail/spamassassin/local.cf
required_hits 5                <==就是他！就是这个分数啦！
report_safe 0
rewrite_header Subject [SPAM]  <==如果是广告信，标头会被改写！

[root@linux ~]# /etc/init.d/amavisd restart
    每个人的主机都不太一样，所以这个分数需要你多方的尝试才能找出最佳的数值。 就是因为害怕误判，所以才希望你在 /etc/amavisd.conf 里面不要将 spam 的规则设定为 D_DISCARD 的啦！ ^_^！ 至于这个档案的处理方式，其实你可以参考底下的网页来改写 local.cf 档案喔！
    • http://spamassassin.apache.org/full/2.6x/dist/doc/Mail_SpamAssassin_Conf.html
    • http://www.yrex.com/spam/spamconfig.htm
    不过你得要注意的是， local.cf 里面很多的设定值已经被 /etc/amavisd.conf 所取代了， 所以你的 local.cf 部分设定可能会失效的！这要特别先说明的。 整个病毒、广告信的安装与设定就到此为止啦，然后我们可以开始稍微测试一下啰！ 你可以利用 CentOS 本身的 Spamassassin 提供的一封广告信来测试看看：
    [root@linux ~]# mail -s 'spam test' dmtsai <  \
> /usr/share/doc/spamassassin-3.0.6/sample-spam.txt
# 假设你的系统有个使用者名为 dmtsai ，你寄出广告信给他，
# 然后用 dmtsai 收信一下，你会发现到该封信件的内容：

[dmtsai@linux ~]$ mail
>N 1 dmtsai@linux  Thu Nov 30 23:18  54/2065  "**SPAM** spam test"
# 瞧！标头多出了一些东西啦！没错！信件标头会被改写！
& 1
From dmtsai@linux.vbird.tsai  Thu Nov 30 23:18:24 2006
X-Original-To: dmtsai@linux.vbird.tsai
Delivered-To: dmtsai@linux.vbird.tsai
X-Quarantine-ID: <v02TdcMd+Vk4>
From dmtsai@linux.vbird.tsai Thu Nov 30 23:18:24 2006
X-Original-To: dmtsai@linux.vbird.tsai
Delivered-To: dmtsai@linux.vbird.tsai
X-Quarantine-ID: <v02TdcMd+Vk4>
X-Virus-Scanned: amavisd-new at vbird.tsai
X-Spam-Flag: YES
X-Spam-Score: 1001.148
X-Spam-Level: ***********************************************
X-Spam-Status: Yes, score=1001.148 tagged_above=5 required=6.31
        tests=[AWL=-2.025, DNS_FROM_RFC_ABUSE=0.374, GTUBE=1000,
        NO_RELAYS=-0.001, UNWANTED_LANGUAGE_BODY=2.8]
# 上面的特殊字体部分，第一行就是病毒扫瞄的证据！
# 后面这几行则是运算广告信总结分数的结果啊！有趣吧！

  • 自动学习抵挡广告信：
    • 在 spamassasin 所提供的功能当中，事实上有两种使用 spamassassin 的方式，一种是透过 spamd 这个 spamassassin 的服务，另一种则是透过 spamc 这个可以让 MTA 呼叫来批次执行的程式。在鸟哥的这个范例当中，我们是透过 amavisd-new 软体来呼叫 spamc 以处理广告信的啦！所以你的 spamassassin 的 daemon 功能不用启动的。

    另外，广告信的变化可是千变万化的，谁也搞不清楚下一次出现广告信的情况会是如何，所以说， 订定死的广告信过滤规则是没有多大的效果的。所以啰，能够自动学习广告信的内容资料，然后自动学习更新资料库， 这才能够因应网际网路的现实残酷的状态。好佳在！咱们的 spamassassin 有提供一支程式与一个称为 bayes (贝式) 的机制来处理自动学习的功能！我们可以透过这个功能来进行分类呐！

    既然有过滤机制的资料库，那么资料库在哪里啊？其实资料库主要有两个，分别是个人的与系统的！ 我们这个案例的系统资料库放置在 /var/amavis/.spamassassin/ 里面， 个人资料库则是在 ~/.spamassassin/ 里面。基本上，建议直接由系统管理员直接修订系统资料库的内容即可。 那么如何处理新的广告信件呢？你必须这样做：
    1. 手动处理广告信资料：
      你得要先手动的将没有被 spam 的广告信抽出来，举例来说，鸟哥将我所收到的广告信放置到 /root/mail/spam 这个档案当中，他是一个 mbox 的格式，也就是 mailbox 的格式啰。 你也可以建立一个使用者名为 spam，那么将你所收到的广告信转寄给这个使用者即可。

    2. 利用 sa-learn 学习广告信：
      接下来你得要更新广告信的资料库了，这个动作主要是经由 sa-learn 这个指令来处理的。 你最好先以‘ man sa-learn ’来了解一下所有的参数才好。假设你的广告信放置在 /root/mail/spam 这个 mbox 格式的档案中，那么你可以这样做：
      sa-learn --spam --mbox --dbpath /var/amavis/.spamassassin/ /root/mail/spam
      如此一来过滤广告信的内容就会被更新了。

    3. 正常信件被误判的处理：
      那如果有正常信件却被分析为广告信呢？没关系，你同样将这些信件独立出来成为一个档案， 例如 /root/mail/nospam 好了，然后这样学习：
      sa-learn --ham --mbox --dbpath /var/amavis/.spamassassin/ /root/mail/nospam
    透过这个学习机制，你的广告信抵挡会越来越精确喔！等到累积了足够的广告信学习后， 就能够修改 /etc/amavisd.conf 里面针对广告信命运的处理方式了 (由 D_PASS 变成 D_DISCARD 看看！) 加油！

  • 不要丢弃 exe 档名的附件：
    • 使用了 amavisd-new 来作为病毒处理与广告信抵挡真是不错的方案，不过，预设 amavisd-new 会丢弃附件夹档档名为 *.exe, .bat, .com... 等等的邮件，而且如果你将某个 .exe 档案压缩成为 .rar 或者是 .zip 的压缩档时， 由于我们的 Linux 有安装解压缩软体 (如 unrar)，结果...该封邮件还是会被丢弃，而不论是否有病毒存在。

    这样实在不怎么人性化，因为有些时候我们必须要传送一些附档名为 .exe 之类的执行档，如果预设会被丢弃， 那如何传送出该档案？除非使用 ftp 了～真麻烦～没关系，我们可以透过修改 amavisd-new 的设定档来放行喔！ 处理的方式很简单，只要这样做即可：
    [root@linux ~]# vi /etc/amavisd.conf
找到底下这一行，大约在 166 行左右
  qr'^\.(exe-ms|dll)$',
将他改成这样：
  qr'^\.(dll)$',

找到底下这两行，大约在 187 行附近
  qr'\.[^./]*[A-Za-z][^./]*\.(exe|vbs|pif|scr|bat|cmd|com|cpl|dll)\.?$'i,
  qr'.\.(exe|vbs|pif|scr|cpl)$'i,
将他改成这样：
  qr'\.[^./]*[A-Za-z][^./]*\.(vbs|pif|scr|cmd|com|cpl|dll)\.?$'i,
  qr'.\.(vbs|pif|scr|cpl)$'i,

[root@linux ~]# /etc/init.d/amavisd restart
    就是将含有 exe 的关键字设定给他移除就是了，如此一来，除非你的 .exe 档案含有病毒， 否则就不会被丢弃啰！
    小标题的图示 其他设定小技巧
    除了之前谈到的几个主要的设定之外， postfix 还有提供一些不错的设定要给大家使用的喔！ 我们可以一个一个来来看看：

  • 单封信件与单个邮件信箱的大小限制
    • 在预设的情况下， postfix 可接受的单封信件最大容量为 10MBytes ，不过这个数值我们是可以更改的， 动作很简单：
    [root@linux ~]# vi /etc/postfix/main.cf
message_size_limit =   40000000
[root@linux ~]# postfix reload
    上面的单位是 bytes ，所以我将单封信件可接受大小改为 40MByte 的意思啦！请按照你的环境来规定这个数值。 而从前我们要管制 /var/spool/mail/account 大多是使用档案系统内的 quota 来达成， 现在的 postfix 不需要啦！可以这样做：
    [root@linux ~]# vi /etc/postfix/main.cf
mailbox_size_limit = 1000000000
[root@linux ~]# postfix reload
    我给每个人 1GB 的空间啊！^_^

  • 寄件备份
    • 收件备份我们知道可以使用 /etc/aliases 来处理的，但是如果想要送件也备份呢？ 利用底下的方式即可：
    [root@linux ~]# vi /etc/postfix/main.cf
always_bcc = some@host.name
[root@linux ~]# postfix reload
    如此一来任何人寄出的信件都会复制一份给 some@host.name 那个信箱。 不过，除非您的公司很重视一些商业机密，并且已经公告过所有同仁，否则进行这个设定值， 鸟哥个人认为侵犯隐私权很严重！

    大标题的图示 其他应用说明
    除了 mail server 自己的设定值之外，我们最好还是针对 mail server 的资料来备份啊来管理啊等等的， 所以底下有些咚咚也可以处理处理：

    小标题的图示 问题检查
    虽然 Mail 很方便，但是仍然会有无法将信件寄出的时候！如果您已经设定好 MTA 了，但是总是无法将邮件寄出去，那可能是什么问题呢？
    • 关于硬体配备：
      无论任何情况之下，如果硬体出问题，那么所有的服务都将不正常啦！所以，请先检查您的硬体是否‘怪怪的！’这个先确认 OK 吧！

    • 关于网路参数的问题：
      如果连不上 Internet ，那么哪里来的 Mail Server 呢？所以请先确认你的网路已经正常的启用了！ 关于网路的确认问题，请查阅前几篇‘Linux 网路侦错’的内容介绍；

    • 关于服务的问题：
      请务必确认 port 25 与 port 110 已经正确的启动了！使用 netstat 指令即可了解是否已经启动该服务！

    • 关于防火墙的问题：
      很多时候，很多朋友使用 Red Hat 或者其他 Linux distribution 提供的防火墙设定软体，结果忘了启动 port 25 与 port 110 的设定，导致无法收发信件！请特别留意这个问题喔！可以使用 iptables 来检查是否已经启用该 port 呢！其余请参考防火墙设定那一章喔！

    • 关于 TCP_Wrappers 的问题：
      如果你的 MTA 还有支援 tcpd 这个程式 (或者说是 libwrap 这个函式库) 的话，那么在 /etc/hosts.allow 与 /etc/hosts.deny 的设定也会影响到收发信件的正常与否！如果 /etc/hosts.deny 有设定‘ALL: ALL’的话，那么请务必在 /etc/hosts.allow 里面加设‘ sendmail: ALL ’喔！

    • 关于设定档的问题：
      在启动 postfix 或者是 sendmail 之后，在登录档当中仔细看看有无错误讯息发生？ 通常如果设定资料不对，在登录档当中都会有记载错误的地方。

    • 关于档案权限的问题：
      如果你曾经手动处理过软体的 tarball 升级，或者是你曾自己处理过一些设定档，那么就得要注意：
      • /etc/mail/, /etc/postfix/ ：里面的档案至少都为 644 或 640 的权限！
      • /var/spool/mqueue ：务必为 700 的权限
      • /var/spool/clientmqueue：这在 sendmail 8.12 才有，所有人与群组务必为 smmsp ，而权限务必为 770 ；
      • 每个 ~/.forward 的档案需要控制其权限喔！

    • 其他档案的设定问题：
      如果发现只有某个 domain 可以收信，其他的同一主机的 domain 无法收信，需要检查 local-host-names 这个档案的设定， 或者是 $mydestination 的设定值才行；
      如果发现邮件被挡下来了！而且老是显示 reject 的字样，那么可能被 access 挡住了；
      如果发现邮件伫列 (mailq) 存在很多的邮件，可能是 DNS 死掉了，请检查 /etc/resolv.conf 的设定是否正确！

    • 其他可能的问题：
      最常发生的就是认证的问题了！这是由于使用者没有在 MUA 上面设定‘我的邮件需要认证’的选项啦！ 请叫你的用户赶紧勾选吧！

    • 还是不知道问题的解决方案：
      如果还是查不出问题的话，那么请务必检查您的 /var/log/maillog (有的时候是 /var/log/mail ，这个要看 /etc/syslog.conf 的设定)，当你寄出一封信的时候，例如 dmtsai 寄给 bird2@linux.vbird.tsai 时，那么 maillog 档案里面会显示出两行，一行为 from dmtsai 一行为 to bird2@linux.vbird.tsai， 也就是‘我由哪里收到信，而这封信会寄到哪里去！’的意思，由这两行就可以了解问题了！尤其是 to 的那一行，里面包含了相当多的有用资讯，包括邮件无法传送的错误原因的纪录！ 如果您对于登录档不熟，请拿出‘基础学习篇’里面的‘认识登录档’一文吧！
    小标题的图示 哪些资料要备份
    不管什么时候，备份总是重要的！那么如果我是单纯的 Mail Server 而已，我需要的备份资料有哪些呢？
    • /etc/passwd, /etc/shadow, /etc/group 等与帐号有关的资料；
    • /etc/mail, /etc/postfix/ 底下的所有档案资料；
    • /etc/aliases 等等 MTA 相关档案；
    • /home 底下的所有使用者资料；
    • /var/spool/mail 底下的档案与 /var/spool/postfix 邮件伫列档案；
    • 如果是 Sendmail 8.12 则可以考虑储存 /var/spool/clientmqueue。
    • 其他如广告软体、病毒扫瞄软体等等的设定与定义档。
    小标题的图示 quota 与目录移转
    网路上有很多‘免费的电子邮件信箱’空间，一般而言，使用的就是 quota 这个磁碟配额工具！因为我们的 Linux 主机硬碟空间就是这么多！当然啰， 使用磁碟配额 (quota) 会是一个对大家比较公平的方法！使用 quota 的技巧已经在‘基础学习篇’里面介绍过了，这里不再重复介绍，要介绍的是几个可能会发生在实际的案例中的一些小技巧：

  • 邮件信箱所在的磁碟空间不足了
    • 这是很可能会发生的问题啊！尤其是在用量很大的网站上面！这个时候你的解决方法主要有：
    1. 新增加一颗硬碟，格式化好之后将他 mount 到 /var/spool/mail 这个目录下；
    2. 如果主机里面还有其他目录具有很大的空间，例如 /home 这个地方，那么就可以：
        cd /var/spool
        mv mail /home
        ln -s /home/mail mail
  • 使用 quota 设定：
    • 一般而言，我们通常会将 /home 做为 quota 的 partition ，那么 /var/spool/mail 其实也可以依附在 /home 这个 partition 之下，来达到 quota 对于使用者的规范喔！达成的方法很简单啦：
    1. 先在主机规划与安装的时候，让 /home 独立于一个 partition 当中；
    2. 以‘鸟哥的 Linux 私房菜 -- 基础学习篇’的 quota 内容为范例，建立好 /home 的 quota 限额；
    3. 将 /var/spool/mail 整个搬到 /home 底下，并做好连结的动作就可以立即生效啦：
        cd /var/spool
        mv mail /home
        ln -s /home/mail mail
  • 关于使用者邮件的放置地点
    • 很多的读者可能喜欢让每个使用者去到自己的家目录读取 mail box 的咚咚，亦即是将 /var/spool/mail 的内容给他搬到个别的家目录去！例如 dmtsai 的 mail box 变成的 /home/dmtsai/dmtsai 这个档案！不过，如此一来的话， MTA 与 pop 都将需要改写其 source code ！所以‘不建议这么搞喔！’
    大标题的图示 重点回顾
    • 电子邮件伺服器的设定需要特别留意，以免被作为广告信与垃圾信的跳板；
    • Mail server 使用的主机名称至少需要 A 的 DNS 标志，不过最好能够具有 MX 标志为宜，且正反解最好成对， 比较可以避免大型主机的抵挡；
    • 邮件主机主要是指 SMTP (简单邮件传送协定) 而已，不过要架设一部可利用类似 Thunderbird 收发的邮件伺服器， 最好能够具有 SMTP 以及 POP3 等通讯协定；
    • 电子邮件传送的元件，主要有 MUA, MTA, MDA 以及最终的 Mailbox 等等；
    • 电子邮件伺服器最需要搞定的地方其实是 Relay 的功能，千万不可 Open Relay 喔！
    • 一封电子邮件至少含有 header 以及 body 等资料在内；
    • 常见的可以启动 SMTP 的软体有 sendmail, postfix 及 qmail 等等。
    • 为避免收到大量的广告信，建议您不要将 email address 放在网际网路上，若需要某些功能必需将邮件位址放在网路上时， 最好能够拥有两个邮件位址，一个用来公开，一个则用来作为自己的主要联络之用。
    • 本章与 LPI 认证的关系：在 LPI 网站 http://www.lpi.org 里面提到的，关于 Sendmail 的考试题库的地方，只有在 LPI level 1 的 102 ，里面的 topic 113 Networking Services ，第二点当中，简易的 Sendmail 设定。强调的是‘应试者必须简单的设定 sendmail (指的应该是 m4 scripts ，不过会很简单！不要担心～)、能够建立 mail aliases 、能够管理邮件伫列、能够启动或者是关闭 sendmail 这个服务、了解使用者的邮件转递 (forward 功能)，以及简单的 sendmail 除错！此外，应试者也需要了解什么是 Open Relay 与避免 Open Relay 才行！’至于会考的档案与指令可能有这些：
      • /etc/sendmail.cf (或是 /etc/mail/sendmailcd)
      • /etc/aliases 或是 /etc/mail/aliases
      • /etc/mail/*
      • ~/.forward
      • mailq
      • sendmail
      • newaliases
    大标题的图示 课后练习
    • 当你利用你的 MTA 发信时，结果竟然被退信，退信的讯息 (/var/log/maillog) 最主要的错误是‘mail loop to me’， 请问可能的发生原因及处理方式为何？
      • 可能发生的原因是由于你的 MTA 设定项目方面的主机名称错误。判断你的 MTA 主机有多个 IP 存在， 不过你并未完全写入设定档中，因此造成某些主机名称无法被 MTA 所接收之故。在 sendmail 方面， 你只要将需要的主机名称写入 /etc/mail/local-host-names 即可，如果是 postfix ，则在 /etc/postfix/main.cf 当中修改 $mydestination 那个设定项目即可。
    • 我在使用 Sendmail 寄信时，却发生底下这个问题，请问可能的发生原因为何？
      • 可能的问题有两个：
      • 你的 Client 端电脑的 IP 或者是网域位址被 /etc/mail/access 所挡住，或者是 /etc/mail/access 没有打开你的 RELAY 权力；
      • 你有进行 SMTP 邮件认证的设定，但是忘记在 MUA 当中设定帐号与密码的项目了！
        • 如果不是这两个原因，那么可能的问题就多了！请详细的检查您的网路设定！
    • 请列出四个 Mail Server 的相关的元件，以及其功用为何？
      • Mail Client ：邮件用户端，其实就是使用 mail 的那位使用者所在的电脑即可称为 mail client ；
      • Mail User Agent ：为一个应用软体，主要的功能就是收受邮件主机的电子邮件，以及提供使用者浏览与编写邮件的功能；
      • Mail Transfer Agent ：为在电脑与本地端 Mail server 或 Internet 上面的 Mail server 传送讯息与邮件的主机；
      • Mail Dilivery Agent ：主要的功能就是将 MTA 所收受的本机信件，放置到本机帐户下的邮件档案中 ( Mailbox )！
    • POP3 与 SMTP 的功能为何？
      • SMTP 为使用于 MUA 或 MTA 与 MTA 之间的传输协定，通常使用 port 25 ，只要主机支援 SMTP ，并且其他 relay 的条件能配合，就可以进行邮件传递！
      • POP3 可以提供使用者经由 MUA 到 MTA 下载邮件，同时并可将邮件从主机上面删除！
    • 请简单的说明 DNS 里面 MX 标志与 Mail 的关系为何？
      • MX recode 可以可以让 mail server 经由 MX 以及 A ( address ) 这个记录来进行 mail gateway 与 mail route 的功能！能够达到的作用相当的多！
    • 今天我突然兴起，想要修改我的 sendmail ，请问， sendmail 的设定档在哪里？而我要以什么程式修改 sendmail 呢？
      • Sendmail 的设定档为 sendmail.cf ，这个档案通常放置在 /etc/sendmail.cf 或者 /etc/mail/sendmail.cf 您可以手动的编辑这个档案，不过不建议如此，取得代之的，可以使用 m4 这个程式来进行 macro 的动作，进一步的完成 sendmail.cf 的修改！至于使用 m4 时，需要先建立 m4 scripts ，再以 m4 转换才能形成 sendmail.cf 喔！
    • 什么是 mailling list ？在 sendmail 底下有什么方法可以不藉由其他的软体达到 mailling list 的功能？
      • Mailling list 就是将使用者寄给一个帐号邮件时，该帐号会主动的将该邮件传送到所有的用户去！有点类似目前的电子报！在 sendmail 底下，我们可以透过 aliases (需配合 newaliases) 以及 ~/.forward 来达成喔！
    • 如何察看邮件伫列的内容，以及邮件伫列内容放置在何方？
      • 使用 mailq 即可知道目前邮件伫列的内容，而邮件伫列虽然可以透过 sendmail.cf 来修改，不过，预设情况下，都是以 /var/spool/mqueue 为邮件伫列目录。
    • 若我的 sendmail 主机有很多名称，我想让这些名称都可以进行 mail 的接收，应该修改什么档案？
      • 可以修改 /etc/mail/local-host-names 来达成！
    • 什么是 Open Relay？
      • 所谓的 Open Relay 就是，不论发信端来自何处，您的 Open Relay 的主机均可以帮发信端将信件发送出去，这个称为 Open Relay 。如果您的 mail server 具有 open relay 的情况，那么很容易遭受到垃圾邮件的填充， 不但造成网路频宽的耗损，也容易让您的主机被列入黑名单当中！
    • 如果要让 Postfix 可以收发来自非本机的外部信件，您可以修改 main.cf 里面的什么参数？
      • 需要在 main.cf 里面修改的变数主要有：
      1. 当 Client 来自信任的网域，也就是 IP 符合 $mynetworks 的设定值时；
      2. 当 Client 来自信任的机器，也就是主机名称符合 $relay_domains 的设定项目时；
      3. 当 Client 来自不信任的网域，但是去的目的地主机端符合 $relay_domains 的设定时。
    • 如何察看您目前的 Postfix 伺服器的所有设定参数？(使用什么指令？)
      • 利用 postconf -n 可以察看‘目前 main.cf 里面设定的参数’，而如果要看所有的参数，则直接使用 postconf 即可！
    • Mail Server 能否运作与 DNS ( MX 与 A recode )的相关性为何？
      • 目前网际网路社会合法的 Mail server 通常仅会针对具有 MX 标志的邮件主机发出信件而已。 而如果有多重 MX 时，首先会选择最小 MX 主机寄信，依序处理。而最终依据 MX 主机的 A 标志来查得最终目标。
    • 什么是 smtp, pop3 以及 imap 协定，他们的用途分别是什么？
    • smtp：用来传递邮件的协定，通常我们称为 MTA 即是此一协定所达成
    • pop3：让 client 端向主机端要求收信的协定，通常预设收信完成后，主机端的 mail box 会被删除；
    • imap：与 pop3 类似，不过 imap 允许使用者在主机的家目录建立邮件资料匣
    大标题的图示 参考资料
    • Sendmail 官方网站： http://www.sendmail.org
    • Postfix 官方网站： http://www.postfix.org
    • Cyrus-SASL 官方网站： http://asg.web.cmu.edu/cyrus/download/sasl/doc/
    • Procmail 官方网站： http://www.procmail.org
    • Open Relay Database： http://www.ordb.org/ (很可惜，已于 2006/12/18 关站)
    • Study Area 之邮件架设：http://www.study-area.org/linux/servers/linux_mail.htm
    • SMTP 认证系统的建置：http://beta.wsl.sinica.edu.tw/~ylchang/Email/sendmail-auth/
    • 台湾学术网路黑名单网页： http://140.111.1.22/tanet/spam.html
    • 卧龙小三的 Procmailrc 范例：ftp://ftp.tnc.edu.tw/pub/Sysop/MAIL/procmailrc
    • 林克敏主任文件集之 Procmail 范例：http://freebsd.lab.mlc.edu.tw/procmail.htm
    • Postgrey 官方网站：http://isg.ee.ethz.ch/tools/postgrey/
    • Postfix 针对 Postgrey 的设定： http://www.postfix.org/SMTPD_POLICY_README.html
    • 一些 postfix 的 relay 机制设定： http://jimsun.linxnet.com/misc/postfix-anti-UCE.txt
    • 小州的 postfix 设定： http://phorum.study-area.org/viewtopic.htm?t=30716
    • POSTFIX 技术手札，Ralf Hildebrandt/Patrick Koetter 合着，上奇出版，2005年。
    • TWU2 兄在酷学园所发表的自制邮件过滤软体： http://phorum.study-area.org/viewtopic.htm?t=38649
    • Amavis-new 一个在 MTA 与伫列间的服务：http://www.ijs.si/software/amavisd/
    • 广告信件分析软体：http://spamassassin.apache.org/index.html
    • Steven 的垃圾信抵挡机制：http://www.l-penguin.idv.tw/article/postfix_spam-spamassassin.htm
    2006/11/13：准备将原本的 sendmail 以及 postfix 整合成为一篇专门介绍 Mail server 的小文章啰！
    2006/11/14：原本的 sendmail 请参考这里，原本的 Postfix 则请参考这里。至于人数统计则以 sendmail 原本网页增加。
    2006/11/30：加上了邮件扫瞄与广告信抵挡的 spamassassin 机制，呼呼！好累～
    2006/12/05：加上自动学习广告信抵挡机制方面的简单介绍。
    2007/02/07：新增不要丢弃 exe 附档名的资讯！
    2007/02/27：感谢网友 Cheng-Lin Yang 提供的意见，在黑名单资料库增加了 http://www.anti-spam.org.cn/, http://www.spamhaus.org/
    2007/04/05：感谢 chunkit 兄的来信告知，将原本的 mail localhost 25 改成 telnet localhost 25 ！
    2002/01/01以来统计人数


鸟哥的 Linux 私房菜 -- SAMBA 伺服器

为取得较佳浏览结果，请爱用 firefox 浏览本网页

SAMBA 伺服器
切换解析度为 800x600
最近更新日期：2006/12/29
在一般的区域网路中 (LAN) 如果都是 Windows 电脑，那么使用‘网路上的芳邻’这个功能，就可以让不同的 Windows 电脑分享彼此的档案啰！但万一这个 LAN 里面有个 Linux 主机时，我怎么让 Linux 也加入这个 Windows 电脑当中的‘网路上的芳邻’呢？也就是说，让 Windows 电脑可以透过‘网路上的芳邻’来存取 Linux 主机上面的档案！呵呵！那就是 SAMBA 这个伺服器的主要目的了！SAMBA 是很有用的一个伺服器，他可以让您的 Linux 刹那间成为一个档案伺服器 (File Server)，并提供整个 LAN 里面的 Windows 很简单的就可以对 Linux 主机进行档案的存取动作。不仅如此， SAMBA 也可以让 Linux 上面的印表机成为印表机伺服器 (Printer Server) ，鸟哥个人觉得， SAMBA 对于整个 LAN 的贡献真的是很大！那么就赶紧来玩一玩吧！ ^_^

1. 本章的行前准备工作
2. 什么是 SAMBA ？
    2.1 SAMBA 的发展历史与名称的由来
    2.2 SAMBA 常见的应用
    2.3 SMB 使用的 NetBIOS 通讯协定
    2.4 SAMBA 使用的 daemons
    2.5 连线模式的介绍 (peer/peer, domain model)
 3. SAMBA 伺服器的基础设定
    3.1 Samba 所需套件及其套件结构
    3.2 基础设定流程与 smb.conf 的主要规划：
        主机整体参数, 分享目录参数, 变数特性
    3.3 没有密码的 smb.conf 设定(纯测试) (lmhosts, testparm, smbclient)
    3.4 安全等级为使用者的工作群组设定 (smbpasswd)
    3.5 设定成为印表机伺服器 (CUPS 系统) (cupsaddsmb)
    3.6 安全性管理： iptables, smb.conf 设定值, Quota, 关于备份
    3.7 主机安装时的规划与中文磁区挂载
 4. Samba 用户端软体功能
    4.1 Windows 系统的使用： WinXP 防火墙, port 445
    4.2 Linux 系统的使用： smbclient, smbmount, nmblookup, smbstatus
 5. 伺服器进阶管理
    5.1 让 Samba 管理网域使用者：PDC
    5.2 问题克服
    5.3 使用者修改自己的密码
    5.4 利用 ACL 配合单一使用者时的控管
 6. 重点回顾
7. 课后练习
8. 参考资料
9. 针对本文的建议：http://phorum.vbird.org/viewtopic.htm?p=118976
大标题的图示 本章的行前准备工作
这一章的主要目的为介绍在不同的平台上面利用同样的协定来进行档案的传输， 其实主要就是让 Linux 与 Windows 主机之间能彼此透过‘网路上的芳邻’这个方式来分享档案， 而最主要的目的就是当你的区域网路内办公用的主机大多是 Windows 系统时， 可以透过网芳来存取 Linux 主机上面的资源，让你不觉得有任何不一样！ 而阅读之前你至少需要有底下的一些基础概念：
  • 网路基础是不能少的，尤其是 Samba 用到很多埠口；
  • 区域网路架构的设定也是要了解的啊！
  • 印表机的设定与使用也不能忘记呐！
大标题的图示 什么是 SAMBA ？
在这个章节中，我们要教大家跳的是热情有劲的巴西 SAMBA 舞蹈..... 喔不～搞错了～是要向大家介绍 SAMBA 这个好用的伺服器啦！咦！怪了！ 怎么伺服器的名称会使用 SAMBA 呢？还真是怪怪的呢！那么这个 SAMBA 伺服器的功能是什么呢？另外， 他最早是经由什么样的想法而开发出来的呢？呵呵！底下就让我们慢慢的谈一谈吧！

小标题的图示 SAMBA 的发展历史与名称的由来
在早期的网路世界当中，档案资料在不同主机之间的传输大多是使用 FTP 这个好用的伺服器软体来进行传送。不过使用 FTP 传输档案却有个小小的问题， 那就是您无法直接修改主机上面的档案资料！也就是说，您想要更改 Linux 主机上面的某个档案时，你必须要将该档案自伺服器上下载下来后才能修改。 也因此该档案在伺服器与用户端都会存在。这个时候，万一如果有一天您修改了某个档案， 却忘记将资料上传回主机，那么等过了一阵子之后，呵呵，您如何知道那个档案才是最新的？

  • 让档案在两部主机之间直接修改
    • 既然有这样的问题，那么好吧，我可不可以在用户端的机器上面直接取用 server 上面的档案， 如果可以在用户端直接进行 Server 端档案的存取，那么我在用户端就不需要存在该档案资料啰，也就是说， 我只要有 Server 上面的档案资料存在就可以啦！有没有这样的档案系统啊 (File System)！ 很高兴的是，前面我们已经提过的 Network File System, NFS 就是这样的档案系统之一啦！我只要在用户端将 Server 所提供分享的目录挂载进来， 那么在用户端的机器上面就可以直接取用 Server 上的档案资料啰，而且， 该资料就像是我用户端上面的 partition 一般，真是好用！

    而除了可以让 Unix Like 的机器互相分享档案的 NFS 伺服器之外，在微软 (Microsoft) 作业系统上面也有类似的档案系统，那就是 Common Internet File System, CIFS 这个咚咚啦！CIFS 最简单的想法就是目前常见的‘网路上的芳邻’咯！ Windows 系统的电脑可以透过桌面上‘网路上的芳邻’来分享别人所提供的档案资料哩！真是方便。 不过，NFS 仅能让 Unix 机器沟通， CIFS 只能让 Windows 机器沟通。伤脑筋，那么有没有让 Windows 与 Unix-Like 这两个不同的平台相互分享档案资料的档案系统呢？

  • 利用封包侦测逆向工程发展的 SMB Server
    • 在 1991 年一个名叫 Andrew Tridgwell 的大学生就有这样的困扰，他手上有三部机器，分别是跑 DOS 的个人电脑、DEC公司的 Digital Unix 系统以及 Sun 的 Unix 系统。在当时， DEC 公司有发展出一套称为 PATHWORKS 的软体，这套软体可以用来分享 DEC 的 Unix 与个人电脑的 DOS 这两个作业系统的档案资料，可惜让 Tridgwell 觉得较困扰的是，Sun 的 Unix 无法藉由这个软体来达到资料分享的目的。

    这个时候 Tridgwell 就想说：‘咦！既然这两部系统可以相互沟通，没道理 Sun 就必需这么苦命吧？可不可以将这两部系统的运作原理找出来，然后让 Sun 这部机器也能够分享档案资料呢？’， 为了解决这样的的问题，他老兄就自行写了个 program 去侦测当 DOS 与 DEC 的 Unix 系统在进行资料分享传送时所使用到的通讯协定资讯，然后将这些重要的资讯撷取下来， 并且基于上述所找到的通讯协定而开发出Server Message Block (SMB) 这个档案系统，而就是这套 SMB 软体就能够让 Unix 与 DOS 互相的分享资料啰！
    Tips:
    再次的给他强调一次，在 Unix Like 上面可以分享档案资料的 file system 是 NFS，那么在 Windows 上面使用的‘网路上的芳邻’所使用的档案系统则称为 Common Internet File System, CIFS     		鸟哥的图示
  • 取名 SAMBA 的主因 ^_^
    • 既然写成了软体，想一想，总是需要注册一下商标吧！因此 Tridgwell 就去申请了 SMBServer (Server Message Block 的简写) 这个名字来做为他撰写的这个软体的商标，可惜的是，因为 SMB 是没有意义的文字，因此没有办法达成注册。既然如此的话，那么能不能在字典里面找到相关的字词可以做为商标来注册呢？ 翻了老半天，呵呵！这个 SAMBA 刚好含有 SMB ， 又是热情有劲的拉丁舞蹈的名称，不然就用这个名字来做为商标好了！ 这成为我们今天所使用的 SAMBA 的名称由来啦！ ^_^
    小标题的图示 SAMBA 常见的应用
    由上面说明的 SAMBA 发展缘由，您就应该不难知道咯， SAMBA 最初发展的主要目就是要用来沟通 Windows 与 Unix Like 这两个不同的作业平台，那么 SAMBA 可以进行哪些动作呢？
    • 分享档案与印表机服务；
    • 可以提供使用者登入 SAMBA 主机时的身份认证，以提供不同身份者的个别资料；
    • 可以进行 Windows 网路上的主机名称解析 (NetBIOS name)
    • 可以进行装置的分享 (例如 Zip, CDROM...)
    底下我们来谈几个 SAMBA 伺服器的应用实例吧！

  • 利用软体直接编修 WWW 主机上面的网页资料
    • 相信很多人都是利用个人电脑将网页制作完毕之后，再以类似 FTP 之类的服务将网页上传到 WWW 主机的， 但这样有个困扰，那就是同时在用户端与 WWW 主机上头都有一份网页资料，常常会忘记哪一份是最新的， 最麻烦的是，有时候下载下来的档案已经经过好多修改了，却在下次的 FTP 作业，不小心又下载一次旧资料， 结果将已经修改过的资料覆盖过去～天呐！又要重写一遍.....真是讨厌！

    如果你有安装 SAMBA 伺服器的设定的话，那么透过‘网芳’的功能，直接连线远端伺服器所提供的目录， 如此一来你可以直接在你的个人电脑上面修改主机的档案资料，只有一份正确的资料而已喔！ 这就有点像是‘线上编修’呢，一修改完成，在 Internet 上面可以立刻检验，方便的很呐！

  • 做成可直接连线的档案伺服器
    • 在鸟哥实验室中，由于电脑数量不多，研究生常常会使用到不同的电脑 (因为大家都得抢没有人用的电脑啊！) ，此外，也常常有研究生拿自己的 NoteBook 来工作，因此，有些团队的资料就分散在各个电脑当中，使用上相当的不方便。 这个时候，鸟哥就使用 SAMBA 将硬碟空间分享出来，由于使用者要登入 SAMBA 这个伺服器主机时需要输入使用者资料 (帐号与密码)，而不同的登入者会取得不一样的目录资源，所以可以避免自己的资料在公用电脑上面被窥视， 此外，在不同的公用电脑上面都可以登入 SAMBA 主机，资料的使用上面真是相当的棒啊！

  • 印表机伺服器
    • SAMBA 除了分享档案系统外，也可以分享印表机喔，鸟哥的研究室好几部电脑就是直接以 Linux 分享的印表机来印制报告的。您会说‘啊 Windows 也可以办的到啊！没有什么了不起的！’是啊。 但是因为 Linux 做为伺服器主机时，鸟哥认为 Linux 毕竟还是比较稳定一点，可以 24 小时且全年无休的努力工作呐。此外，因为目前透过‘网路上的芳邻’来攻击区域网路的 Windows 作业系统的电脑病毒实在是太多了，防不胜防， Linux 对于这样的攻击并没有很大的影响 (因为常见的攻击手法均针对 Windows 而来～)，所以也比较安全一些说～

    SAMBA 的应用挺广泛的，尤其对于区域网路内的电脑来说，更是一项不可多得的好用的伺服器， 虽然或许你会说，SAMBA 的功能不过是模仿 Windows 的网芳以及 AD 相关的软体， 那我直接使用 Windows 不就 OK 了？可惜的是， Windows XP 对于网芳的连线限制依版本而有所不同， 以企业常见的专业版 (Professional) 来说，他仅能提供最多同时十个连线到网芳的连线能力，这.....不太够用吧！ 所以啰，SAMBA 稳定、可靠又没有限制连线数，值得学习吧！^_^！更多的应用您可以自行发掘呐！

    小标题的图示 SMB 使用的 NetBIOS 通讯协定
    事实上，就像 NFS 是架构在 RPC Server 上面一样， SAMBA 这个档案系统是架构在 NetBIOS (Network Basic Input/Output System, NetBIOS) 这个通讯协定上面所开发出来的。既然如此，我们当然就要了解一下 NetBIOS 啰！

    最早 IBM 发展出 NetBIOS 的目的仅是要让区域网路内少数电脑进行网路连结的一个通讯协定而已， 所以考虑的角度并不是针对大型网路，因此，这个 NetBIOS 是无法跨路由的 (Router / Gateway)。这个 NetBIOS 在区域网路内实在是很好用， 所以微软的网路架构就使用了这个咚咚来进行沟通的呐！而 SAMBA 最早发展的时候，其实是想要让 Linux 系统可以加入 Windows 的系统当中来分享使用彼此的档案资料的，所以当然 SAMBA 就架构在 NetBIOS 发展出来啰。

    不过 NetBIOS 是无法跨路由的，因此使用 NetBIOS 发展起来的伺服器理论上也是无法跨越路由的呢！ 那么该伺服器的使用范围不就受限相当的多了？好在，我们还有所谓的 NetBIOS over TCP/IP 的技术呢！这是什么样的技术啊？

    举个例子来说好了，我们知道 TCP/IP 是目前网路连接的基本协定，现在我们将 NetBIOS 想成是一封明信片， 这个明信片只能让您自己欣赏而已，如果今天我们要将这个明信片送到远方的朋友那边时！就需要透过邮件系统 (例如邮局啦、国际快递啦等等的) 来传送了！这个 TCP/IP 就可以视为邮件传递系统啦！透过这个 NetBIOS over TCP/IP 的技术，我们就可以跨路由的使用 SAMBA 伺服器所提供的功能咯！ 当然啦，目前 SAMBA 还是比较广泛的使用在 LAN 里面说。
    Tips:
    或许您会发现在 Windows 网路设定里面常常看到 NetBEUI 这个咚咚，那是什么呢？那个是 NetBIOS Extened User Interface 的简写，也是 IBM 在 NetBIOS 发展出来之后的改良版本。虽然这两者的技术不太相同， 不过，我们只要知道一些简单的概念就可以了！所以，在这里我们不针对 NetBEUI 来介绍。     		鸟哥的图示
    小标题的图示 SAMBA 使用的 daemons
    NetBIOS 当初发展时就着眼在区域网路内的快速资料交流，而因为是定义在区域网路内，因此他并没有使用类似 TCP/IP 之类的传输协定，也就不需要 IP 的设定。如此一来资料如何在两部主机之间交流呢？ 其实主机在 NetBIOS 协定当中的定义为使用‘NetBIOS Name’，每一部主机必须要有不同的 NetBIOS Name 才行， 而档案资料就是在不同的 NetBIOS name 之间沟通啰！我们以一个网芳的设定来作简单的说明好了：
    1. 取得对方主机的 NetBIOS name 定位该主机所在：
      当我们想要登入某部 Windows 主机使用他所提供的档案资料时，必需要加入该 Windows 主机的群组 (Workgroup)，并且我们的机器也必需要设定一个主机名称，注意喔，这个主机名称跟 Hostname 是不一样的，因为这个主机名称是架构在 NetBIOS 协定上的，我们可以简单的称呼他为 NetBIOS Name 好了。在同一个群组当中，NetBIOS Name 必需要是独一无二的喔！

    2. 利用对方给予权限存取可用资源：
      在我们找到该主机名称后，是否能登入该对方主机或者是取用对方主机所提供的资源， 还要看对方 Windows 主机有没有提供我们使用的权限呐！所以，并不是登入该 Windows 主机之后我们就可以无限制的取用该主机的档案资源了。也就是说，如果对方主机允许你登入， 但是却没有开放任何资源让您取用，呵呵，登入主机也无法查看对方的硬碟里面的资料的啦！
    我们的 SAMBA 则是透过两支服务来控制这两个步骤，分别是：
    • nmbd ：这个 daemon 是用来管理工作群组啦、NetBIOS name 啦等等的解析。 主要利用 UDP 协定开启 port 137, 138 来负责名称解析的任务；

    • smbd ：这个 daemon 的主要功能就是用来管理 SAMBA 主机分享的目录、档案与印表机等等。 主要利用可靠的 TCP 协定来传输资料，开放的埠口为 139 及 445(不一定存在) 。
    所以啰， SAMBA 每次启动至少都需要有这两个 daemons 喔！这可不要忘记啰！ ^_^而当我们启动了 SAMBA 之后，主机系统就会启动 137, 138, 139 三个 port ，且同时会有 UDP/TCP 的监听服务喔！这可不要忘记了！ 因为后面设定防火墙的时候，还会使用到这三个 port 的呢！

    小标题的图示 连线模式的介绍 (peer/peer, domain model)
    SAMBA 主机的应用相当的广泛，而且可以依照不同的网域连线与使用者帐号、密码的控管方式不同， 来加以不同的类别应用，例如最常见的 Workgroup 及 Domain 两种方式的连线模式呢！ 底下我们就是要来谈一谈这两种最常见的区域网路的连线模式 peer/peer 及domain model。

  • peer/peer (Workgroup model)：
    • peer 有同等、同辈的意思存在，那么 peer/peer 由字面上的解释来看，当然就是同等地位的 PC 架构了！这是什么意思呢？简单的来说，在区域网路里面的所有 PC 均可以在自己的电脑上面管理自己的帐号与密码， 同时每一部电脑也都具有独力可以执行各项软体的能力，只是藉由网路将各个 PC 连结在一起而已的一个架构， 所以，每一部机器都是可以独立运作的喔！

    这样的架构在目前小型办公室里面是最常见的。例如办公室里面有十个人，每个人桌上可能都安装有一套 Windows 作业系统的个人电脑，而这十部电脑都可以独立进行办公室软体的执行啊、独立上网啊、独立玩游戏啊等等的， 因为这十部电脑都可以独立运作，所以不会有一部电脑关掉，其他的电脑就无法工作的情况发生，这就是 peer/peer 的典型架构。

    以下图的架构为例，在这样的架构下，假设 A 君写了一个报告书，而 B 君想要以网路直接取用这个报告书时，他就必须要知道 A 君使用的电脑的帐号与密码，并且 A 君必须要在 PC A 上面启用 Windows 的‘资源分享(或者是共用)’之后，才能够让 B 君连线进入喔 (此时 PC A 为 Server) ！而且， A 君可以随时依照自己的喜好来更改自己的帐号与密码，而不受 B 君的影响，不过， B 君就得要取得 A 君同意取得新的帐号与密码后，才能够登入 PC A 喔！反过来说，同样的， A 要取得 B 的资料时，同样需要取得 PC B 的帐号与密码后，才能够顺利登入啊 (此时 PC A 为 Client 喔)！因为 PC A, PC B, PC C 的角色与地位都同时可以为 Client 与 Server ，所以就是 peer/peer 的架构了！

    Peer/Peer 的连线模式
    图一、Peer/Peer 的连线模式

    生活周遭中，哪里看到的这种 peer/peer 的架构呢？想起来了吗？没错！就是藉由 Windows 的‘网路上的芳邻’所达成的‘工作群组(workgroup)’的架构，那就是典型的 peer/peer 架构啦！所以， peer/peer 也可以直接说成 workgroup 的连线架构喔。

    使用 peer/peer 的架构的好处，是每部电脑均可以独立运作，而不受他人的影响！不过， 缺点就是当整个网域内的所有人员都要进行资料分享时，光是知道所有电脑里面的帐号与密码，就会很伤脑筋了！ 所以， Peer/Peer 的架构是比较适合 (1)小型的网域，或者是 (2)没有需要常常进行档案资料分享的网路环境，或者是 (3)每个使用者都独自拥有该电脑的拥有权(就是说，该电脑是使用者的，而不是公用的啦！) 而，如果该单位的所有 PC 均是公有的，而且您需要统一控管整个网域里面的帐号与密码的话，那就得使用底下的 domain models 了！

  • domain model
    • 假设今天您服务的单位有 10 部电脑，但是您的单位有 20 个员工，这也就是说，这 20 个员工轮流抢着用这 10 部电脑。如果每部电脑都如同 peer/peer 的架构时，那么每部电脑都需要输入这 20 个员工的帐号与密码来提供他们登入喔，而且，今天假如有个员工想要变更自己的密码时，就需要到 10 台电脑上面进行密码变更的作业！否则他就必须要记得这 10 部电脑里面，那一部电脑是记忆那一个密码.....好烦那～

    如果上述是这样的情况，使用 peer/peer 架构就不是一个好方法了！这个时候就需要藉由 domain model 来达成您的需求啦！所谓的 domain model 概念其实也很简单，既然使用电脑资源需要帐号与密码， 那么我将所有的帐号与密码都放置在一部主控电脑 (Primary Domain Controller, PDC) 上面，在我的网域里面，任何人想要使用任何电脑时，都需要在荧幕前方输入帐号与密码，然后通通藉由 PDC 主机的辨识后，才给予适当的使用权限，也就是说，不同的身份还具有不一样的电脑资源使用权限就是了！ 例如底下的图示：

    domain model 的连线模式
    图二、domain model 的连线模式

    PDC 主机控管整个网域里面的各个机器 (PC A ~ PC D) 的帐号与密码的资讯，假如今天有个使用者帐号名称为 Ken ，且密码为 mypasswd 时，他不论使用哪一部电脑 (PC A ~ PC D) 只要在荧幕前方输入 ken 与他的密码，则该机器会先到 PDC 上面查验是否有 ken ，以及 ken 的密码，并且 PDC 主机会给予 ken 这个使用者相关的电脑资源使用权限。当 ken 在任何一部主机上面登入成功后，他就可以使用相关的电脑资源了！

    这样的架构比较适合人来人往的企业架构，当系统管理员要控管新进人员的电脑资源使用权时，可以直接针对 PDC 来修改就好了，不需要每一部主机都去修修改改的，对于系统管理员来说，这样的架构在控管帐号资源上，当然是比较简单的啦！

    各种架构适用的环境与适用的人都不相同，并没有那个是最好啦！请依照您的工作环境来选择连线的模式啰！当然， SAMBA 可以达到上述两种模式的啦！底下我们会分别来介绍喔！
    大标题的图示 SAMBA 伺服器的基础设定
    SAMBA 这个套件几乎在所有的 Linux distributions 上面都有提供，因为即使你的 Linux 仅做为个人桌上型电脑使用时， 你依旧可能会需要连线到远端的 Windows 的网芳的，那个时候就得要 samba 提供的用户端软体功能啰！ 因此你只要直接安装系统上面提供的预设 samba 版本即可。底下我们会先介绍 samba 伺服器，然后在介绍用户端功能喔！

    小标题的图示 Samba 所需套件及其套件结构
    目前常见的 samba 版本为 3.x 版，旧版的 2.x 版在设定上有点不一样，因此在进入设定前请先确认你的 samba 版本。 咱们的 CentOS 4.x 提供的是 Samba 3.x 的版本。那么你需要什么套件呢？基本上有这些：
    • samba：
      这个套件主要包含了 SAMBA 的主要 daemon 档案 (smbd 及 nmbd)、 SAMBA 的文件档 (document)、以及其他与 SAMBA 相关的 logrotate 设定档及开机预设选项档案等；

    • samba-common：
      这个套件则主要提供了 SAMBA 的主要设定档 (smb.conf) 、 smb.conf 语法检验的测试程式 (testparm)等等；

    • samba-client：
      这个套件则提供了当 Linux 做为 SAMBA Client 端时，所需要的工具指令，例如挂载 SAMBA 档案格式的执行档 smbmount 等等。
    这三个套件你都得要安装才行喔！如果尚未安装的话，看是要由原版光碟去安装，还是使用 yum 都可以啦！ 安装完毕之后，你可以依序察看一下 Samba 的套件结构喔！与他相关的档案基本上有这些东西：
    • /etc/samba/smb.conf：
      smb.conf 是 Samba 的主要设定档名，如果你的 distribution 的 SAMBA 设定档不在 /etc/samba/ 目录当中， 那么你应该使用 locate 或 find 等方式将他找出来就好啦。基本上，咱们的 Samba 就仅有这个设定档而已， 且这个设定档本身就是很详细的说明文件了，请用 vi 去查阅他吧！这个档案主要在设定工作群组、 NetBIOS 名称以及分享的目录等相关设定，我们后续要介绍的都是这个档案而已啦！

    • /etc/samba/lmhosts：
      这个档案的主要目的在对应 NetBIOS name 与该主机名称的 IP ，事实上他有点像是 /etc/hosts 的功能！只不过这个 lmhosts 对应的主机名称是 NetBIOS name 喔！不要跟 /etc/hosts 搞混了！由于目前 SAMBA 的功能越来越强大，所以通常只要您一启动 SAMBA 时，他就能自己捉到 LAN 里面的相关电脑的 NetBIOS name 对应 IP 的资讯，因此这个档案通常可以不用设定了！

    • /etc/samba/smbpasswd：
      这个档案预设并不存在啦！他是 SAMBA 预设的使用者密码对应表。当我们设定的 SAMBA 伺服器是较为严密的，需要使用者输入帐号与密码后才能登入的状态时，使用者的密码预设就是放置在这里咯 (当然啰，您可以自行在 smb.conf 里面设定密码放置的地方及密码档名， 不过我们这里都以预设的状态来说明) 。比较需要注意的是，这个档案因为包含了使用者的密码， 当然权限方面要较为注意啦！这个档案的拥有者需要是 root ，且权限设定为 600 才行喔！

    • /etc/samba/smbusers：
      由于 Windows 与 Unix-like 在管理员与访客的帐号名称不一致，分别为 administrator 及 root， 为了对应这两者之间的帐号关系，可以使用这个档案来设定。不过这个档案的使用必须要经由 smb.conf 内的‘ username map ’设定项目来启动才行。

    • testparm：
      这个指令主要在检验 samba 设定档 smb.conf 的语法正确与否，当你编辑过 smb.conf 时，请务必使用这个指令来检查一次， 避免因为打字错误引起的困扰啊！

    • smbd, nmbd：
      前几个小节曾经提过的两个主要 daemon 就在这里！

    • smbstatus：
      列出目前的 SMB server 的状态，也是很有用途的一个指令啦！

    • smbpasswd：
      如果您的 SAMBA 设定的较为严格，需要规定使用者的帐号与密码，那么那个密码档案的建立就需要使用 smbpasswd 来建置才可以的喔！所以这个指令与建立 SAMBA 的密码有关咯！

    • smbclient：
      当你的 Linux 主机想要藉由‘网路上的芳邻’的功能来查看别台电脑所分享出来的目录与装置时，就可以使用 smbclient 来查看啦！这个指令也可以使用在自己的 SAMBA 主机上面，用来查看是否设定成功哩！

    • smbmount：
      在 Windows 上面我们可以设定‘网路磁碟机’来连接到自己的主机上面，同样的，在 Linux 上面，我们可以透过 smbmount 来将远端主机分享的档案与目录挂载到自己的 Linux 主机上面哪！不过，其实我们也可以直接使用 mount 这个指令来进行同样的功能就是了。

    • nmblookup：
      有点类似 nslookup 啦！重点在查出 NetBIOS name 就是了。

    • smbtree：
      这玩意就有点像 Windows 系统的网路上的芳邻显示的结果，可以显示类似‘靠近我的电脑’之类的资料， 能够查到工作群组与电脑名称的树状目录分布图，有趣吧！

    • /usr/share/doc/samba-<版本>：
      这个目录包含了 SAMBA 的所有相关的技术手册喔！也就是说，当您安装好了 SAMBA 之后，您的系统里面就已经含有相当丰富而完整的 SAMBA 使用手册了！值得高兴吧！ ^_^，所以，赶紧自行参考喔！
    大致的套件结构就是这样，底下就准备来讲一个简单的案例吧！ ^_^

    小标题的图示 基础设定流程与 smb.conf 的主要规划
    既然 Samba 是要加入 Windows 的网芳当中，所以他的设定方式应该是要与网芳差不多才是。所以我们先来聊一聊 Windows 的一些设定方法再说。在早期 Windows 的网芳设定真是很简单，不过也因为太简单， 所以产生的安全问题可是相当的麻烦的。后来在 Windows XP 的 sp2 (服务包第二版) 加入了很多的预设防火墙机制， 因此使用网芳的预设限制常常会是这样的：
    • 主机与主机之间必须要在同一个网域当中 (否则需要修改 Windows 预设防火墙)；
    • 最好设定为同一工作群组；
    • 主机的名称不可相同 (NetBIOS name)；
    • 专业版 Windows XP 最多仅能提供同时十个用户连线到网芳。
    当你的 Windows 主机群符合上述的条件后，就很容易处理网芳分享的工作啦！分享的步骤是这样的：
    1. 叫出档案总管，然后在要分享的目录、磁碟或装置 (如印表机) 上面按下右键，选择‘共用’，然后就能够设定好分享的资料了；
    2. 最好建立一组给用户使用的帐号与密码，让其他主机的使用者可以透过该帐号密码连线进入网芳；
    真是有够简单的！那么 Samba 怎么设定啊？也是很简单，依据上述的限制以及流程你可以这样想像：
    1. 在 smb.conf 当中设定好工作群组、NetBIOS 主机名、密码使用状态等等与主机相关的资讯；
    2. 在 smb.conf 内设定好预计要分享的目录或装置以及可供使用的使用者资料；
    3. 根据步骤 2 的设定，在 Linux 档案系统当中建立好分享出去的档案或装置的使用权限；
    4. 根据步骤 2 的设定，以 smbpasswd 建立起使用者的帐号及密码
    5. 启动 Samba 的 smbd, nmbd 服务，开始运转哩！
    瞧！根据上面的流程，其实我们最需要知道的就是 smb.conf 这个设定档的资讯就是了。 所以首先我们就要来介绍一下这个档案的设定方式啰！这个档案其实可以分为两部份来看， 一个是主机资讯部分，在 smb.conf 当中以 [global] 作为设定的依据；另一个则是分享的资讯， 以个别的目录名称为依据。你要先知道的是：在 smb.conf 当中， 井字号与分号 (# 跟 ;) 都是注解符号！底下咱们就来谈谈这个咚咚吧！

  • 主机整体参数
    • 在 smb.conf 这个设定档当中的设定有点像底下这样：
    # 会有很多加上 # 或 ; 的注解说明，你也可以自行加上来提醒自己相关设定
[global]
   参数项目 = 设定内容
   ....

[分享资源名称]
   参数项目 = 设定内容
   ....
    在 global 当中的就是一些主机的整体参数了，包括工作群组、主机的 NetBIOS 名称、字元编码的显示、登录档的设定、 是否使用密码以及使用密码验证的机制等等，都是在这个 [global] 项目中设定的。至于 [分享资源名称] 则是针对你开放的目录来进权限方面的设定，包括谁可以浏览该目录、是否可以读写等等参数。 在 [global] 部分关于主机名称资讯方面的参数主要有：
    • workgroup = 工作群组的名称：注意，主机群要相同；
    • netbios name = 主机的 NetBIOS 名称啊，每部主机均不同；
    • server string = 主机的简易说明，这个随便写即可。
    另外，过去常常让使用者心生不满的语系显示问题方面，您务必要清楚的知道的是， SAMBA 主机上面的资料 (例如 mount 磁碟分割槽的参数以及原本的资料编码), SAMBA 伺服器显示的语系, Windows 用户端显示的语系, Windows 用户端连上 SAMBA 的软体 都需要符合设定值才行！ 在新版的 3.x 上面有数个提供这些语系转换的设定喔，如下所示：
    • display charset = 自己伺服器上面的显示编码， 例如你在终端机时所查阅的编码资讯。一般来说，与底下的 unix charset 会相同。
    • unix charset = 在 Linux 伺服器上面所使用的编码，一般来说就是 i18n 的编码啰！ 所以你必须要参考 /etc/sysconfig/i18n 内的‘预设’编码。
    • dos charset = 就是 Windows 用户端的编码了！ 一般来说我们的繁体中文 Windows 使用的是 big5 编码，这个编码在 Samba 内的格式被称为‘ cp950 ’喔！
    关于语系编码，建议您参考一下讨论区的这一篇：
      http://phorum.vbird.org/viewtopic.htm?t=22001
    我们的网友 eyesblue 写得太好了！所以建议大家直接前往查阅即可！除此之外，还有登录档方面的资讯， 包括这些参数：
    • log file = 登录档放置的档案，档名可能会使用变数处理；
    • max log size = 登录档最大仅能到多少 Kbytes ，若大于该数字，则会被 rotate 掉。
    还有跟密码有关的参数，包括这几个：
    • security = user, server, domain, share 四选一，这四个设定值分别代表：
      • user ：使用 SAMBA 本身的密码资料库，密码资料库与底下的 smb passwd file 有关；
      • share：分享的资料不需要密码即可分享；
      • server, domain：使用外部主机的密码，亦即 SAMBA 是用户端之意，如果设定这个项目， 你还得要提供‘password server = IP’的设定值才行；
    • encrypt passwords = Yes 代表密码要加密，注意那个 passwords 要有 s 才对！
    • smb passwd file = 密码放置的档案，通常是 /etc/samba/smbpasswd 。
    事实上 Samba 的密码方面设定值很多喔，包括你还可以利用 samba 来修改 /etc/passwd 里头的人物的密码呢！ 不过这个时候就得需要‘ unix password sync ’以及‘ passwd program ’这两个参数值的帮忙了。 我们这里先谈比较简单的，其他进阶的部分可以 man smb.conf 去进行搜寻查阅喔！ ^_^

  • 分享目录参数
    • 在目录参数部分，主要有底下这几个常见的参数喔：
    • [分享名称] ：这个分享名称很重要，他是一个‘代号’而已。 举例来说，你在 Windows 当中使用‘共用’来分享网芳时，假设你将‘D:\game’分享出来， 系统不是还会要你输入一个‘在网路上面的名称’吗？假设你输入‘My_Games’这个名称好了， 那么未来大家在网芳看到的这个资料夹 (D:\game) 名称其实是‘\\你的IP\My_Games’啦！
    • comment ：这个目录的说明！
    • path ：在网芳中显示的名称 [分享名称] 中，所实际进入的 Linux 档案系统。 也就是说，在网芳当中看到的是 [分享] 的名称，而实际操作的档案系统则是在 path 里头所设定的。
    • read only：是否唯读？
    • public ：是否让所有可以登入的使用者看到这个项目？
    • writable ：是否可以写入？这里需要注意一下喔！那个 read only 与 writable 不是两个蛮相似的设定值吗？如果 writable 在这里设定为 no ，亦即不可写入，那跟 read only 不就互相抵触了！那个才是正确的设定？答案是：最后出现的那个设定值为主要的设定！
    • create mode 与 directory mode 都与权限有关的咯！
    • valid users = 使用者，这个项目可以指定能够进入到此资源的特定使用者。
    因为分享的资源主要与 Linux 系统的档案权限有关，因此里头的设定参数多与权限有关。

  • 变数特性
    • 为了简化设定值，Samba 提供很多不同的变数给我们来使用，主要有底下这几个变数喔：
    • %S：取代目前的设定项目值，所谓的‘设定项目值’就是在 [分享] 里面的内容！ 举例来说，例如底下的设定范例：
      [homes]
   valid users = %S
   ....
      因为 valid users 是允许的登入者，设定为 %S 表示任何可登入的使用者都能够登入的意思～今天如果 dmtsai 这个使用者登入之后，那个 [homes] 就会自动的变成了 [dmtsai] 了！这样可以明白了吗？ %S 的用意就是在替换掉目前 [ ] 里面的内容啦！

    • %m：代表 Client 端的 NetBIOS 主机名称喔！
    • %M：代表 Client 端的 Internet 主机名称喔！就是 HOSTNAME。
    • %L：代表 SAMBA 主机的 NetBIOS 主机名称。
    • %H：代表使用者的家目录。
    • %U：代表目前登入的使用者的使用者名称
    • %g：代表登入的使用者的群组名称。
    • %h：代表目前这部 SAMBA 主机的 HOSTNAME 喔！注意是 hostname 不是 NetBIOS name 喔！
    • %I：代表 Client 的 IP 咯。
    • %T：代表目前的日期与时间
    至于相关的变数运用，我们会在底下的设定当中略做介绍喔！

    以上就是在 smb.conf 上头常看到的几种设定项目，相信初次接触 Samba 的朋友，看到上头写的资料肯定是一头雾水的！ 我们底下用几个小范例来实际的介绍 smb.conf 的设定后，您就会知道这些参数如何应用了！ 记得，看完底下的下范例后，要回来再将这些参数的意义瞧一瞧， 而且若有其他额外的参数须知，务必自行 man smb.conf 喔！重要的很！

    小标题的图示 没有密码的 smb.conf 设定(纯测试)
    瞎密？不需要密码就能够使用 SAMBA 主机所提供的目录资源？真假？没错啦，可以达到的。 不过，因为不需要密码就能够登入，虽然你可以设定权限成为唯读，让使用者可以‘瞧瞧而已’， 但是毕竟比较危险，因为如果你不小心将重要资料放置到该分享的目录当中，岂不危险？ 所以尽量不要这样设定。不过，我们还是得介绍一下啦！先说明一下我们的设定需求：

  • 主机预计设定的参数状况：
    • 在 LAN 内所有的网芳主机工作群组 (workgroup) 为： vbirdhouse
    • 这部 Linux 主机 (Samba 服务) 的 NetBIOS 名称为： vbirdserver
    • 使用者登入层级设定为： share
    • 仅分享 /tmp 这个目录而已，且取名为： temp
    • Linux 主机的编码格式假设为万国码 (Unicode, 亦即 utf8)
    • 用户端为中文 Windows ，在用户端的软体也使用 big5 的编码
    底下就开始依序来进行 samba 的设定吧！

  • 1. 设定 lmhosts 档案内容 (optional)：
    • 我们前面谈到 NetBIOS 名称可以由广播的方式自动取得，而 NetBIOS 也可以透过区域网路内经由一部主控电脑来管理， 此外，你也可以利用自己主机当中的 lmhosts 这个设定档来进行 NetBIOS 与 IP 的对应， 让 NetBIOS 与 TCP/IP 可以对应上关系呐！一般来说，这个档案是可以不必设定的，因为可以经由广播的方式取得对应的嘛！ 不过，某些时刻确实可以设定一下，免除一些额外的搜寻时间说。我的区网中电脑名称与 IP 是这样的：
    [root@linux ~]# vi /etc/samba/lmhosts
127.0.0.1       localhost
192.168.1.254   vbirdserver
192.168.1.21    vbirdcpu2
192.168.1.11    vbirdcpu1
# 这个档案的内容很简单，与 /etc/hosts 很类似，左边是 IP 右边是主机名称。
# 只是主机名称必须符合 NetBIOS name 的标准，包括：
# 主机名称不要超过 15 个字元，不要含有特殊字元等等。
# 亦可使用 man lmhosts 来查阅喔！
    鸟哥区网内常用的有三部主机，除了 Linux 这部机器外，还有两部个人电脑，我将这几部电脑的 NetBIOS name 写到这个档案当中，可以免除 Samba 自己去搜寻啰！而再次强调，这个名称是 NetBIOS name 而非 HOSTNAME 喔！
  • 2. 检查语系资料
    • 过去朋友们在进行 SAMBA 的设定时，最容易发生错误的地方就是在中文档名部分， 绝大部分的朋友只要使用了中文档名，常常会发生一些问题，就是无法顺利的上传下载， 或者是原先的中文档名上传后，却变成奇怪的乱码档名。

    为了解决这个问题，你必须要知道几个项目：
    • 原始档案 (你要分享的档案) 编码的格式为何？一般来说，中文 Windows 的编码预设为 Big5 ；
    • 这个档案放置在 Linux 上，则这部 Linux 的预设语系编码为何？这与 /etc/sysconfig/i18n 有关；
    • 在 Samba 上头的显示编码为何？一般来说与上述的 Linux 预设编码相同即可；
    • 在用户端连接到 Samba 主机的软体之语系编码为何？如果是中文 Windows 作业系统，预设为 Big5。
    你的语系资料必须要在上面这几个环境中进行转换，因此如果你的用户端连上 Samba 的软体编码为 Big5 ， 你的 Samba 使用的语系也是 Big5 ，但是 Linux 主机却预设仅支援 utf8 的编码时，而你的 smb.conf 又没有设定好，此时资料传输就会发生一些错误，因此你就会看到很多乱码档名了。

    所以，你至少得要知道你的 Linux 语系编码为何？在 Red Hat 系统 (含我们的 CentOS) 可以查阅 /etc/sysconfig/i18n 这个档案， 如下所示为鸟哥的 i18n ：
    [root@linux ~]# cat /etc/sysconfig/i18n
LANG="en_US.UTF-8"  <==这才是你需要注意的地方！
SUPPORTED="zh_HK.UTF-8:zh_HK:zh:zh_CN.UTF-8:zh_CN:zh:zh_SG.UTF-8:
zh_SG:zh:zh_TW.UTF-8:zh_TW:zh:en_US.UTF-8:en_US:en"
SYSFONT="latarcyrheb-sun16"
    由上头看起来，鸟哥预设的语系编码为 en_US.UTF-8，不过尚有支援 zh_TW 这样的中文编码。 先假设鸟哥的编码为万国码 (Unicode) 好了。知道了之后就能够开始处理 smb.conf 啰！

  • 3. 设定 smb.conf 设定档
    • 在这个例子当中我们仅分享 /tmp 这个目录而已，而且假设这个分享出来的目录是可读写的， 另外，我们并没有分享印表机喔！而在 smb.conf 当中的注解符号可以是‘ # ’也可以是‘ ; ’喔！要注意！
    [root@linux ~]# cd /etc/samba
[root@linux samba]# cp smb.conf smb.conf.raw  <==先备份再说！
[root@linux samba]# vi smb.conf
# 先设定好主机方面的参数
[global]
        # 与主机名称有关的设定资讯
        workgroup     = vbirdhouse
        netbios name  = vbirdserver
        server string = This is vbird's samba server

        # 与语系方面有关的设定项目喔，为何如此设定请参考前面的说明
        unix charset    = utf8
        display charset = utf8
        dos charset     = cp950

        # 与登录档有关的设定项目，注意变数 (%m)
        log file = /var/log/samba/%m.log
        max log size = 50

        # 这里才是与密码有关的设定项目哩！
        security = share

        # 其他预设存在的项目
        socket options = TCP_NODELAY SO_RCVBUF=8192 SO_SNDBUF=8192
        dns proxy = no
        template shell = /bin/false
        winbind use default domain = no

# 底下则是针对 /tmp 的设定而来的！可浏览且可写入喔！
[temp]
        comment   = Temporary file space
        path      = /tmp
        read only = no
        public    = yes
    请您特别留意，在原本的 smb.conf 上面就已经有很多预设值了，这些预设值如果你不知道他的用途， 尽量保留预设值，也可以使用 man smb.conf 去查询该预设值的意义。举例来说， CentOS 4.x 的 smb.conf 预设有针对 server/client 的封包传递项目设定值的 socket options ，也有针对 Windows NT 及 Unix 系统的帐号对应之 idmap uid 之类的设定值，这些设定值在大型的区网架构会使用到，在我们仅有一两部 Linux samba 伺服器的环境下.... 应该是可以不予理会的啦！

  • 4. 用 testparm 查阅 smb.conf 的语法设定正确性
    • 在启动 samba 之前，我们务必要了解到 smb.conf 里面语法是否正确，检验的方式使用 testparm 这个指令即可。 测试方式如下：
    [root@linux ~]# testparm
参数：
-v ：查阅完整的参数设定，连同预设值也会显示出来喔！

[root@linux ~]# testparm
Load smb config files from /etc/samba/smb.conf
Processing section "[temp]"   <==这个地方可以仔细看看，如果有问题会在这边显示
Loaded services file OK.
Server role: ROLE_STANDALONE
Press enter to see a dump of your service definitions <==请按 [Enter] 按键

# Global parameters
[global]
        dos charset = cp950
        display charset = utf8
        workgroup = VBIRDHOUSE
        netbios name = VBIRDSERVER
        server string = This is vbird's samba server
        security = SHARE
        log file = /var/log/samba/%m.log
        max log size = 50
        socket options = TCP_NODELAY SO_RCVBUF=8192 SO_SNDBUF=8192
        dns proxy = No

[temp]
        comment = Temporary file space
        path = /tmp
        read only = No
        guest ok = Yes
    上头是语法验证与各个项目的列出，如果你下达 testparm 却出现如下画面那就是有问题：
    Unknown parameter encountered: "linux charset" <==错误的设定
Ignoring unknown parameter "linux charset"
Processing section "[temp]"
Loaded services file OK.
Server role: ROLE_STANDALONE
Press enter to see a dump of your service definitions
    如果发现上述的错误，这表示你的 smb.conf 有个 linux charset 的设定参数，不过 smb.conf 其实是不支援这个参数的。 可能的问题是 samba 2.x 与 samba 3.x 有一些项目的支援已经不存在了，所以你使用旧版的 2.x 设定档来 3.x 上头执行时，就会出现问题。此外，‘打字错误’也是很常见的一个问题呐！赶紧测试一下语法先， 然后根据 smb.conf 有的项目去进行修改吧。

    如果你想要了解 samba 的所有设定 (包括没有在 smb.conf 里头设定的预设值)，可以使用 testparm -v 来作详细的输出， 资料相当的丰富，透过这个您也可以知道你的主机环境设定为何呢！ ^_^

  • 5. 启动与观察
    • 启动实在太简单了，利用预设的 CentOS 启动方式来处理即可。
    [root@linux ~]# /etc/init.d/smb start
[root@linux ~]# netstat -tlunp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address      Foreign Address  State   PID/Program name
tcp        0      0 0.0.0.0:139        0.0.0.0:*        LISTEN  10338/smbd
tcp        0      0 0.0.0.0:445        0.0.0.0:*        LISTEN  10338/smbd
udp        0      0 192.168.1.254:137  0.0.0.0:*                10343/nmbd
udp        0      0 0.0.0.0:137        0.0.0.0:*                10343/nmbd
udp        0      0 192.168.1.254:138  0.0.0.0:*                10343/nmbd
udp        0      0 0.0.0.0:138        0.0.0.0:*                10343/nmbd
    特别注意，在 Samba (网芳) 当中预设会启动多个埠口，这包括资料传输的 TCP 埠口 (139, 445)， 以及进行 NetBIOS 名称解析之类工作的 UDP 埠口 (137, 138)，所以你才会看到很多资料的。 那么能否仅支援 139 这个必要的埠口，关闭 445 呢？可以啊～透过 testparm -v 的观察， 可以发现‘ smb ports = 445 139 ’这个设定值指定两个埠口的，因此你可以在 smb.conf 增加这个设定值， 并改为 smb ports = 139 即可。不过，建议先保留预设值啦！

  • 6. 用户端的观察
    • 关于用户端的观察我们会在后续进行介绍。在这里仅是说明如何确定我们的 Samba 设定与服务有顺利的在运作。 我们可以在本机上透过 smbclient 这支程式来处理，他的基本语法是这样的：
    [root@linux ~]# smbclient -L [//主机或IP] [-U 使用者帐号]
参数：
-L ：仅查阅后面接的主机所提供分享的目录资源；
-U ：以后面接的这个帐号来尝试取得该主机的可使用资源
    由于在这个范例当中我们并没有规范使用者的安全等级，所以必须要使用 -U 这个参数。 因此你可以这样看看：
    [root@linux ~]# smbclient -L //127.0.0.1
Password:  <==这里按一下 [Enter] 吧！
Domain=[VBIRDHOUSE] OS=[Unix] Server=[Samba 3.0.10-1.4E.9]

    Sharename   Type  Comment
    ---------   ----  -------
    temp        Disk  Temporary file space
    IPC$        IPC   IPC Service (This is vbird's samba server)
    ADMIN$      IPC   IPC Service (This is vbird's samba server)
Domain=[VBIRDHOUSE] OS=[Unix] Server=[Samba 3.0.10-1.4E.9]

    Server           Comment
    ---------        -------
    VBIRDSERVER      This is vbird's samba server

    Workgroup        Master
    ---------        -------
    VBIRDHOUSE       VBIRDSERVER
    上表输出的资讯当中，分享的目录资源 (Sharename) 就是在 smb.conf 当中设定的 [temp] 名称啰！ 因此在这里的意思是：任何人都可以进入 //127.0.0.1/temp 这个目录当中， 而这个目录在 Linux 系统其实是 /tmp 目录。至于那个 IPC$ 及 ADMIN$ 则是为了要应付 Windows 环境所必须要存在的项目就是了。

    基本上，到此为止咱们就设定好一个简单的不需要密码即可登入的 Samba 主机了！ 你可以先行到用户端软体功能的部分进行挂载测试。 底下我们则预计以简易的需要密码才能够登入 Samba 的方式来设计一个范例吧！

    小标题的图示 安全等级为使用者的工作群组设定
    设定一部不需密码即可登入的 Samba server 是非常简单的，不过， 您总不希望某些有机密性质的资料放在不设防的网芳中让大家查阅吧？ 举例来说，你总不希望你的家目录被人家随意浏览吧？家目录内可能有你自己的情书呢！^_^

    那怎么办？没关系，我们可以透过 Samba 主机提供的认证方式来进行使用者权限的给予， 也就是说，你在用户端连线到主机时，必须要输入正确的帐号与密码后，才能够登入 Samba 主机查阅到你自己的资料！ 那会不会很难啊？不会啦！ Samba 本身就提供一个小程式来帮助我们处理密码的建立了， 整个流程还不太难。比较重要的是Samba 使用者帐号必须要存在于 Linux 系统当中 (/etc/passwd)， 但是 Samba 的密码与 Unix 的密码档案并不相同。这就比较有点小麻烦～ 没关系，就让我们依样画葫芦来处理一下这个部分的设定吧！

  • 主机预计分享的资源状态
    • 刚刚前一个免密码时的 smb.conf 设定继续保留；
    • 针对 NetBIOS name 的解析方式依序由 lmhosts, broadcast 及 host 来进行解析；
    • 安全等级提升为 user 等级；
    • 密码档案放置到 /etc/samba/smbpasswd 这个档案当中；
    • 密码必须要加密；
    • 每个可使用 samba 的使用者拥有自己的家目录之外， users 这个群组的使用者可以进入 /home/public 目录中， 且在该目录下 users 这个群组的所有人可具有写入的权限喔！
    好了，开始一步步的处理吧！

  • 1. 设定 lmhosts
    • 这部分与前一小节的设定相同，请自行前往查阅喔！

  • 2. 开始设定 smb.conf 档案
    • 在这个范例的设定档当中，我们会新增几个参数，新增的参数部分会用特殊字体圈起来， 引用之前参数的部分则为一般字体。请交互参考看看啰：
    [root@linux ~]# vi /etc/samba/smb.conf
[global]
        workgroup     = vbirdhouse
        netbios name  = vbirdserver
        server string = This is vbird's samba server
        unix charset    = utf8
        display charset = utf8
        dos charset     = cp950
        log file = /var/log/samba/%m.log
        max log size = 50
        socket options = TCP_NODELAY SO_RCVBUF=8192 SO_SNDBUF=8192
        dns proxy = no
        template shell = /bin/false
        winbind use default domain = no

        # 与密码有关的设定项目，包括密码档案所在与加密与否喔！
        security = user
        encrypt passwords = yes
        smb passwd file = /etc/samba/smbpasswd

        # 与 NetBIOS name 名称解析有关的设定
        name resolve order = lmhosts bcast host

# 新增的每个使用者家目录及群组用户哩！
[homes]
        comment = Home directories
        browseable = no
        writable = yes
        valid users = %S
        create mode = 0664
        directory mode = 0775
[public]
        comment = the user groups work directory
        path = /home/public
        public = yes
        writable = yes
        valid users = @users
[temp]
        comment   = Temporary file space
        path      = /tmp
        read only = no
        public    = yes
    [global] 部分
    在新增的资料部分，主要是与密码档案有关啦！包括安全等级设定为使用本机的密码验证，亦即是‘ security = user ’ 那个项目，而且加上了密码加密。至于 Samba 使用的密码档预设就是 /etc/samba/smbpasswd 这个， 为了增加自己的记忆，干脆直接写到 smb.conf 当中即可。

    至于那个‘ name resolve order ’就有趣了！他说明的是‘这部 Samba 主机针对 NetBIOS name 的解析方式’， 主要的解析方式有几种：
    • lmhosts：直接以 lmhosts 这个档案的内容来对照；
    • wins：利用一部可管理 Windows 网芳的主控电脑来纪录，本 Samba 主机向该部主机 (wins server) 要求 NetBIOS 名称解析结果；
    • host：透过 /etc/hosts 或者是 NIS, DNS 等方式来处理 NetBIOS name 的结果；
    • bcast：在区网中直接透过 NetBIOS 的广播功能处理，亦即是向所有 Samba 主机介面的同一网域主机发出名称解析的需求， 举例来说咱们的 Samba 主机为 192.168.1.254/24 ，则以 bcast 解析 NetBIOS name 时，我们的伺服器会主动向 192.168.1.0/24 发送出解析封包的要求啊。
    我们修改了预设值，让 Samba 仅透过 lmhosts, bcast 及 host 的方式进行主机名称的解析啊！

    [homes] 部分
    至于新增的目录方面，[homes] 是个比较特殊的分享名称，他代表 Linux 主机上头的使用者家目录。 我们知道 [homes] 代表的是分享目录的资源名称， 但你总不希望使用 Samba 时找到的资源分享名称为 //127.0.0.1/homes 吧？ 所以才会有‘ valid users = %S ’这个设定值，那个 %S 代表拥有可登入 Samba 的所有使用者， 且当他登入后，那个 [homes] 会变成 [帐号] ， 请至前一小节的变数部分查询相关的说明。而且使用者的家目录是除了使用者本人外， 并不会开放给其他人浏览的喔 (browseable = no)，另外他的 umask 为 002，因为建立新档 (create mode) 预设权限为 0664 ，而建立新目录 (directory mode) 则为 0775 之故。

    [public] 部分
    另一个新增的分享资源比较有趣，我们命名为 [public] ，指向的目录为 /home/public ， 有趣的地方在于使用的 valid users = @users 这个设定项目，加上 @ 之后的名称代表着群组之意，意思是说，在 Linux 主机上面可使用 Samba 的帐号中，只要该帐号支援 users 这个群组， 那么理论上他就能够进入 /home/public 目录进行存取的权限。不过能否顺利的存取档案还与 Linux 最底层的档案权限有关。且任何人均可查阅到我们的主机有提供 [public] 这个分享资源 (public = yes 之故)。

    例题：
    在上面的这个设定档当中有提到分享出 /home/public 这个目录， 请问这个目录的权限应该如何设定才是符合我们 Samba 案例的要求？
    答：
      在这个案例当中我们提到任何具有 users 群组的使用者都能够完整的存取 /home/public ， 所以这个目录的群组应该属于 users ，且权限至少需为 770 才行。如果 /home/public 预设不存在时， 应该要如此建立：
      [root@linux ~]# mkdir /home/public
[root@linux ~]# chgrp users /home/public
[root@linux ~]# chmod 770 /home/public
      这样当属于 users 群组的使用者进入到此目录后，才能够进行读写的功能。

  • 3. 设定可使用 Samba 的帐号与密码
    • 设定使用者帐号是很重要的一环，因为设定错误的话，当然也就任何人都没有办法登入的！ 在这里我们必须先要说明一下 Linux 的档案系统与 SAMBA 设定的使用者登入权限的相关性！
    • 在 Linux 这个系统下，任何程序都需要取得 UID 与 GID (User ID 与 Group ID) 的身份之后，才能够拥有该身份的权限，也才能够适当的进行存取档案等动作！

    • 关于 Linux 这个系统的 UID 与 GID 与帐号的相对关系，一般记录在 /etc/passwd 当中，当然也能透过 NIS, ldap 等方式来取对应；

    • SAMBA 仅只是 Linux 底下的一套软体，使用 SAMBA 来进行 Linux 档案系统时，还是需要以 Linux 系统下的 UID 与 GID 为准则！
    如果上面这几点说明您没有问题了，现在就来看一下当我们在 Windows 电脑上面以网路上的芳邻来连接 Linux 并且进行资料的存取时，会是怎样的一个情况呢？
      我们需要透过 SAMBA 所提供的功能来进行 Linux 的存取，而 Linux 的存取是需要取得 Linux 系统上面的 UID 与 GID 的，因此，我们登入 SAMBA 主机时，所利用 SAMBA 取得的其实是 Linux 系统里面的相关帐号！这也就是说，在 SAMBA 上面的使用者帐号，必须要是 Linux 帐号中的一个！
    所以说，在不考虑 NIS 或 LDAP 等其他帐号的验证方式，单纯以 Linux 本机帐号 (/etc/passwd) 作为身份验证时， 在 Samba 主机所提供可登入的帐号名称，必须要存在于 /etc/passwd 当中！ 这是一个很重要的概念！例如你要先有 dmtsai 在 /etc/passwd 当中后，才能将 dmtsai 加入 Samba 的使用者当中。这都是很基本的帐号权限概念，如果您觉得这里阅读方面有问题， 若不考虑鸟哥的解释不良，表示你必须要回去读读基础篇了～ ^_^

    好了，假设我的机器里面已经有 dmtsai, nikky, tang 等三人，不过我只想要让 dmtsai 及 nikky 使用 SAMBA 而已的话， 那么如何将这两个使用者加入帐号密码管理档案 /etc/samba/smbpasswd 当中呢？很简单的啦！这样做即可：
    1. 先确认密码档是否存在
[root@linux ~]# ls -l /etc/samba/smbpasswd
-rw-------  1 root root 104 Dec 25 23:13 /etc/samba/smbpasswd
# 注意啊！要这样的权限才可以喔！如果你的 Linux 没有这个档案，请自行建立。

2. smbpasswd 指令功能
[root@linux ~]# smbpasswd [-adem] username
参数说明：
   : 如果都没有加上任何一个参数，例如‘ smbpasswd dmtsai ’时，这表示：
     修改 SAMBA 密码档 (/etc/samba/smbpasswd) 里面的 dmtsai 这个帐号的密码！
     也就是说，密码档里面已经存在一个 dmtsai 的帐号了！
-a : 在 smbpasswd 密码档里面新增一个使用者
-d : 让在 smbpasswd 密码档里面的某个帐号的使用者暂时无法使用 SAMBA
     当多了 -d 的参数时，在 smbpasswd 里面某个栏位会多出一个 D 的参数，
     代表该帐号目前无法使用喔！
-e : 与 -d 参数相反，让某个帐号恢复使用！
-m : 该 username 为机器代码 (Machine Account)，这个与 domain model 有关！

2.1 开始新增使用者吧！
[root@linux ~]# smbpasswd -a dmtsai
New SMB password: <==在这里输入密码！这个密码不一定要与 /etc/shadow 相同
Retype new SMB password: <==再输入一次
Added user dmtsai.

[root@linux ~]# cat /etc/samba/smbpasswd
dmtsai:501:1B0F61E20F8F2D11AAD3B435B51404EE:F7EDDB3F55CC5DB1FE00D7F755028491:
[U          ]:LCT-4590969D:
# 上面的资料为同一行的资料喔！资料为加密过的！

2.2 如果要暂时拒绝一个使用者的登入，可以这样做：
[root@linux ~]# smbpasswd -d dmtsai
[root@linux ~]# cat /etc/samba/smbpasswd
dmtsai:501:1B0F61E20F8F2D11AAD3B435B51404EE:F7EDDB3F55CC5DB1FE00D7F755028491:
[DU         ]:LCT-4590969D:
# 就是这个 D ！代表的就是暂时 disable 啰！
[root@linux ~]# smbpasswd -e dmtsai
    接下来你可以透过相同的方式来新增 nikky 这个使用者的 Samba 密码，那这两个人就能够使用 Samba 啰。 然后我们就能够开始准备来重新启动 Samba 并且测试看看啰！

  • 4. 重新启动 Samba 并测试
    • 在经过重新启动后，我们所进行的修订才会生效。然后使用 smbclient 来检查看看，是否不同身份会有不一样的浏览结果呢？ 赶紧看看：
    [root@linux ~]# testparm
# 这个动作很重要！每次都要进行！确认你的语法无误后再开始！

[root@linux ~]# /etc/init.d/smb restart

[root@linux ~]# smbclient -L //127.0.0.1
Password:                   <==直接按下 [Enter] 即可。
Anonymous login successful  <==是匿名登入喔！
Domain=[VBIRDHOUSE] OS=[Unix] Server=[Samba 3.0.10-1.4E.9]

    Sharename   Type  Comment
    ---------   ----  -------
    public      Disk  the user groups work directory
    temp        Disk  Temporary file space
    IPC$        IPC   IPC Service (This is vbird's samba server)
    ADMIN$      IPC   IPC Service (This is vbird's samba server)

[root@linux ~]# smbclient -L //127.0.0.1 -U dmtsai
Password: <==输入 dmtsai 在 smbpasswd 档案中所建立的密码喔！
Domain=[VBIRDSERVER] OS=[Unix] Server=[Samba 3.0.10-1.4E.9]

    Sharename   Type  Comment
    ---------   ----  -------
    public      Disk  the user groups work directory
    temp        Disk  Temporary file space
    IPC$        IPC   IPC Service (This is vbird's samba server)
    ADMIN$      IPC   IPC Service (This is vbird's samba server)
    dmtsai      Disk  Home directories
    由上表我们可以发现，经由不同的身份登入可以取得不一样的浏览资料， 所以在使用上面需要特别留意喔！

  • 5. 关于权限的再说明
    • 有的时候你会发现，明明在 smb.conf 当中已经设定了 writable 可写入，使用者登入的身份也没有问题， 为啥就是无法写入呢？是否是伺服器设定哪里还有问题啊？非也非也！主要的问题常常是来自于 Linux 档案系统的权限啦！

    举上面的例子来说好了，我们在 smb.conf 当中设定 [public] 为可写入，亦即 /home/public 是可写入的。 假设 dmtsai 属于 users 这个群组，因此以 dmtsai 登入 SAMBA 伺服器后，对于 /home/public 应该是具有可以读写的能力的！但是，如果你以 root 的身份建立 /home/public 却又忘记修改权限的话， 此时 /home/public 是无法让 users 这个群组写入的，因此 dmtsai 这个使用者当然不具有写入的能力。 这样说，了解鸟哥想要说啥了吗？注意注意喔！ ^_^

    上面的设定案例应该蛮足以提供一般家庭用的环境中进行设定了！如果您还要扩充分享的目录与能够登入的使用者， 可以这样做：
    • 利用编辑 smb.conf 来多开放其他的目录，并且特别注意 Linux 在该目录下的权限喔！请使用 chown 与 chmod 吧！
    • 利用 smbpasswd 来新增其他使用者到 /etc/samba/smbpasswd 里面去，如果该帐号并没有出现在 /etc/passwd 里面，请先以 useradd 新增该帐号；
    • 不论进行完任何的设定，请先以 testparm 进行确认，之后以 /etc/init.d/smb restart 来重新启动！
    事实上，SAMBA 的一般用途就是在这个连线的模式中！多使用 SAMBA 来分享您的资源吧！鸟哥都是使用 SAMBA 来做为远端伺服器与我的工作机互通有无的重要媒介说～

    小标题的图示 设定成为印表机伺服器 (CUPS 系统)
    刚刚上面的说明大部分都是针对磁碟与目录的分享来进行 SAMBA 的设定，那么 SAMBA 有没有可能分享出装置呢？举个例子来说，例如那个我们在办公室都会用到的印表机呢？如果说，能够让我们办公室的 File Server 同时提供印表机列印的功能，如此一来，藉由 Linux 这个作业系统可以 24 小时开机的稳定功能，我们就可以随时进行列印啰！所以，底下我们就以 SAMBA 进行印表机列印功能的提供者的角度，来介绍这个 smb.conf 的设定喔！

    在 Linux 底下进行列印的工具很多，不过我们这里要介绍的仅有目前较广为流行的 CUPS (Common Unix Printing System) 这一个。 详细的 CUPS 安装设定方法我们已经在基础篇的 CUPS 章节当中提过， 所以这里我们不再详细说明，仅介绍大致的处理流程就是了。如果你需要较早期的 LPRng 列印系统的话， 建议可以参考底下的资料喔：
    • 依玛猫的列印文件：http://www.imacat.idv.tw/tech/lnxprint.html
    • 鸟哥的 LPRng 简介：http://linux.vbird.org0370samba/0370samba.htm
    底下就来谈一谈一般常见的流程说明吧：

  • 1 安装印表机与确定启动
    • 再次说明，并不是所有的印表机都被 Linux 所支援的，所以当你想要连结一部印表机到 Linux 系统上头时， 请务必到 http://www.linuxprinting.org/printer_list.cgi 上头去看看是否有被支援喔！ 如果没有被支援，那就换一部印表机吧！不要进行垂死的挣扎了....

    如果你的印表机连接埠为使用 USB 或者是平行序列埠的话，那么当你连接上印表机后， 可以利用底下的方式测试看看是否成功的连接上了：
    [root@linux ~]# echo "Hello printer" > /dev/lp0     <==平行序列埠
[root@linux ~]# echo "Hello printer" > /dev/usb/lp0 <==USB 埠
    如果印表机有回应，这表示 OK 的啦！你可以进行底下的工作了。如果你的印表机为网路印表机呢？ 就是说印表机有 IP 的情况下，那么该印表机就不需要加入 Samba 啦！因为该印表机本身就可以直接提供用户端连接， 根本不必透过 Samba 来提供网路连线的嘛！当然啦，如果你有特殊需求， 将网路印表机加入 Samba server 来提供给网芳中的其他用户，也是可以的啦！底下直接来看看如何使用 CUPS 吧。

  • 2. 设定 CUPS 的印表机
    • 请先确认你的 CUPS 已经安装妥当了，原则上，你必须要有底下两个套件存在才行：
    • cups-libs
    • cups
    接下来我们可以开始设定 CUPS 了！设定的原则是这样的：
    • 我需要让 192.168.1.0/24 这个网域可以使用印表机
    • 我需要让 192.168.1.0/24 及 127.0.0.0/8 可以管理 CUPS 系统
    然后开始这样做：
    [root@linux ~]# vi /etc/cups/cupsd.conf
# 底下这个项目在控制谁可以使用 CUPS 系统，约在 772 行左右，
# 找到这些资料并增加一笔记录：
<Location />
Order Deny,Allow
Deny From All
Allow From 127.0.0.1
Allow From 192.168.1.0/24
</Location>

# 底下的项目则在设定谁可以登入 CUPS 系统的管理介面？
# 约在 830 行左右，找到这些资料并进行一些细部修改：
<Location /admin>
#AuthType Basic
#AuthClass System
Order Deny,Allow
Deny From All
Allow From 127.0.0.1
Allow From 192.168.1.0/24
</Location>

# 在最后一行的地方加上这一句
Listen 0.0.0.0:631
# 上面在设定一个不需要密码即可登入的管理环境，是个很粗糙的介面，
# 建议您自行处理一下认证问题，请参考基础篇的说明。
    另外，为了要进行 Windows 相关软体所传来的列印资料，所以我们还需要对 CUPS 作一些额外的设定， 过程也是很简单的：
    [root@linux ~]# vi /etc/cups/mime.convs
# 大概在最后几行的地方，找到这一行，将注解拿掉！
application/octet-stream   application/vnd.cups-raw   0   -

[root@linux ~]# vi /etc/cups/mime.types
# 同样也是在最后面几行的地方，也是将注解拿掉即可！
application/octet-stream
    设定完毕后就可以开始来启动 cups 系统，可以这样做：
    [root@linux ~]# /etc/init.d/cups start
[root@linux ~]# netstat -tunlp | grep '631'
tcp 0  0 0.0.0.0:631     0.0.0.0:*    LISTEN   18271/cupsd
udp 0  0 0.0.0.0:631     0.0.0.0:*             18271/cupsd
    那个 631 的埠口就是 CUPS 所启动的啦！然后我们可以开始设定印表机了！ 由于 CUPS 支援很多不同的印表机连接埠，每种连接埠都不一样，常见的有：
    • USB 连接埠： usb:/dev/usb/lp0
    • 平行序列埠： parallel:/dev/lp0
    • 网路印表机： ipp://ip/印表机型号
    • 网路芳邻印表机： smb://user:password@host/printer
    假设我们的 Samba 上头接了一部 usb 连线的印表机，而我要将这部印表机取名为 hplaser2300 时， 你可以使用浏览器连接到 Samba 主机上头，必须注意到网址喔：

    CUPS 的管理介面示意图
    图三、CUPS 的管理介面示意图

    如上图三所示，先在网址列的地方务必要输入埠口才行！然后按下箭头‘ 2 ’所指的地方， 亦即是‘Manage Printer’之后再按下‘Add printer’的按钮，就会出现如下画面， 记得要填写正确的资料喔！

    CUPS 的管理介面示意图
    图四、CUPS 的管理介面示意图

    然后如下图所示，选择正确的装置所在处！我们假设使用的是 USB 的印表机连接埠：

    CUPS 的管理介面示意图
    图五、CUPS 的管理介面示意图

    之后就是选择正确的型号啰，假设这部印表机为 HP 所出产的：

    CUPS 的管理介面示意图
    图六、CUPS 的管理介面示意图

    选择标准的雷射印表机驱动程式吧！

    CUPS 的管理介面示意图
    图七、CUPS 的管理介面示意图

    最后都成功后，就会找到如下所示的画面了。

    CUPS 的管理介面示意图
    图八、CUPS 的管理介面示意图

    到此为止我们可以假设你的 CUPS 已经有一部印表机存在了，即使该印表机目前无法工作， 但是就是有一部印表机嘛！^_^！接下来看看如何将他连结到咱们的 Samba 伺服器中吧！

  • 3. 在 smb.conf 当中加入印表机的支援
    • 然后开始告诉 Samba 将这部印表机给他分享出去吧！你需要这样处理：
    [root@linux ~]# vi /etc/samba/smb.conf
[global]
        .....其他省略.....
        # 这里列出的则是印表机相关的资料啊！
        printcap name = cups
        load printers = yes
        printing      = cups
[printers]                             <==这个分享的资源名称一定是 printers
        comment     = All Printers
        printable   = yes              <==可以进行列印的功能
        browsable   = yes              <==可以让其他人浏览
        public      = yes
        valid users = @users dmtsai    <==可使用的人员有这些
        path        = /var/spool/samba <==列印伫列的地方，暂存资料
        printer admin = dmtsai         <==这是印表机管理员！需要可使用 SAMBA 者
        .....其他省略.....
    基本上透过这样的设定你的 Samba 就能够顺利的提供印表机的服务了！ 不过可惜的是，Windows 用户端依旧得要安装印表机的驱动程式才能够使用 Samba 所提供的印表机， 此时真是麻烦兼讨厌啊～有没有可能让 Samba 主动的提供驱动程式给使用者，这样一来用户端就不需要额外去找驱动程式啰！ 是可以的，透过 Samba 3.x 即可处理！

    或许你会想，印表机的型号这么多，那么 Linux 该如何提供这些印表机的驱动程式啊？岂不麻烦？ 还好啦， CUPS 主要是透过利用 Postscript 的列印语言与印表机沟通的，因此用户端只要取得 postscript 的驱动程式他们就能够使用咱们的 Samba 伺服器所提供的印表机了！如此一来， 不论印表机的型号为何，只要他们能够支援 Postscript 的列印格式，OK 搞定！而且 CUPS 官网本身就有提供 CUPS 的 Postscript 驱动程式啰！可以到底下的连结去下载：
    • 支援多种 CUPS 版本：http://ftp.easysw.com/pub/cups/windows/
    • 支援 CUPS 1.2 以上版本：http://www.cups.org/windows/software.htm
    由于 CentOS 4.x 使用的是 1.1.x 版本，所以鸟哥下载的是 cups-samba-5.0rc3.tar.gz 这个档案， 接下来我们要将这个档案解压缩，然后将相关的程式给他安装到正确的目录去。 不过您得要注意的是，除了这个驱动程式外，要支援 Windows 2000/xp 的用户端， 你还得到 Windows XP 的底下目录去下载几个档案：
      C:\WINDOWS\system32\spool\drivers\w32x86\3
    里面的 PS 开头的档案通通下载下来，应该有四个档案的，请将他复制成为小写的档案，并且放置到你 Samba 主机上的 /usr/share/cups/drivers/ 目录下，然后将 cups-samba-5.0rc3.tar.gz 解压缩后执行 ./cups-samba.install 档案， 就能够将驱动程式通通安装到 /usr/share/cups/drivers/ 目录下了！这就是基本的驱动程式说！ 在鸟哥的这个目录底下至少含有这几个档案就是了：
    [root@linux ~]# ll /usr/share/cups/drivers
-r--r--r--  1 root root  14234 Sep 24  2002 cups5.hlp
-r--r--r--  1 root root 280268 Jan  4  2004 cupsdrv5.dll
-r--r--r--  1 root root 219540 Jan  4  2004 cupsui5.dll
-rw-r--r--  1 root root 129024 Dec 27 14:18 ps5ui.dll
-rw-r--r--  1 root root 455168 Dec 27 14:18 pscript5.dll
-rw-r--r--  1 root root  27568 Dec 27 14:18 pscript.hlp
-rw-r--r--  1 root root 792644 Dec 27 14:18 pscript.ntf
    上述的档案鸟哥将他打包成为一个档案了，你可以在底下的连结下载：
      http://linux.vbird.org0370samba/cups-samba-windows.tgz
    不过您得注意，这个档案内的 Windows 资料是由 Windows XP 上面捉来的，所以对于 Windows 98/ME 是没有作用的。 您得自行上网查阅相关的资料下载方式喔。 接下来我们必须要在 smb.conf 里面增加一笔新的分享资料，这个分享资料必须是 [print$] 名称才行！ 有点类似这样啦：
    [root@linux ~]# vi /etc/samba/smb.conf
        .....其他省略.....
[print$]
        comment    = Printer drivers
        path       = /etc/samba/drivers  <==存放印表机驱动程式的目录
        browseable = yes
        read only  = yes
        write list = dmtsai              <==这个驱动程式的管理员
        .....其他省略.....

[root@linux ~]# mkdir /etc/samba/drivers
[root@linux ~]# chown dmtsai /etc/samba/drivers
# 因为我们将印表机管理员以及驱动程式管理员的身份设定为 dmtsai 这个使用者，
# 因此存放的目录也要改变一下权限才行呐！

[root@linux ~]# testparm                 <==测试语法
[root@linux ~]# /etc/init.d/smb restart  <==重新启动

[root@linux ~]# smbclient -L //127.0.0.1 -U dmtsai
Password: <==输入密码先
Domain=[VBIRDSERVER] OS=[Unix] Server=[Samba 3.0.10-1.4E.9]

    Sharename    Type      Comment
    ---------    ----      -------
    print$       Disk      Printer drivers
    hplaser2300  Printer   HP Laser Jet 2300 printer
# 瞧！有看到一部印表机以及驱动程式所在的分享资料啰！
    现在我们的要告知 Samba 说，我们的 CUPS 可提供 Windows 2000/XP 用户端的驱动程式， 所以用户不需要自行设定他们的驱动程式哩！要由 cups 告知 Samba 是由 cupsaddsmb 这个指令来搞定的， 整个指令的执行很简单的：
    [root@linux ~]# cupsaddsmb -H [SAMBA 主机名] -h [CUPS 主机名] \
>   -a -v -U [使用者帐号]
参数：
-H ：后续接的是 Samba 主机名，本机的话可以直接用 localhost 即可；
-h ：后续接的为 CUPS 的主机名，同样的可使用 localhost 即可；
-a ：搜寻所有可用的印表机；
-v ：列出更多的资讯；
-U ：印表机管理员

范例：利用前面的说明将印表机驱动程式挂上 SAMBA
[root@linux ~]# cupsaddsmb -H localhost -U dmtsai -a -v
Password for dmtsai required to access localhost via SAMBA: <==输入 dmtsai 密码
# 这里会闪过很多的讯息，说明已经安装了某些资讯，底下鸟哥仅列出简单的讯息而已。
putting file /usr/share/cups/drivers/pscript5.dll as
\W32X86/pscript5.dll (1438.5 kb/s) (average 1342.5 kb/s)

Printer Driver hplaser2300 successfully installed.

Succesfully set hplaser2300 to driver hplaser2300.

[root@linux ~]# ll /etc/samba/drivers
drwxr-xr-x  3 dmtsai dmtsai 4096 Dec 27 14:40 W32X86
    最后在驱动程式的存放目录会多出一个 W32X86 的目录，你可以查询一下该目录的内容， 那就是预计要给用户端使用的驱动程式啦！这样就搞定了！不过，为了将所有的资料通通驱动， 建议您将 CUPS 及 SAMBA 通通重新启动吧！
    [root@linux ~]# /etc/init.d/cups restart
[root@linux ~]# /etc/init.d/smb restart
  • 4. 一些问题的克服：
    • 如果一切顺利的话，你在 Windows 用户端应该可以顺利的连接到印表机啰！ 开心吧！不过，如果你曾经印错资料，那么该如何进入 Linux 的 Samba 主机将该资料移除呢？ 你最好知道底下的几个指令，关于这些指令的进阶用法则请自行给他 man man 看了：
    [root@linux ~]# lpstat -a
hplaser2300 accepting requests since Jan 01 00:00
# 列出所有可用的印表机状态

[root@linux ~]# lpq
hplaser2300 is ready
no entries
# 列出印表机的工作，若有列印工作存在时，会如下所示：
hplaser2300 is ready and printing
Rank    Owner   Job  File(s)                 Total Size
active  dmtsai   5   smbprn.00000003 测试页  42954752 bytes

[root@linux ~]# lprm all
# 移除所有等待中的列印工作！
    列印工作就是这样进行的啦！赶紧试看看吧！

    小标题的图示 安全性管理
    使用 SAMBA 其实是有一定程度的危险性的，这是因为很多网路攻击的蠕虫就是透过 NetBIOS 来攻击的！ 因此，在架设好了 SAMBA 之后，请记得将权限方面的工作做好！权限方面的工作除了 smb.conf 内的设定外， Linux 档案系统的 r, w, x 权限也是相当重要的喔！我们底下就简单的介绍一下一些基本的安全性管理吧！

  • 利用 iptables 来管理
    • 最简单的管理登入 SAMBA 的方法就是透过 iptables 啦！详细的说明我们已经在 防火墙章节当中提过了，所以这里不在详加说明。 要知道的是，如果你仅要针对底下的范围开放 Samba 时，可以这样想：
    • 仅针对 192.168.1.0/24 这个网域开放 SAMBA；
    • SAMBA 的 port 有 137~139 tcp/udp；
    • SAMBA 主机的网路卡为 eth0
    所以 iptables.rule 规则当中应该要加入这几项：
    iptables -A INPUT -p tcp -i eth0 -s 192.168.1.0/24 --dport 139     -j ACCEPT
iptables -A INPUT -p udp -i eth0 -s 192.168.1.0/24 --dport 137:138 -j ACCEPT
    当然啦！这是很简单很简单的防火墙规则，您必须要依据您的环境自行修改 (通常修改那个 192.168.1.0/24 网段即可！) 。除了 iptables 必须要开放之外，您还需要将管制 daemon 是否能够进出的 TCP Wrappers 开放才行呐！如果万一您看到 /etc/hosts.deny 里面多了这一行：
    [root@linux ~]# cat /etc/hosts.deny
ALL : ALL
    不要怀疑，很可能会造成不只 SAMBA 不能动作而已～连其他的 daemon 都可能会无法动作呢！所以，请将这一行拿掉吧！ 或者是将适合的 daemon 开放在 /etc/hosts.allow 档案里面喔！

  • smb.conf 的设定值
    • 事实上 Samba 已经有许多防火墙机制啦！那就是 hosts allow 及 hosts deny 这两个参数。 通常我们只要使用 hosts allow 即可，那么没有写入这个设定项目的其他来源就会被拒绝连线的！ 举例来说，如果你只想要让本机、192.168.1.11, 192.168.1.21 使用 SAMBA 而已，那么可以这样写：
    [root@linux ~]# vi /etc/samba/smb.conf
[global]
        # 跟安全有关
        hosts allow = 127. 192.168.1.11 192.168.1.21
    smb ports = 139
    如此一来不但只有数部主机可以登入我们的 SAMBA 伺服器，而且 Samba 只能以标准的 port 139 来连结， 关闭 Windows 常用且有点问题的 port 445 呢！这样会比较好一些啦！ 未来如果还有人想要连结你的 Samba 时，将他加入 hosts allow 后面即可！ 不难吧！ ^_^

  • 利用 Quota 限制使用者空间使用
    • quota 是磁碟配额限制的一个 daemon ，您可以依据不同的使用者来加以限制他们能够使用的硬碟空间， 前提是‘该磁碟空间必须是一个独立的 partition ’才行，不建议针对根目录 ‘ / ’进行 quota ！这也是为什么我们在主机规划时特别建议大家独立出一个 partition 来进行硬碟规划的原因！关于 quota 的详细用法在‘ 鸟哥的 Linux 私房菜--基础学习篇’里面已经谈得很清楚了， 这里我们不再详谈！只给大家来做个练习就是了！

    例题：
    在规划主机的时候，我将 /dev/hda2 独立一个 partition 给 /home 这个目录，现在想要规划 quota 针对 dmtsai 这个使用者进行磁碟配额的限制，他的 hardlimit 为 50mb 而 softlimit 为 40mb ，请问整个动作应该如何进行？
    答：
    1. 编辑修改 /etc/fstab ，使得 /dev/hda2 这个 partition 成为如下模样：
      /dev/hda2 /home  ext3  defaults,usrquota,grpquota 1 1
      修改完毕之后，请千万记得使用 mount -a 查询看看有没有设定错误 (上面总共只有六个栏位喔！)， 这个动作如果发生错误，那么请记得再次的进行 /etc/fstab 的修改！请特别留意啊！因为写错的话， 很容易造成无法正常开机的窘境！

    2. 上述动作确定没有问题之后，请重新开机启动 quota 的支援：
      sync; sync; sync; reboot
    3. 执行底下的指令，建立 quota 所需要的设定档案：
      quotacheck -avug
      特别注意，如果上述的动作发生‘找不到设定档’的意思的讯息时，您可以这样做：
      touch /home/aquota.user; touch /home/aquota.group
      然后再进行一次 quotacheck 即可！

    4. 启动 quota 啰：
      quotaon -av
    5. 设定 bird 的磁碟配额：
      edquota -u dmtsai
Disk quotas for user dmtsai (uid 501):
Filesystem   blocks    soft  hard inodes  soft  hard
/dev/hdb2        32  40000  50000     8     0     0
      因为我们只针对硬碟空间，不针对 inode 做限制，所以只要前面的数字修订即可！请注意，数字的单位为 kbytes ！

  • 关于备份
    • 跟 SAMBA 最有关的当然就是使用者的资讯啰！所以，您应该要备份的就是使用者的资料，以及 Samba 相关的设定资料了！比较相关的有几个咚咚：
    • /etc (因为含有 /etc/passwd 以及 /etc/samba 里面的资料，所以建议可以全部给他备份下来 )
    • /home (还是可以察看一下，是否有其他非必要的！不过，一般来说，都会是备份的个人资料比较多啦！)
    • 其他由 smb.conf 里面设定开放的目录。
    无论如何，备份还是挺重要的！
    小标题的图示 主机安装时的规划与中文磁区挂载
    现在您知道 Samba 伺服器的功能是用来作为档案伺服器的，每个使用者都可以拥有家目录， 并透过网芳的功能来连结到 Samba 伺服器中。这就有个问题啦，那就是你的使用者如果太多， 并且将他们的重要资料都放到这部 Samba 主机上头的话，那肯定 /home 未来会有点不足啊！ 所以 /home 所在的磁碟或许可以使用大一点的硬碟，或者使用磁碟阵列，使用 LVM 也是个不错的方案。 底下为简单的思考方向：
    • 在安装 Linux 的时候，建议不需要安装 X Window ；
    • 在规划 Linux 时，/home 最好独立出一个 partition ，而且硬碟空间最好能够大一些；
    • /home 独立出来的 partition 可以单独进行 quota 的作业，以规范每个使用者能够使用的最大硬碟容量；
    • 由于 SAMBA 可以做为印表机伺服器，所以建议印表机可以直接连接在 Linux 主机的列印埠 (LPT1, USB...)；
    • 由于 SAMBA 一般来说都仅针对内部 (LAN) 主机进行开放，所以，可能的话 SAMBA 主机直接使用内部保留 IP 来设定即可，当然啦， SAMBA 是否使用 private IP 还得视您的整个网域的 IP 网段的特性来规划。 以鸟哥研究室来说，因为实验室所有电脑的 IP 都是 Public IP，那么 SAMBA 如果使用 Private IP ，当然大家都无法连接上啊！ ^_^
    • 如果您的 SAMBA 主机使用 Public IP 时，请特别留意规范好防火墙的设定，尽量仅让 LAN 内的电脑可以连线进来即可，不要对 Internet 开放喔！
    另外，如果你的 Samba 伺服器需要挂载含有中文的 partition 时，譬如说你将原本 Windows XP 的 FAT32 档案系统挪到 Linux 系统下，此时如果用一般模式来挂载该分割槽时，一些中文档名可能会无法被顺利的列印出来。 这个时候你就得需要这样做了：
    mount -t vfat -o iocharset=big5,codepage=950 /dev/hd[a-d][1-16] /mount/point
    其中 iocharset 指的是本机的语系编码方式， codepage 则与远端软体有关。因为我们是在本机进行挂载， 所以实际上使用 iocharset 这个参数即可啦！更多说明则请看下节的用户端设定部分啰！
    大标题的图示 Samba 用户端软体功能
    现在你已经架设好了 Samba 伺服器啦！有伺服器当然要有用户端来使用才是好的伺服器嘛！不然要这个伺服器干嘛？ 而我们假设区域网路内有 Windows/Linux 系统，这两种系统都是透过 NetBIOS over TCP/IP 来连上 Samba 主机的， 在设定之前你必须要知道的有几件事：
    • 在区网内的主机最好具有相同的工作群组，且具有不同的主机名称；
    • Windows XP pro. 最多仅能允许十个用户同时连接到网芳；
    • 你可以在网芳当中看到的通常是相同群组的主机；
    • 可以使用‘搜寻’-->‘电脑’-->‘输入 IP’来查到 Samba 主机；
    • Windows 的网芳预设仅有同一网域的主机才能登入！
    接下来咱们就分别依照 Windows XP 及 Linux 系统来做说明吧！

    小标题的图示 Windows 系统的使用
    在 Windows 上面的搜寻实在挺简单的，你有好几种方法可以处理：
    • 打开‘档案总管’，‘网路上的芳邻’、‘整个网路’、‘Microsoft Windows Network’ 就能看到属于您群组的所有电脑主机了！

    • ‘开始’、‘搜寻’、‘档案或资料夹’、‘电脑或人员’、‘网路上的电脑’， 然后在出现的方框当中填写正确的 IP ，按下‘搜寻’即可！ 这个方法可以适用于不在同一个群组当中的网路主机喔！
    举例来说，如果想要连接到我们的 Samba 主机的话，而又不知到这部 Samba 主机的 NetBIOS name ， 那利用搜寻的结果会有点类似如下的图示：

    Windows XP 用户端搜寻示意图
    图九、Windows XP 用户端搜寻示意图

    上图九中先在左侧的地方输入正确的 IP 后，按下搜寻，如果一切顺利的话那么右上方就会出现这部 Samba 主机的说明了。 双击一下该主机名称，就会出现右下方的项目！瞧！那就是我们所设定的几个基本项目的啦！真是好高兴！ 然后你就可以开始进入相对应的目录进行资料的存取了，就这么简单。 如果是印表机的话，那么你将滑鼠移动到印表机的上方，按下右键后可以选择‘连线’的项目， 如下所示：

    Windows XP 用户端连线印表机示意图
    图十、Windows XP 用户端连线印表机示意图

    如果一切顺利的话，嘿嘿！你就可以在点选‘开始’、‘设定’、‘印表机和传真’后所出现的视窗看到这部印表机啰！ 真是好棒呐！ ^_^

  • 让 Windows 系统的网芳支援不同网域的 IP 连线
    • 由于 Windows XP sp2 这个作业系统版本预设的防火墙仅开放相同网域的 IP 来源使用本机的网芳资料， 所以如果是不同的网域想要使用时，预设是无法穿透 Windows 防火墙的。此时你可以修改一下防火墙的设定啊！ 请叫出控制台，然后点选‘Windows 防火墙’就会出现如下的图示了：

    Windows XP 伺服器防火墙示意图
    图十一、Windows XP 伺服器防火墙示意图

    按照上图的说明，依序点选‘例外’、‘档案及印表机共用’、‘编辑’后， 就会出现该防火墙机制所管理的埠口以及可连线的网域，如下图所示：

    Windows XP 伺服器防火墙示意图
    图十二、Windows XP 伺服器防火墙示意图

    你可以将四组埠口通通改变成你所需要的 IP 来源，或者是将他设定为任何电脑都能连线。 不过，鸟哥不建议喔！可以参考底下的作法：

    Windows XP 伺服器防火墙示意图
    图十三、Windows XP 伺服器防火墙示意图

    选择自订的方式来设定能够使用你 Windows 网芳资料的来源 IP 或网段即可，然后确定之后即可处理呐！ 这样一来，及时我们的 Linux 不与 Windows 同在一个网域中，也能够登入 Windows 存取网芳资料哩。

  • 透过 port 445 的特殊登入方式
    • 如果你知道 Samba 主机有分享出 port 445 ，并且他已经分享了某个目录时，举例来说， 我们的 192.168.1.254 有分享出 public 这个分享资源名称时，那么这个目录的完整写法为：‘ \\192.168.1.254\public ’，我们可以透过‘开始’、‘执行’来处理这个玩意儿！ 如下所示：

    Windows XP 透过 port 445 连线
    图十四、Windows XP 透过 port 445 连线

    如果可以登入的话就会顺利登入，否则就会弹出一个要你输入帐号密码的视窗，输入正确的资料即可！ 呼呼！真过瘾～除此之外，我们还可以登入别人 Windows 主机的 C 或 D 槽喔！写法则变成这样：
      \\192.168.1.21\c$
    所以说，怕了吧！俺还真害怕～所以啊，Samba 没必要时，那个 port 445 应该是可以关闭的吧！
    小标题的图示 Linux 系统的使用
    咱们的 Samba 有提供 Linux 网芳的用户端功能喔！也就是说 Linux 可以挂载 Samba 主机也能挂载 Windows 提供的网芳啦！ 主要是透过 smbclient 来观察，再以 smbmount 或 mount 来挂载磁区哩。先来介绍一下 smbclient 这个指令吧：
    1. 关于查询的功能
[root@linux ~]# smbclient -L //[IP|hostname] [-U username]
[root@linux ~]# smbclient -L //127.0.0.1 -U dmtsai
Password:
Domain=[VBIRDSERVER] OS=[Unix] Server=[Samba 3.0.10-1.4E.9]
....分享的资源输出省略....
Domain=[VBIRDSERVER] OS=[Unix] Server=[Samba 3.0.10-1.4E.9]

    Server           Comment
    ---------        -------

    Workgroup        Master
    ---------        -------
    VBIRDGRP         VBIRD_OP_2
    VBIRDHOUSE       VBIRDSERVER
# 从这里可以知道在目前网域当中有多少个工作群组与主要的名称解析主机
    除了这个先前用过的查询功能之外，我们可以这样简易使用网芳的：
    2. 利用类似 FTP 的方式登入远端主机
[root@linux ~]# smbclient '//[IP|hostname]/资源名称' [-U username]
# 意思是使用某个帐号来直接登入某部主机的某个分享资源，举例如下：
[root@linux ~]# smbclient '//127.0.0.1/dmtsai' -U dmtsai
Password:
Domain=[VBIRDSERVER] OS=[Unix] Server=[Samba 3.0.10-1.4E.9]
smb: \> dir
# 在 smb 底下其实就是在 //127.0.0.1/dmtsai 这个目录底下啦！所以，
# 我们可以使用 dir, get, put 等常用的 ftp 指令来进行资料传输了！
?   :列出所有可以用的指令，常用！
cd  :变换到远端主机的目录
del :杀掉某个档案
lcd :变换本机端的目录
ls  :察看目前所在目录的档案
dir :与 ls 相同
get :下载单一档案
mget:下载大量档案
mput:上传大量档案
put :上传单一档案
rm  :删除档案
# 其他的指令用法请参考 man smbclient 喔！
    事实上，使用 smbclient 一点也不方便，因为使用的是 ftp 的功能语法，有点怪怪的～能不能像 Windows 那样，可以直接连线网路磁碟机啊？这当然没有问题！不过就需要藉由 smbmount 来协助了！smbmount 可以将远端主机分享出来的目录整个给他 mount 到本机的 mount point (某个目录)，如此一来， 远端主机的目录就好像在我们本机的一个 partition 一样喔！可以直接执行复制、编辑等动作！这可就好用的多了！ 底下我们来谈一谈怎么用这个 smbmount 吧！
    [root@linux ~]# smbmount //IP/分享资源 /挂载点 [-o options]
参数：
-o 后面接的参数 (options) 常用的有底下这些：
   username=你的登入帐号：例如 username=dmtsai
   password=你的登入密码：需要与上面 username 相对应啊！
   iocharset=本机的语系编码方式，如 big5 或 utf8 等等；
   codepage=远端主机的语系编码方式，例如繁体中文为cp950

范例一：以 dmtsai 的身份将其家目录挂载至 /mnt/samba 中
[root@linux ~]# smbmount //127.0.0.1/dmtsai /mnt/samba
> -o username=dmtsai,password=pw_test,codepage=cp950
[root@linux ~]# df
//127.0.0.1/dmtsai  20161024  3088896  17072128  16% /mnt/samba
    经由 smbmount 的动作，我们就可以轻易的将远端分享出来的咚咚给他挂载到自己 Linux 本机上面！好用的很～事实上，原本 mount 这个指令如果有支援 smbfs 的话， 那也就可以直接挂载网路上的芳邻分享出来的目录了！例如上面的例子当中，我们也可以这样下达指令：
    mount -t smbfs //127.0.0.1/dmtsai /mnt/samba \
-o username=dmtsai,password=pw_test,codepage=cp950,iocharset=big5
    更详细的 mount 用法，请 man mount 或者看考‘鸟哥的 Linux 私房菜 -- 基础学习篇’的内容喔！ ^_^

  • 查询 NetBIOS name 与 IP 及其他相关资讯：
    • 现在我们可以透过一些 NetBIOS 相关的功能来取得 NetBIOS name ，不过，如果你还想要知道这个 NetBIOS name 的其他资讯时， 例如 IP、分享的资源等等，那可以使用 nmblookup 这个指令来搞定即可。他是这么使用的：
    [root@linux ~]# nmblookup [-S] [-U wins IP] [-A IP] name
参数：
-S ：除了查询 name 的 IP 之外，亦会找出该主机的分享资源与 MAC 等；
-U ：后面一般可接 Windows 的主要名称管理伺服器的 IP ，可与 -R 互用；
-R ：与 -U 互用，以 Wins 伺服器来查询某个 Netbios name；
-A ：相对于其他的参数， -A 后面可接 IP ，藉 IP 来找出相对的 NetBIOS 资料；

范例一：藉由本机找出 vbirdserver 这部主机的 IP 位址
[root@linux ~]# nmblookup -U localhost vbirdserver
querying vbirdserver on 127.0.0.1
192.168.1.254 vbirdserver<00>

范例二：找出 vbirdserver 的 MAC 与 IP 等资讯：
[root@linux ~]# nmblookup -S vbirdserver
querying vbirdserver on 192.168.1.255
192.168.1.254 vbirdserver<00>
Looking up status of 192.168.1.254
        VBIRDSERVER     <00> -         B <ACTIVE>
        ..__MSBROWSE__. <01> - <GROUP> B <ACTIVE>
        VBIRDHOUSE      <1e> - <GROUP> B <ACTIVE>

        MAC Address = 00-00-00-00-00-00 <==因为是本机资料，所以 MAC 会成为这样
  • 利用 smbstatus 观察 SAMBA 的状态
    • 如果想要查阅目前 SAMBA 有多人人来连线且哪些资源分享已经被使用的话，可以这样看：
    [root@linux ~]# smbstatus [-pS] [-u username]
参数：
-p ：列出已经使用 SAMBA 连线的程序 PID ；
-S ：列出已经被使用的资源分享状态；
-u ：只列出某个使用者相关的分享资料

范例一：列出目前主机完整的 Samba 状态
[root@linux ~]# smbstatus
Samba version 3.0.10-1.4E.9
PID     Username      Group         Machine
-------------------------------------------------------------------
 4973   dmtsai        dmtsai        127.0.0.1    (127.0.0.1)
# 上面列出的是与 PID 有关的资讯，可用 smbstatus -p 单纯列出

Service      pid     machine       Connected at
-------------------------------------------------------
dmtsai        4973   127.0.0.1     Thu Dec 28 10:58:36 2006
# 上面列出的则是分享资源，那个 Service 就是分享的目录。
    你可以透过这个小程式来了解到目前有多少人使用你的 SAMBA 的啦！
    大标题的图示 伺服器进阶管理
    除了前面提到的几个资讯之外，在这里我们也来谈谈如何让你的 Samba 作更多的事情！ 包括将 Windows 使用者的家目录放到 Samba 上头呢！^_^

    小标题的图示 让 Samba 管理网域使用者：PDC
    前面介绍的内容都是属于 Peer/Peer 的连线状况，也就是 Samba 伺服器与 Windows 用户端其实是平等地位的啦！ 所以 Windows 用户端需要知道 Samba 伺服器内的帐号密码资料后，才能够顺利的使用 Samba 的资源。 不过，这样的方式在较大型一些的区域网路环境可能就会有点困扰，例如学校的环境。

    举例来说，如果你有一个电脑教室里面有 50 部 Windows XP Pro. 的个人电脑，由于电脑教室大家都会使用， 因此里面这 50 部个人电脑有使用还原精灵，也就是每次电脑重新开机后整个作业系统就会还原成原本的样子。 但我们知道使用者总是需要有个人家目录吧？他们总不希望这次的工作在重新开机后就失去了～ 所以我们可以利用一部主机来让他们储存资料啊！那就是 Primary Domain Controller (PDC) 主机啰。

    其实 Samba PDC 的作用很简单，就是让 Samba PDC 成为整个区域网路的领域管理员 (domain controller)， 然后让 Windows 主机加入这个领域，未来使用者利用 Windows 登入时，Windows 会前往 PDC 伺服器取得使用者的帐号密码， 同时 PDC 还会传送使用者的重要资料到那部 Windows 个人电脑上，而 Windows 电脑上的使用者登出时， 该使用者修改过的资料也会回传给 PDC ，如此一来不管这个使用者在哪一部个人电脑上面登入， 他都能够取得正确的个人资料！很棒的作用吧！

    PDC 是个很复杂的环境，他可以达到的功能相当的多，而且密码的验证也不必在同一部 PDC 主机上面， 不过这里我们不谈那么复杂的东西，只是做一个简单的练习，因此底下的这部 PDC 使用自己的密码来进行验证， 并且也管理自己所分享出去的资源啰！整个基本的设定流程应该是这样的：
    • 设定好 PDC 主机的 TCP/IP 与 Windows 主机的网路，这个你应该已知如何处理了；
    • 设定 PDC 的角色定位，因为 PDC 管理自己的密码，所以 security = user
    • PDC 最好拥有整个网域的名称解析权力，亦即成为主要的名称解析器；
    • 需有 netlogon 资源分享，提供 windows 2000/XP pro. 用户端的登入之用；
    • 由于 Windows 需读入个人设定档，预设目录为 profile，Linux 系统需预先设定此目录；
    • 增加 PDC 上的使用者帐号以及机器代码 (machine account) 等等
    • 在 Windows 2000/XP pro. 个人电脑上设定成为 PDC 的用户端。
    底下咱们就来依序处理处理先！

  • 0. 设定 lmhosts 或 /etc/hosts 对应 Netbios 与 IP
    • 由于我们的 Samba 即将成为整个网域的名称解析者，因此你最好将整个网域的 NetBIOS name 与 IP 的对应写入此这个档案当中。当然啦，如果你的网域 IP 的取得为 DHCP ，那这个档案就不要写了吧！ 以我们这个案例为例，这个档案的内容应该是：
    [root@linux ~]# vi /etc/samba/lmhosts
127.0.0.1       localhost
192.168.1.254   vbirdserver
192.168.1.21    vbirdcpu2
192.168.1.11    vbirdcpu1
  • 1. 设定 smb.conf 成为具有 PDC 的能力
    • 假设我们要让 PDC 用户端登入时可以取得他自己的家目录，那么需要这样处理：
    [root@linux ~]# vi /etc/samba/smb.conf
[global]
        workgroup         = vbirdhouse
        netbios name      = vbirdserver
        server string     = This is vbird's samba server
        unix charset      = utf8
        display charset   = utf8
        dos charset       = cp950
        log file          = /var/log/samba/%m.log
        max log size      = 50
        socket options    = TCP_NODELAY SO_RCVBUF=8192 SO_SNDBUF=8192
        dns proxy         = no
        template shell    = /bin/false
        winbind use default domain = no
        security          = user
        encrypt passwords = yes
        smb passwd file   = /etc/samba/smbpasswd
        printcap name     = cups
        load printers     = yes
        printing          = cups

        # 与 PDC 有关的一些设定值：
        # 底下几个设定值处理成为本区域网路内的主要名称解析器
        preferred master = yes
        domain master    = yes
        local master     = yes
        wins support     = yes
        # 作业系统 (OS) 等级越高才能成为主网域的控制者，一般 NT 为 32,
        # Windows 2000 为 64 ，所以这里我们设定高一点，但不可超过 255
        os level = 200
        # 底下则是设定能否利用 PDC 登入，且登入需要进行哪些动作：
        domain logons = yes
        logon drive   = K:          <==登入后家目录挂载成 Windows 哪一槽
        logon script  = startup.bat <==每个使用者登入后会自动执行的程式
        time server   = yes         <==自动调整 Windows 时间与 Samba 同步
        admin users   = root        <==预设的管理员帐号！预设为 root
# 因为鸟哥不喜欢在 Samba 当中使用 root ，所以这里你也可以指定成其他帐号。

# 这个在指定登入者能够进行的工作，里面主要是具有许多执行程式：
[netlogon]  <==与前面的 logon script 有关，该程式放置在这里
   comment         = Network Logon Service
   path            = /home/samba/netlogon  <==你要自己主动建立此目录
   writable        = no
   write list      = root
   follow symlinks = yes
   guest ok        = yes

[homes]
        comment = Home directories
        browseable = no
        writable = yes
        valid users = %S
        create mode = 0664
        directory mode = 0775
[temp]
        comment   = Temporary file space
        path      = /tmp
        read only = no
        public    = yes

[root@linux ~]# testparm
[root@linux ~]# /etc/init.d/smb restart
    上面的设定有几个地方比较有趣一点：
    • time server：要使 Samba 与 Windows 主机的时间同步，使用这个项目；
    • logon script：当使用者以 Windows 用户端登入后，Samba 可以提供一支批次档， 让使用者去设定好他们自己的目录配置。整个配置的内容记录在 startup.bat 当中。 你要注意的是，这个 startup.bat 档名可以随意更改，不过他必须要放置到 [netlogon] 所指定的目录内；
    • logon drive：那么这个家目录要挂载到那个分割槽？ 在 Windows 底下大多以 C, D, E... 做为磁碟的代号，你这里可以指定一下家目录要放置成为那个磁碟代号；
    • admin users：指定这个 Samba PDC 的管理员身份。
    • [netlogon]：指定利用网路登入时首先去查询的目录资源。
  • 2. 建立所需要的目录与档案
    • 先来建立 [netlogon] 内所需要的资料好了，那就是一个目录：
    [root@linux ~]# mkdir -p /home/samba/netlogon
    接下来我们还得要建立允许使用者执行的档案，就是那个 startup.bat 才行！ 注意一下，我们这里假设使用者家目录为 K 槽，而 Samba 额外分享的 temp 则为 L 槽， 那你可以这样做：
    [root@linux ~]# vi /home/samba/netlogon/startup.bat
net time \\vbirdserver /set /yes
net use K: /home
net use L: \\vbirdserver\temp
# 这个档案的格式为：net use [device:] [directory]

# 再将该档案转成 DOS 的断行格式才行！因为是提供给 Windows  系统嘛！
[root@linux ~]# unix2dos /home/samba/netlogon/startup.bat
[root@linux ~]# cat -A /home/samba/netlogon/startup.bat
net time \\vbirdserver /set /yes^M$
net use K: /home^M$
net use L: \\vbirdserver\temp^M$
# 瞧见吗？会多出个奇怪的 ^M 符号，那就是 Windows 断行字元。
  • 3. 建立使用者
    • 在 Samba 里面建立使用者就是利用 smbpasswd 这个指令而已，我们已经建立过，所以这里不再说明。 但是由于我们需要 root 这个帐号来管理 PDC 与 Windows 用户端之间连线建立时所需要的权限， 所以你必须要建立起这个使用者才行。建立的方法很简单，直接这样做吧：
    [root@linux ~]# smbpasswd -a root
    另外，我们都知道 Windows XP pro. 的使用者设定档会被放置到‘ C:\Documents and Settings\使用者帐号 ’目录中， 在该目录底下会有类似桌面、我的最爱、应用程式设定、启动、我的文件夹啊等等的， 这些东西会放置到 Samba PDC 的哪里去备份啊？其实是放置到：
      /home/使用者帐号/profile/
    目录下的，该目录预设会被主动的建立起来，不过偶而会有一些权限错误的问题～伤脑筋～ 所以你可以预先处理该目录，以 chmod 或 chown 来改变成该使用者可以存取的权限。 另外，为了避免困扰，对于新增的使用者而言，你可以这样做：
    [root@linux ~]# mkdir /etc/skel/profile
    那以后新增的使用者都有可以存放来自 Windows 的特殊设定档目录喔！比较好管理啰～ 当然啦，使用 useradd 新增使用者后，记得也要使用 smbpasswd -a username 来让该使用者可以使用 Samba 喔！

  • 4. 建立机器码帐号
    • 由于 PDC 会针对 Windows 用户端的主机名称 (NetBIOS name) 进行主机帐号检查， 所以我们也要为用户端的主机名称进行帐号的设定。咦！啥是主机帐号？ 一般使用者帐号是英文或数字，主机帐号则在该帐号最后面加上一个钱字号‘$’即可！ 举例来说， vbirdcpu2 这部主机可设定的帐号名称为 vbirdcpu2$。

    而我们知道要使用 smbpasswd 增加的使用者必须要在 /etc/passwd 当中， 因此要建立这个帐号你就得要这样做：
    [root@linux ~]# useradd -M -s /sbin/nologin -d /dev/null vbirdcpu2$
[root@linux ~]# useradd -M -s /sbin/nologin -d /dev/null vbirdcpu1$
    会增加 -M -s -d 等参数的原因是因为不想要让这个帐号具有可以登入的权限， 因此将这个主机帐号设定的比较怪一点～ ^_^～接下来让 Samba 知道这个帐号是主机帐号， 所以你应该要这样做：
    [root@linux ~]# smbpasswd -a -m vbirdcpu1$
[root@linux ~]# smbpasswd -a -m vbirdcpu2$
    这样便加入主机帐号啰！而我们的 Samba PDC 也就可以透过‘主机帐号’来判断 Windows 用户端能否连上来， 若连接上 PDC 与 Windows 用户端后，接下来一般使用者帐号就可以在 windows 用户端登入了！

  • 5. Windows XP Pro. 用户端的连线与登入
    • 请注意，底下的方法仅是用于 Windows 2000, Windows XP 专业版 (Pro.)，一般的 Windows XP home 版本是不支援的！ 如果你用户端的主机是随机版的 Windows XP ，通常是 Windows XP home ，那底下的方法可能就无法适用啰！ 要连接上 Samba PDC 的过程也是挺简单的，你可以这样做：
    1. 确认 windows 用户端的网域与主机名称

      首先我们必须要确认 Windows 用户端的工作群组与主机名称跟咱们的 Samba PDC 相同， 确认的方式在区域网路里面已经提过了，这里在强调一次。将滑鼠移动到‘我的电脑’上面，按下右键， 选择‘内容’，然后点选‘电脑名称’，会出现如下图示：

      Windows 用户端连上 PDC 的方式
      图十五、Windows 用户端连上 PDC 的方式

      如上图所示，你要先确认箭头 1 处指的主机名称与工作群组，在我们这个案例当中的工作群组为 vbirdhouse， 这部 Windows 主机的 NetBIOS 名称则为 vbirdcpu2 喔！如果不对的话，请按下‘变更’来设定， 并且重新开机。重新开机完毕后再到图十五的画面当中，按下箭头 2 所指的网路识别处。

    2. 设定主机名称与网域名称

      接下来我们要设定这部 Windows XP pro. 要连结到区域网路上的哪部 PDC 上面， 亦即是处理主机帐号以及 Samba PDC 负责的网域 (domain) 啦！ 在图十五按下‘网路识别’后，分别在出现的视窗当中选择：

      1. 下一步；
      2. 这台电脑是公司网路的一部份，而且我在工作时用来连线到其他电脑(T)
      3. 我的公司使用一或多个网域的网路(C)
      4. 下一步

      然后就会出现如下的视窗：

      Windows 用户端连上 PDC 的方式
      图十六、Windows 用户端连上 PDC 的方式

      请依序填写 Samba 主机上面的管理员帐号与密码，要注意这个密码是记录于 /etc/samba/smbpasswd 中的那个，可不是 /etc/shadow 喔！别搞混了～这是 Samba 主机的设定呢。 输入之后按下一步吧，通常都会出现找不到正确主机的画面，如下所示：

      Windows 用户端连上 PDC 的方式
      图十七、Windows 用户端连上 PDC 的方式

      鸟哥也觉得很奇怪，老是告诉我找不到！不过没有关系，这里我们依旧再填一次主机的 NetBIOS name 以及群组名称， 如上图所示，然后继续按下一步，就会出现如下的画面啦：

      Windows 用户端连上 PDC 的方式
      图十八、Windows 用户端连上 PDC 的方式

      这次就给他输入正确的管理员帐号与密码，记得最后面的网域就是工作群组名称，别写错了。 处理完毕后给他按下确定吧！然后就会出现如下画面：

      Windows 用户端连上 PDC 的方式
      图十九、Windows 用户端连上 PDC 的方式

      恭喜您，这就表示已经连接上 Samba PDC 啰！我们希望所有的使用者都直接由 Samba PDC 控管，所以这里请填写 ‘此时不新增使用者’吧！按下一步去。

    3. 如果发生错误情况

      如果老是发生错误讯息为‘使用的帐户是电脑帐户。请使用您的通用使用者帐户或本机使用者帐户来存取这台伺服器’时， 你可以这样做的：

      • 先察看一下 /var/log/samba 里面的登录档资讯，尤其是 vbirdcpu2.log 关于这部主机的资讯呐；
      • 如果还是无法解决，可以在 lmhosts 里面增加 vbirdcpu2 的 IP 与主机名称的对应，然后将 samba 整个关掉‘/etc/init.d/smb stop’，等待一段时间让 NetBIOS 的名称解析时间逾时，再重新启动 samba ‘/etc/init.d/smb start’，然后再重新做一次输入 root 的密码那个动作

      在鸟哥尝试过的案例中，上面第二个步骤挺有效的！不过，还是得要察看 /var/log/samba 里面的登录资讯才行喔！

    4. 重新开机并以新的网域名称登入

      在图十九之后请重新开机，开机后整个画面会有点类似这样：

      Windows 用户端连上 PDC 的方式
      图二十、Windows 用户端连上 PDC 的方式

      请输入你在 Samba PDC 上面拥有的帐号与密码，当然啦，上图中最底下的选项最重要！ 现在这部 Windows 主机可以使用他自己的帐号登入，也可以透过 Samba 主机来登入喔！ 粉不错啦！ ^_^

    5. 观察使用者的家目录与设定档

      如果你可以顺利登入的话，打开档案总管后应该可以看到类似下方的画面：

      Windows 用户端连上 PDC 的方式
      图二十一、Windows 用户端连上 PDC 的方式

      呵呵！该连上的通通连结上来啰！你也可以在自己的家目录 (K 槽) 新增移除资料的！是否很不错啊！ ^_^！ 而当你登出之后，你在 Windows 桌面上头所进行的各项个人化设定通通会被移动到 /home/dmtsai/profile 当中喔！ 如果不相信的话，请自行前往 Samba 主机上头瞧一瞧就知道了。

    6. 一些使用上面的技巧

      虽然 PDC 很好用，不过你要注意的是，每次你使用 PDC 上头的帐号登入 Windows 用户端主机时， Windows 主机会由 /home/username/profile/ 当中载入所需要的资料， 并暂时启动一个资料夹在 C:\Documents and Settings\username 当中，如果你的家目录下的 profile 资料太多时， 光是传输就会花去很多时间的！

      所以，你应该将一些档案资料放置到你的家目录下，亦即 K 槽当中，尽量不要使用 Windows 预设的‘我的文件夹’， 因为‘我的文件夹’会将资料移动到 /home/username/profile/My Documents 目录下，同样的， 储存到桌面的资料会被放置到 /home/username/profile/桌面 目录中，那样在登入与登出时会花去很多时间喔！ 这个小地方也要注意的呢！ ^_^
    好了，关于 SAMBA 的 PDC 作法我们就谈到这里，还有更多的资讯您可以前往这个章节最后面的参考资料所列出的网址去查阅， 因为还有很多的作法呐！事实上，鸟哥觉得在一个网域当中，如果有多部的 Windows NT 主机，例如 Windows 2000/XP pro. 这一类的比较稳定的个人使用桌面版本时，使用 PDC 就很有用了！因为 Windows 2000/XP pro. 也是一个多人的作业系统，不像 Windows 98 是单人的作业系统。所以，当使用 Windows 2000/XP pro. 而无法登入 PDC 时，您是无法使用 Windows 2000/XP pro. 上面的任何的资讯的。 但是在 Windows 98 上面若无法正确的登入，您仍然具有该电脑的主控权喔！

    另外，设定 Windows 用户端之前，请先确认你的 Windows 是什么版本？ 上述的动作对于 Windows XP 家用版 (Home) 是没有作用的！请先确认才行喔！

    小标题的图示 问题克服
    通常我们在设定 SAMBA 的时候，如果是以 Workgroup 的方式来进行 smb.conf 的设定时，几乎很容易就可以设定成功了！并没有什么很困难的步骤。不过，万一还是无法成功的设定起来， 请务必察看登录档，也就是在 /var/log/samba 里面的资料！在这里面的资料当中，您会发现：咦！ 怎么这么多档案啊！因为我们在 smb.conf 里面设定了：
      log file = /var/log/samba/%m.log
    那个 %m 是指 Client 的 NetBIOS Name 的意思，所以，当有个 vbirdcpu2 的主机来登入我们的 vbirdserver 主机时，那么登入的资讯就会被纪录在 /var/log/samba/vbirdcpu2.log 档案喔！而如果万一来源 IP 并没有 Netbios name 的时候，那么很可能是一些错误讯息，这些错误讯息就会被纪录到 log.smbd, log.nmbd 里面去了！所以，如果您要察看某部电脑连上您的 SAMBA 主机发生了什么问题时，特别要留意这个登录档的形式喔！

    另外，如果您的 SAMBA 明明已经启动完成了，却偏偏老是无法成功，又无法查出问题时，建议先关闭 Samba 一阵子，再重新启动：
      /etc/init.d/smb stop
    在我的案例当中，确实有几次是因为 PID 与 NetBIOS 的问题，导致整个 SAMBA 怪怪的～所以完整的关闭之后， 经过一阵子的短暂时间，再重新启动，应该就可以恢复正常了！

    还有，万一您在进行写入的动作时，老是发现‘您没有相关写入的权限！’，不要怀疑，几乎可以确定是 Permission 的问题，也就是 Linux 的权限与 SAMBA 开放的权限并不相符合！无论如何，您必须要了解能不能写入 Linux 磁碟，看的是 PID 的权限与 Linxu 档案系统是否吻合，而那个 smb.conf 里面设定的相关权限只是在 SAMBA 运作过程当中‘预计’要给使用者的权限而已，并不能取代真正的 Linux 权限喔！所以，万一真的发现该问题存在， 请登入 Linux 系统，查验一下该对应的目录的 permission 吧！ ^_^

    小标题的图示 使用者修改 samba 密码
    有个问题是，我们知道使用者可以透过 passwd 修改 /etc/shadow 内的密码，那么使用者可否修改 samba 在 /etc/samba/smbpasswd 内的密码呢？可以啊！直接输入 smbpasswd 就能够修改自己的密码了！ 非常简单吧～不过，如果想要让 /etc/shadow 与 /etc/samba/smbpasswd 同步的话， 那就得要动点手脚了～您可以参考底下这两个连结来处理呢。
    • http://moto.debian.org.tw/viewtopic.htm?t=7732&
    • http://de.samba.org/samba/docs/using_samba/ch09.html
    小标题的图示 利用 ACL 配合单一使用者时的控管
    想像一个案例，如果你是学校的网管人员，有个兼任老师向您申请帐号，主要是要在很多班级内取得同学的专题资料。 因为该老师是兼任的，您或许担心一不小心该教师就将同学的辛苦资料给销毁，倒不是教师们故意的， 而是很多时候....不熟嘛！这个时候如果你将该老师加入同学的群组，然后偏偏同学们所在的目录是群组可写入的话， 那么该教师就能够拥有可读写的权限了，也就容易造成一些莫名的灾难～

    那该怎么办？其实可以透过 ACL 来管理某个目录的单一使用者权限啦！所以说， 权限的管理不必透过 smb.conf 的设定，只要透过 ACL 来管理就能够达到你所需要的目的了。 关于 ACL 的说明我们在前面的认识网路安全当中已经提过了， 这里不再啰唆，请自行前往查阅呐！ ^_^
    大标题的图示 重点回顾
    • Samba 名称的由来是因为需包含没有意义的 SMB server 之故；
    • SAMBA 可以让 Linux 与 Windows 直接进行档案系统的使用；
    • SAMBA 是由 Andrew Tridgwell 在 1991 年的时候利用不同平台所发展出来的；
    • SAMBA 主要架构在 NetBIOS 上发展的，且以 NetBIOS over TCP/IP 克服 NetBIOS 无法跨路由的问题；
    大标题的图示 课后练习
    • 一般来说， SAMBA 使用的设定档放置在哪里？档名为何？
      • 使用的档名为 smb.conf ，通常会放置在 /etc/samba/smb.conf 里面，不过，最好可以使用 rpm -qc packagename 来查询！
    • 哪一个指令可以用来判断 smb.conf 这个设定档的正确性？
      • 当我们修改完 smb.conf 之后，记得要以 testparm 来进行 samba 的确认！
    • 哪一个指令可以用来察看 SAMBA 主机分享出什么目录？
      • 利用 smbclient 即可：‘smbclient -L NetBiosName -U username ’！
    • smbmount 的功能为何？
      • 在 Linux 系统上面，将 Windows 的网路上的芳邻，或者是 Linux 的 SAMBA 所提供分享的资源挂载到自己的系统下！
    • 我今天使用 smbpasswd 去新增一位使用者 badbird，让他可以登入我的 Linux SAMBA 主机，但是无论如何就是无法新增。您认为原因可能是什么？
      • 由于 Samba 使用者的资讯必须要存在于 /etc/passwd 里面，既然无法新增，应该先确认 badbird 这个使用者已经存在于 Linux 系统当中了！如果还是无法新增，则需要查阅 smb.conf 的设定，看看是否 /etc/samba/smbpasswd 这个密码档案不存在？
    大标题的图示 参考资料
    • man 5 smb.conf
    • Study Area ：http://www.study-area.org/linux/servers/linux_samba.htm
    • 电子书 Using Samba：http://de.samba.org/samba/docs/using_samba/ch00.html
    • Samba PDC HOWTO: http://us5.samba.org/samba/docs/man/Samba-HOWTO-Collection/samba-pdc.html
    • SAMBA 官方网站：http://www.samba.org/
    • 杨锦昌老师的 SAMBA 密技：http://apt.nc.hcc.edu.tw/web/student_server_FC1.htm#samba
    • 依玛猫的列印文件：http://www.imacat.idv.tw/tech/lnxprint.html
    • Gentoo Linux 的 Samba 文件：http://www.gentoo.org/doc/zh_tw/quick-samba-howto.xml
    • cupsaddsmb 用法：http://www.enterprisenetworkingplanet.com/netsysm/article.htm/3621876
    • 下载 CUPS-windows 的网站：http://ftp.easysw.com/pub/cups/windows/
    • eyesblue 在讨论区针对语系的说明：http://phorum.vbird.org/viewtopic.htm?t=22001
    • testparm -v
    2001/09/17：好久以前曾经完成的一项任务 ^_^
    2003/07/26：将 2001/09/17 所写的内容做了大幅度的修订，增加原理以及更多的设定项目！
    2003/09/10：将 PDC 部分补充的更完整，因为加入了个人化的 Profiles 在 /home/samba/profiles 当中了！同时加入课后练习喔
    2003/09/30：加入了 CUPS 印表机的支援！
    2005/10/17：Samba 2.2 在中文编码上面与最新的 samba 3.0.x 版本不同。请参考： 中文编码 网友的详细说明喔！
    2006/12/20：将旧的文章移动到 此处
    2006/12/29：终于写完了 Samba 了！将 PDC 改写，很多乱乱的地方都改掉了～
    2007/04/12：原本对 homes 的说明中，那个 umask 应该是 002 ，原先的 022 是错的！
    2003/07/26以来统计人数


鸟哥的 Linux 私房菜 -- vsFTPd 档案伺服器

为取得较佳浏览结果，请爱用 firefox 浏览本网页

vsFTPd 档案伺服器
切换解析度为 800x600
最近更新日期：2006/12/20
在网际网路上面的传输协定当中， FTP (File Transfer Protocol) 可说是最古老的协定之一了！ 早期还没有这么多好用的协定之前 (例如 SAMBA)，都是使用 FTP 来进行资料的传递的呢！另外，一般来说资料的传输以 FTP 这个协定来传送是相当的快速的，而且某些场合当中其实也相当的方便。不过，值得注意的是，使用 FTP 来传输时，其实是具有一定程度的‘危险性’，因为资料在网际网路上面是完全没有受到保护的‘明码’机制！ 所以鸟哥不太建议大家使用这个伺服器的啦！尤其当你建置好了 FTP 之后，如果经常进行资料的传递， 对于您的网路频宽‘真的有很大的损害’啊！不过，无论如何， FTP 仍然有其存在的必要！例如义守大学的 FTP 站就作的相当的棒啊！不过， FTP 伺服器的危险性挺高的，因此我们选择一个强调安全性的 vsftpd 软体来架设喔！

1. 本章的行前准备工作
2. FTP 的资料连结原理
    2.1 FTP 功能简介
    2.2 FTP 的运作流程与使用到的埠口
    2.3 用户端选择被动式连线模式
    2.4 FTP 的安全性问题与替代方案
    2.5 开放什么身份的使用者登入
 3. vsftpd 伺服器基础设定
    3.1 为何使用 vsftpd ？
    3.2 所需要的套件以及套件结构
    3.3 vsftpd.conf 设定值说明
    3.4 vsftpd 启动的模式
    3.5 CentOS 的 vsftpd 预设值
    3.6 仅有实体用户登入的设定：
        chroot 的使用, 更严格的 chroot 环境,
        限制下载频宽, 限制最大上线人数与同一 IP 的来源数,
        建立严格的可使用 FTP 的帐号列表,
    3.7 仅有匿名登入的相关设定：
        建立上传/下载目录, 建立仅可上传目录,
        被动式连线埠口的限制
 4. 用户端的 FTP 连线软体
5. 其他 FTP 伺服器相关设定
    5.1 防火墙设定
    5.2 Super daemon 的额外管理项目
    5.3 常见问题与解决之道
 6. 重点回顾
7. 课后练习
8. 参考资料
9. 针对本文的建议：http://phorum.vbird.org/viewtopic.htm?p=118520
大标题的图示 本章的行前准备工作
架设 FTP 是个很难的任务，因为 FTP 服务同时启用两个连线通道，分别是命令通道与资料流通道， 这两条通道的连线建立方式不太一样，结果就造成了防火墙设定方面的困扰。 所以在学习 FTP 之前，请先确认您已经具有网路基础概念，而且对防火墙也需要有一定程度的概念了喔！
  • 必须要熟悉网路基础，尤其是网路连线的建立是双向的这个概念；
  • 必须要了解防火墙的机制，尤其当防火墙架设在路由器上的网路架构时。
  • 必须要了解 stand alone 与 super daemon 的启动方式。
大标题的图示 FTP 的资料连结原理
FTP 是相当古老的传输协定之一，他最主要的功能是在伺服器与用户端之间进行档案的传输。 FTP 其实是以 TCP 封包的模式进行伺服器与用户端电脑之间的连线，当连线建立后，使用者可以在用户端端连上 FTP 伺服器来进行档案的下载与上传，此外，也可以直接管理用户在 FTP 伺服器上面的档案呢，相当的方便！ 而这个古老的协定是使用明码传输，且过去有相当多的安全危机历史。为了更安全的使用 FTP 协定， 我们主要介绍较为安全但功能较少的 vsftpd 这个软体呐。

小标题的图示 FTP 功能简介
FTP 伺服器的功能除了单纯的进行档案的传输与管理之外，依据伺服器软体的设定架构， 他还可以提供几个主要的功能，底下我们约略的来谈一谈：

  • 不同等级的使用者身份：
    • FTP 伺服器在预设的情况下，依据使用者登入的情况而分为三种不同的身份，分别是 (1)实体帐号,real user；(2)访客, guest；(3)匿名登入者, anonymous 这三种。这三种身份的使用者在系统上面的使用权限差异很大喔！ 例如实体用户取得系统的权限比较完整，所以可以进行比较多的动作；至于匿名登入者， 大概我们就仅提供他下载一下资源而已，并不许匿名者使用太多主机的资源啊！ 当然，这三种人物能够使用的‘线上指令’自然也就不相同啰！ ^_^

  • 命令记录与登录档记录：
    • FTP 可以利用系统的 syslogd 这个 daemon 来进行资料的纪录， 而记录的资料包括了使用者曾经下达过的命令与使用者传输资料(传输时间、档案大小等等)的纪录呢！ 所以你可以很轻松的在 /var/log/ 里面找到各项登录资讯喔！

  • 限制或解除使用者家目录所在(change root, 简称 chroot)：
    • 为了避免使用者在您的 Linux 系统当中随意逛大街 (意指离开使用者自己的家目录而进入到 Linux 系统的其他目录去)， 所以将使用者的工作范围‘局限’在使用者的家目录底下，嗯！实在是个不错的好主意！FTP 可以限制使用者仅能在自己的家目录当中活动喔！如此一来，由于使用者无法离开自己的家目录，而且登入 FTP 后，显示的‘根目录’就是自己家目录的内容，这种环境称之为 change root ，简称 chroot ，改变根目录的意思啦！

    这有什么好处呢？当一个恶意的使用者以 FTP 登入您的系统当中，如果没有 chroot 的环境下，他可以到 /etc, /usr/local, /home 等其他重要目录底下去察看档案资料，尤其是很重要的 /etc/ 底下的设定档，如 /etc/passwd 等等。如果您没有做好一些档案权限的管理与保护，那他就有办法取得系统的某些重要资讯， 用来‘入侵’您的系统呢！所以在 chroot 的环境下，当然就比较安全一些咯！
    小标题的图示 FTP 的运作流程与使用到的埠口
    FTP 的传输使用的是较为可靠的 TCP 封包协定，在前几章的网路基础当中我们谈过， TCP 这种封包格式在建立连线前会先进行三向交握的。不过 FTP 伺服器是比较麻烦一些，因为 FTP 伺服器使用了两个连线，分别是命令通道与资料流通道 (ftp-data) 。这两个连线都需要经过三向交握， 因为是 TCP 封包嘛！那么这两个连线通道的关系是如何呢？底下我们先以 FTP 预设的主动式 (active) 连线来作个简略的说明啰：

    FTP 伺服器的主动式连线示意图
    图一、FTP 伺服器的主动式连线示意图

    简单的连线就如上图所示，至于连线的步骤是这样的：
    1. 建立命令通道的连线
      如上图一所示，用户端会随机取一个大于 1024 以上的埠口 (port AA) 来与 FTP 伺服器端的 port 21 达成连线， 这个过程当然需要三向交握了！达成连线后用户端便可以透过这个连线来对 FTP 伺服器下达指令， 包括查询档名、下载、上传等等指令都是利用这个通道来下达的；

    2. 通知 FTP 伺服器端使用 active 且告知连接的埠号
      FTP 伺服器的 21 埠号主要用在命令的下达，但是当牵涉到资料流时，就不是使用这个连线了。 用户端在需要资料的情况下，会告知伺服器端要用什么方式来连线，如果是主动式 (active) 连线时， 用户端会先随机启用一个埠口 (图一当中的 port BB) ，且透过命令通道告知 FTP 伺服器这两个资讯，并等待 FTP 伺服器的连线；

    3. FTP 伺服器‘主动’向用户端连线
      FTP 伺服器由命令通道了解用户端的需求后，会主动的由 20 这个埠号向用户端的 port BB 连线， 这个连线当然也会经过三向交握啦！此时 FTP 的用户端与伺服器端共会建立两条连线，分别用在命令的下达与资料的传递。 而预设 FTP 伺服器端使用的主动连线埠号就是 port 20 啰！
    如此一来则成功的建立起‘命令’与‘资料传输’两个通道！不过，要注意的是， ‘资料传输通道’是在有资料传输的行为时才会建立的通道喔！并不是一开始连接到 FTP 伺服器就立刻建立的通道呢！留意一下啰！

  • 使用到的埠号
    • 利用上述的说明来整理一下 FTP 会使用到的埠号主要有：
    • 命令通道的 ftp (预设为 port 21) 与
    • 资料传输的 ftp-data (预设为port 20)。
    再强调一次，这两个埠口的工作是不一样的，而且，重要的是两者的连线方向是不一样的！ 首先， port 21 主要接受来自用户端的主动连线，至于 port 20 则为 FTP 伺服器主动连线至用户端呢！ 这样的情况在伺服器与用户端两者同时为公共 IP (Public IP) 的网际网路上面通常没有太大的问题，不过， 万一你的用户端端是在防火墙后端，或者是 NAT 主机后端呢？会有什么问题发生呢？底下我们来谈一谈这个严重的问题！

  • 在 FTP 伺服器与用户端之间具有防火墙的连线问题：
    • 还记得我们的防火墙章节吧？一般来说，很多的区域网路 (LAN) 都会使用防火墙 (iptables) 的 NAT 功能，那么在 NAT 主机后端的 FTP 用户如何连接到 FTP 伺服器呢？ 我们可以简单的以下图来说明：

    若 FTP 用户端与伺服器端连线中间具有防火墙的连线状态
    图二、若 FTP 用户端与伺服器端连线中间具有防火墙的连线状态
    1. 命令通道的建立：
      因为 NAT 主机会主动的记录由内部送往外部的连线资讯，而由于命令通道的建立是由用户端向伺服器端连线的， 因此这一条连线可以顺利的建立起来的；

    2. 资料通道建立时的通知：
      同样的，用户端主机会先启用 port BB ，并透过命令通道告知 FTP 伺服器，且等待主机端的主动连线；

    3. 主机的主动连线问题：
      但是由于透过 NAT 主机的转换后，FTP 伺服器只能得知 NAT 主机的 IP 而不是用户端的 IP ， 因此 FTP 伺服器会以 port 20 主动的向 NAT 主机的 port BB 发送主动连线的要求。 但你的 NAT 主机并没有启动 port BB 来监听 FTP 伺服器的连线啊！
    了解问题的所在了吗？在 FTP 的主动式连线当中，NAT 主机将会被视为用户端，但 NAT 主机其实并非用户端啊， 这就造成问题了。如果你曾经在 IP 分享器后面连接某些 FTP 伺服器时，可能偶尔会发现明明就连接上 FTP 伺服器了 (命令通道已建立)，但是就是无法取得档案名称的列表，而是在超过一段时间后显示‘ Can't build data connection: Connection refused，无法进行资料传输’之类的讯息， 那肯定就是这个原因所造成的困扰了。

    那有没有办法可以克服这个问题呢？难道真的在 Linux NAT 主机后面就一定无法使用 FTP 吗？当然不是！ 目前有两个简易的方法可以克服这个问题：
    • 使用 iptables 所提供的 FTP 侦测模组：
      其实 iptables 早就提供了许多好用的模组了，这个 FTP 当然不会被错过！ 你可以使用 modprobe 这个指令来载入 ip_conntrack_ftp 及 ip_nat_ftp 等模组，这几个模组会主动的分析‘目标是 port 21 的连线’资讯， 所以可以得到 port BB 的资料，此时若接受到 FTP 伺服器的主动连线，就能够将该封包导向正确的后端主机了！ ^_^

      不过，如果你连结的目标 FTP 伺服器他的命令通道预设埠号并非标准的 21 埠号时 (例如某些地下 FTP 伺服器)， 那么这两个模组就无法顺利解析出来了，这样说，理解吗？

    • 用户端选择被动式 (Passive) 连线模式：
      除了主动式连线之外，FTP 还提供一种称为被动式连线的模式，什么是被动式呢？ 既然主动式是由伺服器向用户端连线，反过来讲，被动式就是由用户端向伺服器端发起连线的啰！ 既然是由用户端发起连线的，那自然就不需要考虑来自 port 20 的连线啦！关于被动式连线模式将在下一小节介绍喔！
    小标题的图示 用户端选择被动式连线模式
    那么什么是被动式连线呢？我们可以使用底下的图示来作个简略的介绍喔：

    被动式连线的方向
    图三、被动式连线的方向
    1. 建立命令通道：
      同样的需要建立命令通道，透过三向交握就可以建立起这个通道了。

    2. 发出 PASV 的连线要求：
      当有使用资料通道的指令时，用户端可透过命令通道发出 PASV 的被动式连线要求 (Passive 的缩写)， 并等待伺服器的回应；

    3. FTP 伺服器启动资料埠口，并通知用户端连线：
      如果你的 FTP 伺服器是能够处理被动式连线的，此时 FTP 伺服器会先启动一个埠口在监听。 这个埠口号码可能是随机的，也可以自订某一范围的埠口，端看你的 FTP 伺服器软体而定。 然后你的 FTP 伺服器会透过命令通道告知用户端该已经启动的埠口 (图中的 port PASV)， 并等待用户端的连线。

    4. 用户端随机取用大于 1024 的埠口进行连接：
      然后你的用户端会随机取用一个大于 1024 的埠号来对主机的 port PASV 连线。 如果一切都顺利的话，那么你的 FTP 资料就可以透过 port BB 及 port PASV 来传送了。
    发现上面的不同点了吗？被动式 FTP 资料通道的连线方向是由用户端向主机端连线的喔！ 如此一来，在 NAT 主机内部的用户端主机就可以顺利的连接上 FTP Server 了！但是，万一 FTP 主机也是在 NAT 后端那怎么办.....呵呵！那可就糗了吧～ @_@这里就牵涉到更深入的 DMZ 技巧了，我们这里暂不介绍这些深入的技巧，先理解一下这些特殊的连线方向， 这将有助于您未来伺服器架设时候的考虑因素喔！

    此外，不晓得您有无发现，透过 PASV 模式，伺服器在没有特别设定的情况下，会随机选取大于 1024 的埠口来提供用户端连接之用。那么万一主机启用的埠口被搞鬼怎么办？而且， 如此一来也很难追踪来自入侵者攻击的登录资讯啊！所以，这个时候我们可以透过 passive ports 的功能来‘限定’主机启用的 port number 喔！

    小标题的图示 FTP 的安全性问题与替代方案
    事实上，FTP 是一个不太安全的传输协定呢！怎么说呢？因为 FTP 与 Telnet 相似的， 他是以‘明码’的状态在网际网路上面传输的，所以当然就容易被有心人士将你的资料给他抓下来， 并且加以利用啦！因此，他当然不是很安全啊！所以，在网路上大家才会常常告诫说，不要随意架设 FTP 网站啊！否则主机怎么被破解的都不晓得哩！此外，由于 FTP 软体常常会有漏洞的问题，因此也要常常更新套件喔！

    另外，其实拜 SSH 所赐，目前我们已经有较为安全的 FTP 了，那就是 ssh 提供的 sftp 这个 server 啊！这个 sftp-server 最大的优点就是：‘他是经过加密的资料！’所以在网际网路上面流窜的时候， 嘿嘿！毕竟是比较安全一些啦！所以建议您，除非必要，否则的话使用 SSH 提供的 sftp-server 功能即可～

    然而这个功能对于一些习惯了图形介面，或者是有中文档名的使用者来说，实在是不怎么方便， 虽说目前有个图形介面的 filezilla 用户端软体，不过很多时候还是会发生一些莫名的问题说！ 所以，有的时候 FTP 网站还是有其存在的需要的。如果真的要架设 FTP 网站，那么还是得需要注意几个事项喔：
    1. 随时更新到最新版本的 FTP 软体，并随时注意漏洞讯息；
    2. 善用 iptables 来规定可以使用 FTP 的网域；
    3. 善用 TCP_Wrappers 来规范可以登入的网域；
    4. 善用 FTP 软体的设定来限制使用您 FTP 主机的使用者的不同权限啊；
    5. 使用 Super daemon 来进阶管理您的 FTP 主机；
    6. 随时注意使用者的家目录、以及匿名使用者登入的目录的‘档案权限’；
    7. 若不对外公开的话，或许也可以修改 FTP 的 port 。
    无论如何，在网路上听过太多人都是由于开放 FTP 这个伺服器而导致整个主机被入侵的事件，所以， 这里真的要给他一直不断的强调，要注意安全啊！

    小标题的图示 开放什么身份的使用者登入
    既然 FTP 是以明码传输，并且某些早期的 FTP 伺服器软体也有不少的安全性漏洞，那又为何需要架设 FTP 伺服器啊？ 没办法啊，总是有人有需要这个玩意儿的，譬如说各大专院校不就有提供 FTP 网站的服务吗？ 这样可以让校内的同学共同分享校内的网路资源嘛！不过，由于 FTP 登入者的身份可以分为三种， 你到底要开放哪一种身份登入呢？这个时候你可以这样简单的思考一下啰：

  • 开放实体用户的情况 (Real user)：
    很多的 FTP 伺服器预设就已经允许实体用户的登入了。不过，需要了解的是，以实体用户做为 FTP 登入者身份时， 系统预设并没有针对实体用户来进行‘限制’的，所以他可以针对整个档案系统进行任何他所具有权限的工作。 因此，如果您的 FTP 使用者没能好好的保护自己的密码而导致被入侵，那么你的整个 Linux 系统将很有可能被毁灭啊！ 开放实体用户时的建议如下：
    • 由于实体用户本来就可以透过网路连接到主机来进行工作 (例如 SSH)，因此实在没有需要特别的开放 FTP 的服务啊！ 因为例如 sftp 本来就能达到传输档案的功能啰！

    • 如果确定要让实体用户利用 FTP 伺服器的话，那么你可能需要让某些系统帐号无法登入才行，例如 bin, apache 等等。 最简单常用的作法是透过 PAM 模组来处理，譬如 vsftpd 这个软体预设可以透过 /etc/vsftpd.ftpusers 这个档案来设定不想让他具有登入权限的帐号。
  • 访客身份 (Guest)
    通常会建立 guest 身份的案例当中，多半是由于主机提供了类似‘个人 Web 首页’的功能给一般身份使用者， 那么这些使用者总是需要管理自己的网页空间吧？这个时候将使用者的身份压缩成为 guest ，并且将他的可用目录设定好，即可提供使用者一个方便的使用环境了！且不需要提供他 real user 的权限喔！ 常见的建议如下：
    • 仅提供需要登入的帐号即可，不需要提供系统上面所有人均可登入的环境啊！

    • 当然，我们在主机的设定当中，需要针对不同的访客给他们不一样的‘家目录’， 而这个家目录与使用者的权限设定需要相符合喔！例如要提供 dmtsai 这个人管理他的网页空间，而他的网页空间放置在 /home/dmtsai/www 底下，那我就将 dmtsai 在 FTP 提供的目录仅有 /home/dmtsai/www 而已，比较安全啦！而且也方便使用者啊！

    • 针对这样的身份者，需要设定较多的限制，包括：上下传档案数目与硬碟容量的限制、 连线登入的时间限制、许可使用的指令要减少很多很多，例如 chmod 就不要允许他使用等等！
  • 匿名登入使用者 (anonymous)
    虽然提供匿名登入给网际网路的使用者进入实在不是个好主意，因为每个人都可以去下载你的资料， 万一频宽被吃光光怎么办？但如同前面讲过的，学校单位需要分享全校同学一些软体资源时， FTP 伺服器也是一个很不错的解决方案啊！您说是吧。如果要开放匿名使用者的话，要注意：
    • 无论如何，提供匿名登入都是一件相当危险的事情，因为只要您一不小心， 将重要的资料放置到匿名者可以读取的目录中时，那么就很有可能会泄密！与其战战兢兢，不如就不要设定啊～

    • 果真要开放匿名登入时，很多限制都要进行的，这包括：(1)允许的工作指令要减低很多， 几乎就不许匿名者使用指令啦、(2)限制档案传输的数量，尽量不要允许‘上传’资料的设定、 (3)限制匿名者同时登入的最大连线数量，可以控制盗连喔！
    一般来说，如果你是要放置一些公开的、没有版权纠纷的资料在网路上供人下载的话， 那么一个仅提供匿名登入的 FTP 伺服器，并且对整个网际网路开放是 OK 的啦！ 不过，如果你预计要提供的的软体或资料是具有版权的，但是该版权允许你在贵单位内传输的情况下， 那么架设一个‘仅针对内部开放的匿名 FTP 伺服器 (利用防火墙处理) ’也是 OK 的啦！

    如果你还想要让使用者反馈的话，那是否要架设一个匿名者可上传的区域呢？鸟哥对这件事情的看法是.... ‘万万不可’啊！如果要让使用者反馈的话，除非该使用者是你信任的，否则不要允许对方上传！ 所以此时一个档案系统权限管理严格的 FTP 伺服器，并提供实体用户的登入就有点需求啦！ 总之，要依照您的需求来思考是否有需要喔！
    • 大标题的图示 vsftpd 伺服器基础设定
    终于要来聊一聊这个简单的 vsftpd 啰！vsftpd 的全名是‘Very Secure FTP Daemon ’的意思， 换句话说，vsftpd 最初发展的理念就是在于建构一个以安全为重的 FTP 伺服器呢！我们先来聊一聊为什么 vsftpd 号称‘非常安全’呢？然后再来谈设定吧！

    小标题的图示 为何使用 vsftpd
    为了建构一个安全为主的 FTP 伺服器， vsftpd 针对作业系统的‘程序的权限 (privilege)’概念来设计， 如果你读过基础篇的程序与资源管理章节的话， 你应该会晓得系统上面所执行的程式都会引发一个程序，我们称他为 PID (Process ID)， 这个 PID 在系统上面能进行的任务与他拥有的权限有关。也就是说， PID 拥有的权限等级越高， 他能够进行的任务就越多。举例来说，使用 root 身份所触发的 PID 通常拥有可以进行任何工作的权限等级。

    不过，万一触发这个 PID 的程式 (program) 有漏洞而导致被网路怪客 (cracker) 所攻击而取得此 PID 使用权时， 那么网路怪客将会取得这个 PID 拥有的权限呐！所以，近来发展的套件都会尽量的将服务取得的 PID 权限降低，使得该服务即使不小心被入侵了，入侵者也无法得到有效的系统管理权限，这样会让我们的系统较为安全的啦。 vsftpd 就是基于这种想法而设计的。

    除了 PID 方面的权限之外， vsftpd 也支援 chroot 这个函式的功能，chroot 顾名思义就是‘ change root directory ’的意思，那个 root 指的是‘根目录’而非系统管理员。 他可以将某个特定的目录变成根目录，所以与该目录没有关系的其他目录就不会被误用了。

    举例来说，如果你以匿名身份登入我们的 ftp 服务的话，通常你会被限定在 /var/ftp 目录下工作， 而你看到的根目录其实就只是 /var/ftp ，至于系统其他如 /etc, /home, /usr... 等其他目录你就看不到了！ 这样一来即使这个 ftp 服务被攻破了，没有关系，入侵者还是仅能在 /var/ftp 里面跑来跑去而已，而无法使用 Linux 的完整功能。自然我们的系统也就会比较安全啦！

    vsftpd 是基于上面的说明来设计的一个较为安全的 FTP 伺服器软体，他具有底下的特点喔：
    • vsftpd 这个服务的启动者身份为一般使用者，所以对于 Linux 系统的使用权限较低，对于 Linux 系统的危害就相对的减低了。此外， vsftpd 亦利用 chroot() 这个函式进行改换根目录的动作，使得系统工具不会被 vsftpd 这支服务所误用；

    • 任何需要具有较高执行权限的 vsftpd 指令均以一支特殊的上层程序 (parent process) 所控制 ，该上层程序享有的较高执行权限功能已经被限制的相当的低，并以不影响 Linux 本身的系统为准；

    • 绝大部分 ftp 会使用到的额外指令功能 (dir, ls, cd ...) 都已经被整合到 vsftpd 主程式当中了， 因此理论上 vsftpd 不需要使用到额外的系统提供的指令，所以在 chroot 的情况下， vsftpd 不但可以顺利运作，且不需要额外功能对于系统来说也比较安全。

    • 所有来自用户端且想要使用这支上层程序所提供的较高执行权限之 vsftpd 指令的需求， 均被视为‘不可信任的要求’来处理，必需要经过相当程度的身份确认后，方可利用该上层程序的功能。 例如 chown(), Login 的要求等等动作；

    • 此外，上面提到的上层程序中，依然使用 chroot() 的功能来限制使用者的执行权限。
    由于具有这样的特点，所以 vsftpd 会变的比较安全一些咯！底下就开始来谈如何设定吧！

    小标题的图示 所需要的套件以及套件结构
    vsftpd 所需要的套件只有一个，那就是 vsftpd 啊！^_^！如果你的 CentOS 没有安装， 请利用 yum install vsftpd 来安装他吧！套件很小，下载连同安装不需要几秒钟就搞定了！ 而事实上整个套件提供的设定档也少的令人高兴！简单易用就是 vsftpd 的特色啊！ ^_^！ 这些设定资料比较重要的有：
    • /etc/vsftpd/vsftpd.conf
      严格来说，整个 vsftpd 的设定档就只有这个档案！这个档案的设定是以 bash 的变数设定相同的方式来处理的， 也就是‘参数=设定值’来设定的，注意， 等号两边不能有空白喔！至于详细的 vsftpd.conf 可以使用 ‘ man 5 vsftpd.conf ’来详查。

    • /etc/pam.d/vsftpd
      这个是 vsftpd 使用 PAM 模组时的相关设定档。主要用来作为身份认证之用，还有一些使用者身份的抵挡功能， 也是透过这个档案来达成的。你可以察看一下该档案：
      [root@linux ~]# cat /etc/pam.d/vsftpd
#%PAM-1.0
auth     required  pam_listfile.so item=user sense=deny
file=/etc/vsftpd.ftpusers onerr=succeed
auth     required  pam_stack.so service=system-auth
auth     required  pam_shells.so
account  required  pam_stack.so service=system-auth
session  required  pam_stack.so service=system-auth
      上面的特殊字体为同一行，那个 file 后面接的档案是‘限制使用者无法使用 vsftpd ’之意， 也就是说，其实你的限制档案不见得要使用系统预设值，也可以在这个档案里面进行修改啦！ ^_^

    • /etc/vsftpd.ftpusers
      与上一个档案有关系，也就是 PAM 模组 (/etc/pam.d/vsftpd_ 所指定的那个无法登入的使用者设定档啊！ 这个档案的设定很简单，你只要将‘不想让他登入的帐号’写入这个档案即可。一行一个帐号，看起来像这样：
      [root@linux ~]# cat /etc/vsftpd.ftpusers
# Users that are not allowed to login via ftp
root
bin
daemon
....底下省略....
      瞧见没有？绝大部分的系统帐号都在这个档案内喔，也就是说，系统帐号预设是没有办法使用 vsftpd 的啦！ 如果你还想要让某些使用者无法登入，写在这里是最快的！

    • /etc/vsftpd.user_list
      这个档案是否能够生效与 vsftpd.conf 内的两个参数有关，分别是‘ userlist_enable, userlist_deny ’。 如果说 /etc/vsftpd.ftpusers 是 PAM 模组的抵挡设定项目，那么这个 /etc/vsftpd.user_list 则是 vsftpd 自订的抵挡项目。事实上这个档案与 /etc/vsftpd.ftpusers 几乎一模一样， 在预设的情况下，你可以将不希望可登入 vsftpd 的帐号写入这里。不过这个档案的功能会依据 vsftpd.conf 设定档内的 userlist_deny={YES/NO} 而不同，这得要特别留意喔！

    • /etc/vsftpd.chroot_list
      这个档案预设是不存在的，所以你必须要手动自行建立。这个档案的主要功能是可以将某些帐号的使用者 chroot 在他们的家目录下！但这个档案要生效与 vsftpd.conf 内的‘ chroot_list_enable, chroot_list_file ’两个参数有关。 如果你想要将某些实体用户限制在他们的家目录下而不许到其他目录去，可以启动这个设定项目喔！

    • /usr/sbin/vsftpd
      这就是 vsftpd 的主要执行档咯！不要怀疑， vsftpd 只有这一个执行档而已啊！

    • /var/ftp/
      这个是 vsftpd 的预设匿名者登入的根目录喔！
    大致上就只有这几个档案需要注意而已，而且每个档案的设定又都很简单！真是不错啊！

    小标题的图示 vsftpd.conf 设定值说明
    事实上，/etc/vsftpd/vsftpd.conf 本身就是一个挺详细的设定档，且使用‘ man 5 vsftpd.conf ’则可以得到完整的参数说明。 不过我们这里依旧先将 vsftpd.conf 内的常用参数给他写出来，希望对您有帮助：

  • 与主机较相关的设定值
    • connect_from_port_20=YES (NO)
      记得在前一小节提到的主动式连线使用的 FTP 伺服器的埠号吗？这就是 ftp-data 的埠号；

    • listen_port=21
      vsftpd 使用的命令通道之埠号，如果您想要使用非正规的埠号，在这个设定项目修改吧！ 不过你必须要知道，这个设定值仅适合以 stand alone 的方式来启动喔！(对于 super daemon 无效)

    • dirmessage_enable=YES (NO)
      当使用者进入某个目录时，会显示该目录需要注意的内容，显示的档案预设是 .message ，你可以使用底下的设定项目来修订！

    • message_file=.message
      当 dirmessage_enable=YES 时，可以设定这个项目来让 vsftpd 寻找该档案来显示讯息！

    • listen=YES (NO)
      若设定为 YES 表示 vsftpd 是以 standalone 的方式来启动的！

    • pasv_enable=YES (NO)
      启动被动式连线模式(passive mode)，一定要设定为 YES 的啦！

    • use_localtime=YES (NO)
      是否使用本地时间？vsftpd 预设使用 GMT 时间(格林威治)，所以会比台湾晚 8 小时，建议设定为 YES 吧！

    • write_enable=YES (NO)
      如果你允许使用者上传资料时，就要启动这个设定值；

    • connect_timeout=60
      单位是秒，在资料连接的主动式连线模式下，我们发出的连接讯号在 60 秒内得不到用户端的回应，则不等待并强制断线咯。

    • accept_timeout=60
      当使用者以被动式 PASV 来进行资料传输时，如果主机启用 passive port 并等待 client 超过 60 秒而无回应， 那么就给他强制断线！这个设定值与 connect_timeout 类似，不过一个是管理主动连线，一个管理被动连线。

    • data_connection_timeout=300
      如果伺服器与用户端的资料连线已经成功建立 (不论主动还是被动连线)，但是可能由于线路问题导致 300 秒内还是无法顺利的完成资料的传送，那用户端的连线就会被我们的 vsftpd 强制剔除！

    • idle_session_timeout=300
      如果使用者在 300 秒内都没有命令动作，强制离线！

    • max_clients=0
      如果 vsftpd 是以 stand alone 方式启动的，那么这个设定项目可以设定同一时间，最多有多少 client 可以同时连上 vsftpd 哩！？

    • max_per_ip=0
      与上面 max_clients 类似，这里是同一个 IP 同一时间可允许多少连线？

    • pasv_min_port=0, pasv_max_port=0
      上面两个是与 passive mode 使用的 port number 有关，如果您想要使用 65400 到 65410 这 11 个 port 来进行被动式连线模式的连接，可以这样设定 pasv_max_port=65410 以及 pasv_min_port=65400。 如果是 0 的话，表示随机取用而不限制。

    • ftpd_banner=一些文字说明
      当使用者连线进入到 vsftpd 时，在 FTP 用户端软体上头会显示的说明文字。不过，这个设定值资料比较少啦！ 建议你可以使用底下的设定值来取代这个项目；

    • banner_file=/path/file
      这个项目可以指定某个纯文字档作为使用者登入 vsftpd 伺服器时所显示的欢迎字眼。

  • 与实体用户较相关的设定值
    • guest_enable=YES (NO)
      若这个值设定为 YES 时，那么任何非 anonymous 登入的帐号，均会被假设成为 guest (访客) 喔！ 至于访客在 vsftpd 当中，预设会取得 ftp 这个使用者的相关权限。但可以透过 guest_username 来修改。

    • guest_username=ftp
      在 guest_enable=YES 时才会生效，指定访客的身份而已。

    • local_enable=YES (NO)
      这个设定值必须要为 YES 时，在 /etc/passwd 内的帐号才能以实体用户的方式登入我们的 vsftpd 主机喔！

    • local_max_rate=0
      实体用户的传输速度限制，单位为 bytes/second， 0 为不限制。

    • chroot_local_user=YES (NO)
      将使用者限制在自己的家目录之内(chroot)！这个设定在 vsftpd 当中预设是 NO，因为有底下两个设定项目的辅助喔！ 所以不需要启动他！
    • chroot_list_enable=YES (NO)
      是否启用将某些实体用户限制在他们的家目录内？预设是 NO ，不过，如果您想要让某些使用者无法离开他们的家目录时， 可以考虑将这个设定为 YES ，并且规划下个设定值

    • chroot_list_file=/etc/vsftpd.chroot_list
      如果 chroot_list_enable=YES 那么就可以设定这个项目了！ 他里面可以规定那一个实体用户会被限制在自己的家目录内而无法离开！(chroot) 一行一个帐号即可！

    • userlist_enable=YES (NO)
      是否藉助 vsftpd 的抵挡机制来处理某些不受欢迎的帐号，与底下的设定有关；

    • userlist_deny=YES (NO)
      当 userlist_enable=YES 时才会生效的设定，若此设定值为 YES 时，则当使用者帐号被列入到某个档案时， 在该档案内的使用者将无法登入 vsftpd 伺服器！该档案档名与下列设定项目有关。
    • userlist_file=/etc/vsftpd.user_list
      若上面 userlist_deny=YES 时，则这个档案就有用处了！在这个档案内的帐号都无法使用 vsftpd 喔！

  • 匿名者登入的设定值
    • anonymous_enable=YES (NO)
      设定为允许 anonymous 登入我们的 vsftpd 主机！预设是 YES ，底下的所有相关设定都需要将这个设定为 anonymous_enable=YES 之后才会生效！

    • anon_world_readable_only=YES (NO)
      仅允许 anonymous 具有下载可读档案的权限，预设是 YES。

    • anon_other_write_enable=YES (NO)
      是否允许 anonymous 具有写入的权限？预设是 NO！如果要设定为 YES， 那么开放给 anonymous 写入的目录亦需要调整权限，让 vsftpd 的 PID 拥有者可以写入才行！

    • anon_mkdir_write_enable=YES (NO)
      是否让 anonymous 具有建立目录的权限？预设值是 NO！如果要设定为 YES， 那么 anony_other_write_enable 必须设定为 YES ！

    • anon_upload_enable=YES (NO)
      是否让 anonymous 具有上传资料的功能，预设是 NO，如果要设定为 YES ， 则 anon_other_write_enable=YES 必须设定。

    • deny_email_enable=YES (NO)
      将某些特殊的 email address 抵挡住，不让那些 anonymous 登入！ 如果以 anonymous 登入主机时，不是会要求输入密码吗？密码不是要您 输入您的 email address 吗？如果你很讨厌某些 email address ， 就可以使用这个设定来将他取消登入的权限！需与下个设定项目配合：

    • banned_email_file=/etc/vsftpd.banned_emails
      如果 deny_email_enable=YES 时，可以利用这个设定项目来规定哪个 email address 不可登入我们的 vsftpd 喔！在上面设定的档案内，一行输入一个 email address 即可！

    • no_anon_password=YES (NO)
      当设定为 YES 时，表示 anonymous 将会略过密码检验步骤，而直接进入 vsftpd 伺服器内喔！所以一般预设都是 NO 的！

    • anon_max_rate=0
      这个设定值后面接的数值单位为 bytes/秒 ，限制 anonymous 的传输速度，如果是 0 则不限制(由最大频宽所限制)，如果您想让 anonymous 仅有 30 KB/s 的速度，可以设定‘anon_max_rate=30000’

    • anon_umask=077
      限制 anonymous 的权限！如果是 077 则 anonymous 传送过来的档案 权限会是 -rw------- 喔！

  • 关于系统安全方面的一些设定值
    • ascii_download_enable=YES (NO)
      如果设定为 YES ，那么 client 就可以使用 ASCII 格式下载档案。

    • ascii_upload_enable=YES (NO)
      与上一个设定类似的，只是这个设定针对上传而言！预设是 NO

    • one_process_model=YES (NO)
      这个设定项目比较危险一点～当设定为 YES 时，表示每个建立的连线 都会拥有一支 process 在负责，可以增加 vsftpd 的效能。不过， 除非您的系统比较安全，而且硬体配备比较高，否则容易耗尽系统资源喔！一般建议设定为 NO 的啦！

    • tcp_wrappers=YES (NO)
      当然我们都习惯支援 TCP Wrappers 的啦！所以设定为 YES 吧！

    • xferlog_enable=YES (NO)
      当设定为 YES 时，使用者上传与下载档案都会被纪录起来。记录的档案与下一个设定项目有关：

    • xferlog_file=/var/log/vsftpd.log
      如果上一个 xferlog_enable=YES 的话，这里就可以设定了！这个是登录档的档名啦！

    • xferlog_std_format=YES (NO)
      是否设定为 wu ftp 相同的登录档格式？！预设为 NO ，因为登录档会比较容易读！ 不过，如果您有使用 wu ftp 登录档的分析软体，这里才需要设定为 YES

    • nopriv_user=nobody
      我们的 vsftpd 预设以 nobody 作为此一服务执行者的权限。因为 nobody 的权限 相当的低，因此即使被入侵，入侵者仅能取得 nobody 的权限喔！

    • pam_service_name=vsftpd
      这个是 pam 模组的名称，我们放置在 /etc/pam.d/vsftpd 即是这个咚咚！

    上面这些是相当常见的 vsftpd 的设定参数，还有很多参数我没有列出来，您可以使用 man 5 vsftpd.conf 查阅喔！不过，基本上上面这些参数已经够我们设定 vsftpd 啰。

    小标题的图示 vsftpd 启动的模式
    vsftpd 可以拥有两种启动的方式，分别是一直在监听的 stand alone ，一种则是透过 xinetd 这个 super daemon 来管理的方式，两种方式所使用的启动程序不太相同，而我们的 CentOS 则预设是以 stand alone 来启动的。 那什么时候应该选择 stand alone 或者是 super daemon 呢？如果你的 ftp 伺服器是提供给整个网际网路来进行大量下载的任务，例如各大专院校的 FTP 伺服器，那建议你使用 stand alone 的方式， 服务的速度上会比较好。如果仅是提供给内部人员使用的 FTP 伺服器，那使用 super daemon 来管理即可啊。

  • 利用系统提供的 script 来启动 vsftpd
    其实 CentOS 不用作任何设定就能够启动 vsftpd 啰！是这样启动的啦：
    [root@linux ~]# /etc/init.d/vsftpd start
[root@linux ~]# netstat -tulnp| grep 21
tcp  0  0 0.0.0.0:21  0.0.0.0:*   LISTEN   11689/vsftpd
# 看到啰，是由 vsftpd 所启动的呢！
  • 自行设定以 super daemon 来启动
    如果你的 FTP 是很少被使用的，那么利用 super daemon 来管理不失为一个好主意。 不过若你想要使用 super daemon 管理的话，那就得要自行修改一下设定档了。其实也不难啦，你应该要这样处理的：
    [root@linux ~]# vi /etc/vsftpd/vsftpd.conf
# 找到底下这一行：大约在 109 行左右啦！
listen=YES
# 将他改成这样啊：
listen=NO
    接下来修改一下 super daemon 的设定档，底下这个档案你必须要自行建立的，原本是不存在的喔：
    [root@linux ~]# vi /etc/xinetd.d/vsftpd
service ftp
{
        socket_type             = stream
        wait                    = no
        user                    = root
        server                  = /usr/sbin/vsftpd
        log_on_success          += DURATION USERID
        log_on_failure          += USERID
        nice                    = 10
        disable                 = no
}
    然后尝试启动看看呢：
    [root@linux ~]# /etc/init.d/vsftpd stop
[root@linux ~]# /etc/init.d/xinetd restart
[root@linux ~]# netstat -tulnp| grep 21
tcp  0  0 0.0.0.0:21  0.0.0.0:*   LISTEN   32274/xinetd
    有趣吧！两者启动的方式可不一样啊！管理的方式就会差很多的呦！ 不管你要使用哪种启动的方式，切记不要两者同时启动，否则会发生错误的！ 你应该使用 chkconfig --list 检查一下这两种启动的方式，然后依据你的需求来决定用哪一种方式启动。 鸟哥底下的设定都会以 stand alone 这个 CentOS 预设的启动模式来处理，所以赶紧将刚刚的动作给他改回来喔！

    • 小标题的图示 CentOS 的 vsftpd 预设值
    在 CentOS 的预设值当中，vsftpd 是同时开放实体用户与匿名使用者的，CentOS 的预设值如下：
    [root@linux ~]# vi /etc/vsftpd/vsftpd.conf
# 底下鸟哥仅列出有设定的项目，若无设定时，请以您系统的 man 5 vsftpd.conf
# 结果去搜寻预设值即可喔！
# 1. 与匿名者有关的资讯：
anonymous_enable=YES

# 2. 与实体用户有关的设定
local_enable=YES
write_enable=YES
local_umask=022
userlist_enable=YES

# 3. 与主机有关的设定
dirmessage_enable=YES
xferlog_enable=YES
connect_from_port_20=YES
xferlog_std_format=YES
pam_service_name=vsftpd
listen=YES
tcp_wrappers=YES
    上面各项设定值请自行参考前一小节 vsftpd.conf 设定项目的详细说明吧。 而通过这样的设定值咱们的 vsftpd 可以达到如下的功能：
    • 你可以使用 anonymous 这个匿名帐号或其他实体帐号 (/etc/passwd) 登入；
    • anonymous 的家目录在 /var/ftp ，且无上传权限，亦已经被 chroot 了；
    • 实体用户的家目录参考 /etc/passwd ，并没有被 chroot ，可前往任何有权限可进入的目录中；
    • 任何于 /etc/vsftpd.ftpusers 内存在的帐号均无法使用 vsftpd ；
    • 可利用 /etc/hosts.{allow|deny} 来作为基础防火墙；
    • 当用户端有任何上传/下载资讯时，该资讯会被纪录到 /var/log/vsftpd.log 中；
    • 主动式连线的埠口为 port 20；
    • 使用格林威治时间 (GMT)。
    所以当你启动 vsftpd 后，你的实体用户就能够直接利用 vsftpd 这个服务来传输他自己的资料了。 不过比较大的问题是，因为 vsftpd 预设使用 GMT 时间，因为你在用户端使用 ftp 软体连接到 FTP 伺服器时，会发现每个档案的时间都慢了八小时了！真是讨厌啊！ 所以建议你加设一个参数值，就是‘ use_localtime=YES ’啰！
    [root@linux ~]# vi /etc/vsftpd/vsftpd.conf
# 在这个档案当中加入这一句即可
use_localtime=YES
.....底下省略.....

[root@linux ~]# /etc/init.d/vsftpd restart
    如此一来你的 FTP 伺服器不但可以提供匿名帐号来下载 /var/ftp 的资料，如果使用实体帐号来登入的话， 就能够进入到该使用者的家目录底下去了！真是很简单方便的一个设定啊！且使用本地端时间呢！ ^_^

    小标题的图示 仅有实体用户登入的设定
    虽然在 CentOS 的预设情况当中实体用户已经可以使用 FTP 的服务了，不过我们可能还需要一些额外的功能来限制实体用户， 举例来说，限制使用者无法离开家目录 (chroot) 、限制下载速率、限制使用者上传档案时的权限 (mask)等等。 底下我们先列出一些希望达到的功能，然后再继续进行额外功能的处理：
    • 希望使用台湾本地时间取代 GMT 时间；
    • 使用者登入时显示一些欢迎讯息的资讯；
    • 系统帐号不可登入主机 (亦即 UID 小于 500 以下的帐号)；
    • 一般实体用户可以进行上传、下载、建立目录及修改档案等动作；
    • 使用者新增的档案、目录之 umask 希望设定为 002；
    • 其他主机设定值保留预设值即可。
    你可以自行处理 vsftpd.conf 这个档案，以下则是一个范例。注意，如果你的 vsftpd.conf 没有相关设定值， 请自行补上吧！OK！让我们开始一步一步来依序处理先：
    1. 先建立设定档，这个设定档已经包含了主要设定值：
      [root@linux ~]# vi /etc/vsftpd/vsftpd.conf
# 1. 与匿名者相关的资讯，在这个案例中将匿名登入取消：
anonymous_enable=NO

# 2. 与实体用户相关的资讯
# 可写入，且新增目录、档案权限为 775，因为 umask 为 002 嘛！
local_enable=YES
write_enable=YES
local_umask=002
# 设定抵挡某些使用者登入的项目设定值！注意，底下的档案必须存在！
userlist_enable=YES
userlist_deny=YES
userlist_file=/etc/vsftpd.user_list

# 3. 与主机有关的设定
use_localtime=YES
dirmessage_enable=YES
xferlog_enable=YES
connect_from_port_20=YES
xferlog_std_format=YES
pam_service_name=vsftpd
listen=YES
tcp_wrappers=YES
banner_file=/etc/vsftpd/welcome.txt

[root@linux ~]# /etc/init.d/vsftpd restart

    2. 建立欢迎讯息：

      当我们想让登入者可查阅咱们系统管理员所下达的‘公告’事项时，可以使用这个设定！那就是 banner_file=/etc/vsftpd/welcome.txt 这个参数的用途了！我们可以编辑这个档案即可。 好了，开始来建立欢迎画面吧！
      [root@linux ~]# vi /etc/vsftpd/welcome.txt
欢迎光临本小站，本站提供 FTP 的相关服务！
主要的服务是针对本机实体用户提供的，
若有任何问题，请与鸟哥联络！

    3. 建立限制系统帐号登入的档案

      再来是针对系统帐号来给予抵挡的机制，其实有两个档案啦，一个是 PAM 模组管的，一个是 vsftpd 主动提供的， 在预设的情况下这两个档案分别是：

      • /etc/vsftpd.ftpusers：就是 /etc/pam.d/vsftpd 这个档案的设定所影响的；
      • /etc/vsftpd.user_list：由 vsftpd.conf 的 userlist_file 所设定。

      这两个档案的内容是一样的哩～并且这两个档案必须要存在才行。请你参考你的 /etc/passwd 设定档， 然后将 UID 小于 500 的帐号名称给他同时写到这两个档案内吧！一行一个帐号！
      [root@linux ~]# vi /etc/vsftpd.user_list
root
bin
....底下省略....

    4. 测试结果：

      你可以使用图形介面的 FTP 用户端软体来处理，也可以透过 Linux 本身提供的 ftp 用户端功能哩！ 关于 ftp 指令我们已经在之前的常用网路指令谈过了， 你可以自行前往参考。这里直接测试一下吧：
      1. 测试使用已知使用者登入，例如 dmtsai 这个实体用户：
[root@linux ~]# ftp localhost
Connected to localhost (127.0.0.1).
220-欢迎光临本小站，本站提供 FTP 的相关服务！  <==刚刚建立的欢迎讯息
220-主要的服务是针对本机实体用户提供的，
220-若有任何问题，请与鸟哥联络！
220
Name (localhost:root): dmtsai  <==登入者帐号！
331 Please specify the password.
Password: <==输入密码，荧幕不会有任何讯息的显示
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> bye
221 Goodbye.
      在以上面的方式测试完毕后，你可以在登入者帐号处分别填写 (1)root (2)anonymous 来尝试登入看看！ 如果不能登入的话，那就是设定 OK 的啦！^_^
  • chroot 的使用
    • 假设你的系统当中有许多帐号，但是 dmtsai 以及 bird1 这两个帐号是开放给一般客户的， 你不想让这两个帐号可以离开他的家目录，这个时候就得使用 chroot 的设定了。设定的方式很简单， 你先要修改 vsftpd.conf ，增加这几个项目：
    [root@linux ~]# vi /etc/vsftpd/vsftpd.conf
# 增加是否设定针对某些使用者来 chroot 的相关设定呦！
chroot_list_enable=YES
chroot_list_file=/etc/vsftpd.chroot_list

[root@linux ~]# /etc/init.d/vsftpd restart
    然后建立要被 chroot 的使用者档案：
    [root@linux ~]# vi /etc/vsftpd.chroot_list
dmtsai
bird1
    不要怀疑！这样就能够将这两个使用者限制在家目录内了，有够简单吧！

  • 更严格的 chroot 环境
    • 上面提到的是预设实体用户没有 chroot 而特定人士被 chroot 的环境，那如果我想要的是： 所有使用者预设为 chroot ，但某些使用者可不受限制的环境呢？ 那你就得要这样做了：
    [root@linux ~]# vi /etc/vsftpd/vsftpd.conf
# 预设所有实体用户被 chroot 而开放某些人可完整存取 (不 chroot) 的情况
chroot_local_user=YES
chroot_list_enable=YES
chroot_list_file=/etc/vsftpd.chroot_list

[root@linux ~]# /etc/init.d/vsftpd restart
    由于多了 chroot_list_enable=YES 这个参数，因此写入 /etc/vsftpd.chroot_list 内的使用者反而是被认为可以不受 chroot 的帐号！假设系统中的 nikky 这个使用者为被信任的，所以你要这样：
    [root@linux ~]# vi /etc/vsftpd.chroot_list
nikky
    则未来所有新增的用户都是预设被 chroot 的，除非该用户被写入 /etc/vsftpd.chroot_list 才能够不会被 chroot 呢！这不是比较严格吗？

  • 限制下载频宽
    • 有的时候你可能不希望频宽被使用者上传/下载所耗尽，而影响咱们伺服器的其他工作之运作， 所以限制使用者传输频宽有时也是需要的！假设‘我要限制所有使用者的传输频宽最大可达 100KBytes/秒’， 你可以这样做即可：
    [root@linux ~]# vi /etc/vsftpd/vsftpd.conf
# 增加底下这一个参数即可：
local_max_rate=100000

[root@linux ~]# /etc/init.d/vsftpd restart
    上述的单位是 Bytes/秒，所以你可以依据你自己的网路环境来限制你的频宽！这样就给他限制好啰！有够容易吧！^_^

  • 限制最大上线人数与同一 IP 的来源数
    • 如果你有限制最大使用频宽的话，那么你可能还需要限制最大线上人数才行！举例来说， 你希望最多只有 10 个人同时使用你的 FTP 的话，并且每个 IP 来源最多只能建立一条 FTP 的连线时， 那你可以这样做：
    [root@linux ~]# vi /etc/vsftpd/vsftpd.conf
# 增加底下的这两个参数：
max_clients=10
max_per_ip=1

[root@linux ~]# /etc/init.d/vsftpd restart
    这样就搞定了！让你的 FTP 不会人满为患呐！

  • 建立严格的可使用 FTP 的帐号列表
    • 在上述的设定当中，我们将‘不许使用 FTP 的帐号写入 /etc/vsftpd.user_list 档案中’，所以没有写入 /etc/vsftpd.user_list 当中的使用者就能够使用 FTP 了！如此一来，未来新增的使用者预设都能够使用 FTP 的服务。 如果换个角度来思考，若我想只让某些人可以使用 FTP 而已，亦即是新增的使用者预设不可使用 FTP 这个服务的话那么应该如何作呢？你需要修改设定档成为这样：
    [root@linux ~]# vi /etc/vsftpd/vsftpd.conf
# 这几个参数必须要修改成这样：
userlist_enable=YES
userlist_deny=NO
userlist_file=/etc/vsftpd.user_list

[root@linux ~]# /etc/init.d/vsftpd restart
    则此时‘写入 /etc/vsftpd.user_list 变成可以使用 FTP 的帐号’了！ 所以未来新增的使用者如果要能够使用 FTP 的话，就必须要写入 /etc/vsftpd.user_list 才行！ 使用这个机制请特别小心，否则容易搞混掉～

    透过这几个简单的设定值，相信 vsftpd 已经可以符合大部分合法 FTP 网站的需求啰！ 更多详细的用法则请参考 man 5 vsftpd.conf 吧！

    例题：
    假设你因为某些特殊需求，所以必须要开放 root 使用 FTP 传输档案，那么你应该要如何处理？
    答：
      由于系统帐号无法使用 FTP 是因为 PAM 模组与 vsftpd 的内建功能所致，亦即是 /etc/vsftpd.ftpusers 及 /etc/vsftpd.user_list 这两个档案的影响。所以你只要进入这两个档案，并且将 root 那一行注解掉， 那 root 就可以使用 vsftpd这个 FTP 服务了。 不过，不建议如此作喔！

    小标题的图示 仅有匿名登入的相关设定
    虽然你可以同时开启实体用户与匿名用户，不过建议你主机还是依据需求，针对单一种身份来设定吧！ 底下我们将针对匿名用户，且不开放实体用户。一般来说，这种设定是给类似大专院校的 FTP 伺服器来使用的哩！
    • 使用台湾本地的时间，而非 GMT 时间；
    • 提供欢迎讯息，说明可提供下载的资讯；
    • 仅开放 anonymous 的登入，且不需要输入密码；
    • 档案传输的速限为 30 Kbytes/second；
    • 资料连接的过程 (不是命令通道！) 只要超过 60 秒没有回应，就强制 Client 断线！
    • 只要 anonymous 超过十分钟没有动作，就予以断线；
    • 最大同时上线人数限制为 50 人，且同一 IP 来源最大连线数量为 5 人；
    OK！那如何设定呢？首先我们必须要知道的是匿名使用者的目录在哪里？ 事实上匿名者预设登入的根目录是以 ftp 这个使用者的家目录为主，所以你可以使用‘ finger ftp ’来查阅。 咱们的 CentOS 预设的匿名者根目录在 /var/ftp/ 中。且匿名登入者在使用 FTP 服务时，他预设可以使用‘ ftp ’ 这个使用者身份的权限喔，只是被 chroot 到 /var/ftp/ 目录中就是了。

    因为匿名者只会在 /var/ftp/ 当中浏览，所以你必须将要提供给使用者下载的资料通通给放置到 /var/ftp/ 去。 假设你已经放置了 linux 的相关目录以及 gnu 的相关软体到该目录中了，那我们可以这样做个假设：
    [root@linux ~]# mkdir /var/ftp/linux
[root@linux ~]# mkdir /var/ftp/gnu
    然后将 vsftpd.conf 的资料清空，重新这样处理他吧：
    1. 建立 vsftpd.conf 的设定资料
      [root@linux ~]# vi /etc/vsftpd/vsftpd.conf
# 将这个档案改成这样：
# 1. 与匿名者相关的资讯：
anonymous_enable=YES
# 不必提供密码啦！可直接登入哩！
no_anon_password=YES
# 限制流速啦！
anon_max_rate=30000
# 与连线时间有关的设定项目
data_connection_timeout=60
idle_session_timeout=600
# 限制连线人数
max_clients=50
max_per_ip=5

# 2. 与实体用户相关的资讯，本案例中为关闭他的情况！
local_enable=NO

# 3. 与主机有关的设定
use_localtime=YES
dirmessage_enable=YES
xferlog_enable=YES
connect_from_port_20=YES
xferlog_std_format=YES
pam_service_name=vsftpd
listen=YES
tcp_wrappers=YES
banner_file=/etc/vsftpd/anon_welcome.txt

[root@linux ~]# /etc/init.d/vsftpd restart

    2. 建立欢迎画面与下载提示讯息

      各位亲爱的观众朋友！要注意～在这个案例当中，我们将欢迎讯息设定在 /etc/vsftpd/anon_welcome.txt 这个档案中， 至于这个档案的内容你可以这样写：
      [root@linux ~]# vi /etc/vsftpd/anon_welcome.txt
欢迎光临本站所提供的 FTP 服务！
本站主要提供 Linux 作业系统相关档案以及 GNU 自由软体喔！
有问题请与站长联络！谢谢大家！
主要的目录为：

linux   提供 Linux 作业系统相关软体
gnu     提供 GNU 的自由软体
      看到啰！主要写的资料都是针对一些公告事项就是了！

    3. 测试

      同样的，我们使用 ftp 这个软体来给他测试一下吧！
      [root@linux ~]# ftp localhost
Connected to localhost (127.0.0.1).
220-欢迎光临本站所提供的 FTP 服务！  <==同样的，一些欢迎讯息
220-本站主要提供 Linux 作业系统相关档案以及 GNU 自由软体喔！
220-有问题请与站长联络！谢谢大家！
220-主要的目录为：
220-
220-linux   提供 Linux 作业系统相关软体
220-gnu     提供 GNU 的自由软体
220
Name (localhost:root): anonymous <==一定得是这个匿名帐号
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> dir
227 Entering Passive Mode (127,0,0,1,94,56)
150 Here comes the directory listing.
drwxr-xr-x    2 0    0   4096 Dec 18 17:37 gnu
drwxr-xr-x    2 0    0   4096 Dec 18 17:37 linux
drwxr-xr-x    2 0    0   4096 Aug 13 03:25 pub
226 Directory send OK.
ftp> bye
221 Goodbye.
      看到否？这次可就不需要输入任何密码了，因为是匿名登入嘛！而且，如果你输入任何其他的帐号， 那么 vsftpd 会立刻回应断线的状态喔！OK 的啦！
  • 建立上传/下载目录
    • 在上列的资料当中，实际上匿名使用者仅可进行下载的动作而已。如果你还想让匿名者可以上传档案或者是建立目录的话， 那你还需要额外增加一些设定才行：
    [root@linux ~]# vi /etc/vsftpd/vsftpd.conf
# 新增底下这几行啊！
write_enable=YES
anon_other_write_enable=YES
anon_mkdir_write_enable=YES
anon_upload_enable=YES

[root@linux ~]# /etc/init.d/vsftpd restart
    如果你设定上面四项参数，则会允许匿名者拥有完整的建立、删除、修改档案与目录的权限。 不过，实际要生效还需要 Linux 的档案系统权限正确才行！ 我们知道匿名者取得的身份是 ftp ，所以如果想让匿名者上传资料到 /var/ftp/upload 中， 则需要这样做：
    [root@linux ~]# mkdir /var/ftp/upload
[root@linux ~]# chown ftp /var/ftp/upload
    然后你以匿名者身份登入后，就会发现匿名者的根目录多了一个 /upload 的目录存在了， 并且你可以在该目录中上传档案/目录喔！ 如此一来系统的权限大开！很要命喔！所以，请仔细的控制好你的上传目录才行！

  • 建立仅可上传目录
    • 一般来说，使用者上传的资料在管理员尚未查阅过是否合乎版权等相关事宜前，是不应该让其他人下载的！ 然而前一小节的设定当中，使用者上传的资料是可以被其他人所浏览与下载的！ 如此一来实在是很危险！所以如果你要设定 /var/ftp/upload 仅能上传不能被下载时， 那么被上传的资料的权限就得要被修改一下才行！请将前一小节所设定的四个参数简化成为：
    [root@linux ~]# vi /etc/vsftpd/vsftpd.conf
# 将这几行给他改一改先！
write_enable=YES
anon_mkdir_write_enable=YES
anon_upload_enable=YES
chown_uploads=YES
chown_username=root

[root@linux ~]# /etc/init.d/vsftpd restart
    当然啦，那个 /var/ftp/upload 还是需要可以被 ftp 这个使用者写入才行！ 如此一来被上传的档案将会被修改档案拥有者成为 root 这个使用者， 而 ftp (匿名者取得的身份) 是无法读取 root 的资料的，所以也就无法被下载啰！ ^_^

  • 被动式连线埠口的限制
    • FTP 的连线分为主动式与被动式，主动式连线比较好处理，因为都是透过伺服器的 port 20 对外主动连线， 所以防火墙的处理比较简单。被动式连线就比较麻烦～因为预设 FTP 伺服器会随机取几个没有在使用当中的埠口来建立被动式连线，那防火墙的设定就麻烦啦！

    没关系，我们可以透过指定几个固定范围内的埠口来作为 FTP 的被动式资料连接之用即可， 这样我们就能够预先知道 FTP 资料连结的埠口啦！举例来说，我们假设被动式连接的埠口为 65400 到 65410 这几个埠口时，可以这样设定：
    [root@linux ~]# vi /etc/vsftpd/vsftpd.conf
# 增加底下这几行即可啊！
pasv_min_port=65400
pasv_max_port=65410

[root@linux ~]# /etc/init.d/vsftpd restart
    匿名使用者的设定大致上这样就能符合你的需求啰！自己看着办吧！ ^_^
    大标题的图示 用户端的 FTP 连线软体
    用户端的连线软体主要有文字介面的 ftp 及 lftp 这两支指令，详细的使用方式请参考常用网路指令章节的说明。至于 Linux 底下的图形介面软体，可以参考 gftp 这支程式喔！图形介面的啦！很简单啊！

    上述的软体都是自由软体啊，那么 Windows 作业系统有没有自由软体啊？有的， 你可以使用 filezilla 这个好东西！这个玩意儿的详细说明与下载点可以在底下的连结找到：
    • 说明网站：http://filezilla.sourceforge.net/
    • 下载网站：http://sourceforge.net/project/showfiles.htm?group_id=21558
    目前 (2006/12) 最新的稳定版本是 2.2.29 版，所以底下鸟哥就以这个版本来跟大家说明。 为什么要选择 Filezilla 呢？除了他是自由软体之外，这家伙竟然可以连结到 SSH 的 sftp 呢！ 真是很不错的一个家伙啊！^_^！另外要注意的是，底下鸟哥是以 Windows 版本来说明的， 不要拿来在 X server 上面安装喔！ ^_^

    因为这个程式是给 Windows 安装用的，所以安装的过程就是.....(下一步)^n 就好了！ 并且这个程式支援多国语系，所以你可以选择繁体中文呢！实在是很棒！ 安装完毕之后，请你执行他，就会出现如下的画面了：

    Filezilla 的操作方式
    图四、Filezilla 的操作方式

    图四的 1, 2, 3, 4, 5 分别代表的资料是：
    1. 代表 FTP 伺服器的输出资讯，例如欢迎讯息等资讯；
    2. 代表本机的档案，与 3 有关；
    3. 代表本机的磁碟机所在处，与 2 有关；
    4. 代表远端 FTP 伺服器的目录与档案；
    5. 代表传输时的伫列资讯
    而另外 a, b, c 则代表的是：
    1. 站台管理员，你可以将一些常用的 FTP 伺服器的 IP 与使用者资讯记录在此；
    2. 更新，如果你的资料有更新，可使用这个按钮来同步 filezilla 的荧幕显示；
    3. 位址、使用者、密码与连接埠这四个玩意儿可以即时连线，不记录资讯。
    好，接下来我们连接到 FTP 伺服器上面去，所以你可按下图四的 a 部分，会出现如下画面：

    Filezilla 的操作方式
    图五、Filezilla 的操作方式

    上图五的箭头与相关的内容是这样的：
    1. 先按下‘新站台’的按钮，然后在箭头 2 的地方就会出现可输入的方框；
    2. 在该方框当中填写一个你容易记录的名字，随便填写也没有关系的；
    3. 在这个方框当中填写主机的 IP 就好了，连接埠如果不是标准的 port 21 ，请填写其他埠口。
    4. 这个地方可以挑选不同的连线机制，包括几个常见的机制为：
      • 标准 FTP
      • FTP + SSL/TLS 加密机制
      • FTP + SSL 加密机制
      • SFTP (透过 SSH)
      • FTP + TLS 加密机制
      如果你预计要利用 filezilla 连接到 sftp 的话，这个地方可以挑选 sftp 喔！不然的话就用 FTP 即可；
    5. 在这里选择匿名登入或者是一般登入，所谓一般登入即是利用实体帐号来登入；
    6. 在这里如果使用一般登入时，则你可以填写使用者及密码栏位，否则就会主动以 anonymous 来匿名登入呢！
    基本上这样设定完就能够连上主机了，不过，如果你还想要更详细的规范资料连接的方式 (主动式与被动式) 以及其他资料时， 可以按下图五的‘进阶设定’按钮，就会出现如下画面了：

    Filezilla 的操作方式
    图六、Filezilla 的操作方式

    在这个画面当中你可以选择是否使用被动式传输机制，还可以调整时区的显示呢！ 如果 FTP 伺服器的时间设定错误，导致出现 8 小时的误差时 (台北时间与 GMT 时间)，就能够利用这个设定项目来调整了！ 此外，也能够进行语系的调整，呵呵！绝大部分的 FTP 连线项目都考虑到了，这样就 OK 啦！然后按下图六的确定， 并到图五画面当中按下‘连线’后，就能够得到如下的画面了：

    Filezilla 的操作方式
    图七、Filezilla 的操作方式

    更多的用法就请您自行研究啰！

  • 利用浏览器功能
    • 我们在 Apache 这个 WWW 伺服器的章节当中曾经谈过浏览器所支援的协定，其中一个就是 ftp 这个协定啰！ 这个协定的处理方式可以在网址列的地方这样输入的：
    • ftp://username@your_ip
    要记得，如果你没有输入那个 username@ 的字样时，系统预设会以匿名登入来处理这次的连线。因此如果你想要使用实体用户连线时， 就在在 IP 或主机名称之前填写你的帐号。举例来说，鸟哥的主机 (192.168.1.254) 若有 dmtsai 这个使用者， 那我启动浏览器后，可以这样做：
    • ftp://dmtsai@192.168.1.254
    然后在出现的对话视窗当中输入 dmtsai 的密码，就能够使用浏览器来管理我在 FTP 伺服器内的档案系统啰！ 是否很容易啊！ ^_^
    大标题的图示 其他 FTP 伺服器相关设定
    除了基础设定之外，我们针对 FTP 还有哪些需要考虑的地方呢？底下就来谈一谈：

    小标题的图示 防火墙设定
    防火墙设定有什么难的？将防火墙那一章里面的 script 拿出来， 加入底下这一段在内：
    iptables -A INPUT -p TCP -i $EXTIF --dport 21 -j ACCEPT
    这样就好了吗？当然不是啦！要记得我们还可能会有被动式连线的状态啊，所以某些特殊情况底下， 或许你还需要启动被动式连线的监听的埠口哩！以上面我们谈过的 port 65400 ~ 65410 这几个当作范例好了， 你应该还需要加入这一段呢：
    iptables -A INPUT -p TCP -i $EXTIF --dport 65400:65410 -j ACCEPT
    另外，如果你想要使用 tcp wrappers 的方式来处理 FTP 的连线时，例如仅允许内部 (192.168.1.0/24) 来连线，那应该可以这样做：
    [root@linux ~]# vi /etc/hosts.allow
vsftpd: 192.168.1.0/255.255.255.0

[root@linux ~]# vi /etc/hosts.deny
vsftpd: ALL
    小标题的图示 Super daemon 的额外管理项目
    关于使用 xinetd 这个 super daemon 来管理服务的方法还记得吧？ 要记得基础篇谈到的认识系统服务喔！ 如果忘记的话，也要记得使用‘ man xinetd.conf ’这个好用的查询功能呐！

    我们知道 stand alone 的启动方法可以透过 max_clients 及 max_per_ip 这两个参数来处理同时上线的最大人数。 但是如果是 super daemon 管理的呢？那么就得要透过 xinetd 的语法来处理了。 如果你是使用 super daemon 来管理 vsftpd 的话， 要记得先修改 vsftpd.conf 内的‘listen’项目喔。然后这样做：
    [root@linux ~]# vi /etc/xinetd.d/vsftpd
# vsftpd is the secure FTP server.
service ftp
{
    disable           = no
    socket_type       = stream
    wait              = no
    user              = root
    server            = /usr/sbin/vsftpd
    server_args       = /etc/vsftpd/vsftpd.conf
# 上面这个 server 的设定请依照您的主机环境来设定！
# 至于 server_args 则请写入您的 vsftpd 的设定档完整档名即可！
    per_source        = 5     <==与同一 IP 的连线数目有关
    instances         = 200   <==同一时间最多的连线数目
    no_access         = 192.168.1.3
    banner_fail       = /etc/vsftpd/vsftpd.busy_banner
# 上面这个档案就是当主机忙碌中，则在 Client 端显示的内容！
    log_on_success    += PID HOST DURATION
    log_on_failure    += HOST
}

[root@linux ~]# vi /etc/vsftpd/vsftpd.conf
# 确定这个档案内存在这个参数喔！
listen=NO

[root@linux ~]# vi /etc/vsftpd/vsftpd.busy_banner
421 很抱歉，伺服器现在上线人数过多，请待会儿再连线！
# 那个 421 是错误代码哩！

[root@linux ~]# /etc/init.d/vsftpd stop
[root@linux ~]# /etc/init.d/xinetd restart
    这样设定就可以啦！很简单的一个设定动作，就可以让您的 vsftpd 变的更安全一些喔！

    小标题的图示 常见问题与解决之道
    底下说明几个常见的问题与解决之道吧！

  • 如果在 Client 端上面发现无法连线成功，请检查：
    1. iptables 防火墙的规则当中，是否开放了 client 端的 port 21 登入？
    2. 在 /etc/hosts.deny 当中，是否将 client 的登入权限挡住了？
    3. 在 /etc/xinetd.d/vsftpd 当中，是否设定错误，导致 client 的登入权限被取消了？
  • 如果 Client 已经连上 vsftpd 伺服器，但是却显示‘ XXX file can't be opend ’的字样，请检查：
    1. 最主要的原因还是在于在 vsftpd.conf 当中设定了检查某个档案，但是您却没有将该档案设定起来， 所以，请检查 vsftpd.conf 里面所有设定的档案档名，使用 touch 这个指令将该档案建立起来即可！
  • 如果 Client 已经连上 vsftpd 伺服器，却无法使用某个帐号登入，请检查：
    1. 在 vsftpd.conf 里面是否设定了使用 pam 模组来检验帐号，以及利用 userlist_file 来管理帐号？
    2. 请检查 /etc/vsftpd.ftpusers 以及 /etc/vsftpd.user_list 档案内是否将该帐号写入了？
  • 如果 Client 无法上传档案，该如何是好？
    1. 最可能发生的原因就是在 vsftpd.conf 里面忘记加上这个设定‘write_enable=YES’这个设定，请加入；
    2. 是否所要上传的目录‘权限’不对，请以 chmod 或 chown 来修订；
    3. 是否 anonymous 的设定里面忘记加上了底下三个参数：
      • anon_other_write_enable=YES
      • anon_mkdir_write_enable=YES
      • anon_upload_enable=YES
    4. 是否因为设定了 email 抵挡机制，又将 email address 写入该档案中了！？请检查！
    5. 是否设定了不许 ASCII 格式传送，但 Client 端却以 ASCII 传送呢？请在 client 端以 binary 格式来传送档案！
    上面是蛮常发现的错误，如果还是无法解决您的问题，请您务必分析一下这两个档案：/var/log/vsftpd.log 与 /var/log/messages ，里面有相当多的重要资料，可以提供给您进行除错喔！

    • 大标题的图示 重点回顾
    • FTP 是档案传输协定 (File Transfer Protocol) 的简写，主要的功能是进行伺服器与用户端的档案管理、传输等事项；
    • FTP 的伺服器软体非常多，例如 Wu FTP, Proftpd, vsftpd 等等，各种 FTP 伺服器软体的发展理念并不相同， 所以选择时请依照您的需求来决定所需要的软体套件；
    • FTP 使用的是明码传输，而过去一些 FTP 伺服器软体也曾被发现安全漏洞，因此设定前请确定该软体已是最新版本，避免安全议题的衍生；
    • 由于 FTP 是明码传输，其实可以使用 SSH 提供的 sftp 来取代 FTP ；
    • 大多数的 FTP 伺服器软体都提供 chroot 的功能，将实体用户限制在他的家目录内；
    • FTP 这个 daemon 比较常以 super daemon 来管理，亦即 xinetd 或者是 inet 来管理；
    • FTP 这个 daemon 所开启的正规埠口为 20 与 21 ，其中 21 为命令通道， 20 为资料传输通道；
    • FTP 的资料传输方式主要分为主动与被动(Passive, PASV)，如果是主动的话，则 ftp-data 在伺服器端主动以 port 20 连接到用户端，否则则开放被动式监听的埠口等待用户端来连接；
    • 在 NAT 主机内的用户端 FTP 软体连线时可能发生困扰，这可以透过 iptables 的 nat 模组或利用被动式连线来克服；
    • 一般来说， FTP 上面共有三个群组，分别是实体用户、访客与匿名登入者(real, guest, anonymous)；
    • 可以藉由修改 /etc/passwd 里面的 Shell 栏位，来让使用者仅能使用 FTP 而无法登入主机；
    • FTP 的指令、与使用者活动所造成的登录档是放置在 /var/log/xferlog 里面；
    • 在用户端使用 ftp 这个程式时，可以加上‘ ftp -p hostname’来让连线变成 passive 模式。
    • vsftpd 为专注在安全议题上而发展的一套 FTP 伺服器软体，他的设定档在 /etc/vsftpd/vsftpd.conf ；
    大标题的图示 课后练习
    • FTP 在建立连线以及资料传输时，会建立哪些连线？
      需建立两种连线，分别是命令通道与资料传输通道。在主动式连线上为 port 21(ftp) 与 port 20(ftp-data)。
    • FTP 主动式与被动式连线有何不同？
      主动式连线的时候，命令连线是由 client 端主动连接到主机端，但是 ftp-data 则是由主机端主动的连线到 client 端。至于被动式连线的时候，则不论 command 还是 ftp-data 的连线，伺服器端都是监听客户端的要求的！
    • 有哪些动作可以让您的 FTP 主机更为安全 (secure) ？
      • 随时更新伺服器软体到最新版本；
      • 让 guest 与 anonymous 的家目录限制在固定的目录中(chroot 或是 restricted)；
      • 使用 TCP_Wrappers 启动 FTP ，并以他来控制可连线的 IP；
      • 拒绝 guest 与 anonymous 使用 change, delete, rename 等等指令；
      • 拒绝 root 的登入或者其他系统帐号的登入；
      • 拒绝大部分的 upload 行为！
    • 我们知道 ftp 会启用两个 ports ，请问这两个 port 在哪里规范的 (以 vsftpd 为例)？而且，一般正规的 port 是几号？
      若为 stand alone 时，都是由 vsftpd.conf 规范，命令通道为 listen_port=21 规范，资料连接为 connect_from_port_20=YES 及pasv_max_port=0, pasv_max_port=0 所规范。
      若是 super daemon 所管理时，命令通道则由 /etc/services 所规范了。
    • 那几个档案可以用来抵挡类似 root 这种系统帐号的登入 FTP？
      /etc/vsftpd.ftpusers
      /etc/vsftpd.user_list
    • 在 FTP 的 server 与 client 端进行资料传输时，有哪两种模式？为何这两种模式影响资料的传输很重要？
      资料的传输有 ASCII 与 Binary 两种方式，在进行 ascii 传送方式时，被传送的档案将会以文字模式来进行传送的行为， 因此，档案的属性会被修改过，可能造成执行档最后却无法执行等的问题！一般来说，ASCII 通常仅用在文字档案与一些原始码档案的传送。
    • 我的主机明明时区设定没有问题，但为何登入 vsftpd 这个 FTP 服务时，时间就是少八小时？该如何解决？
      肯定是时区方面出了问题，应该就是 vsftpd.conf 里面少了‘ use_localtime=YES ’这个参数了。
    大标题的图示 参考资料
    • vsftpd 官方网站：http://vsftpd.beasts.org/
    • man 5 vsftpd.conf
    • Filezilla 官方网站：http://filezilla.sourceforge.net/
    2003/09/03：首次完成
    2003/09/04：加入 FTP 伺服器软体的选择建议
    2006/12/19：将旧的文章移动到此处，并请自行参考 wu-ftp, proftpd 等服务！
    2006/12/20：将分散在各处的 FTP 原则说明完毕，也更新完毕啰～疲劳～
    2003/09/03以来统计人数


鸟哥的 Linux 私房菜 -- NTP 时间伺服器

为取得较佳浏览结果，请爱用 firefox 浏览本网页

NTP 时间伺服器
切换解析度为 800x600
最近更新日期：2006/12/08
很多时候由于电脑硬体的问题，所以我们都会调整一下时间，好让电脑系统的时间可以一直保持正确的状态。 而既然要调整时间，那么自然就会有一个让我们可以对照着来调整时间的‘准确时间’咯！ 在实际生活中，我们可以透过电视台、广播电台、电话等等来调整我们的手表，那么如果是在网路上呢？ 该如何让我们的主机随时保持正确的时间资讯？！另外，整个地球被切分成为 24 个时区，那么什么是 GMT (格林威治时间)，我们所在的时区又是哪一区呢？让我们来简单的谈一谈吧！

1. 本章的行前准备工作
2. 关于时区与网路校时的通讯协定
    2.1 什么是时区？全球有多少时区？GMT 在那个时区？
    2.2 什么是夏季节约时间 (daylight savings)？
    2.3 Coordinated Universal Time (UTC)与系统时间的误差
    2.4 NTP 通讯协定
 3. NTP 伺服器的安装与设定
    3.1 所需套件与套件结构
    3.2 主要设定档 ntp.conf 的处理
    3.3 NTP 的启动与观察
    3.4 安全性设定
 4. 用户端的时间更新方式
    4.1 Linux 系统时间与硬体时间
    4.2 Linux 系统时区与手动校时工作： date, hwclock
    4.3 Linux 的网路校时
    4.4 Windows 的网路校时
 5. 重点回顾
6. 课后练习
7. 参考资料
8. 针对本文的建议：http://phorum.vbird.org/viewtopic.htm?p=117976
大标题的图示 本章的行前准备工作
NTP 伺服器是个很容易设定的服务，你只要熟悉网路基础即可轻易的将他设定好。 这一章没有什么很重要的预习功课，您可以轻松的学习啊！ ^_^

大标题的图示 关于时区与网路校时的通讯协定
时间对于现代人来说是很重要的，因为‘ Time is money ！’。既然时间如此重要，对于 Internet 来说应该也是很重要吧？ 为什么呢？还记得我们在基础学习篇里面谈到的‘登录档分析’吧？ 如果你架设了一个登录档记录伺服器的话，那么总得要分析每个主机所传来的资讯吧？如果每一部主机的时间都不相同， 那如何判断问题发生的时间点？所以啰，‘每一部主机的时间同步化’就很重要了。

每一部主机时间的同步化重要性当然不只如此，包括之前谈到的 DHCP 用户端/伺服器端所需要的租约时间限制、 网路侦测时所需要注意的时间点、刚刚谈到的登录档分析功能、具有相关性的主机彼此之间的错误侦测等等， 都需要具有相同的时间才能够捉出问题呢。好了，底下咱们就来聊一聊，如何利用网路来进行主机的时间同步化吧！

小标题的图示 什么是时区？全球有多少时区？GMT 在那个时区？
因为地球是圆的，所以同一个时刻，在地球的一边是白天，一边是黑夜。而因为人类使用一天 24 小时的制度，所以，在地球对角的两边就应该差了 12 的小时才对。由于同一个时间点上面， 整个地球的时间应该都不一样，为了解决这个问题，所以可以想见的，地球就被分成 24 个时区了！

那么这 24 个时区是依据什么来划分的呢？由于地球被人类以‘经纬度’座标来进行定位， 而经度为零的地点在英国‘格林威治’这个城市所在纵剖面上， (注：所谓的纵剖面就是由南极切到北极的直线，而横切面就是与赤道平行的切线)，如下图所示：

地球的子午线、经纬度与时区的分隔概念
图一、地球的子午线、经纬度与时区的分隔概念

因为绕地球一圈是 360 度角，这 360 度角共分为 24 个时区，当然一个时区就是 15 度角啦！ 又由于是以格林威治时间为标准时间(Greenwich Mean Time, GMT 时间)，加上地球自转的关系，因此，在格林威治以东的区域时间是比较快的(+小时)， 而以西的地方当然就是较慢啰！

以台湾为例，因为台湾所在地约为东经 120 度北纬 25 度左右，又因为台湾在格林威治的东方 (废话！因为是东经嘛！ ^_^)，因此台湾本地时间 (local time) 会比 GMT 时间快 8 小时 (GMT + 8)。当格林威治时间为零点，台湾就已经是早上八点了！ 底下约略列出各个时区的名称与所在经度，以及与 GMT 时间的时差：

标准时区 | 经度 | 时差
GMT , Greenwich Mean Time | 0 W/E | 标准时间
CET , Central European | 15 E | +1 东一区
EET , Eastern European | 30 E | +2 东二区
BT , Baghdad | 45 E | +3 东三区
USSR, Zone 3 | 60 E | +4 东四区
USSR, Zone 4 | 75 E | +5 东五区
Indian, First | 82.3E | +5.5东五半区
USSR, Zone 5 | 90 E | +6 东六区
SST , South Sumatra | 105 E | +7 东七区
JT , Java | 112 E | +7.5东七半区
CCT , China Coast (台湾所在地) | 120 E | +8 东八区
JST , Japan | 135 E | +9 东九区
SAST, South Australia | 142 E | +9.5东九半区
GST , Guam | 150 E | +10 东十区
NZT , New Zealand | 180 E | +12 东十二区
Int'l Date Line | 180 E/W | 国际换日线
BST , Bering | 165 W | -11 西十一区
SHST, Alaska/Hawaiian | 150 W | -10 西十区
YST , Yukon | 135 W | -9 西九区
PST , Pacific | 120 W | -8 西八区
MST , Mountain | 105 W | -7 西七区
CST , Central | 90 W | -6 西六区
EST , Eastern | 75 W | -5 西五区
AST , Atlantic | 60 W | -4 西四区
Brazil, Zone 2 | 45 W | -3 西三区
AT , Azores | 30 W | -2 西二区
WAT , West Africa | 15 W | -1 西一区

所以啰，台湾时间是 GMT + 8 就很容易推算出来了吧！要特别留意的是，很多朋友在安装 Linux 的时候， 总是会发现目前的时间慢或者快了 8 小时，不要怀疑，绝对与时区有关！ 赶紧给他查一下如何调整时区吧！ ^_^。

另外，在上表中有个比较有趣的时区，那就是在太平洋上面的国际换日线了！我们刚刚说，在格林威治的东边时间会较快， 而在西边时间会较慢，但是两边各走了 180 度之后就会碰头啊！那不就刚好差了 24 小时吗？没错啦！ 所以才订定为‘国际换日线’啊！国际换日线刚好在太平洋上面，因此，如果您有坐飞机到美国的经验应该会发现，咦！ 怎么出发的时间是星期六下午，坐了 13 个小时的飞机到了美国还是星期六！因为刚好通过了国际换日线， 日期减少了一天喔！如果反过来，由美国到台湾，日期就会多加一天喔！ ^_^

小标题的图示 什么是夏季节约时间 (daylight savings)？
除了时区的概念先建立起来之后，现在再来谈一谈，那么什么是‘夏季节约时间’？ 既然是‘夏季节约时间’当然主要是与夏天有关啦！因为地球在运行的时候是呈现一个倾斜角在绕太阳运转的， 所以才有春夏秋冬(这个大家应该都知道啦！)，在夏天的时候，白天的时间会比较长，所以为了节约用电， 因此在夏天的时候某些地区会将他们的时间定早一小时，也就是说，原本时区是 8 点好了， 但是因为夏天太阳比较早出现，因此把时间向前挪，在 8 点的时候，订定为该天的 7 点～如此一来， 我们就可以利用阳光照明，省去了花费电力的时间，因此才会称之为夏季节约时间！

因为台湾实在是太小了，并没有横跨两个时区，因此，夏季节约时间对我们来说，虽然还是有帮助啦！ 不过，似乎没有特别推行的样子说～

小标题的图示 Coordinated Universal Time (UTC)与系统时间的误差
了解了一些时区的概念之后，这里要谈的是‘什么是正确的时间’。 在计算时间的时候，最准确的计算应该是使用‘原子震荡周期’所计算的物理时钟了 (Atomic Clock, 也被称为原子钟)，这也被定义为标准时间 (International Atomic Time)。而我们常常看见的 UTC 也就是 Coordinated Universal Time (协和标准时间)就是利用这种 Atomic Clock 为基准所定义出来的正确时间。例如 1999 年在美国启用的原子钟 NIST F-1， 他所产生的时间误差每两千年才差一秒钟！真的是很准呐！这个 UTC 标准时间是以 GMT 这个时区为主的喔！所以本地时间与 UTC 时间的时差就是本地时间与 GMT 时间的时差就是了！

事实上，在我们的身边就有很多的原子钟，例如石英表，还有电脑主机上面的 BIOS 内部就含有一个原子钟在纪录与计算时间的进行呐！不过由于原子钟主要是利用计算晶片 (crystal) 的原子震荡周期去计时的，这是因为每种晶片都有自己的独特的震荡周期之故。 然而因为这种晶片的震荡周期在不同的晶片之间多多少少都会有点差异性， 甚至同一批晶片也可能会或多或少有些许的差异(就连温度也可能造成这样的误差呢！)，因此也就造成了 BIOS 的时间会三不五时的给他快了几秒或者慢了几秒。

或许您会认为，BIOS 计时器每天快个五秒也没有什么了不起的，不过如果您再仔细的算一算，会发现，一天快五秒， 那么一个月快2.5分钟，一年就快了 75 分钟了！所以说，呵呵！时间差是真的会存在的！ 那么如果您的电脑真的有这样的情况，那要怎么来重新校正时间呢？那就需要‘网路校时’ (Network Time Protocol, NTP) 的功能了！底下我们就谈一谈那个 NTP 的 daemon 吧！

小标题的图示 NTP 通讯协定
如同前面说的，电脑主机主要是以 BIOS 内部的时间为主要的时间依据，而偏偏这个时间可能因为 BIOS 内部晶片本身的问题，而导致 BIOS 时间与标准时间 (UTC) 有一点点的差异存在！ 所以为了避免主机时间因为长期运作下所导致的时间偏差，进行时间同步 (synchronize) 的工作就显的很重要了！

那么怎么让时间同步化呢？想一想，如果我们选择几部主要主机 (Primary server) 调校时间，让这些 Primary Servers 的时间同步之后，再开放网路服务来让 Client 端连线，并且提供 Client 端调整自己的时间，不就可以达到全部的电脑时间同步化的运作了吗！那么什么协定可以达到这样的功能呢？那就是 Network Time Protocol ，另外还有 Digital Time Synchronization Protocol (DTSS) 也可以达到相同的功能！

不过，到底 NTP 这个 daemon 是如何让 Server 与 Client 同步他们的时间呢？
  1. 首先，主机当然需要启动这个 daemon ，之后，
  2. Client 会向 NTP Server 发送出调校时间的 message ，
  3. 然后 NTP Server 会送出目前的标准时间给 Client ，
  4. Client 接收了来自 Server 的时间后，会据以调整自己的时间，就达成了网路校时咯！
不过，在上面的步骤中您有没有想到一件事啊，那就是如果 Client 到 Server 的讯息传送时间过长怎么办？举例来说，我在台湾以 ADSL 的 PC 主机，连线到美国的 NTP Server 主机进行时间同步化要求，而美国 NTP Server 收到我的要求之后，就发送当时的正确时间给我，不过， 由美国将资料传送回我的 PC 时，时间可能已经延迟了 10 秒钟去了！这样一来，我的 PC 校正的时间是 10 秒钟前的标准时间喔！此外，如果美国那么 NTP 主机有太多的人喜欢上去进行网路校时了，所以 loading (负荷) 太重啦！导致讯息的回传又延迟的更为严重！那怎么办？

为了这些延迟的问题，有一些 program 已经开发了自动计算时间传送过程的误差，以更准确的校准自己的时间！当然啦，在 daemon 的部分，也同时以 server/client 及 master/slave 的架构来提供使用者进行网路校时的动作！所谓的 master/slave 就有点类似 DNS 的系统咯！举例来说，台湾的标准时间主机去国际标准时间的主机校时， 然后各大专院校再到台湾的标准时间校时，然后我们再到各大专院校的标准时间校时！这样一来，那几部国际标准时间主机 (Time server) 的 loading 就不至于太大，而我们也可以很快速的达到正确的网路校时的目的呢！台湾常见的 Time Server 有：
  • tock.stdtime.gov.tw
  • time.stdtime.gov.tw
  • clock.stdtime.gov.tw
  • freq_f.stdtime.gov.tw
  • tick.stdtime.gov.tw
至于 ntp 这个 daemon 是以 port 123 为连结的埠口 (使用 UDP 封包)，所以我们要利用 Time server 来进行时间的同步更新时，就得要使用 NTP 套件提供的 ntpdate 来进行 port 123 的连线喔！关于网路校时更多的说明，可以到 NTP 的官方网站上察看喔！
    http://www.ntp.org
大标题的图示 NTP 伺服器的安装与设定
NTP 伺服器也是一个很容易就可以架设成功的玩意儿，不过这个套件在不同的 distribution 上面可能有不一样的名称， 你要作的其实就是将他安装起来之后，规定一部上层 NTP 伺服器来同步化你的时间即可啊！ 如果你只是想要进行你自己单部主机的时间同步化，别架设 NTP ，直接使用 NTP 用户端软体即可喔！

小标题的图示 所需套件与套件结构
在 CentOS 上头，你所需要的套件其实仅有 ntp 这个玩意儿而已，请自行使用 rpm 去找找看， 若没有安装，请拿出原版光碟来安装，或者利用 yum install ntp 即可啊！ 万一找不到的话，那就用 Tarball 的方式来安装吧！请自行前往 ntp 官方网站下载原始码来安装先。 不过，我们还需要时区相关的资料档案，所以你需要的套件有：
  • ntp
    就是 NTP 伺服器的主要套件啦，包括设定档以及执行档等等，都是这个套件提供的；

  • tzdata
    套件名称为‘ Time Zone data ’的缩写啰～主要提供了各个时区对应的显示格式。
至于你需要的档案方面，主要有这几个玩意儿啦：
  • /etc/ntp.conf
    这个是 NTP daemon 的主要设定档，依据不同的版本放置的目录可能会不同，不过档名都是一样的！使用 locate ntp.conf 搜寻一下您的系统有没有这个档案吧！这也是 NTP 唯一的一个设定档案！

  • /usr/share/zoneinfo/
    这是个目录，这个目录是 Linux 本身提供的，而不是 NTP 所提供的。 在这个目录下的档案其实是规定了各主要时区的时间设定档案，例如台湾地区的时区设定档案在 /usr/share/zoneinfo/Asia/Taipei 就是了！这个目录里面的档案与底下要谈的两个档案 (clock 与 localtime) 是有关系的喔！

  • /etc/sysconfig/clock
    这个档案其实也不包含在 NTP 的 daemon 当中，因为这个是 linux 的主要时区设定档案啊！每次开机后 Linux 会自动的读取这个档案来设定自己系统所预设要显示的时间说！举个例子来说， 在我们台湾地区的本地时间设定中，这个档案内应该会出现一行‘ZONE="Asia/Taipei"’的字样， 这表示我们的时间设定档案‘要取用 /usr/share/zoneinfoe/Asia/Taipei 那个档案’的意思！

  • /etc/localtime
    这个档案就是‘本地端的时间设定档’啦！刚刚那个 clock 档案里面规定了使用的时间设定档 (ZONE) 为 /usr/share/zoneinfo/Asia/Taipei ，所以说这就是本地端的时间了，此时 Linux 系统就会将 Taipei 那个档案复制一份成为 /etc/localtime ，所以未来我们的时间显示就会以 Taipei 那个时间设定档案为准。

    好了，如果现在我这部主机搬到日本东京去了，那么我应该如何调整时间呢？其实什么调整都不需要，因为我们的 localtime 主要是分析与 UTC 时间的时差来显示的格式，所以，您只要将 /etc/sysconfig/clock 里面的 ZONE 设定成为 Asia/Tokyo 并且将 /usr/share/zoneinfo/Asia/Tokyo 复制成为 /etc/localtime ，呵呵！就能显示时间为日本东京的时间了！这样是否能够了解？

  • /bin/date
    这个是 Linux 系统上面常见的日期与时间输出指令，用途很广喔！除了输出时间外，也可以修改时间。

  • /sbin/hwclock
    这是一个 root 才能执行的指令，因为 Linux 系统上面 BIOS 时间与 Linux 系统时间是分开的，所以使用 date 这个指令调整了时间之后，还需要使用 hwclock 才能将修改过后的时间写入 BIOS 当中！

  • /usr/sbin/ntpd
    这就是 NTP 的主要 daemon 档案啦！得要启动他才能提供 NTP 服务。注意，这个指令预设会参考 /etc/ntp.conf 里面的设定喔！

  • /usr/sbin/ntpdate
    这个就是 Client 端用来连接 NTP Server 的主要执行档啰！如果您没有要启用 NTP 而仅想要使用 NTP Client 功能的话，那么只会用到这个指令而已啦！

  • /usr/sbin/ntptrace
    这个指令可以用来追踪某部时间伺服器的时间对应关系，这也是个很有用的指令喔！底下我们会介绍如何使用这支程式！
接下来，我们先来谈一谈如何设计那个 /etc/ntp.conf 吧！

小标题的图示 主要设定档 ntp.conf 的处理
如前所述，由于 NTP 时间伺服器采用类似阶层架构 (stratum) 来处理时间的同步化， 所以他使用的是类似一般 server/client 的主从架构。网路社会上面有提供一些主要与次要的时间伺服器， 这些均属于第一阶及第二阶的时间伺服器 (stratum-1, stratum-2) ，如下所示：
  • 主要时间伺服器：http://www.eecis.udel.edu/~mills/ntp/clock1a.html
  • 次要时间伺服器：http://www.eecis.udel.edu/~mills/ntp/clock2a.html
由于这些时间伺服器大多在国外，所以我们是否要使用这些伺服器来同步化自己的时间呢？ 其实如果台湾地区已经有标准时间伺服器的话，用那部即可，不需要连线到国外啦！浪费频宽与时间啊！ 而如前面提到的，台湾地区已经有第二阶的时间伺服器了，所以当然我们可以直接选择台湾地区的 NTP 主机即可。

  • 时间伺服器的阶层概念
    • 其实 NTP 的阶层概念与 DNS 很类似啦，当你架设一部 NTP 主机，这部 NTP 所向上要求同步化的那部主要主机为 stratum-1 时，那么你的 NTP 就是 stratum-2 啰！举例来说，如果我们的 NTP 是向台湾的 tock.stdtime.gov.tw 这部 stratum-2 的主机要求时间同步化，那我们的主机即为 stratum-3 ，如果还有其他的 NTP 主机向我们要求时间同步， 那么该部主机则会是 stratum-4 啦！就这样啊～ 那最多可以有几个阶层？最多可达 15 个阶层喔！

    如果你评估一下，确定有架设 NTP 的需求时，我们可以直接选择台湾地区的上层 NTP 来同步化时间即可。 举例来说 tock.stdtime.gov.tw 这个国家单位的第二层主机 (stratum-2) 应该是比较适合的。 一般来说，我们在进行 NTP 主机的设定时，都会先选择多部上层的 Time Server 来做为我们这一部 NTP Server 的校正之用，选择多部的原因是因为可以避免因为某部时间伺服器突然挂点时， 其他主机仍然可以提供我们的 NTP 主机来自我更新啊！然后我们的 NTP Server 才提供给自己的 Client 端更新时间。如此一来，国家单位的 tock.stdtime.gov.tw 负载才不会太大，而我们的 Client 也可以很快速的达到校时的动作！

    好了，我假设俺的 NTP 伺服器所需要设定的架构如下：
    • 我的上层 NTP 伺服器共有 tock.stdtime.gov.tw, tick.stdtime.gov.tw, time.stdtime.gov.tw 三部，其中以 tock.stdtime.gov.tw 最优先使用 (prefer)；
    • 不对 Internet 提供服务，仅允许来自内部网域 192.168.1.0/24 的查询而已；
    • 侦测一些 BIOS 时钟与 Linux 系统时间的差异并写入 /var/lib/ntp/drift 档案当中。
    好了，先让我们谈一谈如何在 ntp.conf 里面设定权限控制吧！

  • 利用 restrict 来管理权限控制
    • 在 ntp.conf 档案内可以利用‘ restrict ’来控管权限，这个参数的设定方式为：
    restrict [你的IP] mask [netmask_IP] [parameter]
    其中 parameter 的参数主要有底下这些：
    • ignore
      拒绝所有类型的 NTP 连线；

    • nomodiy
      用户端不能更改 NTP 伺服器的时间参数，这即表示用户端不能使用 ntpc 与 ntpq 这两支程式来修改伺服器啰。 但用户端仍可透过这部主机来进行网路校时的；

    • noquery
      用户端不能够使用 ntpq, ntpc 等指令来查询时间伺服器，等于不提供 NTP 的网路校时啰；

    • notrap
      不提供 trap 这个远端事件登录 (remote event logging) 的功能。

    • notrust
      拒绝没有认证的用户端。
    那如果你没有在 parameter 的地方加上任何参数的话，这表示‘该 IP 或网段不受任何限制’的意思喔！一般来说，我们可以先关闭 NTP 的使用权限，然后在一个一个的启用允许登入的网段。

  • 利用 server 设定上层 NTP 伺服器
    • 上层 NTP 伺服器的设定方式为：
    server [IP or hostname] [prefer]
    在 server 后端可以接 IP 或主机名称，鸟哥个人比较喜欢使用主机名称来设定说！ 至于那个 perfer 表示‘优先使用’的主机啰～有够简单吧！

  • 以 driftfile 记录时间差异
    • 设定的方式如下：
    driftfile [可以被 ntpd 写入的目录与档案]
    因为预设的 NTP Server 本身的时间计算是依据 BIOS 的晶片震荡周期频率来计算的，但是这个数值与上层 Time Server 不见得会一致啊！所以 NTP 这个 daemon (ntpd) 会自动的去计算我们自己主机的频率与上层 Time server 的频率，并且将两个频率的误差记录下来，记录下来的档案就是在 driftfile 后面接的完整档名当中了！关于档名你必须要知道：
    • driftfile 后面接的档案需要使用完整路径档名；
    • 该档案不能是连结档；
    • 该档案需要设定成 ntpd 这个 daemon 可以写入的权限。
    • 该档案所记录的数值单位为：百万分之一秒 (ppm)。
    driftfile 后面接的档案会被 ntpd 自动更新，所以他的权限一定要能够让 ntpd 写入才行。在 CentOS 4.x 预设的 NTP 伺服器中，使用的 ntpd 的 owner 是 ntp ，这部份可以查阅 /etc/sysconfig/ntpd 就可以知道啦！
  • keys [key_file]
    • 除了以 restrict 来限制用户端的连线之外，我们也可以透过金钥系统来给用户端认证， 如此一来可以让主机端更放心了。不过在这个章节里面我们暂不讨论这个部分， 有兴趣的朋友可以参考 ntp-keygen 这个指令的相关说明喔！

    根据上面的说明，我们最终可以取得这样的设定档案内容喔！
    [root@linux ~]# vi /etc/ntp.conf
# 在保留大部分的预设值的情况下，我们作了几个小部分的修改喔：
# 1. 先处理权限方面的问题：
restrict default nomodify notrap noquery
restrict 220.130.158.71  <==底下这三行在开放主机进入的权限
restrict 220.130.158.51
restrict 220.130.158.52
restrict 127.0.0.1   mask 255.0.0.0  <==内部与 LAN 的使用权限
restrict 192.168.1.0 mask 255.255.255.0 nomodify

# 2. 设定主机来源！
server 220.130.158.71 prefer  <==以这部主机为最优先
server 220.130.158.51
server 220.130.158.51

# 3.原本内定的一个内部时间资料，不需要更动他
server  127.127.1.0     # local clock
fudge   127.127.1.0 stratum 10

# 4. 就是那个时间差异分析的咚咚，保留预设值即可。
driftfile /var/lib/ntp/drift
broadcastdelay  0.008

# 5.暂时不会使用的 keys 相关认证功能。
keys            /etc/ntp/keys
    然后准备一下修订一下 /etc/sysconfig/ntpd 吧！
    [root@linux ~]# vi /etc/sysconfig/ntpd
OPTIONS="-u ntp:ntp -p /var/run/ntpd.pid"
SYNC_HWCLOCK=yes
# 将他改成 yes 吧！这样 BIOS 的时间也会跟着改变的！
    这样就设定妥当了，准备来启动 NTP 服务吧！

    小标题的图示 NTP 的启动与观察
    设定完 ntp.conf 之后就可以启动 ntp 伺服器了。启动与观察的方式如下：
    1. 启动 NTP
[root@linux ~]# /etc/init.d/ntpd start

2. 观察启动的埠口看看：
[root@linux ~]# netstat -tlunp
Proto Recv-Q Send-Q Local Address      Foreign Address  PID/Program name
udp        0      0 192.168.1.254:123  0.0.0.0:*        15118/ntpd
udp        0      0 127.0.0.1:123      0.0.0.0:*        15118/ntpd
udp        0      0 0.0.0.0:123        0.0.0.0:*        15118/ntpd
udp        0      0 :::123             :::*             15118/ntpd
# 主要是 UDP 封包，且在 port 123 这个埠口的啦！
    这样就表示我们的 NTP 伺服器已经启动了，不过要与上层 NTP 伺服器连线则还需要一些时间， 通常启动 NTP 后约在 15 分钟内才会和上层 NTP 伺服器顺利连接上。 那要如何确认我们的 NTP 伺服器有顺利的更新自己的时间呢？你可以使用底下几个指令来查阅喔：
    [root@linux ~]# ntpstat
synchronised to NTP server (220.130.158.71) at stratum 3
   time correct to within 495 ms
   polling server every 64 s
# 这个指令可以列出我们的 NTP 伺服器有跟上层连线否。由上述的输出结果可以知道，
# 时间有校正约 495 * 10^(-3) 秒，且每格 64 秒会主动去更新时间喔！

    [root@linux ~]# ntptrace -n 127.0.0.1
127.0.0.1: stratum 3, offset -0.034965, synch distance 0.109233
220.130.158.71: stratum 2, offset -0.000873, synch distance 0.031625
220.130.158.50: timed out, nothing received
***Request timed out
# 这个指令则可以列出目前我们的 NTP 伺服器与上层 NTP 伺服器彼此之间的关系。
# 由于我们已经和第二层连接上，但第二层与第一层就不是我们能管理的啰。
# 所以那个 timed out 可以不理他没关系的。

    [root@linux ~]# ntpq -p
     remote           refid      st t when poll reach   delay   offset  jitter
==============================================================================
*220-130-158-71. 220.130.158.50   2 u   53   64   77   36.800  -10.496   1.890
 220-130-158-51. .INIT.          16 u    -   64    0    0.000    0.000 4000.00
+220-130-158-51. 220.130.158.50   2 u   49   64   77   33.448  -10.431   2.581
 LOCAL(0)        LOCAL(0)        10 l   51   64   77    0.000    0.000   0.004
    这个 ntpq -p 可以列出目前我们的 NTP 与相关的上层 NTP 的状态，上头的几个栏位的意义为：
    • remote：亦即是 NTP 主机的 IP 或主机名称啰～注意最左边的符号， 如果有‘+’代表目前正在作用当中的上层 NTP ，如果是‘*’代表也有连上线，不过是作为次要连线的 NTP 主机。
    • refid：参考的上一层 NTP 主机的位址
    • st：就是 stratum 阶层啰！
    • when：几秒钟前曾经做过时间同步化更新的动作；
    • poll：下一次更新在几秒钟之后；
    • reach：已经向上层 NTP 伺服器要求更新的次数
    • delay：网路传输过程当中延迟的时间，单位为 10^(-6) 秒
    • offset：时间补偿的结果，单位与 10^(-3) 秒
    • jitter：Linux 系统时间与 BIOS 硬体时间的差异时间， 单位为 10^(-6) 秒。
    事实上这个输出的结果告诉我们，时间真的很准了啦！因为差异都在 0.0001 秒以内， 可以符合我们的一般使用了。另外，你也可以检查一下你的 BIOS 时间与 Linux 系统时间的差异， 就是 /var/lib/ntp/drift 这个档案的内容，就能了解到咱们的 Linux 系统时间与 BIOS 硬体时钟到底差多久？单位为 10^(-6) 秒啦！

    小标题的图示 安全性设定
    NTP 伺服器在安全的相关性方面，其实刚刚我们在 /etc/ntp.conf 里面的 restrict 参数中就已经设定了 NTP 这个 daemon 的服务限制范围了！不过，在防火墙 iptables 的部分，还是需要开启连线监听的啦！所以，在您的 iptables 规则的 scripts 当中，需要加入这一段 (我是以开放 192.168.1.0/24 这个网域作为范例的！)
    iptables -A INPUT -p UDP -i $EXTIF -s 192.168.1.0/24  --dport 123 -j ACCEPT
    若还要开放其他的网段或者主机，请自行修改您的防火墙机制咯！
    大标题的图示 用户端的时间更新方式
    上头介绍了 NTP 伺服器的安装与设定，如果我们仅有十部不到的主机时，老实说，实在没有架设 NTP 伺服器的需求。 只要能够在你的主机上头以 NTP 用户端软体来进行网路校时就能够同步化时间了，没必要时时刻刻进行时间的校正吧！^_^！ 底下我们会介绍几个重要的概念，了解一下为何电脑关机了时间还能够继续记忆呢？

    小标题的图示 Linux 系统时间与硬体时间
    在咱们的 Linux 作业系统当中其实有两个时间喔，分别是：
    • 一个是 BIOS 记录的实际时间，这也是硬体所记录的；
    • 一个是 Linux 自己的系统时间，由 1970/01/01 开始记录的时间参数。
    当 Linux 开机后，他会主动的读出 BIOS 所记录的时间，然后开始用自己的方式来计算时间了。 当我们使用 date 之类的指令来查询或者是设定时间时，该时间指的仅是 Linux 的时间而已， 并没有更动到 BIOS 内所记录的时间呐！除非你使用 hwclock 来写入或者是读出 BIOS 的时间。

    而由于 BIOS 会记录时间而且会持续计时，因此我们关机后再开机时，会发现时间其实是有顺利的累积上来的。 为了要维持 BIOS 所记录的资讯，因此主机板上面的电池就很重要了， 因为他可以让 BIOS 在关机的时候还继续的记录硬体资讯以及维持时间的累计。 所以如果你发现开机后整个 BIOS 时间竟然恢复成为系统出厂值，很可能就是主机板上面的电池没电了。 如果你将 BIOS 断电处理时，嘿嘿！时间可能也会恢复成为系统出厂值啊。

    由于每个 BIOS 内部的时间计算器可能有点误差，因此与我们的 Linux 时间多多少少就会产生差异， 这个差异在时间拉长之后，就会发现他的重要性了。所以才会需要进行网路校时嘛！您说是吧～

    小标题的图示 Linux 系统时区与手动校时工作： date, hwclock
    我们在前面说过， Linux 的时区档案就是 /etc/localtime ，这是一个时间格式的档案而不是 ASCII 类型的档案喔！ (file /etc/localtime 可以看出)，至于所有的 Time Zone 则放置在 /usr/share/zoneinfo 这个目录下。请注意：
    • 当 /etc/localtime 存在时，系统的时区以该档案代表的时区来显示、
    • 当 /etc/localtime 不存在时，系统的时区主要以 GMT (或 UTC) 为准；
    所以，如果您想要变更您 Linux 系统的时区，那么只要在 /usr/share/zoneinfo 里面找到您需要的时区档案， 然后将他复制一份成为 /etc/localtime 就可以顺利的更新时区设定了！另外，同时建议修正一下 /etc/sysconfig/clock 这个档案里面的 ZONE 设定值！以我们台湾的 Time zone 为例，在 /etc/sysconfig/clock 这个档案当中应该是‘ZONE="Asia/Taipei"’这就表示我们的时区档案为 /usr/share/zoneinfo/Asia/Taipei 这个档案啰！请对应着修改成您所想要的时区吧！

    例题：
    假设你的主机本来在台湾，后来被搬到美国的洛杉矶 (Los_Angeles) 去了。 请问你如何更改主机的时区参考档案？
    答：
      时区参考档在是 /etc/localtime ，不过这个档案在不同的 Linux distribution 的处理方式不一样。 以 Red Hat 系统为例，他是以复制的方式来处理这个档案。而 SuSE 则是以 hard link 来处理的。 所以，请记得不要随意的单纯用‘复制’的方式来处理，最好先移除后复制。 所以你可以这样做：
      [root@linux ~]# rm /etc/localtime
[root@linux ~]# cp -a /usr/share/zoneinfo/America/Los_Angeles \
> /etc/localtime
[root@linux ~]# vi /etc/sysconfig/clock
ZONE="America/Los_Angeles"
UTC=false
ARC=false
      这样就 OK 的啦！ ^_^

    好了，时区修正完毕了，那么时间呢？如前所述，目前 Linux 系统上面有两个时间喔，一个是 Linux 系统，另一个则是 BIOS 时间！我们可以使用 date 这个指令来手动修正目前主机的时间，不过， date 这个指令仅修正 Linux 时间而已，我们还需要以 hwclock 这个指令来将 BIOS 时间也更新才行！
    [root@linux ~]# date MMDDhhmmYYYY
参数：
MM：月份
DD：日期
hh：小时
mm：分钟
YYYY：西元年

1. 修改时间成为 1 小时后的时间该如何是好？
[root@linux ~]# date
Thu Dec  7 15:36:45 CST 2006

[root@linux ~]# date 120716362006
Thu Dec  7 16:36:00 CST 2006
# 瞧！时间立刻就修改过来了！

    [root@linux ~]# hwclock [-rw]
参数：
-r ：亦即 read ，读出目前 BIOS 内的时间参数；
-w ：亦即 write ，将目前的 Linux 系统时间写入 BIOS 当中啊！

2. 查阅 BIOS 时间，并且写入更改过的时间啰！
[root@linux ~]# hwclock -r
Thu Dec  7 15:37:44 2006  -0.627128 seconds
# 看一看，是否刚好差异约一个小时啊！这就是 BIOS 时间！

[root@linux ~]# hwclock -w
# 这样就写入啰～很简单吧！
    这样可以了解了吗？当我们进行完 Linux 时间的校时后，还需要以 hwclock 来更新 BIOS 的时间，因为每次开机的时候，系统会重新由 BIOS 将时间读出来，所以， BIOS 才是重要的时间依据呐。

    小标题的图示 Linux 的网路校时
    在 Linux 的环境当中可利用 NTP 的用户端程式，亦即是 ntpdate 这支程式就能够进行时间的同步化。 不过你要知道的是，因为 NTP 伺服器本来就会与上层时间伺服器进行时间的同步化， 所以在预设的情况下，NTP 伺服器不可以使用 ntpdate ！也就是说 ntpdate 与 ntpd 不能同时启用的。 所以你不要在 NTP server 上头执行这个指令呦！我们就来看看如何处理吧！
    [root@linux ~]# ntpdate [-nv] [NTP IP/hostname]
参数：
-d ：进入除错模式 (debug) ，可以显示出更多的有效资讯。

[root@linux ~]# ntpdate 192.168.1.254
 7 Dec 17:21:46 ntpdate[1427]: adjust time server 192.168.1.254 offset -0.0147 sec
# 最后面会显示微调的时间有多少 (offset)

[root@linux ~]# hwclock -w
# 还得写入 BIOS 时间才行啊！

[root@linux ~]# vi /etc/crontab
# 加入这一行去！
10 5 * * * root /usr/sbin/ntpdate tock.stdtime.gov.tw && /sbin/hwclock -w
    使用 cron 之后，每天 5:10 Linux 系统就会自动的进行网路校时啰！相当的简易吧！

    小标题的图示 Windows 的网路校时
    或许你一直都没发现，其实 Windows 在预设的情况当中，已经帮我们处理了网路校时的工作喔！ 不管你愿不愿意.....你可以将滑鼠的指标指在工作列右下角的时间处按两下，就会出现如下的画面：

    Windows XP 提供的网路校时功能
    图二、Windows XP 提供的网路校时功能

    如上所示，你可以自行填写台湾的时间伺服器来对应时间，当然也可以填写你自己的时间伺服器啊！ 之后系统就会主动的上网去更新时间了。不过，这是 Windows XP 才有的功能，如果是比较早期的 Windows ， 例如 Windows 95/2000 预设是没有这个功能的。不过也没有关系， 因为国家频率与时间标准实验室 (http://www.stdtime.gov.tw/) 也有提供一个用户端软体喔！连结资料如下：
      http://www.stdtime.gov.tw/chinese/EXE/NTPClock.exe
    你可以下载，直接执行他就知道如何处理了，因为是全中文介面的图形化软体嘛！
    大标题的图示 重点回顾
    • 地球共有 24 个时区，而以格林威治时间 (GMT) 为标准时间；
    • 台湾本地时间为 GMT + 8 小时；
    • 最准确的时间为使用原子钟 (Atomic clock) 所计算的，例如 UTC (Coordinated Universal Time) 就是一例；
    • Linux 系统本来就有两种时间，一种是 Linux 以 1970/01/01 开始计数的系统时间，一种则是 BIOS 记载的硬体时间；
    • Linux 可以透过网路校时，最常见的网路校时为使用 NTP 伺服器，这个服务启动在 udp port 123；
    • 时区档案主要放置于 /usr/share/zoneinfo/ 目录下，而本地时区则参考 /etc/localtime；
    • NTP 伺服器为一种阶层式的服务，所以 NTP 伺服器本来就会与上层时间伺服器作时间的同步化， 因此 nptd 与 ntpdate 两个指令不可同时使用；
    • NTP 伺服器的连线状态可以使用 ntptrace 及 ntpq -p 来查询；
    • NTP 提供的用户端软体为 ntpdate 这个指令；
    • 在 Linux 下想要手动处理时间时，需以 date 设定时间后，以 hwclock -w 来写入 BIOS 所记录的时间。
    • 在 LPI 网站 http://www.lpi.org 里面提到的，在 LPI 102 里面 NTP 其实考的还不少！Topic 1.111.6 Maintain system time 里面说到，应试者应该要了解 BIOS 时间与 UTC 时间的意义，同时需要知道怎么设定 timezone ，而时间差所使用的档案 driftfile 也需要了解呐！可能会考的内容含有：
      • date
      • hwclock
      • ntpd
      • ntpdate
      • /usr/share/zoneinfo
      • /etc/localtime
      • /etc/ntp.conf
      • /etc/ntp.drift (新版已经改至 /var/lib/ntp/drift)
    大标题的图示 课后练习
    • 什么是 GMT (格林威治) 时间与 UTC 时间？
      • 由于地球是圆的，所以同一时间点上，在地球共可分为 24 个时区，其中，我们以欧洲的格林威治时间为一个对照的依据，这个即是 GMT 时间。台湾时间比 GMT 时间快了 8 小时。至于 UTC 时间则是由原子钟所计算的时间，这个时间是相当的准确的， 主要仍以格林威治时间为时区！
    • Linux 系统的所有时区档案放置哪一个目录底下？
      • 所有的时区档案放置于：/usr/share/zoneinfo 底下！至于系统时区的设定档则在 /etc/sysconfig/clock 与 /etc/localtime 喔！
    • 我的 Linux 主机本来放置在日本东京，现在想将他拿到台湾来运作，不过因为日本与台湾有一个小时的时差， 所以我的时间应该需要经过调整才行。不过，因为我的 BIOS Time 主要是依据 UTC 时间来设定的，所以似乎只要更动时区参数即可。请问我该如何设定时区，好让我的 Linux 主机能够显示正确的时间？
      • 先将 /etc/localtime 删除，然后将 /usr/share/zoneinfo/Asia/Taipei 这个档案复制成为 /etc/localtime 即可！
    • 目前 Linux 系统上面的时间伺服器主要是以 NTP 为主，请问这个 daemon 的主要设定档放在哪里，而该设定档中，针对上层 time server 的设定参数为何？而那个 driftfile 参数是干嘛用的？
      • 在 /etc/ntp.conf 这个档案当中，至于上层 time server 的设定参数为 server 啊！那个 driftfile 则是用来做为‘时间差额’的计算的！该参数后面接的是一个完整路径的档名，该档案里面的数值单位为百万分之一(ppm)。
    • 请问 ntptrace 的功能为何？
      • 可以用来追踪上层 time server 的连线时间与目前时间！
    • 我以 date 更新了我 Linux 上面的时间后，该如何将时间数据写入 BIOS 内？
      • 必须利用 hwclock 这个程式来写入，利用 hwclock -w 写入 BIOS
    • 在 Linux 上面如何进行网路校时？
      • 最简单的方法即是使用‘ ntpdate time.servers.ip && hwclock -w ’即可！
    大标题的图示 参考资料
    • NTP 的官方网站：http://www.ntp.org
    • 时间伺服器网页：http://www.stdtime.gov.tw/Time/home.htm
    • NTP 网站：http://www.eecis.udel.edu/~mills/ntp/html/ntpd.html
    2003/08/21：首次完成
    2006/12/05：将旧的文章移动到此处
    2006/12/08：将文章作了个版面修改，同时将一些资料再加强一些。并补充一些额外的查阅 NTP 的指令。
    2009/04/28：将 offset 的时间单位写错了，应该是 ms 不是 us ，亦即 10^(-3) 秒，而不是 10^(-6) 秒。抱歉。
    2003/08/21以来统计人数


鸟哥的 Linux 私房菜 -- 代理伺服器 squid 设定

为取得较佳浏览结果，请爱用 firefox 浏览本网页

简易 Proxy Server 架设
最近更新日期：2004/11/12

代理伺服器的功能可多的呢！在中大型的企业当中，可以藉由单点对外的 Proxy 主机来达到‘节省频宽’的目的，同时，也可以透过这样的 Proxy 架构来达成‘高阶防火墙’的设定，这里的‘高阶’指的是 OSI 七层协定里面比较高阶段的层级，那就是应用与表现层方面的防火墙啦！那如果对于小型的企业呢？这个 Proxy 也可以达到分流的作用，让不同的目标网站可以透过不同的上层 Proxy 来取得资料！啊！真是很不错的一个伺服器啊！不过，这个 Proxy 伺服器也是几个常见的伺服器里面，硬体要求相对比较高的一个咚咚！因为 Proxy 要求的是‘快速’，所以呢，呵呵！当然硬体等级的要求是相当的‘蛮像一回事’的！^_^

原理：
    ：什么是代理伺服器
    ：代理伺服器的运作方式
    ：代理伺服器的用途与优缺点
    ：什么是上层代理伺服器？哪里有上层代理伺服器
    ：我是否一定要设定 Proxy ？
    ：所需要的硬体要求与最佳硬体配置方式
    ：代理伺服器与 NAT 主机的差异
套件安装：
    ：使用 RPM 方式安装 squid
    ：使用 Tarball 方式安装 squid
Server 端设定：
    ：squid 的结构
    ：squid 的 process owner 与 cache directory owner
    ：最简易的 squid 设定方法
    ：记忆体与磁碟快取留存百分比设定
    ：acl 的用法与用途
    ：上层 Proxy 的选择与负载分流的设定方法
    ：与时间相关的设定值 ( connect_timeout, request_timeout )
    ：总是系统自己来捉资料(always_direct)
    ：限制使用 proxy 使用者与 proxy 目标的方式 (acl and http_access )
    ：额外的功能参数
Client 端设定：
    ：Netscape
    ：Internet Explorer
Server 端进阶设定：
    ：末端资料分析 pwebstat
    ：末端资料分析 sarg
    ：防火墙的规划
    ：NAT 与 Proxy 透过 transparent proxy 设定加快网路传输
    ：squid 的注意事项
重点回顾
参考资源
本章习题练习
原理：
    代理伺服器的原理其实很简单啦！就是以类似代理人的角度去取得使用者所需要的资料就是了！但是由于他的功用，使得我们可以透过代理伺服器来额外的达成防火墙的功能！此外，也可以藉由代理伺服器 ( Proxy ) 来达成节省频宽的目的，以及加快内部网路的 WWW 存取速度！总之， Proxy 对于大型的企业来说，实在是一个很不错的东西啊！

    什么是代理伺服器

    在真实世界中，我们或许会帮忙家人去办理一些杂务吧！举个例子来说，例如缴费或者是申办提款卡等等的，那么由于你并不是‘申请者本人’而是‘代理人’的角色，因此有时候会需要秀出一些证件就是了。那么在网路上面的代理伺服器是怎么回事呢？他就是 Proxy Server 啰！他最主要的功能就如同我们上面提的真实世界一样， Proxy 会帮 Client 端的用户去向目的地取得用户端所需要的资料。所以，当 Client 端指定代理伺服器之后，您的所有相关要求( 例如 WWW 的要求 )就会通过代理伺服器去捉取啰！整个代理伺服器与用户端的相关性可以由下图约略看出一个端倪：

    图一、代理伺服器的示意图

    在内部的电脑都是透过 Proxy 来向 Internet 求取资料的，这就是所谓的‘代理伺服器’啦！当然，上面的架构仅只是一个案例，还有相当多的非 Intranet 的 Proxy 架构，亦即是你的 PC 与 Proxy 均在 Internet 上面，但是您一样可以透过这个 Proxy 来帮您达到代理人身份的目的呢！

    在 Proxy 与 Client 的相关性当中，您必需要了解的是：您向外部要求的资料事实上都是 Proxy 帮你取得的！怎么说呢？举个例子来说，假如我在我的浏览器 ( 假设是 Netscape 好了 )设定了我们学校的代理伺服器主机 proxy.ncku.edu.tw 做为我的 Proxy 好了，再假设我的 IP 是 140.116.44.125 ，那么当我想要取得奇摩网站的新闻资讯时，事实上，都是 proxy.ncku.edu.tw 帮我去取得的，所以在奇摩的网站上面看到向他要求资料的人是谁呢？呵呵！当然就是 proxy.ncku.edu.tw 而不是我 140.116.44.125 啰！这样可以了解 Proxy 的功能了吗？

    除了这点功能之外， Proxy 还有一个很棒的额外功能喔，那就是防火墙的功能！怎么说呢？看一下上面的图示，您可以发现一件事情，那就是 Client 端的个人电脑要连上 Internet 一定要经过 Proxy 伺服器，并且，如果有人想要入侵你的系统时，由于你的 proxy 在最外部啊，所以攻击者就会攻击错方向，如此一来，不就比较安全！此外，由于整个 Intranet 对外都是经过 proxy ，也就是‘单点对外’的情况，这种状态底下要来管理防火墙也是比较简单的喔！^_^

    代理伺服器的运作方式

    了解的 Proxy 的功能之后，我们来谈一谈那么 Proxy 到底是怎样运作的呢？为何他会有‘加快网路存取效率’的情况？这就必需要以底下的图示来说明了！

    图二、代理伺服器的运作方式流程图

    当 Client 端设定了代理伺服器之后，在 Client 端想要取得 Internet 上面的资讯时，他是这样取得资料的 (注：那个 Cache 表示为 Proxy 主机的硬碟的意思 )：

    一、Proxy 有使用者预计要求的资料时( Step 1, 2, 3,4 )：
    1. Client 端向 Server 端发送一个资料需求封包；
    2. Server 端接收之后，先比对这个封包的‘来源’与预计要前往的‘目标’网站是否为可接受？如果来源与目标都是合法的，或者说，来源与目标网站我们的 Proxy 都能帮忙取得资料时，那么 Server 端会预计开始替 Client 取得资料。这个步骤中比较重要的就是‘比对政策’啦，有点像是认证的感觉啦；
    3. Server 首先会到自己的硬碟里面，也就是所谓的 cache (快取) 查看一下有没有 Client 端所需要的资料，如果有的话，那就将资料直接送到 Client 端 (步骤4) 而不经过向 Internet 要求资料的程序；

    二、Proxy 没有使用者预计要求的资料时 ( Step 1, 2, 3, 5, 6, 2, 3, 7 )：
    1. 在经过 1, 2, 3 查寻知道 cache 没有资料，或者资料过期之后， Proxy 会向 Internet 上面的目标网站要求资料；
    2. 在将资料取回之后， proxy 会先将取得的资料‘储存一份到 cache 当中’；
    3. 最后才将资料传回给 Client 端使用。

    整个 Proxy 的工作流程就是这个样子，所以，我们就可以知道的是， Proxy 对于 cache 的速度是很要求的，而这个 cache 就是硬碟啦！当然，硬碟容量必需要足够大，而且还要‘足够快’才行！因为由上面的流程当中，我们不难发现， Cache 是一直被重复存取的一个地方喔！所以硬碟的好坏就差别很大啦！可以说他是影响一个 Proxy 效能好坏的关键点呢！

    代理伺服器的用途与优缺点

    一般来说，代理伺服器的用途主要有两个：

    • WWW 网页代理人：最主要的用途当然就是做为网页资料取得代理人啰，也就是说， Proxy 可以帮我们取得 Internet 上面的 WWW 资料就是了！那么能不能取得其他非 WWW 的资料呢？那就不一定了，要看 Proxy 主机是否有设定该服务。一般来说， Proxy 主要还是针对 WWW 网页的代理取得；

    • 做为 Intranet 的单点对外防火墙系统：就如同前面的图示， Proxy 如果架设在 Intranet 对外的连接点上面，那么他就可以被用来做为‘应用层’阶段的防火墙了！而且，这个时候不需要设定 NAT 就可以让 Intranet 内部的私有 IP 的电脑连接上 Internet 了！这是因为您想要的资料是向 proxy 要求，所以真正去取得资料的人是‘Proxy’而不是你的电脑啊！所以，只要 Proxy 可以接受私有 IP 的电脑要求，那这些私有 IP 的电脑就可以连上 WWW 啦！不过，也由于 Proxy 为一个 应用层 阶段的防火墙系统，所以，他并无法进行较低阶的封包过滤！因此，在内部电脑想要透过 Proxy 来取得邮件、或者是其他的服务，呵呵！那就比较麻烦，简直就是麻烦的多啦！

    由于 Proxy 的这种特性，让他很常被使用于大型的企业内部，因为可以达到杜绝内部人员上班时使用非 WWW 以外的网路服务，而且还可以监测使用者的资料要求流向与流量呢！很不错吧！ ^_^好了，接下来我们来谈一谈 Proxy 主要的优缺点吧：

    • 快速的存取动作：一般来说， Proxy 主机的频宽以及硬体配备会比较高档！所以 Proxy 最大的优点就是可以提供用户端较为快速的浏览！咦！但是我们向 Proxy 要求资料的时候， Proxy 不是会自行再储存一份吗？这样不是会多花很多时间？是这样没有错，但是，换一个角度来想，如果在第一位使用者要求过 A 资料后，由于 Proxy 就会自动放一放 A 资料在 Cache 当中，之后的所有使用者只要是重复要求这个 A 资料， Proxy 可以立刻将资料传给使用者，您瞧！这样这个 Client 等于是直接向 Proxy 取得这份 A 资料了！是否更加的快速！这是因为 Proxy 就在您的 Intranet 之内，传输速度可是相当快的！这也就是说：如果您要设定代理伺服器的时候，一定要找距离我们的机器最近的那一部，否则就没有达到代理伺服器的功用了！通常快速的存取动作最明显的大概是连去国外的网站了！这里要强烈的建议，如果你需要连上国外的网页，请一定使用代理伺服器，因为不但可以节省频宽，并且速度上会快上很多很多 ( 例如美国环保署, EPA 网站！ )

    • 降低网路的负荷：由于我们是向代理伺服器要求资料，如果代理伺服器内刚好有你要的资料，将会直接传给你，则你的要求将不会到真实的那一个网页去 ( 除非你在 IE 内按下‘重新整理’这个按钮 ) ，而如果没有你要求的资料，那他也会去捉一份你要的资料给你，并存下来，以后如果有与你相同需要的用户，那他就可以直接传送给用户，如此当可降低网路的负荷！(也就是上面图二的 step 1, 2, 3, 4 )

    • 资料分流：由于各家 ISP 对于不同国家的频宽是有差异的，因此，假设如果您要去美国时使用 Proxy1 速度较快，而 Proxy2 则是去日本比较快，至于台湾本地则 Proxy3 较快，如此一来，我们可以透过设定将不同目标的代理伺服器分开来，以达到分流的目的！则你的网域中将可以达到很好的分流效果，网路‘感觉上’会比较快速喔！

    • 提供防火墙内部的电脑连上 Internet：这个是一般企业比较常用的情况！由于企业内部害怕被骇客侵入，通常会设立一些比较严密的防火墙，然而如此一来公司内部的电脑可能面临无法连上 Internet 的窘境，那使用 proxy 让你的内部电脑可以透过这一架主机的代理服务而取得 Internet 上的资讯，就是一个很好的方法啦！

    • 多层次的管道 ( 上层代理伺服器 )：代理伺服器可以提供多重的管道设定，例如，当你需要国内的资料时，代理伺服器将直接去捉取，而需要国外的资料时，才连到上一层的代理伺服器！如此将可达到你的需求 ( 而不用常常在你的 IE 等浏览器上更改所需的代理伺服器 ) ，这个部分我们在底下还会进行额外的说明。

    有利就有弊，当然 Proxy 也不是万能的天神～他有什么可能潜藏的缺点呢？

    • 容易为 Intranet 的内部人员滥用：因为 Proxy 是对内部的电脑捉取资料 ( 当然也可以对 Internet 上面的使用者捉取资料啦！ ) ，而且在 Internet 上面看到的实际上是你的 Proxy 在捉资料喔！如果你的使用者大量的以浏览器下载 A 图啊，还是透过你的 Proxy 干坏事啦，这样一来可就累了～因为实在不容易轻易的管理！所以，为了杜绝这个状况，强烈的建议多加安装登录档案分析的软体，在管理上面会轻松很多喔！

    • 需要较高超的设定技巧与除错程序：在鸟哥设定过的 Server 当中， Proxy 算是比较不容易设定好‘效能’的一个伺服器了！由上面的传输过程中，您不难发现 Proxy 的 Cache 与他的‘上层代理伺服器’的关系是很紧密的，万一设定错误的话，很有可能反而让您的 Proxy 拖垮 WWW 的浏览速度！最严重的是造成无法连线 ( 在上层 Proxy 与您的 Proxy 之间构成 loop 而跑不出去！ )，因此，这对于管理员来说是比较困扰的一件事。

    • 可能会取得旧的错误资料：由前面的 Proxy 运作过程当中不难发现，Client 端向 Server 端求取资料时，Server 会先向自己的 cache 查寻，如果有该索求资料，就立即将资料送给 Client 。现在假设个例子来说明，万一我的网页三天两头改变一次，那么那个 cache 事实上并没有天天更新啊！这个时候， Client 端所取得的资料就有可能是网页修改之前的旧资料咯！所以，使用者得常常按下‘更新’才能取得新的资料啊！

    总之， Proxy 的优点是很多的，但是缺点却需要网管人员的操心啊！

    什么是上层代理伺服器？哪里有上层代理伺服器

    什么是上层代理伺服器：
    好了，上面提到过所谓的‘上层代理伺服器’这又是什么咚咚？事实上，上层代理伺服器就是一个 Proxy 啦，只是，我们自己设定的这个区域 Proxy 会将自己当作 Client 而去要求另外一个 Proxy 求取资料来给我们的使用者就是了！整个流程图可以这样看：

    图三、上层 Proxy 示意图

    就是我们的 Local proxy 并不会主动的去捉资料，而是透过‘上层代理伺服器’去向 Internet 要求资料！这样有什么好处呢？刚刚上面也曾经提过了，由于这些上层代理伺服器才是真正对外频宽最大的几部机器之一，所以透过他来要求资料一定又比我们的 Local proxy 还要来的快啊！所以我当然会喜欢设定上层 Proxy 噜！这个现象最常发生在对国外的连线上面，有没有设定 Proxy 差异是相当大的呢！上层代理伺服器除了频宽更大之外，还有没有什么好处啊？当然有，最大的好处就是达到分流的效应！例如下图的说明：

    图四、上层代理伺服器的分流动作示意图

    我总共设定了三个上层代理伺服器，由于这三个代理伺服器对外的速度都不相同，所以，当我要去美国时，就以 Proxy1 来要求资料，要连欧洲就以 Proxy3 ，至于要连日本，就以 Proxy 2 来要求我所需要的资料，如此一来，呵呵！可以让我的 Proxy 达到最佳的效能喔！很不错吧！ ^_^！所以上层代理伺服器是很重要的呢！

    哪里有上层代理伺服器？
    目前有哪些流量大、然后又开放出来的 Proxy 呢？我这里举几个网页给大家参考参考：

    • SeedNet 的代理伺服器(http://service.seed.net.tw/dial/server.shtml)；
    • Hinet 的代理伺服器(http://www.hinet.net/support/new_adsl04.htm)；
    • 一些台湾学术网路的代理伺服器(http://turtle.ee.ncku.edu.tw/~tung/proxy/proxylst.html)。

    由前面的介绍中，我们不难发现 Proxy 有可能会被 Client 端过度的滥用，同时也有可能会被拿来为非作歹啊！所以，目前绝大部分的 Proxy 已经‘停止对外开放’了，仅针对自己的网域内的 Client 提供 Proxy 的服务而已～因此，如果您要自行设定 Proxy 的时候，请记得去您当初申请网路的 ISP ( 如果是学术单位，就到上面介绍的学术网路查看看即可！) 查寻一下，才能比较有效的设定好您的主机喔！因为设定错误的话，呵呵！上层 Proxy 根本不提供服务，或者是上层 Proxy 的效能并不好，那个时候您的 Proxy 也会连带的受到很大的影响啊！慎选！慎选！

    我是否一定要设定 Proxy ？

    话又说回来，到底我应不应该设定 Proxy 呢？还是得由理论与实际上的状态来进行说明。事实上，我们的 Proxy 感觉上会加快传输的速度，主要的因素是来自于 cache 已经记录了一份资料了，所以 Client 端取得的其实是这一份资料，而不是真的来自于 Internet 上面的即时资料！这样的好处前面提过了，就是可以增加内部网路传输的效能啊！但是，这要在一个前提之下，就是我的使用者很多时，那么由于来自四面八方的人会四处去求取资料，让我的 Cache 拥有较大的资料库，那么内部传输的速度自然就会有所助益！所以，要架设 Proxy 的情况可以是：

    • 我的 Client 端用户不少，而且大部分仅需要 WWW 这个网路服务而已；
    • 我的 Proxy 还兼做防火墙的任务；
    • 我的 Client 端常常需要连线到传输速度很慢的网站，例如国外的网站；
    • 我的 Client 端常常浏览的网站是‘静态’网站，而不是动态网站(例如讨论区的 PHP )。

    相反的来说，要是 (1)我的 Client 端很少，那么每次上去 WWW 都是求取新的资料，有没有 Proxy 反而看不出效益～此外，(2)Proxy 由于属于应用层了，对于 Internet 的规划上弹性较不足！不像 NAT 主机可以进行很多的功能！(3)我常常上的网站是类似讨论区那种一日多变的网站，在这样的情况下，实在是没有必要架设 Proxy 的！

    但是，如果对于学校单位那原本频宽就不足的环境中，架设 Proxy 来让校内的网路速度提升，呵呵！就是有那个必要性的啦！所以要不要架设 Proxy 呢？请好好的依据您的环境来考量喔！

    所需要的硬体要求与最佳硬体配置方式

    假设您一定需要架设 Proxy ，那么到底什么样的配备是必需的呢？我们刚刚提到 Proxy 对于硬体的要求相当的高！因为我们架设 Proxy 的目的就是希望能够加快网路的传输效能嘛！因此，虽然 Proxy Server 几乎在任何的 Linux 系统上面都能跑 ( 例如我的 P 133 MMX ) ，但是您的 Proxy Server 最好还是能有以下的硬体等级：

    • CPU 最好能够 P III 550 以上等级；
    • RAM 最好能够大于 512 MB ，这也是很重要的一个硬体参数！
    • Hard Disk 最好能用 SCSI 介面的，因为速度与稳定度都比较好！如果不能的话，那么 IDE 介面的硬碟由于目前速度也越来越快，所以使用 IDE 也没有问题，但是最好是‘多颗硬碟’的架构，例如我总共需要 30 GB 的硬碟空间，那么最好是 10 GB 的硬碟三颗这样的架构较佳！为什么呢？由于 cache 对于 Proxy 的重要性相当的大，所以 cache 读取速度越快的话，代表 Proxy 的效能也会越好！那由于 Proxy 对每笔资料写入 cache 时，是‘平均分摊在各个 cache 的目录中 ’，所以当然硬碟数越多越好啰！例如我原本有 10 MB 的资料要写入 cache ，那么这 10MB 写入同一颗硬碟快？还是 10MB 被分散写入三颗硬碟，因此每一颗硬碟仅记录 3.3MB ，那一个快？当然是三颗硬碟的架构会比较快，因为我有三个磁头在帮我写入资料嘛！^_^！请注意喔！这里我们说的是‘多颗硬碟’而不是‘多个 Partition ’喔！因为如果我将 30GB 的硬碟切割成三块 partition 的状态下，由于还是只有一个磁头啊，所以写入的速度差异不会很大！这里要特别留意与了解呢！
    • 网路卡与网路周边最好使用 GBytes 的网路卡，当然啦，一般的公司行号应该不需要用到这样的网路卡才是！我这里指的是较高档的配备啦！

    事实上，最重要的还是 RAM 与 HD 这两样，当然，网路介面也绝对不能忽视就是了！针对硬碟来说，最好使用 SCSI 这个稳定的介面，当然，使用 IDE 也是不错啦！但是要注意保养就是了。此外，就如同上面提到的，在硬碟的架构上是相当的重要的！一般来说，使用磁碟阵列应该是不错的想法，如果没有办法的话，使用多颗硬碟取代单颗硬碟的架构，在效能上也会有不错的显著提升呢！

    既然硬碟这么重要，我们也约略谈一谈硬碟的基础规划应该有哪些需要注意的呢？

    • 最好在架设 Proxy 时，将整体主机的规划做好，并且让 Proxy 主机的服务简单一点，就是仅负责 Proxy 就好了！
    • 每颗硬碟的容量不需要太大，大约在 9 GB 以内即可，此外，最好将硬碟分割一下，一块 Partition 差不多在 2~4 GB 之间即可，因为切太大的话资料的搜寻耗费时间较长，但是 Partition 太小又可能造成空间的浪费～所以差不多的大小就限制在 2~4 GB 吧！
    • 我们刚刚上面有提过，cache 是放置在某个目录下的，而最好一个目录底下就是独立的一个 partition 。此外，由于 cache 所在的硬碟常常会有资料的存取，因此可能此一硬碟的损耗率会比较大，所以这个 cache 所在的硬碟最好不要跟重要资料档案，例如 /, /etc, /usr, /home 等等重要的系统档案放在一起，以免危险啊！
    • 也由于 cache 所在的硬碟资料存取太密集了，所以，硬碟的选择上面需要 (1)转速不能太低； (2)磁头的机械臂需要可以忍受频繁的动作； (3)发热量不可太大，或者可以考虑加装硬碟用风扇。

    代理伺服器与 NAT 主机的差异

    或许您已经发现了一件事，那就是：在内部区域网路使用私有 IP 的 Client 端不论透过 Proxy 或者 NAT 均可以直接取得 WWW 这个 Internet 的服务，那么 NAT 与 Proxy 有没有什么不同的地方啊？他们不都是可以让内部的 Client 连接出去吗？其实这两个玩意儿差异性是‘相当大’的：

    • NAT 是一个利用 TCP/IP 的 packet filter ( 封包过滤机制 )来进行封包处理的一个机制，所以他是‘直接分析 TCP/IP ’，所以在设定防火墙的时候，他的弹性比较高，只要能过 NAT 这一关，那么大部分的网路服务都可以使用，因为 TCP/IP 是比较底层的协定啊！要知道的是，TCP/IP 上头还有 port 、还有 IP 等等的资讯，单是 port 就可以让我们使用很多的不同的协定了！例如 port 20, 21 是 FTP 啊， 80 是 WWW 啊等等的！所以 NAT 能做的事情事很多的！

    • 至于 Proxy 就不一样了， Proxy 主要透过类似 Squid 这一类的软体来达成的一个服务，基本上，一般来说他是透过 port 3128 来进行资料的监听与传输，单是看到这个 port 3128 就应该要晓得他仅是一个 daemon 而已。Proxy 已经是应用层这个阶段的网路项目了，所以他并没有去分析 TCP 的封包，只要 Client 来源合乎他的需求 (例如 IP 是被支援的 ) ，那么他将透过 daemon 的功能帮使用者达成使用者所想要的任务！所以说，能不能做某些事情，与 Proxy 伺服器上面负责的那个 daemon 是有关的！万一 daemon 无法进行 FTP 资料的取得，那么您再怎么努力的尝试上网也是枉然的啊！

    这样说有没有比较有点概念了呢？NAT 是由较底层的网路去进行分析的工作，至于通过 NAT 的封包是干嘛用的， NAT 不去管他！至于 proxy 则主要是由一个 daemon 的功能达成的，所以必需要符合该 daemon 的需求，才能达到某些功能！

    谈完了这些基本的原理之后，我们可得来玩一玩 Proxy 了吧？！事实上，目前有很多的 Proxy 软体，例如 apache 也有提供 proxy 模组的功能喔！但是，最好不要用 Apache 当作您的 Proxy server ，因为.....效能真的太差了～会让您的网路停顿的更厉害～目前 Proxy 的伺服器软体当中，以 squid 这个咚咚最出名，会出名的原因是因为他的效能高！真的很不错的一套软体，所以底下我们就针对 squid 来做说明吧！
套件安装
    我们的 Proxy 伺服器软体选择 squid 这个效能很高的套件来安装，目前 ( 2003/03 ) Squid 已经出到了 2.5 版了，您可以到官方网站上面下载，或者是到中山大学的 FTP 网站上面下载，底下提供一下联系的网址：

    • 官方网站：http://www.squid-cache.org/Versions/v2/2.5/
    • 中山大学：http://ftp.nsysu.edu.tw/Unix/Proxy/squid/source/STABLE/

    同样的， squid 也有两种主要的安装模式，分别是 RPM 版本与 Tarball 版本，不过，由于我们会加入一些不同的参数设定值，所以预设的 RPM 档案并无法满足我们的需求，除非使用 SRPM 来进行重新 configuration 的动作，否则比较不能让我们满意啦！因此，习惯上我们都是以 Tarball 的方式来进行编译、设定与安装，所以底下鸟哥会比较偏重以 Tarball 的安装来进行介绍，如果有兴趣的话，可以尝试以 SRPM 进行修订的工作喔！

    使用 RPM 方式安装 squid

    一般来说，使用您的 Linux distribution 提供的 Squid 也就够了，但是，就如同上面提到的，可能会有一些设定值您无法自由自在的设定，不过。不过，无论如何，以 RPM 来安装是最简便的啦！那么就请拿出您的原版光碟，将他 Mount 上来，查询一下是否有 squid 字样的档案名称？没错，就将他安装上去吧！目前主要的几个 distribution 都有提供这个套件，所以应该可以很快的找到这个套件才是！怎么使用 RPM 呢？没这么难吧！

    [root@test root]# rpm -ivh squidxxxxxxx

    一再地强调， RPM 是粉重要的，请好好的使用他吧！ ^_^！这个指令就安装完毕啰！只是要注意的是，由于 squid 2.2 版以前的设定与 2.4 版以后的设定差异性很大，所以请特别留意您的 squid 版本，如果是使用旧的 Linux distribution 的使用者，例如 Red Hat 6.xx 版本，或者是 Mandrake 7.xx 版本，那么就不要再以 RPM 来升级了！直接使用底下的 Tarball 吧！反正才安装一个档案，还不会太难啦！

    使用 Tarball 方式安装 squid

    一般来说，我还真是蛮喜欢中山大学的 FTP 站 ( 怪了，好像一直在帮人家打广告！ ^_^ ) 没办法，我们南部人嘛！当然是南部的 FTP 站比较亲切啰！这个时候，您可以直接在 Linux 底下使用 wget 来取得我们所需要的 squid 喔！目前我取得的版本是 2.5.STABLE2 版本，取得的方法如下：(注：您也可以到鸟哥的私房菜下载 http://linux.vbird.org/download)

    [root@test root]#  wget  \
    http://ftp.nsysu.edu.tw/Unix/Proxy/squid/source/STABLE/squid-2.5.STABLE2.tar.gz

    好了，这个档案应该就是 /root/squid-2.5.STABLE2.tar.gz 啰！那么就开始来给他安装吧！过程很简单啦，重要的地方只有在下达 ./configure 的地方需要很多的额外参数支援就是了！

    0. 解压缩：
    [root@test root]# cd /usr/local/src
    [root@test src]# tar -zxvf /root/squid-2.5.STABLE2.tar.gz
    # ....(略)....会产生一个 squid-2.5.STABLE2 的目录
    [root@test src]# cd squid-2.5.STABLE2

    1. 开始设定参数：
    [root@test squid-2.5.STABLE2]# export CFLAGES='-O2 -mcpu=i586'
    # 这是一个额外的参数啦！因为我们使用的是 Linux ，而我们的 GNU gcc
    # 有针对每种不同的 CPU 来进行套件的最佳化编译！所以啦，就加入我们的
    # CPU 型号吧！因为我的 CPU 是 P-166 ，反正是个小案例啦！所以才会是 i586，
    # 您的 CPU 只要超过赛扬等级以上，就会是 i686 啰！此外，除了
    # i386, i486, i586, i686 还有 pentium, pentium3, pentium4, athlon,
    # athlon-tbird, athlon-4, athlon-x, athlon-mp, k6, k6-2, k6-3 等等！
    # 如果不确定您的 CPU 那么就用 ix86 之类的方式来命名吧！不过，即使没有
    # 写入这个参数也无所谓啦！至于那个 O2 是最佳化参数啦！

    [root@test squid-2.5.STABLE2]# ./configure --prefix=/usr/local/squid  \
    > --enable-gnuregex --enable-async-io=80 --enable-icmp \
    > --enable-kill-parent-hack --enable-snmp  \
    > --disable-ident-lookups --enable-cahce-digests \
    > --enable-err-language="Traditional_Chinese"  \
    > --enable-poll --enable-linux-netfilter
    # 这个咚咚就有趣啦！因为实在有相当多的参数可以使用，你可以使用
    # ./configure --help 来察看可以使用的许多参数啊！稍微解释一下各个设定值：
    --prefix=/usr/local/squid：未来程式编译完成后放置的安装目录；
    --enable-gnuregex：使用 GNU 提供的正规表示法的原则来进行编译，请注意，
        因为在 Proxy 未来的规划当中，很可能会动用到正规表示法的方式来
        抵挡一些恶意的网站，所以这里应该要加入这个参数的！
    --enable-async-io=80：这个项目主要在控制一些输出入的元件，使用这个项目
        可以让您的 Proxy 效能提升很多喔，因为是非同步输出 (async) 的模式啊！
        后面接的数值是可以变动的，如果您的网站配备很高档，可以尝试将这个数字
        提升到 160 以上，如果是小网站的话，那么可以考虑将他降低至 40 左右。
    --enable-icmp：要不要支援 ICMP 啊！当然是要的！
    --enbale-kill-parent-hack：在我关掉 squid 的时候，要不要连同
        parent process 一起关掉，当然也是要的啦！
    --enable-snmp：这个与制图的 MRTG 比较有关啦！如果没有用到的话，
        可以考虑将这个项目拿掉也没有关系！
    --enable-cache-digests：这个项目很重要的啦，我们在底下再进行说明。
    --enable-err-language="Traditional_Chinese"：不需要写了吧？
        只要有任何的错误讯息，网页上面显示的语系会是中文喔！
    --enable-poll ：可以提升效能；
    --enable-linux-netfilter：可以增加通透式 Proxy 的设定！后面再提啦！

    2. 开始编译以及 Install 啰！
    [root@test root]# make && make install

    3. 开始设定其他的相关参数
    [root@test root]# vi /etc/man.config
    # 在这个档案当中新加入一行：
    MANPATH /usr/local/squid/man   # 与 Squid 有关的 man page
    # 可以让 squid 提供的说明文件让 man 指令可以查到！

    就这样几个简单的步骤就将 squid 给他安装完毕啦！很快速吧！所以我说，使用 Tarball 来安装 squid 其实是很快的，不用太担心啰！
Server 端设定：
    终于来到了主机端的设定项目啦！以下我们会分门别类的介绍各个主要的参数值，这些参数不见得适合您的 Proxy 环境，所以使用的时候敬请特别小心喔！每个项目都要好好的了解一下呐！另外，底下我主要是以 Tarball 安装的目录为主要的介绍状态，如果您是以 RPM 来安装的话，那么所有的档案原理与设定还是一样的，只不过档案存放的路径就不太一样就是了！请以 RPM 的指令或者是 locate 与 find 的方式找出来您的设定档吧！

    squid 的结构

    刚刚安装的目录其实是在 /usr/local/squid 这个目录下，而这个目录又分为几个主要的子目录，分别为：

    • bin/ ：放置主要的 squid 执行 scripts 的目录，重要的是 RunCache 那个档案；
    • etc/ ：几乎所有的 squid 设定档都在这里；
    • libexec/ ：一些函式库；
    • man/ ：就是一些线上文件查寻档啦！
    • sbin/ ：重要的就是那个 squid 的执行档！
    • share/ ：一些错误讯息代码表示档案，以及一些小图示放置的目录；
    • var/ ：预设是放置 log file 的，不过我不喜欢放在这里，这点等一下我们会修改的！

    那么主要的设定档有哪些呢？其实可以说只有两个啦：

    • /usr/local/squid/etc/squid.conf ：这个是主要的设定档，所有的 squid 所需要的设定都是放置在这个档案当中的！鸟哥底下提到的种种设定方法几乎都是这个档案里面的说明喔！所以，如果您英文不错，那么就直接看一下这个档案就知道如何设定 squid 啦！
    • /usr/local/squid/etc/mime.conf ：这个档案则是在设定 squid 所支援的 Internet 上面的档案格式，就是所谓的 mime 格式啰！一般来说，这个档案的预设内容已经能够符合我们的需求了，所以不需要更动他，除非您很清楚的知道您所需要额外支援的 mime 档案格式。

    而执行档其实只有一个，那就是 squid 啦！不过， Squid 这个套件额外的提供了两个可执行的 scripts 来帮助大家执行 squid ，那就是在 bin/ 里面的 RunAccel 与 RunCache ：

    • /usr/local/squid/sbin/squid ：就是我们说的 squid 的执行档啰！要知道这个指令的参数吗？就使用‘ ./squid --help ’就能知道有什么参数啦！
    • /usr/local/squid/bin/RunCache ：这个是主要的执行 squid 的一支简单的 script ，主要是利用 squid.conf 设定档案的内容来启用 squid 喔！
    • /usr/local/squid/bin/RunAccel ：如果您的 WWW 服务也想要透过 Squid 来进行‘加速’的话，那就可以使用 RunAccel 来取代 RunCache 了，不过，我通常还是使用 RunCache 而已！

    squid 的 process owner 与 cache directory owner

    我们前面的原理部分稍微提过， squid 主要是以 daemon 提供的 Proxy 功能，而这个 daemon 最大的功能就是将 Internet 上面捉取的资料给他放入 Cache 目录当中啦！而由于 daemon 会产生一些 processes ( 程序 )，这些程序都会有 Owner 以及 Group 。这样晓得我要讲什么了吧？呵呵！没错，那个放置 cache 的目录 ( 底下简称 cache dir ) 的拥有者以及拥有群组就必需要与 squid 产生的 process 的拥有者与群组相同才行！而为了保险起见，通常 squid 不会以 root 来启动，最好是以 nobody 或者是一些权限比较低的系统帐号来启动他！假设我们的 squid 这个 daemon 是由 nobody 所启动的好了，而假设我的 cache dir 是放置在 /var/spool/squid 下面，则这个 /var/spool/squid 的 Owner 与 group 就必需要是 nobody, nobody 才行！这个很重要喔！因为大部分无法启用 squid 的朋友都是这个动作没有搞正确的原因啊！

    squid 的 Owner 与 Group 是在 squid.conf 里面设定的，而至于 cache dir 则是需要我们手动来设定好他的权限呢！

    最简易的 squid 设定方法

    设定 squid 仅要修改一个档案而已，那就是 /usr/local/squid/etc/squid.conf 啰( RPM 版本就不相同啰！请自行找出来吧！ )！请注意，在这个例子当中，我们并没有介绍高档配备的设定，仅只是列出重要的设定项目还有一些观念，您所想要的设定必需要视您的主机规划而定，例如 cache dir 每个人所放置的目录都不相同啊，所以直接拿我的设定来启动时，可能会完蛋啊！请注意需要修改成您所想要的样式才行！好了，在这个小节当中，我们仅列出来几个一定要设定的参数，至于更进阶的参数将留待后面分别介绍。

    另外要额外提醒的是，在 squid.conf 这个档案当中，预设的情况下是‘除了本机可以使用 squid 的少部分功能外，其他所有的项目都没有被启动’，所以您必需以 vi 的搜寻功能找到下列的设定项目后，将注解符号 (#) 拿掉，或者是自行输入底下的设定才行喔！不啰唆，马上进行吧！

    [root@test root]# cd /usr/local/squid/etc
    [root@test root]# vi squid.conf
    # 1. 关于网路的参数设定部分
    # 　 在这个部分当中，最重要的就是启用 squid 这个 daemon 的 port 了！
    #　　在预设的情况下，公认的标准 proxy port 为 3128 ，至于被查询封包
    #　　观察的则是 3130 这个 port，这里我们分别启用这两个 port ！如果您的
    #　　Proxy 还有帮人家代理 https 这个由 SSL 协定启用的 port ，那么还需要
    #　　启动 https_port ，但是我们这里不谈论 SSL 啦！太危险了～
    http_port 3128
    icp_port  3130

    # 2. 设定快取目录 ( Cache dir ) 的大小与记录档案所在的目录
    #　　这个设定是重要到爆的地方，一定得设定正确才行啊！上面我们不是
    #　　提过关于硬碟与目录吗？好了，现在这样假设：我有两块 partition ，
    #　　这两块 partition 分别挂载在 /usr/local/squid/var/cache1
    #　　以及 /usr/local/squid/var/cache2 这两个区域，此外，两块
    #　　partition 一块为 1GB (cache1) 另一块为 2 GB (cache2) ，则设定为：
    #　　<cache_dir> <aufs|ufs> <目录所在> <MBytes大小> <dir1> <dir2>
    #　　那个 aufs 只有在编译的时候加入 --enable-async-io 那个项目才有支援，
    #　　至于目录所在地与所占用的磁碟大小则请视您的主机情况而定，
    #　　而后面 dir1, dir2 则是两个次目录的大小，通常 16 256 或 64 64 皆可，
    #　　一般来说，数字最好是 16 的倍数，据说效能会比较好啦！
    #　　注意1： 下面两行需要‘视您的主机环境而定！’不要照抄！
    #　　注意2： 在底下的例子中，我的两块 partition 已经 mount 上该目录了！
    #　　　　　　这也就是说，底下的两个目录是‘已经存在的！’
    cache_dir aufs /usr/local/squid/var/cache1 1000 16 256
    cache_dir aufs /usr/local/squid/var/cache2 2000 16 256
    #　　底下则是关于记录档的放置目录与档名！
    cache_access_log /usr/local/squid/var/logs/access.log
    cache_log /usr/local/squid/var/logs/cache.log
    cache_store_log /usr/local/squid/var/logs/store.log
    pid_filename /usr/local/squid/var/logs/squid.pid

    # 3. 关闭认证机制
    #　　不晓得为什么，这一版的 squid 会自动的加入认证机制，请找到底下
    #　　几行，将他 mark 起来！
    #auth_param basic children 5
    #auth_param basic realm Squid proxy-caching web server
    #auth_param basic credentialsttl 2 hours

    # 4. 提供 squid 服务
    #　　预设的情况下，仅有本机可以使用 squid ，我们先将所有的权限开放
    #　　然后在一个一个的关闭啰！先找到底下这一行：
    http_access deny all
    #　　将他改成
    http_access allow all

    # 5. 设定 squid 的拥有者与系统管理员信箱：
    #　　就是刚刚我们上一小节提到的 squid 的拥有者，请注意，这个
    #　　user 与 group 必需要在 /etc/passwd 及 /etc/group 里面存在方可成功！
    #　　我这里以权限最小的 nobody, nogroup 来做为范例，您也可以自行设定！
    #　　另外，cache_mgr 则是 squid 管理员的信箱，当 squid 发生问题时，
    #　　荧幕上就会出现这个信箱给使用者联系管理员之用！
    cache_effective_user   nobody
    cache_effective_group  nogroup  # 您也可以改成 nobody ！
    cache_mgr youraccount@your.e.mail

    # 6. 变更目录权限：
    #　　在预设的情况下，我们主要的纪录资讯都写入 /usr/local/squid/var 里面，
    #　　所以这个时候需要将这个目录的权限改变成为 nobody 与 nogroup 所有！
    #　　当然啰，如果您的 cache_dir 不在这个目录当中，那么还需要额外自行建立，
    #　　例如我的 cache_dir 万一是在 /proxy1 与 /proxy2 时，那么我就必需要：
    #　　chown -R nobody:nogroup /proxy1
    #　　chown -R nobody:nogroup /proxy2
    #　　关于权限的问题是很重要的！请不要忘记了！
    [root@test root]# chown -R nobody:nogroup /usr/local/squid/var

    # 7. 开始启动 squid：
    #　　启动 squid 来试看看吧！不过，首先我们必需要建立快取目录的格式
    #　　才行，此外，由于我们想要以 nobody 来启动 squid ，所以你需要这样：
    [root@test root]# /usr/local/squid/sbin/squid -z # 建立 cache_dir
    [root@test root]# su nobody -c "/usr/local/squid/bin/RunCache &"

    # 8. 查看是否真的启动了 squid 了？
    [root@test root]# netstat -tln | grep 3128
    tcp        0      0 0.0.0.0:3128       0.0.0.0:*          LISTEN

    # 9. 重新读取设定档 squid.conf 的方法：
    [root@test root]# /usr/local/squid/sbin/squid -k reconfigure

    在上面的设定中，重要的地方在于：

    • 你的硬碟规划与 cache_dir 的设定是否吻合：请注意，除非您是‘架设着玩的，纯粹锻炼功力’的角度来设定 Proxy ，那么可以直接以预设的设定来搞定您的 cache_dir ，不然的话，前面我们提过，这个 Cache dir 可是影响 Proxy 效能的相当重要的因素之一，因此，千万不可大意啊！

    • 关于权限的大问题：由于我们常常提倡‘不要以 root 来启动 daemon ’，所以这个 squid 我们是以 nobody 与 nogroup 来启动的！而 Process 与权限的关系是相当相当的重要的，因此，您必需要将上面刚刚建立的 cache_dir 更动整个目录的拥有者才行！如果是锻炼功力而已，那么随意建立一个目录更动一下他的拥有者与群组，就行了，不然的话，请依照您的硬碟规划好好的设计一番！

    • 关于 cache_dir 重新建置的步骤：在上面的第 7 个步骤当中，我们必需以 squid -z 来重建一下 cache_dir 的格式，这个步骤在第一次启动 squid 时才做，其他时候就不需要进行了！而进行这个步骤之前，请务必将上面提到的两点注意事项先搞定，否则您的 squid 很难启动喔！

      •
    • 实际浏览器的查验：虽然上面第 8 个步骤已经确认了 squid 启动了，但是还不能肯定工作正常，这个时候如果您有 client 端的电脑，假设是 Windows 的 IE 好了，那么就赶紧来测试看看能不能使用 squid 啰！启动 IE 后，按下：
        • ‘工具’->
        ‘Internet 选项’->
        ‘连线’->
        ‘区域网路设定’中，点选
        ‘使用 Proxy 伺服器’
      并在网址列输入你的主机名称 ( 或者是 IP 均可 )，然后按确定离开！然后在 IE 中按按看网页的设定有没有成功，如果可以读到网页的话，表示 squid 可以正常的被使用了！

    • cache_dir 这个参数的意义与存取格式的类型：

      • 这个设定项目就是限制暂存区大小的地方啦，格式为：

        cache_dir ufs /usr/local/squid/var/cache 100 16 256

      上面的说明是：暂存区目录为 /usr/local/squid/var/cache ，而暂存空间大小为 100M ， 在这个暂存目录下有 16 个目录，而每个目录中又有 256 个目录 ( 你可以实际进入 /usr/local/squid/cache 当中去看看 ) 。如果你要改变暂存档目录及这个目录的大小时，可以在这里修改！不建议修改 16, 256 这两个数值。另外，通常，如果是我们一般小型的区网 ( 不超过10个人 ) ，那设定个 500 MB作为 cache 应该够了，如果你的硬碟够大，设定成 1000 MB 以上更好，当然，与第一个注意事项相符的，需要与您的实际硬碟大小以及 Partition 放置的目录互相配合才行。修改过这个指令后，要再重新启动 squid 之前，请先使用下面的指令来使你的目录可以进行存取的动作，否则你的 squid 是不会工作的！例如你将上面的参数修改成：

        cache_dir ufs /usr/local/squid/var/cache 1000 16 256

      然后再进行下面的指令：

        rm -rf /usr/local/squid/var/cache
        mkdir /usr/local/squid/var/cache
        chown nobody:nogroup /usr/local/squid/var/cache
        /usr/local/squid/sbin/squid -z

      这样你的squid暂存目录就可以使用啰！另外，如果你在编译 (configure 过程中) 的时候有将 --enable-async-io 这一个参数加进来的话，将可以增加 aufs 这一个资料存取的格式！这个存取的格式可以将你的硬碟发挥到最极限的速度喔！虽然在 squid.conf 档案中有提及，这个 type 可能会有 bug 存在，不过，据鸟哥的使用结果，发现，没啥大问题！好用的很！所以，你可以将上面的咚咚改成下面的样子：
        cache_dir aufs /usr/local/squid/var/cache 1000 16 256

    这样就算已经完成了一个‘很阳春’的小型 proxy 了！为什么说很阳春呢？这是因为这个 Proxy 并没有上层 Proxy 喂资料，所以 Client 端的任何要求这个 Proxy 都需要‘自己去捉’啊！哇！那么这个 Proxy 还真累啊！没错啊，所以底下我们要再来谈一谈其他几个增加 proxy 效能的方法，好让大家的 Proxy Server 可以真的加快您浏览的速度啊！

    记忆体与磁碟快取留存百分比设定

    记忆体与磁碟快取在 squid.conf 当中的相关简易设定如下所示，至于更详细的说明则在下表之后进行解说：

    # 与记忆体有关的设定：因为我的系统很小，所以只给 8 MB！如果您的实体记忆体
    # 很大的情况下，例如 512 MB，可以考虑加大到 64 或 128 MB。
    cache_mem                       8 MB
    # 与磁碟容量有关的设定(注：下列的 90 与 95 是百分比 )
    # 如果您的 cache_dir 所在磁碟很大时，可以考虑将 4096 改成 32768 KB
    cache_swap_low                  90
    cache_swap_high                 95
    maximum_object_size             4096 KB
    # 与记忆体保存资料有关的设定
    maximum_object_size_in_memory   8 KB
    # 我们经由 dns 正反解以及 IP 的结果，记录在暂存区啊！
    ipcache_size                    1024
    ipcache_low                     90
    ipcache_high                    95
    fqdncache_size                  1024

    记忆体的需求数量：
    事实上，除了硬碟之外，记忆体可能是另一个相当重要的影响 Proxy 效能的因子！怎么说呢？因为 Proxy 会将资料存一份在 Cache 硬碟中，但是同时也会将资料暂存在记忆体当中啊，以加快未来使用者存取同一份资料的速度！所以啰，记忆体本来就会被 squid 的程式所消耗掉一些！一般来说，被 squid 消耗掉的记忆体约略每 1GBytes 的 cache_dir 空间就消耗 10MB 的记忆体容量，所以，如果以上面我们的设定为例 (cache1, cache2 共有 3GB)， 那么就有 30MB 以上的记忆体被消耗掉了！除此之外， squid 程式执行当中亦会额外的消耗掉一些实体记忆体，这部份占用掉的记忆体约为 10-20 MB 。

    除了这些记忆体是必须要的之外，您还可以额外的指定一些记忆体来进行比较‘热门’的资料存取！也就是说，可以额外的再加一些记忆体来帮助 squid 工作，而不仅只是上面提到的记忆体使用量！那个就是 cache_mem 这个设定参数的用途啦！所以，请特别留意啊，‘ cache_mem 并不是指我要使用多少记忆体给 squid 使用，而是指 "我还要额外提供多少记忆体给 squid 使用" 的意思’！因此，假设我有 X GB 的磁碟快取空间，而且 squid 程式使用掉 15 MB 的记忆体，那么我 squid 使用掉的记忆体就有：

      X * 10 + 15 + "cache_mem 设定值"

    您可以自行计算一下您的 squid 消耗掉多少记忆体喔！此外， squid 官方网站建议您的实体记忆体 (不含 swap 的记忆体容量) 最好是上面数值的两倍，也就是说，假如我的快取容量为 3 GB ， cache_mem 设定为 16MB ，那么我的 squid 至少会消耗掉 3*10+15+16 = 61MB，则我的实体记忆体最好至少要有 122 MB 以上，才会有比较好的效能！当然，这个单指 Proxy 部分而已，如果您的该部主机还有负责其他的工作，呵呵！那么记忆体就得在累加上去啦！一般来说，如果您的 Proxy 很多人使用时，这个值越大越好，但是最好也要符合上面的需求喔！

    关于磁碟容量的设定：
    请注意，如果您的磁碟快取空间额满了，那么您的 squid 也就‘挂点’了！因此，请随时注意你的磁碟快取空间！但是，要我天天去注意 squid 的 cache_dir 里面的容量，也太劳神了吧？！这个时候就必须要‘cache_swap_low, cache_swap_high ’这些设定的帮忙了！如果以上面表格的设定为例时，他的说明是‘当我的快取目录所占容量为总快取量的 95% 时，那么我的 squid 将会自动的将快取目录内的容量减低至剩下 90% 的容量！’注意，那个 90 与 95 为百分比例喔！以我们的设定为例，我的 cache_dir 总共有 3GB ，那么当快取空间被使用了 3*0.95=2.85GB 时，我的 squid 会自动的将 2.85GB 里面较旧的资料删除，使快取目录内剩下 3*0.9=2.7GB 的空间！这样能了解了吧？请特别注意，如果您的 proxy 容易很多人同时上线时，请将这两个数值更动一下，例如变更为 70 85 ，为什么呢？万一您的使用者突然间都上线了，然后下载大量的档案，那么‘瞬间’可能会使您的 cache 目录超过额度，导致 cache 死掉！所以降低 cache_swap_high 对于大型 proxy 是有需要的！

    是否需要记录捉到的资料：
    还有一个小问题要说明的，是否使用者要求过的资料我都要记录呢？呵呵！那当然不是啦！如果都记录的话，万一像最近好多 Linux distribution 都释出了他们新版的 Linux ISO 档案，那些档案一个都有 600 MB 以上的容量，万一使用者下载个几个这样的档案，我们的 Proxy 想不爆掉都很难～所以这个时候就要限制一下需要记录的‘最大档案’啦！在预设的情况下，我们的 squid 对于超过 4MB 的档案是不记录的(就是不放入 cache 的意思)，但是如果您的硬碟够大的话，我都喜欢将这个数值调大一点，为什么呢？万一我的使用者常常下载一些 10~20 MB 的套件档案，难道我每次都要到官方网站去下载一次吗？当然我不想这样啊！所以我通常将这个数值调大到 32MB ，或者是 32768 KB 啰！除了磁碟快取之外，记忆体的快取可以记录的最大档案容量也可以修正一下喔！但是我们的记忆体可就珍贵的多了！不要开太大，大约预设值就很不错了！

    关于 IP 与完整主机名称的纪录：
    如果能将 IP 与主机名称记录下来的话，搜寻的脚步也会加快一些的！所以以上面的表格为例，我们分别开启了 ipcache_size 与 fqdncache_size( 后面接的数值是 bytes )的记忆容量，由于这些资料都是 ASCII 的资料，用不了什么空间，因此 1024 bytes 已经足够了！至于后面的 low 与 high 则与前面说明的相同！

    acl 的用法与用途

    在 squid.conf 这个档案里面最常看到的大概就是 acl 这个设定项目了！他可是整个 squid.conf 的重头戏啊！很多的来源与目的管制都是靠他来设定完成的呢！我们底下就稍微谈一谈这个重要的咚咚吧！首先，他的语法为：

    <acl> <acl名称> <acl类型> <设定的内容>

    上面那个 <acl名称> 可以想成是一个昵称就是了！别想太多～就只是一个代名词，至于 acl 类型可就有趣的多了，他主要有下面这几大类：

    以来源端来控制：
    • src　 ip-address/netmask：主要控制‘来源的 IP 位址’，例如‘acl nckuip src 140.116.0.0/16’，这表示未来在 squid.conf 里面，任何使用到 nckuip 这个代名词时，就表示他是‘来源为 140.116.0.0/16 的位址’！
    • src　addr1-addr2/netmask：主要控制‘一段范围来源的 IP 位址’，例如‘acl nckuevoffice src 140.116.44.120-140.116.44.130/24’就表示 nckuevoffice 这个代名词为来自 140.116.44.120 到 140.116.44.130 之间这 11 个 IP 的要求！’请注意，是‘来源’喔！
    • srcdomain　.foo.com：主要控制‘来源为一某个网域的电脑’的意思，例如：‘acl vbirdhome srcdomain .vbird.org’，与 src 很类似，都是控制来源的用户端，只不过 src 控制的是 IP 而 srcdomain 则是控制 domain name 就是了！

    以目的端来控制：
    • dst　ip-address/netmask：主要控制‘目的端的 IP 位址’，与 src 类似，只不过是用来控制‘目的端’的位址！
    • dstdomain　.foo.com：这个就没问题了吧？就是用来控制‘目的端的网域’啰！与 srcdomain 类似喔！

    以正规表示法的方式来控制：
    • url_regex [-i] ^http:// ：除了上面两种基本的方法之外，我们也可以使用正规表示法的方式来控制‘网域’的设定值呢！例如‘ acl urlname url_regex ^http://linux\.vbird\.org.* ’这表示 urlname 代表的就是来自 http://linux.vbird.org 这个网站的‘任何资料’，因为‘ .* ’代表任意字元的意思啊！如果仅只是一些档名，例如 gif 这一类的档名时，要怎么作呢？就如底下的说明啦！
    • urlpath_regex [-i] \.gif$：上面提到的是关于整个网址的名称，这里则是只要‘URL 部分相同’就可以啦！例如‘acl gifname urlpath_regex \.gif$ ’则是代表 gifname 代表的是 url 后面是 .gif 的网址，呵呵！那就是 gif 的图档附档名嘛！！这样应该不难理解了吧！

    由于在 squid 当中很多时候都会用到一些 IP 网域啦，以及 domain name 等等的资料，这个时候这个 acl 就可以看做与 bash 里面的‘变数’很类似啰！您可以参考看看的啦！只是他的用途相当的广泛，这个在底下我们会进一步的使用 acl 搭配各种设定值来进行说明的！

    上层 Proxy 的选择与负载分流的设定方法

    上层 Proxy 的设定方式： cache_peer
    我们在上面的原理部分说明过，一部有效能的 Proxy server 必须要能利用上层 Proxy 所提供的效能，才能达到我们所想要的‘加速’功能！那么当然大前提之下就是需要先找到‘最佳效能的上层 Proxy 主机’啰！没错！就是这样的啦！在这里，我们以成功大学的学术网路为架构进行说明，如果您的网路架构并非为学术单位的话，请依照您能找到的上层 Proxy 来进行设定喔！需要特别留意的是，由于成大有许多的上层代理伺服器，这些伺服器都可以做为我个人 proxy 的 parent proxy 主机，不过，由于各个主要的 parent proxy 所提供的网域服务都不尽相同，所以我们得先将主要的几个伺服器对应的网域给他找出来，底下是一个例子：

    gate.ncku.edu.tw  主要服务 .com 的网域
    gate3.ncku.edu.tw 主要服务 .net .edu 的网域
    gate2.ncku.edu.tw 主要服务非 .com .net 与 .edu 的网域
    proxy.ncku.edu.tw 主要服务任何网址

    至于在 squid.conf 当中设定的参数则是‘cache_peer ’这个项目，设定的样式为：

    <cache_peer> <主机名称> <类别> <http_port> <icp_port> <其他参数>
    类别：主要有上层(parent) 与同一层 (sibling) 两种，我们这里主要介绍的是
          上层 Proxy 也就是 parent 这一大类，如果您想要架设一个小型的 Proxy
          Cluster 的话，可以考虑组成 sibling 的功能，由于我们仅想要架设单部
          Proxy Server ，所以这里我们就不探讨 sibling 了！
    http_port icp_port：就是我们最前面设定的啦！ Internet 上面预设是
          3128 3130 这两个！
    其他参数：其他参数的部分就很重要了，主要有底下几个重要参数：
        proxy-only ：只取出上层 Proxy 的 cache 给 client ，并不会将上层 Proxy
            的资料存在自己的 cache 硬碟中；
        weight=n　 ：权重的意思，因为我们可以指定多部上层 Proxy 主机，哪一部
            最重要？就可以利用这个 weight 来设定， n 越大表示这部 Proxy
            越重要！
        no-query　 ：一般来说，如果要向 sibling 要求资料时，会向 sibling 送出
            icp 的要求封包，使用 no-query 就可以取消。一般来说，如果向上层
            Proxy 要求资料时，可以不需要发送 icp 封包，以降低主机的负担
        default　　：表示该部主机为预设的 Proxy 主机的意思；
        no-netdb-exchange：表示不向附近的 Proxy 主机送出 imcp 的封包要求
        no-digest　：表示不向附近主机要求建立 digest 纪录表格。
    范例：
    cache_peer gate.ncku.edu.tw parent 3128 3130 no-digest no-netdb-exchange
    cache_peer gate2.ncku.edu.tw parent 3128 3130 no-digest no-netdb-exchange
    cache_peer gate3.ncku.edu.tw parent 3128 3130 no-digest no-netdb-exchange
    cache_peer proxy.ncku.edu.tw parent 3128 3130 no-digest no-netdb-exchange

    基本上，由于我们向上层 Proxy 要求资料的时候，也是需要时间的，因此，这里我们建议您不要设定太多的上层 proxy 主机，一般来说， 2~4 部也就足够了，太多部 上层Proxy 的情况反而可能会拖垮您的 Proxy 速度呢！OK！既然有了上层 Proxy ，而且每一部所负责的网域并不相同，所以我们当然就需要将网域分门别类啰！如何将这些网域分门别类呢？那就需要 acl 的帮忙啦！先提醒一下，由于我们的 Proxy 旨在帮助 client 端取得资料，所以使用 acl 的时候，是针对‘目标’来进行设定的，因此，使用的是 dst 与 dstdomain 喔！在这里，我们将主要的网域分成底下这几大类：

    0. 自己想要直接使用自己的 Proxy 捉取的资料
    acl directip dst 140.116.44.0/24
    acl directdn dstdomain .vbird.org tw.yaoo.com tw.news.yahoo.com

    1. 成大附近的网域
    acl nckudn dstdomain .ncku.edu.tw
    acl nckuip dst 140.116.0.0/16 163.28.112.0/24 163.28.113.0/24 163.28.114.0/24 163.28.115.0/24 163.28.116.0/24 163.28.117.0/24

    2. 台湾的网域 (请注意：底下为同一行)
    acl twdn dstdomain .tw .twnic.net .hinet.net .acer.net .wownet.net .seeder.net .silkera.net .neto.net timenet.net tw.aunet.net .adsldns.org

    3. 台湾的 IP (注意：底下为同一行)
    acl twip dst 163.28.0.0/16 140.96.0.0/11 140.128.0.0/12 140.92.0.0/16 139.175.0.0/16 139.223.0.0/16 163.12.0.0/14 163.16.0.0/14 168.95.0.0/16 192.72.0.0/16 192.83.160.0/19 192.83.192.0/22 192.192.0.0/16 202.39.0.0/16 202.132.128.0/17 202.145.224.0/19 203.64.0.0/12 210.64.0.0/13 210.60.0.0/14

    4. 一些商业、网域、教育、以及其他的网域
    acl comdn dstdomain .com
    acl netdn dstdomain .net
    acl edudn dstdomain .edu

    这样子就作好了基础的工作了！接着下来，我们要开始来设定‘各个主要的网域要透过哪一个上层 Proxy 来进行资料的取得？’这里就有点难度啦！得小心在意一下！我们的基本假设为这样：
    gate.ncku.edu.tw  仅负责 .com 的网域；
    gate3.ncku.edu.tw 仅负责 .net 与 .edu 的网域
    gate2.ncku.edu.tw 不负责上面的三个网域
    proxy.ncku.edu.tw 不负责上面三个网域
    这么一来，使用 cache_peer_access 这个设定项目时，我们的设定会变成这样喔！

    # 主要的格式范例：
    # <cache_peer_access> <上层 Proxy > <allow|deny> <acl名称>
    cache_peer_access gate.ncku.edu.tw  allow comdn
    cache_peer_access gate.ncku.edu.tw  deny  !comdn
    cache_peer_access gate3.ncku.edu.tw allow netdn
    cache_peer_access gate3.ncku.edu.tw allow edudn
    cache_peer_access gate3.ncku.edu.tw deny  !netdn
    cache_peer_access gate3.ncku.edu.tw deny  !edudn
    cache_peer_access gate2.ncku.edu.tw deny  comdn
    cache_peer_access gate2.ncku.edu.tw deny  netdn
    cache_peer_access gate2.ncku.edu.tw deny  edudn
    cache_peer_access gate2.ncku.edu.tw deny  directdn
    cache_peer_access gate2.ncku.edu.tw deny  directip
    cache_peer_access gate2.ncku.edu.tw deny  twdn
    cache_peer_access gate2.ncku.edu.tw deny  twip
    cache_peer_access gate2.ncku.edu.tw deny  nckudn
    cache_peer_access gate2.ncku.edu.tw deny  nckuip
    cache_peer_access proxy.ncku.edu.tw deny  comdn
    cache_peer_access proxy.ncku.edu.tw deny  netdn
    cache_peer_access proxy.ncku.edu.tw deny  edudn
    cache_peer_access proxy.ncku.edu.tw deny  directdn
    cache_peer_access proxy.ncku.edu.tw deny  directip
    cache_peer_access proxy.ncku.edu.tw deny  twdn
    cache_peer_access proxy.ncku.edu.tw deny  twip
    cache_peer_access proxy.ncku.edu.tw deny  nckudn
    cache_peer_access proxy.ncku.edu.tw deny  nckuip

    经过上面这个动作，我们就可以将 .com 的要求经过 gate.ncku.edu.tw 这一部，并且将 .net 与 .edu 给 gate3.ncku.edu.tw 来服务！此外，将没有被自己定义出来的 IP 或者是网域就丢给 gate2 以及 proxy 这两部来服务，至于我们既然是在台湾，所以自己定义出来的四个 acl 名字 (directdn, directip, twdn, twip) 当然是直接交给我们自己的 Proxy 来捉取了，相信速度上面应该不会有任何的影响的！因此，那四个主要的 acl 名称将在后面继续介绍如何不要透过上层 Proxy 来捉取资料喔！ ( 请参考 always_direct 与 never_direct 的设定值 )

    不要进行 cache 的设定值：
    就如同我们在原理的部分提到的，有些网站的资料事实上并没有做为 cache 的需要，例如 CGI 档案就是一个很鲜明的案例！所以，一般而言， squid 在一开始就会自动帮我们设定好底下这三行：

    hierarchy_stoplist      cgi-bin ?
    acl QUERY urlpath_regex cgi-bin \?
    no_cache deny QUERY

    上面这三行的意思是：‘只要在网址列出现了 cgi-bin 的字样时，该网页资料就不进行 cache 的动作！’这样一来，可以避免我们的主机存放太多的垃圾啊！ ^_^！当然啦，在某些时候，例如您所在的网域真的是很慢，同时又没有适合的上层 Proxy 的环境下，那么将 cgi 之类的网页 cache 下来，也未尝不是一个可以节省浏览时间的一个方法！如果确定要将 cgi-bin 底下的网页也存下来的话，那么就将上面三行注解掉啰！

    与时间相关的设定值 ( connect_timeout, request_timeout )

    由于 Proxy 的设定除了防火墙的额外功能外，最主要的目的还是在于将网页资料 cache 下来！既然如此的话，那么与 Server 的连线时间的确认就显的很重要啦！怎么说呢？万一今天您有设定三部上层 Proxy ，每一部的要求时间都控制在 5 分钟，如此一来，呵呵！万一今天刚好三部上层 Proxy 都挂点，难道我们就宿命似的要等待 15 分钟吗？当然不是啦！所以这个时候，我们可以将连线的等待时间缩短，好让 Proxy 可以发挥更为强大的功能啊！

    # 1. 关于 cache 的更新时间趋势
    # 我们在快取当中的资料总是需要更新的对吧！那么如何设定更新的时间呢？
    # <refresh_pattern> <regex> <最小时间> <百分比> <最大时间>
    # 注意，那个 regex 指的是‘目标’，这个‘目标’大部分为网址，而这个网址
    # 使用正规表示法来表示就是了！上面的意义是说：最小的时间内 (分钟)，如果
    # 档案有更动，就直接更新，或者是目标档案上次更新的时间到现在已经经过最大
    # 时间的‘百分比’时，就予以更新！范例如下：
    refresh_pattern ^ftp:           1440    20%     10080
    refresh_pattern ^gopher:        1440    0%      1440
    refresh_pattern .               0       20%     4320
    # 第一行的意思是，如果网址裂开头是 ftp 的话，那么在一天(1440分钟)后，如果
    # proxy 再次取用这个档案时，则 cache 内的资料会被更新！

    # 2. 关于连线时间限制
    # connect_timeout 指的是连接到其他主机的时间多久之后算失败，预设是两分钟
    #　　　　　　　　 不过我觉得我的机器连线速度还算快速，所以减低了时间
    # peer_connect_timeout 指的是连接到上层 Proxy 多久不成功就算失败，
    #　　　　　　　　 由于上层 Proxy 与我的环境息息相关，不可能连不上，
    #　　　　　　　　 所以我这里将时间调整的很短！
    # request_timeout 指的是，连线上了，但是要求的时间会多长？
    # persistent_request_timeout 指的是连续要求时间会有多长？
    connect_timeout 30 seconds
    peer_connect_timeout 10 seconds
    request_timeout 1 minutes
    persistent_request_timeout 20 seconds
    # 请特别注意喔！上面的设定当中，是因为我的环境‘还算不错’，所以我将
    # 时间调整的很短，因为我晓得我的环境当中不会有花很长时间的状况，
    # 这里请依照您的网路环境来调整喔！或者干脆不要设定也没有关系！

    总是系统自己来捉资料(always_direct)

    刚刚我们在主机分流的地方有提过，有些资料我们要让我们自己的 Proxy 去捉取资料即可，而不透过上层 Proxy ，那么怎么达到这样的目的呢？也不是很难啦！就告诉 Proxy 不要去捉就好啦！怎么告诉他呢？使用 always_direct 或 never_direct 即可！

    # 1. 使用 acl 先定义出要直接或者不要直接去的网址或 IP ，
    # 　 这个部分我们刚刚在上面已经设定好了，就是 directip 与 directdn，
    #　　还有 twdn 与 twip 这几个咚咚！
    # 2. 如果是直接要 Proxy 出去捉资料，可以使用 always_direct
    always_direct allow directip directdn

    # 3. 如果一定‘拒绝经由上层 Proxy 出去’的话，可以使用 never_direct
    never_direct deny twdn twip

    # never_direct allow 表示一定会经由上层 Proxy 来捉资料，
    # never_direct deny  当然就表示一定是自己向外头捉资料啰！

    事实上，这个东西可以让我们的 Proxy 变的很灵活！假设这样的一个案例，我们自己有一个内部的 WWW 网站，这个网站的网址为 192.168.0.100 ，如果我要经由上层 Proxy 去捉资料的话，那不就完蛋了～因为这个是‘私有 IP ’的网域啊！所以，我将他写入 directip 那个 acl 的设定当中，如此一来，呵呵！我们的 Proxy 会自动的经由自己的 route table 去到内部网域读取资料给你，您根本不需要变更您的其他设定就可以自由自在的读取内部与外部的主机资料！此外，如果您发现同一网域还有其他的 WWW 主机，把这些主机的 IP 或主机名称写入 directdn 或 directip 的 acl 设定当中吧！因为在同一网域时，您自己去捉一定会比上层 proxy 捉完之后再传给你来的快吧！

    当然还不只如此啦，有的 WWW主机由于设定的关系，他们并不允许我们的上层 Proxy 来捉取资料，最常见的例子就是类似总图对校内的 client 端开放的图书查寻的软体了！因为如果开放了这些上层 proxy 的话，那么全台湾所有的人只要将他们的浏览器 proxy 设定为成大的上层 proxy 主机，就可以使用成大的资源了！那岂不麻烦？因为这些资源是需要花费经费的啊！这个时候，您也就必须要让这些网址经由我们的 Proxy 自己去捉取啰！这样可以了解乎！

    限制使用 proxy 使用者与 proxy 目标的方式 (acl and http_access )

    既然 proxy 有一定的风险存在，自然就不能让任何人都能使用你的 proxy 主机啰！没错！所以我们必须要管制连线的使用者！管制的方法真是简单的很！就是使用 acl 配合 http_access 即可！在预设的情况中， squid 已经帮我们设定好一些安全的可以连线的 port 了，此外，也只有本机可以使用 proxy 功能呢！

    那么万一如果我样让内部 192.168.0.0/24 这个网域的使用者可以使用我的 proxy 呢？该如何设定？呵呵！您可以这样做：

    # 1. 先设定这个内部网域的 acl 名称
    acl inside src 192.168.0.0/24

    # 2. 设定 http_access 让他可以使用
    http_access allow inside
    http_access deny  all

    那个 http_access deny all 是系统预设的项目！刚刚我们在 最简单的 squid.conf 设定 时已经将他改成 http_access allow all 了！所以请记得将他给改回来啊！不然的话，您的 Proxy 很有可能会被人家利用喔！

    这里再提供一个值得思考的咚咚，如果您跟我一样，都是使用拨接的 ADSL ，这样一来，由于我们的 IP 都不是固定的，如果要让我们的 ADSL 拨接的 client 可以使用我们刚刚设定的 Proxy 时，该怎么办？啊！这样就不能使用‘ acl 配合 src ’的设定方式了吗？呵呵！当然不是，您可以这样想像：

    1. 我先申请一个动态 DNS 的网域名称，例如我的 tsai.adsldns.org ；
    2. 虽然我可以直接在 squid.conf 当中设定 acl 并使用 srcdomain 来设定我的 tsai.adsldns.org ，但是很抱歉的是，如果我的 tsai.adsldns.org 来连接到 Proxy 主机时，事实上，我的拨接制 IP 反查得到的主机名称一定不是 tsai.adsldns.org ，如此一来则 srcdomain 一点用处也没有了；
    3. 再换个方式，如果我写一支 script 来侦测 tsai.adsldns.org 所对应的 IP 呢？并且将他写入一个自订的设定档当中，这样一来，这个档案会随时记录最新的 tsai.adsldns.org 的 IP ，如此一来，我就可以使用 acl 配合 src 的设定方式了！

    很麻烦吗？一点也不会，整个 script 可以像底下这样：

    [root@test root]# cd /usr/local/squid/etc
    [root@test etc]# vi squid.allow.sh
    #!/bin/bash
    # 这支程式可以用来查寻您的 IP 喔！

    # 1. 请输入您的主机名称，请注意，如果有两个以上的主机名称，
    #    请分别以空格分开各个主机名称
    hostnames='tsai.adsldns.org test.adsldns.org'
    basedir=/usr/local/squid/etc/
    email=root@localhost
    squid=/usr/local/squid/sbin/squid

    # 2. 以下为程式段，看看就好了！
    [ -f $basedir/squid.allow.hosts.raw ] || \
            touch $basedir/squid.allow.hosts.raw

    cat /dev/null > $basedir/squid.allow.hosts.now
    runornot=no

    for host in $hostnames
    do
            hostip=`host $host | awk '{print $4}'`
            if [ "$hostip" == "out;" ]; then
                    echo 'Proxy 回应：没有 DNS 的讯息！' |\
                    mail -s 'Proxy 主机回应' $email
                    exit
            fi
            fileraw="$basedir"/squid.allow.`echo $host|cut -d '.' -f1`
            [ -f $fileraw ] || touch $fileraw
            hostraw=`cat $fileraw`
            if [ "$hostraw" != "$hostip" ]; then
                    runornot="yes"
                    echo $hostip > $fileraw
            fi
            echo $hostip >> $basedir/squid.allow.hosts.now
    done

    if [ "$runornot" == "yes" ]; then
            cat $basedir/squid.allow.hosts.raw >  $basedir/squid.allow.hosts
            cat $basedir/squid.allow.hosts.now >> $basedir/squid.allow.hosts
            $squid -k reconfigure
            mail -s 'Proxy 主机回应！Client IP 已经改变' $email < $basedir/squid.allow.hosts
    fi

    如此一来，我将可以把我的随时最新的 IP 纪录在 /usr/local/squid/etc/squid.allow.hosts 这个档案当中！那么要如何更新这个档案的内容在 squid 的设定档中呢！就这样设定即可：

    # 1. 先设定这个档案的名称吧！
    acl allowhost src "/usr/local/squid/etc/squid.allow.hosts"

    # 2. 设定 http_access 让他可以使用
    http_access allow allowhost
    http_access deny  all

    然后将上面这个 squid.allow.sh 给他丢进去 crontab 当中，我预设都是在 30 分钟跑一次！

    [root @test root]# vi /etc/crontab
    10,30 * * * * root /usr/local/squid/etc/squid.allow.sh

    这样就完整的啦！ ^_^

    额外的功能参数

    除了上面提到的这些关于网页快取的功能之外， Proxy 还可以帮我们进行 FTP 的服务取得资料喔！我们可以透过浏览器，经由 proxy 提供的 FTP 功能来登入对方主机，当然，对方主机必须要能够提供匿名登入啊！好了，我们来看看要怎样设定呢？

    # 与 FTP 有关的设定项目，主要是针对被动式连线方式来设定喔！
    ftp_user Squid@
    ftp_passive on

    # 主要与 DNS 的设定值有关，如果在高负载的 Proxy 环境下，可以考虑将
    # dns_children 提高到 20 左右，这个值最大为 32
    dns_timeout 1 minutes
    hosts_file /etc/hosts

    还有一些额外的范例可以参考看看喔：
鸟哥的范例：http://linux.vbird.org/linux_server/0420squid/0420squid_vbird_ex
成大 gate.ncku.edu.tw 的 squid.conf 设定：http://turtle.ee.ncku.edu.tw/~tung/proxy/squid.conf.ncku
电机系 turtle.ee.ncku.edu.tw 的 squid.conf 设定：http://turtle.ee.ncku.edu.tw/~tung/proxy/squid.conf.turtle
台南学校范例 proxy.school.tn.edu.tw 的 squid.conf 设定：http://turtle.ee.ncku.edu.tw/~tung/proxy/squid.conf.school.tn
Client 端设定
    既然 proxy 是给浏览器用的，那么自然在浏览器上面就需要设定一些参数啰！呵呵，没错！那么如何设定呢？由于不同的浏览器在设定 Proxy 的地方也都不同，所以底下我们介绍目前比较常见的两款浏览器，分别是 Netscape 以及 IE 的设定，至于其他的浏览器，请参考各浏览器的相关说明啊！

    Netscape

    Netscape 的设定并不难，只要修改一个小地方即可！

    1. 开启 Netscape 之后，启用‘编辑’并选择‘偏好设定’项目，如下所示：

      2.

    2. 在出现的画面当中，先按下‘进阶’左边的展开模式，然后选择底下的‘代理伺服器’，则画面会出现如下的模样。之后，在右边的视窗当中选择‘自行设定代理伺服器的组态’项目，并且再按下‘检视’，则到下一步去设定：

      3.

    3. 在出现的方框中，由于我们通常仅针对 WWW 进行快取，所以可以仅针对 HTTP 的项目进行设定！在下面的画面当中，请输入‘Proxy 主机的 IP 或者是 domain name ’，以及‘连接的 port number’，这样就可以了。不过，如果有某些网域您想要直接让你的 PC 去捉取资料时，可以将该网域名称填写在最下方的方框中！以下面的画面为例，我的 PC 要连接到 linux.vbird.org 以及 www.study-area.org 时，就可以不透过 Proxy 啦！这个功能也挺适合可以自行调配流量、流速的朋友！

      4.

    4. 再按下‘确定’之后，立刻就生效了！

    Internet Explorer

    在 IE 的设定上面也一点都不难啊！

    1. 开启 IE ，然后在‘工具’内选择‘Internet 选项’：

      2.

    2. 在开启的视窗内选择‘连线’并点选下方的‘区域网路设定’：

      3.

    3. 在出现的方框中，先在下方打勾起‘使用 Proxy 伺服器’，然后依序在网址列填入‘ Proxy 的网址或者是 IP ’以及连接埠填入‘ Proxy 所开放的 port number’，如下方的设定即可。

      4.

    4. 另外，如果有某些网域不想透过这个上层 Proxy 的话，点选上图的 ‘进阶’ 那一项，在出现的框框的最底下，可以填入你不想透过 Proxy 捉取的网站网址，如下所示：

      5.

    如此一来则设定好了 Proxy Server 啰！
Server 端进阶设定
    既然一些主机的设定已经搞定了，接着下来又是到了 Server 的安全与进阶设定时间啦！那么在安全的设定方面，最重要的自然又是我们一再强调的登录档的分析啰！如何分析登录档呢？难道又要自己动手写分析的 scripts ？？呵呵！不用麻烦了，我们可以使用前辈智慧的结晶，直接有软体可以来进行分析喔！还有，既然强调 Proxy 可能会被滥用，所以当然要适当的管理了！这个时候的防火墙设定又要出现啦！呵呵！赶紧来看一下怎么处理吧！

    末端资料分析 pwebstat

    事实上， squid 已经有众多的登录档分析软体了，而且大多是免费的 (http://www.squid-cache.org/Scripts/) ，您可以依照自己的喜好来加以安装与分析你的 squid 喔！我这里仅介绍目前很常被使用的一套软体，也就是 pwebstats 这一套！你可以在 pwebstats 的官方网站上面查得更新的资料 ( http://martin.gleeson.com/pwebstats/installation.html )。不过，由于 pwebstats 在安装的时候需要使用到其他的函式库，因此，你必须要先安装 fly 这套软体才行啊！而在安装 fly 之前，又需要先安装一些必备的图示用的函式库才行，那就是类似 gd, libpng, zlib 等等的套件喔！听起来似乎很多东西要做，但是事实上却非常简单的啦！好吧！那么我们就一步一步的来安装这个 pwebstats 吧！

    安装所需要的套件资料：
    除了系统自己可能已经安装好的 gd, libpng, zlib 之外，您可以由文末提供的官方网站的连结来取得最新的 fly 与 pwebstats 套件，而如果您不需要使用最新的资料，那么也可以经由 鸟哥的私房菜 提供的比较旧的套件版本来安装 ( http://linux.vbird.org/download/ )。我这里假设您已经将所需要的 fly-2.0.0.tar.gz 与 pwebstats-1.3.8.tar.gz 套件都下载到 /root 底下了，那么您可以这样做：

      1. 确认一下到底有没有我们需要的一些相关套件？
      [root@test root]# rpm -qa | egrep '(^gd-|^zlib-|^libpng-)'
      libpng-devel-1.0.14-0.7x.4
      gd-1.8.4-4
      zlib-1.1.3-25.7
      zlib-devel-1.1.3-25.7
      libpng-1.0.14-0.7x.4
      gd-devel-1.8.4-4
      # 请注意，我是以 Red Hat 7.2 为例，如果您的系统并非 RH 7.2 ，那么可能
      # 套件后面接的版本会不太一样，不过，至少都需要有上面的几样套件就是了！
      # 就是 gd, zlib, libpng 这三个套件啦！有的 distribution 还会有 xxx-devel
      # 之类的名称，那个也需要安装喔！如果发现没有安装的话，请拿出您的原版光碟片，
      # 将他 mount 上之后，好好的将他搜寻一下，并且安装上去吧！很重要，一定要
      # 安装这些套件之后，底下的动作才会成功呢！

      2. 开始安装 fly 这支程式
      [root@test root]# cd /usr/local/src
      [root@test src]# tar -zxvf /root/fly-2.0.0.tar.gz
      # ....会产生一个 fly-2.0.0 的目录
      [root@test src]# cd fly-2.0.0
      [root@test fly-2.0.0]# make
      注：
      # ....如果没有出现底下的字样那么就是成功了！
      /usr/bin/ld: cannot find -lttf (或者是 ljpeng ...)
      collect2: ld returned 1 exit status
      make: *** [fly] Error 1
      # 如果是出现 warning 的话，还不打紧，因为仅只是警告而已，所以问题不大，
      # 但是如果出现上面的字样时，就会连带出现第三行的 Error ，那就是编译失败了
      # 果真如此的话，请先寻找一下，以上面为例，找不到 lttf ，而 lttf 其实
      # 就是 libttf 档名啦！(所以 ljpeg 就是 libjpeg )所以给他下达：
      loate libttf
      /usr/lib/libttf.so.2
      # 嗯！找到了！其实是 libttf.so.2 啦！如果你的系统跟我的不同，有可能档名
      # 会不一样，所以请依照你的荧幕显示的讯息来下达指令喔！但是这个编译程式
      # 有点笨，不认识这个档案，所以我们要欺骗他一下，就是下达：
      ln -s /usr/lib/libttf.so.2 /usr/lib/libttf.so
      # 这样就可以啦！如果还有找不到的档案，同样的方式给他连结一下即可！然后
      # 再次的给他执行一次 make 即可！最后会产生一个档名为 fly 的执行档，
      # 如果没有产生执行档，那就是有问题啦！请赶紧再回头去查一查是否有某些
      # 套件没有安装，或者没有依照上面的方式建立连结档案！

      [root@test fly-2.0.0]# cp fly /usr/local/bin
      我们先将 fly 这支程式给他复制到 /usr/local/bin 这个目录去，可以直接使用
      这样就 OK 了！

      3. 开始安装 pwebstats 套件
      [root@test root]# cd /usr/local/src
      [root@test src]# tar -zxvf /root/pwebstats-1.3.8.tar.gz
      # 此时会产生 /usr/local/src/pwebstats-1.3.8 这个目录，这目录里面
      # 已经是可以执行的资料了，不需要进行任何的编译，所以我们将他直接移动到
      # /usr/local/ 里面去！
      [root@test src]# mv pwebstats-1.3.8 /usr/local/pwebstats
      [root@test src]# cd /usr/local/pwebstats
      [root@test pwebstats]# vi pwebstats <==这个是主要的执行档！
      # 由于我们的 perl 这个程式语言的执行档是放置在 /usr/bin/perl ，但是
      # 这支程式预设是书写为：
      #!/usr/local/bin/perl
      # 将上面改写为
      #!/usr/bin/perl
      # 这样就可以了！继续下一步！

      4. 开始设定 squid 的输出输入参数：
      前提要件：
      a. 我的 WWW 主页目录在 /var/www/html
      b. 我的 pwebstats 整个资料库放置在 /usr/local/pwebstats
      c. 我的 squid 登录档放置在 /usr/local/squid/var/logs/access.log.0
      d. 我的 squid 的执行档为 /usr/local/squid/sbin/squid
      e. 我的 pwebstats 输出的资料放置在 /var/www/html/pwebstats
      f. 我的 fly 是放在 /usr/local/bin/fly
      [root@test pwebstats]# mkdir /var/www/html/pwebstats<=请依您的主机而定
      [root@test pwebstats]# cd /usr/local/pwebstats/conf
      [root@test conf]# vi squid-proxy.conf  <==这个就是主要的设定档！
      # 底下请填写你的主机的‘昵称’！
      server:My_Proxy_Server
      # 这个是显示在网页上面的标题内容！
      Server_header:我的代理伺服器
      # squid 登录档放置的完整档名
      logfile:/usr/local/squid/var/logs/access.log.0
      # 我们使用的就是 squid 的登录档啊！所以这里不需改变
      logtype:squid
      # 刚刚提到的，网页资料要输出到底下的目录
      outdir:/var/www/html/pwebstats
      # 一些图像档案的预设目录，这里我们使用 pwebstats 提供的目录！
      templates:/usr/local/pwebstats/templates
      # 嗯！我们就天天来进行一次吧！可以用 weekly 或 daily
      interval:daily
      # 是否在执行的过程中给他输出讯息呢？好吧！
      verbose:true
      # fly 放置的目录，刚刚我们移动的目录啊！
      fly_prog:/usr/local/bin/fly
      # 本机端的要求，这里可以不用设定喔！
      local_patt:
      # 列出几部 client 电脑？我给他来个 50 部好了！
      host_threshold:50
      # 列出几部 Server (被要求资料者)，还是给个 100 部吧！
      remote_host_threshold:100
      # 统计的次数，给他 100 次好了！
      item_threshold:100
      # 做多少个 domain 的分析？给他 15 个就够多了！
      domain_threshold:15
      # 底下保留预设值即可！ (最后面的 dns 反查可以启动！)
      exclude_reqs:true
      #complete_exclude_host:
      #complete_exclude_url_patt:
      #complete_exclude_user:
      dns_lookup:true
      # 事实上，只要上面粗体字的地方写对就好了！其他的保留预设值即可！

      5. 测试执行一次看看：
      [root@test conf]# /usr/local/squid/sbin/squid -k rotate
      上面这个动作会将 squid 的登录档进行 logrotate 的动作喔！就会更新了
      /usr/local/squid/var/logs/access.log.0 这个档案啦！
      [root@test conf]# /usr/local/pwebstats/pwebstats -c  \
      > /usr/local/pwebstats/conf/squid-proxy.conf
      .....(略)......
      -- Reading in log file /usr/local/squid/var/logs/access.log.0:
         The logfile has 27 entries.
         Processing...
         0%                     50%                      100%
         |-----------------------|------------------------|
         ##################################################
         Finished.
      .....(略)......
      呵呵！这样就是成功啦！！！！

      6. 将每天执行的指令写成 scripts 吧！
      # 我将他写在/usr/local/pwebstats/pwebstats.sh 这个档案当中喔！
      [root@test conf]# vi /usr/local/pwebstats/pwebstats.sh
      #!/bin/bash
      /usr/local/squid/sbin/squid -k rotate
      sync; sleep 5s
      /usr/local/pwebstats/pwebstats -c /usr/local/pwebstats/conf/squid-proxy.conf
      [root@test conf]# chmod 755 /usr/local/pwebstats/pwebstats.sh
      [root@test conf]# vi /etc/crontab
      # 加入底下这一行吧！
      59 2 * * * root /usr/local/pwebstats/pwebstats.sh >/dev/null 2>&1

    很简单吧！这样就安装完毕了！不过，由于我们安装的 fly 可能有点问题啦！就我的系统来说，这个 fly 总是编的怪怪的～如果您的 fly 无法编译成功的话，那么直接由鸟哥的私房菜提供的档案来直些下载使用算了！ http://linux.vbird.org/download 找一下 fly 的 binary ，下载完毕之后，请记得：

      gzip -d fly.gz
      chmod 755 fly
      mv fly /usr/local/bin

    这样就可以了！而刚刚我们不是有执行过一次吗？你的登录资料会被放置在 /var/www/html/pwebstats 这个目录当中！假如我的首页就是 /var/www/html/ 的话，那么我的网址列输入 http://myIP/pwebstats 就可以看到类似下图：

    在按下了‘Day 1’之后，会出现如下的画面：

    呵呵！更详细的内容您就可以自行看看啰！加油的啦！！

    末端资料分析 sarg

    除了上面介绍的 pwebstats 之外，其实还有一套相当棒而且功能相当强悍的分析软体，那就是 Squid Analysis Report Generator ( Squid 分析报告制作者)，他的官方网站在：http://web.onda.com.br/orso/sarg.html，他的原理相当的简单，就是将 logfile 拿出来，然后进行一下解析，依据不同的时间、网站、与热门网站等等来进行资料的输出，由于输出的结果实在是太详细了！所以.....呵呵！如果你是老板的话，用这个软体会让你‘爱不释手’啊！因为每个人的每个小动作都会被记录下来，我的天呐！当我第一次看到这个分析的画面时，真的给他吓了老大一跳得说～因为连每个 IP 在‘每个小时所连上的每个网站资料’都有纪录～～害怕了吧～

    不过，有优点就有缺点啦！怎么说呢？因为 SARG 功能太强大了，所以记录的‘资料量’就实在是多了点，如果您的 Proxy 网站属于那种很大流量的网站时，那么就不要使用‘日报表’，也就是每天产生一份报表的那种方式！那么由于资料一天可能会有几 MB 的资料，一两个月还没有关系，如果记录了几年，那么光是这些记录就会花掉好几 GB 的硬碟空间了～此外，也可以使用‘覆盖旧有资料’的方式不要留存旧资料，这样也可以节省硬碟的空间啦！

    这个 SARG 软体已经出到 1.4 版，更好的是，他支援‘多国语系’呢！目前鸟哥已经翻译了一部分的资料，希望能对大家有点帮助啊！对于这个套件，你可以到官方网站上下载最新的版本 ( http://web.onda.com.br/orso/sarg.html ) ，而鸟哥这里也有提供啦！我提供的版本是 1.4 的( 在 2003/03/16 释出的版本 )，已经经过了 patch (套件修补) 的动作，并且加入中文化的语言档案，所以直接下载就有中文显示啰！请到档案下载中心下载：

    • http://linux.vbird.org/download#squid_ap

    整个安装与执行的过程很简单的！我们来试看看吧！(注：假设您已经将 sarg-1.4.taiwan_big5.tar.gz 放置在 /root 底下了！)：

    # 1. 解压缩：
    [root@test root]# cd /usr/local/src
    [root@test src]# tar -zxvf /root/sarg-1.4.taiwan_big5.tar.gz
    ....(略).....
    这个时候会产生一个名为 sarg-1.4 的目录出来！

    # 2. 设定、编译与安装
    [root@test src]# cd sarg-1.4
    [root@test sarg-1.4]# mkdir /usr/local/sarg
    [root@test sarg-1.4]# ./configure --prefix=/usr/local/sarg  \
    > --enable-mandir=/usr/local/sarg/man1  \
    > --enable-bindir=/usr/local/sarg/bin  \
    > && make && make install
    这样可以快速的设定、编译与安装，一次完成！
    安装的资料当中：
    a. 设定档 /usr/local/sarg/sarg.conf
    b. 执行档 /usr/local/sarg/bin/sarg
    c. 说明档 /usr/local/sarg/man1/sarg.1

    # 3. 额外设定 ( 说明文件的路径 )
    [root@test root]# vi /etc/man.config (有时为 man.conf 档名不同！)
    新增加这一行
    MANPATH /usr/local/sarg

    相信吗？这样就安装完毕了！很快速吧！接下来你要做的就是设定啰！设定之前请先注意您的相关资料，以我为例，我的相关资料为：

    • 登录档使用 /usr/local/squid/var/logs/access.log.0 这一个经过 rotation 的档案；
    • 计算的暂存档放置在 /tmp 底下；
    • 我的 SARG 输出的首页放置在 /var/www/html/sarg 这个‘目录’之中；
    • 我想要让我的网页以 big5 的字元编码格式输出！

    这个时候我只要修改一个档案，也就是 /usr/local/sarg/sarg.conf 即可，内容有点像这样：

    [root@test root]# mkdir /var/www/html/sarg
    [root@test root]# vi /usr/local/sarg/sarg.conf
    # 这个档案是 sarg 的设定档，里面已经将整个设定参数讲的很清楚了，
    # 你可以依照你的情况来调整这个档案的参数，无论如何，这个档案里面
    # 应该至少要有底下这几个资料，其他的请自行使用喔！
    language Taiwan_big5
    access_log /usr/local/squid/var/logs/access.log.0
    title "Squid 使用状态报告"
    temporary_dir /tmp
    output_dir /var/www/html/sarg
    overwrite_report no
    mail_utility /bin/mail
    topsites_num 100
    exclude_codes /usr/local/sarg/exclude_codes
    max_elapsed 28800000
    charset big5

    [root@test root]# /usr/local/sarg/bin/sarg
    SARG: 制作报告完成于 /var/www/html/sarg/2003Apr10-2003Apr11

    试跑一下，嘿嘿！已经成功的输出资料啰！这个时候，请在您的浏览器上面输入 http://your.domain.or.IP/sarg 即可看到刚刚跑出来的资料了！很棒吧！好了，我总不能常常这样手动的跑分析资料吧？OK！那么怎么将这个动作放到 crontab 当中呢？！呵呵！我们底下写了一支 script 来同时跑 pwebstats 及 SARG 这两个玩意儿～这支 script 是长这样的：

    1. 建立这支程式： 我将他取名为 /usr/local/squid/etc/squid.logrotate
    [root@test root]# vi /usr/local/squid/etc/squid.logrotate
    #!/bin/bash
    # 这支程式是要写来做为 squid 的 log files analysis 之用的！
    # 执行的方法为 crontab 啰！
    # vi /etc/crontab 加入底下这一行：
    # 59 23 * * * root /usr/local/squid/etc/squid.logrotate

    # 1. parameters settings
    PATH=/sbin:/bin:/usr/sbin:/usr/bin

    # 2. stoping and rotating squid
    sleep 50s
    /usr/local/squid/sbin/squid -k rotate
    /usr/local/squid/sbin/squid -k shutdown

    # 3. pwebstats processing
    /var/www/html/pwebstats/pwebstats -c  \
            /var/www/html/pwebstats/conf/squid-proxy.conf \
            > /dev/null 2>&1

    # 4. sarg processing
    /usr/local/sarg/bin/sarg > /dev/null 2>&1

    # 5. starting squid
    sleep 11s
    su nobody -c "/usr/local/squid/bin/RunCache &" > /dev/null 2>&1

    # 2. 改变档案权限与加入 crontab 排程当中！
    [root@test root]# chmod 744 /usr/local/squid/etc/squid.logrotate
    [root@test root]# vi /etc/crontab
    加入这一行：
    59 23 * * * root /usr/local/squid/etc/squid.logrotate

    这一支程式有什么特点呢？由于我是在 23:59 开始执行，而且执行时期先等待 (sleep) 50 秒钟，且工作完毕后再等 10 秒钟，也就是说，我的 squid 的 log 档案一定会是以天为单位来分隔，所以我们所看到的资料就会‘一”天一天’的显示，而不会跨了不同的两天了！我是比较喜欢这样啦！但是每个人的观点不同，您可以自由调配喔！

    防火墙的规划

    事实上， Proxy 本身就已经可以做为一个防火墙啦！为何还需要针对 Proxy 来进行防火墙的规划？话是这样没错啦！但是我们的 Proxy 是开放 3128 与 3130 这两个 port 啊！您总不能这两个 port 没有开放吧！所以啰，要让您的 Proxy 可以对外面开始服务，就需要启用 3128 这个标准的 Proxy port 啰！所以需要在您的防火墙 scripts 当中加入这一行：

      /sbin/iptables -A INPUT -p TCP -i eth0  --dport 3128:3130 -j ACCEPT

    一般来说，这样就可以正常的启动 Proxy 的服务了！那么至于 Proxy 本身提供的防火墙内容呢？呵呵！就利用 acl 配合 http_access 就能够管制使用者的使用空间了！真是相当的具有弹性啊！ ^_^

    NAT 与 Proxy 透过 transparent proxy 设定加快网路传输

    让我们现在来想像一个连线状态，就是你有一整组内部网路，而这个内部网路都是透过 NAT 主机连线出去的。那么我们谈过，就是在一个内部网域很大的情况下，使用 Proxy 是一个很不错的选择，因为至少他可以减轻频宽的负荷啊！OK！那么我们就架设 Proxy 好了，不过，遗憾的是，架设 Proxy 的时候，也要使用者在浏览器上面设定了你架设好的浏览器才有用啊！否则那部 Proxy 没有人使用的话，架了也是白搭！好了，那么有没有办法在‘使用者不需要在浏览器上面进行任何设定，就可以实现以 Proxy 帮助使用者捉取 WWW 资料 ’呢？当然有啦！那就是 Transparent Proxy 啦！也有人翻译成‘通透式代理伺服器’，为什么这么翻译我也不晓得？？不过，他的原理是这样的：

    • 当使用者经过 NAT 伺服器来连线进入 Internet 时，假如使用的 Internet 协定为 80 (也就是 WWW) ，那么就将这个要求交给 Proxy 来工作，以达到代理伺服器的功能。

    呵呵！也就是说，当使用者是经过 NAT 主机连线出去时，只要让 NAT 主机发现‘咦！你是要去捉 WWW 的资料对吧！好！那么这个动作由 Proxy 主机帮你搞定！’如此一来，使用者根本就不需要在浏览器上面设定 Proxy 的相关资料，因为这个动作是‘由 NAT 主机自己决定的’，所以只要在 NAT 主机上面设定妥当即可，使用者不必设定任何资料呢！呵呵！真是不错！那么要怎么进行呢？只要两个步骤即可：

    1. 设定 Proxy 主机：

      2. 设定 proxy 主机当然就是要又修改 squid.conf 啰！而这个设定相当的简单喔！只要几行就可以搞定：

      [root@test root]# vi /usr/local/squid/etc/squid.conf
      # 这里请填入你的 Proxy 主机名称 与 port ！
      httpd_accel_host vbird.adsldns.org
      # 因为我们是要进行 WWW 的资料快取，所以 port 当然就是 80 啰！
      httpd_accel_port 80
      # 这个很重要！因为设定 httpd_accel_host 之后， cache 的设定会自动被终止，
      # 必须要加上这个设定为 on 之后，才能提供 cache 的功能！
      httpd_accel_with_proxy on
      httpd_accel_uses_host_header on

      [root@test root]# /usr/local/squid/sbin/squid -k reconfigure

      总共就是这四行啦！这样就设定好一个 squid 的 transparent proxy 的功能啰！

    2. 设定 NAT 主机的 port map ：

      3. 再来让我们到 NAT 主机上面看看先，因为需要将 80 这个 port 交给 Proxy 的 3128 来帮忙协助，所以你的防火墙 script 必须要加入这一段才行：

      iptables -t nat -A PREROUTING -i eth0 -p tcp -s 192.168.0.0/24 \
      --dport 80 -j REDIRECT --to-ports 3128

      注意一下，那个 eth0 是‘你的 NAT 对内的网路卡装置代号’，至于 192.168.0.0/24 则是你的内部网域，请依照你的主机实际状态来设定喔！

    完全不需要怀疑！这样一来，您的 client 端完全不需要进行任何的设定，立刻就可以使用 Proxy 的好处啰！很不错吧！呵呵！

    squid 的注意事项

    使用代理伺服器后，浏览国外的网页应该是可以变快的！但是，你要小心几件事：

    1. 若 squid 内设定的使用空间满了，则 squid 将不会运作！
    2. 若 squid 的纪录档太大了，则工作效率会变慢！

    由于我们已经安装的 pwebstats 了，并且已经设定好了 squid -k rotate 的工作，所以第二个问题并不严重，严重的可能会是第一个问题！所以有可能我们会自行手动的删除 Proxy 的快取目录，如何删除呢？虽然上面已经提过了一些注意事项，这里我们再次的说明吧！

    1. 停止 squid
    [root@test root]# kill -9 `cat /usr/local/squid/var/logs/squid.pid`
    (可能会重复做 5 次左右才会完全砍掉！)

    2. 删除暂存目录 (这个目录请依您的系统而定！)
    [root@test root]# rm -rf /usr/local/squid/var/cache1
    [root@test root]# mkdir /usr/local/squid/var/cache1

    3. 重建快取目录并重新启动
    [root@test root]# /usr/local/squid/sbin/squid -z
    [root@test root]# su nobody -c "/usr/local/squid/bin/RunCache &"

    其他的建议：

    1. 关于上层代理伺服器：用 cache_peer 设定上层代理伺服器的数目不要太多，只要 2-5 个之间就好了，而且上层代理伺服器一定要找距离你最近，并且具有较大频宽的主机，如果是在台南，那 proxy.ncku.edu.tw 就是不错的主机，或者向您的 ISP 询问喔；

      2.
    2. 关于暂存目录的设定：以 cache_dir ufs 设定的目录，最好是单独割出来的约 1-2 GB 的硬碟槽，以我为例，我将另外一台主机的 30GB 的硬碟割两槽给 proxy 用，而每一槽只有 2GB ，分别命名为 proxy1 与 proxy2 ，则可以写成
        3.
        cache_dir ufs /proxy1 2000 16 256
        cache_dir ufs /proxy2 2000 16 256

      由于分成两槽来存取，所以整体效率上会比较好，但这是针对一般比较大型的代理伺服器的设定了，我们这个小主机就不用如此设定(但是效率真的有差哩！)。

    3. 善用 acl, always_direct, never_direct：就如同上面提到的，因为你的目的不同，所以会使用到不同的 proxy 作为你的上层代理伺服器，如果你发现你的上层代理伺服器无法针对你常上的网站来求取资料时，就将那个网站加入你的 always_direct 吧！另外，也可以使用 cache_peer_access 来处理喔！

      4.
    4. 在 ./configure 的时候增加 --enable-async-io=80 这一个指令：基本上，增加这个指令之后，将可以使您的磁碟多一个 type ，亦即是 aufs ，这个 type 的速度较快！
重点回顾
  • 代理伺服器 ( Proxy ) 最大的功能是在代理使用者向 Internet 要求 Web page 的资料，同时达成 Web pages 的快取记录 (Cache) ，以达到假性的频宽节省目的；此外，还可以额外的达成防火墙的功能；
  • 目前 Unix Like 的机器中，做为 proxy 功能的伺服器软体几乎都是使用 squid ，而 squid 仅需要设定 squid.conf 这个设定档即可使用；
  • 设定 Proxy 时，如果能以频宽更大的上层 Proxy 来帮助，将有助于 Client 端浏览速度的提升；
  • 以防火墙的功能来说， Proxy 使用应用层的方式来达成防火墙功能，至于 iptables 则是更为底层的 TCP/IP 分析的方式；
  • Proxy 对于硬体的要求较高，尤其是硬碟的 partition 与记忆体，一般来说，一个 cache 目录最好就是一个 partition ，而一个 cache partition 最好容量在 2-4 GB 之间即可；
  • transparent proxy 的功能就是可以让 client 端不需要设定浏览器的 proxy 功能，即可进行 proxy 的工作；
参考资源
  • 优客笔记本：http://turtle.ee.ncku.edu.tw/~tung/proxy/
  • 台北市教育网路中心：http://www.tp.edu.tw/document/squid/index.files/frame.htm
  • squid 官方网站：http://www.squid-cache.org/
  • squid 说明文件计划：http://squid-docs.sourceforge.net/
  • 中山大学资讯工程所：http://www.cc.nsysu.edu.tw/~lmj/Squid.files/frame.htm
  • 鹭江国小：http://proxy.lcps.tpc.edu.tw/
  • fly 官方网站：http://martin.gleeson.com/fly/index.html
  • pwebstats 官方网站：http://martin.gleeson.com/pwebstats/index.html
本章习题练习 ( 要看答案请将滑鼠移动到‘答：’底下的空白处，按下左键圈选空白处即可察看 )
  • 请说明为何 Proxy 可以提升网路的 WWW 浏览速度？
  • 万一 squid 发生了问题，请问我该如何找出问题点？
  • 请说明 Proxy 伺服器的功能为何？
  • 试说明为何 Proxy 伺服器可以提升网域之内的网路安全性？

    • 前往参考用解答
简易 Proxy Server 架设
2001/??/??：第一次完成日期，其实已经忘记了～
2001/11/09：加入增加 Proxy 效能的方法，就是使用多颗硬碟做成的资料储存方式！
2003/04/04：完成大幅度的改写动作！加入了完整的 Proxy 说明，与 pwebstats 的架设！
2003/04/11：完成了另一个末端分析的强大软体 SARG 分析套件！
2003/09/16：微幅调校一下版面！
2004/11/12：修订 transparent proxy 的设定问题， httpd_accel_with_proxy on


鸟哥的 Linux 私房菜 -- APT/YUM server

为取得较佳浏览结果，请爱用 firefox 浏览本网页

简易 APT/YUM 伺服器设定
最近更新日期：2004/06/23

用不惯 Tarball 安装套件却又担心 RPM 的属性相依问题吗？如果有一种套件管理工具可以克服 RPM 属性相依的方法该有多好！有没有这种工具？呵呵！有的，那就是 APT 与 YUM 这两个伺服器了。APT (Advanced Package Tool) 是由 debian 这个 distribution 所发展的一个套件管理工具，其目的在克服 RPM 套件的属性相依问题，让使用者可以透过 APT 的分析直接安装/升级/删除相关联的套件喔。另一个很好用的就是 YUM (Yellow dog Updater, Modified) 这个咚咚，他是由 Duke University 所发起的计划，目的则与 APT 相似，都是在克服 RPM 的属性相依问题，方便使用者进行套件的安装、升级等等工作。由于 APT/YUM 这一类的伺服器在‘系统升级/管理’上面的功能发挥的很好，所以目前很多的 distributions 都把这两个伺服器作为预设的服务喔。在这个章节当中，我们要介绍如何在您的 Linux 伺服器上面建置一个 ATP 或 YUM 伺服器，并且提供更新的 RPM 套件给 Client 端来使用！

前言：
    ：什么是 APT/YUM 呢？他们如何运作
    ：是否需要架设 APT/YUM 伺服器
    ：架设之前，您所需要启用的服务
APT 伺服器：
    ：APT 伺服器利用的机制
    ：安装 APT 软体
    ：APT 伺服器的套件结构
    ：APT 伺服器设定 ( 以 HTTP 提供服务为例 )
    ：Client 端的设定
YUM 伺服器：
    ：YUM 伺服器利用的机制
    ：安装 yum 软体
    ：yum 伺服器的套件结构
    ：yum 伺服器设定
特殊案例：
    ：建立自己的更新套件
    ：如何取得网路上的更新元件
主机的规划技巧与建议：
参考资源：
前言：
    如果您曾经自行安装过某些套件的话，那么您或许会觉得：‘RPM 是比 Tarball 好安装没有错啦，但是每次为了解决套件之间的属性相依问题，真的是很烦，尤其是 RPM 档案在不同的作业系统版本之间也无法相容！’是的！没错！为了要解决这个套件之间的属性相依问题，又要保留 RPM 套件的易安装与查询的特性，所以就有一些套件管理方法出来啦！比较有名的就是 APT 与 YUM 这两个咚咚啦。(注：当然，Mandrake 的 urpmi 也是很棒的工具。)

    什么是 APT/YUM 呢？他们如何运作？

      众所皆知的， RPM 是目前 Linux 世界里面用的最多的套件安装方式。不过，由于 RPM 所管理的套件在安装的时候必须要考虑到不同套件之间的相依性，这在系统管理员处理系统的升级/更新上面是很讨厌的！为了克服这个问题，所以有 APT/YUM 之类的计划出来。APT ( Advanced Package Tool ) 最早是由 debian 这个 distribution 所发展出来的，而 YUM ( Yellow dog Updater, Modified ) 则是由 Duke University 所发起的计划之一，这两者的目的都是‘为了要解决安装 RPM 套件时的属性相依问题！’，而不是额外再建立一个套件安装模式喔。首先，我们谈一谈为什么 RPM 套件会有属性相依的问题？又，什么是属性相依的问题啊？

      • 属性相依的问题大多来自于函式库的引用，举例来说，我们前面 SSH 与 Telnet 伺服器章节中提到的 SSH 伺服器需要使用到 SSL 这个套件的加密机制，所以自然就需要 SSL 的函式库，这个时候，如果您没有安装 SSL 的话，那么 SSH 就不会让您安装了！这就是属性相依的问题啦。也就是说，当我们要安装 A 套件，结果 RPM 套件管理员告诉你还需要 B 套件，而安装 B 套件时，却又发现还缺少 C 套件～真是环环相扣啊！讨厌死了～

      • 要知道某个套件的最低要求是哪些套件时，可以使用 rpm -qR packagename ，至于某个套件提供哪些档案则可以使用 rpm -q --provides packagename 。这些资讯都纪录在 RPM 套件里面。

      如果对于 RPM 还有疑问，请参考基础学习篇的 RPM 与 SRPM 那个章节啰。好了，既然每一个 RPM 套件的标头 (header)里面都会纪录该套件的属性相依关系，那么如果我们可以将该标头的内容纪录下来并且进行分析，不就可以得知每个套件在安装之前需要额外安装哪些基础套件吗？也就是说，我们在伺服器上面先以分析工具将所有的 RPM 档案进行分析，然后将该分析纪录下来，只要在进行安装或升级时先查询该纪录的档案，就可以知道所有相关联的套件档案！没错！是这样。他的整个运作流程有点像这样：

      伺服器端：
      1. 首先，在 APT/YUM 伺服器上面放置了所有的 RPM 套件(这包括来自原版光碟与供应商发行的升级套件)；
      2. 然后以相关的功能去分析各个 RPM 档案的相依性，这些纪录可以解决所谓的属性相依问题，然后将这些资料记录成档案存放在伺服器的某特定目录内；

      客户端：
      1. Client 端如果需要安装/升级/删除某个程式时，会先下载伺服器上面记载的属性相依档案(利用的协定则是 WWW 或者是 FTP)；
      2. 经由比对伺服器端传来的纪录资料进行分析，然后取得所有相关的套件，一次全部下载下来进行升级安装。

      如此一来则克服了属性相依的问题啰！是的！就这么简单啊！整个图示如下：

图一、APT/YUM 伺服器的架构。
      您的 APT/YUM 伺服器上面可以拥有多个版本的 Linux distributions 的 RPM 套件，并且需要提供 WWW/FTP 等服务，而 Client 端则是藉由主机的 WWW/FTP 等协定来进行 RPM 档案的取得喔。

    是否需要架设 APT/YUM 伺服器

      APT/YUM 的功能也只是在管理 RPM 套件而已，只是他比单纯的 RPM 指令要好的地方在于他克服了属性相依的问题，所以用户端可以很方便的进行安装/升级与移除的动作。那么是否意味着我就得要架设 APT 或 YUM 伺服器呢？

      这可不一定呐。如果您只有一部主机，而且上面的网路服务很少，并且也没有提供什么重要的服务，那么架设 APT/YUM 伺服器就没有这么需要了。为什么呢？因为很少用到 APT 的机制啊，而且直接找网路上面有的 APT/YUM 伺服器即可，无须架设啦！要注意的是，架设 APT/YUM 伺服器时，您必须要有够用的硬碟空间、够用的频宽以及提供至少 WWW 或者是 FTP 的网路服务呢！这对只有一部主机的您来说，真的不必要费心思去管理的啦！但如果您的网路环境是如下的模样，可能就得要架设一部 APT/YUM 伺服器比较好啰！

      • 您的网路里面有相当多的同样版本的 Linux distribution 系统；
      • 您的区域网路对外频宽不高，且内部有多部 Linux 主机系统；
      • 您的 Linux distributions 在国内并没有相对应的 APT/YUM 伺服器提供服务，而对国外连线的频宽又很低时；

      也就是说，如果您拥有多部 Linux 主机，或者是您连接到 APT/YUM 伺服器的频宽太低时，就可以考虑架设 APT/YUM 伺服器了。以上面图一来说，如果您的连外网路频宽太低，那么架设一部 APT/YUM 伺服器后，所有的 Linux 是连接到该部 APT/YUM 伺服器进行升级/安装，速度当然比连外要快很多啦！

      所以说，如果您是上层的系统管理员(例如学校的网管老师或者县网、区网的网管人员)，为了您的整个网域的 Linux 主机来打算，那么架设 APT/YUM 是蛮需要的，因为真的可以节省很多连外的频宽；相反的，如果您是一般用户，拥有的了不起就是两三部 Linux 主机而已，那么似乎没有架设 APT 主机的必要性呢！因为由上面的说明来看，架设 APT 主机所需要的‘硬碟空间’可是不能省的，对于一般的用户来说，架设 APT 主机实在是没有什么必要性说～

    架设之前，您所需要启用的服务

      就如同前面的说明，您要架设 APT/YUM 时，请先记得在您的 APT/YUM 主机上面启用 WWW 或者是 FTP 服务了才行！因为 APT/YUM 是利用 WWW/FTP 来进行 RPM 档案在 Server 与 Client 之间的传送的！此外，您的 APT/YUM 主机上面最好将最靠近您主机的 Linux 版本更新套件的网站设定为映射站台 ( mirror )，如此一来，您就可以让系统自动的更新您的 Linux distributions 所需要的更新档案，而不必手动来更新呢！

      此外，由于完整的 APT/YUM 伺服器包含了原本的 Linux distributions 的原版光碟内容，所以需要的硬碟空间是很高的！至少需要 3~5 GB 以上，最好能够有 10GB 以上的硬碟空间。

      好了，底下我们就来开始安装与设定 APT/YUM 伺服器吧！
APT 伺服器：
    底下开始来谈一谈 APT 伺服器吧！

    APT 伺服器利用的机制

      就如同前言说明的， APT 主机可以将已经存在的 RPM 档案进行分析，并且将各个套件的相关系记录下来，以便让使用者依据这个套件的相关性纪录档案来更新与安装他们的 Linux 系统。那么这些档案放在哪里呢？其实因为这些档案被需要让 Client 端可以下载，而且 APT 并不是额外再启用其他的 port ，而是透过 WWW 或者是 FTP 的方式来让 Client 端下载的，所以 APT 的 RPM 档案当然就需要放在可以让 WWW 或者让 FTP 来存取的目录啰！

      在很多 Linux distributions 的 WWW 预设主页是放在 /var/www/html 这个目录下的( 例如 Red Hat 9, Fedora Core I/II, Mandrake 等等 )，所以，除非您想要自行架设虚拟主机，或者是利用连结档的方式来让 RPM 档案放置的目录可以让 WWW 读取，否则您都应该要将 APT 管理的 RPM 档案放置在 /var/www/html 底下。假设我有两个 Linux 的版本要这部 APT 主机管理时，一版是 Mandrake 9.1 一版是 Red Hat 9 ，那么我可以这样编排我的 RPM 档案放置的目录：

      表一、APT 主机相关 RPM 档案放置的目录示意表
      /var/www/html/apt/redhat9
                              |--RPMS.os
                              |--RPMS.updates
                              |--SRPMS.os (非必备目录)
                              |--SRPMS.updates (非必备目录)
                              `--base
                                    |--pkglist.os.bz2
                                    |--pkglist.updates.bz2
                                    |--release
                                    |--release.os
                                    `--release.updates
      /var/www/html/apt/mdk9.1
                            |--RPMS.os
                            |--RPMS.updates
                            |--SRPMS.os (非必备目录)
                            |--SRPMS.updates (非必备目录)
                            `--base
                                  |--pkglist.os.bz2
                                  |--pkglist.updates.bz2
                                  |--release
                                  |--release.os
                                  `--release.updates

      如上所示，我独立出一个名为 apt 的目录来管理我的 APT 档案，另外，因为有两个版本，所以我将 apt 又分为两个目录，因为两个目录的格式一样，所以我以 Red Hat 9 那个 /var/www/html/apt/redhat9 目录来介绍。里面至少会有三个目录才对，分别是 RPMS.os, RPMS.updates, base 这三个目录，其中：

      • RPMS.os 的内容为 Red Hat 9 的原本光碟中的 RPM 档案(i386)；
      • RPMS.updates 的内容为 Red Hat 公司针对 Red Hat 9 这一版所释出的修补套件；
      • base 这个目录里面的资料则是由 APT 伺服器所自动产生的，前面我们提到的 APT 会去分析 RPM 档案而将档案资讯记录下来，记录下来的咚咚就是放置在这个目录下的啦！

      您还会看到其实还有 SRPMS.os 以及 SRPMS.updates 等目录，呵呵！那个就是 Source RPM (SRPM) 档案放置的目录了。因为我们直接可以透过 Binary 来升级，所以我预设不放 SRPM 在我的 APT 伺服器里面啰！

      OK！所以我们需要怎么来架设我们的 APT 以及利用 APT 来升级呢？

      1. 先将所有来自 Linux 原版光碟的 RPM 档案复制到 /full/path/RPMS.os 档案中；
      2. 再将来自原 Linux 版本公司释出的 RPM 修补套件由 Internet 下载到 /full/path/RPMS.updates 当中；
      3. 利用 APT 的功能进行 /full/path/base 这个目录里面资讯的更新；
      4. 到 Client 端上面，以 APT 的功能更新 Client 自己的套件资讯，使与 APT 主机的 /full/path/base 这个目录里面的套件记录资讯同步化；
      5. 到 Client 端上面，可以利用 APT 的功能来更新或者是安装套件了！当然，所使用来下载 RPM 档案的协定当然是 WWW 或是 FTP 啰！而且， Client 端分析的是自己的 RPM 资讯喔，所以每次进行更新之前，应该将 Client 端的 RPM 资讯与 APT Server 端来同步化才行！否则 Server 新增的档案在 Client 端是无法取得资讯的喔！

      所以啰，其实在 APT 主机设定上面最重要的步骤应该是在于主机硬碟的规划、档案的复制与 updates 档案的随时自动更新(可以利用映射站台的功能)，以及 /full/path/base 目录下的资讯更新等等步骤！只要这边没有问题，其他的流程就简单咯！

    安装 APT 软体

      因为 APT 这套件是挺大的，而且也不容易使用 Tarball 来安装，所以比较建议使用 RPM 的方式直接安装，您可以到底下的网站搜寻一下属于您自己的 Linux distributions 的 APT 版本喔：

      • http://rpmfind.net/linux/rpm2html/search.php?query=apt
      • http://apt.freshrpms.net/

      同时我也将一些常见的版本捉下来了，您也可以在这里下载：

      RPM 的部分：
      • Red Hat 9：http://linux.vbird.org/download/linux_server/apt/rh9/apt-0.5.5cnc6-fr1.i386.rpm
      • Red Hat 8：http://linux.vbird.org/download/linux_server/apt/rh8/apt-0.5.5cnc6-fr0.rh80.1.i386.rpm
      • Red Hat 7.3：http://linux.vbird.org/download/linux_server/apt/rh7.3/apt-0.5.5cnc5-fr0.rh73.2.i386.rpm
      • Red Hat 7.1：http://linux.vbird.org/download/linux_server/apt/rh7.1/apt-0.5.4cnc9-fr0.1.rh71.i386.rpm
      • Mandrake 9.1：http://linux.vbird.org/download/linux_server/apt/mdk9.1/apt-0.5.5cnc3-1mdk.i586.rpm
      • Mandrake 9.0：http://linux.vbird.org/download/linux_server/apt/mdk9.0/apt-0.3.19cnc55-2mdk.i586.rpm
      • Mandrake 9.0：http://linux.vbird.org/download/linux_server/apt/mdk9.0/apt-devel-0.3.19cnc55-2mdk.i586.rpm

      SRPM 的部分(可以使用 Red Hat 9 提供的 SRPM 来进行重新编译)：
      • Red Hat 9：http://linux.vbird.org/download/linux_server/apt/rh9/apt-0.5.5cnc6-fr1.src.rpm

      直接以‘ rpm -ivh package.name ’就能安装了！当然，需要选择适合您的版本呐！如果找不到适合您的版本，那么尝试以上面提供的 SRPM 来重新编译试看看能不能成功吧！‘rpm --rebuild SRPM ’或新版的‘rpmbuild --rebuild SRPM’(注：SRPM 表示您由上面下载的 apt-0.5.5cnc6-fr1.src.rpm 这个档案的档名)。

    APT 伺服器的套件结构

      APT 伺服器里面有很多的档案，说明如下：

    • 设定档案：

      •
      • /etc/apt/apt.conf：这个并不是 APT Server 的记录档，而是当我们在指令列模式下达 APT 的指令时 (如底下执行档部分会介绍的 apt-get )，该指令的环境参数。一般来说，使用预设值就可以了！不需要更动他。这个档案的内容当中：

        •
        注解符号为两个斜线( slash )：‘//’
        主要至少分为三大群组，分别为 APT(环境参数), Acquire(下载相关参数) 与 RPM(RPM相关参数)，而每个群组之内又分别具有多个参数，每个参数的设定值最后以分号‘;’隔开，例如下面的范例：
        [root@test root]# vi /etc/apt/apt.conf
        APT　　　　//第一个大群组
        {
          // Options for apt-get
          Get　　　//第一个大群组里面的第一个参数
          {
            Download-Only "false";  //第一个参数的项目与该项目之设定值
            Show-Upgraded "true";   //第二个参数的项目与该项目之设定值
          };
        };
        除了上面的格式外，也可以利用底下的格式来进行设定：
        主群组::参数::项目 "设定值";
        例如上面的范例中，可以将第一个设定值写成：
        APT::Get::Download-Only "false";

        另外，如果您想要使用 Proxy 来加快您的网路传输时，可以修改里面的内容，因为 Proxy 是在 Acquire 里面的 Http 参数，所以您可以使用如下的设定值(注：我以成大的 proxy.ncku.edu.tw:3128 为例)：

        1. 利用原本的设定技巧：
        [root@test root]# vi /etc/apt/apt.conf
        // 找到底下的参数
        Acquire
        {
          // 底下加入这些资料：
          Http
          {
            Proxy "http://proxy.ncku.edu.tw:3128";
          };
          Retries "0";
        };

        2. 或者您也可以改用底下的参数设定：
        [root@test root]# vi /etc/apt/apt.conf
        //在最后一行加入，注意，不要被括号 {} 括住了！
        Acquire::Http::Proxy "http://proxy.ncku.edu.tw:3128";

        上面两种方法都是行的通的啦！

      • /etc/apt/sources.list：这个档案就真的重要了！此档案的作用在于‘选择适合您的 APT 主机’啰！所以这个档案与 Client 的关系比较大。内容有点像这样：

        •
        [root@test root]# vi /etc/apt/sources.list
        # Red Hat Linux 9
        rpm http://ayo.freshrpms.net redhat/9/i386 os updates freshrpms
        #rpm-src http://ayo.freshrpms.net redhat/9/i386 os updates freshrpms

        # 里面料的格式为：
        # rpm <APT伺服器位址> <相对于伺服器的路径> <目录一> <目录二> <目录三> ...
        # 以上面的例子来说，事实上 RPM 放置的目录在：
        # http://ayo.freshrpms.net/redhat/9/i386/RPMS.os
        # http://ayo.freshrpms.net/redhat/9/i386/RPMS.updates
        # http://ayo.freshrpms.net/redhat/9/i386/RPMS.freshrpms
        # 而至于 rpm-src 则是放置 SRPM 档案的伺服器与目录喔！

        如果您是由鸟哥面推荐的 RPM 安装您的 APT 时，这里可以保持预设的路径，不过，如果您知道台湾地区有更快速的映射站台，这里就可以修改成您所找到的 APT 伺服器啰。

    • 执行档案：

      •
      • apt-get：这个是最主要的执行档了！大部分的时候都是给 Client 端用的，语法如下：

        •
        [root@test root]# apt-get <options> <更新项目> <套件名称>
        参数说明：
        options：关于参数有底下几个较常见的：
            -q 不要显示 apt-get 运作时的输出讯息，安静一点比较好吗？！ ^_^
            -y 如果 apt-get 在工作过程中需要使用者回应，这个参数可以直接回答 yes
        更新项目：更新的动作有底下几个：
            update：这个动作很重要，就是我们上面有提到的，Client 端要更新与 APT Server
                    套件相关性档案的清单对应表，就得要使用这个项目了！基本上，
                    每次进行 apt-get 来下载 APT Server 的档案前，最好都先 apt-get update
            install：安装某个套件，后面接套件名称
            dist-upgrade：自动升级我们系统上面已经安装的所有 RPM 套件喔
            clean：将下载自 APT 主机的的 RPM 档案删除哩！
            remove：移除已经安装在我们系统的某个套件！
        范例：
        [root@test root]# apt-get update　　　　 　 # 将 RPM 档案相关性清单更新！
        [root@test root]# apt-get install tcpdump # 安装 tcpdump 这个套件
        [root@test root]# apt-get -y dist-upgrade  # 升级我们系统上面的所有 RPM 套件
        [root@test root]# apt-get clean

        # 至于每日更新的话，可以写入 /etc/crontab 喔
        [root@test root]# vi /etc/crontab
        40 5 * * * root apt-get update; apt-get -y dist-upgrade ; apt-get clean

      • genbasedir：我们在前言的部分一再地提到 APT Server 会分析已经存在的 RPM 档案的属性相关性，并且会将属性的结果放置在 /full/path/base 那个目录内～呵呵！其实该动作很简单的，就是使用这个 genbasedir 即可！

    • 相关目录：

      •
      • /var/cache/apt：一些记录档案的地方，例如当使用 apt-get update 之后，这个目录下的 RPM 档案相关系记录档就会更新了！

        • /var/state/apt：这个则是 apt 在工作的时候，一些状态的纪录档案放置的地方！

    APT 伺服器设定 ( 以 HTTP 提供服务为例 )

      在底下的例子当中，我们主要是设定以 HTTP 为 APT Server 的服务提供者，因为是利用预设的 WWW 系统版本，所以首页在 /var/www/html。鸟哥在 /var/www/html 底下建立一个名为 apt 的目录，并在底下提供 Red Hat 9 与 Mandrake 9.1 的 APT 套件服务功能，注意，我预设仅提供 RPM 档案，并不提供 SRPM 的档案喔！相关的目录如前面提到的表一所示(注：当然 SRPM.os... 等档案就不必建立了！)。好了，那么就来给他安装 APT Server 相关的流程吧！

    1. 建置所需的目录与复制所需的档案：

      2. 如上面提到的 表一 所示为我们所需要的目录，而在每个 RPMS.os 为系统原本的光碟里面的档案，而 RPMS.updates 则为套件升级版本。我这里主要以中山大学的 FTP 网站作为主要的 update 资料来源，使用的是 ncftp 的下载方法：
      1. 建置所需目录：
      [root@test root]# mkdir -p /var/www/html/apt/redhat9/RPMS.os
      [root@test root]# mkdir -p /var/www/html/apt/redhat9/RPMS.updates
      [root@test root]# mkdir -p /var/www/html/apt/mdk9.1/RPMS.os
      [root@test root]# mkdir -p /var/www/html/apt/mdk9.1/RPMS.updates

      2. 利用原版 CD 来复制所需的 .os 的 RPM 档案
      [root@test root]# cd /var/www/html/apt/redhat9/RPMS.os
      # 先放入 Red Hat 9 的原版光碟片
      [root@test RPMS.os]# mount /dev/cdrom
      [root@test RPMS.os]# cp /mnt/cdrom/RedHat/RPMS/* .
      [root@test RPMS.os]# umount /dev/cdrom
      # 重复上面的步骤，将三片 i386 的 RPM 档案都复制进去！
      # 至于 Mandrake 的原版光碟复制方法也是相同的步骤！

      3. 利用 ftp.nsysu.edu.tw 来下载所需要的 RPM 档案
      [root@test RPMS.os]# cd /var/www/html/apt/redhat9/RPMS.updates
      [root@test RPMS.updates]# ncftp  \
      > ftp://ftp.nsysu.edu.tw/Linux/RedHat/linux/updates/9/en/os/i386/
      NcFTP 3.0.2 (October 19, 2000) by Mike Gleason (ncftp@ncftp.com).
      Connecting to 140.117.11.7...
      ====================================================================
       欢迎光临【国立中山大学】档案伺服器 : FTP.NSYSU.edu.tw
         Welcome to National Sun Yat-Sen University FTP Server.
       右列网址提供本站档案搜寻引擎 http://ftp.nsysu.edu.tw/
         File Search Engine on the URL http://ftp.nsysu.edu.tw/
       目前 FTP 部份有 313 人正在线上，最高限制 5000 人.
         There are currently 313 users out of 5000 possible.
      ====================================================================
      Only anonymous FTP !!!! Please press [ENTER] key.
      Logging in...
       ========================================================================
       !!!! Important Function !!!! (重要功能介绍)
       o 'cd key*word' or 'cd prefix*' or 'cd *suffix' provided (case-insentive).
         (例：cd freebsd 可以打成 cd fr 或 cd *sd 或 cd f*e*d 都通用，大小写都行)
       ========================================================================
       请多多利用 <A HREF="http://ftp.nsysu.edu.tw">http://ftp.nsysu.edu.tw</A>
       可以使用方便的档案搜寻引擎喔!!!!!!!!!!!!!!!!!
       ========================================================================
       ADM.Email: ftpadm@cc.nsysu.edu.tw
      Anonymous user (163.28.112.1) logged in
      Logged in to ftp.nsysu.edu.tw.
      Current remote directory is /pub/Linux/RedHat/linux/updates/9/en/os/i386.
      ncftp ...x/updates/9/en/os/i386 > mget *
      .....
      利用上面的步骤就可以将 Red Hat 9 的两个目录下的 RPM 档案放置完毕！至于 Mandrake 9.1 的方法与 Red Hat 9 是完全相同的！请您依照上面的方法来自行安装 Mandrake 到您的系统当中喔！另外，除了中山大学提供的 FTP 网站之外， 您也可以使用淡江大学或者是其他的大专院校提供的 FTP 服务喔！
      淡江大学的 FTP 网站： ftp://ftp.tku.edu.tw/OS/Linux
      中山大学的 FTP 网站： ftp://linux.cdpa.nsysu.edu.tw

    2. 建立 RPM 所在档案的相关资料：

      3. 建立好了档案之后，再来则是需要进行这些 RPM 档案的相关系分析了，分析方法很简单，只要一个动作即可：
      [root@test root]# genbasedir <最上层目录> <相对目录一> <相对目录二> ...
      参数说明：
      最上层目录：以我们的 APT 主机为例，最上层目录有两个，分别就是：
                  /var/www/html/apt/redhat9
                  /var/www/html/apt/mdk9.1
      相对目录一：那就是 RPMS.os 与 RPMS.updates ，但是记得 RPMS 不要写，
                  只要 os 以及 updates 即可！
      范例：
      [root@test root]# genbasedir /var/www/html/apt/redhat9 os updates
      Creating base directory... done
      Components: os updates
      Processing pkglists... os updates done
      Processing srclists... done
      Creating component releases... os updates done
      Creating global release file... done
      Appending MD5Sum... os updates done
      All your base are belong to us!!!
      [root@test root]# genbasedir /var/www/html/apt/mdk9.1 os updates
      # 动作真是给他有点久～耐心等候吧！ ^_^
      进行完上面两个动作后，APT 就会在您的系统上面主动的建立起 /var/www/html/apt/redhat9/base 以及 /var/www/html/apt/mkd9.1/base 这两个目录啰！这也是最重要的目录咯！基本上， APT Server 到这一步骤就已经完全 OK 了！其他的就是 WWW 伺服器的设定啰，因为前面我们已经介绍过 WWW 了，这里不再重复说明说！

    3. 建立 Client 所需要的 sources.list

      4. 我们的 Red Hat 9 所架设的 APT Server 当然也可以让我们自己来升级了！这个时候请您修改 /etc/apt/sources.list 呢！请注意喔！您所选择的 APT Server 需要设定正确才行喔！
      [root@test root]# vi /etc/apt/sources.list
      # 这是我们主机的 Red Hat 9 范例：
      rpm http://192.168.1.2 apt/redhat9 os updates
      # 这是 Mandrake 的范例
      # rpm http://192.168.1.2 apt/mdk9.1 os updates

      [root@test root]# apt-get update
      Get:1 http://192.168.1.2 apt/redhat9 release [543B]
      Fetched 543B in 0s (1359B/s)
      Get:1 http://192.168.1.2 apt/redhat9/os pkglist [420kB]
      Get:2 http://192.168.1.2 apt/redhat9/os release [121B]
      Get:3 http://192.168.1.2 apt/redhat9/updates pkglist [55.1kB]
      Get:4 http://192.168.1.2 apt/redhat9/updates release [126B]
      Fetched 475kB in 8s (57.0kB/s)
      Reading Package Lists... Done
      Building Dependency Tree... Done
      # 这个步骤在测试我们上面的 sources.list 是否正确！
      # 并且可以同时更新我们 Client 端的 RPM 属性档案记录！
      # 要出现上面的讯息才对，如果出现错误讯息，很有可能是 WWW 设定错误！
      这里特别说明的是， apt-get update 的作用在‘取得 APT Server 的各个 RPM 档案的相关性，亦即是 base 目录里面的档案’，取得这些资料后，未来您的 Linux 主机要进行各项安装/升级动作时，就可以直接取用自己的纪录档了。所以，如果主机上面更新了 base 里面的资讯，则您必须要再次的执行 apt-get update 才行，否则主机上面更新的资料您将无法取得。

    4. 定期建立 update RPM 档案的映射资料，并更新 RPM 相关资料

      5. 其实到上一步骤所有 APT 相关的作业应该就已经完成了，不过，要晓得的是， Internet 上面的 update 套件是随时在更新的，所以我们的 APT server 上面的 RPMS.updates 目录也应该要随时更新才对啊！要更新，您可以使用手动的方式来下载，用 ncftp 似乎不错！不过，毕竟不太适合即时更新，这个时候，我们可以利用映射 (mirror) 的方式来进行更新喔！我们以 Red Hat 9 的 update 来进行说明！关于映射的说明请您自行参考 http://mirrordir.sourceforge.net/ ，我们这里仅需要应用而已喔！
      1. 先线上安装 mirror 吧！
      [root@test root]# rpm -ivh \
      > http://mirrordir.sourceforge.net/mirrordir-0.10.49-1.i386.rpm

      2. mirrordir 的语法
      [root@test root]# mirrordir <来源网址> <目标目录>
      [root@test root]# mirrordir -v \
      > ftp://ftp.nsysu.edu.tw/Linux/RedHat/linux/updates/9/en/os/i386/  \
      > /var/www/html/apt/redhat9/RPMS.updates
      # 用 -v 来察看一下 mirrordir 的检查状态，如果以 cron 来进行时，就不需要了！

      3. 定期进行映射并且同时更新 RPM 档案相关性：
      [root@test root]# vi /etc/crontab
      # 加入这一行：
      30 5 * * * root mirrordir ftp://ftp.nsysu.edu.tw/Linux/RedHat/linux/updates/9/en/os/i386/  /var/www/html/apt/redhat9/RPMS.updates && genbasedir /var/www/html/apt/redhat9  os updates
      # 注意喔！上面为连续的一行啊！ ^_^

      如此一来，我们的 APT 主机不但能够自己更新自己与 FTP 映射站的 update 资料，并且同时更新 APT 的 base 目录下的相关性档案喔！而您的 APT Client 就可以随时来更新他的 RPM 套件啰！ ^_^

    Client 端的设定

      无论是 APT Server 或者是 APT Client ，要使用 APT 伺服器的功能，您都必须要安装 APT 软体才行。所以，首先请将您的 Client 依据前面‘安装 APT 伺服器软体’章节进行 apt 的安装；安装完毕之后，最重要的就是修订 /etc/apt/sources.list 这个档案啰！您必须要设定正确的 APT 伺服器才行，如此一来，您就可以运用 APT 的强大功能啦！更多的使用技巧请参考 Linux 网路套件升级 章节。
YUM 伺服器
谈完了 APT 伺服器之后，接下来我们就来谈一谈目前被 Red Hat 及 Fedora 列为预设的 RPM 套件安装/升级机制的 yum 这个伺服器啦。

YUM 伺服器利用的机制
    与 APT 类似的， yum 并没有开发新的网路传输机制，同样仅是利用原本主机就提供的 WWW 或者是 FTP 服务，来让 server/client 进行档案的传输。所以在您 yum 伺服器上的 RPM 档案同样的需要放置在 WWW 或 FTP 服务可以存取的所在目录才行。这里鸟哥同样以 /var/www/html 这个 WWW 的目录作为说明。

    一般来说，我们需要的 RPM 档案就是原本光碟所提供的套件，以及后来厂商提供的升级套件，这两种 RPM 档案我分别将他放置在底下所示的目录内：

    表二、APT 主机相关 RPM 档案放置的目录示意表
    /var/www/html/yum/fedora/core1
                                |--base
                                | 　`--headers
                                `--update
                                    `--headers

    /var/www/html/yum/mandarke/10.0
                                |--base
                                | 　`--headers
                                `--update
                                    `--headers

    如同上表二所示，每一个版本的 Linux 内仅有两个目录，其中 base 是原版光碟的 RPM 档案，至于 update 则是升级的 RPM 档案。比较有趣的地方在于‘经过 yum 分析 RPM 档案后的纪录资料是放置在该目录下的 headers 目录内。’举例来说，我们的 mandrake 10.0 升级用的 RPM 档案是放置在 /var/www/html/yum/mandrake/10.0/update 下，则在该目录下的 RPM 被分析后，每一个 RPM 档案的纪录档则放置在 /var/www/html/yum/mandrake/10.0/update/headers 目录下喔。至于整个 yum 的机制为：

    1. 先将所有来自 Linux 原版光碟的 RPM 档案复制到 /full/path/base 档案中；
    2. 再将来自原 Linux 版本公司释出的 RPM 修补套件由 Internet 下载到 /full/path/update 当中；
    3. 利用 yum 的功能去分析每个目录下的 RPM 档案；
    4. 在 Client 端上面，每次进行 RPM 套件的升级/安装功能时， yum 会自动的读取 headers 内的纪录档，并自动分析 RPM 套件的属性相依问题。

    与 APT 相比， yum 少了一个 Client 端同步化的步骤了，所以，可以避免使用者不小心遗忘了资料同步化而导致无法取得最新 RPM 纪录的问题喔。
安装 yum 软体
yum 在 Red Hat 及 Fedora 是标准配备，所以您无须伤脑筋。但如果您是其他的 distributions 而想要利用这个好用的 yum 功能，那么可以到底下的网站搜寻适合您的 yum 版本：
  • http://rpmfind.net/linux/rpm2html/search.php?query=yum
  • http://free.tnc.edu.tw/modules/news/article.php?storyid=854
找到后，直接安装即可。
yum 伺服器的套件结构
鸟哥觉得， yum 伺服器的套件结构要比 apt 简单一些些，基本上只有底下几个咚咚：
  • 设定档：不要怀疑，只有一个设定档。

    •
    • /etc/yum.conf：这个档案是给 yum client 用的设定档，里面主要规定了要取用 RPM 档案的 yum server 的资讯，内容有点像这样：

      •
      [root@test root]# vi /etc/yum.conf
      # 在这个档案当中，注解符号是 # ，而每一个大项目则以 [] 作为开始
      # 除了 [main] 是用在针对本机相关参数的说明之外，要取用伺服器的目录时，
      # 则需要额外的规定。我们以上述的 base/update 两个目录作为说明：
      [main]
      cachedir=/var/cache/yum
      debuglevel=2
      logfile=/var/log/yum.log
      pkgpolicy=newest
      distroverpkg=fedora-release
      tolerant=1
      exactarch=1
      # 上面主要规定了执行 yum 时所会使用到的目录。例如 /var/cache/yum。

      [base]
      name=Fedora Core $releasever - $basearch - Base
      baseurl=http://127.0.0.1/yum/fedora/core1/base
      # 这里就重要了，那个中括号[]里面就是‘目录名称’需要对应正确喔
      # name 仅只是说明该目录下的咚咚而已，并不重要；
      # baseurl 则是完整的 URL 了！这里请千万填写正确！

      [update]
      name=Fedora Core $releasever - $basearch - Released Updates
      baseurl=http://127.0.0.1/yum/fedora/core1/update

      看到了吗？事实上，我们只要设定好 [base] 与 [update] 里面的网址，呵呵！就可以使用 yum server所提供的更新功能啦。

  • 执行档：

    •
    • yum：这个指令是给 yum client 用来作为更新之用的，简单的操作如下：

      •
      [root@test root]# yum <options> <更新项目> <套件名称>
      参数说明：
      options：这里仅列出常见的参数而已。
          -y 如果 yum 在工作过程中需要使用者回应，这个参数可以直接回答 yes
      更新项目：更新的动作有底下几个：
          install ：安装某个套件，后面需要接套件名称；
          update  ：这就是升级啦！如果 update 后面接套件名称，表示只要 yum 升级该套件
                    而已，如果 update 后面不接套件名称，表示 yum 针对目前该主机所有已
                    经安装的套件进行升级的动作！这是最常使用的项目了。
          list    ：列出目前在 yum server 上面有的 RPM 套件；
          info    ：某个套件的内容，类似 rpm -qi packages 的内容。
          clean   ：将已将下载到本机的 packages 或 headers 移除。
          remove  ：移除已经安装在我们系统的某个套件！
      范例：
      [root@test root]# yum install hdparm  # 安装 hdparm 这个套件
      [root@test root]# yum update hdparm    # 更新 hdparm 这个套件
      [root@test root]# yum -y update      # 更新目前本机上面的所有套件，并自动回覆 yes
      [root@test root]# yum clean packages # 将下载至本机的 RPM 档案删除(放在
                                                /var/cache/yum 里面。

      # 至于每日更新的话，可以写入 /etc/crontab 喔
      [root@test root]# vi /etc/crontab
      40 5 * * * root yum -y update; yum clean packages

    • yum-arch：这个指令则是给 yum server 使用的！重点在分析 RPM 套件的 header 喔！用法真是很简单，同样已 /var/www/html/yum/fedora/core1/base 为例：

      •
      [root@test root]# yum-arch <options> <目录>
      参数说明：
      options：这里仅列出常见的参数而已。
          -q : yum 分析 RPM 过程中不显示讯息。
      范例：
      [root@test root]# yum-arch /var/www/html/yum/fedora/core1/base
      # 只要经过这个步骤， yum 就会自动在 /var/www/html/yum/fedora/core1/base 底下新增
      # 一个名为 headers 的目录，并将分析的 RPM 纪录资料都放置在里面喔！

  • 相关目录：

    •
    • /var/cache/yum：我们在 yum 这个指令里面谈到当使用 yum 进行升级时，下载下来的 rpm 档案并不会自动被删除的，那么这些 rpm 档案放在哪里呢？就是放在 /var/cache/yum 这个目录内。这些档案在升级完成后就可以移除了，所以我们可以使用‘yum clean packages’来移除这些 rpm 档案喔。
yum 相关的咚咚就只有这样，是否真的很简单啊？ ^_^
yum 伺服器设定
yum 伺服器的设定真是简单！最重要的是 WWW/FTP 的设定必须要正确才行。整个步骤是这样的：

1. 先建立所需要的目录：
[root@test root]# mkdir /var/www/html/yum/fedora/core1/base
[root@test root]# mkdir /var/www/html/yum/fedora/core1/update

2. 复制原版光碟的内容：
# 利用 mount 与 cp umount 等功能，将原本光碟的内容整个复制到
# /var/www/html/yum/fedora/core1/base 当中。

3. 利用 mirrordir 下载升级套件。鸟哥这里建议使用中山大学的 FTP 网站：
[root@test root]# mirrordir -v \
> http://linux.cdpa.nsysu.edu.tw/Linux/Fedora/linux/core/updates/1/i386/ \
> /var/www/html/yum/fedora/core1/update

4. 进行 RPM 套件分析：
[root@test root]# yum-arch /var/www/html/yum/fedora/core1/base
[root@test root]# yum-arch /var/www/html/yum/fedora/core1/update

5. 为 client 建立 yum.conf 内容：
[root@test root]# vi /etc/yum.conf
[main]
cachedir=/var/cache/yum
debuglevel=2
logfile=/var/log/yum.log
pkgpolicy=newest
distroverpkg=fedora-release
tolerant=1
exactarch=1

[base]
name=Fedora Core $releasever - $basearch - Base
baseurl=http://127.0.0.1/yum/fedora/core1/base

[update]
name=Fedora Core $releasever - $basearch - Released Updates
baseurl=http://127.0.0.1/yum/fedora/core1/update

6. 开始自我升级：
[root@test root]# yum -y update

没错！别怀疑！整个 yum 伺服器的架设就是这么简单啊！
特殊案例
建立自己的更新套件
如果您曾经自己修改一些 SRPM 的档案，并且重新打包成为 RPM 套件，然后发行给自己的 Linux 机器来安装，此外，您也可能取得一些计划所释出的 RPM 档案，例如 opnewebmail 所释出的 RPM 套件，这些 RPM 档案您又想放置在自己的伺服器上面，以方便自己未来升级与查询之用，那么应该怎么放置呢？最简单的方法就是将这些档案放置在 /var/www/html/yum/fedora/core1/update 里面，不过可能会有问题，例如如果您使用 mirrordir 进行资料的映射时，那么您放置的 RPM 档案将会被删除喔！

事实上，我们可以自己设定好额外的升级目录啊！举例来说，鸟哥自己所制作出来的 RPM 档案都是放置在：
/var/www/html/yum/fedora/core1/myself
当然，该目录是自己建立的，然后将自己新增的 RPM 档案通通给他复制进去该目录下，之后，就是制作 header 档案啦：
yum-arch /var/www/html/yum/fedora/core1/myself
最后只要在 /etc/yum.conf 里面新增一个目录：
[myself]
name=My personal RPM files
baseurl=http://127.0.0.1/yum/fedora/core1/myself
当然啦，要利用您的 RPM 档案的 client ，他的 /etc/yum.conf 就需要加入上面的设定，(注意：127.0.0.1 是在自己的机器上面跑的缘故，您必须要填写正确的 yum server 的主机名称或 IP 才行。)如此一来，您的 RPM 档案就可以被利用啦！
如何取得网路上的更新元件
上面提到的伺服器几乎都是以 FTP 的方式在 internet 上面取得最新的 RPM 套件档案。那如果您的内部网域本身并不提供 FTP 对外连线时，该如何是好？鸟哥曾经遇过一个特别的状况，在该网域内仅提供 port 80 的对外连线，除此之外，一切都是关闭的！而我们使用的 mirrordir 及 ncftp 都是以 ftp 来对外连线，这该如何是好？

好在天无绝人之路啊！记得鸟哥在前面 网路升级套件 那个章节里面提到的 zzgetrpm.sh 档案吗？您只要下载该档案，然后填写正确的 URL ，就可以透过 port 80 下载网路上最新的更新套件了！而后在内部网域当中，您当然就可以透过各方式来进行 yum/apt 的升级噜！^_^
主机的规划技巧与建议
那么架设一部 APT/YUM 主机需要注意哪些事项呢？因为您的 APT 主机还需要运行 WWW ，所以您可能需要独立出一个 partition 以进行虚拟主机的设定，或者是在 /var/www/html 这个预设的 WWW 主页的硬碟空间要足够！反正 APT 主机需要注意的地方最主要还是在于硬碟的空间了！此外， APT 主机最好可以放置在对外频宽较高的网段内，因为还需要对 Internet 取得 update 的 RPM 档案嘛！

而如果您的 APT 主机仅作为 APT 的 update 之用时，而 WWW 仅是附属的功能，那么您在安置 RPM 的所在目录最好额外的限制使用者的浏览网段，避免被外部的人(来自 Internet)作为连线升级的主要主机，那可能会占据掉您的连外频宽呐！所以，可能的话，使用虚拟主机，并且加以设定浏览的属性，例如使用 iptables 设定防火墙，或以 httpd.conf 里面的 ACCEPT/DENY 功能来抵挡，也是一个不错的想法喔！至于 WWW 主机的相关设定请参考前面的章节。
参考资源：
  • http://bazar.conectiva.com.br/~godoy/apt-howto/
  • http://freshrpms.net/apt/server/
  • http://rpmfind.net/linux/rpm2html/search.php?query=apt
  • http://163.19.59.1/~linux/student_samba/apt/apt_server.html
  • http://cle.linux.org.tw/~candyz/
  • http://linux.duke.edu/projects/yum/
简易 APT/YUM 伺服器设定
2003/08/27：首次完成
2004/06/23：首次加入 yum 伺服器的说明！并有实做的例子喔！


鸟哥的 Linux 私房菜 -- OpenWebMail 好用的 WWW 邮件收发软体

为取得较佳浏览结果，请爱用 firefox 浏览本网页

简易 OpenWebMail 设定
切换解析度为 800x600
最近更新日期：2004/11/23
在 Client 端使用 pop3 之类的 MUA 软体来收信是目前一般使用者最常见的信件收受模式。不过， 这种模式由于是直接将信件下载到用户端的个人电脑上，事实上， 很容易遭受不明病毒的影响，并且，如果信件内容大部分是广告信件的话，由主机传送到个人电脑这过程中的传送行为， 将会平白的让使用者损失一定程度的网路频宽。由于电子邮件对于现代人来说， 应该已经是不可或缺的使用工具，所以虽然使用 pop3 有一定程度的风险，大家还是得继续使用啊~难道没有解决的方法吗？呵呵！是有的，那就是使用网页介面 (Web) 的邮件功能啦，也就是 WebMail 。其实 WebMail 并不是一个邮件伺服器，而只是透过主机提供的 Web 介面让使用者登入，并且直接在主机上面进行邮件的收发而已。因此，事实上，您也可以将 webmail 视为一个 MUA 啦！底下我们就来说一说这一个由台湾人发明的 OpenWebMail 吧！

前言：
    ：架设前须知
 OpenWebMail的安装：
    ：FC1 的 RPM 安装
    ：MDK 10.0 的 tarball安装
 一些其他的设定：
问题与解决：
    ：还是无法执行 openwebmail
 参考资源：
大标题的图示 前言
电子邮件对于一般人来说，是越来越重要了，像鸟哥通常就是使用电子邮件来跟大部分的朋友联络， 而且，重要的文件与公事也几乎是使用电子邮件来传递的呢！而在一般的个人电脑上面，我们通常是使用类似 Outlook express/Netscape/Mozilla 之类的 Client 端软体，并透过 POP3/SMTP 协定来收发信件。

不过，遗憾的是，电子邮件其实并不安全！这点在一些 安全通报 上面就可以查阅的到了，不论是 MTA/MUA 都可能有漏洞的！而且，除了漏洞问题之外，更麻烦的是，广告信件的大量发行， 造成我们用户端的频宽浪费，真的是很讨厌！但是，电子邮件又是这样的重要， 不能不收发电子邮件啊！那怎么办？这个时候我们就可以使用 Web 介面的 MUA 来进行电子邮件的收发啊！

那么这种 webmail 的地位是什么呢？是否只要有 webmail 就不需要 mail server 了呢？当然不是这样！webmail 其实可以被当成是一种 MUA 来看待，也就是说，您可以将他想成与 outlook express 同等级的应用软体；而透过这个 webmail 我们可以对 mail serve r进行电子邮件的存取。也就是说， webmail 要能够使用，必须要架构在具有 WWW 及 Mail Server 的服务上面才行！这几者之间的关系可以简单的这样看：
           Server 端                    Client
    -------------------------
   |       Apache/Webmail<---|<----  Mozilla/IE(浏览器)
   |             |           |
   |<---SMTP-----|           |
   |             |           |
   |  /var/spool/mail/accout |
   `-------------------------'
也就是说，当 Client 端以浏览器登入主机后，主机透过 webmail 提供的服务，让登入的使用者可以读取该主机内自己的邮件，并且，也可以透过主机的 smtp 协定来进行邮件的寄发！

小标题的图示 架设前须知
如同前面的说明，webmail 要能够正确的运作，其实还需要 www/mail 这两种服务的存在才行！此外，由于 webmail 需要能够正确的存取主机内的邮件档案 (/var/spool/mail/account)，所以，我们必须要提供 webmail 足够的权力来存取才行。因此，您必需要确定：
  • WWW Server (Apache) 已经顺利运作；
  • Mail Server (Postfix/sendmail) 已经顺利运作；
  • webmail 要求的前置软体必须已经安装：例如 openwebmail 需要 perl / suidperl / perl(CGI) / perl-Text-Iconv / perl-Compress-Zlib 等等的套件呢！其中 suid 方面的软体，则是提供 webmail 存取权力的套件。
所以啰，在您架设 webmail 之前，请先确认您的主机提供的 WWW/Mail 服务是正确无误的！此外，前驱套件也必须要没有问题的安装才行！

底下我们以目前相当热门，并且是由台湾成大博士董仲恺主导发起的 Openwebmail 这个套件来进行安装！这东西很不错喔！您可以在底下的连结当中下载与 Red Hat/Fedora 有关的 RPM 档案：
  • http://turtle.ee.ncku.edu.tw/openwebmail/download/redhat/rpm/packages/
或者是下载原始档案 (tarball)：
  • http://turtle.ee.ncku.edu.tw/openwebmail/download/release/
底下鸟哥将以 FC1 及 Mandrake 10.0 作为测试的基准来安装 openwebmai 喔！
大标题的图示 OpenWebMail 的安装：
因为 openwebmail 本身就有针对 Red Hat/Fedora 释出 RPM 档案，所以我们当然就直接以编译好的 RPM 档案来安装即可！那如果是非 Red Hat/Fedora 怎么办？没关系，可以使用原始码来安装啊！

小标题的图示 FC1 的 RPM 安装
请先确定 Postfix 或者 sendmail 已经安装完毕，此外， Apache 也已经安装好了！如果想要快速的架设好您的 Postfix + SASL 认证的话，可以这样做：(更详细的资讯请查阅： http://linux.vbird.org0390postfix.htm)
# 0. 先确定所有的套件都已经安装了，主要有:
     postfix-2.0.16-1
     cyrus-sasl-2.1.15-6
     cyrus-sasl-md5-2.1.15-6
     cyrus-sasl-devel-2.1.15-6
     cyrus-sasl-plain-2.1.15-6
     如果还有忘记写上去的，还请继续的安装啊！并且，请移除底下的套件
     sendmail
     fetchmail
     mutt

# 1. 先确定一下 /usr/lib/sasl2/smtpd.conf 存在，且内容为：
     pwcheck_method: saslauthd

# 2. 确定一下 /etc/sysconfig/saslauthd 内容为：
     MECH=shadow

# 3. 确定一下 main.cf 里面有：
smtpd_sasl_auth_enable = yes
smtpd_sasl_local_domain=
smtpd_recipient_restrictions =
  reject_unknown_sender_domain
  reject_unknown_recipient_domain
  permit_mynetworks
  permit_sasl_authenticated
  reject_unauth_destination
smtpd_client_restrictions =
  permit_mynetworks
  hash:/etc/postfix/access
  permit_sasl_authenticated
  reject_rbl_client relays.ordb.org
  reject_rhsbl_client dsn.rfc-ignorant.org
smtpd_sasl_security_options = noanonymous

# 4. 然后启动 saslauth 及 postfix 应该就可以啦！
然后，请先下载 FC1 所需要的前驱套件，请连结至： http://turtle.ee.ncku.edu.tw/openwebmail/download/redhat/rpm/packages/fc1/ 下载所有的 RPM 套件，然后再安装 openwebmail 2.40 版，整个安装流程：
1. 安装 openwebmail ：
[root@test root]# rpm -ivh perl* # 假设所有的RPM都放在 /root 底下。
[root@test root]# yum update
# 这个动作仅只是要升级刚刚的套件而已；

[root@test root]# rpm -ivh openwebmail-2.40-1.i386.rpm
# 注意：在预设的情况下， openwebmail 会将档案资料安装至与 apache 有关的路径
# 也就是 /var/www/data 与 /var/www/cgi-bin 底下，所以，如果您已经将 apache
# 以 tarball 方式安装，导致拥有不同的 WWW Root 路径时，最好使用 tarball
# 来安装您的 openwebmail 啊！

2. 初始化设定：
[root@test root]# cd /var/www/cgi-bin/openwebmail
[root@test openwebmail]# ./openwebmail-tool.pl --init
# 因为 openwebmail 支援相当多种认证机制，因此，我们必须在使用 openwebmail
# 之前，先将 openwebmail 的相关设定做好！上面 openwebmail-tool.pl --init
# 就是在达成这样的目标。此外，这个步骤会进行蛮长的一段时间喔！请耐心等候！

[root@test openwebmail]# cd etc
[root@test etc]# vi dbm.conf
# 找到并修改成底下几行：
dbm_ext                 .db
dbmopen_ext             .db
dbmopen_haslock         yes
[root@test etc]# cd ..
[root@test openwebmail]# ./openwebmail-tool.pl --init
Welcome to the Open WebMail!

This program is going to send a short message back to the developer,
so we could have the idea that who is installing and how many sites are
using this software, the content to be sent is:

OS: Linux 2.4.22-1.2199.nptl i686
Perl: 5.008003
WebMail: Open WebMail 2.40 20040816

Send the site report?(Y/n)
sending report...

Thank you.

3. 进一步设定：
[root@test openwebmail]# cd etc
[root#test etc]# vi openwebmail.conf
# 找到这一行：
default_language                en
# 改成这样子：
default_language                zh_TW.Big5
一般来说，设定成这样就足够您运作 openwebmail 了，不过，您的 WWW 主机必须要能提供 perl 的执行环境，因为 openwebmail 就是以 perl 写成的啊！以 apache 为例，您必须要知道如何启动 perl 的 CGI 执行环境：
[root@test root]# vi /etc/httpd/conf/httpd.conf
ScriptAlias /cgi-bin/ "/var/www/cgi-bin/"
<Directory "/var/www/cgi-bin">
    AllowOverride None
    Options None
    Order allow,deny
    Allow from all
</Directory>
AddHandler cgi-script .cgi .pl
至少上面的设定要设定妥当才行啊！好了，那么如何使用 openwebmail 呢？直接在您的浏览器上面输入：
    http://your.linux.server/cgi-bin/openwebmail/openwebmail.pl
就可以使用 openwebmail 啰！很简单吧！不过，如果万一您的认证一直无法成功的话，可以指定一下认证机制看看：
[root@test root]# cd /var/www/cgi-bin/openwebmail/auth
[root@test auth]# vi auth_unix.pl
# 找到底下：
my $passwdfile_plaintext = $conf{'passwdfile_plaintext'} || '/etc/passwd';
my $passwdfile_encrypted = $conf{'passwdfile_encrypted'} || '/etc/master.passwd';
# 改成这样：
my $unix_passwdfile_plaintext="/etc/passwd";
my $unix_passwdfile_encrypted="/etc/shadow";

# 或者是修改底下这个档案成为：
[root@test root]# vi \
/var/www/cgi-bin/openwebmail/etc/defaults/auth_unix.conf
# 其内容只需将
passwdfile_encrypted /etc/master.passwd
# 改为
passwdfile_encrypted /etc/shadow
# 这样就算完成了。
小标题的图示 MDK10.0 的 Tarball 安装
如果您是使用 MDK 作为您的 Linux 系统时，由于 OpenWebMail 并没有针对这个作业系统来设计 RPM 档案，所以，这里我们以 Tarball 来进行安装。首先，请先确认一下您的 Postfix 与 Apache 已经安装妥当。底下我们就完整的来谈一谈啰！(同样的，更详细的 Postfix + SASL 的 SMTP 身分认证资讯请查阅： http://linux.vbird.org0390postfix.htm )
# 0. 先确定一下底下这些套件都已经安装了(使用 rpm 的方式来安装的)
[root@test root]# rpm -qa | egrep '(sasl|postfix|imap)'|sort
cyrus-sasl-2.1.15-10mdk
imap-2002d-8mdk
libpostfix1-2.1.1-0.1.100mdk
libsasl2-2.1.15-10mdk
libsasl2-devel-2.1.15-10mdk
libsasl2-plug-anonymous-2.1.15-10mdk
libsasl2-plug-login-2.1.15-10mdk
libsasl2-plug-plain-2.1.15-10mdk
postfix-2.1.1-0.1.100mdk
# 若没有安装任何一个套件，请使用 urpmi 来安装喔！

# 1. 建立 saslauthd 认证机制与 smtp 认证档案：
[root@test root]# vi /etc/sysconfig/saslauthd
#SASL_AUTHMECH=pam
SASL_AUTHMECH=shadow
# 事实上，就是将认证机制修订成为 shadow 就是了。

[root@test root]# mkdir /etc/postfix/sasl
[root@test root]# vi /etc/postfix/sasl/smtpd.conf
pwcheck_method: saslauthd
mech_list: plain login
# 这一版的 postfix 比较奇怪，他的认证档案预设就是放置在这里喔！

# 2. 修订 postfix 的设定档 master.cf：
[root@test root]# vi /etc/postfix/master.cf
# 找到这个：
smtp    inet    n       -       y       -       -       smtpd
# 改为这个：
smtp    inet    n       -       n       -       -       smtpd

# 3. 修订 postfix 的设定档 main.cf：
# 基本上，内容就有点类似底下这样：
# Postfix 在 MDK 10.0 底下的预设设定资料：
readme_directory = /usr/share/doc/postfix-2.1.1/README_FILES
sample_directory = /usr/share/doc/postfix-2.1.1/samples
html_directory = /usr/share/doc/postfix-2.1.1/html
sendmail_path = /usr/sbin/sendmail.postfix
setgid_group = postdrop
command_directory = /usr/sbin
manpage_directory = /usr/share/man
daemon_directory = /usr/lib/postfix
newaliases_path = /usr/bin/newaliases.postfix
mailq_path = /usr/bin/mailq.postfix
queue_directory = /var/spool/postfix
mail_owner = postfix

# 使用者的设定资料！
mynetworks_style = host
delay_warning_time = 4h
smtpd_banner = $myhostname ESMTP $mail_name ($mail_version) (Mandrake Linux)
unknown_local_recipient_reject_code = 450
smtp-filter_destination_concurrency_limit = 2
lmtp-filter_destination_concurrency_limit = 2
smtpd_sasl_path = /etc/postfix/sasl:/usr/lib/sasl2  # <== 就是这一行
smtpd_sasl_application_name = smtpd
relayhost = [seed.net.tw]
#上面这行很重要，如果想要以动态 IP 架站，就需要 ISP 的 relay host 才行！
#详细资料请参考：(因为我的主机在seednet底下，所以....)
# http://phorum.study-area.org/viewtopic.htm?t=18621
# http://phorum.study-area.org/viewtopic.htm?t=22806
myhostname = hostname.domain.name  # <==这里请输入您的主机名称
mydomain = domain.name              # <==这里则是领域名称
myorigin = $myhostname
inet_interfaces = all
mydestination = $myhostname
mynetworks = 127.0.0.0/8
alias_maps = hash:/etc/postfix/aliases
alias_database = hash:/etc/postfix/aliases
mail_spool_directory = /var/spool/mail
debug_peer_level = 2
debugger_command =
         PATH=/bin:/usr/bin:/usr/local/bin:/usr/X11R6/bin
         xxgdb $daemon_directory/$process_name $process_id & sleep 5
smtpd_sasl_auth_enable = yes
smtpd_sasl_local_domain =
smtpd_recipient_restrictions =
     reject_unknown_sender_domain
     reject_unknown_recipient_domain
     permit_mynetworks
     permit_sasl_authenticated
     reject_unauth_destination
smtpd_client_restrictions = hash:/etc/postfix/access, permit_sasl_authenticated,
     reject_rbl_client   relays.ordb.org,
     reject_rhsbl_client dsn.rfc-ignorant.org
smtpd_sasl_security_options = noanonymous
notify_classes = resource, software
message_size_limit =   31457280
mailbox_size_limit = 1000000000
header_checks = regexp:/etc/postfix/header_checks
body_checks = regexp:/etc/postfix/body_checks

# 4. 其他相关的档案：
/etc/postfix/access
/etc/postfix/header_checks
/etc/postfix/body_checks
/etc/postfix/aliases
# 相关设定请参考上面提供的连结啊！

# 5. 开始启动：
[root@test root]# /etc/rc.d/init.d/saslauthd start
[root@test root]# /etc/rc.d/init.d/postfix   start
这样就完成了 Postfix 的安装与设定，再接下来则是 Apache 的安装与设定了。
# 0. 利用 urpmi 来安装所需要的所有的套件！
[root@test root]# urpmi apache2 php MySQL
Preparing...                ###########################################
   1:libmysql12             ###########################################
   2:libapr0                ###########################################
   3:apache-conf            ###########################################
   4:apache2-common         ###########################################
   5:perl-Data-ShowTable    ###########################################
   6:perl-Mysql             ###########################################
   7:apache2-modules        ###########################################
   8:apache2                ###########################################
   9:libphp_common432       ###########################################
  10:perl-CGI               ###########################################
  11:MySQL-client           ###########################################
  12:MySQL-common           ###########################################
  13:php-ini                ###########################################
  14:apache2-mod_php        ###########################################
  15:MySQL                  ###########################################
# 因为我再最早安装时，并没有选择 WWW ，所以要安装的资料就很多！
# 另外，请您做好 urpmi 的设定才行！

# 1. 开始启动 httpd 啰！
[root@test root]# /etc/rc.d/init.d/httpd start

# 2. 让 MySQL 在开机时不会自动启动， httpd 则会自动启动！
[root@test root]# chkconfig httpd on
[root@test root]# chkconfig mysql off
[root@test root]# chkconfig --list | grep 3:on
httpd           0:off   1:off   2:on    3:on    4:on    5:on    6:off
千万注意，我们目前并没有要使用 MySQL 的计划，所以，当然就要将 MySQL 给他关闭啦！而 httpd 则是需要在开机的时候就与以启动才行， 所以上面的第二个步骤才需要如此的设定喔！现在，您就可以在您的网址列输入您的主机名称，看看能不能连结 http 提供的 WWW 服务呢？！

现在，请注意，预设的状态下， MDK 10.0 的 WWW 主网页是放置在 /var/www/html 底下的，但是 MDK 却没有预设的 data 目录，所以我们就必须要给予设定啦！您可以这样做：
# 0. 将 openwebmail 解压缩，并且移动到适当的目录下：
[root@test root]# cd /usr/local/src
[root@test src]# tar -zxvf /disk1/software/openwebmail-2.40.tar.gz
[root@test src]# cd cgi-bin/
[root@test cgi-bin]# mv openwebmail/ /var/www/cgi-bin/
[root@test cgi-bin]# cd ..
[root@test src]# rmdir cgi-bin
[root@test src]# mv data/openwebmail /var/www/html/openwebmail_data
[root@test src]# rmdir data
# 同时请注意，您的主机上面必须要有 perl 模组的存在了才行！
# 我的 perl 模组有底下这么多：
perl-MailTools-1.59-2mdk
perl-Crypt-SSLeay-0.51-3mdk
perl-Term-Readline-Gnu-1.14-5mdk
perl-Digest-SHA1-2.04-1mdk
perl-Mysql-1.22_19-9mdk
perl-MDK-Common-1.1.11-2mdk
perl-HTML-Parser-3.35-2mdk
perl-File-Slurp-2002.1031-3mdk
perl-Tk-800.024-4mdk
perl-SGMLSpm-1.03ii-6mdk
perl-SDL-1.20.0-8mdk
perl-ldap-0.31-2mdk
perl-Glib-1.021-3mdk
perl-Gtk2-1.023-3mdk
perl-IO-Tty-1.02-9mdk
perl-Gtk2-TrayIcon-0.03-3mdk
perl-Authen-SASL-2.04-2mdk
perl-Locale-gettext-1.01-11mdk
perl-TimeDate-1.16-3mdk
perl-HTML-Tagset-3.03-7mdk
perl-URI-1.25-1mdk
perl-Gnome2-Vte-0.02-1mdk
perl-devel-5.8.3-5mdk
perl-XML-SAX-0.12-3mdk
perl-Convert-ASN1-0.16-4mdk
perl-Data-ShowTable-3.3-9mdk
perl-5.8.3-5mdk
perl-DBI-1.40-2mdk
perl-Libconf-0.33-2.1.100mdk
perl-XML-Parser-2.34-1mdk
perl-CGI-3.00-2mdk
perl-URPM-0.94-11mdk
perl-Expect-1.15-6mdk
perl-Digest-HMAC-1.01-11mdk
perl-base-5.8.3-5mdk
perl-libwww-perl-5.76-3mdk
perl-XML-NamespaceSupport-1.08-3mdk
# 另外，也需要加入两个必要的模组，您可以使用 FC1 的相关档案，下载点：
# http://turtle.ee.ncku.edu.tw/openwebmail/download/redhat/rpm/packages/fc1/
# rpm -ivh perl-Text-Iconv-1.2-fc1.i386.rpm perl-Compress-Zlib-1.16-12.i386.rpm
# 两个就可以啦！

# 1. 初始化设定：
[root@test root]# cd /var/www/cgi-bin/openwebmail
[root@test openwebmail]# ./openwebmail-tool.pl --init
# 因为 openwebmail 支援相当多种认证机制，因此，我们必须在使用 openwebmail
# 之前，先将 openwebmail 的相关设定做好！上面 openwebmail-tool.pl --init
# 就是在达成这样的目标。此外，这个步骤会进行蛮长的一段时间喔！请耐心等候！
[root@test openwebmail]# cd etc
[root@test etc]# vi dbm.conf
# 找到并修改成底下几行：
dbm_ext                 .pag
dbmopen_ext             none
dbmopen_haslock         yes
[root@vbird etc]# vi openwebmail.conf
# 找到并修改成底下几行：
domainnames             auto
auth_module             auth_unix.pl
mailspooldir            /var/spool/mail
ow_cgidir               /var/www/cgi-bin/openwebmail
ow_cgiurl               /cgi-bin/openwebmail
ow_htmldir              /var/www/html/openwebmail_data
ow_htmlurl              /openwebmail_data
logfile                 /var/log/openwebmail.log
[root@test etc]# cd ..
[root@test openwebmail]# ./openwebmail-tool.pl --init

creating db /var/www/cgi-bin/openwebmail/etc/maps/b2g ...done.
creating db /var/www/cgi-bin/openwebmail/etc/maps/g2b ...done.
creating db /var/www/cgi-bin/openwebmail/etc/maps/lunar ...done.
Welcome to the Open WebMail!

This program is going to send a short message back to the developer,
so we could have the idea that who is installing and how many sites are
using this software, the content to be sent is:

OS: Linux 2.6.3-14mdk i686
Perl: 5.008003
WebMail: Open WebMail 2.40 20040816

Send the site report?(Y/n) y
sending report...

Thank you.

# 2. 修订认证机制：
[root@test root]# vi /var/www/cgi-bin/openwebmail/auth/auth_unix.pl
# 找到：
my $passwdfile_encrypted = $conf{'passwdfile_encrypted'} || '/etc/master.passwd';
# 修改成：
my $passwdfile_encrypted = '/etc/shadow';

# 或者是修改底下这个档案成为：
[root@test root]# vi \
/var/www/cgi-bin/openwebmail/etc/defaults/auth_unix.conf
# 其内容只需将
passwdfile_encrypted /etc/master.passwd
# 改为
passwdfile_encrypted /etc/shadow
# 这样就算完成了。
然后连到您的主机：http://hostname/cgi-bin/openwebmail/openwebmail.pl ，就能够看到您的 OpenWebmail 啰！同时，如果还是无法看到相关的咚咚，请查阅您的登录档！
大标题的图示 一些其他的设定：
除了既有的设定之外，如果您想要其他的设定时，这里提供几个简单的设定：
# 1. 网路硬碟：
如果不想提供网路硬碟的话，可以在底下的档案：
/var/www/cgi-bin/openwebmail/etc/openwebmail.conf
加入这行：
enable_webdisk no

# 2. 提供 ssh 连线：
如果不想提供网路连线的话，可以在底下的档案：
/var/www/cgi-bin/openwebmail/etc/openwebmail.conf
加入这行：
enable_sshterm no

# 3. 让登入更简单：
如果不想在网址列输入长长的一段文字，可以修改成为：
vi httpd.conf (请依照您的系统来修订！)
ScriptAlias  /webmail     /var/www/cgi-bin/openwebmail/openwebmail.pl
or
ScriptAlias  /webmail.pl  /var/www/cgi-bin/openwebmail/openwebmail.pl
然后重新启动 apache ，如此一来，您可以在网址列输入：
http://hostname/webmail or http://hostname/webmail.pl
就可以进入 openwebmail 啰！
大标题的图示 问题与解决
  • 还是无法执行 openwebmail：

    一般来说，安装好 openwebmail 之后，应该是立即可以使用了，不过，如果您一直无法进入 openwebmail 的欢迎画面，那么请特别留意：

    1. 在 openwebmail.conf 这个设定档当中，是否填写了适当的认证机制(auth_unit.pl)；
    2. 在 auth_unix.pl 这个设定档当中，是否填写了正确的密码认证档案？
    3. 您的 WWW 是否提供 perl 的 CGI 执行环境？
    4. 仔细查阅 /var/log/httpd/error_log 及 /var/log/openwebmail.log 来解决问题！

  • 来自讨论区的网友留言
    鸟哥好：
最近刚好在装 openwebmail，拜读主站上的文件安装下去，
发现有一些部份在安装时可能需要额外注意的，在此提供给您。
我的 distribution 是用 MDK 9.2，因此我是照 MDK 10.0 的
Tarball 安装作下去的，不过我的 postfix + LAMP 是用 rpm
装的，因此我直接跳到 openwebmail 安装。

文中提到：
现在，请注意，预设的状态下， MDK 10.0 的 WWW
主网页是放置在 /var/www/html 底下的，但是 MDK
却没有预设的 data 目录，所以我们就必须要给予设定啦！
您可以这样做：

但我在 ./openwebmail-tool.pl --init 时仍会碰到要找
/usr/local/www 底下的 cgi-bin 的情形，所以应该还是要
 ln -s /usr/local/www /var/www

另外，文件中下达 ./openwebmail-tool.pl --init 两次，
但事实上第一次执行时系统会告诉我 dbm.conf 的资讯不对，
所以我认为应该先改 dbm.conf 再执行即可？

以上是我粗浅的看法，其实不管怎么样，可以正确的初始化才是重点。

最后是安装后不能改密码的问题，研究后发现在
cgi-bin/openwebmail/etc/defaults/auth_unix.conf
除了更改 passwdfile_encrypted 外，也要将 passwdmkdb 设定成none 才行。

这几点是我安装时几个相异之处，提出来供鸟哥参考。也谢谢鸟哥文件的分享。
大标题的图示 参考资源
  • OpenWebMail 的下载： http://turtle.ee.ncku.edu.tw/openwebmail/download/
  • OpenWebMail 台湾主站： http://turtle.ee.ncku.edu.tw/openwebmail/
  • Ultraman 的 OpenWebMail 实作： http://linux.vbird.org/somepaper/20030317-openwebmail.htm
2004/08/26：首次完成；
2004/10/22：收到网友 tzerming 兄的来信，告知认证机制的修改方面，可使用 auth_unix.conf 的修改方法！
2004/11/23：收到来自讨论区网友 wonton 兄的来信，将该留言放置于问题与解决了！
2004/08/26以来统计人数


鸟哥的 Linux 私房菜 -- 架设 Cluster

为取得较佳浏览结果，请爱用 firefox 浏览本网页

简易 Cluster 架设
最近更新日期：2003/05/20

近年来因为数值模式模拟的盛行，所以‘平行运算’的架构也就越来越重要了！什么是数值模拟呢？主要就是藉由一些物理理论去开发出来的一些‘计算公式’，而这些计算公式藉由程式语言(例如C、Fortran等等)实际的将他编译成为可执行的程式，最常见的例如中央气象局不是每天都会预报天气吗？这个预报的动作就是利用数值计算去演算出来的。另外，还有空气品质模式模拟，也是经过运算出来的，除此之外，例如天文、物理、水文等等很多方面的工作，都是利用这种数值模拟的运算的喔！不过，这些程式是很大型的！也就是说，他们在运算的时间是很长的，如果使用单颗 CPU 的话，不论这颗 CPU 的频率与效能有多高，还是得要运算个好几个钟头的～如此一来，对于像气象预报这个急需时效性的工作可能就会有所延误啊！不过，如果我将这个运算的工作同时丢给多颗 CPU 呢？也就是让多颗 CPU 同时进行这个程式的运算工作，如此一来，将可以大大的减低时间的损耗了～这就是平行运算的简单说明。在 Linux 平台上面，要达成简单的平行运算，可以透过 MPI 的函式库，例如 MPICH 就是一个很有名的 MPI 软体喔！马上来给他看看平行运算类型的 Cluster 建置吧！

原理：
    ：什么是 Cluster 与 Cluster 的优点
    ：Cluster 的主从架构
    ：达成 Cluster 所需要额外功能 ( RSH ) 与软体 ( MPICH )
架设流程：
    ：整体架构
    ：鸟哥的一个实例规范
    ：系统安装 ( Red Hat 9 )
    ：防火墙 ( 含 NAT 主机 ) 与网路设定
    ：NFS 架设规划(相当重要，参考说明)
    ：NIS 架设规划
    ：RSH 设定
    ：安装 Fortran 90 的编译程式 PGI pgf90 ( PS. server version )
    ：安装 MPICH
其他主机相关设定：
    ：X-Window Server/Slave 架构
重点回顾
参考资源
原理：
  • 什么是 Cluster 与 Cluster 的优点

    •
    什么是 Cluster 呢？目前常见的 Cluster (丛集)架构有两种，一种是 Web / Internet cluster system，这种架构主要是将资料放置在不同的主机上面，亦即由多部主机同时负责一项服务；而另外一种则是所谓的平行运算了！平行运算其实就是将同一个运算的工作，交给整个 Cluster 里面的所有 CPU 来进行同步运算的一个功能。由于使用到多个 CPU 的运算能力，所以可以加快运算的速度。目前比较常见于平行运算功能的，通常需要在超级电脑上面才看的到，这些超级电脑主要是用在天文、军事、物理等需要很精密的、大量的运算的工作中，而考虑到稳定性，则通常是用在 Unix 系统上面的硬体架构上。不过，目前由于 PC 上面的 CPU 的运算功能越来越强大了～因此，当然很多程式开发者就动脑筋到 PC 上面来制作平行电脑的系统啰！我们这篇短文主要在介绍的就是‘平行运算’这一类的 Cluster 了！

    由于 Cluster 主要是用在平行运算上面的，而所谓的平行运算是使用到多颗 CPU 的运算功能，因此可以让您的大型运算的程式很快的执行完毕！因此，如果你的工作环境当中，常常会使用到很耗 CPU 运算功能的程式时，就可以尝试使用 Cluster 来进行工作啰！应该可以节省您不少的时间呐！此外，我们这篇短文主要是在 X86 架构下的 PC 来架设 Cluster 的喔！

    不过，也需要特别留意的是，由于我们的 Cluster 是将一个工作平均分给所有的 node (注：一颗 CPU 在一个 Cluster 架构下，就称为一个 node 啰！)，所以，万一您做成的 Cluster 系统当中，所有的 node 并非完全相同的运算等级，那么先做完工作的 node 将会暂停工作，会等到所有的 node 都进行完毕后，才会在进行下一动～所以啦！强烈的建议在同一个 cluster 的架构中，尽量所有的 CPU 都使用相同的 CPU 型号，应该会比较好一点喔！

  • Cluster 的主从架构

    •
    最简单的 Cluster 其实就是以一种主从架构来进行资料的运算工作的，图示如下：
    • 上面的 Master 与 Slave 指的都是 CPU 喔！

      •
    • Master 那部机器上面必须要有可以将工作分配给各个 node 去工作的函式库，也就是 MPI ，他最重要的功能就是将工作给他分配下去的啦！而最重要的软体就是：(1)MPICH；(2)编译器(compiler, 例如 Fortran)；

      •
    • 什么是网路功能呢？如果 master 与 slave 是在同一部机器当中，例如双 CPU 的主机板，那么这里就不需要网路功能啦！不过，如果我是使用四台双 CPU 的 PC 呢？呵呵！那么这四部主机就需要以高速网路架构进行连线啦！此外，还需要在这四部主机之间建立可以互通讯息的通讯协定才行，这方面的功能就含有：(1)R Shell, 亦即称为 RSH；(2)NIS，使 Master 与 Slave 具有相同的帐号群组关系；(3)NFS，使读取写入的资料可以在同一个 partition 上面；

      •
    • Slave 就是单纯的将来自 Master 的任务给他做完就是了！

    整个主从架构大致上就是这样啦！因此，可以知道的是，我们需要的就是上面那些咚咚啰！

  • 达成 Cluster 所需要额外功能 ( RSH ) 与软体 ( MPICH )

    •
    由上面的 Cluster 主从架构当中，我们知道 Master 与 Slave 之间的网路沟通很重要的一个咚咚，那就是 R Shell 啰！此外，还有将一个工作传送给不同的 node 来进行计算的任务，就需要 MPICH 这个函式库来进行！简单的谈一谈这两个玩意儿吧！

    • RSH：

      • 在我们的 Linux 主机上面工作，通常使用 BASH 这个 shell 来传达给 kernel 工作的讯息，以使主机正确的工作；而如果在不同的主机之间，那就可以使用 R Shell 来进行指令的下达喔，如此一来，我们就可以直接在 A 机器，向 B 机器下达工作的指令，而不需要登入 B 机器呢～那就是 RSH 的主要功能啦！最常见的 RSH 指令就是 rcp 与 rsh 了！有兴趣的朋友应该知道以 man 来查寻一下该指令的用法啰！
      需要附带一提的是，这个 RSH 是‘相当危险’的一个服务喔！由于我们可以直接登入 RSH 主机，并且在上面进行指令的下达，为了避免还要输入密码的问题，因此通常 RSH 已经将信任主机设定好了，不过，由于 RSH 会启动一些 port 来监听 Clients 的需求，而偏偏这些 port 与 daemon 都还挺危险的，因此，‘Cluster 最好是设定在内部网域当中，并使用私有 IP ，比较能够避免危险’喔！此外，那个 Master 也必须要设定好一定程度的严密防火墙喔！

    • MPICH：

      • MPI 是 Messages Passing Interface 的缩写，他本身是一个规格很严密的通讯标准，主要的功能是在处理平行运算之间各个 node 的资料交换，请注意， MPI 并不是一套软体喔！而至于 MPICH 就是符合 MPI 这个标准通讯协定的一套软体了！因此，我们可以经由 MPICH 这个软体提供的 MPI 函式库来达成平行运算的功能喔！也就是说，我们所写的程式，只要能够使用 MPICH 提供的函式库，那么该程式就可以进行平行运算时候所需要的功能了，这就可以避免程式开发者还要去处理通讯节点上面的问题，而可以将程式开发的重心着重在程式本身的问题上面！
      MPICH 是由 Mathematics and Computer Science Division的 Argonne 实验室所发展，详细的资料可以参考：http://www-unix.mcs.anl.gov/mpi/mpich/

    除了这两个软体之外，还需要 NIS 与 NFS 喔！所以啦！要建置一个 Cluster 的话，身为系统管理员的您，必须要学会的技能真是相当的多的，至少需要：

    • 熟悉 Linux 的操作技巧；
    • 熟悉 Linux 基础网路参数设定；
    • 熟悉 Linux 相关的 Server 架设(这方面请参考鸟哥的私房菜架站篇)；
    • 了解 RSH 的相关功能与设定技巧；
    • 了解 MPICH 的设定与相关功能；
    • 熟悉至少一种程式语言。

    还真的是不好学啊！鸟哥也是新手玩弄 Cluster 说～大家一起研究研究吧！ ^_^
架设流程
    要架设 Cluster 当然就是需要多部的 PC 来连线啦！不然怎么称为 Cluster 呢？您说是吧！所以，无论如何，在架设 Cluster 之前，请务必要确认您的‘所有硬体以及网路功能都是完整无缺的！’否则就无法继续下去啦！另外，建议 Cluster 的所有主机规格尽量相同，可以避免等待的困扰呢！底下就来谈一谈整个架设流程吧！

  • 整体架构

    •
    整体架构的架设当中，需要的所有软体为：

    • Master 主机安装需要：
      • 防火墙的设定(含 NAT 架设)；
      • RSH
      • NIS Server
      • NFS Server
      • Compiler Install
      • MPICH Install
      • 其他特殊功能

    • Slave 主机安装需要：
      • 防火墙的设定
      • RSH
      • NIS Client
      • NFS Client

    基本上，几乎所有的工作都是在 Master 上面做啦！ Slave 最大的任务就是进行来自 Master 所要求的计算工作，因此，Slave 能够越简单越好～至于 Master 上面，由于我们都是在 Master 主机上面下达工作指令，而总不能老是在荧幕前面下达指令吧！因此上，Master 通常会有两个网路介面，分别是对外的 Public IP 与对内的 Priavte IP。而既然 Master 有提供 Public IP 的设定，自然就比较担心所谓的骇客入侵问题，所以啦，您的 Master 主机，要吗就不要开放 Public IP ，要吗就务必要设定很严密的防火墙，并且不必要的服务就尽量关闭他～毕竟我们的 Cluster 是要用来做为计算运作的，所以不必要的网路协定服务，当然就是关闭他啦！底下鸟哥将以自己的一个实际案例进行说明的啦！参考看看吧！

  • 鸟哥的一个实例规范

    •
    在我这个案例当中， Cluster 主要的功能为：进行 MM5 这个气象模式的运算以及 Models-3/CMAQ 这个空气品质模式的运算，而由于这两个咚咚都是使用 PGI Fortran 90 做为 Compiler ，因此，我就必须要进行 PGI 的安装啦！而我的硬体架构主要是这样的：

    • Master ： 为双 CPU 主机，使用 AMD MP 的 CPU ，并且有一颗 120 GB 的硬碟，此外，由于我的数值模式需要 PGI Fortran ，所以就必须要安装 Server 版的 PGI Fortran 喔！
    • Slave ： 共有三部 Slave ，每一部均为双 CPU 的 AMD MP 的 CPU ，并且有一颗 120 GB 的硬碟；
    • 连接 Master 与 Slave 的为 10/100/1000 的 Switch ，当然，四部主机(1 x master + 3 x slave)都是安装 Intel 的 1GB 网路卡喔！

    硬体连接有点像这样：
    那么底下就来谈一谈怎么安装他吧！

  • 系统安装( Red Hat 9 )

    •
    我的这个系统使用的是最新的 Red Hat 出版的 Red Hat 9 ，会用这个玩意儿最大的原因是因为 Red Hat 是目前支援的 Linux 软体最多的一个 Linux Distribution 了，安装他之后，就比较不会欠东欠西的，此外，很多的软体都是以 Red Hat 做为测试的平台，因此我就选择他来做为我的系统平台啊！另外，需要留意的是，由于 Slave 并不需要使用到图形介面的功能，他单纯是用在计算上面，因此我没有在 slave 上面安装图形介面的打算～至于 Master 则安装了 KDE 这个咚咚喔！好了，Linux 的安装相信大家应该都要很熟悉了，所以我就不再谈安装的详细步骤，仅提几个特别需要注意的地方啰：

    • Partition 方面：

      • 因为我的硬碟实在是在蛮大的，并且在 Slave 上面也是 120 GB 的硬碟，如果不将 Slave 的硬碟使用的话，实在觉得很浪费，因此，一开始我就规划将四部主机的硬碟全部都以 NFS 分享到内部网域当中，而为了避免跟系统的档案放在一起，因此，我就将硬碟分割出除了必要的 partition 之外，其他的就挂载在 /disk1 这个目录当中，四部主机的 parition 都相同，分别是：

      • /     : 10 GB
      • /var  :  5 GB
      • /tmp  :  3 GB
      • Swap  :  3 GB ( 因为我每部 Linux 主机上面都有 1.5 GB 的记忆体 )
      • /disk1: 96 GB

    • 安装时选择的套件：

      • 所有的主机都需要底下的套件安装(注：因为原本的笔记记录的很乱，所以如果找不到相同的字眼，那就是我写错啦！)：
      • Administrattion Tools
      • Development Tools
      • Editors
      • Engineering and Scientific
      • FTP Server
      • Kernel Development
      • Network Servers
      • Server configuration Tools
      • Sound and vedio
      • System Tools
      • Text-based Internet
      • Windows File servers
      不过， Master 需要额外再增加 X Window 方面的支援，例如 KDE 与 X-Window System 这两个主要的套件要勾选喔！

    系统安装大致上就是这些吧，如果有疏漏的，请未来在安装完毕之后，再以原本 Red Hat 9 的光碟来重新安装他吧！反正 Red Hat 系统都是以 rpm 来安装的，挺容易安装的喔！整个安装完毕后，还花不到几分钟呢！

  • 防火墙 ( 含 NAT 主机 ) 与网路设定

    •
    由于我们的 Cluster 主要是用在数值运算，因此，当然不需要对外开放网路服务啦！所以，最好就是以私有 IP 来进行网路的设定是比较好的！此外，最好还是要设定好防火墙的啦！我的网域参数预设是这样的：

    • Network/netmask：192.168.10.0/255.255.255.0
    • Master：(对外)140.116.xxx.yyy；(对内)192.168.10.30, Gateway 为对外的 Gateway 喔！并且有设定 NAT 啊！
    • Slave：192.168.10.10, 192.168.10.20, 192.168.10.40 三部，Gateway 为 192.168.10.30

    网路参数的各个档案是这样的：

    • 各个主机的主机名称请修改：/etc/sysconfig/network
    • 各个主机的网路卡设定项目请修改：/etc/sysconfig/network-scripts/ifcfg-eth0
    • 各个主机的 DNS 查寻系统请修改：/etc/resolv.conf
    • 各个主机的内部主机名称查寻系统请修改：/etc/hosts，我的 /etc/hosts 如下：

      • 127.0.0.1       localhost       localhost.localdomain
      192.168.10.10   node1.cluster
      192.168.10.20   node2.cluster
      192.168.10.30   server.cluster
      192.168.10.40   node4.cluster

    而我的每部主机先将所有的网路服务都给他关掉去，仅剩下 SSH 这个网路协定存在而已～所以，我利用 Red Hat 提供的 ntsysv 这个指令来选择开机时启动的项目有：

    • atd
    • crond
    • iptables
    • keytable
    • network
    • random
    • sshd
    • syslogd
    • xinetd

    至于防火墙系统的规划上面，由于 Master 主机 (192.168.10.30) 具有 NAT 的功能，所以必须要修改一下他的防火墙机制，因此，就有两个不同的防火墙机制 scripts 啰！另外，由于担心外来的入侵攻击，因此，在这个 Cluster 的系统当中，我的 iptables 防火墙机制是使用‘MAC(网路卡卡号)’来做为设定的基准，而不是使用 IP 啊！为什么呢？因为反正我仅允许我自己同网域内的几部电脑连进来而已，当然没有必要针对 IP 啊！所以啰，就必须要收集四部主机的网路卡来允许他进入啰。此外，由于我可能并不在 Cluster 前面操作，因此会启用一两部主机的网路卡卡号，好让他能够进入 Cluster 呦！底下就将我的防火墙机制给他列出来一下：

    • Master：
      • #!/bin/bash
      # This program is for iptables' rules
      # VBird 2003/05/02
      #
      # 0. PATH and modules
        PATH=/sbin:/bin:/usr/sbin:/usr/bin
        export PATH
        modprobe ip_tables
        modprobe iptable_nat
        modprobe ip_nat_ftp
        modprobe ip_nat_irc
        modprobe ip_conntrack
        modprobe ip_conntrack_ftp
        modprobe ip_conntrack_irc
      #
      # 1. clear the rules and make the policys
        iptables -F
        iptables -X
        iptables -Z
        iptables -F -t nat
        iptables -X -t nat
        iptables -Z -t nat
        iptables -P INPUT   DROP
        iptables -P OUTPUT  ACCEPT
        iptables -P FORWARD ACCEPT
        iptables -t nat -P PREROUTING  ACCEPT
        iptables -t nat -P POSTROUTING ACCEPT
        iptables -t nat -P OUTPUT      ACCEPT

      #
      # 2. NAT services
        echo "1" > /proc/sys/net/ipv4/ip_forward
        iptables -t nat -A POSTROUTING -s 192.168.10.0/24 -o eth1 -j MASQUERADE
      #
      # 3. Trust network and conditions
        iptables -A INPUT -m state --state ESTABLISHED,RELATED  -j ACCEPT
        iptables -A INPUT -i lo -j ACCEPT
        iptables -A INPUT -m mac --mac-source XX:YY:ZZ:WW:QQ:PP -j ACCEPT
      # 上面这一行就是网路卡的卡号啦！

    • Slave：

      • Slave 的防火墙机制跟 Master 几乎一模一样，只是因为在内部啊，所以不需要启动 NAT 的服务即可！上面的给改一改先～

    好啦！网路的设定与防火墙就到这里为止，要记得喔，你的网路必须要已经能够正确的启动了！如果还是无法启动网路，或者是防火墙机制还是有问题，那么对外的那个网路卡的网路线还是先给他拔掉吧！比较安全一些些的啦！等到都设定妥当，尤其是防火墙，然后才来启动他吧！

  • NFS 架设规划

    •
    由于我这里预计要设定 NIS ，并且每部主机的 /disk1 都要分享出去，因此，每部主机都必须要开放 NFS 的服务喔！并且，每一部主机的设定都可以相同呐！这样比较容易来设定啰～此外，比较不一样的地方在于 Master 这一部，由于我的 Cluster 所有的帐号都在 NIS 的管制之中，因此，我将 Master 的 /home 也分享出来，并且每部 Slave 主机都挂载 Master 的 /home 才成！

    这个 NFS 在 Cluster 当中是相当重要的，为什么呢？因为我们不是在四部主机上面工作吗，而这四部主机会去读取的‘资料’其实都是‘在本机上面可以看的到的’资料才行，这还包括底下我们会持续介绍的 mpich 这个软体的函式库呢！也就是说：‘在 Cluster 里面，所有的机器会使用到的资料必须都在相同的目录当中！’所以，这就是为什么我们要对 /home 进行分享，以及进行 NIS 的设定了！此外，因为我的 Server 这部 Master 机器分享出去的目录中，已经含有 /disk1 这个 partition，此外，还通通将他挂载在 /cluster/server 底下，因此，可以建议：‘未来在安装所有的 Cluster 需要的套件资料时，例如 Compiler 以及 MPICH 等等，都可以安装到 /cluster/server 这个目录底下，以使所有的主机都能够使用同一个 partition 来源的资料喔！’

    设定程序：

    • Master：
      1. 启动 portmap 并且设定开机启动：
      [root @server root]# /etc/rc.d/init.d/portmap start
      [root @server root]# chkconfig --level 35 portmap on

      2. 设定 NFS 分享出去：
      [root @server root]# vi /etc/exports
      /home  192.168.10.0/24(rw,async,no_root_squash)
      /disk1 192.168.10.0/24(rw,async,no_root_squash)
      [root @server root]# exportfs -rv
      [root @server root]# /etc/rc.d/init.d/nfs start
      [root @server root]# chkconfig --level 35 nfs on

      3. 设定预计的挂载点：
      [root @server root]# mkdir -p /cluster/node1
      [root @server root]# mkdir -p /cluster/node2
      [root @server root]# mkdir -p /cluster/node4
      [root @server root]# mkdir -p /cluster/server

    • Slave：
      1. 启动 portmap 并且设定开机启动：
      [root @node1 root]# /etc/rc.d/init.d/portmap start
      [root @node1 root]# chkconfig --level 35 portmap on

      2. 设定 NFS 分享出去：
      [root @node1 root]# vi /etc/exports
      /disk1 192.168.10.0/24(rw,async,no_root_squash)
      [root @node1 root]# exportfs -rv
      [root @node1 root]# /etc/rc.d/init.d/nfs start
      [root @node1 root]# chkconfig --level 35 nfs on

      3. 设定预计的挂载点：
      [root @node1 root]# mkdir -p /cluster/node1
      [root @node1 root]# mkdir -p /cluster/node2
      [root @node1 root]# mkdir -p /cluster/node4
      [root @node1 root]# mkdir -p /cluster/server

    挂载程序：

    • Master：

      • 将底下这些指令测试执行一下，如果成功后，将指令写入 /etc/rc.d/rc.local 当中
      [root @server root]# mount -t nfs -o bg,intr server.cluster:/disk1 /cluster/server
      [root @server root]# mount -t nfs -o bg,intr  node1.cluster:/disk1 /cluster/node1
      [root @server root]# mount -t nfs -o bg,intr  node2.cluster:/disk1 /cluster/node2
      [root @server root]# mount -t nfs -o bg,intr  node4.cluster:/disk1 /cluster/node4

    • Slave：
      将底下这些指令测试执行一下，如果成功后，将指令写入 /etc/rc.d/rc.local 当中
      [root @node1 root]# mount -t nfs            server.cluster:/home  /home
      [root @node1 root]# mount -t nfs -o bg,intr server.cluster:/disk1 /cluster/server
      [root @node1 root]# mount -t nfs -o bg,intr  node1.cluster:/disk1 /cluster/node1
      [root @node1 root]# mount -t nfs -o bg,intr  node2.cluster:/disk1 /cluster/node2
      [root @node1 root]# mount -t nfs -o bg,intr  node4.cluster:/disk1 /cluster/node4

    呵呵！这样就设定成功了！我们每一部主机‘看起来’就好像有 400 GB 的硬碟空间啊！可怕了吧！ ^_^

  • NIS 架设规划

    •
    NIS 的设定也是很简单，不过主要还是需要分为 NIS Server 与 NIS Client 两部份来设定的！请注意，在设定之前，就已经要将 NFS 搞定喔！这些流程都是有一定程度的相关性的呢！

    • Master：

      • 在 Master 上面需要进行的工作很多喔！首先，一定要修改 ypserv.conf 以及其他相关的档案的呐！
      1. 启动 time 与 time-udp 这两个预先要启动的 daemon
      [root @server root]# chkconfig --level 35 time on
      [root @server root]# chkconfig --level 35 time-upd on
      [root @server root]# /etc/rc.d/init.d/xinetd restart

      2. 建立 NIS 的领域名称 (我这里是设定为 cluster )：
      [root @server root]# nisdomainname cluster
      [root @server root]# echo "/bin/nisdomainname cluster" >> /etc/rc.d/rc.local
      [root @server root]# echo "NISDOMAIN=cluster" >> vi /etc/sysconfig/network

      3. 建立 NIS 设定档：
      [root @server root]# vi /etc/ypserv.conf (在这个档案内增加三行即可)
      127.0.0.0/255.255.255.0   :  *  :  *  :  none
      192.168.10.0/255.255.255.0:  *  :  *  :  none
      *                         :  *  :  *  :  deny
      [root @server root]# touch /etc/netgroup

      4. 启动 NIS：
      [root @server root]# /etc/rc.d/init.d/ypserv    start
      [root @server root]# /etc/rc.d/init.d/yppasswdd start
      [root @server root]# chkconfig --level 35 ypserv on
      [root @server root]# chkconfig --level 35 yppasswdd on

      5. 制作资料库：(每次有更动使用者资讯时，就必须要进行这个步骤！)
      [root @server root]# /usr/lib/yp/ypinit -m
      [root @server root]# chkconfig --level 35 ypserv on
      [root @server root]# chkconfig --level 35 yppasswdd on

    • Slave：

      • 至于 NIS Client 则是需要设定 yp.conf 这个档案呢！
      1. 建立 NIS 的领域名称 (我这里是设定为 cluster )：
      [root @node1 root]# nisdomainname cluster
      [root @node1 root]# echo "/bin/nisdomainname cluster" >> /etc/rc.d/rc.local
      [root @node1 root]# echo "NISDOMAIN=cluster" >> vi /etc/sysconfig/network

      2. 建立 NIS 查寻的主机名称：
      [root @node1 root]# vi /etc/yp.conf
      domain cluster
      ypserver server.cluster

      3. 修改密码验证方式：
      [root @node1 root]# vi /etc/passwd (在这个档案的最底下新增如下一行)
      +::::::
      [root @node1 root]# vi /etc/nsswitch.conf
      passwd:     files nis nisplus
      shadow:     files nis nisplus
      group:      files nis nisplus
      hosts:      files nis dns

      4. 启动 NIS：
      [root @server root]# /etc/rc.d/init.d/ypbind    start
      [root @server root]# chkconfig --level 35 ypbind on

    呵呵！不啰唆！马上就设定妥当啦！

  • RSH 设定

    •
    这个 RSH 已经提过了，主要的功能是提供 Master 可以使用 R 指令(如 rsh, rlogin, rcp 等等)来进行 slave 端主机的操控的！所以啦， RSH daemon 主要是在 slave 机器上面架设的喔！与 Master 就无关啦！Master 只要能够执行 R command 即可！虽然是如此，不过，在我的测试当中，最好 Master 也启动 RSH 比较好一些些啰！在底下的设定当中，我们假设 Server 上面的所有使用者都可以使用 R command 呢！设定的方法很简单啊！

    • Slave & Master：

      • 底下的设定在 Master 与 Slave 上面都需要动作喔！设定一样即可！
      1. 启动 RSH 啰！
      [root @node1 root]# chkconfig --level 35 rsh on
      [root @node1 root]# /etc/rc.d/init.d/xinetd restart

      2. 编辑可使用 R command 的主机设定档：
      [root @node1 root]# vi /etc/hosts.equiv
      server.cluster +

      特别注意，由于 RSH 预设就是不支援 root 使用 R command ，所以您必须要到 master 上面去，并以一般身份使用者进行 R command 的测试才行喔！不要直接以 root 工作，会无法成功的啦！(显示 permission deny 的啦！)

    • Master：

      • 由于 RSH Server 上面的设定中，您的 User 家目录必须要存在一个名为 .rhosts 的档案，原本我的 Server 上面就有一个名为 test 的使用者，而并且为了让我未来新建立的使用者都能够使用 R command ，所以我在 Master 这部机器上面做了这样的动作喔：
      [root @server root]# vi /home/test/.rhosts
      server.cluster
      [root @server root]# vi /etc/skel/.rhosts
      server.cluster
      [root @server root]# chmod 644 /etc/skel/.rhosts

    这样就妥当的设定好了 RSH 啰！

  • 安装 Fortran 90 的编译程式 PGI pgf90 ( PS. server version )

    •
    我由 PGI 的官方网站下载了最新的 PGI Server 套件，请特别留意的是，由于 PGI 有两种模式，一种是工作站(Workstation)一种则是伺服器(Server)模式，其中，工作站仅能提供单一主机来操作，无法进行 Cluster 的功能的！因此，请务必要下载 Server 的版本，并且是支援 Linux 版本的喔！不要搞混了！ PGI Fortran Server version 的下载网址在这个地方：http://www.pgroup.com/downloads.htm，请自行下载吧！比较需要留意的是，从上面这个网站下载的版本仅是分享软体的版本，您安装之后可以具有 15 天的免费使用期限，超过期限之后，又需要重新安装一次，很是麻烦的啦！如果您的 Cluster 是用来进行学术研究的，那么在测试完成之后，可能需要去他的网站注册，这个注册的费用差异可就很大了～因为未来我的 Cluster 需要一直不断的运作，因此是需要去注册的啦！并且，我只会用到 Fortran 这个编译器，因此，我就直接使用 PGIHPF 这个版本来测试安装而已，而不是使用全部 ( 含 PGI Fortran 与 C ) 的版本喔！因为注册的价差差了两～三万台币啊！安装 Fortran 真是很简单的啦！假设您将 linux86-HPF.tar.gz 放置在 /root/software 底下，则：(注：以下的动作仅只要在 Master 上面进行即可喔！)

    1. 建立 pgi fortran 在 /cluster/server/program/pgi 底下：
    [root @server root]# cd /usr/local/src
    [root @server src]# mkdir pgi-fortran; cd pgi-fortran
    [root @server pgi-fortran]# tar -zxvf /root/software/linux86-HPF.tar.gz
    [root @server pgi-fortran]# ./install
    接下来会有一些问题，请依序回答您的问题喔！
    至于授权嘛！请建立吧！
    最重要的地方，是在第三个问题，他会问你要安装的目录，请选择
    /cluster/server/program/pgi

    2. 修改个人参数：由于 RSH 不以 root 工作，所以我以使用者 test 来测试：
    [root @serer root]# vi /home/test/.bashrc
    # 加入这几行关于 PGI 的咚咚：
    PGI=/cluster/server/program/pgi
    export PGI
    PATH=$PGI/linux86/bin:$PATH

    3. 设定查寻路径：
    [root @server root]# vi /etc/man.config
    # 加入这一行：
    MANPATH /cluster/server/program/pgi/man

    这样就好了吗？！没错！确实是这样就完成了！很是简单吧！ ^_^要注意的是：

    • 记得 pgf90 必须要让所有的 node 都能够读的到，所以一定要安装在 Server 的分享出去的目录当中，我这里的例子就是安装在 /cluster/server/program/gpi 这个目录当中啰！
    • 执行档要能够执行，当然是必须要让目录在 PATH 这个变数底下，而我的 pgf90 是在 /cluster/server/program/pgi/linux86/bin 底下，所以，您的 PATH 必须要含有这个目录才行！

    大概就是如此啰！

  • 安装 MPICH

    •
    前面我们提过了，安装 MPICH 是平行运算里面最重要的一项工作了！因为我们就是靠他来帮我们达成运作的啊！那么怎么来安装呢？又是简单得不得了啊！首先，请先下载 mpich 吧！下载的网址在底下，我是以 mpich 1.2.5-1a 来测试的喔！

      http://www-unix.mcs.anl.gov/mpi/mpich/download.html

    假设您将 mpich 下载在 /root/software 里面，并且预计要安装到 /cluster/server/program/mpich 当中，而且仅安装 Fortran 而已的话，可以这样做：

    1. 建立 mpich 在 /cluster/server/program/mpich 底下：
    [root @server root]# cd /usr/local/src
    [root @server src]# tar -zxvf /root/software/mpich.tar.gz
    [root @server src]# cd mpich-1.2.5
    [root @server mpich-1.2.5]# ./configure --enable-debug \
    > -fc=pgf77 -f90=pgf90  \
    > --prefix=/cluster/server/program/mpich
    [root @server mpich-1.2.5]# make && make install

    2. 建立可以利用的主机状态：
    [root @server mpich-1.2.5]# cd /cluster/server/program/mpich/share
    [root @server share]# vi machines.LINUX
    node1.cluster:2
    node2.cluster:2
    node4.cluster:2
    server.cluster:2
    # 这个档案当中，格式为 <主机名称>:<主机的 CPU 个数>

    3. 建立需要的变数：(又是以 test 为准喔！)
    [root @server root]# vi /home/test/.bashrc
    # 加入这一些资料：
    PATH=$PATH:/cluster/server/program/mpich/bin
    export PATH
    MPI_HOME=/cluster/server/program/mpich
    MPI_ARCH=$MPI_HOME/bin/tarch
    export MPI_ARCH MPI_HOME
    [root @server root]# vi /etc/man.config
    # 加入这一行：
    MANPATH /cluster/server/program/mpich/man

    呵呵！这样就已经完成了 MPICH 的安装与设定了！就跟你说很简单吧！但是呢，要测试可就得需要特别留意了，因为 root 预设是不许使用 RSH 的，所以测试一定要使用一般身份的使用者，这里我以 test 这个人做为测试的使用者喔！所以，请以 test 的身份登入主机，并且，这个 test 必须要在所有的主机上面都可以被查询的到才行(请参考 NIS 的设定喔！)。

    [test @server test]$ cp -r /cluster/server/program/mpich/examples/ .
    [test @server test]$ cd examples
    [test @server examples]$ make pi3f90
    [test @server examples]$ mpirun -np 8 pi3f90
    # 上面那个 -np 后面接的就是使用 CPU 的个数啦！因为我有 8 个 node ，
    # 所以当然就以最大的 CPU 个数来测试看看，如果要看到底 CPU 有没有启动的话，
    # 可以先登入各个 slave 的主机，然后执行‘ top -d 1 ’来观察 CPU 的使用率，
    # 再执行上面这个程式，就能够知道 CPU 有没有运作了！ ^_^

    呵呵！没想到 PGI 的试用版本就能够提供多颗 CPU 的 Cluster 运作，真是给他很高兴！这样既然可以测试成功了，自然就可以去向 PGI 的官方网站注册了！注册费用不低，但是挺值得的啊！
其他主机相关设定：
    除了一些基本的 Cluster 设定之外，您的主机其实可能还需要其他的设定项目的！最常见的可能就是 X-Window System 的 server/slave 架构了！您总不希望老是呆在 cluster 前面吧？！粉吵的呢！这个时候，或许就会希望可以在 Client 端连接上 Server 的 X Server 啰！

  • X-Window Server/Slave 架构

    •
    架设一个很简单的 X Server 真的是很容易，容易到让你会很想笑出来～在上面的环境设定好了之后，请注意：‘您的主机应该是在 run-level 为三的文字模式底下，也就是没有 X Window 存在’才对！这个时候，要设定完成 X Server ，仅要修改一个档案，并且启动一支程式即可！先说明一下我的环境：

    X Server 主机的 IP 是 192.168.10.30，作业系统是 Red Hat 9；
    X Client 的 IP 是 192.168.10.100 ，作业系统同时是 Linux 与 Windows 2000 。

    • X Server 的设定：

      • 由于我们需要启动监听来自 X Client 的要求，这个时候需要重新做一下设定：
      1. 先备份原先的设定档：
      [root @server root]# cd /etc/X11/gdm
      [root @server gdm]# mv gdm.conf gdm.conf.bak

      2. 编辑设定档，只要底下两行即可！
      [root @server gdm]# vi gdm.conf
      [xdmcp]
      Enable=1

      3. 启动 gdm ：
      [root @server gdm]# gdm
      [root @server gdm]# netstat -uln
      udp        0      0 0.0.0.0:177             0.0.0.0:*
      # 如果有出现上面这行就对了！
      [root @server gdm]# echo "/usr/bin/gdm" >> /etc/rc.d/rc.local
      # 上面这行在设定开机时启动 gdm 啰！

    • X Client 的设定(在 Linux 上面)：

      • 如果您的 X Client 同样是 Linux ，那么：‘在这目前这个 Client 端连接到 X Server 端执行 X 视窗’的功能，只要进行几个步骤就可以了！
      0. 请务必要在 X Window 当中，进入 X Window 的方式有：
      [root @client root]# startx
      或
      [root @client root]# init 5

      1. 在 X Window 的画面当中，启用一个 shell ，然后输入：
      [root @client root]# xhost + 192.168.10.30
      192.168.10.30 being added to access control list
      [root @client root]# init 3 (离开 X Window)

      2. 在文字介面下输入：
      [root @client root]# X -query 192.168.10.30
      .....(进入 X Window 啰！)

    • X Client 的设定(在 Windows 上面)：

      • 如果您的 X Client 是在 Windows 上面，那么就必须要额外的来执行其他的软体了！目前您可以选择购买 Exceed 这个连线软体，或者是先‘试用’ X-Win 这个软体！都是用在 Windows 上面模拟连接到 Linux X Server 用的软体啦！我这里是以 X-Win 这套程式做为介绍的，您可以在各大学的 FTP 网站上面捉到这个软体，当然，也可以在我这里下载 5.4 版。

      http://linux.vbird.org/download/#x-win54

      1. 在 Windows 上的安装步骤，就是执行他即可啊！然后一直给他下一步就是了！

        2.
      2. 执行 X-Win32 这个程式，在出现如下的图示后，按下 Evaluation 这个试用按钮；

        3.
      3. 按下确认按钮；

        4.
      4. 在右下角的小图示当中，例如： 给他按下那个 X 啰，就会出现如下的图示：

        5.
      5. 按下 Add 之后，会出现如下的图示：

        6.
      6. 上面选择 XDMCP 这个项目，然后选择 Next 之后，会出现：

        7.
      7. 重要的地方在于 Query 这个选项，以及 192.168.10.30 这个 IP 指向喔！都设定好之后，给他 Save 一下，会出现：

        8.
      8. 上面的图示当中，给他按下确定吧！然后呢？在右下角的 X 小图示中 ( [image] ) 按一下 X 之后，就会出现刚刚我们建立的 My Linux X Server 这个选项，给他选择下去的啦，呵呵！就会出现啰：

        9. 很棒吧！这样就能在 Windows 上面连线进入 Linux 使用他的 X Window 功能啰！

    后记：虽然架设一个 X Server/Client 是很简单的一件事，不过，如果您的机器并不是在 LAN 里面的话，而是在 Internet 上面进行 Server/Client 的 X 系统架构的连结，请特别留意的是，由于 X Window 的图形介面需要一直传输图形到您的工作机上面来，如此一来，将会损耗掉大部分的频宽喔！在我的实际案例当中，发现到我的 X Server/Client 之间流量传输达到 2000 Kbits/second, 亦即是 250KBytes/second ，还记得流量的算法吧？！如果是 ADSL 拨接架构的话，目前已经蛮常见 下载/上传 = 1.5M/386K 的传输速度，不过，即使下载达到 1.5M 了，不过在我的案例中竟然高达了 2.0M 的传输！呵呵！了解吧！所以啰，这个 X Window 的 Server/Client 架构请务必在内部网路架设就好，不要想连上 Internet 啊！会等的快睡着.....
重点回顾
  • Cluster 可以是平行计算的一种，主要除了双 CPU 系统外，也可以用在多主机架构下的一种增快数值计算的方式；
  • 平行计算的 Cluster 主要是藉由主从的架构去运行的，其主要的设定都在 Master 上面设定的， Slave 主要是计算功能而已，
  • Cluster 上面相当重要的地方在于 NFS 的设定，因为 Master/Slaves 都需要读取同样的资料，所以 NFS 分享的档案资料就极其重要了；
  • 除了 NFS 之外，还需要 MPI 这个平行计算的函式库之安装，有了 MPI ，Cluster 才能真的运作起来；
  • 在 Cluster 当中，所有的主机之指令的沟通主要亦经过 RSH 的运作；
参考资源
  • Marty's Linux Cluster 架设日志：http://web.csie.chu.edu.tw/~cs87668/cluster.htm
  • 张裕麟先生的小文章：http://www.se.ntou.edu.tw/~ylchang/MyDocuments/MPICH-ins.txt
  • 国家高速电脑中心：http://binfo.ym.edu.tw/edu/seminars/200201.files/frame.htm
  • MPICH官方网站：http://www-unix.mcs.anl.gov/mpi/mpich/
简易 Cluster 架设
2003/05/12：第一次完成日期！
2003/05/20：加入了 X Server/Client 的架构！


鸟哥的 Linux 私房菜 -- DNS server

为取得较佳浏览结果，请爱用 firefox 浏览本网页

架站文件习题解答篇
最近更新日期：2003/09/20

在我们的 Linux 架站文件当中，每个章节或多或少都有些课后练习给大家复习一下！呵呵！那么各个章节的解答会在这里提供喔！

PART I 、架站前进修篇：
    第一章、架站之前所需的技能分析

  • 请简述进行网站架设前，应该具备何种基本技能？

    • 基本的技能需要有：
    1. Linux 系统操作上，至少需要了解帐号管理、档案属性与权限、程序与资源管理、硬体如硬碟之挂载与软体套件之安装如RPM套件管理员等等，而 vi 与 Shell 亦是不可忽略之基本技能，更重要者，日志的管理以及系统服务的原理(如 stand alone 与 super deamon 服务启动的方式差异等)亦需同时厘清，以方便未来架设网站时除错的技巧；
    2. 在网路的基础知识上，TCP/IP 的观念以及路由的概念相当的重要，此外，DNS 的概念也很重要。
    3. 在心态的调整上面，系统管理员需要的道德感以及使命感需要较高的标准。

  • 如果我有一颗硬碟在 A 主机上面安装了 Linux 之后，拿到另一台配备相同的 B 主机上面去进行开机，结果竟然无法顺利开机，您认为可能的原因是什么？

    • 由于配备相同，所以排除硬体的问题，不过，考虑到 IDE 排线与 partition 的代号，以及 /etc/fstab 的对应，所以应该是由于 IDE 插槽放置错误所致(Linux 系统下，每个 IDE 插槽对应的 partition 名称皆不相同喔！)。此外，上次不正常关机也可能造成硬碟损害而无法开机成功！

  • 一般来说，在 Linux 系统上，使用者预设的家目录在那个目录下？另外，新增一个使用者时，该使用者预设的家目录内容来自那个目录下？

    • 在 /etc/default/useradd 这个档案里面会规范使用者的预设家目录以及预设家目录的内容，一般来说，使用者预设家目录在 /home ，至于家目录内的档案则复制来源在 /etc/skel 里面。

  • 磁碟配额 ( quota ) 能否针对某个特定的目录进行限制？Quota 有什么较为特殊的使用限制？

    • Quota 目前仅能针对整个 partition 进行限额配置，如果该特定目录是一个 partition 那就可以进行 quota 设定，否则无法针对特定目录！此外， Quota 除了特定目录以及需要 ext2, ext3 等磁碟格式才支援之外，也需要核心的支援喔！

  • 在 Linux 系统下，要寻找一个档名为 vbird.document 的档案，可以使用什么指令进行搜寻？又，如果要寻找在一天内更动过的档案，又该如何进行？

    • 如果是执行档可以使用 which command 来搜寻，如果是档案，就必须要使用 locate vbird.document 或 whereis vbird.document 或 find / -name vbird.document 。如果要找到一天内更动过的档案，可以使用 find 配合参数，如：‘ find / -ctime 1’。

  • 在 Linux 系统中，常见的套件管理员有 RPM 与 Tarball ，请分别说明这两个套件管理员的优缺点。
    • RPM 套件管理员在安装套件的时候，会将该套件的档案名称、套件功能与讯息等等资讯记录于 /var/lib/rpm 目录内，由于有这些套件的资本资讯，因此在系统内很容易进行 RPM 的升级、安装、移除等动作。不过，由于 RPM 档案之间的相依性相当的强，因此常常会有版本不合或者是欠缺某样前驱套件的问题发生。
    • 至于 Tarball 则是原始码，使用者可以自行设定套件的编译参数，以符合自己的 Linux 平台。此外，由于 Tarball 是原始码，因此需要在您的系统上面进行编译，编译的过程中需要 gcc, make, 以及 kernel source 等套件，还有您所想要安装的套件所需要的前驱套件也同时需要先安装后，才能进行 Tarball 的安装。注意，几乎每个 Tarball 以 tar 程式解开后，在新增的目录下均会有 README 以及 INSTALL 档案，请务必先查阅过后才进行编译工作。

  • 如果我下载了一个档名为 httpd-2.0.52.tar.gz 的档案，一般来说，这个档案代表的意义为何？我该如何让这个档案能够在我的 Linux 系统上面安装？

    • 由于附档名是 .tar.gz 或者是 .tgz 的档案，所以可以认定该档案为一个 Tarball 的档案。至于档名的配置方面，httpd 为套件名称，2.0.52 则通常为该套件的版本名称了！那如何安装？由于该档案为 httpd 这个套件，且格式为 Tarball ，所以您必须要：
    1. 系统上面务必具有 tar, make, gcc 等相关的编译套件；
    2. 使用 tar 解开 httpd-2.0.52.tar.gz 之后，务必进入该目录内读取 REAME 或/与 INSTALL 档案，以了解是否还需要其他的相关套件的搭配安装；
    3. 以 ./configure --help 查阅一下是否有相关可以加入或者取消的编译内容；
    4. 使用 make 读取 Makefile 来编译程式；
    5. 使用 make install 来安装程式！

  • 我以原始码的方式进行一个套件的安装，但是在分析系统的时候，分析程式一直告诉我找不到 cc 这个指令，请问这是什么问题？为何需要 cc ？又，我该如何解决这个问题，好让套件可以顺利的被安装在我的 Linux 上面？

    • 如前面几个题目所说的，因为是原始码，所以还需要编译程式来将该原始码编译成为可以在您的 Linux 系统上面跑的 binary 档案，在 Linux 上头预设的编译程式就是 gcc 这个编译器(compiler)。如果您在安装 Linux 的时候，使用 Linux Installer 预设的套件选择，那通常会没有安装 gcc 以及 make 等套件，此时，请拿出您的原版光碟，以 mount 指令挂载后，使用 RPM 将一个一个相关的套件安装即可(过程会蛮复杂的！)^_^

  • 我发现我的 Linux 系统怪怪的，似乎有什么不知名的程序在记忆体当中跑，我该如何将这个不知名的程序捉出来，并且将他移除？

    • 如果要捉出程序(process)的话，可以使用 ps -aux 或者是直接输入 top 来查询 process 的 ID (PID)，找到 PID 号码后，再以 kill -9 PID 来删除该程序即可。

  • 我总是无法编辑某个档案，您认为应该是什么问题造成的？那又要怎么解决？

    • 无法编辑某个档案，可以先使用 file 这个指令来查询一下该档案的格式，例如想察看 /etc/shadow 的格式，可以下达：‘file /etc/shadow’，如果是文字档，却还是无法编辑，那么最可能发生的原因就是‘权限’的问题了。可以使用 ls -l filename 察看档案权限，再以 chmod 或 chown 来修订该档案的权限。此外，该档案也可能含有隐藏属性，可以使用 lsattr filename 查阅，再以 chattr 来修订隐藏属性。

  • 什么是 UID 与 GID ？UID 有哪些等级？

    • 在 Linux 系统下，使用者与群组其实都是以‘ID(数字)’的格式来设定的，所以使用者与群组其实都是 UID 或 GID (User ID 与 Group ID)，Linux 对于档案权限也都是使用 UID/GID 来分辨。不过人类习惯使用文字来记忆，所以才会有 /etc/passwd 与 /etc/group 来转译 ID 与 User 及 Group 之间，这也才会发生为何在 Internet 上面捉下来的 Tarball 解开之后，往往会有档案拥有人与群组为数字的型态，因为您 Linux 系统上面的 /etc/passwd 与 /etc/group 没有相关的对应文字说。至于 UID 的等级主要有两种，分别是超级管理员(root)，其 UID 为 0，其他非为 0 的 UID 基本上身份是相同的！不过 Linux 通常会将小于 500 的 UID 保留给系统使用。

  • 使用者的家目录参数、UID、GID以及其他相关参数，还有密码档案，放置在哪些档案里面？

    • 放置在 /etc/passwd 与 /etc/shadow 当中。当然还有 /etc/login.defs 喔！

  • 你认为一个称职的网管人员应该具备什么能力？

    • 能力需求相当高，如了(1)作业系统的基础知识(不论是 Linux/Unix/MAC/MS)；(2)网路基础的知识；(3)个别 Internet Services 的运作知识之外，还需要(4)身心保持在备战状态，以及(5)具有相当高程度的道德感、责任感与使命感。

  • 我要启动一个系统预设的 Service，请问我可能可以由执行或修改哪些目录底下的档案来启动？

    • 如果是 stand alone 的服务，可以经由 /etc/rc.d/init.d/* 里面的档案，如 /etc/rc.d/init.d/syslog start；
    如果是 Super daemon 的服务，就必须(1)先到 /etc/xinetd.d 或者是 /etc/inetd.conf 修改相关档案或参数；(2)以 /etc/rc.d/init.d/xinetd restart 来启动。

  • 我要关掉 cron 这个服务，应该怎么关掉他？如果正常的方法无法关闭这个服务，可以使用什么方法来关闭？

    • 因为 cron 是一个 stand alone 的服务，所以可以使用 /etc/rc.d/init.d/cron stop 来关闭；如果还是无法正常关闭，可以使用 ps -aux | grep cron 捉出该程序的 PID ，然后以 kill -9 PID 来关闭。

  • 如果一开机就要执行某个程式，应该要将该程式写入那个档案里面？

    • 可以直接在 /etc/rc.d/rc[run-level].d 里面加入 S 开头的档案，不过，更简单的作法是直接将该程式写入 /etc/rc.d/rc.local ，不过，请注意该程式必须要具有可执行的权限，且 rc.local 也必须要是可执行喔！

    第二章、简易网路基础架构

  • 请简述 OSI 网路七层协定每一层的功能；

    • OSI 网路七层协定主要又分为两大部分，网路层与使用者应用层两部份。至于每一层的相关功能请参考本章节的表一所示。

  • 在 ISP 提供的网路服务中，他们提到传输速度为 1.5M/382K ，请问这个数据的单位为何？

    • 由于电子讯号的基本单位为 bits ，所以一般 ISP 提供的传输速度单位均为 bits/second ，并非我们常用的档案计数单位 Bytes ！

  • 什么是 MAC ( Media Access Control ) ，MAC 主要的功能是什么？

    • 在网路媒体上面，资料要传输时，必须知道下一个节点的位址才能顺利传送，这个节点的位址如网路卡的硬体位址就是 MAC 了。硬体位址是在网路卡出厂时就已经焊死在上面了(某些笔记型电脑的 MAC 则可以经由特殊软体修改)，而软体位址，则是我们常说的 IP ，这两个并不相同喔！其中，MAC 与 IP 互相的对应则是以 ARP Table 来进行转译的！

  • 请解释什么是物理广播 ( Physical Broadcast ) ，他与逻辑广播 ( Logical Broadcast ) 有什么不同？

    • 物理广播主要与网路媒体有关，在同一个网路媒体上面同一时间仅能有一部主机来使用这个网路共享媒体，而要判断目前有没有其他主机在使用这个网路媒体时，就是利用Physical Broadcast 咯！
    至于逻辑广播呢？呵呵！就是在查询到底网域上面有没有我们这部主机想要连接的相关协定或者同一网域内的其他主机了！他则主要与 MAC, ARP 以及软体位址(通称的 IP)有关啦！

  • 什么是封包碰撞？为什么会发生封包碰撞？

    • 当两部主机同时在一个网路媒体上面进行资料传输时，两个资料封包就会发生碰撞的情况，这就是封包碰撞了。在网路媒体流量很高、网路媒体的连线长度过长都会容易发生资料封包碰撞的情况。

  • ARP Table 的作用为何？如何在我的 Linux 察看我的 ARP 表格？

    • ARP Tables 主要在对应 IP 与 MAC ，当主机要将资料封包送出到下个节点时，必须要知道下个节点的 MAC 才能传送，而如果不知道 MAC 时，就得需要使用逻辑广播来查询 IP 与 MAC 的对应才行。不过，当您的主机内部的 ARP table 已经记录了 IP 对应的 MAC 之后，那么该资料封包则可以立即传送到下个节点去，而不需要再次的进行逻辑广播了。要知道目前的 arp table 内有多少纪录，可以使用 ‘ arp -a ’来查询。

  • 简略说明 Netmask 的作用与优点；

    • Netmask 可以有效的增加网路的效率，这是因为 Netmask 可以定义出一个网域的大小，那么 broadcast 的时间就可以降低很多！一般来说，我们如果要将一个大网域再细分为小网域，也需要藉由 Netmask 来进行 subnet 的切割。

  • 我有一组网域为： 192.168.0.0/28 ，请问这个网域的 Network, Netmask, Broadcast 各为多少？而可以使用的 IP 数量与范围各是多少？

    • 因为共有 28 个 bits 是不可动的，所以 Netmask 位址的最后一个数字为 11110000，也就是 (128+64+32+16=240) ，所以：
    Network：192.168.0.0
    Netmask：255.255.255.240
    Broadcast：192.168.0.15
    IP：由 192.168.0.1 ~ 192.168.0.14 共 14 个可用 IP 喔！

  • 承上题，如果网域是 192.168.0.128/29 呢？

    • 因为是 29 个 bits 不可动，所以最后一个 Netmask 的位址为： 11111000 也就是 (128+64+32+16+8=248)，所以：
    Network：192.168.0.128
    Netmask：255.255.255.248
    Broadcast：192.168.0.135
    IP：由 192.168.0.129 ~ 192.168.0.134 共 6 个可用的 IP 喔！

  • 我要将 192.168.100.0/24 这个 C Class 的网域分为 4 个子网域，请问这四个子网域要如何表示？

    • 既然要分为四个网域，也就是还需要藉助 Netmask 的两个 bits (2的2次方为4啊！)，所以 Netmask 会变成 255.255.255.192 ，每个子网域会有 256/4=64 个 IP ，而必须要扣除 Network 与 Broadcast ，所以每个子网域会有 62 个可用 IP 喔！因此，四个子网域的表示方法为：
    192.168.100.0/26, 192.168.100.64/26, 192.168.100.128/26, 192.168.100.192/26。

  • 如何观察 Linux 主机上面的路由资讯 ( route table )？

    • 路由资讯的观察可以下达 route 来直接察看！或者是下达 route -n 亦可！

  • TCP 封包上面的 SYN 与 ACK 标志代表的意义为何？

    • SYN 代表该封包为该系列连线的第一个封包，亦即是主动连线的意思；
    ACK 则代表该封包为确认封包，亦即是回应封包！

  • 什么是三向交握？在哪一种封包格式上面才会有三向交握？

    • 使用 TCP 封包才会有三向交握。TCP 封包的三向交握是一个确认封包正确性的重要步骤，通过 SYN, SYN/ACK, ACK 三个封包的确认无误后，才能够建立连线。至于 UDP 封包则没有三向交握喔！

    第三章、区域网路架构简介

  • 幻想自己是一个私人公司的老板，员工有 20 人，如果我想要让公司的员工都可以连上 Internet ，并且控管每个员工的对外连线，请问我的硬体连线应该怎么配置比较好？另外，应该申请的线路频宽应该多大较佳？而我的内部网域 ( IP, Netmask, ....) 又该如何设定比较好？

    • 因为只有 20 个员工，事实上，人员并不多，所以并不需要在内部加设 router 来隔开不同的网域。不过，由于想要管理员工的上网功能，因此最好以第三章图三的架构，以一部主机内含两块网路卡隔开 Intranet 与 Internet 两个网段，便于管理；至于对外连线的频宽方面，如果 Linux 主机需要进行网路服务的功能，那么最好能够有 512/512 的频宽，因为可能会有 Client 端下载的问题，至于如果单纯的仅下载时(公司没有额外的网路服务)，可以考虑使用 T1/384 之类的频宽，比较省钱；而在内部网域设定上，如同本章节使用的网域 192.168.0.0/24 来设定即可，如果公司内部尚有移动装置(NoteBook)，则可以在 Linux 上加装 DHCP (参考十六章)伺服器。

  • 承上题，假如我的私有网域内有较大的网路流量，那么我的网路媒体应该怎么选择较佳？

    • 如果私有网域内的流量较大，那么网路媒体需要选择 Switch 而不要使用 Hub ！另外，整体包括网路线也都需要使用能够负载 10/100 Mbps 的流量才好。

    第四章、连上 Internet

  • 我要如何确定我在 Linux 系统上面的网路卡已经被 Linux 捉到并且驱动了？

    • 网路卡能不能被捉到可以使用‘ dmesg|grep eth ’来判断，有没有驱动则可以使用 lsmod 看看模组有没有载入核心！最后，以 ifconfig eth0 192.168.0.10 测试看看！

  • 假设我的网路参数为：IP 192.168.100.100, Netmask 255.255.255.0, 请问我要如何在 Linux 上面设定好这些网路参数 (未提及的网路参数请自行定义！)？请使用手动与档案设定方法分别说明。
    • 手动设定为：‘ ifconfig eth0 192.168.100.100 netmask 255.255.255.0 up ’
    • 档案设定为：vi /etc/sysconfig/network-scripts/ifcfg-eth0 ，内容为：
        • DEVICE=eth0
        ONBOOT=yes
        BOOTPROTO=static
        IPADDR=192.168.100.100
        NETMASK=255.255.255.0
        NETWORK=192.168.100.0
        BROADCAST=192.168.100.255
      要启动则使用 ifup eth0 即可！

  • 我要将我的 Linux 主机名称改名字，步骤应该如何(更改那个档案？如何启用？)？

    • Linux 主机名称在 /etc/sysconfig/network 这个档案里面的‘HOSTNAME=主机名称’来设定，先以 vi 来修改，改完后可以使用 /etc/rc.d/init.d/network restart 或者直接 reboot 启动主机名称！

  • /etc/resolv.conf 与 /etc/hosts 的功能为何？

    • 以主机名称寻找 IP 的方法， /etc/resolv.conf 内填写 DNS 主机名称，至于 /etc/hosts 则直接填写主机名称对应的 IP 即可！

  • 我使用 ADSL 拨接连上 Internet ，请问拨接成功之后，我的 Linux 上面会有几个网路介面 (假设我只有一个网路卡)？

    • 因为拨接是使用 PPP (点对点)协定，所以拨接成功后会多出一个 ppp0 的介面，此外，系统原本即有 eth0 及 lo 这两个介面，所以共有三个介面。

  • 在 Linux 上面进行 ADSL 拨接应该使用什么软体？

    • 请爱用 rp-pppoe ，官方网站： http://www.roaringpenguin.com/pppoe/

  • 一般来说，如果我拨接成功，也取得了 ppp0 这个介面，但是却无法对外连线成功，您认为应该是哪里出了问题？该如何解决？

    • 因为拨接成功了，表示物理对外连线没有问题，那么可能的问题应该是发生在 Gateway 上面了！确认的方法请使用 route -n 查阅路由资讯，然后修订 /etc/sysconfig/network-scripts/ifcfg-eth0 吧！

    第五章、Linux 常用网路指令介绍

  • 我要增加一个路由规则，以 eth0 连接 192.168.100.0/24 这个网域，应该如何下达指令？

    • 以手动的方法为：‘route add -net 192.l68.100.0 netmask 255.255.255.0 dev eth0’即可！

  • 我的网路停顿的很厉害，尤其是连接到 tw.yahoo.com 的时候，那么我应该如何检查那个环节出了问题？

    • 使用 traceroute 寻找到底那个环节出问题：‘traceroute tw.yahoo.com’即可！

  • 我发现我的 Linux 主机上面有个连线很怪异，想要将他断线，应该如何进行？

    • 以 root 的身份进行‘netstat -anp |more’查出该连线的 PID，然后以‘ kill -9 PID ’踢掉该连线。

  • 您如何知道 green.ev.ncku.edu.tw 这部主机的 IP ？

    • 方法很多，可以利用 host green.ev.ncku.edu.tw 或 dig green.ev.ncku.edu.tw 或 nslookup green.ev.ncku.edu.tw 等方法找出！

  • 请找出您的机器上面最适当的 MTU 应该是多少？

    • 请利用‘ping -c 3 -M do -s MTU yourIP ’找出您的 IP 的 MTU 数值。

  • 如何在终端机介面上面进行 WWW 浏览？又该如何下载 WWW 上面提供的档案？

    • 要浏览可以使用 lynx ，至于要下载则使用 wget 这个软体。如果想要在终端机上面看到中文，还可以安装 JCMME 。

  • 在终端机介面中，如何连接 bbs.sayya.org 这个 BBS ？

    • 利用 telnet bbs.sayya.org 即可连接上，同样的，要看到中文，还是得安装 JCMME 。
PART II、主机的简易防火措施篇
    第七章、限制 Linux 对外连线的埠口

  • 如何观察您 Linux 主机上面已经有多少 port 被打开了？

    • 如果仅想单纯了解正在 LISTEN 当中的埠口，可以使用‘netstat -tul’，如果还想知道有多少连线已经建立，可以使用‘netstat -an’来察看。

  • 如何观察程序？

    • 利用‘ps -aux’，或者是 top 来察看均可。

  • 请问 LISTEN 的 port 与 daemon 的关系为何？

    • 正在 LISTEN 当中的埠口均是由某些服务(daemons)所启动的，所以要启动埠口就得启用某个服务，要了解某个埠口是由那个 daemon 所启动的，就利用 netstat -tulp 来查阅。

  • 请解释三向交握的原理与封包传输的方向。

    • 三向交握为较为可靠的封包传输的一种确认方式，因此只有 TCP 封包才能具有三向交握。他利用(1) client 对 Server 主动连线时带有的 SYN 标志，(2)Server 回应时的 SYN/ACK 及(3)最终 Client 确认的 ACK 标志来确认封包的可靠性。更详细说明请参考第二章 TCP 与三向交握。

  • 请问 stand alone 与 super daemon 各是什么？

    • Linux 系统的服务有独立启动(stand alone)及超级服务员(super daemon)两种启动的方式。挂在 super daemon 底下的服务可以经由 super daemon 的控管，以加强一些安全功能，不过由于还要经过 super daemon 的管理，所以服务的连接速度上会比 stand alone 慢一点。详细的说明请参考‘鸟哥的 Linux 私房菜 -- 基础学习篇’第二十一章‘认识系统服务’内的相关说明吧！

  • 请问您的 Linux 主机 (不论是那个 distributions ) 有关 daemon 启动与关闭的 scripts 与档案放置在那个目录下？

    • 各个 daemons 的启动与关闭的 scripts 是放置在 /etc/rc.d/init.d 里面，至于 super daemon 的控管参数档案则在 /etc/xinetd.d 里面！

  • 请将您的 linux 主机对外的连线埠口全部关闭！

    • 请参考本章节的作法！利用 ntsysv 或者 chkconfig 等功能加上 reboot ，或者 netstat 配合 kill 的方式！

    第八章、Linux 网路套件升级

  • 请依照您的 Linux 系统进行适合的网路套件升级程序(一个步骤一个步骤写下来)，并说明为何您需要选择这样的网路升级程序？

    • 这题请参考本章节的内容，选择 APT 或者是其他 Linux distributions 网站提供的线上升级方式来进行您的套件升级。

    第九章、多 IP 与 Router 的架设

  • 请问您如何将您的 eth0 这个介面修改成为 192.168.100.2 在网域 192.168.100.0/25 之内的网路参数内容？

    • 因为 192.168.100.0/25 的 netmask 为 255.255.255.128 ，所以可以这样做：‘ifconfig eth0 192.168.100.2 netmask 255.255.255.128 up ’这样即可！如果尚须其他的参数，则需要以档案形式来下达，如 vi /etc/sysconfig/network-scripts/ifcfg-eth0，并修改为：
      DEVICE=eth0
      ONBOOT=yes
      BOOTPROTO=static
      IPADDR=192.168.100.2
      NETMASK=255.255.255.128
      NETWORK=192.168.100.0
      BROADCAST=192.168.100.127

  • 请手动设定 eth0:1 这个虚拟介面，使成为网路参数： 192.168.200.2, 网域在 192.168.200.0/24。

    • ifconfig eth0:1 192.168.200.2 up

  • 如何观察路由表？

    • route -n 即可查阅！注意到 0.0.0.0 那个目标(default gateway)。

  • 如何启动 Linux 的 IP Forward 功能？

    • 直接以‘echo "1" > /proc/sys/net/ipv4/ip_forward ’即可！

  • 假设您是一个学校单位的资讯管理员，学校内有 200 部电脑，奉上面大头的旨意，必须要将 200 部电脑分为 4 个 Subnet ，请问您应该如何布线(请画出示意图)？而这 4 个 Subnet 的网路参数如何选择(请自行选择)？而是否需要 Router ？如果需要的话，假设每个 Router 仅能有两个网路实体介面，那么该如何布线？(注：不要使用虚拟介面)

    • 我的布线如同下图所示：

    每个 Router 都具有两个介面，且四个 Router 的右边介面都在同一个网段内！那么 Router 1 怎么跟 Router 2 的内部网域进行沟通？利用：‘route add -net 192.168.2.0 netmask 255.255.255.0 gw 192.168.5.2’即可！

  • 万一您的网路有点停顿，发现可能是网路上某个节点出现问题，您应该如何确认是哪一部 Router 出问题？

    • 使用第五章Linux 常用网路指令当中提到的 traceroute 来查询！

    第十章、认识网路安全

  • 我老是发现我的系统怪怪的，似乎有点停顿的模样，怀疑可能是 CPU 负荷太大，所以要去检查一下系统相关的资讯。请问，我该以什么指令去检查我的系统相关的资讯？

    • 可以使用 top, sar, free, ps -aux, uptime, last 等功能去查询系统的相关资讯喔！

  • 我怀疑我的系统上面有过多的具有 SUID 的档案存在，导致一般使用者可以随意的取得 root 的权限，请问，我要如何找出这些具有 SUID 权限的档案？

    • 因为 SUID 是 4000 这个权限的模样，所以我可以这样做：
    find / -perm +4000

  • 我由国内一些 ftp 网站上下载了 Red Hat 公司释出的套件，我想安装他，但又不知道该套件档案是否被修改过！请问我该如何确定这个套件的可用性？

    • 利用最简易的 MD5 编码来测试一下，例如‘ md5sum 套件名称’，再比对与原始套件释出的 MD5 数据是否相同！？

  • 良好的密码规划是防备主机的第一要务，请问 Linux 系统当中，关于密码相关的档案与规则设定在哪些档案里面？

    • 密码的设定规则在 /etc/login.defs 里面！至于密码档案在 /etc/shadow 内！

  • 简易说明，当一部主机被入侵之后，应该如何处理？

    • 找出问题、重新安装、漏洞修补、资料还原！请参考本章最后面的‘修补工 0240network-secure-1.php#repaire 作’内容！

    第十一章、简易 Firewall 架设

  • 为什么我架设了防火墙，我的主机还是可能中毒？

    • 防火墙不是万灵丹，他还是可能被病毒或者是木马程式所入侵的！此外，如果您的主机本身就已经提供了多个网路服务，则当该网路服务的套件有漏洞时，防火墙仍然无法克服该服务的漏洞的！因此仍然需要持续的进行主机的监视工作！

  • 请说明为何架设了防火墙，我的主机还是可能被入侵？入侵的依据可能是什么方法？

    • 因为防火墙仅是抵挡某些不受欢迎的封包，如果您有开放 WWW 的服务时，则要求您主机 port 80 的封包将可直接进入您的主机，万一 WWW 套件有漏洞时，那么就可能被入侵了！所以套件的更新很重要！

  • 我们知道核心为 2.4 的 Linux 使用的防火墙机制为 iptables ，请问，如何知道我的 Linux 核心版本？

    • 利用 uname -r 可以查得！

  • 请列出 iptables 预设的两个 table ，以及各个 table 里面的 chains 与各个 chains 所代表的意义；

    • filter 为预设的 Table，里头预设的链有：
    • INPUT：为来自外部，想要进入主机的封包；
    • OUTPUT：为来自主机，想要离开主机的封包；
    • FORWARD：为主机内部网域与外部网域的封包(不论进或者出)，但该封包不会进入主机。
    还有 nat 这个 table：
    • PREROUTING：进行路由之前的封包传送过程
    • OUTPUT：离开主机的封包传送过程；
    • POSTROUTING：已经经过路由了，然后才进行的过滤规则。

  • 什么是 iptables 的预设政策 (Policy)？

    • 当封包的所有属性都不在防火墙的规则当中时，那么这个封包能否顺利的通过防火墙，则以 Policy 作为这个封包的最终动作了！

  • 假设今天我的 Linux 仅是作为 Client 之用，并没有对 Internet 进行任何服务，那么您的防火墙规划应该如何设定比较好？！

    • 既然没有对 Internet 提供任何服务，那么(1)请将所有的对外埠口先关闭吧！(2)防火墙规则当中，最重要的是 INPUT 的 Policy 一定要 DROP ，然后将‘ iptables -A INPUT -m state --state RELATED -j ACCEPT ’即可！

  • 我要将来自 192.168.1.50 这个 IP 来源的封包，只要是向我的 21~23 埠口要求的封包，就将他抵挡，应该如何下达 iptables 指令？

    • iptables -A INPUT -p tcp -s 192.168.1.50 --dport 21:23 -j DROP

  • 我要将我自己主机 ping 的回应功能取消，应该如何下达 iptables 的指令？

    • 因为 ping 能否回应用的是 icmp 的 type 8 (请参考第二章 网路基础 内的 ICMP 相关内容)，所以我可以这样做：
    iptables -I INPUT -p icmp --icmp-type 8 -j DROP

  • 请说明为何这个指令是错误的？‘iptables -A INPUT -p udp --syn -s 192.168.0.20 -j DROP’？

    • 因为只有 TCP 封包才会具有 SYN 的标志， UDP 并没有 SYN 的标志啊！所以上面的指令是错误的！

  • DNS 的要求是必须的，那么我该如何设定我的主机可以接受要求 DNS 的回应呢？

    • 因为 DNS 的来源是 port 53 ，因此要接受来自 port 53 的封包就成为了：
    iptables -A INPUT -p udp --sport 53 -j ACCEPT
    iptables -A INPUT -p tcp --sport 53 -j ACCEPT

  • 如何取消 iptables 在我的系统上面？

    • 先要清除规则后，才能够将 iptables 移除！不过，我们主要将规则清除即可！
    iptables -F; iptables -X; iptables -Z
    iptables -t nat -F; iptables -t nat -X; iptables -t nat -Z

  • 如何储存目前的防火墙机制，以及如何将上次储存下来的机制回复到目前的系统中？

    • 请利用 iptables-save 以及 iptables-restore 这两个指令，配合命令重导向即可！

    第十二章、申请合法的主机名称

  • 请简易说明 /etc/hosts 的用途；

    • 这个档案是早期用在进行主机名称与 IP 的解析的，目前比较常用在内部网域的名称解析上，可以加快内部网域的反查喔！

  • 请说明‘合法授权’的主机名称需要做什么？

    • 如果想要合法授权，就需要向上层 DNS 主机‘注册’才行！而且还要上层 DNS 主机管理员愿意将领域名称的解析权限授权给您啊！

  • 什么是动态 DNS 系统？(仅说明 client 端)

    • 因为我们的 Client 拨接时，得到的 IP 都不是固定的，所以无法以 DNS 系统进行固定 IP 对应主机名称的工作！此时就需要动态 DNS 系统了！以 DNS 主机提供的动态更新主机名称对应 IP 的机制，可以让我们的不同 IP 对应到同一个主机名称呐！

  • 如果您使用 adsl 拨接来上网设定伺服器，那么该申请哪一类型的主机名称？为什么？

    • 因为我是以 ADSL 上网拨接，所以 IP 是不固定的，此时需要申请动态 DNS 主机的主机名称，例如 adsldns.org 以及 no-ip.org 等等！

PART III、各类伺服器架设篇：
    第十三章、简易 Telnet 与 SSH 主机设定

  • Telnet 与 SSH 都是远端连线伺服器，为何我们都会推荐使用 SSH 而避免使用 Telnet 呢？原因何在？

    • 因为 Telnet 除了使用‘明码’传送资料外，本身 telnet 就是很容易被入侵的一个伺服器，所以当然也就比较危险了。至于 ssh 其实也不是很安全的！由台湾电脑危机处理小组的文件可以明显的发现 openssl + openssh 也是常常有漏洞在发布！不过，比起 telnet 来说，确实是稍微安全一些！

  • 请尝试说明 SSH 在 Server 与 Client 端连线时的封包加密机制；

    • 利用 key pair 来达到加密的机制：Server 提供 Public Key 给 Client 端演算 Private key ，以提供封包传送时的加密、解密！

  • 请问 SSH 的设定档是哪一个？如果我要修改让 root 无法使用 SSH 连线进入我的 SSH 主机，应该如何设定？又，如果要让 badbird 这个使用者无法登入 SSH 主机，该如何设定？

    • SSH 设定档档名为 sshd_config ，通常放置在 /etc/ssh/sshd_config 内；如果不想让 root 登入，可以修改 sshd_config 内的参数成为：‘PermitRootLogin no ’，并重新启动 ssh 来设定！如果要让 badbird 使用者无法登入，同样在 sshd_config 里面设定为：‘DenyUsers badbird’即可！

  • 在 Linux 上，预设的 Telnet 与 SSH 伺服器使用的埠口(port number)各为多少？

    • telnet 与 ssh 的埠口分别是：23 与 22！请参考 /etc/services 喔！

  • 如果发现我无法在 Client 端使用 ssh 程式登入我的 Linux 主机，但是 Linux 主机却一切正常，可能的原因为何？(防火墙、known_hosts...)

    • 无法登入的原因可能有很多，最好先查询一下 /var/log/messages 里面的错误讯息来判断，当然，还有其他可能的原因为：
    1. 被防火墙挡住了，请以 iptables -L -n 来察看，当然也要察看 /etc/hosts.deny；
    2. 可能由于主机重新开机过， public key 改变了，请修改您的 ~/ssh/known_hosts 里面的主机 IP ；
    3. 可能由于 /etc/ssh/sshd_config 里面的设定问题，导致您这个使用者无法使用；
    4. 在 /etc/passwd 里面，您的 user 不具有可以登入的 shell ；
    5. 其他因素(如帐号密码过期等等)

  • 既然 ssh 是比较安全的资料封包传送方式，那么我就可以在 Internet 上面开放我的 Linux 主机的 SSH 服务了吗？！请说明您选择的答案的原因！

    • 最好不要对 Internet 开放您的 SSH 服务，因为 SSH 的加密函式库使用的是 openssl ，一般 Linux distribution 使用的 SSH 则是 openssh ，这两个套件事实上仍有不少的漏洞被发布过，因此，最好不要对 Internet 开放，毕竟 SSH 对于主机的使用权限是很高的！

    第十四章、简易 NAT 伺服器

  • 请简单的说明 NAT 主机的用途与运作原理。

    • NAT 主机的最大用途在于‘封包伪装’，可以做为内部 Client 主机对外的连线之用(类似 IP 分享器)，当然，也可以做为区域内主机 (DMZ) 的设定！至于其运作原理则主要以 iptables 的过滤机制有关，利用 iptables 来将通过的封包进行 Source IP 或 destination IP 的伪装！

  • 假设我是您公司的上层主管，我知道我们单位内共有 100 部电脑 (Windows 作业系统)，其中共分为两大部门，这两大部门的资料是互相独立的，并且两大部门各自拥有一部 Linux 主机在负责档案分享的工作(就是未来会谈到的 SAMBA 主机)。不过，我们公司仅有一条对外的 ADSL 双向 512 的专线而已。现在，我命令您规划全公司 100 部电脑都可以连上 Internet ，而且只多给您一部 Linux 主机，并且原有的 Linux 主机功能 ( 就是 SAMBA 啦 ) 还是存在。请问：
    1. 公司的网路规划的示意图如下所示：

      2. 两边的 LAN 并没有互相物理连接，此外，微型电脑为本来的 Linux 主机，而新增一部 Linux 主机则是‘伺服器’那一部！
    2. 多出来的那一部 Linux 主机用途为 ADSL 连接与内部私有网路的连接，该 Linux 的网路参数：‘IP为192.168.0.254(对内)，对外为拨接所产生的介面！启动 NAT 功能’！
    3. 两部 Linux SAMBA 主机的网路参数为：‘部门A：IP为192.168.1.254(对内卡)以及192.168.0.1(对外卡)，新增 route add -net 192.168.2.0 netmask 255.255.255.0 gw 192.168.0.2’，‘部门B：IP为192.168.2.254(对内卡)以及192.168.0.2(对外卡)，新增route add -net 192.168.1.0 netmask 255.255.255.0 gw 192.168.0.1’，两部主机的 Gateway 都是192.168.0.254。
    4. 两个部门的网路参数：‘部门A，Network:192.168.1.0/24，Gateway:192.168.1.254’、‘部门B，Network:192.168.2.0/24，Gateway:192.168.2.254’。

    第十五章、简易 NFS 伺服器设定

  • NFS 的主要设定档为何？而在该档案内主要设定项目为何？

    • 主要的设定档为 /etc/exports 而至于其设定的内容项目在每一行当中则为：
    1. 分享的目录
    2. 针对此分享目录开放的主机或 IP或网域
    3. 针对这部主机所开放的权限参数！

  • 在 NFS 主要的设定档当中仅有少许的参数说明，至于预设的参数说明则没有在该档案当中出现，请问，如果要查阅更详细的分享出来的档案的属性，要看那个档案？

    • 要查阅 /var/lib/nfs/xtab 这个档案才行！

  • 如果已经启动了 nfs 这个伺服器，但是却又修改过主要设定档，请问可以使用那个指令来重新挂载分享出来的目录与 client 端权限的设定值？

    • 透过使用 exportfs ，可以加上 -a 或者是 -rv 这两个参数来重新挂载！如 exportfs -rv

  • 在 client 端如果要挂载 NFS 所提供分享的档案，可以使用那个指令？

    • 那自然就是 mount 啦！还有卸载是 umount 喔！

  • 在 NFS 主要设定档当中，可以透过那个参数来控制不让 client 端以 root 的身份使用您所分享出来的目录与档案？

    • 可以在 /etc/exports 当中的参数项目，设定‘ root_squash ’来控制压缩 root 的身份喔！

  • 我在 client 端挂载了 NFS Server 的某个目录在我的 /home/data 底下，当我执行其中某个程式时，却发现我的系统被破坏了？您认为可能的原因为何？该如何克服这样的问题，尤其是当我的 Client 端主机其实是多人共用的环境，怕其他的使用者也同样发生类似的问题呢？！

    • 可能由于您挂载进来的 NFS Server 的 partition 当中具有 SUID 的档案属性，而您不小心使用了该执行档，因此就可能会发生系统被破坏的问题了！
    可以将挂载进来的 NFS 目录的 SUID 功能取消！例如：
    mount -t nfs -o nosuid,ro server:/directory /your/directory

    第十六章、简易 DHCP 伺服器设定

  • DHCP 的主要用途为何？

    • DHCP 主机的主要用途就是在于自动分配网路参数给 Client 端的电脑，以降低网域当中可能发生的 IP 冲突问题，以及减少网管人员到处检查错误的伤脑筋！

  • DHCP 主要的两种 IP 分配模式为何？

    • 主要的两种分配模式分别为 Dynamic IP 与 Static IP ， Static IP 透过 MAC 的比对，至于 Dynamic IP 则是直接取用网域中尚未被使用到的 IP 来进行 Client 端的分配。

  • 在有 DHCP 主机存在的网域当中，且 client 端亦使用 DHCP 来规划用户端的网路参数，那么请问，在该网域当中，Client 端是如何取得 IP 的呢？？
    1. 首先， Client 端会发出一个 DHCP 要求封包；
    2. Server 端接收到要求后，会主动的回应资讯给 Client ；
    3. Client 若接受该 DHCP 主机所提供的参数，则主机会记录下租约资讯，至于 client 端则开始以主机提供的参数设定其网路；

  • DHCP 是如何发送 Static IP 的？可以使用何种指令取得该资讯？

    • DHCP 主要利用网路卡的硬体位址，亦即俗称的‘网路卡卡号’，也就是 MAC 来进行 Client 端的比对的，至于主动取得 Client 端的方式，可以透过 ping 以及 arp 来获得。

  • 在 DHCP 的租约档，亦即 /var/lib/dhcp/dhcpd.leases 当中，记录了什么资讯？

    • 这个档案主要记录了 Client 端连上 Server 端的纪录资料，他会被 DHCP 主机用来判定与 Client 端的租约行为喔！

  • DHCP 的登录档放置于何处？

    • 就是最重要的 /var/log/messages 这个档案啦(预设状况下！)

    第十七章、简易 DNS 伺服器设定

  • 为何要有 DNS 系统：

    • 最主要的功能其实在于 Hostname 对应 IP 的查询，可以让我们人类以电脑主机名称连上 Internet ，而不必背诵 IP 哩！

  • 那么请教 Unix Like 系统当中，主要使用那个套件做为 DNS 主机的架设，同时，他又是使用那个 daemon 来启动 DNS 系统？

    • 在 Unix Like 系统当中，使用 BIND 这个套件做为 DNS 的架设，至于 daemon 则是使用 named 这个 daemon ！

  • 最早的 Internet 其实是为了政府人员可以连上网路以进行资源的分享，另外，则是电子邮件的使用。而在早期使用的重要档案只有 /etc/hosts 这个，请教这个 hosts 档案的内容含有什么项目？

    • 这个档案的‘格式’为‘ <IP> <主机名称> <主机别名(aliase)>’，而，这个档案里面放置了至少一行，也就是：
    127.0.0.1 localhost localhost.localdomain
    另外，也可以将经常连接的主机 IP 与 HOSTNAME 的对应给他写进来！

  • 请说明 DNS 的三种类型与相关的内容：

    • DNS 主机主要分为： master, slave 与 cache-only 三种类型！在 master 当中，master 主机里面即有设定 DNS 资料档案，例如在 /var/named 里面的正反解档案。至于 slave 的 DNS 主机则主要在进行 master 主机的资料备份，同时也提供 Internet 上面的查询功能。使用 master/slave 的最大优点在于“单点维护”的能力！利用修改 master 即可让 slave 的资料同时更新，减少人力的浪费。至于 cache-only 仅进行快取的纪录，本身并无资料库档案！

  • 正解档案(forward)反解档案(reverse)与内部回圈使用的档案(loopback)主要的纪录功能为：

    • 正解档在设定 hostname 对应到 IP 的纪录，主要的纪录有 A, NS, SOA, MX, CNAME 等等；
    反解档主要设定 IP 对应到 Hostname 的纪录，主要的纪录为 SOA, NS 与 PTR 等。
    内部回圈则是 localhost 与 127.0.0.1 的对应啦！

  • 在主要的 DNS 设定档 /etc/named.conf 当中，有一个较为特殊的档案，他的类型为 hint ，请问这个档案的功能为何？

    • 这个档案主要是由 rs.internic.net 所下载下来的，主要记录了 root (.) 这个 zone 的 IP ！可以让我们的 DNS Server 在找不到资料库时，可以到这个 root 去查询资料！

  • 在 client 端搜寻 HOSTNAME 对应到 IP 的查询时，最重要的档案，以及该档案的主要用途为何？

    • /etc/nsswitch.conf ：可以用来设定查询主机名称的顺序！例如先查询 /etc/hosts 再查询 DNS 系统；
    /etc/hosts ：最早的名称解析器；
    /etc/resolv.conf：这就是 DNS 系统的 resolver (解析器)了。

  • 一般来说，在 Client 端使用的查询 HOSTNAME 的指令大多使用什么？

    • nslookup ：可以用来收集一部主机的相关资讯；
    dig：可以用来收集详细的主机资讯；
    whois ：可以用来收集详尽的 DNS 主机资讯。
    host 则较为简单喔！

  • 请问 named 重要的资讯登录在在那个档案中？

    • 在 /var/log/messages 当中。

    第十八章、简易 WWW 伺服器设定

  • 请问 LAMP 这个伺服器代表什么意思？

    • 这个名词代表了 Linux + Apache + MySQL + PHP 这个 WWW 伺服器的组成！

  • Apache 的设定档档名一般为何？

    • Apache 的设定档档名为 httpd.conf ，不过，由于 httpd.conf 内容参数可以使用‘ include "额外设定档名"’，所以也可能具有其他的额外设定档喔！

  • 在 Apache 的设定档当中，哪一个参数是用来设定‘主网页’的？

    • 设定主网页的参数为：DocumentRoot 喔！后面接的是主网页放置的‘目录’！

  • 哪一个指令用来重新启动与关闭 Apache ？(请以 Tarball 安装的方法来说明)

    • 其实不论是 RPM 还是 Tarball 都是使用 apachectl 这个档案来启动 apache 的，不过 RPM 已经将该档案整合到 /etc/rc.d/init.d/httpd 里面去而已！

  • 当我使用 ps -aux 的时候，发现好多的 httpd... 的程序，这是正常的吗？！最多可以有几个程序是在那个档案的那个参数所设定的？！

    • 这是正常的，主要由 httpd.conf 里面设定的底下两个参数：
    • MinSpareServers
    • MaxSpareServers

  • 又，呈上题，这些程序 (process) 的 owner 与 group 是谁？该察看那个设定档的那个参数？

    • 同样察看 httpd.conf 里面的 User 与 Group 这两个设定值！

  • 如果今天我以 http://your.ip 结果却发现浏览器出现类似 FTP 的画面(会列出该目录下的所有档案)，这是什么原因造成的？该如何避免？

    • 这是由于在 httpd.conf 里面，针对该目录的设定参数‘ Options ’当中，设定了 Indexes 这个设定值，导致当找不到主页时(通常是 index.html)，就会将该目录下的所有档案秀出来！解决的方法就是拿到 Options 里面的 Indexes 设定值即可！

  • 在 Apache 里面， .htaccess 这个档案的功能为何？

    • 可以用来取代 httpd.conf 里面的设定参数！创造属于使用者自己的 Apache 风格！

    第十九章、简易 SAMBA 伺服器设定

  • 一般来说， SAMBA 使用的设定档放置在哪里？档名为何？

    • 使用的档名为 smb.conf ，通常会放置在 /etc/samba/smb.conf 里面，不过，最好可以使用 rpm -qc packagename 来查询！

  • 哪一个指令可以用来判断 smb.conf 这个设定档的正确性？

    • 当我们修改完 smb.conf 之后，记得要以 testparm 来进行 samba 的确认！

  • 哪一个指令可以用来察看 SAMBA 主机分享出什么目录？

    • 利用 smbclient 即可：‘smbclient -L NetBiosName -U username ’！

  • smbmount 的功能为何？

    • 在 Linux 系统上面，将 Windows 的网路上的芳邻，或者是 Linux 的 SAMBA 所提供分享的资源挂载到自己的系统下！

  • 我今天使用 smbpasswd 去新增一位使用者 badbird，让他可以登入我的 Linux SAMBA 主机，但是无论如何就是无法新增。您认为原因可能是什么？

    • 由于 Samba 使用者的资讯必须要存在于 /etc/passwd 里面，既然无法新增，应该先确认 badbird 这个使用者已经存在于 Linux 系统当中了！如果还是无法新增，则需要查阅 smb.conf 的设定，看看是否 /etc/samba/smbpasswd 这个密码档案不存在？！

    第二十章、简易 Mail Server 架设 -- Sendmail 设定

  • 我在使用 Sendmail 寄信时，却发生底下这个问题，请问可能的发生原因为何？
    • 可能的问题有两个：
    • 你的 Client 端电脑的 IP 或者是网域位址被 /etc/mail/access 所挡住，或者是 /etc/mail/access 没有打开你的 RELAY 权力；
    • 你有进行 SMTP 邮件认证的设定，但是忘记在 MUA 当中设定帐号与密码的项目了！
    如果不是这两个原因，那么可能的问题就多了！请详细的检查您的网路设定！

  • 请列出四个 Mail Server 的相关的元件，以及其功用为何？
    1. Mail Client ：邮件用户端，其实就是使用 mail 的那位使用者所在的电脑即可称为 mail client ；
    2. Mail User Agent ：为一个应用软体，主要的功能就是收受邮件主机的电子邮件，以及提供使用者浏览与编写邮件的功能；
    3. Mail Transfer Agent ：为在电脑与本地端 Mail server 或 Internet 上面的 Mail server 传送讯息与邮件的主机；
    4. Mail Dilivery Agent ：主要的功能就是将 MTA 所收受的本机信件，放置到本机帐户下的邮件档案中 ( Mailbox )！

  • POP3 与 SMTP 的功能为何？
    • SMTP 为使用于 MUA 或 MTA 与 MTA 之间的传输协定，通常使用 port 25 ，只要主机支援 SMTP ，并且其他 relay 的条件能配合，就可以进行邮件传递！
    • POP3 可以提供使用者经由 MUA 到 MTA 下载邮件，同时并可将邮件从主机上面删除！

  • 请简单的说明 DNS 里面 MX 标志与 Mail 的关系为何？

    • MX recode 可以可以让 mail server 经由 MX 以及 A ( address ) 这个记录来进行 mail gateway 与 mail route 的功能！能够达到的作用相当的多！

  • 今天我突然兴起，想要修改我的 sendmail ，请问， sendmail 的设定档在哪里？而我要以什么程式修改 sendmail 呢？

    • Sendmail 的设定档为 sendmail.cf ，这个档案通常放置在 /etc/sendmail.cf 或者 /etc/mail/sendmail.cf ！您可以手动的编辑这个档案，不过不建议如此，取得代之的，可以使用 m4 这个程式来进行 macro 的动作，进一步的完成 sendmail.cf 的修改！至于使用 m4 时，需要先建立 m4 scripts ，再以 m4 转换才能形成 sendmail.cf 喔！

  • 什么是 mailling list ？在 sendmail 底下有什么方法可以不藉由其他的软体达到 mailling list 的功能？

    • Mailling list 就是将使用者寄给一个帐号邮件时，该帐号会主动的将该邮件传送到所有的用户去！有点类似目前的电子报！在 sendmail 底下，我们可以透过 aliases (需配合 newaliases) 以及 ~/.forward 来达成喔！

  • 如何察看邮件伫列的内容，以及邮件伫列内容放置在何方？

    • 使用 mailq 即可知道目前邮件伫列的内容，而邮件伫列虽然可以透过 sendmail.cf 来修改，不过，预设情况下，都是以 /var/spool/mqueue 为邮件伫列目录。

  • 若我的 sendmail 主机有很多名称，我想让这些名称都可以进行 mail 的接收，应该修改什么档案？

    • 可以修改 /etc/mail/local-host-names 来达成！

  • 什么是 Open Relay？

    • 所谓的 Open Relay 就是，不论发信端来自何处，您的 Open Relay 的主机均可以帮发信端将信件发送出去，这个称为 Open Relay 。如果您的 mail server 具有 open relay 的情况，那么很容易遭受到垃圾邮件的填充，不但造成网路频宽的耗损，也容易让您的主机被列入黑名单当中！

    第二十一章、简易 Mail Server 架设 -- Postfix 设定

  • 请问 Cyrus SASL 在 1.5.xx 以及 2.xx 版本中，用来作为 SMTP 的认证的机制有何不同？并请说明不同的版本与 Postfix 的搭配情况。

    • 一般而言， SASL 1.5 适用于 postfix 1.xx 版本，至于 SASL 2.x 版则适用于 postfix 2.xx 版。由于 SASL 2.x 主要使用 saslauthd 这个 daemon 来做为身份认证的方式，而 SASL 1.5 则使用的是 pam 与 pwcheck 这两个机制，两个版本的认证机制并不相同。所以使用 Postfix 来设定 SMTP 的身份认证时，请务必记得版本的差异！

  • 如果要让 Postfix 可以收发来自非本机的外部信件，您可以修改 main.cf 里面的什么参数？

    • 需要在 main.cf 里面修改的变数主要有：
    1. 当 Client 来自信任的网域，也就是 IP 符合 $mynetworks 的设定值时；
    2. 当 Client 来自信任的机器，也就是主机名称符合 $relay_domains 的设定项目时；
    3. 当 Client 来自不信任的网域，但是去的目的地主机端符合 $relay_domains 的设定时。

  • 如何察看您目前的 Postfix 伺服器的所有设定参数？(使用什么指令？)

    • 利用 postconf -n 可以察看‘目前 main.cf 里面设定的参数’，而如果要看所有的参数，则直接使用 postconf 即可！

  • 在 Postfix 当中，由于已经具有过滤邮件的机制，所以不太需要使用 procmail 了！请问，我该如何启用信件的 Header 过滤机制？同时，如何设定规则，使得 192.168.100.100 这个主机的来信，以及只要邮件的标头为‘ Your account ’的信件就予以丢弃？

    • 启用的方式可以在 main.cf 里面启用这个设定值：
    header_checks = regexp:/完整路径/档名
    body_checks = regexp:/完整路径/档名
    至于档案内容可以这样做：(注：因为要查阅的是标头，所以需要 header_checks 后面所接的档名呐！)
    /^Subject.*your\ account/ REJECT

    第二十二章、简易 FTP Server 架设 -- Wu FTP 设定

  • FTP 在建立连线以及资料传输时，会建立哪些连线？

    • 需建立两种连线，分别是 command 与 data transfer 的连线，就是命令通道与资料传输通道。一般来说，就是 port 21(ftp) 与 port 20(ftp-data)。

  • FTP 主动式与被动式连线有何不同？

    • 主动式连线的时候， command 连线是由 client 端主动连接到主机端，但是 ftp-data 则是由主机端主动的连线到 client 端。至于被动式连线的时候，则不论 command 还是 ftp-data 的连线，主机端都是 Listen 客户端的要求的！

  • 有哪些动作可以让您的 FTP 主机更为安全 ( secure ) ？

    • 有很多的方法，在设定上面有这些方法：
    • 让 guest 与 anonymous 的家目录限制在固定的目录中(chroot 或是 restricted)；
    • 使用 TCP_Wrappers 启动 FTP ，并以他来控制可连线的 IP；
    • 拒绝 guest 与 anonymous 使用 change, delete, rename 等等指令；
    • 拒绝 root 的登入或者其他系统帐号的登入；
    • 拒绝大部分的 upload 行为！

  • 我们知道 ftp 会启用两个 ports ，请问这两个 port 在哪里规范的？而且，一般正规的 port 是几号？

    • 是在 /etc/services 里面规范的，此外，正规的 ports 在 command 是 21 而 data 是 20 。

  • Wu FTP 的主要设定档在哪里？

    • /etc/ftpaccess

  • 在 Wu FTP 的设定档当中，那个 log transfer 是干嘛用的？

    • log transfer 可以将使用者进行资料传输的时候，将传输的档案大小、内容等等记录到 /var/log/xferlog 里面去！

  • 在 Wu FTP 的设定档当中，那个 passive ports 是干嘛用的？

    • 我们知道 FTP 有主动与被动连线两种方式，如果 FTP 主机允许被动连线，那么 Client 端连线时，主机端将会随机取大于 1024 的 port 来进行 data transfer ，为了避免随机取 port 的问题，所以 passive ports 可以指定固定的几个小范围的 ports ，比较安全。

  • 那一个档案可以用来抵挡类似 root 这种系统帐号的登入 FTP？

    • /etc/ftpusers！(其实是利用 pam 模组来达成的功能！)

  • 在 FTP 的 server 与 client 端进行资料传输时，有哪两种模式？为何这两种模式影响资料的传输很重要？

    • 资料的传输有 ASCII 与 Binary 两种方式，在进行 ascii 传送方式时，被传送的档案将会以文字模式来进行传送的行为，因此，档案的属性会被修改过，可能造成执行档最后却无法执行等的问题！一般来说，ASCII 通常仅用在文字档案与一些原始码档案的传送。

    第二十三章、简易 FTP Server 架设 -- Pro FTPD

  • 如何建立一个使用者，他可以使用 FTP 的功能，但是无法以 telnet 或 ssh 登入系统？！请使用 proftpd 的设定项目来设定！

    • 因为无法使用 telnet/SSH ，这表示他可能不具有正常的 shell ，因此您可以将该使用者在 /etc/passwd 里面，最后一个 shell 参数改成 /bin/false ，然后在 proftpd.conf 里面设定‘RequireValidShell off’即可！

  • 我明明在台湾，我的主机时区 (/etc/sysconfig/clock) 明明在台湾，为何登入 proftpd 之后，显示的系统时间就是慢了 8 小时？请问为什么？如何解决？

    • 这是由于 proftpd 预设使用 GMT 时间，因此，您必须要重新设定 proftpd ，使得时间使用 localtime 才成！修改 proftpd.conf 里面的参数成为：‘TimesGMT  off’

  • 如果发生了无法登入，或者是与 proftpd 的 FTP 功能相关的错误时，要如何 debug 呢？

    • 最先应该查询是否被防火墙挡住了(同时观察 Server/Client 端)；
    克服防火墙问题后，再查询 FTP port 是否有启动；
    再检阅 /var/log/messages 里面的错误讯息，
    最后据以修订 proftpd.conf 的设定参数！

    第二十五章、简易 Proxy Server 架设

  • 请说明为何 Proxy 可以提升网路的 WWW 浏览速度？

    • 这不但由于 Proxy 可以透过上层 Proxy 达到分流的功能，使得网路传输更具效率之外，还由于 Proxy 会将资料快取(cache)在自己的硬碟内，以方便下次的查询，因此对于区域网路的浏览速度是有帮助的！

  • 万一 squid 发生了问题，请问我该如何找出问题点？

    • 最主要还是在于找出问题，所以需要由 suqid 的登录档查询起，当然，硬碟的优劣以及 squid 所取得 PID 的 owner 与 group 都是需要注意的！

  • 请说明 Proxy 伺服器的功能为何？

    • Proxy 伺服器的功能在于代理来自 client 的上网需求，并向目地端主机送出 client 端的要求，以协助 client 端取得所需要的浏览网页。此外，并可将网页资料进行 cache 的功能。

  • 试说明为何 Proxy 伺服器可以提升网域之内的网路安全性？

    • 由于 Proxy 伺服器通常架设之后，会让网域仅有一个 Proxy 主机的出口，亦即单点对外的伺服器，可以强化网路的管理！

    第二十六章、简易 Network Information Service, NIS Server 架设

  • 请简单说明 NIS server 的功能与工作流程

    • 当您有多部具有相同帐号的 Linux 主机时，即可利用 NIS 所提供的服务，来利用一部 NIS 主机掌控所有的 linux 主机的登入时所需查阅的帐号与密码验证。流程如下：
    1. NIS Server 将自己系统内的 /etc/passwd, /etc/group, /etc/hosts 等制作成为 DBM 的资料库格式档案；
    2. NIS Client 若有用户登入的要求时，会前往 NIS Server 搜寻资料库里面的资料做为验证之用。
    3. 每次更动 NIS Server 上面的用户资料时，则 NIS Server 需要重新制作 DBM 资料库档案才行！

  • 请简单说明 NIS Server/client 的架构

    • NIS master/client 的特色为：
    1. NIS Server 的 master 先将自己的帐号、密码相关档案制作成为资料库档案(database file)；
    2. NIS Server 的 master 将自己的资料库档案传送到 slave 上面；
    3. NIS Server 的 slave 接收来自‘信任的 NIS Server master 主机’的资料后，更新自己的资料库，使自己的资料库与 master 主机的资料同步；
    4. 网域当中的所有 NIS Client 查寻 NIS Server 时，会找寻‘最先回应的那一部 NIS 主机的资料库内容’。
    也就是说，架设 slave NIS server 可以分担区域内 NIS 的工作！

  • NIS 启动之前需要先启动那个服务，否则就无法启动成功

    • 因为 NIS 是 RPC Server 的一种，所以必须要启动 portmap 这个 daemon 才行！

  • 我的 NIS 网域名称为 bird ，另外，我主机的 IP 与主机名称为 192.168.5.1/bird.nis.org ，请问要这些资讯需要设定在 NIS Server 的哪些档案之内？

    • 网域名称可以直接手动下达‘ nisdomainname bird ’也可以写入 /etc/sysconfig/network 里面‘NISDOMAIN=bird’；
    IP 与 主机名称 需要写入在 /etc/hosts 里面。

  • /etc/nsswitch.conf 的功能为何？如果我想要让密码查寻先本地的密码档，再查寻 NIS ，需要如何设定？

    • 该档案的功能很多，在 DNS 方面，可以用来决定正、反解的顺序，至于密码则可以用来判断何者为先！如果需要先查本机再查 NIS 的密码时，需要的参数：
    passwd:     files nis nisplus
    shadow:     files nis nisplus

  • NIS Server 将密码等档案做成资料库以提供 NIS client 来查寻，那么请问使用什么动作后，可以将密码档案转成 NIS 的资料库格式档案？

    • /usr/lib/yp/ypinit -m

  • 如果我想要增加网域当中一个新的帐号：newaccount，并且这个 newaccount 可以让 NIS Client 查寻到他的帐号与密码，需要进行哪些步骤？
    1. 先登入 NIS Server 以 useradd newaccount 以及 passwd newaccount 来新增帐号；
    2. 制作密码资料库：‘/usr/lib/yp/ypinit -m’
    3. 重新启动：‘/etc/rc.d/init.d/ypserv restart ; /etc/rc.d/init.d/yppasswdd restart’。

  • 实作范例题：底下是我的网域参数特征：

    • network/netmask:192.168.1.0/255.255.255.0
    NIS server : 192.168.1.100 (hostname: server.nis.test )
    NIS cient: 192.168.1.200 (hostname: client1.nis.test )
    NIS domain name: nis.test
    利用上面的参数来设定 NIS 架构，请一步一步的写下你的设定。
    请自行参考本章节内容设定！

  • 承上题：如果我的网域太大了，所以有一部 NIS slave 主机，这部主机的 IP 为 192.168.1.50 ，请问这部主机该如何设定？

    • 请参考：http://www.linux-nis.org/nis-howto/HOWTO/index.html

    第二十七章、简易 NTP 伺服器设定

  • 什么是 GMT (格林威治) 时间与 UTC 时间？

    • 由于地球是圆的，所以同一时间点上，在地球共可分为 24 个时区，其中，我们以欧洲的格林威治时间为一个对照的依据，这个即是 GMT 时间。台湾时间比 GMT 时间快了 8 小时。至于 UTC 时间则是由原子钟所计算的时间，这个时间是相当的准确的，主要仍以格林威治时间为时区！

  • Linux 系统的所有时区档案放置哪一个目录底下？

    • 所有的时区档案放置于：/usr/share/zoneinfo 底下！至于系统时区的设定档则在 /etc/sysconfig/clock 与 /etc/localtime 喔！

  • 我的 Linux 主机本来放置在日本东京，现在想将他拿到台湾来运作，不过因为日本与台湾有一个小时的时差，所以我的时间应该需要经过调整才行。不过，因为我的 BIOS Time 主要是依据 UTC 时间来设定的，所以似乎只要更动时区参数即可。请问我该如何设定时区，好让我的 Linux 主机能够显示正确的时间？

    • 将 /usr/share/zoneinfo/Asia/Taipei 这个档案复制成为 /etc/localtime 即可！

  • 目前 Linux 系统上面的时间伺服器主要是以 NTP 为主，请问这个 daemon 的主要设定档放在哪里，而该设定档中，针对上层 time server 的设定参数为何？而那个 driftfile 参数是干嘛用的？

    • 在 /etc/ntp.conf 这个档案当中，至于上层 time server 的设定参数为 server 啊！那个 driftfile 则是用来做为‘时间差额’的计算的！该参数后面接的是一个完整路径的档名，该档案里面的数值单位为百万分之一(ppm)。

  • 请问 ntptrace 的功能为何？

    • 可以用来追踪上层 time server 的连线时间与目前时间！

  • 我以 date 更新了我 Linux 上面的时间后，该如何将时间数据写入 BIOS 内？

    • 必须利用 hwclock 这个程式来写入，利用 hwclock -w 写入 BIOS 。

  • 在 Linux 上面如何进行网路校时？

    • 最简单的方法即是使用‘ ntpdate time.servers.ip; hwclock -w ’即可！
架站文件习题解答篇
2003/0919：完成到 Part II (简易主机防火措施篇) 的习题咯！
2003/09/20：完成了 Part III 的习题咯！真开心！大家作作看吧！


鸟哥的 Linux 私房菜 -- 企业级应用篇的目录

为取得较佳浏览结果，请爱用 firefox 浏览本网页

鸟哥的 Linux 私房菜 -- 企业应用篇目录
特别强调
底下的文件主要是针对比较大型的网域才需要的伺服器设定加以介绍的， 一般来说，如果是小型企业，或者是个体户(^_^)通常不太需要底下的资源， 因为一部 Linux 主机就能够完成所有的事情，而且也不会太花费时间与金钱！ 不过，如果是中小企业以上的网路环境时，由于我们需要快速的安装多部主机、 快速且统一的处理员工的帐号等等，此时就需要某些伺服器的帮助了！ 包括安装伺服器(installation server)及帐号控管中心(NIS or LDAP等等)。

这个企业应用中，其实很多部分鸟哥也只是根据过去的经验来撰写的，对于实际的企业环境， 鸟哥很想多多去学习与看看。如果有朋友愿意开放机房与一些相关的软、硬体给鸟哥参观的话， 敬请来信指教喔！小老儿会非常高兴的！ ^_^

在这个章节部分，鸟哥已经假设您看过基础篇与伺服器篇，所以将不会花费很多时间在基础的介绍上， 如果您对于 Linux 基础与简单的伺服器架设没有概念的话，那么底下的文章先看看就好，别急著作！ 否则老是发问一些蠢问题，对您的学习也不是件好事！

大标题的图示 企业环境常见的伺服器架设
包括 Samba 的 PDC 中心、利用 LDAP 架设个人资料的维护、Xen 虚拟主机的运作、 网路安装主机 (Installation server) 的配置、 关于 CentOS YUM 主机的配置等等， 都可以拿来玩一玩！让您的企业环境更加的迅速便捷！ ^_^

Installation Server (构思中) | 如何透过网路来进行 Linux 的安装？
利用 Xen 设计虚拟机器 2007/10/20 | 所谓的‘虚拟机器’就是在一部实体主机上面虚拟出多部实体主机的环境， 且每部实体主机都是独立的，除了原本的那部原主机外，其他的主机都可以独立开、关机， 由于个人电脑的能力在近年来突飞猛进，速度与效能都非常棒，所以用一部实体主机来进行虚拟机器的架设， 并适当的分配不同的服务在上头，将有助于能源的节约、管理的简化以及服务追踪的简化哩
流量控管资料 (构思中) | 包括 MRTG, bounding 等等怎么玩？
简易 APT Server 2003/08/27 | APT (Advanced Package Tool) 是由 debian 这个 distribution 所发展的一个套件管理工具，不过因为太好用了，所以很多机构就将他设计成为可以符合其他 distribution 做为网路更新的一项利器！在这个章节当中，我们要介绍如何在 Red Hat 9 上面建置一个 ATP 伺服器，并且提供 Mandrake 的更新给 Client 端来更新使用！
简易 Proxy 伺服器 2003/09/16 | 代理伺服器这个东西对于大企业可了不得啰！可以提升内部的网路的速度呢！虽然是有点奇怪的说法，不过，他确实可以‘假象’的提升企业内部的网路工作效率，嘿嘿，废话不多说，赶快来看看怎样架设吧！
LDAP 伺服器 构思中 | 如何利用一个主控帐号/密码的主机来管理整个公司内部的员工资料呢？在 Windows 内有 AD 这个东西， 在我们的 Linux 里面则有 LDAP 这个玩意儿！让我们来瞧一瞧这个东西在 Linux 下的用途， 以及在 Windows 网芳等等的用途吧！
OpenWebMail 2004/08/26 | 使用 Webmail 可以避免大部分的病毒信呢！所以这个小东西有越来越热门的趋势！ 在这里，我们使用台湾人自己写的一套自由软体：OpenWebMail 来架设我们的 MUA ！ 很不错的东西！赶紧来看看先！
MySQL 基本指令使用 ( 施工中 ) | 如果已经架设好 LAMP ( Linux + Apache + MySQL + PHP ) 的朋友，最想要知道的大概就是‘嗄！我的资料库出问题，或者是死掉的时候怎么办？’ 呵呵！这个时候我们可以直接登入 MySQL 资料库系统，而不必经由 PHP 程式来管理呢！ But HOW ？我们这里就来谈一谈吧！


鸟哥的 Linux 私房菜 -- 利用 Xen 进行虚拟机器的制作

为取得较佳浏览结果，请爱用 firefox 浏览本网页

利用 Xen 设计虚拟机器
最近更新日期：2008/09/09
我们常常讲，最好将不同的伺服器架设在不同的主机硬体上面，也就是说，每部主机所负责的任务越简单越好， 如此一来不但可以减少主机 debug 的时程，也能够简化安装与设计主机的架构。但是， 每个服务一部主机对于小企业或者是个体户来说，光是放置主机的空间、电源、以及后续的管理问题， 就会导致一堆困扰的产生。这个时候，虚拟机器就非常有用啦。

所谓的‘虚拟机器’就是在一部实体主机上面虚拟出多部实体主机的环境，且每部实体主机都是独立的， 除了原本的那部原主机外，其他的主机都可以独立开、关机，由于个人电脑的能力在近年来突飞猛进， 速度与效能都非常棒，所以用一部实体主机来进行虚拟机器的架设，并适当的分配不同的服务在上头， 将有助于能源的节约、管理的简化以及服务追踪的简化哩！

1. 前言
    1.1 什么是虚拟机器
    1.2 有哪些常见的虚拟机器软体
 2. 初探 Xen
    2.1 Xen 的虚拟类型与特色
    2.2 Xen 的运作环境解释
    2.3 确定你的硬体是否支援 Xen 的运作
    2.4 所需要的 Xen 套件与核心, xen 的套件结构
    2.5 第一个泛用实例
        2.5.0 硬体支援性
        2.5.1 根目录所需磁碟槽
        2.5.2 复制或安装根目录
        2.5.3 设定虚拟磁碟映象档以及终端机介面
        2.5.4 编辑 xen 虚拟资料的设定档
        2.5.5 利用 xm 指令启动与管理 domain-1
        2.5.6 常见错误分析
3. 其他半虚拟化的安装方式
    3.1 制作安装伺服器
    3.2 利用 virt-install 指令安装干净的 CentOS
    3.3 CentOS5 所提供的一个实例
 4. Xen 的进阶认识(这个章节还没有动工，构思中)
    4.1 Xen 的网路介面
    4.2 Xen 网路安全
    4.3 全虚拟化：一个安装 Windows 系统的实例(hvm 模式)
    4.4 教学实例：30个 domainU 的案例
 5. 针对本文的建议：http://phorum.vbird.org/viewtopic.htm?p=128769
大标题的图示 前言
这个章节主要是在介绍 Xen 这个虚拟机器，那，什么是虚拟机器？他有什么用途？ 目前有哪些常见的虚拟机器软体 (Virtual Machine) ？底下我们先来说一说。

小标题的图示 什么是虚拟机器
虚拟机器 (Virtual Machine) 与 Apache 的虚拟主机 (Virtual host) (注1) 不一样， 虚拟机器的目的是希望能够在一部实体主机上面‘同时运作多个作业系统’的一项功能。 为什么我们需要在一部主机上面同时运作多个作业系统呢？可能原因有几个：

  • 让一部强效型主机负责多种业务时：
    由于电脑工业技术的发达，近年来的个人电脑不但越来越便宜，而且功能还越来越强大！ 就在前几个礼拜 (2007/09/xx) ，鸟哥也才收到两部‘四核心的、配备 2GB 主记忆体’的个人电脑！ 这在台湾政府的中信标案里面也已经有提供了，可见个人电脑实在是便宜又好用。

    那么好用的一部电脑如果拿来当网路伺服器，你会觉得很浪费！怎么说呢？ 以鸟哥的鸟站 (http://linux.vbird.org/) 来说，一部 AMD AthlonXP 2000+ (1.6GHz 的 CPU 速度) 就跑得非常的顺畅， 运作至今应该也没有发生突发性大流量导致服务中断的情况，观察这部主机的平均运作情况， 使用 sar 这个指令来察看一下，唔！每日平均 CPU 负载都在 10% 以下而已。 所以说，这部四核心的电脑拿来当鸟站的主机，根本就是浪费了他的才能。

    如果能够将多种服务集中在这部主机上面来跑，岂不甚好！才不好哩！ 如果你看过基础篇 (注2) 与伺服器篇 (注3) 的介绍后， 肯定会认为主机的服务越单纯越好，这样在服务软体除错以及主机环境的单纯化上面比较好。 所以说，一部好的主机如果仅用于一个特定的用途，实在很浪费。但如果每个服务都需要一部主机， 又觉得很讨厌，因为包括主机的硬体维护、电费、软体安装、网路设定等等，都很麻烦，尤其又贵！

    因为上述的问题，所以目前有很多专案都在开发‘在一部实体主机上面模拟出另一部机器’的功能， 也就是说：‘我们希望能够在一部主机上面 "同时" 跑多个作业系统’的意思。如果能达到这样的功能，实际的硬体可以省略掉很多问题， 同时又可以充分的应用实体主机的资源，实在很不错啊！

  • 同时豁弄多种不同的作业系统：
    时间拉回到四、五年前，当时的主机能力仅是还可以，还不算很够力，而且价格不斐。 但是当时多种作业系统都很吸引人，包括 Windows/Linux/Mac/DOS... ，大家都希望能够尝试一下这些作业系统， 然而又不想花钱去购买一部新的主机来玩，这个时候多重开机 (注4) 就成了很重要的一环， 因为他可以让我们在开机的过程当中选择所想要执行的作业系统来操作说。

    不过多重开机有个讨厌的缺点，那就是‘我每次开机只能够单玩一种作业系统’， 所以如果你想要在多个作业系统之间切换时，光是开、关机就会让你火气大起来。 这个时候就有些公司开始开发能够在一个作业系统上面‘模拟出另外一个可执行的作业系统’环境， 所以此时就能够在同时间操作两种作业系统了。当时最流行的是 VMWare 这一套软体啦！

    虽然早期就已经有数种虚拟机器的软体可以玩，不过当时毕竟是使用软体来模拟的， 硬体并不直接支援这种虚拟机器的环境，所以效能上面非常的糟糕！不过拜 Intel/AMD 大力开发强效型 CPU 之功， 目前的主机硬体大部分都有支援虚拟机器的能力，如此一来我们就能够使用快速的虚拟机器的环境啰！

    • 小标题的图示 有哪些常见的虚拟机器软体
    那么目前有哪些常见的虚拟机器软体呢？他们又各有何特色？底下就来说一说：

  • 老牌子的 VMWare (http://www.vmware.com/)
    • 早期的玩家大概都有玩过这一套虚拟机器的软体，这套软体早期仅在 Windows 上面执行， 最大的优点就是可以让使用者在 Windows 环境下同时模拟出一套 Linux 的环境，同时执行两个作业系统。 鸟哥之前使用这套软体的目的是用来捉 Linux 的安装画面！在这个功能上面 VMWare 实在很不错。

    不过早期的 VMWare 效能不太好，加上当时的主机效能也不佳，而且 VMWare 模拟的硬体不会与原本的主机相同， 因此鸟哥很不建议大家使用 VMWare 来学习 Linux 。然而随着时代的进步，目前 VMWare 已经发展的相当不错， 同时也提供 Open source 的版本给 Unix-Like 平台的 OS 使用，算是很不错的。他也是目前虚拟机器市场的龙头老大！

  • 已渐趋成熟的 Xen (http://www.xensource.com/)
    • Xen 是以 GNU 的 GPL 授权发布的自由软体，目的在于提供效能佳、可支援不同作业系统的同时运作、 且让同时运作的作业系统彼此互相独立的系统环境。Xen 是基于 X86 硬体所开发出来的虚拟机器监督器 (Virtual Machine Hypervisor) ，鸟哥觉得他最大的优点就是效能佳！鸟哥曾在一部 Celoron 366 MHz, 记忆体 192MB 的笔记型电脑上面模拟出一个 Xen 机器给上课的同学们豁弄，同时连线 50 个同学到该部模拟的 Xen 机器上还不会觉得有延迟的问题，效能真的是很不错。我们在下一节会详细的介绍 Xen 这个好东西。

  • 后起之秀 KVM (Kernel based Virtual Machine, http://kvm.qumranet.com/kvmwiki)
    • 让 Linux 发明者 Linus Torvarlds 喜好并且将之加入核心功能的虚拟机器就是这个 KVM 的技术！ KVM 已经于 Linux 2.6.20 版的核心中加入此项功能，KVM 不但提供完整的 Intel/AMD CPU 的虚拟技术支援， 而且提供完整的虚拟环境。虽然目前这个技术还不算很成熟，不过未来应该也可以发展的很不错呢！ 因为 Linux 核心本身就有支援啊！ ^_^！更多的 KVM 可以参考： http://en.wikipedia.org/wiki/Kernel-based_Virtual_Machine

  • 酷！炫！有劲的 VirtualBox (http://www.virtualbox.org/)
    • 还有一套自由软体的虚拟机器可以用，那就是同样架构在 x86 上面的 VirtualBox 这套软体啦！ 这套软体提供完整的虚拟环境，且可支援目前市面上的主流作业系统。 鸟哥曾经看过网中人前辈在他的笔记型电脑上面玩过这套东西，非常的炫丽，而且提供图形化介面， 效能方面看起来也相当的优秀。不过，好像整合度方面的问题，偶而模拟的作业环境会当掉， 但是不会影响到原作业系统就是了。想要在 Linux 桌上型电脑上玩玩虚拟环境的朋友，鸟哥觉得这套东西最适合您！

    其实每套虚拟机器的软体都有其存在的价值，因为他们的功能与目的都不一样。举例来说，鸟哥认为 VirtualBox 很适合于想在 Linux 桌上型电脑上面玩 Windows 的朋友，虽然他不够稳定。至于 Xen 则很适合在一部高效能主机上面同时运作多个同版本的 Linux 系统，因为稳定度相当高，且性能优秀， 可让使用者轻松的在一部机器上面运作多个独立的作业系统来分别处理不同的网路服务呢！

    Tips:
    这一章底下的资料牵涉到很多硬体的观念以及 Linux 作业系统最底层核心的架构说明， 如果您不想要了解这些基础概念，可以直接看 CentOS 5.x 的实例说明即可。     		鸟哥的图示
    大标题的图示 初探 Xen
    Xen 的效能为什么能够这么好？ Xen 在使用上面有什么样的限制？我的一部主机最多可以支援几个 Xen 的模拟环境？ Xen 的模拟环境有几种类型？ 这些疑问我们都得要先知道一下才好！ 当然，最好能够有个简单的小例子来处理 Xen 的模拟环境啰。

    小标题的图示 Xen 的虚拟类型与特色
    Xen 这套自由软体在虚拟机器的模拟类型方面主要分为半虚拟化 (Para-virtualization) 及全虚拟化 (Full virtualization) 两种，其中半虚拟化主要是透过修改 Linux 核心来达成的虚拟技术。 半虚拟化技术所产生的虚拟机器需要与原本的作业系统相同较佳。使用半虚拟化的环境所具备的特色有： (注5)
    • 虚拟机器的运作效率与实体机器的效能相当；
    • 最多可支援到具有 32 颗以上 CPU 的主机环境；
    • 支援 x86/32, x86/32 含 PAE 技术, 及 x86/64 的硬体平台环境；
    • 良好的硬体驱动程式支援，几乎支援所有的 Linux 装置之驱动程式；
    Xen 的半虚拟化技术主要是用在相同版本的 Linux 上面，也就是说，如果你想要使用半虚拟化的方式启动多个虚拟机器， 那么那些虚拟机器全部都必须是相同的作业系统，甚至要求相同版本与相同核心的 Linux distribution 喔。

    如果你想要安装不同版本的 Linux 或者是其他的 OS (例如 Windows XP) 时，就得要使用全虚拟化技术了。 但是全虚拟化技术是有其限制的，当你的硬体满足下列需求时，全虚拟化技术才能够动作：
    • 你的硬体支援 Intel 的 VT 技术 (Virtualization Technology, Intel-VT)；
    • 你的硬体支援 AMD 的 SVM 技术 (Secure Virtual Machine, AMD-SVM or, AMD-V)。
    此外，上面提到的 PAE 指的是 Intel 的实体位址延伸技术 (Physical Addressing Extensions, PAE)， 这项技术可让原本仅支援到 4GB 实体记忆体的 32 位元硬体平台，可支援到最大 64GB 的记忆体喔！ 而且， Xen 几乎可以在所有的 P-II 以上等级的硬体平台上面跑半虚拟化任务，如果不跑全虚拟化的话，其实效能确实是 OK 的啦！

    近来由于虚拟机器软体的流行，加上 x86 电脑效能与 CPU 运算核心单元的增加，两大 x86 CPU 制造商 Intel/AMD 都发表了新的整合到 CPU 的虚拟技术，分别是 Intel 的 Vanderpool 虚拟技术以及 AMD 的 Pacifica 技术。 这些技术有的也支援 Xen ，这让 Xen 的效能增进不少呢！ ^_^

    小标题的图示 Xen 的运作环境解释
    在基础学习篇里面我们曾经谈过硬体、核心与应用程式的关系， 所有的应用程式都是在核心层之上来完成的 (注6)。 然后透过核心功能去呼叫与使用硬体元件的命令。好了， 现在来仔细想一想，既然我有多个虚拟机器，每个虚拟机器的环境各别有自己的作业系统核心， 也就是有多个作业系统同时存在。如果所有的作业系统都能够完整的控制硬体的话， 那么硬体到底该接受谁的指令来运作？那个系统的指令会先被执行？这是很重要的问题， 因为如果这边搞不定，那么你的硬体系统就只有当机一途。

    为了解决这个问题，Xen 也分成多个层级 (layer) 来执行。他将 Linux 的核心修改过后， 再使用这个修改过后的核心开机，而开机后先载入 Xen 的监督器 (Hypervisor) ， 并且启动第一个在上头的作业系统，我们称他为 domain-0。 (在 Xen 上面所谓的一个 domain 就是一个虚拟机器啰！)

    Domain-0 之所以要先被载入是因为 Domain-0 含有其他虚拟机器启动所必须的控制指令， 并且 domain-0 也是控制虚拟装置的重要主控系统。 在 domain-0 上头最重要的就是一个 xend 的常驻程式，其他的 domain 都是由这个 xend 来管理的。 至于命名方面，除了 domain-0 之外的其他虚拟机器就依序被称为 domain-1, domain-2 等等， 我们通称为 domain-U 啰。这些咚咚的相关性有点像这样：

    Xen Hypersvisor 的功能示意图
    图 2-1、Xen Hypersvisor 的功能示意图(注7)

    由上图我们知道 domain-0 真的是很重要的，因为他直接控制 Xen 的监督器 (Hypervisor)，而且掌握了实际的 Linux 驱动程式 (drivers)。而其他的虚拟机器 (domain-U) 则是透过 Xen 监督器来与实际的硬体以及 domain-0 达成沟通。而为了让 domain-0 能够与 Xen 结合，我们必须要修改 domain-0 的核心才能够顺利运作。并且需要使用 domain-0 的核心来开机才可以。 domain-0 是所有虚拟机器的来源，所以他可以尽量简单一点，其他的个别服务则可以放置到不同的 domain 当中了。

    那个 xend 也是很重要的咚咚，他可以管理 domain-0 与其他 domain 之间的启动与沟通， 可以提供一个终端机 (console) 介面来让 domain-0 登入其他的 domain ，所以我们也必须要启动这玩意儿才行。

    早期 Xen 尚未被各 distribution 整合到各自的版本中时，使用者必须要由 Xen 的官方网站下载原始码， 然后自行重新编译核心以及编译 Xen 软体才行。说实在的，玩个 Xen 这么麻烦，倒不如不要玩！^_^。 然而在 RHEL 5 (CentOS 5) 以后， Xen 已经包含在原始释出的套件中了，所以我们直接用 yum 就能够安装妥当！ 所以要搞定一部 Xen 的 domain-0 已经不再是不可能的任务啰！^_^

    对于 Xen 的基本原理有一些认识之后，接下来就让我们开始在 CentOS 5 上面进行一个小小的实验吧！

    小标题的图示 确定你的硬体是否支援 Xen 的运作
    虽然说目前的硬体都很新了，不过有的朋友使用的是旧的主机来安装 Linux ，所以我们必须要留意你的硬体是否支援 xen 的运作。而我们知道 Xen 支援半虚拟化与全虚拟化两种模式，两种模式的需求为：

  • 半虚拟化 (Para-virtualization) 硬体需求：
    • 只要是 64 位元的 x86 主机 (x86_64) 都能够支援半虚拟化的环境。如果是 32 位元的主机 (x86) 时， 该主机必须要支援的实体位址延伸技术 (PAE) 才能够使用 xen 喔！那如何确认呢？很简单，检查 CPU 的参数即可：
    [root@linux ~]# cat /proc/cpuinfo | grep flags
flags  : fpu tsc msr pae mce cx8 mtrr mca cmov pat pse36 mmx fxsr sse up
    嘿嘿！这一部主机是鸟哥的 P-III 800 主机，看吧！确实有支援 PAE 喔！所以当然可以玩 Xen 啰。

  • 全虚拟化 (Fully-virtualization) 硬体需求：
    • 如果你需要全虚拟化的技术支援时，此时需要硬体有支援虚拟化技术才行。 目前在 x86 的主机当中， Intel 提供 VT 技术， AMD 则提供 SVM 技术。 这两种技术在 CPU 的旗标分别是： Intel (vmx) 与 AMD (svm) 。 鸟哥在 Core Duo 主机上面的测试可以发现：
    在 Intel Core 2 Duo 的 CPU 主机上面测试 CPU 旗标：
[root@linux ~]# cat /proc/cpuinfo | grep flags
flags   : fpu tsc msr pae mce cx8 apic mtrr mca cmov pat pse36 clflush dts
          acpi mmx fxsr sse sse2 ss ht tm pbe nx lm constant_tsc up pni
          monitor ds_cpl vmx est tm2 cx16 xtpr lahf_lm
# 瞧！是有那个 vmx 的支援啦！
    至于 AMD 的主机旗标则是：(下表感谢donyingle兄的提供！)
    在 AMD Athlon(tm) 64 X2 的 CPU 主机上面测试 CPU 旗标：
[root@linux ~]# cat /proc/cpuinfo | grep flags
flags   : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov
          pat pse36 clflush mmx fxsr sse sse2 ht syscall nx mmxext fxsr_opt
          rdtscp lm 3dnowext 3dnow pni cx16 lahf_lm cmp_legacy svm extapic
          cr8legacy 3dnowprefetch ts fid vid ttp tm stc 100mhzsteps
# 瞧！是有那个 svm 的支援啦！
    如果确定你的 CPU 有支援上述的条件后，嘿嘿！那我们就可以开始底下的游戏啦！如果没有支援呢？ 那很抱歉，底下的资料看看就好！

    小标题的图示 所需要的 Xen 套件与核心
    注意： 在开始安装之前，请先参考前一小节以确定你的硬体已经支援 Xen 的半虚拟化功能了！

    约略谈了一下 Xen 的原理、特色之后，在开始玩弄 Xen 之前，我们得了解运作 Xen 所需要的各项套件，并且顺利安装后，才能够使用的啊！ ^_^。如同前一小节提到的， 要使用 Xen 半虚拟化 (Para-virtualization) 必须要修改核心才能够顺利的运作。 在以前的版本你需要重新编译核心，不过，在新的版本，例如 CentOS 5.x 底下，就已经将 Xen 的核心帮你编译好了！你可以直接安装即可。所以，你需要安装的套件主要有：
    • kernel-xen：修改的 Linux 核心，使可以跑 Xen 的环境；
    • xen：主要的 xen 套件，包括设定档、启动脚本、所需的基本函式库等；
    • xen-libs：Xen 所需要的函式库等；
    • python-virtinst：提供终端机安装的软体；
    • virt-manager：为一个图形使用者介面软体，可在图形介面管理 xen 喔！
    在 CentOS 5.x 的环境下，你可以使用 yum 直接来安装这几个套件。安装完毕后请务必使用新的核心开机！ 以鸟哥的例子来说，我安装了数个核心，包括 kernel-2.6.18-8.1.14.el5 及 kernel-xen-2.6.18-8.14.el5 ， 所以在 grub 的设定档当中会像这样：
    [root@linux ~]# vi /boot/grub/menu.lst
default=0
timeout=5
splashimage=(hd0,0)/boot/grub/splash.xpm.gz
hiddenmenu
title CentOS (2.6.18-8.1.14.el5xen)
        root (hd0,0)
        kernel /boot/xen.gz-2.6.18-8.1.14.el5
        module /boot/vmlinuz-2.6.18-8.1.14.el5xen ro root=/dev/hda1 rhgb quiet
        module /boot/initrd-2.6.18-8.1.14.el5xen.img
title CentOS (2.6.18-8.1.14.el5)
        root (hd0,0)
        kernel /boot/vmlinuz-2.6.18-8.1.14.el5 ro root=/dev/hda1 rhgb quiet
        initrd /boot/initrd-2.6.18-8.1.14.el5.img
    你必须要注意到，鸟哥使用的开机选单为第0个，亦即是 2.6.18-8.1.14.el5xen 那一个！ 然后重新启动这部 Linux 主机喔！启动完成后，应该再次的确认一下是否为 xen 的核心才行！
    [root@linux ~]# uname -r
2.6.18-8.1.14.el5xen
# 仔细看，鸟哥的核心为新的 xen 的核心喔！

[root@linux ~]# chkconfig --list | grep xen
xend        0:off  1:off  2:on   3:on  4:on  5:on  6:off
xendomains  0:off  1:off  2:off  3:on  4:on  5:on  6:off
# Runlevel 3/5 的 xen 相关服务是有启动的才行！

[root@linux ~]# pstree -p | grep xen
        |            |-xenbus(10)
        |            `-xenwatch(9)
        |-xenconsoled(2348)---{xenconsoled}(2349)
        |-xenstored(2340)
# 这样看来，应该确实是有启动的样子喔！继续最后一个确认！

[root@linux ~]# xm list
Name                  ID Mem(MiB) VCPUs State   Time(s)
Domain-0               0      462     1 r-----     49.2
# xm 为 Xen 的重要指令，list 为列出已经在跑的 xen 系统，预设有 domain-0 存在！
    透过上面的测试，我们会知道 xen 确实已经顺利的启动，而且也启动前面谈到的那个重要的 domain-0 啰！ 接下来我们再来聊一聊那 xen 的设定档在哪里？

  • xen 的套件结构
    我们前面谈到过， Xen 在 domain-0 是由一个 xend 的服务所管理的，他可以用来启动、关闭与连结到其他的 domain-U 当中。此外， Xen 亦提供许多的指令来让系统管理员管理他们的 domain-U 啊！这些重要的启动执行档为：
    • /usr/sbin/xend：就是 xend 的启动脚本，使用 python 程式语言写成的；
    • /usr/sbin/xm：重要的管理 xen 的指令，可输入 xm help 查询用法。
    至于与 xen 有关的设定档，包括一些模拟元件的启动脚本都在 /etc/xen 底下，在这个目录下的许多资料为：
    • /etc/xen/xend-config.sxp：这个重要！是 xend 的设定档！内容包括 domain-0 的类型、网路的连结方式、 domain-0 的记忆体与CPU等资源配置、是否使用 vnc 作为 domain-U 的连线方式等等。 不过，鸟哥觉得，这个档案不太需要更动，使用预设值就很够用了。

    • /etc/xen/：里面含有数个 domain-U 的设定档范本，包括：xmexample1, xmexample.hvm。 其中，那个 xmexample.hvm 可作为完整模拟的参考范本喔！

    • /etc/xen/auto：如果你想要在系统开机时就自动启动某个 domain-U 的话，可以将该设定档指定连结到这个目录中。 举例来说，如果你要在开机后立即使用 /etc/xen/xmexample.hvm 设定档来启动某个 domain-U ， 那可以这样做：
      [root@linux ~]# cd /etc/xen/auto
[root@linux auto]# ln -s ../xmexample.hvm .
# 这只是个范例，你可不要跟着做！因为 xmexample.hvm 还需要修改才能运作！
    • /etc/xen/scripts：这目录有趣了！包括虚拟设备的启动、虚拟网路的启动、 虚拟桥接器的启动等等，都是透过这目录底下的所有档案来达成的！
    在你安装完毕，并且使用新核心启动后，接下来让我们开始来处理一个小案例吧！

    • 小标题的图示 第一个泛用实例
    就如同图 2-1 的样子，在主机上的所有 Linux OS 都需要自己能够开机， 而开机流程通常是这样的：(注8)
    • step 1: 按下电源，主机开始读取 BIOS 资料；
    • step 2: 取得开机的装置顺序，并由 MBR 取得开机选单与开机管理程式；
    • step 3: 由开机管理程式载入 Linux kernel 及虚拟磁碟 (initrd)；
    • step 4: Kernel 侦测硬体载入适当的驱动程式，并挂载根目录以读取核心模组；
    • step 5: 开始由 /sbin/init 程式设定主机的环境。
    由上述的动作，我们可以知道 Linux 开机的重点在于 1. 核心 2. 虚拟磁碟 (initrd) 及 3. 根目录 (/) 了。 虽然核心与虚拟磁碟我们的 CentOS 5 已经提供了，但是预设的虚拟磁碟好像并未主动的加入 Xen 的某些驱动程式， 因此我们得需要针对虚拟磁碟进行设定才好。此外，每个 Xen domain 的根目录也很伤脑筋的！因为根目录需要很多资料，而且还需要挂载类似 /sys, /proc, /dev, /selinux 等特殊的档案系统哩！ 那该如何处理根目录呢？底下就让我们来处理处理：

  • 硬体支援性
    • 就如同前面几个小节谈到的，如果我们的硬体并不支援 xen 所必须要的功能，那么你是无法建立好你的 domain-U 的！ 在这个泛用案例当中我们的重点是测试半虚拟化，因此你只要具有 PAE 的支援即可。 鸟哥以较低阶的 P-III 800 来进行测试，硬体检查的结果是这样的：
    [root@linux ~]# cat /proc/cpuinfo | grep flags
flags  : fpu tsc msr pae mce cx8 mtrr mca cmov pat pse36 mmx fxsr sse up
    你可以发现确实存在那个 pae 的关键字，因此我们这个系统是可以玩 Xen 的半虚拟化技术的！ 所以让我们继续进行工作吧！

  • 根目录所需磁碟槽
    • 根目录所需磁碟槽的来源可以有两个，一个是实体硬碟，一个是利用 dd 建立一个大档案来使用。 鸟哥比较倾向利用 dd 来处理你的根目录喔！你可以这样做：
    范例：建立一个 5GB 的大档案
[root@linux ~]# mkdir -p /disk2/xen
# 因为鸟哥的 /disk2 为一颗额外的硬碟，所以容量比较大啦！

[root@linux ~]# cd /disk2/xen
[root@linux xen]# dd if=/dev/zero of=xen.img bs=1M count=5000
5000+0 records in
5000+0 records out
5242880000 bytes (5.2 GB) copied，178.482 秒，29.4 MB/s
# 这个时候会开始创造一个 5GB 左右的档案，由于硬碟速度快慢的关系，
# 这个动作可能会消耗数分钟到数十分钟不等。

[root@linux xen]# ll /disk2/xen
-rw-r--r-- 1 root root 5242880000 Oct 10 00:30 xen.img
    档案是建立起来了，不过如果你的 Linux 有启动 SELinux 的话，还需要一些类型的改变才可以！ 其实动作也不难，这样做就对了！
    [root@linux xen]# chcon -t xen_image_t -R /disk2/xen
[root@linux xen]# ll -aZ /disk2
drwxr-xr-x  root root user_u:object_r:xen_image_t      .
drwxr-xr-x  root root system_u:object_r:file_t         ..
-rw-r--r--  root root user_u:object_r:xen_image_t      xen.img
# 如果你有启动 SELinux 才需要这么做，否则就略过。
# 反正你要记得 Xen 的档案必须要是 xen_image_t 的安全内容类型。
    档案建立起来后，就需要进行格式化啰～格式化的方法为：
    范例：将刚刚建立的大档案格式化为 ext3 的档案格式
[root@linux xen]# mke2fs -j /disk2/xen/xen.img
mke2fs 1.39 (29-May-2006)
/disk2/xen/xen.img is not a block special device.
Proceed anyway? (y,n) y
Filesystem label=
OS type: Linux
Block size=4096 (log=2)
....底下省略....
    由于这是档案不是磁碟分割槽，所以会有上述的警告讯息，你按下‘y’就对啦！

  • 复制或安装根目录
    • 由于 domain-U 与 domain-0 其实是一样的系统，因为是半虚拟化嘛！所以，最简单的根目录制作方法， 就是将原本的 domain-0 的根目录复制到新的分割槽内就对了！ 以鸟哥的例子来说，你可以简单的这样做：
    [root@linux ~]# mount -o loop /disk2/xen/xen.img /mnt
# 先将刚刚制作出来的资料给他挂载起来，这是特殊挂载法喔！

[root@linux ~]# cp -ax /{root,dev,var,etc,usr,bin,sbin,lib} /mnt
# 这几个目录的资料是一定需要复制的！粉重要！。

[root@linux ~]# mkdir /mnt/{proc,sys,home,tmp,selinux}
# 这几个目录与虚拟档案系统有关，包括程序、核心资料等目录，所以要先建立

[root@linux ~]# vi /mnt/etc/fstab
/dev/sda1  /         ext3    defaults        1 1
devpts     /dev/pts  devpts  gid=5,mode=620  0 0
tmpfs      /dev/shm  tmpfs   defaults        0 0
proc       /proc     proc    defaults        0 0
sysfs      /sys      sysfs   defaults        0 0
# 我这里假设我的根目录所在磁碟槽为 SATA 硬碟的第一个分割槽，
# 所以是 /dev/sda1 。此外，其他的档案系统如 proc, sysfs 都必须要写入！
# 至于原本在 domain-0 的其他装置，就给他拿掉吧！

[root@linux ~]# vi /mnt/etc/sysconfig/network
NETWORKING=yes
NETWORKING_IPV6=no
HOSTNAME=xen.test.hostname
# 这里设定一下你的主机名称啦！

[root@linux ~]# vi /mnt/etc/sysconfig/network-scripts/ifcfg-eth0
DEVICE=eth0
BOOTPROTO=none
IPADDR=192.168.0.123
NETMASK=255.255.255.0
ONBOOT=yes
# 建议将 IP 也设好。但是要注意那个 HWADDR 最好能够拿掉不设定！

[root@linux ~]# umount /mnt
# 记得将挂载的资料给他卸载掉
    基本上，根目录的设定到这里就算结束了！不过，你会发现由于 domain-U 的资料都是由 domain-0 来的， 而不同的主机其实设定不会相同，所以使用上述的作法你会发现有几个小问题：
    • 你必须要手动处理一些小设定，包括主机名称, /etc/fstab, IP 参数等等；
    • 即使手动处理过上述的资料，还是很可能会无法成功的启动 domain-U ；
    • 由于 domain-0 可能会安装比较多的套件，这些资料又在 domain-U 当中用不着，徒然造成硬碟容量的浪费。
    所以，虽然这个方法最简单，不过通常鸟哥不是很建议您使用啦！ ^_^

  • 设定虚拟磁碟映象档以及终端机介面
    • 由于预设的 CentOS 虚拟磁碟 (Initial Ram Disk) 并不包含一些 Xen 的相关驱动程式， 因此搞了老半天也是无法驱动 Xen 的 domain-U ，给他气死！ 所以，我们得先就 initrd 来进行一些额外的设定才行。 这个地方非常的重要！因为鸟哥卡在这里好几天～最后才发现原来是 initrd 的问题啊～
    [root@linux ~]# mount -o loop /disk2/xen/xen.img /mnt
[root@linux ~]# cd /boot
[root@linux boot]#  mkinitrd -v -f --fstab /mnt/etc/fstab --with xenblk \
> --with xennet --preload xenblk --preload xennet \
> initrd-2.6.18-8.1.14.el5xen.vbird.img `uname -r`
[root@linux boot]# umount /mnt
# 详细的各项参数请 man mkinitrd ，上述的范例仅是利用 /etc/fstab 的装置来设定，
# 并且加上一些 xen 相关的驱动程式而已。这个过程非常的重要！
# 最终会制作出一个 initrd-2.6.18-8.1.14.el5xen.vbird.img 档案
    除了这个虚拟磁碟之外，为了要方便我们登入 domain-U 的环境，我们需要产生一个终端机介面才行。 因为每个 domain-U 会使用到终端介面，然而我们知道 tty1 ~ tty7 预设给 domain-0 使用掉了。 为此，我们必须得要制作出一个虚拟的终端介面，那就是 xvc0 这个终端介面啰。如何产生呢？ 简单的流程是这样：
    [root@linux ~]# vi /etc/inittab
# 大约在第 51 行的地方加入底下特殊字体的部分：
5:2345:respawn:/sbin/mingetty tty5
6:2345:respawn:/sbin/mingetty tty6
co:2345:respawn:/sbin/agetty xvc0 9600 vt100-nav
# 意思是使用 agetty 建立 xvc0

[root@linux ~]# init q
# init q 这个指令可以让 /etc/inittab  的设定立刻生效而不需要重新开机！

[root@linux ~]# ln -s /dev/console /dev/xvc0
# 如果 xvc0 没有主动建立的话，我们需要手动来建立连结才可以喔！
    做完这一步之后，接下来就是可怕的设定档啰～

  • 编辑 xen 虚拟资料的设定档
    • 接下来就是重头戏啦！因为我们必须要指定 domain-U 的相关虚拟设定值，包括使用几颗 CPU 、使用多少记忆体容量， 以及所使用的核心与根目录的所在等等。如前所述，这些设定档主要都在 /etc/xen 底下， 尤其里面的 xmexample1, xmexample2 等档案就是很好的说明文件档，很有参考价值。 鸟哥先说一下我的设定是这样的：
    [root@linux ~]# vi /etc/xen/centos5
# 这个档案的档名可以随便你取，不过设定档最好是在 /etc/xen 这个目录下才好！
name    = "centos5"
kernel  = "/boot/vmlinuz-2.6.18-8.1.14.el5xen"
ramdisk = "/boot/initrd-2.6.18-8.1.14.el5xen.vbird.img"
memory  = "128"
vcpus   = 1
vif     = [ '' ]
disk    = [ 'tap:aio:/disk2/xen/xen.img,sda1,w' ]
root    = "/dev/sda1 ro "
# name:		只是一个显示的名称，一般建议与档名相同即可；
# kernel:	在 domain-0 上面的档案，用来进行 domain-U 的开机！非常重要！
# ramdisk:	就是 initrd 那个档案啰～刚刚我们才做出来的档名
# memory:	分配给这个 domain-U 的记忆体有多少？如果没有图形，96 MB 也可以！
# vcpus:	使用多少颗 CPU 的意思；
# vif:		是否需要网路卡，如果需要网路卡，至少要有设定！但内容可用预设！
# disk:		用来作为根目录的是那个磁碟，这个最重要啦！语法为：
#	tap:aio:/完整/路径/档名,设计为domain-U的磁碟代号,可否写入
#		以我们这个例子来说，我将之前建立的大档案模拟成为 domain-U 的
#		/dev/sda1 ，并且该 partition 为可写入 (w)。
    特别特别留意的是，上面的设定档当中的 kernel, ramdisk 以及 disk 都是以原本的主机 (domain-0) 的角度来思考的， 也就是说，实际上我们是以 domain-0 的核心档案来进行 domain-U 的开机，因此你会发现在 domain-U 当中并不存在 /boot 这个目录喔！因为实际上用来开机的是 domain-0 的档案嘛！

    至于另一个重点就是那个 disk 参数。我们可以使用模拟的方式也可以使用实际的 partition 来给予设定。 如果是‘用档案来模拟成为 partition’时，使用两个逗号 (,) 隔开成为三个栏位，分别为：

    tap:aio:/完整路径/档案的名称,装置代号名称,写入与否
    • [tap:aio:]：为较新的档案处理模式，旧的方式为使用：[file:]
    • [装置代号名称]：就是模拟的装置，请与 domain-U 内的 fstab 对应起来喔！
    • [w]：就是设定可否写入，若唯读则为[r]
    如果使用实体 partition 来模拟的话，那么开头的部分会以‘phy:’来取代。举例来说，如果我们以 /dev/hda5 来作为 domain-U 的 /dev/sda1 的话，那就会变成：
      disk = [ 'phy:/dev/hda5,sda1,w' ]
    如果一切都搞定之后，接下来让我们来启动 Xen 的 domain-U 吧！

  • 利用 xm 指令启动与管理 domain-1
    • 在 domain-0 可以使用 xm 这个指令来启动、关闭、删除某个 domain-U ， xm 的指令用法是这样的：
    [root@linux ~]# xm [动作] [设定档名] [-c]
参数：
[动作]：要某个设定档内的 domain-U 作何动作之意，常见的动作有：
   create   ：启动这个 domain-U 的意思，例如启动 centos5 这个设定档时，使用：
              xm create centos5
   destroy  ：立即由记忆体中，将这个 domain-U 给删除，常用于 domain-U 出问题时
   list     ：将目前已经启动的 domain 都列出来之意；
   console  ：若有已建立的 domain-U 时，可用 console 来取得 domain-U 的终端介面
   shutdown ：关闭某个已启动的 domain。如果想要关闭全部的 domain-U ，可用
              xm shutdown -a
[设定档名]：亦即在 /etc/xen/ 目录下的档名啰；
-c ：同时建立到该设定档的终端介面 (console)
    如果想要启动我们刚刚建立的 centos5 这个设定档内的 domain 时，你可以使用‘xm create -c centos5 ’即可。 那个 -c 的作用是可以让你直接取得 domain-U 的终端机介面。鸟哥在 pietty 上面连线到 domain-0 ， 然后启动 centos5 这个 domain 的情况如下所示：

    启动 xen domain-U 的示意图
    图 2-2、启动 xen domain-U 的示意图

    在图 2-2 当中，输入指令后 domain-U 的开机流程就会依序的显示在你的终端机上， 感觉上就好像坐在电脑前面看 Linux 主机开机一样！实在是很不赖！最后如果开机顺利成功的话， 结果会像下图所示这样：

    启动 xen domain-U 的示意图
    图 2-3、启动 xen domain-U 的示意图

    在图 2-3 当中，最上方圈起来的开机讯息是错误讯息。由于我们是复制 domain-0 的所有资料， 因此连同原本写在 /etc/rc.d/rc.local 档案内的执行过程也会被执行。但是 domain-U 的状况与 domain-0 并非完全相同，所以就会如上所述出现一些错误讯息啦！这也是我们需要额外处理的部分喔。

    当你以 root 的身份登入后 (这个真的是终端机，并非是 ssh 的画面喔！)，会发现多了一个 xvc0 的终端介面， 这个介面得先在 /etc/inittab 里面设定好才行！如果一切都 OK 了！恭喜您，你已经登入 domain-U 啰！ 接下来请你自行根据你的需要来设定好你的 domain-U 吧！让这两个 domain 并行呢！

    好了，现在我如何登出 centos5 这个 domain-U 呢？你可以这样做的：
    • 直接在 domain-U 的环境中按下 [ctrl]-] 这个组合键来回到 domain-0 的环境；
    • 直接关闭 pietty 等连线的软体；
    • 利用其他 bash 来结束 (kill) 掉使用 xm 所建立的连线程序
    有趣的是，即使你使用上述的方法来离开 domain-U 时， 也不会影响到 domain-U 的继续运作！而且 root 也不会登出，等到你下次再以‘ xm console centos5 ’时， 会继续取得 root 的动作继续处理刚刚未完成的工作呢！很神奇吧～

    现在，请跳回 domain-0 的地方，或者是利用另外一条 pietty 的连线连入 domain-0 ，我们使用 xm list 来察看一下各个 domain 的状况吧！
    [root@linux ~]# xm list
Name             ID Mem(MiB) VCPUs State   Time(s)
Domain-0          0      366     1 r-----    735.2
centos5          42      127     1 ------     52.4
# 你会发现多了一个 domain 出现！名称为 centos5 啦！
# 你也会发现有个 State 吧！那个 State 的意义是这样的：
# r ：该 domain 正在使用 CPU 资源在运作中；
# b ：这个 domain 目前被悬置(blockded)，很可能由于这个 domain 在等待较长时间
#     的输入输出 (I/O) 之故。
# p ：该 domain 处于暂停的状态，通常由于管理员使用 xm pause 之故。
#     当 domain 在此状态时， Xen 的监督器将不会处理该 domain 的动作；
# s ：这个 domain 正在关机当中
# c ：这个 domain 已经 crash 了，但是却没有自动的关掉。通常是因为没有设定
#     on_crash 的相关动作所致。
# d ：该 domain 正在死亡中...因为该 domain 无法正确的 shutdown/crashed 之故。
    很简单吧！这样就完成你的 Xen domain 啰～开始将你所想要的网路服务分门别类的放到不同的 domain-U 中吧！ 加油！

    例题：关于如何登入 domain-U
      我在启动 domain-U 的时候，使用指令为‘ xm create domain-U ’导致我使用 xm list 可以看到新的 domain-U 在运作，但我还是在 domain-0 。请问此时我该如何登入 domain-U 呢？
    答：
      有两种方式，如果想要取得 domain-U 的终端机模式，请使用：

        xm console domain-U

      如果你知道 domain-U 的 IP，并且 domain-U 有启动类似 ssh/telnet 的服务时，可使用网路服务登入。举例来说 domain-U 的 IP 为 192.168.100.100，且有启动 ssh ，则你可以使用：

        ssh username@192.168.100.100

    例题：关于如何关闭 domain-U
      我使用 xm list 时，发现 domain-U 已经启动了，我该如何关闭这个 domain 呢？
    答：
      如果你在 domain-0 上头的话，可以使用：

        xm shutdown domain-U

      来关闭这个 domain-U ， 如果极端一点，你想要关闭所有的 domain-U (除了 domain-0 之外)，则可以下达：

        xm shutdown -a

      那如果你是在 domain-U 里面呢？想关闭该 domain 就直接给他：

        shutdowm -h now

      即可，就好像一般正常程序关机一样喔！ 那如果万一 domain-U 无法顺利关机，则你可以在 domain-0 上面直接下达删除的指令：

        xm destroy domain-U

    例题：关于重复登入的问题
      我利用 xm create -c domain-U 的方式取得终端机来登入 domain-U 了，结果另外一个使用者使用‘xm console domain-U’也来登入该 domain，此时会发生什么问题？该如何解决？
    答：
      由于预设情况下，一个 domain-U 仅有一个终端机，因此第二个登入者将不会询问帐号密码， 而是直接以第一个登入者的身份取得该终端介面，亦即两者将具有相同的终端介面与所有资源。 但如此一来会导致控制权的争夺效应，最终结果两者都无法控制该终端介面。此时建议两者均离开该终端介面， 然后让单一使用者以 xm console 登入，另一使用者则使用类似 ssh 的方式网路登入即可。

  • 常见错误分析
    • Xen 的启动其实是颇不容易的，常常会有一些错误情况发生。底下我们来看看一些常见的错误情况， 让您了解到，您无法启动 Xen 的可能原因为何？

  • 没有启动 Xen 的 xend daemon
    • [root@linux ~]# xm create -c centos5
Using config file "./centos5".
Error: Unable to connect to xend: Connection refused. Is xend running?
    如上所述，肯定你没有启动 xend 这个 daemon 的啦！直接启动他即可：‘/etc/init.d/xend start’

  • 使用到错误的核心或者 domain-0 未以新 xen 核心开机
    • [root@linux ~]# xm create -c centos5
Using config file "./centos5".
Error: (22, 'Invalid argument')
    然后请到登录档内看看，亦即是 /var/log/xen/xend.log 档内，如果出现如下的错误：
    [root@linux ~]# cat /var/log/xen/xend.log
[2007-10-17 13:18:48 xend.XendDomainInfo 31254] ERROR
(XendDomainInfo:203) Domain construction failed
    很有可能就是你的核心档案用错。此时请检查一下你的设定档，看看‘kernel’的项目是否设定正确？ 我们务必要使用 xen 相关的核心来开机才行啊！

  • SELinux 或者是档案权限的问题
    • [root@linux ~]# xm create -c centos5
Using config file "/etc/xen/centos5".
Error: Kernel image does not exist: /boot/vmlinuz-2.6.18-8.1.14.el5xen
    但我看过 /boot/vmlinuz-2.6.18-8.1.14.el5xen 确实是存在的，可能原因为何？一般来说，这种问题应该是 SELinux 的影响所致。确定方法可以用‘setenforce 0’然后再重新‘xm create -c centos5’测试看看， 如果确定可以登入，那表示您的 /boot/vmlinuz-2.6.18-8.1.14.el5xen SELinux 安全格式内容不对。 正确的核心开机类型应该是：
    [root@linux ~]# ll -Z /boot
-rw-r--r--  root root system_u:object_r:boot_t         config-2.6.18-8.1.14.el5xen
-rw-------  root root user_u:object_r:boot_t           initrd-2.6.18-8.1.14.el5xen.vbird.img
-rw-r--r--  root root system_u:object_r:boot_t         symvers-2.6.18-8.1.14.el5xen.gz
-rw-r--r--  root root system_u:object_r:system_map_t   System.map-2.6.18-8.1.14.el5xen
-rw-r--r--  root root system_u:object_r:boot_t         vmlinuz-2.6.18-8.1.14.el5xen
    请自行使用 chcon 指令来处理 SELinux 的错误吧！
  • Kernel panic 的问题
    • 如果出现如下的可怕画面时：
    ....前面省略....
Loading ext3.ko module
Creating root device.
Mounting root filesystem.
mount: could not find filesystem '/dev/root'
Setting up other filesystems.
Setting up new root fs
setuproot: moving /dev failed: No such file or directory
no fstab.sys, mounting internal defaults
setuproot: error mounting /proc: No such file or directory
setuproot: error mounting /sys: No such file or directory
Switching to new root and running init.
unmounting old /dev
unmounting old /proc
unmounting old /sys
switchroot: mount failed: No such file or directory
Kernel panic - not syncing: Attempted to kill init!
    出现这个‘Kernel panic’的问题非常的多且复杂，其实主要的原因就是无法挂载根目录。 因为你核心档案已经进行侦测，并且虚拟磁碟档案 (initrd) 也已经载入啰！ 那什么情况下会无法挂载根目录呢？你应该要这样查阅：

  • 1. 用来作为根目录的档案 SELinux 类型不对：

    首先，请先到 /var/log/messages 里面察看一下，如果出现如下画面：
    Oct 17 12:04:17 xen-test kernel: audit(1192593857.395:259): avc:
denied  { search } for  pid=29687 comm="tapdisk" name="/" dev=hdc1
ino=2 scontext=system_u:system_r:xend_t:s0
tcontext=system_u:object_r:default_t:s0 tclass=dir
# 上面是同一行，意思是说，该档案读取被拒绝了，因为程序的格式为：
# scontext=system_u:system_r:xend_t:s0 ，但是你的档案格式为特殊字体部分，亦即：
# tcontext=system_u:object_r:default_t:s0
# 所以这个档案的读取就被‘deny’了！
    这表示你用来作为根目录的档案 SELinux 类型不对，正确的档案类型是这样的：
    -rw-r--r--  root root user_u:object_r:xen_image_t      xen.img
    所以你可以使用类似底下的方式来处理：
    [root@linux ~]# chcon -t xen_image_t -R /disk2
    似乎连同最顶层的 /disk2 都需要修改 SELinux 安全内容才行！所以你可以加 -R 来让子目录生效！

  • 2. initrd 虚拟磁碟没有载入正确的模组

    另一个可能原因就是虚拟磁碟并没有载入 domain-U 需要的模组，所以你必须要仔细看上面的输出讯息有没有这个项目：
    Creating block device nodes.
Loading xenblk.ko module
XENBUS: Timeout connecting to device: device/vbd/2049 (state 3)
Loading xennet.ko module
netfront: Initialising virtual ethernet driver.
netfront: device eth0 has flipping receive path.
Loading uhci-hcd.ko module
    这表示已经载入了 xen 的相关模组，如果你的画面没有这个讯息时，请参考前一小节关于虚拟磁碟的说明。并且更新你的 domain-U 设定档吧！

  • 3. 设定档内容写错

    很多时候我们都会打错字～实在很麻烦～所以如果上述两点你都确认过了，接下来请检查一下你的打字有没有问题。 假设我的 xen 档案是放置到 /disk2/xen/xen.img 里头，那么两个地方要注意：
    [root@linux ~]# vi /etc/xen/centos5
name    = "centos5"
kernel  = "/boot/vmlinuz-2.6.18-8.1.14.el5xen"
ramdisk = "/boot/initrd-2.6.18-8.1.14.el5xen.vbird.img"
memory  = "128"
vcpus   = 1
vif     = [ '' ]
disk    = [ 'tap:aio:/disk2/xen/xen.img,sda1,w' ]
root    = "/dev/sda1 ro"
    模拟的装置 (disk 项目内) 以及根目录的所在装置 (root 的项目) 需要配合成功，否则就会失败了！ 当然啦，模拟的装置也必须要跟实际的档案相同才行喔！

  • domain-U 本身的问题
    • 如果开机已经到达下面的状况时：
    unmounting old /sys
INIT: version 2.86 booting
                Welcome to  CentOS release 5 (Final)
                Press 'I' to enter interactive startup.
正在设定时钟  (localtime): 三 10月 17 13:24:28 CST 2007 [  确定  ]
正在启动 udev: [  确定  ]
....中间省略....
正在检查档案系统
Checking all file systems.
[/sbin/fsck.ext3 (1) -- /] fsck.ext3 -a /dev/hda1
fsck.ext3: No such file or directory while trying to open /dev/hda1
/dev/hda1:
The superblock could not be read or does not describe a correct ext2
filesystem.  If the device is valid and it really contains an ext2
filesystem (and not swap or ufs or something else), then the superblock
is corrupt, and you might try running e2fsck with an alternate superblock:
    e2fsck -b 8193

[失败]

*** 检查档案系统时发生错误。
*** 系统将带您进入 shell 模式; 然后重新开机
*** 当您离开 shell 时。
Give root password for maintenance
(or type Control-D to continue):
    注意到上面特殊字体的部分，既然已经出现了 INIT 的字样，这表示 domain-U 已经通过了核心侦测、 根目录挂载等动作，且已经顺利的在执行 /sbin/init 这个指令了，因此我们可以确信所有的 Xen 设定都是正确的， 可能发生的错误就在 /disk2/xen/xen.img 这个档案内的配置了。你可能需要依据开机流程一个一个的去处理相关的错误喔！ 最可能发生的就是在 domain-U 的 /etc/fstab 啰～
    大标题的图示 其他半虚拟化的安装方式
    由前一小节的泛用实例我们可以了解，如果 domain-U 的根目录来源为复制自 domain-0 的话， 那么我们必须要手动修改很多设定档，非常的麻烦～ 既然如此，有没有可能我们可以自行将安装程式放入根目录的建置呢？也就是说， 那个 /disk2/xen/xen.img 的内容其实就是经过安装程序而来的，而不是经由复制的。 如此一来不就所有问题都解决了，而且新安装的系统还是很干净的系统呢！ 确实如此！目前 CentOS 5 提供一个好用的软体，那就是 virt-install， 你可以使用 virt-install -h 来察看可以使用的指令哩。

    但是在开始底下的实例之前，你必须要知道几点限制才行：
    • 最简单的安装方式为复制 domain-0 的根目录来给 domain-U 使用(就是前面的范例)；
    • 半虚拟化的安装方式‘并不支援使用光碟或 DVD 的安装模式’；
    • 半虚拟化仅可透过 http, ftp, nfs 等方式来安装干净的 Linux 系统；
    看到上头的限制您应该会吓一跳吧！怎么不能用原版光碟安装喔？没错～是这样！ 使用原版光碟或者是原版光碟的 iso 档案安装时，仅有全虚拟化环境可以达到而已。 那你应该会问，我如何制作或者是取得安装用的伺服器呢？其实我们可以利用各大专院校的 FTP 网站即可啊！ 不需要自行设定安装伺服器的。不过，如果你的环境并非学术网路的话，最好还是自行设定一下安装伺服器比较妥当。 为了每位不同所在处的朋友，所以底下我们先快速的讲一讲如何制作一部安装伺服器，然后再处理其他工作吧！ ^_^

    小标题的图示 制作安装伺服器 (Installation Server)
    如前所述，半虚拟化的 Xen 仅支援 NFS, HTTP, FTP 等网路方式安装，并不支援原版光碟安装的模式， 因此我们得要找到可提供安装的主机才行。如果您在台湾的学术网路中， 那么可以选择国家高速网路中心或者是义守大学的 FTP 网站做为来源，举例来说，如下网址就是一个案例：
      http://ftp.isu.edu.tw/pub/Linux/CentOS/5.0/os/i386/
    万一你是一家企业呢？那最好使用内部的主机架设成为安装伺服器来安装你的 domain-U 比较妥当。 以下鸟哥以 NFS 的方式来简单说明一下建置 CentOS5 的安装伺服器啰。
    1. 选择容量大于 5GB 以上的磁碟分割槽：

      由于完整的 CentOS5 原版光碟含有好多的套件，至少也需要 3500MB 以上的容量来容纳 DVD 碟内的所有资料。 但是鸟哥的主机当初没有额外规划扩充性的问题，因此就得要加挂硬碟啦！ 鸟哥是将我的 CentOS5 原版光碟放置到俺的 /disk1/yum/centos5 目录下的， 这个目录为另外一个独立的 partition ，关于 partition 的处理方法请自行参考基础篇的说明，这里不赘述了。

    2. 复制所有需要的套件：

      先挂载 CentOS5 的光碟或 DVD 碟，然后直接复制即可：
      [root@linux ~]# mount /dev/cdrom /mnt
[root@linux ~]# mkdir -p /disk1/yum/centos5
[root@linux ~]# cp -a /mnt/* /disk1/yum/centos5
[root@linux ~]# umount /mnt
      如果你是使用光碟的话，那么上述的动作就得要进行六次，因为 CentOS5 共有六片光碟。 而且每片光碟内会有一些重复的档案，因此系统会警告你‘是否要覆盖？’此时按下‘y’去覆盖即可。

    3. 建立安装所需要的档案关连性资料

      一般来说，使用 yum 的系统在他 RPM 档案所在的目录下都会有一个名为 repodata 的目录， 该目录记录着档案的相关性以及一些基本的安装资讯。但因为我们将资料复制到自己的主机上， 因此一些基本资料可能就不会吻合，所以我们需要重新制作出这个目录才行。 制作这个目录必须要安装 createrepo 套件，预设的情况下是不会安装该套件的， 因此我们可以这样做：
      [root@linux ~]# yum install createrepo
# 就是安装某个套件而已，这个套件就是用在制作 repodata 目录的。

[root@linux ~]# cd /disk1/yum/centos5
[root@linux centos5]# cp repodata/comps.xml /tmp
# 先将某些安装资讯给他复制出来，准备利用。

[root@linux centos5]# rm -r repodata
# 原本的资料不需要了，将他删除掉再说。

[root@linux centos5]# createrepo -g /tmp/comps.xml .
# 重新建立好 repodata 目录啰！

    4. 启动与设定 NFS 档案系统

      接下来就是设定 NFS 啦！为什么要选择 NFS 呢？因为他够简单！哈哈！
      [root@linux ~]# vi /etc/exports
/disk1/yum/centos5      *(ro)
# 先设定好 NFS 所要分享的目录所在

[root@linux ~]# chcon -t public_content_t -R /disk1/yum/centos5/
# 确定一下你的这个目录是可以透过 SELinux 来管理分享的！

[root@linux ~]# /etc/init.d/portmap start
[root@linux ~]# /etc/init.d/nfs start
[root@linux ~]# /etc/init.d/nfslock start
# 将服务给他启动吧！

[root@linux ~]# showmount -e localhost
Export list for localhost:
/disk1/yum/centos5 *
      如果可以看到最终的结果，那就表示你的 NFS 制作妥当了！
    最终可以知道我们是：
    • 安装协定使用 NFS
    • 主机名称为你这部主机的 IP， 注意，不要使用 127.0.0.1 来安装！
    • NFS 的路径为 /disk1/yum/centos5
    好了，开始来安装干净的 Linux 系统在 domain-U 上面吧！

    小标题的图示 利用 virt-install 指令安装干净的 CentOS
    有了 NFS 安装伺服器后，再来我们使用 virt-install 来安装啰～ 安装的方式非常的简单，你可以这样做即可：
    1. 先建立我们所需要的大档案来作为 domain-U 的磁碟：
[root@linux ~]# dd if=/dev/zero of=/disk2/xen/centos5.virt.img \
> bs=1M count=4096
[root@linux ~]# chcon -t xen_image_t /disk2/xen/centos5.virt.img
# 我建立了一个 4GB 大小的档案来作为安装之用！这个容量应该是够用的！ ^_^
# 比较需要注意的是，如果你有启动 SELinux 时，请注意修改档案的安全内容。

2. 开始使用 virt-install 来安装吧！
[root@linux ~]# virt-install -n centos5_virt -r 256  \
> -f /disk2/xen/centos5.virt.img --nographics \
> -l nfs:192.168.1.254:/disk1/yum/centos5
# -n ：后面接你的 domain-U 的名称，这个名称的设定档会被主动建立在 /etc/xen 底下
# -r ：后面接你要给这个 domain-U 的记忆体，目前至少需要 256MB 才能够执行
# -f ：后面接的就是那个要给 domain-U 的大档案啰！
# --nographics ：不使用图形介面来安装的意思；
# -l ：后面接安装伺服器的来源。安装伺服器的写法为：
#   NFS 时：   nfs:主机的IP:可以安装的目录
#   WWW 时：   http://主机的IP/实际的/完整目录
#   FTP 时：   ftp://主机的IP/实际的完整目录
    如果一切顺利的话，现在就能够进入安装画面了！不过请注意，您的 domain-0 需要开放防火墙让人家使用 NFS 喔！ 否则你是无法顺利安装的啦！ ^_^

    接下来的画面鸟哥是以 pietty 连上 domain-0 之后进行画面撷取的，因为 Xen 的终端机介面显示本来就怪怪的， 加上鸟哥所使用的画面较小，所以您会发现怎么字体都会跑掉～真是不好意思～ 总之，跟一般文字介面的安装方式是一模一样啦！让我们开始来看看图示吧！

  • 1. 语系的选择：

    如下图所示，由于终端机模式仅有英文显示字元，因此我们直接选择‘English’吧。 请注意使用 [Tab] 按键在各个元件之间跳动喔！

    先选择语系资料
    图 3-1、先选择语系资料

  • 2. 关于 domain-U 安装时的 IP 设定：

    一般 IP 设定有 DHCP 与手动设定，如果你的主机所在环境具有 DHCP 伺服器，且你的安装伺服器有针对内部网域开放防火墙时， 那为了方便，你可以直接使用 DHCP 协定即可，如下图所示：(一般来说，鸟哥都会建议先取消 IPv6 的支援)

    设定 IP 取得为 DHCP 或者是手动直接给予 (Manual)
    图 3-2、设定 IP 取得为 DHCP 或者是手动直接给予 (Manual)

    万一你的主机所在环境没有提供 DHCP 的服务时，那你的 IP 就得要手动给予了。在上图当中请选择‘ Manual configuration ’项目，则会出现如下图所示的情况，请填入区域网路的 IP 参数吧。 在本例中鸟哥的 domain-U IP 设定为 192.168.1.31/255.255.255.0 啰～

    手动设定 IP 的示意图
    图 3-2-1、手动设定 IP 的示意图

  • 3. 欢迎画面与分割槽警告讯息：

    接下来仅是说明欢迎的画面，还有，因为我们使用的档案会被视为‘一颗硬碟’而不是一个 partition ， 所以会有警告讯息说明要注意的地方而已。请留意，在预设的情况下， 模拟的硬碟代号为 /dev/xvda 喔！

    只是欢迎画面！
    图 3-3、只是欢迎画面！

    只是一个警告讯息，直接 OK 过去！
    图 3-4、只是一个警告讯息，直接 OK 过去！

  • 4. 开始进行磁碟分割的动作：

    进入安装模式后，这个地方最重要！我们刚刚建立了一个 4GB 的档案作为硬碟之用，而这颗模拟硬碟的磁碟为 /dev/xvda， 我们知道在安装的时候最重要的两个 partition 为 / 与 swap ，所以就得要进行底下的分割咯！ 如下所示，首先我们必须要建立一个客户自订的分割情况 (Create custom layout)， 请使用 [Tab] 按键选择如同下图的说明：

    决定分割的模式，请使用 Custom layout
    图 3-5、决定分割的模式，请使用 Custom layout

    接下来进入到下图之后，我们必须要建立根目录 (/) 与虚拟记忆体 (swap)，在这里我设定根目录为 3200MB， 至于 swap 则设定 256MB。建立的方法依序如下：

    进入分割画面的情况
    图 3-6、进入分割画面的情况

    依照图中的说明，分别选择各项参数
    图 3-7、依照图中的说明，分别选择各项参数

    另外一个 Swap 的设定方法
    图 3-8、另外一个 Swap 的设定方法

    若前两个画面设定妥当后，最后你会看到如下的图示，检查看看是否一个根目录与一个 swap 呢？ 若没问题的话，就按下 [OK] 吧！

    最终的分割表状态
    图 3-9、最终的分割表状态

    只是警告虚拟记忆体比实体记忆体少，不用理会他！
    图 3-10、只是警告虚拟记忆体比实体记忆体少，不用理会他！

  • 5. boot loader 以及开机选项

    设定到此，我们可以开始来决定开机管理程式的相关动作了。首先，当然一定需要 boot loader 啊！ 所以如同下图，我们要使用 Grub 啰！

    使用 grub 作为开机选单
    图 3-11、使用 grub 作为开机选单

    在预设的情况中，domain-U 所使用的终端介面 (console) 为利用 xvc0 这个装置来处理的， 这个部分预设会出现，所以不必理会他！

    domain-U 所使用的终端介面装置
    图 3-12、domain-U 所使用的终端介面装置

    是否需要开机选单密码？不需要吧？
    图 3-13、是否需要开机选单密码？不需要吧？

    选单只有一个，所以就不用改了。
    图 3-14、选单只有一个，所以就不用改了。

    图 3-15、当然是安装在 /dev/xvda 的 MBR 中！

  • 6. 网路设定参数：

    再来就是网路参数的设定部分，鸟哥建议您可以先随便设定，未来要使用这个 domain-U 时， 再详细的设定即可。在这里鸟哥都使用预设值来指定而已。

    使用预设的 DHCP 与 IPv4 即可
    图 3-16、使用预设的 DHCP 与 IPv4 即可

    主机名称也先不要设定，使用 DHCP 预设值
    图 3-17、主机名称也先不要设定，使用 DHCP 预设值

  • 7. 时区与 root 密码：

    因为我们使用台湾时区，所以这里要仔细的选择喔！

    时区请务必选择台湾啊！
    图 3-18、时区请务必选择台湾啊！

    root 密码要设定，不要随便啊！
    图 3-19、root 密码要设定，不要随便啊！

  • 8. 套件安装的选择以及实际开始安装：

    由于我们希望的 domain-U 是用来进行伺服器架设的，所以这里鸟哥选择 Server 而已， 如下图所示。整体安装起来差不多是 1.x GB 的容量而已喔！

    仅选择 Server 的安装设定
    图 3-20、仅选择 Server 的安装设定

    仅是分析套件的相依性画面而已
    图 3-21、仅是分析套件的相依性画面而已，请等待！

    这个是通知讯息，告知你的选择将会被记录到该处
    图 3-22、这个是通知讯息，告知你的选择将会被记录到该处

    看到否，开始安装的整个过程
    图 3-23、看到否，开始安装的整个过程

    安装完毕，请重新开机吧！
    图 3-24、安装完毕，请重新开机吧！

    重新开机完毕后，出现等待登入的画面示意
    图 3-25、重新开机完毕后，出现等待登入的画面示意

    整个过程非常的简单，就如同你在安装一部文字介面的 Linux 主机一般。 从开始安装到结束的整个过程中，花费比较多时间在设定项目，完整安装差不多 10 分钟就搞定了。 这还是因为鸟哥使用旧型主机来安装的，鸟哥曾以新 P4 主机来安装过这一整个流程， 开始安装到结束不到 3 分钟，实在是非常的快速啊！

    接下来你可以查阅一下 /etc/xen/centos5_virt 显示的内容， 该档案是由 virt-install 主动帮我们建立的，我的资料如下所示：
    [root@linux ~]# cat /etc/xen/centos5_virt
# Automatically generated xen config file
name = "centos5_virt"
memory = "256"
disk = [ 'tap:aio:/disk2/xen/centos5.virt.img,xvda,w', ]
# 仔细瞧，发现 xvda 了吗？就是这里决定的啦！

vif = [ 'mac=00:16:3e:2f:4a:ef, bridge=xenbr0', ]
# 可以直接指定模拟网卡的实体卡号以及使用的桥接器

uuid = "9a968f71-c36b-d48a-5a03-304bb41a639f"
# 甚至可以直接定义装置的 uuid 号码呢！

bootloader="/usr/bin/pygrub"
# 没有核心了！而是利用 domain-U 自己的核心来开机的！
# 要使用 domain-U 的核心来开机，就得用这个设定项目才行！

vcpus=1
on_reboot   = 'restart'
on_crash    = 'restart'
    接下来请开始使用 xm create -c centos5_virt 来启动这个干净无暇的 domain-U 啰！

    • 小标题的图示 CentOS5 所提供的一个实例
    虽然 virt-install 已经有够好用了，不过在某些情况下还是无法执行的。首先， virt-install 要求 domain-U 在安装时一定要给予 256MB 的记忆体，如果你的记忆体少于 256MB 时，肯定无法执行 virt-install ～ 再者在 SELinux 启动的情况下，可能还会有无法执行 virt-install 的情况发生。 还好， CentOS5 提供了一个可以驱动安装程式的核心给我们来进行安装过程！ 接下来我们将以 CentOS5 官网所提供的 kernel file 来进行安装的实作喔！

    其实整个过程挺简单的，最重要的就是必须要使用 CentOS5 官网所提供的核心与虚拟磁碟映像档， 有这两个东西就能够处理安装的程序了。底下我们就一步一步来处理这个设定吧！

  • 0. 建立网路连线所需的 DHCP 伺服器
    在预设的情况下 Xen 使用的网路环境为利用桥接方式 (bridge) 来连结实际的网路环境。 但在这种模式底下 domain-U 在安装时，取得 IP 的方式主要为利用 dhcp 协定， 使用手动的方式来设定 IP 却是不可行的方案！除非要转成利用 NAT 的模式来处理。 假设我们都先不更改 Xen 的预设环境，那么我们就得要针对 Xen 的网路模式来建立一部 dhcp 伺服器了。

    详细的 dhcp 伺服器建置方法请参考伺服器架设篇的介绍， 鸟哥在这里仅利用一些时间很快的将整个流程处理一下吧！ 需要注意的是，如果你的网域内已经有一个 public 的 dhcp 了，那么您在建置这个给 domain-U 用的 DHCP 时， 特别留意不要影响到其他的 dhcp 主机喔！鸟哥这里假设我的 domain-U 的 MAC 为 00:16:3E:00:00:11 ， 所以有针对这个 MAC 来处理喔！
    1. 先检查你的 domain-0 是否有安装 dhcp 呢？
[root@linux ~]# rpm -qa | grep dhcp
dhcp-3.0.5-5.el5
# 如果没有出现上述的套件时，请自行使用 yum install dhcp 吧！

2. 修改 DHCP 的设定档
[root@linux ~]# vi /etc/dhcpd.conf
ddns-update-style none;
subnet 192.168.1.0 netmask 255.255.255.0 {
     option routers                  192.168.1.254;
     option subnet-mask              255.255.255.0;
     option domain-name              "xen.test";
     option domain-name-servers      168.95.1.1;
     range 192.168.1.20 192.168.1.25;
     default-lease-time 21600;
     max-lease-time 43200;
     host dic1 {
          hardware ethernet 00:16:3E:00:00:11;
          fixed-address 192.168.1.31;
     }
}
# 鸟哥就是利用那个 hardware ethernet 来控制某个网卡来源的要求的啦！

3. 启动与观察
[root@linux ~]# /etc/init.d/dhcpd start
[root@linux ~]# netstat -tlunp
Proto Recv-Q Send-Q Local Address  Foreign Address State  PID/Program name
udp        0      0 0.0.0.0:67     0.0.0.0:*              22285/dhcpd
# 重点在那个 port 67 啰～

4. 防火墙的处理！
[root@linux ~]# iptables -I INPUT -p udp --dport 67 -j ACCEPT
[root@linux ~]# iptables -A INPUT -s 192.168.1.0/24 -j ACCEPT
# 重点在开放用户端对于主机的连线啰！这个要设定好！
    如此一来 DHCP 主机就设定好了，简单吧！再来开始其他的处理吧！

  • 1. 建立 domain-U 所需要的虚拟磁碟
    同样的，利用 dd 这个指令来建立他吧！鸟哥依旧将我的映像档放置到 /disk2/xen 底下去。
    [root@linux ~]# dd if=/dev/zero of=/disk2/xen/centos5.office.img  \
> bs=1M count=3072 oflag=direct
[root@linux ~]# chcon -t xen_image_t /disk2/xen/centos5.office.img
[root@linux ~]# ll -Z /disk2/xen/centos5.office.img
-rw-r--r--  root root user_u:object_r:xen_image_t    centos5.office.img
    除了要建立这个大档案之外，不要忘记那个可爱又可怕的 SELinux 类型也需要同时变更！ 这点大家都很容易忘记！包括鸟哥在内～ @_@

  • 2. 设定终端机介面
    这个动作在前面的小节中已经讲过了，这里特别再列出来，因为如果你没有作这个动作， 很可能在 domain-U 的地方会让您无法使用 console 的方式登入 domain-U ，届时您可能需要使用类似 ssh 的网路连线方式才能够登入 domain-U 哩！ 而且，如果没有作这个动作，你的 domain-0 则会一直在 /var/log/messages 出现一些错误～实在讨厌～ 实作的方法很简单：
    [root@linux ~]# vi /etc/inittab
# 大约在第 51 行的地方加入底下特殊字体的部分：
5:2345:respawn:/sbin/mingetty tty5
6:2345:respawn:/sbin/mingetty tty6
co:2345:respawn:/sbin/agetty xvc0 9600 vt100-nav
# 意思是使用 agetty 建立 xvc0

[root@linux ~]# init q
# init q 这个指令可以让 /etc/inittab  的设定立刻生效而不需要重新开机！

[root@linux ~]# ln -s /dev/console /dev/xvc0
  • 3. 下载 CentOS5 用来安装 Xen 的核心与映像档
    CentOS5 官网提供的可安装 Xen 核心在底下的连结，分为 i386 与 x86_64 版本：
    • i386: http://mirror.centos.org/centos/5/os/i386images/xen/
    • x86_64: http://mirror.centos.org/centos/5/os/x86_64images/xen/
    鸟哥使用的是 i386 的版本。下载与处理的方式可以这样做：
    [root@linux ~]# cd /boot
[root@linux boot]# wget  \
> http://mirror.centos.org/centos/5/os/i386images/xen/vmlinuz
[root@linux boot]# wget  \
> http://mirror.centos.org/centos/5/os/i386images/xen/initrd.img
# 先下载这两个档案下来，为了方便记忆，所以鸟哥习惯将档名修改一下：

[root@linux boot]# mv vmlinuz centos5_xen_vmlinuz
[root@linux boot]# mv initrd.img centos5_xen_initrd.img
[root@linux boot]# restorecon /boot/*
# 最后一个动作 (restorecon) 在处理 SELinux 的问题啦！
    所以我们已经取得 CentOS5 官网所提供的核心与映像档了！准备处理设定档啰～

  • 4. 撰写‘安装用’设定档
    接下来我们得先就可安装的核心来进行设定档的编写。我这里比较有趣的地方在于几个部分：
    • 我具有 NFS 安装伺服器，该伺服器 IP 为 192.168.1.254，路径为 /disk1/yum/centos5
    • domain-U 在安装时的 MAC 假设为 00:16:3e:00:00:11，且透过 DHCP 取得 IP；
    • 使用 kickstart 方式来安装，而 kickstart 的设定档放置到安装伺服器的 /disk1/yum/centos5/ks.xen.centos5.txt 内
    什么是 kick start 呢？我们刚刚在前一小节使用 virt-install 安装时，不是有很多的选择画面吗？ 所谓的 kick start 就是将所有的选择项目都写入某一个设定档，如此一来，就可以免除手动去挑选的困扰了。 因此，我们会有两个档案需要建立。首先，我们建立 Xen 的设定档，档案如下：
    [root@linux ~]# vi /etc/xen/centos5_xen_install
kernel  = "/boot/centos5_xen_vmlinuz"
ramdisk = "/boot/centos5_xen_initrd.img"
extra   = "text ks=nfs:192.168.1.254:/disk1/yum/centos5/ks.xen.centos5.txt"
name    = "centos5_xen_install"
memory  = "128"
disk    = [ 'file:/disk2/xen/centos5.office.img,xvda,w', ]
vif     = [ 'mac=00:16:3e:00:00:11, bridge=xenbr0', ]
vcpus   = 1
on_reboot = 'destroy'
on_crash  = 'destroy'
# 上面比较特别的只有那个 extra 而已，那个是核心的额外参数说明！
    我们还得建立 kick start 的设定档内容。其实你的 CentOS 本来就有 kickstart 的设定档了， 详情请参考你自己的 /root/anaconda-ks.cfg 档案，您就晓得啰！更详细的 kickstart 请先参考如下网页：
      http://freesf.tnc.edu.tw/docs/rh/rhl-cg-zh_TW-9/ch-kickstart2.html
    鸟哥这里仅作个简单的设定而已：
    [root@linux ~]# vi /disk1/yum/centos5/ks.xen.centos5.txt
# 1. 与安装有关的设定，尤其是 NFS 的设定最要紧！
install
nfs --server=192.168.1.254 --dir=/disk1/yum/centos5

# 2. 语系的支援以及键盘对应表
lang en_US.UTF-8
langsupport --default en_US.UTF-8 zh_TW.BIG5 zh_TW.UTF-8 zh_HK.UTF-8 \
zh_CN.GB18030 en_US.UTF-8
keyboard us

# 3. 网路设定，记住，要与 NFS 安装伺服器同网域才行！
network --device eth0 --bootproto dhcp

# 4. 密码与防火墙还有 SELinux 与时区的相关设定
rootpw --iscrypted $1$NGE.r9ik$D9iqc2bfdpi1DYvqC2CwP.
firewall --enabled --port=
authconfig --enableshadow --enablemd5
selinux --enforcing
timezone Asia/Taipei

# 5. 开机管理程式，注意那个 driveorder 项目，我们的硬碟是虚拟的喔！
bootloader --location=mbr --driveorder=xvda --append="console=xvc0"
reboot

# 6. 磁碟分割表的操作以及安装的套件资料
clearpart --all --initlabel --drives=xvda
part /boot --fstype ext3 --size=100 --ondisk=xvda
part / --fstype ext3 --size=2048 --ondisk=xvda --asprimary
part swap --size=512 --ondisk=xvda
%packages
@core
# 如果你曾经安装过 Linux ，那么上面的选项对你来说，应该不难了解。
# 比较特殊的是 rootpw 那个项目，鸟哥是由 /etc/shadow 复制加密的密码来的，
# 如此则 root 的密码也设定妥当，而且是加密过的资料。
# 在本案例中的 root 密码为 123456789 喔！

[root@linux ~]# chcon -t public_content_t \
> /disk1/yum/centos5/ks.xen.centos5.txt
    如此则将两个设定资料给他设定好了。接下来就是进行安装的流程喔～

  • 5. 实际安装过程
    实际安装真是太简单了！直接启动 Xen 即可啊！请下达：‘xm create -c centos5_xen_install’吧！ 然后在出现一小段时间的 IP 侦测、硬体侦测、套件资料分析等画面后，就会主动的进入实际安装套件的画面！ 接下来我们啥事都不需要担心，所有的安装过程 kickstart 系统都会帮我们搞定的。 实际上，你要做的就只是...喝茶看报纸吧！不过如果你的 domain-0 系统非常的高效能， 老实说，喝茶的时间实在是不够用～ @_@，因为可能 3 分钟就安装完毕了～ ^_^

    kickstart 就是这么好用！你可以将这一组设定放在你的安装伺服器上面，未来想要安装一模一样的环境时， 直接在安装的过程载入这个档案即可，我们不需要还手动挑选有的没有的啦！ ^_^

  • 6. 修改成为可以正常开机的设定档
    在上述第四个步骤时，我们所建立的 /etc/xen/centos5_xen_install 是专门用来安装用的设定档。 既然已经安装妥当了，这个档案就不能继续的使用，否则每次都会重复的进入安装的画面， 会一直不断的重新安装....

    所以接下来我们得要修改一下设定档才行。设定档可以改成底下的模样喔：
    [root@linux ~]# vi centos5_xen_run
name    = "centos5_xen_run"
memory  = "128"
disk    = [ 'file:/disk2/xen/centos5.office.img,xvda,w', ]
vif     = [ 'mac=00:16:3e:00:00:11, bridge=xenbr0', ]
vcpus   = 1
on_reboot = 'restart'
on_crash  = 'restart'
bootloader = "/usr/bin/pygrub"
# 其实就是加入那个 pygrub 的执行档而已。该档案的作用就是
# 作为一个开机载入器来载入 domain-U 开机所需使用的核心与虚拟磁碟。
    接下来如果想要使用刚刚完成的 domain-U 来登入时，请使用：‘ xm create -c centos5_xen_run ’来启动吧！ 启动的画面如下所示，你会发现，怎么透过终端机可以跟在荧幕前面一个模样！还能看到 grub 哩！ 真是有够棒的！

    启动 domain-U 的画面
    图 3-26、启动 domain-U 的画面

    选择好你所需要的开机选项后，嘿嘿！就能够在 pietty 之类的环境完整的操作你的 domain-U 了！ 说实在的，用在教学上，实在是很棒的一个好主意！
    • 大标题的图示

    大标题的图示 参考资料
    • 注1：Apache 是一种 WWW 伺服器软体，虚拟主机 (virtual host) 的概念可以参考底下连结：
      http://linux.vbird.org0360apache.htm#www_adv_virtual
    • 注2：鸟哥的著作之一，Linux 基础篇，网路文件请参考：
      http://linux.vbird.org/linux_basic
    • 注3：鸟哥的著作之一，Linux 伺服器架设篇，网路文件请参考：
      http://linux.vbird.org/linux_server
    • 注4：多重开机，一部主机内有多种作业系统，可在开机的时候选择想要执行的 OS。请参考：
      http://linux.vbird.org/linux_basic/0156installfc4.htm#moreOS
    • 注5：请参考 Xen 的 Users' Manual version 3.0：
      http://www.cl.cam.ac.uk/research/srg/netos/xen/readmes/user/user.html
      鸟哥这里的备份：http://linux.vbird.org/linux_security/xen/user.pdf
      • 也有简体中文版：http://www.linuxsir.org/main/?q=node/188
    • 注6：关于硬体、核心与应用程式的相关性请参考：
      http://linux.vbird.org/linux_basic/0110whatislinux.htm#whatislinux_os
      http://linux.vbird.org/linux_basic/0320bash.htm#bash_what
    • 注7：关于图示的说明可以参考彦明兄的一篇文章：
      http://linux.vbird.org/somepaper/20070214-xen_on_sles_10.pdf
    • 注8：关于更多的开机流程与相关资讯，可以参考底下网页：
      http://linux.vbird.org/linux_basic/0510osloader.htm
    • 注

      其他参考资料：
    • axa 网友在酷学园的一篇 Xen 说明，虽然是针对 Gentoo 版本，不过很值得一看：
      http://phorum.study-area.net/printview.htm?t=35725
    • The Xen virtual machine monitor：http://www.cl.cam.ac.uk/research/srg/netos/xen/index.html
    • Xen Clustering with CentOS 5：http://meshier.com/2007/06/13/xen-clustering-with-centos-5/
    • Xen 的网路模拟情况：http://wiki.xensource.com/xenwiki/XenNetworking
    • CentOS 5 的 Xen 范例：http://wiki.centos.org/HowTos/Xen/InstallingCentOSDomU
    • YHTSAI的部落格：http://www.yhtsai.idv.tw/blogs/index.htm?blog=4
    • Fedora Xen Quick Start：http://fedoraproject.org/wiki/FedoraXenQuickstartFC6
    • 安装 Windows 在 Linux 下：http://linux.vbird.org/linux_security/xen/xen_install_windows.pdf
    • Xen 的其他详细解说：http://www.lslnet.com/linux/f/docs/linux-5520.htm
    • 一些关于网路的设定方式：http://linux.chinaunix.net/bbs/redirect.htm?tid=910815&goto=lastpost
    • http://www.debian-administration.org/articles/360
    • http://phorum.study-area.org/index.htm/topic,52293.msg266975.html
    2007/10/20：经过多日的奋战，终于将 Xen 的半虚拟化安装与操作的方法写出来！全虚拟化的部分还在构思中～
    2007/10/24：透过网友 lvan 的回报，发现没有建置 /dev/xvc0 会有终端介面的问题，所以补上；
    2007/10/24：同样透过 lvan 兄的回报，可以使用 [ctrl]-] 来离开 domain-U 的终端介面！谢谢 lvan 兄！
    2008/09/09：感谢讨论区网友donyingle提供的AMD的64位元CPU的相关资讯，终于有CPU的flags了！