Skip to content

Linux

GNU 的 GPL 授權有底下的權力與義務:

  • 取得軟體與原始碼:你可以根據自己的需求來執行這個自由軟體;
  • 複製:你可以自由的複製該軟體;
  • 修改:你可以將取得的原始碼進行程式修改工作,使之適合你的工作;
  • 再發行:你可以將你修改過的程式,再度的自由發行,而不會與原先的撰寫者衝突;
  • 回饋:你應該將你修改過的程式碼回饋於社群!
  • 不可修改授權:你不能將一個GPL授權的自由軟體,在你修改後而將他取消GPL授權~
  • 不可單純販賣:你不能單純的販賣自由軟體。

由於自由軟體使用的英文為 free software,這個 free 在英文是有兩種以上不同的意義,除了自由之外,免費也是這個單字! 因為有這些額外的聯想,因此許多的商業公司對於投入自由軟體方面確實是有些疑慮存在的!許多人對於這個情況總是有些擔心~

為了解決這個困擾,1998 年成立的『開放原始碼促進會 (Open Source Initiative)』提出了開放原始碼 (Open Source,亦可簡稱開源軟體) 這一名詞! 另外,並非軟體可以被讀取原始碼就可以被稱為開源軟體喔!該軟體的授權必須要符合底下的基本需求,才可以算是 open source 的軟體。

  • 公佈原始碼且用戶具有修改權:用戶可以任意的修改與編譯程式碼,這點與自由軟體差異不大;
  • 任意的再散佈:該程式碼全部或部份可以被販售,且程式碼可成為其他軟體的元件之一,作者不該宣稱具有擁有權或收取其他額外費用。
  • 必須允許修改或衍生的作品,且可讓再發佈的軟體使用相似的授權來發表即可。
  • 承上,用戶可使用與原本軟體不同的名稱或編號來散佈。
  • 不可限制某些個人或團體的使用權
  • 不可限制某些領域的應用:例如不可限制不能用於商業行為或者是學術行為等特殊領域等等
  • 不可限制在某些產品當中,亦即程式碼可以應用於多種不同產品中。
  • 不可具有排他條款,例如不可限制本程式碼不能用於教育類的研究中,諸如此類。

kernel

valias用途适用
Mainlinedev开发测试新硬件开发者
Stable平衡功能与稳定性普通用户
LongtermLTS长期支持有更新保障服务器

Linux distributions

Linux Kernel(含tools)與可運行的軟體整合起來, 加上自己具有創意的工具程式,這個工具程式可以讓使用者以光碟/DVD或者透過網路直接安裝/管理Linux系統。

command-line interface

command-line-interface, CLI

Console 控制台

Linux 系统最底层的物理或虚拟输入/输出设备,直接与内核交互。提供最底层的硬件或虚拟接口;如,tty1。

  • Physical Console 物理控制台,直接连接计算机的键盘和显示器(服务器本地终端)
  • Virtual Console 虚拟控制台,Linux 默认提供 tty1~tty6 虚拟控制台,可通过[ctrl] + [alt] + [f1] ~ [f6] 切换

Terminal 终端

提供用户输入和输出的环境,负责与 Shell 交互;如,GNOME Teriminal、SSH。

  • 物理终端,早期终端,如电传打字机(TTY, teletypewrite)
  • 虚拟终端(Terminal Emulator),现代 Linux 中的终端模拟器
  • 伪终端(PTY,Pseudo Terminal),用于远程登录或图形界面中的终端窗口;如,SSH

Shell 外壳

Shell 是一个命令行解释器,负责解析用户输入的命令并调用系统内核执行。

  • bash, Bourne-Again Shell
  • zsh, Z Shell

流程: 用户 → 在 Terminal 中输入命令 → Shell 解析命令 → 内核执行 → 结果返回至 Terminal

sh
# terminal 退出
# [ctrl] + d
$ exit
$ logout


# 环境变量
$ env
$ printenv

# 切换 root
$ su -
$ sudo -i

$ date +'%Y/%m/%d %H:%M:%S'
$ hwclock

# LANG 
$ locale
$ localectl list-locale # show known locales
$ localectl status # show current locale settings
$ localectl set-locale <locale>

# 时区
$ timedatectl status
# 获取可用时区列表
$ timedatectl list-timezones
$ timedatectl set-timezone <timezone>

$ man -f <command>
$ man -k <command>
$ man [n] <command>
# 1: Executable program or shell commands
# 2: System calls (functions provided by the kernel)
# 3: Library calls  (functions within program libraries)
# 4: Sepcial files (usually found in /dev)
# 5: File formats and conventions, e.g. /etc/passwd
# 6: Games
# 7: Miscllaneous (including macro packages and concentions), e.g. man(7), groff(7), man-pages(7)
# 8: System administration commands (usually only for root)
# 9: Kernel routines

