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


312

อะไรคือความแตกต่าง?

มีสถานการณ์หรือเหตุผลที่เฉพาะเจาะจงสำหรับแต่ละฟังก์ชั่นหรือไม่? ถ้าใช่คุณสามารถยกตัวอย่างสถานการณ์เหล่านั้นได้ไหม

PHP.net บอกว่าพวกมันถูกใช้เพื่อรันโปรแกรมภายนอก ดูการอ้างอิง จากตัวอย่างที่ฉันเห็นฉันไม่เห็นความแตกต่างที่ชัดเจน

หากฉันเพียงแค่เรียกใช้สคริปต์ (bash หรือ python) คุณแนะนำให้ใช้ฟังก์ชันใด


16
นอกจากนี้ยังมีproc_open()และpopen()ทั้งสองอย่างนี้ช่วยให้การควบคุมระดับสูงกว่ากระบวนการวางไข่
คริสเตียน

คำตอบ:


195

พวกเขามีวัตถุประสงค์ที่แตกต่างกันเล็กน้อย

  • exec() ใช้สำหรับเรียกคำสั่งระบบและอาจจัดการกับผลลัพธ์ด้วยตัวคุณเอง
  • system() ใช้สำหรับเรียกใช้งานคำสั่งระบบและแสดงผลข้อความ - ทันที
  • passthru() สำหรับการดำเนินการคำสั่งระบบที่คุณต้องการคืนผลตอบแทนจาก - สันนิษฐานว่าบางสิ่งบางอย่างไบนารี

โดยไม่คำนึงถึงฉันขอแนะนำให้คุณไม่ใช้พวกเขาใด ๆ พวกเขาทั้งหมดผลิตรหัสไม่สามารถแปลได้สูง


147
บางครั้งการพกพาจะต้องเสียสละเพื่อการทำงาน มีบางสิ่งที่ PHP ไม่สามารถทำได้ดี
แฟรงก์ Crook

30
@Kalium: คุณสามารถเพิ่มเติมรายละเอียดเพิ่มเติมในคำสั่งของคุณ? เพียงระบุสถิติร้อยละคลุมเครือไม่เชื่อฉัน ฉันเชื่อว่าการใช้การเรียกของระบบเพื่อเรียกใช้งานสคริปต์นั้นใช้ได้อย่างสมบูรณ์ตราบใดที่แอปพลิเคชันทั้งหมดไม่ได้พึ่งพาสคริปต์หนึ่ง ๆ ในแบ็คเอนด์
codingbear

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

5
@OZ_ ฉันมาถึงสถานการณ์ที่ต้องคำนวณราคาแพงมาก ไม่มี PHP-Module ที่มีอยู่ (สำหรับ) ฉันเขียนโปรแกรม C ของฉันเองและฉันเรียกใช้ด้วย passthru () บางครั้งการพกพาอาจมีความสำคัญน้อยกว่าสิ่งอื่น ๆ ขึ้นอยู่กับโครงการ
เปาโล

9
นอกจากนี้ก็เป็นความเข้าใจผิดที่จะคิดว่า PHP เป็นแบบพกพาได้นานเท่าที่คุณหลีกเลี่ยงexec, ,system passthruโค้ด PHP นั้นขึ้นอยู่กับสภาพแวดล้อมที่มันใช้งานและข้อผิดพลาดด้านความปลอดภัยจำนวนมากเกิดจากการไม่มีสิ่งนี้ในการพิจารณา นี่คือตัวอย่างรวดเร็ว: stackoverflow.com/questions/3003145/…
Pacerier

131

ตามที่ดึงมาจาก http://php.net/ && Chipmunkninja :

ระบบ ()ฟังก์ชั่น

ฟังก์ชั่นระบบใน PHP รับอาร์กิวเมนต์สตริงด้วยคำสั่งเพื่อดำเนินการเช่นเดียวกับอาร์กิวเมนต์ใด ๆ ที่คุณต้องการส่งผ่านไปยังคำสั่งนั้น ฟังก์ชันนี้เรียกใช้งานคำสั่งที่ระบุและทิ้งข้อความที่เป็นผลลัพธ์ไปยังเอาต์พุตสตรีม (ทั้งเอาต์พุต HTTP ในสถานการณ์ของเว็บเซิร์ฟเวอร์หรือคอนโซลหากคุณใช้ PHP เป็นเครื่องมือบรรทัดคำสั่ง) การกลับมาของฟังก์ชั่นนี้เป็นบรรทัดสุดท้ายของเอาต์พุตจากโปรแกรมหากมันส่งเสียงออกข้อความ

