rklm
Projektleitung
Anmeldungsdatum: 16. Oktober 2011
Beiträge: 12832
|
Hi, ich habe nach einem Weg gesucht, btrfs scrub für alle Dateisysteme automatisch ausführen zu lassen unter der Maßgabe, dass möglichst nicht zwei Scrubs gleichzeitig laufen könnten, weil die Dateisysteme auf dem selben Gerät liegen könnten. Ich wollte mal von jemand, der mehr Erfahrung mit systemd hat, hören, ob das so Sinn ergibt. Zuerst habe ich ein Service-Template definiert in /etc/systemd/system/btrfs-scrub@.service | [Unit]
Description=Scrub a btrfs filesystem
[Service]
Type=oneshot
ExecStart=/bin/btrfs scrub start "%f"
|
Dann einen passenden Timer in /etc/systemd/system/btrfs-scrub@.timer | [Unit]
Description=Run btrfs scrub periodically
[Timer]
OnCalendar=monthly
RandomizedDelaySec=14 days
Persistent=true
[Install]
WantedBy=timers.target
|
Dann habe ich für alle btrfs-Dateisysteme einen Timer instantiert (ist bei mir zZ nur eins, von daher hätte ich das auch von Hand ermitteln können): | for p in $(btrfs fi show | sed -n 's#.* path ##p'); do sudo systemctl enable --now "btrfs-scrub@$(systemd-escape -p "$p").timer"; done
|
Macht das so Sinn? Irgendwelche Verbesserungsvorschläge?
|
Developer92
Anmeldungsdatum: 31. Dezember 2008
Beiträge: 4101
|
rklm schrieb: […] weil die Dateisysteme auf dem selben Gerät liegen könnten.
Öhm, warum? Dafür hat man doch Subvolumes.
Ich kenne jetzt deinen speziellen Anwendungsfall nicht, aber ich denke du machst dir gerade zu viele Gedanken. Wie genau sieht dein aktuelles Setup aus? Muss die Lösung skalieren oder geht es nur um 1-2 Geräte? Mein Setup sieht gewöhnlich eine SSD vor, auf der das Betriebssystem und die Programme liegen, sowie einen Storage, was alles mögliche sein kann (eine weitere SSD, eine HDD, ein RAID, etc.). Dafür muss ich dann genau zwei Timer aktivieren, einmal für die SSD, einmal für den Storage. Die Aufteilung der Partitionen läuft komplett über Subvolumes. Das ist IMHO der einfachste und sinnvollste Ansatz den man machen kann. Erspart auch einiges an Kopfzerbrechen 😉
|
rklm
Projektleitung
(Themenstarter)
Anmeldungsdatum: 16. Oktober 2011
Beiträge: 12832
|
rklm schrieb:
| for p in $(btrfs fi show | sed -n 's#.* path ##p'); do sudo systemctl enable --now "btrfs-scrub@$(systemd-escape -p "$p").timer"; done
|
Das ist Blödsinn, so sollte es sein: | for p in $(lsblk -nflo FSTYPE,MOUNTPOINT | awk '$1=="btrfs"{print $2}'); do sudo systemctl enable --now "btrfs-scrub@$(systemd-escape -p "$p").timer"; done
|
|
encbladexp
Ehemaliger
Anmeldungsdatum: 16. Februar 2007
Beiträge: 17449
|
Developer92 schrieb: Das ist IMHO der einfachste und sinnvollste Ansatz den man machen kann. Erspart auch einiges an Kopfzerbrechen 😉
ACK, wenn man bei Storage denken muss, bekommt man meistens Probleme statt Lösungen. mfg Stefan
|
rklm
Projektleitung
(Themenstarter)
Anmeldungsdatum: 16. Oktober 2011
Beiträge: 12832
|
Developer92 schrieb:
Die Aufteilung der Partitionen läuft komplett über Subvolumes. Das ist IMHO der einfachste und sinnvollste Ansatz den man machen kann. Erspart auch einiges an Kopfzerbrechen 😉
Die Diskussion des "Ob" ist off-topic und ich habe auch keine Lust das hier zu diskutieren. So lange die *Ubuntu-Installer kein Neuinstallation mit diesem Setup (ein Dateisystem, zwei Subvolumes für / und /home) erlauben (gerade noch mal mit 18.04 getestet), sind mit einer HD/SSD zwei Partitionen für mich der "einfachste und sinnvollste Ansatz". Man kann sicher noch andere sinnvolle Szenarien finden, aber mein Interesse ist es die Ursprungsfrage des Themas zu beantworten. Hilfreich wäre z.B. die Antwort auf die Frage, ob es mit systemd eine Möglichkeit gibt, sicher zu stellen, dass jeweils nur eine Instanz einer Template-Unit zur Zeit läuft.
|
seahawk1986
Anmeldungsdatum: 27. Oktober 2006
Beiträge: 11181
Wohnort: München
|
rklm schrieb: Hilfreich wäre z.B. die Antwort auf die Frage, ob es mit systemd eine Möglichkeit gibt, sicher zu stellen, dass jeweils nur eine Instanz einer Template-Unit zur Zeit läuft.
Die selbe Instanz kann nicht mehrfach gestartet werden, aber unterschiedliche Instanzen (also ein abweichender Pfad nach dem btrfs-scrub@ Teil) können grundsätzlich parallel gestartet werden. Wenn ich https://www.freedesktop.org/software/systemd/man/systemd.timer.html#RandomizedDelaySec= richtig verstehe, dient der Wert nur dazu es unwahrscheinlicher zu machen, dass zwei Timer parallel laufen, aber es gibt keine harte Garantie, dass das nicht passiert. Wenn ich die Manpage zu btfs scrub richtig verstehe, forkt ein btrfs scrub start PARTITION in den Hintergrund und wartet daher nicht darauf, dass der Scrub abgeschlossen wird. So wie die Unit geschrieben ist würde Systemd nur die primäre PID tracken. Bei einem Programm, das in den Hintergrund forkt brächte man Type=forking - vgl. Beispiel 5 in https://www.freedesktop.org/software/systemd/man/systemd.service.html. Daher würde ich mir überlegen, ob da nicht ein kleines Shell-Skript sinnvoller wäre, das die zur Laufzeit vorhandenen BTRFS-Partitionen nacheinander abarbeitet. | [Unit]
Description=Scrub all btrfs filesystems
[Service]
Type=oneshot
ExecStart=/bin/bash -c "for p in $(lsblk -nflo FSTYPE,MOUNTPOINT | awk '$1==\"btrfs\"{print $2}'); do /bin/btrfs scrub start -B \"$p\"; done"
|
Dann braucht es auch nur einen Timer (den man in einen Zeitraum mit voraussichtlich wenig Nutzung legen kann), es gibt keine fehlgeschlagenen Scrub-Versuche, wenn man etwas an den vorhandenen Partitionen ändert und vergisst die Timer zu aktualisieren und die Unit kommt ohne Instanzen aus.
|
rklm
Projektleitung
(Themenstarter)
Anmeldungsdatum: 16. Oktober 2011
Beiträge: 12832
|
seahawk1986 schrieb: rklm schrieb: Hilfreich wäre z.B. die Antwort auf die Frage, ob es mit systemd eine Möglichkeit gibt, sicher zu stellen, dass jeweils nur eine Instanz einer Template-Unit zur Zeit läuft.
Die selbe Instanz kann nicht mehrfach gestartet werden, aber unterschiedliche Instanzen (also ein abweichender Pfad nach dem btrfs-scrub@ Teil) können grundsätzlich parallel gestartet werden. Wenn ich https://www.freedesktop.org/software/systemd/man/systemd.timer.html#RandomizedDelaySec= richtig verstehe, dient der Wert nur dazu es unwahrscheinlicher zu machen, dass zwei Timer parallel laufen, aber es gibt keine harte Garantie, dass das nicht passiert.
Ja, ist mir klar. Deshalb ja die Frage. Man kann natürlich immer Skripte mit flock bauen, aber ich hatte vermutet, dass systemd da schon etwas mitbringt. Ich habe schon gesucht, aber noch nix in der Richtung gefunden.
Wenn ich die Manpage zu btfs scrub richtig verstehe, forkt ein btrfs scrub start PARTITION in den Hintergrund und wartet daher nicht darauf, dass der Scrub abgeschlossen wird.
Richtig.
So wie die Unit geschrieben ist würde Systemd nur die primäre PID tracken. Bei einem Programm, das in den Hintergrund forkt brächte man Type=forking - vgl. Beispiel 5 in https://www.freedesktop.org/software/systemd/man/systemd.service.html.
Die Unit ist schon bewusst so geschrieben, weil es nur den anfänglichen Trigger braucht, damit der Scrub losläuft. Sollte er wegen eines Reboots unterbrochen werden, nimmt der Kernel nach dem Start die Arbeit selbständig wieder auf. Deshalb gibt es keinen Bedarf, von systemd überwachen zu lassen, ob der Scrub beendet wurde. Wenn es den genannten Mechanismus einer Mutex für alle Instanzen einer Template-Unit gäbe, würde ich die Unit anders schreiben. Dann sähe die Zeile so aus: | ExecStart=/bin/btrfs scrub start -fB "%f"
|
Damit ist sichergestellt, dass die Unit so lange aktiv ist wie der Scrub. Außerdem stellt -f sicher, dass ein aktiver Scrub nach dem Reboot nicht einfach im Hintergrund weiterläuft, sondern dann im Vordergrund synchronisiert wird. Es gibt aber trotzdem die Möglichkeit, dass in dem Szenario dann zwei Scrubs parallel laufen, fällt mir gerade auf.
Daher würde ich mir überlegen, ob da nicht ein kleines Shell-Skript sinnvoller wäre, das die zur Laufzeit vorhandenen BTRFS-Partitionen nacheinander abarbeitet.
Dann braucht es auch nur einen Timer (den man in einen Zeitraum mit voraussichtlich wenig Nutzung legen kann), es gibt keine fehlgeschlagenen Scrub-Versuche, wenn man etwas an den vorhandenen Partitionen ändert und vergisst die Timer zu aktualisieren und die Unit kommt ohne Instanzen aus.
Das würde für einen Server gut funktionieren, aber nicht für einen Desktop. Weil ein Desktop kürzer läuft und häufiger neu bootet, würde auf den früheren Dateisystemen in der Liste eine höhere Scrub-Last liegen, denn bei einem Abbruch durch Boot würde der Job wieder von vorne anfangen oder (falls nicht, da müsste ich noch mal die systemd-Doku wälzen), würde man die später in der Liste stehenden Dateisysteme sehr selten oder gar nicht mehr scrubben. Das könnte man nur lösen, wenn man für die einzelne Ausführung nachhält, welche Dateisysteme schon fertig sind. Das ist dann definitiv kein Einzeiler in der Unit mehr. Deshalb halte ich es bei einem Desktop für sinnvoller, wenn es einen Timer pro Dateisystem gibt, weil systemd dann für die einzelnen Timer die Ausführungen einzeln nachhält. Das müsste man ansonsten in dem Skript nachprogrammieren (s.o.).
|
rklm
Projektleitung
(Themenstarter)
Anmeldungsdatum: 16. Oktober 2011
Beiträge: 12832
|
Ich bin noch auf eine einigermaßen elegante Lösung gekommen. Anstatt ein Timer-Template in /etc/systemd/system/btrfs-scrub@.timer zu definieren, legt man einfach eine Datei für jeden Mountpunkt an und wählt dann manuell verschiedene Startpunkte. /etc/systemd/system/btrfs-scrub@-.timer | [Unit]
Description=Run btrfs scrub on / periodically
[Timer]
OnCalendar=*-*-1
Persistent=true
[Install]
WantedBy=timers.target
|
und /etc/systemd/system/btrfs-scrub@home.timer | [Unit]
Description=Run btrfs scrub on /home periodically
[Timer]
OnCalendar=*-*-15
Persistent=true
[Install]
WantedBy=timers.target
|
|
Developer92
Anmeldungsdatum: 31. Dezember 2008
Beiträge: 4101
|
rklm schrieb: Hilfreich wäre z.B. die Antwort auf die Frage, ob es mit systemd eine Möglichkeit gibt, sicher zu stellen, dass jeweils nur eine Instanz einer Template-Unit zur Zeit läuft.
Kurze Antwort: Nein. Zumindest wäre mir keine Möglichkeit bekannt das systemd direkt handhaben zu lassen. D.h. du müsstest dir eine Art scheduler basteln, der eine Platte nach der anderen schrubbt.
Man kann sicher noch andere sinnvolle Szenarien finden, aber mein Interesse ist es die Ursprungsfrage des Themas zu beantworten.
Ich hoffe du verzeihst wenn ich jetzt wieder dazwischen grätsche, aber: Ein Scrub läuft sowieso mit der niedrigsten möglichen Priorität was I/O betrifft, wenn die Platte also bereits durch einen Scrub I/O technisch ausgelastet ist, wie viel I/O zieht dann überhaupt der zweite Scrubvorgang wenn dieser gestartet wird? Konkreter: Existiert das Problem, welches du ansprichst, in der Praxis überhaupt oder ist das eher theoretischer Natur und mehr ein "wäre schön, das zu lösen, aber eigentlich nicht praxisrelevant"? Zitat aus dem btrfs wiki: The estimated device bandwidth utilization is about 80% on an idle filesystem. The IO priority class is by default idle so background scrub should not significantly interfere with normal filesystem operation. The IO scheduler set for the device(s) might not support the priority classes though.
Ich will deinen Thread nicht unnötig Offtopic machen, deshalb halte ich mich etwas zurück, aber ich würde das trotzdem überdenken. Ich sehe hier den Sinn einfach nicht. Systemd müsste das per default eig. schon alles sauber handhaben. Korrigiert ich, falls ich falsch liege 😉
|
rklm
Projektleitung
(Themenstarter)
Anmeldungsdatum: 16. Oktober 2011
Beiträge: 12832
|
Developer92 schrieb: rklm schrieb: Hilfreich wäre z.B. die Antwort auf die Frage, ob es mit systemd eine Möglichkeit gibt, sicher zu stellen, dass jeweils nur eine Instanz einer Template-Unit zur Zeit läuft.
Kurze Antwort: Nein. Zumindest wäre mir keine Möglichkeit bekannt das systemd direkt handhaben zu lassen.
Das deckt sich mit meinen bisherigen Rechercheergebnissen. Danke!
D.h. du müsstest dir eine Art scheduler basteln, der eine Platte nach der anderen schrubbt.
Ja, das wäre dann das schon erwähnte Skript. Aber dann finde ich die Lösung mit den individuellen Timer-Units schicker (aber siehe unten). Da nimmt einem systemd die Arbeit ab, auch, wenn es keine Garantie gibt, dass ein Scrub wirklich fertig ist, wenn der neue startet.
Ein Scrub läuft sowieso mit der niedrigsten möglichen Priorität was I/O betrifft, wenn die Platte also bereits durch einen Scrub I/O technisch ausgelastet ist, wie viel I/O zieht dann überhaupt der zweite Scrubvorgang wenn dieser gestartet wird? Konkreter: Existiert das Problem, welches du ansprichst, in der Praxis überhaupt oder ist das eher theoretischer Natur und mehr ein "wäre schön, das zu lösen, aber eigentlich nicht praxisrelevant"?
Mir geht es nicht nur um die Bandbreite für normale Nutzung. Ich erwarte, dass es zumindest auf einer ansonsten unbeschäftigten Magnetplatte einen Unterschied macht, ob nur ein Scrub läuft oder mehrere parallel laufen. Außerdem ist das eine nette Gelegenheit, etwas über systemd zu lernen (und das habe ich auch schon). Die Sache mit dem Scrub ist nur ein Teilaspekt.
Systemd müsste das per default eig. schon alles sauber handhaben. Korrigiert ich, falls ich falsch liege 😉
Die Behandlung der IO-Bandbreite ist nicht Sache von systemd - das ist der Kernel.
Es gibt noch eine Lösung, die Redundanz spart: 1. Service-Unit wie im Eingangsposting 2. Timer-Template für alle: /etc/systemd/system/btrfs-scrub@.timer | [Unit]
Description=Run btrfs scrub periodically
[Timer]
# OnCalendar via drop in
Persistent=true
[Install]
WantedBy=timers.target
|
3. Pro Mountpoint ein Drop-In: /etc/systemd/system/btrfs-scrub@-.timer.d/override.conf Bekommt man erzeugt, indem man sudo systemctl edit btrfs-scrub@-.timer eingibt. Und dann z.B. sudo systemctl edit btrfs-scrub@home.timer : | [Timer]
OnCalendar=*-*-15
|
Besonders schick finde ich, dass man Templates und konkrete Ausprägungen mischen kann. Die Service-Unit ist einfach ein generisches Template und die Timer-Units pro Instanz setzen sich aus einem generischen Template und einem Drop-In pro Instanz zusammen, das nur die spezifischen Änderungen enthält. Damit spart man Redundanz. So langsam werde ich mit dem Monster warm. ☺
|
seahawk1986
Anmeldungsdatum: 27. Oktober 2006
Beiträge: 11181
Wohnort: München
|
rklm schrieb: Besonders schick finde ich, dass man Templates und konkrete Ausprägungen mischen kann. Die Service-Unit ist einfach ein generisches Template und die Timer-Units pro Instanz setzen sich aus einem generischen Template und einem Drop-In pro Instanz zusammen, das nur die spezifischen Änderungen enthält. Damit spart man Redundanz. So langsam werde ich mit dem Monster warm. ☺
Man kann auch Vorgabewerte für OnCalendar= im allgemeinen Template nutzen
# allgemeines Template
[Timer]
OnCalendar=*-*-28
und den Wert dann in den Drop-In Dateien übersteuern, in dem man erst die bestehenden Werte löscht und dann den gewünschten Wert neu setzt:
# Drop-In Template
[Timer]
OnCalendar=
OnCalendar=*-*-15
Das hat den Vorteil, dass das allgemeine Template selber funktionsfähig ist.
|
rklm
Projektleitung
(Themenstarter)
Anmeldungsdatum: 16. Oktober 2011
Beiträge: 12832
|
Also, wir können das als erledigt betrachten, denn
Funktioniert die letzte Lösung für mich gut genug. Habe ich mittlerweile eine Neuinstallation hinbekommen unter Erhaltung eines /home-Subvolumes. Der Trick: man mountet das /-Subvolume vor der Installation und löscht darauf alles.
|