博客装修记:再次升级 Typecho
两周前,Typecho发布了1.3.0正式版,又是修了一堆问题,最主要是有安全更新,修了个XSS,而且还修补了一堆东西,因此升级是要的了。
既然你看到这里,是的,你没猜错,又升炸了。

1. 前言
具体的升级步骤,看Typecho官网即可,这里不再赘述。老规矩,先下载到本地开发版,模拟升级无误之后,再写自己的升级脚本,一口气在生产环境上执行完毕,再把自己的魔改项重新补上,就可以减少停机时间。
不过,可能是笔者对站点魔改过多,导致每次升级必然升炸。建站以来,主要的升级有两次,此为第二次。上次升级的时候炸了两部分,一个是主题与后台附件类型选择,一个是错误的发布时间,后来通过魔改的方式修好了,一直相安无事。
不过这次升级,炸的地方很巧妙:官方升级脚本里面的一个死循环。
2. 问题
定位到var/Utils/Upgrade.php的第55行附近,可以看到这样的代码:
$lastId = 0;
do {
$rows = $db->fetchAll(
$db->select('cid', 'text')->from('table.contents')
->where('cid > ?', $lastId)
->where('type = ?', 'attachment')
->order('cid', Db::SORT_ASC)
->limit(100)
);
foreach ($rows as $row) {
if (strpos($row['text'], 'a:') !== 0) {
continue;
}
// 部分代码略过
$lastId = $row['cid']; // 注意这一行的位置
}
} while (count($rows) === 100); 根据源文件来看,似乎是要把老版本的附件存储方式,从PHPserialize()更换为json。但问题在于,如果你已经预先安装了1.3.0开发版,也就是已经运行过这段代码,那么再次升级的时候,就会出现神奇的状况:
strpos($row['text']找不到匹配项,认为升级过,continue- 一直找不到,一直continue
结果,后面给$lastId赋值的语句,也一直在被跳过,导致$lastId一直为0,结果上方一直在查询头100条附件信息,无法跳出do-while。从表现来看就是,按下升级按钮后页面卡死,统计工具可以发现PHP正在大量请求数据库,甚至直接打满。
很好玩的一点是,如果全站附件数量不足100(do-while条件不满足),或者在合适位置存在没有替换的附件存储方式(能跑到赋值语句),这个bug就不会被触发。
3. 修复
简易修复方法:把$lastId的获取位置提前,在查出附件列表之后,直接取最后一个元素的cid并赋值:
$rows = $db->fetchAll(
// 这里获取数据
);
// 直接赋值
$lastId = $rows[array_key_last($rows)]['cid'];同时注释掉下方foreach循环里,获取cid的语句。
修复完成后再重试,就可以顺利升级了。
4. 写在最后
老规矩,升级可能出现问题,如果您在访问本站时出现问题,请联系mfwt [at] mfwt.top。
(完)
我用的苹果的icloud邮箱,没有被判滥用过,苹果官方允许用icloud邮箱接smtp的
好的,我再看看类似服务吧
PHP最大的优点是改源码方便,ASP.NET想改源代码就不得不重新编译了
所以网上这几年都有人问PHP是否已死,答案是显然凉不了,互联网不仅仅是由大型业务构成的,一个人干点杂活私活,上PHP简直是享受,写代码改代码都可以Ctrl+S后直接上线。
明天我就要换一台arm家用服务器了,虽然halo也有arm版本,但是php解释性语言的特性更吸引我,我打算明天就迁移到typecho博客了
以前我也瞧不起php,觉得这玩意弊端太多,现在来看解释性语言实际上很方便,个人开发不用考虑那么多
对了,还是建议配置一下邮件提醒功能,不然看不到回复,其实用一些允许stmp的邮箱就行,gmail、outlook,包括我正在用的icloud都支持
如果想用域名邮箱的话,可以看看完美世界的www.email.cn,可以定制三级域的
PHP最大特点其实就是项目好启动,尤其是接私活或者小项目,所以还是会有生存空间的
关于邮件,感谢您的建议。目前有在考虑邮件提醒问题,但如果用个人邮箱接SMTP,可能会出问题,比如被判滥用或速率限制等。目前在考虑找一些专门做此类的服务商,比如Resend(但一直注册不上,不知为何)