3

Ok so instead of hardcoding some local env variables that mirror a remote server (OpenShift server), I'd like to programmatically do it, so we don't have to keep everything up-to-date manually.

Right now I have this hardcoded in a file:

#!/usr/bin/env bash

export OPENSHIFT_MONGODB_DB_USERNAME="admin"
export OPENSHIFT_MONGODB_DB_PASSWORD="xyz"
export OPENSHIFT_MONGODB_DB_HOST="emsa-xyz-2-emsa.cloudapps.nabisco.com"
export OPENSHIFT_MONGODB_DB_PORT=60161

Instead of hardcoding, I can retrieve the "public" env variables from OpenShift with this command:

rhc env list -a <app-name>

which writes this to stdout:

NODE_ENV=jailbreak
NPM_CONFIG_PRODUCTION=true
OPENSHIFT_MONGODB_DB_HOST=emsa-xyz-2-emsa.cloudapps.nabisco.com
OPENSHIFT_MONGODB_DB_PASSWORD=xyz
OPENSHIFT_MONGODB_DB_PORT=60161
OPENSHIFT_MONGODB_DB_USERNAME=admin

does anyone know how I can take that stdout, and, in turn, export each of those variables?

I assume it would be like so - get each line and then put export in front of it and then run bash -e "export x"...the problem is that probably runs in a subshell and wouldn't effect the current shell?

The existing answer to this question is good and should not be lost.

1 Answers1

2

If you have trust in the output of your rhc command, you can just source it:

. <(rhc env list -a <app-name>)

This will source (execute) each line that rhc produces.

As written, the code above defines the variables but doesn't export them. We could fix that but the code below is safer and does the exporting.

The source command, ., expects a file as an argument. To convert the output of rhc into a file-like object, we use process substitution: <(...).

To be more secure, use:

while read -r line; do declare -x "$line"; done < <(rhc env list -a <app-name>)

Here, we use process substitution, <(...), combined with input redirection, <, so that the while loop reads from the output of rhc. The space between the first and second < is essential: do not omit it.

The -x option to declare tells bash to export the variable.

Changing order

As per comment below, the rhc command can be placed on the line above the while loop via:

tmpvar=$(rhc env list -a <app-name>)
while read -r line; do declare -x "$line"; done <<<"$tmpvar"

<<< creates a here string. In this case, it means the $tmpvar is provided as input to the while loop.

John1024
  • 74,655
  • Nice very cool, there is no manual entry for declare - man declare doesn't seem to exist at least on my MacOS machine, wonder how it works so that it acts as export – Alexander Mills Nov 23 '17 at 01:17
  • 1
    @AlexanderMills declare is a bash builtin. To get help on it, run help declare or else open up man bash and look at the section entitled SHELL BUILTIN COMMANDS. – John1024 Nov 23 '17 at 01:21
  • Do you know of a way to put the rhc command on the line above the while loop? – Alexander Mills Nov 23 '17 at 01:47
  • For now, I am guessing just store it in a variable and it should work. – Alexander Mills Nov 23 '17 at 01:48
  • @AlexanderMills Yes, that can be done with a variable. See the new section at the end of the updated answer. – John1024 Nov 23 '17 at 01:51
  • thanks, I have never seen <<< before, what is that operator? – Alexander Mills Nov 23 '17 at 01:52
  • I will have to look up how <<< works compared to < <() – Alexander Mills Nov 23 '17 at 01:53
  • 1
    @AlexanderMills < <(...) takes the output of the command inside the parens and provides it as input to the while loop. By contrast, <<< takes the contents of the string that follows (in this case, the contents of $tmpvar) and provides it as input to the while loop. <<< is called a here string and is documented in man bash. – John1024 Nov 23 '17 at 01:59
  • Maybe I'm missing something: why not just pipe in to the read command? As in rhc env list -a <app-name> | while read -r line; do declare -x "$line"; done – Jasha Oct 29 '19 at 05:12
  • It appears that I am missing something; my comment above does not work, though I can't figure out why. – Jasha Oct 29 '19 at 05:24
  • @Jasha The processes in a pipeline are in subshells. Any variable created in one of the subshells will cease to exist once the pipeline exits. – John1024 Oct 30 '19 at 05:19
  • Oh, that's interesting. Thanks for the explanation! – Jasha Oct 30 '19 at 05:26