Scripting Intro
Shells like bash and Korn have support for programming constructs
that can be saved as scripts. These scripts in turn then become more
shell commands. Many Linux commands are scripts.
User profile scripts are run when a user logs on and init scripts
are run when a daemon is stopped or started.
This means that system administrators also need basic knowledge of
scripting to understand how their servers and their applications are
started, updated, upgraded, patched, maintained, configured and removed,
and also to understand how a user environment is built.
The goal of this chapter is to give you enough information to be able to read and understand scripts. Not to become a writer of complex scripts. prerequisites =============
You should have read and understood part III shell expansion and
part IV pipes and commands before starting this chapter.
hello world
Just like in every programming course, we start with a simple
hello_world script. The following script will output Hello World.
echo Hello World
After creating this simple script in vi or with echo, you\'ll have
to chmod +x hello_worldchmod +x to make it executable. And unless you
add the scripts directory to your path, you\'ll have to type the path to
the script for the shell to be able to find it.
[paul@RHEL4a ~]$ echo echo Hello World > hello_world
[paul@RHEL4a ~]$ chmod +x hello_world
[paul@RHEL4a ~]$ ./hello_world
Hello World
[paul@RHEL4a ~]$
she-bang
Let\'s expand our example a little further by putting #!/bin/bash on
the first line of the script. The #!#! (shell) is called a
she-bangshe-bang (shell) (sometimes called sha-bang), where the
she-bang is the first two characters of the script.
1 2 | |
You can never be sure which shell a user is running. A script that works
flawlessly in bash might not work in kshksh, cshcsh, or dash. To
instruct a shell to run your script in a certain shell, you can start
your script with a she-bang#!/bin/bash followed by the shell it is
supposed to run in. This script will run in a bash shell.
1 2 3 | |
This script will run in a Korn shell (unless /bin/ksh is a hard link
to /bin/bash). The /etc/shells/etc/shells file contains a list of
shells on your system.
1 2 3 | |
comment
Let\'s expand our example a little further by adding comment lines.
1 2 3 4 5 | |
variables
Here is a simple example of a variable inside a script.
1 2 3 4 5 6 | |
Scripts can contain variables, but since scripts are run in their own shell, the variables do not survive the end of the script.
[paul@RHEL4a ~]$ echo $var1
[paul@RHEL4a ~]$ ./vars
var1 = 4
[paul@RHEL4a ~]$ echo $var1
[paul@RHEL4a ~]$
sourcing a script
Luckily, you can force a script to run in the same shell; this is called
sourcingsource a script.
[paul@RHEL4a ~]$ source ./vars
var1 = 4
[paul@RHEL4a ~]$ echo $var1
4
[paul@RHEL4a ~]$
The above is identical. (shell) to the below.
[paul@RHEL4a ~]$ . ./vars
var1 = 4
[paul@RHEL4a ~]$ echo $var1
4
[paul@RHEL4a ~]$
troubleshooting a script
Another way to run a script in a separate shell is by typing bash with
the name of the script as a parameter.
paul@debian6~/test$ bash runme
42
Expanding this to bash -xbash -x allows you to see the commands that
the shell is executing (after shell expansion).
paul@debian6~/test$ bash -x runme
+ var4=42
+ echo 42
42
paul@debian6~/test$ cat runme
# the runme script
var4=42
echo $var4
paul@debian6~/test$
Notice the absence of the commented (#) line, and the replacement of
the variable before execution of echo.
prevent setuid root spoofing
Some user may try to perform setuidsetuid based script
root spoofing. This is a rare but possible attack. To improve script
security and to avoid interpreter spoofing, you need to add -- after
the #!/bin/bash, which disables further option processing so the shell
will not accept any options.
1 2 3 | |
Any arguments after the ---- (shell) are treated as filenames and
arguments. An argument of - is equivalent to --.
practice: introduction to scripting
===================================
0. Give each script a different name, keep them for later!
1. Write a script that outputs the name of a city.
2. Make sure the script runs in the bash shell.
3. Make sure the script runs in the Korn shell.
4. Create a script that defines two variables, and outputs their value.
5. The previous script does not influence your current shell (the variables do not exist outside of the script). Now run the script so that it influences your current shell.
6. Is there a shorter way to source the script ?
7. Comment your scripts so that you know what they are doing. solution: introduction to scripting ===================================
0. Give each script a different name, keep them for later!
1. Write a script that outputs the name of a city.
$ echo 'echo Antwerp' > first.bash
$ chmod +x first.bash
$ ./first.bash
Antwerp
2. Make sure the script runs in the bash shell.
$ cat first.bash
#!/bin/bash
echo Antwerp
3. Make sure the script runs in the Korn shell.
$ cat first.bash
#!/bin/ksh
echo Antwerp
Note that while first.bash will technically work as a Korn shell script, the name ending in .bash is confusing.
4. Create a script that defines two variables, and outputs their value.
$ cat second.bash
#!/bin/bash
var33=300
var42=400
echo $var33 $var42
5. The previous script does not influence your current shell (the variables do not exist outside of the script). Now run the script so that it influences your current shell.
source second.bash
6. Is there a shorter way to source the script ?
. ./second.bash
7. Comment your scripts so that you know what they are doing.
$ cat second.bash
#!/bin/bash
# script to test variables and sourcing
# define two variables
var33=300
var42=400
# output the value of these variables
echo $var33 $var42
Shells like bash and Korn have support for programming constructs
that can be saved as scripts. These scripts in turn then become more
shell commands. Many Linux commands are scripts.
User profile scripts are run when a user logs on and init scripts
are run when a daemon is stopped or started.
This means that system administrators also need basic knowledge of
scripting to understand how their servers and their applications are
started, updated, upgraded, patched, maintained, configured and removed,
and also to understand how a user environment is built.
The goal of this chapter is to give you enough information to be able to read and understand scripts. Not to become a writer of complex scripts. prerequisites =============
You should have read and understood part III shell expansion and
part IV pipes and commands before starting this chapter.
hello world
Just like in every programming course, we start with a simple
hello_world script. The following script will output Hello World.
echo Hello World
After creating this simple script in vi or with echo, you\'ll have
to chmod +x hello_worldchmod +x to make it executable. And unless you
add the scripts directory to your path, you\'ll have to type the path to
the script for the shell to be able to find it.
[paul@RHEL4a ~]$ echo echo Hello World > hello_world
[paul@RHEL4a ~]$ chmod +x hello_world
[paul@RHEL4a ~]$ ./hello_world
Hello World
[paul@RHEL4a ~]$
she-bang
Let\'s expand our example a little further by putting #!/bin/bash on
the first line of the script. The #!#! (shell) is called a
she-bangshe-bang (shell) (sometimes called sha-bang), where the
she-bang is the first two characters of the script.
1 2 | |
You can never be sure which shell a user is running. A script that works
flawlessly in bash might not work in kshksh, cshcsh, or dash. To
instruct a shell to run your script in a certain shell, you can start
your script with a she-bang#!/bin/bash followed by the shell it is
supposed to run in. This script will run in a bash shell.
1 2 3 | |
This script will run in a Korn shell (unless /bin/ksh is a hard link
to /bin/bash). The /etc/shells/etc/shells file contains a list of
shells on your system.
1 2 3 | |
comment
Let\'s expand our example a little further by adding comment lines.
1 2 3 4 5 | |
variables
Here is a simple example of a variable inside a script.
1 2 3 4 5 6 | |
Scripts can contain variables, but since scripts are run in their own shell, the variables do not survive the end of the script.
[paul@RHEL4a ~]$ echo $var1
[paul@RHEL4a ~]$ ./vars
var1 = 4
[paul@RHEL4a ~]$ echo $var1
[paul@RHEL4a ~]$
sourcing a script
Luckily, you can force a script to run in the same shell; this is called
sourcingsource a script.
[paul@RHEL4a ~]$ source ./vars
var1 = 4
[paul@RHEL4a ~]$ echo $var1
4
[paul@RHEL4a ~]$
The above is identical. (shell) to the below.
[paul@RHEL4a ~]$ . ./vars
var1 = 4
[paul@RHEL4a ~]$ echo $var1
4
[paul@RHEL4a ~]$
troubleshooting a script
Another way to run a script in a separate shell is by typing bash with
the name of the script as a parameter.
paul@debian6~/test$ bash runme
42
Expanding this to bash -xbash -x allows you to see the commands that
the shell is executing (after shell expansion).
paul@debian6~/test$ bash -x runme
+ var4=42
+ echo 42
42
paul@debian6~/test$ cat runme
# the runme script
var4=42
echo $var4
paul@debian6~/test$
Notice the absence of the commented (#) line, and the replacement of
the variable before execution of echo.
prevent setuid root spoofing
Some user may try to perform setuidsetuid based script
root spoofing. This is a rare but possible attack. To improve script
security and to avoid interpreter spoofing, you need to add -- after
the #!/bin/bash, which disables further option processing so the shell
will not accept any options.
1 2 3 | |
Any arguments after the ---- (shell) are treated as filenames and
arguments. An argument of - is equivalent to --.
practice: introduction to scripting
===================================
0. Give each script a different name, keep them for later!
1. Write a script that outputs the name of a city.
2. Make sure the script runs in the bash shell.
3. Make sure the script runs in the Korn shell.
4. Create a script that defines two variables, and outputs their value.
5. The previous script does not influence your current shell (the variables do not exist outside of the script). Now run the script so that it influences your current shell.
6. Is there a shorter way to source the script ?
7. Comment your scripts so that you know what they are doing. solution: introduction to scripting ===================================
0. Give each script a different name, keep them for later!
1. Write a script that outputs the name of a city.
$ echo 'echo Antwerp' > first.bash
$ chmod +x first.bash
$ ./first.bash
Antwerp
2. Make sure the script runs in the bash shell.
$ cat first.bash
#!/bin/bash
echo Antwerp
3. Make sure the script runs in the Korn shell.
$ cat first.bash
#!/bin/ksh
echo Antwerp
Note that while first.bash will technically work as a Korn shell script, the name ending in .bash is confusing.
4. Create a script that defines two variables, and outputs their value.
$ cat second.bash
#!/bin/bash
var33=300
var42=400
echo $var33 $var42
5. The previous script does not influence your current shell (the variables do not exist outside of the script). Now run the script so that it influences your current shell.
source second.bash
6. Is there a shorter way to source the script ?
. ./second.bash
7. Comment your scripts so that you know what they are doing.
$ cat second.bash
#!/bin/bash
# script to test variables and sourcing
# define two variables
var33=300
var42=400
# output the value of these variables
echo $var33 $var42