將 Amazon Linux 2023 的 PHP 透過自行建置升級到 CVE-2026-109618 / 109619 的修正版(官方套件尚未釋出前的暫時做法)

前言

2026-10-21 已釋出 PHP 的修正版 8.2.35 / 8.3.36 / 8.4.27 / 8.5.12。這些版本修正了 2 個 critical 等級的漏洞(CVE-2026-109618 與 CVE-2026-109619)。不過,在我撰寫本文時,Amazon Linux 2023(以下簡稱 AL2023)的官方套件庫中,尚未提供修正版套件。

本文介紹的是,直接沿用 AL2023 發行的 SRPM,只把裡面的 PHP 版本升級到上游修正版後重新建置的作法。這個方法有以下優點:

  • 檔案佈局、設定檔、擴充模組的組成都和官方套件一致,可以直接替換
  • 之後如果 AL2023 釋出官方修正版,會可透過 dnf upgrade 自動換回官方版本

適用對象是,在 EC2 上使用 AL2023 官方套件庫的 php8.2 / php8.3 / php8.5 套件的使用者。本文的步驟已在 8.2 / 8.3 / 8.5 上確認過。8.4 尚未驗證。

免責聲明

  • 自行建置的套件不具有 AWS 簽章,也不屬於 AWS 的支援範圍。導入與營運責任請由讀者自行承擔。
  • 這只是官方套件釋出前的暫時措施。ALAS(Amazon Linux Security Center)公開修正版後,請盡快切換回官方套件。
  • 漏洞細節與影響範圍,請務必以 php-src 的官方公告為準,而不是本文摘要。
  • 文章中的指令,都是作者在自己的環境中於 2026-10-21 實際執行確認過的。標註「未驗證」的部分,請先在你的環境中確認後再使用。

漏洞概述

php-src 的 GitHub Security Advisory 於 2026-10-21 13:34 UTC 公開了以下 2 項。詳細內容請務必閱讀連結中的原文。

ID名稱嚴重性概要GHSA-w8hw-w9fx-j79w / CVE-2026-109618RCE via OOM corruptioncriticalPHP 會用 longjmp() 處理記憶體不足(OOM)錯誤。此時,請求用的記憶體可能會以不正確的狀態殘留,並在請求結束處理時被讀取。透過精心構造 multipart 解析,可以在各種限制範圍內觸發 OOM。GHSA-6wmf-4rv5-p3rp / CVE-2026-109619RCE via stale global statecritical工作程序保留的全域狀態會一直指向已釋放的請求記憶體。當同一個工作程序處理後續請求時,就會發生 use-after-free。

根據公告,CVE-2026-109618 具有以下特性:

  • Apache 的 mod_php 會無條件呼叫請求結束處理,因此不論應用程式如何實作都會受影響。
  • PHP-FPM 在一般啟動後也可能受影響。不過,針對 FPM 的完整攻擊尚未被證實。

受影響版本與修正版如下所示(PHP 8 ChangeLog)。

分支受影響版本修正版8.28.2.35 以下8.2.358.38.3.36 以下8.3.368.48.4.27 以下8.4.278.58.5.12 以下8.5.12

各分支的修正都是 1 個 commit,標題為 "Avoid state corruption via bailout"。

分支commit8.531c0ea7d7ff18.33c832b523ee18.201a40e89fbfc

變更規模很大,達到 +11,556 / −1,017 行,並修改了 Zend/zend_alloc.c 等檔案。

AL2023 套件庫現況

在撰稿當下,AL2023 最新套件庫中的版本如下,全部都屬於受影響版本。

套件版本php8.28.2.34-1.amzn2023.0.1php8.38.3.35-1.amzn2023.0.1php8.58.5.11-1.amzn2023.0.1

你在閱讀本文時的狀況,可以用下列指令確認。如果修正版已經釋出,本文的步驟就不需要了。

dnf repoquery -q --releasever=latest --latest-limit=1 \
  --qf '%{name}-%{version}-%{release}' php8.2-cli php8.3-cli php8.5-cli

