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

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

Тоже занимаюсь написанием удобного интерфейса для wget, пишу его под web на java.
о как раз ищу удобный web интерфейс для wget чтоб он понимал список ссылок и запоминал кукисы от рапидшары, как допишете выкладывайте на хабр!
Выложу, конечно
Смотрели ли в сторону httrack/webhttrack?
Раньше не слышал, возьму на заметку, спасибо
Думаю, команда wait с успехом заменит нижележайший код:

# По наличию записей в active.lst error.lst проверяем идет ли закачка
while [ -s $active_list ] || [ -s $error_list ]
do
sleep 1
done
# Все скачали...
echo "All completed"
Спасибо за подсказку, сейчас попробую ее использовать.
Внес изменения в скрипт по Вашему совету. Вместо:
while [ $i -le $threads ]
do
    download_thread $i &
    sleep 1
    i=`expr $i + 1`
done
if [ ! -e $error_list ]; then touch $error_list; fi
# По наличию записей в active.lst error.lst проверяем идет ли закачка
while [ -s $active_list ] || [ -s $error_list ]
do
    sleep 1
done

Вот этот код:
while [ $i -le $threads ]
do
    download_thread $i &
    downloader_pid="${downloader_pid} $!"
    sleep 1
    i=`expr $i + 1`
done
if [ ! -e $error_list ]; then touch $error_list; fi
# Ждем окончания всех закачек
wait $downloader_pid
А почему бы не использовать aria2c? Можно будет убрать threads.
Да, есть такая замечательная утилита — aria2c (поддерживает скачивание нескольких файлов одновремено, скачивание по списку, + еще скачивание сегментами одного файла). Правда о ее существовании я узнал только после начала работы над скриптом. Поэтому, чтобы оправдать проделанную мной работу, скажу: wget входит практически во все дистрибутивы *nix (можно сказать что это стандарт). Так что для тех у кого нет возможности/желания устанавливать дополнительные программы я написал этот скрипт =)
Ну вообще то не во все, к примеру в FreeBSD по дефолту нет wget, придётся ставить из портов.
есть fetch.
Не будем сравнивать fetch и wget, у них абсолютно разный функционал по возможностям, fetch'У очень далеко до wget'А
Поэтому и написал: «практически». Хотя, если откровенно, то не знал что wget не входит в FreeBSD, думал, что он входит во все популярные дистрибутивы. Теперь думаю что это относится, скорее, к потомкам System V.
Формат инит-файлов никак не связан с наличием wget в дистрибутиве.
Насколько я помню: System V и BSD отличаются не только форматом инит-файлов (с этой темой не очень знаком, поэтому спорить не буду).
Но мое упоминание здесь system V в отношении wget было не очень уместно, потому что linux дистрибутивы содержат особенности реализации разных веток unix (System V и BSD в том числе). Поэтому наличие/отсутствие wget можно отнести только к особенностям конкретного дистрибутива.
Предпологаю, что это связано с GNU.
Ух ты, еще один полезный скрипт в копилку :)
Тоже хочу поблагодарить того человека, который пригласил полезного и интересного человека на хабр :)
Ох нифига ж себе первый bash-скрипт! Если бы у всех первые скрипты были такими, думаю, вендекапца точно не избежать было бы :)
Можно вместо wget использовать axel — еще и в несколько потоков грузить умеет «из коробки»
в заголовке #!/bin/bash, а запускать советуете через sh.
а не проще сделать примерно так:

l=`wc -l $download_list`
la=`echo "$l/$n" | bc`
split -l $la download_list down_split
for $i in `ls down_split*`; do
wget -i $i &
done
wait
ошибочка:

l=`wc -l $download_list |awk '{print $1}'`
la=`echo "$l/$n" | bc`
echo $la
split -l $la $download_list down_split
for i in `ls down_split*`; do
        wget -p -i $i &
