Загрузка без броузера

Автор: (C) Adrian J Chung
Перевод: (C) Александр Саввин

Вы когда-нибудь пробовали скачивать по медленному каналу такой огромный файл, что приходилось держать веб-броузер открытым часы или даже дни напролёт? А если на web-странице находятся ссылки на 40 нужных вам файлов - вы будете нудно щелкать по каждому из них? Что, если броузер "упадёт" до того, как он закончит скачивание? А ведь GNU/Linux поставляется вместе с удобным набором инструментов для независимой от броузера фоновой загрузки. Они позволяют выходить из системы, возобновлять прерванные задания и даже планировать выполнение заданий в периоды малой загрузки сети.

Когда интерактивность становится на пути

Назначение Web-броузеров в интерактивизации Web'а - щелкаем мышкой и ждём несколько секунд результат. Но множество файлов даже при самом быстром соединении требуют для загрузки гораздо больше, чем несколько секунд. Например, образы ISO, популярные среди тех, кто самостоятельно записывает CD-ROM'ы с дистрибутивами GNU/Linux. Некоторые web-броузеры, особенно плохо написанные, при длительном использованни ненадёжны, "теряя" память или "падая" в самый неподходящий момент. Несмотря на интеграцию некоторых броузеров с файловыми менеджерами, многие из них все еще не поддерживают операции множественного выбора и "резиновой нити" [имеется в виду выбор нескольких графических объектов, например файлов, нарисовав вокруг них мышкой "растягивающийся" прямоугольник -- прим. редактора], которые облегчают пересылку нескольких файлов. Кроме того, приходится оставаться зарегистрированным в системе до тех пор, пока файл не будет скачан полностью. Наконец, для того, чтобы щелкнуть по линку, инициализирующему загрузку, вы должны находиться в офисе, к неудовольствию использующих тот же канал коллег.

Для скачивания больших файлов более пригодны наборы инструментальных средств. В данной статье обсуждается, как скомбинировать разные GNU/Linux утилиты -- такие как lynx, wget, at, crontab и т.п. -- для решения различных задач по передаче файла(ов). Также будет использовано небольшое количество скриптов, поэтому будет полезно знание оболочки bash.

Утилита wget

Инструмент загрузки wget включен во все основные дистрибутивы.

  bash$ wget http://place.your.url/here

wget также может обрабатывать FTP, временные метки (date stamps), рекурсивно отражать полное дерево каталогов web-сайта, а если вы не будете осторожны, то весь web-сайт и другие сайты, на которые имеются ссылки:

  bash$ wget -m http://target.web.site/subdirectory

Из-за потенциально высоких нагрузок, которые может создавать wget, при зеркалировании он работает в соответствии с протоколом "robots.txt". Существуют несколько командных опций управления зеркалированием, ограничивающих виды отслеживаемых ссылок и типы загружаемых файлов. Например: следовать только по относительным ссылкам и пропускать изображения GIF:

  bash$ wget -m -L --reject=gif http://target.web.site/subdirectory

Кроме того, wget позволяет возобновлять прерванное задание (опция -"c"), если задан незавершенный файл, к которому добавляются оставшиеся данные.

  bash$ wget -c http://the.url.of/incomplete/file

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

Если у вас процесс загрузки прерывается столь же часто, как и у меня в офисе, вы можете заставить wget повторять URL несколько раз:

  bash$ wget -t 5 http://place.your.url/here

Тут мы делаем 5 попыток. Чтобы совсем не прерываться, используйте "-t inf".

Как на счет прокси-файрволлов? Чтобы указать прокси, через который нужно скачивать, используйте переменную окружения http_proxy или конфигурационный файл .wgetrc. Единственная проблема с проксируемыми соединениями по непостоянному каналу в том, что иногда возобновление срывается. Если загрузка через прокси сорвалась, то в кэше прокси-сервера останется неполная копия файла. Когда вы попытаетесь докачать оставшуюся часть файла с помощью команды "wget -c", прокси проверяет свой кэш и ошибочно сообщает, что вы скачали уже весь файл. Большинство прокси можно заставить не использовать свой кэш, добавив в свой запрос на загрузку специальный заголовок:

  bash$ wget -c --header="Pragma: no-cache" http://place.your.url/here

Опция "--header" позволяет добавлять любое количество и виды заголовков, с помощью которых можно изменять поведение web-серверов и прокси. Некоторые сайты не отдают файлы по ссылкам из внешних источников; контент передается броузеру только, если доступ к нему был получен из других страниц этого сайта. Это можно обойти, добавив заголовок "Referer:" :

  bash$ wget --header="Referer: http://coming.from.this/page" http://surfing.to.this/page