$ more
$ less

Filesystem Hierarchy Standard

Filesystem Hierarchy Standard, FHS

根據檔案是否經常變動,以及檔案運作的情況,大致上有幾個比較重要的目錄分類:

  • static (固定的內容):包含不會變動的工具程式、函式庫與說明文件等
  • dynamic / variable (變動的內容):可能會被運作中的程序所修改掉
  • persistent (持續性內容):開機之後會持續存在且大多不會變動的資料,例如一些環境設定資訊
  • runtime (運作中的內容):包含用戶程序或系統程序運作中的資料,這些資料會在重新開機後被刪除
pathdesc
/bin用户指令
/sbin系统管理员指令
/boot开机有关档案
/dev设备档案
/etc配置文档
/home一般账号家目录
/root系统管理员家目录
/lib系統函式庫與核心函式庫,其中 /lib 包含核心驅動程式,而其他軟體的函式庫若為 64 位元,則使用 /lib64 目錄內的函式庫檔案。 這兩個目錄目前也都是連結到 /usr/lib, /usr/lib64 內。
/lib64
/proc將記憶體內的資料做成檔案類型,放置於這個目錄下,連同某些核心參數也能手動調整
/sys跟 /proc 類似,只是比較針對硬體相關的參數方面。
/usr是 usr 不是 user 喔!是 unix software resource 的縮寫,與 Unix 程式有關。從 RHEL 7 開始, 系統相關的所有軟體、服務等,均放置在這個目錄中了!因此不能與根目錄分離。
/var是一些變動資料,系統運作過程中的服務資料、暫存資料、登錄資料等等。
/tmp一些使用者操作過程中會啟用的暫存檔,例如 X 軟體相關的資料等等。
/media主要是系統上臨時掛載使用的裝置(如隨插即用 USB)之慣用目錄
/mnt主要是使用者或管理員自行暫時手動掛載的目錄
/optoptional 的意思,通常是第三方協力廠商所開發的軟體放置處
/run系統進行服務軟體運作管理的功能,RHEL 7以後,這個目錄也放在記憶體當中了!
/srv通常是給各類服務 (service) 放置資料使用的目錄
sh
# display filesystem
$ df

# / 根目录
# ~ 使用者家目录
# . 本目录
# .. 上一层目录
# - 上一次的工作目录

# list
$ ls -alhd

$ flie </path/to/file>

# change directory
$ cd

# print working directory
$ pwd

# copy
$ cp -ar

# make dirctory
$ mkdir

# remove dirctory
$ rmdir

# remove
$ rm

# move, rename
$ mv

# concatenate files and print on the standard output
$ cat
$ head
$ tail
$ less
# /<key> 查询
# [space] 翻页
# [pageup]
# [pagedown]
# g 跳转第一行
# G 跳转最后一行
# q 退出

萬用字元

符號意義
*代表『 0 個到無窮多個』任意字元
?代表『一定有一個』任意字元
[ ]同樣代表『一定有一個在括號內』的字元(非任意字元)。例如 [abcd] 代表『一定有一個字元, 可能是 a, b, c, d 這四個任何一個』
[ - ]若有減號在中括號內時,代表『在編碼順序內的所有字元』。例如 [0-9] 代表 0 到 9 之間的所有數字,因為數字的語系編碼是連續的!
[^ ]若中括號內的第一個字元為指數符號 (^) ,那表示『反向選擇』,例如 [^abc] 代表 一定有一個字元,只要是非 a, b, c 的其他字元就接受的意思。

Vim

命令模式

按键功能
i,a,o,O切换输入模式
[Esc]切换命令模式
:切换命令行模式
x,X删除字符
dd删除行
yy复制行
p粘贴行
r,R替换
u回退
v选取
[shift] + v逐行选取
h
l
j
k
w前进一个词
b退后一个词
g第一行
G最后一行
nG跳转第n行

命令行模式

按键功能
:w保存
:q退出
:q!强制退出
/word向下搜索
?word向上搜索
n重复搜索动作
N反向重复搜索动作
:1,$s/word1/word2/g从第一行到最后一行寻找 word1 字符串,并将该字符串取代为 word2 !
:%s/word1/word2/g从第一行到最后一行寻找 word1 字符串,并将该字符串取代为 word2 !
:1,$s/word1/word2/gc询问替换
:%s/word1/word2/gc询问替换

配置

