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

Ορισμός ορίων μνήμης με systemd και cgroups

Το php.net συνιστά ως μεταβατικό μέτρο για το PHP2Shell memory_limit=-1 και ένα όριο μνήμης εκτός της PHP. Δείτε πώς ορίζετε αυτό το όριο με systemd και cgroups, χωρίς ένας μεμονωμένος worker να παρασύρει ολόκληρη την υπηρεσία.

Ημερομηνία 6 λεπτά ανάγνωσηςΣκλήρυνση και διαμόρφωση

Εν ολίγοις: Για το μεταβατικό μέτρο του PHP2Shell memory_limit=-1 το PHP-FPM χρειάζεται όριο μνήμης εκτός της PHP. Στο systemd το ορίζετε με MemoryHigh= ως φρένο και MemoryMax= ως σκληρό ανώτατο όριο σε ένα συμπληρωματικό αρχείο για την υπηρεσία FPM. Τα ulimit, LimitAS= ή LimitDATA= είναι γι' αυτό ακατάλληλα, σύμφωνα με το php.net. Ελέγξτε επιπλέον το OOMPolicy=, ώστε ένας μεμονωμένος worker να μην τερματίζει ολόκληρη την υπηρεσία.

Μια σύσταση που στην αρχή προκαλεί απορία

Ανάμεσα στα μεταβατικά μέτρα που δημοσίευσε το php.net στις 21 Οκτωβρίου 2026 για το PHP2Shell υπάρχει ένα που έκανε πολλούς διαχειριστές να διστάσουν: memory_limit=-1, δηλαδή κανένα όριο μνήμης στην ίδια την PHP. Επί χρόνια ίσχυε το αντίθετο ως καλή πρακτική.

Μια σύνδεση με την περιγραφή της ευπάθειας είναι προφανής. Στο CVE-2026-109618 μια κατάσταση Out-of-Memory μπορεί να διακόψει την PHP ενώ τα δεδομένα του αιτήματος έχουν αρχικοποιηθεί μόνο εν μέρει. Το μεταβατικό μέτρο μεταφέρει το όριο μνήμης από την PHP στο λειτουργικό σύστημα. Το php.net το συνδέει ρητά με δύο προϋποθέσεις: η τιμή πρέπει να είναι κλειδωμένη κατά της αντικατάστασης και το όριο πρέπει να προέρχεται από container ή cgroup και όχι από RLIMIT_AS ή RLIMIT_DATA.

Όποιος υλοποιεί μόνο το πρώτο μισό έχει έναν διακομιστή χωρίς κανένα όριο μνήμης. Αυτό το άρθρο δείχνει το δεύτερο μισό. Ακόμη και μαζί, το μέτρο παραμένει μετάβαση: η ευπάθεια διορθώνεται μόνο με PHP 8.5.12, 8.4.27, 8.3.36, 8.2.35 ή επιβεβαιωμένο backport.

Τα cgroups σε δύο προτάσεις

Τα Control Groups, συντομογραφικά cgroups, είναι μια λειτουργία του πυρήνα του Linux που ομαδοποιεί διεργασίες και περιορίζει τους πόρους τους. Το systemd δημιουργεί αυτόματα για κάθε υπηρεσία ένα δικό της cgroup και όλες οι διεργασίες της υπηρεσίας, στην υπηρεσία FPM ο master και όλοι οι workers, ανήκουν σε αυτό.

Οι επιλογές μνήμης του systemd ορίζουν τιμές του ελεγκτή μνήμης cgroup v2. Το αν το σύστημά σας χρησιμοποιεί cgroup v2 το δείχνει μια σύντομη εντολή:

# "cgroup2fs" σημαίνει: το cgroup v2 είναι ενεργό
stat -fc %T /sys/fs/cgroup/

Οι τρέχουσες εκδόσεις των συνηθισμένων διανομών χρησιμοποιούν από προεπιλογή cgroup v2. Αν η εντολή δείξει κάτι άλλο, διευκρινίστε το πριν από τη μετάβαση, επειδή η τεκμηρίωση του systemd περιγράφει τις παλιές επιλογές v1 ως παρωχημένες.

Ορισμός του systemd MemoryMax για το PHP-FPM

Το όριο μπαίνει σε ένα συμπληρωματικό αρχείο, ένα λεγόμενο drop-in. Έτσι το αρχείο unit του πακέτου μένει αμετάβλητο και μια ενημέρωση δεν αντικαθιστά τη ρύθμισή σας. Τα ονόματα υπηρεσιών διαφέρουν ανά διανομή· το παράδειγμα χρησιμοποιεί Debian και Ubuntu με PHP 8.3.

# Ανοίγει επεξεργαστή για το drop-in: sudo systemctl edit php8.3-fpm
# Αποτέλεσμα: /etc/systemd/system/php8.3-fpm.service.d/override.conf
[Service]
MemoryAccounting=yes
MemoryHigh=1536M
MemoryMax=2G
MemorySwapMax=0
OOMPolicy=continue

