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 -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 часто путают.
$ 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).
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)
Это спасает в двух случаях:
- Файл без расширения —
file mystery_fileскажет, что внутри. - Подозрение, что расширение неправильное — кто-то прислал
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
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 # теперь можно