How to access environmental variables inside sshpass interactive mode - bash

The below shell script snippet prints the environmental variable outside of sshpass, but not inside.
#!/bin/bash
[[ $1 = '' ]] && BRANCH="develop" || BRANCH=$1
echo $DESTINATION_FOLDER // prints from env
sshpass -p $PASSWORD ssh -o StrictHostKeyChecking=no $SERVER <<-'ENDSSH'
echo $DESTINATION_FOLDER // doesn't print anything, output: empty
exit
ENDSSH
Am I missing any option to be passed to the interactive mode with sshpass so that it can read environmental variables defined in the local system?

I suggest to replace 'ENDSSH' with ENDSSH to allow bash to interpret the variable in your here-document.
See: https://en.wikipedia.org/wiki/Here_document#Unix_shells

Related

How do I use an command line "flag" variable in SSH command?

I have an SSH command that is able to use variables defined in the script.
Example:
b="03-18-2022"
I'm able to pass this in to my ssh call and use it.
However I want to be able to define $b when I run the script: bash file.sh -b 03-18-2022
.. When I try doing this the SSH command cannot recognize the variable
CODE:
Getting the variable from the input:
while getopts ":b:" arg; do
case "${arg}" in
b) b="$OPTARG";;
esac
done
echo "Locally using begin: $b
printf -v b_str %q "$b"
ssh myserver "bash -s $b_str" << 'EOF'
b=$1
echo "remotely using $b"
The last echo works when the variable is defined in the script but not when it is passed in from the command line

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

Bash script variable not being passed via ssh

I have a bash script which ssh's to a server, and depending on the status of a variable performs a task:
#!/bin/bash
foo=$1
ssh user#host.com '
echo In host
if [ "$foo" == "yes" ]; then
echo "Foo!"
fi
'
When I run sh script.sh yes, although the ssh command works, the conditional evaluates to false. I can see this if I echo $foo - it prints an empty line. How can I access the value of foo within the ssh command?
Variables aren't transferred to a remote machine. You can expand the variable in the code sent through ssh, but you have to be extremely careful because it opens the door to uncontrolled code execution:
#!/bin/bash
foo=$1
ssh user#host.com '
echo In host
if [ "'"$foo"'" == "yes" ]; then
echo "Foo!"
fi
'
Now imagine (don't try) what happens if foo='$(rm -rf /)'.

Passing local variable to remote shell bash script

Trying to pass local variable to remote shell using bash script. Here is what I am trying. This is test.sh
#!/bin/bash
envi=$1
function samplefunction {
echo "Environment selected is $envi"
}
if [ "$envi" = "test" ]; then
ssh user#remotehost <<EOF
$(typeset -f samplefunction)
samplefunction
EOF
else
echo "Please pass correct parameter which is - test"
fi
When I try to execute "./test.sh test" the result I am getting is "Environment selected is". shell is not able to pass the variable to the remote system.
ssh does not (and can't) make such variables available on the remote side.
You can instead embed the definition just like you embedded your function:
ssh user#remotehost <<EOF
$(declare -p envi)
$(typeset -f samplefunction)
samplefunction
EOF
You can also copy all known variables. In that case it helps to squash the errors about setting read-only values:
ssh user#remotehost <<EOF
{
$(declare -p)
} 2> /dev/null
$(typeset -f samplefunction)
samplefunction
EOF
If you have a specific variable you frequently want to copy, you can choose to have ssh send it automatically by adding SendEnv envi to your ssh config. The variable must be exported for this to work.

ssh bash receive variable from a remote file

I need to read the variable from a remote file over SSH and compare it. But I get a variable in the wrong format. how to do it correctly?
#!/bin/bash
pass='dpassspass'
user='root#10.10.19.18'
IP="10.2.1.41"
path=/sys/variable/serv
#not work## No such file or directory# write=$(sshpass -p $ovhpass ssh -t $user echo "$IP" > $path)
sshpass -p $pass ssh -t $user << EOF
echo "$IP" > $path
EOF
my_var=$(sshpass -p $pass ssh -t $user "cd /sys_ovh; ./serv.bash")
echo mystart-"$my_var"-myend
read=$(sshpass -p $pass ssh -t $user cat $path)
echo start-"$read"-end
echo start-"$IP"-end
if [ "$read" == "$IP" ]; then
echo "run"
fi
output:
Connection to 10.10.19.18 closed.
-myendt-10.2.1.41
Connection to 10.10.19.18 closed.
-endt-10.2.1.41
start-10.2.1.41-end
Where I make a mistake? How to take data from the SSH?
The vars my_var and read are filled with a string ending with '\r', telling echo to go back to the first column. I think this is a problem with your local script. You can correct that with
tr -d "\r" < myfile > myfile2
Your fundamental problem comes from using unquoted here documents for the commands. You should properly understand in which order the shell interprets these contructs.
ssh remote cmd >file
executes cmd remotely, but first redirects the output from the ssh command to the local file.
ssh remote "cmd >’$file'"
The quotes cause the redirection to be part of the remote command line. The variable file is interpreted first, by the local shell, though.
ssh remote 'cmd >"$file"`
The single quotes prevent the local shell from modifying the command before sending it. Thus, he variable interpolation and the redirection are both handled by the remote shell, in this order.
So your commented-out "not work" command could easily be fixed with proper quoting. However, it will be much more elegant and efficient to use a single remote session, and execute all the commands in one go. Mixing the local variable IP with remote variables calls for some rather elaborate escaping, though. A major simplification would be to pass the value on standard input, so that the entire remote script can be single quoted.
#!/bin/bash
pass='dpassspass'
user='root#10.10.19.18'
IP="10.2.1.41"
result=$(echo "$IP" |
sshpass -p "$pass" ssh -t "$user" '
path=/sys/variable/serv
cat > "$path"
cd /sys_ovh
./serv.bash
cat "$path"')
echo mystart-"${result%$'\n'*}"-myend
echo start-"${result#*$'\n'}"-end
echo start-"$IP"-end
if [ "${result#*$'\n'}" == "$IP" ]; then
echo "run"
fi
The output from the remote shell is two lines; we pick it apart by using the shell's prefix and suffix substitution operators.

Resources