SSH 원격에 변수를 전달하려고 하는데 작동하지 않습니다. 내 코드는 다음과 같습니다
#!/bin/bash
set -x
conexion="[email protected]"
parameter="$1"
ssh -T $conexion <<'ENDSSH'
clear
echo "$parameter"
ENDSSH
나는 다음을 실행한다:
./script.sh try
그것은 나에게 말했다:
parameter: Undefined variable.
도움이 필요하세요?
답변1
변수(환경 변수) 전달이 ssh
가능하지만 일반적으로 제한됩니다.
클라이언트에게 보내달라고 말해야 합니다. OpenSSH를 예로 들면 다음과 같습니다.
ssh -o SendEnv=parameter host cmd...
그러나 이를 수락하려면 서버도 필요합니다( AcceptEnv
OpenSSH의 구성 지시문 사용). 변수를 허용하는 것은 상당한 보안 위험을 초래하므로 일부 SSH 배포에서는 특정 네임스페이스(예: LC_*
일부 OpenSSH 배포)에서 특정 변수를 허용하지만 일반적으로 기본적으로 수행되지 않습니다.
또한 를 호출하기 전에 변수를 내보내야 합니다 ssh
. 예를 들면 다음과 같습니다.
LC_parameter="$parameter" ssh -o SendEnv=LC_parameter host csh << 'END'
echo $LC_parameter:q
END
위에서는 쉘 변수의 내용을 환경 변수 $parameter
bash
로 전달하고 , 이를 승인하면 환경 변수로 사용자의 로그인 쉘에 전달한 다음 명령에 전달합니다 ( 그런 다음 확장할 수 있음). ) .LC_parameter
ssh
ssh
sshd
csh
host
그러나 언급한 대로 컴퓨터 관리자가 구성에 AcceptEnv LC_parameter
또는 를 추가하지 않는 한 AcceptEnv LC_*
(때때로 기본적으로 수행됨) 이 작업은 작동하지 않습니다 sshd
.
예제의 오류 메시지 Undefined variable
는 원격 사용자의 로그인 셸이 csh
또는 임을 나타냅니다 tcsh
. 예상치 못한 상황을 피하기 위해 쉘을 명시적으로 호출하는 것이 더 좋습니다( ssh host csh
또한 tty가 요청되지 않았으므로 요청하지 않아도 됨을 의미합니다 -T
). $LC_parameter:q
구문에 유의하세요 . 이는 변수에 개행 문자가 포함된 경우 작동하지 않는 csh
것과는 반대로 변수의 내용을 문자 그대로 전달하는 방법 입니다."$LC_parameter"
변수를 사용하는 LC_*
것이 옵션이 아닌 경우 다음을 사용할 수도 있습니다.고객쉘( bash
귀하의 경우)은 변수를 확장합니다. 순진한 접근 방식은
ssh host csh << END
echo "$variable"
END
그러나 이는 변수의 내용이 원격 쉘에 의해 해석되기 때문에 위험합니다. 예시를 $variable
포함 `reboot`
하거나 제시 하면 "; reboot; : "
나쁜 결과를 낳게 됩니다.
따라서 먼저 원격 셸의 구문에서 변수가 올바르게 참조되는지 확인해야 합니다. 여기서는 csh
안정적으로 수행하기 어려운 곳 을 피하고 대신 sh
//를 사용합니다 .bash
ksh
sh 참조를 위해 도우미 함수를 사용하십시오.
shquote() {
awk -v q=\' -v b='\\' '
BEGIN{
for (i=1; i<ARGC; i++) {
gsub(q, q b q q, ARGV[i])
printf "%s ", q ARGV[i] q
}
print ""
exit
}' "$@"
}
다음과 같이 호출됩니다 ssh
.
ssh host sh << END
parameter=$(shquote "$parameter")
echo "\$parameter"
END
로컬 셸이 아닌 원격 셸에서 $
확장이 수행되도록 세 번째 항목을 어떻게 이스케이프하는지 살펴보세요 .$parameter
답변2
환경 변수 전달과 같은 다른 트릭 외에도 LC_*
다음을 수행할 수 있습니다.
PARAMETER="123"
ssh user@host PARAMETER="$PARAMETER" bash -s <<- 'EOF'
echo $PARAMETER
EOF
이 방법의 장점은 원격 호스트 (이름이 다음으로 시작하지 않는 경우), 로컬 호스트(대상 또는 대상) export PARAMETER
의 구성에 이름을 추가할 필요가 없다는 것입니다 .AcceptEnv
LC_
/etc/ssh/sshd_config
SendEnv
-o
/etc/ssh/ssh_config
답변3
ENDSSH
네 번째 줄에서 따옴표를 제거하면 도움이 될 것입니다.
제공: 질문에 대한 @Archemar의 의견.
경고하다이 답변의 설명에서 @StéphaneChazelas가 언급했듯이 이 솔루션을 사용하면 $parameter
여기 문서의 변수가 로컬 셸에 의해 확장됩니다. 즉, 변수의 내용이 원격 셸에 의해 셸 코드로 해석됩니다. 이는 명령 주입 취약점이 발생함을 의미합니다.따라서 이것은 일반적으로 권장되지 않습니다.
답변4
큰따옴표 안에 작은따옴표를 삽입합니다.
$ file_name="one two"
$ ssh remote ls "'$file_name'"
ls: cannot access 'one two': No such file or directory
작은따옴표를 제거하지 않고 변수가 먼저 대체됩니다. 이런 방식으로 콘텐츠는 작은따옴표로 묶어 ssh로 전송됩니다.