Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I'm trying to write a bash script that calls an expect script to establish a master SSH connection to be used for the remaining SSH commands in the bash script.

~/.ssh/config:

ControlMaster auto
ControlPath ~/.ssh/control-%r@%h:%p

upload.sh:

#!/usr/bin/bash

expect -f /home/Dave/bin/ssh.exp

scp /home/Dave/bin/test root@192.168.1.1:/root/test

ssh root@192.168.1.1 "echo 'Test' >> /root/test"

ssh -O exit root@192.168.1.1

ssh.exp:

#!/usr/bin/expect -f

# Enable some diagnostic output
exp_internal 1

spawn /usr/bin/ssh -M -N root@192.168.1.1

expect {
    -re ".*yes.*no.*" {
        exp_send "yes\r"
        exp_continue
    }
    -re ".*password.*" {
        exp_send "OMGSECRET\r"
    }
}

$ bin/upload.sh
spawn /usr/bin/ssh -M -N root@192.168.1.1
parent: waiting for sync byte
parent: telling child to go ahead
parent: now unsynchronized from child
spawn: returns {5212}
Gate keeper glob pattern for '.*yes.*no.*' is ''. Not usable, disabling the performance booster.
Gate keeper glob pattern for '.*password.*' is '*password*'. Activating booster.

expect: does "" (spawn_id exp4) match regular expression ".*yes.*no.*"? (No Gate, RE only) gate=yes re=no
".*password.*"? Gate "*password*"? gate=no
root@192.168.1.1's password:
expect: does "root@192.168.1.1's password: " (spawn_id exp4) match regular expression ".*yes.*no.*"? (No Gate, RE only) gate=yes re=no
".*password.*"? Gate "*password*"? gate=yes re=yes
expect: set expect_out(0,string) "root@192.168.1.1's password: "
expect: set expect_out(spawn_id) "exp4"
expect: set expect_out(buffer) "root@192.168.1.1's password: "
send: sending "OMGSECRET\r" to { exp4 }
mux_client_request_session: read from master failed: Connection reset by peer
root@192.168.1.1's password:
root@192.168.1.1's password:

The SSH connection is being established, but it craps out when I try to reuse it for the SCP command. Why?

Possible final sad edit: Alas it appears cygwin doesn't support multiplexing.

share|improve this question
    
Are you sure that the password is correct and that the server accepts root login with a password? Does it work if you aren't using the expect script? –  Gilles Jan 1 at 23:21
    
Where will the user be typing the password? Why not run the master ssh command in a terminal and make the user enter the password there? –  Gilles Jan 1 at 23:22
    
Do not the password on the command line. It can be snooped by other users if they run ps at the right time. It's safe to pass the password in an environment variable ($::env(PASSWORD) in Tcl). –  Gilles Jan 1 at 23:24
    
I'm sure the password is correct and I can log in from terminal with those credentials. The user enters the password in a web form (PHP), then the server passes the password to the bash script. Since the user doesn't see the terminal window, I can't have them enter the password there. –  Koveras Jan 1 at 23:43
    
@Gilles I removed all mention of PHP from the question. For now, I just want to get this to work from the console. –  Koveras Jan 9 at 6:32

2 Answers 2

Using an Expect script to send a hard-coded plaintext password is generally a Very Bad Idea. If you needs scriptable, passwordless SSH connections, it's far better to use key-pair authentication:

ssh-keygen # and then follow the prompts; don't set a passphrase
ssh-copy-id username@remote.host.example.com

After doing so, you can ssh user@remote.host.example.com without needing to key in your password.

You can still use the control connection muxing set up with the Control directives in ~/.ssh/config, and close the master connection with ssh -O exit user@remote.host.example.com.

You ought also to use ssh's utility of simply running commands remotely - once you have key-pair authentication set up, you can have:

ssh username@remote.host.exameple.com /etc/init.d/dnsmasq restart

in your script and be all set to go.

share|improve this answer
    
Who said password was hard coded? It's prompted from the user (which is btw a requirement). –  Koveras Jan 1 at 20:00
    
In the example bash script, it's metasyntactically set on the first line after the shebang: # Set $user, $addr, $pass, $source and $dest ... –  DopeGhoti Jan 1 at 20:01
    
It's an argument passed to the script though. Is that okay? –  Koveras Jan 1 at 20:01
    
It's still exposing the password in plain text to anyone who manages to read your bash script. Private keys are never set group- or world-readable and allow many layers of additional security. For example, if your key is compromised, you can remove it from the remote host's authorized-keys file and generate a new keypair without having to worry about resetting your password. –  DopeGhoti Jan 1 at 20:04
    
Maybe I should clarify: this script is called from an app that prompts the user for a password. I don't understand at what point it becomes plain text, unless the expect -f upload.exp "$user" "$addr" "$pass" part is logged somewhere with the actual password? –  Koveras Jan 1 at 20:06

if this is still your question:

"The SSH connection is being established, but it craps out when I try to reuse it for the SCP command. Why?"

This happens because you are starting a seperate shell with your expect script. Your ssh session is bound to this shell and if your script ends the shell also end and your ssh session dies.

Sorry but I don't have a solution in a nutshell for this problem.

share|improve this answer
    
This does not provide an answer to the question. To critique or request clarification from an author, leave a comment below their post - you can always comment on your own posts, and once you have sufficient reputation you will be able to comment on any post. –  Karlson Apr 29 at 15:54

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.