PHP Komisches Phänomen (bei SQL-Inserts) - keine Fehlermeldung

Novar

Banned
Registriert
Juni 2022
Beiträge
248
Hallo zusammen,

habe ein "kleines" Problem und stehe irgendwo völlig auf dem Schlauch:
Hier ist ein kleines SMS-Gateway (kleiner NUC-Rechner mit Ubuntu drauf), das seit Jahren in unterschiedlichen Projekten eingesetzt wird. Über ein PHP-Script werden die entsprechenden Parameter (Rufnummer des Empfängers, SMS-Text) entgegen genommen, geprüft und am Ende sowohl in eine Datenbank (mariadb) eingetragen als auch die Files (für den Linux-Dienst "smstools") angelegt. Ebenfalls wird direkt die ID (des Datenbankeintrags) ausgegeben, um den Status der Nachrichten nachträglich überwachen/prüfen zu können.

Gestern habe ich das System aktualisiert (von Ubuntu 16.04 auf 20.04) - es läuft eigentlich auch noch alles so, wie es soll.
Alleine die SQL-Inserts (im Gegensatz zu SELECT-Querys) hauen nicht mehr hin; Scripte werden im Anschluss ohne(!) Fehler einfach beendet. Mir ist völlig unklar, weshalb.
Vorab - folgende Zeilen wurden selbstverständlich schon längst eingepflegt:
Code:
error_reporting(E_ALL | E_STRICT);
ini_set("display_errors", 1);

Bis zu folgender Stelle passt alles, aber dann...:
Code:
    //Trage Datensatz in die Datenbank ein
        $insert_stmt = $mysqli->prepare("INSERT INTO sms_outgoing (handynr, message, filename) VALUES (?, ?, ?)");
        $insert_stmt->bind_param('sss', $handynr, $smstext, $dataname);
        //Fuehre die vorbereitete Anfrage aus.
        if (! $insert_stmt->execute()) {
            echo "<p>Fehler mit der Datenbank: Bitte Info an blabla@blub.de</p>";
        }

Es treten keine Fehler beim Aufruf der php-Datei auf (außer eben das von mir definierte echo).
Es treten auch keinerlei Fehler im error.log (Datenbank als auch Webserver) auf.

What the fuck? :D
 
Ist das aus einer Web-App? Wenn ja, dann ist display_errors ist eine schlechte Idee. Schließlich sollen Endnutzer keine internen PHP-Fehler zu sehen bekommen. Besser wäre display_errors=0, log_errors=1 und error_log=syslog (oder ein Dateiname).

Was heißt "Scripte werden im Anschluss ohne(!) Fehler einfach beendet". Wenn du ein error_log("Test Start"); genau vor dem prepare Aufruf einfügst landet das im Log? Und ein error_log("Test Ende"); direkt hinter der if mit dem execute() nicht mehr? Bist du sicher dass das schreiben in die error.log auch funktioniert?
 
  • Gefällt mir
Reaktionen: madmax2010
Marco01_809 schrieb:
Wenn ja, dann ist display_errors ist eine schlechte Idee. Schließlich sollen Endnutzer keine internen PHP-Fehler zu sehen bekommen.
Weil hier aber ein (hinlänglich beschriebener) Fehler vorliegt, dessen Ursache ich nicht eingrenzen kann, ist es doch vielmehr eine sehr gute Idee, PHP-Fehler auch explizit anzeigen zu lassen...

Marco01_809 schrieb:
Was heißt "Scripte werden im Anschluss ohne(!) Fehler einfach beendet".
Das heißt, dass keinerlei Fehler - ob php oder sql... - in Erscheinung treten oder ausgegeben werden.

Habe mich aber an dieser Stelle unklar ausgedrückt: Das Script an sich läuft natürlich bis zum Ende hin durch, bringt aber effektiv nichts weil der Insert-Befehl nicht umgesetzt wird.
 
Wird der ausgeschnittene Code denn sicher auch ausgeführt? Ich empfehle erneut einen error_log() Aufruf unmittelbar davor/danach einzufügen.
 
Einziger offensichtlicher Fehler ist das du 3 Parameter im Query hast, aber 4 Parameter binden willst.
Nvm, das ist die Typ-Annotation.

Der Rückgabewerte von execute() ist jetzt auch nicht die zuverlässigste Methode um zu gucken ob der Query wirklich richtig in der Datenbank angekommen ist.
Vielleicht mal ganz stumpf mit nem hart hinterlegtem Insert testen von dem du weißt dass der auch gültig ist.
 
Marco01_809 schrieb:
Wird der ausgeschnittene Code denn sicher auch ausgeführt?
Ja, andernfalls meine echo-Ausgabe (Fehler mit der Datenbank: Bitte Info an...) nicht ausgegeben werden würde.
Ergänzung ()

Joshinator schrieb:
Einziger offensichtlicher Fehler ist das du 3 Parameter im Query hast, aber 4 Parameter binden willst.
Nein, will ich nicht.
Wie kommst du darauf, ich würde 4 Parameter binden wollen?

