In a previous post I wrote about a small script I call
ebenv, which makes AWS Elastic Beanstalk environment properties available to shell commands as environment variables. See that post for the rationale behind this script.
Since that time, I came up with a simpler way to obtain the environment properties, and the new script does not depend on
It turns out Elastic Beanstalk on Amazon Linux 2 stores its environment properties in a file at
/opt/elasticbeanstalk/deployment/env, readable by root. Each property is defined on its own line, in shell variable syntax, like this:
When I found this file, I realized I could simplify my ebenv script fairly significantly. All it needs to do is read this file and
export each line, then run the supplied command.
There’s one caveat though—it needs to handle special shell characters, namely
$, because the values in the
env file can contain these characters, which will cause problems with shell interpolation and expansion.
The first version prepended the environment variables to the command invocation. If our command was
rails c, the command sent to the shell was
RACK_ENV=production MY_PROP=my-val rails c. The updated version
exports each property and then runs the command, which is simpler and easier to reason about.
Here’s the updated script, with a couple of strange line breaks so that it’s easier to read here.
#!/bin/bash # This script runs the command (and args) passed to it # as the EB AppUser, after making Elastic Beanstalk # environment properties available to the command. # # Usage: # # ebenv <command> [arguments] # # Example: # # ebenv bin/rails c # # When using shell variables in a command, be sure to # escape or properly quote them so they are expanded by # ebenv rather than by the shell before the arguments # reach ebenv. For example: # # ebenv echo $RACK_ENV #=> [blank] # ebenv echo "$RACK_ENV" #=> [blank] # ebenv echo '$RACK_ENV' #=> production # ebenv echo \$RACK_ENV #=> production # # In the first two examples, $RACK_ENV is interpreted # by the shell before calling ebenv. In the second two # examples, $RACK_ENV is interpolated inside ebenv. # exit if there's no command to run if [[ "$#" == "0" ]]; then echo 'Usage: ebenv <command> [arguments]' exit 1 fi # get the user to run the command as EB_APP_USER="$( /opt/elasticbeanstalk/bin/get-config \ platformconfig -k AppUser )" # export each key=value after escaping special chars while read -r line; do key="$(cut -d= -f1 <<< "$line")" val="$(cut -d= -f2- <<< "$line" \ | sed -r "/[\\$\"']/s/[\\$\"']/\\\\\\0/g")" export "$key=$val" done < /opt/elasticbeanstalk/deployment/env # run the command as the EB AppUser eval "su -s /bin/bash -c \"$*\" \"$EB_APP_USER\""
Feel free to email me if you have suggestions for further improvement.