Skip to content
Author Nejat Hakan
eMail nejat.hakan@outlook.de
PayPal Me https://paypal.me/nejathakan


Understanding the Filesystem

Introduction What is a Filesystem

Welcome to the foundational layer of data organization in Linux: the filesystem. At its core, a filesystem is a method and data structure that an operating system uses to control how data is stored and retrieved. Think of it like a highly organized library or a meticulous filing system in an office. Without it, data stored on a disk (or any storage medium) would be one large, undifferentiated block of information, making it impossible to locate specific pieces of data like documents, programs, or configuration settings.

The filesystem provides several crucial functions:

  1. Hierarchy: It organizes files into a structured hierarchy of directories (often called folders in other operating systems). This tree-like structure allows for logical grouping and easy navigation.
  2. Naming: It allows users and programs to refer to files and directories by human-readable names.
  3. Metadata: It stores information about the files, not just the data within them. This metadata includes details like ownership, permissions, creation/modification times, file size, and the physical location of the data on the storage device.
  4. Data Management: It keeps track of which parts of the storage device are currently in use, which are free, and which blocks of data belong to which file.
  5. API (Application Programming Interface): It provides a consistent way for applications to interact with files (create, read, write, delete, etc.) without needing to know the specific hardware details of the storage device.

In Linux, everything is treated conceptually as a file. This includes not only regular data files and programs but also directories, links, and even hardware devices (like printers, terminals, and disk drives). This "everything is a file" philosophy simplifies interaction with the system, as many of the same tools and commands can be used across different types of objects.

The Linux filesystem starts at a single top-level directory called the root directory, denoted by a forward slash (/). All other filesystems, directories, and files are logically located beneath this root, regardless of how many physical storage devices are attached to the system. This creates a unified, single namespace for all accessible data.

Understanding the filesystem is absolutely critical for anyone working with Linux, from casual users to system administrators and developers. It dictates where programs are installed, where user data is stored, how system configurations are managed, and how security is enforced through permissions.

This section will delve into the structure, components, and management of the Linux filesystem. We will explore the standard layout, different types of files, the concepts of permissions and ownership, and how storage devices are integrated into the hierarchy.

1. The Filesystem Hierarchy Standard (FHS)

Imagine trying to find a specific book in a massive library where every librarian has their own unique, undocumented system for shelving books. It would be chaotic and inefficient. Similarly, early Unix and Linux systems often had different conventions for where system files, user data, and applications should reside. This made it difficult for software developers to create applications that would work reliably across different distributions and challenging for administrators managing multiple systems.

To address this, the Filesystem Hierarchy Standard (FHS) was developed. The FHS defines the main directories and their contents in Linux and other Unix-like operating systems. Its primary goal is to ensure that compliant systems have a predictable and consistent layout. This standardization allows:

  • Software Portability: Developers can create software packages that know where to expect configuration files, libraries, and executables, regardless of the specific Linux distribution.
  • Administrator Efficiency: System administrators can navigate and manage different Linux systems more easily because they know the standard locations for critical files and directories.
  • User Familiarity: Users migrating between different distributions find a familiar structure.
  • System Integrity: It helps separate operating system files from user files and distributable software from local modifications, making upgrades and system maintenance safer.

The FHS specifies a tree-like structure starting from the root directory (/). Let's explore the most important top-level directories defined by the FHS:

  • / (Root Directory)

    • This is the top-level directory of the entire filesystem hierarchy. Everything, absolutely everything, resides logically under the root directory.
    • It should generally contain only the directories required by the FHS and potentially a few critical system recovery tools. It should not be cluttered with user files or large software packages.
  • /bin (Essential User Binaries)

    • Contains essential command-line programs (binaries) needed for basic system operation and available to all users, often required even in single-user mode or before other filesystems are mounted.
    • Examples: ls, cp, mv, bash, cat, mount, umount.
    • These binaries should work even if /usr is not yet mounted. In many modern systems, /bin is often a symbolic link to /usr/bin for simplification.
  • /sbin (Essential System Binaries)

    • Similar to /bin, but contains essential binaries primarily intended for system administration tasks.
    • These commands typically require root privileges to execute effectively.
    • Examples: fdisk, mkfs, ifconfig (older systems), ip, reboot, shutdown, init.
    • Like /bin, these should be available early in the boot process. /sbin is also often linked to /usr/sbin on modern systems.
  • /etc (Configuration Files)

    • Contains system-wide configuration files for the operating system and installed applications.
    • These are typically static text files that control system behavior. They should not contain binary executables.
    • Examples: /etc/passwd (user database), /etc/group (group database), /etc/fstab (filesystem table), /etc/hosts (static hostname lookups), /etc/ssh/sshd_config (SSH server configuration), /etc/nginx/nginx.conf (Nginx configuration).
    • Subdirectories often exist for specific applications (e.g., /etc/apache2, /etc/mysql).
  • /dev (Device Files)

    • Contains special files known as device files, which represent hardware devices attached to the system.
    • Linux treats hardware devices as files, allowing programs to interact with them using standard file I/O operations (read, write).
    • Examples: /dev/sda (first SCSI/SATA disk), /dev/sda1 (first partition on that disk), /dev/nvme0n1 (first NVMe drive), /dev/tty1 (first virtual console), /dev/null (a black hole), /dev/random (random number generator).
    • This directory is typically managed dynamically by the udev system.
  • /proc (Process Information Pseudo-filesystem)

    • This is not a real filesystem stored on disk but a virtual or pseudo-filesystem generated dynamically by the kernel.
    • It provides an interface to kernel data structures, primarily information about running processes (hence the name).
    • Numbered directories (e.g., /proc/1234) correspond to process IDs (PIDs) and contain information about that specific process (command line, memory usage, open files, etc.).
    • Also contains files representing system hardware and kernel configuration parameters (e.g., /proc/cpuinfo, /proc/meminfo, /proc/sys/). Interacting with files under /proc/sys can often tune kernel behavior.
  • /var (Variable Files)

    • Contains variable data files whose content is expected to grow or change frequently during system operation.
    • This directory is crucial for separating dynamic data from the relatively static OS files found in / and /usr.
    • Common subdirectories:
      • /var/log: System log files (e.g., /var/log/syslog, /var/log/auth.log).
      • /var/cache: Application cache data.
      • /var/spool: Data waiting for processing (e.g., mail queues, print spools).
      • /var/lib: State information (e.g., databases, package manager state).
      • /var/tmp: Temporary files preserved between reboots (unlike /tmp).
      • /var/www: Often used for web server content (though /srv is sometimes preferred).
  • /tmp (Temporary Files)

    • Used for storing temporary files created by applications and users.
    • Files in /tmp are typically not guaranteed to survive a system reboot. Many systems are configured to clear /tmp automatically at boot time or on a regular schedule.
    • It's generally world-writable (meaning any user can create files here), but often has the "sticky bit" set for security (explained later).
  • /usr (User Utilities and Applications)

    • Historically stood for "User System Resources," but now often thought of as "Unix System Resources." This directory contains the majority of user-level utilities and applications, libraries, documentation, and other non-essential system files.
    • It's intended primarily for read-only data (binaries, libraries, documentation) installed by the operating system distribution. Locally installed software often goes into /usr/local.
    • It can often be mounted as a separate filesystem and potentially shared read-only across multiple machines.
    • Key subdirectories:
      • /usr/bin: Non-essential command binaries (available after / is mounted).
      • /usr/sbin: Non-essential system administration binaries.
      • /usr/lib or /usr/lib64: Libraries for /usr/bin and /usr/sbin.
      • /usr/include: Standard C header files for development.
      • /usr/share: Architecture-independent shared data (documentation in /usr/share/doc, man pages in /usr/share/man).
      • /usr/local: Locally installed software that is not part of the distribution (e.g., compiled from source). It has its own bin, sbin, lib, share, etc hierarchy. This keeps local modifications separate from the core OS files, simplifying system upgrades.
  • /home (User Home Directories)

    • Contains personal directories for regular users.
    • Each user typically has a subdirectory named after their username (e.g., /home/alice, /home/bob).
    • This is where users store their personal files, documents, application settings (often in hidden dotfiles like .bashrc, .config/), etc.
    • It's common practice to mount /home on a separate partition or filesystem. This allows the operating system to be reinstalled or upgraded without affecting user data.
  • /boot (Boot Loader Files)

    • Contains static files required by the boot loader (e.g., GRUB, LILO) to boot the system.
    • This typically includes the Linux kernel image(s) (e.g., vmlinuz-linux), initial RAM disk images (initramfs*.img or initrd*.img), and boot loader configuration files (e.g., /boot/grub/grub.cfg).
    • It's sometimes placed on a separate small partition, especially when using encryption or certain filesystem types for the root partition.
  • /lib (Essential Shared Libraries and Kernel Modules)

    • Contains shared library files needed by the essential binaries in /bin and /sbin. These libraries are crucial for basic system functionality, even before /usr is mounted.
    • Also typically contains kernel modules (/lib/modules/<kernel-version>/).
    • Similar to /bin and /sbin, /lib is often symbolically linked to its counterpart under /usr (e.g., /lib -> /usr/lib) on modern systems. /lib64 may exist on 64-bit systems for 64-bit libraries, sometimes linked to /usr/lib64.
  • /opt (Optional Application Software Packages)

    • Reserved for the installation of add-on application software packages, particularly commercial or third-party software that doesn't follow the standard filesystem layout.
    • Software installed here usually keeps all its files within a single subdirectory named after the package (e.g., /opt/google/chrome, /opt/MATLAB).
  • /mnt (Mount Point for Temporarily Mounted Filesystems)

    • Historically used as a temporary mount point for manually mounting filesystems (e.g., floppy disks, network shares).
    • System administrators can create subdirectories here (e.g., /mnt/usb, /mnt/nfs) as needed.
  • /media (Removable Media Devices)

    • Intended as a mount point for removable media like USB drives, CD-ROMs, SD cards.
    • Modern desktop environments often automatically create subdirectories here when removable media is detected (e.g., /media/username/usb-drive-label).
  • /srv (Service Data)

    • Contains site-specific data served by this system.
    • The idea is to group data for specific services offered by the machine (e.g., web server files in /srv/www, FTP server files in /srv/ftp). The use of /srv versus /var (e.g., /var/www) can vary depending on distribution and local conventions.

