SSH를 통해 sh -c의 변수 확장 실행

SSH를 통해 sh -c의 변수 확장 실행

LXC 컨테이너에서 SSH를 통해 sh -c를 통해 명령을 실행하려고 합니다. lxc-attach가 포함되어 있으므로 sh -c다음과 같이 사용해야 합니다 ssh <host> "lxc-attach -- sh -c \"<command>;<command>\"". 이는 대부분의 상황에 적용됩니다. 그러나 명령에서 리터럴 환경 변수를 사용하려고 하면 변수가 계속 확장됩니다.

문제는 다음과 같이 단순화될 수 있습니다. 텍스트를 인쇄하고 싶습니다.$HOME

현지의:

user@local:~$ sh -c 'echo $HOME'
/home/user
# Despite single quote the variable gets expanded, one has to escape the $ sign
user@local:~$ sh -c 'echo \$HOME'
$HOME

지금까지는 괜찮았지만 SSH를 통해 시도해 보면외딴:

user@local:~$ ssh remote "sh -c 'echo \$HOME'"
/root
user@local:~$ ssh remote 'sh -c 'echo \$HOME''

user@local:~$ ssh remote "sh -c \'echo \$HOME\'"
/root': 1: Syntax error: Unterminated quoted string

이스케이프 변수의 여러 변형을 시도했습니다. 계속 확장되거나 아무것도 인쇄되지 않거나 오류가 발생합니다.

답변1

SSH는 항상 원격으로 쉘을 실행하여 사용자가 제공한 명령줄을 처리합니다. 바라보다: SSH 원격 명령줄 매개변수를 구문 분석하는 방법

$ ssh remote "sh -c 'echo \$HOME'"
/root

로컬 셸은 따옴표 계층을 취소하고 \$SSH가 되어 원격 셸로 $ 전송하여 실행하고 명시적으로 확장을 시작합니다 .sh -c 'echo $HOME'sh$HOME

$ ssh remote 'sh -c 'echo \$HOME''

이는 다음과 관련이 있습니다.

$ ssh remote 'sh -c echo' \$HOME              # or
$ ssh remote 'sh -c echo' '$HOME'

공백은 인용되지 않았습니다( echo원본에도 없었지만 상관없습니다).

SSH는 공백으로 얻은 매개변수를 연결하고 문자열을 sh -c echo $HOME원격으로 보냅니다. 내부 쉘을 통해 전달된 결과 명령 -c은 command 입니다 echo. 그 내부 $HOME로의 확장 .$0sh

$ ssh remote "sh -c \'echo \$HOME\'"
/root': 1: Syntax error: Unterminated quoted string

여기서 로컬 셸은 다시 가 되고 \$SSH $는 문자열을 sh -c \'echo $HOME\'원격으로 보냅니다. 여기서 SSH 실행 셸은 이러한 백슬래시를 구문 분석하고 sh인수 -c, 'echo, /home/username'(확장됨 $HOME)를 사용하여 명령을 실행합니다. 이것내부에 sh명령에 'echo끝나지 않은 인용 문자열이 있는지 확인하십시오.

너한테는 이런 게 필요해

$ ssh localhost 'sh -c "echo \\\$HOME"'
$HOME

sh -c로컬 셸(위의 작은따옴표), SSH에 의해 시작된 셸(백슬래시) 및 사용자가 시작하는 셸(다른 수준의 백슬래시, 하나는 for 및 하나는 for)을 보호하기 위한 \확장입니다 $.

또는 하나의 백슬래시 대신 작은따옴표를 사용하십시오.

$ ssh localhost 'sh -c '\''echo \$HOME'\'
$HOME

여기 또는 이와 유사한 파일이나 (참조) 문서를 통해 명령을 전달하는 것이 더 쉬울 것입니다.

$ ssh localhost 'sh -s' <<'EOF'
echo '$HOME'
EOF
$HOME

또한보십시오:ssh $host $FOO 및 ssh $host "sudo su user -c $FOO" 유형 구성에서 참조됩니다.

관련 정보