2026-09-21 11:49:03
#吐槽 不是,现在视频网站的吃相都这么难看了吗?迪士尼宣布 Disney+ 从英国开始,未来无论你是否有会员,开的是什么等级会员,视频的开头结尾将统统一视同仁的插入“广告”,当然迪士尼自己的说法是订阅会员依然享有“无广告”体验,视频播放前后强迫用户看的那个插片,只是“推广信息”,是“猜你喜欢、热门内容”之类的内容,并非广告内容。不是大哥,你本来就一直在涨价,还玩这一出,搞毛啊……目前我用的合租新加坡账号还没被插广告,看红R上的讨论,应该是从英国开始逐步推广至全球,目前只是插一些迪士尼自己的预告片啥的,如果不同意新的用户协议(接受这个推广内容)就无法观看,并且用户协议里强调,如果使用反广告措施屏蔽广告的话,被检测到就会停止播放视频,就像YouTube那样,加入打击用户使用广告拦截插件的队伍。(PS:最后的好消息:根据英国网友的实测儿童模式下,依然是真 · 没有广告的,这个应该和欧盟法规有关,但不知道未来新加坡订阅也能这样不,反正我主要是给家里小朋友订阅的,只要儿童模式依然能没广告就行,不然就只能回归BT/PT模式,我辛苦点给他下资源看了)
2026-09-20 00:19:50
一切的开始非常平平无奇。
前天晚上Linux.do论坛抽风,登录状态访问就白屏,这也算是 Discourse 架构论坛的常态了,我就直接把整个浏览器的全部缓存和 Cookie 清空来解决问题。访问白屏的问题解决了,但这么搞的代价懂得都懂:我所有网站的登录状态全掉了。
昨天早上起来,因为要回复文章下的几条新评论,我便重新登录了 WordPress 后台。敲完回复点击提交,起身去倒杯水的功夫,口袋里的手机突然一震——监控服务发来告警:
「主机 CPU 占用超过 80% 且持续超过 5 分钟」
我的第一反应:又特么是哪位闲得蛋疼的在拿小脚本刷我的站了?我这种前后端动静分离的架构还能让后端机 CPU 打满的攻击可不一般。
赶紧坐到电脑前登录服务器排查核心指标,先敲个 top 看看占用,按 P 排序一看,前排俩 PHP:
php 65%
php-fpm 10%
诶,这php-fpm占用不太对劲,因为这套前后端动静分离的架构,平时能让后端 PHP 介入处理的基本也就只剩:1、访客评论;2、访客搜索。
先看下php-fpm的情况,结果诡异的是php-fpm 状态页一片岁月静好:
请求数(accepted conn) 7
活跃进程数量(active processes) 1
空闲进程数量(idle processes) 10
慢请求数量(slow requests) 0
到达进程上限次数(max children reached)0
PHP-FPM 负载低得可怜,根本没有什么从前端机发来的 PHP 动态请求,那个唯一活跃的 1,估计还是我自己没关闭的管理后台页,但现实是,现在系统的整体 CPU 居高不下。这说明消耗 CPU 的大概率不是前端进来的常规 Web 访问,而是脱离了 FPM 进程管理的对 PHP 的直接调用。
不放心的我还是看了一下 Nginx 访问日志,虽然 Nginx 日志里确实夹杂着不少对 /goto/ 链接的恶意访问,以 1 秒 5~10 次的频率访问着,但这都是预期内的情况。
这个/goto/外链跳转页的恶意利用问题持续很多年了,害得我还重构了一个安全的外链跳转页(具体经过详见之前这篇文章《少写一个 else,我的外链跳转页成了黑产眼中的“香饽饽”?重构一个安全的外链跳转页》)并且我直接在 Nginx 层面做了拦截,但是也不知道是不是因为之前问题持续太久,黑产圈估计有个流行的《1000个外链跳转接口.xlsx》之类的热门数据,我的跳转页一直在上边,导致有脚本小子持之以恒的使用着我的外链跳转页。1 秒 5~10 次的频率虽然不低了,但是对 Nginx 来说,对他们返回 403 根本用不了多少性能。
既然大概率不是 web 侧的问题,那我就去看下 PHP 的错误日志,然后鬼使神差地刷新了一下博客后台网页,浏览器给我报了一个 500 错误,PHP 日志里也瞬间开始被同一条致命报错刷屏:
PHP Fatal error: Allowed memory size of 536870912 bytes exhausted (tried to allocate 67108864 bytes) in .../plugins/wordfence/vendor/wordfence/wf-waf/src/lib/waf.php on line 336
单次请求直接撑爆了整整 512MB 内存限制,并且路径指向 Wordfence 的 WAF 核心文件。
好了,现在问题的因果链看起来无比严密且闭环:
浏览器掉登录 -> 我重新登录后台的行为唤醒了 WP 的某个后台维护任务与预加载进程 -> 部分穿过前端 Nginx 防御规则的异常访问触发 Wordfence 防火墙的高频比对 -> Wordfence 解析大量规则与日志导致内存溢出、CPU 飙升。
我当即进入终端清空了 wflogs/ 缓存并暂时移除了 Wordfence 插件,博客后台果然秒速恢复访问,随后 CPU 也回落了。我当时甚至在心里暗骂:艹,Wordfence 又给我惹麻烦(至于为什么是“又”,请见2026-09-10的碎碎谈:《绝了,被自己站点的安全插件拦到外边了》)
因为一会儿马上就要出差,我也没功夫细琢磨了,简单把 Wordfence 的扫描调到低占用模式后,我就关电脑收拾收拾出发了。
然而,问题没有这么简单就放过我。
那幽灵般的 CPU 高占用,在 1 小时 15 分钟(75 分钟)后分秒不差地再度浮现。

