Sysadmin basics: Create hard links in Linux (2024)

Posted: October 11, 2022 | | by Alexon Oliveira (Sudoer, Red Hat)

Image

Sysadmin basics: Create hard links in Linux (1)

In previous articles, I discussed how to create and delete files and directories and copy, move, and rename them. These are daily sysadmin tasks, and knowing how to do them brings you one step closer to becoming an enterprise Linux professional who understands the concepts behind every system operation. This gives you an advantage when developing efficient operational tasks. Continuing with that idea, this article discusses hard links in Linux with examples. My next article covers how to create symbolic (soft) links.

[ Keep your most commonly used commands handy with the Linux commands cheat sheet. ]

What are hard links, and how do sysadmins use them? Before covering links, I'll provide some background concepts about using them.

Skip to bottom of list

Understand index nodes

My buddy Tyler Carrigan did a great job writing about index notes (inodes), and that article will expand your knowledge on something I touch on here. Understanding inodes is important because of the intrinsic nature of file and directory links in the Linux filesystem.

Inodes are data structures that describe a filesystem object, such as a file or directory, and store all the metadata pertaining to the file or directory (such as time stamps, block maps, or extended attributes). You can read more about this in the kernel documentation. Each inode has its own address in the system. When you manipulate hard and soft links, you also deal with the inodes of the original files and directories.

Consider the following information from my virtual machine's (VM's) single disk:

$ sudo fdisk -l | head -10Disk /dev/vda: 20 GiB, 21474836480 bytes, 41943040 sectorsUnits: sectors of 1 * 512 = 512 bytesSector size (logical/physical): 512 bytes / 512 bytesI/O size (minimum/optimal): 512 bytes / 512 bytesDisklabel type: dosDisk identifier: 0x7a1c2d8bDevice Boot Start End Sectors Size Id Type/dev/vda1 * 2048 2099199 2097152 1G 83 Linux/dev/vda2 2099200 41943039 39843840 19G 8e Linux LVM

My VM's disk has a size of 20GiB. This available space is divided into 41,943,040 sectors of 512B each, with a disk block size of 4KiB. This means that every single file I create, whether smaller or larger than 4KiB, will consume at least eight sectors for each corresponding 4KiB chunk of disk block size consumed by my file. The sector addresses consumed by the file will be indexed and referenced by the corresponding inode address that the file receives from the filesystem. This makes it easy to find the file and its metadata on my system.

[ Learn how to manage your Linux environment for success. ]

I'll demonstrate by creating a simple directory and displaying its inode and size information:

$ mkdir dir$ ls -litotal 025606589 drwxrwxr-x. 2 localuser localuser 6 set 19 15:21 dir$ stat dir File: dir Size: 6 Blocks: 0 IO Block: 4096 directoryDevice: fd00h/64768dInode: 25606589 Links: 2Access: (0775/drwxrwxr-x) Uid: ( 1000/localuser) Gid: ( 1000/localuser)Context: unconfined_u:object_r:user_home_t:s0Access: 2022-09-19 15:21:27.616000000 -0300Modify: 2022-09-19 15:21:27.616000000 -0300Change: 2022-09-19 15:21:27.616000000 -0300 Birth: 2022-09-19 15:21:27.616000000 -0300

Use the ls command with the -i option to display inode information. Above, you can see that the inode address of the given dir directory is 25606589. I can confirm that and check other metadata information with the stat command. I'll create a file inside this directory and check the information:

$ touch dir/file$ stat dir File: dir Size: 18 Blocks: 0 IO Block: 4096 directoryDevice: fd00h/64768dInode: 25606589 Links: 2Access: (0775/drwxrwxr-x) Uid: ( 1000/localuser) Gid: ( 1000/localuser)Context: unconfined_u:object_r:user_home_t:s0Access: 2022-09-19 15:29:37.495000000 -0300Modify: 2022-09-19 15:29:40.276000000 -0300Change: 2022-09-19 15:29:40.276000000 -0300 Birth: 2022-09-19 15:21:27.616000000 -0300$ ls -li dir/file25606591 -rw-rw-r--. 1 localuser localuser 0 set 19 15:29 dir/file$ stat dir/file File: dir/file Size: 0 Blocks: 0 IO Block: 4096 regular empty fileDevice: fd00h/64768dInode: 25606591 Links: 1Access: (0664/-rw-rw-r--) Uid: ( 1000/localuser) Gid: ( 1000/localuser)Context: unconfined_u:object_r:user_home_t:s0Access: 2022-09-19 15:29:40.276000000 -0300Modify: 2022-09-19 15:29:40.276000000 -0300Change: 2022-09-19 15:29:40.276000000 -0300 Birth: 2022-09-19 15:29:40.276000000 -0300

The file has its own inode address of 25606591. Its size is 0 because it has no contents yet. I'll add a single byte of data and see what happens:

$ echo 1 > dir/file$ stat dir/file File: dir/file Size: 2 Blocks: 8 IO Block: 4096 regular fileDevice: fd00h/64768dInode: 25606591 Links: 1Access: (0664/-rw-rw-r--) Uid: ( 1000/localuser) Gid: ( 1000/localuser)Context: unconfined_u:object_r:user_home_t:s0Access: 2022-09-19 15:29:40.276000000 -0300Modify: 2022-09-19 15:36:18.812000000 -0300Change: 2022-09-19 15:36:18.812000000 -0300 Birth: 2022-09-19 15:29:40.276000000 -0300

Skip to the bottom of list

Image

Download now

