8.5 Hard Links vs. Symbolic Links: ln & Inodes (104.6)
Key Takeaways
- In Linux filesystems, an Inode (Index Node) stores all file metadata (size, UID, GID, mode, timestamps, block pointers) but does NOT store the filename.
- Directory entries (dentries) map human-readable filenames to inode numbers; inspecting inode numbers is done with `ls -i` or `stat <file>`.
- A Hard Link (`ln target linkname`) creates a new directory entry pointing to an existing inode number; all hard links to an inode are equal peers sharing identical data blocks and link counts.
- Hard links have two fundamental limitations: they CANNOT span across different filesystems/partitions (inodes are local to a single filesystem), and they CANNOT point to directories.
- A Symbolic Link / Soft Link (`ln -s target linkname`) is an independent file with its own unique inode containing the target path string; symlinks CAN span filesystems, CAN link to directories, but become dangling if the target is moved or deleted.
8.5 Hard Links vs. Symbolic Links: ln & Inodes
Quick Summary: In Linux, files are not identified internally by their names, but by unique numerical identifiers called Inodes (Index Nodes). A filename is merely a human-friendly pointer recorded inside a directory file. The
lncommand creates links between filenames and storage data. Linux supports two fundamentally different link types: Hard Links, which create additional directory entries pointing directly to an existing inode on the same filesystem, and Symbolic Links (Soft Links), which are distinct files containing a path string pointing to another target. Understanding inode mechanics, link count rules during file deletion, cross-device boundaries, and relative path pitfalls is vital for LPIC-1 Topic 104.6.
1. Linux Filesystem Architecture: Inodes & Directory Entries
To understand links, one must understand how Linux stores files on disk. A filesystem partition divides storage into two primary areas:
- Data Blocks: Physical sectors on disk where the actual content (text, binary payload, audio) is stored.
- Inode Table: A structured table of metadata records. Each file on the filesystem is represented by exactly one Inode.
Inode Metadata Storage Architecture:
┌─────────────────────────────────────────────────────────┐
│ Inode Structure │
├─────────────────────────────────────────────────────────┤
│ • Inode Number (e.g., Inode #142857) │
│ • File Type (Regular, Directory, Symlink, Socket, etc.) │
│ • File Permissions (DAC mode: rwxr-xr-x) │
│ • User Owner (UID) and Group Owner (GID) │
│ • File Size (in bytes) │
│ • Timestamps: atime (access), mtime (modify), ctime │
│ • Hard Link Count (number of dentries pointing here) │
│ • Pointers to Data Blocks on Physical Disk │
├─────────────────────────────────────────────────────────┤
│ ⚠️ CRITICAL: The FILENAME is NOT stored in the Inode! │
└─────────────────────────────────────────────────────────┘
What is a Directory?
In Linux, a directory is simply a special file containing a lookup table of Directory Entries (dentries). Each dentry maps a string filename to an Inode number:
Directory Data Table (/home/user/):
┌────────────────────────┬──────────────┐
│ Filename (dentry) │ Inode Number │
├────────────────────────┼──────────────┤
│ . │ 1048576 │
│ .. │ 524288 │
│ project.txt │ 1048580 │
│ backup_link.txt │ 1048580 │ <── Same Inode (Hard Link!)
│ shortcut.lnk │ 1048595 │ <── Distinct Inode (Symlink!)
└────────────────────────┴──────────────┘
Inspecting Inodes with ls -i and stat
# Inspect inode numbers using ls -i:
$ ls -li project.txt
1048580 -rw-r--r-- 2 admin staff 1024 Aug 29 10:00 project.txt
# │ │
# └─ Inode Number └─ Link Count = 2
# Detailed metadata inspection using stat:
$ stat project.txt
File: project.txt
Size: 1024 Blocks: 8 IO Block: 4096 regular file
Device: 8,1 Inode: 1048580 Links: 2
Access: (0644/-rw-r--r--) Uid: ( 1000/ admin) Gid: ( 1000/ staff)
Access: 2026-08-29 10:00:00.000000000 -0700
Modify: 2026-08-29 10:00:00.000000000 -0700
Change: 2026-08-29 10:05:00.000000000 -0700
2. Hard Links: Peer Pointers to a Single Inode
A Hard Link is an additional directory entry that points to an existing inode number. Creating a hard link does not allocate a new inode or copy any file data blocks.
# Syntax: ln <target_file> <link_name>
$ ln original.txt hardlink.txt
Hard Link Data Architecture:
"original.txt" ───┐
├───> Inode #1048580 (Link Count: 2) ───> [Physical Data Blocks]
"hardlink.txt" ───┘
Key Technical Characteristics of Hard Links:
- Equal Peers: Neither file is the "original." Both
original.txtandhardlink.txtare identical, first-class names for the same inode. - Shared Permissions and Data: Modifying the content, permissions (
chmod), or ownership (chown) via either name immediately affects both, because there is only one underlying inode. - Link Count Increment: Creating a hard link increments the inode's Hard Link Count by 1.
- Deletion Semantics: Executing
rm original.txtdoes not delete the data on disk! It only removes that specific directory entry and decrements the link count in Inode #1048580 from 2 to 1. The data remains accessible viahardlink.txt. The kernel frees data blocks only when the link count reaches 0 AND no running process holds an open file handle to that inode.
Hard Link Limitations (Critical LPIC-1 Focus)
Hard links have two strict, kernel-enforced limitations:
- CANNOT Cross Filesystem / Partition Boundaries: Inode numbers are unique only within a single filesystem. Inode #142 on
/dev/sda1is completely unrelated to Inode #142 on/dev/sdb1. Attempting to hard link across filesystems fails withln: failed to create hard link: Invalid cross-device link. - CANNOT Point to Directories: To prevent recursive filesystem loops and infinite directory traversal cycles, the Linux kernel forbids standard users and administrators from creating hard links to directories (the only exceptions are the
.and..directory entries maintained internally by the kernel).
3. Symbolic Links (Soft Links): Path Pointers
A Symbolic Link (Symlink / Soft Link) is an independent, special file (file type l) with its own unique Inode number. Its data block contains only a text string representing the target file or directory path.
# Syntax: ln -s <target_path> <link_name>
$ ln -s /var/log/nginx/access.log /home/admin/nginx_log
Symbolic Link Architecture:
"shortcut.lnk" ───> Inode #1048595 ───> String: "/var/log/nginx/access.log"
│
▼
[Target Inode & Data]
Key Technical Characteristics of Symbolic Links:
- Independent Inode: The symlink has its own distinct inode number (
ls -lishows a different inode). - Permission Display:
ls -lshowslrwxrwxrwxpermissions for symlinks. However, these dummy permissions are ignored by the kernel; access is governed entirely by the permissions of the target file. - Cross-Filesystem Capability: Symlinks can freely point across different disk partitions, storage devices, and network mounts.
- Directory Support: Symlinks can point to directories, making them ideal for creating shortcuts to deep directory paths.
- Dangling (Broken) Symlinks: If the target file is renamed, moved, or deleted, the symlink continues to point to the old path string, becoming a broken/dangling link.
# Identifying target with readlink:
$ readlink /home/admin/nginx_log
/var/log/nginx/access.log
# Overwriting an existing symlink destination with -f (--force):
$ ln -sf /var/log/nginx/error.log /home/admin/nginx_log
4. Hard Links vs. Symbolic Links: Direct Comparison
| Architectural Feature | Hard Link (ln) | Symbolic Link (ln -s) |
|---|---|---|
| Inode Allocation | Shares existing Inode number with target | Allocates a new, unique Inode |
| Cross-Filesystem Support | ❌ No (Fails with Invalid cross-device link) | ✅ Yes (Freely crosses partition boundaries) |
| Directory Linking | ❌ No (Forbidden by kernel to prevent loops) | ✅ Yes (Supported) |
| Target File Deleted | ✅ Data preserved via remaining link name | ❌ Becomes broken / dangling link |
| Disk Storage Overhead | Zero additional data blocks (only dentry) | Consumes 1 inode + small text data block |
File Type in ls -l | Regular file (-) | Symbolic link (l) |
| Permission Handling | Linked to target (shares single mode) | Displays lrwxrwxrwx (governed by target) |
5. Relative Symlink Path Resolution Mechanics
A notorious LPIC-1 trap involves relative path resolution when creating symlinks.
⚠️ LPIC-1 Trap — Relative Path Symlink Evaluation: When creating a relative symbolic link, the target path is resolved relative to the directory containing the symlink, NOT relative to your current shell working directory!
# Suppose your current working directory is /home/admin/:
$ pwd
/home/admin
# INCORRECT: Creating a symlink in /tmp pointing to 'data.txt':
$ ln -s data.txt /tmp/data_link
# FAILS: The symlink in /tmp looks for /tmp/data.txt, NOT /home/admin/data.txt!
# CORRECT Option 1: Use an absolute path
$ ln -s /home/admin/data.txt /tmp/data_link
# CORRECT Option 2: Use relative navigation from /tmp
$ ln -s ../home/admin/data.txt /tmp/data_link
💡 LPIC-1 Exam Fill-in-the-Blank Alert: What command and option creates a symbolic link named
/opt/bin/runpointing to the target script/usr/local/bin/app_engine? Answer:ln -s /usr/local/bin/app_engine /opt/bin/run
A system administrator created a hard link to a file: ln /data/file1.txt /data/file2.txt. Later, the administrator executes rm /data/file1.txt. What happens to /data/file2.txt and the underlying data?
An administrator executes the command ln /mnt/storage/report.pdf /home/user/report.pdf, but the command fails with the error ln: failed to create hard link: Invalid cross-device link. What is the cause of this error?
An administrator working in /home/developer runs the command ln -s config.json /etc/app/config.json. When an application tries to read /etc/app/config.json, the read fails with No such file or directory. What caused this failure?