Book: LPI Linux Certification in a Nutshell
Section: Chapter 4.  Devices, Linux Filesystems, and the Filesystem Hierarchy Standard (Topic 2.4)



4.7 Objective 7: Create and Change Hard and Symbolic Links

A link is a pseudofile that creates a shortcut to the original file located elsewhere on the filesystem. Links don't take up very much space, as they don't contain any real data. While the concept of links may seem a little odd, they are very useful and can be used for anything from creating a shortcut, to launching an application, to mirroring the kernel's source.

There are two types of links used on Linux:

Symbolic links

A symbolic link is really a tiny file that contains a pointer to another file. When Linux opens a symbolic link, it reads the pointer and then finds the intended file that contains the actual data. Symbolic links can point to other filesystems, both local and on networked computers, and they can point to directories. They are clearly listed as being a link with the ls -l command by displaying a special "l" (a lowercase L) in column one, and they have no file protections of their own (the actual file's permissions are used instead). Note that if a file with a symbolic link is deleted, then the symbolic link points to nothing and is said to be stale.

Hard links

A hard link is not really a "link" at all, but a copy of another directory entry. The two directory entries have different names but point to the same inode and thus to the same actual data, ownership, permissions, and so on. In fact, if a file with a hard link is deleted, the link remains, still pointing to the valid inode. Except for its name, including its location in the directory hierarchy, the link is indistinguishable from the original file.

Hard links have two important limitations. First, because they share inodes, files and any hard links to them must reside on the same filesystem (inode numbers aren't expected to be unique across filesystems). Second, hard links cannot point to directories. However, hard links take no disk space beyond an additional directory entry.

Symbolic links are used more often than hard links because they are more versatile and easier to manage, yet still consume a trivial amount of disk space.

4.7.1 Why Links?

To see an example of the use of links in practice, consider the directories in /etc/rc.d:

drwxr-xr-x   2 root     root     1024 Dec 15 23:05 init.d
-rwxr-xr-x   1 root     root     2722 Apr 15  1999 rc
-rwxr-xr-x   1 root     root      693 Aug 17  1998 rc.local
-rwxr-xr-x   1 root     root     9822 Apr 13  1999 rc.sysinit
drwxr-xr-x   2 root     root     1024 Dec  2 09:41 rc0.d
drwxr-xr-x   2 root     root     1024 Dec  2 09:41 rc1.d
drwxr-xr-x   2 root     root     1024 Dec 24 15:15 rc2.d
drwxr-xr-x   2 root     root     1024 Dec 24 15:15 rc3.d
drwxr-xr-x   2 root     root     1024 Dec 24 15:16 rc4.d
drwxr-xr-x   2 root     root     1024 Dec 24 15:16 rc5.d
drwxr-xr-x   2 root     root     1024 Dec 14 23:37 rc6.d

Inside init.d are scripts to start and stop many of the services on your system, such as httpd, cron, and syslog. Some of these files are to be executed with a start argument, while others are run with a stop argument, depending upon the runlevel of your system. To determine just which files are run and what argument they receive, a scheme of additional directories has been devised. These directories are named rc0.d through rc6.d, one for each runlevel (see Chapter 5 Boot, Initialization, Shutdown, and Runlevels (Topic 2.6), for a complete description of this scheme). Each of the runlevel-specific directories contains several links, each with a name that helps determine the configuration of services on your system. For example, rc3.d contains the following links, among many others:

S30syslog -> ../init.d/syslog
S40crond -> ../init.d/crond
S85httpd -> ../init.d/httpd

All of these links point back to the scripts in init.d as indicated by the arrows (->) after the script name. If these links were copies of the scripts, editing would be required for all of the runlevel-specific versions of the same script just to make a single change. Instead, links allow us to:

  • Make changes to the original file once. References to the links will yield the updated contents as long as the filename doesn't change.

  • Avoid wasting disk space by having multiple copies of the same file in different places for "convenience."

As another example, consider the directory for the kernel source, /usr/src/linux :

linux -> linux-2.2.10
linux-2.2.10

Makefiles and other automated tools can refer to /usr/src/linux, but in reality, they reference /usr/src/linux-2.2.10. If a new kernel is added, say Version 2.2.14, its source would be placed into an appropriately named directory and the linux link would be reset, as follows:

linux -> linux-2.2.14
linux-2.2.10
linux-2.2.14

Now the appropriate directory can be selected simply by changing the link. No files need to be moved or deleted. Once created, links are normal directory entries, which may be copied, renamed, deleted, and backed up.

Symbolic and hard links are created with the ln command.

ln

Syntax

ln [options] file link
ln [options] files directory

Description

Create links between files. In the first form, a new link is created to point to file, which must already exist. In the second form, links are created in directory for all files specified.

Frequently used options

-f

Overwrite (force) existing links, or existing files in the destination directory.

-i

Prompt interactively before overwriting destination files.

-s

Create a symbolic link rather than a hard link; this is the default.

Example 1

Note that the Bourne shell sh on a Linux system is a symbolic link to bash:

$ ls -l /bin/bash /bin/sh
/bin/bash
/bin/sh -> bash

Example 2

Create a file named myfile, a symbolic link to that file named myslink, and a hard link to that file named myhlink, then examine them:

$ touch myfile
$ ln -s myfile myslink
$ ln myfile myhlink
$ ls -l my*
-rw-r--r--   2 jdoe  jdoe  0 Jan  3 13:21 myfile
-rw-r--r--   2 jdoe  jdoe  0 Jan  3 13:21 myhlink
lrwxrwxrwx   1 jdoe  jdoe  6 Jan  3 13:21 myslink -> myfile

Using the stat command on my* demonstrates that they all ultimately reference the same inode (the inode numbers are the same) and indicates the number of links to the file (two links, one symbolic and one hard):

# stat my*
File: "myfile"
  Size: 0            Filetype: Regular File
  Mode: (0644/-rw-r--r--) Uid: (0/ root)  Gid: (0/ root)
Device:  8,6   Inode: 30        Links: 2
Access: Mon Jan  3 14:33:04 2000(00000.00:06:05)
Modify: Mon Jan  3 14:33:04 2000(00000.00:06:05)
Change: Mon Jan  3 14:33:25 2000(00000.00:05:44)

  File: "myhlink"
  Size: 0            Filetype: Regular File
  Mode: (0644/-rw-r--r--) Uid: (0/ root)  Gid: (0/ root)
Device:  8,6   Inode: 30        Links: 2
Access: Mon Jan  3 14:33:04 2000(00000.00:06:05)
Modify: Mon Jan  3 14:33:04 2000(00000.00:06:05)
Change: Mon Jan  3 14:33:25 2000(00000.00:05:44)

  File: "myslink"
  Size: 0            Filetype: Regular File
  Mode: (0644/-rw-r--r--) Uid: (0/ root)  Gid: (0/ root)
Device:  8,6   Inode: 30        Links: 2
Access: Mon Jan  3 14:33:04 2000(00000.00:06:05)
Modify: Mon Jan  3 14:33:04 2000(00000.00:06:05)
Change: Mon Jan  3 14:33:25 2000(00000.00:05:44)

However, the symbolic link has an inode of its own, which is displayed using the -i option to ls:

# ls -li my*
30 -rw-r--r--   2 root root  0 Jan  3 14:33 myfile
30 -rw-r--r--   2 root root  0 Jan  3 14:33 myhlink
41 lrwxrwxrwx   1 root root  6 Jan  3 14:33 myslink -> myfile

Here you can see that the directory entries for myfile and myhlink both point to inode 30, while the directory entry for myslink points to inode 41. That inode contains the symbolic link to myfile.

As another example, consider the two filesystems in Figure 4-4. The root partition on /dev/sda1 holds a file intended as an example bash startup file, located in /etc/bashrc_user. On the same filesystem, the root user has elected to use /etc/bashrc_user. Not wanting to maintain both files individually, root has created a hard link, /root/.bashrc, to the example file. Both of the directory entries, /etc/bashrc_user and /root/.bashrc, point to the same text data in the same file, described by the same inode, on /dev/sda1. User jdoe has also elected to link to the example file. However, since his home directory is located in /home on /dev/sda9, jdoe cannot use a hard link to the file on /dev/sda1. Instead, he created a symbolic link, /home/jdoe/.bashrc, which points to a small file on /dev/sda9. This contains the pointer to directory entry /etc/bashrc_user, which finally points at the text. The result for root and jdoe is identical, though the two styles of links implement the reference in completely different ways.

Figure 4-4. Hard and symbolic links
figs/lpi_0404.gif
4.7.1.1 Preserving links

Programs such as tar and cp contain options that control whether symbolic links are followed during operation. In the case of a tar backup, this may be important if you have multiple links to large files, because you would get many redundant backups of the same data.

When a symbolic link is encountered with cp , the contents of the file to which the link points are copied unless the -d option is specified. This "no dereference" operator causes cp to copy the links themselves instead. For example, consider a directory dir1 containing a symbolic link, which is recursively copied to other directories with and without the -d option:

# ls -l dir1
total 13
lrwxrwxrwx 1 root root      19 Jan  4 02:43 file1 -> /file1
-rw-r--r-- 1 root root   10240 Dec 12 17:12 file2
# cp -r dir1 dir2
# ls -l dir2
total 3117
-rw-r--r-- 1 root root 3164160 Jan  4 02:43 file1
-rw-r--r-- 1 root root   10240 Jan  4 02:43 file2
# cp -rd dir1 dir3
# ls -l dir3
total 13
lrwxrwxrwx 1 root root      19 Jan  4 02:43 file1 -> /file1
-rw-r--r-- 1 root root   10240 Jan  4 02:43 file2

Directory dir2 has a copy of the entire file1, which is large, probably wasting disk space. Directory dir3, created with cp -rd, is the same as dir1 (including the symbolic link) and takes very little space.

4.7.1.2 Finding links to a file

Finding the file pointed to by a symbolic link is simple. The ls -l command displays a convenient pointer notation, indicating just where links are pointing:

lrwxrwxrwx 1 root root      19 Jan  4 02:43 file1 -> /file1

Going the other way and finding symbolic links to a file is less obvious but is still relatively easy. The -lname option to the find utility locates them for you by searching for symbolic links containing the original filename. Here, the entire local filesystem is searched for myfile, turning up three symbolic links:

# find / -lname myfile
/home/world/rootsfile
/home/finance/hisfile
/root/myslink

Remember that symbolic links could be anywhere, including being located on a remote system (if you're sharing files), so you may not be able to locate them all. (SeeSection 3.1 for additional information on the find command).

Since hard links aren't really links, but duplicate directory entries, you can locate them by searching directory entries for the inode, which is identical in all the links. Unlike symbolic links, you are guaranteed to find all of the links since hard links cannot cross filesystem boundaries. First, identify the inode you're interested in, as well as the filesystem that contains the links:

# df file1
Filesystem    1k-blocks      Used Available Use% Mounted on
/dev/sda9       1981000    451115   1427473  24% /home
# ls -i file
90469 file1

Here, file1 is on the /home filesystem, and its inode number is 90469. Next, find is used with the -inum option to locate all instances of inode 90469:

# find /home -inum 90469
/home/world/file1
/home/finance/file1
/home/jdoe/private/.myfile1

This example turns up three links to file1, including one that user jdoe appears to be hiding!

On the Exam

You should be prepared to identify the differences between hard and symbolic links, when each is used, and their limitations.