首页 > 解决方案 > 从外部覆盖命令

问题描述

我有几个带有文件 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 是 3rdparty 软件,我不想每次需要升级时都对其进行修补)?

标签: bashmakefileoverridingcatunix-ar

解决方案


简短版本:您不能(而且您可能不希望这样做)。

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

如果你真的坚持......并且 Makefile 没有使用硬编码路径(例如/bin/cat)。你可以写你自己的猫,把它放在某个地方,让这个位置在其他可能的命中之前cat(只是把它放在前面)。

还有一些机会(查看 make 文件)它使用变量(例如CAT)来知道要调用什么,因此如果是这种情况,您可以提供自己的定义。

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


功能位的示例/说明。我有一个 Makefile:

all:
    @echo foo

并定义和导出一个“覆盖”回声的功能。echo() { /bin/echo "$@" bar; } ; export -f echo. 我运行 make 并得到:

$ make
foo

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

all:
    @bash -c 'echo foo'

这将为您带来您想要的结果:

$ make
foo bar

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

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

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

all:
    @echo foo

我得到:

$ make
foo bar

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


推荐阅读