백그라운드 프로세스가 끝날 때까지 함수가 반환되지 않는 이유는 무엇입니까?


21

이 스크립트를 고려하십시오.

#!/bin/bash
function start {
  leafpad &
  echo $!
}
PID=$(start)
echo "PID is $PID"

스크립트는 백그라운드 프로세스 인 경우에도 리프 패드 프로세스가 종료 될 때까지 닫는 중괄호를지나 계속 진행되지 않습니다.

왜 이런거야? 함수에서 백그라운드 프로세스를 시작할 수 있습니까?

답변:


22

백그라운드 작업을 작성했지만 여전히 stdout fd가 열려 있기 때문에 함수가 리턴하지만 명령 대체가 차단됩니다. >/dev/null앞에 추가하여 닫으십시오 &.

#!/bin/bash
function start {
  leafpad >/dev/null &
  echo $!
}
PID=$(start)
echo "PID is $PID"

프로세스가 stdin, stdout, stderr을 닫으려면 다음을 사용하십시오.

leafpad >/dev/null 0>&1 2>&1 &

stdin (0), stdout (1) 및 stderr (2)가 닫히고 백그라운드 (&)가 닫힙니다. 또한 이러한 스트림 재 지정을 사용할 때 "지연"된 것을 잊지 마십시오. 즉, 실행 순서대로 복제됩니다.

1>/dev/null 2>&1

과

2>&1 1>/dev/null

동일하지 않습니다! 전자에서는 스트림을 / dev / null (원하는 것)로 복제하고, 후자에서는 / dev / stdout을 stderr에 복제 한 다음 stdout을 닫습니다. 전송 된 모든 메시지 stderr가 콘솔에 나타납니다.


내 시스템에서 확인 됨
— user120161

10
스트림을 닫지 않고 리디렉션합니다.
— dcat

4
닫는; 파일 디스크립터는 n>&-어디에 있습니까 n?
— dcat

1
@dcat : 그렇습니다. 그러나 /dev/null프로세스가 stdout을 쓰려고 할 때 /에서 / 로의 경로 재 지정으로 인해 i / o 오류가 발생하지는 않지만 1유효하지 않은 FD입니다. 따라서 게시물의 용어는 실제 bash 프로그래밍이 아니라 잘못되었습니다. (실제로, FD 1을 0으로 복제한다는 것은 stdin O_RDONLY이로 열린 파일 디스크립터가됨을 의미하며 , 프로세스를 읽으려고 할 때 (원하는 바이트 수가 아닌) 오류가 발생합니다.) wc >/dev/null 0>&1--–wc: standard input: Bad file descriptor
— Peter Cordes

1
@PeterCordes-기존 디스크립터를 닫고 새 디스크립터를 리디렉션하는 것은 상호 배타적 일 필요는 없습니다. exec <&- >&- <>/dev/null >&0stdin / out을 철저하게 처리합니다. 그것은에서 차이가 zsh적어도되는 것입니다 종류 CONCATENATE의 모든 multios가 설정되어 자동으로 동일한 기술자에 열립니다.
— mikeserv
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.