Làm cách nào để chạy tập lệnh shell trên bàn điều khiển Unix hoặc thiết bị đầu cuối Mac?


507

Tôi biết điều đó, quên nó và học lại nó. Thời gian để viết nó xuống.


15
viết upvote đào tạo tất cả các cách đến trạm danh tiếng
DivideByZer0

sẽ không upvote chỉ để chiêm ngưỡng lỗi tuyệt vời mà bạn đã có!
BRHSM

Câu trả lời:


942

Để chạy shtập lệnh không thể thực thi , hãy sử dụng:

sh myscript

Để chạy bashtập lệnh không thể thực thi , hãy sử dụng:

bash myscript

Để bắt đầu thực thi (đó là bất kỳ tệp nào có quyền thực thi); bạn chỉ cần xác định nó theo đường dẫn của nó:

/foo/bar
/bin/bar
./bar

Để tạo tập lệnh thực thi, hãy cấp cho nó quyền cần thiết:

chmod +x bar
./bar

Khi một tập tin có thể thực thi được, kernel có trách nhiệm tìm ra cách để thực hiện nó. Đối với các tệp không nhị phân, điều này được thực hiện bằng cách nhìn vào dòng đầu tiên của tệp. Nó nên chứa một hashbang:

#! /usr/bin/env bash

Hàm băm cho hạt nhân biết chương trình nào sẽ chạy (trong trường hợp này lệnh /usr/bin/envđược chạy với đối số bash). Sau đó, tập lệnh được chuyển đến chương trình (dưới dạng đối số thứ hai) cùng với tất cả các đối số bạn đã đưa tập lệnh làm đối số tiếp theo.

Điều đó có nghĩa là mọi tập lệnh có thể thực thi được nên có hàm băm . Nếu không, bạn không nói với kernel đó gì và do đó kernel không biết nên sử dụng chương trình nào để giải thích nó. Nó có thể là bash, perl, python, sh, hay cái gì khác. . trường hợp giữa shbash).

Một lưu ý về /usr/bin/env

Thông thường nhất, bạn sẽ thấy tiếng nổ băm như vậy:

#!/bin/bash

Kết quả là kernel sẽ chạy chương trình /bin/bashđể diễn giải kịch bản. Thật không may, bashkhông phải lúc nào cũng được vận chuyển theo mặc định và không phải lúc nào cũng có sẵn /bin. Mặc dù trên các máy Linux thường có, có một loạt các máy POSIX khác có bashtàu ở nhiều địa điểm khác nhau, chẳng hạn như /usr/xpg/bin/bashhoặc /usr/local/bin/bash.

Để viết một tập lệnh bash di động, do đó chúng ta không thể dựa vào mã hóa cứng vị trí của bashchương trình. POSIX đã có một cơ chế để xử lý việc đó : PATH. Ý tưởng là bạn cài đặt các chương trình của mình vào một trong những thư mục nằm trong PATHvà hệ thống sẽ có thể tìm thấy chương trình của bạn khi bạn muốn chạy nó theo tên.

Đáng buồn thay, bạn không thể làm điều này:

#!bash

Hạt nhân sẽ không (một số có thể) thực hiện PATHtìm kiếm cho bạn. Tuy nhiên, có một chương trình có thể thực hiện PATHtìm kiếm cho bạn env. May mắn thay, gần như tất cả các hệ thống có một envchương trình được cài đặt /usr/bin. Vì vậy, chúng tôi bắt đầu envsử dụng một đường dẫn được mã hóa cứng, sau đó thực hiện PATHtìm kiếm bashvà chạy nó để nó có thể diễn giải kịch bản của bạn:

#!/usr/bin/env bash

Cách tiếp cận này có một nhược điểm: Theo POSIX, hashbang có thể có một đối số . Trong trường hợp này, chúng tôi sử dụng bashlàm đối số cho envchương trình. Điều đó có nghĩa là chúng tôi không còn chỗ trống để truyền đối số bash. Vì vậy, không có cách nào để chuyển đổi một cái gì đó giống như #!/bin/bash -exuchương trình này. set -exuThay vào đó, bạn sẽ phải đặt sau hashbang.

