NEWS
[Vorlage] Synchronisation / Backup von Fileserver in Cloud und Erfolgsanzeige in VIS
-
ACHTUNG: Man sollte für folgendes auf jeden Fall (Grund)kenntnisse von JavaScript und Shell-Programmierung und Linux mitbringen, sowie vorher ein Backup der Daten machen.
Hi,
ich bin noch nicht so lange in der Linux-Welt unterwegs, aber mag es, mit Scripts Dinge zu steuern :)
Daher möchte ich gerne mit der ioBroker-Community meine Vorgehensweise teilen. Sicherlich alles andere als perfekt, aber es läuft 8-)
Das ganze hat mich etwas Zeit gekostet, vor allem mich einzuarbeiten in Bash, wie Linux tickt, Proxmox, etc. Ist für mich ein nettes Hobby.
<size size="150">Ausgangssituation / Use Case:</size>
Auf einem Linux-Server (bei mir: Proxmox-Virtualisierung) liegen Dateien, die ich Nachts in die Cloud (bei mir: Microsoft OneDrive) synchronisieren möchte. In VIS möchte ich sehen, ob die Synchronisierung erfolgreich lief, also sichergestellt ist, dass ein Backup in die Cloud erfolgte.
<size size="150">Durchführung:</size>
Tools:
-
https://rclone.org/ - sehr mächtig und kann mit vielen Clouds umgehen.
-
https://github.com/ioBroker/ioBroker.simple-api/blob/master/README.md
Bei mir läuft auf einem Proxmox-Container ein Turnkey-Fileserver mit Samba. Im Endeffekt sollte hier eine typische Linux-Umgebung vorliegen.
Auf diesem Container habe ich rclone installiert und über die Kommandozeile entsprechend eingerichtet und die Cloud entsprechend konfiguriert.
Auf der Weboberfläche vom Turnkey-Fileserver habe ich dann entsprechende CronJobs eingerichtet, hier ein Bash-Script-Beispiel, das bei mir jede Nacht läuft. Das Script habe ich in eine Datei gepackt und auf dem Fileserver abgelegt und der CronJob führt es aus.
#!/bin/bash # Variablen DATENOW=`date '+%Y-%m-%d_%H-%M-%S'`; LOCKDIR="/_myshare/_my-cron-jobs/mylock_onedrive_crypto" # Um zu prüfen, dass das Script nicht zweimal gleichzeitig ausgeführt wird. LOGFILE="/_myshare/_my-cron-jobs/rclone_crypto_$DATENOW.log" # ioBroker-Datenpunkte # Achtung: Zum setzen ist der simple-api Adapter notwendig, damit dieser Browser-Kommandos empfangen kann. IOBROKERSTATUS=javascript.0.mic.vis-support.proxmoxBackup.cryptomatorSuccessful IBROKERLASTTIME=javascript.0.mic.vis-support.proxmoxBackup.cryptomatorLastDateTime # ioBroker-IP:Port (Port von simple-api Adapter) IPP=10.10.0.140:8087 # ################################################ # Script nicht 2mal ausführen, daher arbeiten wir mit Lock. # http://wiki.bash-hackers.org/howto/mutex # https://askubuntu.com/questions/142002/generic-solution-to-prevent-a-long-cron-job-from-running-in-parallel # ################################################## if mkdir "${LOCKDIR}"; then echo "Locking succeeded (script is not already running), so we can continue with our script" >&2 trap 'rm -rf "${LOCKDIR}"' EXIT # Lock dir deleted whenever script is exited, stopped, etc. else echo "Lock failed, script is already running - exit" >&2 exit 1 fi # Hier das eigentliche Kommando if rclone sync /_myshare/XYZ remote_OneDrive:XYZ --log-file "${LOGFILE}" --log-level "INFO" echo 'rclone successfully executed' DATENOWSUCC=`date '+%Y-%m-%dT%H:%M:%S'`; curl http://${IPP}/set/${IOBROKERSTATUS}?value=true curl http://${IPP}/set/${IBROKERLASTTIME}?value={$DATENOWSUCC} else echo 'rclone failed' DATENOWFAIL=`date '+%Y-%m-%dT%H:%M:%S'`; curl http://${IPP}/set/${IOBROKERSTATUS}?value=false curl http://${IPP}/set/${IBROKERLASTTIME}?value={$DATENOWFAIL} fiDieses Bash-Script macht folgendes:
-
Es führt die Synchronisierung des lokalen Verzeichnisses "/_myshare/XYZ" mit der Cloud im Verzeichnis "XYZ" durch. Das ganze ist "einweg", das heißt Änderungen in der Cloud werden nicht berücksichtigt. Also eine reine Backup-Lösung.
-
Der Erfolg (oder Misserfolg) der tagtäglichen Synchronisierung wird im ioBroker in Datenpunkte (dank ioBroker-Adapter simple-api) geschrieben.
ioBroker
Damit das ganze läuft, muss im ioBroker der simple-api-Adapter laufen.
Mit folgendem Script werden die benötigten Datenpunkte erstellt, die zum einen das obige Bash-Script füllt, und die zum anderen für die Anzeige im VIS dienen.
/****************************************************************************************** * --------------------------- * PROXMOX: Cloud-Backup mittels rclone: Datenpunkte erstellen und für VIS auswerten * --------------------------- * Diese werden direkt von den Bash-Scripts geschrieben (Fileserver: /_myshare/_my-cron-jobs) * * Siehe https://forum.iobroker.net/viewtopic.php?f=35&t=19004 * * Change Log * 0.2 Mic - Bug fix * 0.1 Mic - Initial release *******************************************************************************************/ const STATE_PATH = 'javascript.0.mic.vis-support.proxmoxBackup.'; // Die verschiedenen Backups // schedule: wann wird das Script ausgeführt. // noOfDays: innerhalb wie vielen Tagen muss das Backup gelaufen sein, damit "Successful"=true const CONF_BACKUP = [ {'name': 'keepass', 'schedule_hour': 5, 'schedule_minute': 15, 'noOfDays': 2}, {'name': 'cryptomator', 'schedule_hour': 5, 'schedule_minute': 20, 'noOfDays': 2}, ]; // Erweitertes Log const LOG_DEBUG = true; /******************************************************************************* * Ab hier nichts mehr ändern / Stop editing here! ******************************************************************************/ // Globale Variablen var G_ScheduleObjects = {}; // Contains the object for each schedule /******************************************************************************* * Executed on every script start. *******************************************************************************/ init(); function init() { // Create states createBackupStates(); // Main Script starten, 3s nach State-Generierung setTimeout(main, 3000); } /******************************************************************************* * Haupt-Skript *******************************************************************************/ function main() { for (let lpEntry of CONF_BACKUP) { var loopScheduleObjectId = lpEntry.name + '_schedule'; // ID for each schedule object. We define it here to be able to clear the schedule. /********************* * 1\. Execute once Backup was performed ********************/ on({id: STATE_PATH + lpEntry.name + 'LastDateTime', change: 'any'}, function(obj) { if (getState(STATE_PATH + lpEntry.name + 'Successful').val === true ) { setState(STATE_PATH + lpEntry.name + 'ForVIS_BackupSuccessful', true); } else { setState(STATE_PATH + lpEntry.name + 'ForVIS_BackupSuccessful', false); // Jetzt nicht unbedingt "within last x days", aber jedenfalls war Backup nicht erfolgreich! } }); // Gelbes Dreieck Kann man links ignorieren, wir brauchen hier die Funktion innerhalb der Schleife /********************* * 2\. Schedule for every day ********************/ if(LOG_DEBUG) log('Proxmox-Cloud-Backup: Setze Schedule für ' + lpEntry.name + ', gesetzt auf Stunde ' + lpEntry.schedule_hour + ' und Minute ' + lpEntry.schedule_minute); clearSchedule(loopScheduleObjectId); // Let's clear the schedule to make sure no former schedules are running. Not sure if we really need this, but just in case. G_ScheduleObjects[loopScheduleObjectId] = schedule({hour: lpEntry.schedule_hour, minute: lpEntry.schedule_minute}, function () { let strDateLastBackup = getState(STATE_PATH + lpEntry.name + 'LastDateTime').val; if (g_myIsValueEmptyNullUndefined(strDateLastBackup) === false) { // Date/Time of backup + X days -- from https://stackoverflow.com/questions/3674539/incrementing-a-date-in-javascript let noOfDaysToCheck = lpEntry.noOfDays; let dtLastBackupPlusXDays = new Date(strDateLastBackup); dtLastBackupPlusXDays = F_addDays(dtLastBackupPlusXDays, noOfDaysToCheck); // Current date let dtCurrentForCompare = new Date(); // Compare if (dtLastBackupPlusXDays > dtCurrentForCompare) { // Last Backup took place within last X days, so we set state to true setState(STATE_PATH + lpEntry.name + 'ForVIS_BackupSuccessful', true); } else { setState(STATE_PATH + lpEntry.name + 'ForVIS_BackupSuccessful', false); } } else { // Datenpunkt für letztes Backup nicht gesetzt, also setzen wir auf false (zur Sicherheit) setState(STATE_PATH + lpEntry.name + 'ForVIS_BackupSuccessful', false); } if(LOG_DEBUG) log('Proxmox-Cloud-Backup: Update Datenpunkt für ' + lpEntry.name + ' durchgeführt.'); }); // Gelbes Dreieck Kann man links ignorieren, wir brauchen hier die Funktion innerhalb der Schleife } // for } /******************************************************************************* * Create States *******************************************************************************/ function createBackupStates() { for (let lpEntry of CONF_BACKUP) { createState(STATE_PATH + lpEntry.name + 'Successful', {'name': lpEntry.name + ' Successful?', 'type':'boolean', 'read':true, 'write':true, 'role':'info', 'def':false }); createState(STATE_PATH + lpEntry.name + 'LastDateTime', {'name': lpEntry.name + ' Last Date/Time', 'type':'string', 'read':true, 'write':true, 'role':'info', 'def':'' }); createState(STATE_PATH + lpEntry.name + 'ForVIS_BackupSuccessful', {'name': lpEntry.name + ' Status For VIS: Performed Successfully?', 'type':'boolean', 'read':true, 'write':true, 'role':'info', 'def':false }); } } /******************************************************************************* * Function to add days to a given date/time. *******************************************************************************/ function F_addDays(startDateTime, numberOfDays) { return new Date(startDateTime.getTime() + (numberOfDays * 24 *60 * 60 * 1000)); }Damit werden dann die entsprechenden Datenpunkte erzeugt, hier ein Auszug:

