PHP shell_exec () so với exec ()


345

Tôi đang đấu tranh để hiểu sự khác biệt giữa shell_exec()exec()...

Tôi đã luôn luôn sử dụng exec()để thực hiện các lệnh phía máy chủ, khi nào tôi sẽ sử dụng shell_exec()?

shell_exec()chỉ là một viết tắt cho exec()? Nó dường như là điều tương tự với ít tham số hơn.


2
ví dụ điển hình để thấy sự khác biệt là để thử các lệnh này: date, whoami, ifconfig, netstat.

Ngoài ra còn có các hàm khác: system (), passthru () Nhìn thấy câu hỏi liên quan này , và đặc biệt câu trả lời này .
Gras đôi

Câu trả lời:


353

shell_exectrả về tất cả các luồng đầu ra dưới dạng một chuỗi. exectrả về dòng cuối cùng của đầu ra theo mặc định, nhưng có thể cung cấp tất cả đầu ra dưới dạng một mảng được chỉ định làm tham số thứ hai.

Xem


21
Nếu bạn cần giá trị thoát VÀ tất cả đầu ra, có lẽ bạn vẫn nên sử dụng "exec" hơn là "shell_exec". Ngay khi bạn chuyển tham số đầu ra cho "exec", nó sẽ được lấp đầy với mọi dòng đầu ra, đối với tôi "exec" có thể mọi thứ của "shell_exec" và hơn thế nữa :)
Preexo

4
@ daniel-a-white Tôi biết đây là một cái cũ, nhưng nó phổ biến vì vậy bạn nên chỉnh sửa câu trả lời của mình để phản ánh nhận xét của @preexo - exec () cũng có khả năng trả về toàn bộ đầu ra nếu bạn sử dụng các tham số tùy chọn của nó . Ngoài ra, không liên quan, ai đó nên điểm chuẩn hai lệnh để xem cái nào tốt hơn vì @preexo nói " dường như tôi exec()có thể [làm] mọi thứ shell_exec()[có thể] và hơn thế nữa :) "
SimpleAnecdote

77

Dưới đây là sự khác biệt. Lưu ý các dòng mới ở cuối.

> shell_exec('date')
string(29) "Wed Mar  6 14:18:08 PST 2013\n"
> exec('date')
string(28) "Wed Mar  6 14:18:12 PST 2013"

> shell_exec('whoami')
string(9) "mark\n"
> exec('whoami')
string(8) "mark"

> shell_exec('ifconfig')
string(1244) "eth0      Link encap:Ethernet  HWaddr 10:bf:44:44:22:33  \n          inet addr:192.168.0.90  Bcast:192.168.0.255  Mask:255.255.255.0\n          inet6 addr: fe80::12bf:ffff:eeee:2222/64 Scope:Link\n          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1\n          RX packets:16264200 errors:0 dropped:1 overruns:0 frame:0\n          TX packets:7205647 errors:0 dropped:0 overruns:0 carrier:0\n          collisions:0 txqueuelen:1000 \n          RX bytes:13151177627 (13.1 GB)  TX bytes:2779457335 (2.7 GB)\n"...
> exec('ifconfig')
string(0) ""

Lưu ý rằng việc sử dụng toán tử backtick là giống hệt với shell_exec().

Cập nhật: Tôi thực sự nên giải thích điều cuối cùng. Nhìn vào câu trả lời này nhiều năm sau, tôi thậm chí không biết tại sao nó lại bị bỏ trống! Daniel giải thích nó ở trên - đó là vì execchỉ trả về dòng cuối cùng và ifconfigdòng cuối cùng sẽ trống.


Điều gì xảy ra nếu có một lỗi xảy ra với lệnh ..? Tôi đang gặp lỗi / Không có tệp hoặc thư mục như vậy nhưng làm cách nào tôi có thể bắt nó vào một biến ????
Chúc mừng Coder

@AlwinAugustin: Hả? Có thể được viết cho STDERR. Hãy thử thêm 2>&1vào cuối lệnh của bạn để chuyển hướng STDERR sang STDOUT nếu bạn đang sử dụng máy linux.
mở

Tôi cũng đã thêm nó. Nhưng tôi vẫn nhận được 0 là giá trị. Tôi đã sử dụng một lệnh wc -l và nếu tệp không có ở đó, tôi cần nhận được thông báo lỗi cho biết Không có tệp hoặc thư mục đó.
Chúc mừng Coder

50

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

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

Sự khác biệt là với shell_execbạn có được đầu ra là một giá trị trả về.


4
Tóm tắt ngắn gọn đẹp! Vẫn cần lưu ý rằng exectrả về dòng cuối cùng của đầu ra. Nếu muốn, bạn có thể tùy ý chuyển vào một mảng làm tham số thứ hai để nắm bắt đầu ra hoàn chỉnh và một số nguyên làm tham số thứ ba để nắm bắt giá trị trả về của lệnh shell, có thể được sử dụng để kiểm tra lỗi. Nhược điểm lớn nhất shell_execlà nó trả về null nếu lệnh bị lỗi HOẶC nếu nó không tạo ra bất kỳ đầu ra nào, vì vậy giá trị trả về của nó không thể được sử dụng đáng tin cậy để kiểm tra lỗi.
Sean the Bean

38

Một vài nét riêng biệt không được chạm vào đây:

  • Với exec (), bạn có thể truyền một biến param tùy chọn sẽ nhận được một mảng các dòng đầu ra. Trong một số trường hợp, điều này có thể tiết kiệm thời gian, đặc biệt nếu đầu ra của các lệnh đã ở dạng bảng.

Đối chiếu:

exec('ls', $out);
var_dump($out);
// Look an array

$out = shell_exec('ls');
var_dump($out);
// Look -- a string with newlines in it

Ngược lại, nếu đầu ra của lệnh là xml hoặc json, thì việc mỗi dòng là một phần của mảng không phải là điều bạn muốn, vì bạn sẽ cần xử lý sau đầu vào thành một dạng khác, vì vậy trong trường hợp đó, hãy sử dụng shell_exec .

Cũng đáng chỉ ra rằng shell_exec là bí danh cho toán tử ngược, dành cho những người được sử dụng để * nix.

$out = `ls`;
var_dump($out);

exec cũng hỗ trợ một tham số bổ sung sẽ cung cấp mã trả về từ lệnh đã thực hiện:

exec('ls', $out, $status);
if (0 === $status) {
    var_dump($out);
} else {
    echo "Command failed with status: $status";
}

Như đã lưu ý trong trang hướng dẫn shell_exec, khi bạn thực sự yêu cầu mã trả về từ lệnh đang được thực thi, bạn không có lựa chọn nào khác ngoài sử dụng exec.


3
Ngoài ra: execcho phép bạn nhận được mã trả về của lệnh (thông qua &$return_vartham số), trong khi shell_execkhông cung cấp cách nào để nhận được nó.
Đánh dấu Amery

Mặc dù câu trả lời được chấp nhận cũng đúng, nhưng theo tôi câu trả lời này quan trọng hơn. Có lẽ câu trả lời tốt nhất sẽ là sự kết hợp của cả hai.
UncaAlby
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.