以太坊幽灵交易根因与Nonce管理实战:从卡死到自动化防护
凌晨三点十七分监控大屏的告警把值班手机震醒。点开一看某资金归集服务最近的链上交易数为零进程却还活着日志里没有任何异常。刷新区块浏览器交易列表躺着一串 pending确认数全是零。再往下翻更诡异的事情出现了nonce 5 的那笔交易不见了nonce 6、7、8 全都挤在交易池里排队却谁也跑不动。这就是区块链运维圈里常说的幽灵交易ghost transaction。它不报错、不出块、不占余额但像一块隐形砖头把后续所有交易全部卡死。如果你正在跑批量转账、资金归集、跨链中继这类高频交易服务Nonce 管理迟早会成为你最头疼的运维课题。这篇日记我把这次事故从现象到根因、从排查到修复的完整过程拆开来讲顺便把我踩过的坑和现在用的自动化防护方案一并交代清楚。1. 凌晨三点半的警报账上没少钱日志没有错先说事故的第一现场。告警规则其实很简单归集服务地址过去 1 小时链上交易数为 0就触发通知。当时服务进程、数据库、节点连接全部正常日志最后一条是交易已广播成功后续就完全没有新的日志输出。这正是这类故障最迷惑人的地方——服务层面一切正常链上却什么都推进不了。我第一反应是去节点上查交易池状态。用eth_getTransactionCount对比两个参数latest和pending。正常情况下两者之差等于当前在池中未确认的交易数最多也就是 1 到 2 的差距。但当时返回的结果是latest 42pending 49。差了 7说明有 7 笔交易积压在池中没出块。接下来查每一笔 pending 交易问题马上就暴露了。交易池里最靠前的交易 nonce 是 4342 已经出块所以理论上 43 应该排在第一个。但奇怪的是区块浏览器上 43 这一笔显示的是未知交易状态既没有进入新区块也没有被节点广播回执。而 44、45、46 到 49 全都正常显示 pending。这里要划第一个重点交易池里看不到 nonce 43 对应的交易内容不代表它不存在。只要全网节点中有一个节点还保留着这笔交易的原始记录它就会一直占着坑。占坑的结果就是44 及以后的交易无论 gas price 多高矿工都不会打包因为以太坊要求同一账户的交易必须严格按照 nonce 顺序执行前面的没走后面的就得排队。我当时试着用eth_sendRawTransaction重新广播一笔 nonce 43 的新交易结果节点直接返回了nonce too low。这就说明 43 这个位置在网络中确实被占据着只是我们自己的节点看不到它的内容。这种看不见但确实存在的状态就是幽灵交易最典型的表现。提示如果服务端日志只显示广播成功而没有等待回执、也没有做 nonce 状态跟踪你几乎不可能在第一时间意识到某笔交易已经变成了幽灵。2. Nonce 是账户的排队号不理解它就理解不了卡死要彻底搞懂幽灵交易得先把 Nonce 机制从原理上理清楚。它不是一个可配置的参数而是以太坊账户模型中强制执行的顺序计数器。每一笔从同一地址发出的交易都携带一个nonce字段。这个值从账户创建后的第一笔交易开始计数从 0 开始每成功广播一笔就递增 1。矿工打包交易时只接受连续 nonce 的序列如果账户当前已处理的 nonce 是 42那么下一笔被接受的交易 nonce 必须是 4344、45 哪怕 gas price 更高也必须等 43 先处理完。用生活中的例子理解你在银行取号叫号系统必须按号码从小到大叫哪怕 45 号的客户是 VIP43 号的人没到场柜员也必须先跳过还是叫 4344、45 只能干等。交易池就是候诊区节点把收到的交易按 nonce 排序前面的位置空着后面的永远轮不到。这里有个特别容易被忽略的点nonce 是账户维度的状态不是钱包维度的状态更不是应用维度的状态。同一个私钥哪怕拆成十个热钱包实例去发交易它们共享同一个 nonce 序列。很多团队做多实例部署时每个实例各自去链上查询 nonce拿到的可能是同一个值结果两笔交易用了同一个 nonce只有一笔能成功另一笔就变成幽灵或者直接被拒绝。另一个基础概念是eth_getTransactionCount的两个参数。latest返回的是已经被打包进区块的交易数量pending返回的是节点交易池中已经确认有效的交易数量包括那个还没出块的 nonce 43。问题在于pending 参数在不同节点实现上的返回值并不完全一致。某些轻节点、归档节点、或者经过特定配置的节点对 pending 的判定规则不同可能导致你拿到错误的 nonce 基数进而制造出非连续序列。所以做 Nonce 时最忌讳的一件事就是每次发交易前都去链上现查一个 nonce 值然后立刻用。这个操作在并发下单时会带来两个极端要么两个请求拿到同一个 nonce 导致覆盖要么拿latest忽略了池中交易导致重复 nonce 或 gap。我后面会谈到现在采用的本地计数器方案这里先记住结论——做一个正常的塞车队列比绞尽脑汁猜远程状态要可靠得多。3. 幽灵交易的本质非连续 Nonce 把后续交易全部锁死回到事故本身。nonce 43 的那笔交易为什么看不见我复盘之后归纳了三种最常见的成因几乎涵盖了所有幽灵交易出现的场景。第一种也是最常见的客户端拿到了 nonce 43构造了交易广播出去时网络超时客户端没收到回执于是认为发送失败。但实际上这笔交易已经被某个节点接受并放进了交易池。客户端随后重试调用节点时发现nonce too low就以为交易没发出去直接跳过。结果就是交易池中 nonce 43 占着位置但客户端已经完全忘记它的存在再往下发就是 nonce 44、45……第二种多实例并发。两个实例同时查询eth_getTransactionCount得到 42于是各自构造 nonce 43 的交易。其中一笔先上链另一笔因为 nonce 冲突被节点拒绝。但被拒绝的那一笔在广播给多个节点的过程中可能已经被部分节点暂存这取决于交易池实现没有立即清理最终真正打包时只剩一笔另一笔就变成了某个节点内存中的幽灵记录。第三种手动重放或者阻塞处理不当。运维在排查时看到某笔交易 pending 太久直接把交易 hash 重新广播一次本来想加速结果因为 gas price 设置低于原交易替换失败还造成了额外的非连续状态。又或者某个内部任务使用了相同的 nonce 重复提交第一笔还在池中第二笔却带着更高的 gas price 覆盖了它原先那笔的状态从此变得不确定。不管哪种成因结果都一样某个 nonce 的位置在网络中处于已占用但未确认的悬空态后续交易全部锁死。资金流因此卡住但余额没有减少因为没有任何一笔交易真正上链执行。这也是幽灵一词的由来——它让资金流看起来正常实际已经冻住了。这里值得多说一句gas price 高低在锁死问题面前没有任何作用。很多运维第一反应是是不是 gas 出价太低导致矿工不打包然后拼命提高后续交易的 gas price。结果只会更糟因为矿工打包交易表是按 nonce 排序的nonce 43 的坑位空着后面的交易 gas price 再高也进不了候选区。反而可能在非连续状态下触发节点的严格校验直接把后面的交易也拒绝掉。注意跳号不是网络拥堵造成的而是序列断裂造成的。拥堵只会让交易 pending 的时间变长序列断裂则是让所有后续交易彻底失去打包资格。4. 从 RPC 到交易池完整排查链路还原事故现场遇到这种问题千万别急着重发交易。我这次事故花了大概四十分钟才完全定位根因期间走了不少弯路。现在把正确的排查链路整理出来你可以直接照着执行。第一步通过 RPC 确认状态差。curl -X POST http://127.0.0.1:8545 -H Content-Type: application/json \ --data {jsonrpc:2.0,method:eth_getTransactionCount,params:[0x你的地址, latest],id:1} curl -X POST http://127.0.0.1:8545 -H Content-Type: application/json \ --data {jsonrpc:2.0,method:eth_getTransactionCount,params:[0x你的地址, pending],id:1}如果pending比latest大 1 以上就说明池子里有多笔未确认交易第一步告警成立。如果差值等于 0那问题可能出在服务本身不一定是 nonce。第二步查看交易池内容寻找缺口。curl -X POST http://127.0.0.1:8545 -H Content-Type: application/json \ --data {jsonrpc:2.0,method:txpool_content,params:[],id:1}txpool_content会返回当前节点交易池中所有交易的完整内容按地址分组。你可以直接数出某个地址下所有 pending 交易的 nonce排序后对比从latest1开始第一个缺失的数字就是 gap 的位置。在我这次事故里就是 43。第三步确认缺失位置是否被占。对于 gap 位置的 nonce尝试查询该 hash 是否存在于链上或者池中。如果交易池里找不到可以再尝试用debug_txPool或者直接对几个额外节点发起同样的查池请求。这一步的核心目标是回答一个问题这个 nonce 到底存不存在如果存在它是被忽略了还是被覆盖了如果不存在那说明是本地状态与链上不一致需要重新广播。第四步验证幽灵确实在。这步可以通过一个反向探测实现构造一笔 gas price 极高的交易塞进 gap nonce 位置。如果节点返回nonce too low说明该位置已被占用——幽灵被确认存在。如果返回成功交易正常进入交易池并被矿工打包那说明只是本地数据滞后gap 其实不存在。这套流程看起来简单但我在实际排查中犯过一个错误直接用eth_getTransactionByHash查询那笔认为存在的交易结果返回 null于是断定 gap 不存在转头把后面的交易重新广播。结果当然没用因为另一个节点上可能还存着原交易。所以一定要用探测法而不是单点查询法。5. 解围实操补洞交易、覆盖交易与双方案对比定位到幽灵交易后怎么解围有两个方向补洞和覆盖。两者适用场景不同我先说结论再展开操作。覆盖方案针对同一个 nonce 重新发送一笔完全相同的交易但提高 gas price。矿工在交易池中看到同一 nonce 的新交易如果新交易的 gas price 比旧交易高且 gas limit 设置合法就会用新的交易替换旧的。这个方案适用于旧交易还在池中但迟迟不打包的情况比如 gas 出价过低、网络拥堵。补洞方案向 gap 位置发送一笔零金额的自转账地址填自己value 为 0gas limit 21000gas price 拉到网络中高位。这笔交易会占用 gap nonce 并快速出块出块后其后面的交易自动恢复打包资格。这个方案适用于旧交易已经彻底消失、仅留下 nonce 占位的情况——也就是我们这次遇到的幽灵交易。实际操作时补洞交易构造如下以 ethers.js 为例const wallet new ethers.Wallet(privateKey, provider); const tx { to: wallet.address, // 转给自己 value: 0, // 零金额 nonce: 43, // 缺口位置的 nonce gasLimit: 21000, // 原生转账固定消耗 maxPriorityFeePerGas: ethers.parseUnits(2, gwei), maxFeePerGas: ethers.parseUnits(50, gwei), }; const txResponse await wallet.sendTransaction(tx);这里有几个细节要提醒你第一gasLimit 一定要设为 21000因为这是一笔标准转账任何超过 21000 的设置都可能让交易失败反而制造新的麻烦。第二value 必须为 0不要为了顺便转点钱而在这个位置塞实际金额等到这个位置确认后后续交易正常了资金流自然恢复。第三gas price 必须给够建议比当前网络平均 gas price 高 20% 到 50%目的就是让这笔补洞交易尽快出块别让它自己反而变成新的 pending。覆盖方案和补洞方案的选择有一个判断标准如果你能通过别的节点查到该 nonce 的原始交易内容哈希优先覆盖如果查不到内容但确认 nonce 被占用就用补洞。覆盖方案的额外风险是需要重新签名构造交易太慢而且如果原交易已经广播到了多个节点新交易必须被这些节点全部接受才能完全替换否则会残留。补洞方案则不需要考虑旧交易内容直接占坑操作最简单成功率最高。解围后的恢复过程也不是瞬间完成的。补洞交易出块后后续 pending 交易的 nonce 变为连续矿工会在下一个或多个区块中按顺序打包这些排队交易。整个过程持续几分钟到十几分钟不等取决于交易池中排队长度和网络出块速度。我在这次事故中补完 nonce 43 后大概过了 8 分钟所有 7 笔 pending 交易全部确认资金流恢复。重要补洞操作必须在同一节点上执行并且广播前确认节点已同步到最新区块。否则nonce too low的误判会再次出现。6. 自动化的 Nonce 管理让跳号不再发生事故处理完只算解决了一半问题。另一半是怎么让幽灵交易不再出现我在这件事之后把服务端的 Nonce 管理从随查随用改成了本地有状态计数运行了三个月再没出过类似事故。做法不复杂但值得作为一个完整方案分享出来。整体思路是服务端维护一个本地 nonce 计数器每次发交易时原子递增同时把每次交易的确认状态跟踪起来。具体分四步。第一步建立一个 nonce 管理服务可以是独立模块也可以是 Redis 里的一个 key。每次需要发交易时从 Redis 执行原子自增操作把返回值作为交易 nonce。这一步保证了同一私钥下、同一时间点全局只有一个实例能拿到某个 nonce。import redis r redis.Redis(hostlocalhost, port6379, decode_responsesTrue) key fnonce:{address} current r.incr(key) # 原子自增 # 第一次使用前需要将 key 初始化为当前的 latest nonce - 1第二步初始化计数器时使用eth_getTransactionCount(address, pending)的值减去一个安全余量避免覆盖池中已有交易。千万别用latest初始化否则会把 pending 中的交易 nonce 当成已用的导致后续构造的交易 nonce 偏低。第三步每笔交易发送后立刻记录 hash 和对应的 nonce存入本地持久化存储并启动一个轮询任务跟踪确认状态。确认成功后更新计数器确认失败或长时间未确认则走替换或补洞流程。第四步设置交易确认超时阈值。比如 5 分钟内未确认触发一次替代交易替代交易同样失败触发警告并停掉该地址的后续发送任务防止非连续状态扩大。这套方案的好处在于你对每一个 nonce 的使用和状态都有完整记录鬼影交易一旦出现你就可以直接从本地日志里找到它从哪里来的、为什么消失。排查时间可以从四十分钟压缩到五分钟。当然分布式场景下还要考虑一个问题如果同一个私钥部署在多个节点上。解决办法是引入全局分布式锁确保任一时刻只有一个实例能拿到 nonce 自增服务。Redis 分布式锁或者数据库行锁都可以重点不是工具而是确保同一私钥不可并发签名这个铁律。提示如果服务不是高频交易场景也可以用轻量方式发交易前用eth_getTransactionCount(pending)实时获取并把结果缓存在本地 3 秒。虽然做不到绝对安全但对低频批处理服务来说已经足够。7. 那些年踩过的 Nonce 坑经验复盘最后这部分我想把运维中容易踩的其他 Nonce 相关的坑集中列一下。它们未必都造成过事故但每一个都足够让人头疼。第一坑不同 RPC Provider 的pending返回值不一致。我把四个常用节点提供商的数据做过对比发现对同一地址某些提供商返回的 pending 值会比链上实际 pending 少一截。原因在于它只统计了自己节点交易池而交易池之间并非实时共享。做非阻塞式调用时这个差异会被放大。对策只信任自建节点或者用多个节点交叉验证。第二坑手动操作时误用latest获取 nonce然后发送交易。如果你的服务正在正常出块手动补一笔交易时用latest拿到的 nonce 值可能已经过时导致nonce too low。要注意手动操作前先查看 pending 状态再决定用哪个值。第三坑冷热钱包分离后热钱包地址的 nonce 状态经常被忽略。热钱包本身是独立账户如果忽略了它也是从 0 开始计数的状态第一次初始化计数器时容易按经验值设定直接导致 nonce 跳号。所以无论什么类型的钱包初始化计数器必须用链上状态。第四坑测试网和主网的行为差异。以太坊测试网对 nonce 冲突的处理在某些情况下更宽容会直接覆盖而非产生幽灵交易。这会导致你在测试环境怎么测都测不出问题一上主网立刻炸锅。所以 Nonce 并发脚本的压测必须选一个行为接近主网的环境并且测试用例要包含并发发送、异步超时、手动重放三种场景。第五坑blocknative 之类的浏览器型工具在跟踪交易时只能看到链上状态看不到交易池内容。真正的 Nonce 管理必须回到节点底层用txpool_content系列接口而不是依赖上层浏览器数据。这里还要补充一个容易误判的点交易卡住时很多人会怀疑是不是余额不足。幽灵交易导致的卡死余额通常显示充足因为没有任何交易成功消耗 gas。但如果你反复发送替代交易gas 会呈倍数消耗最终可能导致余额真的不足变成第二个事故源。所以排查时务必先确认余额与 nonce 状态再决定是否重发。最后聊几句我的感受。Nonce 管理看起来是区块链开发中最基础的知识点但真正在运维层面把这件事做扎实的团队并不多。大多数事故都不是因为技术难而是因为以为客户端已经帮我管好了。实际上钱包库给出的 nonce 管理往往只考虑了单线程、阻塞式调用放到异步高并发环境里就漏洞百出。与其等客户端出 bug 再补丁不如一开始就把 Nonce 作为服务端有状态组件来设计。资金流被跳号卡死这种事经历过一次就够刻骨铭心的了。

