7

I use Ubuntu 15.10 and I'm very new in Linux. After reading in Wikipedia what is a symbolic link in general, and after executing a symlink creation command in the Ubuntu Unix-bash terminal, I ought to better understand the structure of a symlink I worked with several times when creating (and "destroying") Ubuntu learning environments.

There is a short syntax I ran each time when installing a PHPmyadmin (PMA) service. Without running it, the service just didn't work. From the information I gathered, this following syntax creates a symlink that connects Apache to a certain PMA file that includes conf directions.

This is the syntax I ran each time:

cd /etc/apache2/conf-enabled/
sudo ln -s /etc/phpmyadmin/apache.conf phpmyadmin.conf
service apache2 restart

I want to better understand what is actually being done here, for example:

  1. Why is the cd navigation even needed? Couldn't we specify which files we want to work on from the root (computer) folder and that's it?

  2. Why is the -s after the ln?

  3. I navigated to both directories in the ln command but I couldn't find phpmyadmin.conf in either of them - So, how can the system know where it is (assuming there is no system-wide search for it).

Jeff Schaller
  • 67,283
  • 35
  • 116
  • 255

5 Answers5

9

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.

Petr Skocik
  • 28,816
  • 1
    well, soft links bind to 'addresses' only insofar as we'd use the non-computer sense of address like the one you'd write on a letter; they are just a textual desecription, not synchronised and can become orphaned. whereas - 2 more topics for the op to think about - hard links bind to inodes and literally become another handle to the same file, which seems a lot more like a c++ reference if you ask me! a c/c++ pointer is... somewhere awkward in between the two analogies. – underscore_d Jan 01 '16 at 04:39
6
  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/).

gardenhead
  • 2,017
  • 1
    After reading all the answers, which all helped me to develop my knowledge on this, emphasising DopeGhoti 's note about the fact the the ' cd ' command is optional, I have now read the full version of the command that you gardenhead pasted above and I understood what confused me in the original syntax I pasted --- I started there from the end and for a second it confused me... Actually the full syntax that you pasted seems more simple for to understand!!! :) –  Dec 31 '15 at 23:01
  • Glad I could help! Yeah, make sure you understand all the commands that you used: cd, sudo, and ln. Then you'll understand what the original set of commands you posted actually does and how it works, and begin the path to enlightenment :) – gardenhead Dec 31 '15 at 23:48
3
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.

2

A filesystem on any operating system is just a data structure residing on disk (or some other media that can be deemed divided into fixed size "blocks"). I.e., a way to record in such blocks how files are named, perhaps some other data like owner and permissions, and where their contents reside on disk.

In Unix/Linux filesystems, a file is represented by a block containing information on size, owner, group, permissions, and (essentially) a list of blocks containing the actual data. Traditional filesystems contain a fixed number of such inodes, for which a part of the disk is reserved. They are just numbered from 0 on up. A directory in a filesystem is implemented as a file which contains a list of pairs (filenaname, inode number).

With this structure you can have the same file appearing several times under different names (the inode records the number of references). "Deleting a file" is then just marking the entry in the directory as unused somehow, and decreasing the count of references in the inode. If the reference count goes to zero, the space used by the file (inode, blocks used for data and pointers to data blocks) can be reclaimed. "Renaming a file" changes the entry in the directory, "moving a file" is just deleting one directory entry and creating another.

Creating a "hard link" (ln old new) to a file is to just record tne same inode number as old under ǹew. Note that after this operation both directory entries are exactly equivalent. Also note that this will only work inside the same filesystem, i.e., the same disk. To overcome this restriction, symbolic links where invented. A symbolic link is essentially a tiny file that contains the name of the entity linked to. This is created by ln -s old new. Note that old could go away, leaving new as a stale link.

The above is slightly simplified, some modern filesystems are structured differently; but they have to behave as if they are structured as described, because the way files and directories work is too ingrained in Unix to change (much).

vonbrand
  • 18,253
1
  1. The cd command is in fact actually optional; it merely makes the actual syntax of the subsequent ln command a little simpler.
  2. The -s switch for ln instructs it to create a symbolic link rather than a hardlink. There are several differences between the two types of links, but suffice it to sat that a symbolic link is essentially a marker on the filesystem saying "the file you're looking for is actually over here.".
  3. You can create a link to a target that does in fact not exist; this is often called an "orphaned" link.
DopeGhoti
  • 76,081