When you talk about shell programming, or any kind of programming for that matter, you are going to deal with variables on different levels. In the shell, you have the built-in variables you saw earlier, and you can assign variables as well. For instance, without writing a script, type this line at your shell (command-line) prompt:hours=24
Then type this:echo "There are $hours hours in a typical day"
The system responds with this:There are 24 hours in a typical day.
You access that variable by putting a dollar sign ($) in front of it. If you just enter that line in a shell script (not the hours=24 line), made that script executable and ran it, you would get this:There are in a typical day.
The shell script did not pick up the $hours variable. In order for the shell script to know about the variable “hours,” you need to export it. There are two ways to do this. One is to assign the variable as you did and then type the command export hours. You can also put the whole thing on one line and save yourself some keystrokes.export hours="24"
Running the script now displays a much more intelligent message about how many hours are really in a day.
Aside from user-assigned variables, the script can make use of environment variables. These are variables set for you at login time by the system. Some of these are sometimes overwritten by the .bash_profile file in the user’s home directory or the global /etc/profile. A common one to see modified is the PATH variable, which lists the possible search paths for executables. Check your own $HOME/.profile or $HOME/.bash_profile file for the references to PATH.PATH=$PATH:$HOME/bin:/usr/local/bin export PATH
As you can see, you can modify an environment variable by referencing it in your assignment. The second line exports PATH and a number of other variables so that they are available to you in any shell and any environment in which you might work. To have a look at your environment variables, type this command:
Certain characters mean very specific things to the shell. Following is a sample of what you will encounter.Character Description $ Highlights the beginning of a variable’s name # Comment character ? Matches a character * Matches any number of characters . Sources or tells the shell to execute the filename that follows " Defines a string ' Defines even special characters as part of a string ` Executes what is inside the ticks \ Escapes the character that follows [ ] Lists a range of characters inside the brackets
The dollar sign ($) is one that you have already seen. It indicates the beginning of a variable name. You’ve also see the comment character (#) and later, I will discuss some of its special properties. The question mark (?) and the asterisk (*) perform similar functions in that they are used for matching characters. The asterisk will match any number of characters while the question mark matches only a single character. If you wanted to match two characters only, you could use two question marks (??). To match three characters, you can use three question marks (???), and so on.
First and foremost, I want to talk about the backslash (\). When a backslash is put in front of a special character, it stops the shell from interpreting that special character. Here’s a simple and, I think, effective demonstration. At your shell prompt, type this command:echo *
Did you get a listing of every file in your directory separated by spaces? That’s what I thought. Try it again, but this time put a backslash in front of the asterisk.echo \*
Notice that the shell now echoes a single asterisk. Anytime you want to use a special character like those in the shell, but you don’t want them treated in any way special, front them with the backslash (which I suppose is a kind of special treatment).You Can Quote Me on That
Ah, quotes. I have lots of favorites. One of them is “I want to live forever or die trying,” which is something Spider Robinson said but I wish I had. Sorry, different kind of quote.
Of course, I should be talking about what quotes mean to the shell. Double quotes ("") tell the shell to interpret what is inside them as a string. This is the way you define variables or echo text back to the terminal.
You’ll notice that I put a double quote inside my double quotes, but escaped the character with a backslash. If I were to type echo $my_ variable, this is what I would get:This is a double quote " inside my double quotes.
Single quotes (') would seem, on the surface, to do the same thing as double quotes, but they do have another important function. Let’s set a couple of variables and build a little shell script.os_name="Linux" os_desc="way cool" echo "$os_name is $os_desc." Linux is way cool.
That’s more or less what you would expect here. Now, let’s put single quotes around that echo command and see the difference.echo '$os_name is $os_desc.' os_name is $os_desc.
Hmm...it would seem that single quotes stop the shell from interpreting dollar signs as indicators of variable names. Now, how about those back ticks? Back ticks (`), or back quotes, are special in that they execute what is inside them. For instance, if you had a shell script that echoed "The current date and time information is . . . " and you wanted to have that something or other filled in, you would want the output of the date command. Here’s one way of doing this:the_date=`date` echo "The current date and time information is $the_date."
Another, easier way to do this is to put the back-quoted date command inside the echo line itself.echo "The current date and time information is `date`."
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 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!shellscriptingbash
If you are running either any of the Buntus (e.g. ubuntu, kubuntu, lubuntu), including Linux Mint, you may have had Medibuntu in you repositories for things like the DVD decription library (libdvdcss2) and other proprietary codecs. Medibuntu was not a distribution but referred to Multimedia, Entertainment, and Distractions in Ubuntu, referring to the types of packages it stored and made available. That repo has now shut down, my first hint of which was the following message on an "apt-get update".W: Failed to fetch http://packages.medibuntu.org/dists/raring/InRelease W: Failed to fetch http://packages.medibuntu.org/dists/raring/Release.gpg Could not resolve 'packages.medibuntu.org' W: Some index files failed to download. They have been ignored, or old ones used instead.
That's because the repo is no more and isn't coming back. If you have it on your system, you should get rid of it, either by manually removing the entries in /etc/apt by typing the following.sudo rm /etc/apt/sources.list.d/medibuntu.list
Pretty much everything you need in terms of getting restricted codecs to work is in the ubuntu-restricted-extras package (or kubuntu-restricted-extras, etc) except, of course, for the DVD decryption library. You can add that one by executing the following command.sudo /usr/share/doc/libdvdread4/install-css.sh
This will download and install libdvdcss2 from videolan.org where it will now be hosted going forward.
Hey! You're still here. Cool! Feel free to comment if the mood takes you. Also, add me to your circles or friend list if you haven't already done so, and 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. You know what I mean, right?medibuntucodecslibdvdcss2
Welcome back to my Shell Scripting vs Programming series. This is part deux.
In the introduction, I gave you a taste of just how simple it can be to create a shell script. Add a few commands to a file, save it, then execute the file. That’s it. The shell, bash, executes the three commands in that file and exits. Sometimes, the simplest shell script imaginable is the command itself. Imagine a command with a number of options and flags. In previous series on Mastering the Linux Shell, I had a tutorial on using the find command to locate large files that haven't been modified in quite some time. The rather long command looks something like this.find /path/starting_folder -size +1024 \( -mtime +365 -o -atime +365 \) -ls
To make life easier, you could create an alias for the command and put in in your local .bashrc file so that the command is available whenever you log in.alias findbig='find /path/starting_folder -size +1024 \( -mtime +365 -o -atime +365 \) -ls'
I could make several aliases for different starting folders and call them findbig_downloads, findbig_home, findbig_wherever and so on. Now all I had to do was type the appropriate findbig command and I'd have my list of big old files without having to type the long find command each time. Another way to do this would have been to type the command into a file called findbig_whatever, save it in /usr/local/bin, and make it executable, which would have produced the same effect. Rather than an alias, I would have had a shell script. Here are the steps:vi /usr/local/bin/findbig_whatever
Once you have typed in the command, save your work. The next step is to make it executable.chmod +x /usr/local/bin/findbig_whatever
I then create one shell script for each of the incarnations of finding big old files I want, save those, and make each and every one of them executable as well. But wait! Wouldn't it be a lot nicer to have just one script and supply the path I want to search as a parameter to that one command. Sounds great, but how do I pass the path that I want to search? If I just run this script by typing /usr/local/bin/findbig_whatever marcel, it doesn’t search anything other than /path/starting_folder. That’s because the script isn’t using the information being passed to it. This brings us to the subject of parameters.Passing Parameters
Here’s a really simple way to experience how the shell interprets parameters passed to it. Write this little script and call it paramtest:#!/bin/bash # This script demonstrates positional parameters # echo "This is parameter 0 : $0" echo "This is parameter 1 : $1" echo "This is parameter 2 : $2" echo "This is parameter 3 : $3" echo "Here are all the parameters : $*"
Make it executable with chmod +x paramtest. Now, execute it like this:./paramtest this is a shell script
This is the output you will see:This is parameter 0 : ./paramtest This is parameter 1 : this This is parameter 2 : is This is parameter 3 : a Here are all the parameters : this is a shell script
The first thing you should notice is that the script name (or the command, if you prefer) is parameter $0. Parameters $1, $2, and $3 are the first three words passed to the script. Notice also that the last two words, “shell script,” have simply been absorbed by the script. These would have been represented by $4 and $5, which you did not ask to have echoed to the screen. How about the last line? As you can see, the entire list of parameters (not counting the program name) is echoed back.A First Look at Variables
The $0, $1, $2, and so on, are variables. In other words, they can represent different values depending on what parameters are passed to your script. The $* variable is a special one in that it represents all the parameters passed to the shell. Like the $number variables, this is one is built into the shell itself. You do not have to define it.
So, going back to the findbig example, I could modify the script by simply adding a $1 where the command is expecting the pathname. Then, passing a pathname would work. Here’s the resulting script now:find $1 -size +1024 \( -mtime +365 -o -atime +365 \) -ls
To make the script more intelligent, I could add a check for a parameter using the “if” construct. The following is my updated script. I am also going to specify that I always want to use the bash shell for execution. Enter the information as you see it, save the file and make it executable as before.#!/bin/bash # This script will look for and list big old files in a folder if [ $# -eq 0 ] then echo "findbig : You must specify a pathname" exit 0 else find $1 -size +1024 \( -mtime +365 -o -atime +365 \) -ls fi
Lots of stuff here. The script checks to see if there are any parameters at all. If the count of parameters (that’s what the variable, $# means) is zero, it prints an error message and exits. If I remembered to pass it a pathname, I get a nice list of big old files, using whatever starting folder I chose.$ findbig /home/marcel . . . long file listing will appear here . . .
You've gone from creating several scripts to a single, all purpose one. This is where I will leave it until next time.
As usual, if you wish to comment, please do so on Google Plus in the comment form below, or over 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 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!shellscriptingbash
It's time for a new series focusing on the Linux shell. In my last series, I taught you how to work in the shell to manipulate files and directories, execute commands, find things, and work with a powerful editor. This time around, I'm going to talk about programming in the shell. What I want to do is get you comfortable with the idea of writing small, useful scripts to do your job as an administrator of your Linux domain, no matter how small or large. To that end, I will concentrate on bash. Then, I’ll cover some of the other scripting languages out there in order to see how they might best help you do your job. And so today is just an introduction. I'll pick up the pace and start regular tutorials in the next couple of days. When I wrap-up today's introduction, I'll leave you with a teaser to show you just how easy it is to write a shell script.
One of my favorite lines is “I am not a programmer,” which isn’t to say that I don’t know how to program or that I haven’t wrestled with a number of different programming languages over the years. I suppose that sounds a bit like Dr. McCoy saying, "I'm a doctor, not a fill-in-the-blank." Names like COBOL, FORTRAN, BASIC, C, C++, Ada, Perl, and the dreaded assembler all come to mind as a reminder. I have been known to write programs and I am likely to do so again. It just doesn’t happen to be the sort of thing that excites me. Systems administration excites me. So does network design, security, systems integration, and the great bugaboo, technical support (I always loved puzzles).
I’m like the chef who likes to put a number of ingredients together to create a new culinary masterpiece. Like that chef, I rely on others to provide me with the ingredients to do my work. Consequently, I have a deep admiration for professional (and amateur) programmers who can take a complex project and devote weeks or even months to bring out the tools that people like me rely on. If I haven't publicly thanked you lately, "Thanks to you all."
That said, even systems administrators need to program on some level. A single tool is rarely the answer to a single problem, and sometimes, only by assembling the right blend of tools will you provide exactly the solution you seek. Putting those tools together requires programming. The average Linux distribution comes with a plethora of programming and program development environments. Luckily, the average administrator can satisfy all his or her programming needs with a couple of very neat languages.
One of those languages is something you are already using.
The shell is the most basic of environments for working with your Linux system. Whatever you may think of working in a text environment, I guarantee that once you have fully experienced the power of simple text, you will be forever convinced. Text is compact. Text is fast. System administration over a network is best experienced at the shell level. Those forced to resort to graphical tools over a slow Internet connection are also quickly converted.
What many people do not realize is that the shell is actually a programming language. There are many shells. The most common in the Linux world is called bash, the Bourne Again Shell. Other shells you may find on your Linux system include sh, the classic Bourne shell (I have yet to find a major Linux or UNIX distribution that did not include it), pdksh (the public domain Korn shell), and that old programmer’s favorite, csh (the C shell).
The list of shells I’ve given you so far is but a small subset. There’s ash (stands for “a shell”), tcsh (an enhanced C shell), and zsh (the Z shell). Like walking along the beach and building a collection of interesting and unique shell specimens, a little tour through your favorite software repository, such as Freecode, will show you that people are constantly playing with and designing shells. Far from being an exhaustive list of the shells that exist for Linux, my list is merely a collection of the more popular ones. Certainly, all of these are likely to be on your distribution CD. Covering all these shells in detail would demand that I write a book on the subject, or perhaps several books, so I won’t even pretend to attempt it.
Let's write your first shell script.It's Commands All The Way Down
A shell script can be just a collection of commands saved in a file. Too easy? Say that throughout the day, I regularly check the time and date, print the disk-free information, and check how long my system has been running with uptime. I can open a blank file with my favorite editor and just type each command on its own line.date df uptime
Since I'm not covering editors in this teaser, let me show you how to write a script without one. Start by typing the following in your favorite terminal program (e.g. gnome-terminal, konsole, etc) :cat > check3
Now type those three commands, one by one, pressing the return (or Enter) key after each one. What you are doing here is writing to a file called check3, a completely arbitrary name for our script. After you enter the last command, hold down the Ctrl key and press "d" (i.e. Ctrl+d). That will terminate the file creation and save our script. You can then can execute this script by typing the following:bash check3
That’s it. The shell, bash, executes the three commands in that file and exits.
And this is where I leave it for today.
As usual, if you wish to comment, please do so on Google Plus in the comment form below, or over 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 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!bashshellscripting