저는 Debian GNU/Linux 9를 사용하고 있습니다. 알아요/proc
아주 특별한, 알아요무엇 /proc/self
인가요.
이 명령
sh -c '/bin/cat /proc/self/comm - </proc/self/comm'
생산하다
cat
sh
dash
대신 을 사용하면 패턴이 비슷해집니다 sh
. 그러나 bash
, ksh
또는 zsh
결과는 다음과 같습니다.
cat
cat
대신에 /proc/self/stat
나는 둘 다 실제로 동일한 과정이라는 /proc/self/comm
것을 확인할 수 있습니다 . cat
분명히 후드 아래의 껍질은 다릅니다. 괜찮습니다. 이제 우리가 가져 가자
sh -c '/bin/cat /proc/self/environ - </proc/self/environ'
위의 내용을 관찰한 후, sh
또는 dash
내가 볼 것으로 예상한 내용은 cat
나중에 쉘의 환경입니다. 작동하는 것 같습니다(어쨌든 두 환경은 동일할 가능성이 높으므로 여부를 말하기가 어렵습니다.모든 것예상대로 작동하지만 내 요점은 둘 다 environ
null이 아니라는 것입니다.
bash
, ksh
또는 zsh
두 번 볼 것으로 예상했던 환경이 있지만 cat
인쇄만 됩니다.한 번. 두 가지 상황으로 나누어집니다.
bash -c '/bin/cat - </proc/self/environ'
아무것도 인쇄하지 않고environ
마치 비어 있는 것처럼 작동합니다.bash -c '/bin/cat /proc/self/environ'
예상대로 무언가를 인쇄합니다.
무슨 일이야? comm
아니면 그렇지 않습니다 stat
. 왜 다른가요 environ
?
$ uname -a
Linux barbaz 4.9.0-6-amd64 #1 SMP Debian 4.9.88-1 (2018-04-29) x86_64 GNU/Linux
답변1
쉘 간의 차이는 프로세스 설정의 차이로 인해 발생합니다. dash
분기하기 전에 리디렉션을 설정하여 /proc/self
셸을 가리키 도록 bash
하고 zsh
분기 후에 이를 설정하여 /proc/self
새 프로세스를 가리키도록 합니다. 이런 일이 일어나는 것을 볼 수 있습니다 strace -f
:
strace -f dash -c '/bin/cat /proc/self/comm - </proc/self/comm'
연기(그리고 다른 많은 것)open("/proc/self/comm", O_RDONLY) = 3 fcntl(0, F_DUPFD, 10) = 10 close(0) = 0 fcntl(10, F_SETFD, FD_CLOEXEC) = 0 dup2(3, 0) = 0 close(3) = 0 clone(child_stack=NULL, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f12581299d0) = 7743 strace: Process 7743 attached [pid 7742] wait4(-1, <unfinished ...> [pid 7743] execve("/bin/cat", ["/bin/cat", "/proc/self/comm", "-"], [/* 43 vars */]) = 0
( 시스템 호출
/proc/self/comm
전에 열림clone
, 프로세스가 포크되는 곳입니다);strace -f bash -c '/bin/cat /proc/self/comm - </proc/self/comm'
프로그램clone(child_stack=NULL, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7fb506bdee10) = 8106 strace: Process 8106 attached [... snip a ton of signal-handling setup ...] [pid 8106] open("/proc/self/comm", O_RDONLY) = 3 [pid 8106] dup2(3, 0) = 0 [pid 8106] close(3) = 0 [pid 8106] execve("/bin/cat", ["/bin/cat", "/proc/self/comm", "-"], [/* 43 vars */]) = 0
( 자식 프로세스에서
/proc/self/comm
호출 후 열림clone
, 8106).
비어 있는 것으로 나타나는 이유를 이해하려면 environ
좀 더 설명이 필요합니다.언제 /proc/<pid>/environ
열릴까?, 커널포인터 복사본을 작업에 저장mm_struct
, 환경에 대한 포인터를 포함합니다. 하지만execve
, cat
프로세스를 시작하는 데 사용됩니다.mm_struct
프로세스에 대한 새 프로세스 만들기. 따라서 리디렉션은 결국 오래된 정보를 가리키게 되며 cat
입력을 읽을 때 실제 환경을 볼 수 없습니다. 환경을 조성하다하다see는 상위 환경의 복사본으로 간주되지만 execve
새 환경을 분기하고 설정하기 전에 이를 정리하는 셸이 포함됩니다.