0

I would like to use an environment variable I have declared in /etc/environment as a counter which should be accessible to several unrelated scripts that are run at different times.

Is that possible? So far, I had no luck trying exporting its value.

I guess, I could always use a temporary file to store current value, read/write to it but I'm looking for a more elegant way if there is any?

S.R.
  • 393
  • 2
    What happens if two scripts try to change the counter simultaneously? I’d rather use a file which contains the counter value and lock it as explained here and here. – dessert May 15 '18 at 11:50
  • mktemp is elegance in its purest form. ;) – dessert May 15 '18 at 12:00
  • 1
    The issue probably isn't persistence - it's that the other scripts will need to re-source their environment for any modified value to take effect – steeldriver May 15 '18 at 12:00
  • Good point, but I'd take care that doesn't happen. I agree, using a file instead is a way to achieve the same although, what happens if two scripts try to change the value in the file simultaneously ;) I'm mostly asking to improve my understanding of how environment is working. And it would be wonderful if it is somehow possible. – S.R. May 15 '18 at 12:00

3 Answers3

1

The short answer is "No, you can't permanently change an environment variable from within a Bash script".

The longer answer is that when a Bash script is executed it receives a copy of the environment (not references to the environment variables themselves). So, whilst you can change the values of the copies within your script, those changes will be lost when the script exits and are also not visible to other scripts you may be running concurrently.

You can however, change an environment variable with a Bash script by "source"-ing it from the command line:

source  your_script_name
muru
  • 207,970
  • Thanks Peter, I just took a look at "source-ing" and it doesn't cut it for this purpose. I need to pass a variable from a Nemo script to a script that is executed by an applet so, the only viable way seems to be the use of a temporary file as dessert pinpointed. – S.R. May 15 '18 at 12:45
1

The changes will not be absolutely permanent but you can keep the changes to the environment variable as long as you are in the same login shell from which you executed the script.


There are multiple commands to execute a shell script, each command has it's own way to execute it. If you ran the script using the dot(.) operator, the script is executed within the same shell instead of opening another shell for the execution.

. myscript.sh

Hence, the changes to the environment variable made in that script will persist as long as it is executed using dot(.) and the shell from which it was executed is not closed.

0

For years, I've been grappling with this limitation in Bash: not being able to execute a script and update my parent shell's environment variables directly. This issue has been a constant annoyance. Then it hit me, I devised a workaround. It's not perfect, and admittedly, it's a bit of a hack, but it effectively simulates what seemed impossible. If you're able to modify the user's .bashrc, you can cleverly fake direct script execution and dynamic environment configuration. Here's how you can set it up:

Step 1: Create the env_setup.sh Files

Before setting up functions and aliases in your .bashrc, ensure that the env_setup.sh scripts exist in the locations you plan to manage them from, whether it's in specific project directories or more globally accessible locations in your PATH.

Create a basic env_setup.sh script with necessary environment variable exports:

# Example env_setup.sh
export PATH="/usr/local/bin:$PATH"
export MY_ENV_VAR="some_value"

Save this script in the directories where you frequently work, or place it in a directory that's part of your system's PATH to ensure it's universally accessible.

Step 2: Define Functions

To begin, you need to define two functions in your .bashrc file. These functions are crucial for managing the sourcing of scripts, whether they're in the current directory or elsewhere in your system's PATH.

Open your .bashrc in a text editor:

vim ~/.bashrc

Add the following functions:

# Function to source a script from the current directory
env_setup_func_dot() {
    if [ -f "./env_setup.sh" ]; then
        source ./env_setup.sh
    else
        echo "env_setup.sh not found in the current directory!"
        return 1
    fi
}

Function to search and source the script from the PATH

env_setup_func_nodot() { local script_path=$(which env_setup.sh) if [ -n "$script_path" ]; then source "$script_path" else echo "env_setup.sh not found in the PATH!" return 1 fi }

Step 3: Create Aliases

Setting up aliases that users can call as if they were actual scripts enhances usability. Here’s how you can set these aliases:

alias ./env_setup.sh='env_setup_func_dot'
alias env_setup.sh='env_setup_func_nodot'

Step 4: Reload .bashrc

To apply these changes and make the functions and aliases available in your current session, reload your .bashrc:

source ~/.bashrc

With this setup, you can effectively mimic executing scripts directly and managing the shell environment in ways that originally seemed off-limits.

Considerations

Using dots in alias names is unconventional and may lead to confusion, as it's easy to mistake such aliases for file names or commands typically reserved for executables or scripts. While this setup works technically, it's essential to ensure that such usage is clearly documented if shared in a collaborative environment or deployed in a production setting.