我想远程执行一个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。
答案 0 :(得分:5)
我想出了两个解决方案,其中包括bash脚本和stdin中的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。
在这种情况下,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数据之前。