Примечание: практика показывает, что раздел настройки Kerberos можно пропустить. Похоже, что Samba сама настроит конфиг Kerberos. Достаточно чтобы стоял пакет krb5-user .

В ведение

Зачастую возникает необходимость ввести Linux-машину в существующий домен Windows. Например, чтобы сделать файловый сервер с помощью Samba. Сделать это очень просто, для этого вам понадобятся клиент Kerberos, Samba и Winbind.

Перед установкой желательно обновиться:

sudo aptitude update

sudo aptitude upgrade

Установить всё это добро можно командой:

sudo aptitude install krb5-user samba winbind

Также может понадобиться установить следующие библиотеки:

sudo aptitude install libpam-krb5 libpam-winbind libnss-winbind

Либо, если вы используете Ubuntu Desktop, те же пакеты можно поставить через менеджер пакетов Synaptic.

Далее вам потребуется настроить все вышеперечисленные инструменты для работы с вашим доменом. Допустим, вы хотите войти в домен DOMAIN.COM , доменконтроллером которого является сервер dc.domain.com с IP адресом 192.168.0.1 . Этот же сервер является и первичным DNS сервером домена. Кроме того допустим у вас есть второй доменконтроллер 1 ) , он же DNS - dc2.domain.com с IP 192.168.0.2 . Ваш же компьютер будет называться smbsrv01 .

Н астройка DNS

Для начала необходимо изменить настройки DNS на вашей машине, прописав в качестве DNS сервера доменконтроллер 2 ) и в качестве домена поиска - нужный домен.

Если у вас статический IP-адрес, то в Ubuntu Desktop это можно сделать через Network Manager , в Ubuntu Server необходимо изменить содержимое файла /etc/resolv.conf на примерно такое:

domain domain.com

search domain.com

nameserver 192.168.0.1

nameserver 192.168.0.2

В современных дистрибутивах файл resolv.conf создается автоматически и править вручную его не нужно. Для получение нужного результата нужно добавить необходимые изменения в файл: /etc/resolvconf/resolv.conf.d/head Данные которые будут добавлены в него, будут автоматически вставлены в файл /etc/resolv.conf

Если IP-адрес динамический и присваивается DHCP сервером то после перезагрузки resolv.conf может формироваться «неправильный» resolv.conf" , например присутствует только один nameserver 192.168.0.1 и не указаны domain и search. Нужно отредактировать /etc/dhcp/dhclient.conf . Чтобы появились записи domain и search нужно убрать комментарий перед строкой supersede domain-name, и вписать свой домен:

supersede domain-name "domain.com";

Чтобы добавить еще один nameserver нужно убрать комментарий перед prepend domain-name-servers и указать ip сервера:

prepend domain-name-servers 192.168.0.2;

Для применения изменений остается перезапустить службу:

/etc/init.d/networking restart

Теперь убедитесь, что вы задали нужное имя компьютера в файле /etc/hostname :

smbsrv01

Кроме того необходимо отредактировать файл /etc/hosts так, чтобы в нём была запись с полным доменным именем компьютера и обязательно коротким именем хоста, ссылающаяся на один из внутренних IP:

# Имена этого компьютера

127.0.0.1 localhost

127.0.1.1 smbsrv01.domain.com smbsrv01

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

ping dc

ping dc.domain.com

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

Н астройка синхронизации времени

Далее необходимо настроить синхронизацию времени с доменконтроллером. Если разница будет более 5 минут мы не сможем получить лист от Kerberos. Для единовременной синхронизации можно воспользоваться командой:

sudo net time set dc

Если в сети существует сервер точного времени, то можно воспользоваться им или любым публичным:

ntpdate ntp.mobatime.ru

Автоматическая же синхронизация настраивается с помощью ntpd , это демон будет периодически выполнять синхронизацию. Для начала его необходимо установить:

sudo aptitude install ntp

Теперь исправьте файл /etc/ntp.conf , добавив в него информацию о вашем сервере времени:

# You do need to talk to an NTP server or two (or three).

server dc.domain.com

После чего перезапустите демон ntpd :

sudo /etc/init.d/ntp restart

Теперь пора настраивать непосредственно взаимодействие с доменом.

Default_realm = DOMAIN.COM

Kdc_timesync = 1

Ccache_type = 4

Forwardable = true

Proxiable = true

V4_instance_resolve = false

