나는`&`를 사용하고 있습니다 : 왜 프로세스가 백그라운드에서 실행되지 않습니까?


24

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

우분투 12.04 상자에 SSH를 넣고 파이썬 프로그램을 실행하고 있습니다. $python program.py &하지만 터미널 창을 닫을 때 터미널을 닫으면 실행중인 프로세스가 종료된다는 메시지가 나타납니다.

왜 이런거야? 앰퍼샌드를 사용하여 백그라운드에서 프로세스를 실행하고 있습니다. SSH를 사용하고 있는지 여부에 관계없이 어떻게 실행할 수 있습니까?



apt-get 설치 화면, 맨 스크린
captcha

답변:


51

터미널 창을 닫으면 터미널 에뮬레이터가 SIGHUP을 실행중인 프로세스 인 쉘로 보냅니다. 그런 다음 쉘은 SIGHUP을 실행중인 모든 것에 전달합니다. 로컬 시스템에서 이것은 ssh입니다. 그런 다음 ssh는 SIGHUP을 실행중인 원격 쉘로 전달합니다. 따라서 원격 쉘은 SIGHUP을 백그라운드 프로세스 인 모든 프로세스에 보냅니다.

이 문제에는 두 가지 방법이 있습니다.

  1. 쉘에서 백그라운드 프로그램을 분리하십시오.
    1. disown프로세스를 백그라운드로 지정한 후 명령을 사용하십시오 . 이것은 쉘이 잊어 버릴 것입니다.
    2. nohup( nohup $python program.py &)로 명령을 접두사로 사용하십시오 . 이것은 동일한 작업을 수행하지만 중간 프로세스를 사용합니다. 기본적으로 SIGHUP 신호를 무시한 다음 설정을 상속 한 프로그램을 포크 및 실행 한 다음 종료합니다. 포크되어 있기 때문에 시작되는 프로그램은 쉘의 자식이 아니며 쉘은 그것에 대해 알지 못합니다. SIGHUP에 대한 신호 처리기를 설치하지 않으면 무시 동작을 유지합니다.
  2. logout터미널 창을 닫는 대신 사용하십시오 . 를 사용 logout하면 SIGHUP이 아니므로 쉘은 SIGHUP을 자식에게 보내지 않습니다.

또한 터미널이 종료되면 더 이상 존재하지 않으므로 STDOUT 또는 STDERR을 통해 프로그램이 터미널에 쓰지 않아야합니다. 와 같은 것으로 리디렉션하지 않으면 /dev/null프로그램이 계속 실행되지만 프로그램에 쓰려고하면 SIGPIPE가 표시되고 SIGPIPE의 기본 동작은 프로세스를 종료하는 것입니다).


4
기술적으로 ssh죽으면 연결이 끊어지고 연결이 끊어 sshd지면 다른 쪽 끝이 죽습니다. 의 마스터 측 제어 즉 sshd를 의사 단말이 원격 쉘 실행이 죽으면 그건 행글라이더 가입 있도록 (이것은 실제 단말기의 전원을 분리처럼) 시스템은 원격 셸에 SIGHUP 보낸다.
Stéphane Chazelas

@ StéphaneChazelas 그것은 내가 결코 파지 한 가지입니다. 커널이이를 수행하는 경우 SIGHUP에 어떤 프로세스를 결정합니까? 프로그램이 사용하려고 시도하지 않는 한 프로그램이 계속 실행되므로 열려있는 파일 디스크립터가있는 모든 것을 그 TTY에 SIGHUP하지는 않습니다. 그렇다면 현재 STDIN에서 읽는 프로그램을 선택합니까 (한 번에 하나의 STDIN에서만 읽을 수 있기 때문에)?
Patrick

4
상관 없어 내 질문에 대답 했어 POSIX IEEE 1003.1 chap 11, 만약 제어 터미널에 대한 터미널 인터페이스에 의해 모뎀 분리가 감지되면 SIGHUP 신호는 제어 프로세스로 보내 져야한다 .
Patrick

2
또한 시작하는 프로그램의 출력으로 파일 을 nohup생성 nohup.out하십시오. nohup을 사용하여이 방법으로 앱을 시작할 때마다 (또는 출력을로 리디렉션해야 할 때마다) 해당 파일을 삭제하는 것이 귀찮을 수 있습니다 /dev/null.
Ruslan

1
대신 프로그램을 즉시 제거 nohup python program.py &하는 setsid python program.py대신 대신 사용 하는 것이 좋습니다 .
Hitechcomputergeek

14

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

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

귀하의 경우 이것은 다음과 같습니다.

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

3

&운영자 분리형 명령대로, 병렬로 실행하는 ;분리형 명령 직렬로 실행합니다. 두 종류의 명령은 여전히 셸 프로세스의 자식으로 실행됩니다 .

따라서 그 아이들을 시작한 껍질을 닫으면 아이들도 닫힙니다.

원하는 것으로 보이는 데몬 프로세스 는 부모 프로세스와 완전히 분리해야하기 때문에 훨씬 까다 롭습니다. 쉘에는 보통 간단한 방법이 없습니다.


1

로그 아웃하면 로그인 세션과 관련된 백그라운드 프로세스도 정상적으로 종료됩니다. 세션에서 연결을 끊으려면을 사용하여 실행하십시오 nohup.

nohup python program.py &

1

앰퍼샌드 ( &)로 끝나는 명령 후에 명령 프롬프트에서 다음 명령을 실행하십시오 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.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.