При создании Linux, одной из основных мыслей было то, что «Всё есть файл». И это действительно так. Здесь вы узнаете про типы файлов в Linux.
Файлы и их индексные дескрипторы (inode)
Каждый файл содержит какие-то данные, но где храниться информация о самом файле? Такую информацию называют метаданными. Метаданные хранятся в файловых дескрипторах, которые называют inod. Разные типы файловых систем работают с метаданными по разному, например ext4 выделяет некоторое место в начале раздела для хранения индексных дескрипторов. У каждого индексного дескриптора есть свой уникальный номер.
Индексный дескриптор хранит следующую информацию:
- свой номер;
- тип файла;
- владельца файла и права доступа к нему;
- время:
- создания файла (crtime);
- доступа к файлу, его ещё называют временем касания (atime);
- последнего изменения файла (mtime);
- последнего изменения метаданных файла (например изменили права доступа к файлу) (ctime:);
- физическое расположение блоков данных на диске.
Чтобы увидеть номера индексных дескрипторов к команде ls добавляют опцию -i:
alex@ubu:~$ ls -i /etc/ssh/ 928146 moduli 928421 ssh_host_dsa_key 933606 ssh_host_ed25519_key.pub 918838 ssh_config 928422 ssh_host_dsa_key.pub 918245 ssh_host_rsa_key 917921 ssh_config.d 928426 ssh_host_ecdsa_key 928420 ssh_host_rsa_key.pub 928412 sshd_config 928427 ssh_host_ecdsa_key.pub 928069 ssh_import_id 928147 sshd_config.d 928428 ssh_host_ed25519_key
В выводе возле каждого файла написан номер его индексного дескриптора.
Чтобы посмотреть некоторые метаданные файла, можете воспользоваться командой stat:
alex@ubu:~$ stat /etc/ssh/sshd_config File: /etc/ssh/sshd_config Size: 3281 Blocks: 8 IO Block: 4096 regular file Device: 802h/2050d Inode: 394570 Links: 1 Access: (0644/-rw-r--r--) Uid: ( 0/ root) Gid: ( 0/ root) Access: 2022-05-16 08:36:10.592000000 +0000 Modify: 2022-05-13 13:15:09.108000000 +0000 Change: 2022-05-13 13:15:09.108000000 +0000 Birth: 2022-05-13 13:08:03.289339233 +0000
Чтобы стало понятнее я разберу некоторый вывод:
- File: /etc/ssh/ssh_config — путь к файлу и его имя;
- Size: 3281 — размер файла в байтах;
- regular file — тип файла (обычный файл);
- Inode: 394570 — номер индексного дескриптора;
- Links: 1 — количество жестких ссылок (про жёсткие и мягкие ссылки будет написана следующая статья);
- Access: (0644/-rw-r—r—) Uid: ( 0/ root) Gid: ( 0/ root) — владелец и права доступа (это тоже разберём в других статьях);
- Access: — время последнего доступа к файлу;
- Modify: — время последнего изменения файла;
- Change: — время последнего изменения метаданных файла;
- Birth: — время создания файла (Ubuntu 20.04 — не могла вывести это значение, а 22.04 уже может, как и Debian 11).
В итоге, вы должны запомнить что каждому файлу соответствует какой-то inode. Но чтобы было удобнее обращаться к файлам им ещё придумали имена. Имена файлов, кстати, не находятся в индексных дескрипторах, они находятся в каталогах. А каталоги это тоже файлы, но об этом ниже.
Обычные файлы и каталоги
Мы уже рассматривали вывод команды ls -lh:
Тип файла | Права | | Кол-во ссылок | | | Владелец | | | | Группа | | | | | Размер | | | | | | Дата и время последнего доступа к файлу | | | | | | | Имя файла | | | | | | | | - rw-r--r-- 1 alex alex 0 ноя 26 16:17 file.txt
Если помните, первый символ указывает на тип файла. Пришло время узнать какие типы файлов бывают в Linux. А начнем мы с обычных файлов и каталогов.
На обычные файлы указывает символ тире «—«. Обычные файлы содержат какие-то данные. Это могут быть файлы изображений, сжатые файлы, текстовые файлы, файлы программ и другое.
Каталоги, это тоже файлы и на них указывает символ «d«. Они хранят некий список файлов, и это список состоит из строк, в которых записаны имена файлов и их индексные дескрипторы (inode).
Когда мы выполняем команду ls, то мы просто читаем текущий каталог как файл и видим список файлов. Также мы можем команде ls указать конкретный каталог, который нужно прочитать. Получается что команда ls это как команда cat, но только для каталогов:
alex@ubu:~$ ls dir1 file1 alex@ubu:~$ ls /etc/ssh/ moduli sshd_config.d ssh_host_ecdsa_key.pub ssh_host_rsa_key.pub ssh_config ssh_host_dsa_key ssh_host_ed25519_key ssh_import_id ssh_config.d ssh_host_dsa_key.pub ssh_host_ed25519_key.pub sshd_config ssh_host_ecdsa_key ssh_host_rsa_key
А когда мы в каталоге создаём новый файл, то для него выделяется свободный inode, в каталоге записывается новая строчка с именем этого файла и его индексным дескриптором. Ну и конечно на диск записываются какие-то блоки данных, чтобы физически поместить файл на диск. И когда мы открываем файл, например чтобы его отредактировать, мы по inode находим где этот файл физически лежит на диске. Так каталоги помогают нам обращаться к файлам по их именам.
Раз каталог это тоже файл, то он тоже имеет свой индексный дескриптор. Вот пример просмотра каталога с помощью команды stat:
alex@ubu:~$ stat dir1 File: dir1 Size: 4096 Blocks: 8 IO Block: 4096 directory Device: 802h/2050d Inode: 398016 Links: 2 Access: (0775/drwxrwxr-x) Uid: ( 1000/ alex) Gid: ( 1000/ alex) Access: 2022-05-16 08:43:30.267484822 +0000 Modify: 2022-05-16 08:43:30.267484822 +0000 Change: 2022-05-16 08:43:30.267484822 +0000 Birth: 2022-05-16 08:43:30.267484822 +0000
Тип файла — directory (каталог). Пустой каталог сразу занимает 4096 байт. Но размер каталога не зависит от размера файлов в нем. Например, в каталоге будет 10 файлов по 1 GB, при этом размер каталога останется равным 4096 байт. Размер каталога зависит от количества файлов в нем, ведь каталог это файл содержащий список файлов и чем он больше, тем больше размер каталога.
Например, создадим в нашем каталоге 500 пустых файлов и посмотрим на сколько увеличился размер каталога:
alex@ubu:~$ touch dir1/file-{001..500}.txt alex@ubu:~$ stat dir1/ File: dir1/ Size: 20480 Blocks: 40 IO Block: 4096 directory Device: 802h/2050d Inode: 398016 Links: 2 Access: (0775/drwxrwxr-x) Uid: ( 1000/ alex) Gid: ( 1000/ alex) Access: 2022-05-16 08:43:30.267484822 +0000 Modify: 2022-05-16 08:44:19.767639652 +0000 Change: 2022-05-16 08:44:19.767639652 +0000 Birth: 2022-05-16 08:43:30.267484822 +0000
Как видите 500 файлов в каталоге увеличило его размер до 20480 байт.
Файлы и каталоги это самые понятные типы файлов в Linux, ниже рассмотрим более необычные типы.
Файлы устройств
Устройства в Linux тоже представлены файлами, для них даже выделен каталог /dev который хранит виртуальную файловую систему devfs. Эта файловая система хранит список всех устройств компьютера. Такие устройства разделяются на символьные и блочные.
Вот пример некоторых устройств.
Виртуальное устройство консоли к которой мы подключаемся /dev/tty:
alex@ubu:~$ ls -l -i /dev/tty 12 crw-rw-rw- 1 root tty 5, 0 мая 16 08:36 /dev/tty
USB устройство подключенное к USB шине:
alex@ubu:~$ ls -l -i /dev/bus/usb/001/001 144 crw-rw-r-- 1 root root 189, 0 мая 16 08:36 /dev/bus/usb/001/001
Диски и их разделы:
alex@ubu:~$ ls -l -i /dev/sd* 220 brw-rw---- 1 root disk 8, 0 мая 16 08:36 /dev/sda 268 brw-rw---- 1 root disk 8, 1 мая 16 08:36 /dev/sda1 269 brw-rw---- 1 root disk 8, 2 мая 16 08:36 /dev/sda2 270 brw-rw---- 1 root disk 8, 3 мая 16 08:36 /dev/sda3
Как видите, все эти устройства представлены файлами. На символьные устройства указывает символ «c«, а на блочные символ «b«.
Блочные устройства это диски и их разделы, raid-массивы, и тому подобное. Эти устройства могут хранить файловую систему и файлы на ней. Они умеют обрабатывать операции ввода-вывода, то-есть умеют записывать или считывать блоки данных. И обычно поддерживают произвольный доступ к данным.
Символьные устройства это COM-порты, LPT-порты, PS/2-мышки и клавиатуры, USB-мышки и клавиатуры. Такие устройства обычно поддерживают операции (read, write, open, close). И поддерживают посимвольный, то-есть последовательный доступ к данным.
Файлы устройств это не сами устройства, например файл диска будет иметь нулевой размер, хотя сам диск может хранить много данных. Файлы устройств — это интерфейсы, позволяющие системе и программам получить доступ к устройствам. Получается что файловая система devfs расположенная в каталоге /dev это как-бы API для доступа к оборудованию.
Давайте посмотрим на символьное устройство с помощью утилиты stat:
alex@ubu:~$ stat /dev/bus/usb/001/001 File: /dev/bus/usb/001/001 Size: 0 Blocks: 0 IO Block: 4096 character special file Device: 5h/5d Inode: 144 Links: 1 Device type: bd,0 Access: (0664/crw-rw-r--) Uid: ( 0/ root) Gid: ( 0/ root) Access: 2022-05-16 08:36:04.872000000 +0000 Modify: 2022-05-16 08:36:04.872000000 +0000 Change: 2022-05-16 08:36:04.872000000 +0000 Birth: -
Тип этого файла character special file — символьный специальный файл.
И посмотрим на файл блочного устройства:
alex@ubu:~$ stat /dev/sda2 File: /dev/sda2 Size: 0 Blocks: 0 IO Block: 4096 block special file Device: 5h/5d Inode: 269 Links: 1 Device type: 8,2 Access: (0660/brw-rw----) Uid: ( 0/ root) Gid: ( 6/ disk) Access: 2022-05-16 08:36:10.956000000 +0000 Modify: 2022-05-16 08:36:05.296000000 +0000 Change: 2022-05-16 08:36:05.296000000 +0000 Birth: -
Тип такого файла block special file — блочный специальный файл.
Кстати, команда ls -l выводит не размер файла устройства, так как размер таких файлов всегда нулевой, а мажорный и минорный номера:
alex@ubu:~$ ls -l /dev/sda2 brw-rw---- 1 root disk 8, 2 мая 16 08:36 /dev/sda2
В примере выше:
- мажорный номер — 8 — это номер драйвера, который обслуживает это устройство;
- минорный номер — 2 — это внутренний номер устройства в данной системе.
Файлы сокетов
Для взаимодействия программ друг с другом часто используются сокеты. На сокеты в выводе ls -l указывает символ «s«.
Следующий пример будет работать в Ubuntu 22.04, но чтобы выполнить его на Debian 11 вначале нужно установить программу netcat таким образом:
alex@deb:~$ su - Пароль: root@deb:~# apt install netcat root@deb:~# exit выход alex@deb:~$
Дело в том, что в Debian 11 по умолчанию немного другая версия netcat и в ней нет опции -U.
Создать сокет можно с помощью команды nc -lU socket.sock:
alex@ubuntu:~$ nc -lU socket.sock
После выполнения этой команды вы подключитесь к сокету и сможете в него что-нибудь записывать, например:
alex@ubuntu:~$ nc -lU socket.sock 123 333 123 Aaa...
Теперь подключитесь к серверу с помощью другого ssh соединения. И из нового окна терминала подключитесь к этому-же сокету:
alex@ubuntu:~$ nc -U socket.sock 123 333 123 Aaa...
Вы увидите всё то, что вводили в первом терминале.
После этого на первом терминале нажмите комбинацию клавиш «Ctrl + c«, чтобы закрыть сокет. Пока не будем закрывать второй терминал, он нам ещё понадобится.
Посмотрим на файл сокета с помощью утилиты stat:
alex@ubu:~$ stat socket.sock File: socket.sock Size: 0 Blocks: 0 IO Block: 4096 socket Device: 802h/2050d Inode: 398517 Links: 1 Access: (0775/srwxrwxr-x) Uid: ( 1000/ alex) Gid: ( 1000/ alex) Access: 2022-05-16 08:50:00.897716333 +0000 Modify: 2022-05-16 08:49:21.881547299 +0000 Change: 2022-05-16 08:49:21.881547299 +0000 Birth: 2022-05-16 08:49:21.881547299 +0000
Тип файла — socket, и размер у него нулевой.
Символьные ссылки
Про ссылки будет отдельная статья, но здесь разберём этот тип файлов тоже. Символьная ссылка это файл, который указывает на другой файл.
После эксперимента с сокетом, у нас в каталоге остался файл сокета. Давайте сделаем символьную ссылку на этот файл с помощью команды ln -s <путь к файлу> <имя ссылки>:
alex@ubu:~$ ln -s socket.sock ./socket.sock.link alex@ubu:~$ ls -l total 20 drwxrwxr-x 2 alex alex 20480 мая 16 08:44 dir1 srwxrwxr-x 1 alex alex 0 мая 16 08:49 socket.sock lrwxrwxrwx 1 alex alex 11 мая 16 08:51 socket.sock.link -> socket.sock
Как видите, на файл ссылки указывает символ «l«. Теперь можно ссылку использовать как файл, например можно подключиться к сокету используя ссылку. Вот для этого примера нам понадобится второе окно терминала, которое мы запускали раньше:
Посмотрим на символическую ссылку с помощью утилиты stat:
alex@ubu:~$ stat socket.sock.link File: socket.sock.link -> socket.sock Size: 11 Blocks: 0 IO Block: 4096 symbolic link Device: 802h/2050d Inode: 398518 Links: 1 Access: (0777/lrwxrwxrwx) Uid: ( 1000/ alex) Gid: ( 1000/ alex) Access: 2022-05-16 08:51:40.434119694 +0000 Modify: 2022-05-16 08:51:34.426096138 +0000 Change: 2022-05-16 08:51:34.426096138 +0000 Birth: 2022-05-16 08:51:34.426096138 +0000
Тип файла — symbolic link (символьная ссылка). Размер этой ссылки 11 байт. По сути, символьные ссылки это тоже самое что и ярлыки в Windows. Можно создать ссылку на любой файл или каталог.
Итог
Вот мы и разобрали все типы файлов, которые встречаются в Linux:
- обычные файлы (—);
- каталоги (d);
- символьные устройства (c);
- блочные устройства (b);
- сокеты (s);
- символьные ссылки (l).
ольшое спасибо за прекрасно поданый материал. Коротко и по делу с хорошими примероми. Только у меня при написании команды ls -l в каталоге /dev/ мажорные и минорные номера очень разнообразные (стоит линукс Mint 19.2). Хочу спросить а есть ли команда или файл с информацией в самой системе где описаны все эти номера? Например на какой номер какой драйвер отвечает.
Можете посмотреть на файл /proc/devices, там перечислены используемые текущим ядром драйвера (мажорные номера)
Это один из лучших курсов который я нашел! Автору огромное спасибо!
Всё-таки неверно символьные ссылки представлять как ярлыки в Виндовс. Ярлык в Виндовс — это скорее как лаунчер или десктоп-файл в линуксе (только бинарный). В Виндовс уже давно тоже есть символьные ссылки (на уровне файловой системы). Часто в Проводнике они видны пользователю, как ярлыки (только без возможности редактирования), но на ярлыки они совсем не похожи по сути…
Здесь это сделано для упрощения, я думаю не многие знают про ссылки в Windows, а вот про ярлыки должны знать все. Ярлык в Windows ссылается на какой-то файл и символьная ссылка в Linux ссылается на какой-то файл. Ну а технически они конечно совершенно разные.