PHP shell_exec () vs exec ()


345

ฉันกำลังพยายามเข้าใจถึงความแตกต่างระหว่างshell_exec()และexec()...

ฉันมักจะใช้exec()คำสั่งด้านเซิร์ฟเวอร์เสมอเมื่อไรฉันจะใช้shell_exec()?

เป็นshell_exec()เพียงชื่อย่อสำหรับexec()? ดูเหมือนว่าจะเป็นสิ่งเดียวกันกับพารามิเตอร์ที่น้อยลง


2
dateตัวอย่างที่ดีที่จะเห็นความแตกต่างคือการพยายามที่คำสั่งเหล่านี้: whoami, ifconfig, netstat,

นอกจากนี้ยังมีฟังก์ชั่นอื่น ๆ : system (), passthru () ... ดูคำถามที่เกี่ยวข้องนี้และโดยเฉพาะคำตอบนี้
Gras Double

1
ซ้ำซ้อนที่เป็นไปได้ของPHP exec () vs system () vs passthru ()
jww

คำตอบ:


353

shell_execส่งคืนเอาต์พุตสตรีมทั้งหมดเป็นสตริง execส่งคืนบรรทัดสุดท้ายของเอาต์พุตตามค่าดีฟอลต์ แต่สามารถจัดเตรียมเอาต์พุตทั้งหมดเป็นอาร์เรย์ที่ระบุเป็นพารามิเตอร์ที่สอง

ดู


21
หากคุณต้องการ exit-value และเอาต์พุตทั้งหมดคุณอาจใช้ "exec" แทนการใช้ "shell_exec" เร็วที่สุดเท่าที่คุณผ่านพารามิเตอร์ออกไป "exec" มันจะเต็มไปด้วยเส้นของการส่งออกทุกคนก็ดูเหมือนว่าฉัน "exec" สามารถทุกอย่างของ "shell_exec" และอื่น ๆ :)
Preexo

4
@ daniel-a-white ฉันรู้ว่านี่เก่า แต่เป็นที่นิยมดังนั้นคุณควรแก้ไขคำตอบเพื่อสะท้อนความคิดเห็นที่ทำโดย @preexo - exec ()ยังมีความสามารถในการส่งคืนผลลัพธ์ทั้งหมดหากคุณใช้พารามิเตอร์ที่เป็นตัวเลือก . นอกจากนี้ไม่เกี่ยวข้องใครควรเกณฑ์มาตรฐานทั้งสองคำสั่งเพื่อดูว่าดีกว่าเพราะ @ preexo กล่าวว่า " มันดูเหมือนว่าฉันexec()สามารถ [ทำ] ทุกอย่างshell_exec()[สามารถ] และอื่น ๆ :) "
SimpleAnecdote

77

นี่คือความแตกต่าง หมายเหตุการขึ้นบรรทัดใหม่ในตอนท้าย

> 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) ""

หมายเหตุการใช้ที่ผู้ประกอบการ backtickshell_exec()เป็นเหมือน

ปรับปรุง:ฉันควรอธิบายว่าสุดท้าย ดูคำตอบนี้หลายปีต่อมาแม้ว่าฉันจะไม่รู้ว่าทำไมมันถึงปล่อยออกมา! แดเนียลอธิบายไว้ข้างต้น - เป็นเพราะexecคืนค่าบรรทัดสุดท้ายเท่านั้นและifconfigบรรทัดสุดท้ายจะว่างเปล่า


จะเกิดอะไรขึ้นหากมีข้อผิดพลาดเกิดขึ้นกับคำสั่ง .. ฉันได้รับข้อผิดพลาด / ไม่มีไฟล์หรือไดเรกทอรีดังกล่าว แต่ฉันจะจับมันไปยังตัวแปร ????
Happy Coder

@AlwinAugustin: ใช่มั้ย อาจถูกเขียนไปยัง STDERR ลองเพิ่ม2>&1ในตอนท้ายของคำสั่งของคุณเพื่อเปลี่ยนเส้นทาง STDERR ไปยัง STDOUT หากคุณใช้เครื่อง linux
mpen

