惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Hacker News: Ask HN
Hacker News: Ask HN
H
Help Net Security
Microsoft Azure Blog
Microsoft Azure Blog
B
Blog RSS Feed
Jina AI
Jina AI
Stack Overflow Blog
Stack Overflow Blog
量子位
博客园_首页
Vercel News
Vercel News
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
Forbes - Security
Forbes - Security
IT之家
IT之家
N
News and Events Feed by Topic
S
Security Affairs
Recent Commits to openclaw:main
Recent Commits to openclaw:main
Webroot Blog
Webroot Blog
Recorded Future
Recorded Future
L
LangChain Blog
Y
Y Combinator Blog
AI
AI
MyScale Blog
MyScale Blog
大猫的无限游戏
大猫的无限游戏
小众软件
小众软件
Know Your Adversary
Know Your Adversary
AWS News Blog
AWS News Blog
Help Net Security
Help Net Security
Cyberwarzone
Cyberwarzone
L
Lohrmann on Cybersecurity
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Google Online Security Blog
Google Online Security Blog
V2EX - 技术
V2EX - 技术
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
PCI Perspectives
PCI Perspectives
I
Intezer
T
Tenable Blog
G
Google Developers Blog
Application and Cybersecurity Blog
Application and Cybersecurity Blog
T
Troy Hunt's Blog
L
LINUX DO - 最新话题
云风的 BLOG
云风的 BLOG
C
CXSECURITY Database RSS Feed - CXSecurity.com
有赞技术团队
有赞技术团队
O
OpenAI News
P
Proofpoint News Feed
TaoSecurity Blog
TaoSecurity Blog
C
Check Point Blog
Last Week in AI
Last Week in AI
S
Schneier on Security
Simon Willison's Weblog
Simon Willison's Weblog
Blog — PlanetScale
Blog — PlanetScale

暗无天日

