Làm thế nào để / usr / bin / env biết nên sử dụng chương trình nào?


62

Khi tôi sử dụng shebang #!/usr/bin/env pythonđể chạy tập lệnh, làm thế nào để hệ thống biết pythonnên sử dụng tập lệnh nào ? Nếu tôi tìm một pythonđường dẫn bin trong các biến môi trường, tôi không tìm thấy gì.

env | grep -i python

6
oh tôi nghĩ rằng tôi đã tìm ra nó - nó chỉ tìm kiếm $ PATH của bạn cho 'python'
tMC

Tôi cũng đã tự hỏi về điều đó. Và tại sao / usr / bin / env? trái ngược với / bin / env hoặc env, nếu nó chỉ nhận được một danh sách các đường dẫn từ env?
Faheem Mitha

Chỉ 'env' sẽ không hoạt động vì nó phải là đường dẫn đầy đủ. Chương trình 'env' thường được tìm thấy trong / user / bin / env. Trên một số distro, nó cũng có thể được tìm thấy là / bin / env, nhưng an toàn hơn khi đi với / usr / bin / env.
rettops

Câu trả lời:


54

Shebang mong muốn một đường dẫn đầy đủ đến trình thông dịch sẽ sử dụng nên cú pháp sau sẽ không chính xác:

#!python

Đặt đường dẫn đầy đủ như thế này có thể hoạt động:

#!/usr/local/bin/python

nhưng sẽ không di động như trăn có thể được cài đặt trong /bin, /opt/python/binhoặc bất cứ nơi nào vị trí khác.

Sử dụng env

#!/usr/bin/env python

là một phương thức cho phép một cách di động để chỉ định cho HĐH một đường dẫn đầy đủ tương đương với đường dẫn pythonđầu tiên được đặt trong PATH.


56

Dòng shebang (từ bang sharp sharp bang, tức là #!) được xử lý bởi kernel. Nhân không muốn biết về các biến môi trường như PATH. Vì vậy, tên trên dòng shebang phải là một đường dẫn tuyệt đối đến một tệp thực thi. Bạn cũng có thể chỉ định một đối số bổ sung để chuyển đến thực thi đó trước tên tập lệnh (với các hạn chế phụ thuộc hệ thống mà tôi sẽ không đi vào đây). Ví dụ: đối với tập lệnh Python, bạn có thể chỉ định

#!/usr/bin/python

trên dòng đầu tiên và khi bạn thực thi tập lệnh, nhân trên thực tế sẽ thực thi /usr/bin/python /path/to/script. Nhưng điều đó không thuận tiện: bạn cần chỉ định đường dẫn đầy đủ của lệnh. Điều gì nếu bạn có pythontrong /usr/binmột số máy và /usr/local/bintrên những người khác? Hoặc bạn muốn thiết lập của bạn PATHđể /home/joe/opt/python-2.5/binđể sử dụng một phiên bản cụ thể của Python? Vì kernel sẽ không PATHtìm kiếm cho bạn, nên ý tưởng là làm cho kernel chạy một lệnh mà lần lượt tìm kiếm trình thông dịch mong muốn trong PATH:

#!/fixed/path/to/path-lookup-command python

Điều đó path-lookup-commandphải lấy tên của một tệp thực thi làm đối số và tra cứu nó PATHvà thực thi nó: kernel sẽ chạy /fixed/path/to/path-lookup-command python /path/to/script. Khi nó xảy ra, envlệnh làm điều đó. Mục đích chính của nó là để chạy một lệnh với một môi trường khác, nhưng vì nó tìm kiếm tên lệnh trong $PATHđó, nó hoàn hảo cho mục đích của chúng tôi ở đây.

Mặc dù đây không phải là chính thức đảm bảo, hệ thống Unix lịch sử cung cấp envtrong /usr/binvà các hệ thống hiện đại đã giữ vị trí đó một cách chính xác vì việc sử dụng rộng rãi #!/usr/bin/env. Vì vậy, trong thực tế, cách để xác định rằng tập lệnh phải được thực thi bởi trình thông dịch Python yêu thích của người dùng là

#!/usr/bin/env python

2
cái nào được ưa thích giữa envwhich? kể từ đó cũng sẽ có được khả năng thực thi đủ điều kiện nhất từ ​​môi trường PATH của tôi.
Nikhil Mulley

8
@NikhilMulley whichtìm thấy tệp thực thi và in đường dẫn của nó. envtìm chương trình được chỉ định bởi đối số đầu tiên và thực thi nó, truyền cho nó các đối số còn lại.
Kevin

3
Vì vậy, đó envlà một phiên bản eval về whichcơ bản.
Nikhil Mulley

6

Phải, nên chạy:

env | grep PATH

$ PATH của bạn là một danh sách các thư mục. Unix sẽ đi qua danh sách các thư mục đó, theo thứ tự, cho đến khi tìm thấy "python".

Bạn có thể xem thư mục nào nó tìm thấy bằng lệnh 'which':

which python

Thật thú vị, tôi đang thấy một sự khác biệt trong con trăn sys.pathgiữa một env $ env python3 ( ['', '/home/user/test', '/usr/lib/python3.4', '/usr/lib/python3.4/plat-x86_64-linux-gnu', '/usr/lib/python3.4/lib-dynload', '/home/user/.local/lib/python3.4/site-packages', '/usr/lib/python3.4/site-packages', '/usr/local/lib/python3.4/dist-packages', '/usr/lib/python3/dist-packages']) và ./env/bin/python3 (['', '/home/user/test', '/usr/lib/python3.4', '/usr/lib/python3.4/plat-x86_64-linux-gnu', '/usr/lib/python3.4/lib-dynload', '/home/user/test/env3/lib/python3.4/site-packages']) được kích hoạt .
ThorSummoner
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.