ubuntuusers.de

if schleife

Status: Ungelöst | Ubuntu-Version: Server 18.04 (Bionic Beaver)
Antworten |

xylit

Anmeldungsdatum:
22. September 2016

Beiträge: 138

Hallo,

ich bastel zur Zeit am einem Backup Script

1
2
{BASH_VERSION}"
5.0.3(1)-release

Ich möchte eine Abfrage per if/else/fi durchführen und zwar mit zfs snapshots

Dazu habe ich folgendes Script

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15

#!/bin/bash

# Aktueller Snapshot
ORIG="backup/backuplocal@test"


if [ $ORIG ]
then
       echo "Der Snapshot $ORIG ist vorhanden"
else
       echo "Der Snapshot $ORIG ist nicht vorhanden"
#       zfs snapshot $ZULU

fi

erstelle ich den Snapshot mit

1
zfs snap backup/backuplocal@test
1
2
3
4
5
6


zfs list -t snap

NAME                     CREATION
backup/backuplocal@test  Mi Dez 18 13:34 2019

ist dieser vorhanden

führe ich nun das Script aus erhalte ich die Ausgabe

1
2
Der Snapshot backup/backuplocal@test ist vorhanden
backup/backuplocal@test

lösche ich diesen mit

1
/usr/sbin/zfs destroy backup/backuplocal@test

und führe erneut das Script aus, erhalte ich die Ausgabe

1
2
Der Snapshot backup/backuplocal@test ist vorhanden
backup/backuplocal@test

obwol dieser nicht mehr vorhanden ist.

Könnte mir bitte jemand einen Tipp geben?

lg grüße

rklm Team-Icon

Projektleitung

Anmeldungsdatum:
16. Oktober 2011

Beiträge: 13215

Erstens mal gibt es keine "if-Schleife", höchstens eine if-Verzweigung. Eine Schleife wird ja potentiell mehrfach durchlaufen.

Dein Test wird immer "wahr" liefern, denn so, wie Du [ ... ] hier nutzt, prüft es lediglich, ob die Zeichenkette nicht leer ist:

1
2
3
4
5
6
7
8
9
$ for x in backup/backuplocal@test foo 123 ''; do echo "Text: $x"; if [ $x ]; then echo ja; else echo nein; fi; done
Text: backup/backuplocal@test
ja
Text: foo
ja
Text: 123
ja
Text: 
nein

Was Du vermutlich eher möchtest:

1
2
3
4
5
if zfs list -t snap | egrep -q "^$ORIG\\>"; then
  echo "Der Snapshot $ORIG ist vorhanden"
else
  echo "Der Snapshot $ORIG ist nicht vorhanden"
fi

xylit

(Themenstarter)

Anmeldungsdatum:
22. September 2016

Beiträge: 138

guten morgen rklm,

danke, ich beschäftige mich eigentlich das erste mal intentsiv mit der BASH.

Ich habe das so lösen können

1
2
3
4
5
6
7
8
if [ "$MASTERPOOL" ];then
       echo "ja"
else
       echo "nein wird jetzt erstellt"
       zfs snap  backup/backuplocal@test
fi

echo $MASTERPOOL

Ich schaue mir deine if-Verzweigung sehr gerne an. Hast di einen Tipp, wo ich die Parameter zu der if-Verzweigung finden kann?

ich habe im Netz ein Script gefunden das beinhaltet

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
for DATASET in ${DATASETS[@]}
do
    ....
    
	if [ -z "$TEST" ] 
		then


			if [ "$TEST" -eq "0" ]
				then
					
			fi
			continue
	fi
	

	if [ "$recentBSnap" != "$origBSnap" ]
		then
			echo "Fehler: Zum letzten Backup-Spanshot ${recentBSnap} existiert im Master-Pool kein zugehoeriger Snapshot."
			continue
	fi
done

ich würde dieses gerne nachvollziehen können, wie zum Beispiel das

continue,if [ -z "$TEST" ] oder das if [ "$TEST" -eq "0" ] "-z -eq "0"

