Kodomo

Пользователь

Командная строка UNIX. Введение.

Напутствие устанавливающим Linux

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

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

Но есть два прикладных вопроса, на которые было бы полезно ответить прежде, чем вы возьмёте в руки болванки CD (или DVD или что там).

Во-первых, линуксов дикое множество, какой из них лучше? Ответ на этот вопрос очень простой. Все современные дистрибутивы хороши – если бы они такими не были, они бы давно перестали существовать. Но при этом в каждом дистрибутиве полно своих заморочек, непохожих на заморочки других дистрибутивов. Человек, который много пользуется каким-нибудь дистрибутивом, их обычно знает и даже не замечает их существования. Поэтому я советую выбирать такой дистрибутив, для которого вам проще всего будет добыть человеческую помощь. Если ближайший линуксоид в вашей окрестности – я, то тогда выбирайте Debian. (Мне так кажется, что инструкции по установке у них на сайте достаточно понятные).

Второй вопрос: что делать с распределением пространства на жёстком диске?

Ответ, часть 1: нужно откуда-то иметь достаточно пространства на жёстком диске, чтобы линукс туда поставить. Лучше всего ставить разные ОС на физически разные диски. В этом случае нужно иметь очень широкий полёт фантазии, чтобы суметь установкой одной системы поломать себе другую. Если этой возможности нету, то вам хотя бы нужно иметь сколько-нибудь свободного места (не занятого никакими разделами) на жёстком диске. (Если у вас до сих пор весь диск был занят Windows, то для Windows есть утилиты, которые умеют менять размер её разделов. Только я их не знаю, и помочь вам в этом не могу).

Ответ, часть 2: когда у вас есть какое-то количество места на жёстком диске, лучше всего организовать поверх него LVM (т.е. сделать из этого места раздел типа Linux LVM (код 8E), и использовать его как PV для LVM).

Часть 3: когда есть LVM, на какие разделы (LV) его стоит разделять? Давайте порассуждаем. У нас есть дерево файлов, части этого дерева обладают довольно сильно разными свойствами:

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

  1. всё в один раздел – самый простой вариант; даёт возможность использовать пространство наиболее оптимальным образом; недостатки: когда пространство на диске начнёт кончаться, вам будет труднее отыскать, почему (если оно кончится слишком внезапно, у вас может перестать работать часть системы), если вы умудрились порушить какую-нибудь часть файловой системы, вы рискуете сделать компьютер вообще незагружаемым

  2. отдельные разделы под /, /usr, /var, /home – примерно такое разделение типично предлагает Debian.

  3. отдельные разделы под /, /boot, /usr, /var, /home – вдобавок к стандартному разделению вы отделяете загрузчик от всего остального и немножко снижаете себе шансы случайно сделать систему совсем неспособной загрузиться

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

Я рекомендую вам выбрать между 1 и 3 в меру понимания. (Если вы не понимаете, чего хорошего в дополнительном разделении, то лучше выбирайте вариант 1).

На остальные вопросы инсталлятора вы можете ответить уже и самостоятельно.

Переходим к основной теме сегодняшней лекции ==

Идея командной строки

Машины, на которых создавался MULTICS, а впоследствие и UNIX, были новыми, были большим шагом вперёд перед предыдущим поколением машин. На предыдущем поколении машин одна из стен комнаты машинного зала была занята лампочками, отображающими состояние машины, и когда исполнение программы завершалось, программист объяснял математику, на каких лампочках светится ответ к его задаче; в лучшем случае машина выдавала ответ через перфокарты. В новом поколении машин был интерфейс, они были дружественными пользователю, у них была печатная машинка, с которой пользователь мог вбивать команды машине, и была лента бумаги, на которую машина печатала ответы.

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

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

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

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

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

Для передачи флагов сразу придумали способ, как их отличать от данных: если очередной параметр командной строки начинается с минуса, значит это флаг или набор флагов. Флаги изначально условились обозначать одной буквой (как сокращение от описания параметра), и если в одном параметре командной строки за минусом шло несколько букв, то это значило, что мы записываем сразу несколько флагов: например, ls -lR – это синоним ls -l -R. Всё дело в том, что у авторов первых версий UNIX были очень тяжёлые для работы терминалы, и понятие "сильный программист" подразумевало в первую очередь силу пальцев. На эту тему ходит миф, что когда-то, лет десять после создания языка Си3, у одного из его авторов, Denis Ritchie, спросили, что бы он изменил в языке, если бы он мог вернуться в прошлое, он ответил: "Я бы переименовал creat в c".

