PHP exec () vs system () vs passthru ()


312

Sự khác biệt là gì?

Có một tình huống cụ thể hoặc lý do cho từng chức năng? Nếu có, bạn có thể đưa ra một số ví dụ về những tình huống đó?

PHP.net nói rằng chúng được sử dụng để thực hiện các chương trình bên ngoài. xem tài liệu tham khảo Từ các ví dụ tôi thấy, tôi không thấy bất kỳ sự khác biệt rõ ràng nào.

Nếu tôi chỉ đơn giản là chạy một tập lệnh (bash hoặc python), bạn khuyên tôi nên sử dụng chức năng nào?


16
Cũng có proc_open()popen(), cả hai đều cho phép mức độ kiểm soát cao hơn đối với quá trình sinh sản.
Christian

Câu trả lời:


195

Họ có mục đích hơi khác nhau.

  • exec() là để gọi một lệnh hệ thống, và có lẽ tự xử lý đầu ra.
  • system() là để thực thi một lệnh hệ thống và hiển thị ngay lập tức đầu ra - có lẽ là văn bản.
  • passthru() là để thực thi một lệnh hệ thống mà bạn muốn trả về thô - có lẽ là thứ gì đó nhị phân.

Bất kể, tôi đề nghị bạn không sử dụng bất kỳ trong số họ. Tất cả đều sản xuất mã không thể truy cập cao.


147
Đôi khi tính di động phải được hy sinh cho chức năng. Có một số điều PHP không thể làm tốt.
Frank Crook

30
@Kalium: bạn có thể nói rõ hơn về tuyên bố của mình không? chỉ nêu một số thống kê tỷ lệ mơ hồ không thuyết phục tôi. Tôi tin rằng việc sử dụng các lệnh gọi hệ thống để thực thi các tập lệnh là hoàn toàn tốt miễn là toàn bộ ứng dụng không phụ thuộc vào một loạt các tập lệnh ở phía sau.
mã hóa

46
@Christian izkata@izein:~$ dir -bash: dir: command not found- FreeBSD
Izkata

5
@OZ_ Tôi đã đến tình huống tôi phải làm các tính toán rất tốn kém. Không có mô-đun PHP nào (sẵn sàng) cho điều đó. Tôi đã viết chương trình C của riêng mình và tôi gọi nó bằng passthru (). Đôi khi tính di động có thể ít quan trọng hơn những thứ khác. Phụ thuộc vào dự án.
Paolo

9
Ngoài ra, đó là một sai lầm khi nghĩ rằng PHP là di động miễn là bạn tránh exec, system, passthru. Mã PHP phụ thuộc vào môi trường mà nó chạy và nhiều lỗi bảo mật là do không xem xét điều này. Dưới đây là một ví dụ nhanh: stackoverflow.com/questions/3003145/ từ
Pacerier 24/2/2016

131

Như được rút ra từ http://php.net/ && Chipmunkninja :

Các hệ thống () Chức năng

Hàm hệ thống trong PHP lấy một đối số chuỗi với lệnh để thực thi cũng như bất kỳ đối số nào bạn muốn truyền cho lệnh đó. Hàm này thực thi lệnh được chỉ định và đưa bất kỳ văn bản kết quả nào vào luồng đầu ra (đầu ra HTTP trong tình huống máy chủ web hoặc bàn điều khiển nếu bạn đang chạy PHP dưới dạng công cụ dòng lệnh). Sự trở lại của chức năng này là dòng đầu ra cuối cùng từ chương trình, nếu nó phát ra đầu ra văn bản.

Các exec () Chức năng

Chức năng hệ thống khá hữu ích và mạnh mẽ, nhưng một trong những vấn đề lớn nhất với nó là tất cả văn bản kết quả từ chương trình đi trực tiếp vào luồng đầu ra. Sẽ có những tình huống mà bạn có thể muốn định dạng văn bản kết quả và hiển thị nó theo một cách khác hoặc hoàn toàn không hiển thị nó.

Đối với điều này, hàm exec trong PHP hoàn toàn thích nghi. Thay vì tự động đổ tất cả văn bản được tạo bởi chương trình đang được thực thi vào luồng đầu ra, nó cho bạn cơ hội để đặt văn bản này trong một mảng được trả về trong tham số thứ hai cho hàm:

Các shell_exec () Chức năng

Hầu hết các chương trình chúng tôi đã thực hiện cho đến nay, ít nhiều, là các chương trình thực tế1. Tuy nhiên, môi trường mà người dùng Windows và Unix hoạt động thực sự phong phú hơn nhiều so với điều này. Người dùng Windows có tùy chọn sử dụng chương trình Windows Command Prompt, cmd.exe Chương trình này được gọi là shell lệnh.

Các passthru () Chức năng

Một hàm hấp dẫn mà PHP cung cấp tương tự như các hàm mà chúng ta đã thấy cho đến nay là hàm passthru. Hàm này, giống như các hàm khác, thực thi chương trình mà bạn nói với nó. Tuy nhiên, sau đó nó tiến hành gửi ngay đầu ra thô từ chương trình này đến luồng đầu ra mà PHP hiện đang hoạt động (tức là HTTP trong kịch bản máy chủ web hoặc shell trong phiên bản dòng lệnh của PHP).

Các proc_open () Chức năng và popen () chức năng

