Eval in docker-machine: terminal vs shell script - bash

I'm trying to run a simple shell script to automate changing docker-machine environments. The problem is this, when I run the following command directly in the Mac terminal the following is outputted:
eval $(docker-machine env default)
docker-machine ls
NAME ACTIVE DRIVER STATE URL SWARM DOCKER ERRORS
default * digitalocean Running tcp://***.**.***.***:**** v1.12.0
So basically what you would expect, however when I run the following .sh script:
#!/usr/bin/env bash
eval $(docker-machine env default)
The output is:
./run.sh
docker-machine ls
NAME ACTIVE DRIVER STATE URL SWARM DOCKER ERRORS
default digitalocean Running tcp://***.**.***.***:**** v1.12.0
So basically, it is not setting it as active and I cannot access it.
Has anyone run into this issue before and knows how to solve it? Seems really strange to me, have got pretty much everything else running and automated apart from this facet.
Cheers, Aaron

I think you need to source your shell script
source ./myscript.sh
as the exports in the eval are being returned to the process you started to run the shell in and then being disposed of. These need to go to the parent e.g. login shell
Consider a.sh
#!/bin/bash
eval $(echo 'export a=123')
export b=234
when run in two ways
$ ./a.sh
$ echo $a
$ echo $b
$ source a.sh
$ echo $a
123
$ echo $b
234
$

Related

AWS EC2 User Data: Commands not recognized when using sudo

I'm trying to create an EC2 User-data script to run other scripts on boot up. However, the scripts that I run fail to recognize some commands and variables that I'd already declared. I'm running the commands as the "ubuntu" user but it still isn't working.
My user-data script looks something like this:
export user="ubuntu"
sudo su $user -c ". ./run_script"
Within the script, I have these lines:
THIS_PATH="/some/path"
echo "export SOME_PATH=$THIS_PATH" >> ~/.bashrc
source ~/.bashrc
However, the script can't run SOME_PATH/application, and echo $SOME_PATH this returns a blank line. I'm confused because $SOME_PATH/application works when I log into the EC2 using SSH and my debug logs using whoami returns "ubuntu."
Am I missing something here?
Your data script is executed as root and su command leaves $HOME and other ENV variables intact (note that sudo is redundant). "su -" does not help either
So, do not use ~ or $HOME but full path /home/ubuntu/.bashrc
I found out the problem. It seems that source ~/.bashrc isn't enough to restart the shell -- the environment variables worked after I referenced them in another bash script.

Setting environment variables in shell script OS X

I'm trying to create a Shell Script to automate my local dev environment. I need it start some processes (Redis, MongoDB, etc.), set the environment variables then start the local web server. I'm working on OS X El Capitan.
Everything is working so far, except the environment variables. Here is the script:
#!/bin/bash
# Starting the Redis Server
if pgrep "redis-server" > /dev/null
then
printf "Redis is already running.\n"
else
brew services start redis
fi
# Starting the Mongo Service
if pgrep "mongod" > /dev/null
then
printf "MongoDB is already running.\n"
else
brew services start mongodb
fi
# Starting the API Server
printf "\nStarting API Server...\n"
source path-to-file.env
pm2 start path-to-server.js --name="api" --watch --silent
# Starting the Auth Server
printf "\nStarting Auth Server...\n"
source path-to-file.env
pm2 start path-to-server.js --name="auth" --watch --silent
# Starting the Client Server
printf "\nStarting Local Client...\n"
source path-to-file.env
pm2 start path-to-server.js --name="client" --watch --silent
The .env file is using the format export VARIABLE="value"
The environment variables are just not being set at all. But, if I run the exact command source path-to-file.env before running the script then it works. I'm wondering why the command would work independently but not inside the shell script.
Any help would be appreciated.
When you execute a script, it executes in a subshell, and its environment settings are lost when the subshell exits. If you want to configure your interactive shell from a script, you must source the script in your interactive shell.
$ source start-local.sh
Now the environment should appear in your interactive shell. If you want that environment to be inherited by subshells, you must also export any variables that will be required. So, for instance, in path-to-file.env, you'd want lines like:
export MY_IMPORTANT_PATH_VAR="/example/blah"

Scripting Docker, Not Connected After Running Script?

So I have a script that looks like this:
#!/bin/bash
if [ $1 ]; then
docker-machine start $1
docker-machine env $1
eval $(docker-machine env $1)
docker ps -a
fi
Once it has run though, the scope of these commands seem to be over. For instance I don't have a connection to the docker-machine once the script has run, but I'd like to script this part out so I can have access to it.
For instance, after running this script ("./script.sh") I still can't run "docker ps -a".
What's the reason this happens and how could I get it to effectively be connected to after executing this script?
A script (or any other process) cannot modify the environment of its parent process. That is precisely why docker-machine env emits shell code that needs to be evaluated with eval.
If you want these variables accessible outside of your script, you would need to arrange to run eval $(docker-machine env <whatever>) in your current shell.

