V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Distributions
Ubuntu
Fedora
CentOS
中文资源站
网易开源镜像站
mikaelson
V2EX  ›  Linux

帮忙看看这个 shell 脚本,搞不定。。

  •  
  •   mikaelson · 2021-05-19 10:46:59 +08:00 · 3901 次点击
    这是一个创建于 1044 天前的主题,其中的信息可能已经有所发展或是发生改变。

    #!/bin/bash OLD_INFO=hostlist

    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 root@$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 参数,又是另一种错误了。。。

    22 条回复    2021-05-25 22:06:56 +08:00
    jmyz0455
        1
    jmyz0455  
       2021-05-19 10:58:16 +08:00
    “不行”是指脚本异常退出吗?错误吗是多少,还是卡着不动。“另一种错误”是输出什么了。
    cominghome
        2
    cominghome  
       2021-05-19 11:14:56 +08:00
    加 -x 执行
    muzuiget
        3
    muzuiget  
       2021-05-19 11:53:17 +08:00
    看得头疼,用了 awk 和 except 已经不是单纯 shell,这两个工具算是有自己的语言多了,建议直接 Python 。
    guader
        4
    guader  
       2021-05-19 12:02:27 +08:00
    用 while read line do;;done<hostlist,然后 cut -d ' ' -f1,最后 expect 感觉会比较简单
    no1xsyzy
        5
    no1xsyzy  
       2021-05-19 12:10:37 +08:00
    建议直接 ansible

    或者 Python (考虑 plumbum )
    zhuisui
        6
    zhuisui  
       2021-05-19 12:51:30 +08:00
    建议你 expect 的脚本单独写文件,省的还要考虑字符串转换
    newaccount
        7
    newaccount  
       2021-05-19 13:17:38 +08:00
    看起来是在循环里面赋值造成的问题?
    不做太大改动的化,试试这种
    ```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
    ```
    mikaelson
        8
    mikaelson  
    OP
       2021-05-19 13:51:52 +08:00
    @jmyz0455 没法贴图我发帖的时候就没把故障贴上来 = =
    在循环里赋值的时候出错了,正常应该循环一次,赋值一次,他直接循环一次,把所有值都给赋值了。。错误大概如下。
    [root@localhost ~]# sh -x 1.sh
    + OLD_INFO=hostlist
    ++ awk '/^[^#]/{print $1}' hostlist
    + for IP in '$(awk '\''/^[^#]/{print $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'
    no1xsyzy
        9
    no1xsyzy  
       2021-05-19 14:02:24 +08:00
    awk 就是扫全文,你每次都扫一遍全文,繁琐。
    直接写个 ansible playbook 不好吗?
    更轻量一点,用 pthon + plumbum 更形式化地调用命令不好吗?
    mikaelson
        10
    mikaelson  
    OP
       2021-05-19 14:12:50 +08:00
    @no1xsyzy 但是我好奇的是,为什么当 IP 不相同的时候,他能正常赋值呢? ip 相同的时候他反而就赋值出错了。。plumbum 还没玩过,我去百度研究看看= =谢谢。。
    mikaelson
        11
    mikaelson  
    OP
       2021-05-19 14:21:08 +08:00
    @newaccount 亲测可行。。。解决了我的疑惑,但是不懂为什么 for 循环会那样赋值了。。。
    no1xsyzy
        12
    no1xsyzy  
       2021-05-19 14:25:54 +08:00
    @mikaelson 我说得很清楚了,awk 每次重新打开 hostlist 并扫描其全文。
    mikaelson
        13
    mikaelson  
    OP
       2021-05-19 14:30:13 +08:00
    @no1xsyzy 多谢,我去研究看看你说的 plumbum
    iceecream
        14
    iceecream  
       2021-05-19 14:46:09 +08:00
    还在用这种老式的方法嘛。ansible 不香吗。
    mikaelson
        15
    mikaelson  
    OP
       2021-05-19 14:46:30 +08:00
    @iceecream 研究研究!!!毕竟就临时一个需求。
    no1xsyzy
        16
    no1xsyzy  
       2021-05-19 15:29:57 +08:00
    @mikaelson 主要 ansible 可以直接抄作业,工作量反而低一点,只是框架本身显得很重
    james122333
        17
    james122333  
       2021-05-19 22:21:37 +08:00
    因为同个 ip 就是 I==$1 会判断正确
    话说这脚本写的不是一般的差 效能差又不优雅
    mikaelson
        18
    mikaelson  
    OP
       2021-05-20 09:28:55 +08:00
    @james122333 有没有优雅的便捷方式 - -
    hzjseasea
        19
    hzjseasea  
       2021-05-20 10:06:55 +08:00
    for line in lines; do
    hzjseasea
        20
    hzjseasea  
       2021-05-20 10:14:39 +08:00
    #!/bin/bash

    while read line;do
    ip=$(echo $line | awk '/^[^#]/{print $1}')
    ip=$(echo $line | cut -d ' ' -f 1)
    echo $ip
    done < xx

    上一条自动回复了。。不好意思,顺便问一句,你这个 ssh 的 expect 是在控制老版本的交换机么
    blessingsi
        21
    blessingsi  
       2021-05-20 20:00:16 +08:00
    如果只是执行一行命令,推荐 sshpass,比 expect 简单多了。。
    james122333
        22
    james122333  
       2021-05-25 22:06:56 +08:00
    @mikaelson

    写更优雅的脚本
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   3012 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 28ms · UTC 15:01 · PVG 23:01 · LAX 08:01 · JFK 11:01
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.