将 EC2 升级至 PHP8 和 Laravel9 版本

首先

我整理了有关如何将AWS EC2服务器上的PHP和Laravel升级到最新版本的方法。

环境的翻譯選項如下:

– 环境
– 周围的条件 de
– 自然条件

(Note: Chinese translations can vary depending on the context in which the word “environment” is used.)

目前环境

    • Amazon Linux 2

 

    • PHP 7.2.8

 

    • Laravel 5.7.9

 

    • nginx 1.12.2

 

    composer 1.10.15 (なくても可)

更新后

    • Amazon Linux 2

 

    • PHP 8.0.16

 

    • Laravel 9.5.1

 

    • nginx 1.20.0

 

    composer 2.2.7

PHP版本更新

由于PHP版本为7.2,我们将进行升级至PHP8版本。

在升级PHP版本之前,请将/etc/php.ini文件复制到本地作备份。
升级后,/etc/php.ini文件将被重写为默认设置。
$ php -v
PHP 7.2.8

要更改PHP版本,需要先卸载所有PHP包,然后启用PHP8。

// パッケージアップデート
$ sudo yum update -y

// PHPのパッケージをすべてアンインストール
$ sudo yum -y remove php-*

// amazon-linux-extrasをアップデート
$ sudo yum update -y amazon-linux-extras

// amazon-linux-extrasで使用中のパッケージと使えるパッケージを確認
$ amazon-linux-extras

// php7.2を無効化
$ sudo amazon-linux-extras disable php7.2

// PHP8.0を有効化
$ sudo amazon-linux-extras enable php8.0

// PHP8.0をインストール
sudo amazon-linux-extras install -y php8.0

// インストールするパッケージの案内があったので、表示されたコマンドを実行
$ sudo yum clean metadata && sudo yum install -y php-cli php-pdo php-fpm php-mysqlnd

// webサーバーを再起動します。(apacheの場合)
$ sudo systemctl restart httpd.service
$ sudo systemctl restart php-fpm.service

// webサーバーを再起動します。(nginxの場合)
$ sudo systemctl restart nginx
$ sudo systemctl restart php-fpm

$ php -v
PHP 8.0.16

我已经可以将PHP版本升级到PHP8了。

PHP模块

在PHP版本升级后,可能会出现PHP模块消失的情况,因此在升级之前要检查模块。
作为检查的内容,有rpm -qa|grep php和php -m这两个。
这次以假设升级后php-mbstring消失为例,描述重新安装的方法。
我认为在Laravel中,php-mbstring是必需的。

$ rpm -qa|grep php
php-mbstring-7.2.8-3.amzn2.0.2.x86_64
などなど

$ php -m
[PHP Modules]
mbstring
$ rpm -qa|grep php
//php-mbstringなし

$ php -m
[PHP Modules]
//php-mbstringなし

使用以下命令安装php-mbstring。
用以下命令来安装php-mbstring。

$ sudo yum install -y php-mbstring

$ rpm -qa|grep php
php-mbstring-8.0.16-1.amzn2.x86_64.rpm

$ php -m
[PHP Modules]
mbstring

//再起動を忘れずに
$ sudo nginx -s reload
$ sudo systemctl restart php-fpm

我成功安装了php-mbstring。

修改php.ini文件

我已经对以下内容进行了修正。

$ sudo vim /etc/php.ini
- expose_php = On
+ expose_php = Off

# 下記は、お好きに
max_execution_time = 30
upload_max_filesize = 64M
post_max_size = 128M
memory_limit = -1
error_reporting = E_ALL
display_errors = off
display_startup_errors = off
log_errors = on
default_charset = UTF-8

date.timezone = Asia/Tokyo

升级nginx版本

与PHP类似,我们需要先卸载所有的包,然后再启用最新版本的nginx。

在升级nginx之前,请事先将/etc/nginx/nginx.conf文件复制到本地。
升级后,/etc/nginx/nginx.conf文件将被默认覆盖。
$ nginx -v
nginx version: nginx/1.12.2

$ rpm -qa|grep nginx
nginx-all-modules-1.12.2-2.amzn2.0.2.noarch
nginx-mod-mail-1.12.2-2.amzn2.0.2.x86_64
nginx-mod-stream-1.12.2-2.amzn2.0.2.x86_64
nginx-1.12.2-2.amzn2.0.2.x86_64
nginx-mod-http-xslt-filter-1.12.2-2.amzn2.0.2.x86_64
nginx-mod-http-perl-1.12.2-2.amzn2.0.2.x86_64
nginx-filesystem-1.12.2-2.amzn2.0.2.noarch
nginx-mod-http-image-filter-1.12.2-2.amzn2.0.2.x86_64
nginx-mod-http-geoip-1.12.2-2.amzn2.0.2.x86_64

