章節概覽#
本章涵蓋讓 user-space 軟體能與系統基礎設施互動的重要組件,包括:
- System logging — 系統日誌記錄
- 系統函式庫存取的設定檔(取得伺服器與使用者資訊)
- 開機時啟動的伺服器程式(daemons)
- 時間設定與定期任務排程
隨著 systemd 的普及,許多獨立 daemon 已被整合。例如傳統的 syslogd 大部分功能已由 systemd 內建的 journald 取代,但 crond 和 atd 等傳統 daemon 仍然存在。
7.1 System Logging#
大多數系統程式將診斷輸出以訊息形式寫入 syslog 服務。在現代系統上,journald(隨 systemd 而來)負責大部分工作,但許多系統也同時執行傳統的 rsyslogd。
一則 log 訊息通常包含:
- Timestamp — 時間戳記
- Process name 與 Process ID
- Facility — 訊息的一般分類(如 kernel、mail、printer)
- Severity — 訊息的緊急程度(0-7,0 最重要)
7.1.1 檢查 Log 設定#
確認系統使用哪種 logging 的步驟:
- 執行
journalctl檢查 journald 是否運作 - 在 process listing 中尋找 rsyslogd,並檢查
/etc/rsyslog.conf - 若無 rsyslogd,檢查
/etc/syslog-ng目錄(syslog-ng)
日誌檔案通常位於 /var/log,journald 的二進位日誌存放在 /var/log/journal。
7.1.2 搜尋與監控 Log#
使用 journalctl 搜尋日誌的常用方式:
依時間篩選:
journalctl -S -4h # 最近 4 小時
journalctl -S 2020-01-14 # 特定日期之後依 Unit 篩選:
journalctl -u cron.service # 特定 unit
journalctl -F _SYSTEMD_UNIT # 列出所有 unit依文字篩選:
journalctl -g 'kernel.*memory' # 正規表示式搜尋依開機篩選:
journalctl -b # 當前開機
journalctl -b -1 # 上一次開機
journalctl --list-boots # 列出所有開機記錄依嚴重性篩選:
journalctl -p 3 # 等級 0-3(emerg 到 err)
journalctl -p 2..3 # 等級 2 到 3即時監控:
journalctl -f # 類似 tail -f 的效果要完整存取 journal 訊息,需要以 root 身份執行
journalctl,或者使用者需屬於 adm 或 systemd-journal 群組。
7.1.3 Logfile Rotation#
使用 syslog daemon 時,日誌會不斷增長。logrotate 工具負責 log rotation(日誌輪替):
- 將日誌分割成多個 chunk(如
auth.log、auth.log.1、auth.log.2) - 輪替時移除最舊的檔案,依序重新命名
- 部分發行版會壓縮舊日誌(如
auth.log.2.gz) - 部分發行版以日期作為後綴(如
-20200529)
7.1.4 Journal 維護#
journald 儲存在 /var/log/journal 的日誌不需要 rotation。journald 根據以下因素自動管理:
- 檔案系統剩餘空間
- journal 應佔檔案系統的百分比
- 設定的最大 journal 大小
- 日誌訊息的最大保留時間
詳細設定請參考 journald.conf(5) manual page。
7.1.5 深入了解 System Logging#
Syslog 的運作機制:
- 傳統 syslogd 監聽 Unix domain socket
/dev/log等待訊息 - 也可以監聽網路 socket,讓多台機器的 log 集中到一台伺服器
- Syslog 協定定義在 RFC 5424
Facility 與 Severity:
- Facility — 訊息來源的服務類別(kernel、mail system、printer 等)
- Severity — 八個等級(0-7):
| 等級 | 名稱 | 等級 | 名稱 |
|---|---|---|---|
| 0 | emerg | 4 | warning |
| 1 | alert | 5 | notice |
| 2 | crit | 6 | info |
| 3 | err | 7 | debug |
Syslog 與 journald 的關係:
Syslog 仍然存在的原因:
- 擅長跨機器彙整日誌
- rsyslogd 等版本支援模組化輸出(多種格式與資料庫)
journald 則專注於單一機器的日誌收集與組織,並能將日誌轉送給不同的 logger。
7.2 /etc 的結構#
大多數系統設定檔位於 /etc。近年趨勢是將設定檔放入 /etc 下的子目錄(如 /etc/systemd)。
為解決升級時設定被覆蓋的問題,現在可以將自訂設定放在設定子目錄中的獨立檔案(如 /etc/grub.d 中的檔案)。
/etc 中存放的是單一機器的可自訂設定(如 /etc/passwd、/etc/network)。系統預設設定檔(不需自訂的)則放在其他位置,如 /usr/lib/systemd。
7.3 User Management Files#
Unix 系統支援多個獨立使用者。在 kernel 層級,使用者只是數字(user ID),username 僅存在於 user space。
7.3.1 /etc/passwd 檔案#
/etc/passwd 以純文字將 username 對應到 user ID。每行包含七個以冒號分隔的欄位:
juser:x:3119:1000:J. Random User:/home/juser:/bin/bash- Login name — 使用者名稱
- Password —
x表示密碼存在 shadow 檔案中,*表示無法登入 - User ID (UID) — kernel 中使用者的數字表示
- Group ID (GID) — 使用者的 primary group
- GECOS — 使用者的真實姓名等資訊
- Home directory — 家目錄路徑
- Shell — 使用者登入時執行的 shell

