Sự khác biệt giữa ./ và sh để chạy tập lệnh là gì?


71

Tôi đã viết một kịch bản đơn giản. Khi tôi chạy sh <myscriptname.sh>, tôi đã nhận được đầu ra chính xác, nhưng khi tôi chạy ./<myscriptname.sh>, tôi đã gặp lỗi.

Sự khác biệt giữa khi tôi làm shvà là ./gì?


15
Thay vì chỉ nói: "Tôi gặp lỗi", nó sẽ giúp ích nếu bạn dán vào những gì lỗi đã nói.
SpashHit

Câu trả lời:


67

Khi bạn chạy bất kỳ tập lệnh nào bằng cách chuyển tên tệp cho chương trình trình thông dịch tập lệnh, bạn đang chạy chương trình trình thông dịch với tập lệnh dưới dạng đối số được truyền vào nó. Ví dụ, điều này sẽ giống như quá trình 'sh' với đối số 'filename.sh'. Các shthông dịch viên được mở tập tin.

Mặt khác, nếu bạn tự chạy tập lệnh, hệ thống sẽ gọi chương trình thông dịch được chỉ định và nguồn cấp dữ liệu trong nội dung tập lệnh. Trong trường hợp này, quá trình này trông giống như 'filename.sh' không có đối số.

Bạn nên chắc chắn rằng bạn có một dòng bang:

#!/bin/bash
# bash script here

Một dòng bang là dòng đầu tiên trong tập lệnh và bắt đầu với hai ký tự giống nhau #!, đây là những gì hệ thống đọc khi nó cố thực thi tập lệnh và sau đó hệ thống chuyển tập lệnh đến chương trình ngay sau đó. Lưu ý rằng dòng này không liên quan gì đến bash và cũng hoạt động tốt với python và perl, mặc dù chúng là những ngôn ngữ rất khác nhau. Bạn sẽ sử dụng #!/usr/bin/pythonví dụ và sau đó làm theo nó với mã python.

Khi bạn có tập lệnh của mình, hãy đảm bảo bạn đã đặt quyền thực thi:

chmod a+x filename.sh

Sau đó, bạn có thể chạy tập lệnh theo quy trình riêng của mình:

./filename.sh

Hoặc đặt tệp vào một vị trí đã biết với tên chương trình đẹp, thích /usr/sbinvà chạy từ mọi nơi:

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

Và đây thực sự là lợi ích thiết thực của việc sử dụng dòng bang với quyền phù hợp - đó là tất cả về triển khai . Rất khó để khiến người dùng chạy tập lệnh nếu họ phải nhớ chương trình nào để chạy tập lệnh. Hãy nhớ đưa ra một đường dẫn đầy đủ đến tập lệnh mỗi lần họ muốn chạy nó. /usr/local/binVí dụ như đặt nó vào , và làm cho nó có thể thực thi được, có thể tiết kiệm rất nhiều đau buồn cho những người đang cố gắng sử dụng tập lệnh của bạn. Các chương trình này sau đó trở nên khả dụng cho tất cả người dùng trên máy tính của bạn.

Nó cũng tốt để nhận dạng. Nếu bạn đi vào topchương trình, một tập lệnh chạy không có dòng bang sẽ chỉ có tên của trình thông dịch tức là bash, perlhoặc python. Nhưng nếu một tập lệnh được chạy với quyền phù hợp, thì tên của tập lệnh sẽ hiển thị.

Lưu ý: Nếu bạn muốn phân phối một tập lệnh có thể truy cập được cho mọi người, thì vui lòng tạo một trang man và gói gỡ lỗi để cài đặt tập lệnh. Chúng ta cần giảm số lượng tập lệnh ngẫu nhiên trực tuyến và tăng số lượng các cuộc tranh luận có thể được gỡ cài đặt.


1
Bạn cũng có thể sử dụng thư mục bin cá nhân: tạo thư mục bin vào thư mục nhà của bạn đăng xuất và đăng nhập lại và sau đó bạn có thể chạy bất kỳ tập lệnh nào trong thư mục đó mà không cần sh hoặc ./.
papukaija

Tất nhiên, nhưng việc thêm thư mục nhà của bạn vào PATH của bạn có thể được xem là một chút đau đầu. Tốt hơn nên cài đặt mọi thứ. Mặc dù đã có một số thảo luận về việc thêm ~ / .local / bin vào đường dẫn theo mặc định để cho phép người dùng cài đặt các gói địa phương.
Martin Owens -doctormo-

Lưu ý rằng trình thông dịch mặc định là bash, không sh.
Nathan Osman

1
Đừng đặt tiện ích mở rộng trên tập lệnh, đặc biệt là khi bạn đặt nó vào PATH.
geirha

1
/usr/local/bincó lẽ tốt hơn sau đó /usr/sbin- nó chỉ ra rằng chương trình là cục bộ của máy này chứ không phải là một phần của phân phối.
glenn jackman

41

