1

I have Postgres running in a docker container on a remote host. I'm attempting to ssh to that remote host, and use a heredoc to pass a script to that shell. In that script, I attempt to execute a psql query against the postgres database that resides in the container on that host, and assign the output to a variable. I'm sorry, I know that's a bit convoluted, but maybe some code will be more coherent (nor not)

If I run this, I get nothing out of my "echo" of $dbVersion... in fact, due to some other experimentation, I'm fairly convinced it never gets to the "echo" line at all, but for the life of me I don't know why, because...

ssh root@$serverIP13 <<EOF
postgresId=\$(docker ps | grep 'postgres_db' | awk '{print \$1}')
dbVersion=\$(docker exec -i \$postgresId psql -X -A -d myDb  -U myUser -t -c "SELECT Max(Version) FROM DbVersion;")
echo \$dbVersion
EOF

...after turning and twisting my code this way and that... I finally found a way that works, and I get a successful "echo" of my version number. I'm quite new to bash, so I'm hoping someone out there can discern this mystery for me and help me understand a bit better how bash works in this regard, and why the below succeeds, and the above fails.

ssh root@$serverIP13 <<EOF
postgresId=\$(docker ps | grep 'postgres_db' | awk '{print \$1}')
dbVersion=\$(echo "psql -X -A -d myDb -U myUser -t -c 'SELECT Max(Version) FROM DbVersion;'" | docker exec -i \$postgresId bash)
echo \$dbVersion
EOF
3
  • Is the database listening on a port accessible from the network? It'd be much easier to run psql -h "$serverIP13" ... from your local system if so, skipping both the ssh and docker exec steps. Commented Aug 11, 2020 at 10:46
  • I always appreciate folks with common sense! The only port I have open is 22, as I'm trying to constrain my exposure, but... I'm going to add this to my backlog of things to try to do in a future sprint because... it is the simpler solution, and simpler solutions are less likely to break. Thank you for the suggestion. Commented Aug 11, 2020 at 21:21
  • 1
    ssh -L 5432:localhost:5432 root@$serverIP13 to port forward over the ssh connection could help too. That's a couple of network hops, but would let you use a local psql client. Commented Aug 11, 2020 at 23:56

2 Answers 2

2

The normal way to get a docker exec -i output is to call for docker to run a shell (which, in turn, runs your command.
See "Bash / Docker exec: file redirection from inside a container" (I mentioned in 2015)

dbVersion=\$(docker exec -i sh -c '\$postgresId psql -X -A -d myDb  -U myUser -t -c "SELECT Max(Version) FROM DbVersion;"')
Sign up to request clarification or add additional context in comments.

1 Comment

I'll try this out when I get back online tonight. This seems like the "why" I was looking for
1

Following script worked without invoking bash :

ssh root@$serverIP13 << 'EOF'
postgresId=$(docker ps | grep 'postgres_db' | awk '{print $1}')
dbVersion=$(docker exec $postgresId psql -X -A -d postgres -U postgres -c "select current_database()")
echo $dbVersion
EOF

I use 'EOF' to avoid having to escape.

To pass local values to remote :

ssh root@$serverIP13 /bin/bash -s 1 2 3 << 'EOF'
echo $1 $2 $3
EOF

You should not use -i if you put docker exec in $(...)

2 Comments

Thank you for this. I often have variables coming into my script that need to be expanded, but in this case, I do not so good call. That said... is there a way to force variable expansion if you use a quoted 'EOF'?
No, then you have to use an unescaped EOF and quote everything else like in your original attempt.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.