Кроме того, чтобы различать некоторые (необязательные) параметры-данные, их тоже стали помечать флагами (чтобы их проще было различать). Такие параметры пишутся после флагов. Как и в случае с обычными флагами, параметр, который помечен флагом, можно склеить с флагом. В итоге grep -rleab на самом деле является синонимом grep -r -l -e ab, так как флаг -e принимает данные.

Так дела обстояли в 70-е года.

Потом настали 80-е, 90-е, Richard Stallman захотел сделать свою ОС (GNU), и начал с того, что стал делать свой набор утилит. У него условия работы вообще были шикарные: мягкие клавиатуры, стеклянные терминалы, чуть ли не графические системы – сказка. И одна из первых идей, которую он воплотил в своих утилитах – это ввёл новый способ передачи флагов. Чтобы отличить его от старого способа передачи флагов, теперь флаги начинаются с двух минусов, за которыми идёт полноценное описание флага: одно или несколько слов, соединённых минусами. В GNU style flags команда ls -lR выглядит теперь как ls --long --recursive. Таким образом Столлман поборолся сразу с двумя проблемами: во-первых, по записи вызова утилиты стало понятнее, что она делает, а во-вторых, теперь у утилиты флагов может быть больше, чем 2*26+10 (строчные латинские буквы, прописные латинские буквы, цифры). Для флагов, принимающих параметры, Столлман выбрал такой синтаксис: grep --recursive --files-with-matches --regexp=ab (это пример есть синоним grep -rleab или grep -rle ab). Чтобы было проще передавать параметры, в именах которых могут встречаться минусы, но которые нужно воспринимать исключительно как параметры-данные (позиционные параметры), в GNU style flags принято иметь специальный параметр: -- – после него все параметры воспринимаются как позиционные и флагов после него среди параметров не ищется.

Нужно, правда, заметить, что на самом деле и с самого начала существования UNIX в нём были утилиты, не следующие этим двум канонам передачи параметров командной строки, например, типичный вызов утилиты dd выглядит так: dd if=/dev/sda of=/dev/sdb bs=1024 count=1, а параметры утилиты find нужно передавать в заранее определённом порядке, наподобие такого: find /home /usr -name '*.sty'

Вспомним снова первую идею: программа общается с человеком посредством текста. Но текст заодно является довольно удобной сущностью – его можно генерировать, преобразовывать и разбирать с помощью программ. Вдобавок и настройки системы в UNIX принято хранить в человекочитаемых текстовых файлах. Совпадение этих вещей авторы UNIX заметили далеко не сразу, а когда заметили, родилось новое понятие: pipe или даже pipeline – несколько программ соединяются таким образом, что выдача одной является входными данными для следующей. Вход первой и выход последней из них при этом обычно присоединён к терминалу.

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

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

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

Итого:

Документация

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

manpages

Самый первый проект, под который впервые авторам UNIX удалось свою систему продать, был проектом обработки запросов на патенты в Bell Labs.

То, что продавали им авторы UNIX, на самом деле являлось текстовым редактором ed (UNIX гордился тем, что это была операционная система с текстовым редактором) и системой форматирования текста roff. roff принимал на вход файл с описанием разметки, и пользуясь свойствами терминала (типа того, что если одну и ту же букву напечатать дважды в одном и том же месте, она будет выгляеть жирнее), выводил отформатированный текст. Команд форматирования там было совсем немного: сделать текст жирным, сделать текст подчёркнутым, выровнять по правому краю, центрировать, сделать красивые поля.

Спустя некоторое время на основе этих же утилит для UNIX сделали первую систему документации: manpages.

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

Изначально программа постраничного вывода в UNIX называлась more: она выводила страницу текста на экран и писала внизу слово "-- MORE --", если содержимое файла ещё не завершилось. После этого она ожидала нажатия пробела (напечатать следующую страницу) или enter (напечатать ещё одну строку), – и так далее, до тех пор, пока файл не завершится.

Когда Ричард Столлман создавал ОС GNU, он сказал, что more ему недостаточно, ему нужен хороший пагинатор, и поэтому в GNU появилась утилита less с девизом: less is more than more!

