# Filesystem Hierarchy Standard
[TOC]
# FHS:檔案系統階層標準
## 什麼是 FHS?
FHS 的全名是 Filesystem Hierarchy Standard,意即檔案系統階層標準。它定義了 Linux 作業系統中主要目錄的結構與內容。FHS 的目的是讓使用者了解已安裝的軟體通常會放在哪個目錄下。
**FHS 出現的契機**:
早期,越來越多個人與企業利用 Linux 系統開發應用程式,但每個人對於配置目錄與檔案的想法不同,導致難以管理。為了方便管理並讓各種 Linux 發行版本的檔案和目錄位置保持一致,才制定了 FHS 這個標準,使 Linux 具有高移植性.
## Linux 的核心思想:萬物皆檔案
在 Linux 系統中,一切都被視為檔案。這包括硬體(如硬碟、鍵盤、滑鼠)、軟體、文件,甚至是正在執行的程式 (Process) 和指令,都會被表示為檔案型態存在於電腦中。例如:
* **設備 (Device)**:硬碟、鍵盤、滑鼠等設備會被表示為檔案,透過 `/dev/sda` 等設備檔案來存取和操作.
* **行程 (Process)**:每個執行的行程都被表示為檔案,可以在 `/proc` 目錄下找到相應的檔案.
* **檔案和目錄**:最常見的概念,用於儲存資料、設定資訊和程式碼.
## FHS 架構
FHS 的結構是層層遞進的,如同樹狀(Tree)結構。所有檔案都存在於根目錄 (`/`) 下,並按照樹狀結構排序。無論系統中有多少磁碟或分區,它們都會被掛載到一個統一的目錄結構中.

**FHS 定義的三層主要目錄**:
* `/`:一切的起始點。
* `/usr`:與軟體、安裝執行有關。
* `/var`:與系統運作有關。
### Windows 檔案系統 vs. Linux 檔案系統
* **Windows Filesystem**:檔案存在不同的驅動器(硬碟)中,每個驅動器都有一個檔案系統,並用驅動器字母區分分割區,例如 `C:`, `D:`, `E:`.
* **Linux Filesystem**:所有檔案都存在 `/` 下,按照樹狀結構排序。驅動器的檔案必須掛載到檔案系統下才能讀取.
### Linux 檔案權限
Linux 是多人多工的系統,為了考慮每個人的隱私權和工作環境,因此引入了使用者和群組的概念.
* **檔案擁有者 (Owner)**:檔案的創建者,通常可以讀取、寫入和執行檔案.
* **群組 (Group)**:每個檔案都會分配給一個群組,群組內的使用者共享該檔案的權限.
* **其他人 (Others)**:系統中除了檔案擁有者和群組成員以外的所有使用者.
### `ls -l` 命令與檔案屬性
`ls -l` 命令用於顯示檔案的詳細資訊,包括檔案類型、權限、連結數量、擁有者、群組、檔案大小、最後修改時間和檔案名稱.

