Вы когда-нибудь пробовали скачивать по медленному каналу такой огромный файл, что приходилось держать веб-броузер открытым часы или даже дни напролёт? А если на 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 '