善意提醒

如果您打开本站很慢,布局排版混乱,并且看不到图片,那么可能是因为您还没有掌握用科学的方法上网的本领。

2026-03-15

美式拿铁

早上起来,太太和儿子都出门了。桌上一个马克杯,剩了一口牛奶在里面,显然是儿子没喝完就跑了。儿子继承了我「刘一口」的绰号,并不是什么很光彩的事情。尴尬一笑,煮了一杯美式拿铁,用掉了家中最后一包「太古金黃咖啡調糖」,就着家里最后一片巧克力吐司,吃了早餐。

一杯不甚讲究的美式拿铁

餐桌上,摆放着两台咖啡机。这台 SIEMENS 美式滴漏咖啡机,是太太同事送给她的。说是子女年会抽中的奖品,家里派不上用场,没拆包就送给了太太。她转手让我去「研究研究」,我查了 Google 才知道还需要买滤纸,以及咖啡粉还分各种粗细的研磨等级。

美式咖啡需要中度研磨的咖啡粉。我家其实是有过这种咖啡粉的。2017 年我俩去塞班旅游的时候,作为伴手礼带回来一包 Starbucks 的咖啡粉,大概就是中度研磨的。当时还不太懂,送给内弟夫妻俩。他们更不懂,当速溶咖啡冲泡,结局可想而知。最后反正是被扔掉了。

后来 2019 年再去万鸦老旅游,太太和她闺蜜都买了一些印尼产的咖啡粉带回来。她们看销售是用法压壶制作的咖啡,于是回来以后我们也去买了法压壶。不过这些咖啡粉后来被用得差不多了,再后来由于过期了也只能扔掉了。当时也买了椰子粉,兑咖啡喝,味道还不错,很浓烈。瑞幸的「生椰拿铁」开始流行,已经是后来的事情了。

我们得到这台美式咖啡机,是 2021 年 12 月中旬的事情。买完滤纸和咖啡粉,刚喝上自己煮的美式咖啡没多久,我们就被封在上海家里了。还好春节前我刚巧又买了两包另一种风味的咖啡粉。当时只是想在风味上作一个对比,没想到因此导致家里的咖啡「库存」充足,帮我们顺利撑过了 2022 年那段牛奶无法正常供应的「自愿禁足」时期。

我们家之前都是喝速溶式咖啡的入门级「票友」。相比之下,美式咖啡里面的咖啡因比较多,喝了以后尿比较多,也确实不犯困。不过确切地说,是「就算困也睡不着」。我吃过一两次亏,晚上又不能影响家人,只好无聊地挨到天明,因此后来再也不敢中午以后喝美式咖啡了。

也可能因为年纪大了,对咖啡因的耐受度有所降低。因此我们自己煮的时候,把咖啡粉的量就控制得比较低。家里四包咖啡粉,算了一下,够我们喝到明年。煮完一壶,三人分一分,兑一点奶,加一点糖。如果咖啡量比较多,我也会直接加椰子粉完事。春光那种独立小袋包装的速溶椰子粉,一马克杯的咖啡放下去一包,味道刚刚好。

其时,太太也有不少烘焙的材料囤在家里,主要是图便宜,所以买的时候份量都不小。各种面粉首先是不缺的。当时也刚好进了一批黄油,一共十块,塞在冰箱里(家里有两个冰箱)。其它辅料也塞满了榻榻米下面。因此我们家当时从未因为早餐发过愁。太太甚至做过一些塞了卡士达酱的小面包以及甜甜圈接济过四邻。楼下一位邻居过意不去,专程跑上来用罐装可口可乐来换。可乐并非我家刚需,因此后来又以物易物换了水果蔬菜。

那时候,小区里面也有人自己制作美式咖啡,在群里拿出来卖,价格参照了 Starbucks。我们从来没动过这个心思,当然也没去炫耀我们这方面的状况。太太和我都不是会做生意的人。她做完小面包,剩了两个,想着楼上有个独居的老太太,还主动去敲门送去。老太太耳朵听力很不好,太太几乎是在砸门,她也听不见。还好老人能看微信,后来通过楼内「志愿者」联系上,才把小面包送到人手里。

家中空间不大,以前咖啡机是收在厨房。每次要用的时候,搬出来插电,比较不方便。现在这台美式咖啡机就放在餐桌上。反正家里难得来客人,接个排插,日常使用比较方便一些。

