Subshell 백그라운드 프로세스 pid를 변수에 할당

Subshell 백그라운드 프로세스 pid를 변수에 할당

현재 서브셸에서 백그라운드 프로세스를 시작하고 있는데 서브셸 범위 밖의 변수에 해당 pid 번호를 할당하는 방법이 궁금합니다.
나는 많은 다른 것들을 시도했지만 MYPID항상 동일하게 유지됩니다 0.

MYPID = 0;
({ sleep 2 & }; $MYPID=$!)
({ sleep 2 & }; echo $!) > $MYPID

값을 반환하는 유일한 방법은 다음과 같습니다.

$MYPID=$({ sleep 2 & }; echo $!)

그러나 이는 백그라운드 처리 명령을 삭제하고 2초 후에만 결과를 반환합니다.

답변1

bash대화형이 아닌 경우 작업 상태가 인쇄되어서는 안 됩니다.

이것이 실제로 대화형이라면 bash다음과 같이 할 수 있습니다.

{ pid=$(sleep 20 >&3 3>&- & echo "$!"); } 3>&1

sleep우리는 파이프에 변수를 제공하는 대신 stdout이 이전 위치로 이동하기를 원합니다 $pid. 그래서 우리는 저장밖의파일 설명자 3( ) 3>&1의 stdout 을 sleep내부 명령 대체로 복원합니다. 따라서 제공된 파이프에 열려 있는 파일 설명자가 없기 때문에 pid=$(...)일단 종료되면 반환됩니다 .echo$pid

그러나 서브쉘에서 시작되기 때문에(여기서는 명령 대체) sleep별도의 프로세스 그룹에서 실행되지 않습니다. 따라서 sleep 20 &예를 들어 터미널 I/O와는 다르게 동작합니다.

아마도 더 좋은 방법은 생성을 지원하는 쉘을 사용하는 것입니다.인식되지 않음zsh수행할 수 있는 작업 과 같은 백그라운드 작업 :

sleep 20 &! pid=$!

를 사용하면 bash다음과 같이 대략적으로 계산할 수 있습니다.

{ sleep 20 2>&3 3>&- & } 3>&2 2> /dev/null; pid=$!; disown "$pid"

bashstderr로 출력합니다 [1] 21578. 따라서 다시 /dev/null로 리디렉션하기 전에 stderr를 저장하고 sleep명령에 대해 복원합니다. 이렇게 하면 but 의 stderr [1] 21578로 가는 것이 평소대로 진행됩니다./dev/nullsleep

모든 것을 /dev/null로 리디렉션하려면 다음을 수행하면 됩니다.

{ apt-get update & } > /dev/null 2>&1; pid=$!; disown "$pid"

표준 출력만 리디렉션:

{ apt-get-update 2>&3 3>&- & } 3>&2 > /dev/null 2>&1; pid=$!; disown "$pid"

답변2

두 번째 줄은 작동하지 않습니다

({ sleep 2 & }; $MYPID=$!)

서브셸을 포크하고 ( ... )MYPID를 설정한 다음 서브셸이 종료되고 해당 값이 손실됩니다.

세 번째 줄도 작동하지 않습니다

({ sleep 2 & }; echo $!) > $MYPID

$!를 로컬 디렉터리의 0이라는 파일에 echo하면 됩니다.

제가 제공할 수 있는 유일한 답변은 임시 파일을 이용하는 것입니다(var는 다시 푸시할 수 없으므로).

 ( { sleep 100 & } ; echo $! > u ) > /dev/null &> /dev/null
 MYPID=$(<u)

u어떤 파일로든 바꿀 수 있습니다 .

관련 정보