我的Linux学习之路

我的Linux学习之路

我的Linux学习路途不同于其他人,也不同于一般的教材。

我从一开始,就以systemd套件为中心展开学习。

这样做有很多好处:

  1. systemd是当代既成的大部分Linux发行版的标准化服务管理套件,主流发行版几乎没有不使用systemd的
  2. systemd套件完整全面,涵盖了系统管理的各个方面,顺着systemd的脉络就可以学习到全面的系统管理知识。
  3. systemd问题就是当今Linux社区的缩影,你能从面对这个问题的态度中看到整个社区务实与毒性并存的多面性,这是很好的祛魅。
  4. systemd的工程态度是的。

就像下面这些问题一样,按顺序对每一个问题进行回答,这或许不能让你成为一个在学术上精通Linux的人,但是至少会让你谈论起来头头是道。

当然,最重要的是,坚持使用Linux发行版,经验总是在日常使用中积累的。

所有的问题几乎都可以在网上找到答案,或是去问问LLM(大语言模型)。耐下性子一点一点搜集,拼凑起来,你会发现这整个过程充满了乐趣。如果你不确定从哪里开始找的话,可以去看看Debian wikiArch wiki

建议使用的发行版为目前最新版本的Debian,stabletesting都可以,如果你足够有勇气,也可以去试试sid

基础概念

预热

  1. 历史与生态:什么是Unix(以及它所谓的“哲学”)?什么是Linux(内核)?什么是GNU计划?它们三者是什么关系?
  2. 发行版:什么是Linux发行版?为什么有这么多发行版(Debian、RHEL、Arch等等)?它们的核心区别是什么(包管理、发布周期、理念)?
  3. 核心工具组:什么是Shell?什么是POSIX标准(Also known as SUSv4, ISO/IEC 9945, IEEE 1003.1)?什么是Bash(它和POSIX标准Shell相比有什么“Bashism”)?什么是GNU Coreutils?什么是Util-linux?
    • 实践:试着尽可能记住Coreutils的核心命令,并用它们进行操作。
  4. 用户与权限:什么是Root用户?什么是普通用户?为什么普通用户不能执行某些命令?sudo的作用是什么?