Figure 7-1: An entry in the password file
若 password 欄位為空(兩個連續冒號),表示不需密碼即可登入。絕對不要讓使用者無密碼登入。
7.3.2 特殊使用者#
- root (superuser) — 永遠是 UID 0、GID 0
- daemon、bin 等 — 無法登入的系統使用者
- nobody — 權限極低的使用者,部分 process 以此身份執行
無法登入的使用者稱為 pseudo-users,通常基於安全理由而建立。
7.3.3 /etc/shadow 檔案#
shadow password file (/etc/shadow) 儲存加密過的密碼及密碼過期資訊。它的引入是為了提供更安全、更靈活的密碼儲存方式。一般使用者無法讀取此檔案。
7.3.4 操作使用者與密碼#
passwd— 變更密碼chfn— 變更真實姓名chsh— 變更 shell(shell 必須列在/etc/shells中)adduser/userdel— 新增/刪除使用者vipw— 安全編輯/etc/passwd(加鎖備份)vipw -s— 安全編輯/etc/shadow
不要直接用文字編輯器修改
/etc/passwd。使用vipw可以在編輯時加鎖並備份,避免並行修改問題。
7.3.5 群組 (Groups)#
/etc/group 定義群組 ID。每行包含四個欄位:
disk:*:6:juser,beazley- Group name — 群組名稱
- Group password — 幾乎不使用(通常為
*或!) - Group ID (GID) — 唯一的群組 ID
- Additional members — 額外屬於此群組的使用者列表
使用 groups 指令查看你所屬的群組。

Figure 7-2: An entry in the group file
Linux 發行版通常會為每個新使用者建立一個同名的群組。
7.4 getty 與 login#
getty 程式連接到終端機並顯示登入提示。在大多數 Linux 系統上,getty 僅用於虛擬終端 (virtual terminal)。
登入流程:
- getty 顯示登入提示
- 輸入使用者名稱後,getty 將自己替換為 login 程式
- login 要求輸入密碼
- 密碼正確時,login 使用
exec()將自己替換為使用者的 shell - 實際的認證工作由 PAM 處理(見 7.10 節)
現今大多數使用者透過圖形介面(如 gdm)或 SSH 遠端登入,不直接使用 getty 或 login。
7.5 設定時間#
Unix 機器依賴準確的計時。kernel 維護 system clock(系統時鐘),PC 硬體則有電池供電的 real-time clock (RTC)。
- kernel 開機時根據 RTC 設定系統時鐘
- Time drift — kernel 時間與真實時間的差距,長時間運行後會累積
- 不要用
hwclock修正 time drift,應使用網路時間 daemon
hwclock --systohc --utc # 將 RTC 設為 kernel 的 UTC 時間保持硬體時鐘使用 UTC,以避免時區和日光節約時間造成的問題。
7.5.1 Kernel 時間表示與時區#
- kernel 以自 1970 年 1 月 1 日 00:00 UTC 以來的秒數表示時間
- 本地時區由
/etc/localtime控制(二進位檔案) - 時區檔案位於
/usr/share/zoneinfo - 使用
tzselect指令幫助選擇時區
臨時變更時區:
export TZ=US/Central
date7.5.2 Network Time#
Network Time Protocol (NTP) 透過遠端伺服器維持時間同步:
- 傳統由 ntpd 處理,現在 systemd 提供了 timesyncd
- 大多數 Linux 發行版預設啟用 timesyncd
- 若無永久網路連線,可使用 chronyd
- 設定詳見
timesyncd.conf(5)manual page
7.6 使用 cron 與 Timer Units 排程週期性任務#
有兩種方式執行週期性任務:cron 和 systemd timer units。
cron 基礎#
透過 crontab 指令建立 cron job。crontab 檔案每行的前五個欄位指定排程時間:
分鐘 小時 日 月 星期幾 指令範例:
15 09 * * * /home/juser/bin/spmake # 每天 9:15
15 09 14 * * /home/juser/bin/spmake # 每月 14 號 9:15
15 09 5,14 * * /home/juser/bin/spmake # 每月 5 號和 14 號 9:15*表示匹配所有值- 可用逗號指定多個值

