Linux Gazette на русском | Выпуск #5 | Тираж 1356 экз.

Автоматизация регистрации виртуальных консолей.


{

  • Автор: Брайэн Хендерсон [Bryan Henderson], [email protected]
  • Перевод: Алексей Саввин, [email protected]
  • Оригинал [eng]: http://www.linuxgazette.com/issue69/henderson.html
  • Оригинал [rus]: http://gazette.linux.ru.net/lg69/articles/rus-henderson.html
  • Номер: __#74__
}

 

После загрузки Linux на виртуальных консолях вы видите приглашение "login:" и должны на каждой из них набрать свое имя и пароль? Даже если вы -- единственный, кто работает в системе? Хорошо, попробуем это убрать. Можно сделать так, что при каждой загрузке все эти консоли уже будут зарегистрированы и на них будет приглашение командной строки.

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

Введение

Метод регистрации виртуальных консолей, который я собираюсь описать, состоит из установки программы и изменении нескольких строк в /etc/inittab. Но перед этим я возьму вас в познавательное путешествие по землям getty и login, чтобы выяснить, как же регистрируется пользователь Unix.

Во-первых, я должен пояснить, что веду речь о виртуальных консолях -- о тех текстовых консолях, которые вы обычно переключаете нажатием ALT-F2 или CTL-ALT-F2 и так далее. Оболочки (shell), которые вы видите в окошках графического десктопа, совершенно другое. Их также можно автоматически запускать при загрузке, но этот процесс совершенно другой и в этой статье не описывается.

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

Как работает регистрация

Историческая справка

В старых традиционных системах Unix-компьютер был закрыт в отдельной в комнате, а пользователи получали доступ к системе через терминалы в другой комнате. Терминалы были подключены к последовательным портам. Во время первого включения системы она печатала (до появления терминалов с ЭЛТ, действительно, печатала) некую идентификационную информацию, а затем приглашение "login:". Всякий, кто хотел воспользоваться компьютером, подходил к одному из этих терминалов, набирал свое регистрационное имя, затем свой пароль и после этого получал приглашение оболочки и становился "зарегистрированным".

Сегодня на виртуальных терминалах Linux вы видите то же самое, хотя это не ощущается, если только не думать об истории.

Getty

Давайте теперь посмотрим процесс загрузки Linux и выясним, каким образом возникает это приглашение к регистрации.

При начальной загрузке ядро Linux создает процесс init. Это первый и последний процесс, существующий в любой системе Linux. Все другие процессы в системе Linux создаются либо init'ом, либо потомком init'а.

Обычно процесс init выполняет программу с названием Sysvinit или что-то похожее. Стоит заметить, что вы, в общем-то, можете вместо init запустить любую другую программу, какую захотите, указав имя ее бинарника в параметрах загрузки Linux. По умолчанию это программа /sbin/init, которой обычно является Sysvinit. Sysvinit получает инструкции из файла /etc/inittab.

Чтобы узнать о работе init, наберите man init и man inittab.

Если вы посмотрите в /etc/inittab, то увидите инструкции, запускающие несколько процессов, выполняющих программу getty - по одному процессу на каждую виртуальную консоль. Ниже дан пример строки из /etc/inittab, которая сообщает init запустить процесс выполнения getty на виртуальной консоли /dev/tty5:

c5:235:respawn:/sbin/agetty 38400 tty5

В данном случае, реальной программой getty является /sbin/agetty. В своей системе вы можете использовать /sbin/mingetty или любую другую из множества подобных программ. (Программу любую, но лучше, если бы она имела в своем имени строку "getty". Эти программы мы называем getty потому, что самая первая называлась просто "getty", от выражения "get teletype" - "получить телетайп".)

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

Итак, теперь вы знаете, каким образом на виртуальной консоли /dev/tty5 появляется приглашение "login:". Ядро создает процесс init, выполняющий Sysvinit. Sysvinit по инструкциями в /etc/inittab запускает другой процесс, выполняющий программу getty с параметрами, задающими /dev/tty5. Программа getty печатает "login:" на /dev/tty5 и ожидает, пока кто-нибудь что-нибудь напечатает.

Регистрация (Login)

После вашего ответа на приглашение getty зарегистрироваться, getty выполняет (exec) программу login. (В общем-то, вы можете заставить getty выполнить любую программу по вашему выбору, но обычно это /bin/login); т.е. getty заменяет себя на login. Хотя это все тот же самый процесс.

Помните, этот процесс был создан init'ом, принадлежащим суперпользователю. Поэтому этот процес, теперь выполняющий login, также принадлежит суперпользователю.

Первое, что делает login - запрашивает ваш пароль. После того, как вы его введете, login проверяет его правильность. Убедившись, что это так, login переходит к выполнению следующих задач:

  • Заменяет идентификатор владельца процесса на ваш.
  • Заменяет идентификатор группы процесса на вашу группу.
  • Помещает запись в базу данных пользовательских счетов (файл "utmp"), показывая, что вы зарегистрировались. Технически эта база данных сегодня не нужна, но все еще используется старыми программами, такими как who, чтобы сообщать об имени и терминалах зарегистрированных пользователей.
  • Заменяет дополнительные группы процесса на все группы, к которым вы принадлежите.
  • Устанавливает ваш домашний каталог текущим рабочим каталогом процесса.
  • Делает вас владельцем устройства терминала и соответственно устанавливает его атрибуты доступа (permissions).

Следующее, что делает login, - запускает (exec) вашу оболочку shell (которая, в общем-то, может быть любой программой, но обычно является командной оболочкой, например, /bin/bash). Т.е. он заменяет себя на программу оболочки shell.

Чтобы получить всю необходимую информацию, такую, как ваш пароль, uid и программу оболочки, login ищет ваше имя в файле /etc/passwd.

Оболочка (Shell)

Оболочка переходит к выполнению системного профайла оболочки (/etc/profile) и вашего персонального профайла (обычно файл .profile в вашем домашнем каталоге), и, наконец, выводит на терминал приглашение команды ($ или %). В этот момент вы узнаете, что зарегистрированы, а наше путешествие заканчивается.

Автоматизация регистрации

Ок, это было занятно, но наша цель в этой статье -- разработать новый тип регистрации -- автоматический.

Наша задача -- заставить выполняться все эти вещи (init, getty, login и shell), кроме приглашения на ввод имени и пароля.

Для этого существует множество способов, однако я написал программу qlogin, которая делает все это очень просто. qlogin выполняет функции getty и login. Она вызывается init'ом, как и getty, а ее последним действием является вызов программы оболочки, как у login.

Итак, все, что нам потребуется для установки -- заменить приведенную выше строку /etc/inittab на такую строку:

   c4:235:respawn:/sbin/qlogin /dev/tty5 bryanh

Во время загрузки она, вместо прохождения всей процедуры ввода имени пользователя и его пароля, регистрирует имя пользователя bryanh на виртуальной консоле /dev/tty5.

Учтите, "respawn" в этой строке означает, что по завершении этого процесса init создаст его заново. Т.е. в традиционных Unix-системах ваш выход из оболочки вызовет завершение процесса, запустится новый getty и на терминал будет выведено приглашение регистрации для следующего пользователя. В случае qlogin, при вашем выходе из оболочки ее немедленно заменит новая. Таким образом, если вы хотите полностью обновить свою сессию, то для этого хорошим способом будет ввод команды logout.

Начинайте не спеша

Возможно, вам не следует, установив qlogin, сразу переходить к замене в /etc/inittab всех своих getty на qlogin и перегружаться, чтобы посмотреть как это работает. Это было бы слишком оптимистично.

Преимущество разнообразия

Во-первых, я рекомендую вам не переделывать все ваши консоли на qlogin. Оставьте проверенную и надежную систему getty/login хотя бы на одной виртуальной консоле для того, чтобы если вы вдруг пропустили что-нибудь с qlogin, вы смогли зайти на другую консоль и исправить это. А если вы ошиблись в чем-нибудь с getty или login, то смогли бы войти на другую виртуальную консоль через qlogin и также исправить ошибку!

Запуск из оболочки

До начала редактирования /etc/inittab и внесения ошибок в задания init, было бы неплохо вам сначала проверить свои знания с помощью запуска qlogin из оболочки. Посмотрите работу qlogin своими глазами. Проблема с init в том, что, независимо от того, что это очень важный процесс, который вам не желательно нарушать, у него нет стандартного файла ошибок, т.е. не существует способа передать вам сообщение об ошибке, поэтому сложно понять, почему он работает не так, как вы ему говорите.

