Рано или поздно возникает ситуация, когда один и тот же файл нужен сразу в нескольких местах. Копировать его каждый раз – плохое решение: копии расходятся между собой, место на диске тратится впустую, а обновить их все одной командой и тем более быстро откатить изменения обратно не получится. В Linux для этого есть механизм полегче – символическая ссылка (symlink).
В этой статье разберем, что такое символические ссылки, чем они отличаются от жестких, что важно учитывать при работе с ними и как создавать, удалять и использовать symlink на практике – с командами, которые можно сразу проверить в терминале.
Что такое символические ссылки
Символическая ссылка (от англ. symbolic link, symlink, “симлинк”, “мягкая ссылка”) – это специальный файл, который не содержит данных сам по себе, а хранит путь к другому файлу или директории. По сути, это указатель: когда система или программа обращается к ней, она автоматически перенаправляется по пути, записанному внутри ссылки, к реальному объекту. Например, символическая ссылка на папку позволяет обращаться к каталогу из другого места, не создавая его копию.
Проще всего представить символические ссылки как ярлык в Windows или alias в macOS – только реализованный на уровне файловой системы Linux. Благодаря этому символическая ссылка работает одинаково для любой программы: текстового редактора, веб-сервера, команды cat или скрипта на PHP – все они видят ссылку и автоматически переходят по пути, записанному в ней, к реальному файлу или директории.
Важно понимать: символическая ссылка не хранит содержимое исходного файла и не занимает на диске место, сопоставимое с размером цели, – только текст самого пути. Именно поэтому к одному и тому же файлу или директории можно обращаться сразу из нескольких мест, не дублируя данные и не тратя на это лишнее место.
Жесткие и символические ссылки: в чем отличие
Кроме символической, в Linux есть еще один тип ссылок – жесткая ссылка (hard link). Она устроена совсем по-другому, и сравнение с ней хорошо показывает, что на самом деле представляет собой символическая ссылка и почему у нее именно такие возможности и ограничения.
Чтобы понять разницу, нужно вспомнить, как устроена файловая система Linux. В файловой системе каждый объект имеет inode (index node) – структуру данных, в которой хранятся его метаданные: владелец, права доступа, размер и другие сведения. При этом имя файла в inode не хранится – оно является частью записи каталога, которая связывает имя с конкретным inode.
Именно из этого принципа и вытекает, что такое жесткая ссылка: это не отдельный файл-указатель, как символическая ссылка, а еще одна запись в директории, которая указывает на тот же inode, что и оригинальный файл. И оригинал, и жесткая ссылки полностью равноправны и ведут к одним и тем же данным на диске – нельзя даже сказать, какое из имен “настоящее”, а какое “ссылка”.
Разница между жесткой (hard link) и символической (symlink) ссылками видна по нескольким параметрам:
- Inode. У жесткой ссылки – тот же inode, что и у оригинала: это буквально второе имя того же файла. У symlink – собственный, отдельный inode: это самостоятельный файл, внутри которого хранится не содержимое, а путь к цели;
- Ссылка на директорию. Жесткую ссылку на директорию создать нельзя – это стандартное ограничение файловых систем Linux, чтобы избежать циклов в дереве каталогов. У symlink этого ограничения нет: он может указывать как на файл, так и на директорию;
- Работа между файловыми системами и разделами. Жесткая ссылка не может пересекать границу файловой системы – номера inode уникальны только в ее пределах. Symlink этого ограничения не имеет и может ссылаться на объект в другой файловой системе или на другом разделе;
- Поведение при удалении или перемещении оригинала. У каждого inode есть счетчик количества жестких ссылок на него (поле
st_nlink): данные физически удаляются, только когда счетчик доходит до нуля, то есть когда удалено последнее имя, под которым к файлу можно обратиться. Поэтому жесткая ссылка продолжает работать, даже если удалить “оригинал”, так как оригинал и ссылка равноправны. У symlink такого счетчика нет: если удалить, переименовать или переместить цель, ссылка сразу станет нерабочей (“битой”).
Разницу легко увидеть на практике. Если создать файл, жесткую и символическую ссылку на него и посмотреть на номера inode командой ls -li, вывод будет примерно таким:
~$ ls -li original.txt hardlink.txt symlink.txt
2963 -rw-rw-r-- 2 betutorial betutorial 33 Aug 17 14:38 hardlink.txt
2963 -rw-rw-r-- 2 betutorial betutorial 33 Aug 17 14:38 original.txt
3501 lrwxrwxrwx 1 betutorial betutorial 12 Aug 17 14:38 symlink.txt -> original.txtУ original.txt и hardlink.txt номер inode будет одинаковым, у symlink.txt – другим. Также в этом примере видно, что у жесткой ссылки в колонке размера отображается реальный размер файла (это те же данные на диске), а у symlink – длина пути, который в нем записан.
После удаления original.txt жесткая ссылка остается рабочей, а символическая – ломается:
~$ rm original.txt
~$ cat hardlink.txt
Это тестовый файл
~$ cat symlink.txt
cat: symlink.txt: No such file or directoryНа практике из-за описанных ограничений жесткие ссылки используют редко и для узких задач (например, чтобы у одного и того же файла было сразу два имени в пределах одного раздела), а symlink – гораздо чаще, именно благодаря гибкости: возможности ссылаться на директории и работать между разными файловыми системами.
Как создать, удалить и обновить символическую ссылку
В этом разделе разберем, как создать символическую ссылку, удалить и обновить ее, и сразу проверим команды на практике.
Для этого создадим тестовую директорию с файлами:
~$ mkdir ~/symlink-test && cd ~/symlink-test
~/symlink-test$ mkdir project
~/symlink-test$ echo "Это тестовый файл" > project/notes.txtСоздание
Для создания такой ссылки используется команда ln с флагом -s:
ln -s <путь_к_цели> <имя_ссылки>Создадим символическую ссылку на файл:
~/symlink-test$ ln -s project/notes.txt notes-link.txt
~/symlink-test$ ls -l notes-link.txt
lrwxrwxrwx 1 betutorial betutorial 17 Aug 18 08:13 notes-link.txt -> project/notes.txt
~/symlink-test$ cat notes-link.txt
Это тестовый файлСсылка на директорию делается точно так же – никакого отдельного флага не требуется:
~/symlink-test$ ln -s project project-link
~/symlink-test$ ls -l project-link
lrwxrwxrwx 1 betutorial betutorial 7 Aug 18 08:14 project-link -> project
~/symlink-test$ ls project
notes.txt
~/symlink-test$ ls project-link
notes.txtЕсли нужно создать ссылку с тем же именем, что и у цели, но в другой директории, последний аргумент можно опустить – ln возьмет исходное имя файла:
~/symlink-test$ mkdir links && cd links
~/symlink-test/links$ ln -s ../project/notes.txt
~/symlink-test/links$ ls -l
total 0
lrwxrwxrwx 1 betutorial betutorial 20 Aug 18 08:15 notes.txt -> ../project/notes.txt
~/symlink-test/links$ cat notes.txt
Это тестовый файлУдаление
Удалить символическую ссылку можно командой rm или unlink. Обе команды могут удалить символическую ссылку, но отличаются набором возможностей:
rm– может удалить сразу несколько ссылок за один вызов и поддерживает шаблоны (*);unlink– может удалить ровно одну ссылку за раз, шаблоны не поддерживает.
Проверим удаление символических ссылок:
~/symlink-test$ rm notes-link.txt
~/symlink-test$ ls -l
total 8
drwxrwxr-x 2 betutorial betutorial 4096 Aug 18 08:15 links
drwxrwxr-x 2 betutorial betutorial 4096 Aug 18 08:13 project
lrwxrwxrwx 1 betutorial betutorial 7 Aug 18 08:14 project-link -> project
~/symlink-test$ unlink project-link
~/symlink-test$ ls -l
total 8
drwxrwxr-x 2 betutorial betutorial 4096 Aug 18 08:15 links
drwxrwxr-x 2 betutorial betutorial 4096 Aug 18 08:13 project
При удалении символической ссылки ее цель (файл или директория) не удаляется.
/, система воспринимает такой путь как обращение к директории, на которую указывает ссылка, а не к самой ссылке. Поэтому при удалении символической ссылки завершающий / лучше не указывать.Протестируем удаление символической ссылки на директорию с указанием / и без него. Ссылку project-link мы уже удалили выше, поэтому создадим ее заново и попробуем удалить сначала со слэшем, потом без него:
~/symlink-test$ ln -s project project-link
~/symlink-test$ ls -l project-link
lrwxrwxrwx 1 betutorial betutorial 7 Aug 18 08:18 project-link -> project
~/symlink-test$ rm project-link/
rm: cannot remove 'project-link/': Is a directory
~/symlink-test$ rm project-link
~/symlink-test$ ls -l
total 8
drwxrwxr-x 2 betutorial betutorial 4096 Aug 18 08:15 links
drwxrwxr-x 2 betutorial betutorial 4096 Aug 18 08:13 projectСимлинк на директорию нельзя удалить командой rmdir – она предназначена только для настоящих пустых директорий и вернет ошибку Not a directory.
Обновление уже существующей символической ссылки
Отдельная задача – не создать символическую ссылку с нуля, а переключить уже существующую на новую цель. Команда используется одна и та же, но изменяются флаги.
Пример с файлом. Пусть ссылка config.php указывает на старый конфиг, и нужно переключить ее на новый:
~/symlink-test$ echo "старый конфиг" > config-old.php
~/symlink-test$ echo "новый конфиг" > config-new.php
~/symlink-test$ ln -s config-old.php config.php
~/symlink-test$ ls -l config.php
lrwxrwxrwx 1 betutorial betutorial 14 Aug 18 08:21 config.php -> config-old.php
~/symlink-test$ cat config.php
старый конфигПросто повторить ln -s не получится – имя config.php уже занято:
~/symlink-test$ ln -s config-new.php config.php
ln: failed to create symbolic link 'config.php': File existsls -l, что имя действительно принадлежит ссылке, а не файлу с данными.Для перезаписи ссылки добавляем флаг -f (--force, “принудительно”) – он указывает ln не выдавать ошибку, а удалить существующий файл или ссылку с этим именем и создать на его месте новую:
~/symlink-test$ ln -sf config-new.php config.php
~/symlink-test$ ls -l config.php
lrwxrwxrwx 1 betutorial betutorial 14 Aug 18 08:23 config.php -> config-new.php
~/symlink-test$ cat config.php
новый конфигПример с директорией. Пусть current указывает на директорию release-1:
~/symlink-test$ mkdir release-1 release-2
~/symlink-test$ echo "версия 1" > release-1/version.txt
~/symlink-test$ echo "версия 2" > release-2/version.txt
~/symlink-test$ ln -s release-1 current
~/symlink-test$ ls -l current
lrwxrwxrwx 1 betutorial betutorial 9 Aug 18 08:23 current -> release-1
~/symlink-test$ cat current/version.txt
версия 1Попробуем переключить current на release-2 тем же способом:
~/symlink-test$ ln -sf release-2 current
~/symlink-test$ ls -l current
lrwxrwxrwx 1 betutorial betutorial 9 Aug 18 08:23 current -> release-1
~/symlink-test$ cat current/version.txt
версия 1Символическая ссылка current не изменилась. Утилита ln обнаружила, что current ведет на директорию, перешла внутрь нее, создав там новую ссылку с именем release-2 – вместо того, чтобы заменить симлинк current:
~/symlink-test/release-1$ ls -l
total 4
lrwxrwxrwx 1 betutorial betutorial 9 Aug 18 08:24 release-2 -> release-2
-rw-rw-r-- 1 betutorial betutorial 15 Aug 18 08:23 version.txtЧтобы заменить именно current, а не создать ссылку внутри ее цели, нужен еще один флаг – -n (--no-dereference, “не переходить по ссылке”) – он указывает ln воспринимать current как обычное имя, а не заходить внутрь директории, на которую эта ссылка сейчас указывает:
~/symlink-test$ ln -sfn release-2 current
~/symlink-test$ ls -l current
lrwxrwxrwx 1 betutorial betutorial 9 Aug 18 08:26 current -> release-2
~/symlink-test$ cat current/version.txt
версия 2Ту же задачу можно решить и проще – удалить старую ссылку и создать новую:
rm current
ln -s release-2 currentДля тестов и разовых задач данный способ подойдет. Для боевого сервера, где current – это, например, document root работающего сайта, у такого способа есть нюанс: между rm и ln -s есть короткий промежуток времени, когда пути current не существует вообще, и случайный запрос в это время может получить ошибку. Команда ln -sfn заменяет ссылку одной операцией без простоя.
Нюансы, которые важно учитывать при работе с symlink
У симлинка есть несколько особенностей поведения, из-за которых он может повести себя не так, как ожидается.
Чтобы не путать эти примеры с уже созданными файлами и ссылками, создадим для них отдельную тестовую директорию:
~$ mkdir ~/symlink-test2 && cd ~/symlink-test2
~/symlink-test2$ echo "Это тестовый файл" > notes.txtАбсолютный или относительный путь. Ссылку можно создать с абсолютным путем или относительным. Это важно при переносе файлов: относительная ссылка останется рабочей, если переместить и ссылку, и цель в новое место вместе, сохранив их взаимное расположение, а абсолютная – только если не менять расположение самой цели.
~/symlink-test2$ ln -s "$(pwd)/notes.txt" abs-link.txt
~/symlink-test2$ ln -s notes.txt rel-link.txt
~/symlink-test2$ readlink abs-link.txt
/home/betutorial/symlink-test2/notes.txt
~/symlink-test2$ readlink rel-link.txt
notes.txtВидно, что readlink возвращает именно тот путь, который был записан в ссылку при создании, – в первом случае полный, во втором относительный.
Symlink можно создать на несуществующую цель. Linux не проверяет при создании символической ссылки, существует ли путь, на который она указывает, – ошибки не будет, даже если будет опечатка в пути:
~/symlink-test2$ ln -s not-yet-created.txt future-link.txt
~/symlink-test2$ ls -l future-link.txt
lrwxrwxrwx 1 betutorial betutorial 19 Aug 18 11:38 future-link.txt -> not-yet-created.txt
~/symlink-test2$ cat future-link.txt
cat: future-link.txt: No such file or directoryСсылка может стать “битой” в любой момент своей жизни – если цель удалили, переименовали или переместили. Найти все битые ссылки в директории можно при помощи утилиты find:
~/symlink-test2$ find . -xtype l
./future-link.txt
А потом узнать, куда именно ведет конкретная ссылка:
~/symlink-test2$ readlink future-link.txt
not-yet-created.txt
~/symlink-test2$ readlink -f future-link.txt
/home/betutorial/symlink-test2/not-yet-created.txtreadlink возвращает путь ровно в том виде, в каком он записан в ссылке, а readlink -f разворачивает его в полный абсолютный путь.
Symlink может указывать на другую ссылку, образуя цепочку. Система разворачивает такие цепочки автоматически, но если ссылки образуют цикл (ссылаются друг на друга), при обращении к ним будет ошибка:
~/symlink-test2$ ln -s notes.txt chain1.txt
~/symlink-test2$ ln -s chain1.txt chain2.txt
~/symlink-test2$ readlink chain2.txt
chain1.txt
~/symlink-test2$ readlink -f chain2.txt
/home/betutorial/symlink-test2/notes.txt
~/symlink-test2$ ln -s loop2.txt loop1.txt
~/symlink-test2$ ln -s loop1.txt loop2.txt
~/symlink-test2$ cat loop1.txt
cat: loop1.txt: Too many levels of symbolic linksПримеры использования символических ссылок
Рассмотрим несколько типичных задач, в которых symlink находит применение на практике:
- Обновление сайта без остановки (деплой релизов)
Каждая версия сайта разворачивается в отдельную директорию с номером или датой релиза, а на актуальную указывает единый symlink current – именно он настроен как document root веб-сервера:
ln -sfn /var/www/site/releases/2026-08-15 /var/www/site/currentОбновление сводится к одной команде – переключить ссылку на новый релиз. Откат к предыдущей версии делается точно так же, без повторной выгрузки файлов. Благодаря этому переключение происходит мгновенно и без простоя.
- Переключение между версиями Python, Node.js и других сред
Если на сервере установлено несколько версий одного языка или рантайма (например, /opt/node-18 и /opt/node-20), удобно не переписывать пути в каждом проекте или скрипте при переходе на новую версию, а один раз добавить символическую ссылку и переключать ее:
ln -sfn /opt/node-20 /usr/local/nodeВсе проекты и скрипты обращаются к /usr/local/node/bin/node и не знают, какая версия установлена на самом деле. Перейти на другую версию – значит перелинковать одну ссылку, а не искать и менять путь во всех местах, где он был прописан. Если новая версия окажется несовместимой, откат назад – снова одна команда.
- Хранение загружаемых файлов на отдельном диске
Когда файлы, которые загружают пользователи, растут быстрее, чем код приложения, их удобно вынести на отдельный диск или раздел, а в директории сайта оставить только ссылку:
ln -s /mnt/storage/uploads /var/www/site/uploadsКод приложения продолжает работать с привычным путем uploads/, ничего в нем менять не нужно, а хранилище можно расширять независимо от диска с самим сайтом.
- Включение и отключение сайтов в Nginx
В Debian и Ubuntu конфигурации сайтов принято хранить в sites-available, а подключать – символической ссылкой из sites-enabled:
ln -s /etc/nginx/sites-available/example.com.conf /etc/nginx/sites-enabled/example.com.confОтключить сайт – значит просто удалить ссылку, не трогая сам файл конфигурации. Это удобнее, чем закомментировать блок server или хранить несколько версий одного конфига: включение и отключение сайта не требуют правок самого файла и не рискуют испортить его синтаксис.
Заключение
Symlink – это простой указатель на другой файл или директорию: не копия, а еще один путь к тем же данным. В отличие от жесткой ссылки, он может вести на директорию и работать между разными дисками и разделами, но зато способен “сломаться”, если цель удалят или переместят.
Для повседневной работы достаточно нескольких команд: ln -s – создать ссылку, ln -sfn – заменить существующую, rm или unlink – удалить, readlink -f – проверить, куда она ведет, даже если цель не существует. С этим набором symlink пригодится и для деплоя, и для организации файлов на сервере, и для десятков других задач, где не хочется дублировать данные.
Если возникнут вопросы, напишите нам, пожалуйста, тикет из панели управления аккаунта (раздел “Помощь и поддержка”), а если вы захотите обсудить эту статью или наши продукты с коллегами по цеху и сотрудниками Beget – ждем вас в нашем сообществе в Telegram.