Spawn in expect script do not have access to environment variable - linux

I have a expect script named load_data.exp placed in home directory
#!/usr/bin/expect
spawn osm2pgsql -s -l -d postgres -W -U postgres -H $OSM_DATABASE_PORT_5432_TCP_ADDR -P 5432 --hstore $filename
expect "Password"
send "$OSM_DATABASE_ENV_POSTGRES_PASSWORD\n"
interact
there is a environment variable OSM_DATABASE_PORT_5432_TCP_ADDR with has the value of 172.17.0.13 verified by
echo $OSM_DATABASE_PORT_5432_TCP_ADDR
output
172.17.0.13
run the load_data.exp by ./load_data.exp, I got the error
can't read "OSM_DATABASE_PORT_5432_TCP_ADDR": no such variable
while executing
"spawn osm2pgsql -s -l -d postgres -W -U postgres -H $OSM_DATABASE_PORT_5432_TCP_ADDR -P 5432 --hstore $filename"
(file "../load_data.exp" line 4)
seems to be that spawn can not have access to environment variable DATABASE_PORT_5432_TCP_ADDR

You can pass Bash variables to the Expect the following way:
#!/usr/bin/expect
set HOST [lindex $argv 0]
set FILENAME [lindex $argv 1]
set PASSWORD [lindex $argv 2]
spawn osm2pgsql -s -l -d postgres -W -U postgres -H $HOST -P 5432 --hstore $FILENAME
expect "Password"
send "$PASSWORD\n"
interact
Then call your expect script like this:
load_data.exp $OSM_DATABASE_PORT_5432_TCP_ADDR $filename $OSM_DATABASE_ENV_POSTGRES_PASSWORD

Related

Issues when spawn'ing ssh on expect ( {$var} vs. "$var" )

I have a expect script that so far it is working fine ... it spawn a ssh session over an existing ssh tunnel like this:
spawn ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -o {ProxyCommand=nc -X 5 -x localhost:8888 %h %p} "$user_ip"
$user_iphas the username and destination IP, as expected by ssh, like username#IP
The problem is that sometimes, port 8888 is being used by another ssh tunnel, and every time this happens I have to tweak the code and change the tunnel port.
So, I am trying to send the port in a variable, to avoid touch the code all the time.
I am getting the tunnel port from command line, as:
set proxy_port [lindex $argv 2]
and then
spawn ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -o {ProxyCommand=nc -X 5 -x localhost:"$proxy_port" %h %p} "$conn"
I see that proxy_portvariable is properly set, but when the script try to spawn the ssh, I get:
spawn ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -o {ProxyCommand=nc -X 5 -x localhost:8888 %h %p} USERID#10.0.0.1
command-line line 0: garbage at end of line; "-o".
send: spawn id exp5 not open
while executing
"send "$pwd\r""
(file "./amm-qev.new.exp" line 36)
In the error above, I see that the port was properly replaced, but it is complaining about ssh syntax.
What is wrong there that my weak eyes are not catching ?
Tcl's {...} syntax is like single-quoted string ('...') in shell where the $var would not be expanded. You should use double quotes.
spawn ssh -o UserKnownHostsFile=/dev/null \
-o StrictHostKeyChecking=no \
-o "ProxyCommand=nc -X 5 -x localhost:$proxy_port %h %p" \
"$conn"

I cant get my expect script to run remote bash script as "expected"