Утилита less является сейчас стандартной для просмотра документации (да и вообще это удобная утилита), поэтому вам полезно знать хотя бы несколько основных её команд:

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

Секции традиционно такие:

В каждой секции документации обязательно должна находиться статья по имени intro с напутствием читателям этого раздела (или даже просто пользователям).

Каждая из статей manpages нарезана на много разделов, типично среди них бывает (именно в таком порядке):

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

С самого начала система документации планировалась как гипертекстовая – т.е., каждая статья должна содержать (в умеренных количествах) ссылки на другие статьи. Однако в те времена, когда разрабатывалась эта система, помыслить себе программную реализацию гипертекста (то есть чтобы вы курсором подошли к слову, что-нибудь нажали и перешли по ссылке) казалось невозможным да и жутко неудобным. Поэтому вместо программной реализации гипертекста в manpages принят стандартный способ обозначения ссылок на статьи в тексте, который удобно понимать человеку. Формат такой: имя_статьи(секция). Я уже приводил вам выше пример suffixes(7) – статья suffixes в разделе 7. Этот формат ссылок хорошо прижился и используется до сих пор, зачастую даже в чатах.

Наконец, как всей этой документацией пользоваться?

Для этого есть в первую очередь три утилиты: man, apropos, whatis:

Разумеется, в документации есть документация и по самой системе документации, так что команды man man, man apropos, man whatis ничуть не лишены смысла.

texinfo

Когда начала создаваться ОС GNU (которая впоследствие стала GNU/Linux), её авторам не понравились некоторые свойства системы manpages, и они создали свою систему документации рядом.

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

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

Нас в первую очередь интересует точка зрения на texinfo как на систему гипертекстовой документации.

Из основной идеи должно быть понятно, что первым способом деления документации является деление на книги. Каждая книга разбивается по усмотрению авторов на разделы, которые могут иметь довольно много уровней вложенности. У разделов меньшего уровня вложенности принято в конце иметь оглавление со ссылками на вложенные в него разделы – это оглавление называется словом menu.

Когда вы запускаете просмотрщик документации, info, без аргументов, первое, что вы видите – это список книг. Просмотрщик сделан в духе среды emacs4, поэтому чтобы им было действительно удобно пользоваться, нужно выучивать ещё один набор команд. Назову самые важные и самые простые, которые, по счастью, довольно универсальны:

README

Не у всех авторов программ руки доходят до того, чтобы сделать для своего творения документацию в удобном стандартном виде. Многие просто пишут текстовый файл с объяснением, что к чему, и кладут его в дистрибутив программы. Некоторые пишут документацию в HTML, XML, PDF, PS, или, упаси боже, DOC.

Чтобы не терять такую документацию (ибо система большая, пишется в значительной мере всё-таки добровольцами, а написание документации – одно из самых противных дел с точки зрения многих программистов), для неё издревна придумали стандартное место, куда её складывать.

На более древних диалектах UNIX такое место – /usr/doc.

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

Во всяком уважающем себя дистрибутиве линкус сейчас один из этих путей является ссылкой на другой. (Увы, не во всяких).

Контекстная документация

Вдобавок к этим способам, многие программы предоставляют свою специфическую систему документации, например

Веб

Иногда спасает гугл. В сети есть несколько сайтов, на которых красиво отформатированы manpages, и гугл их вам тоже наверняка будет пытаться показывать – но остерегайтесь, эта документация может быть от другой разновидности UNIX и не всегда быть применима в вашем случае.

Кроме гугла бывают всякие форумы (звонок другу, помощь зала). Есть прекрасный текст "How To Ask Questions The Smart Way" (и немного устарелый перевод на русский язык) о том, как не достать людей на форумах, но всё же получить от них нужные ответы. (У программистов довольно странное чувство юмора и понятия добра и зла, и его полезно понимать).

На сегодняшний день канонической и наиболее поддерживаемой документацией всё таки остаются manpages – поэтому я уделил рассказу о них больше всего времени. Иногда некоторые проекты делают документацию только в texinfo или делают для texinfo документацию лучше, чем для manpages. Некоторые проекты плюют на то и на другое, но делают хорошую контекстную документацию. Некоторые проекты вообще не делают стандартной документации. Так что одного общего места, где можно искать документацию, увы, нету. (Именно поэтому в Debian политика оформления пакетов системы требует, чтобы каждом пакете обязательно были manpages – если у программы своих manpages нету, то там хотя бы должно быть написано, а где же находится настоящая документация).

