В этой статье будут описаны ссылки в Linux, вы узнаете какие они бывают, чем отличаются, как их создавать или удалять.
Теория
Для начала вспомним про хранение файлов. Файлы и каталоги на жестком диске хранятся в виде набора блоков. Информация о файле (метаданные), например время создания файла, хранится в индексном дескрипторе — inode. Номер inode является уникальным на файловой системе и связывается с определенным набором блоков. А имя файла это всего лишь понятное для человека наименование которое относится к определенному inode. А каталог — это тоже файл, но особого типа, в котором содержится список имен файлов или других каталогов и указатели на inode для этих файлов.
Теперь перейдём к ссылкам, ссылки — это дополнительные записи в каталоге, позволяющие обращаться к файлам или каталогам, но по другим именам.
В Linux различают два вида ссылок:
- Жесткая — дополнительная запись в каталоге указывающая на уже созданный inode.
- Символьная — запись в каталоге указывающая на свой inode, но при чтении ссылающая на другой файл. При этом ссылается на другой файл по имени а не по inode.
Чтобы было понятнее посмотрите на следующий рисунок и описание к нему:
Есть файл с именем test1.txt и он имеет свой уникальный индексный дескриптор (inode 234), который ссылается на набор блоков (набор блоков 1) на жестком диске.
Файл test2.txt это жесткая ссылка. То есть, просто, дополнительное имя файла, которое ссылается на тот же inode что и test1.txt.
Файл test3.txt это символьная ссылка. Этот файл имеет свой индексный дескриптор (inode 465), и обращается к своему набору блоков (набор блоков 2). Этот файл является файлом отдельного типа (символьная ссылка / symbolic link) и в наборе данных у таких файлов записан путь к файлу на который она ссылается. То есть, в файле test3.txt указано что ссылаться нужно на test2.txt. При этом, если удалить файл test2.txt и попробовать прочитать test3.txt то увидим ошибку, так как ссылка не найдет файл на который она ссылается, такую ссылку называют битой ссылкой.
Особенности жёстких и символьных ссылок
Жесткие ссылки в Linux имеют свои ограничения и особенности:
- их возможно создать только для файлов, а для каталогов нельзя;
- они работают только в пределах одной файловой системы (одного диска или раздела);
- при удалении жёстких ссылок, физически файл удаляется (точнее его inode удаляется) только тогда, когда все жесткие ссылки идущие на этот inode удалены.
Особенности символьных ссылок:
- символьные ссылки можно создавать и на файлы и на каталоги;
- они умеют работать не только в пределах одной файловой системы, но и на примонтированных устройствах;
- удаление ссылки не приведет к удалению файла на который она ссылается.
Создание жёстких ссылок
Все примеры я провожу на Debian 12.
Для работы создадим один каталог, а в нем один файл:
$ mkdir dir1 $ touch dir1/file1.txt
С помощью команды ln создадим жесткую ссылку на файл file1.txt. При этом вначале указываем файл, затем создаваемую ссылку.
$ ln dir1/file1.txt dir1/file2.txt
Посмотрим на эти файлы с помощью команды ls, опция -i говорит показать номера inode:
$ ls -i dir1/ 524638 file1.txt 524638 file2.txt
Как видим, номера одинаковые, значит это два имени ссылающиеся на один файл.
Запишем что-нибудь в первый файл и прочитаем из второго:
$ echo 12345 > dir1/file1.txt $ cat dir1/file2.txt 12345
То есть, при правке одного файла, правится и второй.
Оба файла можно переносить в разные каталоги, они всё равно будут ссылаться на один и тот-же набор данных.
$ mv dir1/file1.txt dir2/ $ echo 54321 > dir1/file2.txt $ cat dir2/file1.txt 54321
Создание символьных ссылок
Теперь создадим символьную ссылку file3.txt на файл file2.txt, для этого нужно команде ln указать опцию -s:
$ ln -s file2.txt dir1/file3.txt $ ls -l dir1/ -rw-r--r-- 2 alex alex 6 ноя 19 17:30 file2.txt lrwxrwxrwx 1 alex alex 9 ноя 19 17:35 file3.txt -> file2.txt $ cat dir1/file3.txt 54321
Так как мы ссылку размещаем в каталог dir1, то именно там она будет искать файл file2.txt. То что это символьная ссылка видно в выводе команды ls -l. В выводе указан тип файла (l) и на что эта ссылка ссылается. В примере я использовал относительные пути, но можно использовать и абсолютные.
Теперь давайте переместим ссылку file3.txt в каталог dir2 и посмотрим что произойдет:
$ mv dir1/file3.txt dir2/ $ ls -l dir2/ -rw-r--r-- 2 alex alex 6 ноя 19 17:30 file1.txt lrwxrwxrwx 1 alex alex 9 ноя 19 17:35 file3.txt -> file2.txt $ cat dir2/file3.txt cat: dir2/file3.txt: Нет такого файла или каталога
Так как путь ссылки не изменился, а файл ищется по относительному пути file2.txt, а в каталоге dir2 нет этого файла, то мы получили ошибку при попытке прочитать данный файл. Такие ссылки, которые ведут на объект которого нет, называются битыми ссылками.
Перенесём file2.txt в каталог dir2 и всё исправится:
$ mv dir1/file2.txt dir2/ $ ls -l dir2/ -rw-r--r-- 2 alex alex 6 ноя 19 17:30 file1.txt -rw-r--r-- 2 alex alex 6 ноя 19 17:30 file2.txt lrwxrwxrwx 1 alex alex 9 ноя 19 17:35 file3.txt -> file2.txt $ cat dir2/file3.txt 54321
Как распознать ссылки
То что файл является символьной ссылкой видно из вывода ls -l, это мы уже разобрали.
Но чтобы проверить битая ли это ссылка можно воспользоваться командой ls с опцией -L, которая попытается достучаться до всех файлов на которые есть символьные ссылки:
$ mv dir2/file2.txt dir1/ $ ls -L dir2/ ls: невозможно получить доступ к 'dir2/file3.txt': Нет такого файла или каталога file1.txt file3.txt
В выводе мы сразу заметим что файла ‘dir2/file3.txt’ не существует, значит это битая ссылка.
Немного сложнее дело обстоит с жесткими ссылками. Давайте еще раз посмотрим на файлы file1.txt и file2.txt, которые ссылаются на один inode и являются жесткими ссылками друг для друга:
$ ls -l dir1/file2.txt -rw-r--r-- 2 alex alex 6 ноя 19 17:30 dir1/file2.txt $ ls -l dir2/file1.txt -rw-r--r-- 2 alex alex 6 ноя 19 17:30 dir2/file1.txt
Обратите внимание на число после -rw-r—r— , это число жестких ссылок. Здесь это число = 2. То-есть на каждый файл ссылается 2 имени. А чтобы понять что они ссылаются на один и тот-же файл нужно использовать опцию -i в утилите ls.
$ ls -li dir1/file2.txt 524638 -rw-r--r-- 2 alex alex 6 ноя 19 17:30 dir1/file2.txt $ ls -li dir2/file1.txt 524638 -rw-r--r-- 2 alex alex 6 ноя 19 17:30 dir2/file1.txt
Как видно file1.txt и file2.txt ссылаются на один inode, под номером 524638. Значит это жесткие ссылки для одного и того же объекта.
Если понравилась статья, подпишись на мой канал в VK.