프로세스의 환경 변수를 읽는 방법 것처럼 파일에는 프로세스의

Linux /proc/<pid>/environ는 업데이트되지 않습니다 (내가 이해하는 것처럼 파일에는 프로세스의 초기 환경이 포함되어 있음).

프로세스의 현재 환경을 어떻게 읽을 수 있습니까?



답변

/proc/$pid/environ프로세스가 자체 환경을 변경하면 업데이트합니다. 프로그램의 환경은을 통해 정상적인 채널을 통해 볼 수 없습니다 : 그것은 조금 무의미이기 때문에 그러나 많은 프로그램은 자신의 환경을 변경 귀찮게하지 않습니다 /proc하고 ps, 심지어는없는 모든 유닉스 변종 기능의이 종류를 가지고 응용 프로그램을 의존하지 않도록, 그 위에.

커널에 관한 한, 환경 execve은 프로그램을 시작하는 시스템 호출 의 인수로만 나타납니다 . 리눅스는를 통해 메모리의 영역을 노출시키고 /proc, 일부 프로그램은이 영역을 업데이트하지만 다른 프로그램은 그렇지 않습니다. 특히, 어떤 쉘 도이 영역을 업데이트한다고 생각하지 않습니다. 면적이 고정 크기이므로 새 변수를 추가하거나 값의 길이를 변경할 수 없습니다.


답변

에서 프로세스 의 초기 환경을 읽을 수 있습니다 /proc/<pid>/environ.

프로세스 환경을 변경 하는 경우 환경을 읽으려면 프로세스의 기호 테이블이 있어야하고 ptrace시스템 호출 (예 :을 사용하여 gdb)을 사용 하여 전역 char **__environ변수 에서 환경을 읽으십시오 . 실행중인 Linux 프로세스에서 변수의 값을 얻는 다른 방법은 없습니다.

그게 답입니다. 이제 몇 가지 참고 사항이 있습니다.

위의 프로세스는 POSIX 호환 프로세스라고 가정합니다. 즉 프로세스가 Ref Spec에char **__environ 지정된 전역 변수 를 사용하여 환경을 관리합니다 .

프로세스의 초기 환경은 프로세스 스택의 고정 길이 버퍼에서 프로세스로 전달됩니다. (이 작업을 수행 일반적인 메커니즘입니다 linux//fs/exec.c:do_execve_common(...).) 버퍼의 크기가 더 이상 할 초기 환경에 필요한 크기보다, 기존 변수를 지우거나 스택 스매싱 않고 새로운 변수를 추가 할 수 없습니다 계산되지 않기 때문에. 따라서 프로세스 환경의 변경을 허용하는 합리적인 체계는 힙을 사용하는데, 임의 크기의 메모리를 할당하고 해제 할 수 있습니다. 이는 GNU libc( glibc) 가 정확히하는 역할입니다.

프로세스가을 사용하는 경우 glibcPOSIX와 호환 __environ되며 glibc//posix/environ.cGlibc 에서 선언되어 프로세스의 힙에서 가져온 __environ메모리에 대한 포인터로 초기화 malloc한 다음 스택의 초기 환경을이 힙 영역으로 복사합니다. 프로세스가 setenv함수를 사용할 때마다 glibca 는 새 값 또는 변수를 수용하도록 가리키는 realloc영역의 크기를 조정합니다 __environ. 으로 glibc 소스 코드를 다운로드 할 수 있습니다 git clone git://sourceware.org/git/glibc.git glibc. 메커니즘을 실제로 이해하려면 Hurd 코드도 읽어야합니다 hurd//init/init.c:frob_kernel_process()(git clone git : //git.sv.gnu.org/hurd/hurd.git hurd).

새로운 프로세스는 경우 이제 fork에드 후속없이, exec스택을 덮어 쓰기, 다음 인수 및 환경 복사 마법에서 이루어집니다 linux//kernel/fork.c:do_fork(...)경우, copy_process루틴 호출을 dup_task_struct호출하여 새로운 프로세스의 스택을 할당 alloc_thread_info_node, 전화 setup_thread_stack( linux//include/linux/sched.h새로운 프로세스)를 사용 alloc_thread_info_node.

마지막으로 POSIX __environ규칙은 사용자 공간 규칙입니다. Linux 커널에서는 아무 것도 연결되어 있지 않습니다. 전역 을 사용 glibc하거나 사용하지 않고 사용자 공간 프로그램을 작성한 __environ다음 원하는 환경 변수를 관리 할 수 ​​있습니다. 아무도 당신을이 일로 체포하지는 않지만 자신의 환경 관리 기능 ( setenv/ getenv)과 자신의 래퍼를 작성 sys_exec해야 할 것이며 아무도 환경의 변화를 어디에서했는지 추측 할 수 없을 것입니다.


답변

프로세스가 환경 변수를 획득 / 삭제할 때 업데이트됩니다. environ/ proc 파일 시스템의 프로세스 디렉토리에 프로세스에 대해 파일이 업데이트되지 않았다는 참조가 있습니까?

xargs --null --max-args=1 echo < /proc/self/environ

또는

xargs --null --max-args=1 echo < /proc/<pid>/environ

또는

ps e -p <pid>

위는 프로세스의 환경 변수를 ps출력 형식으로 인쇄하며 , 환경 변수를 목록으로 보려면 텍스트 처리 (구문 분석 / 필터링)가 필요합니다.

솔라리스 (요청하지는 않지만 참조를 위해 여기에 게시합니다) :

/usr/ucb/ps -wwwe <pid>

또는

pargs -e <pid>

편집 : / proc / pid / environ이 업데이트되지 않았습니다! 나는 정정되었다. 확인 과정은 다음과 같습니다. 그러나 프로세스가 분기되는 하위 프로세스는 프로세스 환경 변수를 상속하며 각각의 / proc / self / environ 파일에 표시됩니다. (문자열 사용)

쉘에서 : xargs는 자식 프로세스이므로 환경 변수를 상속하고 /proc/self/environ파일 에도 반영 됩니다.

[centos@centos t]$ printenv  | grep MASK
[centos@centos t]$ export MASK=NIKHIL
[centos@centos t]$ printenv  | grep MASK
MASK=NIKHIL
[centos@centos t]$ xargs --null --max-args=1 echo < /proc/self/environ  | grep MASK
MASK=NIKHIL
[centos@centos t]$ unset MASK
[centos@centos t]$ printenv  | grep MASK
[centos@centos t]$ xargs --null --max-args=1 echo < /proc/self/environ  | grep MASK
[centos@centos t]$

터미널 / 세션이 환경 변수가 설정된 쉘의 하위 프로세스가 아닌 다른 세션에서 확인하십시오.

동일한 호스트의 다른 터미널 / 세션에서 확인 :

terminal1 : : printenv는 분기되어 bash의 자식 프로세스이므로 자체 환경 파일을 읽습니다.

[centos@centos t]$ echo $$
2610
[centos@centos t]$ export SPIDEY=NIKHIL
[centos@centos t]$ printenv | grep SPIDEY
SPIDEY=NIKHIL
[centos@centos t]$

terminal2 : 동일한 호스트에서-위 변수가 설정된 동일한 쉘에서 시작하지 말고 터미널을 개별적으로 시작하십시오.

[centos@centos ~]$ echo $$
4436
[centos@centos ~]$ xargs --null --max-args=1 echo < /proc/self/environ | grep -i spidey
[centos@centos ~]$ strings -f /proc/2610/environ | grep -i spidey
[centos@centos ~]$ xargs --null --max-args=1 echo < /proc/2610/environ | grep -i spidey
[centos@centos ~]$

답변

다음은 저자의 실제 의도와 관련이 없지만 실제로 “읽기”를 원한다면 /proc/<pid>/environ시도해보십시오.

strings /proc/<pid>/environ

cat그것 보다 낫다 .