Cách tiếp cận này cũng có một ưu điểm khác: Một số hệ thống có thể giao hàng với một /bin/bash, nhưng người dùng có thể không thích nó, có thể thấy nó bị lỗi hoặc lỗi thời và có thể đã cài đặt bashở một nơi khác. Đây thường là trường hợp trên OS X (Mac), nơi Apple vận chuyển lỗi thời /bin/bashvà người dùng cài đặt một bản cập nhật /usr/local/bin/bashbằng cách sử dụng một cái gì đó như Homebrew. Khi bạn sử dụng envphương pháp PATHtìm kiếm, bạn sẽ tính đến sở thích của người dùng và sử dụng bash ưa thích của anh ta đối với phương pháp mà hệ thống của anh ta vận chuyển.


66
Cảm ơn bạn đã dành thời gian để viết một câu trả lời tốt cho một câu hỏi đơn giản.
PA

5
Nếu tôi sử dụng zshnhư vỏ của tôi, tôi sẽ sử dụng hashbang #! /usr/bin/env zsh?
stefmikhail

6
@stefmikhail: Không quan trọng bạn sử dụng trình thông dịch shell nào để gọi tập lệnh, bạn nên sử dụng #! /usr/bin/env zshif (và chỉ khi) mã bên trong tập lệnh nên được thực thi bởi trình bao Z.
Johnsyweb

1
+1 để giải thích. Tôi có xu hướng quên nhưng biết ý nghĩa của lệnh sẽ giúp tôi nhớ lại.
Angelin Nadar

2
@Carpetsmoker Điều này đúng và không giới hạn ở hashbang. các tập lệnh bash phải luôn luôn sử dụng các kết thúc dòng UNIX nếu không, đối số cuối cùng của mỗi lệnh sẽ có một \ r được thêm vào nó, giống như tên lệnh hashbang sẽ.
lhunath

80

Để bắt đầu shell-script 'file.sh':

sh file.sh

bash file.sh

Một tùy chọn khác được đặt quyền thực thi bằng lệnh chmod:

chmod +x file.sh

Bây giờ hãy chạy tệp .sh như sau:

./file.sh

16

Đối với vỏ bourne:

sh myscript.sh

Đối với bash:

bash myscript.sh

Cảm ơn bạn đã trả lời câu hỏi khá rõ ràng này. Đối với một người Mac như tôi, thật dễ dàng để quên các lệnh Unix cũ giữa các vòng.
PA

10

Nếu bạn muốn tập lệnh chạy trong trình bao hiện tại (ví dụ: bạn muốn tập lệnh có thể ảnh hưởng đến thư mục hoặc môi trường của bạn), bạn nên nói:

. /path/to/script.sh

hoặc là

source /path/to/script.sh

Lưu ý rằng /path/to/script.shcó thể là tương đối, ví dụ . bin/script.shchạy script.shtrong binthư mục trong thư mục hiện tại.


7
Hãy rất cẩn thận khi mua hoặc dot'ing với pathnames relateive. Bạn phải luôn bắt đầu chúng bằng ./ Nếu bạn không làm điều này và tên đường dẫn tương đối không chứa bất kỳ dấu gạch chéo nào, bạn sẽ tìm nguồn cung ứng gì đó trong PATH, TRƯỚC một thứ gì đó trong thư mục hiện tại! Rất nguy hiểm cho việc lạm dụng.
lhunath

0

Đầu tiên, cho phép thực hiện: -
chmod +x script_name

  1. Nếu tập lệnh không được thực thi: -
    Để chạy tệp tập lệnh sh: -
    sh script_name
    Để chạy tập tin bash script: -
    bash script_name
  2. Nếu tập lệnh được thực thi: -
    ./script_name

LƯU Ý : -bạn có thể kiểm tra xem tệp có thực thi được hay không bằng cách sử dụng 'ls -a'


0

Phần mở rộng tệp .command được gán cho Terminal.app. Bấm đúp vào bất kỳ tệp .command nào sẽ thực thi nó.


0

Ngoài ra, để chạy trình thông dịch từ cùng một thư mục, vẫn sử dụng #! Hashbang trong tập lệnh.

Ví dụ, một tệp thực thi php7.2 được sao chép từ / usr / bin nằm trong một thư mục cùng với tập lệnh hello .

#!./php7.2
<?php

echo "Hello!"; 

Để chạy nó:

./hello

Mà hành xử giống như:

./php7.2 hello
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.