ssh 명령이 세션을 종료합니다

ssh 명령이 세션을 종료합니다

나는 이것을 가지고있다:

ssh -i "alex-kp.pem" '[email protected]' '

  cd codes/vbe
  eval $(ssh-agent)
  ssh-add -D
  ssh-add ~/.ssh/id_vbe
'

명령을 실행한 다음 세션을 종료하므로 로컬 컴퓨터로 돌아갑니다. 이유를 아는 사람 있나요?

답변1

원격 시스템에서 실행할 명령(즉, 일련의 명령)을 제공했습니다. 명령(이러한 명령)이 완료되면 세션이 종료됩니다. 이는 정의되었으며 예상되는 동작이어야 합니다 man ssh. 다음을 참조하세요.

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

hostname원격 시스템에서 실행되는 더 간단한 예

ssh -i alex-kp.pem [email protected] hostname

답변2

원격 측에서는 무슨 일이 일어나는가

Local은 ssh user@server 'shell_code'SSH 서버를 다음과 같이 실행합니다.

"$SHELL" -c 'shell_code'

나는 그렇다고 말하는 것이 아니다정확히이와 같지만 무슨 일이 일어나고 있는지 이해하기에 충분할 만큼 가깝습니다. 마치 쉘에서 호출하는 것처럼 작성했기 때문에 친숙해 보이지만 실제로는 아직 쉘이 없습니다.

이 방법으로 호출된 셸에 도달했습니다 shell_code. 귀하의 경우 코드는 여러 줄이며 아무 것도 변경되지 않습니다.

plain 과 같은 셸 코드가 없으면 ssh user@serverSSH 서버는 다른 것을 시작합니다.

"$SHELL" -i

다시 한번 말씀드리지만 그렇지 않다고 말씀드리고 싶습니다정확히이와 같이.

이 방법으로 호출된 쉘은 다음과 같습니다.인터렉티브쉘은 프롬프트를 인쇄하고 입력을 기다립니다. 이것이 당신이 달성하고 싶은 행동인 것 같습니다.

SSH 서버는 로컬 통화 형식에 따라 의도적으로 한 가지 형식을 사용합니다 ssh. 후자 형식은 대화형 사용에 매우 적합하며 전자 형식은 일부 비대화형 쉘 코드를 로컬처럼 원격으로 실행할 수도 있습니다. 예를 들어 로컬에서 다음을 수행할 수 있습니다.

<data md5sum

하지만 로컬에서 누락된 경우 md5sum원격을 사용할 수 있습니다.

<data ssh user@server md5sum

md5sum작업을 완료한 후 로컬 종료와 마찬가지로 ssh … md5sum원격도 md5sum작업을 완료한 후 종료됩니다. 굉장히 유용하다.

또는 원격 파일로 파이프할 수 있습니다.

<data ssh user@server 'cat >copy'

또한 cat원격 쉘과 로컬 쉘은 ssh적절한 경우 자동으로 종료됩니다.

또는 서버에 시간을 요청할 수 있습니다.

ssh user@server date

이는 local 처럼 동작하며 date대화형 원격 셸에 들어가지 않습니다.


대화형 셸이 자동으로 종료되는 경우

나는 [ ssh … date]이 기본적으로 종료되지 않을 것으로 예상했습니다. 터미널에 명령을 입력하면 기본적으로 종료되나요?

물론. 명령을 읽는 동안 EOF에 도달하면 대화형 쉘이 종료됩니다. 문제는 Ctrl+ ()를 누를 d때까지 터미널에서 EOF를 "경험"하지 않는다는 것 입니다.한번 아니면 두번). 이것이 터미널에서 작동하는 방식입니다. 그러나 대화형 쉘이 일반 파일이나 파이프에서 읽도록 하면 예상한 순간에 정확히 EOF가 표시됩니다.

{ echo date; echo sleep 5; echo date; } | bash -i

그러면 종료됩니다.

따라서 실제로 할 일이 없을 때 모든 쉘은 기본적으로 종료됩니다. 터미널에서 데이터를 읽는 것은 대화형 셸이 "종료되지 않습니다"라고 합니다.의도적으로입력이 언제든지 나타날 수 있다는 가정하에 현재 입력이 없을 때 EOF를 트리거하지 않도록 설계되었습니다. 그것은 쉘이나 일반적인 프로그램이 아닌 터미널과 관련이 있습니다. 즉, 종료와 같은 것이지만 </etc/fstab cattty에서 일반적인 읽기는 무기한 작동합니다. 같은 이야기입니다.cat


원격 tty의 중요성

SSH 서버가 셸을 실행하는 두 가지 방법은 단순한 형식 이상의 차이가 있습니다. 원격 대화형 명령은 로컬 tty를 사용할 때 잘 작동합니다(따라서 로컬 ssh과 명령 사이의 서버측 tty입니다). 하지만 md5sum원격 비대화형 명령(예: 예)은 tty가 할당되지 않은 경우에도 잘 작동합니다. SSH 서버는 tty를 할당하거나 할당하지 않으며 자동으로 할당됩니다(그러나 원하는 경우 ssh옵션을 통해 명시적으로 선택할 수 있음 ). 나는 두 가지를 최대한 활용하려고 노력한 다음 질문(및 답변)에서 통찰력을 얻을 수 있다고 생각합니다.-t-tt-TSSH에는 별도의 stdin, stdout, stderr 및 tty가 있습니다..


당신은 무엇을 할 수 있나요

첫 번째 프롬프트를 표시하기 전에 일부 쉘 코드를 실행하는 원격 대화형 쉘을 원하는 것 같습니다. 가장 쉬운 방법은 코드를 올바른 시작 스크립트( ~/.bashrc쉘이 Bash인 경우) 에 넣고 ssh(쉘 코드를 전달하지 않고) 대화형 원격 쉘에 넣는 것입니다. 이는 영구적인 솔루션이므로 요청 시 일회성 코드를 실행하고 계속해서 메시지를 받으려는 경우에는 유용하지 않습니다.

요청 시 쉘 코드를 실행하려면 다음과 같은 것이 필요합니다.

ssh -t … '
  exec bash --rcfile <(cat <<"EOF"
    # your custom shell code here
    . ~/.bashrc
    # and/or here
EOF
) -i'

이는 SSH 서버에 의해 시작된 쉘이 이를 이해하고 <(…)(Bash가 이를 이해함) 최종 대화형 쉘로 원하는 쉘이 Bash라고 가정합니다.

SSH 서버는 여전히 tty(때문에)를 사용하는 비대화형 쉘을 실행합니다 -t. 쉘은 exec대신 사용자 정의 파일을 가져오는 대화형 Bash를 사용합니다 ~/.bashrc. 파일은 프로세스 교체의 파이프가 되며 해당 내용은 사용자 정의 쉘 코드와 소스 지침이 됩니다 ~/.bashrc. 이렇게 하면 최종 쉘이 사용자 정의 쉘 코드를 실행한 다음 프롬프트를 표시하게 됩니다.

SSH 서버에 의해 직접 생성된 대화형 셸은 로그인 셸이며 /etc/profile여기서는 두 셸 모두 로그인 셸이 아닙니다. 를 사용하여 최종 쉘을 실행할 수 있지만 -l이를 무시합니다 --rcfile.

그러나 귀하의특정한사용자 정의 쉘 코드는 생존할 수 있도록 설정합니다 exec(종종 상속될 수 있음). 이는 코드 조각을 다음과 같이 단순화할 수 있음을 의미합니다.

ssh -t … '
  cd codes/vbe
  eval $(ssh-agent)
  ssh-add -D
  ssh-add ~/.ssh/id_vbe
  exec bash -i
'

이 경우 -l원하는 경우 최종 Bash를 로그인 쉘로 추가하고 만들 수 있다고 생각합니다. 로그인 쉘과 비로그인 쉘은 서로 다른 파일을 갖게 된다는 점을 기억하십시오. 이러한 파일은 서로 생성될 수 있습니다(즉, ~/.bash_profile서로 생성될 수 있음 ~/.bashrc).비대화형 Bash도 소스를 제공할 수 있습니다.~/.bashrc; 그리고 두 개의 원격 쉘이 순서대로 있으며, 각각은 무언가를 얻을 수 있습니다. 리모콘은 ~/.bashrc아마도 두 번 구매하게 될 것입니다. 함유량에 따라 부작용이 발생할 수 있습니다.

ssh …매우 다른 대안은 로컬 스크립트에서 호출하는 것입니다(셸 코드가 필요하지 않음) expect. 이 스크립트는 필요한 셸 코드를 삽입하고 결국에는 interact일치를 통해 원격 프롬프트를 감지할 수 있다고 가정합니다 @*:*$.

expect -c '
 spawn ssh -i alex-kp.pem [email protected]
 expect "@*:*$ "
 send "cd codes/vbe\r"
 expect "@*:*$ "
 send "eval \$(ssh-agent)\r"
 expect "@*:*$ "
 send "ssh-add -D\r"
 expect "@*:*$ "
 send "ssh-add ~/.ssh/id_vbe\r"
 interact
'

AWS는 모르지만 일반적으로 연결을 끊은 후에도 살아남을 수도 있고 그렇지 않을 수도 있습니다 ssh-agent. eval $(ssh-agent)살아남으려면 ssh-agent -k원격 셸을 종료하기 전에 수동으로 clean()하는 것이 좋습니다.

관련 정보