쉘 변수와 환경 변수의 사용법 차이는 무엇입니까?


16

실제로 명령 줄에서 액세스 할 수있는 두 가지 유형의 변수가 있다는 것을 알지 못했습니다. 내가 아는 것은 다음과 같은 변수를 선언 할 수 있다는 것입니다.

foo="my dear friends"
bar[0]="one"
bar[1]="two"
bar[2]="three"

또는 $ 기호를 사용하여 다음과 같이 액세스하십시오.

echo $foo
echo ${bar[1]}

또는 내장 변수 사용 :

echo $PWD
PATH=$PATH:"/usr/bin/myProg"

이제 쉘 변수와 환경 변수라는 두 가지 유형의 변수가 있다고 들었습니다.

  • 두 가지 유형을 갖는 목적은 무엇입니까?
  • 변수가 어떤 유형인지 어떻게 알 수 있습니까?
  • 각각의 일반적인 사용법은 무엇입니까?


답변:


14

환경 변수는 name=value프로그램이 무엇이든 존재하는 쌍 (쉘, 응용 프로그램, 데몬 등)의 목록입니다. 그것들은 일반적으로 자식 프로세스에 의해 상속됩니다 ( fork/ exec시퀀스에 의해 생성됨 ) : 자식 프로세스는 자신의 부모 변수 사본을 얻습니다.

쉘 변수는 쉘 컨텍스트에서만 존재합니다. 서브 쉘에서만 상속됩니다 (즉, exec조작 없이 쉘을 포크 할 때 ). 쉘 기능에 따라 변수는 환경 변수와 같은 간단한 문자열 일뿐 만 아니라 배열, 복합, 정수 또는 부동 소수점과 같은 유형 변수 등일 수 있습니다.

시 쉘 시작, 모든 환경 변수 (그들은 쉘 변수와 같은 다른 코너의 경우 무효로하지 않는 한 부모는 쉘 변수가 될로부터 상속 IFS하지만 수출 이러한 상속 된 변수는 태그 리셋 일부 포탄입니다) 1 . 즉, 셸에서 설정 한 잠재적으로 업데이트 된 값으로 하위 프로세스에 계속 사용할 수 있습니다. 쉘 아래에 변수가 생성되고 export키워드 로 내 보낸 것으로 태그가 지정된 경우도 마찬가지입니다 .

자신의 이름과 값을 변환 할 수 있습니다하지 않는 한 배열 및 기타 복합 형 변수는 내보낼 수 없습니다 name=value패턴, 또는 쉘 특정 메커니즘이 자리에있을 때 (예 : bash환경의 수출 기능과 이국적인, 비 POSIX 쉘은 같은 rces배열을 내보낼 수 있습니다 ).

따라서 환경 변수와 셸 변수의 주요 차이점은 범위입니다. 환경 변수는 전역 적이며 내 보내지 않은 셸 변수는 스크립트에 로컬입니다.

현대 쉘 (적어도 것 또한주의 ksh하고 bash) 세 번째 쉘 변수 범위를 지원합니다. typeset키워드를 사용하여 함수에서 생성 된 변수 는 해당 함수의 로컬 변수입니다 (함수 선언 방법에 따라이 기능을 활성화 / 비활성화 ksh하고 지속성 동작은와 ( bashksh) 사이에 다릅니다 ). 참조 /unix//a/28349/2594를

(1) 현대 쉘이 좋아에이 적용 ksh, dash, bash유사한. 레거시 Bourne 셸과 Bourne 이외의 구문 csh은 동작이 다릅니다.


1
자녀가 부모의 포크 (정확한 사본)로 만들어지면 모든 것이 자식 프로세스에 상속됩니다. 환경 변수가있는 요점은 execve()시스템 호출에 전달 되므로 일반적으로 동일한 프로세스에서 다른 명령을 실행 하는 동안 데이터를 유지하는 데 사용됩니다 .
Stéphane Chazelas

