2012-10-24 15 views
5

Sto provando a creare uno script di shell che legge un elenco di URL di download da trovare se sono ancora attivi. Non sono sicuro di cosa non vada nella mia sceneggiatura attuale (sono nuovo) e qualsiasi suggerimento sarebbe di grande aiuto!Script di shell con Wget - Se nidificato internamente per loop

user @ pc: ~/test # cat sites.list

http://www.google.com/images/srpr/logo3w.png 
http://www.google.com/doesnt.exist 
notasite 

Script:

#!/bin/bash 
for i in `cat sites.list` 
do 
wget --spider $i -b 
if grep --quiet "200 OK" wget-log; then 
echo $i >> ok.txt 
else 
echo $i >> notok.txt 
fi 
rm wget-log 
done 

Come è, lo script genera tutto per notok.txt - (il primo sito Google dovrebbe vai a ok.txt). Ma se corro:

wget --spider http://www.google.com/images/srpr/logo3w.png -b 

E poi fare:

grep "200 OK" wget-log 

E greps la stringa senza problemi. Che errore ho fatto con la sintassi? Grazie m8!

risposta

6

L'opzione -b invia wget allo sfondo, quindi stai facendo il grep prima che wget abbia finito.

provare senza l'opzione -b:

if wget --spider $i 2>&1 | grep --quiet "200 OK" ; then 
+0

buona cattura !! +1 – Graham

+0

Infatti. +1 anche da parte mia :) – ghoti

+0

Funziona! Grazie! –

4

ci sono alcuni problemi con quello che stai facendo.

  • Il tuo for i in avrà problemi con le righe che contengono spazi vuoti. Meglio usare while read per leggere singole righe di un file.
  • Non stai citando le tue variabili. Cosa succede se una riga nel file (o parola in una riga) inizia con un trattino? Allora wget lo interpreterà come un'opzione. Hai un potenziale rischio per la sicurezza qui, così come un errore.
  • Creare e rimuovere file non è realmente necessario. Se tutto ciò che stai facendo è controllare se un URL è raggiungibile, puoi farlo senza i file temporanei e il codice extra per rimuoverli.
  • wget non è necessariamente lo strumento migliore per questo. Consiglierei di usare curl invece.

Quindi, ecco un modo migliore per gestire questa situazione ...

#!/bin/bash 

sitelist="sites.list" 
curl="/usr/bin/curl" 

# Some errors, for good measure... 
if [[ ! -f "$sitelist" ]]; then 
    echo "ERROR: Sitelist is missing." >&2 
    exit 1 
elif [[ ! -s "$sitelist" ]]; then 
    echo "ERROR: Sitelist is empty." >&2 
    exit 1 
elif [[ ! -x "$curl" ]]; then 
    echo "ERROR: I can't work under these conditions." >&2 
    exit 1 
fi 

# Allow more advanced pattern matching (for case..esac below) 
shopt -s globstar 

while read url; do 

    # remove comments 
    url=${url%%#*} 

    # skip empty lines 
    if [[ -z "$url" ]]; then 
    continue 
    fi 

    # Handle just ftp, http and https. 
    # We could do full URL pattern matching, but meh. 
    case "$url" in 
    @(f|ht)tp?(s)://*) 
     # Get just the numeric HTTP response code 
     http_code=$($curl -sL -w '%{http_code}' "$url" -o /dev/null) 
     case "$http_code" in 
     200|226) 
      # You'll get a 226 in ${http_code} from a valid FTP URL. 
      # If all you really care about is that the response is in the 200's, 
      # you could match against "2??" instead. 
      echo "$url" >> ok.txt 
      ;; 
     *) 
      # You might want different handling for redirects (301/302). 
      echo "$url" >> notok.txt 
      ;; 
     esac 
     ;; 
    *) 
     # If we're here, we didn't get a URL we could read. 
     echo "WARNING: invalid url: $url" >&2 
     ;; 
    esac 

done < "$sitelist" 

Questo è testato. Solo a scopo didattico. Può contenere noci

+1

+1 Bel sforzo pedagogico –

+0

Incredibile, questo è veramente utile! Grazie ghoti. –