我有一个可执行脚本文件夹,其中一些具有Python shebangs,而另一些具有Bash shebangs等。我们有一项cron作业,每晚运行此脚本文件夹,希望是任何脚本中的任何错误都将退出该脚本。工作。
脚本以类似以下内容的方式运行: for FILE in $FILES; do ./$FILE; done
这些脚本由不同的人提供,尽管Python脚本总是在出现错误后退出,但有时开发人员会忘记添加set -e
其Bash脚本。
我可以使用for循环bash -e
,但是然后我需要检测当前脚本是否为Bash / Python / etc。
我可以set -e
从父脚本开始,然后再从source
脚本开始,但是我仍然需要知道每个脚本所使用的语言,并且我希望它们以子shell的形式运行,因此脚本贡献者不必担心搞砸父脚本。
grep
shebangs只是一个短暂的调整,但是了解Bash的灵活性,如果没有一种方法可以像导出变量一样“导出”影响所有子脚本的选项,我会感到惊讶。而且,在很多情况下,我忘记了“ set -e”,所以很高兴知道更多用于防呆的选项。
我看到了一些用于-e
命令替换所涉及的子shell继承的选项,但通常没有。
免责声明:永远不要这样做!这对所涉及的每个人都是巨大的伤害。你将在带有细致错误处理的脚本中以及在没有错误处理的脚本中引入故障。
无论如何,没有人喜欢在StackOverflow上被告知“不要这样做”,所以我的建议是识别脚本并使用shebang字符串加它们来调用它们-e
:
for f in ./*
do
# Determine if the script is a shell script
if [[ $(file -i "$f") == *text/x-shellscript* ]]
then
# Read the first line
read -r shebang < "$f"
# The script shouldn't have been identified as a shell script without
# a shebang, but check anyways
if [[ $shebang != "#!"* ]]
then
echo "No idea what $f is" >&2
continue
fi
# Strip off the #! and run it with -e and the file
shebang=${shebang#??}
$shebang -e "$f"
else
# It's some other kind of executable, just run it directly
"$f"
fi
done
这是一个具有正确错误处理的脚本,该脚本现在停止工作:
#!/bin/bash
my-service start
ret=$?
if [ $ret -eq 127 ]
then
# Use legacy invocation instead
start-my-service
ret=$?
fi
exit "$ret"
这是一个没有错误处理的脚本,现在可以停止工作:
#!/bin/sh
err=$(grep "ERROR" file.log)
if [ -z "$err" ]
then
echo "Run was successful"
exit 0
else
echo "Run failed: $err"
exit 1
fi
有用的观点/例子!在我的特定情况下,所有Bash脚本都遵循相同的模式:运行SQL查询并转储CSV的1-2个命令。因此,当我们忽略它时,它可能导致滚动通过失败的查询。但是,现在,我将重新考虑我的评论中的“所以,很高兴知道更多用于防呆的选项”。最好在此特定位置周围编写一些额外的代码,而不用太大的锤子。
如果我经常遇到人们添加shell脚本而没有错误处理的问题,那么我会添加某种初始检查,git钩子或CI启发式方法,如果发现这些错误,例如没有字符串
# errors handled
或字符串,它们会快速失败。set -e