V4_name_convert = {

Host = {

Rcmd = host

Ftp = ftp

Plain = {

Something = something-else

Fcc-mit-ticketflags = true

DOMAIN.COM = {

Kdc = dc

Kdc = dc2

Admin_server = dc

Default_domain = DOMAIN.COM

Domain.com = DOMAIN.COM

Domain.com = DOMAIN.COM

Krb4_convert = false

Krb4_get_tickets = false

Вам, конечно, нужно изменить domain.com на ваш домен и dc и dc2 на ваши доменконтроллеры. Кстати, возможно вам понадобится написать полные имена доменконтроллеров dc.domain.com и dc2.domain.com . Поскольку у меня прописан домен поиска в DNS, то мне это делать не нужно.

Обратите особое внимание на регистр написания имени домена - везде, где домен написан в верхнем регистре, его обязательно нужно писать именно в верхнем регистре. Иначе волшебным образом ничего может не заработать.

Это не все возможные опции настройки Kerberos, только основные. Однако их обычно достаточно.

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

kinit [email protected]

Вместо username естественно стоит вписать имя существующего пользователя домена.

Имя домена необходимо писать заглавными буквами!

Если вы не получили никаких ошибок - значит вы настроили всё верно и домен отдаёт вам билет Kerberos. Кстати, некоторые распространённые ошибки перечислены чуть ниже.

Убедиться в том, что билет получен, можно выполнив команду

klist

Удалить все билеты (они вам вообще говоря не нужны) можно командой

kdestroy

Р аспространённые ошибки kinit

kinit(v5): Clock skew too great while getting initial credentials

Это значит, что у вашего компьютера не синхронизировано время с доменконтроллером (см. выше).

kinit(v5): Preauthentication failed while getting initial credentials

Вы ввели неверный пароль.

kinit(v5): KDC reply did not match expectations while getting initial credentials

Самая странная ошибка. Убедитесь, что имя realm в krb5.conf , а так же домен в команде kinit введены большими буквами:

DOMAIN.COM = {

# ...

kinit [email protected]

kinit(v5): Client not found in Kerberos database while getting initial credentials

Указанного пользователя не существует в домене.

Н астройка Samba и вход в домен

Для того, чтобы войти в домен, необходимо прописать правильные настройки в файле /etc/samba/smb.conf . На данном этапе вас должны интересовать только некоторые опции из секции . Ниже - пример части файла конфигурации Samba с комментариями по поводу значения важных параметров:

# Эти две опции нужно писать именно в заглавном регистре, причём workgroup без

# последней секции после точки, а realm - полное имя домена

Workgroup = DOMAIN

Realm = DOMAIN.COM

# Эти две опции отвечают как раз за авторизацию через AD

Security = ADS

Encrypt passwords = true

# Просто важные

Dns proxy = no

Socket options = TCP_NODELAY

# Если вы не хотите, чтобы самба пыталась при случае вылезти в лидеры в домене или рабочей группе,

# или даже стать доменконтроллером, то всегда прописывайте эти пять опций именно в таком виде

Domain master = no

Local master = no

Preferred master = no

Os level = 0

Domain logons = no

# Отключить поддержку принтеров

Load printers = no

Show add printer wizard = no

Printcap name = /dev/null

Disable spoolss = yes

После того, как вы отредактируете smb.conf выполните команду

testparm

Она проверит вашу конфигурацию на ошибки и выдаст суммарную сводку о нём:

# testparm

Load smb config files from /etc/samba/smb.conf

Loaded services file OK.

Server role: ROLE_DOMAIN_MEMBER

Press enter to see a dump of your service definitions

Как видно мы задали правильные параметры для того, чтобы наш компьютер стал членом домена. Теперь пора попытаться непосредственно войти в домен. Для этого введите команду:

net ads join -U username -D DOMAIN

И в случае успеха вы увидите что-то похожее на:

# net ads join -U username -D DOMAIN

Enter username"s password:

Using short domain name -- DOMAIN

Joined "SMBSRV01" to realm "domain.com"

И спользуемые параметры команды net

U username%password : Обязательный параметр, вместо username необходимо подставить имя пользователя с правами администратора домена, и указать пароль.

D DOMAIN : DOMAIN - собственно сам домен, домен можно и не указывать, но лучше всё же это всегда делать - хуже не будет.

S win_domain_controller : win_domain_controller , можно не указывать, но бывают случаи когда автоматически сервер не находит контроллер домена.

createcomputer=«OU/OU/…» : В AD часто используется OU (Organizational Unit), есть в корне домена OU = Office, в нем OU = Cabinet, чтобы сразу добавить в нужный можно указать так: sudo net ads join -U username createcomputer=«Office/Cabinet».

Если больше никаких сообщений нет - значит всё хорошо. Попробуйте попинговать свой компьютер по имени с другого члена домена, чтобы убедиться, что в домене всё прописалось так, как надо.

Так же можно набрать команду:

net ads testjoin

Если все хорошо, можно увидеть:

#net ads testjoin

Join is OK

Но иногда после сообщения о присоединении к домену выдаётся ошибка наподобие 3 ) :

DNS update failed!

Это не очень хорошо, и в этом случае рекомендуется ещё раз прочитать раздел про настройку DNS чуть выше и понять, что же вы сделали не так. После этого нужно удалить компьютер из домена и попытаться ввести его заново. Если вы твердо уверены, что всё настроили верно, а DNS всё равно не обновляется, то можно внести вручную запись для вашего компьютера на ваш DNS сервер и всё будет работать. Конечно, если нет никаких других ошибок, и вы успешно вошли в домен. Однако лучше всё же разберитесь, почему DNS не обновляется автоматически. Это может быть связано не только с вашим компьютером, но и с некорректной настройкой AD.

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

Если всё прошло без ошибок, то поздравляем, вы успешно вошли в домен! Можете заглянуть в AD и убедиться в этом. Кроме того хорошо бы проверить, что вы можете видеть ресурсы в домене. Для этого установите smbclient :

sudo aptitude install smbclient

Теперь можно просматривать ресурсы компьютеров домена. Но для этого нужно иметь билет kerberos, т.е. если мы их удалили, то получаем опять через kinit (см. выше). Посмотрим какие ресурсы предоставлены в сеть компьютером workstation :

smbclient -k -L workstation

Вы должны увидеть список общих ресурсов на этом компьютере.

Н астройка Winbind

Если вам необходимо как-либо работать с пользователями домена, например, настраивать SMB-шары с разграничением доступа, то вам понадобится кроме самой Samba ещё и Winbind - специальный демон, служащий для связи локальной системы управления пользователями и группами Linux с сервером Active Directory. Проще говоря Winbind нужен, если вы хотите видеть пользователей домена на своём компьютере с Ubuntu.

Winbind позволяет спроецировать всех пользователей и все группы AD в вашу Linux систему, присвоив им ID из заданного диапазона. Таким образом вы сможете назначать пользователей домена владельцами папок и файлов на вашем компьютере и выполнять любые другие операции, завязанные на пользователей и группы.

Для настройки Winbind используется всё тот же файл /etc/samba/smb.conf . Добавьте в секцию следующие строки:

# Опции сопоставления доменных пользователей и виртуальных пользователей в системе через Winbind.

# Диапазоны идентификаторов для виртуальных пользователей и групп.

Idmap uid = 10000 - 40000

Idmap gid = 10000 - 40000

# Эти опции не стоит выключать.

Winbind enum groups = yes

Winbind enum users = yes

# Использовать домен по умолчанию для имён пользователей. Без этой опции имена пользователей и групп

# будут использоваться с доменом, т.е. вместо username - DOMAIN\username.

# Возможно именно это вам и нужно, однако обычно проще этот параметр включить.

Winbind use default domain = yes

# Если вы хотите разрещить использовать командную строку для пользователей домена, то

# добавьте следующую строку, иначе в качестве shell"а будет вызываться /bin/false

Template shell = /bin/bash

# Для автоматического обновления билета Kerberos модулем pam_winbind.so нужно добавить строчку

Winbind refresh tickets = yes

Параметры:

idmap uid = 10000 - 40000

idmap gid = 10000 - 40000

в новых версиях Samba уже устарели и при проверке конфига самбы с помощью testparm будет выдваться предупреждение:

WARNING: The «idmap uid» option is deprecated

WARNING: The «idmap gid» option is deprecated

Чтобы убрать предупреждения нужно заменить эти строки на новые:

idmap config * : range = 10000-20000

idmap config * : backend = tdb

Теперь перезапустите демон Winbind и Samba в следующем порядке:

sudo /etc/init.d/winbind stop

sudo smbd restart

sudo /etc/init.d/winbind start

Запускаем

sudo testparm

Смотрим есть ли ошибки или предупреждения, если появится:

«rlimit_max: rlimit_max (1024) below minimum Windows limit (16384)»

Без перезагрузки можно устранить так:

ulimit -n 16384

Для сохранения после перезагрузки отредактировать файл /etc/security/limits.conf

# Добавить в конец файла строки:

* - nofile 16384

root - nofile 16384

После перезапуска проверьте, что Winbind установил доверительные отношения с AD командой:

# wbinfo -t

checking the trust secret for domain DCN via RPC calls succeeded

А так же, что Winbind увидел пользователей и группы из AD командами 4 ) :

wbinfo -u

wbinfo -g

Эти две команды должны выдать список пользователей и групп из домена соответственно. Либо с префиксом DOMAIN\ , либо без него - в зависимости от того, какое значение вы указали параметру «winbind use default domain» в smb.conf .

Итак, Winbind работает, однако в систему он ещё не интегрирован.

Д обавление Winbind в качестве источника пользователей и групп

Для того, чтобы ваша Ubuntu прозрачно работала с пользователями домена, в частности, чтобы вы могли назначать пользователей домена владельцами папок и файлов, необходимо указать Ubuntu использовать Winbind как дополнительный источник информации о пользователях и группах.

Для этого измените две строчки в файле /etc/nsswitch.conf :

passwd: compat

group: compat

добавив к ним в конец winbind :

passwd: compat winbind

group: compat winbind

files: dns mdns4_minimal mdns4

ubuntu server 14.04, файл /etc/nsswitch.conf не содержал строку «files: dns mdns4_minimal mdns4» вместо неё было: «hosts: files mdns4_minimal dns wins» Которую я преобразовал в: «hosts: dns mdns4_minimal mdns4 files» после чего всё заработало

Теперь проверьте, что Ubuntu запрашивает у Winbind информацию о пользователях и группах, выполнив

getent passwd

getent group

Первая команда должна вам вернуть всё содержимое вашего файла /etc/passwd , то есть ваших локальных пользователей, плюс пользователей домена с ID из заданного вами в smb.conf диапазона. Вторая должна сделать тоже самое для групп.

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

А вторизация в Ubuntu через пользователей домена

Несмотря на то, что все пользователи домена фактически стали полноценными пользователями системы (в чём можно убедиться, выполнив последние две команды из предыдущего раздела), зайти ни под кем из них в систему всё ещё нельзя. Для включения возможности авторизации пользователей домена на компьютере с Ubuntu необходимо настроить PAM на работу с Winbind.

Для Ubuntu 10.04 и выше добавьте всего одну строку в файле /etc/pam.d/common-session , т.к. PAM и так неплохо справляется с авторизацией:

Для Ubuntu 13.10 чтобы появилось поле ручного ввода логина необходимо в любой файл из папки /etc/lightdm/lightdm.conf/ снизу добавить строку:

greeter-show-manual-login=true

Для Ubuntu 9.10 и ниже придется редактировать несколько файлов (но никто не запрещает использовать этот способ и в 10.04 - он тоже работает):

Последовательность строк в файлах имеет значение!

/etc/pam.d/common-auth

auth required pam_env.so

auth sufficient pam_unix.so likeauth nullok try_first_pass

auth sufficient pam_winbind.so use_first_pass krb5_auth krb5_ccache_type=FILE

auth required pam_deny.so

/etc/pam.d/common-account

account sufficient pam_winbind.so

account required pam_unix.so

/etc/pam.d/common-session

session optional pam_mkhomedir.so skel=/etc/skel/ umask=0077

session optional pam_ck_connector.so nox11

session required pam_limits.so

session required pam_env.so

session required pam_unix.so

/etc/pam.d/common-password

password sufficient pam_unix.so try_first_pass use_authtok nullok sha512 shadow

password sufficient pam_winbind.so

password required pam_deny.so

И, наконец, необходимо перенести запуск Winbind при загрузке системы после всех остальных служб (по умолчанию он запускается с индексом 20). Для этого в терминале выполните следующую команду:

sudo bash -c "for i in 2 3 4 5; do mv /etc/rc$i.d/S20winbind /etc/rc$i.d/S99winbind; done"

Что эквивалентно запуску для каждого уровня (в примере - 4) команды:

mv /etc/rc4.d/S20winbind /etc/rc4.d/S99winbind

В некоторых случаях winbind может иметь иной уровень запуска (например, S02winbind). Поэтому сначала проверьте имена файлов, вполнив команду «ls /etc/rc{2,3,4,5}.d/ | grep winbind» (без кавычек).

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

Часто возникает ситуация, когда домен-контроллер недоступен по различным причинам - профилактика, отключение света или вы принесли ноутбук домой и хотите поработать. В этом случае для Winbind можно настроить кэширование учетных записей пользователей домена. Для этого необходимо сделать следующее. Добавьте в секцию файла /etc/samba/smb.conf следующие строки:

Winbind offline logon = yes

# Период кэширования учетных записей, по умолчанию равен 300 секунд

Winbind cache time = 300

# Необязательная настройка, но избавляет от нудных пауз, указываем контроллер домена dc,

# можно указать и ip, но это является плохим тоном

Password server = dc

Обычно этого достаточно. Если же возникают ошибки, то необходимо создать файл /etc/security/pam_winbind.conf со следующим содержанием 5 ) :

Внимание! При использовании советов ниже может возникать совершенно случайная ошибка «Сбой аутентификации»! Поэтому все что Вы делаете, Вы делаете на свой страх и риск!

# pam_winbind configuration file

# /etc/security/pam_winbind.conf

# turn on debugging

Debug = no

# request a cached login if possible

# (needs "winbind offline logon = yes" in smb.conf)

Cached_login = yes

# authenticate using kerberos

Krb5_auth = yes

# when using kerberos, request a "FILE" krb5 credential cache type

# (leave empty to just do krb5 authentication but not have a ticket

# afterwards)

Krb5_ccache_type = FILE

# make successful authentication dependend on membership of one SID

# (can also take a name)

;require_membership_of =

Silent = yes

Файл /etc/pam.d/gnome-screensaver в таком случае принимает вид:

auth sufficient pam_unix.so nullok_secure

auth required pam_deny.so

А также изменяется файл /etc/pam.d/common-auth :

auth optional pam_group.so

auth sufficient pam_unix.so nullok_secure use_first_pass

auth sufficient pam_winbind.so use_first_pass

auth required pam_deny.so

Если вывод в (графическую) консоль не очень объёмный, можно просто выдельть мышкой кусок и вставить его в сообщение щелчком средней кнопки. В противном случае можно использовать перенаправление вывода в файл через "воронку", например так:

Some_command parameters > logfile.txt

Чтобы видеть результат выполнения на экране, и одновременно писать в файл, можно воспользоваться командой tee :

Some_command parameters | tee -a logfile.txt

Команда setterm -dump создает "слепок" буфера текущей виртуальной консоли в виде простого текстового файла с именем по умолчанию - screen.dump. В качестве ее аргумента можно использовать номер консоли, для которой требуется сделать дамп. А добавление опции -file имя_файла перенаправит этот дамп в файл с указанным именем. Опция же -append присоединит новый дамп к уже существующему файлу - "умолчальному" screen.dump или поименованному опцией -file .

Т.е. после использования команды, например

Setterm -dump -file /root/screenlog

соответственно в файле /root/screenlog будет содержимое одной страницы консоли.

Нашёл еще одно решение для копирования/вставки текста в текстовой консоли без мыши. Также можно копировать текст из буфера прокрутки (т.е. всё что на экране и выше за экраном). Чтобы лучше разобраться, читайте о консольном менеджере окон screen . Также может пригодиться увеличить размер буфера прокрутки.

1) Запускаем screen

2) Нажимаем Enter. Всё. Мы находимся в нулевом окне консоли.

