Kettle PDI 7.1实战:从环境配置到命令行跑批的完整避坑指南
简介这份压缩包是 Pentaho Data IntegrationKettle社区版 7.1.0.0-12 的完整发行文件面向需要做数据抽取、清洗转换与加载的 ETL 工程师和数据集成开发者。包内共 1928 个文件包含 1300 余个 jar 库文件、200 个 ktr 转换、19 个 kjb 作业以及大量 xml、cfg、properties 配置等压缩后体积约 862MB既覆盖核心运行库也提供示例流程和启动脚本便于快速部署与二次开发。作为 2018 年发布的社区版它免费开源内置 Spoon 图形化设计器、Pan 与 Kitchen 命令行执行工具、Carte 分布式服务等关键组件并针对大数据处理性能、数据源连接和错误日志机制做了改进足以支撑从异构数据库、文件到数据仓库的典型集成场景。目前已有 3400 余人学习下载适合刚开始接触 Kettle 或需要在本地搭建数据集成环境的读者作为离线参考包使用。1. PDI CE 7.1 资源拆解这个 zip 装的是什么为什么还有人在用很多人问我Kettle 都到 9.x 了怎么还在折腾 7.1我的回答通常是反过来问一句你的历史项目里是不是还跑着一堆 .ktr 和 .kjb如果是你就知道 pdi_ce7.1.0.0-12.zip 这个 Kettle 7.1 pdi_ce 标准发行包有多难绕开。它对应 Pentaho Data Integration 社区版 7.1社区里俗称 PDI 7.1解压后就是完整的>mkdir -p /opt/etl unzip pdi_ce7.1.0.0-12.zip -d /opt/etl ls -la /opt/etl/data-integration参数说明unzip 的 -d 指定解压目标目录。解压产物根据 zip 内顶层目录展开通常得到># 先确认当前系统默认 Java 版本 java -version # 期望输出类似 openjdk version 1.8.0_292必须带 1.8 字样如果系统默认版本不对不要改全局 PATH而是通过环境变量单独喂给 PDIexport JAVA_HOME/usr/lib/jvm/java-8-openjdk-amd64 export PATH$JAVA_HOME/bin:$PATH参数说明JAVA_HOME 是第一个生效的配置Spoon、Pan、Kitchen 启动脚本会优先读取它然后再回退到 PATH 里的 java。这样做的价值在于你同一台机器上其他服务可以继续用 JDK 17只有 PDI 相关脚本走 JDK 8。切换后记得重新打开终端或 source 一下配置否则环境变量还是旧值。2.3 内存参数改 spoon.sh 前先搞清楚 -Xmx 的含义Spoon 默认堆内存给的比较保守常见配置在 512m 到 1024m 之间。处理几十万行的转换就会频繁 Full GC表现为界面长时间转圈、CPU 占用高但任务不前进。改内存的入口是各启动脚本里的 PENTAHO_DI_JAVA_OPTIONS以 spoon.sh 为例# 打开 spoon.sh 找到这行然后把堆内存调大 PENTAHO_DI_JAVA_OPTIONS-Xmx2048m -XX:MaxPermSize512m -Dfile.encodingUTF-8参数说明-Xmx2048m 是堆内存上限2G 对大部分常规 ETL 足够-XX:MaxPermSize 在 JDK 8 里已经被元空间取代写了也不报错属于无害的历史包袱-Dfile.encodingUTF-8 是很多人忽略的关键项它从 JVM 层面固定文件编码能在源头减少中文乱码问题。改完后重启 Spoon再去“帮助 - 关于”里看 JVM 参数是否生效比盲猜稳得多。注意-Xmx 不要超过物理内存的 50%。堆给得过大GC 暂停反而变长转换没提速机器先卡了。我见过有人直接给 8G结果 16G 内存的机器跑一个小转换界面卡到鼠标都动不了。3. 从零搭一个数据转换CSV 读取到 MySQL 落表环境就绪后第一次实操从最简单的场景开始把一个 CSV 文件读进来清洗掉明显不合法的行写进 MySQL 的一张表。整个过程走完你对 PDI 的执行机制会有直观感受。3.1 转换和作业两种文件类型的分工别混着用PDI 7.1 里有两个容易混淆的核心概念转换Transformation后缀 .ktr和作业Job后缀 .kjb。转换描述的是数据流里面的步骤以并行方式执行数据像水一样从上游步骤流到下游步骤作业描述的是一条调度链路按顺序执行转换、Shell 脚本、发送邮件、判断成功失败等动作。实际项目中我的习惯是一段独立的数据加工逻辑做成一个转换多个转换按业务顺序拼成一个作业。例如“读取 CSV - 清洗 - 入 MySQL”是一个转换“执行清洗转换 - 执行汇总转换 - 发送通知邮件”是一个作业。新手最容易犯的错是把作业当转换用在里面强行连线各种数据步骤最后数据流全乱套。3.2 最小转换实操CSV 文件输入到表输出打开 Spoon 后点“文件 - 新建 - 转换”从左侧面板的“输入”分类拖一个“CSV 文件输入”到画布再从“输出”分类拖一个“表输出”到画布按住 Shift 点击前者再点击后者把两个步骤连起来连接线上会出现一个箭头表示数据流方向。CSV 文件输入 -- 表输出双击“CSV 文件输入”文件路径填 /opt/etl/data/user_data.csv 这类绝对路径。点“获取字段”按钮Spoon 会读取文件头自动生成字段列表。这一步有个高频问题CSV 输入步骤的“编码”默认是 GBK如果源文件是 UTF-8中文到这里就会乱掉后续所有基于内容的判断都得跟着错。先把编码改成 UTF-8再重新获取字段然后逐个检查类型日期字段务必显式写成 yyyy-MM-dd HH:mm:ss 格式。双击“表输出”点“新建”配置数据库连接。连接类型选 MySQL主机填 localhost端口 3306数据库名 etl_test用户名和密码按实际填。配置完后点“测试”确认连接成功再继续。表名填 user_data如果表还不存在可以先用下面的 SQL 手动建出来CREATE TABLE IF NOT EXISTS user_data ( id INT PRIMARY KEY, name VARCHAR(50), created_at DATETIME );这里提醒一个默认行为表输出步骤默认是“追加写”不会清空目标表。只有勾选了“清空表”选项它才会在每次运行前先 TRUNCATE。很多人在重复测试时发现数据翻倍原因就是这个选项没勾不是 PDI 有 bug。点工具栏的“运行”按钮观察下方日志窗口。重点看每个步骤的输入行数和输出行数如果两者不一致说明有行在中途被丢弃。日志里的红色 ERROR 可以直接双击Spoon 会跳转到出问题的步骤不用自己猜。3.3 数据库连接与驱动MySQL 8 为什么连不上PDI 7.1 自带的 MySQL 驱动是 Connector/J 5.x 的老版本它和 MySQL 8.0 的认证协议不兼容。你配置连接时选 MySQL测试时大概率报 ClassNotFoundException 或者 “Access denied for user” 之类后者的迷惑性很强容易让人以为密码错了其实是驱动太旧。正确的做法是手动下载 mysql-connector-java-8.0.23.jar 或兼容的 8.x 驱动放进>ls -la /opt/etl/data-integration/lib/mysql-connector-java*.jar参数说明文件名前的通配符能匹配 5.x 和 8.x 两种驱动。如果你同时放了两个版本的 jarPDI 会优先加载先扫描到的那个旧版覆盖新版连接依然失败。处理办法是只保留一个 8.x 驱动把旧版删掉或移到 lib 外的备份目录。这个“多个版本驱动并存”的坑我前后踩了两次才记住。连接字符串里的参数也值得看一眼MySQL 8 建议加 useSSLfalse 和 serverTimezoneAsia/Shanghai前者避免 SSL 握手噪音后者解决驱动读取服务器时区不一致的问题这两个参数在 PDI 的连接配置里的“选项”页签下填填完点测试成功后再进入下一步。4. 变量传参与命令行跑批把 Kettle 脱离图形界面干活Spoon 适合开发调试生产环境里你还得靠命令行。这章把变量参数化和两个核心命令讲透。4.1 变量与参数用 ${变量名} 替换硬编码路径开发时直接写死路径没问题但同一套转换换环境跑就麻烦。PDI 的变量机制很简单在任意输入框里写 ${变量名}运行时就会替换成实际值。例如 CSV 文件输入的文件路径写成 ${INPUT_FILE}数据库连接的主机名写成 ${DB_HOST}端口写成 ${DB_PORT}。在 Spoon 里右键转换选择“转换属性 - 参数”页签可以给变量定义默认值。这个默认值是兜底逻辑命令行传入参数时用传入值没传时用默认值。生产环境我习惯把默认值留空强制调用方显式传参这样漏传参数的情况会直接在日志里暴露出来而不是悄无声息地读了一个错误的默认路径。4.2 pan.sh 和 kitchen.sh命令行执行的两个入口pan.sh 用于执行转换文件kitchen.sh 用于执行作业文件。两者的参数风格一致最常用的是 -file 和 -param。cd /opt/etl/data-integration ./pan.sh -file/opt/etl/jobs/load_user_data.ktr \ -param:INPUT_FILE/opt/etl/data/user_data.csv \ -param:DB_HOST192.168.1.10 \ -level:Basic /opt/etl/logs/load_user_data.log 21参数说明-file 后面跟 .ktr 文件的绝对路径相对路径容易因为当前工作目录不同而找不到文件-param: 以键值对形式传参变量名和值中间用等号连接-level:Basic 是日志级别可选 Error、Minimal、Basic、Detailed、Debug、Rowlevel。日常排查用 Basic看整体行数就够要追踪具体某一行的数据变换才用 Rowlevel日志会放大到每行记录生产环境慎开。最后的21把标准错误也重定向到同一个日志文件不然报错信息会直接漏到终端里日志文件里什么都看不到。作业的执行方式几乎一样./kitchen.sh -file/opt/etl/jobs/daily_etl.kjb \ -param:BASE_DIR/opt/etl \ -level:Basic /opt/etl/logs/daily_etl.log 21kitchen 和 pan 最大的不同在于 -file 指向 .kjb 文件。作业内部会按连线顺序调用各个转换转换自己的参数如果没在作业里配置就要在命令行一层层传进去这个依赖关系要提前理清不然作业里第一个转换就失败。4.3 日志级别与退出码怎么确认这次跑成功了命令行执行完不能只看有没有报错文字还要看退出码。Linux 下可以用 $? 拿到上一个命令的退出码0 代表成功非 0 代表失败。./pan.sh -file/opt/etl/jobs/load_user_data.ktr -level:Minimal echo exit code: $?如果退出码是 0但日志里有 WARNING一般不影响结果如果退出码非 0去日志里搜 ERROR 关键字定位到具体步骤。注意一个细节kitchen.sh 执行作业时即使某个内嵌转换失败只要作业里配置了“忽略错误继续”最终退出码仍然可能是 0。所以判断一次跑批是否成功最可靠的口径是退出码为 0 且日志里目标步骤的输出行数符合预期。5. 避坑指南从启动到跑批最常见的五个翻车现场这一章整理了我在真实环境里遇到最多的五个问题全部按“现象 - 原因 - 解决”展开方便你直接对照排查。5.1 先给一张问题速查表现象关键报错根源Spoon 启动不了无窗口libwebkitgtk 相关系统缺少旧版 WebKit 依赖MySQL 8 测试失败ClassNotFoundException驱动版本太旧CSV 中文乱码显示为问号或方块编码没选 UTF-8转换跑到一半卡死OutOfMemoryError堆内存配置过小命令行找不到文件FileNotFoundException工作目录与文件路径不匹配表格只能定位方向具体处理看下面几条。5.2 现象一双击 spoon.sh 没反应窗口根本不出现现象Linux 服务器上执行 ./spoon.sh终端没有任何错误输出或者刷一段日志后进程结束图形界面始终不出现。原因PDI 7.1 的 SWT 图形组件依赖旧版 WebKit 库Ubuntu 20.04、Debian 10 以及更新的系统默认仓库里已经没有这个库导致界面初始化失败但异常信息又不够明显。解决优先确认系统里是否缺少 libwebkitgtk 相关依赖ldd /opt/etl/data-integration/libswt/linux/x86_64/libswt-webkit-gtk-*.so输出里如果出现 “not found”就说明缺库。解决方式是安装 libwebkitgtk-1.0-0 或 libwebkitgtk-3.0-0旧版仓库里有现成包如果发行版实在装不上就别折腾图形界面了直接用 pan.sh 和 kitchen.sh 跑开发在 Windows 的 Spoon 里做部署在 Linux 上执行。5.3 现象二测试数据库连接报 ClassNotFoundException现象配置好 MySQL 连接点“测试”在日志里看到 java.lang.ClassNotFoundException: com.mysql.jdbc.Driver。原因PDI 7.1 内置的驱动是 5.x连接 MySQL 8 时类名、协议都不匹配。另一个隐藏原因是 lib 目录下同时存在 5.x 和 8.x 两个驱动 jar加载顺序把旧版顶到前面。解决只保留一个 8.x 驱动。删除旧版后重启 Spoon再进连接配置的“选项”页签确认 driver class 被正确识别为 com.mysql.cj.jdbc.Driver。如果还不成功检查 jar 的权限确认当前用户有读取权限。5.4 现象三CSV 里的中文变乱码日期字段全是 null现象从 CSV 读取的数据中文列显示为乱码日期列在预览时空空如也但原始文件打开看明明是正常的中文和日期。原因CSV 输入步骤的默认编码是 GBK源文件实际是 UTF-8 时全部错位日期字段没有显式指定格式PDI 按默认格式解析失败后静默地置为 null。解决在 CSV 输入步骤的“编码”里改成 UTF-8重新获取字段日期字段在“转换”页签里选择类型为 Date格式写 yyyy-MM-dd HH:mm:ss。改完后先点“预览”看前 100 行确认中文和日期都正常再运行。5.5 现象四转换跑到一半内存溢出界面卡死现象小数据量没问题一旦换成百万级数据Spoon 卡死日志里出现 OutOfMemoryError或者长时间没有响应。原因堆内存默认值只有 512m 到 1024m大转换的中间缓存、排序、去重操作把堆塞满JVM 长时间 Full GC。解决按第 2.3 节的方式把 -Xmx 调到物理内存的 50% 以内例如 2G 或 4G。同时检查转换里是否有不必要的“排序记录”和“内存分组”步骤它们是大数据量下的吃内存大户。如果内存确实不够优先拆分转换按天或按表分段处理而不是给 JVM 堆无限加码。5.6 现象五kitchen.sh 执行后报文件找不到或变量没解析现象用 kitchen.sh 执行作业日志里出现 FileNotFoundException提示某个 .ktr 文件找不到或者 SQL 里出现的是 ${TABLE_NAME} 原样没有替换成实际值。原因作业里引用的转换是相对路径当前工作目录不在预期的目录下变量在作业里没有向下传递给转换步骤。解决作业里的“转换”步骤可以指定文件名改成绝对路径例如 /opt/etl/jobs/load_user_data.ktr。变量传递要在作业的“参数”页签里显式配置或者通过命令行的 -param 一层层传进去。命令行传参时变量名前后不要留空格这是最容易忽略的细节。6. 验证与进阶用退出码、日志和定时任务收编这套 ETL环境配好只是开始真正把 7.1 纳入生产需要一套可验证的执行方式和可追溯的日志习惯。6.1 用退出码和日志结构做执行验证我一般会给每个作业固定一套日志命名规则日志文件名包含作业名和日期例如 daily_etl_20250115.log。然后写一个极简的检查脚本跑完作业后先看退出码再 grep 日志里的 ERROR。#!/bin/bash ./kitchen.sh -file/opt/etl/jobs/daily_etl.kjb \ -param:BASE_DIR/opt/etl \ -level:Basic /opt/etl/logs/daily_etl_$(date %Y%m%d).log 21 if [ $? -eq 0 ]; then echo ETL OK else grep -n ERROR /opt/etl/logs/daily_etl_$(date %Y%m%d).log | tail -50 fi参数说明$(date %Y%m%d) 生成当天日期保证日志按天滚动$? 拿到上一条命令的退出码grep -n 配合 tail -50 只输出最后 50 条错误避免日志文件太大刷爆屏幕。任何一次执行失败最多一分钟内就能定位到是哪一步出错。6.2 把命令挂进 cron 或调度平台定一个每天凌晨执行的定时任务用 crontab 是成本最低的方案0 2 * * * /opt/etl/bin/run_daily_etl.sh /opt/etl/logs/cron.log 21注意 cron 环境的 PATH 和 JAVA_HOME 和交互式终端不一样脚本里要显式 export JAVA_HOME否则 java 命令找不到。这一步是调度落地时最容易翻车的地方看起来脚本手动执行没问题一挂 cron 就失败。从那以后我每套 PDI 环境起来后的第一件事就是强制走一遍“最小转换 命令行 退出码验证”的流程确认 pan.sh、驱动、日志三样都正常再往上叠业务逻辑。这样后面踩的坑大多能控制在业务层面而不是环境层面。希望这份踩坑记录能帮到你。本文还有配套的精品资源点击获取