Οι επιλογές με μια ματιά, σύμφωνα με την τεκμηρίωση του systemd:

Επιλογή Αποτέλεσμα Υπόδειξη για το PHP-FPM
MemoryHigh= όριο στραγγαλισμού: οι διεργασίες επιβραδύνονται έντονα, ανακτάται μνήμη το πραγματικό μέγεθος ελέγχου, λίγο κάτω από το MemoryMax
MemoryMax= απόλυτο όριο: αν δεν μπορεί να τηρηθεί, ενεργοποιείται ο OOM-Killer στην υπηρεσία τελευταία γραμμή άμυνας
MemorySwapMax= όριο για την ανταλλαγή (swap) το 0 εμποδίζει την υπηρεσία να καταφεύγει στο swap
OOMPolicy= συμπεριφορά μετά από συμβάν OOM: continue, stop ή kill το continue αφήνει τους υπόλοιπους workers να συνεχίσουν
LimitAS=, LimitDATA= rlimits ανά διεργασία ακατάλληλα για αυτό το μέτρο, σύμφωνα με το php.net

Το OOMPolicy= αξίζει ιδιαίτερη προσοχή. Με stop ή kill το systemd τερματίζει μετά από ένα συμβάν OOM ολόκληρη την υπηρεσία και όλοι οι ιστότοποι αυτής της υπηρεσίας FPM τίθενται εκτός λειτουργίας. Ποια τιμή ισχύει χωρίς δική σας δήλωση, το ορίζει η προεπιλογή του συστήματος DefaultOOMPolicy=. Ελέγξτε γι' αυτό την αποτελεσματική τιμή, αντί να την υποθέσετε.

Στη συνέχεια επανεκκινήστε την υπηρεσία και κλειδώστε το memory_limit στο pool:

sudo systemctl restart php8.3-fpm
systemctl show php8.3-fpm -p MemoryHigh -p MemoryMax -p MemorySwapMax -p OOMPolicy -p MemoryCurrent
; Αρχείο pool, π.χ. /etc/php/8.3/fpm/pool.d/seite1.conf
php_admin_value[memory_limit] = -1

Πώς λειτουργεί το κλείδωμα, περιγράφει το php_admin_value: κλείδωμα ρυθμίσεων κατά της αντικατάστασης.

Εύρεση της σωστής τιμής

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

  1. Παρακολουθήστε την τρέχουσα ανάγκη μνήμης όλων των διεργασιών FPM για μερικές ημέρες, και σε κορυφές φορτίου.
  2. Εντοπίστε την τυπική ανάγκη ενός worker και πολλαπλασιάστε με το pm.max_children όλων των pools της υπηρεσίας.
  3. Προβλέψτε προσαύξηση για τη διεργασία master, την OPcache και τις κορυφές.
  4. Ορίστε το MemoryHigh= λίγο πάνω από τη μετρημένη κορυφαία τιμή, το MemoryMax= με κάποια απόσταση πάνω από αυτό.
  5. Προσαρμόστε τις τιμές μετά από μία εβδομάδα με βάση τις μετρήσεις και τα συμβάντα OOM.
# Μνήμη όλων των διεργασιών PHP-FPM σε MB (Resident Set Size)
ps -C php-fpm8.3 -o rss= | awk '{s+=$1} END {printf "%.0f MB\n", s/1024}'
# Τρέχουσα επισκόπηση όλων των cgroups ταξινομημένων κατά μνήμη
systemd-cgtop -m

Την τιμή του memory_limit πριν από τη μετάβαση πρέπει να τη σημειώσετε. Μετά την ενημέρωση μπορείτε να επιστρέψετε σε σταθερό όριο στην PHP· πώς να το επιλέξετε με λογική, αναφέρεται στο Σωστή ρύθμιση του memory_limit.

Παρακολούθηση: πότε ενεργοποιείται το όριο

Ένα όριο μνήμης του οποίου την ενεργοποίηση δεν αντιλαμβάνεται κανείς είναι σιωπηλή πηγή σφαλμάτων. Ο πυρήνας μετρά τα συμβάντα OOM ανά cgroup και το systemd καθώς και το πρωτόκολλο του πυρήνα τα καταγράφουν.

# Μετρητής OOM του cgroup της υπηρεσίας (διαδρομή στο cgroup v2)
cat /sys/fs/cgroup/system.slice/php8.3-fpm.service/memory.events
# Μηνύματα του OOM-Killer στο πρωτόκολλο του πυρήνα
journalctl -k --since "-1 day" | grep -i "out of memory"

Αν αυξάνεται ο μετρητής oom_kill, ο πυρήνας τερματίζει workers. Αυτό μπορεί να υποδεικνύει υπερβολικά στενό όριο, ελαττωματική εφαρμογή ή ασυνήθιστα αιτήματα. Στην τρέχουσα κατάσταση αξίζει να συγκρίνετε τέτοια συμβάντα με τα πρωτόκολλα πρόσβασης της ίδιας χρονικής στιγμής.

Σημαντικό

