Wednesday, August 15. 2007
The bash man page says that .bash_profile is executed by login shells. But I log into my desktop using gdm. So I'm confused at what point is .bash_profile executed. Or is it? If it isn't, where should I define environment variables?
The answer to this question lies in the difference between a login and a session. A login occurs when you authenticate to the system in character mode
Fields in this file are separated by colons (":"), and the seventh field contains the name of the shell that will be executed upon login. This doesn't have to be a shell in the traditional command-interpreter sense; it can be any valid program, and it's not uncommon to use a menu program or a specific application (such as an e-mail program) for the convenience of inexperienced users or to constrain what the user can do. If the user should not be permitted to login at all, the program /sbin/nologin is specified as the shell, which simply prints the message "This account is currently not available" and exits (tip: you can create a custom message in the file /etc/nologin.txt).
The normal value for the login shell field on a Fedora system is /bin/bash, the Bourne-again shell (a nameplay on the Bourne shell, one of the first and most popular Unix shells). Like other shells, bash executes a startup script every time a shell starts (~/.bashrc) and two profile scripts at each login (/etc/profile and one of ~/.bash_profile, ~/.bash_login, or ~/.profile -- Fedora sets up new accounts with ~/.bash_profile by default). Note the difference: if you login once and then start three shells, /etc/profile and ~/.bash_profile will each be executed once, but ~/.bashrc will be executed three times.
A session, on the other hand, is the graphical version of a login. The session is started by the display manager gdm (or, alternatively, kdm or xdm) when the program starts. The session is under the control of a session manager, which starts standard clients (GUI programs), re-starts certain clients if they die, and optionally restarts clients that were open when the last session ended. The GNOME session manager is gnome-session and the KDE session manager is ksmserver, which is started by the startkde script. This process completely ignores the seventh field in /etc/passwd, and the login profiles are not executed.
But it's not quite that simple: the session manager is started by the script /etc/X11/xdm/Xsession, and in Fedora, that script does not execute the session manager directly. When starting a GNOME session, it executes this command:
And for a KDE session it executes:
The environment variables used in these commands are set by the script /etc/X11/xinit/xinitrc-common. Usually, SHELL is /bin/bash, SSH_AGENT is /usr/bin/ssh-agent, and DBUS_LAUNCH is "/usr/bin/dbus-launch --exit-with-session".
Together, this means that bash is run as a login shell and therefore executes /etc/profile and ~/.bash_profile. It then starts ssh_agent, which then starts dbus-launch, which then starts the session manager. This chain ensures that environment variables set by the login profiles, ssh_agent, and dbus-launch programs are properly exported to the programs running within the session.
We can easily test this execution path by adding some code to the end of the ~/.bash_profile:
If we now login in character mode, we see these messages:
Notice that the message ".bash_profile executed" from the echo command is displayed correctly, but that zenity can't display its graphical message because there is no X server available. On the other hand, when we login graphically, the zenity dialog shown in the screenshot is displayed, but the output from echo is not visible (note that since there is no window manager running, the zenity window does not have window decorations such as a border, titlebar, or controls). Regardless of how we've logged in, if we check the environment variable FDP, we find that it has been correctly propagated:
So you can safely export environment variables from your .bash_profile in all cases.
However, if the profile needs to interact with the user, it should detect whether it is running in a character-mode or a GUI environment. If in a character-mode environment, the command tty will return success; if in a GUI environment, the DISPLAY variable should be set. To ask the user a question, you could use code such as this:
In addition to the profiles executed at login and the ~/.bashrc script executed when a shell starts, the ~/.bash_logout script is executed when the user logs out. The Fedora default logout script simply clears the character-mode screen, ensuring that no confidential information is left visible.
Display comments as (Linear | Threaded)
Thank you for this Wednesday Why. That's a very interesting topic and a very good explanation. I knew that .bash_profile is also read when starting a X-session with GDM/KDM/XDM but I didn't know that this (without those chains as in Fedora) isn't normal behaviour.
One question left: when you start your X with ´startX´ on the command line and not with GDM/KDM/XDM, is there still a session started? I guess it is.
'startx' is a script which runs 'xinit', which in turn runs the script 'Xclients', which usually runs gnome-session or startkde -- so the session manager does get started. I suppose that makes it a session too...
#1.1 Chris Tyler on 2007-08-15 10:54
You're right -- fixed!
#2.1 Chris Tyler on 2007-08-15 14:35
Thank you for this detailed explanation of how the GDM login process executes ~/.bash_profile. It answers something that has puzzled me for a long time.
I see that "exec -l" causes the zeroth argument of the executed command to be preceded by a dash. When bash sees that it was executed as "-bash" it knows that it has been invoked as a login shell and executes the appropriate startup files. Indeed, /bin/login invokes the shell in this same manner.
I think I'll experiment with putting echo and zenity statements in various startup scripts to better my understanding of them. Maybe using the logger  command to send messages to a log file via syslog can be useful for this?
I just installed Fedora 8 x86_64
I used csh and KDE. Normally, .login is load when I login (in graphical mode) but that not the case. I tried with an user with bash. Same problem, the bash_profile is not load at all.
When I login with in character mode, the .login is load normally.
Can you help me ?
Trinh -- in gnome-terminal, edit the profile and under "Title and Command" make sure "Run command as a login shell" is checked. There'll be something similar in the KDE shell app.
Thank you for clearing up the login process and separating the char mode from the gui mode. I have been looking for this answer for a while. linuxquestions.org sent me to this article. Thanks again.
The author does not allow comments to this entry
php_network_getaddresses: getaddrinfo failed: Name or service not knownphp_network_getaddresses: getaddrinfo failed: Name or service not known