Tuesday, February 4, 2014

More Pi-JNOS fun

So, you have your TNC-Pi built, JNOS up and running on your Pi, but you know there are things that you could be doing, but don't know how.  Well, let's do a (very) short tutorial on bash and the crontab.

bash is the Linux equivalent of the DOS batch files, but it is way more powerful.  crontab is the scheduler which lets you have your Pi do things at a predetermined time.

Unlike DOS, file extensions don't mean a lot to Linux.  But they are often used, and some programs pay attention.  For example, many graphics programs expect a file with the extension .jpg to be a JPEG image.

The command ls for listing files has settings that can cause certain extensions to be listed in specific colors.  By default in Pidora, images and videos are purple, sound files light blue, and archives of various types red.  In addition, files with executable permission are shown in green, and directories in blue:



When you write a "batch file" (in Linux called a bash script), it must have an executable permission.  You give it that permission with the chmod command:

chmod +x myscript

By default, unlike DOS, the current directory is not on the path, so to execute a script you must specify the path. For example:

./myscript

(like DOS, the current directory is . and recall that in Linux, you separate directory levels by / rather than \.

It is traditional, and sometimes helpful, for bash scripts to begin with the line:

#!/bin/sh

And like DOS, we can type commands to be executed, and there is an echo command which displays to the terminal.  So if we had a bash script like:

#!/bin/sh
echo "Say something, anything!"

It would echo to the terminal:


Notice that some of the commands seem a little odd.  We have already seen that the ls command is kind of like the DOS DIR command.  There actually is a Linux dir command, but it is rarely used because it isn't nearly as flexible as ls, which has dozens of options.

You can learn about the options of ls, or any command, by typing man followed by the command.  For example, man ls gives the following screen:


You can page back and forth, in this particular case there are about 11 screens of information. You can even search for specific things within the man page.

bash scripts may also have variables.  You can assign a value to the variable with the equal sign.  Since most Linux commands are lower case, it is customary to make variable names upper case so they stand out.

You can use the variable by placing a $ before its name.  Because there could potentially be some confusion on where the variable name ends, it can be a little safer to enclose the name in curly braces, but this isn't usually necessary.

So if we add a little something to the script:

#!/bin/sh
MYSTRING="dadadididit didididadah"
echo "Say something, anything!"
echo "Here is a string -- ${MYSTRING}"


The result would be:
So far not all that exciting, but there are a few neat features.  bash can loop through the words in a string, which can often be very handy.  For example:

You can also assign the result of a command to a variable by surrounding the command with backward quotes (on most keyboards at the upper left under the tilde).

So for example:

The date command is amazingly flexible.  See the man page for details.  JNOS names its log files as a two digit day of the month, a three character month, and a two character year.  So the log for February 4th, 2014 would be 04Feb14.

Suppose I want to move all of last month's logs files into a single zip file.  I want to do this after the month is over, so I want last month's date.  To further mess things up, I would like the month in the name of the zip file to be numeric, so when I look at a directory listing they are shown in some sensible order.

So, let's consider the following script:

#!/bin/sh

# Get the various date pieces:
#  Month as a 3 character string
MONTHA=`date -d "15 days ago" +"%b"`
#  Month as a 2 digit number
MONTHN=`date -d "15 days ago" +"%m"`
#  Year as a two digit number
YEAR=`date -d "15 days ago" +"%y"`

cd /jnos/logs
zip -om9 Log${YEAR}${MONTHN} *${MONTHA}${YEAR}


The -d switch tells the date command to use the specified date rather than the current date.  There are a number of ways to specify a date, but since I might not get to run this right at the first of the month, "15 days ago" is very likely a date in last month.

The date command also gives me plenty of options for formatting the date.  The + sign tells the command that a format is to follow.  The formats used here return the date as a three character month name, a two character month number, and the last two digits of the year.

If I were to run this today, February 4, 2014, this would move all files in /jnos/logs with names *Jan14 into a zip file named Log1401.zip.

If you are not familiar with the zip switches, -o says to set the date on the zip file to the same as the newest file in the zip, -m says to move files to the zip rather than copy, and -9 says to use maximum compression.  Following common Linux practice, one-character switches can be stuck together behind a single minus sign.

Linux has another neat feature called the crontab.  This is a table of things to do at specific times.  Each user has his own table.  You can list the crontab with:

crontab -l

and edit the crontab with

crontab -e

The lines in the crontab have a kind of peculiar format.  There are five numbers, separated by spaces, a tab, and then a command.  The five numbers are minutes, hours, day of the month, month and day of the week.  An asterisk may be used to mean every possibility.  Multiple occurrences can be separated by commas.

If we called our script compLogs.sh and stored it in a directory called bin off our home directory, the cron line:

36 8 3 * *        bin/compLogs.sh

would cause our script to be run at 8:36 A.M. on the third of every month.

I have a script that sends a finger command to the hamgate four times a day to check the health of the hamgate.  The crontab entry:

0 0,6,12,18 * * *    /root/finger-hamgate

causes the script to run at midnight, 6 A.M., noon and 6 P.M. every day.  Notice that I have multiple hours separated by commas.

This can get pretty gangly.  The Midland hamgate grabs radar images from NWS every five minutes.  Although this could have been done on one line, there are three entries just to make it a bit more readable:

2,7,12,17,22 * * * *      bin/WxImages.sh
27,32,37,42,47 * * * *    bin/WxImages.sh
52,57 * * * *             bin/WxImages.sh


Generally it is good practice to start cron jobs at odd times if possible.  Since there can be multiple cron tabs, if you make a habit of starting jobs at the top of the hour it can cause things to get real busy at certain times, and you might even have a hard time recognizing why.  These things tend to be "out of sight, out of mind" in pretty short order.  By starting jobs at odd times, you reduce the odds that a large number of jobs will start at the same time.

There are lots an lots of bash features that I haven't mentioned.  There are plenty of references, but the real flexibility of bash comes from your imagination, and that is tough to get from a book.  Best plan is to play around, write a bunch of scripts, and when you find something you don't know how to do, look through the man pages, online references, and ask around.  Chances are you can't figure it out because it's so obvious!

As you do this, one man feature that is really handy is a keyword search.  The -k for keyword switch allows you to search all the man pages for a particular keyword, so if you want to do something and don't know the command, this might help.  For example, if I wanted to see what the man pages know about ax25:


So go have some fun!