相关新闻

网页 window.open 连点两次为什么串到同一个窗口:HarmonyOS 7 ArkWeb name 路由怎么防重入

网页 window.open 连点两次为什么串到同一个窗口:HarmonyOS 7 ArkWeb name 路由怎么防重入

网页 window.open 连点两次为什么串到同一个窗口:HarmonyOS 7 ArkWeb name 路由怎么防重入 网页连续两次调用 window.open(url, "preview"),应用侧创建了两个窗口,但后一次内容跑进前一个窗口;关闭其中一个后&#xff…

2026/10/13 10:39:24 阅读更多 →
大鹿岛:一座海岛如何把森林、海蚀礁石与岩雕叠在一起

大鹿岛:一座海岛如何把森林、海蚀礁石与岩雕叠在一起

第一次听到“大鹿岛”这个名字,是在台州朋友的饭桌上。他说那座岛上的石头会讲故事,我当时觉得他在夸张——海岛见得多了,无非是沙滩、海鲜、海风,石头能有什么稀奇。真正登岛是第二年初秋,船从玉环一侧开出去&#xf…

2026/10/13 10:39:24 阅读更多 →
多语言语义检索实战:paraphrase-multilingual-MiniLM-L12-v2 选型、调参与微调

多语言语义检索实战:paraphrase-multilingual-MiniLM-L12-v2 选型、调参与微调

