2010-08-05 10 views
28

Linux에서 C를 사용하여 환경 변수를 설정하는 방법이 있습니까?C에서 환경 변수 설정

나는 setenv() 및 putenv()를 시도했지만 저에게 효과적이지는 않습니다.

+0

왜 그들이 작동하지 않는다고 생각합니까? (즉, 어떻게 테스트 했습니까? getenv?) –

+0

작동하지 않는 코드 샘플과 데모를 게시 할 수 있습니까? – FrustratedWithFormsDesigner

답변

44

여기에 야생의 추측을 하겠지만, 작동하지 않는 것처럼 보이는 일반적인 이유는 작동하지 않기 때문이 아니라 사용자가 환경 변수의 작동 방식을 실제로 이해하지 못하기 때문입니다. 나는이 프로그램이있는 경우 예를 들어, :

int main(int argc, char **argv) 
{ 
    putenv("SomeVariable=SomeValue"); 
    return 0; 
} 

을 그리고 내가 쉘에서 실행, 그것은 쉘의 환경을 수정하지 않습니다 - 자식 프로세스가 할 수있는 방법은 없습니다. 그래서 환경을 수정하는 셸 명령이 내장되어 있으며 간단하게 실행하는 대신 셸에 추가하려는 변수 설정을 포함하는 스크립트가 source 필요합니다.

+0

이것은 쉘에서 "1) 쉘 스크립트를 작성하여 작업을 수행하고 2) 일반적인 방법으로 실행하지 말고"소스 "로 실행하는"변수를 설정하는 프로그램 실행 "을 얻는 것입니다. (대부분의 쉘에서'.script'는'source script'와 같고 입력이 훨씬 적습니다.) – dmckee

+0

그것은 많은 의미를 갖습니다. 고마워요. :) 그래, 그게 내가 한 일이야. 저는 리눅스가 처음이에요. 어리석은 질문이라면 용서해주십시오.하지만 C에서 쉘 환경을 설정하고 스크립트를 소싱하지 않아도되는 자식 프로세스는 전혀 없습니다. 저는이 회사에서 인턴으로 일하고 있으며 리눅스를 실행하는 장치의 시간대를 설정하는 함수를 작성하도록 요청 받았기 때문에 쉘의 TZ 환경을 설정하려고했습니다. – iman453

+0

@iman : 몇 가지 옵션으로'man -k tz'을 시도하십시오. 내 Mac OS X 컴퓨터에서 나타나는 것은'tzset (3)'... – dmckee

5

setenv()/putenv()가 설정 한 환경 변수는 이러한 기능을 실행하는 프로세스에 대해 설정되며 해당 환경 변수에 의해 시작된 프로세스에 의해 상속됩니다. 그러나 은 프로그램을 실행 한 쉘에으로 브로드 캐스트되지 않습니다.

Why isn't my wrapper around setenv() working?

1

환경 블록은 프로세스 로컬 및 자식 프로세스로 복사. 따라서 변수를 변경하면 새 값은 변경 후 생성 된 프로세스 및 하위 프로세스에만 영향을줍니다. 확실히 당신이 시작한 셸은 바뀌지 않을 것입니다.

-2

""Advanced Programming in the UNIX Environment " 책에서 가져 왔습니다.

환경은 실제 name = value 문자열에 대한 포인터의 배열을 나열하고 환경 문자열은 일반적으로 프로세스 메모리 공간의 맨 위에 스택 위에 저장됩니다.