3) Выполняем нужные команды, вывод которых необходимо скопировать.

4) Ctrl+A, Ctrl+[ - мы в режиме копирования. Ставим курсор на начало выделения, жмём пробел, потом ставим курсор на конец выделения, жмём пробел. Текст скопирован в буфер.

5) Ctrl+A, с - мы создали новое 1-е окно.

6) Ctrl+A, 1 - мы перешли на 1-е окно.

7) Открываем любой (?) текстовый редактор (я пробовал в mc), и жмём Ctrl+A, Ctrl+] - текст вставлен. Сохраняем.

8) Ctrl+A, Ctrl+0 - вернуться обратно в нулевое окно.

Как увеличить буфер обратной прокрутки?

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

И такое средство есть, а называется оно framebuffer console , для краткости fbcon . Это устройство имеет файл документации fbcon.txt ; если вы устанавливали документацию к ядру, то он у вас есть. Выискивайте его где-то в районе /usr/share ветви (я не могу указать точный путь из-за разницы в дистрибутивах).

На этом месте прошу прощения: мы должны сделать небольшое отступление и немного поговорить о видеобуфере (framebuffer ).

Видеобуфер - это буфер между дисплеем и видеоадаптером. Его прелесть в том, что им можно манипулировать: он позволяет трюки, которые не прошли бы, будь адаптер связан напрямую с дисплеем.

