Nếu các quy trình kế thừa môi trường của cha mẹ, tại sao chúng ta cần xuất khẩu?


72

Tôi đọc ở đây rằng mục đích của exportshell là làm cho biến có sẵn cho các tiến trình con bắt đầu từ shell.

Tuy nhiên, tôi cũng đã đọc ở đâyở đây rằng "Các quy trình kế thừa môi trường của chúng từ cha mẹ của chúng (quá trình bắt đầu chúng)."

Nếu đây là trường hợp, tại sao chúng ta cần export? Tôi đang thiếu gì?

Các biến shell không phải là một phần của môi trường theo mặc định? Sự khác biệt là gì?

Câu trả lời:


74

Giả định của bạn là các biến shell nằm trong môi trường . Điều này là không đúng. Các exportlệnh là những gì định nghĩa một tên được trong môi trường ở tất cả. Do vậy:

a=1 b=2
export b

dẫn đến trình bao hiện tại biết rằng $amở rộng thành 1 và $b2, nhưng các quy trình con sẽ không biết gì avì nó không phải là một phần của môi trường (ngay cả trong trình bao hiện tại).

Một số công cụ hữu ích:

  • set: Hữu ích để xem các tham số của shell hiện tại, xuất hay không
  • set -k: Đặt args được gán trong môi trường. Xem xétf() { set -k; env; }; f a=1
  • set -a: Nói với shell để đặt bất kỳ tên nào được đặt vào môi trường. Giống như đặt exporttrước mỗi nhiệm vụ. Hữu ích cho .envcác tập tin, như trong set -a; . .env; set +a.
  • export: Nói với vỏ để đặt tên trong môi trường. Xuất khẩu và chuyển nhượng là hai hoạt động hoàn toàn khác nhau.
  • env: Là một lệnh bên ngoài, envchỉ có thể cho bạn biết về môi trường được kế thừa , do đó, nó hữu ích cho việc kiểm tra độ tỉnh táo.
  • env -i: Hữu ích để xóa môi trường trước khi bắt đầu một quy trình con.

Các lựa chọn thay thế cho export:

  1. name=val command # Gán trước khi lệnh xuất tên đó sang lệnh.
  2. declare/local -x name # Xuất khẩu tên, đặc biệt hữu ích trong các hàm shell khi bạn muốn tránh để lộ tên ra phạm vi bên ngoài.
  3. set -a # Xuất khẩu mỗi nhiệm vụ sau.

3
set -klà để người ta có thể sử dụng cmd ENVVAR=valuethay thế ENVVAR=value cmd, điều đó sẽ không hoạt động trong ví dụ của bạn trừ khi set -kđược chạy trước khi gọi f. Ngoài ra, hiện tại không có nhiều shell hỗ trợ nó và chỉ tương thích ngược với shell Bourne. Trong trình bao Bourne (hoặc Korn), điều đó sẽ không hoạt động cho các chức năng. Và bởi vì nó ảnh hưởng đến phân tích cú pháp shell, nó phải có hiệu lực tại thời điểm shell đọc mã sử dụng nó ở đó.
Stéphane Chazelas

1
Bạn cũng có thể muốn đề cậpset -a
Stéphane Chazelas

24

Có sự khác biệt giữa biến shell và biến môi trường. Nếu bạn xác định một biến shell mà không lấy exportnó, nó sẽ không được thêm vào môi trường quy trình và do đó không được kế thừa cho các con của nó.

Sử dụng exportbạn nói với shell để thêm biến shell vào môi trường. Bạn có thể kiểm tra điều này bằng cách sử dụng printenv(chỉ in môi trường của nó stdout, vì đó là quy trình con bạn thấy tác động của exportcác biến ing):

#!/bin/sh

MYVAR="my cool variable"

echo "Without export:"
printenv | grep MYVAR

echo "With export:"
export MYVAR
printenv | grep MYVAR

6

Một biến, một khi được xuất, là một phần của môi trường. PATHđược xuất trong shell, trong khi các biến tùy chỉnh có thể được xuất khi cần. Sử dụng một số mã thiết lập:

$ cat subshell.sh 
#!/usr/bin/env bash
declare | grep -e '^PATH=' -e '^foo='

So sánh

$ cat test.sh 
#!/usr/bin/env bash
export PATH=/bin
export foo=bar
declare | grep -e '^PATH=' -e '^foo='
./subshell.sh
$ ./test.sh 
PATH=/bin
foo=bar
PATH=/bin
foo=bar

Với

$ cat test2.sh 
#!/usr/bin/env bash
PATH=/bin
foo=bar
declare | grep -e '^PATH=' -e '^foo='
./subshell.sh
$ ./test2.sh 
PATH=/bin
foo=bar
PATH=/bin

fookhông được xuất khẩu bởi shell và test2.shkhông bao giờ xuất nó, nên nó không phải là một phần của môi trường subshell.shtrong lần chạy trước.

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.