I want to use an expect script to run an SSH command on Heroku dynos (for example: Get IP of Heroku dynos)
The exact output when logging into the dyno is:
▸ heroku-cli: update available from 6.12.9 to 6.14.21-d83c94b
Establishing credentials... done
Connecting to <dyno> on ⬢ <app>...
~ $
I'm sure the first line would be gone after updating. It takes several seconds for this authentication/login to actually occur.
A simple expect script could go like this:
#!/usr/bin/expect
spawn "./ssh_into_heroku"
expect "xxxx"
send "my_command"
I've tried expect "~ $" { send "my_cmd" } and expect "~ $ " { send "my_cmd" } but neither are working and I have no idea how to debug this.
What would go in the "expect" portion to make this work?
You're waiting for the prompt that ends with a space, a dollar sign and (I'm guessing) another space. You would use this:
set prompt_regex { \$ $}
expect -re $prompt_regex
Related
I have a task of creating docker container and working through its lifecycle. To automate it I am using shell with expect as cloud foundry cli is interactive
below is my code:
#!/usr/bin/expect -f
spawn cf login -a <api url>
#set timeout 30
expect "Email>"
send "email id\r"
expect "Password>"
send "passw0rd"
expect -exact ">"
send "2\r"
Till above line, the code is working as expected.From the last 2 lines above it can be seen that, I have to enter 2 at '>'. After this the $ prompt like below is shown which ends with '$':
expect "trishal#trishal-VirtualBox:~/PycharmProjects/Trishal- VC/containers$"
send "cf ic init"
Now, after coming on '$' prompt, I expect the code to accept 'cf ic init' which is a command to initialize the work space. Its not accepting, the output stays at '$' prompt itself and doesn't proceed. I had also tried below:
expect -exact "$"
send "cf ic init"
no luck
screen remains at
trishal#trishal-VirtualBox:~/PycharmProjects/Trishal-VC/containers$
expect -exact "$" will work for sure to match the literal dollar. All send commands should be sent with \r which represents the 'Enter' key. After the last command, add expect eof if your program will complete at that time and no further interaction required.
I could really use some help. I'm still pretty new with expect. I need to launch a scp command directly after I run sftp.
I got the first portion of this script working, my main concern is the bottom portion. I really need to launch a command after this command completes. I'd rather be able to spawn another command than, hack something up like piping this with a sleep command and running it after 10 s or something weird.
Any suggestions are greatly appreciated!
spawn sftp user#host
expect "password: "
send "123\r"
expect "$ "
sleep 2
send "cd mydir\r"
expect "$ "
sleep 2
send "get somefile\r"
expect "$ "
sleep 2
send "bye\r"
expect "$ "
sleep 2
spawn scp somefile user2#host2:/home/user2/
sleep 2
So i figured out I can actually get this to launch the subprocess if I use "exec" instead of spawn.. in other words:
exec scp somefile user2#host2:/home/user2/
the only problem? It prompts me for a password! This shouldn't happen, I already have the ssh-keys installed on both systems. (In other words, if I run the scp command from the host I'm running this expect script on, it will run without prompting me for a password). The system I'm trying to scp to, must be recognizing this newly spawned process as a new host, because its not picking up my ssh-key. Any ideas?
BTW, I apologize I haven't actually posted a "working" script, I can't really do that without comprimising the security of this server. I hope that doesn't detract from anyones ability to assist me.
I think the problem lies with me not terminating the initially spawned process. I don't understand expect enough to do it properly. If I try "close" or "eof", it simply kills the entire script, which I don't want to do just yet (because I still need to scp the file to the second host).
Ensure that your SSH private key is loaded into an agent, and that the environment variables pointing to that agent are active in the session where you're calling scp.
[[ $SSH_AUTH_SOCK ]] || { # if no agent already running...
eval "$(ssh-agent -s)" # ...then start one...
ssh-add /path/to/your/ssh/key # ...load your key...
started_ssh_agent=1 # and flag that we started it ourselves
}
# ...put your script here...
[[ $started_ssh_agent ]] && { # if we started the agent ourselves...
eval "$(ssh-agent -s -k)" # ...then clean up nicely when done.
}
As an aside, I'd strongly suggest replacing the code given in the question with something like the following:
lftp -u user,123 -e 'get /mydir/somefile -o localfile' sftp://host </dev/null
lftp scp://user2#host2 -e 'put localfile -o /home/user2/somefile' </dev/null
Each connection handled in one line, and no silliness messing around with expect.
I'm trying to automate a startup of a specific service with bash
When the service is started with init.d (/etc/init.d/openvpn.custom) it is promting for username and then password - and then it connects
The auth-user-pass from-file is not possible with the installed version, and it cannot be upgraded because of dependencies
So i'm trying to write a simple bash scripts that executes the init.d script, sleeps for a bit, inputs the username, returns, sleeping a bit, inputting the password - you'll get the flow.
like http://pastebin.com/qWHX7Di5
I've experimented with echo, but it doesent seem to work
This is for a rather legacy firewall i'm asked to keep connected.
Is this even possible?
I would use expect instead of bash. You can still call it from within bash if you need to do other tasks as well.
In expect, the script would be something like the following (untested):
#!/usr/bin/expect -f
set username "username"
set password "password"
spawn /etc/init.d/openvpn.custom start
expect "Username:"
send "$username\r"
expect "Password:"
send "$password\r"
expect eof
You'd want to change the expect "Username:" & expect "Password:" lines to match the actual login prompts that are output by your init.d script.
See the expect man page for further details.
You can try using a here-doc:
/path/to/init.d << END
$username
$password
END
I am writing a script to run ssh so as to login a remote host, after all the operation is done, I type exit and log off. But I want the script to continue running and write log on the local host. The script is something like:
#!/usr/bin/expect
spwan ssh qwerty#remote_host
expect {
"password:" {
send "123123\r"
}
}
interact;
send "echo $(date) >> login_history.log\r"
But the last command "send ..." always failed with the error message like
"send: spawn id exp4 not open ..."
When I log off from the remote host, can the expect script continue to work as it is running on the local host?
YES, processing can continue after an [interact].
Short answer: change the last {send ...} to {exec date >> login_history.log}
There are several concepts you'll want to understand to achieve the control flow you're after. First, http://www.cotse.com/dlf/man/expect/interact_cmd_desc.htm provides a succinct synopsis and example of intermediate [interact] use.
Second: why did you see the message "... spawn id ... not open ..."? Because the spawn id is not open. The script you wrote said, in effect, "interact, then, after interact is over, send a new command to the ssh process." If you've already logged out, then, of course that id for a defunct process is no longer available.
Third: how do you achieve what you want? I'm unsure what you want. It sounds as though it would be enough for you simply to transform the [send] as I've described above. How does that look to you?
This question already has answers here:
Using expect to pass a password to ssh
(6 answers)
Closed 5 years ago.
So I wanted to automate my SSH logins. The host I'm with doesn't allow key authentication on this server, so I had to be more inventive.
I don't know much about shell scripting, but some research showed me the command 'expect' and some scripts using it for exactly this purpose. I set up a script and ran it, it worked perfectly to login.
#!/usr/bin/env expect -f
set password "my_password"
match_max 1000
spawn ssh -p 2222 "my_username"#11.22.11.22
expect "*?assword:*"
send -- "$password\r"
send -- "\r"
expect eof
Initially, it runs as it should.
Last login: Wed May 12 21:07:52 on ttys002
esther:~ user$ expect expect-test.exp
spawn ssh -p 2222 my_username#11.22.11.22
my_username#11.22.11.22's password:
Last login: Wed May 12 15:44:43 2010 from 20.10.20.10
-jailshell-3.2$
But that's where the success ends.
Commands do not work, but hitting enter just makes a new line.
Arrow keys and other non-alphanumeric keys produce symbols like '^[[C', '^[[A', '^[OQ' etc.[1]
No other prompt appears except the two initially created by the expect script.
Any ignored commands will be executed by my local shell once expect times out.
An example:
-jailshell-3.2$ whoami
ls
pwd
hostname
(...time passes, expect times out...)
esther:~ user$ whoami
user
esther:~ ciaran$ ls
Books Documents Movies Public
Code Downloads Music Sites
Desktop Library Pictures expect-test.exp
esther:~ ciaran$ pwd
/Users/ciaran
esther:~ ciaran$ hostname
esther.local
As I said, I have no shell scripting experience, but I think it's being caused because I'm still "inside of" expect, but not "inside of" SSH. Is there any way to terminate expect once I've logged in, and have it hand over the SSH session to me?
I've tried commands like 'close' and 'exit', after " send -- "\r" ". Yeah, they do what I want and expect dies, but it vindictively takes the SSH session down with it, leaving me back where I started. What I really need is for expect to do its job and terminate, leaving the SSH session back in my hands as if I did it manually.
All help is appreciated, thanks.
[1] I know there's a name for this, but I don't know what it is. And this is one of those frightening things which can't be googled, because the punctuation characters are ignored. As a side question, what's the story here?
I think your problem has been solved here before:
Using expect to pass a password to ssh
The command you're looking for is interact. It hands the control over to you/your keyboard.
I've used a similar script to autologin.
I used "interact" and I removed "expect eof". By doing this, I can get the screen back so that I can enter commands by hand.
expect "?assword: "
send -- "$password\r"
expect "$"
interact
putting it all together, log you in and leave you on the command line exactly as though you typed it manually
#!/usr/bin/expect -f
set ip "127.001.001.001"
set password "xxyykkx"
spawn ssh $ip -l root
expect "?assword:"
send "$password\r"
interact