답변:
환경은 마치 마법처럼 보이지 않습니다. 쉘은이를 메모리에 저장하고 execve()
시스템 호출로 전달합니다 . 자식 프로세스는이를라는 배열 포인터로 상속합니다 environ
. 로부터 execve
맨 :
개요
#include <unistd.h> int execve(const char *filename, char *const argv[], char *const envp[]);
argv
새 프로그램에 전달 된 인수 문자열의 배열입니다.
일반적으로 이러한 문자열 중 첫 번째 문자열은 실행중인 파일과 관련된 파일 이름을 포함해야합니다.envp
일반적으로 key = value 형식의 문자열 배열이며 환경으로 새 프로그램에 전달됩니다.
environ(7)
맨 페이지는 또한 몇 가지 통찰력을 제공합니다 :
개요
extern char **environ;
기술
변수
environ
는 "환경"이라는 문자열에 대한 포인터 배열을 가리 킵니다. 이 배열의 마지막 포인터는 값을 갖습니다NULL
. (이 변수는 사용자 프로그램에서 선언해야하지만<unistd.h>
헤더 파일이 libc4 또는 libc5에서 온 경우와 glibc 및 _GNU_SOURCE에서 정의 된 경우 헤더 파일 에서 선언 됩니다.)이 문자열 배열은 프로세스를 시작한 exec (3) 호출에 의한 프로세스
이 GNU 맨 페이지는 모두 POSIX 사양 과 일치합니다.
exec*e
를 내재적으로 사용하는 대신 명시 적으로 env를 전달하는 변형입니다 environ
. v
수단 "벡터", 및 배열 (보다는 "리스트"(가변 길이 함수))로 전달 된 명령 행 인수 지칭 execve
시스템 호출하고, 다른 모든 exec*
기능은 대 libc의 래퍼.
당신은 그것을 약간 잘못했습니다 : SOME_NAME=value
쉘 변수를 만듭니다 (대부분의 쉘에서). export SOME_NAME=value
환경 변수를 만듭니다. 최악의 경우를 위해 대부분의 Unix / Linux / * BSD 쉘은 환경 변수 및 쉘 변수에 액세스 할 때 동일한 구문을 사용합니다.
좀 더 큰 의미에서 "환경"은 프로그램 실행과 함께 제공되는 정보 일뿐입니다. C 프로그램에서는 getpid()
호출 과 함께 프로세스 ID를 찾을 수 있으며 쉘 프로그램에서는 변수 액세스를 사용합니다 $$
. 프로세스 ID는 프로그램 환경의 일부일뿐입니다. "환경"이라는 용어는 모델링 프로그램 실행과 같은보다 이론적 인 컴퓨터 과학 주제에서 비롯된 것으로 생각합니다. 프로그램 실행 모델 에는 "변수와 값 사이의 연관성이 포함 된" 환경 이 있습니다.
그리고이 후자의 강력한 정의는 "환경"이 Unix / Linux / * BSD 쉘에 대한 것입니다 : 이름 ( "변수")과 그 값 사이의 연관성. 대부분의 유닉스 스타일 쉘의 경우, 값은 모두 문자열이지만, 예전처럼 엄격하지는 않습니다. Ksh, Zsh 및 Bash는 요즘 모두 변수를 입력했습니다. 쉘 함수 정의도 내보낼 수 있습니다.
일반 쉘 변수와 다른 환경을 fork/exec
사용하려면 모든 유닉스가 사용하는 새로운 프로세스를 시작하는 방법이 필요합니다 . 이 때 export
이름 / 값 쌍, 즉 이름 / 값 쌍은 함께 쉘에 의해 시작 새로운 실행 파일의 환경에 존재하는 것입니다 execve(2)
시스템 호출 (일반적으로 다음 fork(2)
경우를 제외하고, exec
쉘 명령이 사용되었다).
에 이어 execve()
, main()
새로운 바이너리 의 함수는 환경에 대한 명령 행 인수를 갖습니다 ( var=value
문자열 에 대한 NULL로 끝나는 포인터 배열로 저장되어 있습니다 environ(7)
. 상속 된 다른 상태에는 ulimit
설정, 현재 작업 디렉토리 및 execve()
호출자가 FD_CLOEXEC를 설정하지 않은 열린 파일 설명자가 포함 됩니다. tty의 현재 상태 (에코 활성화, 원시 모드 등)도 새로 exec
프로세스에 의해 상속 된 실행 상태의 일부로 간주 될 수 있습니다 .
간단한 명령 (내장 또는 쉘 기능 이외) bash
에 대해서는 실행 환경에 대한 매뉴얼 설명을 참조하십시오 .
Unix 환경은 다른 운영 체제와는 다릅니다. VMS "lexicals"는 하위 프로세스에 의해 변경 될 수 있으며 해당 변경 사항은 상위 프로세스에서 볼 수 있습니다. cd
자식 프로세스 의 VMS 는 부모의 작업 디렉토리에 영향을줍니다. 적어도 어떤 상황에서는 내 기억이 나에게 실패 할 수 있습니다.
일부 환경 변수는 잘 알려져있다 $HOME
, $PATH
, $LD_LIBRARY_PATH
등을. 일부는 주어진 프로그래밍 시스템에 기본적이므로 부모 쉘은 특정 임시 디렉토리 또는에 표시되지 않는 사용자 ID 및 비밀번호와 같은 많은 특수 목적 정보를 일부 프로그램에 전달할 수 있습니다 ps -ef
. 간단한 CGI 프로그램은 예를 들어 환경 변수를 통해 웹 서버에서 많은 정보를 상속합니다.
SOME_NAME=value command
해당 명령 호출에 대한 SOME_NAME 환경 변수를 설정합니다. 혼란스럽게도 같은 이름의 쉘 변수를 설정하지 않는 것 같습니다.
SOME_NAME=value command
예상과 반대되는 이유 는 이것이 "명령에 전달 된 환경에 SOME_NAME을 추가하지만이 쉘의 변수를 변경하지 마십시오"를 의미하는 특수 구문이기 때문입니다.
fork()
에드, 그러나 그들은 할 (사본) 쉘 변수를받을 수 있습니다.
가장 원시적 인 형태의 환경 변수는 일련의 이름 / 값 쌍입니다. man 1 bash
ENVIRONMENT 섹션 의 bash 맨 페이지 ( )에 설명 된대로 :
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.
실제로는 현재 쉘에서 호출 된 프로그램에 대해 공유되거나 고유 한 동작을 정의 할 수 있습니다. 예를 들어 사용 중이 crontab
거나 환경 변수를 정의하여 시스템에서 기본적으로 사용하는 편집기 이외의 다른 편집기를 정의 visudo
할 수 있습니다 EDITOR
. 매뉴얼 페이지의 출력을 표시하기 위해 어떤 호출기 프로그램을 사용해야하는지 환경을 man
살펴 보는 명령 과 같은 것들에 대해서도 마찬가지 PAGER
입니다.
꽤 많은 유닉스 명령이 환경을 읽고 설정에 따라 출력 / 처리 / 작업이 변경됩니다. 일부는 공유되고 일부는 프로그램에 고유합니다. 대부분의 매뉴얼 페이지에는 환경 변수가 설명 된 프로그램에 미치는 영향에 대한 정보가 들어 있습니다.
다른 실제 그림은 동일한 플랫폼에 여러 개의 Oracle을 설치 한 시스템과 같은 것입니다. 설정 ORACLE_HOME
하면, PATH
환경 변수 에서로드 된 전체 Oracle 명령 세트가 해당 최상위 디렉토리 아래에서 설정, 정의, 맵핑 및 라이브러리를 가져옵니다. JAVA_HOME
환경 변수가있는 java와 같은 다른 프로그램에서도 마찬가지입니다 .
bash 자체에는 히스토리 ( HISTSIZE
, HISTFILE
등), 화면 크기 ( COLUMNS
), 탭 완성 ( FIGNORE
, GLOBIGNORE
) 로캘 및 문자 인코딩 / 디코딩 ( LANG
, LC_*
), 프롬프트 ( PS1
.. PS4
) 및 다양한 범위의 동작을 변경할 수있는 많은 환경 변수가 있습니다 . bash 매뉴얼 페이지에서 다시 지식을 구하십시오.
또한 사용자 정의 환경 변수를 사용하는 스크립트 / 프로그램을 작성할 수 있습니다 (설정을 전달하거나 기능을 변경하기 위해).
"환경 변수" 는 컴퓨터에서 실행중인 프로세스가 작동하는 방식에 영향을 줄 수있는 동적 명명 된 값 집합입니다.
프로세스가 실행되는 운영 환경의 일부입니다. 예를 들어, 실행중인 프로세스는 TEMP 환경 변수의 값을 쿼리하여 임시 파일을 저장하기에 적합한 위치를 찾거나 HOME 또는 USERPROFILE 변수를 사용하여 프로세스를 실행하는 사용자가 소유 한 디렉토리 구조를 찾을 수 있습니다.
여기에 더 많은 정보 → http://en.wikipedia.org/wiki/Environment_variable .
환경 변수에 대해 알고 싶은 모든 것 ... ↑
이 답변에는 변수, 값, 변수 대체, 프롬프트, 에코, 커널, 쉘, 유틸리티, 세션 및 프로세스라는 용어에 대한 일부 쉘 스크립팅 경험과 지식이 필요합니다.
환경 변수 (ENVAR) 지정된 프로세스가 컴퓨터의 운영 체제에서 작동합니다 방식에 영향을 줄 수 글로벌 정의 된 변수의 집합입니다.
우리는 함께 envars을 대체 $
하고 대문자 문자 . 예를 들면 다음과 같습니다 $PS1
..
우리는 이런 식으로 envar를 인쇄 할 수 있습니다 :
echo $PS1
$PS1
Unix 프롬프트 값을 보유합니다. 기본 값이이라고 가정하십시오 \u
\w
$
.
\u
(현재) 사용자를 나타내며\w
작업 디렉토리를 나타내며$
프롬프트를 경계하는 것입니다.우리가 경우에 따라서, : echo $PS1
우리는의 값을 참조 \u
, \w
플러스 끝에서 달러 기호.
해당 envar의 값을 변경하면 해당 컨텍스트에서 Unix 동작을 변경할 수 있습니다. 예를 들면 다음과 같습니다.
PS1="\w >"
이제 프롬프트는 다음과 같습니다 (작업 디렉토리의 이름이 "John"이라고 가정).
John >
우리가 할 수있는 동일한 방식으로 PS1="Hello, I'm your prompt >"
, 그래서 echo $PS1
가져올 것이다 :
Hello, I'm your prompt >
Bash 4.xx에서는 env
명령 을 사용하여 시스템의 모든 envar을 인쇄 할 수 있습니다 . env
터미널에서 실행 하고 출력을 살펴보십시오.
세션의 터미널을 통해 Bash와 함께 제공되는 envar을 사용자 정의 할 수 있습니다.
위에서 언급 한 변경은 일반적으로 일시적이며 다음과 같은 이유가 있습니다.
각 세션 (하위 세션이 아님)은 고유하며 여러 프로세스가 동시에 고유하게 실행될 수 있지만 (각각 고유 한 envar 세트로) 세션 0에서 세션 1 이상으로 상속됩니다.
하나의 프로세스에 대한 변경 사항은 프로세스마다 고유하며 어떤 식 으로든 저장하지 않고 프로세스를 닫으면 중단됩니다.
우리가 선택한 범위에 따라 envar 변경 사항을 저장하는 방법에는 여러 가지가 있습니다. 이러한 변경에 대한 다른 범위 (레벨)는 다음과 같습니다.
유닉스는 커널, 쉘 및 유틸리티의 3 가지 주요 계층으로 구성됩니다. AFAIK 각 쉘에는 자체 envar이 있으며 이들은 주로 쉘에 내장되어 있습니다.
특정 위치는 세계적으로 이러한 일반적으로 변경하는 /etc/profile
우리는 또한에 그렇게 할 수 있지만 .bashrc
물론.
우리는 새로운 envar을 만들 수 있으며 여기에 방법이 있습니다. Bash 4.xx부터는 이름이 지정된 고유 enavar가 없습니다 MESSAGE
(envars는 일반적으로 대문자입니다).
MESSAGE="Hello world!"
우리를 위해 그것을 만들 것이며, 이제 echo 입력하면 $MESSAGE
얻을 수 hello world!
있습니다.
bash
현재 작업 세션 (창)에서 실행 하면 새 bash 하위 세션이 시작되고 실행하지 않으면 더 이상 원래 프로세스에서 작동하지 않습니다 exit
.
참고 : Ubuntu 데스크톱과 같은 터미널 에뮬레이터가있는 운영 체제에서 하위 세션은 일반적으로 동일한 창에서 실행되지만 다른 창의 새 세션은 기존 세션의 하위 세션이 아닙니다 ( 인접한 프로세스 임) .
참고 :!와 같은 envar 값에는 특수 부호를 사용하지 마십시오. 그렇지 않으면 저장되지 않습니다.
사용자 나 전역 수준 conf 파일에 등록하지 않고도 첫 번째 세션에서 생성 된 envar을 두 번째 세션에서도 계속 사용할 수 있습니다 (다음 데이터 참조). 이를 수행하는 방법은 다음과 같습니다.
원래 창으로 이동하여 (현재 창이든 다른 창이든) 다음을 실행하십시오.
export MESSAGE
내보낼 때 $
부호를 사용하지 마십시오 .
이제 모든 하위 세션으로 내보내집니다. 당신이 할 수 있습니다 경우 echo $MESSAGE
하위 세션, 사용자 또는 서로 여부, 그것은 다음 인쇄됩니다.
셸 내부 변수 PS1
는 내보내서는 안되지만 어떤 이유로 든 내보내고 싶지 않고 표시되지 않으면, bash
이후 export
에 실행하지 말고 오히려 bash –norc
.
$PATH
사용자가 일반적으로 가장 많이 변경하는 envar입니다.
만약 우리 echo $PATH
가이 스트림을 보게 될 것입니다 :
/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games
이 envar의 인쇄 된 값은 콜론 (:)으로 구분되지만 여기에는 잠재적으로 더 편안한 방법이 있습니다 ( 동일한 값임).
/usr/local/bin
/usr/bin
/bin
/usr/local/games
/usr/games
유틸리티를 실행할 때 검색해야 할 항목입니다.
실행 which echo
하면 파일 위치를 얻을 수 있습니다. 예를 들어, 파일 위치가에 있음을 알 수 있습니다 /bin/echo
.
이를 바탕으로 evnar의 값을보기 위해 echo envar을 입력 할 필요가 없습니다. 우리는 또한 할 수 있습니다 :
/bin/echo $ENVAR
envar은 여전히 다음과 같이 실행됩니다.
/bin/echo $HOME
우리에게 주어지다
/home/User || /root
그냥:
echo $HOME
우리에게 주어지다
/home/User || /root
참고 : $HOME
로 약칭합니다 ~
.
Bash 4.xx에서 전체 경로없이 유틸리티를 사용하면 시스템은 위에서 언급 한 $PATH
envar 의 6 개 값을 모두 사용합니다 . 따라서 시작 부분부터 시작 /user/local/bin
하여 echo
실행 파일을 찾는 모든 내용을 따릅니다 .
이 경우 /bin/echo
실행 파일이 상주하는 에서 중지됩니다 .
따라서 $PATH
envar을 사용자 정의 할 수있는 주된 이유는 기본 값이 아닌 실행 파일을 설치하는 것입니다.
그러한 실행 파일을 설치 한 후 $PATH
그에 따라 값을 설정해야 합니다.
$PATH
:다음 export $PATH
과 같은 방법으로 하위 세션을 강타 할 수 있습니다 (WordPress 용 WP-CLI 또는 Drupal 용 Drush와 같은 bash 확장 포함).
export PATH="/home/John:$PATH"
이것은 새로운 값을 추가합니다 /home/John
에를 $PATH
하고 바로 후에, 그것은 구문 아래에 저장됩니다, (오른쪽 콜론 뒤에) 그것은 모든 기본 값을 합병한다 $PATH
.
이러한 영구적 인 변경은 관련 스크립트에서 일반적으로 /etc/profile
이름 아래에서 수행 할 수 있습니다 .bashrc
.
!
작동하지 않는 환경 변수 값에 대한 경고, 작동하는 예제, 하위 세션의 잘못된 개념, 수행 할 작업에 대한 매우 기괴한 조언 쉘 변수를 내 보낸 후 전역 환경 변수의 잘못된 개념.
warning about ! in an environment variable value not working that is right below an example showing it working
? 예를 들어주세요.
quite bizarre advice about what to do after exporting a shell variable
정확히 무엇을 의미합니까?
false notion of global environment variables
정확히 무엇을 의미합니까?
exec(3)
가족 의 일부 구성원 (예 : exec * v와 일치하지 않는 구성원 )이 덮개 아래 ** 환경을 전달 한다는 점에 주목할 가치가 있습니다.