子 shell 未传播错误,bash 4.4

子 shell 未传播错误,bash 4.4

我在 github 工作流程中有这个

      - run: bash --version
      - name: run postgres
        run: |
          set -e
          shopt -s inherit_errexit
          export ID=$(docker run \
            --publish 5432:5432 \
            --network skynet \
            --network-alias db.host \
            --env-file .github/env/postgres \
            --detach ${{ steps.postgres-tag.outputs.data }} )
        shell: bash -euET -o pipefail -O inherit_errexit {0}

这是它的运行输出

GNU bash, version 4.4.20(1)-release (x86_64-pc-linux-gnu)
  set -e
  shopt -s inherit_errexit
  export ID=$(docker run \
    --publish 5432:5432 \
    --network skynet \
    --network-alias db.host \
    --env-file .github/env/postgres \
    --detach  )
  shell: /bin/bash -euET -o pipefail -O inherit_errexit {0}
  env:
    AWS_DEFAULT_REGION: us-east-1
    AWS_REGION: us-east-1
    AWS_ACCESS_KEY_ID: ***
    AWS_SECRET_ACCESS_KEY: ***
"docker run" requires at least 1 argument.
See 'docker run --help'.

docker run [OPTIONS] IMAGE [COMMAND] [ARG...]

使用 bash 5 在 OS X 上进行最小复制

bash-5.0$ export ID=$(docker run)
"docker run" requires at least 1 argument.
See 'docker run --help'.

Usage:  docker run [OPTIONS] IMAGE [COMMAND] [ARG...]

Run a command in a new container
bash-5.0$ echo $?
0
bash-5.0$ docker run
"docker run" requires at least 1 argument.
See 'docker run --help'.

Usage:  docker run [OPTIONS] IMAGE [COMMAND] [ARG...]

Run a command in a new container
> echo $?                                                                            # services -> feature/RS2-1228-optimize-build $ ! RC=1
1

但是,shell 并未因错误而退出。我知道通常情况下,子 shell$()不会导致错误发生......但我认为该设置shopt -s inherit_errexit解决了这个问题。我的代码中遗漏了什么吗?

答案1

对比:

$ bash -e -c 'export a=$(false); echo >&2 "If you see this, the previous command succeeded"'
If you see this, the previous command succeeded
$ bash -e -c 'a=$(false); echo >&2 "If you see this, the previous command succeeded"' 

在您的尝试中,命令替换中的命令失败了,但是命令含有命令替换成功。如果命令替换是普通命令(包括对内置命令的调用),则命令替换的状态不会影响包含命令的状态export。命令替换的状态仅在赋值中才重要:赋值命令的状态是命令中最后一个命令替换的状态,如果没有命令替换,则为 0(假设赋值本身没有错误) ,例如尝试分配给只读变量)。

为了让您的脚本在出现第一个错误时停止,您需要启用inherit_errexit 将每个命令替换放在单独的分配中。它必须是一个简单的赋值:导出变量必须是一个单独的命令。

$ bash -e -O inherit_errexit -c 'export a=$(false; echo >&2 "If you see this, errexit is off inside command substitution"); echo >&2 "If you see this, the previous command succeeded"'
If you see this, the previous command succeeded
$ bash -e -O inherit_errexit -c 'a=$(false; echo >&2 "If you see this, errexit is off inside command substitution"); echo >&2 "If you see this, the previous command succeeded"'

相关内容