IT家园's Archiver

逍遥 发表于 2006-6-5 15:23

第十九章 数据库系统
现在许多的商业应用、网页程序都必须使用数据库来存放数据。例如,网站上的留言版、讨论区、购物网站等,全部都是使用数据库来存放重要的数据。本章中,我们将介绍二种常见的数据库:MySQL 及 PostgreSQL。
本章包含了数据库的安装、设定、语法、及各种操作方式的介绍,读完本章后,您将可以了解下列主题:
如何安装、设定 MySQL。
如何安装、设定 PostgreSQL。
如何使用 MySQL 的图形化管理工具。
如何使用 PostgreSQL 的图形化管理工具。
基本的数据库语法介绍。
如何备份、回存数据库。
这些信息将有助您建立一个功能强大的网站,并对于日后安装数据库相关应用时更加得心应手。
19.1 概论
电子商务的兴起让数据库的应用更受到大家的瞩目。在信息科学的应用上,数据库可以说是最历久弥坚的领域。近来,数据产生和数据收集方面的技术有非常快速的进展。许多商业产品广泛使用了条形码、许多企业和政府的交易皆已计算机化,这使得计算机成为数据收集的主要工具。同时,数以百万计的数据库正被使用在企业管理、政府管理、科学和工程的数据管理和许多其它的应用上。
我们可以安装一套数据库系统,并经由一个接口自行开发程序来使用它。数据库的好处有很多,相信对数据库稍有涉入的人都知道,例如数据存取快速、不重复、权限控制、数据独立性等等。以写一个简单的留言版程序而言,传统上使用档案做为留言的记录,若要删除一笔数据,必须对整个档案一行一行的比对;但数据库只需指定该留言的编号即可。不过,如果把数据库系统局限于留言版也太大才小用了。
我们将介绍在 FreeBSD 上使用数据库,因为目前网页数据库使用情形十分风行,尤其在网页开发上使用 MySQL 或 PostgreSQL 数据库加 PHP 更是绝配。目前 Open Source 的数据库中,最常用、最有名的就是 PostgreSQL 及 MySQL,因此,本章将先介绍这二个数据库系统的安装及使用。
至于 PostgreSQL 及 MySQL 这二个数据库系统有什么差别?到底应该选哪一个呢?在 MySQL 3.x 以前,如果您问我这个问题,我一定说 PostgreSQL,因为 MySQL 3.x 不支援 transaction。所谓的 transaction 就是将一连串的 SQL 指令做为一个执行单位,当其中一个指令失败,在同一个 transaction 所执行过的命令都取消。Transaction 对于程序开发的应用十分重要,例如,当我们要新增处理一笔订单时,我们会先将订单输入数据库中,再将金额输入应收帐款中。如果我们在新增应收帐款时出现错误,而订单却已输入数据库,是不正确的做法。有了支援 transaction 的数据库,我们可以将订单的输入和应收帐款的输入做为一个执行单位,如果其中一个执行失败,则数据库会自动取消先前先做的动作,如此一来便可以确保数据的正确性。由于 transaction 十分重要,因此在做为商业上的应用时,我会选择 PostgreSQL。
不过 MySQL 4.x 后已经加入 transaction 的支持,只是功能还是没有 PostgreSQL 那么完整。那么除此之外,这二个数据库的差别是什么?PostgreSQL 是一个功能强大的数据库系统,它的威力不下于商业用的数据库。而 MySQL 的特性是对于简单 SQL 指令处理快速,大部份的日常简单操作,MySQL 的速度会比 PostgreSQL 快一点。以下我们列出它们在功能上的主要差异:
[b]功能[/b]
[b]MySQL 3.x[/b]
[b]MySQL 4.1.x[/b]
[b]PostgreSQL[/b]
版权宣告
GPL
GPL
BSD
Sub-Selects
No
Yes
Yes
Views
No
No
Yes
Foreign Key relationships
No
Yes
Yes
Foreign Key constraints
No
No
Yes
Triggers
No
No
Yes
Indexing on non trivial types
No
No
Yes
Sequences
Some
Some
Yes
Transactions
No
Yes
Yes
OO (Inheritance of tables)
No
No
Yes
Async Notifications
No
No
Yes
Constraints
No
No
Yes
SELECT INTO
No
Yes
Yes
Stored Procedures
No
No
Yes
Row level locking
Yes
Yes
Yes
Table level locking
Yes
Yes
Yes
Multi version Concurrency Control
No
No
Yes
我们可以看到 PostgreSQL 功能真的强大很多,如果您必须设计功能强大又复杂的系统,PostgreSQL 是不二之选。而 MySQL 4.x 以后的重要功能都很齐全,速度也很快,比较适合简单的网页应用,所以目前大部份网页应用软件使用 MySQL 比较多。不过呢,笔者认为 PostgreSQL 及 MySQL 都使用 Transaction 时,二者的效能表现差不多,就网页应用而言,我的首选还是 PostgreSQL。
19.2 安装 MySQL
MySQL 和 FreeBSD 一样也有多种版本同时开发,例如 3.x、4.0.x、4.1.x、5.x 等,其中 4.1.x 是目前较稳定的版本。
您可以自行到
[url=http://www.mysql.com/]http://www.mysql.com[/url]
取得最新版的 MySQL Source Package 来安装,不过安装上比较麻烦。所以我们使用 ports 来安装 MySQL:# cd /usr/ports/databases/mysql41-server
# make WITH_CHARSET=big5 WITH_XCHARSET=all install clean
我们指定 MySQL 预设的字集为 Big5,并另外支持所有的字集。接下来请修改 /etc/rc.conf 并加入下列这一行,以让开机时启动 MySQL:
mysql_enable="yes"
接着您就可以使用下列指令启动 MySQL 了:# /usr/local/etc/rc.d/mysql-server.sh start
启动 MySQL 后,我们就可以使用下列指令进入 MySQL 交互式命令列了:# /usr/local/bin/mysql mysql
若安装成功,你将看到以下画面:
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 14 to server version: 4.1.13
Type 'help;' or '\h' for help. Type '\c' to clear the buffer.
mysql>
MySQL 刚安装完成时,并未设定 root 的密码,因此我们接着要设定 root 的密码并实时更新设定:
mysql> UPDATE user SET password=password('你的密码') where user='root';
Query OK, 0 rows affected (0.00 sec)
Rows matched: 2  Changed: 0  Warnings: 0
mysql> FLUSH PRIVILEGES;
Query OK, 0 rows affected (0.02 sec)
以上指令及 MySQL 更详细的设定说明,我们会在下一小节中加以说明。最后请以 exit; 来离开 MySQL。
如果您有其它使用者要加入也可以加入,最好不要让使有人都有对所有数据库有全部的权限。使用命令列的方式新增使用者有点麻烦,我们等一下再使用其它图形化接口进入新增使用者。
建议您以后使用 MySQL 的图形化接口管理工具「MySQL Administrator」及「MySQL Query Browser」来管理 MySQL,我们会再后续章节中说明如何使用这些管理工具。
19.3 SQL 语法介绍
在使用数据库之前,我们必须先了解一些简单而基本的数据库理论。如果您对于数据库 SQL 语法已经很熟悉了,您可以跳过这一个小节。
基本上数据库的结构有下列几个特点:
一个数据库系统中可以有多个独立数据库。
数据库是由许多数据表 (table) 所组成。
数据表中包含许多记录 (record)。
每一笔记录中的字段数目都一样。
每一个字段储存一种分类过的数据。
例如我们有一个数据库名称是NCU,其中有多个数据表,其中一个资料表名为 student 内容如下:
STUDENT_ID
LAST_NAME
FIRST_NAME
DEPARTMENT
1
Chang
Jack
MIS
2
Wang
Alex
BA
在数据表中有许多字段 (column),每个字段都有一个名称,也就是第一列 (row) 中的 STUDENT_ID、LAST_NAME、FIRST_NAME、DEPARTMENT。接着我们将数据存入,每一笔记录我们都可以看成一列 (row),每一个记录都有一个「唯一的 ID (编号)」。唯一的 ID 十分重要,它是我们在存取数据库时的依据。在新增资料时,以 MySQL 而言,我们可以自行指定 ID 或是由系统自行取得。
另一个观念是关系型数据库。关系型数据库的意义就是每一个资料表间可以存在关系,例如我们在 NCU 的数据库中有另一个数据表名为 score,内容如下:
SCORE_ID
STUDENT_ID
CHINESE
ENGLISH
1
2
99
90
2
1
89
87
score 数据表中存放学生的成绩,我们不需在该数据表中存放学生的信息,只要在该数据表中存放一个字段名为 STUDENT_ID,经由这一个唯一的 ID 我们可以去 student 的数据表中找到学生的数据。
有了这些观念就足以让我们开发出许多数据库的程序了。
SQL (Structured Query Language) 语法十分简单,它是关系型数据库的标准语言,虽然在某些不同数据库系统上有些许的差异,但基本上都遵循一定的标准。
我们可以在命令列下进入 MySQL 来练习 SQL 的语法:# /usr/local/bin/mysql -u root -p
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 202 to server version: 4.1.13
Type 'help;' or '\h' for help. Type '\c' to clear the buffer.
mysql>
下完指令后会要求输入密码,请输入您之前设定的密码。登入后你就可以直接在出现的命令列 mysql> 之后输入 SQL 的语法了。
关于 MySQL 详细的语法,你可以参考 MySQL 中文参考手册,该文件可以在
[url=http://www.freebsd.org.hk/html/mysqldoc/]http://www.freebsd.org.hk/html/mysqldoc/[/url]
中找到。该文件中对于 MySQL 每个细节都有详细的描述,例如字段的名称限制、规则等,我们不会在这里提及。我们只介绍几个简单而常用的指令。 我们以建立一个学生数据表来说明这些语法。
CREATE
ALTER
DROP
INSERT
SELECT
UPDATE
DELETE
制成 script 档
19.3.1 CREATE
建立数据库:CREATE DATABASE db_name
建立数据表:CREATE TABLE tbl_name [(create_definition,...)] [options]
我们先建立一个名为 NCU 的数据库:
mysql> CREATE DATABASE NCU;
请注意,每一个指令皆以 ";" 为结尾,如果没有 ";" 就算换行也是代表同一条指令的延续。
我们可以使用下列指令 show 来列出系统中已存在的数据库有哪些:
mysql> show databases;
+-----------+
| Database  |
+-----------+
| mysql     |
| test      |
| NCU       |
+-----------+
3 rows in set (0.01 sec)
接着用 USE 这个指令来使用 NCU 数据库:
mysql> USE NCU;
接着建立一个放置学生数据的数据表,名为 STUDENT,内容为编号(STUDENT_ID)、姓名 (NAME)、科系 (DEPARTMENT):
mysql> CREATE TABLE STUDENT (
STUDENT_ID int(10) DEFAULT '0' NOT NULL AUTO_INCREMENT,
NAME varchar(50),
DEPARTMENT varchar(10),
PRIMARY KEY (STUDENT_ID) );
在上面的指令中,我们定义学生编号为十位数的整数(int),内定值是 0,不可以是空的 (NOT NULL),数字自动增加 (AUTO_INCREMENT)。姓名是最长为五十个字节的字符串(VARCHAR),科系为最长十个字节的字符串。最后定义主要的 id 是 STUDENT_ID,也就是该数据表中的唯一 ID。
我们可以看到在建立数据表时,我们会顺便划分各个字段所要储存的数据长度及其格式,常用的字段格式请参考 MySQL 中文参考手册。
如果要看现在使用的数据库中有哪些数据表,一样可以使用指令 show 来查看:
mysql> show tables;
+--------------------+
| Tables_in_NCU      |
+--------------------+
| STUDENT            |
+--------------------+
4 rows in set (0.00 sec)
19.3.2 ALTER
建立了数据表后,如果发现数据表的字段不符需求,我们不必将数据表删除重建,可以使用 ALTER 指令来修改数据表的格式。另如我们要新增一个姓别字段,内容只可以是 "男" 或 "女",我们可以使用下面的指令:
mysql> ALTER TABLE STUDENT
ADD SEX ENUM('男','女') DEFAULT '女';
我们增加了一个字段 SEX,使用 ENUM 的格式,指定内容只能为 "男" 或 "女",且默认值是 "女"。
如果我们要将 SEX 字段改名为 DISTINCTION,并将格式改为 VARCHAR:
mysql> ALTER TABLE STUDENT
CHANGE SEX DISTINCTION VARCHAR(4);
如果我们只是要将 SEX 字段格式改为 VARCHAR,但不更改名称,只要将上面的指令中 DISTINCTION 改成 SEX 即可。
如果我们要删除整个 DISTINCTION 字段及该字段的数据:
mysql> ALTER TABLE STUDENT DROP DISTINCTION;
19.3.3 DROP
删除数据库:DROP DATABASE db_name
删除数据表:DROP TABLE table_bame
我们可以使用 DROP 指令来删除不要的资料。例如我们要删除 STUDENT 这一个资料表的话,可以使用下列指令:
mysql> DROP TABLE STUDENT;
19.3.4 INSERT
使用 INSERT 指令可以让我们一笔一笔增加数据。
STUDENT_ID
NAME
DEPARTMENT
1
Jack
MIS
假设我们的数据表中的字段如上表,我们要新增一笔数据,姓名是 JACK、部门是 MIS:
mysql> INSERT INTO STUDENT (NAME, DEPARTMENT)
VALUES ('JACK', 'MIS');
由于我们在指定 STUDENT_ID 的格式时,加了参数 AUTO_INCREMENT,所以我们不需指定值,mysql 会自动帮我们依序指定。
19.3.5 SELECT
我们可以使用 SELECT 来看数据表中的数据,还可以依自己给定的条件来过滤数据。
假设我们要看 STUDENT 数据表中的所有数据的话,可以使用下列指令:
mysql> SELECT * FROM STUDENT;
假设我们只要看 NAME 及 DEPARTMENT 字段的话,我们可以使用下列指令:
mysql> SELECT NAME, DEPARTMENT FROM STUDENT;
假设我们只要看 NAME 字段,而且所属部门为 MIS 的人:
mysql> SELECT NAME FROM STUDENT
WHERE DEPARTMENT='MIS';
假设我们要看 MIS 部门中的人所有字段,而且输出结果时要依 STUDENT_ID 来排序:
mysql> SELECT * FROM STUDENT
WHERE DEPARTMENT='MIS'
ORDER BY STUDENT_ID DESC;
最后的 DESC 表示递减 (descending),由大到小排序。也可以使用 ASC 来表示递增 (ascending)。
除了这些之外,在 MySQL 中还有一些可以使用的函式,例如我们可以使用 count() 这个函式来计算出有多少笔记录:
mysql> SELECT count(*) FROM STUDENT WHERE DEPARTMENT='MIS';
+----------+
| count(*) |
+----------+
| 5        |
+----------+
1 row in set (0.00 sec)
上述结果表示部门为 MIS 的记录有五笔。
会了这些基本的 INSERT 指定就够我们做一般的应用了。
19.3.6 UPDATE
我们可以使用 UPDATE 指令来更新记录。例如我们要将所有记录的部门数据为 MIS 者都改成 CSIE,可以使用下列指令:
mysql> UPDATE STUDENT SET DEPARTMENT='CSIE'
WHERE DEPARTMENT='MIS';
19.3.7 DELETE
DELETE 指令可以让我们删除一笔或多笔数据。例如我们要删除 STUDENT 数据表中姓名为 JACK 的记录:
mysql> DELETE FROM STUDENT WHRE NAME='JACK';
如果我们要删除姓名为 JACK 且部门为 MIS 的数据:
mysql> DELETE FROM STUDENT
WHERE NAME='JACK' AND DEPARTMENT='MIS';
19.3.8 制成 script 档
我们可以将要执行的指定制成档案,以利管理。例如我们写了一个程序,需要先在数据库中建立一些数据,我们可以将对数据库的规划做成一个档案来管理。这样可以使用们要安装程序时更快速方便。
假设我们要建立一个数据库 NCU,该数据库中有一个数据表 STUDENT,数据表中要先建有以下记录:
STUDENT_ID
NAME
DEPARTMENT
1
Jack
MIS
2
Mary
CSIE
我们先建立一个文件名为 ncu.sql,内容如下:
CREATE DATABASE NCU;
USE NCU;
CREATE TABLE STUDENT (
STUDENT_ID int(10) DEFAULT '0' NOT NULL AUTO_INCREMENT,
NAME varchar(50),
DEPARTMENT varchar(10),
PRIMARY KEY (STUDENT_ID) );
INSERT INTO STUDENT (NAME, DEPARTMENT)
VALUES ('JACK', 'MIS');
INSERT INTO STUDENT (NAME, DEPARTMENT)
VALUES ('MARY', 'CSIE');
接着使用下列指令来快速建立数据库:# /usr/local/bin/mysql -u root -p
输入使用者 root 的密码后就完成建立了。
如果我们在数据库中早就有一个数据库名为 NCU,而我们要新增上述数据表及记录,我们只要将原本 ncu.sql 的内容最前面二行删除,改成下列内容:
CREATE TABLE STUDENT (
STUDENT_ID int(10) DEFAULT '0' NOT NULL AUTO_INCREMENT,
NAME varchar(50),
DEPARTMENT varchar(10),
PRIMARY KEY (STUDENT_ID) );
INSERT INTO STUDENT (NAME, DEPARTMENT)
VALUES ('JACK', 'MIS');
INSERT INTO STUDENT (NAME, DEPARTMENT)
VALUES ('MARY', 'CSIE');
之后再以下列指令来在 NCU 数据库中建立数据表:# /usr/local/bin/mysql -u root -p NCU
在网络上有许多 PHP 程序可以下载,下载后要安装数据库时,大多是以这种方式来使用。
19.4 MySQL 管理
19.4.1 维护密码安全
当我们要使用 MySQL 时,必须输入密码。输入密码的方式有很多种,第一种也是最不安全的一个方式是直接在命令列打指令时就输入:# /usr/local/bin/mysql -u root -pmypwd
上面这种方法会让别的使用者使用 ps 指令就可以看到你在执行的指定及密码。因此绝对不要使用这种方法,请改用下列方式输入:# /usr/local/myqsl/bin/mysql -u root -p
接着会要求你输入密码时再输入即可。
另一个方式是在你的家目录下建立一个存放密码的档案,文件名为 .my.cnf,当 mysql 需要使用密码时会自动去读取。该档的内容如下:
[client]
password=your_passowrd
接着要把 .my.cnf 的权限改成只有档案拥有者才可以读写:# chmod 600 ~/.my.cnf
19.4.2 备份数据库
数据库的数据要定时备份,这样才不会在失手时或系统有问题时产生困扰。在 MySQL 中提供一个备份程序 mysqldump。
假设我们有一个数据库名为 WWW,我们可以使用下列指令来备份整个数据库:# /usr/local/bin/mysqldump -u root -p WWW > [url]www.sql[/url]
这样就可以把数据库的数据存在 [url]www.sql[/url] 这个档案中了。日后要回复时只要使用下列指定就可以把资料存回:# /usr/local/bin/mysql -u root -p WWW
我们要注意的是备份出来的档案应该要放在不同的计算机中,而且要注意权限的控制。由于该文件是文字文件,任何人都可以读,所以要特别注意。
我们可以利用 crontab 这个指令来定时备份数据库。我们先建立一个 shell script 档,名为 backupsql.sh,内容如下:
/usr/local/bin/mysqldump -uroot WWW>/home/www.sql
chmod 600 /home/www.sql
接着将该档权限改成只有拥有人可以读、写、执行,其它人都不行:# chmod 700 backupsql.sh
为了要让执行 backupsql.sh 时可以不必输入密码,我们必须先将密码存在 ~/.my.cnf ,请先建立 ~/.my.cnf 档案内容如下:
[client]
password=your_passowrd
接着要把 .my.cnf 的权限改成只有档案拥有者才可以读写:# chmod 600 ~/.my.cnf
接着要让它能定时执行,命令列打 crontab -e 来进入文字编辑,加入下列内容:
#每天 3:05 备份网页数据库
5        3        *        *        *        /root/backupsql.sh
19.4.3 使用者管理
如果您要新增可以联机到 MySQL 的使用者,可以在 MySQL 交互式接口串使用 GRANT 指令来新增使用者。GRANT 在设定使用者权限时,如果使用者存在则更新其权限,如果不存在则新增该使用者。
用法:GRANT 权限 ON 数据库(或表) TO user@host IDENTIFIED BY '密码';
范例一:
新增一个本机的使用者 admin,并开放所有权限,密码为 mypwd:
mysql> GRANT ALL PRIVILEGES ON *.* TO admin@localhost IDENTIFIED BY 'mypwd';
Query OK, 0 row affected (0.00 sec)
范例二:
新增一个来自 [url]www.mydomain.com[/url] 的使用者 www,并设定只能对 www 数据库中所有数据表执行 SELECT, INSERT, UPDATE, DROP, CREATE, DELETE, INDEX,密码为 mypwd:
mysql> GRANT SELECT, INSERT, UPDATE, DROP, CREATE, DELETE,
INDEX ON www.* TO www@[url]www.mydomain.com[/url] IDENTIFIED BY 'mypwd';
Query OK, 0 row affected (0.00 sec)
如果要删除使用者上述新增的使用者 www,可以使用下列指令:
mysql> DELETE FROM user WHERE user='www' and host='www.mydomain.com';
Query OK, 1 rows affected (0.01 sec)
在新增或删除使用者后,离开 MySQL 之前都必须指行下列指令来让它生效:
mysql> FLUSH PRIVILEGES;
Query OK, 0 rows affected (0.01 sec)
19.4.4 如何更改使用者密码
我们可以使用下列指令来更改自己的密码:# /usr/local/bin/mysqladmin -u root -p password newpwd
上面指令中的使用者是 localhost 的 root ,新的密码是 newpwd。在输入指令后,会先询问你旧的密码。
我们也可以使用具有管理使用者权限的 mysql 使用者登入 MySQL 后,使用 UPDATE 指令来更改密码:# /usr/local/bin/mysql -u root -p mysql
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 202 to server version: 4.1.13
Type 'help;' or '\h' for help. Type '\c' to clear the buffer.
mysql> UPDATE user set password=password('新密码')
where user='使用者' and host='主机';
19.5 MySQL 图形化管理工具介绍
MySQL 有许多图形化的管理工具,我们在此介绍二个官方的工具「MySQL Administrator」及「MySQL Query Browser」。MySQL Administrator 是用来管理 MySQL Server 用的,您可以查看目前系统状态、新增使用者等。而 MySQL Query Browser 可以用来查看数据库内容。
我们可以在一台 Windows 的机器上使用图形化的管理工具,或者是在本机的 XWindow 中执行也可以。如果要从另一台计算机联机到 MySQL,则在使用这些工具连到 MySQL 之前,您必须先新增具有权限从远方联机到 MySQL 的使用者。假设我们要新增一个使用者 root,它可以从 192.168.0.2 这台机器联机到 MySQL,而密码为 mypasswd,则可以使用下列指令:
mysql> GRANT ALL on *.* to root@192.168.0.2 IDENTIFIED BY 'mypasswd';
Query OK, 1 rows affected (0.01 sec)
mysql> FLUSH PRIVILEGES;
Query OK, 0 rows affected (0.01 sec)
19.5.1 MySQL Administrator
请先到 MySQL 网站下载 MySQL Administrator,并执行安装,安装后请执行 MySQL Administrator。执行后,您会看到下列画面:
图 19-1
[img]http://homepage.cqwu.net/wxfy/images/ch19_01.png[/img]
请在 Server Host 字段中输入 MySQL Server 的 IP,并输入使用者名称及密码。登入后的第一页,您可以看到目前 MySQL 的状态。如果您的 Server 和 MySQL Administrator 是在同一台机器上,则可以对 MySQL 进行更多的控制,例如停用 MySQL 等。
MySQL Administrator 的管理界面使用上很容易,您可以自已点点看有什么功能,这里我们只介绍如何使用它来新增使用者。首先,请在右边选单中选取「User Administration」,接着在下图标示 2 的地方按鼠标右键,然后选择「Add new User」。
图 19-2
[img]http://homepage.cqwu.net/wxfy/images/ch19_02.png[/img]
然后您就可以在 MySQL User 字段中输入使用者名称,并输入密码。输入完后请按「Apply changes」以套用设定。
接下来我们可以再进一步设定使用者 john 设定权限。假设我们希望设使用者 john 只可以对数据库 www 进行 SELECT、INSERT、UPDATE、及 DELETE 的指令,则可以点选「Schema Privileges」标签,并选取好权限后,按下图 3 的按钮以新增权限。最后请点选「Apply changes」以套用设定。
图 19-3
[img]http://homepage.cqwu.net/wxfy/images/ch19_03.png[/img]
最后,我们要设定使用者可以从什么地方联机到 MySQL Server,请对着该使用者按右键,并选择「Add Host From Which The User Can Connect」,接着输入 IP 即可。
图 19-4
[img]http://homepage.cqwu.net/wxfy/images/ch19_04.png[/img]
如果您要删除使用者,只要对着使用者按右键,并选取「Delete User」即可。
19.5.2 MySQL Query Browser
MySQL Query Browser 一样可以从 MySQL 官方网站下载。下载并安装后,就可以执行 MySQL Query Browser 了。执行 Query Browser 后,会出现一个要求登入的窗口,同样的,您必须输入账号、密码及所要联机的主机。
如果您已经安装了 MySQL Administrator,您可以直接从 MySQL Administrator 中执行 Query Browser,而且不必再输入账号密码:
图 19-5
[img]http://homepage.cqwu.net/wxfy/images/ch19_05.png[/img]
在 MySQL Query Browser 中,我们可以建立删除数据库、数据表、查询数据库中的数据。如果您要建立一个新的数据库,请对着下图中 1 的位置按鼠标右键,再点选「Create New Schema」,最后输入数据库名称即可。
图 19-6
[img]http://homepage.cqwu.net/wxfy/images/ch19_06.png[/img]
建立了数据库后,我们可以再建资料表。请对着我们刚建立的数据库按鼠标右键,再点选「Create New Table」即出现下列窗口:
图 19-7
[img]http://homepage.cqwu.net/wxfy/images/ch19_07.png[/img]
请在「Table Name」中输入表格名称,并在上图 2 的部份输入每一个字段的类别,最后按「Apply Changes」即可。建立数据库后,您就可以在 Query Browser 中输入、检视数据库中的数据。只要对着刚才建立的表格点二下,并点选「Execute」即可查看数据库中的数据。如果您要新增一笔数据,请点选下图中 3 的位置,并选择「Edit」即可进行编辑。
图 19-8
[img]http://homepage.cqwu.net/wxfy/images/ch19_08.png[/img]
MySQL 图形化接口的使用相当直觉,您只要多试几次就可以明白各种使用方法了。
[img]http://homepage.cqwu.net/wxfy/images/note.png[/img]
小提示
如果您想要使用网页接口的 MySQL 管理工具,您可以到
[url=http://www.phpmyadmin.net/]http://www.phpmyadmin.net/[/url]
下载 phpMyAdmin。phpMyAdmin 的设定十分简单,您可以在网络上搜寻到很多相关文件。
19.6 PostgreSQL 安装设定
另一个好用的数据库为 PostgreSQL,这是笔者偏好的数据库,比起 MySQL,它的设定更简单、功能更强大。
我们同样使用 port 来安装 PosgreSQL:# cd /usr/ports/databases/postgresql80-server
# make install clean
执行了 make install 之后,会出现一个进阶设定的窗口,我们使用预设的设定即可。接着,您将看到一个提示讯息,要求你先行备份原本的数据库。如果您是第一次安装 PostgreSQL,可以直接略过。
安装完成后,我们就可以开始做数据库的初始化了。我们使用下列指令来初始化数据库:# su -l pgsql -c initdb
这个指令的意思是以使用者 pgsql 的身份执行 initdb。PostgreSQL 安装时会自动建立一个使用者及群组 pgsql,这是 PostgreSQL 预设最高使用者的账号,您可以使用 vipw 来修改该使用者的数据。由于 pgsql 预设使用的 shell 是 sh,笔者习惯使用 tcsh,所以我将该使用者的数据修改如下:
pgsql:*:70:70::0:0:PostgreSQL Daemon:/usr/local/pgsql:/bin/tcsh
初始化数据库后还有一些后续的设定。一开始 PostgreSQL 只允许让 pgsql 这个使用者经由本机联机存取数据库,如果您希望其它使用者可以经由其它机器联机,您必须先修改 ~pgsql/data/postgresql.conf 这个档案。找出 listen_addresses  的部份,并修改如下:
listen_addresses = '*'
listen_addresses 是表示您所要允许联机的 IP 地址,我们填入 * 表示允许任何联机。如果您安装的 PostgreSQL 是 7.x 的版本,您要修改的是这下列一行:
tcpip_socket = true
postgresql.conf 这个档案记录着 PostgreSQL 的其本设定,其中使用 "#" 为首的是批注。其内容包括可以设定所要使用的连接埠、最大联机数量等,不过我们通常没有必要修改它。
接着我们要设定从别的机器联机所使用的认证方式,请编辑 ~pgsql/data/pg_hba.conf,在文件最下方加入下列设定:
# "local" is for Unix domain socket connections only
local   all         all                               trust
host    all         all         127.0.0.1/32          trust
host    all         all         ::1/128               trust
host    all         all         192.168.0.1   255.255.255.0     md5
这里的设定除了第一行是批注外,第二、三、四行表示信任来自本机的联机,只要使用者存在于数据库中就不需要密码,这三行预设就存在于 pg_hba.conf 中。最后一行表示网域 192.168.0.1~192.168.0.255 的联机都要使用 md5 验证密码。
如果您希望在开机时就启动 PostgreSQL,请修改 /etc/rc.conf 并加入下列这一行:
postgresql_enable="YES"
在我们新增其它使用者之前,必须先启动 PostgreSQL ,以下为启动数据库服务的指令:# /usr/local/etc/rc.d/010.pgsql.sh start
如果您没有在 rc.conf 中加入启动 PostgreSQL 的设定,则上述指令并不会启动 PostgreSQL。
因为 010.pgsql.sh 这支 script 放在 /usr/local/etc/rc.d ,所以在一开机时,系统就会自动执行它来启动 PostgreSQL,如果您要停止 PostgreSQL,只要执行下列指令:# /usr/local/etc/rc.d/010.pgsql.sh stop
接着我们就可以增加一个可以使用远程联机的使用者:# su -l pgsql
% createuser -P
Enter name of user to add: alex
Enter password for user "alex":
Enter it again:
Shall the new user be allowed to create databases? (y/n) y
Shall the new user be allowed to create more new users? (y/n) y
CREATE USER
如此一来我们就可以使用 alex 这个使用者从远程登入了。
19.7 PostgreSQL 管理指令
PostgreSQL 和 MySQL 在指令的应用上有所不同,它将许多管理数据库的指令独立成一个个的执行文件,其中有些指令是使用 psql 为基础所写成的 scripts。例如新增、删除数据库或使用者等指令,都可以直接在命令列执行。以下为常用的指令列表:
[b]指令[/b]
[b]用途[/b]
createdb
建立一个新的数据库。
dropdb
删除数据库。
createuser
建立数据库使用者。
dropuser
删除数据库使用者。
pg_dump
备份一个数据库。
pg_dumpall
备份所有数据库。
psql
交互式的 SQL 指令工具。
19.7.1 建立及删除使用者
因为 PostgreSQL 安装完毕时只有一个使用者 pgsql,如果您要使用其它使用者登入,您必须先以 pgsql 这个使用者来新增其它使用者账号。首先,我们先将身份切换成 pgsql:# su -l pgsql
我们使用 su 加上参数 -l 表示模拟使用者真正 login 的情形,也就是会将工作目录切换到 /usr/local/pgsql,并加载该目录中的 .cshrc 等档案。接着我们就可以使用下列指令来建立一个新的使用者了,假设我们要为 root 建立一个账号:% createuser root
Shall the new user be allowed to create databases? (y/n) y
Shall the new user be allowed to create more new users? (y/n) y
CREATE USER
如此一来,root 也具有存取数据库的权限了。但因为 PostgreSQL 内定没有密码的使用者不可以使用远程登入,如果您希望所新增的使用者可以使用远程登入,您必须在 createuser 指令加上参数 -P 以输入密码,请注意 P 是大写喔。如果你要从数据库中删除一个使用者账号,只要使用 dropuser 这个指令即可:% dropuser root
值得注意的是,您无法使用删除你正在使用中的账号,例如以 root 身份来删除 root 是不被允许的。
如果您要修改某个使用者的密码,可以使用下列指令:# su -l pgsql
% psql template1
Welcome to psql 8.0.3, the PostgreSQL interactive terminal.
Type: \copyright for distribution terms
\h for help with SQL commands
\? for help on internal slash commands
\g or terminate with semicolon to execute query
\q to quit
template1=# ALTER USER pgsql WITH PASSWORD 'mypass';
ALTER USER
template1=# quit
我们先切换身份为 psql 以确保具有权限修改使用者密码,接着我们使用 psql 进入预设的数据库,并使用 ALTER USER 来修改使用者 pgsql 的密码,将密码设为 mypass。最后使用 quit 离开数据库。
19.7.2 建立及删除数据库
在使用数据库之前,我们必须先建立一个数据库。假设我们要建立的数据库名称为 MYDB,您可以使用下列指令加以建立:% createdb MYDB
在 UNIX 的世界中,大小写是有分别的,在 PostgreSQL 中也是一样。因此,不论是在建立数据库,数据表或其字段时,都要注意大小写。建议您除了数据库名称外,最好全部使用小写。
同样的,如果你要删除一个数据库,只要使用 dropdb 这个指令:% dropdb MYDB
19.7.3 交互式 SQL 指令
PostgreSQL 的 client 端指令中,功能最强大的莫过于 psql 这个指令了。psql 可以除了让我们进入交互式的 SQL statement 环境外,也可以加上一些参数变成一个直接响应的指令。例如,我们想要查看目前有哪些数据库:% psql -l
List of databases
Name | Owner | Encoding
-----------+-------+-----------
MYDB | root | SQL_ASCII
template0 | pgsql | SQL_ASCII
template1 | pgsql | SQL_ASCII
(3 rows)
加上 -l 这个参数后,就可以列出所有数据库名称了。除了您所建立的数据库外,还有二个 templateX 的数据库,该数据库存放着 PostgreSQL 的设定,不可以删除。接下来让我们选定一个数据库以进入交互式的窗口:% psql MYDB
Welcome to psql, the PostgreSQL interactive terminal.
Type:        \copyright for distribution terms
        \h for help with SQL commands
        \? for help on internal slash commands
        \g or terminate with semicolon to execute query
        \q to quit
MYDB=#
在这里,我们可以使用 19.3 所列出的一些标准的 SQL statement 来存取数据库,例如 create、drop、delete、update、insert、alter 等。建议您进一步至 PostgreSQL 网站参考其使用手册,PostgreSQL 官方网站是
[url=http://www.postgresql.org/]http://www.postgresql.org[/url]
。您也可以在下列网址中找到中文的使用手册:
[url=http://www.freebsd.org.hk/html/pgsqldoc-7.0c/postgres.htm]http://www.freebsd.org.hk/html/pgsqldoc-7.0c/postgres.htm[/url]

在交互式的接口中,您可以使用 \h 及 \? 来查询可以使用的指令。其中 \h 为查询 SQL statement ,而 \? 则是常询 PostgreSQL 特有的反斜线指令,我们最常用的反斜线指令有 \q 离开交互式接口,及 \d 列出该数据库的所有数据表。
如果您觉得这种命令列的接口不好使用,我们在下一节将会介绍如何在 MS Windows 使用图形化接口的管理工具。
19.7.4 数据库备份及回复
定期备份数据库是十分重要的一件事,我们一定要养成备份的习惯。在 PostgreSQL 中,备份十分容易,假设我们要备份的数据库是 MYDB,您可以使用下列指令:% pg_dump MYDB > MYDB.sql
如此一来,你就可以把 MYDB 这个数据库 dump 出来了。然而,数据库的数据往往十分庞大,动辄数十 MB 至数百 MB,为了节省空间,您可以在备份时顺便压缩数据库。以上述指令而言,我们只要将输出导向到 gzip 即可进行同步压缩:% pg_dump MYDB | gzip > MYDB.sql.gz
我们一般从数据库 dump 出来的数据都是文字文件,所以使用 gzip压缩可以得到很高的压缩比。假设不压缩所备份出来的档案有五十 MB,使用 gzip压缩后大约只剩六百多 KB。因此,我习惯都会加上 gzip压缩。
pg_dump 这个指令只能用来备份单一的数据库,如果您要将所有的数据库中都备份起来,您可以使用 pg_dumpall 来备份:% pg_dumpall |gzip > ALLDB.sql.gz
有了备份,自然也要回存。由于我们使用 pg_dump 所备份出来的数据库实际上是将一堆数据以 SQL statement 的方式存起来,如果您将该备份的档案以文书编辑器打开,您可以看到它其实是先存放数据库中所有数据表的信息,再将存放数据。所以我们只要将这些指令导向到 psql 来执行即可。首先,请先建立要回存的数据库名称,假设我们要将 MYDB 所备份出来的数据存放在 NEWDB 这个数据库中,我们要先建立一个名为 NEWDB 的数据库:% createdb NEWDB
接着再使用下列指令来将数据回存:% cat MYDB.sql | psql NEWDB
如果您备份出来的数据有经过压缩,则需改以下列指令回存:% gunzip -c MYDB.sql.gz | psql NEWDB
或是% cat MYDB.sql.gz | gunzip | psql NEWDB
如果您要回存的档案是经由 pg_dumpall 所备份出来的数据,则必须使用 pgsql 这个使用者来执行下列指令:% gunzip -c ALLDB.sql.gz | psql -e template1
19.8 PostgreSQL 图形化管理工具介绍
许多人可能不太习惯使用命令列来管理数据库,还好 PostgreSQL 提供了许多图形接口的管理工具。您可以在 MS Windows 执行的 pgAdmin。由于这些图形接口操作上比较容易,只要您多试几次,就可以熟悉它们的使用,因此,我们不会深入介绍每个功能的用法。
对于初学者而言,使用 pgAdmin 会比在命令列中输入来得容易。您可以自
[url=http://www.pgadmin.org/]http://www.pgadmin.org/[/url]
下载最新版本的 pgAdmin。
安装完成后,我们打开 pgAdmin,按了左上角的图示后即出现联机设定的窗体。请输入您数据库服务器的位置及账号密码,如图 19-9 所示:
图 19-9
[img]http://homepage.cqwu.net/wxfy/images/ch19_09.png[/img]
请注意,您必须先将 PostgreSQL 的 TCP/IP 联机打开,而且在 pg_hba.conf 中必须允许使用 pgAdmin 的这台主机登入。您可以参考 19.6 中的说明来设定 pg_hba.conf。输入联机数据后,即可开始使用。以建立一个新的数据库为例,我们先在左边的窗口中,对着数据库按右键,再选取 [新物件]->[新建数据库] 如图 19-10 所示:
图 19-10
[img]http://homepage.cqwu.net/wxfy/images/ch19_10.png[/img]
接着我们可以输入数据库名称、编码方式等,如图 19-11:
图 19-11
[img]http://homepage.cqwu.net/wxfy/images/ch19_11.png[/img]
我们输入了数据库名称为 test,并指定使用 UNICODE 的编码方式。接下来您可以看到在管理窗口中多了一个数据库「test」,我们可以在此数据库中再建立数据表。请先点选数据库「test」,再选择「模式」->「public」->「数据表」,并对着数据表按右键选择「新建数据表」。
图 19-12
[img]http://homepage.cqwu.net/wxfy/images/ch19_12.png[/img]
接下来,您就可以输入资料表名称,再选取「资料行」以设定本数据表的字段数据。
图 19-13
[img]http://homepage.cqwu.net/wxfy/images/ch19_13.png[/img]
在 pgAdmin 的主画面中,最上方有几个功能键,可以让我们手动输入 SQL 指令或是查看数据表内容,建议您可以每一个功能都试试看,以熟悉 pgAdmin 的使用接口。基本上 pgAdmin 十分容易上手,而且也功能十分齐全。
[img]http://homepage.cqwu.net/wxfy/images/note.png[/img]
小提示
如果您想要使用网页接口的 PostgreSQL 管理工具,您可以到
[url=http://phppgadmin.sourceforge.net/]http://phppgadmin.sourceforge.net/[/url]
下载 phpPgAdmin。phpPgAdmin 的设定和 phpMyAdmin 一样十分容易,只要您已经安装好网页服务器,就可以使用 phpPgAdmin。

逍遥 发表于 2006-6-5 15:26

第十九章 数据库系统
现在许多的商业应用、网页程序都必须使用数据库来存放数据。例如,网站上的留言版、讨论区、购物网站等,全部都是使用数据库来存放重要的数据。本章中,我们将介绍二种常见的数据库:MySQL 及 PostgreSQL。
本章包含了数据库的安装、设定、语法、及各种操作方式的介绍,读完本章后,您将可以了解下列主题:
如何安装、设定 MySQL。
如何安装、设定 PostgreSQL。
如何使用 MySQL 的图形化管理工具。
如何使用 PostgreSQL 的图形化管理工具。
基本的数据库语法介绍。
如何备份、回存数据库。
这些信息将有助您建立一个功能强大的网站,并对于日后安装数据库相关应用时更加得心应手。
19.1 概论
电子商务的兴起让数据库的应用更受到大家的瞩目。在信息科学的应用上,数据库可以说是最历久弥坚的领域。近来,数据产生和数据收集方面的技术有非常快速的进展。许多商业产品广泛使用了条形码、许多企业和政府的交易皆已计算机化,这使得计算机成为数据收集的主要工具。同时,数以百万计的数据库正被使用在企业管理、政府管理、科学和工程的数据管理和许多其它的应用上。
我们可以安装一套数据库系统,并经由一个接口自行开发程序来使用它。数据库的好处有很多,相信对数据库稍有涉入的人都知道,例如数据存取快速、不重复、权限控制、数据独立性等等。以写一个简单的留言版程序而言,传统上使用档案做为留言的记录,若要删除一笔数据,必须对整个档案一行一行的比对;但数据库只需指定该留言的编号即可。不过,如果把数据库系统局限于留言版也太大才小用了。
我们将介绍在 FreeBSD 上使用数据库,因为目前网页数据库使用情形十分风行,尤其在网页开发上使用 MySQL 或 PostgreSQL 数据库加 PHP 更是绝配。目前 Open Source 的数据库中,最常用、最有名的就是 PostgreSQL 及 MySQL,因此,本章将先介绍这二个数据库系统的安装及使用。
至于 PostgreSQL 及 MySQL 这二个数据库系统有什么差别?到底应该选哪一个呢?在 MySQL 3.x 以前,如果您问我这个问题,我一定说 PostgreSQL,因为 MySQL 3.x 不支援 transaction。所谓的 transaction 就是将一连串的 SQL 指令做为一个执行单位,当其中一个指令失败,在同一个 transaction 所执行过的命令都取消。Transaction 对于程序开发的应用十分重要,例如,当我们要新增处理一笔订单时,我们会先将订单输入数据库中,再将金额输入应收帐款中。如果我们在新增应收帐款时出现错误,而订单却已输入数据库,是不正确的做法。有了支援 transaction 的数据库,我们可以将订单的输入和应收帐款的输入做为一个执行单位,如果其中一个执行失败,则数据库会自动取消先前先做的动作,如此一来便可以确保数据的正确性。由于 transaction 十分重要,因此在做为商业上的应用时,我会选择 PostgreSQL。
不过 MySQL 4.x 后已经加入 transaction 的支持,只是功能还是没有 PostgreSQL 那么完整。那么除此之外,这二个数据库的差别是什么?PostgreSQL 是一个功能强大的数据库系统,它的威力不下于商业用的数据库。而 MySQL 的特性是对于简单 SQL 指令处理快速,大部份的日常简单操作,MySQL 的速度会比 PostgreSQL 快一点。以下我们列出它们在功能上的主要差异:
[b]功能[/b]
[b]MySQL 3.x[/b]
[b]MySQL 4.1.x[/b]
[b]PostgreSQL[/b]
版权宣告
GPL
GPL
BSD
Sub-Selects
No
Yes
Yes
Views
No
No
Yes
Foreign Key relationships
No
Yes
Yes
Foreign Key constraints
No
No
Yes
Triggers
No
No
Yes
Indexing on non trivial types
No
No
Yes
Sequences
Some
Some
Yes
Transactions
No
Yes
Yes
OO (Inheritance of tables)
No
No
Yes
Async Notifications
No
No
Yes
Constraints
No
No
Yes
SELECT INTO
No
Yes
Yes
Stored Procedures
No
No
Yes
Row level locking
Yes
Yes
Yes
Table level locking
Yes
Yes
Yes
Multi version Concurrency Control
No
No
Yes
我们可以看到 PostgreSQL 功能真的强大很多,如果您必须设计功能强大又复杂的系统,PostgreSQL 是不二之选。而 MySQL 4.x 以后的重要功能都很齐全,速度也很快,比较适合简单的网页应用,所以目前大部份网页应用软件使用 MySQL 比较多。不过呢,笔者认为 PostgreSQL 及 MySQL 都使用 Transaction 时,二者的效能表现差不多,就网页应用而言,我的首选还是 PostgreSQL。
19.2 安装 MySQL
MySQL 和 FreeBSD 一样也有多种版本同时开发,例如 3.x、4.0.x、4.1.x、5.x 等,其中 4.1.x 是目前较稳定的版本。
您可以自行到
[url=http://www.mysql.com/]http://www.mysql.com[/url]
取得最新版的 MySQL Source Package 来安装,不过安装上比较麻烦。所以我们使用 ports 来安装 MySQL:# cd /usr/ports/databases/mysql41-server
# make WITH_CHARSET=big5 WITH_XCHARSET=all install clean
我们指定 MySQL 预设的字集为 Big5,并另外支持所有的字集。接下来请修改 /etc/rc.conf 并加入下列这一行,以让开机时启动 MySQL:
mysql_enable="yes"
接着您就可以使用下列指令启动 MySQL 了:# /usr/local/etc/rc.d/mysql-server.sh start
启动 MySQL 后,我们就可以使用下列指令进入 MySQL 交互式命令列了:# /usr/local/bin/mysql mysql
若安装成功,你将看到以下画面:
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 14 to server version: 4.1.13
Type 'help;' or '\h' for help. Type '\c' to clear the buffer.
mysql>
MySQL 刚安装完成时,并未设定 root 的密码,因此我们接着要设定 root 的密码并实时更新设定:
mysql> UPDATE user SET password=password('你的密码') where user='root';
Query OK, 0 rows affected (0.00 sec)
Rows matched: 2  Changed: 0  Warnings: 0
mysql> FLUSH PRIVILEGES;
Query OK, 0 rows affected (0.02 sec)
以上指令及 MySQL 更详细的设定说明,我们会在下一小节中加以说明。最后请以 exit; 来离开 MySQL。
如果您有其它使用者要加入也可以加入,最好不要让使有人都有对所有数据库有全部的权限。使用命令列的方式新增使用者有点麻烦,我们等一下再使用其它图形化接口进入新增使用者。
建议您以后使用 MySQL 的图形化接口管理工具「MySQL Administrator」及「MySQL Query Browser」来管理 MySQL,我们会再后续章节中说明如何使用这些管理工具。
19.3 SQL 语法介绍
在使用数据库之前,我们必须先了解一些简单而基本的数据库理论。如果您对于数据库 SQL 语法已经很熟悉了,您可以跳过这一个小节。
基本上数据库的结构有下列几个特点:
一个数据库系统中可以有多个独立数据库。
数据库是由许多数据表 (table) 所组成。
数据表中包含许多记录 (record)。
每一笔记录中的字段数目都一样。
每一个字段储存一种分类过的数据。
例如我们有一个数据库名称是NCU,其中有多个数据表,其中一个资料表名为 student 内容如下:
STUDENT_ID
LAST_NAME
FIRST_NAME
DEPARTMENT
1
Chang
Jack
MIS
2
Wang
Alex
BA
在数据表中有许多字段 (column),每个字段都有一个名称,也就是第一列 (row) 中的 STUDENT_ID、LAST_NAME、FIRST_NAME、DEPARTMENT。接着我们将数据存入,每一笔记录我们都可以看成一列 (row),每一个记录都有一个「唯一的 ID (编号)」。唯一的 ID 十分重要,它是我们在存取数据库时的依据。在新增资料时,以 MySQL 而言,我们可以自行指定 ID 或是由系统自行取得。
另一个观念是关系型数据库。关系型数据库的意义就是每一个资料表间可以存在关系,例如我们在 NCU 的数据库中有另一个数据表名为 score,内容如下:
SCORE_ID
STUDENT_ID
CHINESE
ENGLISH
1
2
99
90
2
1
89
87
score 数据表中存放学生的成绩,我们不需在该数据表中存放学生的信息,只要在该数据表中存放一个字段名为 STUDENT_ID,经由这一个唯一的 ID 我们可以去 student 的数据表中找到学生的数据。
有了这些观念就足以让我们开发出许多数据库的程序了。
SQL (Structured Query Language) 语法十分简单,它是关系型数据库的标准语言,虽然在某些不同数据库系统上有些许的差异,但基本上都遵循一定的标准。
我们可以在命令列下进入 MySQL 来练习 SQL 的语法:# /usr/local/bin/mysql -u root -p
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 202 to server version: 4.1.13
Type 'help;' or '\h' for help. Type '\c' to clear the buffer.
mysql>
下完指令后会要求输入密码,请输入您之前设定的密码。登入后你就可以直接在出现的命令列 mysql> 之后输入 SQL 的语法了。
关于 MySQL 详细的语法,你可以参考 MySQL 中文参考手册,该文件可以在
[url=http://www.freebsd.org.hk/html/mysqldoc/]http://www.freebsd.org.hk/html/mysqldoc/[/url]
中找到。该文件中对于 MySQL 每个细节都有详细的描述,例如字段的名称限制、规则等,我们不会在这里提及。我们只介绍几个简单而常用的指令。 我们以建立一个学生数据表来说明这些语法。
CREATE
ALTER
DROP
INSERT
SELECT
UPDATE
DELETE
制成 script 档
19.3.1 CREATE
建立数据库:CREATE DATABASE db_name
建立数据表:CREATE TABLE tbl_name [(create_definition,...)] [options]
我们先建立一个名为 NCU 的数据库:
mysql> CREATE DATABASE NCU;
请注意,每一个指令皆以 ";" 为结尾,如果没有 ";" 就算换行也是代表同一条指令的延续。
我们可以使用下列指令 show 来列出系统中已存在的数据库有哪些:
mysql> show databases;
+-----------+
| Database  |
+-----------+
| mysql     |
| test      |
| NCU       |
+-----------+
3 rows in set (0.01 sec)
接着用 USE 这个指令来使用 NCU 数据库:
mysql> USE NCU;
接着建立一个放置学生数据的数据表,名为 STUDENT,内容为编号(STUDENT_ID)、姓名 (NAME)、科系 (DEPARTMENT):
mysql> CREATE TABLE STUDENT (
STUDENT_ID int(10) DEFAULT '0' NOT NULL AUTO_INCREMENT,
NAME varchar(50),
DEPARTMENT varchar(10),
PRIMARY KEY (STUDENT_ID) );
在上面的指令中,我们定义学生编号为十位数的整数(int),内定值是 0,不可以是空的 (NOT NULL),数字自动增加 (AUTO_INCREMENT)。姓名是最长为五十个字节的字符串(VARCHAR),科系为最长十个字节的字符串。最后定义主要的 id 是 STUDENT_ID,也就是该数据表中的唯一 ID。
我们可以看到在建立数据表时,我们会顺便划分各个字段所要储存的数据长度及其格式,常用的字段格式请参考 MySQL 中文参考手册。
如果要看现在使用的数据库中有哪些数据表,一样可以使用指令 show 来查看:
mysql> show tables;
+--------------------+
| Tables_in_NCU      |
+--------------------+
| STUDENT            |
+--------------------+
4 rows in set (0.00 sec)
19.3.2 ALTER
建立了数据表后,如果发现数据表的字段不符需求,我们不必将数据表删除重建,可以使用 ALTER 指令来修改数据表的格式。另如我们要新增一个姓别字段,内容只可以是 "男" 或 "女",我们可以使用下面的指令:
mysql> ALTER TABLE STUDENT
ADD SEX ENUM('男','女') DEFAULT '女';
我们增加了一个字段 SEX,使用 ENUM 的格式,指定内容只能为 "男" 或 "女",且默认值是 "女"。
如果我们要将 SEX 字段改名为 DISTINCTION,并将格式改为 VARCHAR:
mysql> ALTER TABLE STUDENT
CHANGE SEX DISTINCTION VARCHAR(4);
如果我们只是要将 SEX 字段格式改为 VARCHAR,但不更改名称,只要将上面的指令中 DISTINCTION 改成 SEX 即可。
如果我们要删除整个 DISTINCTION 字段及该字段的数据:
mysql> ALTER TABLE STUDENT DROP DISTINCTION;
19.3.3 DROP
删除数据库:DROP DATABASE db_name
删除数据表:DROP TABLE table_bame
我们可以使用 DROP 指令来删除不要的资料。例如我们要删除 STUDENT 这一个资料表的话,可以使用下列指令:
mysql> DROP TABLE STUDENT;
19.3.4 INSERT
使用 INSERT 指令可以让我们一笔一笔增加数据。
STUDENT_ID
NAME
DEPARTMENT
1
Jack
MIS
假设我们的数据表中的字段如上表,我们要新增一笔数据,姓名是 JACK、部门是 MIS:
mysql> INSERT INTO STUDENT (NAME, DEPARTMENT)
VALUES ('JACK', 'MIS');
由于我们在指定 STUDENT_ID 的格式时,加了参数 AUTO_INCREMENT,所以我们不需指定值,mysql 会自动帮我们依序指定。
19.3.5 SELECT
我们可以使用 SELECT 来看数据表中的数据,还可以依自己给定的条件来过滤数据。
假设我们要看 STUDENT 数据表中的所有数据的话,可以使用下列指令:
mysql> SELECT * FROM STUDENT;
假设我们只要看 NAME 及 DEPARTMENT 字段的话,我们可以使用下列指令:
mysql> SELECT NAME, DEPARTMENT FROM STUDENT;
假设我们只要看 NAME 字段,而且所属部门为 MIS 的人:
mysql> SELECT NAME FROM STUDENT
WHERE DEPARTMENT='MIS';
假设我们要看 MIS 部门中的人所有字段,而且输出结果时要依 STUDENT_ID 来排序:
mysql> SELECT * FROM STUDENT
WHERE DEPARTMENT='MIS'
ORDER BY STUDENT_ID DESC;
最后的 DESC 表示递减 (descending),由大到小排序。也可以使用 ASC 来表示递增 (ascending)。
除了这些之外,在 MySQL 中还有一些可以使用的函式,例如我们可以使用 count() 这个函式来计算出有多少笔记录:
mysql> SELECT count(*) FROM STUDENT WHERE DEPARTMENT='MIS';
+----------+
| count(*) |
+----------+
| 5        |
+----------+
1 row in set (0.00 sec)
上述结果表示部门为 MIS 的记录有五笔。
会了这些基本的 INSERT 指定就够我们做一般的应用了。
19.3.6 UPDATE
我们可以使用 UPDATE 指令来更新记录。例如我们要将所有记录的部门数据为 MIS 者都改成 CSIE,可以使用下列指令:
mysql> UPDATE STUDENT SET DEPARTMENT='CSIE'
WHERE DEPARTMENT='MIS';
19.3.7 DELETE
DELETE 指令可以让我们删除一笔或多笔数据。例如我们要删除 STUDENT 数据表中姓名为 JACK 的记录:
mysql> DELETE FROM STUDENT WHRE NAME='JACK';
如果我们要删除姓名为 JACK 且部门为 MIS 的数据:
mysql> DELETE FROM STUDENT
WHERE NAME='JACK' AND DEPARTMENT='MIS';
19.3.8 制成 script 档
我们可以将要执行的指定制成档案,以利管理。例如我们写了一个程序,需要先在数据库中建立一些数据,我们可以将对数据库的规划做成一个档案来管理。这样可以使用们要安装程序时更快速方便。
假设我们要建立一个数据库 NCU,该数据库中有一个数据表 STUDENT,数据表中要先建有以下记录:
STUDENT_ID
NAME
DEPARTMENT
1
Jack
MIS
2
Mary
CSIE
我们先建立一个文件名为 ncu.sql,内容如下:
CREATE DATABASE NCU;
USE NCU;
CREATE TABLE STUDENT (
STUDENT_ID int(10) DEFAULT '0' NOT NULL AUTO_INCREMENT,
NAME varchar(50),
DEPARTMENT varchar(10),
PRIMARY KEY (STUDENT_ID) );
INSERT INTO STUDENT (NAME, DEPARTMENT)
VALUES ('JACK', 'MIS');
INSERT INTO STUDENT (NAME, DEPARTMENT)
VALUES ('MARY', 'CSIE');
接着使用下列指令来快速建立数据库:# /usr/local/bin/mysql -u root -p
输入使用者 root 的密码后就完成建立了。
如果我们在数据库中早就有一个数据库名为 NCU,而我们要新增上述数据表及记录,我们只要将原本 ncu.sql 的内容最前面二行删除,改成下列内容:
CREATE TABLE STUDENT (
STUDENT_ID int(10) DEFAULT '0' NOT NULL AUTO_INCREMENT,
NAME varchar(50),
DEPARTMENT varchar(10),
PRIMARY KEY (STUDENT_ID) );
INSERT INTO STUDENT (NAME, DEPARTMENT)
VALUES ('JACK', 'MIS');
INSERT INTO STUDENT (NAME, DEPARTMENT)
VALUES ('MARY', 'CSIE');
之后再以下列指令来在 NCU 数据库中建立数据表:# /usr/local/bin/mysql -u root -p NCU
在网络上有许多 PHP 程序可以下载,下载后要安装数据库时,大多是以这种方式来使用。
19.4 MySQL 管理
19.4.1 维护密码安全
当我们要使用 MySQL 时,必须输入密码。输入密码的方式有很多种,第一种也是最不安全的一个方式是直接在命令列打指令时就输入:# /usr/local/bin/mysql -u root -pmypwd
上面这种方法会让别的使用者使用 ps 指令就可以看到你在执行的指定及密码。因此绝对不要使用这种方法,请改用下列方式输入:# /usr/local/myqsl/bin/mysql -u root -p
接着会要求你输入密码时再输入即可。
另一个方式是在你的家目录下建立一个存放密码的档案,文件名为 .my.cnf,当 mysql 需要使用密码时会自动去读取。该档的内容如下:
[client]
password=your_passowrd
接着要把 .my.cnf 的权限改成只有档案拥有者才可以读写:# chmod 600 ~/.my.cnf
19.4.2 备份数据库
数据库的数据要定时备份,这样才不会在失手时或系统有问题时产生困扰。在 MySQL 中提供一个备份程序 mysqldump。
假设我们有一个数据库名为 WWW,我们可以使用下列指令来备份整个数据库:# /usr/local/bin/mysqldump -u root -p WWW > [url]www.sql[/url]
这样就可以把数据库的数据存在 [url]www.sql[/url] 这个档案中了。日后要回复时只要使用下列指定就可以把资料存回:# /usr/local/bin/mysql -u root -p WWW
我们要注意的是备份出来的档案应该要放在不同的计算机中,而且要注意权限的控制。由于该文件是文字文件,任何人都可以读,所以要特别注意。
我们可以利用 crontab 这个指令来定时备份数据库。我们先建立一个 shell script 档,名为 backupsql.sh,内容如下:
/usr/local/bin/mysqldump -uroot WWW>/home/www.sql
chmod 600 /home/www.sql
接着将该档权限改成只有拥有人可以读、写、执行,其它人都不行:# chmod 700 backupsql.sh
为了要让执行 backupsql.sh 时可以不必输入密码,我们必须先将密码存在 ~/.my.cnf ,请先建立 ~/.my.cnf 档案内容如下:
[client]
password=your_passowrd
接着要把 .my.cnf 的权限改成只有档案拥有者才可以读写:# chmod 600 ~/.my.cnf
接着要让它能定时执行,命令列打 crontab -e 来进入文字编辑,加入下列内容:
#每天 3:05 备份网页数据库
5        3        *        *        *        /root/backupsql.sh
19.4.3 使用者管理
如果您要新增可以联机到 MySQL 的使用者,可以在 MySQL 交互式接口串使用 GRANT 指令来新增使用者。GRANT 在设定使用者权限时,如果使用者存在则更新其权限,如果不存在则新增该使用者。
用法:GRANT 权限 ON 数据库(或表) TO user@host IDENTIFIED BY '密码';
范例一:
新增一个本机的使用者 admin,并开放所有权限,密码为 mypwd:
mysql> GRANT ALL PRIVILEGES ON *.* TO admin@localhost IDENTIFIED BY 'mypwd';
Query OK, 0 row affected (0.00 sec)
范例二:
新增一个来自 [url]www.mydomain.com[/url] 的使用者 www,并设定只能对 www 数据库中所有数据表执行 SELECT, INSERT, UPDATE, DROP, CREATE, DELETE, INDEX,密码为 mypwd:
mysql> GRANT SELECT, INSERT, UPDATE, DROP, CREATE, DELETE,
INDEX ON www.* TO www@[url]www.mydomain.com[/url] IDENTIFIED BY 'mypwd';
Query OK, 0 row affected (0.00 sec)
如果要删除使用者上述新增的使用者 www,可以使用下列指令:
mysql> DELETE FROM user WHERE user='www' and host='www.mydomain.com';
Query OK, 1 rows affected (0.01 sec)
在新增或删除使用者后,离开 MySQL 之前都必须指行下列指令来让它生效:
mysql> FLUSH PRIVILEGES;
Query OK, 0 rows affected (0.01 sec)
19.4.4 如何更改使用者密码
我们可以使用下列指令来更改自己的密码:# /usr/local/bin/mysqladmin -u root -p password newpwd
上面指令中的使用者是 localhost 的 root ,新的密码是 newpwd。在输入指令后,会先询问你旧的密码。
我们也可以使用具有管理使用者权限的 mysql 使用者登入 MySQL 后,使用 UPDATE 指令来更改密码:# /usr/local/bin/mysql -u root -p mysql
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 202 to server version: 4.1.13
Type 'help;' or '\h' for help. Type '\c' to clear the buffer.
mysql> UPDATE user set password=password('新密码')
where user='使用者' and host='主机';
19.5 MySQL 图形化管理工具介绍
MySQL 有许多图形化的管理工具,我们在此介绍二个官方的工具「MySQL Administrator」及「MySQL Query Browser」。MySQL Administrator 是用来管理 MySQL Server 用的,您可以查看目前系统状态、新增使用者等。而 MySQL Query Browser 可以用来查看数据库内容。
我们可以在一台 Windows 的机器上使用图形化的管理工具,或者是在本机的 XWindow 中执行也可以。如果要从另一台计算机联机到 MySQL,则在使用这些工具连到 MySQL 之前,您必须先新增具有权限从远方联机到 MySQL 的使用者。假设我们要新增一个使用者 root,它可以从 192.168.0.2 这台机器联机到 MySQL,而密码为 mypasswd,则可以使用下列指令:
mysql> GRANT ALL on *.* to root@192.168.0.2 IDENTIFIED BY 'mypasswd';
Query OK, 1 rows affected (0.01 sec)
mysql> FLUSH PRIVILEGES;
Query OK, 0 rows affected (0.01 sec)
19.5.1 MySQL Administrator
请先到 MySQL 网站下载 MySQL Administrator,并执行安装,安装后请执行 MySQL Administrator。执行后,您会看到下列画面:
图 19-1
[img]http://homepage.cqwu.net/wxfy/images/ch19_01.png[/img]
请在 Server Host 字段中输入 MySQL Server 的 IP,并输入使用者名称及密码。登入后的第一页,您可以看到目前 MySQL 的状态。如果您的 Server 和 MySQL Administrator 是在同一台机器上,则可以对 MySQL 进行更多的控制,例如停用 MySQL 等。
MySQL Administrator 的管理界面使用上很容易,您可以自已点点看有什么功能,这里我们只介绍如何使用它来新增使用者。首先,请在右边选单中选取「User Administration」,接着在下图标示 2 的地方按鼠标右键,然后选择「Add new User」。
图 19-2
[img]http://homepage.cqwu.net/wxfy/images/ch19_02.png[/img]
然后您就可以在 MySQL User 字段中输入使用者名称,并输入密码。输入完后请按「Apply changes」以套用设定。
接下来我们可以再进一步设定使用者 john 设定权限。假设我们希望设使用者 john 只可以对数据库 www 进行 SELECT、INSERT、UPDATE、及 DELETE 的指令,则可以点选「Schema Privileges」标签,并选取好权限后,按下图 3 的按钮以新增权限。最后请点选「Apply changes」以套用设定。
图 19-3
[img]http://homepage.cqwu.net/wxfy/images/ch19_03.png[/img]
最后,我们要设定使用者可以从什么地方联机到 MySQL Server,请对着该使用者按右键,并选择「Add Host From Which The User Can Connect」,接着输入 IP 即可。
图 19-4
[img]http://homepage.cqwu.net/wxfy/images/ch19_04.png[/img]
如果您要删除使用者,只要对着使用者按右键,并选取「Delete User」即可。
19.5.2 MySQL Query Browser
MySQL Query Browser 一样可以从 MySQL 官方网站下载。下载并安装后,就可以执行 MySQL Query Browser 了。执行 Query Browser 后,会出现一个要求登入的窗口,同样的,您必须输入账号、密码及所要联机的主机。
如果您已经安装了 MySQL Administrator,您可以直接从 MySQL Administrator 中执行 Query Browser,而且不必再输入账号密码:
图 19-5
[img]http://homepage.cqwu.net/wxfy/images/ch19_05.png[/img]
在 MySQL Query Browser 中,我们可以建立删除数据库、数据表、查询数据库中的数据。如果您要建立一个新的数据库,请对着下图中 1 的位置按鼠标右键,再点选「Create New Schema」,最后输入数据库名称即可。
图 19-6
[img]http://homepage.cqwu.net/wxfy/images/ch19_06.png[/img]
建立了数据库后,我们可以再建资料表。请对着我们刚建立的数据库按鼠标右键,再点选「Create New Table」即出现下列窗口:
图 19-7
[img]http://homepage.cqwu.net/wxfy/images/ch19_07.png[/img]
请在「Table Name」中输入表格名称,并在上图 2 的部份输入每一个字段的类别,最后按「Apply Changes」即可。建立数据库后,您就可以在 Query Browser 中输入、检视数据库中的数据。只要对着刚才建立的表格点二下,并点选「Execute」即可查看数据库中的数据。如果您要新增一笔数据,请点选下图中 3 的位置,并选择「Edit」即可进行编辑。
图 19-8
[img]http://homepage.cqwu.net/wxfy/images/ch19_08.png[/img]
MySQL 图形化接口的使用相当直觉,您只要多试几次就可以明白各种使用方法了。
[img]http://homepage.cqwu.net/wxfy/images/note.png[/img]
小提示
如果您想要使用网页接口的 MySQL 管理工具,您可以到
[url=http://www.phpmyadmin.net/]http://www.phpmyadmin.net/[/url]
下载 phpMyAdmin。phpMyAdmin 的设定十分简单,您可以在网络上搜寻到很多相关文件。
19.6 PostgreSQL 安装设定
另一个好用的数据库为 PostgreSQL,这是笔者偏好的数据库,比起 MySQL,它的设定更简单、功能更强大。
我们同样使用 port 来安装 PosgreSQL:# cd /usr/ports/databases/postgresql80-server
# make install clean
执行了 make install 之后,会出现一个进阶设定的窗口,我们使用预设的设定即可。接着,您将看到一个提示讯息,要求你先行备份原本的数据库。如果您是第一次安装 PostgreSQL,可以直接略过。
安装完成后,我们就可以开始做数据库的初始化了。我们使用下列指令来初始化数据库:# su -l pgsql -c initdb
这个指令的意思是以使用者 pgsql 的身份执行 initdb。PostgreSQL 安装时会自动建立一个使用者及群组 pgsql,这是 PostgreSQL 预设最高使用者的账号,您可以使用 vipw 来修改该使用者的数据。由于 pgsql 预设使用的 shell 是 sh,笔者习惯使用 tcsh,所以我将该使用者的数据修改如下:
pgsql:*:70:70::0:0:PostgreSQL Daemon:/usr/local/pgsql:/bin/tcsh
初始化数据库后还有一些后续的设定。一开始 PostgreSQL 只允许让 pgsql 这个使用者经由本机联机存取数据库,如果您希望其它使用者可以经由其它机器联机,您必须先修改 ~pgsql/data/postgresql.conf 这个档案。找出 listen_addresses  的部份,并修改如下:
listen_addresses = '*'
listen_addresses 是表示您所要允许联机的 IP 地址,我们填入 * 表示允许任何联机。如果您安装的 PostgreSQL 是 7.x 的版本,您要修改的是这下列一行:
tcpip_socket = true
postgresql.conf 这个档案记录着 PostgreSQL 的其本设定,其中使用 "#" 为首的是批注。其内容包括可以设定所要使用的连接埠、最大联机数量等,不过我们通常没有必要修改它。
接着我们要设定从别的机器联机所使用的认证方式,请编辑 ~pgsql/data/pg_hba.conf,在文件最下方加入下列设定:
# "local" is for Unix domain socket connections only
local   all         all                               trust
host    all         all         127.0.0.1/32          trust
host    all         all         ::1/128               trust
host    all         all         192.168.0.1   255.255.255.0     md5
这里的设定除了第一行是批注外,第二、三、四行表示信任来自本机的联机,只要使用者存在于数据库中就不需要密码,这三行预设就存在于 pg_hba.conf 中。最后一行表示网域 192.168.0.1~192.168.0.255 的联机都要使用 md5 验证密码。
如果您希望在开机时就启动 PostgreSQL,请修改 /etc/rc.conf 并加入下列这一行:
postgresql_enable="YES"
在我们新增其它使用者之前,必须先启动 PostgreSQL ,以下为启动数据库服务的指令:# /usr/local/etc/rc.d/010.pgsql.sh start
如果您没有在 rc.conf 中加入启动 PostgreSQL 的设定,则上述指令并不会启动 PostgreSQL。
因为 010.pgsql.sh 这支 script 放在 /usr/local/etc/rc.d ,所以在一开机时,系统就会自动执行它来启动 PostgreSQL,如果您要停止 PostgreSQL,只要执行下列指令:# /usr/local/etc/rc.d/010.pgsql.sh stop
接着我们就可以增加一个可以使用远程联机的使用者:# su -l pgsql
% createuser -P
Enter name of user to add: alex
Enter password for user "alex":
Enter it again:
Shall the new user be allowed to create databases? (y/n) y
Shall the new user be allowed to create more new users? (y/n) y
CREATE USER
如此一来我们就可以使用 alex 这个使用者从远程登入了。
19.7 PostgreSQL 管理指令
PostgreSQL 和 MySQL 在指令的应用上有所不同,它将许多管理数据库的指令独立成一个个的执行文件,其中有些指令是使用 psql 为基础所写成的 scripts。例如新增、删除数据库或使用者等指令,都可以直接在命令列执行。以下为常用的指令列表:
[b]指令[/b]
[b]用途[/b]
createdb
建立一个新的数据库。
dropdb
删除数据库。
createuser
建立数据库使用者。
dropuser
删除数据库使用者。
pg_dump
备份一个数据库。
pg_dumpall
备份所有数据库。
psql
交互式的 SQL 指令工具。
19.7.1 建立及删除使用者
因为 PostgreSQL 安装完毕时只有一个使用者 pgsql,如果您要使用其它使用者登入,您必须先以 pgsql 这个使用者来新增其它使用者账号。首先,我们先将身份切换成 pgsql:# su -l pgsql
我们使用 su 加上参数 -l 表示模拟使用者真正 login 的情形,也就是会将工作目录切换到 /usr/local/pgsql,并加载该目录中的 .cshrc 等档案。接着我们就可以使用下列指令来建立一个新的使用者了,假设我们要为 root 建立一个账号:% createuser root
Shall the new user be allowed to create databases? (y/n) y
Shall the new user be allowed to create more new users? (y/n) y
CREATE USER
如此一来,root 也具有存取数据库的权限了。但因为 PostgreSQL 内定没有密码的使用者不可以使用远程登入,如果您希望所新增的使用者可以使用远程登入,您必须在 createuser 指令加上参数 -P 以输入密码,请注意 P 是大写喔。如果你要从数据库中删除一个使用者账号,只要使用 dropuser 这个指令即可:% dropuser root
值得注意的是,您无法使用删除你正在使用中的账号,例如以 root 身份来删除 root 是不被允许的。
如果您要修改某个使用者的密码,可以使用下列指令:# su -l pgsql
% psql template1
Welcome to psql 8.0.3, the PostgreSQL interactive terminal.
Type: \copyright for distribution terms
\h for help with SQL commands
\? for help on internal slash commands
\g or terminate with semicolon to execute query
\q to quit
template1=# ALTER USER pgsql WITH PASSWORD 'mypass';
ALTER USER
template1=# quit
我们先切换身份为 psql 以确保具有权限修改使用者密码,接着我们使用 psql 进入预设的数据库,并使用 ALTER USER 来修改使用者 pgsql 的密码,将密码设为 mypass。最后使用 quit 离开数据库。
19.7.2 建立及删除数据库
在使用数据库之前,我们必须先建立一个数据库。假设我们要建立的数据库名称为 MYDB,您可以使用下列指令加以建立:% createdb MYDB
在 UNIX 的世界中,大小写是有分别的,在 PostgreSQL 中也是一样。因此,不论是在建立数据库,数据表或其字段时,都要注意大小写。建议您除了数据库名称外,最好全部使用小写。
同样的,如果你要删除一个数据库,只要使用 dropdb 这个指令:% dropdb MYDB
19.7.3 交互式 SQL 指令
PostgreSQL 的 client 端指令中,功能最强大的莫过于 psql 这个指令了。psql 可以除了让我们进入交互式的 SQL statement 环境外,也可以加上一些参数变成一个直接响应的指令。例如,我们想要查看目前有哪些数据库:% psql -l
List of databases
Name | Owner | Encoding
-----------+-------+-----------
MYDB | root | SQL_ASCII
template0 | pgsql | SQL_ASCII
template1 | pgsql | SQL_ASCII
(3 rows)
加上 -l 这个参数后,就可以列出所有数据库名称了。除了您所建立的数据库外,还有二个 templateX 的数据库,该数据库存放着 PostgreSQL 的设定,不可以删除。接下来让我们选定一个数据库以进入交互式的窗口:% psql MYDB
Welcome to psql, the PostgreSQL interactive terminal.
Type:        \copyright for distribution terms
        \h for help with SQL commands
        \? for help on internal slash commands
        \g or terminate with semicolon to execute query
        \q to quit
MYDB=#
在这里,我们可以使用 19.3 所列出的一些标准的 SQL statement 来存取数据库,例如 create、drop、delete、update、insert、alter 等。建议您进一步至 PostgreSQL 网站参考其使用手册,PostgreSQL 官方网站是
[url=http://www.postgresql.org/]http://www.postgresql.org[/url]
。您也可以在下列网址中找到中文的使用手册:
[url=http://www.freebsd.org.hk/html/pgsqldoc-7.0c/postgres.htm]http://www.freebsd.org.hk/html/pgsqldoc-7.0c/postgres.htm[/url]

在交互式的接口中,您可以使用 \h 及 \? 来查询可以使用的指令。其中 \h 为查询 SQL statement ,而 \? 则是常询 PostgreSQL 特有的反斜线指令,我们最常用的反斜线指令有 \q 离开交互式接口,及 \d 列出该数据库的所有数据表。
如果您觉得这种命令列的接口不好使用,我们在下一节将会介绍如何在 MS Windows 使用图形化接口的管理工具。
19.7.4 数据库备份及回复
定期备份数据库是十分重要的一件事,我们一定要养成备份的习惯。在 PostgreSQL 中,备份十分容易,假设我们要备份的数据库是 MYDB,您可以使用下列指令:% pg_dump MYDB > MYDB.sql
如此一来,你就可以把 MYDB 这个数据库 dump 出来了。然而,数据库的数据往往十分庞大,动辄数十 MB 至数百 MB,为了节省空间,您可以在备份时顺便压缩数据库。以上述指令而言,我们只要将输出导向到 gzip 即可进行同步压缩:% pg_dump MYDB | gzip > MYDB.sql.gz
我们一般从数据库 dump 出来的数据都是文字文件,所以使用 gzip压缩可以得到很高的压缩比。假设不压缩所备份出来的档案有五十 MB,使用 gzip压缩后大约只剩六百多 KB。因此,我习惯都会加上 gzip压缩。
pg_dump 这个指令只能用来备份单一的数据库,如果您要将所有的数据库中都备份起来,您可以使用 pg_dumpall 来备份:% pg_dumpall |gzip > ALLDB.sql.gz
有了备份,自然也要回存。由于我们使用 pg_dump 所备份出来的数据库实际上是将一堆数据以 SQL statement 的方式存起来,如果您将该备份的档案以文书编辑器打开,您可以看到它其实是先存放数据库中所有数据表的信息,再将存放数据。所以我们只要将这些指令导向到 psql 来执行即可。首先,请先建立要回存的数据库名称,假设我们要将 MYDB 所备份出来的数据存放在 NEWDB 这个数据库中,我们要先建立一个名为 NEWDB 的数据库:% createdb NEWDB
接着再使用下列指令来将数据回存:% cat MYDB.sql | psql NEWDB
如果您备份出来的数据有经过压缩,则需改以下列指令回存:% gunzip -c MYDB.sql.gz | psql NEWDB
或是% cat MYDB.sql.gz | gunzip | psql NEWDB
如果您要回存的档案是经由 pg_dumpall 所备份出来的数据,则必须使用 pgsql 这个使用者来执行下列指令:% gunzip -c ALLDB.sql.gz | psql -e template1
19.8 PostgreSQL 图形化管理工具介绍
许多人可能不太习惯使用命令列来管理数据库,还好 PostgreSQL 提供了许多图形接口的管理工具。您可以在 MS Windows 执行的 pgAdmin。由于这些图形接口操作上比较容易,只要您多试几次,就可以熟悉它们的使用,因此,我们不会深入介绍每个功能的用法。
对于初学者而言,使用 pgAdmin 会比在命令列中输入来得容易。您可以自
[url=http://www.pgadmin.org/]http://www.pgadmin.org/[/url]
下载最新版本的 pgAdmin。
安装完成后,我们打开 pgAdmin,按了左上角的图示后即出现联机设定的窗体。请输入您数据库服务器的位置及账号密码,如图 19-9 所示:
图 19-9
[img]http://homepage.cqwu.net/wxfy/images/ch19_09.png[/img]
请注意,您必须先将 PostgreSQL 的 TCP/IP 联机打开,而且在 pg_hba.conf 中必须允许使用 pgAdmin 的这台主机登入。您可以参考 19.6 中的说明来设定 pg_hba.conf。输入联机数据后,即可开始使用。以建立一个新的数据库为例,我们先在左边的窗口中,对着数据库按右键,再选取 [新物件]->[新建数据库] 如图 19-10 所示:
图 19-10
[img]http://homepage.cqwu.net/wxfy/images/ch19_10.png[/img]
接着我们可以输入数据库名称、编码方式等,如图 19-11:
图 19-11
[img]http://homepage.cqwu.net/wxfy/images/ch19_11.png[/img]
我们输入了数据库名称为 test,并指定使用 UNICODE 的编码方式。接下来您可以看到在管理窗口中多了一个数据库「test」,我们可以在此数据库中再建立数据表。请先点选数据库「test」,再选择「模式」->「public」->「数据表」,并对着数据表按右键选择「新建数据表」。
图 19-12
[img]http://homepage.cqwu.net/wxfy/images/ch19_12.png[/img]
接下来,您就可以输入资料表名称,再选取「资料行」以设定本数据表的字段数据。
图 19-13
[img]http://homepage.cqwu.net/wxfy/images/ch19_13.png[/img]
在 pgAdmin 的主画面中,最上方有几个功能键,可以让我们手动输入 SQL 指令或是查看数据表内容,建议您可以每一个功能都试试看,以熟悉 pgAdmin 的使用接口。基本上 pgAdmin 十分容易上手,而且也功能十分齐全。
[img]http://homepage.cqwu.net/wxfy/images/note.png[/img]
小提示
如果您想要使用网页接口的 PostgreSQL 管理工具,您可以到
[url=http://phppgadmin.sourceforge.net/]http://phppgadmin.sourceforge.net/[/url]
下载 phpPgAdmin。phpPgAdmin 的设定和 phpMyAdmin 一样十分容易,只要您已经安装好网页服务器,就可以使用 phpPgAdmin。

逍遥 发表于 2006-6-5 15:27

第二十章 SAMBA 网络芳邻
使用 MS Windows 的人大概都知道我们可以经由「网络上的芳邻」看到网络中的计算机,并经由共享数据夹来分享档案、打印机。而在 FreeBSD 中,我们也可以安装一些软件来让 Windows、FreeBSD 的使用者经由网络上的芳邻共享 FreeBSD 机器中的档案。使用 FreeBSD 来做为档案服务器,可以让家中、公司的计算机轻易的交换信息,可以说是非常方便。
本章将介绍如何使用 FreeBSD 架设网络芳邻,并使用 FreeBSD 去存取 Windows 网络芳邻的数据。读完本章后,您将了解下列主题:
网络芳邻的运作原理。
安装及设定 Samba。
使用网页管理 Samba 的设定档。
如何在 Windows 及 FreeBSD 中使用网络芳邻。
20.1 网络芳邻简介
20.1.1 SMB 协定简介
MS Windows 可以说是目前桌上型计算机中市占率最高的操作系统,许多人使用 Windows 来进行日常工作。而在 Windows 平台上,使用者可以经由「网络上的芳邻」来看到不同计算机,并经由设定「共享数据夹」来分享档案及打印机。Windows 的网络芳邻其实是使用 SMB/CIFS 通讯协议。
SMB (Server Message Block) 通讯协议最早是在 1980 年代由 IBM 所发展出来,这个通讯协议可以让不同的计算机共享档案、打印机、及其它装置。SMB 最早是运作在 NetBIOS 的网络协上,一开始 IBM 设计了 NetBIOS 只是为了让网络中少数的计算机可以彼此互相沟通。所以 NetBIOS 的功能比较阳春,在使用上有一些限制。例如,只能使用在局域网络中、跨不过路由器。后来又出现了 NetBEUI (NetBIOS Extend User Interface),也是 IBM 针对 NetBIOS 的改良版。后来又有 NetBIOS over TCP/IP,使得 SMB 协议也可以跑在 TCP/IP 上,并可以经由因特网存取。在使用 NetBIOS 在存取远程计算机时,我们可以使用计算机名称如「\\alex-pc」来存取,而 TCP/IP 只能使用「\\192.168.0.1」这种方式来存取。所以 NetBIOS 也不是一无是处,它提供了比较简单而易懂的方式。
Microsoft 在 1996 年为了市场考量,将 SMB 改名为 CIFS (Common Internet File System),名称看起来比较容易了解,顾名思义就是可以在因特网上使用的档案系统。所以我们其实不应该称呼网络上的芳邻为「网络芳邻」,而是 SMB/CIFS 通讯协议,就好像我们称呼 HTTP、FTP 一样。在 Windows 的世界里,人们可以使用 SMB/CIFS 来共享档案。而在 UNIX 的世界里使用的是 NFS (Network File System);Mac 的世界中则是使用 AppleTalk。我们可以看到不同的操作系统环境中,都有自己的一套方法,不过我们还是可以经由安装软件来达成不同平台共享档案的功能。
20.1.2 Samba 简介
在 1991 年,澳洲的一位个大学生 Andrew Tridgell 为了要让 DOS 的机器和 UNIX 的机器可以共享档案,就在 UNIX 系统中写了一套 SMB 协议的软件。经过了一段时间的发展,他想要为这套软件取一个名字,但又不能直接使用 SMB 这个名字。所以他就翻翻字典,最后找到一个和 SMB 很像的字 Samba。最后 Samba 就开始有长足的发展,加入了许多有志之士。而今,Samba 已经成为 UNIX 世界中 SMB/CIFS 协议的代名词了。
但为什么我们要在 UNIX 中使用 Samba 而不直接使用 Windows 的机器来分享档案呢?以笔者的使用经验,由于我的 FreeBSD 服务器是 24 小时开机,在上面安装了 Samba 之后,网络上的所有计算机都可以使用这台服务器共享档案,而不必另外再开一台 Windows 机器。而且,我在编辑网页、写程序时,会使用 Samba 将我的网页数据、程序直接分享出来,再由 Windows 上的文书编辑软件来进行编辑。存盘后,我不必再使用 FTP 上传档案,而是可以直接使用浏览器看到编辑的结果,很棒吧。
Samba 的功能可不只有档案分享,它还可以让我们使用 UNIX 加入 Windows 的 Domain、ADS,以使用 Windows 的 Domain 使用者权限控管。更多的功能,请参考 Samba 网站的数据。
20.2 安装设定 Samba
Samba 目前有二个主要的版本:2.2.12 及 3.0.x。2.2.12 已经发展很久了,目前已进入停滞状态。和 3.0 比较起来,速度稍快、功能较简单。最大的不同在于 Samba 2.2.12 只支援 code page,而 Samab 3.0 支援 Unicode。Unicode 的支持可以让我们同时在一个目录中存放中文、日文、简体中文等多国语的档名。所以,笔者建议您安装 Samab 3.0。
20.2.1 安装 Samba
Samba 的安装设定很简单,我们可以使用 ports 来安装:# cd /usr/ports/net/samba3
# make install clean
接着,将出现下列画面,让您做一些偏好设定:
图 20-1
[img]http://homepage.cqwu.net/wxfy/images/ch20_01.png[/img]
我们维持原本的设定即可,接下来就可以选 OK 继续编译了。
20.2.2 基本的设定档说明
Samba 的设定文件位置为 /usr/local/etc/smb.conf。在安装完后,设定文件的模板会放在 /usr/local/etc/smb.conf.default,您可以直接复制它来加以修改。
Samba 的设定档中,一个以中括号括起来的部份就是一个区段,如:[区段名称] 。除了 [global] 区段外,每一个区段都是一个分享资源的设定。在 [global] 区段中,决定了 Samba 服务器的主要设定,而其它区段则是不同分享资源的权限设定。[分享资源] 区段可以是打印机或是共享数据夹,我们可以针对不同的目录设定不同的权限。除了设定的数据外,在 smb.conf 档案中行首为 ";" 或 "#" 都是批注。
以下为 smb.conf 的主要的设定说明:
#===================== Global Settings =========================
[global]
# workgroup 就是设定计算机的工作群组。
   workgroup = Workgroup
# 要使用哪一种安全模式。如果设定为 share,就是任何人都可以存取,无需使用账号密码;
# 而设为 user 则是要输入使用者名称及密码。如果我们设为 user,必须要再设定使用者
# 使用者及密码。我们会在下一小节中做更详细的说明。
   security = user
# Windows 98 及 WinNT SP3 以上会将密码加密,我们必须将它设为 yes。
   encrypt passwords = yes
# 设定可以使用 Samba 的网络接口,可以是 IP/netmask 或是网络卡名称。
   interfaces = fxp1
# 设定新建档案时的权限为何。Samba 的权限除了看数据夹的权限设定外,还会看 UNIX 的
# 权限。我们将新建档案的权限设为 0666,新建目录设为 0777,以让不同使用者所建立的
# 可以让有权存取该共享数据夹的使用者存取。
   create mask = 0666
   directory mask = 0777
# 在下载档案时,我们使用 FreeBSD 的系统呼叫 sendfile() 以提高下载速度。使用
# sendfile() 可以提高效能近一倍喔!
   use sendfile = yes
#========================== Share Definitions ==============
# 这个区段是用来设定我们要分享的数据来。在这个区断中,有几个设定的范例可以让我们参考
# 。以下的范例为设定分享的目录是 /home/mp3,设定该目录的分享名称为 "music",只有
# wheel 群组的使用者才可以写入。
#
[music]
   path = /home/mp3
   write list = @wheel
# 另一个范例,假设我们要设定一个上传区,分享路径为 /home/upload,具有写入权限的帐
# 号是 alex 及 wheel 群组,而 samba 群组的使用者只有只读的权限。当 security
# 设为 user 时,我们必需先在系统中建立该真实使用者,再使用 smbpasswd 来建立
# Samba 的密码。必须要注意的是,当您设定某一个使用者对某个目录具有写入权限时,该使
# 用者在系统中对于该目录的 UNIX 权限也必须要有写入权限才可以喔。
[upload]
    path = /home/upload
    write list = alex,@wheel
    valid users = @samba
上述设定档中,在全域设定方面,您大概只需要修改「interfaces」部份即可。接下来的设定重点在于各个共享数据夹的设定。共享数据夹可以让我们分享系统中的某个目录,分享的名称以中括号括起来。例如,我们想要分享系统中的 /home/mp3,而使用者连进来后,看到的数据夹名称为「music」,则我们必须要设定一个区段名为 [music]。在共享资料夹权限设定方面,我们可以使用下列参数:
path:设定该共享数据夹在系统中的真正路径。
invalid users:设定不可以使用此数据夹的使用者。如果是群组名称,则必须在名称之前加上 @。有多个使用者及群组时,可以使用逗号分开。
write list:设定具有读写权限的使用者及群组。如果是群组名称,则必须在名称之前加上 @。有多个使用者及群组时,可以使用逗号分开。
valid users:设定具有读取权限的使用者。如果是群组名称,则必须在名称之前加上 @。有多个使用者及群组时,可以使用逗号分开。
browseable:设定该资料夹是不是要在使用者浏览有哪些资料夹时显示出来。可以设为 yes 或 no。如果设为 no,则该数据夹在浏览时并不会出现,而只能直接使用 \\ip\share 来进入该数据夹 (假设名称为 share)。
当我们联机到一个 Samba 服务器时,如果「security」模式设为 user,Samba 会先讯问使用者名称及密码。接下来,要进入一个共享数据夹时,会经过下列检查:
检查使用者是否在「invalid users」中,如果有,则不可以存取。
检查使用者是否在「valid users」中,如果有则可以存取。如果使用者不在「invalid users」及「valid users」中,则表示可以存取。
检查使用者是否在「write list」中,如果有,则具有读写权限。
基于上述规则,建议您先在「invalid users」中加入不可以使用 Samba 资源的群组,再设定可以读写的使用者即可。
您必须特别注意的是,由于 Samba 3.0 支持 Unicode (UTF-8),如果您要将共享数据夹名称设定为中文,请使用支持 UTF-8 的文书编辑器来编辑 smb.conf,并在存盘时将档案存成 UTF-8 的纯文字格式。Windows 支持 UTF-8 的文书编辑器如 Word、UltraEdit、EmEditor,在存盘时,必须使用 UNIX 的换行格式。以 Word 为例,在存盘时,我们将档案存成纯文字文件 (txt),接下来会出现下列选单:
图 20-2
[img]http://homepage.cqwu.net/wxfy/images/ch20_02.png[/img]
接下来,您可以就可以将该档案放到 FreeBSD 中,并将扩展名 .txt 移除,更名为 smb.conf。还有一点,由于 Windows 的文书编辑软件会在档案最开头加入三个 Unicode 的辨识字符,当您以 ee 打开该档时,可能看到下列这样的内容:
嚜璟global]
workgroup = Workgroup
server string = FreeBSD
interfaces = lnc0
security = user
encrypt passwords = Yes
create mask = 0777
我们可以看到档案第一行的开头有乱码,这时候,请使用 ee 删除开始的三个字符,让第一行变成 [global] 即可。
[img]http://homepage.cqwu.net/wxfy/images/note.png[/img]
小提示
支援 Unicode 的好处是您可以同时使用中文、日文、韩文等多国语。但在共享数据夹名称中使用中文时,设定会比较麻烦一点。不过您一定要记得,当共享数据夹要设为中文时,smb.conf 一定要存成 UTF-8 格式,否则数据夹名称会看不到或是变乱码喔。
对于分享的数据夹除了要在 Samba 设定你想要的权限外,对于该目录在 UNIX 系统上的读写权限也要配合。如果你在 Samba 中的设定都正确,却发现无法对该数据来写入,很可能是在系统中的权限没有正确设定,必须以 chmod 来加以修改。也就是说,如果您设定要分享 /home/mp3,而使用者 alex 登入后无法写入,可能是 Samba 的权限设定不对,或是该使用者在系统中对于该数据夹本来就没有写入权限。这时候,您必须使用 chmod 将 /home/mp3 的权限设为 777,这样该使用者才可以写入该目录。关于更详细的分享目录权限,请参考下一小节的说明。
修改完 smb.conf 之后,我们可以使用指令 testparm 来查看我们的设定有没有语法上的错误。
设定完 smb.conf 后,在启动 Samba 之前,我们必须先增加可以使用 Samba 的使用者密码。假设我们要新增使用者 alex,请先确定使用者 alex 是 FreeBSD 中的系统账号,接下来才可以请使用下列指令来设定它的 Samba 密码:# smbpasswd -a alex
New SMB password:
Retype new SMB password:
我们在 smbpasswd 中使用了参数 -a,表示新增使用者。如果您只是要修改使用者密码,则不需要使用参数 -a。一般使用者也可以使用 smbpasswd 来修改自己的密码。不过一般使用者在修改密码时,密码长度一定要大于五个字符喔。其它关于删除使用者、停用使用者账号的设定,请参考后续小节的说明。
Samba 会将使用者账号密码存放在 /usr/local/private/smbpasswd 中,您可以使用文书编辑器打开该档案,以查看目前有哪些使用者。
[img]http://homepage.cqwu.net/wxfy/images/note.png[/img]
小提示
可以使用 Samba 资源的使用者一定要是系统中的使用者,而且必须先使用 smbpasswd 设定该使用者的密码喔。
20.2.3 启动 Samba
完成了设定之后,我们可以启动 Samba 了。请先编辑 /etc/rc.conf,并加入下列设定:
nmbd_enable="YES"
smbd_enable="YES"
我们在 /etc/rc.conf 设定启用 nmbd 及 smbd, smbd 这支程序是用来做分享数据的 daemon,而 nmbd 则是用来做名称服务的 daemon。如果没有跑 nmbd,您只能使用 IP 连到 Samba。例如,\\192.168.0.1;而有 nmbd 后,您可以使用主机名称 (hostname) 连到 Samba,例如,\\freebsd (假设您的主机名称是 freebsd.twbsd.org)。
接下来,请先将 Samba 的启动程序更名:# cp /usr/local/etc/rc.d/samba.sh.sample /usr/local/etc/rc.d/samba.sh
最后,我们就可以使用下列指令启动 Samba 了:# /usr/local/etc/rc.d/samba.sh start
现在您就可以从 Windows 端联机到 Samba 了,您可以在档案总管的网址列输入 \\ip 或 \\hostname 来使用联机资源。
20.3 smb.conf 设定说明
Samba 的设定档中有很多细项可以让我们进行微调,建议您可以浏览一遍,以了解有什么是您需要的设定。以下我们就针对比较常用的项目分别说明。
20.3.1 global 区段的基本设定
fstype
我们可以使用 Windows 的联机网络磁盘驱动器功能,将一个共享数据夹变成系统中的网络硬盘。例如,将共享数据夹变成 Z: 磁盘驱动器。如果您点选该网络磁盘驱动器,并查看内容,您会看到它的档案系统格式为 NTFS,如下图所示:
图 20-3
[img]http://homepage.cqwu.net/wxfy/images/ch20_03.png[/img]
您可以经由设定 fstype 以改变设定。例如,下列设定是将档案系统变成 UFS2:
fstype = UFS2
netbios name
netbios name 就像是 Windows 中的计算机名称一样,如果您检示工作群组中的计算机,您可以看到预设的是您的 hostname。您可以修改 netbios name 为其它名称,如 snoopy,这样一来您就可以使用 \\snoopy 来连到该计算机。
pid directory
设定用来放 smbd 及 nmbd process id 的档案路径。预设是 /var/run。
server string
在我们查看网络上的芳邻时,除了可以看到计算机名称外,在计算机名称后还会加入一串计算机描述。预设的描述是 Samba + 版本名称。您可以任意设定这个字符串。在设定时,如果您使用 %v,则 %v 会被取代成为 Samba 的版本名称。而 %h 则会被取代成为主机名称。
workgroup
设定工作群组。
20.3.2 global 区段的安全性设定
admin users
设定管理者账号。预设的管理者账号为 root。在管理者账号中的使用者,Samba 不会去检查该使用者在 UNIX 系统中的权限,而会一律以 root 的身份执行删除档案、建立新档案等动作。预设并没有设定管理者账号,也就是没有其它使用者被设定为具有 root 的权限。如果您要设定使用者 alex 具有管理者账号的权限,可以加入下列这一行:
admin users = alex
available
available 可以让我们设定是否要停用 Samba 服务。如果 available 设为 no,则会禁止使用者登入,而且所有登入的动作都会被记录下来。
create mask
设定新建档案时的权限为何。Samba 的权限除了看数据夹的权限设定外,还会看 UNIX 的权限。例如,如果我们将 /home/music 设定让使用者 alex 及 john 都有写入的权限,当使用者 alex 建立了一个档案后,而 john 要去删除该档案时,因为该档案的拥有者不是 john,如果档案的权限是 644,则 john 会无法删除档案。我们可以将新建档案的权限设为 0666,这样一来,john 也可以删除使用者 alex 所建立的档案。这样设计的好处是我们可以让所有权限的控制都交由 Samba 的数据夹权限控制,而非 UNIX 权限。
directory mask
这是用来设定新建目录时权限为何。它的作用和 create mask 差不多,只是会用在目录的权限上。
encrypt passwords
设定是否要使用加密过的密码。Windows 98 及 WinNT SP3 以上会将密码加密,我们必须将它设为 yes。
follow symlinks
设定是否要允许使用者取得、进入 symbolic link 的真的目录及档案。预设是 yes,在设为 yes 的情况下,如果您分享了 /home/music,但在该目录中有一个 symbolic link 指向 /usr/local,则使用者也可以进入到 /usr/local 目录中。这样的设定比较危险。例如,如果使用者可以进入系统中对 /home/music 做 symbolic link,则他可以建一个连结到 /etc/master.passwd,这样使用者就可以从共享数据夹中去存取 master.passwd 这个档了。
guest account
设定 guest 账号,预设是 nobody。当我们在共享数据夹权限中设定了 guest ok 为 yes 时,使用者可以使用这个账号去存取该数据夹,而不需任何密码。这个使用者一定要是系统中的使用者。
map to guest
是否要将登入错误的使用者对映到 guest 使用者而登入,预设是 Never。这个设定只有在 security 不是 share 时才有用。在设定时可以有下列三种模式:
Never:不会自动将登入失败的使用者变成 guest 使用者登入。
Bad User:只有在使用者名称正确,但密码错误时才会自动将使用者身份变成我们在 guest account 中设定的使用者。
Bad Password:只要密码错误就自动转成 guest。
使用自动对映到 guest 使用者的好处是,一般使用者不需要记得自己的密码就可以登入。但缺点是如果使用者登入失败,其身份会自动变成 guest,他有可能会无法使用原本自己账号该有的权限去存取档案。
null passwords
是否允许使用空白密码。预设是 no。
security
这个项目可以说是 Samba 设定文件中最重要的项目,它控制了使用者的登入行为及使用者认证的方法。我们可以将 security 设定为 share、user、server、或 domain,分别说明如下:
share:不需要密码就可以使用 Samba,所有的使用者会被当作 guest 账号。
user:使用者必须要使用合法的账号密码才可以登入。合法的使用者必须是系统中的使用者,而且有使用 smbpasswd 加入 Samba  的密码文件中。
domain:使用 Windows Domain Server 进行身份认证。使用者必须同时是系统中的真实使用者,并且在 Windows Domain Server 中存在才可以登入。
server:设定使用另一台 SMB 主机作身份认证。SMB 主机可以是另一台 Samba 服务器或是 NT Server。
关于 security 的设定相当复杂,建议您使用 user 的模式。如果您有需要使用其它模式,请参考 Samba 网站上关于 smb.conf 的说明。
20.3.3 global 区段的效能调校设定
max open files
设定同时最多可以开启多少档案,预设是 10000。我们通常不需要修改它。
socket options
这个项目控制了开启网络连结 (socket) 时,要设定的选项。预设只有 TCP_NODELAY。如果您有需要调校,请 man setsocopt。
use sendfile
设定下载档案时是否要使用 sendfile()。当设为 yes 时,在下载档案时,会使用 sendfile() 这个系统呼叫,而非传统的读写动作。传统的读写动作必须由 kernel 读取数据,送数据到 Samba,再由 Samba 将资料写到 Kernel,接着才由 Kernel 送到网络上。而使用 sendfile 时,会变成由 kernel 读出档案数据后,直接送到网络上。如此一来,可以大大的提高效率。
20.3.4 global 区段的记录文件及除错设定
log file
设定要将 Samba 记录文件存成什么文件名。我们可以设定针对不同的使用者、不同的来源存成不同的记录文件。例如,我们可以设定 log file 为 /var/log/samba/log.%m,表示将记录文件依不同的来源主机存放,%m 会被取代成为主机名称。您还可以使用 %d 表示 process id,%l 表示客户端的 IP,还有更多代号请 man smb.conf。
log level
设定记录的等级,等级可以设等级的数字可以是 0 到 10。设定为 0 时的记录最少,设定为 10 的记录内容最详细。这个设定值会影响到系统效能,如果等级设得越高,则要记录的东西越多,自然速度会越慢。
max log size
设定记录文件最大的大小,预设是 5000。如果设为 0 表示不限制。在记录文件超出设定值时,Samba 会将该档案更名为 .old 文件,并建立新的记录文件。
20.3.5 global 区段的网络资源设定
deadtime
设定当客户端联机多久没有动作则自动断线并离开子程序。当有客户端联机时,smbd daemon 会产生一支新的子程序来处理客户联机,但是如果客户端一直没有动作,这个子程序的存在只是占用了内存。我们可以设定一段时间没有动作则自动断线,以节省资源。而一般的客户端在断线后,如果有需要在使用资源,会自动联机,使用者不会有任何感觉。预设并没有设定自动断线。
domain master
在 SMB 协议中,同一个 workgroup 的所有计算机中,通常开机最久的计算机会被当做 master browser。当工作群组中的计算机要查询群组中的主机名称时,会到该计算机上查询。如果我们将 domain master 设为 yes,则 nmbd 会告诉工作群组中的计算机这台 Samba 服务器是 master browser,而 Samba 就会将工作群组中的计算机清单存下来,以供客户端查询。建议您将这个项目设为 no,以免占用系统资源。
hosts allow
设定可以使用 Samba 服务的客户端来源。预设并没有设定 host allow,也就是允许任何人联机。以下是几个设定的范例:
host allow = 150.233. except 150.233.1.1:表示允许除了 150.233.1.1 外的其它 150.233.x.x 的机器联机。
host allow = 192.168.0.0/255.255.0.0:表示允许所有 192.168.x.x 联机。
hosts deny
这个项目和 host allow 类似,只是它是用来设定不可以使用 Samba 服务的来源。
interfaces
设定 Samba 只提供服务给此接口的网络卡。如果您有二张网络卡,一张对内,一张对外,则可以设定只允许内部使用 Samba。这个设定可以是网络卡代号、IP/Mask、IP。如果您设定为 fxp*,则表示 fxp0、fxp1 都可以使用。
bind interfaces only
如果没有将 bind interfaces only 设为 yes,则 Samba 只会限制 smbd 只提供档案服务给上列 interface 的网卡。而还是允许其它网卡使用 nmbd 服务进行广播。
max connections
设定最多同时联机的数目,预设是 0 表示没有限制。
wins support
设定是否支持 wins 服务器。由于 SMB 名称查询是使用广播的方式。当有不同的子网域时,需要有 wins 服务器才可以查询到不同子网域的数据。所以如果您有不同子网域时,您可以设定使用 wins 服务器,否则不需设定。
wins server
设定 wins 服务器的 IP。
20.3.6 分享权限设定
本小节将说明分享资料夹时,我们可以对资料夹设定什么权限。每一个数据夹都是一个独立的区段,我们可以分别对不同的数据夹设定不同的权限。例如,是否要允许使用者 A 存取、读写权限为何等等。
browseable
这个项目设定当使用者连到本服务器时,在列出所有共享数据夹时,是否要列出这个资料夹。如果设为否,则使用者联机到本机时,不会列出此目录。但是使用者还是可以使用 \\xxx\share 来直接进入该数据夹。
这项设定的好处是,您可以隐藏不想让使用者看到的共享数据夹,只有知道路径的人才可以存取它。
comment
设定数据夹批注。在使用者从网络芳邻中浏览数据夹时,这个批注会出现在数据夹名称后面。
guest ok
是否允许 guest 账户使用本共享数据夹。
hide dot files
是否要将档名为 . 开头的档案当成隐藏档,预设是 yes。
invalid users
设定不可以使用本共享数据夹的使用者。这个项目可以是一堆用逗号分开的使用者、群组清单。如果是群组名称,则必须在名称之前加上 @。
path
设定此共享数据夹在系统中的绝对路径。
valid users
设定可以使用本共享数据夹的使用者。这个项目可以是一堆用逗号分开的使用者、群组清单。如果是群组名称,则必须在名称之前加上 @。如果使用者同时出现在 invalid users 及 valid users,则不可以存取本数据夹。
write list
设定可以对本共享资料夹进入写入动作的使用者。这个项目可以是一堆用逗号分开的使用者、群组清单。如果是群组名称,则必须在名称之前加上 @。
20.4 使用网页设定 Samba
除了使用文字编辑软件来修改 smb.conf 并用命令列工具设定使用者数据外,我们可以使用 Samba 内建的网页接口工具来进行设定。我们在编辑 smb.conf 时,如果要使用中文数据夹名称时,由于数据夹名称是 Unicode,我们必须使用 Word 来编辑。但如果我们使用 Samba 的网页接口工具,预设就是 UTF-8 了,在设定上会容易许多。
首先编辑 /etc/inetd.conf,将最下方 swat 的批注拿掉:
swat stream tcp nowait.400 root /usr/local/sbin/swat swat
最后重新启动 inetd:# kill -1 `cat /var/run/inetd.pid`
然后就可以使用浏览器以 port 901 连到 Samba Server了。假设 Samba 的 ip 是 192.168.0.1,则输入 [url]http://192.168.0.1:901[/url],被要求输入账号密码时,请输入 root 及 root 在系统中的密码。请注意 root 一定要有密码,否则无法登入。接着出现下列画面:
图 20-4
[img]http://homepage.cqwu.net/wxfy/images/ch20_04.png[/img]
在 swat 的首面中,有很多说明文件的连结供您参考。
接下来,我们选GLOBALS来看全域设定:
图 20-5
[img]http://homepage.cqwu.net/wxfy/images/ch20_05.png[/img]
这里的每一个选项,我们都可以参考上一小节中的说明来设定,设定完后记得要 「Commit Changes」来使设定生效。
如果要开放一个新的目录,我们可以选 SHARES 来设定分享的资料夹:
图 20-6
[img]http://homepage.cqwu.net/wxfy/images/ch20_06.png[/img]
我们可以在 Create Share 字段中建立要分享的资料来名称,再按「Create Share」来新建一个共享资料夹。或是选择「Choose Share」、「Delete Share」来选择或删除已分享的目录。在设定完数据夹后,您必须重新启动 smbd 才会生效喔。
其它的各项功能选项说明如下:
PRINTERS:设定列表机。
WIZARD:使用设定精灵。
STATUS:查看 Samba 的状态,可以在这里重新启动 Samba。
VIEW:观看设定后的 smb.conf 檔。
PASSWORD:设定使用者及密码。
以设定新的使用者为例,如果我们要建立一个新的使用者 friend:
图 20-7
[img]http://homepage.cqwu.net/wxfy/images/ch20_07.png[/img]
使用者 friend 必须是系统中的使用者,否则您必须使用 adduser 或 vipw 建立使用者。建立之后就可以在上图中 User Name 中输入 friend 并密码。这个功能取代了使用 smbpasswd -a 来建立账号的功能。
20.5 Samba 命令列工具介绍
在命令列中有一些工具可以让我们设定使用者数据、浏览目前使用情形等,我这个小节我们先介绍一些基本的命令指令。
20.5.1 smbpasswd 使用者及密码管理
smbpasswd 是一个用来在命令列管理 Samba 使用者的工具,我们可以用它来新增使用者、修改使用者密码、甚至可以执行它来修改其它主机上的 samba 密码。
smbpasswd 这个指令会将 Samba 的使用者信息存放在另一个名为 smbpasswd 的文字文件中,这个文字文件的位置依你安装 Samba 时所下的参数而有所不同,如果您以 ports 安装,则 smbpasswd 位于 /usr/local/private 下,你可以使用文书编辑器去观看它的内容。
samba 的使用者和系统使用者所使用的密码文件是分开的,系统中的密码设定并非 samba 所使用的密码,但是要加入 samba 的使用者一定要存在于系统中。
一般使用者如果要使用 smbpasswd 指令来修改密码,只要输入 smbpasswd 即可,而 root 可以使用一些参数去新增、修改、删除使用者,其使用格式如下:# smbpasswd [参数] [使用者] [密码]
以下我们介绍一些 root 常用的参数:
[b]参数[/b]
[b]说明[/b]
-a
新增一个使用者,并设定密码。如果该使用者已存在,则只进行修改密码的动作。
-d
暂时禁止某一个使用者登入。使用这个参数后,smbpasswd 会在该使用者数据中加一个 D 的符号,如此一来,该使用者便无法登入。下次我们再开放该使用者登入时,他的密码数据还是维持不变。
-e
开放被禁止登入的使用者登入。这个参数执行后,会将 smbpasswd 中该使用者数据中的 D 等号移除,该使用者便又可以登入了。
-x
删除一个使用者的数据。
例如,我们想要新增一个使用者 alex,并设定其密码为 password:# smbpasswd -a alex password
但我建议您不要在命令列中直接输入密码,而是以下列方式来新增使用者:# smbpasswd -a alex
New SMB password:
Retype new SMB password:
Added user alex.
如果您要删除使用者 alex:# smbpasswd -x alex
smbpasswd 还有其它更进一步的功能,您可以 man smbpasswd 以获得更多信息。
20.5.2 smbstatus 服务器状态检视
smbstatus 可以让我们知道目前系统中 Samba 的使用情形。执行 smbstatus 后的信息如下:
Samba version 3.0.20
Service      uid      gid      pid     machine
----------------------------------------------
picture      root     wheel    36153   desktop  (192.168.0.2) Sun Oct 31 23:01:16 2004
public       root     wheel    36153   desktop  (192.168.0.2) Mon Nov  1 14:35:40 2004
mp3          root     wheel    36153   desktop  (192.168.0.2) Mon Nov  1 10:21:51 2004
video        root     wheel    36153   desktop  (192.168.0.2) Mon Nov  1 10:21:50 2004
Locked files:
Pid    DenyMode   Access    R/W      Oplock     Name
-------------------------------------------------------
36153  DENY_NONE  0x20089   RDONLY   LEVEL_II  /home/mp3/song.mp3   Mon Nov  1 17:31:14 200
第一个部份显示的是目前使用者正在使用的数据夹名称,而第二个部份则是正在使用的档案。
20.5.3 nmblookup 名称查询
我们可以使用 nmblookup 来查询网络上 NetBIOS 主机的信息,您可以用来查询 Windows 或 Samba 服务器的计算机名称、IP 等信息。假设我们想要查询 192.168.0.2 这一台机器的 NetBIOS name:# nmblookup -A 192.168.0.2
Looking up status of 192.168.0.2
       DESKTOP          -         B
       DESKTOP          -         B
       WORKGROUP        -  B
       WORKGROUP        -  B
上列信息中,我们可以看到 192.168.0.2 这台机器的名称为 DESKTOP,其群组为 WORKGROUP。您也可以由 NetBIOS 名称反查其 IP:# nmblookup desktop
querying desktop on 192.168.0.255
192.168.0.2 desktop
20.6 Windows 设定
MS windows 系统的设定方面,如果您使用的是 Windows 98/ME,请先确认您有支持「Client for Microsoft Networks」及「File and printer sharing for Microsofe Networks」。而且 Windows 98 的使用者登入系统名称和您要登入 Samba 的使用者名称必须相同才行。如果是 Windows 2000/XP 则没有这个问题。
我们在使用登入 Samba 时,可以从档案总管或浏览器直接输入 \\192.168.0.1 (服务器 IP) 或是 \\hostname (您所设定的 netbios name,预设是 hostname)。或者,您可以将某一个共享数据夹设为系统中的网络磁盘驱动器。
我们只要对着某一个数据夹按鼠标右键,选择「联机网络磁盘驱动器」即可:
图 20-8
[img]http://homepage.cqwu.net/wxfy/images/ch20_08.png[/img]
接下来选择要使用的磁盘驱动器代号:
图 20-9
[img]http://homepage.cqwu.net/wxfy/images/ch20_09.png[/img]
最后就会出现一个新的网络磁盘驱动器了:
图 20-10
[img]http://homepage.cqwu.net/wxfy/images/ch20_10.png[/img]
由于我们安装的是 Samba 3.0,所以在共享资料夹内可以同时存在中文、日文、韩文的档案。
20.7 存取 MS Windows 的网芳资料
如果您要使用 FreeBSD 来存取 MS Windows 的网芳数据,FreeBSD 中内建有 mount_smbfs 这个工具,可以让我们将所要存取的主机及其目录挂在档案系统中。挂入后,存取的方式就好像档案位于硬盘中一样,十分方便,而且对于中文的存取也没有问题。mount_smbfs 是在 4.5-RELEASE 之后才内建的,如果您的系统在 4.5-RELEASE 之前,您必须要自行从 ports 中安装 /usr/ports/net/smbfs。
在使用 mount_smbfs 时,如果您的 kernel 并未将 SMB protocol 编译进来也没关系,系统在使用前会自动加载 smbfs.ko 这个模块。假设我们要存取的主机数据如下:
IP:192.168.0.2
要挂入的分享目录:software
挂入系统中哪一个目录:/mnt
我们可以使用下列指令来挂入:# mount_smbfs -I 192.168.0.2 -N '//192.168.0.1/software' /mnt
这里的参数 I 表示指定 IP 地址,参数 N 表示不须密码验证。如果您所要挂入的分享数据夹需要密码认证,则不要加参数 N。我们在挂入别台计算机的数据夹时,如果没有指定使用者名称,内定会以目前所使用的账号。如果我们要使用别的使用者名称,可以使用下列方式:# mount_smbfs -I 192.168.0.2 '//username@192.168.0.1/software' /mnt
将分享的资料夹挂入后,我们就可以使用 FreeBSD 档案处理的指令,诸如 cp、mv 等来抓取我们所要的档案,就像是从本机硬盘中使用档案一样。

逍遥 发表于 2006-6-5 15:27

第二十一章 NFS
在 UNIX 的世界里,二台 UNIX 系统要共享档案时,最常使用的协议是 NFS (Network File System)。NFS 是一个历史悠久的协议,它就像是 Windows 世界中的网络芳邻一样,可以让我们将另一台机器的目录当成本机的目录使用。
本章将介绍如何架设 NFS 服务器,读完本章后,您将了解下列主题:
NFS 的运作原理。
如何设定 NFS。
如何使用 NFS 服务器。
21.1 概论
NFS 是 Network File System。NFS 就好像是 UNIX 系统中的网络芳邻,您可以使用 NFS 将服务器上的资料夹汇出,让其它 UNIX 主机可以将所汇出的数据夹挂入。当您有多台 UNIX 主机时,使用 NFS 可以让您共享同一个数据夹。如此一来,同一份数据就不必放在多台机器上,而可以经由 NFS 来节省空间并达到数据的同步。使用 NFS 不仅可以分享一个系统中的目录,您也可以用来分享光驱、软盘机等装置。
由于 NFS 发展已久,它和一般档案分享协议最大的差别在于 NFS 的主要程序是内建在系统核心中,而非像 Samba、FTP 等主要的程序是安装在另一套软件上。不过这不代表 NFS 不需要任何软件就可以运行,在 FreeBSD 中,它还是需要下列几支程序的帮忙:
nfsd:用来提供客户端 NFS 服务。
mountd:用来告诉 nfsd 要分享的数据夹有哪些。nfsd 会将收到的 NFS 要求交由这支程序来执行。
rpcbind:用来告诉 NFS 客户端服务器所使用的连接埠为何。
如果您使用的是 FreeBSD 4.x,您会使用 portmap 而非 rpcbind 这支程序。
在客户端方面,要使用 NFS 服务并不需要任何 daemon,但您也可以执行 nfsiod 这支程序以提高 NFS 的效能。
21.2 NFS 设定
首先,我们要先编辑 server 端的 /etc/rc.conf ,并加入下列的设定:
# 如果您使用 FreeBSD 4.x,请使用 portmap_enable。
portmap_enable="YES"
# 由于 FreeBSD 5.x 中,portmap 这支程序己被取代为 rpcbind,
# 所以如果您使用 FreeBSD 5.x,请使用 rpcbind_enable。
rpcbind_enable="YES"
nfs_server_enable="YES"
nfs_server_flags="-u -t -n 4"
mountd_enable="YES"
mountd_flags="-r"
在选项 nfs_server_flags 中,-u 表示我们提供 UDP 方式联机,而 -t 表示以 TCP 方式联机。如果您所要使用 NFS 的 client 都是 FreeBSD,您可以只以 TCP 联机,如此可以有较佳的效能。-n 4 表示我们一次打开四个 nfsd 的 daemon。
接着我们要设定 /etc/exports,这个档案是用来设定我们所要分享的数据夹及其权限。/etc/exports 可能长得像这个样子。
/usr/src /usr/local     -maproot=root
/home  -alldirs  -maproot=root -network 192.168.0.0 -mask 255.255.255.0
/cdrom -ro  -mapall=alex
第一个字段为所要分享的目录,如果所要分享的目录位于同一个 slice 上,则必须写在同一行。例如我们要分享的目录是 /usr/src 及 /usr/local,因为这二个目录位于同一个硬盘的分割区上,所以必须写在同一行,也就是说同一个分割区只有一种权限。在目录之后,我们会指定一些设定权限的参数,其意义如下:
[b]参数[/b]
[b]意义[/b]
-ro
表示 read only,只读。
-maproot=user
如果 client 以 root 存取,则将它的权限对映成本机 user 的权限。
-mapall=user
将所有 client 的存取联机对映到 user,也就是说所有人的身份都转成 user。
-alldirs
可以让使用者将该分享数据夹的任一目录做为 mount point。也就是说当我们分享的是 /usr 时,client 也可以将 /usr/include 当成挂入点来 mount。但前提是 /usr 必须是一个独立的 filesystem,也就是说 /usr 必须是独立分割成一个 slice。
-network IP -mask MASK
指定允许联机的网域。
您可以 man exports 来获得更多关于 exports 格式的信息。我们每次设定完 /etc/exports 都必须以下列指令重新启动 mountd:# kill -HUP `cat /var/run/mountd.pid`
不过由于我们是第一次设定,所以连 mountd 都还没有启动,所以你可以选择重新开机或是执行下列指令来启动 NFS 服务。
首先是启动 RPC port map,如果您是使用 FreeBSD 4.x,请将下列 rpcbind 指令改为 portmap:# rpcbind
# nfsd -u -t -n 4
# mountd -r
完成了 Server 端的设定后,我们还要做 client 端的设定。在 client 端的 rc.conf 中,我们要加入下列的设定:
nfs_client_enable="YES"
nfs_client_flags="-n 4"
当设定了 nfs_client_enable 为 YES 后,在开机时即会自动启动 nfsiod ,而这里的 -n 4 和 server 的设定一样,代表我们一次要启动四份 nfsiod 来做 nfs 联机。我们不一定要在 NFS client 启动 nfsiod,如果没有 nfsiod,照样可以使用,但 nfsiod 可以提高联机效率。
设定完 rc.conf 后,要重新开机才会生效,同样的,如果您不想重新开机,你可以手动执行下列指令来让 nfs client 生效:# nfsiod -n 4
现在我们可以开始使用 NFS 了。首先,我们可以使用 showmount 这个指令来查看 server 上有哪些分享的数据夹,假设 NFS server为 192.168.1.1:# showmount -e 192.168.1.1
Exports list on 192.168.1.1:
/home Everyone
/usr 192.168.1.2
接着我们就可以将想要挂入的数据夹 mount 进来:# mount 192.168.1.1:/home /mnt
如果您要想在一开机就将该数据夹挂入,您可以编辑 /etc/fstab,并加入下列设定:
192.168.1.1:/home   /mnt    nfs rw  0   0
21.3 NFS 的限制
在使用 NFS 时,有些事我们必须特别注意。如果您 NFS server 负担相当重,也许你会发现该服务器时常没有响应,而 client 端也会因此而无法动作。这并非 FreeBSD 独有的问题,使用 NFS 时,网络卡的选择及网络整体的品质很重要。否则在 client 和 server 系统负担不一时,很容易产生没有响应的情形。
有时候我们将 mount 某台服务器的数据夹,但如果该服务器关机或是停止 NFS 服务,当您 ls 所挂入的目录时,整台机器会因而停止动作。此时除非该 NFS 服务器又开启,否则您只能重新启动了。因此,建议您 mount NFS 并完成所需的存取动作后,就立即 umount,才不会使 client hang 住。如果您希望当所 mount 的服务器发生问题时,本机可以不受到影响,您可以改用 mount_nfs 指令并加上参数 -i 及 -s。# mount_nfs -s -i 192.168.1.1:/home /mnt
参数 -i 允许我们在使用 Ctrl+C 来中断 mount 的动作。参数 -s 是使用 soft mount 模式,当档案系统对于所 mount 的服务器操作失败时,重试几次后就不再试了。

逍遥 发表于 2006-6-5 15:28

第二十二章 DNS 服务器
如果说 DNS 服务器是网络上最重要的服务器一点也不为过。少了 DNS 服务器,我们要存取另一台计算机时,都必须要使用 IP。您再也不能使用 [url]www.yahoo.com[/url] 或是 [email]alex@twbsd.org[/email] 等好记的名称。如果您是大型网络的管理者,一定要知道如何架设 DNS 服务器。而一般的系统管理者也应该要知道 DNS 的运作原理。读完本章后,您将对下列 DNS 主题有更深入的了解:
DNS 运作原理。
如何架设 DNS 服务器。
如何设定 DNS 正解及反解。
22.1 DNS 概论
DNS (Domain Name Service) 是网域名称服务的缩写,其主要目的是在解决机器的网域名称 (Domain name) 与 IP address 的对应问题。 在因特网上,为了要联机到其它计算机,必须经由 IP 地址来判断计算机所在位置,例如 140.115.83.240 就是一个 IP 地址。但是这一长串的 IP 并不好记,因此出现了 Domain Name 来为 IP 取一个比较好记的名字,如 bbs.mgt.ncu.edu.tw。Domain Name 的架构是一个树状结构,例如上述的 bbs.mgt.ncu.edu.tw 所代表的就是台湾 (tw) 的中央大学 (ncu) 管理学院 (mgt) 所属的电子布告栏服务器 (bbs)。而 DNS 服务器的功用就是将你输入的 Domain Name 转成 IP,或者是将查询 IP 并转回所对映的 Domain Name。
图 22-1
[img]http://homepage.cqwu.net/wxfy/images/ch22_01.png[/img]
网域架构是一个树状结构,以根网域为起点,慢慢散开成各个节点。以中央大学的 DNS 为例,我们可以看到在台湾的网域 (tw) 下有许多不同的网域,如 .net.tw、.edu.tw 等。而 .edu.tw 下又有很多的教育单位,中央大学的网域 ncu.edu.tw 就是其中之一。
在根网域下的第一层可以分为二大类,第一种是以国码为网域名称,如 .tw、.jp。而另一种是 .org、.com、.net 等不分国码的网域。由于因特网起源于美国,一开始的名称设计并没有国码,只有使用 .org 表示网织、.com 表示公司、.edu 表示教育单位、.gov 表示政府组织等,所以没有国码的网域名称一开始是美国所使用。目前顶层的网域名称皆由 ICANN (The Internet Corporation For Assigned Names and Numbers) 所公布,而每一个第一层的网域都交由各自国家管理。以台湾的网域为例,它是由台湾网络信息中心 (TWNIC) 所管理。TWNIC 将申请授权业务再委托 Hinet 等其它单位受理。如果您要申请 .tw 的网域,可以到 TWNIC 查询代理申请业务的公司。
一般而言, DNS 服务器可以分为三种,主要名称服务器 (Primary/master Server),次要名称服务器 (Secondary/slave Server),及快取名称服务器 (Cache only Server)。主要名称服务器是管理所属网域所需名称对映设定的主要服务器,如果您自己有一个网域,必须经由设定主要名称服务器来管理网域中 IP 所对映的名称。而次要名称服务器是取得主要名称服务器的数据,用以在主要服务器过于忙录或停止服务时备用。每个 DNS 服务器都会将所查询过的 Domain Name 建立快取 (cache),以供下次查询时能快速响应。每一个服务器都会设定该 Domain Name 快取的数据要保留多久,以免得到过时的数据。
DNS 有分为正解 (forward) 及反解 (reverse)。正解就是把 Domain Name 转成 IP,而反解是将 IP 转成 Domain Name。FreeBSD 内建有 DNS 的服务,只要先设定 /etc/namedb/ 下的档案即可打开该服务。
那要如何得到一个 Domain Name 呢?以学校而言,每个学校都有自己的 Domain Name 及 IP 范围,如果你只有一台机器,想要为它申请一个 Domain Name,您并不需要自己架设 DNS。只要向学校计中或是管理该 IP 的单位提出申请正反解即可。如果您想为自己的系所架设 DNS 以管理该系的 IP,必须先向上层 DNS (也就是校方计中) 申请授权,让针对您系所的查询都交有你的 DNS 服务器处理。DNS 的架构是树状结构,以查询 bbs.mgt.ncu.edu.tw 而言,管理 tw 网域的服务器会告诉你管理 ncu.tw 的服务器在哪里,而 ncu.tw 会告诉你管理 mgt.ncu.edu.tw 的服务器在哪里,最后 mgt.ncu.edu.tw 发现自己有 bbs.mgt 的资料,并传回其 IP。
如果您自己要申请一个 Domain Name,你可以到 [url]www.twnic.com.tw[/url] 去申请一个 .tw 的名称,如 abc.com.tw;或者到 YAHOO! 去申请各国的 Domain,如 abc.com。当您去 TWNIC 申请网域名称时,你必须要有自己的 DNS 服务器,并在 TWNIC 设定 DNS 服务器的地址,接着再由您的 DNS 服务器来做解析。如果您是在 YAHOO! 申请网域名称,国外的代理申请者会帮你做 DNS 的服务,你只要在他们的网页设定你想要的名称及所对映的 IP 即可,而且不限个数,当然你也可以自行架设 DNS 服务器。
如果只一个固定 IP,您不需要架设 DNS,除非我们管理一个网域中多个 IP 才有必要。再者,如果您是固接式 ADSL 或是其它由 ISP 提供的联机方式,你的 DNS 反解必须要由上层 ISP 授权由您自行管理你的 IP ,这样你的设定才会生效,否则应该请 ISP 帮你作反解的设定,也就是告诉 ISP 你的 IP 要对映那一个 Domain Name。
对于 DNS 有初步概念之后,我们接着说明如何设定 FreeBSD 成为一台 DNS 服务器。我们以下列的数据做为设定的依据:
网域:twbsd.org
IP:123.44.55.224~123.44.55.231 (八个 IP)
Netmask:255.255.255.248
22.2 named.conf
我们先在原本 /etc/named.conf 文件的最下方加入下列设定,该档中行首以 // 开头者为批注:
// 设定要正解的网域是 twbsd.org,DNS 服务器是 master server
// 并到 twbsd.fwd 这一个档案中去找 twbsdorg 的设定。
zone "twbsd.com" {
    type master;
    file "master/abc.fwd";
};
// 下面是反解的数据,设定要反解的 IP 为 123.44.55.224 到 123.44.55.231
// 设定关于该 IP 范围反解的设定档为 twbsd.rev
zone "224-29.55.44.123.in-addr.arpa" {
    type master;
    file "master/twbsd.rev";
};
第一个部份是正解档的设定,也就是设定将名称转为 IP。我们设定管理 twbsd.org 这个网域,并设定网域设定数据存放在 twbsd.fwd 这个档案中。
第二个部份是反解的设定,也就是设定将 IP 转为名称。如果您的 ISP 会帮您做 IP 反解,您可以忽略反解的设定。
在反解的设定方面,第一行的 zone 设定部份,针对不同的子网络范围有不同的设定格式。如果你的 IP 的范围是整个 Class C,子网掩码 (Netmask) 为 255.255.255.0,或是其它经由切割过的 IP,关于上面反解数据 zone 那一行的设定会有点不同。
以 123.44.55.0 为例,假设我们具有完整 Class C,IP 的范围是 123.44.55.*。则其子网掩码为 255.255.255.0,转换为二进为后有 24 个 1,所以网域可以写成 123.44.55.0/24。在设定zone 时,我们可以设定为:
zone "55.44.123.in-addr.arpa"
若是 Class C 分成二个网域,每一段有 128 个 IP,子网掩码为 255.255.255.128,则二个网域分别可以写成 123.44.55.0/25 及 123.44.55.128/25。这二个网域分可以可设定如下:
zone "0-25.55.44.123.in-addr.arpa" ; 0-25 是第 1段
zone "128-25.55.44.123.in-addr.arpa" ;128-25 是第 2段
若是 Class C 分成四个网域,每一段有 64 个 IP,子网掩码为 255.255.255.192,则可以设定为:
zone "0-26.55.44.123.in-addr.arpa" ; 0-26 是第 1段
zone "64-26.55.44.123.in-addr.arpa" ; 64-26 是第 2段
zone "128-26.55.44.123.in-addr.arpa" ;128-26 是第 3段
zone "192-26.55.44.123.in-addr.arpa" ;192-26 是第 4段
基本上就是将 IP 倒过来写,并在开头指定起始 IP 及范围。
[img]http://homepage.cqwu.net/wxfy/images/note.png[/img]
小提示
还记得子网掩码的计算方法吗?您可以参考「网络设定」一章中关于 IP 地址、子网掩码及切割网络的说明。
接下来就可以在 /etc/namedb/master 目录中新增并编辑 twbsd.fwd 这个正解档及 twbsd.rev 反解檔。
22.3 正解档设定
以下是 /etc/namedb/master/twbsd.fwd 的内容,档案中 ";" 之后为批注:
$TTL        172800
@        IN        SOA        twbsd.org. root.twbsd.org.  (
                                2005100301  ; Serial
                                172800        ; Refresh
                                900        ; Retry
                                3600000        ; Expire
                                3600 )        ; Minimum
        IN                NS                twbsd.org.
        IN                A                123.44.55.225
www        IN                A                123.44.55.226
ftp        IN                CNAME        www
mail        IN                A                123.44.55.227
mail        IN                MX                10 [url]www.twbsd.org[/url]
        IN                MX                20 mail.def.net
接着我们针对档案中的每一行加以解释,您可以依自己的需要来增删数据,请不要直接使用这里的设定。为了说明的需要,有的设定有点重复,例如 mail.twbsd.org 我们设定了三个项目,在真实生活中,并不会有这种情形。
让我们先看到第一行 $TTL 的部份,$TTL 代表这设定的数据要存多久,其后所接的值是以秒数计算。我们这里的设定是 172800,表示二天。
正解档中的内容中除了第一行外,每一行的格式为 [name] [ttl] [class] [type] [data]。以下是每个字段的说明:
name:可以是网域名称或是主机名称,如果不写的话表示与上一个设定相同。
ttl:是数据要存活的时间 (time to live),也就是 cache server 将保留在它的 cache 中的时间。如果不写的话表示和 SOA 中的设定相同。
class:指定网络的类型,这个字段应该都是使用 IN 代表 internet。
type:设定该笔数据的型态,例如:MX, A, CNAME, PTR, NS 等。
data:就是实际设定数据的部份。
以下让我们针对每一行来做说明。首先请看到 @ IN SOA twbsd.org. root.twbsd.org. (…) 的部份,这个部份虽然跨过很多行,但实际上是一个设定项目,只是二个括号中间的设定可以被分为很多行以利阅读。这一行的设定是最基本的,也是最详尽的,在该行中,开头的 @ 代表网域名称 twbsd.org,IN 表示为 internet 的数据型态。SOA 后面接的是 twbsd.org,表示这台 twbsd.org 机器是 twbsd.org 网域中的主要名称服务器。而 root.twbsd.org 表示管理者的Email 是 [email]root@twbsd.org[/email]。接下来让我们看一下括号中的设定所代表的意义:
Serial:这个设定的版本,这次修改的数字必须比上次的数字大,也就是每次修改这个档时,都要将这个数字提高,这样别的服务器才会将数据更新。一般而言,我们会以日期加上几位的数字来表示,如 2004040301 表示 2004 年 4 月 3 日的第一次设定。
Refresh:这个数字是次要名称服务器要多久和主要名称服务器比对数据并更新。
Retry:如果比对失败,要在几秒后再向主要名称服务器查询。
Expire:表示如果次要名称服务器一直连不上主要名称服务器,这笔数据要多久无法比对便失效。这个字段一样是以秒计算。
Minimum:表示别的快取服务器可以将你的设定存放多久。
接下来的 IN NS twbsd.org. 表示将 twbsd.org 这个网域的 DNS 服务器是 twbsd.org 这台机器。这一行中,省略了 name 及 ttl 的字段,直接指定了 class、type、及 data。
IN A 123.44.55.225 表示将 twbsd.org 这台机器的 IP 设为 123.44.55.225。前面省略了主机名称,表示设定的是 @ 的主机。A 代表的就是指定 address,就是将 twbsd.org 这台机器的 IP 地址设定为 123.44.55.225。
www IN A 123.44.55.226 表示将 [url]www.twbsd.org[/url] 的 IP 设定为 123.44.55.226。你可以看到这里使用了字段 name class type data。接着一行使用了 type CNAME,表示将 ftp.twbsd.org 这台机器设定为和 [url]www.twbsd.org[/url] 同一个 IP。也就是这二个名字会对映到同一台机器。
另外,mail IN MX 10 [url]www.twbsd.org[/url] 及下一行 MX 的设定表示将 mail.twbsd.org 的信件交由 [url]www.twbsd.org[/url] 或 mail.def.net 来处理,数字 10 及 20 表示优先级,数字小者优先。这里的设定是将给 mail.twbsd.org 的信件交给 [url]www.twbsd.org[/url] 来处理,如果 [url]www.twbsd.org[/url] 没有回应则交由 mail.def.net 来处理。
22.4 反解档设定
如果您要设定 DNS 反解,则需要再新增并编辑 /etc/namedb/master/twbsd.rev 的档案来设定,也就是设定某一个 Domain Name 要对应到哪个 IP:
$TTL        172800
@        IN        SOA        twbsd.org. root.twbsd.org.  (
                                2001080301  ; Serial
                                172800        ; Refresh
                                900        ; Retry
                                3600000        ; Expire
                                3600 )        ; Minimum
                IN        NS        twbsd.org.
225      IN       PTR       twbsd.org.
226      IN       PTR       [url]www.twbsd.org.[/url]
227      IN       PTR       mail.twbsd.org.
和正解档重复的地方此略过,我们来看 PTR 的部份。PTR 就是将 IP 指向 Domain Name,如 225 IN PTR twbsd.org. 就是将 123.44.55.225 指向 twbsd.org 这台机器。而接下来的 226 IN PTR [url]www.twbsd.org.[/url] 表示将 123.44.55.225 指向 [url]www.twbsd.org[/url]。
22.5 最后的设定
当您修改好正解档和反解档之后,请先到 /etc/namedb/ 目录下执行下列指令以产生 localhost 的反解设定档 /etc/namedb/master/localhost.rev:# cd /etc/namedb
# sh ./make-localhost
接着,请先编辑 /etc/resolv.conf,在 nameserver 部份的第一行加入下列设定,以使用本机作为第一台 DNS 服务器:
nameserver  127.0.0.1
接下来,请修改 /etc/rc.conf,并加入下列一行,以在开机时启用 DNS 服务:
named_enable="YES"
接着我们就可以使用下列指令来启动 DNS 服务了:# /etc/rc.d/named start
在执行完上述指令之后,您应该可以进行 DNS 查询了,但建议您先使用下列指令查看系统日志中是否有错误讯息。如果有错误讯息,您必须先手动排除。# tail /var/log/messages
接着就可以用 nslookup 来试试看我们所做的设定:# nslookup [url]www.twbsd.org[/url]
# nslookup 123.44.55.225
如果你没有设定 /etc/resolv.conf 的话,上面的指令并不会以你的机器为预设 DNS 服务器,这时你可以使用下列指令来以 127.0.0.1 这台机器为服务器,查询 [url]www.twbsd.org[/url] 的设定:# nslookup [url]www.twbsd.org[/url] 127.0.0.1
如果您要查询 MX、NS、SOA 等记录,也可以使用 nslookup 来查询,只要在查询先 set type 即可:
# nslookup
Default Server: localhost.twbsd.org
Address: 127.0.0.1
> set type=MX
> mail.twbsd.org
Server: localhost.twbsd.org
Address: 127.0.0.1
mail.twbsd.org preference = 10, mail exchanger = [url]www.twbsd.org[/url]
twbsd.org nameserver = twbsd.org
[url]www.twbsd.org[/url] internet address = 123.44.55.225
twbsd.org internet address = 123.44.55.225
> set type=NS
> twbsd.org
Server: localhost.twbsd.org
Address: 127.0.0.1
twbsd.org nameserver = twbsd.org
twbsd.org internet address = 123.44.55.225
> set type=SOA
> twbsd.org
Server: localhost.twbsd.org
Address: 127.0.0.1
twbsd.org
origin =twbsd.org
mail addr = root.twbsd.org
serial = 2002080301
refresh = 3600 (1H)
retry = 900 (15M)
expire = 3600000 (5w6d16h)
minimum ttl = 3600 (1H)
twbsd.org nameserver = twbsd.org
twbsd.org internet address = 123.44.55.2.225
> exit

逍遥 发表于 2006-6-5 15:29

第二十三章 指令应用
UNIX 系统和 MS Windows 最大的不同点在于 UNIX 系统主要的设定及使用都可以经由命令列的指令来完成。因此,如何活用指令便显得十分重要。
本章将介绍常用的系统指令,读完本章后,您将会了解下列各类别的指令使用方式:
基本 UNIX 指令
系统管理指令
使用者管理指令
档案系统管理指令
网络相关指令
23.1 基本 UNIX 指令
23.1.1 概论
在 UNIX 系统中,英文字母的大小写会被视为不同的东西,因此在输入指令或文件名时,大小写的差异要特别注意。一般指令用法的格式大概如下:command [option(s)] [filename(s)]
command 是我们要执行的指令。[option] 是我们可以加的参数,用 [ ] 包起来的意思是可以有参数,也可以不加参数。而参数之后,有可能是档名 [filename],并不是所有指令都要加参数或文件名称,不过格式大部份都是依照这种顺序。另外,如果要在命令列中以一行输入多个指令,每个指令间可以用分号 ";" 分开。
23.1.2 man
查看指令的使用说明。例如我们要看指令 man 的使用说明:$ man man
如果我们只知道一个关键词,却不知要使用哪一个指令,我们可以使用参数 k 来查询。例如我们要查询 firewall 相关的指令:$ man -k firewall
man 在查询指令说明时,预设会去找 /usr/share/man 目录下的档案,如果我们要查询的指令说明文件并不位于该目录,我们可以使用参数 M 来指定目录名称。例如我们要查询指定 ab 的用法,该指令的说明文件放在 /usr/local/apache/man ,我们可以使用下列指定:$ man -M /usr/local/apache/man ab
我们看 man 档案时,常会看到像 man(1) 的格式,其中 (1) 表示该指令的分类。依不同的类别,说明档会存在 /usr/share/man/ 不同的目录下。例如 (1) 的档案是在 man1 的目录中。如果同一个名称有二个不同的 man file,分别放在不同目录,我们也可以加上参数来看不同的档案。例如 crontab 有二个档案,一个是 crontab(1),另一个是 crontab(5)。当我们要看 crontab(5) 时,使用下列指令即可:$ man 5 crontab
以下为 man 的类别:
[b]类别[/b]
[b]说明[/b]
1
一般指令。
2
系统呼叫 (System Calls)。
3
函式使用说明 (Library Functions)。
4
核心界面 (Kernel Interface)。
5
档案格式说明。
6
游戏使用说明。
7
杂项。
8
系统管理相关指令说明。
9
核心开发相关说明。
当您使用 man 指令时,所输出的结果大约如下:
LS(1)                   FreeBSD General Commands Manual                  LS(1)
NAME
    ls -- list directory contents
SYNOPSIS
    ls [-ABCFGHLPRTWZabcdfghiklmnopqrstuwx1] [file ...]
DESCRIPTION
    For each operand that names a file of a type other than directory, ls
    displays its name as well as any requested, associated information.  For
    each operand that names a file of type directory, ls displays the names
    of files contained within that directory, as well as any requested, asso-
    ciated information.
    ......
EXAMPLES
    The following is how to do an ls listing sorted by size (and shows why ls
    does not need a separate option for this):
          ls -l | sort -n +4
    Additionally, the -r flag to sort(1) may be used to get the results
    sorted from largest to smallest (a reverse sort).
SEE ALSO
    chflags(1), chmod(1), getfacl(1), sort(1), xterm(1), termcap(5),
    maclabel(7), symlink(7), getfmac(8), sticky(8)
NAME:指令的简单描述。
SYNOPSIS:指令用法,其中 [ ] 所括起来的内容表示该参数可有可无,以 man ls 而言,我们看到 [-ABCF…] 表示可以使用参数 -A -B等。
DESCRIPTION:指令用法的详细描述,包括各项参数的使用及限制。
EXAMPLES:一些用法的范例。
SEE ALSO:列出其它和本指令相关的指令,我们可以从这些指令中得到更多相关的信息。
23.1.3 ls
用以查看目录信息。
在 UNIX 系统中,/ 代表根目录。当要使用某个目录下的目录时,每个目录之间要以 / 隔开。例如 /usr/bin 表示根目录下的 usr 目录下的 bin 这个目录。
另外,"." 和 ".." 也有特殊意义。"." 代表目前所在的目录,而 ".." 表示目前目录的上一层目录。例如,../etc 表示上一层目录下的 etc 这个目录。
假设我们要查看根目录下有哪些档案:$ ls /
在 shell 中,有些符号代表者特殊的意义,例如 * 表示万用字符,可以代表零个或多个字符,而 ? 代表一个字符。举例而言,当我们下达 ls 指令来例出档案时:$ ls myfile*
myfile myfile.exe myfile.txt myfile.txab myfile.abap$ ls myfile.tx?
myfile.txt
我们可以看到使用符号 * 时,会列出所有开头是 myfile 的档案;而使用 ? 时,只会例出 myfile.txt。
但是当我们使用万用字符来取代文件名称时,例如 ls /m*,它不仅例出符合目录,还会列出该目录下所有档案。这时候我们可以使用参数 d 来让 ls 只列出目录而不列出其目录下的档案:$ ls -d /m*
ls 还有一些常用的参数如下,我们也可以同时使用多个参数,如 ls -lad:
[b]参数[/b]
[b]说明[/b]
a
列出所有档案及目录,包含文件名开头为 "." 的隐藏档。
l
列出档案的完整信息。
F
依档案及目录的格式不同加上符号以供区格,例如目录则在目录名称后加上 / 符号;如果是可执行档则加上 *;如果是链接文件则加上 @。
23.1.4 cd
所在目录的切换。例如要切换目录到根目录:$ cd /
切换目录的方式可以使用绝对路径或相对路径名称。绝对路径是指从根目录开始,该目录所在位置。例如 /usr/bin 就是一个绝对路径。而相对路径是指相对于目前所在路径而言,该目录的位置。例如 ../usr/bin 表示在上一层目录下的 usr/bin 这个目录。另外,符号 "~" 表示使用者的家目录,如果要回到自己的家目录,可以使用:$ cd ~
如果只输入 cd 和 cd ~ 所代表的意义相同,都是回到自己的家目录。我们也可以符号 "~" 之后加上使用者名称,来代表该使用者的家目录。例如要切换到使用者 jack 的家目录:$ cd ~jack
另外,如果您使用 tcsh 或 bash,您还可以使用 "-" 来切换二个目录:$ cd /usr/local
$ cd /etc
$ cd -
$ pwd
/usr/local
$ cd -
$ pwd
/etc
23.1.5 pwd
查看目前所在目录名称。例如:$ pwd
/root
23.1.6 cat
列出文字文件内容。假设我们要查看 /etc/rc.firewall 这个档案的内容,我们可以使用下列指令来列出:$ cat /etc/rc.firewall
在 UNIX 系统中有一个转向输出的观念。我们可以把指令输出的结果转向到其它地方 (如档案)。一般内定的标准输出是屏幕,标准输入是键盘。我们可以使用 ">" 符号来将输出转到别的地方。例如,我们要将 ls 的输出结果存成档案 result.txt:$ ls > result.txt
上面的指令会建立一个文件名为 result.txt 的档案,并将 ls 的结果置于该档中。如果所在目录本来就有一个文件名为 result.txt,该档案原本的内容会被清除。如果我们不想清楚该档原本的内容,只是要把结果附加在原本的内容之后,可以使用 ">>" 。例如:$ ls >> result.txt
我们可以使用 cat 指定来做简单的文字文件复制,例如将 /etc/rc.firewall 复制一份到自己根目录下的 firewall.txt:$ cat /etc/rc.firewall > ~/firewall.txt
另外,我们也可以用 cat 来建立一个文字文件并手动编辑其内容:$ cat >test.txt
在此输入文字
输入完后同时按 Ctrl+D 离开
23.1.7 more
以分页模式来列出文字文件内容。当使用 cat 时,如果档案超过一页,画面一闪而过,看都看不清楚。这时候我们可以使用 more 这个指令来将它分页输出。$ more /etc/rc.firewall
输出后,我们可以按空格键来看下一页,或按 Q 来离开。
在 UNIX 系统中还有一个观念是 pipe 管道,就是将一个指令的输出结果作为另一个指令的输入。例如,我们要查看 /etc/ 下的所有档案完整信息,使用 ls -la /etc 时,发现信息超过一页,我们可以使用下列指令:$ ls -la /etc | more
"|" 是位于键盘右上角退格键附近,和 "\" 同一个键的符号。
23.1.8 less
less 也是以分页来输出档案内容,和 more 不同的是它在输出档案全部内容后并不会离开。我们可以使用 page down 及 page up 键来查看,要离开时只要按 Q 键即可。
23.1.9 head
列出档案开头几行,预设是输出档案开头的十行:$ head /etc/rc.firewall
我们也可以加上参数 n 来指定要输出多少行。例如,如果要输出前二十行:$ head -n 20 /etc/rc.firewall
参数 c 让我们可以指定要输出档案开头多少 bytes(通常就是多少字符)。例如,如果要输出档案开头前十个字:$ head -c 10 /etc/rc.firewall
23.1.10 tail
列出档案结尾几行,预设是十行:$ tail /etc/rc.firewall
我们一样可以使用 -n 或 -c 来指定要输出多少行。
23.1.11 w
列出目前在在线的使用者信息、时间、正在执行的动作等。以下为 w 这个指令的输出范例:# w
4:32下午  up 20 days, 23:54, 2 users, load averages: 0.00, 0.00, 0.00
USER             TTY      FROM              LOGIN@  IDLE WHAT
root             v1       -                 4:31下     - top
alex             p0       192.168.0.2       1:20下     - w
我们可以看到目前系统中有二个使用者登入,分别为 root 及 alex,并分别执行指令 top 及 w。使用者 alex 是使用 telnet 联机,所以我们可以看到他的来源 ip,但 root 从 console 登入,所以在 FROM 字段中并没有任何信息。除了在线使用者信息外,我们也可以看到系统已开机时间 (这个范例中是 20 天) 及系统负荷等。
23.1.12 who
列出目前在在线使用者的信息,输出的字段和 w 略有不同。其输出结果如下所示:# who
root             ttyv1     5  2 16:31
alex             ttyp0     5  2 13:20  (192.168.0.2)
23.1.13 date
列出及设定系统时间。如果我们要查看目前时间:$ date
2004年 5月 2日 周日 16时37分12秒 CST
date 的输出结果可能是中文或英文,它会依照您在 .login 或 /etc/csh.login 对于 Locale 的设定而自动调整。
如果我们要设定时间为 2002 年 3 月 12 日 11 点 56 分,我们可以使用下列指令:$ date 200203121156
23.1.14 cal
列出月历。如果要列出当月月历:$ cal
我们也可以指定月份,例如列出 2002 年 3 月:$ cal 3 2002
或是列出整年的月历,例如 2002 年:$ cal 2002
23.1.15 echo
输出一个字符串到标准输出 (通常是屏幕)。例如:$ echo string
我们也可以将输出结果转向到档案:$ echo 'this is a test' > test.txt
这样在 test.txt 中就会有一行字符串 "this is a test"。
23.1.16 clear
清除屏幕,您也可以使用 [Ctrl] + l 来清除画面。
23.2 系统管理
23.2.1 ps
在 UNIX 系统中,每个执行中的程序我们称之为程序 (Process),而 ps 这个指令就是用来看目前系统中正在执行的程序状态。$ ps
PID    TT  STAT   TIME    COMMAND
45836  p0  S      0:00.18 -tcsh (tcsh)
46104  p0  R+     0:00.00 ps
PID 字段指的是 Process ID,就是这个程序的编号,每个程序的编号都是独一无二的;TT 是指登入的 tty;STAT 是该程序目前的状态;而 COMMAND 就是这个程序是那一个指令所执行。
ps 不加任何参数时,只输出自己在执行的程序,我们可以加上参数 -aux 来列出系统中所有使用者的程序及详细数据。$ ps -aux
USER  PID %CPU %MEM  VSZ  RSS  TT STAT STARTED  TIME COMMAND
root    1  0.0  0.1   552  148  ??  ILs   4  2  0:00.17 int
root   23  0.0  0.0   208    8  ??  IWs  -      0:00.00 adjk
alex 6167  0.0  0.8  1332  988  p0  I     7:46  0:00.21 -csh
root 6241  0.0  0.8  1332  976  p0  D     8:03  0:00.17 _su
我们来看看第一行所代表的意义:
USER:该程序的拥有者。
PID:Process ID,范围从 0 到 99999。
%CPU:该程序目前占 CPU 使用时间的百分比。
%MEM:该程序占用虚拟内存的百分比。
VSM:使用的虚拟内存大小。
RSS:使用的物理内存大小。
TT:登入的 tty。
STAT:目前的状态。
STARTED:开始执行的时间。
TIME:该程序到目前为止的 CPU 使用时间。
COMMAND:程序是由哪一个指令执行。
我们常用的 ps 参数有 auxww 等,其中 a 表示显示所有的行程,u 表示显示行程拥有者的信息,x 显示 deamon 的信息,ww 则是显示完整的 COMMAND 字段,不要将太长的部份截断。
23.2.2 kill
kill 指令会送出一个讯号 (Signal) 给指定的程序,程序在收到讯号之后,会依其要求来动作。我们常用的讯号如下:
[b]SIG 名称[/b]
[b]代码[/b]
[b]意义[/b]
HUP
1
hang up,通常用来叫程序重新加载设定。
INT
2
interrup,通知程序中止。
QUIT
3
quit,通知程序离开。
ABRT
6
abort,中断程序。
KILL
9
non-catchable, non-ignorable kill,直接通知 kernel 把该程序移除。
ALRM
14
alarm clock。
TERM
15
software termination signal,通知程序结束。
一般而言,每一个程序都会预设接收到讯号是要执行什么动作,如果我们所送出的讯号在该程序中并没特别去处理它,则程序会自动结束程序。只有 root 可以管理所有程序,一般使用者只能对自己的程序作 kill。
假设我们要叫 PID 为 123 的程序结束:$ kill -9 123
如果要通知程序重新加载设定文件:$ kill -1 123
23.2.3 top
top 是一个好用的程序管理程序,我们可以利用它来秀出执行中的程序。进入 top 之后,我们可以按 "h" 来显示在线说明或按 "q" 来离开。
我们可以看到 top 的输出分成二个部份,最上方是目前关于行程的的系统状态。包含最后一个 PID (last pid)、系统负荷 (load average) 、已开机时间 (up)、总共有多少行程正在执行中、及 CPU 和内存的使用量等等。第二个部份和 ps 一样,列出 PID、行程的拥有者、及其它和行程相关的状态。
top 这个指令会每二秒自动更新一次。您可以按 "s" 来更改更新时间。
在 top 中,如果我们想要对某个程序执行 kill 的动作,只要按 "k" 再输入参数及 PID 即可。
23.2.4 systat
用来监看系统资源使用情形。它有几个常用的参数:
[b]参数[/b]
[b]说明[/b]
-iostat
显示目前磁盘使用情形,以了解其存取的负荷。
-swap
显示所有 swap 装置的使用情形。
-netstat
显示目前网络联机情形。
-vm
显示所有系统信息。
在上述各参数之后,我们还可以指定画面的更新时间,例如:$ systat -vm 1
进入 systat 之后,我们可以按 Ctrl+L 来重绘画面,如果要离开 systat 可以先按 : 再打 quit 后离开。
23.2.5 watch
窥视某个 tty 窗口。
当使用者登入系统后,root 可以使用 watch 指令来取得使用者的窗口画面。也就是说当下达指令后,root 所看到的画面就会和该使用者一样。你可以观察该使用者在做些什么事,输出的结果又是什么。
只有超级使用者 root 可以执行 watch,在执行时,系统会自动加载 snp.ko 这个模块,或者您也可以先在 kernel 中加入下列的设定并重新编译核心:
pseudo-device snp
并新增 snoop device,使用下列指令:# cd /dev
# ./MAKEDEV snp0 snp1 snp2 snp3
接下来就可 watch 指令了。首先,先下指令 w 来看一下站上有哪些使用者。指令结果的第二个字段部份,有使用者的 tty,例如 p0、v0 等,选定要监看的使用者后,使用 watch ttyp0 来监看该使用者,其中 ttyp0 即该使用者的 tty。你可以使用 CTRL+X 来切换不同的 tty,也可以使用 CTRL+G 离开回到自己的画面。
23.2.6 alias
这是 Shell 内建的指令,用来建立别名。例如,我们希望下达指令 abc 时,会执行 ls /etc,我们可以使用下列指令:$ alias abc 'ls /etc'
$ abc
我们可以使用 unalias 来取消所设定的别名,例如:$ unalias abc
23.2.7 bg
将指定的程序放入背景中执行。当我们下达一个指令后,必须要等待该程序结束后才能输入下一个命令。如果该程序必须执行一段很长的时间,我们不想等程序结束,可以把它放到背景中执行。
在下达指令后,按 Ctrl+Z 来暂停程序,接着再执行 bg 即可将程序放到背景中执行。$ sleep 1000
^Z
Suspended
$ bg
[1] sleep 1000 &
$
我们也可以在所要执行的指令后面加上符号 "&",就可以将该程序放到背景执行:$ sleep 1000 &
[2] 46461
23.2.8 jobs
jobs 指令可以让我们查询目前有哪些程序在背景执行。如果加入参数 -l 可以得到 PID 的信息。$ jobs -l
[1] + 46459 Running sleep 1000
[2] - 46461 Running sleep 1500
23.2.9 fg
将指定的程序放到前景中执行。我们使用 jobs 看到目前在背景执行的程序之后,可以使用 fg 把它叫回前景。例如要叫回第一个在背景中执行的程序:$ fg %1
sleep 1000
23.2.10 ntpdate
向时间服务器对时,只有超级使用者才能执行。我们可以使用 ntpdate 这个指令来向时间与频率国家标准实验室的时间服务器对时:# ntpdate -b clock.stdtime.gov.tw
12 Mar 21:24:28 ntpdate[46494]: step time server
210.59.157.30 offset -8.939412 sec
23.2.11 sync
让系统暂存的数据强制存回硬盘。
23.2.12 shutdown
让系统在指定的时间关机。如果我们要立即关机可以下指令:# shutdown now
有时候电力公司通知半夜十二点要停电,我们半夜又不想再去使用计算机,这时指定时间关机就发挥作用了。我们可以在白天时先下指令:# shutdown 0203122359
0203122359 表示 2002 年 3 月 12 日 23:59,格式是 yymmddhhmm。在指定关机前五分钟系统会禁止使用者登入,并且会在 /var/run/ 目录下建立一个文件名为 nologin 的档案,内容为拒绝使用者登入时所要告诉使用者的讯息。如果我们要停止 shutdown ,可以送给它一个 SIGTERM,shutdown 程序在收到讯息后,在离开程序前会先删除 /var/run/nologin 这个档案。# ps -ax|grep shutdown
46644 ?? S# kill -15 46644
shutdown 还有一些参数:
参数
说明
-h
系统停止服务,出现你现在可以放心关机了,但不关闭电源。
-p
系统停止服务并关闭电源。
-r
重新开机。
23.2.13 reboot
立即重新开机。
23.2.14 su
切换使用中的使用者身份。例如,我们要从一般使用者切换成 root:$ su
Password:
#
一般使用者如果要具备切换成 root 的权限,必须在 /etc/group 将它加入在 wheel 群组中。例如,我们要该使用者 jack 可以使用 su 变成 root:
wheel:*:0:root,jack
我们也可以使用 su 来切换成不同的使用者,如果加上参数 -l 表示模拟完全 login 的动作。例如,我们要仿真以使用者 foo 登入系统:# su -l foo
我们也可以用参数 -c 来以不同使用者的身份执行一个指令,执行完后切换身份为原本的使用者。例如,我们要以 foo 的身份来执行 sleep 1000 这个指令并放到背景中执行:# su foo -c 'sleep 1000&'
23.2.15 exit
这是 Shell 内建的指令,我们可以使用这个指令来注销系统或注销不同的 Shell。
23.2.16 dmesg
显示系统讯息暂存区 (message buffer) 的内容。如果是刚开机,暂存区的内容通常就是开机过程的记录。随着开机时间越来越长,讯息也会越来越多,开机过程的记录就会被其它讯息所取代。
23.2.17 lastcomm
显示使用者曾经执行过的指令。如果要使用这个指令,必须在 /etc/rc.conf 中加入下面这一行:
accounting_enable="YES"
系统会在 /var/account 目录下建立记录文件,如果使用者很多的话,档案大小将会十分可观。
如果我们要查看使用者 foo 执行过哪些指令:$ lastcomm foo
这些记录每天会自动转档,存成 acct.0, acct.1 等档案。如果我们要查询的是前一天的记录,可以使用参数 -f 来指定使用哪一个记录文件:$ lastcomm foo -f /var/account/acct.0
23.2.18 crontab
安排定时执行工作。使用 crontab 可以让我们安排工作在指定的年、月、日、小时或分的周期来执行。
如果在 /var/cron 目录中有 allow 这个档案的话,只有使用者名称在档案中的人才可以使用 crontab。如果没有 allow 这个档案,但是有 deny 这个档案的话,被列在 deny 档案中的人不可以使用 crontab 来安排工作。如果二个档案都不存在,预设是所有人都可以执行。
我们可以使用 crontab -e 来编辑自己的排程, 使用 crontab -e 的格式,和 /etc/crontab 的格式不太一样,它少了执行者的字段,内定的指令执行者就是执行 crontab -e 的人。其格式如下:
MAILTO=""
# 分        小时        天        月        星期几        指令
#minute        hour        mday        month        wday        command
#
*/5        *        *        *        *        setiathome       
# minute:代表一小时内的第几分,范围 0-59
# hour:代表一天中的第几小时,范围 0-23
# mday:代表一个月中的第几天,范围 1-31
# month:代表一年中第几个月,范围 1-12
# wday:代表星期几,范围 0-7 (0及7都是星期天)
# who:要使用什么身份执行该指令
# command:所要执行的指令
#
# 时的字段中如果是 *,表示每小时,天的字段中如果是 * 表示每天,
# 依此类推字段中可以使用 "-" 来表示范围。
# 例如:在小时的字段中填 8-11,表示执行的时间是8,9,10,11共四次
# 例如:字段也可以用逗点来表示,以分的字段而言, 1,2,5,9 表示
#       将在 1,2,5,9 分时各执行一次。也可以写成像这样 1-2,12-14
#       表示在 1,2,12,13,14 分各执行一次。
# 又如:以 / 后面加数字表示每几分钟要执行一次。如在分的字段
#       填 0-23/2,表示 1-22 分之间,每隔二分钟执行一次
#       也就是 0,2,4,6,8,10,12,14,16,18,20,22
# 又如:在分的字段是 */5,表示每五分钟一次
#
# 除此之外,也可以用一个开头为 @ 的字符串来表示各种意义
#           字符串            代表意义
#           ------          -------
#           @reboot         开机时路一次
#           @yearly         每年跑一次,等于 "0 0 1 1 *".
#           @annually       (和 @yearly 一样)
#           @monthly        每月跑一次,等于 "0 0 1 * *".
#           @weekly         每周跑一次,等于 "0 0 * * 0".
#           @daily          每天跑一次,等于 "0 0 * * *".
#           @midnight       (和 @daily 一样)
#           @hourly         每小时跑一次,等于 "0 * * * *".
#
# 安排 crontab 时,应该要错开每个程序的执行时间,才不会
# 有一大堆程序同时执行。
执行 crontab 预设会将指令输出结果寄 email 给执行的使用者,如果我们不希望收到这些结果,可以在档案开头加上 MAILTO=""。
另外,我们也可以使用参数 -l 来列出目前执行的 crontab table。或使用参数 -r 来删除 table。
23.2.19 uptime
显示系统开机主机状况。例如:$ uptime
10:51下午 up 8 days, 8:46, 2 users, load averages: 1.01, 1.02, 1.00
出现的信息依序为现在时间、共开机多久、开机时间、目前使用者有多少人、系统每 1 分钟、每 5 分钟、每 15 分钟的平均负荷 (load)。
23.2.20 sysctl
显示或设定核心 (kernel) 状态。使用参数 -a 可以列出目前 kernel 状态值的设定,例如:$ sysctl -a
我们也可以使用参数 -w name=value 的方式来设定新的值。这些值如下表:
[b]NAME [/b]
[b]TYPE [/b]
[b]可否改变 [/b]
kern.ostype
string
no
kern.osrelease
string
no
kern.osrevision
integer
no
kern.version
string
no
kern.maxvnodes
integer
yes
kern.maxproc
integer
no
kern.maxprocperuid
integer
yes
kern.maxfiles
integer
yes
kern.maxfilesperproc
integer
yes
kern.argmax
integer
no
kern.securelevel
integer
raise only
kern.hostname
string
yes
kern.hostid
integer
yes
kern.clockrate
struct
no
kern.posix1version
integer
no
kern.ngroups
integer
no
kern.job_control
integer
no
kern.saved_ids
integer
no
kern.boottime
struct
no
kern.domainname
string
yes
kern.filedelay
integer
yes
kern.dirdelay
integer
yes
kern.metadelay
integer
yes
kern.osreldate
string
no
kern.bootfile
string
yes
kern.corefile
string
yes
kern.logsigexit
integer
yes
vm.loadavg
struct
no
hw.machine
string
no
hw.model
string
no
hw.ncpu
integer
no
hw.byteorder
integer
no
hw.physmem
integer
no
hw.usermem
integer
no
hw.pagesize
integer
no
hw.floatingpoint
integer
no
hw.machine_arch
string
no
machdep.console_device
dev_t
no
machdep.adjkerntz
integer
yes
machdep.disable_rtc_set
integer
yes
user.cs_path
string
no
user.bc_base_max
integer
no
user.bc_dim_max
integer
no
user.bc_scale_max
integer
no
user.bc_string_max
integer
no
user.coll_weights_max
integer
no
user.expr_nest_max
integer
no
user.line_max
integer
no
user.re_dup_max
integer
no
user.posix2_version
integer
no
user.posix2_c_bind
integer
no
user.posix2_c_dev
integer
no
user.posix2_char_term
integer
no
user.posix2_fort_dev
integer
no
user.posix2_fort_run
integer
no
user.posix2_localedef
integer
no
user.posix2_sw_dev
integer
no
user.posix2_upe
integer
no
user.stream_max
integer
no
user.tzname_max
integer
no
假设我们的系统常出现 file: table is full 的讯息,我们可能要重新编译 kernel 并提高 maxuser 的值。或者我们也可以使用 sysctl 来做更动。首先我们看一下 kern.maxfiles 的值:# sysctl kern.maxfiles
kern.maxfiles: 2024
我们可以使用下列指令来提高它:# sysctl -w kern.maxfiles=16244
如果我们要让这个设定在每次重开机时都自动加载,可以将该指令放到 /etc/rc.local 中,或是在 /etc/sysctl.conf 中加入下面这一行:
kern.maxfiles=16244
23.3 使用者管理
23.3.1 vipw
编修使用者密码文件。我们可以使用 vipw 这个指令来编辑使用者密码文件 /etc/master.passwd。如果我们编辑的内容不符合密码文件的格式,vipw 会提出警告。在修改完后,vipw 还会自动执行 pwd_mkdb 来更新系统数据库。
23.3.2 groups
这个指令可以秀出使用者属于哪一个群组。例如秀出使用者 jack 的群组:$ groups jack
wheel jack
23.3.3 adduser
请参考使用者管理一章关于 adduser 指令的介绍。
23.3.4 pwd_mkdb
如果我们直接以文书编辑软件来修改 /etc/master.passwd,在修改完后,必须执行 pwd_mkdb 来将更新的数据做成系统可以读取的数据库文件。pwd_mkdb 还会自动建立 /etc/passwd。
23.3.5 rmuser
删除使用者。使用 rmuser 将会进行下列动作:
如果该使用者有设定使用定时排程的工作,如 crontab 或 at,则先将它移除。crontab 的工作排程会被放在 /var/cron/tabs/username,而 at 的工作排程则放在 /var/jobs/username 中。
如果该使用者有正在执行的程序,则送出 SIGKILL 给该行程以将它停止。
以 vipw 移除让使用者在 /etc/master.passwd 中的账号。
使用者的家目录 /home/username,使用指令 rm -rf /home/username。
再移除使用者邮件目录 /var/mail/username。
如果暂存的目录中 (/tmp 及 /var/tmp) 有该使用的暂存盘,则将它移除。
若该使用者所属群组已无人使用,则编辑 /etc/group 来移除群组。
必须要注意的是 rmuser 并不能删除 UID 为 0 的使用者 (如 root)。
23.3.6 passwd
变更使用者密码。如果不加使用者名称,则会变更所登入的使用者密码。用法如下:# passwd jack
23.3.7 chpass
chfn, chsh, chpass 是一样的东西,用来更改使用者数据,如果以 root 来执行的话,其内容其实就是 master.passwd 的东西。如果以一般使用者执行,使用者可以使用这个指令来修改一些个人信息。
23.3.8 mesg
是否要允许其它使用者传送讯息给自己,如果不允许可以使用 mesg n,如果允许则是 mesg y。如果要执行 write 或 talk 必须设为 mesg y。
23.3.9 write
送出讯息给已经登入的使用者。
用法:write user [tty]
例如,要送出一段讯息给使用者 jack:$ write jack
在 jack 的窗口会出现下列讯息:Message from [email]root@foo.com[/email] on ttyp0 at 01:39 ...
之后所打的每一个讯息都会出现在使用者 jack 的窗口。
23.3.10 last
显示使用者登入记录。例如:$ last
mary   ttyp0 alex.alexwang 三 3/13 04:01    still logged in
foo    ttyp1 alex.alexwang 三 3/13 03:54 -  04:01 (00:06)
jack   ftp   alex.alexwang 三 3/13 03:53    still logged in
ben    ttyp2 alex.alexwang 三 3/13 03:41 -  03:41 (00:00)
如果我们只要显示某位使用者的登入记录,我们可以在指令后面加上使用者登入账号。如果要显示某一个时间有哪些人在在线,我们可以使用参数 -d。例如,2002 年 3 月 10 日 23:45 时有哪些人在在线:$ last -d 0203102345
last 预设会去找 /var/log/wtmp 这个记录文件,如果你想要使用其它记录文件可以加上参数 -f:$ last -f /var/log/wtmp.0
23.4 档案系统管理
23.4.1 touch
改变档案存取的时间。例如:$ ls -l
-rw-r--r-- 1 jack staff 1520505 2/25 20:12 myfile.txt
$ touch myfile.txt
$ ls -l
-rw-r--r-- 1 jack staff 1520505 3/13 15:21 myfile.txt
在上面的例子中,原本 myfile.txt 的存取日期是 2/25,我们使用 touch 之后,时间变成目前的时间了。如果使用 touch 时有加文件名称,但该档案不存在,touch 会建立一个空的档案。
我们也可以使用参数 -t 来指定要将存取时间设定为什么时候。例如,我们要设定为 2002 年 3 月 13 日 23:49:$ touch -t 0203132349 myfile.txt
23.4.2 cp
复制档案或目录。
用法:cp 来源 目的
我们可以使用 cp 来复制档案。例如,将 /etc/services 复制到 ~/services.txt:$ cp /etc/services ~/services.txt
在上面的指令中,如果我们不指定目地档名,将 ~/services.txt 改成 ~/ 的话,预设会使用原来的档名,也就是将 /etc/services 复制到 ~/services。我们也可以同时复制多个档案到一个目录下,例如复制 /etc/services 及 /etc/rc.conf 到 ~/:$ cp /etc/services /etc/rc.conf ~/
如果要复制目录,我们可以使用参数 -R 来将来源目录及其所有子目录复制到目的地:$ cp -R sourdir tardir
23.4.3 ln
建立链接文件,所谓的链接文件就像在 Windows 下的快捷方式。如果我们希望同样一个档案或目录可以放在许多地方,我们可以使用 ln 来建立链接文件,这样一来实际存在的档案只有一个,但在许多地方都有链接。例如我们要将 /etc/services 链接到 ~/services:$ ln /etc/services ~/services
当我们删除链接文件时并不会影响原本的档案。链接的方式可以分为 Hard link 及 Symbolic link,预设是使用 Hard link。二者的差别在于 Hard link 只能在相同的档案系统中建立链接,而且不能链接目录。我们在分割磁盘时,将不同的目录建立在不同的分割区上,假设 /etc/services 位于 ad0s1a 而使用者的家目录 ~/ 位于 ad0s1e,那么上面指定就不会生效。我们必需使用参数 -s 来建立 Symbolic link:$ ln /etc/services ~/services
ln: shit.txt: Cross-device link         $ ln -s /etc/services ~/services
我们也可以建立目录的链接:$ ln -s /etc
在上面这个指令中,我们没有指定目的地,预设会在所在目录建立链接。
23.4.4 mkdir
建立目录。假设我们要在现行目录下建立一个目录 temp:$ mkdir temp
如果我们要建立一个目录 /tmp/abc/tmp,在是在 /tmp 下并没有 abc 这个目录,我们就必须使用参数 -p 来自动建立:$ mkdir /tmp/abc/tmp
mkdir: /tmp/abc: No such file or directory
$ $ mkdir -p /tmp/abc/tmp
23.4.5 rm
删除档案或目录。例如,我们要删除 temp 这个档案:$ rm temp
如果要删除一个目录,必须使用参数 -r:$ rm -r /tmp/abc
在删除档案或目录时,如果该档案是只读的,rm 会询问使用者是否真的要删除,我们可以使用参数 -f 让 rm 不要询问直接删除。或者我们也可以使用参数 -i 来让 rm 在删除档案时不管是否只读都要询问。
23.4.6 mv
搬移档案或目录。例如,我们要将 abc 这个档案搬到 /tmp/test:$ mv abc /tmp/test
如果在 /tmp/test 存在,而且是一个目录的话,那么 abc 会被放在 /tmp/test/abc。如果 /tmp/test 存在,而且是一个档案的话,则原来的 test 这个档案会被删除,改由 abc 取代之。
我们也可以利用 mv 来更改档案或目录名称。例如,我们要将 abc 改名为 cde:$ mv abc cde
23.4.7 df
显示磁盘使用情形。$ df
Filesystem  1K-blocks     Used    Avail Capacity  Mounted on
/dev/ad0s1a    201518   106212    79186    57%    /
/dev/ad1s1f   2595662   738200  1649810    31%    /home
/dev/ad0s1e   2761230  1615176   925156    64%    /usr
/dev/ad1s1e    503966    11546   452104     2%    /var
procfs              4        4        0   100%    /proc
如果你觉得这样的输出结果不容易了解,可以使用参数 -h。我们也可以使用参数 -i 来看 i-node 的使用状况。
23.4.8 du
磁盘使用情形统计。如果我们要看所在目录使用多少磁盘空间,可以使用 du 这个指令。和 df 指定一样,我们可以加参数 -h 来显示较易阅读的统计格式:$ du -h /etc
上述指令中,如果不加目录名称 /etc,预设是显示所在目录的使用统计。我们可以使用 du 这个指定来看系统中所有使用者的家目录使用情形:# du -sh /home/*
750M /home/jack
60M /home/mary
2M /home/john
如果我们要查出目前系统中使用磁盘空间最大的前5名使用者,我们可以利用 du 搭配 sort 指令:# du -s /home/* | sort -rn | head -5
23.4.9 chmod
改变档案目录权限。当我们使用 ls -l 时:$ $ ls -l
drwx------   2 jack  staff      512   2/27 02:14 mail/
drwxr-xr-x   2 jack  staff    77824   2/22 05:37 txts/
-rw-r--r--   1 jack  staff  1520505   3/11 23:39 myfile.txt
drwxr-xr-x  10 jack  staff      512   3/11 05:28 software/
第一个字段代表的是档案的权限。该字段中共有十个字符,第一个字符是档案的类型,其后每三个字符为一组,分别代表使用者 (User)、所属群组 (Group)、其它人 (Other) 对于该档案的存取权限。
r:可以读取,代表数字 4。
w:可以写入,代表数字 2。
x:可以执行,代表数字 1。
在使用 chmod 时,我们可以使用不同的字母来代表使用者 (User)、所属群组 (Group)、其它人 (Other):
u:User,档案的拥有者。
g:Group,拥有者所属群组。
o:Other,其它使用者。
a:All,所有人。
举例而言,如果我们要让 myfile.txt 可以让所有人读取:$ chmod a+r myfile.txt
如果我们要设定和 myfile.txt 拥有者同一个群组的人可以读取及写入该档:$ chmod g=rw myfile.txt
如果要设定移除群组对 myfile.txt 写入的权限:$ chmod g-w myfile.txt
另外,我们也可以使用数字来设定档案权限。r, w, x 都有其对映的数字,以每个使用不同对象为单位,将所对映的数字相加后所得到的数字就是该对象的权限。
图 23-1
[img]http://homepage.cqwu.net/wxfy/images/ch23_01.png[/img]
例如,使用者的权限是 rwx,则其权限为 4+2+1=7。而群组的权限是 rx,其权限为 4+1=5。其它人的权限是 r,则以数字表示为 4。我们要设定 myfile.txt 这个档案的权限:$ chmod 754 myfile.txt
我们来看一下关于目录的权限,目录的权限中,如果有 x 表示可以进入该目录,r 表示可以读取目录内容,而 w 则是可以对该目录写入。我们用下列的例子来说明目录权限的应用:$ chmod 500 mydir
$ cd mydir
$ ls
file.txt doc/ mp3/                $ cd ..
$ chmod 400 mydir
$ cd mydir
mydir: Permission denied.        $ ls mydir
file.txt doc/ mp3/                $ chmod 100 mydir
$ ls
ls: .: Permission denied       
我们上面提及的权限都是以三位数字来表示,另外我们也可以使用四位数字表示。所谓的四位数字是指在原本的三位数之前加上一个关于档案形态的设定。
数字 4,set user id (SUID)。表示该档案在执行时会以档案拥有人的身份执行。
数字 2,如果该档案可以被执行(具 x 权限),则在执行时会以拥有者群组的身份执行。如果是不能被执行的档案,在读写时会控制不能让多个程序同时存取(locked)。
数字 1,sticky。如果将档案设为所有人都可以读写,并设定 sticky,则所有人都可以修改该档案,但是不能删除。如果是目录开放读写权限,但设定了 sticky,则使用者只能新增档案,不能删除,这个可以应用于 FTP 的上传区。
假设我们要设定档案 myfile 可以被所有人读、写、执行,并设定 sticky:$ chmod 1777 myfile
23.4.10 chown
改变档案的拥有人及群组。例如,我们要将目录 temp 的拥有人设为 jack,并设定群组为 staff:# chown jack:staff temp
如果我们要将目录 temp 及其下所有档案及子目录的拥有人改变成 jack,可以使用参数 -R。
23.4.11 chflags
在 FreeBSD 还有一种特别的权限控制,称之为「flags」,这些 flags 的设定可以让我们用来保护特殊的档案。例如 /kernel 就是一个有设定 flag 的档案,我们可以使用 ls 加参数 -o 来显示:# ls -ol /kernel
-r-xr-xr-x 1 root wheel schg 2208222 2/26 02:09 kernel
flags 的设定凌驾于一般的权限设定,我们可以设定的主要 flags 及其所代表的意义如下:
[b]flags[/b]
[b]意义[/b]
nodump
档案不可以被 dump。(只有档案拥有者和 root 可以设定)
sappnd
档案只可以往后附加,不能删除。(只有 root 可以设定)
schg
档案不可以被更动,连 root 都不能删除。(只有 root 可以设定)
uappnd
档案只可以往后附加,不能删除。(档案拥有者和 root 才可设定)
uchg
档案不可以被更动。(档案拥有者和 root 才可设定)
如果我们要解除所设定的 flags 只要在上述的 flgs 之前加上 no 即可,例如 nouchg。
用法:chflags flags file
flags 的设定只有在 kernel security level 为 -1 或 0 时才可以被更改。如果 security level 为 1 或 2 时就不能更动 flags 了。
23.4.12 umask
当我们新增一个文字文件时,预设的档案权限是 644,而新增一个可执行档时,预设的权限是 755,也就是除了档案的拥有人外,其它人都可以读取或执行。这种预设权限是由 umask 来控制。
我们看一下 ~/.cshrc 的内容:
alias h history 25
alias ls ls -F
# A righteous umask
umask 22
这里的设定是 umask 22,也可以表示为 umask 022。022 这三个数字分别代表拥有者、群组、其它人的权限,建立档案是,将档案所有权限减去这些数字后,所得到的值就是档案的预设权限。
例如,一般档案权限的全部权限是 666,分别减去 022 后,得到的预设权限就是 644。而可执行档的权限是 777,分别减去 022 后,就是 755。
知道了 umask 之后,或许我们会希望将它设为 077。当然,设为 077 可能会产生一些问题,例如建立一个网页后,可能没有办法让它在使用者的浏览器中出现 (因为执行 apache 通常是以 nobody 或 www 的身份来执行)。
我们可以使用 umask 来显示目前的设定,或使用 umask num 来设定 umask:$ umask
22
$ umask 77
$ umask
77
23.4.13 diff
比较二个档案的差异。例如:$ diff file1 file2
23.4.14 wc
计算行数(lines)、字数(words)、位数(bytes)。我们可以使用这个指令来计算档案中的字数:$ wc file.txt
77 103 1076 file.txt
输出结果分别代表行数、字数、位数,我们也可以使用参数 -l, -w, -c 来指定要输的是行数、字数、位数。我们可以将 wc 和 ls 一起使用来计算档案数:$ ls /etc | wc -l
100
UNIX 指令的好处就在于我们可以自行组合指令创造出新的用法。
23.4.15 whereis
找寻程序的所在。whereis 预设会去寻找标准的二进制文件、说明文件、及原始程序代码档名符合的档案。所以我们不能用它来找一般文字文件。$ whereis netstat
netstat: /usr/bin/netstat /usr/share/man/man1/netstat.1.gz
23.4.16 which
在使用者的路径设定中寻找该程序。$ which perl
/usr/bin/perl
23.4.17 find
在指定目录下寻找档案。find 可以用的参数很多:
[b]参数[/b]
[b]说明[/b]
-name file
寻找档名为 file 的档案。
-perm mode
寻找权限为 mode 的档案。
-size n[c]
寻找档案大小为 n block 的档案。c 表示字符数。
-atime n
寻找在 n 天之前曾被存取的档案。
-mtime n
寻找在 n 天之前曾被更改时间的档案。
-ctime n
寻找在 n 天之前曾被更改内容的档案。
-newer file
寻找修改时间比 file 新的档案。
-print
找到之后,列出档名。
-exec cmd {} \;
找到之后执行 cmd 指令,在 cmd 最后一定要加上 \; 指令才会执行。如果 cmd 后有加 {} 表示执行的目录在该档案的目录。
-user name
寻找拥有者为 name 的档案。
-group name
寻找群组为 name 的档案。
-nouser
寻找使用者名称不在 /etc/passwd 中的档案。
-nogroup
寻找群组不在 /etc/group 中的档案。
-type t
寻找档案类型为 t 的档案。t 可以是下列字符之一:
b:表示 block special,例如硬盘的装置文件 /dev/ad0 就是一个 block device。
c:character special,例如鼠标的装置文件 /dev/cuaa0。
d:表示目录。
f:表示一般档案。
l:表示 symbolic link。
p:表示 FIFO。
s:表示 socket。
例如,我们要从根目录开始,找出 services 这个档案所在位置:$ find / -name service -print
如果我们要找出档案大小大于 10M 的档案:$ find / -size +10485760c -print
如果我们要从所在目录开始,找出所有扩展名为 bak 的档案,并将它删除:$ find . -name '*.bak' -exec rm {} \;
另外,-name 后面可以使用 pattern match,就是用一些名称规则。例如,我们要找扩展名为 .c、.h、或 .x 或是 .tgz 的档案:$ find . -name "*.[chx]" -o -name "*.tgz"
我们可以使用参数 -o 来代表 or 而连接多个 -name 的参数。
23.4.18 grep
找寻某一个字符串。例如,我们要找 /etc/ 下所有档案内容有 192.168 这个字符串的档案:$ grep '192.168' /etc/*
我们也可以将 grep 和其它指令一起使用,例如要找出现在执行的程序中 inetd 的 PID:$ ps -aux | grep inetd
23.4.19 tar
tape archiver。可以用来压缩备份文件。tar 的用法很多,我们仅介绍简单的压缩与解压缩。旧版的 tar 并不具有压缩功能,只是把档案包装成一个磁带文件。现在的 tar 都可以加上参数 -z 来顺便将档案压缩。
[b]参数[/b]
[b]说明[/b]
z
压缩档案。
x
取出档案。
c
建立档案。
f file
指定要处理的档案。
v
观看过程。
u
更新档案,新的档案会取代较旧的档案。
r
将档案附加在原本的 tar 档之后。
t
列出 tar 档的内容,但不真的解开。
例如,我们要将目录 temp 包装并压缩成 temp.tgz 这个档案:$ tar zcvf temp.tgz temp
要解开 temp.tgz:$ tar zxvf temp.tgz
23.4.20 fsck
检查并修复档案系统。我们可以指定要修复的档案系统,或不加任何参数来检查所有档案系统。fsck 当检查发现有问题时,预设会询问使用者是否要修复,我们也可以加参数 -y 来对于所有问题都回答 y。# fsck /dev/ad0s1e
23.4.21 mount
挂入档案系统。如果要挂入的档案系统在 /etc/fstab 中有记录,则可以不必指定来源:# mount /usr
[b]参数[/b]
[b]说明[/b]
-a
挂入所在在 /etc/fstab 文件中记录的档案系统,有参数 noauto 者除外。
-o option
设定档案系统参数。options 参数如下:
async,异步写入模式。
noexec,该档案系统上的档案不可以被执行。
nosuid,该档案系统不允许 set uid 或 set gid 的档案发生作用。
nosymfollow,在该档案系统上不可使用链接。
rdonly,该档案系统是只读的,连 root 也不可以写入。
sync,使用同步写入模式。
-t type
设定要挂入的档案系统格式。如果要挂入的格式不是内定的格式,mount 会去呼叫 /sbin/mount_XXX 的程序来使用。例如要挂入 msdos 系统时,会去使用 /sbin/mount_msdos 这个程序。常用的格式如下:
ufs,本机的 UNIX 档案格式。
nfs,Network File System。
msdos,DOS 档案格式。
isofs,CD-ROM (ISO-9660) 档案格式。
udf,DVD 所使用的 UDF 档案格式。
例如我们要挂入一个 MS-DOS 的磁盘到 /mnt 的目录中:# mount -t msdos /dev/fd0 /mnt
也可以使用 mount_msdos 指令:# muont_msdos /dev/fd0 /mnt
我们在使用 CD-ROM 之前要先将它挂入,如果是使用光盘安装 FreeBSD,在 /etc/fstab 中有 CD-ROM 的设定,我们只要执行下列指令:# mount /cdrom
如果没有,我们要知道光驱的代号,可以使用 dmesg 来查看开机记录文件中关于 CD-ROM 的讯息。假设我们的光盘代号是 cd0c,要将它挂入 /cdrom:# mount -t cd9660 /dev/cd0c /cdrom
或是:# mount_cd9660 /dev/cd0c /cdrom
23.4.22 umount
移除挂入的档案系统。只要输入 umount mount_point 即可。
CD-ROM 在挂入之后,每法取出光盘片。我们必须使用 umount 来移除才可以将光盘退出:# umount /cdrom
23.5 网络相关指令
23.5.1 ping
检查远程系统的联机状态。ping 指令会送出 ICMP 封包到指定的主机,我们可以藉此来检查网络联机品质。
常用参数如下:
[b]参数[/b]
[b]说明[/b]
-c count
指定要计算 count 次。
-s size
指定每个封包大小为 size。
-t timeout
指定 time out 时间。
-I interface
如果目标主机地址是广播地址,而且我们有多个网接口,可以指定要使用哪一个接口。
例如我们要看 [url]www.freebsd.org[/url] 的联机品质:$ ping [url]www.freebsd.org[/url]
PING freefall.freebsd.org (216.136.204.21): 56 data bytes
64 bytes from 216.136.204.21: icmp_seq=0 ttl=54 time=458.986 ms
64 bytes from 216.136.204.21: icmp_seq=1 ttl=54 time=502.258 ms
64 bytes from 216.136.204.21: icmp_seq=2 ttl=54 time=491.489 ms
^C
--- freefall.freebsd.org ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max/stddev = 458.986/484.244/502.258/18.393 ms
23.5.2 ifconfig
设定或检查网络接口。我们可以使用 ifconfig 来显示所有的网络接口,如果使用参数 -u 表示显示使用中的网络接口,而 -d 则是非运作中的接口。
我们也可以使用 ifconfig 来让网络接口运作或停用。
用法:ifconfig [down|up] interface
假设我们要让网络卡 vr0 停用:# ifconfig vr0 down
我们也可以使用 ifconfig 来设定网络上的 IP 地址。假设要设定 IP 为 192.168.0.1,而子网掩码为 255.255.255.0:# ifconfig vr0 192.168.0.1 netmask 255.255.255.0
接着再使用 ifconfig 将 vr0 启用:# ifconfig vr0 up
23.5.3 arp
显示 arp 地址。例如我们要显示 192.168.0.2 这台机器的网络卡号:$ arp 192.168.0.1
23.5.4 traceroute
追踪由本机到某台主机所使用的路径。当我们使用 ping 来检查网络联机状况时,如果发现无法联机,我们可以使用 traceroute 来检查到底是网络上的哪一台主机有问题。$ traceroute [url]www.freebsd.org[/url]
23.5.5 netstat
显示网络状况。我们可以使用 netstat 来显示目前的联机状况。例如:$ netstat -a
Active Internet connections (including servers)
Proto Recv-Q Send-Q  Local Address Foreign Address   (state)
tcp4       0     20  [url]www.ssh[/url]       198.z27z4z49.1780 ESTABLISHED
tcp4       0      0  *.http        *.*               LISTEN
tcp4       0      0  *.https       *.*               LISTEN
tcp4       0      0  *.smtp        *.*               LISTEN
tcp4       0      0  *.ssh         *.*               LISTEN
tcp4       0      0  *.pop3        *.*               LISTEN
udp4       0      0  *.syslog      *.*
udp6       0      0  *.syslog      *.*
Active UNIX domain sockets
Address  Type   Recv-Q Send-Q    Inode    Conn Refs Nextref Addr
cd864e00 dgram    0      0        0    cd84ef0   0 cd864fc0
cd864fc0 dgram    0      0        0    cd84ef0   0        0
我们可以由上面的结果看到目前有一个使用者正使用 ssh 连到我们的网站。经由上表,我们可以看出我们所提供的服务有哪些,目前的使用情形如何。如果我们希望 Foreign Address 直接显示 IP ,可以使用参数 -n。
我们也可以使用参数 -i 来查看网络接口的使用情形:
$ netstat -ai
Name  Mtu   Network       Address            Ipkts Ierrs   Opkts Oerrs  Coll
dc0   1500      00:80:c8:f6:b2:66 68890922 15997 8370716  1256 60296
                        33:33:c0:f6:78:e9
dc0   1500  fe80:1::280 fe80:1::281:c8ff:        0     -       0     -     -
                        ff02:1::2:c1f7:78e9(refs: 1)
                        ff02:1::1          (refs: 1)
                        ff02:1::1:ffe7:b266(refs: 1)
lp0*  1500                                       0     0       0     0     0
lo0   16384                                  34050     0   34050     0     0
我们简单说明一下各字段所代表的意义:
Name:设备的名称。
Mtu:最大的传送单元(unit)。
Network:此接口所提供的网络或目的地主机。
Address:接口的地址。
Ipkts:表示接收到的封包。
Ierrs:表示接收到但破损的封包数量。
Opkts:表示送出的封包。
Oerrs:表示送出但破损的封包。
Coll:表示发生碰撞 (Collision) 次数。当网络负荷量大时,封包送出时较易发生碰撞,碰撞产生时,系统会等待一段时间尝试再次送出封包。碰撞次数越多,联机品质越差。
23.5.6 sockstat
列出开启中的 socket。$ sockstat
USER     COMMAND   PID  FD PROTO  LOCAL ADDRESS  FOREIGN ADDRESS
root     telnetd 52897   0 tcp4   192.168.0.1:23 192.168.0.2:1969
root     sshd    34063   4 tcp4   *:22           *:*
nobody   httpd   11670  16 tcp4   *:443          *:*
nobody   httpd   11670  17 tcp4   *:80           *:*
root     sendmail  117   4 tcp4   *:25           *:*
root     sendmail  117   5 tcp4   *:587          *:*
root     inetd     109   4 tcp4   *:21           *:*
USER     COMMAND    PID   FD PROTO  ADDRESS
mysql    mysqld     170    6 stream /tmp/mysql.sock
root     sendmail   117    3 dgram  syslogd[100]:3
root     syslogd    100    3 dgram  /var/run/log
每个字段所代表的意义如下:
USER:哪个使用者开启的 socket。
COMMAND:经由哪一个指令。
PID:该指令的 process ID 是多少。
DF:socket 的 file descriptor number。
PROTO:哪一种协定。
LOCAL ADDRESS:本地的地址及 port (Internet sockets only)。
FOREIGN ADDRESS:来源的地址及 port (Internet sockets only)。
ADDRESS:socket 开启的档案或目标程序(UNIX sockets only)。
23.5.7 mail
邮件处理程序。古老的 UNIX 邮件处理程序,这个程序对于不熟悉的人使用起来可能有点困难。但是这是在每个 UNIX 系统中都会有的程序,有时在没有其它选择的状况下,我们还是要使用它,至少要知道如何用它来收发信件。
假设我们要寄信给本机的 root:$ mail root
如果我们要寄信给非本机的使用者,可以使用的收件人格式如下:
[url=mailto:user@cc.ncu.edu.tw]user@cc.ncu.edu.tw[/url]

user@\[140.115.1.13\]
执行了 mail 之后,程序会先要求我们输入邮件主旨,输入后就可以开始打本文了。当完成本文的编辑之后,可以按 Ctrl+D 来将信件送出,或是按二次 Ctrl+C 取消。
我们也可以在执行 mail 时加上参数 -s "subject" 来指定主旨:$ mail -s"hi, my friend" [email]jack@mymail.com[/email]
如果我们想要将一个文字文件的内容当做本文送出,例如,我们可以先编辑一个文字文件 content.txt,接着使用下列方式:$ mail -s "hi, my friend" [email]jack@mymail.com[/email]
说完了寄信,我们来了解一下如何收信。我们可以打 mail 来收信,如果是 root 还可以使用 mail -u user 来收使用者 user 的信件。$ mail
"/var/mail/root": 12 messages 10 unread
>U  1 jack         Fri Feb 22 03:02  42/690   "Hi friend"
U  2 jack         Fri Feb 22 03:02  74/2620  "see you tomorrow"
U  3 [email]mary@abc.com[/email] Sat Feb 23 03:06 570/33527 "don't forget"
&
最后面出现的 & 为 mail 程序命令列的提示符号,在第一封信件开头有一个符号 ">" 表示目前作用中的信件。我们可以直接输入邮件编号来读取信件。另外,我们也可以输入下列指令:
[b]指令[/b]
[b]说明[/b]
h
列出所有信件。
r
回复目前作用中的信件。
n
读取下一封信件。
p
读取前一封信件。
pre [mail number]
保留编号为 mail number 的信件在系统的 mailbox中 (/var/mail/)。程序 mail 对于己读取的信件,预设会将它搬到使用者家目录下的 mbox 中。我们如果日后还想要使用 pop3 来收该信件,就必须使用 pre 将该信件保留在系统的邮件目录中。
d
删除作用中的信件。
z
显示下一页信件列表。
q
离开 mail。
23.5.8 telnnet
使用终端机远程登入网络上的主机。例如:$ telnet bbs.mgt.ncu.edu.tw
如果在 telnet 时要能输入中文,必须加上参数 -8:$ telnet -8 bbs.mgt.ncu.edu.tw
23.5.9 ssh
使用 telnet 并未加数据加密,我们很容易在不知不觉中泄露信息。如果要登入的主机有提供 ssh 登入的话,最好使用 ssh。
用法:ssh username@hostname
ssh hostname
例如:$ ssh mary@140.115.77.11
$ ssh [email]jack@mydomain.com[/email]
$ ssh mydomain.com
只打 hostname 而没有使用者名称,登入名称会是你目前所用的使用者名称。
如果所联机的主机是第一次联机会出现下列一堆东西,打 "yes" 三个字即可:The authenticity of host '140.115.77.11' can't be established.
RSA key fingerprint is 13:93:8a:61:31:df:41:3f:7a:0a:77:ad:7e:49:e7:3f.
Are you sure you want to continue connecting (yes/no)? yes
23.5.10 ftp
档案传输程序。如果要登入的主机允许昵名登入,我们使用参数 -a 来自动登入。$ ftp -a freebsd.csie.nctu.edu.tw
进入 ftp 之后,会出现命令的提示列。我们可以输入以下的指令:
[b]指令[/b]
[b]说明[/b]
help 或 ?
显示可以使用的指令。
ls
列出远程所在目录的档案。
pwd
显示远程所目录位置。
cd dir
进入远程的 dir 目录。
get file
从远程取回 file 档案。
put file
将本地端的 file 档案上传到远程机器。
acsii
使用文字模式传送档案。
binary
使用二进制模式传送档案。
bye
结束 ftp。
mget *.tgz
取回远程所有名称为 *.tgz 的档案。
mput *.tgz
上传本地所有 *.tgz 的档案。
!ls
显示本地所在目录下的档案。
lpwd 或 !pwd
显示本地所在目录。
lcd [dir]
切换本地所在目录。
23.5.11 nslookup
网络主机名称查询。如果我们要查询 [url]www.freebsd.org[/url] 所对映的 IP,最简单的用法是:$ nslookup [url]www.freebsd.org[/url]
我们也可以在上述指令最后面加上要查询的 DNS 主机:$ nslookup [url]www.freebsd.org[/url] dns.hinet.net
我们也可以使用 IP 来进入反查:$ nslookup 216.136.204.21
23.5.12 dig
是另一个功能强大的主机名称查询工具。简单的用法如下:$ dig -x 216.136.204.21
$ dig [url]www.freebsd.org[/url]
23.5.13 tcpdump
显示或记录网络封包。如果要使用 tcpdump,在核心中必须要有 Berkeley packet filter,而且有 /dev/bpf*。如果没有请在核心设定中加入下面这一行,并重新编辑核心:
pseudo-device bpf
执行 tcpdump 后,它会打开指定接口的 promiscuous mode (接口必须支持才有用)。所谓的 promiscuous mode(杂乱模式) 是指不管是否和本机有关的封包都接收进来,要达到这样的效果,必须藉由 bpf 的支持。
我们可以使用 tcpdump 来观察到达某一个网络接口的封包。例如我们要监看接口 vr0 的封包:# tcpdump -i vr0
如果要结束直接按 Ctrl+C 即可。 如果限制封包数量,可以使用参数 -c。我们也可以使用参数 -w 来将捕捉到的封包存成档案,在这里我们存成 dump 这个档案:# tcpdump -c 20 -i vr0 -w dump
使用参数 -r 可以读取储存的封包数据:# tcpdump -r dump
为了控制 tcpdump 能 dump 我们想要的封包,我们还可以在指令最后加上一些 expression 来控制封包的记录。关于 expression 的用法请 man tcpdump。
另外介绍一个好用的分析工具 tcpshow, 我们可以使用 ports 来安装。# cd /usr/ports/net/tcpshow
# make install clean
接着就可以使用 tcpshow 来分析我们储存的封包内容:# tcpshow
---------------------------------------------------------------
Packet 8
TIME:   04:53:10.938750 (0.011744)
LINK:   00:80:2D:BB:65:38 -> 00:50:AA:00:DC:DD type=IP
  IP:   tw -> 189 hlen=20 TOS=00 dgramlen=44 id=4353
        MF/DF=0/1 frag=0 TTL=52 proto=TCP cksum=C56B
TCP:   port http -> 2451 seq=3298970558 ack=2899053999
        hlen=24 (data=0) UAPRSF=010010 wnd=65535 cksum=8549 urg=0
DATA:   
---------------------------------------------------------------
我们简单的说明一下这个封包的内容。第一部份是时间 TIME。
第二行是 LINK,显示了来源 -> 目的地的网络卡号,另外经由 type=IP,我们知道这是一个 Ethernet_II 的 frame。
第三部份 IP,tw -> 189 是来源及目的地的地址。hlen 是 header length 大小是 20 bytes,而整个 IP 封包 (dgramlen) 的大小是 44 bytes。
第四部份是 TCP,来源是的 port 是 http (内定是 80),而目的地的 port 是 2451。接下来是 TCP 封包的 sequence number 及 acknowledgement 编号。TCP 的 header length 是 24,加上 IP 的 header 20 长度刚好是 44,和 dgramlen 的长度一样,这个封包应该没有破损。
最后,这个封包并没有包含其它的数据。

逍遥 发表于 2006-6-5 15:30

第二十四章 Shell Script
身为 UNIX 系统管理者除了要熟悉 UNIX 指令外,我们最好学会几种 scripts 语言,例如 shell script 或 perl。学会 script 语言后,我们就可以将日常的系统管理工作写成一支执行档,如此一来,在管理系统时就可以更加灵活。
Shell script 是最基本的 script 语言,它是一堆 UNIX 指令的集合。本章将介绍 Shell script 的基本功能及语法,期望读者可以经由学习 Shell scripts 让使用 UNIX 系统时可以更加得心应手。
24.1 概论
Shell Script 是一个类似 MS Windows 中 .bat 档的东西,简单的说,Shell Script 就是将一堆 shell 中的指令放在一个文字文件中来执行。因此,为了能写出一个 shell Script,你必须先对 UNIX 指令有初步的认识。身为一个 UNIX 系统的管理者,一定要会使用 shell script 来使管理工作更加容易。
一般我们会将 Shell Script 的扩展名命名为 .sh,但并非一定要这么做,这样做只是为了要让我们更容易管理这些档案。在介绍如何 Shell Script 的内容之前,我们先来看如何写出一个 Shell Script 并执行它。假设我们要写一个名为 test.sh 的 Shell Script,首先用你习惯使用的文字编辑软件来开一个文件名为 test.sh 内容如下:
#!/bin/sh
echo Hello world!!
第一行是必需的,用来定义你要使用的 shell。这里我们定义要使用的是 Bourne Shell,其所在路径是 /bin/sh。在 UNIX 系统中有许多不同的 Shell 可以使用,而每个 Shell 的特性及用法都有些许的不同。因此,在写 Shell Script 时,我们会针对 Bourne Shell (sh) 来写,因为 sh 是所有 UNIX 系统中都会有的 Shell。就算你执行 Shell Script 时的环境不是使用 sh,只要加上第一行 #!/bin/sh 就可以在执行此 Shell Script 时使用 sh。而第二行的 echo 代表列出一个字符串,我们常使用它来输出信息。将 test.sh 存盘后,我们就可以用下列其中一种方式执行它:
1. 转向输入$ sh
2. 如果要输入参数的话,第一种方式便不适用,可以改用这种方法。 就是我们要输入的参数,在上面的 test.sh 中并不需要输入参数:$ sh test.sh
3.你也可以改变 test.sh 的权限,将它变成可以独立执行的档案,这样就可以只打 test.sh 来执行它:$ chmod a+x test.sh
$ ./test.sh
在 Shell Script 中,你们可以使用 # 为批注,在 # 后面的字符串都将被视为批注而被式忽略。而分号 ; 则代表新的一行,例如打 ls;ls -d 代表二个指令。另外,我们可以使用变量、流程控制、甚至是副函式来使程序更加灵活。以下的各章节我们会详细加以说明。
24.2 变量的使用
24.2.1 变量的使用
我们知道 Shell Script 是使用一堆指令拼凑而成,为了方便说明及练习起见,我们不使用编辑档案的方式来执行,而改以在命令列中打我们要的指令。首先,先打 sh 来进入 Bourne Shell。% sh
$
在打了 sh 之后,会进入 Bourne Shell,其一般使用者的提示字符为 $。以下各指令开头的 $ 表示提示字符,而 $ 之后的粗体字才是我们输入的字符串。
在 Shell Script 中,所有的变量都视为字符串,因此并不需要在定义变量前先定义变量类型。在 Shell 中定义和使用变量时有些许的差异。例如,我们定义一个变量 color 并令它的值为 red,接着使用 echo 来印出变量 color 的值:$ color=red
$ echo $color
red
在这里,以 color=red 来定义变量 color 的值为 red,并以 echo $color 来印出 color 这一个变数。在定义变量时,不必加 $,但是在使用它时,必须加上 $。请注意,在等号的二边不可以有空白,否则将出现错误 ,系统会误以为你要执行一个指令。
我们再介绍一个范例:$ docpath=/home/td/src/doc
$ echo $docpath
/home/td/src/doc
$ ls $docpath
abc.txt abc2.txt semmt.doc
$ ls $docpaht/*.txt
abc.txt abc2.txt
这里我们定义了变量 docpath 的值为 /home/td/src/doc,并印出它。接着我们使用 ls 这个指令来印出变量 docpath 目录中所有档案。再以 ls $docpath/*.txt 来印出 /home/td/src/doc/ 目录下所有扩展名为 .txt 的档案。
我们再来看一个例子,说明如何使用变量来定义变量:$ tmppath=/tmp
$ tmpfile=$tmppath/abc.txt
$ echo $tmpfile
/tmp/abc.txt
另外,我们也可以使用指令输出成为变量,请注意这里使用的二个 ` 是位于键盘左上角的 ` ,在 shell script 中,使用 ` 包起来的代表执行该指令:$ now=`date`
$ echo $now
Mon Jan 14 09:30:14 CST 2002
如果在变量之后有其它字符串时,要使用下列方式来使用变量:$ light=dark
$ echo ${light}blue
darkblue
$ echo "$light"blue
darkblue
这里双引号中的字将会被程序解读,如果是使用单引号将直接印出 $light 而非 dark。
经由上面几个简单的例子,相信您对变量的使用已有初步的认识。另外有一些我们必须注意的事情:$ color=blue
$ echo $color
blue
$ echo "$color"
blue
$ echo '$color'
$color
$ echo \$color
$color
$ echo one two three
one two three
$ echo "one two three"
one two three
我们可以看到上面各个执行结果不大相同。在 Shell Script 中,双引号 " 内容中的特殊字符不会被忽略,而单引号中的所有特殊字符将被忽略。另外,\ 之后的一个字符将被视为普通字符串。
如果您希望使用者能在程序执行到一半时输入一个变量的值,您可以使用 read 这个指令。请看以下的范例:
#!/bin/sh
printf "Please input your name:"
read Name
echo "Your name is $Name"
由于 echo 指令内定会自动换行,所以我们使用 printf 这个指令来输出字符串。我们将上述内容存成档案 input.sh,接着使用下列指令来执行:$ sh input.sh
Please input your name:Alex
Your name is Alex
您可以看到变量 Name 已被设为您所输入的字符串了。
24.2.2 程序会自动定义的变量
在执行 Shell Script 时,程序会自动产生一些变量:
[b]变量名称[/b]
[b]说明[/b]
$?
表示上一个指令的离开状况,一般指令正常离开会传回 0。不正常离开则会传回 1、2 等数值。
$$
这一个 shell 的 process ID number
$!
最后一个在背景执行的程序的 process number
$-
这个参数包含了传递给 shell 旗标 (flag)。
$1
代表第一个参数,$2 则为第二个参数,依此类推。而 $0 为这个 shell script 的档名。
$#
执行时,给这个 Shell Script 参数的个数
$*
包含所有输入的参数,$@ 即代表 $1, $2,....直到所有参数结束。$* 将所有参数无间隔的连在一起,存成一个单一的参数。也就是说 $* 代表了 "$1 $2 $3..."。
$@
包含所有输入的参数,$@ 即代表 $1, $2,....直到所有参数结束。$@ 用将所有参数以空白为间隔,存在 $@ 中。也就是说 $@ 代表了 "$1" "$2" "$3"....。
以下我们举几个例子来说明:$ ls -d /home
/home
$ echo $?
0
$ ls /home/aaa/bb/ccc
/home/aaa/bb/cc: No such file or directory
$ echo $?
2
$ echo $?
0
上面例子中的第一行是 ls,我们可以看到存在一个目录 /home,接者 echo $? 时,出现 0 表示上一次的命令正常结束。接着我们 ls 一个不存在的目录,再看 $? 这个变量变成 2,表示上一次执行离开的结果不正常。最后一个 echo $? 所得到的结果是 0,因为上一次执行 echo 正常显示 2。
如果写一个文件名为 abc.sh,内容如下:
#!/bin/sh
echo $#: $1 $2 $3 $4 $5 $6 $7 $8 $9
echo $@
接着以下列指令来执行该档案:$ chmod a+x abc.sh
$ ./abc.sh a "b c d" e f
4:a b c d e f
a b c d e f
上面最后二行即为执行结果。我们可以看到 $# 即为参数的个数,而 $1, $2, $3...分别代表了输入的参数 "a", "b c d", "e", "f",而最后的 $@ 则是所有参数。
24.2.3 系统内定的标准变量
你可以使用 set 这个指令来看目前系统中内定了哪些参数。一般而言会有 $HOME, $SHELL, $USER, $PATH 等。$ echo $HOME
/home/jack
$ echo $PATH
/usr/bin:/usr/sbin:/bin
24.2.4 空变量的处理
如果程序执行时,有一个变量的值尚未被给定,你可以利用下列方式来设定对于这种情形提出警告:$ echo $number one
one
$ set -u
$ echo $number one
sh: ERROR: number: Parameter not set
在 set -u 之后,如果变量尚未设定,则会提出警告。你也可以利用下列的方式来处理一些空变量及变量的代换:
[b]表达式[/b]
[b]说明[/b]
${var:-word}
如果变量 var 尚未设定或是 null,则将使用 word 这个值,但不改变 var 变量的内容。
${var:=word}
如果变量 var 尚未设定或是 null,则变量 var 的内容将等于 word 这个字符串,并使用这个新的值。
${var:?word}
如果变量 var 已经设定了,而且不是 null,则将使用变量 var。否则则印出 word 这个字符串,并强制离开程序。我们可以设定一个字符串 "Parameter null or not set" 来在变量未设定时印出,并终止程序。
${var:+word}
如果变量 var 已经设定了,而且不是 null,则以 word 这个字符串取代它,否则就不取代。
我们以下面的例子来说明:$ echo $name Wang
Wang
$ echo ${name:-Jack} Wang
Jack Wang
$ echo $name Wang
Wang
上面的例子中,变数 $name 并未被取代,而下面的例子中,$name 将被取代:$ echo $name Wang
Wang
$ echo ${name:=Jack} Wang
Jack Wang
$ echo $name Wang
Jack Wang
24.3 运算符号
24.3.1 四则运算
在 shell 中的四则运算必须使用 expr 这个指令来辅助。因为这是一个指令,所以如果要将结果指定给变量,必须使用 ` 包起来。请注意,在 + - * / 的二边都有空白,如果没有空白将产生错误:$ expr 5 -2
3
$ sum=`expr 5 + 10`
$ echo $sum
15
$ sum=`expr $sum / 3`
$ echo $sum
5
还有一个要特别注意的是乘号 * 在用 expr 运算时,不可只写 *。因为 * 有其它意义,所以要使用 \* 来代表。另外,也可以用 % 来求余数。$ count=`expr 5 \* 3`
$ echo $count
$ echo `expr $count % 3`
5
我们再列出更多使用 expr 指令的方式,下列表中为可以放在指令 expr 之后的表达式。有的符号有特殊意义,必须以 \ 将它的特殊意义去除,例如 \*,否则必须用单引号将它括起来,如 '*':
[b]类别[/b]
[b]语法[/b]
[b]说明[/b]
条件判断
expr1 \| expr2
如果 expr1 不是零或 null 则传回 expr1,否则传回 expr2。
expr1 \& expr2
如果 expr1 及 expr2 都不为零或 null,则传回 expr1,否则传回 0。
四则运算
expr1 + expr2
传回 expr1 加 expr2 后的值。
expr1 - expr2
传回 expr1 减 expr2 后的值。
expr1\* expr2
传回 expr1 乘 expr2 后的值。
expr1 / expr2
传回 expr1 除 expr2 后的值。
expr1 % expr2
传回 expr1 除 expr2 的余数。
大小判断
expr1 \> expr2
如果 expr1 大于 expr2 则传回 1,否则传回 0。如果 expr1 及 expr2 都是数字,则是以数字大小判断,否则是以文字判断。以下皆同。
expr1 \
如果 expr1 小于 expr2 则传回 1,否则传回 0。
expr1 = expr2
如果 expr1 等于 expr2 则传回 1,否则传回 0。
expr1 != expr2
如果 expr1 不等于 expr2 则传回 1,否则传回 0。
expr1 \>= expr2
如果 expr1 大于或等于 expr2 则传回 1,否则传回 0。
expr1 \
如果 expr1 小于或等于 expr2 则传回 1,否则传回 0。
文字处理
expr1 : expr2
比较一固定字符串,即 regular expression。可以使用下列字符来辅助:
. 匹配一个字符。
$ 找字符串的结尾。
[list] 找符合 list 中的任何字符串。
* 找寻 0 个或一个以上在 * 之前的字。
\( \) 传回括号中所匹配的字符串。
我们针对比较复杂的文字处理部份再加以举例:$ tty
ttyp0
$ expr `tty` : ".*\(..\)\$"
p0
$ expr `tty` : '.*\(..\)$'
p0
上面执行 tty 的结果是 ttyp0,而在 expr 中,在 : 右侧的表达式中,先找 .* 表示0个或一个以上任何字符,传回之后在结尾 ($) 时的二个字符 \(..\)。在第一个 expr 的式子中,因为使用双引号,所以在 $ 之前要用一个 \ 来去除 $ 的特殊意义,而第二个 expr 是使用单引号,在单引号内的字都失去了特殊意义,所以在 $ 之前不必加 \。
除了使用 expr 外,我们还可以使用下列这种特殊语法:$ a=10
$ b=5
$ c=$((${a}+${b}))
$ echo $c
15
$ c=$((${a}*${b}))
$ echo $c
50
我们可以使用 $(()) 将表达式放在括号中,即可达到运算的功能。
24.3.2 简单的条件判断
最简单的条件判断是以 && 及 || 这二个符号来表示。$ ls /home && echo found
found
$ ls /dev/aaaa && echo found
ls: /dev/aaaa: No such file or directory
$ ls -d /home || echo not found
/home
$ ls /dev/aaaa && echo not found
ls: /dev/aaaa: No such file or directory
[b]条件式[/b]
[b]说明[/b]
a && b
如果 a 是真,则执行 b。如果 a 是假,则不执行 b。
a || b
如果 a 是假,则执行 b。如果 a 是真,则不执行 b。
24.3.3 以 test 来比较字符串及数字
我们说过 Shell Script 是一堆指令的组合,所以在比较字符串及数字时一样是经由系统指令来达成。这里我们使用 test 及 [ 来做运算,运算所传回的结果是真 (true) 或假 ( false)。我们可以将它应用在条件判断上。test 和 [ 都是一个指令,我们可以使用 test 并在其后加上下表中的参数来判断真假。或者也可以使用 [ 表达式 ] 来替代 test,要注意的是 [ ] 中的空白间隔。
[b]表达式[/b]
[b]说明[/b]
-n str1
如果字符串 str1 的长度大于 0 则传回 true。
-z str1
如果字符串 str1 的长度等于 0 则传回 true。
str1
如果字符串 str1 不是 null 则传回 true。
str1 = str2
如果 str1 等于 str2 则传回 true。等号二边有空白。
str1 != str2
如果 str1 不等于 str2 则传回 true。!= 的二边有空白。
a -eq b
Equal,等于。a 等于 b 则传回真 (true)。
a -ne b
Not equal,不等于。a 不等于 b 则传回真 (true)。
a -gt b
Grwater than,大于。a 大于 b 则传回真 (true)。
a -lt b
Less Than,小于。a 小于 b 则传回真 (true)。
a -ge b
Greater or equal,大于或等于。a 大于或等于 b 则传回真 (true)。
a -le b
Less or equal,小于或等于。a 小于或等于 b 则传回真 (true)。
我们举例来说明:$ test 5 -eq 5 && echo true
true
$ test abc!=cde && echo true
ture
$ [ 6 -lt 10 ] && echo true
ture
$ pwd
/home
$ echo $HOME
/home/jack
$ [ $HOME = `pwd` ] || echo Not home now
Not home now
24.3.4 以 test 来处理档案
我们也可以使用 test 及 [ 来判断一个档案的类型。下表中为其参数:
[b]用法[/b]
[b]说明[/b]
-d file
如果 file 为目录则传回真(true)。
-f file
如果 file 是一般的档案则传回真(true)。
-L file
如果 file 是连结档则传回真(true)。
-b file
如果 file 是区块特别档则传回真(true)。
-c file
如果 file 是字符特别文件则传回真(true)。
-u file
如果file 的 SUID 己设定则传回真(true)。
-g file
如果file 的 SGID 己设定则传回真(true)。
-k file
如果file 的 sticky bit 己设定则传回真(true)。
-s file
如果 file 的档案长度大于 0 则传回真(true)。
-r file
如果 file 可以读则传回真(true)。
-w file
如果 file 可以写则传回真(true)。
-x file
如果 file 可以执行则传回真(true)。
我们举例来说明:$ [ -d /bin ] && echo /bin is a directory
/bin is a directory
$ test -r /etc/motd && echo /etc/motd is readable
/etc/motd is readable
第一个指令测试 /bin 是否存在,而且是一个目录,如果是则执行 echo 传回一个字符串。第二个指令是测试 /etc/motd 是否可以被读取,如果是则执行 echo 传回一个字符串。
24.4 内建指令
在 Shell 中有一些内建的指令,这些内建的指令如流程控制及 cd 等指令是 Shell 中的必备元素。另外还有一些为了提高执行效率的指令,如 test、echo 等。有的内建指令在系统中也有同样名称不同版本的相同指令,但是如 test、echo 等在执行时会伪装成是在 /bin 中的指令。
在写 shell script 时,要注意指令是否存在。下列即为常见的内建指令:
[b]指令[/b]
[b]说明[/b]
exit
离开程序,如果在 exit 之后有加上数字,表示传回值,如:exit 0。在 UNIX 系统下,当程序正常结束,会传回一个值 0,如果不正常结束则会传回一个非 0 的数字。
. file
dot 指令,在 shell 中可以使用 "." 来呼叫一个外部档案,例如 . /etc/rc.conf 或 . .profile。注意 . 和其后的指令中间有空白。
echo
印出一个字符串。如果要使用非 shell 内建的 echo 则打 /bin/echo 来使用。
pwd
显示目前所在目录。
read var ...
从标准输入 (通常是键盘) 读入一行,然后将第一个字指派给跟在 read 之后的第一个参数,第二个字给第二个参数,依此类推,直到最后将所有字给最后一个参数。如果只有一个参数则将整行都给第一个参数。
readonly [var..]
readonly 这个指令如果没有加参数则显示目前只读的变量。如果有加变量的话,则将该变量设定为只读。
return [n]
离开所在函式,如果在其后有加数字的话,则传回该数字。和 exit 一样,这个指令可以传回该函式的执行结果,0 表示正常结束。
set
将 $1 到 $n 设定为其参数的字。例如:
$ date
Mon Jan 21 11:19 CST 2002
$ set `date`
$ echo $4
11:19
wait [n]
等待在执行程序 (PID) 为 n 的背景程序结束,如果没有加参数 n 则等待所有背景程序结束。
exec command
执行一个外部程序,通常用于要改变到另一个 shell 或是执行不同的使用者者接口,如:
exec /usr/local/bin/startkde
export [var]
设定环境变量,如果没有参数则印出新的环境变量。
eval command
把参数当成 shell 命令来执行,如:
$ a=c; b=m; c=d; cmd=date
$ eval $`echo $a$b$c`
Mon Jan 21 11:19 CST 2002
24.5 流程控制
24.5.1 if 的条件判断
基本语法:
[b]if[/b] condition-list
      [b]then[/b] list
[b]elif[/b] condition-list
      then list
[b]else[/b] list
[b]fi[/b]
范例一:
#!/bin/sh
if test -r /etc/motd
      then cat /etc/motd
else  echo "There is not motd or file is not readable"
fi
说明:上面这一个程序是检查 /etc/motd 这个档案是否可以读,如果可以则印出该档案,否则印出档案不可读。
范例二:$ ee test.sh
#!/bin/sh
if [ $1 -gt 5 ]
      then echo " $1 is bigger then 5"
elif [ $1 -ge 0 ]
      then echo " $1 is between 5 and 0. "
else echo "$1 is less then 0."
fi$ chmod a+x test.sh
$ ./test.sh 3
3 is between 5 and 0.
说明:这里我们建立一个档名为 test.sh 的档案,以指令 cat test.sh 来看它的内容。接着执行 ./test.sh 3,表示输入一个参数 3。test.sh 档案的内容表示依输入的参数判断参数大于 5 或介于 5 和 0 的中间,或者是小于 0。
24.5.2 while 及 until 循环
基本语法:
[b]while[/b] condition-list
   [b]do[/b] list
   [b]done[/b]
[b]until[/b] condition-list
   [b]do[/b] list
   [b]done[/b]
范例一:
#!/bin/sh
i=1
while [ $i -le 5 ]
   do
       echo $i
       i=`expr $i + 1`
   done
说明:首先令变量 i=1,接着在循环中当 i 小于等于 5 时就印出 i 的值,每印一次 i 就加 1。直到 i 大于 5 才停止。
范例二:
#!/bin/sh
i=1
until [ $i -gt 5 ]
   do
       echo $i
       i=`expr $i + 1`
   done
说明:首先令变量 i=1,接着循环会判断,一直执行到 i 大于 5 才停止。每跑一次循环就印出 i 的值,每印一次 i 就加 1。注意 while 和 until 的判断式中,一个是 -le ,一个是 -gt。
24.5.3 for 循环
基本语法:
[b]for[/b] name [b]in[/b] word1 word2 …
   [b]do[/b] do-list
   [b]done[/b]
[b]for[/b] name
   [b]do[/b] do-list
   [b]done[/b]
范例一:$ ee color1.sh
#!/bin/sh
for color in blue red green
    do
       echo $color
    done$ chmod a+x color1.sh
$ ./color1.sh
blue
red
green
说明:这个档案 color1.sh 中,会在每一次循环中将关键词 in 后面的字符串分配给变量 color,然后印出变量 color。关键词 in 让我们可以依序设定一些值并指派给变量,然而,我们也可以不使用关键词 in。如果没有关键词 in ,程序会自动读取输入的参数,并依序指派给 for 之后的变量。请看范例二。
范例二:$ ee color2.sh
#!/bin/sh
for color
    do
       echo $color
    done$ chmod a+x color2.sh
$ ./color2.sh black green yellow
black
green
yellow
说明:在 color2.sh 这个档中,for 循环没有使用 in 这个关键词。但我们在执行它时输入三个参数,循环会自动将输入的参数指派给 for 之后的变量 color,并印出它。
24.5.4 case 判断
基本语法:
[b]case[/b] word [b]in[/b]
    pattern1[b])[/b] list1 ;;
    pattern2[b])[/b] list2 ;;
    …
[b]esac[/b]
范例:$ ee num.sh
for num
do
   case $num in
       0|1|2|3)       echo $num is between 0~3;;
       4|5|6|7)       echo $num is between 4~7;;
       8|9)           echo $num is 8 or 9;;
       *)             echo $num is not on my list;;
    esac
done$ chmod a+x num.sh
$ ./num.sh 3 8 a
3 is between 0~3
8 is 8 or 9
a is not on my list
说明:这个程序是用来判断输入的参数大小。for 循环会将每一个输入的参数指定给变量 num,而在 case 中,判断变量 num 的内容符合哪一个条件,同一个条件中的每个字用 | 分开。如果未符上面的条件则一定会符合最后一个条件 * 。每一个要执行的 list 是以 ;; 做结尾,如果有多行 list,只要在最后一行加上一个 ;; 即可。
24.6 函式的运用
在 Shell Script 中也可以使用函式 (function) 来使用程序模块化。
基本语法:
name ( )
{
    statement
}
函式有几个要注意的地方:
在使用函式之前一定要先定义它,也就是在一个 Shell Script 中,一定要先写函式的内容,在档案最后再写会呼叫函式的程序部份。
在 Shell Script 中的变量全部都是全域变量 (Global),所以在函式中的变量也会影响函式外的其它部份。
命令列输入的参数在 Shell Script 中是以 $1, $2....来读取,但是这些参数并不会在函式中出现。所以必须使用传递参数的方式来将要在函式中使用的变量传给该函式。传递的方法和在命令列中使用 Shell Script 的方式一样,例如:name arg1 arg2..。传进函式的变数会以 $1,$2... 来储存,这和命令列传给 Shell Script 的参数名称一样但内容不同。
范例:$ ee test.sh
#! /bin/sh
ERRLOG=$1
ok ( )
{
      read ans
      case $ans in
           [yY]*) return 0;;
           *) return 1;;
      esac
}
errexit ( )
{
      echo $1
      date >> $ERRLOG
      echo $1 >> $ERRLOG
      exit
}
echo -n  "Test errexit function [y/n] "
ok && errexit "Testing the errexit function"
echo Normal termination
$ chmod a+x test.sh
$ ./test.sh err.log
说明:
这个程序中有二个函式:errexit 及 ok。第一行定义要将 log 档存在传给这个 Shell Script 的第一个参数。接着是二个函式,之后印出一行字,echo -n 表示印出字后游标不换行。然后再执行 ok 这个函式,如果 ok 函式执行成功则再执行 errexit 函式,并传给 errexit 函式一个字符串,最后再印出一个字符串。
在 ok 函式中,使用 read 指令来读入一个参数并指派给变数 ans。接着判断使用者输入的值是否为 Y 或 y,如果是则传回 1 代表没有成功执行,如果不是则传回 0 代表成功执行函式 ok。
如果 ok 函式传回 1 便不会执行 errexit 函式。如果是 0 则在 errexit 函式中,会先印出要传给 errexit 的参数 " Testing the errexit function",并记录在指定的档案中。

逍遥 发表于 2006-6-5 15:32

附录 A /etc 目录下的档案介绍
/etc 是 FreeBSD 系统主要设定文件所在,了解这个目录下的档案及其格式,对于我们管理及使用 FreeBSD 将有更深入的认识。因此,以下我们就分别说明一下这些档案。
一个个读这些设定档的说明也许有点枯燥,因此,我们将这个章节放在附录中,您可以在有需要时再来参考即可。
A.1 aliases:设定邮件收件者别名
/etc/aliases 是用以告知 sendmail 要将信转给哪个使用者或是交由哪个程序处理。请注意,修改完这个档案后,必须使用指令 newaliases 来让所做的修改在 sendmail 中发生作用。这个档案是用来设定邮件的别名,也就是可以设定要将某人的信件转给其它地方(人员或程序)。你也可以将某人的信转给很多人,这个档案的位置是由 sendmail.cf 档案中的 AliasFile 这个选项所决定的。当 sendmail 收到信时,会一行一行比对,当第一行符合后,就不会再继续下去,所以应注意优先级。
本档案的语法开头的 "#" 代表该行是批注,大小写都视为一样。以下为几个设定的范例:
root: alex
webmanager: alex,jack,[email]jim@other.hostname.com[/email]
nobody: /dev/null
homework: |/usr/local/bin/homework.sh
olduser: :include: /usr/local/olduser_list
范例 1 是将寄给 root 的信转给本机中的使用者 alex。
范例 2 是将寄给 webmanager 的信转给本地的使用者 alex,jack及别地的 [email]jim@other.hostname.com[/email]。
范例 3 是将寄给 nobody 的信直接丢掉,丢入 /dev/null 这个无底深渊,也就是所有给 nobody 的信都直接删除。
范例 4 是将寄给 homework 的信交给 /usr/local/bin/homework.sh 这支程序处理。
范例 5 是将寄给 olduser 的信转给档案 /usr/local/olduser_list中所列出的所有使用者。olduser_list 为使用者清单的文字文件。
当设定了一堆复杂的别名之后,我们要看最后信会寄到哪里时,可以使用下面指令来看寄给 username 的信最后寄给谁:# sendmail -bv username
aliases 档中将很多东西都转向 root,因此你可以去读 root 的信箱或是将 root 的信转给别的地方,下面这一行是将 root 的信都转给 [email]my@my.doma[/email]in:
root:        [email]me@my.doma[/email]in
当邮件无法送出被退回时给使用者时,都是以 MAILER-DEAMON 为账号寄出。因为使用者可能会回复那封被退回的信,所以这个别名是必备的。而 postmaster 则负责处理所有关于邮件问题的信件,因此也是必备的,一定要保留下面二行,这是必要的系统基本设定:
MAILER-DAEMON: postmaster
postmaster: root
在修改完 /etc/aliases 之后,我们必须执行下列指令来更新数据:# newaliases
A.2 crontab:设定定时执行工作
在 UNIX 系统中,有一个背景程序会定时执行一些工作,系统管理者可以修改这个档案以设定定期执行的工作。/etc/crontab 可以让管理者设定要以什么使用者的身份去执行定时工作,而一般使用者如果要设定定时执行工作时,可以使用指令 crontab -e 来编辑自己的定时执行工作。
以下为 /etc/crontab 的内容说明:
# 设定使用的 shell, 路径
SHELL=/bin/sh
PATH=/etc:/bin:/sbin:/usr/bin:/usr/sbin
# 设定执行指令时的目录
HOME=/var/log
# 当指令有输出数据时,要将输出的东西寄给谁。
MAILTO=""
#
# 分        小时        天        月        星期几        身份        指令
#minute        hour        mday        month        wday        who        command
#
*/5        *        *        *        *        root        /usr/libexec/atrun
minute:代表一小时内的第几分,范围 0-59。
hour:代表一天中的第几小时,范围 0-23。
mday:代表一个月中的第几天,范围 1-31。
month:代表一年中第几个月,范围 1-12。
wday:代表星期几,范围 0-7 (0及7都是星期天)。
who:要使用什么身份执行该指令,当您使用 crontab -e 时,不必加此字段。
command:所要执行的指令。
小时的字段中如果是 *,表示每小时,天的字段中如果是 *,表示每天,依此类推。字段中也可以使用 "-" 来表示范围。例如,在小时的字段中填 8-11,表示执行的时间是 8,9,10,11,共四次。
字段中也可以用逗点来表示,以分的字段而言, 1,2,5,9 表示将在 1,2,5,9 分时各执行一次。我们也可以写成像这样 1-2,12-14 ,表示在 1,2,12,13,14 分各执行一次。
另外,也可以用 / 后面加数字表示每几分钟要执行一次。如在分的字段填 0-23/2,表示 1-22 分之间,每隔二分钟执行一次,也就是 0,2,4,6,8,10,12,14,16,18,20,22。如果在分的字段是 */5,表示每五分钟一次。
除此之外,也可以用一个开头为 @ 的字符串来表示各种意义:
[b]字符串[/b]
[b]代表意义[/b]
@reboot
开机时跑一次。
@yearly
每年跑一次,等于 "0 0 1 1 *"。
@annually
和 @yearly 一样。
@monthly
每月跑一次,等于 "0 0 1 * *",也就是每月一日半夜 12 点执行。
@weekly
每周跑一次,等于 "0 0 * * 0",也就是每个周日半夜 12 点执行。
@daily
每天跑一次,等于 "0 0 * * *",也就是每天半夜 12 点执行。
@midnight
和 @daily 一样。
@hourly
每小时跑一次,等于 "0 * * * *"。
另外,我们还可以在档案中以「key = value」的方式设定在执行指令时的环境变量。例如,一般指令有输出执行结果时,会自动寄给 root,我们也可以设定「MAILTO = ""」表示不要将输出结果寄出。以下为几个时间设定的范例:
# 分        小时        天        月        星期几        身份        指令
#minute        hour        mday        month        wday        who        command
#
# 设定每 5 分钟执行一次atrun。
*/5        *        *        *        *        root        /usr/libexec/atrun
# 设定每天一点零一分时执行 /bin/check
1        1        *        *        *        root        /bin/check
# 设定每周一 3:11 分执行 week_check
11        3        *        *        1        root        /usr/local/week_check
# 设定每天一点及四点的零到二十三分中间,每二分钟执行一次 something。
0-23/2        1,4        *        *        root        /bin/something
一般使用者的 crontab 会放在 /var/cron/tabs 目录中,所以如果要备份或升级时,应该要注意这些档案是否要备份。
[img]http://homepage.cqwu.net/wxfy/images/note.png[/img]
小提示
我们在安排 crontab 时,应该要错开每个程序的执行时间,才不会有一大堆程序同时执行,造成系统负荷过高。
A.3 csh.cshrc:Tcsh 使用者登入后的 shell 环境设定
这是给 Shell csh、tcsh 用的内定 .cshrc 档案,也就是进入该 Shell 时会加载的设定。所有使用 csh 及 tcsh 的使用者登入后,系统都会自动加载这个档案中的设定,若使用者自己的家目录中的 .cshrc 和 csh.cshrc 有相同的设定,则会以使用者家目录中的 .cshrc 为主。
# 档案权限设定
umask 022
# 设定内定使用的文字编辑器为 ee
setenv  EDITOR  ee
# 设定当使用者打 ls 时,出来的结果是 ls -F 的结果
alias   ls      ls -F
# 设定当使用者打 cd.. 时,变成是打 cd ..
alias cd.. 'cd ..'
# 设定命令提示符号为 "主机名称 [所在目录] -使用者名称->"
set prompt = "%B%m [%/] -%n-> "
这个档案除了使用者登入时会加载外,如果使用者以 tcsh 或 csh 写 shell scripts,在执行时也会加载这个档案中的设定。
A.4 csh.login:Tcsh 使用者登入后的 shell 环境设定
这是给 csh、tcsh 用的内定 .login 档案,使用者登入 shell 时会自动加载本档中的设定。和 csh.cshrc 不同的时,这个档案只有在使用者登入时才会加载,而执行 shell scripts 时不会使用这个档。如果使用者家目录中的 .login 设定和 csh.login 相冲突时,将以使用者家目录中的 .login 设定为主。
# 要读取系统讯息则将下面一行的 # 拿掉
# msgs -f
# 允许终端机讯息,设为 y 才可以使用 write 的指令,
# 传送讯息给其它使用者
# mesg y
# 设定支持中文的终端机
setenv ENABLE_STARTUP_LOCALE zh_TW.Big5
setenv LC_CTYPE is_IS.ISO_8859-1
setenv LANG zh_TW.Big5
# 登入时显示 FreeBSD Tip
[ -x /usr/games/fortune ] && /usr/games/fortune freebsd-tips
A.5 csh.logout:Tcsh 使用者注销时会执行的设定
这是给 Shell csh、tcsh 用的内定 .login 档案,也就是离开该 Shell 时会执行这个档案中的指令。在离开 Shell 时,Shell 会载入 /etc/csh.logout 及 ~/.logout 的设定。请 man csh。
A.6 defaults/periodic.conf:预设定时执行项目设定
这个档定义了 /etc/periodic 目录下哪些程序要定期执行。我们可以新增并编辑 /etc/periodic.conf 或 /etc/periodic.conf.local 来覆盖这个档案的设定。您可以 man periodic.conf 来得到更多的信息。
A.7 defaults/rc.conf:预设的系统设定文件
系统开机时会读取这个设定档以决定应该执行哪些工作,例如网络设定、该执行哪些系统服务等。 /etc/defaults 目录下的 rc.conf 中所有设定都是默认值,如果我们要修改,请新增 /etc/rc.conf 来加入你的设定,这样在日后升级时我们的设定才不会覆盖。如果 /etc/defaults/rc.conf 中的设定和 /etc/rc.conf 重复时,会以 /etc/rc.conf 为主。另外,当我们执行 sysinstall 后所做的设定,也会被写入 /etc/rc.conf 中。建议您可以读一下 rc.conf 看看我们有哪些可以设定的项目。
rc.conf 有很多设定,例如网络卡 IP、hostname、firewall、要启动什么系统服务等,几乎所有的系统设定都放在这个档案中。FreeBSD 在开机时,会读取 /etc/rc.conf 以决定要不要启动某些服务,而当我们从 ports 中安装程序时,通常安装完后,我们也要设定这个文件才能让该程序在开机时执行。例如,安装完 SNMP 时,我们要在 /etc/rc.conf 中加入「snmpd_enable="YES"」,这样一来 SNMP 才会在开机时启动。
A.8 fbtab:设定使用者登入时对系统装置的存取权限
fbtab 用来设定使用者登入对于系统装置的存取权限。大多数的人都是使用虚拟的终端机,我们登入系统时所使用的 tty 是虚拟的终端机 ttyv0、ttyv1 等,FreeBSD 将这些系统装置视为档案,放在 /dev/ 中。例如,console 就是 /dev/console 这个档,但该档的拥有者是 root,而有的应用程序用要求使用 /dev/console 的存取权限,fbtab 这个档案是用来定义当你从虚拟的终端机登入时,能自动取得某个装置的权限。详细说明请 man fbtab。
A.9 fstab:档案系统的加载设定
这个档案用来定义开机时要挂入的档案分割区及各分割区的参数设定,例如,要挂入哪一个目录中、挂入时的参数、备份时是否要备份等。
# 装置名称        挂入点              档案系统        参数                Dump        Pass#
/dev/ad0s1b        none                swap        sw                0        0
/dev/ad0s1a        /                ufs        rw                1        1
/dev/ad1s1f        /home                ufs        rw                2        2
/dev/ad0s1e        /usr                ufs        rw                2        2
/dev/ad1s1e        /var                ufs        rw                2        2
/dev/acd0c        /cdrom                cd9660        ro,noauto        0        0
proc                /proc                procfs        rw                0
Device:装置名称,就是要挂入的来源,最常用的是 /dev/ 的档案,我们说过FreeBSD 将装置视为档案,所以这里填的是 /dev/*。装置也可以是NFS或是其它的虚拟装置,如 proc,linpro 等。
Mountpoint:挂入点,就是你要将来源挂到什么地方,其中 swap 没有挂入点,所以是 none。
FStype:档案系统就是要挂入的类型,必须在 kernel 中有定义。一般 FreeBSD 的档案是 ufs,硬盘要挂入的设定就是 ufs。如果是 cdrom 就是 cd9660。
  
[b]档案系统格式[/b]
[b]说明[/b]
ufs
本地的 UNIX 档案系统。
ext2fs
Linux EXT2 档案格式。
msdos
FAT/FAT32,DOS 兼容的档案系统。
ntfs
Windows 的 NTFS。
cd9660
CD-ROM 的档案系统。
udf
DVD 数据光盘格式。
nfs
和 Sun Microsystems 相容的 "Network File System"。
smbfs
CIFS/SMB 档案格式,也就是 Windows 的网络芳邻,请参考 Samba 网络芳邻一章。
mfs
本地的 memory-based UNIX 档案系统。
swap
用来作 swapping 的档案系统。
procfs
用来存取执行程序(process)的档案系统。
kernfs
用来存取核心参数(kernel parameter)的档案系统。
Options:参数依各装置而有所不同,如果开机时不挂入的话(如 cdrom),就必须加入参数 noauto。defaults 设定为 rw、dev、exec、auto、nouser、async。可用的参数如下,加上no 则为相反,如 nouser、noauto:
  
[b]参数[/b]
[b]说明[/b]
rw
可读可写。
ro
只可读不可写。
async
所有数据以异步方式完成。
atime
每次存取动作都更新档案时间。
auto
能被 mount -a 自动挂入系统。
dev
解译档案系统特性与储存装置规格。
exec
允许档案系统中的二进制元文件被执行。
user
允许一般user 挂入。
sync
所有数据以同步方式完成。
sw
swap。
noauto
开机时不挂入。
userquota
使用者磁盘配额限制 (须 kernel 支持 quota)。
groupquota
群组磁盘配额限制 (须 kernel 支持 quota)。
dump:表示使用指令 dump 时要备份的档案系统,0表示不要,1表示要。
pass:这个字段是给指令 fsck 用的,是检查的顺序。/ 的数字应该是1而其它的档案系统为2。不需检查的就是0(如 cdrom,swap 等)。
A.10 ftpusers:设定哪些使用者不可以使用 FTP 登入
这个档案用来定义哪些使用者不可以使用 FTP 登入,只要将使用者登入的账号加入这个档案中,该使用者就不能使用 FTP 登入系统了。例如,我们要让使用者 tom 无法使用 FTP 来登入系统,只要在 fupusers 档案开头加入该使用者名称。ftpusers 中也可以加入群组名称,如果您不希望某个群组的使用者使用 FTP 登入,只要在该档案中加入 @groupname 即可。开头为 "@" 表示该行的设定为群组名称。
# $FreeBSD: src/etc/ftpusers,v 1.6 1999/08/27 23:23:41 peter Exp $
#
# list of users disallowed any ftp access.
# read by ftpd(8).
@noftp
tom
root
toor
daemon
operator
bin
tty
kmem
games
news
man
bind
uucp
xten
pop
nobody
A.11 ftpchroot:设定哪些使用者登入后要限制根目录
FreeBSD 内附的 FTP daemon 还有一个重要的功能,就是可以让使用者登入后,只看得到自己的家目录。如果在 ftpchroot 这个档案中有该使用者名称或以 "@" 为开头的群组名称,使用者登入后,根目录就会是自己的家目录,而无法切换目录到非家目录的其它系统目录中。我们也可以设定将某个使用者或群组设定登入后只能在某一个固定的目录中,详细设定请参考「FTP 服务器」一章的说明。
A.12 gettytab:终端机模式设定文件
这个档案是终端机模式设定文件。在启动终端机时 (例如,使用者登入系统时),系统会读取这个档案中关于终端机的设定值。例如,我们可以修改这个档案以设定使用者登入前的提示讯息。以下为该档案 default 的部份:
# im= 就是别人连上你的机器时会看到的字符串,其中 \r\n 表示换行
# 其中的%s %m %h %t 分别对应到 FreeBSD i386 alexwang.com ttyp0,
# 如果你不想显示 FreeBSD ,就把 %s 拿掉。最后一行 if=/etc/issue
# 就是表如果没有 issue 这个档的话,就执行 default。
default:\
        :cb:ce:ck:lc:fd#1000:im=\r\n%s/%m (%h) (%t)\r\n\r\n:sp#1200:\
        :if=/etc/issue:
A.13 group:使用者群组设定档
这个档案记录了系统中的使用者群组设定。详细说明请参考「使用者管理」一章。我们要注意的是每一个群组的编号 (gid) 不可以重复。另外,在 FreeBSD 中,如果使用者要具有 su 成 root 的权限,必须将该使用者加入 wheel 群组中。例如,我们要让使用者 alex 可以 su 成 root 的权限,则在 group 档中 wheel 群组后面加上 alex:
wheel:*:0:root,alex
daemon:*:1:
kmem:*:2:
sys:*:3:
A.14 host.conf:设定 DNS 查询顺序
这个档案用来设定 DNS 查询的顺序。预设的查询顺序是先查询 hosts 这个档,再由 bind 向 DNS Server 查询。如果有 NIS 的话,还要再加入 nis 那一行。
# $FreeBSD: src/etc/host.conf,v 1.6 1999/08/27 23:23:41 peter Exp $
# First try the /etc/hosts file
hosts
# Now try the nameserver next.
bind
# If you have YP/NIS configured, uncomment the next line
# nis
A.15 hosts:定义常用的机器名称对映
我们可以将常用的机器名称及 IP 对映写在这个档案中,以节省向 DNS Server 查询的时间。如果你的主机有多个 domain name,将你最喜欢的放在最前面,这样寄信时才会出现该 domain name。
在设定时,档案中最少要有 localhost 和自己的 domain name。hosts 的格式如下:IP 地址        正式的主机名称        别名
别名的用意在于,使用时可以用比较简单的名称来联机到该机器。例如,我们设定了 bbs.ba.mgt.ncu.edu.tw 的别名为 bbs,则在使用 telnet、ssh、ping 等指令时,我们只要输入 bbs 做为主机名称即可,不必输入其 IP 或是一长串的正式主机名称。以下为设定范例:
127.0.0.1               localhost.com localhost
192.168.0.1             mydomain.com mydomain
192.168.0.1             mydomain.com.
192.168.0.2             mail.mydomain.com mail
140.115.83.240          bbs.mgt.ncu.edu.tw bbs.mgt
140.115.75.5            bbs.ba.mgt.ncu.edu.tw bbs
A.16 hosts.allow:设定允许或拒绝联机的主机
设定允许或拒绝使用本机服务、联机的主机来源。例如你可以在这里加入拒绝某台计算机使用 telnet、ssh、ftp 等联机到你的机器。在「系统安全」一章详细的说明了如何使用这个档案来让我们的主机更安全
A.17 hosts.equiv:设定远程信任主机及使用者
设定远程信任主机及使用者,这个档案主要是给一些 "r" 系列的服务用,例如 rcp、rlogin、rsh 等。详细说明请 man hosts.equiv。
A.18 hosts.lpd:设定可以使用本地列表机的主机
我们可以将 FreeBSD 设定成 LPR 网络列表机,而这个档案是用来设定可以使用本地列表机的主机,只要加入主机名称或 IP 即可。
A.19 inetd.conf:各项 inetd 服务设定档
inetd 是 UNIX 系统中用来掌管许多服务的重要 daemon,我们可以修改这个档来设定 inetd 所要提供的服务。它的格式如下:
#ftp        stream        tcp        nowait  root    /usr/libexec/ftpd       ftpd -l
#ftp        stream        tcp6        nowait  root    /usr/libexec/ftpd       ftpd -l
#ssh        stream        tcp        nowait  root    /usr/sbin/sshd          sshd -i -4
#ssh        stream        tcp6        nowait  root    /usr/sbin/sshd          sshd -i -6
telnet        stream        tcp        nowait  root    /usr/libexec/telnetd    telnetd
#telnet        stream        tcp6        nowait  root    /usr/libexec/telnetd    telnetd
   
第一个字段是服务的名称,要和 /etc/services 搭配设定。如果要开放某一项服务,只要将开头的 # 符号移除即可。我们一般可以在这个档案中设定的常用服务有 telnet、ftp、pop3等。当修改这个档后,必须重跑 inetd 才会生效。# kill -1 `cat /var/run/inetd.pid`
A.20 localtime:记录所在时区设定
这个文件记载你所在的时区数据,你可以经由 sysinstall 来设定时区。该程序会自动将 /usr/share/zoneinfo 中合适的档案复制一份成为 /etc/localtime。
A.21 locate.rc:快速搜寻档案的名称数据库设定
FreeBSD 会自动依这档案的内容来建立硬盘中文件名称数据库,以利我们快速搜寻文件名称。详细的说明请 man updatedb、man locate。
A.22 login.access:控制使用者登入权限
用来设定登入系统使用者的权限,我们可以在这里设定是否允许使用者从 console 登入、从不同区域登入的权限等。
当某个使用者登入后,会先依本档中的设定来控制使用者的登入来源。这里所使用的规则是由上往下比对,先符合者优先,也就是 first match wins,来决定该使用者可以登入或是被拒绝。它的格式是以 ":" 分割成三个字段:permission : users : origins
第一个字段应该是 "+" (可以登入) 或 "-" (拒绝登入) 的其中之一。
第二个字段是一个或多个登入的名称、群组名称或是 ALL(永远符合)。
第三个字段是一个或多个 tty 的名称清单(非网络登入用)、主机名称、所属网域(开头是 "." 的)、主机地址、因特网编号(结尾是 "." 的)、或是本地的机器 (任何没有包含 "." 的字符串)。如果你有跑 NIS,你可以使用@netgroupname在主机或是使用者的格式中。
我们也可以使用 EXCEPT 的运算符号写出非常简洁的规则。群组的设定只有在使用者名称不符合规则时才会被用到,而且这个程序并不会去查使用者主要的群组是什么。
A.23 login.conf:控制使用者可以使用的系统资源
这个档案用来控制不同账号可以使用的系统资源,它会依照使用者在密码文件中的 login class 来寻找相对应的 class 设定,如果没有分类则使用 default 的默认值。请参考「使用者管理」一章中的说明。
A.24 mail.rc:设定 mail 指令参数
用来设定 mail 的参数。当 mail 指令执行时,它会先读 /usr/share/misc/mail.rc、/usr/local/etc/mail.rc 及 /etc/mail.rc,最后再读使用者的 ~/mailrc 这个档。请 man mail,您不必动到这个档。
A.25 make.conf:设定 make 的参数
当我们在重新编译 FreeBSD 内附的程序时 (例如使用 port 安装软件时),我们所使用的指令 make 会读取 /etc/make.conf 来取得一些编译时的参数。它可以让你在 make 时覆盖一些设定而不必去修改 source tree。make.conf档案一定要使用有效的 Makefile 语法。一般而言,我们会修改一些关于下载档案的 FTP 站台设定,以从 port 安装软件而言,当下达 make install 指令时,make 会去抓一些必要的档案,如果要去国外抓的话实在太慢了,所以我们会将 FTP 站台设定为离我最近或最快的站台。只要在 make.conf 中最下方加入下列设定即可:
# 当使用 port 安装软件时,优先使用中央大学资工系及交大资工的 FTP
MASTER_SITE_BACKUP?=    \
        [url]ftp://freebsd.csie.ncu.edu.tw/FreeBSD/ports/distfiles/$[/url]{DIST_SUBDIR}/ \
        [url]ftp://freebsd.csie.nctu.edu.tw/pub/distfiles/$[/url]{DIST_SUBDIR}/
MASTER_SITE_OVERRIDE?=        ${MASTER_SITE_BACKUP}
A.26 manpath.config:设定 man 文件所在位置
设定 man 指令的参数,如 man 的文件所在等。
A.27 master.passwd:使用者密码文件
FreeBSD 使用 shadow password 的方式来保护密码文件,只有 root 才可以读取编码后的密码文件 /etc/master.passwd,而一般使用者只能看到 passwd 文件中的数据。但是这并不是系统用来验证的档案,为了加快速度,FreeBSD 将该文件做成数据库 /etc/spwd.db 及 /etc/pwd.db,因此在修改完 master.passwd 后,必须使用指令 pwd_mkdb 来将 master.passwd 做成数据库档案。不过一般而言,我会使用 vipw 这个指令来修改 master.passwd,vipw 会先将 master.passwd 以预设的文书编辑软件打开,修改完存盘后,它会视需要自动更新数据库。
它的格式是:name:password:UID:GID:class:change:expire:fullname:home:shell
name:使用者账号名称,也就是您 login 时所需输入的名字。使用者名称长度最长可以是 16 个字符,但如果您要使用 NIS,则最多只可以使用8个字符。每个使用者名称不可重复。而且使用者名称中只能包英文字、减号 "-"、底线 "_"、及数字,而且最好不要使用大写的英文字,而开头的第一个字也不可以是减号 "-"。在 master.passwd 这个档案中,每个字段都不可以使用冒号 ":",因为冒号是用来分割字段的特殊符号。
password:可以是空的,代表不用密码就可以登入,这样很危险;也可以是 *,表示不可以登入;上面 vipw 显示出来的项目中,以使用者 root 而言,他的密码是使用 MD5 编码过的,特征是开头为 $1 且看起来比较长;而使用者 tom 的密码是使用 DES 编码过的,DES 会将密码编成一串13个字符的符号。
UID:使用者代号,每个使用者都不一样,不可重复,如果有多个账号使用同样的 UID,FreeBSD 会将它当成同一个账号。编号从 0 到 65535。UID 0 为系统中超级使用者的代号,内定只有 root 和 toor 的 UID 为 0。toor 账号是 bash 所建立的使用者,内定不能使用该使用者登入。
GID:群组代号,编号从 0 到 65535。
class:除了群组外,class是更有弹性的控制方法,可以针对 /etc/login.conf 中不同的使用者设定来调整每个使用者的可使用的资源设定。
change:强迫使用者变更密码的时间,以从1970年到所要变更日期所经过的秒数来表示。你可以使用 date +%s 来求出从1970年到现在时间所经过的秒数,每天为86400秒,以现在时间的秒数加上86400*天数即为你要设定的时间。你可以使用指令下列指令来取得30天后的秒数,再将其填入即可。若设为0则表示不使用此功能:
# expr `date +%s` + 86400 \* 30
expire:账号的有效日期,一样是以从1970年到到期日所经过的秒数来代表。若设为0则表示不使用此功能。
fullname:使用者全名,你可以在此键入真实姓名。请注意这个字段也不可以使用冒号哦。
home:使用者的家目录,即使用者登入后的所在目录。
shell:使用者的 shell。如果使用 /sbin/nologin 表示该名使用者不可以登入。
A.28 motd:使用者登入后讯息
系统登入后,会自动秀出一段文字,称为 Message Of The Day(motd)。这一段文字是可以修改的,你可以编辑 /etc/motd 来制作自己的画面。如果您不希望 motd 内容出现 FreeBSD 的版本信息,您可以在 rc.conf 中加入下面内容:
update_motd="YES"
如此一来,下次您更新 motd 的内容时,系统就不会自动将版本信息加入 motd 中。
A.29 namedb/:DNS 服务器设定档
如果你有架 Name Server 的话,你必须设定该目录下的档案。详细说明请参考「DNS服务器」一章的说明。
A.30 netstart:启动网络服务的程序
这个档案并不会被其它程序所使用,它只是让你在单人模式下执行,用以启动网络。而多人模式的网络设定在于 /etc/rc.network。
A.31 networks:设定本地网络信息
用来设定本地网络的信息,我们通常不会需要修改这个档案。
A.32 newsyslog.conf:设定定期压缩备份文件
这个档主要用来定期检查 /var/log/ 的档案,设定当 log 到一定大小或是定期的将旧的档案压缩备份,并删除太老旧的档案。除了 log 外,您也可以用它来设定定时要压缩备份的档案。
语法:logfilename [owner:group] mode count size when [ZB] [/pid_file] [sig_num]
[b]字段[/b]
[b]说明[/b]
logfilename
log 档名称
[owner:group]
log 档拥有人:群组
mode
该 log 文件的权限(档案属性)
count
最多计算到多少,例如 cron 是 3 表示将有四个压缩档:cron.0.gz, cron.1.gz, cron.2.gz, cron.3.gz。
size
档案最大到多少即压缩备份,以 KB 计。
when
什么时候做备份,请 man newsyslog 来看详细说明。以 @ 为首代表用 ISO 8601 结构的时间格式。以 $ 为首代表使用每天、每周、每月。
一些例子:
$D0 每天半夜十二点
$D23 每天 23:00 时
$W0D23 每周日 23:00
$W5D16 每周五 16:00
$MLD0 每月最后一天半夜十二点
$M5D6 每月第五天 6:00
[ZB]
Z 表示要将该档以 gzip 压缩起来,B 表示该档是 binary 档。
[/pid_file]
pid 文件的绝对路径,如果有设定,则会送出 sig_num 给该程序。
[sig_num]
要送给该 daemon 程的 signal number,预设是 SIGHUP。
A.33 nsmb.conf:设定 smbfs 信息
我们可以在 FreeBSD 中使用 mount_smbfs 来挂入 Windows 网络芳邻中所分享出来的共享数据夹。而 nsmb.conf 就是执行 mount_smbfs 所使用的设定档。我们可以设定所要使用的 codepage、使用者名称及密码等,请 man nsmb.conf 以取得相关的设定说明。
A.34 nsswitch.conf:设定 nsswich 信息
FreeBSD 中有所谓 name-server switch,用来控制名称信息转换,例如,当系统要取得 password、group、host 等信息时,会参考这个档案以决定要从哪里得到信息。请 man nsswitch.conf 以取得相关的设定说明。
A.35 opiekeys:OPIE 设定档
FreeBSD 内建一种密码验证的方法 OPIE (One Time Password In Everything),就是一种只能使用一次的密码。而 opiekeys 这个档案是用来存放使用 OPIE 的使用者设定。您可以 man opie 及 man opiepasswd 以取得更多信息。
A.36 pam.d:PAM 设定档
PAM 是 Pluggable Authentication Module 的缩写。它是 FreeBSD 内建的一种极富弹性的认证机制,您可以参考这个网页来取得更多关于 PAM 的信息:
[url=http://www.freebsd.org/doc/en_US.ISO8859-1/articles/pam/]http://www.freebsd.org/doc/en_US.ISO8859-1/articles/pam/[/url]
;或者如果您安装时有安装 FreeBSD 文件,您也可以在下列目录找到关于 PAM 的说明:# ls /usr/share/doc/en_US.ISO8859-1/articles/pam
A.37 passwd:不含密码的使用者信息文件
FreeBSD 使用 shadow password 的方式来保护密码文件,只有 root 才可以读取编码后的密码文件 /etc/master.passwd,而一般使用者只能看到 passwd 文件中的数据。但是这并不是系统用来验证的档案,为了加快速度,FreeBSD 将该文件做成数据库 /etc/spwd.db 及 /etc/pwd.db,因此在修改完 master.passwd 后,必须使用指令 pwd_mkdb 来将 master.passwd 做成数据库档案。不过一般而言,我会使用 vipw 这个指令来修改 master.passwd,vipw 会先将 master.passwd 以预设的文书编辑软件打开,修改完存盘后,它会视需要自动更新数据库。你不需要改 passwd 的内容,只要改 master.passwd 即可。详细说明请参考 man master.passwd 的说明。
A.38 pccard_ether:启用及停用 PCCARD 网络设备
本文件用以启动或停用 PCCARD 网络设备的执行文件。
A.39 periodic/daily:包含每天会定时执行的工作
设定每天要执行一次的程序。该目录下放的是 shell script,如果你想自行增加的话,只需在该目录下编辑新的 shell script 并将权限设为可执行即可,或者编辑 /etc/daily.local,加入想要执行的指令。在 /etc/defaults/periodic.conf 中定义了定期执行的设定,以下即为 daily 选项每个档案所执行的动作:
[b]档案[/b]
[b]动作[/b]
[b]预设执行[/b]
100.clean-disks
清理磁盘,要清除的档案类型可以在 periodic.conf 中设定。

110.clean-tmps
清除 /tmp。

120.clean-preserve
删除 /var/preserve 中它旧的档案。

130.clean-msgs
清除旧的系统讯息。

140.clean-rwho
清除 /var/rwho 中的旧资料。

150.clean-hoststat
清除 /var/spool/.hoststat。

200.backup-passwd
备份 /etc/master.passwd 及 /etc/group 并比对是否有更动。

210.backup-aliases
备份 /etc/mail/aliases。

300.calendar
执行 calendar -a。

310.accounting
移转 /var/account/ 的档案。

330.news
执行 /etc/news.expire。

400.status-disks
执行 df 及 dump -W。

405.status-ata-raid
检查 ATA Raid 的状态。

420.status-network
执行 netstat -i。

430.status-rwho
执行 uptime。

440.status-mailq
执行 mailq。

450.status-security
执行 /etc/security。

460.status-mail-rejects
统计/var/log/maillog 中记录拒绝的信件数量。

470.status-named
统计 DNS 拒绝记录。

500.queuerun
手动执行 mail queue。

999.local
执行 /etc/daily.local 中使用者自行定义的指令。

A.40 periodic/weekly:包含每周会定时执行的工作
设定每周要执行一次的程序。该目录下放的是 shell script,如果你想自行增加的话,只需在该目录下编辑新的 shell script 并将权限设为可执行即可。在 /etc/defaults/periodic.conf 中定义了定期执行的设定,以下为每周会执行的工作:
[b]档案[/b]
[b]动作[/b]
[b]预设执行[/b]
120.clean_kvmdb
清除过期的 /var/db/kvm_*.db。

310.locate
执行 /usr/libexec/locate.updatedb。

320.whatis
执行 /usr/libexec/makewhatis.local。

330.catman
执行 /usr/libexec/catman.local。

340.noid
找出没有拥有人或群组的档案。

400.status_pkg
使用 pkg_version(1) 找出老旧的 package。

999.local
执行其它在 /etc/weekly.local 中使用者自行定义的指令。

A.41 periodic/monthly:包含每月会定时执行的工作
设定每月要执行一次的程序。该目录下放的是 shell script,如果你想自行增加的话,只需在该目录下编辑新的 shell script 并将权限设为可执行即可。在 /etc/defaults/periodic.conf 中定义了定期执行的设定,以下为每月为执行的档案:
[b]档案[/b]
[b]动作[/b]
[b]预设执行[/b]
200.accounting
执行 ac 指令,统计使用者登入时间。

999.local
执行其它 /etc/monthly.local 使用者自行定义的指令。

A.42 periodic/security:包含每天会执行的安全检查工作
periodic/security 中存放着每天会执行的 security check 档案,这些档案执行与否,同样定义在 /etc/defaults/periodic.conf 中,以下为每日会执行的档案:
[b]档案[/b]
[b]动作[/b]
[b]预设执行[/b]
100.setchksetuid
检查是否有新增的 setuid 程序。

200.chkmounts
检查挂入磁盘的改变。

300.chkuid0
列出所有 uid 为 0 的使用者。

400.passwdless
列出没有密码的使用者。

500.ipfwdenied
列出 ipfw 所拒绝的联机。

510.ipfdenied
列出 ipf 所拒绝的联机。

550.ipfwlimit
列出 ipfw log 中,超出限制的相同记录。

600.ip6fwdenied
列出 ip6fw 所拒绝的联机。

650.ip6fwlimit
列出 ip6fw log 中,超出限制的相同记录。

700.kernelmsg
列出 dmesg 的内容。

800.loginfail
列出登入失败的信息。

900.tcpwrap
列出 TCP Wrap 所拒绝的联机。

A.43 phones:远程主机电话数据库
用来设定远程主机电话的数据库,以供指令 tip 使用,详情请 man tip。
A.44 ppp/:PPP 相关设定档
设定 ppp 及 pppd 的设定档。请参考「网络设定」一章中的 ADSL 及 modem 的设定。
A.45 printcap:列表机设定档
这个档案定义了列表机的设定,请参考 man lptcontrol。
A.46 profile:Shell 设定档
这个档案是当你使用 bash 为 shell 时,进入 shell 会读取的设定。就像 tcsh 所使用的 csh.cshrc 一样。
A.47 rc:开机时会执行的档案
当系统开机时,kernel 会先去加载 /sbin/init ,然后 /sbin/init 会去执行 /etc/rc ,而 rc 会去执行 /etc/rc.d/* 及 etc/rc.* 的档案。几乎所有的设定都在 rc.conf 中,所以你只要去修改 rc.conf 就好了。
A.48 rc.d:所有开机时可能执行的服务
这个目录下存放了所有开机时会自动执行的程序,这些程序会依我们在 rc.conf 中的设定决定需不需要被执行。
A.49 rc.firewall:防火墙设定档
这个档案是作防火墙的设定。你可以在该档中加入你想要的设定,不过前提是你的系统已经准备好防火墙的相关设定了。详情请参考防火墙设定一章的说明。
A.50 rc.local:使用者自行设定开机要执行的工作
这个档案是让你设定开机要执行的程序。你可以在该文件中加入启动程序的指令,如果 rc.local 不存在,请自行新增。你也可以在 /etc/rc.d 的目录中,放在你一开机想要执行的 shell script,并将权限改为可执行。
A.51 rc.*:其它开机时的相关执行档
/etc/ 的其它 rc.* 的档案,如 rc.i386、rc.network 等,你不必去更动它们。一般而言,你想做的设定都可以在 /etc/rc.conf 中达成。如果你想要知道更多它们的信息,请 man rc。
A.52 resolv.conf:DNS 主机及网域设定
设定你 DNS 查询的主机顺序。例如下列范例中,我们设定我们的 domain 为 mydomain.com ,而 nameserver 的后面加上的 IP 就是 DNS Server 的地址。
domain  mydomain.com
nameserver      61.64.127.1
nameserver      168.95.1.1
A.53 services:定义网络服务的端口号
这个档案定义了每个网络服务所使用的 port 及名称。
A.54 shells:定义合法的 shell
这个档案定义了使用者可以使用的 shell。只要是可以使用的 shell 都要在该档案中加入。有些程序为去检查使用者所使用的 shell 是否在 shells 中,例如 FTP 就不允许非使用 shells 中定义的 shell 的使用者登入。
A.55 ssh:SSH 相关设定及金钥
这个目录存放了 SSH daemon 所使用的金钥及设定档。
A.56 sysctl.conf:开机时会执行的 sysctl 内容
这个档案的内容会在开机时被 sysctl 这个指令所执行,用来对系统进行一些参数的调校,请参考「系统调校」一章的说明。
A.57 syslog.conf:定义系统记录文件位置及规则
这个档案定义了系统记录文件所储存的位置及记录的规则。
A.58 ttys:各种终端机权限设定
定义 tty 的形式及某些 tty 允不允许 root 登入。例入 root 就不能从 ttyp* 登入。有的 tty 后面有加 secure, 表示 root 可以从该 tty 登入。

逍遥 发表于 2006-6-5 15:33

附录B 制作 FreeBSD 安装光盘
如果您想要自行制作 FreeBSD 安装光盘,您可以自各大 FTP 站台下载 FreeBSD 回来自行烧录。FreeBSD 各个 RELEASE 版本推出时,都会将光盘的 ISO 文件释出,如果您要烧录 RELEASE 版的开机光盘,必须自 ftp 站台下载 ISO 档。如果您所要烧录的版本是 STABLE 版,通常都没有 ISO 档可以下载,我们必须自行选择所要烧录的档案回来烧录。在这里我们就分别针对 RELEASE 及 STABLE 版本的光盘烧录来加以说明。我们使用的烧录软件是 NERO,您可以自 [url]http://www.nero.com[/url] 下载试用版本。
B.1 烧录 RELEASE 版安装光盘
首先,请到离您最近的 FTP 站台下载所需的 ISO 档,以 FreeBSD 5.2.1-RELEASE 为例,我们以 FTP 软件至 [url]ftp://freebsd.csie.nctu.edu.tw/pub/ISO-IMAGES-i386/5.2.1/[/url] 目录下,您可以看到以下几个档案:
[b]档案[/b]
[b]说明[/b]
5.2.1-disc1.iso
FreeBSD 安装光盘,包含常用的 packages。
5.2.1-mini.iso
FreeBSD 安装光盘,只有安装必备文件,不含常用的 packages。
5.2.1-disc2.iso
修复光盘,可以开机并可自光盘执行系统指令。
5.2.1-disc3.iso
包含更多的 package 软件。
5.2.1-disc4.iso
包含更多的 package 软件。
CHECKSUM.MD5
各个 ISO 档的 MD5 检查结果。
我们选择第一个 INSTALL 光盘下载后,将档名改成 5.2.1-disc1.nrg 后,请依下列步骤进行烧录:
步骤一:进入 NERO 后,使用 [File]->[Open] 开启档案
图 B-1
[img]http://homepage.cqwu.net/wxfy/images/b_01.png[/img]
步骤二:选择档案类型为 CD-Image(*.nrg),并选取档案。
图 B-2
[img]http://homepage.cqwu.net/wxfy/images/b_02.png[/img]
接着将出现下列画面,直接选 OK 即可:
图 b-3
[img]http://homepage.cqwu.net/wxfy/images/b_03.png[/img]
步骤三:进入烧录。我们点选 Finalize 将 CD 终结,并选 Write 进行烧录,如此便可以烧录出一片具光盘开机能力的 FreeBSD 光盘。
图 B-4
[img]http://homepage.cqwu.net/wxfy/images/b_04.png[/img]
B.2 烧录 STABLE 版安装光盘
由于 STABLE 版并没有 ISO 档可以下载,因此我们必须自行选择要下载的档案。我们以烧录 4.9-STABLE-20031202-JPSNAP 版为例,请以 FTP 软件连接到 [url]ftp://freebsd.csie.nctu.edu.tw/pub/FreeBSD/snapshots/4.9-STABLE-20031202-JPSNAP[/url] 目录下,我们要选取除了下列二个目录外的所有档案:
[b]目录[/b]
[b]说明[/b]
4.9-STABLE-20031202-JPSNAP
如果选了这个目录,将一直重复的下载所有目录。
packages
由于 packages 目录链接到其它目录下,而且档案很多,无法完全装入光盘中。
图 B-5
[img]http://homepage.cqwu.net/wxfy/images/b_05.png[/img]
下载完成后,就可以使用下例步骤来烧录了:
步骤一:打开 NERO,选择烧录可开机光盘,如下图:
图 B-6
[img]http://homepage.cqwu.net/wxfy/images/b_06.png[/img]
接着选取开机映象档所在,请先选 Image file,再按 Browse去下载完后 STABLE 版的 floppies目录中,选取 boot.flp 这个档来当开机档:
图 B-7
[img]http://homepage.cqwu.net/wxfy/images/b_07.png[/img]
接着选取 "Enable expert settings",再将 "Kind of emulation" 设为 2.88MB。然后就可以按 NEW 来加入要烧录的档案。
步骤二:我们将该来下载的所有档案加入烧录清单后,就可以执行写入了。
图 B-8
[img]http://homepage.cqwu.net/wxfy/images/b_08.png[/img]
步骤三:写入 CD。在上图中执行 "Write CD" 后,将出现下列画面,我们直接选取 "Write" 即可进入烧录。如此便完成 STABLE 版安装光盘的制作了。
图 B-9
[img]http://homepage.cqwu.net/wxfy/images/b_09.png[/img]

兴爷 发表于 2006-6-5 19:46

支持!  继续努力

TOU 发表于 2006-6-6 08:37

好帖,版主辛苦了!

童话 发表于 2006-6-6 08:39

不错,支持楼主!谢谢

问道 发表于 2006-6-6 08:55

不错的教程!支持!

兴爷 发表于 2006-6-7 23:57

各位有时间多看看吧

wan-130 发表于 2006-8-25 01:32

十在太好了。我想要的。谢谢 楼主。

cshappy911 发表于 2006-12-27 05:45

好复杂啊。。不适合我这种懒人

游戏东西 发表于 2006-12-29 16:57

FreeBSD
YAHOO、SINA等大网站用的系统哦!
也可以安装GNONE桌面系统 感觉真的不错啊!

zengfanxiang 发表于 2007-1-27 15:07

建议看看[url]www.freebsd.org.cn[/url]上面的HandBook
中文版6.1 的,很不错

zengfanxiang 发表于 2007-1-27 15:08

搂住安装过程中怎么截的图阿

jerry768 发表于 2008-8-23 04:25

实在不看懂  先顶 以后有机会再学吧

页: 1 [2]

Powered by Discuz! Archiver 7.2  © 2001-2009 Comsenz Inc.