sh
# 設定搜尋到的關鍵字為高亮度反白
:set hlsearch
# 設定語法檢驗功能
:syntax on
# 取消自動搜尋機制
:set noincsearch
# 搜尋時,忽略大小寫的差異
:set ignorecase
# 設計自動縮排
:set autoindent
# 設定自動產生行號
:set nu
# 設定 tab 的寬度為 8 個字元
:set tabstop=8
# 設定預先顯示的行數為 0,亦即不預先顯示
:set scrolloff=0
# 設定不要折行
:set nowrap
# 設定游標所在行顯示特殊字樣
:set cursorline

档案系统

  • user 拥有者
  • group 群组
  • other 其他人
sh
lrwxrwxrwx 1 root root 7 May  1  2024 /var/spool/mail -> ../mail
[    A   ][B][C ] [D ][E][    F     ] [    G        ]

# A. 檔案類型與權限,第 1 個字元為檔案類型,後續 9 個字元每 3 個一組,共分 3 組,為三種身份的權限;
# B. 檔案連結數,這與檔案系統有關,讀者可暫時略過;
# C. 該檔案的擁有者,本例當中,擁有者身份為 root
# D. 該檔案的所屬群組,本例當中這個檔案屬於 mail 這個群組底下
# E. 這個檔案的容量
# F. 該檔案最後一次被修改/修訂的日期時間
# G. 這個檔案的檔名。

# 檔案類型
# -: 代表後面的檔名為一般檔案
# d: 代表後面的檔名為目錄檔
# l: 代表後面的檔名為連結檔 (有點類似 windows 的捷徑概念)
# b: 代表後面的檔名為一個裝置檔,該裝置主要為區塊裝置,亦即儲存媒體的裝置較多
# c: 代表後面的檔名為一個週邊裝置檔,例如滑鼠、鍵盤等

# 权限对于档案
# r: 可讀的意思, 2^2
# w: 可寫入/編輯/修改的意思(但不含刪除該檔案), 2^1
# x: 可以執行的意思, 2^0

# print user id
$ id

-rw-r--r--. 1 student student 0  Feb 21 22:54 checking
 [ chmod ]    [chown] [chgrp]    [   touch  ] [  mv  ]

# 用户加入群组
$ usermod -aG <group> <user>

$ chmod <u|g|o|a> +[r][w][x] <file>
$ chmod <u|g|o|a> -[r][w][x] <file>
$ chmod <u|g|o|a> =[r][w][x] <file>

# 群组公用
$ chgrp <groupname> <file>
$ chmod g+rwx <file>

# 权限对于目录
# r: 表示具有讀取目錄結構清單的權限
# w: 異動該目錄結構清單的權限,新建/删除/更名/移动
# x: 能否進入該目錄成為工作目錄

特殊权限

SUID

  • SUID 權限僅對二進位程式(binary program)有效;
  • 執行者對於該程式需要具有 x 的可執行權限;
  • 本權限僅在執行該程式的過程中有效 (run-time);
  • 執行者將具有該程式擁有者 (owner) 的權限。
sh
$ ls -l /bin/passwd
-rwsr-xr-x 1 root root 68248 Mar 23  2023 /bin/passwd

# 執行 passwd 這個指令的過程中,身份暫時變成了 root 了!等到 passwd 執行完畢後,就又回復到原本的身份。

SGID

與 SUID 類似的,SGID 為將特殊的權限旗標設定在群組的 x 上。

  • SGID 對二進位程式有用;
  • 程式執行者對於該程式來說,需具備 x 的權限;
  • 執行者在執行的過程中將會獲得該程式群組的支援!

SGID 亦可設定於目錄上。

  • 使用者若對於此目錄具有 r 與 x 的權限時,該使用者能夠進入此目錄;
  • 使用者在此目錄下的有效群組(effective group)將會變成該目錄的群組;
  • 用途:若使用者在此目錄下具有 w 的權限(可以新建檔案),則使用者所建立的新檔案,該新檔案的群組與此目錄的群組相同

SBIT

777 的權限, 代表任何人所建立的任何資料,都可能被隨意的刪除,這就有問題。因此會加上一個 Sticky bit 的特殊權限旗標。

  • 當使用者對於此目錄具有 w, x 權限,亦即具有寫入的權限時;
  • 當使用者在該目錄下建立檔案或目錄時,僅有自己與 root 才有權力刪除該檔案
sh
$ ls -ld /tmp
drwxrwxrwt 11 root root 4096 Jul  3 10:10 /tmp

授权