Understanding the FHS provides a mental map for navigating any standard Linux system. When looking for a configuration file, you head to /etc. When debugging a system service, you check logs in /var/log. When installing software from source, /usr/local is the target. This structure brings order to the complexity of a modern operating system.

Workshop Exploring the FHS

In this workshop, we'll use basic navigation commands to explore the Filesystem Hierarchy Standard on your Linux system. This will help solidify your understanding of where different types of files reside.

Prerequisites: Access to a Linux terminal.

Steps:

  1. Navigate to the Root Directory:

    • Open your terminal. The starting point is usually your home directory.
    • Type cd / and press Enter. This command changes your current directory to the root (/) directory.
    • Command:
      cd /
      
    • Verify your location using the pwd (print working directory) command.
    • Command:
      pwd
      
    • Expected Output:
      /
      
  2. List Top-Level Directories:

    • Use the ls command to list the contents of the root directory. Use the -l option for a long listing format (showing permissions, owner, size, etc.) and -h for human-readable file sizes.
    • Command:
      ls -lh
      
    • Observe the output. You should see most of the directories discussed above (bin, etc, home, usr, var, etc.). Note that some might be symbolic links (indicated by -> in the ls -l output) pointing to directories under /usr on modern systems (e.g., bin -> usr/bin).
  3. Explore /etc (Configuration Files):

    • Change directory into /etc.
    • Command:
      cd /etc
      
    • List some files. Look for familiar configuration files mentioned earlier.
    • Command:
      ls passwd group fstab hosts
      
    • Try viewing the contents of the hosts file using the cat command.
    • Command:
      cat hosts
      
    • Navigate back to the root directory.
    • Command:
      cd /
      
  4. Explore /bin and /usr/bin (Executables):

    • Change directory into /bin.
    • Command:
      cd /bin
      
    • List the contents. You'll see many fundamental commands like ls, cp, pwd.
    • Command:
      ls
      
    • Now, go to /usr/bin.
    • Command:
      cd /usr/bin
      
    • List the contents here. You'll likely find many more commands – applications and utilities installed as part of your distribution.
    • Command:
      ls | head # Show just the first few entries
      
    • Notice the overlap and the sheer number of programs available.
  5. Explore /var/log (Log Files):

    • Navigate to the log directory.
    • Command:
      cd /var/log
      
    • List the files. You should see various log files ending in .log and possibly some compressed archives (.gz).
    • Command:
      ls -lh
      
    • Try viewing the last few lines of the main system log (often syslog or messages, might require sudo for access).
    • Command (adjust filename if needed):
      sudo tail syslog
      # or
      sudo tail messages
      
  6. Explore /dev (Device Files):

    • Go to the /dev directory.
    • Command:
      cd /dev
      
    • List the contents. Notice the different naming conventions (e.g., tty* for terminals, sd* or nvme* for disks, null, zero, random).
    • Use ls -l to see the file types. Notice the 'c' (character device) or 'b' (block device) at the beginning of the permission string for many files here.
    • Command:
      ls -l | head -n 20 # Show first 20 lines of long listing
      
  7. Explore /home (User Directories):

    • Navigate to /home.
    • Command:
      cd /home
      
    • List the contents. You should see a directory corresponding to your own username and perhaps others if multiple users exist on the system.
    • Command:
      ls -l
      
    • Navigate into your own home directory using cd ~ or cd /home/your_username. ~ is a shortcut for your home directory.
    • Command:
      cd ~
      pwd
      
  8. (Optional) Use tree for Visualization:

    • If you have the tree command installed (you might need to install it: sudo apt install tree or sudo yum install tree), it provides a nice visual representation of the directory structure. Try it on a smaller directory first, like /etc/default. Warning: Running tree / can take a very long time and produce massive output.
    • Command:
      tree -L 1 / # Show only the first level under root
      tree -L 2 /etc # Show two levels under /etc
      

By navigating through these key directories, you gain a practical feel for the standard Linux layout defined by the FHS. This knowledge is invaluable for locating files, understanding system behavior, and performing administrative tasks.

Having explored the overall structure (the FHS), let's zoom in on the fundamental building blocks: files, directories, and links. These are the objects that populate the filesystem hierarchy.

Files

In the Linux/Unix philosophy, a file is the fundamental unit of storage. At its most basic level, a file is simply a sequence of bytes containing data. This data could be anything: text for a document or configuration file, machine code for an executable program, pixels for an image, records for a database, etc. The operating system itself doesn't usually impose a structure on the content of a regular file; it's up to the applications that use the file to interpret the bytes correctly.

