MoreRSS

site iconThis cute world修改

於清樂(二花),声学专业背景,从事全能运维和SRE工程师,热爱音乐、运动和茶文化。
请复制 RSS 到你的阅读器,或快速订阅到 :

Inoreader Feedly Follow Feedbin Local Reader

This cute world的 RSS 预览

我看见的世界

2026-05-01 20:33:30

2026 年 2 月 1 6日,除夕夜。

0 点 11 分,窗外鞭炮声还没停,我在本地跑起了 Qwen3.5-397B-A17B 的 2bits 量化版,尝试发了一张经典的 NixOS 天线宝宝 meme 图给它分析,它分析地相当到位!我激动万分,跑去跟很多朋友分享,「也是在本地用上多模态 LLM 了」。

群里立刻有朋友甩过来一张meme:「隔壁家叔叔过年了还在Cursor/OpenClaw/Codex/…,你可千万不要变成那样。」我对着屏幕乐了半天,体会到一种奇妙的割裂感——我身处中国一个偏远的小山坳里度过除夕,却正跟全世界对开源 AI 感兴趣的人们共享同一种激动的心情!

之后 Qwen 陆续开放小模型权重,尤其是 Qwen3.5-35B-A3B 跟 Qwen3.5-27B 两款,凭借出色的智能和能在消费级显卡上跑的体量,迅速在 r/LocalLLaMA 等 self-hosted 社区掀起了狂欢。我也凑热闹,拿它们对接 OpenClaw,效果还真不错。

回想三年前的四月,我在 RTX3070 笔记本上跑 ChatGLM 6B int4 量化版,只能回答些简单问题,还满嘴幻觉,问答不了几轮就会显存 OOM. 而如今依据 artificialanalysis.ai 的评测数据,一张 RTX3090/RTX4090 就能本地流畅推理的 Qwen3.6-27B,其智能程度甚至超过了去年底发布的 DeepSeek V3.2,与闭源的 Gemini 3 Flash 站到了同一水平线。

尤其是刚过去的四月,几乎每隔一两天就有一个新模型发布。从 Qwen3.5 到 GLM、Kimi K2.6,再到 DeepSeek V4 Pro 和 Mimo V2.5 Pro,中国的开放权重模型紧咬着美国闭源模型的步伐。这让我振奋,甚至作为中国人有点自豪,好像自己也出了力似的。虽然其中大部分模型都因为过于巨大,我没机会在本地运行他们,但这仍然具有非凡的意义——它们能催生大量基于这些开源模型的新研究、推动 AI 技术的进化,同时也能催生许多数据敏感型或者成本敏感型中小企业对 AI 的应用,而这将最终普惠大众。

总的来说,今年是 AI 加速进化的一年。

我 2 月份以来一直在密切关注着 AI 领域的最新进展,为各种新变化而兴奋不已。但兴奋过后,一种虚无感涌了上来——工具越来越强,我却越来越不知道该拿它做什么。

公司去年就给我们买了 Cursor Pro 套餐,内部也有各种平台能用上 Codex/ClaudeCode, 我自己最近几个月也陆陆续续充值了 OpenRouter, Kimi, Aliyun, GLM, Minimax, DeepSeek, Mimo 等诸多国内的 AI 套餐或者 API 平台几番试用。作为一名 SRE,我在工作中用 Cursor 和 Claude/Codex 写了不少代码和配置,但整体而言,Coding 在日常工作中占比并不高,而且大多偏简单。再加上考虑到我手中超高的系统权限,我在本地运行任何 AI 工具时都一直保持谨慎。

一方面,我为 AI 暂时还无法替代我的工作而庆幸;另一方面,我也在为自己找不到 AI 能发挥它最大价值的应用场景而感到迷茫。我知道 AI 现在写代码很强大,但是我脑袋空空没有 Ideas.

四月份,我去了山西晋城参加朋友精彩的婚礼,他还请我们看了规模宏大的打铁花,相当震撼,铁花绽放的那一刻就像整个银河系一般在我眼中迅速放大;接着又跑到西安跟 @reaink 吃饭,认识快十年了第一次线下见面,聊了很多;之后又去兰州、桂林转了一圈,吃了兰州的手抓羊肉、桂林的米粉,最后回老家过五一。一路上我越来越强烈地感觉到,在计算机的世界里,我可能找不到现在最急需的东西。我更需要离开电脑,在手头的书里翻一翻线索。

扫了一圈书架,《我看见的世界——李飞飞自传》映入眼帘。去年买的,但是过去一年了甚至还没拆封。

我花了两天时间读完了它,这是我近两年看得最顺畅的一本书,看到与我经历相似的地方我颇有共鸣,看到俏皮的地方我会心一笑。看到她写刚进入普林斯顿的感受,我也回想起来自己刚从十八线小县城进入大学校园的时候、第二份工作刚入职就领到了苹果电脑跟一张升降桌的时候、发现自己的领导是北大本硕的时候,也都觉得自己像是刘姥姥进了大观园,不敢想象自己能拥有这一切。她在追逐北极星路上有过的迟疑、痛苦,也都让我回想起自己自学计算机时的种种。

以前我也读过很多国外的文学作品,也曾为其中内容感动或愤慨,但仍然会觉得它们都离我太远了,始终有一层隔阂在。但在读了李飞飞的作品后,再加上最近一年也去日韩玩了一趟,最近正在筹划 9 月去欧洲玩一圈顺便参加 NixCon, 这些加在一起,我突然感到这层隔阂消失了。

我开始继续读其他的书,现在在读《枪炮、病菌与钢铁》与《科学革命的结构》。这是第一次,我学过历史以来,这么迫切地想重温世界史和科学史。我想知道:生产力的发展、科学的革命,落到一个个具体的人身上,到底会造成什么影响

科学家追逐知识是因为永无止境的好奇心,但这好奇心不一定导致好结果,或者说好坏很难一概而论。核物理能造原子弹也能造核电站;AI 能帮我写代码,也能替换别人的工作,甚至已经被有意识地用于战争。

AI 的发展,最终会造就新一轮的「枪炮、病菌与钢铁」吗?会带来新一轮的「纺织女工大下岗」吗?当下那些光鲜亮丽的 AI 应用,其水面之下是否暗藏危机,未来会不会再一次酿出雾都孤儿、镭女郎那样的惨剧?李飞飞因个人经历而创建了斯坦福以人为本人工智能研究院,我很庆幸当今 AI 领域还有这样的先驱愿意去推动这些事情。但我们也很清楚,当 AI 的萌芽被培育出来后,后续的发展就已经不是谁能够完全掌控的了。

我相信这一轮 AI 的发展长期看会使人类受益,很可能是新一轮科学大爆发的开端。但进步总是伴随着牺牲,从个人的角度看,仅仅是丢掉工作,或许已经算是比较好的结果了。

在过去十多年中,人工神经网络逐渐从科技界的边缘走向舞台中央,传统的机器学习、NLP、CV 研究在近几年被快速边缘化,这些领域的研究者也大都转而投入这股神经网络浪潮中。而在我们普通打工人的领域内,在过去的一年多里,我们已经明确的看到了 AI 替代人类编程、创作音乐、绘画、修改照片、剪辑视频的信号,很多岗位已经在收缩,首当其冲的就是应届毕业生。

SRE 这个岗位因为主要职责并非编写代码,目前还算安全,但这只是暂时的。我们已经看到像 resolve.ai 这样的工具出现,它内化了不少 SRE 的工作流,目前虽然还很粗糙,但方向很明确。公司内部也在探索给 Codex/Claude 各种内部 git/metrics/cloud/k8s 权限,让它辅助完成各种 Infra/SRE 的工作。

当然,在真正的人工智能到来之前,AI Agents 看起来仍然需要更专业的人士来 supervising 它、给它清晰的目标并评估其成果,或者说替它背锅,但这些旧岗位的缩减已成必然,而新的需求与岗位却还隐藏在迷雾之中。

那么,我们将何去何从?作为一名新时代的「纺织女工」,我不禁发出如此疑问。

从 2019 年 6 月买了张绿皮火车票从合肥奔去深圳开始我的打工仔之旅,到现在就快满 7 年了。这 7 年里,我从一个身无分文、自卑怯懦、技术也半桶水的菜鸟,成长为了能独当一面的技术专家,但相对的我对技术的热情却有消退的迹象。

过去两年的我会觉得自己有点像一条已经实现了自己梦想的咸鱼,对此时此刻拥有的一切都感到相当知足(俗称现充),探索未知的动力却明显的下降了。

其实以前我就思考过一个类似的问题——为什么我好多学历牛逼、而且工作多年的同事,远不如我在各种技术爱好者圈子里碰到的朋友们那样技术强悍,甚至从未听闻过许多前沿的新技术?

我得出的结论是:大部分 IT 从业者不像这些技术爱好者那样热衷于技术,技术对他们来说是养家糊口的手段,不是玩具。他们下班后要顾家、要生活,很可能还有其他更感兴趣的事情,精力自然流向别处。这不是对错问题,只是选择不同。而我很幸运——或者说很幼稚——到现在还把技术当成玩具,也因此更容易在技术上脱颖而出。

过去两年的我就有点往非技术方向靠拢的趋势,我越来越多的时间花在登山徒步、游泳骑行等各种其他爱好上,工作上则越来越依靠吃当初的老本。倒不是说这不好,身体健康当然重要,一个人也理所当然可以拥有很多的兴趣,但我技术方面最近几年没啥长进也是事实。

要说现在的我跟 7 年前初来乍到深圳的我有什么区别的话,最明显的一点应该是「限制与自由」:7 年前的我如同一张白纸,什么都不懂,也什么都没有,住的是 10 平米的城中村,每顿饭都得精打细算,我渴望改变现状,我如饥似渴地学习各种全新的知识。而现在的我仿佛拥有了我当初想要的一切,而且还远程上班,好似完全自由了,反而失去了探索未知的动力。

或许应该庆幸 AI 时代就这么突然到来了。它给了我新的限制,而限制,也许恰恰是自由开始的地方。

这可能也是我喜欢「重装徒步」的原因,我喜欢的是背着十多公斤的背包在我第一次见的风景间穿梭,精疲力尽的到达营地后,搭建好帐篷,过滤好饮用水,煮点热乎的东西吃,然后打开帐篷外账,躺着看星星。看累了之后在全身的酸痛、闷热的天气与嘈杂的山林中艰难入睡。

我在家也能随时吃到热乎的,也随时能在天台上看星星,这很舒适,但相对而言就显得无聊。

恐惧或焦虑都源于对未知的想象,而探索未知,正是一个人能经历的最有意思的事情!

不用去考虑一时的成功或者失败,单纯为了满足我的好奇心,我想我应该去追寻这颗新的北极星。

唯一不变的只有变化本身。

我的 2025 - 步履不停

2025-12-27 01:01:00

今年不论是生活上还是工作上都变化颇多。

如同我 11 月份写的 大梦一场,我在今年 1 月份辞职后 gap 了几个月,在 5 月入职了新公司。新工作薪水大涨,而且是远程,很自由,我大部分时间都在老家上班,业余生活相比往年也丰富了很多。

新工作是机缘巧合之下,在 X 上发求职推文找到的:

在老家刚工作两周的时候也发过条 X 推文(其中提到的新购办公用品,公司也给报销了 USD$300):

在新公司的工作内容跟我前司区别不大,仍然是云计算成本优化、网络链路优化、CICD、监控告警、日常故障排查之类的内容。

全年做出的工作成果还不错,给公司省了不少钱,也做了几个新项目,拿到了很不错的绩效,但是更多是吃以前的技术老本,并没有做出什么值得称道的技术探索。

2025 年是我的飞行元年,1 月 30 号(大年初二)是我第一次坐飞机,从深圳飞回老家邵阳。

第一次坐飞机 - 坐了 20 分钟摆渡车才找到飞机...

在云彩上了

如前所述,我一月份辞职了嘛,然后一直 gap 到 4 月中旬才开始找工作,这期间全国到处旅游跟找同学朋友玩又坐了四五次飞机跟几次高铁。6 月份的时候又去香港参加 KubeCon China, 坐了高铁去深圳,回来是飞机。然后 11 月份公司在云南西双版纳团建飞了个来回,再加上 12 月我跟 @Aspirin 去日本玩了一圈,长沙-上海-日本一个来回又飞了 4 趟。

航旅纵横 APP 显示我累计飞行 12 次,总共 22h19min, 累计里程 15225km. 算是一个从 0 到 1 的突破。

航旅纵横 - 飞行里程统计

