Score:2

sourcing environment variable in bashrc: directly vs export from file yields different result - why

it flag

I am running systemd via user (i.e. enable-linger $USER) and I interact with services via systemctl --user

I noticed a strange issue.

Sourcing Type 1

In order for the above systemd to work for a user, I need to add export XDG_RUNTIME_DIR=/run/user/$(id -u) inside my ~/.bashrc

This works fine.

Sourcing Type 2

When I instead source my bashrc as follows, the systemd does not work:

inside .bashrc:

source /path_to_file/my_file.env

inside my_file.env:

XDG_RUNTIME_DIR=/run/user/$(id -u)

Both Sourcing Type 1 and 2 yield the same result when I do echo $XDG_RUNTIME_DIR so I decided to go with Type 2. However then I noticed that when I do systemctl --user daemon-reload the daemon was not running and I got the following error:

Failed to connect to bus: No such file or directory

When I revert back to Souring Type 1, the error is gone and all works as expected.

My question is: What is happening that I am missing here? My main confusion stems from the fact that the env variables are the same, but the end results are not.

chepner avatar
in flag
`.env` files are not shell scripts and should not be sourced at all. Quoting rules are different, so the value assigned to a name by a `.env` parser may be different than what the shell will assign.
Score:4
fr flag

You forgot the export in your .env file, so the variable isn't actually an environment variable.

Shell variables are not exported to environment by default. Only assignments to an already exported variable will be re-exported automatically; if XDG_RUNTIME_DIR is a brand new variable, it will become a shell internal variable unless you use the export or declare -x builtins. (Or unless the "allexport" shell option is enabled, but using it in .bashrc has some weird gotchas.)

echo $FOO "sees" the variable because the expansion of $FOO in command-line is done by the shell interpreter itself, not by the command – 'echo' doesn't have to access the environment at all, whereas 'systemctl' does.

Instead of echo, you could use declare -p FOO to have the shell itself tell you the variable's state (including showing the x flag if the variable is exported), or use env or printenv to see what the environment looks like from the point of view of an external process (non-exported shell variables simply won't show up here).

Either way, you should never need to do this for interactive logins. This specific variable is supposed to be put in your environment through PAM (by pam_systemd) as soon as you log in – even before your shell is run.

For scripts that need to access another user's services, systemctl --user -M ${USER}@.host will make systemctl itself find the specified user's runtime directory and the D-Bus socket.

mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.