문자열 삭제는 간단합니다. 우리는 단순히 환경 목록에서 포인터를 찾아 모든 후속 포인터를 하나씩 이동시킵니다. 그러나 문자열을 추가하거나 기존 문자열을 수정하는 것은 더욱 어렵습니다. 스택 맨 위에있는 공간은 종종 프로세스의 주소 공간의 맨 위에 있으므로 위쪽으로 확장 할 수 없으므로 확장 할 수 없습니다. 그 아래에있는 모든 스택 프레임을 이동할 수 없으므로 아래로 확장 할 수 없습니다.

  1. 것은 우리는 기존 이름을 수정하는 경우 :

    을 수행합니다. 새 값의 크기가 기존 값의 크기보다 작거나 같은 경우 새 문자열을 이전 문자열에 복사 할 수 있습니다.

    B. 그러나 새 값의 크기가 이전 값보다 큰 경우 새 문자열에 대한 공간을 확보하고 새 문자열을이 영역에 복사 한 다음 환경 목록에서 이전 포인터를 name으로 바꾸려면 malloc을 사용해야합니다 이 할당 된 영역에 대한 포인터.

  2. 새 이름을 추가하는 경우 더 복잡합니다. 먼저 malloc을 호출하여 name = value 문자열을위한 공간을 할당하고 문자열을이 영역에 복사해야합니다.

    a. 그런 다음 처음으로 새 이름을 추가 한 경우 malloc을 호출하여 새 포인터 목록 공간을 확보해야합니다.이전 환경 목록을이 새로운 영역에 복사하고이 포인터 목록의 끝에 name = value 문자열에 대한 포인터를 저장합니다. 물론이리스트의 끝 부분에 널 포인터도 저장합니다. 마지막으로 environ을 새로운 포인터 목록을 가리 키도록 설정합니다. 원래 환경 목록이 스택의 맨 위에 포함되어있는 경우 (일반적인 경우),이 포인터 목록을 힙으로 이동했습니다. 그러나이 목록에있는 대부분의 포인터는 여전히 스택 상단의 name = value 문자열을 가리 킵니다.

    B. 환경 목록에 새 문자열을 추가 한 것이 처음이 아니라면 힙에 이미 목록을 저장할 공간이 이미 할당되어 있으므로 realloc을 호출하여 포인터를 한 개 더 할당 할 수 있습니다. 새로운 이름 = 값 문자열에 대한 포인터는 목록의 끝에 (이전 널 포인터의 맨 위에) 저장되고 널 포인터가 뒤에옵니다.

모두 최고입니다.

+0

OP의 질문을 이해했다고 확신하지 않습니다 ... – dmckee

+0

당신은 정확합니다 :-). 내 이해 그는 env 변수를 설정 한 후 자신의 실행 파일에 직면했다. – Hemant

9

모든 유닉스 프로그램은 프로그램을 시작하는 프로세스와는 별도의 프로세스에서 실행됩니다. 이것은 '어린이'과정입니다.

프로그램이 시작될 때 - 명령 행이나 다른 방법으로 실행될 때 - 시스템은 상위 프로세스의 사본 인 (다소) 새로운 프로세스를 작성합니다. 이 복사본에는 부모 프로세스의 환경 변수가 포함되어 있으며, 이는 하위 프로세스가 상위 프로세스의 환경 변수를 '상속받는'메커니즘입니다.

입니다

는 프로세스는 자신의 환경 변수를 설정 (이 모두 크게 말했다 여기에 어떤 다른 답변)입니다.

다른 사람들은 현재 프로세스에서 환경 변수를 설정하는 방법으로 쉘 스크립트를 사용한다고 언급했지만 현재 (셸) 프로세스에서 프로그래밍 방식으로 변수를 설정해야하는 경우 가능한 간접적 인 방법이 있습니다 .

이를 고려

% cat envs.c 
#include <stdio.h> 
int main(int argc, char**argv) 
{ 
    int i; 
    for (i=1; i<argc; i++) { 
     printf("ENV%d=%s\n", i, argv[i]); 
    } 
} 
% echo $ENV1 

% ./envs one two 
ENV1=one 
ENV2=two 
% eval `./envs one two` 
% echo $ENV1 
one 
% 

내장 eval 그 인수가 쉘 프롬프트에서 입력 된 것처럼 인수를 평가합니다. 이것은 sh 스타일 예제입니다. csh 스타일 변형은 연습으로 남겨 둡니다!

+0

나는 이것이 투표 다운 된 것으로 나타났습니다. 그 이유는 무엇입니까? 누군가 오류를 발견 했습니까? –

+0

왜 누군가가 이것을 downvote 모르겠어요. 기묘한. 나에게 좋은 해결책 인 것 같아! – wasatchwizard

+0

대답은 내장 된 bash 명령 'eval'을 사용하여 환경 변수를 설정하기 때문에 프로그래머가 bash를 전혀 사용할 수 없을 가능성이 있기 때문입니다. 프로그래머가 쉘 스크립트 (항상 그런 것은 아니기 때문에)를 사용할 수 있다면, bash 특정 평가 이외의 다른 환경 변수를 설정할 수있는 더 확실하고 나은 방법이 있습니다. (p.s. 나는 downvote하지 않았다) –