#107 5 个 Systemd 加速的方法

2025-09-30

5 个提升 Linux 系统启动速度的 systemd 优化技巧,来自《5 systemd tweaks that really boost my boot time》。
不仅是减少启动秒数,更能提升系统响应速度,减少等待时间;通过分析、禁用、屏蔽和调优服务,可打造符合个人需求的流畅启动体验,且调整可逆,适合长期使用。

一、通过 systemd-analyze 定位启动慢的原因

  1. 工具作用
    • systemd-analyze:显示内核和用户空间初始化的总时间,提供启动时间的宏观概览。
    • systemd-analyze blame:按服务启动耗时排序,列出具体服务的耗时明细,定位低效服务(如配置错误或无用的守护进程)。
    • systemd-analyze critical-chain:展示服务依赖关系链,识别阻塞关键任务的服务,为调整启动顺序提供依据。
  2. 操作建议
    • 多次运行分析工具,区分偶发异常(如硬件检测延迟)和持续低效服务,优先优化问题最突出的服务;保存分析结果以便对比优化效果。

二、禁用不必要的后台服务

  1. 优化逻辑
    • 许多 Linux 发行版默认启用冗余服务(如无打印机时的打印守护进程、无蓝牙硬件时的蓝牙管理器),禁用这些服务可减少启动耗时。
  2. 操作方法
    • systemctl disable [服务名]:禁止服务随系统启动,需用时可手动启动;
    • systemctl mask [服务名]:彻底屏蔽服务(适用于确定完全不需要的服务),防止被意外启动。
  3. 注意事项
    • 避免盲目禁用服务,先确认服务功能及依赖关系;每次仅修改一项并测试,防止系统功能损坏。

三、利用 systemd 并行启动优化依赖关系

  1. 原理优势
    • systemd 支持服务并行启动(区别于传统 init 系统的串行启动),合理配置依赖可提升 CPU 和磁盘利用率。
  2. 优化方法
    • 通过systemctl list-dependencies或查看单元文件,检查服务依赖关系,移除不必要的依赖(如使用After=Requires=指令调整启动顺序);
    • 启用“套接字激活”(socket activation):仅在套接字被访问时启动服务,减少启动时的服务加载量。

四、屏蔽可能被重新启用的服务

  1. 适用场景
    • 部分服务可能因软件更新或依赖关系被重新启用,屏蔽(mask)可确保其持续禁用(如与现有网络管理器冲突的网络守护进程)。
  2. 操作命令
    • systemctl mask [服务名]:将服务绑定到/dev/null,阻止任何启动尝试;
    • systemctl unmask [服务名]:取消屏蔽。
  3. 注意点
    • 屏蔽前务必确认服务无间接依赖,避免影响其他功能。

五、优化桌面会话启动流程

  1. 显示管理器调整
    • 更换为轻量级显示管理器(如 LightDM 比 GDM 启动更快),或调整现有管理器的配置以减少启动耗时。
  2. 自动启动应用管理
    • 在桌面环境中禁用不必要的自动启动程序(如云同步工具、更新助手),仅保留必需应用,加快桌面加载速度。
  3. 启动目标优先级调整
    • 延迟非关键服务的启动,优先加载桌面环境,使系统更快进入可用状态。

#106 转载:Android 15 提供原生 Linux 终端

2025-03-16

Android 的 Linux 终端应用现已广泛适用于 Pixel 设备,获取方法如下

你需要一部 Pixel 设备、最新的软件更新,以及几分钟的时间。

作者:Andy Walker
2025 年 3 月 7 日

TL;DR(摘要)

  • Android 的 Linux 终端应用现已广泛适用于运行 2025 年 3 月更新的 Pixel 设备。
  • 该基于 Debian 的环境允许用户随身携带完整的 Linux 实例,尽管仍缺乏一些便捷功能。

去年年底,我们曾报道过,Google 正在开发一款原生的 Linux 终端应用,使智能手机用户能够随身携带桌面级 Linux 发行版。从那时起,我们已经看到该应用随着 Android 15 测试版推送。而现在,随着 2025 年 3 月的 Pixel 更新,这款应用的稳定版本已更广泛地适用于运行最新稳定版 Android 的 Google 手机用户。

“设置” > “系统” > “开发者选项” 中启用 Linux 开发环境后,Linux 终端应用的图标会自动出现。当我激活该功能并点击图标时,系统提示我下载 567MB 的文件。

尽管我在 Pixel 8 上首次尝试运行该终端时失败了,但第二次尝试成功了。越过这个小障碍后,我便可以通过应用列表中的快捷方式打开终端,并运行诸如 helpdffree -m 等基础命令。当然,你也可以执行更高级的命令。

