Bash: if und grep

ghostadmin

Grand Admiral Special
Mitglied seit
11.11.2001
Beiträge
25.179
Renomée
184
Standort
Dahoam Studios
Ich möchte bei einer Ausgabe einen grep machen, wenn eine bestimmte variable gesetzt ist z.B.

Code:
zfs list -t snapshot | if [ -n "$zfsfolder" ]; then grep "$zfsfolder"; fi | if [ -n "$zfsschedule" ]; then grep "$zfsschedule"; fi

nur dummerweise funktioniert das anders als erwartet aber warum?
wie könnte man das noch machen ohne zig Kombinationen aufzuführen?
 
Das schreit IMO nach einer for-Schleife:
Code:
zfs list -t snapshot |
for d in "$zfsfolder" "$zfsschedule"
do
    if [[ -n "$d" ]]
    then
        grep "$d"
    fi
done
Der Code ist ungetestet, es könnte also sein, dass der Schleifenkopf so nicht stimmt. Die if-Bedingung könnte man so aber sogar in eine Funktion auslagern, was vor allem dann sinnvoll ist, wenn da noch mehr Befehle um das grep herum gegeben sind.

MfG Dalai
 
hmm das zweite grep wird ignoriert

Code:
#!/bin/bash
zfsfolder=data1/test
zfsschedule=[B]weekly[/B]

zfs list -t snapshot |
for d in "$zfsfolder" "$zfsschedule"
do
    if [[ -n "$d" ]]; then
        grep "$d"
    fi
done

output:
data1/test@daily2014-12-27:11:00:48 0 - 30K -
data1/test@daily2014-12-27:11:04:31 0 - 30K -
....
...
..

kann man for überhaupt mit 2 Argumenten laufen lassen?
 
hmm das zweite grep wird ignoriert
Welches zweite? In meinem Code gibt's nur eines.

kann man for überhaupt mit 2 Argumenten laufen lassen?
Natürlich, denn das ist eine for-in-Schleife. Aber ich sehe meinen Fehler, der durch meine Unachtsamkeit, kombiniert mit fehlender Formatierung deines Codes (es lebe Einrückung), ausgelöst wurde: es fehlt die zweite Pipe. Von daher wäre es wohl besser, vorher alle Argumente auf Gültigkeit zu prüfen und dann alles in einem Rutsch abzufackeln:
Code:
if [[ -n "$zfsfolder" ]] && [[ -n "$zfsschedule" ]]
then
    zfs list -t snapshot | grep "$zfsfolder" | grep "$zfsschedule"
fi
Wenn das noch mehr zu prüfende Variablen werden, lohnt es sich vermutlich, das noch weiter zu optimieren, z.B. durch Zwischenspeicherung der Ergebnisse der greps/Befehle. Wenn man das tut, sollte man folgendes beachten: Nach meiner Erfahrung sind Zugriffe auf Dateien von der Laufzeit her schneller, als wenn man Befehlsausgaben in Variablen speichert - eigentlich müssten Speicherzugriffe schneller sein, unabhängig davon, ob die temporäre Datei im Cache liegt oder nicht; vielleicht isses auch eine Eigenheit der Bash (hab andere Shells nicht geprüft).

MfG Dalai
 
Zuletzt bearbeitet:
Zweite Pipe wo?

Von daher wäre es wohl besser, vorher alle Argumente auf Gültigkeit zu prüfen und dann alles in einem Rutsch abzufackeln

Das wäre zu einfach, die Variablen können auch leer sein und der Befehl soll trotzdem ausgeführt werden (dann ohne betreffendem grep).
 
Guckst du in deinem OP: da steht vor jeder der beiden if-Bedingungen eine.

Das wäre zu einfach, die Variablen können auch leer sein und der Befehl soll trotzdem ausgeführt werden (dann ohne betreffendem grep).
Dann solltest du das gleich zu Beginn so schreiben. Dann leite die Ausgabe von "zfs list" in eine temporäre Datei um (mktemp) und greppe dann nur bei Gültigkeit der Variableninhalte. Also so in der Art:
Code:
blub=$(mktemp)

zfs list -t snapshot > "$blub"

if [[ -n "$zfsfolder" ]] && [[ -n "$zfsschedule" ]]
then
   grep "$zfsfolder" "$blub" | grep "$zfsschedule"
fi

