• Willkommen im Linux Club - dem deutschsprachigen Supportforum für GNU/Linux. Registriere dich kostenlos, um alle Inhalte zu sehen und Fragen zu stellen.

Batched discard script bei ext4:

revealed

Guru
Hallo.

Ich nutze SUSE 13.2 mit ext4 auf einer SSD. SUSE liefert für btrfs maintainance scripte. Dabei wird u.a. auch für btrfs trim wöchentlich ausgeführt. Kürzlich habe ich einem Script zu btrfs gesehen, dass es nicht weitermachen soll wenn das Dateisystem nicht btrfs ist. Also hier der verursacher mit dem ich die Notwendigkeit für meinen Script begründe:
/usr/share/btrfsmaintenance/btrfs-trim.sh
Code:
if [ $(stat -f --format=%T "$MNT") != "btrfs" ]; then
                echo "Path $MNT is not btrfs, skipping"
                continue
Beweis:
Code:
WILD-THING:/home/disk # stat -f --format=%T "/home"
ext2/ext3
Jedenfalls verstehe ich auf dieser Grundlage ein eigenes batched discard script zu benötigen. Dann habe ich einige andere scripte gesehen die in eine Datei schreiben. Jetzt dachte ich mir ich möchte das im Journal haben. Deswegen hab ich mir den etwas umgebaut.

Da ich nicht so super bewandert bin was bash /shell und überhaupt scripte angeht, würde ich mich freuen wenn ihr den anschauen würdet ob das so o.k. ist.

Er läuft momentan als cron.weekly; Er läuft auch durch. Aber wie halt?
- tmp für die Pipe habe ich hier gewählt, da es ein tmpfs im RAM ist bei mir.
- Angemeldete Desktopnutzer erhalten ausserdem eine Nachricht mithilfe von wall.

Gruß,

R

Code:
#!/bin/sh
### Trim script for SSD |trim.sh| ###
# - sends a message whats going on to logged in users with wall
# - Logs trim output to journal

# Filesystems to trim:
FS1=/
FS2=/home

# Setup logging:
LOGPIPE=/tmp/trimlogpipe.out;
# Check if Logpipe exists otherwise clean it prior:
if [ -e !$LOGPIPE ]
 then  mkfifo $LOGPIPE
elif [ -e $LOGPIPE ]
 then rm $LOGPIPE & mkfifo $LOGPIPE
fi

# Start logging to journal with identifier "trim.sh"
systemd-cat -t 'trim.sh'< $LOGPIPE &
exec 3>$LOGPIPE

# message for desktop users: (not logged)
TEXT="Starting trim for $FS1 and $FS2 the system might slow down while it is running."
wall -n $TEXT

# Execute the trim command and log to journal:
echo "*** $TEXT ***" >&3;
fstrim -v $FS1 >&3;
fstrim -v $FS2 >&3;

# closing file descriptor 3 closes the fifo
exec 3>&-
Ausgabe im Journal (run-crons):
Sep 10 08:59:58 WILD-THING trim.sh[5126]: *** Starting trim for / and /home the system might slow down while it is running. ***
Sep 10 08:59:58 WILD-THING trim.sh[5126]: /: 22 MiB (23035904 Bytes) getrimmt
Sep 10 08:59:58 WILD-THING trim.sh[5126]: /home: 600 KiB (614400 Bytes) getrimmt
Und die Nachricht von wall erscheint dann beim Nutzer beispielsweise bei KDE als Benachrichtigung im Infobereich.
 
Moin revealed,