值得注意的是,该 Linux 环境基于 Debian,这是最成熟的 Linux 发行版之一。与原生终端应用 Termux 不同,Linux 终端应用是通过 Android 虚拟化框架(AVF) 在虚拟机中运行的。

不过,该 Linux 终端应用仍然缺少一些功能。其中最大的缺陷可能是 不支持 GUI 应用,但正如我们之前进行的《Doom》演示所示,这项功能计划在 Android 16 中推出。

对大多数用户来说,Android 上的 Linux 终端应用或许并不算特别激动人心或具有颠覆性,但对于开发者和高级用户而言,这无疑是一个巨大的进步。它使用户能够在移动设备上运行桌面级 Linux 应用,为各种需求提供便利。

#105 什么是“企业 Linux”

2024-09-17

我看了阮一峰推荐的内容中有篇文章讲什么是“企业 Linux”(后面会附原文和中文翻译)。
RHEL 名字叫红帽企业 Linux,SLE 也是 SUSE Linux Enterprise 的缩写,我也一直好奇,这个“企业”到底是什么意思?

#104 转载:Linux 命令行:获取上一个命令的参数

2023-10-24

readline 快捷键

readline 是 GNU 的库,实现命令行编辑功能,bash、ftp、python、zsh、mysql 等程序的命令行界面都是使用 readline 实现的,具体实现有 ctrl-r(查找历史命令)、ctrl-p(上一历史命令)、ctrl-a(跳到行首)等。

最重要的还有本次我们所需的 alt+.(dot)esc+.meta+. 得到上一命令的最后一个参数。还有更多快捷键可以参考 readline shortcuts

mac 上没有 alt 和 meta 键,所以我一般使用 esc+. 来获取上一条最后的参数。

shell/bash 历史展开 (history expand)

!$ 获取上一命令的最后一个参数。

历史展开由命令、参数、操作符三部分构成,分别表示展开哪一条命令、该命令的哪个参数、对命令的操作。命令展开完成之后才会进入 .bash_history 中,即执行 history 命令不会看到用于历史展开的参数。

本节的所有命令都假设当前 bash 已经有如下的历史:

$ history
1 echo 1 2 3 4 5
2 ls 6 7 8 9 10
3 echo 11 12 13 14 15
4 cat 16 17 18 19 20
5 echo 21 22 23 24 25
  • a. 命令(Event Designators),用 ! 开始一个历史展开。
$ !n                # 表示第n条命令,如!2表示执行ls 6 7 8 9 10
$ !-n               # 表示倒数第n条命令,如!-3表示执行echo 11 12 13 14 15
$ !!                # 表示上一条命令,是!-1的快捷方式
$ !string           # 表示以string开始的最近的一条命令,如!echo表示echo 21 22 23 24 25
$ !?string?         # 表示含有string的最近的一条命令,如!?6?表示cat 16 17 18 19 20
$ ^string1^string2^ # 表示执行上一条命令,并将其中的第一个string1替换为string2,如果string1不存在则替换失败,不会执行命令。
$ !#                # 表示当前命令现在已经输入的部分,如echo 1 2 !#会执行echo 1 2 echo 1 2
  • b. 参数(Word Designators),命令中选取指定的参数,: 用于分割命令部分与参数部分。
$ !!:0              # 表示上一命令的第0个参数,即命令本身,得到的是echo
$ !2:n              # 表示第2个命令的第n个参数,如!2:2得到的是7
$ !!:^              # 表示上一命令第1个参数,可进一步简写为!^,与!!:1同义,得到的是21
$ !!:$              # 表示上一命令的最后一个参数,可进一步简写为!$,得到的是25
$ !!:x-y            # 表示第x到第y个参数,-y意为0-y,如!-2:3-4得到的是18 19
$ !!:*              # 表示上一命令的参数部分,可进一步简写为!*,如!!:*得到的是21 22 23 24 25
$ !!:n*             # 跟!!:n-$同义
$ !!:n-             # 意为!!:n-$-1,从第n个参数到倒数第二个参数,如!-2:3-得到的是18 19

通过 bash 历史展开实现创建并 cd 到目录的方式为:

