我一直在尝试获取一个 expect/bash脚本,该脚本可以读取CSV文件的每一行并同时提取hostname地址和密码;因为我试图访问的每个MikroTik都是不同的。

我最近发送了一个auto.rsc文件给数千个MikroTik路由器,这些路由器被用作住宅解决方案。这个文件填满了硬盘(它有一个IP扫描,创建了一个日志,设法做了这件事。)这使我无法发送额外的auto.rsc文件来清除日志,因为没有可用的空间。

我想出的解决方案是使用expect脚本登录这些并删除auto.log文件。这是我的RSA脚本成功的。

set timeout 3
set f [open "dynuList.txt"]
set dynu [split [read $f] "\n"]
close $f

foreach dynu $dynu {
spawn ssh -o "StrictHostKeyChecking no" -i mtk4.key admin+t@$dynu
expect {
"> " { send "\:do \{ file remove push.auto.log \} on-error\=\{ \[\] \}\r" }
"Connection refused" { catch {exp_close}; exp_wait; continue }
eof { exp_wait; continue }
}
expect ".*"
close
wait
}

我遇到问题的脚本如下:

n=`wc -l hostPasswordDynuList.csv | awk '{print$1}'`
i=1
while [ $i -le $n ]
do
host='awk -F "," 'NR==$i {print $1}' hostPasswordDynuList.csv'
password='awk -F "," 'NR==$i {print $2}' hostPasswordDynuList.csv'
./removeLogExpect.sh $host $password
i=`expr $i + 1`
done

哪个应该将变量传递给此期望脚本

#!/usr/bin/bash/expect -f
set timeout 3
set host [lindex $argv 0]
set password [lindex $argv 1]

spawn ssh -o "StrictHostKeyChecking no" admin+t@$host
expect {
"password: " { send $password"\r" }
"Connection refused" { catch {exp_close}; exp_wait; continue }
eof { exp_wait; continue }
}
expect {
".*" { send "\:do \{ file remove push.auto.log \} on-error\=\{ \[\] \}\r" }
}
expect ".*"
close
wait

我希望脚本能够连接然后登录到没有设置RSA密钥的每个MikroTik,然后命令清除auto.log文件。就目前而言,脚本似乎并没有将变量传递给期望的一半。任何帮助,将不胜感激。

分析解答

expect是Tcl语言的扩展,它是一种功能齐全的编程语言:它可以读取文件并解析comma分离的字段。没有必要使用效率低下的shell脚本多次调用您的expect程序

#!/usr/bin/bash/expect -f
set timeout 3

set file hostPasswordDynuList.csv
set fh [open $file r]

while {[gets $fh line] != -1} {
    lassign [split $line ,] host password

    spawn ssh -o "StrictHostKeyChecking no" admin+t@$host
    expect {
        "password: " { send $password"\r" }
        "Connection refused" {
            catch {exp_close}
            exp_wait
            continue 
        }
        eof {
            exp_wait
            continue 
        }
    }
    expect ".*" 
    send ":do { file remove push.auto.log } on-error={ \[\] }\r"
    expect ".*"
    exp_close
    exp_wait
}

close $fh

有关Tcl内置命令的文档,请参阅https://tcl.tk/man/tcl8.6/TclCmd/contents.htm

expect ".*"行可能没有按照您的想法执行操作:默认模式匹配样式为glob的,因此.*会查找文字点后跟任意数量的字符。您可能正在考虑需要添加-re选项的正则表达式"any character zero or more times"。 然而,强大的期望代码的关键是期望更具体的模式。