현재 환경에서 FOO
변수가 정의(및 -ed)되었다고 가정합니다. export
이 환경을 환경이라고 부르겠습니다 E0
.
이제 ssh
.
% ssh [email protected]
새로 생성된 세션의 환경을 호출합니다 E1
.
일반적으로 말하면FOO
는 에서 정의되지 않으며 특별한 E1
경우에는일반적으로 말하면FOO
해당 값은 in 값과 독립적으로 설정됩니다 E0
.
ssh
via 에 로그인할 때 변수가 해당 값으로 FOO
설정 되도록 (이상적으로는 -ed로 설정되도록) 어떻게 정렬합니까 ?E1
E0
export
E1
중요한 경우에는 및 zsh
를 모두 사용하고 있습니다 .E0
E1
sshd
이 질문에 대한 답을 얻으려면 해당 프로세스에서 실행되는 프로세스의 구성을 내가 제어할 수 없다고 가정하십시오 for.example.com
. 특히 수정 등이 필요한 /etc/ssh/sshd_config
솔루션은 제외됩니다.for.example.com
또한 가정된 값 FOO
은 일정하지 않으며 로그인 세션마다 변경됩니다. 특히 FOO
전혀 설정하지 않을 수도 있는데 FOO
, 이 경우 의 효과가 또는 와 E1
비슷 하면 괜찮습니다 .FOO=
export FOO=
unset FOO
고쳐 쓰다:나는 이것을 시도했다
% ssh [email protected] FOO=$FOO env
...실제로 출력에는 FOO
지정된 대로 설정되어 있는 것으로 표시됩니다. 하지만 로그인 세션을 시작할 때 이 아이디어를 어떻게 적용해야 할지 모르겠습니다. 특히, 내가 실행하면
% ssh [email protected] FOO=$FOO
...명령은 연결을 설정하지 않고 반환됩니다. (나는 이것이 원격 호스트에서 실행되는 "명령"으로 ssh
해석된다고 가정합니다.) FOO=$FOO
반면에 이것을 실행한 후에는
% ssh [email protected] FOO=$FOO zsh
...원격 호스트에서 쉘 프롬프트가 표시되지 않습니다. 명령이 거기에서 중단됩니다. (그러나 이 전에 비밀번호 프롬프트를 받았습니다 ssh
.) 마지막 명령의 다른 변형에서도 동일한 일이 발생합니다.
% ssh [email protected] FOO=$FOO /path/to/zsh
% ssh [email protected] FOO=$FOO env zsh
% ssh [email protected] env FOO=$FOO zsh
% ssh [email protected] env FOO=$FOO zsh -l
% ssh [email protected] 'env FOO=$FOO zsh'
업데이트 2:사실, "매달려 있는" 것처럼 보이는 것은 보이지 않는 프롬프트임이 밝혀졌습니다. 여전히 명령을 실행할 수 있습니다. 또한 로그인 시 실행되는 zsh init 파일은 일반적인 순서와 다르며 (놀랍지도 않게) 환경은 다음과 같습니다.본질적으로(그리고 중요한 것은 IOW가 FOO
평소보다 훨씬 높다는 것입니다.)
업데이트 3:dave_alcarin과 meuh의 도움으로 나는 이것이 내가 추구했던 것과 매우 가깝다는 것을 알았습니다.
% ssh -t [email protected] env FOO=$FOO zsh -l -s
새로운 환경과 일반 환경 사이에는 아직 해결해야 할 몇 가지 중요한 차이점이 있지만 이는 제가 원하는 것과 꽤 가깝습니다.
답변1
SSH에는 클라이언트에서 서버로 환경 변수를 전달하는 기능이 있지만 OpenSSH는 기본 서버 구성에서 이 기능을 비활성화했습니다. 한 가지 예외가 있습니다. TERM
프로토콜에서 특별한 위치를 차지하지만 이를 통해 메시지를 전달하는 것은 TERM
클라이언트가 이를 디코딩할 수 있는지 확인해야 하기 때문에 어색합니다.
그러나 일부 서버는 특정 환경 변수의 통과를 허용하도록 구성되어 있습니다. 예를 들어 Debian은 모든 이름을 허용하도록 SSH 서버를 구성합니다 LC_
. 일반적으로 이는 로케일 변수이지만 원하는 변수를 넣을 수 있습니다.
서버가 변수를 허용하도록 구성되지 않은 경우 해당 변수를 명령의 일부로 전달할 수 있지만 몇 가지 문제가 있습니다. 문제는 명령을 에 전달하면 ssh
기본적으로 서버에 터미널이 생성되지 않는다는 것입니다. 실제로 쉘을 실행하지만 쉘이 터미널이 아닌 파이프로 연결되어 있어 프롬프트를 표시하지 않거나 명령줄 버전을 지원하지 않습니다. 그럼에도 불구하고 명령을 입력할 수 있습니다. 입력을 시도하거나 +종료하세요. 해결책은 옵션을 사용하여 터미널을 열도록 SSH에 명시적으로 지시하는 것입니다.ssh [email protected] FOO=$FOO zsh
ls
Enterexit
EnterCtrlD-t
ssh -t [email protected] FOO=$FOO zsh
로그인 셸에 따라 다음을 실행해야 할 수도 있습니다.
ssh -t [email protected] FOO=$FOO exec zsh
추가 셸 프로세스를 방지하기 위해 프로세스가 명시적으로 호출됩니다 zsh
.
아직 발생하지 않은 두 번째 문제는 참조입니다. SSH 프로토콜은 원격 셸에서 실행되는 문자열을 전송합니다. 여기서 전달하는 문자열은 , 공백 및 FOO=
의 값 으로 구성됩니다 . 따라서 값은 변수에 저장된 문자열 이 아닌 쉘 소스 코드의 일부로 해석됩니다 . 이는 값에 셸 구문에서 특별한 의미를 갖는 문자가 포함된 경우 영향을 미칩니다. 추가 참조 레벨을 추가해야 합니다. 로컬 쉘이 zsh라고 가정하면 매개변수 확장 플래그를 사용할 수 있습니다 .FOO
exec zsh
FOO
FOO
q
ssh -t [email protected] FOO=${(q)FOO} exec zsh
직접 사례와의 또 다른 차이점은 먼저 원격 측에서 로그인 셸을 실행한 다음 이를 비로그인 셸로 바꾸는 것입니다. 체인은 로그인 셸(필수적임)로 시작하므로 .profile
또는 .zprofile
실제로 실행되지만 zsh의 대화형 인스턴스는 도트 파일의 내용에 따라 달라질 수 있는 로그인 셸이 아닙니다. 가장 좋은 해결책은 아마도 도트 파일에서 깨지기 쉬운 작업을 피하는 것입니다. 을 실행할 수 있지만 이렇게 하면 두 번째 로그인 셸이 실행되어 쉽게 더 큰 차이를 만들 수 있습니다( OR이 멱등성을 보장하여 이 문제를 zsh -l
해결할 수도 있음 )..profile
.zprofile