通过ssh将脚本和二进制数据传递给stdin

mxx*_*xxk 4 ssh bash tar

我想远程执行一个bash脚本,它使用tarball并对它执行一些逻辑.诀窍是我只想使用一个ssh命令来执行它(而不是scp用于ssh脚本后面的tarball ).

bash脚本如下所示:

cd /tmp
tar -zx
./archive/some_script.sh
rm -r archive
Run Code Online (Sandbox Code Playgroud)

我意识到我可以简单地将这个脚本重新格式化为单行并使用

tar -cz ./archive | ssh $HOST bash -c '<commands>'
Run Code Online (Sandbox Code Playgroud)

但我的实际脚本很复杂,我必须bash通过标准输入管道.这里的挑战是ssh只提供一个输入管道(stdin),我想将它用于bash脚本和tarball.

mxx*_*xxk 5

我想出了两个解决方案,其中包括bash脚本和stdin中的tarball.

1.将base64编码的tarball嵌入到heredoc中

在这种情况下,服务器接收一个bash脚本,其中tarball嵌入在heredoc中:

base64 -d <<'EOF_TAR' | tar -zx
<base64_tarball>
EOF_TAR
Run Code Online (Sandbox Code Playgroud)

这是完整的例子:

ssh $HOST bash -s < <(
# Feed script header
cat <<'EOF'
cd /tmp
base64 -d <<'EOF_TAR' | tar -zx
EOF

# Create local tarball, and pipe base64-encoded version
tar -cz ./archive | base64

# Feed rest of script
cat <<'EOF'
EOF_TAR
./archive/some_script.sh
rm -r archive
EOF
)
Run Code Online (Sandbox Code Playgroud)

但是,在这种方法中,tar在完全通过网络传输之前,不会开始提取tarball.

2.在脚本之后提供tar二进制数据

在这种情况下,bash脚本通过管道传输到stdin,然后是原始tarball数据.bash传递控制到tarstdin的tar部分的进程:

ssh $HOST bash -s < <(
# Feed script.
cat <<'EOF'
function main() {
  cd /tmp
  tar -zx
  ./archive/some_script.sh
  rm -r archive
}
main
EOF
# Create local tarball and pipe it
tar -cz ./archive
)
Run Code Online (Sandbox Code Playgroud)

与第一种方法不同,这种方法允许tar在通过网络传输时开始提取tarball.

边注

main你问我们为什么需要这个功能?为什么首先提供整个bash脚本,然后是二进制tar数据?好吧,如果二进制数据放在bash脚本的中间,那么就会出现一个错误,因为它tar消耗了tarfile的结尾,在这种情况下会占用一些bash脚本.因此,该main函数用于强制整个bash脚本在tar数据之前.