第六章 檔案系統管理

管理檔案系統是系統管理者最重要的工作之一,我們必須確定使用者可以存取他們需要的資料,而且儲存裝置必須隨時都保持正常運作。

本章讀完後,您將可以了解下列基本的檔案系統管理知識:

6.1 FreeBSD 的檔案系統架構

我們知道在 UNIX 系統中,檔案系統結構是一個樹狀結構,一個目錄下還有很多的目錄及檔案,而這些目錄下又會有更多的目錄及檔案,就像是一顆樹一樣,從根開始往上擴展。

對於硬碟的使用,在 UNIX 系統中,硬碟分割區會被掛在一個目錄下,在存取磁碟前,「掛入」(mount) 是必要的過程。也就是說,系統會將一個硬碟的分割區掛在一個目錄下,就好像 Windows 會將硬碟分割區放在 C:、D: 同樣意思。所以,在 UNIX 系統中,磁碟分割區會和現有的系統目錄合併。

在說明 FreeBSD 如何硬碟掛在目錄下使用之前,我們先來看一下 FreeBSD 對於儲存裝置的命名規則。FreeBSD 會給每個硬碟、光碟機的儲存裝置一個代號,並在 /dev 目錄下產生一個相對映的裝置檔。例如,我們的 IDE 硬碟代號就是 ad。以下為常見的儲存裝置代號:

裝置的代號由 0 開始算,第一個 IDE 硬碟的代號是 ad0,第二個是 ad1,依此類推。如果您有一個 IDE 硬碟,則可以在 /dev/ 中看到一個檔名為 /dev/ad0 的裝置檔。

大多數的作業系統都支援將一個硬碟分割成多個磁區,以 Windows 而言,我們可以將一個硬碟分割成 C:、D: 等多個磁區。在 Windows 中,我們稱這個分割區為 Partition。然而,在 FreeBSD 中,我們稱之為 slice。不管是 Windows 的 Partition 或是 FreeBSD 的 slice,在這裡我們統稱為主要磁區。PC 架構下,BIOS 認得的主要磁區最多只有四個。

FreeBSD 和其它作業系統不同的地方是我們會先分割在主要磁區 (slice) 下再細分成多個分割區,而這個細分之後的分割區才叫做 Partition。以下面這個圖為例:

圖 6-1

我們看到第一個主要磁區是 Windows 用的掉的,它在 FreeBSD 中的代號是 ad0s1,而第二個主要磁區是 FreeBSD 所使用,其代號是 ad0s2,代號 s1s2 指的就是主要磁區 slice 1 及 slice 2。而在 ad0s2 這個主要磁區中,我們又細分為三個分割區,分別是 ad0s2aad0s2bad0s2d

分割區代號 a、b、d 等在 FreeBSD 有一些規則:

所以當您看到一個分割區代號 ad0s1a 時,就可以知道它是第一個 IDE 硬碟 (ad0) 的第一個主要磁區 (ad0s1) 的第一個分割區 (ad0s1a)。

讓我們回到硬碟分割區和目錄之間的關係。在 FreeBSD 中,硬碟分割區會被掛在目錄下使用,例如下列的 df 指令輸出結果:

# df -h
Filesystem     Size    Used   Avail Capacity  Mounted on
/dev/ad0s1a    1.9G    389M    1.4G    21%    /
devfs          1.0K    1.0K      0B   100%    /dev
/dev/ad0s1d    989M     54K    910M     0%    /var
/dev/ad0s1e    4.8G    3.8G    657M    86%    /usr
/dev/ad1s1d    10.9G   149M   10.6G     1%    /usr/local

我們可以看到分割區 ad0s1a 是掛在根目錄 (/) 下,而 ad0s1d 掛在 /var 中。上述 df 指令輸出的範例中,//dev/var/usr 等都是磁碟分割區的掛入點 (mount points)。下圖即為分割區示意圖:

圖 6-2

除了根目錄外,每一個掛入點都可以被卸載。例如 ad1s1d 被掛在 /usr/local 中,我們可以動態卸載它。/usr/local 在掛入磁碟分割區前,它可能空的或是已經有一些檔案或目錄,但掛入後,我們看到該目錄中的東西會全部變成存在於 ad1s1d 這個硬碟中的資料。通常這些系統用的掛入點在還沒掛入磁碟前都是一些空目錄,而掛入後才會出現該目錄下的其它檔案及資料。以 /var 為例,在掛入前它是空的目錄,而掛入後,才會出現 dbmail 等目錄。

請注意,掛入點和磁碟分割區之間並沒有什麼特殊關聯。例如,如果您有二個掛入點 /volume1/volume2,而有二個分割區 ad0s1dad0s1e,您可以任意將 ad0s1d 掛在 /volume1/volume2。以上圖中的掛入點為例,您也可以將 ad1s1d 掛在 /mnt 下,只是 ad1s1d 這個分割區原本是掛在 /usr/local 下,已有一些 /usr/local 下的目錄結構及資料,所以還是掛在 /usr/local 下才不會有系統檔案找不到的問題。

6.2 監看檔案系統使用情形

幾乎所有 FreeBSD 上的應用都必須使用硬碟。我們必須注意系統磁碟空間足夠,並了解磁碟的使用效率。本小節中,我們將介紹一些 FreeBSD 常用的磁碟管理指令,讓我們可以更快的了解目前的系統使用狀態。

6.2.1 磁碟空間使用情形

在大部份的 UNIX 系統中都有二個指令可以了解硬碟的使用情形:dfdu

指令 df 可以顯示目前所有檔案系統的最大可用空間及使用情形,請看下列這個例子:

# df -h
Filesystem     Size    Used   Avail Capacity  Mounted on
/dev/ad0s1a    1.9G    389M    1.4G    21%    /
devfs          1.0K    1.0K      0B   100%    /dev
/dev/ad0s1d    989M     54K    910M     0%    /tmp
/dev/ad0s1f    4.8G    3.8G    657M    86%    /usr
/dev/ad0s1e    1.9G    149M    1.6G     8%    /var
/dev/ad0s1g     26G    890K     24G     0%    /volume2
/dev/da0s1d    325G    261G     38G    87%    /volume1

我們加了參數 -h 表示使用「Human-readable」的輸出,也就是在檔案系統大小使用 GB、MB 等易讀的格式。