Beyond the data itself, the filesystem stores crucial information about each file, known as metadata. This metadata is stored separately from the file's data content, typically in a structure called an inode (index node). Key pieces of metadata stored in the inode include:

  • File Type: Is it a regular file, directory, link, etc.?
  • Permissions: Who can read, write, or execute the file?
  • Owner: Which user ID (UID) owns the file?
  • Group: Which group ID (GID) is associated with the file?
  • Size: How many bytes does the file contain?
  • Timestamps: When was the file last accessed (atime), last modified (mtime), and when were its metadata/attributes last changed (ctime)?
  • Link Count: How many hard links point to this inode? (More on this later).
  • Data Block Pointers: Addresses on the physical storage device where the actual file content (the sequence of bytes) is stored.

File Types: Linux recognizes several types of files, each serving a different purpose:

  1. Regular File (-): The most common type. Contains data as described above (text, executable code, images, etc.). Indicated by a hyphen (-) in the first character of ls -l output.
  2. Directory (d): A special type of file that acts as a container for other files and directories. Internally, it's often represented as a list of filenames and their corresponding inode numbers. Indicated by a d.
  3. Symbolic Link (l): Also known as a soft link or symlink. It's a pointer to another file or directory by name. It contains the path of the target file/directory. Indicated by an l.
  4. Hard Link: Not a distinct file type marker in ls -l (it appears as a regular file or directory), but rather a second name (directory entry) pointing to the same inode as another file. All hard links to the same inode are indistinguishable from the "original" file name.
  5. Character Device (c): A device file that provides unbuffered, direct access to a hardware device. Data is typically read/written character by character. Examples: terminals (/dev/tty*), serial ports (/dev/ttyS*), the null device (/dev/null). Indicated by a c.
  6. Block Device (b): A device file that provides buffered access to a hardware device, usually storage devices. Data is read/written in fixed-size blocks. Examples: hard drives (/dev/sda), NVMe drives (/dev/nvme0n1), CD-ROM drives (/dev/sr0). Indicated by a b.
  7. Socket (s): A special file used for inter-process communication (IPC) within the system, allowing different programs running on the same machine to exchange data. Indicated by an s.
  8. Named Pipe (FIFO) (p): First-In, First-Out (FIFO) special file. Another form of IPC, allowing one process to write data that another process can read in sequence. Indicated by a p.

The file command is useful for inspecting a file and determining its type based on its content or metadata (e.g., file /bin/bash, file /etc/passwd, file /dev/sda).

Inodes

The inode (index node) is a cornerstone concept. Every file and directory on a typical Linux filesystem (like ext4, XFS) has an inode. Think of the inode number as a unique serial number for the file within that specific filesystem. The inode stores all the metadata listed earlier (type, permissions, owner, size, timestamps, data block pointers) but crucially, it does not store the filename or the file's data content directly (only pointers to the data blocks).

Filenames are stored in the directory files. A directory entry essentially maps a human-readable filename to an inode number. This separation is what allows for features like hard links.

You can view the inode number of files using the -i option with ls: ls -li.

Directories

As mentioned, a directory is a special file whose content is a list mapping filenames to inode numbers. When you use a command like ls /home/user, the system:

  1. Finds the inode for the /home/user directory.
  2. Reads the data blocks associated with that inode (which contain the directory entries).
  3. For each entry, it retrieves the filename and the corresponding inode number.
  4. Optionally (e.g., for ls -l), it reads the inode for each listed file to get its metadata (permissions, size, etc.).

Every directory contains at least two special entries:

  • . (dot): A hard link to the directory itself.
  • .. (dot-dot): A hard link to the parent directory. (In the root directory /, .. points to / itself).

These entries are essential for relative path navigation (cd .. moves up one level).

Links provide ways to make a file or directory accessible from multiple locations in the filesystem hierarchy or under different names. Linux supports two main types of links:

1. Hard Links:

  • How it works: A hard link creates a new directory entry (a new name) that points directly to the same inode as an existing file.
  • Characteristics:
    • All hard links to a file share the same inode and thus the same metadata and data blocks. They are essentially identical references to the same underlying file.
    • Modifying the content through one hard link affects all other hard links because they point to the same data.
    • Deleting a hard link (using rm) simply removes that directory entry and decrements the link count stored in the inode. The file's data and inode are only actually removed from the disk when the link count drops to zero (meaning no more directory entries point to it).
    • Limitations:
      • You generally cannot create a hard link to a directory (to prevent recursive loops in the filesystem structure, though . and .. are exceptions managed by the filesystem itself).
      • Hard links cannot cross filesystem boundaries (partitions). Since inode numbers are only unique within a specific filesystem, a link in one filesystem cannot point directly to an inode in another.
  • Creation: ln target_file link_name
  • Identification: Use ls -li. Files with the same inode number are hard links to each other. The number in the third column of ls -l output is the link count.

2. Symbolic Links (Soft Links / Symlinks):

  • How it works: A symbolic link is a special type of file whose content is the path (text string) to another file or directory. It's an indirect pointer.
  • Characteristics:
    • A symlink has its own inode, distinct from the target file's inode.
    • It stores the pathname of the target file/directory.
    • When you access a symlink, the system typically follows the path stored within it to reach the target file or directory.
    • Deleting the symlink (rm link_name) removes only the link itself; the target file/directory is unaffected.
    • Deleting the target file/directory makes the symlink "dangling" or "broken" – it points to a non-existent location.
    • Symlinks can point to directories.
    • Symlinks can cross filesystem boundaries because they store a path, not an inode number.
    • Permissions on the symlink itself are usually irrelevant; access permissions are determined by the permissions of the target file or directory (though the directory containing the symlink must allow access).
  • Creation: ln -s target_file_or_directory link_name
  • Identification: Use ls -l. Symlinks are indicated by an l as the first character, and the output shows the link name followed by -> target_path.

Use Cases:

  • Hard Links: Useful for having a file appear in multiple directories on the same filesystem without duplicating data, or for backup strategies where multiple snapshots might hard-link unchanged files to save space. Less commonly used by average users than symlinks.
  • Symbolic Links: Very common. Used for creating shortcuts, managing different versions of software or libraries (e.g., /usr/lib/libfoo.so -> libfoo.so.1.2), redirecting configuration files, and making files accessible from standard locations even if they reside elsewhere.

Understanding the distinction between these file types and linking mechanisms is fundamental to managing data and navigating the Linux filesystem effectively.

This workshop provides hands-on practice creating, manipulating, and identifying different types of files, directories, and links.

Prerequisites: Access to a Linux terminal.

