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

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

사실 저는 명령줄에서 두 가지 다른 유형의 변수에 액세스할 수 있다는 것을 몰랐습니다. 내가 아는 것은 다음과 같은 변수를 선언할 수 있다는 것뿐입니다.

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"

이제 변수에는 쉘 변수와 환경 변수라는 두 가지(적어도?) 유형이 있다고 들었습니다.

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

답변1

쉘 변수

셸 변수는 대화형 셸 세션이나 스크립트와 같이 현재 셸 세션 내에서 범위가 지정되는 변수입니다.

사용하지 않는 이름에 값을 할당하여 쉘 변수를 만들 수 있습니다.

var="hello"

쉘 변수는 현재 세션의 데이터를 추적하는 데 사용됩니다. 쉘 변수 이름은 일반적으로 소문자입니다.

환경 변수

환경 변수는 내보낸 쉘 변수입니다. 이는 해당 변수가 생성된 셸 세션 내에서뿐만 아니라 해당 세션(셸뿐만 아니라)에서 시작된 모든 프로세스에서도 변수로 표시된다는 의미입니다.

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

또는

export VAR="hello"

일단 쉘 변수를 내보내면 설정이 해제되거나 해당 "내보내기 속성"이 제거될 때까지( export -nin 사용 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.

답변2

환경 변수는 name=value프로그램이 무엇이든(셸, 애플리케이션, 데몬...) 존재하는 쌍 목록입니다. 일반적으로 하위 프로세스( fork/ 시퀀스 에 의해 생성됨)에 의해 상속됩니다 exec. 하위 프로세스는 상위 변수의 자체 복사본을 가져옵니다.

쉘 변수는 실제로 쉘 컨텍스트에만 존재합니다. 이는 하위 쉘 내에서만 상속됩니다(즉, 쉘이 exec작업 없이 포크되는 경우). 셸 기능에 따라 변수는 단순 문자열(예: 환경 문자열)일 뿐만 아니라 배열, 복합 변수, 유형 변수(예: 정수 또는 부동 소수점) 등일 수도 있습니다.

쉘이 시작되면 부모로부터 상속받은 모든 환경 변수도 쉘 변수가 되지만(쉘 변수 및 기타 특수한 경우(예: 일부 쉘에 의한 재설정)로 유효하지 않은 경우는 제외 ) 이러한 상속된 변수는 내보내기 1IFS 로 표시됩니다 . 이는 셸에서 설정한 업데이트된 값을 사용하여 하위 프로세스에서 계속 사용할 수 있음을 의미합니다. 셸에서 생성되고 키워드를 사용하여 내보낸 것으로 표시된 변수에 대해서도 마찬가지입니다 .export

배열 및 기타 복합 유형 변수는 해당 이름과 값을 패턴으로 변환할 수 없거나 name=value쉘별 메커니즘이 적용되지 않는 한 내보낼 수 없습니다(예: bash내보내기 환경의 함수 및 rc및 및 POSIX가 아닌 일부 외부 쉘) es배열을 내보낼 수 있음).

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

또한 최신 쉘(적어도 kshbash)은 세 번째 쉘 변수 범위를 지원합니다. 키워드를 사용하여 typeset함수 내에서 생성된 변수는 해당 함수에 대해 로컬입니다(함수가 선언되는 방식에 따라 이 기능이 활성화/비활성화되며 ksh지속성 동작은 및 사이에 다릅니다). 바라보다bashkshhttps://unix.stackexchange.com/a/28349/2594

1이는 , , 및 이와 유사한 최신 쉘에 적용됩니다 . 이전 Bourne 쉘과 Bourne 이외의 구문 쉘은 동작이 다릅니다.kshdashbashcsh

답변3

쉘 변수는 복사하기 어렵습니다.

$ 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
$ 

Python 3.6은 여기에서 중복 항목을 맹목적으로 전달하는 것처럼 보이지만(누수 추상화) Perl 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(그리고그 밖의 모든 것? )구멍을 패치했다? 보안 취약점은 프로그램 호출의 "일화적인 차이점"도 아니고 단순히 "버그"도 아닙니다.

답변4

하나환경 변수같은쉘 변수, 그러나 이는 구체적이지 않습니다.껍데기. 모든 프로세스가 열려있습니다.유닉스 시스템가지다환경변수 저장. 환경 변수와 쉘 변수의 주요 차이점은 다음과 같습니다. 생각하다작동하다시스템은 모든 것을 통과했습니다.쉘 환경 변수셸에서 실행되는 프로그램에 연결되며 실행하는 명령 내에서 셸 변수에 액세스할 수 없습니다.

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

관련 정보