2010-08-11 39 views
12

Tôi đang sử dụng php 5.2.9 trên máy chủ sản xuất và có vẻ như hàm exec() hoạt động "không chuẩn".exec luôn trả về -1 (hoặc 127)

Nếu tôi chạy exec("ls", $output, $return_var) thì $output sẽ chứa danh sách tệp trong thư mục hiện tại như mong đợi, nhưng $return_var sẽ được đặt thành -1 thay vì 0, như mong đợi. Tôi đang sử dụng số $return_var để xác định bất kỳ nơi nào lệnh đã hoàn tất thành công và trên mọi máy chủ khác đã kiểm tra công việc này như mong đợi :)

Bất cứ ai từng gặp phải tình huống như thế này?


chỉnh sửa:

<?php 
$command = "asd"; 

$t1 = time(); 

$output = Array(); 
$result = -5; 
$r = exec($command, $output, $result); 
$t2 = time(); 

echo "<pre>"; 
var_export(Array(
    'command'=>$command, 
    'result'=>$result, 
    'output'=>implode("\n", $output), 
    'r'=>$r, 
    't2-t1'=>$t2-$t1, 
)); 
echo "</pre>"; 

Dù lệnh tôi đặt trong $command, $result sẽ luôn là -1, ngay cả đối với lệnh không tồn tại ... đây là rất lạ

+2

Điều gì nếu biến '$ command' của bạn là một chuỗi rỗng sao cho' exec() 'không đưa ra đối số nào cho' ls'? Mã thoát có còn '-1' không? Nếu vậy, bạn đã kiểm tra việc triển khai 'ls' cho hệ thống hiện tại của bạn bằng' man ls' để xem liệu mã thoát '-1' có được xác định không? Điều này có đúng với các lệnh khác (có lẽ là 'du -h index.html')? – sleepynate

+0

Có vẻ như tôi không thể gọi 'exec (" ")'. Nó in một cảnh báo. Bất kỳ lệnh nào khác cũng hoạt động giống nhau. 'sleep 5' trả về với -1,' lsmod' trả về -1 vv ... – Quamis

+1

