Aubergine
Aubergine

Reputation: 6032

Variable isn't initialized in script passed through heredoc

Please consider following snippet which should enter kubernetes mysql pod container and should initialise BAR variable to a list of mysql databases.

kubectl -n somens exec -i mysql-69df7d4c77-hxtng bash <<EOF
echo Hello;
BAR=$(echo "show databases" | mysql -u root -pwhatever)
echo "BAR=\$BAR"
EOF 

If I change line

 BAR=$(echo "show databases" | mysql -u root -pwhatever)

to

echo "show databases" | mysql -u root -pwhatever

I will get printed a list of databases while executing entire snippet.

When I run the original, I get empty BAR variable.

Now I know that BAR can be initialised and I am printing it correctly as I tried to set it to test string and print out.

Currently I have a script which runs:

BAR=$(echo "show databases" | mysql -u root -pwhatever)

outside of container and not inside "heredoc", and it initialises the variable properly.

How can I initialise bar correctly using "heredoc"? I apologise for specificity of the example, would not want to lose details converting it to what I believe is similar and not what it actually is(poor dev here).

Upvotes: 1

Views: 569

Answers (1)

Inian
Inian

Reputation: 85560

Assuming you want to run this particular mysql command inside the container you are launching, running the heredoc in this case will have the contents parsed twice, once by the local shell, then again by the target shell (over the container). So you need to ensure the first level of parsing done by the local shell does not expand variables or expand command substitutions.

You can do that by escaping any expansions happening with $ by prefixing them with \$, which means insisting the local shell to defer expanding it and let it passed over and be interpreted by the shell inside the container.

kubectl -n somens exec -i mysql-69df7d4c77-hxtng bash <<EOF
echo Hello;
BAR=\$(echo "show databases" | mysql -u root -pwhatever)
echo "BAR=\$BAR"
EOF

or use a heredoc for a special case with a quoted de-limiter, instead of EOF using 'EOF' which disables any parsing done by the local shell. So with this approach, any manual escaping is no longer needed.

kubectl -n somens exec -i mysql-69df7d4c77-hxtng bash <<'EOF'
echo Hello;
BAR=$(echo "show databases" | mysql -u root -pwhatever)
echo "BAR=$BAR"
EOF

Upvotes: 2

Related Questions