章 9. 系統技巧

# 章 9. 系統技巧

這裡，描述調配和管理系統的基本技巧，大部分在控制檯操作。

## 9.1. 控制台技巧

有一些工具程式來幫助你的控制台活動。

表格 9.1. 支援控制台活動的程式列表

軟體包 | 流行度 | 大小 | 說明
--- | --- | --- | ---
`mc` | V:41, I:182 | 1590 | 參見 節 1.3, “Midnight Commander (MC)”
`bsdutils` | V:443, I:999 | 334 | `script` (1) 命令來記錄終端會話
`screen` | V:52, I:200 | 991 | VT100/ANSI 終端模擬器混合複用的終端
`tmux` | V:94, I:162 | 1291 | 終端複用的備選方案（使用 “Control-B”代替）
`ripgrep` | V:14, I:42 | 5294 | 在原始碼樹中快速遞迴搜尋字串，並自動過濾
`fzf` | V:8, I:35 | 4983 | 模糊的文本查詢器
`fzy` | V:0.08, I:0.36 | 59 | 模糊的文本查詢器
`rlwrap` | V:1, I:12 | 328 | 具備 readline 特徵的命令列封裝
`ledit` | V:0.5, I:7.7 | 375 | 具備 readline 特徵的命令列封裝
`rlfe` | V:0.04, I:0.49 | 45 | 具備 readline 特徵的命令列封裝

### 9.1.1. 清晰的記錄 shell 活動

簡單地使用 script(1) （參見 節 1.4.9, “記錄shell活動”）記錄 shell 活動會產生一個有控制字元的檔案。這些控制字元可以按下面的方式，使用 col(1) 去掉。

    $ script
    Script started, file is typescript

做些操作……按 `Ctrl-D` 退出 `script`.

    $ col -bx < typescript > cleanedfile
    $ vim cleanedfile

有替代的方式來記錄 shell 活動：

- 使用 `tee` (在 initramfs 的啟動過程中可用)：

      $ sh -i 2>&1 | tee typescript

- 使用 `gnome-terminal` 增加行緩衝，用捲軸檢視。

- 使用 `screen` 和 "`^A H`" (參見 節 9.1.2, “screen 程式”)來進行控制台記錄。

- 使用 `vim` 輸入 "`:terminal`" 進入終端模式。使用 "`Ctrl-W N`" 從終端模式退出到普通模式。使用 "`:w typescript`" 將快取寫到一個檔案。

- 使用 `emacs` 和 "`M-x shell`", "`M-x eshell`", 或 "`M-x term`" 來進入記錄控制台。使用 "`C-x C-w`" 將快取寫到檔案。

### 9.1.2. screen 程式

screen(1) 不但允許一個終端視窗執行多個程序，還允許遠端 shell 程序支援中斷的連線.這裡是一個典型的 screen(1) 使用場景.

1. 登入到一個遠端機器。

2. 在單個控制檯上啟動 `screen`。

3. 使用 `^A c` ("Control-A" 接著 "c")在 `screen` 中建立的視窗執行多個程式.

4. 按 `^A n` ("Control-A" 接著"n")來在多個 `screen` 視窗間轉換.

5. 突然，你需要離開你的終端，但你不想丟掉正在做的工作，而這些工作需要連線來保持。

6. 你可以通過任何方式分離 `screen` 會話。

   - 殘忍地拔掉你的網路連線

   - 輸入 `^A d` ("Control-A" 接著 "d") 並手工從遠端連線退出登入

   - 輸入 `^A DD` ("Control-A" 接著 "DD") 分離 `screen` 並退出登入

7. 你重新登入到同一個遠處主機（即使從不同的終端）。

8. 使用 "`screen -r`" 啟動 `screen`.

9. `screen` 魔術般的重新附上先前所有的 `screen` 視窗和所有在活動執行的程式.

| 提示
對於撥號或者按包計費的網路連線，你可以通過 `screen` 節省連線費用，應為你可以在斷開連線時讓一個程序繼續執行，當你稍後再次連線時重新附上它。

在 `screen` 會話裡,除了指令按鍵外的所有鍵盤輸入都會被髮送到當前視窗。 `screen` 所有指令按鍵是通過 `^A` ("Control-A") 加單個鍵[加任何參數] 來輸入.這裡有一些重要的指令按鍵需要記住。

表格 9.2. screen 鍵繫結列表

鍵綁定功能 | 說明
--- | ---
`^A ?` | 顯示幫助螢幕（顯示鍵繫結）
`^A c` | 建立一個新的視窗並切換到該視窗
`^A n` | 到下一個視窗
`^A p` | 到前一個視窗
`^A 0` | 到 0 號視窗
`^A 1` | 到 1 號視窗
`^A w` | 顯示視窗列表
`^A a` | 作為鍵盤輸入傳送 Ctrl-A 到當前視窗
`^A h` | 把當前視窗的硬拷貝寫到一個檔案
`^A H` | 開始/結束 當前視窗到檔案的記錄
`^A ^X` | 鎖定終端(密碼保護)
`^A d` | 從終端分離 screen 會話
`^A DD` | 分離 screen 會話並退出登入

細節參見 screen(1).

參見 tmux(1) ，瞭解替代命令的功能。

### 9.1.3. 在目錄間遊走

在 節 1.4.2, “定製bash”， 2 個技巧允許快速在目錄間遊走，在 `$CDPATH` 和 `mc` 描述。

如果你使用模糊文本過濾程式，你能夠不輸入精準路徑。對於`fzf` 軟體包，在 `~/.bashrc` 裡面包括下列內容。

    FZF_KEYBINDINGS_PATH=/usr/share/doc/fzf/examples/key-bindings.bash
    if [ -f $FZF_KEYBINDINGS_PATH ]; then
      . $FZF_KEYBINDINGS_PATH
    fi

例如：

- 你能夠最小化的操作跳入非常深的子目錄。你首先輸入 "`cd **`" 後按 `Tab`。然後你將被提示候選路徑。輸入部分路徑字串，比如 `s/d/b foo`，將會縮窄候選路徑。通過有游標和回車鍵的 `cd`，你選擇將要使用的路徑。

- 你可以用最小化的操作，從命令歷史裡面選擇一個命令。在命令列提示符下按 `Ctrl-R` 。然後你將被提示候選的命令。輸入部分命令字串，比如 `vim d`，將會縮窄候選項。使用游標和回車鍵選擇將要使用的命令。

### 9.1.4. Readline 封裝

一些命令，比如 `/usr/bin/dash`，它缺少命令列歷史編輯能力，但在 `rlwrap` 或它的等價物下執行就能夠透明的增加這樣的功能。

     $ rlwrap dash -i

這提供一個便利平臺來測試 `dash` 的細微之處，使用類似 `bash` 的友好環境。

### 9.1.5. 掃描原始碼樹

在 `ripgrep` 軟體包中的 rg(1) 命令，在掃描原始碼樹的典型場景中，提供了一個比 grep(1) 命令更快速的替代。它充分利用了現代多核 CPU，並自動使用適當的過濾器來忽略一些檔案。

## 9.2. 定製vim

在你通過 節 1.4.8, “使用 vim” 學習基本的vim(1) 後,請閱讀 Bram Moolenaar 的"Seven habits of effective text editing (2000)" 來理解 `vim` 應當怎樣被使用。

### 9.2.1. 用內部特性定製 vim

`vim` 的行為能夠被顯著的改變，通過 `Ex`-模式 的命令，啟用它的內部特性，比如 "`set ...`" 來設定 vim 選項。

這些 `Ex`-模式 的命令，能夠在使用者的 vimrc 檔案裡面包括，傳統的 "`~/.vimrc`" 或 git 友好的 "`~/.vim/vimrc`"。這裡有一個非常簡單的例子[2]：

    """ Generic baseline Vim and Neovim configuration (~/.vimrc)
    """   - For NeoVim, use "nvim -u ~/.vimrc [filename]"
    """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
    let mapleader = ' '             " :h mapleader
    """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
    set nocompatible                " :h 'cp -- sensible (n)vim mode
    syntax on                       " :h :syn-on
    filetype plugin indent on       " :h :filetype-overview
    set encoding=utf-8              " :h 'enc (default: latin1) -- sensible encoding
    """ current vim option value can be verified by :set encoding?
    set backspace=indent,eol,start  " :h 'bs (default: nobs) -- sensible BS
    set statusline=%<%f%m%r%h%w%=%y[U+%04B]%2l/%2L=%P,%2c%V
    set listchars=eol:¶,tab:⇄\ ,extends:↦,precedes:↤,nbsp:␣
    set viminfo=!,'100,<5000,s100,h " :h 'vi -- bigger copy buffer etc.
    """ Pick "colorscheme" from blue darkblue default delek desert elflord evening
    """ habamax industry koehler lunaperche morning murphy pablo peachpuff quiet ron
    """ shine slate torte zellner
    colorscheme industry
    """ don't pick "colorscheme" as "default" which may kill SpellUnderline settings
    set scrolloff=5                 " :h 'scr -- show 5 lines around cursor
    set laststatus=2                " :h 'ls (default 1)  k
    """ boolean options can be unset by prefixing "no"
    set ignorecase                  " :h 'ic
    set smartcase                   " :h 'scs
    set autoindent                  " :h 'ai
    set smartindent                 " :h 'si
    set nowrap                      " :h 'wrap
    "set list                        " :h 'list (default nolist)
    set noerrorbells                " :h 'eb
    set novisualbell                " :h 'vb
    set t_vb=                       " :h 't_vb -- termcap visual bell
    set spell                       " :h 'spell
    set spelllang=en_us,cjk         " :h 'spl -- english spell, ignore CJK
    set clipboard=unnamedplus       " :h 'cb -- cut/copy/paste with other app
    set hidden                      " :h 'hid
    set autowrite                   " :h 'aw
    set timeoutlen=300              " :h 'tm

`vim` 的鍵盤對映能夠在使用者的 vimrc 檔案裡面修改。例如：

| 注意
沒有非常好的理由，請不要嘗試改變預設的鍵繫結。

    """ Popular mappings (imitating LazyVim etc.)
    """ Window moves without using CTRL-W which is dangerous in INSERT mode
    nnoremap <C-H> <C-W>h
    nnoremap <C-J> <C-W>j
    nnoremap <C-K> <C-W>k
    silent! nnoremap <C-L> <C-W>l
    """ Window resize
    nnoremap <C-LEFT> <CMD>vertical resize -2<CR>
    nnoremap <C-DOWN> <CMD>resize -2<CR>
    nnoremap <C-UP> <CMD>resize +2<CR>
    nnoremap <C-RIGHT> <CMD>vertical resize +2<CR>
    """ Clear hlsearch with <ESC> (<C-L> is mapped as above)
    nnoremap <ESC> <CMD>noh<CR><ESC>
    inoremap <ESC> <CMD>noh<CR><ESC>
    """ center after jump next
    nnoremap n nzz
    nnoremap N Nzz
    """ fast "jk" to get out of INSERT mode (<ESC>)
    inoremap  jk <CMD>noh<CR><ESC>
    """ fast "<ESC><ESC>" to get out of TERM mode (CTRL-\ CTRL-N)
    tnoremap <ESC><ESC> <C-\><C-N>
    """ fast "jk" to get out of TERM mode (CTRL-\ CTRL-N)
    tnoremap jk <C-\><C-N>
    """ previous/next trouble/quickfix item
    nnoremap [q <CMD>cprevious<CR>
    nnoremap ]q <CMD>cnext<CR>
    """ buffers
    nnoremap <S-H> <CMD>bprevious<CR>
    nnoremap <S-L> <CMD>bnext<CR>
    nnoremap [b <CMD>bprevious<CR>
    nnoremap ]b <CMD>bnext<CR>
    """ Add undo break-points
    inoremap  , ,<C-G>u
    inoremap  . .<C-G>u
    inoremap  ; ;<C-G>u
    """ save file
    inoremap <C-S> <CMD>w<CR><ESC>
    xnoremap <C-S> <CMD>w<CR><ESC>
    nnoremap <C-S> <CMD>w<CR><ESC>
    snoremap <C-S> <CMD>w<CR><ESC>
    """ better indenting
    vnoremap < <gv
    vnoremap > >gv
    """ terminal (Somehow under Linux, <C-/> becomes <C-_> in Vim)
    nnoremap <C-_> <CMD>terminal<CR>
    "nnoremap <C-/> <CMD>terminal<CR>
    """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
    if ! has('nvim')
    """ Toggle paste mode with <SPACE>p for Vim (no need for Nvim)
    set pastetoggle=<leader>p
    """ nvim default mappings for Vim.  See :h default-mappings in nvim
    """ copy to EOL (no delete) like D for d
    noremap Y y$
    """ sets a new undo point before deleting
    inoremap <C-U> <C-G>u<C-U>
    inoremap <C-W> <C-G>u<C-W>
    """ <C-L> is re-purposed as above
    """ execute the previous macro recorded with Q
    nnoremap Q @@
    """ repeat last substitute and *KEEP* flags
    nnoremap & :&&<CR>
    """ search visual selected string for visual mode
    xnoremap * y/\V<C-R>"<CR>
    xnoremap # y?\V<C-R>"<CR>
    endif

為了使上面的按鍵繫結正確地執行，終端程式需要配置：`Backspace`-鍵產生 "ASCII DEL"、`Delete`-鍵產生 "Escape sequence"。

其它雜項配置能夠在使用者的 vimrc 檔案裡面修改。例如：

    """ Use faster 'rg' (ripgrep package) for :grep
    if executable("rg")
      set grepprg=rg\ --vimgrep\ --smart-case
      set grepformat=%f:%l:%c:%m
    endif
    """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
    """ Retain last cursor position :h '"
    augroup RetainLastCursorPosition
      autocmd!
      autocmd BufReadPost *
        \ if line("'\"") > 0 && line ("'\"") <= line("$") |
        \   exe "normal! g'\"" |
        \ endif
    augroup END
    """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
    """ Force to use underline for spell check results
    augroup SpellUnderline
      autocmd!
      autocmd ColorScheme * highlight SpellBad term=Underline gui=Undercurl
      autocmd ColorScheme * highlight SpellCap term=Underline gui=Undercurl
      autocmd ColorScheme * highlight SpellLocal term=Underline gui=Undercurl
      autocmd ColorScheme * highlight SpellRare term=Underline gui=Undercurl
    augroup END
    """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
    """ highlight tailing spaces except when typing as red (set after colorscheme)
    highlight TailingWhitespaces ctermbg=red guibg=red
    """ \s\+     1 or more whitespace character: <Space> and <Tab>
    """ \%#\@<!  Matches with zero width if the cursor position does NOT match.
    match TailingWhitespaces /\s\+\%#\@<!$/

### 9.2.2. 用外部軟體包定製 vim

下面能夠發現有趣的外部外掛軟體包：

- Vim - 無所不在的文本編輯器 -- Vim 和 vim 指令碼的官方上游站點

- VimAwsome -- Vim 外掛列表

- vim-scripts -- Debian 軟體包：一個 vim 指令碼的收集

