How do I set bash environment variables from a script? - bash

I have some proxy settings that I only occasionally want to turn on, so I don't want to put them in my ~/.bash_profile. I tried putting them directly in ~/bin/set_proxy_env.sh, adding ~/bin to my PATH, and chmod +xing the script but though the script runs, the variables don't stick in my shell. Does anyone know how to get them to stick around for the rest of the shell session?

Use one of:
source <file>
. <file>

In the script use
export varname=value
and also execute the script with:
source set_proxy_env.sh.
The export keyword ensures the variable is marked for automatic inclusion in the environment of subsequently executed commands. Using source to execute a script starts it with the present shell instead of launching a temporary one for the script.

Did you try this:
. ~/bin/set_proxy_env.sh
Running it by itself opens a separate subshell (I think) and sets the variable there. But then the binding is lost after exiting back into your shell. The dot at the front tells it to run it within the same shell.
Also, don't forget to export the variables you need like so: export MYVAR=value

Related

Makefile to add shell aliases

I am already using a makefile, and I was hoping to be able to use it to store a few useful aliases that the user could then invoke. I know that I can make a bash file with the aliases already built in, so and run it with source, so I can do something like:
# File: aliases.sh
alias useful="command to run"
alias also-useful="another command -to run"
Then I can run this in the current terminal session with:
source ./aliases.sh
Using a Makefile
So I was hoping to achieve something similar with a makefile, I was hoping to have a simple aliases entry, so the user could just run:
make aliases
I prefer to avoid adding an extra file if this is at all possible, because I don't want to add extra files for such simple tasks. If you have any suggestions that would be better, I'd be open to hearing them too.
If what you're asking is for make aliases to create aliases that you can then invoke at your shell prompt, something like:
$ make aliases
$ useful
then that is impossible and the reason has nothing to do with make.
In a UNIX/POSIX system the process hierarchy is strict: a process starts one or more sub-processes, and each of those can start more, etc. So a login manager process starts your shell (or your window manager), your shell starts make, which is another process, and make will run another shell as a subprocess to run each recipe, and each shell will run programs like compilers, commands like rm which are also processes, etc.
It is a fundamental rule of all processes that they cannot modify the environment (memory) of their parents (and they can only modify the environment of their children before they are started). So, if you start a new shell and change your working directory then exit that shell, the parent's shell is not changed. If you set an environment variable in the child process, the variable is not set in the parent. Etc.
Shell aliases are part of a particular shell's memory. So a program you start cannot create aliases in its parent shell. It doesn't matter if that program is make or anything else.
That's why you have to use the special command source to load those into your shell: instead of running a new shell, the source command tells the current shell to run the commands in the script as if you'd typed them in at the command line... so no new process is created and the current shell's environment and memory is modified. If you ran your aliases file as a shell script, via aliases rather than source aliases, then a new shell would be created, the aliases would be defined, then the shell would exit and all the aliases would be gone again.
So, all that to say it's not possible for make to define aliases in the shell that invokes it: the operating system won't allow it.

How can I store and execute the command "export PATH=$PREFIX/bin" from a script?

I would like to write a script that has several commands of the kind
> export PATH=$PREFIX/bin
Where
> $PREFIX = /home/usr
or something else. Instead of typing it into the the Shell (/bin/bash) I would run the script to execute the commands.
Tried it with sh and then with a .py script having the line,
> commands.getstatusoutput('export PATH=$PREFIX/bin')
but these result into the error "bad variable name".
Would be thankful for some ideas!
If you need to adjust PATH (or any other environment variable) via a script after your .profile and equivalents have been run, you need to 'dot' or 'source' the file containing the script:
. file_setting_path
source file_setting_path
The . notation applies to all Bourne shell derivatives, and is standardized by POSIX. The source notation is used in C shell and has infected Bash completely unnecessarily.
Note that the file (file_setting_path) can be specified as a pathname, or if it lives in a directory listed on $PATH, it will be found. It only needs to be readable; it does not have to be executable.
The way the dot command works is that it reads the named file as part of the current shell environment, rather than executing it in a sub-shell like a normal script would be executed. Normally, the sub-shell sets its environment happily, but that doesn't affect the calling script.
The bad variable name is probably just a complaint that $PREFIX is undefined.
Usually a setting of PATH would look something like
export PATH=$PATH:/new/path/to/programs
so that you retain the old PATH but add something onto the end.
You are best off putting such things in your .bashrc so that they get run every time you log in.

