第 9 章 系统技巧

目录

9.1. 控制台技巧
9.1.1. 清晰的记录 shell 活动
9.1.2. screen 程序
9.1.3. 在目录间游走
9.1.4. Readline 封装
9.1.5. 扫描源代码树
9.2. 定制 vim
9.2.1. 用内部特性定制 vim
9.2.2. 用外部软件包定制 vim
9.3. 数据记录和展示
9.3.1. 日志后台守护进程(daemon)
9.3.2. 日志分析
9.3.3. 定制文本数据的显示
9.3.4. 定制时间和日期的显示
9.3.5. shell 中 echo 的颜色
9.3.6. 有颜色输出的命令
9.3.7. 记录编辑器复杂的重复操作动作
9.3.8. 记录 X 应用程序的图像
9.3.9. 记录配置文件的变更
9.4. 监控、控制和启动程序活动
9.4.1. 进程耗时
9.4.2. 调度优先级
9.4.3. ps 命令
9.4.4. top 命令
9.4.5. 列出被一个进程打开的文件
9.4.6. 跟踪程序活动
9.4.7. 识别使用文件和套接字的进程
9.4.8. 使用固定间隔重复一个命令
9.4.9. 使用文件循环来重复一个命令
9.4.10. 从 GUI 启动一个程序
9.4.11. 自定义被启动的程序
9.4.12. 杀死一个进程
9.4.13. 单次任务时间安排
9.4.14. 定时任务安排
9.4.15. 基于事件的计划任务
9.4.16. Alt-SysRq 键
9.5. 系统维护技巧
9.5.1. 谁在系统里?
9.5.2. 警告所有人
9.5.3. 硬件识别
9.5.4. 硬件配置
9.5.5. 系统时间和硬件时间
9.5.6. 终端配置
9.5.7. 声音基础设施
9.5.8. 关闭屏幕保护
9.5.9. 关闭蜂鸣声
9.5.10. 内存使用
9.5.11. 系统安全性和完整性检查
9.6. 数据存储技巧
9.6.1. 硬盘空间使用情况
9.6.2. 硬盘分区配置
9.6.3. 使用 UUID 访问分区
9.6.4. LVM2
9.6.5. 文件系统配置
9.6.6. 文件系统创建和完整性检查
9.6.7. 通过挂载选项优化文件系统
9.6.8. 通过超级块(superblock)优化文件系统
9.6.9. 硬盘优化
9.6.10. 固态硬盘优化
9.6.11. 使用 SMART 预测硬盘故障
9.6.12. 通过 $TMPDIR 指定临时存储目录
9.6.13. 通过 LVM 扩展可用存储空间
9.6.14. 通过挂载另一个分区来扩展可用存储空间
9.6.15. 通过 “mount --bind” 挂载另一个目录来扩展可用存储空间
9.6.16. 通过 overlay 挂载(overlay-mounting)另一个目录来扩展可用存储空间
9.6.17. 使用符号链接扩展可用存储空间
9.7. 磁盘映像
9.7.1. 制作磁盘映像文件
9.7.2. 直接写入硬盘
9.7.3. 挂载磁盘映像文件
9.7.4. 清理磁盘映像文件
9.7.5. 制作空的磁盘映像文件
9.7.6. 制作 ISO9660 镜像文件
9.7.7. 直接写入文件到 CD/DVD-R/RW
9.7.8. 挂载 ISO9660 镜像文件
9.8. 二进制数据
9.8.1. 查看和编辑二进制数据
9.8.2. 不挂载磁盘操作文件
9.8.3. 数据冗余
9.8.4. 数据文件恢复和诊断分析
9.8.5. 把大文件分成多个小文件
9.8.6. 清空文件内容
9.8.7. 样子文件
9.8.8. 擦除整块硬盘
9.8.9. 擦除硬盘上的未使用的区域
9.8.10. 恢复已经删除但仍然被打开的文件
9.8.11. 查找所有硬链接
9.8.12. 不可见磁盘空间消耗
9.9. 数据加密提示
9.9.1. 使用 dm-crypt/LUKS 加密移动磁盘
9.9.2. 使用 dm-crypt/LUKS 挂载加密的磁盘
9.10. 内核
9.10.1. 内核参数
9.10.2. 内核头文件
9.10.3. 编译内核和相关模块
9.10.4. 编译内核源代码:Debian 内核团队推荐
9.10.5. 硬件驱动和固件
9.11. 虚拟化系统
9.11.1. 虚拟化和模拟器工具
9.11.2. 虚拟化工作流
9.11.3. 挂载虚拟磁盘映像文件
9.11.4. Chroot 系统
9.11.5. 多桌面系统

