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

推荐订阅源

V2EX - 技术
V2EX - 技术
T
Troy Hunt's Blog
The Last Watchdog
The Last Watchdog
www.infosecurity-magazine.com
www.infosecurity-magazine.com
S
Secure Thoughts
Hacker News - Newest:
Hacker News - Newest: "LLM"
WordPress大学
WordPress大学
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
博客园 - 司徒正美
TaoSecurity Blog
TaoSecurity Blog
博客园 - Franky
有赞技术团队
有赞技术团队
Google Online Security Blog
Google Online Security Blog
罗磊的独立博客
L
LINUX DO - 最新话题
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
NISL@THU
NISL@THU
小众软件
小众软件
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Recent Commits to openclaw:main
Recent Commits to openclaw:main
K
Kaspersky official blog
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
W
WeLiveSecurity
SecWiki News
SecWiki News
Google DeepMind News
Google DeepMind News
O
OpenAI News
V
V2EX
AI
AI
博客园_首页
Apple Machine Learning Research
Apple Machine Learning Research
大猫的无限游戏
大猫的无限游戏
美团技术团队
C
Cyber Attacks, Cyber Crime and Cyber Security
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Security Archives - TechRepublic
Security Archives - TechRepublic
博客园 - 三生石上(FineUI控件)
G
GRAHAM CLULEY
月光博客
月光博客
T
Threatpost
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
V
Vulnerabilities – Threatpost
Last Week in AI
Last Week in AI
爱范儿
爱范儿
C
CXSECURITY Database RSS Feed - CXSecurity.com
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
Cloudbric
Cloudbric
酷 壳 – CoolShell
酷 壳 – CoolShell
The Hacker News
The Hacker News
N
News | PayPal Newsroom
Know Your Adversary
Know Your Adversary

暗无天日

读: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 自动生成每周链接推荐 - 暗无天日 读 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 输入栈全景解析:从硬件按键到屏幕响应 - 暗无天日 Unix 系统中那些被埋没的配置开关——以 FontConfig 为例 - 暗无天日 在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 - 暗无天日
读:ASCII control characters in my terminal
2026-04-21 · via 暗无天日

Julia Evans 写了一篇文章梳理终端中所有 33 个 ASCII 控制字符的作用。这些控制字符是你每天按 Ctrl-C 终止程序、按 Ctrl-Z 挂起进程、按 Ctrl-W 删一个词时实际发送的那些字节。本文是对她文章的解读。

只有 33 个控制码

ASCII 表的前 32 个位置(0-31)加上第 127 个位置,一共 33 个,留给"控制字符"——它们不对应可打印字符,而是表示某种控制动作。其中 26 个对应 Ctrl-ACtrl-Z ,另外 7 个对应 Ctrl 加上 @[\]^_?

这意味着 Ctrl-1Ctrl-2 这种组合在终端里根本不存在——按下 Ctrl-1 跟直接按 1 效果一样,因为 ASCII 没有为数字键预留控制码的位置。同样, Ctrl+Shift+C 也不是控制码,它由终端模拟器自己处理(用来复制),根本不会发送到终端里运行的程序。

三层处理:谁来响应你的按键

这 33 个控制码并不是统一由某一层处理的,而是分成了三股道:

  1. *OS 终端驱动*直接处理的:比如 Ctrl-C (发送 SIGINT 信号终止程序)、 Ctrl-Z (发送 SIGTSTP 挂起程序)、 Ctrl-D (发送 EOF)。这些按键按下后,OS 的终端驱动会直接拦截并产生相应动作,程序本身收不到这个字节。
  2. *readline 库*处理的:比如 Ctrl-W (删一个词)、 Ctrl-U (删整行)、 Ctrl-R (搜索历史命令)。这些在 bash、python REPL 等使用 readline 的程序中工作,但在 cat 这种不用 readline 的程序中就不起作用。
  3. *应用程序自己定义*的:比如 Ctrl-X 在一般终端程序里没有固定含义,但 Emacs 把它用作了大量快捷键的前缀。

stty -a 可以看到 OS 终端驱动处理的所有控制码映射:

stty -a

在我的机器上输出如下(只列出控制字符映射部分):

intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = <undef>;
eol2 = <undef>; swtch = <undef>; start = ^Q; stop = ^S; susp = ^Z;
rprnt = ^R; werase = ^W; lnext = ^V; discard = ^O; min = 1; time = 0;

