0

I would like to set environment variables for the scope of a terminal session.

Eg, the user would open a terminal, type something like setproject <project_name> and it would export an environment variable PROJECT. When they close the terminal, the variable setting is lost. What was impressive with this system was that it would know what project name was valid and what wasn’t. I’ve worked at places that have done this quite well and I’m wondering how it’s done.

I’d prefer the user not have to type source setproject <project_name> and I also wanted to check if the project they specified was valid or not.

I’ve written something in python, which checks the validity of a project name (against a yaml config file), and passes it on to a bash script, but it doesn’t really work (the environment variable isn’t properly set. It’s set, but only for the scope of the python script)

So, how’d I do this? Are there any good examples of what I’m looking for online?

Adrian
  • 13
  • 2
  • If the user is not to call a command, e.g. `source`, how will the system know what `PROJECT` settings to use? – JohanL Sep 23 '18 at 04:52
  • environment variables are set for the scope of a *process* and its children, not for processes sharing the same terminal session. So using another language process like python could never work. – cdarke Sep 23 '18 at 07:10
  • This is what I thought, so it'd need to be a bash script? – Adrian Sep 23 '18 at 07:25

1 Answers1

3

You can't do this with a normal command -- normal commands (shell scripts, python scripts, binaries, whatever) run as a subprocess under the main shell process, and cannot affect the main shell process's environment. But the shell supports a couple of command-like things that "happen" in the shell itself: functions and aliases. These both need to be defined in the shell before they can be used, so you'd need to put the definition in .bash_profile (or whatever the appropriate shell init file is in your setup -- see here).

The way I would do this would be to define setproject as a shell function, something like this:

# ...in shell init file...
setproject() {
    if [ some_test_for_project_validity ]; then
        export PROJECT="$1"
    else
        echo "setproject: $1 is not a valid project name" >&2
        return 1
    fi
}

The logic you need here is too complicated to put in an alias (they're much simpler and dumber than functions), but you could put the actual script in a separate file and use an alias to avoid having to explicitly source it:

# ...in shell init file...
alias setproject='source /path/to/setproject'

 

# .../path/to/setproject...
# note no shebang, since it won't be run as a normal command
if [ some_test_for_project_validity ]; then
    export PROJECT="$1"
else
    echo "setproject: $1 is not a valid project name" >&2
    return 1    # In a file to be source'd, use return instead of exit
fi
Gordon Davisson
  • 118,432
  • 16
  • 123
  • 151