相关新闻

容器演进与云原生下一站:Serverless、WebAssembly与eBPF如何重塑技术栈

容器演进与云原生下一站:Serverless、WebAssembly与eBPF如何重塑技术栈

解读容器的演进:寻找云原生的下一站前阵子我在一个跑了三年的 Kubernetes 生产集群上处理了一桩棘手的深夜故障:一批 Pod 突然集体进入 Pending 状态,新扩容的节点始终注册不上控制面。排查到最后,问题出在一个容器运行时的已知缺…

2026/10/14 19:57:14 阅读更多 →
数据结构选型:从嵌套循环到哈希索引,压测性能提升400倍

数据结构选型:从嵌套循环到哈希索引,压测性能提升400倍

那天的压测数据出来时,我盯着屏幕愣了好一会儿。一个批量对账任务,原执行时长稳定在两分钟上下,改造之后连 300 毫秒都不到,前后差了差不多四百倍。说“几百倍”真不是标题党,是实打实写在压测报告里的数字。更让我感慨…

2026/10/14 20:08:15 阅读更多 →
基于Qt5.8与模板匹配的手写数字识别实现全流程解析

基于Qt5.8与模板匹配的手写数字识别实现全流程解析

简介:基于Qt5.8的手写数字识别工程包,面向希望将图形界面与计算机视觉结合学习的Qt开发者或机器学习初学者,可作为课程设计、入门实战或算法验证样本,帮助快速理解从界面绘制到模型推断的完整流程。工程内提供写字板交互区域&…

