I want to use expect
to run a simple command cat /tmp/id_rsa.pub
over ssh.
In a shell, I can run this wo problem, (with manually put in the password)
ssh root@localhost 'cat /tmp/id_rsa.pub'
I want to automate this with expect
. My expect
script is,
#!/usr/bin/expect
eval spawn ssh root@localhost 'cat /tmp/id_rsa.pub'
expect "password:"
send "123456"
expect eof
It throws error bash: cat /tmp/id_rsa.pub: no such file or directory
. it looks very strange to me. What could be the possible cause?
Edit: after some testing, I find this is common, not only in the case of cat
. If the argument to spawned command is with space (even if it's in the quotes), it will have problem. For example, replacing cat /tmp/id_rsa.pub
with other commands with spaces, like
eval spawn ssh root@localhost 'which java'
it complains with bash: which java: command not found
. But if replacing that with pwd
, like
eval spawn ssh root@localhost 'pwd'
it work fine.
The spawn command is used to start a script or a program like the shell, FTP, Telnet, SSH, SCP, and so on. The remaining lines are the Expect script that interacts with our shell script. The last line if the end of file which means the end of the interaction.
Normally you would read the command line arguments as shown below. $ cat print_cmdline_args. exp #!/usr/bin/expect puts 'argv0 : [lindex $argv 0]'; puts 'argv1 : [lindex $argv 1]';
The command exp_continue allows expect itself to continue executing rather than returning as it normally would. By default exp_continue resets the timeout timer. The -continue_timer flag prevents timer from being restarted. (See expect for more information.)
Single quotes ('
) have no special meaning to Expect, unlike sh and other compatible shells.
This means that your statment
spawn ssh root@localhost 'cat /tmp/id_rsa.pub'
is parsed into the following words:
spawn
ssh
root@localhost
'cat
- not until the other single quote./tmp/id_rsa.pub'
The usage in sh is to group this to a single argument. In Tcl you could either use double quotes ("
) or curly brackets ({}
). Inside double quotes, Tcl variables will be substituted, while the content inside {}
is passed without any substitution1.
tl;dr The Expect/Tcl equivalent of sh's '
are {}
.
1 A \
before a newline will still be substitued.
As Johannes said, using '
doesn't work.
I had a similar problem, but I wanted to execute more commands and then still get a login shell. I managed to make it work with "
:
expect -c "
set timeout 5;
spawn ssh -XY $user@$host -t \"cat /etc/motd; bash -l\"
expect {
-re \"^Warning.*\" {exp_continue}
-re \"^.*sword: \" {send \"${PASSWORDS[$user]}\r\"; interact}
}
"
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With