I am trying to run an expect script, which should run a bash script on a remote linux server. The bash script is meant to restart a strongswan IPSec tunnel based on the argument sent via the expect script.
Here's my expect script:
#log_user 0
set prompt {\$ >}
expect -re $prompt
set ip 192.168.0.1
set user user
set password 4p4ssw0rd
set target [lindex argv 0]
spawn ssh -p 2228 "$user\#$ip"
expect "password:"
send "$password\r";
expect ">"
send "su -\r"
expect "Password:"
send "$password\r"
expect "#"
send "sh /usr/local/bin/ipsec_fixer.sh $target; exit\r"
expect "#"
Here's the remote script:
target=$1
if [[ -n "$target" ]]; then
value=`grep -i $target /etc/ipsec.conf -A1 |awk '{print $2}'| tail -n 2 | sed 's/0$//'`
declare -a args
args=( $(grep "$value"* /etc/ipsec.conf | awk '{print $2}') )
for each in ${args[#]}; do ipsec down $each; sleep 3; ipsec up $each ; done
else
exit 2
fi
The expect script runs, but I get the following output:
/usr/local/bin/fix_ipsec avpnconnection
spawn ssh -p 2228 user#192.168.0.1
user#192.168.0.1's password:
Last login: Sun Dec 11 05:40:55 2016 from 192.168.0.232
sh /usr/local/bin/ipsec_fixer.sh argv; exit
021 no connection named "-c"
021 no connection named "-c"
021 no connection named "-c"
021 no connection named "-c"
logout
user#remote:/home/login >
I have no idea what is going on. Please what am I doing wrong?
I think I've figured it out: the odd looking
021 no connection named "-c"
021 no connection named "-c"
021 no connection named "-c"
021 no connection named "-c"
lines are from the remote system's shell.
My expect script now looks like this:
set script /usr/local/bin/ipsecfixer.sh
spawn ssh -p 2228 $user#$ip
expect "password:"
send "$password\r";
expect ">"
send "su -\r"
expect "Password:"
send "$password\r"
expect "#"
send "/bin/bash $script $argv\r"
expect "#"
And it does the job, so far..
You could just use
ssh -t -p 2228 user#192.168.0.1 "sudo /bin/sh /usr/local/bin/ipsec_fixer.sh $target"
and use SSH Key-Based Authentication.
As for the messages you get, is it possible that the script you're launching has an influence on the current SSH connections?

Linux expect spawn can not find file

I wrote a expect script named load_data.exp
#!/usr/bin/expect
spawn "osm2pgsql -s -l -d postgres -W -U postgres -H localhost -P 5432 --hstore /absolute/path/to/bruges_belgium.osm"
expect "Password:" {send "mysecretpassword"}
change access by
chmod +x load_data.exp
run it by
./load_data.exp
the file definitely exits, it gives me error
spawn osm2pgsql -s -l -d postgres -W -U postgres -H localhost -P 5432 --hstore /absolute/path/to/bruges_belgium.osm
couldn't execute "osm2pgsql -s -l -d postgres -W -U postgres -H localhost -P 5432 --hstore /absolute/path/to/bruges_belgium.osm": no such file or directory
while executing
"spawn "osm2pgsql -s -l -d postgres -W -U postgres -H localhost -P 5432 --hstore /absolute/path/to/bruges_belgium.osm""
(file "./load_data.exp" line 6)
osm2pgsql is installed and can be run directly in terminal the following sentence
osm2pgsql -s -l -d postgres -W -U postgres -H localhost -P 5432 --hstore /absolute/path/to/bruges_belgium.osm
so there is a problem with spawn, I guess
As the error suggests, it's trying to find a program not called osm2pgsql, but one called osm2pgsql -s -l -d postgres -W -U postgres -H localhost -P 5432 --hstore /absolute/path/to/bruges_belgium.osm including all the spaces and dashes as part of the executable name. Remove the quotes from the spawn command:
spawn osm2pgsql -s -l -d postgres -W -U postgres -H localhost -P 5432 --hstore /absolute/path/to/bruges_belgium.osm
Try specifying absolute path to osm2pgsql (acquired by command 'which osm2pgsql')

Transmit commands via ssh with password using expect

I need to iterate on a sequence of servers(many type of servers, each type of servers stored in separate files), run on them some commands(stored in different files accordingly to server type) and log the output on the local machine, using ssh with password. Since sshpass, ssh key authentication is not a solution for my case please don't recommend them.
Here is my code:
#!/usr/local/bin/expect -f
#Set path to nodes files
NODES=nodes/*
#Set path to commands files
CMD=commands/*
for fn in $NODES
do
echo "Working in $fn"
for fc in $CMD
do
echo "Working in $fc"
if [ ${fn:6:3} = ${fc:9:3} ]
then
# read Nodes from file
while read fn_line; do
#extracting substrings of user, host, password separated by comma
IFS=', ' read -a uhp <<< $fn_line
#establish ssh session to the node
eval spawn ssh -oStrictHostKeyChecking=no -oCheckHostIP=no ${uhp[0]}#${uhp[1]}
echo ${uhp[0]} ${uhp[1]} ${uhp[2]}
#use correct prompt
set prompt "assword:*"
interact -o -nobuffer -re $prompt return
send "${uhp[2]}\r"
set prompt ":|#|\\\$"
interact -o -nobuffer -re $prompt return
#execute and logging HC commands on the node
while read fc_line; do
#set prompt ":|#|\\\$"
#interact -o -nobuffer -re $prompt return
echo "$fc_line\r" >> logs/${fn:6:3}.log
$fc_line\r >> logs/${fn:6:3}.log
#interact -o -nobuffer -re $prompt return
done < $fc
done < $fn
fi
#cat $f
done
done
I know in my code the problem is combination of bash and expect interpreter. Please help me to do it only in expect style or show me how can i combine bash with expect. Other problem is the while after establishing of ssh connection, but i think it can be solved by storing it previously in an array and looping through it after establishing of ssh connection.
How about writing a small utility in expect which spawns ssh command:
#!/usr/bin/expect
set HOST [lindex $argv 0]
set PORT [lindex $argv 1]
set USER [lindex $argv 2]
set PASSWORD [lindex $argv 3]
set COMMAND [join [lrange $argv 4 end] " "]
spawn ssh -oStrictHostKeyChecking=no -oCheckHostIP=no -p $PORT $USER#$HOST $COMMAND
expect "assword:"
send "$PASSWORD\r"
expect eof
exit
and using it in a Bash script like this:
ssh-util <host> <port> <user> <pass> <command>
e.g.
ssh-util 10.0.0.10 22 root s3cr3t ls -la

Problems with sudo inside expect script

I am running the following script
#!/usr/bin/expect -f
set user [lindex $argv 0]
set pass [lindex $argv 1]
set PATH [lindex $argv 2]
set INV_PATH [lindex $argv 3]
spawn ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no $user#localhost
expect "assword: "
send "$pass\r"
expect "$ "
send "echo $pass | /usr/local/bin/sudo -S $INV_PATH/orainstRoot.sh\r"
expect "$ "
send "cd $PATH/bin\r"
expect "$ "
send "echo $pass | /usr/local/bin/sudo -S cp oraenv coraenv sqlplus dbhome /usr/bin\r"
expect "$ "
send "echo $pass | /usr/local/bin/sudo -S $PATH/root.sh\r"
expect "Check"
send "\r"
Its working fine in some machines and for some machines its throwing the following error... I have checked, its not the PATH causing the issue.
/usr/local/bin/sudo: /scratch/prod_sw/app/oraInventory/orainstRoot.sh: command not found
$ echo PASSWD | /usr/local/bin/sudo -S cd /scratch/prod_sw/app/prod_sw/product/11.2.0/db_home/bin
/usr/local/bin/sudo: cd: command not found
$ echo PASSWD | /usr/local/bin/sudo -S cp oraenv coraenv sqlplus dbhome /usr/bin
cp: cannot stat `oraenv': No such file or directory
cp: cannot stat `coraenv': No such file or directory
cp: cannot stat `sqlplus': No such file or directory
cp: cannot stat `dbhome': No such file or directory
$ echo PASSWD | /usr/local/bin/sudo -S /scratch/prod_sw/app/prod_sw/product/11.2.0/db_home//root.sh
Check /scratch/prod_sw/app/prod_sw/product/11.2.0/db_home/install/root_slcad22rhu_2013-07-22_04-41-49.log for the output of root script
Try to give complete path for these files and check once.
cp /path/oraenv /path/coraenv /path/sqlplus /path/dbhome /usr/bin

Resources