Bash Tips for Linux Sysadmins

869

The Bash shell is a fundamental Linux tool and, in this era of containers and clusters and microservices, good old-fashioned Linux system administration skills are as relevant as ever. Today, we’ll learn about running other command shells, Bash built-ins, configuration files, and shell expansion.

Which Shells?

Run cat /etc/shells to see which command shells are installed on your Linux system. Your default shell is set in /etc/passwd:

$ cat /etc/passwd|grep carla
carla:x:1000:1000:carla,,,:/home/carla:/bin/bash

You can run any other shell you want by invoking it from your Bash shell:

carla@studio:~$ tcsh
studio:~> 

Then type exit to return to Bash.

What’s Inside Bash?

Run enable -a to see a list of your Bash built-in commands. Some of these duplicate GNU commands, such as printf, kill, and echo. The Bash versions are stripped-down, with fewer command options. Use the built-in command type to see which they are:

$ type -a kill
kill is a shell builtin
kill is /bin/kill

$ type -a type
type is a shell builtin

Bash executes built-ins first, so if you want the GNU commands, you have to use the full path, like this:

$ /bin/kill 7502

The help syntax for Bash built-ins is backwards:

$ help kill

Bash Configuration Files

There are several Bash configuration files, and they differ according to your Linux distribution, so you may not have all of these. The best way to learn what they do on your system is to read them. User-specific files are read first:

  • /etc/profile, system-wide user environment defaults, applied at login.

  • ~/.bash_login, user settings applied only at login.

  • ~/.bash_profile, user-specific configuration, applied at login.

  • ~/.profile is used when ~/.bash_profile and ~/.bash_login are not present.

  • ~/.bashrc is applied to non-login shells, so you don’t have to log in every time you open a terminal. Most distros place user settings here, and then call ~/.bashrc from login files such as ~/.bash_profile.

  • ~/.bash_logout contains settings applied at logout, such as clearing the console.

  • ~/.bash_history contains your Bash command history up to your configured limit. Commands that you have run are stored in memory until you close the terminal you are working in, and then written to the file. This is why, when you work in multiple terminals, your command history gets mixed up.

What is the size limit of your history file?

$ echo $HISTFILESIZE
2000

Where is this limit set?

$ grep -d skip 2000 .*
.bashrc:HISTFILESIZE=2000

Shell Expansion

Shell expansion is one the biggest sources of confusion for Bash users, so I hope this explanation will help you understand how it works and thereby be less vexed.

You see tilde expansion in filenames, for example ~/.bashrc. The tilde is a shortcut for /home/user.

Brace expansion generates arbitrary text strings. This is a slick way to create a batch of new directories quickly:

$ mkdir -p testdirs/{test4,test5,test6}

There must not be any spaces between your filenames.

Pattern matching uses *, ?, and [] as wildcards. The * matches any string. You probably use this already, for example *.jpg to find all JPG files, or all files that start with a string like catpic*.

Using ? matches any single character:

$ ls tes?t
tesst

Patterns enclosed in square braces have mighty matching powers. This matches any one of the three enclosed characters:

$ locate test[256]
test2
test5
Test6

Square brace expansion supports POSIX character classes: alnum, alpha, ascii, blank, cntrl, digit, graph, lower, print, punct, space, upper, word, and xdigit. Use digit to match any numbers:

$ ls test[[:digit:]]
test4:

test5:

test6:

$ ls test[[:digit:]]*
test666  test9file

test4:

test5:

test6:

alpha matches only letters:

$ ls test[[:alpha:]]*
tesst

The character classes are great shortcuts, and the above POSIX link describes how all of them work.

Command substitution replaces command names with command output. The backslashes at the ends of the lines format the command examples so that they fit the column width. If you copy and paste these examples, you can include the backslashes. If you want to remove them, make sure your command is all on one line:

$ echo "The current directory is $(pwd), the date and time are 
$(date), and my hostname is $(hostname)"
The current directory is /home/carla/testdirs, the date and time  
are Mon Jul 25 13:40:00 PDT 2016, and my hostname is studio

You can use any command or script, and you can combine commands:

$ echo "The usernames in my /etc/passwd file are $(awk -F":"  
'{ print $1 }' /etc/passwd)"

You can use command substitution to assign variables. You can run these commands individually or put them in a script:

$ CWD=$(pwd)
$ DATE=$(date)
$ HOSTNAME=$(hostname)
$ echo "The current directory is $CWD, the date and time are 
$DATE, and my hostname is $HOSTNAME"                                          
The current directory is /home/carla/testdirs, the date and time  
are Sun Jul 24 13:53:34 PDT 2016, and my hostname is studio

Here we are at the end again already. In this article, I’ve shown the basics of how to use some important Bash commands. Please see these other articles for more beginning Bash tutorials.

Sign up to receive one free Linux tutorial each week for 22 weeks from Linux Foundation Training. Sign Up Now »