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

stat, file, xattr, chattr: метаданные и атрибуты

Файл в Linux — это не только содержимое. Это inode с метаданными: размер, права, владелец, три типа дат, расширенные атрибуты, security flags. В этом уроке — как смотреть всё это через stat, как определять тип файла, и как использовать chattr для защиты от удаления (даже root не сможет удалить).


stat: всё про файл

stat — детальная информация о файле:

$ stat /etc/passwd
  File: /etc/passwd
  Size: 2847        Blocks: 8          IO Block: 4096   regular file
Device: 8,1     Inode: 268241     Links: 1
Access: (0644/-rw-r--r--)  Uid: (    0/    root)   Gid: (    0/    root)
Access: 2026-05-13 12:00:00.000000000 +0000
Modify: 2026-04-15 10:30:00.000000000 +0000
Change: 2026-04-15 10:30:00.000000000 +0000
 Birth: 2024-01-01 00:00:00.000000000 +0000

Каждая строка:

Что показывает stat
Size: 2847Размер файла в байтах. Реальный логический размер
Blocks: 8Количество 512-байтных блоков, занятых на диске. Реальное физическое потребление (с учётом sparse, padding)
IO Block: 4096Оптимальный размер блока I/O для этой fs. Обычно 4KB на ext4
Inode: 268241Уникальный номер inode на этой fs. Hard links имеют одинаковый inode
Links: 1Количество hard links на этот inode. Обычно 1, для папок — N+2 (по подпапке и . и ..)
Access (0644)Права в восьмеричной системе + символьно. -rw-r--r-- — владелец чтение/запись, остальные только чтение
Uid / GidВладелец и группа. 0 = root. Можно увидеть как ID числом и как имя в скобках
Accessatime — когда файл последний раз ЧИТАЛИ. Обновляется на каждый read (если включено)
Modifymtime — когда КОНТЕНТ файла менялся (write, truncate)
Changectime — когда МЕТАДАННЫЕ inode менялись (chmod, chown, rename, hard link). НЕ creation time!
Birthbtime — реальное время создания файла. Только на современных fs (ext4 с правильным kernel). На некоторых fs — '-'

stat -c для кастомного форматирования:

# Только размер
$ stat -c '%s' /etc/passwd
2847

# Размер и mtime
$ stat -c '%s bytes, modified %y' /etc/passwd
2847 bytes, modified 2026-04-15 10:30:00.000000000 +0000

# В скриптах: получить mtime в unix timestamp
$ stat -c '%Y' /etc/passwd
1713187800

Формат: %s — size, %y — human mtime, %Y — unix mtime, %a — permissions octal, %U — owner name. Полный список: man stat.


atime, mtime, ctime, btime — четыре времени

Это критично понять — Junior часто путают.

Четыре временные метки файла
atimeAccess time. Когда файл последний раз ЧИТАЛИ (open для read, cat, less). По умолчанию обновляется на каждое чтение, но многие fs монтируются с relatime/noatime — обновляется реже для производительности
mtimeModify time. Когда КОНТЕНТ файла менялся (write, truncate, echo >>). НЕ обновляется при chmod
ctimeChange time. Когда МЕТАДАННЫЕ inode менялись: chmod, chown, rename, добавление hard link. НЕ creation time (хотя название путает)
btimeBirth time. Реальная дата создания. Появилась в современных fs. На старых системах — нет. Доступна через stat -c '%w' (но не везде)
$ touch test.txt
$ stat test.txt | grep -E "Access|Modify|Change"
Access: 2026-05-13 14:00:00     # atime
Modify: 2026-05-13 14:00:00     # mtime
Change: 2026-05-13 14:00:00     # ctime
# Все одинаковые при создании

$ cat test.txt                  # читаем
$ stat test.txt | grep Access
Access: 2026-05-13 14:00:15    # atime обновилось

$ echo "new content" >> test.txt    # пишем
$ stat test.txt | grep -E "Modify|Change"
Modify: 2026-05-13 14:00:30    # mtime обновилось
Change: 2026-05-13 14:00:30    # ctime тоже (inode size меняется)

$ chmod 0600 test.txt           # права
$ stat test.txt | grep -E "Modify|Change"
Modify: 2026-05-13 14:00:30    # mtime НЕ изменилось
Change: 2026-05-13 14:00:45    # ctime изменилось!

