首页 > 解决方案 > bash source 一个结尾有退出命令的文件

问题描述

cat >file1.sh <<'EOF_FILE1'
  echo 'before source'
  source 'file2.sh'
  echo 'after source'
  func1
EOF_FILE1

cat >file2.sh <<'EOF_FILE2'
  echo 'test script'
  func1() {
    echo 'func1 starts'
    exit
  }
  exit
EOF_FILE2

bash file1.sh

预期输出为:

before source
test script
after source
func1 starts

实际输出为:

before source
test script

由于该exit命令,缺少“后源”。有没有办法解决这个问题,因为我无法exit从代码中删除?

标签: bashshell

解决方案


虽然最好的方法是编写旨在获取而不是在考虑该用例的情况下执行的脚本,但如果您出于某种原因不能这样做,您可以考虑aliasexit命令return之前source执行,如下所示:

shopt -s expand_aliases  # enable alias expansion (off by default in noninteractive shells)
alias exit=return        # ...and alias 'exit' to 'return'

source 'file2.sh'        # source in your file which incorrectly uses 'exit' at top-level
unalias exit             # disable the alias...
echo 'after source'
func1

如果您希望函数中的exitin 在调用该函数时仍然生效,则可以使事情变得更复杂一些:

maybe_exit() {
  local last_retval=$?                 # preserve exit's behavior of defaulting to $?
  [[ $do_not_really_exit ]] && return  # abort if flag is set
  (( $# )) && exit "$@"                # if arguments are given, pass them through
  exit "$last_retval"                  # otherwise, use the $? we captured above
}

shopt -s expand_aliases  # enable alias expansion (off by default in noninteractive shells)
alias exit=maybe_exit    # ...and alias 'exit' to 'maybe_exit'

do_not_really_exit=1     # set a flag telling maybe_exit not to really exit
source 'file2.sh'        # source in your file which incorrectly uses 'exit' at top-level
unset do_not_really_exit # clear that flag...
unalias exit             # disable the alias...
echo 'after source'
func1

推荐阅读