今年 2 月到 4 月中旬这段时间在国内逛了很多地方,再加上后面找同学朋友玩、参加技术会议啥的, 今年一整年基本就是在长沙、邵阳、深圳、上海、苏州,这几个地方来回跑,也到香港、张家界、凤凰古城、重庆、安徽安庆以及南京玩过一圈,除了凤凰古城有点太商业化了之外,其他几个体验都很好。

苏州的周庄古镇很有江南韵味,南京的烤鸭是一绝(比北京烤鸭好吃),张家界的鬼斧神工云蒸霞蔚蔚为壮观,重庆的豆花饭跟火锅超级好吃,安徽同学的婚宴菜肴也很有特点。大城市方面,上海跟香港一样摩天大楼跟近代历史建筑交相辉映,跟深圳这样的年轻城市区别明显。

12 月则是跟 @Aspirin 到日本玩了一周时间,时间安排上是东京 3 天、京都 2 天,再大阪 3 天这样子,吃了很多日本特色料理,有豚骨拉面、蘸面、鳗鱼饭、寿司、牛肉寿喜锅、他人丼、生牛肉丼、大阪烧,还有知名的日本穷鬼三件套——吉野家、松屋、食其家。总体感觉就是很有新鲜感,不难吃但是也谈不上喜欢吃。以及日本的很多菜都偏咸,辣味跟国内也有区别,这个是真有点吃不惯,以致于我回到长沙后连吃了好几天红油馄饨才缓过来,感觉在日本呆一周像是呆了一个月…

物价上感觉日本跟香港基本持平,是内地的 2 到 3 倍,日本甚至还有个别商品价格几乎跟大陆一致, 这方面比香港要强。住房价格方面东京 > 京都 > 大阪,高铁(新干线)地铁(JR、电铁跟各种私铁) 跟公交也基本都是内地 3 倍的样子(比香港九巴低不少),铁路系统非常有特色但也很复杂,像是大陆地铁跟高铁的混合体,分啥急行、准急、特急,还有指定席,有的要换站乘车,又的又不用,甚至还有中途解离的车——前 4 节车厢跟后 4 节车厢分别前往不同的终点。作为世界知名的大都市圈,熟悉了这套系统后,出行确实非常方便,感觉长三角珠三角可以借鉴下其中部分元素。

从日本淘了几本 CD 回来,都很有纪念意义:

  • Supercell: 初音未来早期非常经典的专辑,所有歌曲都很好听。
  • Greatest Hits 2011-2017「Alter Ego」:罪恶王冠是我的日漫入坑作之一,当时看完后一直单曲循环「エウテルペ」
  • シングルコレクション 2002-2008:Humbert Humbert 是一个日本民谣组合,我从 16 年一直听到现在。
  • Frieren: Beyond Journey’s End (Original Soundtrack):最近两年看过的印象最深刻的一部动漫,其中的歌曲我也经常单曲循环。
  • 还给老妹带了 Bang Dream 的几本 CD,其中有一本是「迷跡波

其实还很想买 Rolling Girls 的专辑,不过当时没想起来,下次再补吧。

回国后就买了台 CD 机跟新耳机,可能是功放的区别,听起来确实比我七八百块的无线蓝牙耳机效果更好些,听着更舒服,但是听起来跟我用 Macbook Pro 插上耳机听网易云的歌曲没啥区别,可能更多的还是一个仪式感吧 hhh

CD 机与碟

顺带一提,我们离开日本前的最后一顿是天下茶屋站旁边的食其家吃的,然后在从长沙黄花机场回租房的路上又看到路边有一家食其家,瞬间产生了点我好像还在日本的感觉。查了下全长沙一共才三家店,就巧到被我碰到其中一家。

今年应该算是我真正走出去的一年,在这之前我几乎只在湖南邵阳(老家)、安徽合肥(上大学)以及深圳(打工仔)呆过,人比较宅,基本没去远地方旅游过,最远的可能也就是近两年到武功山、香港徒步了几次。

如果说 2024 年我最大的运动成就是徒步,那 2025 年无疑是游泳。

今年差不多是新工作略微稳定后才开始尝试各种运动,先是 6 月份玩了个把月的陆地冲浪板跟跑步,7 月份买了辆山地车之后骑行了一个月,但是 8 月份学游泳找到点乐趣后,基本就放弃其他运动,只练游泳了。

最开始是 7 月份的时候天气变热,开始在老家小水潭游泳,但还跟之前一样只会个狗刨式。8 月份的时候去上海参加 AOSCC 2025 跟 NixOS Meetup, 住的民宿刚好带一个 10 米长度的小泳池,在这个民宿跟着 B 站各种视频教程学了 6 天游泳,把蛙泳给入了门,开始觉得游泳很有意思。之后就在日常老家小水潭游,出门玩的时候也在长沙、深圳游过几次 50 米的标准泳池,游泳技术越发精进。11 月公司在云南团建,我跟同事在酒店的小泳池(长度感觉是 20 米)游了两天。之后回到长沙,发现租房周边就有个游泳馆,25 米的池子,游了几次觉得不错就办了张半年卡,花费 1111 大洋,现在只要呆在长沙,我基本是游三休一的节奏。

最近学习波蛙已经掌握了些诀窍,同时也尝试了一点自由泳。总体感觉游泳很有意思,而且通过游泳, 今年我的形体也出现了很好的变化,倒三角身材初现端倪了,只是肚子上的赘肉仍需努力。

附上 2025 最后一游,也刚好是今年的最佳成绩:

2025 年最后一次游泳记录

