2026-03-13 15:35:59
今天中午发现服务器磁盘又快满了。按目录顺序排查了一遍,发现是 MySQL 的 binlog 文件占用了大量空间。之前通过 mysql console 设置的 binlog_expire_logs_seconds 参数(限制保持3天)在重启 mysql docker 容器后就失效了。参考前文 设置 MySQL binlog 保存天数,节省服务器硬盘空间。
好在今天的开发任务基本完成,也上线测试通过。所以就有时间来折腾一下 docker 中的 MySQL 配置了。以前是能不动就不动,主要是不太想过多了解 docker 的细节,感觉太浪费生命。但是,在自动化运维上,没搞定一项配置,就能节省以后的重复劳动,还是很有必要的。毕竟 AI 虽然可以写代码,但是我并不敢让 OpenClaw 这类神兽去线上服务器操作,还是得自己来。
首先我问了一下 Gemini,这是她最推荐的方式。即,创建一个自定义的配置文件,并将其挂载到容器中。在宿主机创建一个文件,例如 mysql.cnf:
[mysqld]
binlog_expire_logs_seconds=259200
259200 秒代表 3 天。在 docker-compose.yml 中挂载该文件:
services:
mysql:
image: mysql:8.0
volumes:
- ./mysql.cnf:/etc/mysql/conf.d/mysql.cnf
注:MySQL 会自动读取 /etc/mysql/conf.d/ 目录下所有以 .cnf 结尾的文件。
可以的。即支持挂载单个文件,也支持挂载整个目录。
docker compose exec mysql bash
# ls /etc/mysql/
conf.d
# ls /etc/mysql/conf.d/
容器内 /etc/mysql/conf.d/ 目录存在,但是没有任何配置文件。
查看 /etc/my.cnf 文件内容,确认是否包含以下行:
!includedir /etc/mysql/conf.d/
通常在最后一行。
docker compose up -d mysql
自动停止、删除旧容器,并根据新配置启动新容器。
如果只修改了宿主机上被挂载的文件内容,MySQL 通常需要重启才能读取新配置,但此时你执行 docker restart
执行速度很快,感觉嗖的一下就重启好了。
心惊胆颤地检查了一下网站是否正常,以及配置是否生效,结果一切正常,binlog_expire_logs_seconds 的值也正确了。没用的 docker 知识又增加了😓
2026-03-11 10:33:33
本来不想凑 OpenClaw 这个热闹的,因为我似乎也没有具体的使用场景。但是,突然接到了公司领导的任务,必须在公司内部部署一套 OpenClaw。以便雇佣几个免费的数字员工来好好压榨他们。于是,不得不尝试一下了。我上午安装部署了一套腾讯版本的 OpenClaw,叫 WorkBuddy,感觉还不错,就是不能完成我的某些需求,例如:

于是我就想自己部署一套纯血版的 OpenClaw,看看是否能满足我的需求。再加上我发现 OpenClaw 还可以关联 Github Copilot,使用免费的无限 token 的模型,这个就更有吸引了。
参考 OpenClaw 的官网:
https://openclaw.ai
直接一行命令就能安装。例如,我在 Windows 下,打开 PowerShell,输入:
iwr -useb https://openclaw.ai/install.ps1 | iex
iwr 还是第一次见这个命令。
iwr 命令, 全称为 Invoke-WebRequest,是PowerShell中一个内置命令,它类似于 linux 中的 curl 或 wget 命令
安装完成后,会有一个配置引导:
在 Model/auth provider 选择 Copilot

然后 Copilot auth method 选择 GitHub Copilot (GitHub device login)

