Sự khác biệt giữa bộ, xuất và env và khi nào tôi nên sử dụng mỗi?


112

Mỗi lần như vậy tôi sẽ bash ra một tập lệnh bash và nó gây ấn tượng với tôi có một vài cách để thiết lập một biến:

key=value
env key=value
export key=value

Khi bạn đang ở trong một tập lệnh hoặc một lệnh đơn lẻ (ví dụ: tôi sẽ thường xâu chuỗi một biến với trình khởi chạy Wine để đặt tiền tố Wine đúng) những điều này dường như có thể hoán đổi cho nhau nhưng chắc chắn đó không phải là trường hợp.

Sự khác biệt giữa ba phương pháp này là gì và bạn có thể cho tôi một ví dụ về thời điểm tôi đặc biệt muốn sử dụng từng phương pháp không?

Chắc chắn có liên quan đến sự khác biệt giữa `VAR = ...` và` export VAR = ... `là gì? nhưng tôi muốn biết làm thế nào envphù hợp với điều này quá, và một số ví dụ cho thấy lợi ích của mỗi cũng sẽ tốt đẹp :)


5
Lưu ý rằng đó export key=valuelà cú pháp mở rộng và không nên được sử dụng trong các tập lệnh di động (nghĩa là #! /bin/sh).
Simon Richter

Câu trả lời:


110

Hãy để chúng tôi xem xét một ví dụ cụ thể. Các greplệnh sử dụng một biến môi trường được gọi là GREP_OPTIONSđể thiết lập tùy chọn mặc định.

Hiện nay. Cho rằng tệp test.txtchứa các dòng sau:

line one
line two

chạy lệnh grep one test.txtsẽ trở lại

line one

Nếu bạn chạy grep với -vtùy chọn, nó sẽ trả về các dòng không khớp, vì vậy đầu ra sẽ là

line two

Bây giờ chúng tôi sẽ cố gắng đặt tùy chọn với một biến môi trường.

  1. Các biến môi trường được đặt mà không có exportsẽ không được kế thừa trong môi trường của các lệnh bạn đang gọi.

    GREP_OPTIONS='-v'
    grep one test.txt
    

    Kết quả:

    line one

    Rõ ràng, tùy chọn -vđã không được thông qua grep.

    Bạn muốn sử dụng biểu mẫu này khi bạn chỉ đặt một biến cho trình bao sử dụng, ví dụ như trong for i in * ; dobạn không muốn xuất $i.

  2. Tuy nhiên, biến được truyền vào môi trường của dòng lệnh cụ thể đó, vì vậy bạn có thể làm

    GREP_OPTIONS='-v' grep one test.txt

    sẽ trả lại dự kiến

    line two

    Bạn sử dụng biểu mẫu này để tạm thời thay đổi môi trường của trường hợp cụ thể này của chương trình được khởi chạy.

  3. Xuất một biến làm cho biến được kế thừa:

    export GREP_OPTIONS='-v'
    grep one test.txt
    

    trả lại ngay

    line two

    Đây là cách phổ biến nhất để thiết lập các biến để sử dụng các quy trình được bắt đầu sau đó trong trình bao

  4. Điều này đã được thực hiện trong bash. exportlà một bash dựng sẵn; VAR=whateverlà cú pháp bash. env, mặt khác, là một chương trình trong chính nó. Khi envđược gọi, những điều sau đây xảy ra:

    1. Lệnh envđược thực thi như một tiến trình mới
    2. env sửa đổi môi trường và
    3. gọi lệnh được cung cấp như là một đối số. Các envquá trình được thay thế bằng các commandquá trình.

    Thí dụ:

    env GREP_OPTIONS='-v' grep one test.txt

    Lệnh này sẽ khởi chạy hai quy trình mới: (i) env và (ii) grep (thực ra, quy trình thứ hai sẽ thay thế quy trình đầu tiên). Từ quan điểm của grepquá trình, kết quả hoàn toàn giống như chạy

    GREP_OPTIONS='-v' grep one test.txt

    Tuy nhiên, bạn có thể sử dụng thành ngữ này nếu bạn ở ngoài bash hoặc không muốn khởi chạy shell khác (ví dụ: khi bạn đang sử dụng exec()họ hàm thay vì system()cuộc gọi).

Ghi chú thêm về #!/usr/bin/env

Đây cũng là lý do tại sao thành ngữ #!/usr/bin/env interpreterđược sử dụng chứ không phải #!/usr/bin/interpreter. envkhông yêu cầu một đường dẫn đầy đủ đến một chương trình, bởi vì nó sử dụng execvp()hàm tìm kiếm thông qua PATHbiến giống như shell, và sau đó tự thay thế bằng lệnh chạy. Do đó, nó có thể được sử dụng để tìm ra nơi một trình thông dịch (như perl hoặc python) "ngồi" trên đường dẫn.

Điều đó cũng có nghĩa là bằng cách sửa đổi đường dẫn hiện tại, bạn có thể ảnh hưởng đến biến thể python nào sẽ được gọi. Điều này làm cho những điều sau đây có thể:

echo -e '#!/usr/bin/bash\n\necho I am an evil interpreter!' > python
chmod a+x ./python
export PATH=.
calibre

thay vì ra mắt Calibre, sẽ dẫn đến

I am an evil interpreter!

Tại sao GREP_OPTIONS = '- v' grep một test.txt hoạt động? Tôi nghĩ rằng nó cần một dấu chấm phẩy sau '-v' (nhưng tôi đã thử nó và thực tế nó hoạt động.)
Joe

2
Bởi vì với dấu chấm phẩy, nó được hiểu là hai lệnh bash riêng biệt; cái đầu tiên đặt biến (không xuất nó) và cái thứ hai bắt đầu với một môi trường không có biến được xuất. Tuy nhiên, không có dấu chấm phẩy, đây là một lệnh (grep), đi trước bằng cách đặt môi trường cục bộ.
tháng 1

Trường hợp tất cả các biến envđến từ đâu? Ý tôi là khi bạn mở một shell mới, bạn luôn có một vài biến. Vì vậy, một số chương trình phải có exported, phải không?
Pithikos

1
Các biến môi trường @Pithikos được đặt bằng cách "tìm nguồn cung ứng môi trường." Theo mặc định, bash sẽ cung cấp một bashrc trên toàn hệ thống (hoặc profile.d hoặc bash_profile). Sau đó, nó nguồn người dùng của bạn ~ / .bashrc (và / hoặc ~ / .bash_profile). Một trong hai tệp này có thể chứa các lệnh bash để lấy các tập lệnh khác, do đó cuối cùng bạn có thể có các biến môi trường đến từ mọi nơi.
Eric

5
Thế còn set var=blah?
CMCDragonkai
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.