技术解析

帮忙看看这个 shell 脚本,搞不定。。
0
2021-06-11 21:12:11
idczone

#!/bin/bash OLD_INFO=host抗投诉服务器list

for IP in $(awk '/^[^#]/{print $1}' $OLD_INFO); do

USER=$(awk -v I=$IP 'I==$1{print $2}' $OLD_INFO)

PASS=$(awk -v I=$IP 'I==$1{print $3}' $OLD_INFO)

PORT=$(awk -v I=$IP 'I==$1{print $4}' $OLD_INFO)

NEW_PASS=$(awk -v I=$IP 'I==$1{print $5}' $OLD_INFO) 

expect -c"

spawn ssh -p$PORT [email protected]$IP

set timeout 15

expect {

    \"(yes/no)\" {send \"yes\r\";exp_continue}
    
    \"password:\" {send \"$PASS\r\";exp_continue}
    
    \"# \" {send \"echo \'$NEW_PASS\'|passwd --stdin $USER\r exit\r\";exp_continue}
    
}"

done

当 hostlist 文件里的多行记录出现同一个 IP 时。。。脚本就不行了,比如内容如下

192.168.128.130 test 123456 22 abc*123

192.168.128.131 a 123456 22 abc*123

我把脚本改成 for line in hostlist,按行读取,再加个 IP 参数,又是另一种错误了。。。


“不行”是指脚本异常退出吗?错误吗是多少,还是卡着不动。“另一种错误”是输出什么了。

加 -x 执行

看得头疼,用了 awk 和 except 已经不是单纯 shell,这两个工具算是有自己的语言多了,建议直接 Python 。

用 while read line do;;done
建议直接 ansible
或者 Python (考虑 plumbum )

建议你 expect 的脚本单独写文件,省的还要考虑字符串转换

看起来是在循环里面赋值造成的问题?
不做太大改动的化,试试这种
```bash
while read line; do
IP=$(echo $line | awk '{print $1}')
USER=$(echo $line | awk '{print $2}')
PASS=$(echo $line | awk '{print $3}')
echo $IP $USER $PASS
done < $OLD_INFO
```

没法贴图我发帖的时候就没把故障贴上来 = =
在循环里赋值的时候出错了,正常应该循环一次,赋值一次,他直接循环一次,把所有值都给赋值了。。错误大概如下。
[[email&~]sh -x 1.sh
+ OLD_INFO=hostlist
++ awk '/^[^$1}' hostlist
+ for IP in '$(awk '\''/^[^$1}'\'' $OLD_INFO)'
++ awk -v I=192.168.128.131 'I==$1{print $2}' hostlist
+ USER='test
a'
++ awk -v I=192.168.128.131 'I==$1{print $3}' hostlist
+ PASS='123456
123456'
++ awk -v I=192.168.128.131 'I==$1{print $4}' hostlist
+ PORT='22
22'

awk 就是扫全文,你每次都扫一遍全文,繁琐。
直接写个 ansible playbook 不好吗?
更轻量一点,用 pthon + plumbum 更形式化地调用命令不好吗?

但是我好奇的是,为什么当 IP 不相同的时候,他能正常赋值呢? ip 相同的时候他反而就赋值出错了。。plumbum 还没玩过,我去百度研究看看= =谢谢。。

亲测可行。。。解决了我的疑惑,但是不懂为什么 for 循环会那样赋值了。。。

我说得很清楚了,awk 每次重新打开 hostlist 并扫描其全文。

多谢,我去研究看看你说的 plumbum

还在用这种老式的方法嘛。ansible 不香吗。

研究研究!!!毕竟就临时一个需求。

主要 ansible 可以直接抄作业,工作量反而低一点,只是框架本身显得很重

因为同个 ip 就是 I==$1 会判断正确
话说这脚本写的不是一般的差 效能差又不优雅

有没有优雅的便捷方式 - -

for line in lines; do

read line;do
ip=$(echo $line | awk '/^[^$1}')
ip=$(echo $line | cut -d ' ' -f 1)
echo $ip
done < xx
上一条自动回复了。。不好意思,顺便问一句,你这个 ssh 的 expect 是在控制老版本的交换机么

如果只是执行一行命令,推荐 sshpass,比 expect 简单多了。。

@mikaelson
写更优雅的脚本

数据地带为您的网站提供全球顶级IDC资源
在线咨询
专属客服