fetch variable in expect - awk

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

Related

Pass arguments for SQL statement in a shell file from another shell file through ssh command

I am passing command line arguments to a shell file i.e assignRole.sh which contains an SQL command which will use these arguments like below
ssh -o StrictHostKeyChecking=no -T $key < /oracle/oracle_user/makhshif/./assignRole.sh name open_mode >> /oracle/oracle_user/dftest.txt
This gives me error and does not accept arguments of name and open_mode and gives error, but if I execute the statement outside of ssh command like:
/oracle/oracle_user/makhshif/./assignRole.sh name open_mode
This runs fine
What is the problem with ssh command and how should I adjust these parameters so these can be accepted for the shell script assignRole.sh
< /oracle/oracle_user/makhshif/./assignRole.sh
This commands sends a content of that file to stdin. So obviously it can't process variables that you haven't send to remote machine. Just preprocess your script or create a script on remote machine and call it with arguments
Though it's even easier to pass variables like this:
ssh -o StrictHostKeyChecking=no -T $key "var1=$var1 var2=$var2" < /oracle/oracle_user/makhshif/./assignRole.sh name open_mode >> /oracle/oracle_user/dftest.txt
For example my function for executing update scripts on all cluster nodes:
# functions:
ssh_exec(){
local DESCR="$1"; shift
local SCRIPT="$1"; shift
local hosts=("$#")
echo =================================================
echo = $DESCR
echo = Going to execute $SCRIPT...
read -a res -p "Enter 'skip' to skip this step or press Enter to execute: "
if [[ $res = "skip" ]]
then
echo Skipping $SCRIPT...
else
echo Executing $SCRIPT...
for host in "${hosts[#]}"
do
local cur=${!host}
echo Executing $SCRIPT on $host - $cur...
sshpass -p "$rootpass" ssh -o "StrictHostKeyChecking no" root#${cur} \
"ns1=$ns1 ns2=$ns2 search=$search zoo1=$zoo1 zoo2=$zoo2 zoo3=$zoo3 node0=$node0 pass=$pass CURIP=$cur CURHOST=$host bash -s" \
<$SCRIPT >log-$SCRIPT-$cur.log 2>&1
echo Done.
done
echo =================================================
fi
}
Then I use it like this:
read -p "Please check that Solr started successfully and Press [Enter] key to continue..."
#Solr configset and collections:
ssh_exec "Solr configset and collections" script06.sh zoo1 zoo2 zoo3
This command executes script06.sh on 3 servers (zoo1,zoo2,zoo3)
As Sayan said, using < redirects the output of running the assignRole.sh script locally, but you want to execute that script on the remote host, with the arguments.
Pass the whole command as the final argument to ssh, in quotes:
ssh -o StrictHostKeyChecking=no -T $key "/oracle/oracle_user/makhshif/./assignRole.sh name open_mode" >> /oracle/oracle_user/dftest.txt
or split into multiple lines for readability:
ssh -o StrictHostKeyChecking=no -T $key \
"/oracle/oracle_user/makhshif/./assignRole.sh name open_mode" \
>> /oracle/oracle_user/dftest.txt

remote command via ssh: returned heading spaces skipped

For a simple example:
ssh user#ip echo " messages"
this output like:
messages
not the expected(with heading spaces):
messages
and the heading spaces are skipped, how to keep these spaces within the returned output?
It is because ssh accepts only single command argument. If you pass more than one, all of them are passed through bash -c "command", which basically removes all the additional spaces from additional arguments. Workaround can be
ssh user#ip 'echo " messages"'

Expect script SSH not successful

I have made two scripts:
This one fetches IP address & Hostnames:
#!/bin/bash
for i in `cat ~/script/hosts.txt`
do HOSTNAME=`echo $i|awk -F: '{print $1}'`
IP=`echo $i|awk -F: '{print $2}'`
TIMESTAMP=`date +%Y-%m-%d`
~/script/expect.sh $HOSTNAME $IP
done
This one does SSH into the devices:
#!/usr/bin/expect
set timeout 20
set HOSTNAME [lindex $argv 0]
set IP [lindex $argv 1]
exp_internal 1
spawn ssh -o StrictHostKeyChecking=no root#$IP
exit
I want to make a script to bakcup multiple device configurations.
Problem is that SSH is failing due to following errors:
$ ./main.sh
spawn ssh -o StrictHostKeyChecking=no root#10.102.82.235
: Name or service not knownname 10.102.82.235
spawn ssh -o StrictHostKeyChecking=no root#10.102.82.239
: Name or service not knownname 10.102.82.239
When I debug, I see the following error
spawn id exp4 sent <ssh: Could not resolve hostname 10.102.82.235\r\r: Name or
service not known\r\r\n>
: Name or service not knownname 10.102.82.235
I think the issue is due to these characters: "\r\r", "\r\r\n"
Is there any way I can filter these out?
Not an answer, but your shell script can use much improvement:
#!/bin/bash
while IFS=: read -r host ip; do
timestamp=$(date +%Y-%m-%d %T)
~/script/expect.sh "$host" "$ip"
done < ~/script/hosts.txt
Notes:
don't use for line in `cat file` to read the lines of a file -- a for loop reads words from a file
use $(...) for command substitution, not `...` -- improved readability, and easy to nest
don't use UPPERCASE_VARIABLES -- those should be reserved for the shell's use.
your (unused) TIMESTAMP variable actually contains a date, no time.
quote your "$variables" unless you can explain why you want them unquoted.

using awk in expect send getting can't read "1": no such variable error

I am sending awk command through expect send, when i am sending i am getting error but i can't read 1 no such variable
I did use {{}} mechansim but i did work,
expect "$prompt" {
send "awk {{print $1}} /mytest/test.log\r"
}
I tried with eascapse sequence \, but i didnot find any response expect_out(buffer),..etc
expect "$prompt" {
send "awk '{print \$1}' /mytest/test.log\r"
}
I tried with exec command also
expect "$prompt" {
send "exec awk {{print $1}} /mytest/test.log\r"
}
You have to use the curly braces to avoid substitution. Alternatively you have to escape the dollar sign and the curly braces too.
A couple of examples:
1. interacting with a program on your local machine:
#!/usr/bin/expect -d
spawn "/bin/bash"
set cmd "awk '\{print \$1\}' /mytest/test.log\r"
send $cmd
expect eof
puts $expect_out(buffer)
2. interacting with a remote program over ssh:
#!/usr/bin/expect -d
append cmd {awk '{print $1}' /mytest/test.log} "\r"
spawn ssh user#hostname
set prompt ":|#|\\\$"
interact -o -nobuffer -re $prompt return
send "mypassword\r"
interact -o -nobuffer -re $prompt return
send $cmd
send "exit\r"
expect eof
puts $expect_out(buffer)

sshfs not using password in expect script

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?