vim-scripts 軟體包裡面的外掛軟體包，能夠使用使用者的 vimrc 檔案啟用。比如：

    packadd! secure-modelines
    packadd! winmanager
    " IDE-like UI for files and buffers with <space>w
    nnoremap <leader>w         :WMToggle<CR>

新的原生 Vim 軟體包系統同 "`git`" 和 "`git submodule`" 順利的工作。一個這樣的配置例子能夠在 我的 git 倉庫: dot-vim 找到。本質上是這樣做的：

- 通過使用"`git`"和"`git submodule`"，最新的擴充套件軟體包，比如說"`name`"，會被放到 `~/.vim/pack/*/opt/name` 和類似的地方。

- 通過增加 `:packadd! name` 行到使用者的 vimrc 檔案，這些軟體包被放到 `runtimepath`。

- Vim 在它的初始化時載入這些軟體包到 `runtimepath`。

- 在它初始化的最後，安裝文件的標籤被更新，使用 "`helptags ALL`"。

更多資訊，請使用 "`vim --startuptime vimstart.log`" 啟動 `vim` 來檢查實際的執行順序和每一個步驟消耗的時間。

是相當迷惑的看到這麼多的方式[3] 來管理和載入這些外部的軟體包到 `vim`。檢查原始的資訊是最好的方法。

表格 9.3. `vim` 的初始化資訊

按鍵 | 資訊
--- | ---
`:help package` | 解釋 vim 軟體包機制
`:help runtimepath` | 解釋 `runtimepath` 機制
`:version` | 內部狀態，包括 vimrc 檔案的候選
`:echo $VIM` | 環境變數 "`$VIM`" 用來定位 vimrc 檔案的路徑
`:set runtimepath?` | 列出用來搜尋所有執行時支援檔案的目錄
`:echo $VIMRUNTIME` | 環境變數 "`$VIMRUNTIME`" 用來定位大量系統提供的執行時支援檔案

## 9.3. 資料記錄和展示

### 9.3.1. 日誌後臺背景程式（daemon）

許多傳統的程式在"`/var/log/`" 目錄下用文本檔案格式記錄它們的活動.

在一個產生很多日誌檔案的系統上，用 logrotate(8)來簡化日誌檔案的管理。

許多新的程式使用 systemd-journald(8) 日誌服務的二進位制檔案格式來記錄它們的活動，在"`/var/log/journal`" 目錄下。

你能夠從 shell 指令碼記錄資料到 systemd-journald(8) 日誌，使用 systemd-cat(1) 命令。

參見 節 3.5, “系統訊息” 和 節 3.4, “核心訊息”.

### 9.3.2. 日誌分析

這裡是主要的日誌分析軟體 ("`~Gsecurity::log-analyzer`" 在 aptitude(8) 中).

表格 9.4. 系統日誌分析軟體列表

軟體包 | 流行度 | 大小 | 說明
--- | --- | --- | ---
`fail2ban` | V:101, I:111 | 2192 | 禁用造成多個認證錯誤的 IP
`logwatch` | V:9, I:11 | 2436 | 用 Perl 寫的日誌分析軟體，有好的輸出
`awstats` | V:5.5, I:8.5 | 6934 | 強大和特性全面的 web 伺服器日誌分析
`analog` | V:3, I:85 | 3739 | web 伺服器日誌分析
`sarg` | V:0.74, I:0.81 | 863 | 生成 squid 分析報告
`pflogsumm` | V:1.5, I:3.8 | 173 | Postfix 日誌條目概要
`fwlogwatch` | V:0.11, I:0.17 | 487 | 防火牆日誌分析軟體
`squidview` | V:0.03, I:0.46 | 224 | 監控和分析 squid access.log 檔案
`swatch` | V:0.09, I:0.30 | 99 | 有正規表達式、高亮和曲線的日誌檔案檢視器
`crm114` | V:0.07, I:0.34 | 1371 | Controllable Regex Mutilator 和垃圾郵件過濾 (CRM114)
`icmpinfo` | V:0.01, I:0.33 | 42 | 解釋 ICMP 資訊

| 注意
CRM114 提供語言架構來寫模糊 過濾器，使用了 TRE 正規表達式庫 。它主要在垃圾郵件過濾器中使用，但也能夠用於日誌分析。

### 9.3.3. 定製文字資料的顯示

儘管例如 more(1) 和 less(1) 這樣的分頁程式（參見 節 1.4.5, “文件內容查看”）和用於高亮和格式的自定義工具（參見 節 11.1.8, “高亮並格式化純文字資料”）可以漂亮地顯示文字資料，但通用的編輯器 （參見 節 1.4.6, “文字編輯器”）是用途最廣的，且可定製性最高。

| 提示
對於 vim(1) 和它的分頁模式別名 view(1)，“`:set hls`” 可以啟用高亮搜尋。

### 9.3.4. 定製時間和日期的顯示

“`ls -l`” 命令預設的時間和日期顯示格式取決於語言環境（相關的值參見 節 1.2.6, “時間戳”）。“`$LANG`” 變數將被首先考慮，但它會被匯出的 “`$LC_TIME`” 或 "`$LC_ALL`"環境變數覆蓋。

每個語言環境實際的預設顯示格式取決於所使用的 C 標準庫的版本（`libc6` 軟體包），也就是說，不同的 Debian 發行版有不同的預設情況。對於 iso-formates，參見 ISO 8601。

如果你真的想自定義超出語言環境的時間和日期顯示格式，你應該通過 “`--time-style`” 參數或 “`$TIME_STYLE`” 的值來設定時間樣式值（參見ls(1)、date(1)、“`info coreutils 'ls invocation'`”）。

表格 9.5. 使用 時間樣式值 的"`ls -l`" 命令的時間和日期的顯示例子

時間樣式值 | 語言環境 | 時間和日期顯示
--- | --- | ---
`iso` | 任何值 | `01-19 00:15`
`long-iso` | 任何值 | `2009-01-19 00:15`
`full-iso` | 任何值 | `2009-01-19 00:15:16.000000000 +0900`
`locale` | `C` | `Jan 19 00:15`
`locale` | `en_US.UTF-8` | `Jan 19 00:15`
`locale` | `es_ES.UTF-8` | `ene 19 00:15`
`+%d.%m.%y %H:%M` | 任何值 | `19.01.09 00:15`
`+%d.%b.%y %H:%M` | `C` 或 `en_US.UTF-8` | `19.Jan.09 00:15`
`+%d.%b.%y %H:%M` | `es_ES.UTF-8` | `19.ene.09 00:15`

| 提示

你可以使用命令別名以避免在命令列中輸入長的選項，（參見 節 1.5.9, “指令別名”）：

    alias ls='ls --time-style=+%d.%m.%y %H:%M'

### 9.3.5. shell 中 echo 的顏色

大部分現代終端的 shell 中 echo 能夠使用 ANSI 轉義字元來顯示顏色（參見 “`/usr/share/doc/xterm/ctlseqs.txt.gz`”）。

嘗試下列例子

    $ RED=$(printf "\x1b[31m")
    $ NORMAL=$(printf "\x1b[0m")
    $ REVERSE=$(printf "\x1b[7m")
    $ echo "${RED}RED-TEXT${NORMAL} ${REVERSE}REVERSE-TEXT${NORMAL}"

### 9.3.6. 有顏色輸出的指令

在互動式的環境下，指令的輸出帶顏色，能夠給檢查指令的輸出帶來便利。 我在我的"`~/.bashrc`"里加入了下面內容.

    if [ "$TERM" != "dumb" ]; then
        eval "`dircolors -b`"
        alias ls='ls --color=always'
        alias ll='ls --color=always -l'
        alias la='ls --color=always -A'
        alias less='less -R'
        alias ls='ls --color=always'
        alias grep='grep --color=always'
        alias egrep='egrep --color=always'
        alias fgrep='fgrep --color=always'
        alias zgrep='zgrep --color=always'
    else
        alias ll='ls -l'
        alias la='ls -A'
    fi

在互動式指令中，使用別名來限制顏色的影響範圍。匯出環境變數 "`export GREP_OPTIONS='--color=auto'`" 也有好處，這樣能夠讓 less(1) 之類的頁面程式看到顏色。當使用管道到其它指令時，你想去掉顏色，上面列子 "`~/.bashrc`" 中的內容，可以使用 "`--color=auto`" 代替.

| 提示
在互動式的環境中，通過"`TERM=dumb bash`"呼叫 shell ，你能夠關閉這些顏色別名。

### 9.3.7. 記錄編輯器複雜的重複操作動作

你能夠記錄編輯器複雜的重複操作動作。

對於 Vim,請按下面操作。

- "`qa`": 開始記錄輸入字元到有名字的暫存器 "`a`".

- … 編輯器操作

- "`q`": 結束記錄輸入的字元。

- "`@a`":執行暫存器 "`a` 的內容".

對於 Emacs, 請按下面操作。

- "`C-x (`": 開始定義一個鍵盤巨集.

- … 編輯器操作

- "`C-x )`":結束定義一個鍵盤巨集.

- "`C-x e`": 執行一個鍵盤巨集.

### 9.3.8. 記錄 X 應用程式的圖形

有少量方法可以記錄 X 應用程式的影象，包括`xterm` 顯示。

表格 9.6. 圖形影象處理工具列表

軟體包 | 流行度 | 大小 | 螢幕 | 指令
--- | --- | --- | --- | ---
`gnome-screenshot` | V:12, I:101 | 1115 | Wayland | GNOME 下的截圖程式
`flameshot` | V:8, I:18 | 3534 | Wayland | 強大的截圖程式
`gimp` | V:44, I:216 | 32791 | Wayland + X | GUI 選單中的截圖
`x11-apps` | V:30, I:445 | 2461 | X | xwd(1)
`imagemagick` | V:9, I:278 | 79 | X | import(1)
`scrot` | V:4, I:50 | 144 | X | scrot(1)

### 9.3.9. 記錄組態檔案的變更

有特定的工具可以通過 DVCS 的幫助來記錄配置檔案的變更和在 Btrfs 上製作系統快照。

表格 9.7. 記錄配置歷史的軟體包列表

軟體包 | 流行度 | 大小 | 說明
--- | --- | --- | ---
`etckeeper` | V:24, I:27 | 157 | 使用 Git（預設）、Mercurial 或 GNU Bazaar 來儲存配置檔案和它們的後設資料
`timeshift` | V:8, I:13 | 4481 | 使用 rsync 或 BTRFS 快照的系統恢復工具
`snapper` | V:6.1, I:8.1 | 2396 | Linux 檔案系統快照管理工具

你也可以考慮本地指令碼 節 10.2.3, “備份技巧” 方案。

## 9.4. 監控、控制和啟動程式活動

程式活動能夠使用特殊的工具監控和控制。

表格 9.8. 監控和控制程式活動工具列表

軟體包 | 流行度 | 大小 | 說明
--- | --- | --- | ---
`coreutils` | V:911, I:1000 | 17994 | nice(1): 用指定的排程優先權執行一個程式
`bsdutils` | V:443, I:999 | 334 | renice(1): 調整一個目前在執行的程序的排程優先權值
`procps` | V:834, I:997 | 2389 | "`/proc`" 檔案系統工具: ps(1), top(1), kill(1), watch(1), …
`psmisc` | V:404, I:727 | 950 | "`/proc`" 檔案系統工具: killall(1), fuser(1), peekfd(1), pstree(1)
`time` | V:6, I:81 | 148 | time(1):執行一個程式，並從時間消耗方面來報告系統資源的使用
`sysstat` | V:120, I:166 | 1904 | sar(1), iostat(1), mpstat(1), …: linux 系統性能工具
`isag` | V:0.1, I:3.3 | 109 | sysstat 的互動式的系統活動圖
`lsof` | V:445, I:949 | 492 | lsof(8): 使用 "`-p`" 選項列出被一個系統程序開啟的檔案
`strace` | V:10, I:102 | 4393 | strace(1):跟蹤系統呼叫和訊號
`ltrace` | V:1, I:12 | 420 | ltrace(1): 跟蹤庫呼叫
`xtrace` | V:0.04, I:0.70 | 342 | xtrace(1):跟蹤 X11 客戶端和伺服器端之間的通訊
`powertop` | V:33, I:224 | 696 | powertop(1):系統能耗使用資訊
`cron` | V:922, I:997 | 247 | 根據 cron(8) 後臺背景程式（daemon）的排程執行一個程序
`anacron` | V:419, I:476 | 110 | 用於非整天 24 小時執行系統的指令計劃，類 cron
`at` | V:73, I:98 | 158 | at(1) 或 batch(1): 在一個特定的時間執行任務或在某一系統負載下執行

| 提示
`procps` 包提供了非常基礎的監控、控制程式活動功能和啟動程式功能。你應當把他們全部學會。

### 9.4.1. 程序耗時

顯示 指令呼叫程序的時間消耗。

    # time some_command >/dev/null
    real    0m0.035s       # time on wall clock (elapsed real time)
    user    0m0.000s       # time in user mode
    sys     0m0.020s       # time in kernel mode

### 9.4.2. 排程優先順序

程序的排程優先順序是被一個程序優先順序值控制。

表格 9.9. 排程優先順序值列表

程序優先順序值 | 排程優先順序
--- | ---
19 | 最低優先順序程序
0 | 非常高的普通使用者優先順序程序
-20 | root 使用者非常高的優先順序程序

    # nice  -19 top                                      # very nice
    # nice --20 wodim -v -eject speed=2 dev=0,0 disk.img # very fast

在某些情況下，極端的程序優先順序值會對系統造成傷害。小心使用這個指令。

### 9.4.3. ps 指令

在 Debian 系統上的 ps(1) 指令同時支援 BSD 和 SystemV 特徵，有助於識別靜態的程序活動。

表格 9.10. ps 指令樣式列表

樣式 | 典型的指令 | 特徵
--- | --- | ---
BSD | `ps aux` | 顯示 %CPU %MEM
System V | `ps -efH` | 顯示 PPID

對於殭屍（死了的）子程序，你能夠通過 "`PPID`" 欄位的父程序 ID 來殺死它們。

pstree(1) 指令顯示程式樹。

### 9.4.4. top 指令

Debian 系統上的 top(1) 擁有豐富的特徵，有助於識別程序有趣的動態行為。

它是一個互動式的全屏程式。你可以通過按"h"鍵來得到它的使用幫助，按"q"鍵來終止該程式。

### 9.4.5. 列出被一個程序開啟的檔案

你能夠通過一個程序 ID(PID)來列出該程序所有開啟的檔案，例如，PID 為 1 的程序，使用下面的方式。

    $ sudo lsof -p 1

PID=1 通常用於 `init` 程式.

### 9.4.6. 跟蹤程式活動

你能夠跟蹤程式活動，使用strace(1), ltrace(1), xtrace(1) 來跟蹤系統呼叫和訊號、庫呼叫、X11 客戶端和伺服器端之間的通訊。

跟蹤 `ls` 指令的系統呼叫。

    $ sudo strace ls

| 提示
使用在 /usr/share/doc/strace/examples/ 中發現的 strace-graph 指令碼來生成一個好看的樹形檢視

