第二十三章 指令應用

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 的長度一樣,這個封包應該沒有破損。

最後,這個封包並沒有包含其他的資料。