Некоторые особо недружественные web-сайты предоставляют контент только определённым видам броузеров. Это можно обойти с помощью заголовка "User-Agent:".

  bash$ wget --header="User-Agent: Mozilla/4.0 (compatible; MSIE 5.0; Windows NT;
DigExt)" http://msie.only.url/here

(Предупреждение: приведенные выше "хитрости" могут быть расценнены, как обман механизма лицензирования контента, и существуют жесткие законодательные системы, в которых эти действия считаются незаконными. Проверьте свое местное законодательство. У вас могут быть свои особенности.)

В котором часу начать закачку?

Если вы скачиваете большие файлы на своём офисном компьютере через соединение, разделяемое со вспыльчивыми коллегами, которые не любят, когда их медийный поток замедляется почти до нуля, то вам придется назначить закачку файлов на более свободные часы. Вам не нужно оставаться в офисе, ожидая ухода всех коллег или воспользоваться после ужина удаленным доступом из дома. Используйте таймер заданий at.

bash$ at 2300
warning: commands will be executed using /bin/sh
at>
wget http://place.your.url/here
at>
нажмите Ctrl-D

Тут мы задаем начало скачивания на 23:00. Проверьте, что в фоне для этого задания запущен демон таймера atd.

И сколько дней потребуется?

Когда нужно скачать много данных в одном или нескольких файлах, а скорость вашего канала сравнима с протоколом голубиной почты, то, приходя утром на работу, вы часто будете обнаруживать, что скачивание, запущенное по таймеру, всё еще не завершено. Будучи хорошим соседом, вы убиваете задание и создаёте новое задание at, в этот раз с помощью "wget -c", повторяя это, при необходимости, каждый день. Все же, это лучше автоматизировать с помощью crontab. Создайте простой текстовый файл с именем "crontab.txt", содержащий что-то типа этого:

0 23 * * 1-5    wget -c -N http://place.your.url/here
0  6 * * 1-5    killall wget

Это и будет вашим файлом crontab, который определяет какие периодические задания выполнять и когда. Первые пять колонок сообщают когда выполнить команду, а оставшаяся часть каждой строки указывает что необходимо выполнить. В первых двух колонках задаётся время дня -- в 0 минут 23 часа запустить wget, в 0 минут 6 часов убить wget. Символы * в 3-й и 4-й колонках указывают, что эти действия повторяются каждый день каждого месяца. 5-я колонка указывает на какой день недели запрограммирована каждая операция -- "1-5" соответствуют Понедельник-Пятница.

Таким образом, каждую неделю в рабочие дни в 11 часов вечера будет начинаться ваша закачка, а в 6 утра каждого рабочего дня любой всё ещё выполняющийся wget будет прерван. Для активизации этого расписания crontab вы должны выполнить команду:

  bash$ crontab crontab.txt

Опция "-N" для wget будет проверять временные метки (timestamp) целевого файла и остановит скачивание, если они совпадут, что является индикатором того, что файл скачан полностью. Таким образом, вы можете просто установить его и забыть. "crontab -r" удалит это запланированное задание. Таким способом я скачал кучу ISO образов через разделяемые dial-up соединения.

Динамически генерируемые Web страницы

Некоторые web страницы генерируются по запросу, так как они часто изменяются, иногда несколько раз за день. Поскольку технически наша цель файлом не является, то у нее нет длины, и, следовательно, докачка становится бессмысленной -- опция "-c" не работает. Пример -- PHP-сгенерированная страница на Linux Weekend News:

  bash$ wget http://lwn.net/bigpage.php3

Если закачка прерывается и вы пытаетесь докачать, то всё начнётся с самого начала. Временами мой сетевой канал в офисе настолько плох, что мне пришлось написать простой скрипт, обнаруживающий момент полного скачивания динамической HTML страницы:

#!/bin/bash

#создаем, если его нет
touch bigpage.php3

#Проверяем, все ли мы скачали
while ! grep -qi '</html>' bigpage.php3
do
rm -f bigpage.php3

#Скачиваем LWN в одну большую страницу
wget http://lwn.net/bigpage.php3

done

Этот bash-скрипт удерживает загрузку документа, пока не будет найдена строка "</html>", обозначающая конец файла.

SSL и Cookies

URL'ы, начинающиеся с "https://", обязаны предоставлять доступ к удалённым файлам через защищенное соединение SSL (Secure Sockets Layer). Вы обнаружите, что в этой ситуации более удобна другая утилита скачивания под названием curl.