sh
# SUID: 4
# GUID: 2
# SBIT: 1
$ chmod 4755 /bin/passwd
$ chmod u+s <file>
$ chmod g+s <file>
$ chmod o+t <file>

账号权限

sh
$ useradd <username>
$ passwd <username>
$ userdel -r <username> # -r remoe hone dorectory

# /etc/group
$ groupadd <groupname>
$ groupdel <groupname>


$ usermod -a -G <groupname> <username>
$ usermod -r -G <groupname> <username>
$ groups <username>


# 从标准输入设置密码
$ echo 'password' | passwd --stdin <username>

程序

  • 程式 (program):通常為 binary program ,放置在儲存媒體中 (如硬碟、光碟、軟碟、磁帶等), 為實體檔案的型態存在;
  • 程序 (process):程式被觸發後,執行者的權限與屬性、程式的程式碼與所需資料等都會被載入記憶體中,作業系統並給予這個記憶體內的單元一個識別碼 (PID),可以說,程序就是一個正在運作中的程式。

子程序

程序是有相依性的!舉例來說,su 來切換身份成為 root,此時 su 會給予一個具有 root 權限的 bash 環境,那麼使用者登入的 bash 就被稱為父程序。

sh
# 与自己相关的程序
$ ps -l
F S   UID     PID    PPID  C PRI  NI ADDR SZ WCHAN  TTY          TIME CMD
4 R     0 1206530  832026  0  80   0 -  2804 -      pts/1    00:00:00 ps

# F (flag):代表程序的總結旗標,常見為 4 代表 root 特權程序、0 應為一般程序、1 為複製 (forked) 但未執行 (exec) 的程序。
# S (stat):狀態列,主要的分類項目有:
#     R :(running/runnable/run queue) 正在執行或可執行的程序,或者在可執行佇列中的程序
#     S :(interruptible sleep) 該程式目前正在睡眠狀態,但可以被其他事件喚醒來運作程序
#     D :(uninterruptible sleep) 不可被喚醒的睡眠狀態,通常這支程式可能在等待 I/O 的情況(ex>列印)
#     T :(stop by job control),可能是在工作控制(背景暫停)狀態;
#     t :(stop by debugger),可能是在除錯 (traced) 狀態;
#     Z :(Zombie) 僵屍狀態,程序已經終止但卻無法被移除至記憶體外。
# UID/PID/PPID:代表『此程序被該 UID 所擁有/程序的 PID 號碼/此程序的父程序 PID 號碼』
# C:代表 CPU 使用率,單位為百分比;
# PRI/NI:Priority/Nice 的縮寫,代表此程序被 CPU 所執行的優先順序,數值越小代表該程序越快被 CPU 執行。 不過,不同的輸出格式其計算方法不同,因此,讀者大概只要知道 NI (nice) 值即可。
# ADDR/SZ/WCHAN:都與記憶體有關,ADDR 是 kernel function,指出該程序在記憶體的哪個部分,如果是個 running 的程序,一般就會顯示『 - 』 / SZ 代表此程序用掉多少記憶體(Kbytes) / WCHAN 表示目前程序是否運作中,同樣的, 若為 - 表示正在運作中。
# TTY:登入者的終端機位置,若為遠端登入則使用動態終端介面 (pts/n);
# TIME:使用掉的 CPU 時間,注意,是此程序實際花費 CPU 運作的時間,而不是系統時間;
# CMD:就是 command 的縮寫,造成此程序的觸發程式之指令為何。

# pstree
# 安装
$ apt install psmisc
$ pstree -A
# -u: user
# -p: pid
$ pstree -Aup

# ps
# 安装
$ apt install procps
$ ps aux
USER         PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root           1  0.0  0.1 168312 10884 ?        Ss   Jun09   0:35 /sbin/init

# USER:該 process 屬於那個使用者帳號的?
# PID :該 process 的程序識別碼。
# %CPU:該 process 使用掉的 CPU 資源百分比;
# %MEM:該 process 所佔用的實體記憶體百分比;
# VSZ :該 process 使用掉的虛擬記憶體量 (Kbytes)
# RSS :該 process 佔用的固定的記憶體量 (Kbytes)
# TTY :該 process 是在那個終端機上面運作,若與終端機無關則顯示 ?,另外, tty1-tty6 是本機上面的登入者程序,若為 pts/0 等等的,則表示為由網路連接進主機的程序。
# STAT:該程序目前的狀態,狀態顯示與 ps -l 的 S 旗標相同 (R/S/T/Z)
# START:該 process 被觸發啟動的時間;
# TIME :該 process 實際使用 CPU 運作的時間。
# COMMAND:該程序的實際指令為何?

# 动态观察
$ top
top - 10:28:30 up 22 days, 13:57,  4 users,  load average: 0.37, 0.32, 0.28
Tasks: 173 total,   1 running, 172 sleeping,   0 stopped,   0 zombie
%Cpu(s):  2.1 us,  1.6 sy,  0.0 ni, 94.1 id,  0.2 wa,  0.0 hi,  0.0 si,  0.0 st
MiB Mem :   7850.5 total,    570.0 free,   4486.4 used,   3096.9 buff/cache
MiB Swap:   1953.0 total,   1098.7 free,    854.2 used.   3364.1 avail Mem

    PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND
 185013 libvirt+  20   0 3414.4m   1.0g   6.0m S   5.0  13.3     21,29 qemu-system-x86

# 代表目前時間為 10:28:30,本系統開機了 22 天 13 分鐘這麼久的時間,目前有 4 為用戶登入,工作負載為 0.37, 0.32 及 0.28。 那三個數據代表 1, 5, 15 分鐘內的平均工作負載。所謂的工作負載為『單一時間內,CPU 需要運作幾個工作』之意,並非 CPU 使用率。 如果 CPU 數量有 8 核心,那麼此數據低於 8 是可接受的 (每一個核心全力負責一個工作之意)。

# 目前共有 173 個程序,其中 1 個在執行,172 個睡著了,0 個停止的,沒有殭屍程序。

# CPU 的使用率百分比,比較需要注意 id (idle) 與 wa (I/O wait),id 越高代表系統越閒置, wa 越高代表程序卡在讀寫磁碟或網路等 I/O 上,此時系統效能會比較糟糕。

# 體記憶體 (Mem) 與記憶體置換 (Swap) 的總量,與使用量。需要注意的是,上表中雖然 free 僅有 570.0MiB,但是後續有 3096.9 buff/cache (快取) 的量, 所謂的快取指的是 Linux 會將系統曾經取用的檔案暫存在記憶體,以加速未來存取該檔案的效能 (記憶體的速度比磁碟快了 10 倍以上), 當記憶體不足時,系統就會將快取回收,以保持系統的可用性。右下角那個 avail Mem 指的大致就是 free + buff/cache 的量, 因此,目前可用的記憶體量還有 3364.1MiBytes 這麼多喔!

# PID :每個 process 的識別碼 (PID)
# USER:該 process 所屬的使用者;
# PR  :Priority 的簡寫,程序的優先執行順序,越小越早被執行;
# NI  :Nice 的簡寫,與 Priority 有關,也是越小越早被執行;
# %CPU:CPU 的使用率;
# %MEM:記憶體的使用率;
# TIME+:CPU 使用時間的累加;
# COMMAND:指令

优先级 PRI 与 NI

為了讓系統比較快速的執行重要的程序,因此設計上增加了 Priority (PRI) 這個優先序的設定。 基本上,PRI 越低代表系統會執行較多次該程序,也就是該程序會比較早被執行完畢。

PRI 是系統自行彈性規劃的,使用者並不能更改 PRI。為此,Linux 提供一個名為 Nice (NI) 的數值來讓使用者『影響』程序的 PRI。 基本上, PRI 與 NI 的關係如下:

PRI(new) = PRI(old) + NI

NI 越小會讓 PRI 變小,則程序的優先序會往前挪,相反的,NI 越大會造成 PRI 越大,就 讓程序的優先序變落後了。 但是 NI 的使用是有限制的,基本限制如下:

  • nice 值可調整的範圍為 -20 ~ 19 ;
  • root 可隨意調整自己或他人程序的 Nice 值,且範圍為 -20 ~ 19 ;
  • 一般使用者僅可調整自己程序的 Nice 值,且範圍僅為 0 ~ 19 (避免一般用戶搶佔系統資源);
  • 一般使用者僅可將 nice 值越調越高,例如本來 nice 為 5 ,則未來僅能調整到大於 5;

NI 主要透過 nice 與 renice 來處理。

bash

工作管理 (job control) 是用在 bash 環境下的,也就是說:『當用戶登入系統取得 bash shell 之後,在單一終端機介面下同時進行多個工作的行為管理 』

  • 這些工作所觸發的程序必須來自於你 shell 的子程序(只管理自己的 bash);
  • 前景:你可以控制與下達指令的這個環境稱為前景的工作 (foreground);
  • 背景:可以自行運作的工作,你無法使用 [ctrl]+c 終止他,可使用 bg/fg 呼叫該工作;
  • 背景中『執行』的程序不能等待 terminal/shell 的輸入(input)