而且占用报警过于规律,是教科书级的:高占用时 CPU 的总体占用死死卡在 90% 左右,在持续整整 5 分钟后,异常负载消失,CPU占用瞬间回落;接着在沉寂 1 小时 15 分钟后,分秒不差地卷土重来。但问题是当我第二次收到报警提示时,我已经在去隔壁市的车上了,手上就有个手机,这还怎么搞。不过好在因为前后端动静分离,后端机哪怕挂了,也不影响访客访问和爬虫爬取(前端机发现后端机无法访问后会锁死静态缓存不再更新),无非是无法评论,无法搜索罢了。而且高占用的时候,后端机器也并没有完全失去响应,只是稍慢罢了。先凑合着呗,还能咋滴。
直到今天下午我终于有空了,重新打开电脑,做一次正式的 CPU 占用异常排查。
根据昨天和今天上午的观察,高占用时博客访问还是正常的,且每次高占用都极其规律地持续整整 5 分钟,5 min = 300 s,恰好是 PHP 侧 300 秒的超时配置,说明异常进程不是自己退出了,只是因为超时被系统干掉了,既然不是瞬时偶发问题,我就有极其充裕的时间去现场“抓现行”。
等到快到高占用的点儿,我就守着 top,一出现 PHP 线程高占用立刻执行进程占用排序:
ps -eo pid,user,%cpu,%mem,command --sort=-%cpu | grep -i php | head -n 5
终端打印出的第一行结果让我当场愣住:
763014 www-data 92.3 1.0 php /var/www/FreshRSS/app/actualize_script.php
啥情况,吃满 CPU 的不是 WordPress,也不是 Wordfence,而是跑在 Docker 容器里的自建 RSS 阅读器——FreshRSS!(因为 Linux 容器本质上共享宿主机内核,宿主机的 ps 也能将容器内的进程看得一清二楚。)
合着昨天早上我以为的所谓“我登录后台所以触发了 CPU 高占用”,纯粹只是碰巧撞上了它的执行周期?而 Wordfence 内存耗尽让我进不去博客,也只是系统算力被占满、请求积压时引发的次生灾害?这可真有点难猜到——昨天我不是没怀疑过别的程序,但除了 WP 出过异常,其他东西都正常得不能再正常,包括 FreshRSS!
虽然知道是谁出了问题,但是问题的关键还没解决:为什么一个拉取 RSS 的脚本,突然从昨天开始每次执行时都会把 CPU 占用吃满整整 300 秒?
抄起 Linux 诊断神器 strace 直接盯住这个进程排查 CPU 占用:
strace -p 763014 -s 200
终端瞬间开始以抽风一样的速度疯狂滚屏,满屏都是几乎一模一样的系统调用失败,我赶紧按了 ctrl+c 停住刷屏:
newfstatat(AT_FDCWD, "/root/[https://translate.googleapis.com/translate_a/single?client=gtx&sl=auto&tl=zh&dt=t&q=%E3%81%8A%E3%81%AF%E3%81%AE%E3%82%93%EF%BD%9E%E3%81%8A%E3%81%8D%E3%81%9F%EF%BC%9F%E2%99%A1](https://translate.googleapis.com/translate_a/single?client=gtx&sl=auto&tl=zh&dt=t&q=%E3%81%8A%E3%81%AF%E3%81%AE%E3%82%93%EF%BD%9E%E3%81%8A%E3%81%8D%E3%81%9F%EF%BC%9F%E2%99%A1)", 0x7ffd6c94ce30, AT_SYMLINK_NOFOLLOW) = -1 EACCES (Permission denied)
write(2, "Error in translation: Failed to get content from Google Translate API.\n", 71) = 71
write(2, "TranslateTitlesCN: Empty translation result on attempt 1\n", 57) = 57
getcwd("/root", 4096) = 6
屏幕定格的一瞬间,整场事故的逻辑开始变得清晰了:
TranslateTitlesCN 的标题翻译扩展,而对推特的订阅源中恰好抓取到了一条日语标题推送。translate.googleapis.com),但是谷歌估计改了翻译的接口,导致也调用失败了。(自动降级是我自己改的,原版插件没这功能)/root 还权限越界?看着日志里满屏的 /root/https://... 和 EACCES (Permission denied),我一度怀疑自己的眼睛:FreshRSS 明明关在 Docker 容器里,很严谨地用着 www-data,怎么会扯上 /root 目录?凭什么啊,不过甭管凭什么,我都要进容器看到底 FreshRSS 是怎么调用的。
先进入容器内部
docker exec -it freshrss-app /bin/bash
执行 crontab -l,看看具体定时任务是什么:
*/21 * * * * . /var/www/FreshRSS/Docker/env.txt; su www-data -s /bin/sh -c 'php /var/www/FreshRSS/app/actualize_script.php' 2>> /proc/1/fd/2 > /tmp/FreshRSS.log
看起来很贴心,很严谨是吧,先用默认的 root 去加载环境变量文件,以防没有获取环境变量文件的权限,然后再切换到 www-data 用户执行更新脚本,还把日志重定向了,避免使用 root 执行脚本,导致可能的漏洞利用点。
可惜这一行看似很贴心,很严谨的命令,却直接踩中了 Linux 与 PHP 的三个机制暗坑:
su 不带横杠,工作目录被原样继承容器内的 Cron 守护进程是以 root 身份启动的,因此 Cron 触发命令时的初始工作目录默认会是 /root。 随后关键来了——脚本切换权限时使用的是 su www-data,而不是 su - www-data(带横杠的),这俩命令有什么区别:
su - www-data:先完整登录,然后环境重新初始化,并自动 cd 到用户的home目录(通常为 /var/www)。
su www-data:仅切换执行进程的UID/GID,但当前工作目录会被原封不动地保留了下来!
在日常使用终端时,使用 su www-data 是非常好的,因为我们确实需要让当前工作目录以及大部分父环境变量被原封不动地继承下来,这样后续敲sudo XXXXX命令时比较方便。但是对于 FreshRSS 的定时任务,这就导致了一个极度分裂的执行状态:进程表面上用着低权限的 www-data 用户权限,但它的当前工作目录依然停留在 /root,如果每次都写绝对路径,只调用www-data有读写权限的目录,倒是不会出现什么问题,结果又遇到了下一个机制。
翻译插件在网络请求失败后,PHP 内部的 Stream 流处理出现中断,触发了 PHP 底层文件系统的祖传回退机制,PHP 会认为:“这个网络请求既然失败了,那会不会其实它不是一个远程 URL,而是开发者在当前目录下写的一个相对路径文件呢?”于是 PHP 会非常“机智”地把当前的工作目录和要访问的 URL,直接拼接到一起,调用 newfstatat 去相对文件路径找一下(/root/https://translate.googleapis.com/...)是否在硬盘上存在。
问题在于 /root 目录权限是极其严格的 700,归 root 所有。 哪怕仅仅是判断一个文件是否存在,操作系统也要求进程对父级目录具备 x(搜索/遍历)权限。 此时在系统眼里,以 www-data 身份运行的 PHP 进程正在试图访问属于 root 的 700 权限目录,Linux 内核二话不说,直接返回一个 EACCES (Permission denied)。但插件并没有指数退避、错误跳过之类的机制,只会报错后马上继续再重试一次。
这下好了,访问超时 + 路径回退 + 权限越界 + 无回退重试,四重 Buff 叠满,PHP 硬生生把死循环逻辑塞进了 CPU,以每秒上万次的频率抽打 CPU,造就了这场持续 5 分钟的 CPU 暴走。

知道问题的本质后就非常好解决了:
kill -9 763014 强杀进程,在 FreshRSS 扩展管理中将 TranslateTitlesCN 插件禁用(其实早该禁用了,其他非中文源都是用另一个 AI 翻译插件的,当年还没有便宜的 AI 翻译 API,为了省钱,就让这几个更新过于频繁的推特源挂在这个能白嫖免费翻译的插件上)。服务器 CPU 瞬间跌回熟悉的个位数占用。*/21 * * * * cd /var/www/FreshRSS && . ./Docker/env.txt; su www-data -s /bin/sh -c 'php ./app/actualize_script.php' 2>> /proc/1/fd/2 > /tmp/FreshRSS.log
手动触发了一次更新,CPU 纹丝不动,收工。
运维最大的陷阱往往就在这儿:直觉和巧合会编织出一张具有高度欺骗性的网。“刚登录后台就报警”的巧合,差点让我把精力全耗在调试 WordPress 和怨恨安全插件上。
幸好系统的底层调用永远诚实——以后运维还是少看表象猜谜,多用 ps 找准 PID,拿 strace 抓出正在执行的系统调用,那些看似诡异的故障,答案往往就清晰地写在终端显示出的日志里。
本文 服务器 CPU 占用异常排查实录:从误杀 Wordfence 到抓出 FreshRSS 死循环 最初发表于 秋风于渭水。
2026-09-14 11:42:01
一切的开始非常简单:VMware Workstation 曝出了两个虚拟机逃逸与穿透漏洞 CVE-2026-59346 与 CVE-2026-59347。因为使用中涉及在虚拟机里对陌生软件做测试的情况,虚拟机逃逸与穿透这种级别的安全漏洞是注定无法接受的,只得老老实实从 VMware® Workstation 17 Pro 升级到最新的 VMware® Workstation Pro 26H1u1。
然而,在通往新版本的路上,全是坑啊。
PS:如果你是被 VMware Tools 安装失败回滚卡住的,可以直接跳到第七难的VMware Tools 手动安装流程。
众所周知,VMware 被博通收购了,所以整个支持与下载体系全部搬迁进了博通的统一门户,下个安装包必须要登录博通统一账户。
我打开登录页面,密码管理器自动填充了账号密码,点击登录——“用户名或密码错误”。
扯淡吧,密码管理器还能把密码记错的?那就尝试找回密码,博通告诉我:“你压根就没注册过”,切,离谱他妈给离谱开门——离谱到家了,我TM没注册过,那我上次怎么登录下载的安装包,你给我删了就删了呗,瞎说什么。淡定淡定,重新注册一下。
好不容易重新注册进去了,不得不说,博通的网站妥妥一个现代反人类 UI 的集大成者。你必须在支持门户、软件分发、产品授权树状图里一层层翻找,经过数个形似企业级采购合同的确认页面,最终在某个隐蔽的二级子目录里才找到 Workstation Pro 26H1u1 的下载按钮。这破玩意有多隐蔽呢,隐蔽到我写文时想去截个图,我居然就找不到地方了。
再次众所周知,升级安装前必须关闭所有运行中的虚拟机。打开 Workstation 界面,所有机器都显示为“已关闭”,列表里一片祥和。但当我安装时,不出意外地提示仍有虚拟机正在运行。
调出终端,敲下查询命令:
cd "C:\Program Files (x86)\VMware\VMware Workstation"
.\vmrun.exe -T ws list
注意这里是因为我这时候用的是16 pro,新版后路径应该用cd "C:\Program Files\VMware\VMware Workstation"了
控制台返回:Total running VMs: 0。

就瞎扯吧,那台本地用来跑 agent 的 Ubuntu 服务器绝对还活着呢,直接强杀进程容易导致磁盘损坏或残留死锁文件。不过这个倒是好解决,直接通过 SSH 关机就好了:
sudo poweroff
这是 Windows 的服务隔离机制导致的:Workstation 的虚拟机开机自启是通过系统服务
VMware Autostart Service实现的,它是以SYSTEM身份驻留在 Session 0(后台系统会话)层级,而桌面客户端是运行在Session 1(用户会话)层级。导致当前登录用户下的vmrun根本“看”不到启动的虚拟机。这个机制槽点实在是太多,虽然我明白这样设计的原因,这样设计下,重启宿主机后,不需要登录宿主机,虚拟机也会实现自启,但这样设计,也意味着用户如果让他的虚拟机开机自启了,那就无法使用客户端控制他的虚拟机了,必须要手动关机才行。你问要是用户无法手动关机时咋办?那就只能直接杀进程强关了。
安装倒是没啥新状况,顺利安装完成了,但 VMware Workstation 的中文界面没了,一启动就是全英文。倒不是说英文界面看不懂、没法用,只是母语界面更符合直觉,日常扫一眼配置参数时中文界面用起来更舒服一点。
本以为和以前一样改改配置即可,于是开始常规操作:
--locale zh_CN;%APPDATA%\VMware\preferences.ini 和全局 config.ini 中硬编码 pref.locale = "zh_CN"。重启软件,哎,毫无反应,依旧是纯英文。
简单搜了一下找到了一个 26.0.0.1810 版本的 messages\zh_CN 语言文件夹,看起来版本差距不大,直接复制进新版的安装目录试试,再次尝试启动——依旧无效啊。
去检索了一番:合着博通从 17.6 起彻底剥离了外部文本字典加载的多语言机制,官方表示以后“English only”。新版本的多语言不再读取外部 .vmsg 语言文件,而是直接二进制主程序写死。这意味着针对上一个 26.0.0.1810 的汉化资源,面对版本号为 26.0.1.25688693 的新版本,虽然版本号就只差了0.0.1也会完全无效。
既然官方不做人,那只能转向大家的智慧了。去 52pojie(吾爱破解)论坛翻找了一下,果然有大佬针对制作了新版的内存劫持补丁与资源文件。按照说明做了文件替换之后,熟悉的中文界面终于回归了。
宿主机里的安装升级搞定,接下来就要把虚拟机里的 VMware Tools 也升到对应版本,结果撞上了经典的 VMware Tools 安装失败回滚。
挂载虚拟光盘,在 Windows 虚拟机里双击 setup.exe,进度条欢快地读到一半,突然开始“正在回滚操作”,随后弹出一个冷冰冰的错误窗口,逼逼叨叨说了一堆,大概意思就是:
VMware Tools 安装向导提前结束。由于出现了错误,所以未能完成安装。
没有错误代码,没有原因,也没给任何指引,就通知你一句:「没安装上,现在自动结束安装了。」
界面上不写原因,那就只能去日志里自己找。按 Win + R 输入 %TEMP% 回车,找到 vmmsi.log_20260908_111111_Failed.log,直接往上翻,找日志里最后出现的安装失败标识 Return value 3(Return value 3 只是标记这个没装上,真正导致出错的原因得看它上面几行的记录)。
还好日志里倒是写的挺清楚:
Action ended 10:57:15: RemoveExistingProducts. Return value 3.
Property(S): WIX_UPGRADE_DETECTED = {55F0F698-8B00-40BF-8583-A16452EC3FF9}
新版装不上,是因为旧版本的 VMware Tools 卸载不掉。
新安装程序识别到了旧版本,在执行升级前的卸载动作时,旧版的卸载进程跑一半就崩了,因为旧版卸载失败,所以整个新版安装自动回滚。
msiexec /x {55F0F698-8B00-40BF-8583-A16452EC3FF9} /qb 强行卸载:没区别,还是卸载一半就炸了。额,行吧,这种底层 MSI 无法卸载也不是第一次见了,这时候最管用的是微软官方的强制卸载工具:Microsoft Program Install and Uninstall Troubleshooter。
打开微软支持页面准备下载,结果发现:微软大刀部又发力了,微软已经移除了该工具的下载链接,官方建议用户去 Windows 设置里使用新版 windows 疑难解答,但新版疑难解答根本没有强制卸载工具啊!!!
好在我隐约记得家里那台做 NAS 的小主机里有这个工具。立刻开远程桌面连过去,但是问题是,我忘了这个工具我给放什么地方了,而且我记得他实际的名字应该不叫 Microsoft Program Install and Uninstall Troubleshooter.exe,于是只能用 everything 在茫茫多的文件里用关键字 Uninstall 慢慢翻,好再终于找到了,原来叫 MicrosoftProgram_Install_and_Uninstall.meta.diagcab。
然后我犯了一个错误:我刚才用的是宿主机的远程桌面,因为 VMware Tools 还没有被正确安装,所以现在我无法快捷地将宿主机内的卸载工具复制到虚拟机里,于是只能重新用虚拟机里的远程桌面去家里电脑再复制一次。
运行工具,选择“卸载”,手动指定产品识别码 {55F0F698-8B00-40BF-8583-A16452EC3FF9}。工具发挥正常,在磨磨唧唧半个小时后,彻底扬了整个旧版 VMware Tools,重启虚拟机,「设置」->「应用」->「已安装的应用」,列表中不再显示旧版 VMware Tools 看来彻底卸载掉了。以防万一再顺手清理掉 ToolsInstallerCache 安装缓存。
rmdir /s /q "C:\Program Files\Common Files\VMware\ToolsInstallerCache"
清干净旧版,我满心欢喜地再次双击新版安装包,然而在进度条接近末端时——熟悉的“正在回滚操作”再次回归,惊不惊喜,意不意外。
我……(以下省略对博通的几千字友好问候)难道刚才没卸载干净?
再次查看 %TEMP%\vmmsi.log,这次倒是没有了 RemoveExistingProducts,取而代之的是一个新的问题:
CustomAction VM_CopySupportFiles returned actual error code 1603
Action ended 11:40:15: InstallFinalize. Return value 3.
Property(S): SupportFilesDir = C:\Users\admin\AppData\Local\Temp\...
Property(S): VERSIONNTBUILD = 26200
这就是大家常说的 VMware Tools 1603 错误,最最没用的一句报错,因为相当于摊手告诉用户“装失败了,为什么失败我不知道”。
不过结合上边的日志,还是搞懂发生了什么,当前的虚拟机系统是 Windows 11 24H2。我们可爱的微软收紧了安全隔离策略:
SYSTEM 权限服务在后台调用文件操作;AppData\Local\Temp)释放并执行临时的 DLL 文件;我先尝试在系统安全中心中关闭实时保护和篡改防护,可是拦截依然存在;
再尝试在管理员 CMD 中通过 set TEMP=C:\Temp 重定向一个临时路径,避免放在用户的临时目录下,虽然系统这次允许了释放临时的 DLL 文件,但是执行还是被拦截了。
得得得,你系统搞一堆“安全”拦截,那我就索性彻底抛弃 MSI 的自动化安装流程,直接回到最纯粹的系统底层操作:提取驱动和程序本体,用系统命令手动安装驱动和部署程序文件。
挂载虚拟光盘(我这里的盘符是 D:),先尝试解包:
D:\setup.exe /a /p C:\VMToolsExtract
屏幕弹出一个窗口告诉我:setup.exe 支持 /a(管理模式解包),但不认 /p 这个路径参数,这倒是触及我的知识盲区了,于是跑去问了一下机智的 ChatGPT,它教我修改参数传递方式,利用 /v 将传递路径参数:
D:\setup.exe /a /v"TARGETDIR=C:\VMToolsExtract /qn"
注意:这条命令是静默执行的。需要自己去 C:\VMToolsExtract 盯着,文件不再增加就说明解包完了。终于,所有的驱动原文件(.inf / .sys)和 vmtoolsd.exe 整整齐齐地摆在我的眼前了。
接下来就是纯手工的 VMware Tools 手动安装环节:
遍历并强制安装所有解包出来的 .inf 驱动文件:
pnputil /add-driver "C:\VMToolsExtract\*.inf" /subdirs /install
意思是让系统把目录里所有 .inf 驱动全部找出来并强制装进系统驱动库——手动替代 MSI 安装程序做驱动安装。
回车后,控制台开始快速滚动,安装所有的驱动。不过这个东西没很明确的结束提示,只能多等一会儿确保全部安装上了。
PS:安装时十几秒后屏幕会瞬间黑屏并闪烁刷新了一次,不要慌,这是安装 SVGA 3D 显卡驱动时的正常情况。
把程序文件手动复制到默认的安装目录,并通过服务控制器手动建一个服务来每次自动启动:
:: 把程序文件复制到默认目录
mkdir "C:\Program Files\VMware\VMware Tools"
robocopy "C:\VMToolsExtract\VMware\VMware Tools" "C:\Program Files\VMware\VMware Tools" /E /IS
:: 注册系统级后台服务并启动
sc create "VMTools" binPath= "\"C:\Program Files\VMware\VMware Tools\vmtoolsd.exe\"" start= auto DisplayName= "VMware Tools"
sc description "VMTools" "VMware Tools 核心后台管理服务"
sc start "VMTools"
sc create 这条相当于手动帮系统把 VMware Tools 的后台服务登记进服务列表,binPath 指向主程序,start= auto 表示开机自启,把 MSI 安装程序原本该做的事自己手做一遍。
最后控制台返回了明确的 [SC] StartService SUCCESS 就说明成功了。
分辨率自适应缩放与宿主机之间的剪贴板双向同步,依赖的是运行在用户桌面会话中的 vmusr 实例。需要将其写入注册表启动项:
reg add "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Run" /v "VMware User Process" /t REG_SZ /d "\"C:\Program Files\VMware\VMware Tools\vmtoolsd.exe\" -n vmusr" /f
:: 立即启动
start "" "C:\Program Files\VMware\VMware Tools\vmtoolsd.exe" -n vmusr
回车执行,瞬间虚拟机屏幕自适应拉伸铺满了整个宿主机显示区域。尝试一下在主机和虚机之间拖动文件、复制文本,映射虚拟磁盘,这会儿都可操作了,完美。
现在的状态:机器能正常用,分辨率自适应、剪贴板双向同步、文件拖拽、虚拟磁盘映射全部正常,唯一的小问题是每次虚拟机开机都会弹一次“VMware Tools 不是最新版本”。这个可以点「不再提醒我」解决问题。
整个升级过程,槽点多到不知从何吐起:
pnputil 和 sc 不会让人失望,以及老工具就是好用(可惜大都被砍了)。本文 升级 VMware Workstation 的九九八十一难:幽灵虚拟机、1603 报错和手工装 Tools 最初发表于 秋风于渭水。
2026-09-13 11:36:34
最近网上很多不明真相的网友说,GLM-5.3-Flash 的价格只有 DeepSeek-V4.1-Flash 的 1/4 甚至 1/5,就算特价期结束了也比老梁便宜二分之一。其实真用起来完全不是一回事的啦,价格表里便宜一半和实际场景中花多少钱完全一回事:账单最后花多少从来不只看标价——缓存命中率和输出输入比才是决定价格的关键。
下边所有计算的价格都是基于 API 价格,那个不说订阅的事情啊,毕竟 DeepSeek 自己现在压根没订阅制,比这个就没意义了。不过智谱和腾讯最近在订阅侧搞了个活动,有订阅的可以去看一眼。
PS:本来这篇文章上周末写完都准备发了,结果手头事情有点多,这一拖,得,DeepSeek 整了个大的:2026 年 9 月 10 日 12 时起 V4.1 Flash 正式上线,价格大跳水不说,V4 Pro 的请求会全部路由到 V4.1 Flash、按 V4.1 Flash 单价计费——V4 Pro 直接退役了,行吧,又要推倒重算。然后老梁又说 Pro不线下了,AI圈的风向一天一变,服了。
本文价格数据截至 2026-09-12,以两家官方页面为准。
首先让给大家一个最直白,最直接,最不绕弯子、最真相、最不绕弯、最扎心、最硬核、最干脆、最戳痛点的答案:大部分时候写文章、查资料、搞图片视频,GLM 便宜;一写代码就得挑时段——空闲时段 DeepSeek 真便宜,高峰时段就得看命中率了。
智谱 GLM-5.3-Flash 的 5 折特价(输入、输出、缓存命中一律 5 折)已经在 2026 年 9 月 9 日 24:00 结束,现在回到原价,当时缓存存储是限时免费。这波特价刚过去,估计很多人脑子里还是打折时的价格印象,所以下边还是把「特价」和「原价」两列都列出来了。
后边计算的时候,「输入价格」都指缓存没命中的输入单价,「缓存命中」都指命中缓存的输入单价。
DeepSeek-V4.1-Flash 依然分高峰时段与空闲时段,高峰时段为周一至周五 9:00–12:00 和 14:00–18:00(北京时间),其余都是空闲时段。高峰收得贵、低谷收得便宜,网友就给这两档起了外号——高峰叫「梁文峰」,空闲叫「梁文谷」(应该大家都知道这个梗吧)。
人民币(元/百万 tokens)价格表如下。
| 模型和状态 | 输入(缓存命中) | 输入(缓存未命中) | 输出 |
|---|---|---|---|
| DeepSeek 梁文峰(高峰) | 0.04 | 2.00 | 8.00 |
| DeepSeek 梁文谷(空闲) | 0.02 | 1.00 | 4.00 |
| GLM 原价 | 0.23 | 0.80 | 2.80 |
| GLM 特价(9/9 24:00 已结束) | 0.115 | 0.40 | 1.40 |
对比一下上周的价格就知道这波跳水有多狠:空闲时段缓存未命中从 3.00 降到 1.00,输出从 9.00 砍到 4.00,缓存命中更是从 0.10 直接干到 0.02,光这一项就降了 80%。现在梁文谷的缓存命中价 0.02 是全场最低,GLM 特价命中价 0.115 是它的 5.8 倍
每轮请求的总输入:X(M tokens),每轮请求的总输出:Y(M tokens),每轮请求的输出输入比(就是输出 token 数量和输入 token 数量的比值):r = Y/X,缓存命中率(以防万一解释一下:就是这一轮请求里,按缓存价计费的那部分输入 token,占全部输入 token 的比例):k。
那么上边 4 个场景和模型对应的成本公式为:
C_{\text{DS,梁文峰}} = X(2.00-1.96k_{DS}+8.00r)
C_{\text{DS,梁文谷}} = X(1.00-0.98k_{DS}+4.00r)
C_{\text{GLM,原价}} = X(0.80-0.57k_{GLM}+2.80r)
C_{\text{GLM,特价}} = X(0.40-0.285k_{GLM}+1.40r)
简而言之:输入缓存命中的越多,DeepSeek 越便宜;输出占比越大,GLM 越便宜。 两家的计价结构正好在场景坐标系的两头,所以谁贵谁便宜,全看你的使用场景了。
高输出场景:写文章、做 PPT、写文案,模型每轮需要吐出来几百几千字全新内容,而且这种场景很少一个对话干上百轮。
这些场景中 GLM 的特价大约是 DeepSeek 梁文谷的 35%~40%,哪怕按原价算,输入 0.80 对 1.00、输出 2.80 对 4.00,也还是 GLM 全面便宜。DeepSeek 这波降价是挺猛,但要说写东西、查资料,还得是 GLM 的价格合适。
估计看本博客的人里,这是用得最多的场景,也是目前 agent 的主力场景。
在代码任务中,每轮对话都得把系统提示词、Skill 定义、仓库索引和上文的历史代码全带上,一次输入上下文动不动就几十万甚至上百万 tokens,而模型每轮返回的代码或响应往往只有几千、甚至几百 tokens。输入里绝大部分 token 都按缓存命中计费了,缓存命中率会严重影响每轮对话要花多少钱。
以梁文谷为例:
| DeepSeek 命中率 | 输入价格(梁文谷,元/百万 tokens) |
|---|---|
| 90% | 0.1180 |
| 95% | 0.0690 |
| 97.5% | 0.0445 |
| 99% | 0.0298 |
| 99.4% | 0.0259 |
| 99.93% | 0.0207 |
命中率从 90% 提升到 99%,价格能从 0.118 元下降到 0.0298 元,直接少了 75%——同样的任务,一个花 100,一个花 25。
分别对比 90%、95%、97.5%、99% 的区别。
固定命中率下,输出输入比 r 低于分界线时 DeepSeek 便宜,高于分界线时 GLM 便宜:
| 缓存命中率 | vs 梁文谷(空闲) | vs 梁文峰(高峰) |
|---|---|---|
| 90% | r < 0.98% 时 DeepSeek 便宜 | GLM 全赢 |
| 95% | r < 2.32% 时 DeepSeek 便宜 | GLM 全赢 |
| 97.5% | r < 2.99% 时 DeepSeek 便宜 | r < 0.50% 时 DeepSeek 便宜 |
| 99% | r < 3.39% 时 DeepSeek 便宜 | r < 0.88% 时 DeepSeek 便宜 |
空闲时段的梁文谷是真香。代码场景输出占比普遍 1%~2%,按 r = 1% 算,命中率只要过了 90%(精确点就是 90.07%),梁文谷就比 GLM 特价便宜;95% 命中率时 0.109 元对 GLM 的 0.143 元,便宜 24%;到 99% 就是 0.0698 对 0.1319,直接便宜一半。
高峰时段就难受了,按 r = 1% 算,命中率得干到 99.46% 以上梁文峰才能翻盘,但这个命中率基本没戏——我上个月缓存命中率最高的那天也就 97%(这是我自己的数据,有些L站佬友表示用 DS 时当天缓存命中率能到99.4%以上的,你最好看下自己的情况)。
按 r = 1% 算一下每 100 万输入 tokens 的花费(元):
| 命中率 | 梁文谷(空闲) | 梁文峰(高峰) | GLM 特价 |
|---|---|---|---|
| 90% | 0.1580 | 0.3160 | 0.1575 |
| 95% | 0.1090 | 0.2180 | 0.1433 |
| 97.5% | 0.0845 | 0.1690 | 0.1361 |
| 99% | 0.0698 | 0.1396 | 0.1319 |
90% 是道坎:之前 GLM 微赢,之后梁文谷越用越爽。
GLM 原价正好是特价的 2 倍,梁文峰也是梁文谷的 2 倍,两边约掉,数字原地不动——所以「GLM 原价对梁文峰」的分界线和上面「GLM 特价对梁文谷」那条 90% 的线正好一模一样,不用我重新算了。需要注意的变化是 GLM 恢复原价后对上梁文谷:
| 输出输入比 r | GLM 特价 vs 梁文谷(= GLM 原价 vs 梁文峰) | GLM 原价 vs 梁文谷 |
|---|---|---|
| 0% | 86.33% | 48.78% |
| 1% | 90.07% | 51.71% |
| 2% | 93.81% | 54.63% |
| 3% | 97.55% | 57.56% |
(命中率分界线,k 高于分界线 DeepSeek 便宜)
恢复原价后,空闲时段 GLM 基本没得打了:命中率过半梁文谷就赢——谁家 agent 的命中率能掉到 50% 以下啊,我上个月命中率最低的一天(那天从零新建了一个大项目)也有 87%。按 r = 1% 算,GLM 原价要 0.2637 到 0.3150 元,梁文谷只要 0.0698 到 0.1580 元,是梁文谷的 2 倍到 3.8 倍。高峰时段 GLM 还能搏一搏,命中率 90% 以下时 GLM 原价依然比梁文峰便宜,90% 以上才输。
所以 agent 场景下,现在这个时点(特价已经结束):晚上挂机用梁文谷,白天就得看命中率了——90% 以上梁文峰,90% 以下 GLM 原价。这波 DeepSeek 降价,非常稳准狠地打在 GLM 的软肋上——就等你 GLM 特价结束,直接截留用户。
所以大模型 API 怎么省钱?看表对号入座:
| 你的场景 | 选谁 |
|---|---|
| 写文章 / 查资料 / 出图出视频 | GLM-5.3-Flash,按原价也比 DeepSeek 便宜 |
| 写代码,跑在夜间和周末(空闲时段) | 梁文谷,命中率越高越香,90% 以上开始拉开差距 |
| 写代码,跑在周一至周五白天(高峰时段) | 命中率 90% 以上梁文峰,90% 以下 GLM 原价(90%以下命中率基本只限于项目初建还在探讨的时期) |
另外提一嘴两个订阅侧的福利:
1. 智谱给付费订阅用户留了个窗口——即日起到 9 月 20 日,每晚 23:00 到次日 9:00,所有付费套餐用户免费用 GLM-5.3-Flash。你要是刚好是订阅用户,那晚上就不用纠结梁文谷了,直接白嫖 GLM,白天的账再按上面的表算。
2. 腾讯的 Workbuddy 国内版的 DeepSeek-V4.1-Flash 在 9 月 23 日前半价计费,国际版则是直接把 DeepSeek-V4.1-Flash 免费了(但暗中限制了每日额度和请求频率)
不过这类限时活动实际是个什么情况大家都知道:结束时间基本不会延期,能白嫖的时候赶紧用吧。
本文 GLM-5.3-Flash 可能比 DeepSeek-V4.1-Flash 还贵,价格表和实际场景不是一回事 最初发表于 秋风于渭水。
2026-09-08 09:03:36
周末收到了 OpenCode 的邮件,提醒我,部分请求缺失 x-opencode-session 请求头,在 09/06 之后,如果缺失这个请求头,请求可能会失败。