Это важно для:

  • find -mtime — поиск по mtime. «Файлы, изменившиеся за неделю» (контент).
  • find -ctime — «инодные изменения» (включая chmod, chown).
  • find -atime — «не читались давно» (для cleanup).
Inodes изнутри — как ядро хранит метаданные файла

atime — почему обычно noatime

На современных Linux atime по умолчанию обновляется как relatime: только если предыдущий atime < mtime, или > 24 часов. Это оптимизация: иначе каждое чтение файла = запись на диск (для обновления inode), что съедает производительность и SSD writes.

# Узнать настройки монтирования
$ mount | grep " / "
/dev/nvme0n1p1 on / type ext4 (rw,relatime,errors=remount-ro)
                                  ^^^^^^^^^^
                                  relatime по умолчанию

Можно отключить atime совсем — noatime:

# В /etc/fstab
/dev/nvme0n1p1   /   ext4   defaults,noatime  0 1

Это даёт ~10-20% прирост производительности read-heavy нагрузок. На DE-серверах с большим I/O — обычная практика.

Минус: программы, использующие atime для tmp-cleanup (например, tmpwatch), сломаются. Но это редко критично.


file: тип содержимого

file определяет тип файла, не по расширению, а по содержимому. Использует «magic numbers» — первые байты файла.

$ file /etc/passwd
/etc/passwd: ASCII text

$ file /usr/bin/ls
/usr/bin/ls: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2

$ file /etc/ssh/sshd_config
/etc/ssh/sshd_config: OpenSSH ssh_config file, ASCII text

$ file image.jpg
image.jpg: JPEG image data, JFIF standard 1.01

$ file backup.tar.gz
backup.tar.gz: gzip compressed data, last modified: ...

$ file /dev/null
/dev/null: character special (1/3)

Это спасает в двух случаях:

  1. Файл без расширенияfile mystery_file скажет, что внутри.
  2. Подозрение, что расширение неправильное — кто-то прислал data.csv, но это на самом деле gzip-архив.

В скриптах используется для проверки:

if file "$f" | grep -q "ASCII text"; then
    echo "Text file, can grep"
else
    echo "Binary, treat differently"
fi

Extended attributes (xattr)

Помимо стандартных метаданных (size, perms, owner) inode может хранить дополнительные атрибуты — расширенные (extended attributes, xattr). Это key-value пары.

Используются для:

  • ACL (Access Control Lists) — более гибкие права, чем rwx.
  • SELinux/AppArmor security labels.
  • Кастомные метаданные приложений.
  • macOS использует xattr для extended attributes Spotlight, quarantine для скачанных файлов.
# Linux: getfattr / setfattr (из attr пакета)
$ sudo apt install -y attr

$ touch test.txt
$ setfattr -n user.author -v "alice" test.txt

$ getfattr -d test.txt
# file: test.txt
user.author="alice"

# С system attributes
$ getfattr -d -m '.*' /etc/passwd
# Показывает все xattrs, включая системные

На macOS похожий концепт с xattr:

$ xattr -l ~/Downloads/file.dmg
com.apple.quarantine: 0083;...
# Apple использует xattr для маркировки скачанных файлов как 'непроверенные'

chattr: file attributes (Linux-specific)

chattr — это атрибуты файла на уровне filesystem. Это НЕ права (rwx) и НЕ xattr. Это специальные флаги, которые ext4/xfs хранят в inode.

Самый полезный для DE — immutable флаг (+i):

$ touch critical.conf
$ sudo chattr +i critical.conf

# Теперь ни один процесс, даже root, не может:
# - изменить содержимое
# - удалить файл
# - переименовать
# - hard link создать

$ sudo rm critical.conf
rm: cannot remove 'critical.conf': Operation not permitted

$ sudo echo "modify" >> critical.conf
bash: critical.conf: Operation not permitted

Для восстановления возможности изменения:

$ sudo chattr -i critical.conf
$ sudo rm critical.conf      # теперь работает

Это серьёзный layer защиты. Используется для:

  • Защита critical-конфигов (/etc/passwd, /etc/shadow иногда).
  • Audit-логи, которые не должны быть отредактированы.
  • Backup-маркеры, которые не должны случайно удалиться.

Посмотреть атрибуты:

$ lsattr critical.conf
----i------------- critical.conf     # i = immutable

Другие полезные флаги chattr:

  • +a — append-only. Можно дописывать, нельзя перезаписать. Идеально для log-файлов: даже компрометированный процесс не сможет затереть прошлые записи.
  • +s — secure delete. При удалении содержимое перезаписывается нулями (на старых fs; современные SSD и так не гарантируют это из-за wear leveling).
  • +u — undeletable. После удаления контент сохраняется, можно восстановить (на ext4 не поддерживается полноценно).
