将登录 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
调用。
我有一个 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
调用。