我想远程执行一个 bash 脚本,该脚本使用压缩包并对其执行一些逻辑。诀窍是我只想使用一个 ssh 命令来执行此操作(而不是 scp
用于 tarball,然后是 ssh
用于脚本)。
bash 脚本如下所示:
cd /tmp
tar -zx
./archive/some_script.sh
rm -r archive
我意识到我可以简单地将这个脚本重新格式化为一行并使用
tar -cz ./archive | ssh $HOST bash -c '<commands>'
但我的实际脚本非常复杂,我必须通过标准输入将其通过管道传输到 bash
。这里的挑战是 ssh
只提供一个输入管道 (stdin),我想将其用于 bash 脚本和 tarball。
最佳答案
我想到了两个解决方案,都包括 bash 脚本和 stdin 中的 tarball。
1。在 heredoc 中嵌入 base64 编码的 tarball
在这种情况下,服务器会收到一个 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 完全通过网络传输之前不会开始提取 tarball。
2。在脚本之后提供 tar 二进制数据
在这种情况下,bash 脚本通过管道传输到标准输入,然后是原始压缩包数据。 bash
将控制权交给 tar
,它处理标准输入的 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 通过网络传输时开始提取 tarball。
旁注
你问为什么我们需要 main
函数?为什么首先提供整个 bash 脚本,然后提供二进制 tar 数据?好吧,如果将二进制数据放在 bash 脚本的中间,就会出现错误,因为 tar
消耗了 tarfile 的末尾,在这种情况下会吃掉一些 bash 脚本.因此,main
函数用于强制整个 bash 脚本出现在 tar 数据之前。
关于bash - 通过 ssh 将脚本和二进制数据通过管道传输到标准输入,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23553959/