unix envsubst not picking local environment variables inside docker - envsubst

I've for a standard linux docker container that sets some environment variable E1=60 and installs a file myfile which is simply the line:
this is ${E1}
then runs the following script at container startup time:
#!/bin/sh
E1=80
export E1=80
cat myfile | envsubst
the output is:
this is 60
instead of:
this is 80
How do I make envsubst pick up my local/exported E1=80 variable?

resolved, the issue was that there was a previous script that substituted empty vars (which I wasn't aware of) and therefore, my envsubst calls didn't find them

Related

SSH run commands from local file and also pass local env variables

I need to run SSH on Linux and execute commands from a local file into the remote machine. This is working fine, but I also need to pass local environment variables to the remote machine, so the commands can use the values.
Here is the command I'm running:
ssh -i ${SSH_PRIV_KEY} ${SSH_USER}#${IP} < setup.sh
I have a bunch of environment variables set and when the remote machine runs the commands in setup.sh file it needs be able to use the env vars from the local machine.
I tried many things, this but solutions from other threads like this don't work correctly:
myVar='4.0.23'
export $myVar
ssh -i ${SSH_PRIV_KEY} ${SSH_USER}#${IP} myVar=myVar < setup.sh
Only thing I can come up with is to append the start of the file and hardcode the values there before executing ssh, but if possible I would like to find a cleaner solution because I want this to be reusable and the only thing that changes for me between runs is the env vars.
I ended up using this code to get the env vars I need to be stored in a file, then combine the files into one and pass that to the ssh as command:
envvars="
envvar='$envvar'
envvar2='$envvar2'
"
echo $envvars > envfile
cat envfile setup.sh > finalScript
cat $()
ssh -i ${SSH_PRIV_KEY} ${SSH_USER}#${IP} < finalScript

Bash export variables but only for current command

I want to load some environment variables from a file before running a node script, so that the script has access to them. However, I don't want the environment variables to be set in my shell after the script is done executing.
I can load the environment variables like this:
export $(cat app-env-vars.txt | xargs) && node my-script.js
However, after the command is run, all of the environment variables are now set in my shell.
I'm asking this question to answer it, since I figured out a solution but couldn't find an answer on SO.
If you wrap the command in parentheses, the exports will be scoped to within those parens and won't pollute the global shell namespace:
(export $(cat app-env-vars.txt | xargs) && node my-script.js)
Echo'ing one of the environment variables from the app.env file after executing the command will show it as empty.
This is what the env command is for:
env - run a program in a modified environment
You can try something like:
env $(cat app-en-vars.txt) node my-script.js
This (and any unquoted $(...) expansion) is subject to word splitting and glob expansion, both of which can easily cause problems with something like environment variables.
A safer approach is to use arrays, like so:
my_vars=(
FOO=bar
"BAZ=hello world"
...
)
env "${my_vars[#]}" node my-script.js
You can populate an array from a file if needed. Note you can also use -i with env to only pass the environment variables you set explicitly.
If you trust the .txt's files contents, and it contains valid Bash syntax, you should source it (and probably rename it to a .sh/.bash extension). Then you can use a subshell, as you posted in your answer, to prevent the sourced state from leaking into the parent shell:
( source app-env-vars.txt && node my-script.js )
If you file just contains variables like
FOO='x y z'
BAR='bar'
...
you can try
eval $(< app-en-vars.txt) node my-script.js

Import PATH environment variable into Bash script launched with cron

When creating Bash scripts, I have always had a line right at the start defining the PATH environment variable. I recently discovered that this doesn't make the script very portable as the PATH variable is different for different versions of Linux (in my case, I moved the script from Arch Linux to Ubuntu and received errors as various executables weren't in the same places).
Is it possible to copy the PATH environment variable defined by the login shell into the current Bash script?
EDIT:
I see that my question has caused some confusion resulting in some thinking that I want to change the PATH environment variable of the login shell with a bash script, which is the exact opposite of what I want.
This is what I currently have at the top of one of my Bash scripts:
#!/bin/bash
PATH=/usr/local/sbin:/usr/local/bin:/usr/bin:/usr/bin/site_perl:/usr/bin/vendor_perl:/usr/bin/core_perl
# Test if an internet connection is present
wget -O /dev/null google.com
I want to replace that second line with something that copies the value of PATH from the login shell into the script environment:
#!/bin/bash
PATH=$(command that copies value of PATH from login shell)
# Test if an internet connection is present
wget -O /dev/null google.com
EDIT 2: Sorry for the big omission on my part. I forgot to mention that the scripts in question are being run on a schedule through cron. Cron creates it's own environment for running the scripts which does not use the environment variables of the login shell or modify them. I just tried running the following script in cron:
#!/bin/bash
echo $PATH >> /home/user/output.txt
The result is as follows. As you can see, the PATH variable used by cron is different to the login shell:
user#ubuntu_router:~$ cat output.txt
/usr/bin:/bin
user#ubuntu_router:~$ echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games
Don't touch the user's PATH at all unless you have a specific reason. Not doing anything will (basically) accomplish what you ask.
You don't have to do anything to get the user's normal PATH since every process inherits the PATH and all other environment variables automatically.
If you need to add something nonstandard to the PATH, the usual approach is to prepend (or append) the new directory to the user's existing PATH, like so:
PATH=/opt/your/random/dir:$PATH
The environment of cron jobs is pretty close to the system's "default" (for some definition of "default") though interactive shells may generally run with a less constrained environment. But again, the fix for that is to add any missing directories to the current value at the beginning of the script. Adding directories which don't exist on this particular system is harmless, as is introducing duplicate directories.
I've managed to find the answer to my question:
PATH=$PATH:$(sed -n '/PATH=/s/^.*=// ; s/\"//gp' '/etc/environment')
This command will grab the value assigned to PATH by Linux from the environment file and append it to the PATH used by Cron.
I used the following resources to help find the answer:
How to grep for contents after pattern?
https://help.ubuntu.com/community/EnvironmentVariables#System-wide_environment_variables

