我使用表达式“重写包装器”来指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/gcc
as的新实例/usr/bin/gcc.real
,并使您的包装器不受干扰。
从man dpkg-divert
dpkg-divert 是用于设置和更新转移列表的实用程序。
文件转移是强制 dpkg(1) 不将文件安装到其位置而是安装到转移位置的一种方法。当文件引起冲突时,可以通过 Debian 软件包脚本使用转移来将其移走。系统管理员还可以使用它来覆盖某些软件包的配置文件,或者在安装包含这些文件的软件包的较新版本时,每当需要由 dpkg 保留某些文件(未标记为“conffiles”)时。
PS 我使用这种技术向BIND
和ISC-DHCP
init 脚本添加额外的选项。