Tôi biết điều đó, quên nó và học lại nó. Đã đến lúc viết xuống.Làm thế nào để chạy một kịch bản lệnh shell trên một giao diện điều khiển Unix hoặc thiết bị đầu cuối Mac?
Trả lời
Để chạy một sh
kịch bản phi thực thi, sử dụng:
sh myscript
Để chạy một bash
kịch bản phi thực thi, 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ó bằng con đường của nó:
/foo/bar
/bin/bar
./bar
Để thực hiện một kịch bản thực thi, cung cấp cho nó sự cho phép cần thiết:
chmod +x bar
./bar
Khi một tập tin được thực thi, các kernel có trách nhiệm tìm hiểu làm thế nào để thực hiện nó. Đối với các chương trình không phải nhị phân, điều này được thực hiện bằng cách xem dòng đầu tiên của tệp. Nó nên chứa một hashbang
:
#! /usr/bin/env bash
Các hashbang nói với kernel những gì chương trình để chạy (trong trường hợp này lệnh /usr/bin/env
đang chạy với lập luận bash
). Sau đó, kịch bản được chuyển đến chương trình (như đối số thứ hai) cùng với tất cả các đối số bạn đã cung cấp kịch bản làm đối số tiếp theo.
Điều đó có nghĩa là mọi tập lệnh có thể thực thi phải có mã băm. Nếu không, bạn không nói hạt nhân nó là gì là và do đó hạt nhân không biết chương trình nào sẽ sử dụng để diễn giải nó. Có thể là bash
, perl
, python
, sh
hoặc thứ khác. (Trong thực tế, hạt nhân thường sẽ sử dụng trình bao mặc định của người dùng để giải thích tệp, điều này rất nguy hiểm vì nó có thể không phải là trình thông dịch đúng hoặc có thể phân tích cú pháp của nó nhưng với những khác biệt hành vi tinh tế như trường hợp giữa sh
và bash
).
Lưu ý về /usr/bin/env
Phổ biến nhất, bạn sẽ thấy tóc mái băm như vậy:
#!/bin/bash
Kết quả là hạt nhân sẽ chạy chương trình /bin/bash
để giải thích kịch bản. Thật không may, bash
không phải lúc nào cũng được giao hàng theo mặc định và không phải lúc nào cũng có sẵn trong /bin
. Trong khi trên các máy Linux, thông thường, có một loạt các máy POSIX khác nơi các tàu bash
ở các địa điểm khác nhau, chẳng hạn như /usr/xpg/bin/bash
hoặc /usr/local/bin/bash
.
Để viết tập lệnh bash di động, do đó chúng tôi không thể dựa vào mã hóa cứng vị trí của chương trình bash
. POSIX đã có cơ chế để xử lý điều đó: PATH
. Ý tưởng là bạn cài đặt các chương trình của bạn vào một trong các thư mục có trong PATH
và 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 chương trình theo tên.
Đáng buồn thay, bạn không thể chỉ làm điều này:
#!bash
Các hạt nhân sẽ không (một số có thể) thực hiện tìm kiếm PATH
cho bạn. Tuy nhiên, có một chương trình có thể thực hiện tìm kiếm PATH
cho bạn, được gọi là env
. May mắn thay, gần như tất cả các hệ thống đều có một chương trình env
được cài đặt trong /usr/bin
. Vì vậy, chúng ta bắt đầu env
sử dụng một đường dẫn cứng, sau đó thực hiện một tìm kiếm PATH
cho bash
và chạy nó để nó có thể giải thích kịch bản của bạn:
#!/usr/bin/env bash
Cách tiếp cận này đã một nhược điểm: Theo POSIX, các hashbang thể có một đối số. Trong trường hợp này, chúng tôi sử dụng bash
làm đối số cho chương trình env
. Điều đó có nghĩa là chúng tôi không còn chỗ để chuyển đối số cho bash
. Vì vậy, không có cách nào để chuyển đổi một cái gì đó như #!/bin/bash -exu
để chương trình này. Bạn sẽ phải đặt set -exu
sau băm thay vào đó.
Cách tiếp cận này cũng có ưu điểm khác: Một số hệ thống có thể giao hàng với /bin/bash
, nhưng người dùng có thể không thích, có thể thấy lỗi hoặc lỗi thời và có thể đã cài đặt bash
riêng của mình ở một nơi khác. Đây thường là trường hợp trên OS X (Mac), nơi Apple gửi một lỗi thời /bin/bash
và người dùng cài đặt một cập nhật /usr/local/bin/bash
bằng cách sử dụng một cái gì đó như Homebrew. Khi bạn sử dụng phương thức env
thực hiện tìm kiếm PATH
, bạn sẽ xem xét tùy chọn của người dùng và sử dụng dấu gạch chéo ưa thích của mình trên hệ thống mà hệ thống của anh ấy đã đi kèm.
Cảm ơn bạn đã dành thời gian để viết một câu trả lời hay cho một câu hỏi đơn giản. –
Nếu tôi sử dụng 'zsh' làm vỏ của mình, tôi có sử dụng' hashbang' '#!/usr/bin/env zsh'? – stefmikhail
@stefmikhail: Không cần biết thông dịch viên shell nào bạn sử dụng để * gọi * tập lệnh, bạn nên sử dụng '#!/usr/bin/env zsh' nếu (và chỉ nếu) mã * bên trong * tập lệnh sẽ được thực hiện bởi trình bao Z. – Johnsyweb
Để bắt đầu vỏ kịch bản 'file.sh':
sh file.sh
bash file.sh
Một lựa chọn khác được thiết lập cho phép thực thi sử dụng lệnh chmod:
chmod +x file.sh
Bây giờ chạy sh tập tin như sau:
./file.sh
Đố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 anh chàng Mac như tôi, rất dễ quên các lệnh Unix cũ giữa các vòng. –
Nếu bạn muốn kịch bản để chạy trong vỏ hiện tại (ví dụ như bạn muốn nó 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
source /path/to/script.sh
Note rằng /path/to/script.sh
có thể là tương đối, ví dụ . bin/script.sh
chạy script.sh
trong thư mục bin
trong thư mục hiện tại.
Hãy ** rất cẩn thận khi tìm nguồn cung ứng hoặc chấm điểm với các tên đường dẫn có liên quan. Bạn nên ** luôn luôn ** bắt đầu chúng với ./ Nếu bạn không làm điều này, và đường dẫn tương đối không chứa bất kỳ dấu gạch chéo, bạn sẽ tìm nguồn cung cấp một cái gì đó trong PATH, TRƯỚC một cái gì đó trong thư mục hiện hành! Rất nguy hiểm cho việc lạm dụng. – lhunath
Thứ nhất, cho phép để thực hiện: -
chmod +x script_name
- Nếu kịch bản không phải là thực thi: -
Để chạy tập tin sh kịch bản: -
sh script_name
Để chạy tập tin bash script: -
bash script_name
- Nếu tập lệnh có thể thực thi được: -
./script_name
LƯU Ý: -bạn có thể kiểm tra nếu tập tin thực thi hay không bằng cách sử dụng 'ls -a'
Các .command phần mở rộng tập tin được gán cho Terminal.app. Nhấp đúp vào bất kỳ tệp .command nào sẽ thực thi nó.
viết chuyến tàu tối ưu tới tận ga danh tiếng – DivideByZer0
sẽ không chỉ để chiêm ngưỡng lỗi tuyệt vời mà bạn đã có! – BRHSM