Доведіть оновлення PHP до перемикання, з готовим rollback
Як безпечно перевести застосунок на нову гілку PHP: встановити поруч, перевірити код lint і сканером, простежити, що насправді завантажує трафік, потім перемкнути один сокет.

Більшість оновлень PHP ламаються однаково: нову версію ставлять поверх старої, головна сторінка завантажується, усі розслабляються, і перший адміністратор, який наступного ранку відкриває рідко вживаний екран, отримує білу сторінку. Ось метод, яким ми знаходимо ці проблеми на стенді, до cutover, зі шляхом назад, що займає секунди.
Чому оновлення продовжують щось ламати
Кожна гілка PHP прибирає функції, посилює обробку типів і перетворює старі попередження на фатальні помилки. Застосунок, що виріс за роки, несе шляхи коду, які ніхто давно не виконував: експорт, застарілий платіжний модуль, адміністративний звіт. Smoke-тест публічних сторінок до них ніколи не дійде.
Комерційні застосунки додають другий шар. Файли, захищені енкодером, працюють лише якщо loader для нової гілки PHP підтримує формат, яким їх закодовано, а це властивість кожного файлу, а не маркетингової сторінки застосунку.
Крок перший: встановіть поруч, ніколи поверх
Встановіть цільовий PHP поруч із поточним. На RHEL і його перезбірках software collections від Remi роблять це простим: кожна гілка живе у власному префіксі, зі власним сервісом FPM і сокетом. Створіть пул для сайту на новій версії, ідентичний старому пулу за винятком бінарника і шляху до сокета.
Для відвідувачів поки нічого не змінилося. Обидві версії працюють, а вебсервер досі вказує на старий сокет.
Крок другий: перевірте кожен файл новим бінарником
Найдешевший тест: попросити новий PHP розібрати кожен файл:
NEW_PHP=/path/to/new/php
find /var/www/app -name '*.php' -print0 \
| xargs -0 -n1 -P8 "$NEW_PHP" -l 2>&1 \
| grep -v '^No syntax errors'
Це ловить синтаксис, який нова гілка більше не приймає. Воно не ловить вилучені функції чи змінену поведінку, бо ті падають лише під час виконання. Для цього запустіть статичне сканування сумісності, наприклад PHP_CodeSniffer зі стандартом PHPCompatibility, налаштованим на вашу цільову гілку:
phpcs -p --standard=PHPCompatibility --runtime-set testVersion <target> \
--extensions=php /var/www/app
Очікуйте шуму від бібліотек vendor і мертвого коду. Список є картою, а не вироком.
Крок третій: з’ясуйте, які файли насправді завантажує трафік
Застосунок може містити десятки тисяч файлів PHP, з яких лише частка колись виконується. Ви хочете витратити зусилля на сумісність саме на цю частку, і хочете бути певні, що вона включає шляхи для авторизованих користувачів та адміністраторів.
OPcache уже знає. Після звичайного робочого дня на поточній версії, включно з входами людей і роботою адміністраторів, запитайте його, які скрипти він скомпілював:
<?php
// protect this file: admin network only, and delete it afterwards
$s = opcache_get_status(true);
foreach (array_keys($s['scripts']) as $f) { echo $f, "\n"; }
Збережіть список, порівняйте його з результатами lint і сканування, і проблеми, на які справді натраплять, піднімуться вгору. Файли, що з’являються в скануванні, але ніколи в трасуванні, є кандидатами на видалення, а не на виправлення.
Крок четвертий: прочитайте заголовки закодованих файлів
Для закодованого комерційного програмного забезпечення перевіряйте кожен файл, а не довіряйте банеру сумісності. Закодовані файли несуть текстовий заголовок, що називає енкодер і формат:
grep -rl --include='*.php' 'ionCube Loader' /var/www/app \
| while read -r f; do head -c 400 "$f" | strings | head -3; done | sort | uniq -c
Згрупуйте файли за форматом енкодера, потім підтвердьте, що loader для вашої цільової гілки PHP виконує цей формат. Модуль, закодований роки тому для старої гілки, і є тим файлом, який відмовиться завантажуватися на новій, і краще дізнатися про це із заголовка, ніж від клієнта.
Крок п’ятий: прорепетируйте на новому пулі
Спрямуйте тестове ім’я хоста або власний IP через правило заголовка на новий сокет, поки продуктивна система залишається на старому. Пройдіть шляхи з трасування OPcache, з особливою увагою до тих, куди доходять лише авторизовані користувачі та адміністратори, і стежте за журналом помилок нового пулу, поки це робите:
tail -F /var/log/php-fpm/app-new-error.log | grep -E 'Fatal|Uncaught|Deprecated'
Повідомлення про застарілість сьогодні не є відмовами, але вони є списком для наступного оновлення. Запишіть їх.
Крок шостий: перемкніть один рядок, залиште старий пул працювати
Cutover є однією зміною у вебсервері: сокет FastCGI.
# fastcgi_pass unix:/run/php-fpm/app-old.sock;
fastcgi_pass unix:/run/php-fpm/app-new.sock;
nginx -t && systemctl reload nginx
Rollback є тією самою правкою навпаки, застосованою за секунди, без змін пакетів і без перезапуску будь-чого, крім конфігурації вебсервера. Погодьте час із власником сайту, стежте за частотою помилок і часом відповіді першу годину, і тримайте старий пул працюючим протягом періоду обкатки, достатньо довгого, щоб покрити щотижневі та щомісячні завдання. Лише тоді виводьте його з експлуатації.
На стеку з кількох вузлів робіть це по одному вебвузлу за раз за балансувальником, щоб навіть неприємний сюрприз зачепив частку трафіку на кілька хвилин.
Крок сьомий: тримайте cron і CLI в ногу
Вебсервер не єдине, що виконує PHP. Заплановані завдання, обробники черг і інструменти командного рядка часто викликають жорстко прописаний шлях до бінарника. Знайдіть їх:
grep -rE 'php[0-9]*( |$)|/bin/php' /etc/cron* /var/spool/cron /etc/systemd/system 2>/dev/null
Переведіть їх на новий бінарник у тому самому вікні змін або свідомо після, але ніколи випадково.
Ваш контрольний список
- Новий PHP встановлений поруч зі старим, з власним пулом і сокетом.
- Кожен файл перевірений новим бінарником, і проведене сканування сумісності для цільової гілки.
- Трасування OPcache того, що завантажує реальний трафік, включно зі шляхами авторизованих користувачів та адміністраторів.
- Закодовані файли згруповані за форматом і зіставлені з новим loader.
- Репетиція на новому пулі з відкритим журналом помилок.
- Cutover в один рядок, старий пул збережений до кінця обкатки, і cron переведений свідомо.
Якщо у вас є оновлення, яке ви відкладаєте, ми радо сплануємо його разом з вами.
Related
- /what-we-do/data-web/php-upgrades-security-patching/
- /what-we-do/data-web/performance-audits/
- /what-we-do/data-web/high-availability-web-tiers/
Опубліковано 15 вересня 2026 р..
Усі нотатки з практики