Как стать автором
Обновить

Качаем файлы в бэкграунде

Время на прочтение3 мин
Количество просмотров1.7K
Здравствуйте.

У меня на работе безлимитка, которой иногда хочется пользоваться. Например, закачивать много-много музыки, так, чтобы оставил, забыл на пару дней, вспомнил, а оно уже закачалось. Проблема в том, что безлимитка, все-таки, ограничена по скорости (30Kb/s), и если в наглую оставить закачку wget'ом, то никто этому рад не будет.

Я написал небольшой скриптик, который пингует яндекс, и на основании этого меняет скорость закачки:

#!/bin/bash
limit=1
delay=5
num_of_pings=3

while true
do
    # Собственно, качаем. --limit-rate — это ограничение скорости. Обратите внимание на "&" в конце строки, он нужен, чтобы wget уходил в background
    wget -t0 -c --limit-rate=$limit -q хттп://адрес_до_файла&
    # Запоминаем номер работы, которую мы только что создали.
    jobnum=`jobs %% | mawk '{if (NR==1) print $1}' | perl -pe 's/\[//; s/\]\+//'`
    # Даем wget'у немного времени, чтобы поработать.
    sleep $delay<br>
    # Проверяем, не успел ли уже wget все закачать. Для этого смотрим jobs, находим там статус закачки (он либо Running, либо wget'а там нет вообще).
    if [ "`jobs %$jobnum | mawk '{if (NR==1) print $2}'`" == "Running" ]
    then
    # Если еще не докачал, то прерываем его работу вручную.
        kill %$jobnum
    else
    # Ну, а если докачал, то выходим из while'а, и большими шагами идем к выходу.
        break
    fi
    # Даем сети немного времени успокоиться, чтобы результаты работы wget'а не влияли на замер скорости в следующей строчке
    sleep 2
    # Посылаем несколько пингов до яндекса и смотрим сколько времени они идут. Если среднее значение меньше 300 милисекунд, то считаем, что сеть свободна.
    if [ `ping -c $num_of_pings ya.ru | grep time= | mawk '{print $8}' | perl -pe 's/time=//' | mawk '$1 ~ // {sum += $1}; END {sum /= '$num_of_pings'; print sum}' | perl -pe 's/\.[0-9]*//'` -le 300 ]
    then
    # Ага, сеть свободна. Тогда немножечко времени (20 секунд) качаем без ограничений.
        limit=0
        delay=20
    else
    # Упс, занято. Даем людям 5 минут спокойно поработать (закачка на уровне 100b/s).
        limit=100
        delay=300
    fi
done



Эта штука почти не мешает работе, разве что раз в пять минут на 20 секунд. И то, только если не повезет в этот момент освободить канал.

Но проблемы, все-таки, есть:
  1. Когда канал свободен, он используется не на полную — теряются несколько секунд на простой, плюс, немного времени у wget'а на восстановление соединения.
  2. Этот скрипт принципиально не сработает, если сервер, с которого качаем файлы, не поддерживает докачку.
  3. Если скриптина таки зацапает себе канал, то придется ждать 20 секунд.


Собственно, теперь пара вопросов:
Кто-нибудь может подсказать более хороший и правильный способ для таких закачек?
Как можно улучшить этот скрипт, чтобы он стал хорошим и правильным способом?

UPD: Слегка подправил скрипт. Он теперь работает с конкретной работой (job) которую создает, и больше нет глобальных killall wget. Кроме того, пинг теперь не один, а столько, сколько захочется.
Теги:
Хабы:
+30
Комментарии66

Публикации

Изменить настройки темы

Истории

Ближайшие события

Weekend Offer в AliExpress
Дата20 – 21 апреля
Время10:00 – 20:00
Место
Онлайн
Конференция «Я.Железо»
Дата18 мая
Время14:00 – 23:59
Место
МоскваОнлайн