Symbolic links mean shortcuts, right?
If you ever heard that explanation, it is only partially correct, and they are present on a most modern OS. There are two kinds of symbolic links when thinking in terms of files: hard and soft:
Hard Links | Soft Links |
Only link to files | Can link to directories and files |
Link to contents on same disk | Can reference files/folders across disks or networks |
Reference inode/physical locations | If the original file is deleted, the hard link will remain (in own inodes) |
Moving a file will still allow the link to work | Links don’t follow the reference file if moved |
A soft link will most likely match your expectations of a shortcut and the behavior might not be very surprising, but what use is a hard link? One of the most prominent cases of when to use a hard link is when you don’t want to break a link by moving the file it points to! A soft link is clearly more flexible and can work across file systems, which is unlike hard links, but soft links won’t work if a file is moved.
Note:
Besides creating shortcuts, you can do neat tricks like renaming argv[0]
when using symbolic links. The Busybox shell is an example of that, where it contains applets that are executed by a symlink that points to ./busybox
. For example, ls
points to the same binary as cd
! All of them point to ./busybox
. This is a neat way to save space and improve run-time flags without the use of flags.
Note:
Soft links are also used in the /usr/lib
or /lib
folders for shared librarys
. In fact, symlinks are very useful for aliasing paths or getting software to work with hard-coded paths that are inside of the binaries themselves.
How to do it…
Open a terminal, and create the whoami.sh
script:
whoami.sh
#!/bin/bash
VAR=$0
echo "I was ran as: $VAR"
Execute whoami.sh
and observe what has happened:
$ bash whoami.sh
Next, create a soft link to whoami.sh
using the ln
command:
$ ln -s whoami.sh ghosts-there-be.sh
Next, run ls
-la
. Notice any differences?
ls -la ghosts-there-be.sh whoami.sh
On to hard links, which are created this way using ln
:
$ ln ghosts-there-be.sh gentle-ghosts-there-be.sh
$ ln whoami.sh real-ghosts-there-be.sh
Next, let’s look at the difference in results when running the commands:
$ ls -la ghosts-there-be.sh whoami.sh real-ghosts-there-be.sh gentle-ghosts-there-be.sh
lrwxrwxrwx 1 rbrash rbrash 18 Dec 12 15:07 gentle-ghosts-there-be.sh -> ghosts-there-be.sh
lrwxrwxrwx 1 rbrash rbrash 9 Dec 12 14:57 ghosts-there-be.sh -> whoami.sh
-rw-rw-r-- 2 rbrash rbrash 45 Dec 12 14:56 real-ghosts-there-be.sh
-rw-rw-r-- 2 rbrash rbrash 45 Dec 12 14:56 whoami.sh
$ mv whoami.sh nobody.sh
$ bash ghosts-there-be.sh
bash: ghosts-there-be.sh: No such file or directory
$ bash real-ghosts-there-be.sh
I was ran as: real-ghosts-there-be.sh
$ bash gentle-ghosts-there-be.sh
bash: gentle-ghosts-there-be.sh: No such file or directory
How it works…
In step one, we created whoami.sh
. It is similar to the whoami
command, but different because we do not print the $USER
variable, but rather argument 0
(arg0
, as its typically known) or $0
. In laymen’s terms, we are printing out the name used to execute the code or script. When we execute whoami.sh
, it prints to the console:
$ bash whoami.sh
I was ran as: whoami.sh
To create a symbolic soft link, we use ln
with the -s
flag (for symbolic mode). The ln
command expects to be executed in this way: $ ln -s originalFileToBeLinkedTo newFileToLinkToOldFile
.
As we can see in the following code, executing ghosts-there-be.sh
runs the code in whoami.sh
, but arg0
is ghosts-there-be.sh
. Then, when the ls
command is ran with the -l -a
flags (-la
), we can see the soft link to whoami.sh
. Notice the small size of 9 bytes!
$ bash ghosts-there-be.sh
I was ran as: ghosts-there-be.sh
$ ls -la ghosts-there-be.sh whoami.sh
lrwxrwxrwx 1 rbrash rbrash 9 Dec 12 14:57 ghosts-there-be.sh -> whoami.sh
-rw-rw-r-- 1 rbrash rbrash 45 Dec 12 14:56 whoami.sh
Next, we create a hard link by using the ls
command without the -s
flag.
The hard link, real-ghosts-there-be.sh
, runs the same content as ghosts-there-be.sh
, but points to the actual contents of whoami.sh
, even if it is moved and renamed as nobody.sh
:
$ ls -la ghosts-there-be.sh whoami.sh real-ghosts-there-be.sh gentle-ghosts-there-be.sh
lrwxrwxrwx 1 rbrash rbrash 18 Dec 12 15:07 gentle-ghosts-there-be.sh -> ghosts-there-be.sh
lrwxrwxrwx 1 rbrash rbrash 9 Dec 12 14:57 ghosts-there-be.sh -> whoami.sh
-rw-rw-r-- 2 rbrash rbrash 45 Dec 12 14:56 real-ghosts-there-be.sh
-rw-rw-r-- 2 rbrash rbrash 45 Dec 12 14:56 whoami.sh
mv whoami.sh nobody.sh
$ bash ghosts-there-be.sh
bash: ghosts-there-be.sh: No such file or directory
$ bash real-ghosts-there-be.sh
I was ran as: real-ghosts-there-be.sh
$ bash gentle-ghosts-there-be.sh
bash: gentle-ghosts-there-be.sh: No such file or directory
$ bash gentle-ghosts-there-be.sh
bash: gentle-ghosts-there-be.sh: No such file or directory
0 Comments