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

Arrays in der Bash und seltsames Verhalten hierbei

byron1778

Hacker
Hallo Forum!

Ich habe ein bereits bestehendes Script so umgeschrieben, dass es ein wenig kürzer ist.

Vorher sah der Bereich so aus ( es gibt 10 Bereich, 101 - 110 )

Code:
echo ${SEPARATOR}
TASKFILE_ID=101
${ECHO} "`date +'%d/%m/%Y %H:%M:%S'` - Run Taskfile ${TASKFILE_ID}..."

TASKFILE_101=${DATA}/spezial_${TASKFILE_ID}.txt
END_101="END_batchtasks_${TASKFILE_ID}_`date +'%Y%m%d%H%M%S'`"
LOGFILE_101="${LOGS}/run_batchMonitor_${TASKFILE_ID}_`date +'%Y%m%d%H%M%S'`"

${SCRIPTS}/startTaskfile.sh ${TASKFILE_ID} ${TASKFILE_101} ${END_101} ${LOGFILE_101} ${RISKENGINEPORT_1}

Ich habe das Ganze so verkürzt, dass es mittels eines Arrays abgebildet wird ( die Bereiche 101 - 110 ).

Code:
declare -a TASKFILE_
declare -a END_
declare -a LOGFILE_

for i in `ls ${DATA}/spezial_1*.txt | cut -d_ -f2 | cut -d . -f1`
do
        echo ${SEPARATOR}
        TASKFILE_ID=${i}
        ${ECHO} "`date +'%d/%m/%Y %H:%M:%S'` - Run Taskfile ${TASKFILE_ID}..."

        eval TASKFILE_[${i}]=${DATA}/spezial_${TASKFILE_ID}.txt
        eval END_[${i}]="END_batchtasks_${TASKFILE_ID}_`date +'%Y%m%d%H%M%S'`"
        eval LOGFILE_[${i}]="${LOGS}/run_batchMonitor_${TASKFILE_ID}_`date +'%Y%m%d%H%M%S'`"

        ${SCRIPTS}/startTaskfile.sh ${TASKFILE_ID} ${TASKFILE_[${i}]} ${END_[${i}]} ${LOGFILE_[${i}]} ${RISKENGINEPORT_1}
done

Was mich jetzt dabei stutzig macht ist folgendes, im ersten Bsp läuft alles wunderbar.
Im 2ten Code gibt es keine Fehlermeldung, jedoch kommt er nie zu einem Ende!
Es scheint so, als wäre er in einer Endlosschleife gefangen.
Er sagt zwar, dass er am startTaskfile.sh dann weiterarbeitet, aber es gibt kein Ende.

Kann es sein, dass der eval - Code - Bereich irgendwie falsch ausgewertet wird?
Wenn ich das Ganze mit -x debugge, ist die Ausgabe von eval und co in Ordnung, jedoch wie gesagt, kommt es nie zu einem Ende!

Vll. hat jemand eine Idee hierbei!

Danke Euch vielmals!
 

P6CNAT

Advanced Hacker
Hallo,

Seltsam, versuche es mal mit folgendem Ansatz.
Leite das `ls ....` in eine temporäre Datei um,
und lasse es mit "for i in `cat tempdatei`" oder mit "while read i do ... done < tempdatei" laufen.

Gruß
Georg
 
OP
B

byron1778

Hacker
Danke Dir vielmals!

Werde ich kommende Woche versuchen, sobald ich in der Arbeit bin!
Ich denke es liegt irgendwie am eval, aber woran es genau liegt, weiss ich leider nicht.

mfG
 
OP
B

byron1778

Hacker
Hallo!

Bei deinem Ansatz muss ich aber wahrscheinlich auch mit einem Array und einem eval arbeiten?
Weil im ersten Schritt weise ich ja einer Variablen mit dem Namen Taskfile_"Zahl"=spezial_"Zahl".txt 2mal einen Wert ( linke und rechte Seite gleichzeitig ) einen Wert zu und das muss ich ja mit einem Array und einem eval machen oder würde es auch anders gehen?
 

P6CNAT

Advanced Hacker
Hallo,

was hälst du von folgendem Vorschlag:
Verteile das Ganze auf zwei Schleifen.
1. Schreibe jeweils die rechte Seite von TASKFILE, END und LOGFILE usw. mit echo in Tabellenform in eine temporäre Datei
2. In einer zweiten Schleife mit
Code:
while read parameter1 parameter2 parameter3 ...
 do .... 
   ${SCRIPTS}/startTaskfile.sh parameter1 parameter2 parameter3 ....
 done < tempdatei
folgt die eigentliche Verarbeitung.
Ist sicher Geschmacksache, hat aber den Charm, dass das Array durch eine Tabelle in der Datei ersetzt wird und man in der temporären Datei genau sehen kann ob und wo es ein Problem gibt. Statt eval reicht die Verwendung von echo.

Gruß
Georg
 
OP
B

byron1778

Hacker
Hallo!

Ich habe nun den Fehler gefunden!
Es lag nicht an der for - Iteration, wie ich es mir immer dachte, sondern weiter unten bei einer while - Schleife.
Diese Schleife sah so aus:

Code:
while [ ! -f ${DATA}/${END_101} ] || [ ! -f ${DATA}/${END_102} ] || [ ! -f ${DATA}/${END_103} ] || [ ! -f ${DATA}/${END_104} ] || \
      [ ! -f ${DATA}/${END_105} ] || [ ! -f ${DATA}/${END_106} ] || [ ! -f ${DATA}/${END_107} ] || [ ! -f ${DATA}/${END_108} ] || \
      [ ! -f ${DATA}/${END_109} ] || [ ! -f ${DATA}/${END_110} ]
do

Da hier ${END_101} hardcoded ist, dachte ich mir, dass es schon so passen würde, weil ich ja in der for - Iteration ${END_101} anlege und in der while - Schleife dann einfach weiterverwende.
Nur habe ich leider nie bedacht, dass es oben ein Array ist!

Jetzt hätte ich nur mehr eine Frage.
Ich will die while - Schleife mit den vielen ODER Abfragen als for Schleife abarbeiten.
Ist ja seit einiger Zeit in der bash möglich!

Nur weiss ich leider nicht, wie ich dieses Konstrukt schreiben soll/kann.

Folgendes funktioniert nicht:

Code:
for (( i=i=`ls ${DATA}/spezial_1* | cut -d_ -f2 | cut -d . -f1 | head -1`; if [ ! -f ${DATA}/${END_[${i}] ]; ${i}++))

ebenso nicht:

for (( i=i=`ls ${DATA}/spezial_1* | cut -d_ -f2 | cut -d . -f1 | head -1`; ! -f ${DATA}/${END_[${i}]; ${i}++))

Hätte jemand vll einen anderen Vorschlag oder Idee wie ich das umsetzen kann?

Danke Euch allen, die mir geholfen haben!
 

P6CNAT

Advanced Hacker
Probiere es mal in der Art:

Code:
liste=`ls | grep END_1[*]` # Kriterien zwischenspeichern macht das Ganze einfacher
for x in $liste
do
  :
  :
done
Gruß
Georg
 
OP
B

byron1778

Hacker
Ich glaube hier besteht das Problem, dass bei der for ( each ) - Schleife von der Bash jedes Element abgearbeitet wird und damit war´s dann auch!
Ich bräuchte aber die while - Schleife mit den vielen Bediengungen umgeschrieben und da würde meines erachtens nach nur eine for - Schleife greifen, jedoch keine for ( each).
Und hier genau liegt dann mein Problem.

Ich hätte mir in etwa folgendes gedacht:

Code:
for((i=${END_[${i}]; teste ob File ${END_[${i}] || ${END_[${i}] || ${END_[${i}] etc vorhanden ist; ${i}++))
do
.
.
done

Jedoch gibt es kein String - concatenate in der Bash.
Jetzt stellt sich für mich die Frage, ob es überhaupt irgendwie möglich ist eine for oder auch eine äquivalente for ( each ) Schleife anstatt der while - Schleife zu erzeugen?
 

P6CNAT

Advanced Hacker
Hi,

ich fürchte ich kann deinen Gedanken nicht folgen.

Das `ls | grep END_1` impliziert doch, dass die END Dateien vorhanden sind. Wenn keine da ist, wird auch nix abgearbeitet.

Gruß
Georg
 
OP
B

byron1778

Hacker
Die while - Schleife testet, ob KEIN END - File vorhanden ist, dadurch tritt das Programm dann in die Schleife ein!

Code:
while [ ! -f ${END.... ]
do

Erst wenn auch das letzte File ENDFILE vorhanden ist, geht er im Programm weiter.

Und nun muss/möchte ich halt das Programm um etliches kürzen und hier besonders die while - Schleife mit ihrer Bediengung!
Nur weiss ich leider nicht, wie ich das in der Bash umgehen könnte?

So sieht die komplette while - Schleife aus, mir wäre aber eigentlich nur der Schleifenkopf wichtig, alles andere bekomme ich schon selber hin ( hoffentlich :) ! )

Code:
while [ ! -f ${DATA}/${END_101} ] || [ ! -f ${DATA}/${END_102} ] || [ ! -f ${DATA}/${END_103} ] || [ ! -f ${DATA}/${END_104} ] || \
      [ ! -f ${DATA}/${END_105} ] || [ ! -f ${DATA}/${END_106} ] || [ ! -f ${DATA}/${END_107} ] || [ ! -f ${DATA}/${END_108} ] || \
      [ ! -f ${DATA}/${END_109} ] || [ ! -f ${DATA}/${END_110} ]
do

        date

        if  test ! -f ${DATA}/${END_101} ; then
                echo "*** Waiting for Taskfile 101 ***"
           else
                echo "*** Taskfile 101 fertig ***"
        fi

        if  test ! -f ${DATA}/${END_102} ; then
                echo "*** Waiting for Taskfile 102 ***"
           else
                echo "*** Taskfile 102 fertig ***"
        fi
.. weiter bis END_110

        ALLESNOCHMAL=0
        MESSAGE="Message : no message"

        if [ `grep "This connection is not active" ${LOGFILE_101} ${LOGFILE_102} ${LOGFILE_103} ${LOGFILE_104} \
                ${LOGFILE_105} ${LOGFILE_106} ${LOGFILE_107} ${LOGFILE_108} ${LOGFILE_109} ${LOGFILE_110} | wc -l` -gt 0 ]
        then

          ALLESNOCHMAL=1
          MESSAGE="Message : This connection is not active"

        fi

        if [ `grep "SIGBUS" ${LOGFILE_101} ${LOGFILE_102} ${LOGFILE_103} ${LOGFILE_104} ${LOGFILE_105} ${LOGFILE_106} \
                ${LOGFILE_107} ${LOGFILE_108} ${LOGFILE_109} ${LOGFILE_110} ${DEBUGLOGDIR}/${DEBUGLOGNAME} | wc -l` -gt 0 ]
        then

          ALLESNOCHMAL=1
          MESSAGE="Message : SIGBUS"

        fi


        if [ `grep "SIGSEGV" ${LOGFILE_101} ${LOGFILE_102} ${LOGFILE_103} ${LOGFILE_104} ${LOGFILE_105} ${LOGFILE_106} \
                ${LOGFILE_107} ${LOGFILE_108} ${LOGFILE_109} ${LOGFILE_110} ${DEBUGLOGDIR}/${DEBUGLOGNAME} | wc -l` -gt 0 ]
        then

          ALLESNOCHMAL=1
          MESSAGE="Message : SIGSEGV"

        fi


        if [ `grep "errorString = Caught signal signal is 11" ${LOGFILE_101} ${LOGFILE_102} ${LOGFILE_103} ${LOGFILE_104} \
                ${LOGFILE_105} ${LOGFILE_106} ${LOGFILE_107} ${LOGFILE_108} ${LOGFILE_109} ${LOGFILE_110} \
                ${DEBUGLOGDIR}/${DEBUGLOGNAME} | wc -l` -gt 0 ]
        then

          ALLESNOCHMAL=1
          MESSAGE="Message : Caught signal - signal is 11"

        fi


        if [ ${ALLESNOCHMAL} -eq 1 ]
        then

          echo ${SEPARATOR}
          ${ECHO} "`date +'%d/%m/%Y %H:%M:%S'` - caught ${MESSAGE} - kill old BatchMonitors..."

es kommen zwar hier noch ein paar Befehle vor, aber die sind wirklich unwesentlich, nur mehr Abfragen bzgl File Inhalte!!!

done
 

P6CNAT

Advanced Hacker
Hi,

Wie war das, vor lauter Wald sieht man die Bäume nicht ....

Das Programm soll also warten, bis alle END Dateien angelegt sind, 10 Stück.
Damit hat man auch gleich das einfachste Kriterium, 10 Dateien mit ähnlichem Namen.
Dann schlage ich eine einfache Warteschleife ohne Schnörkel vor.

Code:
zaehler=0
while [ zaehler -lt 10 ]
do 
   zaehler=`ls END* | wc -l`
   sleep 10 # Sekunden 
done
Gruß
Georg
 
OP
B

byron1778

Hacker
hallo!

danke für deinen hinweis!

ich habe es jetzt einmal so gelöst, um die große while schleife mit den vielen bediengungen im header - kopf annähernd nachzustellen!

Code:
function while_loop () {
        for i in `ls ${DATA}/spezial_1* | cut -d_ -f2 | cut -d . -f1`
        do
                if [ ! -f ${DATA}/${END_[${i}]} ]
                then
                        return 1        # FALSE
                fi
        done
        return 0        # TRUE
}


while ! while_loop
do
..
done

Anfangs habe ich auch nach einer Möglichkeit gesucht, um mir die while schleife selber zu bauen, indem ich string concatenations verwende, musste aber feststellen, dass es solche in bash nicht gibt!

Wollte die while schleife:

Code:
while [ ! -f $END_101 || ! -f $END_102 || .....

eben mit string concatenations nachbauen, aber das geht nicht wie bereits geschrieben!

Danke Euch einmal für Eure Hilfe!
 
OP
B

byron1778

Hacker
Diese String - concatenations gehen aber nicht bei ein und derselben Variable!
So etwas wäre interessanter.

Ich hätte mir so etwas vorgestellt:

Code:
i=1
i+=$i

Aber so etwas kennt die Bash leider nicht, auch nicht in ähnlicher Form bei Strings, zumindest konnte ich nichts finden!
 

framp

Moderator
Teammitglied
byron1778 schrieb:
Diese String - concatenations gehen aber nicht bei ein und derselben Variable!
So etwas wäre interessanter.

Ich hätte mir so etwas vorgestellt:

Code:
i=1
i+=$i

Aber so etwas kennt die Bash leider nicht, auch nicht in ähnlicher Form bei Strings, zumindest konnte ich nichts finden!
Irgendwie verstehe ich Dich wohl nicht :(
Code:
a="A"
a="$a $a"
echo $a
funktioniert ebenso
 
Oben