{"id":627,"date":"2025-10-17T23:26:08","date_gmt":"2025-10-17T21:26:08","guid":{"rendered":"https:\/\/schoppe.it\/wiki\/?p=627"},"modified":"2025-10-17T23:48:23","modified_gmt":"2025-10-17T21:48:23","slug":"automatisiertes-mysql-backup-mit-upload-auf-einen-ftp-server","status":"publish","type":"post","link":"https:\/\/schoppe.it\/wiki\/automatisiertes-mysql-backup-mit-upload-auf-einen-ftp-server\/","title":{"rendered":"Automatisiertes MySQL-Backup mit Upload auf einen FTP-Server"},"content":{"rendered":"\n<h3 class=\"wp-block-heading\">Funktionsweise<\/h3>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Datenbank sichern<\/strong><br>Mit <code>mysqldump<\/code> wird die angegebene Datenbank konsistent exportiert. Dabei werden auch Routinen und Events gesichert.<br>Der Output wird direkt mit <code>gzip<\/code> komprimiert und in einem Unterverzeichnis von <code>\/var\/backups\/sql_backups<\/code> abgelegt.<\/li>\n\n\n\n<li><strong>Alte Backups bereinigen<\/strong><br>Backupdateien, die \u00e4lter als 14 Tage sind, werden automatisch gel\u00f6scht.<br>Das geschieht \u00fcber den Befehl: <code>find \"$BACKUP_DIR\" -type f -name \"*.sql.gz\" -mtime +14 -exec rm {} \\;<\/code><\/li>\n\n\n\n<li><strong>FTP-Upload (passiv &amp; verschl\u00fcsselt)<\/strong><br>Der Upload erfolgt mit <code>lftp<\/code>. Das Skript nutzt <strong>passiven FTP-Modus<\/strong> und erzwingt <strong>TLS-Verschl\u00fcsselung<\/strong> (FTPS).<br>Damit ist die \u00dcbertragung sowohl NAT-freundlich als auch sicher.<br>Auf dem Zielserver wird das Verzeichnis automatisch angelegt, falls es noch nicht existiert.<\/li>\n<\/ol>\n\n\n\n<h3 class=\"wp-block-heading\">Skript<\/h3>\n\n\n\n<p>Die Bash-Datei erstellen mit nano.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: bash; title: ; notranslate\" title=\"\">\nnano \/var\/backups\/backup.sh\n<\/pre><\/div>\n\n\n<p>Und das folgende Skript einf\u00fcgen und anpassen.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: bash; title: ; notranslate\" title=\"\">\n#!\/bin\/bash\n\n# === Einstellungen ===\nDB_NAME=&quot;db_name&quot;\nDB_USER=&quot;db_user&quot;\nDB_PASS=&quot;db_password&quot;\nBACKUP_DIR=&quot;\/var\/backups\/sql_backups&quot;\nDATE=$(date +&quot;%Y-%m-%d_%H-%M&quot;)\nBACKUP_FILE=&quot;$BACKUP_DIR\/${DB_NAME}_$DATE.sql.gz&quot;\n\n# === Lokales Backup erstellen ===\nmkdir -p &quot;$BACKUP_DIR&quot;\nmysqldump \\\n  --single-transaction --quick --routines --events \\\n  --no-tablespaces \\\n  -u&quot;$DB_USER&quot; -p&quot;$DB_PASS&quot; &quot;$DB_NAME&quot; | gzip &gt; &quot;$BACKUP_FILE&quot;\n\n# === Alte lokale Backups l\u00f6schen (\u00e4lter als 14 Tage) ===\nfind &quot;$BACKUP_DIR&quot; -type f -name &quot;*.sql.gz&quot; -mtime +14 -exec rm {} \\;\n\n# === FTP Upload ===\nFTP_SERVER=&quot;ip-adresse-ftp-server&quot;\nFTP_USER=&quot;ftp_user&quot;\nFTP_PASS=&quot;ftp_password&quot;\nFTP_DIR=&quot;RemoteBackups\/sql_backups&quot;\n\nlftp -u &quot;$FTP_USER&quot;,&quot;$FTP_PASS&quot; &quot;$FTP_SERVER&quot; &lt;&lt;EOF\nset ftp:passive-mode on\nset ftp:ssl-allow yes\nset ftp:ssl-force yes\nset ftp:ssl-protect-data yes\nset ftp:sync-mode no\nset ssl:verify-certificate no\nset ssl:check-hostname no\nmkdir -p $FTP_DIR\ncd $FTP_DIR\nput $BACKUP_FILE\nbye\nEOF\n<\/pre><\/div>\n\n\n<p>Das Skript ausf\u00fchrbar machen.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\nchmod +x \/var\/backups\/backup.sh\n<\/pre><\/div>\n\n\n<p>Einen Cronjob f\u00fcr die automatische Ausf\u00fchrung erstellen. Mit flock wird verhindert, dass mehrere Backup Jobs gleichzeitig laufen. Au\u00dferdem erfolgt eine Ausgabe der Fehler in eine Log-File.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: bash; title: ; notranslate\" title=\"\">\n0 1 * * * flock -n \/var\/lock\/backup.lock \/bin\/bash \/var\/backups\/sql_backup\/backup.sh &gt;&gt; \/var\/log\/sql_backup.log 2&gt;&amp;1\n<\/pre><\/div>\n\n\n<h3 class=\"wp-block-heading\">Hinweise<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Der FTP-Server sollte <strong>passiven Modus (PASV)<\/strong> unterst\u00fctzen.<br>Nur so funktionieren Verbindungen zuverl\u00e4ssig hinter NAT-Routern oder Firewalls.<\/li>\n\n\n\n<li>F\u00fcr zus\u00e4tzliche Sicherheit kann auf dem Zielserver <strong>FTPS (explizit \u00fcber Port 21)<\/strong> aktiviert werden.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Ergebnis<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Lokales Backup: <code>\/var\/backups\/sql_backups\/db_name_YYYY-MM-DD_HH-MM.sql.gz<\/code><\/li>\n\n\n\n<li>Remote-Backup: <code>RemoteBackups\/sql_backups\/<\/code> auf dem FTP-Server<\/li>\n<\/ul>\n\n\n\n<p>Das Skript ist stabil, einfach erweiterbar und eignet sich ideal, um Datenbanken automatisiert zu sichern und Offsite-Backups bereitzuhalten.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Backup von Datenbank und Webdaten<\/h3>\n\n\n\n<p>Das nachfolgende Skript sichert auch die Webdaten.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: bash; title: ; notranslate\" title=\"\">\n#!\/bin\/bash\n\n# === Einstellungen ===\nDB_NAME=&quot;db_name&quot;\nDB_USER=&quot;db_user&quot;\nDB_PASS=&quot;db_password&quot;\nBACKUP_DIR=&quot;\/var\/backups\/sql_backups&quot;\nDATE=$(date +&quot;%Y-%m-%d_%H-%M&quot;)\nSQL_BACKUP_FILE=&quot;$BACKUP_DIR\/${DB_NAME}_$DATE.sql.gz&quot;\n\nmkdir -p &quot;$BACKUP_DIR&quot;\n\n# MySQL-Dump erstellen\nmysqldump \\\n  --single-transaction --quick --routines --events \\\n  --no-tablespaces \\\n  -u&quot;$DB_USER&quot; -p&quot;$DB_PASS&quot; &quot;$DB_NAME&quot; | gzip &gt; &quot;$SQL_BACKUP_FILE&quot;\n\n# Web-Backup\nWEB_SRC_DIR=&quot;\/var\/www&quot;\nWEB_BACKUP_FILE=&quot;$BACKUP_DIR\/presta_web_$DATE.tar.gz&quot;\n\n# === Webroot packen (Caches auslassen) ===\n# Passe die Excludes bei Bedarf an deine Struktur an.\ntar -C &quot;$(dirname &quot;$WEB_SRC_DIR&quot;)&quot; \\\n  --exclude=&quot;$(basename &quot;$WEB_SRC_DIR&quot;)\/var\/cache\/*&quot; \\\n  --exclude=&quot;$(basename &quot;$WEB_SRC_DIR&quot;)\/var\/logs\/*&quot; \\\n  --exclude=&quot;$(basename &quot;$WEB_SRC_DIR&quot;)\/log\/*&quot; \\\n  -czf &quot;$WEB_BACKUP_FILE&quot; &quot;$(basename &quot;$WEB_SRC_DIR&quot;)&quot;\n\n# === Alte lokale Backups (\u00e4lter als 14 Tage) l\u00f6schen ===\nfind &quot;$BACKUP_DIR&quot; -type f \\( -name &quot;*.sql.gz&quot; -o -name &quot;web_*.tar.gz&quot; \\) -mtime +14 -exec rm -f {} \\;\n\n# === FTP Upload ===\nFTP_SERVER=&quot;ip-adresse-ftp-server&quot;\nFTP_USER=&quot;ftp_user&quot;\nFTP_PASS=&quot;ftp_password&quot;\nFTP_DIR=&quot;RemoteBackups\/sql_backups&quot;\n\nlftp -u &quot;$FTP_USER&quot;,&quot;$FTP_PASS&quot; &quot;$FTP_SERVER&quot; &lt;&lt;EOF\nset ftp:passive-mode on\nset ftp:ssl-allow yes\nset ftp:ssl-force yes\nset ftp:ssl-protect-data yes\nset ftp:sync-mode no\nset ssl:verify-certificate no\nset ssl:check-hostname no\n\nmkdir -p $FTP_DIR\ncd $FTP_DIR\n\nput -c &quot;$SQL_BACKUP_FILE&quot;\nput -c &quot;$WEB_BACKUP_FILE&quot;\n\nbye\nEOF\n\n<\/pre><\/div>","protected":false},"excerpt":{"rendered":"<p>Dieses Bash-Skript erstellt regelm\u00e4\u00dfig ein komprimiertes Backup einer MySQL-Datenbank, speichert es lokal ab und l\u00e4dt es anschlie\u00dfend verschl\u00fcsselt auf einen entfernten FTP-Server hoch.<br \/>\nAlte lokale Backups werden automatisch gel\u00f6scht, sodass der Speicherverbrauch kontrolliert bleibt.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[118,119,180],"tags":[],"powershell":[],"wordpress":[],"exchange":[],"linux":[186,228,226,227,121],"class_list":["post-627","post","type-post","status-publish","format-standard","hentry","category-linux","category-postgresql","category-prestashop","linux-chmod","linux-lftp","linux-mkdir","linux-mysqldump","linux-nano","entry"],"_links":{"self":[{"href":"https:\/\/schoppe.it\/wiki\/wp-json\/wp\/v2\/posts\/627","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/schoppe.it\/wiki\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/schoppe.it\/wiki\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/schoppe.it\/wiki\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/schoppe.it\/wiki\/wp-json\/wp\/v2\/comments?post=627"}],"version-history":[{"count":3,"href":"https:\/\/schoppe.it\/wiki\/wp-json\/wp\/v2\/posts\/627\/revisions"}],"predecessor-version":[{"id":631,"href":"https:\/\/schoppe.it\/wiki\/wp-json\/wp\/v2\/posts\/627\/revisions\/631"}],"wp:attachment":[{"href":"https:\/\/schoppe.it\/wiki\/wp-json\/wp\/v2\/media?parent=627"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/schoppe.it\/wiki\/wp-json\/wp\/v2\/categories?post=627"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/schoppe.it\/wiki\/wp-json\/wp\/v2\/tags?post=627"},{"taxonomy":"powershell","embeddable":true,"href":"https:\/\/schoppe.it\/wiki\/wp-json\/wp\/v2\/powershell?post=627"},{"taxonomy":"wordpress","embeddable":true,"href":"https:\/\/schoppe.it\/wiki\/wp-json\/wp\/v2\/wordpress?post=627"},{"taxonomy":"exchange","embeddable":true,"href":"https:\/\/schoppe.it\/wiki\/wp-json\/wp\/v2\/exchange?post=627"},{"taxonomy":"linux","embeddable":true,"href":"https:\/\/schoppe.it\/wiki\/wp-json\/wp\/v2\/linux?post=627"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}