【资料】Linux基础教程

楼主
【资料】Linux基础教程
目录:第1章 TCP/IP基础

1.1 基本概念 7

1.1.1 TCP/IP 7

1.1.2 IP地址和子网 8

1.1.3 网络硬件 10

1.2 地址和路由选择 11

1.2.1 地址解析和路由器 11

1.2.2 地址扩充和伪装 14

1.3 连接和数据传输协议 17

1.3.1 控制和传输协议 17

1.3.2 服务器和应用层协议 18

第2章 Linux基础 21

2.1 文件系统 21

2.1.1 UNIX和树状文件系统 21

2.1.2 文件类型和文件组织 23

2.1.3 使用文件系统 24

2.1.4 VFS、缓冲和ext2 26

2.1.5 其它文件系统 27

2.2 系统内核基础 27

2.2.1 什么是内核 27

2.2.2 可加载模块和设备驱动程序 28

2.2.3 内核不做什么 29

2.3 shell和配置程序 29

2.3.1 命令解释程序 30

2.3.2 不同的shell 33

2.3.3 配置程序、文档和编辑器 33

2.3.4 定制环境 36

2.4 用户和权限 38

2.4.1 用户、组和文件属性 38

2.4.2 超级用户和SU 40

2.4.3 setuid和setgid 41

2.5 进程和守护 42

2.5.1 进程和作业管理 42

2.5.2 forks和exec 45

2.5.3 守护和服务器守护程序 46

2.6 账户管理 48

2.6.1 口令文件 48

2.6.2 账户的添加和删除 50

2.6.2 特殊账户 51

2.7 Linux版本和其他服务器系统 51

2.7.1 Linux的内核版本和发行版本 51

2.7.2 其他服务器操作系统 52

第3章 安装Linux系统 57

3.1 准备工作 57

3.1.1 获取Linux发行版 57

3.1.2 准备服务器硬件 58

3.1.3 准备安装规划 60

3.2 RedHat 的安装过程 63

3.2.1 建立Linux引导盘 63

3.2.2 开始系统安装 63

3.3 Turbolinux中文版安装过程 71

3.3.1 启动Turbolinux 安装程序 72

3.3.2 TurboLinux安装过程 72

3.4 SuSe的安装过程 80

3.5 配置X Window 85

第4章 系统配置 89

4.1 系统启动流程 89

4.1.1 lilo和引导内核 90

4.1.2 运行级别和inittab 93

4.1.3 rc.d下的基本脚本 95

4.1.4 版本之间的区别 100

4.2 网络配置 101

4.2.1 配置网卡 101

4.2.2 TCP/IP的启动 102

4.2.3 协议和路由配置 104

4.2.4 配置工具 107

4.2.6 inetd服务器 111

4.3 定制内核 113

4.3.1 配置系统内核 114

4.3.2 使用新内核 117

4.3.3 从灾难中恢复 118

4.4 使用硬盘 119

4.4.1 为系统安装新的硬盘 119

4.4.2 分区和建立文件系统 119

4.4.3 交换分区 123

4.5 打印机和其他设备 125

4.5.1 配置打印机 125

4.5.2 其他可能的设备 129

4.6 安装应用程序 129

4.6.1 rpm程序 129

4.6.2 编译应用程序 131

4.6.3 其他 132

第5章 局域网服务器 135

5.1 NFS和文件/打印服务 135

5.1.1 共享文件系统 135

5.1.2 通过网络进行打印 139

5.2 Samba服务器 140

5.2.1 在windows环境中集成Linux 141

5.2.2 swat程序 148

5.2.3 重新编译samba 150

5.2.4 从Linux使用windows 文件服务 151

5.2.5 WINS和NetBIOS 152

5.3 DHCP 153

5.4 NIS 157

5.5 远程过程调用和X客户/服务器 161

5.5.1 r命令 162

5.5.2 X Window的客户/服务器模式 164

5.5.3 exceed 164

第6章 Intranet 167

6.1 域名系统 167

6.1.1 DNS的工作模式 167

6.1.2 bind 8 服务器配置 169

6.2 文件传输服务 175

6.2.1 wu-ftpd的配置和管理 175

6.2.2 其他的服务器 179

6.3 WWW服务器 179

6.3.1 Apache服务器 179

6.3.2 proxy系统 184

6.3.3 虚拟主机 186

6.3.4 身份控制 187

6.3.5 重新编译Apache和附加产品 189

6.3.6 SuEXEC和其他 192

6.3.7 高级课题 193

6.3.8 联机手册 195

6.4 BBS和MUD 195

6.4.1 BBS 195

6.4.2 文本MUD 196

第7章 电子邮件 197

7.1 sendmail 和SMTP 197

7.1.1 smtp和邮件传输代理 197

7.1.2 sendmail的配置 200

7.1.3 邮件分拣 209

7.1.4 Fetchmail 211

7.1.5 测试sendmail 214

7.2 POP3服务 216

7.2.1 POP3服务 216

7.2.2 安全性和其他问题 217

7.3 管理邮件队列 218

7.4 qmail 219

7.4.1 下载和编译附加文件 219

7.4.2 安装qmail 220

7.4.3 启动smtp投递代理 222

7.4.4 启动pop3服务 222

7.5 讨论组 223

7.5.1 NewsGroup 223

7.5.2 邮件列表 228

第8章 路由器和防火墙 229

8.1 核心IP转发和Linux路由器 229

8.1.1 Linux的IP转发功能 229

8.1.2 Linux路由器 232

8.1.3 广播路由路径 233

8.2 IP过滤和代理 234

8.2.1 ipchains和IP过滤 234

8.2.2 NAT和IP代理 238

8.3 基于IPChains的防火墙系统 240

8.3.1 防火墙的设计 240

8.3.2 实例说明 242

8.4 拨号网络连接 246

8.4.1 拨号网络连接 247

8.4.2 拨号代理 253

8.4.3 拨号服务器 254

8.5 网络代理程序 258

8.5.1 squid代理程序 258

8.5.2 socks 5及其使用 262

第9章 管理、维护和排错 263

9.1 启动和关机 263

9.2 系统记录 265

9.2.1 syslog 266

9.2.2 进程记账 269

9.3 硬盘管理 272

9.3.1 磁盘限额 273

9.3.2 回收磁盘空间 278

9.3.3 fsck程序 279

9.4 自动作业程序 281

9.4.1 cron程序 281

9.4.2 at守护进程 284

9.5 备份和恢复 285

9.5.1 tar程序和数据备份 285

9.5.2 dump、cpio和其它程序 288

9.5.3 使用软磁盘 289

9.6 网络管理和排错 290

9.6.1 确定网络故障 290

9.6.2 对网络进行监视 292

9.7 账号管理 295

9.8 系统升级和补丁程序 297

9.9 性能调整 298

9.9.1 性能监视 299

9.9.2 调整系统参数 301

9.9.3 服务器的特有问题 302

9.10 负载均衡和其他手段 304

9.10.1 反向代理和Apache本身的优化 304

9.10.2 DNS负载均衡 305

9.10.3 NAT和集群服务器 306

第10章 安全性问题 309

10.1 安全性问题概述 309

10.1.1 安全性级别 309

10.1.2 你安全吗? 311

10.2 访问控制 312

10.2.1 保护你的口令 313

10.2.2 setuid 315

10.2.3 身份认证工具 316

10.3 加密和解密 316

10.4 sniffer和反措施 320

10.4.1 sniffer 320

10.4.2 ssh 322

10.4.3 SSL和https协议 323

10.5 扫描器和其它工具 324

10.6 对服务器的远程攻击 326

10.6.1 WWW和电子邮件的安全性 326

10.6.2 缓冲区溢出 327

10.7 拒绝服务攻击 328

10.8 使用关于安全性的邮件列表 330

第11章 任务的自动化 331

11.1 TCL和expect 331

11.1.1 TCL语言 331

11.1.2 expect 335

11.2 awk和文件的处理 338

11.2.1 grep和正则表达式 339

11.2.2 gawk的使用方法 340

11.3 Perl 347

11.3.1 基本语法 347

11.3.2 perl的使用 358

11.4 其他工具 359

附录A:常用命令和实用程序 361

附录B:joe 使用简介 367

启动joe 367

编辑操作 367

删除 367

移动光标 367

块使用 368

查找 368

文件操作 368

退出 368
1楼
【资料】Linux基础教程 1.1 基本概念
1.1 基本概念

1.1.1 TCP/IP

TCP/IP是UNIX/LINUX世界中网络的基础,甚至,在某种意义上,UNIX网络就是TCP/
IP,而且TCP/IP也就是网际互联的标准。你可能知道有一个叫OSI(开放系统互联标准
)的模型,它是教科书上描述网络互联的标准模型,不幸的是,这个标准在实际的网络
世界中毫无意义,尽管许多教程会以它为模板传授网络理论。这是对标准化和美国政府
的一种嘲弄。事实是,TCP/IP在前进,而OSI已经不复存在。

本书试图直接按TCP/IP的构成来理解问题,尽管这也许不会在考试中给你带来高分,
但它确是唯一合理的方式。如果你喜欢OSI那种似乎井井有条的方式,你总会找到合适的
教材的。

作为网络互联的标准,TCP/IP给出的是一系列协议,这些协议要完成各种各样的网络
应用支持。你可以合理地把这协议看成一组编程接口,一旦应用程序了解这些接口便能
使用网络。为了实现这种抽象,TCP/IP被分成了四层,我们可以通过一个WWW浏览器来
看看这四层的概况:
应用层:www,SMTP,DNS,FTP

传输层:解释数据

网路层:定位IP地址、确定连接路径

链路层:与硬件驱动程序对话


首先WWW浏览器必须调用HTTP协议,这个协议规定用什么样的命令来得到WWW文本,这
种协议构成了TCP/IP的最高层— 应用层。

为了使用HTTP协议,浏览器要把命令发送到服务器上去,并且从服务器得出回答,
但是,必须记住,网络上传输的总是些字节,哪些字节是命令,哪些是回送数据,又有
哪些是用于表示“就绪”,“传输中”或者“停止”的验证码呢?这些解释工作需要一
串复杂的协议进行控制,这构成了第三层 — 传输层。

假定所有校验和和控制字都已经完毕,现在要把这些数据真正发送到对方那里,那么
,面对下一个问题是:这台机器到底位于哪里?如果保证数据被发送到了我希望的位置
?这种地址定位构成了第二层一网路层。

最底层 — 链路层完成最终的工作:将地址、数据等等变换成真正的电气信号,并且
在网络上送出,让网络设备彼此对话。

在以后的各节中,我们将会概述一下各层的情况及与我们相关的主要的问题。相信我
,这里讨论的只是主要的问题。许多问题由于仅有历史的意义而无需考虑,而另外一些
问题不太象是一个LINUX管理者会非常关心的,例如ATM交换。相反,如果要管理LIN
UX务嚣,迟早你必需理解ARP和路由选择。

我知道从理论上说一个服务器管理员也许根本不需要了解下面陈述的问题,也许需要
知道更深奥得多知识。但是根据我的经验,一旦你成为服务器管理者,并且你是在真实
世界而不是管僚机构中,你将很快发现一切困难的任务都必须由你来完成,而且毫无商
量余地,最终你会看到你将成为整个系统的管理者。了解足够多的东西,你将会在系统
管理员的恶梦中生存下来。

在后面的解释中,你将看到TCP/IP是如何工作的,但是我们必须先说明一件事情,你
很容易看出,TCP/IP的设计是有弹性的,实际上,存在某种方法把其他网络协议当成TC
P/IP的基础,例如,我们一般让TCP/IP协议直接与网卡驱动程序对话,但是,也可以想
象这样的情况,把其他的网络协议,例如IPX当成一种虚拟的“网络设备”,这样,TCP
/IP就可以运行在其他的网络协议之上,这种技术被称为IP隧道。不过,在本章中,我们
将不涉及如此复杂的问题。

1.1.2 IP地址和子网

你肯定知道,互联网用IP地址来标识主机地址,而数据传输则是通过把数据分成一
列的小“包”来完成。TCP/IP世界里的每一台主机都要有唯一的IP地址,这个IP地址是
一个32位无符号整数,不过通常使用点分十进制表示。例如,0001000011000001111111
1000000001是二进制的281148929,但是实际应用中把它按照8位一段的方法分成四段,
第一段是00010000,也就是16,第二段是11000000,十进制是192,同样,剩下来的两段
是254和1,因此这个地址是16.192.254.1。

这听起来很简单,但是在实际实现中有些复杂,主要问题是TCP/IP必须兼顾许多困难
的问题,其中之一是网络联接。全世界有太多的网络主机,随便给你一个主机号,你怎
么知道它在哪里?最大恶梦在于,或许13.2.0.5在美国纽约,而64.0.7.6 却在北京,如
果搜索一台主机地址就要查阅全世界的主机列表的话,那么互联网将立即崩溃。

解决这一个问题的第一个要点是网络分类.分类把世界上的IP地址分段,各段之间独立
管理,通常每一段用同样的方式连接到一起,本段的机器之间可以直接互相访问,这样的一
个段称为一个系列网络地址。

为了管理的方便,分段用一个有点古怪的方式。例如,对些公司(比如IBM),一个上
万台机器的网络很正常,而小公司也许只有十几台机器,TCP/IP实现中用A、B、C类地
址来处理这个问题。

A类地址用于超过65534个主机的网络,例如,一个前缀为18的网络使用18.0.0.1~18.
255.255.254的网络地址,这些地址之间是直通的,主机之间可以彼此访问。为了说明这
一点,TCP/IP使用网络掩码和网络地址的概念。

在上面的例子中,网络地址是18.0.0.0,这表示网络的包含地址段是18.0.0.1~18.25
5.255.254,即地址部分除去前缀后,余下的部分由全零变成全1,不过全1的地址将保留
为广播使用。

与网络地址相应,对在此网络中的主机,TCP/IP使用网络掩码。在上面的例子中,掩
码是255.0.0.0,其含义是这样:假设18.0.0.3想和18.110.75对话,那么,将这两个地
址相互异或,再与掩码取“与“(&),结果是零 ,说明这两个地址可以直接对话;相
反,如果要与19.1.1.1对话,那么运算之后不为零,说明必须使用间接方式才能到达。

可以用直接方式理解掩码,掩码中的“1“用来描述网络地址(前缀),“0“用来描
述子网的主机,如:255.0.0.0意味着将主机地址的前8位解释为网络号,而后24位解释
成网内的主机地址。也就是说,与某个A类主机地址前8位相同的主机地址被认为是在同
一子网之内。

A、B、C类用下面的方式规定:

A类地址使用255.0.0.0的掩码,为了管理方便, 规定A类地址总是使用头一位为0的地址
值,这意味着A类地址是从1.0.0.0到126.0.0.0另外还有一个特殊的A类地址127.0.0.0它
用来表示"本机",即自身。

B类地址使用255.255.0.0的掩码,B类网从128~0.0.1到191.255.0.0。

C类地址的掩码是255,255.255.0,网络地址从192.0.0.0到233.255.255.0。

首字节在224以上的地址用于实验和开发,部分用于组播, 通常无需关心。

