首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >服务器上文件列表的高效并行下载与匹配模式解压缩

服务器上文件列表的高效并行下载与匹配模式解压缩
EN

Stack Overflow用户
提问于 2020-10-02 07:09:58
回答 1查看 265关注 0票数 1

每隔6小时,我就必须从web服务器下载bz2文件,解压缩它们并将它们合并到一个文件中。这需要尽可能高效和快速,因为我必须等待下载和解压缩阶段完成,然后再继续合并。

我编写了一些bash函数,这些函数以一些字符串作为输入来构造要作为匹配模式下载的文件的URL。通过这种方式,我可以直接将匹配模式传递给wget,而不必在本地构建服务器的内容列表,然后将其作为一个列表传递给-iwget。我的函数看起来像这样

代码语言:javascript
运行
复制
parallelized_extraction(){
    i=0
    until [ `ls -1 ${1}.bz2 2>/dev/null | wc -l ` -gt 0 -o $i -ge 30 ]; do
        ((i++))
        sleep 1
    done
    while [ `ls -1 ${1}.bz2 2>/dev/null | wc -l ` -gt 0 ]; do
        ls ${1}.bz2| parallel -j+0 bzip2 -d '{}' 
        sleep 1
    done
}
download_merge_2d_variable()
{
    filename="file_${year}${month}${day}${run}_*_${1}.grib2"
    wget -b -r -nH -np -nv -nd -A "${filename}.bz2" "url/${run}/${1,,}/"
    parallelized_extraction ${filename}
    # do the merging 
    rm ${filename}
} 

作为download_merge_2d_variable name_of_variable,我能够通过编写函数parallelized_extraction来加快代码速度,该函数负责在后台运行wget时对下载的文件进行解压缩。为此,我首先等待第一个.bz2文件出现,然后运行并行化提取,直到服务器上出现最后一个.bz2 (这是两个untilwhile循环所做的)。

我对这种方法很满意,不过我认为它还可以改进。以下是我的问题:

如果我的文件列表作为匹配模式给出,

  • 如何启动多个wget实例以执行并行下载?我必须编写多个匹配模式,其中包含“大块”数据,还是必须从服务器下载一个内容列表,拆分这个列表,然后将其作为输入给wget
  • parallelized_extraction,如果下载文件的速度很慢,可能会失败,因为在下一次迭代时,它不会找到任何要提取和退出循环的新bz2文件,尽管wget仍在后台运行。虽然这从未发生在我身上,但这是有可能的。为了解决这个问题,我尝试在第二个中添加一个条件,方法是让PID of wget在后台运行,以检查它是否还在,但是不知怎么的,它没有工作

代码语言:javascript
运行
复制
parallelized_extraction(){
    # ...................
    # same as before ....
    # ...................
    while [ `ls -1 ${1}.bz2 2>/dev/null | wc -l ` -gt 0 -a kill -0 ${2} >/dev/null 2>&1 ]; do
        ls ${1}.bz2| parallel -j+0 bzip2 -d '{}' 
        sleep 1
    done
}
download_merge_2d_variable()
{
    filename="ifile_${year}${month}${day}${run}_*_${1}.grib2"
    wget -r -nH -np -nv -nd -A "${filename}.bz2" "url/${run}/${1,,}/" &
    # get ID of process running in background
    PROC_ID=$!
    parallelized_extraction ${filename} ${PROC_ID}
    # do the merging
    rm ${filename}
}

知道为什么这不管用吗?对如何改进我的代码有什么建议吗?谢谢

更新,我在这里发布我的工作解决方案,基于接受的答案,以防有人感兴趣。

代码语言:javascript
运行
复制
# Extract a plain list of URLs by using --spider option and filtering
# only URLs from the output 
listurls() {
    filename="$1"
    url="$2"
    wget --spider -r -nH -np -nv -nd --reject "index.html" --cut-dirs=3 \
        -A $filename.bz2 $url 2>&1\
        | grep -Eo '(http|https)://(.*).bz2'
}
# Extract each file by redirecting the stdout of wget to bzip2
# note that I get the filename from the URL directly with
# basename and by removing the bz2 extension at the end 
get_and_extract_one() {
  url="$1"
  file=`basename $url | sed 's/\.bz2//g'`
  wget -q -O - "$url" | bzip2 -dc > "$file"
}
export -f get_and_extract_one
# Here the main calling function 
download_merge_2d_variable()
{
    filename="filename.grib2"
    url="url/where/the/file/is/"
    listurls $filename $url | parallel get_and_extract_one {}
    # merging and processing
}
export -f download_merge_2d_variable_icon_globe
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-10-02 09:54:40

你能列出要下载的网址吗?

代码语言:javascript
运行
复制
listurls() {
  # do something that lists the urls without downloading them
  # Possibly something like:
  # lynx -listonly -image_links -dump "$starturl"
  # or
  # wget --spider -r -nH -np -nv -nd -A "${filename}.bz2" "url/${run}/${1,,}/"
  # or
  # seq 100 | parallel echo ${url}${year}${month}${day}${run}_{}_${id}.grib2
}

get_and_extract_one() {
  url="$1"
  file="$2"
  wget -O - "$url" | bzip2 -dc > "$file"
}
export -f get_and_extract_one

# {=s:/:_:g; =} will generate a file name from the URL with / replaced by _
# You probably want something nicer.
# Possibly just {/.}
listurls | parallel get_and_extract_one {} '{=s:/:_:g; =}'

通过这种方式,您将在下载和并行操作时进行解压缩。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/64167453

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档