1. **檔案類型與權限 (Mode)**:第一個字元表示檔案類型,隨後 9 個字元分為 3 組(擁有者、群組、其他人)表示讀取 (r)、寫入 (w)、執行 (x) 權限.
* `-`:一般檔案.
* `d`:目錄.
* `l`:符號連結 (symbolic link).
* `b`:區塊設備檔案 (block device file).
* `c`:字元設備檔案 (character device file).
* `r`:讀取權限 (read).
* `w`:寫入權限 (write).
* `x`:執行權限 (execute).
* **檔案顏色**:藍色為目錄,白色為一般檔案,淺藍色為連結檔,綠色為可執行檔,紅色為壓縮檔.
2. **連結數量 (Links)**:指向此檔案的 hardlink 數量.
3. **擁有者 (Owner)**:檔案的擁有者名稱.
4. **群組 (Group)**:檔案所屬的群組名稱.
5. **檔案大小 (Size)**:檔案的大小,單位為位元組 (bytes).
6. **最後修改時間 (Timestamp)**:檔案最後修改的日期和時間.
7. **檔案名稱 (Name)**:檔案或目錄的名稱.
**檔案時間參數**:
* `mtime` (modification time):檔案內容資料變更時更新.
* `ctime` (status time):檔案狀態(如權限、屬性)改變時更新.
* `atime` (access time):檔案內容被取用時更新.
### 權限管理指令
* **`chmod`**:更改檔案或目錄權限. 可以使用數字(八進位)或符號模式設定權限.
* 數字模式:`r=4`, `w=2`, `x=1`.
* 符號模式:`u` (user), `g` (group), `o` (others), `a` (all). `+` (增加), `-` (去除), `=` (設定) 權限.
* **`chgrp`**:改變檔案所屬群組.
* **`chown`**:改變檔案或目錄的擁有者和/或群組.
### 使用者與群組管理
* **`adduser` & `useradd`**:用於新增使用者. `adduser` 會自動建立家目錄並設定密碼,而 `useradd` 需要手動設定這些選項.
* **`userdel`**:刪除使用者.
* **UID (User Identifier)**:每個使用者都有一個唯一的數字 ID,系統透過 UID 來辨識使用者. UID 0 通常是 root.
* **GID (Group Identifier)**:每個群組都有一個唯一的數字 ID.
* **`id`**:查看使用者的 UID 和 GID.
* **`passwd`**:更改密碼.
### 特殊權限
* **Sticky Bit**:設定在目錄上時,該目錄內的檔案和子目錄只能由檔案所有者、目錄所有者或 root 超級使用者刪除或重命名. `/tmp` 目錄通常會設定 sticky bit (權限為 `1777`).
* **Set UID (SUID)**:當一個程式設定了 SUID 權限,任何執行該程式的使用者,其產生的行程權限會等同於該程式的擁有者權限.
## 根目錄 (`/`) 與其子目錄
根目錄 (`/`) 是 Linux 系統中最重要的目錄,是所有目錄的根源,與開機、還原、系統修復等動作息息相關.
### `/root`
* 放置系統管理員 (root) 的家目錄.
* root 帳號是 Linux 作業系統中最高權限的使用者. 一般不建議直接使用 root 帳號操作,以避免誤操作損毀系統.
### `/home`
* 系統預設的使用者家目錄.
* 新增一般使用者帳號時,其家目錄通常會建立在此目錄下,名稱通常與使用者名稱相同.
* **代號**:`~` 代表目前使用者的家目錄,`~<使用者名稱>` 代表特定使用者的家目錄.
* `/etc/skel`:新增使用者時,此目錄下的所有檔案會自動複製到新使用者的家目錄,用於初始化家目錄.
### `/bin` (Binary)
* 存放一些一般使用者可以操作的基礎指令,例如 `cat`, `mkdir`, `mv`, `cp` 等.
* `/bin` 底下的指令可以被 root 和一般帳號使用.
* **合併**:自 2021 年 2 月起,`/bin` 和 `/usr/bin` 已合併,功能相同.
### `/sbin` (Super user Binaries)
* 存放一些超級使用者權限才能使用的指令,以及一些與系統管理、開機、修復、還原系統相關的指令,例如 `shutdown`, `ifconfig`.
* `sudo` (Super User DO) 命令可以用來取得 root 權限執行這些指令.
* **合併**:`/sbin` 和 `/usr/sbin` 已合併,功能相同.
### `/lib` (Library)
* 存放系統函式庫和核心函式庫,例如開機時使用的函式庫.
* `/bin` 或 `/sbin` 底下的指令會呼叫的函式庫.
* **什麼是函式庫?** 函式庫就像程式的圖書館,是已經寫好的 Function 集合,需要使用時只需導入即可.
* **合併**:`/lib` 和 `/usr/lib` 已合併,功能相同.
### `/lib<qual>`
* 存放與 `/lib` 不同格式的二進位函式庫,例如 `/lib64` 支援 64 位元函式庫.
### `/etc`
* 放置系統主要的設定檔案,如帳號密碼、網路設定、服務啟動檔等.
* 通常一般使用者可以查看此目錄中的檔案,但只有 root 可以修改.
#### `/etc/passwd`
* 儲存使用者資訊,每行代表一個帳號.
* **欄位架構**(以 `:` 隔開):
1. 使用者名稱.
2. 密碼佔位符(通常是 `x`,表示密碼儲存在 `/etc/shadow` 中).
* `x`:對應到 `/etc/shadow` 的密碼.
* `!`:此帳號被鎖定,不能用密碼登入 (用於使用者).
* `*`:此帳號被鎖定,不能用密碼登入 (用於服務).
* 空白:沒有密碼,此時 `passwd` 命令會直接進入設定密碼的環節.
3. 使用者 ID (UID):在 Linux 中,透過 UID 來辨別使用者.
4. 使用者所在群組 ID (GID).
5. 使用者的資訊/完整名稱 (在 `adduser` 指令中輸入的資訊會存在此欄位,用 `,` 隔開).
6. 登入後的起始目錄 (家目錄).
7. 登入後 shell 的路徑.
#### `/etc/shadow`
* 真正放置使用者加密後密碼的地方.
* 只有 root 才能查看,以防止密碼被破解.
* **歷史**:以前 `/etc/passwd` 中有存使用者密碼,但因加密技術不成熟且密碼簡單,為安全性考量才將密碼移至 `/etc/shadow` 並加密.
* **欄位架構**(以 `:` 隔開):
1. 使用者名稱.
2. 加密後的密碼(以 `$number$` 開頭表示加密方式,如 `$1$` 為 MD5,`$5$` 為 SHA-256,`$6$` 為 SHA-512).
3. 上一次密碼變更的天數(從 1970 年 1 月 1 日算起).
4. 密碼最短使用期限(兩次變更密碼最短間隔天數,0 表示隨時可改).
5. 密碼最長使用期限(密碼最多可使用天數,空或 99999 表示關閉此功能或不需要重新設定).
* **注意**:若密碼最短使用期限大於密碼最長使用期限,則使用者無法更改密碼.
6. 密碼過期前發出警告的期限 (天).
7. 密碼過期後的放寬天數(過期後使用者還能登入更改密碼的時間).
8. 帳號過期時間 (從 1970 年 1 月 1 日算起的天數).
9. 保留字段.
### `/boot` (bootstrap)
* 放置系統開機時會使用的相關載入檔,包括 Linux 核心檔案以及開機選單與開機所需設定檔.
* `initrd.img` (Initial ramdisk):在啟動階段會被 Linux 呼叫,是暫時的 root 檔案系統,用於在掛載真正檔案系統前做準備.
* `/etc/grub`:開機管理模式,支援多個作業系統啟動.

