Unit 8 Lab - Scripting
Info
If you are unable to finish the lab in the ProLUG lab environment we ask you reboot the machine from the command line so that other students will have the intended environment.
Resources / Important Links
- Killercoda Labs
- Wikipedia Page for Compilers
- Wikipedia Page for the C Programming Lang
- Wikipedia Page for Truth Table
- CProgramming.com Introductory
- Unit #1 Bonus (VIM) Page
- Unit #8 Bonus (Bash Scripting) Page
Required Materials
- Rocky 9.4+ - ProLUG Lab
- Or comparable Linux box
- root or sudo command access
Downloads
The lab has been provided for convenience below:
Pre-Lab Warm-Up
Review how to use vi, if you have a problem getting out or saving your file or use Unit #1 Bonus (Vim) Page to brush up on your Vim Skills.
Compilers
A brief look at compilers and compiling code So we did all this just to show you a quick rundown of how compiled code works on your system. We are going to be doing scripting today, which is not compiled, but rather interpreted code according to a type of interpreter so we'll just breeze through this part. You can come back and play with this at your leisure, I will provide links for more study.
Lab 🧪
Log into your Rocky server and become root.
Module 2.1: Scripting
After all that pre-lab discussion, we won't be using gcc today—or compiling any programs, for that matter. Instead, we'll focus on scripting, where we write code that the system interprets and executes step by step. Think of it like reading lines from a play, following sheet music, or executing a script—each command is processed in order.
There are plenty of resources available to learn scripting, but the key to improving is daily practice. If you're serious about getting better, I recommend studying additional concepts over time. However, to get started, you only need to understand three fundamental ideas:
- Input and Output - How to receive input and where to send the output.
- Conditionals - How to test and evaluate conditions.
- Loops - How to repeat actions efficiently.
2.2 Getting Input
Let's use examples from our Operate Running Systems lab to see what it looks like to gather system information and store it in variables. Variables in scripting can be thought of as named boxes where we put things we want to look at or compare later. We can, by and large, stuff anything we want into these boxes.
There will be output because this is one of those special variables that make up your environment variables. You can see them with:
These should not be changed, but if necessary, they can be. If you overwrite any, you can reset them by re-logging into your shell.
We can package things in variables and then reference them by their name preceded by a $.
2.3 Checking Exit Codes
One of the most important inputs in scripting is checking the exit code ($?) of a command. This allows us to determine whether a command succeeded or failed.
Checking for installed packages:
$? only holds the exit status of the last executed command, so store it immediately:
2.4 Testing and Evaluating Conditions
2.4.1 Basics of Logic and Truth Tests
I commonly say that “All engineering is the test for truth.” This is not meant as a philosophical statement but a practical one. We take input, verify it, and compare it to our expectations. If it matches, the result is true; otherwise, it is false.
Testing for what something is is much easier than testing for what something is not, as logically, there are infinite possibilities for what something could not be.
Continue exploring these concepts by practicing input handling, storing values in variables, and testing conditions to build efficient scripts.
2.5 Exercise
The Red bunny is tall. We look at our examples and see that this is not true, so the statement evaluates to false.
The Blue bunny is short. We look at our examples and see that this is not true, so the statement evaluates to false.
The Idea of AND and OR
ANDis a restricting test.ORis an inclusive test.
I will prove that here shortly.
ANDingchecks both sides for truth and evaluates to true only ifbothsides are true.ORingallows either side to be true, and the statement still evaluates to true. This makes OR a more inclusive test.
AND Examples
-
The
right bunnyisRedandTall.- This evaluates to
truefor the Red test butfalsefor the Tall test. - The statement evaluates to
false.
- This evaluates to
-
The
left bunnyisBlueandTall.- This evaluates to
truefor the Blue test andtruefor the Tall test. - The statement evaluates to
true.
- This evaluates to
OR Examples
-
The
right bunnyisRedorTall.- This evaluates to
truefor the Red test butfalsefor the Tall test. - The statement evaluates to
true.
- This evaluates to
-
The
left bunnyisRedorShort.- This evaluates to
falsefor Red andfalsefor Short. - The statement evaluates to
false.
- This evaluates to
2.6 - Truth Tables
Google Truth Tables to see engineering diagrams commonly used for testing truth in complex statements.
We will not draw them out in this lab, as there are already well-documented examples. This is a well-known, solved, and understood concept in the engineering world. Instead of reinventing those diagrams, refer to the following link for more details:
2.7 - Flow in a program
- All programs start at the top and run to the bottom. Data never flow back towards the start, unless on a separate path from a decision which always returns to the original path.
When we start thinking about how to lay something out and logically work through it, the idea of a formalized flow chart can help us get a handle on what we're seeing.
Some common symbols you'll see as we go through drawing out our logic. This example creates a loop in the program until some decision evaluates to yes (true).
2.8 - 3 Types of Decisions
There are 3 primary types of decisions you'll run into with scripting, they are:
SinglealternativeDualalternativeMultiplealternative
2.8.1 - Single Alternative if/then
Single alternatives either occur or they do not. They only branch from the primary path if the condition occurs. They either can or cannot occur, depending on the condition, but compared to alternative paths where a decision must occur if these do not evaluate to true, they are simply passed over.
Evaluate these from earlier and look at the difference.
You'll note that only one of them caused any output to come to the screen, the other simply ran and the condition never had to execute.
2.8.2 - Dual alternative (if/then/else)
Dual alternatives forces the code to split. A decision must be made. These are logically if, then, else. We test for a truth, and then, if that condition does not exist we execute the alternative. If you're a parent or if you ever had a parent, this is the dreaded or else. One of two things is going to happen here, the path splits.
2.8.3 - Multiple Alternative (if/then/elif/…/else or Case)
Multiple alternatives provide a branch for any numbers of ways that a program can go. They can be structured as if, then, else if elif in bash, else. They can also be framed in the case statement, which can select any number of cases (like doors) that can be selected from. There should always be a default else value for case statements, that is to say, if one of the many conditions don't exist there is something that happens anyways (*) in case statements.
Set those variables to the conditions of 0, 1, and anything else to see what happens.
Think about why greater than 1 does not hit the condition of 1. Might it be easier to think of as greater than or equal to 2? Here's a list of things you can test against. http://tldp.org/LDP/abs/html/tests.html
Also a huge concept we don't have a lot of time to cover is found here: File test operators http://tldp.org/LDP/abs/html/fto.html, do files exist and can you do operating system level things with them?
We didn't get to go into case, but they are pretty straight forward with the following examples: http://tldp.org/LDP/Bash-Beginners-Guide/html/sect_07_03.html
We didn't get to explore these much earlier, but to test AND and OR functionality use this.
AND condition
We can't install someprogram
OR condition
2.8.4 - Looping around
As with everything today, this is simply a primer and there are hundreds to thousands of examples online a simple google away. There are only two types of loops; counting loops and conditional loops. At the most basic level, we use counting loops when we (or the system) know how many times we want to go through something. Some examples of this are actual hard counts, lists, or lengths of files typically by line. While loops will continue until a condition exists or stops existing. The difference is until that condition occurs there's no reasonable way of knowing how many times the loop may have to occur.
for loops
Counting is iteration.
We can count numbers
We can count items
But, it's impractical to count for ourselves sometimes so we let the system do it for us.
What did each of those do? Let's put them in a loop we can use
Maybe we want to count our 1000 servers and connect to them by name.
Maybe we need to create a list of all our servers and put it in a list
Maybe someone else gave us a list of servers and we need to read from that list to connect and do work.
So, while those are even just a limited set of cases those are all times when, at the start, we know how many times we're going to go through the loop. Counting or For loops always have a set number of times they're going to run. That can change, but when it starts the end number of runs is known.
while loops
While loops are going to test conditions and loop while that condition evaluates to true. We can invert that, as we can with all logic, but I find that testing for truth is always easiest.
It is important to remember that CRTL + C will break you out of loops, as that will come handy here.
Administrators often find themselves looking at data and needing to refresh that data. One of the simplest loops is an infinite loop that always tests the condition of true (which always evaluates to true) and then goes around again. This is especially useful when watching systems for capacity issues during daemon or program startups.
This will run until you break it with CTRL + C. This will loop over the date, free -m, uptime, and sleep 2 commands until the condition evaluates to false, which it will never do.
Let's run something where we actually have a counter and see what that output is
What numbers were counted through?If you immediately run this again, what happens? Why didn't anything happen?
Re-run the above loop. Why did it work this time?
Reset the counter and run it again. Try moving the counter to before the output. Can you make it count from 1 to 100? Can you make it count from 3 to 251? Are there challenges to getting that to work properly?
What if we wanted something to happen for every MB of free RAM on our system? Could we do that?
3.0 - Scripting System Checks
The main thing we haven't covered is what to actually do with these things we've done.
We can put them into a file and then execute them sequentially until
the file is done executing. To do that we need to know the interpreter (bash is
default) and then what we want to do.
Execute this with the following command and you'll have your first completed script.
run the strace command to see what is happening with your system when it interprets this script.
That's a lot of output! Now try adding -c for a summary. Here you can see all the syscalls made by the script and the time is took for each one.
There are a lot of ways to use these tools. There are a lot of things you can do and include with scripts. This is just meant to teach you the basics and give you some confidence that you can go out there and figure out the rest. You can develop things that solve your own problems or automate your own tasks.
Info
Be sure to reboot the lab machine from the command line when you are done.