第三章 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> 來切換中英文。