Αποδείξτε μια αναβάθμιση PHP πριν την αλλαγή, με rollback έτοιμο
Νέο branch PHP με ασφάλεια: εγκατάσταση δίπλα δίπλα, lint και scan του κώδικα, ιχνηλάτηση του τι φορτώνει πραγματικά η κίνηση, και μετά αλλαγή ενός socket.

Οι περισσότερες αναβαθμίσεις PHP αποτυγχάνουν με τον ίδιο τρόπο: η νέα έκδοση εγκαθίσταται πάνω από την παλιά, η αρχική σελίδα φορτώνει, όλοι χαλαρώνουν, και ο πρώτος διαχειριστής που ανοίγει μια σπάνια χρησιμοποιούμενη οθόνη το επόμενο πρωί παίρνει λευκή σελίδα. Αυτή είναι η μέθοδος που χρησιμοποιούμε για να βρίσκουμε αυτά τα προβλήματα στον πάγκο, πριν το cutover, με έναν δρόμο επιστροφής που παίρνει δευτερόλεπτα.
Γιατί οι αναβαθμίσεις συνεχίζουν να χαλούν πράγματα
Κάθε branch της PHP αφαιρεί συναρτήσεις, σφίγγει τον χειρισμό τύπων, και μετατρέπει παλιές προειδοποιήσεις σε fatal errors. Μια εφαρμογή που μεγάλωσε με τα χρόνια κουβαλά διαδρομές κώδικα που κανείς δεν έχει εκτελέσει εδώ και καιρό: μια εξαγωγή, ένα παλιό module πληρωμών, μια αναφορά διαχείρισης. Ένα smoke test των δημόσιων σελίδων δεν θα τις φτάσει ποτέ.
Οι εμπορικές εφαρμογές προσθέτουν ένα δεύτερο επίπεδο. Αρχεία προστατευμένα από encoder τρέχουν μόνο αν ο loader για το νέο branch PHP υποστηρίζει τη μορφή με την οποία κωδικοποιήθηκαν, και αυτό είναι ιδιότητα κάθε αρχείου, όχι της σελίδας marketing της εφαρμογής.
Βήμα ένα: εγκαταστήστε δίπλα δίπλα, ποτέ από πάνω
Εγκαταστήστε τη στοχευόμενη PHP δίπλα στην τρέχουσα. Σε RHEL και τις ανακατασκευές του, τα software collections του Remi το κάνουν απλό: κάθε branch ζει στο δικό του prefix, με τη δική του υπηρεσία FPM και το δικό του socket. Δημιουργήστε ένα pool για το site στη νέα έκδοση, ίδιο με το παλιό pool εκτός από το binary και τη διαδρομή του socket.
Τίποτα δεν έχει αλλάξει ακόμη για τους επισκέπτες. Και οι δύο εκδόσεις τρέχουν, και ο web server δείχνει ακόμη στο παλιό socket.
Βήμα δύο: κάντε lint κάθε αρχείο με το νέο binary
Η φθηνότερη δοκιμή είναι να ζητήσετε από τη νέα PHP να κάνει parse κάθε αρχείο:
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'
Αυτό πιάνει σύνταξη που το νέο branch δεν δέχεται πια. Δεν πιάνει αφαιρεμένες συναρτήσεις ή αλλαγμένη συμπεριφορά, γιατί αυτά αποτυγχάνουν μόνο στην εκτέλεση. Για αυτά, τρέξτε μια στατική σάρωση συμβατότητας, όπως το PHP_CodeSniffer με το πρότυπο PHPCompatibility, ρυθμισμένο στο branch-στόχο σας:
phpcs -p --standard=PHPCompatibility --runtime-set testVersion <target> \
--extensions=php /var/www/app
Περιμένετε θόρυβο από vendored βιβλιοθήκες και νεκρό κώδικα. Η λίστα είναι χάρτης, όχι ετυμηγορία.
Βήμα τρία: μάθετε ποια αρχεία φορτώνει πραγματικά η κίνηση
Μια εφαρμογή μπορεί να περιέχει δεκάδες χιλιάδες αρχεία PHP, από τα οποία ένα κλάσμα τρέχει ποτέ. Θέλετε η προσπάθεια συμβατότητας να ξοδευτεί σε αυτό το κλάσμα, και θέλετε να είστε σίγουροι ότι περιλαμβάνει τις διαδρομές των συνδεδεμένων χρηστών και των διαχειριστών.
Η OPcache το ξέρει ήδη. Μετά από μια κανονική εργάσιμη ημέρα στην τρέχουσα έκδοση, με ανθρώπους να συνδέονται και διαχειριστές να κάνουν τη δουλειά τους, ρωτήστε την ποια scripts έχει μεταγλωττίσει:
<?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 και scan, και τα προβλήματα που θα χτυπήσουν πραγματικά ανεβαίνουν στην κορυφή. Αρχεία που εμφανίζονται στη σάρωση αλλά ποτέ στην ιχνηλάτηση είναι υποψήφια για αφαίρεση, όχι για διόρθωση.
Βήμα τέσσερα: διαβάστε τις κεφαλίδες των κωδικοποιημένων αρχείων
Για κωδικοποιημένο εμπορικό λογισμικό, ελέγξτε κάθε αρχείο αντί να εμπιστευτείτε ένα banner συμβατότητας. Τα κωδικοποιημένα αρχεία φέρουν μια κεφαλίδα απλού κειμένου που κατονομάζει τον encoder και τη μορφή:
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
Ομαδοποιήστε τα αρχεία ανά μορφή encoder, και επιβεβαιώστε ότι ο loader για το branch-στόχο σας τρέχει αυτή τη μορφή. Ένα module που κωδικοποιήθηκε πριν από χρόνια για ένα παλιό branch είναι ακριβώς το αρχείο που θα αρνηθεί να φορτώσει στο νέο, και είναι καλύτερα να το μάθετε από μια κεφαλίδα παρά από έναν πελάτη.
Βήμα πέντε: κάντε πρόβα στο νέο pool
Στρέψτε ένα δοκιμαστικό hostname, ή τη δική σας IP μέσω ενός κανόνα header, στο νέο socket ενώ η παραγωγή μένει στο παλιό. Περπατήστε τις διαδρομές από την ιχνηλάτηση της OPcache, με ιδιαίτερη προσοχή σε αυτές που φτάνουν μόνο συνδεδεμένοι χρήστες και διαχειριστές, και παρακολουθήστε το error log του νέου pool όσο το κάνετε:
tail -F /var/log/php-fpm/app-new-error.log | grep -E 'Fatal|Uncaught|Deprecated'
Οι ειδοποιήσεις deprecation δεν είναι αποτυχίες σήμερα, αλλά είναι η λίστα για την επόμενη αναβάθμιση. Σημειώστε τες.
Βήμα έξι: αλλάξτε μία γραμμή, κρατήστε το παλιό pool σε λειτουργία
Το cutover είναι μία αλλαγή στον web server: το FastCGI socket.
# fastcgi_pass unix:/run/php-fpm/app-old.sock;
fastcgi_pass unix:/run/php-fpm/app-new.sock;
nginx -t && systemctl reload nginx
Το rollback είναι η ίδια αλλαγή ανάποδα, εφαρμοσμένη σε δευτερόλεπτα, χωρίς αλλαγές πακέτων και χωρίς επανεκκινήσεις πέρα από τη διαμόρφωση του web server. Συμφωνήστε τον χρόνο με τον ιδιοκτήτη του site, παρακολουθήστε ρυθμούς σφαλμάτων και χρόνους απόκρισης την πρώτη ώρα, και κρατήστε το παλιό pool σε λειτουργία για μια περίοδο burn-in αρκετά μεγάλη ώστε να καλύψει εβδομαδιαίες και μηνιαίες εργασίες. Μόνο τότε αποσύρετέ το.
Σε ένα stack πολλών κόμβων, κάντε το έναν web node τη φορά πίσω από τον load balancer, ώστε ακόμη και μια άσχημη έκπληξη να φτάσει ένα κλάσμα της κίνησης για λίγα λεπτά.
Βήμα επτά: κρατήστε cron και CLI στο ίδιο βήμα
Ο web server δεν είναι το μόνο που τρέχει PHP. Προγραμματισμένες εργασίες, queue workers και εργαλεία γραμμής εντολών συχνά καλούν μια σταθερά κωδικοποιημένη διαδρομή binary. Βρείτε τα:
grep -rE 'php[0-9]*( |$)|/bin/php' /etc/cron* /var/spool/cron /etc/systemd/system 2>/dev/null
Μεταφέρετέ τα στο νέο binary στο ίδιο παράθυρο αλλαγής, ή σκόπιμα μετά, αλλά ποτέ κατά λάθος.
Η λίστα ελέγχου σας
- Νέα PHP εγκατεστημένη δίπλα στην παλιά, με το δικό της pool και socket.
- Κάθε αρχείο με lint από το νέο binary, και σάρωση συμβατότητας για το branch-στόχο.
- Μια ιχνηλάτηση OPcache του τι φορτώνει η πραγματική κίνηση, μαζί με τις διαδρομές συνδεδεμένων χρηστών και διαχειριστών.
- Κωδικοποιημένα αρχεία ομαδοποιημένα ανά μορφή και αντιστοιχισμένα με τον νέο loader.
- Μια πρόβα στο νέο pool με το error log του ανοιχτό.
- Ένα cutover μίας γραμμής, το παλιό pool κρατημένο μέχρι το τέλος του burn-in, και το 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.
Όλες οι σημειώσεις