done
wait
rm down_split*
/bin/bash исправил на /bin/sh
А такой способ деления списка — тоже вариант. Просто я хотел чтобы список можно было пополнять и во время закачек. Это до конца не реализовано (если качается в несколько потоков, все кроме одного завершились, то при добавлении в список n ссылок они будут качаться одним потоком). Можно немного изменить скрипт чтобы потоки не завершались, а раз в n минут проверяли опять список. Тогда можно использовать его, например, на сервере: просто скидывать сслыки в файл (echo ... >> download.lst)и они сами будут скачиваться.
А вы уверены, что у вас башизмов в коде нет, чтоб смело на /bin/sh исправлять? :-)
Честно — не уверен. Если совсем откровенно, то еще не разобрался в их отличиях :) Не судите строго, повторюсь — это мой первый опыт. Просто тестил и использовал при помощи `sh downloader ...` и все работало.
Я критику с одной целью пишу — знания распространить. :-)
Вот теперь вы знаете, что bash умеет больше, чем обычный sh и между ними есть отличия. В отличие от большинства Linux-ов, на FreeBSD, например, sh != bash.
>Ух ты, еще один полезный скрипт в копилку :)
а можно глянуть что в копилке?
используйте mktemp для создания временных файлов.
Спасибо, добавил в скрипт использование mktemp.
Плюсы:
— можно отказаться от переменной tmp_dir.
— создается случайное имя (вместо «XX» — буквы/цифры), что исключает возможности перезаписи одного временного файла при одновременном вхождении в функцию move_line() в разных потоках.
— никто не сотрёт ваш /home/luser/.ssh/id_rsa симлинком из /tmp/staticfilename -> /home/…
Не совсем понял о чем речь. Я имел ввиду, что ранее использованный код:
1. tmp_file="${tmp_dir}/downloader.tmp"
2. echo $1 >> $3
3. cat $2 | grep -v $1 > $tmp_file
4. mv $tmp_file $2

дает вероятность (хоть и маленькую), что в двух потоках одновременно выполнится строка №3 (т.е. временный файл одного потока перезапишется данными другого потока).
Плюс к тому, возможно перед стартом программы существует "${tmp_dir}/downloader.tmp", который является символьной ссылкой на файл, принадлежащий пользователю.
Таким образом, можно уничтожить файл пользователя, т.к. tmp_dir == /tmp а туда право на запись имеют все.

Поэтому надо использовать mktemp, который создаст НОВЫЙ файл и, возможно, использовать set -o noclobber (но второе — это уже для по настоящему параноидально написанных скриптов)
Данная атака имеет какое-то правильное название, но я его точно не помню. Ключевой момент, что файл в /tmp может быть символьной ссылкой и его может создать злоумышленник.

Вообще, при написании скриптов никогда не стоит забывать, что UNIX — многопользовательская система, поэтому в kill стоит еще и UID проверять, а также по-хорошему стоит отправлять сначала TERM и только через некоторое время KILL.
:-)
А у меня есть свой велосипед на баше для этого дела, забросил ввиду перехода на emacs-wget
Автору большое спасибо, выполнил хорошую автоматизацию отличной программы
Вам спасибо за отзыв и остальным за конструктивную критику. Все это добавляет энтузиазма для работы над чем-нибудь полезным для общества ;)
Вот вам хороший пример, хорошей связки curl+bash Пример скрипта Я думаю будет полезно Вам в нем покапаться :)
>Для работы скрипта необходимо сделать его исполняемым и создать файл "./list/download.lst" со списком ссылок для скачивания.

Запуск:
sh downloader start [количество одновременных скачиваний]


Небольшое замечание:

Если мы собираемся запускать скрипт именно так (передавая как параметр sh), то исполняемым его делать вовсе необязательно.
Исполняемым его нужно делать для того, чтобы иметь возможность запустить непосредственно его самого:

$ ./downloader [number of downloads]
Согласен. Написал в статье.
я дописал еще такую штучку

wget -c -o "${log_dir}/wget_thread${thread}.log" -O "${output_dir}/$(basename "$url")" $url 2>&1 | sed -u 's/.*\ \([0-9]\+%\)\ \+\([0-9.]\+\ [KMB\/s]\+\)$/\1\n# Downloading \2/' | zenity --progress --width=500 --title=«Downloading File: $(basename „$url“)»

Мне удобно, когда в GNOME вылетает окошко с прогресс-баром
как только мои shell скрипты переваливают за 20 строк, я бросаю шелл и перехожу на более удобный инструмент.

в частности, ваш скрипт подвершен упомянутому race condition, т.к. потоки никак не синхронизируются и могут запросто перетереть и файлы списков и сами скачиваемые файлы.

в образовательных целях шелл знать не помешает, но в работе нужны другие инструменты.
если в шелл скрипте более 1 раза встретились grep и awk — скрипт пора переписывать.
Да, скорее делал это в самообразовательных целях, и потому что встала задача такая. Можно было использовать тот же aria2c…
mktemp явно ждёт ещё одного X в 20 строчке, покрайней мере mktemp (GNU coreutils) 7.4 точно не работает без.
если не прибавить к параметрам запуска wget
--user-agent=«какой вам больше нравится»

многие-многие сайты будут футболить запросы потому что банлисты
Спасибо за совет
И вот это будет в тему

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