Call "expect" script in C++ process - expect

I realized a shell using expect/spawn and send commands to SCP files from a remote server which send automatically the password when it is needed.
The script works fine on UNIX terminal.
Nevertheless, I tried to use this script throough a C++ process. It has been called by system() or even popen() function without sucess.
This error is returned: "ioctl(raw): I/O error"
Someone could have any clue?
This is my script:
#!/bin/bash
targetHost=$1
password=$2
sourceFile=$3
destRep=$4
expect -c "
spawn /usr/bin/scp -q $targetHost:$sourceFile $destRep
expect -i $spawn_id {
"*password:*" { send -i $spawn_id $password\r\n; interact }
eof { exit }
}
exit
"

The first thing I'd try is to ditch the bash script (there appear to be quoting issues anyway)
#! /usr/bin/env expect -f
foreach {targetHost password sourceFile destRep} $argv break
spawn /usr/bin/scp -q $targetHost:$sourceFile $destRep
expect -i $spawn_id {
"*password:*" { send -i $spawn_id $password\r; interact }
eof { exit }
}
But the real problem is how the stdio channels/pty get inherited by the expect process (I'm not sure of the proper terminology here)

Related

Trying to Create a remote login tool: "interact" in "expect << EOF" does not work

The use case of this script is I have various servers with different ssh keys. I am trying to write a script so when called will log into the specified server. An example of usage would be:
./ServerLogin.sh Server1
I feel that I am fairly close, but The last part of expect interact is tripping me up. This is a simplified version:
#!/bin/bash
ServerName="$1"
case $ServerName in
"Server1") IP="1.2.3.4" ; keyPath="/path/to/key.pem" ; password="password" ; break ;;
*) echo "Server not recognized" ; exit ;;
esac
/usr/bin/expect << EOD
spawn ssh -i $keyPath user#$IP
expect "*.pem': "
send "$password\r"
interact
EOD
The result of this is it logs in and immediately closes. I want for the session to remain interactable.
Any ideas?
The problem is in expect << EOF. With expect << EOF, expect's stdin is the here-doc rather than a tty. But the interact command only works when expect's stdin is a tty. Your answer is one solution. Another solution is to use expect -c if you prefer not using a tmp file.
expect -c "
spawn ssh -i $keyPath user#$IP
expect \"*.pem': \"
send \"$password\r\"
interact
"
After toying around with it some more, I found a working solution. Basically create the expect script and run it. Why it works like this and not in the original question is beyond me. But it works and I will use this for the time being. Thanks everyone for the help!
Working Solution:
#!/bin/bash
ServerName="$1"
case $ServerName in
"Server1") IP="1.2.3.4" ; keyPath="/path/to/key.pem" ; password="password" ; break ;;
*) echo "Server not recognized" ; exit ;;
esac
function WriteExp {
echo "#!/usr/bin/expect"
echo "spawn ssh -i $keyPath ubuntu#$IP"
echo "expect \"*.pem': \""
echo "send \"$password\\r\""
echo "interact"
}
WriteExp > $ServerName.exp
chmod 755 $ServerName.exp
/usr/bin/expect $ServerName.exp
# Cleanup the evidence
rm $ServerName.exp
Using just tcl/expect, instead of a hybrid of shell and it, makes for much cleaner code, without any of the potential issues posed by shell variable interpolation:
#!/usr/bin/expect -f
switch -- [lindex $argv 0] {
Server1 {
set IP 1.2.3.4
set keyPath /path/to/key.pem
set password "password"
}
default {
puts stderr "Server not recognized"
exit 1
}
}
spawn ssh -i $keyPath user#$IP
expect "*.pem': "
send "$password\r"
interact

expect not taking ssh arguments while/for loop [duplicate]

I have list of filenames in a text file,need to transfer each file into server using scp command.I am reading filenames from Read.sh and passing each file name to transfer.sh script but scp is not executing command in this transfer script.If I run transfer.sh alone with passing args its working fine.
List.txt
/home/kittu/file1.txt
/home/kittu/file2.txt
/home/kittu/file3.txt
Read.sh
#!/bin/bash
while read p; do
echo $p
./transfer.sh "$p"
done <List.txt
transfer.sh
#!/usr/bin/expect -f
# get filename from command-line
set f [lindex $argv 0]
spawn scp "$f" user#192.168.4.151:/home/user/Desktop/
expect "password"
send "123\r"
interact
I just run Read.sh as
>./Read.sh
Output:
/home/user/Desktop/file1.txt
spawn scp /home/mbox140/Desktop/test.sh mbox140#192.168.4.151:/home/mbox140/Desktop/videos/
user#192.168.4.151's password:
Its not executing next statement.Please suggest me any solution.
Try the below script , The changes are that the Transfer.sh is wrapped into bash.sh.
and the reason it waits in the password may be because you are expecting a wrong pattern , try "Password" instead of "password" and after send command, expect for the terminal pattern so that the scp finishes
#!/bin/bash
while read p; do
echo $p
{
/usr/bin/expect << EOF
spawn scp $p user#192.168.4.151:/home/user/Desktop/
expect "Password"
send "123\r"
expect "*#*"
EOF
}
done <List.txt