모든 환경 변수가 쉘 변수로 변환되는 것은 아닙니다. 쉘 변수 이름으로 유효한 것만 ( IFS일부 쉘 과 같이 몇 가지 예외가 있음 )
Stéphane Chazelas

쉘 좋아 rc, es애드혹 인코딩을 사용하여 배열을 내보낼 수 있습니다. bashrc같은 (특별한 인코딩을 사용하여, 다시) 환경 변수를 이용하여 함수를 내보낼 수있다.
Stéphane Chazelas

에서 ksh93, Bourne ( ) 구문이 아닌 구문으로 typeset선언 된 함수에서만 범위를 제한 합니다 ( 다른 쉘에서와 같이 정적 범위 지정정적입니다 ). function foo { ...; }foo() cmd
Stéphane Chazelas

@ StéphaneChazelas 검토해 주셔서 감사합니다! 귀하의 의견을 반영하여 회신이 업데이트되었습니다.
jlliagre

17

쉘 변수

쉘 변수는 범위가 현재 쉘 세션 (예 : 대화식 쉘 세션 또는 스크립트)에있는 변수입니다.

사용하지 않는 이름에 값을 지정하여 쉘 변수를 작성할 수 있습니다.

var="hello"

쉘 변수의 사용은 현재 세션에서 데이터를 추적하는 것입니다. 쉘 변수는 일반적으로 소문자로 된 이름을 갖습니다.

환경 변수

환경 변수는 내 보낸 쉘 변수입니다. 이는 변수를 작성한 쉘 세션뿐만 아니라 해당 세션에서 시작된 프로세스 (쉘뿐만 아니라)에서도 변수로 표시됨을 의미합니다.

VAR="hello"  # shell variable created
export VAR   # variable now part of the environment

또는

export VAR="hello"

쉘 변수를 내 보낸 후에는 설정이 해제 될 때까지 또는 "내보내기 속성"이 제거 될 때까지 ( export -n에서로 bash) 내보내기 상태를 유지 하므로 일반적으로 다시 내보낼 필요가 없습니다. 변수를 설정하면 변수가 unset삭제됩니다 (환경 변수인지 여부에 상관없이)

bash환경 변수가되도록 배열 및 연관 해시 및 기타 셸을 내보낼 수 없습니다. 환경 변수는 값이 문자열 인 단순 변수 여야하며 종종 대문자로 구성된 이름을 갖습니다.

환경 변수를 사용하면 현재 셸 세션에서 데이터를 추적하고 시작된 프로세스가 해당 데이터에 참여할 수 있습니다. 일반적인 경우는 PATH환경 변수로, 셸에서 설정 한 후 나중에 전체 경로를 지정하지 않고 프로그램을 시작하려는 모든 프로그램에서 사용할 수 있습니다.

프로세스에서 환경 변수의 수집을 종종 "프로세스 환경"이라고합니다. 각 프로세스에는 고유 한 환경이 있습니다.

환경 변수는 "전달"될 수 있습니다. 즉, 하위 프로세스는 상위 프로세스에서 환경 변수를 변경할 수 없으며 , 하위 프로세스를 시작할 때 환경을 설정하는 것 외에는 상위 프로세스가 기존 프로세스의 환경을 변경하지 않을 수 있습니다 자식 프로세스.

환경 변수는 env(인수없이) 함께 나열 될 수 있습니다 . 그 외에는 셸 세션에서 내 보내지 않은 셸 변수와 동일하게 나타납니다. 대부분의 다른 프로그래밍 언어는 일반적으로 "일반"변수를 환경 변수와 혼합하지 않기 때문에 쉘에 약간 특별합니다 (아래 참조).

env 현재 세션에서 설정하지 않고 프로세스 환경에서 하나 이상의 환경 변수 값을 설정하는 데 사용될 수도 있습니다.

env CC=clang CXX=clang++ make