今年是周边同龄人集体结婚的一年,不过我貌似仍然没啥找对象的想法,感觉 30 岁后再考虑这个问题也未尝不可,再爽玩两三年先(

今年已经参加过的婚礼:

  • 7/4:一个三十多岁的堂哥突然开窍,相亲没多久就火速成婚
  • 8/1:大学室友 Zhan 在安徽大别山的山坳坳里结婚,寝室 6 个人到齐了 5 个

预计春节前还要参加的婚礼:

  • 2026/1/7: 去安徽砀山参加另一个大学室友 Hu 的婚礼,已经买好了高铁票就等出发了
  • 未知:堂弟今年下半年换工作后跟一位同事擦出爱情火花,也是火速订婚,预定年前结婚
  • 2026/2/14:还是大学室友,Zhao,预计春节前结婚

其中 8 月 1 号这场婚礼,是我今年印象最深刻的一次极限操作:

7 月底的时候我在上海参加完 AOSCC,本想先在上海干几天活,然后顺路请个假去安徽吃喜酒,应该是件很轻松惬意的事情。结果 7/30 派到我手上的一个小故障越查越炸裂,升级成 P0,和同事熬夜搞到第二天凌晨 2 点多才临时止血。7/31 下午我先是乘高铁到苏州,跟其他 3 位大学室友汇合,草草吃完晚饭就开车上高速 4 小时飙到安庆。0 点入住酒店,睡前我翻了下后台记录又发现个更灾难性的问题,又跟领导同事一起鏖战到凌晨 3 点多才初步解决。第二天一早又开 3 个多小时盘山公路才到新郎 Z 的家里,鞭炮作响锣鼓震天,合影、随礼、举杯一条龙。下午 2 点多我们吃完午宴就立即返程苏州了。还好我不会开车 hhh 他们 3 个人又轮班开 7 个多小时,人歇车不歇。回到苏州我又立即高铁返回了上海,到 8 月 1 号夜幕降临的时候,我已经在上海商场,跟 ddl 还有 nobody 在排队等着干饭了。

婚礼 24 小时,往返 1000 km,线上救火+线下道喜+无缝社交,血条见底,那叫一个惊险刺激。

或许该叠个甲,今年像这样猛猛加班仅此一次,整体工作节奏我仍是相当满意的。

技术方面今年有点乏善可陈,今年读完了 Linux/Unix 系统编程手册 上下两册,借助 AI 写了一个Linux 桌面系统 系列,但是没怎么实践这方面的知识,现在又忘得差不多了 2333

在现在 AI 发展这么快的当下,技术博客的受众是越来越少了,常见的技术问题跟细节基本都能直接跟 AI 沟通。我今年写「Linux 桌面系统」系列也主要是让 AI 生成,我主要负责验证相关内容的正确性,顺便学习相关技术。这个过程中学到了很多,也修正了不少 AI 自己臆想出来的虚假内容。实际写出来有点类似一个 Wiki, 它比 Arch Wiki 更精炼更成体系,相比直接问 AI 它的准确性要更高(毕竟经过了人工校对与实际测试)。

得益于新工作的灵活性,我今年参加了 4 次技术会议:

  • 6 月份的时候去香港参加了 KubeCon China,内容基本都是 AI, 也写了一篇KubeCon China 2025 见闻

    6/10 欢迎光临 KubeCon China 2025

  • 7 月底的时候到上海参加了 AOSCC 2025, 技术氛围真好,还感受了一波大学生们的青春气息

    7/27 上海 AOSCC 纪念墙

  • 8 月份又在上海参加了 Nix Meetup, 一起干了好几顿饭。我还在台上讲了下自己的入坑经历,被大家叫 Ryan 老师有点受宠若惊(
    • 从打算搞到最终举办就十来天的时间,结果群友们还搞到了 NixOS 基金会的赞助,整了很多精美小礼物,很有爱了

      8/9 又回上海参加 Nix Meetup 了

  • 9 月份又到上海参加 PyCon China 2025, 见到了很多 X 上认识很久的 saka yihong 等大佬,领了许多小礼物,还跟上海 nonebot 群友们一起干了顿饭,顺便给他们安利了 NixOS(

    9/20 PyCon China 2025 跟 nonebot 的朋友们合影

以及 GitHub 上 followers 终于突破了 1000, 获得的 stars 也超过了 6000, 不过这仍然基本都来自我 2023 年创建的几个 Nix 项目。

2025/01/01 GitHub 统计数据

2025/12/27 GitHub 统计数据

今年开始把 AI 应用到各个方面,公司给整了 Cursor Pro 年费会员,我自己也给阿里千问、智谱 GLM 跟月之暗面 Kimi 充了不少钱。总体感觉,借助 claude/cursor 这类工具来写代码跟文档,可用性已经很高了,指令得当的情况下需要人工介入的次数不多,简化了不少繁琐的工作。但整体的定位仍然是辅助工具,我用 cursor 时也仍然不喜欢它的 Agent UI, 传统的 VSCode UI 布局更让我有掌控感。

今年年底全球开始传出各种通过 AI 提效然后裁员的新闻,包括我现在的公司也裁了一大批客服人员, 并且提倡让开发人员自己完成简单的 UI 设计类工作,AI 替代人确实是正在进行时,但短期内我的岗位还算安全。

总的来说,AI 方面我今年的感想是:能做的越来越多了,但是绝对不能全盘信任它!人工审查仍然是必不可少的,尤其是对自身权限极高的 infra/SRE 同学而言

再次强调,infra/SRE 绝对不应该在 prd 环境中使用 Cursor Auto-Run Mode 这种自动驾驶模式!希望体验这些最新技术的话,最好是放在没有 PRD 环境权限的环境中跑,譬如单独的 VM.

年底组里就有 infra team 的同事在使用 Cursor 的 Auto-Run Mode 为某数据中间件添加备份功能时,备份功能还没搞好,就把重要数据删掉了。直接原因是 Cursor AI 自动执行了kubectl replace -f xxx.yaml --force 导致一个 StatefulSet 被 Delete 再重新 Create,进而导致该数据中间件挂掉。次要原因是用了默认的 StorageClass, ReclaimPolicy 是 Delete,这导致前述流程中 PV 也被级联删除,数据完全丢失。还好其他地方还有一个最近一段时间的备份,勉强救回了大部分数据,不然都不知道这个事该怎么收场。

同事甚至一开始还没意识到是 Cursor 的锅,怀疑是我们的 ArgoCD 强制更新触发了类似 Delete 的操作,最后是我翻遍了 ArgoCD 跟 K8s Audit Log,定位到 Delete 请求来自同事自己的账号,他才进一步找到对应的 Cursor 操作记录与 Delete 日志。

今年可能也算我的理财元年,去年底辞职前去香港开了几张港卡,又开了几家港股美股交易所,国内的 A 股账户也开了两个。在股市上投入了少许资金,巅峰的时候浮盈 20%,但是一年接下来收益是负的 hhh 不过算上我在银行支付宝的其他基金理财产品,总体收益还是正的,赚了一两万块钱吧。

加密货币在几年前玩过一点,今年基本没咋动,就留了点 ETH/SOL/UNI 随波逐流。

目前并没想着靠这些赚钱,只是觉得需要去拿点小钱去玩一玩,熟悉下现代金融是怎么回事。一年下来实际投入比最初预期高不少,港股 A 股跌宕起伏好几次,心慌意乱做了不少错误的决策,算是对这套玩法有了个大概的了解。

总的来看,今年是我一直在旅途上的一年,可能也是我过去十年中最健康的一年,我 2025 年的运动量远超以往。

我在去年年终总结的文末写了,对自己 2025 年的期许是「深入浅出 Linux,徒步中国、徒步世界」,一年过去,勉强算是达成了一半。我读完了《Linux/Unix 系统编程手册》,写了好几篇 Linux 桌面系统相关的文章,徒步走过了中国的多个城市,在日本 city walk 了一周多,还学了小半年的游泳,相比 2024 年,生活又丰富了许多。

接下来的 2026 年,我对自己的期望是「精进英语、泳技与 Linux,探索世界」,用 OKR 类比的话,这个 Object 对应了如下 Key Results:

  • 英语:口语词汇量进阶,综合水平达到 B2 级别,满足我旅游及全英文工作的需求
  • 日语:学完标日初级,达到 N4 级别。要求不高,能看懂简单动漫生肉+日常沟通就行
  • 游泳(25m 短池):蛙泳百米 1m50s、千米 22mins,潜泳 25 米(单趟)
  • 旅游:拿到驾照,自驾游中国,以及拓展亚洲跟世界地图的足迹
  • Linux 学习
    • 积极参与 NixOS 上游贡献
    • 尝试写几个 Linux 小工具,或者参与相关项目的开发,避免手艺生疏

最后,附上我今年的精选照片吧,大致按时间顺序排列:

1/19 香港 利源东西街

Gap 期间:

2/15 跟朋友们在上海K歌,瓜哥在唱 MyGo

2/17 上海百联ZX - miku 好可爱

3/3 周庄古镇 - 下雨了

3/3 周庄古镇 - 小巷灯影

3/5 南京穹窿山 上真观 三清阁

3/9 南京栖霞山

3/14 南京中山陵

3/26 凤凰古城

3/27 张家界 - 武陵源

3/27 张家界 - 袁家界天下第一桥

3/28 张家界 胜似仙境

3/28 张家界 花都结冰了

3/29 张家界 小猴子是真不怕冷

3/30 涪陵火锅

3/31 涪陵豆花饭

4/3 重庆

4/4 对面就是洪崖洞,到了晚上简直人山人海

4/8 重庆独特的轻轨

5/3 东莞松山湖小火车

5/5 深圳 东西都打好包了,就等着运回老家了

在老家的工作状态记录:

5/9 邵阳 回老家第一天,家门口的景色

5/23 山里的蒲公英

林间小路

5/24 山里的覆盆子/树莓

5/27 插秧季

5/28 新置办了升降桌跟双显示器用于工作

然后就上海、老家两头跑:

6/10 香港 欢迎光临 KubeCon China 2025

香港 大 SUSE 上一只小 SUSE

香港 Switch 店在宣传 Miku Boxing

香港 累计有三个朋友 KubeCon 期间在这里买了 Switch 2,它这波血赚

6/17 邵阳 家门口的奇特天气 - 局部降雨

6/20 后山超美的瞬间

7/23 在后山骑行

7/27 上海 AOSCC 纪念墙

7/27 上海 AOSCC 纪念墙 - 最终效果

8/1 室友在安徽大别山山坳坳里结婚,寝室 6 个人到了 5 个

8/9 又回上海参加 Nix Meetup 了

8/13 我的各种参会证以及 keep 跑步纪念奖牌

9/20 PyCon China 2025 跟 nonebot 的朋友们合影

9/20 ddl 送给我的 nonebot 纪念品,以及从方块那批发的 NixOS 挂坠

在西双版纳团建两天:

11/21 西双版纳 千年绞杀滕

11/21 西双版纳 星光夜市 - 好看 但是东西贼贵

年底的日本游:

12/7 秋叶原的魔禁广告牌

12/7 秋叶原

12/7 台場的 Telecom Center 展望台

12/8 京都 我在日本吃过最贵的一顿饭 鳗鱼饭

12/9 周恩来总理写的雨中岚山

12/9 周恩来总理写的雨中岚山

12/9 12 月份的岚山挺好看的

12/9 岚山

12/9 岚山

12/10 生田神社 穿传统服装来祈福的日本家庭

12/10 神户 生牛肉丼

12/10 神户 JR 舞子站

12/10 神户 舞子海上散步道

12/12 大阪烧

12/13 日本 老太太童心未泯

12/13 日本 准备返回上海了 - 在等去关西机场的电车

大梦一场

2025-11-04 22:38:53

回到乡下老家,我把二楼大客厅布置成了办公室,置办了张大号升降桌,配上两台大显示器,宽带也升级到了千兆。

今年大部分时间,我就在这里上班。

上班累了,一抬头,落地窗外就是一片稻田。离家 50 米是村活动广场,我偶尔去玩玩滑板;天热了, 每天中午就去山里水潭练习游泳;下午下班后,常沿着进山路跑上一两个小时,或者骑行;晚上,就刷点动漫,或者研究点技术。每隔一两个月,我会去一线城市参加些感兴趣的技术会议,感受下氛围,或者干脆找个地方旅游上班,顺道联络联络老朋友老同学。

现在这样的状态,就是我目前理想中的生活。


很难想象,就在六年前,我曾心灰意冷,觉得前途无比黑暗。

那时的我学业彻底失败,孤注一掷地奔到深圳,想找一个进入 IT 行业的机会。幸运的是,我入职了一家小作坊当「全干工程师」(啥都得干),在城中村 10 平米的单间里,用两年青春换来了技术经验和一点自信心。接着跳槽,职业生涯才算步入正轨。又过了四年,因为一些事情选择了辞职,Gap 3 个月后,机缘巧合下才入职了现在的公司,开始了如今的生活。

这其中种种,我之前在《我的四分之一人生》 中已讲得很详细,只是自那之后到现在,又是两年过去了。

上周一口气把《凡人修仙传》动画刷完,看到主角韩立结丹时,里面一句评语让我感慨万千:

伪灵根、散修,能走到今天这般境地,还真是不容易啊。

是啊,不容易。年岁渐深,码龄渐涨,薪水也水涨船高,我终于走到了一个能喘口气的阶段。虽然我现在的薪资可能只是很多人的起点,但知足常乐,开心比啥都重要。只要不背上买房、结婚这些重担,即使不刻意去省钱,到 35 岁我也应能攒下一笔可观的财富。到时候,就算 IT 这碗青春饭真没得吃了, 只要手里有钱,不管接下来干啥,底气总会足很多。


当然,能从那段黑暗里走出来,光靠努力是不够的。正如一位长者的名言:「一个人的命运啊,当然要靠自我奋斗,但也要考虑到历史的行程。」

我很难说清自己是否有 IT 天赋。大学自学编程时,经常憋好久都写不出几行代码,无数次想过放弃瞎折腾,老老实实把声学学好算了。即便是现在,代码能力也算不上多强。

要说有什么比天赋更重要,可能还是兴趣吧。因为是在做着自己真正喜欢的东西,所以不觉得苦不觉得累。在困难面前,我往往诉诸行动,而不是怨天尤人。还有就是,我尽量让自己每个错都只犯一次。可能就是这些不起眼的习惯让我慢慢攒下了现在这份不错的 GitHub Profile、持续更新的技术博客,以及在 X 上靠分享获得的一点知名度。

当这些个人积累,恰好又遇上了 IT 行业的时代浪潮,再加上一点点运气作为催化剂,便产生了奇妙的化学反应。正是这些因素凑在一起,才得以让一个本科结业的学渣,也能次次找到满意的工作。


年轻时用健康和时间换钱,压榨精力,忽略家人,也压抑着心底的小念想。这两年,我开始各种「找补」:带父母妹妹看牙洗牙,用徒步、游泳、骑行找回健康,把厨房电器填满,到处旅游结交朋友。

2025 年已经临近尾声,我这份新工作还有乐乐的学业都逐渐稳定了下来,Q3 在工作上做得还不错,领导给出了「Exceeds Expectations」的评价,算是个很不错的新开始。

总之,我又回到了我出生的地方。安徽建筑大学那朦胧的易海,图书馆里陪伴我四年的 IT 书架区,那张写着我挂掉十多门课的成绩单;深圳摩天大楼里的工位,早晚高峰的地铁公交,以及城中村那 20 平的单间…… 这一切,都渐渐成了回忆,有时甚至觉得那只是大梦一场。

梦醒,我渐渐睁开双眼,拉开窗帘,打开落地窗,迎接新一天穿过稻田的阳光。看来,又会是一个风和日丽的日子呢。

未来又待如何呢?「且行且寻」。

Linux 桌面系统故障排查指南(六) - 系统关机与电源管理

2025-10-19 10:22:33

AI 创作声明:本系列文章由笔者借助 ChatGPT, Kimi K2, 豆包和 Cursor 等 AI 工具创作,有很大篇幅的内容完全由 AI 在我的指导下生成。如有错误,还请指正。

系统关机看似简单,但背后涉及了繁杂的资源清理和状态管理过程。当你点击关机按钮,系统却卡在那里不动,或者出现各种奇怪的错误信息时,理解关机流程和故障排查方法就显得尤为重要。

除了关机,Linux 还提供了休眠和挂起两种重要的电源管理功能,它们可以让系统快速进入低功耗状态,同时保持工作状态,是日常使用中非常实用的功能。

作为这个系列的最后一篇文章,本文将探讨系统关机的完整流程,以及休眠和挂起功能的配置与故障排查,从优雅关闭到强制关机,从服务停止到资源清理,从电源管理到状态恢复,全面了解系统的电源管理机制。


systemd 管理的关机过程分为四个主要阶段,每个阶段都有明确的目标和顺序,确保数据完整性和系统稳定性。

关机阶段

  1. 用户会话清理阶段(约 1-5 秒):

    • 通知所有用户会话即将关机
    • 优雅关闭用户应用程序
    • 回收用户设备权限
  2. 系统服务停止阶段(约 2-10 秒):

    • 按依赖关系逆向停止系统服务
    • 卸载文件系统(除根文件系统外)
    • 网络服务断开连接
  3. 内核资源释放阶段(约 1-3 秒):

    • 同步所有文件系统到磁盘
    • 卸载根文件系统为只读
    • 终止所有剩余进程
  4. 硬件关机阶段(约 1-2 秒):

    • 通过 ACPI 发送关机信号
    • 固件接管系统控制权
    • 所有硬件设备断电

当用户发起关机时,systemd 首先处理用户会话的清理工作,确保用户数据得到妥善保存。

会话清理流程

# systemd 发送关机信号
systemctl start shutdown.target

# 用户会话收到终止信号
loginctl terminate-session <session_id>

# 用户服务停止
systemctl --user stop graphical-session.target

关键操作

  • 会话通知:通过 D-Bus 向桌面环境发送关机信号
  • 应用关闭:等待应用保存未保存的数据
  • 权限回收:logind 回收分配给用户的设备访问权限
  • 服务停止:用户 systemd 实例停止所有用户服务

监控用户会话清理

# 查看会话状态变化
journalctl -b | grep -E "(session|Session)"

# 用户服务停止日志
journalctl --user -b | grep -E "(Stopping|Stopped)"

# 设备权限回收
journalctl -u systemd-logind -b | grep -i "device"

用户会话清理完成后,systemd 开始按依赖关系的逆向顺序停止系统服务。

服务停止顺序

  • 图形服务:合成器、显示管理器
  • 网络服务:网络管理器、DNS 解析器
  • 存储服务:磁盘管理、LVM
  • 基础服务:日志、设备管理

关键服务处理

# 查看关机时的服务停止顺序
systemd-analyze critical-chain shutdown.target

# 监控服务停止状态
watch -n 1 'systemctl list-units --state=deactivating'

# 检查服务停止日志
journalctl -b -1 | grep -E "(Stopping|Stopped)" | tail -20

文件系统卸载

# 查看挂载点卸载情况
mount | grep -v "on / type"

# 文件系统同步状态
sync
echo 3 > /proc/sys/vm/drop_caches

# 检查卸载错误
journalctl -b -1 | grep -i "unmount\|busy"

当所有用户空间服务停止后,systemd 执行最终的系统清理:

文件系统操作

  • 调用 sync() 同步所有已挂载文件系统的数据到磁盘
  • 按照逆向挂载顺序卸载所有挂载点
  • 卸载外接硬盘分区等外部存储设备

进程管理

  • 向所有剩余进程发送 SIGTERM,给它们最后清理机会
  • 等待超时后,对顽固进程发送 SIGKILL 强制终止
  • 清理僵尸进程和孤儿进程

Watchdog 监控

  • systemd 的看门狗机制监控服务关闭进度
  • 如果服务停止超过 TimeoutStopSec,强制终止服务
  • 防止系统在关机过程中无限挂起

资源清理

  • GPU 驱动重置显卡状态,释放 VRAM
  • 网络设备完全断电
  • 音频设备硬件重置

当所有用户空间和内核资源处理完毕后,系统进入硬件关机:

ACPI 操作

  • systemd 通过 ACPI 向固件发出关机指令
  • 进入 ACPI S5 状态,告诉固件关闭电源

固件接管

  • BIOS/UEFI 接管系统控制权
  • 执行电源关断,所有设备(CPU、内存、GPU、外部设备)断电
  • 固件执行最后的清理工作

强制关机保护

  • 如果系统未能正常关机,硬件看门狗可能强制切断电源
  • 用户长按电源键也会触发强制关机

此时机器完全断电,关机过程结束。下次开机将重新开始完整的启动周期。

常见关机问题与优化

  1. 服务停止超时
# 查看超时服务
journalctl -b -1 | grep -i "timeout"

# 检查特定服务配置
systemctl cat <service> | grep Timeout

服务停止超时优化:

TimeoutStopSec 参数控制服务停止的最大等待时间,默认值为 90 秒。systemd 在停止服务时会等待服务自行退出,超时后强制终止。对于快速停止的服务,可以设置较短的超时时间(如 10-30 秒), 配置示例:TimeoutStopSec=30s 设置 30 秒超时。

服务停止优化包括:服务应该正确处理 SIGTERM 信号,完成必要的清理工作;避免在停止过程中进行耗时的操作;确保及时释放文件句柄、网络连接等资源。

  1. 文件系统卸载失败
# 查找占用文件系统的进程
lsof | grep <mountpoint>

# 检查文件系统状态
fsck -n /dev/<device>

文件系统卸载优化:

进程占用检查使用 lsof 命令查找仍在使用文件系统的进程。常见原因是应用程序未正确关闭文件句柄,或进程仍在运行。解决方案是强制终止占用进程,或等待进程自然结束。

文件系统状态检查包括:使用 fsck -n 进行只读检查,不修复文件系统;检查文件系统是否正确挂载,是否有错误标记;定期进行文件系统检查,及时发现和修复问题。

  1. 设备繁忙
# 检查设备占用
lsof | grep /dev/<device>

# 查看块设备状态
lsblk -f

设备占用优化:

设备占用分析检查哪些进程仍在使用设备文件。常见设备包括 USB 设备、外部存储、网络设备等。解决方案是确保应用程序正确关闭设备,或强制卸载设备。

块设备状态检查包括:使用 lsblk 查看设备挂载状态和文件系统类型;检查设备是否处于忙碌状态; 在关机前确保所有外部设备已安全移除。

强制关机处理与优化

当正常关机失败时,可以使用以下方法:

# 安全强制关机
systemctl poweroff -f

# 紧急关机(立即执行)
systemctl poweroff -ff

# 内核强制重启
echo b > /proc/sysrq-trigger

# 内核强制关机
echo o > /proc/sysrq-trigger

强制关机方法:

systemctl poweroff -f 强制关机,跳过某些检查和服务停止。强制终止所有进程,直接进入关机流程,可能导致数据丢失,应谨慎使用,适用于系统响应缓慢但仍有基本功能时。

systemctl poweroff -ff 紧急关机,立即执行,不等待任何操作完成。立即终止所有进程,强制关机,高数据丢失风险,仅在紧急情况下使用,适用于系统完全无响应,需要立即关机。

echo b > /proc/sysrq-trigger 内核级别的强制重启。直接调用内核重启功能,绕过用户空间,即使系统完全无响应也能执行,适用于系统完全卡死,无法响应用户命令。

echo o > /proc/sysrq-trigger 内核级别的强制关机。直接调用内核关机功能,立即断电,最高数据丢失风险,适用于极端紧急情况,需要立即断电。

关机优化最佳实践:

预防措施:定期检查服务配置,确保服务能正常停止;监控文件系统状态,及时处理问题;避免在关机前进行大量 I/O 操作。

优雅关机:优先使用正常的关机命令;给系统足够时间完成清理工作;避免频繁使用强制关机。

故障预防:定期更新系统和驱动;监控系统资源使用情况;及时处理系统警告和错误。


除了关机,Linux 还提供了两种重要的电源管理功能:休眠(Hibernate)挂起 (Suspend)。这两种功能可以让系统快速进入低功耗状态,同时保持工作状态,是日常使用中非常实用的功能。

休眠是将系统内存中的所有数据保存到磁盘(通常是交换分区或交换文件),然后完全关闭电源。当系统从休眠中恢复时,会从磁盘读取保存的数据,恢复到休眠前的状态。

休眠的工作原理

  1. 内存数据保存:将 RAM 中的所有数据写入到交换分区或专门的休眠文件
  2. 系统状态保存:保存 CPU 状态、设备状态、网络连接等
  3. 完全断电:系统完全关闭,所有硬件断电
  4. 快速恢复:开机时直接从磁盘恢复内存状态,跳过正常启动过程

休眠配置

# 检查当前休眠配置
cat /sys/power/state
cat /sys/power/disk

# 检查交换分区大小(需要足够容纳内存数据)
swapon --show
free -h

# 检查休眠文件(如果使用文件而非交换分区)
ls -lh /swapfile

启用休眠功能

# 方法一:使用交换分区
# 1. 确保有足够大的交换分区(建议为内存大小的 1.5-2 倍)
sudo swapon --show

# 2. 获取交换分区的 UUID
sudo blkid | grep swap

# 3. 更新 GRUB 配置
sudo nano /etc/default/grub
# 添加:GRUB_CMDLINE_LINUX_DEFAULT="resume=UUID=your-swap-uuid"

# 4. 更新 GRUB 配置
sudo update-grub

# 5. 重新生成 initramfs
sudo update-initramfs -u

# 方法二:使用交换文件
# 1. 创建交换文件(大小建议为内存的 1.5-2 倍)
sudo fallocate -l 8G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile

# 2. 永久挂载交换文件
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab

# 3. 配置休眠到交换文件
echo 'RESUME=UUID=$(findmnt -no UUID -T /swapfile)' | sudo tee /etc/initramfs-tools/conf.d/resume
sudo update-initramfs -u

休眠故障排查

# 检查休眠支持
cat /sys/power/state | grep disk

# 检查休眠目标
cat /sys/power/disk

# 测试休眠功能
sudo systemctl hibernate

# 查看休眠日志
journalctl -b | grep -i hibernate
dmesg | grep -i hibernate

# 检查交换空间使用情况
swapon --show
free -h

常见休眠问题

  1. 交换空间不足

    • 问题:交换分区或文件太小,无法容纳内存数据
    • 解决:增加交换空间大小,建议为内存的 1.5-2 倍
  2. 休眠文件损坏

    • 问题:休眠文件损坏导致恢复失败
    • 解决:删除损坏的休眠文件,重新创建
  3. 硬件不支持

    • 问题:某些硬件不支持休眠功能
    • 解决:检查 BIOS/UEFI 设置,更新固件

挂起是将系统进入低功耗状态,保持内存供电,CPU 和大部分硬件断电。系统可以快速恢复到挂起前的状态,但需要持续供电。

挂起的工作原理

  1. 内存保持供电:RAM 继续供电,保持数据不丢失
  2. CPU 进入睡眠状态:CPU 进入深度睡眠,功耗极低
  3. 外设断电:硬盘、USB 设备、网络设备等断电
  4. 快速唤醒:通过键盘、鼠标、网络唤醒等快速恢复

挂起类型

  • S1(Power On Suspend):CPU 停止执行,但保持供电
  • S2(CPU Off):CPU 断电,但保持缓存
  • S3(Suspend to RAM):CPU 和缓存断电,仅内存供电
  • S4(Suspend to Disk):等同于休眠

挂起配置

# 检查支持的挂起状态
cat /sys/power/state

# 检查当前挂起模式
cat /sys/power/mem_sleep

# 设置挂起模式(deep 为 S3,s2idle 为 S2)
echo deep | sudo tee /sys/power/mem_sleep

# 永久设置挂起模式
echo 'mem_sleep_default=deep' | sudo tee -a /etc/default/grub
sudo update-grub

挂起故障排查

# 测试挂起功能
sudo systemctl suspend

# 查看挂起日志
journalctl -b | grep -i suspend
dmesg | grep -i suspend

# 检查挂起相关服务
systemctl status systemd-suspend
systemctl status systemd-hibernate

# 检查挂起钩子脚本
ls -la /usr/lib/systemd/system-sleep/

常见挂起问题

  1. 挂起后无法唤醒

    • 问题:系统挂起后无法通过键盘、鼠标唤醒
    • 解决:检查 BIOS 设置,启用 USB 唤醒功能
  2. 挂起后系统重启

    • 问题:挂起后系统自动重启而不是恢复
    • 解决:检查硬件兼容性,更新驱动
  3. 挂起功耗过高

    • 问题:挂起状态下功耗仍然很高
    • 解决:检查外设电源管理,禁用不必要的设备
模式 功耗 恢复时间 数据保持 适用场景
关机 0W 30-60秒 不保持 长时间不使用
休眠 0W 10-30秒 完全保持 长时间不使用,需要快速恢复
挂起 1-5W 1-3秒 完全保持 短时间不使用,需要快速恢复

选择建议

  • 短时间离开(几分钟到几小时):使用挂起
  • 长时间离开(几小时到几天):使用休眠
  • 长期不使用(几天以上):使用关机

混合使用策略

# 设置自动挂起(当系统空闲时)
sudo systemctl enable systemd-suspend.timer

# 设置定时休眠(夜间自动休眠)
sudo systemctl edit systemd-hibernate.timer
# 添加:
[Timer]
OnCalendar=*-*-* 02:00:00
Persistent=true

在实际使用中,大多数用户通过桌面环境的设置界面来配置电源管理功能。GNOME、KDE Plasma、XFCE 等桌面环境都提供了图形化的电源管理设置,可以方便地配置自动挂起和休眠时间。

对于使用 Wayland 合成器(如 Sway、Hyprland)的用户,通常使用专门的 idle 守护进程来管理电源状态。swayidle、hypridle 等工具可以配置系统在空闲时自动锁屏、关闭显示器或进入挂起状态。

电源管理优化

# 检查电源管理配置
cat /sys/power/pm_async
cat /sys/power/pm_freeze_timeout

# 优化挂起延迟
echo 5000 | sudo tee /sys/power/pm_freeze_timeout

# 检查设备电源管理
ls /sys/bus/usb/devices/*/power/
cat /sys/bus/usb/devices/*/power/control

通过合理配置和使用休眠、挂起功能,可以显著提高 Linux 桌面系统的使用体验,既节省电力又保持工作状态的连续性。


在实际使用 Linux 桌面系统时,往往会遇到多层次、多组件交织的故障。通过系统化的排查方法,可以快速定位问题并制定解决方案。本章通过几个典型案例,讲解如何综合使用日志、调试工具和系统命令进行故障排查。

现象:用户登录后,屏幕闪烁后回到登录界面,桌面无法显示。

排查步骤

  1. 检查显示管理器状态
systemctl status display-manager
journalctl -u display-manager -b
  1. 确认用户会话
loginctl list-sessions
loginctl show-session <session_id>
  1. 检查合成器日志(Wayland 示例):
journalctl --user -u sway -f
export WAYLAND_DEBUG=1
  1. 检查 GPU 驱动状态
lspci -k | grep -A 3 -i vga
dmesg | grep -i drm

常见原因

  • 驱动不匹配或未加载
  • 合成器启动失败
  • 用户环境变量设置错误

解决方法

  • 更新或切换 GPU 驱动
  • 使用默认配置启动合成器
  • 检查 $XDG_RUNTIME_DIR$WAYLAND_DISPLAY 是否正确

现象:某些应用程序启动后立即崩溃,或运行中无响应。

排查步骤

  1. 查看用户服务日志
journalctl --user -b -u <application>.service
  1. 启用应用调试信息
export GDK_DEBUG=all    # GTK 应用
export QT_LOGGING_RULES="qt.qpa.*=true"  # Qt 应用
export WAYLAND_DEBUG=1
  1. 分析核心转储
coredumpctl list
coredumpctl info <pid>
coredumpctl debug <pid>
  1. 检查依赖库版本
ldd $(which <application>)

常见原因

  • 缺少或版本不匹配的库
  • Wayland/Xwayland 支持不完整
  • GPU 驱动异常

解决方法

  • 安装或升级依赖库
  • 强制应用使用 X11 或 Wayland 后端
  • 检查驱动更新或使用回滚版本

现象:系统关机卡住,服务停止超时,最终需要强制关机。

排查步骤

  1. 查看关机日志
journalctl -b -1 -e
systemd-analyze blame shutdown.target
  1. 检查服务停止状态
systemctl list-units --state=deactivating
journalctl -b -1 | grep -E "(Stopping|Stopped)"
  1. 文件系统状态
mount | grep -v "on / type"
lsof | grep <mountpoint>
  1. 硬件设备状态
lsblk -f
dmesg | grep -i "error\|fail\|timeout"

常见原因

  • 某些服务或进程未能及时停止
  • 文件系统被占用或损坏
  • 设备驱动异常导致无法卸载

解决方法

  • 强制停止顽固服务:
systemctl stop <service> -i
  • 检查并修复文件系统:
fsck -n /dev/<device>
  • 临时使用强制关机:
systemctl poweroff -ff

现象:应用启动正常,但无法连接网络资源。

排查步骤

  1. 检查网络接口和状态
ip addr
ip route
nmcli device status
  1. 测试 DNS 和连通性
ping 8.8.8.8
dig www.example.com
  1. 查看网络服务日志
journalctl -u NetworkManager -b
  1. 检查防火墙和权限
sudo iptables -L -v -n
sudo nft list ruleset

常见原因

  • DHCP 或静态 IP 配置错误
  • DNS 配置异常
  • 防火墙阻塞访问

解决方法

  • 修复网络配置
  • 检查防火墙规则
  • 重启网络服务

面对复杂问题,单靠经验可能难以定位故障,推荐遵循以下方法:

  1. 日志为先:系统日志、用户服务日志、应用日志是最直接的线索
  2. 逐层排查:从硬件 → 驱动 → 系统服务 → 用户会话 → 应用
  3. 最小复现:关闭非必要服务和应用,简化环境重现问题
  4. 工具辅助journalctlstracecoredumpctllsofperf
  5. 文档与社区:查阅官方文档和社区经验,快速定位常见故障

通过上述方法,可以系统化地分析并解决大多数 Linux 桌面问题,提高系统稳定性和用户体验。

至此,我们已经完成了《Linux 桌面系统故障排查指南》系列的全部六篇文章。通过这个系列,我们全面了解了 Linux 桌面系统的各个组件,从启动安全到网络配置,从多媒体输入到会话管理,从系统服务到电源管理。

Linux 桌面系统虽然有时候会出各种奇怪的问题,但理解其工作原理后,大部分问题都能找到解决思路。关键是要有耐心,多实践,多总结。特别是在电源管理方面,合理使用关机、休眠和挂起功能,可以显著提高系统的使用体验和电力效率。

这个系列到这里就结束了,希望这些内容能帮助你在 Linux 桌面的道路上走得更顺畅一些。

Linux 桌面系统故障排查指南(五) - 网络

2025-10-19 10:21:33

AI 创作声明:本系列文章由笔者借助 ChatGPT, Kimi K2, 豆包和 Cursor 等 AI 工具创作,有很大篇幅的内容完全由 AI 在我的指导下生成。如有错误,还请指正。

网络连接是现代桌面的基础功能,涉及硬件驱动、固件加载、网络管理和 DNS 解析等多个环节。

本文将从网卡驱动开始,经过内核网络栈,到达应用层,了解 Linux 网络系统的完整架构,包括如何配置网络连接,如何设置防火墙规则,以及如何诊断各种网络问题。


网络连接是现代桌面的基础功能,涉及硬件驱动、固件加载、网络管理和 DNS 解析等多个环节。网络故障是最常见的桌面问题之一,理解其工作原理有助于快速定位和解决连接问题。

现代 Linux 桌面大多使用 systemd-networkd 配合 iwd 进行网络管理,形成完整的网络解决方案。

虽然目前仍有部分系统默认使用 NetworkManager 管理网络,用 wpa_supplicant 管理 WiFi, 但这已经不够「现代」了(逃

网络协议栈

  • 硬件层:网卡驱动和固件
  • 链路层:MAC 地址管理和链路检测
  • 网络层:IP 地址配置和路由管理
  • 传输层:TCP / UDP 连接管理
  • 应用层:DNS 解析和服务发现

主要组件

  • systemd-networkd:网络接口管理,处理 DHCP 和静态配置
  • iwd:无线网络管理,支持 WPA2 / WPA3
  • systemd-resolved:DNS 解析和缓存

有线网络

  1. 内核加载网卡驱动
  2. 检测链路状态(网线连接)
  3. systemd-networkd 通过 DHCP 获取 IP 配置
  4. 配置路由和 DNS

无线网络

  1. 加载无线网卡驱动和固件
  2. iwd 扫描可用网络
  3. 选择网络并进行认证(WPA2 / WPA3)
  4. 建立连接后通过 DHCP 获取 IP

网络管理命令

# 查看接口状态
ip link show
ip addr show

# 无线网络管理(iwd)
iwctl station wlan0 scan
iwctl station wlan0 connect "SSID"

# 网络服务状态
systemctl status systemd-networkd iwd

# DNS 解析测试
resolvectl query example.com
resolvectl status

现代网络正在往 IPv6 迁移的过程中,目前仍有许多站点都只支持 IPv6,因此 IPv4+IPv6 双栈成为一个过渡方案,systemd-networkd 提供完整的双栈支持。

双栈特点

  • IPv4:通过 DHCP 获取配置,32 位地址
  • IPv6:通过 Router Advertisement 获取,128 位地址
  • 并行工作:两个协议栈同时运行
  • IPv6 优先:通常有 IPv6 的会优先走 IPv6 网络,没有才走 IPv4.
    • Linux 中通过 glibc 的 getaddrinfo() 来实现该逻辑,可通过 /etc/gai.conf 调整该函数的地址排序算法。因为 APP 通常直接使用第一条记录发起连接,所以 /etc/gai.conf 通常能直接决定系统中是 IPv6 优先还是 IPv4 优先。

双栈验证

# 查看 IPv4 配置
ip -4 addr show
ip -4 route

# 查看 IPv6 配置
ip -6 addr show
ping -6 2001:4860:4860::8888

# DNS 双栈测试
nslookup -type=A google.com
nslookup -type=AAAA google.com

连接问题诊断流程

  1. 硬件层面
# 检查接口存在
ip link show

# 查看驱动加载
dmesg | grep -i firmware
lspci | grep -i network
  1. 链路层面
# 有线:检查链路状态
ethtool eth0

# 无线:扫描网络
iw dev wlan0 scan | grep SSID
  1. 网络配置
# DHCP 状态
journalctl -u systemd-networkd

# IP 配置检查
ip addr show dev eth0

# 路由表
ip route
  1. DNS 解析
# DNS 配置
resolvectl status
cat /etc/resolv.conf

# 解析测试
dig @8.8.8.8 example.com
nslookup example.com

常见问题与解决

  • 无法获取 IP:检查 DHCP 服务、网线连接、无线密码
  • DNS 解析失败:验证 DNS 服务器配置、检查 systemd-resolved 状态
  • IPv6 无连接:确认路由器支持 IPv6、检查 IPv6AcceptRA 配置
  • 连接不稳定:查看信号强度、检查驱动兼容性

nftables 是现代 Linux 的防火墙解决方案,它提供比 iptables 更简洁的语法和更好的性能。

基本概念

  • 表(Table):包含链和规则的容器
  • 链(Chain):规则的有序列表
  • 规则(Rule):匹配条件和动作
  • 集合(Set):用于批量匹配的地址或端口列表

nftables 的四表五链、规则等概念跟 iptables 是完全一致的,这一部分可以参考我之前的文章iptables 及 docker 容器网络分析, 这里不再赘述。

NixOS 配置示例

# configuration.nix
networking.nftables = {
  enable = true;
  ruleset = ''
    # 定义表
    table inet filter {
      # 定义链
      chain input {
        type filter hook input priority 0; policy drop;

        # 允许回环接口
        if lo accept

        # 允许已建立的连接
        ct state established,related accept

        # 允许 SSH
        tcp dport 22 accept

        # 允许 HTTP/HTTPS
        tcp dport {80, 443} accept

        # 允许 DNS
        udp dport 53 accept
        tcp dport 53 accept

        # 允许 DHCP
        udp dport 67 accept
        udp dport 68 accept

        # 允许 ICMP
        icmp type {echo-request, echo-reply, destination-unreachable} accept
        ip6 nexthdr icmpv6 icmpv6 type {echo-request, echo-reply, destination-unreachable} accept
      }

      chain forward {
        type filter hook forward priority 0; policy drop;
      }

      chain output {
        type filter hook output priority 0; policy accept;
      }
    }
  '';
};

常用 nftables 命令

# 查看当前规则
nft list ruleset

# 查看特定表
nft list table inet filter

# 临时添加规则
nft add rule inet filter input tcp dport 8080 accept

# 删除规则
nft delete rule inet filter input handle <handle>

# 清空表
nft flush table inet filter

端口转发配置

networking.nftables.ruleset = ''
  table inet nat {
    chain prerouting {
      type nat hook prerouting priority 0;

      # 端口转发:将外部 8080 端口转发到内网 192.168.1.100:80
      tcp dport 8080 dnat to 192.168.1.100:80
    }

    chain postrouting {
      type nat hook postrouting priority 100;

      # 源地址转换(SNAT)
      oifname "eth0" masquerade
    }
  }
'';

WireGuard 配置

# configuration.nix
networking.wireguard.interfaces = {
  wg0 = {
    ips = [ "10.0.0.2/24" ];
    privateKeyFile = "/etc/wireguard/private.key";
    peers = [
      {
        publicKey = "peer-public-key";
        allowedIPs = [ "0.0.0.0/0" ];
        endpoint = "vpn.example.com:51820";
        persistentKeepalive = 25;
      }
    ];
  };
};

TUN/TAP 接口

# 创建 TUN 接口
ip tuntap add dev tun0 mode tun
ip addr add 10.0.0.1/24 dev tun0
ip link set tun0 up

# 创建 TAP 接口
ip tuntap add dev tap0 mode tap
ip addr add 192.168.100.1/24 dev tap0
ip link set tap0 up

桥接网络

# 创建网桥
ip link add name br0 type bridge
ip link set dev br0 up

# 添加接口到网桥
ip link set dev eth1 master br0
ip link set dev tap0 master br0

# 配置网桥 IP
ip addr add 192.168.1.1/24 dev br0

Docker 网络管理

# 查看网络
docker network ls

# 创建自定义网络
docker network create --driver bridge --subnet=172.20.0.0/16 mynetwork

# 连接容器到网络
docker network connect mynetwork container_name

# 查看网络详情
docker network inspect mynetwork

Podman 网络配置

# 创建网络
podman network create mynet

# 运行容器
podman run --network mynet -d nginx

# 查看网络
podman network ls

内核网络参数

# configuration.nix
boot.kernel.sysctl = {
  # TCP 缓冲区大小
  "net.core.rmem_max" = 134217728;
  "net.core.wmem_max" = 134217728;
  "net.ipv4.tcp_rmem" = "4096 87380 134217728";
  "net.ipv4.tcp_wmem" = "4096 65536 134217728";

  # TCP 拥塞控制
  "net.ipv4.tcp_congestion_control" = "bbr";

  # 连接跟踪
  "net.netfilter.nf_conntrack_max" = 1048576;
  "net.netfilter.nf_conntrack_tcp_timeout_established" = 3600;

  # 网络队列
  "net.core.netdev_max_backlog" = 5000;
  "net.core.netdev_budget" = 600;
};

网络参数调优:

TCP 缓冲区优化:

net.core.rmem_max = 134217728 设置 TCP 接收缓冲区的最大值为 128MB。更大的接收缓冲区可以处理突发的高流量,减少丢包,提高网络吞吐量,特别适合高带宽网络环境,适用于高带宽、高延迟网络,如光纤网络、VPN 连接。

net.core.wmem_max = 134217728 设置 TCP 发送缓冲区的最大值为 128MB。更大的发送缓冲区可以缓存更多待发送数据,提高发送效率,减少发送阻塞,提高网络传输效率,适用于大文件传输、流媒体上传、高并发网络应用。

net.ipv4.tcp_rmem = "4096 87380 134217728" 设置 TCP 接收缓冲区的初始值、默认值和最大值。参数说明:初始值 4KB,默认值 87KB,最大值 128MB。动态调整接收缓冲区大小,根据网络条件自动优化,在低延迟和高吞吐量之间自动平衡。

net.ipv4.tcp_wmem = "4096 65536 134217728" 设置 TCP 发送缓冲区的初始值、默认值和最大值。参数说明:初始值 4KB,默认值 64KB,最大值 128MB。动态调整发送缓冲区大小,适应不同的网络负载,在内存使用和网络性能之间找到最佳平衡点。

TCP 拥塞控制优化:

net.ipv4.tcp_congestion_control = "bbr" 使用 BBR(Bottleneck Bandwidth and RTT)拥塞控制算法。BBR 是 Google 开发的现代拥塞控制算法,基于带宽和延迟测量,在高带宽、高延迟网络环境下性能更好,减少延迟和丢包,适用于现代网络环境,特别是高带宽网络和长距离连接。

连接跟踪优化:

net.netfilter.nf_conntrack_max = 1048576 增加连接跟踪表大小到 100 万条记录。支持更多并发网络连接,避免连接跟踪表溢出,支持高并发网络应用,如 P2P 下载、多用户服务,适用于服务器环境、高并发网络应用。

net.netfilter.nf_conntrack_tcp_timeout_established = 3600 设置已建立连接的超时时间为 1 小时。延长连接跟踪时间,减少连接重建的频率,减少连接重建开销,提高长连接应用的性能,适用于长连接应用,如数据库连接、WebSocket 连接。

网络队列优化:

net.core.netdev_max_backlog = 5000 增加网络设备接收队列大小到 5000 个数据包。更大的接收队列可以处理突发流量,减少丢包,提高网络处理能力,减少因队列满而导致的丢包,适用于高流量网络环境,如服务器、网络设备。

net.core.netdev_budget = 600 增加每次网络处理的数据包数量到 600 个。提高网络处理效率,减少处理开销,提高网络吞吐量,减少 CPU 使用率,适用于高负载网络环境,需要优化网络处理性能。

优化效果评估:通过缓冲区优化,网络吞吐量可提升 20-50%;BBR 拥塞控制算法可显著减少网络延迟;连接跟踪优化支持更多并发连接;队列优化减少丢包,提高网络稳定性。

网络流量监控

# 实时流量监控
iftop -i eth0

# 网络连接监控
netstat -tuln
ss -tuln

# 网络统计
cat /proc/net/dev
cat /proc/net/snmp

# 带宽测试
iperf3 -s  # 服务器端
iperf3 -c server_ip  # 客户端

网络延迟分析

# ping 测试
ping -c 10 8.8.8.8

# 路由跟踪
traceroute 8.8.8.8
mtr 8.8.8.8

# 网络质量测试
qperf server_ip tcp_bw tcp_lat

连接问题排查

# 检查网络接口状态
ip link show
ip addr show

# 检查路由表
ip route show
ip route get 8.8.8.8

# 检查 ARP 表
ip neigh show

# 检查网络统计
cat /proc/net/dev
cat /proc/net/snmp

DNS 问题排查

# 测试 DNS 解析
dig @8.8.8.8 example.com
nslookup example.com

# 检查 DNS 配置
resolvectl status
cat /etc/resolv.conf

# 测试 DNS 性能
dig @8.8.8.8 example.com +stats

防火墙问题排查

# 检查防火墙规则
nft list ruleset
iptables -L -v -n

# 测试端口连通性
telnet server_ip port
nc -zv server_ip port

# 检查连接跟踪
cat /proc/net/nf_conntrack

网卡绑定配置

# configuration.nix
networking.bonds = {
  bond0 = {
    interfaces = [ "eth0" "eth1" ];
    driverOptions = {
      mode = "802.3ad";
      lacp_rate = "fast";
      xmit_hash_policy = "layer3+4";
    };
  };
};

networking.interfaces.bond0.ipv4.addresses = [{
  address = "192.168.1.100";
  prefixLength = 24;
}];

VLAN 网络配置

# configuration.nix
networking.vlans = {
  vlan100 = { id = 100; interface = "eth0"; };
  vlan200 = { id = 200; interface = "eth0"; };
};

networking.interfaces.vlan100.ipv4.addresses = [{
  address = "192.168.100.1";
  prefixLength = 24;
}];

networking.interfaces.vlan200.ipv4.addresses = [{
  address = "192.168.200.1";
  prefixLength = 24;
}];

创建网络命名空间

# 创建命名空间
ip netns add ns1
ip netns add ns2

# 创建 veth 对
ip link add veth1 type veth peer name veth2

# 将接口移到命名空间
ip link set veth1 netns ns1
ip link set veth2 netns ns2

# 配置命名空间内的网络
ip netns exec ns1 ip addr add 10.0.1.1/24 dev veth1
ip netns exec ns1 ip link set veth1 up
ip netns exec ns2 ip addr add 10.0.1.2/24 dev veth2
ip netns exec ns2 ip link set veth2 up

# 测试连通性
ip netns exec ns1 ping 10.0.1.2

网络是计算机科学中最复杂的技术之一,数据在互联网中的流动造就了现代信息社会,现代 AI 的发展也与现代网络中产生的超大规模数据密不可分。

本文只是对 Linux 网络的一个简单介绍,下一篇文章我们会聊聊系统关机和故障排查,看看系统是如何优雅地关机的,以及遇到问题时该如何处理。

# 网络接口管理
ip link show                           # 查看网络接口
ip addr show                          # 查看 IP 地址
ip route show                         # 查看路由表
ip neigh show                         # 查看 ARP 表

# 网络连接管理
ss -tuln                              # 查看网络连接
netstat -tuln                         # 传统网络连接查看
lsof -i                               # 查看端口占用

# 网络测试
ping -c 4 8.8.8.8                    # ping 测试
traceroute 8.8.8.8                   # 路由跟踪
mtr 8.8.8.8                          # 网络质量测试
# nftables 管理
nft list ruleset                      # 查看所有规则
nft list table inet filter            # 查看特定表
nft add rule inet filter input tcp dport 8080 accept  # 添加规则
nft delete rule inet filter input handle <handle>     # 删除规则

# iptables 管理(传统)
iptables -L -v -n                     # 查看规则
iptables -A INPUT -p tcp --dport 22 -j ACCEPT  # 添加规则
iptables -D INPUT -p tcp --dport 22 -j ACCEPT  # 删除规则
# DNS 解析测试
dig @8.8.8.8 example.com              # DNS 查询
nslookup example.com                  # 传统 DNS 查询
resolvectl query example.com          # systemd-resolved 查询

# 网络监控
iftop -i eth0                         # 实时流量监控
tcpdump -i eth0                       # 网络包捕获
wireshark                             # 图形化网络分析

# 带宽测试
iperf3 -s                             # 启动 iperf3 服务器
iperf3 -c server_ip                   # 客户端测试
# 网络配置
/etc/systemd/network/                 # systemd-networkd 配置
/etc/nftables.conf                    # nftables 配置
/etc/resolv.conf                      # DNS 配置

# 网络服务
/etc/systemd/system/                  # systemd 服务配置
/etc/wireguard/                       # WireGuard 配置
/etc/openvpn/                         # OpenVPN 配置

# 网络状态
/proc/net/dev                         # 网络接口统计
/proc/net/snmp                        # 网络协议统计
/proc/net/nf_conntrack                # 连接跟踪表

Linux 桌面系统故障排查指南(四) - 多媒体处理与中文支持

2025-10-19 10:20:33

AI 创作声明:本系列文章由笔者借助 ChatGPT, Kimi K2, 豆包和 Cursor 等 AI 工具创作,有很大篇幅的内容完全由 AI 在我的指导下生成。如有错误,还请指正。

Linux 桌面系统的多媒体处理和中文支持涉及多个子系统。音频延迟、字体渲染质量、输入法响应速度等问题看似简单,背后却涉及 PipeWire、fontconfig、fcitx5 等多个组件的协同工作。

本文将深入探讨 Linux 桌面系统的多媒体处理能力,了解 PipeWire 如何统一管理音频和视频,fontconfig 如何优化字体显示,以及 fcitx5 如何提供流畅的中文输入体验。


现代 Linux 桌面(Wayland)由 PipeWire 统一处理音频和视频,取代了传统的 PulseAudio 和 JACK。PipeWire 提供了更低的延迟、更好的硬件兼容性,以及统一的媒体处理框架。

https://docs.pipewire.org/page_overview.html

PipeWire 作为媒体服务器的核心,连接应用程序和硬件设备,提供音频混合、视频处理和路由功能。它从一开始就定位为"通用多媒体处理框架",而非仅局限于音频,这种设计源于现代多媒体场景(如视频会议、屏幕共享、直播、跨应用媒体协作等)对"音频+视频"统一处理的强需求。Pipewire 支持所有接入 PulseAudio,JACK,ALSA 和 GStreamer 的程序。

核心组件

  • pipewire:核心守护进程,管理媒体流图
  • wireplumber:会话管理器,处理设备连接和路由策略
  • pipewire-pulse:PulseAudio 兼容层
  • pipewire-jack:JACK 专业音频兼容层
  • pipewire-alsa:ALSA 兼容层

技术特点

  • 统一架构:同时处理音频、视频、MIDI
  • 低延迟:相比 PulseAudio 显著降低音频延迟
  • 硬件兼容:支持专业音频设备和消费级硬件
  • 安全隔离:通过权限控制保护媒体数据

NixOS 配置

services.pipewire = {
  enable = true;
  alsa.enable = true;      # ALSA 兼容
  pulse.enable = true;     # PulseAudio 兼容
  jack.enable = true;      # JACK 兼容
};

services.pipewire.wireplumber.enable = true;

# 禁用 PulseAudio 避免冲突
hardware.pulseaudio.enable = false;

配置文件路径

  • /etc/pipewire/pipewire.conf:主配置文件
  • /etc/pipewire/pipewire-pulse.conf:PulseAudio 兼容配置
  • /etc/wireplumber/:WirePlumber 会话管理器配置

应用播放音频的典型流程

  1. API 连接:应用通过 ALSA / PulseAudio / JACK API 连接到 PipeWire
  2. 流创建:在 PipeWire 图中创建音频流节点
  3. 路由决策:WirePlumber 根据策略路由到输出设备
  4. 音频处理:混合多个应用流,执行格式转换、音量调节、调整音频效果
  5. 硬件输出:通过 ALSA 驱动将 PCM 数据发送给声卡 DAC,最终输出模拟音频输出

音频节点管理

# 查看音频设备
pw-cli list-objects | grep -E "(Audio|Sink|Source)"

# 实时监控音频流
pw-top

# 图形界面管理
pavucontrol

# 查看 ALSA 设备
aplay -l
arecord -l

音频路由控制

# 设置默认输出设备
pactl set-default-sink alsa_output.pci-0000_00_1f.3.analog-stereo

# 应用音量控制
pactl list sink-inputs
pactl set-sink-input-volume 123 50%

# 创建自定义连接
pw-cli create-link <source-node> <sink-node>

传统 Linux 系统中,音频和视频处理长期处于"各自为战"的状态:

  • 音频:由 PulseAudio(桌面)、JACK(专业)等系统负责
  • 视频:依赖 V4L2(摄像头捕获)、X11/Wayland(屏幕截图)、GStreamer(流处理)、FFmpeg(编解码)等分散组件

这种碎片化导致了诸多问题:

  • 跨应用同步困难:直播时麦克风声音与摄像头画面延迟不一致
  • 权限管理混乱:沙盒应用如 Flatpak 访问摄像头/屏幕需单独适配
  • 现代场景支持不足:Wayland 下的屏幕共享、HDR 视频渲染缺乏统一支持
  • 硬件加速复杂:GPU 编解码需各组件单独对接,兼容性差

PipeWire 的设计初衷就是打破这种割裂:通过一套统一的框架同时管理音频和视频流,让"音频+ 视频"的协作(如会议软件同时捕获麦克风和摄像头、直播工具混合游戏画面与解说声音)变得简单高效。因此,视频处理是其"统一多媒体管道"目标的自然延伸。

PipeWire 作为现代 Linux 桌面系统的多媒体框架,相比传统方案具有以下核心优势:

统一的"管道"模型

  • 音频流和视频流都被抽象为"节点"
  • 通过统一的"节点-端口-连接"模型实现跨应用的音视频混合
  • 框架内置时间戳同步机制,确保音视频流始终保持时序一致(延迟误差可控制在毫秒级)

原生适配现代桌面协议

  • 作为 Wayland 官方推荐的多媒体中间层
  • 通过与 xdg-desktop-portal 框架协同工作,实现标准化的"授权式"屏幕共享
  • 支持 HDR 视频和高分辨率流传输,性能损耗远低于传统 X11 截图
  • 遵循 Wayland 安全隔离原则,所有跨应用资源访问都通过用户授权的门户接口

简化沙盒应用权限

  • 通过 Polkit 权限系统集中管理设备访问
  • 沙盒应用无需直接操作硬件设备,只需通过 PipeWire API 请求流数据
  • 支持动态权限调整

高效硬件加速整合

  • 内置统一的硬件加速抽象层
  • 通过 GStreamer 或 FFmpeg 后端自动适配底层硬件加速接口
  • 支持"零拷贝"传输,CPU 占用率可降低 50% 以上

灵活的动态路由

  • 允许实时调整视频流路径
  • 用户可通过图形工具拖拽节点实现流的动态切换
  • 支持自动故障恢复和流的动态转换

在 Wayland 环境中,屏幕共享功能是通过 xdg-desktop-portal 和 PipeWire 协同工作实现的。这与 X11 有很大的不同,后者通过其自身的扩展(如 X11R6 的 XFIXES 扩展)直接访问屏幕内容。

工作原理

在 Wayland 下,每个应用程序只能访问自己的窗口、键盘鼠标事件等,无法随意截屏或访问全局资源。屏幕共享的完整流程是:

  1. 应用发起请求:视频会议软件调用 org.freedesktop.portal.ScreenCast 接口,请求屏幕共享
  2. 用户授权:xdg-desktop-portal 显示原生对话框,请求用户确认共享范围(整个屏幕/特定窗口/区域)
  3. 合成器提供数据:获得授权后,xdg-desktop-portal 通知合成器,合成器将相应的屏幕内容通过 PipeWire 流返回给 xdg-desktop-portal.
  4. PipeWire 流传输:xdg-desktop-portal 将流信息返回给应用,应用程序通过 PipeWire 接收屏幕数据进行处理和传输

可以看到应用程序只需要先与 xdg-desktop-portal 交互获得 PipeWire 流信息,然后直接访问 PipeWire, 全程都不直接与合成器交互。

协议优势

  • 安全性:基于 xdg-desktop-portal 的授权机制,需要用户明确同意
  • 隐私保护:用户可以精确控制共享范围,只共享特定窗口而非整个屏幕
  • 性能:直接访问合成器缓冲区,避免额外的内存拷贝
  • 兼容性:支持多显示器、不同分辨率和刷新率
  • 标准化:所有应用都使用相同的 portal 接口,确保跨桌面环境的一致体验

门户实现要求

要使用 Wayland 屏幕共享,系统需要安装 DE/WM 所支持的 xdg-desktop-portal 实现。

主流应用支持:目前主流的 OBS、Discord、Zoom、Chrome/Chromium 等应用都已经支持基于 xdg-desktop-portal 的 Wayland 屏幕共享机制。

摄像头设备管理

# 查看 PipeWire 视频设备
pw-cli list-objects | grep -i video

# 查看 V4L2 设备
v4l2-ctl --list-devices

# 摄像头格式查询
v4l2-ctl --device=/dev/video0 --list-formats

# 摄像头权限检查
ls -l /dev/video*
groups $USER  # 确认在 video 组

# 测试摄像头
ffplay /dev/video0

屏幕共享环境配置

# Wayland 环境检查
echo $WAYLAND_DISPLAY
echo $XDG_SESSION_TYPE

# 设置桌面环境标识(重要!)
export XDG_CURRENT_DESKTOP=sway  # 或 gnome, kde, xfce 等

# 检查 PipeWire 服务状态
systemctl --user status pipewire-session-manager
systemctl --user status pipewire

# 检查桌面门户服务
systemctl --user status xdg-desktop-portal
systemctl --user status xdg-desktop-portal-wlr  # Sway/Hyprland
# 或
systemctl --user status xdg-desktop-portal-gnome  # GNOME

PipeWire 视频配置

NixOS 中可通过 services.pipewire.extraConfig.pipewire."10-video"."context.properties" 来声明这部分配置。

# 编辑 PipeWire 主配置
vim ~/.config/pipewire/pipewire.conf

# 视频相关配置示例
context.properties = {
    # 视频缓冲区配置
    default.video.rate = 30
    default.video.size = "1920x1080"

    # 硬件加速配置
    gstreamer.plugins = [
        "vaapi"      # Intel/AMD GPU 硬件加速
        "nvenc"      # NVIDIA GPU 硬件加速
    ]
}

硬件加速配置

# 检查硬件加速支持
vainfo  # VA-API 支持检查
nvidia-smi  # NVIDIA GPU 状态

# 环境变量设置
export LIBVA_DRIVER_NAME=i965  # Intel GPU
export LIBVA_DRIVER_NAME=radeonsi  # AMD GPU
export LIBVA_DRIVER_NAME=nvidia  # NVIDIA GPU

# GStreamer 硬件加速测试
gst-launch-1.0 videotestsrc ! vaapih264enc ! mp4mux ! filesink location=test.mp4

视频编码优化

# FFmpeg 硬件加速编码
ffmpeg -f v4l2 -i /dev/video0 -c:v h264_vaapi -b:v 2M output.mp4

# OBS 硬件编码配置
# 设置 -> 输出 -> 编码器选择 "FFmpeg VAAPI" 或 "NVENC"

内存和 CPU 优化

# 调整视频缓冲区大小
vim ~/.config/pipewire/pipewire.conf

context.properties = {
    # 减少视频缓冲区延迟
    default.video.quantum = 1/30  # 30fps
    default.video.min-quantum = 1/30
    default.video.max-quantum = 1/15  # 最大 15fps 延迟
}

屏幕共享问题

  1. xdg-desktop-portal 服务状态:确认门户服务正常运行
  2. 门户实现安装:检查是否安装了适合的 portal 实现
  3. 环境变量设置:正确设置 XDG_CURRENT_DESKTOP
  4. 权限配置:检查摄像头和屏幕录制权限
  5. 合成器支持:确认合成器支持相应的 portal 接口
  6. 应用兼容性:部分应用需要特定版本的 PipeWire 和 portal 支持

音频设备识别问题

  • 检查设备存在
aplay -l
arecord -l
  • 验证 PipeWire 运行
systemctl --user status pipewire wireplumber
journalctl --user -u pipewire -f
  • 权限检查
ls -l /dev/snd/
groups $USER  # 确认在 audio 组

音频延迟优化

# 编辑用户配置
vim ~/.config/pipewire/pipewire.conf

# 低延迟配置示例
context.properties = {
    default.clock.rate = 48000
    default.clock.quantum = 32
    default.clock.min-quantum = 32
    default.clock.max-quantum = 32
}

PipeWire 低延迟配置:

default.clock.rate = 48000 设置音频采样率为 48kHz,平衡音质和性能。48kHz 是专业音频的标准采样率,提供良好的音质同时保持合理的计算开销。相比 44.1kHz 提供更好的音质,相比 96kHz 减少 CPU 和内存使用,适用于大多数音频应用,特别是需要低延迟的实时音频处理。

default.clock.quantum = 32 设置音频缓冲区大小为 32 个样本,约 0.67ms 延迟。较小的缓冲区减少音频延迟,但需要更频繁的音频处理。计算方式:32 样本 ÷ 48000Hz = 0.67ms 延迟,适用于实时音频应用,如音乐制作、游戏、视频会议。

default.clock.min-quantum = 32 设置最小缓冲区大小,防止系统动态调整到更小的值。固定最小缓冲区大小,避免系统在低负载时过度优化导致的不稳定,确保延迟的一致性,避免音频处理的不稳定。

default.clock.max-quantum = 32 设置最大缓冲区大小,防止系统动态调整到更大的值。固定最大缓冲区大小,避免系统在高负载时增加延迟,确保延迟的上限,保持低延迟特性。

延迟优化效果:约 0.67ms 的音频延迟,适合实时应用;适度的 CPU 使用增加,但通常可接受;固定缓冲区大小提供更稳定的音频处理;特别适合音乐制作、游戏、实时通信等对延迟敏感的应用。

注意事项:过小的缓冲区可能导致音频断断续续或 CPU 使用率过高;需要根据具体硬件和应用需求调整参数;某些音频设备可能不支持极小的缓冲区大小。


中文支持是中文用户桌面体验的核心组成部分,包括字体渲染配置和中文输入法设置。本章节将详细介绍如何在 Linux 桌面环境中正确配置中文字体和输入法,解决常见的显示和输入问题。

字体渲染是桌面应用显示质量的关键因素,特别是对于中文用户,CJK(中日韩)字体的正确配置直接影响阅读体验。Linux 桌面通过 fontconfig 系统统一管理字体配置,解决字体匹配、渲染和显示问题。

fontconfig 是 Linux 桌面系统的字体配置框架,负责:

  • 字体发现:扫描系统字体目录,建立字体索引
  • 字体匹配:根据应用请求的字体特征(族名、样式、语言等)选择最合适的字体
  • 字体渲染:配置字体渲染参数(抗锯齿、子像素渲染、提示等)
  • 字体替换:当请求的字体不存在时,提供合适的替代字体

核心组件

  • fc-cache:字体缓存生成工具
  • fc-list:字体列表查询工具
  • fc-match:字体匹配测试工具
  • 配置文件:XML 格式的字体配置规则

配置文件层次

# 系统级配置(优先级从高到低)
/etc/fonts/fonts.conf                    # 主配置文件
/etc/fonts/conf.d/                       # 配置片段目录

# 用户级配置
~/.config/fontconfig/fonts.conf          # 用户主配置
~/.config/fontconfig/conf.d/             # 用户配置片段

常见 CJK 字体族

字体族 特点 适用场景
Source Han Sans Adobe 开源,专业设计 现代应用,网页显示
Source Han Serif Adobe 开源,衬线字体 设计软件,印刷
Source Han Mono 思源等宽字体 编程,代码显示
Noto Sans CJK Google 开源,与 Source Han 为同一字体 系统界面,兼容性
WenQuanYi 文泉驿,轻量级 系统界面,终端

说明:Source Han 系列和 Noto CJK 系列实际上是同一套字体,只是分别由 Adobe 和 Google 以自己的品牌名发布。

以及一些新兴的开源字体:

字体族 特点 适用场景
LXGW WenKai Screen 霞鹜文楷屏幕版 屏幕阅读,文档
Maple Mono NF CN 中英文等宽字体 编程,终端

NixOS 字体配置示例

# configuration.nix
fonts = {
  # 禁用默认字体包,使用自定义配置
  enableDefaultPackages = false;
  fontDir.enable = true;

  # 安装常用 CJK 字体和图标字体
  packages = with pkgs; [
    # 图标字体
    material-design-icons
    font-awesome
    nerd-fonts.symbols-only
    nerd-fonts.jetbrains-mono

    # Noto 是 Google 开发的开源字体家族
    # 名字的含义是「没有豆腐」(no tofu),因为缺字时显示的方框或者方框被叫作 tofu
    #
    # Noto 系列字族只支持西文,命名规则是 Noto + Sans 或 Serif + 文字名称。
    noto-fonts # 大部分文字的常见样式,不包含汉字
    noto-fonts-color-emoji # 彩色的表情符号字体
    # Noto CJK 为「思源」系列汉字字体,由 Adobe + Google 共同开发
    # Google 以 Noto Sans/Serif CJK SC/TC/HK/JP/KR 的名称发布该系列字体。
    # 这俩跟 noto-fonts-cjk-sans/serif 实际为同一字体,只是分别由 Adobe/Google 以自己的品牌名发布
    # noto-fonts-cjk-sans # 思源黑体
    # noto-fonts-cjk-serif # 思源宋体

    # Adobe 以 Source Han Sans/Serif 的名称发布此系列字体
    source-sans # 无衬线字体,不含汉字。字族名叫 Source Sans 3,以及带字重的变体(VF)
    source-serif # 衬线字体,不含汉字。字族名叫 Source Serif 4,以及带字重的变体
    # Source Hans 系列汉字字体由 Adobe + Google 共同开发
    source-han-sans # 思源黑体
    source-han-serif # 思源宋体
    source-han-mono # 思源等宽
  ];

  # 字体渲染配置
  fontconfig = {
    enable = true;
    antialias = true;        # 启用抗锯齿
    hinting.enable = false;  # 高分辨率下禁用字体微调
    subpixel.rgba = "rgb";   # IPS 屏幕使用 RGB 子像素排列

    # 默认字体族配置
    defaultFonts = {
      serif = [
        "Source Serif 4"        # 西文衬线字体
        "Source Han Serif SC"   # 中文宋体
        "Source Han Serif TC"   # 繁体宋体
      ];
      sansSerif = [
        "Source Sans 3"         # 西文无衬线字体
        "Source Han Sans SC"    # 中文黑体
        "Source Han Sans TC"    # 繁体黑体
      ];
      monospace = [
        "Maple Mono NF CN"      # 中英文等宽字体
        "Source Han Mono SC"    # 中文等宽
        "JetBrainsMono Nerd Font"  # 西文等宽
      ];
      emoji = [ "Noto Color Emoji" ];
    };
  };
};

字体渲染配置参数:

antialias = true 启用字体抗锯齿,让字体边缘更平滑,提升显示质量。通过灰度插值技术平滑字体边缘,减少锯齿效果,显著提升文字显示质量,特别是在高分辨率屏幕上,适用于所有现代显示设备,特别是高分辨率屏幕。

hinting.enable = false 在高分辨率屏幕(如 4K)上禁用字体微调,避免过度渲染。字体微调 (hinting)是为低分辨率屏幕设计的优化技术,在高分辨率下可能造成过度渲染,在高分辨率屏幕上提供更自然的字体显示效果,适用于高分辨率屏幕(通常 200+ DPI),如 4K 显示器、高分辨率笔记本屏幕。

subpixel.rgba = "rgb" 针对 IPS 屏幕的 RGB 子像素排列优化,提升字体清晰度。利用 LCD 屏幕的 RGB 子像素结构,通过子像素渲染技术提升字体清晰度,在 LCD 屏幕上显著提升字体清晰度,减少模糊感,适用于 IPS、TN、VA 等 LCD 屏幕,不适用于 OLED 屏幕。

字体渲染优化效果:抗锯齿和子像素渲染显著提升文字显示质量;在高分辨率屏幕上禁用微调提供更自然的显示效果;合理的字体回退机制确保各种文字的正确显示;优化的渲染配置在提升质量的同时保持良好性能。

重要说明:Source Han 系列(Adobe 发布)和 Noto CJK 系列(Google 发布)实际上是同一套字体,只是分别由 Adobe 和 Google 以自己的品牌名发布。在 NixOS 中,source-han-sansnoto-fonts-cjk-sans 指向的是同一套字体文件。

原因:系统缺少中文字体或字体匹配规则不正确

排查步骤

# 1. 检查已安装的 CJK 字体
fc-list :lang=zh-cn

# 2. 测试字体匹配
fc-match "sans-serif:lang=zh-cn"
fc-match "serif:lang=zh-cn"

# 3. 查看字体详细信息
fc-list | grep -i "noto\|source\|wqy"

使用上面提供的示例配置通常可解决问题。

原因:CJK 字体通常包含中文、日文、韩文字符,当系统缺少专门的中文字体时,会使用包含日文字符的 CJK 字体,导致中文字符显示为日语字形。

排查步骤

# 检查当前使用的字体
fc-match "sans-serif:lang=zh-cn"
fc-match "serif:lang=zh-cn"

# 查看字体包含的语言支持
fc-list :lang=zh-cn
fc-list :lang=ja

解决方法

# configuration.nix
fonts.fontconfig = {
  enable = true;
  defaultFonts = {
    sansSerif = [
      "Source Han Sans SC"    # 简体中文优先
      "Source Han Sans TC"    # 繁体中文备选
      "Source Sans 3"         # 西文备选
    ];
    serif = [
      "Source Han Serif SC"   # 简体中文优先
      "Source Han Serif TC"   # 繁体中文备选
      "Source Serif 4"        # 西文备选
    ];
  };
};

字体信息查询

# 列出所有字体
fc-list

# 按语言过滤字体
fc-list :lang=zh-cn
fc-list :lang=en

# 查看字体详细信息
fc-list -v "Source Han Sans SC"
fc-list -v "LXGW WenKai Screen"

# 测试字体匹配
fc-match -v "sans-serif:lang=zh-cn"
fc-match -v "serif:lang=zh-cn"
fc-match -v "monospace:lang=zh-cn"

字体渲染测试

# 临时安装字体测试工具
nix shell nixpkgs#pango

# 创建测试文本文件
echo "中文测试 Chinese Test 123" > test.txt

# 使用不同字体渲染测试
pango-view --font="Source Han Sans SC 12" test.txt
pango-view --font="LXGW WenKai Screen 12" test.txt
pango-view --font="Maple Mono NF CN 12" test.txt

现代 Linux 桌面主要使用 fcitx5 作为中文输入解决方案,它通过插件系统支持多种输入引擎,并与图形环境深度集成。

核心组件

  • fcitx5-daemon:主守护进程,管理输入法状态
  • 输入引擎:拼音、五笔、仓颉等具体输入法实现
  • 图形前端:负责候选词界面显示
  • 配置工具:fcitx5-configtool 提供图形化配置

配置文件路径

  • ~/.config/fcitx5/config:主配置文件
  • ~/.config/fcitx5/profile:输入法引擎配置
  • ~/.config/fcitx5/conf/:各输入法引擎的详细配置

Wayland text-input 协议流程

  1. 按键捕获:键盘事件首先到达 Wayland 合成器
  2. 协议通信:合成器通过 text-input 协议与客户端应用通信
  3. 输入法服务:fcitx5 作为 Wayland 输入法服务接收事件
  4. 候选生成:fcitx5 处理按键并生成候选词
  5. 候选显示:通过 Wayland 协议在光标位置显示候选窗口
  6. 文本提交:用户选择后通过 text-input 协议提交最终文本

text-input 协议有 v1 跟 v3 两个版本,目前(2025-09)Electron/Chrome 以及其他大部分程序框架都已经支持了 text-input-v3. 桌面环境方面所有主流 Compositor 也都支持 text-input-v3. 所以目前 wayland 下输入法的可用性已经很高了。

XWayland 使用场景

  • 尚未支持 Wayland 的旧版应用
  • 需要特定 X11 功能的专业软件
  • 通过应用启动脚本单独设置环境变量

XWayland 应用输入流程

  1. 按键捕获:键盘事件首先进入 Wayland 合成器(Hyprland、KWin 等)。
  2. 事件转发给 XWayland(例如xwayland-satellite
    • 如果目标是 X11 应用窗口,合成器会将事件交给 XWayland
    • XWayland 将 Wayland 输入事件转换为 X11 协议事件(如 KeyPress/KeyRelease),并交付给目标应用。
  3. 应用侧的输入法模块拦截事件
    • X11 应用(GTK/Qt 程序)内部加载了 fcitx5-gtk / fcitx5-qt 插件(通常根据环境变量加载,后面会介绍这些环境变量)。
    • 这些插件拦截来自 XWayland 的键盘事件,并通过 D-Bus 将事件上报给 fcitx5
    • 此时应用相当于是「把键盘输入交给 fcitx5 代管」。
  4. fcitx5 处理输入逻辑
    • fcitx5 收到键盘序列后,进入输入法逻辑:拼音解析、候选词生成。
    • fcitx5 控制候选窗口的显示位置(通常跟随输入光标),候选窗口本身可能是 X11 窗口(由 fcitx5 自己创建,并通过 XWayland 显示)。
  5. 输入结果返回应用
    • 当用户选定候选词后,fcitx5 通过 D-Bus 调用 IM 插件接口直接把确认后的字符串传给应用。
    • 应用的 IM 插件收到字符串后,调用应用内的「输入上下文 API」插入文本。
    • 在应用看来,它就像直接得到了「输入了一串中文」的事件。

XWayland 环境变量设置

# GTK 应用使用 fcitx(通过 GTK IM 模块)
export GTK_IM_MODULE=fcitx

# Qt 应用使用 fcitx(通过 Qt IM 模块)
export QT_IM_MODULE=fcitx

# X11 应用使用 fcitx(通过 XIM 协议)
export XMODIFIERS=@im=fcitx

输入法机制说明

GTK IM 模块、Qt IM 模块以及 XIM 协议,都是 X11 下的东西,在 wayland 下只需要 text-input 协议即可,不需要这些幺蛾子。

推荐配置策略

  1. 默认 Wayland 优先

    • 让现代应用使用原生 Wayland text-input 协议
  2. 按需 XWayland

    • 使用 GDK_BACKEND=x11 强制特定应用使用 XWayland
    • 为特定应用创建启动脚本设置 IM_MODULE 相关环境变量
  3. 应用启动脚本示例

#!/bin/bash
# 强制特定应用使用 XWayland
export GTK_IM_MODULE=fcitx  # 使用 GTK IM 模块
export QT_IM_MODULE=fcitx   # 使用 Qt IM 模块
export GDK_BACKEND=x11      # 强制使用 X11 后端
your-application

输入法无响应问题

  1. 进程状态检查

    ps aux | grep fcitx5
    systemctl --user status fcitx5
  2. 环境变量验证(仅 xwayland 场景):

    echo $GTK_IM_MODULE $QT_IM_MODULE $XMODIFIERS
    echo $XDG_RUNTIME_DIR $DBUS_SESSION_BUS_ADDRESS
  3. D-Bus 通信检查

    busctl --user tree org.fcitx.Fcitx5
    dbus-monitor --session "interface='org.fcitx.Fcitx5'"
  4. 诊断工具使用

    fcitx5-diagnose
    fcitx5-configtool

候选框显示问题

  1. Wayland 原生应用排查

    # 检查 Wayland 环境
    echo $WAYLAND_DISPLAY $XDG_RUNTIME_DIR
    
    # 检查 text-input 协议支持
    wayland-info | grep text-input
    
    # 查看合成器日志中 text-input 相关错误
    journalctl --user -u fcitx5
  2. XWayland 应用排查

    # 检查 XWayland 环境变量
    echo $GTK_IM_MODULE $QT_IM_MODULE $XMODIFIERS
    
    # 检查 XWayland 连接
    echo $DISPLAY
    
    # 验证 XIM 连接
    xdpyinfo | grep -i input
  3. 权限和会话检查

    # 确认 fcitx5 在正确的用户会话中运行
    loginctl show-session $(loginctl | grep $USER | awk '{print $1}')
    
    # 检查 D-Bus 会话
    echo $DBUS_SESSION_BUS_ADDRESS
  4. 应用兼容性

    • Wayland 应用:部分应用需要重新启动才能识别输入法
    • XWayland 应用:需要正确设置 XMODIFIERS 环境变量
    • 混合环境:某些应用可能在不同环境下表现不同

性能优化

# 调整 fcitx5 配置
vim ~/.config/fcitx5/profile

# 禁用不需要的输入引擎
# 减少候选词数量提高响应速度

# 云拼音配置
vim ~/.config/fcitx5/conf/cloudpinyin.conf

特殊场景处理

  1. 多显示器环境

    • Wayland:候选框通常能正确跟随光标位置
    • XWayland:候选框可能在错误屏幕显示,需要调整 X11 配置
  2. 高分屏适配

    • Wayland:自动适配系统缩放比例
    • XWayland:可能需要手动设置 GDK_SCALEQT_SCALE_FACTOR
  3. 游戏和全屏应用

    • Wayland:部分游戏可能需要 gamescope 等工具
    • XWayland:传统全屏游戏通常工作正常
  4. 终端应用

    • Wayland 终端:需要终端模拟器支持 text-input 协议
    • XWayland 终端:使用 X11 的 XIM 协议或 GTK/Qt IM 模块

本文详细介绍了 Linux 桌面系统的多媒体处理能力,重点阐述了 PipeWire 如何统一管理音频和视频,以及 fontconfig 和 fcitx5 如何提供完善的中文支持。

PipeWire 支持视频流处理,本质是为了解决 Linux 多媒体生态中长期存在的"音频-视频割裂"“传统协议适配困难"“沙盒权限复杂"等问题。相比传统方法,它通过统一管道模型、原生适配现代桌面、简化权限管理、整合硬件加速、动态路由等特性,让视频流的捕获、传输、处理和协作变得更高效、更安全、更易用。

如今,PipeWire 已成为 Linux 桌面视频处理的事实标准(如 GNOME 45+、KDE Plasma 6 均默认依赖),未来还将进一步整合 AI 处理(如实时美颜、降噪)等新功能,成为连接硬件、应用与用户的"多媒体中枢”。

中文支持方面,虽然配置稍微复杂一些,但一旦搞定就基本不用再操心了。fontconfig 的字体匹配机制和 fcitx5 的输入法框架为中文用户提供了完整的桌面体验。

下一篇文章我们会聊聊网络架构,看看系统是如何处理网络连接和管理的。