读:AI Agent 安全日志——从可见性与隐私的两难说起 - 暗无天日 读:AI Agent 生产化——一份从原型到上线的速查清单 - 暗无天日 AI写作的语言指纹——如何让文字不那么像机器 - 暗无天日 读:50 条 Claude Code 技巧——一个工程经理的六个月使用心得 读:AI 辅助开发为什么让 E2E 测试更有价值 - 暗无天日 读:在Emacs中使用Claude Code(Spacemacs适配版) - 暗无天日 Claude Code 背后的工程哲学——读 Agent Harness Engineering 读:Agent Harness Engineering——AI 智能体不只是模型,还有套件 - 暗无天日 browser-harness:让 AI 直接接管你的浏览器 - 暗无天日 读:Security-First CI/CD —— DevSecOps 自动化实践指南 TIL: 数字小键盘的小数点陷阱与行内算术求值 - 暗无天日 读:Immutability 不是万能药,它是一种权衡 - 暗无天日 Conducty:给 Claude Code 加上项目记忆和并行执行能力 - 暗无天日 读 — GitHub Trending 里的 Claude Code 技能包 读 — Prompt Caching 省钱指南 TIL: Emacs 中那些跟鼠标配合的冷门快捷键 - 暗无天日 读:Anvil——把 Emacs 变成 AI 的工具服务器 读:Emacs 代码折叠终极指南 - 暗无天日 读:Clojure 搭车客指南 - 暗无天日 git推送失败后恢复仓库损坏的完整记录 - 暗无天日 多智能体系统的两个有效模式——以及对 Claude Code 用户的启示 - 暗无天日 用 Org Babel 写 Literate 博文:扩展执行 + 定制导出 proced:Emacs 内置的进程查看器 - 暗无天日 从 proced 定制中学到的 Elisp 模式 读:让 Emacs proced 在 macOS 上显示 CPU 和内存 异步编程的函数着色税 - 暗无天日 链式调用的代价:JavaScript 和 Clojure 的共同教训 - 暗无天日 hyperfine:命令行基准测试工具 - 暗无天日 管道中的变量去哪了?——子 shell 作用域陷阱 - 暗无天日 开源包装器的信任陷阱:四个危险信号 - 暗无天日 程序员愿意为 AI 写文档,却不愿为同事写 - 暗无天日 mktemp: Shell 脚本中临时文件的安全陷阱与最佳实践 - 暗无天日 WSL9x —— 在 Windows 9x 里跑 Linux 内核 6.19 用 ox.el 做你想做的事 —— org-export 高级编程指南 读:Hot-wiring the Lisp Machine —— 用纯 Elisp 构建零依赖的 Org 静态站点生成器 Elisp 性能优化的六个实战教训 - 暗无天日 fcitx5 下 Emacs 无法切换输入法的排查 - 暗无天日 ERT 测试交互命令的三种方式 - 暗无天日 SEM Assistant: 当 Elisp 守护进程遇上 LLM 用 dmsg 给 Elisp 加上结构化调试日志 用 org-habit 追踪非每日习惯 - 暗无天日 Clojure X-Men:当编程语言特性变成超能力 - 暗无天日 TIL: 用 diff-hl 在 fringe 中显示 git 变更 读:llm-test —— 用 LLM agent 驱动 Emacs 测试 TIL: AI 时代的橡皮鸭调试 - 暗无天日 fcitx 启动后键盘输入卡顿的排查 - 暗无天日 TIL: 早期网页的图片热区导航 - 暗无天日 读 Seeing the Whole System 用 Emacs 自动生成每周链接推荐 - 暗无天日 读:ASCII control characters in my terminal 读 What to learn - 暗无天日 Lisp 的括号之痛——一个愚人节玩笑揭开的老伤疤 - 暗无天日 一本书该"线性读"还是"并行读" - 暗无天日 读 How to Monetize a Blog:一篇伪装成变现指南的讽刺文 Python Mock 第三方依赖的四种策略 - 暗无天日 Emacs Lisp 热重载实用指南 - 暗无天日 Prot 的 Emacs 配置哲学 - 暗无天日 TIL: 从直播对谈中学到的三个 Emacs 技巧 - 暗无天日 TIL: 自动使用项目虚拟环境的 Python - 暗无天日 TIL: 让 Help buffer 自动获得焦点 一条命令让本地开发用上 HTTPS —— slim 工具介绍 用 fsck 检查和修复 Linux 文件系统 排查Linux进程"卡死"实战:从strace到gdb全流程 - 暗无天日 PostgreSQL 索引:从基础到你可能不知道的高级用法 - 暗无天日 用 .pdbrc 自定义 Python 调试器 ANSI 转义码的标准化现状 - 暗无天日 终端程序的潜规则 - 暗无天日 PARA Org-mode 测试配置 - 暗无天日 AI越强越辣鸡?控制论说这是必然的 - 暗无天日 AI 越强越需要你盯着——反馈循环实操指南 - 暗无天日 你的AI代理正在偷你的密钥——四种你没想到的泄露通道 - 暗无天日 LLM 在 DevOps 中的三种角色 - 暗无天日 写作风格的反建议 - 暗无天日 反驳本质复杂性——Dan Luu 论为什么《没有银弹》错了 - 暗无天日 文件充满了危险——Dan Luu 谈文件系统的可靠性陷阱 - 暗无天日 AI 时代的 PARA 方法:用 Org-mode 和 AI 打造个人知识管理系统 Linux 数据去重学习笔记 - 暗无天日 创建跨平台 ZIP 文件的隐藏陷阱:Extra Field - 暗无天日 X11 Forwarding 排障指南 - 暗无天日 IP欺骗端口扫描:当别人冒充你去扫描别人 - 暗无天日 Linux 输入栈全景解析:从硬件按键到屏幕响应 - 暗无天日 在Linux上限制儿童使用电脑 - 暗无天日 GIF不仅仅是一种图片格式——用GIF流做些奇怪的事 - 暗无天日 Leiningen 学习笔记:Clojure 项目构建与管理从入门到实战配置 - 暗无天日 Google SRE Book 读书笔记 - 暗无天日 yes 管道 head 发生了什么 - 暗无天日 为什么 nohup 在 crontab 中不起作用 Bash中的Indirection与Nameref - 暗无天日 Linux PAM 简介 - 暗无天日 从Linux ISO文件启动计算机 - 暗无天日 用 Bash 打造一个Screen Locker 用GitHub Actions自动构建EGO博客 - 暗无天日 blocking I/O 的作用 - 暗无天日 mobileog 手机端同步提示Error:2 No such file 的解决方法 回收 WSL2 VHDX 文件占用空间 使用 org-mode columnview 生成任务列表 - 暗无天日 Emacs 作为 MPD 客户端 - 暗无天日 移动文件路径却不破坏org file link的方法 - 暗无天日 如何合理的导出help link 成HTML - 暗无天日 笑话理解之Biology - 暗无天日
Unix 系统中那些被埋没的配置开关——以 FontConfig 为例 - 暗无天日
2026-04-14 · via 暗无天日

Mechanism, Not Policy

Unix 设计哲学中有一条广为人知的信条:*"提供机制,而非策略"(Mechanism, not policy)*。意思是系统应该提供灵活的底层能力,而把"怎么用"的决定权留给用户。