这里,描述配置和管理系统的基本技巧,大部分在控制台操作。

有一些工具程序来帮助你的控制台活动。


简单地使用 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" 将缓存写到文件。

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") 加单个键[加任何参数] 来输入.这里有一些重要的命令按键需要记住。


细节参见 screen(1).

参见 tmux(1) ,了解替代命令的功能。

第 1.4.2 节 “定制 bash”, 2 个技巧允许快速在目录间游走,在 $CDPATHmc 描述。

如果你使用模糊文本过滤程序,你能够不输入精准路径。对于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,将会缩窄候选项。使用光标和回车键选择将要使用的命令。

在你通过 第 1.4.8 节 “使用 vim” 学习基本的vim(1) 后,请阅读 Bram Moolenaar 的"Seven habits of effective text editing (2000)" 来理解 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\+\%#\@<!$/

下面能够发现有趣的外部插件软件包:

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。检查原始的信息是最好的方法。


尽管例如 more(1) 和 less(1) 这样的分页程序(参见 第 1.4.5 节 “分页程序”)和用于高亮和格式的自定义工具(参见 第 11.1.8 节 “高亮并格式化纯文本数据”)可以漂亮地显示文本数据,但通用的编辑器 (参见 第 1.4.6 节 “文本编辑器”)是用途最广的,且可定制性最高。

[提示] 提示

对于 vim(1) 和它的分页模式别名 view(1),“:set hls” 可以启用高亮搜索。

大部分现代终端的 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}"

你能够记录编辑器复杂的重复操作动作。

对于 Vim,请按下面操作。

  • "qa": 开始记录输入字符到有名字的寄存器 "a".

  • … 编辑器操作

  • "q": 结束记录输入的字符。

  • "@a":执行寄存器 "a 的内容".

对于 Emacs, 请按下面操作。

  • "C-x (": 开始定义一个键盘宏.

  • … 编辑器操作

  • "C-x )":结束定义一个键盘宏.

  • "C-x e": 执行一个键盘宏.

程序活动能够使用特殊的工具监控和控制。


[提示] 提示

procps 包提供了非常基础的监控、控制程序活动功能和启动程序功能。你应当把他们全部学会。

通过匹配某些条件的文件来循环重复一个命令,有几种方法,例如,匹配全局模式"*.ext".

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 节 “查找文件的语法”.

对于 命令行界面(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 3 中:

  • 未设置 $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)。

一些程序会被另一个程序自动启动。下面是自定义该过程的方法。

[提示] 提示

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

使用 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) 。

Systemd 能够执行计划程序,不仅基于时间事件,还能够基于挂载事件。参见 第 10.2.3.3 节 “时间事件触发的备份”第 10.2.3.2 节 “挂载事件触发的备份” 的例子。

按 Alt-SysRq (PrtScr)组合键跟一个字母按键,进行不可思议的系统应急控制。


更多信息参见 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(实时) 任务优先级(打开)

下面设置系统的硬件时间为: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, ntpdatechrony 这类包提供的 NTP 服务。

[提示] 提示

systemd 下,是使用 systemd-timesyncd 来替代进行网络时间同步。参见 systemd-timesyncd(8).

参见下面内容。

[提示] 提示

ntp 包里面的 ntptrace(8) 能够跟踪 NTP 服务链至原始源。

用于现在的 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) 可以很好地配置声音和静音设置。


糟糕的系统维护可能会暴露你的系统,导致它被外部非法使用。

对于系统安全性和完整性的检查,你需要从下面这些方面开始。