方針:為什麼要升級 SRPM 的版本

一開始,我嘗試在 AL2023 的 SRPM 上直接加入修正 commit 當作 patch。這樣差異最小,但最後沒有成功。

  • 8.5:修正 commit 依賴於 8.5.11 之後加入的其他變更。--fuzz=0 時,會有 patch 套用失敗的 hunk。
  • 8.2 / 8.3:patch 雖然能套上去,但連結時失敗。

    undefined reference to `php_var_unserialize_set_incomplete_classes_only'
    undefined reference to `php_url_scanner_early_rinit'

    修正 commit 變更了 re2c 的原始碼(.re)。但發行 tarball 中包含的是已生成的 .c,建置時不會重新生成。因此,變更不會反映到已生成的程式碼中。

因此,我改成 把 SRPM 參照的 tarball 換成 php.net 的修正版(php-8.x.y.tar.xz)。修正版 tarball 內包含正確生成的原始碼。AL2023 特有的 patch 群組也可以順利套用到修正版上(後面 %prep 會確認)。

升級版本時,除了漏洞修正之外,也會帶入其他變更。

版號提升漏洞修正以外的變更8.2.34 → 8.2.35、8.3.35 → 8.3.36僅有 CI 與 Windows 相關變更,以及內建 PCRE2 的修正。AL2023 會使用系統的 pcre2 進行建置,因此內建 PCRE2 的修正與你無關8.5.11 → 8.5.12也包含其他上游錯誤修正。請確認 ChangeLog,並在你的應用程式上做實際測試。

前提與環境

建置是在 public.ecr.aws/amazonlinux/amazonlinux:2023 容器內進行。容器架構必須與你要安裝套件的目標主機相同。

目標建置環境(作者使用的環境)Graviton(aarch64)在 Graviton EC2(c7g.4xlarge)上的 Dockerx86_64x86 主機上的 Docker(--platform linux/amd64)也可以在 x86 主機上用 QEMU 模擬建置 arm64,但速度非常慢,不建議。

編譯選項會從 SRPM 與 redhat-rpm-config 繼承,不需要自行指定,與官方建置使用相同選項。

架構主要選項x86_64-march=x86-64-v2 -mtune=genericaarch64-march=armv8.2-a+crypto -mtune=neoverse-n1

包含 %check(測試)的建置時間大約如下:

版本環境時間8.5c7g.4xlarge約 12 分鐘8.3c7g.4xlarge約 9~11 分鐘8.26 核心 Intel 桌機約 14~15 分鐘

建置步驟

以下以 php8.5 為例。若是 8.3 / 8.2,請自行替換版本號。

目標SRPM修正版php8.5php8.5-8.5.11-1.amzn2023.0.18.5.12php8.3php8.3-8.3.35-1.amzn2023.0.18.3.36php8.2php8.2-8.2.34-1.amzn2023.0.18.2.35### 1. 啟動建置用容器

mkdir -p out
docker run -d --name php-rebuild -v "$PWD/out:/out" \
  public.ecr.aws/amazonlinux/amazonlinux:2023 sleep infinity
docker exec -it php-rebuild bash

如果是在 x86 主機上為 x86_64 建置,docker run 請加上 --platform linux/amd64。

後續指令都在容器內執行。

2. 安裝建置工具

dnf install -y dnf-plugins-core rpm-build rpmdevtools
# %prep 會用 gpgv2 驗證 tarball 簽章;gnupg2-minimal 不夠
dnf -y swap gnupg2-minimal gnupg2
useradd -m builder

rpmbuild 不要以 root 執行,請改用一般使用者 builder。

3. 取得 SRPM 並安裝建置依賴