exec ()ฟังก์ชั่น

ฟังก์ชั่นระบบค่อนข้างมีประโยชน์และทรงพลัง แต่หนึ่งในปัญหาที่ใหญ่ที่สุดคือข้อความทั้งหมดที่ได้จากโปรแกรมไปยังสตรีมเอาต์พุตโดยตรง จะมีสถานการณ์ที่คุณอาจต้องการจัดรูปแบบข้อความที่เป็นผลลัพธ์และแสดงในลักษณะที่แตกต่างกันหรือไม่แสดงเลย

สำหรับเรื่องนี้ฟังก์ชั่น exec ใน PHP ถูกดัดแปลงอย่างสมบูรณ์ แทนที่จะทิ้งข้อความทั้งหมดที่สร้างโดยโปรแกรมที่กำลังดำเนินการไปยังเอาต์พุตสตรีมโดยอัตโนมัติจะเปิดโอกาสให้คุณใส่ข้อความนี้ในอาร์เรย์ที่ส่งคืนในพารามิเตอร์ที่สองไปยังฟังก์ชัน:

shell_exec ()ฟังก์ชั่น

โปรแกรมส่วนใหญ่ที่เราดำเนินการอยู่ในขณะนี้มีอยู่จริงหรือไม่ก็โปรแกรมจริง 1 อย่างไรก็ตามสภาพแวดล้อมที่ผู้ใช้ Windows และ Unix ทำงานได้ดีขึ้นกว่านี้มาก ผู้ใช้ Windows มีตัวเลือกในการใช้โปรแกรม Windows Command Prompt, cmd.exe โปรแกรมนี้เรียกว่าเชลล์คำสั่ง

passthru ()ฟังก์ชั่น

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

The proc_open ()ฟังก์ชั่นและpopen () ฟังก์ชั่น

proc_open () คล้ายกับ popen () แต่ให้การควบคุมการเรียกใช้โปรแกรมในระดับที่สูงกว่ามาก cmd เป็นคำสั่งที่จะดำเนินการโดยเชลล์ descriptorspec เป็นอาร์เรย์ที่จัดทำดัชนีโดยที่ปุ่มแทนหมายเลขตัวอธิบายและค่าแสดงถึงวิธีที่ PHP จะส่งตัวบอกถึงกระบวนการของลูก ไพพ์จะถูกตั้งค่าเป็นอาเรย์ของดัชนีพอยน์เตอร์ที่สอดคล้องกับจุดสิ้นสุดของไพพ์ของ PHP ที่สร้างขึ้น ค่าส่งคืนเป็นทรัพยากรที่แสดงถึงกระบวนการ คุณควรทำให้ว่างโดยใช้ proc_close () เมื่อคุณทำเสร็จแล้ว


6
ความเร็วในการประมวลผลของ shell_exec นั้นเร็วกว่าทางเลือกอื่น
Dinesh Saini

29
คุณควรจะพูดถึงว่าคุณได้คัดลอกคำตอบของคุณได้โดยตรงจากChipmunkNinja
TachyonVortex

7
@TachyonVortex โชคดีที่เขาคัดลอกคำตอบคำต่อคำเพราะ ChipmunkNinja ไม่มีอยู่อีกต่อไป
Phileo99

2
มีสำเนาของบทความนั้นในเครื่อง wayback: web.archive.org/web/20130809032648/http://chipmunkninja.com/…
bagonyi

2
แล้ว popen และ proc_open ล่ะ?
CMCDragonkai

103

คำตอบก่อนหน้าดูเหมือนจะสับสนเล็กน้อยหรือไม่สมบูรณ์ดังนั้นนี่คือตารางความแตกต่าง ...

