.sh chỉ định gia hạn?


12

Tại sao một số hệ thống sẽ chạy một .shtệp chỉ bằng cách chỉ định tên tệp mà không có phần mở rộng và các hệ thống khác yêu cầu tên cộng với phần mở rộng? Trong trường hợp của tôi, tôi đang cố gắng viết một loạt các lệnh theo các hướng dẫn này .

Tôi đang chỉ định tiện ích mở rộng ngay bây giờ nhưng có thể chạy các lệnh mà không cần .shthiết hơn.


4
Sử dụng .shnhư một tiện ích mở rộng trong nhiều trường hợp được coi là thực tiễn xấu: Nó trái với cách các lệnh khác được đặt tên (bạn không chạy ls.elf), nó thường gây hiểu lầm (nếu bạn foo.shbắt đầu với #!/bin/bash, thì chạy sh foo.shsẽ chạy nó với một trình thông dịch khác với nó được tạo cho ) và nếu bạn viết lại foo.shthành chương trình Python, sử dụng tiện ích mở rộng đó có nghĩa là bạn cần chọn giữa việc giữ tên gây hiểu lầm và viết lại mọi chương trình gọi nó.
Charles Duffy

2
... nơi mà nó một thực hành tốt nhất là thư viện vỏ, không lệnh với +xbộ - nơi foo.shlà một thư viện có thể được bắt nguồn vào bất kỳ vỏ POSIX, foo.bashcó thể được bắt nguồn vào bash, foo.kshvào ksh vv
Charles Duffy

Câu trả lời:


39

Bạn đang bối rối. Phần .shmở rộng chỉ là một gợi ý cho con người và hoàn toàn KHÔNG ảnh hưởng đến cách hệ thống xử lý tệp. Unix / Linux đã không tạo ra Secrets.pdf.exelỗi lầm của Windows .

Đây là những gì xảy ra khi bạn gõ foo:

  1. Chuyển hướng cho STDIN, STDOUTSTDERRđược thiết lập.

  2. Shell kiểm tra bảng băm bên trong của nó để xem nó đã biết một $PATHmục nhập chưa foo. Nếu không tồn tại, shell sẽ tìm kiếm các thư mục trong đó $PATH, tìm kiếm một tệp foocó tên bit Thực thi được đặt trong các quyền của tệp. Chiến foothắng đầu tiên .

  3. Nếu hai byte đầu tiên của tệp foo#!, chuỗi tiếp theo là tên của trình thông dịch sẽ chạy. Do đó, #!/bin/bashgiới thiệu một tập lệnh Bash, #!/usr/bin/perlgiới thiệu một tập lệnh Perl, v.v.

  4. Nếu tệp bắt đầu bằng \177ELF, đó là tệp nhị phân thực thi và ld.sokhởi động nó.

Đọc man execveman ld.sogiải thích chi tiết hơn.


15
Có, trên Linux, bạn có thể bấm đúp vào Secrets.pdf mà không có manh mối nào về tên mà nó thực sự có thể thực thi được;)
OrangeDog

1
@OrangeDog Tôi biết bạn đang nói đùa, nhưng tôi cảm thấy mình phải chỉ ra rằng bit thực thi ( chmod +x) giải quyết được khá nhiều điều này, phải không?
wchargein

3
@WChargin Điều đó phụ thuộc vào mức độ hoạt động của hệ thống tệp của bạn (ví dụ: chia sẻ mạng được chia sẻ hoặc phân vùng NTFS có thể thiết lập tối ưu xbit trên mọi thứ) và nơi tệp đến (mọi quá trình kiểm soát thư mục có thể bị lừa để thiết lập quyền) . Vì vậy, nó giảm nhẹ nó, nhưng tôi sẽ không nói rằng nó giải quyết nó.
IMSoP

2
@WChargin, tuy nhiên, nhưng tôi nghĩ rằng quan điểm của anh ấy thường là các trình quản lý tệp không hiển thị bit thực thi, tức là không có "gợi ý cho con người" như một phần mở rộng.
Paul Draper

1
Tôi không bao giờ bấm nhầm Secrets.pdf.exevì tôi luôn vô hiệu hóa hide file extensiontính năng ngu ngốc
phuclv

12

Điểm mấu chốt là đây: Các phần mở rộng không liên quan trong bất kỳ hệ thống giống như Unix. Tên tệp chỉ là tên và không ảnh hưởng đến việc liệu tập lệnh hoặc tệp thực thi được biên dịch có thể chạy hay không . Một lập trình viên có thể thêm một .shphần mở rộng để chỉ định rằng một tệp là shell script hoặc .pycho kịch bản python, nhưng không giống như Windows, bất kỳ unix nào không quan tâm đến việc đặt tên, nó quan tâm đến các quyền.