这个 device login 跟之前安装 Github copilot CLI 的 device login 是一样的,都是本地生成一个授权码,然后去 github 网站输入授权码就能完成授权。还是非常方便的。但是注意不要在 WSL1 中这样操作(有 bug),在 PowerShell 中是正常的。参考之前整理的文档:无限免费大模型 token, Github Copilot CLI SDK 安装及测试 而且,我猜测,还是需要安装 Github Copilot CLI 的,因为之前 Copilot CLI SDK 也是必须安装 Github Copilot CLI 的。原原因是,OpenClaw 代码大概率是通过 SDK 调用 Copilot CLI 的 server mode 来使用 Copilot 的能力。SDK 负责和 CLI 进行通信,CLI 负责和 Copilot 的后端服务进行通信。流程如下:
OpenClaw
↓
SDK Client
↓ JSON-RPC
Copilot CLI (server mode)
虽然只是个猜测,但是大概率是这样的。
因为 github copilot 中,这两个模型是免费无限量的。我可不想在 openclaw 中使用付费的模型,鬼知道会不会直接导致一个月 300 次的额度浪费完。
我其实不太了解这两个模型的具体区别。问了一下 gemini,他推荐的是 gpt-5-mini。给出的理由是:
OpenClaw 类工具的核心痛点是处理动态网页和反爬措施。GPT-5 mini 在视觉推理(Vision Reasoning)上有专项优化。
虽然分辨不了真假,但是我平时使用 gpt 5 mini 确实体验还不错。没有太大的问题。
我刚开始配置的是飞书,但是我发现怎么也配置不成功,现象是飞书里的机器人不显示聊天输入框。。。可能是哪里配置出了问题吧。算了,我也不想纠结了。于是换企业微信。
用企业微信的原因是,我上午用腾讯版的 OpenClaw,即 WorkBuddy 关联过企业微信机器人,操作要简单很多,而且没有坑。飞书的配置还是太复杂,涉及的权限也多,可能是功能更强大更灵活吧。但是我只需要简单的聊天功能,企业微信就够了。具体配置参考企业微信官方的 OpenClaw 配置文档即可,写的还是非常详细的:
https://open.work.weixin.qq.com/help2/pc/cat?doc_id=21657
哈哈,配置完成后,就能痛快体验 OpenClaw 的能力了。

我感觉,其实还是挺折腾的,如果没有特殊需求,直接使用腾讯版本的 WorkBuddy 就好了。
而且那个内置的免费模型还有联网搜索功能,比自己配置 OpenClaw 折腾半天,还有考虑成本的问题要省心多了。虽然 WorkBuddy 早晚还是要收费的。
2026-03-09 12:00:06
正在开发人事管理系统的入职登记表 word 导出功能,使用 golang 的 “github.com/nguyenthenguyen/docx” 包进行 word 模板替换时(参考前文: golang 对 word docx 文档中的占位符进行替换),遇到了一个诡异的问题。
就是大部分占位符都能正确替换,但有几个占位符却无法替换成功。
我开始以为是代码的问题,检查了半天没有发现问题。
然后,我又怀疑是这个三分库的 bug,可能出了异常,但是没有把 error 返回出来。
但是,感觉也不太可能,毕竟在类似的使用场景下,大部分占位符都能正确替换,说明这个库的基本功能是正常的。
最后,我才想到,可能是 word 模板本身的问题。
问了一下 DeepSeek,也印证了这种猜测。
在 DOCX 的 XML 中,一个段落(
)可能由多个
<w:p>
<w:r><w:t>你</w:t></w:r>
<w:r><w:t>好</w:t></w:r>
</w:p>
此时,golang 代码就没法正确替换
doc.Replace("你好", "Hello", -1)
怎么能看到 word 文件的 XML 结构呢?其实很简单,DOCX 文件本质上是一个 ZIP 压缩包,我们可以直接解压它来查看内部的 XML 文件。
可以看看这个文件夹的目录结构:
> tree
.
├── [Content_Types].xml
├── _rels
├── customXml
│ ├── _rels
│ │ └── item1.xml.rels
│ ├── item1.xml
│ └── itemProps1.xml
├── docProps
│ ├── app.xml
│ ├── core.xml
│ └── custom.xml
└── word
├── _rels
│ ├── document.xml.rels
│ └── header1.xml.rels
├── document.xml
├── endnotes.xml
├── fontTable.xml
├── footnotes.xml
├── header1.xml
├── media
│ └── image1.png
├── settings.xml
├── styles.xml
└── theme
└── theme1.xml
8 directories, 18 files
这个 work 文件的结构真是非常值得学习,看起来就像是一个小型网站模板系统一样,图片和样式都被分离出来了,文档内容在 document.xml 中,样式在 styles.xml 中,图片在 media 文件夹中。
最后再用 zip 打包,只是后缀改成了 docx,真是天才。
Excel 也是类似的,特别是在大数据量下,用了 ZIP 压缩可以大大减少文件大小,相比 csv 文件来说,docx 和 xlsx 的文件大小可以小很多。
如果 Markdown 搞个扩展模式,例如 mdx, 也可以通过类似的方式把图片整合进去,感觉也很棒。
言归正传,我们打开 document.xml 文件,搜索一下正常的占位符文本(例如, 占位符 GT1 可以被正确的替换),会看到确实是没有分割:
<w:r>
<w:rPr>
<w:rFonts w:hint="eastAsia" w:ascii="宋体" w:hAnsi="宋体" w:cs="宋体"/>
<w:bCs/>
<w:sz w:val="21"/>
<w:szCs w:val="21"/>
</w:rPr>
<w:t>GT1</w:t>
</w:r>
而异常的占位符(例如, 占位符 GT2)被分割成了两部分:

