How do I dereference a symbolic link?
$ ls -l /usr/bin/java
lrwxrwxrwx. 1 root root 22 Jul 20 2010 /usr/bin/java -> /etc/alternatives/java
$ ls -l /etc/alternatives/java
lrwxrwxrwx. 1 root root 30 Aug 9 2010 /etc/alternatives/java -> /usr/java/jdk1.6.0_20/bin/java
$ ls -l /usr/java/jdk1.6.0_20/bin/java
-rwxr-xr-x. 1 root root 50810 Apr 13 2010 /usr/java/jdk1.6.0_20/bin/java
Lets create a chain of symbolic links:
mkdir /tmp/symlink
cd /tmp/symlink
echo "this is a test file" > abc.txt
ln -s abc.txt link1
ln -s link1 link2
ln -s link2 link3
ln -s link3 link4
Now lets use the last link that we created:
cat link4
this is a test file
What if we make it a circular link?
rm link1
ln -s link4 link1
Now lets try to use one of the symbolic links:
cat link4
cat: link4: Too many levels of symbolic links
You noticed that? Okay, lets move further:
# we will create a chain of symlinks, which is 50 links deep
mkdir /tmp/links
cd /tmp/links
for i in {0..50}
do
ln -s l${i} l$(expr $i + 1)
done
echo hello > l0
Lets see what files/links this script has generated:
cd /tmp/links
ls -l
You will notice that all the symlinks upto l40 resolve correctly:
$ cat l40
hello
$ # notice that:
$ # all links from l41 and above will not resolve
$ cat l41
cat: l41: Too many levels of symbolic links
$ cat l51
cat: l51: Too many levels of symbolic links
Lets print the whole link path now:
# doesn't handle circular symlink loops at the moment
F=l51
while [ -h "$F" ]
do
G=$(readlink $F)
echo "$F -> $G"
F=$G
done
echo "Finally -> $F"
OUTPUT:
l51 -> l50
l50 -> l49
l49 -> l48
...OUTPUT SKIPPED..
l3 -> l2
l2 -> l1
l1 -> l0
Finally -> l0
What’s the bottomline?
- Even if there is no circular symlink loop, the symlink might fail to resolve. This depends on the
MAXSYMLINK
limit. - UNIX / Linux doesn’t handle symlink loops at all. The whole assumption is based on a limit. If the symlink chain grows more than a certain limit, we will get a Too many levels of symbolic links error, regardless of the symlink loop or not.
References: