Жесткие и символические ссылки в Linux

Каталог как файл-список имен других файлов, которым сопоставлены номера индексных дескрипторов, не запрещает иметь два разных имени файла, указывающих на одни и те же метаданные . Такой эффект носит название жесткой ссылки, создать которую можно при помощи команды ln.

Жесткие и символические ссылки в Linux

Жесткая ссылка

[email protected]:~$ touch  readme

[email protected]:~$ ls -li  readme

20318653   -rw-r—r— 1  john john 0  ноя.    1  01:32 readme

[email protected]:~$  ln readme readme.txt

[email protected]:~$ touch README

[email protected]:~$ ls -li readne readme.txt README

20318653 -rw-r—r— 2 john john 0 ноя. 1 01:32 readme

20319121 -rw-r—r— 1 john john 0 ноя. 1 01:33 README

20318653 -rw-r—r— 2 john john 0 ноя. 1 01:32 readme.txt

Более того, оба имени являются равнозначными, и нет возможности узнать, какое из них создано первым, из чего нужно заключить, что первое и единственное имя файла уже является его жесткой ссылкой (на номер индексного дескриптора).

При добавлении файлу нового имени (жесткой ссылки) в его метаданных увеличивается счетчик количества имен, а при удалении файла сначала удаляется имя и уменьшается счетчик количества имен, и только при удалении последнего имени высвобождаются метаданные и данные файла.

Счетчик имен файла

[email protected]:~$ ln readme read.me

[email protected]:~$  ls -li  read*

20318653 -rw-r—r—   3 john john 0 ноя. 1 01:32 readme

20318653 -rw-r—r—   3 john john 0 ноя. 1 01:32 read.me

20318653 -rw-r—r- —   3 john john 0 ноя. 1 01:32 readme.txt

[email protected]:~$ rm readme

[email protected]:~$  ls -li  read*

20318653 -rw-r—r—  2 john john 0 ноя. 1 01:32 read.me

20318653 -rw-r—r— 2 john john 0 ноя. 1 01:32 readme.txt

[email protected]:~$  rm readme.txt

[email protected]:~$  ls -li read*

20318653 -rw-r—r—  1  john john 0 ноя. 1 01:32 read.me

Удаление открытого файла

Нужно заметить, что удаление файла — двухшаговая операция, состоящая из удаления имени файла, а затем — удаления метаданных (и высвобождения блоков, занимавшихся этим файлом).

Удаление метаданных файла не выполняется вообще, если у файла еще остались имена (жесткие ссылки), и не происходит сразу, если файл открыт каким-либо процессом.

Метаданные и блоки, занимаемые файлом, высвобождаются только при закрытии этого файла всеми открывшими его процессами, что проиллюстрировано в примере ниже.

Команда df измеряет доступное (свободное, disk free) место на файловой системе указанного файла, тогда как команда du, наоборот, измеряет занимаемое (disk usage) указанным файлом место на его файловой системе.

[email protected]:~$ df -h .

Файл.система                        Размер   Использовано   Дост   Использовано%  Смонтировано в

/dev/mapper/ubuntu-root     455G                    400G       32G                          93% /

[email protected]:~$ du -sh astra-linux-l.3-special-edition-snolensk-disk3-devel.iso

2,8G astra-linux-l.3-special-edition-snolensk-disk3-devel.iso

[email protected]@ubuntu:~$ rm astra-linux-l.3-special-edition-snolensk-disk3-devel.iso

[email protected]:~$ df -h .

Файл.система                        Размер   Использовано   Дост   Использовано%  Смонтировано в

/dev/mapper/ubuntu-root      455G                    400G      32G                           93% /

[email protected]:~$ lsof astra-linux-l.3-special-editrion-snolensk-disk3-devel.iso

COMMAND    PID   USER   FD   TYPE     DEVICE           SIZE/OFF      NODE      NAME

fuseiso            16925     john   3r     REG         252,0        2947385344   20316584   astra-linux-1.3-special-edition-

snolensk-disk3-devel.iso

[email protected]:~$ kill 16925

[email protected]:~$ df -h .

Файл.система                        Размер   Использовано   Дост   Использовано%  Смонтировано в

/dev/mapper/ubuntu-root      455G                      397G     35G                           92% /

Специальные имена текущего  .  и родительского  . .  каталога на поверку тоже оказываются жесткими ссылками, поэтому у любого каталога по крайней мере два имени — свое «собственное» в родительском и специальное  в самом себе, а у каталогов с подкаталогами еще и имена . . в каждом из дочерних.

Имена каталогов

[email protected]:~$ mkdir folder

[email protected]:~$ ls -ldi folder

20357139   drwxr-xr-x 2  john john 4096 апр. 1 01:58 folder

[email protected]:~$ cd folder

[email protected]:~/folder$  ls -lai

итого  8

20357139 drwxr-xr-x   2 john john 4096 ноя. 1 01:58 .

20332580 drwxr-xr-x  4 john john 4096 ноя. 1 01:58  . .

