Chúng được phân chia theo quy trình
Những người trả lời khác đã giúp tôi hiểu rằng phạm vi biến vỏ là về các quá trình và hậu duệ của họ .
Khi bạn nhập một lệnh như ls
trên dòng lệnh, bạn thực sự đang tiến hành một quy trình để chạy ls
chương trình. Quá trình mới có vỏ của bạn là cha mẹ của nó.
Bất kỳ quá trình nào cũng có thể có các biến "cục bộ" riêng, không được truyền cho các tiến trình con. Nó cũng có thể đặt các biến "môi trường". Sử dụng export
tạo ra một biến môi trường. Trong cả hai trường hợp, các quá trình không liên quan (đồng đẳng của bản gốc) sẽ không thấy biến; chúng tôi chỉ kiểm soát những gì quá trình con nhìn thấy.
Giả sử bạn có bash shell, chúng ta sẽ gọi A. Bạn gõ bash
, tạo ra bash shell con, chúng ta sẽ gọi B. Mọi thứ bạn gọi export
trong A vẫn sẽ được đặt trong B.
Bây giờ, trong B, bạn nói FOO=b
. Một trong hai điều sẽ xảy ra:
- Nếu B không nhận được (từ A) một biến môi trường được gọi
FOO
, nó sẽ tạo một biến cục bộ. Con của B sẽ không nhận được (trừ khi B gọi export
).
- Nếu B đã nhận (từ A) một biến môi trường được gọi là
FOO
chính nó, nó sẽ tự sửa đổi nó và các con sau đó của nó . Con của B sẽ thấy giá trị mà B gán. Tuy nhiên, điều này sẽ không ảnh hưởng đến A.
Đây là một bản demo nhanh.
FOO=a # set "local" environment variable
echo $FOO # 'a'
bash # forks a child process for the new shell
echo $FOO # not set
exit # return to original shell
echo $FOO # still 'a'
export FOO # make FOO an environment variable
bash # fork a new "child" shell
echo $FOO # outputs 'a'
FOO=b # modifies environment (not local) variable
bash # fork "grandchild" shell
echo $FOO # outputs 'b'
exit # back to child shell
exit # back to original shell
echo $FOO # outputs 'a'
Tất cả điều này giải thích vấn đề ban đầu của tôi: Tôi đặt GEM_HOME
trong vỏ của mình, nhưng khi tôi gọi bundle install
, điều đó đã tạo ra một quy trình con. Bởi vì tôi đã không sử dụng export
, quá trình con không nhận được vỏ GEM_HOME
.
Không xuất khẩu
Bạn có thể "hủy xuất" một biến - ngăn không cho nó được truyền cho trẻ em - bằng cách sử dụng export -n FOO
.
export FOO=a # Set environment variable
bash # fork a shell
echo $FOO # outputs 'a'
export -n FOO # remove environment var for children
bash # fork a shell
echo $FOO # Not set
exit # back up a level
echo $FOO # outputs 'a' - still a local variable
FOO=bar
, điều đó đặt giá trị cho quá trình shell hiện tại. Nếu sau đó tôi chạy một chương trình như (bundle install
), thì nó tạo ra một tiến trình con, không có quyền truy cậpFOO
. Nhưng nếu tôi đã nóiexport FOO=bar
, quá trình con (và con cháu của nó) sẽ có quyền truy cập vào nó. Đến lượt mình, một trong số họ có thể gọiexport FOO=buzz
để thay đổi giá trị cho con cháu của nó hoặc chỉFOO=buzz
thay đổi giá trị cho chính nó. Điều đó có đúng không?