Expect script to find file existence on remote server

允我心安 提交于 2019-12-11 09:17:13

问题


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 stackoverflow 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.

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

Expect Script

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" }
}

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

Found Logic

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

Not Found Logic

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>

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 .....".

QUESTIONS

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

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

  3. Is my script having issues?

Thank you in advance for the help!


回答1:


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

set prompt "sftp> $"

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.

You can make use of it in the code as

expect $prompt

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

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.

A compromised approach can be written as

#!/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" }
}

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> 

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" 

What I am trying to match is as follows,

dinesh.txt
sftp>

\n - to match the new line which is from the previous line

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

\\s+ - to match more than one space

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

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.

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. :)



来源:https://stackoverflow.com/questions/27641153/expect-script-to-find-file-existence-on-remote-server

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!