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

    Здравствуйте.

    У меня на работе безлимитка, которой иногда хочется пользоваться. Например, закачивать много-много музыки, так, чтобы оставил, забыл на пару дней, вспомнил, а оно уже закачалось. Проблема в том, что безлимитка, все-таки, ограничена по скорости (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. Кроме того, пинг теперь не один, а столько, сколько захочется.

    Похожие публикации

    AdBlock похитил этот баннер, но баннеры не зубы — отрастут

    Подробнее
    Реклама

    Комментарии 66

      0
      А скрипт когда качает у вас пинг на яндекс не возрастает?
        +1
        Да и вообще вам нормальный шейпер нужен просто :)
          0
          Возрастает. Именно поэтому я wget убиваю и чуть-чуть жду :)
          (killall wget — это как раз оно)

          Шейпер? А шо це такое?
            +1
            Эээээ…

            Шейпинг — ограничение пропускной способности канала для отдельного узла сети ниже технических возможностей канала до узла. Шейпинг обычно используется как средство ограничения максимального потребления трафика со стороны узла сети.

            Устройство (или программу), осуществляющую ограничение скорости называют шейпер.
              0
              Нуууу, это не то. Я же тоже хочу работать с нормальной скоростью :)
              Нужно только wget ограничивать, а не весь трафик с моего компьютера.
                0
                То, то. Шейперы разные бывают :)
                Я для похожих целей использую delay_pools в squid
                  0
                  Вот, как раз, squid'овские delay_pools — не то (на сколько я знаю). Они же не могут ограничить работу одной только утилиты, только целый хост. А файлы я качаю с того же компьютера, на котором работаю.
                  Плюс, suqid штука достаточно большая, и поднимать ее на своем рабочем компьютере только для такой мелкой задачи — слегка непропорционально.
                    –2
                    Все равно шейперы бывают разные :)
                      –13
                      «черные, белые, красные»
                      © Отпетые Мошенники
                      0
                      сквид хоть и мощная, но небольшая штука.
                      так можно по разному коннектится к сквиду.
                      например все программы подефолту под одним лоином, wget под другим. вот и получаетм 2 асл которые рулим как нам надо.
                        0
                        Вся суть этого скрипта, что он отдает канал на закачку файла, только когда канал не используется. И только на закачку (не ограничивая компьютер целиком). Squid так может? (я просто не в курсе)
                          0
                          Squid, возможно и не может, а вот если порыться в QoS то наверняка там есть приоритизация траффика по его типу. Т. е. грубо говоря, *.mp3 файл качается на всю (или не на всю, тут как шейпер настроишь), но только до тех пор, пока не пойдет загрузка *.htm.
                          Посколько TCP/IP стек формирует очереди, то, грубо говоря, веб-странички идут «вне очереди», а уже после этого дается возможность скачатся mp3шке. Скорость не теряется никогда, веб летает. Конечно, возникнут сложности с настройкой, если ваши коллеги тоже не прочь покачать те же самые типы файлов :)

                          QoS+шейпер это то, что вам нужно. Но(!) если повозится с настройками.
                            0
                            Да и не обязательно весь траффик пускать через сквид. Пускай через него работает только wget. В скрипт надо будет добавить export http_proxy="http://127.0.1.2:8080" и export ftp_proxy="http://127.0.1.2:8080", а к вызову wget'a если есть авторизация прокси надо добавить --proxy-user=… и --proxy-password=…

                            А вообще, есть такая штучка для линухов, называется trickle — позволяет управлять шириной канала для отдельных процессов. Попробуйте, может это то, что надо.
                            0
                            там выше ошибочное высказывание что delay_pools рулят только хостами и сетями.
                            На самом деле они оперируют понятием acl которое может включать в себя например аутентификацию на прокси. Для вашей задачи достаточно 2- пулов 1-го и 2-го классов. В общем, RTFM — сквид очень гибкая штука.
                0
                Скорее всего большинство здесь посчитают этот шейпер не нормальным, но именно его я и использую для таких целей. Справляется отлично! Стоит копейки.

                  0
                  Какой именно?
                    0
                    Ой извините, что-то не то нажал и запостил сообщение… Отправлено через 5 минут ;)

                    Скорее всего большинство посчитает этот шейпер не нормальным, но все же я его использую и он мне нравится. Это не реклама конечно… Буду рад если хоть кому-то этот софт покажется интересным. Для начала не покупайте, а погоняйте месяц. Кажется там такой триал.

                    cfosspeed __http://www.cfos.de/speed/cfosspeed_ru.htm

                    + кряка было не найти, но стоит он копейки… за что им респект и уважуха!
                      0
                      Ну и что это? За что минусы? кто ставил? ;)
              +1
              Лучше уж не просто шейпить, а на базе QoS. В общих чертах это описано в статье про QoS (в Википедии)
                0
                Если я не ошибаюсь, то регулировать QoS, или нет — задача рутера. У меня до рутера доступа нет. Да и не пропорционально, опять же, в рутер лезть для таких целей.
                Плюс, мне нужно понижать приоритет конкретных пакетов, а не повышать приоритет всех остальных.
                  0
                  Немного ошибаетесь :) QoS есть в любой современной операционной системе. В винде, конечно, нужны надстройки, хотя и там на базовом уровне всё есть. Но вам будет мало того, что есть. Можете попробовать Traffic inspector, там это есть в более грамотном состоянии, чем в голой винде (хотя и не слишком много возможностей). Ну а если вы под линуксом или фряхой, то наверняка всё знаете и так :)
                • НЛО прилетело и опубликовало эту надпись здесь
                    +1
                    там всегда так
                  0
                  if [ `jobs %wget | mawk '{if (NR==1) print $2}'`0 == Running0 ]

                  then
                  # Если еще не докачал, то прерываем его работу вручную.
                  killall wget
                  else
                  # Ну, а если докачал, то выходим из while'а, и большими шагами идем к выходу.
                  break
                  fi
                    +4
                    какой-то странный хабр последнее время — в процессе набивания комментария, берёт и постит его раньше времени :(

                    if [ `jobs %wget | mawk '{if (NR==1) print $2}'`0 == Running0 ]
                    |
                    v
                    $status=$(jobs %wget | mawk '{if (NR==1) print $2}')
                    if [ "$status" == "Running" ]


                    и «странные нолики» не нужны (если обернуть `` в кавычки)
                      0
                      Я пытался с одинарными — не сработало.
                      Сейчас поправлю.
                        0
                        Да, что за черт, только что перенес в «Linux для всех», а теперь не хватает кармы отредактировать :(
                        Видимо, это переносится на когда-нибудь потом.
                    0
                    предложение по улучшению:
                    1) запуск wget
                    2) sleep
                    3) проверка — не скачал ли уже всё? (если скачал — выход)
                    4) пинг
                    5a) если пинг хороший, и в предыдущем цикле был тоже хороший, то вгет не трогаем
                    5b) если пинг хороший, и в предыдущем цикле был плохой, то вгет перезапускаем с повышенным приоритетом
                    5c) если пинг плохой, а был хороший, то даем юзерам поработать
                    5d) если пинг плохой, и был плохой, то либо вгет не трогаем, либо останавливаем вообще на некий период

                    ключевые отличия — пинг запускается синхронно с вгетом, если ситуация в сети не меняется, то лишних kill'ов вгета нет => оптимальнее использование времени.
                    а за счет того что во время пинга вгет еще качает — накидываем на оценку задержки например лишние 100мс если «быстрый» режим, и ничего не накидывать если «медленный».
                      +1
                      Если пинг запускается синхронно с wget'ом (без прекращения закачки), то время пинга будет очень большое, т. к. wget жрет весь канал и неохотно его отдает.
                      Что можно сделать, так это, если в прошлом цикле был хороший пинг, и в этом тоже, то можно длинну цикла увеличить. И, соответственно, если 2 раза подряд плохой пинг, то дать юзерам подольше нормально поработать.
                        0
                        а вы вгету в быстром режиме тоже скорость зарежьте на 90% от максимальной. чтобы для пингов кусочек полосы остался.
                          0
                          Все равно не получится различить, медленный пинг из-за того, что wget все занимает, или из-за того, что юзеры полезли. Юзеров нужно любить, и быть увереным, что им эта закачка не мешает :)
                            0
                            Да, есть еще догадка, что wget, заряженный на 90% проиграет по производительности wget'у, заряженному на 100%, но прирываемому раз в 20 секунд. Хотя, в этом я не уверен — считать надо.
                              +2
                              с точностью до наоборот. на установку-переустановку соединения больше времени и ресурсов тратится.
                                0
                                Я как посчитаю — скажу :)
                                Сейчас работать надо.
                                  +1
                                  И правда. Вот статистика, ниже немного рассчетов:
                                  Loading stats

                                  Средняя пауза — 4.2 секунды
                                  Средняя закачка — 19.3 секунды
                                  Срещний цикл — 23.5 секунд

                                  За цикл 90% скрипт закачает примерно 23.5*download_speed*0.9 байт.
                                  За тот же цикл текущий скрипт закачает 19.3*download_speed байт.
                                  Итого, постоянно качающий скрипт закачает примерно на 20% больше, чем непостоянно качающий.
                        • НЛО прилетело и опубликовало эту надпись здесь
                            0
                            Да, я то же самое хотел спросить.
                              0
                              Очень просто. Если поставить limit-rate, который не будет сильно тормозить интернет днем, когда люди работают, то он и ночью, когда никто не работает, тоже канал на полную использовать не будет. А так канал используется на полную всегда, когда он свободен (и даже днем, когда его не используют).
                                0
                                включайте закачки по крону ночью, не мешайте работать людям днём. С рабочим днём 8 часов вы получаете от 1/2 до 2/3 времени, когда вы можете качать на всю ширину канала. Уверяю вас, вам этого хватит, я сам был в такой же ситуации.
                                  0
                                  А вот я люблю работать поночам…
                                    0
                                    *по ночам
                            • НЛО прилетело и опубликовало эту надпись здесь
                                0
                                -a
                                  0
                                  "… Этот скрипт принципиально не сработает, если сервер, с которого качаем файлы, не поддерживает докачку..."
                                    0
                                    100b/s, это когда инет пользуют сотрудники, чтобы им не мешало. В остальное время wget занимает канал полностью.

                                    У wget'а есть опция -c, которая продолжает закачку (докачивает) файла. Понятно, что если сервер докачку не поддерживает, то ничего не сработает.
                                    0
                                    Это на весь офис канал 30 кб/сек? новосибирский коммерческий блин интернет (
                                      0
                                      Ну, он, по идее, больше, только остальная часть зарезервирована под VoIP.
                                      +2
                                      таким инетом только яндекс пинговать, не более того
                                      канал урезан строго на 2 телефонных потка без запапса, а вы умудряетесь лить по нему музло.
                                        0
                                        Канал — мегабит. Выделена полоса под VoIP, остальное поделено меджу несколькими оффисами. То, что используется под закачку, не мешает ничему другому (когда полоса выделенная на офис не используется сотрудниками). Но лимит на офис — 30kb/s.
                                        0
                                        Я бы сюда ещё добавил очередь закачки, т. е. скрипт читает url'ы из файла или из fifo, чтобы уж нагрузить так нагрузить. Да и жёстко прописывать url в скрипт не очень красиво, хотя бы сделать это через аргумент командной строки или на худой конец через константу.
                                          +1
                                          1. Калибровка: wget без limit-rate иногда, смотрим скорость за 10 секунд

                                          2. Ставим limit-rate на 10% меньше, чем получившаяся скорость и постоянно следим.

                                          3. Если скорость на очередном этапе меньше установленного limit-rate — пора ещё на 10% уменьшить.

                                          4. Если уже несколько минут ровно limit-rate — можно попробовать запустить калибрационное измерение (п.1)

                                          Слежение за скоростью — по размеру файла или по логу wget.
                                            0
                                            Проверьте свой роутер на доступность по SNMP. Часто бывает, что открыт и без пароля. Снимать текущую скорость по SNMP — это гораздо лучше, чем ping :)
                                              0
                                              Рутер, который раздает сеть, не в моей юрисдикции. Лезть в него — значт портить отношения с админом, а это нехорошо :)
                                                0
                                                на чтение разрешений может и хватить.
                                              0
                                              У меня роутер под линуксом без каких-то специальных на то настроек вполне себе поровну траффик распределяет. То есть у меня висит wget в бэкрграунде и я, или кто-то с другого компьютера идёт в инет, то у меня скорость сама по себе на wget падает и всё.

                                              А если торренты, то там уже не поковырявшись с шейпером никак их не подвинуть, но руки не добираются до настройки :)
                                                0
                                                Вроде в винде есть служба фоновой загрузки (BITS), которая работает, когда канал свободен. Правда, что плохо, этой службой любят пользоваться вирусы, поэтому она у меня отключена)) Но я думаю, ее можно как-то использовать для этих целей.
                                                  +1
                                                  Жаль, только, что у меня не windows :)
                                                  0
                                                  -b

                                                  wget работает в бекграунде
                                                    0
                                                    wget bla-bla&
                                                    тоже посылает его в бэкграунд. Только это не тот бэкграунд, который хочется получить.
                                                      0
                                                      я просто к тому что вы используете & когда вгет имеет для этого опцию, хотя разницы конечно никакой
                                                        0
                                                        Просто стандартные штучки bash'а как-то привычнее :)
                                                          0
                                                          Откройте консоль в графике, сделайте wget с -b и wget с &. Закройте консоль.
                                                          Только в первом случае wget будет жить, второй умрет как дочерний процесс консоли.
                                                            0
                                                            > хотя разницы конечно никакой
                                                            Может вы имели в виду конкретный случай (т. е. то, что здесь это роли не сыграет), тогда я не к месту сказал.
                                                              0
                                                              Я, таки, возражаю.
                                                              Если сделать wget bla-bla&
                                                              и закрыть консоль, то wget остается жить. Его можно найти в ps (ps aux | grep wget)
                                                                0
                                                                если из консоли выйти по-человечески через exit, то во втором случае процесс останется жить
                                                          +1
                                                          фаерволы позволяют шейпить трафик по пользователям если сорс пакета сама машина с фаерволом, запускаем wget от пользователя с N и задаем его очереди самый низкий приоритет

                                                          тут например настройка фаерволла

                                                          Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                                                          Самое читаемое