0

I'm working through creating a Dockerfile that calls on a script named start.sh I want to take the environment variables that are passed from the user either by means of docker-compose.yml or docker run -e now what I've wanted to do is something where I have a list of these variables defined dynamically in an array.

## Environment Variables
## Missing Vars off the hop SLACK_HOOK_URL
CONFIG_SETTINGS=(
  AWS_ID
  AWS_SECRET
  BUCKET_REGION
  BUCKET_NAME
  DB_USER
  DB_PASSWORD
  DB_HOSTIP
  DB_PORT
  DB_NAME
)

I only have to unset a subset of the above variables defined in this array.

CONFIG_SECRETS=(
  AWS_ID
  AWS_ID_STR
  AWS_SECRET
  AWS_SECRET_STR
  BUCKET_NAME
  BUCKET_NAME_STR
  DB_USER
  DB_USER_STR
  DB_PASSWORD
  DB_PASSWORD_STR
  DB_HOSTIP
  DB_HOSTIP_STR
  DB_PORT
  DB_PORT_STR
  DB_NAME
  DB_NAME_STR
)

My problem is the following for loop.

## Sanitization section
for i in "${!CONFIG_SECRETS[@]}"; do
  ## Nullify environment variables that contain secrets before launching.
  # echo ${CONFIG_SECRETS[$i]}
  eval $"${CONFIG_SECRETS[$i]}"=$""
  unset $"${CONFIG_SECRETS[$i]}"
  echo \$${CONFIG_SECRETS[$i]} is now to: $"${CONFIG_SECRETS[$i]}"
done

For example, the below is a for loop I created to iterate through these variables and set them.

for i in "${!CONFIG_SETTINGS[@]}"; do
  echo ${CONFIG_SETTINGS[$i]}"_KEY"
  ## Indirect references http://tldp.org/LDP/abs/html/ivr.html
  eval FROM_STRING=\$"${CONFIG_SETTINGS[$i]}_STR"
  eval VALUE_STRING=\$${CONFIG_SETTINGS[$i]}
  eval KEY_STRING=\$"${CONFIG_SETTINGS[$i]}_KEY"
  TO_STRING="$KEY_STRING$VALUE_STRING"
  sed -i '' "s/$FROM_STRING/$TO_STRING/g" ./config.tmpl
done

This modifies the following configuration file.

{
  "aws_id": "YOUR-AWS-ID",
  "aws_secret": "YOUR-AWS-SECRET",
  "bucket_region": "YOUR-BUCKET-REGION",
  "bucket_name": "YOUR-BUCKET-NAME",
  "db_conn": "USER:PASSWORD@tcp(localhost:3306)/DBNAME",
  "slack_hook_url": ""
}

The full context script minus things that are outside of the scope of this question.

#!/bin/bash

## Launch service will tell prism-bin what mode to run in.
LAUNCHMODE="${MODE:-$1}"

## This variable will be what can override default launch args.  I may modify this as I learn more about prism-bin
LAUNCHARGS="${CUSTOM_ARGS:-$2}"

## This is setup this way to handle any situations that might arise from the
## config being JSON and bash not being any good at JSON.
# ## Strings to replace.
AWS_ID_STR="YOUR-AWS-ID"
AWS_SECRET_STR="YOUR-AWS-SECRET"
BUCKET_REGION_STR="YOUR-BUCKET-REGION"
BUCKET_NAME_STR="YOUR-BUCKET-NAME"
DB_USER_STR="USER"
DB_PASSWORD_STR="PASSWORD"
DB_HOSTIP_STR="localhost"
DB_PORT_STR="3306"
DB_NAME_STR="DBNAME"

# Environment Variables/Defaults
## Json sucks in BASH/Shell so you need to add trailing commas intermittently.
## Just pay attention to this.  Also at some point I'll need to make a fringe
## case for handling key/values that aren't included in the default config.
AWS_ID="${AWS_ID:-potato}"
AWS_SECRET="${AWS_SECRET:-potato}"
BUCKET_REGION="${BUCKET_REGION:-potato}"
BUCKET_NAME="${BUCKET_NAME:-potato}"
DB_USER="${DB_USER:-potato}"
DB_PASSWORD="${DB_PASSWORD:-potato}"
DB_HOSTIP="${DB_HOSTIP:-potato}"
DB_PORT="${DB_PORT:-potato}"
DB_NAME="${DB_NAME:-potato}"

## Environment Variables in Array
CONFIG_SETTINGS=(
  AWS_ID
  AWS_SECRET
  BUCKET_REGION
  BUCKET_NAME
  DB_USER
  DB_PASSWORD
  DB_HOSTIP
  DB_PORT
  DB_NAME
)
CONFIG_SECRETS=(
  AWS_ID
  AWS_ID_STR
  AWS_SECRET
  AWS_SECRET_STR
  BUCKET_NAME
  BUCKET_NAME_STR
  DB_USER
  DB_USER_STR
  DB_PASSWORD
  DB_PASSWORD_STR
  DB_HOSTIP
  DB_HOSTIP_STR
  DB_PORT
  DB_PORT_STR
  DB_NAME
  DB_NAME_STR
)

## Sanitization section
# Awaiting someone smarter than me to suggest a method for this.
# https://unix.stackexchange.com/questions/474097/i-want-to-unset-a-list-of-bash-variables-that-have-their-variable-strings-stored
for i in "${CONFIG_SECRETS[@]}"; do
  unset $i
  eval echo \$"${CONFIG_SECRETS[$i]}"=\$${CONFIG_SETTINGS[$i]}
done
0

3 Answers 3

1

This should be a simple loop

#!/bin/bash

UNSET=(a b c)

a=10 b=20 c=30 d=40 e=50

echo Before a=$a b=$b c=$c d=$d e=$e

for i in ${UNSET[@]}
do
  unset $i
done

echo After a=$a b=$b c=$c d=$d e=$e

This results in

Before a=10 b=20 c=30 d=40 e=50
After a= b= c= d=40 e=50
1
  • Looks good, works well. Tyvm
    – chamunks
    Oct 9, 2018 at 1:01
0

You can dereference variables with !:

$ foo=bar
$ bar=1
$ echo ${!foo}
1

You can't use a variable inside an expansion like that though, so you will probably have to do something really ugly with eval.

1
  • 1
    Hmm so, I'm not sure how this answers the question precisely. I'm looking to use the strings in the arrays as variable names. Which in the for loop I'm trying to dereference. Pardon my ignorance here I'm just a bit confused as to how to apply it. Also, I appreciate the response and gave an upvote but apparently I'm too new for it to count. Sorry </3
    – chamunks
    Oct 9, 2018 at 0:11
0

I think you've worked yourself into a circle; simply loop over the array and unset the parameter referred to by the loop:

AWS_SECRET='secret_here'
echo Before:
declare -p AWS_SECRET
set|grep AWS_SECRET

for secret in "${CONFIG_SECRETS[@]}"
do
  unset $secret
done

echo After:
declare -p AWS_SECRET
set|grep AWS_SECRET
3
  • I feel like I've worked myself into a circle at this point :P Although I wonder if by your suggestion I would just be unsetting $secret and not the environment variable represented by $secret
    – chamunks
    Oct 9, 2018 at 0:39
  • That's why I set up a sample variable (AWS_SECRET), to confirm that it's set before the loop and not set after the loop -- test it and see!
    – Jeff Schaller
    Oct 9, 2018 at 0:40
  • Also, keep in mind that the variable name is defined as a string within in an array and not your normal way so the example should contain a dynamically referenced string if possible. as its the problem that I'm having, unsetting parameters normally is much easier than doing what I'm doing.
    – chamunks
    Oct 9, 2018 at 0:45

You must log in to answer this question.

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