$ sudo yum -y remove nginx-mod*

$ sudo amazon-linux-extras disable nginx1.12
$ sudo amazon-linux-extras install nginx1

$ rpm -qa|grep nginx
nginx-1.20.0-2.amzn2.0.4.x86_64
nginx-filesystem-1.20.0-2.amzn2.0.4.noarch

$ rpm -qa|grep nginx
nginx-filesystem-1.22.0-1.amzn2.0.1.noarch
nginx-core-1.22.0-1.amzn2.0.1.x86_64
nginx-1.22.0-1.amzn2.0.1.x86_64

$ nginx -v
nginx version: nginx/1.20.0

// nginx.confファイルを修正します。
$ sudo vim /etc/nginx/nginx.conf

//設定ファイルのチェック
$ sudo nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

// webサーバーを再起動します。(nginxの場合)
$ sudo systemctl restart nginx
$ sudo systemctl restart php-fpm

如果需要该模块,也可以使用以下命令进行安装。

然而,在我的情况下出现了错误。

// nginx-modをインストール
$ sudo yum -y install nginx-mod*

$ rpm -qa|grep nginx
nginx-mod-http-xslt-filter-1.20.0-2.amzn2.0.4.x86_64
nginx-mod-http-geoip-1.20.0-2.amzn2.0.4.x86_64
nginx-mod-mail-1.20.0-2.amzn2.0.4.x86_64
nginx-mod-stream-1.20.0-2.amzn2.0.4.x86_64
nginx-filesystem-1.20.0-2.amzn2.0.4.noarch
nginx-mod-http-image-filter-1.20.0-2.amzn2.0.4.x86_64
nginx-1.20.0-2.amzn2.0.4.x86_64
nginx-mod-http-perl-1.20.0-2.amzn2.0.4.x86_64

$ sudo nginx -t
nginx: [emerg] module "/usr/lib64/nginx/modules/ngx_http_geoip_module.so" version 1020000 instead of 1022000 in /usr/share/nginx/modules/mod-http-geoip.conf:1
nginx: configuration file /etc/nginx/nginx.conf test failed

这是对应方法。因此,上述模块没有安装。

 

nginx.conf的配置文件

