我正在尝试使用测试用户列表针对使用 bash 的主机列表编写 SSH 连接测试脚本,你能帮忙吗?

Mat*_*hew 5 ssh shell-script

我正在尝试使用一组相应的测试用户帐户来测试一组主机的 ssh 连接。

即:testuser1 test ssh connection to server1,,testuser2 test ssh connection to server2testuser3 test ssh connection to server3

每个测试用户都使用私钥登录: ssh -i ~/keys/testuser1key testuser1@server1

但是,将这些信息放入变量时遇到了问题。到目前为止,这是我对脚本的了解:

for host in $(cat hosts)
do
   if
      ssh -i $host 'true' exit
   then
      echo "SSH connection for $host ok"
   else
      echo "SSH connection for $host failed"
   fi
done
$SHELL
Run Code Online (Sandbox Code Playgroud)

host文件如下所示:

~/keys/testuser1key testuser1@server1
~/keys/testuser2key testuser2@server2
~/keys/testuser3key testuser3@server3
...
Run Code Online (Sandbox Code Playgroud)

我收到错误,例如 could not resolve hostname true

我认为host文件中的空间是破坏脚本的原因。我在运行我的用户帐户时使用了一个类似的脚本,没有问题,并且没有“-i”ssh 标志。( ssh myuseraccount@testserver1)

任何关于更好的方法的帮助或建议表示赞赏!

ste*_*ver 7

我建议使用while read循环,以便您可以将空格分隔的标记分配给各个变量,而不是依赖于隐式 split+glob 行为$(cat hosts)

唯一棘手的一点是read默认情况下从标准输入读取 - 也是如此ssh。所以你要么需要传递-n标志来告诉 ssh 从 /dev/null 读取:

while read -r identityfile host; do
  if ssh -n -i "$identityfile" "$host" true
  then
    echo "SSH connection for $host ok"
  else
    echo "SSH connection for $host failed"
  fi
done < hosts
Run Code Online (Sandbox Code Playgroud)

或告诉read从不同的文件描述符读取:

while read -u3 -r identityfile host; do
  if ssh -i "$identityfile" "$host" true
  then
    echo "SSH connection for $host ok"
  else
    echo "SSH connection for $host failed"
  fi
done 3< hosts
Run Code Online (Sandbox Code Playgroud)

注意:您通过使用~而不是$HOME例如为主机文件的身份文件部分添加前缀使事情变得有些困难。引用"$identityfile"可以防止 shell 的波浪号扩展;但是不加引号(as $identityfile)是危险的,因为它允许分词和文件名生成1。这似乎是的,至少OpenSSH的实现ssh扩张~本身,但如果你的SSH实现没有,那么将需要额外的处理,以妥善处理。

1在这种情况下,主要关注的是文件名生成(通配),因为如果名称包含空格,则整个方法都有缺陷。