Bash

子殼不傳播錯誤,bash 4.4

  • October 6, 2020

我在 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解決了這個問題。我的程式碼中是否缺少某些內容?

對比:

$ 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"'

引用自:https://unix.stackexchange.com/questions/613019