.sh ระบุส่วนขยายหรือไม่


12

ทำไมบางระบบจะเรียกใช้.shไฟล์เพียงแค่ระบุชื่อไฟล์โดยไม่ต้องมีนามสกุลและอื่น ๆ จำเป็นต้องใช้ชื่อรวมทั้งนามสกุล? ในกรณีของฉันฉันพยายามที่จะเขียนชุดคำสั่งต่อไปนี้คำแนะนำ

ฉันกำลังระบุส่วนขยายตอนนี้ แต่ความสามารถในการเรียกใช้คำสั่งโดยไม่.shต้องการจะดีกว่า


4
ใช้.shเป็นส่วนขยายอยู่ในสถานการณ์ที่หลายคนคิดว่าการปฏิบัติที่ไม่ดี: มันขัดกับวิธีการที่คำสั่งอื่น ๆ ที่มีชื่อ (คุณไม่ได้ทำงานls.elf) ก็มักจะเข้าใจผิด (ถ้าคุณfoo.shเริ่มต้นด้วย#!/bin/bashแล้วการทำงานsh foo.shจะทำงานกับล่ามที่แตกต่างกว่าที่มันสร้างขึ้นมาเพื่อ ) และถ้าคุณเขียนใหม่foo.shเป็นโปรแกรม Python การใช้ส่วนขยายนั้นหมายความว่าคุณต้องเลือกระหว่างการรักษาชื่อที่ทำให้เข้าใจผิดในขณะนี้และเขียนใหม่ทุกโปรแกรมที่เรียกใช้
Charles Duffy

2
... ที่ซึ่งเป็นแนวปฏิบัติที่ดีที่สุดคือเชลล์ไลบรารีไม่ใช่คำสั่งที่มี+xset - ที่ไหนfoo.shคือไลบรารีที่สามารถหาแหล่งที่มาลงในเชลล์ POSIX ใด ๆfoo.bashสามารถหาได้จาก bash, foo.kshksh เป็นต้น
Charles Duffy

คำตอบ:


39

คุณกำลังสับสน .shนามสกุลเป็นเพียงคำใบ้ต่อมนุษย์และมีอย่างไม่มีผลกระทบต่อวิธีการที่ระบบจัดการไฟล์ Unix / Linux ไม่ได้ทำให้Secrets.pdf.exeความผิดพลาด ของ Windows

นี่คือสิ่งที่เกิดขึ้นเมื่อคุณพิมพ์foo:

  1. การเปลี่ยนเส้นทางสำหรับSTDIN, STDOUTและSTDERRมีการตั้งค่า

  2. เชลล์ตรวจสอบตารางแฮชภายในเพื่อดูว่ามันรู้$PATHรายการfooแล้วหรือไม่ หากไม่มีอยู่เชลล์จะค้นหาไดเร็กทอรี$PATHโดยมองหาไฟล์ชื่อfooที่มี Execute บิตที่ตั้งค่าในสิทธิ์การใช้ไฟล์ fooชัยชนะครั้งแรก

  3. หากสองไบต์แรกของไฟล์fooคือ#!สตริงถัดไปคือชื่อของล่ามที่จะเรียกใช้ ดังนั้น#!/bin/bashแนะนำสคริปต์ Bash #!/usr/bin/perlแนะนำสคริปต์ Perl ฯลฯ

  4. หากไฟล์เริ่มต้นด้วย\177ELFมันเป็นไบนารีที่ปฏิบัติการได้และld.soเริ่มต้นมัน

อ่านman execveและman ld.soสำหรับคำอธิบายโดยละเอียดเพิ่มเติม


15
ใช่บน Linux คุณสามารถคลิกสองครั้งที่ Secrets.pdf โดยไม่มีเงื่อนงำจากชื่อที่ใช้งานได้จริง)
OrangeDog

1
@ OrangeDog ฉันรู้ว่าคุณล้อเล่น แต่ฉันรู้สึกว่าฉันต้องชี้ให้เห็นว่าบิตที่ปฏิบัติการได้ ( chmod +x) ค่อนข้างแก้ปัญหานี้ใช่ไหม?
wchargin

