我正在尝试编写一个 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.sh
中error_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 1
为return 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
.- 您很可能想要打印“错误发生在...之后”消息外部循环的