Hallo.
Ich hänge jetzt seit einer Woche an ein Problem für das ich keine Lösung finde.
Ich möchte für mich selber ein Backup Programm erstellen, dass dann einen rsync Befehl ausführt (genauer: ein Backup ausführt).
Das was ich nicht zusammenbringe:
Ich möchte den über "subprocess" ausgeführten "rsync" Befehl im Termnial anzeigen lassen und alles was da angezeigt wurde in eine Datei speichern (für eventuell spätere Fehlersuche).
In einem anderen Forum wurde mir logging empfohlen, aber da schaffe ich es immer nur dass mir die erste Zeile angezeigt wird, oder alles am Schluss.
Bei einem Backup dass vielleicht eine Stunde oder mehr läuft würde ich gerne sehen, dass noch was passiert, bzw. anhand der Dateien die gerade kopiert werden sehen wollen wie weit es ungefähr ist.
Hat von euch jemand eine Idee wie man die Ausgabe eines Subprocesses in Echtzeit im Terminal anzeigen lassen kann? Glaub das mit dem in der Datei speichern bekomm ich dann wieder selber hin.
Vielen Dank im Voraus
Gruß Thomas
Subprocess Problem(Längere Ausgabe im Terminal anzeigen lassen)
Hallo,
wie hast du das mit der Log-File denn probiert?
'rsync' bietet von Haus aus Log-Option an:
https://wiki.ubuntuusers.de/rsync/
Grüße
Dennis
wie hast du das mit der Log-File denn probiert?
'rsync' bietet von Haus aus Log-Option an:
https://wiki.ubuntuusers.de/rsync/
Code: Alles auswählen
run([
'rsync', '-vahHA', f'--log-file=/media/Data_Backup/Logs/{date.today()}.log',
f'--link-dest=/media/Data_Backup/{date.today()}', '/media/Wolke/',
f'/media/Data_Backup/{date.today()}'],
check=True)
Dennis
"When I got the music, I got a place to go" [Rancid, 1993]
Hi.
Danke für die Antwort.
Da hab ich mich wohl falsch ausgedrückt. Das mit dem Log-File ist nicht mein Problem, sondern die Anzeige des rsync-Verlaufs im Terminal.
Ich erhoffe mir davon, dass bei längeren Backups ein wenig ersichtlich ist wie weit das Backup schon ist, bzw. das ich abschätzen kann wie lange es noch ungefähr dauert.
Dafür wurde mir der import "logging" empfohlen (auf gutefrage.net), aber mit dem komm ich nicht so wirklich klar.
Auszüge meines Codes:
So definiere ich die Pfade (z.B.: um sie für weitere Backups schneller abändern zu können)
Backup Funktion:
Ist das möglich diesen Prozess im Terminal anzeigen zu lassen, als würde ich rsync als bash in der Konsole ausführen?
Danke für die Antwort.
Da hab ich mich wohl falsch ausgedrückt. Das mit dem Log-File ist nicht mein Problem, sondern die Anzeige des rsync-Verlaufs im Terminal.
Ich erhoffe mir davon, dass bei längeren Backups ein wenig ersichtlich ist wie weit das Backup schon ist, bzw. das ich abschätzen kann wie lange es noch ungefähr dauert.
Dafür wurde mir der import "logging" empfohlen (auf gutefrage.net), aber mit dem komm ich nicht so wirklich klar.
Auszüge meines Codes:
So definiere ich die Pfade (z.B.: um sie für weitere Backups schneller abändern zu können)
Code: Alles auswählen
# Pfade definieren
source = "/home/dns" # -> Pfad welches gesichert werden soll definieren
target = "/mnt/Laufwerke/10_Backup-Linux/01_Backup-home-dns/" # -> Pfad wohin gesichert werden soll
log_pfad = "/mnt/Laufwerke/10_Backup-Linux/01_Backup-home-dns/_Log-Files/"
backup_dir = "/mnt/Laufwerke/10_Backup-Linux/01_Backup-home-dns/_gelöschte_Dateien"
exclude = "/mnt/Laufwerke/10_Backup-Linux/01_Backup-home-dns/_rsync-Exclude-File/Rsync-Exclude-Linux-Home"
Code: Alles auswählen
def backup_home(logfile=logfile_test()):
# Liste von allem was an subprocess übergeben wird
rsync_liste = ['rsync',
'-avPXAh',
('--log-file=' + logfile),
'--delete',
('--backup-dir=' + backup_dir),
('--exclude-from=' + exclude),
source,
target]
# Backup-Subprocess:
backup_process = subprocess.Popen(rsync_liste, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
stdout, stderr = backup_process.communicate()
Defaultargumente werden bei der Definition der Funktion festgelegt, da möchte man normalerweise keine Funktionsaufrufe haben. Konstanten werden komplett gross geschrieben.
Und wenn Du die Ausgabe des Programms im Terminal haben willst, dann darfst Du sie eben nicht umleiten!
Und wenn Du die Ausgabe des Programms im Terminal haben willst, dann darfst Du sie eben nicht umleiten!
Code: Alles auswählen
# Pfade definieren
SOURCE = "/home/dns" # -> Pfad welches gesichert werden soll definieren
TARGET = "/mnt/Laufwerke/10_Backup-Linux/01_Backup-home-dns/" # -> Pfad wohin gesichert werden soll
LOG_PATH = "/mnt/Laufwerke/10_Backup-Linux/01_Backup-home-dns/_Log-Files/"
BACKUP_DIR = "/mnt/Laufwerke/10_Backup-Linux/01_Backup-home-dns/_gelöschte_Dateien"
EXCLUDE = "/mnt/Laufwerke/10_Backup-Linux/01_Backup-home-dns/_rsync-Exclude-File/Rsync-Exclude-Linux-Home"
def backup_home(logfile=None):
if logfile is None:
logfile = logfile_test()
# Liste von allem was an subprocess übergeben wird
arguments = ['rsync',
'-avPXAh',
'--log-file, logfile,
'--delete',
'--backup-dir', BACKUP_DIR,
'--exclude-from', EXCLUDE,
SOURCE,
TARGET]
subprocess.run(arguments)
- __blackjack__
- User
- Beiträge: 14002
- Registriert: Samstag 2. Juni 2018, 10:21
- Wohnort: 127.0.0.1
- Kontaktdaten:
@Medds: Du darfst halt nicht `communicate()` verwenden, sondern musst `stdout` und `stderr` von dem Prozess auslesen und ausgeben und noch irgend etwas anderes damit machen. Wobei man da überlegen sollte `stderr` einfach nach `stdout` umzuleiten. also `subprocess.STDOUT` statt `subprocess.STDERR`.
Falls Du sonst nichts weiter mit den Zeilen machen willst, dann siehe die Antwort von Sirius3. Das ist dann einfacher. Ich würde das dort dann noch durch das Argument ``check=True`` beim `run()`-Aufruf ergänzen, damit Fehler beim ``rsync`` nicht einfach ignoriert werden.
Grunddatentypen haben nichts in Namen zu suchen. Namen von Konstanten werden KOMPLETT_GROSS_GESCHRIEBEN.
Ungetestet:
Falls Du sonst nichts weiter mit den Zeilen machen willst, dann siehe die Antwort von Sirius3. Das ist dann einfacher. Ich würde das dort dann noch durch das Argument ``check=True`` beim `run()`-Aufruf ergänzen, damit Fehler beim ``rsync`` nicht einfach ignoriert werden.
Grunddatentypen haben nichts in Namen zu suchen. Namen von Konstanten werden KOMPLETT_GROSS_GESCHRIEBEN.
Ungetestet:
Code: Alles auswählen
def backup_home(log_filename):
backup_process = subprocess.Popen(
[
"rsync",
"-avPXAh",
"--log-file=" + log_filename,
"--delete",
"--backup-dir=" + BACKUP_DIR,
"--exclude-from=" + EXCLUDE,
SOURCE,
TARGET,
],
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
)
for line in backup_process.stdout:
print(line)
#
# TODO Do something else with line.
#
if backup_process.wait() != 0:
raise RuntimeError(
f"Backup endet with non-zero exit code {backup_process.returncode}"
)
“The best book on programming for the layman is »Alice in Wonderland«; but that's because it's the best book on anything for the layman.” — Alan J. Perlis
Vielen Dank euch beiden.
Die Variante von __blackjack__ funktioniert super.
Und das beste daran. Ich verstehe es sogar noch.
Da war das halbe Jahr Python-Pause nicht förderlich.
Shame on me
Macht ja auch Sinn. Ich versuche es diesmal besser zu verinnerlichen.
Was meinst du mit:
Eine weitere Frage hätte ich noch:
Ist das das gleiche wie , oder hat irgendwelche Vorteile?
Nochmals vielen Dank für tolle Hilfe.
Die Variante von __blackjack__ funktioniert super.
Und das beste daran. Ich verstehe es sogar noch.
habt ihr mir vor geraumer Zeit schon mal gesagt.Namen von Konstanten werden KOMPLETT_GROSS_GESCHRIEBEN
Da war das halbe Jahr Python-Pause nicht förderlich.
Shame on me
Macht ja auch Sinn. Ich versuche es diesmal besser zu verinnerlichen.
Was meinst du mit:
Kannst du ein Beispiel geben was du damit meinst?Grunddatentypen haben nichts in Namen zu suchen.
Eine weitere Frage hätte ich noch:
Ist das
Code: Alles auswählen
run()
Code: Alles auswählen
Popen()
Code: Alles auswählen
run()
Nochmals vielen Dank für tolle Hilfe.
- __blackjack__
- User
- Beiträge: 14002
- Registriert: Samstag 2. Juni 2018, 10:21
- Wohnort: 127.0.0.1
- Kontaktdaten:
@Medds: Grunddatentypen sind die eingebauten Datentypen für die es (in der Regel) auch Syntax gibt um literale Werte in das Programm zu schreiben. Also `int`, `float`, `str`, `list`, `dict`, und so weiter. Das Problem damit das als Namensbestandteil zu verwenden, ist, dass man während der Programmentwicklung öfter man auf andere, spezialisiertere Typen wechselt, und dann überall die dann falschen, irreführenden Namen anpassen muss.
`run()` ist einfacher wenn man nur ein externes Programm ablaufen lassen will, ohne das man im eigenen Code Zugriff auf das `Popen`-Objekt braucht. Denn das verwendet `run()` intern im das externe Programm auszuführen.
`run()` ist einfacher wenn man nur ein externes Programm ablaufen lassen will, ohne das man im eigenen Code Zugriff auf das `Popen`-Objekt braucht. Denn das verwendet `run()` intern im das externe Programm auszuführen.
“The best book on programming for the layman is »Alice in Wonderland«; but that's because it's the best book on anything for the layman.” — Alan J. Perlis
Ok Danke.
rsync_liste war falsch weil da der Grunddatentyp Liste drinnen stand. Danke für die ausführliche Erkärung.
Das 'Popen()' gegen das 'run()' auszutauschen hat bei mir nicht funktioniert, aber egal, weil 'Popen()' funktioniert.
check=True hat auch nicht funktioniert, aber denke das war für das run() gedacht.
Wenn ich das richtig verstehe, ist das
rsync_liste war falsch weil da der Grunddatentyp Liste drinnen stand. Danke für die ausführliche Erkärung.
Das 'Popen()' gegen das 'run()' auszutauschen hat bei mir nicht funktioniert, aber egal, weil 'Popen()' funktioniert.
check=True hat auch nicht funktioniert, aber denke das war für das run() gedacht.
Wenn ich das richtig verstehe, ist das
das equivalent zum 'check=True'?if backup_process.wait() != 0:
raise RuntimeError(
f"Backup endet with non-zero exit code {backup_process.returncode}"
)
Ah eine letzte Frage hätte ich noch.
Wenn ich die jetzigen Konstanten in eine Funktion schreibe bei der ich Auswählen kann welche Pfade ich benutzten möchte, sind das dann keine Konstanten mehr, oder?
Weil so ist das Programm gedacht, dass es dann mal so wird, dass am Anfang auszuwählen ist mit beispielsweise 1, 2 oder 3 welches Backup ich ausführen möchte.
Versteh ich das richtig dass dann nicht mehr groß geschrieben werden sollte?
Wenn ich die jetzigen Konstanten in eine Funktion schreibe bei der ich Auswählen kann welche Pfade ich benutzten möchte, sind das dann keine Konstanten mehr, oder?
Weil so ist das Programm gedacht, dass es dann mal so wird, dass am Anfang auszuwählen ist mit beispielsweise 1, 2 oder 3 welches Backup ich ausführen möchte.
Versteh ich das richtig dass dann nicht mehr groß geschrieben werden sollte?
- __blackjack__
- User
- Beiträge: 14002
- Registriert: Samstag 2. Juni 2018, 10:21
- Wohnort: 127.0.0.1
- Kontaktdaten:
@Medds: Da würde ich ja eher Kommandozeilenargumente für her nehmen. Dann stellt sich aber auch die Frage warum das überhaupt in Python geschrieben ist, und nicht einfach ein Shell-Skript.
“The best book on programming for the layman is »Alice in Wonderland«; but that's because it's the best book on anything for the layman.” — Alan J. Perlis