下面是一个简单的脚本,用来检测典型的所有人可写的错误文件权限。

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

由于 debsums 软件包使用本地存储的 MD5 校验码,因此面对恶意攻击,也不能完全相信系统安全性检测工具。

使用 live CDdebian-installer CD 以救援模式启动你的系统,可以让你简单地重新配置你的启动设备的数据存储。

如果设备在 GUI(图形用户界面)桌面系统下被自动挂载,在对它们进行操作前,你可能需要从命令行手工 umount(8) 这些设备。

对于硬盘分区配置,尽管 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) 替代了它。


[小心] 小心

尽管 parted(8) 声称也能用来创建和调整文件系统,但使用维护最好的专门工具来做这些事会更为安全,例如 mkfs(8)(mkfs.msdos(8)、mkfs.ext2(8)、mkfs.ext3(8)、mkfs.ext4(8)……)和 resize2fs(8)。

[注意] 注意

为了在 GPTMBR 之间切换,你需要直接删除开头的几个块中的内容(参见 第 9.8.6 节 “清空文件内容”)并使用 “parted /dev/sdx mklabel gpt” 或 “parted /dev/sdx mklabel msdos” 来设置它。请注意,这里使用的 “msdos” 是用于 MBR

尽管重新配置你的分区或可移动存储介质的激活顺序可能会给分区产生不同的名字,但你可以使用同一个 UUID 来访问它们。如果你有多个硬盘并且你的 BIOS/UEFI 没有给它们一致的设备名的话,使用 UUID 是不错的选择。

[提示] 提示

你可以使用 blkid(8) 来查看一个特定块设备的 UUID

你也可以使用 "lsblk -f"来检测 UUID 并查看其它信息。

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):报告物理卷的相关信息

对于 ext4 文件系统, e2fsprogs 包提供下面的工具。

  • mkfs.ext4(8) 创建新的 ext4 文件系统

  • fsck.ext4(8) 检查和修复现有 ext4 文件系统

  • tune2fs(8) 配置 ext4 文件系统的超级块

  • debugfs(8) 交互式的调试 ext4 文件系统. (它有 undel 命令来恢复已经删除的文件.)

mkfs(8) 和 fsck(8) 命令是由 e2fsprogs 包提供的,是各种文件系统相关程序的前端。(mkfs.fstypefsck.fstype). 对于 ext4 文件系统,它们是 mkfs.ext4(8) 和 fsck.ext4(8) (它们被符号链接到 mke2fs(8) 和 e2fsck(8)).

Linux 支持的每一个文件系统,有相似的命令。


[提示] 提示

Ext4 文件系统是 Linux 系统上默认的文件系统,强烈推荐使用这个文件系统,除非你有特殊的理由不使用。

Btrfs 状态能够在 Debian wiki on btrfskernel.org wiki on btrfs 发现。它被期望作为 ext4 文件系统之后的下一个默认文件系统。

一些工具可以在没有 Linux 内核支持的情况下访问文件系统(参见 第 9.8.2 节 “不挂载磁盘操作文件”).

固态硬盘(Solid state drive,SSD) 目前可以被自动检测。

/etc/fstab 里面,将易失性数据路径挂载为 "tmpfs",可以减少不必要的磁盘访问来阻止磁盘损耗。

你可以使用兼容 SMARTsmartd(8) 后台守护进程(daemon)来监控和记录你的硬盘。

  1. BIOS 中启用 SMART 功能。

  2. 安装 smartmontools 软件包。

  3. 通过 df(1) 列出硬盘驱动并识别它们。

    • 让我们假设要监控的硬盘为 “/dev/hda”。

  4. 检查 “smartctl -a /dev/hda” 的输出,看 SMART 功能是否已启用。

    • 如果没有,通过 “smartctl -s on -a /dev/hda” 启用它。

  5. 通过下列方式运行 smartd(8) 后台守护进程(daemon)。

    • 消除 /etc/default/smartmontools” 文件中 “start_smartd=yes” 的注释。

    • 通过 “sudo systemctl restart smartmontools” 重新启动 smartd(8) 后台守护进程(daemon)。

