Это не настоящий конспект лекции, а некий пересказ по горячим следам.

Принципы устройства Linux

Построение старого кадра.

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

Смешение языцей

Переходим к тому, что файлы должны быть текстовые, т. к. с ними работать человеку. Можно выделить 2 принципа: human-readable (человекочитаемость), это когда любую строку файла можно прочитать и понять по документации без соотв средств, и human-writeable (человекопроизводный), это когда весь файл (напр., конфигурационный) может быть с помощью документации создан вручную. Например, системный журнал размером 10МБ — человекочитаемый, но написать его самому невозможно, да и незачем.

Сколько и каких текстовых файлов есть в системе: системные настройки в /etc — все текстовые (разве что XML попадается). Пользовательские настройки в $HOME (обычно имя файла начинается на точку, чтобы его ls без параметров не показывал) — тоже текстовые. Процесс запуска и останова системы (файлы в /etc/init.d и /etc/rc.d) — текстовые сценарии на shell.

Отступление: “.??*” — это шаблон shell, означающий имя файла, начинающееся на “.”, за которой следует два любых символа (“?” и “?”) и любое (в том числе 0) количество любых символов (“*”). Так покажутся все файлы, кроме “.” и “..” (строго говоря, не покажутся ещё “.?”, но таких обычно нет).

Утилиты обработки текста. Их очень много, в одном только coreutils (info coreutils) — десятки.

Работа со строками. cat читает со стандартного ввода и выводит на стандартный вывод. Зачем такая простая программа? В shell есть удобные средства перенаправления ввода и вывода. tac выводит строки файла в обратном порядке. head и tail выводят, соотв., первые и последние несколько строк файла. sort — сортирует строки файла (стандартного ввода) лексикографически, grep ищет и показывает только те строки, в которых имеется вхождение заданной подстроки (точнее, регулярного выражения, но об этом не успеем). Тренируемся на файла /etc/passwd — он текстовый и разнообразный.

Работа со словами: wc — это worg counter, счётчик строк, слов и символов, cut вырезает и показывает некоторые поля файла (в примере — первое и пятое). Посимвольные: tr — заменяет одни символы на другие, iconv преобразует из одной кодировки в другую.

Отступление: tr вообще не умеет считывать из какого-либо файла, всегда читает со стандартного ввода, а пишет на стандартный вывод. Но в shell сделать перенаправление ввода легче лёгкого, с помощью “<”. С помощью “|” в shell вывод первой программы подаётся на ввод второй, то есть cal | iconv -f koi8-r -t cp1251 работает так: программа cal (календарь) выводит календарь на стандартный вывод, но shell уже сделал так, что этот стандартный вывод — канал, труба, другой конец которой — стандартный ввод команды iconv.

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

Утилиты

Подведём итог прошлой лекции и начала этой. Что такое Linux как операционная среда?

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

Детали налицо, необходим конструктор.

Триединая оболочка

Что это за «конструктор»?

Он должен позволять автоматизировать то, что сделано руками. Если автоматизация будет другими средствами, не такими, как в командной строке, то «третий раз» (программирование решения) будет отдельной сложной задачей. Например, есть встроенный в текстовый редактор ЯП, но им никто не пользуется, продолжают по сотне раз делать одно и то же руками, потому что ручные команды — это клавиши и стрелки, а операторы ЯП — совсем другое. К тому же это, извините, бейсик. Надо, чтобы команды ЯП совпадали с командами ручной работы.

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

Не надо забывать, что с помощью shell пользователь общается с системой. Это — первое, что он делает, потом только составляет сценарий. Поэтому пользовательскую работу надо сделать как можно удобнее.

Итак, shell рассматривается с трёх сторон:

  1. Высокоуровневый язык программирования, ориентированный на работу в системе
  2. Интерпретатор командной строки, позволяющий удобно с ней работать
  3. Оболочка — каркас конструктора, организующий взаимодействие утилит

Shell — общее имя для нескольких программ. Раньше их было много, теперь наиболее распространены две: bash (есть в любом Linux-е) и zsh (тоже есть, но не всегда установлен по умолчанию). Есть ещё sh (как правило, это урезанный bash) — программа, соответствующая стандарту POSIX (имеет меньше возможностей). Поэтому программировать рекомендуется на sh, а для собственной работы в командной строке использовать что нравится.

