博客装修记:再次升级 Typecho

warning: 这篇文章距离上次修改已过158天,其中的内容可能已经有所变动。

两周前,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

(完)


木头箱子脆脆,但是这样正好

如无特殊声明,本站内容遵循 CC BY-NC-SA 4.0 协议

转载请注明出处并保留作者信息,谢谢!

本站由 搬瓦工VPS 强力驱动

none
最后修改于:2026年02月03日 12:57

已有 6 条评论

  1. 我用的苹果的icloud邮箱,没有被判滥用过,苹果官方允许用icloud邮箱接smtp的

    1. 好的,我再看看类似服务吧

  2. PHP最大的优点是改源码方便,ASP.NET想改源代码就不得不重新编译了

    1. 所以网上这几年都有人问PHP是否已死,答案是显然凉不了,互联网不仅仅是由大型业务构成的,一个人干点杂活私活,上PHP简直是享受,写代码改代码都可以Ctrl+S后直接上线。

      1. 明天我就要换一台arm家用服务器了,虽然halo也有arm版本,但是php解释性语言的特性更吸引我,我打算明天就迁移到typecho博客了
        以前我也瞧不起php,觉得这玩意弊端太多,现在来看解释性语言实际上很方便,个人开发不用考虑那么多
        对了,还是建议配置一下邮件提醒功能,不然看不到回复,其实用一些允许stmp的邮箱就行,gmail、outlook,包括我正在用的icloud都支持
        如果想用域名邮箱的话,可以看看完美世界的www.email.cn,可以定制三级域的

        1. PHP最大特点其实就是项目好启动,尤其是接私活或者小项目,所以还是会有生存空间的

          关于邮件,感谢您的建议。目前有在考虑邮件提醒问题,但如果用个人邮箱接SMTP,可能会出问题,比如被判滥用或速率限制等。目前在考虑找一些专门做此类的服务商,比如Resend(但一直注册不上,不知为何)

添加新评论

提醒:『评论回复邮件提醒』功能正在测试中
评论后,如果站长有回复,会有邮件通知