How to set global environment variables at boot through a script, and have them available for an application that runs before login?

59,019

Solution 1

You can try putting a script to gather the variables in /etc/profile.d/

Example:

/etc/profile.d/somescript.sh

#!/bin/bash
TEST=$(cat /var/somefile)
export $TEST

/etc/profile does a call that will run any script in /etc/profile.d/, and this applies to all users on the system including root.

Solution 2

There is no way for a process to influence the environment of another existing process. Processes only influence the environment of their child processes.

So you need to set these environment variables in an ancestor of the application that needs them. Instead of having your service separately invoke the environment-setting bash script and the application, have your service invoke a bash script that sets the environment variables then launches the application.

#!/bin/bash
. /path/to/environment/variable/setter.bash
exec /path/to/application
Share:
59,019
barn
Author by

barn

Software Engineer and tech enthusiast.

Updated on September 18, 2022

Comments

  • barn
    barn almost 2 years

    I have a service that runs at boot, and in that service it calls a bash script in the background that exports some environment variables. The problem I'm having is that those environment variables are not being sent to the parent of the background process so as soon as my script is done executing, they are gone.

    In addition, after the script is run the service then calls another script that starts an application that I have. This application needs access to those environment variables.

    The RHEL system I run it on is meant to never be logged in to by the user, it only boots up and starts the application. I know that environment variables for a parent process/shell can't really be set by a child background process shell though.

    I need a way to do this through a script that gets called by my service (not necessarily in the background though), not by adding them in my service (which didn't work either for me) and not by storing them in an /etc/environment or .profile or anything such as that.

    In my service I tried adding the environment variables (not what I want to do though):

        export TEST=192.168.1.1
    

    I also tried this in my service:

        TEST=192.168.1.1
        export TEST=${TEST}
    

    I tried changing how my service calls the bash script:

        /bin/asdf/script &
    

    I also tried sourcing the script so that it runs in the same shell (which I got from this):

        . ./bin/asdf/script
        #I'm very confused why this didn't work
    

    I also found this which looked interesting but it didn't really pan out in my case.

  • barn
    barn over 12 years
    From what I have read online, there are hacks (something having to do with eval on a source script, or using gdb) to get it to work though. I'm not overly interested in it being in the background, if I can run the commands in the current "shell" (are you in a shell during boot when your service is executing?) then that would be fine too.
  • barn
    barn over 12 years
    Unfortunately, I cannot start the application from the service, as there are many different processes that are started and things that are configured from the application start script, and they must be kept separate from the service for IA.
  • Gilles 'SO- stop being evil'
    Gilles 'SO- stop being evil' over 12 years
    @sqenixs A shell is a process like any other. There is no such thing as “being in a shell”. When you speak of “eval on a source script”, that's a protocol where a program (which may of may not be a shell script) prints out definitions in shell syntax, and a shell script interprets them. Setting environment variables with gdb could work, or it could have no effect, or it could crash your application; as you might imagine, using a debugger in production is not recommended (and, again, for good reason).
  • Gilles 'SO- stop being evil'
    Gilles 'SO- stop being evil' over 12 years
    There's probably a solution to your problem, but you need to be more precise with your requirements. In your question, you write “after the script is run the service then calls another script that starts an application”. So you seem to have a solution: set the environment variables inside that other script. But then in a comment you write that you “cannot start the application from the service”. So, which is it?
  • Nikhil Mulley
    Nikhil Mulley over 12 years
    perhaps, make or configure the environment of /sbin/init at the boot time. Since every process is a child of init anyways, child process can acquire the environment. Just a thought/guess.
  • barn
    barn over 12 years
    I cannot start the application directly from the service but I can start it from the service by calling a script that does it. I would like to keep the setting of the environment variables separate from the script that starts the application to abstract out as much functionality that does not need to be in the application start script as possible.
  • barn
    barn over 12 years
    You may be on to something here. I don't want to do exactly that though since the script cannot be located in the /etc directory for IA reasons. But I think I can create a symlink in there that points to my script. But to complicate things, some of the environment variables that are set by the script are coming from environment variables set by the service. So this might not work, since the variables have to already be set before the service script gets to the end, but not too early or the environment variables needed won't have been created by the service yet.
  • barn
    barn over 12 years
    I guess I can get rid of the dependency on the variables set in the service. In this case, I think it will work, as long as the script gets run before the service starts up. Do you know when the login shell is started up? Or can I control when the login shell starts up? I don't have a service for it in the rcX.d directory for my run level .
  • Slavik
    Slavik about 4 years
    it works, when I run echo $TEST as my user. It also works, when I do sudo echo $TEST, but it doesn't work when I become root via sudo su and run echo $TEST as the root.