是否可以在文件读取操作中创建动态内容?

是否可以在文件读取操作中创建动态内容?

是否可以根据文件名生成文件内容?

我需要很多类似的.conf文件,其内容仅取决于文件名。

我可以创建一些“动态”文件并生成一堆指向该文件的符号链接吗?

也许 fifo 是一个解决方案,但我无法在生成脚本中获取文件名:

zsh$ mkfifo ./dynamic.conf
zsh$ ln -s ./dynamic.conf ./case1.conf
zsh$ echo $0  > ./dynamic.conf & 
zsh$ cat ./case1.conf

我有zsh(我需要case1.conf)。

答案1

完全不同的方法因为我只知道最后一个答案你会翻白眼。

在本教程中,您将依赖inotify这意味着它确实是特定于 Linux 的。您将彻底解决问题——各个配置文件仍然存在,但您将自动重新生成它们每次改变主控

你有你的“主”配置文件,比如说master.conf,它包含你的所有部分、子部分等。你设置你的脚本,以便inotify当该脚本更改时,它将重写所有这些文件。 (为了避免竞争条件,您可能需要采取一些额外的技巧,例如将文件存储在子目录中,以及交换目录以执行“提交”。)

https://stackoverflow.com/q/5316178/3849157我们得到一个基本的 perl 脚本:

my $inotify = Linux::Inotify2->new;
$inotify->watch("/etc/master.conf", IN_MODIFY);
while () {
  my @events = $inotify->read;
  unless (@events > 0){
    print "read error: $!";
    last ;
  }

  foreach my $event (@events) {
    next unless $event->IN_MODIFY;
    # 1. TODO: RE-READ IN THE CONFIG FILE
    # (example)
    $config_hash = &parse_master_file;

    # 2. TODO: RE-GENERATE YOUR CONFIG FILES
    # (example)
    for $section qw( section1 section2 misc ) {
        open(S,"> /etc/${section}.conf")
        print S &dump_config($config_hash,$section)
        close(S)
    }
  }
}

执行parse_master_filedump_config取决于您。另外,主循环中可能应该调用 sleep,否则你的 CPU 会着火。

答案2

您有一个读取所有这些文件的应用程序/程序.conf,并且您希望将它们全部合并到一个文件中,该文件动态地为程序选择的文件名吐出适当的信息。基于管道的解决方案的问题在于,提供管道的程序无法检测到消费者已打开或想要读取的文件。所以你需要另一种方法。

来自另一个领域的一个鲜为人知的解决方案,解决了另一个领域的令人沮丧的问题:在构建 rpm 时,我们需要缩短 rpmbuild 过程,以修复最终打包步骤中的一些小问题。该spec文件有几个与我们正在构建的 RPM 相关的“部分”...准备、构建、文件。当我们的程序构建但文件部分存在一些错误时,我们希望 rpmbuild 跳过重新编译。但它不会这样做......按设计。

有些人发现你可以用来LD_PRELOAD加载一个专门设计的so/dll 文件来捕获open调用。如果open调用的是规范文件,它将为除该files部分之外的所有内容提供空条目,以便在rpmbuild读取文件时,它实际上正在读取该 DLL 告诉它的内容。

我使用了它好几个星期,但在某个时刻,我擦除了虚拟机,将该程序从存在中删除,从此再也找不到它了。 :( 一个名为的程序mock现在执行此操作,但我不知道它是否以相同的方式执行或使用其他方法。

但这就是这个想法。您需要创建一个 DLL,它可以通过 LD_PRELOAD 加载并覆盖open对该程序的调用,但将您不感兴趣的文件的调用传递给(真实的)。对于您感兴趣的文件,它会提供数据由您的主文件找到并合并。

听起来很复杂?是的,有一点。好的一面是,您将拥有创建一些非常令人讨厌的 rootkit 和特洛伊木马的工具。

ltrace -e open <program>要验证这是否可行,请使用以下命令运行程序:

ltrace -e open /usr/bin/tail /etc/fstab

您将会看到这个输出(类似)...

(0, 0, 0, 0x7f1c32ade000, 88)                             = 0x3055621160
open("/etc/fstab", 0, 00)                             = 4

只要您的程序使用 glibc 打开这些文件(而不是直接系统调用),您就会在上面的输出中看到它,并且您可以正常工作了。

下一步:某个人详细描述如何覆盖ioctl调用。这会让你走上正轨。这里有一个非常好的教程。

答案3

所提出的解决方案对于生产使用来说太疯狂了。

事实上,您似乎对 inotify 方法很好(文件在主配置修改后显式重新生成),因此您可以只使用一个简单的脚本来重新生成所有垃圾。在那里,inotify 被避免而没有损失功能。好处是您需要调试的东西更少,并且不必在后台照顾该过程。

对于lulz,应该指出的是,可以实现所讨论的功能,但我看不出有任何理由这样做。事情是这样的:一个特殊的文件系统(例如基于熔丝的)等等 - 打开、读取等。处理这些文件的任何人发出的例程最终都会调用您的代码,因此您可以反馈您想要的任何内容。但话又说回来,你到底为什么要这么做。

相关内容