<w:r>
<w:rPr>
<w:rFonts w:hint="eastAsia"/>
</w:rPr>
<w:t>GT</w:t>
</w:r>
<w:r>
<w:rPr>
<w:rFonts w:hint="eastAsia"/>
<w:lang w:val="en-US" w:eastAsia="zh-CN"/>
</w:rPr>
<w:t>2</w:t>
</w:r>
这就是为什么 GT1 能被正确替换,而 GT2 却无法替换的原因了。
最简单直接的方法,就是删掉有问题的占位符,然后手动敲一遍。
⚠:千万不要尝试从别处复制黏贴字符串过来,然后修改某个字符。word 的复制黏贴会产生意想不到的格式变化,即便你复制黏贴过来清除格式,再应用格式也不行。一定要手动敲一遍。
我现在才理解为何发票之类的文件,默认都是采用 PDF 或者图片了。Word 的格式调整能浪费你一天时间。
Word 虽然编辑起来方便,但是遇到类似的占位符替换问题,排查起来真的非常麻烦。
不知道 Latex 会不会是更好的选择呢?毕竟它是基于文本的,直接替换字符串就行了,不会有被拆分成多个 run 的问题。
2026-03-05 14:54:11
今天在调研自动生成人事系统的入职文件时,我才知道 PDF 交互式表单字段(AcroForms)这个东东。我以为 PDF 格式就是不能编辑的。。。原来 PDF 是可以包含类似网页 form 表单的,可以直接通过 pdfcpu 命令工具,获取其他库用代码进行自动填充。

使用 pdfcpu 可以检测一个 pdf 文件是否包含交互式表单。并通过命令行填充表单。
go install github.com/pdfcpu/pdfcpu/cmd/pdfcpu@latest
最神奇的是,这个居然给我自动安装上了 go 1.25。我本地的 go 版本总是被迫升级。
go: downloading github.com/pdfcpu/pdfcpu v0.11.1
go: github.com/pdfcpu/[email protected] requires go >= 1.24.0; switching to go1.25.7
go: downloading go1.25.7 (linux/amd64)
go: downloading github.com/hhrutter/pkcs7 v0.2.0
go: downloading github.com/hhrutter/tiff v1.0.2
go: downloading github.com/hhrutter/lzw v1.0.0
go: downloading golang.org/x/image v0.32.0
go: downloading golang.org/x/text v0.30.0
go: downloading github.com/mattn/go-runewidth v0.0.19
go: downloading github.com/clipperhouse/uax29/v2 v2.2.0
可以用官方提供这个 pdf 样例做测试:
https://github.com/pdfcpu/pdfcpu/blob/master/pkg/samples/form/demo/english.pdf
> pdfcpu form list test.pdf
installing user font:
Roboto-Regular
pdfcpu: no form available
同样是输入如下命令:
pdfcpu form list english.pdf
可以看到结果如下图

每个字段有对应的名字。
新建一个 english.json 的文件,内容如下:
{
"header": {
"source": "english.pdf",
"version": "pdfcpu v0.4.1",
"creation": "2023-04-04 20:22:17 CET",
"producer": "pdfcpu v0.4.1"
},
"forms": [
"textfield": [
{
"name": "firstName",
"value": "Horst",
"locked": false
}
],
"datefield": [
{
"name": "dob",
"value": "31.12.1999",
"locked": true
}
],
}
]
}
执行命令:
$ pdfcpu form fill english.pdf english.json tmp.pdf
就能实现自动填充,非常方便
这个我没测试过,不知道是否可行,但是 gemini 说可以使用 LibreOffice Writer (直接导出)
2026-03-04 20:30:33
昨天刚经历了个人小程序不备案就无法打开的噩梦,个人小程序不备案无法访问,报错“该小程序仅支持由小程序开发团队体验,无法访问”。晚上又迎来暴击,提交小程序备案刚过预审,就被封号处理 🥲。前后也就半小时,开发了上百个小程序,还是第一次遇到这种情况。

