1 of 99

Linux Hands On Workshop

3-hour hands-on workshop · 31 October 2026

Cladius Fernando · AI-rambh

2 of 99

About The Speaker

Cladius Fernando

SHAPING PROFESSIONALS

  • Field CTO

Hazel AI

​

  • Ex- Global AI Academy Head

Persistent Systems

​

  • Ex- Principal AI Architect (R&D)

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

3 of 99

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

4 of 99

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

5 of 99

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

6 of 99

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

  • You have been cd-ing for five minutes and are lost
  • A command says “no such file” — check where you actually are
  • You need the full path to paste somewhere

1 · Orientation

7 of 99

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

  • You just cd-ed somewhere — always look first
  • Something “isn’t there”: try -a before you panic
  • You want to know which file is big or recent: -lh, -lt
  • Before any rm with a wildcard: ls the pattern first

1 · Orientation

8 of 99

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

  • You will run several commands in the same folder — go there instead of typing long paths
  • Tab after every few letters; never type a full folder name
  • Lost? cd ~ then start again

1 · Orientation

9 of 99

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

10 of 99

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

11 of 99

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

12 of 99

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

13 of 99

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

14 of 99

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 · *

15 of 99

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

  • Before you cp or mv anything — give it a home first
  • -p whenever the path has more than one new level
  • Scripts: -p never fails because the folder already exists

2 · Files & folders

16 of 99

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

  • You need a placeholder file to exist right now
  • A build tool decides what to rebuild by timestamps
  • Honestly: not often. echo “text” > file makes a file with content

2 · Files & folders

17 of 99

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

  • You want to keep the original safe and work on a copy
  • The destination is a folder → end it with / so a typo can’t silently rename
  • Copying a folder? You forgot -r. Everyone does, once.

2 · Files & folders

18 of 99

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

  • Renaming anything — there is no “rename” command you need
  • Tidying: moving files into the folder they belong in
  • Names with spaces or brackets: wrap in “quotes”, or let Tab do it

2 · Files & folders

19 of 99

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

  • You have run ls with the same pattern and liked what you saw
  • Junk, caches, build output — never originals of anything
  • Unsure? mv it to a trash folder instead. You can rm that tomorrow.

2 · Files & folders

20 of 99

* ? " "

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

  • Many files share a pattern — never type 300 names
  • Always ls the pattern before rm, mv or cp it
  • A name has a space? Quote it, or type the first letters and press Tab — Tab quotes for you

2 · Files & folders

21 of 99

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

22 of 99

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

23 of 99

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

24 of 99

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

25 of 99

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

26 of 99

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

27 of 99

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

  • The file is short: a config, a key, a note, a CSV header
  • You want the whole thing in your scrollback to copy from
  • Not for logs. If it scrolls for more than a second, you wanted less or tail

3 · Looking inside

28 of 99

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

  • You want to read a long file, not process it
  • You don’t know what you’re looking for yet — browse, search, browse
  • It’s what man pages and git log open in, so learn q now

3 · Looking inside

29 of 99

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

  • head: what shape is this file? Column names? Format?
  • tail: what happened most recently? Logs grow at the bottom.
  • tail -f: watching a server while you poke it

3 · Looking inside

30 of 99

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

  • “How big is this, really?” before you cat it
  • Checking your own work: did tail -n 500 give me 500?
  • At the end of a pipe: how many matches? (grep -c is the shortcut)

3 · Looking inside

31 of 99

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

32 of 99

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

33 of 99

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

34 of 99

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

35 of 99

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

36 of 99

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

37 of 99

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

  • “Which lines mention X?” — logs, code, CSVs, anything text
  • You know a word but not which file it’s in: grep -r word .
  • Stacking: grep A file | grep B narrows to lines with both
  • Counting things: -c beats piping into wc -l

4 · Searching

38 of 99

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

  • “Where is that file?” — you know its name or type, not its folder
  • “What is eating my disk?” — -size +100M
  • Shape is always: find WHERE RULES. The dot means “from here”.
  • Know a word inside the file instead? That’s grep -r.

4 · Searching

39 of 99

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

40 of 99

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

41 of 99

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

42 of 99

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

43 of 99

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

44 of 99

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

45 of 99

> >>

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

  • Output is worth keeping: a filtered log, a list, a report
  • > the first time, >> every time after — or you wipe your own work
  • Building a file line by line from the shell

5 · Plumbing

46 of 99

