【问题标题】:Gnu Make different exit status from script and shellGnu 从脚本和 shell 中创建不同的退出状态
【发布时间】:2013-01-16 01:42:53
【问题描述】:

基本代码:

def make_check(local, master, old_revno, old_revid, future_revno, future_revid,
    tree_delta, future_tree):
    try:
        check_call('make check', shell=True)
    except CalledProcessError as e:
        raise BzrError(e)

结果: bzr:错误:命令“make check”返回非零退出状态 2

我有一个包含“检查”目标的 Makefile,其中运行一些脚本以检查所有源代码是否具有有效的语法。

如果我从控制台运行make check,它的状态为0。

如果我从 Bazaar 中的预提交挂钩运行 make check,它的状态为 2。

我进行了一些深入的调查,包括检查环境变量(基本相同)并针对这两种方法运行 strace

在这两种情况下,脚本的输出是相同的,但在 precommit 挂钩的情况下,退出状态为 2,我无法辨别,因为它调用的最后一个进程的退出状态为 0,并且没有其他外部系统调用。有没有我忽略的东西,或者make 中可能存在内部错误?

控制台

16436 execve("/usr/bin/make", ["make", "check"], [/* 22 vars */]) = 0
#Big snip
16947 execve("/bin/sh", ["/bin/sh", "-c", "find archive/rpm/6 -name '*.rpm' -printf '%f\\n' | rev | cut -d- -f3- | rev | sort | uniq -c | grep -v '^ *1 ' &&  \\\n{ echo \"ERROR: Found duplicate RPMs in archive.\"; exit 1; } || true"], [/* 35 vars */]) = 0
#Big snip
16948 exit_group(0)                     = ?
16947 <... wait4 resumed> [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0, NULL) = 16949
16947 --- SIGCHLD (Child exited) @ 0 (0) ---
16947 rt_sigreturn(0x11)                = 16949
16947 wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0, NULL) = 16948
16947 wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0, NULL) = 16950
16947 wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0, NULL) = 16951
16947 wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0, NULL) = 16952
16947 wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0, NULL) = 16953
16947 wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 1}], 0, NULL) = 16954
16947 exit_group(0)                     = ?
16436 <... wait4 resumed> [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0, NULL) = 16947
16436 --- SIGCHLD (Child exited) @ 0 (0) ---
16436 rt_sigreturn(0xffffffff)          = 16947
16436 rt_sigprocmask(SIG_BLOCK, [HUP INT QUIT TERM XCPU XFSZ], NULL, 8) = 0
16436 rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
16436 chdir("/code/n/branches/jeff")    = 0
16436 close(1)                          = 0
16436 munmap(0x7f7ed780e000, 4096)      = 0
16436 exit_group(0)

脚本

14001 execve("/usr/bin/make", ["make", "check"], [/* 21 vars */]) = 0
#Big snip
14525 execve("/bin/sh", ["/bin/sh", "-c", "find archive/rpm/6 -name '*.rpm' -printf '%f\\n' | rev | cut -d- -f3- | rev | sort | uniq -c | grep -v '^ *1 ' &&  \\\n{ echo \"ERROR: Found duplicate RPMs in archive.\"; exit 1; } || true"], [/* 34 vars */]) = 0
#Big snip
14526 exit_group(0)                     = ?
14525 <... wait4 resumed> [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0, NULL) = 14527
14525 --- SIGCHLD (Child exited) @ 0 (0) ---
14525 rt_sigreturn(0x11)                = 14527
14525 wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0, NULL) = 14526
14525 wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0, NULL) = 14528
14525 wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0, NULL) = 14529
14525 wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0, NULL) = 14530
14525 wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0, NULL) = 14531
14525 wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 1}], 0, NULL) = 14532
14525 exit_group(0)                     = ?
14001 <... wait4 resumed> [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0, NULL) = 14525
14001 --- SIGCHLD (Child exited) @ 0 (0) ---
14001 rt_sigreturn(0xffffffff)          = 14525
14001 rt_sigprocmask(SIG_BLOCK, [HUP INT QUIT TERM XCPU], NULL, 8) = 0
14001 rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
14001 chdir("/code/n/branches/jeff")    = 0
14001 close(1)                          = 0
14001 munmap(0x7f064aa7b000, 4096)      = 0
14001 exit_group(2)                     = ?

更新

我将以下目标附加到我的 Makefile:

.PHONY: foobar

foobar:
        echo "Testing foobar"

当通过预提交挂钩脚本调用时,此目标还会导致 make 进程以错误状态 2 退出,同时手动执行仍然成功。

【问题讨论】:

  • 当您尝试使用更简单的 Make 目标时会发生什么?重现错误的最简单规则(称为最简单的脚本)是什么?
  • 如果我在没有Makefile 的目录中运行make check,则退出代码为2。只是说'。
  • @tripleee 确实如此。这两者都在同一个目录中运行,并且在每种情况下都在执行 Makefile 中的脚本。
  • @Beta 我创建了一个非常简单的目标,它表现出相同的行为。在问题底部查看我的更新。
  • @Beta 然后我通过删除旧的 Makefile 并创建一个只包含我在上面创建的虚拟目标而没有别的东西来进行测试。这按预期工作并返回 0。

标签: gnu-make bazaar


【解决方案1】:

这本质上是一个 Makefile Inception 问题。 bzr 启动了 make,其中包含许多 Makefile,其中一些是已构建的,其中一个依赖于无法获得锁定的 bzr 命令,因为另一个 bzr 进程持有它。由于它是从一个包含启动并对其进行了 FORCE 设置,因此当从 bzr 运行时,它总是会导致任何目标失败,但并不明显,因为它没有像大多数人一样停止 make 命令会出错。

【讨论】:

    猜你喜欢
    • 2013-09-09
    • 1970-01-01
    • 2013-03-01
    • 1970-01-01
    • 2011-08-03
    • 2018-07-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-19
    相关资源
    最近更新 更多