简介:这份资源是 sentence-transformers 库中 paraphrase-multilingual-MiniLM-L12-v2 模型的本地化压缩包,面向从事自然语言处理、语义搜索与文本聚类的中高级开发者。模型可将句子和段落映射到 384 维密集向量空间,适用于多语言语义检索、相…

2026/10/13 10:39:24 阅读更多 →

最新新闻

今客CRM PHP源码部署与二次开发实战指南

今客CRM PHP源码部署与二次开发实战指南

简介:今客CRM客户管理系统PHP版v1.2.2是一套开源、可部署的轻量级客户关系管理源码,面向计算机专业学生、PHP初学者及毕业设计开发者,用于学习Web系统架构、CRM业务逻辑实现与前后端协同开发。资源共929个文件,涵盖340个PHP核心逻…

2026/10/13 11:21:39 阅读更多 →
虚拟化集群9台VM集体失联复盘:存储链路抖动与光模块老化排查

虚拟化集群9台VM集体失联复盘:存储链路抖动与光模块老化排查

如果有一天早上,你刚端起杯子还没喝一口,监控群里突然开始连环报警,内容都是同一句话:“XX系统不可用”。你打开虚拟化平台一看,9台虚拟机齐刷刷变成灰色,状态全部异常,业务电话一个接一个打进来…

