Topics
![]() | About Shells
|
![]() |
Acceptable Use Policy |
![]() |
Free Trial |
![]() |
IRC Resources |
![]() |
Rates |
![]() |
Scripting |
![]() |
Shell Forum |
![]() |
Shell Games |
Shell ScriptingThere are a variety of different shells available, bourne shell (/bin/sh), korn shell (/sbin/ksh), bash (/bin/bash), csh (/bin/csh), tcsh (/bin/tcsh), and zsh (/bin/zsh). Each of these shells has different capabilities and a different scripting language. With the exception of csh and tcsh, they are all supersets of the Bourne shell (/bin/sh). Consequently most Unix shell scripting is done with Bourne shell scripts and for that reason, that is what this document covers. Once you learn the basics of Bourne shell scripting, you can look at the manuals for the other shells and figure out how to write scripts in them. As I mentioned, most are supersets of the Bourne shell, with the exception of csh and tcsh, and thus most simply add additional commands and capabilities. First it is helpful to understand a little bit about Unix permissions and conventions. There are three groups of permission bits associated with every Unix file, Owner, Group, and Other, and each of these has three bits, a read, write, and execute bit. In addition to these three groups there are a handful of special meaning bits but usually they aren't relevant to shell scripting.
These bits can be represented as an octal number with '1' being the
execute bit, '2' being the write bit, and '4' being the read bit. A
combination of these OR of all bits set. For
example: When you create a shell script, after creating it, you will usually want to execute the above chmod command to set the permissions so that it can be executed.
The Linux and other Unix operating systems need to know if a file is a
binary executable file or a scripting language file. If it is a binary,
the operating system loads it into memory and executes it. If it is a
script, Linux looks at the first line to determine what scripting language
should interpret it. In the case of Bourne shell scripts that would be
/bin/sh. The way to tell the operating system is to put the following in
the very first line of the
file: With the exception of the '#!/bin/sh' used to indicate to Linux that it is a shell script, shell scripts are nothing more than shell commands in a file. Anything you can type into the shell command prompt, you can also put into a shell script file. By extension, you can use facilities like loop constructs that ordinarily would appear in a shell script, as typed commands. Hello World
The first program most people learning C write is a "Hello
World" program, so here is a simple shell script that performs the
same function: To be useful, a programming language generally has to have variables, looping constructs (a way of doing something repeatitively), branching constructs (a way to alter execution based upon a condition), variables, arithmetic and string manipulation, some I/O capability, and the Bourne shell provides all of these things. VariablesThe bourne shell provides simple variables in the form of $name where, name is some alpha-numeric name and must not be one of the reserved keywords. Bourne shell variables are at once integers, booleans, and strings. Whatever you assign to a variable is stored as a string. If used in a mathematical expression, it is interpreted as an interger value. If used in a conditional expression, any non-zero value is interpreted as TRUE, zero as FALSE. Variables may be optionally exported in which case they will be made available in the environment of any program that is executed from the shell.
Variable assignment is done like
this: The command line is passed to the shell with variables starting at $0, and then $1, $2, and so on depending upon the number of arguments. $0 is the name of the program (shell script) itself and this is useful in that you can write shell scripts that behave differently depending upon the name they were invoked as by examining the value of $0 and acting accordingly. Conditionals
Conditionals work pretty simple in the Bourne shell. The syntax is like
this: In the above example, the conditional execution was decided by the value of a variable $value. If $value contained a non-zero value, the commands in the if clause would have been executed; otherwise the commands in the else clause, if it existed, would have been executed. If a command isn't an internal shell command then the shell attempts to execute a program by that name. If it finds and executes it, then the exit value of the program is returned and used just as if the command had been a variable. For example:
#!/bin/sh
if grep "^$1:" /etc/passwd >/dev/null
then
echo 'Yes, '${1}' exists in the password file.'
else
echo 'No, '${1}' is not found in the password file.'
fi
The above little script simply looks for a username in the password file
and says if they exist or not. Type it into a file and call it lookpw,
chmod 755 on the file so that you can execute it, the try it. Try
something like: In the above example, 'grep' is an external program that looks for strings in a file. It normally echoes to standard output any line that matches, but I've redirected the output to /dev/null which discards it. Grep also returns a non-zero value if a match is found, and a zero value if not. This allows us to base conditional execution in the shell upon the exit value of grep and do something different when it found a match as opposed to when it did not. In the above example, using double quotes allows the expansion of special characters within the double quotes, single quotes is interpreted literally. So, the '^' before the $1 variable means start of line, and the ':' after the $1 value is a literal colon. Thus grep is looking for whatever we type from the start of the line in the password file up to the first ':'. This first field is the login and so this program looks for logins in the password file. In this example we demonstrated how to take a command line argument, form an expression, and pass that to an external program (grep), and then take the exit value of that program and execute conditional code based upon that exit value. Loop ConstructsLike the C programming language, the Bourne shell provides several looping structures. The most commonly used are: while $value do ... done In this form, shell keeps doing whatever commands are in the loop until value is zero. If nothing ever changes value to a non-zero value then the shell will keep executing the code indefinitely. The other common loop construct is: For x in ... do ... done In this example, the loop assigns a value to $x for each item in the list that follows 'in', and do whatever is between the 'do' and the 'done'. The list may be replaced with lines from a file by doing this: for x in $(<file) do ... done In the following example, I've created a file called tstfile with the following content: root xyzzy mysql blob And I've created the following script:
#!/bin/sh
for x in $(<tstfile)
do
if grep "^${x}:" /etc/passwd > /dev/null
then
echo 'Yes, '${x}' is in the password file.'
else
echo 'No, '${x}' is not in the password file.'
fi
done
Running the script produces the following output: Yes, root is in the password file. No, xyzzy is not in the password file. Yes, mysql is in the password file. No, blob is not in the password file. This demonstrated reading input from a file, processing that input in a primitive way, and executing conditional code with each iteration based upon that input. There is much more and I'll expand on this in the future. Check back.
Custom Search
|

