Как я могу прочитать URL-адреса в отдельных строках в текстовом файле и пинговать каждый

У меня есть .txt файл с 5 URL в нем. Я хочу прочитать его построчно, выполнить 4 запроса ping для каждого сайта и извлечь время. Код, который я написал ниже, но он не работает.

Кто-нибудь может дать мне подсказку?

#!/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 $8 }' < $var.txt | awk '/time/' > $var2.txt | tr '=' '\t' < $var2.txt | awk '{ print $2 }' > $var2.txt
    done

    var=$((var+1))  
done 

2 ответа

Решение

Это, а также ответ Сергея пришли из Loop over текстовый файл с URL-адресами и выполнить ping для каждого.

Предполагая файл urls находится в текущем каталоге и содержит только ваши URL, по одному в строке:

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

Пример запуска

Выше сценарий был назван avg Вот.

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

Пояснения

  • #!/bin/bash
    этот так называемый шебанг определяет, с какой оболочки должен запускаться ваш скрипт, здесь bash
  • while IFS='' read -r l || [ -n "$l" ]; do stuff; done < "urls"
    read файл с именем urls построчно, присваивая переменную содержимое текущей строки l и делать stuff с этим
  • ping -q -w 10 "$l" знак равно ping -qw10 "$l")
    вызов ping с содержанием переменной l в качестве аргумента и вариантов -q Uiet (меньше продукции нам не нужно) и -w 10 (время ожидания в секундах), поэтому обрабатываемый в данный момент URL-адрес проверяется точно 10 секунд - вы можете настроить это значение в соответствии со своими потребностями, а также указать другие параметры (см. man ping) для списка)
  • avg=$(ping … | sed …)
    труба на выходе ping в sed который сокращает среднее время ответа и сохраняет это значение в переменной avg

    • sed '$!d;s_.*=[^/]*/\([^/]*\)/.*_\1_'
    • sed '$!d
      не (!) d выберите последнюю строку ($) но все остальное
    • sed 's/a/b/'
      s ubstitute a от b - также может быть написано как, например, sed 's_a_b_' если это полезно, таким образом нам не нужно экранировать буквенные символы косой черты в строках
      • .* - возьми все
      • = а также / - буквальное "=" и "/"
      • [^/]* - бери все что не есть (^) косая черта
      • \([^/]*\) - бери все что не есть (^) косая черта и сохранить его в группе
      • \1 - первая группа, сохраненная с \(…\) до
    • та же самая работа могла бы быть сделана с awk -F/ '/^rtt/{print$5}':
      • -F/ - определить / как F разделитель полей
      • /^rtt/{…} - выберите начало строки (^) с "RTT" и сделать с этим
      • print$5 - print только поле № 5
  • echo "Average respond time for $l: $avg ms" >> avg_time
    печатать текст, вставляя содержимое переменных l а также avg и перенаправить этот вывод в файл avg_time добавление к его содержанию

Для одной простой команды, такой как ping можно использовать xargs, Классная вещь о xargs в том что --arg-file опция, которая позволяет указать файл, который xargs будет использовать для предоставления позиционных параметров команде, которую вы пытаетесь запустить; в вашем случае это будет один сайт на строку в текстовом файле.

В частности, команда, которую вы хотите, это:

xargs -I% --arg-file=./input.txt  ping -c 4 %
  • -I позволяет нам выбрать заполнитель для каждого аргумента, который xargs внутренне будет
  • --arg-file файл, из которого поступят позиционные параметры; обратите внимание, что мы используем ./ указать, что файл находится в текущем рабочем каталоге
  • ping -c 4 будет пытаться ping каждый сайт, который приходит input.txt с 4 пакетами

Обратите внимание, что мы также можем использовать -q возможность ping это предотвратит печать строки для каждого полученного / переданного пакета, с выводом только статистики. Оттуда мы можем очистить вывод еще дальше с awk или любая другая утилита для обработки текста (имейте в виду, что вывод будет буферизован при прохождении через канал и ожидании ping чтобы на самом деле закончить и выводить статистику, поэтому будет отображаться на экране немного медленно):

$ xargs -I% --arg-file=./input.txt  ping -c 4 % -q | awk '/^---/||/avg/'                                                                                     
--- Ask-ubuntu.ru 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 $2};/avg/{print $8}'                                                         
Ask-ubuntu.ru
39.809
unix.stackexchange.com
189.557
stackoverflow.com
161.974
Другие вопросы по тегам