Điều duy nhất tôi có thể thấy là [bài đăng trên trang hướng dẫn sử dụng php exec] (http://www.php.net/manual /en/function.exec.php#76687) nhưng kể từ khi nó làm việc trên các máy chủ khác nó không rõ ràng lý do tại sao nó sẽ được điều này. – Troubadour

Trả lời

1

Giả sử hệ thống trở $ result == -1 là Unix-like dựa (Tôi không biết làm thế nào sẽ hành xử Windows với cùng mã)

Các PHP (5.2.9) exec() chức năng không không gọi C exec() nguyên thủy (trả về -1 nếu nó không thể thay thế/thực hiện quá trình, mà không phải là trường hợp ở đây). Thay vào đó, nó gọi popen() tạo ra một đường ống, thực hiện một fork() và thực thi một shell với lệnh của bạn. return_value, -1, không phải là kết quả trực tiếp từ nguyên thủy C, mà đúng hơn là được xây dựng bởi PHP nội bộ, tùy thuộc vào cách lệnh của bạn được xử lý. Nói cách khác, lệnh "ls" có thể đã được thực hiện tốt, trong khi ví dụ PHP không thể đóng đúng đường ống.

Nhìn vào mã C, trong ext/standard/exec.c, có thể có hai lý do tại sao mã trả về là -1, được kích hoạt bởi lỗi; trường hợp thứ hai xảy ra sau popen() gọi

fp = VCWD_POPEN(cmd_p, "r"); 

    if (!fp) { 
     php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to fork [%s]", cmd); 
     goto err; 
    } 
    // ... 
    err: 

    pclose_return = -1; 
    goto done; 

Tuy nhiên trong trường hợp này, bạn sẽ không thấy kết quả và nhật ký sẽ hiển thị lỗi.

Sau đó, return_value được thiết lập thông qua dòng

pclose_return = php_stream_close(stream); 

Nhìn vào _php_stream_free() (php_stream_close() là một macro thay thế bằng _php_stream_free()), các ứng cử viên có khả năng nhất mà có thể trở lại -1 là

ret = stream->ops->close(stream, preserve_handle ? 0 : 1 TSRMLS_CC); 

Lần lượt gọi gián tiếp C nguyên bản(). Theo hướng dẫn sử dụng

Hàm pclose() trả về -1 nếu wait4 (2) trả về lỗi hoặc phát hiện một số lỗi khác.

Dường như có lỗi được phát hiện trong khi đóng ống, điều đó không ngăn dữ liệu kết quả được đặt.Để tìm ra lý do một cách nghiêm ngặt, bạn cần phải kiểm tra thiết lập và nhật ký hệ điều hành, cấu hình PHP và các tham số biên dịch.

Tôi muốn giới thiệu

  • để áp dụng các bản vá lỗi cho hệ điều hành của bạn, và có thể nâng cấp lên phiên bản mới hơn (nếu có),
  • để cập nhật PHP để 5.3.3 (mới nhất tính đến nay) kể từ mã PHP exec() đã thay đổi đáng kể.

Lưu ý rằng có những thay đổi liên quan đến mô-đun suhosin PHP trong phiên bản 5.3 nâng cao theo mặc định bảo mật khi chạy tệp PHP.

+0

Vâng, đó là "unix-like" (trung thực, tôi không có ideea nếu nó là Linux hoặc một hương vị unix). câu trả lời hay. Sự cố đã được quản trị viên máy chủ khắc phục, nhưng tôi không biết những gì anh ta đã làm để giải quyết hoặc sửa lỗi ... Vấn đề là máy chủ được cấu hình theo cách rất hạn chế. Tôi đã truy cập vào các lệnh rất ít (ví dụ php-cli không có sẵn thông qua SSH, và rất nhiều lệnh khác. – Quamis

+0

Tôi chấp nhận câu trả lời của bạn như là hoàn chỉnh nhất và tôi giả định rằng quản trị viên máy chủ đã đi đến hệ điều hành. – Quamis

0

Hãy chắc chắn rằng bạn đang không chạy trong safe mode và exec đó không được liệt kê trong disable_functions trong php.ini.

Một trong các trường hợp này sẽ gây ra exec() không thành công, mặc dù tôi cho rằng sẽ có thông báo.

+0

Tôi không chạy ở chế độ an toàn (bạn không thể sử dụng exec ở chế độ an toàn) và không có chức năng bị vô hiệu hóa. – Quamis

+0

@Quamis - Tôi không nghĩ rằng nó áp dụng trong trường hợp của bạn, nhưng bạn có thể sử dụng exec trong chế độ an toàn. Điều gì xảy ra sau đó là với chế độ an toàn được kích hoạt, chuỗi lệnh được thoát với escapeshellcmd(). - http://php.net/manual/en/function.exec.php –

0

Chúng ta có thể nhận được kết quả đầu ra của quy trình PHP không? Điều đó có thể sẽ chứa câu trả lời mà chúng tôi đang tìm kiếm.

Ngoài ra, 5.2.14 là phiên bản mới nhất của chuỗi 5.2. Bất kỳ cơ hội nào bạn có thể thử nó ở đó? Nếu bạn đang sử dụng nhà cung cấp dịch vụ lưu trữ được chia sẻ, bạn vẫn có thể làm cho nó chạy cục bộ để xem liệu hành vi có thay đổi hay không.

0

Tôi đã dùng thử trên hai máy tính Linux khác nhau (PHP 5.03 và PHP 5.2.10) - cả hai đều hoạt động tốt.

PHP 5.2.10 Ví dụ:

array (
    'command' => 'ls', 
    'result' => 0, 
    'output' => 'atmail 
... 
vhosts', 
    'r' => 'vhosts', 
    't2-t1' => 0, 
) 

Tôi muốn kiểm tra lại cho bất kỳ chỉ thị an ninh liên quan đến trong tập tin php.ini của bạn, kiểm tra quyền tập tin trong thư mục bạn đang cố gắng để tìm kiếm, và xem bạn có SELinux và/hoặc AppArmor đang chạy hay không.

Bạn cũng có thể xem xét một thuật ngữ giống như opendir()/readdir().

IMHO .. PSM

0

Dường như sự cố đã được quản trị viên cố định. Tôi không biết anh ta đã làm gì, nhưng bây giờ nó hoạt động. Vấn đề là quản trị viên máy chủ khá "nghiêm ngặt" và có thể anh ta có chút hạn chế với một số cấu hình hệ thống. Từ SSH shell ví dụ tôi không thể nhìn thấy nơi mà các tập tin nhị phân php đã được cài đặt. Tôi khá chắc chắn rằng trình bao SSH đã được chroot, và cũng là máy chủ web (hoặc đó là chúng hoàn toàn khác nhau, nhưng tôi không biết làm thế nào mà có thể mà không sử dụng bất kỳ loại gắn kết nào) ...

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