Often it is useful to have access to a file in multiple locations in a filesystem. To avoid creating multiple copies of the file, use a link. Links don't take up very much space, as they only add a bit of metadata to the filesystem, so they're much more efficient than using separate copies.
There are two types of links used on Linux:
A symbolic link is simply a pointer to another filename. 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 remote, 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).
A symbolic link can point to a filename that does not actually exist. Such a symbolic link is said to be broken or stale.
A hard link is not really a link at all. It is simply another directory entry for an existing file. 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, when you delete a file, you are only removing a directory entry (in other words, one hard link to the file). As long as any directory entries remain, the file's inode is not actually deleted. In fact, a file is not deleted until its link count drops to zero (and the file is no longer open for reading or writing).
Hard links have two important limitations. First, because all of the links to a file point to the same inode, any hard links must by definition reside on the same filesystem. Second, hard links cannot point to directories. However, hard links take no disk space beyond an additional directory entry.
To see an example of the use of links in practice, consider the directories in /etc/rc.d on a typical Red Hat system:
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, crond, and syslogd. Some of these files are to be executed with a start argument, while others are run with a stop argument, depending on 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 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, /lib/modules/
kernel_version
/build:
build -> /usr/src/linux-2.4.18
Makefiles and other automated tools for building third-party kernel modules can refer to /lib/modules/'uname -r'/build, but in reality they reference /usr/src/linux-2.4.18. If a new kernel is added, say version 2.4.20, its source would be placed into an appropriately named directory and the build link in the new modules directory would be set, as follows:
build -> /usr/src/linux-2.4.20
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
ln [options] file link
ln [options] files directory
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.
Hard links are created unless the -s option is specified.
Overwrite (force) existing links, or existing files in the destination directory
.
Prompt interactively before overwriting destination files.
Create a symbolic link rather than a hard link.
Note that the Bourne shell sh on a Linux system is a symbolic link to bash:
$ ls -l /bin/bash /bin/sh
-rwxr-xr-x 1 root root 626028 Feb 11 07:34 /bin/bash
lrwxrwxrwx 1 root root 4 Feb 23 10:24 /bin/sh -> bash
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 myfile and myhlink both ultimately reference the same inode (the inode numbers are the same) and indicates the number of hard links to the file:
# stat my*
File: 'myfile'
Size: 0 Blocks: 0 IO Block: 4096 Regular File
Device: 3a05h/14853d Inode: 1212467 Links: 2
Access: (0644/-rw-r--r--) Uid: ( 0/ root) Gid: ( 0/ root)
Access: 2003-03-15 21:36:33.000000000 -0600
Modify: 2003-03-15 21:36:33.000000000 -0600
Change: 2003-03-15 21:36:33.000000000 -0600
File: 'myhlink'
Size: 0 Blocks: 0 IO Block: 4096 Regular File
Device: 3a05h/14853d Inode: 1212467 Links: 2
Access: (0644/-rw-r--r--) Uid: ( 0/ root) Gid: ( 0/ root)
Access: 2003-03-15 21:36:33.000000000 -0600
Modify: 2003-03-15 21:36:33.000000000 -0600
Change: 2003-03-15 21:36:33.000000000 -0600
File: 'myslink' -> 'myfile'
Size: 6 Blocks: 0 IO Block: 4096 Symbolic Link
Device: 3a05h/14853d Inode: 1213365 Links: 1
Access: (0777/lrwxrwxrwx) Uid: ( 0/ root) Gid: ( 0/ root)
Access: 2003-03-15 21:36:33.000000000 -0600
Modify: 2003-03-15 21:36:33.000000000 -0600
Change: 2003-03-15 21:36:33.000000000 -0600
Note that the symbolic link has an inode of its own, which can also be displayed using the -i option to ls:
# ls -li my*
1212467 -rw-r--r-- 2 root root 0 Mar 15 21:36 myfile
1212467 -rw-r--r-- 2 root root 0 Mar 15 21:36 myhlink
1213365 lrwxrwxrwx 1 root root 6 Mar 15 21:36 myslink -> myfile
Here you can see that the directory entries for myfile and myhlink both point to inode 1212467, while the directory entry for myslink points to inode 1213365. That inode contains the symbolic link to myfile.
As another example, consider the two filesystems in Figure 6-3. 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.
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.
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. (See "Objective 3: Perform Basic File Management in Chapter 5 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 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!