Что такое NFS? Network File System. Протокол сетевого доступа к файловым системам. Протокол NFS

Что такое NFS? Network File System. Протокол сетевого доступа к файловым системам. Протокол NFS

Глава 29 NFS: сетевая файловая система

Введение

В этой главе мы рассмотрим сетевую файловую систему ( NFS - Network File System), популярное приложение, которое предоставляет приложениям клиентов прозрачный доступ к файлам. Краеугольным камнем NFS является Sun RPC: вызов удаленной процедуры (Remote Procedure Call), что мы и опишем в первую очередь.

Программе клиента не требуется специальных средств, чтобы воспользоваться NFS. Ядро определяет что файл находится на NFS сервере и автоматически генерирует RPC вызов, для того чтобы получить доступ к файлу.

Мы не будем подробно рассматривать, как реализуется доступ к файлам, а рассмотрим, как при этом используются протоколы Internet, особенно UDP.

Вызов удаленной процедуры компании Sun

В большинстве случаев задачи сетевого программирования решаются путем написания программ приложений, которые вызывают функции, предоставляемые системой, чтобы осуществить конкретные сетевые операции. Например, одна функция осуществляет активное открытие TCP, другая пассивное открытие TCP, третья посылает данные по TCP соединению, четвертая устанавливает конкретные опции протокола (включает TCP таймер "оставайся в живых") и так далее. В разделе "Интерфейсы прикладного программирования" главы 1 мы упоминали, что существует два популярных набора функций для сетевого программирования (прикладной программный интерфейс, API), это сокеты и TLI. Программный интерфейс, используемый клиентом, и программный интерфейс, используемый сервером, могут отличаться, так же как и операционные системы, которые функционируют у клиента и сервера. Именно коммуникационный и прикладной протоколы определяют, сможет ли конкретный клиент общаться с сервером. Unix клиент, написанный на C, использующий сокеты в качестве программного интерфейса, и TCP - в качестве коммуникационного протокола, может общаться с сервером на мейнфрейме, написанным на COBOLе с использованием других API и TCP, если оба хоста подключены к сети и оба имеют реализацию TCP/IP.

Обычно клиент посылает серверу команды, а сервер отправляет клиенту отклики. Все рассмотренные нами приложения, - Ping, Traceroute, демоны маршрутизации, клиенты и сервера DNS, TFTP, BOOTP, SNMP, Telnet, FTP, SMTP - все построены именно таким образом.

RPC, вызов удаленной процедуры, реализует иной подход к сетевому программированию. Программа клиента просто вызывает функции в программе сервера. Так это решено с точки зрения программиста, однако в действительности имеет место следующая последовательность действий.

  1. Когда клиент вызывает удаленную процедуру, вызывается функция на локальном хосте, которая сгенерирована пакетом RPC. Эта функция называется client stub. client stub упаковывает аргументы процедуры в сетевое сообщение и отправляет сообщение серверу.
  2. server stub на хосте сервера получает сетевое сообщение. Аргументы извлекаются из сетевого сообщения, и осуществляется вызов процедуры сервера, написанной прикладным программистом.
  3. Функция сервера возвращает управление server stubу, который, в свою очередь, принимает полученные значения, упаковывает их в сетевое сообщение и отправляет сообщение обратно к client stub.
  4. client stub возвращает приложению клиента значения из сетевого сообщения.

Сетевое программирование, использующее stubы и библиотечные RPC подпрограммы использует интерфейсы прикладного программирования API (сокеты или TLI), однако пользовательские приложения (программа клиента и процедуры сервера, вызываемые клиентом) никогда не обращаются к API. Приложению клиента достаточно вызывать процедуру сервера, при этом все детали реализации спрятаны пакетом RPC, client stubом и server stubом.

Пакеты RPC имеют следующие положительные стороны.

  • Программирование становится легче, так как не приходится решать задачи сетевого программирования (а если и приходится, то совсем немного). Прикладные программисты просто пишут программу клиента и процедуры сервера, которые вызывает клиент.
  • Если используется ненадежный протокол, такой как UDP, все детали, а именно тайм-ауты и повторные передачи обрабатываются пакетом RPC. Это, в свою очередь, упрощает пользовательское приложение.
  • Библиотека RPC обрабатывает необходимое преобразование аргументов и возвращаемых значений. Например, если аргументы состоят из целых чисел и чисел с плавающей точкой, пакет RPC обработает все различия между представлением целых чисел и чисел с плавающей точкой на клиенте и сервере. Благодаря этому упрощается реализация клиентов и серверов для функционирования в разнородных средах.

Программирование RPC подробно описано в главе 18 . Два наиболее популярных RPC пакета это Sun RPC и RPC пакет в Open Software Foundation"s ( OSF) Distributed Computing Environment ( DCE). Мы рассмотрим, как осуществляется вызов процедуры, как выглядит возвращаемое сообщение и как это соотносится с пакетом Sun RPC, так как именно этот пакет используется в сетевой файловой системе. Версия 2 Sun RPC описана в RFC 1057 [ Sun Microsystems 1988a].

Существует два вида Sun RPC. Одна версия построена с использованием API сокет и работает с TCP и UDP. Другая называется TI-RPC (независимо от транспорта - transport independent), построена с использованием TLI API и работает с любыми транспортными уровнями, предоставляемыми ядром. С нашей точки зрения между ними нет никакой разницы, так как в этой главе мы рассматриваем только TCP и UDP.

На рисунке 29.1 показан формат сообщения вызова процедуры RPC, с использованием UDP.

Рисунок 29.1 Сообщения вызова процедуры RPC в формате UDP датаграммы.

Стандартные IP и UDP заголовки показаны раньше (рисунок 3.1 и рисунок 11.2). Все, что следует после UDP заголовка, определяется пакетом RPC.

Идентификатор транзакции ( XID - transaction ID) устанавливается клиентом и возвращается сервером. Когда клиент получает отклик, он сравнивает XID, возвращенный сервером, с XID отправленного запроса. Если они не совпадают, клиент отбрасывает сообщение и ожидает прихода следующего. Каждый раз, когда клиент выдает новый RPC, он меняет XID. Однако если клиент передает RPC повторно (если отклик не был получен), XID не меняется.

Переменная call равна 0 для вызова и 1 для отклика. Текущая версия RPC (RPC version) равна 2. Три следующие переменные, номер программы (program number), номер версии (version number) и номер процедуры (procedure number), идентифицируют конкретную процедуру, которая должна быть вызвана на сервере.

Полномочия (credentials) идентифицируют клиента. В некоторых примерах это поле остается незаполненным, а в других здесь можно встретить цифровой идентификатор пользователя и идентификатор группы к который он принадлежит. Сервер может заглянуть в полномочия и решить, обработать ли запрос или нет. Проверка (verifier) используется для защищенного RPC (Secure RPC), которое использует DES шифрование. Несмотря на то, что поля полномочий и проверки это поля с переменной длиной, их длина передается как часть поля.

Дальше следуют параметры процедуры. Их формат зависит от того, как приложение определяет удаленную процедуру. Как получатель (server stub) узнает размер параметров? Так как используется UDP, размер параметров можно рассчитать как размер UDP датаграммы минус длина всех полей вплоть до поля проверки. Когда вместо UDP используется TCP, понятия фиксированной длины не существует, так как TCP это поток байтов без разделителей записей. В подобном случае, между TCP заголовком и XID появляется 4-байтовое поле длины, из которого приемник узнает длину RPC вызова в байтах. Это позволяет, если необходимо, послать сообщение вызова RPC в нескольких TCP сегментах. (DNS использует подобную технику; упражнение 4 главы 14.)

На рисунке 29.2 показан формат RPC отклика. Он отправляется от server stub к client stub, когда удаленная процедура завершает свою работу.

Рисунок 29.2 Формат сообщения отклика процедуры RPC как UDP датаграмма.

XID вызова просто копируется в XID отклика. В поле reply находится 1, по этому полю проводится различие между вызовом и откликом. Поле статуса (status) содержит нулевое значение, если сообщение вызова было принято. (Сообщение может быть отброшено, если номер версии RPC не равен 2 или если сервер не может аутентифицировать клиента.) Поле проверки (verifier) используется в случае защищенного RPC, чтобы указать сервер.

В поле статуса приема (accept status) находится нулевое значение, если все нормально. Ненулевое значение может указывать, например, на неверный номер версии или неверный номер процедуры. Если вместо UDP используется TCP, то, как и в случае сообщения вызова RPC, между TCP заголовком и XID посылается 4-байтовое поле длины.

XDR: представление внешних данных

Представление внешних данных ( XDR - External Data Representation) это стандарт, используемый для кодирования значений в RPC вызове и отклике сообщениях - полей заголовка RPC (XID, номер программы, статус приема и так далее), параметров процедуры и результатов процедуры. Стандартный способ кодирования данных позволяет клиенту вызвать процедуру в системе с отличной архитектурой. XDR определен в RFC 1014 [ Sun Microsystems 1987].

XDR определяет определенное количество типов данных и точный способ того, как они передаются в RPC сообщении (порядок битов, порядок байтов и так далее). Отправитель должен построить RPC сообщение в XDR формате, тогда получатель конвертирует XDR формат в исходное представление. (В тот формат, который принят для его системы.) Мы видим, например, на рисунках 29.1 и 29.2, что все целые значения, которые мы показали (XID, вызов, номер программы и так далее), это 4-байтовые целые числа. И действительно, все целые в XDR занимают 4 байта. XDR поддерживает и другие типы данных, включая целые без знака, логические, числа с плавающей точкой, массивы фиксированной длины, массивы переменной длины и структуры.

Соответствие портов

Программы RPC сервера, содержащие удаленные процедуры, используют динамически назначаемые порты, а не заранее известные порты. Это требует "регистрации" в какой-либо форме, для того чтобы постоянно иметь информацию, какая динамически назначаемый порт использует та или иная RPC программа. В Sun RPC этот регистратор называется преобразователь портов (port mapper). (Port mapper - это сервер, который конвертирует номера RPC программ в номера портов протоколов DARPA. Этот сервер обязательно должен быть запущен, чтобы можно было исполнить RPC вызов.)

Термин "порт" (port) в названии происходит от номеров портов TCP и UDP, характеристики семейства протоколов Internet. Так как TI-RPC работает поверх любых транспортных уровней, а не только поверх TCP и UDP, название port mapper в системах, использующих TI-RPC ( SVR4 и Solaris 2.2, например), было преобразовано в rpcbind. Однако мы будем продолжать использовать более привычное - port mapper.

В действительности, сам преобразователь портов должен иметь заранее известный порт: UDP порт 111 и TCP порт 111. Преобразователь портов - это всего лишь программа RPC сервера. Он имеет номер программы (100000), номер версии (2), TCP порт 111 и UDP порт 111. Серверы регистрируют друг друга в преобразователе портов, используя RPC вызовы, а клиенты запрашивают преобразователь портов, используя RPC вызовы. Преобразователь портов предоставляет четыре процедуры сервера:

  1. PMAPPROC_SET. Вызывается RPC сервером при старте, чтобы зарегистрировать номер программы, номер версии и протокол в преобразователе портов.
  2. PMAPPROC_UNSET. Вызывается сервером, чтобы удалить ранее зарегистрированное преобразование.
  3. PMAPPROC_GETPORT. Вызывается RPC клиентом при старте, чтобы получить номер порта для заданного номера программы, номера версии и протокола.
  4. PMAPPROC_DUMP. Возвращает все пункты (номер программы, номер версии, протокол и номер порта) в базу данных преобразователя портов.

Когда стартует программа сервер RPC и позже, когда она вызывается программой клиента RPC, осуществляются следующие шаги.

  1. Преобразователь портов должен стартовать первым, обычно при загрузке системы. При этом создается конечная точка TCP и осуществляется пассивное открытие TCP порта 111. Также создается конечная точка UDP, которая находится в ожидании, когда на UDP порт 111 прибудет UDP датаграмма.
  2. При старте программа сервера RPC создает конечную точку TCP и конечную точку UDP для каждой поддерживаемой версии программы. (Программа RPC может поддерживать несколько версий. Клиент указывает требуемую версию при вызове процедуры сервера.) Динамически назначаемый номер порта закрепляется за каждой конечной точкой. (Нет никакой разницы, одинаковые ли номера портов TCP и UDP или разные.) Сервер регистрирует каждую программу, версию, протокол и номер порта, осуществляя удаленной вызов процедуры преобразователя портов PMAPPROC_SET.
  3. Когда стартует программа клиента RPC, она вызывает процедуру преобразователя портов PMAPPROC_GETPORT, чтобы получить динамически назначаемый номер порта для заданной программы, версии и протокола.
  4. Клиент отправляет сообщение вызова RPC на номер порта, полученный в пункте 3. Если используется UDP, клиент просто посылает UDP датаграмму, содержащую сообщение вызова RPC (рисунок 29.1), на номер UDP порта сервера. В ответ сервер отправляет UDP датаграмму, содержащую сообщение RPC отклика (рисунок 29.2). Если используется TCP, клиент осуществляет активное открытие на номер TCP порта сервера и затем посылает сообщение вызова RPC по соединению. Сервер отвечает сообщением отклика RPC по соединению.

Программа rpcinfo(8) печатает все текущие настройки преобразователя портов. (Здесь происходит вызов процедуры преобразователя портов PMAPPROC_DUMP.) Ниже показан обычный вывод:

Sun % /usr/etc/rpcinfo -p
program vers proto port
100005 1 tcp 702 mountd демон монтирования NFS
100005 1 udp 699 mountd
100005 2 tcp 702 mountd
100005 2 udp 699 mountd

100003 2 udp 2049 nfs сам NFS

100021 1 tcp 709 nlockmgr менеджер блокирования NFS
100021 1 udp 1036 nlockmgr
100021 2 tcp 721 nlockmgr
100021 2 udp 1039 nlockmgr
100021 3 tcp 713 nlockmgr
100021 3 udp 1037 nlockmgr

Мы видим, что некоторые программы поддерживают несколько версий, и каждая комбинация номера программы, номера версии и протокола имеет свою собственную раскладку номеров портов, обслуживаемую преобразователем портов.

Доступ к обеим версиям монтирующего демона можно получить через один и тот же номер TCP порта (702) и один и тот же номер UDP порта (699), однако каждая версия блокирующего менеджера имеет свой собственный номер порта.

Протокол NFS

NFS предоставляет клиентам прозрачный доступ к файлам и файловой системе сервера. Это отличается от FTP (глава 27), который обеспечивает передачу файлов. С помощью FTP осуществляется полное копирование файла. NFS осуществляет доступ только к тем частям файла, к которым обратился процесс, и основное достоинство NFS в том, что он делает этот доступ прозрачным. Это означает, что любое приложение клиента, которое может работать с локальным файлом, с таким же успехом может работать и с NFS файлом, без каких либо модификаций самой программы.

NFS это приложение клиент-сервер, построенное с использованием Sun RPC. NFS клиенты получают доступ к файлам на NFS сервере путем отправки RPC запросов на сервер. Это может быть реализовано с использованием обычных пользовательских процессов - а именно, NFS клиент может быть пользовательским процессом, который осуществляет конкретные RPC вызовы на сервер, который так же может быть пользовательским процессом. Однако, NFS обычно реализуется иначе, это делается по двум причинам. Во-первых, доступ к NFS файлам должен быть прозрачным для клиента. Поэтому, вызовы NFS клиента осуществляются операционной системой клиента от имени пользовательского процесса клиента. Во-вторых, NFS сервера реализованы внутри операционной системы для повышения эффективности работы сервера. Если бы NFS сервер являлся пользовательским процессом, каждый запрос клиента и отклик сервера (включая данные, которые будут считаны или записаны) должен пройти через разделитель между ядром и пользовательским процессом, что вообще довольно дорогое удовольствие.

В этом разделе мы рассмотрим версию 2 NFS, как она документирована в RFC 1094 [ Sun Microsystems 1988b]. Лучшее описание Sun RPC, XDR и NFS дано в [ X/Open 1991]. Подробности использования и администрирования NFS приведены в [ Stern 1991]. Спецификации версии 3 протокола NFS были реализованы в 1993 году, о чем мы поговорим в разделе этой главы.

На рисунке 29.3 показаны типичные настройки NFS клиента и NFS сервера. На этом рисунке необходимо обратить внимание на следующее.

  1. Клиенту безразлично, получает ли он доступ к локальному файлу или к NFS файлу. Ядро определяет это, когда файл открыт. После того как файл открыт, ядро передает все обращения к локальным файлам в квадратик, помеченный как "доступ к локальным файлам", а все ссылки на NFS файлы передаются в квадратик "NFS клиент".
  2. NFS клиент отправляет RPC запросы NFS серверу через модуль TCP/IP. NFS обычно использует UDP, однако более новые реализации могут использовать TCP.
  3. NFS сервер получает запросы от клиента в виде UDP датаграмм на порт 2049. Несмотря на то, что NFS может работать с преобразователем портов, что позволяет серверу использовать динамически назначаемые порты, UDP порт 2049 жестко закреплен за NFS в большинстве реализаций.

Рисунок 29.3 Типичные настройки NFS клиента и NFS сервера.

  • Когда NFS сервер получает запрос от клиента, он передаются локальной подпрограмме доступа к файлу, которая обеспечивает доступ к локальному диску на сервере.
  • Серверу может потребоваться время, для того чтобы обработать запросы клиента. Даже доступ к локальной файловой системе может занять некоторое время. В течение этого времени сервер не хочет блокировать запросы от других клиентов, которые также должны быть обслужены. Чтобы справиться с подобной ситуацией, большинство NFS серверов запускаются несколько раз, то есть внутри ядра существует несколько NFS серверов. Конкретные методы решения зависят от операционной системы. В большинстве ядер Unix систем не "живет" несколько NFS серверов, вместо этого запускается несколько пользовательских процессов (которые обычно называются nfsd), которые осуществляют один системный вызов и остаются внутри ядра в качестве процесса ядра.
  • Точно так же, NFS клиенту требуется время, чтобы обработать запрос от пользовательского процесса на хосте клиента. RPC выдается на хост сервера, после чего ожидается отклик. Для того, чтобы пользовательские процессы на хосте клиента могли в любой момент воспользоваться NFS, существует несколько NFS клиентов, запущенных внутри ядра клиента. Конкретная реализация также зависит от операционной системы. Unix система обычно использует технику, напоминающую NFS сервер: пользовательский процесс, называемый biod, осуществляет один единственный системный вызов и остается внутри ядра как процесс ядра.
  • Большинство Unix хостов может функционировать как NFS клиент и как NFS сервер, или как и то и другое одновременно. Большинство PC реализаций (MS-DOS) имеют только реализации NFS клиента. Большинство IBM мейнфреймов предоставляет только функции NFS сервера.

    NFS в действительности - это нечто большее, чем просто NFS протокол. На рисунке 29.4 показаны различные программы RPC, которые используются с NFS.

    Приложение

    Номер программы

    Номер версии

    Количество процедур

    преобразователь портов
    NFS
    программа mount
    менеджер блокирования
    монитор статуса

    Рисунок 29.4 Различные RPC программы, используемые в NFS.

    Версии, которые мы показали на этом рисунке в виде единиц, найдены в таких системах как SunOS 4.1.3. Новые реализации предоставляют более новые версии некоторых программ. Solaris 2.2, например, также поддерживает версии 3 и 4 преобразователя портов и версию 2 демона mount. SVR4 также поддерживает версию 3 преобразователя портов.

    Демон монтирования вызывается на хосте NFS клиента, перед тем как клиент может получить доступ к файловой системе сервера. Мы опишем этот процесс ниже.

    Менеджер блокирования и монитор статуса позволяют клиенту заблокировать часть файлов, которые находятся на NFS сервере. Эти две программы не зависимы от протокола NFS, потому что блокирование требует идентификации клиента и на хосте клиента, и на сервере, а NFS сам по себе "безразличен". (Ниже мы скажем о безразличности NFS более подробно.) Главы 9, 10 и 11 [ X/Open 1991] документируют процедуры, которые используются менеджером блокирования и монитором статуса для блокирования в NFS.

    Описатели файлов

    Одна из основ NFS реализуется описателями файлов. Для обращения к файлу или директории на сервере объекта используется opaque. Термин opaque обозначает, что сервер создает описатель файла, передает его обратно клиенту, который клиент затем использует при обращении к файлу. Клиент никогда не просматривает содержимое описателя файла - его содержимое представляет интерес только для сервера.

    NFS клиент получает описатель файла каждый раз когда открывает файл, который в действительности находится на NFS сервере. Когда NFS клиент читает или пишет в этот файл (по поручению пользовательского процесса), описатель файла передается обратно серверу. Это указывает на то, что доступ к файлу был осуществлен.

    Обычно пользовательский процесс не работает с описателями файлов. Обмен описателями файлов осуществляют NFS клиент и NFS сервер. В версии 2 NFS описатель файла занимает 32 байта, а в версии 3 он вырос до 64 байт.

    Unix серверы обычно хранят в описателе файла следующую информацию: идентификатор файловой системы (major и minor номера устройства файловой системы), номер инода (i-node) (уникальный номер внутри файловой системы), номер поколения инода (номер, который изменяется каждый раз, когда инод повторно используется для другого файла).

    Протокол монтирования

    Клиент использует NFS протокол монтирования, чтобы смонтировать файловую систему сервера, перед тем как получить доступ к NFS файлам. Обычно это происходит при загрузке клиента. В результате клиент получает описатель файла файловой системы сервера.

    На рисунке 29.5 описана последовательность действий Unix клиента при исполнении команды mount(8).

    Рисунок 29.5 Протокол монтирования, используемый Unix командой mount.

    При этом осуществляются следующие шаги.

    1. При загрузке сервера на нем стартует преобразователь портов.
    2. После преобразователя портов на сервере стартует демон монтирования ( mountd). Он создает конечную точку TCP и конечную точку UDP, а также назначает каждой из них динамически назначаемый номер порта. Затем он регистрирует эти номера у преобразователя портов.
    3. Клиент исполняется команду mount, которая выдает RPC вызов на преобразователь портов сервера, чтобы получить номер порта от демона монтирования на сервере. Для обмена между клиентом и преобразователем портов могут быть использованы и TCP и UDP, однако обычно используется UDP.
    4. Преобразователь портов сообщает номер порта.
    5. Команда mount выдает RPC вызов демону монтирования, чтобы смонтировать файловую систему сервера. И снова может быть использован как TCP, так и UDP, однако обычно используется UDP. Теперь сервер может проверить "годность" клиента основываясь на его IP адресе и номере порта, чтобы убедиться, можно ли этому клиенту смонтировать указанную файловую систему.
    6. Демон монтирования откликается описателем файла указанной файловой системы.
    7. Команда mount клиента выдает системный вызов mount, чтобы связать описатель файла, полученный в шаге 5, с локальной точкой монтирования на хосте клиента. Описатель файла хранится в коде NFS клиента, и с этого момента любое обращение пользовательских процессов к файлам на файловой системе сервера будет использовать описатель файла как стартовую точку.

    Подобная реализация отдает весь процесс монтирования, кроме системного вызова mount на клиенте, пользовательским процессам, а не ядру. Три программы, которые мы показали - команда mount, преобразователь портов и демон монтирования - пользовательские процессы.

    В этом примере на хосте sun (NFS клиент) была исполнена команда

    sun # mount -t nfs bsdi:/usr /nfs/bsdi/usr

    Эта команда монтирует директорию /usr на хосте bsdi (NFS сервер) как локальную файловую систему /nfs/bsdi/usr. На рисунке 29.6 показан результат.

    Рисунок 29.6 Монтирование директории bsdi:/usr как /nfs/bsdi/usr на хосте sun.

    После чего при обращении к файлу /nfs/bsdi/usr/rstevens/hello.c на клиенте sun, происходит обращение к файлу /usr/rstevens/hello.c на сервере bsdi.

    Процедуры NFS

    NFS сервер предоставляет 15 процедур, которые мы сейчас опишем. (Числа, которые использованные при описании, не совпадают с номерами NFS процедур, так как мы сгруппировали их по функциональному признаку.) Несмотря на то что NFS разрабатывалась таким образом, чтобы работать между различными операционными системами, а не только между Unix системами, некоторые из процедур основаны именно на Unix функционировании, что, в свою очередь, может не поддерживаться другими операционными системами (например, жесткие линки, символические линки, групповое пользование, права доступа на исполнение и так далее). Глава 4 содержит дополнительную информацию о характеристиках файловых систем, некоторыми из которых пользуется NFS.

    1. GETATTR. Возвращает атрибуты файлов: тип файла (обычный файл, директория и так далее), права доступа, размер файла, владельца файла, время последнего обращения и так далее.
    2. SETATTR. Устанавливает атрибуты файла. Установлен может быть только определенный набор атрибутов: права доступа, владелец, групповое владение, размер, время последнего обращения и время последней модификации.
    3. STATFS. Возвращает статус файловой системы: размер свободного пространства, оптимальный размер для передачи и так далее. Используется, например, Unix командой df.
    4. LOOKUP. "Оценивает" файл. Эта процедура вызывается клиентом каждый раз, когда пользовательский процесс открывает файл, который находится на NFS сервере. Возвращается описатель файла, вместе с атрибутами файла.
    5. READ. Читает из файла. Клиент указывает описатель файла, начальное смещение в байтах и максимальное количество байтов, которое необходимо считать (до 8192).
    6. WRITE. Записывает в файл. Клиент указывает описатель файла, начальное смещение в байтах, количество байт, которое необходимо записать, и данные, которые необходимо записать.

      Требуется, чтобы NFS записи были синхронными (с ожиданием). Сервер не может ответить OK до тех пор, пока данные не были успешно записаны (и любая другая информация о файле, которая должна быть обновлена) на диск.

    7. CREATE. Создает файл.
    8. REMOVE. Удаляет файл.
    9. RENAME. Переименовывает файл.
    10. LINK. Делает жесткий линк на файл. Жесткий линк это Unix концепция, которая определяет, что конкретный файл на диске может иметь любое количество точек входа (имен, которые также называются жесткими линками), которые указывают на этот файл.
    11. SYMLINK. Создает символический линк на файл. Символический линк это файл, который содержит имя другого файла. Большинство операций, которые осуществляются над символическим линком (например, открытие), в действительности совершаются с тем файлом, на котороый указывает символический линк.
    12. READLINK. Чтение символического линка возвращает имя файла, на который указывает символический линк.
    13. MKDIR. Создает директорию.
    14. RMDIR. Удаляет директорию.
    15. READDIR. Читает директорию. Используется, например, Unix командой ls.

    В действительности, приведенные имена процедур начинаются с префикса NFSPROC_, который мы опустили.

    UDP или TCP?

    NFS был исходно написан, чтобы использовать UDP, и эту возможность предоставляют все производители. Однако, более новые реализации, также поддерживают TCP. Поддержка TCP используется для работы в глобальных сетях, которые становится все быстрее. Поэтому использование NFS в настоящее время уже не ограничено локальными сетями.

    Границы между локальными и глобальными сетями стираются, и все это происходит очень быстро. Времена возврата меняются в очень широком диапазоне, и все чаще возникает переполнение. Эти характеристики глобальных сетей приводят к тому, что все чаще в них используются алгоритмы, которые мы рассматривали для TCP - медленный старт и избежание переполнения. Так как UDP не предоставляет ничего похожего на эти алгоритмы, то они или им подобные должны быть встроены в NFS клиент и сервер, иначе необходимо использовать TCP.

    NFS поверх TCP

    Реализация NFS Berkeley Net/2 поддерживает как UDP, так и TCP. [ Macklem 1991] описывает эту реализацию. Давайте рассмотрим, чем отличается использование NFS при работе поверх TCP.

    1. Когда сервер загружается, он запускает NFS сервер, который осуществляет активное открытие на TCP порт 2049, ожидая прихода запроса на соединение от клиента. Это обычно делается в дополнение к обычному NFS UDP, который ожидает входящие датаграммы на UDP порте 2049.
    2. Когда клиент монтирует файловую систему сервера с использованием TCP, он осуществляет активное открытие на TCP порт 2049 на сервере. При этом устанавливается TCP соединение между клиентом и сервером для этой файловой системы. Если тот же самый клиент монтирует еще одну файловую систему на том же самом сервере, создается еще одно TCP соединение.
    3. И клиент, и сервер устанавливают TCP опцию "оставайся в живых" на своих концах соединения (глава 23). Это позволяет определить момент выхода из строя или перезагрузки того или иного участника обмена.
    4. Все приложения на клиенте, которые используют файловую систему сервера, делят одно и то же TCP соединение для этой файловой системы. Например, если была на рисунке 29.6, бы еще одна директория на bsdi, с именем smith, ниже директории /usr, обращения к файлам в /nfs/bsdi/usr/rstevens и /nfs/bsdi/usr/smith делили бы одно и то же TCP соединение.
    5. Если клиент определяет, что сервер вышел из строя или перезагрузился (после получения TCP ошибки "соединение закрыто по тайм-ауту" или "соединение закрыто хостом"), он старается повторно подсоединиться к серверу. Клиент осуществляет еще одно активное открытие, чтобы повторно установить TCP соединение для этой файловой системы. Любой запрос от клиента, для которого отработан тайм-аут на предыдущем соединении, повторно выдается на новое соединение.
    6. Если клиент вышел из строя, то же происходит и с приложениями, которые работали до выхода из строя. Когда клиент перезагружается, он, возможно, повторно смонтирует файловую систему сервера с использованием TCP, причем будет использовано другое TCP соединение с сервером. Предыдущее соединение между клиентом и сервером для этой файловой системы находится в полуоткрытом состоянии (сервер думает, что оно все еще открыто), однако так как сервер установил опцию "оставайся в живых", это полуоткрытое соединение будет закрыто, когда TCP сервер пошлет следующую пробу "оставайся в живых".

    Со временем и другие производители планируют начать поддержку NFS поверх TCP.

    Примеры NFS

    Давайте воспользуемся tcpdump, чтобы посмотреть, какие NFS процедуры привлекаются клиентом для обычных операций с файлом. Когда tcpdump определяет, что UDP датаграмма содержит RPC вызов (call равен 0 на рисунке 29.1) с портом назначения 2049, он декодирует датаграмму как NFS запрос. Точно так же, если UDP датаграмма содержит RPC отклик (reply равен 1 на рисунке 29.2) с портом источника равным 2049, он декодирует датаграмму как NFS отклик.

    Простой пример: чтение файла

    В первом примере мы скопируем файл, находиться на NFS сервере, на терминал с использованием команды cat(1):

    Sun % cat /nfs/bsdi/usr/rstevens/hello.c копирование файла на терминал
    main()
    {
    printf ("hello, world\n");
    }

    Файловая система /nfs/bsdi/usr на хосте sun (NFS клиент) в действительности является файловой системой /usr на хосте bsdi (NFS сервер), как показано на рисунке 29.6. Ядро sun определяет это, когда cat открывает файл и использует NFS для доступа к файлу. На рисунке 29.7 показан вывод команды tcpdump.

    1 0.0 sun.7aa6 > bsdi.nfs: 104 getattr
    2 0.003587 (0.0036) bsdi.nfs > sun.7aa6: reply ok 96

    3 0.005390 (0.0018) sun.7aa7 > bsdi.nfs: 116 lookup "rstevens"
    4 0.009570 (0.0042) bsdi.nfs > sun.7aa7: reply ok 128

    5 0.011413 (0.0018) sun.7aa8 > bsdi.nfs: 116 lookup "hello.c"
    6 0.015512 (0.0041) bsdi.nfs > sun.7aa8: reply ok 128

    7 0.018843 (0.0033) sun.7aa9 > bsdi.nfs: 104 getattr
    8 0.022377 (0.0035) bsdi.nfs > sun.7aa9: reply ok 96

    9 0.027621 (0.0052) sun.7aaa > bsdi.nfs: 116 read 1024 bytes @ 0
    10 0.032170 (0.0045) bsdi.nfs > sun.7aaa: reply ok 140

    Рисунок 29.7 Функционирование NFS при чтении файла.

    Команда tcpdump декодирует NFS запрос или отклик, также она печатает поле XID для клиента, вместо номера порта. Поле XID в строках 1 и 2 равно 0x7aa6.

    Имя файла /nfs/bsdi/usr/rstevens/hello.c обрабатывается функцией открытия в ядре клиента по одному элементу имени за раз. Когда функция открытия достигает /nfs/bsdi/usr, она определяет, что это точка монтирования файловой системы NFS.

    В строке 1 клиент вызывает процедуру GETATTR, чтобы получить атрибуты директории сервера, которую смонтировал клиент (/usr). Этот RPC запрос содержит 104 байта данных, помимо IP и UDP заголовков. Отклик в строке 2 возвращает OK и содержит 96 байт данных, помимо IP и UDP заголовков. Мы видим на этом рисунке, что минимальное NFS сообщение содержит примерно 100 байт данных.

    В строке 3 клиент вызывает процедуру LOOKUP для файла rstevens и получает отклик OK в строке 4. LOOKUP указывает имя файла rstevens и описатель файла, который был сохранен ядром, когда монтировалась удаленная файловая система. Отклик содержит новый описатель файла, который используется в следующем шаге.

    В строке 5 клиент осуществляет LOOKUP файла hello.c с использованием описателя файла из строки 4. Он получает другой описатель файла в строке 6. Этот новый описатель файла как раз то, что клиент использует в строках 7 и 9, чтобы обратиться к файлу /nfs/bsdi/usr/rstevens/hello.c. Мы видим, что клиент осуществляет LOOKUP для каждого компонента имени в пути к открываемому файлу.

    В строке 7 клиент еще раз исполняет GETATTR, затем следует READ в строке 9. Клиент запрашивает 1024 байта, начиная со смещения равного 0, однако получает данных меньше чем 1024 байта. (После вычитания размеров RPC полей и других значений, возвращенных процедурой READ, в строке 10 возвращаются 38 байт данных. Это как раз размер файла hello.c.)

    В этом примере пользовательский процесс ничего не знает об этих NFS запросах и откликах, которые осуществляются ядром. Приложение всего лишь вызывает функцию открытия ядра, которая вызывает обмен 3 запросами и 3 откликами (строки 1-6), а затем вызывает функцию чтение ядра, которая вызывает 2 запроса и 2 отклика (строки 7-10). Для приложения клиента, файл, находящийся на NFS сервере, прозрачен.

    Простой пример: создание директории

    В качестве еще одного примера сменим рабочую директорию на директорию, которая находится на NFS сервере, а затем создадим новую директорию:

    Sun % cd /nfs/bsdi/usr/rstevens меняем рабочую директорию
    sun % mkdir Mail создаем директорию

    На рисунке 29.8 показан вывод команды tcpdump.

    1 0.0 sun.7ad2 > bsdi.nfs: 104 getattr
    2 0.004912 (0.0049) bsdi.nfs > sun.7ad2: reply ok 96

    3 0.007266 (0.0024) sun.7ad3 > bsdi.nfs: 104 getattr
    4 0.010846 (0.0036) bsdi.nfs > sun.7ad3: reply ok 96

    5 35.769875 (35.7590) sun.7ad4 > bsdi.nfs: 104 getattr
    6 35.773432 (0.0036) bsdi.nfs > sun.7ad4: reply ok 96

    7 35.775236 (0.0018) sun.7ad5 > bsdi.nfs: 112 lookup "Mail"
    8 35.780914 (0.0057) bsdi.nfs > sun.7ad5: reply ok 28

    9 35.782339 (0.0014) sun.7ad6 > bsdi.nfs: 144 mkdir "Mail"
    10 35.992354 (0.2100) bsdi.nfs > sun.7ad6: reply ok 128

    Рисунок 29.8 Функционирование NFS при смене директории (cd) на NFS директорию, а затем создание директории (mkdir).

    При смене директории клиент вызывает процедуру GETATTR дважды (строки 1-4). Когда мы создаем новую директорию, клиент вызывает процедуру GETATTR (строки 5 и 6), затем LOOKUP (строки 7 и 8, чтобы проверить, что такой директории не существует), затем MKDIR, чтобы создать директорию (строки 9 и 10). Отклик OK в строке 8 не означает, что директория существует. Он просто означает, что процедура вернула какое-то значение. tcpdump не интерпретирует значение, возвращаемое NFS процедурами. Команда просто печатает OK и количество байт данных в отклике.

    Безразличность

    Одна из характеристик NFS (критики NFS называют это бородавкой, а не характеристикой) заключается в том, что NFS сервер безразличен. Сервер не заботится о том, какие клиенты получают доступ и к каким файлам. Заметьте, что в списке NFS процедур, показанных ранее, нет процедуры открытия или закрытия. Процедура LOOKUP напоминает открытие, однако сервер никогда не знает, осуществил ли клиент обращение к файлу, после того как был сделан LOOKUP.

    Причина такого "безразличного поведения" заключается в том, чтобы упростить восстановление после выхода из строя сервера, после того как он сломался и перезагрузился.

    Пример: выход сервера из строя

    В следующем примере мы читаем файл с NFS сервера, когда сервер выходит из строя и перезагружается. Это покажет как "безразличность" сервера позволяет, клиенту "не знать" о том, что сервер вышел из строя. Все то время, пока сервер сломался и перезагружается, клиент не знает о проблеме, и приложение клиента работает так же, как и раньше.

    На клиенте sun мы стартовали cat с очень большим файлом в качестве аргумента (/usr/share/lib/termcap на NFS сервере svr4), отсоединили Ethernet кабель в процессе передачи, выключили и перезагрузили сервер и затем снова подсоединили кабель. Клиент был сконфигурирован таким образом, чтобы читать 1024 байта за одно NFS чтение. На рисунке 29.9 показан вывод tcpdump.

    Строки 1-10 соответствуют открытию файла клиентом. Эта операция напоминает ту, что показана на рисунке 29.7. В строке 11 мы видим первое чтение (READ) из файла 1024-х байт данных; отклик возвратился в строке 12. Это продолжается до строки 129 (чтение READ по 1024 байта и затем отклик OK).

    В строках 130 и 131 мы видим два запроса, которые отработаны по тайм-ауту и повторно переданы в строках 132 и 133. Первый вопрос: мы видим два запроса на чтение, один начинается со смещения 65536, а другой начинается со смещения 73728, почему? Ядро клиента определило, что приложение клиента осуществляет последовательное считывание, и постаралось получить блоки данных заранее. (Большинство Unix ядер осуществляют это чтение вперед (read-ahead).) Ядро клиента также запустило несколько NFS демонов блочного ввода-вывода (I/O) (biod процессы), которые стараются сгенерировать несколько RPC запросов от имени клиента. Один демон считывает 8192 байта, начиная с 65536 (в 1024-байтных цепочках), а другие осуществляют чтение вперед по 8192 байта, начиная с 73728.

    Повторные передачи клиента появляются в строках 130-168. В строке 169 мы видим, что сервер перезагрузился, и послал ARP запрос перед тем, как откликнуться на NFS запрос клиента из строки 168. Отклик на строку 168 посылается в строке 171. Запросы клиента на чтение (READ) продолжаются.

    1 0.0 sun.7ade > svr4.nfs: 104 getattr
    2 0.007653 (0.0077) svr4.nfs > sun.7ade: reply ok 96

    3 0.009041 (0.0014) sun.7adf > svr4.nfs: 116 lookup "share"
    4 0.017237 (0.0082) svr4.nfs > sun.7adf: reply ok 128

    5 0.018518 (0.0013) sun.7ae0 > svr4.nfs: 112 lookup "lib"
    6 0.026802 (0.0083) svr4.nfs > sun.7ae0: reply ok 128

    7 0.028096 (0.0013) sun.7ae1 > svr4.nfs: 116 lookup "termcap"
    8 0.036434 (0.0083) svr4.nfs > sun.7ae1: reply ok 128

    9 0.038060 (0.0016) sun.7ae2 > svr4.nfs: 104 getattr
    10 0.045821 (0.0078) svr4.nfs > sun.7ae2: reply ok 96

    11 0.050984 (0.0052) sun.7ae3 > svr4.nfs: 116 read 1024 bytes @ 0
    12 0.084995 (0.0340) svr4.nfs > sun.7ae3: reply ok 1124

    Считывание

    128 3.430313 (0.0013) sun.7b22 > svr4.nfs: 116 read 1024 bytes @ 64512
    129 3.441828 (0.0115) svr4.nfs > sun.7b22: reply ok 1124

    130 4.125031 (0.6832) sun.7b23 >
    131 4.868593 (0.7436) sun.7b24 >

    132 4.993021 (0.1244) sun.7b23 > svr4.nfs: 116 read 1024 bytes @ 65536
    133 5.732217 (0.7392) sun.7b24 > svr4.nfs: 116 read 1024 bytes @ 73728

    134 6.732084 (0.9999) sun.7b23 > svr4.nfs: 116 read 1024 bytes @ 65536
    135 7.472098 (0.7400) sun.7b24 > svr4.nfs: 116 read 1024 bytes @ 73728

    136 10.211964 (2.7399) sun.7b23 >
    137 10.951960 (0.7400) sun.7b24 >

    138 17.171767 (6.2198) sun.7b23 > svr4.nfs: 116 read 1024 bytes @ 65536
    139 17.911762 (0.7400) sun.7b24 > svr4.nfs: 116 read 1024 bytes @ 73728

    140 31.092136 (13.1804) sun.7b23 > svr4.nfs: 116 read 1024 bytes @ 65536
    141 31.831432 (0.7393) sun.7b24 > svr4.nfs: 116 read 1024 bytes @ 73728

    142 51.090854 (19.2594) sun.7b23 > svr4.nfs: 116 read 1024 bytes @ 65536
    143 51.830939 (0.7401) sun.7b24 > svr4.nfs: 116 read 1024 bytes @ 73728

    144 71.090305 (19.2594) sun.7b23 > svr4.nfs: 116 read 1024 bytes @ 65536
    145 71.830155 (0.7398) sun.7b24 > svr4.nfs: 116 read 1024 bytes @ 73728

    Повторные передачи

    167 291.824285 (0.7400) sun.7b24 > svr4.nfs: 116 read 1024 bytes @ 73728
    168 311.083676 (19.2594) sun.7b23 > svr4.nfs: 116 read 1024 bytes @ 65536

    Сервер перезагрузился

    169 311.149476 (0.0658) arp who-has sun tell svr4
    170 311.150004 (0.0005) arp reply sun is-at 8:0:20:3:f6:42

    171 311.154852 (0.0048) svr4.nfs > sun.7b23: reply ok 1124

    172 311.156671 (0.0018) sun.7b25 > svr4.nfs: 116 read 1024 bytes @ 66560
    173 311.168926 (0.0123) svr4.nfs > sun.7b25: reply ok 1124
    считывание

    Рисунок 29.9 Считывание файла клиентом, когда NFS сервер вышел из строя и перезагрузился.

    Приложение клиента никогда не узнает, что сервер выходил из строя и перезагружался, за исключением того, что между строками 129 и 171 была 5-минутная пауза, таким образом, выход из строя сервера прозрачен для клиента.

    Чтобы оценить продолжительность тайм-аутов при повторных передачах в этом примере, представьте, что существуют два демона клиента, каждый со своими собственными тайм-аутами. Интервалы для первого демона (читающего со смещения 65536) примерно следующие (округлено до двух знаков после запятой): 0,68; 0,87; 1,74; 3,48; 6,96; 13,92; 20,0; 20,0; 20,0 и так далее. Интервалы для второго демона (читающего со смещения 73728) точно такие же. Это означает, что эти NFS клиенты используют тайм-ауты, которые кратны 0,875 секунды с верхним пределом равным 20 секундам. После каждого тайм-аута интервал повторной передачи удваивается: 0,875; 1,75; 3,5; 7,0 и 14,0.

    Сколько времени клиент будет осуществлять повторные передачи? Клиент имеет две опции, которые могут повлиять на это. Во-первых, если файловая система сервера смонтирована жестко (hard) , клиент будет повторно передавать вечно, однако если файловая система сервера смонтирована мягко (soft) , клиент прекратит свои попытки после фиксированного количества повторных передач. Также, в случае жесткого монтирования клиент имеет опцию, позволяющую пользователю прервать неудачные повторные передачи или не прерывать. Если при монтировании файловой системы сервера, хост клиента указывает что прервать можно, и если мы не хотим ждать 5 минут, пока сервер перезагрузится после выхода из строя, мы можем ввести символ прерывания, чтобы прекратить работу приложения клиента.

    Несколько одинаковых процедур

    RPC процедуры могут быть исполнены сервером несколько раз, но при этом все равно возвращают тот же самый результат. Например, процедура чтения NFS. Как мы видели на рисунке 29.9, клиент просто повторно выдает вызов READ до тех пор, пока он получает отклик. В нашем примере причина повторной передачи была в том, что сервер вышел из строя. Если сервер не вышел из строя, а сообщения, содержащие RPC отклики, были потеряны (так как UDP ненадежный протокол), клиент просто повторно передает, и сервер снова осуществляет то же самое чтение (READ). Та же самая часть того же самого файла считывается снова и посылается клиенту.

    Это работает, потому что каждый запрос на чтение READ содержит начальное смещение. Если бы NFS процедура попросила сервер считать следующие N байт файла, это бы не сработало. Если бы сервер не был безразличным (это значение наоборот к безразличности), и отклик потерян, а клиент повторно выдает READ для следующих N байт, результат будет отличаться. Именно поэтому процедуры NFS READ и WRITE имеют начальное смещение. Именно клиент поддерживает состояние (текущее смещение для каждого файла), а не сервер.

    К несчастью, не все операции с файловыми системами можно исполнить несколько раз. Например, представьте себе следующие шаги: клиент NFS выдает запрос REMOVE, чтобы удалить файл; NFS сервер удаляет файл и отвечает OK; отклик сервера потерян; NFS клиент отрабатывает тайм-аут и повторно передает запрос; NFS сервер не может найти файл и возвращает ошибку; приложение клиента получает ошибку, сообщающую о том, что файл не существует. Эта ошибка возвращается приложению клиента, и эта ошибка несет неверную информацию - файл не существовал и был удален.

    Ниже приведен список NFS процедур, которые можно исполнить несколько раз: GETATTR, STATFS, LOOKUP, READ, WRITE, READLINK и READDIR. Процедуры, которые нельзя исполнить несколько раз: CREATE, REMOVE, RENAME, LINK, SYMLINK, MKDIR и RMDIR. SETATTR обычно исполняется несколько раз, если только она не была использована для того, чтобы обрезать файл.

    Так как в случае использования UDP всегда могут появиться потерянные отклики, NFS сервера должны иметь способ обработать операции, которые нельзя исполнять несколько раз. Большинство серверов имеют кэш последних откликов, в котором они хранят последние принятые отклики для подобных операций. Каждый раз, когда сервер получает запрос, он, во-первых, просматривает свой кэш, и если найдено совпадение, возвращает предыдущий отклик, вместо того чтобы вызывать NFS процедуру снова. [ Juszczak 1989] описывает детали этих типов кэша.

    Подобный подход к процедурам на серверах применяется ко всем приложениям, основанным на UDP, а не только NFS. DNS, например, предоставляет сервис, безболезненно используемый несколько раз. DNS сервер может осуществить запрос разборщика любое количество раз, что не приведет к отрицательным результатам (может быть, кроме того, что будут заняты сетевые ресурсы).

    NFS версии 3

    В течение 1994 года были выпущены спецификации для версии 3 протокола NFS [ Sun Microsystems 1993]. Реализации, как ожидается, станут доступными в течение 1994 года.

    Здесь вкратце описаны основные различия между версиями 2 и 3. Мы будем называть их V2 и V3.

    1. Описатели файлов в V2 это массив фиксированного размера - 32 байта. В V3 это массив переменного размера с размером до 64 байт. Массив переменной длины в XDR определяется 4-байтным счетчиком, за которым следуют реальные байты. Это уменьшает размер описателя файла в таких реализациях, как, например, Unix, где требуется всего около 12 байт, однако позволяет не-Unix реализациям обмениваться дополнительной информацией.
    2. V2 ограничивает количество байт на процедуры READ или WRITE RPC размером 8192 байта. Это ограничение не действует в V3, что, в свою очередь, означает, что с использованием UDP ограничение будет только в размере IP датаграммы (65535 байт). Это позволяет использовать большие пакеты при чтении и записи в быстрых сетях.
    3. Размеры файлов и начальное смещение байтов для процедур READ и WRITE расширены с 32 до 64 бит, что позволяет работать с файлами большего размера.
    4. Атрибуты файла возвращаются в каждом вызове, который может повлиять на атрибуты. Это уменьшает количество вызовов GETATTR, требуемых клиентом.
    5. Записи (WRITE) могут быть асинхронными, тогда как в V2 они должны были быть синхронными. Это может улучшить производительность процедуры WRITE.
    6. Одна процедура была удалена (STATFS) и семь были добавлены: ACCESS (проверка прав доступа к файлу), MKNOD (создание специального файла Unix), READDIRPLUS (возвращает имена файлов в директории вместе с их атрибутами), FSINFO (возвращает статистическую информацию о файловой системе), FSSTAT (возвращает динамическую информацию о файловой системе), PATHCONF (возвращает POSIX.1 информацию о файле) и COMMIT (передает ранее сделанные асинхронные записи на постоянное хранение).

    Краткие выводы

    RPC это способ построить приложение клиент-сервер таким образом, что клиент просто вызывает процедуры на сервере. Все сетевые детали спрятаны в stubах клиента и сервера, которые генерируются для приложений пакетом RPC и в подпрограммах библиотеки RPC. Мы показали формат RPC сообщений вызова и отклика и упомянули, что XDR используется, чтобы кодировать значения, что позволяет RPC клиентам и серверам работать на машинах с различной архитектурой.

    Одно из наиболее широко используемых приложений RPC это Sun NFS, протокол доступа к разнородным файлам, который широко используется на хостах практически всех размеров. Мы рассмотрели NFS и то, как он использует UDP или TCP. В протоколе NFS версии 2 (NFS Version 2) определено 15 процедур.

    Доступ клиента к NFS серверу начинается с протокола монтирования, после чего клиенту возвращается описатель файла. Затем клиент может получить доступ к файлам в файловой системе сервера с использованием этого описателя файла. Имена файлов просматриваются на сервере по одному элементу имени за раз, при этом для каждого элемента возвращается новый описатель файла. Конечный результат это описатель того файла, к которому было осуществлено обращение, и который используется при последовательных чтениях и записях.

    NFS старается сделать все свои процедуры независимыми от количества исполнений таким образом, чтобы клиент мог просто повторно выдать запрос, если отклик был потерян. Мы видели примеры этого: в случае, когда клиент читал файл, пока сервер вышел из строя и перезагружался.

    Упражнения

    На рисунке 29.7 мы видели, что tcpdump интерпретирует пакеты как NFS запросы и отклики, и при этом печатает XID. Может ли tcpdump сделать это для любых RPC запросов или откликов?
  • Как Вы думаете, почему в Unix системах программа RPC сервера использует динамически назначаемые порты, а не заранее известные?
  • RPC клиент вызвал две процедуры сервера. Первая процедура потребовалось на исполнение 5 секунд, а второй - 1 секунда. Клиент имеет тайм-аут равный 4 секундам. Нарисуйте временную диаграмму того, чем обмениваются клиент и сервер. (Представьте, что на прохождение сообщения от клиента к серверу и наоборот время не тратится.)
  • Что произойдет в примере на рисунке 29.9, если пока NFS сервер был выключен, его Ethernet плата была удалена?
  • Когда сервер перезагрузился на рисунке 29.9, он обрабатывал запрос, начинающийся на смещении 65536 (строки 168 и 171), а затем обрабатывал следующий запрос, начинающийся со смещения 66560 (строки 172 и 173). Что произойдет с запросом, начинающимся со смещением 73728 (строка 167)?
  • Когда мы описывали независимые от количества исполнений NFS процедуры, то показали пример отклика REMOVE, который потерялся в сети. Что произойдет в этом случае, если используется TCP вместо UDP?
  • Если NFS сервер использует динамически назначаемый порт вместо порта 2049, что произойдет с NFS клиентом, когда сервер выйдет из строя и перезагрузится?
  • Номеров зарезервированных портов (глава 1, раздел "Номера портов") очень-очень мало, их максимум 1023 на хост. Если NFS сервер требует, чтобы его клиенты имели зарезервированные порты (что обычно так и есть), и NFS клиент, использующий TCP, монтирует N файловых систем на N различных серверах, необходимо ли клиенту иметь различные зарезервированные номера портов для каждого соединения?
  • NFS позволяет предоставить общий доступ к каталогам Unix-машины. Небезопасность NFS, и в частности NIS, связана с RPC - по количеству всевозможных эксплоитов RPC представляется негласным лидером (если не считать Sendmail). Так как эти протоколы предназначены для внутренних сетей, защищать их придется от «своих» пользователей. Хотя перед их применением нужно решить, действительно ли они нужны.

    В домашней сети они могут быть достаточно полезными, но в корпоративной сети из соображений безопасности лучше найти им более безопасную альтернативу.

    Файловая система NFS .

    Сетевая файловая система (Network File System, NFS) была разработана компанией Sun как средство доступа к файлам, размещенным на прочих Unix-машинах в пределах локальной сети. При разработке NFS безопасность вообще не учитывалась, что с годами стало причиной многих уязвимостей.

    NFS может работать по протоколу TCP или UDP, она использует систему RPC, а это означает, что должны быть запущены следующие часто уязвимые приложения: portmapper, nfs, nlockmgr (lockd), rquotad, statd и mountd.

    Не надо запускать NFS - нужно найти альтернативное решение. Если же NFS все-таки нужна, здесь будет рассказано о том, как нужно минимизировать риск ее использования.

    /etc/exports

    Первый шаг заключается в выборе машин, которые будут экспортировать свои файловые системы. Потом можно определить, каким машинам допускается подключаться к NFS-серверам (или серверу, если он один) сети. Не надо использовать NFS на машинах, непосредственно (напрямую) подключенных к Интернету. После того, как будут выбраны машины, надо выбрать каталоги на этих машинах, которые будут экспортированы.

    Каталоги «на экспорт» определяются в файле /etc/exports. Формат каждой записи прост: имя каталога, список пользователей, которым разрешен доступ и режим доступа. К примеру:

    Полный доступ (чтение/запись) к каталогу /home/user разрешен машине с IP-адресом 10.0.0.6. Самое лучшее - это не давать полный доступ, а ограничиться доступом «только чтение» (rо). Кроме данного, можно также указать следующие опции:

    • Secure - запрос на монтирование (mount) должен исходить из привилегированного порта (с номером до 1024). Это означает, что команду на монтирование ввел пользователь с привилегиями root.
    • Root_squash - запрос пользователя root будет расцениваться как запрос анонимного пользователя. Это позволяет причинить наименьший вред системе. Эта опция должна быть включена.
    • All_squash - все запросы (не только от пользователя root) будут расцениваться как исходящие от анонимного пользователя. Полезно применять для публично экспортируемых каталогов.

    Если крекер с правами root получит доступ к машине, которой дан rw-доступ к каталогу, указанному в /etc/exports, он получит полный контроль над файловой системой, поэтому нельзя экспортировать корневой каталог (/), и системно-важные каталоги, к примеру /usr, /bin, /sbin, /lib, /opt и /etc. Хорошо для экспорта подходят домашние каталоги пользователей.

    Со стороны клиента монтирование общей файловой системы нужно выполнять указанием опции -о nosuid:

    # mount -t nfs -о nosuid 10.0.0.3:/home/user/files /mnt/home/frank

    Это не даст крекеру, получившему доступ к NFS-серверу, получить root-доступ к клиентам.

    Ограничение доступа .

    Независимо от сервиса для ограничения доступа к машине нужно применять IPTables. В случае с NFS-сервером это особенно важно. При применении IPTables надо помнить, что NFS-демон использует порт 2049/TCP/UDP.

    Некоторые RPC-сервисы, к примеру portmapper и NFS, используют постоянные порты (113 и 2049/tcp/udp соответственно), но у остальных RPC-сервисов порты не постоянны, что затрудняет фильтрацию пакетов с помощью IPTables. Единственное, что известно, - это то, что RPC используют порты в диапазоне 32768-65535.

    Если используется ядро 2.4.13 или более новое, то с помощью опции -р <порт> можно точно указать порт для каждого RPC-сервиса.

    Рассмотрим функцию start() из файла /etc/rc.d/init.d/nfslock, используемую для запуска nsflock:

    start () {

    #. Start daemons .

    if [ "$USERLAND_LOCKD" ]; then

    echo -n $"Starting NFS locking: "

    daemon rpc.lockd

    echo -n $"Starting NFS statd: "

    daemon rpc.statd

    echo [ $RETVAL -eq 0 ] && touch /var/touch/lock/subsys/nfslock

    return $RETVAL }

    Для того, чтобы заставить демон statd употреблять конкретный порт, можно употреблять опцию -р, к примеру daemon rpc.statd -p 32800 (или какой угодно другой - какой больше нравится). Точно так же нужно установить порт для mountd, nfsd, rquotad - все они запускаются из сценария /etc/rc.d/init.d/nfs:

    start () {

    # Start daemons.

    action -n $"Starting NFS services: " /usr/sbin/exportfs -r

    if t _x /usr/sbin/rpc.quotad ] ; then echo -n $"Starting NFS quotas: " daemon rpc.rquotad echo

    fi echo -n $"Starting NFS mountd: "

    daemon rpc.mountd 3RPCMOUNTDOPTS

    echo -n $"Starting NFS daemon: " daemon rpc.nfsd $RPCNFSDOPTS echo touch /var/lock/subsys/nfs

    Технология изменения порта для lockd (nlockmgr) отличается от вышеприведенной (не надо пытаться изменить файл /etc/rc.d/init.d/nfslock - ничего не выйдет).

    Lockd исполнен или как модуль ядра, или вкомпилирован в ядро статически. Для изменения номера порта надо открыть файл /etc/modules и найти опции, передаваемые модулю:

    options lockd nlm_udpport=33000 nlm_tcpport=33000

    Теперь, когда RPC-сервисы используют статические порты, которые известны, надо применять IPTables. В следующем наборе правил предполагается, что NFS - единственный запущенный на машине сервер, доступ к которому разрешен только машинам, перечисленным в файле /usr/local/etc/nfsexports.hosts:

    IPX = "/usr/sbin/iptables"

    # Очищаем все цепочки

    $IPT --flush

    $IPT -t nat --flush $IPT -t mangle --flush $IPT -X

    # Разрешаем loopback-трафик $IPT -A INPUT -i lo -j ACCEPT $IPT -A OUTPUT -o lo -j ACCEPT

    # Правила по умолчанию $IPT -P INPUT DROP $IPT -P OUTPUT DROP $IPT -P FORWARD DROP

    $IPT -A INPUT -m state -state ESTABLISHED,RELATED -j ACCEPT $IPT -A OUTPUT -m state -state NEW,ESTABLISHED,RELATED -j ACCEPT

    # Разрешаем доступ каждому компьютеру,

    # указанному в /usr/local/etc/nfsexports.hosts

    for host in "cat /usr/local/etc/nfsexports.hosts"; do $IPT -I INPUT -s $host -p tcp -dport 111 -j ACCEPT

    $IPT -I INPUT -s $host -p udp -dport 111 -j ACCEPT

    $IPT -I INPUT -s $host -p udp -dport 2049 -j ACCEPT

    $IPT -I INPUT -s $host -p tcp --dport 32800 -j ACCEPT

    $IPT -I INPUT -s $host -p tcp --dport 32900 -j ACCEPT

    $IPT -I INPUT -s $host -p tcp -dport 33000 -j ACCEPT

    $IPT -I INPUT -s $host -p tcp --dport 33100 -j ACCEPT

    Конечно, это только скелет, нужно будет добавить еще много правил: хотя бы разрешить применение SSH и установить некоторые параметры ядра с помощью /prос.

    Туннелирование NFS через SSH .

    Аббревиатура NFS иногда расшифровывается как «No File Security» - данные три слова говорят сами за себя. Поэтому очень важно обеспечить защиту NFS-трафика. Это легко сделать с помощью ssh.

    Начально можно изменить файл /etc/exports на NFS-сервере так, чтобы файловые системы экспортировались локальному узлу:

    Затем надо применять SSH для форвардинга портов NFS и mountd. NFS использует порт 2049/udp, a mountd, как было указано, порт с номером 33000:

    # ssh [email protected] -L 200: localhost:2049 -f sleep 120m

    # ssh [email protected] -L 200: localhost:33000 -f sleep 120m

    Данные две команды предоставляют пользователю интерактивную оболочку, но, так как она не нужна, SSH выполняет команду sleep 120: возвращаемся обратно в командную строку, но форвардинг портов будет длиться еще 2 часа.

    Монтирование файловой системы со стороны клиента выглядит очень необычно:

    mount -t nfs -о nosuid port=200 mountport=210 nfsserver.test.net:/home/user /mnt/another

    Если трюки с ssh-тунпелированием слишком сложны, можно применять проект SHFS (Shell Filesystem) (http: //shfs.sourceforge.net/ ), который дает возможность автоматизировать всю эту процедуру.

    После установки получить доступ к SHFS надо или с помощью команды mount -t shfs, или с помощью новой команду shfsmount. Синтаксис данной команды похож на предыдущий:

    shfsmount [email protected]:/home/user /mnt/user

    CFS и TCFS

    Криптографическая файловая система (Cryptographic File System) использует прозрачное кодирование и дешифрование NFS-трафика с помощью алгоритма DES. Кроме данного, она поддерживает автоматическое управление ключами, что делает процесс максимально «прозрачным» для пользователя.

    Хотя CFS разработана для SunOS и BSD, она порядком интересна, потому что представляется первой попыткой «прозрачного» кодирования общих файлов. Прозрачная криптографическая файловая система (Transparent Cryptographic File System, TCFS) предоставляет еще более прозрачный способ кодирования NFS-трафика.

    Кроме кодирования данных, данная файловая система поддерживает проверку целостности данных.

    NFS (Network File System) — сетевой протокол доступа к доступ к файлам и файловой системе NFS-сервера, популярный в семейства ОС Linux/ UNIX, а также различных системах хранения. Microsoft также, не желая отставать от конкурентов, внедрила базовый функционал NFS сервера еще в Windows Server 2003 R2. В последующих версиях серверных платформ Microsoft возможности встроенного NFS Windows сервера расширялись, появлялся новый функционал и средства управления. NFS сервер в Windows Server 2012 – очередная веха в развитии данной технологии.

    Что же нового предлагают нам разработчики Microsoft в данном продукте? Новые возможности NFS сервера в Windows Server 2012:

    1. Поддержка стандарта NFS v4.1 . Поддержка последней версии NFS 4.1 – одно из основных новшеств Windows Server 2012. По сравнению с NFS v3 этот протокол обеспечивает повышенную безопасность, производительность и совместимость, полностью реализуя все аспекты RFC 5661.
    2. Производительность «из коробки». Благодаря использованию новой транспортной инфраструктуры RPC-XDR, оптимальная производительность NFS сервера может быть достигнута сразу «из коробки» без необходимости тонкой настройки параметров системы. Оптимальная производительность достигается за счет автоматически настраивающегося кэша, разделения рабочих процессов на пулы и динамическое управление пулами, основанное на их нагрузке.
    3. Упрощенное развертывание и управление . Данный факт достигнут за счет:
      • — более 40 командлетов PowerShell для настройки сервера NFS и управления общими папками
      • — простого графического интерфейса управления, позволяющего одновременно управлять как SMB, так и NFS шарами, а также настройками скрининга файлов и .
      • — фиксации RPC порта (порт 2049) для простоты настройки файерволов
      • — нового провайдера WMI v2
      • — упрощенной идентификации за счет плоского файла мапинга
    4. Улучшения в NFSv3 . За счет быстрой отправки клиентам уведомлений о сбоях монитором NSM (Network Status Monitor), старые NFS клиенты лучше и быстрее обрабатывают процедуру failover, что означает меньшее время простоя.

    Итак, NFS сервер в Windows Server 2012 значительно улучшен с точки зрения простоты развертывания, масштабируемость, стабильность, доступность, надежность, безопасности и совместимости. Общие папки могут быть одновременно доступны по протоколам SMB и NFS, что означает возможность использования Windows Server 2012 в качестве хранилища в гетерогенных сетях.

    NFS сервер в Windows Server 2012 можно установить с помощью GUI и Powershell. Чтобы установить NFS сервер с помощью графического интерфейса, откройте и внутри роли файлового сервера (File and Storage Services) отметьте компонент Server for NFS .

    После окончания установки компонента NFS, сервер необходимо перезагрузить.

    Установка этой же роли с помощью Powershell также не вызывает затруднений, просто выполните команду:

    Add-WindowsFeature "FS-NFS-Service"

    Настройка общей папки NFS в Windows Server 2012

    Далее мы покажем, как с помощью установленной нами роли создать NFS шару (общую папку) на сервере Windows. Создать NFS шару можно опять несколькими способами: с помощью графического интерфейса или Powershell.

    Создание общего каталога NFS с помощью консоли Server Manager

    Откройте консоль Server Manager , перейдите в раздел Share management (находится внутри роли File and Storage Services ).
    В контекстном меню запустите мастер создания нового общего каталога- New Share…

    Выберите тип шары NFS Share — Quick

    Затем необходимо задать тип аутентификации NFS клиентов: возможно, задействовать как Kerberos- аутентификацию, так и анонимную.

    Предположим, в качестве потребителя создаваемого NFS ресурса будет выступать сервер виртуализации ESXi, в котором возможность аутентифицировать NFS соединения отсутствует (ESXi не поддерживает NFSv4). Поэтому тип аутентификации будет No Server Authentication , отметим также опции Enable unmapped user access и Allow unmapped user access by UID/GID .

    Чтобы немного обезопасить создаваемую NFS шару от доступа сторонних лиц, ограничим доступ к NFS ресурсу по IP адресу клиента.

    Host: 192.168.1.100
    Language Encoding : BIG5
    Share Permissions : Read/Write
    Allow root access : Yes

    Далее осталось проверить, что на уровне NTFS пользователь, в которого мапится подключающийся юзер, имеет доступ на чтение/запись (если решено задействовать анонимный доступ, придется для пользователя Everyone дать полные r/w права на уровне NTFS).

    Как создать NFS шару с помощью Powershell

    Создадим новую NFS шару:

    New-NfsShare -Name "NFS " -Path "d:\shares\nfr" -AllowRootAccess $true -Permission Readwrite -Authentication sys

    Разрешим доступ к шаре для IP адреса 192.168.1.100 и зададим кодировку BIG5 (возможность просмотра содержимого NFS шары для клиента ESXi).

    Grant-NfsSharePermission -Name “NFS” -ClientName 192.168.1.100 -ClientType host -LanguageEncoding BIG5

    Созданную NFS шару можно использовать, например, как NFS-datastore в среде виртуализации , или для доступа к данным с других Unix-like клиентов. Как смонтировать NFS шару в Windows — клиентах описано в статье.

    Для раздачи файлов внутри локальной сети можно выделить такие технологии (рассматриваются системы на базе Linux):

    • Network File System (NFS) - протокол сетевого доступа к файловым системам;
    • Files transferred over Shell protocol (FISH) - сетевой протокол, который использует или RSH для передачи файлов между компьютерами;
    • Secure SHell FileSystem (SSHFS) - клиент файловой системы для монтирования дисковых устройств на удаленных системах, для взаимодействия с удаленной системой используется SFTP ;
    • Samba - пакет программ, которые позволяют обращаться к сетевым дискам и принтерам на различных операционных системах по протоколу SMB/CIFS;

    В данной заметке речь пойдет про NFS .

    NFS (Network File System) полезна когда нужно раздать файлы/директории всем внутри сети. Прозрачность доступа с помощью NFS позволяет клиентам подключить удаленную файловую систему как локальную директорию, причем файловые системы могут быть разных типов. Это означает, что любое приложение клиента, которое может работать с локальным файлом, с таким же успехом может работать и с файлом подключенным по NFS , без каких либо модификаций самой программы.

    К преимуществам NFS можно отнести:

  • уменьшение нагрузки на процессор;
  • отображение совместно используемых ресурсов как обычных директорий в системе;
  • На данный момент доступна NFS v4.1 , в которой ввели новую возможность pNFS позволяющей распараллелить реализацию общего доступа к файлам. Также есть расширение для NFS 2 и 3 - WebNFS , которое позволяют легче интегрироваться в веб-браузеры и дает возможность работать через брандмауэр.

    Схема работы NFS протокола.

    Установка и настройка NFS-сервер под Linux

    Проверим поддерживает ли система NFS

    Cat /proc/filesystems | grep nfs

    Под Arch Linux сервер и клиент находиться в одном пакете

    Yaourt -S nfs-utils

    Для установки сервера (nfs-kernel-server ) и клиента (nfs-common ) под Ubuntu необходимы пакеты

    Sudo apt-get install nfs-kernel-server nfs-common portmap

    Дальше в заметке для сервера будет использоваться IP 192.168.1.100 . Для того что бы за сервером всегда был закреплен один и тот же IP необходимо в DHCP-сервере (чаще всего роутер) указать раздачу конкретного IP конкретному MAC-адресу. Или поднять свой локальный DNS-сервер. Например или .

    MAC-адрес можно узнать с помощью ifconfig (поле ether в Arch Linux ).

    NFSv4 предполагает что есть корневая директория, внутри которой уже расположены файлы для раздачи. Например, /srv/nfs - корень, /srv/nfs/audio - директория для раздачи музыки. Если не следовать этому новому указанию в версии 4 , то можно получить ошибку при подключении клиентом:

    Mount.nfs: access denied by server while mounting 192.168.1.100:/home/proft/torrents

    Если все же хочется использовать на сервере подход без корневой-директории для NFS , то при монтировании клиентом надо явно указать версию 3

    # для команды mount mount -o "vers=3" 192.168.1.100:/home/proft/torrents /home/proft/nfs/torrents # для fstab 192.168.1.100:/home/proft/torrents /home/proft/nfs/torrents nfs soft,nfsvers=3 0 0

    Я буду использовать NFSv4 с root-директорией в /srv/nfs/ и монтированием вложенных директорий с помощью mount --bind .

    Предположим, что мы хотим

    • раздавать директорию ~/torrents с rw доступом для всех внутри локальной сети;
    • раздавать директорию ~/photos с ro доступом для хоста с IP 192.168.1.101 ;

    Для начала создадим корневую директорию и необходимые вложенные.

    Sudo mkdir -p /srv/nfs/{torrents,photos}

    Примонтируем существующие директории torrents, photos в /srv/nfs .

    # sudo vim /etc/fstab /home/proft/torrents /srv/nfs/torrents none bind 0 0 /home/proft/photos /srv/nfs/photos none bind 0 0

    Отредактируем /etc/exports , в котором описываются все директории для совместного доступа

    # sudo vim /etc/exports # формат файла: directory allowed-hosts(options) /srv/nfs/torrents 192.168.1.1/24(rw,async) /srv/nfs/photos 192.168.1.101(ro,async)

    Обратите внимание на отсутствие пробела между allowed-hosts и (options) . Наличие пробела вводит другую трактовку правил.

    Доступные опции:

    • ro (rw) - разрешить доступ только на чтение (чтение/запись);
    • subtree_check (no_subtree_check) - в некоторых случаях приходится экспортировать не весь раздел, а лишь его часть. При этом сервер NFS должен выполнять дополнительную проверку обращений клиентов, чтобы убедиться в том, что они предпринимают попытку доступа лишь к файлам, находящимся в соответствующих подкаталогах. Такой контроль поддерева (subtree checks ) несколько замедляет взаимодействие с клиентами, но если отказаться от него, могут возникнуть проблемы с безопасностью системы. Отменить контроль поддерева можно с помощью опции no_subtree_check . Опция subtree_check , включающая такой контроль, предполагается по умолчанию. Контроль поддерева можно не выполнять в том случае, если экспортируемый каталог совпадает с разделом диска;
    • sync (async) - указывает, что сервер должен отвечать на запросы только после записи на диск изменений, выполненных этими запросами. Опция async указывает серверу не ждать записи информации на диск, что повышает производительность, но понижает надежность, т.к. в случае обрыва соединения или отказа оборудования возможна потеря данных;
    • noaccess - запрещает доступ к указанной директории. Может быть полезной, если перед этим был задан доступ всем пользователям сети к определенной директории, и теперь хотите ограничить доступ в поддиректории лишь некоторым пользователям;
    • no_root_squash – по умолчанию пользователь root на клиентской машине не будет обладать теми же правами к директории на сервера. Эта опция снимает это ограничение;
    • nohide - NFS автоматически не показывает нелокальные ресурсы (например, примонтированые с помощью mount --bind), эта опция включает отображение таких ресурсов;
    • insecure - использование непривилегированных портов (> 1024);

    Запускаем NFS-сервер

    # под archlinux sudo systemctl start rpc-idmapd.service rpc-mountd.service # под ubuntu sudo /etc/init.d/nfs-kernel-server start

    В дальнейшем при изменении конфигурационного файла достаточно его перечитать командой:

    Sudo exportfs -rav

    Команда rpcinfo -p | grep nfs позволяет проверить успешность запуска сервера.

    Клиент под Linux

    Установка

    # под archlinux yaourt -S nfs-utils # под ubuntu sudo apt-get install portmap nfs-common

    Создадим директории для монтирования сетевых ресурсов torrents и photos

    Mkdir -p ~/nfs/{torrents,photos}

    Для ручного монтирования выполним

    Sudo mount -t nfs -o rw,soft 192.168.1.100:/srv/nfs/torrents /home/proft/nfs/torrents sudo mount -t nfs -o rw,soft 192.168.1.100:/srv/nfs/photos /home/proft/nfs/photos

    Опция soft указывает тихо отменить попытки подключить шару после определенного количества времени (время задается опцией retrans ). Подробнее в man nfs .

    Данный способ не очень удобен, так как каждый раз после перезагрузки придется выполнять эти команды. Сделаем монтирование автоматическим.

    Для автоматического монтирования редактируем файл /etc/fstab

    # sudo vim /etc/fstab 192.168.1.100:/srv/nfs/torrents /home/proft/net/torrents nfs rw,soft 0 0 192.168.1.100:/srv/nfs/photos /home/proft/net/photos nfs ro,soft 0 0

    Но и у этого способа есть свои недостатки, например, если сервер не доступен то загрузка клиента может подвиснуть из-за попыток подключиться к NFS-серверу. Для исправления этого см. ниже про AutoFS .

    AutoFS - автоматическое подключение сетевых ресурсов

    Есть возможность монтировать удаленный ресурс с помощью AutoFS при первом обращении и автоматически отмонтировать при отсутствии активности.

    AutoFS использует для настройки шаблоны, расположенные в /etc/autofs . Основной шаблон называется auto.master , он может указывать на один или несколько других шаблонов для конкретных типов носителей.

    Установка

    # под archlinux yaourt -S autofs # под ubuntu sudo apt-get install autofs

    Существует несколько способов указать способы автомонтирования. Я использую такой: в /home/proft/nfs автоматически создается директория с именем NFS-сервера, в которой автоматически создаются доступные директории на сервере.

    # sudo vim /etc/autofs/auto.master /home/proft/nfs /etc/autofs/auto.nfs --timeout=60

    Дополнительный параметр timeout устанавливает количество секунд после которых устройство будет размонтировано. Параметр ghost указывает что сконфигурированные ресурсы будут отображаться всегда, а не только тогда, когда они доступны (эта опция включена по умолчанию в AutoFS 5 )

    Опишем в /etc/autofs/auto.nfs NFS-сервер и root-директорию.

    # sudo vim /etc/autofs/auto.nfs nfsserver 192.168.1.100:/srv/nfs

    Теперь при первом обращении /home/proft/nfs/torrents произойдет автоматическое монтирование NFS-ресурса.

    Перезапустим службу autofs:

    # под archlinux sudo systemctl restart autofs # под ubuntu sudo /etc/init.d/autofs restart

    Еще можно указать время ожидания доступности NFS-ресурса. Для этого необходимо изменить значения MOUNT_WAIT .

    # под archlinux # sudo vim /etc/conf.d/autofs MOUNT_WAIT=5 # под ubuntu sudo /etc/default/autofs MOUNT_WAIT=5

    Форсирование использования NFS v3

    В некоторых случаях NFSv4 может работать медленно. Для исправления этого можно принудительно указать использовать третью версию.



    © 2024 beasthackerz.ru - Браузеры. Аудио. Жесткий диск. Программы. Локальная сеть. Windows