เหตุใดไฟล์สคริปต์ทั้งหมดจึงเริ่มต้นด้วยไฟล์
#!/bin/sh
หรือด้วย
#!/bin/csh
จำเป็นหรือไม่ จุดประสงค์ของสิ่งนี้คืออะไร? แล้วทั้งสองต่างกันอย่างไร?
เหตุใดไฟล์สคริปต์ทั้งหมดจึงเริ่มต้นด้วยไฟล์
#!/bin/sh
หรือด้วย
#!/bin/csh
จำเป็นหรือไม่ จุดประสงค์ของสิ่งนี้คืออะไร? แล้วทั้งสองต่างกันอย่างไร?
คำตอบ:
สิ่งนี้เรียกว่าShebang
:
http://en.wikipedia.org/wiki/Shebang_(Unix)
#! ล่าม [ตัวเลือก - อาร์กิวเมนต์]
Shebang จะเกี่ยวข้องก็ต่อเมื่อสคริปต์มีสิทธิ์ในการดำเนินการ (เช่น chmod u + x script.sh)
เมื่อเชลล์รันสคริปต์จะใช้ตัวแปลที่ระบุ
ตัวอย่าง:
#!/bin/bash
# file: foo.sh
echo 1
$ chmod u+x foo.sh
$ ./foo.sh
1
#!
เส้นบอกเคอร์เนล (โดยเฉพาะการดำเนินงานของexecve
ระบบโทร) ว่าโปรแกรมนี้ถูกเขียนในภาษาแปล; ชื่อพา ธ สัมบูรณ์ที่ตามหลังระบุตัวแปล โปรแกรมที่คอมไพล์เป็นรหัสเครื่องจะเริ่มต้นด้วยลำดับไบต์ที่แตกต่างกัน - บน Unixes ที่ทันสมัยที่สุด7f 45 4c 46
( ^?ELF) ซึ่งระบุว่าเป็นเช่นนั้น
คุณสามารถวางเส้นทางสัมบูรณ์ไปยังโปรแกรมใดก็ได้ที่คุณต้องการหลังจาก#!
นั้นตราบใดที่โปรแกรมนั้นไม่ใช่#!
สคริปต์ เคอร์เนลเขียนการเรียกใหม่ของ
./script arg1 arg2 arg3 ...
โดย./script
เริ่มต้นด้วยพูด#! /usr/bin/perl
ราวกับว่าบรรทัดคำสั่งเป็นจริง
/usr/bin/perl ./script arg1 arg2 arg3
หรือตามที่คุณได้เห็นคุณสามารถใช้ในการเขียนสคริปต์ตั้งใจที่จะตีความโดย#! /bin/sh
sh
#!
สายการประมวลผลเฉพาะถ้าคุณโดยตรงเรียกใช้สคริปต์ ( ./script
ในบรรทัดคำสั่ง); ไฟล์ต้องสามารถเรียกใช้งานได้ด้วย ( chmod +x script
) ถ้าคุณทำสายไม่จำเป็น (และจะถูกละเว้นถ้ามี) และไฟล์ไม่ต้องมีการปฏิบัติการ จุดของคุณลักษณะที่จะช่วยให้คุณโดยตรงเรียกใช้โปรแกรมตีความภาษาโดยไม่ต้องรู้ว่าสิ่งที่ภาษาที่พวกเขาจะถูกเขียนใน. (Do - คุณจะพบว่าโปรแกรมที่ดีหุ้นจำนวนมากในความเป็นจริงการใช้คุณลักษณะนี้.)sh ./script
#!
grep '^#!' /usr/bin/*
กฎบางประการในการใช้คุณลักษณะนี้มีดังนี้
#!
ต้องเป็นสองคนแรกมากไบต์ในแฟ้ม โดยเฉพาะอย่างยิ่งไฟล์จะต้องอยู่ในการเข้ารหัสที่เข้ากันได้กับ ASCII (เช่น UTF-8 จะทำงานได้ แต่ UTF-16 จะไม่ทำงาน) และต้องไม่ขึ้นต้นด้วย "เครื่องหมายลำดับไบต์" มิฉะนั้นเคอร์เนลจะไม่รู้จักว่าเป็น#!
สคริปต์#!
ต้องเป็นเส้นทางสัมบูรณ์ (เริ่มต้นด้วย/
) ไม่สามารถมีช่องว่างแท็บหรืออักขระขึ้นบรรทัดใหม่#!
/
อย่าใส่มากกว่าหนึ่งช่องที่นั่น#!
บรรทัดได้พวกมันจะไม่ถูกขยาย#! /usr/bin/awk -f
) บางครั้งมันก็มีประโยชน์ ( #! /usr/bin/perl -Tw
) น่าเสียดายที่คุณไม่สามารถใส่อาร์กิวเมนต์สองตัวขึ้นไปหลังพา ธ สัมบูรณ์ได้#! /usr/bin/env interpreter
แทน#! /absolute/path/to/interpreter
. นี่เป็นความผิดพลาดเกือบตลอดเวลา มันทำให้พฤติกรรมของโปรแกรมของคุณขึ้นอยู่กับ$PATH
ตัวแปรของผู้ใช้ที่เรียกใช้สคริปต์ และไม่ใช่ทุกระบบenv
ในตอนแรกsetuid
หรือsetgid
สิทธิพิเศษนี้ไม่สามารถใช้#!
; ต้องรวบรวมเป็นรหัสเครื่อง (หากคุณไม่รู้ว่าอะไรsetuid
คืออะไรอย่ากังวลกับสิ่งนี้)เกี่ยวกับcsh
มันเกี่ยวข้องกับsh
โดยประมาณอย่างที่ Nutrimat Advanced Tea Substituteทำกับชา แต่ก็มี (หรือมากกว่ามี; การใช้งานที่ทันสมัยของsh
ได้จับขึ้นไป) จำนวนหนึ่งได้เปรียบกว่าsh
สำหรับการใช้งานแบบโต้ตอบ แต่ใช้มัน (หรือลูกหลานของมันtcsh
) สำหรับการเขียนสคริปต์คือมักจะผิดพลาด sh
หากคุณกำลังใหม่ที่จะเปลือกสคริปต์โดยทั่วไปผมขอแนะนำให้คุณไม่สนใจมันและมุ่งเน้น หากคุณกำลังใช้csh
ญาติเป็นเชลล์ล็อกอินของคุณให้เปลี่ยนไปใช้bash
หรือzsh
เพื่อให้ภาษาคำสั่งแบบโต้ตอบจะเหมือนกับภาษาสคริปต์ที่คุณกำลังเรียนรู้
#!
; ไม่มีความคิดเห็นว่าเป็นสไตล์ที่ดีหรือไม่ ดูคำถามนี้และคำตอบของฉันสำหรับการอภิปรายข้อดีข้อเสียของการ#!/usr/bin/env
แฮ็ก
#!/usr/bin/env
ถูกต้องคือ แต่ฉันยังคงมีความเห็นว่ามันเป็นความคิดที่ไม่ดี
สิ่งนี้กำหนดเชลล์ (ตัวแปลคำสั่ง) ที่คุณใช้สำหรับการตีความ / รันสคริปต์ของคุณ แต่ละเชลล์มีความแตกต่างกันเล็กน้อยในวิธีที่มันโต้ตอบกับผู้ใช้และรันสคริปต์ (โปรแกรม)
เมื่อคุณพิมพ์คำสั่งที่พรอมต์ Unix แสดงว่าคุณกำลังโต้ตอบกับเชลล์
เช่น#!/bin/csh
หมายถึง C-shell, /bin/tcsh
t-shell, /bin/bash
bash shell เป็นต้น
คุณสามารถบอกได้ว่าคุณใช้เชลล์แบบโต้ตอบใด
echo $SHELL
คำสั่งหรืออีกทางหนึ่ง
env | grep -i shell
คุณสามารถเปลี่ยนเชลล์คำสั่งของคุณด้วยchsh
คำสั่ง
แต่ละชุดมีชุดคำสั่งและวิธีการกำหนดตัวแปรและชุดโครงสร้างการเขียนโปรแกรมที่แตกต่างกันเล็กน้อย ตัวอย่างเช่นคำสั่ง if-else ที่มี bash ดูแตกต่างจากคำสั่งใน C-shell
หน้านี้อาจเป็นที่สนใจเนื่องจาก "แปล" ระหว่างคำสั่ง bash และ tcsh / ไวยากรณ์
การใช้คำสั่งในเชลล์สคริปต์ช่วยให้คุณรันโปรแกรมโดยใช้เชลล์อื่น ตัวอย่างเช่นฉันใช้tcsh
เชลล์แบบโต้ตอบ แต่มักจะเรียกใช้สคริปต์ bash โดยใช้ / bin / bash ในไฟล์สคริปต์
นอกเหนือจาก:
แนวคิดนี้ขยายไปยังสคริปต์อื่น ๆ ด้วย ตัวอย่างเช่นหากคุณตั้งโปรแกรมใน Python คุณจะต้องใส่
#!/usr/bin/python
ที่ด้านบนสุดของโปรแกรม Python
#! $SHELL
หรือไม่? สิ่งนี้จะใส่เชลล์ที่ถูกต้องใน Shebang หรือไม่?
!#/bin/bash
คำสั่ง มันบอกระบบว่าจะใช้เชลล์อะไรในการรันเชลล์สคริปต์ของคุณ
$SHELL
ไม่จำเป็นต้องบอกคุณว่าคุณกำลังใช้เชลล์ใดอยู่ในขณะนี้ โดยปกติจะบอกเชลล์เริ่มต้นของคุณ ชุด tcsh $version
และ$tcsh
; $BASH_VERSION
ชุดทุบตี ไม่ใช่ทุกเปลือกที่จำเป็นต้องมีกลไกที่คล้ายกัน
#!
บรรทัดต้องตรงกับไวยากรณ์ของสคริปต์ไม่ใช่เชลล์แบบโต้ตอบที่ใช้โดยใครก็ตามที่เรียกใช้สคริปต์
#!/bin/csh -f
; คำสั่ง-f
บอกเชลล์ไม่ให้แหล่งที่มาของผู้ใช้.login
และ.cshrc
ทำให้สคริปต์ทำงานได้เร็วขึ้นและหลีกเลี่ยงการพึ่งพาการตั้งค่าของผู้ใช้ (หรือดีกว่านั้นอย่าเขียนสคริปต์ csh) อย่าใช้-f
สำหรับสคริปต์ sh หรือ bash มันไม่ได้มีความหมายเหมือนกัน