Anzeige:
Ergebnis 1 bis 11 von 11

Thema: BASH - Script Domains prüfen

  1. #1
    mupp
    Gast

    BASH - Script Domains prüfen

    Hallo zusammen,

    ich bin dabei mich in Bash Scripte einzulesen und muss sagen für Unix/Linux Anfänger ist das sehr komplex!

    Ich möchte eine große Liste von Domains per HTTP-Request prüfen,
    es soll dabei eine Ausgabe erfolgen, ob die entsprechende Domain Konnektiert oder nur "geparkt" ist.

    Hier mein Script, an dem ich die Verzweiflung bekomme:
    Code:
    #!/bin/bash
    VAR1=www.heise.de
    
    DIG=dig $VAR1 | grep -A 1 AUTH
    $DIG
    echo "$DIG"
    if wget $VAR1 2>&1 | grep -q 'Host nicht gefunden' ; then
    echo "Anfrage auf $VAR1 war nicht erfolgreich!"
    else
    echo "Anfrage auf $VAR1 war erfolgreich!"
    fi
    Die Domain wurde von mir geändert.

  2. #2
    Registrierter Benutzer
    Registriert seit
    07.05.2007
    Beiträge
    656
    Moin,

    Zitat Zitat von mupp Beitrag anzeigen
    ...Hier mein Script, an dem ich die Verzweiflung bekomme:...
    Ich versehe mal das Script mit Kommentaren:
    Code:
    #!/bin/bash
    VAR1=www.heise.de # ok, Du willst diese Domain pruefen
     
    DIG=dig $VAR1 | grep -A 1 AUTH # was willst Du erhalten?
    # Folgendes liefert die Befehlsliste "dig $VAR1 | grep -A 1 AUTH":
    # ;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0
    #
    # Wenn Du diese Ausgabe in die Variable DIG schreiben willst, dann so:
    DIG="`dig $VAR1 | grep -A 1 AUTH`"
         # allerdings ist mir nicht klar, was Du mit "-A 1" im grep bezweckst.
         # da steht nur ne Leerzeile nach der Trefferzeile
    $DIG # huch? Du willst das, was in $DIG steht, ausfuehren??? 
         # Das gibt Mecker vom Meister ;-)
    echo "$DIG" # ok, mal ausgeben, was in $DIG steht
    # die naechste Zeile sieht erstmal ok aus, ich würde aber fuer wget 
    # noch die Option -q reinnehmen, den eigentlichen Output willst Du
    # ja nicht haben. Und bei der Abfrage auf eine Zeichenkette ist Vorsicht
    # angebracht - was ist, wenn ein Benutzer Englisch als Sprache einstellt?
    if wget $VAR1 2>&1 | grep -q 'Host nicht gefunden' ; then
      echo "Anfrage auf $VAR1 war nicht erfolgreich!"
    else
      echo "Anfrage auf $VAR1 war erfolgreich!"
    fi
    So, jetzt berichtige mich bitte und erkläre mal, was Du an den Stellen bezweckst, die mir schleierhaft sind.

    Jan

  3. #3
    mupp
    Gast
    Hallo Jan,

    erstmal danke für deine Hilfe!

    Ich möchte drei Dinge mit dem Script tun:
    1) Ich habe ein Textfile mit "X" Domains, die ich im Script Zeile für Zeile verarbeiten möchte
    2) Außerdem soll der http-get Request auf Code "200" geprüft werden
    3) Ich möchte sehen welche Domain geprüft wird, damit Tipp-Fehler im Textfile mit den genannten Domains vermieden werden kann.

    Vielleicht kannst du mir helfen, also vorweg - ich will das Scripten selber lernen und suche kein fertiges!

  4. #4
    Registrierter Benutzer
    Registriert seit
    07.05.2007
    Beiträge
    656
    Moin,

    Zitat Zitat von mupp Beitrag anzeigen
    ...Ich möchte drei Dinge mit dem Script tun:
    1) Ich habe ein Textfile mit "X" Domains, die ich im Script Zeile für Zeile verarbeiten möchte
    2) Außerdem soll der http-get Request auf Code "200" geprüft werden
    3) Ich möchte sehen welche Domain geprüft wird, damit Tipp-Fehler im Textfile mit den genannten Domains vermieden werden kann.

    Vielleicht kannst du mir helfen, also vorweg - ich will das Scripten selber lernen und suche kein fertiges!
    OK, dann nur ein paar Hinweise ;-)
    1. Zum zeilenweisen Abarbeiten einer Textdatei gibt es verschiedene Möglichkeiten, ein paar gebräuchliche sind:
    Code:
    cat datei | while read zeile; do
    ...
    done
    # oder
    for zeile in `cat datei`; do
    ...
    done
    # oder
    while read zeile; do
    ...
    done <datei
    Alle Methoden haben ihre Vor- und Nachteile, am besten ausprobieren und ein wenig im bash-Manual stöbern.

    2. Das Prüfen, ob eine Domain überhaupt existiert, geht wohl am einfachsten über host und dann dem Auswerten der Antwort (grep):
    Code:
    jan@jack:~/tmp/tst_wget> host www.heise.de
    www.heise.de has address 193.99.144.85
    jan@jack:~/tmp/tst_wget> host gibtsnicht.heise.de
    Host gibtsnicht.heise.de not found: 3(NXDOMAIN)
    dig geht natürlich auch, aber da erscheint mir eine Auswertung der Antwort (weil geschwätziger) schwieriger.

    Wenn der Host gar nicht gefunden wurde, kann man innerhalb der Schleife mit continue mit der nächsten Zeile weitermachen oder per break aus der Schleife raushüpfen.

    Zum Prüfen, ob hinter der Domain tatsächlich eine erreichbare Webseite liegt (ich nehme an, Dich interessiert nur HTTP), kannst Du wie schon probiert wget nehmen. Ich lege Dir die Optionen -S und --spider nahe, mit denen Du - wieder in Zusammenarbeit mit grep - genau die Infos kriegen solltest, die Du brauchst.

    3. Das ist einfach - dafür gibts echo.

    Außerdem noch meine 2 Standard-Tipps: Wenn Du innerhalb eines Shell-Scripts Fehlersuche treiben willst, dann setze an den Anfang ein "set -x", damit kriegst Du angezeigt, was die Shell wirklich treibt. Und wenn Du Dir mal ein paar Anregungen holen willst, was mit Shell-Scripts so möglich ist, dann ist /etc/init.d eine wahre Fundgrube.

    So, viel Spaß beim Scripten, wenn Du nicht weiterkommst, dann melde Dich einfach wieder.

    Jan

  5. #5
    mupp
    Gast
    Hallo Jan,

    ich komme einfach nicht auf eine vernünftige Lösung, dass ganze
    Lesen der advanced bash guide bringt nichts, wenn man aus dem
    Kopf heraus das script nicht zusammen basteln kann..

    Kannst du mir helfen, in dem du auf jeden Fall bitte entsprechende
    Kommentare reinschreibst um mich nochmal in die richtige Richtung zu schubsen??

    ./test.sh www.heise.de
    #!/bin/bash

    header=`curl -I -s "$1"`
    if [ -n "$header" ]; then
    echo "Connected"
    else
    echo "Not Connected"
    fi
    Soweit verstehe ich das auch alles.. die Domain wird per http request geprüft und liefert mir connected aus..
    Aber wie kann ich das machen, dass ich nicht die Domain dem Script mit gebe, sondern auf eine Datei verweise,
    in dem tausend andere stehen??

    Ich möchte in der Shell auch sehen welche Domain er gerade prüft..

    Kannst du mir nochmal helfen??
    Geändert von mupp (30-01-2008 um 14:23 Uhr)

  6. #6
    Registrierter Benutzer
    Registriert seit
    07.05.2007
    Beiträge
    656
    Moin,

    Zitat Zitat von mupp Beitrag anzeigen
    ......Aber wie kann ich das machen, dass ich nicht die Domain dem Script mit gebe, sondern auf eine Datei verweise,
    in dem tausend andere stehen??
    Ich machs mal so, dass ich eine Variante zeige, wie man sowas angeht. Du siehst wohl am schnellsten, wie es zu machen ist, wenn Du ein konkretes Beispiel hast.
    Code:
     #!/bin/bash
     # Aufruf: check_connect.sh Dateiname
    
    # zuerst pruefen, ob eine Datei uebergeben wurde und ob diese existiert:
    # Wichtig: den Variablennamen in "" stellen, er kann Leerzeichen u. a.
    # enthalten oder leer sein
    if test -z "$1" -o ! -f "$1" -o ! -r "$1"; then
      echo "keine Datei angegeben oder nicht existent oder nicht lesbar"
      # der naechste echo gibt eine usage-Meldung aus.
      # der Ausdruck basename "$0" liefert den Dateinamen des Scripts
      # ohne Pfad ($0 ist immer der Scriptname mit Pfad)
      # die `` lassen die Shell wissen, dass das darin enthaltene Kommando
      # ausgefuehrt werden soll und dessen Ausgabe an die Stelle des 
      # `...`-Abschnitts eingefügt wird. Da ich aussen um die auszugebende
      # Zeile "" gesetzt habe, muss ich die inneren "" mit einem \ entwerten.
      echo "Aufruf: `basename \"$0\"` Dateiname"
      exit 1
    fi
    
    # Jetzt die Schleife ueber die Datei in verschiedenen Varianten
    
    # Variante 1: while-Schleife per read, der Dateiinhalt wird per
    # Eingabeumleitung in die Schleife "eingespeist"; domain ist die
    # Variable, in der der Inhalt der jeweiligen Zeile steht
    while read domain; do
      # Ausgeben, welche Domain geprüft wird
      echo "Prüfe Domain <$domain>"
      header=`curl -I -s "$domain"`
      if [ -n "$header" ]; then
        echo "<$domain> Connected"
      else
        echo "<$domain> Not Connected"
      fi
    done <"$1"
    
    # 2. Variante: while-Schleife, die ihre Daten über eine Pipe von einem
    # cat erhält:
    cat "$1" | while read domain; do
      # Ausgeben, welche Domain geprüft wird
      echo "Prüfe Domain <$domain>"
      header=`curl -I -s "$domain"`
      if [ -n "$header" ]; then
        echo "<$domain> Connected"
      else
        echo "<$domain> Not Connected"
      fi
    done
    
    # 3. Variante: for-Schleife, die ihre Daten über die oben beschriebene
     # Methode aus einem `...`-Block erhält
    for domain in `cat "$1"`; do
      # Ausgeben, welche Domain geprüft wird
      echo "Prüfe Domain <$domain>"
      header=`curl -I -s "$domain"`
      if [ -n "$header" ]; then
        echo "<$domain> Connected"
      else
        echo "<$domain> Not Connected"
      fi
    done
    
    exit 0
    Noch einige Anmerkungen zu den Vor- und Nachteilen der 3 Varianten:

    1. + 2. können mit Leerzeichen innerhalb der Zeileninhalte umgehen, was Variante 3 so nicht kann (eine Zeile "a b" würde 2 einzelne Durchläufe verursachen), dafür müsste man die Shell-Variable IFS (Input Field Separator) umsetzen.

    1. kann nur aus Dateien lesen (die Eingabeumleitung "<" funktioniert nur mit Dateien), während sich 2. + 3. auch für andere Fälle eignen (z. B. eine wilde Kombination aus Shell-Befehlen wie sed, grep, ..., mit der man Dateien und Anderes manipulieren kann, oder für die Bearbeitung von normalen Kommandoausgaben wie ps), also alles, was Ausgaben auf STDOUT schickt.

    In Variante 2 läuft die Schleife in einer Subshell ab (die Pipe öffnet sie), damit kann ich Variablen, die ich innerhalb der Schleife verändere, nach der Schleife nicht auswerten, da sie dort nicht bekannt sind.

    Jan
    Geändert von jan61 (30-01-2008 um 22:59 Uhr)

  7. #7
    Registrierter Benutzer
    Registriert seit
    02.07.2003
    Ort
    Essen
    Beiträge
    20
    Ich glaub das Script macht genau das was du willst.
    Es ist zwar ein ganz anderer Ansatz aber es funtioniert.

    #!/bin/bash
    #
    # domcheck A Domain Checking Script
    # ver:0.1
    # description: Checks The Availability of Domains.
    #Latest Version http://******

    DOMAINS()
    {
    if [ ! -e ./domains ]
    then
    touch ./domains
    echo
    echo 'Write the domains you want to check in the file domains'
    echo 'Attention only one domain per line'
    echo 'Example: linux.org'
    echo ' debian.org'
    echo ' linuxfriends.org'
    echo
    exit 1
    else
    echo
    fi

    }

    CLEAR()
    {
    if [ -e ./domaincheck.log ]
    then
    rm ./domaincheck.log
    touch ./domaincheck.log
    else
    touch ./domaincheck.log
    fi
    }

    CHECK()
    {
    for name in $(cat ./domains); do
    if ping -q -c 1 $name 2>&1 | grep -q ', 0% packet loss';
    then
    echo "`date` $name reachable" >> ./domaincheck.log
    else
    echo "`date` $name unreachable" >> ./domaincheck.log
    fi
    done
    }

    RESULT()
    {
    echo "Attention the following domains are unreachable !!!!"
    echo
    cat ./domaincheck.log | grep unreachable
    echo
    }

    DOMAINS
    CLEAR
    CHECK
    RESULT
    Geändert von Thallez (04-02-2008 um 22:04 Uhr)
    GREETINGS
    _-=Thallez=-_
    www.linuxfriends.org

  8. #8
    Registrierter Benutzer
    Registriert seit
    07.05.2007
    Beiträge
    656
    Moin,

    Zitat Zitat von Thallez Beitrag anzeigen
    Ich glaub das Script macht genau das was du willst.
    Es ist zwar ein ganz anderer Ansatz aber es funtioniert.
    nein, das tut es nicht! Finger weg davon.

    Die Versionsnummer 0.1 sollte man hier IMHO ernst nehmen, das Script ist ziemlich wacklig (und äußerst unübersichtlich - Code Obfuscation durch Weglassen sämtlicher Strukturierung, sprich Einrückung, finde ich persönlich ziemlich Sch...). Ich habe mir den Code-Abschnitt mal in ein Shellscript kopiert und es dann ganz einfach k.o. gehauen - es gibt noch etliche andere Varianten, wie man das Ding in den Orkus schicken kann - siehe unten:
    Code:
    jan@jack:~/tmp/domchk> chmod 755 domcheck.sh
    jan@jack:~/tmp/domchk> mkdir domains domaincheck.log
    jan@jack:~/tmp/domchk> ./domcheck.sh
    
    rm: Entfernen von „./domaincheck.log“ nicht möglich: Ist ein Verzeichnis
    cat: ./domains: Ist ein Verzeichnis
    Attention the following domains are unreachable !!!!
    
    cat: ./domaincheck.log: Ist ein Verzeichnis
    Was sagt uns das?

    1. Die Tests sind äußerst schlampig, ein -e prüft nun mal ausschließlich die Existenz, aber nie den Dateityp ab. Wenn also im Verzeichnis, aus dem heraus man das Script aufruft, zufälligerweise ein Unterverzeichnis "domains" existiert, dann gibts eben einen Fehler. Und wenn z. B. "domains" keine reguläre Datei, sondern eine Named Pipe oder ein Device ist, dann wirds richtig lustig, dann kann ich nämlich das Script von außen ansteuern, es wird ja ungeprüft gelesen und nirgends gequotet. Und es wird nirgends geprüft, ob ich die "domains"-Datei überhaupt lesen und die "domaincheck.log" schreiben darf - ruf das Script mal in / oder /bin oder ... auf.

    2. Noch schlimmer - wenn eine Datei namens "domaincheck.log" im aktuellen Verzeichnis existiert, wird die einfach plattgemacht. Was ist, wenn der Anwender die braucht (könnte ja von einem ganz anderen Programm / Script erzeugt worden sein)? Es wird übrigens auch nicht geprüft, ob der touch auf die "domaincheck.log" klargegangen ist - so kannst Du Dir ratzfatz z. B. Daten zerschießen, alles was Du ausgibst, wird in dem Fall nämlich einfach an die Datei angebammelt (wieder ganz einfach nachvollziehbar: Einfach dem aktuellen Verzeichnis die Schreibrechte entziehen - wenn die Datei Schreibrechte hat, wird angehängt).

    3. Es wird keinerlei Eingabevalidierung gemacht:
    Code:
    jan@jack:~/tmp/domchk> rmdir domains/
    jan@jack:~/tmp/domchk> echo "www heise.de" >domains
    jan@jack:~/tmp/domchk> rmdir domaincheck.log/
    jan@jack:~/tmp/domchk> ./domcheck.sh
    
    Attention the following domains are unreachable !!!!
    
    Sa Feb  2 00:13:27 CET 2008 www unreachable
    Wow - Das Web ist also nicht erreichbar ;-) - Wer hat das Internet kaputt gemacht??? Für eine ungeprüfte Eingabedatei eine for-Schleife zum Lesen einzusetzen ist tödlich! Da besteht nämlich überhaupt keine Chance mehr, die Eingabe zu validieren (es sei dann, man setzt IFS vorher um).

    4. Eigentlich wollte mupp eine Anzeige, welche Domain gerade geprüft wird (nämlich um genau solche Eingabefehler erkennen zu können) - das Script macht also nicht so richtig "genau das was du willst".

    5. ping nutzt ein anderes Protokoll als wget & Co. - ICMP. Wenn ein ping ein Resultat liefert, heisst das noch lange nicht, dass auch TCP- oder UDP-Pakete ankommen.

    6. Nach Synflood-Attacken per ICMP (siehe man ping, Option -f) vor längerer Zeit (such mal nach "icmp synflood" in Google) haben etliche Admins ICMP in ihren Firewalls geblockt - selbst heise.de war einige Zeit per ping nicht ereichbar. Ich bin mir sicher, dass viele Admins das noch nicht wieder rückgängig gemacht haben. Wenn also ein ping nicht durchkommt, heisst das noch lange nicht, dass die Domain (bzw. der Host - eine Domain kann ping gar nicht checken) nicht erreichbar ist.

    Jan

    P.S.: Wenn Du schon Werbung machst - auf der Firmenwebseite habe ich die "latest version" dieses Scripts nicht gefunden, auch keine andere. Suchen kann man da ja auch nicht.

  9. #9
    mupp
    Gast
    Hallo zusammen,


    ich schaue mir das Script in Ruhe wenn ich wieder @work bin an;
    Trotzdem vielen lieben Dank dafür..

    Grüße aus dem echten Karnevals-okult

    Dennis!

  10. #10
    Registrierter Benutzer
    Registriert seit
    02.07.2003
    Ort
    Essen
    Beiträge
    20
    Zitat Zitat von jan61 Beitrag anzeigen
    P.S.: Wenn Du schon Werbung machst - auf der Firmenwebseite habe ich die "latest version" dieses Scripts nicht gefunden, auch keine andere. Suchen kann man da ja auch nicht.
    Ja ja jetzt bekomm ich es von beiden Seiten schlechter Code der von mir stammt und von der Firma, weil ich schlechten Code verbreitet hab der aber nicht represantativ ist für die Arbeit der Firma ist sondern von mir während meiner Ausbildung geschrieben wurde und nur auf den File-Server rumflog.

    Deswegen auch der Edit von der Firmen URL.
    Sorry hatte nur gedacht er bring euch weiter.
    GREETINGS
    _-=Thallez=-_
    www.linuxfriends.org

  11. #11
    Registrierter Benutzer
    Registriert seit
    07.05.2007
    Beiträge
    656
    Moin,

    Zitat Zitat von Thallez Beitrag anzeigen
    Ja ja jetzt bekomm ich es von beiden Seiten schlechter Code der von mir stammt und von der Firma, weil ich schlechten Code verbreitet hab der aber nicht represantativ ist für die Arbeit der Firma ist sondern von mir während meiner Ausbildung geschrieben wurde und nur auf den File-Server rumflog...
    tut mir leid, wenn Du deswegen Ärger hast. Es ist nur so, dass ich mir Scripts, die (augenscheinlich) von einer Firma stammen, sehr genau anschaue (wenn ich die Zeit dazu habe ;-). Mach es in Zukunft so, dass Du für solche Scripts eben keine "offizielle" Referenz angibst - sonst weckst Du falsche Erwartungen ;-)

    Und meine Anmerkungen nimmst Du einfach so, wie sie gemeint waren: Als Code-Review, der hilft, in Zukunft diverse Fehler zu vermeiden. Ich habe die Erfahrungen ja auch nicht mit der Muttermilch eingesogen, sondern durch viele ähnliche Diskussionen in Mailing-Listen u. ä und vor allem durch viel Praxis gewonnen.

    Jan

Lesezeichen

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •