내 사용자 이름 (myuser)으로 만 로그인 할 수있는 시스템이 있지만 다른 사용자 (scriptuser)로 명령을 실행해야합니다. 지금까지 필요한 명령을 실행하기 위해 다음을 생각해 냈습니다.
ssh -tq myuser@hostname "sudo -u scriptuser bash -c \"ls -al\""
그러나 더 복잡한 명령을 실행하려고하면 [[ -d "/tmp/Some directory" ]] && rm -rf "/tmp/Some directory"
인용에 문제가 생길 수 있습니다. 나는이 예 복잡한 명령을 전달할 수있는 방법을 잘 모르겠어요 bash -c
때, \"
이미 명령을 내가 전달하고있어 (그래서 나는 공백이 포함 / tmp를 / 일부 디렉토리를 인용하는 방법을 모르는의 경계를 delimites.
인용이 아무리 복잡하거나 미친 지에 관계없이 명령을 전달할 수있는 일반적인 해결책이 있습니까? 아니면 이것이 어떤 한계에 도달 했습니까? 다른 가능하고 더 읽기 쉬운 솔루션이 있습니까?
답변
때때로 사용하는 트릭은 base64를 사용하여 명령을 인코딩하고 다른 사이트에서 bash로 파이프하는 것입니다.
MYCOMMAND=$(base64 -w0 script.sh)
ssh user@remotehost "echo $MYCOMMAND | base64 -d | sudo bash"
이렇게하면 안전한 문자열 안에 쉼표, 백 슬래시, 따옴표 및 변수가 포함 된 스크립트가 인코딩되어 다른 서버로 전송됩니다. ( -w0
기본적으로 열 76에서 발생하는 줄 바꿈을 비활성화하는 데 필요합니다). 다른 한편으로, $(base64 -d)
스크립트를 해독하고 실행할 bash에 공급합니다.
스크립트가 아무리 복잡해도 아무 문제가 없습니다. 탈출 할 필요가 없기 때문에 탈출 문제를 해결하십시오. 원격 호스트에 파일을 작성하지 않으며 매우 복잡한 스크립트를 쉽게 실행할 수 있습니다.
답변
참고 항목 -tt
옵션을? ssh(1)
설명서를 읽으십시오 .
ssh -tt root@host << EOF
sudo some # sudo shouldn't ask for a password, otherwise, this fails.
lines
of
code
but be careful with \$variables
and \$(other) \`stuff\`
exit # <- Important.
EOF
내가 자주하는 일 중 하나는 vim을 사용하고 :!cat % | ssh -tt somemachine
트릭을 사용하는 것 입니다.
답변
가장 쉬운 해결책은 @thanasisk의 의견을 수정하는 것입니다.
scp
컴퓨터에 스크립트를 작성한 다음 실행하십시오.
rm
처음에 스크립트 자체를 가지고 있어야합니다 . 셸에서 파일을 열었으므로 파일이로드 된 후 문제없이 제거 할 수 있습니다.
이 순서대로 작업을 수행하면 ( rm
첫째, 다른 작업은 두 번째로) 어느 시점에서 실패하면 제거됩니다.
답변
%q
format 지정자를 사용하여 printf
변수 이스케이프를 처리 할 수 있습니다.
cmd="ls -al"
printf -v cmd_str '%q' "$cmd"
ssh user@host "bash -c $cmd_str"
printf -v
출력을 변수에 씁니다 (이 경우 $cmd_str
). 나는 이것이 가장 간단한 방법이라고 생각합니다. 파일을 전송하거나 명령 문자열을 인코딩 할 필요가 없습니다 (트릭을 좋아하는만큼).
다음은 대괄호 및 앰퍼샌드와 같은 작업에도 적용되는보다 복잡한 예입니다.
$ ssh user@host "ls -l test"
-rw-r--r-- 1 tom users 0 Sep 4 21:18 test
$ cmd="[[ -f test ]] && echo 'this really works'"
$ printf -v cmd_str '%q' "$cmd"
$ ssh user@host "bash -c $cmd_str"
this really works
나는 그것을 테스트하지 않았지만 다음과 sudo
같이 간단해야합니다.
ssh user@host "sudo -u scriptuser bash -c $cmd_str"
원하는 경우 단계를 건너 뛰고 중간 변수 작성을 피할 수 있습니다.
$ ssh user@host "bash -c $(printf '%q' "$cmd")"
this really works
또는 변수를 완전히 작성하지 마십시오.
ssh user@host "bash -c $(printf '%q' "[[ -f test ]] && echo 'this works as well'")"
답변
bash에서 이와 같은 것을 실행하는 “올바른”(구문 적) 방법은 다음과 같습니다.
ssh user@server "$( cat <<'EOT'
echo "Variables like '${HOSTNAME}' and commands like $( uname -a )"
echo "will be interpolated on the server, thanks to the single quotes"
echo "around 'EOT' above.
EOT
)"
ssh user@server "$( cat <<EOT
echo "If you want '${HOSTNAME}' and $( uname -a ) to be interpolated"
echo "on the client instead, omit the the single quotes around EOT."
EOT
)"
작동 방식에 대한 자세한 설명은 https://stackoverflow.com/a/21761956/111948을 참조 하십시오.
답변
sudo
선택한 사용자로서 명령을 실행할 수있는 쉘을 제공 하는 데 사용할 수 있다는 것을 알고 있습니까?
-i,-로그인
대상 사용자의 비밀번호 데이터베이스 항목으로 지정된 쉘을 로그인 쉘로 실행하십시오. 이는 .profile 또는 .login과 같은 로그인 특정 자원 파일을 쉘에서 읽음을 의미합니다. 명령이 지정되면 쉘의 -c 옵션을 통해 실행되도록 쉘로 전달됩니다. 명령을 지정하지 않으면 대화식 쉘이 실행됩니다. sudo는 쉘을 실행하기 전에 해당 사용자의 홈 디렉토리로 변경하려고 시도합니다. 명령은 사용자가 로그인 할 때와 비슷한 환경에서 실행됩니다. sudoers (5) 매뉴얼의 명령 환경 섹션은 -i 옵션이 명령이 실행되는 환경에 어떤 영향을 미치는지 문서화합니다. sudoers 정책이 사용 중입니다.
답변
로컬 머신에서 스크립트를 정의한 후 cat
원격 머신으로 파이프 할 수 있습니다.
user@host:~/temp> echo "echo 'Test'" > fileForSsh.txt
user@host:~/temp> cat fileForSsh.txt | ssh localhost
Pseudo-terminal will not be allocated because stdin is not a terminal.
stty: standard input: Invalid argument
Test