【发布时间】:2021-10-14 02:07:39
【问题描述】:
我尝试启动部署在独立服务器中的所有退出的 docker 容器,所以基本上我应该执行下面的基本命令
[ $(docker ps -a | grep Exited | wc -l) -ne 0 ] && docker start $(docker ps -a | grep Exited | cut -d' ' -f1)
它像在纯 linux shell 中一样工作得很好,但是当我尝试使用 expect 来“发送”“基本”命令时发生错误(如下所示)。 (本地ip是241,远端是209)
[root@localhost start_shell_dir]# spawn ssh root@192.168.1.209
root@192.168.1.209's password:
Last login: Fri Oct 15 22:23:25 2021 from 192.168.1.241
[root@localhost ~]# invalid command name "0"
while executing
"0 -ne 0 "
invoked from within
"send "[ 0 -ne 0 ] && docker start ""
错误日志显示我已经登录远程机器,当我执行 docker 命令时出现问题。
评论区的Glenn jackman 向我展示了basic rule for tcl,然后我意识到期望在发送实际命令之前会进行命令替换。我们可以通过执行bash -x script.sh 看到它。
[root@localhost start_shell_dir]# bash -x startContainer.sh
+ read ip pass
+ read ip pass
+ /usr/bin/expect
[root@localhost start_shell_dir]# ++ docker ps -a
++ grep Exited
++ wc -l
++ docker ps -a
++ grep Exited
++ cut '-d ' -f1
spawn ssh root@192.168.1.209
root@192.168.1.209's password:
Last login: Fri Oct 15 22:37:56 2021 from 192.168.1.241
[root@localhost ~]# invalid command name "0"
while executing
"0 -ne 0 "
invoked from within
"send "[ 0 -ne 0 ] && docker start ""
无论如何,对我有用的最后一个命令是下面显示的命令(用大括号替换双引号并在 $() 之前用反斜杠将其保留为普通字符,而不是预先解析它)。
send {[ \$(docker ps -a | grep Exited | wc -l) -ne 0 ] && docker start \$(docker ps -a | grep Exited | cut -d' ' -f1)}
#!/bin/bash
# my original script with error
while read ip pass
do
{
/usr/bin/expect <<-END
spawn ssh root@$ip
expect {
"yes/no" { send "yes\r";exp_continue }
"password:" { send "$pass\r" }
}
expect "#"
send "[ $(docker ps -a | grep Exited | wc -l) -ne 0 ] && docker start $(docker ps -a | grep Exited | cut -d' ' -f1)"
expect eof
END
}&
done<apps_ip.txt
【问题讨论】:
-
实际错误是什么? (您似乎包含了指向 PNG 文件的链接而不是错误消息。)您可以使用 Ansible 或 Salt Stack 等通用自动化工具来代替编写此脚本吗?
-
我是新手,甚至期望使用 shell,并且现在不打算像学习 Ansible 或 Salt Stack 那样深入。写这个脚本更像是为了好玩,LOL