第二十三章 指令应用

UNIX 系统和 MS Windows 最大的不同点在于 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 的类别:

类别 说明
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)

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:

参数 说明
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

我们来看看第一行所代表的意义:

我们常用的 ps 参数有 auxww 等,其中 a 表示显示所有的行程,u 表示显示行程拥有者的信息,x 显示 deamon 的信息,ww 则是显示完整的 COMMAND 字段,不要将太长的部份截断。

23.2.2 kill

kill 指令会送出一个讯号 (Signal) 给指定的程序,程序在收到讯号之后,会依其要求来动作。我们常用的讯号如下:

SIG 名称 代码 意义
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

用来监看系统资源使用情形。它有几个常用的参数:

参数 说明
-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<s 0:00.00 shutdown 0203122359
# 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 的方式来设定新的值。这些值如下表:

NAME TYPE 可否改变
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 将会进行下列动作:

必须要注意的是 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 root@foo.com 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) 对于该档案的存取权限。

在使用 chmod 时,我们可以使用不同的字母来代表使用者 (User)、所属群组 (Group)、其它人 (Other):

举例而言,如果我们要让 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

例如,使用者的权限是 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/		<--- 权限为 500,没问题
$ cd ..
$ chmod 400 mydir
$ cd mydir
mydir: Permission denied.	<--- 权限为 400,只可以读不能进入
$ ls mydir
file.txt doc/ mp3/		<--- 权限为 400,只可以读不能进入
$ chmod 100 mydir
$ ls
ls: .: Permission denied	<--- 权限为 100,只能进入,不能看内容

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

假设我们要设定档案 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 及其所代表的意义如下:

flags 意义
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 可以用的参数很多:

参数 说明
-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 来顺便将档案压缩。

参数 说明
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
参数 说明
-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 封包到指定的主机,我们可以藉此来检查网络联机品质。

常用参数如下:

参数 说明
-c count 指定要计算 count 次。
-s size 指定每个封包大小为 size。
-t timeout 指定 time out 时间。
-I interface 如果目标主机地址是广播地址,而且我们有多个网接口,可以指定要使用哪一个接口。

例如我们要看 www.freebsd.org 的联机品质:

$ ping www.freebsd.org
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 www.freebsd.org

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  www.ssh       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

我们简单说明一下各字段所代表的意义:

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

每个字段所代表的意义如下:

23.5.7 mail

邮件处理程序。古老的 UNIX 邮件处理程序,这个程序对于不熟悉的人使用起来可能有点困难。但是这是在每个 UNIX 系统中都会有的程序,有时在没有其它选择的状况下,我们还是要使用它,至少要知道如何用它来收发信件。

假设我们要寄信给本机的 root:

$ mail root

如果我们要寄信给非本机的使用者,可以使用的收件人格式如下:

执行了 mail 之后,程序会先要求我们输入邮件主旨,输入后就可以开始打本文了。当完成本文的编辑之后,可以按 Ctrl+D 来将信件送出,或是按二次 Ctrl+C 取消。

我们也可以在执行 mail 时加上参数 -s "subject" 来指定主旨:

$ mail -s"hi, my friend" jack@mymail.com

如果我们想要将一个文字文件的内容当做本文送出,例如,我们可以先编辑一个文字文件 content.txt,接着使用下列方式:

$ mail -s "hi, my friend" jack@mymail.com < content.txt

说完了寄信,我们来了解一下如何收信。我们可以打 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 mary@abc.com Sat Feb 23 03:06 570/33527 "don't forget"
&

最后面出现的 & 为 mail 程序命令列的提示符号,在第一封信件开头有一个符号 ">" 表示目前作用中的信件。我们可以直接输入邮件编号来读取信件。另外,我们也可以输入下列指令:

指令 说明
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 jack@mydomain.com
$ 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 之后,会出现命令的提示列。我们可以输入以下的指令:

指令 说明
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

网络主机名称查询。如果我们要查询 www.freebsd.org 所对映的 IP,最简单的用法是:

$ nslookup www.freebsd.org

我们也可以在上述指令最后面加上要查询的 DNS 主机:

$ nslookup www.freebsd.org dns.hinet.net

我们也可以使用 IP 来进入反查:

$ nslookup 216.136.204.21

23.5.12 dig

是另一个功能强大的主机名称查询工具。简单的用法如下:

$ dig -x 216.136.204.21
$ dig www.freebsd.org

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 <dump | more
---------------------------------------------------------------
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 的长度一样,这个封包应该没有破损。

最后,这个封包并没有包含其它的数据。