系统安装

  1. 准备工作:什么是LiveCD/LiveUSB?我们在操作系统内安装的那些二进制文件——固件(Firmware)是什么东西(本质上说,是部分厂商为了绕过内核开源限制,加载他们的内核模块所必须的一部分二进制代码段)?为什么我需要非自由固件才能让系统工作
  2. 磁盘准备:
    • 什么是分区表(MBR vs GPT)?为什么GPT是现代标准?
    • 思考问题:必须得分区吗?我们不分区就不能使用一个磁盘吗(Superfloppy)?
    • 每种分区都有独特的类型编号(GPT PARTTYPE字段),是什么含义?
    • 什么是文件系统?EXT4, BTRFS, XFS有哪些主要区别?它们为什么有先进文件系统(卷管理文件系统)和传统文件系统两大阵营之分?
    • 什么是Swap?它在现代大内存机器上还有必要吗?(参考为Swap辩护
    • 实践:使用Debian Installer安装系统,并进行手动分区,创建一个EFI分区、一个Swap分区、一个根(/)分区。理解每个分区的作用。
  3. 包管理器:什么是本地包管理器(dpkgrpm)和在线包管理器(aptdnf)?
  4. 什么是软件仓库(Repository / 软件源)?
    • 实践:试着在你新安装的系统上修改/etc/apt/sources.list文件,尝试更换为国内镜像源,并执行apt updateapt upgrade

系统启动与核心服务

解构引导过程

  1. 什么是计算机的引导(Bootstrap)?
  2. 固件阶段:了解Legacy BIOS(PC98-style BIOS)和UEFI两种时代的固件。UEFI的优势是什么(安全启动、引导管理器)?试着去看看UEFI论坛的官方标准文档
    • 实践:试着浏览一下自己的主机的UEFI固件,尝试理解各种页面的功能。
  3. 引导管理器(Bootloader)阶段:什么是UEFI Portable Executable(PE)程序?什么是GRUB/systemd-boot?它们如何被UEFI加载?什么是BLS(Boot Loader Specification)?什么是BLS Type 1 Boot Entry?什么是UKI(Unified Kernel Image)?
    • 思考问题:
    • 既然UEFI固件已经有一个Boot Manager了,为什么我们还需要GRUB/systemd-boot?
    • UKI不需要额外的引导管理器也能被UEFI固件直接加载,这是怎么做到的?
    • 实践:试着封装一个UKI,看看ukify工具接受的各种参数。
  4. 内核加载阶段:内核命令行参数(Kernel Cmdline)有什么用?
    • 思考问题:UKI为什么要把内核命令行参数作为内核的一部分封装在自己内部呢?
    • 实践:试着修改自己的系统的内核命令行参数,使systemd的日志变得超级详细。
  5. Initramfs阶段:Initramfs是什么?它的使命是什么(加载驱动、挂载实根)?它是如何切换到真正的根文件系统(实根)的?
    • 思考问题:UKI为什么要把Initramfs封装在自己内部呢(提示:这不仅仅是一个技术问题,而且涉及安全性问题)?
    • 思考问题:传统情况下,Initramfs是怎么打包的?systemd项目组的mkosi-initrd将Initramfs像构建其他系统镜像一样从头开始构建,然后进行裁剪,为什么说这和传统方式相比是颠倒的?这有什么好处、或者说、是为了什么?
  6. 用户空间初始化阶段:Init进程的作用是什么?从systemd的视角分析系统初始化过程

systemd核心管理套件

  1. systemd服务管理:
    • 什么是守护进程(Daemon)?什么是服务(Service)?为什么守护进程不是服务(或者说,不完全是服务)?Supervisor应用程序的定义是什么?它是怎么让守护进程变成服务的?
    • 历史知识:什么是SysvinitLSB标准?Sysvinit本身没有任何Supervise功能(只能依赖外部Supervisor),它是怎么“管理”(如果你非要这么称呼的话。实际上它本身根本就没有服务概念,不了解它启动的进程、也不会进行任何实际意义上的管理)守护进程的?Sysvinit和systemd的争端是Linux社区永远的创伤,这能为我们对开源社区的理解带来什么启发
    • systemctl的基本用法(startstoprestartreloadstatusenabledisablemask)及其含义。
    • systemd-run是快速启动程序并将其构建为服务的好帮手,试一试使用systemd-run运行一个程序。
    • 什么是Cron?systemd-timer相比它有什么优势?
    • 实践:试着创建一个Cron作业,然后使用systemd-timersystemd-service把它取代掉。
  2. systemd日志管理:
    • 什么是日志?
    • Syslog是什么协议?如何让它通过网络收集日志?
    • systemd提供了标准的日志组件systemd-journald,它会收集哪些日志?
    • systemd-journald可以独立工作,也可以和Syslog一起工作,这是怎么实现的?它相比传统Syslog模型(扇入扇出)的优势是什么?
    • 实践:试着使用journalctl命令行工具抓取你之前创建的systemd-timer作业的日志。
  3. systemd网络管理:
    • 什么是“可预测网络接口命名规则”(Predictable Network Interface Names)?那些古怪的字母都是什么意思?
    • 使用iproute2ss工具分析网络情况,那些字段信息都是什么意思?这些工具替代了旧时代的net-tools工具组,为什么?
    • 既然上面那些命令行工具就能配置网络,为什么我们还需要一个网络管理套件(ifupdownNetworkManagersystemd-networkd……)?网络管理套件覆盖了哪些功能?
    • systemd提供了网络管理组件systemd-networkd,怎么使用它的.network配置文件来配置网络?
    • systemd提供了动态DNS管理组件systemd-resolved,这个“动态”是什么意思?
  4. systemd语言管理:
    • 系统语言和GlibC有什么关系?为什么要用GlibC提供的localedef工具对语言进行编译后才能使用?
    • LANGLANGUAGELC_*这些语言相关的环境变量有什么区别?
    • LANGUAGE=CLANGUAGE=en_US.UTF-8有什么区别?为什么要用UTF-8编码?
    • systemd提供了语言管理套件systemd-localed及其客户端localectl。试着使用localctl修改系统语言试试,看看系统发生了什么变化?
  5. systemd时间管理:
    • 什么是RTC?
    • 什么是时区?它影响什么?什么是UTC?
    • systemd提供了时区管理工具systemd-timedated及其客户端timedatectl,试着用它调整系统时区,看看系统发生了什么变化?
    • 什么是NTP协议?为什么我们要使用NTP?
    • systemd提供了时间同步工具systemd-timesyncd,试着用它进行时间同步。

用户环境与日常使用

终端与Shell探究

  1. 终端:什么是tty?什么是ptygetty的作用是什么?systemd-getty-generator是怎么自动在检测到的终端设备上生成getty服务的?
  2. Shell环境:
    • Login shell vs Non-login shell,Interactive vs Non-interactive shell都是什么意思?它们的配置文件加载顺序是什么?
    • SSH的工作原理是什么?为什么一种可靠的认证方式是远程访问协议的基本要求(这也是它全面取代RSH协议的主要原因)?SSH支持很多种认证方式(密码、密钥对、证书等等),它们的思路分别是什么?
    • 实践:看看标准POSIX的标准Shell脚本语法(变量、条件判断、循环、函数),试着编写一个简单的脚本。
    • 实践:定制你的~/.bashrc,添加实用的别名(Alias)和函数。

文件系统与权限管理

  1. 文件系统层次结构:
    • 根据FHS 3.0的内容,熟悉/下各主要目录的用途(/etc/var/usr/home/opt等等)。
    • 理解Usrmerge的意义及其对Linux发行版的深远影响。
    • systemd开发组说“WE DO NOT CARE FHS”,结合systemd的文件系统层次结构规范,理解它和FHS相比有什么不同,以及这么说的原因。
  2. 权限管理:
    • 理解经典的UGO(User, Group, Others)八进制权限位,以及相关工具chmodchownchgrp 的用法。
    • 什么是ACL(Access Control List)?它在什么场景下比UGO更有用?
    • /etc/passwd/etc/shadow/etc/group 文件的作用?为什么我们需要shadow?PAM(Pluggable Authentication Modules)是用来解决什么问题的?
    • 思考问题:每个用户都会放到一个独立的同名组,这有什么特别的意义吗?为什么不直接都放到一个user组呢(事实上,Linux发行版历史上确实这么做过)?
    • systemd提供了用户记录解析工具systemd-userdbd及其客户端userdbctl,了解systemd全新的JSON用户记录格式,试着创建一个JSON用户记录,然后使用userdbctl进行分析,思考:为什么systemd要创建这种新的用户记录格式?它是为了解决传统UNIX单体用户数据库(/etc/passwd)的哪些问题?

桌面环境

  1. GUI栈:
    • X11 vs Wayland的区别是什么?Wayland的设计目标和优势是什么?目前还有哪些生态短板?
    • 什么是显示管理器(Display Manager,如GDM、LightDM)?什么是窗口管理器(Window Manager,例如Mutter)?什么是桌面环境(Desktop Environment,例如GNOME、KDE)?它们之间的关系是什么?
    • 实践:去看看不同的桌面环境长什么样,自己评价一下,然后思考为什么说GNOME是类Unix社区桌面环境中“走自己的路”的先锋。
  2. 输入框架:fcitx5ibus两大阵营的区别是什么?它们分别与不同的GUI工具链(GTK、Qt)和显示协议(X11、Wayland)的兼容性如何?
    • 实践:配置好中文输入法,确保它在你的桌面环境中正常工作。

高级系统管理

存储管理

  1. 逻辑卷管理(LVM):为什么需要LVM?它如何通过池化实现灵活的磁盘管理?
    • 思考问题:BTRFS和ZFS这类先进文件系统自带卷管理能力,这是否意味着传统LVM终将被淘汰?
  2. RAID:了解通过RAID卡在硬件层面实现RAID的手段、通过Device Mapper内核模块和用户空间的RAID工具组(mdadm或现代的LVM2)在软件层面实现RAID的手段,以及RAID 0, 1, 5, 6, 10的基本原理和适用场景。
  3. S.M.A.R.T.:如何使用smartctl监控硬盘健康状况?

网络管理

  1. Linux虚拟网络设备:了解Linux Bridge、Bond、VLAN以及它们依赖的桥接、交换、路由的基本概念。
    • 实践:systemd-networkd可以通过.netdev配置文件直接创建和管理这些虚拟设备。试着用它创建一个Linux Bridge。
  2. 防火墙:nftables是传统iptables的全面迭代,它相比iptables的优势是什么?它为什么否定了原先的“五表五链”模型,转而使用完全自定义的链表?了解一下nftables的基本规则集配置。
  3. NAT:什么是NAT?什么是SNAT和DNAT?为什么我们要做NAT?如何使用nftables实现一个简单的NAT(家庭网关)?

虚拟化与容器

  1. 基本概念:什么是虚拟机、什么是容器?虚拟机与容器的区别是什么?
  2. VM:什么是虚拟机管理器(VMM/Hypervisor)?为什么有两类虚拟机管理器?Type-1和Type-2两类Hypervisor的区别是什么?
    • 思考问题:KVM把Linux内核本身变成了一个Hypervisor——那么QEMU/KVM到底算Type-1还是Type-2?这个分类的模糊性本身说明了什么?
    • 实践:systemd提供了虚拟机工具组systemd-vmspawn,试着用它运行一个VM(你可以在Linux Containers获取可用的VM QCoW2镜像,或者用MKOSI自己构建)。
  3. 容器:系统容器(如LXC)和应用容器/微服务容器(如Docker)的区别是什么?什么是OCI标准?
    • 思考问题:LXC说“系统容器中运行了完整的用户空间”,“完整的用户空间”在这里到底是什么意思?这在容器内的载荷进程(PID 1)的体现是什么?
    • 实践:systemd提供了容器工具组systemd-nspawn,试着用它运行一个容器(你可以在Linux Containers获取可用的根文件系统目录镜像,或者用MKOSI自己构建)。
  4. 内核基石:什么是CGroups?V1和V2有什么区别?什么是Namespaces?它们如何构成了容器技术的基础?
    • 思考:systemd推行的两大CGroup原则:“中间节点无进程”原则和“单一写入者”原则有什么意义?为什么第二个原则受到了猛烈的抨击,以至于systemd不得不开放Delegate=接口?这场争端的本质是“谁有权管理CGroup树”的控制权之争——理解这个妥协方案是如何达成的。

安全加固

  1. 强制访问控制(MAC):什么是DAC(自主访问控制)和MAC(强制访问控制)?AppArmor(基于路径)和SELinux(基于标签)的设计差异是什么?
    • systemd的单元文件中提供了大量沙箱化指令(ProtectHome=PrivateTmp=NoNewPrivileges=CapabilityBoundingSet=等等),它们利用的是内核的哪些机制(Namespaces、Capabilities、Seccomp)?
    • 实践:使用systemd-analyze security <服务名>分析一个服务的安全评分,然后试着给它添加沙箱化指令,把评分降下来。
  2. Web面板:了解Cockpit项目,它如何利用系统已有的API(如systemd D-Bus API)来提供一个现代化的Web管理界面?
    • 思考问题:Cockpit直接调用systemd的D-Bus接口等系统已有的API来完成操作。这种“给现有系统API套上Web前端”的架构,和自建管理层的面板相比,为什么更不容易出问题?

自动化与状态管理

  1. 自动化运维:
    • 为什么自动化配置管理需要“幂等性”(Idempotency)?用Shell脚本的if检查也能实现幂等的自动化能力,为什么我们需要一个专门的工具?
    • Ansible:Ansible是怎么通过SSH实现无客户端(Agent-less)的自动化管理的?有没有Agent在部署环境时真的这么重要吗?
    • 实践:编写一个Ansible Playbook来自动化安装软件包、配置服务。
  2. 镜像化运维:
    • 无论幂等性做得多好,Ansible本质上仍然是在一个运行中的系统上做原地变更(Mutation),这意味着它无法避免配置漂移(Configuration Drift)和“雪花服务器”(Snowflake Server)问题。这是什么意思?
    • 什么是“不可变基础设施”(Immutable Infrastructure),它为什么要求我们不修改机器,而是每次从头构建镜像然后替换
    • Lennart Poettering力推的Hermetic /usr范式将系统的代码与状态彻底彻底分离为四层:基础镜像(Hermetic /usr)、初始化状态(通过/usr中的配置定义的Factory Reset状态)、持久化状态(/etc + /var)、运行时状态(/run)。这四层分离在管理上的意义是什么?
    • Usr-Immutable OS:当/usr变为只读镜像时,系统升级变成了原子性的镜像替换而非apt upgrade式的逐包变更——这对回滚、可复现性、安全验证分别意味着什么?
    • 思考问题:这个模型和手机操作系统(Android的A/B分区更新、iOS的系统分区只读)、以及容器(只读镜像层 + 可写运行层)有什么相通之处?Lennart本人说过,他希望管理一台Linux服务器和管理一台手机一样简单——这句话背后的技术愿景是什么?

深入场景

  1. Udev:/dev(Devfs)的创建和管理者是谁?Udev是怎么了解设备信息的?Udev为什么成为了systemd的一部分?systemd是怎么和Udev集成的?什么是Udev规则?它的匹配语法是怎样的?
  2. Web服务:什么是Web服务器?它本质上在做什么(监听端口、解析HTTP请求、返回响应)?
    • 试着读一下Python内部实现的http.server的代码。
    • 对比一下Apache2,Nginx和Caddy,选一个试着搭建一个网站。
  3. 网络Debug:网络发生问题了,我们应该从哪些层面上逐层分别进行排查?链路层、网络层、传输层、应用层,以及抓包,分别都要用到哪些工具组?
  4. 网络文件系统:有哪些网络文件系统(NFS,CIFS/SMB,WebDAV)?如何选择网络文件系统?怎么挂载网络文件系统?
    • systemd的automount单元可以“懒挂载”目标,为什么这对网络文件系统特别有用?
  5. 私有云:为什么我们要把资源“云化”(池化与按需分配)?
    • 实践:试着使用Incus部署一个轻巧的私有云并启动一个系统容器和一个VM。
  6. 系统镜像构建:一个可交付的Linux发行版本质上由哪些部分构成?构建一个容器镜像、构建一个VM镜像,和构建一个裸机可用的Raw Disk镜像有什么不同?
    • systemd组开发的MKOSI是一个全能的镜像构建器,试着用它构建一个客制化的系统镜像。
  7. 远程控制协议:什么是VNC?什么是RDP?我该怎么进行远程连接?
    • Wayland出于安全考虑不允许应用随意读取其他应用的画面——那么远程桌面在Wayland下是怎么工作的?了解PipeWire和xdg-desktop-portal在其中的角色。
  8. 零配置互联:什么是mDNS协议?什么是LLMNR协议?它们如何让hostname.local在局域网内自动解析而不需要任何DNS服务器
    • 启用systemd-resolved的mDNS功能,和内网的其他主机实现轻松互联。
  9. 开源许可证:GPL是什么?MIT是什么?Apache是什么?这些许可证该怎么选?
  10. 编译工具链:不同的C库实现有什么区别(GlibC vs MuslC)?GCC(GPL)和LLVM/Clang(Apache 2.0)两大编译器派系的分裂是怎么来的?Makefile、Autotools、CMake、Meson这些构建系统各自解决了什么问题?我该怎么编译一个开源项目?
  11. Git与CI/CD:为什么开发流程需要Git这样的版本控制工具?CICD是什么意思?它们分别解决什么问题?为什么现在的CI工具都以Git事件为驱动?
    • 试着用Cron和搓一个简单的CI流程。
  12. 监控与告警:熟悉一下Nagios为首的旧时代监控系统,再看一看Prometheus + Grafana为首的新时代监控系统,想一想它们有什么区别。
    • 思考问题:为什么Prometheus选择Pull模型而非Push模型?哪些场景是Pull模型天然不擅长的,以至于需要Pushgateway补充?
  13. 引导Debug:假设有一天系统起不来了——密码忘掉了,或是引导崩溃了,怎么打开systemd的Debug Shell并进行Debug?怎么在Initramfs阶段打断引导并进行Debug?
    • 思考问题:物理访问权等于完全控制权——这就是为什么度量引导(Measured Boot)和全盘加密(LUKS)很重要。
  14. 网络启动:了解一下传统的PXE网络启动,然后去了解systemd建立在HTTP Boot之上的新时代网络启动,了解它是如何大大简化网络启动链路的。
  15. K8s:为什么容器数量达到成百上千、分布在数十台节点上时,我们需要一个编排器进行托管?Kubernetes是为了解决大面积容器管理场景下的什么问题而诞生的,它与云平台又有什么区别?
    • Docker公司与以谷歌为首的CNCF之间的博弈如何重塑了整个容器生态?OCI标准是怎么在这场博弈中诞生的?
    • K8s的核心抽象是什么?为什么最小调度单位是Pod而不是容器?
    • CRI(Container Runtime Interface):Docker曾经通过dockershim被K8s支持,后来为什么被移除(技术原因和政治原因)?
  16. eBPF:了解什么是BPF,eBPF?eBPF程序是怎么在运行时挂钩到内核的?通过eBPF,很多人担忧Linux正逐渐变身为一个“混合内核”,这是什么意思?