Die Speicherbeschränkung für PHP-Skripte kann nicht aufgehoben werden

7

Die Situation

Ich habe ein Problem mit einem PHP-Skript, bei dem die folgende Fehlermeldung angezeigt wird:

Fatal error: Out of memory (allocated 359923712) (tried to allocate 72 bytes) in /path/to/piwik/core/DataTable.php on line 969

Das Skript, das ich ausführe, ist: /path/to/piwik/misc/cron/archive.sh

Ich gehe davon aus, dass die Zahlen Bytes sind, was bedeutet, dass die Gesamtzahl ungefähr 360 MB beträgt.

In jeder Hinsicht habe ich die Speicherbeschränkungen auf dem Server deutlich über 360 MB erhöht, aber dies ist die Anzahl (Geben oder Nehmen eines Bytes), bei der ständig Fehler auftreten.

Bitte beachten Sie : Bei dieser Frage geht es weder um die Behebung eines Speicherverlusts im Skript noch darum, warum das Skript selbst so viel Speicher verwendet. Das Skript ist Teil des Piwik-Archivierungsprozesses, daher kann ich keine Speicherlecks usw. beheben. Weitere Informationen zu diesem Skript und warum ich das Speicherlimit erhöhe, finden Sie unter "Einrichten der automatischen Archivierung".

Die Frage

Angesichts der Tatsache, dass das Skript versucht, mehr als 360 MB Speicher zu verwenden, den ich nicht ändern kann, warum scheint es mir nicht möglich zu sein, die für PHP auf meinem Server verfügbare Speichermenge zu erhöhen?

Update 23. Juni : Hintergrundinformationen finden Sie unter "Was ich versucht habe"> "Erhöhen der Speicherbeschränkungen pro Prozess unter Linux". Wenn ich dies einstelle ulimit -v 1024000, überprüfen Sie es mit " ulimit -vIch erhalte den korrekten Wert" 1024000 ". Wenn ich das Skript erneut ausführe, wird es viel weiter gehen, aber irgendwann wird ein Fehler auftreten, wenn das gleiche Speicherlimit (~ 360 MB) erreicht wurde. Wenn ich es sofort überprüfe ulimit -v, wurde es auf den ursprünglichen Wert von '524288' ​​zurückgesetzt. Dies scheint die Hauptursache des Problems zu sein.


Was ich versucht habe

Erhöhung des Speicherlimits von PHP

Angesichts der Datei php.ini:

php -i | grep php.ini
Configuration File (php.ini) Path => /usr/local/lib
Loaded Configuration File => /usr/local/lib/php.ini

Ich habe diese Datei bearbeitet, daher lautet die Anweisung memory_limit.

memory_limit = -1

Starten Sie Apache neu und überprüfen Sie, ob der neue Wert feststeckt.

$ php -i | grep memory_limit
memory_limit => -1 => -1

Führen Sie das Skript aus und erhalten Sie den gleichen Fehler.

Ich habe auch versucht 1G, 768Musw. alle zum gleichen Ergebnis (dh keine Änderung).

Update 22. Juni : Basierend auf Vangel's Hilfe habe ich versucht, post_max_sizein Kombination mit der Einstellung 20M einzustellen memory_limit. Auch dies hat keine Auswirkung.

Update 23. Juni : Basierend auf der Hilfe von olefebvre kann ich bestätigen, dass der Benutzer, der das Skript ausführt, über Lese- / Schreibberechtigungen für die Datei php.ini verfügt, die die Einstellungen von enthält memory_limit.

Entfernen des Speicherlimits für untergeordnete Prozesse von Apache

Ich habe die Datei httpd.conf gefunden und bearbeitet, um sicherzustellen, dass es keine RLimitMEMDirektive gibt.

Ich habe dann WHMs Apache-Konfiguration> Speichernutzungsbeschränkungen verwendet, um eine Einschränkung zu generieren, die angeblich 1000 MB betrug (und durch Überprüfen von httpd.conf bestätigt wurde).

Beides führte zu keiner Änderung des Skriptfehlers bei 360 MB.

Erhöhen der Speichergrenzen pro Prozess unter Linux

Die im System festgelegten aktuellen Grenzwerte:

$ ulimit -m
524288

$ ulimit -v
524288

Ich habe versucht, beide auf unbegrenzt zu setzen:

$ ulimit -m unlimited
$ ulimit -v unlimited

$ ulimit -m
unlimited

$ ulimit -v
unlimited

Dies hat wiederum zu keiner Verbesserung meines Problems geführt.

Update 23. Juni : Ich bin hier auf ein verwandtes Problem gestoßen. Wenn ich einstelle ulimit -v 1024000, überprüfe es mit ulimit -vIch erhalte den korrekten Wert von '1024000'. Wenn ich das Skript erneut ausführe, wird es viel weiter gehen, aber irgendwann wird ein Fehler auftreten, wenn dasselbe Speicherlimit erreicht wurde. Wenn ich es sofort überprüfe ulimit -v, wurde es auf den ursprünglichen Wert von '524288' ​​zurückgesetzt. Dies scheint die Hauptursache des Problems zu sein.


Mein Setup

$ cat /etc/redhat-release
CentOS release 5.5 (Final)

$ uname -a
Linux example.com 2.6.18-164.15.1.el5 #1 SMP Wed Mar 17 11:30:06 EDT 2010 x86_64 x86_64 x86_64 GNU/Linux

$ php -i | grep "PHP Version"
PHP Version => 5.2.9

$ httpd -V
Server version: Apache/2.0.63
Server built:   Feb  2 2011 01:25:12
Cpanel::Easy::Apache v3.2.0 rev5291
Server's Module Magic Number: 20020903:13
Server loaded:  APR 0.9.17, APR-UTIL 0.9.15
Compiled using: APR 0.9.17, APR-UTIL 0.9.15
Architecture:   64-bit
Server compiled with....
 -D APACHE_MPM_DIR="server/mpm/prefork"
 -D APR_HAS_SENDFILE
 -D APR_HAS_MMAP
 -D APR_HAVE_IPV6 (IPv4-mapped addresses enabled)
 -D APR_USE_SYSVSEM_SERIALIZE
 -D APR_USE_PTHREAD_SERIALIZE
 -D SINGLE_LISTEN_UNSERIALIZED_ACCEPT
 -D APR_HAS_OTHER_CHILD
 -D AP_HAVE_RELIABLE_PIPED_LOGS
 -D HTTPD_ROOT="/usr/local/apache"
 -D SUEXEC_BIN="/usr/local/apache/bin/suexec"
 -D DEFAULT_PIDLOG="logs/httpd.pid"
 -D DEFAULT_SCOREBOARD="logs/apache_runtime_status"
 -D DEFAULT_LOCKFILE="logs/accept.lock"
 -D DEFAULT_ERRORLOG="logs/error_log"
 -D AP_TYPES_CONFIG_FILE="conf/mime.types"
 -D SERVER_CONFIG_FILE="conf/httpd.conf"

Ausgabe von $ php -i: http://pastebin.com/EiRut6Nm

Jess Telford
quelle
Ich denke du hast die falsche php.ini bearbeitet. normalerweise befindet sich die php.ini in /etc/php.ini. Ich bin mir nicht sicher, ob es dort sein könnte, aber auf allen meinen RHEL-Servern und CentOS-Servern war es immer da. Warum also nicht mal probieren
?
Danke für den Tipp. Mein Server hat keine /etc/php.ini Datei, also definitiv nicht da :) Gemäß der Frage kann ich bestätigen, dass nach dem Bearbeiten der /usr/local/lib/php.ini Datei und dem Neustart von Apache die Einstellungen Stock.
Jess Telford
Ich bin gespannt, warum die Frage abgelehnt wurde. Ist das nicht eine gute Frage ? Wenn nicht, wie kann ich es verbessern?
Jess Telford

Antworten:

2

Hintergrund:

Ich habe gerade die aktuelle Version von Piwik gekauft. In Version 1.5 wird Zeile 969 wie folgt angezeigt:

public function addRowsFromSerializedArray( $stringSerialized )
{
    $serialized = unserialize($stringSerialized);
    if($serialized === false)
    {
        throw new Exception("The unserialization has failed!");
    }
    $this->addRowsFromArray($serialized);
}

