it-swarm-vi.com

Tại sao chúng ta sử dụng "./" (dấu gạch chéo) để thực thi một tệp trong Linux / UNIX?

Tại sao chúng ta sử dụng ./filename để thực thi một tập tin trong linux?

Tại sao không nhập nó như các lệnh khác gcc, ls vv ...

89
Renjith G

Trong Linux, UNIX và các hệ điều hành có liên quan, . Biểu thị thư mục hiện tại. Vì bạn muốn chạy một tệp trong thư mục hiện tại của mình và thư mục đó không nằm trong $PATH, Bạn cần bit ./ Để báo cho Shell biết nơi thực thi. Vì vậy, ./foo Có nghĩa là chạy tệp thực thi có tên foo có trong thư mục này.

Bạn có thể sử dụng type hoặc which để có được đường dẫn đầy đủ của bất kỳ lệnh nào được tìm thấy trong $PATH.

80
badp

Câu trả lời theo nghĩa đen là như những người khác đã đưa ra: bởi vì thư mục hiện tại không nằm trong $PATH Của bạn.

Nhưng tại sao? Tóm lại, đó là vì bảo mật. Nếu bạn đang tìm trong thư mục chính của người khác (hoặc/tmp) và nhập chỉ gcc hoặc ls, bạn muốn biết bạn đang chạy phiên bản thật chứ không phải phiên bản độc hại người bạn chơi khăm đã viết mà xóa tất cả các tập tin của bạn. Một ví dụ khác sẽ là test hoặc [, Có thể ghi đè các lệnh đó trong tập lệnh Shell, nếu Shell của bạn không có các lệnh đó là tích hợp.

. Làm mục nhập cuối cùng trong đường dẫn của bạn an toàn hơn một chút, nhưng có những cuộc tấn công khác sử dụng điều đó. Một cách dễ dàng là khai thác các lỗi chính tả phổ biến, như sl hoặc ls-l. Hoặc, tìm một lệnh phổ biến không được cài đặt trên hệ thống này - vim, ví dụ, vì các hệ thống quản trị hệ thống có khả năng cao hơn mức trung bình để nhập loại đó.

103
mattdm

Nếu bạn muốn nói, tại sao bạn cần ./ khi bắt đầu - đó là bởi vì (không giống như trong Windows), thư mục hiện tại không phải là một phần của đường dẫn của bạn theo mặc định. Nếu bạn chạy:

$ ls

shell của bạn tìm kiếm ls trong các thư mục trong biến môi trường PATH của bạn (echo $PATH để xem nó) và chạy tệp thực thi đầu tiên được gọi là ls mà nó tìm thấy. Nếu bạn gõ:

$ a.out

shell cũng sẽ làm như vậy - nhưng có lẽ nó sẽ không tìm thấy một tệp thực thi được gọi là a.out. Bạn cần nói với Shell nơi a.out là - nó nằm trong thư mục hiện tại (.) Thì đường dẫn là ./a.out.

Nếu bạn hỏi tại sao lại gọi là "a.out", thì đó chỉ là tên tệp đầu ra mặc định cho gcc. Bạn có thể thay đổi nó bằng dòng lệnh -o arg. Ví dụ:

$ gcc test.c -o test
$ ./test
45
Simon Whitaker

Bạn có thể thử thêm :. đến biến $ PATH của bạn.

Hãy thử ALT + F2 và gõ: gksudo gedit /etc/environment nếu chạy Linux/GTK (đây là những gì bạn có nếu sử dụng Ubuntu).

TUY NHIÊN, tôi thực sự khuyên bạn KHÔNG nên làm điều đó. Đó là xấu xấu xấu và xấu.

Bạn biết đấy, những thứ đó hoạt động như thế này từ năm 1970. Có một lý do tại sao thư mục hiện tại không được bao gồm trong $ PATH.

. là thư mục hiện tại

.something sẽ là một tệp ẩn (Nhập "ALT +" để làm cho chúng xuất hiện trong Nautilus hoặc thử "ls -la ".

./someProgram.sh là những gì bạn gõ để CHẠY một sốProPro.sh thực thi trong thư mục hiện tại.

.somethingElse có nghĩa là bạn có một tệp thực thi ẩn trong thư mục hiện tại, đó là một ý tưởng tồi.

4
tiktak

Trên thực tế, quy tắc đầy đủ hơn: nếu có dấu gạch chéo / Trong đường dẫn, đừng tìm kiếm PATH

Trước khi chúng ta đi vào lý do, trước tiên bạn nên biết về thực tế này: chạy một trong hai:

bin/someprog

hoặc là:

/bin/someprog

hoặc là:

cd bin
./myexec

thực hiện bin/someprog mà không cần tìm kiếm biến PATH với cùng lý do: tất cả bin/someprog, /bin/someprog./someprog có dấu gạch chéo / Trong đó.

someprog một mình không có dấu gạch chéo /, và do đó chỉ tìm kiếm trong PATH.

POSIX 7 chỉ định quy tắc này tại: http: //pub.opengroup.org/onlinepub/9699919799/utilities/V3_chap02.html#tag_18_09_01_01

Cơ sở lý luận cho quy tắc / POSIX PATH

Giả sử rằng đang chạy:

someprog

sẽ tìm kiếm:

  • liên quan đến CWD trước
  • liên quan đến PATH sau

Sau đó, nếu bạn muốn chạy /bin/someprog Từ bản phân phối của mình và bạn đã làm:

someprog

đôi khi nó sẽ hoạt động, nhưng những cái khác thì nó sẽ thất bại, vì bạn có thể đang ở trong một thư mục chứa một chương trình someprog khác không liên quan.

Do đó, bạn sẽ sớm biết rằng điều này không đáng tin cậy và cuối cùng bạn sẽ luôn sử dụng các đường dẫn tuyệt đối khi bạn muốn sử dụng PATH, do đó đánh bại mục đích của PATH.

Đây cũng là lý do tại sao có các đường dẫn tương đối trong PATH của bạn là một ý tưởng thực sự tồi tệ. Tôi đang nhìn bạn, node_modules/bin .

Ngược lại, giả sử rằng đang chạy:

./someprog

Sẽ tìm kiếm:

  • liên quan đến PATH trước
  • liên quan đến CWD sau

Sau đó, nếu bạn vừa tải xuống tập lệnh someprog từ kho git và muốn chạy nó từ CWD, bạn sẽ không bao giờ chắc chắn rằng đây là chương trình thực tế sẽ chạy, bởi vì có thể bản phân phối của bạn có:

/bin/someprog

đó là trong bạn PATH từ một số gói bạn đã cài đặt sau khi uống quá nhiều sau Giáng sinh năm ngoái.

Do đó, một lần nữa, bạn sẽ buộc phải luôn chạy các tập lệnh cục bộ liên quan đến CWD với các đường dẫn đầy đủ để biết bạn đang chạy gì:

"$(pwd)/someprog"

điều này cũng sẽ vô cùng khó chịu.

Một quy tắc khác mà bạn có thể muốn đưa ra là:

đường dẫn tương đối chỉ sử dụng PATH, đường dẫn tuyệt đối chỉ CWD

nhưng một lần nữa, điều này buộc người dùng luôn phải sử dụng các đường dẫn tuyệt đối cho các tập lệnh không phải PATH với "$(pwd)/someprog".

Quy tắc tìm kiếm đường dẫn / Cung cấp một giải pháp dễ nhớ cho vấn đề về:

  • dấu gạch chéo: không sử dụng PATH
  • không gạch chéo: chỉ sử dụng PATH

điều này giúp bạn luôn dễ dàng biết được những gì bạn đang chạy, bằng cách dựa vào thực tế là các tệp trong thư mục hiện tại có thể được biểu thị dưới dạng ./somefile hoặc somefile, và do đó, nó mang ý nghĩa đặc biệt đối với một trong số chúng.

Đôi khi, hơi khó chịu khi bạn không thể tìm kiếm some/prog Liên quan đến PATH, nhưng tôi không thấy giải pháp nào cho việc này.