mkdir -p /src && cd /src
dnf download --source php8.5-8.5.11-1.amzn2023.0.1
rpm -K *.src.rpm          # 確認輸出 "digests signatures OK"
dnf builddep -y /src/*.src.rpm
cp /src/*.src.rpm /home/builder/ && chown builder /home/builder/*.src.rpm
su - builder -c 'rpm -ivh --define "_topdir /home/builder/rb" /home/builder/php8.5-*.src.rpm'

4. 【建議】先用未修改的 SRPM 做基準建置

%check 測試中有些項目會依環境而失敗(後文會說明)。為了判斷版本升級後是否新出現失敗測試,你需要一個比較基準。因此,建議在修改 spec 之前先建置一次並保留日誌。

T=/home/builder/rb; S=$(ls $T/SPECS/*.spec)
su - builder -c "rpmbuild --define '_topdir $T' -ba $S" 2>&1 | tee /src/build-baseline.log
grep -A30 'FAILED TEST SUMMARY' /src/build-baseline.log
# 為避免混入發行物,刪除基準建置產生的 RPM
rm -rf $T/RPMS/* $T/SRPMS/*

基準建置產生的 RPM 會輸出到與修正版 RPM 相同的 RPMS/ 目錄。如果不刪除,會讓未修正的 RPM 混進發行物中。

5. 修改 spec 的版本與 Release

T=/home/builder/rb; S=$(ls $T/SPECS/*.spec)
sed -i 's/^%global upver .*/%global upver 8.5.12/' $S
sed -i 's/^Release: .*/Release: 0.1.local%{?dist}/' $S
# 不刪掉的話,Release 末尾會多出 .0.1
sed -i '/^%define _trivial/d; /^%define _buildid/d' $S

0.1.local 這段可以改成你喜歡的字串,但務必要比官方的 1.amzn2023.0.1 小。原因會在「版本命名與切回官方版」說明。

6. 取得並驗證修正版 tarball 與簽章

AL2023 的 spec 中,tarball 是 Source0,簽章(.asc)是 Source21。由於 spectool 同時指定多個 -s 時只會使用最後一個,所以要分開執行。

su - builder -c "cd $T/SOURCES && spectool -g -s 0 $S && spectool -g -s 21 $S"

Source 的編號可能會隨 spec 版本改變。不放心的話,先用 spectool -l $S 確認清單再執行。

接著與 php.net 公布的 sha256 做比對。

echo "08bc2eba2a588654ade1357174aa646b761556c862dda0678345ee29ed481209  $T/SOURCES/php-8.5.12.tar.xz" | sha256sum -c

撰稿當下,php.net 上列出的 tar.xz sha256 如下。

檔案sha256php-8.5.12.tar.xz``08bc2eba2a588654ade1357174aa646b761556c862dda0678345ee29ed481209``php-8.3.36.tar.xz``dd54693aa334c5c4d72e9aee96b082c2473750a18a6c1d105789c93a3b1692fd``php-8.2.35.tar.xz``5737b98601fe5ab1b8c5db0c82ed3158acb9283ed3081ffe2faffb9ac81455e6

不要直接照抄這個表,請以你從 php.net 直接取得的值為準。

curl -s 'https://www.php.net/releases/index.php?json&version=8.5'

輸出中,請使用對應 php-8.5.12.tar.xz 的 sha256 值。

7. 執行 %prep

su - builder -c "rpmbuild --define '_topdir $T' -bp $S"

在 %prep 中會做兩件事:

  • 驗證 SRPM 內附 keyring 所對應的 tarball 簽章
  • 套用 AL2023 自有 patch

只要這裡沒有錯誤,就表示簽章驗證與 patch 套用都成功了。

8. 建置

su - builder -c "rpmbuild --define '_topdir $T' -ba $S" 2>&1 | tee /src/build.log
grep -A30 'FAILED TEST SUMMARY' /src/build.log

9. 將 %check 結果與基準建置比對

這個 spec 會忽略 %check 的結束碼。因此,即使測試失敗,建置本身也可能成功。 請務必檢查 FAILED TEST SUMMARY。

作者在自己的環境中失敗的測試如下,且在版本升級前後結果相同。

版本失敗數失敗的測試8.54個pcre gh11956、openssl ecc_custom_params、opcache preload_006、preload_0118.32個gh11956、ecc_custom_params8.21個gh11956

失敗測試可能會因環境不同而改變,因此請拿步驟 4 取得的基準建置日誌來比對。只要版本升級後沒有新增失敗測試即可。

10. 收集 RPM

cd /out
find $T/RPMS -name '*local*.rpm' ! -name '*debuginfo*' ! -name '*debugsource*' -exec cp {} /out/ \;
sha256sum *.rpm > SHA256SUMS
ls -1

RPM 與 SHA256SUMS 會輸出到主機端的 ./out。

版本命名與切回官方版

用 Release: 0.1.local%{?dist} 建置後,版本會變成 8.5.12-0.1.local.amzn2023。用 rpmdev-vercmp 比較時,順序如下:

8.5.11-1.amzn2023.0.1     (目前的官方版本)
  < 8.5.12-0.1.local.amzn2023   (自行建置)
  < 8.5.12-1.amzn2023.0.1       (未來預期的官方版本)
rpmdev-vercmp 8.5.12-0.1.local.amzn2023 8.5.11-1.amzn2023.0.1
rpmdev-vercmp 8.5.12-0.1.local.amzn2023 8.5.12-1.amzn2023.0.1

從這個順序可以得到以下結論:

  • 它比目前的官方版本更新,因此 dnf upgrade 會安裝自行建置版本。
  • 它比未來的官方版本 8.5.12-1.amzn2023.0.1 舊,因此官方版本釋出後,dnf upgrade 會自動替換回去。

如果 AWS 不升版、而是直接回補修正(例如 8.5.11-1.amzn2023.0.2),那麼自行建置版本會被判定為「較新」。此時 dnf upgrade 不會自動切回官方版。請改用 dnf distro-sync,或重新建立 AMI(參見「切回」)。

在類正式環境中的驗證

不要直接上正式環境,請先在模擬正式主機的容器中驗證。

1. 確認正式環境的狀態

在正式主機上先確認以下項目:

rpm -qa 'php*' | sort                         # 已安裝的 PHP 套件
rpm -q --qf '%{version}\n' system-release      # AL2023 的發行版本(格式為 2023.x.YYYYMMDD)
php -m > /tmp/php-m.before                     # 擴充模組清單(比對用)

2. 建立類正式容器並做快照

基底映像檔請使用與正式主機發行版本相符的標籤。 如果在最新版映像檔中安裝舊 releasever 的 PHP,會發生 openssl 3.5 與 3.0 的衝突而失敗。

<release> 請替換成步驟 1 中確認到的正式主機 system-release 版本。

docker run -it --name prodlike \
  public.ecr.aws/amazonlinux/amazonlinux:<release>.0 bash
# --- 容器內 ---
# 將 releasever 固定成正式環境一致(不要加尾端的 .0)
echo <release> > /etc/dnf/vars/releasever
dnf install -y php8.5-cli php8.5-fpm ...       # 安裝與正式環境 rpm -qa 'php*' 相同的套件
exit
docker commit prodlike prodlike:snapshot

3. 在一次性容器中測試

後續驗證都在由快照啟動的一次性容器中進行,失敗了重建即可。

docker run --rm -it -v "$PWD/out:/rpms" prodlike:snapshot bash

接下來在容器中完整試過下面的「套用」與「切回」步驟。

套用

1. 驗證並安裝 RPM

cd /rpms
sha256sum -c SHA256SUMS

REL=8.5.12-0.1.local.amzn2023
ARCH=$(uname -m)            # aarch64 或 x86_64

# 只選擇與已安裝的 php8.5* 同名的自行建置版本(PECL 擴充套件未重新建置,因此排除)
pkgs=""
for n in $(rpm -qa --qf '%{name}\n' "php8.5*" | grep -v pecl); do
  pkgs="$pkgs ./$n-$REL.$ARCH.rpm"
done
dnf upgrade -y --best --disablerepo='*' $pkgs

dnf upgrade 的每個選項都有其理由:

  • --disablerepo='*':只使用本機 RPM,避免第三方套件庫干擾。
  • --best:必要。 如果不加,dnf 會默默略過無法解決相依性的套件,但仍顯示 Complete!,並以 0 結束碼結束(詳見「踩雷點」)。