餐桌上还有另一台咖啡机,还套着包装袋,是 2024 年我在公司年会的时候,抽中的德龙意式咖啡机。又过了快一年才启用,做过两次意式咖啡均不太成功,之后再度被「束之高阁」。相比起美式咖啡而言,意式咖啡的操作步骤要更麻烦一些,维修保养的要求也更高一些,因此不太适合早上上班 / 上学的「冲锋期」。早上的时间也是「寸土寸金」,我还想着让儿子养成每天早晨大便的习惯,因此一分钟都耽误不起。

随着儿子渐渐长大,在观察并请教过以后,他也学会了自己煮美式咖啡。不过他这人比较懒,煮完端着杯子就跑了,连咖啡壶都不洗,经常都是我帮他收拾。后来他又退回到喝速溶咖啡的状态,去 HotMax 买一些便宜货,想喝就自己冲一条。我觉得美式咖啡已经够「懒人友好」了,算是我能接受的一个平衡点吧,不过这个平衡点显然不是儿子的。

现在已经不再像上海封城的时候了,牛奶至少是管够,所以早餐恢复到以巴氏鲜奶为主的菜单。我们家都不是咖啡的「铁杆粉丝」,因此美式拿铁我只会在周末的时候偶尔为之,或者在太太需要开夜车的时候做上一杯。不管是 2026 年还是 2027 年,希望将来都不再需要我们「被迫」靠咖啡来解决早餐。愿望能否成真,或许就是某个本该是农民的人一念之间的事情吧。

2026-02-04

CEF的异步CreateBrowser造成的问题及解决方案

图片由 Google Gemini 3 Pro + Nano Banana Pro 生成

公司有个软件,用到了 CEF 浏览器。CEFWebClient 是一个 CEFClient 的子类,作为一个子窗口放在另外一个由我们软件控制生命周期的父窗口中的。这个父窗口的创建,有时候是自动的,而且可能会短期内进行多次。因此,我们遇到了一个问题:如果父窗口太快被「干掉」,那么可能会 Crash。

父窗口的这个行为,当然可以被认为是「不正常」。但首先我的问题是「为什么」。为什么会出现这种事情?

一年前,查这个问题费了我不少时间和精力。本文主要是把相关经验给传承下去,因此接下来我就尽量长话短说了。

CEF 中创建浏览器的方法是先 new 一个 CEFWebClient,放在智能指针里面,然后交给 CefBrowserHost::CreateBrowser() 去创建窗口。这一步许多人都知道,教程和文档上都是这样写的。不太为人所知的细节是:CefBrowserHost::CreateBrowser() 可能是异步的。

这里就要介绍一些上下文了。
跟 Demo 不同,我们的软件,把 multi_threaded_message_loop 设置为 true。几乎是必须如此,因为这个程序并不单纯是个浏览器而已,没法把主线程消息循环让给 CEF。
在多线程模式下,CEF 会有自己的一些线程用来干活。包括创建浏览器窗口这种事情,也是在它的线程中,而不是调用线程或主线程。

因此,CefBrowserHost::CreateBrowser() 是在另一个线程中进行的。这一点我一开始确实没想到,建个窗口而已,谁会想到 CEF 要搞成异步的啊?官方文档也没强调这个事实。这导致调用线程在函数调用返回时,浏览器窗口还没真正创建起来,只是把这个任务给安排了下去而已。如果父窗口在浏览器窗口真正创建前被销毁了,实际创建浏览器窗口的时候就会出问题。

我们的调用线程其实就是主线程,一开始尝试了让主线程等着,但不行。不管是用信号同步,还是用个 while 循环暴力堵住,都会导致死锁。很明显,CefBrowserHost::CreateBrowser() 在子线程中先是作了一些准备工作,然后又用到了主线程,毕竟创建窗口只可能在主线程中进行。可能是一个 SendMessage 类似的操作。我们是直接用了 Spotify 预编译好的 CEF 二进制分发包,并没有从 CEF 源代码从头编译,所以没有往里面深究。总之如果不把主线程空出来,后面的事情没法继续。

简单休眠 20ms 再放行貌似就可以解决问题,似乎是因为工作线程那边的准备工作已经完成了,已经能够正确应对父窗口被销毁这种事情了。但 20ms 时间够不够?谁知道呢。肯定不能靠这种方式在生产环境上运作。最好是有个判断标志可以判断出准备工作做完了没有,但目前 CEF 对我们来说是个黑盒,也没留这个窗口,我们只能想办法去探上一探。