rm -f "$blub"
Aber es sind eh Schüsse ins Blaue, wenn nur die Hälfte der Infos gegeben sind... Denn was da wo unter welcher Bedingung noch ausgeführt werden soll, unabhängig vom grep, und was da wie gepipet werden soll: *noahnung*.

MfG Dalai
 
Wie oben geschrieben soll der grep nur gemacht werden wenn eine bestimmte Variable gesetzt ist. Das Script kann mit unterschiedlichen Parametern aufgerufen werden z.B. -l um alle Snapshots zu listen und wenn zusätzlich $zfsschedule und/oder $zfsfolder als Parameter angegeben sind soll das Ergebnis weiter gefiltert werden. Deswegen stehen ja die ganzen if oben und nicht nur eins.
 
zfsfolder=data1/test
zfsschedule=weekly

zfs list -t snapshot | grep ^$zfsfolder |grep $zfsschedule | tr -s " " | while read backupname backupgroesse minus gesamtgroesse minus;do echo "$backupname #### $backupgroesse #### $gesamtgroesse" ;done
 
if [ "$zfsfolder" ];then
GREP_OPT="grep ^
$zfsfolder"
elif [ "$
zfsschedule" ];then
GREP_OPT="grep $zfsschedule"
fi

zfs list -t snapshot | $
GREP_OPT | tr -s " " | while read backupname backupgroesse minus gesamtgroesse minus;do echo "$backupname #### $backupgroesse #### $gesamtgroesse" ;done

besser kommste eh mit ner "case" wo du die werte schion abrufst und je nachdem dann die liste der snapshots in nen array schreibst.

case "$1" in
-l|-list)
SNAPSHOTS=$( zfs list -t snapshot )
;;
-s|-suche)
SNAPSHOTS=$( zfs list -t snapshot | grep $2 )
;;
esac

for $SNAP in ${SNAPSHOTS
[*]};do
echo $SNAP
done







 
Zuletzt bearbeitet:
Das müsste dann eher so:
Code:
if [ -n "$zfsfolder" ] && [ -n "$zfsschedule" ]; then
    GREP_OPT="grep $zfsfolder | grep $zfsschedule"
elif [ -n "$zfsfolder" ]; then
    GREP_OPT="grep $zfsfolder"
elif [ -n "$zfsschedule" ]; then
    GREP_OPT="grep $zfsschedule"
fi

Wenn aber beide zfsschedule und zfsfolder leer sind kommt gar kein Output und mit beiden gesetzten Parametern kommt ein Fehler von grep weil er meint das | noch Bestandteil von grep ist.

Bei letzterem stand das in der Variable:
grep ^data1/test | grep daily
Fehler:
grep: |: Datei oder Verzeichnis nicht gefunden
grep: grep: Datei oder Verzeichnis nicht gefunden
grep: daily: Datei oder Verzeichnis nicht gefunden

Ansonsten schreib ich den Befehl halt 4x hin wenns nicht anders geht.
 
Dann setze die leeren Variablen auf "." und schon geht's, denn grep sucht dann zwar ebenfalls, aber der Punkt steht ja für ein beliebiges Zeichen, und somit wird nichts weiter gefiltert. Sowas sollte man allerdings nur machen, wenn es nicht auf Laufzeit ankommt.

MfG Dalai
 
Hätte jetzt 2 verschiedene Lösungen

Code:
if [ -z $zfsfolder ]; then
    zfsfolder="."
fi
if [ -z $zfsschedule ]; then
    zfsschedule="."
fi

zfs list -H -t snapshot -o name,creation -s creation | grep $zfsfolder | grep $zfsschedule

Code:
zfslist="zfs list -H -t snapshot -o name,creation -s creation"
if [ $zfsfolder ] && [ $zfsschedule ]; then
    $zfslist | grep $zfsfolder | grep $zfsschedule
elif [ $zfsfolder ]; then
    $zfslist | grep $zfsfolder
elif [ $zfsschedule ]; then
    $zfslist | grep $zfsschedule
else
    $zfslist
fi

Bei zweitem Frage ich mich gerade warum es mit if [ -n $zfsfolder ] nicht funktioniert wenn die Variable nicht gesetzt ist. Habe also da einen match bei if mit leerer Variable, mit if [ $zfsfolder ] gehts dagegen.
 
setz die variablem mal in "XXXX" bash mag keine lerren variablen in if while for etc

case wäre trotzdem die saubere methode mit

*)
echo "ungueltige Variable"
;;

