Найдено на просторах интернета.
Задача.
1. Скачивание списка ссылок из файла
2. Скачивание одновременно нескольких файлов
3. Перенос неудавшихся закачек в отдельный список для дальнейших повторных попыток.
#!/bin/sh
log_dir="${PWD}/log"
list_dir="${PWD}/list"
output_dir=${PWD}
# download_list - файл ссылок для скачивания
download_list="${list_dir}/download.lst"
# В active_list записываются активные закачки
active_list="${list_dir}/active.lst"
# В done_list записываются скачанные ссылки
done_list="${list_dir}/done.lst"
# В error_list записываются неудавшиеся закачки
error_list="${list_dir}/error.lst"
# $timeout - время перед повторной попыткой скачивания неудавшейся закачки
timeout=5
# Перемещает строку $1 из файла $2 в файл $3, нужна для манипуляций со списками
# move_line line source_file dest_file
move_line()
{
tmp_file=`mktemp -t downloader.XX`
echo $1 >> $3
cat $2 | grep -v $1 > $tmp_file
mv $tmp_file $2
}
# Функция скачивания, в $1 передается номер потока скачивания
download_thread()
{
thread=$1
# Цикл скачивания, пока файлы download.lst и error.lst не станут пустыми
while [ -s $download_list ] || [ -s $error_list ]
do
# Если download.lst пустой - переносим в него строку из error.lst
if [ ! -s $download_list ]
then
read url < $error_list
move_line $url $error_list $download_list
sleep $timeout
fi
read url < $download_list
move_line $url $download_list $active_list
echo "[Thread ${thread}]Starting download: $url"
# Старт закачки
wget -c -o "${log_dir}/wget_thread${thread}.log" -O "${output_dir}/$(basename "$url")" $url
# Проверка кода завершения wget (Если 0 - закачка успешная)
if [ $? -eq 0 ]
then
# Закачка файла завершилась удачно
move_line $url $active_list $done_list
echo "[Thread ${thread}]Download successful: $url"
else
# Ошибка закачки - перемещаем в файл с ошибочными ссылками
move_line $url $active_list $error_list
echo "[Thread ${thread}]Error download: $url"
fi
done
return 0
}
# Завершает ранее запущенные процессы скрипта и закачки из active.lst
stop_script()
{
# Убиваем все процессы этого скрипта кроме текущего
kill -9 `ps ax | grep $0 | grep -v "grep" | awk '{print $1}' | grep -v $$`
# Убиваем все процессы закачек из active.lst
while [ -s $active_list ]
do
read url < $active_list
move_line $url $active_list $download_list
kill -9 `ps ax | grep $url | grep -v "grep" | awk '{print $1}'`
done
}
case "$1" in
"stop" )
echo "Stoping downloader..."
stop_script
echo "Done..."
;;
"start" )
# Проверка наналичие файла со ссылками для скачивания
if [ ! -e $download_list ];
then
echo "[Error] There is no ${list_dir}/download.lst file"
exit
fi
echo "Starting downloader..."
# На случай вторичного запуска скрипта останавливаем ранее запущенные процессы
stop_script
# Если не задано кол-во одновременных закачек в $2, устанавливаем 1 поток
if [ -z $2 ]
then
threads=1
else
threads=$2
fi
# Запускаем в фоне закачки
i=1
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
# Все скачали...
echo "All completed"
;;
* )
echo "Usage:"
echo "\t$0 start [number of threads]"
echo "\t$0 stop"
;;
esac
return 0
Для работы скрипта необходимо сделать его исполняемым и создать файл "./list/download.lst" со списком ссылок для скачивания.
Запуск:
./downloader start [количество одновременных скачиваний]
Параметр после 'start' необязательный (если его не указать — используется «1»).
Т.е. `./downloader start 2` запустит скрипт с одновременным скачиванием 2-х файлов.
Остановка:
./downloader stop
При завершении скрипта при помощи «Ctrl+C» закачки не завершаются, т.к. работают в фоне, поэтому необходимо выполнить вышеуказанную команду команду для остановки скачивания.
Я решил не загромождать скрипт, но в принципе, не сложно реализуется работа со списками (show — вывод на экран, add — добавление закачки, wipe — очистка). А так он рабочий хоть и с минимальной функциональностью.
Дальше я вкратце опишу принципы работы скрипта, чтобы желающим легче было модифицировать его под свои нужды.
В константах указаны:
log_dir — папка с логами wget'a (по умолчанию "./log")
list_dir — папка со списками download_list, active_list, done_list, error_list (по умолчанию "./list")
output_dir — папка куда будут сохраняться скачиваемые файлы (по умолчанию ".")
download_list список ссылок для скачивания
active_list — список активных закачек
done_list — список завершенных закачек
error_list — список неудавшихся закачек
timeout — время перед повторной попыткой скачивания неудавшейся закачки
В начале работы скрипт останавливает ранее запущенные его копии, а также закачки из active_list (конечно если такие имеются) с переносом их в download_list. Это делается на случай повторного запуска скрипта до завершения скачивания ранее запущенным процессом. Дальше в цикле создается необходимое количество фоновых закачек. Каждый такой фоновый поток реализуется функцией download_thread(). Ее работа заключается в скачивании файлов из списка пока списки download_list и error_list не станут пустыми. Таким образом основная часть скрипта, проверяя эти файлы узнает закончилась ли скачка. Перед запуском wget'a ссылка переносится из файла download_list в файл active_list. После завершения работы wget'a ссылка переносится, либо в done_list (если код возврата был '0'), либо в error_list (если код возврата был не равен '0').
После того как все скачано (списки download_list и error_list пусты) скрипт завершает свою работу.
Задача.
1. Скачивание списка ссылок из файла
2. Скачивание одновременно нескольких файлов
3. Перенос неудавшихся закачек в отдельный список для дальнейших повторных попыток.
#!/bin/sh
log_dir="${PWD}/log"
list_dir="${PWD}/list"
output_dir=${PWD}
# download_list - файл ссылок для скачивания
download_list="${list_dir}/download.lst"
# В active_list записываются активные закачки
active_list="${list_dir}/active.lst"
# В done_list записываются скачанные ссылки
done_list="${list_dir}/done.lst"
# В error_list записываются неудавшиеся закачки
error_list="${list_dir}/error.lst"
# $timeout - время перед повторной попыткой скачивания неудавшейся закачки
timeout=5
# Перемещает строку $1 из файла $2 в файл $3, нужна для манипуляций со списками
# move_line line source_file dest_file
move_line()
{
tmp_file=`mktemp -t downloader.XX`
echo $1 >> $3
cat $2 | grep -v $1 > $tmp_file
mv $tmp_file $2
}
# Функция скачивания, в $1 передается номер потока скачивания
download_thread()
{
thread=$1
# Цикл скачивания, пока файлы download.lst и error.lst не станут пустыми
while [ -s $download_list ] || [ -s $error_list ]
do
# Если download.lst пустой - переносим в него строку из error.lst
if [ ! -s $download_list ]
then
read url < $error_list
move_line $url $error_list $download_list
sleep $timeout
fi
read url < $download_list
move_line $url $download_list $active_list
echo "[Thread ${thread}]Starting download: $url"
# Старт закачки
wget -c -o "${log_dir}/wget_thread${thread}.log" -O "${output_dir}/$(basename "$url")" $url
# Проверка кода завершения wget (Если 0 - закачка успешная)
if [ $? -eq 0 ]
then
# Закачка файла завершилась удачно
move_line $url $active_list $done_list
echo "[Thread ${thread}]Download successful: $url"
else
# Ошибка закачки - перемещаем в файл с ошибочными ссылками
move_line $url $active_list $error_list
echo "[Thread ${thread}]Error download: $url"
fi
done
return 0
}
# Завершает ранее запущенные процессы скрипта и закачки из active.lst
stop_script()
{
# Убиваем все процессы этого скрипта кроме текущего
kill -9 `ps ax | grep $0 | grep -v "grep" | awk '{print $1}' | grep -v $$`
# Убиваем все процессы закачек из active.lst
while [ -s $active_list ]
do
read url < $active_list
move_line $url $active_list $download_list
kill -9 `ps ax | grep $url | grep -v "grep" | awk '{print $1}'`
done
}
case "$1" in
"stop" )
echo "Stoping downloader..."
stop_script
echo "Done..."
;;
"start" )
# Проверка наналичие файла со ссылками для скачивания
if [ ! -e $download_list ];
then
echo "[Error] There is no ${list_dir}/download.lst file"
exit
fi
echo "Starting downloader..."
# На случай вторичного запуска скрипта останавливаем ранее запущенные процессы
stop_script
# Если не задано кол-во одновременных закачек в $2, устанавливаем 1 поток
if [ -z $2 ]
then
threads=1
else
threads=$2
fi
# Запускаем в фоне закачки
i=1
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
# Все скачали...
echo "All completed"
;;
* )
echo "Usage:"
echo "\t$0 start [number of threads]"
echo "\t$0 stop"
;;
esac
return 0
Для работы скрипта необходимо сделать его исполняемым и создать файл "./list/download.lst" со списком ссылок для скачивания.
Запуск:
./downloader start [количество одновременных скачиваний]
Параметр после 'start' необязательный (если его не указать — используется «1»).
Т.е. `./downloader start 2` запустит скрипт с одновременным скачиванием 2-х файлов.
Остановка:
./downloader stop
При завершении скрипта при помощи «Ctrl+C» закачки не завершаются, т.к. работают в фоне, поэтому необходимо выполнить вышеуказанную команду команду для остановки скачивания.
Я решил не загромождать скрипт, но в принципе, не сложно реализуется работа со списками (show — вывод на экран, add — добавление закачки, wipe — очистка). А так он рабочий хоть и с минимальной функциональностью.
Дальше я вкратце опишу принципы работы скрипта, чтобы желающим легче было модифицировать его под свои нужды.
В константах указаны:
log_dir — папка с логами wget'a (по умолчанию "./log")
list_dir — папка со списками download_list, active_list, done_list, error_list (по умолчанию "./list")
output_dir — папка куда будут сохраняться скачиваемые файлы (по умолчанию ".")
download_list список ссылок для скачивания
active_list — список активных закачек
done_list — список завершенных закачек
error_list — список неудавшихся закачек
timeout — время перед повторной попыткой скачивания неудавшейся закачки
В начале работы скрипт останавливает ранее запущенные его копии, а также закачки из active_list (конечно если такие имеются) с переносом их в download_list. Это делается на случай повторного запуска скрипта до завершения скачивания ранее запущенным процессом. Дальше в цикле создается необходимое количество фоновых закачек. Каждый такой фоновый поток реализуется функцией download_thread(). Ее работа заключается в скачивании файлов из списка пока списки download_list и error_list не станут пустыми. Таким образом основная часть скрипта, проверяя эти файлы узнает закончилась ли скачка. Перед запуском wget'a ссылка переносится из файла download_list в файл active_list. После завершения работы wget'a ссылка переносится, либо в done_list (если код возврата был '0'), либо в error_list (если код возврата был не равен '0').
После того как все скачано (списки download_list и error_list пусты) скрипт завершает свою работу.