Один из таких трюков связан с буфером прокрутки; оказывается, вы можете "попросить" видеобуфер выделить больше памяти буферу прокрутки. Достигается это через загрузочные параметры ядра. Сначала вы требуете framebuffer (видеобуфер); Затем запрашиваете больший буфер прокрутки.

Нижеследующий пример касается GRUB , но может быть легко адаптирован к LILO . В файле настройки GRUB - menu.lst - найдите соответствующую ядру строчку, и затем: Удалите опцию vga=xxx , если таковая присутствует. Добавьте опцию video=vesabf или то, что соответствует вашему "железу". Добавьте опцию fbcon=scrollback:128 . После этой процедуры, строка параметров ядра должна выглядеть приблизительно так:

Kernel /vmlinuz root=/dev/sdb5 video=radeonfb fbcon=scrollback:128

Спрашивается, зачем удалять опцию vga=xxx ? Из-за возможных конфликтов с видео-опцией. На своем ATI адаптере, я не могу изменить буфер прокрутки, если vga=xxx присутствует в списке. Возможно в вашем случае это не так. Если вышеперечисленные опции работают - хорошо; но что, если вы хотите увеличить число строк, или установить более мелкий шрифт на экране? Вы всегда делали это при помощи опции vga=xxx - а она-то и исчезла. Не переживайте - то же самое может быть достигнуто изменением параметров fbcon, как описано в файле fbcon.txt (но не описано в данной статье).

