Что хранится в правах файла
Каждый inode (метаданные файла) в Linux содержит 16-битное поле mode: 4 бита типа файла (regular, dir, symlink, …), 3 бита special permissions (SUID, SGID, sticky — урок 05) и 9 бит обычных прав. Эти 9 бит распадаются на три группы по три:
- owner (u): что может делать владелец
- group (g): что может делать primary group файла
- other (o): что могут все остальные
Каждая группа — три бита: r (read), w (write), x (execute). Сложите три по три, получите 9 бит. Это и есть то, что показывает ls -l:
$ ls -l report.csv
-rw-r--r-- 1 levo levo 1024 May 13 12:34 report.csv
Первый символ - — тип файла (regular file). Далее идут три тройки: rw- для owner, r-- для group, r-- для other. Это значит: я могу читать и писать, моя группа может только читать, любой посторонний — тоже только читать.
Каждый символ — это один бит. Дефис = бит выключен.
Что значат rwx для файлов и директорий
Один и тот же бит rwx имеет разный смысл в зависимости от того, файл это или директория:
Для директорий смысл совершенно другой — это часто сбивает.
Контринтуитивный момент: чтобы удалить файл, нужен w на директории, а не на самом файле. Файл — это просто имя в директории, оно содержится в данных директории. Удаление = модификация списка имён.
$ touch ~/readonly.txt
$ chmod 0444 ~/readonly.txt # read-only для всех
$ rm ~/readonly.txt
rm: remove write-protected regular file 'readonly.txt'? y
removed '/home/levo/readonly.txt'
rm спросил подтверждение (потому что нет w на самом файле), но потом всё равно удалил — у меня есть w на ~. Если убрать w с домашней директории — rm упадёт с Permission denied.
Octal: 4-2-1
Symbolic нотация rwxr-xr-x читается, но в скриптах её писать неудобно. Поэтому существует octal — каждая тройка кодируется одной цифрой:
r= 4w= 2x= 1-= 0
Складываем биты в тройке — получаем цифру от 0 до 7. Девять бит = три цифры:
Запомни эти комбинации — они покрывают 95% случаев.
Канонические комбинации, которые ты увидишь каждый день:
0755 = rwxr-xr-x — для исполняемых файлов и большинства директорий
0644 = rw-r--r-- — для обычных data-файлов
0600 = rw------- — для приватных файлов: ssh-ключи, env-файлы
0700 = rwx------ — для приватных директорий: ~/.ssh
0666 = rw-rw-rw- — world-writable файл (опасно)
0777 = rwxrwxrwx — world-writable executable (очень опасно)
Префиксная 0 обычно опускается: chmod 755 == chmod 0755. Четвёртая цифра (специальные биты SUID/SGID/sticky) появится в уроке 05.
$ chmod 0644 report.csv
$ ls -l report.csv
-rw-r--r-- 1 levo levo 1024 May 13 12:34 report.csv
$ chmod 0755 deploy.sh
$ ls -l deploy.sh
-rwxr-xr-x 1 levo levo 512 May 13 12:35 deploy.sh
Когда какие права
Заучи это — будешь правильно настраивать сервисы с первого раза.
Symbolic: точечные изменения
Octal удобен когда задаёшь все права сразу. Когда нужно добавить или убрать один бит, не трогая остальные — используется symbolic:
chmod [who][op][perm] file
- who:
u(owner),g(group),o(other),a(все) - op:
+(добавить),-(убрать),=(установить ровно) - perm:
r,w,x(плюсX,s,t— будут позже)
$ chmod u+x script.sh # добавить execute для owner
$ chmod g-w report.csv # убрать write для group
$ chmod o=r notes.txt # для other — ровно read (исчезнет всё остальное)
$ chmod a+r data.parquet # readable для всех
$ chmod u+x,g+x,o-r file # несколько за раз через запятую
a это shortcut для ugo. Если опустить who — chmod +x действует на a (минус umask, но это редко важно).
X — умный execute
Заглавный X ставит execute только если это директория или у файла уже есть хотя бы один execute-bit:
$ chmod -R a+X .
# Сделать всё traversable: на dirs поставит x для всех,
# но на data-файлах НЕ поставит — там execute не нужен.
Это критически полезно при chmod -R на смешанной директории. Без X ты бы испортил права на data-файлы.
# [X] ПЛОХО — даст +x всем CSV, парквет-файлам, etc:
$ chmod -R a+rx /data
# [x] ХОРОШО — даст +x только директориям и executable-ам:
$ chmod -R a+rX /data
umask: что отрезается у новых файлов
Когда touch file или open(... O_CREAT) создаёт новый файл, kernel не назначает ему права 0666 — он применяет umask (user file-creation mask). umask — это битовая маска, которая вычитается из дефолтных прав:
- Дефолт файла: 0666 (rw-rw-rw-)
- Дефолт директории: 0777 (rwxrwxrwx)
- Реальные права = дефолт AND NOT umask
$ umask
0022
$ touch newfile
$ ls -l newfile
-rw-r--r-- 1 levo levo 0 May 13 12:40 newfile
# 0666 AND NOT 0022 = 0644 -> rw-r--r--
$ mkdir newdir
$ ls -ld newdir
drwxr-xr-x 2 levo levo 4096 May 13 12:40 newdir
# 0777 AND NOT 0022 = 0755 -> rwxr-xr-x
Дефолтный umask=0022 на большинстве Linux: «убери write у group и other». Это стандарт для multi-user системы — твои файлы по умолчанию читаемы, но не записываемы для других.
AND NOT — побитовая операция: то, что в umask — исключается.
Когда менять umask
- 0077 — все приватно. Используется на bastion-хостах, для root-сессии. Новые файлы будут
0600, директории0700. - 0002 — group-shared. В shared dir под группой
data-teamновые файлы будут0664, директории0775. Часто используется вместе с SGID.
# В .bashrc или /etc/profile.d/secure.sh
umask 0077
Изменения umask — пер-процесс. Дочерние процессы наследуют. Сессионно: umask 0027 — действует до выхода. Постоянно: пишешь в /etc/profile, ~/.bashrc или systemd unit-file (UMask= директива).
chmod -R: рекурсивно
$ chmod -R 0755 /opt/myapp # ВСЕ файлы получат 0755 — даже data!
$ chmod -R u+rwX,go+rX /opt/myapp # ЛУЧШЕ — X умный
Второй вариант: owner получает полный доступ, group/other могут читать и traverse-ить директории, но не получают +x на не-executable файлах.
Альтернатива через find:
# Директориям 0755, файлам 0644
$ find /opt/myapp -type d -exec chmod 0755 {} +
$ find /opt/myapp -type f -exec chmod 0644 {} +
# Скрипты с .sh — отдельно 0755
$ find /opt/myapp -name '*.sh' -exec chmod 0755 {} +
Это самый чистый паттерн для post-deployment правки прав.
Попробуй сам
- Создай файл и поставь права
0640:echo "secret data" > confidential.txt chmod 0640 confidential.txt ls -l confidential.txt - Сделай скрипт исполняемым через symbolic:
echo '#!/bin/bash
echo hi’ > hello.sh chmod u+x hello.sh ./hello.sh
3. Посмотри текущий umask и измени его временно:
```bash
umask
umask 0077
touch private.txt
ls -l private.txt # будет 0600
- Рекурсивный fix прав на проекте:
mkdir -p /tmp/proj/{data,scripts} touch /tmp/proj/data/a.csv /tmp/proj/scripts/run.sh find /tmp/proj -type d -exec chmod 0755 {} + find /tmp/proj -type f -exec chmod 0644 {} + chmod 0755 /tmp/proj/scripts/run.sh
macOS-различия
- На macOS
chmodподдерживает дополнительные ACL-флаги через+a(POSIX ACL расширенные). Базовый rwx работает идентично. - Default umask на macOS —
0022, как и в Linux. - На APFS есть extended attributes и quarantine-флаги (
com.apple.quarantine), которые иногда блокируют выполнение даже приchmod +x. Снимаются черезxattr -d com.apple.quarantine file.
Главное
- 9 бит прав делятся на тройки owner/group/other, каждая тройка — это rwx.
- В octal:
r=4, w=2, x=1. Канон:0644(data),0755(executables/dirs),0600(secrets),0700(private dirs). - В symbolic:
chmod u+x file,chmod g-w report.csv,chmod a+rX dir/. X(заглавный) — execute только для dirs и уже-executable файлов. Безопаснееxпри-R.- umask — биты, которые вычитаются из дефолта при создании файла. Дефолт
0022-> файлы0644, директории0755. - Для рекурсивного fix прав на mixed-content лучше
find -type d+find -type fраздельно.