【问题标题】:Expect script to find file existence on remote server期望脚本在远程服务器上查找文件存在
【发布时间】:2014-12-25 21:20:04
【问题描述】:

我正在编写一个期望脚本来确定远程服务器上是否存在特定文件。我的测试服务器与远程服务器位于同一网络中。当我尝试通过 stackoverflow 搜索类似的东西时,我所能找到的只是期望可以在本地服务器上运行的脚本。

此链接 (How to find if a file exists in expect script) 是最近的。

在类似的行中,我发现以下网站 - Expect with SFTP

期待脚本

基于这两个我尝试编写我的期望脚本 -

#! /usr/bin/expect

set fileName [lindex $argv 0]
set hostIp "10.0.0.1"

puts "SSH to server"
spawn sftp local@$hostIp
sleep 2
expect "Password:"
sleep 2
exp_send "local123\r"
sleep 2
expect "sftp> "
sleep 2
set prompt "sftp> "

exp_send "ls $fileName\r"
sleep 2

expect { 
"$fileName" { send_user "\n Found \n" }
"sftp>" { send_user "\n Not Found \n" }
}

无论对“ls $fileName”的响应如何,我都会得到输出为“Found”。期望部分的逻辑是 -

找到逻辑

spawn sftp local@10.0.0.1
Connecting to 10.0.0.1...
CentOS release 6.2 (Final)
Kernel 2.6.32-279.14.1.el6.x86_64 on an x86_64

Password:
sftp> ls file1.txt
file1.txt

找不到逻辑

spawn sftp local@10.0.0.1
Connecting to 10.0.0.1...
CentOS release 6.2 (Final)
Kernel 2.6.32-279.14.1.el6.x86_64 on an x86_64

sftp> ls file2.txt
Couldn't stat remote file: No such file or directory
Can't ls: "/file2.txt" not found
sftp>

所以在这两种情况下,脚本输出都是“FOUND”,这是我不明白逻辑的地方。如果文件存在,我希望文件名会弹出。否则,我希望看到消息“无法说明......”。

问题

  1. 可以期望检测到提示吗?我可以把它存放在某个地方吗?

  2. 有没有更好的方法来查找远程服务器上是否存在文件?

  3. 我的脚本有问题吗?

提前感谢您的帮助!

【问题讨论】:

  • $fileName 存在于找到和未找到的响应中。
  • @BradLanam - 如果找到文件,则输出“ls $fileName”,然后就是文件名本身。就像在发现的逻辑中一样。如果找不到文件,那么它将打印以下内容 - 无法统计远程文件:没有这样的文件或目录 无法 ls: "/file2.txt" 未找到 sftp>

标签: tcl expect


【解决方案1】:

Expect 可以做任何tcl 可以做的事情。当然,您可以将提示保存到某个变量中并进一步使用它。

set prompt "sftp> $"

$ 符号在这里做什么?默认情况下,expect 将匹配 glob 样式,^ 用于匹配字符串的开头,$ 用于匹配字符串的结尾。

你可以在代码中使用它

expect $prompt

无论你想得到什么,只有当涉及到expect时才是好方法。

我可以在您的脚本中看到一些问题。正如 Brad Lanam 指出的那样,您不应该使用文件名作为匹配标准来检查文件是否存在。

折衷的方法可以写成

#!/usr/bin/expect
if {$argc!=1} {
        puts "\nUsage : $argv0 <file-name>\n"
        exit
}
set prompt "sftp> $"; # To match 'sftp> ' at the end
set filename [lindex $argv 0]; # User input
set timeout 60; # 1 min 
spawn sftp dinesh1,nmd@frs.sourceforge.net; # Replace this with your sftp server
expect "Password:"
send "mypassword\r"
expect $prompt
send "cd htdocs\r"
expect $prompt
send "ls $filename\r"
expect {
        "No such file or directory" { puts "\n\n File  is not available :( \n\n" }
        -re "\n$filename\\s+\n$prompt" { puts "\n\n File is available :) \n\n" }
        timeout { puts "\n\n timeout happened :( \n\n" }
}

如果文件不可用,我们将收到No such file or directory 的消息,这显然是文件不可用的标准。

如果文件存在,则输出如下所示,

sftp>ls dinesh.txt
ls dinesh.txt
dinesh.txt
sftp> 

您可能想知道为什么命令ls dinesh.txt 在输出中出现两次。这是因为,生成的进程正在回显通过send 发送的命令。 (这是不同的故事。如果您有兴趣,请查看here 以了解更多信息)

为了匹配这个,我使用了正则表达式作为

-re "\n$filename\\s+\n$prompt" 

我要匹配的内容如下,

dinesh.txt
sftp>

\n - 匹配上一行的新行

$filename - 这将替换为给定的文件名。即'dinesh.txt'

\\s+ - 匹配多个空格

$prompt - 这将被替换为 'sftp> $'

最后,我添加了timeout,如果expect 发生超时。默认超时值为 10 秒,我在脚本中将其更改为 60 秒。

注意:如何知道文件名和提示符之间有多个空格?为什么它不能像文件名、换行符和提示符。通过查看输出,我们可以得出这样的任何结论。没有什么神奇的东西可以找到,expect 出现-d(或exp_internal 1)选项是有原因的。用这些选项触发它,你就是一个期望的专家。 :)

【讨论】:

  • 感谢您对脚本的清晰解释。我现在明白了我的期望脚本是如何出现问题的。有了您的建议和意见,我已经成功更新了我的脚本。它的工作方式与我预期的完全相同。感谢您的帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-02-08
  • 2020-02-11
  • 1970-01-01
  • 1970-01-01
  • 2011-05-29
相关资源
最近更新 更多