SSH 세션이 종료되면 왜 Python 백그라운드 프로세스가 종료됩니까?


19

startup.sh키 라인을 사용하여 python3 스크립트를 시작하는 bash 스크립트가 있습니다 ( ).

nohup python3 -u <script> &

나는시 ssh에서 직접이 스크립트를 호출, 파이썬 스크립트는 I 종료 후 백그라운드에서 계속 실행됩니다. 그러나 이것을 실행할 때 :

ssh -i <keyfile> -o StrictHostKeyChecking=no <user>@<hostname> "./startup.sh"

프로세스는 즉시 종료됩니다 ssh 실행을 마치면 종료되고 세션을 닫습니다.

둘의 차이점은 무엇입니까?

편집 : 파이썬 스크립트가 Bottle을 통해 웹 서비스를 실행 중입니다.

EDIT2 : 또한 호출 하고 실행 하는 init 스크립트만들 려고했지만 동일한 동작을 얻었습니다.startup.shssh -i <keyfile> -o StrictHostKeyChecking=no <user>@<hostname> "sudo service start <servicename>"

EDIT3 : 스크립트의 다른 부분 일 수 있습니다. 스크립트는 다음과 같습니다.

chmod 700 ${key_loc}

echo "INFO: Syncing files."
rsync -azP -e "ssh -i ${key_loc} -o StrictHostKeyChecking=no" ${source_client_loc} ${remote_user}@${remote_hostname}:${destination_client_loc}

echo "INFO: Running startup script."
ssh -i ${key_loc} -o StrictHostKeyChecking=no ${remote_user}@${remote_hostname} "cd ${destination_client_loc}; chmod u+x ${ctl_script}; ./${ctl_script} restart"

EDIT4 : 마지막 줄에서 마지막 줄을 실행할 때 :

ssh -i ${key_loc} -o StrictHostKeyChecking=no ${remote_user}@${remote_hostname} "cd ${destination_client_loc}; chmod u+x ${ctl_script}; ./${ctl_script} restart; sleep 1"

echo "Finished"

그것은 결코 도달하지 못하며 echo "Finished", 나는 전에 보지 못한 Bottle 서버 메시지를 봅니다.

Bottle vx.x.x server starting up (using WSGIRefServer())...
Listening on <URL>
Hit Ctrl-C to quit.

수동으로 SSH를 입력하고 프로세스를 종료하면 "완료"가 표시됩니다.

EDIT5 : EDIT4를 사용하여 끝점에 요청하면 페이지가 다시 표시되지만 병 오류가 발생합니다.

Bottle vx.x.x server starting up (using WSGIRefServer())...
Listening on <URL>
Hit Ctrl-C to quit.


----------------------------------------
Exception happened during processing of request from ('<IP>', 55104)

파이썬 스크립트의 기능에 대한 설명을 더 많이 얻을 수있는 방법이 있습니까? 전체 소스 코드 없이도 추측을 할 수 있지만, 파이썬 스크립트가 무엇을하는지 더 잘 알면 교육을 잘받는 추측을하는 데 도움이 될 수 있습니다.
Bratchley

네-질문에 추가되었습니다.
neverendingqs

스크립트는 연결된 터미널이나 그와 비슷한 것에 의존한다는 점에서 초기에 무언가를하고있을 수 있으며 타이밍 문제 일 수 있습니다. 세션이 처음 몇 초 동안 지속되면 작동하지 않습니다. 가장 좋은 방법은 straceLinux를 사용 truss중이 거나 Solaris를 실행 중이고 종료 방법 / 이유를 확인하는 것입니다. 예를 들어 ssh -i <keyfile> -o StrictHostKeyChecking=no <user>@<hostname> strace -fo /tmp/debug ./startup.sh.
Celada

&시작 스크립트 끝에서 를 사용해 보셨습니까 ? 를 추가하면 &ssh 세션의 종속성이 부모 ID가되지 않습니다 (부모 ID가 죽을 때 자식이됩니다). 또한 이것은 이전 게시물을 기반으로 한 중복 질문이라고 생각합니다 . 이전 문장에서 귀하에게 제출 한 게시물은 더 자세하게 설명 할 수있는 게시물과 중복 됩니다.
Jacob Bryan

