LinuxQuestions.org
Help answer threads with 0 replies.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - Newbie
User Name
Password
Linux - Newbie This Linux forum is for members that are new to Linux.
Just starting out and have a question? If it is not in the man pages or the how-to's this is the place!

Notices


Reply
  Search this Thread
Old 02-13-2012, 11:44 AM   #1
newbc
LQ Newbie
 
Registered: Feb 2012
Posts: 8

Rep: Reputation: Disabled
Question on expect and arguments


I've got an expect script working when I set the variable for the password inside the script, but I can't figure out how to provide the password as an argument. Here is the boiled down problem:

Script:

#!/usr/bin/expect
set pass [lindex $argv 0]

send "$pass\r"

Usage:

./myScript.sh testPassword

Output:

- it does nothing and simply returns the prompt. This is to highlight the issue, it also fails when used in the actual context of - ;"password:" {send "$pass\r";exp_continue};}

However, if I change the send command to be this:

send "$pass"

it correctly repeats the password to the prompt. It seems to dislike the "\r" escape sequence for some reason. I've googled many examples of this in the past few days and I've tried many combinations of things but can't seem to find what simple and obvious thing I am missing. Would really appreciate any help you can offer!

Also - why can't I just use #!/usr/bin/expect AND #!/bin/bash in the same script? Is expect also a shell and that conflicts with bash or something? I've only been through one scripting book so far but it really didn't cover the # operator very well.
 
Old 02-13-2012, 01:47 PM   #2
Dark_Helmet
Senior Member
 
Registered: Jan 2003
Posts: 2,786

Rep: Reputation: 374Reputation: 374Reputation: 374Reputation: 374
There's not problem with your usage--not technically anyway.

It's that you don't understand what '\r' represents. When your script executes:
Code:
send "$pass\r"
The value of the variable 'pass' is written to standard output. The '\r' acts to send an Enter/Return key press. Specifically, the effect is to move the output cursor to the beginning of the current line.

Because the cursor has been moved to the beginning of the line, when the script ends, your bash prompt is written on top of the value of 'pass'.

The reason the command works without the '\r' is because the bash prompt is written immediately after the value of 'pass' -- the cursor is not moved.

Quote:
Also - why can't I just use #!/usr/bin/expect AND #!/bin/bash in the same script? Is expect also a shell and that conflicts with bash or something? I've only been through one scripting book so far but it really didn't cover the # operator very well.
You misunderstand. The '#' is not an operator. It truly just means that the text following the '#' is a comment (in most scripting languages). The shebang line (e.g. '#!/bin/bash') is a special form of comment that must be placed (if present) at the beginning of the script file to identify what program should be used to interpret all the commands in the file.

You can have a bash script launch an expect script. You can have an expect script launch a bash script. Just write the pieces of the task(s) in separate files. Launch the pieces as necessary.

As an advanced approach--'advanced' not meaning 'better' but simply not normally used--can embed expect scripts within a bash script using 'here' documents. For instance:
Code:
#!/bin/bash

cat << EOF | /usr/bin/expect

spawn "sudo ls"

expect "password: "
send "mypassword\r"

interact
EOF

echo "sudo ls command completed"
The above uses the fact that the cat command will echo everything between the cat command and the EOF, then pipes all the text to /usr/bin/expect, which then interprets the text as an expect script. This allows you to use bash variables directly in the expect script without dealing with command line options. However, there can be some tricky syntax situations where bash does some substitutions in the cat text before sending it to expect.
 
Old 02-13-2012, 03:19 PM   #3
newbc
LQ Newbie
 
Registered: Feb 2012
Posts: 8

Original Poster
Rep: Reputation: Disabled
I don't understand why a carriage return/line feed, or as you say "Enter/Return" key press would move the cursor to the beginning of the current line. It should move it to the beginning of the next line?

I'm sorry, I thought that smaller example would make the question easier to answer - looks like I was wrong there haha Ok, here's my full script and output. Hopefully this will be able to convey the full picture better:

********************
SCRIPT:


#!/usr/bin/expect
set pass [lindex $argv 0]
set user "myUsername"
set src "mySourceFile.name"
set dest "/myRemoteDirectory/myDestFile.name"

spawn scp -o StrictHostKeyChecking=no $src $user@myhost:$dest
expect {
;"password:" {send "$pass\r";exp_continue};}

********************
OUTPUT:
[user@localHost ~]$ ./copyFile.sh myPassword
spawn scp -o StrictHostKeyChecking=no .bashrc user@remoteHost:/myRemoteDirectory/myDestFile.name
user@remoteHost's password:
Permission denied, please try again.
user@remoteHost's password:
Permission denied, please try again.
user@remoteHost's password:
Permission denied (publickey,gssapi-with-mic,password).
lost connection

********************

Now, when I change this line:

- set pass [lindex $argv 0]

to this:

- set pass actualPassword

It works perfectly fine and I get the following output. Any ideas?

********************
[user@localHost ~]$ ./copyFile.sh
spawn scp -o StrictHostKeyChecking=no .bashrc user@remoteHost:/myRemoteDirectory/myDestFile.name
user@remoteHost's password:
.mySourceFile.name
 