이는 make환경 변수 CC가 값 clang으로 CXX설정 되고로 설정되는 것으로 시작 clang++합니다.

프로세스 환경 을 정리 하는 데 사용될 수도 있습니다 .

env -i bash

이 시작 bash하지만 새로운 현재 환경을 전송하지 않습니다 bash(여전히 것이다 과정 그것의 쉘 초기화 스크립트에서 새로 생성으로 환경 변수).

차이의 예

$ var="hello"   # create shell variable "var"
$ bash          # start _new_ bash session
$ echo "$var"   # no output
$ exit          # back to original shell session
$ echo "$var"   # "hello" is outputted
$ unset var     # remove variable

$ export VAR="hello"  # create environment variable "VAR"
$ bash
$ echo "$VAR"         # "hello" is outputted since it's exported
$ exit                # back to original shell session
$ unset VAR           # remove variable

$ ( export VAR="hello"; echo "$VAR" )  # set env. var "VAR" to "hello" in subshell and echo it
$ echo "$VAR"         # no output since a subshell has its own environment

다른 언어

대부분의 프로그래밍 언어에는 환경 변수를 가져오고 설정할 수있는 라이브러리 함수가 있습니다. 환경 변수는 간단한 키-값 관계로 저장되므로 일반적으로 언어의 "변수"가 아닙니다. 프로그램은 키 (환경 변수의 이름)에 해당하는 값 (항상 문자열 임)을 가져올 수 있지만이 값을 정수 또는 언어가 예상하는 데이터 유형으로 변환해야합니다.

C에서, 환경 변수를 사용하여 액세스 될 수있다 getenv(), setenv(), putenv()unsetenv(). 이 루틴으로 작성된 변수는 C 프로그램이 시작하는 프로세스와 동일한 방식으로 상속됩니다.

다른 언어는 %ENVPerl 의 해시 또는의 ENVIRON대부분의 구현에서 연관 배열 과 같이 동일한 작업을 수행하기위한 특수 데이터 구조를 가질 수 있습니다 awk.


thx, 훌륭하게 명확한 설명. 따라서 환경은 다른 프로그램이 살 수 있고 각 환경 변수를 볼 수있는 큰 필드와 같습니다. 일부 프로그램에는 전용 변수가 있으며 쉘과 같이 자신 만 볼 수 있습니다. 그러나 모든 "내보내기"에서 개인 변수를 볼 수있는 메커니즘이 있습니다. 이것이 잘 이해된다면, 내가 확신하지 못하는 유일한 것보다 동시에 둘 이상의 환경이 존재할 수있는 것입니까?
상어

@sharkant 실행중인 각 프로세스에는 고유 한 환경이 있습니다. 이 환경은 시작된 프로세스에서 상속됩니다. 서로 다른 프로세스 환경 간에는 "크로스 토크"가 없습니다. 프로세스에서 환경 변수를 변경하는 유일한 방법은 프로세스 자체가 환경 변수를 수정하는 것입니다.
Kusalananda

내 이해를 돋보이게 해줘서 고마워 자체 물고기 그릇 안에 각 물고기. 다른 프로세스를 생성하는 프로세스는 어떻습니까? 프로세스와 하위 프로세스가 모두 하나의 환경 내에 있습니까?
상어

1
@sharkant 대부분의 언어에는 환경 변수를 가져오고 설정할 수있는 라이브러리 함수가 있습니다. C에서, 이것은 함께 이루어집니다 getenv(), setenv(), putenv()unsetenv(). 이 루틴으로 작성된 변수는 C 프로그램이 시작하는 프로세스와 동일한 방식으로 상속됩니다. 다른 언어는 %ENVPerl 에서와 같이 동일한 것에 대한 특수 데이터 구조를 가질 수 있습니다 .
Kusalananda

1
FWIW : exec*()기능 군은 실행중인 프로세스의 환경을 설정할 수도 있습니다.
Satō Katsura

5

