你是否下载过一个非常巨大的文件,以至于你不得不将你的web浏览器几个小时甚至几天的打开?假如你有一个40个文件链接在一个web页上,你又需要它——你愿意不厌期烦的一个一个的点开它们吗?再假如浏览器在工作完成前发生了故障呢?Linux 早已拥有一系列用手动的工具来对付这种情况,它完全不用使用浏览器。支持断点续传、镜像下载、计划下载等windows下载工具的所有功能:)。酷不酷?下面,就跟我来吧!
在这种方式中存在的交互性
Web浏览器是使Web具有交互性——点击然后希望结果能在几秒钟内出来。但是,即使是在很快的线路里,下载许多文件仍然需要相当长的时间。例如ISO镜像文件就被普遍用在GNU/Linux的CD-ROM发行版中。一些web浏览器,尤其是只有简单编码的浏览器,对于长时间的工作并不能很好的运作,它可能会漏掉记忆存储或者会不合时宜的发生故障。尽管将一些浏览器和文件治理器已经结合起来了,但仍然不能支持多个文件的下载及捆绑传送(就是将几个文件捆绑在一起以便于传送)。所以你不得不保持登录状态直到整个文件下载完毕。最后你还得去你的办公室点击链接开始下载,而这样你会因为共享了同事的带宽而使他很不兴奋。
下载大型文件这个任务更适合另外一套工具来完成。这篇文章将告诉你怎么样把各种GNU/Linux 的应用程序结合起来,也就是lynx,wget,at,crontab等等来解决各种文件传送中的问题。我们将用到一些简单的脚本,所以有一点bash shell方面的知识对下面的学习会有帮助。
wget 应用程序
其主要分类包括wget 下载工具。
bash$ wget http://place.your.url/here
它还可以处理FTP、时间戳及递归的镜像整个web网站的目录树——假如你一不小心,整个web网站及所有别的站点就会链接到:
bash$ wget -m http://target.web.site/subDirectory
由于潜在的高负载,这个工具被放在服务器中,这个工具在下载过程中会自动根据“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多重试几次:
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
(注重:以上提供的技巧是被使用在满足内容许可机制的情况下使用。否则,将是违法的行为。)
指定下载的时间
假如你想在你办公室的与你的同事共用一根线路的电脑里下载大型文件,想象一下他们因为原本像畅快的小溪一样的线路忽然便得像爬虫一样慢而发怒的样子,你就会考虑将你的文件传送时候改在非高峰使用期了。你不必在等到每个人都离开后还呆在办公室里,也不必在饭后在家中远程登录。你只要在工作日程安排程序中做以下设置:
bash$ at 2300
warning: commands will be executed using /bin/sh
at> wget http://place.your.url/here
at> press Ctrl-D
我们设定在晚上23点的时候开始下载。我们要做的就是确信atd这个日程安排守护进程还在工作^&^。
下载要花好几天?
当你下载的一个或多个文件包含许多数据,而机器的带宽使得它的传送速度可以和信鸽相比的时候,你会发现当你在第二天早上到了公司,预定的下载还没有完成。你终止这个工作而且提交另外一个at工作,这次你使用了“wget -c”,只要下载没有完成,就天天都重复这个工作。这时候最好是使用“crontab.txt”自动执行它。建立一个名为 “crontab.txt”的纯文本文件,内容如下:
0 23 * * 1-5 wget -c -N http://place.your.url/here
0 6 * * 1-5 killall wget
这将是crontab文件,它指定周期性的执行什么工作。前面的五栏指定什么时候开始执行命令,每行的后面部分指定执行什么。前两栏指定时间——晚上23点整开始wget,早晨6点整就killall wget。位于第三第四的* 表示每个月的每一天都可以进行这样的工作。第五栏表示每个星期的哪些天安排了工作时间进程——“1-5”表示星期一到星期五。
每个工作日的晚上23点下载工作开始,早6点整下载工作停止。为使这个crontab工作时间表发挥作用,你需要键入以下命令:
bash$ crontab crontab.txt
“-N”参数将检查目标文件的时间邮戳,当它找到了匹配的时间戳,它就会终止下载,因为它表明整个这个文件已经被传送。“crontab -r”可以取消这个日程时间安排。我使用这种方法来通过拨号上网下载了许多ISO文件。
下载动态网页
一些动态的网页需根据需要产生,经常频繁的变动。既然目标文件从技术角度上讲不能算是一个文件,那么也就无所谓什么文件长度,继续下载也就变得毫无意义——“-c” 选项难以工作。例如:在Linux Weekend News中生成PHP页:
bash$ wget http://lwn.net/bigpage.php3
假如你中断了下载,然后又想继续,它将从头开始下载。我办公室的Net线路有时候慢得让人受不了,所以我写了一个简单的脚本用来决定什么时候中断传递动态的Html页:
#!/bin/bash
#create it if absent
toUCh bigpage.php3
#check if we got the whole thing
while ! grep -qi '</html>' bigpage.php3
do
rm -f bigpage.php3
#download LWN in one big page
wget http://lwn.net/bigpage.php3
done
这个bash脚本在找到“</html>”之前会一直下载文档,“</html>”标志着文件的结束。
SSL和Cookies
用“https://”开头可以通过SSL(Secure Sockets Layer,安全套接口层)访问远程文件。你会发现另外一个名为curl的下载软件, 在有些情况下使用它会相当便利。
一些web站点在提供你想要的服务内容之前会给浏览器强行灌输许多cookie。加上一个“Cookie:”头和正确的信息,这个信息可以从你的浏览器的cookie文件中获得。
bash$ cookie=$( grep nytimes ~/.lynx_cookies awk '{printf("%s=%s;",$6,$7)}' )
为了从http://www.nytimes.com/下载资料,上面的脚本可以构建你所需要的cookies。当然前提是你已经为使用这个浏览器的站点注册了。w3m使用了一个稍微有点不同的cookie文件格式:
bash$ cookie=$( grep nytimes ~/.w3m/cookie awk '{printf("%s=%s;",$2,$3)}' )
可以用下面这个bash执行下载:
bash$ wget --header="Cookie: $cookie" http://www.nytimes.com/reuters/technology/tech-tech-supercomput.html
也可以使用curl工具:
bash$ curl -v -b $cookie -o supercomp.html http://www.nytimes.com/reuters/technology/tech-tech-supercomput.html
URLs列表
目前为止,我们下载的文件都是单个的文件或者镜像整个站点,也是存储整个网站目录。但有时候我们想下载几个文件,当然,它的URL已经在web页中给出,而又不想将整个站点都存储下来。一个简单的例子就是,我们只想将站点中排列好了的100个音乐文件的前面20个下载回来。在这里“--accept”和“--reject”因为不是在文件扩展部分都不可以使用。所以,我们使用“lynx -dump”。
bash$ lynx -dump ftp://ftp.ssc.com/pub/lg/ grep 'gz$' tail -10 awk '{print $2}' > urllist.txt
使用很多GNU文本处理工具都可以把来自lynx的输出过滤一下。在上面这个例子里,我们将在“gz”中的URL的结尾析取出来并将最后10个文件存储下来。一个很小的bash脚本命令可以自动下载文件中列出的所有URLs:
bash$ for x in $(cat urllist.txt)
> do
> wget $x
> done
我们已经成功的将Linux Gazette的最近十期下载下来。
如何处理带宽问题
假如你对带宽不是很熟,而且你的文件下载因为你在web服务器的终端而非常慢的时候,下面这个技巧可以帮助你畅通无阻的传送文件。它需要使用到curl和几个镜像web站点,在那里有目标文件的几个相同的备份。例如,假设你想从下面三个站点下载Mandrake 8.0的ISO :
url1=http://ftp.eecs.umich.edu/pub/linux/mandrake/iso/Mandrake80-inst.iso
url2=http://ftp.rpmfind.net/linux/Mandrake/iso/Mandrake80-inst.iso
url3=http://ftp.wayne.edu/linux/mandrake/iso/Mandrake80-inst.iso
文件长度是677281792,使用curl的“--range” 选项同时分三部分下载。
bash$ curl -r 0-199999999 -o mdk-iso.part1 $url1 &
bash$ curl -r 200000000-399999999 -o mdk-iso.part2 $url2 &
bash$ curl -r 400000000- -o mdk-iso.part3 $url3 &
分成了三个下载过程,不同的服务器传送ISO镜像文件的不同部分。“-r”选项指定从目标文件中选取的字节范围。完成后,再将三个部分合在一起——cat mdk-iso.part? > mdk-80.iso。(在烧录到CD-R之前建议你检查md5散列)curl使用“--verbose”选项并在它自己的窗口中运行的话可以追踪每个传送过程。
总结
不要害怕使用非交互性方式来下载远程文件。web设计者设法强迫我们在他们的站点上交互式的冲浪,但仍然有免费的工具帮助我们自动进行这个工作,省下我们不少麻烦哦。