kannst du falsch eingaben abfangen. auch gibts in bash die Funktion "GETOPT"
http://wiki.bash-hackers.org/howto/getopts_tutorial
 
Zuletzt bearbeitet:
getopts benutze ich schon, dass Script hat 18 Parameter und 388 Zeilen ;)

Code:
 echo "$progname [-M snap] [-cklr] [-S schedule] [-K keep] [-F path/to/src/zfs]"
    echo "-F FOLDER source zfs dataset where snapshot should be taken"
    echo "-K KEEP amount of generations or days the snapshots should be kept"
    echo "   i.e. d7 for 7 days or g7 max. 7 generations"
    echo "-S SCHEDULE daily,weekly,monthly schedule, this is just a name for the snapshot"
    echo "optional parameters:"
    echo "-c only do cleanup of snapshots older than keep amount, no new snapshot"
    echo "-k just kill all snapshots, nothing else"
    echo "-l list all related snapshots, no new snapshot"
    echo "-r recursive, do a snapshot recursive on all datasets"
    echo ""
    echo "or for zfs send and remote zfs receive:"
    echo "$progname [-M send] [-diIrs] [-F path/to/src/zfs] [-H host] [-p port] [-S schedule]"
    echo "          [-T path/to/target/zfs] [-m mailaddress] [-u user] [-w mac]"
    echo "-F FOLDER source zfs dataset containing the snapshot for zfs send"
    echo "-H HOST remote host as backup target"
    echo "-S SCHEDULE daily,weekly,monthly schedule"
    echo "-T TARGET target zfs dataset for storing the zfs data"
    echo "optional parameters:"
    echo "-d destroy old snapshots on the remote zfs related to local source folder"
    echo "   works only if zfs receive was done with -d option to use folder as prefix"
    echo "   do not use if you plan to send incremental snapshots"
    echo "-i incremental sends difference between 2 last snapshots (cannot be used with -d option)"
    echo "   only works when the filesystem already exists in the target"
    echo "-I incremental sends difference between first and last snapshot"
    echo "-m MAIL adress for sending log"
    echo "-p PORT ssh port (default 22)"
    echo "-r recursive, sends all child snapshots"
    echo "-s shutdown remote host after zfs send"
    echo "-u USER ssh user (default root)"
    echo "-w MAC address for wakeup"
    echo "Example initial: $progname -r -F data1/filer -H 192.168.5.180 -S daily -T diskpool/backup"
    echo "     inremental: $progname -ir -F data1/filer -H 192.168.5.180 -S daily -T diskpool/backup"
 
Bei zweitem Frage ich mich gerade warum es mit if [ -n $zfsfolder ] nicht funktioniert wenn die Variable nicht gesetzt ist. Habe also da einen match bei if mit leerer Variable, mit if [ $zfsfolder ] gehts dagegen.
Nein, nicht leere Variable sondern ein (nicht)leerer String wird hier geprüft! Und Strings müssen eben in Anführungszeichen stehen, damit sie korrekt ausgewertet werden.

MfG Dalai
 
Ich erzeuge also eine Liste die in einer Variable gespeichert wird.

Wenn ich dann mit:
for snapshot in $zfssnaplist
das ganze zeilenweise durchgehe dann fehlt dort aber das Datum, es ist nur der Name des Snapshots enthalten. Warum?

Was mir auch aufgefallen ist, wenn man die komplette zfssnaplist mit echo ausgibt, ist das Datum drin aber die Formattierung total durcheinander. Die Werte sind nicht mehr durch Zeilen getrennt sondern nur durch Leerzeichen.

Muss ich das dann in ein Array speichern und wenn ja wie?

Hier wie das normal aussieht:
data1/test@daily2014-12-27:11:00:48 Sa Dez 27 11:00 2014
data1/test@daily2014-12-27:11:04:31 Sa Dez 27 11:04 2014
data1/test@daily2014-12-27:11:07:28 Sa Dez 27 11:07 2014
data1/test@daily2014-12-27:11:14:55 Sa Dez 27 11:14 2014

Das Datum erhalte ich sonst mit: awk '{ print $4 "-" $3 "-" $6 }'

Beim for wird aber nur z.B. data1/test@daily2014-12-27:11:00:48 ausgegeben
 
