I've written a little script to supply a password to sshfs, but for some reason sshfs isn't grabbing the password. Any pointers? (PS I know ssh keys are better/safer, but politics where I work prevents key based authentication being setup on the target server - sigh... ).
#!/usr/bin/expect
# NOT WORKING!!
exp_internal 1
spawn sshfs server:/export/pc_storage /home/sonia/mnt/server
expect {
"assword:" {
send "secret\r\r"
send_user "\n"
}
timeout {
send_user "timed out!\n"
}
}
To terminate the password, I've tried \r \n \r\r - none work.
Debugging output, showing that password prompt is triggering:
spawn sshfs server:/export/pc_storage /home/sonia/mnt/server
parent: waiting for sync byte
parent: telling child to go ahead
parent: now unsynchronized from child
spawn: returns {17532}
expect: does "" (spawn_id exp6) match glob pattern "assword:"? no
pcuser#server's password:
expect: does "pcuser#server's password: " (spawn_id exp6) match glob pattern "assword:"? yes
expect: set expect_out(0,string) "assword:"
expect: set expect_out(spawn_id) "exp6"
expect: set expect_out(buffer) "pcuser#server's password:"
send: sending "secret\r\r" to { exp6 }
% uname -a
Linux zapote 2.6.38-10-generic-pae #46-Ubuntu SMP Tue Jun 28 16:54:49 UTC 2011 i686 i686 i386 GNU/Linux
% sshfs -V
SSHFS version 2.2
FUSE library version: 2.8.4
fusermount version: 2.8.4
using FUSE kernel interface version 7.12
SOLVED:
(I can't post an answer as I don't have 100 points - double sigh)
I need to fix this up a bit... For example I hard coded PS1 in my .bashrc to "bash_prompt" (I use zsh by default).
#!/usr/bin/expect
# FIX: get homedir from env, set bash prompt somehow...
set timeout 30
spawn /bin/bash
expect "bash_prompt"
send_user "Shell spawned.\n"
send -- "sudo umount /home/sonia/mnt/server &> /dev/null\r"
expect "bash_prompt"
send -- "sshfs server:/export/pc_storage /home/sonia/mnt/server\r"
expect {
"assword:" {
send "secret\r"
send_user "\n"
}
timeout {
send_user "timed out!\n"
}
}
expect "bash_prompt"
Rather than use Expect, you can just supply the password directly.
Try this:
echo your-password | sshfs server:/export/pc_storage /home/sonia/mnt/server -o password_stdin
Not sure if you can make this work with your password policies, but its worth a shot.
I need to fix this up a bit... For example I hard coded PS1 in my .bashrc to "bash_prompt" (I use zsh by default).
#!/usr/bin/expect
# FIX: get homedir from env, set bash prompt somehow...
set timeout 30
spawn /bin/bash
expect "bash_prompt"
send_user "Shell spawned.\n"
send -- "sudo umount /home/sonia/mnt/server &> /dev/null\r"
expect "bash_prompt"
send -- "sshfs server:/export/pc_storage /home/sonia/mnt/server\r"
expect {
"assword:" {
send "secret\r"
send_user "\n"
}
timeout {
send_user "timed out!\n"
}
}
expect "bash_prompt"
\r\r does not seem right. Have you tried \r\n?
Related
I have the following vm's running on vmhost:
[root#server ~]# virsh list
Id Name State
----------------------------------------------------
2 vm1 running
3 xw-4530c running
4 optaserver running
I'm trying to fetch the name of the virtual machine starting with "xw" with an expect script, but it gives me all kinds of errors.
I've replaced single quotes with curly brackets... because of... I think tcl? :)
What is wrong with the set command below?
The purpose with the script is to fetch the name, to run virsh reboot $xw ...
spawn ssh -o StrictHostKeyChecking=no $user#$host
expect "password:"
send "$password\r"
expect -re $prompt
send "virsh list\r"
expect -re $prompt
set xw [exec virsh list | grep xw | awk { { print \$2 } } ]
puts $xw
expect -re $prompt
For awk, the "outer" braces are Tcl's non-interpolating quotes: they already prevent variable substitution, so the awk $ does not need to be escaped.
However, exec is trying to launch virsh on your local machine not on the remote host.
This is where you need the expect_out variable which buffers the text going to and fro the spawned process.
send "virsh list\r"
expect -re $prompt
regexp -expanded -- { \m xw \S+ } $expect_out(buffer) xw
puts $xw
read about expect_out in your expect man page
regexp is a Tcl command.
\m is a regex assertion that matches an empty string at the start of a word;
\S is a non-space character
Thanks to Donal's suggestion:
send "virsh list\r"
set xw "not found"
expect {
-re {\m(xw\S+)} { # using capturing parentheses
set xw $expect_out(1,string)
exp_continue ;# continue to expect the prompt
}
-re $prompt
}
puts $xw
The task is to remotely reboot ip-phones every night.
sshpass:
sshpass -p 12345678 ssh -o StrictHostKeyChecking=no admin#192.168.2.1 reboot
In response: Connection to 192.168.2.1 closed by remote host.
In addition, the phone, as usual in CLI, asks to answer y.
expect:
COMM="
log_file debug.log
exp_internal 1
set timeout 5
spawn ssh admin#192.168.2.1
expect \"password:\"
send \"12345678\r\"
sleep 5
expect \"*>\"
send \"reboot\r\"
sleep 5
expect \"*y/N*\"
send \"y\r\"
expect eof
"
expect -c "$COMM"
When I do it myself from the console, everything is ok. Using cron, in debug.log, for some reason, after authorization on the device, the line for entering the expect \"*>\" command does not appear. Even if we remove expect \"*>\" and just use send, there is no reaction.
I ask for hints in solving the problem or suggest another solution. Thanks.
different debug.log between console and cron
console:
expect: does " \r\n" (spawn_id exp5) match glob pattern "*>"? no
^[[1;36m
expect: does " \r\n\u001b[1;36m\r\n\t" (spawn_id exp5) match glob pattern "*>"? no
Grandstream GXV3240 Command-Line Interface Copyright 2017
Grandstream Networks, Inc.
^[[0m
GXV3240>
expect: does " \r\n\u001b[1;36m\r\n\tGrandstream GXV3240 Command-Line Interface Copyright 2017\r\n\t\tGrandstream Networks, Inc.\r\n\u001b[0m\r\nGXV3240> " (spawn_id exp5) match glob pattern "*>"? yes
expect: set expect_out(0,string) " \r\n\u001b[1;36m\r\n\tGrandstream GXV3240 Command-Line Interface Copyright 2017\r\n\t\tGrandstream Networks, Inc.\r\n\u001b[0m\r\nGXV3240>"
expect: set expect_out(spawn_id) "exp5"
expect: set expect_out(buffer) " \r\n\u001b[1;36m\r\n\tGrandstream GXV3240 Command-Line Interface Copyright 2017\r\n\t\tGrandstream Networks, Inc.\r\n\u001b[0m\r\nGXV3240>"
send: sending "reboot\r" to { exp5 }
cron:
expect: does " " (spawn_id exp4) match glob pattern "*>"? no
^[[1;36m
Grandstream GXV3240 Command-Line Interface Copyright 2017
Grandstream Networks, Inc.
^[[0m
^[[6n
expect: does " \r\n\u001b[1;36m\r\n\tGrandstream GXV3240 Command-Line Interface Copyright 2017\r\n\t\tGrandstream Networks, Inc.\r\n\u001b[0m\r\n\u001b[6n" (spawn_id exp4) match glob pattern "*>"? no
expect: timed out
send: sending "reboot\r" to { exp4 }
expect: does " \r\n\u001b[1;36m\r\n\tGrandstream GXV3240 Command-Line Interface Copyright 2017\r\n\t\tGrandstream Networks, Inc.\r\n\u001b[0m\r\n\u001b[6n" (spawn_id exp4) match glob pattern "*y/N*"? no
expect: timed out
I don't know if this will fix your problem: without seeing the debug output it's impossible to say.
When you're embedding expect code into a shell script, I recommend using a heredoc -- that makes the quoting much simpler
expect <<'END_EXPECT'
log_file debug.log
exp_internal 1
set timeout 10
spawn ssh admin#192.168.2.1
expect "password:"
send "12345678\r"
expect "*>"
send "reboot\r"
expect "y/N"
send "y\r"
expect eof
END_EXPECT
I increased the timeout and removed the sleeps -- generally sleep is not required in an expect script if you have the patterns right.
Reboot Grandstream VoIP terminal – script solution:
#!/bin/bash
ip_adr="192.168.0.2"
pass="admin"
sshpass -p ${pass} ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no admin#${ip_adr} << EOF
reboot
exit
EOF
unset pass
I am new to using expect. I try the code below and it fails:
expect -c 'spawn ssh user#host < script.ecma3
expect Password: ;
send "******\r";
send "exit\r";'
anyone could clarify
This might help you
#!/usr/bin/expect
set timeout -1
spawn -noecho bash -c "ssh -t user#host '<here-comes-your-command>'"
expect {
-re ".*assword.*" {
exp_send "$env(PASS_WORD)\n"
exp_continue
}
}
Note :-
1) Copy script to remote host before running it. passing whole script is not good thing to do.
2) to access enviornment variables in expect , $env(variable_name) is used.
In above example , for $PASS_WORD, i used $env(PASS_WORD) .
I'm having some trouble with expect.
I'm trying to ssh onto another machine and then create a directory on that machine.
Right now this is what my code looks like:
spawn ssh username#ipAddress
expect "password"
send "password"
file mkdir directoryName
That code is giving me a "permission denied".
When I try replacing
file mkdir directoryName
with
send "mkdir directoryName"
There's no error, but it doesn't make a file.
Thanks.
This might help you :-
#!/usr/bin/expect
set timeout -1
spawn -noecho bash -c "ssh username#serveraddress 'cd /user/bill/work;<your=command>'"
expect {
-re "assword:"{
send "mypassword/r"
}eof{
wait
}
You must send the command inside ssh as it will run on remote machine.
Explanation for above script :-
set timeout -1will set this loop in infinite (but it will exit once spawn process is finished.
-re will match regex for assword:
eof will wait until spawn is finish.
After sending mkdir command, wait for eof to happen.
send "mkdir directoryName\r"
expect eof
I have written an Ansible playbook which prompts me to enter password interactively for SSH and SUDO like below.
$ ansible-playbook -i test --limit dev app_name.yml -vv --tags=stop
SSH password:
SUDO password[defaults to SSH password]:
There are various options available with Ansible like defining password in ansible_ssh_password under group_vars but it don't seem to work for me since I can't have sshpass installed in my target server nor I am allowed to make any changes to my sudoers file.
I tried to execute ansible-playbook from a little expect script below
#!/usr/bin/expect -f
set password PASSWORD
set where_to_execute [lindex $argv 0]
set which_app_to_execute [lindex $argv 1]
set what_to_execute [lindex $argv 2]
send "ansible-playbook -i test --limit $where_to_execute $which_app_to_execute -vv --tags=$what_to_execute \r"
expect "SSH password:"
send "$password \r"
expect "SUDO password*"
send "$password \r"
expect "$"
send "exit \r"
Unfortunately this is also not working may be because SSH process is not spawned by expect. Did anyone try this method and got things working. Please suggest. Thanks.
The problem with your expect scripts is that you aren't actually running the ansible command there (or any command for that matter).
You use
send "ansible-playbook -i test --limit $where_to_execute $which_app_to_execute -vv --tags=$what_to_execute \r"
which sends that string to ... nowhere as far as I know. There's nowhere for it to go.
What you want to be doing is spawning that ansible command and then using expect to communicate with it.
Something like this:
spawn ansible-playbook -i test --limit $where_to_execute $which_app_to_execute -vv --tags=$what_to_execute
You may also want to set the timeout value if the ansible command can take a little while (to prevent expect from killing it when it doesn't return quickly enough).
It works for me using the python implementation of expect. pexpect
install pexpect using pip: pip install pexpect
You can use this code as an workaround for your expect script:
#!/usr/bin/python
import pexpect
def main(args):
#Setup variables
password, where, which, what = args
cmd = "ansible-playbook -i test --limit %s %s -vv --tags=%s" % (where, which, what)
child = pexpect.spawn(cmd)
child.sendline(password)
child.expect('SSH password:')
child.sendline(password)
child.expect('SUDO password*')
child.expect(pexpect.EOF)
print child.before
if __name__ == '__main__':
main(sys.argv[1:])
This is the most simple example but it's working fine for me.
./myscript.py mypassword dev app_name.yml stop
As #Etan Reisner pointed out, the main difference between your code that isn't working and my pexpect code is the spawn ansible command. The above code on expect also works fine:
#!/usr/bin/expect -f
spawn /usr/bin/ansible -m ping myserver --ask-pass
expect "SSH password:"
send "mypassword\r"
expect "$ "