这里 intr = ^C 表示 Ctrl-C 触发中断信号, erase = ^? 表示退格键(byte 127)触发删除字符, kill = ^U 表示清行, werase = ^W 表示删一个词。所有这些映射都可以通过 stty 命令修改——比如 stty intr ^X 可以把中断信号改到 Ctrl-X 上。不过实际上几乎没有人改这些映射,改了只会让自己在各种教程和问答里找不到北。

Ctrl-M 就是 Enter,Ctrl-I 就是 Tab

这是一个容易让人困惑的设计: Ctrl-M 发送的字节值是 13,跟按 Enter 键完全一样; Ctrl-I 发送的字节值是 9,跟按 Tab 键完全一样。所以如果你想给终端程序设置 Ctrl-MCtrl-I 作为快捷键,会发现它们的效果跟 EnterTab 一样——因为从程序的角度看,收到的是同一个字节。

这也解释了为什么很多终端程序(包括 bash 的 readline)的快捷键覆盖了 Ctrl-ACtrl-Z 的大部分,唯独跳过了 Ctrl-ICtrl-M ——不是故意这样设计的,而是这两个位置已经被 TabEnter 占了。

canonical 模式 vs noncanonical 模式

Ctrl-WCtrl-U 的行为取决于终端当前处于哪种模式:

  • *canonical 模式*(规范模式):OS 终端驱动负责行编辑。你按 Backspace 删字符、按 Ctrl-W 删词、按 Ctrl-U 清行,这些都是 OS 在缓冲区里处理的,程序只有在你按 Enter 之后才能看到整行输入。 catgrep 等非交互程序通常用这种模式。
  • *noncanonical 模式*(原始模式):OS 不做任何行编辑,每按一个键程序就立刻收到。 Ctrl-WCtrl-U 的删词、清行功能需要程序自己实现。bash、python REPL、vim 等交互式程序用这种模式。

可以用 strace 观察一个程序设置了哪些终端模式:

strace -tt -o /tmp/strace-out vim
grep ioctl /tmp/strace-out | grep SET

你会看到 vim 启动时关闭了 ISIG (不再由 OS 处理信号)和 ICANON (关闭 canonical 模式),改为 raw 模式自己处理所有输入。vim 退出时又把这些设置恢复回去。

Backspace 的混乱历史

Backspace 键时,终端到底发送哪个字节?这个问题居然没有统一答案:

  • 有些机器发 byte 127 (ASCII 名 DEL
  • 有些机器发 byte 8 (ASCII 名 BS ,Backspace)

在 Linux 上, Backspace 键发送的是 byte 127 ,OS 终端驱动和 readline 都把它映射为"删除前一个字符"。 Ctrl-H 发送 byte 8 ,在 readline 里它的效果跟 Backspace 一样(都是删除一个字符),但在 cat 这种只用 canonical 模式的程序里, Ctrl-H 只会打印出 ^H 而不会删字符——因为 canonical 模式只认识 sttyerase 设置的那个字节(127)。

如果你的 Backspace 键行为异常(按了不删字符反而显示 ^H ),原因就是你的终端发的是 byte 8stty 期望的是 byte 127 。修复方法是 stty erase ^H ,把删除字符的映射从 127 改到 8。

Ctrl-S 冻屏之谜

Ctrl-S 发送 byte 19 (ASCII 名 XOFF ),OS 终端驱动收到后会暂停向终端输出——这就是古老的"软件流控制"。在 90 年代的低速串口终端上这很有用(输出太快来不及看就按 Ctrl-S 暂停, Ctrl-Q 恢复),但今天几乎没人需要这个功能了。

问题在于 Ctrl-S 这个按键被 XOFF 占了,导致 readline 无法用它做"前向搜索历史命令"( Ctrl-R 是反向搜索, Ctrl-S 本应是正向搜索)。解决方法是用 stty -ixon 关闭软件流控制,这样 Ctrl-S 就不再触发 XOFF,而是被传给 readline 使用。

ASCII 名字可以忽略

每个控制码在 ASCII 标准里都有一个正式名字,比如 byte 3ETX (End of Text)、byte 26SUB (Substitute)。但这些名字是为 1960 年代的电报机设计的——那个时代的 ETX 表示"报文结束",跟今天终端里 byte 3 的作用(发送 SIGINT 终止程序)毫无关系。33 个控制码里,大约一半的 ASCII 名字跟它今天在终端中的功能对不上,所以不如直接忽略这些名字。

原文链接: ASCII control characters in my terminal