2026/10/14 19:57:32 阅读更多 →

最新新闻

双电机项目的学习记录1

双电机项目的学习记录1

cubemx里的配置问题,为什么这样配System Core → RCC → High Speed Clock (HSE) 选 Crystal/Ceramic Resonator所以才这样配置是为了精度更高-----------------------------------------------------------------------------------------------------------------…

2026/10/15 4:04:46 阅读更多 →
page_alloc alloc_pages_exact_noprof

page_alloc alloc_pages_exact_noprof

alloc_pages_exact_noprof() 是 alloc_pages_exact() 的无 profiling 底层实现,核心目标是分配“恰好满足需求”的物理连续内存,而非伙伴系统默认的 2 的幂次页块。设计动机:消除高阶分配的浪费伙伴系统只能按 2^order 个页分配。如果你需要 …

2026/10/15 4:04:46 阅读更多 →
SAP ABAP DDIC Table Type 深度解析,从 Internal Table 类型蓝图到主键、辅助键与 Clean Core

SAP ABAP DDIC Table Type 深度解析,从 Internal Table 类型蓝图到主键、辅助键与 Clean Core

在一个规模稍大的 SAP ABAP 项目里,经常会看到这样的声明。 DATA lt_flights TYPE spfli_key_tab.代码只有一行,但这里其实已经确定了很多东西。lt_flights 的每一行长什么样,它到底是 STANDARD TABLE、SORTED TABLE 还是 HASHED TABLE,哪些字段组成主键,主键是否允许重复…

