2012-05-11 60 views
1

我有下面的Makefile:當子命令拋出時終止makefile命令?

#runs the working directory unit tests 
test: 
    @NODE_ENV=test; \ 
     mocha --ignore-leaks $(shell find ./test -name \*test.js); 

#deploys working directory 
deploy: 
    @make test; \ 
    make deploy-git; \ 
    make deploy-servers; 

#deploys working to git deployment branch 
deploy-git: 
    @status=$$(git status --porcelain); \ 
    if test "x$${status}" = x; then \ 
     git branch -f deployment; \ 
     git push origin deployment; \ 
     echo "Done deploying to git deployment branch."; \ 
    else \ 
     git status; \ 
     echo "Error: cannot deploy. Working directory is dirty."; \ 
    fi 

deploy-servers: 
# for each server 
#  @DEPLOY_SERVER_IP = "127.0.0.1"; \ 
#  make deploy-server 

#deploy-server: 
# connect to this server with ssh 
# check if app is already running 
# stop the app on the server if already running 
# set working directory to app folder 
# update deployment git branch 
# use git to move head to deployment branch 
# start app again 

注意deploy-serversdeploy-server是現在只是假人。這是deploy命令應該做的:

  1. 運行測試(make test),退出失敗
  2. 推現任部署分支(make deploy-git),退出失敗
  3. 服務器上
  4. 拉部署分支( make deploy-servers

可以在Makefile中看到如下:

deploy: 
    @make test; \ 
    make deploy-git; \ 
    make deploy-servers; 

問題是我不知道如何防止make deploy-gitmake test失敗時執行,以及如何防止make deploy-servers在測試失敗或make deploy-git失敗時執行。

有沒有一個明確的方法來做到這一點,或者我應該使用shell文件還是使用正常的編程語言編寫這些工具?

回答

8

shell命令的退出狀態列表是列表中最後一個命令的退出狀態。只需將您的命令列表分成單獨的簡單命令。默認情況下,當命令返回非零時,make停止。所以,你得到你想要

deploy: 
    @make test 
    make deploy-git 
    make deploy-servers 

你應該永遠忽略一個簡單的命令的退出狀態,您可以用破折號前綴是:

target: 
    cmd1 
    -cmd2 # It is okay if this fails 
    cmd3 

make手冊中有所有細節。

+0

+1,但是請注意OP,您可能希望(至少)執行'make test $(MAKEFLAGS)'將任何其他命令行標誌傳播到子版本。 –

+0

@威廉 - 這取決於,因爲我的make(GNU Make 3.81)似乎自動執行此操作。我剛剛測試過,因爲你的評論讓我感到緊張。 – sage

1

make應該已經這樣做了;它執行的複雜命令爲sh -e(只要它不在POSIX兼容shell的循環中)將在命令退出非零時中止執行,並在命令失敗時中止整個Makefile,除非您明確告訴它不要。如果你覺得偏執,你可以在你的命令中使用&&來代替;

2

其他人已經給出了基於將「配方」分成單個命令的答案。

在的情況下,是不是可行的,你可以做的是在shell腳本set -e做,如果一個命令失敗,終止:

target: 
     set -e ; \ 
      command1 ; \ 
      command2 ; command3 ; \ 
      ... commandN 

這是相同的set -e你乾脆把頂部附近當某些命令終止失敗時,可以使用shell腳本來保護它。

假設我們對command2command3的終止狀態不感興趣。假如這些指示失敗或者不能可靠地使用終止狀態是可以的。然後,而不是set -e我們可以編寫一個明確的退出測試:

target: 
     command1 ; \ 
     command2 || exit 1 ; \ 
     command3 ; \ 
     true # exit 0 will do here also. 

由於command3可以指示故障,我們不希望它失敗我們的建設,我們添加了一個成功的虛擬指令。

+0

非常好的你用這些有用的信息擴展給定的答案。我希望我能接受大量的答案.. – Tom

0

我在潛在斷點解決就此問題通過代理到一個新的make命令:

.PHONY cmd_name cmd_name_contd 

cmd_name: 
    if [ "`pwd`" = "/this/dir" ]; then make cmd_name_contd; fi 

cmd_name_contd: 
    @echo "The directory was good, continuing" 

這樣,如果該目錄是錯誤的,它只是退出默默,你也可以用添加一個else條件在失敗時顯示的消息。