NEWS
Dateien kopieren mit Fehlerauswertung stdout,stderr,error
-
Hallo,
ich kopiere Nachts um 00:30 das History Verzeichnis auf meine NAS sowie zu anderen Zeiten auch andere Dateien.
Nach dem Kopieren überprüfe ich, ob das Verzeichnis/Datei am Ziel existiert und ob der Zeitstempel von Quelle und Ziel übereinstimmt.
Im Prinzip klappt das auch sehr gut. Aber in unregelmäßigen Abständen (3-6 mal im Monat) gibt es von meiner Prüfroutine eine Fehlermeldung: "Kopierfehler...." (weil Zieldatei nicht existiert)
Jetzt wollte ich der Sache etwas genauer auf die Spur gehen.
Hier meine Routine, der Aufruf ist ein Blockly, das eigentliche geschieht mit einer Javascript-Funktion.
Die eigentliche Kopier-Routine am Ende muss per SSH aufgerufen werden, wegen den Zugriffsrechten.function (sQ, sZ, sInfo) var sStr, befehl, result1, result2, result3; var SSH = require('simple-ssh'); var ssh = new SSH({ host: '127.0.0.1', user: 'myuser', pass: 'mypass' }); // Prufe ob NAS gemountet ist sStr = ''; exec('mount | grep /mnt/NAS', async (error, result, stderr) => { sStr = result; console.info('mount | grep result: ' + result ); // ==> leer console.info('mount | grep stderr: ' + stderr ); // ==> leer console.info('mount | grep error: ' + error ); // ==> Error: Command failed: mount | grep /mnt/NAS_FB at .... // falls nicht gemountet => mount if (!String(sStr).includes('/mnt/NAS')) { console.info('====== mount NAS ======'); exec('sudo mount -t cifs //192.168.xxx.xxx/Pfad/ und so weiter /mnt/NAS', async (error, result, stderr) => { console.info('mount result: ' + result ); // ==> leer console.info('mount stderr: ' + stderr ); // ==> leer console.info('mount error: ' + error ); // ==> 'null' }); } else { console.info('====== NAS existiert ======'); } await wait(300); result1 = 'leer'; result2 = 'leer'; result3 = 'leer'; befehl = ['sudo cp -a ',sQ, ' ', sZ].join(''); console.info( befehl ); // ==> Ausgabe: sudo cp -a /opt/iobroker/iobroker-data/Pruf_LOG.txt /mnt/NAS/ioBroker/Test/ ssh.exec( befehl, async (error, result, stderr) => { console.info('befehl result: ' + result ); // ==> keine Ausgabe console.info('befehl stderr: ' + stderr ); // ==> keine Ausgabe console.info('befehl error: ' + error ); // ==> keine Ausgabe }).start(); // =========> Datei ist kopiert, aber keine Ausgabe von result, stderr, error !!!!! *** Alternativer Versuch *** ssh.exec( befehl, { out: function( stdout, stderr, error ) { console.info('befehl result: ' + result ); // ==> keine Ausgabe result1 = result; console.info('befehl stderr: ' + stderr ); // ==> keine Ausgabe result2 = stderr; console.info('befehl error: ' + error ); // ==> keine Ausgabe result3 = error; },}).start(); // =========> Datei ist kopiert, aber keine Ausgabe von result, stderr, error !!!!! console.info(result1); // ==> "leer" console.info(result2); // ==> "leer" console.info(result3); // ==> "leer" });
Meine Vermutung ist, dass ich bei dem SSH als anderer User unterwegs bin und somit keine Ausgabe erscheint.
Ich habe auch versucht, das Ergebnis auf Variablen zu kopieren und später (wenn SSH vorbei) auszugeben, aber alle 3 sind "leer"
Getestet habe ich auch schon statt >>sudo cp -a ',sQ, ' ', sZ<< den Befehl >>sudo rsync -rt ',sQ, ' ', sZ<< , Datei wurde kopiert auch aber keine Ausgaben.
Wie erhalte ich die stdout, stderr, error um meinen Kopierfehler auszuwerten?
Oder gibt es einen anderen Weg Dateien/Verzeichnisse zu kopieren? Mit Fehlerausgabe/Auswertung?
Vielleicht eleganter?
Eine Sache interessiert mich noch: Wie bekomme ich heraus, ob der Kopiervorgang abgeschlossen / fertig ist? Gerade bei dem History-Verzeichnis kann dass schon mal ein paar Sekunden dauern.
Danke -
@martinsu sagte in Dateien kopieren mit Fehlerauswertung stdout,stderr,error:
Ich habe auch versucht, das Ergebnis auf Variablen zu kopieren und später (wenn SSH vorbei) auszugeben, aber alle 3 sind "leer"
So läuft das nicht. SSH ist dann nicht "vorbei". Du arbeitest ja mit Callbacks. Der
ssh.exec
wird nur gestartet und direkt danach wird die Logik weiter ausgeführt. Da wartet keine Funktion auf eine andere. Dafür gibt es ja Promises (wenn man das Verhalten möchte).@martinsu sagte in Dateien kopieren mit Fehlerauswertung stdout,stderr,error:
Wie erhalte ich die stdout, stderr, error um meinen Kopierfehler auszuwerten?
Das steht ja in der Doku. Error ist eine separate Option neben
out
: https://github.com/MCluck90/simple-ssh?tab=readme-ov-file#api -
Vorschlag (natürlich ungetestet):
const SSH = require('simple-ssh'); const ssh = new SSH({ host: '127.0.0.1', user: 'myuser', pass: 'mypass' }); // Prufe ob NAS gemountet ist exec('mount | grep /mnt/NAS', async (error, result, stderr) => { console.info('mount | grep result: ' + result); console.info('mount | grep stderr: ' + stderr); console.info('mount | grep error: ' + error); // falls nicht gemountet => mount if (!String(result).includes('/mnt/NAS')) { console.info('====== mount NAS ======'); exec('sudo mount -t cifs //192.168.xxx.xxx/Pfad/ /mnt/NAS', async (error, result, stderr) => { console.info('mount result: ' + result); console.info('mount stderr: ' + stderr); console.info('mount error: ' + error); }); } else { console.info('====== NAS existiert ======'); } // Eine frei erfundene Zeit warten ist nicht optimal, da das nicht garantiert, dass der Befehl auch abgeschlossen ist await wait(300); const befehl = `sudo cp -a ${sQ} ${sZ}`; console.info(befehl); ssh.exec(befehl, { out: (stdout) => { console.info('befehl result: ' + stdout); }, err: (stderr) => { console.info('befehl error: ' + stderr); } }).start(); });
-
@haus-automatisierung
Das der ssh.exec() nur angestoßen wird, ist mir klar. Aber die Zeilen
console.info('befehl result: ' + result ); // ==> keine Ausgabe usw.......
müssten doch eigentlich ausgeführt werden, wenn der callback zurück kommt, oder? Da kommt aber auch keine Ausgabe.
mit out, das habe ich wohl falsch verstanden und falsch angewendet.
Ich habe nach Deinem Vorschlag dies hier probiert:befehl = ['sudo cp -a ',sQ, ' ', sZ].join(''); ssh.exec( befehl, { out: ( stdout ) => { console.info('befehl stdout: ' + stdout ); }, err: ( stderr ) => { console.info('befehl stderr: ' + stderr ); } }).start();
Dabei erhalte ich eine Fehlermeldung, obwohl die Datei kopiert ist (Berechtigungen werden beibehalten, ist das ein Fehler?)
befehl stderr: cp: preserving permissions for ‘/mnt/NAS_FB/iobroker/Test/Pruf_LOG.txt’ befehl stderr: : Operation not supported
Wenn ich jetzt eine Datei kopiere, die es nicht gibt, kommt:
befehl stderr: cp: cannot stat '/opt/iobroker/iobroker-data/Pruf_xLOG.txt' befehl stderr: : No such file or directory
Stimmt soweit.
Wie würdest Du denn Dateien/Verzeichnisse kopieren? Hast Du eine andere / bessere Lösung?
-
@martinsu
Du kannst über eine nicht interaktive Verbindung kein sudo schicken.
Normalerweise kommt ja dann die passwortabfrage, was ja etwas schwierig wird.
Entweder vergibst du dem Remote Nutzer die entsprechende Berechtigung oder du konfigurierst
Das auf entfernten Rechnerhttps://wiki.ubuntuusers.de/sudo/Konfiguration/
Der iobroker nutzt das selbst. Da kannst du dann an den in der Doku erwähnten Stellen diese Konfiguration findest.
Bei einem copy Befehl dann eher ersteres
Nachtrag
Um von einem Rechner auf einen anderen Rechner was zu kopieren bietet sich rsync an. Der kann sehr viel.
https://wiki.ubuntuusers.de/rsync/Den Sync dann einfach per cron (also der vom Betriebssystem) anstoßen.
-
@oliverio
den rysnc hatte ich auch schon probiert:befehl = ['sudo rsync -rt ',sQ, ' ', sZ].join(''); ssh.exec( befehl, { out: ( stdout ) => { console.info('befehl stdout: ' + stdout ); }, err: ( stderr ) => { console.info('befehl stderr: ' + stderr ); } }).start();
leider kommt dann:
befehl stderr: rsync: [receiver] rename "/mnt/NAS/iobroker/Test/Pruf_LOG.txt.l53NvH" -> "Pruf_LOG.txt": Permission denied (13)
befehl stderr: rsync error: some files/attrs were not transferred (see previous errors) (code 23) at main.c(1338) [sender=3.2.7] -
Oh Mann.
Lese meinen ersten Post nochmal gaaaaanz genau durch.
Ganz speziell den Part wo ich das Wort sudo erwähnte.
Auch lese die Beschreibung von rsync mal genau durch,
Du scheinst die Funktionsweise noch nicht ganz verstanden haben.
Woher soll dieser Befehl den nun wissen von wo nach wohin er da was kopieren soll? Auch würde ich ihn nicht mit ssh ausführen. Rsync kann selbst ssh und wendet das beim kopieren auch an, wenn du die richtigen Parameter angibst.Alle Befehle des JavaScript Adapters werden mit dem Benutzer iobroker auf dem lokalen Rechner ausgeführt.
Ausprobieren kannst du die shellbefehle wenn du auf der Konsolesudo -u iobroker bash
Ausführst. Dann bist du mit der Berechtigung iobroker unterwegs und du kannst rsync oder ssh ausprobieren.