Τρέχουσα κατάσταση: PHP2Shell. Δύο κρίσιμες ευπάθειες της PHP (CVSS 9.2) επιτρέπουν κακόβουλο κώδικα χωρίς σύνδεση. Patches από τις 21/10/2026.Τι πρέπει να γίνει τώρα →

Η OPcache εξηγημένη: η κρυφή μνήμη bytecode της PHP

Η OPcache κρατά τον μεταφρασμένο κώδικα PHP στην κοινή μνήμη. Αυτό εξοικονομεί υπολογιστικό χρόνο, απαιτεί όμως προσοχή στις αναπτύξεις, τις επανεκκινήσεις και στους διακομιστές με πολλούς πελάτες.

Ημερομηνία 5 λεπτά ανάγνωσηςΓνώση PHP

Εν συντομία: Η OPcache είναι η ενσωματωμένη κρυφή μνήμη bytecode της PHP. Σύμφωνα με το εγχειρίδιο αποθηκεύει προμεταγλωττισμένο bytecode στην κοινή μνήμη, ώστε η PHP να μη χρειάζεται να φορτώνει και να μεταφράζει τα σενάρια σε κάθε αίτημα. Περιλαμβάνεται στο πακέτο διανομής από την PHP 5.5.0. Η OPcache κάνει την PHP ταχύτερη, αλλά δεν αντικαθιστά την ενημέρωση: μετά από ένα patch της PHP πρέπει να γίνει επανεκκίνηση όλων των διεργασιών PHP, δεν αρκεί να αδειάσει η κρυφή μνήμη.

Τι κάνει ακριβώς η OPcache;

Σε κάθε αίτημα η PHP πρέπει να διαβάσει ένα σενάριο, να το αναλύσει και να το μεταφράσει σε opcodes, δηλαδή στις εντολές για την εικονική μηχανή της Zend Engine. Σε ένα CMS με εκατοντάδες αρχεία αυτό είναι πολλή δουλειά που επαναλαμβάνεται συνεχώς.

Η OPcache αποθηκεύει το αποτέλεσμα αυτής της μετάφρασης στην κοινή μνήμη (shared memory). Όλοι οι workers μιας υπηρεσίας PHP-FPM ή όλες οι διεργασίες Apache με mod_php έχουν πρόσβαση σε αυτήν. Αν ένα αρχείο δεν αλλάξει, το bytecode του επαναχρησιμοποιείται απευθείας.

Η OPcache φορτώνεται ως επέκταση Zend, όχι ως κανονική επέκταση:

; Linux (διαδρομή ανάλογα με το πακέτο)
zend_extension=opcache.so
; Windows
; zend_extension=php_opcache.dll

Σύμφωνα με το εγχειρίδιο, η OPcache πρέπει να φορτώνεται πριν από το Xdebug, όταν και τα δύο είναι ενεργά.

Σημασία έχει σε ποιον ανήκει η κοινή μνήμη. Στο PHP-FPM τη δημιουργεί η κύρια διεργασία (master) και όλοι οι workers όλων των pools αυτής της υπηρεσίας τη χρησιμοποιούν. Στο mod_php ανήκει στην κύρια διεργασία του Apache. Μια επανεκκίνηση της υπηρεσίας αδειάζει επομένως πλήρως την κρυφή μνήμη, ενώ ένας μεμονωμένος νέος worker όχι. Για τη γραμμή εντολών δεν υπάρχει κοινή μνήμη μεταξύ των κλήσεων, επειδή κάθε κλήση είναι ξεχωριστή διεργασία· εκεί η OPcache είναι από προεπιλογή απενεργοποιημένη.

Για όσους αποφασίζουν αρκεί ένας εμπειρικός κανόνας: η OPcache έχει σχεδόν πάντα νόημα σε διακομιστές παραγωγής, απαιτεί όμως σαφή διαδικασία για αναπτύξεις και ενημερώσεις.

Ποιες ρυθμίσεις της OPcache μετρούν;

Οι παρακάτω τιμές προέρχονται από τη σελίδα διαμόρφωσης του εγχειριδίου της PHP. Η στήλη «Τροποποιήσιμο» δείχνει πού επιτρέπεται να οριστεί μια ρύθμιση: INI_SYSTEM μόνο στο php.ini ή στη διαμόρφωση του διακομιστή, INI_ALL παντού.

