0

Attempting to set a user environment variable using input from a user in a bash script running in a makefile.

all:
    if[ ! $(ENV_VAR) ] ; then \
        read -p "What the variable?" env_var; \
        if [[ $$env_var == valid_value || $$env_var == other_valid_value ]]; then \
            echo export ENV_VAR=$$env_var >> /home/userName/.bashrc; \
            source /home/userName/.bashrc \
        else \
            echo $$env_var is an invalid value\; Try again; \
        fi \
    fi

This code doesn't work. Is there any way to run source in a bash script?

Here's an example of the output:

What the variable? valid_value
What the variable? valid_value
What the variable? valid_value
...

After running the script the ~/.bashrc file did get the appropriate export command. Running source after the script does make and environment variable I need. I just need it to run in the make script.

LukeDev
  • 509
  • 4
  • 19
  • 3
    Why do you think it needs to be interactive? – Barmar Dec 17 '21 at 17:27
  • 2
    Note that environment variables that are set in this script won't be available in other commands from the makefile. Each command is run in a separate subshell. – Barmar Dec 17 '21 at 17:29
  • add `.ONESHELL:` in the line before your `all` target – OrenIshShalom Dec 17 '21 at 18:17
  • @Barmar; I'm running source so that the environment will persist in all shells. But source won't do this if it's run in a non-interactive shell – LukeDev Dec 17 '21 at 18:19
  • 1
    `source` works the same in interactive and non-interactive shells. – Barmar Dec 17 '21 at 18:20
  • @OrenIshShalom What does `.ONESHELL` do? – LukeDev Dec 17 '21 at 18:20
  • @Barmar; sorry I misspoke, it's not source that needs the interactive shell, it's the .bashrc file. https://stackoverflow.com/questions/43659084/source-bashrc-in-a-script-not-working This answer has more details – LukeDev Dec 17 '21 at 18:22
  • @LukeDev It fixes what I said above about each command running in a separate subshell. They all run in the same shell. – Barmar Dec 17 '21 at 18:22
  • If your `.bashrc` exits when it's not interactive, fix that. – Barmar Dec 17 '21 at 18:26
  • 2
    BTW, changing your .bashrc in a makefile rule seems like a very strange thing to do. – Barmar Dec 17 '21 at 18:27
  • If your goal is to update the user's login shell environment, nothing you do in the makefile will work. It's running in a child process, it can't change the parent process's environment. – Barmar Dec 17 '21 at 18:28
  • The user needs to run `source ~/.bashrc` by hand after running the makefile. – Barmar Dec 17 '21 at 18:28
  • @Barmar; I need to add an environment variable in the make script and use it after without having the user run source. It can be done, part of my problem is I'm not super familiar with bash so I'm also having some syntax issues – LukeDev Dec 17 '21 at 18:30
  • `||` should be `-o` – Barmar Dec 17 '21 at 18:31
  • @Barmar The `||` is working fine for me. I already tested that – LukeDev Dec 17 '21 at 18:33
  • 1
    That's not possible. If you use `||` it needs to be `if [ ... ] || [ ... ]`. You can't use it in the middle of `[ ... ]` – Barmar Dec 17 '21 at 18:39
  • You can use it inside `[[ ... ]]` because that's special bash syntax. But make doesn't use bash, it uses sh. – Barmar Dec 17 '21 at 18:40
  • @Barmar my sh is using bash, so the second syntax is valid for make on my machine and the other machines this makefile will run on – LukeDev Dec 17 '21 at 18:40
  • 1
    But bash disables most of its extensions when it's run using the name `sh`. – Barmar Dec 17 '21 at 18:41
  • 2
    And you didn't use `[[`, so it doesn't matter. – Barmar Dec 17 '21 at 18:41
  • I didn't set up the machines, I just know that it's running bash in the shell. It's a CentOS variant if that means anything to you. Fixed my code, must've missed the `[[`. – LukeDev Dec 17 '21 at 18:44
  • Why do you think you need to source `~/.bashrc` for any of this? bashrc _isn't where environment variables should be set in the first place_; that's for `.bash_profile` -- `.bashrc` should be used for aliases, non-exported shell functions, and other process-local state. – Charles Duffy Dec 17 '21 at 18:45
  • ...and really, if you want to have software that automatically sets environment variables, it's better to build a whole new structure that's easy to edit. Say, have your `.bash_profile` look at files in `~/.env.d` and export a new variable for each file in that directory -- then you just create a file when you want to add a variable, delete the file to delete the variable, etc; and you don't have any of the pitfalls (a set that includes serious security concerns) that come from programmatically generating content that's run as code. – Charles Duffy Dec 17 '21 at 18:47
  • @CharlesDuffy honestly was just following info online (SO, other tutorials). Would I need to source .bash_profile for it to persist across shells? – LukeDev Dec 17 '21 at 18:49
  • So, the point of `.bash_profile` is that it should be used for things that are exported in the environment, so once it's sourced _once_ the values are provided to any child process. So the typical right way to use it is that you have your operating system / terminal window / etc set up to source `.bash_profile` _as part of the login process_ in a shell that acts as parent process to your GUI session / other apps, and everything it sets is available to other subprocesses started as part of the same session later. – Charles Duffy Dec 17 '21 at 19:15
  • Mind, that workflow means your environment variables are set _on login_, so if you change them then yes, you need to source the file again (or log out and back in). – Charles Duffy Dec 17 '21 at 19:18

0 Answers0