第三章 UNIX 系统入门

在开始进阶的 FreeBSD 设定之前,我们先来了解一下 UNIX 系统的架构及基本知识。这些知识对于我们之后管理、使用 FreeBSD 十分重要。如果您是 UNIX 新手,请务必详读本章。

本章将介绍下列主题:

3.1 第一次登入系统

安装完 FreeBSD 后,重新开机,要知道的第一件事就是要怎么使用嘛。我第一次使用 FreeBSD 时,一开机看到 login: 时我当场呆在那里,完全不知如何下手。所以我一定要说一下这个,如何登入并更改密码。说了一堆好像很难的样子,其实不会啦,开机后看到 login: 时,打 root 就可以登入系统了,如图 3-1。

图 3-1

这里的 root 就是所谓的超级使用者,这个使用者是 UNIX 系统中的预设管理者名称。root 拥有系统所有权限,我们可以使用这个账号登入系统进行管理。root 这个使用者拥有许多一般使用者所没有的权限,建议您平常使用时最好不要以 root 登入。例如收发 email,程序开发、浏览网页、练习 UNIX 指令等,应该以一般使用者的身份来进行。因为您可能不小心打了某个指令而删除不该被删除的档案、或因为不良的操作而影响系统的稳定。因此,在我们设定完系统后,您应该新增一个一般使用者以减少错误的发生。

由于这是刚装好的系统,所以当我们以 root 登入时,系统不会问我们密码。一个没有密码保护的系统是十分危险的事,所以我们第一件要做的事就是设定 root 的密码。请执行指令 passwd 来设定您的密码,系统会问您二次新密码,以确认二次输入的密码相同。请不要使用太简单的密码,以免造成安全的漏洞。

如果您要离开系统,只要打 exit 或是 [Ctrl] + [D] 即可离开。不过离开系统并不是关机喔,如果您要关机,必须先打指令 shutdown now 才能关闭电源。

3.2 认识 UNIX 使用环境

在开始使用之前,我们先说明一些简单的指令用法,以利后续的设定,更详情的指令介绍请参考本书「指令应用」一章中的说明,或使用指令 man 来查询指令的用法。如果您是 UNIX 初学者,先阅读「指令应用」可以让您对 UNIX 指令及系统管理有更多的了解。

3.2.1 UNIX 指令语法

UNIX 系统预设开机后是跑在命令列模式,就是会有一个命令列提示 (又称为 prompt),登入系统后,我们可以在命令列提示中输入指令。在 FreeBSD 中,一般使用者所看到的命令列提示字符是百分比符号 % 或是金钱符号 $,而超级使用者 root 的提示符号是井字号 #。

我们可以在命令列提示之后输入指令,例如:

# date
Wed Jun 15 03:20:44 CST 2005

我们输入指令 date 之后可以看到目前的系统时间。

指令语法

在 UNIX 系统中的指令大多是下列格式:

command [-options] arg1 arg2 ...

command 的部份就是指令本身,而 [-options] 表示指令的选项,arg1、arg2 则是要给该指令的参数。-option 使用 [] 括起来表示指令的选项可有可无, 有的指令可能可以不必加任何选项及参数,如我们刚才输入的指令 date。而在指令之后输入参数会有不同的作用,例如,我们可以使用 date 这个指令来修改目前的系统时间:

# date 200507141730

上述指令即是设定时间为 2005 年 7 月 14 日下午 17 点 30 分。 下面这个范例是有加上选项的指令:

# ls -ld /usr /etc

ls 这个指令是用来列出档案的信息,选项 -l 表示列出详细信息,选项 -d 表示只列出目录本身而不列出目录下的档案,而最后的二个参数则是我们要列出的档案或目录。

值得注意的是,UNIX 系统中的指令及文件名有区分大小写喔,例如,date 和 DATE 是不一样的东西喔。如果您输入了 DATE,您将会看到命令列出现「DATE: Command not found.」,表示指令不存在。如果您输入指令 ls 来查看一个档案,但该档案不存在,则会出现「ls: noexist: No such file or directory」,表示档案不存在。所以当我们在输入指令时,如果有发生问题,应该先查看输出的错误讯息是什么,再根据该讯息修正指令。

在 UNIX 系统中,如果您想了解一个指令的用法,例如可以使用哪些参数等,可以使用 man 这个指令来查询 manual。 例如,您可以使用下列指令来查询 ls 这个指令的用法:

# man ls

更多关于 man  的用法,请参考「指令应用」一章的说明。当您对指令用法有问题时,man 绝对是你是好朋友,懂得善用男人 (man) 可是 UNIX 入门的第一步喔。

指令规则

大部份的情况下,UNIX 的指令输入方式都有下列规则:

特殊按键

当我们在使用命令列输入指令时,有一些特殊按键可以让我们在命令列中移动。例如,我们可以使用键盘的左右键来移动光标,其它还有一些常用的热键如下:

还有一个您一定要知道的小秘诀,当您要 cd 到一个目录时,您可以只打档名的一部份,再按 [Tab] 键,tcsh 会自动帮您补上剩余的部份。例如,我们要切换工作目录 (使用 cd 这个指令) 到 /usr/local,当你打了 cd /usr/lo 时,即可按 [Tab] 键,只要在 /usr 中,除了 local 外没有其它开头为 lo 的档案或目录,tcsh 便会自动补齐成 cd /usr/local。除了 cd 外,其它的指令也是一样,只要按 [Tab] 即可自动补齐。而且除了档案及目录外,指令也可以自动补齐喔。例如,你要下指令 ifconfig,您可以只打 ifc 再按 Tab 键,tcsh 会自动补成 ifconfig。如果您只打 if 即按 Tab 键,您会发现并没有任何动作,因为在系统中,除了 ifconfig 外,还有指令开头也是 if,如 ifmcstat。

3.2.2 UNIX 的目录结构

和大多数的系统一样,UNIX 系统中有档案和目录的分别。档案指的是我们一般的文字文件、音乐文件、图片文件等等,而档案会被放在目录中来管理。

家目录

每一个使用者都有一个「家目录」(home directory),在登入系统后,使用者所在的目录会是在家目录中。该目录中存放了一些使用者登入后会用到的档案,使用者可以在家目录中建立自己的档案、目录等。一般使用者的家目录是在 /home/username 中,而系统管理者的家目录是 /root。

我们在下指令时,可以使用「~」这个符号表示家目录。例如,下列指令表示查看自己家目录中的档案:

# ls ~

如果您要查看其它使用者的家目录,可以在「~」之后加上使用者名称,例如:

# ls ~alex

目前工作目录

目前工作目录 (Current working directory) 顾名思义就是您目前在系统中的所在路径。您可以使用指令 pwd 来查看目前所在路径。

当我们在执行指令时,如果没有告诉该指令目录或文件名称,预设就是会使用目前的工作目录。例如,ls 这个指令,如果没有加上任何参数,表示我们要查看目前工作目录中的档案。

我们可以使用指 cd 来切换工作目录。例如,我们要将目前工作路径切换到 /usr:

# cd /usr
# pwd
/usr

我们可以看到在 cd 到 /usr 后,使用指令 pwd 的结果变成了 /usr 了。

您可以使用下列指令来回到之前的工作目录:

# cd -

目录结构

在 Windows 操作系统中,在档案总管中可以看到 Windows 的 "树状" 目录结构。而 FreeBSD 中的目录也是像一颗树,一个目录下还有很多个目录,和 Windows 不同的是在 UNIX 系统中每一个目录都有一定用途。我们了解 FreeBSD 目录结构的用意就是让我们知道每个目录的用途,日后我们要安装新软件或使用 FreeBSD 时,能按照这种规则来做,这样一来在管理维护上比较方便,目录也会比较有条理。

图 3-2

以下我们就简单的说明 FreeBSD 的目录结构,您也可以使用指令 man hier 来查看目录结构说明。