$ sudo chattr +a /var/log/audit.log
$ echo "append" >> /var/log/audit.log    # OK
$ echo "overwrite" > /var/log/audit.log  # FAIL
bash: /var/log/audit.log: Operation not permitted
WARNING

chattr — это только на Linux ext2/3/4/xfs. На macOS аналог — флаги chflags (uchg для immutable). На btrfs/zfs — собственные механизмы. В Docker-контейнерах chattr может не работать (capabilities ограничены).


Реальные DE-сценарии

Сценарий 1: защита production-конфига.

# После настройки сервиса
$ sudo chattr +i /etc/myapp/production.conf

# Теперь даже случайное `rm` или `sed -i` не сработают
# Только сначала chattr -i, потом изменение

Сценарий 2: append-only логи для compliance.

# Audit-лог финансовой системы
$ sudo touch /var/log/financial-audit.log
$ sudo chattr +a /var/log/financial-audit.log

# Приложение может только дописывать
# Атакующий с root не может удалить или подделать существующие записи (только новые добавить)

Сценарий 3: поиск файлов по mtime — что изменилось ночью.

# Файлы, которые менялись после 00:00 сегодня
$ find /var/data -newermt "$(date +%Y-%m-%d)" -type f

-newermt (newer modification time) — мощный фильтр для find. Можно комбинировать:

# Файлы между двумя датами
$ find /var/data -newermt "2026-05-12" -not -newermt "2026-05-14" -type f

Попробуй сам

$ cd ~/linux-sandbox

# stat в action
$ touch test-file
$ stat test-file
# Все 4 timestamp одинаковые

$ cat test-file       # обновит atime
$ stat -c "atime: %x, mtime: %y, ctime: %z" test-file

$ echo "hello" >> test-file    # обновит mtime + ctime
$ stat -c "atime: %x, mtime: %y, ctime: %z" test-file

$ chmod 0600 test-file    # обновит ctime
$ stat -c "atime: %x, mtime: %y, ctime: %z" test-file

file:

$ touch text.txt
$ echo "hello" > text.txt
$ file text.txt
text.txt: ASCII text

$ cp /usr/bin/ls .
$ file ls
ls: ELF 64-bit ...

chattr (нужен root):

$ touch protected.txt
$ sudo chattr +i protected.txt
$ lsattr protected.txt
----i------------- protected.txt

$ rm protected.txt
rm: cannot remove 'protected.txt': Operation not permitted

$ sudo chattr -i protected.txt
$ rm protected.txt    # теперь можно

Проверка знанийKnowledge check
Junior получает alert: 'файл /etc/myapp/secret.conf был изменён в 03:00 ночи, но никто не работал в это время — возможна компрометация'. Junior запускает `stat /etc/myapp/secret.conf`. Видит: 'Modify: 2025-12-01' (стабильное mtime), но 'Change: 2026-05-13 03:00'. Что произошло?
ОтветAnswer
Очень полезная разница mtime vs ctime для security. mtime обновляется при изменении КОНТЕНТА файла, ctime — при изменении inode-метаданных. Если mtime стабильное (2025-12), но ctime свежее (03:00 сегодня), значит контент НЕ менялся, но что-то изменилось в inode: (1) chmod (изменили права), (2) chown (сменили владельца), (3) rename (файл переместили или переименовали и вернули обратно), (4) добавлен/удалён hard link, (5) расширенные атрибуты (xattr) изменились. В контексте security-alert: НЕ компрометация контента файла, но кто-то возился с правами или владельцем. Дальше шаги: (1) Посмотреть auth.log для sudo-команд в 03:00: `sudo grep '03:0' /var/log/auth.log`. (2) Если есть auditd — проверить journal: `ausearch -f /etc/myapp/secret.conf`. (3) Сравнить ls -la вывод с baseline — какие права/owner сейчас vs ожидаемые. (4) Профилактика на будущее: `sudo chattr +i /etc/myapp/secret.conf` — immutable, никто не сможет изменить даже метаданные без явного снятия флага. Это даёт уверенность, что секретный конфиг не подменён в любом смысле.

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

Результат: 0 из 0
Концептуальный
Вопрос 1 из 5. В чём разница между mtime и ctime?

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

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

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

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