link()
Функция link() в PHP создаёт жёсткую ссылку — второй элемент файловой системы, указывающий на тот же inode, что и исходный файл.
Функция PHP link() создаёт жёсткую ссылку — второй элемент файловой системы, указывающий на те же данные на диске, что и существующий файл. На этой странице рассказывается, что такое жёсткая ссылка, описывается синтаксис и возвращаемое значение функции, приводится полный рабочий пример, объясняются отличия от символической ссылки, а также разбираются частые причины ошибок.
Что такое функция link()?
link() создаёт жёсткую ссылку от существующего файла (цели) к новому имени (ссылке). Жёсткая ссылка — это не копия и не ярлык: это второй элемент каталога, ссылающийся на тот же inode — базовый объект на диске, хранящий данные и метаданные файла. Поскольку оба имени указывают на один и тот же inode, они полностью взаимозаменяемы: редактирование через одно имя отражается при обращении через другое, а данные файла удаляются только после того, как будут удалены все жёсткие ссылки на него.
Из этого непосредственно следуют два вывода:
- Жёсткие ссылки должны находиться на той же файловой системе (разделе), что и цель. Inode-ы локальны для файловой системы, поэтому создать жёсткую ссылку через диски или точки монтирования невозможно. Если нужно создать ссылку между файловыми системами, используйте символическую ссылку — см.
symlink(). - Жёсткие ссылки на директории обычно запрещены. Большинство операционных систем не разрешают жёсткие ссылки на директории, чтобы предотвратить циклические ссылки в дереве файловой системы.
Синтаксис
link(string $target, string $link): bool| Параметр | Описание |
|---|---|
$target | Путь к существующему файлу, на который нужно создать ссылку. |
$link | Путь новой жёсткой ссылки (не должна существовать заранее). |
Функция возвращает true в случае успеха и false при ошибке, при этом генерируется предупреждение E_WARNING.
Полный рабочий пример
Этот пример создаёт файл, создаёт жёсткую ссылку на него, а затем подтверждает, что оба имени разделяют один inode:
<?php
$target = __DIR__ . '/target.txt';
$link = __DIR__ . '/hardlink.txt';
file_put_contents($target, "Hello hard links\n");
if (link($target, $link)) {
echo "Created hard link\n";
}
echo "Same inode? " . (fileinode($target) === fileinode($link) ? "yes" : "no") . "\n";
echo "Link count: " . stat($target)['nlink'] . "\n";
echo "Read via link: " . file_get_contents($link);
unlink($link); // remove only the new name
echo "After unlink, target still exists? " . (file_exists($target) ? "yes" : "no") . "\n";Вывод:
Created hard link
Same inode? yes
Link count: 2
Read via link: Hello hard links
After unlink, target still exists? yesОбратите внимание: после вызова link() количество ссылок (nlink) равно 2 — inode теперь имеет два имени. Удаление одного имени с помощью unlink() лишь уменьшает этот счётчик; данные сохраняются до тех пор, пока счётчик не достигнет нуля. Именно поэтому удаление файла с жёсткой ссылкой не освобождает дисковое пространство, если остались другие жёсткие ссылки.
Корректная обработка ошибок
Поскольку link() генерирует предупреждение при ошибке, в рабочем коде обычно подавляют предупреждение с помощью @ и проверяют возвращаемое значение, либо заранее проверяют путь назначения:
<?php
$target = __DIR__ . '/target.txt';
$link = __DIR__ . '/hardlink.txt';
if (file_exists($link)) {
echo "A file already exists at the link path.\n";
} elseif (@link($target, $link)) {
echo "Hard link created.\n";
} else {
echo "Could not create hard link.\n";
}Частые причины возврата false функцией link():
- Целевой файл не существует, или у вас нет прав на его чтение.
- У вас нет прав на запись в директорию, где будет создана ссылка.
- Путь для ссылки уже занят.
- Цель и ссылка находятся на разных файловых системах.
- Цель является директорией (на большинстве систем запрещено).
Жёсткая ссылка vs. символическая ссылка
Жёсткая ссылка (link()) | Символическая ссылка (symlink()) | |
|---|---|---|
| Указывает на | Тот же inode (данные) | Путь (другое имя файла) |
| Переживает удаление оригинала | Да — данные хранятся, пока не удалены все ссылки | Нет — становится висячей ссылкой |
| Может пересекать файловые системы | Нет | Да |
| Может ссылаться на директорию | Как правило, нет | Да |
| Определяется с помощью | stat()['nlink'] > 1 | is_link() |
Если нужно проверить, является ли путь символической ссылкой, или узнать, куда она указывает, см. is_link() и readlink(). Для проверки метаданных ссылки используйте linkinfo().
Когда это использовать?
Жёсткие ссылки удобны для дедупликации и атомарной замены файлов. Инструменты резервного копирования используют их, чтобы неизменённые файлы в разных снапшотах занимали одну копию на диске. Сценарии развёртывания создают жёсткую ссылку на новую версию сборки и переименовывают её поверх старой, чтобы читатели никогда не видели частично записанный файл. Для повседневных задач типа «ярлык», когда нужно пересечь диски или указать на директорию, используйте symlink().
Заключение
link() создаёт жёсткую ссылку — второе имя для того же inode в той же файловой системе. Данные существуют до тех пор, пока не удалена последняя жёсткая ссылка; ссылки не могут пересекать файловые системы, а директории, как правило, не поддерживают жёсткие ссылки. Воспользуйтесь рабочим примером выше, чтобы самостоятельно убедиться в поведении общего inode, и используйте link() вместе с unlink(), symlink() и is_link() для полного управления ссылками в файловой системе. Для более широкого обзора файловых функций см. главу PHP Filesystem.