[英]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.