2011-12-28 40 views
10

Tôi không thể sử dụng %ENV var trên tập lệnh Perl của mình để sử dụng thư viện Oracle.% ENV không hoạt động và tôi không thể sử dụng thư viện được chia sẻ

BEGIN { 
    $ORACLE_HOME = "/usr/lib/oracle/10.2.0.3/client64"; 
    $LD_LIBRARY_PATH = "$ORACLE_HOME/lib"; 
    $ORACLE_SID="prod"; 
    $ENV{ORACLE_SID}=$ORACLE_SID; 
    $ENV{ORACLE_HOME}= $ORACLE_HOME; 
    $ENV{LD_LIBRARY_PATH}= $LD_LIBRARY_PATH; 
}; 

Nếu tôi in $ENV{'ORACLE_HOME'}$ENV{'LD_LIBRARY_PATH'} tất cả dường như ok nhưng, khi tôi chạy kịch bản của tôi, tôi có lỗi:

install_driver(Oracle) failed: Can't load '/usr/local/lib64/perl5/auto/DBD/Oracle/Oracle.so' for module DBD::Oracle: libclntsh.so.10.1: cannot open shared object file: No such file or directory at /usr/lib64/perl5/DynaLoader.pm line 200. at (eval 3) line 3 Compilation failed in require at (eval 3) line 3. Perhaps a required shared library or dll isn't installed where expected at persistence.perl line 22

Tìm kiếm trên web tôi thấy rằng cách chính xác để thiết lập env VAR trên Perl là sử dụng hàm băm %ENV.

Xuất ORACLE_HOMELD_LIBRARY_PATH qua vỏ unix (export LD_LIBRARY_PATH=...) hoạt động chính xác. Lời khuyên nào?

+0

Đã lâu rồi tôi phải làm việc với Oracle và Perl và tôi nhớ rằng một trong những thư viện mà mô-đun Perl cần không cài đặt với bản cài đặt của nhà phát triển. Tôi sẽ phải giải nén các tập tin và kéo thư viện ra khỏi gói cơ sở dữ liệu. –

+0

Nhưng thật lạ lùng, bởi vì nếu tôi xuất các đường dẫn đó thông qua trình bao, nó hoạt động chính xác. Dường như không phải là một vấn đề liên quan đến các thư viện bị thiếu – Daniele

+0

Shell shell wrapper là cách chúng tôi luôn làm. –

Trả lời

10

Biến môi trường LD_LIBRARY_PATH phải được đặt trước khi chương trình của bạn bắt đầu - trước khi bản thân perl được tải. Thay đổi nó trong BEGIN{} sẽ ảnh hưởng đến các chương trình mới mà bạn bắt đầu, nhưng nó sẽ không ảnh hưởng đến việc tải thư viện được chia sẻ - trong trường hợp này (mặc dù tôi chưa từng sử dụng DBD :: Oracle). .so vào chương trình đã chạy, do đó, "quá muộn" để thay đổi LD_LIBRARY_PATH. Trình liên kết động /lib/ld.so (hoặc hơn) được bắt đầu trước perl, do đó, vào thời điểm tập lệnh của bạn được biên dịch và BEGIN{} chạy, nó đã được thiết lập.

Bạn thể cố gắng tái exec kịch bản của bạn là người kế vị của nó sở hữu hoặc một cái gì đó *, nhưng một kịch bản shell ngắn được gần như chắc chắn sẽ là giải pháp đơn giản nhất:

#!/bin/sh 
    export LD_LIBRARY_PATH=/usr/lib/oracle/10.2.0.3/client64/lib 
    export ORACLE_SID=prod 
    exec /usr/local/bin/your-db-program "[email protected]" 

* - đây sẽ là kinda điên, nhưng TIMTOWTDI:

eval { 
    use DBD::Oracle foo bar baz; … 
    }; 
    if ([email protected] =~ /install_driver\(Oracle\) failed/) { 
    $ENV{LD_LIBRARY_PATH} .= ':/usr/lib/oracle/10.2.0.3/client64/lib'; 
    $ENV{ORACLE_SID} = 'prod'; 
    warn "Restarting with LD_LIBRARY_PATH reset:\n\[email protected]\n"; 
    exec { $0 } $0 => @ARGV; 
    } 
+0

Cảm ơn bạn rất nhiều. Nó hoạt động hoàn hảo – Daniele

-1

Tôi vừa trải qua một điều tương tự. Tôi đã phải đảm bảo rằng môi trường Oracle đã được thiết lập trước khi bất cứ điều gì khác được gọi là nó. Đảm bảo khối BEGIN là trước bất kỳ câu lệnh "sử dụng" nào khác. Trong trường hợp của tôi, một cái gì đó đã được gọi trong tập tin httpd.conf của Apache, vì vậy tôi đã phải thiết lập môi trường của tôi ở đó thay vì trong gói của tôi.

+0

Có, khối 'BEGIN' của tôi trước mọi thứ – Daniele

+0

Đây có phải là môi trường web không? Nếu có, có thể có thứ gì đó đang tải DBD :: Oracle trước khi nó làm cho nó thành kịch bản của bạn. – gpojd

+0

Không, nó không nằm trong môi trường web. Nó chỉ là một kịch bản mà tôi chạy từ shell – Daniele

1

tôi đã viết một vài kịch bản thử nghiệm để xác minh rằng môi trường đã được thiết lập khi bạn thay đổi %ENV:

use strict; 
use warnings; 
use feature qw(say); 

BEGIN { 
    my $foo = "bar-bar"; 
    $ENV{FOO} = "$foo"; 
} 

system qq(/bin/echo printing out \$FOO); 

này in ra:

printing out bar-bar 

đó là những gì tôi mong đợi.

sau đó tôi đã cố gắng này:

use strict; 
use warnings; 
use feature qw(say); 

BEGIN { 
    my $foo = "bar-bar"; 
    $ENV{FOO} = "$foo"; 
} 


system qq(./test.sh); 

và tạo ra một chương trình test.sh trông như thế này:

#! /bin/sh 

echo This is what I got: $FOO; 

Trong trường hợp này, kịch bản Perl của tôi đang chạy test.sh mà in ra giá trị của $FOO biến môi trường được đặt trong tập lệnh Perl của tôi.Chạy test.pl tôi nhận được:

This is what I got bar-bar 

Điều này cho thấy không chỉ là Perl thiết lập các biến môi trường, nhưng điều đó nó cũng được xuất khẩu các biến, vì vậy được gọi là kịch bản shell có quyền truy cập đối với họ.

Bạn có thể thử một kỹ thuật tương tự để xác minh rằng cả hai LD_LIBRARY_PATHORACLE_HOME đang được đặt trước khi chúng được sử dụng. Tôi nghi ngờ bạn sẽ thấy rằng điều này thực sự xảy ra, nhưng chương trình của bạn vẫn không hoạt động khi bạn đặt %ENV.

Điều này chỉ ra một kết luận: Đặt môi trường cho LD_LIBRARY_PATHORACLE_HOME có thể xảy ra quá muộn vào thời điểm tập lệnh Perl của bạn bắt đầu. Tôi tin rằng hệ điều hành kiểm tra LD_LIBRARY_PATH trước khi Perl bắt đầu. Tôi thấy điều này làm một tìm kiếm trên LD_LIBRARY_PATH:

LD_LIBRARY_PATH is an environment variable you set to give the run-time shared library loader (ld.so) an extra set of directories to look for when searching for shared libraries. Multiple directories can be listed, separated with a colon (:). This list is prepended to the existing list of compiled-in loader paths for a given executable, and any system default loader paths.

Vì vậy, LD_LIBRARY_PATH là cho ld.so runtime thư viện chia sẻ bộ nạp, Nếu ld.so đã được nạp, thay đổi LD_LIBRARY_PATH sẽ không làm bất cứ điều gì.

Tôi đã tìm thấy một cuộc thảo luận tương tự trên Perl Monks. Tôi nhận thấy ai đó tìm thấy rerunning env dường như hoạt động.

0

Một giải pháp là thay đổi /etc/ld.so.conf

On CentOS/RHEL 6.4, bạn có thể tạo etc/ld.so.conf.d/oracle với điều này:

/oracle/sw/product/11.2.0/dbhome_1/lib 

Rõ ràng, sửa đổi phù hợp với ORACLE_HOME của bạn.

Sau đó chạy

ldconfig -v 
0

Bạn có thể đặt lệnh export vào khởi động kịch bản cho vỏ unix mà bạn nên có quyền chỉnh sửa. Bằng cách đó, các biến môi trường sẽ được đặt bất cứ khi nào bạn bắt đầu một trình bao mới và tất cả các tập lệnh và chương trình sử dụng Oracle sẽ chọn chúng.

Các vấn đề liên quan