Phiên bản ngắn:

  • shlà trình thông dịch dòng lệnh (dấu gạch ngang).
    Chạy sh my_scriptlàm cho dash giải thích kịch bản.

  • ./cố gắng tìm ra trình thông dịch nào sẽ sử dụng, bằng cách nhìn vào dòng đầu tiên. Ví dụ #!/bin/bash, hoặc thậm chí #!/bin/ruby(trái ngược với chạy ruby my_script).


7
Nó không thực sự ./tìm thấy bất cứ thứ gì, đó là phương thức thực thi hệ thống nhìn vào hai byte đầu tiên của tệp.
Martin Owens -doctormo-

9
Chắc chắn rồi. Đây là một lời giải thích rất dài về tất cả. Tôi thực dụng :)
Stefano Palazzo

Khi bạn sử dụng shvà tập tin chứa sha-bang, điều đó có nghĩa là sha-bang sẽ bị bỏ qua hoặc nó sẽ mở shell nơi shliên kết quá và sau đó có thể một số shell khác hoặc nó làm gì :)?
Ini

5

Sự khác biệt bạn làm là,

  • với sh, bạn đang chạy một chương trình sẽ diễn giải các dòng trong kịch bản của bạn giống như bạn đã gõ chúng trên dấu nhắc tương tác của thiết bị đầu cuối,

  • với việc ./bạn đang tạo một phím tắt giả sử rằng tập lệnh nằm ngay tại thư mục hiện tại bạn đang ngồi VÀ nó sẽ được thực thi (vì ví dụ bạn đã ban hành chmod +x myscript.sh), giúp bạn tiết kiệm thời gian vô giá cho thời gian trong tương lai :-)


3
+1 vì là người duy nhất tuyên bố chính xác rằng tệp phải được thực thi.
Mikel

2
Lưu ý rằng với shcác tập tin không nhất thiết phải được thực thi.
Ini

3

Có ba lý do chính khiến bạn gặp lỗi:

  • tập tin không thể
    chạy được chmod +x <myscriptname.sh>để sửa nó
  • phân vùng không cho phép chạy tập lệnh (được gắn " noexec")
    sao chép tập lệnh vào/usr/local/bin
  • các #!dòng có lỗi
    chắc chắn rằng dòng đầu tiên là #!/bin/shhay#!/bin/bash

Nếu dòng đầu tiên của bạn có vẻ đúng nhưng vẫn không hoạt động, hãy đảm bảo tệp không có kết thúc dòng DOS.

Lỗi sẽ trông giống như thế này:

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

Bạn có thể sửa nó bằng cách chạy dos2unix <myscriptname.sh>hoặc nếu bạn không có điều đó ,
perl -p -i -e 's/\r\n$/\n/' <myscriptname.sh>.


0

Và câu trả lời là sh là tên của vỏ rất phổ biến. Nhưng lỗi thời và được thay thế bởi những người khác. Ngày nay sh được liên kết với các shell khác được cài đặt trên máy. ví dụ tôi đã bash putt ở đó. Chạy bất kỳ shell nào từ sh thường kích hoạt một số chế độ 'tương thích' với hành vi 'shell' ban đầu.

Vì vậy, giải pháp khá đơn giản. Hãy xem những gì đằng sau lệnh sh (ls -al / bin / sh) và đặt #! / Bin / anything_you_find_there làm dòng đầu tiên (hoặc nếu có đoạn mã nào đó trong tập lệnh của bạn chỉnh sửa nó).

Và thay vào đó, có thể có một số lỗi trong chính kịch bản. Giống như sự phụ thuộc được đáp ứng bởi sh, nhưng không phải là thông dịch viên thực sự được sử dụng.


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

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

Không /usr/sbin, đó là cho các công cụ quản trị không thiết yếu, /usr/local/binlà lựa chọn tốt hơn nếu bạn không muốn có ~/bin/, nhưng nên tránh sudocàng nhiều càng tốt.


Trên Ubuntu, mặc định ~/.profileđã có mã để thêm ~/bin, nếu nó tồn tại, thành PATH. Một lưu ý khác, đừng đặt phần mở rộng lên các tập lệnh.
geirha

1
Tôi đã tham khảo <myscriptname.sh>, nhưng lý do căn bản của việc không đưa tiện ích mở rộng vào tập lệnh là gì? Tôi thường làm vì có các tệp văn bản đơn giản hiển thị như thế giúp tôi không cố chỉnh sửa các tệp nhị phân mà tôi cũng giữ trong ~ / bin /. ( ls ~/bin/|wc -l = 428) Tôi đặt rất nhiều thứ trong đó;)
Joey1978

Hãy tưởng tượng bạn viết một kịch bản để đạt được một nhiệm vụ cụ thể. Sau đó, bạn nhận ra việc viết tập lệnh đặc biệt này trong python sẽ làm cho nó hiệu quả hơn nhiều, vì vậy bạn viết lại nó bằng python. Bây giờ bạn có hai lựa chọn. 1) Để lại phần mở rộng .sh rất dễ gây hiểu lầm hoặc 2) đổi tên tập lệnh và tìm kiếm và thay thế tất cả việc sử dụng tập lệnh để sử dụng tên mới. Nếu bạn nhìn vào các tập lệnh /bin/usr/binbạn sẽ thấy chúng không sử dụng tiện ích mở rộng.
geirha
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.