9

我只是偶然发现了这个问题。我试图写一个非常基本的Makefile目标:

core: myprogram
        ulimit -c 10000
        ./myprogram
        ulimit -c 0

这个想法是将核心大小限制设置为适当的值,使程序崩溃,然后将核心大小限制重置为零。当我调用此规则时,我收到以下错误消息:

$ make core
cc -Wall -Wextra -m32 -g  -o example example.c 
ulimit -c 100000
make: ulimit: Command not found
make: *** [core] Error 127

首先,我有点惊讶,但我认为问题出在ulimit内置 shell 的事实上。而且,令人惊讶的是(至少对我而言),这些内置函数不能从Makefile.

此外,ulimit既可以是仅内置函数(在我的 Debian 上就是这种情况) ,可以仅是二进制程序(/usr/bin/ulimit)。

所以,我的问题很简单,如果可能的话,如何以优雅和便携的方式解决这个问题,并从 Makefile 内部调用内置函数?

4

5 回答 5

21

您收到此错误的原因是 make(尤其是 GNU make)尝试执行许多优化。其中之一是,如果命令看起来是一个不需要 shell 的简单命令,那么 make 将简单地通过 fork/exec 直接调用它而不运行 shell。如果该命令仅作为 shell 内置存在,那么这将不起作用。您的命令行ulimit -c 10000是一个简单的命令,并且 ulimit 并没有被定义为只有 make 知道的 shell-builtin,所以 make 将尝试ulimit直接 fork/exec。因此,解决您当前问题的一种方法是简单地添加一个对 shell 特殊的字符(最明显的是;),这将暗示需要将该命令发送到 shell。

但是,这对您不起作用。

与上面 H2CO3 的评论完全相反:考虑到它提供的功能,它怎么可能是[内置的 shell]?您必须问自己的真正问题是相反的:考虑到它提供的功能,它怎么可能不是一个? ulimit 的手册页明确指出:ulimit 实用程序应设置或报告对 shell 及其子进程写入的文件施加的文件大小写入限制,并且进一步:由于 ulimit 影响当前 shell 执行环境,因此始终提供为一个shell常规内置。

您必须记住,UNIX 中的进程几乎不可能修改其父进程的任何方面。它只能修改自己或它调用的任何子进程。这包括环境变量、工作目录,还包括 ulimit 设置。

那么,很好,这如何适用于您的情况?您必须记住,make 配方中的每个逻辑行都是在单独的 shell中调用的。所以对于像这样的命令:

core: myprogram
        ulimit -c 10000 ;
        ./myprogram
        ulimit -c 0 ;

(添加分号以强制 shell)make 基本上调用的是这样的:

core: myprogram
        /bin/sh -c 'ulimit -c 10000 ;'
        /bin/sh -c './myprogram'
        /bin/sh -c 'ulimit -c 0 ;'

如您所见,每个 ulimit 都在其自己的 shell 中调用,因此它实际上是无用的。它将修改该外壳的核心文件大小限制,然后外壳退出并且更改丢失,然后在具有原始 ulimit 的新外壳中调用您的程序,然后调用第三个外壳并将内核的 ulimit 设置为 0 (也无用)。

您需要做的是将所有这些命令放在一个逻辑行上,如下所示:

core: myprogram
        ulimit -c 10000; ./myprogram

(您不需要重新设置限制,因为 shell 无论如何都会退出)。

附带说明一下,就是为什么 make 不太担心这些 shell 内置函数的原因。在不需要使用诸如分号之类的特殊外壳字符的上下文中,基本上不可能使用这样的内置函数来产生任何效果。

于 2013-07-09T14:00:42.173 回答
3

any 的默认 shellMakefilesh. 如果您必须使用特定 shell 的内置函数,请在您的Makefile:

SHELL:=bash

请注意,这是不好的做法,因为您的想法是您Makefile应该在任何机器上工作,而不仅仅是那些bash已安装的机器。

如果您想支持任一变体(外部与内置),您可以检查bash相应的可用性。ulimitvia ,并根据检查的结果which设置一个包含要使用的命令的变量(ulimitvs. )。bash -c "ulimit"

编辑: MadScientist 关于ulimit. 出于文档目的,我将保持此答案不变,但它对 perror 的特定问题没有帮助。

于 2013-07-09T12:05:18.617 回答
2

你可以说:

core: myprogram
        $(shell /bin/bash -c "ulimit -c 10000")
        ./myprogram
        $(shell /bin/bash -c "ulimit -c 0")
于 2013-07-09T12:08:10.527 回答
0

在官方 GNU make 文档(http://www.gnu.org/software/make/manual/make.html)第 5.3.2 章中,它说“用作 shell 的程序取自变量 SHELL。如果这个您的 makefile 中没有设置变量,程序 /bin/sh 用作 shell。" 您可以将 SHELL 设置为 /bin/bash。

于 2015-01-05T13:47:19.373 回答
-1

简短回答:在命令末尾添加分号 (;)。这样,您将使用内置工具调用 FULL shell。

        ulimit -c 10000;

代替

        ulimit -c 10000
于 2018-08-22T11:39:19.703 回答