Steps:

  1. Setup:

    • Navigate to your home directory.
    • Command:
      cd ~
      
    • Create a dedicated directory for this workshop.
    • Command:
      mkdir filesystem_workshop
      cd filesystem_workshop
      
  2. Creating Directories and Files:

    • Create a nested directory structure in one command using mkdir -p.
    • Command:
      mkdir -p project/src project/docs project/bin
      
    • Verify the structure using ls -R (recursive listing) or tree (if installed).
    • Command:
      ls -R
      # or
      tree
      
    • Create an empty file using touch.
    • Command:
      touch project/docs/README.md
      
    • Create a file with some text content using echo and redirection >.
    • Command:
      echo "Initial source code" > project/src/main.c
      
    • Verify file creation.
    • Command:
      ls project/src project/docs
      cat project/src/main.c
      
  3. Inspecting File Types and Inodes:

    • Use ls -l to see the types (first character: - for file, d for directory).
    • Command:
      ls -l project
      ls -l project/src/main.c
      
    • Use the file command to get more details about the file types.
    • Command:
      file project
      file project/src/main.c
      file /bin/bash # Example of an executable
      file /dev/null # Example of a character device
      
    • View the inode numbers using ls -li. Note the inode number for project/src/main.c.
    • Command:
      ls -li project/src
      
  4. Creating and Testing Hard Links:

    • Create a hard link named main_backup.c that points to the same inode as project/src/main.c.
    • Command:
      ln project/src/main.c project/src/main_backup.c
      
    • List the files in project/src with their inode numbers. Observe that main.c and main_backup.c have the same inode number. Also, note the link count (third column) for these files is now 2.
    • Command:
      ls -li project/src
      
    • Append some text to main.c and then display the content of main_backup.c. The changes should be reflected in both, as they point to the same data.
    • Command:
      echo "// Added a comment" >> project/src/main.c
      cat project/src/main_backup.c
      
    • Remove the original main.c. Check the link count and inode number of main_backup.c. The count should decrease to 1, but the file still exists because the link count didn't reach zero.
    • Command:
      rm project/src/main.c
      ls -li project/src
      cat project/src/main_backup.c # Still exists!
      
    • Attempt to create a hard link to the project/docs directory (this should fail on most systems).
    • Command:
      ln project/docs project/docs_hardlink # Likely produces an error
      
  5. Creating and Testing Symbolic Links:

    • Recreate the original file for clarity.
    • Command:
      echo "Restored source code" > project/src/main.c
      
    • Create a symbolic link (in the main filesystem_workshop directory) pointing to project/src/main.c.
    • Command:
      ln -s project/src/main.c main_source_link.c
      
    • List the files in the current directory using ls -li. Note that main_source_link.c has its own unique inode number and its file type is l (link). The output also shows -> project/src/main.c.
    • Command:
      ls -li
      
    • Display the content using the symlink. It should show the content of the target file.
    • Command:
      cat main_source_link.c
      
    • Create a symbolic link to the project/docs directory.
    • Command:
      ln -s project/docs documentation_link
      
    • List the contents. Note the link pointing to the directory.
    • Command:
      ls -l
      
    • Try navigating into the linked directory.
    • Command:
      cd documentation_link
      pwd # Note your current path might still show the link name or the resolved path
      ls # Should show README.md
      cd .. # Go back
      
    • Now, remove the target file project/src/main.c.
    • Command:
      rm project/src/main.c
      
    • Try to access the file via the symbolic link main_source_link.c. This should fail (e.g., "No such file or directory").
    • Command:
      cat main_source_link.c # Error expected
      
    • List the link using ls -l. It will often be shown in a different color (like red) in the terminal, indicating a broken or dangling link.
    • Command:
      ls -l main_source_link.c
      
  6. Exploring Inode Information with stat:

    • Recreate the target file again.
    • Command:
      echo "Final source code version" > project/src/main.c
      
    • Use the stat command to view detailed metadata (including inode information, timestamps, link count) for the file and the symbolic link.
    • Command:
      stat project/src/main.c
      stat main_source_link.c # Note 'File:' shows the link, 'Links:' is 1 for the link itself
      stat documentation_link
      
    • Compare the Inode number reported by stat for project/src/main.c and the hard link project/src/main_backup.c (if you still have it). They should be identical. Compare with the inode number for main_source_link.c, which should be different.
  7. Cleanup:

    • Navigate out of the workshop directory and remove it recursively.
    • Command:
      cd ..
      rm -r filesystem_workshop
      

This workshop demonstrated the practical differences between regular files, directories, hard links, and symbolic links, along with how to use common commands like mkdir, touch, echo, ls, cat, ln, rm, and stat to manage and inspect them.

3. Permissions and Ownership

A critical aspect of any multi-user operating system like Linux is controlling who can access which files and what they can do with them (read, write, execute). This is managed through a system of ownership and permissions. This system forms the basis of security and data integrity within the filesystem.

Users and Groups

Every file and directory in Linux has an owner and an associated group.

  • Owner: Usually, the user who created the file is designated as its owner. The owner has special privileges regarding the file's permissions. Ownership is tracked using a numeric User ID (UID).
  • Group: Every file also belongs to a group. This allows the owner to grant access privileges to other users who are members of that specific group. Group association is tracked using a numeric Group ID (GID).

Linux manages users and groups through configuration files, primarily:

  • /etc/passwd: Contains information about user accounts, including username, UID, primary GID, home directory, and default shell. (Note: Despite the name, passwords themselves are usually stored securely in /etc/shadow).
  • /etc/group: Contains information about groups, including group name, GID, and a list of users who are members of that group.

Every user has a primary group (specified in /etc/passwd) and can also be a member of multiple supplementary groups (listed in /etc/group). When a user creates a file, it typically inherits the user's UID as the owner and the user's primary group (or sometimes the group of the parent directory, depending on settings) as the group owner.

You can see your own UID, GID, and group memberships using the id command:

id
# Example output: uid=1000(student) gid=1000(student) groups=1000(student),27(sudo),100(users)

Permission Bits

For each file and directory, Linux maintains three sets of permissions, corresponding to three categories of users:

  1. User (Owner): Permissions that apply only to the owner of the file (the UID associated with the file).
  2. Group: Permissions that apply to users who are members of the group associated with the file (the GID associated with the file), excluding the owner (whose permissions are determined solely by the User/Owner bits).
  3. Others: Permissions that apply to all other users on the system who are neither the owner nor members of the file's group.

Within each of these three sets (User, Group, Others), there are three basic permission types:

  • Read (r):
    • For Files: Allows viewing the contents of the file (e.g., using cat, less).
    • For Directories: Allows listing the names of the files and subdirectories within the directory (e.g., using ls). Requires execute permission (x) as well to access file metadata or enter the directory.
  • Write (w):
    • For Files: Allows modifying or deleting the content of the file. Note: Deleting the file itself often depends on the permissions of the directory containing the file, not the file itself.
    • For Directories: Allows creating new files/subdirectories within the directory, deleting files/subdirectories from the directory, and renaming files/subdirectories within the directory. Requires execute permission (x) as well.
  • Execute (x):
    • For Files: Allows running the file as a program or script (if it is executable).
    • For Directories: Allows entering (accessing) the directory (e.g., using cd) and accessing files or subdirectories within it by name if you know the name. Required in combination with r to list contents effectively and with w to create/delete/rename items.

Viewing Permissions (ls -l):

The ls -l command displays permissions in a standard format at the beginning of each line:

-rwxr-xr-- 1 student student 1024 Oct 26 10:30 my_script.sh
drwxr-x--- 2 student staff    4096 Oct 26 10:35 shared_project

Let's break down the permission string (e.g., -rwxr-xr--):

  1. First Character: File type (- for regular file, d for directory, l for symlink, etc.).
  2. Next Three Characters (rwx): Permissions for the User (Owner). r=read, w=write, x=execute. A hyphen (-) means the permission is denied.
  3. Next Three Characters (r-x): Permissions for the Group. Here, group members can read and execute, but not write.
  4. Last Three Characters (r--): Permissions for Others. Here, others can only read the file.