2026/10/15 4:04:46 阅读更多 →
page_alloc alloc_pages_exact_nid_noprof

page_alloc alloc_pages_exact_nid_noprof

alloc_pages_exact_nid_noprof() 是 alloc_pages_exact() 的 NUMA 节点限定版本,并在 noprof重构中被引入。核心作用与设计动机它的核心目标是:在指定 NUMA 节点上优先分配“恰好满足需求”的物理连续内存。与 alloc_pages_exact_noprof() 的关键区别在于…

2026/10/15 4:04:46 阅读更多 →
为什么很多人的经验无法长期积累?

为什么很多人的经验无法长期积累?

记忆留不住的客观规律很多人觉得经验攒不下来是自己不用心,其实大脑本身就不擅长长期存储高密度的细节信息。认知心理学的追踪数据显示,人对具体场景下的信息细节,72小时后的自然留存率仅为29%,剩下的内容会被大脑自动修剪成模糊的…

2026/10/15 4:04:46 阅读更多 →
Map 中删除一个 key,它的内存会释放么?

Map 中删除一个 key,它的内存会释放么?

在 Go 语言开发中,我们频繁使用内置函数 delete(m, key) 来删除哈希表中的元素。许多开发者直觉上会认为:既然删除了 key,对应的内存就应该被操作系统或 Go 垃圾回收器(GC)回收。然而事实并非如此:调用 del…