Leider kann ich keine Doku finden, die mich weiter bringt.

Auch dass heir ""^$ORIG\\>" kann ich nichts damit anfangen.

liebe grüße

seahawk1986

Anmeldungsdatum:
27. Oktober 2006

Beiträge: 11265

Wohnort: München

rklm Team-Icon

Projektleitung

Anmeldungsdatum:
16. Oktober 2011

Beiträge: 13215

xylit schrieb:

danke, ich beschäftige mich eigentlich das erste mal intentsiv mit der BASH.

Ja, irgendwann ist halt das erste Mal. ☺

Ich habe das so lösen können

1
2
3
4
5
6
7
8
if [ "$MASTERPOOL" ];then
       echo "ja"
else
       echo "nein wird jetzt erstellt"
       zfs snap  backup/backuplocal@test
fi

echo $MASTERPOOL

Du testest nach wie vor darauf, dass eine Variable nicht leer ist; in diesem Fall halt MASTERPOOL. Du müsstest zeigen, wie Du diese Variable füllst. Sonst kann man nicht beurteilen, ob das tut, was es anscheinend soll.

Hast di einen Tipp, wo ich die Parameter zu der if-Verzweigung finden kann?

Neben den schon von seahawk1986 genannten, kannst Du im Terminal help test eingeben - dann siehst Du, welche Parameter test versteht. test ist übrigens eine andere Form von [ - das ist nämlich in der Tat ein Kommando!

Auch dass heir ""^$ORIG\\>" kann ich nichts damit anfangen.

Das ist ein Regulärer Ausdruck. Konkret betrachtet egrep hier die Eingabe (also das, was zfs list -t snap ausgibt) zeilenweise und schaut, ob es eine Zeile gibt, die mit dem Inhalt von $ORIG anfängt (dafür das "^"), gefolgt von einem Zeichen, das nicht zu einem Wort gehört (also Leerzeichen, Zeilenumbruch, Tab usw.). Zu Regulären Ausdrücken findest Du reichlich im Netz und hier im Wiki.

xylit

(Themenstarter)

Anmeldungsdatum:
22. September 2016

Beiträge: 138

hier mal das Script zum Testen

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#!/bin/bash

# Datasets, die in das Backup sollen
DATASETS="backuplocal"
MASTERPOOL="backup"

ZFSPATH="/usr/sbin/zfs"

# Anzahl der zu behaltenden letzten Snapshots, mindestens 1
KEEPOLD=3
KEEPOLD=$(($KEEPOLD + 1))
PREFIX="auto"


#ORIG=$($ZFSPATH list -rt snap -H -o name "${BACKUPPOOL}/${DATASET}" | grep "@${PREFIX}-" | tail -1 | cut -d@ -f2)
datum=$(date '+%y-%m-%d_%H:%M:%S')

#ORIGSNAP=$(zfs list -rt snap -H -o name ${MASTERPOOL}/${DATASET}@${PREFIX}-$(date '+%y-%m-%d_%H:%M:%S')


ORIGSNAP=$(/usr/sbin/zfs list -t snapshot | grep  backup/backuplocal@test)



if [ "$ORIGSNAP" ];then
       echo "ja ist bereits vorhanden"
else
       echo "nein  wird jetzt erstellt"
       /usr/sbin/zfs snapshot backup/backuplocal@test


fi

Hier mal das ganze Script auf das meines Aufbaut

https://esc-now.de/_/zfs-offsite-backup-auf-eine-externe-festplatte/?lang=en

Hier mal mein Script etwas angepasst

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
#!/bin/bash

#Pool mit den zu sichernden Daten
MASTERPOOL="backup"
# Backup-Pool
BACKUPPOOL="poolsecure"
# Datasets, die in das Backup sollen
DATASETS="backuplocal"
# Anzahl der zu behaltenden letzten Snapshots, mindestens 1
KEEPOLD=3
KEEPOLD=$(($KEEPOLD + 1))

# Praefix fuer Snapshot-Namen
PREFIX="auto"

#------------------------------ Server Informationen
HOST=$(hostname --fqdn)
HOSTIP=$(hostname -I)
OS=$(cat /etc/os-release | grep PRETTY_NAME)
PROXMOX=$(pveversion -v | grep proxmox-ve)
#---------------------------------------------------

ZFSPATH="/usr/sbin/zfs"
PROXMOX=$(/usr/bin/pveversion -v | grep pve-manager)
ZFSVERSION=$(/usr/sbin/modinfo zfs | grep version)
# Überblick der einzelnen pools mit Snapshots
ZFSINFO=$(/usr/sbin/zfs list -ro space -t all rpool)
ZFSINFO1=$(/usr/sbin/zfs list -ro space -t all poolsecure)
# Gesamtüberblick der pools
ZPOOLSTATUS=$(/usr/sbin/zpool iostat)


#Logfiles in Logrotate aufnehmen
SNAPTIME="/root/zfsbackuplocal/zfs-snapshot-time.log"
SNAPLIST="/root/zfsbackuplocal/zfs-list-snapshots.log"



MAILTO1=""
MAILTO2=""

# Systeminformationen in die Datei server.log
LOGSERVER="/root/zfsbackuplocal/zfs-backup.log"


VM="600"

#-----------------------------------------------------------------------------------------------------------------------------------------------------



# Dateien Leeren
echo -n > $SNAPTIME
echo -n > $SNAPLIST
echo -n > $LOGSERVER


/usr/sbin/qm shutdown $VM

/usr/bin/sleep 10

#---------------------------- Backup Start mit Datum und Uhrzeit
date +'%c|Backup--START auf dem Server '$HOST' ' >> $SNAPTIME





#KEEPOLD=$(($KEEPOLD + 1))

for DATASET in ${DATASETS[@]}
do
    echo -e "Namen des aktuellsten Snapshots aus dem Backup holen"

        recentBSnap=$($ZFSPATH list -rt snap -H -o name "${BACKUPPOOL}/${DATASET}" | grep "@${PREFIX}-" | tail -1 | cut -d@ -f2) 
	if [ -z "$recentBSnap" ] 
		then

#		sleep 3	
		
                echo -e "Kein Snapshot gefunden-Es existiert kein Backup-Snapshot in ${BACKUPPOOL}/${DATASET}. Soll ein neues Backup angelegt werden? (Vorhandene Daten in ${BACKUPPOOL}/${DATASET} werden ueberschrieben.)"


#		sleep 3

		ANTWORT=${?}
			if [ "$ANTWORT" -eq "0" ]
				then
					# Backup initialisieren (date '+%y-%m-%d_%H:%M:%S')"
					echo -e "--------------------------------------------"
					echo -e "FULL Snapshot wird angelegt"

					NEWSNAP="${MASTERPOOL}/${DATASET}@${PREFIX}-$(date '+%y-%m-%d_%H:%M:%S')"
					$ZFSPATH snapshot $NEWSNAP 2> /dev/null

					echo -e "--------------------------------------------"
                                        echo -e "FULL SNAPSHOT wird nach ${BACKUPPOOL}/${DATASET} gesendet"
					echo -e "--------------------------------------------"
					echo -e "--------------------------------------------"

					time  $ZFSPATH send -v $NEWSNAP |pv| $ZFSPATH recv -F "${BACKUPPOOL}/${DATASET}" 
			fi
			continue
	fi
	

        echo -e "Check ob der korrespondierende Snapshot im Master-Pool existiert"

	origBSnap=$($ZFSPATH list -rt snap -H -o name "${MASTERPOOL}/${DATASET}" | grep $recentBSnap | cut -d@ -f2)
	if [ "$recentBSnap" != "$origBSnap" ]
		then
			echo "Fehler: Zum letzten Backup-Spanshot ${recentBSnap} existiert im Master-Pool kein zugehoeriger Snapshot."
			continue
	fi



	echo "aktuellster Snapshot im Backup: ${BACKUPPOOL}/${DATASET}@${recentBSnap}"
	
	# Name fuer neuen Snapshot
	NEWSNAP="${MASTERPOOL}/${DATASET}@${PREFIX}-$(date '+%y-%m-%d_%H:%M:%S')"
	# neuen Snapshot anlegen
	$ZFSPATH snapshot  $NEWSNAP  

echo "neuen Snapshot angelegt:------------------------- ${NEWSNAP}"
echo "neuer Snapshot ${NEWSNAP}  wurde nach ${BACKUPPOOL}/${DATASET} gesendet" 

	echo "Sending incremental snapshot streams" 

	# Senden Inkrementell 
	time $ZFSPATH send -i $recentBSnap $NEWSNAP |pv| $ZFSPATH recv -F  ${BACKUPPOOL}/${DATASET} 


	# Auflisten der aktuellen Snapshots 
	$ZFSPATH list -t snapshot -o name,creation  "${BACKUPPOOL}/${DATASET}"  >> $SNAPLIST
	$ZFSPATH list -t snapshot -o name,creation  "${MASTERPOOL}/${DATASET}"  >> $SNAPLIST

	# Alle Snapshot älter als 3 Tage werden gelöscht
	$ZFSPATH list -rt snap -H -o name "${BACKUPPOOL}/${DATASET}" | grep "@${PREFIX}-" | tail +$KEEPOLD | xargs -n 1 $ZFSPATH destroy -r > /dev/null 2>&1 &
	$ZFSPATH list -rt snap -H -o name "${MASTERPOOL}/${DATASET}" | grep "@${PREFIX}-" | tail +$KEEPOLD | xargs -n 1 $ZFSPATH destroy -r > /dev/null 2>&1 &
done


#---------------------------- Backup Ende  mit Datum und Uhrzeit

date +"%c|Backup--ENDE auf dem Server "$HOST" : $?" >> $SNAPTIME

#-System Informationen
echo -e "\n--------Promox Version------------------------------------"  >> $LOGSERVER
echo -e "$PROXMOX\n--------------------------------------------"  >> $LOGSERVER
echo -e "\n--------zfs Version------------------------------------" >> $LOGSERVER
echo -e "$ZFSVERSION\n--------------------------------------------" >> $LOGSERVER
echo -e "\n--------Plattenplatz auf rpool-------------------------" >> $LOGSERVER
echo -e "$ZFSINFO\n-----------------------------------------------" >> $LOGSERVER
echo -e "\n--------Plattenplatz auf poolsecure--------------------" >> $LOGSERVER
echo -e "$ZFSINFO1\n----------------------------------------------" >> $LOGSERVER
echo -e "\n--------Übersicht der pools--------------------"  >> $LOGSERVER
echo -e "$ZPOOLSTATUS\n----------------------------------------------" >> $LOGSERVER

# Mail senden
echo "Backup----$HOST-$HOSTIP" | biabam $SNAPTIME,$SNAPLIST,$LOGSERVER -s "ZFS-SNAPSHOT-Backup-beendet" $MAILTO1,$MAILTO2


/usr/sbin/qm start $VM

Danke für die Links, dieses Script läuft seit 3 Wochen sehr gut.

Es wird jede Nacht ein Webserver der auf einem Proxmox Installiert ist, auf einem zweitem ZFS mirror auf dem gleichen Proxmox Server gesichert , der mit LUKS verschlüsselt wurde, poolsecure.

Der Weberver muss heruntergefahren werden, deshalb qm shutdown 600. Dass ganze geht auch per SSH

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
zpool iostat
              capacity     operations     bandwidth
pool        alloc   free   read  write   read  write
----------  -----  -----  -----  -----  -----  -----
poolsecure  16,3G   448G      0     41    530  1,38M
----------  -----  -----  -----  -----  -----  -----

sdb            crypto_LUKS            c444dee3-77ae-47b4-9659-110e94014fd3
└─securedrive1 zfs_member  poolsecure 9878571015065641370
sdc            crypto_LUKS            59f501a3-351b-41a6-a68e-b89cae96eac2
└─securedrive2 zfs_member  poolsecure 9878571015065641370

aber es macht mich etwas unsicher, da ich einige Dinge nicht nachvollziehen kann und noch einige am herunterfahren der VM abzufragen sind, gerade bei Windows Servern. Da kommt noch das qm unlock ins Spiel und ist auf der VM der Qemu-guest-agent installiert.

Ich galube, ich habe dass ganze etwas unterschätzt.

melde mich bestimmt nochmal mit einer Frage 😎

erholsame Feiertage.

liebe grüße

rklm Team-Icon

Projektleitung

Anmeldungsdatum:
16. Oktober 2011

Beiträge: 13215

Da kann man noch einiges aufräumen und vereinfachen. Spontan fällt mir da das Logging in Zeilen 149 bis 158 auf. Das kannst Du viel einfacher so machen:

1
2
3
4
5
6
7
cat <<EOF

--------Promox Version----------------------
$PROXMOX
--------------------------------------------
...
EOF >> "$LOGSERVER"

Entsprechend "..." für die anderen Zeilen ersetzen.

Nebenbei stellt das nur einmalige Ausgabeumleiten sicher, dass alle Daten in derselben Datei landen, weil die Logdatei exakt ein Mal geöffnet wird.

Weiters

  • Würde ich Variablen des Skriptes klein schreiben - das liest sich angenehmer und man kann sie dann sofort von Umgebungsvariablen unterscheiden.

  • Die absoluten Pfade der Executables weglassen. Wenn Du sicher sein willst, dann bau lieber vorne ins Skript so etwas ein: PATH="/bin:/usr/bin:$PATH".

  • Die Zeilen sind teilweise unfassbar lang. Das erschwert das Lesen. Du kannst Zeilen mit "\" als letzten Zeichen in die nächste umbrechen.

  • Ich weiß nicht, was Du in $DATASETS reinschreiben willst - im Moment ist es ja nur ein Wert. Da Du schon ein Array benutzt, solltest Du das dann auch sauber quoten: for DATASET in "${DATASETS[@]}". Ich finde Variablennamen, die sich nur durch ein angehängtes "S" unterscheiden, leicht verwirrend. Für die Schleife hätte ich da vermutlich eher $ds gewählt.

  • Ich weiß nicht, was Zeile 86 machen soll. Du müsstest da ja eigentlich eine Eingabe vom Terminal einlesen. Da gibt es aber kein read.

xylit

(Themenstarter)

Anmeldungsdatum:
22. September 2016

Beiträge: 138

bei einer Virtualisierung mit KVM?

danke rklm

du bist anscheindend der HIT im Forum.

"ich weiß nicht, was die Zeile 86 machen soll. Du müsstest da ja eigentlich eine Eingabe vom Terminal einlesen. Da gibt es aber kein read."

Da mache Dir mal einen Kopf, ich bin seit 20 Jahren in der EDV aber nicht in der BASH tätig!

Sorry, dass ich nachfrage, nach einem https://www.youtube.com/watch?v=7-v-2mOIdvI

mache

rklm Team-Icon

Projektleitung

Anmeldungsdatum:
16. Oktober 2011

Beiträge: 13215

xylit schrieb:

ich weiß nicht, was die Zeile 86 machen soll. Du müsstest da ja eigentlich eine Eingabe vom Terminal einlesen. Da gibt es aber kein read.

Da mache Dir mal einen Kopf, ich bin seit 20 Jahren in der EDV aber nicht in der BASH tätig!

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
cat <<PROMPT
Kein Snapshot gefunden-Es existiert kein Backup-Snapshot in ${BACKUPPOOL}/${DATASET}.
Soll ein neues Backup angelegt werden? (Vorhandene Daten in ${BACKUPPOOL}/${DATASET} werden ueberschrieben.)"
PROMPT

read -p '(Ja/Nein) ' antwort
case "$antwort" in
j*|J*)
  # Backup initialisieren (date '+%y-%m-%d_%H:%M:%S')"
  ...
  continue
;;
esac
Antworten |