เชลล์สคริปต์ยังคงทำงานโดยไม่มี #! (บรรทัด sha-bang)


10

ฉันใหม่สำหรับเชลล์สคริปต์และหนังสือจำนวนมากเขียนว่าใช้บรรทัด #! (sha-bang) ในการเริ่มต้นสคริปต์เพื่อเรียกล่ามและสิ่งนี้จะเรียกเชลล์ใหม่สำหรับสคริปต์และทำการแปลบรรทัดตามบรรทัด แต่อย่างใดอย่างหนึ่ง ของสคริปต์พื้นฐานของฉันยังคงทำงานอยู่โดยไม่มีสายเวทย์

ดังนั้นคำถามของฉันคือ:

  • สคริปต์พื้นฐานของฉันรับล่ามมาจากไหน
  • สคริปต์จัดการเพื่อค้นหาล่ามได้อย่างไร

ตอนนี้ให้ฉันบอกคุณเกี่ยวกับสคริปต์พื้นฐานของฉันมันมีเพียงบรรทัดต่อไปนี้:

echo "สคริปต์พื้นฐานไม่มีเส้นวิเศษ"


คำตอบ:


3

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


1
ใช่ .. อาจเป็นเพราะกระสุนปัจจุบันของฉันกำลังเรียกใช้เชลล์เริ่มต้นสำหรับเชลล์สคริปต์ที่ไม่มีหมายเลขเวทย์มนตร์
user1678213

1
@ user1678213 ใช่มันคือเชลล์ของคุณ (ไม่ใช่เคอร์เนล) ที่ทำสิ่งนี้
Gilles 'ดังนั้น - หยุดความชั่วร้าย'

1
ฉันเชื่อว่าคำสั่ง POSIX นั้นใช้ / bin / sh ในกรณีนี้
vonbrand

2
@ vonbrand นี่เป็นความเข้าใจผิดที่พบบ่อย POSIX ไม่ได้มอบอำนาจให้ POSIX เชลล์เป็น/bin/shเพียงเพื่อให้สามารถshประมวลผลได้ครั้งแรกที่พบในขณะที่สำรวจ PATH ที่สอดคล้องกัน
jlliagre

3
ไม่ถูกต้องไม่ใช่"เปลือกการเข้าสู่ระบบ"ที่ใช้ในการเรียกใช้งาน สิ่งที่สามารถเกิดขึ้นได้คือการที่เชลล์โทร (ถ้าสคริปต์ถูกเรียกจากเชลล์) อาจมีลูกของตัวเองตีความมัน
Stéphane Chazelas

8

เมื่อคุณรันโปรแกรมเคอร์เนลจะตรวจสอบว่ามันเริ่มต้นด้วยลำดับไบต์มายากลหรือไม่ หากไฟล์เรียกทำงานเริ่มต้นด้วย#!เคอร์เนลจะตีความส่วนที่เหลือของบรรทัดเป็นชื่อล่าม หากไฟล์เรียกทำงานเริ่มต้นด้วย\177ELF(โดยที่\177127 ไบต์) ไฟล์จะโหลดเป็นไฟล์ปฏิบัติการของELF นั่นเป็นชนิดปกติในระบบยูนิกซ์ส่วนใหญ่ในปัจจุบัน

หากเคอร์เนลไม่รู้จักรูปแบบไฟล์ก็จะปฏิเสธที่จะรันไฟล์และส่งกลับข้อผิดพลาด ENOEXEC (ข้อผิดพลาดรูปแบบ Exec) เมื่อเชลล์สังเกตเห็นว่ามันจะทำหน้าที่ตัวเองเพื่อรันโปรแกรมเป็นเชลล์สคริปต์

หากต้องการเห็นสิ่งนี้ในการดำเนินการให้เพิ่มคำสั่งบางอย่างลงในสคริปต์ของคุณ:

ps l $$
ls -l /proc/$$/exe
echo hello

(นี่สำหรับ Linux ปรับสำหรับ unices อื่น ๆ ) จากนั้นลองเรียกใช้สคริปต์นั้นจากเชลล์ต่างๆ คุณจะเห็นว่าบางเชลล์วางไข่อินสแตนซ์ใหม่ของตัวเองเพื่อรันสคริปต์ (bash, ksh93) ในขณะที่คนอื่นวางไข่/bin/sh(เส้นประ, pdksh, zsh)