С опцией fbcon=scrollback:128 у меня буфер прокрутки увеличился до 17 экранов (35 раз Shift+PgUp по полэкрана). Кстати, 128 - это килобайт. Автор статьи утверждает, что больше установить нельзя. Я и не пробовал.

Можно заюзать script .

Script filename.log

когда все нужные команды выполнены -

Все записано в filename.log

В FreeBSD есть замечательная утилита watch, которая позволяет мониторить терминалы, но как оказалось, в Linux она выполняет совсем иные функции =\ Стоит погуглить на эту тему, чего-нть да найдется...

Для того, чтобы записать данные в файл или прочитать их оттуда, процессу необходимо сначала открыть этот файл (при открытии на запись, возможно, придётся предварительно создать его). При этом процесс получает дескриптор (описатель) открытого файла - уникальное для этого процесса число, которое он и будет использовать во всех операциях записи. Первый открытый файл получит дескриптор, второй - 1 и так далее. Закончив работу с файлом, процесс закрывает его, при этом дескриптор освобождается и может быть использован повторно. Если процесс завершается, не закрыв файлы, за него это делает система. Строго говоря, только в операции открытия дескриптора указывается, какой именно файл будет использоваться. В качестве «файла» используются и обычные файлы, и файлы-дырки (чаще всего - терминалы), и каналы , описанные в разделе Pipeline..Конвейер. Дальнейшие операции - чтение, запись и закрытие, работают с дескриптором, как с потоком данных , а куда именно ведёт этот поток, неважно.

Каждый процесс Linux получает при старте три «файла», открытых для него системой. Первый из них (дескриптор) открыт на чтение , это стандартный ввод процесса. Именно со стандартным вводом работают все операции чтения, если в них не указан дескриптор файла. Второй (дескриптор 1) - открыт на запись, это стандартный вывод процесса. С ним работают все операции записи, если дескриптор файла не указан в них явно. Наконец, третий поток данных (дескриптор 2) предназначается для вывода диагностических сообщений, он называется стандартный вывод ошибок . Поскольку эти три дескриптора уже открыты к моменту запуска процесса, первый файл, открытый самим процессом, будет, скорее всего, иметь дескриптор 3 .

Дескриптор Описатель потока данных, открытого процессом. Дескрипторы нумеруются начиная с. При открытии нового потока данных его дескриптор получает наименьший из неиспользуемых в этот момент номеров. Три заранее открытых дескриптора: стандартный ввод (), стандартный вывод (1) и стандартный вывод ошибок (2) процессу выдаются при запуске.

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

Стандартный вывод

