Chạy một tập lệnh Python từ PHP


114

Tôi đang cố chạy một tập lệnh Python từ PHP bằng lệnh sau:

exec('/usr/bin/python2.7 /srv/http/assets/py/switch.py arg1 arg2');

Tuy nhiên, PHP chỉ đơn giản là không tạo ra bất kỳ đầu ra nào. Báo cáo lỗi được đặt thành E_ALL và display_errors đang bật.

Đây là những gì tôi đã thử:

  • Tôi đã sử dụng python2, /usr/bin/python2python2.7thay vì/usr/bin/python2.7
  • Tôi cũng sử dụng một đường dẫn tương đối thay vì một đường dẫn tuyệt đối mà cũng không thay đổi bất cứ điều gì.
  • Tôi đã cố gắng sử dụng các lệnh exec, shell_exec, system.

Tuy nhiên, nếu tôi chạy

if (exec('echo TEST') == 'TEST')
{
    echo 'exec works!';
}

nó hoạt động hoàn toàn tốt trong khi shutdown nowkhông làm gì cả.

PHP có quyền truy cập và thực thi tệp.

CHỈNH SỬA: Cảm ơn Alejandro, tôi đã có thể khắc phục sự cố. Nếu bạn gặp vấn đề tương tự, đừng quên rằng máy chủ web của bạn có thể / hy vọng không chạy dưới dạng root. Thử đăng nhập với tư cách người dùng máy chủ web của bạn hoặc người dùng có quyền tương tự và cố gắng tự chạy các lệnh.


Trước tiên, hãy truy cập vấn đề này stackoverflow.com/questions/21659637/… Nếu không được khắc phục và bạn gặp sự cố như Trong trường hợp nếu bạn gặp khó khăn với việc nhập hoặc tty hoặc không có yêu cầu không hoạt động, vui lòng kiểm tra liên kết này để biết chi tiết các bước thực hiện nó. stackoverflow.com/a/57978771/9470457 Cảm ơn !!!
Thứ

Câu trả lời:


159

Đã thử nghiệm trên Ubuntu Server 10.04. Tôi hy vọng nó cũng giúp bạn trên Arch Linux.

Trong PHP, sử dụng hàm shell_exec :

Thực thi lệnh thông qua shell và trả về kết quả đầu ra hoàn chỉnh dưới dạng chuỗi.

Nó trả về đầu ra từ lệnh đã thực thi hoặc NULL nếu xảy ra lỗi hoặc lệnh không tạo ra đầu ra.

<?php 

$command = escapeshellcmd('/usr/custom/test.py');
$output = shell_exec($command);
echo $output;

?>

Trong tệp Python test.py, hãy xác minh văn bản này ở dòng đầu tiên: (xem giải thích của shebang) :

#!/usr/bin/env python

Ngoài ra, tệp Python phải có các đặc quyền chính xác (thực thi cho người dùng www-data / apache nếu tập lệnh PHP chạy trong trình duyệt hoặc curl) và / hoặc phải là "thực thi". Ngoài ra, tất cả các lệnh trong .pytệp phải có đặc quyền chính xác:

Lấy từ hướng dẫn sử dụng php :

Chỉ là lời nhắc nhanh cho những ai đang cố gắng sử dụng shell_exec trên nền tảng kiểu unix và dường như không thể làm cho nó hoạt động. PHP thực thi với tư cách là người dùng web trên hệ thống (nói chung là www cho Apache), vì vậy bạn cần đảm bảo rằng người dùng web có quyền đối với bất kỳ tệp hoặc thư mục nào mà bạn đang cố gắng sử dụng trong lệnh shell_exec. Điều khôn ngoan khác, nó dường như sẽ không làm gì cả.

Để tạo tệp thực thi trên nền tảng loại unix :

chmod +x myscript.py

6
Cảm ơn bạn, điều đó đã thành công! Còn một vấn đề nữa - người dùng Apache không thể thực thi một lệnh trong tập lệnh Python nhưng tôi đã có thể khắc phục điều đó bằng cách sử dụng sudo và thêm một ngoại lệ cho tập lệnh của tôi vào tệp sudoers. Cảm ơn một lần nữa! :)
Tài khoản bị bỏ rơi

1
Tôi đang gặp phải vấn đề tương tự của người dùng apache, bạn có thể vui lòng hướng dẫn tôi không?
Emma

1
Tôi đã sử dụng câu trả lời của bạn, nó thực thi tập lệnh python tốt nhưng tôi không thể lặp lại kết quả không có gì xuất hiện trên trang web, bạn có thể giúp tôi.
Hamdi Charef