Old 02-13-2012, 04:12 PM   #4
Dark_Helmet
Senior Member
 
Registered: Jan 2003
Posts: 2,786

Rep: Reputation: 374Reputation: 374Reputation: 374Reputation: 374
Quote:
I don't understand why a carriage return/line feed, or as you say "Enter/Return" key press would move the cursor to the beginning of the current line. It should move it to the beginning of the next line?
No. The '\r' is somewhat of a historical carryover from the days where typewriters were prevalent. You read '\r' as 'carriage return' -- 'carriage' being the mechanism that moved from left to right as letters were typed and 'return' to move the carriage back to the initial left position. It was common to want the carriage to return to the left (for corrections) without advancing to the next line.

There is another character '\n' which is read as 'new line' or 'newline'. This character does what you are probably thinking. In Linux, the newline not only scrolls to the next line but also performs a 'carriage return' by placing the cursor at the beginning of that new line. On Windows/DOS systems, the newline simply advances the line, without the carriage return. The effect on Windows/DOS for using '\n' only (and not '\r\n') is text that looks like:
Code:
This is some
            thing you might see.
To verify, try it yourself:
Code:
#!/usr/bin/expect
send "01234567890123456789012345678901234567890123456789\r"
As long as your bash prompt is less than 50 characters long, you should still see some of the number printed after your bash prompt returns.

Compared with:
Code:
#!/usr/bin/expect
send "01234567890123456789012345678901234567890123456789\n"
Which should show the full range of numbers with your bash prompt on the next line.

There are reasons why the distinction is still maintained. For instance, sometimes you want to re-write a line with updated information once every second. In such a case, a '\r' is needed instead of '\n'. You see this kind of thing all the time with console-based progress bars.

As for your script, I'm not an expect expert, but I would guess that '$argv 0' does not contain what you expect. It may hold the newline/carriage return from when you entered the command. I'll have to experiment a little to find out.

EDIT:
As a follow-up, does your password contain any special characters? For instance an asterisk '*'? If it uses special characters, you need to make sure that bash is not doing any wildcard substitution/matching. If your password does contain special wildcard characters, I would suggest enclosing your password in double quotes at the command line:
Code:
./copyFile.sh "myPassword"

Last edited by Dark_Helmet; 02-13-2012 at 05:34 PM.
 
Old 02-13-2012, 07:48 PM   #5
chrism01
LQ Guru
 
Registered: Aug 2004
Location: Sydney
Distribution: Rocky 9.2
Posts: 18,360

Rep: Reputation: 2751Reputation: 2751Reputation: 2751Reputation: 2751Reputation: 2751Reputation: 2751Reputation: 2751Reputation: 2751Reputation: 2751Reputation: 2751Reputation: 2751
Nice explanation by Dark_Helmet; see also the ASCII table codes 10 & 13 (decimal) http://www.asciitable.com/
 
Old 02-13-2012, 08:47 PM   #6
newbc
LQ Newbie
 
Registered: Feb 2012
Posts: 8

Original Poster
Rep: Reputation: Disabled
I've been using lf/cr 10/13 in code for years without realizing what they were actually doing. Great explanation indeed, thank you for that

About the script - after running the first script (just the output) again I could see that it was the special characters. Double quotes didn't do it, but single quotes did. Great catch! Thank you so much for your help, I have a lot to learn about Linux
 
Old 02-13-2012, 09:17 PM   #7
Dark_Helmet
Senior Member
 
Registered: Jan 2003
Posts: 2,786

Rep: Reputation: 374Reputation: 374Reputation: 374Reputation: 374
Quote:
Originally Posted by newbc View Post
About the script - after running the first script (just the output) again I could see that it was the special characters. Double quotes didn't do it, but single quotes did. Great catch! Thank you so much for your help, I have a lot to learn about Linux
Glad I could help. And if I may be so bold, from what you said, it sounds as though your password contains a '$' somewhere. The '$' would be interpreted by bash as the beginning of a shell variable reference. So bash would attempt to substitute the value of the variable for the reference--all before invoking expect. More than likely, the accidental variable reference evaluated to an empty string. Empty string or not, it mucked up what expect saw.

If you want to use a literal $ on the command line, you can do what you discovered: enclose the text in single quotes (which prevents bash from doing any substitutions in the text), or you can escape the $ with a backslash. For instance:
Code:
./copyFile.sh myPa\$\$word
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
A question about passing arguments into a pthread in C... trist007 Programming 6 12-27-2011 02:32 PM
EXPECT/TCL: the "source" command and passing arguments qmqmqm Programming 4 04-02-2009 05:36 PM
A question about expect. imjoe Programming 1 10-26-2005 04:42 AM
expect question deiussum Programming 0 08-05-2005 03:51 PM
expect question reitzell Programming 1 11-20-2004 09:03 AM

LinuxQuestions.org > Forums > Linux Forums > Linux - Newbie

All times are GMT -5. The time now is 05:01 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration