Shell Basics

Shells

The programming language the shell recognizes is dependant on the shell: sh, csh, tcsh, Korn shell, bash.

In some Unix environments, when users log in, the Bourne shell (or its close cousin, bash) starts up. On many systems, however, users will start in the C shell (csh).

You can change from csh to sh (or bash) simply by typing sh at the command line.

To make this change permanent, issue the command:

chsh
# then enter your password, then in Linux specify:
/bin/bash
# if your login system is a Unix system, specify:
/bin/sh

You may also need to check your .login and .profile files for a line like:

shell=/bin/csh

(Get fancy and build a grep command to do this for you.)

Change it to:

shell=/bin/sh
or
shell=/bin/bash

Why change your default shell? Isn’t the C shell just fine? See “Csh Programming Considered Harmful.” Simply put, the Bourne shell is the industry standard. You can do much more with sh than you can with csh. Some things can’t be done in csh at all.

 

Important Concept Number One: Order of Operations

Sometimes your results won’t make sense until you’re clear on the default order of operations performed by the shell.

The shell responds to a carriage return (the “Enter” key) by scanning the line and performing these operations in this order:

  1. Uses spaces to identify words (commands, options and arguments)
  2. Interprets wildcards to generate filenames
  3. Removes any quote characters
  4. Substitutes variables
  5. Substitutes embedded commands
  6. Executes the command

For example consider the command:

echo *

This will NOT echo the * onto the screen. It will provide a listing of all the files in your current directory. This is because the shell interprets the wildcard and passes the value (“all files”) as an argument to echo.

 

Login Scripts

Several small scripts are called upon login. They’re good examples of basic scripting.

Open the file ~/.bashrc

# .bashrc

# User specific aliases and functions

alias rm=’rm -i’
alias cp=’cp -i’
alias mv=’mv -i’

# Source global definitions
if [ -f /etc/bashrc ]; then
. /etc/bashrc
fi

Like a polite script, .bashrc reveals its own name at the top of the script:

# .bashrc

This is different from the standard beginning for a shell script. Normally you’d see a line specifying an interpreter:

#!/bin/bash

In this case you don’t, because this script is being called from a different, already-running shell script. In cases where a script is being called by another script (which is what happens with .bashrc), there may be a : character alone on the first line. Usually this is to allow a script called by one interpreter (like csh) to run under another interpreter (in this case sh). See the ITS script frzlegi.shl for an example.

 

Aliases

The three alias declarations are defaults set (usually by the sysadmin) for some of your commands. The rm command, for instance, is forced into a different mode by the option -i .

    1. What does this option do to the function of rm ?
    2. What option for rm will override this one?

Also notice that there are no spaces before or after equal signs! Bourne/bash will gladly blow up every time you use spaces next to equal signs in normal operations.

Finally, note that you could alias more than one command, as long as they’re separated by semicolons:

alias dw=”date;who”

 

If clauses

Now consider the “if” clause:

# Source global definitions
if [ -f /etc/bashrc ]; then
. /etc/bashrc
fi

In plain English, this reads something like:
“If there’s a file named /etc/bashrc, then execute /etc/bashrc.”

An if clause begins with the keyword “if,” followed by a test. If the test succeeds (for instance, some criteria is met), “then” indicates what to do next.

An if clause ends with the keyword “fi,” which is of course “if” spelled backward.

 

Tests

Note the way the test criteria is structured:

[ -f /etc/bashrc ]

“[” means “test.” (In fact there is a test command to which the character [ is aliased.)
What it’s testing for is the existence of a file (-f) named /etc/bashrc. If the file exists, the test is successful, and the “then” section will run. Run the command

help test

to see the test criteria available through this command.

 

The .

Also notice the “ . ” character:

. /etc/bashrc

Notice that there is a space between the dot and the slash!

This isn’t the dot with which you may be familiar. This dot, within the scripting context, means “execute.” In this example, it’s saying, “execute the bashrc file.” Formally, this operation is known as “sourcing.” It’s used to run a command in the existing script context; when you are running a script, for instance, this character causes the following command to run within the current context of the script, not as if it has been issued in a fresh terminal window.

 

Practical Uses

Consider some of the things you want to watch as a system administrator, for instance, who was logged in when. You could issue the command

(date;who)>>~/users.log

to record who’s currently logged in.

    1. What does the who command return?
    2. What does the users command return?

 

Start Writing a Script

Now you’re going to write a script.

Open vi, pico or your favorite text editor with a new filename:

vi userlog.sh

The first line of your script must declare the bash shell as the interpreter for the script:

#!/bin/bash

(Read “hash bang bin bash.”)

 

touch

Remember that you must have a target log file to which your script will write. The line:

touch ~/users.log

will either update the last-modified date of the users.log file, or create it if it doesn’t exist.

On the third line, place your user-logging command:

(date;who)>>~/users.log

Save the file.

Now call your script several times .

    1. What else is necessary to make it run?
    2. Under what user’s permissions will this script run?
    3. Run the command cat ~/users.log .
    4. Compare the output of cat with the output of tail: tail ~/users.log .

Your log file should look like this when you cat it:

User Log File