1
"#! / usr / bin / env python" trên dòng đầu tiên đã thực hiện thủ thuật đối với tôi. Tuyệt quá!
C3PO

1
Đối với OSX: echo shell_exec("/usr/local/bin/python3 /Users/cyborg/Dev/magic.py"); hoặc:echo shell_exec("/usr/bin/python /Users/cyborg/Dev/magic.py");
Cyborg

23

Tôi khuyên bạn nên sử dụng passthruvà xử lý bộ đệm đầu ra trực tiếp:

ob_start();
passthru('/usr/bin/python2.7 /srv/http/assets/py/switch.py arg1 arg2');
$output = ob_get_clean(); 

16

Nếu bạn muốn biết trạng thái trả về của lệnh và nhận toàn bộ kết stdoutquả đầu ra, bạn có thể thực sự sử dụng exec:

$command = 'ls';
exec($command, $out, $status);

$outlà một mảng của tất cả các dòng. $statuslà trạng thái trả lại. Rất hữu ích để gỡ lỗi.

Nếu bạn cũng muốn xem stderrđầu ra, bạn có thể chơi với proc_open hoặc chỉ cần thêm 2>&1vào của bạn $command. Cái sau thường đủ để làm cho mọi thứ hoạt động và nhanh hơn để "thực hiện".


8

Alejandro đã đóng đinh nó, thêm phần làm rõ cho ngoại lệ (Ubuntu hoặc Debian) - Tôi không có đại diện để thêm vào chính câu trả lời:

tệp sudoers: sudo visudo

ngoại lệ được thêm vào: www-data ALL=(ALL) NOPASSWD: ALL


7
Có vẻ không hiệu quả khi thêm dữ liệu www vào sudoers và cung cấp cho apache nhiều quyền hơn mà nó cần. Cấp quyền cho dữ liệu www đối với tập lệnh mà bạn đang thực thi là đủ.
JasonRDalton

Ý tưởng tuyệt vời, nhưng chắc chắn có thể khiến hệ thống của bạn dễ bị tấn công. Tôi đồng ý với @JasonRDalton
Reed

6

Để làm rõ lệnh nào sẽ sử dụng dựa trên tình huống

exec() - Thực hiện một chương trình bên ngoài

system() - Thực thi một chương trình bên ngoài và hiển thị đầu ra

passthru() - Thực hiện một chương trình bên ngoài và hiển thị đầu ra thô

Nguồn: http://php.net/manual/en/ Chức năng.exec.php


4

Trong trường hợp của tôi, tôi cần tạo một thư mục mới trong thư mục có wwwtên scripts. Trong scriptstôi đã thêm một tệp mới có tên test.py.

Sau đó tôi đã sử dụng sudo chown www-data:root scriptssudo chown www-data:root test.py.

Sau đó, tôi vào scriptsthư mục mới và sử dụng sudo chmod +x test.py.

Tệp test.py của tôi trông giống như thế này. Lưu ý phiên bản Python khác:

#!/usr/bin/env python3.5
print("Hello World!")

Từ php bây giờ tôi làm điều này:

$message = exec("/var/www/scripts/test.py 2>&1");
print_r($message);

Và bạn sẽ thấy: Hello World!


3

Các phương pháp trên có vẻ phức tạp. Sử dụng phương pháp của tôi như một tài liệu tham khảo.

Tôi có hai tệp sau:

  • run.php

  • mkdir.py

Ở đây, tôi đã tạo một trang HTML chứa GO nút. Bất cứ khi nào bạn nhấn nút này, một thư mục mới sẽ được tạo trong thư mục có đường dẫn bạn đã đề cập.

run.php

<html>
 <body>
  <head>
   <title>
     run
   </title>
  </head>

   <form method="post">

    <input type="submit" value="GO" name="GO">
   </form>
 </body>
</html>

<?php
	if(isset($_POST['GO']))
	{
		shell_exec("python /var/www/html/lab/mkdir.py");
		echo"success";
	}
?>

mkdir.py

#!/usr/bin/env python    
import os    
os.makedirs("thisfolder");

1

Điều này thật tầm thường, nhưng chỉ muốn giúp những ai đã làm theo gợi ý của Alejandro nhưng gặp phải lỗi này:

sh: blabla.py: lệnh không tìm thấy

Nếu ai đó gặp phải lỗi đó, thì cần phải thực hiện một chút thay đổi đối với tệp php bởi Alejandro:

$command = escapeshellcmd('python blabla.py');
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.