上面的指令輸出的第一個欄位及最後一個欄位分別是檔案系統及其掛入點。我們可以看到 /dev/ad0s1a 這個分割區被掛在根目錄下。我們在上一小節提到過 ad 所代表的是 IDE 的硬碟,而 s1 表示第一個主要磁區。我另外有一個 SCSI 硬碟,它的代號是 da,它的容量很大,主要用來存放資料。devfs 是一個特別的檔案系統,該檔案系統並非真的磁碟,而是 FreeBSD 用來管理系統硬體裝置的虛擬檔案系統。

接下來的四個欄位 Size、Used、Avail、及 Capacity 分別是該分割區的容量、已使用的大小、剩下的大小、及使用的百分比。當硬碟容量已滿時,您可能會看到已使用的百分比超過 100%,因為 FreeBSD 會留一些空間給 root,讓 root 在檔案系統滿時,還是可以寫東西到該檔案系統中,以進行管理。

另外,我們還可以使用參數 -i 來查看目前檔案系統 inode 的使用情形。有的時候雖然檔案系統還有空間,但若沒有足夠的 inode 來存放檔案的資訊,一樣會不能增加新的檔案。

# df -ih
Filesystem     Size    Used   Avail Capacity iused    ifree %iused  Mounted on
/dev/ad0s1a    1.9G    389M    1.4G    21%   20495   262127    7%   /
devfs          1.0K    1.0K      0B   100%       0        0  100%   /dev
/dev/ad0s1d    989M     62K    910M     0%      24   141286    0%   /tmp
/dev/ad0s1f    4.8G    3.8G    657M    86%  311439   348015   47%   /usr
/dev/ad0s1e    1.9G    149M    1.6G     8%    1758   280864    1%   /var
/dev/ad0s1g     26G    890K     24G     0%      12  3532786    0%   /volume2
/dev/da0s1d    325G    261G     38G    87%  707277 43311409    2%   /volume1

我們可以看到根目錄的已經用掉的 inode 數量為 20495,還有 262127 的可用 inode。

小提示

還記得什麼是 inode 嗎?所謂的 inode 是用來存放檔案及目錄的基本資訊 (metadata),包含時間、檔名、使用者及群組等。在分割磁區時,系統會先做出一堆 inode 以供以後使用,inode 的數量關係著系統中可以建立的檔案及目錄總數。如果要存的檔案大部分都很小,則同樣大小的硬碟中會有較多的檔案,也就是說需要較多的 inode 來掛檔案及目錄。

指令 df 只能用來查看整個檔案系統的使用情形,如果您需要知道某個目錄的使用情形,可以用指令 du

指令 du 能以指定的目錄下的子目錄為單位,顯示每個目錄內所有檔案所占用的磁碟空間大小。例如:

# du -h /etc
104K	/etc/defaults
6.0K	/etc/X11
8.0K	/etc/bluetooth
4.0K	/etc/gnats
 52K	/etc/isdn
388K	/etc/mail
 68K	/etc/mtree
2.0K	/etc/ntp
 38K	/etc/pam.d
 44K	/etc/periodic/daily
6.0K	/etc/periodic/monthly
 42K	/etc/periodic/security
 16K	/etc/periodic/weekly
110K	/etc/periodic
6.0K	/etc/ppp
318K	/etc/rc.d
2.0K	/etc/skel
130K	/etc/ssh
 10K	/etc/ssl
1.7M	/etc

我們目樣使用 -h 參數來顯示 human-readable 的格式。在應用時,我們可以使用 du 這個指令來查看哪個目錄佔用最多的空間。不過,du 的輸出結果通常很長,我們可以加上 -s 參數來省略指定目錄下的子目錄,而只顯示該目錄的總合即可:

# du -sh /etc
1.7M    /etc

在查看目錄的使用情形時,我們可以將輸出結果導到 sort 指令進行排序,以了解哪個檔案用了最多的空間:

# du /etc | sort -nr | more
1746	/etc
388	/etc/mail
318	/etc/rc.d
130	/etc/ssh
110	/etc/periodic
104	/etc/defaults
68	/etc/mtree
52	/etc/isdn
44	/etc/periodic/daily
42	/etc/periodic/security
38	/etc/pam.d
16	/etc/periodic/weekly
10	/etc/ssl
8	/etc/bluetooth
6	/etc/ppp
6	/etc/periodic/monthly
6	/etc/X11
4	/etc/gnats
2	/etc/skel
2	/etc/ntp

sort 的參數 -nr 表示要以數字排序法進行反向排序,因為我們要對目錄大小做排序,所以不可以使用 human-readable 的大小輸出,不然目錄大小中會有 K、M 等字樣,會造成排序不正確。

6.2.2 磁碟使用效率

除了查看硬碟的空間使用情形外,我們還可以查看目前硬碟是否忙碌中,以了解硬碟的使用效率。我們可以使用 systat 這個指令:

# systat -vm 1
   3 users    Load  0.12  0.12  0.09                   6 26 00:38

Mem:KB    REAL            VIRTUAL                     VN PAGER  SWAP PAGER
       Tot   Share      Tot    Share    Free         in  out     in  out
Act  130120    5436   385556    11716   30540 count  146
All  233584   17544  2762124    45604         pages  846
                                                                Interrupts
Proc:r  p  d  s  w    Csw  Trp  Sys  Int  Sof  Flt      8 cow     474 total
            75      1514  379 2525  690   66  375   70564 wire    100 0: clk
                                                   132932 act         1: atkb
14.0%Sys   1.6%Intr  2.3%User  0.0%Nice 82.2%Idl    18024 inact       3: sio1
|    |    |    |    |    |    |    |    |    |      13024 cache       4: sio0
=======+>                                           17516 free        7: ppc0
                                                          daefr   128 8: rtc
Namei         Name-cache    Dir-cache                  38 prcfr    40 9: fxp0
   Calls     hits    %     hits    %                  228 react    31 10: fxp
    1020      672   66                                    pdwak       11: hpt
                                      43 zfod             pdpgs       12: psm
Disks   ad0   da0 pass0                43 ofod            intrn       13: npx
KB/t  28.20  0.00  0.00                   %slo-z    35664 buf     175 14: ata
tps     164     0     0                70 tfree       334 dirty       15: ata
MB/s   4.52  0.00  0.00                             17810 desiredvnodes
% busy   43     0     0                             16852 numvnodes
                                                    13772 freevnodes

