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

时间:2014-05-08 22:53:42

标签: bash ssh tar

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

bash脚本如下所示:

cd /tmp
tar -zx
./archive/some_script.sh
rm -r archive

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

tar -cz ./archive | ssh $HOST bash -c '<commands>'

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

1 个答案:

答案 0 :(得分:5)

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

1。将base64编码的tarball嵌入到heredoc

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

base64 -d <<'EOF_TAR' | tar -zx
<base64_tarball>
EOF_TAR

以下是完整的示例:

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
)

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

2。在脚本

之后提供tar二进制数据

在这种情况下,bash脚本通过管道传输到stdin,然后是原始tarball数据。 bash将控制传递给tar,后者处理stdin的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
)

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

旁注

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