Linux /proc/<pid>/environ
는 업데이트되지 않습니다 (내가 이해하는 것처럼 파일에는 프로세스의 초기 환경이 포함되어 있음).
프로세스의 현재 환경을 어떻게 읽을 수 있습니까?
Linux /proc/<pid>/environ
는 업데이트되지 않습니다 (내가 이해하는 것처럼 파일에는 프로세스의 초기 환경이 포함되어 있음).
프로세스의 현재 환경을 어떻게 읽을 수 있습니까?
답변:
/proc/$pid/environ
프로세스가 자체 환경을 변경하면 업데이트합니다. 프로그램의 환경은을 통해 정상적인 채널을 통해 볼 수 없습니다 : 그것은 조금 무의미이기 때문에 그러나 많은 프로그램은 자신의 환경을 변경 귀찮게하지 않습니다 /proc
하고 ps
, 심지어는없는 모든 유닉스 변종 기능의이 종류를 가지고 응용 프로그램을 의존하지 않도록, 그 위에.
커널에 관한 한, 환경 execve
은 프로그램을 시작하는 시스템 호출 의 인수로만 나타납니다 . 리눅스는를 통해 메모리의 영역을 노출시키고 /proc
, 일부 프로그램은이 영역을 업데이트하지만 다른 프로그램은 그렇지 않습니다. 특히, 어떤 쉘 도이 영역을 업데이트한다고 생각하지 않습니다. 면적이 고정 크기이므로 새 변수를 추가하거나 값의 길이를 변경할 수 없습니다.
PATH=foo
쉘로 작성 한다고해서 쉘이 수정된다는 의미는 아닙니다 *envp
. 일부 셸에서는 내부 데이터 구조 만 업데이트했으며 업데이트하는 외부 프로그램 실행 코드입니다 *envp
. 봐 assign_in_env
에서 variables.c
예를 들어, bash는 소스입니다.
fork
하면 libc는 sys_fork
하위 프로세스에 힙 할당 환경을 사용하여 호출합니다.
argv
가 더 일반적이지만 둘 다 존재합니다).
에서 프로세스 의 초기 환경을 읽을 수 있습니다 /proc/<pid>/environ
.
프로세스 가 환경을 변경 하는 경우 환경을 읽으려면 프로세스의 기호 테이블이 있어야하고 ptrace
시스템 호출 (예 :을 사용하여 gdb
)을 사용 하여 전역 char **__environ
변수 에서 환경을 읽으십시오 . 실행중인 Linux 프로세스에서 변수의 값을 얻는 다른 방법은 없습니다.
그게 답입니다. 이제 몇 가지 참고 사항이 있습니다.
위의 프로세스는 POSIX 호환 프로세스라고 가정합니다. 즉 프로세스가 Ref Spec에char **__environ
지정된 전역 변수 를 사용하여 환경을 관리합니다 .
프로세스의 초기 환경은 프로세스 스택의 고정 길이 버퍼에서 프로세스로 전달됩니다. (이 작업을 수행 일반적인 메커니즘입니다 linux//fs/exec.c:do_execve_common(...)
.) 버퍼의 크기가 더 이상 할 초기 환경에 필요한 크기보다, 기존 변수를 지우거나 스택 스매싱 않고 새로운 변수를 추가 할 수 없습니다 계산되지 않기 때문에. 따라서 프로세스 환경의 변경을 허용하는 합리적인 체계는 힙을 사용하는데, 임의 크기의 메모리를 할당하고 해제 할 수 있습니다. 이는 GNU libc
( glibc
) 가 정확히하는 역할입니다.
프로세스가을 사용하는 경우 glibc
POSIX와 호환 __environ
되며 glibc//posix/environ.c
Glibc 에서 선언되어 프로세스의 힙에서 가져온 __environ
메모리에 대한 포인터로 초기화 malloc
한 다음 스택의 초기 환경을이 힙 영역으로 복사합니다. 프로세스가 setenv
함수를 사용할 때마다 glibc
a 는 새 값 또는 변수를 수용하도록 가리키는 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
해야 할 것이며 아무도 환경의 변화를 어디에서했는지 추측 할 수 없을 것입니다.
/proc/[pid]/
이상한 인코딩을 가진 것으로 보입니다 (다른 사람이 무엇을, 왜 알 수 있는지). 나를 cat environ
위해 환경 변수를 읽기 어려운 형식으로 인쇄하기 만하면 됩니다. cat environ | strings
나를 위해 이것을 해결했습니다.
프로세스가 환경 변수를 획득 / 삭제할 때 업데이트됩니다. 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 ~]$
export foo=bar
하나의 bash는 세션 (PID XXXX)에, 다음 할 cat /proc/xxxx/environ | tr \\0 \\n
다른 배쉬의 세션에서 나는 볼 수 없습니다 foo
.
gdb
pid에 환경을 연결하려고 시도 했지만 여전히 참조가 없습니다. 메모리의 환경 변수 블록은 변경이있을 때마다 재 할당되고 proc 파일 시스템의 자체 프로세스 환경 파일에 반영되지 않지만 자식 프로세스에 의해 상속 될 수 있습니다. 즉, 포크가 발생할 때 본질적인 세부 사항을 더 쉽게 알 수 있으며 자식 프로세스가 환경 변수를 그대로 복사하는 방법은 무엇입니까?
다음은 저자의 실제 의도와 관련이 없지만 실제로 "읽기"를 원한다면 /proc/<pid>/environ
시도해보십시오.
strings /proc/<pid>/environ
cat
그것 보다 낫다 .
strings
. 간단하게 유지하십시오.
xargs --null
.
tr '\0' '\n' < /proc/$$/environ | ...