将 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版本。
升级后,/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。
升级后,/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
引用的文章