Proc_open () tương tự như popen () nhưng cung cấp mức độ kiểm soát lớn hơn nhiều đối với việc thực hiện chương trình. cmd là lệnh được thực thi bởi shell. descriptorspec là một mảng được lập chỉ mục trong đó khóa đại diện cho số mô tả và giá trị đại diện cho cách PHP sẽ chuyển mô tả đó cho tiến trình con. các đường ống sẽ được đặt thành một mảng các con trỏ tệp được lập chỉ mục tương ứng với phần cuối của bất kỳ đường ống nào được tạo. Giá trị trả về là một tài nguyên đại diện cho quá trình; bạn nên giải phóng nó bằng cách sử dụng Proc_close () khi bạn kết thúc với nó.


6
Tốc độ thực thi shell_exec nhanh hơn so với thay thế khác.
Dinesh Saini

29
Bạn nên đề cập rằng bạn đã sao chép câu trả lời của mình trực tiếp từ ChipmunkNinja .
TachyonVortex

7
@TachyonVortex may mắn là anh đã sao chép nguyên văn câu trả lời, vì ChipmunkNinja không còn tồn tại.
Phileo99

2
Có một bản sao của bài viết đó trong máy Wayback: web.archive.org/web/20130809032648/http://chipmunkninja.com/...
bagonyi

2
Còn popen và Proc_open thì sao?
CMCDragonkai

103

Các câu trả lời trước có vẻ hơi khó hiểu hoặc không đầy đủ, vì vậy đây là bảng về sự khác biệt ...

+----------------+-----------------+----------------+----------------+
|    Command     | Displays Output | Can Get Output | Gets Exit Code |
+----------------+-----------------+----------------+----------------+
| system()       | Yes (as text)   | Last line only | Yes            |
| passthru()     | Yes (raw)       | No             | Yes            |
| exec()         | No              | Yes (array)    | Yes            |
| shell_exec()   | No              | Yes (string)   | No             |
| backticks (``) | No              | Yes (string)   | No             |
+----------------+-----------------+----------------+----------------+
  • "Hiển thị đầu ra" nghĩa là nó truyền đầu ra tới trình duyệt (hoặc đầu ra dòng lệnh nếu chạy từ một dòng lệnh).
  • "Có thể nhận đầu ra" có nghĩa là bạn có thể nhận đầu ra của lệnh và gán nó cho một biến PHP.
  • "Mã thoát" là một giá trị đặc biệt được trả về bởi lệnh (còn được gọi là "trạng thái trả về"). Không thường có nghĩa là nó đã thành công, các giá trị khác thường là mã lỗi.

Những điều linh tinh khác cần lưu ý:

  • Toán tử shell_exec () và toán tử backticks làm điều tương tự.
  • Ngoài ra còn có Proc_open () và popen () cho phép bạn đọc / ghi các luồng tương tác với một lệnh thực thi.
  • Thêm "2> & 1" vào chuỗi lệnh nếu bạn cũng muốn chụp / hiển thị thông báo lỗi.
  • Sử dụng escapeshellcmd () để thoát các đối số lệnh có thể chứa các ký tự vấn đề.
  • Nếu chuyển một biến đầu ra $ cho exec () để lưu trữ đầu ra, nếu đầu ra $ không trống, nó sẽ nối đầu ra mới vào nó. Vì vậy, bạn có thể cần hủy đặt ($ output) trước.

Những cái nào có thể thực thi một tập tin php?
johny tại sao

1
@johnywhy none per se - trừ khi bạn rõ ràng gọi php cli hoặc đại loại như vậy. Tôi cho rằng bạn muốn includevà bạn bè
Hagen von Eitzen

21

Tất cả thực sự phụ thuộc vào cách bạn muốn xử lý đầu ra mà lệnh có thể trả về và liệu bạn có muốn tập lệnh PHP của mình chờ chương trình callee kết thúc hay không.

  • exec thực thi một lệnh và chuyển đầu ra cho người gọi (hoặc trả về nó trong một biến tùy chọn).

  • passthrutương tự như exec()chức năng trong đó nó thực thi một lệnh. Chức năng này nên được sử dụng thay thế exec()hoặc system()khi đầu ra từ lệnh Unix là dữ liệu nhị phân cần được truyền trực tiếp trở lại trình duyệt.

  • system thực hiện một chương trình bên ngoài và hiển thị đầu ra, nhưng chỉ dòng cuối cùng.

Nếu bạn cần thực thi một lệnh và có tất cả dữ liệu từ lệnh được truyền trực tiếp trở lại mà không có bất kỳ sự can thiệp nào, hãy sử dụng passthru()chức năng.


8

Nếu bạn đang chạy tập lệnh PHP của mình từ dòng lệnh, passthru()có một lợi ích lớn. Nó sẽ cho phép bạn thực hiện các kịch bản / chương trình như vim, dialog, vv, cho phép các chương trình xử lý điều khiển và trở về kịch bản của bạn chỉ khi chúng được thực hiện.

Nếu bạn sử dụng system()hoặc exec()để thực thi các tập lệnh / chương trình đó, đơn giản là nó sẽ không hoạt động.

Gotcha: Vì một số lý do, bạn không thể thực thi lessbằng passthru()PHP.


1
Tôi không hiểu bạn đang nói gì. Bạn có thể thực thi các chương trình từ CLI và (F) CGI (cũng như mod_php). Có thể có các hạn chế do hệ thống, chẳng hạn như selinux. Nhưng một hệ thống thiết lập tốt sẽ có những lựa chọn tắt. Tất nhiên, một máy chủ được chia sẻ là một câu chuyện khác, nhưng bạn sẽ không cung cấp một môi trường chung cho các khách hàng quý, phải không?
Christian
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.