当第一个脚本中调用的脚本因错误代码退出时如何继续运行脚本?

当第一个脚本中调用的脚本因错误代码退出时如何继续运行脚本?

我正在尝试编写一个 bash 脚本,它将重复运行第二个脚本,直到它失败并捕获第二个脚本的标准输出和标准错误。我已经设法处理了在此过程中遇到的大多数问题,并最终得到了这个脚本(称为error_checker.sh):

#!/usr/bin/env bash

i=0

while [ $? -ne 1 ]
do
i=$[$i+1]
source script.sh &> log.txt
echo "This error occurred after $i run(s)." >> log.txt
done

我想重复重复的脚本称为script.sh,并具有以下代码:

#!/usr/bin/env bash

 n=$(( RANDOM % 100 ))

 if [[ n -eq 42 ]]; then
    echo "Something went wrong"
    >&2 echo "The error was using magic numbers"
    exit 1
 fi

 echo "Everything went according to plan"

error_checker.sh脚本可以将失败运行的 stdout 和 stderr 输出到指定文件 log.txt,但当脚本与该行的第二个脚本一起退出时

source script.sh &> log.txt

因此,我无法将附加错误消息附加到该文件。

我搜索了一段时间,发现这可能与运行第二个脚本时创建子shell有关,这可能会解决问题,但我只是无法./使用source.如果我改为source./当我输入时整个终端就会冻结./error_checker.sh

非常感谢任何伸出援助之手!

更新: 感谢您当前的答案!我认为现在我的主要问题是,当我更改source script.sh为在新的shell进程./script.sherror_checker.sh运行它时,整个终端就冻结了,这阻止了我使用./,这就是为什么我只能error_checker.sh在使用时成功运行source script.sh。有什么想法发生了什么吗?

更新二: 我更改source./并发现虽然整个终端似乎冻结了并且我必须通过按ctrl + c来结束该过程,但它仍然可以生成log.txt。然而,虽然 using 的版本source会生成一个 log.txt said Something went wrong. The error was using magic numbers,这表明 stdout 和 stderr 是通过 using 捕获的&>,但 using 的版本./生成了一个 log.txt said Everything went according to plan. The error occurred after X run(s)。知道发生了什么吗?

最终更新:我已经根据格伦对以下内容的回答编辑了我的代码,并且它运行良好。似乎 while 循环中的 echo 命令阻止了我实际评估 script.ph 的退出状态,从而创建了无限循环。

#!/usr/bin/env bash

i=0

while [ $? -ne 1 ]
do
((i++))
./script.sh >& log.txt
done

echo "This error occurred after $i run(s)." >> log.txt

答案1

因为您正在获取脚本,所以更改exit 1return 1

如果您还计划将 script.sh 作为“顶级”脚本运行,您可以这样做

if (( n == 42 )); then
    if [[ "$0" == "${BASH_SOURCE[0]}" ]]; then
        # I'm the "main" script
        exit 1
    else
        # I'm being sourced from some other script
        return 1
    fi
fi

如果你必须使用source(我对此表示怀疑,但我们必须查看代码)并且您无法更改该脚本,那么您必须在子 shell 中执行 source 命令。这意味着exit将从子 shell 退出,而不是从运行顶层程序的当前 shell 退出:

i=0
#     /--------------------------------\  parentheses create a subshell
while (source script.sh >> log.txt 2>&1)
do
    ((i++))
done
echo "This error occurred after $i run(s)." >> log.txt

这将创建一个日志文件,其中包含:

Everything went according to plan
...
Everything went according to plan
Something went wrong
The error was using magic numbers
This error occurred after 302 run(s).

关于您的代码的一些注释:

  • $[...]是未记录的语法,可能已弃用。用于$((...))算术扩展或((...))算术评估。
  • $?是退出状态以前的命令,对于 while 循环的第二次迭代,是echo.由于echo仅当无法写入标准输出(或指定的文件描述符)时才返回非零,因此您有一个无限循环因为您没有测试 script.sh 的退出状态!
    • 在出现错误情况后,您有大约百分之一的机会按下 Ctrl+C,因此 99% 的时间日志文件将包含“良好”消息”
  • &>不是惯用的:使用>& file或更明显的>file 2>&1.
  • 您很可能想要打印“错误发生在...之后”消息外部循环的

相关内容