CefBrowserHost::CreateBrowser() 的第二个参数,是个 CefRefPtr 智能指针,具备引用计数。这个引用计数,对调试器是可见的。我盯着看了一阵子,发现只要引用计数上升到一定程度再放行,就没有问题。貌似工作线程在「准备阶段」把这个智能指针挂到了主线程够得着的地方了,以便创建窗口时访问。只要这个操作已经完成,此后即使父窗口被析构,引用计数也不会有被降为 0 的担忧,后面就能正常工作下去。

这个引用计数在cef_base.h里面,class CefRefCount的私有成员,

//
// Class that implements atomic reference counting.
///
class CefRefCount {
 public:
  CefRefCount() : ref_count_(0) {}

  ///
  // Increment the reference count.
  ///
  void AddRef() const { base::AtomicRefCountInc(&ref_count_); }

  ///
  // Decrement the reference count. Returns true if the reference count is 0.
  ///
  bool Release() const { return !base::AtomicRefCountDec(&ref_count_); }

  ///
  // Returns true if the reference count is 1.
  ///
  bool HasOneRef() const { return base::AtomicRefCountIsOne(&ref_count_); }

  ///
  // Returns true if the reference count is at least 1.
  ///
  bool HasAtLeastOneRef() const {
    return !base::AtomicRefCountIsZero(&ref_count_);
  }

 private:
  mutable base::AtomicRefCount ref_count_;
  DISALLOW_COPY_AND_ASSIGN(CefRefCount);
};

还好是在头文件里面,而且只是一个权限问题,因此连重新编译 libcef_dll_wrapper.lib 都不需要。魔改了一下,我们就这样用下去了。

至于引用计数要增加到多少才算是可以放行,我们取了一个经验数据。但这个方案我们一直用得有点担心。最后还是遇到了问题。重现出来一查,就是这个经验数据不再适用了。

正确的解决方案,还是要回到 CEF 的官方机制 OnAfterCreated() 上来。
官方是这样说的:一个 CefBrowser 有没有创建成功,一定要等到 OnAfterCreated() 被调用。不管是要干什么正经事情,还是要「去死」,都得等到它调用了以后。
实际试下来,虽然 OnAfterCreated() 的调用比引用计数「到位」要迟,但的确可以保证不出事情。

所以事情其实没有那么复杂:如果 OnAfterCreated() 还没被调用到,那么就不能关闭父窗口。不能关闭怎么办?先把窗口给 SW_HIDE 了,然后向 CEFWebClient 作个标记。等到 OnAfterCreated() 被调用的时候,再向父窗口发个消息让它自己销毁,调 DestroyWindow() 就行。

经验教训是:一切还得按规矩办。自己想土办法,或许能在某些场合解决问题,但终究不是长治久安之策。
但是,虽然没有看或调试源代码,不过这次也算是刺探了一下 CEF 的一些内部运行机制,也是有好处的。

2026-01-30

冷暖自知

大约一年以前,公司楼下,开了一家咖啡店。
装修貌似从夏天就开始了,进度一直比较慢,磨磨蹭蹭,到 2024 年总算是正式营业了。

不过,说起来是「店」,可能更像是一个柜台。在原本的大堂里面,装修出来了一个吧台的样子,买来咖啡机,找了店员,然后就这样做起了生意来。

说实话,我们从一开始就不太看好。把柜台开在大堂里面,那么客流就比较受限。我们这栋楼又是一栋六层楼的老楼,并没有太多人。大堂也远没有园区里其它更新一些的大楼气派。然而老板招了三个员工,三个小伙子挤在吧台里,一看就知道有危险活不下去。过了一阵子,店员就只剩一个了,老是蹲在大堂门外抽烟,看来生意不太好。

刚开业的时候,推出了一波 2 元买美式的促销「活动」。同事还是很「给面子」,去薅了一杯,觉得太苦,于是往里面加了可乐。多亏了他这种勇于探索的精神,我们都知道了这样做会得到一杯酸啤酒味的东西,以后应该没有人再去尝试了。

咖啡店老板看来还是个爱折腾的人。过了一阵子,灯箱有变化,说是研发了「牛肉面」。我看到了就很疑惑,这都什么跟什么啊?

然而这老板的确是把一楼的一家倒闭掉的服装店(把服装店开在一栋老旧的写字楼里面,有生意才见鬼了)的位置给盘了一半下来,真的开了一家牛肉面馆。我后来上下楼一直闻到很香的味道,知道有面馆,但一直以为是从楼里面进去。直到最近我才知道它的正门开在旁边,通往停车场。

我会知道,因为我看见楼里面的门(其实应该是后门)上贴着东西。

通知书 - 页 1
通知书 - 页 2

老板半年多欠了 10 万的店租和水电费。难怪我有好一阵子没见到咖啡吧开业了。
这下咖啡机什么的估计要被卖掉折现了。可惜了柜台里面那一排排的原料,乳品估计都坏了,苏打水应该还能用吧。

这是另一处地方打出的广告

生意肯定是不好,但店租不能少。不过我估计前面一年半年应该是类似这样免租金的。老板可能也想好了,先干一阵子,没起色就跑,不然沉没成本也太高了。但装修钱还是砸里面了啊,说到底还是不明智。

这年头啊,还是得少创业,多苟着吧。

2026-01-26

两盆冷水敬 AI

我要给 AI 泼两盆冷水。

图片由 Google Gemini 3 Pro + Nano Banana Pro 生成

第一盆是泼给 Vibe Coding 的。

很多鼓吹这个的文章,都认为它将导致大量的 Software Engineer 失业。更有甚者觉得整个软件行业被会颠覆,因为人人都能写代码。

是不是这样,我目前还不想去讨论,毕竟世界一日千里。然而,跟大家说一个常识:「AI 就是世界所有知识的平均数」。

你现在觉得 AI 比你强,那是因为在你问的那些方面,你的知识水平还没到及格线。AI 厉害的地方在于它能低成本地快速补全你欠缺的东西。但是如果你是某个方面的专家,你就会发现 AI 还是离你有一段距离。在真正的专家那边,这段距离不小。

通过 Vibe Coding 或许能快速获得一个「还能用」的软件。这个软件或许能快速解决用户当前的某个需求。如果这个需求很容易描述的话,这个软件也用起来也挺不错。比如写个「俄罗斯方块」游戏之类。不过一旦需求复杂起来,要描述的难度也就急剧上升,系统内部的复杂度大增,出问题的可能性也随之大增。众所周知,软件开发最麻烦的地方,其实是「八二原则」里面那些 80% 用来解决性能以及鲁棒性问题的代码。如果不在这些地方下足工夫,那这种软件,其实无法「交付」,只能自己用用。

在我看来,AI 其实蛮适合解决这类问题的,因为 AI「不嫌麻烦」。前提是人也要不嫌麻烦,不厌其烦地提要求,从各种角度假设,让 AI 检查再检查。如果能有这种意识,已经是一个超出平均水准相当多的「产品」兼「测试」人员了。如果说要被淘汰的 Software Engineer 就是这类既不具备产品意识也缺乏质量意识的人,那我只能说句「活该」。但话说回来,既然是如此的人才,计算机语言真的那么难学,非得绕着走吗?

总之,普通人的不可能三角——高质量、低门槛、易获得——在这里依然起作用。AI 确实缩短了三角形的边长,让平庸的代码产出变得廉价,但它并没有改变三角形的定律:真正的顶级质量,永远不可能通过「一键生成」这种低门槛的方式获得。

第二盆要泼给 AI 写作。

周末看了一些号称完全由AI生成的文章。用到了多个 Agent,互相协作,的确蔚为壮观。
然而,看了以后,给我的感觉就是:没有灵魂。

AI 讲逻辑是很厉害的,说起话来头头是道。我认为,一些科普、分析、说明性质的文章,换句话说,议论文和应用文,是行家里手。略加提示与输入,文笔也不是好不起来,模仿一些文学大家或许都绰绰有余。

但是,它不能给我新的东西。

我不太知道如何形容这种所谓「新的东西」。AI 写的文章,肯定有让我眼前一亮的部分。但是,我想看到的,来自人类自身的体验和感悟,一些鲜活的事例,个人的见闻,没有。如果有,那也是人喂进去的,不算 AI 自己的东西。

我也知道,AI 目前还只能加工,无法去「采风」。这不算它的错,只是它目前的局限之所在。我很期待有一天,它能够有自己的东西,但至少目前还没有。

所以,目前我只能看着这些一篇篇滴水不漏的文章,完全没有阅读的欲望。或许我喜欢的不是这类文章吧,我可能更喜欢随笔一些。「讲道理」没关系,但更要有故事。

