Skip to content

Python3 - subprocess.Popen

Python3
  • Für ein UI zum Tool Restic, an dem ich jetzt schon eine ganze Zeit "code", brauche ich einen Prozess der asynchron läuft.

    Ok, ich versuche das mal als Laie zu erklären. Ich starte oft Prozesse mit

    process = subprocess.run(['restic','version'], check=True, stdout=subprocess.PIPE, universal_newlines=True)
    

    Das gibt mir die Version von Restic zurück. Dieser Prozess wird gestartet und beendet!

    Nun wollte ich aber eine Sicherung mounten. Und dieser Prozess in Restic, wird gestartet und läuft, so lange bis man ihn mit CTRL + C auf der Konsole beendet. Jo, damit war dann meine Denksportaufgabe für gestern definiert. Ich muss eingestehen, es hat was länger gedauert 😀

    Nach einiger Zeit hatte ich rausbekommen, das ich es so machen muss.

    p1 = subprocess.Popen(cmd,stdin=subprocess.PIPE)
    

    Wir starten den Prozess und übergeben ihm den Restic Befehl (cmd) und setzen als stdin die subprocess.PIPE. Damit wird der Prozess unabhängig gestartet, mein Python3 Script wartet nicht mehr auf das Ende. So nach dem Motto, gestartet und vergessen 🙂

    Da tauchte das nächste Problem auf. Restic erwartet eine Passwort Eingabe. Ja, ich möchte das übergeben und ja ich weiß das ist aus Sicherheitsaspekten evt. nicht der beste Ansatz. Egal, da kümmere ich mich später drum!

    Viele Anleitungen im Netz gefunden, aber irgendwie war ich zu blöde die umzusetzen. Nur ein Ansatz machte dann bei mir das, was ich erwartete und auch teilweise verstand.

    # Wir schreiben das erwartete Passwort als Eingabe
    p1.stdin.write('12345678'.encode())
    p1.stdin.flush()
    p1.stdin.close()
    msg_box(self, "Repository erfolgreich gemountet!")
    

    Erste Zeile

    Ohne das .encode() funktioniert das nicht. Dem Prozess Popen muss das als Bytes Stream übergeben werden!

    This means that the string is converted to a stream of bytes, which is how it is stored on any computer. As bytes!

    Wir schreiben also diesen Bytes Stream in das Objekt p1
    Quelle: https://www.askpython.com/python/string/python-encode-and-decode-functions

    pwd='12345678'
    

    Und so sieht das aus, als Bytes Stream

    b'12345678'
    

    Zeile 2

    Die kann ich mir leider nicht erklären.

    Zeile 3

    Damit wird die Verbindung zum Prozess p1 geschlossen. Ohne schließen funktioniert es nicht.

    Wenn jemand weiß, wie man das Vernünftig erklären kann, wäre ich sehr dankbar.

    Fazit

    Der Prozess ist erfolgreich gestartet, läuft unabhängig vom Python Script. Das Passwort wird auch erfolgreich übergeben Das was ich brauchte 🙂 Wieder ein Stück weiter und was gelernt!!

  • Restic v0.17.0 released

    Restic
    1
    0 Stimmen
    1 Beiträge
    96 Aufrufe
    Niemand hat geantwortet
  • Restic v0.16.5 released

    Restic
    1
    0 Stimmen
    1 Beiträge
    115 Aufrufe
    Niemand hat geantwortet
  • Restic v0.14.0 released

    Restic
    5
    0 Stimmen
    5 Beiträge
    160 Aufrufe
    FrankMF

    @berthold GUI v1.5.0 released mit Unterstützung für restic 0.14.0 und dem Migrations Tool. Bitte zum Testen evt. nicht auf die wichtigsten Daten loslassen 😉

    Mein Test mit meinem Repo auf dem REST-Server war erfolgreich.

  • Restic - Kompression

    Restic
    2
    0 Stimmen
    2 Beiträge
    300 Aufrufe
    FrankMF

    Gestern Abend noch ein paar Tests gemacht, aber nicht wirklich Erfolg gehabt. Ok, dann heute noch mal von vorne und mit System. Als erstes muss man mal Daten finden, die man auch gut komprimieren kann, ich will ja auch ein deutliches Ergebnis sehen.

    Meine Wahl fiel auf einen openwrt Ordner, mit dem ich mal ein Image selber gebaut hatte. Schön viele kleine Dateien, sollte sich gut komprimieren lassen.

    Original

    547e3596-69df-48ac-9409-5173367afb85-grafik.png

    Test mit 7z

    Rechtsklick, mit den Bordmittel und dann 7z gewählt.

    364b497f-cf59-408c-ba2b-cad70cc09529-grafik.png

    Test mit Restic V1

    Ich habe auf einer mechanischen 1TB Platte zwei Ordner angelegt, einmal Restic_V1, einmal Restic_V2.

    frank@frank-MS-7C37:~/Downloads$ restic version restic 0.13.1 compiled with go1.18 on linux/amd64 Init restic init -r /media/1TB/Restic_V1/ Backup frank@frank-MS-7C37:~/Downloads$ restic -r /media/1TB/Restic_V1/ backup /home/frank/openwrt/ enter password for repository: repository 731db857 opened successfully, password is correct created new cache in /home/frank/.cache/restic no parent snapshot found, will read all files Files: 407839 new, 0 changed, 0 unmodified Dirs: 41286 new, 0 changed, 0 unmodified Added to the repo: 7.851 GiB processed 407839 files, 11.061 GiB in 4:49 snapshot 24cd8ef4 saved Ergebnis

    799fa3ee-5bdf-48ba-a05e-8f7f24f1c41b-grafik.png

    Test mit Restic V2 frank@frank-MS-7C37:~/Downloads$ ./restic_v0.13.0-126-g26c33332_linux_amd64 version restic 0.13.1-dev (compiled manually) compiled with go1.18 on linux/amd64 Init ./restic_v0.13.0-126-g26c33332_linux_amd64 init -r /media/1TB/Restic_V2/ --repository-version 2 Backup frank@frank-MS-7C37:~/Downloads$ ./restic_v0.13.0-126-g26c33332_linux_amd64 -r /media/1TB/Restic_V2/ backup /home/frank/openwrt/ enter password for repository: repository 33c5e24c opened (repo version 2) successfully, password is correct created new cache in /home/frank/.cache/restic no parent snapshot found, will read all files Files: 407839 new, 0 changed, 0 unmodified Dirs: 41286 new, 0 changed, 0 unmodified Added to the repo: 7.835 GiB processed 407839 files, 11.061 GiB in 2:47 snapshot 474d0376 saved Ergebnis

    caafd946-1285-4e1d-8873-a3ff4141a777-grafik.png

    Fazit

    Fassen wir es mal ein wenig zusammen. Das Original hat 12,1GB

    ITool Dateigröße Zeit 7z 2,2GB ca. 11:59 Restic V1 8,5GB 4:49 Restic V2 2,9GB 2:47

    Man kann auch noch etwas an der Kompression einstellen, ich habe es für diesen Test auf der Standardeinstellung(?) gelassen.

    You can set the desired compression level by passing it to --compression (e.g. restic backup --compression max), supported are auto, max and off.

    Das Ergebnis sieht sehr vielversprechend aus. Es könnte den Platzverbrauch stark begrenzen, sehr wichtig für mich wenn man seine Daten in einer Cloud speichert. (Stichwort: Kosten) Und was hier auch noch schön ins Auge fällt, es ist schneller 🙂 Das möchte ich hier nicht versuchen zu erklären, da ich nicht genau woran es liegt. Vermutung, ich muss wesentlich weniger Daten "schreiben".

    Ich freue mich extrem, diese Version produktiv einzusetzen. Mal überlegen, ob ich die Version hier auf dem Haupt-PC mal testweise nutze, ich denke das wäre spannend.

    @Restic-Team: Vielen Dank für dieses tolle Feature!
  • Restic UI - Youtube Video Vorstellung

    Restic UI
    3
    0 Stimmen
    3 Beiträge
    195 Aufrufe
    FrankMF

    Hallo @berthold, du bist mein einziger Star 🙂 Ok, darum geht es mir ja nicht, wie Du weißt mache ich das hauptsächlich für mich und meine Backups klappen damit sehr gut. Ist also produktiv einsetzbar.

    Wie Du gemerkt hast, gibt es Zeiten da mache ich ganz viel und dann wieder Zeiten da passiert nix. Das ist bei mir normal, ich muss da "Bock" drauf haben. Habe ich viel Stress auf der Arbeit, passiert Abends eher sehr wenig..

    Ich hoffe das ich mittlerweile alle Fehler gefunden habe, die Grundfunktionen sind alle funktional. Mittlerweile kann man die JSON Datei mit den Daten der Backups auf Wunsch auch verschlüsseln 🙂

    Ich habe noch eine ganze Reihe an Notizen, was ich gerne noch machen möchte. Wichtig ist mir aber im Moment, das ich alle Fehler finde und das so wie es jetzt ist, einwandfrei läuft.

    Darum, wenn es jemand nutzt, bitte gebt Feedback. Egal ob positiv oder negativ. Ich freue mich persönlich natürlich mehr über positives Feedback 🙂

  • Python3 - enumerate()

    Python3
    2
    0 Stimmen
    2 Beiträge
    116 Aufrufe
    FrankMF

    Ich habe noch was Code gefunden, den ich mal dringend aufräumen musste 🙂 Wenn ich mit dem Restic UI die Snapshots anzeige, dann sieht das so aus.

    reading repository password from stdin ID Time Host Tags Paths ---------------------------------------------------------------------------- 4e769748 2021-12-31 21:48:34 frank-MS-7C37 /home/frank/Bilder 34298934 2022-01-26 20:15:53 frank-MS-7C37 /home/frank/Bilder 0d5d88f2 2022-01-27 21:05:07 frank-MS-7C37 /home/frank/Bilder f0e7d5a7 2022-01-29 13:46:12 frank-MS-7C37 /home/frank/Bilder 79918d70 2022-01-29 13:52:56 frank-MS-7C37 /home/frank/Bilder d74272a3 2022-01-30 11:54:20 frank-MS-7C37 /home/frank/Bilder 11b0b5ad 2022-01-30 11:57:44 frank-MS-7C37 /home/frank/Bilder 4a7450d2 2022-02-20 09:35:56 frank-MS-7C37 /home/frank/Bilder c1a4a51d 2022-02-20 09:36:43 frank-MS-7C37 /home/frank/Bilder d178ded5 2022-02-20 09:38:53 frank-MS-7C37 /home/frank/Bilder 997e2259 2022-02-20 16:35:57 frank-MS-7C37 /home/frank/Bilder 3320ad5c 2022-02-20 16:49:19 frank-MS-7C37 /home/frank/Bilder ---------------------------------------------------------------------------- 12 snapshots

    Mich interessieren die IDs, weil ich bei der Eingabe der IDs überprüfen möchte, ob die eingegebene ID existiert. Also muss ich das irgendwie auslesen und speichern. Das habe ich bis jetzt so gemacht.

    def id_append(self, result): # We split the result into individual lines. # Result was passed. And create an list. result_list = result.split('\n') # We count the number of repositories and search for 'source'. count = result.count(backup_data[row].source) # Offset added, first interesting line is line 3! count = count + 3 # We loop through the list and output the ID's and store in snapshot_id x = 3 while x < count: a = result_list[x] y = a[0:8] snapshot_id.append(y) x = x + 1

    Das erschien mir heute, beim erneuten Betrachten, Spaghetticode zu sein. Machen wir das mal etwas ordentlicher.

    Ich nehme die Ausgabe (stdout) und erzeuge eine Liste, jede Zeile ein Element.

    result_list = result.split('\n')

    Sieht so aus

    ['reading repository password from stdin', 'ID Time Host Tags Paths', '----------------------------------------------------------------------------', '4e769748 2021-12-31 21:48:34 frank-MS-7C37 /home/frank/Bilder', '34298934 2022-01-26 20:15:53 frank-MS-7C37 /home/frank/Bilder', '0d5d88f2 2022-01-27 21:05:07 frank-MS-7C37 /home/frank/Bilder', 'f0e7d5a7 2022-01-29 13:46:12 frank-MS-7C37 /home/frank/Bilder', '79918d70 2022-01-29 13:52:56 frank-MS-7C37 /home/frank/Bilder', 'd74272a3 2022-01-30 11:54:20 frank-MS-7C37 /home/frank/Bilder', '11b0b5ad 2022-01-30 11:57:44 frank-MS-7C37 /home/frank/Bilder', '4a7450d2 2022-02-20 09:35:56 frank-MS-7C37 /home/frank/Bilder', 'c1a4a51d 2022-02-20 09:36:43 frank-MS-7C37 /home/frank/Bilder', 'd178ded5 2022-02-20 09:38:53 frank-MS-7C37 /home/frank/Bilder', '997e2259 2022-02-20 16:35:57 frank-MS-7C37 /home/frank/Bilder', '3320ad5c 2022-02-20 16:49:19 frank-MS-7C37 /home/frank/Bilder', '----------------------------------------------------------------------------', '12 snapshots', '']

    Diesmal benutzen wir die enumerate() Funktion

    for count, value in enumerate(result_list): print(count, value)

    Das was raus kommt, sieht so aus

    0 reading repository password from stdin 1 ID Time Host Tags Paths 2 ---------------------------------------------------------------------------- 3 4e769748 2021-12-31 21:48:34 frank-MS-7C37 /home/frank/Bilder 4 34298934 2022-01-26 20:15:53 frank-MS-7C37 /home/frank/Bilder 5 0d5d88f2 2022-01-27 21:05:07 frank-MS-7C37 /home/frank/Bilder 6 f0e7d5a7 2022-01-29 13:46:12 frank-MS-7C37 /home/frank/Bilder 7 79918d70 2022-01-29 13:52:56 frank-MS-7C37 /home/frank/Bilder 8 d74272a3 2022-01-30 11:54:20 frank-MS-7C37 /home/frank/Bilder 9 11b0b5ad 2022-01-30 11:57:44 frank-MS-7C37 /home/frank/Bilder 10 4a7450d2 2022-02-20 09:35:56 frank-MS-7C37 /home/frank/Bilder 11 c1a4a51d 2022-02-20 09:36:43 frank-MS-7C37 /home/frank/Bilder 12 d178ded5 2022-02-20 09:38:53 frank-MS-7C37 /home/frank/Bilder 13 997e2259 2022-02-20 16:35:57 frank-MS-7C37 /home/frank/Bilder 14 3320ad5c 2022-02-20 16:49:19 frank-MS-7C37 /home/frank/Bilder 15 ---------------------------------------------------------------------------- 16 12 snapshots 17

    Mich interessieren nur die Zeilen mit /home/frank/Bilder Das kann man so abfragen

    if backup_data[row].source in value:

    Und jetzt nur die ID entsprechend abspeichern

    snapshot_id.append(value[0:8])

    Sieht jetzt komplett so aus

    result_list = result.split('\n') for count, value in enumerate(result_list): if backup_data[row].source in value: snapshot_id.append(value[0:8]) print(count, value[0:8])

    Somit speichert er jetzt nur noch die IDs, der folgenden Ausgabe.

    3 4e769748 4 34298934 5 0d5d88f2 6 f0e7d5a7 7 79918d70 8 d74272a3 9 11b0b5ad 10 4a7450d2 11 c1a4a51d 12 d178ded5 13 997e2259 14 3320ad5c

    Diese IDs, kann ich dann weiterverarbeiten.

  • Restic - Passwortübergabe

    Restic
    1
    0 Stimmen
    1 Beiträge
    174 Aufrufe
    Niemand hat geantwortet
  • Restic - Beispielzeiten

    Restic
    1
    0 Stimmen
    1 Beiträge
    478 Aufrufe
    Niemand hat geantwortet