組合按鍵如下:

  • command & :直接將 command 丟到背景中執行,若有輸出,最好使用資料流重導向輸出到其他檔案
  • [ctrl]+z :將目前正在前景中的工作丟到背景中暫停
  • jobs [-l]:列出目前的工作資訊
  • fg %n :將第 n 個在背景當中的工作移到前景來操作
  • bg %n :將第 n 個在背景當中的工作變成執行中

基础档案系统

  • 磁區(Sector)為最小的物理儲存單位,目前主要有 512bytes 與 4K 兩種格式;
  • 將磁區組成一個圓,那就是磁柱(Cylinder)(在此忽略磁軌)
  • 分割的最小單位可能是磁柱 (cylinder) 也可能是磁區 (sector),這與分割工具有關
  • 磁碟分割表主要有兩種格式,分別是 MSDOS (或稱 MBR) 與 GPT 分割表
  • MSDOS 分割表中,第一個磁區最重要,裡面有:主要開機區(Master boot record, MBR) 446 bytes 及分割表(partition table) 64 bytes。
  • GPT 分割表除了分割數量擴充較多之外,支援的磁碟容量也可以超過 2TB。

MSDOS

由於 MSDOS 分割表的紀錄區塊僅有 64 bytes 用在分割表,因此預設分割表僅能紀錄四筆分割資訊。所謂的分割資訊即是紀錄開始與結束的磁區。這四筆紀錄主要為『主要分割槽 (primary)』與『延伸分割槽 (extended)』。延伸分割不能被格式化應用, 需要再從延伸分割當中割出『邏輯分割 (logical)』之後,才能夠應用。以 P 代表主要、E 代表延伸、L 代表邏輯分割槽,則相關性為:

  • 主要分割與延伸分割最多可以有四筆(硬碟的限制)
  • 延伸分割最多只能有一個(作業系統的限制)
  • 邏輯分割是由延伸分割持續切割出來的分割槽;
  • 能夠被格式化且作為資料存取的分割槽為主要分割與邏輯分割。延伸分割無法被格式化;
  • 邏輯分割的數量依作業系統而不同,在Linux系統中SATA硬碟已經可以突破63個以上的分割限制;

GPT

常見的磁碟磁區有 512bytes 與 4K 容量,為了相容於所有的磁碟,因此在磁區的定義上面, 大多會使用所謂的邏輯區塊位址(Logical Block Address, LBA)來處理。GPT 將磁碟所有區塊以此 LBA(預設為 512bytes) 來規劃,而第一個 LBA 稱為 LBA0 (從 0 開始編號)。

與 MSDOS 僅使用整顆磁碟的第一個 512bytes 區塊來紀錄不同, GPT 則使用了 34 個 LBA 區塊來紀錄分割資訊! 同時與過去 MSDOS 僅有一個區塊的情況不同, GPT 除了前面 34 個 LBA 之外,整個磁碟的最後 33 個 LBA 也拿來作為另一個備份! 因此,如果磁碟前面的分割紀錄不小心被惡搞而失去,可以透過分割工具,以磁碟最後方的磁區記載的分割表來復原, 對於資訊安全來說,也是相當重要的保護!

LBA2 ~ LBA33 為實際紀錄分割表的所在,每個 LBA 紀錄 4 筆資料,所以共可紀錄 32*4=128 筆以上的分割資訊。 因為每個 LBA 為 512bytes,因此每筆紀錄可佔用512/4=128 bytes的紀錄,因為每筆紀錄主要紀錄開始與結束兩個磁區的位置, 因此紀錄的磁區位置最多可達 64 位元,若每個磁區容量為 512bytes ,則單一分割槽的最大容量就可以限制到 8ZB, 其中 1ZB 為 2^30 TB。 此外,每筆 GPT 的分割紀錄,都是屬於 primary 的分割紀錄,可以直接拿來進行格式化應用的。

Linux EXT 档案系统

一般檔案會有屬性(如權限、時間、身份資料紀錄等)以及實際資料的紀錄, 同時整個檔案系統會紀錄全部的資訊,因此通常檔案系統會有如下幾個部份:

  • superblock:記錄此 filesystem 的整體資訊,包括inode/block的總量、使用量、剩餘量, 以及檔案系統的格式與相關資訊等;
  • inode:記錄檔案的屬性,一個檔案佔用一個inode,同時記錄此檔案的資料所在的 block 號碼;
  • block:實際記錄檔案的內容,若檔案太大時,會佔用多個 block

Superblock