地址255为特殊的含义,它用于广播,即“向本网上所有人通话”。这个概念对任何人
都应该是很容易理解的。使用广播有两种方法,并且是几乎等价的,即:(1)使用全1的
地址,即255.255.255.255 。(2)使用本址广播,即用网络号加上全1。例如,A类网180
.0.0.0可以使用18.255.255.255广播,B类网190.4.0.0的广播地址则是190.4.255.255。
无论哪一种,对于广播地址的访问都将引发对数据发送给本网络上的所有机器。

计算网络掩码和标志子网地址是网络管理者经常需要进行的工作,第一种计算是根据
某个确定的主机地址和它的网络掩码求出所有可以和它直接通信(在同一子网之内)的
主机地址。例如,主机地址是202.112.50.3,掩码是255.255.255.0,与它可以直接通话
的主机的地址可以这样计算:掩码是255.255.255.0,因此32位网络地址的前24位被解释
为网络地址,所以凡是和202.112.50.3的前24位内容相同的主机地址就和它处在同一子
网之内,后8位是子网里面的机器地址,它可以从全0变到全1,所以所有和这个主机在同
一子网之内的主机的地址是202.112.50.0-202.112.50.255。

网络地址/掩码一般用斜线分开,如网络地址是202.199.248.0,掩码255.255.255.0在
UNIX中一般写成202.199.248.0/255.255.255.0。但是也有另外一种写法,就是用掩码中
1的个数来代替掩码的实际形式。例如,255.255.255.0的前24位是1,其他位是0,因此
可以写成202.199.248.0/24。同样,下面的两栏地址形式是彼此等效的:

202.199.248.0/255.255.255.0 202.199.248.0/24

122.24.0.0/255.255.255.0 122.24.0.0/16

13.4.5.7/255.0.0.0 13.4.5.7/8

我们在前面一直设置掩码的0/1分界在字节边界处,但是这其实并不是必须的。完全可
以有其他形式的掩码。例如,240等于二进制的11110000,因此一个255.255.255.240的
掩码意味着前面28位是网络地址,而后面4位是子网内的IP。同样,网络地址也可以不由
0结尾。举个例子来说,202.112.50.16/255.255.255.240是什么意思?202.112.50.16是
二进制的11001010011100000011001000010000,套上一个有28位为1的网络掩码,意味着
最后四位由全0变成全1,就是最小是11001010011100000011001000010000,最大是1100
1010011100000011001000011111,这两个数是202.112.50.16和202..112.50.31,所以这
个网络地址代表202.112.50.16到202.112.50.31的所有主机。这个网络地址也可以写成
202.112.50.16/26。

1.1.3 网络硬件

TCP/IP并不关心具体的网络实现,但是不幸的是系统管理员必须了解。你的网卡可能
会失效,以太网可能会拥塞,调制解调器会被击穿,还有诸如此类的种种问题。另一方
面,特别对于以太网,如何将IP地址译码成实际的电气位置是非常重要的问题。

对于一般的系统,最重要的两种网络连接是以太网和电话线。以太网使用同轴电缆,
双纹线或光纤作为连接介质,面电话线则为广域网提供主要的连接手段。

以太网无疑是最主要的网络技术,对一个DIY人员来说,10MB或100 MB以太网的硬件
连接如此简单以至于无需在这里作任何描述。但是有几个特殊点可能仍然需要指出。首
先是以太网的通讯协议。

以太网命使用一种载波监听/碰撞检测的方式工作,因为线路上跑的是电气讯号,所
以以太网卡通过监视电缆电位来判断是否有某个设备在传输数据。如果网卡接到一个发
送任务,它首先判断线路上是否有数据传输,如果有,它等待一会:如果没有,它就以
一个特定的数据包大小(帧)将数据发送到线路上。

以太网的帧格式有些怪异,它允许在帧中包含帧的类型,当一个帧到达某台计算机时
,计算机根据帧的类型作不同的处理。如果你经管理过Netware,那么肯定会面对802.2
或802.3以及Ethernet -II的种种令人晕头转向的配置问题。幸运的是,在Linux或者W
indows的世界里,你极少需要真正处理它们。

