我们有一个使用 IonCube 加密的 PHP 应用程序。此应用程序调用存储在同一目录中的 XML 文件来获取其配置选项。
该软件的许可证允许我们在我们拥有的任意数量的域上使用它,但由于加密,我们需要在我们拥有的每个域上安装脚本(我们有几千个域)。我们希望将所有域指向同一服务器上的同一位置,并且只安装一次应用程序。当应用程序尝试读取 XML 配置设置文件时,我们希望根据用户浏览的域为其提供不同版本的配置信息。配置数据将存储在我们将创建的数据库中。
由于应用程序已加密,我们无法将配置文件设为变量或将其指向可以执行某些逻辑的另一种类型的文件,也无法改变其处理配置文件的方式。
知道如何在上述限制条件下做到这一点吗?
到目前为止,我想到的唯一办法是使用用户空间文件系统(可能基于 FUSE)来实现这一点……但我希望还有其他方法。我们在 LAMP 平台上运行它。
答案1
在我看来,你的问题可以分为两个方面……第一个是让程序将配置信息传递给你的网络应用程序的方法,第二个是让该程序知道谁在调用它,这样它就可以将正确的配置。
第一个问题可以通过使用命名管道来解决。将配置文件(例如,config.xml)设为命名管道或 FIFO,然后设置一个写入该命名管道的程序。
第二个问题更复杂,因为写入命名管道的程序实际上并不知道另一端是谁。您可以通过创造性地使用 lsof 来解决这个问题。一旦您知道是谁在呼叫您,您就可以尝试从他们的环境中找到一些有用的信息,以帮助您了解哪个站点实际上正在被访问。
这里有一些相当复杂的 perl 试图解决这两个问题。您无疑会想要调整它以适合您的环境,但希望它能有所帮助。
#! /usr/bin/perl
use strict;
use POSIX qw(mkfifo);
my $f = "the_config.txt";
unlink $f if -e $f;
mkfifo($f, 0644) or die "mkfifo $f failed: $!\n";
while (1) {
my ($interesting_command, $interesting_pid);
unless (-p $f) {
unlink $f;
mkfifo($f, 0700) or die "mkfifo $f failed: $!\n";
}
# the open blocks until someone else tries to read the pipe
open(FIFO, "> $f") or die "can't write $f: $!\n";
# figure out who is on the other end?
open(LSOF, "lsof $f |") or die "can't run lsof: $!\n";
while (<LSOF>) {
chomp;
my ($command, $pid, $user, $fd) = split(m/\s+/, $_);
next unless $fd =~ m/\d+r$/; # we are only interested in the reader
$interesting_command = $command;
$interesting_pid = $pid;
}
close LSOF;
if (!defined($interesting_pid)) {
print "couldn't find the corresponding pid, :-(\n";
close FIFO;
sleep 2;
next;
}
print FIFO "I see you process $interesting_pid ($interesting_command)\n"
or die "couldn't print to $f: $!\n";
my $the_site = get_site($interesting_pid);
print FIFO "looks like your server name was $the_site\n"
or die "couldn't print to $f: $!\n";
close FIFO or die "couldn't close $f: $!\n";
sleep 2;
print "looping\n";
}
sub get_site {
my $pid = shift;
my $server_name;
# extract data from his environment...
local($/) = "\0";
open(PE, "/proc/$pid/environ") or die "can't open environ for pid $pid\n";
while (<PE>) {
my ($key, $val) = split(m/=/, $_);
next unless $key eq 'SERVER_NAME';
$server_name = $val;
}
close(PE);
if ($server_name eq '') {
return "not found, :-(\n";
}
return $server_name;
}
我通过设置一个简单的 CGI 脚本来读取文件来测试这一点:
#! /usr/bin/perl
print "Content-type: text/html\n\n";
print "<html><head></head><body><pre>\n";
open(F, "/full_path_to_the_named_pipe/the_config.txt");
while (<F>) {
print;
}
close(F);
print "</pre></body></html>\n";
从我的个人网站点击此按钮会打印用于点击它的域名。
显然,您必须确保运行脚本的用户有权执行 lsof 并读取 Web 服务器的环境,否则它将无法提取服务器名称。您还需要确保写入命名管道的脚本始终在运行,否则您的 php 应用程序将永远阻塞。可能还有许多其他注意事项,但希望这些足以让您入门。