3
@WChargin ขึ้นอยู่กับความประพฤติของระบบไฟล์ของคุณ (เช่นการแชร์เครือข่ายที่ติดตั้งอยู่หรือพาร์ติชั่น NTFS อาจตั้งค่าxบิตทุกอย่างในแง่ดี) และที่มาของไฟล์ (กระบวนการใด ๆ ที่ควบคุมไดเรกทอรีจะถูกหลอกให้ตั้งค่าสิทธิ์) . ดังนั้นมันจะลดลงแต่ฉันจะไม่บอกว่ามันจะแก้ปัญหาได้
IMSoP

2
@WChargin แต่ฉันคิดว่าประเด็นของเขาที่โดยปกติแล้วตัวจัดการไฟล์จะไม่แสดงบิตที่ใช้งานได้นั่นคือไม่มี "คำใบ้สำหรับมนุษย์" เหมือนกับส่วนขยาย
Paul Draper

1
ฉันไม่เคยผิดพลาดคลิกที่Secrets.pdf.exeเพราะฉันมักจะปิดการใช้งานโง่hide file extensionคุณลักษณะ
phuclv

12

จุดสำคัญคือ: ส่วนขยายที่ไม่เกี่ยวข้องใด ๆ ในยูนิกซ์เช่นระบบ system.A ชื่อไฟล์เป็นเพียงชื่อและไม่มีผลกระทบหรือไม่ว่าสคริปต์หรือรวบรวมวิ่งสามารถปฏิบัติการได้ โปรแกรมเมอร์อาจเพิ่ม.shส่วนขยายเพื่อกำหนดว่าไฟล์เป็นเชลล์สคริปต์หรือ.pyสำหรับสคริปต์ไพ ธ อน แต่ไม่เหมือนกับ Windows ยูนิกซ์ใด ๆ ที่ไม่สนใจการตั้งชื่อ แต่ก็มีความสำคัญกับการอนุญาต

สิ่งสำคัญคือสิทธิ์ในการเรียกใช้ที่อนุญาตให้กับไฟล์ ซึ่งคุณสามารถตรวจสอบด้วย

ls -l /path/to/file

กำลังเรียกใช้ไฟล์ปฏิบัติการ

ในการเรียกใช้สคริปต์โดยทั่วไปมีหลายวิธี

  • ./my_script_nameหากไดเรกทอรีปัจจุบันของคุณเป็นเช่นเดียวกับสคริปต์และสคริปต์มีสิทธิ์ปฏิบัติการคุณสามารถเรียกใช้มันชอบดังนั้น .หมายถึงไดเรกทอรีปัจจุบัน
  • หากไดเรกทอรีปัจจุบันของคุณแตกต่างกันและสคริปต์มีสิทธิ์ในการเรียกใช้งานคุณสามารถเรียกใช้งานได้โดยระบุพา ธ เต็ม: /home/user/bin/my_script_name

(ข้างต้นสองวิธีพึ่งพามีการตั้งค่าสิทธิ์ปฏิบัติการ; หรือไม่ว่าไฟล์เป็นส่วนหนึ่งของ$PATHตัวแปรที่ไม่เกี่ยวข้องการแสดงตนของ. #!สายยังเรื่อง; โดยไม่ต้องมันสคริปต์ที่จะได้รับการดำเนินการโดยเปลือกปัจจุบันคุณมีเปิดถ้าผมมี. cshสคริปต์ ไม่มีบรรทัดนั้นและพยายามเรียกใช้ด้วยการทุบตีด้วย./my_script.cshมันจะล้มเหลว)

  • หากสคริปต์ของคุณอยู่ในไดเรกทอรีที่เป็นส่วนหนึ่งของ$PATHตัวแปรของคุณคุณสามารถเรียกใช้ได้เพียงแค่เรียกชื่อ คุณสามารถเรียกchmodคำสั่งในบรรทัดคำสั่งเพียงแค่พิมพ์ชื่อเพราะมันอยู่ใน/binโฟลเดอร์ /binเป็นส่วนหนึ่งของ$PATHตัวแปรเสมอ ในกรณีนี้สิทธิ์ในการเรียกใช้งานและตำแหน่งของสคริปต์
  • การระบุล่ามเป็นคำสั่งและสคริปต์เป็นอาร์กิวเมนต์ สคริปต์ดังกล่าวจะทำหน้าที่เป็นไฟล์อินพุตไปยังล่าม
  • การจัดหาไฟล์ . filename.shหรือsource filename.shจะทำให้สคริปต์ที่ได้รับการปฏิบัติราวกับว่ามันเป็นคีย์บอร์ดคือเป็นถ้ามันเป็นพิมพ์ลงในบรรทัดคำสั่งโดยตรง ในกรณีนี้สิทธิ์การใช้งานและตำแหน่งจะไม่สำคัญ

ตัวอย่าง

ตัวอย่างที่ 1, ใช้งานล่ามเพื่อดำเนินการอนุญาต

$-> ls -l abc.py                                                               
-rw-rw-r-- 1 xieerqi xieerqi 44 Apr 27 22:39 abc.py
$-> python abc.py                                                              
a
b
c

ตัวอย่าง # 2, รันด้วย./ชุดอนุญาตให้ใช้สิทธิ์, ชุดบรรทัด shebang

$-> cat abc.py                                                                 
#!/usr/bin/env python
for letter in 'a' 'b' 'c' :
   print letter
$-> ls -l abc.py
-rwxrwxr-x 1 xieerqi xieerqi 66 Apr 27 23:02 abc.py*
$-> ./abc.py                                                                   
a
b
c

ตัวอย่าง # 3 ทำงานโดยไม่มีชุดบรรทัด shebang (ล้มเหลวเนื่องจากทุบตีไม่สามารถอ่านสคริปต์ python ได้ไม่มีบรรทัด shebang ถือว่าเชลล์ปัจจุบันเป็นล่าม)

$-> cat abc.py                                                                 
for letter in 'a' 'b' 'c' :
   print letter
$-> ./abc.py                                                                   
./abc.py: 2: ./abc.py: Syntax error: word unexpected (expecting "do")

ตัวอย่าง # 4 การเรียกใช้สคริปต์ที่มีสิทธิ์อนุญาตในการเรียกใช้งานตั้งค่าโฟลเดอร์ฟอร์มที่เป็นส่วนหนึ่งของ$PATHตัวแปร

#  /home/xieerqi/bin is part of my path variable
$-> echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/opt/microchip/xc16/v1.25/bin:/opt/microchip/xc32/v1.40/bin:/opt/microchip/xc8/v1.35/bin:/home/xieerqi/bin:/home/xieerqi/bin/sh

$-> # current directory is /home/xieerqi
$-> pwd
/home/xieerqi
$-> # move the file to ~/bin
$-> mv ~/abc.py ~/bin/abc.py
$-> # now I can run it just by calling the name
$-> abc.py
/home/xieerqi/bin/abc.py: 2: /home/xieerqi/bin/abc.py: Syntax error: word unexpected (expecting "do")
$-> # Syntax error because again, no interpreter specified.                    
$-> # must add #!/usr/bin/env python
$-> vi /home/xieerqi/bin/abc.py          
$-> # after adding the line with vi text editor, we can run
$-> abc.py                                                                     
a
b
c

ตัวอย่าง # 5 การลบส่วนขยายยังคงทำงานเนื่องจากส่วนขยายไม่สำคัญ แต่ก็มีสิทธิ์และเป็นส่วนหนึ่งของ$PATH:

$-> mv ~/bin/abc.py  ~/bin/abc                                                 
$-> abc
a
b
c

ฉันรันคำสั่งและได้รับ '-rwxr-x ---' ฉันต้องการให้ค่าอ่านอะไรและฉันจะเปลี่ยนได้อย่างไร
Philip Kirkbride

หรือว่าคุณบอกว่าฉันควรเปลี่ยนชื่อ 'filename.sh' เป็น 'filename'?
Philip Kirkbride

1
@PhilipKirkbride ชื่อไม่เกี่ยวข้อง คุณรันคำสั่งของคุณอย่างไร? มันอยู่ที่ไหน ? ไดเรกทอรีอยู่ในส่วนของคุณPATHหรือไม่?
Sergiy Kolodyazhnyy

@PhilipKirkbride ให้ฉันขยายคำตอบของฉันในหนึ่งนาทีเพื่อให้ชัดเจนขึ้น
Sergiy Kolodyazhnyy

1
ลองดูที่man chmodวิธีการตั้งค่าการอนุญาต
Nick Mertin

6

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

โดยปกติคุณต้องทำสิ่งที่ค่อนข้างง่ายและคุณเริ่มต้นด้วยสคริปต์เชลล์เล็กน้อย เมื่อเวลาผ่านไปคุณเริ่มเพิ่มฟังก์ชันการทำงานให้กับสคริปต์ของคุณมากขึ้นเรื่อย ๆ จนกว่าจะถึงเวลาที่สคริปต์จะไม่ทำงานหรือคุณต้องการฟังก์ชั่นบางอย่างที่คุณไม่สามารถทำได้อย่างง่ายดายด้วยเชลล์สคริปต์และคิดเกี่ยวกับการเขียนสคริปต์เชลล์นี้เป็นภาษาอื่น , perl, ... ?)

