我有一个数组,$HOSTS
其中包含一组主机名。我有一个数据库表,其中包含一组 IP 地址。我想遍历该表中的每个 IP 地址并向hostname -s
该地址发送命令 (),然后将输出添加到$HOSTS
。远程服务器未配置 PKI,并且脚本必须在无人干预的情况下自动运行。这是一个封闭的网络,root 密码作为变量存储在脚本中 ( $SERVERPASSWORD
)。在有人说之前,我意识到将 root 密码放在这样的变量中并不是一个好主意,但在这种情况下,与保护 root 密码相比,不进行任何人为交互更为重要。
这是我当前(已清理)脚本的相关部分:
for IP in $(sql query that returns a list of IP addresses);do
HOSTS=($(expect -c 'spawn ssh root@$IP "hostname -s"; expect "assword:";send ""$SERVERPASSWORD"\r";interact' ${HOSTS[@]}))
done
这样做的结果是失败的,说:
无法读取“IP”:执行“spawn ssh root@$IP“hostname -s””时没有这样的变量
我可以用一个来echo $IP
代替它,并且它会按预期工作,所以我知道 IP 变量正在循环中填充。
经过一番谷歌搜索,我发现似乎expect
需要设置自己的变量,不能使用 Bash 变量,但我发现的所有解决方案都是针对实际的 Expect 脚本,而不是针对在 Bash 脚本中使用 expect。我尝试修改命令,expect set IP $IP -c 'spawn ....'
但似乎没有成功。
我该怎么做才能读取这个 For 循环中expect
的值?$IP
答案1
摆脱使用全大写变量名的习惯,让它们保留在 shell 中。有一天你会写PATH=something
,然后想知道你的脚本为什么坏了。
您还可以使用它array+=( "new element" )
来附加到数组。
下面,我将单行代码扩展为代码以便于阅读。
这只是 shell 中的一个引用问题。有几种方法可以解决它:
对期望主体使用双引号。这意味着您必须以不同的方式处理期望引用:您可以对所有双引号使用反斜杠(粗略)或使用括号(这是 Tcl 的单引号机制):
hosts+=( "$( expect -c " spawn ssh root@$ip {hostname -s} expect {assword:} send {$serverPassword}; send \\r expect eof " )" )
将变量传递到环境中。这里我使用带引号的 heredoc,因此您无需担心引用:
hosts+=( "$( ip="$ip" pw="$serverPassword" expect <<<'END_EXPECT' spawn ssh root@$env(ip) "hostname -s" expect "assword:" send "$env(serverPassword)\r" expect eof END_EXPECT )" )