check_url

Et appendix til mit foredrag man wget.

Da jeg sad og forberedte foredraget om wget kom jeg ind på problemet med at wget ignorerer kommentarafmærkning i HTML-dokumenter. Derfra var der ikke særlig langt til at jeg fik lyst til at skrive et program til at undersøge om en URL peger på en eksisterende resource.

Her følger programmet med mine kommentarer og forklaringen:

#!/bin/tcsh

Vi bruger kommandofortolkeren /bin/tcsh. På nogle systemer finder man tcsh i kataloget /usr/bin/. Hvis det er tilfældet skal linien ændres så den stadigvæk peger på tcsh.

#--------------------------------------------------------
#--  Check parameter:

if ( "$1" == "") then
   echo "Programmet kræver et HTTP URL som argument."
   exit 1
endif

Vi undersøger om det første kommandolinieargument ($1) er en tom streng. Det er vi ikke interesserede i.

#--------------------------------------------------------
#--  Split parameter:

set protokol=`echo $1 | cut -d':' -f1`

Kommandoen mellem de "baglæns" apostroffer (`) udføres og det der kommer ud sættes i stedet for de "baglæns" apostroffer (og teksten mellem dem).

echo $1 sender kommandolinieargumentet ud på stdout, der sendes videre (|) til cut.

cut er et nyttigt lille værktøj der tager en fil (eller stdin) og nøjes med at skrive udvalgte søjler ud igen. -d efterfulgt af et tegn i anførselstegn angiver hvilket tegn der bruges som skilletegn mellem søjlerne. Her har vi valgt kolon (:). -f efterfulgt af en liste med søjlenumre (komma og bindestreg kan bruges som man almindeligvis gør det) angiver hvilke søjler der skal udskrives. Her har vi valgt kun at udskrive første søjle, det vil sige alt før det første kolon.

Hvis $1 er http://jacob.sparre-andersen.dk/ vil resultatet af kommandoen mellem de "baglæns" apostroffer altså være http, så det svarer til at der stod set protokol=http, hvilket sætter variablen protokol til http.

set maskine=`echo $1 | cut -d':' -f2- | cut -d'/' -f3`

Her tager vi anden søjle og udad ved kolon-opdelingen (-f2-) og sender videre til endnu et eksemplar af cut der bruger skråstreger som skilletegn (-d'/') og udskriver tredie søjle (-f3).

Hvis vi bruger samme eksempel som før sender den første cut-kommando teksten //hugin.risoe.dk/Jacob/ videre til den næste cut-kommando der klipper hugin.risoe.dk ud (det tomme felt før den første skråstreg tæller også som en søjle). Det svarer altså til at der stod set maskine=hugin.risoe.dk på denne linie.

set resource=/`echo $1 | cut -d':' -f2- | cut -d'/' -f4-`

Denne linie ligner den forrige, men her udskrives fjerde søjle og udad ved skråstregsopdelingen, og så står der en skråstreg foran det hele.

Hvis vi fortsætter med samme eksempel som før bliver resultatet af kommandoerne i "baglæns" apostroffer Jacob/, hvilket svarer til at der stod set resource=/Jacob/ på denne linie.

#--------------------------------------------------------
#--  Prøv telnet:

if ( "$protokol" == "http" ) then

Vi kan kun håndtere HTTP-protokollen.

   ( echo "HEAD $resource HTTP/1.0"; \
     echo ""; \
     sleep 10s ) \

Her starter vi en midlertidig kommandofortolker, der skriver en HTTP-forespørgsel (for eksempel HTTP /Jacob/ HTTP/1.0) og venter ti sekunder. Semikoloner (;) bruges til at adskille kommandoer og bagstreger (\) bruges til at markere at næste linie er en del af denne linie.

     | telnet $maskine 80 \

Hele resultatet fra den midlertidige kommandofortolker sendes videre til en telnet-opkobling på web-serverens port nummer 80.

     |& grep HTTP > /tmp/HTTP-resultat

Her samler vi almindeligt output (kendt som "stdout") og fejlmeddelelser ("stderr") og sorterer alle linier der ikke indeholder teksten "HTTP" fra. Resten skrives til en midlertidig fil.

   set resultat=`cut -d" " -f2- /tmp/HTTP-resultat`

Her kører vi cut med mellemrum som skilletegn og skriver hele den midlertidige fil, bortset fra første søjle ud. Den midlertidige fil vil her typisk indeholde en enkelt linie med teksten "HTTP 200 OK", så variablen kommer til at indeholde teksten "200 OK".


   echo $protokol\://$maskine$resource $resultat

Her skriver vi URL'en og resultatet fra HTTP-forespørgslen ud. I stedet for at samle et URL af de enkelte dele kunne man jo egentlig bare bruge $1. På den anden side kan vi på denne måde se at opdelingen i protokol, maskine og resource fungerer.

else
   echo "Ukendt protokol."
   exit 2
endif

Hvis det er en anden protokol meddeler vi det lige.

#--------------------------------------------------------

Man kan enten bare kalde check_url direkte fra kommandolinien:

 ~/> check_url http://jacob.sparre-andersen.dk/
 http://jacob.sparre-andersen.dk/ 200 OK
 ~/> check_url ftp://ftp.sslug.dk/SSLUG-folder.tgz
 Ukendt protokol.
 ~/>

Man kan også lave en fil med URL'er og køre check_url med hvert af URL'erne:

 ~/> cat testdata 
 http://jacob.sparre-andersen.dk/
 http://www.sslug.dk/
 http://www.sslug.dk/~sparre/
 ~/> foreach url ( `cat testdata` )
 foreach? check_url $url
 foreach? end
 http://jacob.sparre-andersen.dk/ 200 OK
 http://www.sslug.dk/ 200 OK
 http://www.sslug.dk/~sparre/ 403 Forbidden
 ~/>

Var det noget med en kopi af check_url?

Denne side vedligeholdes af Jacob Sparre Andersen (<jacob@jacob-sparre.dk>), der også gerne besvarer spørgsmål om check_url.