Linux Hands On Workshop
3-hour hands-on workshop · 31 October 2026
Cladius Fernando · AI-rambh
About The Speaker
Cladius Fernando
SHAPING PROFESSIONALS
Hazel AI
Persistent Systems
Persistent Systems
Certifications
Claude Certified Developer
ANTHROPIC
FOUNDATIONS
Claude Certified Associate
ANTHROPIC FOUNDATIONS
Claude Certified Architect
ANTHROPIC FOUNDATIONS
Claude Certified Architect
ANTHROPIC PROFESSIONALS
AI Practitioner
AWS
FOUNDATIONAL
Agentic AI
AWS
DEMONSTRATED
Solutions Architect
AWS
PROFESSIONAL
Data Analytics
AWS SPECIALITY
AI Business Professional
MICROSOFT
Azure Fundamentals
MICROSOFT
Terraform Associate
HASHICORP
Digital Leader
GOOGLE CLOUD
Excellence
Bridging the Gap between classroom
and cubicle
Agentic AI Demystified
Master the essentials
Books
Programme outline
01 Introduction to Linux and the terminal
02 Navigation and file management
03 File viewing and searching
04 Redirection, pipes and permissions
05 Processes, system commands and wrap-up
Linux Workshop · AI-rambh
Six jobs, twenty-odd commands
Each category: the commands, their four most useful options, when to reach for which — then two questions before we move on.
1 · ORIENTATION
pwd ls cd
Where am I, what is here, how do I move
2 · FILES & FOLDERS
mkdir touch cp mv rm
Make, copy, rename, delete — and wildcards
3 · LOOKING INSIDE
cat less head tail wc
Read a file without drowning in it
4 · SEARCHING
grep find
Text inside files, files inside folders
5 · PLUMBING
> >> | cut sort uniq
Chain small commands into answers
6 · THE SYSTEM
chmod du df ps kill
Permissions, disk, processes
Linux Workshop · AI-rambh
CATEGORY 1 OF 6 · ACT 1
Orientation
You have been dropped into a company you have never seen. Where are you, what is here, how do you move?
pwd · ls · cd
pwd
print working directory — where am I?
$ pwd
/home/user/acme-corp/infra/servers/web-03
Piece of the path | Means |
/ | the root — everything on the machine hangs off this one folder |
/home/priya | your home folder; the shortcut for it is ~ |
. | the folder you are in right now |
.. | the folder one level up |
REACH FOR IT WHEN
1 · Orientation
ls
list what is here
Option | Meaning | Example |
-l | long listing: permissions, owner, size, date | ls -l |
-a | all — include hidden files (names starting with a dot) | ls -a |
-h | human sizes (12K, 3.4M) — pair it with -l | ls -lh |
-t | newest first | ls -lt |
$ ls -la
drwxr-xr-x .secrets -rw-r--r-- README.txt drwxr-xr-x infra
REACH FOR IT WHEN
1 · Orientation
cd
change directory — move somewhere else
Form | Takes you |
cd infra/servers | down into a folder (relative to where you are) |
cd .. | up one level; cd ../.. up two |
cd or cd ~ | home, from anywhere |
cd - | back to where you just were |
$ cd inf<Tab>ser<Tab>web-<Tab><Tab>
web-01/ web-02/ web-03/ web-04/
REACH FOR IT WHEN
1 · Orientation
Which one do I reach for?
You are thinking… | Type |
“Wait, where am I?” | pwd |
“What is in this folder?” | ls |
“It says the file isn’t here, but it should be.” | ls -a |
“Which of these files is the big one?” | ls -lh |
“I need to work inside that folder.” | cd folder |
“Oops, wrong folder, go back.” | cd - or cd .. |
The habit: cd, then ls, then act. Looking before doing is what separates people who lose files from people who don’t.
1 · Orientation
KNOWLEDGE CHECK · ORIENTATION · 1 OF 2
You are in ~/acme-corp/projects/alpha/src. Which single command takes you to acme-corp?
A
cd ..
B
cd ../..
C
cd ../../..
D
cd ~
Hands up · 20 seconds
ANSWER · C
You are in ~/acme-corp/projects/alpha/src. Which single command takes you to acme-corp?
A
cd ..
B
cd ../..
C
cd ../../..
D
cd ~
Each .. climbs one level: src → alpha → projects → acme-corp is three climbs. cd ~ would overshoot to your home folder.
1 · Orientation
KNOWLEDGE CHECK · ORIENTATION · 2 OF 2
ls shows an empty folder, but your teammate swears a config file is in there. What do you run?
A
ls -l
B
ls -a
C
pwd
D
cd ..
Hands up · 20 seconds
ANSWER · B
ls shows an empty folder, but your teammate swears a config file is in there. What do you run?
A
ls -l
B
ls -a
C
pwd
D
cd ..
Files whose names start with a dot are hidden from a plain ls. -a shows all of them. -l adds detail but still skips dotfiles.
1 · Orientation
CATEGORY 2 OF 6 · ACT 2
Files & folders
Investigators never work on the originals. Build an evidence folder, copy what matters, rename the mess, delete the junk — and only the junk.
mkdir · touch · cp · mv · rm · *
mkdir
make a directory (folder)
Option | Meaning | Example |
(none) | make one folder here | mkdir evidence |
-p | parents — make the whole path, no error if it exists | mkdir -p a/b/c |
-v | verbose — say what was created | mkdir -v logs |
$ mkdir -pv evidence/logs
mkdir: created directory 'evidence'
mkdir: created directory 'evidence/logs'
REACH FOR IT WHEN
2 · Files & folders
touch
make an empty file, or bump a file’s timestamp
Form | Meaning | Example |
touch f | file doesn’t exist → create it empty | touch notes.txt |
touch f | file exists → update its “last modified” time, contents untouched | touch index.html |
touch a b c | several at once | touch a.txt b.txt |
$ touch report.txt && ls -l report.txt
-rw-r--r-- 1 priya 0 Oct 31 10:42 report.txt
REACH FOR IT WHEN
2 · Files & folders
cp
copy — SOURCE first, DESTINATION last
Option | Meaning | Example |
(none) | copy a file; destination can be a folder or a new name | cp a.log evidence/ |
-r | recursive — needed to copy a folder and everything in it | cp -r logs backup/ |
-i | interactive — ask before overwriting | cp -i a.log b.log |
-v | verbose — print each copy as it happens | cp -v *.log evidence/ |
$ cp -v infra/.../access.log evidence/
'infra/.../access.log' -> 'evidence/access.log'
REACH FOR IT WHEN
2 · Files & folders
mv
move — which is also how you rename
Option | Meaning | Example |
(none) | destination is a folder → move into it | mv a.log evidence/ |
(none) | destination is a name → rename | mv draft.txt final.txt |
-i | interactive — ask before overwriting an existing file | mv -i a.txt b.txt |
-v | verbose — show each move | mv -v *.tmp trash/ |
$ mv "Q3 Report final (2).docx" q3-report.docx
(no output = it worked; ls to confirm)
REACH FOR IT WHEN
2 · Files & folders
rm
remove — there is no recycle bin
Option | Meaning | Example |
(none) | delete a file, for ever | rm cache.tmp |
-i | interactive — ask for each file | rm -i *.tmp |
-r | recursive — delete a folder and all its contents | rm -r build/ |
-f | force — no questions, no errors. Dangerous with -r. | rm -rf build/ |
$ ls *.tmp # look first
$ rm *.tmp # then delete exactly what you saw
REACH FOR IT WHEN
2 · Files & folders
* ? " "
wildcards and quotes — the shell expands names before the command runs
Pattern | Matches | Example |
*.tmp | anything ending in .tmp | rm *.tmp |
cache_* | anything starting with cache_ | ls cache_* |
? | exactly one character | ls web-0? |
"Q3 Report (2).docx" | quotes: spaces and brackets stay one name | mv "Q3 (2).docx" q3.docx |
$ rm *.tmp → rm cache_0001.tmp cache_0002.tmp …
$ rm * .tmp → rm EVERYTHING, then “.tmp not found”
REACH FOR IT WHEN
2 · Files & folders
Which one do I reach for?
You are thinking… | Type |
“I need somewhere to put this.” | mkdir name |
“Keep the original, give me a copy to mess with.” | cp from to |
“Copy this whole folder.” | cp -r from to |
“Terrible file name, fix it.” | mv old new |
“This belongs in that folder.” | mv file folder/ |
“Get rid of all the junk ending in .tmp.” | ls *.tmp then rm *.tmp |
cp and mv take the same shape: FROM then TO. rm takes only victims.
2 · Files & folders
KNOWLEDGE CHECK · FILES & FOLDERS · 1 OF 2
Rename draft.txt to final.txt. Which command?
A
cp draft.txt final.txt
B
rename draft.txt final.txt
C
mv draft.txt final.txt
D
touch final.txt
Hands up · 20 seconds
ANSWER · C
Rename draft.txt to final.txt. Which command?
A
cp draft.txt final.txt
B
rename draft.txt final.txt
C
mv draft.txt final.txt
D
touch final.txt
A rename is a move to a new name. cp would leave you with two files; rename exists on some systems but isn’t the standard tool; touch just makes an empty file.
2 · Files & folders
KNOWLEDGE CHECK · FILES & FOLDERS · 2 OF 2
You meant to type rm *.tmp but your finger slipped: rm * .tmp. What happens?
A
Same thing — the shell ignores the space
B
An error, nothing is deleted
C
Every file in the folder is deleted, then “.tmp: no such file”
D
Only a file literally named .tmp is deleted
Hands up · 20 seconds
ANSWER · C
You meant to type rm *.tmp but your finger slipped: rm * .tmp. What happens?
A
Same thing — the shell ignores the space
B
An error, nothing is deleted
C
Every file in the folder is deleted, then “.tmp: no such file”
D
Only a file literally named .tmp is deleted
The space makes two arguments. * alone expands to every visible file, which rm dutifully removes; the error about .tmp arrives after the damage. This is why you ls the pattern first.
2 · Files & folders
CATEGORY 3 OF 6 · ACT 2
Looking inside
The log has 10,000 lines. Reading all of it is not an option. Four ways to look at exactly the part you need.
cat · less · head · tail · wc
cat
print the whole file to the screen
Option | Meaning | Example |
(none) | dump the file, top to bottom, no paging | cat README.txt |
-n | number every line | cat -n main.py |
a b | several files → joined one after another (that’s the “concatenate” in the name) | cat a.log b.log |
$ cat .secrets/vault.key
vault access key:
KEY-2763-ZULU
REACH FOR IT WHEN
3 · Looking inside
less
scroll through a big file, one screen at a time
Key (inside less) | Does |
Space / b | next screen / previous screen (arrows work too) |
/word then n | search forward for word; n = next match |
G / g | jump to the end / back to the top |
q | quit. The one key everyone forgets. |
$ less evidence/access.log
… press G to see last night, /DELETE to hunt, q to leave
REACH FOR IT WHEN
3 · Looking inside
head · tail
the first lines · the last lines
Form | Meaning | Example |
head f | first 10 lines | head employees.csv |
head -n 3 f | first N lines (-n 1 = just the header) | head -n 1 employees.csv |
tail -n 500 f | last N lines — newest entries in any log | tail -n 500 access.log |
tail -f f | follow: keep printing as the file grows (Ctrl+C to stop) | tail -f app.log |
$ tail -n 1 evidence/access.log
10.0.46.116 - - [30/Oct/2026:23:59:16 +0530] "GET /health HTTP/1.1" 200 …
REACH FOR IT WHEN
3 · Looking inside
wc
word count — but mostly line count
Option | Meaning | Example |
-l | lines — the one you’ll use 95% of the time | wc -l access.log |
-w | words | wc -w essay.txt |
-c | bytes (size) | wc -c core.dump |
(none) | all three: lines, words, bytes | wc README.txt |
$ wc -l evidence/lastnight.log
500 evidence/lastnight.log
REACH FOR IT WHEN
3 · Looking inside
Which one do I reach for?
You are thinking… | Type |
“Small file, just show me.” | cat file |
“Big file, let me browse and search it.” | less file |
“What are the columns / what does this look like?” | head file |
“What happened last?” | tail file |
“Show me the last 500 entries.” | tail -n 500 file |
“How many lines is that?” | wc -l file |
Rule of thumb: cat for things you can read in one screen, less for things you want to read, head/tail for things you want to sample.
3 · Looking inside
KNOWLEDGE CHECK · LOOKING INSIDE · 1 OF 2
A server log has 10,000 lines. You want to see the 20 most recent entries. Which command?
A
cat app.log
B
head -n 20 app.log
C
tail -n 20 app.log
D
wc -l app.log
Hands up · 20 seconds
ANSWER · C
A server log has 10,000 lines. You want to see the 20 most recent entries. Which command?
A
cat app.log
B
head -n 20 app.log
C
tail -n 20 app.log
D
wc -l app.log
Logs are appended at the bottom, so the newest entries are the tail. head gives the oldest 20; cat scrolls all 10,000 past you; wc -l only counts them.
3 · Looking inside
KNOWLEDGE CHECK · LOOKING INSIDE · 2 OF 2
You opened a file with less and now the terminal won’t take your commands. Which key gets you out?
A
Esc
B
Ctrl+Z
C
q
D
Close the window and open a new one
Hands up · 20 seconds
ANSWER · C
You opened a file with less and now the terminal won’t take your commands. Which key gets you out?
A
Esc
B
Ctrl+Z
C
q
D
Close the window and open a new one
q quits less (and man, and git log). Ctrl+Z only hides it in the background. For a running command that won’t stop, the key is Ctrl+C — different situation, different key.
3 · Looking inside
CATEGORY 4 OF 6 · ACT 3
Searching
Two questions, two tools. “Which lines say DELETE?” is grep. “Where is the file that maps IPs to people?” is find — or grep -r when you know a word inside it.
grep · find
grep
print the lines that contain a word
Option | Meaning | Example |
-i | ignore case — Error, ERROR, error all match | grep -i error app.log |
-c | count matching lines instead of printing them | grep -c DELETE a.log |
-n | show line numbers | grep -n TODO main.py |
-r | recursive — search every file under a folder | grep -r 10.0.42.33 infra/ |
$ grep -r 10.0.42.33 infra/
infra/vpn/assignments.txt:10.0.42.33 simran.mehta finance
REACH FOR IT WHEN
4 · Searching
find
list files under a folder that match a rule
Option | Meaning | Example |
-name "x" | by name; quote the pattern so the shell leaves * alone | find . -name "*.log" |
-iname "x" | same, ignoring case | find . -iname "readme*" |
-type f / d | only files / only folders | find . -type d |
-size +1M | bigger than 1 MB (+) or smaller (-) | find . -size +1M |
$ find . -name "*.docx"
./finance/q2-report.docx
./finance/q3-report-final.docx
REACH FOR IT WHEN
4 · Searching
Which one do I reach for?
You are thinking… | Type |
“Which lines in this file say DELETE?” | grep DELETE file |
“How many lines say it?” | grep -c DELETE file |
“Some file somewhere mentions this IP. Which?” | grep -r 10.0.42.33 . |
“Where are all the .log files?” | find . -name "*.log" |
“What’s bigger than 1 MB around here?” | find . -size +1M |
“Lines with DELETE and 200?” | grep DELETE file | grep " 200 " |
grep looks inside files. find looks for files. If you can picture the text, grep; if you can picture the name, find.
4 · Searching
KNOWLEDGE CHECK · SEARCHING · 1 OF 2
How many lines in app.log contain the word ERROR? One command, one number.
A
grep -n ERROR app.log
B
grep -c ERROR app.log
C
wc -l ERROR app.log
D
find app.log -name ERROR
Hands up · 20 seconds
ANSWER · B
How many lines in app.log contain the word ERROR? One command, one number.
A
grep -n ERROR app.log
B
grep -c ERROR app.log
C
wc -l ERROR app.log
D
find app.log -name ERROR
-c counts matching lines. -n prints them with line numbers (you’d still have to count). wc doesn’t filter — it would try to open a file called ERROR. find matches file names, not contents.
4 · Searching
KNOWLEDGE CHECK · SEARCHING · 2 OF 2
Somewhere under the current folder — you don’t know where — is a file whose name ends in .conf. List every such file.
A
ls *.conf
B
grep -r .conf .
C
find . -name "*.conf"
D
cat */*.conf
Hands up · 20 seconds
ANSWER · C
Somewhere under the current folder — you don’t know where — is a file whose name ends in .conf. List every such file.
A
ls *.conf
B
grep -r .conf .
C
find . -name "*.conf"
D
cat */*.conf
A file name anywhere below here is a find job. ls only sees this folder; grep -r searches inside files for the text “.conf”; cat prints contents. The quotes stop the shell from expanding * before find sees it.
4 · Searching
CATEGORY 5 OF 6 · ACT 3 · THE HEART OF IT
Plumbing
No single command finds the culprit. Six small ones, each doing one thing, connected with a pipe — that does. This is the idea Linux is built on.
> >> | cut sort uniq
> >>
redirection — send output into a file instead of the screen
Symbol | Meaning | Example |
cmd > file | write output to file, replacing whatever was there | tail -n 500 a.log > night.log |
cmd >> file | append output to the end of file | echo "IP: 10.0.42.33" >> report.txt |
echo text | print text — with > it’s how you create a file with content | echo "hello" > hi.txt |
cmd 2> file | send error messages to a file (or 2>/dev/null to bin them) | find / -name x 2>/dev/null |
$ echo "User: simran.mehta" >> evidence/report.txt
$ cat evidence/report.txt # two lines now, not one
REACH FOR IT WHEN
5 · Plumbing
|
the pipe — output of the left becomes input of the right
grep DELETE log
keep the lines I care about
cut -d' ' -f1
keep only the IP column
sort | uniq -c
count each IP
Shape | Reads as |
a | b | run a, feed everything it prints into b |
a | b | c | d | an assembly line; each stage does one small job |
a | b > file | pipe through, then save the final result |
$ grep failed error.log | wc -l
40
REACH FOR IT WHEN
5 · Plumbing
cut
keep one column from every line
Option | Meaning | Example |
-d ' ' | delimiter — what separates the columns (space here) | cut -d ' ' -f1 a.log |
-d ',' | comma for CSV files | cut -d ',' -f4 employees.csv |
-f1 | field number — which column to keep (counting from 1) | cut -d ',' -f2 |
-f1,3 / -f2-4 | several columns, or a range | cut -d ',' -f2-3 |
$ head -n 3 hr/employees.csv | cut -d ',' -f2
username
aarav.sharma
neha.gupta
REACH FOR IT WHEN
5 · Plumbing
sort · uniq
put lines in order · collapse repeats and count them
Option | Meaning | Example |
sort | alphabetical; puts identical lines next to each other | sort names.txt |
sort -n | numeric — 9 before 10 (plain sort puts 10 first) | … | sort -n |
sort -r | reverse — biggest first | … | sort -nr | head |
uniq -c | collapse adjacent duplicates, prefix each with its count | sort | uniq -c |
$ cut -d ',' -f4 hr/employees.csv | sort | uniq -c | sort -n
3 legal
5 hr
9 engineering
REACH FOR IT WHEN
5 · Plumbing
tr
translate: swap, change case or delete characters
Option | Meaning | Example |
tr '#' '$' | swap one character for another, position by position | banner X | tr '#' '$' |
tr 'a-z' 'A-Z' | ranges work too: lower case becomes upper case | echo hi | tr 'a-z' 'A-Z' |
tr -d 'x' | delete every x from the stream | echo a1b2 | tr -d '0-9' |
tr -s ' ' | squeeze a repeated character into one | ls -l | tr -s ' ' |
$ echo 'case closed' | tr 'a-z' 'A-Z'
CASE CLOSED
REACH FOR IT WHEN
5 · Plumbing
THE ONE-LINER FROM THE FIRST FIVE MINUTES
“Which IP sent the most DELETE requests last night?”
grep DELETE lastnight.log
15 lines out of 500 — only the DELETEs
| cut -d ' ' -f1
15 IP addresses, nothing else
| sort
identical IPs now sit next to each other
| uniq -c
3 lines: a count beside each IP
| sort -n
smallest count first, biggest last
| tail -n 1
12 10.0.42.33 — the culprit
5 · Plumbing · build it one stage at a time, run after every |
Which one do I reach for?
You are thinking… | Type |
“Save this output as a file.” | cmd > file |
“Add this line to the end of my report.” | echo "…" >> file |
“Feed this into the next command.” | cmd1 | cmd2 |
“Just the IP column.” | cut -d ' ' -f1 |
“Which value shows up the most?” | sort | uniq -c | sort -n | tail -n 1 |
“How many?” | | wc -l |
> and >> go to a file. | goes to another command. Nothing else to memorise.
5 · Plumbing
KNOWLEDGE CHECK · PLUMBING · 1 OF 2
You run tail -n 5 a.log > b.txt and then, a minute later, run exactly the same command again. How many lines does b.txt have?
A
10
B
5
C
0 — the second run fails because b.txt exists
D
It asks you whether to overwrite
Hands up · 20 seconds
ANSWER · B
You run tail -n 5 a.log > b.txt and then, a minute later, run exactly the same command again. How many lines does b.txt have?
A
10
B
5
C
0 — the second run fails because b.txt exists
D
It asks you whether to overwrite
A single > replaces the file every time, silently, no questions. You’d get 10 lines only with >>. This is also how people wipe a report they spent ten minutes building.
5 · Plumbing
KNOWLEDGE CHECK · PLUMBING · 2 OF 2
In grep DELETE log | cut -d ' ' -f1 | sort | uniq -c, why is sort there before uniq?
A
uniq only merges lines that are next to each other, so identical IPs must be grouped first
B
It makes the pipeline run faster
C
uniq refuses to run on unsorted input
D
No reason — it works the same without it
Hands up · 20 seconds
ANSWER · A
In grep DELETE log | cut -d ' ' -f1 | sort | uniq -c, why is sort there before uniq?
A
uniq only merges lines that are next to each other, so identical IPs must be grouped first
B
It makes the pipeline run faster
C
uniq refuses to run on unsorted input
D
No reason — it works the same without it
uniq happily runs on unsorted input — it just gives you wrong counts, because it only compares each line with the one before it. sort puts the duplicates side by side so they collapse into one counted line.
5 · Plumbing
INTERLUDE · WHY IT WORKS
The Unix philosophy
Why do a handful of tiny commands add up to a detective? Because the people who built Unix agreed on a few design rules, and you have been following them all session.
do one thing well · work together · use plain text
A story: the missing option
1
banner prints big text made of # characters
2
A colleague wants $ instead of # and asks why the tool has no option for it
3
The tempting fix: add one more command-line option to banner
THE DESIGN QUESTION
Should banner learn to draw with any character you like?
Or should a different tool change one character into another?
A real exchange between me and my colleague about the Unix command banner.
The Unix answer: pipe it to another tool
banner X
draws big letters with #
tr '#' '$'
swaps one character for another
big X made of $
same shape, new character
$ banner X | tr '#' '$'
banner draws. tr swaps. Together they give a feature neither has alone.
Adding the option would have made banner bigger and harder to maintain. A separate, tiny tool that only changes characters works after any command that prints text.
Three rules behind the pipe
The rule (Doug McIlroy) | Where you used it today |
Write programs that do one thing and do it well | wc counts, cut cuts, sort sorts. Nothing else. |
Write programs to work together | grep | cut | sort | uniq -c caught the culprit. |
Write programs to handle text streams, because that is a universal interface | Logs, CSV files and your report were all plain text that any command could read. |
“The power of a system comes more from the relationships among programs than from the programs themselves.” Kernighan and Pike, The UNIX Programming Environment (1984)
Interlude · Unix philosophy
Try it yourself: tr in Git Bash
$ echo "### EVIDENCE ###" | tr '#' '$'
$$$ EVIDENCE $$$
$ echo "case closed" | tr 'a-z' 'A-Z'
CASE CLOSED
$ echo "### EVIDENCE ###" | tr '#' '$' | tr 'A-Z' 'a-z'
$$$ evidence $$$
banner is not installed in Git Bash, so echo plays the first stage. Your turn: turn your own name into capitals, then swap every a for @.
Why this is good design
1
Every command does one main thing and does it well
2
Instead of adding flexibility to a tool, chain it with another tool
3
Good design can be taught: the rules just have to be written down
WHERE THE RULE COMES FROM
The Unix philosophy, started by Ken Thompson and written down by Doug McIlroy in the Bell System Technical Journal in 1978.
Many engineers learn these rules the hard way, from peers, seniors and their own mistakes. You are getting them up front.
Eric Raymond’s 17 Unix rules
1
Build modular programs
2
Write readable programs
3
Use composition
4
Separate mechanisms from policy
5
Write simple programs
6
Write small programs
7
Write transparent programs
8
Write robust programs
9
Make data complicated when required, not the program
10
Build on potential users’ expected knowledge
11
Avoid unnecessary output
12
Write programs which fail in a way that is easy to diagnose
13
Value developer time over machine time
14
Write abstract programs that generate code instead of writing code by hand
15
Prototype software before polishing it
16
Write flexible and open programs
17
Make the program and protocols extensible
KNOWLEDGE CHECK · UNIX PHILOSOPHY · 1 OF 2
mv draft.txt final.txt prints nothing when it works. Which Unix rule is that?
A
Write transparent programs
B
Avoid unnecessary output
C
Prototype software before polishing it
D
Separate mechanisms from policy
Hands up · 20 seconds
ANSWER · B
mv draft.txt final.txt prints nothing when it works. Which Unix rule is that?
A
Write transparent programs
B
Avoid unnecessary output
C
Prototype software before polishing it
D
Separate mechanisms from policy
Silence is a feature. Output nobody asked for clutters the screen and becomes junk input for the next command in a pipe. When mv says nothing it worked; when it fails, it says so.
Interlude · Unix philosophy
KNOWLEDGE CHECK · UNIX PHILOSOPHY · 2 OF 2
wc only counts lines, words and bytes. Why do Unix tools stay this small?
A
Small programs run faster on old hardware
B
Small single-purpose tools can be chained with pipes into answers no single tool gives
C
Linux cannot run large programs
D
It saves disk space on lab computers
Hands up · 20 seconds
ANSWER · B
wc only counts lines, words and bytes. Why do Unix tools stay this small?
A
Small programs run faster on old hardware
B
Small single-purpose tools can be chained with pipes into answers no single tool gives
C
Linux cannot run large programs
D
It saves disk space on lab computers
Because wc only counts, it can count anything you pipe into it: grep … | wc -l, ls | wc -l. Tools that do one thing well are the ones you can combine.
Interlude · Unix philosophy
CATEGORY 6 OF 6 · ACT 4
The system
You know who did it. Now protect the evidence, find what’s eating the disk, and kill the process that shouldn’t be running.
ls -l · chmod · du · df · ps · kill
ls -l
reading the permission string
$ ls -l evidence/
-rw-r--r-- 1 priya staff 52140 Oct 31 11:02 lastnight.log
Piece | Means |
- | type: - file, d directory |
rw- | owner (priya) can read and write, not execute |
r-- | group (staff) can only read |
r-- | everyone else can only read |
r = 4, w = 2, x = 1. Add them per group: rw- = 6, r-- = 4, so this file is 644. All-read-only is 444.
REACH FOR IT WHEN
6 · The system
chmod
change mode — set who may read, write, run
Form | Meaning | Example |
444 | read-only for everyone — lock evidence | chmod 444 lastnight.log |
644 | owner reads and writes, others read — the normal file | chmod 644 notes.txt |
+x | add execute — turn a script into a program you can ./run | chmod +x hunt.sh |
-R | recursive — apply to a folder and everything inside | chmod -R 755 site/ |
$ chmod 444 evidence/lastnight.log && ls -l evidence/
-r--r--r-- 1 priya staff 52140 lastnight.log
REACH FOR IT WHEN
6 · The system
du · df
disk used by this · disk free overall
Form | Meaning | Example |
du -sh dir | summary, human-readable: one total for the folder | du -sh projects/ |
du -sh dir/* | one total per thing inside — find the hog | du -sh projects/* |
du -sh * | sort -h | …ranked, biggest last | du -sh * | sort -h |
df -h | free space on every drive | df -h |
$ du -sh projects/*
8.0K projects/alpha
4.0K projects/beta
7.9M projects/legacy
8.0K projects/website
REACH FOR IT WHEN
6 · The system
ps · kill
what is running · make it stop
Form | Meaning | Example |
ps | your processes, with their PIDs (process IDs) | ps |
ps -ef | every process on the machine (ps aux on some systems) | ps -ef | grep nginx |
kill PID | ask the process to stop politely | kill 4242 |
kill -9 PID | stop it now, no chance to clean up — last resort | kill -9 4242 |
$ cat infra/run/xmr-miner.pid && kill $(cat infra/run/xmr-miner.pid)
4242 ← then ps: it’s gone, the other two are not
REACH FOR IT WHEN
6 · The system
Which one do I reach for?
You are thinking… | Type |
“Who can read or change this file?” | ls -l file |
“Nobody touches this evidence.” | chmod 444 file |
“Let me run this script.” | chmod +x script.sh |
“Which folder is eating the disk?” | du -sh * | sort -h |
“How much space is left at all?” | df -h |
“What’s running, and how do I stop that one?” | ps then kill PID |
Permissions: read the string, then change the number. Disk: df for the drive, du for the folder. Processes: ps for the PID, kill for the PID.
6 · The system
KNOWLEDGE CHECK · THE SYSTEM · 1 OF 2
-rw-r--r-- Can “everyone else” — people who aren’t the owner and aren’t in the group — edit this file?
A
Yes — read and write
B
No — they can only read it
C
No — they have no access at all
D
Only if they run it with -x
Hands up · 20 seconds
ANSWER · B
-rw-r--r-- Can “everyone else” — people who aren’t the owner and aren’t in the group — edit this file?
A
Yes — read and write
B
No — they can only read it
C
No — they have no access at all
D
Only if they run it with -x
Read the string in threes after the first dash: rw- owner, r-- group, r-- others. The last three have an r and nothing else: read only. In numbers, this file is 644.
6 · The system
KNOWLEDGE CHECK · THE SYSTEM · 2 OF 2
Three services are running. You know the crypto-miner is PID 4242. Stop it — and only it.
A
rm 4242
B
kill 4242
C
exit 4242
D
Close the terminal — that stops everything
Hands up · 20 seconds
ANSWER · B
Three services are running. You know the crypto-miner is PID 4242. Stop it — and only it.
A
rm 4242
B
kill 4242
C
exit 4242
D
Close the terminal — that stops everything
kill takes a PID and sends that one process a stop request. rm deletes files, not processes; exit closes your own shell; closing the terminal is a blunt instrument that takes the innocent services with it.
6 · The system
THREE HOURS AGO THIS WAS NOISE
tail -n 500 access.log | grep DELETE | cut -d ' ' -f1 | sort | uniq -c | sort -n | tail -n 1
Seven commands you now own, one pipe, one culprit. Put it in a file, chmod +x it, and you’ve written your first shell script.
Cheat sheet in your hands · practice assignment in the repo · ./submit when you’re done
cladiusfernando.com
INTERLUDE · FROM COMMANDS TO SCRIPTS
Shell scripting
You typed the pipeline once. A script lets you run it forever.
one file · many commands · run it again
What is a shell script?
1
A text file of commands
The same commands you type at the prompt, one per line, saved in a file.
2
A first line that names the shell
#!/usr/bin/env bash tells the system which program should read the file.
3
A permission to run
chmod +x makes it executable, so ./hunt.sh works like any other command.
THE IDEA
Anything you can type, you can save.
Anything you can save, you can repeat.
THE FIRST LINE OF EVERY SCRIPT
This is the shebang
#!
hash + bang = sha-bang = shebang
#!/usr/bin/env bash
#!
the two magic characters: the system reads them first and knows this is a script
/usr/bin/env
finds the program by name wherever it is installed
bash
the interpreter that should read the rest of the file
Your first script: hunt.sh
#!/usr/bin/env bash
# hunt.sh - who sent the most DELETEs last night?
grep DELETE evidence/lastnight.log \
| cut -d' ' -f1 | sort | uniq -c \
| sort -n | tail -n 1
$ chmod +x hunt.sh
$ ./hunt.sh
12 10.0.42.33
THREE STEPS
Running a script
Three things to know before you press Enter
Form | Meaning | Example |
bash hunt.sh | run it with bash; needs no permission bit | bash hunt.sh |
./hunt.sh | run the file itself; needs chmod +x and a shebang | ./hunt.sh |
#!/usr/bin/env bash | line 1: which program should read this file | setup.sh, line 1 |
# text | comment: the shell ignores the rest of the line | # World generator |
$ ./hunt.sh
bash: ./hunt.sh: Permission denied
$ chmod +x hunt.sh && ./hunt.sh
12 10.0.42.33
REACH FOR IT WHEN
Variables and substitution
Form | Meaning | From setup.sh |
NAME=priya07 | set a variable; no spaces around the = | NAME="${1:-}" |
"$NAME" | use it; double quotes keep spaces safe | "$BASE/acme-corp" |
$(cmd) | run cmd and insert its output here | web-0$(rnd 1 4) |
$(( 1 + 2 )) | arithmetic | $(( RANDOM % 10 )) |
BASE="${WORKSHOP_HOME:-$HOME}"
ROOT="$BASE/acme-corp"
echo "Building ACME Corp in $ROOT ..."
Building ACME Corp in /home/priya/acme-corp ...
REACH FOR IT WHEN
Arguments and input
Form | Meaning | Example |
$1 $2 | first and second argument given to the script | bash setup.sh priya07 |
"$@" | all arguments, each kept as one word | cp "$@" backup/ |
${1:-x} | $1, or x when it is missing | ${1:-.} |
read -r v | ask the user and store the answer in v | read -r NAME |
NAME="${1:-}"
while [ -z "$NAME" ]; do
printf 'Your ID, e.g. priya07: '
read -r NAME
done
NAME="$(printf '%s' "$NAME" | tr -cd 'a-z0-9')"
REACH FOR IT WHEN
Decisions: if, test and case
if [ -d "$ROOT" ]; then
printf '%s exists. Wipe it? [y/N] ' "$ROOT"
read -r yn
case "$yn" in
y|Y) rm -rf "$ROOT" ;;
*) echo "Keeping it."; exit 0 ;;
esac
fi
Test | True when |
-d x | x is a folder |
-f x | x is a file |
-w x | x is writable |
-z s | s is empty |
-n s | s is not empty |
Spaces inside [ ] are required: [ -d "$ROOT" ]. case matches patterns; * is the catch-all. Default answer here is no.
Loops: for and while
Where your 300 .tmp files came from
# a known list
for s in web-01 web-02 web-03 web-04; do
mkdir -p "infra/servers/$s/var/log"
done
# a counted range
for i in $(seq 1 300); do
printf 'cache %d\n' "$i" > "tmp/cache_$i.tmp"
done
# until something changes
while [ -z "$NAME" ]; do read -r NAME; done
REACH FOR IT WHEN
Interlude · Shell scripting · Source: cladius/linux-workshop-student-edition
Functions: give a pipeline a name
# random number between $1 and $2
rnd() { printf '%d' $(( RANDOM % ($2 - $1 + 1) + $1 )); }
# lower-case $1, then fingerprint it
h() {
printf '%s' "$1" | tr '[:upper:]' '[:lower:]' \
| md5sum | cut -d' ' -f1
}
$ rnd 10 99
47
HOW IT WORKS
Exit codes: success is 0
Form | Meaning | Example |
$? | exit code of the last command: 0 = success | echo $? |
a && b | run b only if a succeeded | mkdir x && cd x |
a || b | run b only if a failed | cd "$ROOT" || exit 1 |
exit 1 | stop the script and report failure | exit 1 |
[ -f .state/meta ] || { echo "run setup.sh"; exit 1; }
if verify "$n" "$ans"; then
markdone "$n"; echo "Task $n done"
else
fail "$n"; echo "Not yet"
fi
REACH FOR IT WHEN
Background jobs: & and kill
for svc in backup-agent health-monitor xmr-miner; do
nohup bash "infra/services/$svc.sh" >/dev/null 2>&1 &
echo $! > "infra/run/$svc.pid"
done
# each service is just a loop that never ends
while :; do sleep 2; done
Piece | Meaning |
& | run in the background; the prompt comes back at once |
$! | the PID of the job you just started |
nohup | keep running even if the terminal closes |
>/dev/null 2>&1 | throw away both normal output and errors |
WHY PID FILES
Habits that keep scripts safe
Quote your variables
risky rm -rf $ROOT/*
safer rm -rf "$ROOT"/*
An empty or spaced value splits into the wrong words.
Stop if cd fails
risky cd "$ROOT"; rm -f *
safer cd "$ROOT" || exit 1
Otherwise the rest runs in the wrong folder.
Look before you delete
risky rm *.tmp
safer ls *.tmp then rm *.tmp
setup.sh even asks before wiping your world.
Fail on unset variables
risky echo "$TYPO" (silently empty)
safer set -u (stops with an error)
Put it near the top of a script.
KNOWLEDGE CHECK · SHELL SCRIPTING · 1 OF 2
You save hunt.sh and run ./hunt.sh. The shell answers: Permission denied. What fixes it?
A
sudo ./hunt.sh
B
chmod +x hunt.sh
C
cd .. and try again
D
mv hunt.sh hunt
Hands up · 20 seconds
Interlude · Shell scripting
ANSWER · B
You save hunt.sh and run ./hunt.sh. The shell answers: Permission denied. What fixes it?
A
sudo ./hunt.sh
B
chmod +x hunt.sh
C
cd .. and try again
D
mv hunt.sh hunt
The file is not marked executable. chmod +x sets the permission bit. bash hunt.sh would also work without it. sudo only changes who runs it, not whether the file may run.
Interlude · Shell scripting
KNOWLEDGE CHECK · SHELL SCRIPTING · 2 OF 2
Why does setup.sh put || exit 1 after its cd into the new folder?
A
It makes the script run faster
B
A failed cd stops the script instead of running the rest in the wrong folder
C
It creates the folder when it is missing
D
It is only a comment
Hands up · 20 seconds
Interlude · Shell scripting
ANSWER · B
Why does setup.sh put || exit 1 after its cd into the new folder?
A
It makes the script run faster
B
A failed cd stops the script instead of running the rest in the wrong folder
C
It creates the folder when it is missing
D
It is only a comment
|| runs its right side only when the left side failed. Without it, a failed cd would leave the script in whatever folder it started in, and the mkdir and cp commands after it would run there.
Interlude · Shell scripting
We'd Love Your Feedback
Help us improve future sessions by sharing your experience.
Scan to open the 2-minute feedback form
Thank You
Cladius Fernando · AI-rambh