systat 有許多資訊,我們使用參數 -vm1 來顯示最詳細的資訊,並設定每 1 秒更新一次資訊。在上面一堆複製的資訊中,請將重點於在中間「====+>」及左下角的 Disks,中間部份的「====+>」表示目前 CPU 的使用情形,我們可以看到有 82.2% 的 Idle (閒置)。而硬碟的使用情形中,我的第一個硬碟 ad0 正在忙碌中,有 43% 的忙碌。而另一個 SCSI 硬碟 da0 則是完全閒置,也就是沒有人正在使用它。

如果您想要知硬碟本身的存取速度,可以使用 diskinfo 這個指令。diskinfo 加了 -t 參數會對硬碟做一些測試並回報結果:

# diskinfo -v -t ad0
ad0
       512             # sectorsize
       40020664320     # mediasize in bytes (37G)
       78165360        # mediasize in sectors
       77545           # Cylinders according to firmware.
       16              # Heads according to firmware.
       63              # Sectors according to firmware.

Seek times:
       Full stroke:      250 iter in   5.199255 sec =   20.797 msec
       Half stroke:      250 iter in   4.011383 sec =   16.046 msec
       Quarter stroke:   500 iter in   6.797812 sec =   13.596 msec
       Short forward:    400 iter in   2.774055 sec =    6.935 msec
       Short backward:   400 iter in   3.257613 sec =    8.144 msec
       Seq outer:       2048 iter in   0.352483 sec =    0.172 msec
       Seq inner:       2048 iter in   0.369383 sec =    0.180 msec
Transfer rates:
       outside:       102400 kbytes in   4.511970 sec =    22695 kbytes/sec
       middle:        102400 kbytes in   4.770641 sec =    21465 kbytes/sec
       inside:        102400 kbytes in   4.174557 sec =    24530 kbytes/sec

diskinfo 指令的 -r 參數會先印出一些分割區的基本資訊,包含 sector size、分割區大小、磁柱數量等。接下來的測試會花一點時間,測試結果包含了「Seek times」及「Transfer rates」。「Seek times」指的是硬碟的搜尋速度,而「Transfer rates」是資料找到後從硬碟傳到系統的速度。

6.3 掛入檔案系統

6.3.1 掛入與卸載 FreeBSD 檔案系統

我們知道在存取磁碟前,必須先將該磁碟「掛入」(mount) 一個目錄中,而掛入檔案系統的指令為 mount。它的用法如下:

# mount device mount-point

例如,我們要將 ad0s1e 掛入 /home2 中:

# mount /dev/ad0s1e /home2

在執行 mount 指令前,我們必須確定掛入點存在,如果不在必須先建立目錄。

如果執行 mount 時不加任何參數則可以顯示目前已掛入的檔案系統:

# mount
/dev/ad0s1a on / (ufs, local)
devfs on /dev (devfs, local)
/dev/ad0s1d on /tmp (ufs, local, soft-updates)
/dev/ad0s1f on /usr (ufs, local, soft-updates)
/dev/ad0s1e on /var (ufs, local, soft-updates)
/dev/ad0s1g on /volume2 (ufs, local, soft-updates)
/dev/da0s1d on /volume1 (ufs, local, soft-updates)

如果您要卸載一個檔案系統,可以使用 umount 指令。例如,我們要卸載 /usr/local:

# umount /usr/local

如果在卸載檔案系統時出現下列訊息,表示該檔案系統忙碌中,有可能有其它人正在存取它。

# umount /var
umount: unmount of /var failed: Device busy

6.3.2 掛入與卸載其它檔案系統

mount 指令除了可以讓我們掛入 FreeBSD 的預設的檔案系統 UFS 外,我們還可以用它來掛入其它 FreeBSD 支援的檔案系統格式。例如,FreeBSD 安裝光碟是一般標準的資料光碟,它的檔案系統格式是 CD9660,我們將該 CD 掛入系統目錄中。首先,請先將光碟放入光碟機中,接著請使用下列指令來掛入光碟片:

# mount -t cd9660 /dev/acd0 /cdrom

在使用 mount 指令時,我們加上參數 -t cd9660 以指定檔案系統格式為 cd9660。我們可以看到在掛入之前,/cdrom 這個目錄是空的,而掛入後就出現了許多資料。光碟機掛入後,您會發現光碟機的退片鍵將失去作用,我們必須先卸載它才可以取出光碟片。

如果您要卸載它,可以使用 umount 指令。如果您在卸載時發生錯誤,請注意您的所在目錄是不是在 /cdrom 下,如果是,必須先離開才可以順利 umount:

# cd /
# umount /cdrom

我們說過,掛入點和磁碟分割區之間並沒有必然的關係,您也可以將光碟掛入 /mnt 中,不一定要掛入 /cdrom,將 CDROM 掛入 /cdrom 只是習慣用法而已。

除了一般資料光碟的 cd9660 檔案格式外,FreeBSD 還支援下列常用的檔案格式:

檔案系統格式 說明
ufs FreeBSD 預設的檔案系統。
ext2fs Linux EXT2 檔案格式。
msdosfs FAT/FAT32,DOS 相容的檔案系統。
ntfs Windows 的 NTFS。
cd9660 CD-ROM 的檔案系統。
udf DVD 資料光碟格式。
nfs 和 Sun Microsystems 相容的 "Network File System"。
smbfs CIFS/SMB 檔案格式,也就是 Windows 的網路芳鄰,請參考 Samba 網路芳鄰一章。
mfs 本地的 memory-based UNIX 檔案系統。
swap 用來作 swapping 的檔案系統。
procfs 用來存取執行程序(process)的檔案系統。
kernfs 用來存取核心參數(kernel parameter)的檔案系統。

您可以在 mount 指令的參數 -t 之後加入上述檔案格式做為參數以掛入正確的檔案系統。或者,您也可以依檔案系統的不同使用 mount_xxxx 指令。例如,要掛入 msdos 檔案系統時,可以使用 mount_msdosfs;要掛入 cd9660 時,可以使用指令 mount_cd9660。您可以在 /sbin 目錄下看到這些 mount 的指令:

