如何为 FPATH 中的函数编写“重写包装器”?

如何为 FPATH 中的函数编写“重写包装器”?

我使用表达式“重写包装器”来指foo代重写某些原始函数的函数,并在执行期间调用该原始函数(或其副本)。

我找到了有关此的 Stack Exchange 线程(例如这个),但就我而言,我还有一个额外的要求,即原始文件foo和覆盖文件foo都可以通过FPATH和 自动加载进行访问。 (覆盖版本可能会出现在搜索序列中的较早位置,从而掩盖原始版本。)

有没有办法做到这一点?

FWIW,在我正在处理的特定场景中,重写foo只是将一些非标准值分配给原始引用的一些全局变量来执行其操作。

答案1

您可以使用此函数以与此相同的方式从文件加载函数的代码autoload,而不受文件名必须与函数名匹配的限制。

## load_from FILE FUNCTION_NAME
load_from () {
  eval "$2 () { $(<$1) }"
}

包装器代码如下所示。扩展为in 加载路径$^fpath/somefunction(N)的定义列表(扩展为for every in的列表,并且 glob 限定符限制对现有文件的扩展)。请注意,这仅在您具有单层包装器和包装器时才有效somefunction$^fpath/somefunction/dir/somefunction/dir$fpath(N)在 f 路径中。

#autoload somefunction
local some_parameter=overridden_value
local autoload_files
autoload_files=($^fpath/somefunction(N))
load_from $autoload_files[2] somefunction_wrapped
somefunction_wrapped "$@"

答案2

为了在 Debian 中用包装器替换 binaries/init.d 文件/脚本,我在生产中使用了文件转移多年,并取得了巨大成功。

如果您只是使用与要隐藏的原始文件同名的包装器,那么在相应包的下一次更新中,包装器很可能会被您想要替换的文件重写。

例如,要添加 的包装器gcc,您可以这样做:

sudo dpkg-divert --add --rename --divert /usr/bin/gcc.real /usr/bin/gcc

之后,您可以将包装纸放在/usr/bin/gcc

从那时起,旧的gcc二进制文件将是/usr/bin/gcc.real,最重要的是,gcc由 Debian APT 系统完成/安装的所有后续更新,将安装/usr/bin/gccas的新实例/usr/bin/gcc.real,并使您的包装器不受干扰。

使用 dpkg-divert 替换二进制文件

man dpkg-divert

dpkg-divert 是用于设置和更新转移列表的实用程序。

文件转移是强制 dpkg(1) 不将文件安装到其位置而是安装到转移位置的一种方法。当文件引起冲突时,可以通过 Debian 软件包脚本使用转移来将其移走。系统管理员还可以使用它来覆盖某些软件包的配置文件,或者在安装包含这些文件的软件包的较新版本时,每当需要由 dpkg 保留某些文件(未标记为“conffiles”)时。

PS 我使用这种技术向BINDISC-DHCPinit 脚本添加额外的选项。

相关内容