我想起了《奇点天空》里面的「节日」,近乎贪婪地索求「故事」,不惜以「丰饶之角」来交换。或许,这就是人类存在的意义吧。

2026-01-15

逻辑的奴隶?这次我把 AI 领进了死胡同

最近有同事问我:为什么公司旧版软件在执行某个特定操作时,屏幕上的一部分 UI 就不动了?

说实话,这套旧代码现在成了公司里的「考古遗迹」。唯一深谙此道的同事已经财务自由,移民香港了。我对这个细节也并不非常清楚,只能去看代码。相关代码错综复杂,看得我眼花缭乱却毫无头绪。

想到最近 Google Gemini 3 Pro 的强劲表现,我索性把代码全扔给了它,开启 Pro 模式进行深度分析。

为了「提高效率」,我在 Prompt 中加入了自己的判断:「我认为是相关的 Windows 消息被过滤了。」在我看来,这再自然不过——既然界面停下了,那逻辑上一定是忽略了导致绘图的消息。我只是找不到过滤逻辑的标志位而已,而这事正适合让 AI 靠「蛮力」深挖。

从逻辑上讲,AI 显然非常「同意」我的判断。它一头扎进了我给出的代码里面,然后得出了一些似是而非的结论。我核对后发现,有些结论可以直接排除,有些则根本不符合事实。这意味着,顺着我的思路走下去,连 AI 也找不到真正的原因。

对话进入了死胡同。而 AI 在这种情况下似乎不知道「退出来」,只是机械地一次又一次给出「可能是……原因」的无效推测。最后我不得不靠调试来自行解决问题。

真正的原因,是那位同事在软件界面上遮挡了一个不进行重绘的透明窗口。

图片由 Google Gemini 3 Pro + Nano Banana Pro 生成

事后复盘:我在这里犯了一个典型的错误——我不该在一开始就说出我目前为止的判断。

我反思,如果当初少说一点,让它自行研究,结果会不会更好?我们一贯以来对于 AI 的使用方法,基本上都是「让它知道得越多越好」。我甚至曾这样建议别人:『别隐瞒,把你知道的东西事无巨细都告诉它,哪怕你认为没用的也要告诉它。』

这个原则本身没错,但前提是:你告诉它的是「事实」,而不是「错误的观点」。

很多人类尚且无法区分「事实」与「观点」,AI 可能就更不知道了。在我看来,我的提问还有改进的空间:

  1. 明确标注信息属性: 在 Prompt 中清晰指出哪些是明确的事实,哪些是模糊的现状,哪些仅代表个人的观点和推测。
  2. 允许 AI 「退后一步」: 对于 AI 而言,这只是在做题。Prompt 越具体,求解范围就越窄。我们不能只是把 AI 领到迷宫门口,然后让它进行探索,却不允许它「爬墙头」。

人类会犯错,然后学到东西。AI 也会。如果 AI 能「对抗」人类的意志,我不知道这是好还是坏?

总之,共同进步吧。

2026-01-13

Internet 好像也没有那么危险嘛

图片由 Google Gemini 3 Pro + Nano Banana Pro 生成

周日晚上,突然接到公司同事的电话,说我手上有一台服务器「被人攻击」,所以机房要把外网 IP 给黑洞 24 小时。

挂了电话之后,想想不对,那台服务器并非生产环境,平时都是内部自己用,要被攻击也轮不到它。

这台服务器,主要都是运维同事在用,我自己了解不多。去年年中,运维同事辞职,我更是早已不负责相关业务。这台服务器有点「三不管」的感觉:登记簿上还挂在我名下,最近没什么空去推进蛮复杂的交接工作,所以还没轮到它;实际管理者没什么能力进行管理,主观意愿上也不想去管;它暂时也没什么多大用处,几乎算是「闲置」状态。

然而,我总觉得自己对它还有「责任」,于是走跳板机从内网连上去又看了看。这一看就让我冒冷汗了。上面居然有个 squid,而且貌似是「向全世界开放」的状态。让 Google Gemini 帮忙统计了一下 access.log,发现晚上出事前一分钟就产生了 3GB 的流量,峰值可能确实把机房设定的阈值给顶破了。所以这应该就是直接原因了。

可是,我不记得自己有在这台机器上搭过 squid,也不记得运维同事搭过。他是个谨慎的人,应该不至于干出这种事情。那是谁干的?