การเขียนใหม่ตั้งแต่ต้นมักจะถือว่าเป็นข้อผิดพลาด แต่สำหรับสคริปต์มันอาจสมเหตุสมผลเพราะโดยปกติแล้วพวกเขาจะไม่ใหญ่หรือมีฟังก์ชั่นมากมาย แต่สมมติว่ามีความเป็นไปได้ที่จะเขียนซ้ำตั้งแต่เริ่มต้นในภาษาอื่นการบำรุงรักษาการทำงานและ params / flag ของเชลล์สคริปต์เริ่มต้น

ผู้ใช้สคริปต์นี้ไม่จำเป็นต้องระวังการเปลี่ยนแปลงภาษานี้พวกเขาจะดำเนินการคำสั่งเดียวกันและมันจะทำงานต่อไป

หากชื่อสคริปต์ของคุณdo-something.shสามารถดำเนินการต่อไปได้do-something.shแต่ตอนนี้มันถูกเขียนเป็นไพ ธ อน (ตัวอย่างเช่น) ดังนั้นคำใบ้เริ่มต้นของคุณจึงเป็นสิ่งที่ทำให้เข้าใจผิดโดยสิ้นเชิง


4

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

#!/bin/bash

จากนั้นคุณก็ต้องทำไฟล์ให้กับระบบด้วย

chmod 755 yourfilename

เช่นเดียวกับการใช้chmod +x yourfilenameตัวเลขนั้นอธิบายได้ง่าย

มันเป็นจำนวนสาม octals เพิ่มจำนวนแรกหมายถึงผู้คนที่สองของกลุ่มและหนึ่งในสามสำหรับคนอื่น ๆ เพิ่มเติมเกี่ยวกับการที่คุณสามารถหาที่นี่

และถ้าคุณอยู่ในไดเรกทอรีเดียวกับสคริปต์ของคุณอย่าลืมใช้./แบบนี้:

./yourfilename

พยายามนี้ น่าเสียดายที่ไม่แตกต่างจากผลลัพธ์ต้นฉบับ
Philip Kirkbride

@PhilipKirkbride ได้ดูที่คำตอบที่แก้ไขแล้วของฉันนี้จะช่วยให้แสงมากขึ้น
Videonauth

0

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

QDOS (ระบบปฏิบัติการที่รวดเร็วและสกปรกภายหลังเปลี่ยนชื่อเป็น "DOS" โดย IBM หลังจาก mirosoft ละเมิดลิขสิทธิ์และขายอย่างผิดกฎหมาย) และอื่น ๆ ราคาถูก ๆ ของ CP / M รวมถึง windows ผสมทั้งหมดนี้เพราะในระบบเหล่านั้นไม่มี สิ่งต่าง ๆ เช่นเรียกใช้สิทธิ์บนไฟล์ สิ่งนี้ส่งผลให้มีการรักษาความปลอดภัยมากมายในช่วง 30-40 ปีที่ผ่านมา อันที่จริงไม่กี่นาทีที่ผ่านมาฉันเพิ่งได้รับอีเมลขยะหลายฉบับที่มีไฟล์ซิปที่ติดกับ booby ซึ่งถูกเปลี่ยนชื่อเป็น MYPICTURE.JPG.zip :)

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