如果正式環境中安裝了對應檔案不在 out/ 裡的套件,dnf 會因找不到檔案而停止。這時請比對已建置套件清單與正式環境中的套件。

2. 確認沒有漏裝

# 如果沒有任何輸出,表示全部都已替換成自行建置版本
rpm -qa --qf '%{name}-%{release}\n' 'php8.5*' | grep -v pecl | grep -v local

3. 確認運作正常

作者在更新後檢查了以下項目:

php -v                                  # 應顯示 8.5.12
php -m | diff /tmp/php-m.before -       # 擴充模組清單應與更新前相同
php-fpm -t                              # 確認 FPM 設定有效
rpm -Va 'php*'                          # 除設定檔外不應有差異
find /etc -name '*.rpmnew' -o -name '*.rpmsave'   # 不應有任何輸出

PECL 擴充套件

種類結果AL2023 以套件形式提供的 PECL 擴充套件(php8.5-pecl-igbinary / msgpack / redis6)不需要重新建置。因為在 8.5.x 之間 Zend API 相同,更新後仍可直接使用pecl install 手動安裝的擴充套件作者在 8.2.x 上測試過的擴充套件,更新後也仍可載入其他擴充模組尚未驗證,請用 php -m 的比對結果確認。

重新啟動 php-fpm

spec 裡的 %transfiletriggerin fpm 會在交易結束時執行 systemctl try-restart php-fpm。因此,執行中的 php-fpm 會自動重新啟動。重新啟動的那幾秒內,正在處理的請求可能會中斷。

請確認重新啟動後的 master process 是使用新的 binary。

# 如果輸出中不含 "(deleted)",就表示正在使用新的 binary
readlink /proc/$(systemctl show -p MainPID --value php-fpm)/exe

常駐的 PHP CLI 程序

由 cron 啟動的長時間工作、queue worker 等常駐 PHP CLI 程序,會一直使用舊 binary,直到你重新啟動它們為止,請自行重啟。

踩雷點

--best 不加時,相依性有問題的套件會被默默略過

如果執行 dnf upgrade 時不加 --best,它會顯示以下訊息並略過套件:

Skipping packages with broken dependencies

但最後仍會顯示 Complete!,結束碼也是 0。也就是說,從腳本執行時看起來像是成功了。請務必加上 --best,並在套用後確認 grep -v local 的結果。

舊版 AL2023 發行版上,php8.2-sodium 的相依性無法解決

在安裝了 libsodium 1.0.18 的舊版 AL2023 發行版上,如果主機使用 php8.2,就會發生相依性錯誤。

libsodium自建版 php8.2-sodium 所需libsodium.so.26舊主機上安裝的libsodium 1.0.18(libsodium.so.23)2023.11 之後的發行版已經內含 1.0.19。

解法是從最新版套件庫取得 libsodium 1.0.19,並在同一個交易中安裝。先確認是否還有其他套件依賴舊版 libsodium。若除了 php8.2-sodium 之外還有其他套件出現,也要確認那些套件是否能在 libsodium 1.0.19 上正常運作。

rpm -q --whatrequires 'libsodium.so.23()(64bit)'

在建置環境(最新版 AL2023 容器)中取得它。

dnf download --arch x86_64 libsodium-1.0.19-5.amzn2023

在目標主機上,與 PHP 套件一起傳入。

dnf upgrade -y --best --disablerepo='*' $pkgs ./libsodium-1.0.19-5.amzn2023.x86_64.rpm

驗證用基底映像檔版本與正式環境不同

如同「在類正式環境中的驗證」所說,如果在最新版映像檔中安裝舊 releasever 的 PHP,會發生 openssl 3.5 與 3.0 衝突。基底映像檔的標籤必須與正式環境的發行版一致。寫入 /etc/dnf/vars/releasever 的值,請去掉標籤尾端的 .0。

gnupg2-minimal 會讓 %prep 失敗