Figure 7-3: An entry in the crontab file
若 cron job 產生 standard output 或錯誤,cron 會將資訊 email 給 job 的擁有者。將輸出導向
/dev/null可避免收到信件。
7.6.1 安裝 Crontab 檔案#
crontab file— 安裝 crontab 檔案crontab -e— 編輯 crontabcrontab -l— 列出 cron jobscrontab -r— 移除 crontab
使用者的 crontab 存放在 /var/spool/cron/crontabs。
7.6.2 System Crontab 檔案#
系統層級的 cron 任務定義在 /etc/crontab,格式多一個使用者欄位:
42 6 * * * root /usr/local/bin/cleansystem > /dev/null 2>&1部分發行版也使用 /etc/cron.d 目錄及 /etc/cron.daily 等目錄。
7.6.3 Timer Units#
systemd timer unit 是 cron job 的替代方案。需要建立兩個 unit 檔案:
Timer unit (loggertest.timer):
[Unit]
Description=Example timer unit
[Timer]
OnCalendar=*-*-* *:00,20,40
Unit=loggertest.service
[Install]
WantedBy=timers.targetService unit (loggertest.service):
[Unit]
Description=Example Test Service
[Service]
Type=oneshot
ExecStart=/usr/bin/logger -p local3.debug I\'m a loggerOnCalendar格式:year-month-day hour:minute:secondType=oneshot表示服務執行完畢後即結束- Timer unit 放在
/etc/systemd/system
7.6.4 cron 與 Timer Units 的比較#
cron 的優勢:
- 設定更簡單
- 與第三方服務的相容性
- 使用者更容易安裝自己的任務
Timer units 的優勢:
- 透過 cgroups 追蹤相關 process
- journal 中有更好的診斷資訊記錄
- 更多啟動時間和頻率的選項
- 可使用 systemd 依賴關係與啟動機制
7.7 使用 at 排程一次性任務#
at 服務用於排程只執行一次的任務:
at 22:30
at> myjob按 CTRL-D 結束輸入。
atq— 查看已排程的 jobatrm— 移除 job- 可指定未來日期:
at 22:30 30.09.15
7.7.1 Timer Unit 等效方式#
使用 systemd-run 建立一次性的 transient timer unit:
systemd-run --on-calendar='2022-08-14 18:00' /bin/echo this is a test- 也可用
--on-active=30m指定相對時間(30 分鐘後)
使用
--on-calendar時,必須包含未來的日期和時間。否則 timer 和 service unit 會持續存在,每天在指定時間重複執行。
7.8 以一般使用者執行 Timer Units#
Timer units 也可以一般使用者身份執行,透過 --user 選項傳給 systemd-run。
但有一個限制:若使用者登出,unit 會終止(因為 systemd 的 user manager 與登入 session 綁定)。解決方式:
loginctl enable-linger # 為自己啟用
loginctl enable-linger user # root 為其他使用者啟用7.9 User Access 進階主題#
7.9.1 User ID 與使用者切換#
使用 sudo 和 su 切換使用者時,本質上是在改變 user ID。kernel 的三個基本規則:
- process 可以執行 setuid 程式(只要有適當的檔案權限)
- 以 root (UID 0) 執行的 process 可用
setuid()變成任何使用者 - 非 root process 無法使用
setuid()
7.9.2 Process Ownership、Effective UID、Real UID 與 Saved UID#
每個 process 實際上有多個 user ID:
- Effective UID (euid) — 決定 process 的存取權限(如檔案權限)
- Real UID (ruid) — 表示啟動 process 的使用者,決定誰可以 kill 該 process
- Saved user ID — process 可在 euid 和 saved UID 之間切換
- File system user ID (fsuid) — 定義存取檔案系統的使用者(很少使用)
大多數 process 的 euid 和 ruid 相同。執行 setuid 程式時,Linux 將 euid 設為程式擁有者,但保留原始使用者在 ruid 中。
安全注意事項:
- 必須嚴格控制具有 setuid 權限的程式數量與品質
- 將 bash shell 設為 setuid root 會讓任何本地使用者取得完整系統控制權
- 利用 root 程式的弱點是系統入侵的主要方法之一
7.9.3 User Identification、Authentication 與 Authorization#
多使用者系統的三個安全面向:
- Identification — 辨識使用者是誰
- Authentication — 驗證使用者確實是他所宣稱的人
- Authorization — 定義並限制使用者被允許做的事
kernel 只認識數字 user ID,所有與 username 和密碼相關的認證都在 user space 進行。
7.9.4 使用函式庫取得使用者資訊#
程式透過標準函式庫函式(如 getpwuid())取得使用者名稱,而非直接讀取 /etc/passwd。這樣可以在不修改程式的情況下變更認證實作(如改用 LDAP)。
7.10 Pluggable Authentication Modules (PAM)#
PAM 是 1995 年由 Sun Microsystems 提出的認證框架(Open Software Foundation RFC 86.0)。應用程式將使用者交給 PAM 來判斷是否能成功認證,支援雙因素認證、實體金鑰等多種方式。
PAM 使用動態載入的 authentication modules(共享物件),每個模組執行特定任務。例如 pam_unix.so 可以檢查使用者的密碼。
7.10.1 PAM 設定#
設定檔位於 /etc/pam.d 目錄。每行設定包含三個欄位:
function_type control_argument moduleFunction types(功能類型):
- auth — 認證使用者身份
- account — 檢查帳號狀態(是否被授權)
- session — 執行 session 相關動作(如顯示每日訊息)
- password — 變更密碼或其他憑證
Control arguments(控制引數):
- sufficient — 成功即完成認證,失敗則繼續下一條規則
- requisite — 成功則繼續,失敗則立即結束認證(失敗)
- required — 成功則繼續,失敗也繼續處理後續規則,但最終一定回報失敗
範例(chsh 的認證堆疊):
auth sufficient pam_rootok.so
auth requisite pam_shells.so
auth sufficient pam_unix.so
auth required pam_deny.so此設定的流程:root 直接通過 → 檢查 shell 是否在 /etc/shells → 檢查密碼 → 全部失敗則拒絕。

