What is a symbolic link made from? Understanding the structure of symlinks

Symlinks

Autodereferenced references to filenames

A symlink is literally a text file that's treated specially by the kernel and whose contents is a path to another file/directory.

You can read the contents of a symlink file with readlink, and if you standardly open a symlink file, the system will open the file/directory referenced by contents of the symlink.

Pointer/C++ reference analogy

If you're familiar with C/C++, then a symlink behaves somewhat like a C++ reference or an autodereferenced pointer in most contexts (not all: e.g., rm or mv work directly on the symlink, not on the target). The difference is that real C++ references bind to memory addresses whereas symlinks bind to filesystem addresses.

Dangling symlinks

The contents of a symlink don't have to be a valid filepath reference --> then you have a dangling symlink (like danglig pointer or a dangling reference).

Relative symlinks

If the filepath in a symlink isn't an absolute one (starting with /), then the relative filepath is resolved relatively to the location of the symlink (in non-symlink contexts, relative paths are resolved relatively to the $PWD).


The -s Flag and Hardlinks

The -s flag is for "create symlinks". ln can also create hardlinks. Hardlinks operate at another level, which is closer to the implementation of the filesystem (consequently, you cannot create hardlinks across different filesystems).

Unix filesystems store filenames(/directory names) and file contents (directory contents) separately, and names are just autodereferenced reference-counted pointers to their contents. A hardlink creates another name for the same contents while increasing the reference count.

$ echo 'the contents' > f1
$ ls -l f1 
  * 1 * #the 2nd column is the reference count
$ ln f1 f2 #create another name for the contents of f1
$ ls -l f1
   * 2 * #the contents of f1 has two named references to it
$ rm f1  #the contents of f1 lives on (in f2) #
         # because rm only removes the reference to the data block
         #and this isn't the only reference
         #(rm ivokes a system call literally named `unlink`)

Directory hardlinks

You can't create directory hardlinks, but . and .. are directory hardlinks implicitly created for you. Consequently the hardlink count for a directory reflects how many subdirectories it has (each subdirectory comes with a .. hardlink to the parent).


Symlinks and Hardlinks—Big Picture Overview:

echo 'file data' > fileName 
ln fileName fileName2 #hardlink
ln -s "$PWD/fileName" absoluteSymlinkTofileName 
ln -s fileName relativeSymlinkTofileName 

On the same physical file system, ln creates another name for file data (ln will fail across filesystems). You can delete either fileName or fileName2 and as long as at least one name remains, file data lives on.

absoluteSymlikTofileName is an autodereferenced reference to the fileName name. As long as that path resolves to something, the symlink is valid. If you delete the target, the symlink dangles. This is an absolute symlink so you can move it to other places without changing its validity.

relativeSymlinkToFileName refers to a name called fileName in the same directory as the directory of relativeSymlinkToFileName. If you move it to another directory that also has a file (or directory) named fileName, then it'll point to that instead.


  1. The ln command creates the symlink in the current directory if no directory is specified. Thus, phpmyadmin.conf is put in /etc/apache2/conf-enabled/. You could have also done

    ln -s /etc/phpmyadmin/apache.conf /etc/apache2/conf-enabled/phpmyadmin.conf
    

    This is standard behavior for pretty much all Unix commands.

  2. The -s option specifies that you are creating a soft link as opposed to a hard link. Read more here.

  3. I don't quite understand the question ("how can the system know where it is?"). phpmyadmin.conf is created in the current directory (in this case /etc/apache2/conf-enabled/).


ln -s /etc/phpmyadmin/apache.conf phpmyadmin.conf

3. This command creates a symbolic link at the location /etc/apache2/conf-enabled/phpmyadmin.conf, whose target is /etc/phpmyadmin/apache.conf. After this, opening the file /etc/apache2/conf-enabled/phpmyadmin.conf is equivalent to opening /etc/phpmyadmin/apache.conf. If /etc/phpmyadmin/apache.conf exists, then /etc/apache2/conf-enabled/phpmyadmin.conf has the same content. If /etc/phpmyadmin/apache.conf doesn't exist then opening /etc/apache2/conf-enabled/phpmyadmin.conf will fail, just as if /etc/apache2/conf-enabled/phpmyadmin.conf didn't exist.

   A symbolic link is just text. The link itself keeps existing and pointing to the same target whether that target exists or not. This allows, for instance, symbolic links to removable drives to keep existing whether the drive is present or not, or replacing a file that a symbolic link happens to point to (the fact that the target might temporarily stop existing doesn't affect the symbolic link). When the target doesn't exist, the symbolic link is said to be broken

1. The link could have been created without changing the current directory. Of course the command would have to be changed to include the full path to the desired link.

   ln -s /etc/phpmyadmin/apache.conf /etc/apache2/conf-enabled/phpmyadmin.conf

   When the a symbolic link is absolute (i.e. its target is an absolute path), there's no advantage to changing to the directory before creating the link. When a symbolic link is relative, there is an advantage, because the first argument to ln -s is the target of the link, and it's interpreted relative to the location of the link, not to the current directory at the time the ln command is run. For example, a relative link could have been made like this:

   ln -s ../../phpmyadmin/apache.conf /etc/apache2/conf-enabled/phpmyadmin.conf

   But if the current directory isn't /etc/apache2 then in general ../../ isn't /etc, so ../../phpmyadmin/apache.conf isn't an existing target; for example it won't be picked up by shell completion.

2. The ln command existed before symbolic links. It originally created hard links, which have a significantly narrower use case so aren't used much. Although ln -s is used more often than plain ln, the meaning of plain ln can't be changed because that would break backward compatibility.