Основы шелла

Вернёмся к интерпретаторам командной строки.

Исторически сложилось, что подавляющее большинство интерпретаторов командной строки в UNIX синтаксически похожи на один из двух языков: Bourne shell и C shell. Наиболее известные имена шеллов в первом семействе: Bourne shell (/bin/sh) – первый из семейства, Korn shell (ksh) – наиболее успешный из комерческих, Bourne Again shell (bash) – основной шелл в линуксах сейчас, Z shell (zsh) – все, кто освоили его, потом с отвращением смотрят на все другие шеллы. Во втором семействе: C shell (csh) и Turbo C shell (tcsh). Синтаксически шеллы разных семейств имеют меньше шансов быть похожими, чем из одного семейства.

Когда всё безобразие, которое творится в UNIX стандартизовывали, комиссия POSIX описала свой стандарт на то, как должен выглядеть шелл в значительной мере было основано на ksh. bash, zsh, ksh, sh могут исполнять почти все программы, удовлетворяющие синтаксису POSIX sh почти без проблем, и у них есть флаги для эмуляции большей совместимости со стандартом, но, как это всегда случается со стандартами в компьютерах, по-настоящему их никто не соблюдает. Здесь стоит ещё заметить, что кроме больших шеллов, которые я перечислил, которые стремятся предоставлять как можно больше возможностей, довольно активно сейчас развиваются и маленькие шеллы, у авторов которых как правило две цели в уме: чтобы размер самого шелла был как можно меньше, но он удовлетворял POSIX. Эти шеллы пользуются популярностью в случаях, когда линукс запихивают туда, где ему по-настоящему-то быть не положено: в маршрутизаторы, на мобильники и т.п. Самых популярных таких шеллов два5: ash и dash.

Так как у вас больше всего шансов общаться именно с каким-нибудь диалектом линукс, а в линукс традиционно входит bash (по той простой причине, что он входит в проект GNU), то я буду рассказывать в первую очередь про него, и, если не буду забывать, буду комментировать, что из того, что я рассказывают, отличается от стандарта. По большому счёту, если вы научились пользоваться одним шеллом из семейства sh, то и любым другим шеллом из этого семейства вы научитесь пользоваться без слишком больших усилий.

Итак, если мы говорим о большом шелле, то это программа, которая стремится удовлетворять всем условиям, которые мы перечислили выше, но при этом ещё и давать пользователю ещё больше плюшек. Куда в шелле можно воткнуть плюшки?

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

Второе место, где шелл может сделать жизнь пользователю проще – это каким-нибудь (однозначным и просто описываемым) образом преобразовывать строку прежде, чем отправлять её исполняться. В этом месте шелл облегчает жизнь не только пользователю системы, но и программисту отдельных утилит. Например, утилита ls, если ей перечислить файлы в командной строке, покажет только их. Когда мы говорим ls *.txt, первым делом шелл преобразует эту команду и подставляет вместо *.txt все файлы в текущей директории с расширением .txt – тогда ls остаётся только вывести их имена на экран.

Упражнения

  1. Прочитайте: intro(1).
  2. Как узнать, в каком разделе документации manpages что находится (не подглядывая в этот конспект или в гугл)?

  1. Т.е. делает для разной аппаратуры похожий способ управления ей. В UNIX это хорошо видно на примре файлов-устройств (1)

  2. Если никому ничего нельзя, то между пользователями не будет конфликтов! Это изречение недалеко (но заодно и очень далеко) от идеологии UNIX. (2)

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

  4. Изначально emacs назывался текстовым редактором. Сейчас это такая среда, в которой есть браузер, есть почтовая программа, есть клиенты разных сетей чатов, есть игры, есть своя система ввода иероглифов -- и, согласно одной шутке, единственное, чего нет в emacs -- это хорошего текстового редактора. Противостояние vi vs. emacs -- это одно из древнейших противостояний. Обычно, люди, которые довольно рано научились редактировать тексты в vi, больше никакие другие текстовые редакторы за нормальные не признают -- и аналогично с людьми, которые довольно рано освоили emacs. (4)

  5. Данные и близко не достоверны. Это лишь имена тех, с кем сталкивался я. (5)