Linux 如何跳过以前成功运行的行重新运行bash脚本?
我有一个bash脚本,它充当分析管道的包装器。如果脚本出错,我希望能够通过简单地重新运行原始命令,从错误发生的位置运行脚本。我设置了两个不同的陷阱;一个将从我的脚本中删除非零退出时生成的最后一个文件,另一个将在退出信号=0时删除所有临时文件,并在运行结束时基本上清理文件系统。我在bash环境中打开了noclobber,它允许我的脚本跳过脚本中已写入文件的行,但只有在我没有设置非零退出陷阱的情况下才会这样做。一旦我设置了这个陷阱,它就会在第一行退出,在那里noclobber标识了一个它不会覆盖的文件。有没有一种方法可以让我跳过以前成功运行过的代码行,而不必从一开始就重新运行代码?我知道我可以对每一行使用条件语句,但我认为可能有更简洁的方法Linux 如何跳过以前成功运行的行重新运行bash脚本?,linux,bash,Linux,Bash,我有一个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运行filter.vcf时中断了脚本。当我再次运行脚本时,它会从头开始再次运行,即在varaints.vcf重新启动。为了让makefile将源代码显示为已满,我是否遗漏了什么
更新的答复:
好的,这是一个新手的错误,但由于我不熟悉生成makefile,我将发布我的错误解释。我的makefile没有从退出点重新运行的原因是,我为目标命名了与正在生成的输出文件不同的名称。因此,如果你说出目标,VK Kashyap的回答非常正确
variants.vcf
filtered.vcf
filtered2.vcf
与生成的输出文件相同,脚本将跳过以前完成的任务。make实用程序可能是您想要实现的目标的答案 它具有内置的依赖性,用于检查您试图使用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确切语法的更多详细信息。make utility可能是您想要实现的目标的答案 它具有内置的依赖性,用于检查您试图使用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脚本中的显式条件实现:
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规则中的变量来最小化打字错误:
Variants.vcf: input_file
complexanalysis_tool $^ > $@
Filtered.vcf: input_file
complexanalysis_tool2 $^ > $@
没有内置的方法可以做到这一点 但是,您可以通过跟踪最后一个成功的行并构建自己的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规则中的变量来最小化打字错误:
Variants.vcf: input_file
complexanalysis_tool $^ > $@
Filtered.vcf: input_file
complexanalysis_tool2 $^ > $@
谢谢VK Kashyap和Ulmäute。我在两个答案上都做了标记,因为这两个答案都给了我可以使用的选择。我并没有真正考虑这个实用工具,谢谢你把这个介绍给我。如果你喜欢,那就酷吧。然而,接受答案的正确方式是接受它,选择最能帮助你的答案,谢谢你,VK Kashyap和Ulmäute。我在两个答案上都做了标记,因为这两个答案都给了我可以使用的选择。我并没有真正考虑这个实用工具,谢谢你把这个介绍给我。如果你喜欢,那就酷吧。然而,正确的接受方式 答案是接受它,选择对你帮助最大的一个