Script para obter o código de status HTTP de uma lista de urls?

87

Tenho uma lista de URLs que preciso verificar, para ver se ainda funcionam ou não. Eu gostaria de escrever um script bash que faça isso para mim.

Eu preciso apenas do código de status HTTP retornado, ou seja, 200, 404, 500 e assim por diante. Nada mais.

EDITAR Observe que há um problema se a página diz "404 não encontrado", mas retorna uma mensagem 200 OK. É um servidor da web mal configurado, mas você pode ter que considerar este caso.

Para obter mais informações, consulte Verificar se um URL leva para uma página que contém o texto "404"

Manu
fonte
2
Para ser justo, o "bug" do meu script é apenas quando o servidor retorna o código HTTP 200, mas o corpo do texto diz "404 não encontrado", que é um servidor da web com comportamento inadequado.
Phil
2
O status de saída do wget será 0 se o código de resposta for 200, 8 se 404, 4 se 302 ... Você pode usar o $? variável para acessar o status de saída do comando anterior.
Casey Watson

Respostas:

194

O Curl tem uma opção específica --write-out, para isso:

$ curl -o /dev/null --silent --head --write-out '%{http_code}\n' <url>
200
  • -o /dev/null joga fora a saída normal
  • --silent joga fora o medidor de progresso
  • --head faz uma solicitação HEAD HTTP, em vez de GET
  • --write-out '%{http_code}\n' imprime o código de status necessário

Para encerrar isso em um script Bash completo:

#!/bin/bash
while read LINE; do
  curl -o /dev/null --silent --head --write-out "%{http_code} $LINE\n" "$LINE"
done < url-list.txt

(Leitores com olhos de águia perceberão que isso usa um processo de curl por URL, o que impõe penalidades de bifurcação e conexão TCP. Seria mais rápido se vários URLs fossem combinados em um único curl, mas não há espaço para escrever a repetição monstruosa de opções que o curl requer para fazer isso.)

Phil
fonte
Muito agradável. Posso executar esse comando em cada url do meu arquivo?
Manu
1
@Manu: Sim, editei minha resposta para mostrar uma maneira possível de encerrar o comando curl. Ele assume que url-list.txt contém um URL por linha.
Phil
1
Não sei por que o script de cima e de responder sempre me dá 000 na saída, mas quando executo o comando apenas uma vez sem loop funciona ...
Karol F
1
@KarolFiturski Eu tive o mesmo problema (que você provavelmente já corrigiu, mas apenas no caso de alguém se deparar com isso ...) no meu caso, tive retornos de carro nos finais de linha do meu arquivo de entrada, fazendo com que os urls fiquem como http://example.com/\rdurante o ciclo
Jordan Robinson
1
Eu tive esse problema e fui capaz de corrigi-lo trocando a linha que termina do tipo Windows para o tipo Linux.
Tristan
38
wget --spider -S "http://url/to/be/checked" 2>&1 | grep "HTTP/" | awk '{print $2}'

imprime apenas o código de status para você

user551168
fonte
9
+1 Mostra vários códigos quando um url é redirecionado, cada um em uma nova linha.
Ashfame
Tive que me livrar do --spider para que funcionasse com o pedido que eu estava tentando fazer, mas funciona.
amitavk
30

Ampliando a resposta já fornecida por Phil. Adicionar paralelismo a ele é um acéfalo no bash se você usar xargs para a chamada.

Aqui está o código:

xargs -n1 -P 10 curl -o /dev/null --silent --head --write-out '%{url_effective}: %{http_code}\n' < url.lst

-n1 : usa apenas um valor (da lista) como argumento para a chamada curl

-P10 : Mantenha 10 processos curl a qualquer momento (ou seja, 10 conexões paralelas)

Verifica a write_out parâmetro no manual do curl para mais dados que você pode extrair usando (tempos, etc).

Caso ajude alguém, esta é a chamada que estou usando no momento:

xargs -n1 -P 10 curl -o /dev/null --silent --head --write-out '%{url_effective};%{http_code};%{time_total};%{time_namelookup};%{time_connect};%{size_download};%{speed_download}\n' < url.lst | tee results.csv

Ele apenas produz um monte de dados em um arquivo csv que pode ser importado para qualquer ferramenta de escritório.

