章節概覽#

本章探討 Linux 系統中的使用者環境 (User Environments),重點在於 shell 啟動檔案(startup files)的設計與管理。這些檔案(又稱 dot files,因為檔名以 . 開頭)決定了使用者登入後 shell 和互動程式的預設行為。

隨著時間推移,啟動檔案容易累積不必要的環境變數和測試,導致各種問題。本章說明如何正確建立、組織和維護這些檔案。


13.1 建立啟動檔案的準則#

設計啟動檔案時,應以使用者為核心考量。如果你是機器上唯一的使用者,錯誤容易修復;但若檔案會被其他使用者共用(例如作為新使用者的預設值),則需格外謹慎。

建立啟動檔案的兩個基本目標:

  • Simplicity(簡潔):保持啟動檔案數量少、內容精簡,容易修改且不易出錯。每多一個項目就多一個潛在的故障點。
  • Readability(可讀性):在檔案中加入充分的註解,讓使用者能清楚了解每個部分的功能。

13.2 何時修改啟動檔案#

在修改啟動檔案之前,先問自己是否真的有必要。合理的修改理由包括:

  • 想要變更預設的 prompt
  • 需要為本地安裝的關鍵軟體做調整(但優先考慮使用 wrapper script)
  • 現有的啟動檔案已經損壞

如果你的 Linux 發行版一切運作正常,修改時要特別小心。預設的啟動檔案可能與 /etc 中的其他檔案有互動關係。


13.3 Shell 啟動檔案的要素#

13.3.1 Command Path#

Command path 是啟動檔案中最重要的部分。路徑至少應包含以下目錄(按此順序):

/usr/local/bin
/usr/bin
/bin

這個順序確保 /usr/local 中的自訂程式可以覆蓋系統預設版本。

許多使用者會建立自己的 bin 目錄來存放腳本,可以將其加到路徑最前面:

$HOME/bin

較新的慣例是將個人二進位檔放在 $HOME/.local/bin

如果需要系統管理工具(如 sysctlfdisklsmod),可以加入 sbin 目錄:

/usr/local/sbin
/usr/sbin
/sbin

不要在路徑中加入 .(當前目錄)。這是安全風險——攻擊者可以在常見目錄中放置名為 ls 的木馬程式。即使放在路徑末端,也可能被利用打字錯誤(如 s1ks)來攻擊。

13.3.2 Manual Page Path#

傳統上 MANPATH 環境變數用來設定手冊頁路徑,但不建議手動設定,因為這會覆蓋 /etc/manpath.config 中的系統預設值。

13.3.3 Prompt#

有經驗的使用者傾向避免冗長、複雜的 prompt。應根據實際需求選擇包含的資訊。

bash 中常用的 prompt 特殊字元:

  • \u — 使用者名稱
  • \h — 主機名稱(短格式)
  • \! — 歷史記錄編號
  • \w — 當前工作目錄(\W 只顯示最後一層)
  • \$ — 一般使用者顯示 $,root 顯示 #

簡單的 prompt 設定範例:

PS1='\u\$ '

避免在 prompt 中使用對 shell 有特殊意義的字元,如 { } = & < >。特別注意 > 字元——如果不小心複製貼上 prompt 內容,可能會因為重新導向而覆蓋檔案。

13.3.4 Aliases#

Aliases 是 shell 的字串替換功能,可以在執行命令前將一個字串替換為另一個。雖然方便,但有幾個缺點:

  • 難以操作引數
  • 令人困惑——which 命令可以告訴你某個東西是 alias,但不會告訴你它的定義位置
  • 在 subshell 和非互動式 shell 中無法使用,也不會傳遞給子 shell

定義 alias 時的經典錯誤是為現有命令添加額外引數,例如 alias ls='ls -F'。這會使移除 -F 參數變得困難,對不了解預設引數已被更改的使用者可能造成嚴重後果。

建議盡量使用 shell function 或獨立的 shell script 來取代 alias。

13.3.5 Permissions Mask#

使用 shell 內建的 umask 命令設定預設權限。兩個合理的選擇:

  • 077 — 最嚴格,不讓其他使用者存取新檔案。適合多使用者系統中重視隱私的環境。
  • 022 — 讓其他使用者可以讀取新檔案。適合單一使用者系統,因為以 pseudo-user 身分執行的 daemon 需要能存取檔案。

某些應用程式(尤其是郵件程式)會自行覆蓋 umask 為 077,因為它們認為自己的檔案只應由檔案擁有者存取。


13.4 啟動檔案的順序與範例#

13.4.1 bash Shell#

在 bash 中,可以使用的啟動檔案包括 .bash_profile.profile.bash_login.bashrc。要理解應該使用哪個檔案,需要先了解 bash shell 的兩種類型。

Login Shell#

Login shell 是使用者首次登入系統時取得的 shell(例如透過 /bin/login 或 SSH)。判斷方法:

echo $0

如果第一個字元是 -,就是 login shell。