Zuletzt bearbeitet:
Wenn ich dann mit:
for snapshot in $zfssnaplist
das ganze zeilenweise durchgehe dann fehlt dort aber das Datum, es ist nur der Name des Snapshots enthalten. Warum?
Eine for-in-Schleife splittet an Leerzeichen bzw. genaugenommen IIRC an $IFS, also Leerzeichen, Tabs und Newlines. Daher lassen sich auch Dateien mit einer solchen Schleife verarbeiten, z.B. sowas:
Code:
for f in /opt/*.sh
do
    # befehl hier
done

Was mir auch aufgefallen ist, wenn man die komplette zfssnaplist mit echo ausgibt, ist das Datum drin aber die Formattierung total durcheinander. Die Werte sind nicht mehr durch Zeilen getrennt sondern nur durch Leerzeichen.
Du hast Anführungszeichen bei der Ausgabe der Variable vergessen, wodurch sämtliche Formatierung verlorengeht.

Muss ich das dann in ein Array speichern und wenn ja wie?
Kann man machen, muss man aber nicht unbedingt, denn das kann Zirkus werden, da IIRC auch dort an $IFS gesplittet wird.

MfG Dalai
 
Wenn ich sage:
Code:
for snapshot in "$zfssnaplist"; do
$snapshotndate=$(echo "$snapshot" | awk '{ print $4 "-" $3 "-" $6 }' | tr -d '\n')
echo "snap: $snapshotdate\n"

Dann bekomme ich als Ausgabe von $snapshotdate:
snap: 27-Dec-201427-Dec-201427-Dec-201427-Dec-201427-Dec-201427-Dec-201427-Dec-201427-Dec-201427-Dec-201427-Dec-201427-Dec-201427-Dec-201427-Dec-201427-Dec-201427-Dec-201427-Dec-201427-Dec-201427-Dec-201427-Dec-201428-Dec-201428-Dec-201428-Dec-201428-Dec-201428-Dec-201428-Dec-201428-Dec-201428-Dec-201428-Dec-201428-Dec-201428-Dec-201428-Dec-201428-Dec-201428-Dec-201428-Dec-201428-Dec-201428-Dec-201428-Dec-201428-Dec-201429-Dec-201429-Dec-201429-Dec-201429-Dec-201429-Dec-201429-Dec-201429-Dec-201429-Dec-2014\n

Die for Schleife rennt also nur 1x. Muss ich dann den Output von zfs list neu formatieren? Das trennt via TAB

Der Befehl ist wie folgt:
zfssnaplist=$(LC_ALL=C zfs list -H -t snapshot -o name,creation -s creation | grep "$zfsfolder" | grep "$zfsschedule")
 
Zuletzt bearbeitet:
Eine for-in-Schleife ist für solche Ausgaben (mehrere Trennzeichen) ungeeignet, sofern man nicht am $IFS rumspielen will. Warum nicht einfach
Code:
echo "$zfssnaplist" | awk '{...}' usw.
? Oder, wenn du es zeilenweise verarbeiten musst:
Code:
echo "$zfssnaplist" |
while read line
do
    # befehle hier
done
wobei man line auch noch aufsplitten kann, wenn man genau weiß, wie eine Zeile aufgebaut ist (*). Beachte bei letzterem Fall, dass innerhalb der while-Schleife gesetzte Variablen nach dem Ende der Schleife den Inhalt von vor der Schleife haben, weil hier eine Pipe im Einsatz ist!

*) Ich setze sowas z.B. bei df ein:
Code:
df |
while read fs blocks used avail usep mount
do
    # hier kann man dann auf alle Teile einer Zeile einzeln zugreifen
done

MfG Dalai
 
Warum nicht einfach echo "$zfssnaplist" | awk '{...}' usw.

da komme ich nicht ganz mit

while read line; do

genau das funktioniert.

nun kann ich sehen welche Snapshots "reif" sind zu löschen
snapshotdate=$(echo "$snapshot" | awk '{ print $4 "-" $3 "-" $6 }' ) #get date of snapshot
getsnapsec=$(date +%s -d "$snapshotdate") #get age of snapshot in seconds since 1970
getnowsec=$(date +%s -d `LANG=C date +%b-%d-%Y`) #get seconds of 1970 until now
keepsec=$(( $days * 24 * 60 * 60 )) #convert days in seconds
allowedsec=$(( $getsnapsec + $keepsec ))

Oder kann man das einfacher mit date machen?
 
da komme ich nicht ganz mit
Ich sagte ja bereits: mit den gegebenen Informations-/Code-Häppchen ist es schwierig, sinnvollen Code vorzuschlagen, weil vielleicht andere Varianten viel besser geeignet sind, aber das Gesamtbild dafür fehlt. Es würde ja schon reichen, mal zu beschreiben, was rein kommt und was rauskommen soll.

Oder kann man das einfacher mit date machen?
Vorsicht, da sind ein paar Stolperfallen/Ungenauigkeiten in deinem Code: ich würde immer auf Backticks verzichten, denn die Dinger braucht kein Mensch mehr (sie sind nicht schachtelbar, sie sind unleserlich und lassen sich zu leicht mit einfachen Annführungszeichen verwechseln). Außerdem würde ich bei Berechnungen mit date immer auf LANG=C achten, d.h. auch in der Zuweisung von getsnapsec; das setzt natürlich voraus, dass dein awk-Ausdruck das Datum im passenden Format ausgibt (hab ich jetzt nicht geprüft). Weiterhin stimmt der Kommentar zum getnowsec nicht, denn dieser Befehl holt sich die vergangenen Sekunden bis zur vergangenen Mitternacht (momentan also 29.12.2014 00:00), nicht bis jetzt.

Hat es einen bestimmten Grund, den Kram in Sekunden umzurechnen, wenn du eh Tage reingibst? Und wieso wird das Alter des Snapshots zur Haltezeit addiert? *kopfkratz

MfG Dalai
 
Bitte das Problem mal nach http://de.wikipedia.org/wiki/EVA-Prinzip erklären. Also Beispiel Eingabe formulieren und was willst du in verschiedenen Fällen als Ausgabe haben. Dann kann man dir wesentlich einfacher helfen. In einem so langen Forum-Thread verliert man sonst schnell die Übersicht.

Hab keine zfs Ausgabe nehme daher einfach mal daily von automysqlbackup
Code:
#ls -lt /var/lib/automysqlbackup/daily/redmine/
total 264
-rw------- 1 root root 42432 Dez 30 06:49 redmine_2014-12-30_06h49m.Dienstag.sql.gz
-rw------- 1 root root 42431 Dez 29 06:30 redmine_2014-12-29_06h30m.Montag.sql.gz
-rw------- 1 root root 42433 Dez 28 06:32 redmine_2014-12-28_06h32m.Sonntag.sql.gz
-rw------- 1 root root 42432 Dez 26 06:48 redmine_2014-12-26_06h48m.Freitag.sql.gz
-rw------- 1 root root 42436 Dez 25 06:53 redmine_2014-12-25_06h53m.Donnerstag.sql.gz
-rw------- 1 root root 42433 Dez 24 06:28 redmine_2014-12-24_06h28m.Mittwoch.sql.gz

verschiedene greps (hoffentlich hilfts)
Code:
# ls -lt /var/lib/automysqlbackup/daily/redmine/ | grep -Po "redmine.*"
redmine_2014-12-30_06h49m.Dienstag.sql.gz
redmine_2014-12-29_06h30m.Montag.sql.gz
redmine_2014-12-28_06h32m.Sonntag.sql.gz
redmine_2014-12-26_06h48m.Freitag.sql.gz
redmine_2014-12-25_06h53m.Donnerstag.sql.gz
redmine_2014-12-24_06h28m.Mittwoch.sql.gz
# ls -lt /var/lib/automysqlbackup/daily/redmine/ | grep -Po "redmine.*2014.*"
redmine_2014-12-30_06h49m.Dienstag.sql.gz
redmine_2014-12-29_06h30m.Montag.sql.gz
redmine_2014-12-28_06h32m.Sonntag.sql.gz
redmine_2014-12-26_06h48m.Freitag.sql.gz
redmine_2014-12-25_06h53m.Donnerstag.sql.gz
redmine_2014-12-24_06h28m.Mittwoch.sql.gz
# ls -lt /var/lib/automysqlbackup/daily/redmine/ | grep -Po "redmine.*2014.*Sonntag.*"
redmine_2014-12-28_06h32m.Sonntag.sql.gz
 
IWeiterhin stimmt der Kommentar zum getnowsec nicht, denn dieser Befehl holt sich die vergangenen Sekunden bis zur vergangenen Mitternacht (momentan also 29.12.2014 00:00), nicht bis jetzt.

date +%s holt die Sekunden seit der Unix Epoche 1970-01-01 00:00:00 UTC. Die Frage war ja nicht ob das funktioniert sondern obs noch einen anderen Weg gibt mit der man das Datum ohne Umwandlung voneinander abziehen kann.
Mittlerweile habe ich allerdings auch noch die Stunden integriert.

Was seltsames, in der Schleife habe ich d=$((d+1))
Als Ausgabe dann echo "$d snapshots were deleted"
Es wird aber kein Wert angezeigt.

Code:
clean_zfssnap() {

# clean old zfs snapshots according to keep interval
echo "--- start cleanup of local zfs snapshots ---" | tee -a $logfiletemp

# put . in variable if not set, otherwise grep fails
if [ -z "$zfsschedule" ]; then
    zfsschedule="."
fi
if [ -z "$zfsfolder" ]; then
    zfsfolder="."
fi

# use LC_ALL=C for getting output in english (otherwise months are not english and can not be handled by date command)
if [ "$zfsrecursive" == "1" ]; then
    echo "searching for recursive snapshots containing: ${zfsfolder} and ${zfsschedule}" | tee -a $logfiletemp
    zfssnaplist=$(LC_ALL=C zfs list -H -t snapshot -o name,creation -s creation | grep "$zfsfolder" | grep "$zfsschedule") #command cannot be put in variable because fails when LC_ALL is used
else
    echo "searching for snapshots containing: ${zfsfolder}@ and ${zfsschedule}" | tee -a $logfiletemp
    zfssnaplist=$(LC_ALL=C zfs list -H -t snapshot -o name,creation -s creation | grep "${zfsfolder}@" | grep "$zfsschedule")
fi

if [ "$?" != "0" ]; then
    echo "Error: could not get list of snapshots" | tee -a $logfiletemp
    exit $?
else
    echo "OK: list of snapshots was created" | tee -a $logfiletemp
    #echo "$zfssnaplist"
fi

keepgen=$(echo $snapkeep | egrep '^g[0-9]+$')
keepday=$(echo $snapkeep | egrep '^d[0-9]+$')
keephour=$(echo $snapkeep | egrep '^h[0-9]+$')

if [ -n "$keepgen" ] && [ -n "$zfssnaplist" ]; then
    generations=$(echo "$snapkeep" | tr -d 'g')
    echo "keep generations $generations was specified in parameter"
    # get amount of snapshots (oldest first) and delete until we have allowed number of generations
    echo "$zfssnaplist" |
    while read snapshot; do
        #echo $snapshot | awk '{ print $1 }'
        i=$((i+1))
        if [ $i -gt $generations ]; then
            d=$((d+1))
            snapshotname=$(echo "$snapshot" | awk '{ print $1 }')
            echo "remove snapshot $snapshotname"
            #zfssnapdestroy=(zfs destroy $snapshotname)
            if [ "$?" != "0" ]; then
                echo "Error: could not destroy snapshot $snapshotname" | tee -a $logfiletemp
            else
                echo "OK: snapshot $snapshotname was destroyed" | tee -a $logfiletemp
            fi

        fi
    done
elif ( [ -n "$keepday" ] || [ -n "$keephour" ] ) && ( [ -n "$zfssnaplist" ] ); then

    if [ -n "$keepday" ]; then
        alloweddays=$(echo "$snapkeep" | tr -d 'd')
        echo "keep days $alloweddays was specified in parameter"
    elif [ -n "$keephour" ]; then
        allowedhours=$(echo "$snapkeep | tr -d 'h')
        echo "keep hours $allowedhours was specified in parameter"
    else
        echo "Error: could not get keep interval" | tee -a $logfiletemp
    fi

    echo "$zfssnaplist" |
    while read snapshot; do
        i=$((i+1))
        snapshotdate=$(echo "$snapshot" | awk '{ print $3 "-" $4 "-" $6 }' ) # get date of snapshot i.e. Dec-26-2014 11:11
        snapshothour=$(echo "$snapshot" | awk '{ print $5 }')

        getsnapdatesec=$(date +%s -d "$snapshotdate") #get age of snapshotdate in seconds since 1970
        getsnaphoursec=$(date +%s -d "$snapshothour")

        getdatenowsec=$(date +%s -d $(LANG=C date +%b-%d-%Y)) #get seconds of 1970 until now
        gethournowsec=$(date +%s -d $(LANG=C date +%H:%M))

        getsnapagedate=$(( $getdatenowsec - $getsnapdatesec ))
        getsnapagehours=$(( $gethournowsec - $getsnaphoursec ))

        getsnapage_s=$(( $getsnapagedate + $getsnapagehours ))
        getsnapage_h=$(( $getsnapage_s / 3600 ))
        getsnapage_d=$(( $getsnapage_s / 86400 ))

        if [ -n "$alloweddays" ] && [ -n "$getsnapage_d" ]; then
            if (( $getsnapage_d > $alloweddays )); then
                snapshotname=$(echo "$snapshot" | awk '{ print $1 }')
                d=$((d+1))
                #zfssnapdestroy=(zfs destroy $snapshotname)
                if [ "$?" != "0" ]; then
                    echo "Error: could not destroy $getsnapage_d days old snapshot $snapshotname from $snapshotdate $snapshothour" | tee -a $logfiletemp
                else
                    echo "OK: $getsnapage_d days old snapshot $snapshotname from $snapshotdate $snapshothour was destroyed" | tee -a $logfiletemp
                fi
            fi
        elif [ -n "$allowedhours" ] && [ -n "$getsnapage_h" ]; then
            if (( $getsnapage_h > $allowedhours )); then
                snapshotname=$(echo "$snapshot" | awk '{ print $1 }')
                d=$((d+1))
                #zfssnapdestroy=(zfs destroy $snapshotname)
                if [ "$?" != "0" ]; then
                    echo "Error: could not destroy $getsnapage_h hours old snapshot $snapshotname from $snapshotdate $snapshothour" | tee -a $logfiletemp
                else
                    echo "OK: $getsnapage_h hours old snapshot $snapshotname from $snapshotdate $snapshothour was destroyed" | tee -a $logfiletemp
                fi
            fi
        else
            echo "Error: could not calculate snapshot age ( got $getsnapage_d days = $getsnapage_h hours)" | tee -a $logfiletemp
        fi
    done

else
    echo "Error: KEEP parameter $snapkeep not valid or could not retrieve list of snapshots" | tee -a $logfiletemp
    exit $?
fi

if [ -n "$d" ]; then
    echo "$d snapshots were deleted" | tee -a $logfiletemp
else
    echo "$d snapshots were found to delete, nothing to do" | tee -a $logfiletemp
fi


}
 
Zuletzt bearbeitet:
date +%s holt die Sekunden seit der Unix Epoche 1970-01-01 00:00:00 UTC.
Das stimmt zwar, aber schau mal genau hin, was du als Referenz mit -d reingibst: nur die Tagesangabe. Und das führt zu Mitternacht. Probier's einfach mal aus ohne das +%s.

Die Frage war ja nicht ob das funktioniert sondern obs noch einen anderen Weg gibt mit der man das Datum ohne Umwandlung voneinander abziehen kann.
Ich würde das ähnlich machen. Wobei ich vermutlich nicht soviele Variablen dafür nutzen würde, denn eigentlich reicht das Alter des Snapshots und die Angabe des Löschalters (beide mit demselben Bezugspunkt, also Sekunden, Stunden oder was auch immer) und ein simpler Vergleich, was größer ist.

Was seltsames, in der Schleife habe ich d=$((d+1))
Als Ausgabe dann echo "$d snapshots were deleted"
Es wird aber kein Wert angezeigt.
Hatte ich doch geschrieben:
Beachte bei letzterem Fall, dass innerhalb der while-Schleife gesetzte Variablen nach dem Ende der Schleife den Inhalt von vor der Schleife haben, weil hier eine Pipe im Einsatz ist!
Wobei das nicht zwingend von einer Pipe abhängt sondern von einer Subshell (eine Pipe ist nur eine Möglichkeit, eine Subshell zu öffnen). Das kann man auf verschiedenen Wegen umgehen, z.B. indem man keine Pipe benutzt, sondern die while-Schleife aus einer zuvor erstellten (temporären) Datei lesen lässt. Es gibt noch andere Wege, aber meist benutze ich genau diesen.

Noch eine Sache: die vielen tee -a $blub kann man zu einem zusammenfassen, indem man alle Befehle in geschweifte Klammern setzt und dahinter das tee. Konkret:
Code:
{
befehl 1
befehl 2
befehl 3
} | tee -a $blub
Das vermeidet überflüssige Wiederholungen und dadurch entstehende Tippfehler.

MfG Dalai
 
Zuletzt bearbeitet:
Zurück
Oben Unten