簡體   English   中英

Shell執行程序如何運行腳本?

[英]How does the Shell executor run scripts?

我們最近搬到了Gitlab,並開始使用管道。 我們已經設置了一個構建服務器(一個Ubuntu 16.04實例),並安裝了一個使用Shell執行程序的運行程序,但是我不確定它如何實際執行.gitlab-ci.yml文件中定義的腳本。 考慮以下代碼片段:

script:
    - sh authenticate.sh $DEPLOY_KEY
    - cd MAIN && sh deploy.sh && cd .. 
    - sh deploy_service.sh MATCHMAKING
    - sh deauthenticate.sh

我的印象是它將這些命令通過管道傳遞給Bash,因此我期待默認的Bash行為。 但是,由於ssh錯誤,導致deploy.sh失敗了; Bash然后繼續執行deploy_service.sh (這是預期的行為),但是由於無法can't open deploy_service.sh錯誤而失敗,並且作業在沒有Bash執行最后一條語句的情況下終止。

據我了解,如果您先執行set -e ,Bash只會在出錯時中止,因此我期望所有語句都將被執行。 我嘗試將set -e作為第一條語句添加,但這沒有任何區別-它不會在第一個ssh錯誤時終止。

我在下面添加了來自Gitlab的確切輸出:

沒有set -e

$ cd MAIN && sh deploy.sh && cd ..
deploy.sh: 72: deploy.sh: Bad substitution
Building JS bundles locally...

> better-npm-run build

running better-npm-run in x
Executing script: build

to be executed: node ./bin/build 
-> building js bundle...
-> minifying js bundle...
Uploading JS bundles to server temp folder...
COMMENCING RESTART. 5,4,3,2,1...
ssh: Could not resolve hostname $: Name or service not known
$ sh deploy_service.sh MATCHMAKING
sh: 0: Can't open deploy_service.sh
ERROR: Job failed: exit status 1

帶有set -e

$ set -e
$ cd MAIN && sh deploy.sh && cd ..
deploy.sh: 72: deploy.sh: Bad substitution
Building JS bundles locally...

> better-npm-run build

running better-npm-run in x
Executing script: build

to be executed: node ./bin/build 
-> building js bundle...
-> minifying js bundle...
Uploading JS bundles to server temp folder...
COMMENCING RESTART. 5,4,3,2,1...
ssh: Could not resolve hostname $: Name or service not known
$ sh deploy_service.sh MATCHMAKING
sh: 0: Can't open deploy_service.sh
ERROR: Job failed: exit status 1

為什么在沒有set -e情況下以錯誤終止(也為什么僅在第二個錯誤而不是ssh錯誤終止)? 任何見解將不勝感激。

Gitlab腳本塊實際上是外殼腳本的數組。 https://docs.gitlab.com/ee/ci/yaml/#script數組中每個元素的失敗將使整個數組失敗。 要解決此問題,請將您的腳本塊放在一些script.sh文件中

喜歡

script:
    - ./script.sh

我認為您的sh deploy.sh不會生成非零的退出代碼。

您正在使用set -e告訴當前進程退出(如果命令以非零返回碼退出),但是您正在創建一個子進程來運行Shell腳本。

這是我稱為deploy.sh的簡單示例腳本:

#!/bin/bash
echo "First."
echox "Error"
echo "Second"

如果我運行腳本,則可以看到錯誤的處理方式:

$ sh deploy.sh 
First.
deploy.sh: line 5: echox: command not found
Second

如果我先運行set -e ,您將看不到它的作用。

$ set -e
$ sh deploy.sh 
First.
deploy.sh: line 5: echox: command not found
Second

現在,我將-e添加到/bin/bash shebang中:

#!/bin/bash -e
echo "First."
echox "Error"
echo "Second"

當我使用sh運行腳本時, -e 仍然無效。

$ sh ./deploy.sh 
First.
./deploy.sh: line 3: echox: command not found
Second

使用bash直接運行此腳本時, -e生效。

$ ./deploy.sh 
First.
./deploy.sh: line 3: echox: command not found

要解決您的問題,我相信您需要:

  • -e添加到腳本shebang行( #!/bin/bash -e
  • 使用./deploy.sh直接從bash調用腳本,而不通過sh運行腳本。

請記住,如果deploy.sh 確實失敗,則cd ..不會運行( &&表示如果前一個命令成功,則運行下一個命令),這意味着您位於錯誤的目錄中,無法運行deploy_service.sh 使用cd MAIN; sh deploy.sh; cd ..會更好cd MAIN; sh deploy.sh; cd .. cd MAIN; sh deploy.sh; cd .. cd MAIN; sh deploy.sh; cd .. ,但是我建議用更簡單的替代方法替換對deploy.sh的調用:

script:
  - sh authenticate.sh $DEPLOY_KEY
  - (cd MAIN && sh deploy.sh) 
  - sh deploy_service.sh MATCHMAKING
  - sh deauthenticate.sh

這沒有什么大不相同,但是將導致cd MAIN && sh deploy.sh在子進程中運行(括號是這樣做的),這意味着整個腳本的當前目錄不受影響。 可以將其想象為“生成一個子流程,並在子流程的更改目錄中並運行該腳本”,並且當該子流程完成時,您將在開始的地方結束。

正如其他用戶所評論的那樣,您實際上是在sh而不是bash中運行腳本,因此全面來看可能會更好:

script:
  - ./authenticate.sh $DEPLOY_KEY
  - (cd MAIN && ./deploy.sh) 
  - ./deploy_service.sh MATCHMAKING
  - ./deauthenticate.sh

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM