一、前言
在之前的系列文章中,我写了 LikeShop 的部署、二开和故障排查。这一篇聚焦一个上线后必然面对的问题:版本升级与备份。
先说一个我身边发生的真实事故。一个团队用 LikeShop 跑了半年的商城,官方发了一个安全修复版本。开发同学直接在后台点了"在线更新",更新完成后页面显示正常,但第二天发现部分商品图片全部 404、订单列表报错。排查后发现,在线更新覆盖了 server/public/uploads 目录,导致所有上传的图片被清空了。更麻烦的是,他们没有提前备份数据库,回滚都回不去。
这个事故暴露了两个问题:第一,不知道哪些目录不能被覆盖;第二,没有养成升级前备份的习惯。
LikeShop 的版本升级分为在线更新 和手动更新 两种方式,选择哪种方式取决于系统是否做过二次开发。无论选哪种,备份都是升级流程的第一步,没有备份就不要动升级。这篇文章就把备份策略、两种升级方式的完整步骤和常见问题排查拆开讲清楚。
二、升级前的备份策略
2.1 为什么备份是升级的第一条铁律
官方文档在升级说明中反复强调:备份好整个项目的代码、资源文件、数据库,要保证自己操作失误以后,可以回滚项目。
这句话不是客套。升级过程中可能出现的问题包括:文件覆盖遗漏、数据库结构同步失败、二开代码被覆盖、升级包与当前版本不匹配。任何一个问题出现,如果没有备份,就只能从头重做。
2.2 必须备份的四个对象
| 备份对象 | 说明 | 重要性 |
|---|---|---|
| 数据库 | 所有业务数据 | 最高优先级 |
| server/.env | 环境配置文件(数据库密码、调试开关等) | 最高优先级 |
| server/public/uploads/ | 所有上传文件(商品图片、用户头像等) | 最高优先级 |
| 项目代码 | 整个项目目录(尤其是二开修改的文件) | 高优先级 |
官方文档特别标注:server/.env、server/public/uploads、数据库、是重要文件,不要轻易删除覆盖。
2.3 数据库备份方法
方式一:命令行导出(推荐)
bash
mysqldump -u 用户名 -p 数据库名 \
--single-transaction \
--routines \
--triggers \
--set-gtid-purged=OFF \
> likeshop_backup_$(date +%Y%m%d).sql
--single-transaction 参数可以在不锁表的情况下导出一致性快照,适合生产环境。
方式二:宝塔面板备份
在宝塔的「数据库」菜单中,找到对应数据库,点击「备份」即可。建议同时将备份文件下载到本地,不要只留在服务器上。
2.4 文件备份方法
bash
# 备份 .env 文件
cp server/.env server/.env.backup_$(date +%Y%m%d)
# 备份 uploads 目录
tar -czf uploads_backup_$(date +%Y%m%d).tar.gz server/public/uploads/
# 备份整个项目代码(排除 runtime 和 uploads 以减小体积)
tar -czf project_backup_$(date +%Y%m%d).tar.gz \
--exclude='server/runtime' \
--exclude='server/public/uploads' \
./
如果项目用 Git 管理,务必确认二开代码已经提交到独立分支。官方源码作为上游分支,自己的改动在独立分支上开发,后续同步官方更新时才能处理冲突。
三、升级方式选择:在线更新 vs 手动更新
LikeShop 提供两种升级方式,选择依据是系统是否做过二次开发。
3.1 选择依据
| 场景 | 推荐方式 |
|---|---|
| 系统未做任何二开,使用官方原版代码 | 在线更新 |
| 系统做过二开,修改了核心文件 | 手动更新 |
| 系统做过二开,但只新增了独立文件 | 在线更新(需谨慎) |
官方说明非常明确:系统没有做二次开发,可以直接选择在线更新功能;系统已做二次开发,进行了功能修改,请谨慎选择在线更新功能,推荐以更新包的形式手动更新。
为什么二开系统不能用在线更新? 在线更新会覆盖核心文件,如果你的二开修改了 OrderLogic.php 或 PayLogic.php,更新后这些修改会被官方版本覆盖,功能直接丢失。手动更新允许你有选择地合并文件,保留自己的改动。
3.2 一个必须知道的约束
目前暂不支持跨版本更新。 如果你当前的版本是 1.8.8,想升级到 2.9.0,必须从 1.8.9 开始逐个版本依次升级。官方客服明确回复过:要一个个版本升级。
这意味着升级前需要先确认当前版本号,然后规划好升级路径,逐个版本下载更新包。
四、在线更新的完整步骤
4.1 前置条件:产品授权
在线更新需要先完成产品授权。在个人中心给相应的产品授权,填写产品正在使用服务器域名(SaaS 用平台的),填写服务器的 IP 地址,然后保存。
授权信息中的域名和 IP 必须与实际部署环境一致,否则在线更新会报错。
4.2 操作步骤
第一步:备份。 按照第二节的方法,备份数据库、.env 文件和 uploads 目录。
第二步:进入系统更新页面。 管理后台 → 「系统更新」→ 「一键更新」。
第三步:点击更新。 系统会自动从官方服务器下载更新包并执行更新。更新过程中不要关闭浏览器或刷新页面。
第四步:强制刷新站点。 官方说明:更新成功后需要强制刷新站点 。可以在宝塔中重启 PHP 服务,或者执行 php think clear 清理缓存。
4.3 在线更新常见问题
问题一:老版本更新列表报错。 由于域名变动,更新逻辑文件中的 $base_url 需要修改。文件位置是 server/application/admin/logic/UpgradeLogic.php 或 server/app/admin/logic/system/UpgradeLogic.php,将 $base_url 改为 https://server.likeshop.cn。
问题二:is_dir(): open_basedir restriction in effect 报错。 这是 open_basedir 配置导致的。在更新时可先关闭防跨站,更新完成后再打开 。或者修改 php.ini 中的 open_basedir 路径为站点根目录。
问题三:授权域名和 IP 都正确但仍然报错。 三种可能:站点配置了多个域名,在线更新操作的后台域名不在第一位,需要将此域名设置在 Nginx 的第一位;使用了负载均衡,需要将多个 IP 地址填写到产品授权中;使用了 DCDN(全站加速),需要临时关闭后再更新。
问题四:mkdir Permission denied 报错。 目录权限不足,宝塔默认的网站文件是 www 用户,请设置为 www 用户。另外检查服务端目录名称是否被调整过,比如本来是 xxx/server,被改成了 xxx/servershop,会导致无法更新。
五、手动更新的完整步骤
手动更新是二开系统的推荐方式,核心原则是只覆盖官方文件,保留自己的修改。
5.1 操作步骤
第一步:备份。 同上,备份数据库、.env、uploads 和整个项目代码。
第二步:下载更新包。 从官方渠道下载对应版本的更新包。
第三步:文件覆盖。 这是手动更新的核心步骤。官方说明:项目除了文件 server/.env、目录 server/runtime、server/public/uploads 以外,其他的文件目录全部覆盖掉。
bash
# 解压更新包
unzip likeshop_update_vX.X.X.zip -d /tmp/likeshop_update/
# 覆盖文件(排除 .env、runtime、uploads)
rsync -av --exclude='.env' --exclude='runtime/' --exclude='public/uploads/' \
/tmp/likeshop_update/server/ /www/wwwroot/likeshop/server/
注意 :如果二开修改了核心文件(如 OrderLogic.php),不要直接覆盖这些文件。需要手动对比更新包中的版本和自己修改的版本,合并改动。这是手动更新最耗时但也最安全的部分。
第四步:同步数据库结构。 官方说明:使用工具同步所有表的数据结构。更新包中通常包含 SQL 文件,记录了新增的字段和表。需要在数据库中执行这些 SQL,或者使用数据库对比工具(如 Navicat 的数据同步功能)来同步结构。
第五步:同步指定表的数据。 官方说明:同步 dev_auth、menu_decorate、dev_crontab、ad_position 表的数据,如果找不到表,可以忽略。这几张表存储的是权限节点、装修数据、定时任务配置和广告位数据,直接覆盖更新包中的对应数据即可。
第六步:清理缓存。 执行 php think clear 清理 ThinkPHP 运行时缓存,然后重启 PHP 服务。
5.2 二开代码的合并策略
如果二开修改了核心文件,手动合并时建议采用以下策略:
策略一:对比合并。 用 Beyond Compare 或 VS Code 的 diff 功能,对比更新包中的官方版本和自己修改的版本,逐行合并。重点保留自己的扩展逻辑,同时接纳官方的安全修复和性能优化。
策略二:扩展优先重构。 如果二开代码大量侵入核心文件,建议借升级的机会重构------把扩展逻辑提取到独立的 Logic 或 Service 中,核心文件恢复为接近官方原版的状态。这样下次升级时,核心文件可以直接覆盖,扩展文件不受影响。
六、升级失败的回滚方案
6.1 在线更新失败的回滚
如果在线更新过程中出现错误(如 open_basedir 报错后数据库回滚失败),官方提供了两种处理方案:自行回滚数据库到更新前,再执行更新;或者直接下载服务端代码自行覆盖文件并执行 SQL。
回滚步骤:
bash
# 1. 导入升级前的数据库备份
mysql -u user -p dbname < backup_before_upgrade.sql
# 2. 恢复代码到升级前的版本
# 如果用了 Git:
git checkout <升级前的tag或commit>
# 3. 清理缓存
php think clear
redis-cli FLUSHDB
# 4. 重启 PHP 服务
6.2 手动更新失败的回滚
手动更新如果出现问题,回滚相对简单:把备份的项目代码恢复回去,导入数据库备份,清理缓存即可。这也是手动更新比在线更新更安全的原因之一------每一步都可控。
七、升级检查清单
无论选择哪种升级方式,升级前后都建议按以下清单逐项核对:
| 阶段 | 检查项 | 说明 |
|---|---|---|
| 升级前 | 确认当前版本号 | 记录当前版本,规划升级路径 |
| 升级前 | 备份数据库 | mysqldump 或宝塔面板备份 |
| 升级前 | 备份 .env 文件 | 复制到安全位置 |
| 升级前 | 备份 uploads 目录 | 打包压缩 |
| 升级前 | 提交二开代码到 Git | 确保改动可追溯 |
| 升级中 | 逐个版本升级 | 不支持跨版本更新 |
| 升级中 | 不关闭浏览器 | 在线更新过程中保持页面打开 |
| 升级后 | 清理缓存 | php think clear |
| 升级后 | 强制刷新站点 | 重启 PHP 或 Nginx |
| 升级后 | 验证核心功能 | 下单、支付、后台登录 |
| 升级后 | 检查上传文件 | 确认图片正常显示 |
八、总结
LikeShop 版本升级的核心可以概括为三条线:
备份优先 :数据库、server/.env、server/public/uploads 是三个绝对不能丢的文件。升级前必须完整备份,确保可以回滚。
方式选择:未二开的系统用在线更新,方便快捷;二开的系统用手动更新,只覆盖官方文件,保留自己的修改。无论哪种方式,都不支持跨版本升级,必须逐个版本依次更新。
回滚准备:升级前准备好回滚方案。数据库备份用于回滚数据,代码备份用于回滚文件,Git 分支用于追溯二开改动。
升级不是"点一下按钮"的事,而是一次需要谨慎操作的生产变更。把备份做扎实,把升级路径规划清楚,把回滚方案准备好,才能从容应对升级过程中可能出现的各种问题。