나는 nohup ./startup.sh &전에 시도했지만 같은 행동을했다. startup.sh에 이미 포크 ( nohup python3 -u <script> &) 가 포함되어 있으므로 다시 포크 할 필요가 없습니다.
neverendingqs

답변:


11

표준 입력 / 출력 및 오류 흐름에서 명령을 분리합니다.

nohup python3 -u <script> </dev/null >/dev/null 2>&1 &  

ssh더 이상 출력이없고 더 이상 입력이 필요하지 않은 표시기가 필요합니다. 다른 것을 입력하고 출력 수단을 리디렉션ssh 입력 / 출력이 터미널에서오고 나가지 않으므로 안전하게 종료 할 수 있습니다. 이것은 입력이 다른 곳에서 와야하고 출력 (STDOUT과 STDERR)이 다른 곳으로 가야 함을 의미합니다.

</dev/null부분 지정 /dev/null입력으로 <script>. 왜 이것이 유용한 지 :

/ dev / null을 stdin으로 리디렉션하면 해당 프로세스의 모든 읽기 호출에 즉시 EOF가 제공됩니다. 일반적으로 tty에서 프로세스를 분리하는 데 유용합니다 (이러한 프로세스를 데몬이라고 함). 예를 들어, ssh를 통해 원격으로 백그라운드 프로세스를 시작할 때 프로세스가 로컬 입력을 기다리지 않도록 stdin을 경로 재지 정해야합니다. /programming/19955260/what-is-dev-null-in-bash/19955475#19955475

또는 다른 입력 소스로부터의 리디렉션은 전류가 지속되는 한 비교적 안전해야합니다 ssh 세션을 열어 둘 필요가없는 해야합니다.

>/dev/null부분에서 쉘은 표준 출력을 / dev / null로 리디렉션하여 본질적으로 버립니다.>/path/to/file작동합니다.

마지막 부분 2>&1은 STDERR을 STDOUT으로 리디렉션합니다.

프로그램에 대한 세 가지 표준 입력 및 출력 소스가 있습니다. 표준 입력은 일반적으로 대화식 프로그램 인 경우 키보드 또는 다른 프로그램의 출력을 처리하는 경우 다른 프로그램에서 제공됩니다. 프로그램은 일반적으로 표준 출력으로 인쇄하고 때로는 표준 오류로 인쇄합니다. 이 세 개의 파일 디스크립터 ( "데이터 파이프"라고 생각할 수 있음)를 종종 STDIN, STDOUT 및 STDERR이라고합니다.

때로는 이름이 지정되지 않고 번호가 매겨집니다! 내장 번호는 0, 1, 2 순입니다. 기본적으로 이름을 지정하거나 번호를 지정하지 않으면 STDOUT에 대한 것입니다.

그러한 맥락에서 위의 명령이 표준 출력을 / dev / null로 리디렉션하는 것을 알 수 있습니다. 이는 원하지 않는 것을 버릴 수있는 곳 (비트 버킷이라고도 함)으로 표준 오류를 표준 출력으로 리디렉션하는 것입니다 ( 이 작업을 수행 할 때 대상 앞에 &를 넣어야합니다).

그러므로 간단한 설명은“이 명령의 모든 출력은 블랙홀로 입력되어야합니다.”이것이 프로그램을 정말 조용하게 만드는 좋은 방법입니다!
> / dev / null 2> & 1은 무슨 뜻입니까? | Xaprb


nohup python3 -u <script> >/dev/null 2>&1 &그리고 nohup python3 -u <script> > nohup.out 2>&1 &했다. nohup이 자동으로 모든 출력을 리디렉션한다고 생각했습니다. 차이점은 무엇입니까?
neverendingqs

