Erstellen eines Datenbankdumps



  • Hallo zusammen,

    ich habe eine Anwendung unter C++/CLI geschrieben, welche Daten in eine mysql-Datenbank schreibt.
    Wenn die Applikation geschlossen wird, rufe ich mit ProcessInfo eine batch-Datei auf, die einen Datenbankdump erstellt und abspeichert (mysqldump -user=root -p=**** db_name...)
    Das funktioniert alles, jedoch mit dem Nachteil, dass ich das Passwort in die batch-Datei eingeben muss - was ich eigentlich vermeiden möchte.
    system("mysqldump...") funktioniert bei C++/CLI nicht.
    Hat irgendjemand eine andere Idee, die ich umsetzen kann? Ich habe sonst nichts gefunden...
    Vielen Dank für eure Hilfe!



  • @uvbey

    also wenn ich das richtig verstanden habe gehts Dir um ein Backup zum Programmende. Ein diesbezüglicher Code wäre im Destroy (Destruktor) gut aufgehoben. Für sowas habe ich einen proprietären Serializer in Perl der je Tabelle eine Datei serialisiert. Der Algorithmus ist portabel und kann natürlich auch nach c++ umgesetzt werden. Interesse?

    MFG



  • Das Problem bei Batch-Dateien ist, dass das das Passwort im Klartext im mysqldump-Audruf drinsteht und andere Benutzer möglicherweise die Kommandozeile sehen können und damit auch das Passwort. Wenn du der einzige Benutzer auf dem System bist spielt das vielleicht keine Rolle.
    Ich kenne mich mit mySQL nicht aus, aber ich würde das so angehen:

    1. einen mySQL Backup-Benutzer erzeugen, der nur minimale Rechte hat (am Besten darf der außer dumps nix machen)
      2a) die Umgebungsvariable MYSLQ_PWD für den ausführenden (Windows?-Benutzeraccount setzen, keinesfalls für alle Benutzer
      2b) eine mySQL-Parameterdatei (*.cnf) erstellen, vor Zugriff durch andere Benutzer schützen und die Datei per --defaults-file an mysqldump übergeben.

    Hier gibts einen ausführlichen Thread dazu.

    @_ro_ro
    Rofl, im Destruktor des Programms? Lass den Quatsch, du hast keine Ahnung vom Programmaufbau, also bitte nicht mutmaßen oder unbegründete Annahmen treffen. Und ein proprietäres Dateiformat statt Bordmittel? Das schreit nach Problemen.

    Edit:
    Statt system solltest du den Backup-Prozess besser mit CreateProcess erzeugen, wenn du unter Windows unterwegs bist. Vielleicht wirst du damit das Konsolenfenster los.



  • @DocShoe sagte in Erstellen eines Datenbankdumps:

    Statt system solltest du den Backup-Prozess besser mit CreateProcess erzeugen, wenn du unter Windows unterwegs bist. Vielleicht wirst du damit das Konsolenfenster los.

    Er verwendet auch nicht system, da es im context von C++/CLI auch nicht funktioniert, wie er es auch geschrieben hat.
    Der Hinweis mit CreateProcess ist hier der richtige.
    @uvbey : Schau dir dazu mal die .Net Process.Start Methoden an



  • @DocShoe

    ein System-Call Bordmittel? Hab' ich auch noch nicht gehört. Und was soll daran falsch sein, im Destroy (Cleanup) ein Backup zu schreiben? Das machen einige Programme die ich entwickelt habe und die haben sich bewährt.

    Also ein bischen mehr Respekt bitte, von wegen keine Ahnung.

    MFG



  • @_ro_ro sagte in Erstellen eines Datenbankdumps:

    ein System-Call Bordmittel?

    Mit Bordmitteln meine ich die zur MySQL gehörenden Tools (zb. mysqldump). Solange es keine wichtigen Gründe gibt, sie nicht nicht zu benutzen, sollte man sie auch benutzen. Sie sind getestet und haben sich in großen Produktivsystemen bewährt, was bei selbstgebastelten Lösungen nicht immer der Fall ist.

    @_ro_ro sagte in Erstellen eines Datenbankdumps:

    Und was soll daran falsch sein, im Destroy (Cleanup) ein Backup zu schreiben? Das machen einige Programme die ich entwickelt habe und die haben sich bewährt.

    Weil das eine Lösung sein kann. In deinem Fall ist das vielleicht so, aber das ist kein allgemeingültiger Ansatz, zumal du die Programmstruktur des TE auch nicht kennst. In welchem Destruktor soll er denn den Export machen, kannste mir da vielleicht nen konkreten Klassennamen und das passende Objekt dazu nennen?



  • @DocShoe

    ein Trigger wäre auch eine Möglichkeit. Wenn schon eine DB Anbindung dann richtig.

    MFG

    PS: Was den Destruktor betrifft, da gibt es sicher eine Klasseninstanz über die das Programm abgewickelt wird. Zumindest wenn objektorientiert programmiert wird, wird eine solche Instanz zu Programmbeginn erstellt und am Ende des Programms destroyed. Davon bin ich ausgegangen.

    Und noch etwas zu Serializiern die nicht mysqldump heißen und nicht via batch aufgerufen werden:

    https://isocpp.org/wiki/faq/serialization



  • @_ro_ro , DocShoe und firefly:

    erst einmal vielen Dank für eure Hinweise! Ich werde die gleich mal abarbeiten.
    Prinzipiell verwende ich natürlich am liebsten Standard-SW wie mysqldump und schaue mir als erstes CreateProcess und die .Net Process.Start Methoden an.
    Das Problem mit den Windows-Benutzeraccount ist sicherlich, dass ich nicht der Einzige bin, der admin-Rechte auf dem (Vereins-)Rechner hat. Und eigentlich möchte ich die DB gerade vor den anderen Admins schützen. Da ist dann schnell mal etwas verstellt, und schon habe ich dann das Problem... Deshalb wäre ein Aufruf aus dem Programm heraus für mich das Einfachste.
    Ich melde mich, wenn ich weitergekommen bin. Danke schon einmal für eure Unterstützung!



  • @uvbey sagte in Erstellen eines Datenbankdumps:

    Deshalb wäre ein Aufruf aus dem Programm heraus für mich das Einfachste.

    Das meine ich auch. Von welchen Datenmengen reden wir? JSON- oder CSV-Dateien im 2stelligen MB-Bereich sind bestimmt kein Thema und als Datenaustauschformat weitgehend mit Drittprogrammen kompatibel. Viel Erfolg.



  • ..so, ich habe es hinbekommen: 😋

    Process^ myProcess = gcnew Process();
    myProcess->Start("mysqldump",  "--user=root --password=passwd db-name -r pfad/mysqldump_db-name.sql");
    

    Das funktioniert so, wie ich es mir vorgestellt habe. Das einzige, was im Cmd-Fenster für wenige ms erscheint, ist die Meldung, dass das Passwort in dem Befehl unsicher ist...

    Wichtig ist, dass der Speicherort mit "-r ..." angegeben ist. Eine Umleitung ( > ) funktioniert nicht - warum auch immer🤔
    Das hat mich einiges an Zeit gekostet...
    Nochmals vielen herzlichen Dank für eure Unterstützung!!



  • Guck mal hier, man kann das Fenster des gestarteten Prozesses auch verstecken.



  • @DocShoe
    Danke, habe ich eingefügt. Dann habe ich das eigentliche Passwort noch mit ein paar Daten verknüpft und dann einen Hash-Wert daraus berechnet, der mein neues Passwort für die Datenbank darstellt. So steht das DB-Passwort auch nicht im Klartext in der Exe-Datei. Das alles sollte für meine Zwecke vollkommen ausreichend sein 😉



  • ..leider habe ich immer noch ein Problem und hoffe, dass ihr mir dabei helfen könnt:

    Wie geschrieben, funktioniert das ganz gut:

    Process^ myProcess = gcnew Process();
    myProcess->StartInfo->CreateNoWindow = true;
    myProcess->Start("mysqldump",  "--user=root --password=passwd db-name -r pfad/mysqldump_db-name.sql");
    

    ...wobei das mit dem CreateNoWindow doch nicht funktioniert. Bei mir sieht man es manchmal nur kurz aufblitzen, bei unserem langsameren Vereinsrechner ist es schon deutlicher zu sehen. Aber egal, das ist jetzt nicht mein Thema.
    Ich wollte die Ausgabe noch zippen. Als Batchdatei funktioniert folgendes:

    mysqldump --user=root --password=passwd-db db-name  | 7z.exe a  C:/Test/mysqldump.sql.7z -si C:/Test/mysqldump.sql  -ppasswd-7z
    

    Es wird ein 7z-File "mysqldump.sql.7z" generiert.
    Wenn ich das allerdings in meinen obigen Code einfüge, passiert nichts! Keine Fehlermeldung, aber auch keine File-Generierung. mysqldump wird ausgeführt, die DB geöffnet, allerdings kein File abgelegt. Ich vermute mal, dass es etwas mit dem pipe-Befehl zu tun hat. Funktioniert das generell bei Prozessen nicht (ich hatte ja auch das Problem mit dem '>')? Habt ihr eine Idee, was ich noch versuchen könnte?

    Danke und schöne Grüße aus der Südheide



  • @uvbey

    Das "Pipen" der Prozessdaten übernimmt der Konsolenprozess für dich, das myProcess->Start(...) ruft die angegebene Anwendung auf und übergibt ihr stumpf die angegebenen Parameter. Du könntest auf das Prozessende warten und dann mit dem Dateinamen des MySQL-Dumps nach dem gleichen Schema 7z aufrufen. Oder du überlegst was ganz anderes, denn immer den Dump mit dem gleichen Dateinamen zu überschreiben hat auch Beigeschmack.
    Was willst du eigentlich genau erreichen, warum muss am Ende des Programms ein Backup erzeugt werden?



  • ..mein Programm schreibt Anwesenheits- und Trainingsdaten in eine Datenbank, welche lokal auf einem Vereinsrechner läuft. Damit diese Daten auch bei einem Rechnerdefekt oder -fehlbedienung nicht weg sind, wird nach jedem Trainingstag ein Dump erstellt und auf OneDrive abgelegt. So sind die Daten ausreichend gesichert. Das mit dem Zippen habe ich mir überlegt, um einerseits Speicherplatz zu sparen, andererseits auch eine nichtlesbare Datei zu generieren (stehen halt auch Mitgliedernamen drin).
    Mit Deiner Vorgehensweise müsste ich also drei Prozesse starten:

    mysqldump --user=root...
    7z a mysqldump.7z  mysqldump.sql  -ppasswd 
    del mysqldump.sql
    

    ´Schön ist das nicht gerade...

    Edit: Natürlich wird jeder Dump mit einem Datum versehen, so dass wir auch eine Historie haben. Das habe ich hier nur aus Gründen der Vereinfachung nicht mit eingefügt.



  • Bzgl. CreateNoWindow (s. Remarks):
    Wenn du noch .NET Framework verwendest, mußt du noch explizit UseShellExecute = false setzen, da dieser Wert sonst standardmäßig gesetzt ist und dann CreateNoWindow ignoriert wird.

    PS: Schau dir auch mal MySqlBackup.Net an - damit kannst du dann aus deinem Programm heraus einen DB-Dump ausführen.



  • @uvbey

    aus meiner Sicht liegt hier ein grundlegender Fehler im Konzept. Also was die Datensicherung betrifft, die kann doch unabhängig von irgendwelchen Programmaufrufen stattfinden. Und wenn sie an ein Programm gekoppelt wird, dann erschließt sich mir nicht warum man dazu mysqldump als externes Programm aufrufen muss verbunden mit einer expliziten Angabe der Zugangsdaten. Denn: In Deinem Programm ist der Zugang ja bereits hergestellt, also hast Du in Deinem Programm Vollzugriff und kannst mit den Daten auch Backup-Dateien anlegen. Und wie wäre es mit einem dedizierten Backup-Server nach dem Master/Slave-Prinzip?

    MFG



  • Was spricht denn gegen einen Windows Task Scheduler Job oder Shutdown Skript?
    Ich würde tatsächlich einen dedizierten Windows-Benutzer anlegen und die Backups über den Task Scheduler/Shutdown Skript mit diesen Benutzer anlegen. Das geschieht dann im Hintergrund, ohne dass jemand anderes davon was mitbekommt. Vielleicht noch eine Log-Datei dazu schreiben, damit man sieht, ob was schiefgelaufen ist.
    Oder du guckst dich mal nach Professionellen Lösungen um, vielleicht bieten die ihr Produkt als Freeware für eingeschränkten Gebrauch an.



  • @Th69 sagte in Erstellen eines Datenbankdumps:

    UseShellExecute = false

    ..das funktioniert leider auch nicht ☹

    Der Vorschlag, aus dem Programm heraus einen dump zu erstellen, ist sicherlich richtig. Allerdings muss ich dann ja noch ein Zip-Programm installieren / einbinden, welches (aus dem Programm heraus) die Daten zippt und die (temporäre ) sql-Datei dann wieder löscht. Ich denke, das übersteigt meine Fähigkeiten und kostet mich auch zu viel Zeit, mir das alles anzueignen (Ich bin noch mit Fortran 4 groß geworden 😉 ).

    @DocShoe: Das mit dem Windows Task Scheduler war übrigens mein erster Ansatz und war bis vor kurzem in Betrieb. Allerdings stellt sich dann wieder die Frage, wie ich mit dem Passwort umgehen soll. Die Herausforderung ist ja, dass sich auf dem Vereinsrechner mehrere Admins tummeln, denen ich nicht unbedingt die Kontrolle über die Datenbank geben möchte. Manche spielen doch gerne etwas herum, ohne dass sie genau wissen, was sie da tun... Und persönliche Bereiche sind auf dem Vereinsrechner unerwünscht, das muss ich respektieren.
    Ich versuche doch mal den Ansatz, einen Dump zu erstellen, dann ihn zu zippen und den Ursprungsdump wieder zu löschen...



  • Moin.
    Ich habe das Programm jetzt wie folgt angepasst:

    Process^ myProcess = gcnew Process();
    myProcess->StartInfo->UseShellExecute = false;
    myProcess->StartInfo->CreateNoWindow = true;
    myProcess->Start("mysqldump", "--user=dumpuser --password=passwd db-name -r pfad/mysqldump_db-name.sql");						// sql-dump erstellen
    Sleep(100);
    myProcess->Start("7z", "a  pfad/mysqldump_db-name.sql.7z  pfad/mysqldump_db-name.sql -ppasswd-7z");							// sql-dump zippen
    Sleep(100);
    std::remove("pfad/mysqldump_db-name.sql");							// sql-dump löschen
    

    Das Endergebnis ist perfekt: Es liegt ein gezippter und mit dem Passwort 'passwd-7z' verschlüsselter Datenbankdump vor. Unschön ist, dass zweimal die Cmd-Fenster kurz auftauchen - auch wenn nichts sicherheitsrelevantes drin steht. Auch funktioniert beispielsweise:

    myProcess->WaitForExit(100);
    

    überhaupt nicht. Anstelle von "Sleep(100)" eingesetzt werden keine weiteren Prozesse mehr gestartet.
    Hat da noch jemand eine Idee?


Anmelden zum Antworten