2015-04-17 22 views
18

Khi php được sử dụng như là một module apache, một biến môi trường đến từ một chỉ thị apache SetEnv có sẵn để php của getenv(), nhưng nó không xuất hiện để có sẵn cho C phần mở rộng thông qua stdlib của getenv(). Ít nhất nó xảy ra với mô-đun pgsql.Tại sao putenv() cần thiết trên một biến môi trường đã được xác định?

Nếu biến được reinstantiated với mã php:

putenv("varname=".getenv("varname")); 

sau đó nó trở nên có sẵn để mã của tiện ích.

Câu hỏi: tại sao quá trình khôi phục lại cần thiết? Môi trường php lõi khác với môi trường "chuẩn" (stdlib) như thế nào?

Điều này xảy ra với: PHP Version 5.3.10-1ubuntu3.17 trong Ubuntu 12.04, làm mô-đun apache. Khi chạy từ dòng lệnh, cách giải quyết ở trên là không cần thiết. Từ câu hỏi khác: Using .pgpass from Apache libphp5.so có vẻ như cách giải quyết này cũng cần thiết cho php-5.4 trong FreeBSD vì vậy nó không chỉ là Ubuntu hoặc php-5.3.

Nó không phụ thuộc vào variables_orderE trong đó. Tôi đã thử cả hai EGPCSGPCS$_ENV không được điền khi có, như mong đợi, nhưng điều đó không thay đổi kết quả của getenv(), dưới dạng documented hoặc rõ ràng là kết quả của số getenv() của stdlib từ các tiện ích mở rộng bên trong.


Demo của vấn đề với các module pgsql. Nó được xây dựng trên đầu trang của thư viện chia sẻ libpq được viết bằng C, được gọi là getenv() trên một số biến môi trường tùy chọn PG*.

Trong file cấu hình apache, dưới một <VirtualHost>, Tôi đang thiết này để làm cho các nỗ lực kết nối thất bại:

SetEnv PGHOST doesnotexist 

và không chỉ định một máy chủ trong pg_connect cuộc gọi, vì vậy PGHOST phải được thực hiện khi xuất hiện.

Trước tiên hãy thử:

$v=getenv("PGHOST"); 
echo "PGHOST=$v\n"; 

$cnx=pg_connect("user=daniel"); 
if ($cnx) { 
    echo "Connection is successful."; 
} 

Kết quả:

 
PGHOST=doesnotexist 
Connection is successful. 

Vì vậy PGHOST là nhận bỏ qua, mặc dù là trong môi trường.

Second thử, bây giờ đặt lại PGHOST vào môi trường mặc dù nó đã có:

$v=getenv("PGHOST"); 
echo "PGHOST=$v\n"; 
putenv("PGHOST=".getenv("PGHOST")); 
$cnx=pg_connect("user=daniel"); 
if ($cnx) { 
    echo "Connection is successful."; 
} 

quả (thất bại trong việc kết nối với các máy chủ nhất định, như mong đợi):

PGHOST=doesnotexist 
Warning: pg_connect(): Unable to connect to PostgreSQL server: 
could not translate host name "doesnotexist" to address: 
Name or service not known in /var/www/test/pgtest2.php on line 8 
+0

Tôi thấy bạn có đường dẫn unix, nhưng bạn có xảy ra một thứ gì đó như Cygwin không? Có một vấn đề cửa sổ trong vùng lân cận này dựa trên đó các thời gian chạy C khác nhau được chia sẻ với nhau. – covener

+0

Không điều này xảy ra với linux ubuntu 12.04 –

+0

Cũng xảy ra trên FreeBSD 10.1 với PHP 5.4. – CXJ

Trả lời

8

Lý do là:

Giá trị môi trường bạn nhận được từ getenv()[PHP] (func php tion) khác với môi trường bạn truy vấn với getenv()[C] (hàm C lib). Những gì getenv()[PHP] làm, đang kiểm tra với sapi đã đăng ký cho một trận đấu (http://lxr.php.net/xref/PHP_5_6/ext/standard/basic_functions.c#3999).

apache2 sapi thực hiện điều này thông qua ngữ cảnh môi trường riêng của mình (http://lxr.php.net/xref/PHP_5_6/sapi/apache2handler/sapi_apache2.c#253), không phải môi trường hệ điều hành chuẩn từ quy trình apache.

CHỈ khi không tìm thấy kết quả phù hợp, nó sẽ kiểm tra môi trường của quá trình thực tế. Vì vậy, đây là lý do tại sao getenv()[PHP] trả về một giá trị, nhưng getenv()[C] thì không.

Bây giờ, "hack" cũng đơn giản: putenv()[PHP], lưu trữ khóa/giá trị đã cho trong môi trường của quá trình đang chạy, đó là lý do tại sao nó có thể được tìm thấy sau bởi getenv()[c].

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