Archlinux + MATE Terminal - `.bash_profile` is not being sourced

I am using Arch Linux with MATE as desktop environment. So terminal emulator is MATE Terminal. Recently I installed Jekyll with gem install jekyll. But when I ran jekyll -v it says bash: jekyll: command not found. So I tried to add path of Jekyll to PATH variable.
I ran PATH=$PATH/$HOME/.gem/ruby/2.2.0/bin and it worked perfectly. Now I can run jekyll commands. To add it permanently to PATH variable I edited the ~/.bash_profile file like following. It is not working after reboot. But
source ~/.bash_profile works perfectly.
#
# ~/.bash_profile
#
[[ -f ~/.bashrc ]] && . ~/.bashrc
export PATH="${PATH}:/home/heisenberg/.gem/ruby/2.2.0/bin"
According to ArchWiki this is the proper way to concat something permanantly to PATH. But it isn't working. Can somebody figure me out where the wrong is?
[N. B. : Adding the same line in ~/.bashrc is doing okay.]
Depending on the option it is given, bash can be run as an interactive shell or login shell. The default interactive shell mode does not read ~/.bash_profile. login shell bash do.
See:
First, some setup:
% cat ~/.bashrc
…
export BASHRC="yes"
…
% cat ~/.bash_profile
…
export BASH_PROFILE="yes"
…
Now run a regular (interactive) bash:
% bash
[galaux#magenta ~]$ echo $BASHRC
yes
[galaux#magenta ~]$ echo $BASH_PROFILE
Notice we did not get yes with this last one.
Now with a login shell:
% bash --login
[galaux#magenta ~]$ echo $BASHRC
yes
[galaux#magenta ~]$ echo $BASH_PROFILE
yes
See paragraph INVOCATION from man bash.

Source environment variables and execute bash before running local script on remote machine [duplicate]

This question already has answers here:
Pass commands as input to another command (su, ssh, sh, etc)
(3 answers)
Closed 6 years ago.
I'm trying to execute the remote local script with ssh connection. I've read a document about the syntax of it. But my issue is that, before running the script, I need to execute bash and source environment variables.
This looks appropriate for me but it has not a source command :
ssh [user]#[server] 'bash -s' < [local_script]
I've tried such a thing with EOF but it didn't work for me too :
#!/bin/bash
/usr/bin/ssh "$user#$$host" <<EOF
bash -s
source /dir/to/profile/.profile
source /dir/to/env/set/env.sh
/path/to/script/script.sh stop
EOF
Do you have an idea for this type of implementation of remote commands ? I have to source profile before the environment settings otherwise it gives an exception. But the main problem is about source.
Maybe it was an easy question but I don't have any ideas. Thank you in advance for your all answers.
eval can accomplish this for you:
eval $(cat /path/to/environment) ./script.sh
You can source multiple files this way too if you want if you know there
path:
eval $(cat /path/to/environment1 /path/to/environment2) ./script.sh
Or iterate over a directory:
eval $(cat $(find -type f /path/to/environments)) ./script.sh
Stick SSH in front of it if you're doing this remotely to solve your specific problem:
# note the quotes otherwise we'll source our local environment
ssh user#host "'eval $(cat /path/to/environment)' ./remote_script.sh"
# If it's a local environment you want to sort, then do the same
# command without the quotes:
ssh user#host "eval $(cat /path/to/environment)" ./remote_script.sh
If you want to source a remote environment into your own then use eval
locally as so:
eval "$(ssh user#host cat /path/to/environment)" ./local_script.sh
This alls you to source an external file setting it's environment variables in the same forked instance that will calls your script (making them available).
Consider a script file that looks like this:
#!/bin/sh
echo "$VAR1"
echo "$VAR2"
test_function
Now consider your environment file looks like this:
# Environment Variables
VAR1=foo
VAR2=bar
test_function()
{
echo "hello world"
}
You'd see the output if you use the eval example:
foo
bar
hello world
Alternatively, if you just open up your script you wrote, you can source
these environment variables directly from within it and then you can just
call the script normally without any tricks:
#!/bin/sh
# Source our environment by starting with period an then following
# through with the full path to the environment file. You can also use
# the 'source' keyword here too instead of the period (.).
. /path/to/environment
echo "$VAR1"
echo "$VAR2"
test_function
I know it is old but just wanted to add that it can be done without an extra file - use '\' to escape local variables and remote command substitution - ie:
ssh me#somehost "RMTENV=\$(ls /etc/profile) && source \$RMTENV"
I use this to execute remote java commands and need the ENV to find java.
I fixed the problem by writing another template script that sources the environment variables and runs the script:
PROFILE=/dir/to/profile/.profile
source $PROFILE
cd /dir/to/script
/bin/bash script $1
If you use the source command with bash shell, #!/bin/bash doesn't work for the source command.

Resources