Про shell как язык программирования мы разговаривать не будем — это долго, и язык сам по себе обычный. В руководстве всё написано. А вот на особенностях этого языка применительно к другим ипостасям shell — интерпретатора командной строки и оболочки — поговорим.

Интерпретатор

Об удобстве: это понятие субъективное. Попытка объективного определения: удобно то, что позволяет делать работу быстро и качественно (даже если поначалу пугает:).

Что есть в shell для удобства работы (список неполный!): Входные и выходные сценарии (несколько разных), которые запускаются один раз при входе в систему — .bash_profile, всякий раз при запуске shell-а, который будет взаимодействовать с пользователем (интерактивного) — .bashrc, всякий раз при запуске любого shell-a (в т. ч. запущенного для интерпретации сценария) — в bash нету, в zsh — .zhenv; при выходе из системы (.bash_logout) и т. п. Это позволяет настроить окружение, выполнить какие-то действия при входе и выходе и т. п.

У shell много функций редактирования командной строки (около 150), каждую можно прицепить к какой-нибудь клавише на клавиатуре, или к последовательности нажатий (команда bind).

Чтобы не набирать в командной строке длинную команду по многу раз, из неё можно сделать сокращение вида alias сокр='длинная_часто_используемая_команда', и набирать только сокр.

Самое мощное и удобное средство, облегчающее жизнь — достраивание. Есть клавиша “Tab”, и соотв. ей команда «надоело набирать, дальше очевидно!» (complete). Например, достраивание имён файлов выглядит так: ls teTab превращается в ls texts, т. к. других файлов, чьи имена начинаются на te в каталоге не было, дальше дописываем OpTab — и получаем ls texts/OpenLectory, т. к. на Op начинается имя единственного подкаталога в каталоге texts. Итого 9 нажатий вместо 20. Если достраивание останавливается н неоднозначности (например, ls texts/OTab, а в каталоге texts на “O” начинаются OLL и OpenLectory, то shell покажет эти варианты; если второй раз нажать на Tab, он начнёт их по одному перебирать.

В zsh (и в новом bash) имеется возможность задавать произвольное достраивание. То есть shell по началу команды догадывается, из какого списка надо брать варианты для Tab: если файловая операция — из списка подходящих файлов, если сетевая — из списка известных адресов, если Tab нажат после символа “-” — из списка допустимых ключей набранной команды и т. д.

Скоро ли все пользовательские задачи будут решаться многократным нажатием на один лишь Tab? Нескоро: Достраивание достраивает лишь очевидное, думать и творить надо пользователю.

Как работают шаблоны мы уже видели “*” — любое к-во символов, “?”- один любой, а ещё есть диапазоны: “[a-z0-9+]” означает «одна любая латинская маленькая буква, цифра или знак “+”», а “[^aouie]” — «один любой символ, кроме a, o, u, i, e». Важно: преобразованием шаблона в список файлов занимается shell, команда видит уже готовый список. В примере echo D* просто вывело то, что ему передал shell- список файлов, а ls D* сработал как ls список_файлов_и_каталогов и вывел для каждого каталога в списке его содержимое.

Переменные в shell, разумеется, есть. Им можно присваивать любые строковые значения. Но любую переменную можно превратить в переменную окружения командой export. Переменные окружения есть в любом процессе Linux (не только в shell), это часть понятия процесс, и они наследуются от того процесса, который их породил. Любой процесс может посмотреть в окружение и вести себя в соответствие с содержимым переменных. Переменные можно переопределять. В переменной PATH хранится список каталогов, где shell ищет запускаемые программы, в переменной LANG — язык, на котором будут выводиться сообщения. “$” в начале — это подстановка значения переменной вместо её имени. Переменная PS1 определяет строку-подсказку shell.

Конструктор

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

Что нужно для конструктора:

Таким образом shell стремится быть максимально удобным в качестве конструктора, он удачно совмещает три в одном: переменные, они же — окружение, запуск утилиты — это просто её имя (куда проще!), перенаправление ввода-вывода делается одним символом и т. п., всего таких свойств десятки, если не сотни.

Главы учебника

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