"ssh -t"로 로그인하고 명령을 실행할 수 없는 이유는 무엇입니까?

"ssh -t"로 로그인하고 명령을 실행할 수 없는 이유는 무엇입니까?

저는 Mac OS Big Sur에서 가상 Ubuntu 16.04 Linux 인스턴스(vagrant 사용)를 실행하고 있습니다. 다음 두 명령을 제대로 실행할 수 있습니다(하나는 가상 서버에 ssh로 접속하고 두 번째는 그 안에서 명령을 실행합니다)...

$ ssh myvirtual.local
Warning: Permanently added '10.0.4.19' (ECDSA) to the list of known hosts.
Last login: Wed Sep 15 16:37:57 2021 from 10.0.4.1
$ foreman start -f Procfile.debug
16:38:26 rails.1      | started with pid 27884
16:38:26 worker.1     | started with pid 27885
16:38:26 scheduler.1  | started with pid 27887
...

나는 이 두 명령을 결합할 수 있기를 원했기 때문에 시도해 보았습니다.

$ ssh -t myvirtual.local 'foreman start -f Procfile.debug’
Warning: Permanently added '10.0.4.19' (ECDSA) to the list of known hosts.
bash: foreman: command not found
Connection to 10.0.4.19 closed.

단일 명령을 사용하여 원래 수행한 작업을 시뮬레이션하기 위해 실행해야 하는 다른 설정이 무엇인지 혼란스럽습니다. 어떤 아이디어가 있나요?

답변1

이 경우의 주요 차이점은 ssh host로그인 모드에서 로그인 쉘을 시작한다는 것입니다. 접두어는 , sshd, 또는 (아마도 쉘의 시스템 시작 스크립트에서 시스템 시작 스크립트를 읽어 로그인 세션을 초기화해야 함을 쉘에 알려줍니다. 구현) 및 대화형(입력 프롬프트를 표시하기 때문). 이것이 패턴이다.-argv[0].profile.bash_profile.zprofile.zlogin.login/etcrloginssh

에서는 ssh -t host 'some shell code'및 인수를 사용하여 로그인 쉘을 실행 sshd하지만 로그인 쉘이라고 지시하지 마십시오. 쉘은 또한 비대화형이며 터미널에서 코드를 묻는 메시지를 표시하지 않습니다. 이것이 패턴이다.-csome shell codersh

귀하의 경우 변수를 설정하기 위한 세션 초기화 파일의 일부 지침이 $PATH아직 실행되지 않았기 때문에 명령을 찾을 수 없을 가능성이 높습니다.

모든 쉘이 동시에 로그인 쉘로 작동하고 인수로 제공된 코드를 해석할 수 있는 것은 아닙니다.

케이스는 bash괜찮습니다. 시작 시 로그인 셸로 시작 되며 bash또는 옵션이 전달되면 실행 명령이 전달되더라도 1은 여전히 ​​로그인 세션 초기화 파일을 읽습니다(POSIX 모드 제외).argv[0]--l--login-c

따라서 이렇게 하는 대신 다음과 같이 하세요.

ssh -t host 'some code'

다음을 수행할 수 있습니다.

ssh -t host "exec bash --login -c 'some code'"

이것은 또 다른 것을 시작 bash하지만 이번에는 해석하기 전에 로그인 셸로 사용됩니다(그 안의 코드 ~/.bash_profile와 초기화가 있는 곳을 해석할 것입니다 /etc/profile)./etc/profile.d$PATHsome code

또는 정의가 작성된 파일을 찾아 $PATH다음을 수행할 수 있습니다.

ssh -t host '. /path/to/that/file && some code'

이것은 여전히 ​​또 다른 차이점을 남깁니다. 즉, 쉘은 대화형이 아니며 시작 파일은 대화형일 때와 비대화형일 때 다르게 동작하도록 결정할 수 있습니다( i존재 여부를 확인하거나 $-변수가 존재하는지 확인하여 $PS1).

