วิธีการรันเชลล์สคริปต์บนคอนโซล Unix หรือเทอร์มินัล Mac


507

ฉันรู้ว่ามันลืมมันและเรียนรู้อีกครั้ง เวลาที่จะเขียนมันลงไป


15
เขียนรถไฟ upvote ไปจนถึงสถานีชื่อเสียง
DivideByZer0

ไม่ต้องลงคะแนนเพียงเพื่อชื่นชมข้อผิดพลาดที่ยอดเยี่ยมที่คุณได้รับ!
BRHSM

คำตอบ:


942

ในการรันshสคริปต์ที่ไม่สามารถเรียกใช้งานได้ให้ใช้:

sh myscript

ในการรันbashสคริปต์ที่ไม่สามารถเรียกใช้งานได้ให้ใช้:

bash myscript

เพื่อเริ่มปฏิบัติการ (ซึ่งเป็นไฟล์ใด ๆ ที่มีสิทธิ์อนุญาตปฏิบัติการ); คุณเพียงแค่ระบุมันตามเส้นทางของมัน:

/foo/bar
/bin/bar
./bar

ในการทำให้สคริปต์เรียกทำงานได้ให้สิทธิ์ที่จำเป็น:

chmod +x bar
./bar

เมื่อไฟล์สามารถเรียกใช้งานได้เคอร์เนลจะเป็นผู้รับผิดชอบในการหาวิธีออกจากไฟล์ สำหรับผู้ที่ไม่ใช่ไบนารีสิ่งนี้ทำได้โดยดูที่บรรทัดแรกของไฟล์ มันควรจะมีhashbang:

#! /usr/bin/env bash

hashbang บอกเคอร์เนลว่าจะให้โปรแกรมทำงานอะไร (ในกรณีนี้คำสั่ง/usr/bin/envจะถูกรันด้วยอาร์กิวเมนต์bash) จากนั้นสคริปต์จะถูกส่งไปยังโปรแกรม (เป็นอาร์กิวเมนต์ที่สอง) พร้อมกับอาร์กิวเมนต์ทั้งหมดที่คุณให้สคริปต์เป็นอาร์กิวเมนต์ที่ตามมา

นั่นหมายความว่าสคริปต์ที่เป็นปฏิบัติการทุกคนควรมี hashbang หากไม่เป็นเช่นนั้นคุณจะไม่บอกเคอร์เนลว่ามันคืออะไรดังนั้นเคอร์เนลจึงไม่ทราบว่าโปรแกรมใดที่จะใช้เพื่อทำงานระหว่างมัน มันอาจจะเป็นbash, perl, python, shหรือสิ่งอื่น (ในความเป็นจริงเคอร์เนลมักจะใช้เชลล์เริ่มต้นของผู้ใช้เพื่อ interprete ไฟล์ซึ่งเป็นอันตรายมากเพราะมันอาจจะไม่ใช่ล่ามที่ถูกต้องเลยหรืออาจจะแยกวิเคราะห์บางส่วน แต่มีความแตกต่างของพฤติกรรมเล็กน้อยเช่น กรณีระหว่างshและbash)

หมายเหตุเกี่ยวกับ /usr/bin/env

โดยทั่วไปคุณจะเห็นแฮ็กเรียบเช่น:

#!/bin/bash

ผลลัพธ์คือเคอร์เนลจะรันโปรแกรม/bin/bashเพื่อแปลสคริปต์ แต่น่าเสียดายที่ไม่ได้ให้มาเสมอโดยค่าเริ่มต้นและก็ไม่เคยมีอยู่ในbash /binในขณะที่เครื่อง Linux ก็มักจะมีช่วงของเครื่อง POSIX อื่น ๆ ที่bashเรือในสถานที่ต่างๆเช่นหรือ/usr/xpg/bin/bash/usr/local/bin/bash

ในการเขียนสคริปต์ทุบตีแบบพกพาเราจึงไม่สามารถbashเชื่อถือตำแหน่งของโปรแกรมได้อย่างหนัก POSIX PATHแล้วมีกลไกในการจัดการกับว่า: แนวคิดคือคุณติดตั้งโปรแกรมของคุณในหนึ่งในไดเรกทอรีที่อยู่ในPATHและระบบควรจะสามารถค้นหาโปรแกรมของคุณเมื่อคุณต้องการเรียกใช้โดยใช้ชื่อ

น่าเศร้าที่คุณไม่สามารถทำสิ่งนี้ได้:

#!bash

เคอร์เนลจะไม่PATHค้นหาข้อมูลสำหรับคุณ มีโปรแกรมที่สามารถทำได้คือPATHการค้นหาสำหรับคุณ envแต่ก็เรียกว่า โชคดีที่เกือบทุกระบบมีโปรแกรมที่ติดตั้งในenv /usr/binดังนั้นเราจึงเริ่มenvใช้เส้นทางฮาร์ดโค้ดซึ่งจะPATHทำการค้นหาbashและเรียกใช้เพื่อให้สามารถตีความสคริปต์ของคุณ:

#!/usr/bin/env bash

วิธีการนี้มีหนึ่งข้อเสีย: ตาม POSIX, hashbang สามารถมีหนึ่งอาร์กิวเมนต์ ในกรณีนี้เราใช้bashเป็นอาร์กิวเมนต์ของenvโปรแกรม นั่นหมายความว่าเราไม่มีช่องว่างเหลือที่จะผ่านการโต้แย้งไปbashได้ ดังนั้นจึงไม่มีวิธีที่จะแปลงอะไรที่คล้าย#!/bin/bash -exuกับโครงการนี้ คุณต้องใส่set -exuhashbang แทน

