Execute same command for each non-interactive bash session

.bash-profilebashbashrcshell

I need to implement some config – I need to execute some code, if someone on my system calls for bash command in any form (interactive, non-interactive and bash -c form). For example this is command I want to add to each bash call:
touch /tmp/$RANDOM
I added that line to /bash/bash.bashrc and it works fine for logon shell and for shells, which was initalized by calling bash command.
But this will not work for bash session initialized like this:
bash -c 'echo 1' – new file will not be created

From documentation I understand, that bash.bashrc and bash_profile called only for logon or interactive shells.
Is there any way to create some similar calls for non-interactive shells too?

Best Answer

To make bash parse a file when invoked as a non-interactive shell, you need to set the environment variable BASH_ENV to point to that file. From man bash (section on INVOCATION):

When bash is started non-interactively, to run a shell script, for example, it looks for the variable BASH_ENV in the environment, expands its value if it appears there, and uses the expanded value as the name of a file to read and execute. Bash behaves as if the following com‐ mand were executed:

    if [ -n "$BASH_ENV" ]; then . "$BASH_ENV"; fi

but the value of the PATH variable is not used to search for the file‐ name.

So where to set BASH_ENV?

Either: If you want a variable to be available to the environment system-wide, a good place to put it is /etc/environment. This file is specifically made for system-wide environment variable settings. It is not parsed by the shell but by the PAM module pam_env, so you can not use shell syntax or variable expansion within, but only simple assignments of the following type:

    VARIABLE=value

or

    VARIABLE=/full/path/to/file

Changes will take effect at the next login/authentication, so switch to a new tty console or logout and re-login to your session.

On a standard desktop system, this should work for all types of authenticated sessions using PAM, including console logins, ssh and display managers, but also daemons such as atd and cron. If everything works as expected, then you are done and there is no need to read on.

However, mistakes do occasionally sneak into the PAM configuration files of some programs/distributions, so if /etc/environment is not parsed by a certain type of program, make sure that the necessary PAM module is loaded in the PAM configuration file for that program in /etc/pam.d:

    session       required   pam_env.so readenv=1

(Note: The readenv flag which turns reading of the config file on/off should not actually be needed, since it is set to on (1) by default - but it doesn't hurt to make sure either.)

Or: If you are working on a system that does not provide pam_env, then the best alternative that comes to my mind would be write a simple init script (or service unit file on systemd) that parses a custom config file (such as /etc/default/environment) at boot.