这个理念催生了无数强大的工具,但也带来了一个副作用。Henry Spencer 曾一针见血地指出:

这种态度的缺点是,人们倾向于认为一旦完成了高度可配置和富有表现力的接口,工作就算完成了……即使结果是其他任何人如果不经过漫长研究几乎不可能使用。可配置性的反面是迫切需要良好的默认值和一种简单的方式将一切重置为默认值。表达力的反面是需要指导——无论是在程序中还是在文档中——关于如何入门以及如何实现最常见的需求。

ESR 在 The Art of Unix Programming 中也表达了类似的观点:

当人们说一个用户界面是直观的,他们的意思是它 (a) 可发现、(b) 使用时透明、(c) 遵循最小惊讶原则。

venam 在文章中列举了 Linux 系统中 9 个"被埋没的配置开关"的例子。本文将以 FontConfig 为重点深入探讨,其余领域简要带过。

FontConfig:你可能从未了解过的字体魔法

大多数人只知道 fc-list

如果你问一个 Linux 用户怎么管理字体,大概率会得到这样的回答:

fc-list | head
/usr/share/fonts/100dpi/courB18.pcf.gz: Adobe Courier:style=Bold
/usr/share/fonts/100dpi/helvBO18.pcf.gz: Adobe Helvetica:style=Bold Oblique
/usr/share/fonts/100dpi/UTRG__12.pcf.gz: Adobe Utopia:style=Regular
/usr/share/fonts/gsfonts/D050000L.otf: D050000L:style=Regular
/usr/share/fonts/100dpi/timB12-ISO8859-1.pcf.gz: Adobe Times:style=Bold

这确实是大多数人使用 FontConfig 的方式——列出系统里有哪些字体,然后就没了。

FontConfig 的配置格式

但实际上,FontConfig 拥有一套极其强大的 XML 配置格式,可以对字体进行 匹配和属性编辑 。配置文件位于 /etc/fonts/fonts.conf/etc/fonts/conf.d/ 目录下。

ls /etc/fonts/conf.d/ | head
10-hinting-slight.conf
10-scale-bitmap-fonts.conf
10-yes-antialias.conf
11-lcdfilter-default.conf
20-unhint-small-dejavu-lgc-sans.conf
20-unhint-small-dejavu-lgc-sans-mono.conf
20-unhint-small-dejavu-lgc-serif.conf
20-unhint-small-dejavu-sans.conf
20-unhint-small-dejavu-sans-mono.conf
20-unhint-small-dejavu-serif.conf

每个配置文件都是一个 XML 文档,核心结构是 <match> 元素,包含 =<test>=(匹配条件)和 =<edit>=(编辑操作):

<match target="font">
  <test name="family">
    <string>Monospace</string>
  </test>
  <edit name="hintstyle" mode="assign">
    <const>hintslight</const>
  </edit>
</match>

这段配置的意思是:对所有 Monospace 族字体,将 hintstyle 设置为 hintslight。

预置的优化配置

你的系统上很可能已经有一套预置的字体优化配置,但大多数人从未留意过:

ls /usr/share/fontconfig/conf.avail/
05-reset-dirs-sample.conf
09-autohint-if-no-hinting.conf
10-autohint.conf
10-hinting-full.conf
10-hinting-medium.conf
10-hinting-none.conf
10-hinting-slight.conf
10-no-antialias.conf
10-scale-bitmap-fonts.conf
10-sub-pixel-bgr.conf
10-sub-pixel-none.conf
10-sub-pixel-rgb.conf
10-sub-pixel-vbgr.conf
10-sub-pixel-vrgb.conf
10-unhinted.conf
10-yes-antialias.conf
11-lcdfilter-default.conf
11-lcdfilter-legacy.conf
11-lcdfilter-light.conf
11-lcdfilter-none.conf
...(共 70+ 个预置配置文件)

这些预置配置涵盖了各种渲染优化场景,如 LCD 滤波器设置、像素间距建议、特定语言的字体回退等。

fc-match:查看字体匹配真相

fc-match 是理解 FontConfig 行为的关键工具:

fc-match Sans
wqy-zenhei.ttc: "文泉驿正黑" "Regular"

这会告诉你当你请求 Sans 字体时,系统实际会使用什么字体。加上 -s 参数可以看到完整的替换链:

fc-match -s Sans | head -5
wqy-zenhei.ttc: "文泉驿正黑" "Regular"
DejaVuSans.ttf: "DejaVu Sans" "Book"
DejaVuSans-Bold.ttf: "DejaVu Sans" "Bold"
DejaVuSans-Oblique.ttf: "DejaVu Sans" "Oblique"
DejaVuSans-BoldOblique.ttf: "DejaVu Sans" "Bold Oblique"