再仔细看,简直大汗淋漓了。还有一个未能投入工作的 OpenVPN,以及一个名叫 proxy 的账号,gid 是 0。完了。什么时候被黑的?!

这个 proxy 账号看起来是 2021 年创建的。日志已经灭失了一大半。我只能根据仅有的一点线索,去拼凑还原当时的情况。

「黑客」看来轻车熟路,一上来就登录了 root 账号,随后创建 proxy,设置 sudo,然后就去安装 squid。

但接下来的情况让我迷惑不解。他光是开防火墙 3128 端口就折腾了半天,安装 squid 时也一时输错成了 apt-get(这台服务器是 CentOS)。装完 squid 设了 allowed_ips,但 conf 中却大手一挥设成 allow all 就走了,OpenVPN 也是安装了一半就放弃了。前面半截太过顺利,后面半截却画风一转,这不对劲。

我们用的密码都是 64 位随机字符串,SSH 端口也开在非标准端口上。如果这台服务器这么容易被攻破,那么我们剩下的服务器也是凶多吉少。剩下的时间,我都在审查和反省所有可能的入侵路径。还是想不明白,当时到底什么情况?最后凌晨两点钟,实在熬不住,洗澡睡觉去了。


第二天到了公司,我按计划去翻邮件,看看有没有可能出事前是弱密码,后来才改成的强密码。结果这一翻,就发现了「真凶」,也算是一场乌龙。

2021 年的时候,当时老板找我要了一台服务器的 root 权限,说是他儿子要用。
他儿子当时参与了我们的一些项目,也算是「实习」吧,后来去英国读书去了。要这台服务器,是说方便参与维护,当时公司里面还真没人来维护那些东西,所以我也就把这台不太重要的服务器给他了。看起来,当天他儿子拿到 root 密码,接着就动手了。

大学生嘛,做事情没顾那么多,也是可以理解的。谁还不知道自己大一的时候是个什么样子呢?估计他当时折腾完以后用过一阵子,然后就把这事给忘了。现在他早已毕业,无论是在当地工作或回国发展,总之应该也用不上这个东西了。这代理就这样一直开放在 Internet 上,不知道有没有人发现,估计没有。虽然日志有限,但看起来 2025 年一整年都没人用过,直到这个周日。大概总算被什么人给扫描到了吧。

这事说起来就是个内部管理问题。这种事情,就算放在现在,我感觉也没法拒绝。老板自己也大概把这事给忘了。只能是吃一堑长一智吧,以后「出借」的东西要加强审计。以及不要认为别人都会好好善后。哪怕他真的会,但有时候也会偷懒啊。

话说回来,貌似 Internet 好像也没有那么危险嘛?一个完全开放的 HTTP 代理,3128 端口也是知名端口,居然存在了快五年才被人第一次发现。或许现在 ProxyHunter 已经没人用了,但是我国政府的扫描器不是一直在巡天么?GFW 果真对外不对内?所以啊,世界还真的是一个大草台班子吗?

2026-01-08

关于明尼苏达 ICE 枪击案的个人评论

看了 BBC 上关于明尼苏达 ICE 枪击案的视频。不同的媒体释出的版本,各位也可以都去 YouTube 上搜一下看看。

https://www.bbc.com/news/videos/cx2ypz4zjvxo

首先说一下个人感觉:纯粹就是谋杀。当然,非要说误杀也行,毕竟动机无法揣测。但肯定是「杀」,不是「自卫」。

被枪击的车辆一开始挡在皮卡前面,然后 ICE 的人走过去要拉车门,已经拉了一两下了。没拉开,显然司机锁了车门。但驾驶位的窗是开着的,我估计双方也是在对骂。从皮卡司机位下车的那个 ICE 显然更激动,虽然副驾驶位的同事有做手势让他 Calm down,但他把手都伸到车窗里了,看最后那一下的动作,感觉要去从内侧开车门。

没人愿意这样被人拉下车,而且此时也没人拿枪指着司机。司机看起来是想要离开,至少是想要摆脱眼前这种局面。如果换成是我的话,被不怀好意的人包围,并且有人开始拉车门,估计也不会愿意呆在原地。

从轮胎的动作看,是一个类似三角调头的操作,往左后方倒车,然后挂 D 挡往右前方前进。右边的车的驾驶侧车门是开着的,司机为了避让,不可能一开始就把方向盘往右打死,这也是很正常的事情。并且,换档的时候,打方向盘只有一只手,操作速度没有那么快。因此方向盘一开始看似只是回正了,但随后也就朝右了。而且总之在开枪者决定开枪的那个时刻,车辆向右拐,避开他的趋势,已经很明显了。