Joshinator schrieb:
Der Rückgabewerte von execute() ist jetzt auch nicht die zuverlässigste Methode um zu gucken ob der Query wirklich richtig in der Datenbank angekommen ist.
execute() gibt true zurück, wenn erfolgreich - und false, wenn nicht erfolgreich.

Eine in der Regel durchaus zuverlässige Methode.
 
Ach ja OK wenn die false zurückgibt gibt es ja doch einen Fehler - MySQLi reported aber standardmäßig nicht von selbst Fehler, sondern gibt nur den boolean Rückgabewert. Siehe https://www.php.net/manual/en/mysqli-driver.report-mode.php
Es empfiehlt sich den report mode auf ERROR | STRICT oder ALL zu setzen, damit MySQL-Fehler als Exception geworfen werden - lässt sich dann einfacher debuggen und das Script macht nicht einfach mit undefiniertem Verhalten weiter wenn ein Fehler nicht an Ort und Stelle behandelt wird.

Lass dir in der if mal $mysqli->error_list ausgeben, z.B. mit var_dump oder print_r.
 
Marco01_809 schrieb:
Lass dir in der if mal $mysqli->error_list ausgeben, z.B. mit var_dump oder print_r.
Habe ich eben erneut getan, wurde schon vor Stunden probiert.
Die "Seite" bleibt leer.
Einzige Ausgaben sind mein Echo-Hinweis, dass es ein Problem gibt und danach nochmals "Message-ID:", die ganz am Ende vom Script ausgegeben wird - aber ohne ID, natürlich, weil vorausgehend ja kein Eintrag in der Datenbank erstellt wurde... :D

Ich bin kurz davor nen Backup zurück zu schieben. Hab die Platte geklont, ehe ich das System aktualisiert habe.... aber ich denk mir halt, dass es das doch nicht sein kann.
An den ganzen Scripten wurde auch nichts verändert, die wurden seit zwei/drei Jahren nicht mehr angefasst. An php hat sich nichts geändert, auch davor lief bereits php 7.2 drauf. Kann es nicht nachvollziehen...
 
Also bleibt die Seite leer oder ist da deine Meldung aus Zeile 6? Wenn du das var_dump unmittelbar nach dem echo einfügst dann muss die Ausgabe auch erscheinen. Selbst wenn das error_list array leer ist gibt var_dump immer noch array(0) {} aus.

Wenn die Ausgabe von var_dump wirklich nicht erscheint, dann bleibt nur dass der ausgeschnittene Code gar nicht ausgeführt wird sondern die Meldung von einer anderen Stelle kommt - ich vermute es gibt noch mehr Stellen im Code an denen !execute() geprüft wird mit genau der gleichen Fehlermeldung?
Marco01_809 schrieb:
Ich empfehle erneut einen error_log() Aufruf unmittelbar davor/danach einzufügen.
Damit wäre auch getestet ob euer error logging in die Datei überhaupt funktioniert. Bei einem Server/OS-Umzug kommen mir da direkt Dateirechte in den Sinn.
 
Marco01_809 schrieb:
Wenn du das var_dump unmittelbar nach dem echo einfügst dann muss die Ausgabe auch erscheinen.
Das tut sie auch, aber halt ohne Inhalt.
Einfach nur "Array ( )".

Marco01_809 schrieb:
ich vermute es gibt noch mehr Stellen im Code an denen !execute() geprüft wird mit genau der gleichen Fehlermeldung?
Nope.
In php prüfe ich execute nur bei Inserts - und das ist der einzige php-seitige Insert. Bei den paar weiteren Select-Abfragen in anderen Scripten sehe ich ja ohnehin sofort, ob ich ein Ergebnis erhalte. :D

Per bash-script gäbs dann noch paar UPDATE-Querys, die bei Statusveränderungen (z.B. wenn eine Nachricht zugestellt wurde) eben jenes im entsprechenden Datensatz aktualisieren. Aber das ist erstmal völlig unabhängig von dem hier vorgestellten Problem.
 
Problem "gelöst".
Habe das vorausgehend angelegte Image wieder zurück gespielt - nachdem der SQL-Insert weder über phpmyadmin noch über das terminal/putty direkt in der Datenbank irgendwas bewirkte und auch hier KEINERLEI(!) Fehler ausgegeben wurden...

Was weiß ich was da abging.
Image zurück gespielt, wieder update, upgrade, Anpassung der source.list, anschließendes dist-upgrade und abschließenden Reboot durchgeführt. Also alles so gemacht, wie davor auch.

Nur dieses mal gibts keine Probleme, es funktioniert alles.
Vermutlich hätte es gereicht, mysql vom System zu werfen, neu zu installieren und den db-dump rein zu werfen. Aber ist mir jetzt auch egal... :D

Danke dennoch für eure Zeit.
 
Zurück
Oben