Shell Scripting: Really Programming The Shell

When you open up a terminal window on your Linux system, you are opening up a programming environment. While it may seem like just this place where you type commands to list your files or check on the amount of disk space you have left, the shell is a real programming language. True story. You even have access to constructs like “ifthenelse,” while and for loops, case statements, and more.

In case you're wondering how we got here, this is part 4 in a series.

Just to give you an idea of what I'm talking about, here’s a little script that runs the fabled Fibonacci sequence (named after famed 13th-century Italian mathematician, Leonardo Pisano, aka Fibonacci). In case you've forgotten the Fibonacci sequence is pretty simple. Each number in the sequence is the result of the sum of the two previous numbers.

   # Run a Fibonacci sequence through 10 iterations
   #
   last_number=1
   previous_number=1
   fib_iterations=0
   echo "The sequence starts with 1 and 1"
   until [ $fib_iterations -ge 10 ]
      do
         new_number=`expr $previous_number + $last_number`
         echo "The sum of $previous_number and $last_number is $new_number"
         previous_number=$last_number
         last_number=$new_number
         fib_iterations=`expr $fib_iterations + 1`
      done
   #
   echo "The sequence ends here after $fib_iterations."

All right, let’s try something with a little more system administration potential. We know that Linux is a multiuser system, but letting people log in time and again when they already have sessions open may not be what you want. You may be running a hungry database application that costs you on resources (or licenses) each time somebody logs in. Or maybe you're a geek running an old-style BBS and you don't want people logged in more than once.  Who knows? Doesn't matter. How can you stop users from logging in multiple times?

In the following example, you’ll create a file called user.allow that you’ll put in a hypothetical script directory called /usr/local/.Admin. If you add a user ID to this plain-text file with a space and a number, that user is allowed to log in however many times the number specifies.

   marcel 3
   inewton 2
   aeinstein 4

In that example, marcel is allowed three logins, inewton is allowed two, and aeinstein is allowed a grand total of four. All other users will by default be allowed only one login at a time. The information in this file will be used by our logtest script to make sure that people don't log in any more times than they are allowed. To make sure that everyone executes this script on login, add this line to the /etc/profile file:

. /usr/local/.Admin/logtest

Notice the period at the beginning of the line that tells the shell to source (or execute) the filename that follows. Before you get too comfortable with this wonderful idea, you’ll also want to make sure that the root user can log in as many times as he or she needs. To do all this, we're also going to use a rather cool server command called finger. You can, if you'll pardon the expression, finger a user to find out where they've logged in from and when, as well as how long they've been idle. It's extremely useful if you're the admin and you need to keep tabs on what your users are doing. The finger command isn't usually installed by default on a desktop Linux distribution, so you may have to install it first using apt or yum or zypper.

Excellent. I think you’ve got it all, so let’s have a look at the logtest script. 

   # Test for multiple logins and refuse login if beyond configuration
   #
   if [ "$LOGNAME" != "root" ]
   then
      no_logins=`finger | grep $LOGNAME | wc -l`
      no_allowed=`grep $LOGNAME /usr/local/.Admin/user.allow | cut -f2 -d" "`
      echo "No logins is $no_logins, while allowed is $no_allowed."
      if [ -z $no_allowed ]
         then
            let no_allowed=1
      fi
      echo "There are... $no_logins login processes under your name."
      echo "You are allowed $no_allowed login(s)."
      if [ $no_logins -gt $no_allowed ]
        then
            echo "You have exceeded your allowable limit."
            echo "Please try again later."
            sleep 5
            exit 0
      fi
   else
      echo "You are SuperUser and can log in all you want!"
   fi

Notice the -z test in the line that runs if [ -z $no_allowed ]. This tests the variable $no_allowed to see whether it is zero length or not. If it is zero (in other words, the UID was not listed in the user.allow exceptions file), you default that number to one.

By the way, your shell supports a number of tests on variables and file types. You can test to see if a string length is zero sized (as you did in the example with the -z), if a file is executable (-x), or if a file even exists (-e) for that matter. There are a number of such tests built in to be used with files or variables. To see what kind of tests the shell supports, type man test. But I digress . . . 

Anyhow, if you try to log in as marcel for the fourth time, you get this message:

   There are... 4 login processes under your name.
   You are allowed 3 login(s).

   You have exceeded your allowable limit.
   Please try again later.

At this point, you get logged out and have to start getting used to the idea of being somewhat less greedy. Or you try to make a deal with the systems administrator with promises of beer or pizza.

This is where I'm going to leave it for today. 

Please comment if the mood takes you, either in the comment form below or directly on Google Plus, You can also comment here on Facebook and add me to your circles or friend list if you haven't already done so; oh yeah, if you're on Twitter, follow me there. Also, make sure you sign up for the mailing list over here so that you're always on top of what you want to be on top of.  And buy an eBook from me. Oh, and a final request, please share this article with your favorite Linux and FOSS group or news site; I would sincerely appreciate it. Until next time . . .

A votre santé! Bon appétit!

Facebook Comments Box

Leave a Reply

Your email address will not be published. Required fields are marked *