需要修改nginx.conf文件,特别是由于server内部默认值的原因,必须恢复到原始状态。
请务必修改以下的server_name、root、location(3行)。

    server {
        listen       80;
        listen       [::]:80;
        server_name  example.com;
        root         /usr/share/nginx/html;
        include /etc/nginx/default.d/*.conf;

        location / {
             try_files $uri $uri/ /index.php?$query_string;
        }

作为参考,Laravel的文档中提供了一个nginx.conf的示例。无需复制。

 

順便提一下,对于我的情况来说,我的nginx.conf文件经过最简配置后变成了以下设置。

user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;

# Load dynamic modules. See /usr/share/doc/nginx/README.dynamic.
include /usr/share/nginx/modules/*.conf;

events {
    worker_connections 1024;
}

http {
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile            on;
    tcp_nopush          on;
    tcp_nodelay         on;
    keepalive_timeout   65;
    types_hash_max_size 4096;

    include             /etc/nginx/mime.types;
    default_type        application/octet-stream;

    # Load modular configuration files from the /etc/nginx/conf.d directory.
    # See http://nginx.org/en/docs/ngx_core_module.html#include
    # for more information.
    include /etc/nginx/conf.d/*.conf;

    server {
        listen       80;
	    server_name example.com;
        root         /var/www/html/public;
        include /etc/nginx/default.d/*.conf;

        location / {
                try_files $uri $uri/ /index.php?$query_string;
        }
    }
}

由于nginx.conf默认在conf配置文件中有两处包含(include)的设置,所以这里也会提及这两个文件的内容。

    • include /etc/nginx/conf.d/*.conf;

 

    include /etc/nginx/default.d/*.conf;
# PHP-FPM FastCGI server
# network or unix domain socket configuration

upstream php-fpm {
        server unix:/run/php-fpm/www.sock;
}
# pass the PHP scripts to FastCGI server
#
# See conf.d/php-fpm.conf for socket configuration
#
index index.php index.html index.htm;

location ~ \.(php|phar)(/.*)?$ {
    fastcgi_split_path_info ^(.+\.(?:php|phar))(/.*)$;

    fastcgi_intercept_errors on;
    fastcgi_index  index.php;
    include        fastcgi_params;
    fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
    fastcgi_param  PATH_INFO $fastcgi_path_info;
    fastcgi_pass   php-fpm;
}

明白了,因为index index.php index.html index.htm等内容在/etc/nginx/default.d/php.conf文件中已经有所记录,所以不需要再在nginx.conf文件中重复记录。

修改php-fpm的配置文件。

由于php-fpm的配置文件被默认覆盖,需要对其进行修正。

$ sudo vim /etc/php-fpm.d/www.conf
- user = apache
- group = apache
- ;listen.owner = nobody
- ;listen.group = nobody
- ;listen.mode = 0660

+ user = nginx
+ group = nginx
+ listen.owner = nginx
+ listen.group = nginx
+ listen.mode = 0660

重启

$ sudo systemctl restart nginx
$ sudo systemctl restart php-fpm

作曲家升级

如果没有安装composer

请按照这篇文章的参考进行安装最新版本。

 

$ composer -V
Composer version 2.2.9 2022-03-15 22:13:37

如果已安装composer

// 現在のバージョン
$ composer -V
Composer version 2.1.9

// パーミッションエラーでバージョンアップデートできない
$ composer self-update
Upgrading to version 2.2.7 (stable channel).
                                                                                                   
  [Composer\Downloader\FilesystemException]                                                            
  Filesystem exception:                                                                                
  Composer update failed: "/usr/local/bin/composer" could not be written.                              
  rename(/home/ec2-user/.cache/composer/composer-temp.phar,/usr/local/bin/composer): Permission denied

$ ls -la /usr/local/bin
-rwxr-xr-x 1 ec2-user ec2-user 2268732 10月 12 18:07 /usr/local/bin

// パーミッションを変更
$ sudo chmod 0777 /usr/local/bin

$ composer self-update
Upgrading to version 2.2.7 (stable channel).
   
Use composer self-update --rollback to return to version 2.1.9

$ composer -V
Composer version 2.2.9 2022-03-15 22:13:37

// パーミッションを元に戻す
$ sudo chmod 0755 /usr/local/bin/

Laravel的版本升级

Laravel将从5系升级到9系。

首先,需要更新依赖包。
这次需要将版本从5系升级到9系,需要修改composer.json文件。

$ php artisan --version
Laravel Framework 5.7.9

$ vim composer.json

在Laravel的文档中,记录了必要的更新信息。
如果查看7系,8系和9系,需要进行以下更新。

在以下的东西中,如果原本没有包装盒,就不需要装入。

"php": "^8.0"
"laravel/framework": "^9.0"
"nunomaduro/collision": "^6.1"
"guzzlehttp/guzzle": "^7.0.1"
"laravel/ui": "^3.0"
"phpunit/phpunit": "^9.0"
"laravel/tinker": "^2.0"

此外,如果在composer.json文件中存在facade/ignition,则应进行如下更改。

- "facade/ignition"
+ "spatie/laravel-ignition": "^1.0"

 

如果有Fideloper/Proxy,由于在Laravel 9中无法使用,所以应删除它。

- "fideloper/proxy"

 

而且,如果告诉composer要使用的php版本,它会自动进行匹配,执行以下命令。
顺便说一下,composer应该在laravel项目的根目录中运行(即存在app目录的地方)。

$ composer config platform.php 8.0.16

composer.json 文件被添加了以下内容。

    "config": {
        "platform": {
            "php": "8.0.16"
        },

那么,我们来执行composer update并安装软件包吧。

错误处理1

$ composer update

  Problem 1
    - phpunit/phpunit[9.3.0, ..., 9.5.x-dev] require ext-dom * -> it is missing from your system. Install or enable PHP's dom extension.
    - Root composer.json requires phpunit/phpunit ^9.3 -> satisfiable by phpunit/phpunit[9.3.0, ..., 9.5.x-dev].

看来似乎需要ext-dom。

$ sudo yum -y install php-xml

$ composer update

我们成功地完成了安装步骤。让我们来确认一下版本吧。

错误处理2

$ php artisan -V

PHP Fatal error:  Declaration of App\Exceptions\Handler::report(Exception $exception) must be compatible with Illuminate\Foundation\Exceptions\Handler::report(Throwable $e) in /usr/share/nginx/html/user_html/app/Exceptions/Handler.php on line 35

app/Exceptions/Handler.php の Exception の処理が 6.x から 7.x で変更されているため、修正が必要なようです。

$ vim app/Exceptions/Handler.php

修改

namespace App\Exceptions;

- use Exception;
+ use Throwable;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;

class Handler extends ExceptionHandler
{
    ...
-     public function report(Exception $exception)
+     public function report(Throwable $throwable)
    {
-        parent::report($exception);
+        parent::report($throwable);
    }
    ...
-    public function render($request, Exception $exception)
+    public function render($request, Throwable $throwable)
    {
-        return parent::render($request, $exception);
+        return parent::render($request, $throwable);
    }

错误处理3

$ php artisan -V

In cache.php line 91:
                                         
  Call to undefined function str_slug()  

由于Laravel 6系中删除了框架的辅助函数,因此在配置文件中发生了错误。

 

当你添加laravel/helpers包后,你可以继续像以前一样使用它,所以请添加它。

$ composer require laravel/helpers

错误处理4

出现了以下错误。

$ php artisan --version


   Error

  Undefined constant Illuminate\Http\Request::HEADER_X_FORWARDED_ALL

  at vendor/fideloper/proxy/config/trustedproxy.php:48
     44▕      * - 'HEADER_X_FORWARDED_AWS_ELB' (If you are using AWS Elastic Load Balancer)
     45▕      *
     46▕      * @link https://symfony.com/doc/current/deployment/proxies.html
     47▕      */
  ➜  48▕     'headers' => Illuminate\Http\Request::HEADER_X_FORWARDED_ALL,
     49▕
     50▕ ];
     51▕