+----------------+-----------------+----------------+----------------+
|    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             |
+----------------+-----------------+----------------+----------------+
  • "แสดงผลลัพธ์" หมายถึงสตรีมเอาต์พุตไปยังเบราว์เซอร์ (หรือเอาต์พุตบรรทัดคำสั่งหากเรียกใช้จากบรรทัดคำสั่ง)
  • "สามารถรับเอาท์พุท" หมายความว่าคุณสามารถรับเอาท์พุทของคำสั่งและกำหนดให้กับตัวแปร PHP
  • "exit code" เป็นค่าพิเศษที่ส่งคืนโดยคำสั่ง (หรือเรียกว่า "สถานะการส่งคืน") ศูนย์มักจะหมายความว่ามันสำเร็จแล้วค่าอื่น ๆ มักจะเป็นรหัสข้อผิดพลาด

สิ่งอื่น ๆ ที่ต้องระวัง:

  • shell_exec () และตัวดำเนินการ backticks ทำสิ่งเดียวกัน
  • นอกจากนี้ยังมี proc_open () และ popen () ซึ่งช่วยให้คุณสามารถอ่าน / เขียนสตรีมแบบโต้ตอบด้วยคำสั่งการดำเนินการ
  • เพิ่ม "2> & 1" ลงในสตริงคำสั่งหากคุณต้องการจับภาพ / แสดงข้อความแสดงข้อผิดพลาด
  • ใช้ escapeshellcmd () เพื่อหนีการโต้แย้งคำสั่งที่อาจมีตัวอักษรปัญหา
  • หากผ่านตัวแปร $ output ไปยัง exec () เพื่อเก็บเอาท์พุทถ้า $ output ไม่ว่างเปล่ามันจะผนวกเอาท์พุทใหม่เข้าไป ดังนั้นคุณอาจต้องยกเลิกการตั้งค่า ($ output) ก่อน

อันไหนที่สามารถรันไฟล์ php ได้?
johny ทำไม

1
@ johnywhy ไม่มีต่อ se - เว้นแต่คุณจะเรียก php cli หรืออย่างชัดเจน ฉันคิดว่าคุณต้องการincludeและเพื่อน ๆ
Hagen von Eitzen

21

ทุกอย่างมาถึงวิธีที่คุณต้องการจัดการเอาต์พุตที่คำสั่งอาจส่งคืนและไม่ว่าคุณต้องการให้สคริปต์ PHP ของคุณรอให้โปรแกรม callee สิ้นสุดหรือไม่

  • exec ดำเนินการคำสั่งและส่งออกไปยังผู้โทร (หรือส่งกลับในตัวแปรเสริม)

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

  • system รันโปรแกรมภายนอกและแสดงผล แต่เฉพาะบรรทัดสุดท้าย

หากคุณต้องการดำเนินการคำสั่งและให้ข้อมูลทั้งหมดจากคำสั่งส่งกลับโดยตรงโดยไม่รบกวนให้ใช้passthru()ฟังก์ชัน


8

หากคุณใช้งานสคริปต์ PHP จากบรรทัดคำสั่งคุณpassthru()จะได้รับประโยชน์มากมาย มันจะช่วยให้คุณสามารถรันสคริปต์ / โปรแกรมเช่นvim,dialogฯลฯ ให้โปรแกรมเหล่านั้นควบคุมการจับและกลับไปสคริปต์ของคุณเฉพาะเมื่อพวกเขาจะทำ

ถ้าคุณใช้system()หรือexec()เพื่อรันสคริปต์ / โปรแกรมเหล่านั้นจะไม่สามารถใช้งานได้

Gotcha: ด้วยเหตุผลบางอย่างคุณไม่สามารถใช้งานlessด้วยpassthru()PHP ได้


1
ฉันไม่เข้าใจสิ่งที่คุณพูด คุณสามารถรันโปรแกรมทั้งจาก CLI และ (F) CGI (เช่นเดียวกับ mod_php) อาจมีข้อ จำกัด ที่ระบบกำหนดเช่น selinux แต่ระบบการตั้งค่าที่ดีจะช่วยให้ผู้ที่เลือกปิด แน่นอนว่าโฮสต์ที่ใช้ร่วมกันเป็นเรื่องที่แตกต่างกัน แต่คุณจะไม่เสนอสภาพแวดล้อมที่ใช้ร่วมกันให้กับลูกค้าที่ได้รับความนิยมเช่นกันไม่ใช่หรือ?
Christian
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.