ich hab noch nicht Alles durch geguckt aber der erste Fehler ist dein Test ob die LOGPIPE existiert. Kleines Beispiel:
Code:
#!/bin/bash
file=/test.txt
if [ -e !$file ]
then echo "ist nicht da"
else echo "da"
fi
ergibt "da" obwohl es nicht existiert.
Code:
#!/bin/bash
file=/test.txt
if [ ! -e $file ]
then echo "ist nicht da"
else echo "da"
fi
ergibt "ist nicht da". Dein Test ist also falsch. Ich weiß ehrlich gesagt auch nicht ob der Test "-e" überhaupt für pipes verwendet werden kann, eigentlich ist der für Dateitests da. Dann verstehe ich nicht warum Du "elif" und "then" verwendest wo ein "else" es genauso tut. Als nächstes willst Du sicherlich nicht das "rm $LOGPIPE" in den Hintergrund schicken sondern die beiden Befehle "rm" und "mkfifo" hintereinander ausführen. Dafür verwendet man das "&&".
Zum Rest muß dir aber wahrscheinlich jemand anderes was schreiben da ich mich weder mit named-pipes noch mit trim auskenne.
 
OP
revealed

revealed

Guru
Hallo.

ergibt "ist nicht da". Dein Test ist also falsch.
Das korrigiere ich jetzt. (Den Script würde ich dann am Ende nochmal posten).

-e FILE
FILE exists
Das sollte schon passen. Also die Logpipe ist ja ein File. Die Abfrage eigentlich auch nur, weil sonst eine unschöne Warnung geschmissen werden kann von mkfifo.

Ja das mit der Pipe... das ist eine gute Frage. Zumal ich ja auch irgendwie wo reinschreiben muss, wie es scheint. Ich würde das am liebsten gerne ohne einen Zwischenschtopp auf ein Laufwerk machen.

Ich weiss leider nicht, wie.

Vielen Dank schonmal!

Gruß,

R

PS.: Ich hängs mal hier als paste rein:
http://susepaste.org/47025025
 
OP
revealed

revealed

Guru
Ich hab nochmal ganz umgebaut:

(da hab ich das && wieder verplant)...
http://susepaste.org/33980609

- geht jetz ohne zwischenstopp in einer extra Datei.
- Man kann mountpoints als durch leerzeichen getrennte Liste eintragen.

Damit erledigt sich auch das mkfifo, wozu ich zunächst durch deine Hilfe die Abfrage korrigiert hatte.