fc-pattern:调试字体属性

fc-pattern 可以让你看到字体的完整属性列表:

fc-match --verbose Sans | head -20
Pattern has 45 elts (size 48)
	family: "文泉驿正黑"(w) "WenQuanYi Zen Hei"(w) "文泉驛正黑"(w)
	familylang: "zh-cn"(s) "en"(w) "zh-tw"(w)
	style: "Regular"(s)
	stylelang: "en"(s)
	fullname: "文泉驿正黑"(w) "WenQuanYi Zen Hei"(w) "文泉驛正黑"(w)
	fullnamelang: "zh-cn"(s) "en"(w) "zh-tw"(w)
	slant: 0(i)(s)
	weight: 100(f)(s)
	width: 100(f)(s)
	size: 12(f)(s)
	pixelsize: 12.5(f)(s)
	spacing: 0(i)(w)
	foundry: "WenQ"(s)
	antialias: True(w)
	hintstyle: 0(i)(w)
	hinting: True(w)
	verticallayout: False(s)
	autohint: False(w)
	globaladvance: False(w)

为什么这么强大的能力几乎没人知道?

venam 指出,目前的字体相关界面仅限于显示已安装字体列表和不同尺寸的预览。曾经有一个叫 fontweak 的项目试图让 FontConfig 的配置更加可发现,但功能有限且无法展示全局视图。

FontConfig 的困境是典型的 "mechanism without discoverable policy" : 它提供了强大的匹配-编辑机制,但用户需要一个直观的界面来回答"我的系统当前对字体到底做了什么?"

其他被埋没的配置

venam 在文章中还列举了其他几个类似的例子,这里简要概述。

Audio Restore List

PulseAudio 和 PipeWire 会记住每个设备、每个音频流的最后音量设置。但这个信息是隐藏的——当你插上耳机或打开视频时,你无法预知音量会是多少。可能震耳欲聋,也可能完全静音。

Journald

systemd.journal-fields(7) 定义了一套固定的字段体系,Journald 本质上是一个固定列/字段的线性存储。但大多数人只会随机敲命令直到找到想要的结果,或者死记硬背一两个 --unit <service> --reverse 之类的技巧。

sudo

每个人都知道 sudo ,但很少有人能解释 sudo -ll 的输出,或者完整配置 sudoers 文件。sudoers 文件包含默认全局设置、别名和匹配规则,但唯一的编辑器 visudo 对新手极其不友好。

Polkit

Policy Kit 是一个很棒的桌面安全概念:标准化的动作和服务,通过间接总线触发,由集中的策略执行器决定调用者是否被允许。但它的规则和 JavaScript 格式的配置散落在系统各处,创建新的动作和规则非常困难。

udev

udev 规则是另一个"配置散落"的典型。它有匹配模式和动作执行(甚至支持 goto 和标签跳转,是图灵完备的)。唯一"可视化"这些配置的方法是:

systemd-analyze cat-config udev/rules.d
# /usr/lib/udev/rules.d/01-md-raid-creating.rules
# do not edit this file, it will be overwritten on update
# While mdadm is creating an array, it creates a file
# /run/mdadm/creating-mdXXX.  If that file exists, then
# the array is not "ready" and we should make sure the
# content is ignored.

KERNEL=="md*", TEST=="/run/mdadm/creating-$kernel", ENV{SYSTEMD_READY}="0"

# /usr/lib/udev/rules.d/10-dm.rules
...

为什么这个问题难以解决

venam 在文章结尾提到了人们面对复杂配置的三种态度:

  1. 保持默认 —— 用容器化/不可变系统的方式,一切保持出厂设置
  2. 精雕细琢(RICE) —— 乐在其中地折腾每一项配置
  3. 探索中间地带 —— 尝试让隐藏的能力更容易被发现和使用

FontConfig 的例子很好地说明了核心矛盾:可配置性和可发现性之间存在天然的张力。提供更多配置选项意味着更复杂的界面,而简化界面又意味着放弃一些能力。

但也许问题不在于"要不要简化",而在于"如何让用户知道这些选项的存在"。一个好的界面不一定需要展示所有选项,但它应该让用户在需要时能够 发现 选项的存在。这正是目前大多数 Linux 系统工具所缺失的。

正如 ESR 所说,一个好的界面应该是可发现的、透明的、符合最小惊讶原则的。我们还有很长的路要走。