เป็นไปได้ไหมที่จะมี shebang นั้นแทนที่จะระบุเส้นทางไปยังล่ามมันมีชื่อของล่ามและให้เชลล์ค้นหาผ่าน $ PATH หรือไม่
ถ้าไม่มีเหตุผลทำไม?
เป็นไปได้ไหมที่จะมี shebang นั้นแทนที่จะระบุเส้นทางไปยังล่ามมันมีชื่อของล่ามและให้เชลล์ค้นหาผ่าน $ PATH หรือไม่
ถ้าไม่มีเหตุผลทำไม?
คำตอบ:
การค้นหาเส้นทางเป็นคุณลักษณะของไลบรารี C มาตรฐานใน userspace เช่นเดียวกับตัวแปรสภาพแวดล้อมโดยทั่วไป เคอร์เนลไม่เห็นตัวแปรสภาพแวดล้อมยกเว้นเมื่อมันผ่านสภาพแวดล้อมจากผู้เรียกexecve
ไปยังกระบวนการใหม่
เคอร์เนลไม่ได้ทำการตีความใด ๆ บนเส้นทางในexecve
(มันขึ้นอยู่กับฟังก์ชั่นการห่อหุ้มเช่นexecvp
การค้นหา PATH) หรือใน shebang (ซึ่งมากหรือน้อยเส้นทางการexecve
โทรภายใน) ดังนั้นคุณต้องใส่เส้นทางที่แน่นอนในshebang¹ การปรับใช้ Shebang ดั้งเดิมนั้นเป็นโค้ดเพียงไม่กี่บรรทัดและไม่ได้มีการขยายอย่างมีนัยสำคัญตั้งแต่นั้นมา
ใน Unix เวอร์ชันแรกเชลล์ทำหน้าที่เรียกใช้งานตัวเองเมื่อพบว่าคุณกำลังเรียกใช้สคริปต์ Shebang ถูกเพิ่มเข้ามาในเคอร์เนลด้วยเหตุผลหลายประการ (สรุปเหตุผลโดย Dennis Ritchie :
shebangs ที่ไม่มี Path จะต้องเพิ่มเคอร์เนลเพื่อเข้าถึงตัวแปรสภาพแวดล้อมและกระบวนการPATH
หรือเพื่อให้เคอร์เนลรันโปรแกรม userspace ที่ทำการค้นหา PATH วิธีแรกต้องเพิ่มจำนวนความซับซ้อนให้กับเคอร์เนล วิธีที่สองคือแล้วเป็นไปได้ด้วยshebang#!/usr/bin/env
¹ หากคุณใส่เส้นทางแบบสัมพัทธ์มันจะแปลความหมายของไดเรกทอรีปัจจุบันของกระบวนการ (ไม่ใช่ไดเรกทอรีที่มีสคริปต์) ซึ่งไม่ค่อยมีประโยชน์ใน Shebang
execve
หรือใน shebang แม้ว่าจะมีเหตุผลเล็กน้อยที่จะมีเส้นทางสัมพัทธ์ใน shebang
/lib64/ld-linux-x86-64.so.2
(ดูldd
ผลลัพธ์) Linux ทำให้เป็นชื่อสามัญอย่างสมบูรณ์: binfmt
การสนับสนุน (ตั้งแต่ 2.1.43) ช่วยให้คุณสามารถลงทะเบียนคู่ล่ามพา ธ / พา ธ / หมายเลขมายากลหรือไฟล์นามสกุล คุณสามารถ.exe
เรียกใช้PE32 ได้wine
เมื่อคุณเรียกใช้คลาส Java และไฟล์ jar เรียกใช้java
ฯลฯ
มีอะไรเกิดขึ้นมากกว่าสบตา #!
บรรทัดถูกตีความโดยเคอร์เนล Unix หรือ Linux #!
ไม่ใช่ลักษณะของเชลล์ ซึ่งหมายความว่าPATH
ไม่มีอยู่จริงในขณะที่เคอร์เนลตัดสินใจว่าจะดำเนินการอะไร
วิธีที่ใช้กันมากที่สุดในการจัดการกับไม่ทราบซึ่งปฏิบัติการเรียกใช้หรือจะเรียกในแฟชั่นแบบพกพาหรือคล้ายกันคือการใช้งานperl
#!/usr/bin/env perl
เคอร์เนลดำเนินการ/usr/bin/env
ซึ่งสืบทอดPATH
ตัวแปรสภาพแวดล้อม env
ค้นหา (ในตัวอย่างนี้) perl
ในPATH
และใช้การexecve(2)
เรียกระบบเพื่อให้เคอร์เนลเรียกใช้perl
ไฟล์ปฏิบัติการ
$ strace sleep 1
execve("/usr/bin/sleep", ["sleep", "1"], [/* 99 vars */]) = 0
การแปลงเป็นพา ธ แบบเต็มทำโดยเชลล์ (ทั่วไปมากขึ้น: ใน userspace) เคอร์เนลต้องการชื่อไฟล์ / พา ธ ที่สามารถเข้าถึงได้โดยตรง
หากคุณต้องการให้ระบบค้นหาไฟล์สั่งการของคุณโดยดูผ่านตัวแปร PATH คุณสามารถเขียน shebang ของคุณใหม่#!/usr/bin/env EXEC
ได้
แต่ในกรณีนี้ไม่ใช่เคอร์เนลที่ทำการค้นหา
strace
(แปลงเป็น/usr/bin/strace
บางจุด) ด้วย 2 อาร์กิวเมนต์