将登录 shell 时存在的文件读入字符串并使用 expect 脚本进行循环

Read a file which is present on logged in shell into string and do a loop using expect script

我有一个 expect shell 脚本,用于使用 ssh 自动登录 shell 登录后,我在登录 shell 上创建了一个文件,我想阅读并显示登录服务器上存在的文件的内容。

我期望的 scrip 看起来是这样的,它的作用是 1. 使用 ssh 登录 shell 2.在那里创建一个文件 3.读取创建的文件内容并显示。

#!/usr/bin/expect

spawn telnet 10.10.10.10
expect "login:*"
send "XXXXXX\r"
expect "Password*"
send "XXXXX\r"
expect "#"
send "ls -lrt > temp\r"
expect "#"
set f [open ./temp]
set entry [split [read $f] "\n"]
close $f
expect "#"
foreach line $entry {
    puts "$line\n"
}
exit

它表示不存在临时文件,因为它假设该文件存在于执行预期脚本的位置。但是我想读取我在登录 shell 上创建的文件。我正在使用 Mac 来编写脚本。

ls -lrt > temp 在远程主机(telnet 服务器)上运行,但 open ./temp 在本地主机(telnet 客户端)上运行。您不能直接打开远程服务器上的文件。

您想捕获命令的输出,而不是创建临时文件:

set cmd "ls -lrt"
send "$cmd\r"
expect -re "$cmd\r\n(.*)\r\n#$"
set ls_output $expect_out(1,string)
puts $ls_output

我们发送命令,然后期望匹配一个正则表达式:

  • 我们发送的命令:ls -lrt
  • 换行符:expect 总是发回 \r\n 换行符。
  • 无论命令输出什么:(.*)
  • 一个换行符,你的提示字符#,以及文本的结尾

第一组捕获括号中的文本出现在 expect_out 数组中,数组键为 1,string

如果您的提示不完全是一个没有前导或尾随字符的散列字符,您需要相应地调整正则表达式。

提示:在开发 expect 脚本时,启用调试,以便您可以查看哪些与您的 expect 模式匹配或不匹配:expect -d script.exp

问题是文件是在远程主机上创建的,而您却试图在本地读取它。如果您在两者之间没有共享文件系统(很可能不是默认设置;如果您这样做了,您就不会问这个问题了!)那是行不通的。

相反,您希望以易于理解的格式远程获取写出的信息,然后在本地解析它。格式部分供您考虑,但其余部分如下:

spawn telnet 10.10.10.10
expect "login:*"
send "XXXXXX\r"
expect "Password*"
send "XXXXX\r"
expect "#"
send "ls -lrt\r"

# Create the accumulator so that won't be surprised if there's no remote output
set entry {}
# This is the multi-clause version of the expect command
expect {
    "#" {
        # Got a prompt; drop out of the expect
    }
    -re {^.*$} {
        # Got some other line; save and wait for the next one
        lappend entry $expect_out(0,string)
        exp_continue; # <<< MAGIC; asks expect to keep waiting
    }
}

foreach line $entry {
    puts "$line\n"
}
exit

几乎所有关于如何使用 Expect 自动执行一些稍微棘手的事情的问题似乎最终都会使用 expect 的多子句版本和适当的 exp_continue 调用。