当子命令抛出时终止makefile命令?

时间:2012-05-11 21:46:47

标签: shell 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. 在服务器上提取部署分支(make deploy-servers
  4. 您可以在Makefile中看到:

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

    问题是我不确定如何在make deploy-git失败时阻止make test执行,以及如何在测试失败或{{1}时阻止make deploy-servers执行失败。

    有没有明确的方法可以做到这一点,还是应该使用shell文件或用普通的编程语言编写这些工具?

4 个答案:

答案 0 :(得分:9)

shell命令 list 的退出状态是列表中最后一个命令的退出状态。只需将命令列表分成单独的简单命令即可。默认情况下,make在命令返回非零时停止。

让你得到你想要的东西
deploy:
    @make test
    make deploy-git
    make deploy-servers

如果你希望忽略简单命令的退出状态,你可以用短划线作为前缀:

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

您的make手册包含所有详细信息。

答案 1 :(得分:2)

其他人已经给出了基于将“配方”分成单个命令的答案。

在不可行的情况下,您可以在shell脚本中执行set -e,以便在命令失败时终止它:

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

这个set -e与shell脚本顶部附近的command2相同,以便在某些命令终止失败时使其保释。

假设我们对command3set -e的终止状态不感兴趣。假设这些指示失败,或者不能可靠地使用终止状态。然后,我们可以编写显式退出测试代替target: command1 ; \ command2 || exit 1 ; \ command3 ; \ true # exit 0 will do here also.

command3

由于{{1}}可以指示失败,并且我们不希望它失败,我们添加了一个成功的虚拟命令。

答案 2 :(得分:1)

make应该已经这样做了;它使用sh -e执行复杂命令,只要它不在POSIX兼容shell的循环中,如果命令退出非零,则中止执行,并在命令失败时中止整个Makefile除非你明确告诉它不要。如果您感到偏执,可以在命令中使用&&代替;

答案 3 :(得分: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条件,并在失败时显示一条消息。