Learning Platform
Глоссарий Troubleshooting
Урок 07.03 · 18 мин
Начальный
chownchgrpOwnershipRecursiveFile permissions

Owner + group хранятся в inode

Каждый файл в Linux имеет ровно одного owner (UID) и ровно одну group (GID). Эти два числа лежат прямо в inode рядом с правами. Когда ls -l показывает:

$ ls -l report.csv
-rw-r--r-- 1 levo levo 1024 May 13 12:34 report.csv

Третий и четвёртый столбцы — это owner и group. Здесь оба равны levo. Это типичная конфигурация: файл создаётся пользователем levo, primary GID этого user — тоже levo (на современной Ubuntu каждому юзеру даётся своя группа того же имени, это называется UPG — User Private Group scheme).

Когда kernel проверяет доступ к файлу:

  1. Если process.euid == file.uid -> проверка по owner-битам
  2. Иначе если file.gid есть в group-list процесса -> проверка по group-битам
  3. Иначе -> проверка по other-битам

То есть order matters: если ты owner, тебе сразу применяются owner-биты, даже если они строже, чем group или other. Это часто удивляет: можно создать файл с правами 0066, и owner не сможет его прочитать, хотя другие могут.

chown: меняем owner

$ chown NEW_OWNER file
$ chown NEW_OWNER:NEW_GROUP file
$ chown :NEW_GROUP file      # только group
$ chown -R NEW_OWNER:NEW_GROUP dir/

Менять owner может только root. Это политика безопасности: иначе ты мог бы создать файл с какими угодно правами и “подарить” его другому пользователю, чтобы обойти его quota или вызвать атаку через quota-исчерпание.

# Под обычным юзером:
$ chown root:root myfile.txt
chown: changing ownership of 'myfile.txt': Operation not permitted

# Под sudo:
$ sudo chown postgres:postgres /var/lib/postgresql/16/main/pg_hba.conf
$ ls -l /var/lib/postgresql/16/main/pg_hba.conf
-rw------- 1 postgres postgres 4823 May 13 12:34 pg_hba.conf

Двоеточие vs точка

Разделитель user/group — :. Раньше (на BSD-системах и в очень старом Linux) поддерживалась точка chown user.group, но это устарело и может работать неправильно если в имени user есть .. Всегда :.

$ chown levo:data team_report.csv      # [x] канон
$ chown levo.data team_report.csv      # ВНИМАНИЕ: устарело, может сломаться

chgrp: меняем только group

chgrp group file — частный случай chown без смены owner. Эквивалент chown :group file. Обычный пользователь может менять group файла на любую, в которой он сам состоит:

$ groups
levo sudo docker

# Я в группе docker — могу присвоить эту группу файлу
$ chgrp docker myfile.txt   # [x] работает

# Я не в группе postgres — не могу
$ chgrp postgres myfile.txt
chgrp: changing group of 'myfile.txt': Operation not permitted

Рекурсия: chown -R

Самый частый DE-сценарий: после tar -xf или cp от root всё стало root-owned, и приложение не может писать в свои директории.

# Восстановили бэкап под root
$ sudo tar -xzf airflow-backup.tar.gz -C /opt

$ ls -l /opt/airflow/
drwxr-xr-x 3 root root 4096 May 13 logs/
drwxr-xr-x 2 root root 4096 May 13 dags/

# Чтобы airflow смог писать логи:
$ sudo chown -R airflow:airflow /opt/airflow

$ ls -l /opt/airflow/
drwxr-xr-x 3 airflow airflow 4096 May 13 logs/
drwxr-xr-x 2 airflow airflow 4096 May 13 dags/

-R рекурсивно проходит по дереву, изменяя owner на каждом файле и директории. Symlinks по умолчанию не следует — меняет owner самой ссылки. Флаг -h явно работает только на симлинках, -L следует по ним.

—reference: скопировать ownership с другого файла

$ sudo chown --reference=template.json new_file.json
# Возьмёт owner+group из template.json

Удобно когда восстанавливаешь один файл из бэкапа и нужно повторить ownership соседа.

—from: меняем только у тех файлов, где сейчас определённый owner

$ sudo chown -R --from=root airflow:airflow /opt/airflow
# Изменит owner только у файлов, которые СЕЙЧАС root.
# Файлы, уже принадлежащие airflow, не тронуты.

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

DE-сценарии: когда меняют ownership

Типичные DE-кейсы для chown

В работе DE chown срабатывает регулярно — почти всегда после операций под root.

После cp/scp от rootsudo chown -R user:user /opt/appЧасто файлы скопированы под sudo, теперь приложение не может в них писать. Standard fix.
После restore из backupsudo chown -R service:service /var/lib/servicetar -xf обычно сохраняет UID/GID из архива. Если бэкап делался на другой машине, числа могут не совпадать с локальными — нужен ремап.
Volume в Dockersudo chown -R 1000:1000 ./dataКонтейнер запущен от UID 1000, но volume на host принадлежит root. Контейнер не может писать. Решение — поправить ownership на host.
Получение файла от другого usersudo chown me:me incoming.csvКоллега положил CSV в /tmp под своим UID. Чтобы редактировать — нужно стать owner.
Переход на service-юзераsudo chown -R --from=root postgres:postgres /pg_dataПосле установки postgres из tarball — переводим всё на service-аккаунт.

Под капотом: чем отличается user-mode и kernel-mode

Команда chown levo:data file.csv приводит к syscall:

chown("file.csv", 1000, 100);   // (path, uid, gid)