2026/10/13 11:21:39 阅读更多 →
九台虚拟机集体失联?虚拟化共享存储故障排查与恢复实录

九台虚拟机集体失联?虚拟化共享存储故障排查与恢复实录

凌晨1:47,我手机上的监控报警像连环夺命call一样开始振动。业务群里的消息一瞬间就刷了屏——“9台服务器全部失联”。我揉着眼睛坐起来,第一反应是觉得哪里搞错了:晚上巡检的时候明明一切正常,怎么一下子就全没了?更让…

2026/10/13 11:21:39 阅读更多 →
OpenCV图像矫正实战:透视变换与文档扫描全流程

OpenCV图像矫正实战:透视变换与文档扫描全流程

简介:本资源面向图像处理初学者与OpenCV开发者,聚焦“全能扫描王”式文档矫正功能的实现,帮助解决拍摄文档倾斜、扭曲与透视失真问题。包内共13个文件,以9个png与1个jpg测试图片、1个cpp核心源码为主,另含gitattribute…

2026/10/13 11:21:39 阅读更多 →
Java Files.lines()从文本行创建Stream的实战指南与避坑详解

Java Files.lines()从文本行创建Stream的实战指南与避坑详解

做 Java 开发这些年,读取文本文件这事几乎天天都在干。早年间我是标准的 BufferedReader 加 while ((line reader.readLine()) ! null) 循环,一行一行处理,写多了确实觉得啰嗦。后来 Java 8 引入 Stream API,我第一次用 Fil…