ฉันได้เพิ่มมันยัง แต่ยังฉันได้รับ 0 เป็นค่า ฉันได้ใช้หนึ่งคำสั่ง wc -l และหากไฟล์ไม่ได้อยู่ที่นั่นฉันต้องได้รับข้อความแสดงข้อผิดพลาดว่าไม่มีไฟล์หรือไดเรกทอรีดังกล่าว
Happy Coder

50

shell_exec- ดำเนินการคำสั่งผ่านเปลือกและส่งกลับผลลัพธ์ที่สมบูรณ์เป็นสตริง

exec - ดำเนินการโปรแกรมภายนอก

ความแตกต่างคือเมื่อshell_execคุณได้รับผลลัพธ์เป็นค่าส่งคืน


4
สรุปรวบรัดดี! ควรสังเกตว่าexecส่งคืนบรรทัดสุดท้ายของเอาต์พุต หากต้องการคุณสามารถเลือกที่จะส่งผ่านอาร์เรย์เป็นพารามิเตอร์ที่สองเพื่อจับเอาท์พุทที่สมบูรณ์และจำนวนเต็มเป็นพารามิเตอร์ที่สามเพื่อจับค่าส่งคืนของคำสั่งเชลล์ซึ่งสามารถใช้สำหรับการตรวจสอบข้อผิดพลาด ข้อเสียที่ใหญ่ที่สุดshell_execคือมันส่งคืนค่า null หากคำสั่งล้มเหลวหรือหากไม่สร้างเอาต์พุตใด ๆ ดังนั้นค่าส่งคืนจะไม่สามารถใช้สำหรับการตรวจสอบข้อผิดพลาดได้อย่างน่าเชื่อถือ
Sean the Bean

38

ความแตกต่างเล็กน้อยที่ไม่ได้สัมผัสที่นี่:

  • ด้วย exec () คุณสามารถผ่านตัวแปรตัวแปรเสริมซึ่งจะได้รับอาร์เรย์ของบรรทัดเอาต์พุต ในบางกรณีสิ่งนี้อาจช่วยประหยัดเวลาโดยเฉพาะอย่างยิ่งหากเอาต์พุตของคำสั่งนั้นเป็นตารางอยู่แล้ว

เปรียบเทียบ:

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

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

ในทางกลับกันถ้าเอาต์พุตของคำสั่งคือ xml หรือ json การมีแต่ละบรรทัดเป็นส่วนหนึ่งของอาร์เรย์ไม่ใช่สิ่งที่คุณต้องการเนื่องจากคุณจะต้องประมวลผลอินพุตเป็นรูปแบบอื่นดังนั้นในกรณีนั้นให้ใช้ shell_exec .

มันก็คุ้มค่าที่จะชี้ให้เห็นว่า shell_exec เป็นนามแฝงสำหรับผู้ดำเนินการ backtic สำหรับผู้ที่เคยใช้ * ระวัง

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

exec ยังสนับสนุนพารามิเตอร์เพิ่มเติมที่จะให้รหัสส่งคืนจากคำสั่งดำเนินการ:

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

ดังที่บันทึกไว้ในหน้าคู่มือ shell_exec เมื่อคุณต้องการโค้ดส่งคืนจากคำสั่งที่ถูกเรียกใช้งานจริงคุณไม่มีทางเลือกนอกจากใช้ exec


3
นอกจากนี้: execให้คุณรับรหัสส่งคืนของคำสั่ง (ผ่าน&$return_varพารามิเตอร์) ในขณะที่shell_execไม่สามารถรับได้
Mark Amery

แม้ว่าคำตอบที่ได้รับการยอมรับนั้นถูกต้อง แต่ในความเห็นของฉันคำตอบนี้มีความสำคัญมากกว่า อาจเป็นคำตอบที่ดีที่สุดคือการรวมกันของทั้งสอง
UncaAlby
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.