- Роль Inode в файловых системах Linux
- Что такое inode?
- Сколько существует инодов?
- Команды для работы с inode
- Номер inode файла
- Номер inode каталога
- Подведем итог
- Tyler Carrigan
- Node.js для начинающих: основы работы с файлами
- Модуль fs
- Создание нового файла
- Запись данных в файл
- Чтение файла
- Переименование файла
- Удаление файла
- Руководство по Node.js, часть 9: работа с файловой системой
- Работа с файловыми дескрипторами в Node.js
- Данные о файлах
- Пути к файлам в Node.js и модуль path
- ▍Получение информации о пути к файлу
- ▍Работа с путями к файлам
- Чтение файлов в Node.js
- Запись файлов в Node.js
- Присоединение данных к файлу
- Об использовании потоков
- Работа с директориями в Node.js
- ▍Проверка существования папки
- ▍Создание новой папки
- ▍Чтение содержимого папки
- ▍Переименование папки
- ▍Удаление папки
- Модуль fs
- Модуль path
- ▍path.basename()
- ▍path.dirname()
- ▍path.extname()
- ▍path.isAbsolute()
- ▍path.join()
- ▍path.normalize()
- ▍path.parse()
- ▍path.relative()
- ▍path.resolve()
Роль Inode в файловых системах Linux
Оригинал: Inodes and the Linux filesystem
Автор: Tyler Carrigan (Red Hat)
Дата публикации: 9 июня 2020 г.
Перевод: В.Костромин
Дата перевода: 15 июня 2020 г.
Понять строение файловых систем Linux довольно сложно, особенно когда вы погружаетесь в хитросплетение данных и метаданных. Каждый раз, когда вы запускаете команду ls и видите вывод — перечисление файлов, разрешения, владельцев и т.д. — вы должны понимать, что данные о просматриваемых файлах хранятся где-то отдельно от самих файлов и должны вызываться при обращении к файлу. Иноды усердно работают «за кадром», выполняя работу, которую вы не видите. Давайте же посмотрим, что же такое inode и для чего он нужен.
Что такое inode?
Inode – это сокращение от «index node», по-русски – индексный узел. По сути он представляет собой уникальную порцию метаданных в заданной файловой системе. Эта порция метаданных описывает то, что мы называем файлом. Иноды относятся только к определенной файловой системе, не касаясь других. Как ни странно это может показаться, но все иноды хранятся в общей таблице и это иногда вызывает недоумение. Однако каждая файловая система, смонтированная на вашем компьютере, имеет свои собственные inode. Номер inode может использоваться более одного раза, но никогда не может дважды использоваться одной и той же файловой системой. Идентификатор файловой системы в сочетании с номером инода создает уникальную идентификационную метку.
Сколько существует инодов?
Если вы не хотите связываться с математикой, вы можете пропустить этот раздел. В каждой системе имеется множество inode и есть несколько относящихся к ним числовых значений, которые нужно знать. Прежде всего, хотя это и менее важно, теоретическое максимальное число inode равно 2 ^ 32 (приблизительно 4,3 миллиарда inode). Во-вторых, что гораздо важнее, это число inode в вашей системе. Как правило, количество inode составляет 1:16 от объема файловой системы в КБ. Очевидно, что каждая система отличается, поэтому вам нужно рассчитать это значение самостоятельно.
Команды для работы с inode
Есть хорошая новость для тех, кто не любит математику: для этого есть специальная команда. Чтобы узнать количество inode в вашей системе, вы можете использовать команду df с опцией -i , как показано здесь:
Вы можете видеть, что в этом примере мы запустили команду df -i на файловой системе /dev/sda1 . В этой системе всего имеется 524 288 инодов, но только 312 из них используется (примерно 1%).
Номер inode файла
Мы также можем узнать номер inode конкретного файла. Для этого можно использовать команду ls -i с указанием нужного файла. Например:
Номер inode этого файла — 1459027.
Номер inode каталога
Подобно тому, как мы узнали номер inode файла, мы можем посмотреть и номер inode каталога. Для этого снова используем команду ls -i с некоторыми дополнительными опциями. Например:
Как вы можете видеть, мы использовали опцию -i (inodes), а также -l (long format) и -d (directory). Применение этих флажков позволяет нам получить множество информации о каталоге my_articles, включая номер inode, разрешения, владельцы и т.д.
Подведем итог
Если вы хотите узнать больше о файловых системах и их структурах, то inode — это отличная тема для начала. Очень важно знать как помечаются и индексируются самые маленькие единицы данных. Некоторые из более продвинутых операций могут быть выполнены с помощью inode. Например, вы можете открыть индекс и прочитать содержимое файла. Это позволит вам более глубоко понять, какие данные хранятся в inode.
Надеммся, что этот поверхностный обзор послужит для вас отправной точкой для более глубокого изучения inode.
Tyler Carrigan
Tyler работает менеджером в Enable Sysadmin, является ветераном подводного флота и энтузиастом новых технологий! Он впервые познакомился с Red Hat в 2012 году при использовании основанной на Red Hat Enterprise Linux боевой системы в Центре управления ракетами на подводной лодке USS Georgia.
Источник
Node.js для начинающих: основы работы с файлами
Сегодня мы поговорим о том, как работать с файловой системой средствами Node.js, рассмотрим базовые операции, выполняемые с файлами. К таким операциям относятся следующие:
- Создание файла
- Чтение файла
- Запись данных в файл
- Удаление файла
- Переименование файла
Необходимость в выполнении подобных операций возникает в самых разных ситуациях.
Модуль fs
В Node.js имеется стандартный модуль, fs (сокращение от File System), дающий разработчику средства для работы с файловой системой. Импортировать его в проект можно так:
Методы этого модуля представлены в синхронной и асинхронной формах. Функции обратного вызова, передаваемые асинхронным методам, принимают в качестве первого параметра объект ошибки, а в качестве второго — данные, возвращённые при успешном выполнении операции. Рассмотрим пример:
Метод .readFile() , о котором мы ещё поговорим, предназначен для чтения файлов. В этом примере у функции обратного вызова есть два параметра — err и data . В первый параметр попадают ошибки, которые могут возникнуть при попытке чтения файла, во втором оказываются данные, полученные после успешного выполнения операции. Обратите внимание на то, что .readFile() — это асинхронный метод модуля fs . Его синхронная версия называется .readFileSync() . Похожий подход используется и для именования других методов модуля.
Создание нового файла
Начнём с примера:
Здесь метод fs.open() используется для создания нового файла. В качестве первого аргумента он принимает имя файла. Его второй аргумент представляет собой флаг, указывающий системе на то, что именно мы хотим сделать с файлом. В данном случае это флаг w (сокращение от writing), который указывает на то, что мы хотим открыть файл для записи. Метод .open() может принимать различные флаги. Вот некоторые из них:
- r : открыть файл для чтения
- r+ : открыть файл для чтения и записи
- rs : открыть файл для чтения в синхронном режиме
- w : открыть файл для записи
- a : открыть файл для записи данных в конец файла
- a+ : открыть файл для чтения и для записи данных в конец файла
Теперь, прежде чем переходить к следующему примеру, отредактируем только что созданный файл testFile.txt с помощью какого-нибудь текстового редактора. Внесём в него следующий текст:
Запись данных в файл
Поговорим о том, как дописать что-нибудь в файл:
Здесь мы используем метод .appendFile() для добавления данных в конец существующего файла. В качестве первого аргумента этот метод принимает имя файла, в качестве второго — данные, которые нужно добавить в конец файла. Третий аргумент — это, как обычно, функция обратного вызова.
После того, как код, показанный выше, успешно отработает, содержимое файла будет выглядеть так:
Существует и другой способ записи данных в файл. Он подразумевает использование метода .writeFile() . Этот метод очень похож на .appendFile() , но у него есть одно важное отличие. Дело в том, что с помощью метода .appendFile() мы добавляем в файл новые данные после тех данных, которые в нём уже есть. А при использовании метода .writeFile() содержимое файла заменяется на новое. Испытаем этот метод:
После успешного выполнения операции в файле окажется следующий текст:
Как видно, содержимое файла полностью заменено новым.
Чтение файла
Для чтения файлов модуль fs предоставляет метод .readFile() , пример использования которого мы уже видели. В качестве первого параметра он принимает имя файла, в качестве второго — кодировку. Третий параметр — функция обратного вызова. Попытаемся вывести в консоль содержимое файла testFile.txt с помощью этого метода:
Вот что у нас получится.
Данные файла, выведенные в консоль
Теперь поговорим о переименовании файлов.
Переименование файла
Для переименования файлов используется метод .rename() :
Первый аргумент метода представляет собой имя существующего файла, второй — новое имя этого файла. После успешного вызова этого метода файл testFile.txt превращается в newTestFile.txt .
Удаление файла
Для удаления файлов используется метод .unlink() :
Источник
Руководство по Node.js, часть 9: работа с файловой системой
Сегодня, в девятой части перевода руководства по Node.js, мы поговорим о работе с файлами. В частности, речь пойдёт о модулях fs и path — о файловых дескрипторах, о путях к файлам, о получении информации о файлах, об их чтении и записи, о работе с директориями.
Работа с файловыми дескрипторами в Node.js
Прежде чем вы сможете взаимодействовать с файлами, находящимися в файловой системе вашего сервера, вам необходимо получить дескриптор файла.
Дескриптор можно получить, воспользовавшись для открытия файла асинхронным методом open() из модуля fs :
Обратите внимание на второй параметр, r , использованный при вызове метода fs.open() . Это — флаг, который сообщает системе о том, что файл открывают для чтения. Вот ещё некоторые флаги, которые часто используются при работе с этим и некоторыми другими методами:
- r+ — открыть файл для чтения и для записи.
- w+ — открыть файл для чтения и для записи, установив указатель потока в начало файла. Если файл не существует — он создаётся.
- a — открыть файл для записи, установив указатель потока в конец файла. Если файл не существует — он создаётся.
- a+ — открыть файл для чтения и записи, установив указатель потока в конец файла. Если файл не существует — он создаётся.
Файлы можно открывать и пользуясь синхронным методом fs.openSync() , который, вместо того, чтобы предоставить дескриптор файла в коллбэке, возвращает его:
После получения дескриптора любым из вышеописанных способов вы можете производить с ним необходимые операции.
Данные о файлах
С каждым файлом связан набор данных о нём, исследовать эти данные можно средствами Node.js. В частности, сделать это можно, используя метод stat() из модуля fs .
Вызывают этот метод, передавая ему путь к файлу, и, после того, как Node.js получит необходимые сведения о файле, он вызовет коллбэк, переданный методу stat() . Вот как это выглядит:
В Node.js имеется возможность синхронного получения сведений о файлах. При таком подходе главный поток блокируется до получения свойств файла:
Информация о файле попадёт в константу stats . Что это за информация? На самом деле, соответствующий объект предоставляет нам большое количество полезных свойств и методов:
- Методы .isFile() и .isDirectory() позволяют, соответственно, узнать, является ли исследуемый файл обычным файлом или директорией.
- Метод .isSymbolicLink() позволяет узнать, является ли файл символической ссылкой.
- Размер файла можно узнать, воспользовавшись свойством .size .
Тут имеются и другие методы, но эти — самые употребимые. Вот как ими пользоваться:
Пути к файлам в Node.js и модуль path
Путь к файлу — это адрес того места в файловой системе, где он расположен.
В Linux и macOS путь может выглядеть так:
В Windows пути выглядят немного иначе:
На различия в форматах записи путей при использовании разных операционных систем следует обращать внимание, учитывая операционную систему, используемую для развёртывания Node.js-сервера.
В Node.js есть стандартный модуль path , предназначенный для работы с путями к файлам. Перед использованием этого модуля в программе его надо подключить:
▍Получение информации о пути к файлу
Если у вас есть путь к файлу, то, используя возможности модуля path , вы можете, в удобном для восприятия и дальнейшей обработки виде, узнать подробности об этом пути. Выглядит это так:
Здесь, в строке notes , хранится путь к файлу. Для разбора пути использованы следующие методы модуля path :
- dirname() — возвращает родительскую директорию файла.
- basename() — возвращает имя файла.
- extname() — возвращает расширение файла.
Узнать имя файла без расширения можно, вызвав метод .basename() и передав ему второй аргумент, представляющий расширение:
▍Работа с путями к файлам
Несколько частей пути можно объединить, используя метод path.join() :
Найти абсолютный путь к файлу на основе относительного пути к нему можно с использованием метода path.resolve() :
В данном случае Node.js просто добавляет /flavio.txt к пути, ведущем к текущей рабочей директории. Если при вызове этого метода передать ещё один параметр, представляющий путь к папке, метод использует его в качестве базы для определения абсолютного пути:
Если путь, переданный в качестве первого параметра, начинается с косой черты — это означает, что он представляет собой абсолютный путь.
Вот ещё один полезный метод — path.normalize() . Он позволяет найти реальный путь к файлу, используя путь, в котором содержатся спецификаторы относительного пути вроде точки ( . ), двух точек ( .. ), или двух косых черт:
Методы resolve() и normalize() не проверяют существование директории. Они просто находят путь, основываясь на переданным им данным.
Чтение файлов в Node.js
Самый простой способ чтения файлов в Node.js заключается в использовании метода fs.readFile() с передачей ему пути к файлу и коллбэка, который будет вызван с передачей ему данных файла (или объекта ошибки):
Если надо, можно воспользоваться синхронной версией этого метода — fs.readFileSync() :
По умолчанию при чтении файлов используется кодировка utf8 , но кодировку можно задать и самостоятельно, передав методу соответствующий параметр.
Методы fs.readFile() и fs.readFileSync() считывают в память всё содержимое файла. Это означает, что работа с большими файлами с применением этих методов серьёзно отразится на потреблении памяти вашим приложением и окажет влияние на его производительность. Если с такими файлами нужно работать, лучше всего воспользоваться потоками.
Запись файлов в Node.js
В Node.js легче всего записывать файлы с использованием метода fs.writeFile() :
Есть и синхронная версия того же метода — fs.writeFileSync() :
Эти методы, по умолчанию, заменяют содержимое существующих файлов. Изменить их стандартное поведение можно, воспользовавшись соответствующим флагом:
Тут могут использоваться флаги, которые мы уже перечисляли в разделе, посвящённом дескрипторам. Подробности о флагах можно узнать здесь.
Присоединение данных к файлу
Метод fs.appendFile() (и его синхронную версию — fs.appendFileSync() ) удобно использовать для присоединения данных к концу файла:
Об использовании потоков
Выше мы описывали методы, которые, выполняя запись в файл, пишут в него весь объём переданных им данных, после чего, если используются их синхронные версии, возвращают управление программе, а если применяются асинхронные версии — вызывают коллбэки. Если вас такое состояние дел не устраивает — лучше будет воспользоваться потоками.
Работа с директориями в Node.js
Модуль fs предоставляет в распоряжение разработчика много удобных методов, которые можно использовать для работы с директориями.
▍Проверка существования папки
Для того чтобы проверить, существует ли директория и может ли Node.js получить к ней доступ, учитывая разрешения, можно использовать метод fs.access() .
▍Создание новой папки
Для того чтобы создавать новые папки, можно воспользоваться методами fs.mkdir() и fs.mkdirSync() :
▍Чтение содержимого папки
Для того чтобы прочесть содержимое папки, можно воспользоваться методами fs.readdir() и fs.readdirSync() . В этом примере осуществляется чтение содержимого папки — то есть — сведений о том, какие файлы и поддиректории в ней имеются, и возврат их относительных путей:
Вот так можно получить полный путь к файлу:
Результаты можно отфильтровать для того, чтобы получить только файлы и исключить из вывода директории:
▍Переименование папки
Для переименования папки можно воспользоваться методами fs.rename() и fs.renameSync() . Первый параметр — это текущий путь к папке, второй — новый:
Переименовать папку можно и с помощью синхронного метода fs.renameSync() :
▍Удаление папки
Для того чтобы удалить папку, можно воспользоваться методами fs.rmdir() или fs.rmdirSync() . Надо отметить, что удаление папки, в которой что-то есть, задача несколько более сложная, чем удаление пустой папки. Если вам нужно удалять такие папки, воспользуйтесь пакетом fs-extra, который весьма популярен и хорошо поддерживается. Он представляет собой замену модуля fs , расширяющую его возможности.
Метод remove() из пакета fs-extra умеет удалять папки, в которых уже что-то есть.
Установить этот модуль можно так:
Вот пример его использования:
Его методами можно пользоваться в виде промисов:
Допустимо и применение конструкции async/await:
Модуль fs
Выше мы уже сталкивались с некоторыми методами модуля fs , применяемыми при работе с файловой системой. На самом деле, он содержит ещё много полезного. Напомним, что он не нуждается в установке, для того, чтобы воспользоваться им в программе, его достаточно подключить:
После этого у вас будет доступ к его методам, среди которых отметим следующие, некоторые из которых вам уже знакомы:
- fs.access() : проверяет существование файла и возможность доступа к нему с учётом разрешений.
- fs.appendFile() : присоединяет данные к файлу. Если файл не существует — он будет создан.
- fs.chmod() : изменяет разрешения для заданного файла. Похожие методы: fs.lchmod() , fs.fchmod() .
- fs.chown() : изменяет владельца и группу для заданного файла. Похожие методы: fs.fchown() , fs.lchown() .
- fs.close() : закрывает дескриптор файла.
- fs.copyFile() : копирует файл.
- fs.createReadStream() : создаёт поток чтения файла.
- fs.createWriteStream() : создаёт поток записи файла.
- fs.link() : создаёт новую жёсткую ссылку на файл.
- fs.mkdir() : создаёт новую директорию.
- fs.mkdtemp() : создаёт временную директорию.
- fs.open() : открывает файл.
- fs.readdir() : читает содержимое директории.
- fs.readFile() : считывает содержимое файла. Похожий метод: fs.read() .
- fs.readlink() : считывает значение символической ссылки.
- fs.realpath() : разрешает относительный путь к файлу, построенный с использованием символов . и .. , в полный путь.
- fs.rename() : переименовывает файл или папку.
- fs.rmdir() : удаляет папку.
- fs.stat() : возвращает сведения о файле. Похожие методы: fs.fstat() , fs.lstat() .
- fs.symlink() : создаёт новую символическую ссылку на файл.
- fs.truncate() : обрезает файл до заданной длины. Похожий метод: fs.ftruncate() .
- fs.unlink() : удаляет файл или символическую ссылку.
- fs.unwatchFile() : отключает наблюдение за изменениями файла.
- fs.utimes() : изменяет временную отметку файла. Похожий метод: fs.futimes() .
- fs.watchFile() : включает наблюдение за изменениями файла. Похожий метод: fs.watch() .
- fs.writeFile() : записывает данные в файл. Похожий метод: fs.write() .
Интересной особенностью модуля fs является тот факт, что все его методы, по умолчанию, являются асинхронными, но существуют и их синхронные версии, имена которых получаются путём добавления слова Sync к именам асинхронных методов.
- fs.rename()
- fs.renameSync()
- fs.write()
- fs.writeSync()
Использование синхронных методов серьёзно влияет на то, как работает программа.
В Node.js 10 имеется экспериментальная поддержка этих API, основанных на промисах.
Исследуем метод fs.rename() . Вот асинхронная версия этого метода, использующая коллбэки:
При использовании его синхронной версии для обработки ошибок используется конструкция try/catch :
Основное различие между этими вариантами использования данного метода заключается в том, что во втором случае выполнение скрипта будет заблокировано до завершения файловой операции.
Модуль path
Модуль path, о некоторых возможностях которого мы тоже уже говорили, содержит множество полезных инструментов, позволяющих взаимодействовать с файловой системой. Как уже было сказано, устанавливать его не нужно, так как он является частью Node.js. Для того чтобы пользоваться им, его достаточно подключить:
Свойство path.sep этого модуля предоставляет символ, использующийся для разделения сегментов пути ( \ в Windows и / в Linux и macOS), а свойство path.delimiter даёт символ, используемый для отделения друг от друга нескольких путей ( ; в Windows и : в Linux и macOS).
Рассмотрим и проиллюстрируем примерами некоторые методы модуля path .
▍path.basename()
Возвращает последний фрагмент пути. Передав второй параметр этому методу можно убрать расширение файла.
▍path.dirname()
Возвращает ту часть пути, которая представляет имя директории:
▍path.extname()
Возвращает ту часть пути, которая представляет расширение файла:
▍path.isAbsolute()
Возвращает истинное значение если путь является абсолютным:
▍path.join()
Соединяет несколько частей пути:
▍path.normalize()
Пытается выяснить реальный путь на основе пути, который содержит символы, использующиеся при построении относительных путей вроде . , .. и // :
▍path.parse()
Преобразует путь в объект, свойства которого представляют отдельные части пути:
- root : корневая директория.
- dir : путь к файлу, начиная от корневой директории
- base : имя файла и расширение.
- name : имя файла.
- ext : расширение файла.
Вот пример использования этого метода:
В результате его работы получается такой объект:
▍path.relative()
Принимает, в качестве аргументов, 2 пути. Возвращает относительный путь из первого пути ко второму, основываясь на текущей рабочей директории:
▍path.resolve()
Находит абсолютный путь на основе переданного ему относительного пути:
Источник