อะไรคือความแตกต่างระหว่าง. / และ sh เพื่อเรียกใช้สคริปต์?


71

ฉันเขียนสคริปต์ง่าย ๆ เมื่อฉันรันsh <myscriptname.sh>ฉันได้รับเอาต์พุตที่ถูกต้อง แต่เมื่อฉันรัน./<myscriptname.sh>ฉันพบข้อผิดพลาด

ความแตกต่างระหว่างตอนที่ผมทำคืออะไรshและ./?


15
แทนที่จะพูดว่า "ฉันได้รับข้อผิดพลาด" มันจะช่วยได้ถ้าคุณวางในสิ่งที่ข้อผิดพลาดนั้นพูด
SpashHit

คำตอบ:


67

เมื่อคุณเรียกใช้สคริปต์ใด ๆ โดยส่งชื่อไฟล์ไปยังโปรแกรมตัวแปลสคริปต์คุณกำลังเรียกใช้โปรแกรมตัวแปลโดยที่สคริปต์เป็นอาร์กิวเมนต์ที่ส่งผ่านเข้าไป เช่นนี้ดูเหมือนว่ากระบวนการ 'sh' กับอาร์กิวเมนต์ 'filename.sh' shล่ามเปิดไฟล์

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

คุณควรตรวจสอบให้แน่ใจว่าคุณมีสายปัง:

#!/bin/bash
# bash script here

บรรทัด bang เป็นบรรทัดแรกในสคริปต์และเริ่มต้นด้วยอักขระสองตัวเดียวกัน#!นี่คือสิ่งที่ระบบอ่านเมื่อพยายามเรียกใช้สคริปต์จากนั้นระบบจะส่งสคริปต์ไปยังโปรแกรมทันทีหลังจากนั้น โปรดทราบว่าบรรทัดนี้ไม่มีอะไรเกี่ยวข้องกับการทุบตีและทำงานได้ดีกับงูหลามและ Perl แม้ว่ามันจะเป็นภาษาที่แตกต่างกันมากก็ตาม คุณจะใช้#!/usr/bin/pythonเป็นตัวอย่างแล้วตามด้วยรหัสหลาม

เมื่อคุณมีสคริปต์ตรวจสอบให้แน่ใจว่าคุณได้ตั้งค่าการอนุญาตให้ใช้งานแล้ว:

chmod a+x filename.sh

จากนั้นคุณสามารถเรียกใช้สคริปต์เป็นกระบวนการของตัวเอง:

./filename.sh

หรือวางไฟล์ลงในตำแหน่งที่รู้จักพร้อมชื่อโปรแกรมที่ดีชอบ/usr/sbinและเรียกใช้จากที่ใดก็ได้:

sudo cp filename.sh /usr/sbin/program-name
program-name

และนี้เป็นจริงในทางปฏิบัติประโยชน์ของการใช้สายปังที่มีสิทธิ์ - มันคือทั้งหมดที่เกี่ยวกับการใช้งาน เป็นการยากมากที่จะให้ผู้ใช้เรียกใช้สคริปต์หากพวกเขาต้องจำโปรแกรมที่เรียกใช้สคริปต์ด้วย อย่าลืมให้เส้นทางแบบเต็มไปยังสคริปต์ทุกครั้งที่ต้องการเรียกใช้ /usr/local/binตัวอย่างเช่นเมื่อวางไว้ที่ใดและทำให้สามารถใช้งานได้สามารถบันทึกความเศร้าโศกมากมายสำหรับผู้ที่พยายามใช้สคริปต์ของคุณ โปรแกรมเหล่านี้จะพร้อมใช้งานสำหรับผู้ใช้ทุกคนในคอมพิวเตอร์ของคุณ

นอกจากนี้ยังเป็นสิ่งที่ดีสำหรับการระบุตัวตน ถ้าคุณเข้าไปในtopโปรแกรมการทำงานสคริปต์ไม่มีสายปังก็จะมีชื่อของล่ามคือbash, หรือperl pythonแต่ถ้าสคริปต์รันด้วยสิทธิ์ที่ถูกต้องชื่อของสคริปต์ก็จะปรากฏขึ้น

