---
# System prepended metadata

title: FHS 上課檔案

---

# FHS 上課檔案
[TOC]


## 什麼是 FHS
- FHS 全名：Filesystem Hierarchy Standard（檔案系統階層標準）
    - ex: windows 系統中的 C、D、E槽
    - ex: OS 系統中的目錄架構
- 定義：定義 Linux 系統中，所有目錄及子目錄架構及目錄內容
- 目的：讓使用者瞭解已安裝的軟體通常是放在哪個目錄下

::: info
### FHS 出現的契機
- 越來越多人、企業利用 Linux 系統開發應用程式
    - 每個人對於配置目錄及文件想法不同 
        - => 很難管理  :-1: 
    - 制定一個標準方便管理 :+1: 
:::
## FHS 架構
![](https://hackmd.io/_uploads/HkB2xSJS2.png)
> photo from: [照片來源](https://hackmd.io/@ncnu-opensource/book/https%3A%2F%2Fhackmd.io%2FPubDEY-tSKuAsszd1xiK1w%3Fview)
- FHS 的結構為一層一層的，像樹一樣（Tree）
- FHS 萬物皆檔案
    - 在 Linux 系統中，一切皆檔案
    - 硬體、軟體、文件...

## `/` Root
-  `/` = root(根目錄)
- Linux系統中最重要的目錄，是所有目錄的根源
- 是整個電腦系統的根本
- ![](https://hackmd.io/_uploads/HyZ9tLFJp.png)
    - 比喻成樹木的話，即為所有分支的源頭
    - 開機、還原、系統修復等動作皆與根目錄有關
- 具備修復、系統的重要資料
:::info
- `cd` = Change Directory
    - 切換目錄
- `ls` = 列出目前目錄的檔案及目錄列表
    - `-l`: 顯示詳細資訊
        - ![](https://hackmd.io/_uploads/HyXz38t1a.png)
        - ![](https://hackmd.io/_uploads/H1LpYnzep.jpg)
            - 白色：檔案類型
            - 紅色：檔案權限
            - 橘色：連結數
            - 黃色：檔案擁有者
            - 綠色：檔案所在群組
            - 藍色：檔案大小
            - 桃紅色：最後修改日期
            - 紫色：目錄或檔案名稱
    - `-a`: 可以顯示所有檔案（顯示隱藏的檔案與目錄）
    - `-F`: 顯示檔案類型
    - `-r`: 以反向排序列出檔案
    - `-R`: 列出目錄下所有檔案，包含目錄下的資料夾內的所有檔案
    - `-t`: 依照檔案建立時間列出
    - `-S`: 依照檔案大小排序
:::

### `/root`
- 放置系統管理者的家目錄
    - 系統中的神
    - 可使用救援模式（root)

:::info
#### 什麼是 super user
- 整個Linux作業系統中，最高權限的使用者
    - root
    - 權限很高不建議直接使用 root，下錯指令就 gg 
- 當我們需要使用較高權限怎麼辦？
    - `sudo` : 可以用來取得 root 權限
:::

### `/home`
- `/home`
![](https://hackmd.io/_uploads/rJM4ZHyBn.png)
- 系統預設的使用者家目錄
    - 新增一個一般使用者帳號時，此使用者的家目錄應該會此目錄底下

:::info
- 代號：
    - `~` 目前使用者的家目錄
    - `~` <使用者名稱>` 此使用者的家目錄
:::

## 根目錄下的子目錄
### `/bin` Binary
- `/bin`  = binary
- 放一些一般使用者可以操作的[基礎指令](https://refspecs.linuxfoundation.org/FHS_3.0/fhs/ch03s04.html)
  ![](https://hackmd.io/_uploads/H1m0lHyr2.png)
- `/bin` 底下的指令可以被 root 與一般帳號所使用
    - e.g. `cat`, `mkdir` 等指令
:::info
- `cat`: 將檔案內容印出
- `mkdir`: 建立目錄
:::
### `/sbin` Super user Binaries
- `sbin` Super user Binaries 
- 放置一些[超級使用者權限才能使用的指](https://refspecs.linuxfoundation.org/FHS_3.0/fhs/ch03s16.html)，以及一些一般使用者可以使用的指令
    - 包括開機、修復、還原系統所需要的指令
    - 與系統管理有關的指令
    - e.g. `shutdown`, `update`, `ifconfig`
:::success
#### ifconfig
- 安裝
    ```bash=
    sudo apt install net-tools
    ```
- 輸入 `ifconfig` 查看目前啟用的網路介面
    - ![](https://hackmd.io/_uploads/SycnTKtkT.png)
- 關閉網路介面卡
    - 網卡關掉就不能上網
    - ❗要記得網卡名稱，不然關上就打不開了❗
    ```bash=
    ifconfig <網卡名稱> down
    ```
- 開啟網路介面卡
    ```bash=
    ifconfig <網卡名稱> up
    ```
- 查看所有網卡
    ```bash=
    ifconfig -a
    ```
- 查看指定網卡：
    ```bash==
    ifconfig <網卡名稱>
    ```
:::

### `/lib`
- `/lib`= Library
![](https://hackmd.io/_uploads/S13EWr1rh.png)
- 系統函式庫和核心函式庫
    - ex：開機時使用的函式庫， 
    - `/bin` 或 `/sbin` 底下指令會呼叫的函式庫
:::info
#### 什麼是函示庫？
- 程式的圖書館
- 就像是一群已經寫好的 Function 包起來變成一個 Library，當我要使用這個 Function 時，我們只需要 import 包含這個 Funtion 的 Library。
- 例子：如果我們要做高登食譜裡的糖醋排骨，我們只需要在高登食譜中的目錄中去目錄中尋找糖醋排骨，在根據裡面的食材和步驟做糖醋排骨。
    - 目錄就等於 `lib`，食材及步驟等於 Function

#### 什麼是 binary？
- binary file = 二進位檔案
- 電腦檔案分為 binary file 和 ASCII（純文字檔案）
- 二進位檔是將資料以二進位的格式儲存，例如影像檔或執行檔
    - 一般文書處理軟體並不能處理二進位檔，如果以記事本開啟二進位檔，只會出現一堆亂碼
- 64 or 32 lib
    - lib64，支援 64 位元的函式庫
    - lib32，支援 32 位元的函式庫
- 查看你是 64 bit 還是 32 bit
    ```bash=
    uname -a
    ```
:::


### `/etc`
:::success
#### vim
- 安裝
  ```bash=
  sudo apt-get install vim
  ```
- 編輯相關指令
    - i: 進入編輯模式
    - esc：離開編輯模式
- 儲存、離開等指令
    - `:w`：存檔
    - `:q`：離開 vim
    - `:!`：強制執行
- [其他 vim 相關指令連接](https://linux.vbird.org/linux_basic/centos7/0310vi.php)
- [成大資工Wiki](http://wiki.csie.ncku.edu.tw/vim/vimrc#%E4%BB%8B%E9%9D%A2%E5%84%AA%E5%8C%96)
:::
- `/etc`
- 放置系統主要的設定檔案
    - 帳號密碼、系統的主要設定、各種服務的啟動檔
    - 通常一般使用者可以查看此目錄中的檔案，但只有 root 可以修改
 ![](https://hackmd.io/_uploads/B1EuyW1ep.png) 

- `/etc/passwd`：使用者資訊，一般使用者就可以查看
   ![](https://hackmd.io/_uploads/HyDR1Wke6.png)
    - 使用者名稱
    - 密碼欄位
        - 為什麼顯示的是 `X`
            - 不安全`
    - 使用者 ID 號碼 (UID)
        | UID 範圍         | ID 使用者特性  |
        | ---------------- | -------------- |
        | 0                | 系統管理員     |
        | 1 ~ 999          | 預留給系統使用 |
        | 1000 ~ 4294967295 | 一般使用者     |
    - 使用者的群組 ID 號碼 (GID)
    - 使用者名稱
    - 使用者家目錄
    - 登入後使用的 shell 的路徑
        - 不能亂刪
:::success
### Demo 修改使用者家目錄
:::


- `/etc/shadow`：真正放置使用者密碼的地方，原理是將 `/etc/passwd` 的檔案加密移至 `/etc/shadow` ，且只有 root 可以查看，防止破譯
    - 使用者名稱
    - 密碼：已被編碼（雜湊）處理（不可逆）
        | 符號        | 符號意義 / 雜湊方法 |
        | ----------- | ------------------- |
        | !           | 被禁用              |
        | *           | 不能登入            |
        | `$1$`         | MD5                 |
        | `$2a$` / `$2y$` | Blowfish            |
        | `$5$`        | SHA-256             |
        | `$6$`         | SHA-512             |
    - 上次密碼變更日期
    - 密碼最短使用期限
        - 變更密碼之後，如果還要更改密碼，必須等的時間，單位為天
            - 若此欄位為空白或 0，表示停用此功能，隨時可更改。
    - 密碼最長使用期限
        - 一組密碼最久可以使用的時間，然後就要更改密碼，單位為天
            - 密碼過期後，仍可以使用，但在下次登入時，系統會要求使用者立即變更密碼
            - 若此欄位是空的，則代表停用此功能
            - 若此欄位為 99999 表示密碼不需要重新設定
    :::info
    - 若密碼最長使用期限的值小於密碼最短使用期限，則此使用者就會不能更改自己的密碼
        - 使用者 123
            - 密碼最短使用期限: 100
            - 密碼最長使用期限: 10
    :::
    - 密碼需要變更前的警告
        - 上例 7 表示 7 天內系統會警告帳號
            - 密碼過期前多久，系統會對使用者發出警告，單位為天
            - 若此欄位為空白或 0，表示停用此功能
    - 密碼過期的放寬時間
        - 當密碼過期後，使用者還有多久的時間可以登入更改密碼，單位為天
        - 如果此欄位是空的則代表關閉此功能
    - 帳號過期日期
        - 從 1970 年 1 月 1 日算起的天數
        - 如果此欄位是空的則代表關閉此功能

- `/etc/group`：放置關於系統管理員對使用者和使用者群組管理文件
    - 群組名稱：不可重複
    - 群組密碼：通常不需要設定（空白或 x）
    - 群組 ID (GID)
    - 支援的帳號名稱
### `/boot` 
- `/boot`= bootstrap
![](https://hackmd.io/_uploads/BkJ1Zr1Bh.png)	
- 放置系統開機時會使用的相關載入檔
    - 包括 Linux 核心檔案以及開機選單與開機所需設定檔
- `initrd.img`
    - Initial ramdisk
    - 在啟動階段會被 Linux 呼叫
    - 縮短開機時間
    - 暫時的 root file system，用於全新安裝，crash急救，網路開機等時候
        - 需要在掛載檔案系統前準備好，但還沒有工具
- `/etc/grub`
    - 開機管理模式
    - 支援多個作業系統啟動
    - ![](https://hackmd.io/_uploads/r1IxmpGlp.png)
        > [照片來源](https://www.google.com/url?sa=i&url=https%3A%2F%2Fwww.fosslinux.com%2F115040%2Fa-complete-guide-to-installing-grub-bootloader-on-linux.htm&psig=AOvVaw20FScA40KSVLd3udLGZkpD&ust=1695978468270000&source=images&cd=vfe&opi=89978449&ved=0CBEQjRxqFwoTCKj9gKP6zIEDFQAAAAAdAAAAABAg)

### `/dev` 
- `/dev`= device
![](https://hackmd.io/_uploads/SJ21ZHJSn.png)
- 任何硬體裝置與周邊設備的相關資料，都以檔案型態儲存在`/dev`中
    - 在 Linux 中，**所有東西都以檔案存在**
    - ex：鍵盤、滑鼠等
- `/dev/input`
    - 放置外接式設備資訊的目錄
    - 滑鼠
- `/dev/null`：空裝置
    - 一個特殊的裝置檔案
        - 丟棄一切寫入其中的數據
    - 被稱為黑洞
    - 小測試
    ```bash=
    cat <檔案名稱> > /dev/null
    ```
:::info
#### Bash 環境中的資料流導向
- 標準輸入 (stdin)
    - 代碼: 0
    - `<`
    - `<<`
- 標準輸出 (stdout)
    - 代碼: 1
    - `>`: 覆蓋
    - `>>`: 累加
- 標準錯誤輸出 (stderr)
    - 代碼: 2
    - `2>`: 覆蓋
    - `2>>`: 累加
<!-- - 其他
    - `|`: pipelines, 把前一個指令的輸出當下一個指令的輸入
    ```bash=
    ls -al /dev | grep null
    ```
    - `&`: 背景執行
    - `$`:  -->
:::

### `/mnt`
![](https://hackmd.io/_uploads/BJd8bBJSn.png)
- 為管理員、使用者**手動**掛上（mount）的目錄
    - 暫時掛載某些**額外**的裝置
    - 與 `/media` 不同的是，`/mnt` 需要系統管理員手動掛載至目錄
        - 以前只有 `/mnt` 沒有 `/media`
        - `/mnt` 掛載不會顯示在 nautilus left panel
:::info
#### 什麼是掛載
- 由作業系統使一個儲存裝置（諸如硬碟、CD-ROM或共享資源）上的電腦檔案和目錄可供使用者通過電腦的檔案系統訪問的一個過程
- 將裝置的檔案（萬物皆檔案）放在系統的某個位置使他們連接
    - ex: 在本機安裝一台光碟機，這台光碟機就會掛載在 `/dev` 裡面，光碟機的檔案會自動放在 `/media` 中
:::

### `/media`
![](https://hackmd.io/_uploads/SyiHZrkBn.png)
- 放置可以移除的自動裝置掛載目錄
    - ex：軟碟、光碟、DVD
    - 但並非所有 Linux 都會自動掛載（Ubuntu 會）
:::info
#### 怎麼區分 `/dev`、`/mnt`、`/media`
| 目錄 | 目錄內容 |例如在 Ubuntu 上接 USB|
| -------- | -------- | -------- | 
| `/dev` | 放置各種硬體設備檔案 | 只要 USB 成功連接上了電腦，`/dev` 下就會顯示 USB 的設備檔 |
| `/media` | 放置可移除的裝置**自動掛載**的目錄 | **系統**會自動將 USB 中的檔案掛載到 `/media` |
| `/mnt` | 放置臨時**手動**掛載的目錄 | **系統管理員**可以手動將 USB 中的檔案手動掛載至 `/mnt` |
- 如果系統管理員沒有特別將 USB 中的檔案手動掛載至 `/mnt`，則 `/mnt` 不會顯示 USB 中的檔案 !
:::
### `/opt`
- 放置第三方軟體的目錄
    - 怕這個檔案汙染系統的話，可以把雜七雜八的東西放在這裡
    - ex：chrome
:::info
### 什麼是第三方軟體？
- 額外安裝到 Linux 中的軟體
- 透過非 `apt install` 指令安裝的，都安裝至 `/opt`
    - ex: dpkg
#### apt v.s. dpkg
- 方便軟體的安裝、更新及移除的工具
- dpkg = Debian Packager 
    - 基礎工具
    - 可以直接透過 .deb檔案將套件安裝至系統上
    - 只能處理單一檔案
    - `dpkg -i <package.deb>`
- apt = Advanced Packaging Tools
    - 高級工具
    - 將dpkg再包一層的套件管理系統
    - 同時會下載和安裝相關的軟體及套件
:::
:::success
### 小實作
- 安裝第三方軟體: Chrome
    - 下載安裝檔

    ```bash=
    wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb
    ```
    - 安裝
    ```bash=
    sudo dpkg -i google-chrome-stable_current_amd64.deb
    ```
- 如果是 M1 的同學請用以下方法

    ```bash=
    sudo apt install chromium-browser
    ```
    
:::



### `/srv`
- srv = service
- 放置一些 Ubuntu 規定的網路服務啟動後所需取用的資料目錄
![](https://hackmd.io/_uploads/rkTvWrJrh.png)
    - ex：`/srv/ftp`
### `/tmp`
- 放置暫存檔案 (雜七雜八的東西)
![](https://hackmd.io/_uploads/Hkd_ZHJBn.png)
    - 不適合放重要資料，因開機時通常 `tmp` 的資料會刪除
    - 任何人都能夠存取
        - 容易被放病毒
        - 解決方法：提高權限
            - `/tmp` 的權限是 777
            - 777：所有使用者與群組的權限可讀可寫可執行
            - 因為 /tmp 是讓所有使用者暫存檔案的地方，所以要可讀可寫
### `/run`
- 放置系統開機後在運作後所產生的資訊
    - 不建議放重要檔案
    - 放置臨時檔案的目錄
    - ![](https://hackmd.io/_uploads/BkxY-SJr3.png)
    - ex: .pid
        - 內容只有一行，紀錄目前的 process 的 id 是多少 (pid)
        - 防止同個 service 同時啟動多個副本
        - 會導致這些副本互相搶資源
        - 啟動服務前會先檢查有沒有 .pid
            - 有，就停止啟動服務
            - 沒有，就啟動服務，然後把此服務的 pid 存進 `<service> .pid`
            - 其它同一個 service 的多餘 process 則自動退出
            - 當關閉服務時，`<service>.pid `也會跟著被刪除 (kill)

### `/usr` 及其子目錄
- `/usr`： Ｕnix software resource 縮寫
- 放置 Unix 作業系統軟體資源，相關軟體、服務等，非使用者資料
- 跟系統核心運作無關的一些可有可無的檔案
![](https://hackmd.io/_uploads/H1qtZByHn.png)
- 安裝時此目錄會佔用最多磁碟容量
#### `/usr/bin`
- 放置一般使用者能夠使用的指令
- 使用者安裝的程式的指令會在這裡
    - 此目錄下不能再有子目錄
#### `/usr/sbin`
- 非系統平時運作所需要的指令
- 通常給超級使用者使用
#### `/usr/lib`
- 額外安裝的函示庫存放在此
    - ex: python 的函式庫
:::info
#### 合併
- 2021 Feb 將以下目錄合併
    - `/bin` 和 `/usr/bin` 
    - `/sbin` 和 `/usr/sbin` 
    - `/lib` 和 `/usr/lib` 
- 現在是都一樣的功能
:::
:::warning
#### 為什麼需要有 `/usr/bin` ?
- 合併前 `/usr` 意思非 Unix software resource，而是 user
    - 原始目錄目的：在一開始開發的時候，使用的是 1.5 MB 的 disks，後來當這個硬碟滿了後，才創建 `/usr` 目錄
    - `/bin` 放置的是系統必備的二進位檔案，且需要在 `/usr/bin` 安裝前就可以使用
    - `/usr/bin` 放置的檔案包含系統核心操作的非必備檔案，像是一些應用軟體工具的執行黨
        - ex：c++、gcc
:::

:::info
#### 差異


| 目錄 1 | 功能 | 目錄 2 | 功能 |
| ------ | ---- | ------ | ---- |
|   `/bin`     |   單用戶模式時，系統啟動或修復時所需的執行檔案。   |  `/usr/bin`      |   普通用戶使用且不需要啟動的檔案   |
| `/sbin`       | 只有 super user 可執行且系統必備的檔案，非一般使者執行的檔案。     | `/usr/sbin`       |只有super user 可執行但非系統平時運作所需要的指令      |
| `/lib`   | `/bin` 或 `/sbin` 函式庫，主要是系統運行所需的函式庫     | `/usr/lib`   |`/usr/bin` 和 `/usr/sbin` 的函式庫，多為系統的普通使用的函式庫  |

:::

#### `/usr/local`
- 放置管理員自行安裝的軟體（非系統預設提供的），方便管理
![](https://i.imgur.com/IJXOk6Z.png)
    -  此目錄下也有 `/bin` 、`/etc` 、`/include` 、`/lib` 等目錄
- 軟體升級新版系統或新發行版時，可以安裝在這
    - 為避免影響原系統中的軟體
    - 無須重新安裝全部程式
    - 可以與原先系統提供軟體版本做區分
:::info
#### `/usr/local/bin`、`/usr/local/sbin` 及 `/usr/local/lib` 
- `/usr/local` 放置的是 使用者自己安裝的應用程式相關檔案，非操作系統本身的檔案
- 下載應用軟體或編譯原先軟體的檔案後，編輯後的 `./configure` 系統通常會預設 `prefix` 至 `/usr/local` 
    - `./configure --prefix/usr/bin/`
    - `/usr/local/bin` 儲存以上軟體的一般使用者執行檔案
    - `/usr/local/sbin` 儲存以上軟體的超級使用者才能執行的檔案
    - `/usr/local/lib` 放置`/usr/local/bin` 跟`/usr/local/sbin` 的函式庫

> 跟 /opt 差異：
> /opt 裝得是一些系統使用者自行安裝的較混雜的軟體
:::
:::info
#### 什麼是 prefix ?
- prefix = 配置安裝路徑
    - 避免雜亂
    - 容易刪除或複製
    - 可以與其他原先檔案做區隔，較不會污染其他目錄
- 可以使用 prefix 指定：`./configure --prefix=/usr/lcoal/test`
    - 相關的檔案就會都放在 `/usr/lcoal/test` 

:::


### `/var` 及其子目錄
- `/var` = variable
- 記載著各種系統上的變數的地方，針對常態性變動的檔案
    - 系統開始運行後，會漸漸開始佔用硬碟容量
    - 快取 (cache)、紀錄檔 (log file) 以及某些軟體運作所產生的檔案
- 適合存放需要頻繁改寫的檔案
    - ex: mysql 的檔案
#### `/var/cache`
- 放置程式本身運作過程中會產生的一些暫存檔
    - `/var/cache/apt`：放置apt 命令安裝的 package
        - 下載過程時會先儲存在 `/var/cache/apt/archives/partial` 中
        - 下載完畢後，會被轉移至 `/var/cache/apt/archives` 目錄中
    - 如果需要重新下載應用程式，系統會在此目錄中尋找並獲取暫存黨，不需要重新安裝，節省安裝時間

#### `/var/lib`
- 放置程式運作過程中需要使用到的資料檔案
- ex：MySQL 的 data base 跟 table 通常都會存在 /var/lib
:::info
#### About `/var/lib`
- `/var/lib` and `/usr/lib` have a similar purpose.
- Cause `/var` is variable so the directory in `/var/lib` is writable.
- The `/usr` directory which is often required to be read-only.
- ex: 如果我使用 MySQL，我的 MySQL 函式庫檔案會放在 `/usr/lib`，但我需要寫入 MySQL 的資料庫會放在 `/var/lib`，且資料庫內容會因為寫入而一直變更
:::
#### `/var/lock`
- 放置被上鎖的檔案
    - 當一個檔案正在使用時一次只能被一個應用程式使用時，因此當檔案被使用時，需將檔案上所防止他人使用。
    - 避免兩個檔案同時運作是發生問題
    - 目前此目錄也已被挪到/run/lock 中！
#### `/var/log`
- 放置登入檔案的目錄
    - 非常重要，因此目錄紀錄了系統的重要訊息及錯誤訊息等，如果沒有紀錄的話可能會不知道有問題，也無法進一步解決問題
    - `/var/log/syslog`：紀錄系統登入資訊記錄及Kernel錯誤或警示資訊記錄等等
        - 設定檔案在`/etc/syslog.conf` or `/etc/rsyslog.conf`
    - `/var/log/boot.log` or `/var/log/bootstrap.log`：記錄系統開機或者服務啟動時，顯示的啟動或關閉訊息
    - `/var/log/mail.log`：紀錄郵件的往來資訊
    - `/var/log/wtmp` : 記錄登入者的相關資訊
    - `var/log/btmp` : 紀錄登入失敗的資訊
#### `/var/mail`
- 放置個人郵箱信件的目錄
    - 目前這個目錄也被放置到 /var/spool/mail/目錄中
#### `/var/spool`
- 放置佇列資料
    - 佇列資料 : 排隊等待其他程式使用的資料
        - ex: 要列印東西
    - 使用後的資料通常會被刪除
## 沒在 FHS 但重要的目錄
### `/lost+found`
- 如果系統檔案發生錯誤，會將遺漏的訊息放置到此目錄
- 通常此目錄為空白的
    - ext2/3/4 有此目錄
    - reiserfs、tmpfs 沒有此目錄
### `/proc` 
- `/proc` = process：放置系統中處理程序及執行緒的相關狀態資訊
    - 目錄本身是一個虛擬檔案系統(virtual filesystem)
        - 目錄中放置的資料是在記憶體中，因此不佔硬體空間
        - 使用 `ls -l`查看大小為 0
    - 檔案可讀可寫
    - ex: 系統核心、process 資訊、周邊裝置的狀態、網路狀態等等
    - `/proc/cpuinfo`：紀錄 cpu 相關資訊
    - `/proc/interrupts`：紀錄系統中產生的中斷的詳細信息

### `/sys` 
- `/sys` = sysytem
- 記錄 kernel (核心) 與系統硬體相關的資訊
    - ex: 已載入的核心模組、核心偵測到的硬體設備資訊
- 與 `/proc` 相似，同樣為虛擬檔案系統，不佔硬體空間
    - 可以說是新的 `/proc`
    - `/sys/devices`：紀錄系統設備，並按照設備類型分類


# 基本指令

[TOC]

:::success
:bulb: 善用 **tab**、**上下鍵**
:::

## 與檔案、路徑相關
- pwd : print working directory, 現在在哪個路徑
    - `-P`: 印出此目錄所連結的實體目錄位置
- ls [path] : list
    - `-a`: 全部檔案,包含開頭為 `.` 的隱藏檔案
    - `-A`: 包含隱藏的全部檔案,但不包含 `.` `..` 這兩個目錄
    - `-l`: 列出所有屬性與權限等等資料
    - `-d <DIR>`: 印出指定目錄資料
    - `-r`: 以反向排序列出檔案
    - `-R`: 列出目錄下所有檔案，包含目錄下的資料夾內的所有檔案
    - `-t`: 依照檔案建立時間列出
    - `-S`: 依照檔案大小排序
    - `-c`,`-u` : 查看特定的檔案變動時間
        - Modification Time (mtime)
            - 預設顯示
            - 檔案內容最後的變更時間
        - Status Time (ctime)
            - -c
            - 檔案狀態最後的變更時間
            - e.g. 權限, 屬性
        - Access Time (atime)
            - -u
            - 檔案被讀取的最後時間
    - 各欄位意義
        - 檔案類型
        ![](https://hackmd.io/_uploads/B11AQSyS3.png)
            - `-` : 一般檔案,白色字體；綠色為可執行檔案
            - d : 目錄,藍色字體
            - l : 連結檔案,淺藍色字體
            - p : 有用 `|` (pipe) 的檔案
            - b : 存取硬體設備的檔案 (暫存再寫入),黃色字體
            - c : 存取硬體設備的檔案 (立即),黃色字體
            - s : socket 檔案,粉紅色字體
        - 權限
        ![](https://hackmd.io/_uploads/H1Ea7HkSh.png)
            - 共三組 rwx , 分別代表 owner, group, other user 的權限
            - r : Read
            - w : Write
            - x : eXecute
        - counter 數: 在同個 filesystem 裡任何地方指到這個目錄的集合
        ![](https://hackmd.io/_uploads/BJjnmrkrh.png)
        ![](https://hackmd.io/_uploads/H11y1NRZT.png)
        - 擁有者
        ![](https://hackmd.io/_uploads/rke3XSySh.png)
        - 群組
        ![](https://hackmd.io/_uploads/r1wimrJSn.png)
        - 檔案大小 (byte)
        ![](https://hackmd.io/_uploads/Hk297ryBh.png)
        - mtime
        ![](https://hackmd.io/_uploads/BkXqmr1rn.png)
- `cd`: change directory, 變換目錄
    - cd [相對路徑]
    - cd [絕對路徑]
    - cd [特殊目錄]
        - `.` : 當前目錄
        - `..` : 上一層目錄
        - `-` : 前一個工作目錄
        - `~` : 當前 user 的家目錄, 直接下 cd 也可以回家目錄
        - ~<username> : 指定 user 的家目錄
- `clear`: 清空 terminal 畫面
    - 快捷鍵: ctrl+shift+L
- `touch <filename>`: 更新檔案的 m/c/atime
    - 如果檔案不存在會建立空檔案
- `cat <filename>`: concatenate, 檢視指定檔案的內容
    - -b : 印出行號, 空白行不標記
    - -n : 印出行號, 空白行也標記行號
    - -T : 會把 TAB 按鍵用 ^I 顯示出來
- `wc`: 印出行數, 字元數, 位元數
    - `-l`: 印出行數
    - `-w`: 印出字元數
    - `-c`: 印出位元數
- mkdir <DIR_name> : 建立目錄
    - `mkdir -p <DIRpath/DIR_name>`: 如果後面接的路徑不存在, 可以一次建立多層目錄
- rm <filename_or_DIR> : 刪除指定內容
    - -r : recursive, 會把目錄裡的檔案跟目錄刪掉
    - -f : force
    :::danger
    ### 摧毀系統（電腦）的指令
    - **不要隨便使用**
    
bash=
    rm -rf --no-preserve-root /
    

    :::
- `mv`: 移動或更名
    - `mv <source> <destination>`: 移動
    - `mv <file_or_DIR> <new_name>`: 更名
- `cp <source> <destination>`: copy
    - `-a`: 複製檔案全部特性
    - `-p`: 連同檔案的權限、owner、時間一起複製, 常用於備份
    - `-r`: recursive, 複製整個目錄
    - `-s`: 建立檔案的 symbolic link (softlink), 等同 ln -s
    - `-l`: 建立檔案的 hardlink, 等同 ln
- `echo`: 在 terminal 上印出字串或變數
    - `-n`: 不換行
    - echo "print(\"hello world\")" > hello.py
    - echo $PATH
        - 在 bash 先解析變數內容再印出
        - PATH : 由一堆目錄所組成的 []
- `|` : pipeline, 用於串接指令
    - echo "1234" | base64
    - echo "1234" | md5sum

:::info
### 一些符號
- `>`, `>>`
    - 標準輸入 (stdin)
    - 代碼: 0
- `<`, `<<`
    - 標準輸出 (stdout)
    - 代碼: 1
- 2>
    - 標準錯誤輸出 (stderr)
    - 代碼: 2
- `|`: pipelines, 把前一個指令的輸出當下一個指令的輸入
- `$`: 解析變數內容
- `&`: 背景執行
:::

## 與查詢相關
- `man <something_you_want_to_know>`: manual, 查看操作手冊
- `less <filename>`: 查看檔案內容
    - 空白鍵: 下一頁
    - `b`: 上一頁
    - Enter: 下一行
    - `q`: 離開
    - `/string`: 搜尋指定字串
- `head <filename>`: 擷取檔案前幾行, 預設顯示前 10 行
    - `-n`: 指定顯示的行數
- `tail`: 擷取檔案後幾行, 預設顯示後 10 行
    - `-n`: 指定顯示的行數
- grep "keywords" : 從輸出中找指定的關鍵字
    - `-i`: 不分大小寫搜尋
    - `"^keywords"`: 以 keyword 開頭搜尋
- `whereis <filename_or_DIR>`: 由一些特定的目錄中尋找檔案檔名
    - -l : 可以列出 whereis 會去查詢的幾個主要目錄
    - -b : 只找 binary 格式的檔案
    - -m : 只找在說明檔 manual 路徑下的檔案
    - -s : 只找 source 來源檔案
    - -u : 搜尋不在上述三個項目當中的其他特殊檔案
- which <欲尋找的執行檔> : 列出第一筆由 PATH 目錄中找到的結果
    - -a : 將所有找到的指令均列出

<!-- ## 跟環境變數有關
- `env`: environment, 列出現在的 shell 的所有環境變數跟內容
- `export`:
- `locale`: 語系變數
    - LC_TIME="en_US" ls -al -->

## 與連結相關
- ln <source> <destination> : 建立一個檔案的 hardlink
    - `-s`: 建立 symbolic link (softlink)
    :::info
    ### 硬連結 vs 軟連結
    - Hardlink
        - 幫檔案建立一個「別名」, 但其實是同一個檔案
        - 柯P就是柯文哲, 柯文哲就是柯P, 只是有兩個名字
    - Symbolic Link （softlink）
        - 一個獨立的特殊檔案, 內容是儲存「路徑」
        - e.g. 路牌指向學校大門, 路牌是路牌, 只是表示大門的位置在哪裡
    :::
    :::success
    ### DEMO
    - 觀察 counter
    - 觀察檔案類型
    - 觀察刪除 source 後的 soft & hard link
    :::
## 與使用者相關
- `sudo <command>`: super user do, 輸入使用者的密碼用 root 的身分執行指令
:::danger
- `su`: 輸入 root 的密碼改變身分
    - **不要**用 su 登入 root 管理主機
:::
:::info
- `sudo su - <username>`: 切換使用者
    - `-`: 把環境 reset 成目標使用者的環境變數
:::
- `whoami`: 現在是哪個使用者
- `id`: 查看自己的 uid, 所屬群組的 gid
    - sudo id <others_username> : root 查閱其他使用者 UID, GID
    - **系統是透過 uid 辨別使用者**
    - uid 放在 /etc/passwd 第三個欄位
    - 可以下 cat /etc/group | grep <username> 對照是否相同
- `sudo adduser <new_username>`: 創建使用者與他的家目錄
- `sudo deluser <username>`: 刪除使用者
- `exit`: 登出現在的使用者
    :::success
    ### DEMO
    - 修改別人的 uid
    - 在別人的家目錄底下新增檔案, 觀察 owner
    :::
- `last`: 列出使用者登入的資訊 
    - /var/log/wtmp 內容編碼過, 所以用 last 指令查詢
    - `-n <number>`: 指定顯示的列數
<!-- - `lastlog`: 列出每個使用者的登入狀況 FIXME -->
- `w`: 現在有哪些登入的使用者
- passwd : 修改密碼
<!-- - finger : 查詢使用者的相關訊息
    - sudo apt install finger
    - finger <username> -->
<!-- - usermod : 修改使用者資訊
    - sudo usermod -l <new_name> <old_name> ： 修改帳號名稱
    - sudo usermod -s <shell dir> <username> ：修改使用者登入的起始位置
    - sudo usermod -a -G <group_name> <user_name> : 新增群組
        - -G ： 接次要群組, 修改這個使用者能夠支援的群組
        - -a ： 與 -G 合用, 可『增加次要群組的支援』而非『設定』 -->
- groups : 顯示出目前的使用者的所屬群組
    - 第一個群組為有效群組
        - 新增檔案的擁有者為有效群組
    - 其他為支援群組
- sudo groupadd <group_name> : 新增群組
    - -g <num> : 自訂 GID
<!-- - groupmod : 修改與 group 相關資訊
    - groupmod [-g gid] [-n new_name] <group_name>
    - -g : 修改現有群組的 GID, 建議不要隨意更動
    - -n : 修改現有群組的群組名稱 -->
- sudo groupdel <group_name> : 刪除群組
    - 在沒有使用者把這個群組當作 initial group 的情況下才能夠刪除
        - 查看 /etc/passwd 第四個欄位
- gpasswd : 群組管理相關指令
    - 系統管理員 root 可執行的指令
        - `sudo gpasswd <groupname>`: 設定群組密碼
        - sudo gpasswd -A <username> <groupname> : 新增 user 成為群組管理員
        - sudo gpasswd -M <username> <groupname> : 新增 user 進群組
        - sudo gpasswd -r <groupname> : 刪除該群組的密碼
    - 群組管理員可執行的指令
        - gpasswd -a <username> <group_name> : 將指定 user 新增至群組
        - `gpasswd -d <username> <group_name>`: 將指定 user 從群組移除
- `newgrp <group_name>`: 切換有效群組

## 與權限相關
- `chown`: change owner, 改變檔案或目錄的擁有者
    - 要是現有的使用者才可以成功執行 chown
    - chown <user_name> <dirname/filename>
    - chown :<group_name> <dirname/filename>
    - chown <user_name>:<group_name> <dirname/filename>
    - -R : recursive, 可以連同目錄底下的檔案一起變更使用者
- `chgrp <group name> <dirname/filename>`: change group, 改變檔案或目錄的所屬群組
    - -r : recursive, 常用於目錄變動
    - 要是現有的群組才可以成功執行 chgrp
- `chmod <???> <file_or_dir>`: 改變使用者權限
    - `-R`: recursive
    - 數字類型
        - ![](https://hackmd.io/_uploads/rJLUmHyr3.png)
        - chmod 755 <filename/dir_name> : owner 可讀可寫可執行, 其他使用者可讀可執行
        - Q:`-rw-r--r--` 權限怎麼改?
    - 符號類型
        - chmod <人 動作 權限設定,...> <file_or_dir>
            - 人: u, g, o, a
            - 動作: +(加入), -(除去), =(設定)
            - 權限設定: r, w, x
        - Q:`-rw-rw-r--` 怎麼改成 `-rwxr-xr-x`?
    - 權限的意義
        - 權限之於檔案
            - r : 可讀取檔案內容
            - w : 可編輯檔案內容, 但沒有刪除檔案的權限
            - x : 可以把檔案內容給系統執行
        - 權限之於目錄
            - 目錄是一張記錄檔案名稱的清單
            - r : 可讀取這張清單
            - w : 可編輯這張清單, 等同可以編輯名稱、新增、刪除、移動該目錄底下的檔案或目錄
            - x : 可以 cd 進目錄
                - 所以要開放目錄給大家看的話, 至少要給 r-x 的權限
:::info
### 檔案特殊權限
#### SUID
- Set UID
- 指令設定
    - chmod 4??? <filename>
    - chmod u+s <filename>
- 只能用在二進位檔案
- 在執行程式的當下切換成 owner 的權限
    - 提權或降權
- 舉例1
    ![](https://hackmd.io/_uploads/rJNXuPF-6.png)
    ![](https://hackmd.io/_uploads/SyyhFwY-6.png)
- 舉例2
    :::success
    ### DEMO
    
C=
    #include <stdio.h>
    #include <unistd.h>

    int main() {
        printf("The uid is: %d\n", geteuid());
        return 0;
    }
    

    :::

#### SGID
- Set GID
- 指令設定
    - chmod 2??? <filename>
    - chmod g+s <filename>
- 只能用在二進位檔案
- 讓在群組所屬的目錄底下產生的資料屬於群組, 而非使用者有效群組
- 舉例
    ![](https://hackmd.io/_uploads/SyVDdICZa.png)
    ![](https://hackmd.io/_uploads/S1DF3Ptb6.png)
    
#### SBIT
- Sticky Bit
- 指令設定
    - chmod 1??? <filename>
    - chmod o+t <filename>
- 雖然權限是 777, 但限制只有擁有者跟 root 才能刪除資料 FIXME
- 舉例
    ![](https://hackmd.io/_uploads/BJvE9vtZp.png)
:::
<!-- 
## 與安裝軟體相關
- `sudo apt install <packagename>`: 從 APT 平台中的 package 安裝
- upgrade dis update 
- sudo wget <網址> : 從指定網址下載安裝檔
- sudo dpkg -i <filename.deb> : 安裝 deb 檔 -->

## 與打包、壓縮相關
- 根據檔案的副檔名選擇相對應的指令
- *.gz
    - `gzip <filename>`: 壓縮, 壓縮後檔名為 filename.gz
    - `gzip -d <filename>`: 解壓縮
- *.bz2
    - `bzip2 <filename>`: 壓縮, 壓縮後檔名為 filename.bz2
    - `bzip2 -d <filename>`: 解壓縮
    - `-k`: 保留原始檔案
- *.xz
    - `xz <filename>`: 壓縮, 壓縮後檔名為 filename.xz
    - `xz -d <filename>`: 解壓縮
    - `-k`: 保留原始檔案
- *.tar
    - tar [-z|-j|-J] [c|x] [v]  [-f <filename>] <filename>
        - `-z`: 透過 gzip 的支援壓縮, 檔名建議設為 *.tar.gz
        - `-j`: 透過 bzip2 的支援壓縮, 檔名建議設為 *.tar.bz2
        - `-J`: 透過 xz 的支援壓縮, 檔名建議設為 *.tar.xz
        - `-c`: 建立打包檔案
        - `-x`: 解打包、壓縮
        - `-v`: 列出正在處理的檔案案名稱
        - `-f`: 指定打包、壓縮後的檔案名稱
    - tar -zcvf <destination> <source>
    - tar -zxvf <destination> <source>
- *.zstd
    - sudo apt-get install zstd
    - `zstd <filename>`: 壓縮, 壓縮後檔名為 filename.zst
    - `zstd -d <filename>`: 解壓縮    

## 與 process 相關
- process: 系統執行中的程式
- ps : 列出 process 的資訊
    - ps -aux
    - -A ：所有的 process 都列出, 與 -e 具有同樣的效用
    - -a ：不與 terminal 有關的所有 process
    - -u ：有效使用者 (effective user) 相關的 process
    - -x ：通常與 -a 這個參數一起使用, 可列出較完整資訊
    - 欄位意思
        - USER : process 擁有者
        - PID : process id
        - %CPU : 佔用 CPU 的使用率
        - %MEM : 佔用實體記憶體的比例