PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Bash - Problem mit verschachtelten Schleifen



peshay
12-01-2009, 09:39
Hallo, ich habe bei einem Skript ein Problem mit einer If-Schleife in einer While-Schleife, das Skript soll auf mehreren Servern SQL-Befehle ablassen.
Hier der Part, der mir Schwierigkeiten bereitet.


while read liste; do
# set variables from server database
HOST=$(echo $liste | awk '{ print $1 }')
PORT=$(echo $liste | awk '{ print $2 }')
OUSER=$(echo $liste | awk '{ print $3 }')
DBUSER=$(echo $liste | awk '{ print $5 }')
DBPASS=$(echo $liste | awk '{ print $6 }')
if CheckHost $HOST $PORT $OUSER; then
# write log info
echo --------- Executing command at $HOST --------- | tee -a logfile
# create command
echo -e "connect $DBUSER/$DBPASS;\n$(cat $commandfile)\nexit;" >$tmpfile
$ssh -p $PORT $OUSER@$HOST <$tmpfile "cat >command
source .profile 2>/dev/null
cat command | sqlplus -S /nolog
rm command
" 2>&1 | tee -a logfile
else
Hint connection to $HOST could not be established. >>logfile
fi
done < ~/remote-cmd-script/dbliste

Die Funktion CheckHost(), prüft nur ob der hostname richtig ist, ein ping geht und ein kurzer ssh funktionert. Sie gibt mir auch den return code 0 zurück was ich zum Beispiel mit einem "&& echo $?" dahinter geprüft habe.
Die If-Schleife läuft dann einmal durch, anschließend wird die While-Schleife beendet, obwohl noch viele weitere Einträge in der dbliste sind.
Wenn ich die If-Schleife raus nehme, läuft das Skript komplett über alle Einträge in der dbliste.
Mir ist irgendwie nicht klar, was mit dieser If-Schleife nicht stimmt.
Ich habe auch schon ein set -x reingesetzt, das Skript beendet sich mit If-Schleife dann so:


+ echo -e 'connect corpus/corpus;\nselect login from party where login like '\''sumuser'\'';\nexit;'
+ ssh -o BatchMode=yes -p 22 user@somehost 'cat >command
+ tee -a logfile
source .profile 2>/dev/null
cat command | sqlplus -S /nolog
rm command
'

LOGIN
----------------------------------------------------------------
sumuser

logout
+ read liste
+ OnExit
+ set +x

Als würde die liste auf einmal nichts mehr liefern...

Achja, ein Tipp wie ich die Variablen einfacher befüllen kann als so, wäre auch echt nett:


HOST=$(echo $liste | awk '{ print $1 }')

undefined
12-01-2009, 11:48
Also erst mal handelt sich nicht um ein Schleifen Problem sondern um eine Anweisung.
Funktions aufrufe innerhalb einer Anweisung sollten zwischen backsticks stehen.

if test -n "`CheckHost $HOST $PORT $OUSER`" ; then

Sie gibt mir auch den return code 0
Dann

if test `CheckHost $HOST $PORT $OUSER` -eq 0 ; then
Ist aber nicht gut um Fehler ab zu fangen ;)

peshay
12-01-2009, 11:57
hab mal das zweite von dir eingefügt, und bekomm dann ein:
change-on-all.sh: line 182: test: -eq: unary operator expected

undefined
12-01-2009, 12:00
Ja klar - weil wie schon geschrieben nicht gut.
Wenn du so etwas machst solltest du sicher stellen das auch ein INT Wert zurück kommt.
http://www-user.tu-chemnitz.de/~hot/unix_linux_werkzeugkasten/bash.html#testexpr

[EDIT]
Siehe auch $?


# $? hält den Exit-Status des letzten Vordergrund-Kommandos
echo $?

undefined
12-01-2009, 12:08
Um es kurz zu machen.


## Befehl
CheckHost $HOST $PORT $OUSER
## Status
if test $? -eq 0 ; then
echo "OK";
fi

peshay
12-01-2009, 13:16
Ja, so habe ich jetzt abgeändert, dennoch endet die sich darumbefindliche While-Schleife, nachdem er das erste mal durch die If Abfrage durch ist..

peshay
12-01-2009, 13:24
Sorry Jungs, ihr habt den Contest gegen Unixboard.de verloren, da gabs eine Antwort und die volkommen richtig ;)
Die Info möchte ich euch nicht vor enthalten:


Auf den ersten Blick sieht das Skript ganz OK aus. Kann das sein, daß in der CheckHost-Funktion irgendein Kommando läuft ("cat ...", "while read ...", oder "ssh" ohne Eingabeumlenkung oder "-n"-Option), das dann effektiv den Input frisst, der in die Schleife gelangen soll? Eventuell kannst du den Aufruf dieser Funktion mal so abändern:


if CheckHost $HOST $PORT $OUSER </dev/null; then


Zur zweiten Frage: statt


while read liste; do
HOST=$(echo ... | awk ...)
PORT=...
...

sollte ein einfaches


while read HOST PORT OUSER _JUNK_ DBUSER DBPASS; do
...
done <list

eigentlich ziemlich dasselbe erreichen ... (die _JUNK_-Variable enthält damit dann das 4. Feld in deiner Liste, das du ja scheinbar nicht benötigst.)

Gruss