目录名称 说明
/ UINX 系统的根目录,是目录的最上层。
/bin/ 放置基本的使用者指令,是开机时必备的。
/boot/ 系统开机时必需用到的设定。
/dev/ UNIX 系统将外围设备视为档案来管理,这个目录就是放置装置节点文件 (device node)。在 FreeBSD 5.0 以前 /dev/MAKEDEV 可以使用管理这些节点档的工具。5.0 以后这些 device node 都改由 devfs 来管理。
/etc/ 放置系统的设定文件,例如使用者密码、群组等。
/etc/defaults/ 放置预设的系统设定文件。请 man rc。
/etc/gnats/ gnats 的设定档,请 man send-pr。
/etc/isdn/ isdn 的设定档,请 man isdnd。
/etc/kerberosIV/ kerberos version IV 的设定档,请 man kerberos。
/etc/mail/ Sendmail 的设定档。
/etc/mtree/ 目录权限的设定文件,请 man mtree。
/etc/namedb/ DNS 服务器的设定档,请 man named。
/etc/periodic/ 每天、每周、每月定时要执行的设定,请 man periodic。
/etc/ppp/ ppp 的设定档,请 man ppp。
/etc/ssl/ OpenSSL 的设定档。
/kernel 开机时系统会加载的核心 (kernel)。在 FreeBSD 5.x 中,kernel 这个文件已被放在 /boot 目录中。
/modules/ Kernel 可以加载的模块,请 man kldstat。在 FreeBSD 5.x 中, 这个目录已被放在 /boot 目录中。
/mnt/ 空目录,我们可以用它来作为暂时 mount 档案系统。
/proc/ 系统执行中程序 (process) 数据,请 man procfs mount_procfs。
/root/ 超级使用者 root 的家目录。
/sbin/ 系统程序及管理工具的目录。
/stand/ 这是安装磁盘上的指令。
/tmp/ 暂存目录,许多程序都会需要暂存目录来存放数据。开机时会清除。
/usr/ 包含主要的使用者工具及应用软件。您可以把它看成 Windows 中的 windows 目录及 program file 目录的集合。
/usr/bin/ 一般的使用者指令及应用软件。
/usr/games/ 一些小游戏。
/usr/include/ 标准 C 语言的标头文件。
/usr/lib/ 系统函式库。
/usr/libdata/ 一些系统工具的数据库。
/usr/libexec/ 系统服务程序 (daemons) 及工具。
/usr/local/ 非 FreeBSD 所附的软件都会安装在这个目录下,我们在安装软件时最好都安装在这个目录。您可以将它视为 Windows 操作系统中的 program file 目录。这个目录中也有 bin sbin etc lib 等目录。
/usr/obj/ 在编译 FreeBSD 系统时存放过程中暂存盘的位置。
/usr/ports/ FreeBSD ports 移植软件的原始程序目录,我们可以从这个目录中找到自己想要的软件来快速安装。
/usr/sbin/ 可以让使用者执行的系统服务及工具。
/usr/share/ 系统软件共享的数据库。
/usr/src/ 放置 BSD 或其它软件原始程序代码的目录。
/usr/X11R6/ X Windows 的目录。
/var/ 放置系统记录文件、暂存盘的目录。
/var/account/ 使用者执行过的指令记录文件,请 man acct。
/var/at/ 定时执行排程的数据文件。请 man at。
/var/backups/ 系统重要档案的备份区。
/var/cron/ 使用者排程的数据表,请 man cron。
/var/db/ 重要的系统数据库。
/var/games/ 内附的游戏纪录文件。
/var/log/ 系统记录文件,我们可以在这里查看系统状况记录。
/var/mail/ 使用者信件暂存区。
/var/preserve/ 文件编辑时异常中止时,会将文件存到这个目录,请 man ex。
/var/msgs/ 系统讯系的数据库,请 man msgs。
/var/quotas/ 档案系统使用容量限制的记录。
/var/run/ 记录系统开机后执行状态的暂存区。请 man utmp。
/var/spool/ 列表机或邮件输出时的缓冲区。
/var/tmp/ 系统暂存区,开机时不会清除。
/var/yp/ the NIS maps。

相对路径与绝对路径

我们可以看到 UNIX 系统的目录结构是树状结构,而我们可以使用 cd 这个指令来改变目前的工作路径。当我们要在目录之间移动时,必须要输入路径名称。 而在输入路径时,有二种输入方式:相对路径及绝对路径。

所谓的绝对路径就是以「/」为开头的路径名称。「/」在 UNIX 中表示根目录,也可以用来分开各个目录的名称。所以从根目录开始,指定路径名称就称为绝对路径。例如「/usr/bin」就是一个绝对路径。

相对路径就是相对于目前路径的目录。如果您现在的所在目录 (工作路径) 是「/usr」,而 /usr/share/man 的相对路径就是「share/man」。

另外,有二个特殊的路径「.」及「..」。「.」所代表的是目前所在路径,而「..」表示上一层目录。因此,如果您的所在目录是 /usr,而 /etc 的相对路径就是「../etc」。

3.2.3 档案与目录管理

我们已经知道 UNIX 系统中的目录结构,接下来我们看看如何管理这些档案及目录。

观看档案内容

最基本的档案格式纯文字文件。如果您要观看纯文本文件内容,可以使用 cat 这个指令:

# cat /etc/shells

# $FreeBSD: src/etc/shells,v 1.5 2000/04/27 21:58:46 ache Exp $
#
# List of acceptable shells for chpass(1).
# Ftpd will not allow users to connect who are not using
# one of these shells.

/bin/sh
/bin/csh
/bin/tcsh

cat 这个指令会印出档案内容。不过如果档案案很大时,画面会一下子就卷走了。

如果您想要看一个比较大的文字文件,可以使用 more 或是 less 的指令,这二个指令会将档案内容分页显示,我们只要按 [Page Up]、[Page Down]、或是空格键就显示可以上一页或下一页。您也可以使用上下键来一行一行往上或往下卷。

# more /etc/rc.firewall

如果您看到一半想要离开,可以按 [q] 键即可。另外,如果您想要在 moreless 的输出中搜寻一个字符串,可以按 [/] 之后,再输入相要找的字即可。

小提示

您有没有注意到我们在使用指令 man 时也是分页显示,它其实就是使用 more,所以您也可以按 「q」来离开,或「/」来查找一个关键词。

档案与目录管理

我们简单介绍一下如何建立目录、复制档案、删除及搬移档案。首先,如果您要建立目录,可以使用 mkdir 这个指令:

# mkdir myfolder

我们给 mkdir 指令一个参数 myfolder,表示建立一个名为 myfolder 的目录。这个目录的参数可以是相对路径也可以是绝对路径。建立了目录后,您可以使用 ls 看一下它是不是真的建出来了。

如果您要复制一个档案或目录,可以使用 cp 这个指令:

# cp /etc/rc.firewall ./firewall
# cp /etc/rc ./
# cp -R myfolder folder1

上述第一行指令表示将 /etc/rc.firewall 复制一分到目前目录下,并命名为 firewall。如果您不指定档名,例如第二行指令,表示将该档案复制后维持同样的文件名称。如果您所要复制的是目录,必须加上 -R 的参数,如第三行指令所示。

接下来是重新命名档案或目录名称,重新命名或是搬移档案都是使用 mv 这个指令:

# mv folder1 folder2
# mv firewall /tmp/tmpfile
# mv /tmp/tmpfile folder2

第一行指令表示将 folder1 更名为 folder2,第二行指令是将 firewall 这个档案搬到 /tmp 目录下,并更名为 tmpfile。而第三行指令是将 /tmp/tmpfile 搬到 folder2 目录下。我们可以看到第三行指令比较特别,因为 folder2 是已经存在的一个目录,所以在更名时,档案会直接被放在该目录下。如果 folder2 不存在时,第三行指令的结果就会变成是将 /tmp/tmpfile 搬到目录所在目录下,并更名为 folder2。

接下来我们看看要如何删除档案及目录:

# rm folder2/tmpfile
# rm -rf folder2

第一行指令就是要删除 folder2 目录下的 tmpfile。如果您要删除的是目录,则必须加上 -r 的参数,如第二行所示。而参数 -f 表示强制删除,如果档案或目录不存在时,不要显示任何错误讯息。

文件名称规则

我们在命名档案或目录时,有一些特殊字符是不可以使用的,例如「/」表示根目录,而且会用来分开目录名称,所以不可以使用。另外,还有一些规则:

除此之外,有三个特殊字符在使用上要特别小心,分别是「\」、「*」及「?」。「\」在 UNIX 中是一个换行符号,也是一个跳脱字符。当我们在命令列要下一个指令太长时,可以使用「\」来换成,例如:

# ls /usr/bin \  <- 按 [Enter]
? /usr/local

在上述指令中,我们第一行最后有一个「\」,按下 [Enter] 后,会出现一个问号的提示字符,接着我们可以再继续输入未完成的指令,最后的结果就好像是二行指令变成一行一样。

另外「\」还可以做为跳脱字符。例如,我们要建立一个文件名称就叫做「\」,这时候我们可以在 「\」的前面再加一个「\」,表示取消「\」的特殊意义。

「*」及「?」分别代表了「任何字」及「任何字符」,例如下列二行指令:

# ls /etc/net*
/etc/netconfig     /etc/netstart     /etc/network.subr    /etc/networks
# ls /etc/rc.con?
/etc/rc.conf

第一行指令是要列出 /etc 目录下任何开头为 net 的档案,不管 net 后面有几个字都列出来。而第二个指令是要列出 /etc 下,任何开头是 rc.con,而最后一个字符是任何字的档案。

「*」表示任何字,不管是几个字符,而「?」表示任何字符,因为这二个字是特殊字符,我们不建议您用在档案命名上。如果您非要以这二个字为档名,必须在该字前面加上「\」来跳脱它的特殊意义。例如:

# mkdir abc\*
# rm -r abc\*

搜寻档案

我们已经知道基本的档案管理了,接下来我们来看看要如何在茫茫人海中寻找一个档案。

如果您要找的是指令所在路径,可以使用 whereis

# whereis pwd
pwd: /bin/pwd /usr/share/man/en.ISO8859-1/man1/pwd.1.gz /usr/src/bin/pwd

我们可以看到 pwd 这个指令的位置是 /bin/pwd,另外还有它的使用手册及原始码路径也列出来了。

如果你要找的是任何类型的档案,可以使用 find。例如,我们要在 /etc 找 rc.conf 这个档案的位置:

# find /etc -name rc.conf
/etc/defaults/rc.conf
/etc/rc.conf

find 的第一个参数是要找的路径名称,接着我们使用 -name 后面加上文件名称来找 rc.conf 这个档。如果您要找所有扩展名为 .conf 的档案,可以用下列指令:

# find /etc -name "*.conf"
/etc/apmd.conf       /etc/host.conf    /etc/natd.conf       /etc/rc.conf
/etc/auth.conf       /etc/inetd.conf   /etc/newsyslog.conf  /etc/resolv.conf
/etc/devd.conf       /etc/login.conf   /etc/nsmb.conf       /etc/sysctl.conf
/etc/devfs.conf      /etc/mac.conf     /etc/nsswitch.conf   /etc/syslog.conf
/etc/dhclient.conf   /etc/make.conf    /etc/pf.conf         /etc/usbd.conf

更多 find 指令的用法请参考「指令应用」一章的说明。

3.2.4 重导 I/O 及管道

所谓的重导 I/O 就是重新导向输入或输出的数据。在 UNIX 中有所谓的标准输入和标准输出。标准输入指的是预设的输入方式,例如我们在输入指令时,标准输入就是键盘,而标准输出就是将结果输出到预设的输出装置,也就是我们的屏幕。

然而,我们也可以使用一些特殊字符将标准输入、输出导向到其它地方。如果我们要重新导向标准输出,可以使用「大于」符号「>」,例如,我们可以让指令 ls 的结果不要显示在屏幕上,而导向输出在档案中:

# ls /etc > /tmp/result

上述指令的结果就会在 /tmp/result 中新增一个档案,内容就是 /etc 的档案列表。另外,我们可以使用 cat 这个指令及「>」来建立一个小的文字文件。cat 这个指令会将我们所输入的数据印在屏幕上,我们可以将输出重新导向到一个档案中:

# cat > /tmp/result
/etc/rc.conf
/etc/rc.firewall
[Ctrl]+[d]

我们在输入指令后就可以开始输入内容,最后要离开只要按 [Ctrl]+[d] 即可。

上述指令中,我们使用一个「>」,它会建立一个新的档案 /tmp/result,如果该档案已存在,它会将档案清空。如果我们使用二个「大于」符号「>>」,则会在档案后面附加上内容,而不会清除档案原本的内容:

# cat >> /tmp/result
/etc/rc
[Ctrl]+[d]

经过上述指令后,/tmp/result 就会变成有三行资料了。

那我们要如何重导标准输入呢?既然标准输出是「>」,标准输入自然就是「<」了。例如,在 FreeBSD 中有一个 nslookup 指令可以用来查主机名称,它的使用方式如下:

# nslookup
> twbsd.org
Server:         168.95.192.1
Address:        168.95.192.1#53

Name:   twbsd.org
Address: 220.132.178.72
> exit

执行了 nslookup 后,我们必须输入所要查找的主机名称,最后输入 exit 离开。我们可以新增一个档案,内容为多个主机名称,最后使用下列指令一次喂给 nslookup

# nslookup < filename

除了重导 I/O 外,还有一个类似重导的功能,称之为管道 (pipe)。我们可以将一个指令的输出转向到另一个指令的输入,而转向的方式就是使用「|」的符号。例如,我们可以将 ls 指令的输出,转向到 more 这个指令进行分页:

# ls /etc | more

另外有二个常用来和管道配合使用的指令「sort」及「grep」。sort 指令是用来做排序用,例如,我们可以将 ls 的输出结果依文件名称排序:

# ls /etc | sort

而 grep 指令可以用来过滤我们想要的数据,例如,我们可以将 ls 的结果导向到 grep 去找出文件名有包含 rc 的档案:

# ls /etc | grep rc

我们也可以在 grep 指令中加上参数 -v 表示要滤掉的字符串。例如下列指令就会滤掉文件名包含 host 的档案:

# ls /etc | grep -v host

3.3 文书编辑器

因为许多系统设定都必须修改设定档,而修改设定文件必须使用文书编辑软件,所以在开始所有设定之前,让我们先来了解文书编辑器的用法。

我们将介绍 FreeBSD 内附的二套文书编辑软件 ee 及 vi。这二套软件都是在命令列模式下使用的软件,ee 是一套比较适合初学者的编辑器,它的使用方式和我们一般的使用习惯较接近,操作简单又容易上手。不过 ee 是 FreeBSD 特有的编辑软件,在其它的 UNIX 系统中无法使用。因此,我们也将介绍另一套所有 UNIX 系统都内附的编辑器 vi。

vi 是一套威力强大的工具,操作熟练的人会觉得如有神助,而对于初学者而言却是望之却步。是否要将 vi 练到出神入化见人见智,但对于一个 UNIX 系统管理者而言,我们至少要知道一些基本的操作方式。

3.3.1 ee

ee 是 FreeBSD 系统内附较适合初学者的文书编辑软件,它是 Easy Editor 的简称,顾名思义 ee 使用上十分容易。当您要编辑档案 example.txt 时,只要在命令列上打 ee example.txt 即可。执行 ee 之后将会出现下列画面:

图 3-3

在画面最上方有使用说明,几乎我们所有的会使用到的功能都在最上方的说明中。您可以使用上下左右键来移动游标,并直接输入内容,以下为 ee 的指令说明,请注意我们将键盘上独立的按键以小于及大于的符号括起来,例如 <Ctrl> 表示键盘上 Ctrl 这个键:

