Tại sao tôi cần đặt sh trước khi chạy tệp .sh?


16

Khi tôi muốn chạy .shcác tệp trong Terminal, tôi cần đặt shtrước chúng.

Có cách nào để tránh điều này, và do đó tiết kiệm gõ?


3
Tôi đã tạo một thư mục tại ~ / bin để đặt các tập lệnh shell của mình vào và đặt nó vào $ PATH của tôi và cũng đính kèm một Thư mục hành động vào thư mục ~ / bin để tự động đặt quyền thực thi vì điều đó rất dễ quên.
Kaydell

Câu trả lời:


22

Nếu bạn đang chạy tập lệnh của mình từ trình bao, bạn thực sự không cần #!/bin/shshebang như được nêu trong câu trả lời này , hệ thống giống như Unix mà tôi đã sử dụng, bao gồm cả OS X, sẽ mặc định /bin/shnếu không có trình thông dịch cụ thể nào được chỉ định ( mặc dù đó là một ý tưởng tốt vì những người không có vỏ sẽ không biết cách thực thi tập lệnh của bạn trừ khi bạn đưa ra shebang.)

Bạn cũng không cần một .shphần mở rộng. Bạn làm cần thiết phải thiết lập quyền thực thi, ví dụ

$ chmod +x script.sh

(Đây $là dấu nhắc trình bao; Tôi đang sử dụng nó để minh họa các lệnh bạn đưa ra cho trình bao tương tác. Đừng gõ nó!)

Tuy nhiên, tôi nghĩ điều khó hiểu của bạn là bạn đã tạo một tập lệnh, ví dụ script.sh, trong thư mục hiện tại và đang cố gắng thực thi nó bằng cách chỉ cần gõ script.sh. ví dụ

$ cat >script.sh
echo hello, world
^D
$ chmod +x script.sh
$ script.sh
-bash: script.sh: command not found

( ^Dcó nghĩa là control- D. Bạn sẽ tìm thấy ký hiệu này trong nhiều lần viết về việc sử dụng Unix.)

Thực tế là script.shtrong trường hợp này là một kịch bản shell chỉ là một nửa vấn đề; Vấn đề thực sự của bạn là theo mặc định, shell sẽ không tìm kiếm thư mục hiện tại cho một chương trình. Tuy nhiên, điều này hoạt động:

$ sh script.sh
hello, world

bởi vì shlấy kịch bản làm đối số.

Bạn có thể thực thi một tập lệnh script hoặc, một lần nữa, bất kỳ tập lệnh thực thi nào trong thư mục hiện tại, nếu nó được đánh dấu thực thi (tức là chmod +x), bằng cách chỉ định rằng bạn muốn chạy tập lệnh trong thư mục hiện tại:

$ ./script.sh
hello, world

Bạn cũng có thể di chuyển tập lệnh đến một thư mục trên của bạn PATH. Tôi khuyên bạn nên /usr/local/binlàm điều này nếu tập lệnh của bạn dự định sẽ được sử dụng trên toàn hệ thống hoặc một binthư mục trong nhà bạn nếu tập lệnh chỉ dành cho bạn. Cái sau yêu cầu bạn thêm $HOME/bin, mở rộng vào thư mục bin mới của bạn, PATHbằng cách thêm các dòng sau vào thư mục chính .profilecủa bạn:

PATH=$HOME/bin:$PATH
export PATH

Cuối cùng, bạn có thể, nếu bạn muốn, thực sự thêm thư mục hiện tại vào thư mục của bạn PATH, điều này sẽ cho phép bạn chỉ cần đi đến một thư mục có chứa script.shhay bất kỳ loại thực thi nào khác.

$ script.sh

để thực hiện nó. Tuy nhiên, tôi không khuyến khích thực hành này , vì bây giờ kẻ tấn công có thể lừa bạn chạy một tệp thực thi tùy ý bằng cách thả một tập lệnh thực thi (có tên, giả sử ls) vào một thư mục mà bạn sẽ tham gia. Tuy nhiên, nếu bạn thực sự muốn làm điều đó chỉ cần thêm những điều sau đây vào .profile:

PATH=.:$PATH
export PATH

Đặt '.' vào cuối $ PATH thay vì bắt đầu và bây giờ bạn không cần phải lo lắng về một bóng ma 'ls'. (Mặc dù nếu ai đó có thể xâm nhập vào hệ thống của bạn, bạn đã gặp sự cố lớn hơn.)
TJ Luoma

2
@TJ, nhưng bạn làm cần phải lo lắng về những thứ như thế slhay llshay l... tức là, lỗi chính tả. Chỉ cần rời .khỏi $PATH. Ngoài ra, bạn có thể không (hoặc không nên) nhất thiết phải tin tưởng tất cả mọi người trên hệ thống của mình. Ví dụ: giả sử có một số khai thác cho phép kẻ tấn công thả một tệp tùy ý vào một thư mục nào đó, nhưng chúng cần bạn thực thi tệp đó để chuyển sang khai thác tốt hơn (ví dụ: thu thập dữ liệu và về nhà điện thoại). Phòng thủ chuyên sâu!
Reid

@TJLuoma Những gì @Reid nói, cộng với hãy nhớ rằng có nhiều trường hợp sử dụng cho một hệ thống Unix ngoài máy tính để bàn OS X cá nhân. Chưa thử, nhưng tôi cá là ngay cả tài khoản khách cũng có thể để một trong những mục đó trong /tmphoặc một số thư mục có thể ghi trên thế giới khác.
zigg

Nếu bạn đang sử dụng một hệ thống mà người khác có quyền truy cập vào các thư mục bạn sử dụng, bạn đã gặp vấn đề lớn hơn.
TJ Luoma

@TJLuoma Tốt nhất bạn không bao giờ nên sử dụng nhiều tài khoản trên bất kỳ hệ thống Unix nào. /tmpet al. đến với lãnh thổ.
zigg

10

Bạn không cần phải gọi shnếu tệp script được đánh dấu là có thể thực thi được. Trong trường hợp đó, bạn có thể gọi nó là tên của tôi giống như bất kỳ lệnh nào khác từ shell hiện có.


Để hoàn toàn chính xác, bạn sẽ muốn làm hai điều:

  1. Chỉnh sửa tập lệnh của bạn để bao gồm một lệnh shebang ở đầu tập lệnh của bạn:

    #!/bin/sh

    ... Điều đó sẽ cho trình bao biết trình thông dịch nào sẽ sử dụng để chạy tập lệnh; trong trường hợp này, việc /bin/shthực thi

  2. Đánh dấu tập lệnh là tệp thực thi của bạn bằng lệnh chmod :

    chmod u+x scriptname.sh

Khi bạn thực hiện cả hai điều đó, bạn sẽ có thể chạy tập lệnh của mình bằng cách nhập tên tệp của tập lệnh vào dòng lệnh. Bạn sẽ cần phải ở cùng thư mục với tập lệnh của mình, trừ khi bạn cũng thực hiện bước bổ sung thêm thư mục chứa vào biến PATH của mình . Nếu bạn không quan tâm shell nào chạy tập lệnh, bạn không cần bước một để chỉ định shnhưng thường chính xác hơn là đặt "shebangsh".


Shebang không thực sự cần thiết /bin/sh, mặc dù chúng không bị tổn thương.
zigg

@zigg - Bạn nói đúng. Tôi hy vọng Chris không bận tâm đến các chỉnh sửa của tôi, Nuke hoặc chỉnh sửa lại theo ý muốn: -0
bmike

@bmike Các chỉnh sửa làm việc cho tôi. Đối với các shebang, thói quen của tôi là luôn luôn chỉ định bởi vì tôi đã từng viết rất nhiều kshkịch bản từ thời còn trên HP-UX - nhưng thật tốt khi biết rằng điều đó không thực sự cần thiết.
Chris W. Rea

1
Tôi nghĩ rằng tôi cần phải lùi lại từ tuyên bố trước đây của tôi về sự cần thiết công việc (mặc dù phần còn lại của câu trả lời của tôi vẫn còn đứng.) Bạn có thể chạy một kịch bản công việc ít từ một vỏ, nhưng nếu bạn sử dụng một execsyscall, bạn nhận được ENOEXEC(lỗi định dạng exec ). Xin lỗi về điều đó, @bmike, @ ChrisW.Rea. Tôi sẽ đi chỉnh sửa câu trả lời của tôi bây giờ.
zigg
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.