是否可以每次都在 bash 脚本中存储 ssh 连接而不是 $(ssh user@ip command) ?

是否可以每次都在 bash 脚本中存储 ssh 连接而不是 $(ssh user@ip command) ?

我认为我已有的代码效率不是很高,因为它每次都必须连接到同一台机器并执行命令。代码:

tmp=$(ssh -nq $USER@$IP "$COMMAND" 2>> $LOG)
tmp1=$(ssh -nq $USER@$IP "$COMMAND1" 2>> $LOG)
tmp2=$(ssh -nq $USER@$IP "$COMMAND2" 2>> $LOG)
tmp3=$(ssh -nq $USER@$IP "$COMMAND3" 2>> $LOG)

在大多数情况下$COMMAND,是某种grep.

我可以以某种方式存储 ssh 连接或重构代码,这样它就不会每次都连接到机器吗?

答案1

如果远程用户的 shell 是 ksh93、zsh 或 bash(或sh实现为其中任何一个),您可以执行以下操作:

eval "$(ssh -nq "$user@$host" '
  printf "%s=%q\n" \
    tmp1 "$(command1)" \
    tmp2 "$(command2)" \
    tmp3 "$(command3)"')"

但请注意,您将丢失远程命令的退出状态。这可能允许远程用户导致您执行任意命令(例如通过在他们的 中输出某些内容~/.bashrc)。

另一种选择是使用ssh 的多个调用之间共享连接ControlMaster的功能。ssh您也可以使用该auto模式。就像是:

mkdir -p -- ~/.ssh/ctl
tmp1=$(ssh -o ControlMaster=auto \
           -o ControlPath="$HOME/.ssh/ctl/%L-%r@%h:%p" \
           -o ControlPersist=5m -nq "$user@$host" cmd1)

(对于...也一样tmp2)。该语法将重新使用现有连接(如果存在),否则创建一个新连接。它将在闲置 5 分钟后终止,或者您可以使用以下命令显式关闭它:

ssh -o ControlPath="$HOME/.ssh/ctl/%L-%r@%h:%p" -O exit "$user@$host"

第一次调用将花费一些时间,因为它将执行连接和身份验证,而接下来的调用会快得多。

当然,如果您不需要将三个命令输出放入三个不同的变量中,您可以这样做:

tmp=$(ssh -nq "$user@$host" '
   cmd1
   cmd2
   cmd3')

因此 3 个命令输出将串联显示在$tmp.

答案2

您可以使用此处文档:

cat <<EOF | ssh $USER@$IP 2>>$LOG
grep x *
grep -i y *.log
EOF

相关内容