php5.4升php7.3踩坑之路

6年没有更新博客了,近期计划内项目有一些web服务底层基于php7+、mysql5.7+开发的,而服务器的php版本停留在了5.4一直未更新(mysql.5.5),导致环境无法部署,考虑到运行的服务比较关键致使升级的计划一而再被拖延。

这次决定将php5.4和mysql5.5升级至php7.3和mysq5.7做个记录,希望能帮助到其他类似需要升级的人。

先说一下版本情况:

centos6.8,php5.4,mysql5.7

升级php7.3过程比较简单。

1、安装epel源

yum install epel-release

2、加载remirepo的php源(注意:centos7不是用这个源)

rpm -Uvh http://rpms.famillecollet.com/enterprise/remi-release-6.rpm

2、安装php7.3

yum --enablerepo=remi-php73 install php

3、安装主要扩展包

yum --enablerepo=remi-php73 install php-xml php-soap php-xmlrpc php-mbstring php-json php-gd php-mcrypt php-fpm

4、安装完成后,重启php-fpm

kill -USR2 `cat /var/run/php-fpm/php-fpm.pid`

5、以下非必要

yum update

至此,php7.3安装完成,此处我遇到1个关于mysqli扩展的问题,默认php-fpm的配置是加载了mysqli的,但是不知道为什么我查看phpinfo是没有mysqli扩展信息的,后来在php.ini里开启了mysqli扩展才识别了,不知道其他人有没有遇到。

接着就是升级mysql5.4至mysql5.7了。

首先备份数据库,升级MySQL通常不会丢失数据,但保险起见,我们需要做这一步。

这种方式备份的侧重点是库与表,备份文件里面会有use db_name这样的语句,方便于恢复数据时知道要把表创建到哪个数据库。

mysqldump -uroot -p [--no-data] --databases db_name1 db_name2 > /dir/backup.sql;  //--no-data指不备份数据,只备份库与表结构。
mysqldump -u xxx -h xxx -P 3306 -p --all-databases > databases.sql;   // 备份所有库

1、备份完数据库之后,开始卸载旧版本 MySQL

yum remove mysql mysql-*

2、确认mysql是否卸载完全

yum list installed | grep mysql

3、上面的情况是没有未删除部分,如果有的话可通过下面的命令删除:

yum remove mysql-libs

4、查看系统版本

[root@iZbp18bpfv23id1yoiv3f0Z include]# uname -r
2.6.32-754.35.1.el6.x86_64

5、mysql官方源太慢了,这里用第三方源(传送门)

//贴图

6、然后根据自己系统配置选择对应的 rpm 包(我这里下载的是5.7.23),鼠标右键打开复制链接,然后到软件包目录执行下载命令

wget http://mirrors.sohu.com/mysql/MySQL-5.7/mysql-5.7.23-1.el6.x86_64.rpm-bundle.tar

7、解压包

tar -zcvf mysql-5.7.23-1.el6.x86_64.rpm-bundle.tar

8、安装rpm以及相关依赖

yum localinstall mysql-community-common-5.7.23-1.el6.x86_64.rpm
yum localinstall mysql-community-libs-5.7.23-1.el6.x86_64.rpm
yum localinstall mysql-community-client-5.7.23-1.el6.x86_64.rpm
yum localinstall mysql-community-server-5.7.23-1.el6.x86_64.rpm

9、OK安装完成,查看版本

[root@*** include]# mysql -V
mysql  Ver 14.14 Distrib 5.7.23, for Linux (x86_64) using  EditLine wrapper

10、重启mysql

service mysqld start

11、如果重启mysql失败,初始化数据库。

mysqld --initialize

12、基于mysql5.7的安全机制有变更,默认mysql是有密码的,查看默认密码。

