Câu trả lời:
Một môi trường không kỳ diệu như vẻ ngoài của nó. Shell lưu trữ nó trong bộ nhớ và chuyển đến execve()
cuộc gọi hệ thống. Quá trình con kế thừa nó như là một con trỏ mảng được gọi environ
. Từ execve
trang hướng dẫn:
TÓM TẮC
#include <unistd.h> int execve(const char *filename, char *const argv[], char *const envp[]);
argv
là một chuỗi các chuỗi đối số được truyền cho chương trình mới.
Theo quy ước, chuỗi đầu tiên phải chứa tên tệp được liên kết với tệp đang được thực thi.envp
là một chuỗi các chuỗi, theo quy ước của biểu mẫu key = value, được truyền dưới dạng môi trường cho chương trình mới.
Trang này environ(7)
cũng cung cấp một số thông tin chi tiết:
TÓM TẮC
extern char **environ;
SỰ MIÊU TẢ
Biến
environ
chỉ đến một mảng các con trỏ tới các chuỗi được gọi là "môi trường". Con trỏ cuối cùng trong mảng này có giá trịNULL
. (Biến này phải được khai báo trong chương trình người dùng, nhưng được khai báo trong tệp tiêu đề<unistd.h>
trong trường hợp các tệp tiêu đề đến từ libc4 hoặc libc5 và trong trường hợp chúng đến từ glibc và _GNU_SOURCE đã được xác định.) quá trình bằng lệnh exec (3) đã bắt đầu tiến trình.
Cả hai trang GNU này đều khớp với đặc tả POSIX
exec*e
biến thể vượt qua một env, thay vì sử dụng environ
biến toàn cục. Nghĩa v
là "vectơ" và tham chiếu đến các đối số dòng lệnh được truyền dưới dạng một mảng (chứ không phải là "danh sách" (hàm có độ dài thay đổi)) execve
là một lệnh gọi hệ thống và tất cả các exec*
hàm khác là các hàm bao libc cho nó.
Bạn đã hiểu sai một chút: SOME_NAME=value
tạo một biến shell (trong hầu hết các shell). export SOME_NAME=value
tạo ra một biến môi trường. Để tốt hơn cho điều tồi tệ hơn, hầu hết các shell Unix / Linux / * BSD sử dụng cú pháp giống hệt nhau trong việc truy cập các biến môi trường và biến shell.
Trong một số ý nghĩa lớn hơn, một "môi trường" chỉ là thông tin đi cùng với việc thực hiện chương trình. Trong các chương trình C, bạn có thể tìm thấy ID tiến trình với một getpid()
cuộc gọi, trong chương trình shell bạn sẽ sử dụng quyền truy cập biến : $$
. ID tiến trình chỉ là một phần của môi trường của chương trình. Tôi tin rằng thuật ngữ "môi trường" xuất phát từ một số chủ đề khoa học máy tính lý thuyết hơn, như mô hình hóa thực hiện chương trình .. Các mô hình thực hiện chương trình có một môi trường "chứa các liên kết giữa các biến và giá trị của chúng".
Và sau này, định nghĩa mạnh hơn là "môi trường" dành cho các shell BSD Unix / Linux / *: sự liên kết giữa các tên ("biến") và các giá trị của chúng. Đối với hầu hết các shell kiểu Unix, các giá trị đều là các chuỗi ký tự, mặc dù điều đó không hoàn toàn đúng như trước đây. Ksh, Zsh và Bash đều đã gõ các biến trong những ngày này. Ngay cả định nghĩa hàm shell cũng có thể được xuất.
Việc sử dụng một môi trường tách biệt với các biến shell đơn giản liên quan đến fork/exec
phương pháp bắt đầu một quy trình mới mà tất cả các Unix sử dụng. Khi bạn export
là một cặp tên / giá trị, cặp tên / giá trị đó sẽ có mặt trong môi trường của các tệp thực thi mới, được bắt đầu bằng shell với một execve(2)
lệnh gọi hệ thống (thường theo a fork(2)
, trừ khi exec
sử dụng lệnh shell).
Theo sau execve()
, main()
hàm của nhị phân mới có các đối số dòng lệnh, môi trường (được lưu trữ dưới dạng một mảng con trỏ kết thúc NULL với var=value
chuỗi, xem environ(7)
trang man). Các trạng thái khác được kế thừa bao gồm các ulimit
cài đặt, thư mục làm việc hiện tại và bất kỳ mô tả tệp mở nào mà execve()
người gọi không có FD_CLOEXEC được đặt cho. Trạng thái hiện tại của tty (bật echo, chế độ thô, v.v.) cũng có thể được coi là một phần của trạng thái thực thi được kế thừa bởi một exec
quy trình mới.
Xem bash
mô tả của hướng dẫn về môi trường thực thi để biết các lệnh đơn giản (ngoài các hàm dựng sẵn hoặc hàm).
Môi trường Unix khác với ít nhất một số hệ điều hành khác: VMS "từ vựng" có thể được thay đổi bởi một tiến trình con và sự thay đổi đó có thể nhìn thấy ở cha mẹ. Một VMS cd
trong một tiến trình con sẽ ảnh hưởng đến thư mục làm việc của cha mẹ. Ít nhất trong một số trường hợp, và trí nhớ của tôi có thể làm tôi thất vọng.
Một số biến môi trường đang nổi tiếng, $HOME
, $PATH
, $LD_LIBRARY_PATH
và những người khác. Một số thông thường cho một hệ thống lập trình nhất định, do đó, trình bao cha mẹ có thể truyền rất nhiều thông tin mục đích đặc biệt cho một số chương trình, như một thư mục tạm thời cụ thể, hoặc ID người dùng và mật khẩu không hiển thị ps -ef
. Các chương trình CGI đơn giản thừa hưởng rất nhiều thông tin từ máy chủ web thông qua các biến môi trường.
SOME_NAME=value command
sẽ đặt biến môi trường SOME_NAME cho lệnh gọi đó. Một cách khó hiểu, dường như nó không đặt biến shell cùng tên.
SOME_NAME=value command
hành vi của bạn trái với mong đợi của bạn là vì đó là một cú pháp đặc biệt có nghĩa là "thêm SOME_NAME vào môi trường được truyền vào lệnh nhưng không làm thay đổi các biến của shell này".
fork()
ed, nhưng họ làm nhận (bản sao) các biến shell.
Các biến môi trường ở dạng raxi của chúng chỉ là một tập hợp các cặp tên / giá trị. Như được mô tả trong trang bash man ( man 1 bash
) trong phần MÔI TRƯỜNG:
When a program is invoked it is given an array of strings called the
environment. This is a list of name-value pairs, of the form
name=value.
The shell provides several ways to manipulate the environment. On
invocation, the shell scans its own environment and creates a parameter
for each name found, automatically marking it for export to child pro-
cesses. Executed commands inherit the environment.
Trong điều kiện thực tế, nó cho phép bạn xác định hành vi được chia sẻ hoặc duy nhất cho các chương trình được gọi từ trình bao hiện tại. Ví dụ: khi sử dụng crontab
hoặc visudo
bạn có thể xác định EDITOR
biến môi trường để xác định trình soạn thảo khác ngoài trình soạn thảo mà hệ thống của bạn sẽ sử dụng theo mặc định. Điều tương tự cũng có thể đúng đối với những thứ như man
lệnh nhìn vào PAGER
môi trường của bạn để tìm ra chương trình máy nhắn tin nào nên được sử dụng để hiển thị đầu ra của trang man với.
Khá nhiều lệnh unix đọc môi trường và tùy thuộc vào những gì được đặt ở đó thay đổi đầu ra / xử lý / hành động của chúng tùy thuộc vào các lệnh này. Một số được chia sẻ, một số là duy nhất cho chương trình. Hầu hết các trang man chứa thông tin về cách biến môi trường có ảnh hưởng đến chương trình được mô tả.
Các minh họa thực tế khác dành cho những thứ như các hệ thống có nhiều bản cài đặt của Oracle trên cùng một nền tảng. Bằng cách cài đặt ORACLE_HOME
, toàn bộ bộ lệnh oracle (như được tải từ PATH
biến môi trường của bạn ) sau đó kéo cài đặt, định nghĩa, ánh xạ và thư viện từ dưới thư mục cấp cao nhất đó. Điều tương tự cũng đúng với các chương trình khác như java với JAVA_HOME
biến môi trường.
Bản thân bash có nhiều biến môi trường có thể thay đổi hành vi của một loạt các thứ từ lịch sử ( HISTSIZE
, HISTFILE
v.v.), kích thước màn hình ( COLUMNS
), hoàn thành tab ( FIGNORE
, GLOBIGNORE
) ngôn ngữ và mã hóa / giải mã ký tự ( LANG
, LC_*
), prompt ( PS1
.. PS4
), và vân vân (một lần nữa tìm kiếm kiến thức từ trang bash man).
Ngoài ra, bạn có thể viết các tập lệnh / chương trình sử dụng các biến môi trường tùy chỉnh của riêng bạn (để vượt qua các cài đặt hoặc thay đổi chức năng).
"Biến môi trường" là một tập hợp các giá trị động được đặt tên có thể ảnh hưởng đến cách các quy trình đang chạy sẽ hoạt động trên máy tính.
Chúng là một phần của môi trường hoạt động trong đó một quy trình chạy. Ví dụ, một quy trình đang chạy có thể truy vấn giá trị của biến môi trường TEMP để khám phá một vị trí phù hợp để lưu trữ các tệp tạm thời hoặc biến HOME hoặc USERPROFILE để tìm cấu trúc thư mục do người dùng chạy quy trình sở hữu.
Thêm thông tin ở đây → http://en.wikipedia.org/wiki/En Môi_variable .
Mọi thứ bạn muốn biết về Biến môi trường ...
Câu trả lời này đòi hỏi một số kinh nghiệm và kiến thức về kịch bản shell với các thuật ngữ biến, giá trị, thay thế biến, dấu nhắc, echo, kernel, shell, tiện ích, phiên và quy trình.
Một biến môi trường (envar) là một tập hợp các biến định nghĩa toàn cầu có thể ảnh hưởng đến cách một quá trình nhất định sẽ cư xử trên hệ điều hành của máy tính.
Chúng tôi thay thế envars bằng một chữ cái$
và viết hoa . Ví dụ : $PS1
.
Chúng ta có thể in một envar theo cách này:
echo $PS1
$PS1
giữ giá trị của dấu nhắc Unix. Nói giá trị bản địa của nó là \u
\w
$
.
\u
là viết tắt của người dùng (hiện tại),\w
là viết tắt của thư mục làm việc,$
là để biên giới nhắc.Vì vậy, nếu chúng ta làm : echo $PS1
, chúng ta sẽ thấy các giá trị của \u
, \w
cộng với ký hiệu đô la cuối cùng.
Chúng ta có thể thay đổi hành vi Unix trong bối cảnh đó, nếu chúng ta thay đổi các giá trị của envar đó. Ví dụ:
PS1="\w >"
Bây giờ lời nhắc trông như thế này (giả sử thư mục công việc được đặt tên là "John"):
John >
Theo cách tương tự chúng ta có thể làm PS1="Hello, I'm your prompt >"
, vì vậy echo $PS1
sẽ mang lại:
Hello, I'm your prompt >
Trong Bash 4.xx, chúng ta có thể in TẤT CẢ các envars trong hệ thống bằng env
lệnh. Tôi đề nghị thực hiện env
trong thiết bị đầu cuối và xem xét đầu ra.
Thiết bị đầu cuối của phiên chúng ta hãy tùy chỉnh các envars đi kèm với Bash.
Những thay đổi đã nói ở trên thường là tạm thời và đây là lý do:
Mỗi phiên (không phải là phiên phụ) là duy nhất và một số quy trình có thể chạy duy nhất cùng một lúc (mỗi phiên có một bộ envars riêng) nhưng thường có sự kế thừa từ phiên 0 đến phiên 1 trở lên.
Những thay đổi chúng tôi thực hiện cho một quy trình là duy nhất cho quy trình đó và sẽ chấm dứt nếu chúng tôi đóng nó mà không lưu chúng theo một cách nào đó.
Có một số cách có sẵn để lưu trữ các thay đổi envar, tùy thuộc vào phạm vi chúng tôi chọn. Dưới đây là các phạm vi (cấp độ) khác nhau cho những thay đổi như vậy:
Unix được xây dựng gồm 3 lớp chính: Kernel, shell và các tiện ích. AFAIK mỗi vỏ có đặc điểm riêng và chúng được chế tạo chủ yếu hoặc độc quyền trong vỏ.
Vị trí cụ thể để thay đổi toàn cầu thường là /etc/profile
mặc dù chúng ta cũng có thể làm điều đó trong .bashrc
khóa học.
Chúng ta có thể tạo ra những người mới và đây là một cách; kể từ Bash 4.xx, không có enavar bản địa nào được đặt tên MESSAGE
(như đã nói, envars thường được đặt ở trên).
MESSAGE="Hello world!"
sẽ tạo nó cho chúng ta và bây giờ nếu chúng ta gõ echo $MESSAGE
, chúng ta sẽ nhận được hello world!
.
Nếu chúng tôi thực thi bash
trong phiên làm việc hiện tại (cửa sổ), chúng tôi sẽ bắt đầu một phiên phụ bash mới và sẽ không còn hoạt động trong quy trình ban đầu, trừ khi chúng tôi thực thi exit
.
Lưu ý: Trong các hệ điều hành có trình giả lập thiết bị đầu cuối (như máy tính để bàn Ubuntu), phiên phụ thường chạy trên cùng một cửa sổ, nhưng phiên mới trong cửa sổ khác không phải là phiên phụ của phiên hiện có (đó là quy trình liền kề ) .
Lưu ý: Không sử dụng các dấu hiệu đặc biệt trong các giá trị envar như! hoặc họ sẽ không được cứu.
Chúng ta vẫn có thể sử dụng envar được tạo trong phiên đầu tiên, trong phiên thứ hai, mà không cần đăng ký nó trong các tệp conf cấp độ người dùng hoặc toàn cầu (xem dữ liệu sau). Đây là cách để làm điều đó:
Chuyển đến phiên ban đầu (cho dù trên cửa sổ hiện tại hay khác) và thực hiện:
export MESSAGE
Khi xuất khẩu, không sử dụng $
dấu hiệu.
Bây giờ nó được xuất khẩu cho tất cả các phiên phụ. Nếu bạn sẽ làm echo $MESSAGE
trong một phiên phụ, cho dù từ người dùng của bạn hay người khác, thì nó sẽ được in.
Lưu ý rằng các biến nội bộ của Shell như PS1
không nên xuất, nhưng nếu bạn muốn xuất chúng từ bất kỳ lý do gì và chúng không xuất hiện, thì đừng thực hiện bash
sau export
mà thay vào đó bash –norc
.
$PATH
là envar mà người dùng thường sẽ thay đổi nhiều nhất.
Nếu chúng ta echo $PATH
, chúng ta sẽ thấy luồng này:
/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games
Các giá trị in của envar này được phân tách bằng dấu hai chấm (:) ở đó, nhưng đây là một cách có khả năng thoải mái hơn (đây là các giá trị giống nhau ):
/usr/local/bin
/usr/bin
/bin
/usr/local/games
/usr/games
Đây là các direcotries để tìm kiếm, khi chúng tôi chạy một tiện ích.
Bằng cách thực thi, which echo
chúng ta sẽ có được vị trí tệp của nó - ví dụ, chúng ta có thể thấy nó tồn tại /bin/echo
.
Dựa vào đó, chúng ta không phải gõ echo envar để xem các giá trị của evnar. Chúng tôi cũng có thể làm:
/bin/echo $ENVAR
Envar vẫn sẽ được thực thi, ví dụ:
/bin/echo $HOME
Cung cấp cho chúng tôi
/home/User || /root
Cũng như:
echo $HOME
Cung cấp cho chúng tôi
/home/User || /root
Lưu ý: $HOME
được viết tắt là ~
.
Trong Bash 4.xx, khi chúng tôi sử dụng một tiện ích không có đường dẫn đầy đủ, hệ thống sẽ sử dụng tất cả 6 giá trị được đề cập ở trên, của $PATH
envar. Vì vậy, nó sẽ bắt đầu từ /user/local/bin
và sẽ theo tất cả nội dung của nó để tìm kiếm echo
tệp thực thi.
Trong trường hợp này, nó sẽ dừng lại /bin/echo
, trong đó, trong trường hợp này, thực thi cư trú.
Do đó, lý do chính chúng ta có thể tùy chỉnh $PATH
envar, là cài đặt các tệp thực thi không thuộc bất kỳ giá trị gốc nào của nó.
Sau khi cài đặt các tệp thực thi như vậy, chúng ta nên đặt $PATH
giá trị của chúng cho phù hợp và sau đó chúng ta sẽ có thể làm việc với chúng.
$PATH
:Chúng tôi có thể export $PATH
bash các phiên phụ (bao gồm các tiện ích mở rộng bash như WP-CLI cho WordPress hoặc Drush cho Drupal) theo cách này:
export PATH="/home/John:$PATH"
Điều này sẽ thêm một giá trị mới /home/John
vào $PATH
, và sau đó ngay sau đó, nó sẽ sáp nhập bất kỳ giá trị gốc nào vào nó (ngay sau dấu hai chấm), được lưu trữ theo cú pháp $PATH
.
Thay đổi vĩnh viễn như vậy có thể được thực hiện trong kịch bản có liên quan, thường là dưới /etc/profile
và theo tên .bashrc
.
!
một giá trị biến môi trường không hoạt động ngay bên dưới một ví dụ cho thấy nó hoạt động, một khái niệm sai về các phiên phụ, lời khuyên khá kỳ quái về những việc cần làm sau khi xuất một biến shell và một khái niệm sai về các biến môi trường toàn cầu.
warning about ! in an environment variable value not working that is right below an example showing it working
? Xin ví dụ.
quite bizarre advice about what to do after exporting a shell variable
, Chính xác ý của bạn là gì?
false notion of global environment variables
, Chính xác ý của bạn là gì?
exec(3)
gia đình (tức là những người không phù hợp với giám đốc điều hành * v) vượt qua ** môi trường dưới vỏ bọc.