也谈下载Cygwin的安装包

时间:2022-08-22 17:10:47
近几天想研究一下Mozilla,由于在Win32平台下面编译Mozilla需要用到Cygwin,于是就想着从网上下载一份完整的Cygwin安装包来安装(其实机器上已经有了Cygwin,但老想着用最新的,呵呵)。
可是用cygwin的那个setup.exe来在线下载,几次都下载失败,并且每次重新下载都得再次选择一下安装包,非常恼人(在此批评一下cygwin的这个setup.exe安装程序的开发者,怎么不考虑考虑不稳定的网络环境呢)。
如此试过几次后,便想着能否使用其他方法来把那些安装包都下载到本地来。于是把下载来的setup.ini文件进行简单的分析后,决定使用shell+gawk+wget来完成这一事情。
1、setup.ini的格式简述:
setup.ini的文件格式比较简单,是一个文本描述文件。
跟SHELL脚本一样,行首用“#”来表示注释。在这个只关注软件包的描述,所以对其他都忽略不予考虑。一个典型的软件包的描述如下:
@ ELFIO
sdesc: "ELF file reader and producer implemented as a C++ library"
ldesc: "ELFIO is a C++ library for reading and generating files in the
ELF (Executable and Linkable Format) binary format. This library is
unique and not based on any other product. It is also platform
independent. The library uses standard ANSI C++ constructions and runs
on a wide variety of architectures."
category: Devel System Libs Utils
requires: cygwin
version: 1.0.2-1
install: release/ELFIO/ELFIO-1.0.2-1.tar.bz2 159970 41b32111cbaaad78ea56dc62b757dd46
source: release/ELFIO/ELFIO-1.0.2-1-src.tar.bz2 280550 891cb420a38144e94447e99e3fddafa2
[prev]
version: 1.0.0-1
install: release/ELFIO/ELFIO-1.0.0-1.tar.bz2 151514 47cf28298685439ba5b5ac478e8eb44e
source: release/ELFIO/ELFIO-1.0.0-1-src.tar.bz2 274022 d29ab8fb0cad01250969983afca9891b

如上所示,@后面跟着的是软件包的名称;sdesc以及ldesc后面跟着的是软件包描述,category后面是这个软件包的分类,requires后面跟的是软件包的依赖关系,version后面的就是该软件包的版本。而接下来install后面跟着的就是软件包的文件路径了,这就是我们要关注的一行了(由于本人比较贪心,所以把source一行也拉进来了,两行的格式其实是一样的)。
install这一行的格式为:install: [软件包文件的相对路径] [文件大小] [文件的CHECKSUM]
这一行中,我们关注的也就是软件包文件的相对路径,只要我们把整个setup.ini文件中的install:为首的行中的那个文件路径拿出来,我们就离成功很近了。

2、提取setup.ini中的软件包路径
从setup.ini的方法比较多,一般来说支持正则表达式的工具都可以。我用gawk,命令行如下:
     gawk '/^install:|^source:/ {print $2}' setup.ini
这个命令行从setup.ini中把install:及source:开头的行中的包文件的相对路径都提取出来,输出到标准输出上。

3、组合出下载路径,使用wget下载
单单把软件包的相对路径提取出来是不够的,我们还得找一个Cygwin的镜像下载地址,通过镜像下载地址与软件包相对路径结合,形成绝对下载路径,才能使用wget来下载。例如使用http://ftp.gwdg.de/pub/linux/sources.redhat.com/cygwin/这个镜像下载地址,那么在每个软件包的相对路径前面加上这个镜像地址,就形成了可用的绝对地址供wget使用来下载了。另外,由于不同的软件包放在不同的目录层次中,为了保持下载来的文件目录结构跟服务器上的一致(wget -P, --directory-prefix=PREFIX),还需要指定下载文件的存放路径,所以,根据软件包的相对路径,使用dirname取出目录名来指定软件包的存放路径。

综上所述,形成一下脚本:

#! /bin/sh
# This script use to generate a download script for cygwin !
#
# Usage : ./cyg_scratch.sh setup.ini
DEFAULT_SETUP_INI=setup.ini
BASE_MIRROR_SITE=http://ftp.gwdg.de/pub/linux/sources.redhat.com/cygwin/

## If the setup.ini specified ?
if [ -z $1 ] ; then
    SETUP_INI=$DEFAULT_SETUP_INI
else
    SETUP_INI=$1
fi

## If the SETUP_INI exists ?
if [ ! -f $SETUP_INI ] ; then
    echo "$SETUP_INI does not exists !"
    exit 0
fi

## Scratch the package file names in the setup.ini
for fname in `gawk '/^install:|^source:/ {print $2}' $SETUP_INI`
do
    wget -P `dirname $fname` $BASE_MIRROR_SITE$fname
## You can change to any statements to download the file you want.
#  `dirname $fname` : the directory prefix
#  
done

## END