第三章 UNIX 系统入门

3.1 第一次登入系统

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

图 3-1

这里的 root 就是所谓的超级使用者,这个使用者是 UNIX 系统中的预设管理者名称。root 拥有系统所有权限,我们可以使用这个账号登入系统进行管理。root 这个使用者拥有许多一般使用者所没有的权限,建议您平常使用时最好不要以 root 登入。例如收发 email,程序开发、浏览网页、练习 UNIX 指令等,应该以一般使用者的身份来进行。因为您可能不小心打了某个指令而删除不该被删除的档案、或因为不良的操作而影响系统的稳定。因此,在我们设定完系统后,您应该新增一个一般使用者以减少错误的发生。
由于这是刚装好的系统,所以当我们以 root 登入时,系统不会问我们密码。一个没有密码保护的系统是十分危险的事,所以我们第一件要做的事就是设定 root 的密码。请执行指令 passwd 来设定您的密码,系统会问您二次新密码,以确认二次输入的密码相同。请不要使用太简单的密码,以免造成安全的漏洞。

3.2 基本指令介绍

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

指令 说明
cd 改变所在位置,和 DOS 中的用法类似,如果要到 /etc 下,就打 cd /etc
pwd 直接打就会显示目前所在目录的名称。
ls 看目录中的档案清单。打 lsls /etc,就像 DOS 中的 dir。
w 查询目前在在线的使用者。
ee 文书编辑软件。
date 看目前的日期及时间。
mkdir 建立一个目录,mkdir abc 就可以建立一个目录叫 abc 。
rm 删除档案或目录。删除档案时 rm file.txt,删除目录时要加参数 -rf , 如 rm -rf abc
cp 复制档案,就像 DOS 中的 copy。cp file newfile。
man 查询在线使用手册,如 man cp 就可以看到 cp 这个指令的详细说明。
su 从一般使用者变成超级使用者即 root。

还有一个您一定要知道的小秘诀,当您要 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.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-2

在画面最上方有使用说明,几乎我们所有的会使用到的功能都在最上方的说明中。您可以使用上下左右键来移动游标,并直接输入内容,以下为 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。

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

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

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

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

如果您想变更自己所使用的 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。
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->

就是开头是机器名称,再来是路径名称,最后是使用者名称。

由于在 /etc 下的 csh.cshrc 是通用的设定,但如果使用者自己的设定和通用设定一样时,会以使用者的设定为主。例如,在一般使用者的家目录下的 .cshrc 也有一行编辑器的设定,当设定不同时,会以使用者目录下的设定为主。因此,我们必须再编辑 ~/.cshrc,并找到setenv EDITOR vi 换成 setenv EDITOR 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 并在最后面加入以下的设定:

setenv ENABLE_STARTUP_LOCALE zh_TW.Big5
# 若是使用远程登入时,才能打出中文
# 4.x 请设定为 is_IS.ISO_8859-1,5.x 为 is_IS.ISO8859-1
setenv LC_CTYPE is_IS.ISO8859-1
# 若是console下用,才能打出中文
setenv LANG zh_TW.Big5

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

3.5 FreeBSD 的目录结构

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

以下我们就简单的说明 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。

3.6 使用者及权限管理

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

在 UNIX 系统中,每个使用者「至少」会属于一个群组,我们可以针对不同使用者或不同群组来设定他们在系统中的使用权限。例如,我们有一个使用者名为「猪小弟」,他的群组是「小猪」,我们让小猪群组可以进入猪圈这个数据夹。同时由于猪小弟生病了,需要吃药,所以我们将它加入「病猪」群组,所有病猪都可以吃特别的饲料,其它健康的猪只则禁止存取。如此一来,我们就不必一只一只去设定每只猪及每个数据夹的权限,下次新增一个特别饲料时,只要设定只有病猪可以存取即可。

所以我们在新增使用者时,必须指定他的群组,预设的群组是一个和使用者同名的新群组,我们先来看看新增使用者的过程,请使用指令 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。

在 ls 结果的第一个字段表着该档案或目录的存取权限,该字段共有十个字符,第一个字符表示档案的类型,以 jack 这个目录为例,它的类型是目录,所以第一个字是 d,如果是一般的档案,则第一个字是 - 。接下来的九个字符,以三个为单位,分别代表着使用者 (User)、群组 (Group)、及其它人 (Others) 的权限:

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

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

图 3-3

假设我们要更改档案 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.7 系统服务及行程管理

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

3.7.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 来使用。TT 这个字段是我们正在使用的 tty,如果是在 console 前执行的执令,则 tty 为 ttyvX,如果是 telnet 到系统中,则 tty 为 ttypX。STAT 字段为目前该程序的状态。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.7.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 可以送信号给不属于自己的行程,而一般使用者只能管理自己的行程。

3.7.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"

假设我们想要让 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

如果 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.8 虚拟终端机

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

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

Fri Mar 20 14:05:16 CST 2004
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.8.1登入后的讯息

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

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

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

图 3-4

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

3.8.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.8.3 使用中文终端机

FreeBSD 的console 并无法显示中文,如果我们要在 console 下使用中文的环境,则必须安装 big5con 这套软件才可以。怎么安装呢? 您可以将本书光盘二 /ports/distfiles 目录中的所有档案复制到 /usr/ports/distfiles 中,或是将光盘放入光驱中,并使用指令 mount /cdrom 将光驱 mount 进来。如此一来,在安装软件时,系统就不会要求连上网络取回所需档案(有的档案不能从CDROM 安装,您必须至网络下载)。接着以root 的身份直接使用下列指令来安装:

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

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

图3-5