我的脚本在无限循环中从Web服务器下载文件。我的脚本调用wget来获取最新的文件(我之前没有得过的文件),然后需要处理每个新文件。问题是在运行wget之后,文件已经正确下载(基于单独窗口中的ls
),但有时我的脚本(特别是开始for curFile in
的行)看到它们,有时它没有,这让我觉得它有时会看到一个过时的缓存。
while [ 5 -lt 10 ]; do
timestamp=(date +%s)
wget -mbr -l0 --no-use-server-timestamps --user=username --password=password ftp://ftp.mysite.com/public_ftp/incoming/*.txt
for curFile in ftp.mysite.com/public_ftp/incoming/*.txt; do
curFileMtime=$(stat -c %W "$curFile")
if((curFileMtime > timestamp)); then
echo "$curFile"
cp "$curFile" CommLink/MDLFile
cd CommLink
SendMDLGetTab
cd ..
fi
done
sleep 120
done
通过循环的前几次这似乎工作正常,然后它变得零星(有时它看到新文件,有时它没有)。我已经做了很多谷歌搜索,并发现bash确实缓存了用于运行可执行文件的路径名(所以有时它会尝试执行不在那里的东西,如果最近删除了可执行文件)但我还没有找到任何东西在缓存非可执行文件名时,这会导致它看不到那些东西。有任何想法吗?如果是缓存问题,我怎么强迫它不要查看缓存?
答案 0 :(得分:0)
作为最直接的问题 - -b
的{{1}}参数告诉它在后台运行。因此,设置此标志后,第一个后续命令将在wget
仍在运行时发生。
除此之外:全局表达式的结果 - 例如wget
- 不会被shell缓存。 然而,这个glob只在每个循环中被评估一次:如果一个新的文本文件在该循环的开始时不存在,它将不会被拾取直到下一次迭代。
但是,问题中的代码用于排除ftp.mysite.com/public_ftp/incoming/*.txt
运行之前已存在的文件的机制很容易出现竞争条件。我会建议以下内容:
wget
一些更好的观点:
while IFS= read -r -d '' filename; do
[[ "$filename" -nt CommLink/MDLFile ]] || continue # retest in case MDLFile has changed
cp -- "$filename" CommLink/MDLFile && {
touch -r "$filename" CommLink/MDLFile # copy mtime to destination
(cd CommLink && exec SendMDLGetTab) # scope cd to subshell
}
done < <(find ftp.mysite.com/public_ftp/incoming/ \
-name '*.txt' \
-newer CommLink/MDLFile \
-print0)
之后但在wget
之前中断此脚本的先前调用,则确保处理更新方面更加强大。cp
可确保MDLFile的新副本保留原始文件的mtime。 (有人可以用touch -r
替换cp
以硬链接inode以获得相同的效果而没有任何竞争条件,并且只在磁盘上存储一次MDLFile,如果副作用可以接受的话。)ln -f
成功,则cd
的范围通过执行要在子shell中的单独目录中执行的操作。 (运行外部命令时,使用cd
会抵消此子shell的成本,其最终目的是触发)。exec
中所示)可确保正确处理所有可能的名称(包括带有文字换行符的名称)。