The Environment

Chapter 11

Earlier, as previously mentioned, the shell holds a set of details known as the environment throughout our session. Information stored in this space helps programs understand our setup. Although configuration files are typically used for program settings, some programs check the environment for specific values to modify their actions. With this knowledge, we can personalize our shell experience by leveraging the environment.

In this chapter, we will work with the following commands:

  • printenv – Print part or all of the environment

  • set – Set shell options

  • export – Export environment to subsequently executed programs

  • alias – Create an alias for a command

What Is Stored In The Environment?

In the environment, the shell holds two primary data types, albeit with bash, these types mostly appear similar. These types include environment variables and shell variables. Shell variables consist of data inserted by bash, while environment variables encompass all other forms of data. Apart from variables, the shell also retains certain program-related information, specifically aliases and shell functions. We discussed aliases in Chapter 5, while shell functions, associated with shell scripting, will be explored in Part 4.

Examining The Environment

We can check the environment contents using either the built-in set command in bash or the printenv program. The set command reveals both shell and environment variables, while printenv specifically showcases the environment variables. As the environment content list can be quite extensive, it's advisable to channel the output of either command into less:

[me@linuxmachine ~]$ printenv | less

Doing so, we should get something that looks like this:

SHELL=/bin/bash
SESSION_MANAGER=local/pop-os:@/tmp/.ICE-unix/1528,unix/pop-os:/tmp/.ICE-unix/152
8
QT_ACCESSIBILITY=1
COLORTERM=truecolor
XDG_CONFIG_DIRS=/etc/xdg/xdg-pop:/etc/xdg
SSH_AGENT_LAUNCHER=gnome-keyring
XDG_MENU_PREFIX=gnome-
GNOME_DESKTOP_SESSION_ID=this-is-deprecated
GTK_IM_MODULE=ibus
GNOME_SHELL_SESSION_MODE=pop
SSH_AUTH_SOCK=/run/user/1000/keyring/ssh
XMODIFIERS=@im=ibus
DESKTOP_SESSION=pop
GTK_MODULES=gail:atk-bridge
PWD=/home/dev
LOGNAME=dev
XDG_SESSION_DESKTOP=pop
XDG_SESSION_TYPE=x11
GPG_AGENT_INFO=/run/user/1000/gnupg/S.gpg-agent:0:1
SYSTEMD_EXEC_PID=1547
XAUTHORITY=/run/user/1000/gdm/Xauthority
WINDOWPATH=2

The displayed information comprises a lineup of environment variables alongside their corresponding values. For instance, there's a variable named USER with the value me. Additionally, the printenv command enables the listing of a particular variable's value:

When invoked without any options or arguments, the set command showcases both the shell and environment variables along with any established shell functions. Unlike printenv, its output is thoughtfully arranged in alphabetical order:

It is also possible to view the contents of a variable using the echo command, like this:

One element of the environment that neither set nor printenv displays is aliases. To see them, enter the alias command without arguments:

Some Interesting Variables

The environment encompasses numerous variables, and while yours might not match the presented one here, you'll probably encounter the following variables within your own environment:

Variable
Contents

DISPLAY

The name of your display if you are running a graphical environment. Usually this is “:0”, meaning the first display generated by the X server.

EDITOR

The name of the program to be used for text editing.

SHELL

The name of your shell program.

HOME

The pathname of your home directory.

LANG

Defines the character set and collation order of your language.

OLD_PWD

The previous working directory.

PAGER

The name of the program to be used for paging output. This is often set to /usr/bin/less.

PATH

A colon-separated list of directories that are searched when you enter the name of a executable program.

PS1

Prompt String 1. This defines the contents of your shell prompt. As we will later see, this can be extensively customized.

PWD

The current working directory.

TERM

The name of your terminal type. Unix-like systems support many terminal protocols; this variable sets the protocol to be used with your terminal emulator.

TZ

Specifies your timezone. Most Unix-like systems maintain the computer’s internal clock in Coordinated Universal Time (UTC) and then displays the local time by applying an offset specified by this variable.

USER

Your username.

Don't worry if some of these values are missing. They vary by distribution.

How Is The Environment Established?

Upon logging into the system, the bash program initiates and scans through a set of configuration scripts known as startup files. These files establish the default environment applicable to all users. Subsequently, additional startup files in our home directory delineate our individualized environment. The specific sequence varies based on the type of shell session initiated, which falls into two categories: a login shell session and a non-login shell session.

A login shell session involves entering our username and password, such as when initiating a virtual console session. Conversely, a non-login shell session commonly happens when launching a terminal session within the graphical user interface (GUI).

Login shells read one or more startup files as shown:

File
Contents

/etc/profile

A global configuration script that applies to all users.

~/.bash_profile

A user's personal startup file. Can be used to extend or override settings in the global configuration script.

~/.bash_login

If ~/.bash_profile is not found, bash attempts to read this script.

~/.profile

If neither ~/.bash_profile nor ~/.bash_login is found, bash attempts to read this file. This is the default in Debian-based distributions, such as Ubuntu.

Non-login shell sessions read the following startup files:

File
Contents

/etc/bash.bashrc

A global configuration script that applies to all users.

~/.bashrc

A user's personal startup file. Can be used to extend or override settings in the global configuration script.

Apart from parsing the mentioned startup files, non-login shells also acquire their environment from the parent process, typically originating from a login shell.

Inspect your system to identify the available startup files from this list. Keep in mind that as most filenames listed begin with a period (indicating they're hidden), you'll need to utilize the ls -a option to view them.

For the everyday user, the ~/.bashrc file holds significant importance as it's nearly always accessed. By default, non-login shells read this file, and most login shell startup files are designed to also incorporate the reading of the ~/.bashrc file.

What's In A Startup File?

If we take a look inside a typical .bash_profile (taken from a CentOS 4 system), it looks something like this:

Lines starting with # are considered comments and are ignored by the shell, serving solely for human readability. The initial noteworthy content appears on the fourth line, showcasing the following code:

This is called an if compound command, which we will cover fully when we get to shell scripting in Part 4, but for now we will translate:

This piece of code illustrates how a login shell accesses the contents of .bashrc. The subsequent section in our startup file pertains to the PATH variable.

Have you ever pondered how the shell locates commands when we input them on the command line? For instance, when we type ls, the shell doesn't scour the entire system to find /bin/ls (the complete pathname of the ls command); instead, it scans through a compilation of directories listed within the PATH variable.

The PATH variable is commonly (though not universally, contingent on the distribution) established by the /etc/profile startup file, often utilizing this code:

The PATH is adjusted by appending the directory $HOME/bin at the list's conclusion. This showcases parameter expansion, a concept briefly discussed in Chapter 7. To illustrate its functionality, give this a try:

Using this technique, we can append text to the end of a variable's contents.

Appending the string $HOME/bin to the end of the PATH variable extends the list of directories inspected when a command is used. Consequently, when we aim to establish a directory within our home directory to house personal programs, the shell is set to assist us. Simply naming it bin will suffice, and we're all set to proceed.

Note

Many distributions provide this PATH setting by default. Some Debian based distributions, such as Ubuntu, test for the existence of the ~/bin directory at login, and dynamically add it to the PATH variable if the directory is found.

Lastly, we have:

The export command instructs the shell to share the contents of PATH with the child processes spawned from this shell.

Modifying The Environment

With an understanding of the location and content of startup files, we can edit them to tailor our environment to suit our preferences.

Which Files Should We Modify?

As a guideline, if you aim to include directories in your PATH or define new environment variables, incorporate these modifications in .bash_profile (or its equivalent, as per your distribution; for instance, Ubuntu utilizes .profile). For other adjustments, use .bashrc. Unless you're the system administrator requiring alterations to the system-wide defaults, confine your changes to files within your home directory. While it's feasible to modify files in /etc like profile, it's prudent to proceed cautiously for now.

Text Editors

For modifying the shell's startup files and many other configuration files within the system, we rely on a tool known as a text editor. This program, akin to a word processor in certain aspects, enables editing text on-screen using a movable cursor. Its distinction lies in supporting only plain text, excluding formatting, and often encompassing features tailored for programming tasks. Text editors serve as a primary tool for software developers to write code and aid system administrators in handling configuration files governing system operations.

Linux hosts numerous text editors, likely with several installed on your system. Why the abundance? Primarily because programmers enjoy creating them, and given their extensive use by programmers, these editors are crafted to mirror their preferences and how they envision their functionality.

Text editors are generally categorized as either graphical or text-based. Within GNOME and KDE environments, you'll find various popular graphical editors. GNOME typically features an editor named gedit, commonly labeled as "Text Editor" in the GNOME menu. In KDE, you'll typically encounter three editors—kedit, kwrite, and kate—varying in complexity from simpler to more advanced.

Several text-based editors are available, with popular ones including nano, vi (often replaced by vim, meaning "Vi IMproved" on most Linux systems), and emacs. Nano, a user-friendly editor, was created as a substitute for the pico editor within the PINE email suite. Vi, a traditional Unix-like system editor, will be the focus of our upcoming chapter. Emacs, initially developed by Richard Stallman, is a comprehensive, multipurpose programming environment. Although accessible, it's infrequently included as a default installation on most Linux systems.

Using A Text Editor

Every text editor can be accessed from the command line by inputting the editor's name followed by the file you wish to edit. If the file isn't present, the editor assumes you aim to create a new one. Here's an instance using gedit:

Executing this command will launch the gedit text editor, opening the file named "some_file" if it exists.

Graphical text editors are typically intuitive, so we won't delve into them here. Instead, let's focus on our initial text-based editor, nano. We'll launch nano to edit the .bashrc file. However, before we proceed, let's practice "safe computing." Whenever editing a crucial configuration file, it's wise to generate a backup copy as a precaution against accidental alterations. To create a backup of the .bashrc file, follow these steps:

The name you give to the backup file is flexible; choose something descriptive. Common extensions like .bak, .sav, .old, or .orig indicate backup files. Also, keep in mind that cp will silently overwrite existing files.

Now that we have a backup file, we'll start the editor:

Once nano starts, we’ll get a screen like this:

Note

If your system does not have nano installed, you may use a graphical editor instead.

The screen layout includes a top header, the file's text in the middle, and a command menu at the bottom in nano. As it was created as a substitute for an email client's text editor, nano has limited editing capabilities.

In every text editor, the initial command to grasp is how to exit the program. In nano, you exit by typing Ctrl-X, as indicated in the bottom menu with the notation ^X denoting Ctrl-X. This notation, employing symbols like ^, represents control characters, a widely used convention in various programs.

The next essential command is saving our work, achieved in nano by using Ctrl-O. Equipped with this information, we're set to start editing. Navigate to the end of the file using the down arrow key and/or the PageDown key, then insert the following lines into the .bashrc file:

Note

Your distribution may already include some of these, but duplicates won't hurt anything.

Here is the meaning of our additions:

Line
Meaning

umask 0002

Sets the umask to solve the problem with shared directories we discussed in Chapter 9.

export HISTCONTROL=ignoredups

Causes the shell's history recording feature to ignore a command if the same command was just recorded.

export HISTSIZE=1000

Increases the size of the command history from the default of 500 lines to 1000 lines.

alias l.='ls -d .* --color=auto'

Creates a new command called l. which displays all directory entries that begin with a dot.

alias ll='ls -l --color=auto'

Creates a new command called ll, which displays a long format directory listing.

Several of our additions might not be immediately apparent, so it's advisable to include comments in our .bashrc file to provide explanations for humans.

Using the editor, change our additions to look like this:

Great! With our alterations finished, press Ctrl-O to save the modified .bashrc file, then Ctrl-X to exit nano.

Why Comments Are Important

When altering configuration files, it's wise to include comments to document your changes. While you might recall modifications made tomorrow, remembering them in six months might prove challenging. Adding comments is a favor to your future self. Additionally, maintaining a log of changes can be beneficial.

In shell scripts and bash startup files, comments typically start with the # symbol. However, different configuration files may use alternate symbols. Most configuration files include comments, serving as guidance.

It's common to encounter lines in configuration files that are commented out to prevent them from impacting the associated program. This practice offers suggestions or demonstrates correct configuration syntax. For instance, in Ubuntu 8.04's .bashrc file, these lines are present:

The last three lines comprise valid alias definitions but are currently commented out. Removing the leading # symbols, a process known as uncommenting, would activate these aliases. Conversely, adding a # symbol at the start of a line deactivates a configuration line while preserving its information.

Activating Our Changes

The modifications in our .bashrc won't be applied until we close our current terminal session and initiate a new one. This is because the .bashrc file is read only at the session's start. Yet, we can compel bash to re-read the updated .bashrc file using this command:

After doing this, we should be able to see the effect of our changes. Try out one of the new aliases:

Summary

Throughout this chapter, we've acquired a crucial skill: editing configuration files using a text editor. As we explore command man pages in the future, pay attention to the supported environment variables—there might be some valuable insights. In the upcoming chapters, we'll delve into shell functions, an influential feature that can be integrated into bash startup files, further enhancing your assortment of customized commands.

Last updated