Мефодий уже сталкивался с тем, что некоторые программы умеют выводить не только на терминал, но и в файл, например, info при указании параметрического ключа « -o » с именем файла выведет текст руководства в файл, вместо того, чтобы отображать его на мониторе. Даже если разработчиками программы не предусмотрен такой ключ, Мефодию известен и другой способ сохранить вывод программы в файле вместо того, чтобы выводить его на монитор: поставить знак « > » и указать после него имя файла. Таким образом Мефодий уже создавал короткие текстовые файлы (сценарии) при помощи утилиты cat (см. лекцию Доступ процессов к файлам и каталогам).

$ cat > textfile Это файл для примеров. ^D $ ls -l textfile -rw-r--r-- 1 methody methody 23 Ноя 15 16:06 textfile

Пример 2 . Перенаправление стандартного вывода в файл

От использования символа « > » возможности самой утилиты cat , конечно, не расширились. Более того, cat в этом примере не получила от командной оболочки никаких параметров: ни знака « > », ни последующего имени файла. В этом случае cat работала как обычно, не зная (и даже не интересуясь!), куда попадут выведенные данные: на экран монитора, в файл или куда-нибудь ещё. Вместо того, чтобы самой обеспечивать доставку вывода до конечного адресата (будь то человек или файл), cat отправляет все данные на стандартный вывод (сокращённо - stdout).

Подмена стандартного вывода - задача командной оболочки (shell). В данном примере shell создаёт пустой файл, имя которого указано после знака « > », и дескриптор этого файла передаётся программе cat под номером 1 (стандартный вывод ). Делается это очень просто. В лекции Доступ процессов к файлам и каталогам было рассказано о том, как запускаются команды из оболочки. В частности, после выполнения fork() появляется два одинаковых процесса, один из которых - дочерний - должен запустить вместо себя команду (выполнить exec()). Так вот, перед этим он закрывает стандартный вывод (дескриптор 1 освобождается) и открывает файл (с ним связывается первый свободный дескриптор, т. е. 1), а запускаемой команде ничего знать и не надо: её стандартный вывод уже подменён. Эта операция называется перенаправлением стандартного вывода. В том случае, если файл уже существует, shell запишет его заново, полностью уничтожив всё, что в нём содержалось до этого. Поэтому Мефодию, чтобы продолжить записывать данные в textfile , потребуется другая операция - « >> ».

$ cat >> textfile Пример 1. ^D $ cat textfile Это файл для примеров. Пример 1. $

Пример 3 . Недеструктивное перенаправление стандартного вывода

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

Стандартный вывод Поток данных, открываемый системой для каждого процесса в момент его запуска, и предназначенный для данных, выводимых процессом.

Стандартный ввод

Аналогичным образом для передачи данных на вход программе может быть использован стандартный ввод (сокращённо - stdin). При работе с командной строкой стандартный ввод - это символы, вводимые пользователем с клавиатуры. Стандартный ввод можно перенаправить при помощи командной оболочки, подав на него данные из некоторого файла. Символ « < » служит для перенаправления содержимого файла на стандартный ввод программе. Например, если вызвать утилиту sort без параметра, она будет читать строки со стандартного ввода. Команда « sort < имя_файла » подаст на ввод sort данные из файла.

$ sort < textfile Пример 1. Это файл для примеров. $

Пример 4 . Перенаправление стандартного ввода из файла

Результат действия этой команды совершенно аналогичен команде sort textfile , разница в том, что когда используется « < », sort получает данные со стандартного ввода, ничего не зная о файле « textfile », откуда они поступают. Механизм работы shell в данном случае тот же, что и при перенаправлении вывода: shell читает данные из файла « textfile », запускает утилиту sort и передаёт ей на стандартный ввод содержимое файла.

Стоит помнить, что операция « > » деструктивна : она всегда создаёт файл нулевой длины. Поэтому для, допустим, сортировки данных в файле надо применять последовательно sort < файл > новый_файл и mv новый_файл файл . Команда вида команда < файл > тот_же_файл просто урежет его до нулевой длины!

Стандартный ввод Поток данных, открываемый системой для каждого процесса в момент его запуска, и предназначенный для ввода данных.

Стандартный вывод ошибок

В качестве первого примера и упражнения на перенаправление Мефодий решил записать руководство по cat в свой файл cat.info:

$ info cat > cat.info info: Запись ноды (coreutils.info.bz2)cat invocation... info: Завершено. $ head -1 cat.info File: coreutils.info, Node: cat invocation, Next: tac invocation, Up: Output of entire files $

Пример 5 . Стандартный вывод ошибок

Удивлённый Мефодий обнаружил, что вопреки его указанию отправляться в файл две строки, выведенные командой info , всё равно проникли на терминал. Очевидно, эти строки не попали на стандартный вывод потому, что не относятся непосредственно к руководству, которое должна вывести программа, они информируют пользователя о ходе выполнения работы: записи руководства в файл. Для такого рода диагностических сообщений , а также для сообщений об ошибках, возникших в ходе выполнения программы, в Linux предусмотрен стандартный вывод ошибок (сокращённо - stderr).

Стандартный вывод ошибок Поток данных, открываемый системой для каждого процесса в момент его запуска, и предназначенный для диагностических сообщений , выводимых процессом.