[root@******************* include]# grep 'temporary password' /var/log/mysqld.log
2021-03-09T10:52:05.394381Z 1 [Note] A temporary password is generated for root@localhost: *****?4#v
2021-03-09T10:54:04.766642Z 1 [Note] A temporary password is generated for root@localhost: *****zyc6/(
2021-03-09T10:55:15.770123Z 1 [Note] A temporary password is generated for root@localhost: *****Vy!y0!h

13、还是基于安全,默认登录到mysql命令控制台,执行任何有效命令都会提示重新设置密码。

mysql -> select host from mysql.user where User='root';
ERROR 1820 (HY000): You must reset your password using ALTER USER statement before executing this statement.

14、修改密码(5.7的密码验证要求高,密码过于简单会提示错误)

SET PASSWORD FOR 'root'@'localhost' = PASSWORD('123456');

15、密码过于简单报错

ERROR 1819 (HY000): Your password does not satisfy the current policy requirements

16、最后让修改生效执行

flush privileges;

至此,mysql的安装以及配置完成,剩下就是进入控制台 source导入上面备份的数据库就行了。

==================================================我是分割线

踩坑开始:

由于论坛(https://bbs.mudbest.com)是基于discuz7.2开发的,很多函数在php7.3被废弃了甚至会报错,php7.3和mysql5.7升级完成之后,然后一脸懵逼。。论坛挂了。。。无法访问。

现在回过头看discuz7的代码(无法言喻。。),打开php-fpm的运行错误,在php-fpm.conf内添加以下内容,然后打开error_log就可以看到运行的错误信息了

[www]
catch_workers_output = yes

坑整理:
1、set_magic_quotes_runtime 报致命错误。
2、ob_start(‘ob_gzhandler’) 报致命错误。
3、preg_replace 带evel的 报致命错误。
4、php7 session不能传递的解决方案
5、….各种告警(修了70%,剩下30%不想修了,直接改告警登记屏蔽了,哈哈)

关于问题3、4 的解决方式:
1、针对 preg_replace evel替代方案就是将 全站用到 evel的换成preg_replace_callback,来个例子。

$message = preg_replace("/\s?(.+?)[\/code]\s?/ies", "codedisp('')", $message);

改写成

$message = preg_replace_callback(
"/\s?(.+?)[\/code]\s?/is",
function ($matches) {
return codedisp($matches[1]);
},
$message
);

扩展知识:

//适合单一任务
$template = preg_replace_callback( //处理eval
    "/[\n\r\t]*\{eval\s+(.+?)\}[\n\r\t]*/is",
    function ($matches) { return str_replace("\\\"", "\"", preg_replace("/\<\?\=(\\\$.+?)\?\>/s", "\", "<? $matches[1] ?>")); },
    $template
);
 
//需要同一正则处理多个任务时  [推荐]
function stripvtags($expr) {
    $expr = str_replace("\\\"", "\"", preg_replace("/\<\?\=(\\\$.+?)\?\>/s", "\", $expr));
    return $expr;
}
$template = preg_replace_callback( //处理eval
    "/[\n\r\t]*\{eval\s+(.+?)\}[\n\r\t]*/is",
    function ($matches) { return stripvtags("<? $matches[1] ?>"); },
    $template
);
$template = preg_replace_callback( //处理echo
    "/[\n\r\t]*\{echo\s+(.+?)\}[\n\r\t]*/is",
    function ($matches) { return stripvtags("<? echo $matches[1] ?>"); },
    $template
);
 
//与第一种差不多, 只不过是分开写
class Template {
    public function test() {
        $template = preg_replace_callback( //处理eval
            "/[\n\r\t]*\{eval\s+(.+?)\}[\n\r\t]*/is",
            array($this, 'stripvtagsEval'),
            $template
        );
    }
    protected function stripvtagsEval($matches) {
        return str_replace("\\\"", "\"", preg_replace("/\<\?\=(\\\$.+?)\?\>/s", "\", "<? $matches[1] ?>")); 
    }
}

2、session问题只需要将php.ini内的session.use_trans_sid设置为1,并且将存放session的目录权限改为可写入。

session.use_trans_sid=0

改为

session.use_trans_sid=1

至此,从升级配置直至填坑恢复,用了2天,又掉了不少头发,赶紧洗洗睡了。