結論:需要關注是否有bash -c,開發的腳本是否有#!/bin/bash
在測試環境準備中,docker容器初始化的時候,比如通過jenkins或python腳本(paramiko)部署的時候,部署腳本經常需要使用docker exec來執行語句,啓停容器內的服務。
由於開發的start.sh腳本使用了相對路徑,必須進入路徑再執行./start.sh,所以我使用分號隔開先後兩條語句執行。例如
docker exec nebula_service0 bash -c "cd /usr/local/sandai/scheduler/sbin; ./start.sh restart; "
這裏首先有一個要點,就是 bash後面要帶-c ,否則不支持多條命令。所有的命令需要以字符串形式傳入,故使用雙引號,如果內部的命令需要引號,則需要轉義。
第二個要點,在paramiko裏,如果不帶restart; 最後的分號,就可能看不到最後一個命令執行成功時的輸出(有點奇葩)。
結果執行了以後,有的服務能成功。但有的服務會出現沒報錯,就是服務沒重啓,執行了命令好像沒效果一樣。這就尷尬了,真的很影響問題定位~
詭異的是,直接用
docker exec -it nebula_service0 /bin/bash
cd /usr/local/sandai/scheduler/sbin; ./start.sh restart
進到容器裏面,然後再執行命令,就表現好好的,沒有任何問題
後來經過一番折騰發現,研發的start.sh不是所有的都規範
能夠成功的腳本,第一行有
#!/bin/bash
[commands ..]
而不能成功執行的腳本,第一行沒有解釋器路徑,而是直接開始寫命令
[commands ..]
所以辦法就有兩個:
第一個辦法,讓開發規範腳本,腳本前面都加上#!/bin/bash
第二個辦法,使用sh start.sh或bash start.sh代替./start.sh,經測試無需解釋器路徑
docker exec nebula_service0 bash -c "cd /usr/local/sandai/scheduler/sbin; sh start.sh restart; "