
Я читал руководство по использованию chattr
на моей машине Linux ( kali4-amd64
), когда увидел это в списке определений атрибутов файлов:
A directory with the 'P' attribute set will enforce a hierarchical
structure for project id's. This means that files and directory created in
the directory will inherit the project id of the directory, rename
operations are constrained so when a file or directory is moved into
another directory, that the project id's much match. In addition, a hard
link to file can only be created when the project id for the file and the
destination directory match.
Я лично не знаю, что такое «идентификатор проекта» в Linux/UNIX, и многократные поиски в Google тоже не дали результатов, поэтому я надеюсь, что кто-нибудь здесь сможет мне помочь.
решение1
То, о чем вы спрашиваете, является частью концепции проектных квот. Проектные квоты — это способ управлениядисковая квота. Конкретный тип файловой системы может поддерживать или не поддерживать идентификаторы проекта. Давайте сосредоточимся на ext4 и начнем с man 8 tune2fs
:
-O [^]feature[,...]
Установить или очистить указанные функции (опции) файловой системы в файловой системе. […][…]
project
Включить отслеживание идентификатора проекта. Используется для отслеживания квоты проекта.
quota
Включить внутреннюю квоту файловой системы inodes.[…]
-Q quota-options
Устанавливает функцию 'quota' на суперблоке и работает с файлами квот для заданного типа квоты. Параметры квот могут быть одним или несколькими из следующих:
[^]usrquota
Устанавливает/очищает inode квоты пользователя в суперблоке.
[^]grpquota
Устанавливает/очищает групповую квоту inode в суперблоке.
[^]prjquota
Устанавливает/очищает inode квоты проекта в суперблоке.
Вы можете включить эти параметры в существующей файловой системе:
tune2fs -O project,quota /your/device
(или укажите их mke2fs
при создании новой файловой системы). Затем включите квоту проекта (возможно, с квотой пользователя и/или квотой группы, если хотите):
tune2fs -Q prjquota /your/device
Смонтируйте его:
mount /your/device /the/mountpoint
Теперь вы можете управлять квотами с помощью таких инструментов, как setquota
и quota
(обратите внимание, что в старых (-ish) версиях инструментов может отсутствовать опция -P
, которая обрабатывает квоты проекта). Традиционно вы бы ограничили объем дискового пространства, который может использовать пользователь или группа. С квотой проекта вы можете сделать это для «проектов», независимо от пользователей и групп, которые участвуют.
Это работает так. Сначала поместите себя в точку монтирования и создайте несколько каталогов:
cd /the/mountpoint
mkdir foo bar baz
Включить для них иерархию проектов:
chattr +P foo bar baz
Назначьте их на два разных проекта:
chattr -p 123 foo # 123 is an arbitrary number, project id
chattr -p 5 bar baz # so is 5, the point is they are different
Создавайте файлы в:
echo "lorem ipsum" > foo/file1
echo "lorem ipsum" > bar/file2
echo "lorem ipsum" > baz/file3
Теперь вызовите:
lsattr -pR .
и вы увидите (среди прочих) такие строки:
123 --------------e---P ./foo/file1
5 --------------e---P ./bar/file2
5 --------------e---P ./baz/file3
что означает file1
принадлежит проекту с id 123
, file2
и file3
принадлежит проекту с id 5
. Если вы определяете квоты для этих проектов (т.е. ограничиваете объем дискового пространства, которое могут использовать проекты), каждый файл будет влиять на потребление квоты соответствующего ему проекта.
Теперь то, что вы процитировали, имеет большой смысл:
файлы и каталоги, созданные в каталоге, унаследуют идентификатор проекта каталога
В нашем примере file1
унаследовал идентификатор проекта от foo
. Если вы создадите больше файлов/каталогов в , foo
то они также унаследуют идентификатор. Это позволяет вам (и другим пользователям) работать над проектом в его назначенном каталоге, в то время как файлы, которые вы создаете, автоматически учитываются в соответствующей квоте.
жесткая ссылка на файл может быть создана только в том случае, если идентификатор проекта для файла и целевой директории совпадают.
ln ./baz/file3 ./foo/
потерпит неудачу (попробуйте), но ln ./baz/file3 ./bar/
получится. ОС не позволит вам легко «встроить» файл, который принадлежит одному проекту (и должен оставаться таким, поскольку исходный путь не отсоединен) в другой каталог проекта. Связывание файла внутри его проекта разрешено.
когда файл или каталог перемещается в другой каталог, идентификаторы проекта должны совпадать
Я думаю, что это довольно обманчиво. mv
будет делать свою работу, даже если идентификаторы не совпадают. Дело в том, что если вы вызываете
mv baz/file3 foo/
инструмент сначала попытается переместить rename(2)
файл по новому пути, но это не удастся (как и ln
выше). Обычно или в пределах того же проекта это будет успешно, и исходное имя исчезнет. Видимо, это поведение и есть то, о чем говорит "идентификаторы проекта должны совпадать".
Но mv
пока не выходит. Это как перемещение между файловыми системами: после mv
неудачного переименования он возвращается в режим копирования+удаления. По сути, он создаеткопия(с новым номером inode) в целевом каталоге. В нашем случае копия наследует идентификатор проекта foo
(как и любой новый файл в этом каталоге), поэтому она влияет на потребление квоты project 123
. Исходный путь затем отсоединяется. Это может повлиять на потребление квоты project 5
; а может и нет: жесткие ссылки или открытые файловые дескрипторы приведут к тому, что исходный inode и данные сохранятся.
Обратите внимание, что это несколько удивительно: создается новый файл, старые жесткие ссылки (если таковые имеются) не привязаны к новому файлу, дескрипторы файлов, указывающие на старый файл, не имеют никакого отношения к новому; как будто операция перемещения выполнялась между файловыми системами.
Есть способ сделать mv
переименование вместо копирования+удаления. Если вручную назначить исходный файл целевому проекту
chattr -p 123 baz/file3
тогда mv baz/file3 foo/
действительно переместит его без копирования, не нарушая жесткие ссылки (если таковые имеются). Но учтите, что номер проекта принадлежит inode (не пути, не имени, не записи каталога), поэтому chattr -p
влияет на все жесткие ссылки.
Поэтому, если вам нужно переместить большой файл (т. е. данные, хранящиеся в каком-то inode, а не просто в одной из многих жестких ссылок) в другой проект, изменение проекта и последующее перемещение избавит вас от ненужного копирования.