나는 nohup
우분투를 발견하고 있습니다 disown
.bash
나는 가지고있다 while.py
.
import time
while True:
print(1)
time.sleep(1)
먼저 ssh를 사용하여 우분투 서버에 연결하고 를 입력한 nohup python3 while.py &
다음 exit
터미널에 들어갔다 나갔습니다. 서버에 다시 연결하고 를 입력하면 ps aux | grep python
프로세스가 실행 중인 것을 명확하게 볼 수 있습니다. 그런 다음 프로세스를 종료합니다.
둘째, 에 들어갔습니다 python3 while.py & disown
. 프로그램이 1
셸에서 인쇄를 시작합니다. 그런 다음 셸을 종료하고 서버에 다시 연결합니다. 그러나 을 입력하면 ps aux | grep python
프로세스가 실행되는 것을 볼 수 없습니다.
거부해도 터미널을 닫은 후 프로세스가 종료되는 것을 방지할 수 없는 것 같습니다. 관련 이슈를 검색해봤습니다.셀치크disown
쉘이 SIGHUP을 보내지 않는지 확인하고 nohup
프로세스가 보낸 SIGHUP을 수신하지 않는지 확인하는 것을 언급했습니다 .이 답변터미널이 종료될 때 모든 프로세스에 SIGHUP, SIGCONT, SIGCHID를 전송한다고 언급했습니다. 그래서 터미널을 닫은 후 nohup과 disown이 다르게 동작하는 이유가 무엇인지 궁금합니다.
영어는 나의 모국어가 아닙니다. 문법적인 오류가 있어도 용서해주세요. 도와주시면 감사하겠습니다.
답변1
원래 Unix 하드웨어 환경에서 "터미널"은 직렬 포트에 연결된 하드웨어였습니다. 이는 실제 터미널이나 전화선 모뎀 또는 이와 유사한 것일 수 있습니다.
원격 모뎀을 이용하여 모뎀을 호출하여 접속하면 시스템에 로그인이 됩니다. 연결을 끊으면("전화 끊기") 시스템은 직렬 포트에 연결된 모든 장치에 HUP를 보냅니다. 그런 다음 시스템은 man -s 7 signal
직렬 포트에 연결된 각 프로세스에 HUP 신호(참고자료 참조)를 보내 신호를 지우고 다음 사용자가 포트를 사용할 수 있도록 합니다. 물리적 터미널을 종료하면 끊김 현상도 시뮬레이션됩니다.
직렬 포트는 여전히 존재하지만 대부분의 "터미널"은 이제 가상이고 소프트웨어로 구현되며 의사 터미널(pty) 인터페이스를 통해 연결됩니다. 그러나 이것은 여전히 직렬 포트와 거의 동일합니다. 의사 터미널에는 두 가지 인터페이스가 있습니다. 하나는 터미널 소프트웨어 연결을 위한 기본 인터페이스이고, 다른 하나는 외부 직렬 포트의 소프트웨어 측면과 같은 기능을 하는 클라이언트입니다.
메인 pty가 닫히거나(창을 닫거나 ssh 연결을 끊는 등) 다른 여러 작업이 발생하면 모뎀 끊김과 동일한 이벤트가 트리거되어 터미널에 연결된 모든 프로세스에 HUP 신호가 전송됩니다.
이 nohup
명령은 프로세스가 HUP 신호를 수신하지 못하도록 방지하여 프로세스가 직접 종료되지 않도록 합니다. 그러나 여전히 표준 입력과 표준 출력이 터미널에 연결되어 있을 수 있습니다. 마스터 pty가 닫힌 후 stdin 및 stdout은 /dev/null로 효과적으로 대체됩니다. 이로 인해 읽기를 시도할 때 프로세스가 stdin에서 EOF를 수신하여 여전히 종료될 수 있습니다.
셸에 백그라운드 작업이 있고 셸을 종료하면 일반적으로 HUP 신호를 사용하여 자체적으로 정리할 작업을 종료하려고 시도합니다. 이 disown
명령은 작업 제어 목록에 있는 작업을 삭제하도록 쉘에 지시합니다. 이는 터미널에서 작업 프로세스의 연결을 해제하지 않으며 터미널은 여전히 해당 프로세스를 제거하려고 시도할 수 있습니다.
답변2
문제의 원인을 발견했습니다.이 답변말하는
터미널인 경우파괴되다(이것은 xterm 또는 ssh에 의해 생성된 것과 같은 pty이고 xterm을 닫거나 SSH 연결을 종료하여 제어 프로그램이 종료되는 경우 발생할 수 있습니다.) 프로그램은실패하다일단 시도하면표준 입력에서 읽기또는표준 출력에 쓰기.
Disown은 터미널이 종료된 후에 연결을 끊 stdout
거나 disown 하지 않습니다 stderr
. 내 프로그램이 print(1)
쓰기를 시도 stdout
하고 프로그램이 충돌하게 됩니다.
stdout
이 문제를 해결하려면 리디렉션 하고 stderr
전달 하면 됩니다.python3 while.py >/dev/null 2>&1 & disown
답변3
disown은 쉘의 작업 제어에서 프로세스를 제거하고 프로세스는 여전히 터미널 세션에 연결되므로 터미널을 종료하면 프로세스가 종료됩니다.