"&"를 사용하고 있습니다. 프로세스가 백그라운드에서 실행되지 않는 이유는 무엇입니까?

"&"를 사용하고 있습니다. 프로세스가 백그라운드에서 실행되지 않는 이유는 무엇입니까?

&백그라운드에서 프로세스를 실행하는 명령을 연결할 수 있다는 것을 알고 있습니다 .

SSH를 통해 Ubuntu 12.04 시스템에 연결하고 $python program.py &--를 사용하여 Python 프로그램을 실행하고 있지만 터미널 창을 닫으면 터미널을 닫으면 실행 중인 프로세스가 종료된다는 메시지가 표시됩니다.

왜 이런거야? & 기호를 사용하여 백그라운드에서 프로세스를 실행하고 있습니다. SSH를 통해 연결되어 있는지 여부에 관계없이 어떻게 작동하게 합니까?

답변1

터미널 창을 닫으면 터미널 에뮬레이터는 실행 중인 프로세스(예: 셸)에 SIGHUP을 보냅니다. 그런 다음 쉘은 해당 SIGHUP을 실행 중인 모든 항목에 전달합니다. 로컬 시스템에서는 ssh입니다. 그런 다음 ssh는 SIGHUP을 실행 중인 원격 셸로 전달합니다. 따라서 원격 셸은 모든 프로세스(데몬)에 SIGHUP을 보냅니다.

이 문제를 해결하는 방법에는 두 가지가 있습니다.

  1. 셸에서 백그라운드 프로그램의 연결을 해제합니다.
    1. disown프로세스를 백그라운드에 배치한 후 이 명령을 사용하십시오. 이렇게 하면 쉘이 이를 잊어버리게 됩니다.
    2. 명령 앞에 nohup( )를 추가합니다 nohup $python program.py &. 이는 동일한 작업을 수행하지만 중간 프로세스를 사용합니다. 기본적으로 SIGHUP 신호를 무시한 다음 설정을 상속하는 프로그램을 분기하고 실행한 다음 종료합니다. 포크되기 때문에 시작되는 프로그램은 쉘의 서브루틴이 아니며 쉘은 이를 인식하지 못합니다. SIGHUP용 신호 처리기를 설치하지 않는 한 무시된 상태로 유지됩니다.
  2. 터미널 창을 닫는 대신 logout(또는 Ctrl+ )를 사용하세요 . d를 사용하면 logout이는 SIGHUP이 아니므로 쉘은 하위 항목에 SIGHUP을 보내지 않습니다.

또한 프로그램이 STDOUT 또는 STDERR을 통해 터미널에 쓰지 않도록 해야 합니다. 터미널이 종료되면 둘 다 더 이상 존재하지 않기 때문입니다. 그런 식으로 리디렉션하지 않으면 /dev/null프로그램은 계속 실행되지만 쓰기를 시도하면 SIGPIPE를 받게 되며 SIGPIPE의 기본 동작은 프로세스를 종료하는 것입니다.

답변2

프로세스는 터미널의 백그라운드에서 실행되지만 stdout(and stderr)의 출력은 여전히 ​​터미널로 전송됩니다. 이를 중지하려면 두 출력을 모두 리디렉션하기 > /dev/null 2>&1전에 추가하세요 . 또한 추가하면 터미널을 닫은 후에도 프로세스가 종료되지 않는지 확인됩니다.&/dev/nulldisown

COMMAND > /dev/null 2>&1 & disown

귀하의 경우에는 다음과 같습니다:

python program.py > /dev/null 2>&1 & disown

답변3

연산자는 직렬로 실행할 명령을 분리 &하는 것처럼 병렬로 실행할 명령을 분리합니다 ;. 두 명령 모두 여전히쉘 프로세스의 하위 프로세스로 실행.

따라서 이러한 하위 키를 시작한 셸을 닫으면 해당 하위 키도 닫힙니다.

당신이 원하는 것은악마, 이는 상위 프로세스에서 완전한 분리가 필요하므로 훨씬 더 까다롭습니다. 쉘에는 일반적으로 이를 수행하는 쉬운 방법이 없습니다.

답변4

앰퍼샌드( )로 끝나는 명령 뒤에 &명령 프롬프트에서 다음 명령을 실행합니다 bg.

bash> python program.py &  
bash> bg  

이렇게 하면 "&" 명령이 백그라운드로 실행됩니다.

bash> jobs  

백그라운드에서 실행 중인 작업이 나열됩니다.

bash> fg 1   

그러면 작업 #1이 포그라운드로 나타납니다.

또 다른 방법(로그아웃 기능)

bash> at now  
bash> /full/path/python /full/path/program.py  
bash> ^d   `(# That is, Control-D, to run the command, Control-C to cancel)`  

여러 줄 명령을 제출할 수 있습니다 . at^d(Control-D) 이전을
참조하세요 man at.

관련 정보