それで、私はHabrの本格的なユーザーになりました。 この記事に招待してくれた人に感謝したい:
少し前まで、Linux(特にUbuntu 8.10)での作業を理解し始め、リストからファイルを自動的にダウンロードするタスクがありました。 「Wget -i」は確かに良いことですが、私はもっと欲しかった、つまり:
- ファイルからリンクのリストをダウンロードする
- 一度に複数のファイルをダウンロードする
- 失敗したダウンロードを別のリストに転送して、再試行します。
そのため、wgetが提供できるよりもわずかに高度なファイルのダウンロードツールが必要でした。 bashを使用して実装することにしました。 真実はbashスクリプトを書く経験の不足を妨げるかもしれませんが、ちょうど週末に来ました、そして、トピックに関する材料に費やされた時間は無駄ではありませんでした。
私の仕事の結果は次のスクリプトでした:
更新: ヒントのおかげで、zencdはwaitコマンドを使用してダウンロードが完了するのを待ちました。
更新2: shulcはエラーを指摘しました: #!/ Binbashを#!/ Bin / shに置き換えました。 darkkは、一時ファイルを作成するためのmktempの存在を提案しました。
#!/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
* This source code was highlighted with Source Code Highlighter .
スクリプトを機能させるには、スクリプトを実行可能にし、ダウンロードリンクのリストを含むファイル "./list/download.lst"を作成する必要があります。
打ち上げ:
sh downloader start [ ]
または、 Mezomishが正しく指摘したように、次のように:
./downloader start [ ]
'start'の後のパラメーターはオプションです(指定しない場合は、「1」が使用されます)。
つまり `sh downloader start 2`は同時に2つのファイルをダウンロードしながらスクリプトを実行します。
停止:
sh downloader stop
または
./downloader stop
スクリプトが「Ctrl + C」で終了しても、ダウンロードは終了しません。 バックグラウンドで動作するため、上記のコマンドを実行してダウンロードを停止する必要があります。
スクリプトを散らかさないことにしましたが、原則として、リストを操作するのは難しくありません(表示-表示、追加-ダウンロードの追加、ワイプ-クリア)。 そのため、最小限の機能を備えていますが、彼は労働者です。
なぜなら これが私の最初のbashスクリプトです。コメント/提案/推奨事項は大歓迎です。
さらに、スクリプトの原則について簡単に説明します。これにより、ニーズに合わせてスクリプトを変更する方が簡単になります。
定数は以下を示します。
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-失敗したダウンロードのリスト
タイムアウト-ダウンロードの再試行に失敗するまでの時間
作業の開始時に、スクリプトは以前に起動したコピーを停止し、active_list(もしあれば)からのダウンロードをdownload_listに転送して停止します。 これは、以前に起動したプロセスによってダウンロードが完了する前にスクリプトが再起動された場合に実行されます。 さらにループでは、必要な数のバックグラウンドダウンロードが作成されます。 このような各バックグラウンドスレッドは、download_thread()関数によって実装されます。 その仕事は、download_listとerror_listが空になるまでリストからファイルをダウンロードすることです。 したがって、これらのファイルをチェックするスクリプトの主要部分は、ダウンロードが終了したかどうかを調べます。 wgetを開始する前に、リンクはdownload_listファイルからactive_listファイルに転送されます。 wgetが完了すると、リンクはdone_list(戻りコードが「0」の場合)またはerror_list(戻りコードが「0」に等しくない場合)に転送されます。
すべてがダウンロードされた後(download_listとerror_listは空です)、スクリプトは作業を終了します。
以上です。 必要に応じて、スクリプトに少し精通している人なら誰でも必要な機能を追加できます。