1

I am trying to paas an env variable to a remoye host using the code below.

ssh username@ip "env current_quarter=$current_quarter" sh -s << 'EOF' 
pwd 
echo "${current_quarter}" 
EOF

pwd prints the correct location on the remote host but echo "${current_quarter}" does not print the current_quarter.

sshtest
  • 13
  • 3
  • What is the local value of `$current_quarter`? Are you aware `ssh` concatenates multiple arguments into one command string passed to the remote shell? Some things should be quoted also in the context of the remote shell. See the discussion [here](https://superuser.com/a/1534401/432690). I'm not saying this is the culprit. I'm saying some values of the variable can break the code. Some can even inject code. – Kamil Maciorowski Apr 21 '21 at 08:18

1 Answers1

1

By putting EOF in quotes you are telling the local shell to not expand the here document before passing it to ssh. According to the bash documentation this applies to parameter expansion, command substitution and arithmetic expansion.

Contrary to what I thought when originally writing this answer the remote shell is not affected through this and will execute the here document like you wrote it directly in the remote shell (including all the kinds of expansion and substitution that were skipped in the local shell by quoting EOF).

If you just want to use the local variable test you remove the quotes from the EOF:

ssh user@host sh -s <<EOF
pwd
echo $test
EOF

For fish users it would look like this:

ssh user@host "\
pwd
echo $test
"

Now if you want to pass the local variable test as the remote variable remote_test and not expand locally you just escape the variable with a backslash:

ssh user@host sh -s <<EOF
export remote_test=$test
pwd
echo "\${remote_test}"
EOF

Edit:

Running:

ssh user@host "env remote_test=$test" sh -s <<'EOF'
pwd
echo "${remote_test}"
EOF

should be equivalent to the third code example with the exception that env is not part of the shell and can also be used in non-bourne shells.

(This is however identical to the code example OP gave but since OP marked this answer as correct I suspect that env and export behave differently when encountering certain character sequences but I have not found conclusive evidence supporting this hypothesis.)

lycheese
  • 26
  • 2
  • 1
    This answer totally ignores the fact an attempt to pass the local value is in this fragment of the local code: `ssh username@ip "env current_quarter=$current_quarter" sh -s`. The code makes the server run `env current_quarter=foo sh -s` in a shell, where `foo` is the local value from local expansion. IMO quoted `EOF` was by design. – Kamil Maciorowski Apr 21 '21 at 08:47
  • I see what you mean. I tried out the code example and it did not run on my machine so I just assumed the command itself is the problem. Got it to run now. My bad. – lycheese Apr 21 '21 at 09:01
  • 2
    I don't know what to do with this answer. It tries to be helpful. It is accepted, so probably it was helpful. Nevertheless I think `neither the local nor remote variable getting expanded` is *false*. The OP's code does expand `${current_quarter}` on the remote side. The OP's code *works for me* with sane values of (local) `$current_quarter`. IMO the answer does not explain *why* the OP's code might not work. *Maybe* in some circumstances it really doesn't work; and maybe in the same circumstances this answer does help. For now I cannot tell what failed for the OP and why the answer helps. – Kamil Maciorowski Apr 21 '21 at 10:03
  • We are in the same boat there. I considered deleting my answer after getting OP's code to work and realizing that what I thought was the issue was not the issue at all. But now it is accepted and I sincerely have not the slightest clue why… – lycheese Apr 21 '21 at 12:32
  • Yeah... I still think `nor remote variable getting expanded` is false, but I'm not going to downvote your answer (please review the statement though). I'm planning to downvote the question, if the OP doesn't reply to my comment in a day or two. The OP is unregistered, may never come back. Maybe this is the right thing to do in the long run: downvote the problem that cannot be replicated and let it be abandoned and forgotten. Oh well. – Kamil Maciorowski Apr 21 '21 at 12:45
  • Ok I played around with it some more and I think quoting EOF escapes all variables once. Looking up the [bash documentation](https://www.gnu.org/software/bash/manual/html_node/Redirections.html#Here-Documents) seems to confirm that. Should I just edit my answer to conform with this or are there rules that the content should not be altered in such a way? – lycheese Apr 21 '21 at 13:05
  • Quoting `EOF` only matters in the local shell. The remote `sh` gets some code via its stdin and it neither is aware nor cares a here document was used. In the OP's case the code sent to the remote shell contains a literal `"${current_quarter}"` string. The code is what matters for the remote shell. So it's not a matter of "escaping *once*". It's a matter of "escaping in the context of the local shell". // An edit that corrects mistakes or false statements, or makes a post more strict is good. If you think you can improve the answer by editing, go ahead. – Kamil Maciorowski Apr 21 '21 at 13:19