Login shell 啟動時會依序執行:

  1. /etc/profile
  2. 使用者的 .bash_profile.bash_login.profile(只執行找到的第一個)

Non-Login Shell#

Non-login shell 是登入後額外啟動的互動式 shell。視窗系統的終端程式(如 xterm、GNOME Terminal)預設啟動的就是 non-login shell。

Non-login shell 啟動時會執行:

  1. /etc/bash.bashrc
  2. 使用者的 .bashrc

兩種 Shell 的歷史原因#

早期使用者透過終端以 login shell 登入,再透過視窗系統啟動 non-login subshell。為避免重複設定環境,login shell 負責完整設定(PATH、環境變數等),non-login shell 只負責輕量的設定(如 alias)。

現代桌面使用者通常透過圖形化 display manager 登入,大多數 display manager 會啟動一個非互動式的 login shell。因此建議將所有環境設定放在 .bashrc 中,並讓 .bash_profile 指向它。

.bashrc 範例#

# Command path.
PATH=/usr/local/bin:/usr/bin:/bin:/usr/games
PATH=$HOME/bin:$PATH

# PS1 is the regular prompt.
PS1='\u\$ '

# EDITOR and VISUAL determine the editor that programs such as less
# and mail clients invoke when asked to edit a file.
EDITOR=vi
VISUAL=vi

# PAGER is the default text file viewer for programs such as man.
PAGER=less

# These are some handy options for less.
LESS=meiX

# You must export environment variables.
export PATH EDITOR VISUAL PAGER LESS

# By default, give other users read-only access to most new files.
umask 022

可以透過 symbolic link 或以下 one-liner 讓 .bash_profile 指向 .bashrc

. $HOME/.bashrc

區分 Login 和 Interactive Shell#

如果需要在 .bashrc 中區分 login 和 non-login shell,可以檢查 $- 變數中的 i 字元:

case $- in
  *i*) # interactive commands go here
    ;;
  *)   # non-interactive commands go here
    ;;
esac

13.4.2 tcsh Shell#

tcshcsh 的增強版,提供命令列編輯和檔名補全等功能。tcsh 不區分 login 和 non-login shell——啟動時先尋找 .tcshrc,找不到則使用 .cshrc

建議使用 .cshrc 而非 .tcshrc,以確保在遇到傳統 csh 的系統上也能相容。

.cshrc 範例#

# Command path.
setenv PATH $HOME/bin:/usr/local/bin:/usr/bin:/bin

# EDITOR and VISUAL
setenv EDITOR vi
setenv VISUAL vi

# PAGER
setenv PAGER less

# Options for less.
setenv LESS meiX

# Default permissions.
umask 022

# Customize the prompt.
set prompt="%m%% "

13.5 預設使用者設定#

測試啟動檔案的最佳方式是建立一個新的測試使用者,使用空白的 home 目錄,從頭撰寫啟動檔案。確認一切正常後,再建立第二個測試使用者來驗證。

13.5.1 Shell Defaults#

新使用者的預設 shell 應為 bash,原因包括:

  • 使用者用來互動的 shell 與撰寫腳本的 shell 一致
  • bash 是 Linux 發行版的預設 shell
  • bash 使用 GNU readline 函式庫來接受輸入,介面與許多其他工具一致
  • bash 提供良好的 I/O 重新導向和 file handle 控制

還有許多其他 shell 可選擇(rc、ksh、zsh、es、fish 等)。其中 zshfish 在尋找替代 shell 的新使用者中相當受歡迎。使用者可以透過 chsh 命令自行變更 shell。

13.5.2 Editor#

傳統的預設編輯器是 viemacs,因為它們幾乎在所有 Unix 系統上都存在。Linux 發行版通常將 nano 設為預設,因為對初學者更友善。

在 shell 啟動檔案中避免使用大型的編輯器啟動檔。可以在 .exrc 中設定小型選項(例如讓 vi 顯示匹配括號的 showmatch),但避免大幅改變編輯器的行為或外觀。

13.5.3 Pager#

Pager 是一次顯示一頁文字的程式(如 less)。將 PAGER 環境變數設為 less 是合理的預設值。


13.6 啟動檔案的常見陷阱#

在啟動檔案中應避免以下做法:

  • 不要放入任何圖形化命令——不是所有 shell 都在圖形環境中執行
  • 不要設定 DISPLAY 環境變數——可能導致圖形化 session 異常
  • 不要設定終端類型 (terminal type)
  • 不要省略描述性註解
  • 不要在啟動檔案中執行會輸出到標準輸出的命令
  • 不要在啟動檔案中設定 LD_LIBRARY_PATH

13.7 進階啟動主題#

本書不涵蓋視窗環境 (windowing environment) 的啟動檔案,因為這是一個龐大的主題。Display manager 有自己的啟動檔案(如 .xsession.xinitrc),加上 GNOME 和 KDE 相關的各種組合,選擇繁多。

保持 shell 啟動檔案簡潔的原則同樣適用於 GUI 啟動檔案。事實上,你很可能完全不需要修改 GUI 啟動檔案。