Использование стандартного вывода ошибок наряду со стандартным выводом позволяет отделить собственно результат работы программы от разнообразной сопровождающей информации, например, направив их в разные файлы. Стандартный вывод ошибок может быть перенаправлен так же, как и стандартный ввод/вывод, для этого используется комбинация символов « 2 ».

$ info cat > cat.info 2> cat.stderr $ cat cat.stderr info: Запись ноды (coreutils.info.bz2)cat invocation... info: Завершено. $

Пример 6 . Перенаправление стандартного вывода ошибок

В этот раз на терминал уже ничего не попало, стандартный вывод отправился в файл cat.info , стандартный вывод ошибок - в cat.stderr . Вместо « > » и « 2 » Мефодий мог бы написать « 1> » и « 2> ». Цифры в данном случае обозначают номера дескрипторов открываемых файлов. Если некая утилита ожидает получить открытый дескриптор с номером, допустим, 4 , то чтобы её запустить обязательно потребуется использовать сочетание « 4> ».

Иногда, однако, требуется объединить стандартный вывод и страндартный вывод ошибок в одном файле, а не разделять их. В командной оболочке bash для этого имеется специальная последовательность « 2>&1 ». Это означает «направить стандартный вывод ошибок туда же, куда и стандартный вывод»:

$ info cat > cat.info 2>&1 $ head -3 cat.info info: Запись ноды (coreutils.info.bz2)cat invocation... info: Завершено. File: coreutils.info, Node: cat invocation, Next: tac invocation, Up: Output of entire files $

Пример 7 . Объединение стандартного вывода и стандартного вывода ошибок

В этом примере важен порядок перенаправлений: в командной строке Мефодий сначала указал, куда перенаправить стандартный вывод (« > cat.info ») и только потом велел направить туда же стандартный вывод ошибок. Сделай он наоборот (« 2>&1 > cat.info »), результат получился бы неожиданный: в файл попал бы только стандартный вывод, а диагностические сообщения появились бы на терминале. Однако логика здесь железная: на момент выполнения операции « 2>&1 » стандартный вывод был связан с терминалом, значит, после её выполнения стандартный вывод ошибок тоже будет связан с терминалом. А последующее перенаправление стандартного вывода в файл, конечно, никак не отразится на стандартном выводе ошибок. Номер в конструкции « &номер » - это номер открытого дескриптора. Если бы упомянутая выше утилита, записывающая в четвёртый дескриптор, была написана на shell, в ней бы использовались перенаправления вида « >&4 ». Чтобы не набирать громоздкую конструкцию « > файл 2>&1 » в bash используются сокращения: « &> файл » или, что то же самое, « >& файл ».

Перенаправление в никуда

Иногда заведомо известно, что какие-то данные, выведенные программой, не понадобятся. Например, предупреждения со стандартного вывода ошибок. В этом случае можно перенаправить стандартный вывод ошибок в файл-дырку , специально предназначенный для уничтожения данных - /dev/null . Всё, что записывается в этот файл, просто будет выброшено и нигде не сохранится .

$ info cat > cat.info 2> /dev/null $

Пример 8 . Перенаправление в /dev/null

Точно таким же образом можно избавиться и от стандартного вывода, отправив его в /dev/null .

Система ввода/вывода в LINUX .

В системе ввода/вывода все внешние устройства рассматриваются как файлы, над которыми допускается производить обычные файловые операции. Конечно, существуют и драйверы устройств, но интерфейс с ними оформлен для пользователя как обращение к специальному файлу. Специальные файлы являются средством унификации системы ввода/вывода.

Каждому подключенному устройству (терминалу, дискам, принтеру и т. д.), соответствует, как минимум, один специальный файл. Большая часть этих специальных файлов хранится в каталоге /dev:
$ cd /dev
$ ls -l
onsole пульт управления системы
dsk порции на диске
fd0 флоппи-диск 1
mem память
lр принтер
lр0 параллельный порт 0
. . .
root порция на диске для корневой файловой системы
swap своп-порция
syscon альтернативное имя пульта
systty еще одно имя для системной консоли
term директория для терминалов
ttyS0 серийный порт 0 (COM1)
. . .

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

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

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

На одном диске можно создать несколько файловых систем. Некоторые системы используют по одной файловой системе на диске, а другие - по несколько. Новую файловую систему можно создать с помощью команды mkfs (make file system). Например, выражение # /sbin/mkfs /dev/dsk/fl1 512 означает: создать на флоппи-диске b: размером в 512 блоков.

По желанию можно задать размер файловой системы в блоках и количество i-узлов (т. е. максимальное число файлов, которые могут быть сохранены в файловой системе). По умолчанию число i-узлов равно числу блоков, деленному на четыре. Максимальное число i-узлов в одной файловой системе 65 000. Если по некоторым причинам вам необходимо более 65000 i-узлов на диске, необходимо создать две или более файловые системы на этом диске.

Всякая файловая система может быть прикреплена (монтирована) к общему дереву каталогов, в любой его точке. Например, каталог / - это корневой (root) каталог системы, кроме этого, он является основанием файловой системы, которая всегда монтирована. Каталог /usr1 находится в каталоге /, но в данном случае является отдельной файловой системой от корневой файловой системы, так как все файлы в нем находятся на отдельной части диска или вообще на отдельном диске. Файловая система /usr1 - монтируемая файловая система - корень в точке, где каталог /usr1 существует в общей иерархии (рис. 1 и 2).