Vấn đề là sự cho phép thực thi được cấp cho một tập tin. Mà bạn có thể kiểm tra với

ls -l /path/to/file

Chạy thực thi

Để chạy script thường có một số cách.

  • Nếu thư mục hiện tại của bạn giống với tập lệnh và tập lệnh có quyền thực thi, bạn có thể chạy nó như vậy ./my_script_name. Các thư mục .có nghĩa là hiện tại.
  • Nếu thư mục hiện tại của bạn khác và tập lệnh có quyền thực thi, bạn có thể chạy nó bằng cách chỉ định đường dẫn đầy đủ: /home/user/bin/my_script_name

(Trên đây hai phương pháp dựa vào việc thiết lập sự cho phép thực thi; hay không tập được một phần của $PATHbiến là không liên quan Sự hiện diện của. #!Dòng cũng có vấn đề; không có nó, nó kịch bản sẽ được thực hiện bằng vỏ hiện tại bạn đã mở Nếu tôi có. cshKịch bản không có dòng đó và cố gắng chạy nó trong bash với./my_script.csh , nó sẽ thất bại)

  • Nếu tập lệnh của bạn nằm trong thư mục là một phần của $PATHbiến, bạn có thể chạy nó chỉ bằng cách gọi tên. Bạn có thể gọi chmodlệnh trong dòng lệnh chỉ bằng cách gõ tên của nó vì nó nằm trong /binthư mục./binluôn là một phần của $PATHbiến. Trong trường hợp này, quyền và vị trí của tập lệnh có thể thực thi được
  • Chỉ định một trình thông dịch là lệnh và kịch bản làm đối số. Bằng cách đó, script sẽ đóng vai trò là tệp đầu vào cho trình thông dịch.
  • Tìm nguồn cung cấp một tập tin. Các . filename.shhoặc source filename.shsẽ làm cho kịch bản được đối xử như thể nó là đầu vào bàn phím, ví dụ như nếu nó được gõ vào dòng lệnh trực tiếp. Trong trường hợp này, quyền và vị trí thực thi không thành vấn đề

Ví dụ

Ví dụ # 1, chạy với trình thông dịch, để thực thi quyền

$-> ls -l abc.py                                                               
-rw-rw-r-- 1 xieerqi xieerqi 44 Apr 27 22:39 abc.py
$-> python abc.py                                                              
a
b
c

Ví dụ # 2, chạy với ./bộ quyền thực thi, bộ dòng shebang.

$-> cat abc.py                                                                 
#!/usr/bin/env python
for letter in 'a' 'b' 'c' :
   print letter
$-> ls -l abc.py
-rwxrwxr-x 1 xieerqi xieerqi 66 Apr 27 23:02 abc.py*
$-> ./abc.py                                                                   
a
b
c

Ví dụ # 3, chạy mà không có bộ dòng shebang (không thành công, vì bash không thể đọc tập lệnh python; không có dòng shebang nào giả định trình bao hiện tại làm trình thông dịch)

$-> cat abc.py                                                                 
for letter in 'a' 'b' 'c' :
   print letter
$-> ./abc.py                                                                   
./abc.py: 2: ./abc.py: Syntax error: word unexpected (expecting "do")

Ví dụ # 4, tập lệnh đang chạy có quyền thực thi đặt thư mục biểu mẫu là một phần của $PATHbiến

#  /home/xieerqi/bin is part of my path variable
$-> echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/opt/microchip/xc16/v1.25/bin:/opt/microchip/xc32/v1.40/bin:/opt/microchip/xc8/v1.35/bin:/home/xieerqi/bin:/home/xieerqi/bin/sh

$-> # current directory is /home/xieerqi
$-> pwd
/home/xieerqi
$-> # move the file to ~/bin
$-> mv ~/abc.py ~/bin/abc.py
$-> # now I can run it just by calling the name
$-> abc.py
/home/xieerqi/bin/abc.py: 2: /home/xieerqi/bin/abc.py: Syntax error: word unexpected (expecting "do")
$-> # Syntax error because again, no interpreter specified.                    
$-> # must add #!/usr/bin/env python
$-> vi /home/xieerqi/bin/abc.py          
$-> # after adding the line with vi text editor, we can run
$-> abc.py                                                                     
a
b
c

Ví dụ # 5, xóa tiện ích mở rộng, vẫn chạy vì tiện ích mở rộng không quan trọng, nhưng nó có quyền và là một phần của $PATH:

$-> mv ~/bin/abc.py  ~/bin/abc                                                 
$-> abc
a
b
c

Tôi đã chạy lệnh và tôi nhận được '-rwxr-x ---' này. Tôi muốn giá trị gì để đọc và làm cách nào để thay đổi nó?
Philip Kirkbride

Hay bạn đang nói rằng tôi chỉ nên đổi tên 'filename.sh' thành 'filename'?
Philip Kirkbride

1
@PhilipKirkbride Tên không liên quan. Làm thế nào để bạn chạy lệnh của bạn? Nó đâu rồi ? Là thư mục nó là một phần của bạn PATH?
Sergiy Kolodyazhnyy

@PhilipKirkbride Hãy để tôi mở rộng câu trả lời của mình sau một phút để làm cho nó rõ ràng hơn.
Sergiy Kolodyazhnyy

1
Hãy xem man chmodđể biết cách đặt quyền
Nick Mertin

6

Giải thích tốt ở đây rồi. Tôi chỉ muốn thêm rằng lý tưởng là bạn không nên sử dụng phần mở rộng tệp cho tệp thực thi.

Thông thường bạn cần phải hoàn thành một cái gì đó tương đối dễ dàng và bạn bắt đầu với một kịch bản shell nhỏ. Theo thời gian, bạn bắt đầu thêm ngày càng nhiều chức năng vào tập lệnh của mình, cho đến khi đến lúc nó trở nên không thể nhận ra hoặc bạn cần một số chức năng mà bạn không thể thực hiện dễ dàng với tập lệnh shell và suy nghĩ về việc viết lại tập lệnh shell này bằng ngôn ngữ khác (python , perl, ...?).

Viết lại từ đầu thường được coi là một lỗi, nhưng đối với các tập lệnh thì có thể có ý nghĩa bởi vì thông thường chúng không lớn hoặc có nhiều chức năng. Nhưng hãy giả sử rằng có thể viết lại từ đầu bằng một số ngôn ngữ khác, duy trì chức năng và thông số / cờ của tập lệnh shell ban đầu.

Người dùng của tập lệnh này không cần phải biết về sự thay đổi ngôn ngữ này, họ sẽ tiếp tục thực hiện cùng một lệnh và nó sẽ tiếp tục hoạt động.

Nếu tập lệnh của bạn được đặt tên do-something.sh, nó có thể tiếp tục do-something.sh, nhưng bây giờ nó được viết bằng python (ví dụ), và vì vậy gợi ý ban đầu của bạn bây giờ là hoàn toàn sai lệch.


4

Để chạy các tệp mà không có tiện ích mở rộng, bạn không cần phải làm gì nhiều, chỉ cần đảm bảo rằng bạn có (trong trường hợp tập lệnh bash) dòng shebang thích hợp ở dòng đầu tiên:

#!/bin/bash

sau đó bạn cũng cần tho làm cho tập tin thực thi được cho hệ thống

chmod 755 yourfilename

Điều này giống như sử dụng chmod +x yourfilenamecác con số được giải thích dễ dàng.

Nó là một số ba số bát phân được thêm vào, số thứ nhất là viết tắt của người dùng, số thứ hai cho nhóm và số thứ ba cho những người khác, nhiều hơn về những gì bạn có thể tìm thấy ở đây .

Và nếu bạn ở cùng thư mục với tập lệnh của mình, đừng quên sử dụng ./như thế này:

./yourfilename

Đã thử điều này. Thật không may, không có sự khác biệt so với kết quả ban đầu.
Philip Kirkbride

@PhilipKirkbride hãy xem câu trả lời sửa đổi của tôi, điều này sẽ giúp làm sáng tỏ hơn.
Videonauth

0

Hậu tố .sh thực sự có thể cản trở, bởi vì để chạy nó, bạn phải gõ myscript.sh thay vì chỉ myscript sẽ không hoạt động. Tốt hơn là chỉ gọi nó là "myscript" không có hậu tố .sh và việc sử dụng nhanh lệnh "file" sẽ cho bạn biết nếu đó là tệp thực thi nhị phân (định dạng ELF trên linux) hoặc tập lệnh shell hay bất kỳ loại tập lệnh nào khác.

QĐOS (Hệ điều hành nhanh và bẩn, sau này được IBM đổi tên thành "DOS" sau khi mirosoft vi phạm bản quyền và bán trái phép cho họ) và các bản CP / M rẻ tiền khác, bao gồm cả windows, trộn lẫn tất cả những thứ này vì trên các hệ thống đó không có những thứ như quyền thực thi trên tập tin. Điều này đã dẫn đến vô số f'up bảo mật trong 30-40 năm qua. Trên thực tế, chỉ vài phút trước tôi đã nhận được một vài thư rác với tệp zip bị bẫy được đổi tên thành MYPICTURE.JPG.zip :)

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.