### `/dev` (device)
* 存放與設備(如硬碟、USB、終端機、鍵盤、滑鼠)對應的設備檔案.
* 在 Linux 中,任何硬體裝置與周邊設備的相關資料都以檔案型態儲存在 `/dev` 中.
* `/dev/null`:一個特殊的空裝置檔案,任何寫入其中的數據都會被丟棄,被稱為「黑洞」.
### `/media`
* 放置可移除的自動裝置掛載目錄,例如軟碟、光碟、DVD、USB.
* 在 Ubuntu 等系統中會自動掛載.
### `/mnt` (mount)
* 為管理員、使用者手動掛上 (mount) 的目錄,用於暫時掛載某些額外的裝置.
* 與 `/media` 不同的是,`/mnt` 需要系統管理員手動掛載.
* **掛載 (Mount)**:由作業系統使儲存裝置上的電腦檔案和目錄可供使用者通過電腦的檔案系統訪問的過程.
#### `/dev`, `/media`, `/mnt` 的區別
| 目錄 | 目錄內容 | 例如在 Ubuntu 上接 USB |
| -------- | -------------------- | -------------------------------------------- |
| `/dev` | 放置各種硬體設備檔案 | 只要 USB 成功連接上電腦,`/dev` 下就會顯示 USB 的設備檔 |
| `/media` | 放置可移除的裝置**自動掛載**的目錄 | **系統**會自動將 USB 中的檔案掛載到 `/media` |
| `/mnt` | 放置臨時**手動掛載**的目錄 | **系統管理員**可以手動將 USB 中的檔案掛載至 `/mnt` |
### `/opt` (optional)
* 放置第三方軟體的目錄.
* 這些軟體通常是透過非 `apt install` 指令安裝的,例如 Chrome.
* 將第三方軟體放在此處,可避免汙染系統環境.
### `/run`
* 放置系統開機後運作時產生的資訊,以及各種服務所需的暫存檔案.
* 例如 `.pid` 檔案,記錄目前行程的 ID,用於防止同一個服務同時啟動多個副本.
### `/srv` (service)
* 放置一些 Ubuntu 規定的網路服務啟動後所需取用的資料目錄.
* 例如 FTP 服務的預設資料夾是 `/srv/ftp`.
### `/tmp` (temporary)
* 讓一般使用者或正在執行的程式暫時存放檔案的地方.
* 通常開機時 `/tmp` 的資料會被刪除,不適合放重要資料.
* `/tmp` 的權限通常是 `777` (所有使用者與群組皆可讀、寫、執行).
* 可透過設定 `noexec` 選項來關閉執行權限,增加安全性,避免惡意程式執行.
* `/dev/shm` 也是一個任何人都可以任意寫入的地方,它是存在記憶體中的臨時檔案系統,讀寫速度很快.
## `/usr` 及其子目錄
`/usr` 全名為 Unix software resource (或 Unix System Resources、Unix Software Resources),放置 Unix 作業系統軟體資源,相關軟體、服務等,而非使用者資料. 系統安裝時此目錄通常佔用最多磁碟容量.
### `/usr/bin`
* 放置一般使用者能夠使用的指令,使用者安裝的程式的指令會在這裡.
* **合併**:`/usr/bin` 已與根目錄下的 `/bin` 合併,功能相同.
### `/usr/sbin`
* 存放非系統平時運作所需要的指令,通常給超級使用者使用.
* **合併**:`/usr/sbin` 已與根目錄下的 `/sbin` 合併,功能相同.
### `/usr/lib`
* 存放額外安裝的函式庫,而非系統基本的函式庫,例如 Python 或 GCC 的函式庫.
* **合併**:`/usr/lib` 已與根目錄下的 `/lib` 合併,功能相同.
### `/usr/local`
* 放置系統管理員自行安裝的軟體(非系統預設提供),方便管理.
* 此目錄下也有 `/bin`、`/lib`、`/etc` 等子目錄.
* 通常用於將自行安裝的軟體與作業系統的預設軟體區分開來,避免影響原系統或無需重新安裝全部程式.
* **`prefix`**:配置安裝路徑的選項,可指定軟體的安裝位置,避免雜亂.
### `/usr/share`
* 主要放置唯讀架構的檔案,幾乎都是文字檔案.
* 例如 `man` (線上說明文件).
## `/var` 及其子目錄
`/var` (variable) 記載著各種系統上的變數,針對常態性變動的檔案. 系統開始運行後,會漸漸開始佔用硬碟容量,適合存放需要頻繁改寫的檔案,例如快取 (cache)、紀錄檔 (log file) 以及某些軟體運作所產生的檔案.
### `/var/cache`
* 放置程式本身運作過程中會產生的一些暫存檔,例如 `apt install` 命令下載的套件.
### `/var/lib`
* 放置程式運作過程中需要使用到的資料檔案,例如 MySQL 的資料庫和表格通常會存在這裡.
* 與 `/usr/lib` 類似,但 `/var/lib` 目錄是可寫的.
### `/var/lock`
* 放置被上鎖的檔案,避免兩個應用程式同時使用同一個檔案而發生問題.
* 目前此目錄已挪到 `/run/lock` 中.
### `/var/log`
* 放置各種重要的系統紀錄檔,包括系統訊息、錯誤訊息、開機紀錄、郵件往來資訊、登入登出記錄等.
* 例如:
* `/var/log/syslog`:記錄系統登入資訊、Kernel 錯誤或警示資訊.
* `/var/log/boot.log` 或 `/var/log/bootstrap.log`:記錄系統開機或服務啟動/關閉訊息.
* `/var/log/mail.log`:記錄郵件往來資訊.
* `/var/log/wtmp`:記錄登入者的相關資訊.
* `/var/log/btmp`:記錄登入失敗的資訊.
* `/var/log/auth.log`:記錄所有與認證和安全相關的事件,如登錄嘗試、`sudo` 使用、SSH 登錄等.

