Ich habe ein Skript, das jede Nacht von einem Cron-Job läuft. In letzter Zeit hat es nach einigen Minuten völlig eingefroren angefangen, und ich kann nicht verstehen warum. Wenn dies Java wäre, könnte ich einfach kill -3 PID
ausführen und es würde einen Thread-Dump in stdout ausgeben. Gibt es eine Entsprechung in PHP, wo ich einen Dump der aktuellen Stack-Trace (und idealerweise Speicher-Info) auf einem laufenden PHP-Skript erhalten könnte?
Das Beste, was Sie tun können, ist, PHP selbst mit --enable-debug
während configure
zu kompilieren. Wenn der Prozess dann noch nicht reagiert, können Sie mithilfe von gdb und einigen Makros einen Stacktrace auf PHP-Ebene mithilfe der folgenden Schritte erstellen:
Und dann debug im Voraus: -)
Beachten Sie, dass dafür eine PHP-Binärdatei mit Symbolinformationen erforderlich ist, --enable-debug
stellt dies sicher.
Ja. Sie können ein Backtrace mit debug_backtrace
erhalten. Möglicherweise benötigen Sie auch memory_get_usage
.
Sofern Sie gdb- und debugging-Symbole für PHP installiert haben, können Sie eine vollständige PHP-Rückverfolgung erhalten.
Die Methode zum Installieren von Debugging-Symbolen kann von Distribution zu Distribution variieren. Zum Beispiel lief ich auf Amazon Linux rpm -qa | grep php56-common
und übergab das Ergebnis an debuginfo-install
. Beachten Sie, dass das Installieren von Debugging-Symbolen mit dem Standard-Paket-Manager möglicherweise nicht das gewünschte Ergebnis bringt - bei Amazon Linux habe ich Debugging-Symbole für eine andere PHP-Version erhalten, wenn yum install php56-debuginfo
und gdb das nicht taten.
Wenn Sie Ihren Computer so konfiguriert haben, dass Core-Dumps erstellt werden , brauchen Sie den Prozess nicht einmal laufen, um ein Backtrace zu bekommen. Sie können kill -ABRT $pid
und den Core Dump später überprüfen.
Sie können dann einen laufenden Prozess mit gdb -p $pid
oder einen Core-Dump mit gdb /usr/bin/php $path_to_core_dump
debuggen.
Wenn Sie bt
eingeben, erhalten Sie einen C-Stack-Trace. Dies wird manchmal genug sein, um Ihnen einen Hinweis darauf zu geben, was falsch sein könnte. Stellen Sie sicher, dass die Debugsymbole korrekt installiert sind. bt
sollte auf Dateinamen und Zeilennummern im PHP-Quellcode zeigen.
Probieren Sie jetzt p executor_globals.current_execute_data
. Es sollte etwas wie = (struct _zend_execute_data *) 0x7f3a9bcb12d0
ausgeben. Wenn dies der Fall ist, kann gdb die Interna von PHP überprüfen.
Mit ein wenig Python-Skripting können Sie ein komplettes PHP-Backtrace erstellen. Geben Sie python-interactive
ein und fügen Sie dann dieses kleine Skript ein:
Beachten Sie, dass diese Methode stark von den Interna von PHP abhängt, daher funktioniert sie bei früheren oder späteren Versionen möglicherweise nicht. Ich habe das mit PHP 5.6.14 gemacht. Der Vorteil dieser Methode ist, dass sie sowohl für laufende Prozesse als auch für Core-Dumps funktioniert. Außerdem müssen Sie PHP nicht neu kompilieren oder Ihr PHP-Skript neu starten. Sie können sogar gdb und Debugging-Symbole installieren nachdem Sie einen hängenden Prozess entdecken.
Ein PHP-Skript sollte einen Timeout haben, wenn es die maximale Laufzeit überschreitet. Sicher würde das das Problem für dich lösen; warte nur darauf, dass es kaputtgeht, und da ist deine Stack-Spur.
Ich denke, es ist möglich, dass Sie etwas in Ihrem Code (oder php.ini) haben, das die maximale Laufzeit auf Null setzt, um das Brechen zu stoppen. Wenn Sie das haben, dann entfernen Sie es (oder setzen Sie es auf ein sehr großes Timeout, wenn der Standard wirklich zu klein ist).
Sie können auch versuchen, es mit xDebug oder einem ähnlichen Tool auszuführen, das Ihnen einen Profiler-Trace liefert, der Ihnen einen Aufrufbaum des Programms gibt, und Ihnen auch erlaubt, den Code in Ihrer IDE durchzugehen Sie können genau sehen, was passiert. Wenn dort eine Endlosschleife ist, sollten Sie in der Lage sein, sie ziemlich schnell zu identifizieren.
Tags und Links php