환경 변수 란 정확히 무엇입니까?


42

나는 그것이 VARIABLE=value환경 변수 를 만들고 export VARIABLE=value현재 쉘에 의해 생성 된 프로세스에서 사용할 수있게 한다는 것을 알고 있습니다. env현재 환경 변수를 보여 주지만 어디에 살고 있습니까? 무엇 (또는 환경 변수 구성 환경에 그 문제를)?

답변:


29

환경은 마치 마법처럼 보이지 않습니다. 쉘은이를 메모리에 저장하고 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 사양 과 일치합니다.


4
+1 exec(3)가족 의 일부 구성원 (예 : exec * v와 일치하지 않는 구성원 )이 덮개 아래 ** 환경을 전달 한다는 점에 주목할 가치가 있습니다.
msw

5
자식 프로세스 (자식 프로세스는 부모의 모든 메모리를 상속)가 아니라 실행 된 프로그램 (동일한 프로세스)에 관한 것이기 때문에 execve () 시스템 호출에 대해 데이터를 전달하는 또 다른 방법입니다 (그렇지 않으면 메모리를 지우십시오) 프로세스의).
Stéphane Chazelas

@msw : 전역 변수 exec*e를 내재적으로 사용하는 대신 명시 적으로 env를 전달하는 변형입니다 environ. v수단 "벡터", 및 배열 (보다는 "리스트"(가변 길이 함수))로 전달 된 명령 행 인수 지칭 execve시스템 호출하고, 다른 모든 exec*기능은 대 libc의 래퍼.
Peter Cordes

19

당신은 그것을 약간 잘못했습니다 : 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 프로그램은 예를 들어 환경 변수를 통해 웹 서버에서 많은 정보를 상속합니다.


1
여전히 조금 더 복잡한 것 같습니다. bash에서 적어도 SOME_NAME=value command해당 명령 호출에 대한 SOME_NAME 환경 변수를 설정합니다. 혼란스럽게도 같은 이름의 쉘 변수를 설정하지 않는 것 같습니다.
Samuel Edwin Ward

2
더 정확하게 말하면, 환경 변수는 상속되지 않고 쉘에서 생성 된 프로그램으로 명시 적으로 전달됩니다.
msw

2
@SamuelEdwinWard가 SOME_NAME=value command예상과 반대되는 이유 는 이것이 "명령에 전달 된 환경에 SOME_NAME을 추가하지만이 쉘의 변수를 변경하지 마십시오"를 의미하는 특수 구문이기 때문입니다.
msw

1
람다 미적분 / 함수 프로그래밍에 대한 링크. 그것은 많은 의미가있는 흥미로운 연결입니다.
Matt

1
이 중 일부는 옳지 않습니다. 예를 들어, 서브 쉘은 서브 프로세스입니다되어야 fork()에드, 그러나 그들은 (사본) 쉘 변수를받을 수 있습니다.
ruakh

7

가장 원시적 인 형태의 환경 변수는 일련의 이름 / 값 쌍입니다. man 1 bashENVIRONMENT 섹션 의 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 매뉴얼 페이지에서 다시 지식을 구하십시오.

또한 사용자 정의 환경 변수를 사용하는 스크립트 / 프로그램을 작성할 수 있습니다 (설정을 전달하거나 기능을 변경하기 위해).


0

"환경 변수" 는 컴퓨터에서 실행중인 프로세스가 작동하는 방식에 영향을 줄 수있는 동적 명명 된 값 집합입니다.

프로세스가 실행되는 운영 환경의 일부입니다. 예를 들어, 실행중인 프로세스는 TEMP 환경 변수의 값을 쿼리하여 임시 파일을 저장하기에 적합한 위치를 찾거나 HOME 또는 USERPROFILE 변수를 사용하여 프로세스를 실행하는 사용자가 소유 한 디렉토리 구조를 찾을 수 있습니다.

여기에 더 많은 정보 → http://en.wikipedia.org/wiki/Environment_variable .

환경 변수에 대해 알고 싶은 모든 것 ... ↑


1
이 링크가 사라질 가능성은 없지만 여기에 관련된 텍스트로 질문에 대답하고 백업 정보에 대한 추가 정보로 링크를 제공하는 것이 좋습니다 .
Anthon

@Anthon 난 당신이 정확하다고 생각하고 가능한 빨리 변경을 할 것입니다 ... 조언을 주셔서 감사합니다 ...
SoCalDiegoRob

-1

이 답변에는 변수, 값, 변수 대체, 프롬프트, 에코, 커널, 쉘, 유틸리티, 세션 및 프로세스라는 용어에 대한 일부 쉘 스크립팅 경험과 지식이 필요합니다.

환경 변수 (ENVAR) 지정된 프로세스가 컴퓨터의 운영 체제에서 작동합니다 방식에 영향을 줄 수 글로벌 정의 된 변수의 집합입니다.

1. 예시적인 소개 :

우리는 함께 envars을 대체 $하고 대문자 문자 . 예를 들면 다음과 같습니다 $PS1..

우리는 이런 식으로 envar를 인쇄 할 수 있습니다 :

echo $PS1

$PS1Unix 프롬프트 값을 보유합니다. 기본 값이이라고 가정하십시오 \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터미널에서 실행 하고 출력을 살펴보십시오.

2. 이러한 데이터는 어떻게 표시되고 조작됩니까?

세션의 터미널을 통해 Bash와 함께 제공되는 envar을 사용자 정의 할 수 있습니다.

위에서 언급 한 변경은 일반적으로 일시적이며 다음과 같은 이유가 있습니다.

각 세션 (하위 세션이 아님)은 고유하며 여러 프로세스가 동시에 고유하게 실행될 수 있지만 (각각 고유 한 envar 세트로) 세션 0에서 세션 1 이상으로 상속됩니다.

하나의 프로세스에 대한 변경 사항은 프로세스마다 고유하며 어떤 식 으로든 저장하지 않고 프로세스를 닫으면 중단됩니다.

따라서 이러한 변경 사항을 어떻게 저장할 수 있습니까?

우리가 선택한 범위에 따라 envar 변경 사항을 저장하는 방법에는 여러 가지가 있습니다. 이러한 변경에 대한 다른 범위 (레벨)는 다음과 같습니다.

  • 프로세스 수준 : envar은 현재 세션의 프로그램에만 사용할 수 있습니다.
  • 수출 수준 다음 envars 현재 세션에서 프로그램 또는 모든 사용할 수있는 자사의 하위 세션.
  • 글로벌 레벨 : 모든 세션 (1 차 및 모든 서브)에 대한 변경 사항이 저장됩니다.

envar 데이터는 어디에 저장됩니까?

유닉스는 커널, 쉘 및 유틸리티의 3 가지 주요 계층으로 구성됩니다. AFAIK 각 쉘에는 자체 envar이 있으며 이들은 주로 쉘에 내장되어 있습니다.

특정 위치는 세계적으로 이러한 일반적으로 변경하는 /etc/profile우리는 또한에 그렇게 할 수 있지만 .bashrc물론.

3. 새로운 envar 생성 :

우리는 새로운 envar을 만들 수 있으며 여기에 방법이 있습니다. Bash 4.xx부터는 이름이 지정된 고유 enavar가 없습니다 MESSAGE(envars는 일반적으로 대문자입니다).

MESSAGE="Hello world!"

우리를 위해 그것을 만들 것이며, 이제 echo 입력하면 $MESSAGE얻을 수 hello world!있습니다.

bash현재 작업 세션 (창)에서 실행 하면 새 bash 하위 세션이 시작되고 실행하지 않으면 더 이상 원래 프로세스에서 작동하지 않습니다 exit.

참고 : Ubuntu 데스크톱과 같은 터미널 에뮬레이터가있는 운영 체제에서 하위 세션은 일반적으로 동일한 창에서 실행되지만 다른 창의 새 세션은 기존 세션의 하위 세션이 아닙니다 ( 인접한 프로세스 임) .

참고 :!와 같은 envar 값에는 특수 부호를 사용하지 마십시오. 그렇지 않으면 저장되지 않습니다.

원래 세션에서 모든 하위 세션으로 envar 내보내기

사용자 나 전역 수준 conf 파일에 등록하지 않고도 첫 번째 세션에서 생성 된 envar을 두 번째 세션에서도 계속 사용할 수 있습니다 (다음 데이터 참조). 이를 수행하는 방법은 다음과 같습니다.

원래 창으로 이동하여 (현재 창이든 다른 창이든) 다음을 실행하십시오.

export MESSAGE

내보낼 때 $부호를 사용하지 마십시오 .

이제 모든 하위 세션으로 내보내집니다. 당신이 할 수 있습니다 경우 echo $MESSAGE하위 세션, 사용자 또는 서로 여부, 그것은 다음 인쇄됩니다.

셸 내부 변수 PS1는 내보내서는 안되지만 어떤 이유로 든 내보내고 싶지 않고 표시되지 않으면, bash이후 export에 실행하지 말고 오히려 bash –norc.

4. $ PATH envar :

$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로 약칭합니다 ~.

시스템-$ PATH 관계 및 가능한 사용자 상호 작용 :

Bash 4.xx에서 전체 경로없이 유틸리티를 사용하면 시스템은 위에서 언급 한 $PATHenvar 의 6 개 값을 모두 사용합니다 . 따라서 시작 부분부터 시작 /user/local/bin하여 echo실행 파일을 찾는 모든 내용을 따릅니다 .

이 경우 /bin/echo실행 파일이 상주하는 에서 중지됩니다 .

따라서 $PATHenvar을 사용자 정의 할 수있는 주된 이유는 기본 값이 아닌 실행 파일을 설치하는 것입니다.

그러한 실행 파일을 설치 한 후 $PATH그에 따라 값을 설정해야 합니다.

5. 부록-확장 $PATH:

다음 export $PATH과 같은 방법으로 하위 세션을 강타 할 수 있습니다 (WordPress 용 WP-CLI 또는 Drupal 용 Drush와 같은 bash 확장 포함).

export PATH="/home/John:$PATH"

이것은 새로운 값을 추가합니다 /home/John에를 $PATH하고 바로 후에, 그것은 구문 아래에 저장됩니다, (오른쪽 콜론 뒤에) 그것은 모든 기본 값을 합병한다 $PATH.

이러한 영구적 인 변경은 관련 스크립트에서 일반적으로 /etc/profile이름 아래에서 수행 할 수 있습니다 .bashrc.


3
이 답변에는 끔찍한 잘못이 있습니다. 세션과 프로세스의 혼란, !작동하지 않는 환경 변수 값에 대한 경고, 작동하는 예제, 하위 세션의 잘못된 개념, 수행 할 작업에 대한 매우 기괴한 조언 쉘 변수를 내 보낸 후 전역 환경 변수의 잘못된 개념.
JdeBP

warning about ! in an environment variable value not working that is right below an example showing it working? 예를 들어주세요.
JohnDoea

quite bizarre advice about what to do after exporting a shell variable정확히 무엇을 의미합니까?
JohnDoea

false notion of global environment variables정확히 무엇을 의미합니까?
JohnDoea
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.