Обычно признаком того, что с init что-то не в порядке служит сообщение "id X spawning too fast. Disabled for 5 minutes." Это означает, что программа (например, qlogin), выполнять которую вы заставляете init, работает с ошибками и немедленно прерывается. А поскольку это запись "respawn", init просто создает новый процесс, выполняющий ту же программу. И эти процессы запускаются и "падают" поочередно. Init замечает это и "притормаживает" процедуру "respawn" на 5 минут, надеясь, что кто-нибудь исправит проблему. Но какова причина ошибки выполнения программы? Никто не знает, кроме самой программы, но она молчит.

Поэтому нужно просто вызвать qlogin из командной строки оболочки с теми же аргументами, с которыми вы собираетесь запускать ее из init. Теперь, если qlogin "рухнет", она выдаст сообщение об ошибке.

Разумеется, было бы лучше, если бы оболочка, из которой вы вызываете qlogin, была оболочкой суперпользователя. В противном случае я могу рассказать вам прямо сейчас, какие у вас будут сообщения об ошибках.

Одно отличие - управляющий терминал

Один хитрый аспект выполнения qlogin из оболочки -- это свойство управляющего терминала. Созданный вами с помощью qlogin процесс регистрации будет использовать указанный вами терминал в качестве своего терминала для ввода и вывода, но его управляющим терминалом будет терминал, в котором вы набрали "qlogin".

Причина этого различия в следующем: если управляющий процесс Linux'а открывает терминал для ввода, но еще не имеет управляющего терминала, то этот терминал и становится его управляющим. Но если управляющий терминал уже существует, то он сохраняется. Init же не имеет управляющего терминала, поэтому его не создает и наследующий процесс qlogin. Однако оболочки login'а имеют управляющие терминалы, следовательно их имеют и наследующие процессы, создаваемые вами вводом команд (таких как qlogin) в командной строке.

Различие можно увидеть, нажав Control-C: он ничего не делает. Ввод Control-C на стадартном входном устройстве кроме вставки символа Control-C во входной поток смысла не имеет. Но на управляющем терминале Control-C передает переднеплановым (foreground, в противоположность фоновым, background) процессам, связанным с этим терминалом, сигнал SIGINT, который имеет знакомый эффект прерывания программы.

То есть, если вы регистрируете себя на /dev/tty5, набрав "qlogin /dev/tty5 ..." на /dev/tty1, то Control-C на /dev/tty5 работать не будет. Поместите эту же команду "qlogin /dev/tty5 ..." в /etc/inittab, и Control-C на /dev/tty5 будет работать прекрасно.

Замечание: будучи педантом, я должен признать, что говоря о Control-C, я предполагаю, что свойства терминала TTY установлены таким образом, что Control-C является "символом прерывания". Вы можете использовать stty, чтобы установить какой-нибудь другой символ прерывания или вообще никакого.

О qlogin

qlogin в вашей системе нет, поэтому вам потребуется ее установить. Скачайте ее с ibiblio.org и выполните простые инструкции по установке. Как вы обнаружите, дополнительным условием будет расширение Perl под названием User::Utmp, которого, возможно, также нет в вашей системе, поэтому вам потребуется выполнить инструкциям по его получению и установке.

qlogin написан на Perl и достаточно прост. Поэтому вы сами сможете увидеть шаги, выполняемые при регистрации пользователя. И вы также можете изменять программу для подгонки к своим собственным потребностям.

Одна хорошая вещь в qlogin в том, что она настолько самостоятельная, что даже не требует конфигурационных файлов. Вы можете сообщить все, что ей необходимо знать для вашей регистрации, параметрами командной строки. Например, вы можете обойти свой файл /etc/passwd или зарегистрировать пользователя, которого нет даже в /etc/passwd. Вы контролируете все.

