Файловая система, права, дескрипторы
↑ 1.2 ОС и Linux для разработчика · ← Предыдущая · → Следующая
Зачем это на собесе
Сервис пишет логи, временные файлы, читает конфиги и сертификаты, монтирует volumes в Docker. Ошибки «Permission denied» и «Too many open files» — классика продакшена.
Подтемы
- Файловая система Linux, inode, ссылки
- Права доступа, chmod/chown, umask, особые биты
- Файловые дескрипторы, ulimit
- Работа с файлами в .NET
- Файлы в Docker
Объяснение
Файловая система Linux
- Единое дерево от
/. Важные каталоги:/etc(конфиги),/var/log(логи),/tmp(временные),/home,/app(обычно приложение в контейнере),/proc(виртуальная ФС с информацией о процессах). - «Всё есть файл»: устройства, сокеты, пайпы тоже представлены файлами.
- inode хранит метаданные файла (права, владельца, размер, блоки). Имя — ссылка на inode.
- Жёсткая ссылка — ещё одно имя того же inode. Символическая (
ln -s) — файл-указатель на путь.
Права доступа
Пример вывода ls -l: -rwxr-x--- 1 app app 4096 appsettings.json
| Символы | Кому | Что значит |
|---|---|---|
- | тип | обычный файл (d каталог, l символическая ссылка) |
rwx | владелец (user) | чтение, запись, выполнение |
r-x | группа (group) | чтение и выполнение |
--- | остальные (other) | нет прав |
r(4) чтение,w(2) запись,x(1) выполнение. Для каталогаx— право войти.chmod 640 file→ rw-r-----.chown app:app file— сменить владельца.umask— маска прав по умолчанию для новых файлов.- Особые биты: setuid, setgid, sticky (на
/tmp— удалять можно только свои файлы).
Файловые дескрипторы
Процесс обращается к открытым файлам, сокетам и пайпам через целые числа — дескрипторы (0 stdin, 1 stdout, 2 stderr).
- Лимит на процесс:
ulimit -n(часто 1024 по умолчанию, в контейнерах выше). - Каждое TCP-соединение — дескриптор. Утечка соединений или файлов (не вызван
Dispose) →Too many open files.
ls -l /proc/<pid>/fd | wc -l # сколько дескрипторов открыто
lsof -p <pid> # какие именноВ .NET
// всегда освобождать файловые ресурсы
await using var stream = File.OpenRead(path);
using var reader = new StreamReader(stream);
// кроссплатформенные пути
var logPath = Path.Combine(AppContext.BaseDirectory, "logs", "app.log");
var tmp = Path.GetTempFileName();
// права (Unix)
File.SetUnixFileMode(path, UnixFileMode.UserRead | UnixFileMode.UserWrite);В Docker
- Контейнер лучше запускать не от root (
USER appв Dockerfile). Тогда volume, смонтированный с хоста, должен быть доступен этому UID, иначе «Permission denied». - Логи пишите в stdout/stderr, а не в файлы внутри контейнера: их собирает Docker или агент.
- Файловая система контейнера эфемерна: всё, что нужно сохранить, — в volume или объектное хранилище (MinIO).
Нюансы и подводные камни
- Windows и Linux: регистр в именах файлов (
Config.json≠config.jsonв Linux), разделители путей. ИспользуйтеPath.Combine. - Удалённый, но открытый процессом файл продолжает занимать место (частая загадка «диск заполнен, а файлов нет» — ротация логов без переоткрытия).
- Запись больших временных файлов в слой контейнера раздувает его и замедляет. Используйте volume или tmpfs.
- Права 777 «чтобы заработало» — дыра в безопасности.
Вопросы с ответами
Как читать права -rwxr-x--- и что значит chmod 750?
Владелец rwx, группа r-x, остальные без прав. 750 = 7 (rwx) владельцу, 5 (r-x) группе, 0 остальным.
Что такое файловый дескриптор и почему возникает Too many open files?
Целочисленный идентификатор открытого файла, сокета или пайпа в процессе. Ошибка возникает при превышении лимита: обычно из-за утечки (не закрыты файлы или соединения) или слишком низкого ulimit.
Почему контейнер не может записать в смонтированный volume?
Процесс работает под пользователем без прав на каталог хоста (UID и GID не совпадают). Решение: выставить владельца и права на хосте, запускать с нужным UID или использовать named volume.
Куда писать логи сервиса в контейнере?
В stdout и stderr в структурированном виде. Сбор, ротацию и отправку делает инфраструктура (Docker driver, агент, OTel Collector).
Связанные темы
- Предыдущая: Память: стек, куча, виртуальная память · Следующая: Linux и shell для бэкендера: логи, сигналы, переменные окружения
- IDisposable и using: IDisposable, using, финализаторы, IAsyncDisposable
- Linux в DevOps: Этап 1 · Фундамент — Linux, Bash, сети
- Оптимизация Docker-образов (non-root): 2.6 Оптимизация образов — размер, .dockerignore, non-root, distroless, chiseled
- Хранение файлов в MinIO: Хранение и отдача файлов через MinIO