覆盖从外部制作的命令



我有几个文件stamp1.txt和stamp0.txt的目录,我想要覆盖cat命令。例如,我需要它来禁止"stamp1"文件存档到库中。

所以我写了一个名为"realname"的小过滤器程序和 bash 脚本来覆盖原始的 cat 命令。

function cat() { 
local e=""
for s in $@
do
if realname $s; then
e=$e" "$s;
fi
done
command cat $e;
}

所以命令:

cat dir1/stamp1.txt dir2/stamp0.txt

将转换为

cat dir2/stamp0.txt

这个例子工作得很好

ar cruv some_lib.a `cat dir1/stamp1.txt dir2/stamp0.txt`

但是当我运行一些makefile来构建一些软件时 - 在这个过程中使用了原始的cat也没有被覆盖。

如何在不更改makefile的情况下覆盖cat或任何其他命令以使其在make过程中工作(makefile是第3方软件,我不想每次需要升级时都修补它(?

你不能用 shell 函数做到这一点,因为 shell 函数只存在于本地 shell 中。 它不会传递给像make这样的程序。 此外,GNU make 默认总是调用/bin/sh,而不是/bin/bash,并且上面的 shell 函数是用 bash 语法编写的,因此将其放在您的~/.bashrc中不会有任何影响。

您可以运行:

$ make SHELL=/bin/bash

并将该 shell 函数添加到您的~/.bashrc中,这可能会起作用。

您唯一可以做的其他事情(假设您的第三方 makefile 直接调用cat并且不使用像$(CAT)这样的变量(是创建一个catshell 脚本(不是函数(并将其放在PATH上,然后再/bin,并在调用 make 时/usr/bin。 像这样:

$ mkdir tmp
$ vi tmp/cat
...add commands...
$ chmod 755 tmp/cat
$ PATH=$(pwd)/tmp:$PATH make ...

当然,当您执行此操作时,您不能在脚本中使用command cat ...,您必须使用完全限定的路径,例如/bin/cat ...

简短版本:你不能(你可能不应该想要(。

更长版本:你已定义一个 shell 函数。您实际上甚至可以将该 shell 函数导出到环境中export -f cat。但是,除非 Makefile 说bash -c cat ...而不仅仅是cat(或其他对相同效果的引用(,否则它不会给你你想要的行为。

如果你真的坚持...并且生成文件没有使用硬编码路径(例如/bin/cat(。你可以写你自己的猫,把它放在某个地方,让这个位置先于其他可能的点击cat(把它放在前面(。

也有一些机会(查看 make 文件(它使用了一个变量(例如CAT( 知道该怎么称呼,因此如果是这种情况,您可以提供自己的定义。

无论如何。我不鼓励您使用这样的解决方法,因为这样做会使机器的实际行为变得模糊。这里声明了一些东西...以及环境中的其他东西赋予它不同的含义。这是错误和最终不明显(更难解决(错误的非常常见的来源。


功能位的示例/说明。我有一个制作文件:

all:
@echo foo

并定义并导出"覆盖"echo 的函数。echo() { /bin/echo "$@" bar; } ; export -f echo.我运行制作并得到:

$ make
foo

因为 make 只是在PATH中寻找echo(尝试exec,一旦找到它,它就会运行它(。如果我将其更改为在两者之间有 bash 步骤,导出的功能将启动,但是......这是在make中使用命令的常用方法,您必须编辑您不想要的Makefile:

all:
@bash -c 'echo foo'

这将产生您想要的结果:

$ make
foo bar

我提到的另一个选项。我已经将该函数的行为放入脚本中,/tmp/bin/echo阅读:

#!/bin/bash
/bin/echo "$@" bar

我已经修改了PATHenv varexport PATH=/tmp/bin:$PATH.现在,即使使用Makefile的第一种形式:

all:
@echo foo

我得到:

$ make
foo bar

但是,如果给出的 Makefile 说/bin/echo,我就没有这样的运气了。您仍然可以更改二进制文件...或者通过强制共享库预加载来更改其行为...但听起来很极端,并充分揭示了为什么这真的可能不是最好的方向。

相关内容

  • 没有找到相关文章