Hallo Leute,
ich hab ein seltsames verhalten bei einem Shellskript und weiß leider nicht mehr weiter.
Infos:
Ubuntu Linux (6.06 Dapper LTS) auf einem
Intel Dual Xeon á 1,6 GHz (4x1,6 GHz)
Raid 5 3x80 GB
Soviel zum System an sich.
Auf dem Server läuft VMWare Server 1.02 und in der VMWare läuft momentan ein Exchange Server.
Der Speicherplatz dieser VM ist komplett vorreserviert und nicht in 2GB blöcke aufgeteilt.
Diesen Exchange möchte ich nun per Shellskript auf einen externen NAS sichern.
Shellskript arbeitet (im groben) wie folgt:
-Variablen deklarieren
-VM herunterfahren
-Backup durchführen (Ordner in dem die VM liegt zippen und auf dem NAS speichern)
-VM starten
-Ende
Wenn ich dieses Skript von Hand anschmeiße ist auch alles OK.
Wenn ich dieses Skript auf eine andere VM anwende, bei der der Speicherplatz NICHT vorreserviert ist geht es auch.
Wenn ich allerdings das Skript per Cronjob um 3 Uhr Nachts ausführen lasse, Startet er das Skript, bricht aber nach ca. 4-700 MB Sicheurng OHNE Fehlermeldung ab.
In den Logs ist zumindest kein Fehler ersichtlich.
Jetzt kommt aber nicht mit Sprüchen wie: Dann schmeiß es doch per hand an.
Das geht nämlich nicht, da ich den Server zwischen 6 Uhr morgens und 1 Uhr nachts nicht herunterfahren darf.
Da ich nachts aber nicht arbeite, geht es nur per Cronjob!!
So nun hoffe ich das einer von euch ne Idee hat...
Linux 15.036 Themen, 107.107 Beiträge
Du könntest ja mal das Shellscript posten ;-).
Vielleicht läuft das Shellscript mit den falschen Rechten .
Braucht das Shellscript root-Rechte oder läuft es mit unprivilegierten Rechten ?
Wenn die Shell einen neuen Prozess startet, dann wird erstmal mit fork() ein Kindprozess gestartet und dann wird dieser Kindprozess mit dem Systemcall exec?() durch den eigentlichen Prozess ersetzt.
Dabei werden sämtliche Rechte vererbt, mit denen der Prozess gestartet wurde.
Poste mal die Ausgabe von
"crontab -l" (-l ist ein kleines L)
Kennst du den Advanced Bash-Scripting Guide ?
http://www.tldp.org/LDP/abs/html/
PS: Wenn du das Gastbetriebsystem in VMware laufen läßt, dann kannst du doch gar nicht auf die Dateien in der virtuellen Festplatte von VMware vonn Linux aus zugreifen, oder doch ?
Ich greife uach nicht auf die Daten der VM zu, sondern ich sichere die Komplette VM. Wie ein Image.
Script:
#!/bin/sh
#
# ==== Assign variables ====
VMName="W3krzexch" # Name of VM to back up
Today=$(date +'%d-%m-%y') #Loads current date as dd-mm-yyyy into variable
DirToBackup="/vm/W3krzexch/" #Specifies to back up name_of_machine folder
VMXPath="/vm/W3krzexch/Windows Server 2003 Standard Edition.vmx"
#Name of backup file. Includes date stamp.
BackupDestination="/backup/VM/"$VMName"_"$Today".zip"
#Name and location of backup log file
BackupLog="/backup/VM/"$VMName"_backup$Today".log
nowtime=$(date +'%D-%R')
i=0
WL='/vm/W3krzexch/Festplatte D.vmdk.WRITELOCK'
#==== Shutdown VM ====
state=`vmware-cmd "$VMXPath" getstate | sed 's/getstate() = //'`
if [ "$state" = "on" ]
then
echo "Shutdown VM "$VMName" at "$nowtime >>$BackupLog
vmware-cmd "$VMXPath" stop
else
echo "VM-State was already OFF" >>$BackupLog
fi
# ==== Run the backup=====
until [ $i -eq 10 ]
do
i=`expr $i + 1`
sleep 60
if [ ! -f "$WL" ]
then
nowtime=$(date +'%D-%R')
echo "Start packing at "$nowtime >>$BackupLog
zip -r $BackupDestination $DirToBackup >>$BackupLog
#echo "zip"
mbcheck=`ls -al "$BackupDestination" | awk '{print $5}'`
if [ $mbcheck -ge 734003200 ]
then
i=10
status="SUCCESFULL"
else
echo $i" attemp not successful! Starting next try!" >> $BackupLog
status="FAILED"
fi
else
echo "VM not completely shutdown" >>$BackupLog
state=`vmware-cmd "$VMXPath" getstate | sed 's/getstate() = //'`
if [ "$state" = "on" ]
then
vmware-cmd "$VMXPath" stop
# echo "stop"
else
echo "There was an critical error while shutting down the VM" >>$BackupLog
vmware-cmd "$VMXPath" start
sleep 180
echo "VM was startet again to solve the problem" >>$BackLog
status="FAILED"
fi
fi
done
#==== Startup VM ====
nowtime=$(date +'%D-%R')
echo "Start VM at "$nowtime >>$BackupLog
vmware-cmd "$VMXPath" start
#=== Backup abgeschlossen ====
echo ' ' >>$BackupLog
echo 'BACKUP '$status >>$BackupLog
Wie gesagt, dass Script läuft.
Also es ist direkt in den Crontab (nano /etc/crontab) eingegeben worden und zwar mit rootrechten
59 2 * * 1 root /vm/backup/backup-email.sh
Das ABS Guide kenne ich noch nicht. Muss ich mir bei Zeiten mal durchlesen.
Auf den ersten Blick sehe ich keine Fehler. Ich würde mal für die Diagnose den Rückgabewert von zip auswerten:
Läuft das zip -r .. Backup innerhalb der until Schleife ?
Wenn ja, warum ?
(nickles läuscht alle Tabulatoren. Ich sehe wahrscheinlich nicht ganz die Zugehörigkeit der zip Anweisung)
"echo "Start packing at "$nowtime >>$BackupLog
zip -r $BackupDestination $DirToBackup >>$BackupLog"
Du willst Loddaten von zip in diese Logdatei schreiben. Das wird so nicht funktionieren, zumindest nicht bei den Fehlermeldungen.
Es gibt drei Standardkanäle die automatisch geöffnet und initialisert werden, wenn ein Programm gestartet wird.
Standardeingabekanal mit der Nummer 0, den Standardausgabekanal mit der Nummer 1 und den Standardfehlerkanal mit der Nummer 2
Programme geben in der Regel Fehlermeldungen auf dem Standardfehlerkanal mit der Nummer 2 aus. Die normalen Ausgaben werden an Kanal 1 gesendet.
Wenn du Fehlermeldungen protokollieren willst, dann mußt du Kanal 2 in eine Datei umleiten:
stdout und stderr in gemeinsame Dateien:
>file 2>&1
stdout und stderr in getrennte Dateien:
>file 2>file1
nur stderr in Datei
2> file
Ich nehme mal an wenn du anstelle von ">" ">>" nutzt, dann werden die Daten an die Datei angehängt.
Ich habe da auch immer wieder Probleme und mir deshalb das Buch
Unix Shellprogrammierung von Rainer Krienke gekauft (Hanser Verlag) ;-).
Programme geben mit einer "return 0" Anweisung am Ende der main() Funktion den Rückgabewert 0 zurück, wenn alles O.K. war.
Wenn ein Fehler aufgetreten ist, dann brechen C-Programme mit "exit Rückgabewert" ab. Man kann den Rückgabewert in einem Shellscript auswerten.
In der Variable "$?" ist dieser Rückgabewert gespeichert und man kann diesen Rückgabewert ausgeben lassen oder in Abhängigkeit davon eine Aktion durchführen:
if [ $? != 0 ] ; then
echo " Fehler ist bei zip aufgetreten !"
echo " exit status : $? >> $BackupLog"
fi
Ließ mal die manpage von zip.
Ich weiß nicht warum zip abbricht , aber du kannst ja mal tar nutzen.
(Warum läuft zip innerhalb der Schleife ? Dadurch wird auch zip 10 mal gestartet .)
tar ist ursprünglich für Backups auf Magnetbänder programmiert worden und kann gzip aufrufen um die Daten zu komprimieren.
PS: Ich kann dir dieses Buch empfehlen wenn du nicht gut Englisch kannst:
http://www.amazon.de/Shell-Programmierung-Grundlagen-Werkzeuge-praktische-Skripte/dp/3446407375/ref=sr_1_1/302-9964088-2941623?ie=UTF8&s=books&qid=1181634215&sr=8-1
"
if [ ! -f "$WL" ]
then
nowtime=$(date +'%D-%R')
echo "Start packing at "$nowtime >>$BackupLog"
Würde ich anders machen:
Am Anfang vom Script
#Backup Variable (oder einen anderen Bezeichner wählen) auf false setzen
BACKUP = false
...
.....
if [ ! -f "$WL" ] ; then
BACKUP=true
fi
done von der until Schleife
Danach !!
if [ $BACKUP == true ] , then
nowtime=$(date +'%D-%R')
echo "Start packing at "$nowtime >>$BackupLog
zip -r $BackupDestination $DirToBackup >>$BackupLog
fi
Auf jeden Fall würde ich die zip Anweisung aus der until Schleife rausnehmen und erstmal nur eine Variable auf true setzen.
Tar war ursprünglich an dieser Stelle eingesetzt. Zip ist schon die alternative.
Tar bricht genauso ab!
Die Zip Funktion sitzt innerhalb der until Schleife, damit falls ein Fehler beim beenden der VM oder beim anlegen der Zip Datei auftritt, der Vorgang erneut gestartet wird. Fall der Zip Vorgang erfolgreich ist, wird die until Schleife ja auch beendet, also das ist schon so gewollt.
Das mit dem Fehler in die Datei schreiben werde ich mal probieren.
Vielleicht kommt da was bei raus!
Wie gesagt, komisch ist nur, dass er es einwandfrei macht, wenn ich das Script per hand starte.
Rechtemäßig kann von daher ja auch nichts falsch sein.
Wenn du irgendwelche Zustände überwachen willst reicht es doch auch eine bolsche Variable (es gibt leider nur String Variablen bei der Shellprogrammierung) zu setzen oder zu löschen. Du mußt doch deshalb nicht das Programm zip mehrmals starten.
Wenn du eine 2 Gigabyte große Datei mehrmals kopieren willst, könnte doch auch irgendein Speicher überlaufen und deshalb das Programm abbrechen.
Wenn du warten willst bis in diese Datei nicht mehr geschrieben wird, dann kannst du eine bolsche Variable überwachen.
Wenn das Backup gemacht werden soll, dann setze diese bolsche Variable auf true und wenn ein Fehler aufgetreten ist , dann setze diese Variable auf
false.
Am Ende wertest du die Variable aus und startest zip nur einmal.
Bei C gibt es dafür den Datentyp bool und die zwei Schlüsselwörter true und false.
Du kannst bei einem Shellscript auch eine Stringvariable entweder mit true oder false (ähnlich wie bei C) initialisieren und dann auswerten.
Ich kopiere da nichts mehrfach.
Der until loop erfüllt da schon seinen Zweck...
Ausserdem habe ich das Script auch schon in einer sehr vereinfachten Form versucht...
Da hat es aber auch nicht funktioniert....
Also muss es entweder mit dem cron zutun haben oder mit dem NAS.
NAS schließe ich aber eigentlich aus, da es ja geht wenn ich es per Hand ausführe.
Bin ratlos...
naja muss ich mir zur Not ne andere Sicherungsmethode überlegen.
Vielleicht versuche ich mal nur nen cp Befehl.
Gucken ob das geht...
Du wertes in dieser until Schleife überhaupt keine Rückmeldungen von zip aus.
Die Variable $? speichert den Rückgabewert des letzten Befehls.
In dieser Schleife sind überhaupt keine Abbruchbedingungen definiert.
....
until [ $i -eq 10 ]
do
i=`expr $i + 1`
sleep 60
if [ ! -f "$WL" ]
then
nowtime=$(date +'%D-%R')
echo "Start packing at "$nowtime >>$BackupLog
zip -r $BackupDestination $DirToBackup >>$BackupLog
#echo "zip"
mbcheck=`ls -al "$BackupDestination" | awk '{print $5}'`
....
Wenn diese Writelock Datei nicht mehr existiert (keine Zugriffe auf den Server ?), dann wird die Schleife mehrmals durchlaufen.
Du mußt mit "if [ $? == 0 ] ; then break "aus dieser Schleife austreten, nach dem der zip Befehl erfolgreich war.
Wenn zip erfolgreich durchlief, wird nach dem done Schlüsselwort die Ausführung des Shellscriptes fortgesetzt und die Schleife abgebrochen.
Frage ...
... wenn du das Script manuell statest, stellst du da vorher sicher, dass der Exchange Server nicht mehr verwendet wird und das keine offenen Verbindungen mehr bestehen?
... lauefn ev. noch andere Backups auf den externen NAS?
... was könnte um 3 Uhr nachts anders sein als z.B. 14 Uhr nachmittags?
d-oli
genau diese fragen habe ich mir auch schon gestellt...
aber es kam nichts kunstruktives bei rum!
habe die zeit ja auch schon nach hinten verschoben...
sprich von 1 auf 3 und von 3 auf 5 aber nichts hat geholfen.
habe extra diese uhrzeit gewählt, da dort kein anderes backup gefahren wird.
der einzige zugriff auf den exchange könnte von ihm selbst kommen (also die datenbankbereinigung) aber die sollte an diesem zeitpunkt auch schon durchgelaufen sein.
aber das is ja auch egal, da der exchange für die sicherung eh ausgeschaltet wird (VM wird heruntergefahren)
Ich hab irgendwie immernoch die dumme befürchtung, dass es an der größe der VM liegt.
Denn die VM mit dem Exchange ist 70 GB groß.
Wenn ich das Script per cronjob auf ne testvm anwende (kein vorreservierter Speicherplatz --> 2GB) funktioniert es tadellos. (gerade probiert!!)
Kann es sein das Linux probleme mit der Dateigröße hat?
Das hängt vom Dateisystem und von der Klustergrösse ab:
http://en.wikipedia.org/wiki/Comparison_of_file_systems (nach Limits scrollen)
d-oli
Es gibt anscheinend ein Problem mit zu grossen tar-Dateien:
http://answers.google.com/answers/threadview?id=25116
The size of files you put into a tar archive (not the archive itself)
is limited to 11 octal digits, the max. size of a single file is thus
ca. 68 GBytes.
Hier wird ein ähnliches Problem beschrieben, leider ohne Lösung:
http://lists.samba.org/archive/rsync/2002-September/003589.html
... das Problem könnte also bei tar oder zip liegen ...
d-oli
Das klingt doch schonmal hilfreich....
Mehr oer weniger...
Zumindest ein Ansatz...
Ich werd erstma schauen ob es nachher mit dem cp befehlt funktioniert.
Große Server werden mit rsync gespiegelt. rsync arbeitet mit einem Sender und einem Empfänger. Bei ganz großen Dateien wie ISO Images werden auch nur Dateiteile übertragen damit Bandbreite (und damit auch Zeit ) gespart wird.
Ich weiß aber nicht ob rsync mit so großen Dateien zurecht kommt.
Wozu dann das Geschwafel? Es ist nicht immer nötig das letzte Wort zu haben.
Jemand der ein solches Shellscript schreiben kann, weiss sehr wohl was mit rsync anzufangen ist. Zudem geht es hier um tar, zip und cp, von rsync ist nur im Link die Rede.
Wenn der Server heruntergefahren ist, dann existiert diese Writelock Datei nicht mehr.
....
until [ $i -eq 10 ]
do
i=`expr $i + 1`
sleep 60
if [ ! -f "$WL" ]---> Datei existiert nicht und wird auch nicht wieder angelegt solange das Shellscript läuft.
then
nowtime=$(date +'%D-%R')
echo "Start packing at "$nowtime >>$BackupLog
zip -r $BackupDestination $DirToBackup >>$BackupLog
#echo "zip"
...
Folglich wird die Schleife 10 mal ausgeführt. Dadurch wird auch zip 10 x gestartet.
Ich weiß jetzt nicht ob zip 10mal kurz hintereinader gestartet wird (wartet das Shellscript so lange bis zip beendet wurde oder macht das Shellscript gleich in der nächsten Zeile nach zip weiter ?) oder 10 nacheinander.
Au jeden Fall werden 10 Instanzen von zip erzeugt die jede für sich 70 GByte kopieren soll.
In diesem Script fehlt eine Abbruchbedingung, sonst wird zip 10 mal gestartet.
Ich würde zip überhaupt nicht in einer Schleife starten, sondern nur eine bolsche Variable setzen und erst am Ende zip EINMAL starten.
es fehlt keine abbruchbedingung... glaub mir doch einfach!!
zip -r $BackupDestination $DirToBackup >>$BackupLog | erstellt Zip
#echo "zip"
mbcheck=`ls -al "$BackupDestination" | awk '{print $5}'` | weißt der Variable die größe der Datei zu
if [ $mbcheck -ge 734003200 ] | prüft ob Zipdatei größer 700 MB
then
i=10 | wenn dem so ist, wird I (das ist die loop variable) direkt auf 10 gesetzt!! das ist der ausstieg
status="SUCCESFULL" | aus dem loop!!!! es funktioniert!! also reite da bitte nicht weiter drauf rum!!! hätte man sicher
|auch eleganter machen können!