Como posso ler URLs em linhas separadas em um arquivo .txt e pingar cada uma delas

6

Eu tenho um arquivo .txt com 5 URLs nele. Eu quero lê-lo linha por linha e executar 4 solicitações de ping para cada site e extrair o tempo. O código que escrevi está abaixo, mas não está funcionando.

Alguém pode me dar uma dica?

#!/bin/bash

cat /home/akis/Desktop/sites.txt
declare -i var=1
while read -r line
do
    while $var <= 5 
    do
        var2=$((var2+1)) 
        name="$line" | ping -c 4 $name > $var.txt | awk '{ print  }' < $var.txt | awk '/time/' > $var2.txt | tr '=' '\t' < $var2.txt | awk '{ print  }' > $var2.txt
    done

    var=$((var+1))  
done 
    
por Akis Tachmatzidis 17.11.2017 / 14:12

2 respostas

8

Isto, assim como a resposta de Sergiy , veio de Faça um loop sobre o arquivo de texto com URLs e execute ping em cada .

Supondo que o arquivo urls resida no diretório atual e contenha seus URLs somente , um por linha:

#!/bin/bash
while IFS='' read -r l || [ -n "$l" ]; do
  avg=$(ping -q -w 10 "$l" | sed '$!d;s_.*=[^/]*/\([^/]*\)/.*__')
  echo "Average respond time for $l: $avg ms" >> avg_time
done < "urls"

Exemplo de execução

O script acima foi nomeado avg aqui.

$ cat urls
askubuntu.com
unix.stackexchange.com
stackoverflow.com
$ ./avg
$ cat avg_time 
Average respond time for askubuntu.com: 37.742 ms
Average respond time for unix.stackexchange.com: 35.966 ms
Average respond time for stackoverflow.com: 38.982 ms

Explicações

  • #!/bin/bash
    o assim chamado shebang define qual shell seu script deve ser iniciado aqui está bash
  • while IFS='' read -r l || [ -n "$l" ]; do stuff; done < "urls"
    read o arquivo chamado urls linha por linha, atribuindo o conteúdo da linha atualmente processada para a variável l e fazendo stuff com ela
  • ping -q -w 10 "$l" (= ping -qw10 "$l" )
    chame ping com o conteúdo da variável l como o argumento e as opções -q uiet (menos saída que não precisamos) e -w 10 (tempo limite em segundos), para que o URL atualmente processado seja pingado para exatamente 10 segundos - você pode ajustar este valor às suas necessidades, assim como especificar outras opções (veja man ping ) para a lista)
  • avg=$(ping … | sed …)
    canalize a saída de ping para sed , que corta o tempo médio de resposta e salva esse valor na variável avg

    • sed '$!d;s_.*=[^/]*/\([^/]*\)/.*__'
    • sed '$!d
      não ( ! ) d elete a última linha ( $ ), mas o resto inteiro
    • sed 's/a/b/' e s ubstitute a por b - também pode ser escrito como, por exemplo, sed 's_a_b_' se for útil, dessa forma não precisamos evitar caracteres de barras literais nas strings
      • .* - leve tudo
      • = e / - um literal "=" e "/"
      • [^/]* - pega tudo que não é ( ^ ) uma barra
      • \([^/]*\) - pega tudo que não é ( ^ ) uma barra e salva em um grupo
      • - o primeiro grupo salvo com \(…\) antes
    • o mesmo trabalho também pode ser feito com awk -F/ '/^rtt/{print}' :
      • -F/ - define / como o delimitador F ield
      • /^rtt/{…} - selecione o início da linha ( ^ ) com "rtt" e faça com ele
      • print - print somente no. %código%
  • 5
    imprima o texto inserindo o conteúdo das variáveis echo "Average respond time for $l: $avg ms" >> avg_time e l e redirecione essa saída para o arquivo avg anexando ao seu conteúdo

por dessert 11.11.2017 / 14:50
7

Para um único comando simples, como ping , pode-se usar xargs . O legal sobre xargs é que ele tem a opção --arg-file , que permite especificar o arquivo que xargs usará para fornecer parâmetros posicionais ao comando que você está tentando executar; no seu caso, isso seria um site por linha no arquivo de texto.

Especificamente, o comando que você quer é o seguinte:

xargs -I% --arg-file=./input.txt  ping -c 4 %
  • -I nos permite escolher o espaço reservado para cada argumento, que xargs internamente irá
  • --arg-file é o arquivo do qual os parâmetros posicionais virão; Observe que estamos usando ./ para indicar que o arquivo está localizado no diretório de trabalho atual
  • ping -c 4 tentará ping de cada site proveniente de input.txt com 4 pacotes

Observe que também podemos usar a opção -q para ping , que impedirá a impressão de uma linha para cada pacote recebido / transmitido, com apenas as estatísticas sendo exibidas. A partir daí, podemos limpar a saída ainda mais com awk ou qualquer outro utilitário de processamento de texto (lembre-se de que a saída será armazenada em buffer durante o pipe e aguardar que ping realmente termine e produza estatísticas. na tela um pouco lento):

$ xargs -I% --arg-file=./input.txt  ping -c 4 % -q | awk '/^---/||/avg/'                                                                                     
--- askubuntu.com ping statistics ---
rtt min/avg/max/mdev = 49.677/73.403/94.312/19.276 ms
--- unix.stackexchange.com ping statistics ---
rtt min/avg/max/mdev = 40.015/59.099/115.545/32.590 ms
--- stackoverflow.com ping statistics ---
rtt min/avg/max/mdev = 40.130/40.878/42.685/1.056 ms

$ xargs -I% --arg-file=./input.txt  ping -c 4 % -q | awk -F'[ /]' '/^---/{print };/avg/{print }'                                                         
askubuntu.com
39.809
unix.stackexchange.com
189.557
stackoverflow.com
161.974
    
por Sergiy Kolodyazhnyy 13.11.2017 / 08:41