如果在Laravel应用程序的运行过程中,出现了以下错误,请检查strage/logs/laravel.log文件。
原因可能是需要更新应用程序的”信任的代理”中间件。请参考下面的文章进行操作。

 

 local.ERROR: Class "Fideloper\Proxy\TrustProxies" not found 
{"exception":"[object] (Error(code: 0)
: Class \"Fideloper\\Proxy\\TrustProxies\" not found at 
/usr/share/nginx/html/xxxxx/app/Http/Middleware/TrustProxies.php:8)
[stacktrace]

我会修正文件。

$ vim app/Http/Middleware/TrustProxies.php

修改

- use Fideloper\Proxy\TrustProxies as Middleware;
+ use Illuminate\Http\Middleware\TrustProxies as Middleware;

- protected $headers = Request::HEADER_X_FORWARDED_ALL;

+ protected $headers =
+   Request::HEADER_X_FORWARDED_FOR |
+   Request::HEADER_X_FORWARDED_HOST |
+   Request::HEADER_X_FORWARDED_PORT |
+   Request::HEADER_X_FORWARDED_PROTO |
+   Request::HEADER_X_FORWARDED_AWS_ELB;

为了预防万一,在应用程序中执行删除fideloper/proxy的依赖关系的命令。

$ composer remove fideloper/proxy

让我们再次确认Laravel的版本。

$ php artisan --version
Laravel Framework 9.5.1

我成功升级到了Laravel9版本!

错误处理5

顺便说一下,如果变成以下版本,我们需要对composer.json进行以下修改。

$ php artisan --version
Laravel Framework 9.x-dev

- "minimum-stability": "dev"
+ "minimum-stability": “stable”
- "prefer-stable": true

 

$ composer update

$ php artisan --version
Laravel Framework 9.5.1

我可以升级版本了!

错误处理6

当使用带有登录功能的Laravel时,以下错误会在storage/logs/laravel.log中输出。

staging.ERROR: Trait "Illuminate\Foundation\Auth\AuthenticatesUsers" not found 
{"exception":"[object] (Symfony\\Component\\ErrorHandler\\Error\\FatalError(code: 0):
 Trait \"Illuminate\\Foundation\\Auth\\AuthenticatesUsers\" not found 
at /var/www/html/app/Http/Controllers/Admin/Auth/LoginController.php:9)

安装Laravel/UI将解决错误。

$ composer require laravel/ui 

错误处理7

在storage/logs/laravel.log中输出了以下错误。

In aws.php line 28:
                                                    
  Class "Aws\Laravel\AwsServiceProvider" not found  
                                                    

Script @php artisan package:discover --ansi handling the post-autoload-dump event returned with error code 1

安装AWS SDK是一个好主意。

$ composer require aws/aws-sdk-php-laravel

如果使用Amazon ElastiCache的Redis。

升级版本后发生以下错误。