Octal (Numeric) Representation:

Permissions are often represented using a three-digit octal (base-8) number. Each digit corresponds to User, Group, and Others, respectively. The value of each digit is calculated by summing the values of the granted permissions:

  • r (read) = 4
  • w (write) = 2
  • x (execute) = 1

Examples:

  • rwx = 4 + 2 + 1 = 7
  • r-x = 4 + 0 + 1 = 5
  • rw- = 4 + 2 + 0 = 6
  • r-- = 4 + 0 + 0 = 4
  • --- = 0 + 0 + 0 = 0

So, the permission string -rwxr-xr-- translates to octal 754. The permission string drwxr-x--- translates to octal 750 (applied to a directory).

Changing Permissions (chmod)

The chmod (change mode) command is used to modify the permissions of a file or directory. You must be the owner of the file or the root user to change its permissions. chmod accepts two main modes for specifying permissions:

  1. Symbolic Mode: Uses letters (u, g, o, a for all) and symbols (+ to add, - to remove, = to set exactly) to modify specific permissions.

    • chmod u+x file: Adds execute permission for the user (owner).
    • chmod g-w file: Removes write permission for the group.
    • chmod o=r file: Sets others' permissions to read-only (removes w and x if present, adds r if absent).
    • chmod ug+rw file: Adds read and write permissions for user and group.
    • chmod a+x file: Adds execute permission for all (user, group, others).
    • chmod -R g+r directory: Recursively adds read permission for the group to the directory and all its contents (-R for recursive).
  2. Octal Mode: Uses the three-digit octal representation described above. This sets all permissions explicitly.

    • chmod 755 file: Sets permissions to rwxr-xr-x (owner: rwx, group: r-x, others: r-x). Common for executable scripts and programs.
    • chmod 644 file: Sets permissions to rw-r--r-- (owner: rw-, group: r--, others: r--). Common for non-executable data files.
    • chmod 700 directory: Sets permissions to rwx------ (owner: rwx, group: ---, others: ---). Makes the directory private to the owner.
    • chmod -R 600 directory: Recursively sets permissions on all files/dirs inside to rw-------.

Changing Ownership (chown, chgrp)

  • chown (change owner): Changes the user and/or group ownership of a file or directory. Using it typically requires root privileges (sudo).

    • sudo chown newuser file: Changes only the user owner.
    • sudo chown :newgroup file: Changes only the group owner (note the leading colon).
    • sudo chown newuser:newgroup file: Changes both user and group owner.
    • sudo chown -R user:group directory: Recursively changes ownership for the directory and its contents.
  • chgrp (change group): Changes only the group ownership. Sometimes non-root users can use this if they are the owner of the file and a member of the target group. Often requires sudo.

    • sudo chgrp newgroup file
    • sudo chgrp -R newgroup directory

Special Permissions (SUID, SGID, Sticky Bit)

Beyond the basic rwx permissions, there are three special permission bits:

  1. SUID (Set User ID):

    • Applies only to executable files.
    • When an SUID executable is run, the process runs with the privileges of the file owner, not the user who executed it.
    • Indicated by an s in the user's execute permission slot (rwsr-xr-x). If the owner doesn't have execute permission, it's shown as an uppercase S (rwSr-xr-x), which is usually not useful.
    • Security Risk: SUID programs (especially those owned by root) must be written very carefully, as any vulnerability could grant unauthorized root access.
    • Example: The passwd command (/usr/bin/passwd) is typically SUID root so that normal users can change their own passwords (which requires modifying the protected /etc/shadow file).
    • Octal representation: Add 4000 (e.g., chmod 4755 file).
  2. SGID (Set Group ID):

    • For Executable Files: The process runs with the privileges of the file's group, not the user's primary group. Indicated by an s in the group's execute slot (rwxr-sr-x). Uppercase S (rwxr-Sr-x) if group execute is not set.
    • For Directories: This is more commonly used. When SGID is set on a directory (drwxr-s---):
      • New files created within that directory inherit the group ownership of the directory itself, rather than the primary group of the user creating the file.
      • New subdirectories created within it also inherit the SGID bit.
    • Use Case: Useful for creating shared directories where all files created by members of a specific group should belong to that group, facilitating collaboration.
    • Octal representation: Add 2000 (e.g., chmod 2770 directory).
  3. Sticky Bit:

    • Historically used for executables (keeping them in swap memory), but now primarily used on directories.
    • When set on a directory (drwxrwxrwt), it restricts file deletion. A user can only delete or rename files within that directory if they are the owner of the file, the owner of the directory, or the root user. Even if a user has write permission (w) on the directory (which normally allows deletion), the sticky bit prevents them from deleting other users' files.
    • Indicated by a t in the others' execute permission slot. If others don't have execute permission, it's shown as an uppercase T (drwxrwx--T), which restricts its usefulness.
    • Use Case: Commonly set on world-writable directories like /tmp and /var/tmp to prevent users from maliciously deleting each other's temporary files.
    • Octal representation: Add 1000 (e.g., chmod 1777 /tmp).

Default Permissions (umask)

When a new file or directory is created, it gets default permissions. These defaults are determined by the system's base creation mode modified by the user's umask (user file-creation mode mask).

  • The base default mode is typically 666 (rw-rw-rw-) for files and 777 (rwxrwxrwx) for directories.
  • The umask value specifies permissions that should be removed (or masked out) from the base defaults.
  • Common umask value: 0022 (often written as 022).
    • For files (666): 666 - 022 = 644 (rw-r--r--). The mask 022 means remove write (2) permission for group and others.
    • For directories (777): 777 - 022 = 755 (rwxr-xr-x). The mask 022 means remove write (2) permission for group and others.
  • Another common umask: 0002.
    • Files: 666 - 002 = 664 (rw-rw-r--).
    • Directories: 777 - 002 = 775 (rwxrwxr-x). More permissive for group members.
  • A more restrictive umask: 0077.
    • Files: 666 - 077 = 600 (rw-------).
    • Directories: 777 - 077 = 700 (rwx------). Makes files/dirs private to the owner by default.

You can view your current umask with the umask command. You can set it for your current shell session using umask 0022 (or another desired value). System-wide defaults are usually set in files like /etc/profile or /etc/bashrc, and users can override them in their personal startup files (~/.bashrc, ~/.profile).

Understanding permissions, ownership, and the umask is essential for securing files, collaborating with others, and ensuring programs run with appropriate privileges.

Workshop Managing Permissions and Ownership

This workshop focuses on manipulating file permissions and ownership using chmod, chown, chgrp, and understanding the effect of umask and special permissions.

Prerequisites:

  • Access to a Linux terminal.
  • Ability to use sudo for changing ownership (or coordinate with a system administrator if not possible). If sudo is unavailable, some steps involving chown might need to be skipped or adapted.
  • Ideally, having a second user account available for testing permissions would be beneficial but not strictly required (we can conceptually test).

Steps:

  1. Setup:

    • Navigate to your home directory and create a workshop directory.
    • Command:
      cd ~
      mkdir permissions_workshop
      cd permissions_workshop
      
    • Create a test file and a test directory.
    • Command:
      echo "This is a test file." > data.txt
      mkdir project_dir
      touch project_dir/report.doc
      
  2. Examine Initial Permissions and Ownership:

    • Use ls -l to see the default owner, group, and permissions. Note them down.
    • Command:
      ls -l
      ls -l project_dir
      
    • Check your current umask. Calculate the expected default permissions based on the umask and compare with the actual permissions observed. (Remember: 666 base for files, 777 for directories).
    • Command:
      umask
      
  3. Using chmod (Symbolic Mode):

    • Remove read permission for 'others' from data.txt.
    • Command:
      chmod o-r data.txt
      ls -l data.txt
      
    • Add write permission for the 'group' to data.txt.
    • Command:
      chmod g+w data.txt
      ls -l data.txt
      
    • Set the permissions for project_dir so that only the owner can access it fully (read, write, execute), and no one else has any permissions.
    • Command:
      chmod u=rwx,go= project_dir # Note: go= removes all permissions for group/others
      # Or alternatively: chmod 700 project_dir
      ls -ld project_dir # Use -d to list the directory itself, not its contents
      
  4. Using chmod (Octal Mode):

    • Set permissions on data.txt back to a common default for data files: rw-r--r-- (owner: rw, group: r, others: r). Calculate the octal value (644).
    • Command:
      chmod 644 data.txt
      ls -l data.txt
      
    • Create a simple script file and make it executable only for the owner and group.
    • Command:
      echo '#!/bin/bash' > run_me.sh
      echo 'echo "Script executed!"' >> run_me.sh
      chmod 750 run_me.sh # rwxr-x---
      ls -l run_me.sh
      ./run_me.sh # Try executing it (should work)
      
    • (Conceptual Test): If another user (not in your group) tried to run ./run_me.sh, they should get a "Permission denied" error.
  5. Changing Ownership (Requires sudo):

    • If you cannot use sudo, review these commands conceptually.
    • Check the current owner/group of data.txt.
    • Command:
      ls -l data.txt
      
    • Change the owner to root (or another existing user if preferred).
    • Command:
      sudo chown root data.txt
      ls -l data.txt # Verify owner changed
      
    • Try editing the file as your normal user (this should fail, as you are no longer the owner and likely don't have write permission via group/other).
    • Command:
      echo "Trying to append" >> data.txt # Expected: Permission denied
      
    • Change the group ownership to a common group like staff or users (check available groups with cat /etc/group).
    • Command:
      sudo chgrp users data.txt # Replace 'users' if needed
      ls -l data.txt # Verify group changed
      
    • Change both owner and group back to yourself. Find your username and primary group name using id -u -n and id -g -n.
    • Command:
      MY_USER=$(id -u -n)
      MY_GROUP=$(id -g -n)
      sudo chown $MY_USER:$MY_GROUP data.txt
      ls -l data.txt # Verify ownership restored
      
  6. Testing SGID for Group Collaboration:

    • Create a directory for shared work.
    • Command:
      mkdir shared_docs
      
    • Requires sudo or specific group setup: Change the group ownership of shared_docs to a group that you and potentially another test user belong to (e.g., users or a custom group). Let's assume the group is users.
    • Command:
      sudo chgrp users shared_docs
      
    • Set permissions so that the owner and group members have full access (rwx), and enable the SGID bit. Others should have no access. Octal: 2770.
    • Command:
      chmod 2770 shared_docs
      ls -ld shared_docs # Note the 's' in the group execute position
      
    • Create a file inside shared_docs. Check its group ownership. It should belong to the users group (inherited from the directory), not necessarily your primary group.
    • Command:
      touch shared_docs/meeting_notes.txt
      ls -l shared_docs/
      
    • (Conceptual Test): If another user who is also a member of the users group created a file in shared_docs, it would also belong to the users group, allowing group members to collaborate more easily.
  7. Testing the Sticky Bit:

    • Create a directory intended for temporary, multi-user access.
    • Command:
      mkdir common_tmp
      
    • Make it world-writable and readable/executable by all, and add the sticky bit. Octal: 1777.
    • Command:
      chmod 1777 common_tmp
      ls -ld common_tmp # Note the 't' in the others execute position
      
    • Create a file inside common_tmp as yourself.
    • Command:
      touch common_tmp/my_temp_file.log
      ls -l common_tmp/
      
    • (Conceptual Test / Requires Second User): If a different user created a file (e.g., common_tmp/their_temp_file.log) in common_tmp, you would not be able to delete their_temp_file.log (even though you have write permission on the directory), because you are not the file owner. You can delete my_temp_file.log because you own it.
  8. Testing umask:

    • Check your current umask.
    • Command:
      umask
      
    • Set a more restrictive umask for the current session, e.g., 0077.
    • Command:
      umask 0077
      umask # Verify it changed
      
    • Create a new file and directory. Check their permissions. They should be much more restricted (e.g., rw------- for the file, rwx------ for the directory).
    • Command:
      touch private_file.key
      mkdir private_dir
      ls -l private_file.key private_dir
      
    • Set the umask back to a more common value (e.g., 0022) for the remainder of the session.
    • Command:
      umask 0022
      
  9. Cleanup:

    • Navigate out of the workshop directory and remove it recursively.
    • Command:
      cd ..
      rm -r permissions_workshop
      

This workshop covered the essential commands and concepts for managing access control in the Linux filesystem, including standard permissions, ownership changes, special permission bits (SGID, Sticky Bit), and the role of the umask in setting default permissions.

4. Mounting and Unmounting Filesystems

So far, we've discussed the logical structure (FHS) and the objects within it (files, directories, links, permissions). But where does the actual storage come from? Hard drives, SSDs, USB drives, network shares – these all contain filesystems with data. The process of making the data on these storage devices accessible within the main Linux directory tree (/) is called mounting.

Concept: Mounting is the act of attaching an external or secondary filesystem (located on a device or partition) to a specific directory within the existing filesystem hierarchy. This directory, which serves as the access point for the attached filesystem, is called the mount point.

Imagine the main Linux filesystem (/) as a large building. Mounting is like opening a door (the mount point directory) in that building that leads directly into another separate building (the filesystem on the storage device).

  • Before Mounting: A directory like /mnt/usb_drive might be empty or contain some files belonging to the root filesystem.
  • After Mounting: When a USB drive's filesystem is mounted onto /mnt/usb_drive, the original contents of /mnt/usb_drive become hidden (temporarily inaccessible), and instead, accessing /mnt/usb_drive now shows the root directory of the filesystem on the USB drive.
  • Unmounting: When the filesystem is unmounted, the connection is severed. The mount point directory (/mnt/usb_drive) reverts to showing its original contents (if any), and the USB drive's filesystem is no longer accessible at that location.

Key Components:

  1. Device: The storage medium containing the filesystem you want to access. In Linux, devices are represented by files in the /dev directory (e.g., /dev/sda1 for the first partition on the first SATA/SCSI disk, /dev/nvme0n1p2 for the second partition on the first NVMe drive, /dev/mapper/vg0-lv_home for a logical volume). Network filesystems might use a server/path notation (e.g., server:/exported/path).
  2. Mount Point: An existing, usually empty, directory within the current filesystem hierarchy where the external filesystem will be attached (e.g., /mnt, /media/usb, /home). The root filesystem (/) itself is mounted very early during the boot process.
  3. Filesystem Type: The type of filesystem format used on the device (e.g., ext4, xfs, btrfs for native Linux; vfat or ntfs for Windows compatibility; iso9660 for CD/DVDs; nfs or cifs for network filesystems). The kernel needs to understand the filesystem type to be able to read it.

The mount command

The primary command for mounting filesystems manually is mount. Its basic syntax often looks like:

mount -t <type> -o <options> <device> <mount_point>
  • -t <type>: Specifies the filesystem type. Often, mount can auto-detect the type, so this might be optional. Examples: -t ext4, -t vfat, -t ntfs-3g (for NTFS write support), -t iso9660, -t nfs.
  • -o <options>: Specifies mount options, which are comma-separated keywords that control how the filesystem is mounted. Common options include:
    • ro: Mount read-only. No writing allowed.
    • rw: Mount read-write (usually the default).
    • defaults: A standard set of options, typically equivalent to rw,suid,dev,exec,auto,nouser,async.
    • noexec: Do not allow execution of binaries on the mounted filesystem (security enhancement).
    • nodev: Do not interpret character or block special devices on the filesystem (security).
    • nosuid: Do not allow SUID/SGID bits to take effect (security).
    • user: Allow any user to mount the filesystem (often used in /etc/fstab). nouser is the default, meaning only root can mount.
    • users: Allow any user belonging to the 'users' group to mount/unmount.
    • owner: Allow the device owner to mount/unmount.
    • sync/async: Control how data is written (synchronously - slower but safer immediately; asynchronously - faster, default).
    • loop: Used to mount a file as if it were a block device (useful for ISO images or disk images).
  • <device>: The device file representing the partition or storage (e.g., /dev/sdb1).
  • <mount_point>: The directory where the filesystem will be attached (e.g., /mnt/data). This directory must exist before running mount.

Viewing Mounted Filesystems:

To see which filesystems are currently mounted, where they are mounted, and with which options, you can use:

  • mount: Lists all mounted filesystems, often including virtual filesystems like /proc, /sys, /dev/pts. The output format can be dense.
  • findmnt: A newer utility providing clearer, tree-like output.
  • df -hT or lsblk -f: Shows disk usage, mount points, and filesystem types in a user-friendly format (-h for human-readable sizes, -T for type with df; -f for filesystem info with lsblk).

Example Mounting:

# Assuming /dev/sdb1 is a USB drive formatted with FAT32 (vfat)
# and /mnt/usb_drive directory exists

sudo mkdir /mnt/usb_drive # Create mount point if it doesn't exist
sudo mount -t vfat /dev/sdb1 /mnt/usb_drive

# If auto-detection works:
sudo mount /dev/sdb1 /mnt/usb_drive

# Mount an ISO image file using loop device:
sudo mkdir /mnt/iso
sudo mount -o loop -t iso9660 /path/to/image.iso /mnt/iso

The umount command

To detach a mounted filesystem, use the umount command (note: it's umount, not unmount). You can specify either the device or the mount point.

sudo umount <mount_point>
# Example: sudo umount /mnt/usb_drive

# OR

sudo umount <device>
# Example: sudo umount /dev/sdb1

"Device is Busy" Errors:

You cannot unmount a filesystem if any process is currently using it (e.g., has a file open on it, or has its current working directory set to somewhere within the mounted filesystem). If you attempt to unmount a busy filesystem, you'll get an error like "target is busy".

To find out which processes are using the filesystem, you can use commands like:

  • lsof <mount_point>: Lists open files associated with the mount point.
  • fuser -m <mount_point>: Shows PIDs of processes using the filesystem. fuser -k -m <mount_point> can attempt to kill those processes (use with caution!).

You need to stop these processes or change their working directory before you can successfully unmount the filesystem.

Automatic Mounting (/etc/fstab)

Manually mounting filesystems every time you boot is tedious. The /etc/fstab (file system table) file is used to define filesystems that should be mounted automatically at boot time or made available for easier manual mounting by users.

Each line in /etc/fstab represents a filesystem and typically consists of six fields, separated by spaces or tabs:

<device_spec> <mount_point> <type> <options> <dump> <pass>
  1. <device_spec>: Specifies the device to mount. This can be:

    • Device File: /dev/sda1 (Traditional, but not recommended as names can change if hardware is added/removed).
    • UUID (Universally Unique Identifier): UUID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx (The preferred method, as UUIDs are unique to the filesystem itself and don't change). Use the blkid command (as root) to find the UUID of a filesystem.
    • LABEL: LABEL=DataPartition (Uses a filesystem label, which you can set. More readable than UUID but less guaranteed to be unique). Use blkid or lsblk -f to find labels.
    • Network Path: server:/path/to/share (for NFS).
  2. <mount_point>: The directory where the filesystem should be mounted (e.g., /home, /data, /mnt/backup). Use none for swap partitions.

  3. <type>: The filesystem type (e.g., ext4, xfs, vfat, ntfs, btrfs, swap, nfs, auto to auto-detect).

  4. <options>: Mount options (comma-separated), similar to the -o options for the mount command.

    • defaults: Common starting point (rw,suid,dev,exec,auto,nouser,async).
    • noauto: Do not mount automatically at boot (requires manual mount <mount_point> later).
    • user: Allow any user to mount/unmount this filesystem using mount <mount_point> (implies noauto, nosuid, nodev, noexec unless overridden).
    • nofail: Boot process won't halt if the device is not present. Useful for external drives or network shares that might not always be available.
    • Other options like ro, rw, noexec, owner, group, specific filesystem options (e.g., discard for SSDs).
  5. <dump>: Used by the (rarely used nowadays) dump backup utility. Usually set to 0 (do not dump).

  6. <pass>: Determines the order for filesystem checks (fsck) at boot time.

    • 0: Do not check.
    • 1: Check first (usually only for the root filesystem /).
    • 2: Check after filesystems with 1. Common for other permanent, local filesystems like /home.

Example /etc/fstab entries:

# <device_spec>             <mount_point>  <type>  <options>         <dump> <pass>
UUID=abc...def                /              ext4    errors=remount-ro 0      1
UUID=123...456                /home          ext4    defaults          0      2
UUID=789...abc                none           swap    sw                0      0
/dev/cdrom                    /media/cdrom   iso9660 ro,user,noauto    0      0
//server/share                /mnt/cifs_share cifs   credentials=/etc/cifs.credentials,noauto,user 0 0
LABEL=BackupDrive             /mnt/backup    ntfs    defaults,nofail   0      0
tmpfs                         /tmp           tmpfs   defaults,noatime,mode=1777 0 0 # Mounting /tmp as tmpfs (in RAM)

Caution: Editing /etc/fstab incorrectly can render your system unbootable. Always double-check syntax and ensure mount points exist before rebooting. You can test your /etc/fstab entries without rebooting by running sudo mount -a after saving the file. This command attempts to mount all filesystems listed in /etc/fstab that are not already mounted (and don't have the noauto option).

Mounting provides the essential mechanism for integrating diverse storage resources into a single, navigable filesystem tree, making Linux incredibly flexible in how it handles data storage.

Workshop Mounting Filesystems

In this workshop, we'll simulate adding a new storage device by creating a loop device from a file, formatting it, mounting it manually, and then configuring automatic mounting via /etc/fstab.

Prerequisites:

  • Access to a Linux terminal.
  • Ability to use sudo.
  • Sufficient free space in your home directory (~100MB).

Steps:

  1. Setup and Create a Disk Image File:

    • Navigate to your home directory.
    • Command:
      cd ~
      
    • Create an empty file that will act as our virtual disk image (e.g., 100MB). We use dd for this.
    • Command:
      dd if=/dev/zero of=mydisk.img bs=1M count=100
      # if=input file (/dev/zero provides null bytes)
      # of=output file (our image)
      # bs=block size (1 Megabyte)
      # count=number of blocks
      
    • Verify the file was created and has the correct size.
    • Command:
      ls -lh mydisk.img
      
  2. Format the Disk Image:

    • Format the mydisk.img file with a common Linux filesystem type, like ext4. mkfs.ext4 will treat the file as a block device.
    • Command:
      sudo mkfs.ext4 mydisk.img
      
    • You will likely be prompted about proceeding since mydisk.img is not a block special device. Type y and press Enter.
  3. Create a Mount Point:

    • Create a directory that will serve as the mount point.
    • Command:
      mkdir mydisk_mount
      
  4. Manual Mounting:

    • Mount the formatted disk image file onto the mount point using the loop option.
    • Command:
      sudo mount -o loop mydisk.img mydisk_mount/
      
    • Verify that it's mounted. Check df -hT or findmnt. You should see mydisk.img (or /dev/loopX associated with it) mounted at ~/mydisk_mount with type ext4.
    • Command:
      df -hT | grep mydisk_mount
      findmnt | grep mydisk_mount
      
    • Try creating a file on the mounted filesystem.
    • Command:
      sudo touch mydisk_mount/hello_from_mounted_disk.txt
      ls -l mydisk_mount/
      
    • Observe that only root can write initially, because root did the mount and mkfs. Let's fix ownership so your user can use it.
    • Command:
      sudo chown $(id -u):$(id -g) mydisk_mount/
      touch mydisk_mount/another_file.txt # Should work now
      ls -l mydisk_mount/
      
  5. Manual Unmounting:

    • Unmount the filesystem. Make sure your current directory is not inside mydisk_mount.
    • Command:
      cd ~ # Ensure we are outside the mount point
      sudo umount mydisk_mount
      
    • Verify it's unmounted (df -hT or findmnt should no longer list it). Check the contents of mydisk_mount (it should be empty again).
    • Command:
      df -hT | grep mydisk_mount # Should show nothing
      ls mydisk_mount/ # Should be empty
      
  6. Configure Automatic Mounting via /etc/fstab:

    • Get the UUID: Loop devices don't have stable UUIDs in the same way real partitions do. For this workshop, we'll use the file path directly in /etc/fstab, but be aware that for real partitions, UUID is strongly recommended. (If this were a real partition, say /dev/sdb1, you'd run sudo blkid /dev/sdb1 to get its UUID).
    • Edit /etc/fstab: Extreme Caution: Mistakes in /etc/fstab can prevent your system from booting. Be very careful. Open /etc/fstab with a text editor using sudo.
    • Command (use nano, vim, gedit, etc.):
      sudo nano /etc/fstab
      
    • Add the following line at the end of the file. Replace /home/your_username/mydisk.img with the actual absolute path to your mydisk.img file. Replace /home/your_username/mydisk_mount with the absolute path to your mount point.
      # Mount loop device example (replace paths!)
      /home/your_username/mydisk.img  /home/your_username/mydisk_mount  ext4  loop,defaults,nofail  0 0
      
      • /home/your_username/mydisk.img: The device (our image file)
      • /home/your_username/mydisk_mount: The mount point
      • ext4: Filesystem type
      • loop,defaults,nofail: Options (loop is essential, defaults for standard options, nofail prevents boot issues if the file is missing)
      • 0 0: Dump and Pass values
    • Save the file and exit the editor (e.g., in nano, press Ctrl+X, then Y, then Enter).
  7. Test the /etc/fstab Entry:

    • Use mount -a to mount all filesystems listed in /etc/fstab that aren't already mounted (and don't have noauto).
    • Command:
      sudo mount -a
      
    • Verify that mydisk_mount is now mounted again.
    • Command:
      df -hT | grep mydisk_mount
      ls mydisk_mount/ # Should show the files created earlier
      
    • Unmount it again using the mount point.
    • Command:
      sudo umount ~/mydisk_mount
      
  8. Cleanup:

    • Crucially, remove the line you added from /etc/fstab to avoid potential issues later, especially if you delete the mydisk.img file.
    • Command:
      sudo nano /etc/fstab # Remove the line you added
      # Save and exit
      
    • Remove the mount point directory and the disk image file.
    • Command:
      rmdir mydisk_mount
      rm mydisk.img
      

This workshop demonstrated the lifecycle of mounting: creating a filesystem, mounting it manually using mount (with the loop option for our file-based example), checking the mount status, unmounting with umount, and configuring persistent mounting via /etc/fstab. Remember the importance of using UUIDs for real devices and exercising caution when editing /etc/fstab.

Conclusion Summary and Next Steps

We have journeyed through the core concepts of the Linux filesystem, a fundamental component that underpins nearly every operation within the system. We started with the importance of a standardized layout, exploring the Filesystem Hierarchy Standard (FHS) and the purpose of key directories like /bin, /etc, /usr, /var, and /home. Understanding the FHS provides a crucial map for navigating any Linux system effectively.

Next, we delved into the building blocks: files, directories, and links. We differentiated between regular files, directories, device files, and the mechanisms of hard links (direct inode pointers) and symbolic links (pathname pointers), understanding their respective use cases and limitations. The central role of the inode in storing metadata was highlighted.

We then tackled the critical aspects of access control through permissions and ownership. We examined how user (u), group (g), and other (o) permissions (r, w, x) dictate access, how they are represented symbolically and in octal format, and how to manipulate them using chmod. We also covered changing ownership with chown and chgrp, explored the purpose and implications of special permissions (SUID, SGID, Sticky Bit), and learned how the umask influences default permissions for newly created files and directories.

Finally, we explored how storage devices are integrated into the hierarchy using the mount mechanism. We learned how to manually mount and umount filesystems, specifying device, mount point, type, and options. We also investigated the /etc/fstab file, understanding its structure and role in configuring persistent mounts using stable identifiers like UUIDs.

Mastering these concepts is essential for proficiency in Linux. Whether you are administering servers, developing software, or simply using Linux as your desktop environment, a solid grasp of the filesystem enables you to manage data effectively, troubleshoot problems, secure your system, and understand how different components interact.

Next Steps for Deeper Learning:

  • Specific Filesystem Types: Explore the features, strengths, and weaknesses of common Linux filesystems like Ext4, XFS, and Btrfs (including features like journaling, snapshots, CoW).
  • Disk Management Tools: Learn advanced disk partitioning and management using tools like fdisk, gdisk, parted.
  • Logical Volume Management (LVM): Understand how LVM provides a flexible layer above physical storage, allowing for resizing volumes, creating snapshots, and combining disks.
  • RAID (Redundant Array of Independent Disks): Investigate software RAID (mdadm) for combining multiple disks for performance and/or redundancy.
  • Network Filesystems: Dive deeper into NFS (Network File System) and CIFS/Samba (for Windows interoperability) to understand how filesystems can be shared across a network.
  • Filesystem Checking and Repair: Learn about fsck (filesystem check) and its filesystem-specific variants (e.g., e2fsck, xfs_repair) for diagnosing and fixing filesystem corruption.
  • Advanced Permissions: Explore Access Control Lists (ACLs) (getfacl, setfacl) which offer more granular permission control beyond the basic UGO model.

The Linux filesystem is a rich and powerful system. Continuous exploration and practice with the commands and concepts introduced here will solidify your understanding and empower you to work more effectively within the Linux environment.