und ist speziell $serialized = unserialize($stringSerialized);. Der Anruf bei unserializekann unglaublich speicherintensiv sein. Es gibt einen ausgezeichneten Beitrag hier .

Wie Sie bereits bemerkt haben, ist dies eindeutig kein Fehler in Ihrem Skript und ein gültiger Speichermangel .

Vorschlag: In der Konfigurationsdatei, wie oben in meinem Kommentar angegeben:

/.../piwik/config/global.ini.php

Ich denke, Sie müssen möglicherweise eine dieser Grenzen erhöhen:

# during archiving, Piwik will limit the number of results recorded, for performance reasons
# maximum number of rows for any of the Referers tables (keywords, search engines, campaigns, etc.)
# this limit will also be applied to the Custom Variables names and values reports
datatable_archiving_maximum_rows_referers = 1000
# maximum number of rows for any of the Referers subtable (search engines by keyword, keyword by campaign, etc.)
datatable_archiving_maximum_rows_subtable_referers = 50

# maximum number of rows for any of the Actions tables (pages, downloads, outlinks)
datatable_archiving_maximum_rows_actions = 500
# maximum number of rows for pages in categories (sub pages, when clicking on the + for a page category)
# note: should not exceed the display limit in Piwik_Actions_Controller::ACTIONS_REPORT_ROWS_DISPLAY
#       because each subdirectory doesn't have paging at the bottom, so all data should be displayed if possible.
datatable_archiving_maximum_rows_subtable_actions = 100

# maximum number of rows for other tables (Providers, User settings configurations)
datatable_archiving_maximum_rows_standard = 500

wo ich die Semikolons in # Zeichen geändert habe, nur um die Autocolor von sf lesbar zu machen.

Sie können auch versuchen, Folgendes hinzuzufügen:

CMD_TO_CHECK_SETTINGS="$PHP_BIN -i > /tmp/piwik-php-env.out"
$CMD_TO_CHECK_SETTINGS

in archive.sh, um festzustellen, ob andere Einstellungen im Gange sind, die die Datei php.ini überschreiben.

M. Tibbits
quelle
Vielen Dank für die Antwort, die jedoch darauf hinweist, was ich bereits weiß, wie in der Frage angegeben. Da diese Antwort bei der eigentlichen Frage nicht hilft, würde ich gerne abstimmen (habe aber nicht genug Vertreter, um dies zu tun).
Jess Telford
Aha! Fortschritt! Ich habe memory_minimum_limitauf 1024 erhöht und die von Ihnen aufgelisteten Variablen um jeweils den Faktor 10 erhöht und ulimit -m und ulimit -v auf 'unbegrenzt' gesetzt. Die Fehlermeldung, die ich jetzt erhalte, lautet: SQLSTATE[08S01]: Communication link failure: 1153 Got a packet bigger than 'max_allowed_packet' bytesWeitere Untersuchungen haben mich dazu veranlasst, mysqlds zu erhöhen max_allowed_packet=32M(war zuvor bei 1M). Lief das Drehbuch perfekt! Ich werde es eingrenzen und über die genaue Lösung berichten :)
Jess Telford
Endgültige Lösung; 1. Bearbeiten /etc/my.cnfund einstellen max_allowed_packet=32M. 2. Bearbeiten /usr/local/lib/php.iniund einstellen memory_limit = 512M. 3. Stellen Sie ein ulimit -v 1048576. Ich weiß nicht warum, aber das Ändern der Einstellungen, die Sie in der Konfigurationsdatei von piwik erwähnt haben, scheint den zweiten oben angegebenen SQL-Fehler verursacht zu haben, der mich dazu veranlasste, max_allowed_packet festzulegen. Vielen Dank für Ihre Hilfe!
Jess Telford
1
Ohne genau zu wissen, was / wo die Fehlermeldung ist, besteht mein anfänglicher Verdacht darin, dass ein Funktionsaufruf einen Befehl unter einem anderen Benutzer ausgibt, der nicht über die von ulimitIhnen angegebenen großzügigen Einstellungen verfügt.
M. Tibbits
1
@ M.Tibbits lassen Sie uns diese Diskussion im Chat fortsetzen
Jess Telford
2

Die Antwort von M. Tibbits spielt darauf an, dass Piwik während des Archivierungsprozesses mehr Ressourcen verwenden kann.

Es gibt eine Einschränkung, wie groß ein SQL-Befehl ausgeführt werden kann, der standardmäßig nur 1 MB beträgt. Für mehr Information; Paket zu groß

Um die Größenbeschränkung in MySQL zu erhöhen, bearbeiten /etc/my.cnfund festlegenmax_allowed_packet=32M

Stellen Sie sicher, dass das PHP-Speicherlimit pro gegabeltem Prozess durch Bearbeiten /usr/local/lib/php.iniund Festlegen hoch genug eingestellt istmemory_limit = 512M

Stellen Sie schließlich sicher, dass alle Prozesse mindestens eine feste Grenze von 1 G haben, bevor das System sie durch Ausführen ulimit -v 1048576über die Befehlszeile abschaltet .

Aktualisieren

ulimit -v 1048576erhöht nur die weiche Grenze. Wenn das harte Limit nicht hoch genug ist, setzt das System das weiche Limit automatisch auf das des harten Limits zurück.

Fügen Sie den -HSchalter hinzu, um das harte Limit festzulegen:

ulimit -vH 1048576

gefolgt von einer Erhöhung des Soft-Limits auf diesen Wert:

ulimit -vS 1048576
Jess Telford
quelle
Ich habe möglicherweise zu früh gesprochen - anscheinend funktioniert diese Lösung nicht.
Jess Telford
1
Das harte Limit muss erhöht werden, gefolgt vom weichen Limit. Dies war die endgültige Lösung.
Jess Telford
0

Dies ist definitiv ein Skriptfehler. Es scheint, dass es einen Speicherverlust gibt, egal wie sehr Sie das Speicherlimit in PHP erhöhen, es wird es treffen.

Ich benutze Piwik auf einer grundlegenden Ebene und kann mich nicht erinnern, jemals ein Archivierungsskript direkt verwendet zu haben. Piwik ist immer noch ein bisschen fehlerhaft, aber die neueste Version ist 1.4 und scheint viel weniger fehlerhaft zu sein als die vorherigen.

Ich empfehle, nicht mit System- oder PHP-Einstellungen herumzuspielen, um ein fehlerhaftes Skript aufzunehmen. Das Piwik-Support-Forum zu besuchen, könnte eine bessere Idee sein

Abhishek Dujari
quelle
Vielen Dank für Ihre Antwort. Wie in der Frage angegeben; Hier geht es nicht darum, einen Fehler in Piwik zu beheben. Das seltsame Verhalten ist: Angesichts der Tatsache, dass ein Skript mehr als 360 MB Speicher benötigt, warum kann ich nicht zulassen, dass es mehr verwendet?
Jess Telford
den Webserver neu gestartet?
Abhishek Dujari
Ich habe Apache neu gestartet, wenn Sie das meinen. Es ist für mich nicht möglich, das gesamte Betriebssystem neu zu starten.
Jess Telford
ja nur Webserver. Also, was hast du bekommen? Auch wenn es nicht geklappt hat, wäre es hilfreich, sich die phpinfo anzuschauen. Ich vermute, dass es das INI nicht von dem Ort aufnimmt, an dem Sie es ändern? ps wir sind weit weg von Zeitzonen. Schicken Sie mir Ihre Skype-ID, wenn Sie können, und vielleicht können wir uns einfach unterhalten, um dies herauszufinden. Dann veröffentlichen Sie die Lösung hier
Abhishek Dujari
1
Ich habe Ihre Antwort oben auf Tibbits Antwort gelesen. Ich wollte vorschlagen (ich weiß ziemlich spät), Grenzen zu betrachten. Wenn ulimit Ihr Problem ist, können Sie die Änderung entweder mit dem Kernel-Tune-Parameter oder mit Ihrem Betriebssystem mit dieser Datei /etc/security/limits.conf dauerhaft machen und für den Benutzer, der PHP / Web ausführt, ein unbegrenztes Memlock-Limit hinzufügen.
Abhishek Dujari
0