简而言之就是 OpenCode 的风控要求,使用 Go 订阅的请求至少需要有:X-Opencode-Session 与 user-agent 这两个请求头
user-agent:用来识别你用的是什么 agent 工具,根据他们飞书群内客服的说法:目前允许用户将 Go 订阅用于 opencode 之外的其他 agent 工具,也不阻止你用中转,但仅限常见的 agent 工具,禁止直接使用脚本调用,Zen 则没有这个限制(毕竟浪费的算力和 token 是你掏钱,OpenCode 反正不会亏)。
X-Opencode-Session:OpenCode 靠这个标头做 GPU 上下文缓存。同一个对话的所有多轮请求,都带上同一个固定的 Session ID;而不同的对话之间,使用不同的 Session ID,这样可以将同一个对话的请求调度到同一个 GPU,直接复用上一轮已经生成的显存缓存,而不用做跨 GPU 复制 KV 缓存。(为了节省算力,省钱)是一个符合UUID(v4)格式,形如550e8400-e29b-41d4-a716-446655440000的32(36)位字符串。
NewAPI 本身提供修改请求头的功能,我们的思路就是:
X-Opencode-Session 的请求头。(比如 Session-Id、Session_id、X-Conversation-Id、X-Claude-Code-Session-Id)可以用 webhook.site 抓包。访问网页后,复制网页上为你生成的唯一链接(比如 https://webhook.site/3a2b1d-a1b2-c3d4-d5e6-123456789),把 agent 工具对应模型的 Base URL 改成这个链接(记得换个假 KEY,不然真实 Key 会被抓包到),模型名随便填一个能发出去请求的就行,去工具里随便发一次请求,看看你的工具,正常的请求头会是什么样的。

以 Workbuddy 为例,可以看到工具本身就会发送 user-agent,所以这个好解决,但是 Workbuddy 是不可能发送 X-Opencode-Session 的,毕竟这是个 OpenCode 客户端专有的请求头。
不过仔细测试后发现,Workbuddy 会为每个对话发送 x-conversation-id 和 acp-connection-id 请求头,其中的 x-conversation-id 完美符合 x-opencode-session 的要求和格式:不同对话间不同,同一个对话中固定,断开网络或重启也不变,使用UUID V4格式(acp-connection-id 则属于标记连接的,网络环境变化或重启后会变化)。
找到「渠道 – 编辑 – 请求头覆盖」填入如下 JSON
x-conversation-id 为 X-Opencode-Session){
"*": true,
"X-Opencode-Session": "{client_header:x-conversation-id}"
}
User-Agent 和 X-Opencode-Session,屏蔽其他请求头{
"User-Agent": "{client_header:user-agent}",
"X-Opencode-Session": "{client_header:x-conversation-id}"
}
正常的 agent 工具,请求头可能有十几个二十几个,如果只发关键的,其实也在暴露”你有个中间层在改请求头”这个事实。
所以先抓包看看你的 agent 工具到底发了什么请求,然后把 x-real-ip(真实 IP)、remote-host(主机名)、x-user-id(设备追踪标识)这种会暴露你实际位置和用户身份的参数给干掉。其他的都给透传了,这样更像真实的工具请求。具体怎么写你可以问你的 AI。
找到「渠道 – 编辑 – 参数覆盖」填入如下 JSON
{
"operations": [
{
"mode": "copy_header",
"keep_origin": true,
"from": "X-Opencode-Session",
"to": "X-Opencode-Session"
},
{
"mode": "copy_header",
"keep_origin": true,
"from": "Session-Id",
"to": "X-Opencode-Session"
},
{
"mode": "copy_header",
"keep_origin": true,
"from": "Session_id",
"to": "X-Opencode-Session"
},
{
"mode": "copy_header",
"keep_origin": true,
"from": "X-Conversation-Id",
"to": "X-Opencode-Session"
},
{
"mode": "copy_header",
"keep_origin": true,
"from": "X-Claude-Code-Session-Id",
"to": "X-Opencode-Session"
}
]
}
注意:参数覆盖无法修改 stream 参数,另外它本身只处理请求体/请求头的映射操作,和请求头覆盖不一样,按需选用。
X-Opencode-Session 的值,不然一旦有并行任务,在上游看来就是同一个人在交替请求完全不一样的任务,看起来像是多人共用,妥妥属于高风险特征。webhook.site 再抓一次包对着看,缺什么补什么。本文 OpenCode Go 请求失败?NewAPI 中转配置 x-opencode-session 请求头教程 最初发表于 秋风于渭水。
2026-09-03 11:38:44
可能很多人知道我的后端主机用的是腾讯云的机器。但很多人不知道腾讯云轻量应用服务器每年都有个周年庆活动,这应该是最适合续费主机的时候了,为什么呢,因为5年以上用户,1折续费。这价格可不好找。
良心云有时候确实挺良心的,和其他厂商常见的”新用户才是人,老用户不如狗”的续费策略不同,腾讯轻量云周年庆对老用户可谓良心,除了新购优惠,还包括老用户续费折扣、双人拼团加赠时长、同价续费、2核4G可免费升级4核4G,活动持续到2026年10月12日(含)。
活动入口:腾讯云轻量云六周年活动 (放心点,链接没AFF,是官方直达链接)。
| 腾讯轻量云实例使用时长 | 续费折扣 |
|---|---|
| 6个月内轻友 | 5折 |
| 6~12月轻友 | 4.5折 |
| 1~3年轻友 | 2.5折 |
| 3~5年轻友 | 1.5折 |
| 5年及以上轻友 | 1折 |
以我现在后端这台 2H4G/30M2T 的主机来说,要是原价续费 1 年就需要 648 元,因为是5年以上用户,打1折,就仅需 64.8 元,再加上双人开团活动送 3 个月,平均下来每月只需要 64.8/15=4.32 元/月。每个月还没一瓶红牛贵。轻量云 1折续费这价格几乎等于不要钱嘛,结论:
满足条件的轻量云实例新购或者续费之后,可以参与拼团,两个人即可成团。
| 续费/新购时长 | 加赠时长 |
|---|---|
| 新购1年 | 3个月 |
| 续费1年 | 3个月 |
| 续费6个月 | 1个月 |
注意:每个账号只能参加一次拼团,且一旦成团的实例退款有额外限制条款,这次不像之前还能玩”自己和自己拼、再退款一台”那种白嫖操作了。也没必要为了赠送时长去购买自己用不到的吃灰服务器。
多2个核心,对跑WordPress、PHP、Java、.NET、Docker、Node.js之类的动态内容的主机还是很有意义的。
这里有个点要注意:参加了免费升配,就等于放弃了实例的同价续费资格(因为升配后实例规格变了)。
所以如果你的主机是同价续费的,且确实需要多出来的这2个核心的话,可以先续费,再升配。
PS:轻量云之前有过一个CPU性能提升活动,虽然还是2核,但是会给你换新的 CPU 型号,据说能获得20%的CPU单核性能提升,不知道现在控制台还能看到这个活动不。(感觉纯粹是因为一些老实例正好需要迁移到新宿主机上,新主机本来就会提升出一点性能,不如包装成活动给用户)
用2个核心忽悠你升配放弃原价续费,看似免费从2核变4核了,但未来续费的价格可就涨回去了。
腾讯云轻量云六周年活动对三类用户比较合适
本文 腾讯云轻量应用服务器续费1折:老用户难得比新用户便宜的活动 最初发表于 秋风于渭水。