현재 서브셸에서 백그라운드 프로세스를 시작하고 있는데 서브셸 범위 밖의 변수에 해당 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"
bash
stderr로 출력합니다 [1] 21578
. 따라서 다시 /dev/null로 리디렉션하기 전에 stderr를 저장하고 sleep
명령에 대해 복원합니다. 이렇게 하면 but 의 stderr [1] 21578
로 가는 것이 평소대로 진행됩니다./dev/null
sleep
모든 것을 /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
어떤 파일로든 바꿀 수 있습니다 .