Linux – mysqldump sieht Leerzeichen als leeren Datenbanknamen an

Erinnert Ihr Euch noch an diesen Beitrag : Solution – mysqldump – No database selected when selecting the database aus dem Jahr 2016 ?

MariaDB & mysqldump

Damals stolperte ich über einen Fehler im Kommandozeilenparsing von Mysqldump.

Wie sich herausgestellt hat, konnte der Betreuer Michael Scholm bei Redhat die Ursache für das Problem entdecken. Kommt Ihr nie drauf: Das  war Schuld ! Oh ?! Ihr habt es nicht gesehen, hier nochmal  . Vielleicht mit der Lupe, da: > <. Ein Space.  Hier … zwischen dem „usr/bin/mysqldump“ und dem „–addlocks“ ist ein “ “ zuviel drin:

/usr/bin/mysqldump  --add-locks -e --force -R ....

Da es keine Option ist, wird es tatsächlich als valider Versuch, einen Datenbanknamen anzugeben gewertet.IMHO, ein Parser-Logik-Bug. Redhat sieht das anders: „not a bug“. Da jetzt raus ist, was es verursacht, kann man es ja leicht beheben.

etwas Kontext

Die Parser für Linux sind, sagen wir mal, ein bisschen eigen und deren Interpretation auch. Als Trenner zweier Argumente einer Kommandozeile gilt ein freistehendes Leerzeichen. Die Bash-Shell entfernt doppelte Leerzeichen und setzte ein Leerzeichen an die Stelle. So ein Leerzeichen zu viel ist schnell getippt und würde zu vielen „Dicke Finger-Syndrom“-Problemen führen, weil ..

… Ja, weil der Parser ohne diesen Trick, zwei Leerzeichen in Folge so übersetzen :

ls -la  foo => ls -la "" foo

Weil „Leerzeichen“ sind Trenner, also steht da oben eigentlich: „ls{Trenner}-la{Trenner}{Trenner}foo .

Wenn man aber zwischen den Trennern nichts hat, dann kommt ein leeres Argument raus. Was ein leeres Argument bedeutet, zeigt sich hier im Beispiel:

[marius ~]$ ls -la "" foo
ls: Zugriff auf '' nicht möglich: No such file or directory
ls: Zugriff auf 'foo' nicht möglich: No such file or directory

Wie man sehen kann versucht ls tatsächlich auf aka. „“ zuzugreifen. Wie das gehen soll ? Gar nicht. Ist ein Logikbug im Kontext von ls . Es wiederspricht der Natur eines ls , etwas aufzulisten, das es nicht gibt. Ergo müßte das Argument ignoriert werden. Jeder Mensch würde das so machen. Computerprogramme sind in der Beziehung blöde. Deswegen gibt es die Bash, die das Doppel-Leerzeichen wegnormaliziert und so vorhersehbare Fehler vermeidet, weil ..

Fehler vermeiden

wie man im obigen ls Beispiel gesehen hat, kann man es ja explizit angeben, wenn man muß => „“ oder “

MariaDB zieht sich jetzt auf den Standpunkt zurück, daß mysqldump sich ja nur wie ls verhalten würde. Tut es natürlich nicht, weil mysqldump komplett failed, wo ls einfach weitermacht und einen Fehler ausgibt.  Naja, Nobodys perfect.

Update

… oh, Redhat hat die Meinung geändert und einen Featurerequest bei MariaDB für einen besseren Parser erstellt. \o/ Das gibt einen dicken Daumen rauf! Mal sehen wies bei MariaDB ausgeht.

Solution – mysqldump – No database selected when selecting the database

International shortform:

Hi, if you reached this page, because it’s one of five webpages regarding this specific error message, please scroll down to the end.

Und für alle anderen, die lange Form:

Die Shell kann komisch sein, aber die Abwesenheit der Bashshell ist noch zu viel komischeren Sachen fähig, eine davon ist der Bug von Mysqldump keine Datenbank angegeben zu haben.

Hintergrund: Wenn man in Java mit Exec() einen Befehl startet, hat man keine Shell vor sich und damit auch eine Menge Sicherheitsprobleme nicht mehr. Nachteil : u.a. „*“ wird nicht mehr funktionieren, denn das wird von der Bash geparst. Keine Bash => Kein „*“ Keine „<>“ .

Das kennt man noch. Was jetzt kommt, ist allerdings extrem schwer zu debuggen, deswegen bin ich auch ein klein bisschen stolz als einziger im Netz eine Lösung präsentieren zu können, auch wenn die eher trivialer Natur ist. Sucht mal nach der Fehlermeldung, es gibt nur 4 Seiten, die diese Meldung behandeln 😉 (OK, jetzt 5 )

Das hier ist der Befehl:

/usr/bin/mysqldump  --add-locks -e --force -R --triggers --add-drop-table --hex-blob -h localhost --password=dbpass --user=dbuser dbname;

Das erzeugt die Fehlermeldung :

mysqldump: Got error: 1046: No database selected when selecting the database

obwohl eine Datenbank angegeben ist. Gibt man den  Befehl in die Shell ein, geht es sofort ohne Anpassungen. Kleine Anmerkung, auf die Fehlermeldung an sich muß man geistig erstmal kommen, richtig wäre nämlich „no databasename given“

Wie löst man das jetzt, wenn man doch schon alles richtig angegeben hat ?

Na man drückt dem Befehl die Pistole auf die Brust, so daß er sich nicht mehr herausreden kann ;D

/usr/bin/mysqldump  --add-locks -e --force -R --triggers --add-drop-table --hex-blob -h localhost --password=dbpass --user=dbuser --databases dbname

Der kleine Zusatz „–databases“ ist eigentlich dazu da, mehr als eine Datenbank in einen SQL-Dump zu integrieren. Es geht aber auch nur mit einer einzigen Datenbank und komischerweise kommt der Parser jetzt nicht mehr durch einander und erkennt die Datenbank am Ende des Befehls. Es gibt so bescheuerte Bugs 😀

Ok, Hello there.  You found this page, because it’s the only one marked as solution to the problem, that you give mysqldump a databasename and it says, that you did not. It’s a bug that occurs only in the absence of bash. You counter it by adding „–databases “ infront of your databasename. See the above example if your uncertain how to do it.

If you wanne see more articles in english, please leave a comment about it. Cu.