Changing the value of a export variable from a bash script

I did the following from a bash shell.
export myPath="/home/user/dir"
Then I verified the value of this by 'echo'ing this value from both shell and a inside a bash script. Both worked fine.
Then I tried setting the value of this variable from inside a script like this.
myPath="/home/user/newdir"
and tried printing this variable from shell. I thought the variable will hold the updated value, but it was showing the old value.
How can I update the value from a script? I am looking to do it without using source if possible.
To make the variables persist after the script finishes, you have to run it using the source command:
When a script is run using source it runs within the existing shell, any variables created or modified by the script will remain available after the script completes. In contrast if the script is run just as filename, then a separate subshell (with a completely separate set of variables) would be spawned to run the script.

Why are bash script variables not saving?

I have a simple bash script:
#!/bin/bash
JAVA_HOME=/usr
EC2_HOME=~/ec2-api
echo $EC2_HOME
export PATH=$PATH:$EC2_HOME/bin
I run the script like so
$ ./ec2
/Users/user/ec2-api
The script runs and produces the correct output.
However, when I now try to access the EC2_HOME variable, I get nothing out:
$ echo $EC2_HOME
I get a blank string back. What am I doing wrong?
Do either of the following instead:
source ec2
or
. ec2
(note the . notation is just a shortcut for source)
Explanation:
This is because ./ec2 actually spawns a subshell from your current shell to execute the script, and subshells cannot affect the environment of the parent shell from which it spawned.
Thus, EC2_HOME does get set to /Users/user/ec2-api correctly in the subshell (and similarly the PATH environment variable is updated and exported correctly in the subshell as well), but those changes won't propagate back to your parent shell.
Using source runs the script directly in the current shell without spawning a subshell, so the changes made will persist.
(A note on export: export is used to tell new shells spawned from the current shell to use the variables exported from the current shell. So for any variables you would only use in the current shell, they need not be exported.)
A shell script can never modify the environment of their parent.
To fix your problem, you can use the dot (.) command:
$ . ./ec2
and that should work. In cshell, it would be
% source ./ec2
To learn more about shells and scripts, my best resource is by far Unix power tools.

Save Global variables BASH

I am new at bash and trying to solve some issues for a code I'm trying to make.
I am at the terminal under my user name and connect to bash
USER$
USER$ bash
bash$
now in the bash I am saving some variables f.e:
i=2
k=2
let p=$k*$i
now I want to use those variables outside the bash function
bash$exit
USER$
but now the variables are not there
I try using export, but it did not really work, could use ur help, tnx
Not possible. You cannot set environment variables in a parent process like this.
Unlike a DOS batch file, a Unix shell script cannot directly affect the environment of its calling shell.
You could consider using the . (dot) or source command to read and execute the script in the context of the calling shell. This means that changes made in the script do affect the environment (in general; you can still run into issues with sub-shells).
The other alternative is to have the script that sets the variables write the values in name=value format into a file which the calling script then reads (with . or source again).
The conventional solution is to add the settings to your .profile or . bashrc -- which you should use depends on your specific needs and your local Bash configuration; my first recommendation would be .profile, but then you have to avoid any bashisms because this file is shared with sh (so, no let, for example).
For more specific needs, put the commands in a file, and source it when you need it. You might also want to create a simple script to update the file with your current values.
# source this file to update $HOME/stuff
cat<<HERE>$HOME/stuff
i='$i'
k='$k'
p='$p'
export i k p
HERE
The syntax here is quite simple, but assumes you don't have values which can contain single quotes or otherwise free-form content. How to safely store arbitrary values which you don't have complete control over is a much more complex discussion; I am providing a simple solution for the basic use case where you merely need to save a few simple scalar values, like numbers.
To keep your variables when you connect to a remote system, look at the documentation for the tool you are using to connect. For example, ssh has configuration options for importing environment variables from the local system when starting a remote session.

Resources