2026/10/15 4:03:46 阅读更多 →

日新闻

Docker Compose 容器化部署 ChirpStack LoRaWAN 网络服务器实战

Docker Compose 容器化部署 ChirpStack LoRaWAN 网络服务器实战

1. 为什么选择容器化方式部署 LoRa 网络服务LoRa 物联网项目落地时,网络服务器是整个链路的核心枢纽。它负责接收网关上报的数据包、完成去重与解密、再把有效载荷分发给上层应用。早期大家习惯把网络服务器直接装在物理机上,依赖一堆系统库和特定版本的…

2026/10/15 0:00:46 阅读更多 →
共享LLM服务下的跨模型自动扩缩容:Kubernetes实战与避坑指南

共享LLM服务下的跨模型自动扩缩容:Kubernetes实战与避坑指南

1. 共享推理服务里,扩缩容到底难在哪做过大模型推理服务部署的人,大概都经历过这样的场景:一个团队共用一套推理集群,A 业务跑的是 7B 的小模型,B 业务跑的是 72B 的大模型,C 业务白天流量高、晚上几乎归零…

2026/10/15 0:00:46 阅读更多 →
Systemd 启动阶段根文件系统只读之谜:fstab 与 remount-fs 服务深度解析

Systemd 启动阶段根文件系统只读之谜:fstab 与 remount-fs 服务深度解析

1. 引子:一次内核恐慌引发的追查先从一个真实场景说起。某次我给一台老旧的嵌入式设备折腾系统裁减,为了把启动时间压进两秒以内,我手贱地把一串自认为“没用”的 systemd 服务给 disable 了,其中就包括systemd-remount-fs.servic…

2026/10/15 0:00:46 阅读更多 →

周新闻

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

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

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

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

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

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

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

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

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

2026/10/14 3:29:58 阅读更多 →

月新闻

我发现了一个新思路:用 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/15 0:14:36 阅读更多 →
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/14 22:45:47 阅读更多 →
黑夜航拍船只数据集训练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/14 7:53:34 阅读更多 →