章節概述#

本章是全書的基礎章節,介紹在 Linux 系統中會用到的 Unix 指令與工具。內容涵蓋 shell 的使用、基本與中階指令、目錄導覽、環境變數、I/O 重導向、程序管理、檔案權限、壓縮封存,以及 Linux 目錄階層結構。即使你已有一定經驗,仍建議瀏覽本章,特別是 Section 2.19 的目錄階層部分。

本章使用 Unix 一詞多於 Linux,因為這些指令在 BSD 等其他 Unix 系統上同樣適用。


2.1 Bourne Shell: /bin/sh#

Shell 是 Unix 系統最重要的組件之一,它是一個執行指令的程式,同時也是一個小型的程式設計環境。

  • 許多系統的重要部分其實是 shell scripts — 包含一系列 shell 指令的文字檔
  • 所有 Unix shell 都源自 Bourne shell (/bin/sh),這是 Bell Labs 開發的標準 shell
  • Linux 使用增強版的 Bourne shell,稱為 bash(Bourne-again shell),是大多數 Linux 發行版的預設 shell
  • /bin/sh 通常是指向 bash 的連結

2.2 使用 Shell#

2.2.1 Shell 視窗 (The Shell Window)#

登入後開啟終端機視窗,shell 會顯示一個提示符號,通常以 $ 結尾。本書中的指令都以 $ 開頭表示。

  • # 開頭的指令需要以 superuser (root) 身份執行
  • 最佳實踐是使用 sudo 來執行需要 root 權限的指令

2.2.2 cat#

cat 是最簡單的 Unix 指令之一,用來輸出一個或多個檔案的內容:

cat file1 file2 ...
  • 名稱來自 concatenation(串接),因為它可以串接多個檔案的內容

2.2.3 Standard Input 與 Standard Output#

Unix 程序使用 I/O streams 來讀寫資料:

  • Standard input (stdin) — 程序的輸入來源,預設連接到終端機
  • Standard output (stdout) — 程序的輸出目標,預設連接到終端機
  • Standard error (stderr) — 第三個 I/O stream,用於診斷和除錯訊息

CTRL-D 可送出 EOF(end-of-file)訊號來結束 stdin 輸入。不要與 CTRL-C(終止程式)混淆。


2.3 基本指令#

2.3.1 ls#

列出目錄內容:

ls -l    # 詳細列表(含權限、擁有者、大小、日期)
ls -F    # 顯示檔案類型資訊

2.3.2 cp#

複製檔案:

cp file1 file2         # 複製檔案
cp file dir            # 複製到目錄
cp file1 file2 file3 dir  # 複製多個檔案到目錄

2.3.3 mv#

移動或重新命名檔案:

mv file1 file2    # 重新命名
mv file dir        # 移動到目錄

2.3.4 touch#

建立空檔案,或更新已存在檔案的修改時間戳記:

touch file

2.3.5 rm#

刪除檔案。刪除後通常無法復原:

rm file

2.3.6 echo#

將引數印到 standard output:

echo Hello again.
  • 對於查看 shell glob 展開結果和變數值非常有用

2.4 目錄導覽#

Unix 目錄階層從 /root directory)開始,目錄分隔符號是 /(正斜線),不是 \

  • Absolute path(絕對路徑)— 以 / 開頭,如 /usr/lib
  • Relative path(相對路徑)— 不以 / 開頭,相對於目前目錄
  • .. 代表上層目錄,. 代表目前目錄

2.4.1 cd#

切換 current working directory

cd dir    # 切換到指定目錄
cd        # 回到 home directory

cd 是 shell 內建指令(built-in),不是獨立程式。它無法作為子程序執行,因為子程序無法改變父程序的工作目錄。

2.4.2 mkdir#

建立新目錄:

mkdir dir

2.4.3 rmdir#

刪除空目錄。若目錄不為空,可用 rm -r dir 遞迴刪除。

rm -r 可能造成嚴重損害,尤其以 root 身份執行時。不要搭配 glob(如 *)使用 -r 選項,執行前務必再三確認。

2.4.4 Shell Globbing(萬用字元)#

Shell 可以使用 globbing 來匹配檔案名稱模式:

  • * — 匹配任意數量的任意字元
  • ? — 匹配恰好一個任意字元
  • 用單引號可以防止 glob 展開:echo '*'

在 Unix 中使用 * 匹配所有檔案,而非 *.**.* 只會匹配名稱中包含 . 的檔案。


2.5 中階指令#

2.5.1 grep#

從檔案或輸入流中搜尋匹配的文字行:

grep root /etc/passwd
grep root /etc/*
  • -i — 不區分大小寫
  • -v — 反向搜尋(顯示不匹配的行)
  • 支援 regular expressions(正規表達式):.* 匹配任意字元序列,.+ 匹配一個以上字元,. 匹配任一字元

2.5.2 less#

分頁瀏覽大型檔案或長輸出:

less /usr/share/dict/words
grep ie /usr/share/dict/words | less
  • 空白鍵往前翻頁,b 往回翻頁,q 離開
  • /word 向前搜尋,?word 向後搜尋

2.5.3 pwd#

顯示目前工作目錄的完整路徑。使用 pwd -P 可以顯示真實路徑(排除 symbolic link 影響)。

2.5.4 diff#

比較兩個文字檔的差異:

diff file1 file2
diff -u file1 file2    # unified format,適合自動化工具

2.5.5 file#

辨識檔案格式:

file file

2.5.6 find 與 locate#

  • find — 在目錄樹中即時搜尋檔案:
find dir -name file -print
  • locate — 透過預建索引搜尋,速度較快但可能不是最新的

2.5.7 head 與 tail#

快速檢視檔案的開頭或結尾:

head /etc/passwd       # 前 10 行
head -5 /etc/passwd    # 前 5 行
tail /etc/passwd       # 最後 10 行
tail +n file           # 從第 n 行開始顯示

2.5.8 sort#

將文字檔按字母順序排序。-n 按數值排序,-r 反向排序。


2.6 變更密碼與 Shell#

  • 使用 passwd 指令變更密碼,建議使用 16 字元以上的長密碼
  • 使用 chsh 指令變更預設 shell(如 zsh、ksh、tcsh)

2.7 Dot Files(隱藏檔)#

Dot files 是以 . 開頭的檔案或目錄,如 .bashrc.login.ssh

  • ls 預設不會顯示它們,需使用 ls -a
  • Shell glob 也不會匹配 dot files,除非明確使用 .* 之類的模式

2.8 Environment 與 Shell Variables#

  • Shell variable — 僅在目前 shell 中有效:
STUFF=blah
  • Environment variable — 會傳遞給子程序:
STUFF=blah
export STUFF

賦值時 = 前後不能有空格。

  • 子程序會繼承父程序的 environment variables
  • 許多程式會讀取 environment variables 作為設定(如 LESS 環境變數)

2.9 The Command Path#

PATH 是一個特殊的 environment variable,包含 shell 搜尋指令時會查找的目錄清單,以冒號 : 分隔:

echo $PATH
# /usr/local/bin:/usr/bin:/bin

PATH=dir:$PATH      # 在最前面加入目錄
PATH=$PATH:dir      # 在最後面加入目錄

修改 $PATH 時若打錯字,可能會覆蓋整個 path。不過這不是永久性的,只要開啟新 shell 即可恢復。


2.10 Special Characters(特殊字元)#

常見的特殊字元及其用途:

字元名稱用途
*star, asterisk正規表達式、glob
.dot目前目錄、檔名分隔符號
!bang否定、指令歷史
|pipe管線指令
/forward slash目錄分隔符號、搜尋
$dollar變數、行尾
'single quote字面字串
`backtick指令替換
"double quote半字面字串
~tilde否定、home 目錄捷徑
#hash, pound註解、前處理器

2.11 Command-Line Editing#

常用的命令列編輯快捷鍵:

按鍵功能
CTRL-B / CTRL-F左移 / 右移游標
CTRL-P / CTRL-N上一個 / 下一個指令
CTRL-A / CTRL-E移到行首 / 行尾
CTRL-W刪除前一個單字
CTRL-U / CTRL-K刪除到行首 / 行尾
CTRL-Y貼上已刪除的文字

2.12 Text Editors#

學習 Unix 必須掌握至少一個文字編輯器:

  • Emacs — 功能強大,有豐富的線上說明
  • vi — 速度至上,操作風格像遊戲

雖然 nano、Pico 等編輯器較友善,但如果你想認真學習 Unix,建議學習 vi 或 Emacs。


2.13 Getting Online Help#

Manual Pages (man pages)#

man ls              # 查看 ls 的手冊頁
man -k keyword      # 按關鍵字搜尋手冊頁
man 5 passwd        # 查看特定 section 的手冊頁

手冊頁分為多個 section

Section說明
1使用者指令
2Kernel system calls
3高階 Unix 程式庫文件
5檔案描述(系統設定檔)
8系統管理指令與伺服器

其他取得幫助的方式:

  • command --helpcommand -h
  • info command — GNU 的替代文件格式
  • /usr/share/doc — 某些套件的文件目錄

2.14 Shell Input and Output#

Standard Output 重導向#

command > file      # 輸出到檔案(覆蓋)
command >> file     # 輸出到檔案(附加)

Pipe(管線)#

head /proc/cpuinfo | tr a-z A-Z
  • 可以串接任意多個管線指令

2.14.1 Standard Error#

Standard error (stderr) 是獨立於 stdout 的輸出串流,stream ID 為 2:

ls /fffffffff > f 2> e       # stdout 到 f,stderr 到 e
ls /fffffffff > f 2>&1       # stdout 和 stderr 都到 f

2.14.2 Standard Input 重導向#

head < /proc/cpuinfo
  • 大多數 Unix 指令接受檔名作為引數,因此 stdin 重導向較不常用

2.15 Understanding Error Messages#

2.15.1 Unix 錯誤訊息的結構#

Unix 錯誤訊息通常包含三個部分:

  1. 程式名稱(如 ls
  2. 檔案名稱(如 /dsafsda
  3. 錯誤描述(如 No such file or directory

排錯時,永遠先處理第一個錯誤訊息,後續錯誤可能是連鎖反應。

2.15.2 常見錯誤#

  • No such file or directory — 最常見的錯誤,也稱為 ENOENT
  • File exists — 嘗試建立已存在的檔案或目錄
  • Not a directory / Is a directory — 將檔案當目錄用,或反之
  • No space left on device — 磁碟空間已滿
  • Permission denied — 權限不足
  • Operation not permitted — 嘗試終止不屬於你的程序
  • Segmentation fault / Bus error — 程式存取了不允許的記憶體區域

2.16 Listing and Manipulating Processes#

每個程序都有一個 process ID (PID)

ps        # 列出你的程序
ps x      # 列出所有你的程序
ps ax     # 列出系統上所有程序
ps u      # 詳細資訊
ps w      # 顯示完整指令

ps 輸出欄位:PIDTTY(終端設備)、STAT(程序狀態,S=sleeping、R=running)、TIME(CPU 時間)、COMMAND

2.16.1 ps 指令選項#

支援三種風格:Unix、BSD、GNU。BSD 風格最常用,可組合使用如 ps auxw

2.16.2 Process Termination#

使用 kill 發送 signal 給程序:

kill pid           # 發送 TERM 信號
kill -STOP pid     # 暫停程序
kill -CONT pid     # 繼續執行
kill -KILL pid     # 強制終止(最後手段)

KILL 信號無法被忽略或處理,kernel 會直接終止程序並從記憶體中移除。僅在其他方法無效時使用。

2.16.3 Job Control#

Shell 支援 job control,可以暫停和切換程式:

  • CTRL-Z — 發送 TSTP 信號暫停程式
  • fg — 將程式帶回前景
  • bg — 將程式移到背景

2.16.4 Background Processes#

使用 & 將程序放到背景執行:

gunzip file.gz &
  • 建議將背景程序的輸出重導向到檔案,避免干擾終端機

2.17 File Modes and Permissions#

每個 Unix 檔案都有 permissions,透過 ls -l 查看:

-rw-r--r--  1 juser somegroup  7041  Mar 26 19:34  endnotes.html

Mode 的四個部分:

  1. File type- 一般檔案、d 目錄、l symbolic link
  2. User permissions — 檔案擁有者的權限
  3. Group permissions — 檔案群組的權限
  4. Other permissions — 其他人的權限

Figure 2-1: The pieces of a file mode

權限符號:

  • r — 可讀取
  • w — 可寫入
  • x — 可執行
  • - — 無此權限
  • s — setuid(執行時以檔案擁有者身份執行)

2.17.1 Modifying Permissions#

使用 chmod 修改權限:

chmod g+r file       # 為 group 加上讀取權限
chmod go+r file      # 為 group 和 other 加上讀取權限
chmod go-r file      # 移除權限
chmod 644 file       # 使用八進位數字設定(absolute mode)

常用的 absolute mode:

Mode意義用途
644user: rw, group: r, other: r檔案
600user: rw, group: -, other: -檔案
755user: rwx, group: rx, other: rx目錄、程式
700user: rwx, group: -, other: -目錄、程式
  • umask 指令可設定新檔案的預設權限遮罩(022077

Symbolic link 是指向另一個檔案或目錄的檔案,類似 Windows 的捷徑:

ln -s target linkname

不要忘記 -s 選項。沒有 -sln 會建立 hard link,除非你了解 hard link 的機制(參見 Section 4.6),否則應避免使用。

  • Symbolic link 可能產生 chained symbolic links,增加追蹤難度
  • 建立時務必確認引數順序,並使用完整路徑

2.18 Archiving and Compressing Files#

2.18.1 gzip#

gzip (GNU Zip) 是標準的 Unix 壓縮工具:

gzip file          # 壓縮(產生 file.gz)
gunzip file.gz     # 解壓縮

2.18.2 tar#

tar 用來將多個檔案和目錄打包成單一 archive 檔案:

tar cvf archive.tar file1 file2 ...   # 建立 archive
tar xvf archive.tar                    # 解開 archive
tar tvf archive.tar                    # 列出 archive 內容
  • c — create mode
  • x — extract mode
  • t — table-of-contents mode
  • v — verbose output
  • f — 指定 archive 檔名

解開前務必先用 t 模式檢查內容,確認是否有合理的目錄結構,避免將大量檔案倒入目前目錄。

2.18.3 Compressed Archives (.tar.gz)#

gunzip file.tar.gz && tar xvf file.tar    # 兩步驟解開

2.18.4 zcat#

更有效率的方式是使用管線:

zcat file.tar.gz | tar xvf -

或使用 tar 的 z 選項作為捷徑:

tar ztvf file.tar.gz    # 檢視壓縮 archive 內容
tar zxvf file.tar.gz    # 解開壓縮 archive

2.18.5 Other Compression Utilities#

  • xz / bzip2 — 壓縮率比 gzip 高,但速度稍慢,副檔名為 .xz.bz2
  • zip / unzip — 與 Windows ZIP 格式相容
  • .Z 檔案是舊版 compress 程式產生的,gunzip 可以解壓

2.19 Linux Directory Hierarchy Essentials#

Linux 目錄結構遵循 Filesystem Hierarchy Standard (FHS)

Figure 2-2: Linux directory hierarchy

主要根目錄子目錄#

目錄說明
/bin基本可執行程式(ls、cp 等)
/dev裝置檔案
/etc系統設定檔(密碼、開機、網路等)
/home一般使用者的家目錄
/lib程式庫檔案(shared libraries)
/proc系統統計資訊的虛擬檔案系統
/run系統執行期間的資料(PID、socket 等)
/sys裝置與系統介面(類似 /proc)
/sbin系統管理程式(通常需要 root)
/tmp暫存檔案(開機時可能被清除)
/usr大部分使用者空間程式和資料
/var可變動的資料(日誌、快取等)

2.19.1 Other Root Subdirectories#

  • /boot — kernel boot loader 檔案
  • /media — 可移除媒體的掛載點
  • /opt — 第三方軟體(許多系統不使用)

2.19.2 /usr 目錄#

/usr 包含大部分使用者空間程式和資料:

  • /usr/include — C 編譯器的 header 檔案
  • /usr/local — 管理者自行安裝的軟體
  • /usr/man — 手冊頁
  • /usr/share — 跨平台共用的輔助資料檔案

/usr 發音為 “user”,但實際上不包含使用者檔案。根目錄與 /usr 有相似的子目錄結構(如 /bin/usr/bin),這是歷史原因造成的 — 過去需要控制根目錄的磁碟空間使用量。

2.19.3 Kernel Location#

  • Kernel 通常是 /vmlinuz/boot/vmlinuz 二進位檔案
  • Boot loader 負責將 kernel 載入記憶體
  • Loadable kernel modules 位於 /lib/modules,可在執行時動態載入和卸載

2.20 Running Commands as the Superuser#

不建議直接啟動 root shell,原因包括:

  • 無法追蹤系統變更指令的記錄
  • 無法辨識是哪位使用者執行了系統變更
  • 無法使用一般使用者的 shell 環境
  • 需要輸入 root 密碼

2.20.1 sudo#

sudo 讓管理者以自己的身份登入並以 root 執行指令:

sudo vipw
  • sudo 會透過 syslog 記錄所有操作

2.20.2 /etc/sudoers#

設定哪些使用者可以使用 sudo:

User_Alias ADMINS = user1, user2
ADMINS ALL = NOPASSWD: ALL
root ALL=(ALL) ALL

務必使用 visudo 指令來編輯 /etc/sudoers,它會在儲存後檢查語法錯誤。

2.20.3 sudo Logs#

查看 sudo 日誌:

journalctl SYSLOG_IDENTIFIER=sudo

在較舊的系統上,日誌位於 /var/log/var/log/auth.log


2.21 Looking Forward#

完成本章後,你應該能夠在命令列上執行程式、重導向輸出、操作檔案與目錄、檢視程序列表、閱讀手冊頁,以及以 superuser 身份執行指令。接下來的章節將結合 kernel 和 user-space 的系統組件,使用本章學到的命令列工具進行探索。