@neverendingqs, nohup원격 호스트에 어떤 버전이 있습니까? 는 POSIX는 nohup리디렉션 할 필요가 없습니다 stdin내가 놓친하는,하지만 여전히 리디렉션해야 stdout하고 stderr.
Graeme

작업하고있는 것 같습니다 nohup (GNU coreutils) 8.21.
neverendingqs

@neverendingqs nohup와 같은 메시지를 인쇄 nohup: ignoring input and appending output to ‘nohup.out’합니까?
Graeme

그렇습니다-정확한 메시지입니다.
neverendingqs

3

man ssh:

 ssh [-1246AaCfgKkMNnqsTtVvXxYy] [-b bind_address] [-c cipher_spec] [-D [bind_address:]port]
     [-e escape_char] [-F configfile] [-I pkcs11] [-i identity_file] [-L [bind_address:]port:host:hostport]
     [-l login_name] [-m mac_spec] [-O ctl_cmd] [-o option] [-p port]
     [-R [bind_address:]port:host:hostport] [-S ctl_path] [-W host:port] [-w local_tun[:remote_tun]]
     [user@]hostname [command]

달릴 때 ssh -i <keyfile> -o StrictHostKeyChecking=no <user>@<hostname> "./startup.sh" 쉘 스크립트 startup.sh를 ssh 명령으로 실행합니다.

설명에서 :

명령이 지정되면 로그인 쉘 대신 원격 호스트에서 실행됩니다.

이를 기반으로 스크립트를 원격으로 실행해야합니다.

그것과 달리기의 차이점 nohup python3 -u <script> & 로컬 터미널에서 실행하는 것의 이것이 로컬 백그라운드 프로세스로 실행되고 ssh 명령이 원격 백그라운드 프로세스로 실행하려고 시도한다는 것입니다.

스크립트를 로컬로 실행하려면 ssh 명령의 일부로 startup.sh를 실행하지 마십시오. 당신은 같은 것을 시도 할 수 있습니다ssh -i <keyfile> -o StrictHostKeyChecking=no <user>@<hostname> && "./startup.sh"

스크립트를 원격으로 실행하려는 경우 ssh 세션이 종료 된 후이 프로세스를 계속하려면 먼저 screen원격 호스트 에서 세션을 시작해야 합니다. 그런 다음 화면 내에서 python 스크립트를 실행해야하며 ssh 세션을 종료 한 후에도 계속 실행됩니다.

스크린 사용자 매뉴얼 참조

화면이 최선의 선택이라고 생각하지만 nohup을 사용해야 shopt -s huponexit하는 경우 nohup 명령을 실행하기 전에 원격 호스트에서 설정 을 고려 하십시오. 또는 disown -h [jobID]SIGHUP이 전송되지 않도록 프로세스를 표시하는 데 사용할 수 있습니다 . 1

백그라운드에서 쉘 프롬프트를 종료 한 후에 어떻게 작업을 계속 실행합니까?

SIGHUP (Hangup) 신호는 시스템에서 터미널을 제어하거나 제어 프로세스를 종료 할 때 사용됩니다. SIGHUP을 사용하여 구성 파일을 다시로드하고 로그 파일을 열고 닫을 수도 있습니다. 즉, 터미널에서 로그 아웃하면 실행중인 모든 작업이 종료됩니다. 이를 피하기 위해 -h 옵션을 전달하여 명령을 해제 할 수 있습니다. 이 옵션은 쉘이 SIGHUP을 수신 할 때 SIGHUP이 작업으로 전송되지 않도록 각 jobID를 표시합니다.