Kernel:

  1. Открывает inode файла
  2. Проверяет capabilities процесса: CAP_CHOWN нужен для смены owner. У root она есть, у обычного user — нет (в default config).
  3. Если разрешено — обновляет поля i_uid и i_gid в inode, помечает inode dirty.
  4. Сбрасывает SUID/SGID-биты (если они были) — security-мера, чтобы нельзя было передать privileged executable.

Последний пункт важен: после chown SUID/SGID слетают. Если ты сделал chown root:root /usr/bin/passwd, ты потеряешь SUID и passwd перестанет работать для обычных юзеров. Восстановить — chmod u+s /usr/bin/passwd.

$ ls -l setuid_binary
-rwsr-xr-x 1 root root 0 May 13 setuid_binary    # SUID есть

$ sudo chown newowner setuid_binary
$ ls -l setuid_binary
-rwxr-xr-x 1 newowner root 0 May 13 setuid_binary  # SUID СЛЕТЕЛ

Numeric IDs

USER и UID в Docker — как работает ownership в контейнерах

Можно указывать UID/GID числом — особенно полезно в Docker, где имени airflow ещё может не быть в /etc/passwd контейнера:

$ chown 1001:1001 /data/airflow
# Эквивалентно chown airflow:airflow ЕСЛИ UID/GID совпадают

В Dockerfile часто так:

RUN chown -R 1001:1001 /opt/airflow

Это работает без зависимости от того, есть ли user airflow в image — kernel оперирует числами.

Если хочешь именованный chown в pure-number mode:

$ chown --no-dereference 1001:1001 file
$ chown -h 1001:1001 file     # short for --no-dereference

Если в имени есть только цифры (например, chown 1001 file), chown сначала ищет user с именем "1001" в /etc/passwd. Если такого нет — трактует как numeric UID. Чтобы заставить numeric:

$ chown +1001 file   # знак + явно говорит: это UID

Что НЕ может chown

  • Менять owner файла на несуществующий UID обычного user — root это всё-таки может. Появится файл с owner=12345, и ls -l покажет числовой UID без имени:
    $ ls -l orphan.txt
    -rw-r--r-- 1 12345 12345 0 May 13 orphan.txt
    Это случается, если ты восстановил из tar бэкапа другой машины с другими UID.
  • Менять owner файла на read-only FS — получишь EROFS. Сначала надо перемонтировать rw.
  • Менять owner на FAT32/exFAT — эти FS не имеют POSIX permissions, chown молча игнорируется.

Попробуй сам

  1. Создай файл и посмотри owner/group:
    touch mine.txt
    ls -l mine.txt   # должно быть твой_user:твой_user
  2. Узнай numeric UID и GID:
    stat -c '%u %g' mine.txt
  3. Создай файл под sudo и поменяй owner на себя:
    sudo touch /tmp/root_owned.txt
    ls -l /tmp/root_owned.txt
    sudo chown "$(id -u):$(id -g)" /tmp/root_owned.txt
    ls -l /tmp/root_owned.txt
  4. Скопируй ownership с одного файла на другой:
    touch template.txt new.txt
    sudo chown nobody:nogroup template.txt
    sudo chown --reference=template.txt new.txt
    ls -l template.txt new.txt

macOS-различия

  • chown на macOS работает одинаково, но дефолтная primary group там обычно staff (GID 20), не уникальная группа на пользователя.
  • chgrp идентичен.
  • На APFS меняется ownership как на ext4. На FAT-USB-флешках — игнорируется (нет POSIX-метаданных).
Проверка знанийKnowledge check
После восстановления Airflow из бэкапа ты выполнил 'sudo tar -xzf airflow-backup.tar.gz -C /opt'. Все файлы оказались с owner=1003:1003, потому что на старом сервере UID Airflow был 1003. На новом сервере UID Airflow — 1001. Какая команда исправит ситуацию максимально точечно, не трогая другие файлы в /opt?
ОтветAnswer
sudo chown -R --from=1003:1003 airflow:airflow /opt/airflow. Опция --from=OLD меняет owner ТОЛЬКО у файлов, которые сейчас принадлежат указанному OLD. Это нужно потому, что в /opt могут быть другие приложения (например, /opt/grafana, /opt/postgres) со своими ownership — слепое 'chown -R airflow:airflow /opt/airflow' сработает только если бы ты ограничил scope, но обычно делают так: chown -R airflow:airflow /opt/airflow и принимают, что все файлы внутри становятся airflow. Вариант --from точечнее: если в /opt/airflow по какой-то причине лежат файлы под root (например, конфиги из /etc/airflow), они не тронутся. На практике паттерн используют для миграций UID между серверами: tar сохраняет числовые UID, на новой машине эти числа имеют другой смысл — нужен ремап. Альтернатива: tar --owner=airflow --group=airflow при создании архива.

Главное

  • Owner + group хранятся в inode рядом с правами.
  • Менять owner может только root (через sudo chown). Менять group — owner файла (если он состоит в target group) или root.
  • Разделитель user/group — : (не точка).
  • chown -R рекурсивно, --reference=other копирует ownership с другого файла, --from=old ограничивает scope.
  • После chown слетают SUID/SGID — security-мера.
  • В Docker и в скриптах используй numeric UID/GID — это устраняет зависимость от наличия user в image.

Проверьте понимание

Результат: 0 из 0
Прикладной
Вопрос 1 из 4. Обычный пользователь levo пытается выполнить 'chown postgres:postgres data.csv' на файле, который он сам создал. Команда падает с 'Operation not permitted'. Почему?

Закончили урок?

Отметьте его как пройденный, чтобы отслеживать свой прогресс

Войдите чтобы оценить урок

Прогресс модуля
0 из 5