Некоторые web-сайты запихивают cookies в броузер до предоставления затребованного контента. Необходимо добавить заголовок "Cookie:" с правильной информацией, которую можно получить из cookie-файла вашего web-броузера. Для lynx и Mozilla формат файла cookie:

  bash$ cookie=$( grep nytimes ~/.lynx_cookies |awk '{printf("%s=%s;",$6,$7)}' )

создает требуемый cookie для скачивания подборки с http://www.nytimes.com/, полагая, что вы уже зарегистрировались на этом сайте с помощью броузера. w3m использует немного другой формат файла cookie:

  bash$ cookie=$( grep nytimes ~/.w3m/cookie |awk '{printf("%s=%s;",$2,$3)}' )

Теперь скачивание можно выполнить таким образом:

  bash$ wget --header="Cookie: $cookie"
http://www.nytimes.com/reuters/technology/tech-tech-supercomput.html

или с помощью инструмента curl:

bash$ curl -v -b $cookie -o supercomp.html \
http://www.nytimes.com/reuters/technology/tech-tech-supercomput.html

[здесь строка разорвана (обратной косой чертой) из-за проблем с форматированием -- прим. перев.

Создание списков URL

До этого момента мы скачивали либо единичные файлы, либо полностью зеркалировали весь веб-сайт. Иногда необходимо скачать множество файлов с разными URL, указанными на веб-странице, но полномасштабное зеркалирование всего сайта не нужно. Например, требуется скачать первые 20 музыкальных файлов с сайта, отображающий по порядку 100 самых популярных песен. В данном случае, опции "--accept" и "--reject" работать не будут, поскольку они работают только с расширениями файлов. Вместо них используем "lynx -dump".

  bash$ lynx -dump ftp://ftp.ssc.com/pub/lg/ |grep 'gz$' |tail -10 |awk '{print $2}' > urllist.txt

Затем вывод lynx можно отфильтровать с помощью различных GNU утилит обработки текста. В приведённом выше примере мы выделили URL'ы, заканчивающиеся на "gz" и сохранили в файле последние 10. Крошечная скриптовая команда bash автоматически скачает любые URL'ы, перечисленные в этом файле:

bash$ for x in $(cat urllist.txt)
>
do
>
wget $x
>
done

Таким образом мы успешно скачали последние 10 выпусков Linux Gazette.

"Купаясь" в широком канале

Если вы один из немногих избранных, имеющих широкий канал, и скорость скачивания файлов ограничивается только на стороне web-сервера, то ускорить процесс пересылки файла может помочь следующий трюк. Для этого вам потребуется применение curl и наличие нескольких зеркальных веб-сайтов, на которых хранятся идентичные копии нужного файла. Например, вам нужно скачать ISO Mandrake 8.0 из следующих трех мест:


url1=http://ftp.eecs.umich.edu/pub/linux/mandrake/iso/Mandrake80-inst.iso
url2=http://ftp.rpmfind.net/linux/Mandrake/iso/Mandrake80-inst.iso
url3=http://ftp.wayne.edu/linux/mandrake/iso/Mandrake80-inst.iso

Длина файла равна 677281792, поэтому запустим три одновременных скачивания с помощью опции curl "--range" option:


bash$ curl -r 0-199999999 -o mdk-iso.part1 $url1 &
bash$ curl -r 200000000-399999999 -o mdk-iso.part2 $url2 &
bash$ curl -r 400000000- -o mdk-iso.part3 $url3 &

Создаются три фоновых процесса скачивания, каждый из которых копирует разные части ISO-образа с разных серверов. Опции "-r" задают поддиапазоны байтов, выбираемых из целевого файла. По завершению просто объедините с помощью cat все три части вместе -- cat mdk-iso.part? > mdk-80.iso. (Настоятельно рекомендуем проверить md5 hash до записи на CD-R.) Запуск каждого curl в своем собственном окне с опцией "--verbose" позволяет отследить каждый процесс скачивания.

Заключение

Не бойтесь использовать "не интерактивные" способы обмена файлами. Неважно насколько хитроумно web-дизайнеры пытаются заставить вас бродить по их сайту в интерактивном режиме, всегда найдутся свободные распространяемые инструменты для автоматизации этого процесса, обогащая тем самым наш сетевой опыт.


Adrian J Chung

Во время, свободное от изучения компьютеров в Университете западной Индии, Тринидад, Адриан пишет скрипты для автоматизации скачивания web email и экспериментирует с интерфейсом различных скриптовых сред, используя самодельные рендереры компьютерной графики и библиотеки визуализации данных.


Copyright c 2001, Adrian J Chung.
Published in Issue 70 of Linux Gazette, September 2001
Перевод: (C) 2001, Александр Саввин.