### 9.4.7. 識別使用檔案和套接字的程序

你可以通過 fuser(1) 來識別出使用檔案的程序，例如，用下面的方式識別出 "`/var/log/mail.log`" 由哪個程序開啟。

    $ sudo fuser -v /var/log/mail.log
                         USER        PID ACCESS COMMAND
    /var/log/mail.log:   root       2946 F.... rsyslogd

你可以看到 "`/var/log/mail.log`" 是由 rsyslogd(8) 指令開啟並寫入。

你可以通過 fuser(1) 來識別出使用套接字的程序，例如，用下面的方式識別出 "`smtp/tcp`" 由哪個程序開啟。

    $ sudo fuser -v smtp/tcp
                         USER        PID ACCESS COMMAND
    smtp/tcp:            Debian-exim   3379 F.... exim4

現在你知道你的系統執行 exim4(8) 來處理連線到 SMTP 埠 (25)的 TCP 連線.

### 9.4.8. 使用固定間隔重複一個指令

watch(1) 使用固定間隔重新執行一個指令，並全螢幕顯示輸出。

    $ watch w

顯示哪些人登入到系統，每 2 秒鐘更新一次。

### 9.4.9. 使用檔案迴圈來重複一個指令

通過匹配某些條件的檔案來迴圈重複一個指令，有幾種方法，例如，匹配全域性模式"`*.ext`".

- Shell 迴圈方式(參見 節 12.1.4, “shell 迴圈”):

    for x in *.ext; do if [ -f "$x"]; then command "$x" ; fi; done

- find(1) 和 xargs(1) 聯合:

    find . -type f -maxdepth 1 -name '*.ext' -print0 | xargs -0 -n 1 command

- find(1) 使用 "`-exec`" 選項並執行指令:

    find . -type f -maxdepth 1 -name '*.ext' -exec command '{}' \;

- find(1) 使用 "`-exec`" 選項並執行一個短的 shell 指令碼:

    find . -type f -maxdepth 1 -name '*.ext' -exec sh -c "command '{}' && echo 'successful'" \;

上面的列子確保適當處理怪異的檔名（如包含空格）。 find(1) 更多高階的用法，參見 節 10.1.5, “查詢檔案的語法”.

### 9.4.10. 從 GUI 啟動一個程式

對於 指令列介面（command-line interface，CLI），`$PATH` 環境變數所指定的目錄中第一個匹配相應名稱的程式會被執行。參見 節 1.5.3, “"`$PATH`" 變數”。

對於遵從 freedesktop.org 標準的 圖形使用者介面（graphical user interface，GUI），`/usr/share/applications/` 目錄中的 `*.desktop` 檔案給每個程式的 GUI 選單顯示提供了必要的屬性。遵從Freedesktop.org xdg 菜單系統的每一個軟體包，通過 "/usr/share/applications/"下 "*.desktop"提供的資料來安裝它的選單。 遵從 Freedesktop.org 標準的現代桌面環境，用 xdg-utils 軟體包利用這些資料生成它們的選單。參見"/usr/share/doc/xdg-utils/README"。

舉個例子，`chromium.desktop` 檔案中為 “Chromium 網路瀏覽器” 定義了相關屬性，例如程式名 “Name”，程式執行路徑和參數 “Exec”，所使用的圖示 “Icon” 等等（參見 桌面調配項規範）。檔案內容如下：

    [Desktop Entry]
    Version=1.0
    Name=Chromium Web Browser
    GenericName=Web Browser
    Comment=Access the Internet
    Comment[fr]=Explorer le Web
    Exec=/usr/bin/chromium %U
    Terminal=false
    X-MultipleArgs=false
    Type=Application
    Icon=chromium
    Categories=Network;WebBrowser;
    MimeType=text/html;text/xml;application/xhtml_xml;x-scheme-handler/http;x-scheme-handler/https;
    StartupWMClass=Chromium
    StartupNotify=true

這是一個較為簡單的說明。`*.desktop` 檔案像下面那樣被搜尋。

桌面環境設定 `$XDG_DATA_HOME` 和 `$XDG_DATA_DIR` 環境變數。舉個例子，在 GNOME 中：

- 未設定 `$XDG_DATA_HOME`。（將使用預設值 `$HOME/.local/share`。）

- `$XDG_DATA_DIRS` 被設定為 `/usr/share/gnome:/usr/local/share/:/usr/share/`。

基準目錄（參見 XDG Base Directory Specification）和`應用程式`目錄如下所示。

- `$HOME/.local/share/` → `$HOME/.local/share/applications/`

- `/usr/share/gnome/` → `/usr/share/gnome/applications/`

- `/usr/local/share/` → `/usr/local/share/applications/`

- `/usr/share/` → `/usr/share/applications/`

`*.desktop` 檔案將按照這個順序在這些 `applications` 目錄中進行搜尋。

| 提示
要建立一個使用者自定義的 GUI 選單項，需要在 `$HOME/.local/share/applications/` 目錄中新增一個 `*.desktop` 檔案。

| 提示
"`Exec=...`" 行不會由 shell 解析。如果需要設定環境變數，使用 env(1) command。

| 提示
相似地，如果在這些基準目錄下的 `autostart` 目錄中建立了一個 `*.desktop` 檔案，則 `*.desktop` 檔案中指定的程式會在桌面環境啟動時自動執行。參見 Desktop Application Autostart Specification。

| 提示
相似地，如果在 `$HOME/Desktop` 目錄中建立了一個 `*.desktop` 檔案並且桌面環境被調配為支援桌面圖示啟動器功能，則點選圖示時指定的程式會被執行。請注意，`$HOME/Desktop` 目錄的實際名稱與語言環境有關。參見 xdg-user-dirs-update(1)。

### 9.4.11. 自定義被啟動的程式

一些程式會被另一個程式自動啟動。下面是自定義該過程的方法。

- 應用程式調配選單：

  - GNOME 桌面：“設定” → “應用程式” → “預設應用程式”

  - KDE 桌面：“應用開始選單”→ “設定” → “系統設定” → “應用程式” → “預設應用程式”

  - Iceweasel 瀏覽器：“編輯” → “首選項” → “應用程式”

  - mc(1)：“`/etc/mc/mc.ext`”

- 例如 “`$BROWSER`”、“`$EDITOR`”、“`$VISUAL`” 和 “`$PAGER`” 這樣的環境變數（參見 environ(7)）

- 用於例如 “`editor`”、“`view`”、“`x-www-browser`”、“`gnome-www-browser`” 和 “`www-browser`” 這樣的程式的 update-alternatives(1) 系統（參見 節 1.4.7, “設置預設文本編輯器”）

- “`~/.mailcap`” 和 “`/etc/mailcap`” 檔案的內容關聯了程式的 MIME 型別（參見 mailcap(5)）

- “`~/.mime.types`” 和 “`/etc/mime.types`” 檔案的內容關聯了 MIME 型別的副檔名（參見 run-mailcap(1)）

| 提示
update-mime(8) 會更新 "`/etc/mailcap`" 檔案，期間會用到 "`/etc/mailcap.order`" 檔案 (參見 mailcap.order(5)).

| 提示
`debianutils` 軟體包提供 sensible-browser(1)、sensible-editor(1) 和 sensible-pager(1)，它們可以分別對要呼叫的編輯器、分頁程式和網路瀏覽器作出明智的選擇。我建議你閱讀那些 shell 指令碼。

| 提示

為了在 GUI（圖形使用者介面）下執行例如 `mutt` 這樣的控制台應用程式來作為你的首選應用程式，你應該像下面那樣建立一個 GUI（圖形使用者介面）應用程式並設定 “`/usr/local/bin/mutt-term`” 為你想要啟動的首選應用程式。

    # cat /usr/local/bin/mutt-term <<EOF
    #!/bin/sh
    gnome-terminal -e "mutt \$@"
    EOF
    # chmod 755 /usr/local/bin/mutt-term

### 9.4.12. 殺死一個程序

使用 kill(1) 通過程序 ID 來殺死（傳送一個訊號）一個程序。

使用 killall(1) 或 pkill(1) 通過程序命令的名字或其它屬性來做同樣的事情。

表格 9.11. kill 指令常用訊號列表