Рис. 1. Файловая система перед
монтированием /dev/dsk/os1

Рис. 2. Файловая система после
монтирования /dev/dsk/os1 как /usr/

Для монтирования файловой системы используется команда /sbin/mount. Эта команда разрешает расположить данную файловую систему везде в существующей структуре каталогов:
#/sbin/mount/dev/dsk/osl/usr1 монтирует /dev/dsk/osl на /usr1
#/sbin/mount/dev/dsk/flt/а монтирует /dev/dsk/flt на /а

Если нужно монтировать файловую систему на диски, которые должны быть защищены от записи, чтобы система была доступна только для чтения, необходимо добавить опцию - r к команде /sbin/mount.
Каталог, к которому прикрепляется монтируемая файловая система, должен быть в данный момент пустой, так как содержимое его будет недоступно, пока файловая система монтируется.

Чтобы получить информацию о файловых системах, которые смонтированы, например, на системе LINUX, можно использовать команду /sbin/mount без аргументов (рис. 3).

Рис. 3.

Эта команда выводит каталог, на который была смонтирована файловая система (например, usrl), устройство /dev, на котором она находится, час и дата, когда она была смонтирована. Для демонтирования файловой системы используется команда /sbin/umount, которая имеет обратное действие по отношению к команде mount. Она освобождает файловую систему и как бы вынимает ее целиком из структуры каталогов, так что все ее собственные файлы и каталоги становятся недоступны:
# /sbin/umount /b
# /sbin/umount /dev/dsk/0s2

Корневая файловая система не может быть демонтирована. Кроме того, команда umount не будет выполнена, если кто-нибудь использует файл из той файловой системы, которую пытаются демонтировать (это может быть даже простое пребывание пользователя в одном из каталогов демонтируемой файловой системы).

В командах mount и umount пользователь использует аббревиатуру физических дисковых устройств.
В LINUX дисковые устройства имеют своеобразные обозначения. В LINUX пользователь никогда не сталкивается с проблемой точного указания физического устройства, на котором располагается информация. В LINUX произвольное число внешних устройств может быть очень большим, поэтому, пользователь имеет дело только с именем каталога, в котором находятся нужные ему файлы. Все файловые системы монтируются один раз, как правило, при загрузке системы. На некоторые каталоги могут быть смонтированы файловые системы и с удаленных компьютеров.

Для физических устройств в LINUX существуют директории dsk и rdsk, которые содержат файлы, соответствующие дисковым устройствам. Обыкновенно имена файлов в этих директориях одинаковы и единственная разница между ними, что директория rdsk содержит дисковые устройства со специальным доступом (raw), который используют некоторые устройства системы для более быстрого доступа к диску. Одна типичная директория dsk содержит следующие устройства:
$ 1s /dev/dsk
0s0 1s0 c0t0d0s0 c0tld0s0 f0 f05q f13dt fld8d
0sl 1sl c0t0d0sl c0tld0sl f03d f05qt f13h fld8dt
0s2 1s2 c0t0d0s2 c0tld0s2 f03dt f0d8d f13ht fld8t
. . .
$

B системе LINUX дисковые устройства логически разделены на секции, подобно разделам определяемым в Partition Table MasterBoot MS DOS. Файлы 0s1, 0s2, 0s3 и т. д, соответствуют секциям первой, второй, третьей и т. д. диска с номером 0. Файлы 1s0, 1sl, 1s2 и т. д. соответствуют секциям первой, второй, третьей и т. д. диска с номером 1. Если система имеет больше дисков, секции будут пронумерованы ns0, nsl и т. д. для каждого диска с номером n.

Системы с большим количеством дисковых устройств используют следующую систему нумерации:
с controller d disk s section

где controller - номер контроллера диска; disk - номер диска; section -номер секции диска.
Так, 0s0 обычно эквивалентно c0t0d0s0, а 0sl - c0t0d0sl, и трехсимвольные имена секций - это просто сокращение для дискового контроллера с номером 0.

Файлы, имена которых начинаются с f, определяют различные виды гибких дисков. Каталог rmt содержит файлы на устройствах типа магнитная лента:
$ 1s /dev/rmt
c0s0 cls0 c3s0 ntape ntapel tape tapel

Файлы c0s0, cls0, c2s0 и c3s0 определяют четыре кассетных ленточных запоминающих устройства. Файлы tape и tapel определяют магнитные запоминающие устройства с двумя бобинами. Файлы, чьи имена начинаются с n, относятся к тем же устройствам, только лента не перематывается после использования, в то время как использование других файлов заставляет ленту перематываться, когда использующая ее программа заканчивает работу.

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

Файловая система extX при операциях ввода/вывода использует буферизацию данных. При считывании блока информации ядро выдает запрос операции ввода/вывода на несколько расположенных рядом блоков. Такие операции сильно ускоряют извлечение данных при последовательном считывании файлов. При занесении данных в файл файловая система extX, записывая новый блок, заранее размещает рядом до 8 смежных блоков. Такой метод позволяет размещать файлы в смежных блоках, что ускоряет их чтение и дает возможность достичь высокой производительности системы.