명령 대체, 프로세스 대체, 파이프 및 백그라운드 작업에서 실행될 때 "jobs" 및 "dirs"가 원래 셸에서와 동일하게 출력되는 이유는 무엇입니까?

명령 대체, 프로세스 대체, 파이프 및 백그라운드 작업에서 실행될 때 "jobs" 및 "dirs"가 원래 셸에서와 동일하게 출력되는 이유는 무엇입니까?

내가 맞다면 명령 대체, 프로세스 대체, 파이프 및 백그라운드 작업은 원래 셸이 아닌 하위 셸에서 자체적으로 지정된 명령을 실행합니다.

그러나 명령이 jobs또는 인 경우 dirs해당 출력은 원래 셸에서 직접 실행될 때와 정확히 동일합니다.

echo $( jobs )

cat <(jobs)

jobs | less

echo $( dirs )

cat <(dirs)

dirs | less

dirs &

왜 그런 겁니까? 서브셸이 원본 셸에서 작업 및 디렉터리 스택을 상속하기 때문입니까, 아니면 jobs및 이 dirs서브셸이 아닌 원본 셸에서 실행되고 있기 때문입니까?

하지만

jobs &

아무것도 출력하지 않습니다. 왜 다른 명령과 다른가요? 감사해요.

관련된하위 쉘에서 스크립트를 가져오면 스크립트의 명령이 원래 쉘의 상태에 액세스할 수 있습니까?

답변1

이 답변의 첫 번째 부분은 과 내장되어 있으므로 일반적으로 bash는 서브 쉘을 호출하는 대신 직접 실행합니다 jobs.dirs

$(jobs)파이프나 명령 대체( )나 프로세스 대체( )가 있는 경우에도 마찬가지이다 <(jobs).

jobs &백그라운드에서 명령을 실행하거나( ) 명시적으로 서브셸을 요청하는 경우( . 사용 ) ( jobs )는 그렇지 않습니다 .

이것은 질문의 마지막 부분을 설명합니다. 서브셸에서 실행 하면 jobs서브셸 자체에 대한 작업이 표시됩니다.

다음은 이 개념을 잘 보여주는 예입니다.

$ sleep 1001 &
[1] 15927
$ sleep 1002 &
[2] 15940
$ jobs
[1]-  Running                 sleep 1001 &
[2]+  Running                 sleep 1002 &
$ ( sleep 1003 & jobs )
[1]+  Running                 sleep 1003 &
$ jobs
[1]-  Running                 sleep 1001 &
[2]+  Running                 sleep 1002 &

jobs서브셸에서 실행할 때 해당 서브셸에 대한 작업 만 표시되는 것을 볼 수 있습니다 (이 경우).sleep 1003

이제 요약하자면 문제의 중간 부분을 해결해야 합니다. 이것이 dirs &바로 (하위 쉘에서 실행되는 것처럼 ( dirs )) 여전히 Pushd 스택에 저장된 디렉터리를 표시하는 이유입니다.

DIRSTACK이는 쉘이 디렉토리 목록을 특수 배열 변수로 내보내고 이 변수가 서브쉘에 의해 상속되기 때문인 것으로 나타났습니다 . (자세한 내용은DIRSTACK 여기.)

이것이 어떻게 작동하는지 보여주는 한 가지 방법은 pushd하위 쉘에서 사용하고 원래 쉘의 디렉토리 스택에 어떻게 영향을 주지 않는지 확인하는 것입니다.

$ dirs
~
$ pushd ~/tmp
~/tmp ~
$ ( dirs; pushd / >/dev/null; dirs )
~/tmp ~
/ ~/tmp ~
$ dirs
~/tmp ~

나는 이것이 당신이 요청한 모든 문제를 해결해야 한다고 믿습니다.


고쳐 쓰다jobs | less:bash에는 현재 셸에서 명령을 실행할 수 있는 특별한 조항이 있습니다 jobs(다른 내장 명령은 그렇지 않습니다.)

코드에는 하위 쉘을 생성하지 않고 실행하고 출력을 다른 명령으로 jobs_hack파이프할 수 있도록 나중에 검사되는 변수에 검사가 저장 되어 있습니다.jobs

바라보다여기이 기능을 구현하는 소스 코드의 관련 부분을 이해하십시오. (배쉬 4.4부터)

관련 정보