Skip to content

Instantly share code, notes, and snippets.

@epixoip
Last active August 2, 2022 21:54
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save epixoip/de857e35a73ad7b1dac0e3af602c05ba to your computer and use it in GitHub Desktop.
Save epixoip/de857e35a73ad7b1dac0e3af602c05ba to your computer and use it in GitHub Desktop.
#!/bin/sh
# Wed Aug 26 19:25:48 PDT 2009 by epixoip
# a "download manager" tailored for comcast subscribers, ensuring "powerboost"
# speeds for the entire duration of a download. if you are unfamiliar with
# comcast powerboost: http://www.dslreports.com/faq/14520
# (this is really just an excuse to write a "multi-threaded" shell script)
usage() {
cat >&2 <<EOF
powerboost - ensures comcast powerboost speeds for duration of download
Syntax: $0 [options] URL
Options:
-t Number of concurrent "threads"
-o Output file name
-h Display this message
EOF
exit 1
}
error()
{
echo "error: $1" >&2
usage
}
warn()
{
echo "warning: $1" >&2
}
spawn_thread()
{
r_start=$((r_end + 1))
if test "$r_start" -gt "$filesize"; then
return
fi
r_end=$((r_start + 20000000))
if test "$r_end" -gt "$filesize"; then
r_end="$filesize"
fi
chunk=$((chunk + 1))
echo "Retrieving chunk $chunk ($r_start - $r_end)"
curl -so $outfile.$chunk -r $r_start-$r_end $url &
pids="$pids $!"
}
waitall()
{
while true; do
for pid in "$@"; do
shift
if kill -0 "$pid" 2>/dev/null; then
set -- "$@" "$pid"
else
wait "$pid"
fi
done
if test "$#" -lt 1; then
break
fi
sleep 0.3
done
}
while getopts "ht:o:" opts; do
case $opts in
t) threads="$OPTARG";;
o) outfile="$OPTARG";;
h) usage;;
?) usage;;
esac
x="$OPTIND"
done
if test -n "$x" && test "$x" -gt 0; then
shift $((x - 1))
fi
if test -z "$1"; then
usage
fi
url="$1"
threads="${threads:-4}"
outfile="${outfile:-$(basename $url)}"
pids=""
filesize="$(curl -sI $url | sed -rn 's/Content-Length:\W+([0-9]+).*$/\1/ip')"
if test -z "$filesize"; then
error "$(basename $url) does not exist on server $(dirname $url)"
fi
maxthreads=$((filesize / 20000000))
if test "$threads" -gt "$maxthreads"; then
warn "more threads were requested than needed; reducing threads to $maxthreads"
threads=$maxthreads
fi
r_start=0
r_end=-1
chunk=0
start_time=$(date +%s)
set -o monitor
for t in $(seq 1 $threads); do
spawn_thread
sleep 0.3
done
while test "$r_end" -lt "$filesize"; do
trap spawn_thread CHLD
wait
done
waitall $pids
end_time=$(date +%s)
elapsed=$((end_time - start_time))
speed=$(echo "scale=2; $filesize / $elapsed" | bc)
echo "Retrieved $filesize bytes in $elapsed seconds [avg $speed bytes/sec]"
echo "Reassembling file..."
> $outfile
for i in $(seq 1 $chunk); do
cat $outfile.$i >>$outfile
rm -f $outfile.$i
done
echo 'Done!'
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment