Expect Script : spawn id exp4 not open - terminal

I have created an expect script to download some files via sftp.
I now need to copy the files so I have the script:
#!/usr/bin/expect
set now [clock seconds]
set date [clock format [clock seconds] -format {%Y-%m-%d}]
spawn sftp test#user
expect "sftp>"
send "cd public_html\n";
expect "sftp>"
send "get *\n";
expect "sftp>"
send "quit\n";
expect " $"
send "cp -R /media/user/A/$date /media/user/B\n"
But I am getting the error:
sftp> quit
send: spawn id exp4 not open
while executing
"send "cp -R /media/user/A/$date /media/user/B\n""
(file "./test1" line 44)
What is causing this?

Related

Loop through file and send commands over expect

I am trying to send commands from a file to a device over expect. I tried sending them one at a time from my local machine but all of my file paths were relative to local, not relative to the remote device. My solution was to try to upload the file to the device and load the commands from there. When I try to load the file I keep getting a permissions issue even though if I cat the file from the device I don't have a problem reading it. The file has 1 command per line.
devicepath=rsync://root#localhost:$PORT_RSYNC/root/var/root/file.txt
/usr/bin/rsync -Pavr $1 $devicepath
expect <<- expect_feed
set send_slow {1 .001}
spawn ssh -o NoHostAuthenticationForLocalhost=yes -p $PORT_SSH root#localhost
expect -re "password:"
send -s "password\r"
expect -re $PROMPT_ROOT
send -s "chmod 777 /var/root/file.txt\r"
expect -re $PROMPT_ROOT
set f [cat /var/root/file.txt]
set cmds [split [read $f] "\n"]
close $f
foreach line $cmds {
send -s "$line\r"
expect -re $PROMPT_ROOT
expect_feed
This yields:
root# cat: /var/root/file.txt: Permission denied
I also tried
set f [open /var/root/file.txt]
...but it gave the same error.
If the file you send over contains shell commands, treat it as such and simply source it on the remote host
devicepath=rsync://root#localhost:$PORT_RSYNC/root/var/root/file.txt
/usr/bin/rsync -Pavr "$1" "$devicepath"
export PROMPT_ROOT PORT_SSH
expect << 'EXPECT_FEED'
set send_slow {1 .001}
spawn ssh -o NoHostAuthenticationForLocalhost=yes -p $env(PORT_SSH) root#localhost
expect -re "password:"
send -s "password\r"
expect -re $env(PROMPT_ROOT)
send -s ". /var/root/file.txt\r" ;# <<<<
expect -re $env(PROMPT_ROOT)
send "exit\r"
expect eof
EXPECT_FEED
I prefer to use quoted heredocs: shell variables can be passed to expect via the environment.
I'm assuming root's shell is a POSIX-type shell where . is the "source" command.
Thanks for the great suggestions. It is working like this.
It would probably work just as well without send slow now that it is sending one line at a time and waiting for a response.
The last command in the file is 'quit' in order to return to the root prompt, I suppose that could have been hard coded
cmdpath=$1
export cmdpath
expect << 'EXPECT_FEED'
set send_slow {1 .001}
set commandfile [open $env(cmdpath)]
spawn ssh -o NoHostAuthenticationForLocalhost=yes -p $env(PORT_SSH) root#localhost
expect -re "password:"
send -s "password\r"
expect -re $env(PROMPT_ROOT)
send -s ">the name of the process accepting commands<\r"
while { [gets $commandfile line] != -1 } {
expect -re $env(PROMPT)
send -s "$line\r" }
expect -re $env(PROMPT_ROOT)
send "exit\r"
expect eof
EXPECT_FEED

SFTP file transfer between two server and running this script from 3rd server

I have developed a script using TCL expect. The use of the script is - if user runs it from server A, it will check sftp file transfer between server B and server C. Below is my code:
#!/usr/bin/expect -f
lassign $argv 1 2
spawn ping -c 2 -i 3 -W 1 $1
expect {
" 0%" {puts "Source is rechable!"}
" 100.0%" {puts "Source is not rechable.Please restart IPSEC and check!";exit 1}
}
#SSH to remote server $1
spawn ssh -o StrictHostKeyChecking=no root#$1
expect {
"Password:" {send "password\r";exp_continue}
"*#" {send "ssh successful\r";exp_continue}
}
send "\n"
#Creating a file in remote server which will be transferred via sftp
send "touch /tmp/mfile\n"
expect "#"
send "chmod 755 /tmp/mfile\n"
expect "#"
#sftp to server$2
spawn sftp -o StrictHostKeyChecking=no root#$2
expect {
"Password:" {send "Training\r";exp_continue}
"sftp>" {send "sftp successful\r";exp_continue}
}
send "\n"
#sending remote file
send "put /tmp/mfile\n"
send "\n"
sleep 2
send "File send to Remote Server successfully\n"
expect "sftp>"
send "cd /root/\n"
expect "sftp>"
send "rename mfile mfile_1\n"
expect "sftp>"
#sending back the file
send "get mfile_1 /tmp\n"
expect "sftp>"
sleep 2
send "quit\n"
send "exit\n"
The issue is the file is getting transferred to the Server C from the Server B with this code, but the file is not sent back to Server B. I am yet to add other logic in the code but first wanted to check if the basic code works. Any clue regarding file transfer back would be helpful.

How to make expect nested in the bash script properly?

Here is the expect file which can run succesfully.
#!/usr/bin/expect -f
set host vps_ip
set user test
set loginpwd passwd
set adminpwd passwd
set timeout 300
set prompt "#|>|\\\$"
spawn scp /home/wpdatabase_backup.sql $user#$host:/tmp
expect -nocase "password:"
send "$loginpwd\r"
expect eof
spawn ssh $user#$host
expect -nocase "password:"
send "$loginpwd\r"
expect -re $prompt
send "su\r"
expect "assword:"
send "$adminpwd\r"
expect -re $prompt
send "mysql -u root -pxxxx wpdatabase < /tmp/wpdatabase_backup.sql\r"
expect eof
Here is the bash file:
mysqlword="xxxx"
mysqldump -u root -p$mysqlword wpdatabase > /home/wpdatabase_backup.sql
Now i want to make the expect file nested in the bash file because the bash file is more complicated than expect file ,most lines in the bash file were omitted.
code:
#!/usr/bin/bash
mysqlword="xxxx"
mysqldump -u root -p$mysqlword wpdatabase > /home/wpdatabase_backup.sql
/usr/bin/expect <<EOD
set host vps_ip
set user test
set loginpwd passwd
set adminpwd passwd
set timeout 300
set prompt "#|>|\\\$"
spawn scp /home/wpdatabase_backup.sql $user#$host:/tmp
expect -nocase "password:"
send "$loginpwd\r"
expect eof
spawn ssh $user#$host
expect -nocase "password:"
send "$loginpwd\r"
expect -re $prompt
send "su\r"
expect "assword:"
send "$adminpwd\r"
expect -re $prompt
send "mysql -u root -pxxxx wpdatabase < /tmp/wpdatabase_backup.sql\r"
expect eof
<<EOD
An error occur :
spawn scp /home/wpdatabase_backup.sql #:/tmp
ssh: Could not resolve hostname : Name or service not known
lost connection
send: spawn id exp6 not open
while executing
"send "\r""
Quote the terminator:
cat<<'EOD'
set host vps_ip
set user test
spawn scp /home/wpdatabase_backup.sql $user#$host:/tmp
EOD
Result:
set host vps_ip
set user test
spawn scp /home/wpdatabase_backup.sql $user#$host:/tmp
But how to make the output of result run in bash?
/usr/bin/expect <<cat<<'EOD'
set host vps_ip
set user test
spawn scp /home/wpdatabase_backup.sql $user#$host:/tmp
EOD
The code can't run!
This is because in a here-document with an unquoted terminator like EOD, parameter substitution is performed by the shell. You can see that if you replace /usr/bin/expect with cat:
$ cat<<EOD
set host vps_ip
set user test
spawn scp /home/wpdatabase_backup.sql $user#$host:/tmp
EOD
Result:
set host vps_ip
set user test
spawn scp /home/wpdatabase_backup.sql #:/tmp
So, how to avoid parameter substitution? Quote the terminator:
$ cat<<'EOD'
set host vps_ip
set user test
spawn scp /home/wpdatabase_backup.sql $user#$host:/tmp
EOD
Result:
set host vps_ip
set user test
spawn scp /home/wpdatabase_backup.sql $user#$host:/tmp

can't create folder with expect script

I have this script
#!/usr/bin/expect
set DATE [exec date +%F]
spawn sftp user#192.168.0.20
expect "password:"
send "password\n"
expect "sftp>"
send "cd /getfile/$DATE/ \n"
expect "sftp>"
send "lcd /putfile/ \n"
expect "sftp>"
send "mkdir $DATE"
expect "sftp>"
send "lcd /putfile/$DATE \n"
expect "sftp>"
send "mget *.* \n"
expect "sftp>"
send "quit \n"
everything works here, but it does not create the directory. The error is:
cant create directory
I don't know what I'm doing wrong. Any help would be appreciated.
If you want to download files to a local new directory, why not create this directory with expect's exec instead of with sftp?
#!/usr/bin/expect
set DATE [exec date +%F]
exec mkdir "$DATE"
cd "$DATE"
spawn ...

perl program not running thorough automated script until it is executed manually first

i am writing code to automate some steps . First it is required to switch user and then run a perl script. Here is my code
if [ -a /try/Test ]
then
su trial -c ". /try/.profile Test"
expect -c 'spawn try1;
send "3\r";
send "1\r";
send "show\r";
interact';
fi
try1 is my perl program which i am trying to call.This script throws this error
couldn't execute "try1": no such file or directory
while executing
"spawn try1"
but once i do this step manually and then run this script then this script runs without nay error.
I think you've already asked about it (and I did answer, didn't I)?
Here's the basic skeleton (make sure to add error/timeout/unexpected output handling):
# collect password
stty -echo
send_user -- "Password: "
expect_user -re "(.*)\n"
send_user "\n"
stty echo
set pass $expect_out(1,string)
spawn sudo sh;
expect -re ": *$";
send -- "$pass\r"
expect -re "\$ *$";
send "echo SETTING PARAMS\r";
expect -re "\$ *$";
send "echo RUNNING MY COMMAND\r";
expect -re "\$ *$";
interact

Resources