# ls /sbin/mount*
/sbin/mount*             /sbin/mount_mfs*        /sbin/mount_procfs*
/sbin/mount_cd9660*      /sbin/mount_msdosfs*    /sbin/mount_std*
/sbin/mount_devfs*       /sbin/mount_nfs*        /sbin/mount_udf*
/sbin/mount_ext2fs*      /sbin/mount_nfs4*       /sbin/mount_umapfs*
/sbin/mount_fdescfs*     /sbin/mount_ntfs*       /sbin/mount_unionfs*
/sbin/mount_linprocfs*   /sbin/mount_nullfs*

實際上,當您執行 mount 加參數 -t 時,mount 就是會依據 -t 所給的檔案系統去執行相對映的 mount_xxx。

必須注意的是,在 Windows/DOS 作業系統中,有所謂的延伸磁區 (Extended Partitions)。延伸磁區有點像是 FreeBSD 的 slice,在延伸磁區下,會在細分成多個邏輯磁區 (Logical Partitions),當 FreeBSD 遇到這種磁區時,會將各個邏輯磁區編號從第五個 slice 開始 (跳過最多 4 個 slice 的限制)。所以,DOS 中第一個邏輯磁區在 FreeBSD 中的編號就是 ad0s5,第二個邏輯磁區就是 ad0s6,依此類推。

另外,有些檔案系統在 FreeBSD 中只有唯讀的能力。例如 NTFS,我們只能夠讀取該磁區的資料,而無法進行任何寫入的動作。

6.3.3 開機時自動掛入

如果您在安裝 FreeBSD 時是以光碟安裝,您也許會發現只要以下列二個指令其中一個就可以掛入光碟機:

# mount /cdrom
# mount /dev/acd0

我們之所以可以這麼做是因為在 /etc/fstab 中已經記錄了 /cdrom 應該要掛入另一個裝置。讓我們來看一下這個檔:

# Device	Mountpoint	FStype	Options		Dump	Pass#
/dev/ad0s1b	none		swap	sw		0	0
/dev/ad0s1a	/		ufs	rw		1	1
/dev/ad0s1d	/tmp		ufs	rw		2	2
/dev/ad0s1f	/usr		ufs	rw		2	2
/dev/ad0s1e	/var		ufs	rw		2	2
/dev/acd0	/cdrom		cd9660	ro,noauto	0	0

我們可以看到最後一行掛入點 (Mount point) /cdrom 所對映的裝置是 /dev/acd0,而檔案系統格式的欄位中 (FStype) 所指定的格式是 cd9660,所以我們可以不必打完整的指令就可以掛入光碟。

在系統開機時,FreeBSD 會參考 fstab 來決定要將哪些檔案系統掛進來。在 fstab 各個欄位所代表的意義如下:

如果您新增一個分割區,並且希望在開機時自動載入,可以編輯 fstab,並加入您所要掛入的磁區。

6.4 磁碟分割與格式化

如果您目前系統只有一個硬碟,並想加上第二個硬碟時,如果是 Windows 或 DOS,我們都會先做硬碟的切割 (partition),再做格式化 (format)。在 FreeBSD 中,要使用一個新硬碟的動作也類似,必須先切割磁區,再進行格式化。

切割磁區的意思就是指定要讓系統使用多大的硬碟空間,之後我們在將這個空間格式化成 FreeBSD 的檔案系統格式。FreeBSD 大家應該聽過 FAT 檔案系統,它是以前 DOS 時代所使用的檔案系統,後來又發展了 FAT32,以支援大於 2GB 的磁碟分割區。而 Windows NT/2000/XP 預設使用的檔案系統為 NTFS。FreeBSD 4.x 預設使用的檔案系統格式為 UFS (Unix File System),在 5.x 之後,加入了新的檔案系統格式 UFS2。UFS2 和 UFS 最大的差別是 UFS2 支援 1TB 以上的硬碟分割區,除此之外, UFS2 還有一些新的功能,但都是在 UFS 上進行小修改,所以就速度上而言應該差不多。如果您有興趣可以參考這一份 Little UFS2 FAQ (http://sixshooter.v6.thrupoint.net/jeroen/faq.html)。

總而言之,新增一個硬碟的步驟為:

我們假設您要加入的是一顆 IDE 硬碟,而希望將這個硬碟掛入 /volume1 這個目錄下。您第一步要做的就是先將硬碟插入電腦後,開機看看 BIOS 有沒有偵測到這個硬碟。我們假設這個硬碟接在第一個排線,是電腦中的第二顆硬碟,則開機後,這個硬碟的代號就是 ad1。請使用 root 登入後,執行指令 dmesg 或是 more /var/run/dmesg.boot,看看 FreeBSD 有沒有偵測新的硬碟 ad1

接下來,您就可以使用指令 sysinstall (如果是 FreeBSD 5.2 以前的版本,請使用 /stand/sysinstall) 來新增硬碟了。

6.4.1 使用 sysinstall

在使用 sysinstall 來設定新的硬碟之前,請先確定您是以 root 身份執行。接下來,您就可以依照下列步驟來新增硬碟:

  1. 進入 sysinstall

    進入 sysinstall 的主選單後,首先請選擇 [Configure],進入後,再選擇 [Fdisk] 項目以進入 Fdisk 選單。第一次進入 Fdisk 時,sysinstall 會要求您選擇所要設定的硬碟,請選擇 ad1。

  2. 使用 Fdisk

    相信您對於 Fdisk 的畫面應該很熟悉,我們在安裝 FreeBSD 時就使用過它。如果您要讓 FreeBSD 使用整個硬碟,請按 [A],接下來請按 [W] 以將設定寫入硬碟。在按了 [W] 後,會出現一個確認的視窗,選 [Yes] 即可。最後會出現要您選擇所要使用的 Boot Manager,因為這一個硬碟不是要用來開機用的,所以我們選 [None]。寫入後,請按 [Q] 離開 Fdisk 的畫面,並回到 Configure 畫面。接著請離開 sysinstall,再重新執行 sysinstall 以讓 sysinstall 重新偵測硬碟設定。

  3. 使用 Disk Label Editor

    重新執行 sysinstall 後,請選擇 [Configure] -> [Label] 以進入 Disk Label Editor。Disk Label Editor 會幫我們在 Slice 下切割 Partition 並格式化硬碟。在 Disk Label Editor 中,我最多可以建八個分割區 (Partition),編號從 a 到 h。不過有的代號有特殊用途。例如,分割區 a 通常會保留給根目錄使用,所以我們開機時所使用的分割區代號會是 a。而代號 b 表示是 swap partition,我們可以在多個硬碟中都有 swap partition。代號 c 是用來表示整個硬碟或是整個 Slice。所以最後 d-h 才是一般我們會使用到的分割區代號。

    我們要讓 FreeBSD 使用整個硬碟,所以必須將整個 Slice 切成一個 Partition。所以一進入 Disk Label Editor 後,請按 [C],在畫面上會顯示整個 Slice 的大小,直接按 Enter 即可建立一個分割區。接下來,我們必須選擇所要掛入本分割區的目錄,請選擇  FS 後,再輸入您所要掛入的目錄,例如 /volume1。如果是在安裝 FreeBSD 時,我們所設定的掛入點會被寫到 /etc/fstab 中,開機後就會自動將磁碟掛入該目錄。但是我們這裡所指定的掛入點並不會被寫入 /etc/fstab 中,最後我們還是必須再設定 /etc/fstab

    最後請按 [W]以進行分割及格式化。完成後,系統會將該才所建立的磁碟掛入您所指定的目錄下。接著請離開 sysinstall 回到命令列。

  4. 設定 /etc/fstab

    為了讓系統在開機時可以自動將此分割區掛入,我們必須再設定 /etc/fstab。請在 /etc/fstab 中增加下列資料:

    # Device          Mountpoint   FStype  Options     Dump    Pass#
    /dev/ad1s1d       /volume1     ufs     rw          2       2

6.4.2 使用命令列

您不一定要使用 sysinstall 來分割及格式化硬碟,sysinstall 只是提供一個比較容易使用的介面,最後還是會呼叫命令列的指令以完成硬碟的設定。使用命令列的方式比較複雜,而且較容易出錯,但卻可以讓您有更靈活的應用。看了如何從命令列新增一個硬碟可以讓您對 sysinstall 所做的事更瞭解。

我們一樣假設要新增的硬碟為 ad1,並且將整個硬碟切成一個磁區給 FreeBSD 使用。第一步要做的就是先使用 dd 這個指令來清除硬碟上舊的設定:

# dd if=/dev/zero of=/dev/ad1 bs=1k count=1

上述指令的意思是從 /dev/zero 這個裝置讀出資料寫到 /dev/ad1 中,每次寫入的 block size (bs) 為 1KB,做一次寫入的動作即可 (count)。我們知道 FreeBSD 各動硬體裝置當做檔案來看待,/dev/zero 這個檔案其實是一個虛擬的檔案,我們從這個檔案讀出來的資料都是 0。上述指令的動作的目的就是要將硬碟 ad1 的開頭 1024KB 清成 0,而硬碟開頭的部份存放的就是一些分割區設定的資料 (Partition Table)。

接下來呢我們就必須使用 fdisk 這個指令來切割 slice 了:

# fdisk -BI ad1
******* Working on device /dev/ad1 *******
fdisk: invalid fdisk partition table found

上述 fdisk 指令表示我們要將 ad1 切割成一個 slice (參數 -I),並清除放開機資訊的第 0 個 sector。您可以忽略「invalid fdisk partition table found」的警告,因為我們一開始並沒有任何分割區。接下來我們就可以使用下列 bsdlabel 指令來建立預設的 partition label,再使用 bsdlabel 加參數 e 以修改建立的 lable:

# bsdlabel -B -w ad1s1 auto
# bsdlabel -e ad1s1

接著會使用您預設的文書編輯軟體跳出一個視窗,請將 a: 改成 d: 後存檔離開,因為我們新增加的分割區不是要給根目錄使用,所以不用代號 a,而是使用第一個不具特別意義的代號 d。

# /dev/ad1s1:
8 partitions:
#        size   offset    fstype   [fsize bsize bps/cpg]
 d: 78156146       16    unused        0     0
 c: 78156162        0    unused        0     0 # "raw" part, don't edit
 

將 a: 改成 d: 後,存檔離開即可。接下來我們就可以格式化這一個分割區了。FreeBSD 中用來格式化 UFS 檔案系統的指令為 newfs

# newfs /dev/ad1s1d

以上即為新增一顆硬碟所要做的事。請注意,bsdlabel 這個指令是 FreeBSD 5.1 以後才有的,在 5.1 以前,請使用 disklabel

接下來您就可以將新的硬碟掛入了,假設您要掛入的目錄是 /volume1,則請使用下列指令:

# mkdir /volume1
# mount /dev/ad1s1d /volume1

最後,如果您希望一開機就將此分割區掛入,請修改 /etc/fstab,並加入此分割區的設定。

6.5 使用 USB 磁碟機

現在有很多 USB 裝置:USB 大姆哥、USB 硬碟外接盒、USB 光碟機等。大多數的作業系統都是將 USB 設備看模擬成 SCSI 裝置,FreeBSD 也是一樣。USB 硬碟、大姆哥等都會被當做 SCSI 硬碟,代號會是 da0、da1;而 USB 光碟機則是 cd0。

6.5.1 事前的準備

在開始使用 USB 磁碟機之前,我們必須先確定系統有支援 USB 裝置。在核心 (Kernel) 中,關於 USB 硬碟及光碟機的支援必須要有下列項目:

device	scbus	# SCSI bus (required for SCSI)
device	da	# Direct Access (disks)
device	cd	# 支援 CD-ROM/DVD
device	pass	# Passthrough device (direct SCSI access)
device	uhci	# UHCI PCI->USB interface (支援 USB 1.x)
device	ohci	# OHCI PCI->USB interface (支援 USB 1.x)
device	ehci	# EHCI PCI->USB interface (支援 USB 2.0)
device	usb	# USB Bus (required)
device	umass	# Disks/Mass storage - Requires scbus and da

如果您不使用 USB 光碟機,可以將「device cd」移除。如果您使用的是 GENERIC 核心 (FreeBSD 預設的核心),那麼您的核心已經支援 USB 硬碟了 。如果您使用的是 FreeBSD 6.0 以前的版本,您必須再修改修改核心,以支援 USB 2.0。請在核心設定檔中加入下列這一行以使用 USB 2.0:

device	ehci	# EHCI PCI->USB interface (USB 2.0)

不過您必須注意 FreeBSD 4.10 以後才開始支援 USB 2.0 喔。如果沒有加入 USB 2.0 的支援,所有裝置將會以 USB 1.1 速度運作。關於如何編譯核心請參考「編譯核心」一章的說明。

另外,我們必須啟動 usbd 以支援某些 USB 裝置,例如 USB hub 等。FreeBSD 安裝完成後,預設可能有啟動 usbd,如果沒有,請修改 /etc/rc.conf 加入下列設定:

usbd_enable="YES"

重新編譯核心,並修改 /etc/rc.conf 後,您必須重新開機才可以繼續下列動作喔。

重開機後,您就可以將 USB 裝置插入。插入後,您會在 console 看到下列訊息:

umass0: USB Flash Disk, rev 2.00/2.00, addr 2
da0 at umass-sim0 bus 0 target 0 lun 0
da0: <OTi Flash Disk 2.00> Removable Direct Access SCSI-2 device
da0: 1.000MB/s transfers
da0: 125MB (256000 512 byte sectors: 64H 32S/T 125C)

我們可以看到這個裝置的名稱為 da0,我們以下的操作都會以 da0 做為範例。如果您沒有看到上述訊息,表示沒有抓到 USB 裝置,請檢查核心設定後再試一次。

由於 USB 磁碟機會被模擬成 SCSI 裝置,所以您也可以使用 SCSI 工具 camcontrol 來查看目前所有 USB 裝置:

# camcontrol devlist
<OTi Flash Disk 2.00> at scbus1 target 0 lun 0 (da0,pass0)

6.5.2 掛入已格式化的磁碟機

如果您要掛入已從 Windows/DOS 中格式化好的 USB 磁碟機,它的檔案格式有可能是 FAT/FAT32 或是 NTFS。 如果您不知道它的檔案格式,可以使用指令 fdisk 查看:

# fdisk da0
******* Working on device /dev/da0 *******
parameters extracted from in-core disklabel are:
cylinders=125 heads=64 sectors/track=32 (2048 blks/cyl)

parameters to be used for BIOS calculations are:
cylinders=125 heads=64 sectors/track=32 (2048 blks/cyl)

Media sector size is 512
Warning: BIOS sector numbering starts with sector 1
Information from DOS bootblock is:
The data for partition 1 is:
sysid 11 (0x0b),(DOS or Windows 95 with 32 bit FAT)
start 32, size 255968 (124 Meg), flag 80 (active)
beg: cyl 0/ head 1/ sector 1;
end: cyl 124/ head 63/ sector 32
The data for partition 2 is:
<UNUSED>
The data for partition 3 is:
<UNUSED>
The data for partition 4 is:
<UNUSED>

請注意粗體字的部份,我們可以看到在 da0 中有一個分割區,其檔案系統格式為 FAT32。所以要掛入檔案系統時,分割區代號為 da0s1 (請參考本章最開頭分割區代號的說明)。以下我們的操作都是使用 da0s1

掛入 FAT/FAT32 檔案格式

如果您要掛入的檔案系統為 FAT/FAT32,在 FreeBSD 5.x 以後,請使用指令 mount_msdosfs,若是 FreeBSD 4.x 請使用 mount_msdos

# mount_msdosfs -L zh_TW.Big5 /dev/da0s1 /mnt

我們在 mount_msdosfs 指令中使用參數 -L,並指定 locale 為 zh_TW.Big5 以支援中文檔名。如果沒有加此參數,中文檔名將會是亂碼。

如果您在掛入時出現下列錯誤訊息,表示您需要安裝 libiconv 模組:

# mount_msdosfs -L zh_TW.Big5 /dev/da0s1 /mnt
mount_msdosfs: Unable to load iconv library: Shared object "libiconv.so" 
not found, required by "mo"
: No such file or directory
mount_msdosfs: msdosfs_iconv: No such file or directory

我們可以使用 port 來安裝 libiconv 模組:

# cd /usr/ports/converters/libiconv
# make install

接著您就可以重新執行掛入的指令了。

掛入 NTFS 檔案格式

如果您要掛入的檔案系統格式為 NTFS,則必須使用指令 mount_ntfs

# mount_ntfs -C Big5 /dev/da0s1 /mnt

同樣的,我們使用參數 -C 以支援 NTFS 的中文檔名。不過,NTFS 在 FreeBSD 中只能唯讀而無法寫入,所以您無法在 NTFS 分割區中進入任何寫入的動作。

6.5.3 格式化 USB 磁碟機

如果您要在 FreeBSD 中格式化 USB 磁碟機,首先要考量的是這個磁碟是否要再拿到其它作業系統中使用。FreeBSD 可以格式化磁碟成為 FAT/FAT32 及 UFS。但是 Windows 作業系統只支援 FAT/FAT32。所以如果您要將磁碟拿到 Windows 中使用,請格式化成 FAT32。

FAT 檔案系統格式的效率很差,尤其是大容量的檔案系統時,存取的速度很慢。所以如果這個 USB 磁碟只要給 FreeBSD 使用,建議您格式化成 UFS 格式。如果您要將 USB 磁碟格式化成 FreeBSD 的 UFS 格式,請參考本章關於磁碟分割的說明,只要在格式化時選 da0 即可。我們這裡只針對如何格式化成 FAT/FAT32 做說明。

分割磁區

在格式化之前,我們必須先進行磁碟分割。理論上,不同的磁碟分割區有不同的代號,例如,FreeBSD 磁碟分割區的代號為 165,而 FAT32 分割區的代號為 11。165 這個數字有沒有很熟的感覺,我們在安裝 FreeBSD 切割 slice 時就曾經使用過它。

您可以使用 sysinstall 來切割磁區,也可以使用命令列的指令。如果您要使用 sysinstall,請在進入 sysinstall 後,選擇 [Configure] -> [Fdisk],將整個硬碟分割成一個磁區。請注意在 輸入分割區類型代號時,請將 165 改成 11 表示使用 FAT32。

如果您要使用命令列模式來切割磁區,和分割 FreeBSD 硬碟一樣,我們使用 fdisk 這個指令。但因為 fdisk 在分割磁碟區時預設會使用 FreeBSD 的分割區代號,所以我們必須使用互動模式來進行磁碟分割 :

# dd if=/dev/zero of=/dev/da0 bs=1k count=1
# fdisk -B da0
******* Working on device /dev/da0 *******
parameters extracted from in-core disklabel are:
cylinders=125 heads=64 sectors/track=32 (2048 blks/cyl)

parameters to be used for BIOS calculations are:
cylinders=125 heads=64 sectors/track=32 (2048 blks/cyl)

Do you want to change our idea of what BIOS thinks ? [n] <== 按 Enter 即可
fdisk: invalid fdisk partition table found
Media sector size is 512
Warning: BIOS sector numbering starts with sector 1
Information from DOS bootblock is:
The data for partition 1 is:
sysid 165 (0xa5),(FreeBSD/NetBSD/386BSD)
   start 32, size 255968 (124 Meg), flag 80 (active)
       beg: cyl 0/ head 1/ sector 1;
       end: cyl 124/ head 63/ sector 32
Do you want to change it? [n] y <== 輸入 y 以修改 Partition 1 的設定

The static data for the slice 1 has been reinitialized to:
sysid 165 (0xa5),(FreeBSD/NetBSD/386BSD)
   start 32, size 255968 (124 Meg), flag 80 (active)
       beg: cyl 0/ head 1/ sector 1;
       end: cyl 124/ head 63/ sector 32
Supply a decimal value for "sysid (165=FreeBSD)" [165] 11 <== 輸入 FAT32 分割區代號 11
Supply a decimal value for "start" [32] <== 按 Enter 即可
Supply a decimal value for "size" [255968] <== 按 Enter 即可
Explicitly specify beg/end address ? [n] <== 按 Enter 即可
sysid 11 (0x0b),(DOS or Windows 95 with 32 bit FAT)
   start 32, size 255968 (124 Meg), flag 80 (active)
       beg: cyl 0/ head 1/ sector 1;
       end: cyl 124/ head 63/ sector 32
Are we happy with this entry? [n] y <== 輸入 y 以確定 Partition 1 的設定
The data for partition 2 is:
<UNUSED>
Do you want to change it? [n] <== 按 Enter 即可,我們不修改 Partition 2
The data for partition 3 is:
<UNUSED>
Do you want to change it? [n] <== 按 Enter 即可,我們不修改 Partition 3
The data for partition 4 is:
<UNUSED>
Do you want to change it? [n] <== 按 Enter 即可,我們不修改 Partition 4
Partition 1 is marked active
Do you want to change the active partition? [n] <== 按 Enter 即可

We haven't changed the partition table yet. This is your last chance.
parameters extracted from in-core disklabel are:
cylinders=125 heads=64 sectors/track=32 (2048 blks/cyl)

parameters to be used for BIOS calculations are:
cylinders=125 heads=64 sectors/track=32 (2048 blks/cyl)

Information from DOS bootblock is:
1: sysid 11 (0x0b),(DOS or Windows 95 with 32 bit FAT)
start 32, size 255968 (124 Meg), flag 80 (active)
beg: cyl 0/ head 1/ sector 1;
end: cyl 124/ head 63/ sector 32
2: <UNUSED>
3: <UNUSED>
4: <UNUSED>
Should we write new partition table? [n] y <== 輸入 y 以寫入設定

分割好磁碟後,我們就可以開始格式化了。

格式化成 FAT/FAT32

FreeBSD 中格式化 FAT 的指令為 newfs_msdos

# newfs_msdos /dev/da0s1

newfs_msdos 指令會自動依您的磁碟大小選擇使用 FAT 或是 FAT32。現在您可以試著掛入看看可不可以使用:

# mount_msdosfs -L zh_TW.Big5 /dev/da0s1 /mnt

 

6.6 檔案系統修復

Unix 系統中大多有一個用來檢查及修復檔案系統的程式 - fsck。在不正常關機的情形下 (例如停電),FreeBSD 在開機時會自動執行 fsck。fsck 是 File System Consitency checK 的縮寫,主要的用途在於檢查檔案系統的一致性 (consistency)。在系統開機時,要掛入檔案系統前,FreeBSD 會先檢查檔案系統是否被標示為「clean」,如果不是,則會進行檔案系統檢查。在掛入檔案系統時,系統會將檔案系統標示為「not clean」。而在正常關機時,系統會先卸載檔案系統,並於卸載時將檔案系統標示為「clean」。這也就是為什麼不正常關機後,在開機時會進行檔案系統檢查的原因。因為在不正常關機時,沒有人去將檔案系統設為「clean」。

為什麼檔案系統會有不一致呢?這要從檔案系統的格式說起。一個檔案可以分為檔案屬性 (meta-data) 和檔案資料 (file content) 二個部分,檔案的屬性可能包含了檔案長度、檔案擁有者、連結數目等。而檔案資料就是檔案的實際內容。目錄的結構也類似,只是目錄的檔案資料部份存放的是檔案的檔名、檔案在檔案系統中的位置等。這些資料在寫入或刪除時,可能都會被快取在記憶體中,再慢慢寫入硬碟裡。而硬碟的速度相對於記憶體而言很慢,在寫入資料時,可能有寫入一半就因為電源中斷而寫入不完全。例如,在新增檔案時,有可能檔案資料的部份已經寫入硬碟中,但卻還來不及更新檔案屬性及目錄資料。這種情形就稱為檔案系統不一致。

基本上,fsck 會檢查一致性,比較一些項目,例如 inode 的位址是否指向對的資料、空白區塊的數目是否正確、目錄結構是否完整等。但是實際上,fsck 修復檔案的能力有限,它只能確保結構完整,但對於資料內容並沒有修復的能力。而且,在開機過程中進行 fsck 需要花很久的時間。因此,盡量避免不正常關機才是比較好的方法。

然而,減少檔案系統不一致的方法有很多種,在 Linux 中常見的方法是使用 journaling 或稱為 logging 的方式。就是檔案系統有任何更新時,系統都會先將檔案屬性的部份記錄在一個日誌裡,因為比較重要的屬性資料都很小,在寫入日誌時失敗的機率比較低。等到系統更新完硬碟資料後才清除日誌中的資料。如果更新到一半就關機,下次開機時,會使用倒推法回復原來的樣子,或是將沒寫完的東西繼續寫下去。這種檔案系統就叫做 Journaling File System,Linux 的 Ext3、Reiserfs 都是屬於這種檔案系統。不過 Journaling 的缺點就是要寫二次屬性資料,所以在速度上會慢一點。

FreeBSD 目前沒有 Journaling File System,不過,在 FreeBSD 5.x 以後的 GENERIC Kernel 中,內建有 Soft Update 的技術。Soft Update 就是將要寫入硬碟的屬性資料利用特殊方法按順序先寫在記憶體中,在更新大量屬性資料時,可以保証資料的一致性,並讓不正常關機後的檔案系統修復動作減到最少。而且,Soft Update 還結合了「Background fsck」的功能,讓系統在開機時不必花很長的時間進行 fsck,而是將這個動作放在背景執行。Background fsck 結合了「檔案系統快照」(我們會在下一小節說明),它會將開機時的檔案系統狀態快速的記錄下來,再慢慢進行檢修。

使用 Soft Update 可以增加資料寫入的效率,避免資料不一致的情形,所以在 5.x 以後,除了根目錄外,所有分割區預設都啟用 Soft Update。不過 Soft Update 有幾個缺點,因為它記錄許多將屬性資料在記憶體中,所以實際更新硬碟資料的時間可能會延遲個幾秒鐘,在不正常關機時,實際資料不見的比率也比較高。另外,在刪除檔案後,檔案空間被真正釋放的時間也會有點延遲。

總之,當不正常關機或檔案系統上次沒有被正常卸載時,在開機時就會自動進行 fsck。如果您要手動執行 fsck,必須先將分割區卸載後才可以執行。而執行的方式就是在 fsck 指令後面加上所要檢查的分割區代號。例如:

# fsck -y /dev/ad0s1d
** /dev/ad1s1d
** Last Mounted on
** Phase 1 - Check Blocks and Sizes
** Phase 2 - Check Pathnames
** Phase 3 - Check Connectivity
** Phase 4 - Check Reference Counts
** Phase 5 - Check Cyl groups
2 files, 2 used, 506337 free (25 frags, 63289 blocks, 0.0% fragmentation)

我們在上述指令中加入了 -y 參數,表示遇到問題時自動修復,不要再詢問。但是因為 fsck 要在檔案系統卸載後才能執行,所以如果是系統分割區,您必須要先進入單人模式 (Single user mode)。進入單人模式的方法在 FreeBSD 5.x 以後只要在開機選單中選取「Boot FreeBSD in single user mode」即可,在 4.x 中,只要在開機時看到「boot:」時,輸入「boot -s」即可。這樣一來,除了根目錄外,其它的分割區在開機時都不會被自動掛入。

6.7 檔案系統快照

檔案系統快照 (File System Snapshots) 顧名思義就是在檔案系統上照張相片,也就是將檔案系統當時的情形記錄下來,就好像照相一樣。日後您可以一張一張照片翻出來看。例如,您目前檔案系統中有十個檔案,我們先使用檔案系統快照拍一張照片。之後我們可以刪除檔案,在目前檔案系統中已經沒有東西了。但如果您將照片掛入,您還是可以看到這些檔案。簡單的來說,檔案系統快照的功能就是記錄當時檔案系統的狀態。

檔案系統快照只能用在獨立的「檔案系統」。例如我們的 /home/var 分別是獨立的分割區 /dev/ad0s1d /dev/ad0s1e,則我們可以對 /home /var 做檔案系統快照。

讓我們實際操作一次如何進行快照。建立檔案系統快照的方法有二個,一是使用 mount 指令,另一個是使用 mksnap_ffs。例如我們在將 /home 這一個分割區做一個檔案系統快照,並將快照存成 /home/snapshot20050730,可以使用下列指令:

# mount -u -o snapshot /home/snapshot20050730 /home

或是:

# mksnap_ffs /home /home/snapshot20050730

您會發現在 /home 中多了一個檔案名為 snapshot20050730。這個檔案就是現在這個時間點的檔案系統狀態。必須要注意的是,如果您要對 /home 做快照,在快照時只能將結果放在 /home 目錄下。例如,你可以放在 /home/snapshot/20050730,或是 /home/alex/backup/0730。但是不能放在 /var/snap.0730。也就是對某一個檔案系統進行快照的結果只能放在該檔案系統中。但是快照完成後,您就可以將它複製到其它地方。

現在,您可以在 /home 中先建一些檔案,等一下我們再將剛才的 snapshot 翻開來看,您會發現這些新建的檔案都不會出現在「照片」中。

我們現在來看看要怎麼把「照片」翻開來看。要看快照的內容可以使用下列指令:

# mdconfig -a -t vnode -f /home/snapshot20050730 -u 3
# mount -r /dev/md3 /mnt

上面的指令是將快照檔案掛入第 3 個 md 裝置,再使用 mount 指令將它像檔案系統一樣掛入。因為這是快照,照片是不能修改的,所以我們只能以唯讀格式掛入。您現在可以看一下 /mnt 中的檔案,是不是和您 /home 中的檔案一樣,但卻沒有新建的檔案存在。而且您可以試著開啟檔案,連檔案內容都一樣。很神奇吧,傑克!

md 是 FreeBSD 中一種特別的裝置,它可以讓我們將檔案模擬成檔案系統,您可以隨意指定沒有在使用中的 md 裝置,如 md1md2md3 等。我們使用 mdconfig 這個指令將設定檔案使用某一個編號的裝置,在掛入時必須也使用相對的編號 (例如上面的 md3)。而在使用完快照後,我們必須將它卸載,並釋放 md 裝置:

# umount /mnt
# mdconfig -d -u 3

以上就是檔案系統快照,是不是很好用。

同一個檔案系統中最多可以有 20 個檔案統快照,如果您有舊的快照不用了,可以直接使用 rm 指令刪除它。如果您要查找某一目錄下所有的快照,可以使用下列指令:

# find /home -flags snapshot

如果您查看一下我們做出來的快照,您會發現它的檔案大小和檔案系統大小一模一樣。但是如果您將它放在原本的檔案系統中,它是不佔空間的。如果您將 /home 的快照複製到其它的分割區中,它才會真正的佔空間。

這麼神奇的檔案系統快照有什麼功用呢?實際上的應用可多了。您有沒有發現檔案系統快照的速度非常快,這一點可以讓我們在備份時更快。傳統上,如果您要備份系統,您必須先停止網路服務,以免使用者資料備份到一半卻有人修改而造成錯誤,接著您才可以備份資料。而這樣一來,服務中斷的時間會非常長,直到整個檔案備份完為止。

而利用檔案系統快照,您先停止網路服務,將檔案系統進行快照,快照完後立即啟用網路服務。接下來,再將快照掛入後依正常程序備份即可。或者,您也可以直接備份快照的檔案即可。如此一來,服務中斷的時間就可以大幅減少了,是不是很讚!