BASH嵌套循环中exit 1无法终止程序,求问题排查方案
问题排查:Bash脚本调用exit无法终止循环的原因及解决
问题场景
以下Bash代码在调用error_exit执行exit 1时,无法在首次触发错误时终止整个程序,反而会继续执行后续循环:
#!/bin/bash THIS_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" JINJANG_DIR="$(cd "$THIS_DIR/../.." && pwd)" DATAS_DIR="$THIS_DIR/datas" error_exit() { echo "" echo "ERROR - Following command opens the file that has raised an error." echo "" echo " > open \"$1\"" exit 1 } cd "$DATAS_DIR" find . -name 'datas.*' -type f | sort | while read -r datafile do localdir="$(dirname $datafile)" echo " * Testing ''$localdir''." filename=$(basename "$datafile") ext=${filename##*.} if [ "$ext" == "py" ] then unsafe="-u" else unsafe="" fi datas="$DATAS_DIR/$datafile" find . -name 'template.*' -type f | sort | while read -r template do filename=$(basename "$template") ext=${filename##*.} template="$DATAS_DIR/$template" outputfound="$DATAS_DIR/$localdir/output_found.$ext" cd "$JINJANG_DIR" python -m src $UNSAFE "$DATA" "$TEMPLATE" "$OUTPUTFOUND" || error_exit "$localdir" done cd "$DATAS_DIR" done
执行后输出示例:
ERROR - Following command opens the file that has raised an error. > open "./html/no-param-1" * Testing ''./html/no-param-2''. ERROR - Following command opens the file that has raised an error. > open "./html/no-param-2" * Testing ''./latex/no-param-1''. ERROR - Following command opens the file that has raised an error. > open "./latex/no-param-1" * Testing ''./latex/no-param-2''. ERROR - Following command opens the file that has raised an error.
核心原因
管道(|)会创建子进程,while循环在子shell中执行。当你在循环里调用exit 1时,只会终止当前的子shell进程,而外层的父shell进程(执行外层循环的进程)不受影响,会继续执行下一次循环迭代。
比如代码中这两段结构:
find . -name 'datas.*' -type f | sort | while read -r datafile # ... find . -name 'template.*' -type f | sort | while read -r template
管道右侧的while循环都在独立的子shell里运行,exit只能退出这个子shell,无法终止整个脚本。
解决方法
方法1:用进程替换替代管道
将管道结构改成进程替换,让while循环在当前shell中执行,这样exit就能终止整个脚本。修改后的循环结构如下:
外层循环修改:
while read -r datafile do # 原循环内代码不变 done < <(find . -name 'datas.*' -type f | sort)
内层循环修改:
while read -r template do # 原循环内代码不变 done < <(find . -name 'template.*' -type f | sort)
额外注意:变量大小写错误
代码中存在变量大小写不匹配的问题,会导致python命令接收空值,需要修正:
- 定义的小写
unsafe,调用时写成了$UNSAFE - 定义的
datas,调用时写成了$DATA - 定义的
template,调用时写成了$TEMPLATE - 定义的
outputfound,调用时写成了$OUTPUTFOUND
修正后的python命令:
python -m src $unsafe "$datas" "$template" "$outputfound" || error_exit "$localdir"
内容的提问来源于stack exchange,提问作者projetmbc
相关产品推荐
相关产品推荐

