Câu trả lời:
export
làm cho biến có sẵn cho các quy trình phụ.
Đó là,
export name=value
có nghĩa là tên biến có sẵn cho bất kỳ quy trình nào bạn chạy từ quy trình shell đó. Nếu bạn muốn một quy trình sử dụng biến này, hãy sử dụng export
và chạy quy trình từ trình bao đó.
name=value
có nghĩa là phạm vi biến được giới hạn trong trình bao và không có sẵn cho bất kỳ quy trình nào khác. Bạn sẽ sử dụng điều này cho các biến vòng lặp (nói), các biến tạm thời, v.v.
Điều quan trọng cần lưu ý là việc xuất một biến không làm cho nó có sẵn cho các tiến trình cha. Đó là, việc chỉ định và xuất một biến trong một quy trình được sinh ra sẽ không làm cho nó có sẵn trong quy trình đưa ra nó.
name=value command
không làm cho biến có sẵn trong quy trình phụ command
.
Những người khác đã trả lời rằng xuất khẩu làm cho biến có sẵn cho các mạng con và điều đó đúng nhưng chỉ là tác dụng phụ. Khi bạn xuất một biến, nó đặt biến đó trong môi trường của shell hiện tại (tức là shell gọi putenv(3)
hoặc setenv(3)
).
Môi trường của một quá trình được kế thừa qua exec, làm cho biến có thể nhìn thấy trong các lớp con.
Chỉnh sửa (với quan điểm 5 năm): đây là một câu trả lời ngớ ngẩn. Mục đích của 'xuất khẩu' là tạo ra các biến "trong môi trường của các lệnh được thực hiện sau đó", cho dù các lệnh đó là chuỗi con hay quy trình con. Một triển khai ngây thơ sẽ chỉ đơn giản là đặt biến trong môi trường của trình bao, nhưng điều này sẽ làm cho nó không thể thực hiện được export -p
.
bash
, xuất thực sự thêm biến vào môi trường của shell hiện tại, nhưng đây không phải là trường hợp với dash
. Dường như với tôi rằng việc thêm biến vào môi trường của shell hiện tại là cách đơn giản nhất để thực hiện ngữ nghĩa của nó export
, nhưng hành vi đó không bắt buộc.
dash
phải làm gì với điều này. Các poster ban đầu được hỏi cụ thể về bash
.
bash
nhưng áp dụng như nhau cho bất kỳ biến thể bourne-shell. Quá cụ thể và cung cấp câu trả lời chỉ áp dụng cho bash
là một tội ác lớn.
bash
là jQuery của shell.
export makes the variable available to subshells, and that is correct
Đây là một cách sử dụng thuật ngữ rất khó hiểu. Subshells không cần export
kế thừa các biến. Các quy trình làm.
Người ta nói rằng không cần thiết phải xuất khẩu bash khi sinh ra các mạng con, trong khi những người khác nói hoàn toàn ngược lại. Điều quan trọng cần lưu ý sự khác biệt giữa subshells (những người được tạo ra bởi ()
, ``
, $()
hoặc vòng) và quy trình con (quá trình được gọi theo tên, ví dụ một chữ bash
xuất hiện trong kịch bản của bạn).
Điều phổ biến trong hai cấu trúc này là không thể chuyển các biến trở lại trình bao cha.
$ noexport=noexport; export export=export; (echo subshell: $noexport $export; subshell=subshell); bash -c 'echo subprocess: $noexport $export; subprocess=subprocess'; echo parent: $subshell $subprocess
subshell: noexport export
subprocess: export
parent:
Có thêm một nguồn gây nhầm lẫn: một số người nghĩ rằng các quy trình con 'rẽ nhánh' là những quy trình không thấy các biến không xuất. Thông thường các fork () ngay lập tức được theo sau bởi exec () và đó là lý do tại sao dường như fork () là thứ cần tìm, trong khi thực tế nó là exec (). Bạn có thể chạy các lệnh mà không cần fork () trước tiên bằng exec
lệnh và các quy trình được bắt đầu bằng phương thức này cũng sẽ không có quyền truy cập vào các biến không được báo cáo:
$ noexport=noexport; export export=export; exec bash -c 'echo execd process: $noexport $export; execd=execd'; echo parent: $execd
execd process: export
Lưu ý rằng lần này chúng ta không thấy parent:
dòng này, vì chúng ta đã thay thế shell cha bằng exec
lệnh, vì vậy không còn gì để thực thi lệnh đó.
&
) cũng tạo ra một subshell.
var=asdf bash -c 'echo $var'
hay var=asdf exec bash -c 'echo $var'
? Đầu ra là asdf
. Sự ;
khác biệt nếu được đặt sau định nghĩa biến. Điều gì sẽ là lời giải thích? Có vẻ như var
(không có ;
) liên quan đến quá trình sinh sản bằng cách nào đó, do shell nguồn gốc không liên quan gì đến nó. echo $var
không in gì nếu thực hiện trên dòng thứ hai. Nhưng một lót var=asdf bash -c 'echo $var'; echo $var
cho asdf\nasdf
.
export NAME=value
cho các cài đặt và các biến có ý nghĩa đối với một quy trình con.
NAME=value
cho các biến tạm thời hoặc vòng lặp riêng tư cho quá trình shell hiện tại.
Chi tiết hơn, export
đánh dấu tên biến trong môi trường sao chép vào một quy trình con và quy trình con của chúng khi tạo. Không có tên hoặc giá trị nào được sao chép lại từ quy trình con.
Một lỗi phổ biến là đặt một khoảng trắng xung quanh dấu bằng:
$ export FOO = "bar"
bash: export: `=': not a valid identifier
Chỉ có biến được xuất ( B
) được nhìn thấy bởi quy trình con:
$ A="Alice"; export B="Bob"; echo "echo A is \$A. B is \$B" | bash
A is . B is Bob
Thay đổi trong quy trình con không thay đổi vỏ chính:
$ export B="Bob"; echo 'B="Banana"' | bash; echo $B
Bob
Các biến được đánh dấu để xuất có các giá trị được sao chép khi quy trình con được tạo:
$ export B="Bob"; echo '(sleep 30; echo "Subprocess 1 has B=$B")' | bash &
[1] 3306
$ B="Banana"; echo '(sleep 30; echo "Subprocess 2 has B=$B")' | bash
Subprocess 1 has B=Bob
Subprocess 2 has B=Banana
[1]+ Done echo '(sleep 30; echo "Subprocess 1 has B=$B")' | bash
Chỉ các biến được xuất trở thành một phần của môi trường ( man environ
):
$ ALICE="Alice"; export BOB="Bob"; env | grep "ALICE\|BOB"
BOB=Bob
Vì vậy, bây giờ nó phải rõ ràng như mặt trời của mùa hè! Cảm ơn Brain Agnew, alexp và William Prusell.
Cần lưu ý rằng bạn có thể xuất một biến và sau đó thay đổi giá trị. Giá trị thay đổi của biến sẽ có sẵn cho các tiến trình con. Khi xuất đã được đặt cho một biến, bạn phải làm export -n <var>
để xóa thuộc tính.
$ K=1
$ export K
$ K=2
$ bash -c 'echo ${K-unset}'
2
$ export -n K
$ bash -c 'echo ${K-unset}'
unset
Như bạn có thể đã biết, UNIX cho phép các quy trình có một tập hợp các biến môi trường, là các cặp khóa / giá trị, cả khóa và giá trị là các chuỗi. Hệ điều hành có trách nhiệm giữ các cặp này cho mỗi quy trình riêng biệt.
Chương trình có thể truy cập các biến môi trường của nó thông qua API UNIX này:
char *getenv(const char *name);
int setenv(const char *name, const char *value, int override);
int unsetenv(const char *name);
Các quy trình cũng kế thừa các biến môi trường từ các quy trình cha. Hệ điều hành chịu trách nhiệm tạo một bản sao của tất cả các "envars" tại thời điểm tiến trình con được tạo.
Bash , trong số các shell khác, có khả năng thiết lập các biến môi trường theo yêu cầu của người dùng. Đây là những gì export
tồn tại cho.
export
là một lệnh Bash để đặt biến môi trường cho Bash. Tất cả các biến được thiết lập bằng lệnh này sẽ được kế thừa bởi tất cả các quy trình mà Bash này sẽ tạo.
Thêm về môi trường ở Bash
Một loại biến khác trong Bash là biến nội bộ. Vì Bash không chỉ là vỏ tương tác, nên trên thực tế nó là một trình thông dịch kịch bản, như bất kỳ trình thông dịch nào khác (ví dụ Python), nó có khả năng giữ tập hợp các biến của riêng nó. Cần phải đề cập rằng Bash (không giống như Python) chỉ hỗ trợ các biến chuỗi.
Ký hiệu để xác định các biến Bash là name=value
. Các biến này nằm trong Bash và không liên quan gì đến các biến môi trường được giữ bởi hệ điều hành.
Thông tin thêm về Shell Tham số (bao gồm các biến)
Cũng đáng lưu ý rằng, theo hướng dẫn tham khảo Bash:
Môi trường cho bất kỳ lệnh hoặc hàm đơn giản nào có thể được tăng cường tạm thời bằng cách thêm tiền tố vào nó bằng các phép gán tham số, như được mô tả trong Shell Paramameter . Các câu lệnh gán này chỉ ảnh hưởng đến môi trường mà lệnh đó nhìn thấy.
Để tổng hợp mọi thứ:
export
được sử dụng để đặt biến môi trường trong hệ điều hành. Biến này sẽ có sẵn cho tất cả các quy trình con được tạo bởi quy trình Bash hiện tại mãi mãi về sau.Các câu trả lời được chấp nhận hàm ý này, nhưng tôi muốn làm sáng tỏ những kết nối đến builtins vỏ:
Như đã đề cập, export
sẽ làm cho một biến có sẵn cho cả vỏ và trẻ em. Nếu export
là không được sử dụng, biến sẽ chỉ sẵn có trong vỏ, và chỉ có vỏ builtins có thể truy cập vào nó.
Đó là,
tango=3
env | grep tango # prints nothing, since env is a child process
set | grep tango # prints tango=3 - "type set" shows `set` is a shell builtin
Đây là một ví dụ khác:
VARTEST="value of VARTEST"
#export VARTEST="value of VARTEST"
sudo env | grep -i vartest
sudo echo ${SUDO_USER} ${SUDO_UID}:${SUDO_GID} "${VARTEST}"
sudo bash -c 'echo ${SUDO_USER} ${SUDO_UID}:${SUDO_GID} "${VARTEST}"'
Chỉ bằng cách sử dụng xuất VARTEST, giá trị của VARTEST mới khả dụng trong sudo bash -c '...'!
Để biết thêm ví dụ, xem:
bash-hackers.org/wiki/doku.php/scripting/processtree
Hai trong số những người tạo ra UNIX, Brian Kernighan và Rob Pike, giải thích điều này trong cuốn sách "Môi trường lập trình UNIX" của họ. Google cho tiêu đề và bạn sẽ dễ dàng tìm thấy phiên bản pdf.
Chúng giải quyết các biến shell trong phần 3.6 và tập trung vào việc sử dụng export
lệnh ở cuối phần đó:
Khi bạn muốn làm cho giá trị của một biến có thể truy cập được trong các khung con, nên sử dụng lệnh xuất của shell. (Bạn có thể nghĩ về lý do tại sao không có cách nào để xuất giá trị của biến từ vỏ phụ sang mẹ của nó).
Chỉ để hiển thị sự khác biệt giữa một biến được xuất trong môi trường (env) và biến không xuất trong môi trường:
Nếu tôi làm điều này:
$ MYNAME=Fred
$ export OURNAME=Jim
sau đó chỉ $ OURNAME xuất hiện trong env. Biến $ MYNAME không có trong env.
$ env | grep NAME
OURNAME=Jim
nhưng biến $ MYNAME không tồn tại trong trình bao
$ echo $MYNAME
Fred
Mặc dù không được đề cập rõ ràng trong cuộc thảo luận, KHÔNG cần phải sử dụng xuất khi sinh ra một lớp con từ bên trong bash vì tất cả các biến được sao chép vào tiến trình con.
export name=value
không phải là di động. Tùy thuộc vào chính xác những gì bạn muốn, hãy thửname=value; export name
cho một giải pháp di động.