쉘 변수를 복제하기가 어렵습니다.

$ FOO=bar
$ FOO=zot
$ echo $FOO
zot
$ 

그러나 환경 변수는 복제 될 수 있습니다. 그것들은 단지 목록 일 뿐이며 목록에는 중복 된 항목이있을 수 있습니다. 바로 여기 envdup.c에 있습니다.

#include <err.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

extern char **environ;

int main(int argc, char *argv[]) {
    char **newenv;
    int envcount = 0;

    if (argc < 2) errx(64, "Usage: envdup command [args ..]");

    newenv = environ;
    while (*newenv++ != NULL) envcount++;

    newenv = malloc(sizeof(char *) * (envcount + 3));
    if (newenv == NULL) err(1, "malloc failed");
    memcpy(newenv, environ, sizeof(char *) * envcount);
    newenv[envcount]   = "FOO=bar";
    newenv[envcount+1] = "FOO=zot";
    newenv[envcount+2] = NULL;

    environ = newenv;
    argv++;
    execvp(*argv, argv);
    err(1, "exec failed '%s'", *argv);
}

어떤 환경 변수가 설정되어 있는지 보여주기 envdup위해 컴파일하고 실행할 수 있습니다 env...

$ make envdup
cc     envdup.c   -o envdup
$ unset FOO
$ ./envdup env | grep FOO
FOO=bar
FOO=zot
$ 

이것은 아마도 프로그램이 얼마나 잘 처리하는지에 대한 버그 나 다른 이상한 점을 찾는 데 유용 할 것 **environ입니다.

$ unset FOO
$ ./envdup perl -e 'exec "env"' | grep FOO
FOO=bar
$ ./envdup python3 -c 'import os;os.execvp("env",["env"])' | grep FOO
FOO=bar
FOO=zot
$ 

파이썬 3.6은 맹목적으로 중복 (누수 추상화)을 통과하지만 펄 5.24는 그렇지 않습니다. 껍질은 어때?

$ ./envdup bash -c 'echo $FOO; exec env' | egrep 'bar|zot'
zot
FOO=zot
$ ./envdup zsh -c 'echo $FOO; exec env' | egrep 'bar|zot' 
bar
FOO=bar
$ 

세상에, sudo첫 번째 환경 항목 만 삭제 한 다음 bash두 번째 환경 항목을 실행하면 어떻게됩니까? 안녕하세요 PATH또는 LD_RUN_PATH착취. 귀하가 sudo(그리고 다른 모든 것들 ?) 그 구멍에 대한 패치는 ? 보안 익스플로잇은 호출 프로그램에서 "일화 적 차이"나 "버그"가 아닙니다.


1
그것은 사실이지만 일화적인 차이이며 아마도 중복 변수를 설정하는 프로그램의 버그입니다.
jlliagre


0

환경 변수 는 A이다 쉘 변수 ,하지만 특정 아니다 . 유닉스 시스템의 모든 프로세스 에는 환경 변수 스토리지가 있습니다. 환경과 쉘 변수의 주요 차이점운영 체제가 쉘의 모든 환경 변수 를 쉘이 실행하는 프로그램으로 전달하는 반면, 쉘 변수는 실행하는 명령에서 액세스 할 수 없다는 것입니다.

env –이 명령을 사용하면 현재 프로그램을 수정하지 않고 사용자 정의 환경에서 다른 프로그램을 실행할 수 있습니다. 인수없이 사용하면 현재 환경 변수 목록이 인쇄됩니다. printenv –이 명령은 모든 또는 지정된 환경 변수를 인쇄합니다. set –이 명령은 쉘 변수를 설정하거나 설정 해제합니다. 인수없이 사용하면 환경 및 쉘 변수 및 쉘 함수를 포함한 모든 변수 목록이 인쇄됩니다. unset –이 명령은 쉘 및 환경 변수를 삭제합니다. export –이 명령은 환경 변수를 설정합니다

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.