perl+DBD::Oracle+mod_perl+Oracle LDAP名称解析程序=崩溃



这发生在我的旧Fedora系统上。今天,我安装了一个新的centos6.5,安装了最新的oracle客户端(12.1.0.1.0),cpan的最新DBD::oracle(1.68),在尝试连接数据库时遇到了同样的问题:apache segfault。当我从命令行尝试相同的perl时,或者作为CGI,它可以工作;当我关闭sqlnet.ora文件中的LDAP名称解析程序时,它也能正常工作。

从头开始:这是我的开始.pl:

$ENV{'NLS_LANG'}='AMERICAN_AMERICA.AL32UTF8';
$ENV{'ORACLE_HOME'}='/opt/oracle/OraHome1';
use DBI ();
use DBD::Oracle ();

这是我的测试程序:

#!/usr/bin/perl
require "startup.pl" unless defined $ENV{'ORACLE_HOME'};
use DBI;
use DBD::Oracle;
print "Content-type: text/plainnn";
print "connecting: n";
my $dbh=DBI->connect("dbi:Oracle:mydb", 'username', 'password');
print "connected! n";

从shell运行此操作效果良好。以CGI脚本运行效果良好。从mod_perl运行它会使apache:崩溃

[Wed Dec 04 16:38:01 2013] [notice] Apache/2.2.15 (Unix) DAV/2 PHP/5.3.3 mod_wsgi/3.2 Python/2.6.6 mod_perl/2.0.4 Perl/v5.10.1 configured -- resuming normal operations
[Wed Dec 04 16:38:28 2013] [notice] child pid 25756 exit signal Segmentation fault (11)

对httpd进程执行strace显示以下内容:

connect(21, {sa_family=AF_INET, sin_port=htons(389), sin_addr=inet_addr("10.250.52.237")}, 16) = 0
write(21, "0f211`72124200", 14) = 14
poll([{fd=21, events=POLLIN|POLLPRI|POLLERR|POLLHUP}], 1, -1) = 1 ([{fd=21, revents=POLLIN}])
read(21, "02042021", 8)       = 8
read(21, "1a2047n144", 14) = 14
write(21, "0201226212c201220042cn=bpas_p,cn=OracleCo"..., 153) = 153
poll([{fd=21, events=POLLIN|POLLPRI|POLLERR|POLLHUP}], 1, 10000) = 1 ([{fd=21, revents=POLLIN}])
read(21, "02041{21", 8)         = 8
read(21, "2d2041r040cn=bpas_p,cn=OracleCont"..., 377) = 377
--- SIGSEGV (Segmentation fault) @ 0 (0) ---

因此,很明显,httpd在与10.250.52.237:389(oracle名称解析程序的ldap端口)通信时崩溃。

我的标准sqlnet.ora是:

NAMES.DIRECTORY_PATH    = (LDAP, ONAMES, TNSNAMES)
NAMES.DEFAULT_DOMAIN    = xxx.yyyy.zzz
NAMES.PREFERRED_SERVERS =
  (ADDRESS_LIST =
    (ADDRESS = (PROTOCOL = TCP)(HOST = oranames01.yyyy.zzz)(PORT = 1501))
    (ADDRESS = (PROTOCOL = TCP)(HOST = oranames02.yyyy.zzz)(PORT = 1502))
  )

这是我的ldap.ora:

DIRECTORY_SERVERS = (oranames01.yyyy.zzz:389:636, oranames02.yyyy.zzz:389:636)
DEFAULT_ADMIN_CONTEXT = "dc=xxx, dc=yyyy, dc=zzz"
DIRECTORY_SERVER_TYPE = OID

strace转储的地址(10.250.52.237)是oranames01.yyyy.zzz.的IP地址

现在,如果我从sqlnet.ora 中删除LDAP适配器

NAMES.DIRECTORY_PATH    = (ONAMES, TNSNAMES)

并将数据库连接字符串放入tnsnames.ora

mydb.xxx.yyyy.zzz=(DESCRIPTION=(SOURCE_ROUTE=OFF)(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=ivorapo01.xxx.yyyy.zzz)(PORT=15350)))(CONNECT_DATA=(SERVICE_NAME=mydb.xxx.yyyy.zzz)(FAILOVER_MODE =(TYPE = SELECT)(METHOD = BASIC)(RETRIES = 180)(DELAY = 1))))

一切都很好——命令行、cgi-perl和modperl。

因此,很明显,mod_perl和LDAP名称解析程序的组合似乎存在一些问题。

这种情况发生在我的Fedora 14系统上,首先是apache 2.2.17和Oracle客户端10.2.0.1.0,现在是新安装的CentOs 6.5、apache 2.2.15和Oracle客户端12.1.0.1.0。在谷歌上搜索mod_perl和oracle显示了一些关于oracle_HOME设置太迟的点击(我也有这个,把它放在startup.pl中解决了这个问题),但似乎没有什么适合我的问题。

有人能证实吗?或者,有人能确认mod_perl+DBD::Oracle+Oracle LDAP名称解析在他们的网站上工作吗?现在,我可以通过不使用LDAP名称适配器来解决这个问题,但我希望在投入生产之前解决这个问题。

我追踪到ldap库/lib64/libldap-2.4.so.2。这个库由mod_ldap、mod_authnz_ldap和mod_php通过一个可选的依赖项使用(依赖项列表似乎是php->libcurl->libssl->libldap,但我并没有真正调查)。这个库还复制了oracle在libclntsh.so中定义的几个函数名。显然,这些函数彼此不兼容。就我而言,崩溃发生在ldap_search_st中。

一旦我从服务器上删除了mod_php、mod_ldap和mod_authnz_ldap,崩溃就停止了。

由于php对libldap的依赖似乎是可选的,我尝试重新启用php,并将/lib64/libldap-2.4.so.2重命名为/lib64/libldap-2.4.so.2.disabled,这样php就不会加载它。我重新启用了php,服务器仍然没有崩溃。

我的服务器上不需要php,所以我再次禁用了php并取消了库重命名。但解决方案似乎是:

a) 您不能在一个进程中同时使用oracleLDAP名称解析程序和系统LDAP库。

b) 如果要使用LDAP解析程序,则需要禁用mod_LDAP和mod_authnz_LDAP。

c) 如果您的服务器不需要php,也可以禁用它。如果确实需要php,则可以保持启用状态,但必须确保它不会加载系统ldap库。php中的Ldap函数以及依赖于它的curl函数将不起作用。

d) 您可以重命名系统ldap库以确保它不会被拉入,但这将扼杀系统中依赖ldap的所有其他内容。(请注意,perl中的Net::LDAP模块不会NOT使用此库,因此在重命名后它仍然可以工作!)。

e) 如果您真的需要php和ldap库,我看到的唯一解决方法是将libldap-2.4.so.2复制到/etc/ld.so.cache中不存在的某个目录,并为需要该库的程序(但显然不是http服务器)将ld_library_PATH设置为该目录。

相关内容

  • 没有找到相关文章

最新更新