또한 huponexit쉘 종료, 종료 또는 삭제시 작동 방식에 대한이 요약을 참조하십시오 . 현재 문제가 셸 세션이 끝나는 방법과 관련이 있다고 생각합니다. 2

  1. huponexit 옵션이 설정된 경우에만 ssh 연결이 닫히면 ssh 연결을 통해 열린 쉘의 배경에 관계없이 모든 하위 프로세스가 SIGHUP으로 종료됩니다. 이것이 사실인지 확인하려면 shopt huponexit를 실행하십시오.

  2. huponexit가 true이면 nohup 또는 disown을 사용하여 프로세스를 쉘에서 분리하여 종료시 종료되지 않도록 할 수 있습니다. 또는 화면으로 물건을 실행하십시오.

  3. 요즘 적어도 일부 리눅스에서는 기본값 인 huponexit가 false이면 정상적인 로그 아웃시 백그라운드 작업이 종료되지 않습니다.

  4. 그러나 huponexit가 false 인 경우에도 ssh 연결이 끊어 지거나 끊어지면 (정상 로그 아웃과 다름) 백그라운드 프로세스가 여전히 종료됩니다. 이것은 (2)에서와 같이 disown 또는 nohup으로 피할 수 있습니다.

마지막으로 shopt huponexit를 사용하는 방법에 대한 몇 가지 예가 있습니다.

$ shopt -s huponexit; shopt | grep huponexit
huponexit       on
# Background jobs will be terminated with SIGHUP when shell exits

$ shopt -u huponexit; shopt | grep huponexit
huponexit       off
# Background jobs will NOT be terminated with SIGHUP when shell exits

bash매뉴얼 페이지 에 따르면 huponexit스크립트가 아닌 대화식 쉘에만 영향을 미칩니다- 'huponexit 쉘 옵션이 shopt로 설정된 경우 bash는 대화식 로그인 쉘이 종료 될 때 모든 작업에 SIGHUP을 보냅니다.'
Graeme

2

어쩌면 -n시작할 때 옵션을 시도해 볼 가치가 ssh있습니까? 로컬에 대한 원격 프로세스 종속성을 막을 것이며 stdin물론 종료되는 즉시 닫힙니다 ssh session. 그리고 이것은 그것의 접근을 시도 할 때마다 원격 가격 종료를 야기 할 것이다 stdin.


성공없이 그것을 시도 ==.
neverendingqs

2

경쟁 조건이 의심됩니다. 다음과 같이 갈 것입니다.

  • SSH 연결 시작
  • SSH는 startup.sh를 시작합니다
  • startup.sh는 백그라운드 프로세스를 시작합니다 (nohup).
  • startup.sh 완료
  • ssh가 완료되면 자식 프로세스가 종료됩니다 (예 : nohup).

ssh가 문제를 줄이지 않으면 다음이 발생했을 것입니다 (이 두 가지 순서는 확실하지 않음).

  • nohup은 파이썬 스크립트를 시작합니다
  • nohup은 상위 프로세스 및 터미널에서 연결을 끊습니다.

nohup이 할 일이 있기 전에 startup.sh와 ssh가 완료되기 때문에 마지막 두 가지 중요한 단계는 발생하지 않습니다.

startup.sh가 끝나고 몇 초 동안 잠을 자면 문제가 사라질 것으로 예상됩니다. 시간이 얼마나 필요한지 잘 모르겠습니다. 그것을 최소한으로 유지하는 것이 중요하다면, proc에서 무언가가 안전한지 볼 수 있습니다.


좋은 지적은, 이것에 대한 창이 매우 길다고 생각하지 마십시오. 아마도 몇 밀리 초일 것입니다. 당신은 확인할 수 있습니다 /proc/$!/comm되지 않았습니다 nohup의 출력을 사용하거나 더 이식 ps -o comm= $!.
Graeme

정상적인 로그 아웃에서는 작동하지만 세션이 삭제되거나 종료되면 어떻게됩니까? sighup에서 작업을 완전히 무시하기 위해 작업을 계속 해제하지 않아도됩니까?
iyrin December

@RyanLoremIpsum : 시작 스크립트는 자식 프로세스가 완전히 분리 될 때까지만 기다려야합니다. 그 후에는 ssh 세션에 어떤 일이 발생하는지는 중요하지 않습니다. 짧은 기간 동안 ssh 세션이 종료되면 다른 작업을 수행 할 수 없습니다.
mc0e