Οδηγία Προεπιλογή Τροποποιήσιμο Σημασία
opcache.enable 1 INI_ALL κρυφή μνήμη ενεργή ή ανενεργή, κατά την εκτέλεση μπορεί μόνο να απενεργοποιηθεί
opcache.enable_cli 0 INI_SYSTEM κρυφή μνήμη για τη γραμμή εντολών
opcache.memory_consumption 128 INI_SYSTEM μέγεθος της κοινής μνήμης σε MB
opcache.interned_strings_buffer 8 INI_SYSTEM μνήμη για κοινές συμβολοσειρές σε MB
opcache.max_accelerated_files 10000 INI_SYSTEM μέγιστος αριθμός σεναρίων στην κρυφή μνήμη
opcache.validate_timestamps 1 INI_ALL ελέγχει αν τα αρχεία έχουν αλλάξει
opcache.revalidate_freq 2 INI_ALL διάστημα ελέγχου σε δευτερόλεπτα, 0 = σε κάθε αίτημα
opcache.restrict_api κενό INI_SYSTEM επιτρέπει συναρτήσεις API μόνο από μία διαδρομή
opcache.validate_permission 0 INI_SYSTEM ελέγχει τα δικαιώματα αρχείων με βάση τον τρέχοντα χρήστη
opcache.validate_root 0 INI_SYSTEM αποτρέπει συγκρούσεις ονομάτων σε chroot
opcache.file_cache κενό INI_SYSTEM δεύτερο επίπεδο κρυφής μνήμης στον δίσκο

Μια τυπική διαμόρφωση παραγωγής θα μπορούσε να μοιάζει ως εξής. Ελέγξτε προηγουμένως τις τιμές με την εφαρμογή σας:

opcache.enable=1
opcache.memory_consumption=256
opcache.interned_strings_buffer=16
opcache.max_accelerated_files=20000
opcache.validate_timestamps=1
opcache.revalidate_freq=60
opcache.restrict_api=/var/www/admin-tools

Όποιος ορίσει opcache.validate_timestamps=0 κερδίζει λίγη απόδοση. Τότε όμως η OPcache δεν αναγνωρίζει πλέον καθόλου αλλαγμένα αρχεία και κάθε ανάπτυξη χρειάζεται επαναφορά της κρυφής μνήμης ή επανεκκίνηση.

Παρακολούθηση και στοχευμένο άδειασμα της κρυφής μνήμης

Η OPcache έχει δικές της συναρτήσεις, μεταξύ άλλων τις opcache_get_status(), opcache_get_configuration(), opcache_invalidate() και opcache_reset(). Μια σύντομη ματιά μόνο για ανάγνωση στο επίπεδο πλήρωσης:

<?php
$status = opcache_get_status(false);
if ($status === false) {
    exit("OPcache ist nicht aktiv.\n");
}
printf("Gecachte Skripte: %d\n", $status['opcache_statistics']['num_cached_scripts']);
printf("Freier Speicher: %.1f MB\n", $status['memory_usage']['free_memory'] / 1048576);

Σε διακομιστές με πολλούς ιστότοπους δεν πρέπει κάθε εφαρμογή να μπορεί να αδειάζει ή να διαβάζει την κρυφή μνήμη όλων των άλλων. Γι' αυτό προορίζεται το opcache.restrict_api: μόνο σενάρια κάτω από την καθορισμένη διαδρομή επιτρέπεται να καλούν τις συναρτήσεις API.

JIT: ο μεταγλωττιστής κώδικα μηχανής στην OPcache

Από την PHP 8.0 η OPcache περιλαμβάνει έναν μεταγλωττιστή JIT, που μεταφράζει opcodes σε κώδικα μηχανής. Σύμφωνα με το RFC του JIT αποτελεί ένα σχεδόν αυτόνομο τμήμα της OPcache και αποθηκεύει τον παραγόμενο κώδικα σε ξεχωριστή περιοχή της κοινής μνήμης. Ελέγχεται μέσω των opcache.jit και opcache.jit_buffer_size. Από την PHP 8.4.0 το opcache.jit είναι από προεπιλογή ορισμένο σε disable. Πότε αξίζει ο JIT, εξηγεί το άρθρο JIT και απόδοση στην PHP 8.

OPcache και ασφάλεια: τι ισχύει μετά το PHP2Shell

Η OPcache δεν είναι εργαλείο ασφάλειας, έχει όμως συνέπειες για την ασφάλεια. Τρία σημεία είναι σημαντικά μετά το PHP2Shell:

  1. Μια επαναφορά της κρυφής μνήμης δεν είναι ενημέρωση. Το opcache_reset() αδειάζει μόνο σενάρια στην κρυφή μνήμη. Ο διερμηνέας με τις ευπάθειες CVE-2026-109618 και CVE-2026-109619 παραμένει στη μνήμη μέχρι να γίνει επανεκκίνηση όλων των διεργασιών. Πώς γίνεται αυτό, περιγράφεται στη σελίδα Επανεκκίνηση του PHP-FPM και όλων των workers.
  2. Κώδικας που έχει εισαχθεί κακόβουλα μπορεί να ζει στην κρυφή μνήμη. Αν ένα αρχείο παραποιήθηκε και αργότερα αντικαταστάθηκε, με απενεργοποιημένο έλεγχο χρονοσημάνσεων μπορεί να συνεχίσει να εκτελείται η παλιά εκδοχή. Μετά από έναν καθαρισμό ανήκει γι' αυτό και μια επανεκκίνηση.
  3. Η κοινή μνήμη χρειάζεται διαχωρισμό. Σε διακομιστές με πολλούς πελάτες βοηθούν ξεχωριστά pools PHP-FPM ανά ιστότοπο καθώς και τα opcache.validate_permission και opcache.restrict_api. Ένας κατάλογος για το opcache.file_cache επιτρέπεται να είναι εγγράψιμος μόνο από τον χρήστη της PHP.