[email protected]:~/folder$ mkdir child

[email protected]:~/folder$ cd child

[email protected]:~/folder/chlld$ ls -lai

итого 8

20357140 drwxr-xr-x 2 john john 4096 ноя. 1 02:01 .

20357139 drwxr-xr-x 3 john john 4096 ноя. 1 02:01 . .

[email protected]:~/folder/chlld$ cd . ./. .

[email protected]:~$  stat folder/

Файл: «folder/»

Размер: 4096             Блоков: 8                      Блок B/B:         4096          каталог

Устройство:   fc00h/64512d        Inode: 20357139                      Ссылки:   3

. . .                        . . .                            . . .

[email protected]:~$ rmdir folder

rmdlr: не удалось удалить «folder»: Каталог не пуст

Существенным ограничением жесткой ссылки в дереве каталогов, куда смонтирована более чем одна файловая система, является локальность жесткой ссылки в пределах своей файловой системы в силу локальной значимости номеров индексных дескрипторов.

Так как на каждой новой файловой системе номера индексных дескрипторов начинают нумероваться с нуля, то жесткая ссылка всегда указывает на метаданные файла в «своей» файловой системе и не может указывать на метаданные файла в «чужой» файловой системе общего дерева каталогов.

Для преодоления этого ограничения служит символическая ссылка symlink, являющаяся самостоятельным служебным типом и содержащая путевое имя к целевому файлу.

Символическая ссылка

[email protected]:~$ ln -s read.me readme.1st

[email protected]:~$ ls -li read*

20318653   -rw-r—r—     1  john john  0 ноя. 1  01:32 read.me

20319944  lrwxrwxrwx  1  john john  6 ноя. 2 00:02 readme.1st -> read.me ★

В случае с символической ссылкой при удалении целевого файла сама ссылка будет указывать в никуда и называться «сиротой» (orhpan). Попытка прочитать такую ссылку приводит к странным, на первый взгляд, результатам: файл «существует» для команды ls, но команда просмотра содержимого Cat говорит об обратном. Ничего удивительного, если помнить, что ls работает с именами файлов, a cat — с их данными (которые действительно не существуют).

Сиротская ссылка

[email protected]:~$ rm read.me

[email protected]:~$ ls read*

readme.1st

[email protected]:~$ cat readme.1st

cat: readme.1st: Нет такого файла или каталога

[email protected]:~$ ls -l read*

Irwxrwxrwx 1  john john 6 ноя.         2 00:02 readme.1st -> read.me

[email protected]:~$ cat read.me

cat: read.me: Нет такого файла или каталога

Символические ссылки могут ссылаться на имена друг друга неограниченное количество раз, а при попытке использовать одну из таких ссылок будут использованы данные файла, последнего в цепочке ссылок. По ошибке можно даже закольцевать  две или более ссылок, с чем разберется операционная система при чтении одной из ссылок.

Кольцевые ссылки

 

[email protected]:~$ ln -s readme.1st read.me

[email protected]:~$ ls -l read*
lrwxrwxrwx 1  john john  10 ноя.       2 00:42 read.me -> readme.1st
lrwxrwxrwx 1   john john      8 ноя.    2 00:04 readme.1st -> read.me
[email protected]:~$ cat read.me
cat: read.me: Слишком много уровней символьных ссылок

Основным назначением символических (и изначально, жестких) ссылок является «множественная каталогизация» файлов, т.е. разные наборы разных имен одних и тех же данных. Типичным примером использования ссылок является организация boot сценариев запуска системных служб при старте операционной системы. Сами сценарии располагаются в каталоге /etc/lnit.d, а в каталогах /etc/rcS.d, /etc/rc0.d, …, /etc/rc6.d размещены символические ссылки на эти сценарии, которые должны быть запущены с определенными параметрами при переключении состояния системы между так называемыми «уровнями исполнения» runlevel.

Сценарии запуска служб и их каталогизация по уровням исполнения

[email protected]:~$ ls -l /etc/rc?1.d

/etc/rc2.d:
lrwxrwxrwx  1 root root 20 окт. 12  2018 /etc/rc2.d/S19postgresql -> .. /init.d/postgresql
lrwxrwxrwx  1 root root 17 ноя. 31  2018 /etc/rc2.d/S20postflx -> ../init.d/postftx
/etc/rc6.d:
lrwxrwxrwx  1 root root 17 ноя. 31  2018 /etc/rc6.d/K20postftx -> . ./init.d/postftx
lrwxrwxrwx  1 root root 20 окт. 12  2018 /etc/rc6.d/K21postgresql -> ../init.d/postgresql

В этом примере сценарии postfix и postgresql имеют вторичные имена, начинающиеся с K в каталоге rc6.d, и другие вторичные имена, начинающиеся с S в каталоге rc2.d. Это символизирует необходимость запускать (start) службы postfix и postgresql при переключении системы на уровень исполнения № 2 и уничтожать (kill) процессы этих служб при переключении системы на уровень исполнения № 6.

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *