我家里有一个跑着 Docker Swarm 的树莓派集群。为了方便维护,它们使用相同的配置——用户、Docker 版本等等。
有时候某些更新需要在集群的所有节点上执行同样的操作,比如创建一个新的 Docker macvlan 网络。
要做到这一点,要么就得在所有节点上手动执行相同的命令:挨个 ssh 进去,跑完命令,再换下一台。
既然我想着从长远来看少干点活、把一切弄得尽可能井井有条,我就开始研究怎么同时在所有节点上执行命令。
第一轮:自己写 Python 脚本
第一次尝试是自己写一个 Python 脚本。一方面是想顺便把 Python 学得更扎实一点,另一方面是我找不到一种更原生的方式来执行命令。
可想而知(嘿,我对这门语言还没多少经验 🙂),它很快就变成了一团臃肿的乱麻,而且特别容易出问题。
我得找个别的办法,不用再去重新理解三周前写的东西,也不用再琢磨上次到底是什么搞崩了。
第二轮:pssh
四处搜索的时候,我偶然发现了 [pssh](https://linux.die.net/man/1/pssh),它可以通过 SSH 并行执行任务。
总的来说,把它跑起来还挺容易的。
问题在于,有些操作需要通过 sudo 来执行。到处传递密码可不是什么好主意,所以我又得去找办法,弄清楚怎么在远程服务器要求输入密码时把 sudo 密码发过去。
结果发现,只要你碰巧看到对的 StackOverflow 评论,这事儿就简单得很。
太长不看版:
stty -echo; printf "Password: "; read PASS; stty echo; echo "${PASS}" | \
pssh -h <HOSTFILE> -o /tmp/output -t 0 -I "`cat ./commands.sh`"-I "`cat ./commands.sh`" 必须写成这样(用引号和反引号包起来),否则命令无法正确执行。密码会作为单独的一条命令发送,而不会被当作 sudo 的输入。
另一个要注意的地方是,由于这样的设置方式,执行 sudo 时需要加上 -S 参数,才能正确读取密码输入。