bash - 通过 ssh 将脚本和二进制数据通过管道传输到标准输入

标签 bash ssh tar

我想远程执行一个 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/

相关文章:

database - SSH 隧道在 DataGrip 中不起作用

java - 需要将 SSH 命令自动化到路由器

bash - 从 tar 存档中删除重复项

php - 允许通过 PHP 访问 protected 文件

c - 为什么这些 'xset' 命令在 Raspberry Pi Raspbian 上的 C 程序中的 system() 中不起作用?

linux - Bash 脚本在进入 docker 容器时退出

linux - 空间是否被视为 Bash 中的元字符?

c++ - Linux 键盘扫描码问题 : For example, UP ARROW 给出 ^[[A

ssh - 我可以在命令行上覆盖 Ansible SSH key list 变量 ansible_ssh_private_key_file 吗?

c++ - 从 C++ 程序创建 tar.gz-archive 不起作用