Figure 7-4: PAM rule execution flow
7.10.2 PAM 設定語法提示#
- 使用
man -k pam_尋找系統上可用的 PAM 模組 - 許多發行版自動產生 PAM 設定檔,直接修改前先閱讀檔案中的註解
/etc/pam.d/other定義沒有專屬設定檔的應用程式的預設設定(通常是拒絕所有)@include語法可載入整個設定檔- 部分模組使用
/etc/security中的額外檔案來設定 per-user 限制
7.10.3 PAM 與密碼#
密碼設定的歷史遺留物:
/etc/login.defs— shadow password 套件的原始設定檔,有 PAM 時很少使用- PAM 設定中的加密演算法設定在
passwordfunction 中
grep password.*unix /etc/pam.d/*設定密碼時,PAM 使用 obscure(檢查密碼強度)和 sha512(加密演算法)等參數。驗證密碼時,pam_unix.so 會自動嘗試猜測加密演算法(透過 libcrypt 函式庫)。
7.11 展望#
本章幾乎完全在 user space 層面討論了系統設定,涵蓋了 logging、使用者管理、時間設定、任務排程與認證等 Linux 系統的核心組成部分。這些內容展示了如何將服務與任務分割成小型、獨立但仍能互動的部分。
下一章將回到 kernel,深入探討 user-space process 及其所消耗的資源。