当一个帧被发送到网络上时,它实际上是在网络的整个电气连接上漫游。“电气连接
”指电信号可以传递到的任何地方,比如,集线器上连接的几片网卡,穿过几根电缆或
双绞线,等等。然而一台机器上的两片网卡不在一个电气连接上,因为电信号无法直接
在两者之间传递。(你会问如果这两片卡正好插在同一个集线器上会如何,我只能说:!
@#$%)每个以太网卡必须有一个唯一的“以太网地址”,也叫MAC地址。它是一个48位整
数,理论上,它应该是全世界唯一的,当网卡发出一个数据帧时,它在帧的头部包含发
送者和接收者的“以太网地址”,因此,当一个网卡“听到”与自已地址适应的帧时,
它接收这个数据帧。显然,只要整个电气连接上没有两片网卡的“以太网地址“相同,
这种方式就可以工作。

有几个特殊的问题,首先,“以太网地址”必须在整个电气连接上唯一,当然你会想
:“这是肯定的; 2的48次方比任何电气连接都大得多”,这很难说,确实有某些不那
么聪明(或不那么负责,也许仅仅不太走运,随你去猜)的厂商生产过一些以太网地址
完全相同的网卡,如果拿到这样的网卡,你必须找到厂家提供的设置程序修改以太网地
址,用术语叫“设置MAC地址”。第二,你可能会想,是否以太网的这种工作方式意味着
任何帧实际可以被整个网络的成员收听到而不是确定地送到对应地址,答案是确实如此
。有一种叫“嗅探器“的东西就是干这个的;最后,由于电信号实际是以近于光速的速
度传播,所以可能会发生这样的情况:两片网卡同时发现网络空闲,同时传送数据,结
果造成信号的混乱。术语中这叫碰撞。以太网卡可以通过电位检测判断出碰撞的存在,
一旦发生碰撞,碰撞两者立刻停止发送数据,等待一段时间,随后重新试图发送。由于
以太网的信号共享性质,对于连接数太多的网络,网络碰撞将使行实际上每次发送都会
碰撞,这时我们说以太网已经拥塞,你必须分割或升级网络连接了。

广域网连接中,最主要的是基于电话拨号的IP连接。但是这包含着许多种类型,其中
最主要的也许是调制器和ISDN连接。对于专线的连接,曾经流行过一个称为X .25的分组
交换协议,但是这已成为历史。事实上,从逻辑角度看来,电活线连接比以太网简单得
多,因为你不必关心信号应该传送给谁的问题。不幸的是,它们实在太慢,而且也过于
昂贵了。

一般情况下,我们用以太网构成局域网连接再用其它技术(例如DDN或者ISDN)将整个
局域网连入Internet。在这种情况下,我们必须了解许多事情,特别是关于网际互联的
一些行为方式。

1.2 地址和路由选择

这一节我们来研究数据在网络上如何寻址,特别是与ARP和RIP相关的一些内容。如果
你准备用Linux实现廉价的路由器和防火墙,那么这部分知识是必需的。

1.2.1 地址解析和路由器

如同我们在以太网能够实现网卡之间的直接地址数据传送,为此,它要了解发送者和
接收者的MAC地址,对于需要向所有连接者通知的内容,它使用广播,广播可以被所有网
络接口设备接收。

MAC地址是一个48位的整数,它用来标记网卡,问题是TCP/IP用IP地址来描述传输地
址,而IP地址是32位的,那么,如何将IP地址转换为MAC地址呢?

为了解决从IP地址到实际的设备之间的转换问题,TCP/IP定义了两件事情,首先是地
址转换协议ARP,它用来解决在一个子网之内如何将IP地址转换为实际的设备位置。显然
,设备可以不仅是以太网,但是象调制解调器这样的连接,其地址翻译在建立连接时就
已经确定了。而令牌环等设备在地址确定方面实际是和以太网一样的,所以我们主要讨
论的将是以太网。

假设某主机想和与自己同子网的机器通信,例如202.14.0.3到202.14.0.7,它首先将
使用以太网提供的硬件广播功能:首先广播一个数据包,其内容将包括:自己的IP地址
,自己的MAC地址,以及试图通讯的IP地址。由于硬件广播可以送到以太网电气连接的任
何地方,所以202.14.0.7如果开着就会接收到这个数据包,于是它向202.14.0.3回送一
个数据包(因为广播包中已经包含了202.14.0.3的MAC地址,所以B知道如何送数据),
内容将包含202.14.07的MAC地址。这样,一个“广播-应答”就确定了两台机器的MAC地
址。

为了提高效率,每台机器都会在自己的系统上维护一个对照表,每当得到一个应答或
是听到一个地址广播,机器就在自己的对照表中加入一项,这样以后再需要与相应地址
通信时就可以直接从表中查到MAC地址。因为MAC到IP的映射可能会改变,所以对照表被
设定为每过一段时间更新一次。

因为ARP是靠广播来维护的,所以在一个庞大的网络系统内部,广播可能会消耗大量网
络资源,这曾经带来许多问题。随着以太网将速度提升到GB级,ARP广播已经不那么令人
头痛,然而某些广播仍然十分讨厌。

ARP解决了在同一物理网络系统之内IP到物理地址的解析问题,而对需要跨越子网的通
信,TCP/IP使用路由的方法。

路由器是一台用作子网之间数据传送的计算机,它接收由某个子网来的数据请求,并
将它转发到另一个子网上,你可以考虑,类似于下面的结构



图1.1 路由器说明

子网A中的机器需要与B中的机器对话时,它首先判断出机器不在本子网之内,于是它
把请求包发送到R上。

R上有两个网络接口,不妨假定A、B的网络地址是192.168.1.0和192.168.2.0,而R上
的两个接口分别是192.168.1.3和192.168.2.6,显然,A可以把它数据包发送到192.168
.1.3上,当路由器尺接到这样一个数据包时,它发现这个数据包的地址是在网络B中,于
是它将数据包提交给B上的接口192.168.26,然后这个接口就可以直接与目标机器对话了
。当B中机器反馈这个响应时,发生相反的过程。

对于更复杂的情况,工作方式与这个例子是一致的。所不同的是,这时由A到B的路径
可能更加复杂,有两种标准案可以考虑。

首先的方法是采用递送缺省路由方式,比如,考虑下面的一个情况:

图1.2 路由递送

在子网A中有一台计算机,地址为192.168.1.1,它想和192.168.3.7对话,按照网络掩
码,它知道192.168.3.7不在自己的子网内,于是它把信息投递到路由器R1。

路由器R1知道目标地址是192.168.1.0/24的信息应该发送到子网A,对于192.168.3.7
,它也一无所知。但是它知道这个网络上还有另外一个与它相连的路由器R2,于是它把
信息投递到R2。R2知道192.168.2.0/24的信息如何投递,但也同样不知道关于192.168.
3.7的事情,于是它再将自己的信息投递到自己的缺省路由器R3,最后,R3发现目标地址
正是它所负责的网络地址,于是,投递成功。

另外一个方法是为了解决上面方法的一个缺陷。例如,由于用户可能动态地加入和移
除网络,使得路由表将频繁地修改。为此,可以使用动态修正的方法,让每个路由与其邻
近的路由器联系,不断交换路由信息,使得路由信息表总是可以使用。如何交换路由信
息构成了TCP/IP协议的重要部分。

无论哪一种方案,都可能成数据包在路由之间循环。解决的方式是引入一个“跳“的
概念,为每一个数据规定一个最大跳数,每通过一个路由器被减去一跳,当跳数达到零
时如果还没有到达目的地,数据将被简单地丢弃。

1.2.2 地址扩充和伪装

如同我们所看到的样,互联网地址被分成A、B和C类地址。由于A类地址只有只有126个
,所以对一个普通公司来说去申请一个A类地址几乎是不可能的;B类地址有几万个,应
该说并不少,但是拥有上万台机器的公司更多;至于C类地址目前尚宽裕,然而政策和路
由规则的限制也许会使得使用C类地址有些困难。

无论怎样,互联网址地已经告急;对于B类地址尢其如此。最大问题也许是,每个网络
要求自己的机器位于一个物理网络中,在B类和A类的情况下几乎是不可能的。想一想,
如何将几万台机器连接进一个以太网系统!更不用说产生的地址广播了。

假定你申请到了一个B类网址,显然,你有必要将其切割成更小的子网,否则你肯定会
面对地址管理的恶梦;但是一旦你进行了这种切割,那么你就会面对另一个问题:B类网
总是假定掩码为255.255.0.0,每一台机器假定为可以直接与网络内的任何机器对话,这
会带来ARP问题。



图1.3 ARP代理问题

为为分割子网,你引入路由器R,将它放到主干上,并有将M4和M5放在路由器后面。
但是M1和M2,M3都会认为M4,M5就在主干上,并且试图用ARP广播取得M4,M5的MAC地址
,当然这不会成功了,所以M4,M5就无法工作。

最根本的解决方法当然是修改总体的网络设置,并且将M1,M2,M3也放到路由后面,
修改它们的网络掩码。但对于已经分配了很多网络地址的网络,这就会带来一些很讨厌
的问题,所以实用中一般采用另外的办法,即ARP代理。

在ARP代理方式下,R将截获所有对于M4、M5的ARP请求,并且代替M4和M5回应ARP广播
,这样在M1、M2、M3看来,仿佛路由器R除了R的实际地址之外,还拥有M4、M5的IP地址
,或者说在M1看来M4、M5的IP都对应着R,因此它们会将所有目标是M4,M5的通信送到R
,R自己当然是知道M4,M5的存在的,它会将数据包转发给M4、M5,这样的方式称为ARP
代理(proxy ARP)。

显然对于M4和M5,也可以由R1代理M1,M2,M3来完成这个工作;不过由于实际上在主
干上的机器总是极多的,如果手工加所有的代理项请求是不现实的,因此实现中通常用
另外一个办法,即改变M4,M5的掩码,使得M4,M5认为自己处于一个C类甚至更小的子网
中,而凡越出掩码范围的信息,让它们将R2作为缺省路由,将数据发送到R2。

ARP代理的主要用处是在B类地址中分割子网,尽管技术上它也适用于C类网,但是很少
有人这样干。要记住ARP并不能节约网络地址,而仅仅是使得B类(有时也用于A类)网络
的物理连接更灵活,地址管理更有效率。并且它总是用在你的B类地址已经被分配了相当
一部分的情况,如果你有一个未使用的B类地址,毫无疑问将其分裂成一组C类地址会更
有效率。如:




图1.4 分割子网

R为主路由,R1,···R12各自带一个较小的网络,R1分析数据包的目的地址并且
把它发送到对应的路由上,而A,B,C,···D分别将R2···R11作为缺省路由器。

可惜这里叙述的内容显然无助于普通的公司级用户。一般来说,在大学中申请一组IP
地址是容易的(一般的大学会有4-32个C类地址)。而对公司这几乎是不可能的。一个
普通公司能申请到时候1-16个IP地址已经不错了。



图1.5 IP代理

为了解决IP地址不够的问题,有另外一个解决方案,即IP代理。首先,TCP/IP申定义
了几个特殊的系列IP地址,对A类是10.0.0.0,B类为172.16.0.0和192.168.0.0,这些地址
用于“私用网络”,任何人都可以随意使用。

你可能会对这个感到奇怪,如果有两个单位使用同样网络会不会出现同路,答案是这
些网络并不直接接入Internet,相反,它们需要一个特殊的路由器来处理这个问题。

IP代理路由器R有两个网络地址,连到Internet的这一端,是一个 申请到的真实IP,
如203.17.45.6,在另一端则是私用网络地址,比如10.0.0.1。当私用网络上的一台主机
(如10.2.3.5)想和Internet上的主机对话时,它将数据报文发送到R,但是R并不是直
接转发这个数据包,而是改写数据包的封装,使得看上去数据是从R的203.17.45.6网络
接口发送出来的,所以这个数据包能够到达目的地。而当数据返回时,它返回到203.17.
45.6,然后路由器分析包上的封装,将数据包转送到10.2.3.5。

显然这有一个弱点,即外界并不知道10.2.3.5的任何事情,因此除非对话是由私用网发
起,否则对话不会成功。这使得外界不能去主动访问私用网上主机。对于某些工作这是
非常头痛的,例如ftp将会失灵,因为ftp要求一个反向的会话。不过,HTTP和TELNET,
gopher等都不受这个限制。

还有另一个技术用于使IP地址的使用有效率。也许你的系统中有很多机器,但并不是
全都打开的。例如,你有100台机器联到网上,但是也许最多只有50台计算机会同时打开
。这在一个官僚机构中是很常见的。于是,你可以让IP地址动态分配,只有实际工作的
机器才需要IP,这样,只要50个IP就足以解决问题了。这种技术称为DHCP(动态主机配置
协议)。这个技术还有一个古怪的应用,就是你可以省去为下面的的机器提供网络配置信
息的麻烦,而是让客户机器直接从DHCP中得到正确的路由和其他必要信息。

1.3 连接和数据传输协议

连接和传输协议提供网络机器之间传输数据的基本支持,它主要包括报文传输的控制
协议,直接的数据传输协议和机器之间的数据流传输协议。

1.3.1 控制和传输协议

假定你已经构造了“正确”的网络体系结构,那么下步就是在IP地址之间投递数据
。如同我们说的那样,IP层的实现就提供了如何向目标地址投递数据的知。但是在投递
数据时,仍然必须引入一些协议,它们规定投递的方式和一旦出错如何处理。

最常见的差错是路径错误。路由可能失效,目标主机可能挂起,网络线路可能断连,
甚至某个缺乏经验的研究生错误地修改了路由列表。无论哪一种情况,对发送者来说数
据都是丢失了。TCP/IP中定义ICMP协议来处理这种问题,它用来在路由或主机之间传送
关于网络的状况信息。例如,众所周知的ping命令就使用ICMP协议来确定目标主机是否
工作。ICMP关心的只是网络连接是否可用,路由信息是否正确,以及目标主机是否工作
,它不关心目标机器上是否有任何服务程序在运行。

除此之外,ICMP还需要完成其它一些功能,例如路由重定向。

假设网络连接是可用的,那么下一步是约定传输数据的协议。有两种标准的协议用来
处理数据传输,第一种方案是发送者简单地向目标投递信息,所有的判断,纠错,流量
控制等等都由传输协议去处理;另一种办法是发送和接收者自己完成各种高级控制和较
验工作,协议只提供发送和接收机制。第一处称为传输控制协议(TCP),第二种称为用
户数据报协议(UDP),TCP更常用一些。

无论哪一种情况,都要理解所谓“端口”的含义。端口是一个十六位整数,实际传输
中,源地址和目标地址都是用“IP地址+端口”的数对来标况的,因此,一台机器可以同
时进行多路的UDP或TCP通讯,只要使用不同的端口。

让我们用TCP来解释一下这种情况,因为这是大部分网络程序使用的协议。TCP是一个
连接传输协议,当连接开始时在源和目的之间建立一条虚拟的数据通路,通路由两个端
点的地址和端口号决定,而且数据传输是双向的,一条通路可以同时向两个方向传递数
据。

最重要的一点是,TCP连接决定于两端点,也就是说,(A,port1;B,prot2)和(A,
port3;B,port2)是两条独立的连接路径,一台机器上的端口可以用于不同的数据传输任
务,只要另一端的地址和端口号不同。

连接建立之后,双方就可以相互交谈了,因为数据连接是双向的,每一方都可以既发
送又接收信息,一方发送信息的时候,基本上是按照队列的先进先出的方式传递,接收
方如果发现某个部分传输错误就向发送方提出请求把相应部分重发一次。所有的排队和
纠错工作都由TCP协议来完成。

UDP和TCP是类似的,不同的是UDP是一个无连接协议,它不能构成数据通路,相反,发
送者盲目地向目标投递数据并且等待回应,使用UDP的程序必须自己处理和数据较验,排
队,以及准备应付数据次序混乱,缓冲区溢出,数据包丢失等等问题。

很显然,无论TCP或UDP, 必须提供一种机制用于分配可用的端口号。IP地址是系统管理
者设定的,而对于端口号,一般采用一种折衷的方式。TCP/IP保留某些端口号用于标准
的服务应用,而其它的端口号由操作系统控制,当应用程序需要传输数据时动态分配。
但这种保留并不是具备实际的约束能力,因为操作系统总可以用自己的方式分配端口号
。在UNIX系统中,为了管理的统一,规定要分配小于1024端口号,必须拥有系统管理员
权限,而普通的用户程序只能申请大于1024的端口号。不过,某些较大的端口号在近来
的系统中也具备了特定的含义(如 1080,8080等),但是这些含义并非严格地被遵守。

1.3.2 服务器和应用层协议

现在我们可以理解服务器的实现了。服务器软件就是一种按照TCP或者UDP连接回应客
户机器请求的软件,而运行服务器软件的机器就成为服务器。

服务器的实现是靠一种监听机制,TCP/IP为每种重要的服务功能分配一个端口号,而
股务器程序在这个端口上进行监听。当某个客户程序申请服务时,它试图去和对应端口
进行连接。如果对应端口上有服务程序在监听,将会成功地形成一个连接。服务器可以
处理这个连接,分析客户机送来的请求,回送合适的应答。但更常见的办法是服务器启
动一个子进程,将连接转交给子进程,然后自己继续监听其它的请求。

在整个协议的顶层,就是如何完成标准服务所需要的格式约束协议了,如 TELNET,F
TP,HTTP 等等,尽管许多人把这些东西和实现它们的应用程序看成一回事,不过实际上
它们仍然是不同的。这些协议是独立于使用的应用程序的,因此,不同厂家的浏览器才
能给出同样正确的结果。原则上,如果你熟悉 HTTP 文件协议,你也完全可以用TELNET
程序来阅读远端服务器的WWW传输,或者,直接 TELNET 到 25/110 端口来完成发信和收
信(不过,如果你凭心算就能解码 ISO-8859信件,我只能对你表示廉价的崇拜)。特别
是后者,是调试的主要手段之一。

FTP 协议是特别需要重视的,因为它的实现有些古怪,它使用两个连接:首先客户向
服务器的21端口发出请求,建立一个连接。但是这个连接仅用于传输 FTP 命令。当客户
程序正式要求下载某个文件时,服务器向客户机发出要求,建立第二条连接,文件内容
由这条连接传递。第二条连接使用较高的端口号(大于1024),这个通路是设计防火墙
的专家的噩梦之一。目前发展了一种新的ftp工作方式,即第二条连接不用服务器发起,
而是让客户向服务器的20端口发出请求,用这个连接来传递ftp数据。

HTTP协议相对来说简单一点,服务器在80端口等待客户的连接,所有的数据也从这个
连接传送。每传送一个独立的文件需要一个新的连接。

另外还有许多协议,我们在本书后面将详细介绍,例如 DNS,NFS 等等。我们在这里
只简单地列出一些重要的协议所使用的端口和协议类型:

协议名 端口 协议类型 说明

daytime 13 TCP/UDP 日期/时间服务

ftp 21 TCP 文件传输服务

ftp-data 20 TCP ftp数据

ssh 22 TCP/UDP Security Shell

telnet 23 TCP 远程登录

smtp 25 TCP 电子邮件

time 37 TCP/UDP 时间服务

domain 53 TCP/UDP DNS域名服务

gopher 70 TCP/UDP Gopher服务

http 80 TCP HTTP传输协议

pop-3 110 TCP 邮局协议3

sunrpc 111 TCP/UDP 端口映像程序

auth 113 TCP 用户身份认证

nntp 119 TCP Usenet新闻传输

netbios-ns 137 TCP/UDP netbios名字服务

netbios-dgm 138 TCP/UDP netbios数据处理

netbios-ssn 139 TCP/UDP netbios会话

imap2 143 TCP/UDP IMAP邮件管理

irc 194 TCP/UDP Internet Chat

https 443 TCP/UDP 使用SSL的http

表1.1 TCP/UDP端口

除此之外,有一个协议非常重要。但我们在这本书中无法叙述,因为各种公司都加上
自己的稀奇古怪的内容,而且往往保密。这就是 SNMP 协议,它用于对网络进行远程管
理,也许有一天我们可以用一整本书的篇幅讨论 SNMP 和各种怪异的实现,但本书计划
中不含这一部分。



2楼
【资料】Linux基础教程 第2章 Linux基础
第2章 Linux基础

本章要点:

本章介绍Linux的一些基本概念,特别是文件系统和进程管理的基本知识。

本章具体包括以下内容。

LINUX文件系统概述

系统内核概述

shell脚本的基本格式

UNIX的用户权限和用户账号管理

进程管理的基本概念和操作

Linux的发行版本

2.1 文件系统

让我们首先来解释Linux的文件系统概念。我无意将你培养成为职业的系统破坏者,只
是介绍一些基本概念。特别地,直接操作设备的物理扇区来读写ext2文件系统这样的想
法让我只要想一下就会脖子发凉,如果你是这方面的专家,请告诉我到底怎么做。

2.1.1 UNIX和树状文件系统


与普通的UNIX系统一样,Linux使用树状的文件系统。每个系统都有一个根目录,从这
里开始可以遍历整个系统中的所有文件,它没有驱动器和盘符的概念。

你可能会怀疑在没有驱动器符的情况下Linux如何处理多于一个的磁盘分区,可以看一
下下面的示意图:



图2.1 文件系统示例

在我们的例子里,在/下有四个目录,其中,/bin直接和/位于同一个分区中,这个包
含/的分区称为根分区。除此之外,根分区下还存在三个目录:/home,/mnt和/usr。

在系统中要存放大量的常用文件,例如日常的命令,系统文档等等。我们分划了一个
独立的分区用来存放这些文件,这个分区被“连接”在/usr目录下,因此要访问分区上
的文件只要访问/usr目录就可以了。

同样,我们为用户的私人文件开设了一个分区,连接在/home下面,每个用户都可以使
用自己的目录内的文件(比如:/home/emp1)。但是我们发现有一个目录需要容纳特别
多的文件,以至于将它单独分区可能会好一些,因此我们又设置了一个独立的磁盘用来
容纳这些数据,这个磁盘分区被连接到/home/httpd。

这台机器上还包含了一个DOS分区,一个光盘驱动器,另外网络中还有一个服务器提供
了共享的网络目录,我们把它们全都连接到文件系统之中,不过由于每个目录分支点(
术语叫mount point)只能安装一个文件系统,所以我们在/mnt下面开设了三个目录来连
接它们。

所有的文件都可以通过目录名加文件名来访问,对于系统来说,具体的每个文件到底
在那个磁盘或者那个服务器上是无关紧要的,只要了解这个文件所在的目录就行了。Li
nux利用/作为根目录的标志以及目录层之间的分割符,其作用相当于DOS的\。不过与DO
S不同的是,Linux的文件名、目录名命名规则要宽泛的多,可以用相当长的文件名和目
录名,在文件名和目录名中都可以包含不止一个的句点,而且区分大小写。例如 \test
和\TEST是不同的两个文件。而一个位于/mnt/dos目录下的名为file1的文件其绝对路径
名就是/mnt/dos/file1。

应该指出的是,“文件系统”这个词在Linux文献中有几种含义,第一种用来描述我们
这里说的从/开始的系统中所有文件和目录的集合;第二种用来描述如同我们例子里面与
/usr对应的那个分区那样的可以直接连接到某个目录下的完整集合体,即文件系统的一
个独立部分;第三种含义是文件系统的具体实现方式,即操作系统如何把这种逻辑的目
录结构映射成磁盘上的数据。具体的含义很容易根据上下文判断出来,大家可以自己注
意。

用cd命令可以在不同的目录之间切换,Linux承认绝对路径和相对路径,这个内容对于
任何熟悉dos的用户都应该是极其简单的,例如从/mnt/dos切换当前路径到/home/httpd
的命令可以是cd /home/httpd,也可以是cd ../../home/httpd。但是必须注意的是,在
cd命令之后的空格不可省略。

尽管理论上Linux应该自动对文件名进行过滤,但是这方面仍然有一些问题,例如,L
inux允许用减号作为一个文件的起始字母,然而-也用于许多命令后的开关,因此会带来
一些问题,如果你碰到了类似的问题,有时候使用绝对路径名会解决问题。


2.1.2 文件类型和文件组织


Linux把许多不同的东西看成文件。在一般情况下,我们会碰到下面类型的文件:

普通文件

目录

设备文件

链接

普通文件和目录

普通文件和目录的含义与DOS或者windows下的概念是类似的,普通文件就是一些数据
的集合,而目录则是包含文件的容器。实际上,目录也是一种特殊的文件,只是它包含
的内容是文件的存放信息。文件可以用rm命令删除,目录用mkdir命令建立,用rmdir删
除。

设备文件

UNIX设备被当成文件来处理,通常UNIX的设备文件被分成字符设备和块设备,字符设
备通常是类似于终端那样可以用处理文本文件的方式来处理的东西,例如,Linux在启动
时打开了六个虚拟终端,分别称为tty1到tty6,这些虚拟终端对应的文件是/dev/tty1到
/dev/tty6。假设你有超级用户权限,就可以直接向这些TTY上写文本,而这些文本则会
显示在主机的控制台上。块设备则代表了类似磁盘的东西,如磁盘,CD-ROM或者虚拟驱
动器。一般情况下,每个块设备还要包含一些子设备,例如,第一个IDE硬盘被称为hda
,但是这个硬盘可以包含多个分区,那么,第一个分区称为hda1,以下依次是hda2,hda
3,….等等。

设备文件用mknod命令建立,用rm命令删除。

链接

链接实际是一种文件别名,每个文件至少应该有一个名字,而如果你需要给文件增加
一个名字以便访问,那么就需要建立一个链接。链接被分为软链接和硬链接。软链接实
际上只是一段文字,里面包含着它所指向的文件的名字,系统看到软链接后自动跳到对
应的文件位置处进行处理;相反,硬联接为文件开设一个新的目录项,硬链接与文件原
有的名字是平权的,在Linux看来它们是等价的。由于这个原因,硬链接不能连接两个不
同文件系统上的文件。

链接可以用ln命令创建,例如,在/home/user目录下有一个文件dest,现在需要在/
tmp目录下建立一个链接以便直接在/tmp下访问它,那么可以用这样的命令:

ln /home/user/dest /tmp/dest

这个操作将会建立一个硬链接,但如果/home/user和/tmp在不同分区上时这个命令将
会失败。

ln –s /home/user /tmp/dest

这个命令将建立一个软链接。


如同其它UNIX Like系统一样,Linux的目录组织经常给人晕头转向的感觉,下面是一
些基本的目录的说明。注意,理论上你可以更改这些目录的位置和名字,但是这样做很
可能使一些假定文件“就在哪里”的程序混乱。

/:所有目录的“祖先”。

/lib:大部分应用程序必须使用的动态连结库文件

/usr:绝大部分的东西都在那里,比较复杂的应用程序(/usr/bin,/usr/sbin),
应用程序的附加文件(/usr/lib),应用程序的文档(/usr/doc),应用程序的联机手册
(/usr/man)。

/usr/local:这里是一般的附加软件的安装地点,如果你在安装了Linux之后又试图安
装新的应用程序包,通常会被安装在这里。

/var:这里包含的是一些随着系统运行会不断改变的内容,例如各种记账信息,邮件
和打印队列等等。许多人建议把它单独构成一个分区。

/tmp:临时文件,有必要的话将它独立成一个分区。

/dev:Linux用这个目录存放设备文件。

/proc:这实际上不是一个磁盘目录,而是用来显示系统的运行状态,在其中包含各
种虚拟“文件”用来显示系统的当前状况,如进程和CPU等等。

/mnt:习惯上在这个目录下开设出各种文件系统的连结点,但你可以随便更改它而不
会带来任何问题。

/home:缺省的非超级用户的宿主目录的所在地点。

2.1.3 使用文件系统

通常,对于服务器,我们在安装的同时就为它设计好了文件系统,特别是如何分区,
某个分区应该连结到哪个目录下等等。但是我们也需要对文件系统进行维护,例如为服
务器增加一个硬盘,或者解决文件系统混乱的灾难性问题等等。另外,诸如CD-ROM,软
磁盘,或者服务器上的共享目录等等显然是需要经常更换的,在Linux中,用文件系统的
安装和拆卸来对付这样的问题。

本节不会涉及那些有关处理文件系统灾难或者建立新的分区之类的问题;这种问题可
以参考系统配置和日常维护的那两章,这里只是介绍一些基本的知识。

一个文件系统可以连结到已有的Linux系统中,也可以把连结上的文件系统从整个目录
树中脱离,这是用mount和umount命令实现的。

mount命令的格式是

mount 开关 分区或者设备名 文件系统连结点

开关是一些命令参数,例如,假定我们需要使用某个软盘上的文件,将它插入驱动器
A,然后执行

mount /dev/fd0 /mnt/floppy

然后软盘的文件系统就被挂到/mnt/floppy目录下,相当于dos的a:\file1的文件现在
的名字是/mnt/floppy/file1。注意mount命令要求在挂接之前连结点(在这个例子中是/
mnt/floppy)必须存在,否则无法执行。

一般总是把文件系统连结到某个空目录。假如/mnt/floppy目录在连结之前就包含某些
文件,那么执行上述命令的结果将使/mnt/floppy目录的内容变为软磁盘上的内容,而原
有的内容在卸掉这个文件系统之前将不可访问。

/dev/fd0是与驱动器A对应的设备,相应地驱动器B是/dev/fd1。硬盘的情况比较复杂
,因为Linux是利用设备接口来描述设备的,例如,第一个IDE接口上的主盘是/dev/hda
,从盘是/dev/hdb,第二个IDE接口上的两个盘是/dev/hdc和/dev/hdd。问题是由于硬盘
使用的是分区,所以必须使用子设备名,例如,把/dev/hda上的第一个分区连结到/mnt
/diskc上的命令是

mount /dev/hda1 /mnt/diskc

相应地,第二个分区是/dev/hda2,以此类推

同样,SCSI驱动器用/dev/sda,/dev/sdb等等描述,对应的子设备名字是/dev/sda1,
/dev/sda2等等。

Linux对IDE光驱用硬盘的命名方式,不过光盘不存在分区问题,所以可以直接使用设
备名,例如把第二IDE从盘上的CDROM连结到/mnt/cdrom的命令是

mount /dev/hdd /mnt/cdrom

mount命令最常用的两个命令开关是-t和-o ,-t命令用来标志准备挂接的文件系统的
类型,(在下一小节中详细介绍),-o选项用来设置一些选项,最主要的选项是ro和rw
。这两个选项定义了对文件系统的存取方式,如果使用ro选项,那么这个文件系统将以
只读方式连入,无法修改上面的任何信息。缺省的设置是rw。

连结了一个文件系统之后,就可以向这个系统对应的目录进行操作,效果就是操作对
应的文件系统,如果要把这个文件系统卸下,使用umount命令,其格式是:

umount 连结点

例如,在上面的例子中,把连结在/mnt/floppy的软盘文件系统卸下的命令是

umount /mnt/floppy

注意由于这个过程会改变目录结构,因此必须在没有任何进程访问/mnt/floppy下的文
件,也没有任何用户的当前目录是/mnt/floppy或者它的下级目录时才能完成,否则会返
回一个 device is busy的错误。在有些UNIX系统中你可以用umount –f 的方法来强行
越过这个限制,但这是一种极其粗野的方式,只有你明确地知道你到底在干什么才可以
,在Linux中这个功能已经被取消。(有一个有趣的问题,如果你的文件系统是级联的,那
么在拆卸下级文件系统之前上一层文件系统不能被拆卸)由于这个原因,在有人使用系统
的情况下拆卸服务器的文件系统几乎是不可能的。如果你实在要这样干,请参考系统配
置那一章,将系统切换到单用户模式,这个过程会把所有用户从系统上踢掉,然后再完
成你的拆卸过程。

作为一种保护机制,已经mount的cd-rom不能通过按下面板上的按钮直接弹出,而必须
首先执行umount命令,当然也可以用eject命令完成umount和弹出的自动操作。对于软盘
没有这样的保护,所以你必须注意不要弹出一个已经连结的软盘,如果你这么做了,由
于unix的文件工作方式,除非这个软盘是以read only方式连入,否则几乎肯定会出现问
题。

mount和umount都需要超级用户权限才能执行,另外,它们都支持-a选项,mount –a
挂接在/etc/fstab中定义的所有可挂接文件系统;umount –a卸下所有定义在/etc/mta
b中得已挂接文件系统。每当挂接一个文件系统时,系统自动在/etc/mtab中增加一条纪
录;当这个系统被卸下时自动把纪录清除。直接输入不带参数的mount指令将会显示当前
已挂接的文件系统。

2.1.4 VFS、缓冲和ext2

每一种UNIX变体都有其独特的文件系统实现方式,Linux文件系统的实现依赖于所谓e
xt2文件系统,但是它也支持其他许多种出自其他操作系统的文件系统实现。在这个方面
,Linux引入了虚拟文件系统(VFS)的概念,任何文件系统连接入Linux时都必须先经过
VFS映射成为标准的文件系统。只要增加VFS到具体文件系统的映射,就可以让Linux支持
新的文件系统。一般说Linux必须在ext2文件系统上启动,但是也存在用基于MSDOS的某
种文件系统来实现它的可能。

VFS的最大一个影响也许是在缓冲文件方面。如同在MS-DOS上经常看到的那样,Linux
也使用内存高速缓冲磁盘的读写。事实上,为了提高性能,Linux被设计为将“几乎所有
”的空余内存都用来作为磁盘缓冲,这个设计使得Linux具有UNIX类系统中最高的磁盘效
能。(如果你对这个有兴趣,那么,有些人曾经宣布,在Linux+PeniumII+IDE上运行ta
r+zip比Sun solaris+SCSI上快一倍左右,原因是solaris不使用磁盘缓冲。)它的缓冲
对读写都同样有效,为此,系统必须每隔一段时间将缓冲区中的内容和磁盘中的内容进
行同步,如果在同步间隙中掉电,未写入的数据将会丢失。在拆卸任何文件系统或者关
机、重新启动之前,系统内核将自动同步其内容。当然你也可以使用sync命令来进行这
个同步。

尽管如此,仍然可能由于某些原因使得文件系统未能正确同步,通常造成这种现象的
原因是掉电,因此,缺省的系统启动脚本会在每次重新启动时自动检测文件系统,并且
启动fsck程序修理那些没有正确同步的文件系统。(fsck是系统管理员用来修理文件系
统的主要工具,它的用法我们将在“日常维护”中介绍。)这个命令有时要耗费很长的
时间。

Ext2是Linux的标准文件系统,与任何UNIX文件系统类似,它将磁盘分割成为一系列数
据块,再由数据块构成块组。每个文件由唯一的I节点(inode)描述,它包含文件的存放
和权限信息。象一切UNIX一样,Linux在内存中缓冲inode表来加快文件的存取。

(如果这些内容会让你糊涂,那么不要紧,你并不需要了解ext2的具体实现。实际上
对于一个非内核设计者来说理解ext2的实现的唯一理由是要去挽救一个已经被灾难完全
摧毁的文件系统。然而,备份和恢复会容易的多,不是吗?)

2.1.5 其它文件系统

Linux支持许多文件系统,“支持”的意思是说你可以把载有这些文件系统的磁盘分区
或者什么其他的设备直接连接到Linux文件系统中。一般情况下,如果要连接一个不是e
xt2的文件系统,你需要在mount命令行中用-t指令明确地给出文件系统的类型。Linux系
统目前支持的文件系统类型主要有:

minix:最早的MINIX系统的文件系统

ext2:Linux的标准文件系统,它还有一个比较早的形式即ext,目前已经不用

msdos:这就是标准的MSDOS文件系统

umsdos:这是一个特殊的文件系统实现,可以用MSDOS来存贮类似UNIX的长文件名文件

vfat:这是windows 95/98使用的文件系统,支持windows 95长文件名

iso9660:CD-ROM的标准文件系统

hpfs:OS/2用的文件系统

ntfs:windows nt 4.0用的文件系统(使用它要小心,目前这个功能还不是很可靠,
绝对不要把一个NTFS文件系统连接成rw的方式!)

ufs:BSD用的文件系统

sysv:System V系列的一些UNIX使用的文件系统。

Ext2和ISO9660通常不需要使用类型说明,而msdos/win95文件系统则常常需要明确地
说明其为msdos或者vfat,例如,在/dev/hdb2上装有一个windows 95文件系统,那么,
将它连结到/mnt/win95的命令是

mount /dev/hdb2 /mnt/win95 –t vfat

偶尔你必须为连结到文件系统中的msdos软盘说明其类型:

mount /dev/fd0 /mnt/floppy –t msdos


2.2 系统内核基础

下面我们要解释有关系统内核的一些东西。必须记住,GNU+Linux的一个特色是如此之
多的程序可以使用,因此几乎所有的东西都可以用你自己的东西替换掉,除了系统内核


2.2.1 什么是内核


Linux将系统的一些关键性程序分离出来构成所谓操作系统内核。象大部分UNIX操作系
统的内核那样,Linux内核必须完成下面的一些任务:

管理对文件系统的读写,把对文件系统的操作映射成对磁盘或其他块设备的操作

管理程序的运行,为程序分配资源,并且处理程序之间的通讯

管理存储器,为程序分配内存,并且管理虚拟内存

管理输入输出,将设备映射成设备文件

管理网络

文件系统的概念我们已经在前面一节中介绍过了,内核必须包含VFS管理程序以及将各
种具体文件系统映射成VFS的程序。另外的几项功能差不多也象文件系统一样复杂,首先
是对于内存的管理。

Linux使用虚拟存储管理方式,利用现代处理器的页面映射能力,在x86处理器上,Li
nux使用4GB地址空间,系统的物理存贮器通常总是少于这个数字。操作系统除了使用物
理存储器外,也支持将硬盘空间映射成为虚拟内存。所有存贮器(物理内存和虚拟内存
)分成大小相等的页面,在x86系统中,每一页的大小是4kB,通过给出页号和页面内偏
移量对某个内存地址进行访问,在物理内存紧张的时候,操作系统必须把某些没有使用
的页面从内存移动到硬盘上以便腾出空闲的页面供程序使用,这个过程称为对换。

显然对换需要虚拟存储空间,通常情况下Linux用交换分区来处理这个问题,在硬盘上
开设一个独立的分区专门用于映射虚拟内存,这种分区称为交换分区。交换分区可以并
且经常不止一个,之所以这样是由于早期的Linux核心要求每个交换分区不能超过128MB
。对于较重负荷的服务器,交换内存用到256MB甚至更多都是很正常的事情,因此那时的
系统经常有多个交换分区,目前这个限制已经去除,但仍有人使用多于一个的交换分区


核心的另外一个任务是执行用户程序,为此核心必须支持可执行文件格式。Linux使用
多种可执行文件的格式,诸如elf,a.out等等(与ms-dos不同,没有办法从名字上区分
一个文件到底是什么格式,核心只关心二进制文件的具体形式)。

除此之外,所有的设备驱动程序都必须包含在系统内核之中,依靠这些驱动程序操作
系统才能够对硬件进行操作。

2.2.2 可加载模块和设备驱动程序

在一些系统中内核的运行参数以及内核中包含的设备驱动程序都只能在系统启动时装
入,因此要想改变系统硬件或者对硬件的运行参数进行调整,唯一的选择是重新启动。
Linux支持在运行期间加载核心模块。

模块(modules)是Linux的概念,它意味着可以将一些功能的程序分离出来,动态地加
入和撤出内核。通常这种实现的目的是减少内核需要的物理存储空间(内核不能对换,
也不使用虚拟内存映射)以及使系统的配置更灵活。尽管理论上随意加入和拆卸内核的
功能容易使内核陷入危险中,但是Linux的实现使得加载一个内核模块实际是相当安全的


必须注意的是,一个放在模块中的程序和直接放在内核映像文件(例如,在许多系统
上的/vmlinuz)中的并没有什么不同,把某个部分当成模块还是直接放入内核映像的理
由通常只是为了方便。例如,尽管可以把软驱的驱动程序作成可加载模块,但是对于一
个经常使用软盘的用户来说这只会带来烦恼,因为在使用软盘之前他必须将驱动模块调
入,相反,对于一个普通用户,ntfs驱动程序可以合情合理地做成模块,因为需要访问
windows NT分区的几率肯定是很小的。网卡和声卡驱动程序也通常做成模块的形式,因
为它们的种类实在太多,在内核中包含所有的驱动程序肯定是一种疯狂的想法。

内核模块可以用insmod命令加载,用rmmod命令卸载,其语法是:

/sbin/insmod 模块名

/sbin/rmmod 模块名

而使用lsmod命令可以显示当前加入的内核模块。

由于许多模块的加载都涉及到复杂的版本、相互依赖等问题,所以Linux文档提倡使用
更简单的modprobe命令来加载模块:

/sbin/modprobe 模块名

需要指出的是,模块是在编译系统内核时设定的,通常在/lib/modules目录下有一个
目录,其名字是你的内核版本号(比如:2.2,14),而各种模块都包含在这个目录下,
名字是xxxx.o,xxxx是模块名,而.o是缺省的扩展名。在使用上面的各个命令时,不需
要使用扩展名也不需要使用路径。例如,使用/lib/modules/2.2.14/ipv4/ip_masq_qua
ke.o的命令为

/sbin/modprobe ip_masq_quake.o

也存在另外一种方案,这种方式中,当核心需要某个模块时,它自动去寻找对应的模
块文件并且将它加载到系统中。这是通过正确地编译内核实现的,不过,一般不推荐使
用这样的办法,因为增大了出现意外事故的几率。

2.2.3 内核不做什么

Linux内核是一个比较复杂的程序,技术上讲,它不同于一些现代操作系统所采用的微
内核,相反,许许多多的东西被加入到了内核之中。但是,比起许多其他系统,Linux内
核是非常小而且简单的。另外,许多东西虽然是Linux的一部分但是和内核完全无关,拆
卸它们至少在理论上不会影响系统的正常运转。

首先的可以拆卸或者替换的东西是命令解释程序,再就是X-Window,这些东西只是几
个应用程序,它们并不运行在核心态中,对于Linux它们也不是绝对必要的(然而,这种
说法也许只有理论上的意义,一个没有shell的Linux几乎肯定是不可操作的)。

2.3 shell和配置程序

作为一个UNIX系统管理者,你必须了解shell。Linux在对shell的依赖方面比其它UNI
X产品好一些,因为有近乎无穷多的shell和相关的自动化工具可用。不过,我想无论如
何,你都必须了解bash,这是Linux的缺省shell。

3楼
2.3.1 命令解释程序

一个复杂的可以编程的命令解释程序是UNIX的特色之一,它们通常被称为shell。由于
shell仅仅是一些标准的UNIX程序,因此它可以毫无困难地在Linux上实现。当然一般人
总是喜欢使用较为好用的shell程序。

Linux下用的最多的shell是bash,它很庞大也很复杂,但是确实功能强大。对于许多
用户来说,bash的命令行接口已经足够好,例如提供了在命令行编辑历史纪录的功能。
事实上,shell的用法可以用一本书来描述,因为shell命令本身构成了一种语言,具有
不逊于一般语言的编程能力。

本书作者不奢望你是一个shell script专家,也无意让你成为一个shell专家,但是为
了对系统进行有效的管理,至少必须能够看懂shell脚本。如果你已经熟悉shell编程就
可以简单地跳过这一小节,否则,这里给出了对shell语法的一些简单描述。

一个shell脚本通常就是一个文本文件,但是被设置成具有可执行的属性。你可以合情
合理的把它看成一个批处理命令,然而,shell允许使用变量和流程控制,因此它能完成
的东西比DOS的批命令要丰富的多。

在shell脚本里面可以简单地定义变量,变量可以是一个数值或者字符串,shell并不
了解变量类型的概念,区分变量类型的工作要你自己完成。

为了定义变量,可以简单地使用赋值语句,例如,下面的命令将my_var的内容置为1:

[wanghy@openlab wanghy]$ my_var=1

注意[wanghy@openlab wanghy]$是系统提示符。后面的才是输入内容。在使用bash时
有一个特殊要求,即等号两边不能有空格。

如果要访问变量的内容,使用$前缀,例如:

[wanghy@openlab wanghy]$ echo $my_var

1

另外,Linux定义了一些特殊的变量,首先是命令行参数,这些参数被用$0,$1,…的方
式引用,$#则指代命令行参数的个数,$*则给出全部参数构成的字符串。如果这些说法
让你感到困难,看一下下面脚本的运行结果。

[wanghy@openlab wanghy]$ cat testpar

echo $0

echo $1

echo $2

echo $*

[wanghy@openlab wanghy]$ ./testpar par1 par2 par3

./testpar

par1

par2

par1 par2 par3

shell中定义了一些特殊的字符,除了$指代变量,<,>,<<,>>,|进行标准I/O重定向之外
,还有下面一些字符:

` 这个符号(就是在Tab和Esc之间的那个键)用于执行命令替换,例如出于某种原因
你想执行uname –r命令得到内核的版本号并且存入$kernel_version里,可以执行下面
的程序代码:

kernel_version=`uname -r`

双引号和单引号用于标记字符串,但是它们也有一些不同,主要是如果有一个字符串
中包含$var这样看起来象是变量名的部分时,双引号括起来的字符串将其解释为变量而
单引号不作任何处理。

反斜杠用于在字符串中包含特殊字符。

. 号用于执行一个脚本,例如:. ./testpar执行当前目录下的testpar脚本。它不能
用于执行二进制文件。

Bash的另外一个功能是执行各种程序流程,它支持if….then….else…..fi的选择模
式,其中if后跟各种测试指令,测试指令的基本形式是test 表达式,如test 1<2,tes
t –f /etc/smb.conf等等。test也可以用方括号代替,例如test 1<2 和[ 1 < 2 ]等价
,注意使用方括号时方括号和中间的表达式之间必须用空格隔开。可以选择的测试指令
包括:

数字比较

-eq (等于) -ge (大于等于)-le(小于等于)-ne(不等于)-gt (大于)-lt(小
于)

字符串比较

= 等于 != 不等于 –n 字符串长度是否大于零 –z 字符串长度是否等于零

文件测试

-d 是否为目录

-f 是否存在这个文件

-r 是否可读

-s 是否具有大于零的长度

-w 是否可写

-x 是否可执行

逻辑操作

! 求逻辑非

-a 逻辑AND

-o 逻辑OR

另外,shell支持for,while,until和case,shift语句。if,while,case和until语
句的用法都很简单,只要看一下系统给的例子就可以了,for语句比较复杂,其格式是

for var in list

do

…..

done

其含义是对list中的每个值执行一次循环。如果list写成”$@”则对所有命令行参数
执行一次循环。

下面是case的基本用法:

case str in

str1|str2)

statement1;

str3|str4)

statement2;

str5)

statement3;

*);

esac


*相当于"case else"。str1|str2)表示“若等于str1或者str2则” ,小括号是不可少
的。

while语句的用法是

while { expression }

do

.....

......

done

until语句的用法是

until test expression

do

.......

......

done

shift语句与dos里的用法相同,它把命令行参数的位置左移,缺省的情况下移动一次


另外的标准语句还有break和exit,分别用于退出一个循环或者退出当前脚本。

还有一个语句是select,用来接受用户输入,其用法可以参考下面的脚本:

select input in continue over

do

if test $input = "continue" ; then

echo "contiune"

else

echo "over"

exit

fi

done

[由于本书仅仅希望你能够看懂script而不是会编写复杂的script,因此不准备详细地
叙述shell编程的要点。当然许多人把会熟练地编写script看成一个UNIX高级用户的标志
,但是对于Linux系统管理员来说,高超的脚本技能绝对不是必要的。]

2.3.2 不同的shell

对于大部分人来说,UNIX提供的shell是太多了,最常用的大概是sh,csh和bash程序
,但是其他的象tcsh,zsh之类的程序也经常出现,如果有兴趣,你可以看看在Linux发
行盘里面提供了多少种不同的shell。问题在于,不同的shell不仅是外貌不同,在流程
控制和表达式的使用方面也存在区别,事实上,这样的问题经常让人晕头转向。

在Linux的启动阶段,它使用sh作为命令解释器,其语法就是我们刚才讨论的语法,
但是不支持bash提供的一些高级特性。事实上,bash是作为对sh程序的一种强化出现的
。当Linux准备就绪以后,它使用/etc/passwd文件中的描述为每个用户提供自己的shel
l,通常提供的是bash或者csh。这些shell都是用户友好的,提供了诸如命令行补齐,历
史纪录,通配符等等高级特性。不过,许多人都喜欢使用自己习惯的shell程序。

对shell掌握程度曾经是UNIX用户水平的衡量标志之一,因为那个时候除了shell以外
没有更好的自动化任务工具,有些系统甚至不愿意提供C编译器。但是现在,在perl和C
编译器作为Linux发行版本的一部分出现时,过分的强调诸如shell,awk等工具的使用能
力并无意义。作者建议你用Perl完成日常的任务管理工作。

2.3.3 配置程序、文档和编辑器

UNIX的一个典型的特性是它的系统配置程序都是文本。系统内核、应用程序等等都需
要一系列数据进行缺省设置,在许多系统上,这种设置是以某种内部数据库的形式提供
的,而在UNIX系统中,它们被实现为简单的文本文件。理论上,使用文本文件会使得配
置文件的大小比压缩二进制编码大一些,但是文本文件容易操作的优点完全抵销了这个
弱点。

传统上,系统的配置文件被放在/etc下面,一般情况下,如果要修改某个软件的设置
,你需要做的就是编辑对应的配置文件,然后重新运行这个软件。Linux下的软件的配置
文件被设置为很容易理解的形式(当然也有一些东西例外,比如sendmail)。一个典型
的例子是缺省的/etc/bashrc,它用来设置一些bash使用的参数文件:

# /etc/bashrc


# System wide functions and aliases

# Environment stuff goes in /etc/profile


# For some unknown reason bash refuses to inherit

# PS1 in some circumstances that I can't figure out.

# Putting PS1 here ensures that it gets loaded every time.

PS1="[\u@\h \W]\\$ "

以#开头的行很容易看出是注释行(大部分UNIX应用程序都这样,偶尔某些东西使用分
号作为注释开始的标志)。所以实际的命令只有一行,如果你熟悉UNIX里面“说话的规
则),你很容易看出这是用来设置缺省的命令提示符的(\u:用户名 \h:机器名 \W 目
录名)。

对于UNIX专家来说,这种配置程序是极其简单的,只要一个普通的文本编辑程序就可
以完成包括裁剪内核,调整软件运行参数等等多方面的工作,但是这也足以让新手晕头
转向,尤其是当某些东西没有写在文档里面的时候。(有一个说法,当你不会使用某个
软件时,windows用户决定去寻找一个更简单的产品,UNIX用户则去寻找一本更厚的文档
)。Linux则采取了比较温和的办法,对于许多涉及到太多的配置文件的一些软件的设置
,Linux提供许多配置程序(技术上这种东西可以在任何UNIX体系上使用,不过UNIX老手
往往不屑于使用这种功能)。不过要记住,这些配置程序所作的和一个熟练的系统管理
员用编辑程序作的实际是一样的(也许更愚蠢一些),只要你愿意,你总可以手工完成
它的任何工作。不过,有些编辑工作是如此地复杂以至于除了它的开发者以外没有人愿
意手工去做(比如说:sendmail)。相反,有些配置工具十分愚蠢,它们偶尔会给你带
来一些严重的麻烦,所以有经验的用户决不用它。

这种文本编辑方式的系统配置显然要依赖于两种东西,文本编辑器和对于配置文件格
式说明的文档。通常人们只是在已有的内容上面修改一下,因此通常各种Linux软件都提
供配置文件的范例。但是更详细的内容必须通过文档来得到,Linux软件通常提供两种文
档,即联机手册和文档文件。

联机手册是Linux文档的主要来源,一般它提供给那些“原生”的Linux程序,它有终
端和X两种版本,例如,在终端下想要了解more命令的用法,输入man more就会出现类似
下面的屏幕:

[root@openlab joe]# man more

MORE(1) UNIX Reference Manual MOR
E(1)

NAME

more - file perusal filter for crt viewing

SYNOPSIS

more [-dlfpcsu] [-num] [+/ pattern] [+ linenum] [file ...]

DESCRIPTION

More is a filter for paging through text one screenful at a time. Th
is

version is especially primitve. Users should realize that less(1) pr
o? vides more(1) emulation and extensive enhancements.

OPTIONS

Command line options are described below. Options are also taken fro
m

the environment variable MORE (make sure to precede them with a dash

(``-'')) but command line options will override them.

-num This option specifies an integer which is the screen size (in

lines).


:

注意结束处的冒号,这表示手册中关于more的内容还没有全部显示出来,用^F和^B可
以上下翻页,当移动到手册页面末尾时,<end>标志将会出现。

阅读完毕之后,用q键退出。

在X下,执行xman &就可以阅读手册内容。

偶尔某些名字有多重含义,例如exit既可能指shell的exit命令也可能指标准C的exit
()函数,手册用分节的方式来处理这个问题,例如第一节是普通命令,第二节是标准系
统调用等等,详细的定义可以在xman的菜单里面找到。要在终端下使用分节,使用

man –S [节号] 命令名

联机手册的内容构造的相当简明而清晰,但是对于一个新手来说,它们往往帮不上忙
。许多软件在/usr/doc目录下提供了TXT或者HTML格式的较为详细的文档可以阅读。另外
,/usr/doc/HOWTO目录中存放着Linux-HOWTO的内容,对于新手是最有用的信息来源之一


如果你能够理解文档,那么就可以通过编辑配置程序来完成系统和应用软件的配置。
这意味着你需要至少掌握一种编辑工具。UNIX下最主要的编辑工具是vi和emacs,但是对
于象编辑配置文件这样的工作,它们的功能是过于强大了。如果你会用任何一种当然很
好,如果你不会也无关紧要,象joe之类的编辑器要简单的多,而且同样可以完成工作。
(个别发行商不提供joe,但这总不能妨碍你自己去下载源代码然后编译)。

2.3.4 定制环境

通常一个用户总是希望定制自己的shell环境。对于一个系统管理员来说,正确的系统
设置可以加快工作的效率。

首先需要设置的是系统的预定义搜索路径。与MS-DOS不同,Linux只搜索在PATH环境变
量里面明确地设置的路径,它并不执行对当前目录的搜索。因此,如果要执行当前目录
里的程序,必须明确地用./指定:

./test

设置路径的命令在各种shell里是不同的,在bash里,你需要的是定义一个PATH变量,
然后把它输出到环境变量里面,这是通过export命令实现的:

PATH="/usr/bin:/bin";export PATH

用分号连结起来的两个命令连续地被执行,在export后面的PATH不用加$,设置路径时
不同的目录之间用分号分开。当然,你也可以用两条命令来处理:

PATH="/usr/bin:/bin"

export PATH

另外一个很多人喜欢定制的环境变量是提示符,bash用PS1和PS2来设置提示符,这表
示shell的一级提示符和二级提示符。例如,下面的命令把提示符设置成为MS-DOS方式:

PS1="\w>";export PS1

\w代表当前工作目录,类似的特殊字符还有

\# 显示当前命令的命令编号。

\$ 显示$符作为提示符,如果用户是root的话,则显示#号。

\\ 显示反斜杠。

\d 显示当前日期。

\h 显示主机名。

\n 打印新行。

\nnn 显示nnn的八进制值。

\s 显示当前运行的shell的名字。

\t 显示当前时间。

\u 显示当前用户的用户名。

\W 显示当前工作目录的名字。

\w 显示当前工作目录的路径。

另外一种十分有用的技术是别名。别名用alias命令实现,例如

alias ll="ls -l"

以后输入ll就等效于输入ls –l。

有几个缺省的别名,如果你的系统没有设置,强烈建议你加上,即

alias rm="rm –i"

alias cp="cp –r"

alias mv="mv –r"

这几条命令可以提供对错误操作的一种预防方式。

你可以对自己的shell加上复杂的定义,但是当你退出系统时,这些定义就消失了,为
了使这些定制信息自动可用,可以有多种处理方法。最简单的是在你的宿主目录(/etc
/passwd里面定义的你的主目录)中建立一个.bashrc或者.bash_profile文件(两个名字
都可以),放入你想要定制的内容。以后bash开始执行时会自动去调用其中的内容。如
果你用的是其他的某种shell,也有相应的配置文件,比如csh的配置文件是.cshrc。注
意点号开始的文件名是隐含文件,只有用ls –a命令才能看到。如果你想要让所有用户
都能自动使用这些东西,为他们建立一组合适的配置文件,然后拷贝到/etc/skel目录。
4楼
【资料】Linux基础教程 2.4 用户和权限
2.4 用户和权限

本节讨论Linux的用户/文件权限问题。许多用户不了解setuid和setgid,这使得他们
在处理WWW server的cgi功能时出现种种问题。

2.4.1 用户、组和文件属性

Linux是一种多用户操作系统,为了确保在多用户环境下的系统运转的安全性,Linux
使用用户权限机制对系统进行管理,这种管理主要是通过文件管理机制完成的。

Linux对每个文件设置一个16位数字来完成对文件的存取控制,这个数字称为文件属性
。如同我们在前面说的那样,Linux并不使用文件名来区分文件的类型,文件的性质用文
件属性来描述。在这个16位数字中有9位用于设置用户对文件的存取控制,3位用于对可
执行文件进行特殊处理,另外3位用于设置文件的类型。这样说可能会让人有些迷糊,我
们依次来处理这些问题。

文件类型在文件系统中我们已经提到过,它可以是设备文件,普通文件,目录,链接
中的某一种,下面是一个信手拈来的例子:

ls -l

total 48

drwxr-xr-x 5 wanghy wanghy 4096 Jan 21 13:25 Desktop

drwxrwxr-x 2 wanghy wanghy 4096 Jan 28 14:25 bin

-rwxrwxrwx 1 wanghy wanghy 10 Jan 27 19:43 cc

lrwxrwxrwx 1 root root 19 Jan 27 10:33 ss -> /etc/X11/XF86
Config

lrwxrwxrwx 1 root root 2 Jan 27 10:29 test -> zz

-rwxrwxrwx 1 wanghy wanghy 32 Jan 27 19:31 testpar

-rw-rw-r-- 2 wanghy wanghy 8 Jan 27 08:52 tk

-rw-rw-r-- 2 wanghy why 8 Jan 27 08:52 tt

-rw-rw-r-- 1 root root 8 Jan 27 10:29 zz

ls –l命令显示出文件的详细信息,它以分栏方式出现,最左面的一栏是文件属性栏
。容易看到在文件属性中

drwxrwxr-x 2 wanghy wanghy 4096 Jan 28 14:25 bin

最左面的d代表着这个文件是一个目录,它可以出现为一个l(软链接),b(块设备),c
(字符设备),d(目录)或者简单地一个-号(普通文件)。

接下来的九个字母代表存取控制,从左至右每三个为一组,分成三组,分别代表文件
的拥有者,同组用户和其他用户。

文件的拥有者是文件逻辑上的主人,只有他才能修改文件的属性。一般来说每当有人
新建一个文件,他就自动地成为文件的拥有者。在第三栏我们看到的wangh就是文件系统
纪录的文件拥有者。在拥有者权限栏位中出现的rwx表示拥有者可以直接读(r)、写(w)、
执行(x)相应的文件。在这个形式

-rw-rw-r-- 2 wanghy why 8 Jan 27 08:52 tt

rw-表示文件的拥有者可以读和写这个文件,但是不能执行。一个-号代表相应的属性
位没有被设置。

同组用户是在Linux用户管理中定义的该文件所属组的用户。所属组显示在ls –l输出
的第四栏。所谓组就是在/etc/group文件中设置的一些集合,例如,下面的/etc/group
文件

root:x:0:root

bin:x:1:root,bin,daemon

daemon:x:2:root,bin,daemon

sys:x:3:root,bin,adm

adm:x:4:root,adm,daemon

why:x:101:wanghy,adm,test

定义了root,bin,daemon,sys,adm和wanghy几个组。其中的why组包含wanghy,ad
m和test三个用户。

刚才的tt文件在组权限这一栏的值是rw-,表示同组用户可以读和写这个文件,在这个
例子中,就是why组,因此wanghy,adm和test都可以对这个文件进行读写。

最后,其他用户的权限是r--,意味着所有其它用户只能阅读这个文件,不能修改,也
不能执行。

文件的拥有者可以用chmod命令更改文件的属性,也可以通过更改文件的属主把文件交
给他人控制。

chmod命令的用法是

chmod 属性字 文件名

属性字有两种用法,最基本的用法是使用字母,用u,g,o分别代表文件拥有者,组用
户和其他用户,+和-号用于调整权限。

例如,要给tt文件加上“拥有者可以执行”的权限,命令为

chmod u+x tt

取消tt的所有人可以读的属性的命令是

chmod o-s tt

chmod另外的一种用法是使用数字,为拥有者,组用户和其他用户分别计算一个数,计
算规则是r=4,w=2,x=1,然后相加(例如,r-x=5),最后将三个数连到一起,例如为tt
分配一个rwxrw-r—的属性的命令是

chmod 764 tt

文件的拥有者可以用chown命令将文件的所有权交给其他用户,但一旦交出就不能收回
,例如,下面命令将tt的所有权交给root

chown root tt

有时需要对一个目录下的所有文件及下级子目录更改属性,这可以使用-R开关,例如


chmod –R o+r share/*

一个有趣的问题是一个新创建的文件具有什么样的属性,这是通过umask命令实现的,
设置了umask之后,你新创建的文件具有0777-umask的属性,例如,大部分系统的缺省u
mask是002,因此用户新创建的文件属性就是777-002=775或者rwxrwxr-x。你总可以用自
己的设置来改变这个umask值,例如

umask 066

将使得你以后的文件自动具有711属性。直接输入不带参数的umask命令则显示当前的
umask。

2.4.2 超级用户和SU

UNIX的文件存取控制尽管十分有用,但是你系统在运行中总是会碰到需要绕过UNIX文
件存取控制的情况。这是利用超级用户权限实现的。

UNIX的root用户大概是它最出名的地方,每个系统必须有一个root用户,这个用户执
行系统的维护和管理。但是你要理解的是,对于系统来说这个名字其实没有意义。系统
内核真正关心的是用户的uid。uid是一个整数,在/etc/passwd文件中定义,如果某个用
户的uid等于零,系统将认为他是超级用户,从而对它不再使用存取限制和安全性验证。
所以root用户可以操作任何人的文件或者象文件的拥有者一样管理文件。

root用户可以不受文件管理机制的影响,几乎可以做任何事情,由于unix的进程权限
机制,root用户所执行的程序具有root权限,除非它自己将自己切换成为其他用户。

由于root用户可以访问整个文件系统,因此文件系统和用户组的管理都由它来完成。
但是为了安全,许多实际的系统禁止root用户从服务器控制台以外的地方登陆,这意味
着你不能直接从telnet以root身份进入系统。

即使能够用root身份远程进入系统,直接以一个uid=0的身份在系统上操作也是危险的
,因为超级用户的误操作可以彻底破坏整个系统。一般的方式是以普通用户的身份进入
系统,需要执行超级用户的任务时再用su命令切换成超级用户。

su命令本来是用来给普通用户切换成超级用户的,但是也可以用它切换成别的用户,
其语法是

su 用户名

输入后,系统将提示你输入相应用户的口令,只有正确的口令才能完成身份切换。假
如在su命令中没有给出用户名,那么系统缺省认为你要切换成超级用户,将提示你输入
超级用户口令。

关于超级用户和用户管理的详细内容我们在用户管理一章中讨论。

刚才我们提到系统识别超级用户是通过uid,实际上整个UNIX的文件存取权限都是基于
uid的,uid在/etc/passwd文件中定义,通常这个文件的属性是444,即全程可读,下面
是一个例子:

[wanghy@openlab /etc]$ cat passwd

root:x:0:0:root:/root:/bin/bash

bin:x:1:1:bin:/bin:

daemon:x:2:2:daemon:/sbin:

adm:x:3:4:adm:/var/adm:

lp:x:4:7:lp:/var/spool/lpd:

sync:x:5:0:sync:/sbin:/bin/sync

shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown

halt:x:7:0:halt:/sbin:/sbin/halt

mail:x:8:12:mail:/var/spool/mail:

news:x:9:13:news:/var/spool/news:

uucp:x:10:14:uucp:/var/spool/uucp:

operator:x:11:0:operator:/root:

games:x:12:100:games:/usr/games:

gopher:x:13:30:gopher:/usr/lib/gopher-data:

ftp:x:14:50:FTP User:/ftp:

nobody:x:99:99:Nobody:/:

xfs:x:100:101:X Font Server:/etc/X11/fs:/bin/false

gdm:x:42:42::/home/gdm:/bin/bash

postgres:x:40:233:PostgreSQL Server:/var/lib/pgsql:/bin/bash

squid:x:23:23::/var/spool/squid:/dev/null

lyf:x:500:500::/home/lyf:/bin/bash

wanghy:x:501:501::/home/wanghy:/bin/bash

testvv:x:502:502::/home/testvv:/bin/bash

在每个用户名字后面有两个数字,前一个是uid,后一个是gid,gid用于标志用户属于
哪个组。你可以看到root的uid和gid都是0。如果有一个用户的uid被设置成为0,那么他
就自动地获得了root权限。

一个有趣的问题是passwd的属性,显然passwd必须确保至多仅对root可写,但是如果
设置成400(仅超级用户可读)会如何呢?在大部分Linux上系统仍然能够工作,然而它会
抱怨不知道哪个uid到底叫什么名字(“我不知道我叫什么名字“)。

除了超级用户之外,系统定义uid<10的用户为系统用户,而新建的用户将使用500以上
的uid。

2.4.3 setuid和setgid

缺省情况下,Linux的用户保护机制不仅对于直接对文件的存取,也用于设置用户执行
的程序,一个用户所启动的程序通常自动具有了这个用户的权限,也就是这个程序对文
件的存取按照用户的权限执行。这使得用户不能绕过文件存取机制破坏文件系统。

然而很多情况下我们必须绕过文件保护机制,例如passwd程序,它用来更改用户的口
令,在Linux的实现中它去修改/etc/passwd和/etc/shadow文件,因此它必须设计为以超
级用户身份执行。为此,Linux提供setuid程序来完成这种工作。

setuid是一种文件特殊属性,它使得被设置了setuid位的程序无论被哪个用户启动,
都自动具有文件拥有者的权限,可以看到passwd文件的属性是

[wanghy@openlab bin]$ ls -l passwd

-r-s--x--x 1 root root 22312 Sep 25 11:52 passwd

文件属性中的s代表setuid,因为passwd程序的拥有者是root,因此passwd程序执行时
自动获得超级用户权限,所以无论谁执行passwd程序都可以修改系统的口令文件。(说
实话,这是UNIX的设计中的一个噩梦)另一个例子是web页面服务器,缺省时httpd服务
器是利用nobody的权限执行,而且没有人愿意将自己的目录设置成777,因此httpd启动
的程序无法修改用户的程序。对于需要写私人信息的cgi程序这显然是不可使用的,但是
你可以为cgi程序加上setuid,这样你自己的cgi程序就可以修改自己的私有文件了。

setgid与setuid类似,只是具有setgid的可执行文件运行时自动获得文件对应的组权
限,因为组权限不像用户权限那样精确,所以用setgid的程序不是很多。

setuid和setgid都是对正常的UNIX安全机制开的后门,原则上,只有在明确的非用不
可的功能中才能使用setuid和setgid。特别是,具有root的setuid的应用程序经常是系
统遭受攻击的目标。在安全性的部分我们将更详细地讨论setuid和setgid的问题。

要给一个文件加上setuid位,使用命令:

chmod u+s 文件名

同样,要加上setgid位,使用命令

chmod g+s 文件名

尽管理论上可以给不可执行的文件加上setuid和setgid,但是这样做通常没有什么意
义。

2.5 进程和守护

进程概念是一切多任务操作系统的基础。本节介绍基本的进程管理命令。另外,还要
介绍与服务器紧密相关的一大类进程,即守护进程。在术语中,守护进程称为daemon。

2.5.1 进程和作业管理

UNIX是一个多任务的操作系统,这是通过CPU在各个任务之间进行时间片轮转实现的,
为此,UNIX/Linux通过进程的概念进行作业管理。

理论上,进程包括一个程序以及与它的执行状态对应的上下文,如内存分配,文件存
取状态等等,不过你完全可以简单地把进程说成是“一个执行中的程序”。除了少数核
心进程之外,其他的用户级进程就是这样一些东西。

一般把进程的状态分成下列几种:

运行态:进程随时可以执行

睡眠:由于进程缺少某些必要的资源,所以陷入了挂起的状态,只有得到某个信号才
能继续运行

阻止:由于某个原因,系统向进程发出了一个阻止信号,于是进程暂时停止运行,直
到接受到一个“继续运行”的信号才可以继续。

僵尸:进程本来应该已经死亡,但是由于某种原因,进程占用的id号还没有被释放。

为了显示系统中的所有进程,可以使用ps -aux命令,例如,下面是一个例子:

USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND

root 1 0.1 0.1 1104 368 ? S 14:34 0:05 init [3]

root 2 0.1 0.0 0 0 ? SW 14:34 0:05 [kflushd]

root 3 0.0 0.0 0 0 ? SW 14:34 0:03 [kupdate]

root 4 0.0 0.0 0 0 ? SW 14:34 0:00 [kpiod]

root 5 0.2 0.0 0 0 ? SW 14:34 0:08 [kswapd]

bin 358 0.0 0.1 1196 288 ? S 14:36 0:00 portmap

root 413 0.0 0.0 1156 180 ? S 14:36 0:00 syslogd -m
0

root 424 0.0 0.0 1448 0 ? SW 14:36 0:00 [klogd]

daemon 440 0.0 0.1 1128 296 ? S 14:36 0:00 /usr/sbin/a
td

root 456 0.0 0.0 1304 188 ? S 14:36 0:00 crond

root 476 0.0 0.1 1124 436 ? S 14:36 0:00 inetd

root 492 0.0 0.1 1176 436 ? S 14:36 0:00 lpd

root 521 0.0 0.1 2104 284 ? S 14:36 0:00 sendmail: a
ccept$

root 538 0.0 0.1 1144 384 ? S 14:36 0:00 gpm -t ps/2

root 554 0.0 0.0 2560 68 ? S 14:36 0:00 httpd

root 744 0.0 0.4 2216 1100 pts/0 S 14:59 0:00 login -wang
hy$

wanghy 745 0.0 0.3 1744 980 pts/0 S 14:59 0:00 -bash

root 815 3.2 0.4 1656 1088 tty1 S 15:26 0:26 ncftp

wanghy 827 0.0 0.3 2680 968 pts/0 R 15:40 0:00 ps -aux

root 845 0.0 0.3 1576 856 pts/0 T 15:48 0:00 vi

第一栏里给出的是进程的拥有者。不过这里有一些微妙的事情,进程有四个跟拥有者
相关的数值,分别是uid,gid和euid、egid。后两者是进程执行时使用的“实际”身份,
它们通常和uid与gid相同,然而对于一个setuid或者setgid程序,这里将显示进程的实
际使用的权限。

第二栏的数值是进程的唯一pid号,或者进程标志符,操作系统用这个数字来标出进程
的身份。

接下来的几行是一些信息,如CPU和内存的使用情况等等,第八栏是进程的执行状态,
标有S说明这个进程正处于睡眠中,R表示进程处于运行中,而T表示进程被阻止,正在等
待一个CONT信号让它重新投入运行。

在这里提到了信号这个词,信号大致就是系统向进程发出一个通知,警告它必须尽快
去处理某些事情。在UNIX中定义了许多信号,但和普通用户及管理员关系最密切的有下
面这样一些:

信号ID 名称 含义 是否可以捕获 是否可以阻塞?

1 SIGHUP 挂起 是 是

2 SIGINT 中断 是 是

3 SIGQUIT` 退出 是 是

9 SIGKILL 杀死进程 否 否

15 SIGTERM 软件终止 是 是

如果想了解关于信号的详细内容,可以参考linux头文件中的signal.h。实际上,对于
最终用户,signal更多地用来杀死某个不应该被执行的进程,这是通过执行kill或者ki
llall命令实现的。

kill命令用来向进程发送一个信号,其语法是

kill [-信号] 进程ID

其中的信号可以使用信号ID或者信号名,使用信号名时,前缀SIG省略,如果不明确地
给出信号,那么使用信号SIGTERM。尽管技术上可以用kill向进程发送任何信号,但是实
际上这个命令几乎总是用于杀死进程。进程ID就是在ps ax中看到的进程pid,例如,在
上面的例子中,杀死portmap程序的命令是

kill 358

或者

kill –15 358

或者

kill –TERM 358

因为SIGTERM信号可以被捕获和阻塞,所以一个设计好的程序可以不理睬这个信号,如
果要杀死这样的程序,可以使用SIGKILL信号,如:

kill –9 358

或者

kill –KILL 358

使用pid对许多人可能是不方便的,另外,可能有一个程序的多个拷贝在内存中执行,
一个一个地杀死这些程序有时是很讨厌的事情,为此,Linux提供了killall命令。kill
all和kill基本等同,但是它使用进程名而不是pid来发送信号,因此可以一次杀死所有
同名进程。

kill –l或者killall –l将显示所有可用的信号。

有一个信号SIGTSTP用于定义“键盘阻止”。处于某些原因,你可能想暂停当前的某个
工作而去进行某个更重要的工作,这可以通过按下^Z来完成,按下这个组合键时,系统
象当前的前台程序发送SIGTSTP信号,于是当前程序被阻止,你可以在这个期间进行其他
工作,例如,在前面的例子中显示的被阻止的vi就是这样一个程序,用jobs命令可以显
示当前被^Z挂起的程序:

[openlab]# jobs

[1]+ Stopped vi

最前面的号码是作业号,在挂起这个程序之后,你可以用fg命令将它重新投入前台运
行,或者用bg命令将它放到后台去执行。

语法是

fg [作业号]

bg [作业号]

省略作业号则执行最近被阻止的作业。

当一个进程的父进程被撤销时,它通常会接受到撤销信号,从而它也会退出。

另外一个常用的指令是&,它通常用于避免程序截获前台输入,例如,在xterm下,直
接执行netscape & 将启动netscape 程序,在netscape退出前,xterm只能等待。相反,
netscape &指令启动netscape,同时xterm仍然可以处理前台命令。

2.5.2 forks和exec

forks是UNIX中被程序员熟知的功能之一。简单地讲,forks创造一个新的进程。

实际上,forks是一个进程用来克隆自身的方法,某个进程调用forks将在内存中开设
一个自身的拷贝,即建立一个与自身几乎完全相同的进程。执行forks的进程称为父进程
,而克隆出的进程称为子进程。两者只有非常小的区别:两个进程的pid号不同;新进程
要建立自己的一些资源。

实际上,整个UNIX的进程创建机制都是基于forks的。执行一个新的程序在UNIX中有一
个专门的功能组,称为exec,它包含彼此差不多的一些函数族,如execl,execv等等,功
能上也相似,都是去执行另外一个程序。但是,UNIX的exec函数被设计为被执行的程序
接管原来程序的全部资源,因此当被执行的程序结束以后,执行程序也就消亡了。显然
,这不是我们想要的,所以,UNIX/Linux在准备启动一个新的程序时,负责启动的程序
首先调用forks产生出一个新的进程,在这个过程中它使用forks的一个功能,即forks函
数自动区分是原始进程还是被forks出来的进程,如果是子进程则调用exec来执行所要调
用的程序。

一个主进程可以forks出多个子进程,当然,forks越多,就消耗越多的资源,有时这
可能是很讨厌的,因此,在大部分Linux系统上限制每个进程只能forks出有限的进程数
,缺省下这个数字是256。因为许多服务器守护进程都依赖于forks,所以这个限制经常
是服务器噩梦的来源。如果你的网络负担非常沉重,你可能必须手工调节这个数字把它
加大到一个合理的值。(不过,也许使用更强大的系统是更合适的解决方法?)

要察看当前的 forks极限,使用ulimit命令:

[wanghy@openlab wanghy]$ ulimit -u

256

如果要设置forks极限,使用带参数的ulimit指令:

ulimit –u 512

这个命令将forks极限设置为512。

ulimit –u unlimited

这个命令取消对forks的限制。

另一个问题是进程的优先级。内核调度任务时,优先级越高的任务能得到越高的CPU使
用率。一般情况下,内核会自动安排进程的优先级,而且这种普通的进程优先级机制已
经完全够用,然而,在某些极端的情况下,你可能想让某些任务以尽可能高的优先级执
行。

强行指定某个进程的优先级是不可能的,但是你可以在一定的范围内让某个任务以尽
可能高的优先级运行,这可以用nice命令实现:

nice –n -15 sh

这个命令让你以一个很高的优先级执行一个新的shell。-n后面的数用来标志你对这个
进程的期待值,这个数越小,进程的优先级越高,范围是从-20到19。

启动的进程仍然可以用renice命令修改期待值,例如:

renice –20 1553

将pid为1553的程序的优先级提升到最高。

2.5.3 守护和服务器守护程序

守护程序就是一个在后台跑的程序,它通常用来执行一些系统相关的任务。大部分守护
进程都是在系统启动是投入运行,随时等待呼叫。但是守护程序也可以设置为手动启动
和停止。

最基本的守护程序是init程序,当系统启动后它就开始运行,实际上除了内核产生的
进程以外所有的进程都是init直接间接地forks出来的。另外两个几乎一切UNIX都必须提
供的守护程序是inetd和crond,crond用来设置在某个特定的时间执行特定的工作(例如
:在每星期六晚上10:00开始整理硬盘)。

inetd是一个用来管理许多存取不太频繁的服务进程的守护程序,它在有任务时启动
对应的服务进程并且在网络客户程序和服务进程之间执行翻译,通过inetd启动的服务器
进程可以不理会复杂的BSD网络编程接口,inetd把通过网络的通信翻译成普通的文件读
写操作,使得编程变得简单,但是相应地,inetd的效能不是很好,因此重负荷的应用通
常用独立的守护进程实现。

大部分独立的网络服务被实现为服务器守护程序,它们可以被绑定在某一个端口上,
在后台接受客户的请求,许多这样的守护程序使用forks机制来完成工作,例如sendmai
l。sendmail监听向25端口的请求,当接受到一个这样的请求时,它forks出一个自身的
拷贝,将连结请求交给这个子进程,然后它自己又可以在25端口上继续监听。

由于forks的问题,个别服务器守护程序会在内存中产生多个子进程,例如httpd程序
,在一台负担很重的机器上,它可以产生出几百个子进程,而只有第一个进程是真正的
控制进程。要找到这样的进程当然可以用more和grep命令仔细寻找,但是Linux系统中提
供别的方法,前面讲到的killall是一个可行的方案,另外一个方法包含在/var/run目录
中,其中会以xxxx.pid的形式包含了守护进程启动时(第一个)的pid,其命名方法就是
守护进程的名字(如果是在inetd.conf中启动的守护进程则由inetd程序命名),格式就
是一个简单的文本文件,例如:

[wanghy@mail run]$ cat /var/run/httpd.pid

392

[wanghy@mail run]$ ps ax | grep httpd | more

392 ? S 0:00 httpd

26070 ? S 0:00 httpd

26071 ? S 0:00 httpd

26072 ? S 0:00 httpd

26073 ? S 0:00 httpd

26074 ? S 0:00 httpd

显然杀死httpd进程的命令是

kill `cat httpd.pid`

注意反引号是执行其中的命令。

但是要注意sendmail有所不同,其pid文件除了包含pid号之外,还包含了sendmail的
启动命令:

[wanghy@mail run]$ cat sendmail.pid

363

/usr/sbin/sendmail -bd -q1

下面是常用的网络服务器守护进程的列表:

inetd:启动其他网络服务的服务器

下面是由inetd启动的常用服务器:

sendmail:邮件传输服务器

in.telnetd:telnet服务程序

in.ftpd:ftp服务器

pop3d:邮局协议服务器,用于向邮件客户机器最终传送邮件和管理服务器上存储的邮
件。

下面是一些其他的服务器:

httpd:Apache WWW服务器的守护程序

smbd:windows 9x类型文件服务程序

nfsd:网络文件系统服务器

portmap:端口映射服务,为很多其他服务器提供服务

lpd:打印机服务程序

named:网络域名服务器

nmbd:广播netbios名字的服务程序

innd:电子新闻组服务器

routed:路由服务器

sshd:SSL shell服务程序

守护程序对信号的响应与一般进程稍有不同,例如,SIGHUP信号通常将使接受到这个
信号的程序终止。但是当一个守护程序接受到这个信号时,它简单地让自己重新启动。
实际上,在调试服务器时经常需要重新启动守护进程,而killall –HUP是简单可靠地重
启某个服务器守护进程的标准方式。

另一个容易出现问题的地方是守护程序的uid。如同我们在第一张中解释的那样,为了
进行服务,守护程序必须将自己绑定(bind)到某个端口。TCP/IP实现中保留小于1024
的端口号用于提供服务,而更高的端口可以用于客户程序发起请求。考虑到这种情况,
UNIX要求凡是绑定到数值小于1024的端口的程序必须具有root权限,这意味着大部分服
务器守护进程必须以root身份执行,因此它们可以做任何事情,这潜在地对系统的安全
性构成了威胁(显然,你不能从普通用户的身份启动httpd)。幸运的是,大部分服务器
守护程序在设计的时候都已经考虑了这个问题,有些程序让inetd来完成绑定,因此它们
可以以一个比较低的权限来执行,而另外一些程序则用一个具有root权限的进程处理所
有的请求,当得到一个请求时,它forks出一个子进程,并且将子进程的euid设成权限比
较低的用户,然后再让子进程处理这个请求。例如,apache服务器当使用独立程序启动
时就使用类似这样的方式。也有一些守护进程必须以root身份执行,最典型的是sendma
il,对于这样的程序必须小心,因为许多攻击都是利用这种程序的漏洞。

2.6 账户管理

在你安装系统之后,你必须建立一些用户以便使用。尽管技术上建立和删除账户应该
在日常管理的部分完成,但是我们这本书是一本教程,如果等到讲日常管理那一章再出
理,你的Linux可能已经被错误操作破坏了n次了。



5楼
【资料】Linux基础教程 2.6.1 口令文件
2.6.1 口令文件

Linux是一个多用户操作系统,在系统中可以有多个用户在同时工作,为了管理账户,
Linux使用两个文件,称为/etc/passwd和/etc/shadow。

passwd文件在前面就已经提到过,现在来详细的解释一下,让我们看一看前面提到的
/etc/passwd文件,通常这个文件每行代表一个用户,格式是这样:

wanghy: $1$EtinNb.u$uMi3KAS9l9XY1CNJ99zWB1:501:501::/home/wanghy:/bin/bash

各个栏目之间用冒号分开,第一栏是用户的名字,就是在系统的login:提示符下输入
的名字,接下来的一栏是加密后存放的口令字,在一般的UNIX系统上,这个加密使用DE
S加密算法,但是由于计算机技术的发展,短密钥的DES加密技术已经无法提供足够的安
全性,而长密钥加密系统要受到美国法律的限制。目前,Linux支持MD5加密方式,这种
加密方式产生的密文就类似于上面的情况。当然,你仍然可以使用原来的DES短密钥方式
,但其可靠性不是很高。

下面的两栏是uid和gid,UNIX通过这两个值来确定用户身份。然后有一栏是空的,这
一栏曾经用来填写用户的详细资料,不过UNIX从不使用这个内容,因此你可以让它空着


/home/wanghy是这个用户的宿主目录,注意这个目录必须是这个用户可以访问的,否
则无法登录,接下来,/bin/bash是用户登录时使用的缺省shell。

上面说的是passwd的原始形式,不过,这种形式中口令密文被存放在passwd中,意味
着任何人都可以看到。尽管MD5的加密强度比较高,但是利用高性能的计算机和蛮力搜索
的方法,完全有可能用穷举的方式找出用户的口令原文(办法就是猜测一个口令,加密
演算后和密文比较,如此循环)。特别是UNIX的口令通常限制为不多于8个字符,一个有
足够决心的口令猜测者是有可能完成的。因此,几乎所有的Linux系统都使用shadow方式
,这种方式中,密文保存在shadow文件中,而passwd文件中只有一个"x",例如,在/et
c/passwd中:

wanghy:x:501:501::/home/wanghy:/bin/bash

而同时系统中有一00个shadow文件,它才是真实的password文件,但是它被设置为只
有超级用户才能读取,下面是/etc/shadow文件中的相应内容:

wanghy:$1$EtinNb.u$uMi3KAS9l9XY1CNJ99zWB1:10977:0:99999:7:-1:-1:134550524

在口令密文之后的几项是一些设置,例如口令被更改的时间,口令的有效期等等。不
过你实在没有理由一定要研究它们,useradd和adduser程序会做同样的事情。

传统上,可以使用直接编辑passwd文件的方式来管理用户信息,这种方式最常用的是
用来建立一个没有口令的用户。但是如上所述,要使得更改有效,必须同时修改passwd
和shadow文件才能完成这个工作,为了解决这个问题,可以使用pwconv程序,它可以根
据/etc/passwd的内容对/etc/shadow文件进行同步。


$ pwconv

通过passwd中的口令栏的设定(实际是/etc/shadow文件的设定),可以设置不需要口
令就可以登录的用户和禁止登录的用户,例如,这样的passwd设定:

testvv:*:502:502::/home/testvv:/bin/bash

口令处的星号将testvv设置为无法登录,相反,如果这里是空的,表示不需要口令:

testvv::502:502::/home/testvv:/bin/bash

另一对用来做账户管理的文件是/etc/group和/etc/gshadow。这两个文件用来管理用
户组,其关系相当于passwd和shadow,例如,下面的group文件:

root:x:0:root

bin:x:1:root,bin,daemon

daemon:x:2:root,bin,daemon

sys:x:3:root,bin,adm

adm:x:4:root,adm,daemon

定义了五个用户组,每行一个,如bin的用户组gid是1,其中包括root,bin和daemon三
个用户。对应的口令文件在/etc/gshadow,同样可以手工编辑/etc/group文件进行用户
组的管理,然后用grpconv来同步:

$ grpconv


2.6.2 账户的添加和删除

显然,我们可以手工修改/etc/passwd文件来实现账户的添加和删除,不过除非你右受
虐倾向,否则意义不大(如果你真的要这么干,你可以使用vipw程序)。相反,我们建
议使用adduser程序。

adduser程序最简单的用法是

adduser [用户名]

例如,adduser test将建立一个名为test的用户。

adduse有一些常用的命令开关:

-c [注释] 填写passwd文件中的注释域的内容(就是那个从来不用的栏目)

-d [宿主目录] 定义用户的宿主目录,这个目录将被自动创建,如果缺省,使用/hom
e/用户名,例如,对于test用户就是/home/test

-e [有效期] 到哪一天用户的这个账号口令将被失效,格式是YYYY-MM-DD

-f [天数] 口令达到有效期的话对用户警告的天数,超过这个天数账号就会被禁止登
录。缺省值是-1,表示永远不会真正禁止登录。

-G [组名] 用户属于哪个组

-m 创建宿主目录,这是缺省值

-M 不创建宿主目录

-n 建立用户的同时建立一个同名的用户组,这个是缺省值

-s [路径名] 用户的登录shell

-u [uid] 用户的uid

在建立用户时,缺省的情况下,一些基本的设置定义在/etc/login.defs文件中,而如
果存在/etc/skel目录的话,这个目录中的所有文件都会被拷贝到用户的宿主目录中,所
以你可以设计一套比较好的配置文件,如.bashrc,.profile等等,然后放在/etc/skel
目录中。

刚刚建立的Linux帐户是帐户是无法登录的,为了使用户能够以这个用户名登录,超级
用户必须执行passwd程序为用户设置口令,例如,建立了test用户之后:

passwd test

系统将提示你输入用户口令并且确认,确认之后就可以使用这个帐户了。

要删除某个帐户,使用userdel命令:

userdel [-r] [用户名]

-r选项在删除用户的同时也会自动删除他的宿主目录。

2.6.2 特殊账户

在一般的系统中,都会有一些特殊的账户,许多这些账户都是系统进行管理或者执行
服务功能用的,这些账户被设置为不可登录(在shadow文件中的口令域是一个*)。例如
daemon,uucp,lp,mail,news等等。

有一个账户是特别需要注意的,即nobody用户,它相当于其他系统的guest账号,缺省
下的这个账户是

nobody:x:99:99:Nobody:/:

由于是一个guest账户,所以不应该有任何文件属于它,以免引起安全性问题。在许多
系统上,nobody的uid是65535(-1),不过为了避免出现稀疏文件问题,Linux用一个小得
多的数值。


2.7 Linux版本和其他服务器系统

现在我们介绍一些关于Linux的知识。这些东西仅仅是一些个人看法,信不信是你自己
的事情。

2.7.1 Linux的内核版本和发行版本

关于Linux的版本问题有两种主要的内容,分别是内核版本和发行版本。内核版本就是
我们前面提到的,由Linus维护的系统内核的版本,由于每天都有新的要求提出或是新的
漏洞被发现,因此从产生的那一天起Linux内核就在不断的修改和升级之中。一般情况下
,对于一个服务器系统,我们关心的是那些已经被发布的稳定版本,目前这个系列的主
要版本号是2.2,我用的是2.2.14,另外,2.4的版本也即将发布。

一般来说,关心内核版本号的主要理由是编译应用程序或者修补已知的漏洞。对于编
译应用程序,可以认为主版本号相同的系统之间的差异可以忽略,而如果主版本号不同
就可能为你的移植过程带来烦恼。另外,由于新的漏洞不断地被发现,所以不断地升级
你的内核可能是必要的,至少,了解自己使用的内核是十分重要的。

另一方面,我们能接触到的通常都是发行版本,发行版本其实就是某个厂商或者组织
搜集了一些应用程序,编译并且打包,然后以CD-ROM的方式发布出来。对于应用软件来
说,各种发行版本之间的差别实际是很小的,但是,对于系统管理员的日常维护,它们
之间的关系就很讨厌了。

各种发行版本通常都有自己的安装程序,为了安装程序的方便,各个版本按照自己的
方案对系统的目录(主要是/etc)往往要进行重新组织,结果是,一个熟悉redhat的配
置专家可能在debian面前晕头转向。

大量使用的配置程序往往使问题变得更加复杂。基于菜单或者图形的配置工具通常会
使得问题变得简单一些,但是它们往往依赖于假定某些文件“就在某个地方”,结果当
你试图把它们移植到别的发行版本的时候,你会发现过大的工作量会使你感到根本不值
得。

另外,每种发行版本都会带有自己搜集的一些应用程序,技术上说这些程序不是发行
版本的一部分,你可以从别的地方拿到这些程序,或者把某个发行版本里的程序拿到其
他发行版本里面用。

值得说明的是,目前有所谓“中文的Linux”,笔者无意对此多加评述,但是对于一
个服务器来说,中文界面实际是不需要的。由于Linux内核的原因,无论中文或者英文的
Linux服务器都可以建立和管理中文的文件名。既然你不会用一台服务器作为上网的浏览
工具,那么中文化对你并无现实的好处,而在目前,许多中文化系统都必须在系统内核
或者别的什么地方打上一些补丁,它们潜在地引入了不稳定因素。

目前发行的Linux主要版本中,有些是为桌面准备的,例如corel的产品,也有一些由
于某种原因很难拿到。在剩下的产品中,我建议你考虑如下产品:

redhat :如果你是一个新手,你可以考虑这个产品。它包含大量的配置命令和附加程
序,非常容易安装和配置。

Slackware:这是一个适合于喜欢手工编写系统配置程序但是经验不是很多的用户的版
本,它的脚本组织的很简单也很清晰。不幸的是它包含的附加程序比较少,你可能不得
不从网络上下载大量的东西以便使用

Turbo Linux Chinese:这是一个中文化的版本,谢天谢地它的中文是用外挂应用程序
的方式实现的,也就是如果你不使用中文你就可以把中文补丁拆掉。其完整发行版本包
含10张CD-ROM,包含了一般情况下你需要的“几乎所有”的东西,价格也不菲(300元以
上,当然相对于其价值来说便宜得难以想象)。尽管如此,它的某些为了中文化而做的
努力对于服务器管理者可能还是十分讨厌的。

红旗Linux:这个可以合情合理地看成redhat的汉化版本,不过好像没有源代码包,其
他关于redhat的评语都可以直接用到它上面。价格么。。。。比redhat贵一些。

2.7.2 其他服务器操作系统

选择Linux作为网络服务器的主要理由是性能价格比。任何Linux发行版本的价格相对
于网络服务器或者管理费用都是可以忽略的,除此之外,另外的一些原因也在考虑之列
,比如管理的复杂性,维护和技术支持的费用等等,未来的可升级性。

通常你不会是网络工程的负责者而仅仅是一个服务器或者网络系统的管理员,因此这
里列出一些常见的网络服务器操作系统,将它们和Linux做一些对比,也许这些比较能说
明你的老板选择Linux,也许不能。

在谈论这些比较之前我们应该首先澄清几个问题。许多传统UNIX的用户宣称Linux是“
一个玩具”,笔者并不反对这个说法,但是任何系统都是从玩具发展起来的。在当年IB
M vs UNIX,UNIX vs Windows NT和CP/M vs MS-DOS我们都听到过前者对后者的贬低。对
这个问题的最佳回答是,如果市场上的10元人民币的玩具小汽车能够带20吨有效载荷以
每小时200公里的速度从北京跑到哈尔滨,而一百万元的名牌载重卡车却只能每小时跑5
0公里,那么没有人在乎他们用的是不是玩具汽车。另外一个典型的误解是,软件价格总
是可以忽略的。事实上,当你面对那些商业产品的时候,这个概念可能正确也可能不正
确,例如,Solaris只需要很低的费用就可以买到,然而你也许必须购买昂贵的专用工作
站来跑它,总的成本可能远远超出你的想象。

另一个很重要的问题是,Linux是一种低端产品,显然,用18元的redhat加上一万元的
DIY机器与上百万元的IBM大型机相互比较是毫无意义的,我们的讨论将限于在低端使用
的那些常用的服务器系统。这主要包括Solaris,SCO UNIX,Windows NT和FreeBSD,由
于使用Netware的用户已经很少,所以我们将不再讨论这个产品了。

所谓低端,我们是在x86服务器的意义上说的,它通常指这样的一个系统:

处理速度低于每秒10亿次(比如说双Pentium III 500或者G4之类的处理器)

内存不多于512MB(在x86系统上通常可以配置很多的内存,相反,工作站系统的内存
经常会让人无法接受。尽管工作站内存比普通的DRAM效果好,但是在繁重的任务中,内
存耗尽通常是首先发生的,存储器的容量比质量更重要)

网络接口的速度不高于100M(GB级的以太网已经开始使用,然而,一个GB级的网络服
务器意味着什么样的服务器负担?)

同时连接数低于1000(这是一个什么概念?它意味着你的网站将接受每天上百万甚至
几百万的访问量)

①Linux & Windows NT

这两者都运行在x86系统上,而且技术上说你绝对可以用DIY的机器运行Windows NT,
但是两者仍然有区别。

Windows NT一直被Linux用户诟病的是它的执行效率,以及易于崩溃的名声。与某些宣
传相反,实际上Windows NT对硬件的要求是极其奢侈的。实际上我怀疑能否在我们这里
说的“低端”硬件上有效地运行Windows NT。在双PIII Xeon+512MB内存的系统上Windo
ws NT表现的还可以,但是在PII 350+64MB的系统上Windows NT表现的如同蜗牛一般,而
且应该记住Microsoft的“官方”说法是NT的系统要求是Pentium 166+32MB。在那些典型
的Linux vs NT的测试中,使用的内存通常高达2GB,我怀疑你是否有足够的预算来完成
一个基于NT的系统。下面是一些来自Microsoft的关于Windows 2000 Server的信息,你
可以自己对你需要的硬件进行一个估计:



Windows 2000 Server硬件要求



133MHz或更高的Pentium兼容的CPU

建议至少有256MB的RAM(最小支持128MB;最大支持4GB )

2GB的硬盘,至少有1.0GB的空闲空间(如果你是通过网络进行安装将需要额外的硬盘
空间)

Windows 2000 Server最多支持在一台机器上有4个CPU


除此之外,Microsoft Exchange Server又是一个额外的预算开销。你可以不使用N
T的文件和打印服务而仅仅让它作为Web服务,这样不涉及许可证问题,但是你不可能不
让你的用户使用电子邮件,而Exchange Server的许可证费用足以让你破产。另外,就我
们所知道的,Exchange Server至少需要128MB内存和双CPU才能以合理的速度运转。(当
然,是在Microsoft的意义上的“合理速度!”)

相反,Linux的硬件需求低的多,事实上,一台普通的PII +64MB内存可能就足以满足
一个普通的公司的需求。而且你不需要考虑烦人的许可证限制。特别是,由于Linux的投
资如此之小,所以在任何情况下,你都可以首先试验一下,即使不成功你也决不会损失
什么。

②Linux & 商业UNIX

无疑很多人仍然愿意选择商业的UNIX。由于商业的UNIX多数运行在RISC系统上,把它
们和DIY的x86兼容机相比显然毫无意义。但是也有一些可以在x86系统上运行的UNIX实现
,如Solaris for X86和SCO UNIX。

Solaris for x86是一个典型的产品,其SPARC版本已经为人们所熟知,但是x86版本并
没有经受过太多的考验。尽管Sun的支持者大量宣传Linux如何不稳定,或者如何缺少复
杂的特性,但是在x86上Solaris并没有表现出比Linux更高的稳定性(Solaris的图形倒确
实比Linux好得多,但是这肯定不是一个服务器管理员所关心的),而且,尽管理论上So
laris是一种出色的产品,但是一个甚至不包含编译器的UNIX系统是你需要的吗?

Solaris确实拥有许多应用程序,但是在普通的Solaris发行版本中并不包含这些东西
,你得另外购买,而且,Sun提供的许多程序并不是世界上大部分人正在使用的那一种,
你可能必须完成Sun的专门培训才能成功地使用这个产品,这意味着额外的开销。当然,
你可以去寻找免费的程序并且编译它们,但是这就会面对一个新的问题,Solaris的普通
发行版不包含编译器,所以你或者出一笔额外的开支购买C编译器,或者去下载GNU的GC
C编译器,但是后者在Solaris系统中到底会产生什么样的代码很难说。这是因为Solari
s并不是一种标准的UNIX,(或者说,既不是SYSTEM V也不是BSD),而且Sun出于自己的
目的更改了许多东西,你会发现这是一件非常头痛的事情。

当然SPARC上的Solaris具有比Linux更好的稳定性和带负载能力,但是我想在现在x86
芯片以18个月加快一倍的速度发展的时代,你肯定不愿意每年购买一台SPARC然后在年底
将它淘汰(也许你可以不淘汰,但是你愿意相信200MHZ的SPARC在性能上能超越600MHZ
Pentium III Xeon吗?),相反,每年淘汰几台x86倒是任何公司都会干的事情。

[有一个真实的例子。我们曾经购买了一台SPARC工作站用来作为Internet服务器,但
是某一天它的sendmail配置坏了,于是我们需要重新配置,但是没有人能从头写一个se
ndmail.cf,所以我们试图使用m4程序来完成,但是发现在那个版本的solaris中不包含
配置sendmail必要的一些文件,而且对于当时14.4KB的连接速度,下载sendmail配置程
序显然是不现实的。于是这台SPARC就变成了废物,所有人无奈地等待他们的电子邮件,
直到最后我们用一台Linux代替了它。现在我们用那台Solaris当成执行Linux图形程序的
终端。]

SCO UNIX是另外一个例子,它通常用于银行和保险业中,由于历史上的原因,SCO的局
域网支持是不错的的,但是其Internet服务器程序不是很好。而且SCO UNIX大概是最古
怪的UNIX实现之一,无论如何,我们不会建议一个新手使用SCO。

③Linux & BSD

对于低端的应用,也许唯一可以对Linux构成威胁的是BSD家族的成员,特别是FreeBS
D。

FreeBSD也是一个免费的UNIX系统,不同的是它是一个纯的UNIX系统,是一个标准的B
SD风格UNIX的实现,另外,它的版权规则和GPL不同。由于原始设计的一些原因,FreeB
SD的网络特性要比Linux好一些,特别在系统负担沉重的时候。许多著名的网站都是利用
它构成的。

本书作者同时使用Linux和FreeBSD,但是在单位的网站上则使用Linux。事实上,Fre
eBSD超强的带负载能力显然对于象作者所面对的那样的环境是没有必要的,而Linux相对
于FreeBSD则表现了容易管理和支持硬件较多的优点。另外,由于要作为Proxy Server,
所以Linux的高速缓存文件的能力是非常重要的,相反,FreeBSD的磁盘处理速度不是很
令人满意。

尽管如此,作者同样相当欣赏FreeBSD,事实上,如果你要做的是一个极其庞大负担也
十分繁重的系统,那么,可能FreeBSD会是比较好的选择,相反,如果你的主要任务是文
件和打印服务,或是如同我们一样用DDN专线连入Internet,那么Linux可能更合适一些

电脑版 Page created in 0.0781 seconds with 4 queries.