หมายเหตุ:หากคุณต้องการแจกจ่ายสคริปต์ที่ทุกคนสามารถเข้าถึงได้โปรดสร้าง man page และแพ็กเกจ deb เพื่อติดตั้ง เราจำเป็นต้องลดจำนวนสคริปต์สุ่มทางออนไลน์และเพิ่มจำนวนของเดบิตที่สามารถถอนการติดตั้งได้


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

แน่นอน แต่การเพิ่มโฟลเดอร์บ้านของคุณใน PATH สามารถเห็นได้ว่าเป็นเรื่องปวดหัว ติดตั้งสิ่งต่าง ๆ ได้ดีกว่า แม้ว่าจะมีการพูดคุยเกี่ยวกับการเพิ่ม ~ / .local / bin ในพา ธ โดยค่าเริ่มต้นเพื่ออนุญาตให้ผู้ใช้ภายในติดตั้งแพคเกจ
Martin Owens -doctormo-

โปรดทราบว่าล่ามเริ่มต้นคือไม่bash sh
นาธานออสมัน

1
PATHอย่าใส่ส่วนขยายในสคริปต์โดยเฉพาะอย่างยิ่งเมื่อคุณไม่ได้ใส่ไว้ใน
geirha

1
/usr/local/binน่าจะดีกว่าแล้ว/usr/sbin- มันบ่งบอกว่าโปรแกรมอยู่ภายในเครื่องนี้แทนที่จะเป็นส่วนหนึ่งของการกระจาย
เกล็นแจ็คแมน

41

รุ่นสั้น:

  • shเป็นล่ามบรรทัดคำสั่ง (เส้นประ)
    การทำงานsh my_scriptทำให้ dash ตีความสคริปต์

  • ./พยายามค้นหาล่ามที่จะใช้โดยดูที่บรรทัดแรก เช่น#!/bin/bashหรือแม้กระทั่ง#!/bin/ruby(ตรงข้ามกับการทำงานruby my_script)


7
มันไม่ได้เป็นสิ่ง./ที่พบอะไรจริงๆมันเป็นวิธีการดำเนินการระบบซึ่งดูที่สองไบต์แรกของไฟล์
Martin Owens -doctormo-

9
อย่างแน่นอน นี่คือคำอธิบายที่ยาวมากของมันทั้งหมด ฉันกำลังใช้งานได้จริง :)
Stefano Palazzo

เมื่อคุณใช้shและไฟล์มี sha-bang หมายความว่า sha-bang จะถูกเพิกเฉยหรือมันจะเปิดเชลล์ที่shลิงก์ด้วยเช่นกันและบางทีเชลล์อื่น ๆ หรือมันทำอะไร :)?
Ini

5

ความแตกต่างที่คุณทำคือ

  • ด้วยsh, คุณกำลังเรียกใช้โปรแกรมที่จะตีความบรรทัดในสคริปต์ของคุณเหมือนกับที่คุณพิมพ์บนพรอมต์แบบโต้ตอบของเทอร์มินัล

  • เมื่อ./คุณใช้ช็อตคัทสมมติว่าสคริปต์อยู่ตรงนี้ในไดเรกทอรีปัจจุบันที่คุณใช้งานและมันจะสามารถเรียกใช้งานได้ (เพราะเช่นคุณออกใช้chmod +x myscript.sh) ช่วยให้คุณประหยัดเวลาอันมีค่าสำหรับเวลาในอนาคต :-)


3
+1 สำหรับการเป็นคนเดียวที่จะระบุอย่างกระชับว่าไฟล์นั้นจะต้องสามารถเรียกใช้งานได้
มิเคล

2
โปรดทราบว่าด้วยshไฟล์จะต้องไม่สามารถเรียกใช้งานได้
Ini

3

มีสามเหตุผลหลักที่คุณอาจได้รับข้อผิดพลาด:

  • ไฟล์นี้ไม่สามารถ
    เรียกใช้chmod +x <myscriptname.sh>เพื่อปฏิบัติการได้
  • พาร์ติชันไม่อนุญาตให้เรียกใช้สคริปต์ (ถูกเมาท์ " noexec")
    คัดลอกสคริปต์ไปที่/usr/local/bin
  • #!บรรทัดมีข้อผิดพลาด
    ให้แน่ใจว่าบรรทัดแรกเป็น#!/bin/shหรือ#!/bin/bash