Estani
fonte
2
Paralelismo, entrada de arquivo e csv. Exatamente o que eu estava procurando.
Agey
Brilhante, fez meu dia.
xlttj
Isso é incrível, exatamente o que eu estava procurando, obrigado senhor. Uma pergunta, como alguém poderia incluir o título da página nos resultados do csv?
MitchellK
@estani - stackoverflow.com/users/1182464/estani como alguém poderia incluir a obtenção do título da página de uma página no arquivo .csv. Desculpe por repostagem, esqueci de marcá-lo para que você fosse notificado sobre esta questão. Muito Obrigado.
MitchellK
@MitchellK isso não está controlando o conteúdo da chamada http de forma alguma. Se o "título da página" (seja lá o que for) estiver no url, você poderá adicioná-lo. Caso contrário, você precisa analisar a página inteira para extrair o "título" dela (supondo que você se refira a uma página html recuperada pelo http). Procure outras respostas no estouro da pilha ou faça essa pergunta específica.
estani
15

Isso depende amplamente disponível wget, presente em quase todos os lugares, mesmo no Alpine Linux.

wget --server-response --spider --quiet "${url}" 2>&1 | awk 'NR==1{print $2}'

As explicações são as seguintes:

--quiet

Desligue a saída do Wget.

Fonte - páginas de manual do wget

--spider

[...] não vai baixar as páginas, é só verificar se elas estão lá. [...]

Fonte - páginas de manual do wget

--server-response

Imprima os cabeçalhos enviados por servidores HTTP e as respostas enviadas por servidores FTP.

Fonte - páginas de manual do wget

O que eles não dizem --server-responseé que a saída desses cabeçalhos é impressa no erro padrão (sterr) , portanto, a necessidade de redirecionar para stdin.

A saída enviada para a entrada padrão, podemos canalizá-la awkpara extrair o código de status HTTP. Esse código é:

  • o segundo ( $2) grupo de caracteres não em branco:{$2}
  • na primeira linha do cabeçalho: NR==1

E porque queremos imprimi-lo ... {print $2}.

wget --server-response --spider --quiet "${url}" 2>&1 | awk 'NR==1{print $2}'
Salathiel Genèse
fonte
1
Eu usei este com2>&1 | head -1 | awk '{ print $2 }'
Evhz
7

Use curlpara buscar apenas o cabeçalho HTTP (não o arquivo inteiro) e analisá-lo:

$ curl -I  --stderr /dev/null http://www.google.co.uk/index.html | head -1 | cut -d' ' -f2
200
dogbane
fonte
curl me diz 200 quando wget diz 404 ... :(
Manu
O -Isinalizador faz com que curl faça uma solicitação HTTP HEAD, que é tratada separadamente de um HTTP GET normal por alguns servidores e pode, portanto, retornar valores diferentes. O comando ainda deve funcionar sem ele.
lambshaanxy
4

wget -S -i *file* obterá os cabeçalhos de cada url em um arquivo.

Filtre greppelo código de status especificamente.

Colinross
fonte
1

Encontrei uma ferramenta "webchk" escrita em Python. Retorna um código de status para uma lista de urls. Https://pypi.org/project/webchk/

A saída é semelhante a esta:

▶ webchk -i ./dxieu.txt | grep '200'
http://salesforce-case-status.dxi.eu/login ... 200 OK (0.108)
https://support.dxi.eu/hc/en-gb ... 200 OK (0.389)
https://support.dxi.eu/hc/en-gb ... 200 OK (0.401)

Espero que ajude!

Yura Loginov
fonte
0

Devido a https://mywiki.wooledge.org/BashPitfalls#Non-atomic_writes_with_xargs_-P (saída de trabalhos paralelos em xargsriscos sendo misturados), eu usaria GNU Parallel em vez de xargsparalelizar:

cat url.lst |
  parallel -P0 -q curl -o /dev/null --silent --head --write-out '%{url_effective}: %{http_code}\n' > outfile

Neste caso específico, pode ser seguro usar xargsporque a saída é muito curta, então o problema com o uso xargsé que se alguém alterar o código posteriormente para fazer algo maior, ele não será mais seguro. Ou se alguém lê esta pergunta e pensa que pode substituí-la curlpor outra, então isso também pode não ser seguro.

Ole Tange
fonte