我有一个程序将其设置存储在 ~/.config/myprogram
我以交互方式和批处理排队系统使用。当以交互方式运行时,我希望这个程序使用我的配置文件(它确实如此)。但是在批处理模式下运行时,配置文件不是必需的,因为我指定了覆盖所有相关设置的命令行选项。此外,通过网络访问配置文件会使程序的启动时间增加几秒钟;如果文件不存在,程序启动速度会更快(因为每个作业只需要大约一分钟,这对批处理作业吞吐量有重大影响)。但是因为我也以交互方式使用该程序,所以我不想一直移动/删除我的配置文件。根据我的批处理作业在集群上的调度时间(基于其他用户的使用情况),
(另外:网络文件性能如此之慢可能是一个错误,但我只是集群的用户,所以我只能解决它,不能修复它。)
我可以构建一个不读取配置文件(或有一个不读取配置文件的命令行选项)的程序版本以供批量使用,但该程序的构建环境设计不佳且难以设置。我更喜欢使用通过我系统的包管理器安装的二进制文件。
我怎样才能欺骗这个程序的特定实例来假装我的配置文件不存在(不修改程序)?我希望有一个 form 的包装器pretendfiledoesntexist ~/.config/myprogram -- myprogram --various-options...
,但我对其他解决方案持 开放态度。
Sté*_*las 33
该程序可能会解析该文件的路径$HOME/.config/myprogram
。所以你可以告诉它你的主目录在别处,比如:
HOME=/nowhere your-program
Run Code Online (Sandbox Code Playgroud)
现在,您的程序可能需要您的主目录中的其他资源。如果您知道它们是哪个,您可以为您的程序准备一个假的家,并提供指向其中所需资源的链接。
mkdir -p ~/myprogram-home/.config
ln -s ~/.Xauthority ~/myprogram-home/
...
HOME=~/myprogram-home myprogram
Run Code Online (Sandbox Code Playgroud)
sle*_*anc 28
如果所有其他方法都失败了,请编写一个包装库,您将使用LD_PRELOAD
该库进行注入,以便open("/home/you/my-program/config.interactive")
拦截对调用的调用,但其他任何调用都将通过。这适用于任何类型的程序,甚至是 shell 脚本,因为它会过滤系统调用。
extern int errno;
int open(const char *pathname, int flags)
{
char *config_path = get_config_file_path();
if (!strstr(pathname, config_path))
{
return get_real_open(pathname, flags);
}
else
{
errno = ENOENT;
return -1;
}
}
Run Code Online (Sandbox Code Playgroud)
注意:我还没有测试过这段代码,我也不是 100% 确定这errno
部分能正常工作。
看看fakeroot
它如何处理像getuid(2)
和之类的调用stat(2)
。
基本上,链接器会将该应用程序链接到您的库,该库会覆盖该open
符号。由于您不能使用open
在您自己的库中命名的两个不同的函数,您必须在第二部分(例如get_real_open
)中将其分开,这将依次链接到原始open
调用。
./Application
Application -----> libc.so
open()
Run Code Online (Sandbox Code Playgroud)
LD_PRELOAD=yourlib_wrap.so ./Application
Application -----> yourlib_wrap.so --------------> yourlib_impl.so -----> libc.so
open() get_real_open() open()
Run Code Online (Sandbox Code Playgroud)
编辑:显然有一个ld
标志可以启用 ( --wrap <symbol>
) 允许您编写包装器而不必求助于双重链接:
/* yourlib.c */
#include <stdio.h>
int __real_open(const char *pathname, int flags)
int __wrap_open(const char *pathname, int flags)
{
char *config_path = get_config_file_path();
if (!strstr(pathname, config_path))
{
/* the undefined reference here will resolve to "open" at linking time */
return __real_open(pathname, flags);
}
else
{
errno = ENOENT;
return -1;
}
}
Run Code Online (Sandbox Code Playgroud)