% Login and Shell Startup Files, aliases, options: .bash_profile and .bashrc % Ian! D. Allen -- -- [www.idallen.com] % Fall 2015 - September to December 2015 - Updated 2018-02-22 09:57 EST - [Course Home Page] - [Course Outline] - [All Weeks] - [Plain Text] Introduction ============ Shells have a number of options and settings that affect how they work. You can also define shell aliases and functions to create your own command names. You can change any of these at any time, but the settings are *not* saved. The settings only last until the shell exits, and they aren't always passed on to new shells. To make your settings apply to every shell, you put the settings in *profile* or *start-up* files. Shells read these files when they first start to load the settings you want. The two profile files you need to create for this course are `.bash_profile` and `.bashrc` and this file will explain what to put in each of these new files. You can always change any settings after the shell is running, but unless you also change the settings saved in your start-up files, the settings will be lost when the current shell exits. All shell startup files are kept in your HOME directory, which is where `cd` takes you without arguments. Your HOME directory is also usually available in the environment variable `$HOME`. What happens when you Log In? ============================= When you type in your user name (userid) and password to log in, the system encrypts your password and compares it against the encrypted password in the password files. If they match, you are allowed to log in. At log-in time, the system sets your current directory to be the `HOME` directory listed for your account in the password file. An initial environment is prepared (e.g. containing a system default `PATH`). For a text command-line (terminal or console) log in, the shell specified in the password file is executed. (This shell is usually `/bin/bash`.) For a graphical log-in, a window manager is started and your Desktop is initialized for display. If your login shell is `/bin/bash`, the BASH process reads ("sources") some system start-up files such as `/etc/profile` and `/etc/bash.bashrc` that may set system defaults for various shell settings. Next, a login shell looks in your home directory for more start-up files such as `.bash_profile` or `.bash_login` that you can create and use to alter the system defaults. (See `man bash` for the full list.) You can create your own initialization files to customize your environment and terminal settings. Some systems give default `.bash_login` and `.bash_logout` files when you create a new account. The default files are copied from a system directory such as `/etc/skel`. If you don't have these files, you can create them yourself. Your instructor may have removed all default start-up files from your system, so as not to confuse you as to what a "normal" system looks like. Login shells, Interactive shells, and the GUI ============================================= There are different start-up files for different types of shells. We need to understand the terms **Login Shell** and **Interactive Shell**. Login Shell ----------- A **Login Shell** used to be the first shell you got when you logged in to a Unix system. The system treated this shell specially, since it was your first connection to the machine. A Login Shell got its own start-up file, from where it would read shell options and other settings. The original Bourne shell Login Shell start-up file was named `.profile`. A BASH login shell first tries to find the file `.bash_profile`, then falls back to using the traditional `.profile` file. It does not read your `.bashrc` file. Non-Login Shell --------------- The second (and subsequent) shells you got after you had already logged in were not Login Shells. When these non-login shells started up, they read a different start-up file. A BASH non-login shell tries to find the file `.bashrc` from which to read settings when it starts up. It does not read your `.bash_profile`. Non-Interactive Shell --------------------- You are most familiar with using a shell to find and run commands interactively with a keyboard and screen, but shells also run **non interactively** when running without a keyboard and/or screen. A file transfer program (e.g. WinSCP, FileZilla, SCP) might log in to your system using your account and a non-interactive shell to transfer files for you. A BASH shell that is not interactive still reads the `.bashrc` file when it starts up. It does not read `.bash_profile` (because it is not a Login Shell). ### No output allowed for non-interactive shells When a file transfer program logs in to your account to transfer files, it does not expect your account to start producing output. Output from your account will corrupt the file transfer. This means your `.bashrc` file must not generate any visible output when run by a non-interactive shell. > Your `.bashrc` file must not produce any output when read by a > non-interactive shell. File transfer programs will fail if your `.bashrc` > file produces output that corrupts the file transfer. GUI Interfaces vs. Login Shells =============================== On modern Unix systems with a GUI interface, you may be logged in without using any visible shell at all, so the concept of Login Shell has lost its clear meaning. It may be true that *every* terminal window you start up using the GUI is treated as a Login Shell (MacOSX does this), or it may treat those terminal windows as ordinary shells. This lack of clear meaning for Login Shell leads to confusion as to where to put your shell settings. Do you use `.bash_profile` or do you use `.bashrc`? The solution is to use both, to handle both cases, but to make the `.bash_profile` file refer to the `.bashrc` file so that all the settings are made in only the `.bashrc` file. > Your profile files are not re-read by your current shell after you edit > them -- you have to tell your current shell to re-read the file to make the > new content take effect in the current shell, e.g. type `source ./.bashrc` `.bash_profile` -- only one line ================================ Create (if necessary) and put only one single line in your `.bash_profile` file: source ./.bashrc That is the only line that should be in your `.bash_profile`. That line sends the shell to use the `.bashrc` for all settings. We will put all shell settings for all shell uses, Login, Interactive, etc., in the one `.bashrc` file. Do not put any other lines in your `.bash_profile`. `.bashrc` -- all other settings =============================== By using `source ./.bashrc` in `.bash_profile`, we ensure that **every** shell, Login or not, reads the `.bashrc` file when it first starts. The `.bashrc` is the file that we create (if necessary) and into which we put *all* shell settings. Any settings you define in `.bashrc` will apply to all BASH shells. (If you want to start a BASH shell that does *not* read any start--up files, use the `--norc` option when you start it.) You are only required to create this file with two lines, each described below, in your `.bashrc` in this course: 1. The line with the comment `# exit if not interactive`, described below, must be the first line in `.bashrc` 2. You must set your prompt `PS1` string, described below, as a second line Those are the only two lines that must be in your `.bashrc` file. First Line: No Output for Non-Interactive Shells ------------------------------------------------ > Your `.bashrc` file must not produce any output when read by a > non-interactive shell. File transfer programs will fail if your `.bashrc` > file produces output that corrupts the file transfer. To be safe, the first executable line of your `.bashrc` must be this one: [ -z "${PS1-}" ] && return # exit if not interactive Note the required use of spaces around all of the words in the above line. This line is one of the two required lines that must be in your `.bashrc` in this course. ### Non-interactive shells and PS1 Non-interactive shells (e.g. run by file transfer programs using your account) do not set a prompt, and these shells must not generate prompts or any output when they run. Programs transferring files to/from your account depend on non-interactive shells executing without generating any unexpected output. > Do not set the `PS1` prompt string in any start-up file unless it is > already set, indicating an interactive shell. Do not produce any output in > any start-up file unless the shell is interactive (has `PS1` set > non-empty). To prevent the rest of a `.bashrc` from running if the shell is not interactive, make sure this line is at the start of the file (make sure you type this exactly as shown, including all the spaces): [ -z "${PS1-}" ] && return # exit if not interactive The above line will check for the existence of a prompt and skip the rest of the `.bashrc` if the shell is not being used interactively. The result will be no unexpected output when a shell is used non-interactively. **Do not insert any lines line that generate output above this line; this line should be at the top of the file.** You can test your shell's non-interactive output by using `ssh` to execute a remote command that produces no output, such as `true` or `cd`, and making sure that no output appears after you enter your password: (If you are asked to accept a sever host key, say `yes` below.) $ ssh localhost true *** COURSE LINUX SERVER *** user@localhost's password: $ Above, there is no unexpected output from the remote non-interactive shell. The remote system produces no spurious output. Below is a system that is broken and file transfers will fail: $ ssh localhost true *** COURSE LINUX SERVER *** user@localhost's password: Welcome back gracious Lord of All. $ The above "Welcome" line is output from an `echo` command inside a `.bashrc`. The non-interactive output will cause file transfer programs to fail. Remove the line that produces this output or put it *after* the `exit if not interactive` command given to you, above: [ -z "${PS1-}" ] && return # exit if not interactive echo "Welcome back gracious Lord of All." PS1='YesMaster$ ' If you fully log in and the shell is interactive, the `.bashrc` runs normally (a prompt is defined) and the `echo` generates the expected output: $ ssh localhost *** COURSE LINUX SERVER *** user@localhost's password: Welcome back gracious Lord of All. YesMaster$ exit $ Second Line: Set a Shell `PS1` Prompt ------------------------------------- Setting your `PS1` prompt is the only other required line that must be in your `.bashrc` file. Having part of your current working directory visible in your shell prompts is helpful. Setting this `PS1` prompt does only that: PS1='[\W]$ ' # include only the current directory in your shell prompt You can optionally include more fields in the prompt, if you wish: PS1='[\u@\h \W]$ ' # optional: include user, host, and PWD in shell prompt Put the one `PS1` prompt setting statement somewhere *below* (after) the `# exit if not interactive` line, described above that must be the first line in the file. RTFM in `man bash` to learn what all the backslash escape characters mean in the `PS1` variable prompt string. There are many more! Summary of `.bash_profile` and `.bashrc` ======================================== **Do not set any options or aliases that you do not understand!** If you don't know the meaning of a setting, don't use it. You can RTFM in the `bash` man page for all BASH settings. - Create these files in your HOME directory, if necessary. (Some systems will have already created these files for you.) - `.bash_profile` -- in this course, this file must be only one line long: source ./.bashrc - `.bashrc` -- in this course, this file must contain at least these two lines: [ -z "${PS1-}" ] && return # exit if not interactive PS1='[\W]$ ' # include only the current directory in your shell prompt 1. Your `.bashrc` file must not produce any output when read by a non-interactive shell. File transfer programs will fail if your `.bashrc` file produces output that corrupts the file transfer. 2. Your profile files are not re-read by your current shell after you edit them -- you have to tell your current shell to re-read the file to make the new content take effect in the current shell, e.g. type `source ./.bashrc` 3. Do not set the `PS1` prompt string in any start-up file unless it is already set, indicating an interactive shell. Do not produce any output in any start-up file unless the shell is interactive (has `PS1` set non-empty). The `exit if not interactive` line ensures this. 4. You can choose any `PS1` prompt string you like. Appendix -- Optional BASH Settings for System Administrators ============================================================ You might read the optional material: [**BASH Settings for System Administrators**]. This material is not required for this course; it is optional. **Do not set any options or aliases that you do not understand!** -- | Ian! D. Allen, BA, MMath - idallen@idallen.ca - Ottawa, Ontario, Canada | Home Page: http://idallen.com/ Contact Improv: http://contactimprov.ca/ | College professor (Free/Libre GNU+Linux) at: http://teaching.idallen.com/ | Defend digital freedom: http://eff.org/ and have fun: http://fools.ca/ [Plain Text] - plain text version of this page in [Pandoc Markdown] format [www.idallen.com]: http://www.idallen.com/ [Course Home Page]: .. [Course Outline]: course_outline.pdf [All Weeks]: indexcgi.cgi [Plain Text]: 350_startup_files.txt [**BASH Settings for System Administrators**]: 370_optional_settings.html [Pandoc Markdown]: http://johnmacfarlane.net/pandoc/