2026/10/13 11:21:39 阅读更多 →
论文查重免费平台实测:每天200篇额度如何让降重成本归零

论文查重免费平台实测:每天200篇额度如何让降重成本归零

又是一年毕业季,朋友圈里满是“查重又要花钱”“学校只给一次免费查重机会”的哀嚎。我自己去年帮课题组改论文,前前后后用第三方付费查重花了小几百,后来偶然发现一个每天能免费用 200 篇的查重平台,一开始以为是噱头&#xff0c…

2026/10/13 11:20:38 阅读更多 →

日新闻

物联网系统集成避坑指南:从选型到验收的关键要点

物联网系统集成避坑指南:从选型到验收的关键要点

做了这么多年物联网系统集成的项目,我最大的感受是,大部分坑不是出在技术前沿,而是出在一些看起来很平常的地方。设备选了便宜的、协议没问清楚、现场没摸透、验收标准写得含糊——这些细枝末节,最后都会变成延期、超支和扯皮的大…

2026/10/13 0:00:57 阅读更多 →
ESP32舵机控制全攻略:从PWM原理到高级玩法与常见故障排查

ESP32舵机控制全攻略:从PWM原理到高级玩法与常见故障排查

如果你玩ESP32有一阵子了,很难不碰到舵机控制这道坎。做智能小车要转方向,做机械臂要抬关节,做云台要偏航俯仰,背后都是同一个东西在干活:舵机。而我见过太多人卡在“代码能编译、舵机就是不听话”这个阶段&#xff0c…

2026/10/13 0:00:57 阅读更多 →
CAN总线原理与STM32实战:抗干扰、仲裁、错误处理全解析

CAN总线原理与STM32实战:抗干扰、仲裁、错误处理全解析

1. 为什么CAN总线至今仍是工业现场的“硬通货”?——从汽车底盘到智能温室的真实需求你有没有拆过一辆老款燃油车的中控台?或者调试过某高校实验室里那台跑着Modbus协议却频频丢帧的PLC控制柜?又或者,在某个农业物联网项目里&…

2026/10/13 0:00:57 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/13 2:54:56 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/12 0:16:38 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/13 1:58:08 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 21:05:09 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 14:48:49 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 18:11:17 阅读更多 →