[提示] 提示

smartd(8) 后台守护进程(daemon)可以使用 /etc/smartd.conf 文件进行自定义,文件中包含了相关的警告。

在安装时创建在 Logical Volume Manager 逻辑卷管理(LVM) (Linux 特性) 上的分区,它们可以容易的通过合并扩展或删除扩展的方式改变大小,而不需要在多个存储设备上进行大量的重新配置。

我们在这里讨论磁盘影响的操作。

一个未挂载设备(例如,第二个 SCSI 或 串行 ATA 设备 “/dev/sdb”)的磁盘映像文件 “disk.img” 可以使用 cp(1) 或 dd(1) 通过下列方式建立。

# cp /dev/sdb disk.img
# dd if=/dev/sdb of=disk.img

传统 PC 中位于主 IDE 硬盘第一扇区的主引导记录(MBR)(参见 第 9.6.2 节 “硬盘分区配置”)的磁盘映像可以使用 dd(1) 通过下列方式建立。

# dd if=/dev/hda of=mbr.img bs=512 count=1
# dd if=/dev/hda of=mbr-nopart.img bs=446 count=1
# dd if=/dev/hda of=mbr-part.img skip=446 bs=1 count=66
  • mbr.img”:带有分区表的 MBR

  • mbr-nopart.img”:不带分区表的 MBR

  • mbr-part.img”:仅 MBR 的分区表

如果你使用 SCSI 或 串行 ATA 设备作为启动硬盘,你需要使用 “/dev/sda” 替代 “/dev/hda”。

如果你要建立原始硬盘的一个硬盘分区的映像,你需要使用 “/dev/hda1” 等替代 “/dev/hda”。

可以使用循环设备通过下列方式挂载和卸载包含单个分区映像的磁盘映像 “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

按下面的方式使用 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)在上面创建文件系统等.

"源目录"下的目录树可以通过如下所示的 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。

这里,我们讨论直接操作存储介质上的二进制数据。

有硬链接的文件,能够使用 "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

在可以物理访问您的 PC的情况下,任何人都可以轻易获得 root 权限,访问您的 PC 上的所有文件 (见 第 4.6.4 节 “root 密码安全”)。 这意味着登录密码系统在您的 PC 被偷盗时并不能保证您私人和敏感数据的安全。您必须部署数据加密技术来实现。尽管 GNU 隐私守护 (见 第 10.3 节 “数据安全基础”) 可以对文件进行加密,但它需要一些用户端的工作。

Dm-crypt 通过原生的 Linux 内核模块,使用 device-mapper,用很少的用户操作实现本地自动数据加密。


[小心] 小心

数据加密会消耗 CPU 时间等资源,如果它的密码丢失,加密的数据会变成无法访问。请权衡其利弊。

[注意] 注意

通过 debian-installer (lenny 或更新版),整个 Debian 系统能够被安装到一个加密的磁盘上,使用 dm-crypt/LUKS 和 initramfs.

[提示] 提示

请参阅 第 10.3 节 “数据安全基础” 用户空间加密实用程序: GNU Privacy Guard

您可以用 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 软件包。对于这些文件系统,可能需要配置文件的所有者和权限。

对于支持的架构,Debian 使用软件包来分发模块化的 Linux内核.

如果你正在阅读本文档,你可能不需要亲自编译内核。

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)动态内核模块支持 是一个新的分布式独立框架,被设计用来允许单个的内核模块在不改变整个内核的情况下升级。这可以用于维护内核代码树外部的模块。这也使你升级内核时,重新编译模块变得非常简单。

硬件驱动是运行在目标系统上主 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 档案库基础” 里面描述。

也请注意到, fwupdLinux Vendor Firmware Service 下载的固件数据并加载到正在运行的 Linux 内核,可能是 non-free

通过使用虚拟系统,我们能在单个机器上同时运行多个系统。

有几个 虚拟化 和模拟器工具平台。

  • 完全的 硬件模拟 软件包,比如通过 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 的 virtualenvvenv

容器虚拟化使用 第 4.7.5 节 “Linux 安全特性”,是 第 7.7 节 “沙盒” 的后端技术。

