![子 shell 未传播错误,bash 4.4](https://linux22.com/image/181256/%E5%AD%90%20shell%20%E6%9C%AA%E4%BC%A0%E6%92%AD%E9%94%99%E8%AF%AF%EF%BC%8Cbash%204.4.png)
我在 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"'