在 %prep 中,tarball 簽章是用 gpgv2 驗證的。容器內預設安裝的 gnupg2-minimal 沒有 gpgv2,因此會失敗。請用 dnf -y swap gnupg2-minimal gnupg2 替換。

spectool -s 指定多個時,只會使用最後一個

像 spectool -g -s 0 -s 21 這樣寫時,最後只會抓到最後一個來源。請逐一執行。

_trivial / _buildid 會讓 Release 尾端多出字串

AL2023 的 spec 中有 %define _trivial 與 %define _buildid。如果保留它們,Release 尾端會多出 .0.1。想要得到預期的版本,請刪除這兩行。

基準建置的 RPM 會混入發行物

基準建置的 RPM 會輸出到與修正版相同的 RPMS/ 目錄。請在建置修正版前刪除它們。

%check 失敗時,建置仍可能成功

因為 spec 忽略 %check 的結束碼,所以即使測試失敗,建置也可能成功。請檢查 FAILED TEST SUMMARY,並與基準建置比對。

切回

dnf distro-sync -y 'php8.5*'

這個步驟已在類正式容器中確認過。

  • 執行後,會回到你主機所固定 releasever 對應的官方版本。
  • 套件組成會與套用前相同。

如果舊版 php8.2 主機也一併更換了 libsodium,那就要一起切回。

dnf distro-sync -y 'php8.2*' libsodium

切回後,會回到有漏洞的版本。

部署到多台主機與 AMI

以下是一般性的部署範例。

  • 已確認: 在 EC2 Image Builder(AL2023 / arm64)中,透過 S3Download 取得 RPM,再以 dnf upgrade --best --disablerepo='*' 進行替換,並檢查 Release 與 PHP_VERSION 的流程,在 8.5.12 與 8.3.36 都有通過。
  • 未驗證: 文章中的指令與元件定義,已移除作者環境的特定內容並重新整理過;未以原樣直接執行。請依你的環境調整並先驗證。

把 RPM 放到 S3

將 RPM 與 SHA256SUMS 放到 S3。

aws s3 cp out/ s3://<your-bucket>/php-rebuild/8.5.12-0.1.local/ --recursive

讓執行個體取得檔案的方法有兩種:

  • 替執行個體角色加權限:授予該 prefix 的 s3:GetObject 權限。若加密方式是 SSE-S3,就不需要 KMS 權限。
  • 使用預簽名 URL:產生效期較短的連結。

用 SSM Run Command 逐台套用

從 staging 環境開始,一台一台套用。加上 --max-concurrency 1 --max-errors 0 後,只要有一台失敗就會停止。

aws ssm send-command \
  --document-name AWS-RunShellScript \
  --targets 'Key=tag:<your-tag-key>,Values=<your-tag-value>' \
  --max-concurrency 1 --max-errors 0 \
  --parameters 'commands=["bash /path/to/apply-php-rebuild.sh"]'

apply-php-rebuild.sh 的內容,就是把「套用」步驟寫成腳本:從 S3 下載、sha256sum -c、dnf upgrade --best --disablerepo='*'、檢查是否漏裝、確認 readlink 等。

燒錄到 AMI

只更新運行中的執行個體還不夠。Auto Scaling 新起的執行個體仍會從有漏洞的 AMI 啟動。請把 RPM 也燒錄進 AMI,並更新 Launch Template。

如果你在 CloudFormation 中,將 Launch Template 的 ImageId 設成 SSM 參數型別(AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>),那麼即使只把 SSM 的值改成新的 AMI ID,Launch Template 仍可能指向舊 AMI。因為 SSM 值只會在建立或更新 stack 時被解析,所以在 AMI 燒錄完成後,請再更新一次 stack,讓 Launch Template 套用變更。如果 ASG 有 UpdatePolicy(例如 AutoScalingRollingUpdate),也要注意這次 stack 更新會觸發執行個體替換。