หากบรรทัดแรกของคุณดูถูกต้อง แต่ก็ยังใช้งานไม่ได้ตรวจสอบให้แน่ใจว่าไฟล์นั้นไม่มีจุดสิ้นสุดของบรรทัด DOS

ข้อผิดพลาดจะมีลักษณะดังนี้:

$ ./myscript.sh
bash: ./myscript.sh: /bin/bash^M: bad interpreter: No such file or directory

คุณสามารถแก้ไขได้โดยการทำงานหรือถ้าคุณไม่ได้ว่าdos2unix <myscriptname.sh>
perl -p -i -e 's/\r\n$/\n/' <myscriptname.sh>


0

และคำตอบก็คือ sh คือชื่อของเปลือกหอยยอดนิยม แต่ล้าสมัยและถูกแทนที่โดยผู้อื่น ทุกวันนี้ SH เชื่อมโยงกับเชลล์อื่น ๆ ที่ติดตั้งบนเครื่อง เช่นฉันทุบตีที่นั่น การเรียกใช้เชลล์ใด ๆ จาก sh มักจะเรียกใช้โหมด 'ความเข้ากันได้' บางอย่างกับพฤติกรรมของ 'เชลล์' ดั้งเดิม

ดังนั้นการแก้ปัญหาค่อนข้างง่าย ดูว่ามีอะไรอยู่เบื้องหลังคำสั่ง sh (ls -al / bin / sh) และใส่ #! / bin / Anything_you_find_there เป็นบรรทัดแรก (หรือหากมีบางอย่างในสคริปต์ของคุณแก้ไขมัน)

และอาจมีข้อผิดพลาดบางอย่างในสคริปต์ของตัวเอง เช่นเดียวกับการพึ่งพาที่พบโดย sh แต่ไม่ใช่ล่ามที่ใช้จริง


0
mkdir ~/bin ; cp myscript.sh ~/bin/

echo "export PATH="$PATH:/home/$USER/bin" >> ~/.profile ; source ~/.profile ; 

ไม่ใช่/usr/sbinสำหรับเครื่องมือการดูแลระบบที่ไม่จำเป็น/usr/local/binเป็นตัวเลือกที่ดีกว่าถ้าคุณไม่ต้องการมี~/bin/แต่แนะนำให้หลีกเลี่ยงsudoมากที่สุด


บน Ubuntu เริ่มต้น~/.profileแล้วมีรหัสสำหรับการเพิ่มถ้ามันมีอยู่แล้วที่จะ~/bin PATHในบันทึกอื่นอย่าใส่ส่วนขยายลงในสคริปต์
geirha

1
ฉันอ้างอิง <myscriptname.sh> แต่เหตุผลที่ไม่ใส่ส่วนขยายในสคริปต์คืออะไร ฉันมักจะทำเพราะมีไฟล์ข้อความธรรมดาที่มองเห็นเช่นนั้นทำให้ฉันพยายามแก้ไขไบนารีที่ฉันเก็บไว้ใน ~ / bin / ( ls ~/bin/|wc -l = 428) ฉันใส่ของจำนวนมากลงในนั้น;)
Joey1978

ลองนึกภาพคุณเขียนสคริปต์เพื่อให้ได้งานที่เฉพาะเจาะจง จากนั้นคุณก็รู้ว่าการเขียนสคริปต์นี้ในไพ ธ อนจะทำให้มีประสิทธิภาพมากขึ้นดังนั้นคุณจึงเขียนมันใหม่ในไพ ธ อน ตอนนี้คุณมีสองทางเลือก 1) ปล่อย. sh-extension ที่ทำให้เข้าใจผิดในตอนนี้หรือ 2) เปลี่ยนชื่อสคริปต์และค้นหาและแทนที่การใช้สคริปต์ทั้งหมดเพื่อใช้ชื่อใหม่ หากคุณดูสคริปต์ใน/binและ/usr/binคุณจะเห็นพวกเขาไม่ได้ใช้ส่วนขยาย
geirha
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.