Zum Schluss kann man dann den Datenpunkt "javascript.0.mic.vis-support.XXXXBackup.cryptomatorForVIS_BackupSuccessful" entsprechend in VIS verwenden. Er gibt true/false zurück.

Das "smarte" an der ganzen Sache ist:
Im VIS wird nur dann "Backup erfolgreich" angezeigt, wenn
-
Der Cron-Job ausgeführt wurde
-
- Die Synchronisierung mit der Cloud erfolgreich war
-
- Die letzte erfolgreiche Ausführung innerhalb von X Tagen war (im JavaScript konfigurierbar, im Beispiel auf 2 Tage gesetzt, 'noOfDays': 2)
Schlussbemerkungen:
Die Installation und Einrichtung von rclone ist über den obigen Link und Google gut durchführbar.
Sämtliche Pfade müssen natürlich im Bash-Script und Javascript angepasst werden etc.
Bitte das ganze erst mal nur mit Test-Verzeichnissen durchführen, gerade das Tool rsync ist da gnadenlos und führt exakt das aus, was in den Parametern steht.
Für Verbesserungsvorschläge usw. bin ich natürlich sehr dankbar :)
P.S. Warum verwende ich Microsoft OneDrive? Nun, es bietet 1TB Speicherplatz in Verbindung mit dem MS-Office-Abo, daher aus meiner Sicht sehr günstig in dieser Kombination und mir ist ansonsten kein Cloud-Anbieter bekannt mit diesem guten Ratio aus "Euro pro GB Speicher".
-