在 EC2 Image Builder 中,可以用以下類似的 component 來實作:

  • 透過 S3Download 步驟取得 RPM
  • 透過 ExecuteBash 步驟執行相同的 dnf upgrade --best --disablerepo='*'
  • 檢查所有 PHP 套件都已換成自己的 Release,且 PHP_VERSION 是修正版
name: php-rebuild-upgrade
schemaVersion: 1.0
phases:
  - name: build
    steps:
      - name: Download
        action: S3Download
        inputs:
          - source: s3://<your-bucket>/php-rebuild/8.5.12-0.1.local/*
            destination: /tmp/php-rebuild/
      - name: Upgrade
        action: ExecuteBash
        inputs:
          commands:
            - |
              set -euo pipefail
              cd /tmp/php-rebuild
              sha256sum -c SHA256SUMS
              REL=8.5.12-0.1.local.amzn2023
              ARCH=$(uname -m)
              pkgs=""
              for n in $(rpm -qa --qf '%{name}\n' "php8.5*" | grep -v pecl); do
                pkgs="$pkgs ./$n-$REL.$ARCH.rpm"
              done
              dnf upgrade -y --best --disablerepo='*' $pkgs
              # 若仍有未替換成自行建置版本的套件,就讓流程失敗
              if rpm -qa --qf '%{name}-%{release}\n' 'php8.5*' | grep -v pecl | grep -v local; then
                echo "some php packages were not upgraded" >&2
                exit 1
              fi
              if [ "$(php -r 'echo PHP_VERSION;')" != "8.5.12" ]; then
                echo "unexpected PHP_VERSION" >&2
                exit 1
              fi

在 bash 中,對命令使用 ! 否定時,即使該命令失敗,set -e 也不會觸發。舉例來說,! rpm -qa ... | grep -v local 這種寫法,在檢查失敗時不一定會讓腳本停止。請把檢查寫成 if ...; then exit 1; fi 的形式。

在 set -o pipefail 下,如果寫成 php -m | grep -qi 'Zend OPcache',即使擴充模組已載入,也可能判定失敗。因為 grep -q 一旦找到相符內容就會停止讀取,這會讓仍在輸出的 php 因 SIGPIPE 異常結束,而 pipefail 會把這視為整個管線失敗。

作者的環境中就發生過這種情況:前一個 php -v 明明顯示 with Zend OPcache,後續檢查卻誤判成「OPcache 沒有載入」。輸出越大越容易發生,有時在本機測試又不容易重現。請先把輸出存入變數,再進行檢查。

mods=$(php -m)
if ! grep -qi 'Zend OPcache' <<<"$mods"; then
  echo "Zend OPcache is not loaded" >&2
  exit 1
fi

像 grep -v 這種會把輸入讀到底的命令,就不會有這個問題。head -1 也會因為和 grep -q 類似的原因而避免使用。

官方版釋出後

當 ALAS 公開修正版套件後,就切換回官方版本。

  1. 官方版本的 Release 比自行建置版本高,因此一般 dnf upgrade 就會自動替換。
  2. 從 AMI 建置流程中移除安裝自行建置 RPM 的步驟。
  3. 確認沒有殘留 local 的 Release。
dnf upgrade -y 'php8.5*'
# 如果沒有任何輸出,就表示已切回官方版本
rpm -qa --qf '%{name}-%{version}-%{release}\n' 'php*' | grep local

如果官方修正不是升版,而是以 backport 方式釋出,那麼 dnf upgrade 不會自動替換。請參考「版本命名與切回官方版」中的說明,改用 dnf distro-sync。

參考連結


原文出處:https://qiita.com/amu-kuroneko/items/46f00fbe8b5bac009c1c


精選技術文章翻譯,幫助開發者持續吸收新知。

共有 0 則留言


精選技術文章翻譯,幫助開發者持續吸收新知。
🏆 本月排行榜
🥇
站長阿川
📝9   💬1  
316
🥈
mike
1
評分標準:發文×10 + 留言×3 + 獲讚×5 + 點讚×1 + 瀏覽數÷10
本數據每小時更新一次
📢 贊助商廣告 · 我要刊登