Bash 및 서브셸

Bash 및 서브셸

온라인 문서에서 수집한 내용에 따르면 다음은 포함된 명령 부분에 대한 하위 쉘을 생성해야 합니다 {}.

$ bash -c '{ sleep 10; echo "Sleeping process", $$; }  & echo $$; '
11237
 Sleeping process, 11237

그러나 보시다시피 두 경우 모두 프로세스 ID는 동일합니다. 내가 무엇을 놓치고 있나요? 어떤 조언을 해주셔서 감사합니다.

답변1

just 는 {}현재 셸에서 명령을 함께 그룹화하고 ()새 하위 셸을 시작합니다. 그러나 여러분이 하고 있는 일은 그룹화된 명령을 배경에 두는 것인데, 이는 실제로 새로운 프로세스입니다. 현재 프로세스에 있었다면 백그라운드로 처리할 수 없었을 것입니다. IMHO, strace를 사용하여 이런 종류의 것을 보는 것이 더 쉽습니다.

sauer@humpy:~$ strace -f -etrace=process bash -c '{ sleep 10; echo "Sleeping process", $BASHPID, $BASH_SUBSHELL; }  & echo $BASHPID;' > /tmp/file
execve("/bin/bash", ["bash", "-c", "{ sleep 10; echo \"Sleeping proce"...], [/* 20 vars */]) = 0
arch_prctl(ARCH_SET_FS, 0x7f15a90da700) = 0
clone(Process 25347 attached
child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f15a90da9d0) = 25347
[pid 25346] exit_group(0)               = ?
clone(Process 25348 attached (waiting for parent)
Process 25348 resumed (parent 25347 ready)
child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f15a90da9d0) = 25348
[pid 25348] execve("/bin/sleep", ["sleep", "10"], [/* 20 vars */] <unfinished ...>
[pid 25347] wait4(-1, Process 25347 suspended
 <unfinished ...>
[pid 25348] <... execve resumed> )      = 0
[pid 25348] arch_prctl(ARCH_SET_FS, 0x7f922ad16700) = 0
[pid 25348] exit_group(0)               = ?
Process 25347 resumed
Process 25348 detached
<... wait4 resumed> [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0, NULL) = 25348
--- SIGCHLD (Child exited) @ 0 (0) ---
wait4(-1, 0x7fffaa432ad8, WNOHANG, NULL) = -1 ECHILD (No child processes)
exit_group(0)                           = ?
Process 25347 detached

sauer@humpy:~$ cat /tmp/file
25346
Sleeping process, 25347, 1

bash 명령이 시작된 다음 clone(). strace에 -f 옵션을 사용하면 하위 프로세스도 따라가며 절전 모드를 실행할 때 또 다른 포크(음, "복제")가 표시됩니다. -f를 꺼진 상태로 두면 백그라운드 프로세스를 생성할 때 하나의 복제 호출만 표시됩니다.

sauer@humpy:~$ strace -etrace=clone bash -c '{ sleep 10; echo "Sleeping process", $BASHPID, $BASH_SUBSHELL; }  & echo $BASHPID;' > /tmp/file
clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f2bdd5399d0) = 26394
sauer@humpy:~$ strace -etrace=process bash -c '{ sleep 10; echo "Sleeping process", $BASHPID, $BASH_SUBSHELL; }  & echo $BASHPID;' > /dev/null
execve("/bin/bash", ["bash", "-c", "{ sleep 10; echo \"Sleeping proce"...], [/* 20 vars */]) = 0
arch_prctl(ARCH_SET_FS, 0x7fd01ae86700) = 0
clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7fd01ae869d0) = 26706
exit_group(0)                           = ?

새 프로세스를 얼마나 자주 생성하는지 알고 싶다면 포크 및 복제 호출만 관찰하면 더욱 단순화할 수 있습니다.

sauer@humpy:~$ strace -etrace=fork,clone bash -c '{ sleep 10; echo "Sleeping process", $BASHPID, $BASH_SUBSHELL; }  & echo $BASHPID;' > /dev/null
clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f467fa769d0) = 27025

답변2

업데이트:

위의 답변을 참조하시기 바랍니다. {}를 사용하면 실제로 서브셸을 생성하는 것이 아닙니다. 대신, 여기의 배경 접지는 내가 찾고 있던 답을 제공합니다.

좋아요, 기본적으로 저는 생성되는 서브쉘의 잘못된 "표시기"를 사용하고 있었습니다. 나는 BASHPID~ 에 대해 배웠다여기그리고 이를 추가로 사용하면 BASH_SUBSHELL실제로 서브쉘이 생성되는 것을 볼 수 있습니다.

테스트 명령:

$ bash -c '{ sleep 10; echo "Sleeping process", $BASHPID, $BASH_SUBSHELL; }  & echo $BASHPID; '
12074
 Sleeping process, 12075, 1

셸과 하위 셸 모두에 대한 상위 프로세스 ID도 표시하는 또 다른 테스트 명령:

$ bash -c '{ sleep 10; echo "Sleeping process", $BASHPID, $BASH_SUBSHELL, $PPID; }  & echo $BASHPID, $PPID; '
12411, 9128
$ Sleeping process, 12412, 1, 9128

관련 정보