开枪者一开始并未持枪,并且明显可以躲开。但他的选择是拔枪,然后跟着车辆的移动方向去前凑瞄准,随后在即将失去射击角度的那一刹那开枪射击驾驶员。正常人要是为了保命的话,应该是连滚带爬地向后退,至少上身会是向后闪避的状态,双手伸出试图阻挡车辆,而不是想着去掏枪。

开枪的一瞬间,可以看到开枪人的两条腿的站姿

掏枪干什么呢?在那个时候,即使他打死了司机,一枪爆头,如果车辆真的是正对着他撞过去,在那个距离上,他也无法避免被撞。但司机只是在向右转弯,并没有去撞他的企图。开枪者此时甚至已经错开一个身位了。事实上,开完枪后,他也很简单地就躲开了失去控制的车辆。故此,很难让人相信他开枪的目的是为了「自卫」,特别是作为一个「有经验」的 Agent。

我个人感觉他就是想阻止司机离开,本意可能是想击伤司机,没想到一枪毙命。当然也可能是 PTSD 之下发 P 疯了。这些都是可以「辩解」的点。但这改变不了事实:他就是想通过开枪达到自己的某个目的,而那个目的绝对不是「保护自己的生命安全」。

中国大陆在 2007 年也发生过「储户被押钞员一枪爆头」的事件,当时我还写过一篇 Blog。过了这么多年,事情是在越来越好,还是越变越糟,各位心中自有评断。无论如何,这些都是不应该发生的悲剧。牺牲究竟能不能换来一点什么,从前的我,希望有,现在的我,但愿有吧。

2025-12-24

订阅了Google AI Pro

看过一些朋友的推荐,也跟 Google Gemini 一番探讨之后,今天终于下决心订阅了 Google AI Pro。

可以有更多的 Google Gemini 配额了,包括「思考」和「Pro」,后者貌似就最近两天才加上的。以及,更多的 Nano Banana / Nano Banana Pro 图片配额。还可以用 Veo3.1 做视频。免费版的 Deep Research 配额我曾经用满过,所以还真是有必要成为付费用户。

Google 全家桶里面也可以用 Gemini 了。我记得有印象在 Gmail 里面看到过 Gemini 的图标,但今天去找的确找不到了。莫非是当时 Google 放的鱼饵?

另外,对我而言还有一个挺有吸引力的福利:2TB 存储空间。太太的 Google Photos 空间早就满过了,删了一些视频才降下来。我自己也不敢拍太多照片和视频,就怕哪天空间满了出事情。这问题甚至影响到了我的某些旅游的体验,现在不成问题了。

详细介绍见这里,不过我不知道算不算是最新的:https://support.google.com/gemini/answer/16275805

我是选的「包年」方式,因为感觉一旦用上了应该就「回不去了」。
首年 $100,之后每年 $200。包月正常价是 $20,现在也有试用优惠。不知道是不是年底或圣诞节特别搞的活动。反正都要买,不想等几天错过了,就下单了。
我个人是不太在意这些小恩小惠的,何况已经很划算了。

说起来,Google AI Pro 应该是普通中国人最容易「够到」的顶级 AI 品牌的付费服务了。ChatGPT Plus 之前对中国用户想尽办法封锁,还砍单封号来着。直到现在也没见得有多方便,甚至连「安全」都不一定算得上。我曾经形容为「被中美混合双打」,为了用个靠谱的AI也真是难为了。

图片由 Google Gemini 3 Pro + Nano Banana Pro 生成

当然,对于普通人,我一律是劝他们尽量多用 AI,哪怕是国产 AI。
有在用总比没有在用要强。面对熊,你只需要比同伴跑得快就行。

AI 问:那如果是面对狼群呢?

我说:你差不多得了。 

2025-12-22

丢失的 Blogger 铅笔小图标

图片由 Google Gemini 阅读本文后生成,真是厉害

之前在自己折腾 Blogger,大概就是 2023 年或 2024 年把  Blogger 重新翻出来写的时候,一不小心,把每篇 Blog 下面的「铅笔」小图标给整没了。

