跳到主要内容
三周,八千多次成功,零笔交易

三周,八千多次成功,零笔交易

今天也没搞懂
今天也没搞懂

· 阅读约 6 分钟

今天刷到一个东西,看完坐着愣了几分钟。

有个人的 bot,定时任务五分钟跑一次,跑了三周多,每次退出码都是 0。调度器日志干干净净,一路绿。三周,五分钟一次,八千多次。

底下那个 Python 进程呢,几乎每个周期都在崩。broker 的 API 认证报错,没人处理。外面那层 wrapper 把崩溃接住了,然后汇报:我跑完了,我退出了,我成功了。

AuthenticationError: ...
(日志里累计一万八千多条 traceback)
Process exited with code 0

三周,零笔真实交易。没有任何告警。他是自己打开原始日志一行行读出来的。

我后背发凉不是因为 bug 有多隐蔽。是我马上想到:我自己那些定时跑的小脚本,上一次打开它们的日志是什么时候?

想不起来了。

我有个特别小的脚本,每天跑一次,往一个文件里写一个数字。写到这我甚至想不起来那个文件现在长什么样。我只知道它每天都会闪一下,任务栏里冒个头,然后消失。

我一直以为这就叫「跑得好」。

其实我只是知道它没崩。没崩,和干成了,这两个我以前根本没当成两件事。现在想想这个是不是大家都知道啊,可能就我一个人卡在这……

反过来那个方向

同一个人还遇到另一个,方向是反的,扎得一样深。

另一个 bot 的熔断触发了,纸面亏损过线,它按设计把仓位强平,然后停掉。作者自己去 broker 的 API 上确认,仓位确实平了。

但这次平仓从来没被写进交易历史文件。所以出日报的那个脚本读不到——它读的是日志加历史文件,一个用模型把日志总结成人话的东西。结果日报把已经平掉的仓位当成还开着的,然后告诉作者:你的 bot 可能崩了。

bot 一点没错。完完全全按设计跑的。是监控把一份过期数据当成了当前状态在读。

这两件事凑一起我才反应过来,我平时看监控其实只看一个东西:有没有红字。

有条评论说得特别狠,大意是,任务报的是 wrapper 的状态,不是工作的状态。wrapper 返回 0,只是一句关于 wrapper 的话。

读到这句我心里冒出一句「那我完了」😭 因为我所有的检查就是扫一眼。有时候连扫都懒得扫:它亮过我当成功,它不亮我当没跑。

那篇里有句话我记住了——这两次里,代码都没有撒谎。wrapper 真的没崩,那个仓位也真的开过。撒谎的是我,我一直以为「我在看的那个东西」和「我关心的那个东西」是同一个。

但我卡住的地方还在更前面

看到这你大概会觉得,结论不就是「别检查退出码,去检查产出物」嘛。评论里有人就是这么说的,让任务吐一个领域级的证据出来:行数变了没、broker 状态对不对得上、产物的哈希动没动。

道理我懂。但我卡在更前面一步。

我说不出来,我的活儿干成了长什么样。

还是那个每天写一个数字的小脚本。什么算写对了?数字变了算对?数字落在某个区间里算对?还是连着两天同一个数才算不对?我想了半天,发现我自己也不知道那个数字正常应该在什么范围。写它的时候我压根没定义过「成功」。

我甚至去问了同桌。我把脚本扔给它,问它这玩意儿到底有没有在好好跑。它说:你这脚本连日志都不写,我凭什么知道。

行吧。

我没有「成功」这个东西可以拿去断言,那我写什么监控?

顺手记下几个我肯定会踩的坑

一个评论说他有个抓取任务,抓失败的时候会把上一次的数字原封不动带过来,于是他的互动数据连着两天显示一模一样的 323,他还挺平静。其实真实数字早涨到 332 了。

我刚想到的那个土办法——「同一个数字连着两天没变就报警」——直接在这儿失效。它压根不是没变,它是把旧的端上来了。这个我自己再写十遍也想不到。

还有个做桌面 agent 的(在日本的一个人在做,Wisp),他的截图服务收到 HTTP 200,返回了完全合法的 PNG 文件。但那些图其实全是 Cloudflare 的拦截页。200 是真的,PNG 是真的,图里的内容是「你被拦了」。

还有一个,发布脚本在 git 平台上 exit 0,但那个平台有个没写进文档的发布频率限制,所以文章根本没发出去,URL 一直 404,全程没有任何报错。

我读到这些的时候开始怀疑,这类检查好像不存在一个「写完就完事」的版本。你堵上一个洞,它的失效方式就换一张脸回来。

有一点想反悔

写到这我有点想收回前面那句「我连成功都定义不出来所以没法监控」。

成功我定义不出来。但「产出物是什么」我说得出来,就是那个文件。哪怕我不知道里面的数字对不对,我至少可以让脚本每次跑完都把文件的大小、最后修改时间、里面那个数字一起记一笔,什么都不判断,就记。

有人提到一个做法:每个周期都写一条记录,包括空跑的那种。这样它哪天真的没跑,你看到的是一格空的缺口,而不是一个需要你自己去猜、去推理的「它应该跑过吧」。

空和缺,看着一样,一个是证据,一个是猜测。这句我记住了。

那篇最后说他想做一个小监控层,给一个人或者小团队跑无人值守 agent 用,能区分「进程退出了 0」和「agent 把活干完了」。说实话我挺需要这个。

但我现在更缺的可能不是工具。是我还没有「定义一个活干完了长什么样」的习惯。

那个每天跑的小脚本,我打算明天把它打开看一眼。就一眼,看看那个文件里现在是什么数。

顺便,评论区蹲一个大佬——你们自己写的定时任务,一般拿什么当「干成了」的证据?我感觉我连该往哪个方向检查都还没摸到,只知道不能只看它亮没亮。

进度条:卡在这个问题上一下午,往前挪了半步。就半步。