一台服务器使用FB 10.4已经很长时间了,因为Let’s Encrypt从2019年12月1日开始,ACME v2启用,要求certbot最低版本是0.29.0,
而10.4最高只支持到0.27.1,头脑一发热,就准备升级到11.0,
freebsd-update -r 11.0-RELEASE upgrade
freebsd-update install
shutdown -r now
freebsd-update install
pkg-static install -f pkg
pkg update
pkg upgrade -f
freebsd-update install
...
这么一套组合拳下来,花了好几个小时后,升级完成了.
可是....mysql没有启动.
查看log,发现有如下错误:/usr/local/libexec/mysqld: Undefined symbol "fdatasync"
搜索一通,说是升级到FB 11.1可以解决,那么就继续折腾吧.
可是,这次就报错了: freebsd-update gunzip: (stdin): unexpected end of file
又是一通折腾,最后看到说应该是之前的升级没有弄好,应该freebsd-update rollback,我脑子一抽,居然就执行了这个命令.
看着屏幕上显示删除了xxx,心里就觉得不妙,但此时已经没法中断了.
硬着头皮重启后,ssh却连不上了.心情降到了冰点.深呼吸,喝了口茶定定神,想到云服务器还可以vnc的方式登录,死马当活马医,万幸万幸,连上并登录上去了.
但是,执行freebsd-update -r 11.0-RELEASE upgrade还是报gunzip: (stdin): unexpected end of file,并且提示却缺少一些lib,之前的sshd没有启动,也是提示缺少了一些lib.
走投无路了,这时候,好运气终于开始来了,峰回路转了,我搜到了这个帖子:https://mpc.lists.freebsd.questions.narkive.com/sUJyHY80/problems-with-upgrade
同是天涯沦落人啊,10.3R -> 11.1R -> rollback -> 10.4,哈哈哈哈
回帖的真是高手,膜拜膜拜.
立即开始着手找10.4版的base.txz,国内所有的镜像,最低都是11.2了,最后,在官网上找到了链接.可是,现在ssh已经不能用了,下载了这个怎么传到服务器上呢? 愁啊
哎,凌晨两点了,脑子不好使啊,为了怎么上传base.txz,居然想了半个多小时.最后,还是想到了直接在服务器上:
fetch http://ftp-archive.freebsd.org/pub/FreeBSD-Archive/old-releases/amd64/10.4-RELEASE/base.txz
接下来,就是完全按照帖子来了:
cp base.txz /tmp/
xz -dc base.txz|tar tvf - | egrep 'libldns.so.5|libheimipcc.so.11'
# 或者
xz -dc base.txz|tar tvf - | egrep 'libldns.so.5|libheimipcc.so.11' | egrep -v '^l'
# 确定丢失的lib确实是base.txz包含的.
# 然后
xz -dc base.txz|tar xvf - ./usr/lib/private/libldns.so.5 ./usr/lib/private/libheimipcc.so.11
# 可以看到/tmp/usr/lib/private/下已经解压出了这两个lib
# 因为我的/usr/lib/private下完全没有这两个lib文件,所以备份就省了
cp /tmp/usr/lib/private/libldns.so.5 /usr/lib/private/
cp /tmp/usr/lib/private/libheimipcc.so.11 /usr/lib/private/
然后
service sshd start
没有报错了,用netstat -anp tcp看看,tcp/22端口已经正常监听.用ssh也没有问题了.
因为nginx和mysql还是提示有问题,缺少libssl.so.8这个文件. 然而在base.txz里没有这个lib
事后想来,应该是之前的升级,把nginx和mysql都已经升级到11.0这个版本下的package,所以依赖应该也是11.0这个版本的里.
我想重装这个nginx,可是pkg却提示有问题,一通搜索折腾后,用以下方法解决了pkg的问题:
pkg-static update
pkg-static del -f pkg
pkg
# 根据提示安装pkg
先备份了nginx的配置文件,然后:
pkg upgrade -f nginx
nginx和相关的依赖都被降级了,nginx也没有问题了.
mysql还是不能用,不管了,先冷备份数据目录和配置文件吧.犹豫再三,还是敲下了
pkg upgrade -f mysql57-server
满怀希望的敲下service mysql-server start,然后netstat -anp tcp,可是,tcp/3306端口没有开
what?? 查看log,还是提示缺少libssl.so.8
这不科学啊,pkg info|grep mysql,版本没有变化,也就是说,pkg upgrade -f mysql57-server没有效果.
思来想去,还是先修复client吧:
pkg upgrade -f mysql57-client
这回的终端输出,提示了client正确降级,并且相关的依赖也降级了.
该来的还是要来了,一咬牙一闭眼,颤抖的手敲下了:
pkg del -f mysql57-server
# 嗯,只删除了这个包,没有其它依赖被删除
pkg install mysql57-server
检查了配置文件和数据文件没有被修改后,敲下service mysql-server start,然后netstat -anp tcp,哦也,成功了.
至此,服务器终于恢复了正常,没有耽误使用.
反思&教训:
- 生产服务器除非必要,尽量不要升级,尤其是跨大版本升级;
- 升级后,千万千万不要做rollback,尤其是跨大版本升级;
- 升级之前,一定要做备份,云服务器做快照是一个很方便的方式
因为使用freebsd-update -r升级耗时太久,所以生产服务器的升级方案(设想未经验证):
- 在同区同机房短期购买一台同等配置的云服务器(或许可以差一些),比如按量购买,或者购买一个月;
- 使用最新的镜像初始化服务器,然后升级到最新版本的系统和软件;
- 创建一个快照或者镜像.
- 将生产服务器上的应用与数据,备份/迁移到新的服务器,测试是否正常.数据迁移可以走内网.
- 如果一切正常,那么对于新的服务器,做一个自定义镜像.
- 对于原来的生产服务器做一个快照备份.
- 对于原来的生产服务器,使用自定义镜像初始化.
- 测试生产环境,正常就可以上线了.如果有问题,就恢复之前备份的快照.