ฉันจะมองหาอะไรด้วยls -lคำสั่งของคุณ? นี่: lrwxrwxrwx 1 i 0 Oct 11 05:15 exe -> /bin/bash- ถ้าเป็นเช่นนั้นมันพูดว่าอะไร? นอกจากนี้ยังสังเกตเห็นฉันมีSHELL=/bin/bashบนenvแต่เปลี่ยนไม่ได้ดูเหมือนจะเปลี่ยนแปลงพฤติกรรม บางทีมันอาจไม่เกี่ยวข้องกัน?
Emanuel Berg

ดูเหมือนว่าคุณกำลังเปลี่ยนตัวแปรเชลล์ "SHELL" ถ้าใช่แล้วคุณแค่เปลี่ยนค่าของตัวแปรเชลล์ SHELL.it ไม่เปลี่ยน chnge shell.for chnaging เชลล์แก้ไขไฟล์ / etc / passwd
user1678213

2
@EmanuelBerg ใช่ (จริง ๆ แล้วฉันควรจะเขียนls -l /proc/$$/exe) exeจุดเชื่อมโยงไปยังเปลือกที่รันสคริปต์ของคุณ เมื่อคุณเรียกใช้สคริปต์ของคุณคุณจะเห็นว่ามันทุบตีที่ตีความสคริปต์ หากคุณทำงานได้จากเช่น pdksh /bin/shมันวิ่ง ฉันไม่รู้เกี่ยวกับเชลล์ใด ๆ ที่ใช้SHELLตัวแปรสภาพแวดล้อมหรือล็อกอินเชลล์ในสถานการณ์นั้น
Gilles 'หยุดความชั่วร้าย'

2
@ user1678213 การเปลี่ยนเปลือกใน/etc/passwdการเปลี่ยนแปลงสิ่งที่เปลือกจะถูกดำเนินการเมื่อคุณเข้าสู่ระบบมากกว่า SSH หรือบนคอนโซลข้อความ มันไม่ได้เปลี่ยนเชลล์ที่อาจเรียกใช้สคริปต์
Gilles 'หยุดความชั่วร้าย'

2
@ user1678213 ฉันตรวจสอบสิ่งที่ฉันเขียนที่นี่โดยใช้การทดสอบ ไม่มีเปลือกหอยผมทดสอบมองในการตัดสินใจที่เปลือกจะใช้พวกเขาทั้งสองง่ามตัวอย่างของตัวเองหรือดำเนินการ/etc/passwd /bin/sh
Gilles 'หยุดความชั่วร้าย'

-2

มันอาจเป็นไปได้หนึ่งใน 3 ข้อต่อไปนี้:

  1. คุณกำลังเรียกใช้สคริปต์โดยตรงกับล่าม IE: bash script.sh

  2. ชื่อของไฟล์สคริปต์มีนามสกุล. sh ซึ่งทำให้ระบบค้นหาโปรแกรมเริ่มต้นสำหรับไฟล์ประเภทนี้

  3. สภาพแวดล้อมของเชลล์ที่คุณใช้งานอยู่นั้นกำลังรัน 'echo' ด้วยตัวเองเนื่องจากฉันสามารถเดาได้ว่าไฟล์สคริปต์นั้นสามารถเรียกใช้งานได้ ตัวอย่างเช่นหากคุณจะใช้ bash shell และมีคำสั่งในไฟล์ของคุณที่ใช้โดย ksh เท่านั้นคุณจะเห็นว่ามันใช้งานไม่ได้

โชคดี!


3
ฉันไม่ได้เรียกมันด้วยการทุบตีหรือด้วยการขยายใด ๆ
user1678213

1
และสภาพแวดล้อมของเชลล์ไม่ได้ดำเนินการเพราะเมื่อฉันเรียกใช้คำสั่ง ps หลังจากเรียกใช้สคริปต์ของฉัน คำสั่ง ps แสดงกระบวนการทุบตีสองกระบวนการซึ่งหมายความว่ามีการทุบตีสองครั้ง หนึ่งคือเปลือก bash สำหรับเข้าสู่ระบบของฉันและอีกอันหนึ่งคือทุบตีสำหรับ basic_script ของฉัน
user1678213

1
2: เคอร์เนลจะไม่ทำอะไรอย่างนั้น Zsh ทำได้และ bash สามารถบิดไปทำมันได้ 3: ใช่ แต่มันแตกต่างกันเล็กน้อยระหว่างเชลล์ดูคำตอบของฉัน
Gilles 'SO- หยุดความชั่วร้าย'
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.