
startup.sh
핵심 라인을 사용하여 python3 스크립트(라고 부르자)를 시작하는 bash 스크립트가 있습니다 .
nohup python3 -u <script> &
직접 들어가서 이 스크립트를 호출 하면 ssh
Python 스크립트는 종료 후에도 백그라운드에서 계속 실행됩니다. 그러나 이것을 실행하면 다음과 같습니다.
ssh -i <keyfile> -o StrictHostKeyChecking=no <user>@<hostname> "./startup.sh"
프로세스 ssh
실행이 완료되자마자 프로세스가 종료되고 세션이 닫힙니다.
둘 사이의 차이점은 무엇입니까?
편집: Python 스크립트는 Bottle을 통해 웹 서비스를 실행하고 있습니다.
EDIT2: 나도 시도해봤어초기화 스크립트 생성를 호출 startup.sh
하고 실행했지만 ssh -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 오류가 발생합니다.
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)
답변1
표준 입력/출력 및 오류 흐름에서 명령의 연결을 끊겠습니다.
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을 리디렉션해야 합니다. https://stackoverflow.com/questions/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입니다. 기본적으로 명시적으로 이름을 지정하거나 1위를 지정하지 않으면 STDOUT에 대해 이야기하는 것입니다.
해당 컨텍스트를 고려하면 위의 명령이 표준 출력을 /dev/null로 리디렉션하는 것을 볼 수 있습니다. 이 곳은 원하지 않는 모든 항목(종종 비트 버킷이라고 함)을 덤프할 수 있는 곳입니다. 그런 다음 표준 오류를 표준 출력으로 리디렉션합니다( 이 작업을 수행할 때 목적지 앞에 &를 넣어야 합니다.)
따라서 간단히 설명하면 "이 명령의 모든 출력은 블랙홀에 들어가야 합니다."입니다. 그것은 프로그램을 정말 조용하게 만드는 좋은 방법 중 하나입니다!
> /dev/null 2>&1은 무슨 뜻인가요? | Xaprb
답변2
보다 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"
쉘 스크립트 start.sh를 ssh 명령으로 실행하게 됩니다.
설명에서:
command를 지정하면 로그인 쉘 대신 원격 호스트에서 실행됩니다.
이를 기반으로 스크립트를 원격으로 실행해야 합니다.
로컬 터미널에서 실행하는 것과 차이점은 nohup python3 -u <script> &
ssh 명령이 원격 백그라운드 프로세스로 실행을 시도하는 동안 로컬 백그라운드 프로세스로 실행된다는 것입니다.
스크립트를 로컬에서 실행하려는 경우 ssh 명령의 일부로 시작.sh를 실행하지 마십시오. 다음과 같은 것을 시도해 볼 수도 있습니다.ssh -i <keyfile> -o StrictHostKeyChecking=no <user>@<hostname> && "./startup.sh"
screen
스크립트를 원격으로 실행하려는 경우 SSH 세션이 종료된 후에도 이 프로세스를 계속하려면 먼저 원격 호스트에서 세션을 시작해야 합니다 . 그런 다음 화면 내에서 Python 스크립트를 실행해야 하며 SSH 세션을 종료한 후에도 계속 실행됩니다.
내 생각에는 screen이 최선의 선택이라고 생각하지만, nohup을 사용해야 한다면 shopt -s huponexit
nohup 명령을 실행하기 전에 원격 호스트에 설정하는 것을 고려해 보세요. 또는 disown -h [jobID]
SIGHUP이 전송되지 않도록 프로세스를 표시하는 데 사용할 수 있습니다 .1
백그라운드에서 쉘 프롬프트를 종료한 후에도 작업을 계속 실행하려면 어떻게 해야 합니까?
SIGHUP(Hangup) 신호는 터미널 제어 또는 제어 프로세스 중단 시 시스템에서 사용됩니다. SIGHUP을 사용하여 구성 파일을 다시 로드하고 로그 파일을 열고 닫을 수도 있습니다. 즉, 터미널에서 로그아웃하면 실행 중인 모든 작업이 종료됩니다. 이를 방지하려면 disown 명령에 -h 옵션을 전달할 수 있습니다. 이 옵션은 쉘이 SIGHUP을 수신하는 경우 SIGHUP이 작업으로 전송되지 않도록 각 작업 ID를 표시합니다.
huponexit
또한 쉘이 종료되거나 종료되거나 삭제될 때 작동 방식에 대한 요약을 참조하세요 . 현재 문제는 쉘 세션이 끝나는 방식과 관련이 있는 것 같습니다.2
ssh 연결을 통해 열린 셸의 백그라운드 여부에 관계없이 모든 하위 프로세스는 huponexit 옵션이 설정된 경우에만 ssh 연결이 닫힐 때 SIGHUP으로 종료됩니다. 이것이 사실인지 확인하려면 shopt huponexit를 실행하세요.
huponexit가 true이면 nohup 또는 disown을 사용하여 프로세스를 셸에서 분리하여 종료할 때 프로세스가 종료되지 않도록 할 수 있습니다. 또는 화면으로 작업을 실행하세요.
요즘 일부 Linux에서는 기본값인 huponexit가 false인 경우 일반 로그아웃 시 백그라운드 작업이 종료되지 않습니다.
- 그러나 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
답변3
어쩌면 -n
시작할 때 옵션을 시도해 볼 가치가 있습니까 ssh
? 로컬에 대한 원격 프로세스 종속성을 방지합니다 stdin
. 물론 ssh session
종료되자마자 닫힙니다. 그리고 이로 인해 에 액세스하려고 할 때마다 원격 가격이 종료됩니다 stdin
.
답변4
python
이는 스크립트나 python
자체가 수행하는 작업에 대한 문제처럼 들립니다 . 실제로 수행되는 작업(리디렉션을 단순화하는 막대) 은 프로그램을 실행하기 전에 신호 nohup
에 대한 핸들러를 (무시)로 설정하는 것뿐입니다 . 프로그램이 실행되기 시작하면 프로그램을 다시 설정하거나 자체 처리기를 설치하는 것을 막을 수 없습니다 .HUP
SIG_IGN
SIG_DFL
시도해 볼 수 있는 한 가지 방법은 명령을 괄호로 묶어 이중 포크 효과를 얻고 스크립트가 python
더 이상 셸 프로세스의 하위 항목이 아니도록 하는 것입니다. 예:
( nohup python3 -u <script> & )
시도해 볼 만한 또 다른 방법은(다른 쉘을 사용하고 있지 않은 경우 ) 대신 내장된 bash
쉘을 사용하는 것입니다 . 모든 것이 문서화된 대로 작동한다면 실제로 아무런 차이가 없어야 하지만 대화형 셸에서는 신호가 스크립트로 전파되는 것을 중지합니다 . 다음 줄이나 아래와 동일한 줄에 disown을 추가할 수 있습니다( a 뒤에 a를 추가하는 것은 오류입니다 ).disown
nohup
HUP
python
;
&
bash
python3 -u <script> </dev/null &>/dev/null & disown
위 방법이나 그 조합이 작동하지 않는 경우 문제를 해결할 수 있는 유일한 곳은 스크립트 python
자체입니다.