Skip to content

Python3 - Popen und seine Geheimnisse ;)

Python3
1 1 218
  • Eine der letzten Baustellen in meinem Tool Restic UI war die Funktion zum Mounten eines Restic Backups.

    Das größte Problem dabei war, das dieser Prozess nicht beendet wird sonder offen bleibt. Das kennt ihr, wenn ihr das schon mal über die Konsole gemacht habt, dann erscheint das folgende

    reading repository password from stdin
    repository 6859cd64 opened successfully, password is correct
    Now serving the repository at /home/frank/m5
    When finished, quit with Ctrl-c or umount the mountpoint.
    

    Jetzt kann man in meinem Tool das Passwort mittlerweile abspeichern oder wahlweise auch jedes mal eingeben. Aber, was mache ich wenn das Passwort falsch eingegeben wurde? Ich habe tagelang versucht, die Fehler abzufangen, das geht aber meiner Meinung nach nicht, da der Prozess am Laufen ist. Was machen?

    Ich habe so ziemlich jede Seite im Netz zum Thema Popen durch 😉 Nichts davon brachten den gewünschten Erfolg.

    Ok, fangen wir von vorne an, was sagt die Dokumentation von Restic?

    EXIT STATUS
    ===========
    
    Exit status is 0 if the command was successful, and non-zero if there was any error.
    

    Gut, wenn ich den richtigen Fehlercode nicht abfangen kann, dann kann ich evt. ermitteln ob der Prozess läuft oder einen Fehler ausgibt. Das würde mir zu mindestens helfen, den User zu informieren.

    Bei den hunderten von Webseiten, hatte ich irgendwo was über p.poll() aufgeschnappt. Das steht in der Python Dokumentation.

    Popen.poll()

    Check if child process has terminated. Set and return returncode attribute. Otherwise, returns None.
    

    Das sollte für meinen Zweck ausreichend sein. Erster Versuch

    # no passwd in backup_data? Ok, we ask for one
    if len(backup_data[row].password) == 0:
        pwd = get_password(self) ## pwd ('1234', True)
        if pwd[1] is False:
            return False
    
    try:
        cmd = ['restic',
                                        '-r',
                                        backup_data[row].repository,
                                        'mount',
                                        mount_path]
        
       
        # We create the object, here with stdin and open the asynchronous subprocess
        p1 = subprocess.Popen(cmd,stdin=subprocess.PIPE,stderr=subprocess.PIPE) 
        p1.stdin.write(pwd[0].encode()))
        p1.stdin.close()
    
    except Exception:
        pass
    
    finally:
        try:
            if p1.poll() == 1:                          
                 raise Exception("The Restic mount command was not successful. Probable cause: wrong password or no key found")
            else:
                msg_box(self, "Successful mount of the Repository!")    
        except Exception as e:
            msg_box_error(self, repr(e))
    

    Ich hoffe man versteht was ich hier mache.

    • Wir holen uns das Passort über eine Usereingabe
    • Wir bauen den Restic Befehl cmd
    • Wir starten den subprocess.Popen
    • Wir senden das Passwort auf stdin
    • Wir schließen stdin
    • In finally machen wir den p1.poll() und werten diesen aus.

    Bei den vielen, vielen, super vielen Test war mir aufgefallen, das das klappte.

    p1.poll() gab einmal None aus und einmal eine 1

    None war ein laufender Prozess, also erfolgreich gemountet.
    Eine 1 war ein Fehler, hier falsche Passwort Eingabe.

    Nach einigen weiteren Tests, ging es auf einmal nicht mehr. Ich wusste aber ganz genau, das es ging, ich konnte das in der Konsole noch lesen. Also meine Kontrollausgaben. Was war passiert. Eine halbe Stunde Grübeln und ich kam zu der Überzeugung, das muss ein Zeitproblem sein. Ok, also eine Bremse 🙂 einbauen. Im finally vor dem try kommt das rein.

    print("POLL", p1.poll()) 
    import time
    time.sleep(1.0)
    

    Kleine Kontrollausgabe, wir importieren das Modul time (ja, gehört nicht an diese Stelle, ich weiß...) und dann lassen wir den Prozess 1 Sekunde pausieren. Wir geben hier jetzt dem subprocess die Gelegenheit, das falsche Passwort zu erkennen und den richtigen Exit Status zu setzen. Und Bingo es ging so wie ich es mir vorgestellt hatte. 🤓

    Wieder extrem viel gelernt.

    Hinweis

    Der Code oben ist nur ein Ausschnitt, ich hoffe das er nachvollziehbar ist. Wenn nicht einfach hier drunter kommentieren, es gibt das dann in lang 😉

    Für Profis, die evt. hier mal drüber stolpern. Ich nehme jede Verbesserung gerne auf und probiere es auch aus.

    Wünsche mir eigentlich immer noch, das ich die Ausgabe

    Fatal: wrong password or no key found
    

    vernünftig abfangen und weiterverarbeiten kann. So wie mit

    output = process.stdout
    

    bei einem subprocess.run.

  • Restic - Migrate

    Restic restic restic-ui
    1
    2
    0 Stimmen
    1 Beiträge
    256 Aufrufe
    Niemand hat geantwortet
  • PyQt6 - QRegularExpressionValidator

    Python3 pyqt6 python3
    1
    0 Stimmen
    1 Beiträge
    655 Aufrufe
    Niemand hat geantwortet
  • Restic - Passwortübergabe

    Restic restic
    1
    0 Stimmen
    1 Beiträge
    232 Aufrufe
    Niemand hat geantwortet
  • Python3 - JSON

    Python3 python3
    3
    1
    0 Stimmen
    3 Beiträge
    266 Aufrufe
    FrankMF
    [image: 1603645936018-ede1a88a-5183-4f85-a602-27650362d532-grafik.png] Die Backups sollen Namen haben, also habe ich das erweitert. Jetzt sollen diese als Liste rechts angezeigt werden. Das mache ich wie folgt. for key in backups: print(backups[key]['name'], key) liste = backups[key]['name'] + " ID: " + key self.listWidget.addItem(liste) Mittels des Keys kann ich auf den Namen zugreifen und die Liste damit füllen. Aktuell habe ich noch den Key hinten angefügt, weil ich noch keine Idee habe, wie ich die Backups anders verarbeiten soll. Aber, Stück für Stück. Der Backup-Name wird nach Auswahl in der Statusbar angezeigt. So weit klappt das so wie ich mir das vorstelle. Für heute ist Feierabend
  • Python3 - zwei Webseiten als Empfehlung

    Python3 pyqt5 python3
    1
    0 Stimmen
    1 Beiträge
    200 Aufrufe
    Niemand hat geantwortet
  • Python und GUI

    Verschoben Python3 python3
    1
    1
    0 Stimmen
    1 Beiträge
    198 Aufrufe
    Niemand hat geantwortet
  • Rest-Server

    Verschoben Restic rest-server linux restic
    8
    0 Stimmen
    8 Beiträge
    746 Aufrufe
    FrankMF
    Dann mal eben ausprobiert. Auf meinem Server war die Version 0.9.7 selber, mit go, gebaut. Dann mache ich das auch mit der v0.10.0 so. Aber bevor ich anfange, wird die v0.9.7 gesichert. mv /usr/local/bin/rest-server /usr/local/bin/rest-server_0_9_7 So erspare ich mir im Problemfall das selber bauen. Ok, dann die neue Version bauen. git clone https://github.com/restic/rest-server.git cd rest-server go run build.go Danach befindet sich im Verzeichnis die Binärdatei rest-server Die kopieren wir jetzt cp rest-server /usr/local/bin Danach kurzer Test # rest-server --version rest-server 0.10.0 (v0.10.0-6-g037fe06) compiled with go1.11.6 on linux/amd64 Gut Version passt Dann ein Backup gestartet. Das sichert einen Teil meines Home-Verzeichnis Files: 153 new, 100 changed, 177857 unmodified Dirs: 0 new, 1 changed, 0 unmodified Added to the repo: 81.881 MiB processed 178110 files, 80.571 GiB in 0:28 snapshot 607e0027 saved Applying Policy: keep the last 3 snapshots, 3 monthly snapshots keep 5 snapshots: ID Time Host Tags Reasons Paths --------------------------------------------------------------------------------------- fa97890e 2020-07-25 21:02:05 frank-XXX monthly snapshot /home/frank 5b073bbb 2020-08-30 10:17:27 frank-XXX monthly snapshot /home/frank f7cf37ef 2020-09-06 15:13:03 frank-XXX last snapshot /home/frank 0157462c 2020-09-13 13:32:12 frank-XXX last snapshot /home/frank 607e0027 2020-09-14 08:09:34 frank-XXX last snapshot /home/frank monthly snapshot --------------------------------------------------------------------------------------- 5 snapshots remove 1 snapshots: ID Time Host Tags Paths --------------------------------------------------------------------- 3010b7cc 2020-09-06 11:39:27 frank-XXX /home/frank --------------------------------------------------------------------- 1 snapshots 1 snapshots have been removed, running prune counting files in repo building new index for repo [1:34] 100.00% 17351 / 17351 packs So weit funktioniert das genau wie vorher. Im Changelog stand ja was von Subfoldern. Das betrifft mich nicht, weil ich für jeden User genau ein Verzeichnis habe. So mit alles Gut Dann warte ich mal morgen ab, ob die täglichen Backups der Server rund laufen.
  • Restic - Ein Backupkonzept - Wiederherstellung

    Verschoben Restic linux restic
    1
    0 Stimmen
    1 Beiträge
    760 Aufrufe
    Niemand hat geantwortet