Hilfe für Optimierung eines Shellskripts

ruffy85

New Member
Hallo,

ich bin auf der Suche nach Hilfe für die Optimierung meines Shellskripts auf euer Forum gestoßen und versuche hier mal mein Glück.

Das folgende Shellskript lädt mehrere xml Dateien herunter und führt deren Inhalt in eine einzige Datei zusammen, die ich später mit einem PHP Skript auslesen und auf meiner Webseite anzeigen lasse.

Mein Problem liegt darin, dass diese Datei sehr lang ist. Ich frage mich, ob ich das Herunterladen und Schreiben nicht mittels weiterer Schleifen vereinfachen kann. Bisher ohne Erfolg.

Hier das bisherige Skript. Wie man unschwer erkennt, ist es sehr lang. Leider.

Code:
#!/bin/bash
cachedir="cache"
getfile="wget -c --directory-prefix=cache"
url="http://www.euro-ro.net/vcxml/loki"
write="more +2"

while true;
do
  rm vcards.xml
  rm cache/*
  touch vcards.xml
  echo "<?xml version=\"1.0\" encoding=\"utf-8\"?>" >> vcards.xml
  echo "<system>" >> vcards.xml

  $getfile $url/**Lorenor**.xml
  $getfile $url/bloody_eye.xml
  $getfile $url/blackangel666.xml
  $getfile $url/DerToro.xml
  $getfile $url/TalRascha.xml
  $getfile $url/Der%20Schnitter.xml
  $getfile $url/Darezard.xml
  $getfile $url/>.:-DrUnKeN WiZzArd-:.<.xml
  $getfile $url/Assaka.xml
  $getfile $url/*Grace*.xml
  $getfile $url/Kiron%20Angel.xml
  $getfile $url/Das%20Sage.xml
  $getfile $url/.LONER..xml
  $getfile $url/leech%204%20life.xml
  $getfile $url/*Energy*.xml
  $getfile $url/o0Raven0o.xml
  $getfile $url/Dark-Secret.xml
  $getfile $url/-Becci-.xml
  $getfile $url/Sukaru.xml
  $getfile $url/maverick202.xml
  $getfile $url/'Nuako.xml
  $getfile $url/-Miko-.xml
  $getfile $url/_Selene.xml
  $getfile $url/Knight%20StefaN.xml
  $getfile $url/*Dragonsniper*.xml
  $getfile $url/Tribestar.xml
  $getfile $url/ajoOba`.xml
  $getfile $url/-spuki-.xml
  $getfile $url/LordSchlumpf.xml


  $write $cachedir/**Lorenor**.xml >> vcards.xml
  $write $cachedir/bloody_eye.xml >> vcards.xml
  $write $cachedir/"Der Schnitter.xml" >> vcards.xml
  $write $cachedir/DerToro.xml >> vcards.xml
  $write $cachedir/blackangel666.xml >> vcards.xml
  $write $cachedir/TalRascha.xml >> vcards.xml
  $write $cachedir/Darezard.xml >> vcards.xml
  $write $cachedir/">.:-DrUnKeN WiZzArd-:.<.xml" >> vcards.xml
  $write $cachedir/Assaka.xml >> vcards.xml
  $write $cachedir/*Grace*.xml >> vcards.xml
  $write $cachedir/"Kiron Angel.xml" >> vcards.xml
  $write $cachedir/Das%20Sage.xml >> vcards.xml
  $write $cachedir/".LONER..xml" >> vcards.xml
  $write $cachedir/"leech 4life.xml" >> vcards.xml
  $write $cachedir/*Energy*.xml >> vcards.xml
  $write $cachedir/o0Raven0o.xml >> vcards.xml
  $write $cachedir/Dark-Secret.xml >> vcards.xml
  $write $cachedir/-Becci-.xml >> vcards.xml
  $write $cachedir/Sukaru.xml >> vcards.xml
  $write $cachedir/maverick202.xml >> vcards.xml
  $write $cachedir/"'Nuako.xml" >> vcards.xml
  $write $cachedir/-Miko-.xml >> vcards.xml
  $write $cachedir/"_Selene.xml" >> vcards.xml
  $write $cachedir/"Knight StefaN.xml" >> vcards.xml
  $write $cachedir/*Dragonsniper*.xml >> vcards.xml
  $write $cachedir/Tribestar.xml >> vcards.xml
  $write $cachedir/"ajoOba`.xml" >> vcards.xml
  $write $cachedir/-spuki-.xml >> vcards.xml
  $write $cachedir/LordSchlumpf.xml >> vcards.xml

  echo  "</system>" >> vcards.xml
  chown web1 vcards.xml
  chgrp web1 vcards.xml
  sleep 3600
done
Ich bedanke mich schon im Voraus für eure Tipps und Anregungen.
 
Hallo Ruffy,

gibt es denn Performance-Probleme oder stören Dich schlicht und ergreifend die vielen einzelnen Anweisungen?

MfG,
marneus
 
Was mir als erstes Einfällt ist natürlich, daß man das am Besten in eine for-Schleife packt.
Zum anderen würde ich sagen, daß einige Datein in Anfürungsstriche oder excapt werden müssen.

Wenn Du ausserdem das cache-Verzeichnis vorher löschst kannst Du mit
"cat *.xml >> vcards.xml" den Teil kürzen.

Und zu guter letzt, wenn Du es direkt über den User web1 aufrufen würdest, bräuchtest Du den letzten Teim mit chown/chgrp nicht mehr.

huschi.
 
Derzeit rufe ich es testweise als root auf. Später dann im korrekten Verzeichnis als web1.

Mich stören die vielen Anweisungen. Ich habe das Problem, dass unschöne Zeilen eingefügt werden, wenn ich more -2 *.xml >> vcards.xml ausführen lasse, das sieht dann so aus:
Code:
**************
**Lorenor**.xml
**************

Diese Zeichenfolge wird für jede Datei erstellt und erscheint in der vcards.xml. Dadurch kann die vcards.xml nicht mehr korrekt eingelesen werden und es kommt zu Fehlern bei der Bearbeitung, die durch das php Skript erfolgt. Lese ich die Dateien einzeln ein, entsteht diese Zeichenfolge nicht-

Was für mich denkbar wäre, wäre ein Array, keine Ahnung, ob das machbar ist. Eindimensionale Arrays sind ja möglich. Ich denke an diese Möglichkeit, da die Anzahl der einzulesenden xml datein größer werden wird und ich somit sicherlich weniger Aufwand habe, die Datei anzupassen.

Mir würde es am besten gefallen, wenn ein Aufruf des wget Kommandos mit dem Array möglich wäre, dafür habe ich aber keine brauchbare Lösung gefunden. Ich dachte an eine for Schleife, aber das funktioniert nicht.

Ebenfalls sollte so später das kontinuierliche Schreiben in die vcards.xml geschehen, aber das will auch nicht. Ich habe more gewählt, da ich die geladenen Dateien erst ab der zweiten Zeile in die vcards.xml schreiben will, soweit ich weiß, kann das cat leider nicht. Aber beim Einlesen mehrerer Dateien mittels more entsteht die oben genannte unschöne Zeichenfolge.

Gedanklich habe ich mir das so gedacht, bekomme es aber nicht hin.
Code:
array="( "**Lorenor**.xml" "bloody_eye.xml" ... )
i=0
y="Länge des Array"
while i=<y 
do
wget $url/$array[i]
$write $array[i] >> vcards.xml
i++
done
Also, ich möchte die einzelnen Dateien in ein eindimensionales Array speichern und mittels einer while-Schleife (Zählschleife), jedes Elelemt des Arrys herunterladen und den Inhalt der Dateien in die vcards.xml schreiben. Dann i um Eins erhöhen. Aber ich bin scheinbar zu blöd für den passenden Shellcode.
 
Code:
#!/bin/bash

VCARDS=vcards.xml
WGETOPTIONS="-......"

echo "<system>" > "$VCARDS"

for file in '**Lorenor**.xml' 'bloody_eye.xml'; do
     wget "$WGETOPTIONS" "$url/$file"
     head -2 "$cachedir/$file" >>"$VCARDS"
done;
echo "</system>" >>"$VCARDS"
#
oder wenn alle Dateien in $cachedir stehen:
Code:
find $cachedir -type f -print0 |xargs -n 1 -0 head -2 >>$VCARDS
 
Last edited by a moderator:
Vielen Dank für diese schnelle Hilfe. Wow, der Code ist echt kurz und tut genau das, was er soll. Habe es etwas angepasst und nun sieht mein Code wie folgt aus.
Code:
#!/bin/bash
cachedir="cache"
getfile="wget -c --directory-prefix=cache"
url="http://www.euro-ro.net/vcxml/loki"
write="more +2"
VCARDS=vcards.xml
DATEN=("**Lorenor**.xml" "bloody_eye.xml" "Der Schnitter.xml")

while true; do
  rm vcards.xml
  rm cache/*
  echo "<?xml version=\"1.0\" encoding=\"utf-8\"?>" > $VCARDS
  echo "<system>" >> vcards.xml

  for file in ${DATEN[*]}; do
     $getfile  "$url/$file"
     sleep 2
     $write  "$cachedir/$file" >> "$VCARDS"
  done;

  echo "</system>" >>"$VCARDS"
  sleep 3600
done

Meine letzte Frage nun. Ich habe unter DATEN ja die Dateien genannt, manche enthalten aber Leerzeichen. Das würde dann ja falsch interpretiert werden. Zum Beispiel bei Der Schnitter.xml. Das Skript würde Der und Schnitter.xml suchen, aber beides nicht finden. Wie muss ich das korrekt angeben, damit es auch Dateien mit Leerzeichen findet?

EDIT:
Habe meine Daten nun in einem Array gespeichert, dass ich auslesen lasse. Nach wie vor gibt es Probleme mit Leerzeichen.
 
Last edited by a moderator:
Die einzelnen Daten in einfache Anführungszeichen "'" einbetten und das `echo "$DATEN"` einfach durch "$DATEN" ersetzen.

Ansonsten kann es zu Fehlern kommen, wenn auf die vcards.xml zugegriffen wird, während die Datei neu aufgebaut wird. Das kannst Du vermeiden, indem Du die Daten zunächst in eine temporäre Datei schreibst und diese ganz zum Schluss umbenennst.

Code:
DATEN="**Lorenor**.xml bloody_eye.xml"
VCARDS=vcards.xml.$$

...

for file in $DATEN; do

...

echo "</system>" >>"$VCARDS"
mv "$VCARDS" vcards.xml
sleep 3600
Das "$$" wird beim Laufenlassen durch die jeweilige Prozess-ID der shell ersetzt.
(Achtung: in einer Zeile wurde die Variable $VCARDS allerdings nicht verwendet, was bei der Umbenennung-Methode fatale Auswirkungen hätte...)

EDIT: gut, das mit den einzelne Anführungszeichen bringt nichts. Leerzeichen dürfen einfach nicht drin sein -- was sie ja ohnehin nicht dürfen, da man sie sonst ja nicht als legale URL darstellen kann (dafür gibt es ja %20).
 
Last edited by a moderator:
Das Skript funktioniert für alle Daten, außer denen mit einem Leerzeichen im Namen. Ich habe verschiedene Methoden probiert das Problem zu lösen, aber ohne Erfolg. Immer erscheint das gleiche Ergebnis :(

Folgendes haber ich probiert, am Beispiel von "Der Schnitter.xml":
Code:
DATEN=("Der Schnitter.xml")
DATEN="Der\ Schnitter.xml"
DATEN=('Der Schnitter.xml')
DATEN=("Der\ Schnitter.xml")

Immer passierte Folgendes.
Code:
--13:58:20--  http://www.euro-ro.net/vcxml/loki/Der
           => `cache/Der
Resolving www.euro-ro.net... 217.68.157.21, 217.68.157.22, 217.68.157.23, ...
Connecting to www.euro-ro.net|217.68.157.21|:80... connected.
HTTP request sent, awaiting response... 404 Not Found
13:58:20 ERROR 404: Not Found.

cache/Der: No such file or directory
--13:58:22--  http://www.euro-ro.net/vcxml/loki/Schnitter.xml
           => `cache/Schnitter.xml'
Resolving www.euro-ro.net... 217.68.157.26, 217.68.157.21, 217.68.157.22, ...
Connecting to www.euro-ro.net|217.68.157.26|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 666 [application/xml]

100%[=================================================================================================================>] 666           --.--K/s

13:58:22 (70.57 MB/s) - `cache/Schnitter.xml' saved [666/666]

Nun ist es Zufall, dass es die Datei Schnitter.xml gibt und diese geladen wird. Aber die will ich ja nicht haben, sondern die Datei "Der Schnitter.xml". Ich kann derzeit keine Dateien mit Leerzeichen im Namen verarbeiten.
 
Dachte ich anfangs auch ;) Nur dann speichert er die Datei als "Der Schnitter.xml", will aber "Der%20Schnitter.xml" in vcards.xml einfügen. Ergebnis:
Code:
cache/Der%20Schnitter.xml: No such file or directory

Es ist zum verrückt werden. Scheinbar ist meine Bash defekt. Jedenfalls denke ich das nun. Obwohl ich die drei Werte in meinem Array eindeutig durch "" gekennzeichnet habe, sind es vier Werte geworden. Anscheinend wird "" ignoriert und jedes Leerzeichen als Trennung genommen. Dadurch entsteht der Fehler bei "Der Schnitter.xml". Das Leerzeichen innerhalb der "" wird ausgewertet und so entstehen zwei Elemente. Einmal "Der" und einmal "Schnitter.xml".

Wie kann ich dieses problem lösen? Wie zwinge ich meine bash dazu es richtig zu machen?
 
Last edited by a moderator:
... mit %20 und ohne Zwischenspeichern ...
Code:
    getfile ="wget -O - "
    $getfile "$url/$file" | $write  >> "$VCARDS"
 
Last edited by a moderator:
Vielen Dank für diese Lösung. Darauf wäre ich nicht gekommen. Ich habe mich schon mit der Anpassung von IFS beschäftigt, was aber zu mehr Problemen führte.

Mit dieser Lösung funktioniert es nun wie gewünscht, daran habe ich nicht gedacht. War der Überzeugung, dass ich die Dateien zwischenspeichern muss, damit es funktioniert.

EDIT:
Neuer Fehler, der erst auffällt, wenn das PHP Skript die entstandene vcards.xml parsed. Nun ist es nicht mehr möglich, die Dateien erst ab der zweiten zeile einzulesen. Es wird ab der ersten Zeile eingelesen, wodurch ich die xml Definition mehrfach drin habe und es somit zu Fehlern kommt. Wie kann ich das denn nun lösen?
 
Last edited by a moderator:
Back
Top