2017-10-19 148 views
1

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

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

我的印象是,它只是管這些命令猛砸,因此我期待默認猛砸行爲。但是,發生的情況是deploy.shssh錯誤而失敗;然後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錯誤)?任何見解將不勝感激。

+2

「SH deploy.sh」你調用'sh'這裏不是'bash'。它們在您的系統上可能不是同一件事。如果你想bash,調用bash。 – Kenster

+0

@Kenster'bash'用於在該腳本上調用'sh',並使用適當的退出代碼(第一個錯誤爲127,第二個錯誤爲255)將錯誤返回給'bash'。問題是'bash'沒有按照預期檢測到錯誤。 – Amposter

+0

來自文檔:#如果構建應該在另一個用戶(shell執行程序)的上下文中執行,則使用此命令 'cat generated-bash-script | su --shell/bin/bash --login user' – Amposter

回答

0

Gitlab腳本塊實際上是一個shell腳本數組。 https://docs.gitlab.com/ee/ci/yaml/#script 數組中每個元素的失敗都會失敗整個數組。 要解決把你的腳本塊在一些script.sh文件

script: 
    - ./script.sh 
0

我不認爲你的sh deploy.sh正在產生一個非零退出代碼。

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

這裏的,我已經叫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家當:

#!/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 

要解決你的問題,我相信你需要:使用./deploy.sh

  • 添加-e到腳本家當線(#!/bin/bash -e
  • 調用腳本的bash直接,而不是運行通過腳本sh

記住,如果deploy.sh確實失敗則cd ..運行(&&方式運行下一個命令,如果前面的一個成功),這意味着你是在錯誤的目錄運行deploy_service.sh。你會用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腳本,沒有慶典,因此所有的這一輪可能會更好:

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

'deploy.sh'返回一個非零的退出代碼(我在腳本中使用'set -e',並且多次檢查'$?'變量)。我知道'&&'警告以及爲什麼下一個聲明失敗,但這是不言而喻的。重點是兩行('cd MAIN && sh deploy.sh && cd ..'和'sh deploy_service。sh MATCHMAKING')正在返回非零退出代碼,但執行程序僅在第二個語句失敗時發生錯誤。 – Amposter