shell脚本批量执行命令
凌晨三点,本批服务器上的量执令日志文件把磁盘撑爆了。我登上跳板机,行命看着十几台机器上同样的本批错误日志,手动一台台登录、量执令grep、行命删除,本批干到天亮。量执令那次之后我写了个脚本,行命循环遍历IP列表,本批一条ssh命令批量执行。量执令现在再遇到这种破事,行命两分钟搞定。本批 批量执行命令的量执令核心就一句话:把命令通过循环或并行工具分发到多台机器上。最常见的行命做法是 这个脚本顺序执行,一台接一台。十台以内还行,上百台就等到天荒地老。而且如果某台机器网络卡住,整个循环就堵在那里。我吃过这个亏——有台老机器的SSH端口响应极慢,脚本跑了四十分钟还没轮到最后几台。 解决办法是用 有个细节容易被忽略:命令里的引号。 还有一种场景是命令特别长或者逻辑复杂,塞进一行ssh里可读性极差。我的做法是把脚本先scp到目标机器,再远程执行: 这样脚本在本地可以正常调试,传上去直接跑。缺点是每台机器都要传一次,如果脚本本身很大,网络传输就是瓶颈。折中方案是先把脚本放到内网的某台文件服务器上,远程机器用 批量执行最怕的是“部分成功”。十台机器里八台执行成功,两台失败,你得知道是哪两台。所以脚本里一定要记录输出和退出码: 别小看这个日志,出问题的时候它就是你的救命稻草。我习惯把每台机器的输出单独存一个文件,命名带上IP和时间戳,事后排查一目了然。 最后说一个真实教训。有次批量改配置,脚本里用了for循环加ssh。比如你有一个hosts.txt,每行一个IP:#!/bin/bash for ip in $(cat hosts.txt); do echo "=== $ip ===" ssh user@$ip "df -h | grep /data" done&把每次ssh丢到后台,或者用parallel、pssh这类工具。parallel我用得最多,一行命令搞定并发:parallel -j 10 ssh user@{ } "systemctl restart nginx" :::: hosts.txt-j 10表示同时跑10个任务。这个数字别贪大,SSH连接本身有开销,并发太高反而拖慢整体速度,还容易触发目标机器的连接数限制。我一般设成机器数量的1/3到1/2。ssh user@$ip "echo $HOSTNAME"里的$HOSTNAME会在本地展开,而不是在远程机器上。想要远程执行时再展开,得用单引号或者转义。这个坑我踩过不止一次,调试半天才发现变量在本地就被替换了。for ip in $(cat hosts.txt); do scp deploy.sh user@$ip:/tmp/ ssh user@$ip "bash /tmp/deploy.sh" donewget或curl拉取。for ip in $(cat hosts.txt); do if ssh user@$ip "command" >> /tmp/batch.log 2>&1; then echo "$ip OK" >> /tmp/batch_result.log else echo "$ip FAILED" >> /tmp/batch_result.log fi donesed -i直接替换,结果有台机器的配置文件格式跟其他不一样,替换后语法错误,服务起不来。批量操作前先在单台机器上验证,或者用--dry-run模式跑一遍,确认无误再全量执行。这个习惯让我后来少加了很多班。
-
上一篇
-
下一篇
- 最近发表
- 随机阅读
- 搜索
-
- 友情链接
-