Warm tip: This article is reproduced from serverfault.com, please click

linux-如果脚本为bash,则具有任意可执行文件继承errexit

(linux - have arbitrary executable inherit errexit, if script is bash)

发布于 2020-11-27 22:54:33

我有一个可执行脚本文件夹,其中一些具有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的形式运行,因此脚本贡献者不必担心搞砸父脚本。

grepshebangs只是一个短暂的调整,但是了解Bash的灵活性,如果没有一种方法可以像导出变量一样“导出”影响所有子脚本的选项,我会感到惊讶。而且,在很多情况下,我忘记了“ set -e”,所以很高兴知道更多用于防呆的选项。

我看到了一些用于-e命令替换所涉及的子shell继承的选项,但通常没有。

Questioner
dcc310
Viewed
1
that other guy 2020-11-28 08:06:23

免责声明:永远不要这样做!这对所涉及的每个人都是巨大的伤害。你将在带有细致错误处理的脚本中以及在没有错误处理的脚本中引入故障。

无论如何,没有人喜欢在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