訊號值 | 訊號名 | 操作 | 註釋
--- | --- | --- | ---
0 | --- | 沒有訊號傳送(參見 kill(2)) | 檢查程序是否執行
1 | SIGHUP | 終止程序 | 從終端斷開連線（訊號 掛起）
2 | SIGINT | 終止程序 | 從鍵盤中斷 (`CTRL-C`)
3 | SIGQUIT | 終止程序並觸發 dump core | 從鍵盤退出 (`CTRL-\`)
9 | SIGKILL | 終止程序 | 不可阻塞的 kill 訊號
15 | SIGTERM | 終止程序 | 可被阻塞的終止訊號

### 9.4.13. 單次任務時間安排

執行 at(1) 指令來安排一次性的工作。

    $ echo 'command -args'| at 3:40 monday

### 9.4.14. 定時任務安排

使用 cron(8) 來進行定時任務安排。參見 crontab(1) 和 crontab(5).

你能夠作為一個普通使用者定時執行一個程序，比如， `foo` 使用 "`crontab -e`" 指令建立一個 crontab(5) 的檔案 "`/var/spool/cron/crontabs/foo`"。

這裡是一個 crontab(5) 檔案的列子。

    # use /usr/bin/sh to run commands, no matter what /etc/passwd says
    SHELL=/bin/sh
    # mail any output to paul, no matter whose crontab this is
    MAILTO=paul
    # Min Hour DayOfMonth Month DayOfWeek command (Day... are OR'ed)
    # run at 00:05, every day
    5  0  *  * *   $HOME/bin/daily.job >> $HOME/tmp/out 2>&1
    # run at 14:15 on the first of every month -- output mailed to paul
    15 14 1  * *   $HOME/bin/monthly
    # run at 22:00 on weekdays(1-5), annoy Joe. % for newline, last % for cc:
    0 22 *   * 1-5 mail -s "It's 10pm" joe%Joe,%%Where are your kids?%.%%
    23 */2 1 2 *   echo "run 23 minutes after 0am, 2am, 4am ..., on Feb 1"
    5  4 *   * sun echo "run at 04:05 every Sunday"
    # run at 03:40 on the first Monday of each month
    40 3 1-7 * *   [ "$(date +%a)" == "Mon" ] && command -args

| 提示
對那些非連續執行的系統，安裝 `anacron` 軟體包來定時執行週期性的指令，指令在接近機器啟動的時間執行，並允許有特定的時間間隔。參見 anacron(8) 和 anacrontab(5).

| 提示
對於定時系統維護指令碼，你能夠以root 帳號定時執行，把這類指令碼放入 "`/etc/cron.hourly/`", "`/etc/cron.daily/`", "`/etc/cron.weekly/`", 或 "`/etc/cron.monthly/`". 這些指令碼的執行時間，可以通過 "`/etc/crontab`" 和 "`/etc/anacrontab`" 來定製。

`cron` 後臺守護程序（daemon）不存在時，Systemd 也有按時間計劃執行程式的低階能力。例如， `/lib/systemd/system/apt-daily.timer` 和 `/lib/systemd/system/apt-daily.service` 建立每天的 apt 下載行動。參見 systemd.timer(5) 。

### 9.4.15. 基於事件的計劃任務

Systemd 能夠執行計劃程式，不僅基於時間事件，還能夠基於掛載事件。參見 節 10.2.3.3, “時間事件觸發的備份” 和 節 10.2.3.2, “掛載事件觸發的備份” 的例子。

### 9.4.16. Alt-SysRq 鍵

按 Alt-SysRq (PrtScr)組合鍵跟一個字母按鍵，進行不可思議的系統應急控制。

表格 9.12. 著名的 SAK 命令鍵列表

Alt-SysRq 之後的鍵 | 行為描述
--- | ---
`k` | kill 殺死在當前虛擬控制台上的所有程序 (SAK)
`s` | sync 所有已經掛載的檔案系統來避免資料損壞
`u` | 重新以只讀方式掛載所有已掛載的檔案系統 (umount)
`r` | 在 X 崩潰後，從 raw 模式恢復鍵盤

更多資訊參見 Linux 核心使用者和管理員手冊 » Linux Magic System Request Key Hacks

| 提示
從 SSH 終端等，你能夠通過向 "`/proc/sysrq-trigger`" 寫入內容來使用 Alt-SysRq 特性。例如，從 root shell 提示字元執行 "`echo s > /proc/sysrq-trigger; echo u > /proc/sysrq-trigger`" 來 syncs 和 umounts 所有已掛載的檔案系統。

目前(2021) Debian amd64 Linux 核心為 `/proc/sys/kernel/sysrq=438=0b110110110`:

- 2 = 0x2 - 啟用控制台日誌級別控制 (開啟)

- 4 = 0x4 - 啟用鍵盤控制 (SAK, unraw) (開啟)

- 8 = 0x8 - 啟用程序除錯轉儲（debugging dumps of processes）等。（關閉）

- 16 = 0x10 - 啟用 sync 命令(開啟)

- 32 = 0x20 - 啟用只讀重新掛載（開啟）

- 64 = 0x40 - 啟用程序訊號 (term, kill, oom-kill) (關閉)

- 128 = 0x80 - 允許重啟、關閉電源（開啟）

- 256 = 0x100 - 允許調整所有 RT（即時） 任務優先順序（開啟）

## 9.5. 系統維護技巧

### 9.5.1. 誰在系統裡？

你可以通過下面的方法檢查誰登入在系統裡。

- who(1) 顯示誰登入在系統裡面。

- w(1) 顯示誰登入在系統裡面，他們在做什麼。

- last(1) 顯示使用者最後登入的列表。

- lastb(1) 顯示使用者最後錯誤登入的列表。

| 提示
"`/var/run/utmp`" 和 "`/var/log/wtmp`" 儲存這樣的使用者資訊。參見 login(1) 和 utmp(5).

### 9.5.2. 警告所有人

你可以通過下面的方式使用 wall(1) 給登入系統的每一個人傳送資訊。

    $ echo "We are shutting down in 1 hour" | wall

### 9.5.3. 硬體識別

對於 PCI 類裝置(AGP, PCI-Express, CardBus, ExpressCard 等), 一開始就使用 lspci(8) (也許加上 "`-nn`" 選項) 進行硬體識別比較好。

此外，你可以通過閱讀 "`/proc/bus/pci/devices`" 裡面的內容或瀏覽"`/sys/bus/pci`" 下面的目錄樹來進行硬體識別(參見 節 1.2.12, “procfs 和 sysfs”).

表格 9.13. 硬體識別工具列表

軟體包 | 流行度 | 大小 | 說明
--- | --- | --- | ---
`pciutils` | V:258, I:993 | 289 | Linux PCI 工具: lspci(8)
`usbutils` | V:83, I:887 | 322 | Linux USB 工具: lsusb(8)
`nvme-cli` | V:24, I:34 | 2222 | Linux NVMe 工具: nvme(1)
`pcmciautils` | V:4.1, I:6.4 | 92 | Linux PCMCIA 工具: pccardctl(8)
`scsitools` | V:0.2, I:2.3 | 261 | SCSI 硬體管理工具集: lsscsi(8)
`procinfo` | V:0.4, I:6.2 | 149 | 從 "`/proc`": lsdev(8) 獲得系統資訊
`lshw` | V:13, I:90 | 971 | 硬體調配資訊: lshw(1)
`discover` | V:26, I:620 | 81 | 硬體識別系統: discover(8)

### 9.5.4. 硬體調配

像 GNOME 和 KDE 這類現代圖形桌面系統，雖然大部分硬體的調配都能夠通過相應的圖形調配工具來管理，但知道一些調配它們的基礎方式，也是一個好的主意。

For the keyboard and terminal configuration, see 節 8.2, “鍵盤輸入” and 節 8.3, “顯示輸出”.

表格 9.14. 硬體調配工具列表

軟體包 | 流行度 | 大小 | 說明
--- | --- | --- | ---
`console-setup` | V:81, I:974 | 422 | Linux 控制檯字型和鍵盤表工具
`keyd` | V:1.1, I:1.3 | 1437 | keyboard key remapping daemon using kernel level input primitives (evdev, uinput)
`keyd-application-mapper` | V:0.00, I:0.09 | 34 | keyboard key remapping daemon - application-specific remapper
`x11-xserver-utils` | V:309, I:531 | 559 | X 服務端工具: xset(1), xmodmap(1)
`acpid` | V:55, I:85 | 158 | 管理高階可調配和電源介面(ACPI)事件分發的後臺背景程式（daemon）
`acpi` | V:7, I:79 | 49 | 顯示 ACPI 裝置資訊的工具
`sleepd` | V:0.08, I:0.11 | 84 | 在筆記本空閒時，使其進入休眠狀態的後臺背景程式（daemon）
`hdparm` | V:117, I:213 | 246 | 硬碟存取最佳化 (參見 節 9.6.9, “硬碟最佳化”)
`smartmontools` | V:235, I:265 | 2455 | 使用 S.M.A.R.T. 控制和監控儲存系統
`setserial` | V:3.2, I:5.2 | 104 | 串列埠管理工具集
`memtest86+` | V:1, I:19 | 12483 | 記憶體硬體管理工具集
`scsitools` | V:0.2, I:2.3 | 261 | SCSI 硬體管理工具集
`setcd` | V:0.06, I:0.66 | 33 | 光碟機存取最佳化
`big-cursor` | I:0.64 | 26 | 圖形化界面的大滑鼠游標

這裡, ACPI 是一個比 APM 新的電源管理系統框架。

| 提示
現代系統的 CPU 頻率調整功能，是由核心模組 `acpi_cpufreq` 管理的。

### 9.5.5. 系統時間和硬體時間

下面設定系統的硬體時間為：MM/DD hh:mm, CCYY.

    # date MMDDhhmmCCYY
    # hwclock --utc --systohc
    # hwclock --show

Debian 系統的時間通常顯示為本地時間，但硬體時間通常使用 UTC(GMT) 時間。

如果硬體時間設定為 UTC 時間，請在“`/etc/default/rcS`”裡面設定“`UTC=yes`”。

下面是重新調配 Debian 系統使用的時區。

    # dpkg-reconfigure tzdata

如果你希望通過網路來更新系統時間，考慮使用 `ntp`, `ntpdate` 和 `chrony` 這類包提供的 NTP 服務。

| 提示
在 systemd 下，是使用 `systemd-timesyncd` 來替代進行網路時間同步。參見 systemd-timesyncd(8).

看下面。

- 精確時間和日期管理 HOWTO

- NTP 公共服務專案

- `ntp-doc` 包

| 提示
在 `ntp` 包裡面的 ntptrace(8) 能夠跟蹤 NTP 服務鏈至原始源。

### 9.5.6. 聲音基礎設施

用於現在的 Linux 的音效卡裝置驅動程式由 高階 Linux 聲音體系（Advanced Linux Sound Architecture，ALSA） 提供。ALSA 提供了相容之前的 開放聲音系統（Open Sound System，OSS）的模擬模式。

應用軟體不僅可被配置為不僅直接訪問聲音裝置，也可以通過一些標準化聲音服務端系統來訪問它們。目前，PulseAudio、JACK 和 PipeWire 被用作聲音的服務端系統。參見 Debian 維基聲音頁面 得到最新情況。

每個流行的桌面環境通常都有一個通用的聲音引擎。每個被應用程式使用的聲音引擎都可以選擇連線到不同的聲音伺服器。

| 提示
使用 “`cat /dev/urandom > /dev/audio`” 或 speaker-test(1) 來測試揚聲器（^C 停止）。

| 提示
如果你無法聽到聲音，那你的揚聲器可能連線到了一個靜音輸出。現代的聲音系統有許多輸出。`alsa-utils` 軟體包中的 alsamixer(1) 可以很好地調配聲音和靜音設定。

表格 9.15. 聲音軟體包

軟體包 | 流行度 | 大小 | 說明
--- | --- | --- | ---
`alsa-utils` | V:340, I:459 | 2696 | 調配和使用 ALSA 的工具
`oss-compat` | V:0.6, I:9.7 | 21 | 在 ALSA 下相容 OSS，預防 “`/dev/dsp not found`” 錯誤
`pipewire` | V:321, I:365 | 135 | 音訊和影片處理引擎多媒體服務端 - 後設資料包
`pipewire-bin` | V:328, I:365 | 2219 | 音訊和影片處理引擎多媒體服務端 - 音訊服務和命令列程式
`pipewire-alsa` | V:169, I:234 | 190 | 音訊和影片處理引擎多媒體服務端 - 代替 ALSA 的音訊服務
`pipewire-pulse` | V:289, I:337 | 53 | 音訊和影片處理引擎多媒體服務端 - 代替 PulseAudio 的音訊服務
`pulseaudio` | V:156, I:182 | 6602 | PulseAudio 服務端
`libpulse0` | V:440, I:577 | 969 | PulseAudio 客戶端庫
`jackd` | V:2, I:14 | 8 | JACK Audio Connection Kit. (JACK) 伺服器（低延遲）
`libjack0` | V:1.8, I:8.8 | 329 | JACK Audio Connection Kit. (JACK) 庫（低延遲）
`libphonon4qt5-4` | V:22, I:50 | 572 | Phonon：KDE 聲音引擎

### 9.5.7. 關閉螢幕保護

關閉螢幕保護，使用下面的指令。

表格 9.16. 關閉螢幕保護指令列表

環境 | 指令
--- | ---
Linux 控制檯 | `setterm -powersave off`
X 視窗（關閉螢幕保護） | `xset s off`
X 視窗（關閉 dpms） | `xset -dpms`
X 視窗（螢幕保護 GUI 調配） | `xscreensaver-command -prefs`

### 9.5.8. 關閉蜂鳴聲

可以把電腦的揚聲器拔掉來關閉蜂鳴聲。把 `pcspkr` 核心模組刪除，也可以做到這點。

bash(1) 用到的 readline(3) 程式，當遇到告警字元(ASCII=7)時，將會發生。下面的操作將阻止發生。

    $ echo "set bell-style none">> ~/.inputrc

### 9.5.9. 記憶體使用

對你來說，這裡有兩種可用的方法來得到記憶體的使用情況。

- “`/var/log/dmesg`” 中的核心啟動資訊包含了可用記憶體的精確總大小。

- free(1) 和 top(1) 顯示正在執行的系統中記憶體資源的相關資訊。

下面是一個例子。

    # grep '\] Memory' /var/log/dmesg
    [    0.004000] Memory: 990528k/1016784k available (1975k kernel code, 25868k reserved, 931k data, 296k init)
    $ free -k
                 total       used       free     shared    buffers     cached
    Mem:        997184     976928      20256          0     129592     171932
    -/+ buffers/cache:     675404     321780
    Swap:      4545576          4    4545572

你可能會覺得奇怪：“dmesg 告訴你 free 為 990 MB，而 free -k 告訴你 free 為 320 MB。這丟失了超過 600 MB ……”。

別擔心 “`Mem:`” 這行中 “`used`” 較大的值以及 “`free`” 較小的值，放輕鬆，你需要檢視的是下面的那個（在上面的例子中它們是 675404 和 321780）。

對於我的 MacBook，有 1GB=1048576k 記憶體（顯示卡系統用掉一些），我看到的如下。

表格 9.17. 報告的記憶體大小

報告 | 大小
--- | ---
dmesg 中 total 的大小 | 1016784k = 1GB - 31792k
dmesg 中的 free | 990528k
shell 下的 total | 997184k
shell 下的 free | 20256k（但有效的為 321780k）

### 9.5.10. 系統安全性和完整性檢查

糟糕的系統維護可能會暴露你的系統，導致它被外部非法使用。

對於系統安全性和完整性的檢查，你需要從下面這些方面開始。

- `debsums` 軟體包，參見 debsums(1) 和 節 2.5.2, “頂層“Release”檔案及真實性”。

- `chkrootkit` 軟體包，參見 chkrootkit(1)。

- `clamav` 軟體包家族，參見 clamscan(1) 和 freshclam(1)。

- Debian security FAQ。

- Securing Debian Manual。

表格 9.18. 用於系統安全性和完整性檢查的工具

軟體包 | 流行度 | 大小 | 說明
--- | --- | --- | ---
`logcheck` | V:4.8, I:5.9 | 120 | 後臺背景程式（daemon），將系統日誌檔案中的異常通過郵件傳送給管理員
`debsums` | V:4, I:30 | 108 | 實用程式，使用 MD5 校驗碼對已安裝軟體包的檔案進行校驗
`chkrootkit` | V:9, I:14 | 987 | rootkit 檢測軟體
`clamav` | V:9, I:39 | 39204 | Unix 的反病毒實用程式 —— 指令列介面
`tiger` | V:1.2, I:1.5 | 7800 | 報告系統安全漏洞
`tripwire` | V:1.3, I:1.6 | 5060 | 檔案和目錄完整性檢測軟體
`john` | V:1.1, I:7.3 | 469 | 先進的密碼破解工具
`aide` | V:2.0, I:2.4 | 324 | 高階入侵環境檢測 —— 靜態二進位制
`integrit` | V:0.10, I:0.18 | 2771 | 檔案完整性驗證程式
`crack` | V:0.09, I:0.57 | 153 | 密碼猜測程式

下面是一個簡單的指令碼，用來檢測典型的所有人可寫的錯誤檔案許可權。

    # find / -perm 777 -a \! -type s -a \! -type l -a \! \( -type d -a -perm 1777 \)

| 注意
由於 `debsums` 軟體包使用本地儲存的 MD5 校驗碼，因此面對惡意攻擊，也不能完全相信系統安全性檢測工具。

## 9.6. 資料儲存技巧

用 Linux 即用系統 (參見 節 3.2.2, “USB 上的 Linux 即用救援系統” 和 節 3.2.3, “從 GRUB 啟動的 Linux 即用應急救援系統”) 啟動你的系統，這將使在已經安裝的系統上重新配置資料儲存變得容易。

| 注意
對硬碟(HDD)的描述也適合用於其它儲存裝置，比如 SSD / U 盤 / 記憶體卡 /……。替換例子中 `/dev/sda` 的裝置名稱，用其適合的裝置名稱 `/dev/nvme0`、`/dev/mmcblk0`……。

如果裝置在 GUI（圖形使用者介面）桌面系統下被自動掛載，在對它們進行操作前，你可能需要從命令列手工 umount(8) 這些裝置。

### 9.6.1. 硬碟空間使用情況

硬碟空間的使用情況可以通過 `mount`、`coreutils` 和 `xdu` 軟體包提供的程式來評估：

- mount(8) 顯示所有掛載的檔案系統(= 磁碟).

- df(1) 報告檔案系統使用的硬碟空間。

- du(1) 報告目錄樹使用的硬碟空間。

| 提示
你可以將 du(8) 的輸出傳輸給 xdu(1)，來使用它的圖形互動式演示，例如 “`du -k . |xdu`”、“`sudo du -k -x / |xdu`” 等等。

### 9.6.2. 硬碟分割槽調配

對於硬碟分割槽調配，儘管 fdisk(8) 被認為是標準的調配，但是 parted(8) 工具還是值得注意的。

老的 PC 使用經典的主開機記錄（Master Boot Record，MBR）方案，將硬碟分割槽資料儲存在第一個扇區，即 LBA 扇區 0（512 位元組）。

一些帶有統一可擴充套件韌體介面（Unified Extensible Firmware Interface，UEFI）的近代 PC，包括基於 Intel 的 Mac，使用 全域性唯一標識分割槽表（GUID Partition Table，GPT）方案，硬碟分割槽資料不儲存在第一個扇區。

儘管 fdisk(8) 一直是硬碟分割槽的標準工具，但現在 parted(8) 替代了它。

表格 9.19. 硬碟分割槽管理軟體包

軟體包 | 流行度 | 大小 | 說明
--- | --- | --- | ---
`util-linux` | V:917, I:1000 | 4658 | 多種系統工具，包含 fdisk(8) 和 cfdisk(8)
`parted` | V:449, I:568 | 122 | GNU Parted，硬碟分割槽調整程式
`gparted` | V:12, I:87 | 2313 | 基於 `libparted` 的 GNOME 分割槽編輯程式
`gdisk` | V:19, I:277 | 967 | 用於 GPT/MBR 並存的硬碟的分割槽編輯程式
`kpartx` | V:17, I:26 | 76 | 為分割槽建立裝置對映的程式

| 注意
儘管 parted(8) 聲稱也能用來建立和調整檔案系統，但使用維護最好的專門工具來做這些事會更為安全，例如 mkfs(8)（mkfs.msdos(8)、mkfs.ext2(8)、mkfs.ext3(8)、mkfs.ext4(8)……）和 resize2fs(8)。

| 注意
為了在 GPT 和 MBR 之間切換，你需要直接刪除開頭的幾個塊中的內容（參見 節 9.8.6, “清空檔案內容”）並使用 “`parted /dev/sdx mklabel gpt`” 或 “`parted /dev/sdx mklabel msdos`” 來設定它。請注意，這裡使用的 “`msdos`” 是用於 MBR。

### 9.6.3. 使用 UUID 存取分割槽

儘管重新配置你的分割槽或可移動儲存介質的啟用順序可能會給分割槽產生不同的名字，但你可以使用同一個 UUID 來訪問它們。如果你有多個硬碟並且你的 BIOS/UEFI 沒有給它們一致的裝置名的話，使用 UUID 是不錯的選擇。

- mount(8) 指令帶有 “`-U`” 選項可以使用UUID 來掛載一個塊裝置，而不必使用他的檔名稱，例如 “`/dev/sda3`”。

- “`/etc/fstab`”（參見 fstab(5)）可以使用 UUID。

- 引載載入程式（節 3.1.2, “第二階段：引載加載程序”）也可以使用 UUID。

| 提示
你可以使用 blkid(8) 來檢視一個特定塊裝置的 UUID。 你也可以使用 "`lsblk -f`"來檢測 UUID 並檢視其它資訊。

### 9.6.4. LVM2

LVM2 是一個用於 Linux 核心的邏輯卷管理器。使用 LVM2 的話，硬碟分割槽可以建立在邏輯捲上來替代物理硬碟。

LVM 有下列需求。

- Linux 核心中的裝置對映支援（Debian 核心預設支援）

- 使用者自定義裝置對映支援庫（`libdevmapper*` 軟體包）

- 使用者自定義 LVM2 工具（`lvm2` 軟體包）

請從下面的 man 手冊開始瞭解 LVM2。

- lvm(8)：LVM2 機制的基礎知識（列出了所有 LVM2 指令）

- lvm.conf(5)：LVM2 的組態檔案

- lvs(8)：報告邏輯卷的相關資訊

- vgs(8)：報告卷組的相關資訊

- pvs(8)：報告物理卷的相關資訊

### 9.6.5. 檔案系統調配

對於 ext4 檔案系統, `e2fsprogs` 包提供下面的工具。

- mkfs.ext4(8) 建立新的 ext4 檔案系統

- fsck.ext4(8) 檢查和修復現有 ext4 檔案系統

- tune2fs(8) 調配 ext4 檔案系統的超級塊

- debugfs(8) 互動式的除錯 ext4 檔案系統. (它有 `undel` 指令來恢復已經刪除的檔案.)

mkfs(8) 和 fsck(8) 指令是由 `e2fsprogs` 包提供的，是各種檔案系統相關程式的前端。(`mkfs.fstype` 和 `fsck.fstype`). 對於 ext4 檔案系統,它們是 mkfs.ext4(8) 和 fsck.ext4(8) (它們被符號連結到 mke2fs(8) 和 e2fsck(8)).

Linux 支援的每一個檔案系統，有相似的指令。

表格 9.20. 檔案系統管理包列表

軟體包 | 流行度 | 大小 | 說明
--- | --- | --- | ---
`e2fsprogs` | V:822, I:997 | 1543 | ext2/ext3/ext4 檔案系統工具
`btrfs-progs` | V:51, I:78 | 5250 | Btrfs 檔案系統工具
`reiserfsprogs` | V:11, I:22 | 473 | Reiserfs 檔案系統工具
`zfsutils-linux` | V:33, I:33 | 1895 | OpenZFS 檔案系統工具
`dosfstools` | V:257, I:564 | 310 | FAT 檔案系統工具. (Microsoft: MS-DOS, Windows)
`exfatprogs` | V:34, I:459 | 558 | exFAT 檔案系統工具，由三星維護。
`exfat-fuse` | V:2, I:45 | 73 | FUSE 讀寫 exFAT 檔案系統（微軟）驅動。
`xfsprogs` | V:41, I:87 | 4382 | XFS 檔案系統工具. (SGI: IRIX)
`ntfs-3g` | V:201, I:512 | 1501 | FUSE 讀寫 NTFS 檔案系統（微軟：Windows NT……）驅動。
`jfsutils` | V:0.4, I:6.9 | 1104 | JFS 檔案系統工具. (IBM: AIX, OS/2)
`xorriso` | V:14, I:64 | 378 | ISO-9660 檔案系統工具 和 來自 libburnia 的 CD/DVD 燒錄工具
`wodim` | V:7, I:89 | 898 | 來自 cdrkit 的命令列 CD/DVD 燒錄工具
`genisoimage` | V:17, I:160 | 1567 | 來自 cdrkit 的 ISO-9660 檔案系統命令列工具
`reiser4progs` | V:0.1, I:1.2 | 1367 | Reiser4 檔案系統工具
`hfsprogs` | V:0.3, I:3.2 | 394 | HFS 和 HFS Plus 檔案系統工具. (Apple: Mac OS)
`zerofree` | V:7, I:120 | 30 | 把 ext2/3/4 檔案系統上空閒塊設定為零的程式

| 提示
Ext4 檔案系統是 Linux 系統上預設的檔案系統，強烈推薦使用這個檔案系統，除非你有特殊的理由不使用。 Btrfs 狀態能夠在 Debian wiki on btrfs 和 kernel.org wiki on btrfs 發現。它被期望作為 ext4 檔案系統之後的下一個預設檔案系統。 一些工具可以在沒有 Linux 核心支援的情況下存取檔案系統(參見 節 9.8.2, “不掛載磁碟操作檔案”).

### 9.6.6. 檔案系統建立和完整性檢查

mkfs(8) 在 Linux 系統上建立檔案系統。fsck(8) 指令在 Linux系統上提供檔案系統完整性檢查和修復功能。

在檔案系統建立後，Debian 現在預設不周期性的執行 `fsck`。

| 注意
在已經掛載的檔案系統上執行 `fsck` ，一般是不安全的.

| 提示
在 "`/etc/mke2fs.conf`" 裡設定 "`enable_periodic_fsck`" 並使用 "`tune2fs -c0 /dev/partition_name`" 設定最大掛載數為 0，便可以在重啟時，讓 root 檔案系統包括在內的所有檔案系統上，安全的執行fsck(8) 指令. 參見 mke2fs.conf(5) 和 tune2fs(8). 從啟動腳本里面執行的 fsck(8) 指令結果，可以在 "`/var/log/fsck/`" 目錄下檢視。

### 9.6.7. 通過掛載選項優化檔案系統

“`/etc/fstab`” 中包含了基礎的靜態檔案系統調配。例如，

    «file system»                   «mount point» «type» «options»    «dump» «pass»
    proc                                      /proc proc   defaults          0 0
    UUID=709cbe4c-80c1-56db-8ab1-dbce3146d2f7 /     ext4   errors=remount-ro 0 1
    UUID=817bae6b-45d2-5aca-4d2a-1267ab46ac23 none  swap   sw                0 0
    /dev/scd0                        /media/cdrom0  udf,iso9660 user,noauto  0 0

| 提示
UUID（參見 節 9.6.3, “使用 UUID 存取分割槽”）可以替代一般的塊裝置名稱（例如 “`/dev/sda1`”、“`/dev/sda2`”……）來識別一個塊裝置。

從 Linux 2.6.30 起，核心的預設行為是提供"`relatime`"選項。

參見 fstab(5) 和 mount(8)。

### 9.6.8. 通過超級塊（superblock）優化檔案系統

一個檔案系統的特性可以使用 tune2fs(8) 指令通過超級塊來優化。

- 執行 “`sudo tune2fs -l /dev/sda1`” 可以顯示 “`/dev/sda1`” 上的檔案系統超級塊內容。

- 執行"`sudo tune2fs -c 50 /dev/sda1`" 改變 "`/dev/sda1`" 檔案系統的檢查(在啟動時執行 `fsck`)頻率為每 50 次啟動.

- 執行 “`sudo tune2fs -j /dev/sda1`” 會給檔案系統新增日誌功能，即 “`/dev/sda1`” 的檔案系統從 ext2 轉換為 ext3。（對未掛載的檔案系統這麼做。）

- 執行 “`sudo tune2fs -O extents,uninit_bg,dir_index /dev/sda1 && fsck -pf /dev/sda1`” 在 “`/dev/sda1`” 上將它從 ext3 轉換為 ext4。（對未掛載的系統這麼做。）

| 提示
儘管 tune2fs(8) 的名字是這樣的，但它不僅能用於 ext2 檔案系統，也能用於 ext3 和 ext4 檔案系統。

### 9.6.9. 硬碟最佳化

| 警告
在你折騰硬碟調配之前，請檢查你的硬體並閱讀 hdparm(8) 的 man 手冊頁，因為這可能會對資料完整性造成相當大的危害。

你可以通過 “`hdparm -tT /dev/sda`” 來測試 “`/dev/sda`” 硬碟的存取速度。對於一些使用 (E)IDE 連線的硬碟，你可以使用 “`hdparm -q -c3 -d1 -u1 -m16 /dev/sda`” 來啟用 “(E)IDE 32 位支援”、啟用 “using_dma flag”、設定 “interrupt-unmask flag” 並設定 “multiple 16 sector I/O”（危險！），從而加速硬碟存取速度。

你可以通過 “`hdparm -W /dev/sda`” 來測試 “`/dev/sda`” 硬碟的寫入快取功能。你可以使用 “`hdparm -W 0 /dev/sda`” 關閉寫入快取功能。

現代高速 CD-ROM 光碟機，你可以使用 "`setcd -x 2`" 降低速度，來讀取不當壓縮的 CDROM 光碟。

### 9.6.10. 固態硬碟最佳化

固態硬碟（Solid state drive，SSD） 目前可以被自動檢測。

在 `/etc/fstab` 裡面，將易失性資料路徑掛載為 "`tmpfs`"，可以減少不必要的磁碟訪問來阻止磁碟損耗。

### 9.6.11. 使用 SMART 預測硬碟故障

你可以使用相容 SMART 的 smartd(8) 後臺背景程式（daemon）來監控和記錄你的硬碟。

1. 在 BIOS 中啟用 SMART 功能。

2. 安裝 `smartmontools` 軟體包。

3. 通過 df(1) 列出硬碟驅動並識別它們。

   - 讓我們假設要監控的硬碟為 “`/dev/sda`”。

4. 檢查 “`smartctl -a /dev/sda`” 的輸出，看 SMART 功能是否已啟用。

   - 如果沒有，通過 “`smartctl -s on -a /dev/sda`” 啟用它。

5. 通過下列方式執行 smartd(8) 後臺背景程式（daemon）。

   - 消除 `/etc/default/smartmontools`” 檔案中 “`start_smartd=yes`” 的註釋。

   - 通過 “`sudo systemctl restart smartmontools`” 重新啟動 smartd(8) 後臺守護程序（daemon）。

| 提示
smartd(8) 後臺背景程式（daemon）可以使用 `/etc/smartd.conf` 檔案進行自定義，檔案中包含了相關的警告。

### 9.6.12. 通過 $TMPDIR 指定臨時儲存目錄

應用程式一般在臨時儲存目錄 “`/tmp`” 下建立臨時檔案。如果 “`/tmp`” 沒有足夠的空間，你可以通過 `$TMPDIR` 變數來為程式指定臨時儲存目錄。

### 9.6.13. 通過 LVM 擴充可用儲存空間

在安裝時建立在 Logical Volume Manager 邏輯儲區管理(LVM) (Linux 特性) 上的分割槽，它們可以容易的通過合併擴充或刪除擴充的方式改變大小，而不需要在多個儲存裝置上進行大量的重新調配。

### 9.6.14. 通過掛載另一個分割槽來擴充可用儲存空間

如果你有一個空的分割槽（例如 “`/dev/sdx`”），你可以使用 mkfs.ext4(1) 將它格式化，並使用 mount(8) 將它掛載到你需要更多空間的目錄。（你需要複製原始資料內容。）

    $ sudo mv work-dir old-dir
    $ sudo mkfs.ext4 /dev/sdx
    $ sudo mount -t ext4 /dev/sdx work-dir
    $ sudo cp -a old-dir/* work-dir
    $ sudo rm -rf old-dir

| 提示
你也可以選擇掛載一個空硬碟映像檔案（參見 節 9.7.5, “製作空的磁碟映像檔案”）作為一個迴圈裝置（參見 節 9.7.3, “掛載磁碟映像檔案”）。實際的硬碟使用量會隨著實際儲存資料的增加而增加。

### 9.6.15. 通過 “mount --bind” 掛載另一個目錄來擴充套件可用儲存空間

如果你在另一個分割槽裡有一個帶有可用空間的空目錄（例如 “`/path/to/emp-dir`”），你可以通過帶有 “`--bind`” 選項的 mount(8)，將它掛載到一個你需要更多空間的目錄（例如 “`work-dir`”）。

    $ sudo mount --bind /path/to/emp-dir work-dir

### 9.6.16. 通過 overlay 掛載（overlay-mounting）另一個目錄來擴充套件可用儲存空間

如果你在另一個分割槽表中有可用的空間（例如，“`/path/to/empty`” 和 “`/path/to/work`”），你可以在其中建立一個目錄並堆疊到你需要空間的那個舊的目錄（例如，“`/path/to/old`”），要這樣做，你需要用於 Linux 3.18 版核心或更新版本（對應 Debian Stetch 9.0 或更新版本）的 OverlayFS。

    $ sudo mount -t overlay overlay \
      -olowerdir=/path/to/old-dir,upperdir=/path/to/empty,workdir=/path/to/work

“`/path/to/empty`” 和 “`/path/to/work`” 應該位於可讀寫的分割槽，從而能夠寫入 “`/path/to/old`”。

### 9.6.17. 使用符號連結擴充可用儲存空間

| 注意
這是一個已棄用的做法。某些軟體在遇到“軟連結目錄”時可能不會正常工作。請優先使用上文所述的“掛載”的途徑。

如果你在另一個分割槽裡有一個帶有可用空間的空目錄（例如 “`/path/to/emp-dir`”），你可以使用 ln(8) 建立目錄的一個符號連結。

    $ sudo mv work-dir old-dir
    $ sudo mkdir -p /path/to/emp-dir
    $ sudo ln -sf /path/to/emp-dir work-dir
    $ sudo cp -a old-dir/* work-dir
    $ sudo rm -rf old-dir

| 警告
別對由系統管理的目錄（例如 “`/opt`”）使用“連結到目錄”，這樣的連結在系統升級時可能會被覆蓋。

## 9.7. 磁碟映像

我們在這裡討論磁碟影響的操作。

### 9.7.1. 製作磁碟映像檔案

一個未掛載裝置（例如，第二個 SCSI 或 序列 ATA 裝置 “`/dev/sdb`”）的磁碟映像檔案 “`disk.img`” ，可以使用下列方式之一建立。

    # dd if=/dev/sdb of=disk.img; sync

    # cp /dev/sdb disk.img ; sync

    # cat /dev/sdb > disk.img ; sync

傳統 PC 中位於主 IDE 硬碟第一扇區的主引導記錄（MBR）（參見 節 9.6.2, “硬碟分割槽調配”）的磁碟映像可以使用 dd(1) 通過下列方式建立。

    # dd if=/dev/sda of=mbr.img bs=512 count=1
    # dd if=/dev/sda of=mbr-nopart.img bs=446 count=1
    # dd if=/dev/sda of=mbr-part.img skip=446 bs=1 count=66

- “`mbr.img`”：帶有分割槽表的 MBR

- “`mbr-nopart.img`”：不帶分割槽表的 MBR

- “`mbr-part.img`”：僅 MBR 的分割槽表

如果你要建立原始硬碟的一個硬碟分割槽的映像，你需要使用 “`/dev/sda1`” 等替代 “`/dev/sda`”。

### 9.7.2. 直接寫入硬碟

磁碟映像檔案 “`disk.img`” 可以通過下列方式之一寫入到一個匹配大小的未掛載裝置（例如，第二個 SCSI 裝置 `“/dev/sdb`”。

    # dd if=disk.img of=/dev/sdb ; sync

    # cp disk.img /dev/sdb ; sync

    # cat disk.img >/dev/sdb ; sync

相似地，硬碟分割槽映像檔案 “`partition.img`” 可以通過下列方式寫入到匹配大小的未掛載分割槽（例如，第二個 SCSI 裝置的第一個分割槽 “`/dev/sdb1`”）。

    # dd if=partition.img of=/dev/sdb1 ; sync

### 9.7.3. 掛載磁碟映像檔案

可以使用迴圈裝置通過下列方式掛載和解除安裝包含單個分割槽映像的磁碟映像 “`partition.img`”。

    # losetup --show -f partition.img
    /dev/loop0
    # mkdir -p /mnt/loop0
    # mount -t auto /dev/loop0 /mnt/loop0
    ...hack...hack...hack
    # umount /dev/loop0
    # losetup -d /dev/loop0

可以簡化為如下步驟。

    # mkdir -p /mnt/loop0
    # mount -t auto -o loop partition.img /mnt/loop0
    ...hack...hack...hack
    # umount partition.img

可以使用 迴圈裝置 掛載包含多個分割槽的磁碟映像 “`disk.img`” 的每個分割槽。

    # losetup --show -f -P disk.img
    /dev/loop0
    # ls -l /dev/loop0*
    brw-rw---- 1 root disk   7,  0 Apr  2 22:51 /dev/loop0
    brw-rw---- 1 root disk 259, 12 Apr  2 22:51 /dev/loop0p1
    brw-rw---- 1 root disk 259, 13 Apr  2 22:51 /dev/loop0p14
    brw-rw---- 1 root disk 259, 14 Apr  2 22:51 /dev/loop0p15
    # fdisk -l /dev/loop0
    Disk /dev/loop0: 2 GiB, 2147483648 bytes, 4194304 sectors
    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: 6A1D9E28-C48C-2144-91F7-968B3CBC9BD1

    Device         Start     End Sectors  Size Type
    /dev/loop0p1  262144 4192255 3930112  1.9G Linux root (x86-64)
    /dev/loop0p14   2048    8191    6144    3M BIOS boot
    /dev/loop0p15   8192  262143  253952  124M EFI System

    Partition table entries are not in disk order.
    # mkdir -p /mnt/loop0p1
    # mkdir -p /mnt/loop0p15
    # mount -t auto /dev/loop0p1 /mnt/loop0p1
    # mount -t auto /dev/loop0p15 /mnt/loop0p15
    # mount |grep loop
    /dev/loop0p1 on /mnt/loop0p1 type ext4 (rw,relatime)
    /dev/loop0p15 on /mnt/loop0p15 type vfat (rw,relatime,fmask=0002,dmask=0002,allow_utime=0020,codepage=437,iocharset=ascii,shortname=mixed,utf8,errors=remount-ro)
    ...hack...hack...hack
    # umount /dev/loop0p1
    # umount /dev/loop0p15
    # losetup -d /dev/loop0

或者，你也可以使用 `kpartx` 軟體包中的 kpartx(8) 建立 裝置對映裝置來達到相同的效果。

    # kpartx -a -v disk.img
    add map loop0p1 (253:0): 0 3930112 linear 7:0 262144
    add map loop0p14 (253:1): 0 6144 linear 7:0 2048
    add map loop0p15 (253:2): 0 253952 linear 7:0 8192
    # fdisk -l /dev/loop0
    Disk /dev/loop0: 2 GiB, 2147483648 bytes, 4194304 sectors
    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: 6A1D9E28-C48C-2144-91F7-968B3CBC9BD1

    Device         Start     End Sectors  Size Type
    /dev/loop0p1  262144 4192255 3930112  1.9G Linux root (x86-64)
    /dev/loop0p14   2048    8191    6144    3M BIOS boot
    /dev/loop0p15   8192  262143  253952  124M EFI System

    Partition table entries are not in disk order.
    # ls -l /dev/mapper/
    total 0
    crw------- 1 root root 10, 236 Apr  2 22:45 control
    lrwxrwxrwx 1 root root       7 Apr  2 23:19 loop0p1 -> ../dm-0
    lrwxrwxrwx 1 root root       7 Apr  2 23:19 loop0p14 -> ../dm-1
    lrwxrwxrwx 1 root root       7 Apr  2 23:19 loop0p15 -> ../dm-2
    # mkdir -p /mnt/loop0p1
    # mkdir -p /mnt/loop0p15
    # mount -t auto /dev/mapper/loop0p1 /mnt/loop0p1
    # mount -t auto /dev/mapper/loop0p15 /mnt/loop0p15
    # mount |grep loop
    /dev/loop0p1 on /mnt/loop0p1 type ext4 (rw,relatime)
    /dev/loop0p15 on /mnt/loop0p15 type vfat (rw,relatime,fmask=0002,dmask=0002,allow_utime=0020,codepage=437,iocharset=ascii,shortname=mixed,utf8,errors=remount-ro)
    ...hack...hack...hack
    # umount /dev/mapper/loop0p1
    # umount /dev/mapper/loop0p15
    # kpartx -d disk.img

### 9.7.4. 清理磁碟映像檔案

使用下面的方式，一個磁碟映像檔案 "`disk.img`" 能夠清理掉所有已經刪除的檔案，成為一個乾淨的稀疏映像 "`new.img`"。

    # mkdir old; mkdir new
    # mount -t auto -o loop disk.img old
    # dd bs=1 count=0 if=/dev/zero of=new.img seek=5G
    # mount -t auto -o loop new.img new
    # cd old
    # cp -a --sparse=always ./ ../new/
    # cd ..
    # umount new.img
    # umount disk.img

如果 “`disk.img`” 位於 ext2、ext3 或 ext4，你也可以像下面那樣使用 `zerofree` 軟體包中的 zerofree(8)。

    # losetup --show -f disk.img
    /dev/loop0
    # zerofree /dev/loop0
    # cp --sparse=always disk.img new.img
    # losetup -d /dev/loop0

### 9.7.5. 製作空的磁碟映像檔案

按下面的方式使用 dd(1) ，可以製作一個大小為 5GiB 的空磁碟映像檔案。

    $ dd bs=1 count=0 if=/dev/zero of=disk.img seek=5G

專業的 fallocate(8) 可以在這裡被使用，用來替代使用 dd(1)。

按下面的方式使用環回裝置，你能夠在這個磁碟映像"`disk.img`"上建立 ext4 檔案系統。

    # losetup --show -f disk.img
    /dev/loop0
    # mkfs.ext4 /dev/loop0
    ...hack...hack...hack
    # losetup -d /dev/loop0
    $ du  --apparent-size -h disk.img
    5.0G  disk.img
    $ du -h disk.img
    83M disk.img

對於 "`disk.img`",它的檔案大小是5.0 GiB，而它實際磁碟使用僅僅是 83MiB.這個差距可能是由於 ext4 裡面有稀疏檔案.

| 提示
稀疏檔案的實際磁碟使用會隨著資料的寫入而增加。

迴環裝置 或 裝置對映 裝置上使用類似的操作，在這些裝置按 節 9.7.3, “掛載磁碟映像檔案” 掛載後, 你能夠使用 parted(8) 或 fdisk(8)對這個磁碟映像"`disk.img`"進行分割槽，能夠使用 mkfs.ext4(8), mkswap(8)在上面建立檔案系統等.

### 9.7.6. 製作 ISO9660 映象檔案

| 提示
cdrkit 提供的 genisoimage(1) 和 Libburnia 提供的 xorrisofs(1) ，這兩個命令共享相同的命令語法，僅命令名稱不一樣。

"`源目錄`"下的目錄樹可以通過如下所示的 cdrkit 提供的 genisoimage(1) 指令來製作 ISO9660 映象檔案，"`cd.iso`"。

    #  genisoimage -r -J -T -V volume_id -o cd.iso source_directory

類似的，可引導的 ISO9660 映象檔案，"`cdboot.iso`", 能夠從 `debian-installer` 類似目錄樹 "`source_directory`" 製作，方式如下。

    #  genisoimage -r -o cdboot.iso -V volume_id \
       -b isolinux/isolinux.bin -c isolinux/boot.cat \
       -no-emul-boot -boot-load-size 4 -boot-info-table source_directory

這裡的 Isolinux boot loader (參見 節 3.1.2, “第二階段：引載加載程序”) 是用於啟動的.

按下面的方式，你可以直接從光碟機裝置計算 md5sum 值，並製作 ISO9660 映象。

    $ isoinfo -d -i /dev/cdrom
    CD-ROM is in ISO 9660 format
    ...
    Logical block size is: 2048
    Volume size is: 23150592
    ...
    # dd if=/dev/cdrom bs=2048 count=23150592 conv=notrunc,noerror | md5sum
    # dd if=/dev/cdrom bs=2048 count=23150592 conv=notrunc,noerror > cd.iso

| 警告
為了得到正確結果，你必須小心避免 Linux ISO9600 檔案系統預讀 bug。

### 9.7.7. 直接寫入檔案到 CD/DVD-R/RW

| 提示
對 cdrkit提供的wodim(1) 和 Libburnia 提供的 xorrecord(1)而言，DVD 只是一個大的 CD。這些命令共享相同的命令語法，僅命令名稱不一樣。

你能夠通過如下所示的指令找到可用的裝置。

    # wodim --devices

然後將空的 CD-R 插入 CD 驅動器並且把 ISO9660 映象檔案，"`cd.iso`" 寫入到裝置中，例如用如下所示的 wodim(1) 將資料寫入到 "`/dev/sda`" 裝置。

    # wodim -v -eject dev=/dev/sda cd.iso

如果用 CD-RW 代替 CD-R，用如下所示的指令來替代。

    # wodim -v -eject blank=fast dev=/dev/sda cd.iso

| 提示
如果你的桌面系統自動掛載 CDs，在使用 wodim(1) 之前在終端裡面用 "`sudo umount /dev/sda`" 解除安裝它。

### 9.7.8. 掛載 ISO9660 映象檔案

如果 "`cd.iso`" 包含一個 ISO9660 映象, 下面的指令手工掛載這個檔案到 "`/cdrom`".

    # mount -t iso9660 -o ro,loop cd.iso /cdrom

| 提示
現代桌面系統能夠自動掛載可移動介質，如按 ISO9660 格式化的 CD(參見 節 10.1.7, “可移動儲存裝置”).

## 9.8. 二進位制資料

這裡，我們討論直接操作儲存介質上的二進位制資料。

### 9.8.1. 檢視和編輯二進位制資料

最基礎的檢視二進位制資料的方法是使用 "`od -t x1`" 指令。

表格 9.21. 檢視和修改二進位制資料的軟體包列表

軟體包 | 流行度 | 大小 | 說明
--- | --- | --- | ---
`coreutils` | V:911, I:1000 | 17994 | 基礎軟體包，有 od(1) 來匯出檔案(HEX, ASCII, OCTAL, …)
`bsdmainutils` | V:4, I:136 | 17 | 工具軟體包，有 hd(1) 來匯出檔案(HEX, ASCII, OCTAL, …)
`hexedit` | V:0.8, I:7.9 | 70 | 二進位制瀏覽和編輯器(HEX, ASCII)
`bless` | V:0.2, I:1.4 | 924 | 全功能的十六進位制編輯器(GNOME)
`okteta` | V:1, I:12 | 1589 | 全功能的十六進位制編輯器(KDE4)
`ncurses-hexedit` | V:0.1, I:1.2 | 130 | 二進位制瀏覽和編輯器(HEX, ASCII, EBCDIC)
`beav` | V:0.04, I:0.32 | 137 | 二進位制瀏覽和編輯器(HEX, ASCII, EBCDIC, OCTAL, ...)

| 提示
HEX 是十六進位制英文hexadecimal首字母縮略詞，基數 radix 是 16。OCTAL 是八進位制英文octal 首字母縮略詞，基數 radix是 8。ASCII是美國資訊交換標準程式碼 American Standard Code for Information Interchange 的英文縮寫，即正常的英語文字程式碼。EBCDIC是擴充二進位制編碼十進位制交換碼 Extended Binary Coded Decimal Interchange Code 的英文縮寫，在 IBM 大型機 作業系統上使用。

### 9.8.2. 不掛載磁碟操作檔案

有工具可以在沒有掛載磁碟的情況下讀寫檔案。

表格 9.22. 不掛載磁碟操作檔案的軟體包列表

軟體包 | 流行度 | 大小 | 說明
--- | --- | --- | ---
`mtools` | V:7, I:53 | 400 | 不掛載磁碟的 MSDOS 檔案工具
`hfsutils` | V:0.2, I:2.7 | 178 | 不掛載磁碟的 HFS 和 HFS+ 檔案工具

### 9.8.3. 資料冗餘

Linux 核心所提供的RAID軟體系統提供核心檔案系統級別的資料冗餘來實現高水平的儲存可靠性。

有在應用程式級別增加資料冗餘來實現高水平儲存可靠性的工具。

表格 9.23. 向檔案新增資料冗餘的工具列表

軟體包 | 流行度 | 大小 | 說明
--- | --- | --- | ---
`par2` | V:9, I:116 | 297 | 奇偶校驗檔案卷設定，用於檢查和修復檔案
`dvdisaster` | V:0.1, I:1.2 | 1422 | CD/DVD 媒體資料損失/劃傷/老化的保護
`dvbackup` | V:0.01, I:0.03 | 413 | 使用 MiniDV 行動式攝像機的備份工具(提供 rsbep(1))

### 9.8.4. 資料檔案恢復和診斷分析

有用於資料檔案恢復和診斷分析的工具。

表格 9.24. 資料檔案恢復和診斷分析軟體包列表

軟體包 | 流行度 | 大小 | 說明
--- | --- | --- | ---
`testdisk` | V:2, I:25 | 2275 | 分割槽掃描和磁碟恢復的實用程式
`magicrescue` | V:0.2, I:1.7 | 257 | 通過查詢幻數 magic 位元組來恢復檔案的工具（譯註：請 man file 來了解幻數）
`scalpel` | V:0.2, I:2.2 | 89 | 簡潔、高效能的檔案提取
`myrescue` | V:0.2, I:1.8 | 81 | 恢復損壞硬碟中的資料
`extundelete` | V:0.5, I:7.3 | 152 | 恢復刪除 ext3/4 檔案系統上的檔案的實用程式
`ext4magic` | V:0.3, I:3.4 | 235 | 恢復刪除 ext3/4 檔案系統上的檔案的實用程式
`ext3grep` | V:0.2, I:1.8 | 299 | 幫助恢復 ext3 檔案系統上刪除的檔案的工具
`scrounge-ntfs` | V:0.2, I:1.5 | 49 | NTFS 檔案系統的資料恢復程式
`gzrt` | V:0.03, I:0.47 | 34 | gzip 恢復工具包
`sleuthkit` | V:2, I:25 | 1119 | 診斷分析工具(Sleuthkit)
`autopsy` | V:0.2, I:1.1 | 1026 | SleuthKit 的圖形化介面
`foremost` | V:0.4, I:4.0 | 102 | 恢復資料的診斷程式
`guymager` | V:0.13, I:0.75 | 1049 | 基於 Qt 的診斷影象工具
`dcfldd` | V:0.3, I:2.7 | 113 | 增強版的 `dd`，用於診斷和安全

| 提示
在 `e2fsprogs` 軟體包裡有 debugfs(8) 命令，使用該指令裡的 `list_deleted_inodes` 和 `undel` 指令，你能夠恢復 ext2 檔案系統上刪除的檔案。

### 9.8.5. 把大檔案分成多個小檔案

當一個檔案太大而不能備份的時候，你應該在備份之前先把它分割為多個小於 2000MiB 的小檔案，稍後再把這些小檔案合併為初始的檔案。

    $ split -b 2000m large_file
    $ cat x* >large_file

| 注意
為了防止檔名衝突，請確保沒有任何以 "`x`" 開頭的檔案。

### 9.8.6. 清空檔案內容

為了清除諸如日誌檔案之類的檔案的內容，不要用 rm(1) 指令去刪除檔案然後建立新的空檔案，因為這個檔案可能在指令執行的期間還在被使用。以下是清除檔案內容的正確方法。

    $ :>file_to_be_cleared

### 9.8.7. 樣子文件

下面的指令創建樣子文件或空文件。

    $ dd if=/dev/zero    of=5kb.file bs=1k count=5
    $ dd if=/dev/urandom of=7mb.file bs=1M count=7
    $ touch zero.file
    $ : > alwayszero.file

你將發現下列文件。

- "`5kb.file`" 是 5KB 零。

- "`7mb.file`" 是 7MB 隨機數據。

- "`zero.file`" 也許是一個 0 字節的文件。如果這個文件之前就存在，則它的 `mtime` 會被更新，而它的內容和長度保持不變。

- "`alwayszero.file`" 一定是一個 0 字節文件。如果這個文件之前存在，則它的 `mtime` 會被更新，而它的內容會被清零。

### 9.8.8. 擦除整塊硬碟

有幾種方法來完全擦除裝置上整個硬碟上資料，比如說，在 "`/dev/sda`" 上的 USB 盤。

| 注意
在執行這裡的命令之前，你應該用 mount(8) 命令來檢視 USB 盤 的掛載位置。"`/dev/sda`" 指向的裝置可能是裝有整個系統的 SCSI 硬碟或者 serial-ATA 硬碟。

如下所示是通過資料歸 0 的方式來擦除硬碟上所有資料的。

    # dd if=/dev/zero of=/dev/sda

如下是用隨機資料重寫的方式來擦除所有資料的。

    # dd if=/dev/urandom of=/dev/sda

如下是用隨機資料重寫的方式來高效擦除所有資料。

    # shred -v -n 1 /dev/sda

你或者可以使用 badblocks(8) 加上 `-t random` 選項。

因為 dd(1) 指令在許多可引導的 Linux CDs (例如 Debian 安裝光碟) 上的 shell 環境下都是可用的，你能夠在裝有系統的硬碟上，例如 "`/dev/sda`", "`/dev/sda`" 等等裝置上執行擦除指令來完全清除已經安裝的系統。

### 9.8.9. 擦除硬碟上的未使用的區域

硬碟（或 USB 盤）上未使用的區域，例如“`/dev/sdb1`”可能仍然包含可被擦除的資料，因為他們本身只是解除了從檔案系統的連結，這些可以通過重寫來清除。

    # mount -t auto /dev/sdb1 /mnt/foo
    # cd /mnt/foo
    # dd if=/dev/zero of=junk
    dd: writing to `junk': No space left on device
    ...
    # sync
    # umount /dev/sdb1

| 警告
這對您的 USB 盤 來說通常已經足夠好了，但這還不完美。大部分已擦除的檔名和它們的屬性可能隱藏並留在檔案系統中。

### 9.8.10. 恢復已經刪除但仍然被開啟的檔案

即使你不小心刪除了某個檔案，只要這個檔案仍然被一些應用程式所使用（讀或者寫），恢復此檔案是可能的。

嘗試下列例子

    $ echo foo > bar
    $ less bar
    $ ps aux | grep ' less[ ]'
    bozo    4775  0.0  0.0  92200   884 pts/8    S+   00:18   0:00 less bar
    $ rm bar
    $ ls -l /proc/4775/fd | grep bar
    lr-x------ 1 bozo bozo 64 2008-05-09 00:19 4 -> /home/bozo/bar (deleted)
    $ cat /proc/4775/fd/4 >bar
    $ ls -l
    -rw-r--r-- 1 bozo bozo 4 2008-05-09 00:25 bar
    $ cat bar
    foo

當你安裝了 `lsof` 軟體包的時候，在另外一個終端執行如下指令。

    $ ls -li bar
    2228329 -rw-r--r-- 1 bozo bozo 4 2008-05-11 11:02 bar
    $ lsof |grep bar|grep less
    less 4775 bozo 4r REG 8,3 4 2228329 /home/bozo/bar
    $ rm bar
    $ lsof |grep bar|grep less
    less 4775 bozo 4r REG 8,3 4 2228329 /home/bozo/bar (deleted)
    $ cat /proc/4775/fd/4 >bar
    $ ls -li bar
    2228302 -rw-r--r-- 1 bozo bozo 4 2008-05-11 11:05 bar
    $ cat bar
    foo

### 9.8.11. 查詢所有硬連結

有硬連結的檔案，能夠使用 "`ls -li`" 確認。

    $ ls -li
    total 0
    2738405 -rw-r--r-- 1 root root 0 2008-09-15 20:21 bar
    2738404 -rw-r--r-- 2 root root 0 2008-09-15 20:21 baz
    2738404 -rw-r--r-- 2 root root 0 2008-09-15 20:21 foo

"`baz`" 和 "`foo`" 的連結數為 "2" (>1)，表示他們有硬連結。它們的 inode 號都是"2738404".這表示它們是同樣的硬連結檔案。如果你不想偶然碰巧發現硬連結檔案，你可以通過 inode 號來查詢它。比如說, 按下面的方式查詢 "2738404" 。

    # find /path/to/mount/point -xdev -inum 2738404

### 9.8.12. 不可見磁碟空間消耗

所有開啟的檔案被刪除後，仍然消耗磁碟空間，儘管他們不能夠被普通的 du(1) 所看見。這些被刪除的檔案和他們的大小，可以通過下面的方式列出。

    # lsof -s -X / |grep deleted

## 9.9. 資料加密提示

在可以物理存取您的 PC的情況下，任何人都可以輕易獲得 root 許可權，存取您的 PC 上的所有檔案 (見 節 4.6.4, “root 密碼安全”)。 這意味著登入密碼系統在您的PC被偷盜時並不能保證您私人和敏感資料的安全。您必須部署資料加密技術來實現。儘管 GNU 隱私守護 (見 節 10.3, “資料安全基礎”) 可以對檔案進行加密，但它需要一些使用者端的工作。

Dm-crypt 通過原生的 Linux 核心模組，使用 device-mapper，用很少的使用者操作實現本地自動資料加密。

表格 9.25. 資料加密工具列表

軟體包 | 流行度 | 大小 | 說明
--- | --- | --- | ---
`cryptsetup` | V:35, I:78 | 462 | 可用於加密的塊裝置 的實用程式（dm-crypt / 3LUKS）
`cryptmount` | V:1.9, I:2.5 | 236 | 可用於加密的塊裝置著重於正常使用者掛載/解除安裝的實用程式（ dm-crypt / LUKS）
`fscrypt` | V:0.4, I:1.1 | 6545 | 可用於加密檔案系統的實用程式(fscrypt)
`libpam-fscrypt` | V:0.27, I:0.34 | 6594 | 可用於加密檔案系統的實用程式(fscrypt)

| 注意
資料加密會消耗 CPU 時間等資源，如果它的密碼丟失，加密的資料會變成無法訪問。請權衡其利弊。

| 注意
通過 debian-installer (lenny 或更新版)，整個 Debian 系統能夠被安裝到一個加密的磁碟上，使用 dm-crypt/LUKS 和 initramfs.

| 提示
請參閱 節 10.3, “資料安全基礎” 使用者空間加密實用程式： GNU Privacy Guard。

### 9.9.1. 使用 dm-crypt/LUKS 加密移動磁碟

您可以用 dm-crypt/LUKS 加密大容量可移動裝置上的資料，例如掛載在“`/dev/sdx`”上的 USB 盤。你只需按如下步驟簡單地把它格式化。

    # fdisk /dev/sdx
    ... "n" "p" "1" "return" "return" "w"
    # cryptsetup luksFormat /dev/sdx1
    ...
    # cryptsetup open /dev/sdx1 secret
    ...
    # ls -l /dev/mapper/
    total 0
    crw-rw---- 1 root root  10, 60 2021-10-04 18:44 control
    lrwxrwxrwx 1 root root       7 2021-10-04 23:55 secret -> ../dm-0
    # mkfs.vfat /dev/mapper/secret
    ...
    # cryptsetup close secret

然後，它就可以正常的在現代桌面環境下使用 `udisks2` 軟體包，掛載到 "`/media/username/disk_label`"，只不過它會要求輸入密碼 (參見 節 10.1.7, “可移動儲存裝置”)。不同的是寫入的資料都是加密的。密碼條目可以自動使用鑰匙環（參見 節 10.3.6, “密碼金鑰環”）。

你可以把它格式化成其他格式的檔案系統，例如用 "`mkfs.ext4 /dev/mapper/sdx1`" 把它格式化為 ext4。如果使用 btrfs，則需要安裝 `udisks2-btrfs` 軟體包。對於這些檔案系統，可能需要配置檔案的所有者和許可權。

### 9.9.2. 使用dm-crypt/LUKS掛載加密的磁碟

舉個列子，用 dm-crypt/LUKS 在"`/dev/sdc5`"上建立的加密磁碟可以用如下步驟掛載到"`/mnt`"：

    $ sudo cryptsetup open /dev/sdc5 ninja --type luks
    Enter passphrase for /dev/sdc5: ****
    $ sudo lvm
    lvm> lvscan
      inactive          '/dev/ninja-vg/root' [13.52 GiB] inherit
      inactive          '/dev/ninja-vg/swap_1' [640.00 MiB] inherit
      ACTIVE            '/dev/goofy/root' [180.00 GiB] inherit
      ACTIVE            '/dev/goofy/swap' [9.70 GiB] inherit
    lvm> lvchange -a y /dev/ninja-vg/root
    lvm> exit
      Exiting.
    $ sudo mount /dev/ninja-vg/root /mnt

## 9.10. 核心

對於支援的架構，Debian 使用軟體包來分發模組化的 Linux核心.

如果你正在閱讀本文件，你可能不需要親自編譯核心。

### 9.10.1. 核心參數

許多 Linux 特性可以按下面的方式，通過核心參數來調配。

- 核心參數通過 bootloader 初始化(參見 節 3.1.2, “第二階段：引載加載程序”)

- 對通過 sysfs 存取的核心參數，在執行時通過 sysctl(8) 修改(參見 節 1.2.12, “procfs 和 sysfs”)

- 當一個模組被啟用時，通過 modprobe(8) 參數來設定模組參數。(參見 節 9.7.3, “掛載磁碟映像檔案”)

細節參見 "The Linux kernel user’s and administrator’s guide » The kernel’s command-line parameters" 。

### 9.10.2. 核心標頭檔案

大部分普通程式編譯時不需要核心標頭檔案，如果你直接使用它們來編譯，甚至會導致編譯中斷。在 Debian 系統上，普通程式編譯依賴 `libc6-dev` 軟體包 (由 `glibc` 原始碼包建立)提供的，在"`/usr/include/linux`" 和 "`/usr/include/asm`" 裡的標頭檔案。

| 注意
對於編譯一些核心相關的程式，比如說從外部原始碼編譯的核心模組和 automounter 後臺守護（daemon）程式(`amd`),你必須包含相應的核心標頭檔案到路徑裡，比如"`-I/usr/src/linux-particular-version/include/`", 到你的命令列。

### 9.10.3. 編譯核心和相關模組

Debian 有它自己的方式來編譯核心和相關模組。

表格 9.26. Debian 系統核心編譯需要安裝的主要軟體包列表

軟體包 | 流行度 | 大小 | 說明
--- | --- | --- | ---
`build-essential` | V:16, I:511 | 17 | 建立 Debian 軟體包所必須的軟體包: `make`, `gcc`, …
`bzip2` | V:163, I:972 | 113 | bz2 檔案壓縮和解壓縮工具
`libncurses5-dev` | I:36 | 6 | ncurses 開發者庫和文件
`git` | V:406, I:616 | 50972 | git：Linux 核心使用的分散式版本控制系統
`fakeroot` | V:31, I:513 | 224 | 為非 root 使用者建立軟體包提供一個偽造的 root 環境
`initramfs-tools` | V:465, I:988 | 49 | 建立 initramfs 的工具（Debian 規範）
`dkms` | V:79, I:147 | 235 | 動態核心模組支援 dynamic kernel module support (DKMS) (通用)
`module-assistant` | V:1, I:13 | 395 | 製作模組軟體包的幫助工具（Debian 規範）
`devscripts` | V:5, I:32 | 2763 | Debian Package maintainer Debian 包維護者的幫助指令碼（Debian 規範）

如果你在 節 3.1.2, “第二階段：引載加載程序” 使用 `initrd` , 請一定閱讀 initramfs-tools(8), update-initramfs(8), mkinitramfs(8) 和initramfs.conf(5) 裡的相關資訊。

| 警告
在編譯 Linux 核心原始碼時，請不要放置從"`/usr/include/linux`" 和 "`/usr/include/asm`" 到原始碼樹(比如："`/usr/src/linux*`") 裡目錄的符號連結。(一些過期的文件建議這樣做.)

| 注意
當在 Debian `stable` 版裡編譯最新的 Linux 核心時, 可能需要使用一些從Debian `unstable` 版裡 backported 向後移植的最新版本的工具。 module-assistant(8) (或者它的短形式 `m-a`) 幫助使用者，從一個或多個定製的核心，容易的構建和安裝模組軟體包。 dynamic kernel module support (DKMS)動態核心模組支援 是一個新的分散式獨立框架，被設計用來允許單個的核心模組在不改變整個核心的情況下升級。這可以用於維護核心程式碼樹外部的模組。這也使你升級核心時，重新編譯模組變得非常簡單。

### 9.10.4. 編譯核心原始碼：Debian 核心團隊推薦

從上游核心原始碼編譯個性化的核心二進位制包，你應當使用由它提供的 "`deb-pkg`" 物件。

    $ sudo apt-get build-dep linux
    $ cd /usr/src
    $ wget https://mirrors.edge.kernel.org/pub/linux/kernel/v6.x/linux-version.tar.xz
    $ tar --xz -xvf linux-version.tar.xz
    $ cd linux-version
    $ cp /boot/config-version .config
    $ make menuconfig
     ...
    $ make deb-pkg

| 提示
linux-source-version 軟體包使用 "`/usr/src/linux-version.tar.bz2`" 提供有 Debian 補丁的 Linux核心原始碼。

從 Debian 核心原始碼軟體包編譯特定的二進位制包，你應當使用 "`debian/rules.gen`" 裡的 "`binary-arch_architecture_featureset_flavour`" 物件。

    $ sudo apt-get build-dep linux
    $ apt-get source linux
    $ cd linux-3.*
    $ fakeroot make -f debian/rules.gen binary-arch_i386_none_686

進階資訊參見：

- Debian Wiki: KernelFAQ

- Debian Wiki: DebianKernel

- Debian Linux 核心手冊：https://kernel-handbook.debian.net

### 9.10.5. 硬體驅動和韌體

硬體驅動是執行在目標系統上主 CPU 上的程式碼。大部分硬體驅動現在是自由軟體，已經包含在普通的 Debian 核心軟體包裡，放在 `main` 區域。

- GPU 驅動

  - Intel GPU 驅動 (`main`)

  - AMD/ATI GPU 驅動 (`main`)和/

  - NVIDIA GPU 驅動 (nouveau 驅動放在 `main` , 由廠家支援的二進位制驅動，放在 `non-free`.)

韌體是載入在連線在目標系統裝置上的程式碼或資料(比如說，CPU microcode、 GPU 執行的渲染程式碼 或 FPGA / CPLD 資料……）部分韌體包是作為自由軟體存在，但是很多韌體包由於包含有沒有原始碼的資料，二進位制不是作為自由軟體存在。安裝這些韌體資料是必需的，這樣裝置才能按期望執行。

- 韌體資料軟體包，含有載入到目標裝置易失性儲存器上的資料。

  - firmware-linux-free (`main`)

  - firmware-linux-nonfree (`non-free-firmware`)

  - firmware-linux-* (`non-free-firmware`)

  - *-firmware (`non-free-firmware`)

  - intel-microcode (`non-free-firmware`)

  - amd64-microcode (`non-free-firmware`)

- 韌體更新程式軟體包，更新在目標裝置非易失性儲存器上的資料。

  - fwupd (`main`)：從 Linux Vendor Firmware Service 下載韌體資料的韌體更新後臺守護程序（daemon）。

  - gnome-firmware (`main`): fwupd 的 GTK 前端

  - plasma-discover-backend-fwupd (`main`): fwupd 的 Qt 前端

請注意，從 Debian 12 Bookworm 開始，使用者使用由官方安裝介質裡面提供的 `non-free-firmware` 軟體包來提供完善的安裝體驗。 `non-free-firmware` 區域在 節 2.1.5, “Debian 檔案庫基礎” 裡面描述。

也請注意到， fwupd 從 Linux Vendor Firmware Service 下載的韌體資料並載入到正在執行的 Linux 核心，可能是 `non-free`。

## 9.11. 虛擬化系統

通過使用虛擬系統，我們能在單個機器上同時執行多個系統。

| 提示
參見 Debian wiki 的系統虛擬化。

### 9.11.1. 虛擬化和模擬器工具

有幾個 虛擬化 和模擬器工具平臺。

- 完全的 硬體模擬 軟體包，比如通過 games-emulator 元軟體包安裝的軟體包

- 大部分 CPU 層的模擬，加上一些 I/O 裝置的模擬，比如 QEMU

- 大部分 CPU 層的虛擬化，加上一些 I/O 裝置的模擬，比如 Kernel-based Virtual Machine (KVM)

- 作業系統級的容器虛擬化，加上核心級的支援，比如 LXC (Linux Containers), Docker, systemd-nspawn(1), ...

- 作業系統級的檔案系統訪問虛擬化，加上在檔案路徑上的系統庫呼叫，比如 chroot

- 作業系統級的檔案系統訪問虛擬化，加上在檔案所有者許可權上的系統庫呼叫，比如 fakeroot

- 作業系統 API 模擬器，比如 Wine

- 直譯器級的虛擬化，加上它的執行選擇和執行時庫忽略，比如 Python 的 virtualenv 和 venv

容器虛擬化使用 節 4.7.5, “Linux 安全特性”，是 節 7.7, “沙盒” 的後端技術。

這裡有一些幫你搭建虛擬化系統的軟體包。

表格 9.27. 虛擬化工具列表

軟體包 | 流行度 | 大小 | 說明
--- | --- | --- | ---
`coreutils` | V:911, I:1000 | 17994 | GNU 核心工具包含 chroot(8)
`util-linux` | V:917, I:1000 | 4658 | 其他系統工具包含 unshare(8)
`systemd-container` | V:73, I:76 | 2710 | systemd container/nspawn 工具包含 systemd-nspawn(1)
`schroot` | V:6.8, I:8.8 | 2222 | 在 chroot 下執行 Debian 二進位制包的特異工具
`sbuild` | V:1.3, I:6.4 | 154 | 從 Debian 原始碼構建 Debian 二進位制包的工具
`debootstrap` | V:5, I:45 | 331 | 搭建一個基本的 Debian 系統 (用 sh 寫的)
`mmdebstrap` | V:7, I:12 | 574 | 搭建一個 Debian 系統 (用 Perl 寫的)
`cdebootstrap` | V:0.1, I:1.3 | 114 | 搭建一個 Debian 系統 (用 C 寫的)
`cloud-image-utils` | V:1, I:14 | 66 | 雲映象管理工具
`cloud-guest-utils` | V:5, I:22 | 71 | 雲客戶機工具
`virt-manager` | V:12, I:48 | 2310 | 虛擬機器管理器: 用於管理虛擬機器的桌面應用
`libvirt-clients` | V:49, I:71 | 1159 | libvirt 的庫程式
`docker.io` | V:48, I:50 | 81426 | docker: Linux 容器執行時
`podman` | V:31, I:34 | 84758 | podman：在 Pods 裡面執行基於 OCI 容器的引擎
`podman-docker` | V:2.8, I:3.3 | 270 | 在 Pods 裡面執行基於 OCI 容器的引擎 -- docker 封裝器
`incus` | V:0.8, I:2.9 | 23 | Incus：系統容器和虛擬機器管理器
`games-emulator` | I:0.18 | 21 | games-emulator: Debian 的遊戲模擬器
`bochs` | V:0.07, I:0.64 | 8180 | Bochs: IA-32 PC 模擬器
`qemu-system` | I:21 | 61 | QEMU: 全功能系統的模擬二進位制
`qemu-user` | V:5.8, I:9.3 | 468923 | QEMU: 使用者模式的模擬二進位制
`qemu-utils` | V:14, I:108 | 12175 | QEMU: 工具集
`qemu-system-x86` | V:53, I:92 | 68056 | KVM: x86 硬體上有 硬體輔助虛擬化的全虛擬化
`virtualbox` | V:3.4, I:4.1 | 151566 | VirtualBox:i386 和 amd64 上 x86 的虛擬化解決方案
`gnome-boxes` | V:1.2, I:6.4 | 7045 | Boxes：用於訪問虛擬機器系統的簡單的 GNOME 應用程式
`xen-tools` | V:0.1, I:1.5 | 719 | 用於管理 debian XEN 虛擬伺服器的工具
`wine` | V:13, I:55 | 204 | Wine: Windows 應用程式程式設計介面實現（標準套件）
`dosbox` | V:1, I:12 | 2697 | DOSBox:有 Tandy/Herc/CGA/EGA/VGA/SVGA 顯示卡,聲音和 DOS 的 x86 模擬器
`lxc` | V:10, I:13 | 1629 | Linux 容器使用者層工具
`python3-venv` | V:8, I:147 | 6 | venv 建立虛擬的 python 環境（系統庫）
`python3-virtualenv` | V:7, I:39 | 374 | virtualenv 建立隔離的虛擬 python 環境
`pipx` | V:7, I:47 | 4409 | pipx 在隔離的環境中安裝 python 應用程式

參見維基百科 Comparison of platform virtual machines 來獲得不同平臺的虛擬化解決方案的詳細比較資訊。

### 9.11.2. 虛擬化工作流

| 注意
自從 `lenny` 之後，預設的 Debian 核心就是支援 KVM 的。

典型的虛擬化工作流涉及以下幾個步驟。

- 建立空檔案系統 (目錄樹或磁碟映像)。

  - 目錄樹可以通過 "`mkdir -p /path/to/chroot`" 建立。

  - 原始的磁碟映像檔案能夠使用 dd(1) 建立 (參見 節 9.7.1, “製作磁碟映像檔案” 和 節 9.7.5, “製作空的磁碟映像檔案”).

  - qemu-img(1) 能夠建立和轉化 QEMU 支援的磁碟映像檔案.

  - 原始的格式和 VMDK 檔案格式,能夠作為虛擬化工具的通用格式.

- 使用 mount(8) 掛載磁碟映像到檔案系統 (可選).

  - 對於原始磁碟映像檔案,把它作為迴環裝置 或 裝置對映 裝置掛載. (參見 節 9.7.3, “掛載磁碟映像檔案”).

  - 對於 QEMU 支援的磁碟映像,把它們作為 network block device 網路塊裝置掛載 (參見 節 9.11.3, “掛載虛擬磁碟映像檔案”).

- 在目標檔案系統上部署需要的系統資料。

  - 使用 `debootstrap` 和 `cdebootstrap` 之類的程式來協助處理這個過程(參見 節 9.11.4, “Chroot 系統”).

  - 在全功能系統模擬器下使用作業系統安裝器。

- 在虛擬化環境下執行一個程式。

  - chroot 提供基本的虛擬化環境,足夠能在裡面編譯程式,執行控制檯應用,執行後臺程式 daemon.

  - QEMU 提供跨平臺的 CPU 模擬器.

  - QEMU 和 KVM 通過 hardware-assisted virtualization硬體輔助虛擬化來提供全功能系統的模擬.

  - VirtualBox 可以在 i386 和 amd64 上,使用或者不使用 hardware-assisted virtualization硬體輔助虛擬化來提供全功能系統模擬.

### 9.11.3. 掛載虛擬磁碟映像檔案

對於原始磁碟映像檔案,參見 節 9.7, “磁碟映像”.

對於其它虛擬磁碟映像檔案,你能夠用使用 network block device網路塊裝置 協議的 qemu-nbd(8) 來匯出他們,並使用核心模組 `nbd` 來掛載它們.

qemu-nbd(8) 支援 QEMU 所支援的磁碟格式: raw, qcow2, qcow, vmdk, vdi, bochs, cow (user-mode Linux copy-on-write), parallels, dmg, cloop, vpc, vvfat (virtual VFAT)和主機裝置.

網路塊裝置 能夠用和迴環裝置一樣的方式支援分割槽 (參見 節 9.7.3, “掛載磁碟映像檔案”). 你能夠按下面的方式掛載 "`disk.img`" 的第一個分割槽.

    # modprobe nbd max_part=16
    # qemu-nbd -v -c /dev/nbd0 disk.img
    ...
    # mkdir /mnt/part1
    # mount /dev/nbd0p1 /mnt/part1

| 提示
你可以給 qemu-nbd(8) 使用 "`-P 1`" 選項來匯出"`disk.img`"的第一個分割槽.

### 9.11.4. Chroot 系統

如果你希望從終端控制台嘗試一個新的 Debian 環境，我推薦你使用 chroot。這使你能夠執行 `unstable` 和 `testing` 的控制台應用程式，不會有通常的相關風險，並且不需要重啟。chroot(8) 是最基礎的方法。

| 注意
下面的列子假設根源系統和 chroot 系統都共享相同的 `amd64` CPU 架構。

雖然你能夠手工使用 debootstrap(1)來建立一個 chroot(8) 環境，這要求瑣碎的工作。

sbuild 軟體包從原始碼構建一個 Debian 軟體包，使用 schroot 軟體包管理的 chroot 環境。它和幫助指令碼 sbuild-createchroot(1) 一起。讓我們按如下所示的方式執行它，來學會它是怎樣工作的。

    $ sudo mkdir -p /srv/chroot
    $ sudo sbuild-createchroot -v --include=eatmydata,ccache unstable /srv/chroot/unstable-amd64-sbuild http://deb.debian.org/debian
     ...

你能夠看到 debootstrap(8) 是如何在 "`/srv/chroot/unstable-amd64-sbuild`" 下部署 `unstable` 環境的系統資料,用於一個最小的構建系統。

你可以使用 schroot(1) 來登入到這個環境。

    $ sudo schroot -v -c chroot:unstable-amd64-sbuild

你可以看到一個執行在 `unstable` 環境的系統 shell 是如何建立的。

| 注意
"`/usr/sbin/policy-rc.d`" 檔案總是用 101 退出，阻止在 Debian 系統上自動啟動後臺守護程式。參見 "`/usr/share/doc/init-system-helpers/README.policy-rc.d.gz`"。

| 注意
一些在 chroot 下的程式，需要訪問比上面根源系統上的 `sbuild-createchroot` 能夠提供的檔案之外的更多檔案才能夠執行。例如，"`/sys`", "`/etc/passwd`", "`/etc/group`", "`/var/run/utmp`", "`/var/log/wtmp`"等等.也許需要使用 bind-mounted 或複製.

| 提示
`sbuild` 軟體包幫助建立一個 chroot 系統來構建一個軟體包，在 chroot 內使用 `schroot` 作為它的後端。它是一個檢查構建依賴（build-dependencies）的理想系統。更多資訊參見 sbuild at Debian wiki 和在"Guide for Debian Maintainers"中的 sbuild 配置樣例 。

| 提示
systemd-nspawn(1) 命令使用 `chroot` 類似的方法幫助執行一個命令，或者輕量級容器內的作業系統。它更強大，因為它使用名稱空間來完全虛擬化程序樹、程序間通訊、主機名、域名，並可選網路和使用者資料庫。 參見 systemd-nspawn。

### 9.11.5. 多桌面系統

如果你希望嘗試任一作業系統的一個新的 GUI 桌面環境，我推薦在 Debian `穩定版` 系統上使用 QEMU或者KVM ，這些軟體應用虛擬化技術安全的執行多桌面系統。這能讓你執行任何桌面應用，包括 Debian `不穩定版`和`測試版`上的桌面應用，並且沒有與之相關的通常意義上的風險，並且不需要重啟。

因為單純的 QEMU 工具是非常慢的，當主機系統支援 KVM 的時候，建議使用它來加速。

虛擬機器管理器，也被稱為 `virt-manager`，它是一個便利的管理 KVM 虛擬機器的 GUI（圖形使用者介面）工具，它呼叫 libvirt。

按下面的方法，能夠建立一個可以用於QEMU 的包含有 Debian 系統的虛擬磁碟映像 "`virtdisk.qcow2`"，這個 Debian 系統使用 debian 安裝器:小 CD安裝。

    $ wget https://cdimage.debian.org/debian-cd/5.0.3/amd64/iso-cd/debian-503-amd64-netinst.iso
    $ qemu-img create -f qcow2 virtdisk.qcow2 5G
    $ qemu -hda virtdisk.qcow2 -cdrom debian-503-amd64-netinst.iso -boot d -m 256
    ...

| 提示
在虛擬化下執行 Ubuntu 和 Fedora 之類的其它 GNU/Linux 發行版，是一個不錯的學習其調配技巧的方法。其它專有作業系統也可以在這個 GNU/Linux 虛擬化下很好的執行。

在 Debian wiki: SystemVirtualization 參看更多技巧。

[2] 更多精心製作的定製例子： "Vim Galore", "sensible.vim", ...

[3] vim-pathogen 也很流行。

章 8. I18N 和 L10N |  | 章 10. 資料管理