$ mkdir somewhere/dir && cd !#:1          # 其中!#表示本行所有命令"mkdir somewhere/dir && cd”,:1取第一个参数就是目录名
  • ​c. 操作符(Modifiers),在可选的参数部分之后,用一个或多个 : 操作符加特定字符。

  • h 去除最后的一个文件路径部分,

    • 假设上一条命令 echo /tmp/123/456/,则 cd !:1:h:h 意为 cd /tmp/123
    • 假设上一条命令 echo /tmp/123/456,则 cd !:1:h:h 意为 cd /tmp
  • t 去除所有的开始的文件路径部分,
    • 假设上一条命令为 echo /tmp/123/456/,则 cd !:1:t 意为 cd
    • 假设上一条命令为 echo /tmp/123/456,则 cd !:1:t 意为 cd 456
  • r 去除后缀,
    • 假设上一条命令为 echo /tmp/bbs.c,则 echo !:1:r 意为 echo /tmp/bbs
  • e 得到后缀,
    • 假设上一条命令为 echo /tmp/bbs.c,则 echo !:1:e 意为 echo .c
  • p print 命令而不执行
  • [g]s/string1/sting2/ 将命令的 string1 替换为 string2,g 意为全局替换,
    • 假设上一条命令为 echo 1 2 1,则 !:gs/1/3/ 意为 echo 3 2 3
    • 上面的 ^string1^string2^ 相当于 !!:s/string1/string2/
  • [g]& 意为执行上次替换,g 意为全局替换。
    • 接上例,假设上一条命令为 echo 123451,则 !:& 意为 echo 323451

使用符号 $$_