这里有一些帮你搭建虚拟化系统的软件包。

表 9.27. 虚拟化工具列表

软件包 流行度 大小 说明
coreutils V:880, I:999 18307 GNU 核心工具包含 chroot(8)
systemd-container V:53, I:61 1330 systemd container/nspawn 工具包含 systemd-nspawn(1)
schroot V:5, I:7 2579 在 chroot 下执行 Debian 二进制包的特异工具
sbuild V:1, I:3 243 从 Debian 源码构建 Debian 二进制包的工具
debootstrap V:5, I:54 314 搭建一个基本的 Debian 系统 (用 sh 写的)
cdebootstrap V:0, I:1 115 搭建一个 Debian 系统 (用 C 写的)
cloud-image-utils V:1, I:17 66 云镜像管理工具
cloud-guest-utils V:3, I:13 71 云客户机工具
virt-manager V:11, I:44 2296 虚拟机管理器: 用于管理虚拟机的桌面应用
libvirt-clients V:46, I:65 1241 libvirt 的库程序
incus V:0, I:0 56209 Incus:系统容器和虚拟机管理器(在 Debian 13 "Trixie")
lxd V:0, I:0 52119 LXD:系统容器和虚拟机管理器(在 Debian 12 "Bookworm" )
podman V:14, I:16 41948 podman:在 Pods 里面运行基于 OCI 容器的引擎
podman-docker V:0, I:0 249 在 Pods 里面运行基于 OCI 容器的引擎 -- docker 封装器
docker.io V:41, I:43 150003 docker: Linux 容器运行时
games-emulator I:0 21 games-emulator: Debian 的游戏模拟器
bochs V:0, I:0 6956 Bochs: IA-32 PC 仿真器
qemu I:14 97 QEMU: 快速的通用处理器仿真器
qemu-system I:22 66 QEMU: 全功能系统的模拟二进制
qemu-user V:1, I:6 93760 QEMU: 用户模式的模拟二进制
qemu-utils V:12, I:106 10635 QEMU: 工具集
qemu-system-x86 V:33, I:91 58140 KVM: x86 硬件上有 硬件辅助虚拟化的全虚拟化
virtualbox V:6, I:8 130868 VirtualBox:i386 和 amd64 上 x86 的虚拟化解决方案
gnome-boxes V:1, I:7 6691 Boxes:用于访问虚拟机系统的简单的 GNOME 应用程序
xen-tools V:0, I:2 719 用于管理 debian XEN 虚拟服务器的工具
wine V:13, I:60 132 Wine: Windows 应用程序编程接口实现(标准套件)
dosbox V:1, I:15 2696 DOSBox:有 Tandy/Herc/CGA/EGA/VGA/SVGA 显卡,声音和 DOS 的 x86 模拟器
lxc V:9, I:12 25890 Linux 容器用户层工具
python3-venv I:88 6 venv 创建虚拟的 python 环境(系统库)
python3-virtualenv V:9, I:50 356 virtualenv 创建隔离的虚拟 python 环境
pipx V:3, I:19 3324 pipx 在隔离的环境中安装 python 应用程序

参见维基百科 Comparison of platform virtual machines 来获得不同平台的虚拟化解决方案的详细比较信息。

[注意] 注意

自从 lenny 之后,默认的 Debian 内核就是支持 KVM 的。

典型的虚拟化工作流涉及以下几个步骤。

对于原始磁盘映像文件,参见 第 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"的第一个分区.

如果你希望从终端控制台尝试一个新的 Debian 环境,我推荐你使用 chroot。这使你能够运行 unstabletesting 的控制台应用程序,不会有通常的相关风险,并且不需要重启。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

如果你希望尝试任一操作系统的一个新的 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
...
[提示] 提示

虚拟化下运行 UbuntuFedora 之类的其它 GNU/Linux 发行版,是一个不错的学习其配置技巧的方法。其它专有操作系统也可以在这个 GNU/Linux 虚拟化下很好的运行。

Debian wiki: SystemVirtualization 参看更多技巧。



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

[3] vim-pathogen 也很流行。