วิธีการนี้มีข้อดีอีกอย่างคือ: ระบบบางระบบอาจมาพร้อมกับ a /bin/bashแต่ผู้ใช้อาจไม่ชอบมันอาจพบว่าเป็นรถบั๊กซีหรือล้าสมัยและอาจติดตั้งเองที่bashอื่น กรณีนี้มักเกิดขึ้นใน OS X (Macs) ซึ่ง Apple จัดส่งเครื่องล้าสมัย/bin/bashและผู้ใช้ติดตั้งรุ่นล่าสุด/usr/local/bin/bashโดยใช้บางอย่างเช่น Homebrew เมื่อคุณใช้envวิธีการที่ทำการPATHค้นหาคุณจะต้องคำนึงถึงความพึงพอใจของผู้ใช้และใช้การทุบตีที่เขาต้องการมากกว่าระบบที่เขาจัดส่ง


66
ขอบคุณที่สละเวลาเขียนคำตอบที่ดีสำหรับคำถามง่ายๆ
PA

5
ถ้าฉันใช้zshเป็นเปลือกของฉันฉันจะใช้hashbang #! /usr/bin/env zsh?
stefmikhail

6
@stefmikhail: ไม่สำคัญว่าคุณจะใช้ล่ามเชลล์ตัวใดในการเรียกใช้สคริปต์คุณควรใช้#! /usr/bin/env zshถ้า (และเฉพาะในกรณีที่) โค้ดภายในสคริปต์ควรถูกเรียกใช้โดย Z เชลล์
Johnsyweb

1
+1 สำหรับคำอธิบาย ฉันมักจะลืม แต่การรู้ความหมายของคำสั่งจะช่วยให้ฉันจำได้
Angelin Nadar

2
@Carpetsmoker นี้ถูกต้องและไม่ จำกัด hashbang สคริปต์ทุบตีควรใช้การสิ้นสุดบรรทัด UNIX เสมอมิฉะนั้นอาร์กิวเมนต์สุดท้ายของทุกคำสั่งจะมีการต่อท้าย \ r เช่นเดียวกับชื่อคำสั่ง hashbang
lhunath

80

ในการเริ่มเชลล์ - สคริปต์ 'file.sh':

sh file.sh

bash file.sh

อีกตัวเลือกหนึ่งคือตั้งค่าอนุญาตให้ใช้สิทธิได้โดยใช้คำสั่ง chmod

chmod +x file.sh

ตอนนี้เรียกใช้ไฟล์. sh ดังนี้

./file.sh

16

สำหรับเปลือก bourne:

sh myscript.sh

สำหรับทุบตี:

bash myscript.sh

ขอบคุณที่ตอบคำถามนี้ค่อนข้างชัดเจน สำหรับผู้ชาย Mac อย่างฉันมันง่ายที่จะลืมคำสั่ง Unix แบบเก่าระหว่างรอบ
PA

10

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

. /path/to/script.sh

หรือ

source /path/to/script.sh

โปรดทราบว่า/path/to/script.shสามารถเป็นญาติตัวอย่างเช่น. bin/script.shทำงานscript.shในbinไดเรกทอรีภายใต้ไดเรกทอรีปัจจุบัน


7
จะมากระมัดระวังในการจัดหาหรือ dot'ing กับ pathnames relateive คุณควรเสมอพวกเขาเริ่มต้นด้วย ./ ถ้าคุณไม่ทำเช่นนี้และชื่อพา ธ ญาติไม่ได้มีทับใด ๆ ที่คุณจะได้รับการจัดหาสิ่งที่อยู่ในเส้นทางก่อนที่บางสิ่งบางอย่างในไดเรกทอรีปัจจุบัน! อันตรายมากสำหรับการละเมิด
lhunath

0

ก่อนอื่นให้อนุญาตสำหรับการดำเนินการ: -
chmod +x script_name

  1. หากสคริปต์ไม่สามารถใช้งานได้: -
    สำหรับการเรียกใช้ไฟล์สคริปต์ sh: -
    sh script_name
    สำหรับการเรียกใช้ไฟล์สคริปต์ทุบตี: -
    bash script_name
  2. หากสคริปต์ทำงานได้: -
    ./script_name

หมายเหตุ : คุณสามารถตรวจสอบว่าไฟล์นั้นสามารถเรียกใช้งานได้หรือไม่โดยใช้ 'ls -a'


0

นามสกุลไฟล์คำสั่งถูกกำหนดให้กับ Terminal.app การดับเบิลคลิกที่ไฟล์คำสั่งใด ๆ จะดำเนินการ


0

นอกจากนี้เล็กน้อยเพื่อเรียกใช้ล่ามจากโฟลเดอร์เดียวกันยังคงใช้#! hashbangในสคริปต์

ตัวอย่างเช่นไฟล์ปฏิบัติการ php7.2 ที่คัดลอกมาจาก/ usr / binอยู่ในโฟลเดอร์พร้อมกับสคริปต์สวัสดี

#!./php7.2
<?php

echo "Hello!"; 

วิธีเรียกใช้:

./hello

ซึ่งมีพฤติกรรมเท่ากับ:

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