Now the file is consuming eight sectors, even though I only added 1B of data. That's because I'm working with the default 4KiB block disk size and 512B sector size. But the inode address remains the same, and that's important because, regardless of the size of the file, it will always be referenced by its inode address, not each individual sector it consumes.

Also, if I copy of this file, the duplicate will have its own inode address and will consume eight extra sectors:

$ cp dir/file dir/copy$ stat dir/file File: dir/file Size: 2 Blocks: 8 IO Block: 4096 regular fileDevice: fd00h/64768dInode: 25606591 Links: 1Access: (0664/-rw-rw-r--) Uid: ( 1000/localuser) Gid: ( 1000/localuser)Context: unconfined_u:object_r:user_home_t:s0Access: 2022-09-19 15:42:17.328000000 -0300Modify: 2022-09-19 15:36:18.812000000 -0300Change: 2022-09-19 15:36:18.812000000 -0300 Birth: 2022-09-19 15:29:40.276000000 -0300$ stat dir/copy File: dir/copy Size: 2 Blocks: 8 IO Block: 4096 regular fileDevice: fd00h/64768dInode: 25811328 Links: 1Access: (0664/-rw-rw-r--) Uid: ( 1000/localuser) Gid: ( 1000/localuser)Context: unconfined_u:object_r:user_home_t:s0Access: 2022-09-19 15:42:17.328000000 -0300Modify: 2022-09-19 15:42:17.328000000 -0300Change: 2022-09-19 15:42:17.328000000 -0300 Birth: 2022-09-19 15:42:17.328000000 -0300

Now that you understand the concept, what if you just want to reference a file with a different name or in a different location without changing the original inode address or any other metadata information? Or perhaps you want to change the inode address but want access to the same information provided by the original file or directory?

That's where the link creation feature comes into play! There are two different ways to create links to files or directories in the system: hard links and symbolic links. This article covers hard links.

Skip to bottom of list

Create hard links

When you're creating a hard link, you're creating another file (with a different name) that points to the exact same data as the original file. That means it acts as the original file, and you cannot differentiate between the new hard link and the original name of the file.

It's basically a mirror copy of the original file. They both have the same content, permissions, and inode address. Be aware that any changes made in one file affect the other file in the same way, except for deletion, which will not impact the original data. When you delete the original file, and there's at least one hard link alive, you can still access the original data until all hard links have been deleted.

However, hard links have limitations. You cannot create hard links for directories or create a hard link in a different filesystem from the original file.

[ Get the guide to installing applications on Linux. ]

The ln command creates links. Use the -h option to see its available parameters.

To create a hard link, type ln {source} {target}, like this:

$ ls /tmp/$ ln dir/file /tmp/hard$ ls -l /tmp/total 4-rw-rw-r--. 2 localuser localuser 2 set 19 15:36 hard

To prove this hard link is a mirror of the original file, check its metadata information, content, and inode address:

$ ls -i dir/file25606591 dir/file$ ls -i /tmp/hard25606591 /tmp/hard$ stat dir/file File: dir/file Size: 2 Blocks: 8 IO Block: 4096 regular fileDevice: fd00h/64768dInode: 25606591 Links: 2Access: (0664/-rw-rw-r--) Uid: ( 1000/localuser) Gid: ( 1000/localuser)Context: unconfined_u:object_r:user_home_t:s0Access: 2022-09-19 15:42:17.328000000 -0300Modify: 2022-09-19 15:36:18.812000000 -0300Change: 2022-09-19 16:49:20.216000000 -0300 Birth: 2022-09-19 15:29:40.276000000 -0300$ stat /tmp/hard File: /tmp/hard Size: 2 Blocks: 8 IO Block: 4096 regular fileDevice: fd00h/64768dInode: 25606591 Links: 2Access: (0664/-rw-rw-r--) Uid: ( 1000/localuser) Gid: ( 1000/localuser)Context: unconfined_u:object_r:user_home_t:s0Access: 2022-09-19 15:42:17.328000000 -0300Modify: 2022-09-19 15:36:18.812000000 -0300Change: 2022-09-19 16:49:20.216000000 -0300 Birth: 2022-09-19 15:29:40.276000000 -0300

Both results have the same information. Adding any data to the hard link will change the original file as well:

$ cat dir/file1$ cat /tmp/hard1$ echo 0 > /tmp/hard$ cat /tmp/hard0$ cat dir/file0

If you delete the original file, the hard link remains with the original data and you can keep using it:

$ rm dir/file$ ls dir/$ cat /tmp/hard0

The same would happen if you deleted the hard link and kept the original file.

Wrap up

In certain scenarios, it is better to use hard links instead of copying the original data, which will duplicate the content in your system and consume sectors. Read my follow up article on how symbolic links work and how they compare to hard links.

[ Cheat sheet: Get a list of Linux utilities and commands for managing servers and networks. ]

Topics: Certification Red Hat Enterprise Linux (RHEL) Linux

Sysadmin basics: Create hard links in Linux (2024)
Top Articles
Latest Posts
Article information

Author: Barbera Armstrong

Last Updated:

Views: 5809

Rating: 4.9 / 5 (79 voted)

Reviews: 86% of readers found this page helpful

Author information

Name: Barbera Armstrong

Birthday: 1992-09-12

Address: Suite 993 99852 Daugherty Causeway, Ritchiehaven, VT 49630

Phone: +5026838435397

Job: National Engineer

Hobby: Listening to music, Board games, Photography, Ice skating, LARPing, Kite flying, Rugby

Introduction: My name is Barbera Armstrong, I am a lovely, delightful, cooperative, funny, enchanting, vivacious, tender person who loves writing and wants to share my knowledge and understanding with you.