2012-05-11 63 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条件在失败时显示的消息。