Oh böser Nebeneffekt... er erstellt einfach eine Datei namens "2" und schreibt da rein. So gehts doch nicht. :(

Gruß,

R
 

josef-wien

Ultimate Guru
Zum "alten" Skript:

Wenn sowohl bei then als auch bei else etwas gemacht wird, sollte man sich vor Abfragen "ist nicht" hüten, sie erschweren im nachhinein das Verständnis.
revealed schrieb:
rm $LOGPIPE & mkfifo $LOGPIPE
Der zweite Befehl wird nur dann ausgeführt, wenn der erste in Ordnung geht, d. h. es ist gleichgültig, ob eine neue Datei angelegt oder die alte verwendet wird.

Vorschlag:
Code:
if test -e $LOGPIPE
  then rm $LOGPIPE
fi
mkfifo $LOGPIPE
if test $? -eq 0
  then echo Verarbeitung
  else echo Fehler
fi
Eine Information, daß das Skript fertig ist, scheint mir übrigens sinnvoller als das in der Praxis unnötige "könnte das System bremsen".
_______

Zum "neuen" Skript:

revealed schrieb:
er erstellt einfach eine Datei namens "2" und schreibt da rein
Genau das hast Du verlangt.

Strichpunkt und neue Zeile ist "doppelt gemoppelt".
 
OP
revealed

revealed

Guru
Genau das hast Du verlangt.
Falls du weisst wie... ? Würdest du mir bitte zeigen, wie ich die Info im Speicher behalte, ohne sie in ein File zu stopfen? Das wäre mir eigentlich die liebste Lösung.

Falls das nicht möglich ist, würde ich dann auch den genannten Lösungsweg verwenden.

Gruß,

R
 
OP
revealed

revealed

Guru
oh mann ich habe gerade im IRC erfahren, dass in systemd auch eine solchige funktion schon mit drin ist.

Quelle:
https://lizards.opensuse.org/2015/02/06/ssd-configuration-for-opensuse/#comment-14717

Eine Lösung wäre also:
Code:
systemctl enable fstrim.timer

Aber mir ist das Script irgendwie lieber weil ich eben sehe was passiert. Sonst bekomm ich des ja garnicht mit. Würde mich nach wie vor über eine Lösung zur Loganbindung freuen.

@josef-wien: Bei deinem letzten Tipp bin ich übrigens an der Umsetzung gescheitert. Deswegen sieht er jetz so aus.
http://susepaste.org/64474041
Ich füre das aber auf mein geringes können zurück.

Gruß,

R
 
OP
revealed

revealed

Guru
Hallo.

Code:
if test -e $LOGPIPE
  then rm $LOGPIPE
fi
mkfifo $LOGPIPE
if test $? -eq 0
  then echo Verarbeitung
### <- Hier müsste mein Script dazwischen?
  else echo Fehler
fi

Dann funktioniert er nicht mehr. Ich glaub da wären größere nacharbeiten nötig? Und da hab ich mich ca. 2 Stunden drin verlaufen. Ich kenn mich halt echt null aus. Habs sogar mit einer Funktion versucht. Er bleibt immer stehen.

edit: Ich war davon auch so frustriert, dass ich es immer überschrieben hab und am ende gelöscht und wieder aus dem Paste importiert habe, weil ich am Ende alles durcheinander hatte. /edit

Deswegen hab ich es jetz mal so in der letzten Version gemacht, dass ich da den else exit 0; (Sorry falls das wieder ein Rückschritt war).

util-linux-systemd installieren, und logger anschauen?
hab ich installiert. Davon bin ich gleich weg, weil ich ja zu systemd loggen möchte und logger ist für "syslog" der ist nicht installiert.

Gruß,

R
 

josef-wien

Ultimate Guru
Die Zeilen 1 bis 10 bleiben. Meine Befehle ersetzen die Zeilen 11 bis 16.
revealed schrieb:
### <- Hier müsste mein Script dazwischen?
Hier kommt alles ab Zeile 17 (# Start logging to journal with identifier "trim.sh").

P. S. Laut manpage gibt es den Parameter "--journald".
 
OP
revealed

revealed

Guru
Ja so gehts auf einmal -- jetzt frag ich mich aber echt. :???: :eek:ps:
http://susepaste.org/88583293

Das habe ich nicht gesehen. Dafür schonmal vielen Dank! Leider leider nahm ich ursprünglich diesen Satz zum Anlass nicht weiter zu lesenen:
logger - a shell command interface to the syslog(3) system log module
--journald ..... The entry is read from stdin or input file. ....
... überlege gerade wie ...

Ich hab schonmal folgende schwierigkeit damit:
Aus der Manpage copy paste:
Code:
printf "%s\n%s\n%s\n" MESSAGE_ID=42 DOGS=bark "CARAVAN=goes on" | logger --journald
Kein eintrag im journal aufzufinden.

Und wenn ich es so versuche:
Code:
log="logger --journald";
logger: journald entry could not be wrote

omg! Man lasse einfach den "--journald" weg ---- ärgerlich die Umwege vorher....:
Code:
#!/bin/sh -x
### Trim script for SSD |ext4-trim.sh| ###
# - sends a message whats going on to logged in users with wall
# - Logs trim output to journal
# Space separated list of filesystems to trim:
FS="/ /home";
# message for desktop users: (not logged)
TEXT="Starting batched trim!";
# Setup logger with identifier:
log="logger -t ext4-trim.sh";
# Send message:
wall -n $TEXT;
# Execute the trim command and log to journal:
echo "*** $TEXT ***" | $log;
 for i in $FS; do
  /usr/sbin/fstrim -v "$i" | $log;
 done;
exit 0;
#  else echo Fehler
#fi
Jetzt könnte man sich überlegen, wovon der Script aussteigen soll.
 
OP
revealed

revealed

Guru
Übrigens hab ich die Erkenntnis über die durch systemd gelieferte Funktion zum Anlass hierfür hergenommen:
http://linux-club.de/wiki/opensuse/Systemd#Tipp:_weekly_trim_durch_systemd

Gruß,

R
 
Oben