superblock 為整個檔案系統的總結資訊處,要讀取檔案系統一定要從 superblock 讀起。superblock 主要紀錄資料為:

  • block 與 inode 的總量;
  • 未使用與已使用的 inode / block 數量;
  • block 與 inode 的大小 (block 為 1, 2, 4K,inode 為 128bytes, 256bytes 或 512bytes);
  • filesystem 的掛載時間、最近一次寫入資料的時間、最近一次檢驗磁碟 (fsck) 的時間等檔案系統的相關資訊;
  • 一個 valid bit 數值,若此檔案系統已被掛載,則 valid bit 為 0 ,若未被掛載,則 valid bit 為 1

inode table

每一個 inode 都有號碼,而 inode 的內容在記錄檔案的屬性以及該檔案實際資料是放置在哪幾號 block 內。 inode 記錄的檔案資料至少有底下這些:

  • 該檔案的存取模式(read/write/excute);
  • 該檔案的擁有者與群組(owner/group);
  • 該檔案的容量;
  • 該檔案建立或狀態改變的時間(ctime);
  • 最近一次的讀取時間(atime);
  • 最近修改的時間(mtime);
  • 定義檔案特性的旗標(flag),如 SetUID...;
  • 該檔案真正內容的指向 (pointer);

由於每個檔案固定會佔用一個 inode,而目前檔案所記載的屬性資料越來約多,因此 inode 有底下幾個特色:

  • 每個 inode 大小均為固定 (可能是 256bytes 或 512bytes,依據檔案系統不同而定。舊的系統則只能到 128 bytes);
  • 每個檔案都僅會佔用一個 inode 而已;
  • 承上,因此檔案系統能夠建立的檔案數量與 inode 的數量有關;
  • 系統讀取檔案時需要先找到 inode,並分析 inode 所記錄的權限與使用者是否符合,若符合才能夠開始實際讀取 block 的內容。

data block

檔案實際的資料存放在 data block 上面,每個 block 也都會有號碼,提供給檔案來儲存實際資料,也讓 inode 可以紀錄資料放在哪個 block 號碼內。

  • 原則上,block 的大小與數量在格式化完就不能夠再改變了(除非重新格式化);
  • 每個 block 內最多只能夠放置一個檔案的資料;
  • 承上,如果檔案大於 block 的大小,則一個檔案會佔用多個 block 數量;
  • 承上,若檔案小於 block ,則該 block 的剩餘容量就不能夠再被使用了(磁碟空間會浪費)。
sh
# 打印设备信息
$ lsblk -l <device>

# 打印设备信息
$ parted <device> print
$ parted /dev/nvme0n1

Model: SAMSUNG MZVLW256HEHP-00000 (nvme)
Disk /dev/nvme0n1: 256GB
Sector size (logical/physical): 512B/512B
Partition Table: gpt
Disk Flags:

Number  Start   End     Size    File system     Name  Flags
 1      1049kB  300MB   299MB   fat32                 boot, esp
 2      300MB   1324MB  1024MB  ext4
 3      1324MB  3372MB  2048MB  linux-swap(v1)        swap
 4      3372MB  256GB   253GB   ext4
 
# 打印设备uuid
$ blkid

# 设备用量
$ df -T

# 打印分区信息
$ fdisk -l
Disk /dev/nvme0n1: 238.47 GiB, 256060514304 bytes, 500118192 sectors
Disk model: SAMSUNG MZVLW256HEHP-00000
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: gpt
Disk identifier: 183D7EAF-AC1D-4DA5-8BEC-3954846978A2

Device           Start       End   Sectors   Size Type
/dev/nvme0n1p1    2048    585727    583680   285M EFI System
/dev/nvme0n1p2  585728   2586623   2000896   977M Linux filesystem
/dev/nvme0n1p3 2586624   6586367   3999744   1.9G Linux swap
/dev/nvme0n1p4 6586368 500117503 493531136 235.3G Linux filesystem

# 打印 filesystem 信息
$ stat /
  File: /
  Size: 4096            Blocks: 8          IO Block: 4096   directory
Device: 259,4   Inode: 2           Links: 20
Access: (0755/drwxr-xr-x)  Uid: (    0/    root)   Gid: (    0/    root)
Access: 2025-07-08 11:14:22.286414146 +0800
Modify: 2025-05-10 15:51:11.494160414 +0800
Change: 2025-05-10 15:51:11.494160414 +0800
 Birth: 2024-05-01 07:56:02.000000000 +0800
sh

$ apt install lvm2 -y

$ fdisk /dev/sdb

Command (m for help): n  
Partition type  
p   primary (0 primary, 0 extended, 4 free)  
# e   extended (container for logical partitions)  
Select (default p): p  
Partition number (1-4, default 1):  
First sector (2048-1048575999, default 2048):  
Last sector, +/-sectors or +/-size{K,M,G,T,P} (2048-1048575999, default 1048575999):  
  