Haben Sie versucht, die Befehlszeilenoption definieren zu verwenden? php -d memory_limit = 512M test.php

Übrigens, haben Sie überprüft, ob die php.ini für den Benutzer lesbar ist, der php über die Befehlszeile ausführt?

olefebvre
quelle
Ich kann bestätigen, dass die php.ini für den Benutzer, der php ausführt, lesbar ist, da ich beim Bearbeiten der darin enthaltenen Werte als dieser Benutzer angemeldet bin. php -d memory_limit=512Merzeugt das gleiche Ergebnis wie das Festlegen des Werts in der Datei php.ini. Vielen Dank für die Vorschläge :)
Jess Telford
1
Zu php -d memory_limit=2G /path/to/test.phpIhrer Information : Ich habe versucht, mit test.php anzurufen, <?php $str = ""; while(true) $str .= "M";?>das Folgendes enthielt: was zu der gleichen Fehlermeldung führte:Fatal error: Out of memory (allocated 362545152) (tried to allocate 362282961 bytes) in /path/to/test.php on line 1
Jess Telford
0

Das Linux-Limit pro Prozess / Benutzer hat damit nichts zu tun. Der Fehler, den Sie erhalten, ist speziell an PHP gebunden.

In diesem Sinne vermute ich, dass es irgendwo eine ini_set-Direktive gibt, die Ihr Limit überschreibt. Selbst wenn Sie ini_set in eine Datei der obersten Ebene einfügen, wird diese von der Datei der unteren Ebene überschrieben.

Führen Sie einfach `grep -r -i" ini_set "/ path / to / piwiki" aus und prüfen Sie, ob das Limit manuell überschrieben wird.

Aleksey Korzun
quelle
Danke für den Tipp. Die Ausgabe von `ack" ini_set "/ path / to / piwik / ist hier: pastebin.com/kDJHLC3e - Sie können in Zeile 47 der Ausgabe sehen, dass Piwik mit memory_limit herumspielt. Nach weiteren Untersuchungen wird lediglich versucht, den Wert zu erhöhen, wenn er zu niedrig ist. Daher hilft es tatsächlich, nicht zu behindern :( Gute Idee!
Jess Telford
1
Nun, es könnte zu niedrig sein;) Wenn überhaupt var_dump ($ minimumMemoryLimit), um zu sehen, auf was es erhöht wird.
Aleksey Korzun
Es erhöhte es auf den erwarteten Wert, den ich in httpd.conf festgelegt hatte - danke für den Gedanken :)
Jess Telford
0

Können Sie bestätigen, in welcher Konfigurationsdatei Sie die Speicherbeschränkungen geändert haben? Beachten Sie, dass es zwei verschiedene Konfigurationen gibt: eine für PHP, das über den Webserver ausgeführt wird, und die zweite für PHP, das über die CLI ausgeführt wird.

~$ ls /etc/php5/
apache2  cli  conf.d
~$ ls /etc/php5/apache2/
conf.d  php.ini
~$ ls /etc/php5/cli/    
conf.d  php.ini

Wenn dies über einen Browser in demselben Verzeichnis ausgeführt wird, in dem sich das eigentliche Skript befindet, erstellen Sie eine temp.php-Datei mit den folgenden Inhalten:

<?php phpinfo(); ?>

Überprüfen Sie, wie das memory_limitangezeigt wird, wenn Sie zu dieser Datei navigieren.

uzzi09
quelle
Das Skript wurde vom Terminal ausgeführt. Wie in der Frage angegeben, php -ibestätigt die Ausgabe von , dass ich memory_limit an der richtigen Stelle gesetzt habe. Vielen Dank für die Eingabe.
Jess Telford
0

Ich habe dieses Problem letzte Woche, meine Lösung in CentOS Rehel ist

nano /etc/httpd/conf/hpptd.conf

Suche RLimitMEM-Direktive löschen oder kommentieren Nein verwendet diese Direktiven oder wenn Verwendung erlauben 2000000 Wert

  • Speichern Sie diese Datei
  • Starten Sie den Dienst neu
  • Service httpd Neustart
Richard
quelle
1
Wie in der Frage erwähnt, habe ich dies bereits ohne Erfolg versucht.
Jess Telford