[英]How do I rerun a bash script skipping over lines which have previously run sucesfully?
我有一个bash脚本,用作分析管道的包装器。 如果脚本出错,我希望能够通过简单地重新运行原始命令来从发生错误的位置运行脚本。 我设置了两个陷阱。 一个将删除脚本中非零退出时生成的最后一个文件,另一个将删除退出信号= 0时的所有临时文件,并在运行结束时实质上清除文件系统。 我在bash环境中启用了noclobber,它允许我的脚本跳过已经写入文件的脚本行,但这仅在我未设置非零出口陷阱的情况下才这样做。 一旦设置了此陷阱,它将在第一行退出,在该行中noclobber标识不会覆盖的文件。 我有办法跳过以前成功运行的代码行,而不必从头开始重新运行代码吗? 我知道我可以在每一行使用条件语句,但是我认为这样做可能更简洁。
set -o noclobber
# Function to clean up temporary folders when script exits at the end
rmfile() { rm -r $1 }
# Function to remove the file being currently generated
# Function executed if script errors out
rmlast() {
if [ ! -z "$CURRENTFILE" ]
then
rm -r $1
exit 1
fi }
# Trap to remove the currently generated file
trap 'rmlast "$CURRENTFILE"' ERR SIGINT
#Make temporary directory if it has not been created in a previous run
TEMPDIR=$(find . -name "tmp*")
if [ -z "$TEMPDIR" ]
then
TEMPDIR=$(mktemp -d /test/tmpXXX)
fi
# Set CURRENTFILE variable
CURRENTFILE="${TEMPDIR}/Variants.vcf"
# Set CURRENTFILE variable
complexanalysis_tool input_file > $CURRENTFILE
# Set CURRENTFILE variable
CURRENTFILE="${TEMPDIR}/Filtered.vcf"
complexanalysis_tool2 input_file2 > $CURRENTFILE
CURRENTFILE="${TEMPDIR}/Filtered_2.vcf"
complexanalysis_tool3 input_file3 > $CURRENTFILE
# Move files to final destination folder
mv -nv $TEMPDIR/*.vcf /test/newdest/
# Trap to remove temporary folders when script finishes running
trap 'rmfile "$TEMPDIR"' 0
更新:
已为我提供建议使用make实用工具的答案。 我想利用其内置实用程序来检查是否已满足依赖关系。 在我看来,VK Kashyap建议的makefile似乎并不会跳过先前完成的任务的执行。 因此,例如,我运行上述脚本,并在使用ctrl c运行filtered.vcf时中断了该脚本。 当我再次重新运行脚本时,它将再次从头开始运行,即再次从varaints.vcf开始。 我是否缺少某些东西以使Makefile将源显示为已满?
更新答案:
好的,这是一个菜鸟错误,但是由于我不熟悉生成makefile,因此我将发布有关错误的解释。 我的makefile没有从出口点重新运行的原因是,我给目标命名的名称与要生成的输出文件的名称不同。 因此,如果您将目标命名为VK Kashyap,那么答案很正确。
variants.vcf
filtered.vcf
filtered2.vcf
与生成的输出文件相同,脚本将跳过先前完成的任务。
make Utility可能是您要实现的目标的答案。
它具有内置的dependecy检查(您尝试通过tmp文件实现的内容)
#run all target when all of the files are available
all: variants.vcf filtered.vcf filtered2.vcf
mv -nv $(TEMPDIR)/*.vcf /test/newdest/
variants.vcf:
complexanalysis_tool input_file > variants.vcf
filtered.vcf:
complexanalysis_tool2 input_file2 > filtered.vcf
filtered2.vcf:
complexanalysis_tool3 input_file3 > filtered2.vcf
您可以使用bash脚本以如下方式调用此make文件:
#/bin/bash
export TEMPDIR=xyz
make -C $TEMPDIR all
make实用程序将检查自身是否已完成任务,并跳过已完成任务的执行。 它会在您遇到错误完成任务的地方继续。
您可以在Internet上找到有关Makefile确切语法的更多详细信息。
没有内置的方法可以做到这一点。
但是, 可以通过跟踪最后成功的行并构建自己的goto
语句来酿造类似的东西,如此处所述,以及bash中是否有“ goto”语句? (只需将“标签”替换为实际的行号)。
但是,问题是这是否真的是一个聪明的主意。
更好的方法是仅运行所需的命令,而不运行尚未执行的命令。 这可以通过bash脚本中的显式条件来完成:
produce_if_missing() {
# check if first argument is existing
# if not run the rest of the arguments and pipe it into the first one
local curfile=$1
shift
if [ ! -e "${curfile}" ]; then
$@ > "${curfile}"
fi
}
produce_if_missing Variants.vcf complexanalysis_tool input_file
produce_if_missing Filtered.vcf complexanalysis_tool2 input_file2
或使用专门用于此类事情的工具(请参阅VK Kahyap的使用make
的答案,尽管我更喜欢在make-rules中使用变量以最大程度地减少错别字):
Variants.vcf: input_file
complexanalysis_tool $^ > $@
Filtered.vcf: input_file
complexanalysis_tool2 $^ > $@
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.