Συμβουλή

Ελέγχετε μετά από κάθε ενημέρωση αν η ώρα εκκίνησης των διεργασιών PHP είναι μεταγενέστερη της ενημέρωσης. Μια γεμάτη OPcache με υψηλό ποσοστό επιτυχιών δεν αποδεικνύει ότι εκτελείται ο νέος διερμηνέας.

Πώς βοηθά συγκεκριμένα η PHP SOS;

  • Έλεγχος διαμόρφωσης: Διαβάζουμε την ενεργή διαμόρφωση της OPcache ανά τρόπο λειτουργίας και την συγκρίνουμε με την εφαρμογή σας.
  • Ασφαλείς αναπτύξεις: Στήνουμε μια σταθερή διαδικασία για επαναφορά της κρυφής μνήμης και επανεκκίνηση, ώστε να μη συνεχίζει να εκτελείται κάποια παλιά εκδοχή του κώδικα.
  • Διαχωρισμός πελατών: Στο πλαίσιο της θωράκισης διακομιστή ορίζουμε ξεχωριστά pools, restrict_api και κατάλληλα δικαιώματα.
  • Έλεγχος μετά τις ενημερώσεις: Αποδεικνύουμε μέσω των χρόνων εκκίνησης των διεργασιών ότι ο ενημερωμένος διερμηνέας είναι πράγματι ενεργός.

Συχνές ερωτήσεις

Είναι η OPcache ενεργή από προεπιλογή;

Η OPcache διανέμεται με την PHP από την PHP 5.5.0 και σύμφωνα με το εγχειρίδιο λειτουργεί με opcache.enable=1 ως προεπιλογή, μόλις φορτωθεί η επέκταση. Το αν είναι φορτωμένη εξαρτάται από το πακέτο ή τον πάροχό σας. Στη γραμμή εντολών, αντίθετα, η OPcache είναι από προεπιλογή απενεργοποιημένη (opcache.enable_cli=0).

Γιατί βλέπω ακόμη τον παλιό κώδικα μετά από μια ανάπτυξη;

Πιθανότατα η OPcache ελέγχει τις αλλαγές αρχείων μόνο ανά διαστήματα ή και καθόλου. Με το opcache.revalidate_freq περιμένει από προεπιλογή δύο δευτερόλεπτα, με το opcache.validate_timestamps=0 ποτέ. Τότε βοηθά μόνο μια επαναφορά της κρυφής μνήμης ή μια επανεκκίνηση του PHP-FPM ή του Apache.

Αρκεί το opcache_reset() μετά από ενημέρωση της PHP;

Όχι. Το opcache_reset() αδειάζει μόνο την κρυφή μνήμη με τα μεταφρασμένα σενάρια. Μια ενημέρωση της PHP αντικαθιστά τον ίδιο τον διερμηνέα, που είναι φορτωμένος σε κάθε εκτελούμενη διεργασία. Γι' αυτό πρέπει να γίνει επανεκκίνηση όλων των διεργασιών PHP.

Είναι ενεργός ο JIT στην PHP 8.4;

Σύμφωνα με το εγχειρίδιο, το opcache.jit είναι από την PHP 8.4.0 από προεπιλογή ορισμένο σε disable, ενώ το opcache.jit_buffer_size είναι 64M. Προηγουμένως ίσχυε το αντίστροφο: jit σε tracing, ενδιάμεση μνήμη στο 0. Και στις δύο περιπτώσεις ο JIT δεν είναι ενεργός χωρίς συνειδητή διαμόρφωση.

Πηγές

Άμεση επικοινωνία

Κάθε ώρα μετράει. Γράψτε μας τώρα.

Περιγράψτε σύντομα το σύστημα, την έκδοση PHP και ό,τι παρατηρείτε. Θα επικοινωνήσουμε μαζί σας, θα διευκρινίσουμε την κατάσταση και θα εργαστούμε εξ αποστάσεως μέχρι το περιστατικό να κλείσει και να τεκμηριωθεί.

Άμεση βοήθεια