Expect Script Running Remote Script in Background

I have expect script which connects to remote machine and running a script which exist on remote machine however , its takes 15-20 min so i send exit from my expect script. This break my remote scirpt and i cannot run.
Tried to run as a ;
/usr/bin/bash myscript.sh > /dev/null 2>&1 &
however this doesnot work.
my expect script looks like;
........
expect {
-re ".*#.*" { send "/usr/bin/bash myscript.sh > /dev/null 2>&1 &\n"; }
}
expect {
-re ".*#.*" { exp_send "exit \r"; }
}
By the way there is no nohub on machnie.
You need to launch the remote program with nohup so that it will ignore the terminal going away. This is a standard Unix programming trick, and is used because the normal configuration is to kill processes (with the HUP — Hang Up — signal) when the user logs out of the terminal from which they were launched to stop them from otherwise behaving badly.
expect -re ".*#.*"
send "nohup /usr/bin/bash myscript.sh > /dev/null 2>&1 &\r"
expect -re ".*#.*"
send "exit\r"

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

How to get expect -c to work in single line rather than script

Running:
my_machine~/opt/ams/data/ep/success$ expect -c "spawn /usr/bin/scp xmlEventLog_2010-03-22T14-28-36_PFS_1_2.xml adaptive#10.10.12.17:/opt/ams/epf_3_4/xmlEventLog_2010-03-22T14-28-36_PFS_1277900174_2.xml; expect { '*password:*' { send 'ad'\r\n }}"
Does not seem to work as I am still asked for the password.
spawn /usr/bin/scp xmlEventLog_2010-03-22T14-28-36_PFS_1_2.xml adaptive#10.10.12.17:/opt/ams/epf_3_4/xmlEventLog_2010-03-22T14-28-36_PFS_1277900174_2.xml
adaptive#10.10.12.17's password:
If I run it as ascript it runs ok.
my_machine~/opt/ams/data/ep/success$ ./try.sh
spawn /usr/bin/scp xmlEventLog_2010-03-22T14-28-36_PFS_1_2.xml adaptive#10.10.12.17:/opt/ams/epf_3_4/xmlEventLog_2010-03-22T14-28-36_PFS_1277900174_2.xml
adaptive#10.10.12.17's password:
xmlEventLog_2010-03-22T14-28-36_PFS_1_2.xml 100% 13MB 13.2MB/s 00:01
my_machine~/opt/ams/data/ep/success$ cat try.sh
#!/bin/bash
expect -c "
spawn /usr/bin/scp xmlEventLog_2010-03-22T14-28-36_PFS_1_2.xml adaptive#10.10.12.17:/opt/ams/epf_3_4/xmlEventLog_2010-03-22T14-28-36_PFS_1277900174_2.xml
expect {
"*password:*" { send "ad"\r\n; interact }
eof { exit }
}
exit
"
my_machine~/opt/ams/data/ep/success$
I would like to run this in a one line command rather than a script. Has anyone got any ideas?
Thanks in advance
A
I answered my own question below
Got it:
The following code scps a file called Sean_Lilly.zip from my box to another box without entering a password:
expect -c "spawn /usr/bin/scp Sean_Lilly.zip adaptive#10.10.12.17:/opt/ams/epf_3_4/Sean_Lilly.zip; sleep 5; expect -re \"password\"; send \"ad\r\n\"; set timeout -1; expect -re \"100%\";"
I know this can be done by setting passwordless ssh access between the two boxes but I wanted to do it in one command line using expect. Thanks fuzzy lollipop for the inspiration. Note if you run expect -d -c "spawn ... you get excellent debug on what is happening including whether your regex is good enough
You are missing a ; on the first one line example at the end of the last command. And there is a better way to pattern match the password.
try the following:
expect -c "spawn /usr/bin/scp xmlEventLog_2010-03-22T14-28-36_PFS_1_2.xml adaptive#10.10.12.17:/opt/ams/epf_3_4/xmlEventLog_2010-03-22T14-28-36_PFS_1277900174_2.xml; expect -re \".*password.*\"; send 'ad\r\n';"

Resources