SSH를 사용하여 원격 서버에 연결할 때 스크립트가 내용을 확인하고 stdin으로 돌아오기 전에 개인 스크립트를 배포하는 스크립트를 만들려고 합니다. 이 모든 작업은 하나의 SSH 연결 내에서 이루어집니다. 그렇지 않으면 여러 번 수행해야 합니다. 인증을 위해..).
작동하는 스크립트가 있습니다.
#!/bin/zsh
HOST="$1"
# Install ZSH if it's not already installed
ssh "$HOST" <<- EOF
if [ ! -x /bin/zsh ]; then
if [ -x "/usr/bin/dnf" ]; then
sudo dnf install -y zsh >/dev/null
elif [ -x "/usr/bin/apt-get" ]; then
sudo DEBIAN_FRONTEND=noninteractive apt-get install -y zsh >/dev/null
fi
fi
EOF
# Copy ZSH configuration to remote host
tar -cz -f - -C "$HOME" --exclude="*.zwc" {.zshrc,.zshenv,.config/zsh/{p10k.zsh,plugins}} | ssh "$HOST" 'tar -xz -f - -C "$HOME"'
# Login with ZSH in a login shell
ssh -t "$HOST" 'SHELL=/bin/zsh /bin/zsh -l'
하지만 이를 위해 여러 연결을 사용합니다. 하나의 연결만 어떻게 사용할 수 있나요?
POC를 시도했습니다
#!/bin/zsh
HOST="$1"
# redirect 3 to standard output
exec 3>&1
ssh -t $HOST >&3 <&1 &
# doesn't work, doesnt execute on remote host
echo "hostname"
# this as well
echo "hostname" >&1
# works, give back the tty of the remote server to the user
exec 1<&0
wait
echo "THE END"
하지만 tty가 반환될 때까지 원격 서버에서 명령을 실행할 수 없습니다. 그리고 파일을 보내는 방법도 모르겠습니다.
이 모든 작업을 수행할 수 있는 방법이 있나요?
답변1
동일한 스트림을 통해 셸 코드, tar 파일 및 사용자 입력을 보내는 것은 잠재적으로 암호나 키 암호 문구를 요구 ssh -t
하지만 ssh
매우 서투르고 취약합니다.
conf 파일이 너무 크지 않고 환경 변수를 수용할 수 있고 원격 sshd의 AcceptEnv LC_*
구성에 하나가 있는 경우(일반적인 경우) 다음 base64 중 하나로 인코딩된 tgz 파일을 전달할 수 있습니다.
#! /bin/zsh -
HOST=${1?}
LC_ZC=$(
tar -cz -f - -C ~ --exclude="*.zwc" {.zshrc,.zshenv,.config/zsh/{p10k.zsh,plugins}} |
base64
) exec ssh -o SendEnv=LC_ZC -t "$HOST" '
if ! command -v zsh; then
if command -v dnf; then
sudo dnf install -y zsh
elif command -v apt-get; then
sudo DEBIAN_FRONTEND=noninteractive apt-get install -y zsh
fi
fi > /dev/null
echo "$LC_ZC" | base64 -d | tar -zxf - -C ~
unset -v LC_ZC
SHELL=/bin/zsh exec /bin/zsh -l'
(또한 원격 시스템에 있는 사용자의 로그인 쉘이 POSIX와 유사하다고 가정합니다.)
그렇지 않은 경우 가장 쉬운 방법은 아마도 여러 호출을 사용하는 것이지만 ssh
모두 연결 다중화 기능을 사용하여 동일한 로그인 세션을 공유하는 것입니다( ControlMaster
// 매뉴얼 페이지의 지침 및/또는 이 사이트의 예를 참조하십시오).ControlPath
ControlPersist
최신 버전의 openssh를 사용하는 또 다른 방법은 -R remote_socket:local_socket
Unix 도메인 소켓을 사용하여 tar 파일을 전송하는 것입니다( zsh/net/socket
예: zsh 모듈 사용).