# Linux 系統核心與操作實務 :::info **Author: Tai Ming Chen  ==[About me](https://mingchen.dev)==** **Lead, Google Developer Group On Campus NCUE** ::: >[!Important] **摘要:** >本文檔涵蓋各大 Linux 基礎知識點,並於各章節後附上實務操作,可由此練習並確保自己已完全理解。此文內容涵蓋檔案系統架構、核心指令操作、權限管理、遠端連線、套件管理及資源監控等,適合追求系統化學習的 Linux 初學者。 > [!Note] **前言:** > 若您尚未於 **Google Cloud Platform (GCP)** 配置 **VM instance**,請先參閱我寫的這篇文章 [**GCP Compute Engine 部署指南**](https://hackmd.io/@mingchen/gcp) 完成環境準備。如取得 VM 後需設定本機終端機 (Local Terminal) 的 SSH 連線,建議先行閱讀本文 [**章節 5.2**](https://hackmd.io/451UTxynQZOTjeD86aqr3g?both=#52-%E5%B8%B8%E7%94%A8%E6%8C%87%E4%BB%A4%E8%A7%A3%E6%9E%90) 完成配置。 **目錄** [TOC] --- ## 一、Linux 核心設計哲學 (Linux Core Design Philosophy) 在操作 Linux 系統前,需理解其兩大核心設計概念: ### 1.1 一切皆檔案 (Everything is a file) Linux 系統將幾乎所有的資源抽象化為檔案形式進行管理。不僅限於文字或二進位資料,目錄(Directory)、硬體裝置(如硬碟 `/dev/sda`、終端機 `/dev/tty`)、甚至執行中的進程(Process)與網路連線,在核心(Kernel)視角下皆以檔案描述符(File Descriptor)進行讀寫與操作。 ### 1.2 單一樹狀結構 (Single Hierarchical Tree) ![image](https://hackmd.io/_uploads/HkWbOKsUWg.png) Linux 採用單一根目錄結構。所有儲存裝置與分割區(Partition)皆掛載(Mount)於根目錄 `/` 之下。此設計異於 Windows 系統的多磁碟代號(如 C:\, D:\)架構,確保了檔案路徑的統一性與邏輯一致性。 ### 1.3 沉默是金 (Silence is Golden) Linux 指令遵循「==**沒有消息就是好消息 (No news is good news)**==」的準則。 執行指令後,若系統直接跳回提示字元(Prompt)而未顯示任何訊息,代表**指令已成功執行**。只有在發生錯誤或警告時,系統才會主動輸出文字。此設計是為了讓指令能更方便地被其他程式調用或串接,避免不必要的資訊干擾自動化流程。 ### 1.4 組合小工具完成複雜任務 (Small Tools & Pipes) Linux 傾向開發功能單一且專精的小工具,而非功能包山包海的巨型軟體。透過 **管線 (Pipe, `|`)** 機制,將前一個指令的輸出(Stdout)直接傳遞給下一個指令當作輸入(Stdin)。例如:`ps` (列出進程) 本身不具備搜尋功能,但透過 `ps aux | grep nginx` 即可達成強大的搜尋效果。 ### 1.5 終端機操作效率與慣例 (Terminal Efficiency and Conventions) Linux 終端機 (CLI) 的設計目標是極致的效率,熟練以下操作慣例能大幅提升工作速度: * **自動補全 (Tab Completion)**: 輸入指令或檔名時,只需打前幾個字並按下 **`Tab` 鍵**,系統會自動補齊剩餘名稱。 * 若按一下 `Tab` 沒反應,代表有重複的名稱,此時**連按兩下 `Tab`**,系統會列出所有可能的選項供你參考。 * **複製與貼上 (Copy & Paste)**: 在 Linux 終端機中,`Ctrl+C` 是終止程式,並非複製。 * **複製**:選取文字後通常即自動複製,或使用 `Ctrl + Shift + C` (視終端機軟體而定)。 * **貼上**:點擊 **滑鼠右鍵** 或使用 `Ctrl + Shift + V`。 * **常用快捷鍵 (Shortcuts)**: * **`Ctrl + C`**:**中斷 (Interrupt)**。強制終止目前正在前景執行的程式)。 * **`Ctrl + L`**:**清屏 (Clear)**。清除畫面內容,讓游標回到頂端(等同於輸入 `clear` 指令)。 * **`Ctrl + D`**:**結束輸入 (EOF)**。退出目前的 Shell 連線(等同於輸入 `exit`)。 * **`Up / Down Arrow`**:**歷史紀錄**。快速切換執行過的上一條或下一條指令。 * **`Ctrl + R`**:**搜尋歷史**。輸入關鍵字,快速搜尋過去曾執行過的複雜指令。 * **`Ctrl + A` / `Ctrl + E`**:將游標快速移動到指令行的 **開頭 (Home)** 或 **結尾 (End)**,在編輯長指令時非常實用。 --- ## 二、檔案系統階層標準 (FHS, Filesystem Hierarchy Standard) ![image](https://hackmd.io/_uploads/ByPFjYsL-e.png) Linux 目錄結構遵循 FHS 標準,各目錄具備明確的定義與用途。以下為核心目錄的技術解析: | 目錄路徑 | 全名與意義 | 技術解析與用途 | | :--- | :--- | :--- | | **/** | **Root** | **根目錄**。檔案系統的邏輯起點,僅系統管理員 (Root) 具備寫入權限。 | | **/bin** | **Binaries** | **使用者二進位執行檔**。存放系統運作所需之最基礎指令(如 `ls`, `cp`, `bash`),供所有使用者執行,通常在單人維護模式下仍可使用。 | | **/sbin** | **System Binaries** | **系統二進位執行檔**。存放系統管理與維護指令(如 `ifconfig`, `fdisk`, `reboot`),主要由系統管理員執行。 | | **/etc** | **Etc.** | **系統設定檔**。存放系統與應用程式的全域設定檔案(如 `/etc/passwd`, `/etc/ssh/sshd_config`)。此目錄內容均為文字檔,是系統備份的關鍵標的。 | | **/home** | **Home** | **使用者家目錄**。一般使用者的預設工作空間。例如使用者 `user1` 的家目錄位於 `/home/user1`。 | | **/var** | **Variable** | **可變動資料**。存放系統運作過程中頻繁變更的檔案,包含系統日誌 (`/var/log`)、郵件佇列、快取與資料庫檔案。 | | **/tmp** | **Temporary** | **暫存目錄**。提供程式或使用者存放臨時檔案。多數系統設定為重新啟動後自動清空此目錄。 | | **/usr** | **Unix System Resources** | **使用者系統資源**。存放安裝的應用程式、函式庫與文件。架構類似根目錄,內含 `bin`, `lib`, `local` 等子目錄。 | | **/dev** | **Devices** | **裝置檔案**。硬體裝置的介面檔。例如 `/dev/sda` 對應第一顆實體磁碟,`/dev/null` 為空裝置(寫入的資料將被丟棄)。 | | **/proc** | **Process** | **虛擬檔案系統 (Procfs)**。此目錄不佔用硬碟空間,而是核心與行程狀態在記憶體中的映像。可讀取系統即時資訊(如 `/proc/cpuinfo`, `/proc/meminfo`)。 | >[!Note] **實務演練#1: 系統探索** > **說明**:參照下方指令,熟悉目錄結構並尋找特定系統資訊。 > > 1. **切換路徑**:前往系統日誌目錄 `/var/log` 並執行 `pwd` 確認路徑為 `/var/log`。 ![image](https://hackmd.io/_uploads/Bk7J2KoIWg.png) > 3. **尋找資訊**:欲確認目前 Linux 核心版本,可執行 `cat /proc/version` 應顯示類似 `Linux version 5.x.x...` 的資訊。 ![image](https://hackmd.io/_uploads/ByXJ6FoI-x.png) --- ## 三、指令列操作與檔案管理 (Command Line Operations and File Management) ### 3.1 基礎指令 * **`pwd`** (Print Working Directory):顯示目前所在的工作目錄絕對路徑。 * **`ls`** (List Directory Contents):列出目錄內容。 * `ls -l`:以長格式顯示詳細資訊(權限、擁有者、檔案大小、修改時間)。 * `ls -a`:顯示所有檔案,包含隱藏檔(檔名以 `.` 開頭)。 * `ls -lh`:以人類可讀格式(Human-readable,如 KB, MB)顯示檔案大小。 * **`cd`** (Change Directory):切換工作目錄。 * `cd /etc`:切換至指定**絕對路徑**。 * `cd ..`:切換至上一層目錄。 * `cd ~` 或 `cd`:切換至使用者的家目錄。 * `cd -`:切換至前一次所在的目錄。 * **`touch filename`**:建立空檔案,或更新既有檔案的時間戳記(Timestamp)。 * **`mkdir dirname`** (Make Directory):建立新目錄。 * `mkdir -p dir1/dir2`:建立多層級目錄,若父目錄不存在則自動建立。 * **`cp source destination`** (Copy):複製檔案或目錄。 * `cp file1 file2`:複製檔案。 * `cp -r dir1 dir2`:遞迴複製(Recursive),用於複製目錄及其內容。 * **注意**:若目標檔案已存在,預設將直接覆蓋。 * **`mv source destination`** (Move):移動或重新命名檔案。 * `mv file1 dir1/`:將檔案移動至指定目錄。 * `mv oldname newname`:在同一目錄下移動即為 **重新命名**。 * **`rm filename`** (Remove):刪除檔案或目錄。**此操作無法復原**。 * `rm file1`:刪除檔案。 * `rm -r dir1`:遞迴刪除目錄及其內容。 * `rm -rf /`:強制遞迴刪除根目錄(危險指令,會直接把系統清空)。 * **`file filename`**:辨識檔案類型。Linux 依據檔案標頭(Header)而非副檔名判斷類型。 ### 3.2 檔案內容檢視 * **`cat filename`** (Concatenate):輸出檔案完整內容至標準輸出(Stdout)。適合小型檔案。 * **`less filename`**:分頁檢視器。支援上下捲動與搜尋,按 `q` 退出。適合大型檔案。 * **`head -n 5 filename`**:讀取檔案前 5 行。 * **`tail -n 5 filename`**:讀取檔案末尾 5 行。 * `tail -f filename`:持續監控檔案新增內容(Follow),常用於即時監控系統日誌。 >[!Note] **實務演練#2: 網站部署模擬** > > :::warning > **情境說明**: 你是公司的系統管理員。現在目標是要你準備一個新網站的專案資料夾結構,專案名稱為 `MySite`。在開發過程中,你會經歷架設目錄、寫入檔案、檢察系統日誌、發現放錯位置需要搬移、進行備份,以及最後刪除舊版本的一連串流程。 > ::: >請依序完成以下 6 個關卡: > > #### 關卡 1:基礎建設 (建立結構) > 1. 請確保你現在位於家目錄 (`~`)。 > 2. 建立一個名為 `MySite` 的主目錄。 > 3. 進入該目錄,並使用**一行指令**同時建立三個子目錄:`css`、`js`、`images`。 > 4. 在 `MySite` 裡面建立一個空的 `index.html` 以及 `style.css` 檔案。 > > #### 關卡 2:填錯位置了 (移動與更名) > 1. 你發現你在 `MySite` 的根目錄下誤建了一個 `style.css` 檔案。 > 2. 請把這個 `style.css` **移動** 到 `css` 子目錄裡面。 > 3. 老闆說首頁名稱不喜歡 `index.html`,請把它 **重新命名** 為 `welcome.html`。 > > #### 關卡 3:寫入內容與檢視 (編輯與預覽) > 1. 網頁不能是空的。請使用 `echo` 指令搭配 **輸出重導向符號 (`>`)**,將字串 `"<h1>Hello Linux</h1>"` 寫入至 `welcome.html` 檔案中。 > > :::warning > **註:** 指令為 `echo "<h1>Hello Linux</h1>" > welcome.html` > ::: > > 2. 使用 `cat` 指令確認 `welcome.html` 的內容是否正確寫入。 > 3. 模擬產生一個長日誌檔:請執行 `seq 1 50 > server.log` (產生一個包含數字 1 到 50 的檔案)。 > 4. 檔案太長了,請使用 `head` 指令只看前 5 行,再使用 `tail` 指令只看最後 3 行。 > > #### 關卡 4:緊急備份 (複製目錄) > 1. 開發到一半,你要進行大改版。請**退回到家目錄**。 > 2. 將整個 `MySite` 資料夾(包含裡面所有的子目錄與檔案),**完整複製**一份,並命名為 `MySite_v1.0_backup`。 > > #### 關卡 5:清理與破壞 (刪除) > 1. 回到原本的 `MySite` 資料夾。 > 2. 發現 `images` 資料夾暫時用不到,請將 `images` 資料夾刪除。 > 3. 專案取消了。請回到家目錄,將原本的 `MySite` 資料夾整個 **強制刪除**,只留下備份檔。 > > #### 關卡 6:驗收成果 > 1. 請列出 `MySite_v1.0_backup` 裡面的所有內容 (包含子目錄下的檔案),確認備份是否完整。 --- :::success ### 💡 實戰演練解答 #### 關卡 1 解答:基礎建設 ```bash # 1. 回到家目錄 cd ~ # 2. 建立主目錄 mkdir MySite # 3. 進入目錄並建立子目錄 cd MySite mkdir css js images # 若在外部建立可使用 mkdir -p MySite/{css,js,images} # 4. 建立首頁檔案 touch index.html ``` #### 關卡 2 解答:移動與更名 ```bash # 1. 模擬建立錯誤位置的檔案 touch style.css # 2. 移動檔案 (mv 來源 目的地) # 把當前目錄下的 style.css 搬到當前目錄下的 css 資料夾內 mv style.css css/ # 3. 重新命名 (其實也是 mv 指令) # 把 index.html "移動" 成 welcome.html mv index.html welcome.html ``` #### 關卡 3 解答:寫入內容與檢視 ```bash # 1. 寫入內容 ( > 代表覆蓋寫入) echo "<h1>Hello Linux</h1>" > welcome.html # 2. 檢視檔案內容 cat welcome.html # 輸出應為: <h1>Hello Linux</h1> # 3. 產生長檔案 (seq 產生序列數字) seq 1 50 > server.log # 4. 檢視部分內容 head -n 5 server.log # 輸出: 1 到 5 tail -n 3 server.log # 輸出: 48 到 50 ``` #### 關卡 4 解答:緊急備份 ```bash # 1. 退回家目錄 cd .. # 或執行 cd ~ # 2. 複製整個目錄 (-r 參數: 代表 recursive 遞迴) # 把 MySite 複製成 MySite_v1.0_backup cp -r MySite MySite_v1.0_backup ``` #### 關卡 5 解答:清理與破壞 ```bash # 1. 進入原本的資料夾 cd MySite # 2. 刪除目錄 (需使用 -r 參數) rm -r images # 3. 回家目錄並刪除整個專案 cd ~ # 危險指令之一,請務必確認路徑正確 rm -rf MySite ``` #### 關卡 6 解答:驗收成果 ```bash # 使用 -R (Recursive) 參數來列出所有層級的檔案 ls -R MySite_v1.0_backup ``` **預期輸出結果**: > 註: 備份是在刪除 images 之前做的,所以備份檔應保留完整的 images 目錄 ```text MySite_v1.0_backup: css js images server.log welcome.html MySite_v1.0_backup/css: style.css MySite_v1.0_backup/js: MySite_v1.0_backup/images: ``` ::: ### 核心觀念複習 1. **`>` vs `>>`**: * `>` (覆蓋):會把檔案內容清空後寫入新內容。 * `>>` (累加):會在檔案既有內容的**最後面**新增資料,不會清空舊資料。 2. **檢視指令的選擇 (`cat`, `head`, `tail`)**: * 檔案很小(幾行而已):用 `cat` 一次看完。 * 檔案很大(如幾萬行的日誌):用 `less` (可翻頁) 或 `head`/`tail` (只看頭尾關鍵資訊)。 3. **`mkdir -p`**:如果你想一次建立多層目錄(例如 `mkdir -p A/B/C`),加上 `-p` 參數系統會自動建立父目錄且不會報錯。 4. **`mv` 的雙重身分**:它既是「移動」,也是「重新命名」。差別只在於最後一個參數是「既有的資料夾路徑」還是「新的檔案名稱」。 5. **`cp -r` 與 `rm -r`**:只要是針對「目錄(資料夾)」進行複製或刪除,務必加上 `-r` (recursive),告訴系統需連同目錄內的子檔案一起處理,否則 Linux 會拒絕執行。 --- ## 四、權限控制與使用者管理 (Permission Control and User Management) ### 4.1 檔案權限 (Permissions) Linux 採用多使用者多工架構,權限管理是系統安全的基石。透過 `ls -l` 可檢視檔案權限,格式如:`drwxr-xr-x` (目錄/擁有者權限/群組權限/其他人權限) 權限字串分為四部分:`[檔案類型] [擁有者權限] [群組權限] [其他人權限]` 1. **檔案類型**:`-` 代表一般檔案,`d` 代表目錄,回顧剛剛的實務練習二,可以發現確實僅 `index.html` 以 `-` 標示為一般檔案,其餘則顯示 `d` 代表為目錄。 ![image](https://hackmd.io/_uploads/HyXsMcoUWx.png) 3. **權限旗標**(每三碼一組,分別對應 User, Group, Others): * **r (Read)**:讀取。對檔案為讀取內容;對目錄為可列出清單。 * **w (Write)**:寫入。對檔案為修改內容;對目錄為可建立或刪除檔案。 * **x (Execute)**:執行。對檔案為可執行程式;對目錄為可進入(cd)該目錄。 ### 4.2 權限修改指令 * **`chmod`** (Change Mode):變更檔案權限模式。 * **八進位數值法**:r=4, w=2, x=1。 * `chmod 755 file`:擁有者(7=4+2+1),群組(5=4+0+1),其他人(5=4+0+1)。適合執行檔與目錄。 * `chmod 644 file`:擁有者(6=4+2),群組(4),其他人(4)。適合設定檔與一般文件。 * **符號操作法**: * `chmod u+x file`:為擁有者(User)增加執行權限(Execute)。 * **`chown`** (Change Owner):變更檔案擁有者與所屬群組。 * `chown user:group file`:將檔案擁有者改為 `user`,群組改為 `group`。 ### 4.3 超級使用者與權限委派 (Sudo) * **Root**:於系統中擁有最大權限。直接使用 Root 登入存在高風險。 * **`sudo`** (Superuser Do):允許一般使用者以 Root 權限執行指令。 * `sudo command`:單次以 Root 權限執行。 * `sudo -i`:切換為 Root 身分的 Shell 環境。 * `/etc/sudoers`:定義哪些使用者可以使用 sudo(需用 `visudo` 編輯)。 > [!Note] **實務演練#3: 權限控管** > > :::warning > **情境說明**: 你是情報局的資深技術探員。你的任務是保護一份機密文件,並製作一個自動銷毀程式。為了防止內部間諜竊取資料,你需要嚴格控制檔案的「讀取」與「執行」權限,最後甚至需要動用最高指揮官 (Root) 的權限來接管檔案。 > ::: > > 請依序完成以下 5 個關卡: > > #### 關卡 1:機密檔案建立 (檢視權限) > 1. 確保位於家目錄 (`~`)。 > 2. 建立一個名為 `top_secret.txt` 的檔案,並寫入內容 `"Launch Code: 123456"`。 > > :::warning > **註:** 指令為 `echo "Launch Code: 123456" > top_secret.txt` > ::: > 3. 使用 `ls -l` 檢視該檔案。請觀察第一欄的權限字串(例如 `-rw-rw-r--` 或 `-rw-r--r--`)。 > 4. **思考**:依據預設權限,你的「同群組同事」或「其他人」是否看得到內容?(有 `r` 就代表看得到)。 > > #### 關卡 2:全面封鎖 (修改權限 chmod) > 1. 發現預設權限太危險!請使用 **八進位數值法** 修改權限,設定為: * **擁有者 (User)**:可讀、可寫 (rw) * **群組 (Group)**:無權限 (-) * **其他人 (Others)**:無權限 (-) * *(提示:4=讀, 2=寫, 1=執行)* > 2. 再次執行 `ls -l top_secret.txt`,確認權限字串是否變成了 `-rw-------`。此時這份檔案只有你看得到。 > > #### 關卡 3:自動執行腳本 (執行權限 x) > 1. 建立一個簡單的 Shell 腳本檔案 `nuke.sh`,內容為 `echo "Boom! The mission is complete."`。 > 2. 嘗試直接執行它:輸入 `./nuke.sh`。 > 3. **發生錯誤**:系統應該會回報 `Permission denied` (權限不足),因為檔案預設沒有「執行 (x)」權限。 > 4. 請使用 **符號操作法** (例如 `u+...`),幫這個檔案加上「執行」權限。 > 5. 再次嘗試執行 `./nuke.sh`,確認是否成功印出訊息。 > > #### 關卡 4:最高權限接管 (Sudo 與 Chown) > 1. 為了安全起見,局長要求這份機密檔案 `top_secret.txt` 必須上繳,連你都不能再碰。 > 2. 請使用 `sudo` 搭配 `chown` 指令,將檔案的擁有者改為 **root**。 > > :::warning > **註:** 執行 sudo 時需要輸入你的使用者密碼 > ::: > > 3. 驗證時刻:以你目前的身份嘗試 `cat top_secret.txt`。 > * **預期結果**:應該要出現 `Permission denied`,因為你已經不是擁有者了,且該檔案權限仍是 `600` (只許擁有者讀寫)。 > 4. 只有 Root 能看:請使用 `sudo` 搭配 `cat` 指令強行讀取檔案內容。 > > #### 關卡 5:清理環境 > 1. 任務結束。請刪除 `nuke.sh`。 > 2. 嘗試刪除 `top_secret.txt`。 > * **注意**:這可能會跳出確認訊息,或因為檔案屬於 root 而受到保護。如果刪不掉,請思考如何運用 `sudo` 來強制刪除。 --- :::success ### 💡 實戰演練解答 #### 關卡 1 解答:機密檔案建立 ```bash # 1. 建立檔案並寫入 echo "Launch Code: 123456" > top_secret.txt # 2. 檢視權限 ls -l top_secret.txt # 輸出範例:-rw-rw-r-- user user ... # 解析:最後三碼 r-- 代表其他人可讀,這很危險! ``` #### 關卡 2 解答:全面封鎖 ```bash # 1. 修改權限 (User=4+2=6, Group=0, Others=0) chmod 600 top_secret.txt # 2. 驗證 ls -l top_secret.txt # 預期輸出:-rw------- ``` #### 關卡 3 解答:自動執行腳本 ```bash # 1. 建立腳本 echo 'echo "Boom! The mission is complete."' > nuke.sh # 2. 嘗試執行 (會失敗) ./nuke.sh # 訊息:-bash: ./nuke.sh: Permission denied # 3. 加入執行權限 (u+x 代表 User加Execute) chmod u+x nuke.sh # 或者用數字法:chmod 700 nuke.sh 也可以 # 4. 再次執行 (成功) ./nuke.sh ``` #### 關卡 4 解答:最高權限接管 ```bash # 1. 變更擁有者為 root (需使用 sudo) # 語法:sudo chown [帳號]:[群組] [檔案] sudo chown root:root top_secret.txt # 2. 嘗試自己讀取 (會失敗,因為你現在是 "Others") cat top_secret.txt # 訊息:cat: top_secret.txt: Permission denied # 3. 使用 Root 身分讀取 (成功) sudo cat top_secret.txt ``` #### 關卡 5 解答:清理環境 ```bash # 1. 刪除腳本 rm nuke.sh # 2. 刪除機密檔 (因為擁有者是 root,普通刪除可能會問你是否刪除有防寫保護的檔案) rm top_secret.txt # 如果刪不掉,或不想一直按 y 確認,請用 sudo rm sudo rm top_secret.txt ``` ::: ### 核心觀念複習 1. **權限代號整理 (rwx)**: * 讀取 (`r`=4):看內容。 * 寫入 (`w`=2):改內容。 * 執行 (`x`=1):跑程式 (對檔案) 或 進入資料夾 (對目錄)。 2. **為什麼 `chmod 777` 是禁忌?**:給予 `777` 代表「任何人」都能讀、寫、執行該檔案。這在伺服器上極度危險,駭客可以輕易植入並執行病毒。請習慣使用「最小權限原則」(如 `600`, `644`, `755`)。 3. **`sudo` 的意義**:當你看到 `Permission denied` 時,不要無腦加 `sudo`。先思考是「權限設錯了」還是「你真的需要管理員權限」。 4. **`./script.sh`**:在 Linux 執行當前目錄下的程式,必須加上 `./` 指定路徑,且該檔案必須具備 `x` 權限。 --- ## 五、遠端連線與檔案傳輸 (Remote Connection and File Transfer (SSH)) ![image](https://hackmd.io/_uploads/SkHbosoUWg.png) SSH (Secure Shell) 是 Linux 遠端管理的標準協定。特別是在雲端環境 (如 GCP, AWS),這是你控制伺服器的核心途徑。 ### 5.1 核心運作原理 * **Client / Server 架構**: * **SSH Server (`sshd`)**:被控制端(你的 GCP 雲端主機)。 * **SSH Client (`ssh`)**:控制端(你的本機電腦)。 * **認證方式**: * **金鑰認證 (Public Key Authentication)**:GCP 建議方式。 * **公鑰 (Public Key)**:像是「鎖頭」,部署在 GCP 主機的 `~/.ssh/authorized_keys`。 * **私鑰 (Private Key)**:像是「鑰匙」,留在本機,**絕對不可外流**。 ### 5.2 常用指令解析 在介紹個別指令之前,我們必須先瞭解剛建立好的 GCP VM 要怎麼連進去? 由於 GCP 預設不允許密碼登入,我們必須透過 **SSH 金鑰對 (Key Pair)** 來驗證身分。請依序完成以下四個步驟,這是一勞永逸的最佳設定方法: #### 前置作業:GCP 連線設定 1. **產生專用金鑰 (本機端)** 開啟你電腦的終端機 (PowerShell 或 Terminal),建立一組專門給 GCP 用的金鑰,並透過 `-C` 參數指定使用者名稱(這會成為你登入 Linux 的帳號)。 ```bash # 1. 先進入 .ssh 資料夾 cd ~/.ssh # 2. 生成金鑰對: ssh-keygen -t rsa -f [金鑰路徑/檔名] -C [使用者名稱] ssh-keygen -t rsa -f gcp_key -C user ``` > 過程可直接按 Enter 略過密碼設定 2. **部署公鑰 (GCP Console 端)** 我們要將「鎖頭」交給 GCP。 * 在本機顯示公鑰內容:`cat ~/.ssh/gcp_key.pub` * **完整複製** 輸出內容(包含開頭的 `ssh-rsa` 到結尾的 `user`)。 * GCP 網頁點擊 VM 名稱 -> **編輯 (EDIT)** -> 下滑至 **Security and access** 區塊 -> **新增項目 (Add item)** -> 貼上公鑰 -> **儲存**。 ![image](https://hackmd.io/_uploads/S1iZ0anUZx.png) 3. **設定快速連線 (本機 Config 設定)** 為了避免每次都要打 IP 和指定金鑰路徑,我們編輯 `~/.ssh/config` 檔案(Windows 路徑為 `C:\Users\你的名字\.ssh\config`,若無此檔請手動建立)。 ```text Host my-gcp # 自訂別名 (之後打 ssh my-gcp 即可) HostName 34.81.xxx.xxx # GCP VM 的外部 IP User myuser # 剛才在 -C 指定的使用者名稱 IdentityFile ~/.ssh/gcp_key # 私鑰的絕對路徑 ``` 4. **開始連線** 設定完成後,現在你只需要輸入別名即可登入: ```bash ssh my-gcp ``` --- #### 1. 遠端登入 (`ssh`) 當設定好 Config 後,你的操作將變得非常簡單,但了解原始指令仍很重要: * **`ssh user@IP`**:最基本的登入方式(需預設金鑰 `id_rsa` 已部署)。 * **`ssh -i key_file user@IP`**:指定特定私鑰登入(若未設定 Config 時使用)。 * 例:`ssh -i ~/.ssh/gcp_key myuser@34.81.183.9` * **`ssh <Alias>`**:**推薦方式**。使用 `~/.ssh/config` 設定的別名登入。 * 例:`ssh my-gcp` #### 2. 安全檔案傳輸 (`scp`) SCP (Secure Copy) 是基於 SSH 的檔案傳輸工具,指令邏輯類似 `cp`,但能跨越網路。 **語法結構**:`scp [參數] [來源路徑] [目的路徑]` > **語法**:遠端路徑必須寫成 `使用者@主機:路徑` (注意那個**冒號**)。 | 動作 | 指令範例 | 說明 | | :--- | :--- | :--- | | **上傳檔案** | `scp local.txt user@IP:/home/user/` | 將本機的 `local.txt` 傳到遠端家目錄。 | | **下載檔案** | `scp user@IP:/var/log/syslog ./` | 將遠端的 `syslog` 下載到本機目前目錄 (`./`)。 | | **上傳目錄** | `scp -r project_folder user@IP:/var/www/` | 加上 **`-r`** 參數,遞迴複製整個資料夾。 | | **使用別名** | `scp file.txt my-gcp:~/` | 若已設定 SSH Config,可直接用別名取代 `user@IP`。 | ### 5.3 現代開發神器:VS Code Remote - SSH Visual Studio Code 官方套件允許你直接編輯遠端主機上的檔案,就像在編輯本機檔案一樣,VS Code 會自動處理背後的檔案同步與終端機連線,想知道如何進行配置可見下方實務演練! --- >[!Note] **實務演練#4: 遠端連線及檔案傳輸** > > :::warning > **情境說明**: 你剛在 GCP 啟動了一台 Linux 主機。你的任務是建立從本機到雲端的安全連線,利用 SCP 交換資料,並最終**將 VS Code 連接上雲端主機**,建立一個無延遲的開發環境。 > ::: > > **前置準備**: > 1. GCP Console 網頁上找到 VM 實體,記下 **「外部 IP」**。 > 2. 開啟 GCP 網頁上的 **「SSH」按鈕** 視窗 (作為部署公鑰的管道)。 > 3. 確認本機已安裝 **VS Code** 以及擴充套件 **Remote - SSH**。 > > 請依序完成以下 6 個關卡: > > #### 關卡 1:打造鑰匙 (Local 端產生金鑰) > 1. **回到本機終端機**。 > 2. 進入 `.ssh` 目錄 (通常在 `~/.ssh`)。 > 3. 使用 `ssh-keygen` 產生金鑰,檔名命名為 `gcp_key` (Passphrase 可留空)。 > 4. 使用 `cat` 顯示 **公鑰 (`gcp_key.pub`)** 內容,並複製那串 `ssh-rsa` 開頭的文字。 > > #### 關卡 2:部署鎖頭 (Remote 端安裝公鑰) > 1. **切換到 GCP 網頁版 SSH 視窗**。 > 2. 使用 `nano ~/.ssh/authorized_keys` 編輯授權檔案。 > 3. 將複製的公鑰內容,**貼上** 到檔案最後一行並存檔。 > 4. 保險起見,需確保權限正確:`chmod 600 ~/.ssh/authorized_keys`。 > > #### 關卡 3:建立捷徑 (Local 端 Config 設定) > 1. **回到本機終端機**,編輯 `~/.ssh/config`。 > 2. 新增區塊,別名設為 `my-gcp`: > * HostName: `GCP_外部_IP` > * User: `你的GCP帳號` > * IdentityFile: `本機 gcp_key 私鑰絕對路徑` > 3. 測試連線:執行 `ssh my-gcp`,確認能免密碼登入後輸入 `exit` 登出。 > > #### 關卡 4:上傳檔案 (SCP 上傳) ==如已依照前面指引配置金鑰,則由此關開始實做== > 1. 在本機建立檔案 `app_config.txt`,內容寫入 `"Environment=Production"`。 > 2. 使用 `scp` 指令,透過 `my-gcp` 別名,將此檔案**上傳**到遠端主機的家目錄。 > > #### 關卡 5:下載日誌 (SCP 下載) > 1. 假設遠端主機產生了日誌。請用 `ssh` 遠端執行指令產生一個檔案: > `ssh my-gcp "echo 'System All Green' > system.log"` > 2. 使用 `scp` 指令,將遠端的 `~/system.log` **下載** 回本機目前的目錄 (`.`)。 > 3. 在本機 `cat system.log` 確認內容。 > > #### 關卡 6:遠端連線 (VS Code Remote Connect) > 1. 開啟 **VS Code**。 > 2. 點擊左下角的綠色 `><` 圖示 (或按 `F1` 搜尋 `Remote-SSH: Connect to Host...`)。 > 3. 在選單中,你應該會看到剛剛設定好的別名 **`my-gcp`**,請點選它。 > 4. 系統會詢問平台,請選擇 **Linux**。 > 5. **驗收時刻**: > * 左下角綠色區塊應顯示 `SSH: my-gcp`。 > * 開啟左側檔案總管 (Explorer) -> `Open Folder` -> 預設應為 `/home/你的帳號` -> 按 OK。 > * 你應該能在 VS Code 檔案列表中,直接看到剛剛上傳的 `app_config.txt` 與 `system.log`。試著打開 > `app_config.txt` 修改並存檔,體驗無延遲的開發環境。 --- :::success ### 💡 實戰演練解答 #### 關卡 1 & 2 & 3 (金鑰與 Config) ==**(請參考前文)**== #### 關卡 4 解答:上傳檔案 ```bash # 1. 建立檔案 echo "Environment=Production" > app_config.txt # 2. 上傳 (注意冒號) # 語法:scp [來源] [目的地] scp app_config.txt my-gcp:~/ ``` #### 關卡 5 解答:下載日誌 ```bash # 1. 遠端建立檔案 (模擬) ssh my-gcp "echo 'System All Green' > system.log" # 2. 下載 (注意冒號在前面) # 語法:scp [遠端來源] [本機目的地] # my-gcp:~/system.log -> 遠端路徑 # . -> 本機當前目錄 scp my-gcp:~/system.log . # 3. 檢查 cat system.log ``` #### 關卡 6 解答:VS Code 設定檢查 如果在 VS Code 找不到 `my-gcp`: 1. 檢查 VS Code 設定中 `Remote.SSH: Config File` 是否指到了正確的路徑 (通常預設是 `~/.ssh/config`)。 2. 確保 `Remote - SSH` 擴充套件已啟用。 3. 若連線失敗,點擊 VS Code 右下角的 "Output" (輸出) 面板,切換到 "Remote - SSH" 查看錯誤日誌,通常是 Key 權限問題或 IP 錯誤。 ::: ### 核心觀念複習 1. **SCP 的方向性**: * **上傳 (Push/Upload)**:`scp 本機 遠端:` * **下載 (Pull/Download)**:`scp 遠端: 本機` 2. **別名 (Host Alias) 的重要性**: * 在關卡 6 中你會發現,VS Code 直接讀取了你的 SSH Config。這意味著你**不需要**在 VS Code 裡重新輸入 IP 和金鑰路徑。只要 Config 設得好,所有支援 SSH 的工具都能共用設定。 3. **路徑中的冒號 (`:`)**: * 這是 SSH/SCP 區分「本機路徑」與「遠端路徑」的關鍵符號。漏了冒號,`scp` 會以為你只是想在本機複製檔案並改名而已。 --- ## 六、套件管理與軟體生態系 (Package Management and Software Ecosystem) 在 Windows,我們習慣到各個網站下載 `.exe` 或 `.msi` 檔來安裝軟體;但在 Linux 世界(尤其是企業級環境),這種做法極度不被推薦。 Linux 採用 **集中式軟體庫 (Repositories)** 的管理模式。這是一個由官方維護、經過嚴格資安審查的「App Store」。所有的軟體安裝、更新、移除,都由 **套件管理員 (Package Manager)** 統一處理。 ### 6.1 為什麼我們需要套件管理員? 1. **解決相依性地獄 (Dependency Hell)**:安裝軟體 A 時,它可能需要軟體庫 B 和 C 的特定版本。套件管理員會自動計算並幫你一次裝好,不需要你手動尋找。 2. **安全性 (Security)**:官方軟體庫經過簽章驗證,確保你下載的軟體未被駭客竄改。 3. **統一更新 (Centralized Updates)**:一條指令即可修補系統中**所有**已安裝軟體的漏洞,包含作業系統核心與應用程式。 ### 6.2 Debian/Ubuntu 系列核心指令 (`apt`) 對於 GCP 預設的 Debian 或 Ubuntu 系統,我們使用 **APT (Advanced Package Tool)**。 | 指令 | 說明 | 技術細節 | | :--- | :--- | :--- | | `sudo apt update` | **更新軟體清單** | **這步最重要!** 這不會更新軟體,而是去雲端下載最新的「軟體目錄索引」。若不執行,電腦會找不到最新發布的軟體。 | | `sudo apt upgrade` | **升級所有套件** | 根據剛剛下載的清單,將系統內舊版的軟體升級到最新版。 | | `sudo apt install [軟體名]` | **安裝軟體** | 自動下載軟體及其所有相依套件 (Dependencies)。 | | `sudo apt remove [軟體名]` | **移除軟體** | 移除程式本體,但**保留**設定檔 (Config files)。 | | `sudo apt purge [軟體名]` | **徹底移除** | 移除程式本體**以及**所有的設定檔。 | | `sudo apt autoremove` | **自動清理** | 清除那些「曾經被依賴,但現在已經沒人需要」的孤兒套件,釋放空間。 | > [!Tip]**Tip**: > 在 Red Hat / CentOS / Fedora 系列中,對應的指令是 `dnf` (舊版為 `yum`),操作邏輯基本一致。 --- > [!Note] **實務演練#5: 終端機改造計畫 (Terminal Makeover)** > > :::warning > **情境說明:** > 你是剛接手這台伺服器的工程師。你發現目前的終端機介面樸素乏味。你的任務是透過套件管理工具,安裝 **「系統監控」**、**「系統資訊」** 以及 Linux 界著名的 **「趣味彩蛋」**,將你的終端機打造成一個既專業又有趣的儀表板,並在最後練習如何乾淨地移除這些娛樂軟體。 > ::: > > 請依序完成以下 4 個關卡: > > #### 關卡 1:同步資訊 (Sync) > 在安裝任何東西之前,確保你的軟體目錄是最新的。 > 1. 執行 `sudo apt update`。 > 2. 觀察輸出訊息,確認最後一行顯示 `... packages can be upgraded` 或 `Done`,代表同步完成。 > > #### 關卡 2:視覺化監控 (Process Monitor) > 傳統的 `top` 指令畫面單調。我們要安裝 `htop`,這是一個色彩豐富且支援滑鼠操作的進程管理器。 > 1. 執行 `sudo apt install htop`。 > 2. 安裝完成後,輸入 `htop` 啟動它,你會看到彩色的 CPU 與記憶體使用條。按 `F10` 離開。 > > #### 關卡 3:系統資訊 (System Info) > 我們改用穩定性最高的 `screenfetch`,這是一個能在終端機顯示帥氣 ASCII Logo 與硬體資訊的經典工具。 > 1. 執行 `sudo apt install screenfetch`。 > 2. 直接輸入 `screenfetch` 執行。 > 3. **觀察**:你應該會看到 Linux 發行版的 Logo (如 Debian 的漩渦或企鵝) 以及右側的 CPU、RAM、Uptime 等資訊。 > > #### 關卡 4:小彩蛋 > ![image](https://hackmd.io/_uploads/SyHHnW6LWg.png) > > 為了增加樂趣,我們安裝 `sl` 與 `cmatrix` 兩個特效套件。 > 1. **安裝特效套件:** 執行 `sudo apt install sl cmatrix` (可以一次裝兩個)。 > 2. **小彩蛋-1:** Linux 工程師常因打字太快把 ls 打錯成 sl。於是有人寫了一個軟體,當你打錯時,會有一輛火車開過你的螢幕... > 3. **小彩蛋-2:** 輸入 `cmatrix` 執行,會出現駭客任務的特效 (按 `Ctrl + C` 離開)。 > 4. **Got U 😨:** 老闆說伺服器不能裝遊戲。請執行 `sudo apt purge sl cmatrix` 一次徹底移除這兩個軟體。 > 5. **移除孤兒檔案:** 執行 `sudo apt autoremove`,系統會幫你自動刪除不再被需要的相依檔案。 --- :::success ### 💡 實戰演練解答 #### 關卡 1-3 解答:安裝與執行 ```bash # 1. 更新清單 (必做) sudo apt update # 2. 安裝 htop 與 screenfetch sudo apt install -y htop screenfetch # 3. 執行 htop # 按 F10 離開 screenfetch # 顯示系統資訊 ``` #### 關卡 4 解答:安裝特效與清理 ```bash # 1. 安裝套件 sudo apt install -y sl cmatrix # 2. 執行特效 sl # 3. 執行特效 cmatrix # 按 Ctrl+C 離開 # 4. 徹底移除 (包含設定檔) sudo apt purge -y sl cmatrix # 5. 自動清理不再需要的相依套件 sudo apt autoremove -y ``` ::: ### 核心觀念複習 1. **`update` vs `upgrade`**: * `update` 只是「下載目錄」。 * `upgrade` 才是真的「下載套件」。 >[!Tip] > 先執行 **update**,再進行 **upgrade**。 2. **`remove` vs `purge`**: * 如果你只是暫時不想用,但想保留設定(例如軟體的帳號密碼設定),用 `remove`。 * 如果你想把軟體連根拔起,彷彿它從未來過,用 `purge`。 3. **相依性 (Dependencies)**:安裝 A 軟體時,Linux 自動幫你裝了 B 和 C。當你移除 A 時,B 和 C 就變成了「孤兒 (Orphans)」。使用 `autoremove` 可以幫你把這些沒用的孤兒清掉,節省硬碟空間。 --- ## 七、系統資源監控與進程管理 (System Resource Monitoring and Process Management) ![image](https://hackmd.io/_uploads/r1NhxyaUWx.png) 在 Windows 中,當電腦變慢時,我們會打開「工作管理員」來檢查是哪個程式在吃 CPU。在 Linux 伺服器上,我們沒有圖形介面,必須依賴強大的指令列工具來進行「健康檢查」與「故障排除」。 ### 7.1 即時監控常用指令 | 指令 | 說明 | 核心指標解析 | | :--- | :--- | :--- | | **`top`** | Linux 內建最經典的監控工具。 | **Load Average (平均負載)**:顯示 1、5、15 分鐘內的系統負載。若數值超過 CPU 核心數(例如 2 核 CPU 負載超過 2.0),代表系統過忙。<br>**%CPU / %MEM**:個別進程佔用的資源百分比。 | | **`htop`** |進階版的監控工具,提供圖形化、彩色介面,並支援滑鼠操作。 | 提供直觀的長條圖顯示 CPU 與 RAM 使用量。操作比 `top` 更人性化(可直接按 F9 刪除進程)。 | | **`free -h`** | **記憶體檢查**<br>專門用於查看 RAM 使用情形。 | **Mem**:實體記憶體。<br>**Swap**:置換空間(虛擬記憶體)。當實體 RAM 用光時,系統會變慢並開始使用硬碟當記憶體,這時就要注意 Swap 使用量。 | ### 7.2 進程快照 (`ps`) `top` 是看動態狀況,`ps` (Process Status) 則是取得靜態狀況。常用於查修特定服務是否活著。 * **`ps aux`**:顯示系統上**所有使用者**的**所有進程**詳細資訊。 * `a`:所有終端機下的進程。 * `u`:顯示使用者 (User) 與資源使用資訊。 * `x`:顯示非終端機介面的背景進程 (Daemon)。 * **`ps aux | grep [名稱]`**:最常用的組合技。利用管線 (`|`) 過濾出所關心的進程。 * 範例:`ps aux | grep nginx` (檢查 Nginx 是否在跑)。 ### 7.3 背景工作管理 * **`&` (Background)**:在指令最後加上 `&`,讓程式直接在背景執行,不佔用你的終端機。 * 範例:`sleep 300 &` * **`jobs`**:列出目前 Shell 下所有的背景工作。 ### 7.4 終止進程 (`kill`) 當程式當機或佔用過多資源時,我們需要發送信號 (Signal) 來終止它。 * **`kill [PID]`**:發送 `SIGTERM (15)` 信號。這是**禮貌地**請程式停止,讓它有機會存檔或清理暫存。 * **`kill -9 [PID]`**:發送 `SIGKILL (9)` 信號。這是**強制關閉**。作業系統會直接把該進程從記憶體中移除,程式無法做任何清理。**僅在 `kill` 無效時使用。** * **`pkill [名稱]`**:依據「程式名稱」一次殺死所有相關進程(例如 `pkill nginx`)。 --- > [!Note] **實務演練#6: 資源危機處理** > > :::warning > **情境說明**: > 警告!伺服器出現異常負載。有幾個不知名的「殭屍程式」正在背景偷吃資源,還有一個失控的壓力測試程式佔據了 CPU。你是系統管理員,請利用監控工具找出這些 Bad Guy,並執行「清除計畫」。 > ::: > 請依序完成以下 4 個關卡: > > #### 關卡 1:製造混亂 (背景執行) > 我們要模擬一些背景程式。 > 1. 執行 `sleep 3000 &` (這會模擬一個要在背景睡 3000 秒的閒置程式)。 > 2. 再執行兩次 `sleep 3000 &` (現在你應該有 3 個 sleep 程式在背景執行)。 > 3. 執行 `jobs` 指令,確認你有看到三個 Running 的工作。 > > #### 關卡 2:調查 (ps 與 grep) > 你需要找出這些程式的「身分證字號 (PID)」。 > 1. 使用 `ps aux` 搭配 `grep`,搜尋名稱為 `sleep` 的進程。 > 2. **觀察**:你應該會看到類似以下的輸出,記下第一欄或第二欄的數字 (PID): > ```text > user 1234 0.0 0.0 ... sleep 3000 > user 1235 0.0 0.0 ... sleep 3000 > ``` > > #### 關卡 3:壓力測試 (模擬高負載) > 我們要製造一個真的會吃 CPU 的程式來觀察 `top` 的變化。 > 1. 執行 `yes > /dev/null &` > > :::danger > **警告:** `yes` 是一個會瘋狂輸出 'y' 的指令,我們把它導向黑洞 `/dev/null`,這會導致 CPU 單核心飆高 > ::: > > 2. 立刻輸入 `htop` (或 `top`)。 > 3. **觀察**: > * 找到 CPU 使用率最高的那個進程,它的 Command 應該是 `yes`。 > * 觀察 CPU Bar 是否有一條變成了 100% (紅色或綠色)。 > * 記下這個 `yes` 的 **PID**。 > > #### 關卡 4:清除威脅 (Kill) > 現在要解決問題。 > 1. 在 `htop` 介面中,直接按 `F9` (Kill),選擇剛剛那個 `yes` 進程,並按 Enter (發送 `SIGTERM`),若無法在 htop 操作,可按 F10 離開,改用指令。 > 2. 使用指令 `kill [PID]` 刪除剛剛那三個 `sleep` 進程的其中一個。 > 3. 使用 `pkill sleep`,一次刪除剩下所有的 sleep 進程。 > 4. **驗收**:執行 `jobs`,應該顯示 `Terminated` 或空無一物。執行 `ps aux | grep sleep` 應該只剩下 grep 自己。 --- :::success ### 💡 實戰演練解答 #### 關卡 1 & 2 解答:製造混亂並調查 ```bash # 1. 產生背景程式 sleep 3000 & sleep 3000 & sleep 3000 & # 2. 檢查 jobs # 預期輸出: [1] Running, [2] Running, [3] Running # 3. 找 PID ps aux | grep sleep ``` #### 關卡 3 解答:壓力測試 ```bash # 1. 製造高 CPU 負載 yes > /dev/null & # 2. 開啟監控 htop # 觀察完畢後按 F10 離開 ``` #### 關卡 4 解答:清除威脅 ```bash # 1. 殺死高負載程式 (假設 yes 的 PID 是 9999) kill 9999 # 或者如果殺不掉: kill -9 9999 # 2. 殺死其中一個 sleep (假設 PID 是 8881) kill 8881 # 3. 一次殺光剩下的 sleep pkill sleep # 4. 最終檢查 jobs ``` ::: ### 核心觀念複習 1. **PID (Process ID)**:每個程式都有唯一的編號。要控制程式,就要先知道它的 PID。 2. **`kill` vs `kill -9`**: * 盡量先用 `kill` (SIGTERM),讓程式有機會存檔。真的卡死不動才用 `kill -9` (SIGKILL)。 3. **Pipe `|` 的威力**:`ps aux | grep nginx` 是一個標準動作。`ps` 吐出幾千行資料,透過管線傳給 `grep`,`grep` 只過濾出你要的那一行。 --- ## 八、網路基礎與連線檢測 (Network Fundamentals and Connection Diagnostics) 在 Linux 伺服器維運中,不少的故障排除都與網路有關。當一個網站連不上時,系統管理員必須具備「分層除錯」的能力,依據 OSI 模型由內而外進行檢測。 ![image](https://hackmd.io/_uploads/SyBqEza8We.png) ### 8.1 [Layer 1-3] 網路介面與 IP 配置 (Physical, Data Link & Network Layers) 在開始任何網路通訊前,必須先確認「本機身分」與「硬體狀態」。此層級對應 OSI 模型的物理層(網卡狀態)、資料連結層(MAC)與網路層(IP)。 ![image](https://hackmd.io/_uploads/BysfCZTIWg.png) * **檢測指令**:`ip addr` (顯示 IP 與介面屬性) * 備註:此指令屬於 `iproute2` 套件,已取代舊版 `net-tools` 的 `ifconfig`。 #### 欄位解析: 1. **介面狀態 (Layer 1 - Physical)**: * 看到 `<BROADCAST,MULTICAST,UP,...>` 中的 **`UP`**,代表網卡已啟動且物理連線正常。若顯示 `DOWN`,代表網卡被停用或網路線沒插好。 2. **MAC 位址 (Layer 2 - Data Link)**: * `link/ether` 後面的 `42:01:0a...` 是硬體卡號。在區域網路 (LAN) 中,封包是靠這個地址傳送的。 3. **IP 位址 (Layer 3 - Network)**: * `inet`:**IPv4 位址**。 * `inet6`:**IPv6 位址**。 #### 常見介面說明: * **`lo` (Loopback Interface)**: * **IP**:固定為 `127.0.0.1`。 * **說明**:這是系統專用的虛擬迴圈介面,主要用於本機內部的網路通訊。當應用程式(如 Nginx 連線 MySQL)透過此介面溝通時,封包僅在作業系統核心記憶體中流動,完全繞過實體網卡與線路,因此具備極低延遲、高頻寬,且不受外部網路斷線影響的特性。 * **`eth0` / `ens4` (Ethernet Interface)**: * **命名規則**:`eth` 是傳統命名;`ens` 或 `enp` 是現代 **可預測網路介面命名 (Predictable Network Interface Names)**,依據硬體匯流排位置決定,確保多網卡時順序不亂跳。 > [!Important] **雲端環境特例 (Cloud NAT)** > 在 GCP / AWS 等雲端環境執行 `ip addr` 時,你通常**只會看到內網 IP (Private IP)**。 > 這是因為雲端供應商採用 **1:1 NAT (Network Address Translation)** 技術。外部 IP (Public IP) 其實綁定在資料中心的「網際網路閘道器 (Internet Gateway)」上,閘道器收到封包後再轉發給你的 VM。**這是正常現象,並非設定錯誤。** --- ### 8.2 [Layer 3] 網路連通性測試 (Network Layer) 確認本機 IP 無誤後,下一步是測試「封包能否到達目的地」。這主要依賴 **ICMP 協定**。 * **檢測指令**:`ping [目標主機]` * **範例**:`ping -c 4 8.8.8.8` (測試 Google DNS) * **參數**:Linux 的 ping 預設會無限執行,務必加上 `-c 4` (Count) 只傳送 4 個封包。 #### 診斷邏輯: * **成功 (0% packet loss)**:代表 L3 路由 (Routing) 正常,本機到目標的路是通的。 * **失敗 (100% packet loss)**: * 可能是網路斷線。 * **常見誤判**:目標主機的防火牆設定了 **「拒絕 ICMP」**。許多伺服器為了安全(防 Ping Flood 攻擊)會關閉 Ping 回應,但 Web 服務其實是正常的。因此 Ping 不通不代表服務掛了。 > [!Tip] **找不到 ping 指令?** > 許多精簡版 Linux (如 Docker 容器或雲端極簡 Image) 預設不包含 Ping。若出現 `command not found`,請執行 `sudo apt install iputils-ping` 安裝。 --- ### 8.3 [Layer 4] 傳輸層與監聽檢查 (Transport Layer) 這一層我們關注 **TCP/UDP Port** 與 **Socket** 狀態。這是 Web Server 無法連線最常見的錯誤點。 * **檢測指令**:`ss -tulnp` (Socket Statistics) * **註:** 比舊版 `netstat` 更快更高效,能直接從 Kernel 讀取資訊。* #### 參數說明: * `-t` (TCP) / `-u` (UDP):顯示協定。 * `-l` (Listening):只顯示正在「監聽中」的 Port(等待連線)。 * `-n` (Numeric):不解析服務名稱(顯示 `80` 而非 `http`),加速顯示。 * `-p` (Process):顯示是哪個 **PID** 的程式佔用了這個 Port (需 sudo)。 #### 輸出解讀: | Local Address:Port | 意義 | 安全性與除錯 | | :--- | :--- | :--- | | **`0.0.0.0:80`** | 監聽所有介面 | **正常**。代表允許外部所有 IP 連線進來。 | | **`127.0.0.1:3306`** | 僅監聽 Loopback | **封閉**。代表只允許**本機**連線(常見於資料庫安全設定)。如果想從外部連進來會被拒絕。 | | **`[::]:22`** | IPv6 監聽 | 代表支援 IPv6 的 SSH 連線。 | --- ### 8.4 [Layer 7] 應用層請求測試 (Application Layer) 確認路通了 (L3)、門也開了 (L4),最後就是模擬瀏覽器發送 HTTP 請求,確認應用程式 (Nginx/Apache/App) 是否正常回應。 * **檢測指令**:`curl [URL]` (Client URL) #### 常用檢測模式: 1. **內容驗證**: * 指令:`curl http://127.0.0.1` * 結果:顯示 HTML 原始碼。若看到 `<title>Welcome...</title>` 代表網頁伺服器正確運作。 2. **狀態檢查 (Header Only)**: * 指令:`curl -I http://google.com` * 結果:只看 HTTP Header。重點看第一行的 **Status Code**。 * `200 OK`:正常。 * `301/302`:轉址。 * `404 Not Found`:找不到檔案。 * `500 Internal Server Error`:伺服器錯誤。 3. **詳細除錯 (Verbose)**: * 指令:`curl -v http://google.com` * 結果:顯示完整的通訊過程,包含 **L3 (IP 連線)** -> **L4 (TCP 三向交握)** -> **L7 (HTTP Request/Response)**。這是除錯時用於顯示詳細資訊的常用指令。 --- ### 小結:網路除錯流程 (Troubleshooting Workflow) 當遇到「網頁連不上」或「服務無法存取」的問題時,請依照 OSI 模型 **由下而上** 進行檢查: 1. **L1/L2 (物理/連結層)**:**`ip addr`** * **檢查重點**:網卡介面 (如 `ens4`) 的狀態是否為 **`UP`**? * **判斷**:是否有顯示 **`inet`** (IPv4 位址)?若只有 `lo` (127.0.0.1) 而沒有其他 IP,代表網卡未啟動或未取得 IP。 2. **L3 (網路層)**:**`ping -c 3 8.8.8.8`** * **檢查重點**:封包是否能走出本機並到達網際網路? * **判斷**:顯示 **`0% packet loss`** 代表路由 (Routing) 與外網連線正常。若失敗,問題出在網路設定或閘道器 (Gateway)。 3. **L4 (傳輸層)**:**`sudo ss -tulnp | grep [port]`** * **檢查重點**:服務是否啟動?Port 是否開啟?監聽範圍正確嗎? * **判斷**: * 狀態必須是 **`LISTEN`**。 * 監聽位址若是 **`0.0.0.0:80`** 代表**對外開放** (正常)。 * 監聽位址若是 **`127.0.0.1:80`** 代表**僅限本機** (外部連不進來,需修改服務設定)。 4. **L7 (應用層)**:**`curl -v http://localhost`** * **檢查重點**:Web Server 程式本身是否健康?能否正確處理請求? * **判斷**: * 若顯示 **`HTTP/1.1 200 OK`** 或 HTML 原始碼,代表服務完全正常。 * 若顯示 `Connection refused`,代表 L4 沒開好。 * 若顯示 `500 Internal Server Error`,代表程式碼寫壞了 (與網路無關)。 > [!Tip] **Last mile: 防火牆 (Firewall)** > 如果 L1 到 L7 本機測試全部通過,但外部瀏覽器還是連不進來,通常問題在於 **GCP 防火牆** (VPC Firewall Rules) 沒開,或是被 Linux 內部的 `ufw` / `iptables` 擋住了。 --- >[!Note] **實務演練#7: 網路連線檢測** > > :::warning > **情境說明**: > 你剛接手一台全新的伺服器,老闆要求你在上面架設 Web 服務並確保對外連線正常。目前狀況不妙,你不知道 IP 是多少、不知道網路通不通,甚至連 Web Server (Nginx) 都還沒安裝😭。你的任務是執行一套完整的 **「部署與健檢流程」**:確認身分 -> 測試外網 -> 安裝服務 -> 檢查監聽 -> 驗收連線。 > ::: > > 請依序完成以下 5 個關卡: > > #### 關卡 1:確認身分 (Identify) > 1. 執行 `ip addr`。 > 2. **觀察**:找到非 `lo` 的網卡(通常是 `eth0` 或 `ens` 開頭)。 > 3. 確認該網卡有顯示 `inet` 後面的 IP 位址 (例如 `10.x.x.x` 或 `172.x.x.x`)。 > > #### 關卡 2:外網連通 (Connectivity) > 在安裝軟體前,必須確定這台機器能連到網際網路。 > 1. 執行 `ping -c 3 google.com`。 > 2. **觀察**:確認顯示 `0% packet loss` 且有回應時間 (time=xx ms)。若這裡失敗,後面的安裝一定會失敗。 > > #### 關卡 3:部署服務 (Deployment) > 因為是全新環境,我們需要先安裝 Nginx。 > 1. 更新軟體庫:`sudo apt update`。 > 2. 安裝 Web Server:`sudo apt install -y nginx`。 > 3. 啟動服務:`sudo service nginx start`。 > > #### 關卡 4:監聽檢測 (Audit Ports) > 我們要確認 Nginx 是否真的有在監聽 Port 80 ,而沒有安裝失敗。 > 1. 執行 `sudo ss -tulnp | grep nginx`。 > 2. **觀察**:你應該看到類似 `tcp LISTEN 0 511 0.0.0.0:80 ... users:(("nginx",pid=...))` 的資訊。 > 3. **解讀**:這代表 Nginx 正在 `0.0.0.0` (所有介面) 的 Port `80` 上監聽 TCP 連線。 > > #### 關卡 5:自我驗收 (Localhost Test) > 最後,用 `curl` 模擬瀏覽器,驗證網頁內容。 > 1. 執行 `curl http://127.0.0.1`。 > 2. **觀察**:你應該會看到 Nginx 的歡迎 HTML 代碼 (`<title>Welcome to nginx!</title>`)。最後,執行 `curl -I http://127.0.0.1`,確認第一行顯示 `HTTP/1.1 200 OK`。 --- :::success ### 💡 實戰演練解答 #### 關卡 1 & 2 解答:基礎檢查 ```bash # 1. 查 IP ip addr # 2. 測外網 (限制 3 次) ping -c 3 google.com ``` #### 關卡 3 解答:部署 Nginx ```bash # 1. 更新並安裝 sudo apt update sudo apt install -y nginx # 2. 啟動 nginx sudo service nginx start ``` #### 關卡 4 & 5 解答:驗收服務 ```bash # 1. 查 Port (需 sudo 才能看到進程名稱) sudo ss -tulnp | grep nginx # 預期輸出包含: 0.0.0.0:80 # 2. 測試網頁內容 curl http://127.0.0.1 # 3. 測試 HTTP 狀態碼 curl -I http://127.0.0.1 # 預期輸出: HTTP/1.1 200 OK ``` ::: ### 核心觀念複習 1. **為什麼 `ss` 比 `netstat` 好?** * 在高流量的伺服器上,連線數可能高達數萬條。舊的 `netstat` 會讀取 `/proc` 檔案系統,速度很慢;`ss` 直接跟核心溝通,速度極快。 2. **`0.0.0.0` vs `127.0.0.1` 的巨大差異**: * 在 `ss` 輸出中,`0.0.0.0:80` 代表允許**任何人**從外部連進來。 * 如果顯示 `127.0.0.1:80`,代表只允許**本機自己**連線,外面的人連不進來(這是很多資料庫預設的安全設定)。 3. **Ping 不通不代表壞掉**: * 很多企業防火牆會設定「拒絕 ICMP (Ping) 封包」,但允許 HTTP (Web) 通過。所以 Ping 只是參考,`curl` 或 `telnet` 測 Port 才是最準的。