Command NOT found when called from inside bash script

I have an application named puppet installed on my Linux box. It is installed at location /usr/test/bin/puppet
This is how .bash_profile looks
export PATH=/usr/test/bin
if I run command puppet apply from console, it works fine but when I call puppet command from inside bash script, it says command not found
#!/bin/bash
puppet apply x.pp
Any ideas on what is wrong ?
.bash_profile is loaded only if bash is invoked as login shell (bash -l or from a real tty), at least in Debian based distributions bash in a virtual tty (for example when using xterm, gnome-terminal, etc...) is invoked as interactive shell.
Interactive shells loads the configuration from ~/.bashrc.
bash manpage:
~/.bash_profile
The personal initialization file, executed for login shells
~/.bashrc
The individual per-interactive-shell startup file
Shellscripts don't load any of these.
You can check which files are opened by any program with strace:
strace ./s.sh 2>&1 | grep -e stat -e open
Possible solutions:
You can export the variable at the beginning of every script:
#!/bin/bash
export PATH=$PATH:...
Or you can have another file with the desired variables and source it from any script that need those:
/etc/special_vars.sh:
export PATH=$PATH:...
script:
#!/bin/bash
. /etc/special_vars.sh
puppet ...
Configure the PATH in in ~/.bashrc, ~/.bash_profile and ~/.profile for the user running the script (sub-processes will inherit the environment variables) to have some warranty that the user can run the script from different environments and shells (some bourne compatible shells others than bash do load ~/.profile)
Maybe the export of PATH is wrong?
export PATH=$PATH:/usr/test/bin/puppet
You could try using an alias, like so
in your .bash_profile:
alias puppet='bash puppet.fileextension'
you can also do
alias puppet='bash path/to/puppet.fileextension'
which will let you run the script from anywhere in Terminal.
EDIT:
OP has stated in the comments that there will be two different systems running, and he asked how to check the file path to the bash file.
If you do
#!/bin/bash
runPuppet(){
if [ -e path/to/system1/puppet.fileextension]
then
bash path/to/system1/puppet.fileextension $1 $2
elif [ -e path/to/system2/puppet.fileextension]
then
bash path/to/system2/puppet.fileextension $1 $2
fi
}
runPuppet apply x.pp
and change the runPuppet input to whatever you'd like.
To clarify/explain:
-e is to check if the file exists
$1 & $2 are the first two input parameters, respectively.

--environment argument given to ember is ignored if export EMBER_ENV is run

When I run this in a bash file, the argument environment is not received by the ember app:
#!/bin/bash
# create nginx.conf
echo "Create nginx.conf from nginx.conf.erb"
export `cat ./.env`
erb ./config/nginx.conf.erb > ./config/nginx.conf
./node_modules/ember-cli/bin/ember serve --environment=acceptance
I think it has something to do with the export function. When I put the ember serve command before the export it works.
The .env file looks like this
EMBER_ENV=development
Running bash 3.2 on Mac OS 10.10 (Yosemite)
Edit: I changed the question because it didn't have all the relevant code
In this case, you're giving ember two conflicting arguments: You're passing EMBER_ENV=development through the environment, and --environment=acceptance through the command line. The former tells it to use the environment named development, and the latter tells it to use the environment named acceptance -- but it can't do both at the same time.
Knowing which of those two conflicting commands ember will choose to honor is an item for which you'd need to check its documentation for. Of course, the better thing is just to fix the conflict.
I'd suggest doing the following:
./node_modules/ember-cli/bin/ember serve "--environment=${EMBER_ENV:-acceptance}"
...if you want to honor the EMBER_ENV in your file rather than the one on the command line (but fall back to acceptance when the file doesn't specify an EMBER_ENV). If you use bash -x, you'll explicitly see the script passing a --environment= appropriate to what's given in the .env file.
If you always want to use the environment acceptance, on the other hand, override or remove the environment after loading it from your file:
export `cat ./.env`
# if the file contained `EMBER_ENV`, unset it so our command-line argument is honored
unset EMBER_ENV
./node_modules/ember-cli/bin/ember serve --environment=acceptance
All that said --
export `cat ./.env`
is actually a quite buggy way to do things (though it won't break if the only thing you're setting is EMBER_ENV, and the only value it has is a single word in all ASCII with no whitespace or special characters). If you trust your .env file to be written by a non-malicious user in valid shell syntax, you'd have fewer bugs with:
set -a # automatically export all variables
source .env # run .env as a shell script within the current interpreter
If you don't trust your .env to be written as a non-malicious script in valid shell syntax, then perhaps something more like:
while IFS='=' read -r k v;
[[ $k ]] || continue # skip empty lines
printf -v "$k" %s "$v" || continue # set any variable given as a shell variable
export "$k" # export those variables to the environment
done < .env

Resources