期望脚本找到远程服务器上的文件

问题描述:

我正在编写一个Expect脚本来找出远程服务器上是否存在特定文件.我的测试服务器与远程服务器位于同一网络中.当我尝试在*中搜索类似的内容时,我只能找到期望在本地服务器上运行的脚本.

I am writing an expect script to figure out the existence of a specific file on a remote server. My test server is located in the same network as the remote server. While I tried to search through * for similar stuff all I could find is expect scripts that would work on local server.

此链接(如何查找是否有文件在期望脚本中存在)是最接近的.

This link (How to find if a file exists in expect script) was the closest.

在相似的地方,我找到了以下网站- 使用SFTP进行访问

On similar lines I found the following website to - Expect with SFTP

基于两者,我尝试编写我的期望脚本-

Based on both I tried to write my expect script -

#! /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".期望部分的逻辑是-

Regardless of the response to "ls $fileName", I get the output as "Found". The logic on expect part was -

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",这是我无法理解的地方.如果文件存在,我希望文件名弹出.否则,我希望看到消息无法声明.....".

So in both cases the script output is "FOUND" which is where I don't get the logic. I am expecting the file name to pop up if the file is present. Else I am expecting to see the message "Could not state .....".

  1. 可以期望检测到提示吗?我可以将其存储在某个地方吗?

  1. Can expect detect a prompt? Can I store it somewhere?

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

Is there a better way to find the existence of a file on a remote server?

我的脚本有问题吗?

预先感谢您的帮助!

Expect可以做tcl可以做的事情.当然,您可以将提示保存到一些变量中并进一步使用.

Expect can do whatever tcl can do. Of course, you can save the prompt into some variable and use it further.

set prompt "sftp> $"

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

What is this $ symbol doing here ? By default, expect will match with glob style and ^ is used to match the beginning and $ is to match the end of a string.

您可以在代码中以

expect $prompt

无论采用哪种方式,只有在涉及expect时,这才是好方法.

Whatever the way you are trying to get is good approach only when it comes to expect.

我可以在您的脚本中看到一些问题.正如布拉德·拉纳姆(Brad Lanam)所指出的那样,您不应使用文件名作为匹配条件来检查文件是否存在.

I can see some issues in your script. As Brad Lanam pointed out, you should not use filename as match criteria for checking whether the file present or not.

折衷的方法可以写成

#!/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,这显然是文件不可用的标准.

If file is not available, we are getting the message as No such file or directory, which is obviously the criteria if file not available.

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

In case of file present, then the output looks like this,

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

您可能想知道为什么在输出中两次看到命令ls dinesh.txt.这是因为,生成的进程正在回显通过send发送的命令. (这是另一回事.请查看此处,以了解是否您有兴趣)

You might be wondering why the command ls dinesh.txt being seen twice in the output. That is because, the spawned process is echoing back the command being sent via send. (This is different story. Have a look at here to know more about if you are interested)

为此,我使用了正则表达式作为

To match this, I have used regular expressions as

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

我要匹配的内容如下,

dinesh.txt
sftp>

\n-匹配上一行的新行

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

$filename - this will be replaced with the given file name. i.e. 'dinesh.txt'

\\s+-匹配多个空格

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

$prompt - this will be replaced with 'sftp> $'

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

At last, I have added timeout, if in case timeout happens with expect. Default timeout value is 10s and I have changed it to 60s in the script.

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

Note : How to know there are multiple spaces between file name and the prompt ? Why it can't be like filename, newline and the prompt. By seeing the output we can come to any conclusion like this. There is no magic to find and there is a reason why expect is brought up with an option of -d (or exp_internal 1). Trigger it with those options and you are an expect's expert. :)