使用 SSH 上传文件,然后将控制权交还给用户

使用 SSH 上传文件,然后将控制权交还给用户

我正在尝试创建一个脚本,当您使用 SSH 连接到远程服务器时,该脚本会检查内容并部署您的个人脚本,然后再返回标准输入,所有这些都在一个 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

通过同一流发送 shell 代码、tar 文件和用户输入ssh -t,同时又ssh可能要求输入密码或关键密码短语,这将是极其笨拙和脆弱的。

如果您的conf文件不是太大并且可以适应环境变量,并且远程sshdAcceptEnv LC_*在其配置中有一个(这是常见的),您可以传递以其中之一编码的tgz文件base64:

#! /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'

(还假设远程计算机上用户的登录 shell 是类似 POSIX 的)。

如果没有,最简单的方法可能是使用多个调用,ssh但所有调用都与连接多路复用功能共享相同的登录会话(请参阅手册页中的ControlMaster//说明和/或查看此站点上的示例)。ControlPathControlPersist

使用最新版本的 openssh 的另一种方法是-R remote_socket:local_socket使用 Unix 域套接字来传输 tar 文件(zsh/net/socket例如使用 zsh 的模块)。

相关内容