Prerequisite
Goals
-
Review the main configuration files associated with the bash shell
-
Write and execute shell scripts
-
Syntax for logical evaluations, flow controls and loops
1. The bash environment
Variables
When you type a command at the prompt the bash shell will use the PATH variable to find which executable on the system you want to run. You can check the value of path using the echo command:
echo $PATH
|
/usr/bin:/bin:/usr/sbin:/usr/X11R6/bin:/usr/local/bin:/sbin/:/usr/local/sbin/
|
In fact many variables are needed by the shell to accommodate for each user’s environment. For example PWD, HOME, TERM and DISPLAY are such variables.
To initialise and declare a variable the syntax is as follows:
VARIABLE=VALUE
Remember not to put any spaces around the ‘=’ sign. Once a variable is declared and initialised it can be referenced by using the dollar symbol in front as here:
echo $VARIABLE
|
This declares a local variable (only available for the current process) that can be listed with set. It is possible to get an exported variable (available to all child processes spawned after the variable has been defined) using export. Exported variables are listed with the env command.
When a shell session is started a number of configuration files are read and most of the variables are set.
To free a variable from its current value use unset.
Configuration files
One can distinguish configuration files which are read at login time and configuration files which are read for each new bash session.
The profiles
The first file to be read at login is /etc/profile, after that the shell will search for the files ~/.bash_profile, ~/.bash_login and ~/.profile and execute the commands from the first available on. For every new shell (for example if an xterm emulator is started) these profiles are not read again.
Contents: the profiles are used to define exported variable (e.g PATH) that will be available for every subsequent program.
The bashrc files
The runtime control files ~/.bashrc and /etc/bashrc are sourced every time a shell is started
Contents: the runtime control files will store aliases and functions.
Notice that non-interactive shells read neither of these files. Instead a BASH_ENV variable pointing to the file to be sourced is declared in the script.
Function syntax
function-name ()
{
command1;
command2;
}
You can test which files are being read by adding an echo Profile line in /etc/profile, the type:
bash No profile is read, you shouldn’t see anything
bash -login This forces bash to act as a login bash, the word
Profile should show up.
The following commands control the way bash starts:
bash -norc
bash -noprofile
Notice that any new bash session will inherit the parent’s global variables defined in /etc/profile and ~/.bash_profile.
Controlling readline
The GNU library readline is used by programs that expect user input. It also offers extensive vi and emacs style editing functionality.
Example: the readline default editor setting for bash is emacs. One can for example use ^E to go to the end of a line. What happens when we next start, as below, a shell without editing support?
bash --noediting
|
The files /etc/inputrc or ~/.inputrc are used to control the readline library. One can for example link a keyboard combination to an action.
Example options for inputrc:
|
set editing-mode vi change the initial editor style (default is emacs)
|
Control-o: "> output" bind the sequence Ctrl+o will cause the string “> output ” to be printed
|
TAB: complete automatically complete commands and file names (is set by default)
|
set bell-style none input errors are not audible (other option is audible)
|
Finally, when a user logs out, the shell will read commands from ~/.bash_logout if it exists. This file usually contains the clear command which clears the screen once the shell exits.
2. Scripting Essentials
The script file
A shell script is a list of instructions saved in a flat file. Only two things are necessary.
1. The script’s first line must be #!/bin/bash (for a bash script)
2. The file must be readable and executable (with 755 permission for example)
Assuming the script is in your current directory it can be started with
NOTICE
|
The interpreter specified after the #! sign (pronounce she-bang!) is used to read the commands in the script. If no interpreter is specified then the shell will attempt to interpret the commands itself.
|
Alternative methods
|
bash script-name
|
start a new interactive bash which will run the script then exit
|
source script-name
|
force your current shell to run the script
|
. script-name
|
same as source
|
exec ./script-name
|
same as ./script-name except that the current shell will exit one the script has run
|
Passing variables to the script
Variables entered at the command line are referenced inside the script as $1 for the first argument, $2 for the second, etc …
Example script, mycat:
This script is expecting one argument, a file, and will display the content of the file using cat. To run this script on the lilo.conf file, you would run:
./mycat /etc/lilo.conf
|
Another way of passing variables to a script is by letting the script prompt the user for input interactively. This is achieved using the read command. The default name of the read variable is REPLY. Here is the modified script:
Interactively passing:
#!/bin/bash
|
echo -n "Which file shall I display ?"
|
read
|
cat $REPLY
|
or
read -p “File to display: “ FILENAME
cat $FILENAME
Special Variables
Special variables can only be referenced and are automatically set by bash. These are the most common special variables you will encounter:
$* List of all variables entered at the command line
$# Number of arguments entered at the command line
$0 The name of the script
$! PID of the most recent background command
$$ PID of the current shell
$? Exit code of the last command
For the positional parameters $1, $2 etc … there is a shift operator which renames each parameter in a cyclic way as follows.
$2 becomes $1
$3 becomes $2 … etc
This can be summarised as $(n+1) $n
3. Logical evaluations
Logical statements are evaluated with the test command or the brackets [ ]. In both case the result is stored in the $? variable such that:
if the statement is true then $? is 0
if the statement is false then $? is not 0
Here are some examples to illustrate:
using test
|
using [ ]
|
meaning
|
test –f /bin/bash
|
[ -f /bin/bash ]
|
test if /bin/bash is a file
|
test -x /etc/passwd
|
[ -x /bin/passwd ]
|
test if /etc/passwd is executable
|
One can evaluate more than one statement at a time using the || (OR) and && (AND) logical operators on the command line. For example we could test if /bin/bash is executable and in /etc/inittab exists:
test -x /bin/bash && test -f /etc/inittab
[ -e /bin/kbash ] || [ -f /etc/passwd ]
|
This is the same as using the flags -o and -a within the test operator for example
test -x /bin/bash -a -f /etc/inittab
|
[ -e /bin/kbash -o -f /etc/passwd ]
|
4. Flow Control and Loops if then
Syntax: if CONDITION ; then
command1
command2
fi
#!/bin/bash
|
|
if [ -x /bin/bash ] ; then
|
echo “The file /bin/bash is executable”
|
while loop
Syntax: while CONDITION is true; do
command
done
Example: Aligne 10 hashes (#) then exit
#!/bin/bash
|
COUNTER=0
|
while [ $COUNTER -lt 100 ]; do
|
echo -n "#"
|
sleep 1
|
let COUNTER=COUNTER+1
|
done
|
Until loop
Syntax: until CONDITION is false; do
command
done
Example: Same as above, notice the C style increment for COUNTER
#!/bin/bash
|
COUNTER=20
|
until [ $COUNTER -lt 10 ]; do
|
echo -n "#"
|
sleep 1
|
let COUNTER-=1
|
done
|
for loop
Syntax for VARIABLE in SET; do
command
done
Example: the set 'SET' can be the lines of a file
#!/bin/bash
for line in `cat /etc/lilo.conf`; do
IMAGE=$(echo $line | grep image)
if [ “$IMAGE” != “” ]; then
echo Kernel configured to boot: $line
fi
done
5. Expecting user input
We assume that the script is waiting for user input, depending on the answer, the rest of the program will execute something accordingly. There are two possible ways to achieve this: select and case.
Using case
Syntax: case $VARIABLE in
CHOICE1) command1 ;;
CHOICE2) command2 ;;
esac
Using select
Syntax: select VARIABLE in SET; do
if [ $VARIABLE = CHOICE ]; then
command
fi
if [ $VARIABLE = CHOICE ]; then
command
fi
done
While shell scripts seamlessly handle character strings, a little effort is needed to perform very basic arithmetic operations.
Binary operations
Adding or multiplying numbers together can be achieved using either expr or the $(( )) construct.
Example:
expr 7 + 3; expr 2 \* 10; expr 40 / 4; expr 30 – 11
$((7+3)); $((2*10)); $((40/4)); $((30-11))
Comparing values
Test operators:
-
Numbers
|
Strings
|
-lt
|
< (sort strings lexicographically)
|
-gt
|
> (sort strings lexicographically)
|
-le
|
N/a
|
-ge
|
N/a
|
-eq
|
==
|
-ne
|
!=
|
7. Exercises and Summary
Files
Files
|
Description
|
/etc/bashrc
|
a system wide startup file for interactive bash sessions (used for setting up the PS1 prompt)
|
/etc/inputrc
|
startup file for the readline library used by the shell to read and edit user input. This file combines keyboard combinations with editing commands but can also be used to associate keyboard combinations to any command (macro)
|
/etc/profile
|
system wide configuration file for bash. It contains exported variables such as the PATH and is always read at login
|
~/.bash_profile
|
the user's customised configuration file for bash. It contains exported variables an is always read at login
|
~/.bashrc
|
the user's customised startup file for bash. It is read every time a new interactive shell is started unless the –norc option is given
|
~/.inputrc
|
the user's customised startup file for the readline library
|
Scripting items
Item
|
Description
|
$(( ))
|
operator used to substitute the result of a numerical evaluation in a command line
|
expr
|
perform a numerical evaluation
|
for loop
|
see p.72
|
if then
|
see p.71
|
until loop
|
see p.72
|
while loop
|
see p.71
|
Commands
Command
|
Description
|
test
|
test(1) – check file types and compare values
|
unset
|
(bash built-in) command that removes a variable value or a function
|
env
|
print all exported (global) variables defined in the current shell
|
export
|
(bash built-in) command that makes a variable part of the environment of subsequent processes
|
set
|
(bash built-in) command that when started with no arguments prints the value of all shell variables defined
|
Dostları ilə paylaş: |