@Graeme 그래, 나는 그것이 매우 빠르다고 생각하지만, nohup이 확실하게 무엇을하는지 정확히 알지 못한다. 이것에 대한 권위있는 (또는 최소한 지식이 풍부하고 자세한) 소스에 대한 포인터가 유용 할 것입니다.
mc0e 2014

어떻게 이런 일에 대해 - lingrok.org/xref/coreutils/src/nohup.c
그레엄

1

이것은 python스크립트 나 python그 자체가하는 일에 문제 가있는 것 같습니다. nohup실제로하는 모든 것 (바 단순화 리디렉션)은 프로그램을 실행하기 전에 HUP신호 처리기 를 SIG_IGN(무시)로 설정하면됩니다. 프로그램 SIG_DFL이 실행을 시작한 후에 다시 설정 하거나 자체 핸들러를 설치하는 것을 중지 할 것은 없습니다 .

시도 할 수있는 한 가지는 더블 포크 효과를 얻고 python스크립트가 더 이상 쉘 프로세스의 자식이 아닌 명령을 괄호로 묶는 것 입니다. 예 :

( nohup python3 -u <script> & )

시도해 볼만한 가치가있는 또 다른 것은 ( bash다른 쉘이 아닌 다른 것을 사용하는 경우) disown대신 내장 을 사용하는 것입니다 nohup. 모든 것이 문서화 된대로 작동한다면 실제로 차이가 없어야하지만 대화식 쉘에서는 HUP신호가 python스크립트로 전파되는 것을 막을 것 입니다. 다음 줄 또는 아래와 같은 줄에 disown을 추가 할 수 있습니다 (에 a ;를 추가 &하면 오류가 발생합니다 bash).

python3 -u <script> </dev/null &>/dev/null & disown

위 또는 일부 조합이 작동하지 않으면 문제를 해결할 수있는 유일한 곳은 python스크립트 자체입니다.


이중 포크 효과가 충분합니까 (@RyanLoremIpsum의 답변을 기반으로)?
neverendingqs

둘 다 = [. 문제를 해결하지 못했습니다. 파이썬 문제라면 조사를 시작할 위치에 대한 아이디어가 있습니까? (파이썬 스크립트를 너무 많이 게시 할 수는 없습니다)?
neverendingqs

@neverendingqs, 하위 huponexit쉘에서 실행 disown하면 프로세스가 작업 목록에 추가되지 않는 것과 동일한 효과 가 있습니다.
Graeme

@neverendingqs, 내 대답을 업데이트했습니다. 로 리디렉션을 사용해야한다는 것을 잊었습니다 disown. 그래도 큰 차이가있을 것으로 기대하지 마십시오. 가장 좋은 방법은 python스크립트가 왜 종료되는지 알려주도록 스크립트 를 변경하는 것입니다.
Graeme

출력 리디렉션이 효과가 있었지만 ( unix.stackexchange.com/a/176610/52894 ) 명시 적으로 수행하는 것과 수행하는 것의 차이점은 확실 nohup하지 않습니다.
neverendingqs

0

작업이 세션과 관련되어 있기 때문이라고 생각합니다. 종료되면 모든 사용자 작업도 종료됩니다.


2
그러나 왜 터미널을 얻고, 명령을 입력하고 실행하고, 종료하는 것과 다른가? 닫으면 두 세션이 모두 닫힙니다.
neverendingqs

동의, 이것이 왜 자신의 터미널을 수동으로 닫는 것과 다르지 않은지 이해하고 싶습니다.
Avindra Goolcharan

0

nohup출력 파일을 열 수 있다면 에 실마리가있을 수 있습니다 nohup.out. 그것은 가능하다 python당신을 통해 스크립트를 실행할 때 경로에 있지 않습니다 ssh.

명령에 대한 로그 파일을 작성하려고합니다. 다음을 사용하십시오.

nohup /usr/bin/python3 -u <script> &>logfile &

ssh스크립트를 수동으로 실행하는 데 사용 하므로 python3이 경로에 있다고 가정합니다.
neverendingqs

@neverendingqs 로그 파일에 아무것도 포함되어 있습니까?
BillThor

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