Давайте взгянем на опции qlogin:

    --command
     команда (один из распространненых способов назвать программу плюс ее
     аргументы) для запуска после выхода qlogin. Обычно /bin/bash.
    --arg0
     Аргумент нулевого значения для программы, которая выполняется после
     выхода qlogin'а; то что выводится командой ps.
    --uid
     цифровой id пользователя процесса.
    --gid
     цифровой id группы процесса
    --homedir
     домашний каталог и начальный текущий рабочий каталог процесса.
    --utmp/--noutmp
     определяет, будет ли qlogin регистрировать сессию в базе данных
     пользовательских счетов (файл utmp).
     

А аргументы qlogin задают терминальное устройство, используемое процессом.

Все детали про применению qlogin -- в документации, которая с ним поставляется.

Что еще можно делать с qlogin

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

  qlogin /dev/tty5 root --command=/bin/top --noutmp

  

Допустим, ваш компьютер является узлом торговой системы магазина. Терминалами будут последовательные терминалы в кассовых аппаратах. Кассиры не желают регистрироваться в Linux и не желают видеть shell. Если программой POS является /usr/local/bin/pos, вы можете сделать следующее:

  qlogin /dev/ttyS1 cashier --uid=500 --gid=500 --command=/usr/local/bin/pos
      --arg0=POS --homedir=/

   

В этом случае, программе pos, возможно, потребуется некоторая инициализация последовательного порта, например, установка его скорости. В традиционной моделе Unix-регистрации getty это делает перед тем, как отправит туда приглашение к регистрации.

Переднеплановые процессы

[Ваш редактор спросил Брайана: "Мне казалось, что в системе не существует концепции переднепланового (foreground) процесса; это вымысел оболочки." Ниже его ответ. --Iron]

Обычно я думаю также; возможно, потому, что я читал документацию к Bash. Однако ядро Linux определяет "группу переднепланового процесса" (foreground process group). Каждый управляющий терминал имеет группу переднепланового процесса. По умолчанию, это процессовая группа процесса (*1), который изначально был открыт терминалом. Но процесс может установить группу процесса переднего плана любой процессовой группе в своей сессии с помощью ioctl.

    (*1) Примечание переводчика: Я вполне осознаю, что данное выражение звучит, по меньшей мере, жутко, но мне не удалось сразу подобрать хороший перевод выражения "process group of the process" без потери или искажениия смысла. Возможно, позже (во второй жизни) меня осенит, и я подкорректирую это и, вероятно, другие трудные места. --Alex

В статье я несколько вольно использовал ссылку на "foreground processes," который, как я думаю, можно легко интерпретировать как "процессы в группе процессов переднего плана".

Я думаю, что только смысл группы процессов переднего плана (сущность ядра) в том, что процессы в этих группах процессов получают сигналы control-C и hangup.

Управление заданиями в Bash используют этот ioctl, чтобы любое ваше "переднеплановое задание" ("foreground job") стало переднеплановой процессовой группой для вашего терминала. Вот почему, поместив что-либо в фон, например, "grep abc * &", вы не сможете прервать это с помощью control-C. Для прерывания вам необходимо сначала выполнить "fg", заставляя Bash использовать ioctl для перевода этого в foreground, а только затем ввести Control-C.

Много лет назад, до Web, когда терминалы имели гораздо большее значение, я потратил много часов, продираясь через код ядра и экспериментируя, чтобы изучить обработку групп, сессий, управляющих терминалов, управление заданием, SIGINT, SIGHUP и т.д. Я бы смог написать об этом длинную статью, но, думаю, это уже действительно архаичная информация.

[Читателям: если вы хотите подтолкнуть его выложить свою такую "архаичную информацию", пишите в Mailbag. Помните, также, что Mailbag -- это место, где вы можете заказывать статьи по любой другой тематике. -- Iron ]

Bryan Henderson

Bryan Henderson (Брайэн Хендерсон), системный программист, работающий, в основном, на больших компьютерных системах. Любовь Брайэна к компьютерам возникла в старших классах с 110-бодового подключения к местному колледжу, но Брайэн мало интересовался домашними компьютерами, пока не появился Linux.


Команда переводчиков:

Владимир Меренков | Александр Михайлов | Иван Песин | Сергей Скороходов | Алексей Саввин | Павел Ступин | Роман Шумихин |

Со всеми предложениями, идеями и комментариями обращайтесь на [email protected]

Сайт рассылки: http://gazette.linux.ru.net