local.ERROR: Class "RedisCluster" not found {"exception":"[object] 
(Error(code: 0): Class \"RedisCluster\" not found at

在PHP8中,需要使用pecl工具安装redis。顺便提一下,无法通过yum安装。

$ sudo yum install php-pecl-redis
読み込んだプラグイン:extras_suggestions, langpacks, priorities, update-motd
amzn2-core                                                                                                                                                 | 3.7 kB  00:00:00    
amzn2extra-docker                                                                                                                                          | 3.0 kB  00:00:00    
amzn2extra-nginx1                                                                                                                                          | 3.0 kB  00:00:00    
amzn2extra-php8.0                                                                                                                                          | 3.0 kB  00:00:00    
パッケージ php-pecl-redis は利用できません。
エラー: 何もしません
// peclでインストールしますので、pearをインストールします
$ sudo yum install -y php-pear

// phpredisをインストールすると、ビルドエラーが起きるので、その前にphp-develとgccをインストールします
$ sudo yum install -y gcc
$ sudo yum install -y php-devel

// php.iniに追加
$ sudo su
# echo "extension=redis.so" > /etc/php.d/redis.ini
# exit 

// peclでphpredisをインストールします。3つ聞かれますが、デフォルトでよいので、Enterを押しましょう。
$ sudo pecl install redis

enable igbinary serializer support? [no] :
enable lzf compression support? [no] :
enable zstd compression support? [no] :

$ sudo pecl list | grep redis
redis   5.3.7   stable

// webサーバーを再起動します。(apacheの場合)
$ sudo systemctl restart httpd.service
$ sudo systemctl restart php-fpm.service

// webサーバーを再起動します。(nginxの場合)
$ sudo systemctl restart nginx
$ sudo systemctl restart php-fpm

在进行动作确认时的错误处理方法。

如果在上述措施之后问题仍然无法解决,我们将从以下方面进行错误处理。

    • logの確認

 

    • 設定ファイルの確認

 

    • キャッシュクリア

 

    ファイルとディレクトリの権限

记录确认命令

$ sudo tail -100 storage/logs/laravel.log

$ sudo tail -100 /var/log/php-fpm/www-error.log

// nginxの場合
$ sudo tail -100 /var/log/nginx/access.log
$ sudo tail -100 /var/log/nginx/error.log

// apacheの場合
$ sudo tail -100 /var/log/apache2/access.log
$ sudo tail -100 /var/log/apache2/error.log
もしくは
$ sudo tail -100 /var/log/httpd/access.log
$ sudo tail -100 /var/log/httpd/error.log

确认设置文件

另外,我们需要检查和修正可能引起错误的设置文件。


$ sudo vim .env

$ sudo vim /etc/nginx/nginx.conf 

$ sudo vim /etc/php.ini

$ sudo vim /etc/php-fpm.d/www.conf

// 修正後は、webサーバーを再起動します。
$ sudo systemctl restart nginx
$ sudo systemctl restart php-fpm

清除缓存

由于缓存的原因,可能会导致错误保留不变。

$ php artisan cache:clear
$ php artisan config:clear
$ php artisan route:clear
$ php artisan view:clear

清除缓存错误

由于执行php artisan cache:clear命令时出现了以下错误,我们将进行修复。
错误原因是因为在storage/framework/cache目录下不存在data目录,所以只需要创建该目录即可。

$ php artisan cache:clear
Failed to clear cache. Make sure you have the appropriate permissions.

$ sudo mkdir storage/framework/cache/data
$ touch storage/framework/cache/data/.gitkeep
$ sudo vim storage/framework/cache/.gitignore

设定.gitignore文件以排除data。

/*
!.gitignore
!data
$ php artisan cache:clear
Application cache cleared!

我成功清除了缓存。

文件和目录的权限

Laravel的权限设置可以通过进入Laravel项目目录,并按照以下步骤进行。

$ sudo chown -R nginx:nginx ./
$ sudo find ./ -type d -exec chmod 755 {} +
$ sudo find ./ -type f -exec chmod 664 {} +
$ sudo chmod 777 -R storage bootstrap/cache

假设我们希望通过SFTP连接上传文件到EC2,那么需要为SSH连接的用户授予适当的权限。对于用户名为ec2-user的用户,以下权限是最好的选择。

$ sudo chown -R nginx:ec2-user ./
$ sudo find ./ -type d -exec chmod 775 {} +
$ sudo find ./ -type f -exec chmod 664 {} +
$ sudo chmod 777 -R storage bootstrap/cache

将Laravel的版本从Laravel9降级到Laravel8系

考虑到Laravel 9版本可能需要进行较多的修改,因此可能有些情况下希望改用Laravel 8系列。
只需修改composer.json文件并执行composer update命令即可。

"laravel/framework": "^9.0"      "laravel/framework": "8.83.5"
"nunomaduro/collision": "^6.1"  →    "nunomaduro/collision": "^5.0"
$ composer update

$ php artisan --version
Laravel Framework 8.83.5

引用的文章

 

广告
将在 10 秒后关闭
bannerAds