% Startup Files: .bash\_profile and .bashrc % Ian! D. Allen - idallen@idallen.ca - www.idallen.com % Fall 2012 - September to December 2012 - Updated Thu Mar 14 02:46:10 EDT 2013 Startup Files: .bash\_profile and .bashrc ========================================= Loading shell defaults, options, aliases, the prompt, and functions is done when the shell first starts. You can change things while the shell is running, but the changes are *not* saved. Start-up files are places to save things so that every new shell gets them. All startup file references are to files in your home directory, which is where **`cd`** takes you without arguments. Your home directory is also usually available in the environment variable **`$HOME`**. > Your start-up files are not re-read by your current shell after you edit > them - you have to tell your current BASH shell to re-read them to make the > new content take effect in the current shell, e.g. > $ **`source ./.bashrc`** $HOME/.bash\_profile ===================== If you use a Linux system (e.g. RedHat, Knoppix, Ubuntu, Fedora, SuSE, etc.), your login shell is already BASH and it reads (“sources”) the **`.bash_profile`** file when you log in. The **`.bash_profile`** is only read *once* by the login shell, not by any other non-login shells you might start up after you log in. > The **`.bashrc`** file is **not** read by a login shell, so most people put > **`source ./.bashrc`** in their **`.bash_profile`**. You can put things in **`.bash_profile`** that need to be done exactly *once* when you log in and that are *inherited* by other shells: - set (and export) **`PATH`** and/or **`TERM`** - set **`umask`** - set your erase character (backspace character) - set your prompt **`PS1`** (and export it:  **`export PS1`**) Any aliases you define in these login profile files will apply *only* to the BASH shell at login, not to any other shells you start. It is usually better to define aliases in your **`$HOME/.bashrc`** file and use `source ./.bashrc` in the **`.bash_profile`**. If you find that a nested shell is not inheriting PATH, TERM, or PS1, you must “export” the variable, e.g. “export PS1”. To define aliases and shell options that cannot be exported or inherited, use the other start-up file **`.bashrc`**: > Your start-up files are not re-read by your current shell after you edit > them - you have to tell your current BASH shell to re-read them to make the > new content take effect in the current shell, e.g. > $ **`source ./.bash_profile`** $HOME/.bashrc ============== Put things in your **`.bashrc`** that don’t get exported or inherited from parent shells and that must be set new for each new shell, such as aliases and shell options. Every non-login BASH shell reads (“sources”) **`.bashrc`** when it first starts up. Every new non-login BASH shell reads this file, unless you use the “`--norc`” option when you start it. Any aliases and options you define in **`.bashrc`** will apply to all BASH shells, except your login shell that sources **`.bash_profile`** instead. > The **`.bashrc`** file is **not** read by a login shell, so most people put > **`source ./.bashrc`** in the **`.bash_profile`**. Set your personal BASH aliases and functions in the **`.bashrc`** file, e.g. **`alias cd..='cd ..'`** Set your own useful shell options in your **`.bashrc`**; I recommend these: - **`shopt -s failglob`** - **`set -o ignoreeof -o noclobber -o notify -o nounset`** - **`set -o physical -o interactive-comments`** `shopt -s failglob` : Give an error message if a GLOB fails to match any pathnames, instead of silently returning the GLOB pattern unchanged. `set -o ignoreeof` : The shell will ignore \^D (EOF) at the prompt; use “exit” to exit. `set -o noclobber` : Protects files from being overwritten when **“`>`”** redirection is used. Use the “force” syntax **“`>|`”** (that’s a *pipe* character) to force overwriting, e.g. **`date >| file`** `set -o notify` : Notifies user immediately when a background job (started with **“`&`”** or **`bg`**) completes. Without this, you won’t be told that the background job is done until you push ENTER. `set -o nounset` : Displays an error when expanding a variable that has not been set. Essential for detecting typing errors in variable names. `set -o physical` : Expand all symbolic links in output of pwd and when using cd so that you see the real directory names and paths. Essential for system administrators to know *exactly* where you are in the file system. `set -o interactive-comments` : Allow **“`#`”** to comment out any following text when typed interactively, e.g. **`echo a b # this text is not seen`** Refer to the BASH man page for details on these options. > Your start-up files are not re-read by your current shell after you edit > them - you have to tell your current BASH shell to re-read them to make the > new content take effect in the current shell, e.g. > $ **`source ./.bashrc`** Recommended shell aliases ------------------------- Don’t take aliases from other people unless you *know* what they do! Here are some optional but recommended sysadmin aliases for your .bashrc: alias l='less' alias mv='mv -i' alias cp='cp -i -p' alias ls='ls -abp --color=auto' alias grep='grep --color=auto' I *don’t* recommend aliasing “rm” to “rm -i”, since it requires you to confirm *every* removal and quickly loses any protective value. Saving lots of shell history ---------------------------- As system technicians, having a long history of previous commands available is useful. The number of commands to keep in memory and number of commands to save to disk (in the **`.bash_history`** file) are controlled by the BASH shell variables **`HISTSIZE`** and **`HISTFILESIZE`**. Having all your shells append their history, rather than overwrite the history file, is also useful. Here are some suggested settings to preserve a long history: export HISTSIZE=2000 export HISTFILESIZE=1000000 export HISTCONTROL=ignoredups export HISTTIMEFORMAT= shopt -s cmdhist shopt -s histappend See **`man bash`** for the details. 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 Environment Variables. Next, a login shell looks in your home directory for more start-up files such as **`.bash_profile`** or **`.bash_login`** that you can 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`**.) Non-interactive shells and PS1 ============================== > 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). Non-interactive shells do not set a prompt, and these shells must not generate prompts or output when they run. Programs transferring files to/from your account depend on non-interactive shells executing without generating any unexpected output. You can check to see if your shell is generating any unexpected output by using **`ssh`** to execute the **`true`** command (or any command that generates no output) and watching for any output after you enter your password: $ ssh localhost true *** COURSE LINUX SERVER *** user@localhost's password: Welcome back gracious Lord of All. $ The above “Welcome” line output from an **`echo`** command inside a **`.bashrc`** will cause file transfer programs to fail. To prevent the rest of a **`.bashrc`** from running if the shell is not interactive, insert this line at the start of the file (make sure you type this as shown, including the spaces): [ -z "$PS1" ] && return The above line will skip the rest of the file if the shell is not being used interactively. The result will be no unexpected output when a shell is used non-interactively. You can test this using a command that produces no output, such as **`true`** or **`cd`**, and making sure that no output appears: $ ssh localhost true *** COURSE LINUX SERVER *** user@localhost's password: $ Above, there is no unexpected output from the non-interactive shell, but if you fully log in and the shell is interactive, the **`.bashrc`** runs normally and generates the expected output: $ ssh localhost *** COURSE LINUX SERVER *** user@localhost's password: Welcome back gracious Lord of All. YesMaster$ exit exit $ -- | Ian! D. Allen - 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 [Plain Text]: 210_startup_files.txt [Pandoc Markdown]: http://johnmacfarlane.net/pandoc/