What specific syntax must be changed in the code below in order to prevent the error that is being thrown when an environment variable contains an unexpected token?


Specifically, a cloud-init startup script running in an RHEL 7 VM in Azure needs to switch to run as a non-root user while running a short sequence of specific commands including the following line which passes the values of environmental variables into az login:

su - azureuser << EOF
echo "User from whoami is: "
echo "About to login to az.  "
az login --service-principal -u \"$AZ_CLIENT\" -p \"$AZ_PASS\" --tenant \"$AZ_TENANT\"

Note that the su - azureuser << EOF...EOF is used in the cloud-init script in order to ensure that the commands contained between the EOF delimiters are executed as the specified non-root user.


The error being thrown seems to be caused by a parenthetic symbol that is part of a random password that populates the $AZ_PASS variable. We changed the password below to a fake password for security, but we the following retains the ( symbol to illustrate the error:

azure-arm: User from whoami is:
azure-arm: azureuser
azure-arm: About to login to az.
azure-arm: -bash: line 4: syntax error near unexpected token `('
azure-arm: -bash: line 4: `az login --service-principal -u \"client-id-long-string\" -p \"gy75k9([0y6se2v^\" --tenant \"long-tenant-id-string\"'

1 Answer 1


You don't need to escape the double quotes in a here-doc. The way you have it there, the outer shell expands the variables, and the shell started by su sees -p \"gy75k9([0y6se2v^\" literally, the backslashes escape the quotes, and the ( is unquoted.

Without the backslashes, it should work as long as the password doesn't contain \, $, " or backtick. Or change to single quotes so you only need to care about single quotes in the password.

su - azureuser << EOF
az login --service-principal -u '$AZ_CLIENT' -p '$AZ_PASS' --tenant '$AZ_TENANT'

See Escape a variable for use as content of another script about dealing with arbitrary values, including the single quotes.

Alternatively, have the shell started by su expand the variables. You'll need to quote the here-doc delimiter (or all the $ signs in the here-doc), and usesu -p to have the environment variables preserved past su. And this time, double-quotes are needed, to allow the inner shell to expand the variables.

su -p - azureuser << 'EOF'
az login --service-principal -u "$AZ_CLIENT" -p "$AZ_PASS" --tenant "$AZ_TENANT"
  • The answer to this other OP , and particularly the contents of this other link enabled us to resolve a related problem without having to post another question on this site.
    – CodeMed
    May 20, 2021 at 23:33

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .