Коротко: символическая ссылка (симлинк, символьная ссылка) в Linux — это маленький файл, который указывает на другой путь. Создаётся она командой ln -s ЦЕЛЬ ИМЯ_ССЫЛКИ: сначала существующий файл или каталог, затем новая ссылка, в том же порядке, что и у cp. ls -l показывает, куда ведёт ссылка, а rm ИМЯ_ССЫЛКИ удаляет саму ссылку и не трогает цель.
ln -s /srv/app/releases/v2 /srv/app/current # ссылка на каталог
ln -s ../shared/config.yml config.yml # относительная ссылка на файл
ln -sfn releases/v3 current # перенаправить существующую ссылку на каталог
ls -l current # current -> releases/v3
rm current # удалить ссылку, а не цельВесь вывод на этой странице получен в Debian 12 с GNU coreutils 9.1 и findutils 4.9.0 во временном каталоге 21 октября 2026 года; абсолютные пути в выводе сокращены до /srv/app и /etc/nginx. Раздел про Windows написан по справке Microsoft по команде mklink и не запускался. В Ubuntu, Rocky Linux и AlmaLinux тот же GNU ln.
Что такое символическая ссылка
Символическая ссылка — это файл, всё содержимое которого составляет путь. Когда программа открывает ссылку, ядро идёт по этому пути и открывает цель, поэтому редакторы, веб-серверы и скрипты работают со ссылкой так, будто это настоящий файл или каталог. В выводе ls -l она начинается с буквы l и показывает цель после стрелки:
$ ln -sv releases/v2 app/current
'app/current' -> 'releases/v2'
$ ls -l app/current
lrwxrwxrwx 1 root root 11 Oct 21 19:45 app/current -> releases/v2Размер 11 — это длина текста releases/v2: ничего, кроме этой строки, ссылка не хранит. Симлинк похож на ярлык Windows, но с одним важным отличием: ярлык — это файл, который понимает только оболочка Windows, а символическую ссылку разрешает ядро, и работает она для любой программы.
Как создать символическую ссылку в Linux
ln -s принимает сначала цель, затем имя новой ссылки. Если указать только цель или вторым аргументом назвать существующий каталог, ссылка появится там под именем самой цели:
ln -s /etc/hostname # создаёт ./hostname -> /etc/hostname
ln -s /opt/tool/bin/tool /usr/local/bin/ # создаёт /usr/local/bin/tool
ln -s -t /usr/local/bin /opt/tool/bin/* # по ссылке на каждый файл, каталог назначения первымЦель не обязана существовать. ln всё равно создаст ссылку и ни о чём не предупредит: это удобно для ссылки, которую вы заполните позже, и это же классический способ получить битую ссылку из-за опечатки. Вторая частая ошибка — перепутанные аргументы: ln -s newlink real при существующем real завершается ошибкой failed to create symbolic link 'real': File exists, потому что ln пытается создать ссылку под именем вашего существующего файла.
Жёсткая ссылка и символическая: в чём разница
Без -s команда ln создаёт жёсткую ссылку: второе имя того же файла, а не указатель на путь. Оба имени делят один inode, и данные живут, пока не удалено последнее имя:
$ ln -v orig.txt hard.txt
'hard.txt' => 'orig.txt'
$ ls -li orig.txt hard.txt
3542701 -rw-r--r-- 2 root root 5 Oct 21 19:45 hard.txt
3542701 -rw-r--r-- 2 root root 5 Oct 21 19:45 orig.txt
$ rm orig.txt; cat hard.txt
data| Символическая (ln -s) | Жёсткая (ln) | |
|---|---|---|
| Что это | Маленький файл, в котором записан путь | Ещё одно имя того же inode |
| Цель удалена | Ссылка ломается (становится битой) | Данные остаются, второе имя работает |
| Каталоги | Да | Нет: hard link not allowed for directory |
| Между файловыми системами | Да | Нет: Invalid cross-device link |
| В выводе ls -l | l в начале, -> цель | Выглядит как обычный файл, счётчик ссылок больше 1 |
| Типичное применение | Текущий релиз, sites-enabled, программы в /usr/local/bin | Снимки бэкапов (rsync --link-dest), дедупликация |
Почти для всего на сервере нужен -s. Жёсткие ссылки встречаются в основном в инструментах резервного копирования, например в схеме со снимками из руководства по rsync.
Относительная или абсолютная цель?
Относительная цель отсчитывается от каталога, в котором лежит ссылка, а не от каталога, в котором вы были, когда набирали команду. Именно эта ошибка стоит за большинством битых ссылок:
$ ln -s notes.txt conf/notes # ищет conf/notes.txt
$ cat conf/notes
cat: conf/notes: No such file or directory
$ ln -sr notes.txt conf/notes # -r сам вычисляет относительный путь
'conf/notes' -> '../notes.txt'| Относительная (../shared/x) | Абсолютная (/srv/app/shared/x) | |
|---|---|---|
| Переживает перенос всего дерева | Да | Нет |
| Переживает перенос одной ссылки | Нет: в проверке рабочая ссылка, перенесённая на каталог ниже, дала No such file or directory | Да: абсолютная ссылка, перенесённая так же, продолжила работать |
| Работает в контейнере или chroot, где дерево смонтировано по другому пути | Да | Только если путь там такой же |
| Легко читать | Хуже | Лучше |
Простое правило: относительные ссылки — внутри одного проекта или дерева релизов, абсолютные — из системных мест вроде /usr/local/bin или /etc/nginx/sites-enabled.
Как заменить ссылку: -f и -n
ln отказывается перезаписывать существующее имя. Ключ -f сначала удаляет старое, и для ссылки на файл этого достаточно:
$ ln -s target.txt name
ln: failed to create symbolic link 'name': File exists
$ ln -sfv target.txt name
'name' -> 'target.txt'Со ссылкой на каталог один -f делает не то: ln проходит по существующей ссылке внутрь каталога и создаёт новую ссылку уже там. -n велит ln считать существующую ссылку обычным файлом, поэтому ссылки на каталоги всегда перенаправляйте через -sfn:
$ ln -sfv releases/v3 app/current
'app/current/v3' -> 'releases/v3' # неверно: новая ссылка внутри releases/v2
$ ln -sfnv releases/v3 app/current
'app/current' -> 'releases/v3' # верноЕсли при переключении релиза ни один запрос не должен застать ссылку отсутствующей, создайте новую ссылку под временным именем и переименуйте её поверх старой командой mv -T current.new current: rename() заменяет имя атомарно.
Куда ведёт ссылка: readlink и realpath
$ readlink app/current
releases/v3
$ readlink -f app/current
/srv/app/releases/v3
$ realpath app/current
/srv/app/releases/v3Простой readlink печатает текст, записанный в ссылке, и раскрывает только один уровень. readlink -f и realpath проходят по всей цепочке ссылок и печатают итоговый абсолютный путь. Разница между вариантами видна на битых ссылках: для ссылки на несуществующий файл readlink -f и realpath всё равно напечатали предполагаемый путь с кодом возврата 0, а readlink -e не напечатал ничего и вернул 1, поэтому в скрипте проверять нужно именно им. pwd -P делает то же для текущего каталога; к чему это приводит, показано в руководстве по pwd (англ.).
Как найти и исправить битые симлинки
$ ls -l broken
lrwxrwxrwx 1 root root 11 Oct 21 19:45 broken -> missing.txt
$ cat broken
cat: broken: No such file or directoryОшибка называет саму ссылку, а она-то существует, поэтому поначалу это сбивает с толку. find -type l выводит все ссылки, а -xtype l — только те, чья цель отсутствует:
find /etc /usr/local -xtype l # список битых ссылок
find ./etc -xtype l -print -delete # удалить их, сначала прочитав списокВ проверке -xtype l вывел две битые ссылки и пропустил рабочую. Ссылка, которая указывает сама на себя, напрямую или по кругу, ломается иначе: cat a ответил Too many levels of symbolic links. Подробнее об этих проверках — в руководстве по find (англ.).
Как удалить симлинк: rm или unlink, без слеша в конце
rm current или unlink current удаляет ссылку и оставляет цель в покое. Проблемы начинаются со слеша в конце, который автодополнение оболочки добавляет к ссылке на каталог:
$ rm current/
rm: cannot remove 'current/': Is a directory
$ unlink current/
unlink: cannot unlink 'current/': Not a directory
$ rmdir current
rmdir: failed to remove 'current': Not a directory
$ rm -v current
removed 'current'Те же ошибки в русской локали
Если на сервере включена русская локаль, ln, rm и cat пишут те же ошибки по-русски, и искать их приходится уже в таком виде. Ниже — вывод тех же команд в Debian 12 (GNU coreutils 9.1) с переменными LC_ALL=C.UTF-8 и LANGUAGE=ru; в первом столбце тот же текст в английской локали:
| Английская локаль | Русская локаль | Что значит |
|---|---|---|
ln: failed to create symbolic link 'name': File exists | ln: не удалось создать символьную ссылку 'name': Файл существует | Имя уже занято: нужен -f (для каталога -sfn), или перепутаны аргументы |
cat: broken: No such file or directory | cat: broken: Нет такого файла или каталога | Цели ссылки нет: ссылка битая |
cat: a1: Too many levels of symbolic links | cat: a1: Слишком много уровней символьных ссылок | Ссылки указывают друг на друга по кругу |
ln: dd: hard link not allowed for directory | ln: dd: не допускается создавать жёсткие ссылки на каталоги | Для каталога нужен ln -s |
rm: cannot remove 'current/': Is a directory | rm: невозможно удалить 'current/': Это каталог | Уберите слеш в конце: rm current |
rmdir: failed to remove 'current': Not a directory | rmdir: не удалось удалить 'current': Это не каталог | Это ссылка, а не каталог: rm current |
Отсюда и разнобой в названиях: в переводе GNU coreutils это «символьная ссылка», в документации и статьях чаще пишут «символическая», а в разговоре говорят просто «симлинк». Все три слова означают одно и то же.
Права, владелец и копирование
- Права: у симлинка всегда
lrwxrwxrwx, и Linux их не учитывает. Значение имеют права цели.chmod 600 slinkпоменял права цели на-rw-------и не тронул ссылку; подробнее — в руководстве по chmod (англ.). - Владелец:
chownтоже действует на цель;chown -hменяет владельца самой ссылки. - Копирование: простой
cp slink copyскопировал содержимое цели в обычный файл;cp -P(иcp -a) скопировал ссылку как ссылку.rsync -aиtarтоже сохраняют ссылки ссылками.
Симлинки на сервере: sites-enabled в nginx и релизы
В Debian и Ubuntu файл nginx.conf подключает все файлы из /etc/nginx/sites-enabled, а не из sites-available. Сайт включают, создав ссылку на его файл из sites-available, а выключают, удалив ссылку:
sudo ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx
# снова выключить сайт: удалить ссылку, но никогда не файл в sites-available
sudo rm /etc/nginx/sites-enabled/example.com
sudo nginx -t && sudo systemctl reload nginx$ ls -l /etc/nginx/sites-enabled
lrwxrwxrwx 1 root root 38 Oct 21 19:46 example.com -> /etc/nginx/sites-available/example.comЗдесь берите абсолютный путь. ln -s sites-available/example.com sites-enabled/, набранная в /etc/nginx, создаёт битую ссылку: её относительная цель отсчитывается от sites-enabled, и ссылка указывает на sites-enabled/sites-available/example.com. Полная настройка сайта описана в руководстве по reverse proxy на nginx (англ.). На той же схеме построены деплои без простоя: каждый релиз лежит в своём каталоге, а current указывает на рабочий, так что откат — это один ln -sfn обратно на предыдущий релиз.
Символические ссылки в Windows: mklink
В Windows тоже есть симлинки, их создаёт команда mklink в командной строке. По справке Microsoft порядок аргументов обратный по сравнению с Linux: сначала новая ссылка, затем цель.
rem символическая ссылка на файл
mklink C:\links\app.conf C:\apps\app\app.conf
rem символическая ссылка на каталог
mklink /D C:\www\current C:\www\releases\v2
rem соединение каталогов (junction)
mklink /J C:\data D:\data
rem жёсткая ссылка
mklink /H C:\links\hard.txt C:\files\orig.txtДля создания символических ссылок по умолчанию нужны права администратора, поэтому открывайте командную строку через «Запуск от имени администратора». mklink — встроенная команда cmd, а не отдельная программа, поэтому в PowerShell используется своя команда:
New-Item -ItemType SymbolicLink -Path C:\www\current -Target C:\www\releases\v2На Windows VPS соединения каталогов (/J) — привычный способ перенести папку с данными на другой диск или раздел так, чтобы программы продолжали работать по старому пути: они связывают только папки на локальных томах, а для их создания права администратора не нужны.
Частые вопросы
Что такое символическая ссылка (симлинк) в Linux?
Символическая ссылка, она же симлинк, символьная или мягкая ссылка, — это маленький файл, в котором записан путь к другому файлу или каталогу. Когда программа открывает ссылку, ядро открывает цель. Если цель удалить или переместить, ссылка становится битой и никуда не ведёт. Создаётся она командой ln -s ЦЕЛЬ ИМЯ_ССЫЛКИ.
Чем жёсткая ссылка отличается от символической?
Символическая ссылка хранит путь: она может указывать на каталоги и на другие файловые системы и ломается, если цель удалить. Жёсткая ссылка — второе имя тех же данных: данные живут, пока существует хотя бы одно имя, но жёсткие ссылки нельзя создавать на каталоги и между файловыми системами.
Как удалить симлинк, не удалив цель?
Выполните rm имя_ссылки или unlink имя_ссылки без слеша в конце. Со слешем rm считает имя каталогом, на который указывает ссылка: rm -rf имя_ссылки/ удаляет содержимое каталога-цели, а саму ссылку оставляет на месте.