Using the Shell, History, Variables, and Redirection

1 hour
  • 3 Learning Objectives

About this Hands-on Lab

The shell is the basic element of interaction with a Linux system. No matter what GUI desktops may exist, the shell is always there and ready to execute your commands. In this lab, we’ll explore what shells are available, what makes up the shell environment, and the different ways to log in, executing the shell’s environment as needed for our task.

Learning Objectives

Successfully complete this lab by achieving the following learning objectives:

Discover Available Shells, Use Privilege Elevation Commands, and View and Manipulate User History

See what shells are available in the environment

cat /etc/shells

Determine what shell we’re using:

set | grep SHELL

Find our user ID, group ID, and groups we’re secondary members of:


Elevate privileges and run id:

sudo -i id

Find out who you’re logged in as:


Elevate privileges and run whoami:

sudo -i whoami

View the history stack:


Write the history stack to a file:

history > shell-history.txt

Find the times you used whoami:

grep -i whoami shell-history.txt


whoami <up arrow>

run the last command


run a history command by number

!<number> ex !48
Explore System Variables, Create and Use Custom Variables, and Understand Special Variables

Create a script:




echo Hello, my name is $USER
echo My $PRODUCT costs 10 dollars

run it


Create the $PRODUCT variable and rerun the script



Find out which shell level we’re on:

echo $SHLVL

Edit the script:
At the top of the file, right below #/bin/bash, enter:

echo Shell is at level $SHLVL

Run the script again:


We need to export the variable to make it available to the current shell:

export PRODUCT

Run the script again:


Edit the script:


Replace 10 dollars with $COST dollars USD. Save and quit the file.
Declare a COST variable:

export COST=100

View the file’s contents:


Run the script again:


Edit the script:


Change the PRODUCT variable line to:

echo "My $PRODUCT costs $$COST dollars USD"

We have to include a ` to make the$` properly show up.
Save and quit.
View the file’s contents:


Run the script:


Edit the script:


At the bottom of the file, enter:

echo My $PRODUCT comes in $1 and I have $2 of them in stock

echo The executable name is $0
echo The arguments entered were $*
echo The number of arguments were $#
echo The PID of this shell is $$

Here, $1 is the color of the snowblower and $2 is the amount in stock.
Save and quit.
View the file’s contents:


Run the script:


Enter the arguments:

bash Blue 10
Use Input/Output/Error Redirection to Execute Multiple Commands and Send Data to Disk

List the files output so they’re each on a separate line:

ls -1

Send the output to lsoutput.txt:

ls -1 > lsoutput.txt

Get its word count:

wc -l lsoutput.txt

View the file’s contents, using it as an argument:

cat lsoutput.txt

View the file’s contents, using it as an input:

cat < lsoutput.txt

The < is an input redirect.

Pipe the output to the nl (numbered lines) command:

cat lsoutput.txt | nl

This has each item on its own numbered line.

Pipe the output to the nl and tac (i.e., the opposite of cat) commands:

cat lsoutput.txt | nl | tac

This time, each item is numbered, but the list starts from the last number.

Run the following:

find /proc -iname "*.*"

We’ll see a lot of stdrr (Permission Denied errors).

Put the good (or stdout) data in procdata.txt:

find /proc -iname "*.*" > procdata.txt

We’ll still see all the error messages.

View the procdata.txt file’s contents:

cat procdata.txt

We should see good/stdout data.

Send the stderr data to badprocdata.txt:

find /proc -iname "*.*" 2> badprocdata.txt

Put the stdout data in procdata.txt and get rid of the stderr data:

find /proc -iname "*.*" > procdata.txt 2> /dev/null

View the file’s contents:

cat procdata.txt

Use the tee command to write the stdout data to a file and send the rest to the console:

find /proc -iname "*.*" | tee procdata.txt

Discard the stderr data and send the stdout data to the file:

find /proc -iname "*.*" 2> /dev/null | tee procdata.txt

Using a ; between commands makes them both run, no matter if one throws an error:

ls ; farg

Here, farg is not an actual command, but both commands still run.

Using double pipes means "if the first command fails, only then run the next command." Try it:

ls || farg

Because ls worked, farg did not run.

Switch them around:

farg || ls

Since farg failed, it had to failover to ls.
Using double ampersands means "run the next command only if the first command is successful." Try it:

ls && farg

Since ls worked, it also ran farg.
Reverse the order:

farg && ls

Because farg failed, ls did not run.

Additional Resources

In preparation for setting up a server for a new group of users, you install a SUSE Linux Enterprise Server 15 system and set about learning what makes up the Bash environment elements. You look at the history function, discover how to re-execute commands, and use the history features to your advantage. You also learn how to write simple scripts, use system variables, in them and make and use your own custom variables that help make your scripts more useful.

What are Hands-on Labs

Hands-on Labs are real environments created by industry experts to help you learn. These environments help you gain knowledge and experience, practice without compromising your system, test without risk, destroy without fear, and let you learn from your mistakes. Hands-on Labs: practice your skills before delivering in the real world.

Sign In
Welcome Back!

Psst…this one if you’ve been moved to ACG!

Get Started
Who’s going to be learning?