What happened to /etc/profile?

Some time ago, my servers started ignoring the content of /etc/profile

I have lines there that export LANG, LC_ALL, and EDITOR. It used to work. What’s the problem?
 
I'm going to guess you're not using a bourne (or compatible) shell (sh(1), bash(1), etc), those are the only ones that actually read it, csh(1) and tcsh(1) don't.

Note that you should NOT set LC_ALL to change your locale(1) settings. It's used to overrule all other locale(1) settings. It's not meant to be used as a "user" setting.
 
I have been using bash since the dawn of history. I didn’t change the server config but upgraded them as well as the CI servers. It stopped working everywhere.

Code:
# finger root && cat /etc/profile | grep export && locale && echo $EDITOR
Login: root                       Name: Charlie Root
Directory: /root                        Shell: /usr/local/bin/bash
Last login Mon Nov 16 04:52 (CET) on ttyv0
No Mail.
No Plan.
# BLOCKSIZE=K; export BLOCKSIZE
export LANG=en_US.UTF-8
export LC_ALL=en_US.UTF-8
export EDITOR=nano
LANG=
LC_CTYPE="C"
LC_COLLATE="C"
LC_TIME="C"
LC_NUMERIC="C"
LC_MONETARY="C"
LC_MESSAGES="C"
LC_ALL=

#
 
Hmm. Something I overlooked with regards to bash (I don't use it):
Code:
20200716:
  AFFECTS: users of shells/bash, shells/bash-static
  AUTHOR: ehaupt@FreeBSD.org

  In order to cleanly decouple bash from base, bash now reads `profile` from
  LOCALBASE/etc insead of from /etc. If you are using system wide bash
  configuration in /etc/profile please migrate to LOCALBASE/etc/profile

  # cp /etc/profile /usr/local/etc/profile

  or create a symlink

  # ln -s /etc/profile /usr/local/etc/

  If you encounter the following error, you may have the obsolete
  /lib/libreadline.so.8 lying around after an incomplete base update:

  ld-elf.so.1: Undefined symbol "rl_signal_event_hook" referenced from COPY relocation in /usr/local/bin/bash

  Please refer to to (23.5.6.2) in the FreeBSD Handbook on how to
  safely check for outdated files and libraries:

  https://www.freebsd.org/doc/en/books/handbook/makeworld.html
 
Yes, it started about a half year ago. Thank you, SirDice. I didn’t find it.

Although I don’t find this change logical. The point of /etc/profile is to set it for all users and any shell. Bash should read both /etc/profile and something like /usr/local/etc/bash_profile
 
A link (ln -s /etc/profile /usr/local/etc/) causes /etc/profile to be loaded twice. This leads to loading /etc/profile.d/* and /usr/local/etc/profile.d/* twice as well. The issue is that /etc/profile (at least in 14.0-RELEASE) is trying to avoid this recursion by checking whether it tries to load itself. But since "/usr/local/etc/profile" is not equal to "/etc/profile", this check fails. If the profile settings are just setting variables, this is probably not an issue (just a bit of waste time). However, if making output like a login banner (e.g. using the "td-system-tools" package, which installs /usr/local/etc/profile.d/system-info.sh for this purpose), the output is made twice.

A work around is to have a script /usr/local/etc/profile, which checks whether it is called by /etc/profile (/etc/profile sets a variable _loaded; if it is set, then just do not try to load /etc/profile again):
if [ "${_loaded}" = "" ] ; then
if [ -e /etc/profile ] ; then
. /etc/profile
fi
fi
 
Just going to ask here since the title of this thread is my exact question. It is largely answered by SirDice's post, but I am still a little confused.

I set up a new FreeBSD 14.3 machine and installed bash. The provided bash manual mentions loading /usr/local/etc/profile if it exists, which it doesn't. The online manual instead mentions /etc/profile, which does exist, and is constructed to load everything you would expect it to, but it itself is not loaded. This makes sense, given the information in SirDice's post, but then why do new installations still only get /etc/profile? And why the discrepancy between the manual pages? Am I missing something?

 
but then why do new installations still only get /etc/profile?
It's used by sh(1), which is included in the base OS (and set as the default shell nowadays). Bash isn't. It's built and installed using the LOCALBASE prefix, which is /usr/local on FreeBSD. So $LOCALBASE/etc/profile points to /usr/local/etc/profile. The code itself is compiled this way, but the man page that's included with the source of bash, probably doesn't account for the PREFIX change, it's copied 1-to-1.
 
Hmm, looking at the port, it should modify the man page:
Code:
	@${REINPLACE_CMD} -e "s|%%PREFIX%%|${PREFIX}|g" -e "s|%%LOCALBASE%%|${LOCALBASE}|g" \
		-e "s|\(/etc/profile\)|${PREFIX}\1|g" \
		${WRKSRC}/doc/bash.1

And indeed, locally I have that change, here for example:
Code:
       --noprofile
              Do not read either the system-wide startup file
              /usr/local/etc/profile or any of the personal initialization
              files ~/.bash_profile, ~/.bash_login, or ~/.profile.  By
              default, bash reads these files when it is invoked as a login
              shell (see INVOCATION below).
While the "online" version of the man page looks like this:
Code:
       --noprofile
	      Do  not read either the system-wide startup file /etc/profile or
	      any  of  the  personal  initialization  files   ~/.bash_profile,
	      ~/.bash_login,  or  ~/.profile.	By  default,  bash reads these
	      files when it is invoked as a login shell	 (see  INVOCATION  be-
	      low).

I'm not sure why this discrepancy exist. Maybe the online HTML version hasn't been regenerated after this change was made.
 
bash.html is unchanged.
Code:
diff --git a/shells/bash/Makefile b/shells/bash/Makefile
index f320b9b85148..d7bec622b1a6 100644
--- a/shells/bash/Makefile
+++ b/shells/bash/Makefile
@@ -84,7 +84,7 @@ post-patch:
        ${RM} ${WRKSRC}/y.tab.c
        @${REINPLACE_CMD} -e "s|%%PREFIX%%|${PREFIX}|g" -e "s|%%LOCALBASE%%|${LOCALBASE}|g" \
                -e "s|\(/etc/profile\)|${PREFIX}\1|g" \
-               ${WRKSRC}/doc/bash.1
+               ${WRKSRC}/doc/bash.1 ${WRKSRC}/doc/bash.html
Code:
--noprofile
    Do not read either the system-wide startup file /usr/local/etc/profile or
    any of the personal initialization files ~/.bash_profile, ~/.bash_login, or
    ~/.profile. By default, bash reads these files when it is invoked as a
    login shell (see INVOCATION below).
Edit: Is this it. bash(1)
Edit: The online version is bash 5.1. This is an old manual from before the changes were made.
 
It's used by sh(1), which is included in the base OS (and set as the default shell nowadays).
Right. I guess my next question would be why /usr/local/etc/profile is not shipped with bash, but I guess maybe to avoid conflicts with sh. So I do in fact need something like the script posted by dreibh.
 
I guess my next question would be why /usr/local/etc/profile is not shipped with bash
It's not shipped with bash because it's entirely system dependant. You may or may not have noticed, in general, ports install fairly standard configuration files that came with the original distribution (which is why they often need a bit of tweaking to get it to work on FreeBSD). There is no profile script that comes with the bash distfiles.
 
Back
Top