在 shell/bash 里 $ 符号表示当前是普通用户(# 是 root),在 sh 脚本或命令行里,$ 开头的表示变量。

# root 用户
[root@localhost iotl] # echo root
# 普通用户
[root@localhost iotl] $ echo hello

以下是一些特殊变量:

  • $_ 代表上一个命令的最后一个参数
  • $# 参数个数。
  • $0 当前 shell 名称(zsh or bash)或脚本的名字。
  • $1 传递给该 shell 脚本的第一个参数。
  • $2 传递给该 shell 脚本的第二个参数。
  • $@ 表示所有的独立的参数,将各个参数分别加双引号返回。
  • $* 以一对双引号给出参数列表。
  • $$ 脚本运行的当前进程 ID 号或所在命令的 PID。
  • $? 显示最后命令的退出状态,0 表示执行成功,其他表示失败。
  • $! 代表最后执行的后台命令的 PID

总结

  1. 快捷键使用 esc + .
  2. 执行最近的以 xxx 开头的命令 !xxx
  3. 快捷修改上一条命令用三个 ^^^ (例如 ^/^/etc^ls / 改为 ls /etc)
  4. 重复当前行前面的命令 !#
  5. 灵活的找到前面的参数: 冒号 !!:3^ 开始、& 结束(可以缩写为 !^!&,注意不是 !#
  6. 重复前面的命令的参数 !#:1
  7. 实际中更多使用快捷键,比如交换前后字母有 ctrl + tesc + t ,比如交换前后单词(word)有 alt + t (别和 alt + dot 搞混了)

参考链接:

  • [1] http://www.gnu.org/software/bash/manual/bashref.html#History-Interaction
  • [2] http://stackoverflow.com/questions/4009412/bash-first-argument-of-the-previous-command
  • [3] https://www.cnblogs.com/tianyapiaozi/archive/2012/09/21/bash_history_arguments.html

#103 Debian 系统

2023-06-14

Debian 给人的印象就是历史悠久、社区文化、稳定。
但实际上我还是主要使用的 CentOS 作为服务器操作系统(桌面使用 Ubuntu 很久了,可能从某种程度上认为是 Debian 系统)。

了解一下这个对我来说熟悉又陌生的 Linux 发行版。

  1. 稳定版提供至少 5 年长期支持(LTS)
  2. 分支
    • 稳定版(stable)
    • 测试版(testing)
    • 不稳定版本(unstable)
      PS:Ubuntu 就是基于 Debian 不稳定版本构建

发行版目录

https://www.debian.org/releases/index.zh-cn.html

版本号 代号 发布日期 支持截止日期 LTS 支持截止日期 ELTS 支持截止日期 当前状态
14 Forky 待定 待定 待定 待定 代号已公布
13 Trixie 待定 待定 待定 待定 测试版(testing) — 发布日期尚未确定
12 Bookworm 2023-06-10 2026-06-10 2028-06-30 2033-06-30 当前稳定(stable)版本
11 Bullseye 2021-08-14 2024-08-14 2026-08-31 2031-06-30 当前旧的稳定(oldstable)版本
10 Buster 2019-07-06 2022-09-10 2024-06-30 2029-06-30 已存档版本,另有第三方付费扩展长期支持
9 Stretch 2017-06-17 2020-07-18 2022-07-01 2027-06-30 已存档版本,另有第三方付费扩展长期支持
8 Jessie 2015-04-25 2018-06-17 2020-06-30 2025-06-30 已存档版本,另有第三方付费扩展长期支持

重要组件(以 Debian 14 为例)

类型 组件 说明
初始化系统 systemd 提供系统和服务管理功能,作为 Debian 默认的初始化系统,用于启动和管理系统服务。
默认桌面 GNOME 44 -
显示服务器 Wayland Wayland 是现代显示服务器协议,提供更高效和安全的显示支持。
网络管理工具 NetworkManager 提供图形化和命令行工具,用于管理有线、无线网络连接,支持 VPN 配置。
防火墙框架 nftables 和其他主流 Linux 发行版一样使用 nftables 取代传统的 iptables。
Python 版本 Python 3.12 Python 2 已被废弃。
Shell Bash 5.x -

如果需要添加更多组件或者特定场景(如开发环境、服务器环境),可以进一步补充。

参考资料与拓展阅读

  • https://packages.debian.org/stable/
  • https://packages.debian.org/stable/gnome/
  • https://packages.debian.org/stable/python/

  • https://www.debian.org/News/2021/

  • https://www.oschina.net/p/debian_linux

  • https://www.debian.org/doc/packaging-manuals/

  • https://www.debian.org/doc/packaging-manuals/menu.html/

  • https://www.debian.org/releases/index.zh-cn.html

  • https://wiki.debian.org/LTS
  • https://wiki.debian.org/DebianReleases

#102 inode 使用率太高的问题

2023-04-03

Jenkins 发布失败,日志显示 scp No space left on device,也就是磁盘空间不足。

查看之后发现是磁盘占用其实不高,不过 inode 使用率满了(其实监控也在报),也就是说小文件太多了。

[staff001@192.168.64.234 ~]# df -h
Filesystem            Size  Used Avail Use% Mounted on
/dev/vda1              40G   29G  8.7G  77% /
tmpfs                 972M     0  972M   0% /dev/shm
/dev/vdb               99G   41G   54G  44% /data

[staff001@192.168.64.234 ~]# df -i
Filesystem            Inodes   IUsed   IFree IUse% Mounted on
/dev/vda1            2621440 2621440       0  100% /
tmpfs                 248685       1  248684    1% /dev/shm
/dev/vdb             6553600  467525 6086075    8% /data

通过经验和 find 命令找到文件太多的目录:

find /var -xdev -printf '%h\n'          | sort | uniq -c | sort -n | awk '{sum+=$1;print $0;}END{print "\nTotal: "sum}'

# 只看二级目录的数据
find /var -xdev -type f | cut -d / -f 3 | sort | uniq -c | sort -n | awk '{sum+=$1;print $0;}END{print "\nTotal: "sum}'

#101 Linux 网络:开放端口范围

2023-03-03

线上环境,有一个服务启动时,四个进程只成功了三个,检查发现端口被占用。
再一看,是被另外三个进程中的一个连接 MongoDB 占用了。

# 查看
cat /proc/sys/net/ipv4/ip_local_port_range
1024    65000

$ sysctl net.ipv4.ip_local_port_range
net.ipv4.ip_local_port_range = 1024     65000

PS:查了一下,个人机器(Ubuntu)上配置的是:32768 60999

把下限往上提到 20000,避开服务常用接口:

# 临时配置
echo "20000 65000" > /proc/sys/net/ipv4/ip_local_port_range
sysctl -w net.ipv4.ip_local_port_range="20000 65000"

# 持久配置
vim /etc/sysctl.conf

#100 dd 替代品

2022-12-25
dd if=image.iso of=/dev/sdb bs=4M

# 用 cat 就行:
cat image.iso >/dev/sdb
# 如果想要进度信息:
cat image.iso | pv >/dev/sdb

dd if=/dev/zero of=image.iso bs=4MB count=25
# 用 head:
head -c 100MB /dev/zero >image.iso

参考:https://eklitzke.org/the-cult-of-dd

#99 bash 上下键搜索历史记录

2022-12-16

我一直用 zsh + omz,但是毕竟 bash 才是大多数情况下的默认 Shell。

zsh 和 bash 都是用上下键来搜索历史记录,但是不同的是,zsh 会利用已经输入部分做前缀匹配,而 bash 不会,只是简单的上一条、下一条。

今天学会一个方法(Bash history search, partial + up-arrow):

bind '"\e[A": history-search-backward'
bind '"\e[B": history-search-forward'

凑活凑活吧。

已经加到我个人的 bash 配置中。

#98 转载:Linux/UNIX 编程如何保证文件落盘

2022-11-10

我们编写程序 write 数据到文件中时,其实数据不会立马写入磁盘,而是会经过层层缓存。每层缓存都有自己的刷新时机,每层缓存都刷新后才会写入磁盘。这些缓存的存在是为了加速读写操作,因为如果每次读写都对应真实磁盘操作,那么读写的效率会大大降低。带来的坏处是如果期间发生掉电或者别的故障,还未写入磁盘的数据就丢失了。对于数据安全敏感的应用,比如数据库,比如交易程序,这是无法忍受的。所以操作系统提供了保证文件落盘的机制。我们来看下这些机制的原理和使用。