网上搜索了一下,好多人遇到了同样的问题。而且普遍是,根本没有真实用户访问过的情况下,因为备案完成前,根本没有新用户能打开小程序。那么何来的用户投诉。。。微信审核团队撒谎也不能认真点。。。

没办法,客户着急用。我先临时把小程序的功能改造成网页 H5 版本,先让用户用着。好在客户比较好说话,也没有埋怨我。但是我真是有苦说不出,正月十五过节的晚上,刚家庭聚餐喝了个半晕状态,还要连夜改造小程序为网页版。这还好不是企业版小程序,否则交了 300 大洋还要被封禁,估计客户得跟我翻脸。
在小程序后台,点击申诉按钮,才能看到违规的具体原因。给我的理由是:
违反规则《微信小程序平台运营规范》1.注册提交规范
1. 注册提交规范
1.1 提供给用户可以联络到开发者的链接或电子邮箱等有效联系方式。
1.2 提供给平台联络到开发者的管理员微信号,并保证该微信号真实有效。
1.3 你所提交的微信小程序,不得关联至你不具有完整合法权益或不具备完整授权的网站、应用程序、产品或服务等。
1.4 为保障平台和其他用户的安全、稳定,我们会在你提交微信小程序、运营微信小程序等全过程中,要求你提供相应的材料、进行相应的修改等补充和调整,你应当按照我们的要求协助我们进行审核,否则,将影响审核的结果。
1.5 微信鼓励开发者进行创新,不允许重复注册、提交2个及以上页面、内容、功能相同或同质化严重的微信小程序,以为用户提供多样化服务。同时,请避免注册或提交与已有的微信小程序相同或类似的微信小程序,保障微信小程序之间相互具有区别性和不可替代性,避免给用户造成混淆,影响用户体验,使微信小程序的账号资源得以合理使用。
看了一下这个规范,我感觉唯一可能有问题的是第五条。因为我的这个小程序功能确实是一套界面类似的功能,但是执行逻辑确实各不相同,因为不同版本的处理逻辑是不一样的。这个确实没办法,因为审核人员又不可能去看 js 逻辑代码。这以后就有点难搞了,想一套模版卖多份基本就没有活路了。而且,我提交的这个版本,还是用 AI 把 js 逻辑完全重写了一遍的版本,改动反而是最大的一版。。。我猜测微信应该是有一套自动截屏的系统,把小程序各个界面做截图备份,然后匹配相似度。因为这种判定不太可能是靠审核人员人工判定,大概率是靠系统比对后给出的建议。
同时,也有一个客户给我转发了一个竞品的小程序,我当时还惊叹这么简单的功能为何花那么多精力在界面美化上。我现在想明白了,大概就是为了规避这个恶意注册的问题。其实大体思路:
我感觉这是非常离谱的一个处理方式。因为没人会认真读你的条款。我做了这么多年的小程序开发,也是第一次见。但是,你不能因为一次违规就直接封号,为啥不能先拒绝发布,打回去重新开发修改呢?直接就封号也是真的任性。
2026-03-03 21:59:54
之前个人小程序不备案还能继续使用,只是限制每天的使用人数。今天发现更严格了,不备案,直接没法打开了。如下图:

提示“该小程序仅支持由小程序开发团队体验,无法访问”,看来要跟企业小程序一样的严格了。刚开始,我没意识到是备案的问题,我以为只是刚发布,还没有更新到所有下载节点。登录到小程序后台看,才发现确实是没有备案的原因。

你的小程序还未履行备案手续,发布上线后小程序将无法被搜索,仅限制小程序”成员管理”页中的微信用户调试体验使用,完成备案即可解除限制。真的太恶心了,我都备案了几十个小程序和网站了,每次都得重新来一遍,有这个必要吗?审核部门得多闲,非得反复看我的备案🙄哎,头痛,以后要想节约时间。就得先备案,然后同步开发小程序。主要是担心有的小程序没法过审核,先备案的话还要打回改名。