Created a new partition 1 of type 'Linux' and of size 500 GiB.  
  
Command (m for help): t  
Selected partition 1  
Hex code (type L to list all codes): 8e  
Changed type of partition 'Linux' to 'Linux LVM'.  
  
Command (m for help): p  
Disk /dev/sdb: 500 GiB, 536870912000 bytes, 1048576000 sectors  
Disk model: QEMU HARDDISK  
Units: sectors of 1 * 512 = 512 bytes  
Sector size (logical/physical): 512 bytes / 512 bytes  
I/O size (minimum/optimal): 512 bytes / 512 bytes  
Disklabel type: dos  
Disk identifier: 0xf334c1db  
  
Device     Boot Start        End    Sectors  Size Id Type  
/dev/sdb1        2048 1048575999 1048573952  500G 8e Linux LVM  
  
Command (m for help): w  
The partition table has been altered.  
Calling ioctl() to re-read partition table.  
Syncing disks.

$ sudo pvcreate /dev/sdb1
$ sudo vgcreate vg-att /dev/sdb1
$ sudo lvcreate -L 499.9G -n lv-upload vg-att

$ pvdisplay
--- Physical volume ---  
PV Name               /dev/sdb1  
VG Name               vg-att  
PV Size               <500.00 GiB / not usable 3.00 MiB  
Allocatable           yes  
PE Size               4.00 MiB  
Total PE              127999  
Free PE               5  
Allocated PE          127994  
PV UUID               VX5xRF-Ch1H-5r90-OYup-dFXa-s18D-ONDh5P

$ vgdisplay
--- Volume group ---  
VG Name               vg-att  
System ID  
Format                lvm2  
Metadata Areas        1  
Metadata Sequence No  3  
VG Access             read/write  
VG Status             resizable  
MAX LV                0  
Cur LV                1  
Open LV               1  
Max PV                0  
Cur PV                1  
Act PV                1  
VG Size               <500.00 GiB  
PE Size               4.00 MiB  
Total PE              127999  
Alloc PE / Size       127994 / <499.98 GiB  
Free  PE / Size       5 / 20.00 MiB  
VG UUID               Cx5mv7-OHpf-Zu1d-8vNA-QSE4-Z2G7-33E9Gk

$ lvdisplay
--- Logical volume ---  
LV Path                /dev/vg-att/lv-upload  
LV Name                lv-upload  
VG Name                vg-att  
LV UUID                eJearD-JaDo-fBD0-UeA6-5xgq-JpHn-G00sM5  
LV Write Access        read/write  
LV Creation host, time ff1ccmjmpl6bqg0, 2024-11-07 15:57:21 +0800  
LV Status              available  
open                 1  
LV Size                <499.98 GiB  
Current LE             127994  
Segments               1  
Allocation             inherit  
Read ahead sectors     auto  
- currently set to     256  
Block device           254:0

$ mkfs.ext4 /dev/vg-att/lv-upload

mke2fs 1.44.5 (15-Dec-2018)  
Discarding device blocks: done  
Creating filesystem with 131065856 4k blocks and 32768000 inodes  
Filesystem UUID: 22a86f97-0a42-42c6-b6bf-599a570fe140  
Superblock backups stored on blocks:  
32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208,  
4096000, 7962624, 11239424, 20480000, 23887872, 71663616, 78675968,  
102400000  
  
Allocating group tables: done  
Writing inode tables: done  
Creating journal (262144 blocks): done  
Writing superblocks and filesystem accounting information: done

$ mount /dev/vg-att/lv-upload /data/att/up
$ df -Th
/dev/mapper/vg--att-lv--upload ext4      492G  2.5G  464G   1% /data/att/up

$ sudo du -sh
$ sudo fdisk -l

# 扩容
$ umount /data/att/up
$ lvextend -L +1G /dev/vg-att/lv-upload

# 检查磁盘错误(锟:可以不用。待试验)
$ e2fsck -f /dev/vg-att/lv-upload
# 更新文件系统
$ resize2fs /dev/vg-att/lv-upload

$ mount /dev/vg-att/lv-upload /data/att/up

# /etc/fstab
/dev/sda1: UUID="d5ab1a65-21ce-43d9-863d-a41fc4f43140" BLOCK_SIZE="4096" TYPE="ext4" PARTUUID="fe2f0e85-9369-394a-bf0c-a822db7581e2"

Ref

https://www.kernel.org

https://linux.vbird.org