Where can I store variables and values for current Unix user so that I can use them in SSH and scripts? - bash

I have some variables I use quite frequently to configure and tweak my Ubuntu LAMP server stack but I'm getting tired of having to copy and paste the export command into my SSH window to register the variable and its value.
Essentially I would like to keep my variables and their values in a file inside the user profiles home directory so when I type a command into a SSH window or execute a bash script the variables can be easily used. I don't want to set any system-wide variables as some of these variables are for setting passwords etc.
What's the easiest way of doing this?
UPDATE 1
So essentially I could store the variables and values in a file and then each time I login into a SSH session I call this file up once to setup the variables?
cat <<"EOF" >> ~/my_variables
export foo='bar'
export hello="world"
EOF
ssh root#example.com
$ source ~/my_variables
$ echo "$foo"
$ bar
and then to call the variable from within a script I place source ~/my_variables at the top of the script?
#!/bin/bash
source ~/my_variables
echo "$hello"

Just add your export commands to a file and then run source <the-file> (or . <the-file> for non-bash shells) in your SSH session.

Related

Old version of script is run unless invoked with "sh scriptname"

I'm making a small edit to a shell script I use to mask password inputs like so:
#!/bin/bash
printf "Enter login and press [ENTER]\n"
read user
printf "Enter password and press [ENTER]\n"
read -s -p pass
With the read -s -p pass being the updated part. For some reason I'm not seeing the changes when I run it normally by entering script.sh into the command line but I do see the changes when I run sh script.sh. I've tried opening new terminal windows, and have run it in both ITerm and the default Mac terminal. I'm far from a scripting master, does anyone know why I'm not seeing the changes without the prefix?
Use a full or relative path to the script to make sure you're running what you think you're running.
If you are running it as simply script.sh then the shell will PATH environment variable lookup to locate it. To see which script.sh bash would be using in that case, run type script.sh.
Relative Path
./script.sh
Full Path
/path/to/my/script.sh

How to Set docker container ip to environment variable dynamically on startup?

I want to export docker container hostname as an environment variable which I can later use in my app. In my docker file I call my script "run" as last command
CMD run
The run file is executable and works fine with rest of commands I perform but before them I want to export container hostname to an env. variable as follows
"run" File Try 1
#!/bin/bash
export DOCKER_MACHINE_IP=`hostname -i`
my_other_commands
exec tail -f /dev/null
But when I enter docker container and check, the variable is not set. If I use
echo $DOCKER_MACHINE_IP
in run file after exporting, it shows ip on console when I try
docker logs
I also tried sourcing another script from "run" file as follows
"run" File Try 2
#!/bin/bash
source ./bin/script
my_other_commands
exec tail -f /dev/null
and the script again contains the export command. But this also does not set the environment variable. What I am doing wrong?
When you execute a script, any environment variable set by that script will be lost when the script exits.
But for both the cases you've posted above the environment variable should be accessible for the commands in your scripts, but when you enter the docker container via docker run you will get a new shell, which does not contain your variable.
tl;dr Your exported environment variable will only be available to sub shells of the shell which set the variable. And if you need it when logging in you should source the ./bin/script file.

set docker-machine variables using a bash script

I have a script like so:
#!/usr/bin/env bash
eval $(docker-machine env default)
The goal is to automate the setting of variables like
export DOCKER_TLS_VERIFY
export DOCKER_HOST
export DOCKER_CERT_PATH
export DOCKER_MACHINE_NAME
But when I check afterwards, the variables are not set. This is not the case if I run each export command manually. What am I doing wrong?
export makes variables available only to the active shell session. If you want them to persist through sessions, you must add them to your bash profile:
docker-machine env default >> ~/.bash_profile
This way, the variables will be available in all future shell sessions. Make sure to restart the shell after executing the command.
If you want the environment set in your current shell you need to "source" the script rather than run it.
When you run a script, the variables will be set in the child bash processes environment and will not exist once that script/process dies.
$ ./machine.sh
DOCKER_HOST is tcp://192.168.99.100:2376
$ echo "[$DOCKER_HOST]"
[]
When you source a script, the variables will be set in your current environment
$ . machine.sh
DOCKER_HOST is tcp://192.168.99.100:2376
$ echo "[$DOCKER_HOST]"
[tcp://192.168.99.100:2376]

Append to a remote environment variable for a command started via ssh on RO filesystem

I can run a Python script on a remote machine like this:
ssh -t <machine> python <script>
And I can also set environment variables this way:
ssh -t <machine> "PYTHONPATH=/my/special/folder python <script>"
I now want to append to the remote PYTHONPATH and tried
ssh -t <machine> 'PYTHONPATH=$PYTHONPATH:/my/special/folder python <script>'
But that doesn't work because $PYTHONPATH won't get evaluated on the remote machine.
There is a quite similar question on SuperUser and the accepted answer wants me to create an environment file which get interpreted by ssh and another question which can be solved by creating and copying a script file which gets executed instead of python.
This is both awful and requires the target file system to be writable (which is not the case for me)!
Isn't there an elegant way to either pass environment variables via ssh or provide additional module paths to Python?
How about using /bin/sh -c '/usr/bin/env PYTHONPATH=$PYTHONPATH:/.../ python ...' as the remote command?
EDIT (re comments to prove this should do what it's supposed to given correct quoting):
bash-3.2$ export FOO=bar
bash-3.2$ /usr/bin/env FOO=$FOO:quux python -c 'import os;print(os.environ["FOO"])'
bar:quux
WFM here like this:
$ ssh host 'grep ~/.bashrc -e TEST'
export TEST="foo"
$ ssh host 'python -c '\''import os; print os.environ["TEST"]'\'
foo
$ ssh host 'TEST="$TEST:bar" python -c '\''import os; print os.environ["TEST"]'\'
foo:bar
Note the:
single quotes around the entire command, to avoid expanding it locally
embedded single quotes are thus escaped in the signature '\'' pattern (another way is '"'"')
double quotes in assignment (only required if the value has whitespace, but it's good practice to not depend on that, especially if the value is outside your control)
avoiding of $VAR in command: if I typed e.g. echo "$TEST", it would be expanded by shell before replacing the variable
a convenient way around this is to make var replacement a separate command:
$ ssh host 'export TEST="$TEST:bar"; echo "$TEST"'
foo:bar

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