### `/var/mail`
* 放置個人郵箱信件的目錄. 目前這個目錄也可能被放置到 `/var/spool/mail/` 目錄中.
### `/var/spool`
* 放置佇列資料(排隊等待其他程式使用的資料),例如列印佇列或郵件佇列. 使用後的資料通常會被刪除.
## 沒在 FHS 但重要的目錄
### `/lost+found`
* 當檔案系統發生錯誤時,會將遺漏的訊息或檔案片段放置到此目錄.
* 通常此目錄為空白. `ext2/3/4` 檔案系統有此目錄.
### `/proc` (process)
* 一個虛擬檔案系統 (virtual filesystem),目錄中放置的資料是在記憶體中,因此不佔硬體空間.
* 記錄系統核心、行程 (process) 資訊、周邊裝置狀態、網路狀態等等.
* 例如 `/proc/cpuinfo` 記錄 CPU 相關資訊.
* 使用 `ls -l` 查看時,檔案大小為 0.
* `/proc` 提供了一種將系統內部狀態抽象為檔案的方式,方便查看和管理.

### `/sys` (system)
* 與 `/proc` 相似,同樣為虛擬檔案系統,不佔硬體空間,資料儲存在記憶體中.
* 記錄 kernel (核心) 與系統硬體相關的資訊,例如已載入的核心模組、核心偵測到的硬體設備資訊.
## Linux 常用指令
| 指令 | 簡介|
| ---- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `cd`| `c`hange `d`irectory,切換路徑。 `cd ..` 回到上一個目錄,`cd .` 當前目錄,`cd -` 回到前一個工作目錄,`cd ~` 回到家目錄|
| `ls`| `l`i`s`t,列出目前目錄下的檔案及目錄列表. <br> `-l`: 顯示詳細資訊. <br> `-a`: 顯示所有檔案(包括隱藏檔案與目錄). <br> `-r`: 以反向排序列出. <br> `-R`: 列出目錄下所有檔案,包含子資料夾. <br> `-t`: 依照檔案建立時間列出. <br> `-S`: 依照檔案大小排序. |
| `sudo` | `S`uper `U`ser `DO`,以電腦管理員身份執行該指令.|
| `^c` (`Ctrl+c`) | 中斷進行中的程式. |
| `^z` (`Ctrl+z`) | 暫停但不中斷程式.|
| `^l` (`Ctrl+l`) | 清除之前的畫面.|
| `pwd`| `p`rint `w`orking `d`irectory,顯示當前目錄位置.|
| `mkdir` | `m`a`k`e `dir`ectory,建立資料夾.|
| `touch` | 新增檔案.|
| `cat` | `con`catenate,將檔案內容印出.|
| `head` | 顯示檔案的前面幾行,預設 10 行.|
| `tail` | 顯示檔案的最後幾行,預設 10 行,`-f` 可實時監控檔案變動 (常用於日誌).|
| `more` | 分頁顯示檔案內容,適用於顯示較大的檔案,只能向下翻頁.|
| `less`| 類似 `more`,但可以上下滾動並支援搜索功能,更靈活.|
| `cp` | `c`o`p`y,複製檔案. `-r` 複製資料夾 (recursive),`-p` 連同檔案權限、擁有者、時間都複製 (常用於備份).|
| `rm` | `r`e`m`ove,刪除檔案. `-r` 刪除資料夾 (recursive),`-f` 強制刪除 (要小心使用!).|
| `rmdir` | `r`emove `dir`ectory,刪除空資料夾.|
| `mv`| `m`o`v`e,移動檔案 (剪下貼上) 或重新命名.|
| `echo` | 將字串輸出到終端機. `echo $PATH` 印出路徑環境變數. `echo $$` 印出當前 shell 的 PID.|
| `man` | Manual,查閱系統中每個命令或程式的手冊頁.|
| `info` | 提供比 `man` 更詳細、更結構化的檔案說明. |
| `whatis` | 更簡潔的指令說明,只返回一行簡短描述.|
| `type` | 查詢某個指令的型態.|
| `file`| 確定檔案型態.|
| `uname` | 顯示有關 Linux 系統基本資訊,`-a` 顯示詳細系統資訊.|
| `netstat` | 查看系統的網路連接和統計數據.|
| `ss`| 現代化的 socket 統計工具,顯示網路連接、監聽 port 等.|
| `dig` | DNS 查詢工具,用於獲取域名的 DNS 資訊.|
| `ping`| 測試網路連通性.|
| `ifconfig`| 查看目前啟用的網路介面,超級使用者可關閉/開啟網卡. (需安裝 `net-tools`).|
| `ps` | 列出行程狀態 (靜態),`ps aux` 顯示所有行程的詳細資訊.|
| `top`| 動態監控系統狀態,包括 CPU 使用率、RAM 使用情況、行程數量等.|
| `history` | 顯示用戶執行過的命令歷史.|
| `df` | 檢視硬碟使用狀況,`-h` 以人類可讀單位顯示. |
| `lsblk` | 列出區塊裝置資訊. |
| `ln -s` | 建立軟連結 (Soft Link),類似 Windows 捷徑.|
| `ln`| 建立硬連結 (Hard Link),指向檔案的實際數據區塊,刪除原檔案不會影響硬連結.|
| `sl` | 一個會顯示小火車動畫的程式,用於打錯 `ls` 時的幽默提示 (需安裝 `sudo apt install sl`). |
| `sudo -i` | 切換到 root 使用者的命令,並進入該使用者的登錄環境. |
| `mount` | 手動掛載儲存裝置.|
| `umount` | 卸載裝置. (注意是 `umount` 而非 `unmount`).|
| `grep` | 搜尋文件內容.|
| `last` | 顯示近期登錄過的使用者記錄.|
| `lastlog` | 顯示最後一次登入的使用者資訊.|
| `who` | 顯示現在系統上有哪些使用者登入. |
| `w`| 顯示系統上有哪些人,以及他們正在做什麼. |
| `sudo apt update` | 檢查軟體源更新.|
| `sudo apt upgrade` | 下載並安裝更新. |
| `whereis` | 列出某個檔案或目錄的位置.|
| `pstree` | 以樹狀圖檢視所有執行中的作業.|
| `dmesg` | 顯示開機訊息 / 顯示硬體狀態.|
| `vim` / `nano` | 文字編輯器. `vim` 有三種模式:一般指令模式、編輯模式、指令列命令模式.|
## 伺服器磁碟分割考量
Linux 系統中的每個目錄存放不同用途的檔案。在規劃伺服器時,可以根據主機用途來規劃磁碟分割,例如:
* **Mail server**:`/var/spool` (郵件佇列) 空間要大.
* **Web server**:`/home` (使用者網頁空間) 或 `/var/www/` (預設網頁路徑) 可能需要較大空間.
**為什麼要分割磁區?**
* **效能考量**:將資料集中有助於資料讀取速度和效能,不同磁區位置會影響讀寫速度.
* **資料安全性**:磁區檔案系統損壞時,不會影響到其他磁區.
* **壞處**:分割大小難以拿捏.