按键 意义
<Ctrl> + [ 或 <ESC> 键 显示主选单。
<Ctrl> + o 输入 ASCII code,例如输入 65 就会显示 A。
<Ctrl> + u 跳到档案结尾。
<Ctrl> + t 跳到档案开头。
<Ctrl> + c 输入指令。在按了 Ctrl+c 后,上方选单会出现命令说明,例如您可以直接输入数字,表示将光标移到某一行。
<Ctrl> + y 搜寻。按了 Ctrl+y 之后,你可以输入欲搜寻的字符串。如果要搜寻下一个该字符串,只要再按 Ctrl+x 即可。预设的搜寻是不分大小写的,如果要区分大小写,您可以按 Ctrl+c 并输入 case 即可。如果要取消只要再按 Ctrl+c 并输入 nocase。
<Ctrl> + a 跳到行首。
<Ctrl> + e 跳到行尾。
<Ctrl> + d 删除光标所在位置的字符。
<Ctrl> + j 贴上上一次所删除的字符。
<Ctrl> + k 删除光标所在位置的一整行。
<Ctrl> + l 贴上上一次删除的一整行内容。
<Ctrl> + w 删除一个字。
<Ctrl> + r 贴上上一次所删除的字。
<Ctrl> + p 将光标移到上一行。
<Ctrl> + n 将光标移到下一行。
<Ctrl> + b 将光标移到上一个字,和方向键左键一样。
<Ctrl> + f 将光标移到下一个字,和方向键右键一样。
<Ctrl> + g 下一页。
<Ctrl> + v 上一页。
<Ctrl> + z 移到下一个字。
<Esc> + <Enter> 离开 ee。如果档案有修改过,它会问您是否要储存档案。

当我们按了 <Esc> 键时,会出现一个主选单,在选单中我们可以进行一些设定,如果您储存这些设定,它会被存在您的 home 目录下的 .init.ee,以 root 为例,设定档会存放在 /root/.init.ee。如果您要还原默认值,只需将该档删除即可。

3.3.2 vi

Vi 是一个历史悠久且功能强大的 UNIX 文书编辑器。在古早的年代,许多键盘都只有一些基本按键,连上下左右键都没有,所以 vi 大多数的功能都必须使用一些特殊的按键。

Vi 在使用时可以分成二种模式,一种是「编辑模式」,另一种则为「命令模式」。在编辑模式时,我们可以使用上下左右键来移动光标并编辑输入我们所要编辑的文字内容。而命令模式时,我们可以进行档案操作 (开文件、存盘等)、搜寻等功能。使用 vi 时,我们会很常按 <Esc> 键,<Esc> 键可以让我们离开编辑模式并进入命令模式。请执行 vi example.txt 来编辑 example.txt 这个档案,一进入 vi 时,预设会处于命令模式,我们必需先输入 "o"、"i"、或"a"才能进入编辑模式。

以下即为进入编辑模式的指令:

按键 意义
i Insert (插入),在目前光标前开始输入。
a Append (附加),在目前光标后开始输入。
o 在光标下方新增一空白行并开始编辑。
O 在光标上方新增一空白行并开始编辑。

如果您输入错误,您无法使用 <Delete> 或 <Backspace> 来删除,我们必须使用 vi 的其它命令来进行。请先按 <Esc> 来进入命令模式,接着您就可以使用下列指令来进行进阶编辑:

按键 意义
x 删除光标所在位置的字符。
dw 删除游标所在到字尾,即删除一个字。
dd 删除游标所在一整行。
d + 数字 + <Enter> 删除从光标所在位置到其下方 n 行。例如输入 d5 <Enter>,将删除光标所在位置起 6 行。
yw 复制光标开始到字尾。
yy 复制游标所在一整行。
y + 数字 + <Enter> 复制从光标所在位置到其下方 n 行。例如输入 y4 <Enter>,将复制光标所在位置起 5 行。
p 贴上上一次复制的内容。
:w <Enter> 存档。
:w 文件名称 <Enter> 另存新檔。您必输在 w 后输入新的档名。
:q <Enter> 离开 vi。如果档案有修改过会无法离开。
:wq <Enter> 存档并离开。
:q! <Enter> 不存档并离开。

接下来我们说明一下如何在档案中穿梭移动:

按键 意义
h 游标向左移。
j 游标向下移。
k 游标向上移。
l 游标向右移。
^ 跳到行首。
$ 跳到行尾。
w 游标跳到下个字的开头。
e 游标跳到下个字的结尾。
b 游标跳到上个字的开头
<Ctrl> + d 光标往下移动半个屏幕。
<Ctrl> + u 光标往上移动半个屏幕。
<Ctrl> + f 光标往上移动一个屏幕。
<Ctrl> + b 光标往下移动一个屏幕。
:数字 <Enter> 跳到 n 行,例如输入 :100 即可将光标移到第 100 行。
/欲搜寻的字符串 <Enter> 输入 / 后,您可以在 / 后输入所要搜寻的字符串,如果要找下一个,则直接按 / <Enter> 即可。

只要您熟悉了上列指令,您大概就可以很轻松的使用 vi 了。Vi 还有许多功能,你可以 man vi 来获得更多信息。

3.4 Shell 环境简介

在 UNIX 系统中,使用者对于系统的操作是透过 "Shell",Shell 就好像是 DOS 中的 command.com 或 Windows 中的 explorer.exe。Shell 在接收到指令之后,会将它转换成机器可以读的语法来对系统进入操作。

FreeBSD 内附的 Shell 有 sh、csh、tcsh,sh 名为 Bourne Shell,它是 UNIX 系统中最悠久的 shell,所有的 UNIX 系统都会内附这个 shell,我们在写 shell scripts 时为了可移植性,大多使用 sh。在 FreeBSD 中 csh 和 tcsh 是一样的东西,csh 名称的由来是因为它的 scripts 语法和 C 语言很像。至于要使用哪一种 shell 全凭个人偏好,您也可以自行从 ports 中安装 Linux 用的 bash 或 ksh。

以笔者个人而言,写 shell scripts 自然是使用 Bourne Shell,而系统登入时,我偏好使用 tcsh。tcsh 除了有 3.2 节中提及的使用 <Tab> 键自动完成档名外,最重要的一点是它会自动搜寻上一次输入的指令 (history-search-backward)。

例如,我们输入下列指令:

# ls /usr/port/www
# cd /usr/port/www
# cd /usr

在输入上述指令后,现在我们如果使用键盘方向键按上,将出现上一次所输入的指令内容。如果我们先打了 ls 再按方向键上,则 tcsh 会自动找出最近输入过开头为 ls 的指令,多按几次上它还会继续出现上上一次输入过的 ls 指令,很棒吧。

小提示

FreeBSD 的 tcsh 有 history search backward 的功能是因为在 ~/.cshrc 中有二行: 

bindkey -k up history-search-backward
bindkey -k down history-search-forward

如果您不想使用 history search backware,只要将该二行删除即可。

如果您想变更自己所使用的 Shell,可以执行下列指令:

# chsh -s /bin/tcsh

上述指令中,我们将所使用的 Shell 变更成 /bin/tcsh。请注意,您所输入的 shell 名称一定要存在于 /etc/shells 这个档中。系统预设的 shell 有 /bin/sh/bin/csh/bin/tcsh。 如果想使用自行安装的 shell,您必须先将该 shell 的路径加入 /etc/shells 中才可以使用。

3.4.1 Shell 的环境变量

在 Shell 有所谓的环境变量,当我们在 shell 中执行指令时,这些环境变量可能会被该程序用来判断程序所要执行时的参数。例如,我们在执行 cal 这个指令时,我们不必打它的绝对路径 /usr/bin/cal,因为 shell 会自动依照 PATH 这个环境变量所设定的路径去找我们所输入的指令。您可以使用下列指令来看目前 PATH 这个变量的内容:

# echo $PATH
/sbin:/bin:/usr/sbin:/usr/bin:/usr/games:/usr/local/sbin:/usr/local/bin

如果您使用 tcsh,您也可以打 setenv 来看目前所有的环境变量。以下为一些常用的环境变量:

变量名称 描述
USER 目前所使用的使用者名称。
PATH 执行指令所要搜寻的位置,以冒号隔开。
SHELL 目前所使用的 Shell。
TERM 目前所使用的终端机模式。
OSTYPE 操作系统名称。
MACHTYPE 系统所使用的 CPU 架构。
PAGER 当需要分页时,所要使用的分页软件,如 more 或 less。例如 man 这个指令就会参考您所设定的 PAGER 而使用 more 或 less。
EDITOR 预设所要使用的编辑器。

您也可以使用 setenv 来改变一个环境变量的值。例如,我们要将预设的文书编辑器改成 ee,在 tcsh 中可以使用:

# setenv EDITOR ee

如果您使用的是 Bourne Shell:

# export EDITOR="ee"

3.4.2 Tcsh 的环境设定

登入系统后,您会发现在光标之前有一个井字号 "#",这个井字号我们称之为提示符号 (prompt)。在 tcsh 及 csh 中,当以 root 登入时,预设的提示符号是 "#",而以一般使用者登入时,提示符号为 "%"。

FreeBSD 安装好后,我们必须做一些设定让 FreeBSD 使用起来更顺手。在预设的况状下,系统并不支持中文文件名,对于使用中文的人不太方便。另外,命令列提示符号的样子也不符合我们的需求。如果你想要客制化一些指令,也可以在这里加上去。所以在开始进行其它设定之前,我们先建立一个良好的使用环境。

在使用者登入后,Tcsh 会先去读取 /etc/csh.cshrc/etc/csh.login 的设定,接着会读取该使用者家目录下的 .cshrc 及 .login。因此,我们可以经由设定这几个档案让设定使用者一登入时就生效。

首先编辑 /etc/csh.cshrc 加入下列设定:

setenv EDITOR ee
alias ls ls -F
set prompt = "%B%m [%~] -%n-> "

第一行设定是将预设的文书编辑器改成 ee。第二行是要将指令 ls 变成 ls -F,就是每次打 ls 时,系统会出现 ls -F 的效果。而第三行是将命令列的提示符号改成下面这样:

mydomain [/home/john] -john->

就是开头是机器名称,再来是路径名称,最后是使用者名称。修改完 csh.cshrc 或 ~/.cshrc 后,您必须注销再登入才会看到修改后的效果。或者,您也可以使用 下列指令来让修改立即生效:

# source ~/.cshrc

由于在 /etc 下的 csh.cshrc 是通用的设定,但如果使用者自己的设定和通用设定一样时,会以使用者的设定为主。例如,在一般使用者的家目录下的 .cshrc 也有一行编辑器的设定,当设定不同时,会以使用者目录下的设定为主。因此,我们必须再编辑 ~/.cshrc,将 EDITOR 从 vi 改 ee,如此一来设定才会生效。

如果您希望日后每个新增的使用者的设定都是这样,则必须修改 /usr/share/skel/dot.cshrc 档案,该档内容的修改和修改 ~/.cshrc 一样,把 vi 换成 ee ,并加入 「alias ls ls -F」。因为在使用 adduser 指令新增使用者时,它会问你是否要将 /usr/share/skel/dot.file 复制到使用者目录下,因此我们就修改这里,让日后新增使用者时能使用该设定。

/etc/csh.cshrc/etc/csh.login 的差别在于如果是使用者登入,二个档案都会被执行,如果是 scripts 则只会去读取 csh.cshrc。我们接下来要让使用者登入后可以支持中文的 console 环境,所以我们编辑 /etc/csh.login 并在最后面加入以下的设定:

# 支持中文的环境,让我们可以在 console 下或 telnet 中使用中文。
setenv LANG zh_TW.Big5

上述的环境变量设定会在使用者登入时自动被加载,一些程序 (例如 date) 会自动读取这些变量,并产生中文的讯息。不过由于我们的 console 尚未支持中文,我们必须先安装中文终端机软件,或在支持中文的 PC 上使用 telnet 登入。别急,我们会在下面几节中说明如何安装中文终端机。

3.5 使用者及权限管理

由于 FreeBSD 和所有的 UNIX 系统一样,在设定上都是为了支持多个使用者的环境,所以在使用者管理上必须考量到多个使用者同时使用时所会造成的影响。例如使用者 A 不可以删除使用者 B 的数据,某些使用者可以存取某些数据夹,某些则否。为了让系统管理更有效率,在支持多人使用的操作系统中,都有群组及权限的观念。

在 UNIX 系统中,每个使用者「至少」会属于一个群组,我们可以针对不同使用者或不同群组来设定他们在系统中的使用权限。以学校为例,每一个不同科系的学生都可以自由使用该科系中的资源。例如,只有资工系的学生可以使用资工系计算机教室、研究室等,这个「科系」就是使用者的预设群组。管理者可以针对这个群组去设定该群组可以使用的资源,而不必针对一个个学生设定。而每个学生还可以参加多个社区,例如管乐社、吉他社等。而只有该社团的成员才可以使用社团资源,如借用乐器、申请经费。这时候我们就可以把社团看成一个个使用者额外加入的群组。

上述例子中,在 UNIX 系统的实际情形可能是有一个使用者「u654321」,它的预设群组是「csie」,同时,他也是「guitar」群组。日后有新的资工学生时,我们只要将它加入「csie」群组即可,他就会具有资工学生的所有功能,而不必在新增使用者时去设定很多权限。

所以我们在新增使用者时,必须指定他的群组,预设的群组是一个和使用者同名的新群组,我们先来看看新增使用者的过程,请使用指令 adduser 来新增使用者。系统会问您一些问题:

# adduser
Username: jack

执行了 adduser 之后,首先要输入使用者名称,使用者名称除了英文字、数字及 -_ 外不可以包含其它特殊字符。

Full name: Jack

接着我们要输入使用者全名,这个字段可以是空的,如果您不输入则直接按 Enter 即可。

Uid (Leave empty for default):	

这个字段是使用者编号,直接留白按 Enter 即可,系统会自动指定。

Login group [jack]:

输入使用者群组名称,群组名称预设会自动产生一个和新增的使用者同名的群组,如果要使用不同的群组,必须先手动新增群组。我们直接按 Enter 即可。

Login group is jack. Invite jack into other groups? []: wheel

是否要将新的使用者加入其它群组,由于这是我们新增的第一个一般使用者,所以我们将它加入系统管理者 wheel 这个群组,让他可以使用 su 这个指令来切换身份成 root。

Login class [default]:

登入的类别,这是用来分类控制使用者对于系统资源的使用,请参考「使用者管理」一章中关于系统资源限制的说明。在这里我们直接按 Enter 使用默认值即可。

Shell (sh csh tcsh nologin) [sh]: tcsh

输入所要使用的 Shell,建议输入 tcsh,如果您不想让该使用者登入系统,可以输入 nologin。

Home directory [/home/jack]:

输入使用者的家目录,也就是使用者在系统中的数据夹,所有使用者的目录我们都放在 /home 下,所以我们直接按 Enter 即可。

Use password-based authentication? [yes]:

是否要使用密码认证的方式,预设为是,我们直接按 Enter 即可。

Use an empty password? (yes/no) [no]:

是否要使用空密码,预设为否。

Use a random password? (yes/no) [no]:

是否使用随机产生的密码,如果使用随机产生的密码,在新增完毕后,系统会告知我们产生的密码,预设为否。

Enter password:

输入该使用者的密码。

Enter password again:

再输入一次密码,以确认输入无误。

Lock out the account after creation? [no]:

在新增完使用者后,是否要先将该账户关闭。

最后会显示我们刚才输入的结果:

Username : jack
Password : *****
Full Name : Jack
Uid : 1003
Class :
Groups : jack
Home : /home/jack
Shell : /bin/tcsh
Locked : no
OK? (yes/no): y

如果全部 ok 则输入 y。

adduser: INFO: Successfully added (jack) to the user database.
Add another user? (yes/no): n
Goodbye!

最后系统会询问我们是否要新增另一个使用者,如果没有则按 n 离开。

新增完使用者后,我们可以看到 /home 目录下多了一个使用者 jack 的目录:

# ls -la /home
drwxr-xr-x  10 root    wheel      512  3 21 16:12 ./
drwxr-xr-x  21 root    wheel      512  1 14 06:29 ../
drwxr-xr-x  13 jack    jack      1024  3 21 16:05 jack/

"." 及 ".." 这二个目录分别代表着目前所在的目录及上一层目录,我们可以看到它的拥有者是 root,群组是 wheel。而 jack 这个目录的目录的拥有者是 jack,其群组也是 jack。

图 3-4

在 ls 结果的第一个字段表着该档案或目录的存取权限,该字段共有十个字符,第一个字符表示档案的类型,以 jack 这个目录为例,它的类型是目录,所以第一个字是 d,如果是一般的档案,则第一个字是 - 。除了目录和一般档案之外,还有可能有「l」表示是连结档 (link)、「b」及「c」代表装置文件 block device 及 charactor device。连结文件就像是 Windows 系统中的快捷方式,而装置文件是 FreeBSD 用来管理硬件的方式,FreeBSD 会将键盘、硬盘等装置都用装置文件来管理,而这些装置文件都放在 /dev 中。

除了档案类型外,接下来的九个字符,以三个为单位,分别代表着使用者 (User)、群组 (Group)、及其它人 (Others) 的权限:

我们看到 jack 这个目录,它的权限是 rwxr-xr-x,前三个字 rwx 表示使用者 jack 对于这个目录有读取、写入及进入目录的权限;接下来的 r-x 表示 jack 群组可以读取及进入该目录,但无法写入数据;最后三个 r-x 表示其它使用者可以读取、进入该目录。

在 UNIX 世界中,档案的类型和扩展名完全没有关系,扩展名只是我们一般的命名习惯,只是参考用。档案是否为可执行档,除了档案本身必须要是可执行外,档案权限方面一定要有执行的权限才行,也就是执行的人必须对于该档案有「x」权限。

使用者的权限除了可以使用 rwx 来表示外,我们也可以使用数字来设定权限。假设档案拥有者的权限为 rwx,由于 r 代表的数字是 4、w 是 2、x 是 1,所以档案拥有者的权限就是 4+2+1,也就是 7。同理,如果群组的权限是 r-x,则数字表示为 4+0+1,也就是 5。如果我们要将权限设成 rwxr-xr--,则数字就是 754,如下图所示:

图 3-5

假设我们要更改档案 file.txt 的权限为 rwxr-xr-- (754),我们可以使用 chmod 这个指令:

# chmod 754 file.txt

我们上面提及的权限都是以三位数字来表示,另外我们也可以使用四位数字表示。所谓的四位数字是指在原本的三位数之前加上一个关于档案形态的设定。

假设我们要设定档案 myfile 可以被所有人读、写、执行,并设定 sticky:

# chmod 1777 myfile

除了使用数字一次设定权限之外,我们也可以分别针对档案的使用者、群组及其它人来设定权限。chmod 这个指令在权限的参数部份,除了使用数字外,也可以使用 (对谁)(做什么动作)(权限) 这种语法。

项目 使用的字符 代表意义
对谁 u 使用者 (User)
对谁 g 群组 (Group)
对谁 o 其它人 (Others)
对谁 a 所有人 (All)
做什么动作 + 增加权限
做什么动作 - 移除权限
做什么动作 = 直接设定权限
权限 r 读取
权限 w 写入
权限 x 执行
权限 t Sticky
权限 s Set UID 或 GID

例如,我们要设定其它人对档案 file.txt 只有读取及执行的权利:

# chmod o=rx file.txt

更多 chmod 的用法,请参考「指令应用」一章中的说明。

3.6 系统服务及行程管理

FreeBSD 和其它常用的操作系统一样都是多任务的环境,我们可以同时执行数个工作,例如同时听音乐、开浏览器上网。在系统一开机后,便会自动执行许多程序来维持系统的正常运作。这些正在执行的程序我们称之为行程 (process)。

3.6.1 行程

每一个行程都有一个与众不同的编号,称之为 process id (PID)。所有正在执行中的程序都需要使用到一些系统资源,例如内存、CPU 等等。PID 的做用就是让系统可以根据这一个独特的编号来做资源的调配及工作排程。当我们在进行管理这些程序时,也必须要依照 PID 来区分不同的行程。

几乎所有的行程都是由其它程序所呼叫执行的,这个呼叫、执行一个新的行程的人是该行程的 parent。例如当我们执行了 ls 时,ls 这个行程的 parent 就是我们当时所使用的 shell。唯一没有 parent 的例外是 init 这支程序。当 FreeBSD 开机执行完系统核心程序之后,会自动执行 init 这支程序,由于这是开机后所执行的第一支程序,所以它的 PID 是 1。init 执行之后,会再呼叫其它程序,例如 /etc/rc 来启动开机必须执行的系统设定等。

每一个行程和档案、目录一样,都有行程的拥有者及群组。程序执行之后,可能必须要开启某些档案或对于系统装置进行存取,而使用这些资源时,即是以该行程的拥有者及群组的身份进行存取。

我们可以使用 ps 这支程序来取得行程的信息,以下即为 ps 指令的输出结果:

# ps
PID    TT  STAT   TIME      COMMAND
77393  p0  ILs    0:00.02   login [pam] (login)
78056  p0  IL     0:00.02   su
78057  p0  SL     0:00.02   _su (tcsh)
78074  p0  RL+    0:00.00   ps
89678  v0  ILs+   0:00.01   /usr/libexec/getty Pc ttyv0
78073  v1  SLs+   0:00.01   /usr/libexec/getty Pc ttyv1
 616   v2  ILs+   0:00.00   /usr/libexec/getty Pc ttyv2
 617   v3  ILs+   0:00.00   /usr/libexec/getty Pc ttyv3
 618   v4  ILs+   0:00.00   /usr/libexec/getty Pc ttyv4
 619   v5  ILs+   0:00.00   /usr/libexec/getty Pc ttyv5
 620   v6  ILs+   0:00.00   /usr/libexec/getty Pc ttyv6
 621   v7  ILs+   0:00.00   /usr/libexec/getty Pc ttyv7

我们可以看到第一个字段是 PID,它的范围从 1 到 99999,当用完了 99999 后,系统会自动从头开始找一个没人用的 PID 来使用。Kernel thread 的 PID 是 1 到 100,100 以后才是供一般使用者程序使用。TT 这个字段是我们正在使用的 tty,如果是在 console 前执行的执令,则 tty 为 ttyvX,如果是 telnet 到系统中,则 tty 为 ttypX。STAT 字段为目前该程序的状态 ,您可以 man ps 以查询各个 state 所代表的意义。TIME 则是该程序所使用的 CPU 时间。最后的字段 COMMAND 则是该程序被执行时所下的指令。

除了 ps 之外,我们也可以使用 top 来查看所有行程的状态:

# top
last pid: 78151;  load averages:  1.11, 1.04, 1.01   up 27+14:45:03  18:02:07
51 processes:  3 running, 48 sleeping
CPU states:  0.2% user, 96.8% nice, 1.5% system, 1.5% interrupt, 0.0% idle
Mem: 114M Active, 45M Inact, 64M Wired, 12M Cache, 34M Buf, 7952K Free
Swap: 512M Total, 372K Used, 512M Free

 PID USERNAME  PRI NICE   SIZE    RES STATE    TIME   WCPU    CPU COMMAND
235  root      96    0  1616K  1044K select 114:50  0.05%  0.05%  natd
425  root      96    0  9644K  4836K select   2:02  0.00%  0.00%  httpd
4872 root      96    0  3900K  2048K select   1:40  0.00%  0.00%  top
470  root      96    0  3776K  2240K select   1:39  0.00%  0.00%  sendmail
290  root      96    0  1312K   764K select   0:30  0.00%  0.00%  syslogd
490  root       8    0  1336K   864K nanslp   0:17  0.00%  0.00%  cron
    

top 这个指令会每二秒自动更新一次。我们可以看到 top 的输出分成二个部份,最上方是目前关于行程的的系统状态。包含最后一个 PID (last pid)、系统负荷 (load average) 、已开机时间 (up)、总共有多少行程正在执行中、及 CPU 和内存的使用量等等。第二个部份和 ps 一样,列出 PID、行程的拥有者、及其它和行程相关的状态。其它更多关于 ps 及 top 的用法,请参考「指令应用」一章的说明。

3.6.2 系统服务及行程管理

我们每执行一个指令,都会产生一个新的行程,有的程序在执行完毕后,就会结束离开;而有的程序会常驻在系统中。例如当我们执行 ls 这个指令时,会产生一个新的行程,在该指令列出了目录或档案信息后,便会立即结束。而像网页服务器所执行的 httpd 这类的程序,会一直常驻在系统中,随时等候联机的要求,这种常驻的程序称之为 daemon。

Daemon 这个字是由希腊神话而来,Daemon 是一只会跟随在主人身边的小恶魔,它是个调皮的小东西,会帮人类做一些有用的事。不过它本身并没有善恶之分,也可能会做出不好的事情,全看人类本身。

FreeBSD 系统内附的 daemon 在命名上大都依循一定的规则,例如 FTP daemon 所执行的程序是 ftpd,而负责 telnet 服务的 daemon 叫做 telnetd,大到上就是在该服务的名字后面加上一个 "d" 结尾。其它非 FreeBSD 内附的程序大都有类似的规则,像 Apahce 这种网络服务器的主要执行程序为 httpd。但也有例外的程序,例如系统中的邮件服务器 Sendamil,它的执行档是 sendmail 而非 smtpd 或 maild。

通常 daemon 在执行后,会将自己的 PID 以扩展名为 .pid 的档案写在 /var/run 目录下,例如 /var/run/syslogd.pid/var/run/cron.pid。 该档案的内容为该 daemon 的 PID,可以让我们直接看该档案而得知该程序的行程编号。

有时候我们可能会需要和正在执行中的 daemon 沟通。例如当我们修改了 /etc/syslog.conf 这个 syslogd 所使用的设定档时,我们必须告诉它这个档被修改过了,请重新读取。和 daemon 沟通的方式就是传送给它一个信号 (signal),程序在收到信号后,会依照信号的类别做不同的事。以上述要求 syslogd 重新读取设定档为例,我们会送给它一个 SIGHUP 的信号。

除了 SIGHUP 外,如果我们想要终止一个程序的执行,可以传送 SIGTERM 或 SIGKILL 的信号。SIGTERM 表示通知正在执行中的程序我们希望它中止执行,如果该程序中有接收 SIGTERM 的机制,它可以做一些离开前的处理,例如关闭所开启的档案、结束某些正在执行的动作等等。然而,收到 SIGTERM 的程序也可以选择忽视,但 SIGKILL 则是不管程序是否在忙着其它事情,都必须中即停止,而且这个信号是不可以被忽视的。所有的信号都可以使用数字来表示,例如 SIGHUP 可以使用数字 1 表示、SIGTERM 为 15、SIGKILL 为 9。

系统中传送信号的指令是 kill 这个指令,假设我们要送一个 SIGHUP 的信号给 PID 为 199 的程序,我们可以使用下列指令:

# kill -HUP 199

上述指令中的参数 -HUP 也可以使用 -1 来取代。

值得注意的是,只有超级使用者 root 可以送信号给不属于自己的行程,而一般使用者只能管理自己的行程。

小提示

管理者可以对系统有最大的控制权,您可以使用 kill 去删除其它使用者正在执行的工作。例如,若有人正在复制档案,而系统变得很慢,您可以先使用 ps 去查出该指令的 PID,再用 kill -9 去停止该指令。而如果该使用在正在在线,他会在 console 中看到该指令被 killed 的讯息。

3.6.3 基本系统服务 inetd

在系统中有一个专门负责各式网络服务的超级服务器 "inetd"。 我们可以经由修改设定文件请它负责许多网络相关的服务,例如 telnet、ftp、ssh 等。当有 telnet 联机要求时,inetd 会依照设定执行负责 telnet 服务的 telnetd 这支程序,再将主导权转手给 telnetd,并继续等待下一个联机要求。若下一个联机是 ftp,则 inetd 会呼叫 ftpd 这支程序来负责。

其实像 ftpd 这类的程序,它本身也可以自己成为一支 daemon,由自己等待 ftp 的联机要求,而无需经由 inetd。使用 inetd 来管理这些网络服务的好处是我们不必为了提供十种网络服务而执行十个常驻程序。每一个常驻程序都会占用一些系统资源,而使用一个 inetd 来统筹,可以让这些资源空出来。另外,inetd 也可以用来过滤联机来源,针对不同的联机,我们可以使用 inetd 内建的 TCP Wrapper 功能来进行联机网域的限制,相关设定我们会再后续章节中提及。

有优点就会有缺点,使用 inetd 来管理网络服务固然有其优点,但对于联机较频繁、需要更快反应的服务而言并不合适。以 FTP 为例,一个联机进来,inetd 都必须重新执行一次 ftpd。如果我们是以 daemon 的方式,让 ftpd 常驻于系统中,则当有联机要求时,我们就可以直接将自己复制一份出来进行 ftp 服务,而不需重头执行。所以对于一台大型的 FTP 服务器而言,通常会使用独立 daemon 的方式。而一些较少使用的服务,如 telnet、ssh 等就交由 inetd 来处理。

FreeBSD 预设并不会启动 inetd,所以如果我们想要让它在一开机就执行,必须在 /etc/rc.conf 中加入下列设定:

inetd_enable="YES"

 

小提示

修改了 rc.conf 之后,必须重新开机 inetd 才会启动。或者,您也可以手动执行下列指令来立即启动 inetd:

# inetd -wW -C 60

我们在执行 inetd 时给了几个参数,表示要使用内建的 TCP Wrapper 功能,并限制每个 IP 来源一分钟内最多可以建立联机 60 次。这是系统开机时预设会给的参数 (在 /etc/defaults/rc.conf 中的 inetd_flags 指定)。

假设我们想要让 inetd 负责 telnet 及 ftp 服务,我们必须修改 /etc/inetd.conf ,将 telnet 及 ftp 前的 "#" 拿掉,如下所示:

# $FreeBSD: src/etc/inetd.conf,v 1.63 2003/06/09 21:04:30 markm Exp $
#
# Internet server configuration database
#
# Define *both* IPv4 and IPv6 entries for dual-stack support.
# To disable a service, comment it out by prefixing the line with '#'.
# To enable a service, remove the '#' at the beginning of the line.
#
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
#shell  stream  tcp     nowait  root    /usr/libexec/rshd       rshd
#shell  stream  tcp6    nowait  root    /usr/libexec/rshd       rshd
#login  stream  tcp     nowait  root    /usr/libexec/rlogind    rlogind
#login  stream  tcp6    nowait  root    /usr/libexec/rlogind    rlogind
#finger stream  tcp     nowait/3/10 nobody /usr/libexec/fingerd fingerd -s
#finger stream  tcp6    nowait/3/10 nobody /usr/libexec/fingerd fingerd -s
#exec   stream  tcp     nowait  root    /usr/libexec/rexecd     rexecd
  

接着,再使用下列指令来启动 inetd 服务:

# /usr/sbin/inetd -wW -C 60

如果 inetd 已经被启动了,而我们修改过 inetd.conf 必须要求 inetd 重新读取设定档:

# kill -HUP `cat /var/run/inetd.pid`

请注意这里 `cat /var/run/inetd.pid` 所使用的 ` 是键盘左上角的那一个符号,而非单引号。

不过我们建议您使用 ssh 联机以取代 telnet,因为 ssh 是以加密过的方式联机,比较不会以明码的方式传送数据。您可以使用 putty 这个软件在 MS windows 下联机到 FreeBSD 中。您可以从 http://www.chiark.greenend.org.uk/~sgtatham/putty/ 下载 putty,也可以在本书光盘二的 wintools 目录下找到该软件。

当然,您也可以在FreeBSD中使用 ssh 的方式连到别台机器,FreeBSD 中内建有 ssh 软件,你可以使用下列指令:

# ssh jack@123.123.78.9

这个指令表示以使用者 jack 身份联机到 123.123.78.9,我们也可以使用主机名称的方式,例如jack@dns.abc.edu.tw ,或者也可以只打 ssh dns.abc.edu.tw 来登入,此时登入名称会是您现在用的使用者名称。

如果所联机的站台是第一次使用 SSH联机,则会出现下列一堆东西,表示接收到所联机站台RSA key,并询问您是否要继续连接。此时打 "yes" 三个字即可:

The authenticity of host '123.456.78.9' can't be established.
RSA key fingerprint is 13:96:8a:61:31:cf:32:3f:7a:0a:77:ad:7e:49:e7:3f.
Are you sure you want to continue connecting (yes/no)?  yes

系统会将所接收到的金钥 (key) 存放在使用者家目录下的 .ssh/known_hosts 档案中。如果日后在 known_hosts 目录中所记录的站台金钥有变更时,我们可以编辑该档案以删除旧的金钥。

设定到这里后,就可以不必在机器前作业了。通常我的习惯是设定到这个地方后,就使用 telnet 或 ssh 的方式经由其它计算机联机到机器来作其它的设定,这样我就不必一定要待在机器前,可以在自己家中使用别的机器联机到 FreeBSD 中做设定。不过要注意的是 root 账号预设是不能使用远程登入,如果您想使用远程登入并拥有 root 的权限,您必须先使用一般的使用者登入后,再执行 su 这个指令来切换身份成为 root,而且这个使用者必须加入 wheel 群组中。假设您在新增使用者时并未将该使用加入 wheel 群组,您可以手动编辑 /etc/group 来加入该使用者…。例如我们要让一般使用者 alex 拥有 su 成为 root 的权限:

wheel:*:0:root,alex

3.6.4 定时执行工作

在 FreeBSD 系统中,系统常常会定时执行一行工作,例如,每天的系统信息统计、系统安全检查等。而系统管理者及一般使用者也可以设定定时执行一些工作,这些工作可以时只执行一次、或是定时重复执行。

如果是要设定只执行一次的工作,例如,设定在今天 10:00 时执行某个指令,我们可以使用「at」这个指令。如果是要设定重复报行的工作,例如,设定每天 12 点执行某个指令,我们可以使用「crontab」这个指令,或者是由系统管理者编辑 /etc/crontab 这个档案来进行设定。我们先来看看「crontab」重复定时执行程序的说明:

「crontab」重复定时执行程序

在 UNIX 系统中,有一个背景程序会定时执行一些工作,这个程序在 FreeBSD 中称为「cron」。「cron」这个程序会定时去检查 /etc/crontab /var/cron/tabs 中的档案,并执行其中的设定。/etc/crontab 可以让管理者设定要以什么使用者的身份去执行定时工作,而一般使用者如果要设定定时执行工作时,可以使用指令 crontab -e 来编辑自己的定时执行工作,crontab 会将使用者的工作设定放在 /var/cron/tabs 中。

我们先来看一下 /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

小时的字段中如果是 *,表示每小时,天的字段中如果是 *,表示每天,依此类推。字段中也可以使用 "-" 来表示范围。例如,在小时的字段中填 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 * *",也就是每月一日半夜 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

# 设定每天半夜十二点执行 something。
@daily	root	/bin/something

如果你以一般使用者或是管理者的身份执行 crontab -e 来设定 crontab,你不必设定身份的字段,因为 crontab 会自动取得您的身份。使用 crontab -e 所设定的工作会被放在 /var/cron/tabs 目录中,所以如果要备份或升级时,应该要注意这些档案是否要备份。

小提示

我们在安排 crontab 时,应该要错开每个程序的执行时间,才不会有一大堆程序同时执行,造成系统负荷过高。

「at」设定只执行一次的程序

cron 可以用来设定不断的重复定时执行一些工作,然而,如果您只希望在某个时间执行「一次」某个指令,可以使用「at」。

「at」的设定可以分为三个指令:「at」用来建立工作、「atq」用来列出目前待执行的工作有哪些、「atrm」用来删除 atq 中所列出的工作。当您执行了 at 后,它会要求您在命令列中以 shell scripts 的写法输入想要执行的指令,而您也可以先将所要执行的指令写再一个档案中,再让 at 去执行。

在使用 at 指令时,必须先输入您要在什么时候执行工作,而时间的格式可以是下列任何一种:

格式 说明
at 10pm 设定晚上十点执行。时间的格式可以是 HHMM 或 HH:MM。
at 8:30am Oct 10 设定十月十日早上八点半执行。
at midnight Jan 1 2005 设定 2005 年一月一日的第一秒钟执行。
at teatime 设定在下次的下午 4 点执行。teatime 表示是 4:00pm,而 midnight 表示半夜十二点,noon 表示中午十二点。
at -t MMDDhhmm 表示在 MM 月 DD 日 hh 时 mm 分时执行,您还可以在 MM 前加上年,而年的格式二位或是四位都可以。

如果您要设定在 10pm 执行某些工作,您可以打「at 10pm」后按 <Enter>,接着您必须开始输入所要执行的指令,在全部输入完成后,请按 <Ctrl>+<D>结束编辑。如果您不想使用命令列编辑的方式输入所要执行的工作,您可以先写一个 shell script 并使用下列指令设定:

# at -f mycommand.sh 10pm

上述指令中,您所写的 shell scripts 档案是 mycommand.sh。

在设定之后,接着您可以使用下列指令列出目前等待执行的 at 工作:

# atq
Date                                 Owner          Queue   Job#
2005年 6月 5日 周日 22时00分00秒 CST    root             c      2

如果您要删除某一个工作,只要使用 atrm 并输入该工作在 atq 中的 job id 即可。例如,我们要删除 ID 为 2 的工作:

# atrm 2

限制一般使用者使用 cron 及 at

大部份的情况下,一般使用者应该不会需要使用定时排程的工作。如果您发现有使用者定时会执行一些耗费系统数据的工作,我们可以为这个指令设限,只允许必要的使用者执行。

如果要限制使用 crontab,只需要在 /var/cron 目录中,加入 allow 或是 deny 这个档即可。例如,我们只允许少数几个使用者执行 crontab,我们可以新增 /var/cron/allow 这个档,内容为该使用者的名称。相对的,如果我们要限制少数几个使用者执行 crontab,只要编辑 /var/cron/deny 这个档即可。而指令 at 的限制也是一样,不同的只是允许执行 at 指令的名单是 /var/at/at.allow,而拒绝的名单是 /var/at/at.deny

3.7 虚拟终端机

大多数的时候,我们都是在命令列模式 (文字模式) 下执行系统管理的工作,命令列模式相较于图形模式而言,所使用的系统资源较少,同时也是一般 UNIX 最常使用的模式。

在系统一开机后,屏幕上会出现类似下列画面:

Fri Mar 20 14:05:16 CST 2005
FreeBSD/i386 (example.com) (ttyv0)
login:

我们看到第二行的部份有一个 ttyv0,ttyv0 所代表的是编号为 0的系统 console 终端机。我们在该机器面前所使用的屏幕中文字模式的画面就叫做 console,我们可以在 console 下执行许多指令。FreeBSD 一开机后就会建立让多虚拟的 console 终端机机,我们可以同时开机多个 console 画面同时进行操作。您可以使用 ALT+F2、ALT+F3、…直到 ALT+F8 来切换不同的 console 画面。当您使用 ALT+2 时,您会看到前面所提及的 login 画面,而画面上有一个 ttyv1 的字样。如果您要切换回 ttyv0 只要按 ALT+F1 即可。

当我们使用 telnet 或 ssh 进入系统时,我们所看到的虚拟终端机是 ttyp0、ttyp1 等等。关于各种 tty 权限的设定被记录在 /etc/ttys 这个档案中。

console none                            unknown off secure
#
ttyv0   "/usr/libexec/getty Pc"         cons25  on  secure
# Virtual terminals
ttyv1   "/usr/libexec/getty Pc"         cons25  on  secure
ttyv2   "/usr/libexec/getty Pc"         cons25  on  secure
ttyv3   "/usr/libexec/getty Pc"         cons25  on  secure
ttyv4   "/usr/libexec/getty Pc"         cons25  on  secure
ttyv5   "/usr/libexec/getty Pc"         cons25  on  secure
ttyv6   "/usr/libexec/getty Pc"         cons25  on  secure
ttyv7   "/usr/libexec/getty Pc"         cons25  on  secure
ttyv8   "/usr/X11R6/bin/xdm -nodaemon"  xterm   off secure
# Pseudo terminals
ttyp0   none                    network
ttyp1   none                    network
ttyp2   none                    network
……

这个档案中设定了每一个不同的终端机类型可以使用的权限,例如 ttyv0 最后面都有一个 secure 的字样,而 ttyp0 则无,表示 root 可以从 ttyv0 登入,但不可以从 ttyp0 登入,这也就是为什么 telnet 进来时,不可以使用 root 登入的原因。如果您想让 root 可以使用 telnet 登入,只要在 ttyp0、ttyp1 等行加入 secure 即可,但我们并不建议做这样的设定。更多关于 ttys 这个档案的格式及其设定,请 man ttys。

3.7.1登入后的讯息

在您登入系统之后,屏幕会自动秀出一段文字,这段文字称为 Message Of The Day(motd)。这一段文字是可以修改的,你可以编辑 /etc/motd 来制作自己的画面。如果你想使用像 BBS 中的文书编辑软件,来画 ANSI 图的话,你可以安装 ve 这个软件。

# cd /usr/ports/chinese/ve
# make install clean

再使用 ve /etc/motd 来修改讯息。例如笔者所使用的画面如下:

图 3-6

您可以在本书第二片光盘 /examples/etc/motd 找到笔者所使用的 motd 设定档。

3.7.2 登入前的讯息

在登入系统前 FreeBSD 时,你会看到下面的画面:

FreeBSD/i386 (example.com) (ttyv0)
login:

我们在这里要做的就是把它改成想要的样子。更改 login 前的画面有二种方式,一种是修改 /etc/gettytab/etc/issue,另一种方式是修改 telnetd。

方式一:

编辑 /etc/gettytab,找到 default的地方。

default:\
:cb:ce:ck:lc:fd#1000:im=\r\n%s/%m (%h) (%t)\r\n\r\n:sp#1200:\ :if=/etc/issue:

其中的%s %m %h %t 分别对应到 FreeBSD i386 example.com ttyp0,如果你不想显示 FreeBSD ,就把 %s 拿掉。最后一行 if=/etc/issue 就是表如果没有 issue 这个档的话,就执行 default。

如果你不仅仅是要修改 FreeBSD/i386 这个部份,还想要在 login 前秀出一段文字的话,你可以新增 /etc/issue 这个档,并编辑你想要的画面。和 motd 一样,issue 也可以使用 ANSI 画面,所以你可以用 ve 来编辑画面。如果你在该档中加入 %s %m %h %t 等参数的话,也是会出现 FreeBSD i386 example.com ttyp0等,如果不加就不会出现。

但由于 issue 这个档只会在 console 登入时才有作用,如果您要在开机前的画面中秀出更多的数据,您可以使用第二种方式。

方式二:

如果你想要在登入前执行一些指令,例如秀出开机时间等,必须要以更改 telnetd 的方式来做。首先,请编辑一个可执行档 /usr/local/libexec/telnetd.sh 内容如下:

#!/bin/sh
TTY=`/usr/bin/tty | /usr/bin/cut -c9`

if [ "$TTY" = 'v' ]; then
    exec /usr/libexec/telnetd
else
    /bin/cat /etc/issue
    echo "颜色句柄`/usr/bin/uptime`控制结束码"
    exec /usr/libexec/telnetd
fi

上面句柄部份,你可以使用 ve 来加入颜色句柄,编辑完后要把该档变成可执行的档案,使用下列指令:

# chmod 755 /usr/local/libexec/telnetd.sh

再编辑 /etc/inetd.conf,将原来的 "/usr/libexec/telnetd telnetd" 换成 "/usr/local/libexec/telnetd.sh telnetd.sh":

telnet stream tcp nowait root /usr/libexec/telnetd.sh telnetd.sh

最后重跑 inetd,使用指令 kill -HUP `cat /var/run/inetd.pid` 即完成设定。

3.7.3 使用中文终端机

FreeBSD 的console 并无法显示中文,如果我们要在 console 下使用中文的环境,则必须安装 big5con 这套软件才可以。请使用 root 的身份直接使用下列指令来安装:

# cd /usr/ports/chinese/big5con
# make install clean

安装完后,先执行 rehash 来更新一下 tcsh 指令的快取,之后我们就可以使用指令 b5c 来出现像 DOS 下倚天中文的环境,如图 3-7。

图 3-7

小提示

您可以使用 <Ctrl>+<Alt>+<数字> 来切换不同的输入法,并使用 <Ctrl>+<Space> 来切换中英文。