Το όριο μνήμης είναι μεταβατικό μέτρο και δεν αντικαθιστά την ενημέρωση της PHP. Σχεδιάστε την ενημέρωση παράλληλα και επανεκκινήστε μετά όλες τις διεργασίες PHP. Όλα τα μεταβατικά μέτρα με μια ματιά υπάρχουν στο Άμεσα μέτρα όταν δεν μπορείτε ακόμη να εφαρμόσετε patch.

Τι συμβαίνει στο εσωτερικό της PHP σε έλλειψη μνήμης, εξηγεί το memory_limit και Out-of-Memory. Στον Apache με mod_php ισχύει η ίδια τεχνική για την υπηρεσία Apache, μόνο που η PHP μοιράζεται τότε το όριο με τον ίδιο τον διακομιστή ιστού.

Συμπέρασμα: μη ξεχνάτε το δεύτερο μισό

Το memory_limit=-1 είναι ένα υπεράσπιστο μεταβατικό μέτρο μόνο μαζί με ένα εξωτερικό όριο. Το systemd κάνει αυτό το όριο δυνατό με λίγες γραμμές: MemoryHigh ως φρένο, MemoryMax ως σκληρό ανώτατο όριο, MemorySwapMax κατά της διαφυγής στο swap και ένα συνειδητά επιλεγμένο OOMPolicy. Μετρήστε πριν, παρακολουθήστε μετά και έχετε κατά νου ότι όλα τα pools μιας υπηρεσίας μοιράζονται το όριο.

Κυρίως όμως: σχεδιάστε το τέλος του μέτρου. Μετά την ενημέρωση σε διορθωμένη έκδοση PHP επιστρέφετε σε σταθερό memory_limit. Το όριο cgroup μπορείτε να το κρατήσετε ως πρόσθετη προστασία κατά διεργασιών που ξεφεύγουν.

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

  • Μέτρηση: Καταγράφουμε την ανάγκη μνήμης των υπηρεσιών PHP σας και εξάγουμε κατάλληλα όρια.
  • Υλοποίηση: Ορίζουμε drop-ins με MemoryHigh, MemoryMax και κατάλληλο OOMPolicy, κλειδώνουμε το memory_limit στο pool και επανεκκινούμε ελεγχόμενα τις υπηρεσίες.
  • Παρακολούθηση: Ενσωματώνουμε τα συμβάντα OOM στην παρακολούθηση και προσαρμόζουμε τις τιμές.
  • Οδηγούμε στο patch: Μέσω της υπηρεσίας patch PHP εφαρμόζουμε την ενημέρωση και επαναφέρουμε στη συνέχεια οργανωμένα τις μεταβατικές τιμές.

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

Γιατί να είναι το memory_limit -1; Δεν είναι επικίνδυνο;

Μόνο του θα ήταν. Το php.net συνιστά το memory_limit=-1 ως μεταβατικό μέτρο ρητά μαζί με όριο μνήμης μέσω container ή cgroup. Ο περιορισμός μεταφέρεται έτσι από την PHP στο λειτουργικό σύστημα. Χωρίς αυτό το εξωτερικό όριο δεν πρέπει να ορίσετε την τιμή.

Μπορώ να χρησιμοποιήσω αντί γι' αυτό το ulimit ή το LimitAS=;

Όχι. Το php.net αποθαρρύνει ρητά τα RLIMIT_AS και RLIMIT_DATA και ακριβώς αυτά τα όρια ορίζουν τα ulimit -v, LimitAS= και LimitDATA=. Η τεκμηρίωση του systemd επισημαίνει επιπλέον ότι το LimitAS= περιορίζει τον χώρο διευθύνσεων και όχι την κατανάλωση μνήμης.

Τι συμβαίνει όταν το PHP-FPM φτάσει το όριο;

Στο MemoryHigh ο πυρήνας επιβραδύνει τις διεργασίες και ανακτά μνήμη. Στο MemoryMax ενεργοποιείται μέσα στην υπηρεσία ο OOM-Killer και τερματίζει μια διεργασία, συνήθως έναν μεγάλο worker. Το αν θα σταματήσει στη συνέχεια ολόκληρη η υπηρεσία το ρυθμίζει το OOMPolicy=.

Ισχύει το όριο για κάθε pool ξεχωριστά;

Όχι. Όλα τα pools μιας υπηρεσίας FPM μοιράζονται ένα cgroup και άρα ένα κοινό όριο. Χωριστά όρια ανά ιστότοπο απαιτούν χωριστές υπηρεσίες FPM ή containers.

Πώς ορίζω το όριο στο Docker ή στο Kubernetes;

Μέσω του περιορισμού μνήμης του container, για παράδειγμα με την επιλογή --memory στο docker run ή με resources.limits.memory στο Kubernetes. Και τα δύο χρησιμοποιούν επίσης cgroups. Η αρχή παραμένει ίδια: όριο εκτός της PHP, memory_limit κλειδωμένο στην PHP.

Πηγές

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

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

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

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