我只是偶然发现了这个问题.我试着写一个非常基本的Makefile目标:
core: myprogram
ulimit -c 10000
./myprogram
ulimit -c 0
Run Code Online (Sandbox Code Playgroud)
我们的想法是将核心大小限制设置为适当的值,使程序崩溃,然后将核心大小限制重置为零.当我调用此规则时,我收到以下错误消息:
$ make core
cc -Wall -Wextra -m32 -g -o example example.c
ulimit -c 100000
make: ulimit: Command not found
make: *** [core] Error 127
Run Code Online (Sandbox Code Playgroud)
首先,我有点惊讶,但我认为这个问题来自于ulimit内置shell 的事实.而且,令人惊讶的是(至少对我而言),这些内置函数无法从a调用Makefile.
此外,ulimit既可以是仅一个内置函数(它是这种情况在我的Debian)或仅一个二进制程序(/usr/bin/ulimit).
所以,我的问题很简单,如何以优雅和可移植的方式解决这个问题,并从Makefile内部调用内置函数?
Mad*_*ist 17
您收到此错误的原因是make(特别是GNU make)尝试执行许多优化.其中之一是,如果命令看起来是一个不需要shell的简单命令,那么make将直接通过fork/exec调用它而不运行shell.如果该命令仅作为内置shell存在,那么这将不起作用.你的命令行ulimit -c 10000是一个简单的命令,ulimit没有被定义为只有一个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 ;
Run Code Online (Sandbox Code Playgroud)
(添加分号以强制shell)基本上调用的是:
core: myprogram
/bin/sh -c 'ulimit -c 10000 ;'
/bin/sh -c './myprogram'
/bin/sh -c 'ulimit -c 0 ;'
Run Code Online (Sandbox Code Playgroud)
如您所见,每个ulimit都在自己的shell中调用,因此它实际上没用.它将修改该shell的核心文件大小限制,然后shell退出并且更改丢失,然后在具有原始ulimit的新shell中调用您的程序,然后调用第三个shell并将core的ulimit设置为0 (也没用).
您需要做的是将所有这些命令放在一个逻辑行上,如下所示:
core: myprogram
ulimit -c 10000; ./myprogram
Run Code Online (Sandbox Code Playgroud)
(您不需要设置限制,因为shell无论如何都会退出).
作为旁注,这就是为什么make不太担心这些shell内置函数.像这样的内建基本上不可能使用任何影响的情况下,你并不需要使用一些特殊的shell字符像一个分号.