Reputation: 6975
I have a command I've installed via npm (db-migrate
). I want to run it from the command line as part of automating database migration. The config file for the script can reference environment variables. I'm already setting database credentials as environment variables in another file. So rather than set them twice, I told the migration config to use the environment variables. The problem is, how do I get the environment variables from the file before running the migration script? Also, how can I run the migration script directly from the npm bin
?
I found a nice general solution to this problem, so I'm posting the question and the answer for at least the benefit of my future self.
Upvotes: 1
Views: 3139
Reputation: 6975
This can be done using a few tools:
PORT=3000 node index.js
But we want to read the variables from a file. This can be done using export
and xargs
:
export $(cat app.env | xargs)
bin
. The path to the bin
folder can be obtained using npm bin
. So we just need to add that to the path before running the command:PATH=$(npm bin):$PATH
export $(cat app.env | xargs) && PATH=$(npm bin):$PATH db-migrate up
This reads the environment variables, sets them, adds the npm bin
to the path, and then runs the migration script.
By the way, the content of app.env
would look something like this:
PORT=3000
DB_NAME=dev
DB_USER=dev_user
DB_PASS=dev_pass
UPDATE:
There are a few caveats with this method. The first is that it will pollute your current shell with the environment variables. In other words, after you run the export...xargs
bit, you can run something like echo $DB_PASS
and your password will show up. To prevent this, wrap the command in parens:
(export $(cat app.env | xargs) && PATH=$(npm bin):$PATH db-migrate up)
The parens cause the command to be executed in a subshell environment. The environment variables will not bubble up to your current shell.
The second caveat is that this will only work if your environment variables don't have spaces in them. If you want spaces, I found an OK solution based on this gist comment. Create a file named something like load-env.sh
:
# loads/exports env variables from a file
# taken from: https://gist.github.com/judy2k/7656bfe3b322d669ef75364a46327836#gistcomment-3239799
function loadEnv() {
local envFile=$1
local isComment='^[[:space:]]*#'
local isBlank='^[[:space:]]*$'
while IFS= read -r line; do
[[ $line =~ $isComment ]] && continue
[[ $line =~ $isBlank ]] && continue
key=$(echo "$line" | cut -d '=' -f 1)
value=$(echo "$line" | cut -d '=' -f 2-)
eval "export ${key}=\"$(echo \${value})\""
done < "$envFile"
}
Then run your command like this:
(source scripts/load-env.sh && loadEnv app.env && PATH=$(npm bin):$PATH db-migrate up)
Upvotes: 3