expect sudo ssh login issue [duplicate] - bash

This question already has answers here:
How can I escape a double quote inside double quotes?
(9 answers)
Closed 5 years ago.
i wrote an expect script to ssh remotely to multiple linux boxes and running this command chmod -R o-w /etc/
But i am getting an error expect: invalid option -- 'R'
Please find the script below
#!/bin/bash
username=$1
userpass=$2
rootpass=$3
cat server_list | while read host
do
expect -c "
set timeout 5
spawn ssh -o StrictHostKeyChecking=no -tq ${username}#${host} sudo su - root
expect "ssword" { send "${userpass}r" }
expect "ssword" { send "{rootpass}r" }
expect "#"
send "chmod -R o-w /etc"
expect "#" { send "exitr" }
expect eof"
done
i am running the script like this
./test1.sh test test#123 test#123
Kindly help

Use "--" flags in the send command which will force the next argument to be read as string.
send -- "chmod -R o-w /etc"
Read more in Expect manpage

Related

Passing variables to SSH [duplicate]

This question already has answers here:
Passing external shell script variable via ssh
(2 answers)
Variable issues in SSH
(1 answer)
Closed 1 year ago.
The following code loops through states in a array and passes a state to a server via ssh -
STATES="NY CO"
arr_states=(${STATES//' /'/ })
for i in "${arr_states[#]}"; do
state=$i
ssh -o SendEnv=state jenkins#server sh -s << 'EOF'
sudo su
cd /home/jenkins/report
psql -d db -c "$(sed 's/state_name/'"$state"'/' county.sql)" -U user
echo $state
EOF
done
The output of echo $state in the above is an empty string even if I pass it NY.
When I change the 'EOF' to EOF, the output of echo $state is the string I passed (NY). But then it says, the file county.sql does not exist.
How do I get it to recognize both the variable I pass and the file on the remote I am trying to run.
As an approach that doesn't require you to do any manual escaping of your code (which frequently becomes a maintenance nightmare, since it means that code needs to be changed whenever you modify where it's expected to run) -- consider defining a function, and using declare -f to ask the shell to generate code that will output that function for you.
The same can be done with variables, using declare -p. Thus, passing both a function with the remote code, and the variables that remote code needs to operate that way:
#!/usr/bin/env bash
# This is run on the remote server _as root_ (behind sudo su)
remotePostEscalationFunc() {
cd /home/jenkins/report || return
if psql -d db -U user -c "$(sed -e "s/state_name/${state}/" county.sql)"; then
echo "Success processing $state" >&2
else
rc=$?
echo "Failure processing $state" >&2
return "$rc"
fi
}
# This is run on the remote server as the jenkins user (before sudo).
remoteFunc() {
sudo su -c "$(declare -p state); $(declare -f remotePostEscalationFunc); remotePostEscalationFunc"
}
# Everything below here is run locally.
arr_states=( NY CO )
for state in "${arr_states[#]}"; do
ssh jenkins#server 'bash -s' <<EOF
$(declare -f remoteFunc remotePostEscalationFunc); $(declare -p state); remoteFunc
EOF
done
You were almost right with the change from 'EOF' to EOF. You are just missing a backslash (\) before $(sed. So the following should work:
arr_states=(${STATES//' /'/ })
for i in "${arr_states[#]}"; do
state=$i
ssh -o SendEnv=state jenkins#server sh -s << EOF
sudo su
cd /home/jenkins/report
psql -d db -c "\$(sed 's/state_name/'"$state"'/' county.sql)" -U user
echo $state
EOF
done

Capture Bash output to variable in Shell Script [duplicate]

This question already has answers here:
How do I set a variable to the output of a command in Bash?
(15 answers)
Closed 3 years ago.
I have written a shell script to run other shell script on remote server(Shell script is running successfully on remote server). I want to capture output to some variable. Below is my code.
Please can anyone help me out.
#! /bin/sh
sshpass -p password ssh -T root#serverIP1 << EOF
sshpass -p password ssh -T root#serverIP2 << EOS
copyoutput=bash /opt/Shellscriptlocation/DiskSpace.sh
EOS
EOF
echo $copyoutput
This should work for you by placing command substitution in outermost shell:
copyoutput=$(
sshpass -p password ssh -T root#serverIP1 << EOF
sshpass -p password ssh -T root#serverIP2 << EOS
bash /opt/Shellscriptlocation/DiskSpace.sh
EOS
EOF
)
echo "$copyoutput"

Testing account existence using expect

I have a list of 400 servers and I like to check unix account existence with expect to loop it
I wrote a bash script that uses expect command but it returns me error message that I don't understand the meaning
#!/bin/bash
fic_serv="test.txt"
echo "Passwd"
stty -echo
read -s passwd
stty echo
suffix="suffix"
account="acc"
for server in `cat $fic_serv`
do
prompt="[$acc#$server ~]$ "
expect -c "
spawn ssh -o StrictHostKeyChecking=no $account#$server.$suffix
expect "Password: "
send "$passwd\r"
expect $prompt
send "logout\r"
"
done
[acc#serv ~]$ couldn't read file "
send "passwd\r"
expect [acc#server ~]$
send "logout\r"
": no such file or directory
(I modified the value)
You should use while, not for, to parse files in Bash. Use a "redirect" to treat a file as standard input and read one line at a time.
while read server; do
...
done < $fic_serv
Your major problem is Expect interprets your "s as "end of script". Escape them, as in \", or use {}, as in:
expect -c "
spawn ssh -o StrictHostKeyChecking=no $account#$server.$suffix
expect {Password: }
send {$passwd\r}
expect $prompt
send {logout\r}
"
If you have 400 servers to manage, I strongly recommend you use ansible.
You could just put the list of hosts into a file, let's call it inventory, and run the following command:
ansible -i inventory -m shell -a "id acc" all
Using here-docs in the shell to embed code for another language is usually better than quoting hell, and sharing variables through the environment is easier and safer than parameter expansion:
export account passwd
while IFS= read -r server; do
export prompt="[$acc#$server ~]$ "
export host="$server.$suffix"
expect << 'END_EXPECT'
spawn ssh -o StrictHostKeyChecking=no $env(account)#$env(host)
expect "Password: "
send "$env(passwd)\r"
expect $env(prompt)
send "logout\r"
expect eof
END_EXPECT
done < "$fic_serv"
As shown, I like to indent the heredoc to make it more obvious.
And depending on the error message or login prompt, there can be more logic to indicate that the account name and/or password are incorrect.

How to use expect inside bash script [duplicate]

This question already has an answer here:
Embedding an Expect script inside a Bash script
(1 answer)
Closed 5 years ago.
Could anybody please tell me why this is not working?
#!/bin/bash
cd /home
touch somefile
/usr/bin/expect<<FILETRANSFER
spawn scp -r -P remoteServerPort somefile remoteServerIP:/home
expect "assword:"
send "MyPassWord\r"
interact
FILETRANSFER
echo "It's done"
It doesn't give any error but file is not transferred to remote server.I have tried many ways still couldn't find any solution.
The bash script you have defined is passing the expect commands on the standard input of expect. However, the expect command requires its arguments on a file or as an argument using the -c option.
You have several options but to add the less modifications on your script you just need to use the process substitution to create a here-document (temporary) for the expect command.
#!/bin/bash
echo "[DEBUG] INIT BASH"
cd /home
touch somefile
/usr/bin/expect <(cat << EOF
spawn scp -r -P remoteServerPort somefile remoteServerIP:/home
expect "Password:"
send "MyPassWord\r"
interact
EOF
)
echo "[DEBUG] END BASH"

couldn't read file :expect error in a bash script [duplicate]

This question already has an answer here:
How to use Expect in a Bash script
(1 answer)
Closed 7 years ago.
I am facing error in my below expect embedded bash script.
When i run it,I get the below error and the script ends
Even though I am giving the arguments on commandline.The expect send is unable to get the $site variable
./expect_delete "password" usa rvomero
"Enter site name for Username: couldn't read file "site": no such file or directory"
The script:
#!/bin/bash
password="$1"
me=`whoami`
site="$2"
list="$3"
echo $site $list
for i in `echo $list`
do
/tools/cfr/bin/expect -c "
set timeout 10
spawn <fullpathtoanotherbashscript> $site $i
expect "Enter site name for $me: "
send "$site\r"
expect "Enter password for $me: "
send "$password\r"
expect eof
"
done
Any help appreciated
You might be better off encapsulating the expect script in ' so there isn't any shell expansion going on and getting your variables in to it by simply exporting them -
export USER=fred
expect -c '
set user $env(USER)
....
'

Resources