Part 5: Challenge Solutions & Next Steps
Table of Contents
Solutions to all workshop challenges and your path forward These are complete solutions to all workshop challenges. Make sure you’ve attempted each challenge on your own before looking at the solutions. The learning happens in the struggle! Create this directory structure: Approach 1: Step-by-step Approach 2: Efficient (one-liner approach) Approach 3: Using brace expansion Mistake 1: Forgetting Mistake 2: Wrong location Analyze Question 1: How many total requests? Question 2: How many 404 errors? Question 3: List all unique IP addresses Question 4: Which IP made the most requests? Question 5: Show only successful requests (HTTP 200) Using awk for Question 4: Using grep -o for IP extraction: Step 1: Set permissions for hello.sh Step 2: Set permissions for backup.sh Step 3: Set permissions for secret.sh Step 4: Create sysinfo.sh Alternative sysinfo.sh with better formatting: Step 5: Make sysinfo.sh executable Test it: Permission number breakdown: Common combinations: Using symbolic notation: Mistake 1: Forgetting the shebang Mistake 2: Wrong permission order Step 1: Backup your config Step 2: Add aliases and function Step 3: Save and reload In nano: Step 4: Test everything Here’s a complete section to add to your Issue 1: Changes don’t persist Issue 2: Aliases don’t work in scripts Issue 3: mkcd doesn’t work To verify all your solutions work: Congratulations on completing the workshop! Here’s your path forward: Daily Usage: Use the terminal for everyday tasks OverTheWire Bandit: Complete levels 0-15 Customize Further: Bash Scripting: Text Processing Masters: Version Control: Multiplexing: Editor Mastery: Choose one Remote Work: Systems Administration: Modern Tools: Interactive Learning: Documentation: Communities: The command line is not about memorizing commands. It’s about: Remember: Even experienced developers: The difference is they know what to search for and what’s possible. The skills you’ve learned will serve you throughout your career. Every time you: You’ll use these command-line skills. Keep practicing. Keep exploring. Keep building. Completed the workshop? Share it! You’ve graduated from beginner to capable terminal user. The terminal is no longer intimidating - it’s your powerful tool. Keep practicing, keep customizing, and most importantly - have fun automating things! Drop a comment below or reach out: Happy hacking!Navigation
Part 1 Solution: Build a Project Structure
The Challenge
~/workshop-challenges/web-project/
├── src/
│ ├── components/
│ │ ├── Header.js
│ │ └── Footer.js
│ └── styles/
│ └── main.css
├── public/
│ └── index.html
├── tests/
│ └── app.test.js
└── README.mdComplete Solution
# Start from home directory
cd ~
# Create root directory
mkdir -p workshop-challenges/web-project
cd workshop-challenges/web-project
# Create all directories
mkdir -p src/components
mkdir -p src/styles
mkdir public
mkdir tests
# Create files
touch src/components/Header.js
touch src/components/Footer.js
touch src/styles/main.css
touch public/index.html
touch tests/app.test.js
touch README.md
# Verify
ls -Rcd ~ && \
mkdir -p workshop-challenges/web-project/{src/{components,styles},public,tests} && \
cd workshop-challenges/web-project && \
touch src/components/{Header,Footer}.js src/styles/main.css public/index.html tests/app.test.js README.mdcd ~
mkdir -p workshop-challenges/web-project
cd workshop-challenges/web-project
# Create directories with brace expansion
mkdir -p src/{components,styles} public tests
# Create files with brace expansion
touch src/components/{Header,Footer}.js
touch src/styles/main.css
touch public/index.html
touch tests/app.test.js
touch README.mdWhat You Learned
mkdir -p to create nested directories{a,b,c} for efficiencytouchcdCommon Mistakes
-p flagmkdir src/components # Error if src doesn't exist
mkdir -p src/components # Creates parent directories# Make sure you're in the right place
pwd # Check current directory
cd ~/workshop-challenges/web-project # Go to correct locationPart 2 Solution: Web Server Log Analysis
The Challenge
sample-data/server.log and answer 5 questions.Complete Solution
wc -l sample-data/server.log
# Output: 8 sample-data/server.log
# Or just the number:
wc -l < sample-data/server.log
# Output: 8grep "404" sample-data/server.log | wc -l
# Output: 2
# Alternative:
grep -c "404" sample-data/server.log
# Output: 2cut -d' ' -f1 sample-data/server.log | sort -u
# Output:
# 192.168.1.1
# 192.168.1.2
# 192.168.1.3
# 192.168.1.4
# To count them:
cut -d' ' -f1 sample-data/server.log | sort -u | wc -l
# Output: 4cut -d' ' -f1 sample-data/server.log | sort | uniq -c | sort -rn | head -1
# Output: 4 192.168.1.1
# More readable format:
cut -d' ' -f1 sample-data/server.log | sort | uniq -c | sort -rn | head -1 | awk '{print $2 " (" $1 " requests)"}'
# Output: 192.168.1.1 (4 requests)grep " 200 " sample-data/server.log
# Output: All lines with status 200
# Count them:
grep -c " 200 " sample-data/server.log
# Output: 5Complete answers.txt File
# Create answers.txt
cat > ~/answers.txt << 'EOF'
Question 1: Total requests
Command: wc -l sample-data/server.log
Output: 8
Question 2: 404 errors
Command: grep -c "404" sample-data/server.log
Output: 2
Question 3: Unique IPs
Command: cut -d' ' -f1 sample-data/server.log | sort -u
Output:
192.168.1.1
192.168.1.2
192.168.1.3
192.168.1.4
Question 4: Most active IP
Command: cut -d' ' -f1 sample-data/server.log | sort | uniq -c | sort -rn | head -1
Output: 192.168.1.1 (4 requests)
Question 5: Successful requests
Command: grep " 200 " sample-data/server.log
Output: 5 lines with status 200
EOFExplanation of Commands
cut -d' ' -f1-d' ': Use space as delimiter-f1: Extract first field (the IP address)sort | uniq -csort: Sort lines (required for uniq)uniq -c: Count unique occurrencessort -rn-r: Reverse (highest first)-n: Numeric sorthead -1Alternative Solutions
awk '{print $1}' sample-data/server.log | sort | uniq -c | sort -rn | head -1grep -oE '^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+' sample-data/server.log | sort | uniq -cWhat You Learned
cutuniq -csort -ngrepPart 3 Solution: Script Setup & Execution
The Challenge
hello.sh executable (only for you)backup.sh readable and executable by everyonesecret.sh readable and writable only by yousysinfo.sh that displays system informationsysinfo.sh executableComplete Solution
cd ~/scripts
chmod 700 hello.sh
# Verify
ls -l hello.sh
# Output: -rwx------ ... hello.shchmod 755 backup.sh
# Verify
ls -l backup.sh
# Output: -rwxr-xr-x ... backup.shchmod 600 secret.sh
# Verify
ls -l secret.sh
# Output: -rw------- ... secret.shcat > ~/scripts/sysinfo.sh << 'EOF'
#!/bin/bash
echo "System Information"
echo "=================="
echo ""
echo "Date and Time:"
date
echo ""
echo "Username:"
whoami
echo ""
echo "Current Directory:"
pwd
EOFcat > ~/scripts/sysinfo.sh << 'EOF'
#!/bin/bash
echo "================================"
echo " System Information"
echo "================================"
echo ""
echo "Date/Time: $(date)"
echo "User: $(whoami)"
echo "Directory: $(pwd)"
echo "Hostname: $(hostname)"
echo "Shell: $SHELL"
echo ""
echo "================================"
EOFchmod +x ~/scripts/sysinfo.sh
# Verify
ls -l ~/scripts/sysinfo.sh
# Output: -rwxr-xr-x ... sysinfo.sh~/scripts/sysinfo.sh
# Or if ~/scripts is in PATH:
sysinfo.shUnderstanding Permissions
rwx rwx rwx = 777
421 421 421
Owner Group Others700 = rwx—— (Only owner has full access)755 = rwxr-xr-x (Owner full, others read+execute)644 = rw-r–r– (Owner read+write, others read only)600 = rw—–– (Only owner read+write)400 = r–––– (Only owner read, cannot modify)Alternative Permission Methods
# hello.sh - only user executable
chmod u=rwx,g=,o= hello.sh
# Or:
chmod u+rwx,g-rwx,o-rwx hello.sh
# backup.sh - everyone can read and execute
chmod u=rwx,g=rx,o=rx backup.sh
# Or:
chmod a+rx backup.sh
# secret.sh - only user read/write
chmod u=rw,g=,o= secret.shWhat You Learned
<<)Common Mistakes
# Wrong:
echo "date" > script.sh
# Correct:
echo "#!/bin/bash" > script.sh
echo "date" >> script.sh# Remember: owner, group, others
chmod 700 file # owner=7, group=0, others=0Part 4 Solution: Environment Customization
The Challenge
mkcd functionComplete Solution
cp ~/.bashrc ~/.bashrc.backup
# Or for zsh:
cp ~/.zshrc ~/.zshrc.backup# Open your config file
nano ~/.bashrc # or ~/.zshrc
# Scroll to the end and add:# Workshop Aliases
alias ll='ls -lah'
alias gs='git status'
alias gp='git pull'
alias dev='cd ~/workshop-challenges'
alias reload='source ~/.bashrc' # Change to ~/.zshrc if using zsh
# Create directory and enter it
mkcd() {
mkdir -p "$1" && cd "$1"
}Ctrl+O, Enter, Ctrl+Xsource ~/.bashrc
# Or for zsh:
source ~/.zshrc# Test ll
cd ~
ll
# Should show detailed listing
# Test gs
gs
# Should show git status or error if not in git repo
# Test dev
dev
pwd
# Should show: /home/yourusername/workshop-challenges
# Test mkcd
cd ~
mkcd test-directory
pwd
# Should show: /home/yourusername/test-directory
# Test reload
echo "alias test='echo works'" >> ~/.bashrc
reload
test
# Should output: worksComplete .bashrc Addition
.bashrc:# =====================================
# Workshop Customizations
# =====================================
# Required aliases
alias ll='ls -lah'
alias gs='git status'
alias gp='git pull'
alias dev='cd ~/workshop-challenges'
# Determine which config file to reload
if [ -n "$BASH_VERSION" ]; then
alias reload='source ~/.bashrc'
elif [ -n "$ZSH_VERSION" ]; then
alias reload='source ~/.zshrc'
fi
# Useful function: make directory and change into it
mkcd() {
if [ -z "$1" ]; then
echo "Usage: mkcd <directory>"
return 1
fi
mkdir -p "$1" && cd "$1"
}
# =====================================
# End Workshop Customizations
# =====================================Bonus: Additional Useful Customizations
# Navigation
alias ..='cd ..'
alias ...='cd ../..'
alias ....='cd ../../..'
alias ~='cd ~'
alias -- -='cd -' # Go to previous directory
# Listing variations
alias la='ls -A'
alias l='ls -CF'
alias lt='ls -ltrh' # Sort by time, newest last
alias lsize='ls -lSrh' # Sort by size
# Safety nets
alias rm='rm -i'
alias cp='cp -i'
alias mv='mv -i'
alias ln='ln -i'
# Git shortcuts
alias ga='git add'
alias gc='git commit'
alias gco='git checkout'
alias gb='git branch'
alias gl='git log --oneline --graph'
alias gd='git diff'
# System info
alias df='df -h'
alias du='du -h'
alias free='free -h'
alias ps='ps auxf'
alias psg='ps aux | grep -v grep | grep -i -e VSZ -e'
# Quick edits
alias bashrc='nano ~/.bashrc'
alias zshrc='nano ~/.zshrc'
alias hosts='sudo nano /etc/hosts'
# Networking
alias ports='netstat -tulanp'
alias myip='curl ifconfig.me'
alias pingg='ping google.com'
# Utility functions
extract() {
if [ -f "$1" ]; then
case "$1" in
*.tar.bz2) tar xjf "$1" ;;
*.tar.gz) tar xzf "$1" ;;
*.bz2) bunzip2 "$1" ;;
*.rar) unrar x "$1" ;;
*.gz) gunzip "$1" ;;
*.tar) tar xf "$1" ;;
*.tbz2) tar xjf "$1" ;;
*.tgz) tar xzf "$1" ;;
*.zip) unzip "$1" ;;
*.Z) uncompress "$1";;
*.7z) 7z x "$1" ;;
*) echo "'$1' cannot be extracted" ;;
esac
else
echo "'$1' is not a valid file"
fi
}
# Create backup of file
backup() {
cp "$1" "$1.backup-$(date +%Y%m%d-%H%M%S)"
echo "Backed up $1"
}
# Find process by name
psgrep() {
ps aux | grep -v grep | grep -i -e VSZ -e "$1"
}
# Make directory and create .gitkeep
mkgit() {
mkdir -p "$1" && touch "$1/.gitkeep" && cd "$1"
}What You Learned
.bashrc and .zshrcCommon Issues and Fixes
# Make sure you're editing the right file
echo $SHELL # Check your shell
# For bash:
nano ~/.bashrc
# For zsh:
nano ~/.zshrc# Aliases only work in interactive shells
# Use functions instead for scripts:
# In script (functions work):
mkcd() { mkdir -p "$1" && cd "$1"; }
mkcd test
# Not in script (aliases don't work):
alias mkcd='mkdir -p "$1" && cd "$1"' # Won't work in script# Make sure function syntax is correct:
mkcd() {
mkdir -p "$1" && cd "$1"
}
# Not:
function mkcd() { # This works but is bash-specific
mkdir -p "$1" && cd "$1"
}Verification
# Clone the workshop repo
git clone https://github.com/yourusername/linux-tutorial.git
cd linux-tutorial
# Run all verifications
cd 01-getting-started && ./verify.sh
cd ../02-reading-searching && ./verify.sh
cd ../03-permissions-processes && ./verify.sh
cd ../04-environment-customization && ./verify.shWhat’s Next?
Immediate Practice (This Week)
Deepen Your Skills (Next Month)
sed for find-and-replaceawk for data processingAdvanced Topics (2-3 Months)
tmux or screensystemd: Service managementcron: Task schedulingjournalctlfzf: Fuzzy finderripgrep: Better grepbat: Better catexa: Modern lszoxide: Smart cdPractice Resources
man bash - Your best friendFinal Thoughts
man pages constantlyKeep Learning
Share Your Progress
.bashrc configurationsQuestions or Feedback?