Рубрика:
Карьера/Образование /
Лабораторная работа
|
Facebook
Мой мир
Вконтакте
Одноклассники
Google+
|
ПАВЕЛ ЗАКЛЯКОВ, ИТ-специалист
Лабораторная работа: исследуем inode Часть 2. Взаимодействие с inode через стандартные программы на пользовательском уровне (подготовка и проведение)
Можно ли «увидеть» inode? Да, в работе рассказывается, «как» и на что он «влияет»
Продолжение. Начало в [СА №7-8, 2017, URL: http://samag.ru/archive/article/3485], где были рассмотрены теоретические вопросы строения файловых систем (ФС) ext2-ext4.
Подготовка лабораторного стенда
Для проведения работы используется ОС CentOS Linux 6.9 (64-битная сборка). С минимальными коррективами данная работа может быть проведена как на дистрибутиве 32-битной сборки, так и на другой системе, при условии, что в ней будут установлены нижеупомянутые основные и дополнительные программы.
Все задания выполняются из-под консоли от обычного пользователя. Графический интерфейс не требуется, но его наличие не возбраняется. Наличие прав администратора для выполнения заданий не требуется, за исключением этапа подготовки лабораторного стенда (установка дополнительных пакетов, внесение изменений в файл /etc/sudoers).
Этапы настройки лабораторного стенда следующие:
1. Произвести базовую (минимальную) установку вышеупомянутой системы (требуется первый установочный диск, CentOS-6.9-x86_64-bin-DVD1.iso).
2. Создать учётную запись пользователя user, от которого будет выполняться работа.
# adduser user
# passwd user
3. Произвести дополнительную установку пакетов с установочного диска (DVD1) или с серверов обновления: man, tree, man-pages-ru (не обязательно), gpm-libs (необходим для lde).
# yum -y install tree man man-pages-ru gpm-libs
Вместе с man будут установлены зависимые пакеты: xz, xz-lzma-compat.
4. Произвести дополнительную установку пакетов из репозитория EPEL: lde.
# yum -y install lde
или
# rpm -ihv lde-2.6.1-4.el6.x86_64.rpm
5. Внести изменения в файл /etc/sudoers (дописать нижеследующие строчки), чтобы указанные в них команды можно было запускать через механизм sudo от обычного пользователя.
guest ALL=(ALL) NOPASSWD: /bin/mount -o loop disk100ext2 /mnt/ext2
guest ALL=(ALL) NOPASSWD: /bin/mount -o loop disk100ext4 /mnt/ext4
guest ALL=(ALL) NOPASSWD: /bin/umount /mnt/ext2
guest ALL=(ALL) NOPASSWD: /bin/umount /mnt/ext4
guest ALL=(ALL) NOPASSWD: /bin/mount -o loop,user_xattr,acl disk100ext2 /mnt/ext2
guest ALL=(ALL) NOPASSWD: /bin/mount -o loop,user_xattr,acl disk100ext4 /mnt/ext4
guest ALL=(ALL) NOPASSWD: /usr/sbin/setcap cap_sys_admin+ep /mnt/ext2/file1
guest ALL=(ALL) NOPASSWD: /usr/sbin/setcap cap_sys_admin+ep /mnt/ext4/file1
6. Создать директории для последующего монтирования в них исследуемых ФС.
# mkdir /mnt/ext2
# mkdir /mnt/ext4
Задания для самостоятельного выполнения
Часть 1. Взаимодействие с inode через стандартные программы на пользовательском уровне
Пункт 1. Первое место, откуда обычный пользователь может узнать о существовании inode, даже не имея ни капли теоретических знаний, – это из вывода ряда консольных программ при их запуске с соответствующими ключами. При запуске команд df -i, ls -i, tree -a -L 1 --inodes / стандартный вывод утилит дополняется информацией по inode. Первая программа показывает свободное место (от англ. disk free) на примонтированных разделах жёсткого диска, вторая – список (от англ. list) файлов в рабочей директории, третья – содержимое корневой директории. Запустите первые две команды с ключом -i и без него, а третью – с и без --inodes, проанализируйте их вывод. В помощь вам существуют команды man ls, man df, man tree.
Пункт 2. Права объекта файловой системы хранятся в его inode. Увидеть их можно командами ls -li имя_объекта или stat имя_объекта. Используя их:
Узнаем, как взаимодействовать с объектами файловой системы, имеющими странные имена |
Пункт 2.1. Просмотрите информацию для корня (/) файловой системы и директорий: /etc, /home, /tmp, причём сделайте это как из корня, так и из самих директорий. Запомните номера inode в привязке к именам директорий. (Смена директории производится командой cd с указанием её названия. Запуск cd без параметров помещает вас в домашнюю директорию. Посмотреть текущую (рабочую) директорию можно командой pwd.) Почему номер inode корневой директории ФС («/» и «.» в ней) имеет номер 2, а не 1? Сразу отметим, что это не журнал, поскольку в ФС ext2 он не предусмотрен, а номер будет также 2, а не 1. Для журнала ФС забронирован номер 8. Внимательно просматривая результат выполнения команды ls -li /, можно заметить, что традиционно первым свободным для использования номером inode для файлов и директорий является номер 11, он же прописан впараметре s_first_ino in суперблока, но чаще всего по техническим моментам он оказывается занят директорией lost+found, поскольку именно она создаётся ОС сразу после создания ФС. При необходимости использования именно этого номера директорию можно переименовать или удалить. А то, как «захватить» нужный inode номер, было рассмотрено в ответе на вопрос № 14 перед началом работы.
Пункт 2.2. Обратите внимание на то, что есть такие имена директорий, как «.» и «..», а команда ls по умолчанию не отображает имена, начинающиеся с «.». Для того чтобы ихувидеть, используйте дополнительно ключ -a.
Пункт 2.3. Ответьте на вопросы: совпадает ли номер inode у корневой директории (/) и у директории «..» внутри директории /etc? Совпадает ли номер inode у директории /etc припро-смотре списка директорий внутри корня («сверху») и изнутри её самой («снизу»), где она представлена именем «.»?
Пункт 3. Взаимодействие с объектами ФС по их номерам inode довольно типично при решении ряда задач администрирования. Смоделируем эти ситуации.
Пункт 3.1. Решим задачу поиска объекта(ов) ФС по номеру его inode. Для этого исходя из предположения, что пользователь находится в своей домашней директории (~), создадим иерархию директорий, файл и несколько жёстких ссылок на него. Это будет файл, который в дальнейшем будет искаться.
- ~/dir1/
- ~/dir1/file1
- ~/dir1/hard_link_to_file1
- ~/dir1/dir2/
- ~/dir1/dir2/hard_link_to_file1
Используя команды ls -li и stat имя_объекта_ФС, посмотрите информацию об объектах ФС, каждый раз до создания жёстких ссылок и после. В выводе обеих команд обратите внимание на параметр «число ссылок».
$ mkdir dir1
$ cd dir1
$ touch file1
$ mkdir dir2
посмотрите, что получилось.
$ ln file1 hard_link_to_file1
посмотрите, что получилось.
$ ln file1 dir2/hard_link_to_file1
посмотрите, что получилось.
Имена file1 и hard_link_to_file1 равносильны, то есть «идентичны» с точки зрения доступа к содержимому и параметрам файла. Заметили ли вы, что они ссылаются на один и тот же inode?
Допустим, он был 123456, осуществим поиск по нему. Для ускорения поиска выполним его внутри директории ~/dir1.
$ find ~/dir1 -inum 123456 -print
$ find ~/dir1 -inum 123456 -exec ls -l {} +
Команда find позволяет выполнять разные действия в отношении найденных объектов. С параметром -print осуществляется только вывод, с параметром -exec возможен запуск любой команды, которой вместо фигурных скобок {} передаётся найденное имя, знак «+» является неотъемлемой частью синтаксиса команды find.
Пункт 3.2. Решим задачу удаления/переименования объектов ФС со странными именами.
Как легко догадаться, выделенную выше команду ls с ключами легко заменить на любую, в том числе и на rm (или rmdir), в случае если требуется удаление объектов ФС.
Также вместо параметра -print у команды find возможно задать параметр -delete для удаления всех найденных объектов. Естественно, результат её выполнения будет зависеть отполномочий пользователя и установленных прав у найденных объектов.
Скорее вопрос заключается в том, откуда файлы (или директории) со странными именами могут появиться в ФС? При нормальных условиях работы ОС их быть не должно, но вряде случаев причиной этого могут быть как заражённые различными вирусами внешние флеш-накопители, так и «слишком умные» пользователи системы, которые знают, что вбольшинстве ФС, используемых в ОС UNIX и Linux, в качестве имён объектов ФС разрешено использовать любые символы, кроме символа с кодом «0» (NULL) и разделителя «/».
То, что в именах могут встречаться символы, имеющие одинаковое или сильно схожее начертание в латинице и кириллице, такие как «a», «о», «е», различные знаки: минус, дефис, тире и т.д., давно известно, но куда более интересно то, что в именах могут быть и более трудно отличимые при просмотре символы, например «пробел» (код 32 = 0x20) в конце имени, символы с кодами ASCII 1-31, скажем, тот же backspace (код 8 = 0x08, \b) и др., которые использовать при желании, набрав на клавиатуре, без ухищрений не получится. Также поле для деятельности сильно расширилось с введением поддержки Unicode в форматах UTF-8 и UTF-16.
Наиболее известен коррекционный символ Right-To-Left Override, RLO, UTF-16BE 0x202E, UTF-8 E2 80 AE, позволяющий в ряде программ с графическим интерфейсом (например, почтовых) видеть имя picRLOgpj.exe, где RLO – тот самый символ, как picexe.jpg [1, 2].
Также удивление (особенно после утомительного дня или бессонной ночи, когда сознание притуплено) может вызвать символ «/» (косая черта направо, UTF-8 E2 81 84) в имени, который сильно похож, а в ряде систем не отличим по начертанию от традиционного символа «/» (слеш).
Рассмотрим варианты появления объектов ФС с нестандартными символами в имени и подходы для их удаления/переименования.
Пункт 3.2.1. Выполните команды для создания файлов и директории.
$ mkdir aa$'\xe2\x81\x84'bb
$ touch pic$'\xe2\x80\xae'gpj.exe
$ touch "aa?b"
$ touch `printf "aa\bb"`
$ touch $(printf "aa\bb")
Обратите внимание на три вида разных кавычек в командах: одинарные «'», двойные «"» и обратные «`». Последняя команда идентична предпоследней. Она на один символ длиннее, но новичками воспринимается легче из-за другого синтаксиса (без обратных кавычек).
Пункт 3.2.2. Запустите команду ls -l для просмотра содержимого текущей (рабочей) директории.
$ ls -l
-rw-rw-r--. 1 guest guest 0 Май 1 10:17 aa?b
-rw-rw-r--. 1 guest guest 0 Май 1 10:17 aa?b
drwxrwxr-x. 2 guest guest 4096 Май 1 10:17 aa/bb
-rw-rw-r--. 1 guest guest 0 Май 1 10:17 picgpj.exe
Как видите, отличить имена aa?b от aa?b не так просто, особенно если права доступа, владельцы, группы и времена создания совпадают. Попробуем удалить этот файл (эти файлы), для этого запустите команды:
$ rm aa?b
$ ls -l
По незнанию можно подумать, что команда ls их тоже не различила, поскольку результат её работы выглядит именно так, однако это утверждение не верно, поскольку знающие пользователи отметят, что в bash символ «?», без экранирования его знаком «\» (\?) или кавычками, является символом-джокером. Использование знака «?» в общем случае в команде i без знания такой особенности, как и в других командах, может иметь свои последствия. Убедиться, что имена разные, можно, создав файлы заново (повторив команды 3 и 4пункта 3.2.1) и просмотрев на номера их inode. Они будут различны.
Сравните выводы команд ls -l, ls -1 и ls -1|grep aa.
Визуально вывод двух последних команд отличается, поскольку у команды i есть опция -q, позволяющая вместо непечатаемых символов в имени файла при выводе размещать знаки вопроса. Эта опция включена по умолчанию при выводе на терминал. При перенаправлении стандартного вывода команды ls на стандартный ввод команды grep ключ -q недобавляется, поскольку вывод команды ls не связан с терминалом. Если ключ добавить, то разница в отображении между двумя командами исчезнет.
$ ls -1 -q|grep aa
Однако лучше всего увидеть разницу в выводе можно, просматривая его как поток двоичных данных с помощью команды od.
$ ls -1|od -A n -t ax1
a a ? b nl a a bs b nl
61 61 3f 62 0a 61 61 08 62 0a
$ ls -1|grep aa|od -A n -t ax1
a a ? b nl a a bs b nl
61 61 3f 62 0a 61 61 08 62 0a
Пункт 3.2.3. Для обращения к объектам ФС со странными именами можно использовать символ табуляции для дописывания конца имён. Рассмотрим, как это работает. Создайте файл picRLOgpj.exe из пункта 3.2.1, убедитесь, что он создался, просмотром содержимого директории, удалите файл, набрав его имя побуквенно с клавиатуры.
$ touch pic$'\xe2\x80\xae'gpj.exe
$ ls -1
picexe.jpg
$ rm picgpj.exe
rm: невозможно удалить «picgpj.exe»: Нет такого файла или каталога
Вы получите ошибку, поскольку не смогли набрать коррекционный символ в имени. С точки зрения ОС и ФС получаются разные имена. Однако если наберёте имя не до конца:
$ rm pic
и после этого нажмёте клавишу <Tab>, то на экране вы увидите также:
$ rm picgpj.exe
но команда отработает без ошибки.
Пункт 3.2.4. Ещё одним способом набора «сложного» имени может быть выделение и копирование мышью. То есть опять создаём файл, в предположении, что он появился не понашей воле, просматриваем результат и набираем на клавиатуре команду rm.
$ touch pic$'\xe2\x80\xae'gpj.exe
$ ls -1
picexe.jpg
$ rm |
После этого с помощью курсора мыши выделяем имя файла в выводе команды ls и жмём на колесо вертикальной прокрутки у мыши (scroll). В месте расположения клавиатурного курсора появится выделенный мышью текст. Если после нажать «ввод», то команда удаления выполнится без ошибки. Естественно, в графической среде с мышью можно использовать и стандартные команды «копировать» и «вставить» контекстного меню, вызываемого правой кнопкой.
Пункт 3.2.5. Наиболее простой способ оперирования со странными именами в bash, если известны коды их символов, – это посимвольная подстановка в создаваемое имя объекта ФС (параметр команды) необходимого числа конструкций вида $'\xXX' или $'\xXX\xXX', или $'\xXX\xXX\xXX' и т.д., где XX – это шестнадцатеричные значения первого, второго и т.д. кодов символа в случае использования одно-, двух-, трёх- и многобайтового представления символов. Вместо шестнадцатеричных значений можно использовать восьмеричные безпредшествующего «x». Естественно, XX могут подставляться через переменные, а вся команда находится в теле цикла.
Для выяснения, какой код у встретившегося символа, используется команда od, как было написано выше.
Непривычным может показаться лишь то, что некоторые форматы кодировок используют разные длины для кодирования отдельных групп символов (планов), так называемые кодировки переменной длины. Например, при использовании популярного формата для Unicode – UTF-8 ответ на вопрос: «А сколько байт будет занимать строка из пяти символов?»– отнюдь не тривиален при вхождении в строку символов из разных планов.
Узнать, какая кодовая таблица используется у вас в консоли, можно с помощью команды locale.
Пункт 4. Нюансы сохранения данных и использования блоков можно увидеть с помощью команды stat либо сравнивая информацию от вывода команды df (статистику использования блоков) до создания файла и после, также можно использовать ключ -s (или --size) у команды ls.
Замечание. При использовании ключа -s размер выдаётся в блоках по 1024 байта слева от имени файла. Если установлена переменная окружения POSIXLY_CORRECT и не задана опция -k, то применяется размер блока 512. Если используется опция -k, то размеры выдаются в килобайтах. 1 килобайт = 1024 байтам.
Проверим на практике один теоретический момент. В [3], в разделе «Advanced» Ext2fs features, сказано, что для ускорения работы с символьными (мягкими) ссылками, в случае если размер последних составляет менее 60 байт, то они хранятся в inode, при этом используется 0 блоков с данными.
Замечание. Аналогичную схему можно было бы применить и к маленьким файлам. В 1999 году на сайте redhat.com из раздела Linux Kernel Hackers' Guide была опубликована ссылка на статью по разработке и использованию ФС ext2 [3], где Реми Кард с сотоварищами сообщил, что реализовать аналогичную возможность в отношении маленьких файлов планируется в ближайшем будущем.
Поддержка «встраиваемого хранения» (функция inline data) была добавлена в марте 2014-го, но на момент подготовки данной публикации (2017 год) в большинстве ОС Linux нереализована. Для её использования в ФС ext4 необходима WIP-версия утилит e2fsprogs (клон репозитория git). ФС должна быть создана командой mke2fs с опцией -O inline_data [4].
Последняя версия загрузчика GRUB (2.02 на момент подготовки публикации) не поддерживает данный функционал, однако существует патч [5].
Разберёмся, откуда взялась цифра 60. Поскольку при «встраиваемом хранении» ни один блок с данными не используется, то невостребованными окажутся те байты структуры inode, которые ответственны за прямые и косвенные адреса блоков с данными. Из теории следует, что под адреса выделено: (12 прямых + 3 косвенных ссылки) * 4 байта = 60 байт. То естьграница по использованию и неиспользованию блоков с данными должна проходить на переходе «60-61». С другой стороны, разработчиками для ссылок заявлено «меньше 60» («<60»), то есть граница должна быть на переходе «59-60». Попробуем понять, откуда расхождение в 1 байт?
Пункт 4.1. Создайте файлы с размерами от 0 до 61 байта. Посмотрите вывод команд stat и ls -s и оцените, сколько каждый из них занимает блоков с данными.
Создавать файлы можно разными способами, вот лишь некоторые полезные команды, которые могут вам пригодиться:
- создать файл с именем file0 нулевого размера (если такой файл не существует):
touch file0
- дописать в файл с именем fileX 1 байт:
echo -n "1">>fileX
- дописать в файл с именем fileY 2 байта:
echo -n "2">>fileY
- дописать в файл с именем fileZ 10 байт:
echo -n "1234567890">>fileZ
Также можно использовать либо цикл, дописывая в файл по одному однобайтовому символу нужное число раз, либо команду dd.
$ i=1; while [ $i -le 60 ] ;do echo -n "1" >>file60; let i=i+1; done
$ dd if=/dev/zero of=file60 bs=1 count=60
Замечание. Обратите внимание, что если у вас не установлена ни одна из переменных: COMMAND_BLOCK_SIZE, BLOCK_SIZE или BLOCKSIZE, то команда stat по умолчанию будет считать блок равным 512 байт. То есть при размере истинного логического блока в вашей ФС 1024 байта (в два раза больше) команда stat будет выдавать в два раза большее значение числа блоков. При размере 2048 байт – в четыре раза, 4096 – в восемь раз и т.д. (подробнее – см. info coreutils 'stat invocation').
Обратили ли вы внимание, что файл размером 0 байт не занимает ни одного блока, что выглядит вполне логичным?
Пункт 4.2. Расширьте поле эксперимента, добавив к исследованию файлы с размерами: 511, 512, 513, 1023, 1024, 1025, 2047, 2048, 2049, 4095, 4096, 4097, 8191, 8192 и 8193 байта.
Пункт 4.3. Напишите, где (на границе каких значений объёма файла), по вашим наблюдениям, происходит скачкообразное изменение количества блоков, используемых файлом дляхранения данных по информации, выводимой утилитой stat?
Пункт 4.4. Ответьте на вопросы.
На сколько блоков сразу происходило скачкообразное изменение в предыдущем пункте? Можно ли по этой информации косвенно определить размер логического блока виспользуемой ФС? Если да, то как? Какой размер логического блока в ФС, на которой вы создавали файлы в пункте 4.1 и пункте 4.2? Есть ли связь размера блока с «переходами», полученными в пункте 4.3?
Пункт 4.5. Создайте файлы с именами длиной в 1, 2, 59, 60 и 61 байт.
$ touch 1
$ touch 12
$ touch 1234567890…1234567890123456-59
$ touch 1234567890…12345678901234567-60
$ touch 1234567890…123456789012345678-61
Пункт 4.6. Создайте файлы с именами длиной в 1, 2, 29, 30, 31 символ, используя буквы русского алфавита.
$ touch ы
$ touch ыы
$ touch абвгдеёжзийклмнопрстуфхцчшщьы
$ touch абвгдеёжзийклмнопрстуфхцчшщьыъ
$ touch абвгдеёжзийклмнопрстуфхцчшщьыъэ
Пункт 4.7. Создайте мягкие ссылки на только что созданные файлы в пункте 4.5. и пункте 4.6.
$ ln -s 1 link-1
$ ln -s 12 link-12
$ ln -s 123…123456-59 link-123...6-59
$ ln -s 123…1234567-60 link-123...67-60
$ ln -s 123…12345678-61 link-123...678-61
$ ln -s ы link-ы
$ ln -s ыы link-ыы
$ ln -s абв…щьы link-абв…щьы
$ ln -s абв…щьыъ link-абв…щьыъ
$ ln -s абв…щьыъэ link-абв…щьыъэ
Посмотрите вывод команд stat и ls s и оцените, сколько каждая из созданных ссылок занимает блоков с данными. Уловили ли вы разницу между пунктом 4.5 и пунктом 4.6 (между размерами в символах и в байтах)? Разница заметна, поскольку имена закодированы с помощью кодировки в формате UTF-8, у которой латиница с цифрами и кириллица принадлежат к разным планам, использующим 1 и 2 байта для кодирования символов соответственно.
Вместо заключения
В результате выполнения первой части заданий вы произвели первое поверхностное знакомство с inode на практике. Также вы узнали о том, как взаимодействовать с объектами ФС, имеющими странные имена. Далее следуют:
- Часть 2. Взаимодействие через утилиты ФС.
- Часть 3. «Сырое» чтение данных из ФС.
- Можно ли верить коду в редакторе? bi-directional текст – https://habrahabr.ru/post/252813.
- Можно ли верить своим глазам? (Unicode в именах файлов) – https://habrahabr.ru/post/126198.
- Design and Implementation of the Second Extended Filesystem – http://e2fsprogs.sourceforge.net/ext2intro.html.
- How to use the new Ext4 Inline Data feature? (storing data directly in the inode) – https://unix.stackexchange.com/questions/197633/how-to-use-the-new-ext4-inline-data-feature-storing-data-directly-in-the-inod/197806.
- grub ext4 inline data support patch – http://git.savannah.gnu.org/cgit/grub.git/commit/?h=andrey/ext4_inline_data&id=d4af83fc600d02dcfedae457353efbce8726b8d9.
Facebook
Мой мир
Вконтакте
Одноклассники
Google+
|