bash로그인 셸로 실행하면 ~/.bashrc(대부분의 다른 셸에서 발생하는 것과는 반대로) 시작 시 (대화형 셸 사용자 정의 파일)이 해석되지 않지만 대부분의 사람들은 데비안 및 그 파생 제품 source ~/.bashrc에서 이를 사용합니다. ~/.bash_profile버전은 ~/.profile기본적으로 이 작업을 수행합니다(물론 쉘이 인 경우에만 bash).

bash이는 ssh를 통해 호출될 때 기본적으로 해석되지 않지만 ~/.bashrc구성 옵션을 사용하여 컴파일 타임에 구성할 수 있습니다 SSH_SOURCE_BASHRC. Debian 및 Ubuntu와 같은 파생 제품이 이를 가능하게 합니다. 따라서 이렇게 할 때 ssh ubuntu-host 'some code'로그인 쉘이 해당 시스템에서 bash이면 실행될 쉘이 bash해석되기 전에 sshd해석 됩니다.~/.bashrcsome code

따라서 궁극적으로 모드 안팎 으로 ~/.bashrc해석되지만 @Quasimodo가 지적했듯이 Debian 및 Ubuntu의 기본값은 맨 위에 있습니다.rloginrsh~/.bashrc

# If not running interactively, don't do anything
case $- in
    *i*) ;;
      *) return;;
esac

$PATH따라서 이 줄 아래에 정의가 있는 경우 rlogin모드( bash대화형, $-포함 i~/.bashrc소스가 있는 경우)에서만 해석되며 모드( 소스는 있지만 해당 내용의 대부분을 건너뛰는 경우) ~/.profile에서는 해석되지 않습니다 . 쉘은 대화형이 아닙니다.)rsh~/.bashrc


1 (/와 반대로)로 시작하는 경우 argv[0]a 전달이 로그인 셸로 처리되는지 여부는 컴파일 활성화 여부에 따라 달라집니다.--l--login-c codebashNON_INTERACTIVE_LOGIN_SHELLS

답변2

두 가지 경우가 항상 동일하지는 않기 때문에 환경 설정이 누락되었습니다.

ssh remoteHost
someCommand

ssh -t remoteHost someCommand

다음 명령 블록은 선호하는 솔루션에서 누락된 변수 세트를 제공합니다(위 두 예의 두 번째 형식). 질문에 이러한 내용을 추가하면 설정 방법을 설명하는 질문을 완성해 드리거나, 이 정보를 사용하여 직접 설정할 수도 있습니다.

ssh -t myvirtual.local env | grep = | sort >/tmp/env.1
( echo env; echo exit ) | ssh -tt myvirtual.local | grep = | sort >/tmp/env.2
comm -13 /tmp/env.1 /tmp/env.2

내 시스템의 간단한 출력 예는 여기에 있습니다.

EDITOR=vi
HISTCONTROL=ignoredups
LESSCLOSE=/usr/bin/lesspipe %s %s
LESSOPEN=| /usr/bin/lesspipe %s
LS_COLORS=rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:...
PAGER=less
PATH=/home/roaima/bin:/usr/local/bin:/usr/local/sbin:/usr/sbin:/sbin:/usr/bin:/bin
PROMPT_COMMAND_WAS=echo -ne "\033]0;${USER}@${HOSTNAME}: ${PWD}\007"
SHLVL=1
SSH_CLIENT=192.1.1.9 31996 22
SSH_CONNECTION=192.1.1.9 31996 192.1.1.18 22
TTY=/dev/pts/0
XDG_SESSION_ID=c61

이는 Ruby 또는 Rails에만 해당되는 내용은 아니지만 제 경우에는 변수가 다르다는 것을 보여줍니다 ( 및 에서 실제 값을 볼 PATH수 있습니다 )./tmp/env.1/tmp/env.2

이를 추적하고 정렬한 후에는 연결이 종료될 때 신호를 받지 않도록 또는 foreman아래에서 실행 하는 것이 좋습니다 . 하지만 이러한 추가 도구를 도입하기 전에 초기 문제를 해결하는 것이 좋습니다.screentmuxSIGHUPssh

관련 정보