这个小图标是管理员才能看到的。直接一点就可以进到编辑界面。对于我这种时常在回顾自己文章时发现错别字,需要马上去修改的人而言,真的是很方便。把它弄丢了以后,我每次就得根据文章的标题或标签再去 Blogger 后台找到那篇文章。有时候某些想法只是一瞬间的事情,过了就没了,对于我而言,更可怕的是「过了就忘了」,这也太可怕了!

我一开始还以为是自己之前在编辑主题的时候不小心把它给误删了。但今天想起这事,下决心解决,去看代码的时候,才发现好像不是这么一回事。代码都在里面,但就是不起作用了。

这是原来的代码:

<b:includable id="postQuickEdit" var="post">
  <b:if cond="data:post.editUrl">
    <span expr:class=""item-control " + data:post.adminClass">
      <a expr:href="data:post.editUrl" expr:title="data:top.editPostMsg">
        <img alt="" class="icon-action" height="18" src="https://resources.blogblog.com/img/icon18_edit_allbkg.gif" width="18" />
      </a>
    </span>
  </b:if>
</b:includable>

看到这里我就有点犯嘀咕。cond 明显是条件,该不会是 post.editUrl 没东西吧?
我把 cond 改成一个必定成立的条件,放到页面上一试,还真是。图标出来了,点击没用处,没能跳到编辑页面。问 Google Gemini,它说新一些的主题里面这个图标的确已经被隐藏了。看来 Google 是铁了心要把这个功能干掉了。

我想自己整,但发现真正的编辑页面的 URL 好像有两个 ID 我不知道哪里能拿到。Google Gemini 给出的修改方法语焉不详,而且看起来也没有说到点子上。算了还是求助于传统的 Google 吧。

搜到的第一个贴子是 Google 自己的页面,Blogger 的 Support 论坛:
https://support.google.com/blogger/thread/242102130/editurl-the-url-of-the-edit-form-for-this-article-deleted

里面有提到这位大神,是一个法语的 Blog:
https://bloggercode.orbiona.com/2021/10/faq.html

后面有个英语 Blog 也提到上面那篇:
https://too-clever-by-half.blogspot.com/2022/08/the-case-of-missing-pencil.html

法语对我而言有不少困难,还好有 Google Translate。
我翻到解决方案一节就知道了:看起来那个法语大神给出的就是我想要的东西。
简单地说,把原来的那段代码替换为:

<b:includable id='postQuickEdit' var='post'>
  <!-- /2021/10/faq.html -->
  <b:with value='data:view.isPage ? "blog/page/edit/" : "blog/post/edit/"' var='path'>
    <span expr:class='"item-control " + data:post.adminClass'>
      <a expr:href='data:blog.bloggerUrl path (data:path + data:blog.blogId + "/" + data:post.id)' expr:title='data:top.editPostMsg'>
        <img alt='' class='icon-action' height='18' src='https://resources.blogblog.com/img/icon18_edit_allbkg.gif' width='18'/>
      </a>
    </span>
  </b:with>
</b:includable>

就可以搞定了。

原因据说是 Google 慑于第三方 Cookies 的限制,没法让前台(blogspot.com)和后台(blogger.com)在域名不相同的情况下还能把管理员的登录会话串起来,索性就把整个功能废掉了。

解决方案的原理也很简单:你不让我跳编辑页面,我就自己组 URL。知道 BlogID,也知道 PostID,还有什么做不到的呢?

当然,这里头还有一些诸如「管理员权限的判断」等小东西。按照「八二原则」,真正花时间的往往是在这些事情上。掌握了核心技术,路只走了 20% 而已。这位法语大神甚至已经把「页面」和「博文」的差别也搞定了。我就不折腾了,直接用她的吧。

照例吐槽一下:搜索结果中,简体中文的页面依然是一无所获,繁体中文有两篇讲到了这个事情,其中一篇涉及到了核心问题,不过最完整的解决方案还是法文以及英文的页面。简体中文在世界文化交流领域里面就是一个小角落,不管卖出了多少玩具电动车,都改变不了这个事实。不要再夜郎自大了。

2025-12-16

如果你还认为自己是普通人

我不认为自己是什么「普通人」。就算我哪怕曾经有过这样的想法,但不久前以及现在也不再这样认为了。

如果你还自认为是个「普通人」,那么,最好赶紧跟下面这种人区分清楚。

你可以说「这个人根本不是什么普通人」,也可以声明自己「并不是普通人」。如果你已经了解此事,但仍然还是默不作声,那么这份恶,你就也有一份。

祝你去世

没有人是「普通人」。你是独一无二的,你就是你。