|

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

  • No single command answers the question, but a chain of small ones does
  • Build it one stage at a time; run it after every | and look
  • Any command that prints can feed any command that reads

5 · Plumbing

47 of 99

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

  • Lines have columns and you want just one: the IP, the user, the department
  • Mid-pipeline, right before sort | uniq -c
  • Column counting is from 1, and the delimiter must be exactly right

5 · Plumbing

48 of 99

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

  • “Which value appears most?” — the pair sort | uniq -c is the answer, always in that order
  • uniq only sees neighbours: unsorted input gives wrong counts
  • A second sort -n on the counts ranks them; tail -n 1 takes the winner

5 · Plumbing

49 of 99

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

  • Swap or clean characters in a stream: # to $, tabs to spaces, lower case to upper
  • tr reads only its input, so always feed it with a pipe: banner X | tr
  • It works on single characters, not words: for whole-word changes you need a different tool

5 · Plumbing

50 of 99

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 |

51 of 99

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

52 of 99

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

53 of 99

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

54 of 99

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

55 of 99

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

56 of 99

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

57 of 99

58 of 99

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.

59 of 99

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.

60 of 99

61 of 99

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

62 of 99

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 @.

63 of 99

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.

64 of 99

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

65 of 99

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

66 of 99

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

67 of 99

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

68 of 99

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

69 of 99

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

70 of 99

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

  • “Permission denied” — look at the string before you look anywhere else
  • A script won’t run: no x in the owner column
  • Checking who else on the machine can read a secret

6 · The system

71 of 99

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

  • Protecting a file from accidental edits — yours included
  • You wrote a script and ./script.sh says “permission denied”
  • Never chmod 777 to “fix” something. It is how secrets leak.

6 · The system

72 of 99

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

  • “Disk full” — df -h tells you which drive; du -sh * tells you which folder, one level at a time
  • Before copying a folder somewhere small
  • Remember: du is “what is this using”, df is “what is left”

6 · The system

73 of 99

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

  • Something is hogging CPU or a port and you need its PID
  • A command ignores Ctrl+C: find it with ps, kill it from another terminal
  • On a real Linux box, top shows the same list live, sorted by CPU

6 · The system

74 of 99

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

75 of 99

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

76 of 99

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

77 of 99

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

78 of 99

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

79 of 99

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

80 of 99

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

81 of 99

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.

82 of 99

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

83 of 99

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

  • Write the file: nano hunt.sh, then paste the pipeline under the shebang
  • Make it executable: chmod +x hunt.sh
  • Run it: ./hunt.sh (the ./ means 'this folder')
  • A backslash at the end of a line continues the command on the next one

84 of 99

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

  • Permission denied on your own script: chmod +x
  • Quick test of a file you have not made executable: bash file
  • Sharing a script: always keep the shebang on line 1

85 of 99

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

  • A value appears more than once: name it once, change it once
  • You need the output of one command inside another: $( )
  • Always write "$VAR" in quotes unless you know why not

86 of 99

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

  • The same script must work on different files or IDs: take it as $1
  • Give $1 a default so the script also runs with no arguments
  • No argument and no default? Ask with read
  • The last line uses tr -cd to keep only letters and digits of the ID

87 of 99

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.

88 of 99

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

  • for: you have a list, or a number of times, and the same job for each
  • while: repeat until a condition changes
  • Task 6 gave you rm *.tmp because the 300 files were made by a loop of 3 lines

Interlude · Shell scripting · Source: cladius/linux-workshop-student-edition

89 of 99

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

  • Call it like a command: rnd 10 99
  • Inside, $1 and $2 are the function's own arguments
  • It prints its result; capture it with $( ): n=$(rnd 1 4)
  • h uses tr, the tool from the Unix philosophy slides

90 of 99

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

  • if tests a command's exit code, not a true/false value
  • Guard the start of a script: check the inputs, exit 1 early
  • check's verify function simply returns 0 for pass and 1 for fail

91 of 99

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

  • Saving $! to a file lets another script stop that exact process later
  • kill "$(cat infra/run/NAME.pid)" is the pattern you used in task 14
  • ps shows what is running; kill ends one process

92 of 99

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.

93 of 99

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

94 of 99

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

95 of 99

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

96 of 99

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

97 of 99

98 of 99

We'd Love Your Feedback

Help us improve future sessions by sharing your experience.

Scan to open the 2-minute feedback form

99 of 99

Thank You

Cladius Fernando · AI-rambh