Linux Basic β Linux File System Practice Exercises
Linux File System β Practice Exercises
These exercises reinforce everything covered in Chapter 6: the FHS, paths, file types, inodes, links, and disk usage. Work through them in order on a real Linux system or a VM.
Exercise 1 β FHS Exploration
Goal: Navigate the Filesystem Hierarchy Standard and locate key files for three installed services.
Task:
- Find the main configuration file for
ssh(the SSH daemon) - Find where
sshlogs are written - Find the
sshdbinary itself - Find the
sshdsystemd unit file - Find the runtime PID file (if any) for
sshd
Bonus: Repeat the same five steps for cron and nginx (if installed).
π‘ Show Answer
# 1. SSH configuration file
cat /etc/ssh/sshd_config | head -20
# Location: /etc/ssh/sshd_config
# 2. SSH logs β check in /var/log
grep -r sshd /etc/rsyslog.conf 2>/dev/null || echo "check journalctl"
sudo journalctl -u ssh --no-pager | tail -10
# On older distros: /var/log/auth.log or /var/log/secure
# 3. sshd binary location
which sshd
# /usr/sbin/sshd
ls -l /usr/sbin/sshd
# 4. Systemd unit file
systemctl show ssh --property=FragmentPath
# Or:
find /lib/systemd /etc/systemd -name "ssh*" 2>/dev/null
# /lib/systemd/system/ssh.service
# 5. Runtime PID file
cat /run/sshd.pid 2>/dev/null || echo "No PID file β check /run"
ls /run/ | grep ssh
# Bonus β cron
ls /etc/cron* /var/spool/cron/
which cron crond 2>/dev/null
find /lib/systemd -name "cron*" 2>/dev/null
# Bonus β nginx (if installed)
ls /etc/nginx/
ls /var/log/nginx/
which nginx
Exercise 2 β Path Navigation Lab
Goal: Practice converting between absolute and relative paths without a GUI.
Setup:
mkdir -p /tmp/pathlab/{alpha/{a1,a2},beta/{b1,b2},gamma}
touch /tmp/pathlab/alpha/a1/file1.txt
touch /tmp/pathlab/beta/b2/file2.txt
touch /tmp/pathlab/gamma/file3.txt
cd /tmp/pathlab/alpha/a1
Tasks (you are in /tmp/pathlab/alpha/a1/):
- Print the absolute path to
file2.txtwithout usingrealpath - Copy
file1.txttobeta/b1/using only a relative path - Create a symlink in
/tmp/pathlab/gamma/pointing tofile1.txtusing a relative target path - Use
realpathto confirm the symlink resolves correctly - Move to
/tmp/pathlab/beta/b1/andcatfile1.txtusing a relative path that goes up two directories
π‘ Show Answer
# 1. Absolute path to file2.txt
echo /tmp/pathlab/beta/b2/file2.txt
# (manually constructed β absolute paths start from /)
# 2. Copy using relative path (from /tmp/pathlab/alpha/a1/)
cp file1.txt ../../beta/b1/
ls /tmp/pathlab/beta/b1/
# file1.txt
# 3. Symlink in gamma using a relative target
# From gamma's perspective, file1.txt is at ../alpha/a1/file1.txt
ln -s ../alpha/a1/file1.txt /tmp/pathlab/gamma/link1.txt
ls -la /tmp/pathlab/gamma/
# link1.txt -> ../alpha/a1/file1.txt
# 4. Verify with realpath
realpath /tmp/pathlab/gamma/link1.txt
# /tmp/pathlab/alpha/a1/file1.txt
# 5. Cat from /tmp/pathlab/beta/b1/
cd /tmp/pathlab/beta/b1/
cat ../../alpha/a1/file1.txt
# (empty file, but no error)
# Cleanup
rm -rf /tmp/pathlab
Exercise 3 β Inode Investigation
Goal: Use stat and ls -i to compare regular files, directories, and symlinks.
Tasks:
- Create three files and compare their inode numbers β are they consecutive?
- Create a directory and note how
statshows its link count β why is it at least 2? - Compare
statoutput for a regular file vs a symlink to that file β note the differences
π‘ Show Answer
# 1. Create files and compare inodes
touch /tmp/inode_a /tmp/inode_b /tmp/inode_c
ls -i /tmp/inode_a /tmp/inode_b /tmp/inode_c
# Inode numbers are assigned by the filesystem β not always consecutive
# They may or may not be adjacent depending on filesystem state
# 2. Directory link count
mkdir /tmp/testdir
stat /tmp/testdir | grep Links
# Links: 2
# Why 2? Every directory has:
# - One entry in its parent (the dirname itself)
# - One '.' entry inside itself (pointing back to the same inode)
# Each subdirectory adds another '..' entry, increasing the parent's link count by 1
mkdir /tmp/testdir/subA /tmp/testdir/subB
stat /tmp/testdir | grep Links
# Links: 4 (testdir itself = 1, . inside = 1, subA/.., subB/..)
# 3. Regular file vs symlink inode comparison
echo "hello inode" > /tmp/original.txt
ln -s /tmp/original.txt /tmp/symlink.txt
stat /tmp/original.txt
# Inode: XXXXX Size: 12 Links: 1 regular file
stat /tmp/symlink.txt
# Inode: YYYYY Size: 16 Links: 1 symbolic link -> /tmp/original.txt
# - DIFFERENT inode numbers (symlink is its own filesystem object)
# - symlink Size = length of the path string "/tmp/original.txt"
# Cleanup
rm -rf /tmp/testdir /tmp/inode_a /tmp/inode_b /tmp/inode_c /tmp/original.txt /tmp/symlink.txt
Exercise 4 β Links Lab
Goal: Create and test hard links and symlinks, observe the cross-filesystem limitation, and find dangling symlinks.
Tasks:
- Create a file and a hard link to it. Prove they share an inode. Delete the original β does the content survive?
- Attempt a hard link to
/etc/hostnamefrom/tmp/β note the error - Create a symlink and then remove its target β observe the dangling state with
lsandfind - Atomically switch a symlink from version 1 to version 2 using the deployment pattern
π‘ Show Answer
# 1. Hard link exercise
echo "content to keep" > /tmp/original.txt
ln /tmp/original.txt /tmp/hardlink.txt
ls -li /tmp/original.txt /tmp/hardlink.txt
# Both show same inode number, Link count = 2
rm /tmp/original.txt
cat /tmp/hardlink.txt
# content to keep β data survives, inode still has 1 link
ls -li /tmp/hardlink.txt
# Link count is now 1
# 2. Cross-filesystem hard link (will fail)
ln /etc/hostname /tmp/hostname_link
# ln: failed to create hard link '/tmp/hostname_link' => '/etc/hostname':
# Invalid cross-device link
# /etc is on the root filesystem; /tmp may be on tmpfs β different devices
# 3. Dangling symlink
echo "I exist" > /tmp/real.txt
ln -s /tmp/real.txt /tmp/mylink.txt
rm /tmp/real.txt
ls -la /tmp/mylink.txt
# lrwxrwxrwx 1 ubuntu ubuntu 12 Apr 1 10:00 /tmp/mylink.txt -> /tmp/real.txt
# (shown in red in most terminals)
cat /tmp/mylink.txt
# cat: /tmp/mylink.txt: No such file or directory
find /tmp -xtype l
# /tmp/mylink.txt β found by -xtype l (type is symlink but target missing)
# 4. Deployment pattern
mkdir -p /tmp/deploy/app-v1 /tmp/deploy/app-v2
echo "version 1" > /tmp/deploy/app-v1/main.sh
echo "version 2" > /tmp/deploy/app-v2/main.sh
ln -s /tmp/deploy/app-v1 /tmp/deploy/current
cat /tmp/deploy/current/main.sh
# version 1
ln -sfn /tmp/deploy/app-v2 /tmp/deploy/current
cat /tmp/deploy/current/main.sh
# version 2
# Rollback
ln -sfn /tmp/deploy/app-v1 /tmp/deploy/current
cat /tmp/deploy/current/main.sh
# version 1
# Cleanup
rm -rf /tmp/deploy /tmp/mylink.txt /tmp/hardlink.txt
Exercise 5 β Disk Detective
Goal: Use df and du to identify where disk space is being consumed.
Tasks:
- Check overall disk space with
df -hβ identify the filesystem with the highestUse% - Check inode usage with
df -iβ are any filesystems at risk of running out of inodes? - Find the top 5 directories consuming the most space under
/var - Find any files over 50 MB anywhere on the system (excluding
/procand/sys) - Check if any deleted-but-open files are consuming space
π‘ Show Answer
# 1. Overall disk space
df -h
# Look for Use% near 80% or higher β those need attention
# 2. Inode usage
df -i
# IUse% > 80% indicates risk
# IUse% at 100% means no new files can be created on that filesystem
# 3. Top directories under /var
du -h --max-depth=2 /var 2>/dev/null | sort -rh | head -10
# Common space consumers:
# /var/lib/docker β Docker images and containers
# /var/log/journal β systemd logs
# /var/cache/apt β apt package cache
# /var/lib/mysql β MySQL data files (if installed)
# Drill deeper into the biggest one found:
du -sh /var/log/* | sort -rh | head -5
# 4. Large files (excluding /proc and /sys)
find / -xdev -type f -size +50M \
-not -path "/proc/*" \
-not -path "/sys/*" \
-printf '%s\t%p\n' 2>/dev/null \
| sort -rn \
| awk '{printf "%.0fMB\t%s\n", $1/1024/1024, $2}' \
| head -10
# 5. Deleted-but-open files (consuming space even though unlinked)
sudo lsof +L1 2>/dev/null | grep DEL
# If output is long, check total space they consume:
sudo lsof +L1 2>/dev/null | grep DEL | awk '{print $7}' | \
awk '{sum += $1} END {print "Total deleted-but-open:", sum/1024/1024, "MB"}'
# Fix: restart the process that has the file open
# Example: if nginx has a deleted log open:
# sudo systemctl restart nginx
Challenge: Full Disk Simulation
Advanced β simulate and resolve a disk-full situation on a practice VM (do NOT do this on a production system):
# WARNING: This will fill /tmp β do on a throwaway VM only
# Fill up /tmp with a large file
dd if=/dev/zero of=/tmp/bigfile bs=1M count=1000 # 1 GB
# Observe:
df -h /tmp
# Now try to create a file in /tmp
touch /tmp/newfile # May fail if /tmp is its own partition
# Resolution:
rm /tmp/bigfile
df -h /tmp
Summary Checklist
After completing these exercises you should be comfortable with:
- β Locating configuration, logs, and binaries for any installed service using FHS knowledge
- β Constructing and converting between absolute and relative paths
- β
Using
statandls -ito inspect inode metadata - β Creating and managing hard links and symlinks
- β Implementing the versioned deployment symlink pattern
- β
Finding dangling symlinks with
find -xtype l - β
Using
df -handdf -ito assess disk and inode health - β
Using
du -sh *andsort -rhto find space consumers - β
Detecting deleted-but-open files with
lsof +L1
| β Back to Disk Usage: df and du | β Chapter Home: Linux File System |