SlideShare a Scribd company logo
1 of 14
Download to read offline
Т.В. Шапорев

Конспект вводных занятий практикума по ОС UNIX.
Москва, 2012

Первое занятие 1
На занятиях практикума в качестве подопытного кролика будет использоваться UNIX в
варианте Linux.
UNIX возник в начале 70-х годов прошлого века. Согласно легенде произошло это следующим образом: в одно из подразделений Bell Laboratories поступил новый компьютер PDP. Компьютер
использовался главным образом для подготовки документации. Печатающее устройство работает
гораздо медленнее процессора, так что из-за однозадачной операционной системы во время печати
центральный процессор практически простаивал. Чтобы в это время можно было играть в «звёздные
войны», Томпсон придумал многозадачную систему, которую потом быстренько, всего-то лет за
десять, довели до ума и стали распространять как UNIX V7.
Вообще подобного рода исторические зарисовки могут быть очень полезными: чтобы лучше
понять, почему UNIX получился именно таким, каким получился, надо представлять, в каких
условиях его создавали.
Итак: когда деревья и компьютеры были большими… Когда-то они были действительно
большими. В вашингтонском музее вычислительной техники экскурсовод говорит замечательную
фразу: «обратите внимание, слева от вас БИТЫ сумматора с нулевого по седьмой». Один бит информации — это в 40-х годах было устройство с габаритом метра полтора 2 . Это, впрочем, было задолго
до меня, а лично я вполне помню БЭСМ-6, которая занимала три этажа в южном крыле лабораторного корпуса, потребляла 360 киловатт электроэнергии, для обслуживания требовались сменные
бригады техников под руководством нескольких инженеров… В общем, можно прикинуть, в какие
деньги обходилось обслуживание такой конструкции в западных условиях, и неудивительно, что с
пользователей брали деньги за каждую секунду работы центрального процессора. (Когда в учебном
классе каждому предоставляется индивидуальный компьютер с производительностью больше, чем у
БЭСМ-6, этак примерно на пару порядков — это уже полный разврат, раньше такого не было.)
Неудивительно, что из таких дорогих игрушек стремились выжать максимум, и, кроме того, чтобы
использовать многозадачную операционную систему, к одному компьютеру подключалось много
удалённых рабочих мест, так называемых терминалов. Таким терминалом могла быть электрическая
пишущая машинка, а если досталось устройство с электронно-лучевой трубкой, так это, считай, повезло. Терминалы могли различаться количеством строк на экране, набором клавиш, их подключали
либо напрямую, либо через модем и телефонную линию… На этом разнообразии могли одновременно работать много пользователей… А операционная система должна была более-менее эффективно
обслуживать весь этот зверинец.
Чтобы в системе могли одновременно работать несколько человек, систему пришлось с самого начала строить как многозадачную и многопользовательскую, и, в частности, позаботиться о том,
чтобы люди не могли испортить чужую информацию (без разницы, по ошибке или по злому умыслу).
Сейчас пожалуйста включите компьютеры и загрузите UNIX.
На клавиатуре нажмите клавиши Ctrl, Alt и, не отпуская их, клавишу F2.
Вместо красивой цветной заставки должен появиться скучный чёрный экран, на котором,
ближе к левому верхнему углу, есть слово login. Таким образом система изображает старомодное
алфавитно-цифровое рабочее место, «терминал», и именно этот режим будет основным на занятиях.
Современный цветной интерфейс с окошками и менюшками в принципе-то удобней, проблема в том,
что все эти удобства стали обычными уже после того, как сформировался стандарт UNIX, соответственно, они нестандартные. То есть каждый уважающий себя современный UNIX предоставляет
интерфейс современного типа, и все такие современные интерфейсы в чём-нибудь друг от друга
отличаются, каждую новую систему надо будет разучивать заново. С другой стороны, если уметь
работать со старомодным алфавитно-цифровым так называемым command line interface, то худобедно с любым UNIXом можно начать работать сразу.
1

Для расчёта времени необходимо иметь в виду, что первое занятие начинается с постановки задачи, то есть
обсуждаются вопросы 1) зачем вообще физику информатика, 2) каким образом будет оцениваться работа в семестре и
3) прочие правила игры — всё это здесь пропущено.
2
Не знаю почему. Уже тогда технически возможно было сделать ламповый триггер, и было бы это во всех отношениях не
хуже, но… может быть просто не придумали ещё?
Для того, чтобы различать, кто именно работает с системой, у каждого пользователя есть
индивидуальная «кличка», именно её система просит ввести после приглашения login, а для того,
чтобы убедиться, что это именно вы, потом система спросит секретный пароль.
Выполните вход в систему, добейтесь, чтобы все получили приглашение интерпретатора
команд.
О людях, которые умели бы непосредственно силой мысли управлять компьютером, мне слышать не приходилось. Для взаимодействия с человеком в компьютере, в числе прочего, есть специальная программа, которая ждёт, что будет введено с клавиатуры, а потом пытается это выполнить,
если может — такая программа называется интерпретатором команд (или командным интерпретатором). По традиции командные интерпретаторы в UNIX называются словом shell (оболочка).
Поскольку система была рассчитана на довольно суровую аппаратуру (даже электрическую
пишущую машинку), то разработчики системы экономили как могли: большинство команд UNIX —
это аббревиатуры или сокращения. Команда начинает выполняться после того, как нажата клавиша
Enter.
Наверное самая популярная команда в UNIX — это ls, сокращение от слова list. Выполните
команду ls и полюбуйтесь на содержимое текущей директории. Если хочется знать, какая директория текущая, то выполните команду pwd — это аббревиатура от print working directory. Прежде, чем
рассказывать, что такое текущая директория, и зачем она нужна, надо сделать важное замечание:
Большая часть того, что написано в учебнике, и вообще всё, что связано с практическими
занятиями, можно извлечь из самой системы. Традиционная информационно-справочная служба в
UNIX называется man (сокращение от manual). Обычно после самой команды man через пробел указывается название того, о чём нужна справка. Команда man man покАжет подсказку о себе самой.
Команда man ls выдаст полное описание возможностей команды ls — посмотрите, сколько всего
разного умеет эта простенькая на вид команда.
Наконец, всё это примеры структуры команд в UNIX: есть собственно команда, которая может
вести себя по-разному в зависимости от параметров, аргументов или ключей (все три слова в этом
месте обозначают одно и то же), которые перечисляются после команды и разделяются пробелами
(или табуляциями).
В качестве ещё одного практически полезного примера наберите всё ту же команду ls с
ключиками, то есть ls -l, и посмотрите, насколько результат отличается от предыдущего раза.
Чтобы понять, что это такое возникло на экране (и не забыть про обещанную текущую
директорию), придётся вести рассказ издалека — от структуры файловой системы.
Если говорить о файловой системе, то, кстати, что такое файл?
Надеюсь, вы помните определение «файл — это именованный набор данных».
Но вообще-то, раз уж вы видите компьютер не первый раз в жизни (и даже уже получали зачёты по информатике минимум дважды), то по опыту работы (например с MS Windows) наверное помните, что файловая система имеет (в первом приближении) иерархическую древовидную структуру, а
файлы бывают двух типов: собственно файлы с данными и директории 3 , которые содержат другие
файлы (в том числе директории) — для первого занятия этого достаточно.
Для дальнейшего нам потребуются следующие особенности файловой системы UNIX. Во-первых, все данные в UNIX организованы в ОДНО дерево. Дерево это растёт, начиная с основополагающей, так называемой корневой директории, которая всегда носит имя из единственной косой черты:
/ (обратите внимание на наклон черты — это так называемый «прямой слэш»). Если файл живёт не в
корневой директории, а закопан поглубже, то для точного описания его положения надо перечислить
все директории, которые надо пройти, чтобы до него добраться, и в том порядке, в котором их надо
пройти, начиная от корня (например /usr/local/bin ...), причём в качестве разделителя используется всё та же косая черта. Такой полный путь к файлу, начиная с левой косой черты, ещё называется абсолютным. Если файл запрятан достаточно глубоко, то набирать его (на электрической пишущей машинке!) может быть довольно утомительно, но можно облегчить себе жизнь с помощью так
называемого относительного пути. У каждого процесса 4 в системе есть своя любимая директория,
которую он помнит, и которая называется текущей директорией. Так вот, если путь к файлу начинается с чего бы то ни было, отличного от косой черты, то считается, что слева надо приписать текущую директорию. В простейшем случае, если не было указано ни одной косой черты, то это просто
имя файла в текущей директории. (Соглашение об абсолютных и относительных именах файлов

3
4

Противники англицизмов в русской речи требуют переводить directory исконно русским словом «каталог».
Понятие процесса раскрывается на лекции. Если этой лекции ещё не было — придётся выкручиваться.
поддерживается ядром системы — запомните этот факт, потому что когда мы доберёмся до языка C,
соглашение останется в силе.)
Теперь вернёмся к результату команды ls -l, которая сообщает содержимое текущей директории в деталях и подробностях. О каждом файле перечислены, справа налево: имя файла, время
последнего изменения файла, длина файла в байтах, некоторое количество других деталей, включая
кличку владельца файла, и в крайней левой позиции — магическая комбинация из десяти букв или
знаков минус. В этой комбинации крайний левый символ — это тип файла, для директорий там стоит
буква d, а для обычных файлов данных, что называется regular file, указан прочерк (минус). Оставшиеся девять символов называются «маской прав доступа к файлу», «полномочиями файла» и тому
подобными словами.
Система многопользовательская, так что надо как-то запретить хулиганам (или просто неосторожным людям) портить чужие файлы, не позволить шпионам или конкурентам подглядывать в
чужие данные и т.п. Для решения этой задачи, во-первых, все пользователи системы поделены на три
категории: сам владелец файла, всякие посторонние люди и (промежуточная ступень) группа
владельца файла. В одну группу пользователей обычно, так сказать, «по смыслу», объединяются
люди, работающие над одним проектом. Во-вторых, всё, что можно сделать с файлом, тоже сгруппировано в три категории: файлы можно читать, записывать или выполнять. (В отличие от DOS или MS
Windows, где возможность выполнения файла определяется по его расширению навроде .EXE, здесь
возможность выполнить файл запоминается явно отдельным признаком.) И вот в выводе команды
ls -l слева после типа файла присутствуют именно эти типы доступа: группа из трех символов для
прав доступа владельца файла, ещё три символа прав доступа группы владельца файла и оставшиеся
три — для всех остальных.
Если в группе присутствует буква r, то файл можно читать (от слова read), если буква w, то
записывать (write), буква x означает разрешение выполнять файл (eXecute).
Если какое-то действие для кого-то не разрешено, то вместо соответствующей буквы ставится
прочерк (минус).
Для того, чтобы изменить маску доступа, в системе есть команда chmod (change mode), но
прежде, чем пользоваться этой командой, придётся научиться записывать маску доступа в восьмеричной форме (потому что эта форма пригодится и в языке C тоже).
Маска прав доступа к файлу в UNIX — едва ли не последнее место, где сохранилась восьмеричная форма записи; она была популярна на старых системах, но сейчас вместо этого модно использовать шестнадцатеричную запись. Тем не менее, вот как раз в этом месте восьмеричная запись
удобней, потому что группа из трех признаков доступа (разрешено/не разрешено) кодируется тремя
битами, и три бита ровнёхонько укладываются в одну восьмеричную цифру. На всякий случай имеет
смысл напомнить упрощённое правило перевода в восьмеричную систему: в группе из трех битов
младший имеет вес единица, средний — двойка, старший — четвёрка, суммируются веса
присутствующих признаков.
Теперь надо несколько минут потренироваться в переводе: перевести в восьмеричную форму
то, что выдала команда ls, потом представить, что какую-то маску надо изменить — как бы она
выглядела после этого. Пример: комбинации rwxr-xr-- соответствует набор весов 421 401 400,
то есть (после суммирования) восьмеричное значение 754.
Нужно это вот зачем: команда chmod умеет много всякого, полный набор её возможностей
лучше посмотреть в man, но в простейшем варианте это:
chmod восьмеричная-маска имя-файла
Команда потребуется в конце занятия.
Прежде, чем менять атрибуты файла, надо иметь файл, сейчас самое время научиться
создавать файлы. К сожалению, для этого потребуется достаточно длинная преамбула.
Итак, каждому нормальному процессу в UNIX совершенно забесплатно, без каких-то специальных действий, что называется «по умолчанию» предоставляются три канала ввода-вывода: канал
стандартного ввода, канал стандартного вывода и стандартный канал сообщений об ошибках. (В
стандарте языка C они скрываются под псевдонимами stdin, stdout и stderr, так что, в принципе, они
должны быть уже известны из программы первого курса.) По умолчанию канал стандартного ввода
принимает информацию с клавиатуры, а оба стандартных канала вывода показывают информацию на
экране.
Это можно изменить.
Если в командной строке написать символ < (меньше) и после него имя файла, то канал
стандартного ввода будет читать информацию из указанного файла (вместо клавиатуры).
Если в командной строке написать символ > (больше) и после него имя файла, то канал стандартного вывода будет складывать информацию в указанный файл (а не на экран). Если такого файла
ещё не было, он будет создан. Если такой файл уже есть, он будет «переписан поверх», то есть старое
содержимое полностью забыто, вместо него записано новое (если это разрешено маской доступа к
файлу).
Наконец, символ | (вертикальная черта) делает совсем смешную штуку: стандартный вывод
команды слева от черты подаёт на стандартный вход команды справа. По английски это называется
pipe (запомните это слово, оно ещё не раз встретится), а на русский переводится... обычно транспортёр или конвейер. Использовать это можно например, так: если команда ls печатает слишком много,
так что Вы не успеваете всё рассмотреть, то можно её вывод подать на вход команде more, которая
поделит его на кусочки размером в один экран: ls -l | more. Когда команда man выдаёт информацию кусочками по одному экрану, то она внутри себя использует именно этот механизм. Впрочем,
сегодня нам pipe не потребуется.
До торжественного финала осталось ещё две команды.
Первая из них, cat, означает вовсе не кошку, это сокращение от слова конкатенация. Опятьтаки полный набор её возможностей лучше посмотреть в man, а вкратце, этой команде можно подсунуть (в аргументах) несколько имён файлов, она содержимое этих файлов «склеит» один к другому, а
результат отправит на стандартный вывод. А вот если ей не указать ни одного входного файла, то
команда будет читать стандартный ввод. То есть, если команде cat не указать ни одного входного
файла, но при этом переназначить вывод (символом «больше»), то в это файл будет записано то, что
Вы наберёте на клавиатуре. Чтобы сказать, что уже хватит, и ввод с клавиатуры закончен, надо
нажать одновременно клавиши Ctrl и D, это по традиции записывается ^D.
По традиции первой на любом языке программирования пишут программу, которая выдаёт
что-нибудь вроде “Hello, world!”. Простейшим средством shell для того, чтобы что-нибудь «напечатать на экран», является команда echo, которая просто повторяет то, что записано после неё в аргументах (будьте осторожны со знаками препинания: восклицательный знак, точка с запятой и тому
подобные символы для shell имеют специальное значение, так что эффект от них может быть
неожиданным).
Таким образом, для практического освоения всего этого материала теперь предлагается до
конца занятия…
Во-первых с помощью команды cat создать файл из двух 5 строчек, примерно так:
cat >myprog
#!/bin/sh
echo Hello
^D
Теперь хорошо бы проверить результат с помощью команды ls, и просмотреть содержимое
файла (подумайте, как это можно сделать, я уже рассказал о соответствующем средстве, хотя и не
рекламировал, что им это можно сделать).
Во-вторых, сделать файл выполняемым с помощью команды chmod (предварительно,
конечно же, рассчитав новую маску доступа), и проверить результат с помощью ls.
Ну и наконец, выполнить получившуюся программу, подсунув имя файла системе как
команду; если файл назван myprog, то команда будет выглядеть как 6
./myprog

5

Про первую строчку на первом занятии достаточно запомнить, что «так надо», хотя вообще-то эта строчка не просто
магический заголовок, а построена по правилам: комментарии в shell начинаются с символа #, а вот если в самом начале
файла встречается комментарий, начинающийся с #!, то потом идёт абсолютный путь к той программе, которая должна
выполнить файл. Таким образом можно вместо стандартного shell-а указать более продвинутый, или вообще язык
программирования Perl, если это нужно.
6
Возможно тут потребуется объяснить, зачем нужен префикс ./ (точка-слэш), но если не будет вопросов, то объяснение и
рассказ о том, почему его не было раньше, откуда он взялся, и как от него избавиться быстро или аккуратно —может
быть лучше этот рассказ отложить на третье занятие, чтобы связать с переменной PATH.
Второе занятие: редактор vi
Наверное вы на прошлом занятии уже оценили, что создавать программы командой cat не
слишком удобно: даже две строчки набрать без единой ошибки — и то может быть непросто, если же
строчек пара тысяч, то это практически нереально. Хотелось бы уметь исправлять ошибки ввода.
Естественно, для этой цели придуманы специальные программы, которые называются «текстовый
редактор». В принципе это не должно быть новостью: даже если вы не слышали именно этих слов, то
всё равно вряд ли могли обойтись без какого-нибудь текстового редактора, изучая программирование
на первом курсе.
Фактическим стандартом в UNIX является текстовый редактор vi (или vim), и с ним та же
история, что и с command line interface-ом: по сравнению с современными текстовыми редакторами
vi выглядит, мягко выражаясь, непривычно, но так или иначе, именно он стал стандартом. (У vi есть
возможности, за которые ему можно многое простить, в первую очередь поиск и замена с использованием регулярных выражений, но, увы и ах, в рамках наших занятий на них просто не хватит
времени; интересующимся рекомендую самостоятельно заглянуть в man.) В принципе, в UNIX
можно работать и по-другому, половина моих коллег на работе начинала с того, что приносила с
собой и собирала с исходных текстов свой любимый редактор для UNIX. Так тоже можно. Опять же,
на заре своей карьеры я на каждой новой системе разучивал новый текстовый редактор, но с
некоторого раза мне это надоело и после того, как я выучил vi, у меня такой надобности не возникало.
Чтобы понять, почему vi устроен так, а не иначе, полезно вспомнить обстановку, в которой
его сочиняли: разнообразные терминалы, начиная с электрической пишущей машинки. Вообще-то vi
не предназначен для электрической пишущей машинки, для этого есть другой более старый редактор,
а вот любое устройство с электронно-лучевой трубкой (или аналогом) vi обязан был уметь обслуживать. При этом на клавиатуре как правило присутствовали клавиши Shift и Ctrl, а вот насчёт всех
остальных — никаких гарантий, даже стрелок могло не оказаться, а уж функциональные клавиши,
как на современной клавиатуре — вообще роскошь. Из-за таких ограничений у vi есть особенность,
которой нет у современных редакторов: режимы работы (и режимов этих примерно два с половиной).
В одном из режимов, так называемом режиме ввода, алфавитно-цифровые клавиши просто запоминаются в файле — так работают современные редакторы. Но основным для vi является другой, так называемый командный режим, в котором те же самые алфавитно-цифровые клавиши являются
командами редактору (например, что-нибудь удалить), сами клавиши не отображаются на экране,
виден только результат. (Есть старая программистская шутка про похожий редактор: заранее угадать,
во что превратится файл, если набрать свою фамилию как команду.) Наконец, есть особая разновидность командного режима, в котором vi изображает из себя тот старый редактор, который умел работать даже с электрической пишущей машинкой, часть возможностей vi доступна только в таком
режиме. Такой режим имитации начинается с ввода двоеточия, при этом курсор перемещается в нижний левый угол, и (в отличие от основного командного режима) можно видеть набранную команду
(что удобно); команда выполняется после нажатия клавиши Enter.
Малый джентельменский набор команд vi состоит из следующего.
Чтобы начать редактировать какой-то файл наберите команду
vi имя-файла
Если такого файла нет, то vi его создаст.
Прежде, чем в программу заходить, хорошо бы знать, как из неё выйти. Выход из vi —
команда (в режиме эмуляции)
:q↵
от слова quit, символом ↵ обозначен Enter. При таком выходе из редактора были бы забыты все изменения в файле, которые вы успели наредактировать, если они есть, то редактор откажется выходить и
напечатает диагностику со смыслом, дескать, были изменения, и вся эта работа пропадёт, как же так?
Если вы хотите именно этого, то есть в файле получилась полная ерунда, не стоящая запоминания, то
надо сказать об этом vi (чтоб выходил и не умничал), указав восклицательный знак:
:q!↵
Но обычно всё-таки в результате редактирования получается что-нибудь нужное, и это
нужное надо сохранить-запомнить. Это делается командой
:x↵
от слова exit. То же самое делает команда основного режима
ZZ
(надо набрать два Z-большое подряд, хотя их и не видно на экране).
Команды h j k l (в основном командном режиме) работают как стрелки влево, вниз, вверх и
вправо (←↓↑→) соответственно. Найти терминал без клавиш со стрелками сейчас вряд ли получится,
но всё-таки эти команды могут пригодиться, если попадутся терминал и vi, которые не понимают
друг друга (редко, но бывало). Чаще (по моему опыту) встречается ситуация, когда редактор не знает
о клавишах листания страниц (PgDn/PgUp), в таком случае их можно заменить командами ^F (Ctrl+F,
от слова forward) и ^B (Ctrl+B, от слова backward). (Кстати, есть ещё команды «слово вперёд» w и
«слово назад» b, но в малый джентельменский набор они не входят.)
Так перемещаться по тексту можно, но не всегда удобно: если компилятор пожаловался на
ошибку в 1157-й строке, то нажать стрелку вниз нужное число раз (и не ошибиться при этом) —
занятие довольно утомительное. Чтобы перемещаться по номеру строки придумана команда G (то
есть go to), но сначала придётся выучить ещё одну новую деталь: команды vi могут иметь числовой
аргумент; если набрать какое-нибудь десятичное число, то (хотя его не будет видно на экране) это
число будет передано следующей команде. Как правило число указывает, сколько раз надо команду
повторить, а если число не указано, то это означает единицу. То есть, например, если вместо
«простой» стрелки набрать 9→, то курсор подвинется влево на девять символов. Команда G является
исключением из обоих этих правил: аргумент означает номер строки, а команда G без аргументов
перемещается на последнюю строку файла (как вы думаете, почему не первую?)
Чтобы перемещаться по тексту файла, надо для начала этот текст сделать.
Для перехода в режим ввода можно использовать как минимум следующие команды:
a c i o
A C I O
Разница между большими и малыми буквами здесь в том, что большие буквы делают дополнительную работу, например, если по команде a (от слова append) текст будет вводиться после
текущего положения курсора, то команда A передвинет курсор в конец строки, а потом сделает то же,
что и a (то есть A добавляет текст в конец строки). Аналогично, команда i (то есть insert) включит
режим ввода перед текущим положением курсора (это аналог общепринятого сейчас в других местах
режима ввода, так что и команда из самых популярных), по сравнению с ней команда I передвинет
курсор в начало строки, потом включит режим ввода. Вообще изо всего набора из восьми команд мне
обычно нужны только три: i, A и С. На устаревших системах могут потребоваться ещё команды o
или O (от слова open); дело в том, что современные версии vi адекватно реагируют на Enter в режиме
ввода и создают новую строчку, но так сложилась не сразу, и если вдруг попадётся редактор, который этого не умеет, то новые строки придётся создавать специально для того предназначенной
командой.
Выход из режима ввода — команда Esc.
Удаление информации делается в командном режиме командами x — удалить один символ,
dw — удалить слово (команда состоит из двух букв) или dd — удалить одну строку. Если нужно
удалить много строк, то можно использовать числовой аргумент, но обычно бывает удобней
воспользоваться режимом имитации и командой d. Например, команда
:3,157d↵
удалит строчки с третьей по сто пятьдесят седьмую. Символ $ в этом месте обозначает последнюю
строку файла, так что команда
:1,$d↵
удалит содержимое файла полностью.
Чтобы не запутаться в номерах, полезно сначала сделать видимой нумерацию строк командой
:set nu↵
(или, если без сокращений :set number).
Копирование информации в vi сделано способом, который был в моде довольно давно и сейчас выглядит непривычно. Информация, которая удаляется в основном командном режиме, не пропадает сразу, а запоминается в неком внутреннем «кармане», и потом содержимое этого внутреннего
кармана можно воспроизвести командами p или P (от слова paste); разница между ними в том, помещают они информацию после или до текущего положения курсора. Так, например, комбинация xp
меняет местами два символа. Если нужно скопировать несколько строчек, то придётся сначала их
удалить (только командой dd с аргументом), потом вернуть обратно командой P, и только потом
переместить курсор и наконец-то сделать нужную копию.
Бывают ситуации, когда нужно что-то найти в большом файле, например, известно имя
функции, но не известен номер строки, в которой она написана. Для поиска придумана команда
/образец для поиска/↵
Стоит иметь в виду, что образцы для поиска — это не просто текст, а так называемые
регулярные выражения, так что символы . (точка), *, $, ^ и им подобные могут работать совсем не
так, как вы ожидаете. Впрочем, с именем C-шной функции сюрпризов быть не должно.
Команда / ищет информацию «вперёд» (сверху вниз). Для поиска информации в обратном
направлении можно использовать аналогичную команду
?образец для поиска?↵
Напоследок несколько команд, которые непонятно, как уложить в классификацию, но они
полезны:
Команда D удаляет информацию от текущего положения курсора до конца строки.
Команда J склеивает вместе две строчки.
Команды 0 (ноль) 7 или $ перемещают курсор в начало или конец строки соответственно.
Команда % делает совсем смешную штуку — ищет парную скобку. То есть если курсор стоит
на скобке, неважно, открывающей или закрывающей, круглой или фигурной, то по этой команде
курсор будет передвинут на соответствующую ей скобку, если такая есть — бывает удобно
проверить, правильно ли расставлены скобки в программе, не доводя до компилятора.
Отмена предыдущей команды :u↵
Для практического освоения этого материала предлагается за оставшееся от занятия время при
помощи vi изменить программу, написанную на прошлом занятии, так, чтобы:
1) она выводила другой текст;
2) она выводила текст другим цветом при помощи escape-последовательностей 8 ;
3) задача повышенной сложности: при помощи цикла for со следующего занятия вывести
все возможные комбинации цвета текста и фона.

7
8

Да, ноль — это команда, а не аргумент. Догадайтесь, почему.
Основной подвох будет в том, чтобы запомнить в файле сам символ escape — используйте Ctrl+V.
Приложение: управляющие коды ANSI для терминалов.
Все управляющие коды начинаются с последовательности двух байт esc[, где комбинацией
e
sc обозначен единственный символ escape с восьмеричным кодом 033 (не имеющий печатного
изображения).
e

sc[m

возврат (ранее измененных) атрибутов текста к умалчиваемому значению (как правило
белым по черному).

e

sc[1m

жирный шрифт, реально отображается увеличенной яркостью текста.

e

sc[3?m

установка цвета текста, вместо ? подставляется цифра от 0 до 7.

e

sc[4?m

установка цвета фона текста, вместо ? подставляется цифра от 0 до 7.

e

sc[5m

моргающий текст.

Эти команды можно комбинировать, например esc[44;31;1m - это яркий красный текст на
голубом фоне.
e

sc[y;xH

e

sc[J

e

sc[A

вверх.

e

sc[B

вниз.

e

sc[С

вправо.

e

sc[D

установка курсора в заданную позицию (вместо x и y подставляются нужные координаты);
верхний левый угол имеет координаты 1,1. Сокращенный вариант команды esc[H
устанавливает курсор в верхний левый угол.

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

влево.
Общепринятым названием для терминалов такого типа является ansi, хотя в каждом
конкретном случае это может оказаться что-то иное (console, dtterm, vt340, и т.п.).
В данной сводке перечислен минимум команд; практически все существующие ANSI-терминалы поддерживают другие полезные возможности, однако набор этих возможностей меняется от
терминала к терминалу, так что лучше ими не пользоваться для решения учебных задач. Для более
полного понимания проблемы см. описания (man) разделов curses, termcap и terminfo.
Третье занятие: азы программирования shell
Хотя основное назначение shell — выполнять команды с клавиатуры, можно набор команд
записать в файл, и shell будет их выполнять по мере чтения — это называется прямой интерпретацией. Если к этому добавить несколько деталей, то получится более-менее полноценный 9 язык
программирования.
Как и раньше, и всё по тем же причинам, я буду рассказывать про самый старый и самый
традиционный shell 10 .

Переменные.
Как во всяком уважающем себя языке программирования, в shell есть переменные. В отличие
от более уважающих себя языков все переменные только одного типа — это строки. Даже если
заставить shell выполнять арифметические операции, то сначала входные данные будут из строк
преобразованы в числа, а после вычислений числа переведены обратно в строки. Понятно, что
работает это не слишком быстро (ну не для матфизики он придуман).
Переменная возникает, если ей присвоить значение инструкцией (сюрприз!) присваивания,
например так:
NAME1=value
Выглядит вполне традиционно, но возможен подвох, в отличие хоть от того же C, вокруг
знака равенства нельзя ставить пробелы (это было бы воспринято как команда с именем — в этом
примере — NAME1, и вряд ли shell такую команду найдёт).
Чтобы использовать значение переменной, надо приписать к нему слева знак $. Например,
команда
echo $NAME1
напечатала бы (в нашем случае) слово value.
Имя переменной можно брать в фигурные скобки (например так: echo ${NAME1}). Бывают
ситуации, когда имя переменной нужно брать в скобки. Например, захотите Вы приписать к
значению переменной цифру 2 справа примерно так:
NAME2=$NAME12
понятно, что shell попытается найти переменную NAME12, и даже если найдёт, это не то, что имелось
в виду. Вот в подобных случаях помогают скобки:
NAME2=${NAME1}2
Внутри себя shell использует множество переменных для собственных нужд. Сейчас их можно
посмотреть командой env. (Обратите внимание на слово «сейчас» — в традиционном shell-е такой
команды нет.) Изо всего этого набора на первый случай стоит обратить внимание на две переменных:
Переменная с именем TERM содержит некое условное имя терминала. (Посмотрите, какое
именно.) Значение этой переменной потребуется для решения некоторых задач из задания (чтобы
отличить алфавитно-цифровой интерфейс от графического).
Переменная по имени PATH (посмотрите её значение) содержит список директорий, разделённый двоеточиями, в которых shell будет искать команды для выполнения (например выполняемый файл команды ls живёт в /bin). Программа, написанная на первом занятии, могла показаться
не совсем настоящей, потому что для её запуска нужно было приписывать префикс ./ (точка-слэш),
так вот дело не в программе, а в настройках среды. Самый простой (хотя и не самый правильный)
способ сделать самодельную команду «настоящей» — добавить к переменной PATH символ текущей
директории — точку (чтобы UNIX вёл себя как DOS или MS Windows). Подумайте, как эту точку
добавить попроще.
Кроме таких переменных традиционного типа у shell есть ещё набор квазипеременных, имя
которых состоит из одного символа, и это не буква! Самые популярные из таких специальных
переменных — это, наверное, переменные с «именами» из одной цифры, которые обозначают
параметры команды.

9

Насколько именно полноценный — вопрос, конечно, интересный. Не знаю, можно ли на shell написать модель машины
Тьюринга или перемножение матриц, но даже если и можно, то это задача для настоящих э… энтузиастов.
10
Интересно было бы прикинуть, так ли уж велик шанс сегодня встретиться с настолько старыми системами, про
которые я рассказываю. Не возьмусь назвать процент, но в прошлом году мой хороший знакомый Сергей Вакуленко
оживил как раз такую старую систему на новых микроконтроллерах. Дело в том, что микроконтроллеры хотя и новые, но
дешёвые настолько, что возможностей аппаратуры не хватает для Linux, а вот UNIX образца годов 70х – 80х вполне себе
живёт. Так что вот прямо сейчас этот шанс растёт.
Например, если бы команда ls была написана на shell (вообще-то это не так от слова
«совсем», но например), то после вызова ls -l переменная $1 указывала бы на строчку –l. Если
написать обращение подлиннее, например ls -l –a /usr, то соответствие стало бы таким:
$1 → -l
$2 → -a
$3 → /usr
Содержимое $0 указывает на выполняемый файл, из которого команда была запущена (в
нашем примере /bin/ls). Вообще механизм передачи параметров из командной строки в shell
такой же, как и в C (вспоминайте аргументы функции main!), только иначе оформлен, что впрочем
неудивительно, поскольку shell написан на C.
Значение переменной $# — это общее число параметров в командной строке.
Не видите ли Вы тут какого-нибудь подвоха? Что будет, если аргументов-ключиков больше 9,
как достать до десятого?
На самом деле способов больше одного:
Во-первых, можно использовать специальные переменные $* или $@, которые содержат все
аргументы чохом, сколько их ни есть (точную разницу между этими двумя переменными пожалуйста
посмотрите в man-е самостоятельно).
Во-вторых, предусмотрена специальная команда shift, которая передвигает аргументы по
цепочке: в переменной $1 оказывается значение, которое раньше было $2 (а прежнее значение $1
забывается), на месте $2 оказывается то, что было $3, и так далее — на месте $9 появится ранее
недоступный десятый аргумент.

Метасимволы.
Большинство символов на клавиатуре (буквы и цифры) остаются самими собой и передаются
программе как есть, но другие, более заковыристые символы, могут привести к тому, что shell
сделает что-нибудь особенное (изменит командную строчку), а сами такие символы программа на
shell даже и не увидит.
Вам уже известно больше одного такого символа, как вы думаете, какие именно?
Во-вторых, естественно, символ $. А во-первых символы переназначения ввода-вывода < | >,
про которые шла речь на первом занятии. Вообще-то таких символов больше, чем учебного времени,
чтобы про них рассказать, а те из метасимволов, которые скорее всего потребуются для решения
задания, следующие:
Символы * и ? вызывают сопоставление с именами файлов: если встречается строчка с этими
символами, то shell пытается её заменить на перечень всех имён файлов 11 , соответствующих строчке
(если такие есть), причём символ ? соответствует любому одному символу, а * любой строчке, в том
числе пустой. (В принципе этот механизм вам должен быть уже знаком, современный MS Windows с
именами файлов работает аналогично.) Примеры: одиночный символ * будет заменён на перечень
всех имён в текущей директории, строчка z* будет заменена на имена всех файлов, начинающихся с
z, а строчка /bin/* будет заменена на содержимое директории /bin. Если хочется увидеть исходники C-шной программы, то для этого подходит шаблон *.c, для заголовочных файлов подойдёт
шаблон *.h, а если хочется увидеть вообще все C-шные тексты, то можно попробовать шаблон *.?,
но при этом есть риск зацепить скомпилированные объектные файлы (которые в UNIX заканчиваются на .o).
Бывают ситуации, когда хочется метасимволы всё-таки оставить самими собой, передать в
программу точку с запятой или вопросительный знак, а не то, что из него получится. «Лобовой» способ отменить специальное значение метасимвола — это, как говорится, «заэкранировать» его
значение, написав перед ним обратную косую черту: ?. Чтобы отменить специальное значение обратной косой черты, надо её написать дважды (ничего не напоминает?) Это, наверное, самый
надёжный способ, но не самый удобный: некоторые строчки могут анализироваться shell-ом несколько раз, чтобы на выходе получилась обратная косая черта, на входе их должно оказаться… много, в
общем, в геометрической прогрессии. Поэтому другой способ — это взять строчку в кавычки, одинарные или двойные. Как вы думаете, зачем предусмотрены две разновидности кавычек? Один ответ
достаточно понятен, специальное значение кавычек тоже ведь может захотеться отменить. Второй
смысл угадать вряд ли получится: разные кавычки работают всё-таки немного по-разному, внутри
11

Кроме имён, начинающихся с точки. Ну вот так было придумано. Если нужны имена, начинающиеся с точки, то для
них надо написать отдельный шаблон, начинающийся с точки.
двойных кавычек символ $ сохраняет специальное значение, то есть подставляются значения
переменных.
Если внимательно присмотреться, то найдётся ещё и третий тип кавычек: одинарные обратные
(в верхнем левом углу клавиатуры), их значение совсем не похоже на предыдущие: в обратных
кавычках пишется команда, а стандартный вывод этой команды превращается в строку. Например,
предписание присваивания
FILES=`ls`
запомнит в переменной FILES все имена файлов в текущей директории (только пожалуйста не
используйте ls в обратных кавычках для решения задания — то же самое можно сделать гораздо,
гораздо эффективней, а главное — проще).

Управляющие конструкции
Прежде, чем обсуждать инструкции if, while и им подобные, хорошо бы вспомнить понятие
кода возврата: любой процесс в UNIX, когда завершается, сообщает операционной системе некое
целое число. По соглашению, код возврата ноль говорит о том, что всё хорошо, любые другие коды
возврата означают, что что-то не так (разные номера могут означать разные ошибки).
Условное предписание выглядит следующим образом:
if условие
then
какие-то команды
else
другие команды
fi
Была когда-то мода заканчивать инструкции теми же словами, которыми они начинались,
только задом наперёд. И вот отголоском этой моды if заканчивается на fi. Естественным образом,
если условие выполнено, то выполняется набор команд после слова then, а иначе после слова else,
и часть else можно пропустить, если она не нужна. Ключевой момент в том, что такое условие.
Условие — это команда, и если она завершилась нормально (вернула ноль), то это означает «да». Уж
не знаю, поможет или окончательно запутает сравнение с языком C (но знать об этом приходится): в
языке C ноль — это false, «нет»; то есть проверка условия if в shell-е и C устроены наоборот.
Стоит запомнить, что условием может быть любая команда — это может потребоваться для
решения задания.
Хотя эта команда и может быть любой, в 90 с лишним процентах случаев после if стоит
команда test, специально придуманная для проверки всяческих условий. Полный набор её
возможностей пожалуйста изучите самостоятельно (из man), для примера вот условие, которое
проверят, является ли текущая директория директорией (это условие может не выполниться —
подумайте, как такое возможно):
test –d .
В современных версиях shell-а обычно есть синоним команде test — одна или две открывающие скобки, это выглядит гораздо приятнее (if [ -d . ]; then), но стоит помнить, что это всё
тот же старый test, чтобы не пропустить нужные пробелы, знать, куда смотреть в man или чем её
заменить, если попалась старая система.
Хотя в команде test предусмотрен набор операций для сравнения строк, часто строки удобней
анализировать специально для того придуманной инструкцией выбора case-esac:
case строчка in
образец) набор команд ;;
другой образец) другой
набор
команд
;;
… и так далее …
esac
Разберём эту конструкцию на детали. После ключевого слова case присутствует строчка, которая затем будет сравниваться с образцами; обычно в это месте используется значение переменной,
например $1, но строчка может быть получена и каким-нибудь более сложным способом, например,
в результате выполнения команды (вроде `uname`).
Образец устроен примерно так же, как шаблоны имён файлов, но кроме вопроса и звёздочки
здесь можно использовать квадратные скобки: внутри пары квадратных скобок перечисляется всё то,
что имеет право встретиться на месте одного символа (но если сразу после открывающей скобки
поставить «крышку» ^, то это будет, наоборот, перечень того, что встречаться не должно).
Закрывающая круглая скобка отделяет образец от команд (парной открывающей для неё, увы,
не предусмотрено), команд может быть несколько на нескольких строчках, и две точки с запятой
подряд завершают все команды для одного образца.
Обработка аргументов командной строки могла бы выглядеть примерно так:
case $1 in
-a) SMALL_A_FLAG=yes ;;
-[Zz]) ANY_CASE_Z=yes ;;
-*) обработка чего-то, начинающегося с минуса ;;
[a-z]*[0-9]) обработка чего-то, начинающегося на маленькую букву,
и заканчивающееся цифрой ;;
*.c) echo $1 is C language source code ;;
*) echo error!
exit 1 ;;
esac
Стоит пояснить, что образцы проверяются до первого совпадения (если строчка подходит под
несколько образцов, то сработает только первый из них). Поскольку со звёздочкой совпадает что
угодно, то её пишут последней, и как правило она значит, что строчка ни на что не годится, то есть
это ошибка.
Чтобы пример стал полным, хорошо бы к нему добавить команду shift (помните?) и
«завернуть» в цикл. Как правило для этого используется цикл for.
Цикл for устроен так:
for имя-переменной in список-значений
do
собственно тело цикла,
список команд
done
Почему цикл заканчивается словом done, а не od, я не знаю. Примеры:
for i in 1 2 3
do
echo $i
done
Напечатает цифры 1, 2 и 3.
for i in 1 2 zzz
do
echo $i
done
Список значений может быть разнообразным.
for name in *
do
echo $name
done
Напечатает имена файлов в текущей директории (такой очень примитивный аналог ls).
То, что циклу for нужно заранее предоставить список значений, сильно ограничивает его
возможности, и если этих возможностей не хватило, то можно использовать цикл общего вида:
while условие
do
собственно тело цикла,
список команд
done
Все элементы этой конструкции, кроме самого слова while, уже встречались раньше: тело
цикла такое же, как в for, а условие такое же, как в if.
Другие возможности
Бывают ситуации, в которых надо задать пользователю вопрос. Чтобы узнать ответ
пользователя в shell предусмотрена команда read. Опять-таки, умеет она много всякого и полный
перечень её возможностей лучше посмотреть в man, но в простейшем варианте команда
read имя-переменной
прочитает набранную на клавиатуре строчку и запомнит её в указанной переменной.
Приятной особенностью именно этого shell-а является возможность писать функции.
Определение функции в shell выглядит следующим образом:
имя-функции () {
тело функции,
список команд
}
Встретив вот такую пустую пару круглых скобок, shell понимает, что следующий набор
команд внутри фигурный скобок надо не выполнять сразу, а запомнить. Зато после того, как его
запомнили, функцию можно вызывать как любую другую команду shell. Стоит обратить внимание,
что описание параметров отсутствует; параметры доступны обычным образом через $1, … $9, они
могут быть любыми, их может быть разное число, но зато и анализировать их внутри функции надо
самостоятельно, в отличие от языков вроде Паскаля или Java, проверять ошибки компилятор не
будет.
1.
2.
3.
4.

Для практического освоения shell на остатке занятия предлагаются следующие задачи:
Написать программу, которая печатает идентификатор процесса и идентификатор родительского
процесса. Хотя это задача не столько на shell, сколько на чтение man, её надо сделать, чтобы на
следующем занятии сравнить с аналогичной C-шной программой.
Написать аналог команды echo, который печатает аргументы в столбик.
(Теперь это задача нормальной сложности.) С помощью цикла for вывести на экран все
возможные сочетания цветов текста и фона.
(Задача повышенной сложности.) Решить предыдущую задачу при помощи цикла со счётчиком — его придётся сделать из цикла while и команды expr (команду expr изучить
самостоятельно).
Приложение: примеры задач на shell 12
1.

Написать простейшую “менюшную” систему для выбора и запуска программы из заданного
списка на языке любого из UNIX shell-ов (экран раскрасить в разные цвета по вкусу).
2. Написать программу рекурсивного обхода директорий на языке любого командного интерпретатора UNUX, который это позволит. Обязательное требование - программа должна быть в одном
файле. Кроме собственно обхода директорий программа должна выполнять какой-либо “сервис”:
находить все файлы, содержащие заданное слово (с помощью команды grep), для всех файлов,
содержащих в имени большие буквы, печатать исходное имя и вариант имени со всеми
маленькими буквами и т.п.
3. По имени команды определить полный путь к исполняемому файлу (аналог команды which).
4. “Напоминалка”: написать программу, которая по достижении заданного момента времени,
выведет сообщение или запустит заданную команду.
5. Написать программу, которая для всех имен файлов из заданного списка находит имена, содержащие большие буквы и переименовывает их в имя из только маленьких букв. Указание: имена
можно обрабатывать командами tr или sed. Программа должна отличать имена файлов от имён
объектов других типов.
6. Написать программу, которая для всех имен файлов из заданного списка директорий (а при пустом списке - в текущей директории) находит имена, содержащие большие буквы и переименовывает их в имя из только маленьких букв. Указание: имена можно обрабатывать командами tr
или sed. Программа должна отличать имена файлов от имён объектов других типов.
7. Модифицировать программу из пп. 6 или 7 так, чтобы при наличии соответствующего ключа в
командной строке, она заменяла (наоборот) маленькие буквы большими.
8. Модифицировать программу из пп. 7 так, чтобы при наличии соответствующего ключа в
командной строке, она рекурсивно обрабатывала вложенные директории.
9. Написать программу сравнения содержимого двух директорий. Для файлов с совпадающими
именами сравнить также их содержимое (например командой cmp).
10. Написать программу для экспериментального определения предопределённых макросов
компилятора C. Указание: можно использовать команду strings.
11. “Умное копирование”: команда cp сохраняет не все атрибуты файла, например, теряется время
модификации. В задаче требуется написать команду, которая сохраняет максимум возможных
атрибутов файла, а в остальном полностью аналогична cp. Указание: воспользоваться утилитой
tar или cpio. (Обратите внимание, что и tar, и cpio “по умолчанию” рекурсивно обходят
поддиректории, а этого как раз НЕ требуется.)

12

Для домашнего задания.

More Related Content

What's hot

Lecture14
Lecture14Lecture14
Lecture14Muuluu
 
Архиваторы и комппьютерные вирусы
Архиваторы и комппьютерные вирусыАрхиваторы и комппьютерные вирусы
Архиваторы и комппьютерные вирусыNadinFura
 
презентация "Архиваторы"
презентация "Архиваторы"презентация "Архиваторы"
презентация "Архиваторы"Page Delited
 
присяжный Root Conf2009 Beta 1
присяжный Root Conf2009 Beta 1присяжный Root Conf2009 Beta 1
присяжный Root Conf2009 Beta 1Liudmila Li
 
процессоры
процессорыпроцессоры
процессорыttku
 
телекоммуникационные технологии
телекоммуникационные технологиителекоммуникационные технологии
телекоммуникационные технологииЕлена Ключева
 
Files folders 6 kl
Files folders 6 klFiles folders 6 kl
Files folders 6 klOlga0204
 
п о файловая система
п о файловая системап о файловая система
п о файловая системаkrasoa2009
 
Root Conf2009 Fin
Root Conf2009 FinRoot Conf2009 Fin
Root Conf2009 FinLiudmila Li
 
Os
OsOs
OsIKTO
 
презентация1
презентация1презентация1
презентация1ruslan_gorlov4
 
КОМПЬЮТЕРНОЕ ОБЕСПЕЧЕНИЕ СОВРЕМЕННОГО ОФИСА
КОМПЬЮТЕРНОЕ ОБЕСПЕЧЕНИЕ СОВРЕМЕННОГО ОФИСАКОМПЬЮТЕРНОЕ ОБЕСПЕЧЕНИЕ СОВРЕМЕННОГО ОФИСА
КОМПЬЮТЕРНОЕ ОБЕСПЕЧЕНИЕ СОВРЕМЕННОГО ОФИСАKarim
 
системное администрирование
системное администрированиесистемное администрирование
системное администрированиеsplinter408
 
P01 About OS Windows
P01 About OS WindowsP01 About OS Windows
P01 About OS Windowsavkraynyaya
 
Файлы и папки
Файлы и папкиФайлы и папки
Файлы и папкиNickEliot
 

What's hot (19)

Lecture14
Lecture14Lecture14
Lecture14
 
Архиваторы и комппьютерные вирусы
Архиваторы и комппьютерные вирусыАрхиваторы и комппьютерные вирусы
Архиваторы и комппьютерные вирусы
 
презентация "Архиваторы"
презентация "Архиваторы"презентация "Архиваторы"
презентация "Архиваторы"
 
присяжный Root Conf2009 Beta 1
присяжный Root Conf2009 Beta 1присяжный Root Conf2009 Beta 1
присяжный Root Conf2009 Beta 1
 
ос урок1
ос урок1ос урок1
ос урок1
 
процессоры
процессорыпроцессоры
процессоры
 
телекоммуникационные технологии
телекоммуникационные технологиителекоммуникационные технологии
телекоммуникационные технологии
 
Files folders 6 kl
Files folders 6 klFiles folders 6 kl
Files folders 6 kl
 
п о файловая система
п о файловая системап о файловая система
п о файловая система
 
Root Conf2009 Fin
Root Conf2009 FinRoot Conf2009 Fin
Root Conf2009 Fin
 
Os
OsOs
Os
 
презентация1
презентация1презентация1
презентация1
 
КОМПЬЮТЕРНОЕ ОБЕСПЕЧЕНИЕ СОВРЕМЕННОГО ОФИСА
КОМПЬЮТЕРНОЕ ОБЕСПЕЧЕНИЕ СОВРЕМЕННОГО ОФИСАКОМПЬЮТЕРНОЕ ОБЕСПЕЧЕНИЕ СОВРЕМЕННОГО ОФИСА
КОМПЬЮТЕРНОЕ ОБЕСПЕЧЕНИЕ СОВРЕМЕННОГО ОФИСА
 
Additional
AdditionalAdditional
Additional
 
системное администрирование
системное администрированиесистемное администрирование
системное администрирование
 
P01 About OS Windows
P01 About OS WindowsP01 About OS Windows
P01 About OS Windows
 
Файлы и папки
Файлы и папкиФайлы и папки
Файлы и папки
 
Sistema
SistemaSistema
Sistema
 
«Unicode. Ликбез»
«Unicode. Ликбез»«Unicode. Ликбез»
«Unicode. Ликбез»
 

Similar to Конспект вводных занятий практикума по ОС UNIX

Обзор операционных систем Microsoft Windows.
Обзор операционных систем Microsoft Windows.Обзор операционных систем Microsoft Windows.
Обзор операционных систем Microsoft Windows.aizhanzhik
 
история развития операционных систем
история развития операционных системистория развития операционных систем
история развития операционных системNickEliot
 
история развития операционных систем
история развития операционных системистория развития операционных систем
история развития операционных системNickEliot
 
Операционные системы и среды
Операционные системы и средыОперационные системы и среды
Операционные системы и средыAlexandr Konfidentsialno
 
операционная система
операционная системаоперационная система
операционная системаzodiakasp
 
операционная система
операционная системаоперационная система
операционная системаzodiakasp
 
Операционная система Windows
Операционная система WindowsОперационная система Windows
Операционная система WindowsАнна Ефремова
 
Manual Mac OS X pentru toti in limba rusa
Manual Mac OS X pentru toti in limba rusaManual Mac OS X pentru toti in limba rusa
Manual Mac OS X pentru toti in limba rusaIon Andronic
 
реферат на тему копия
реферат на тему копияреферат на тему копия
реферат на тему копияZotov Sergei
 

Similar to Конспект вводных занятий практикума по ОС UNIX (20)

Обзор операционных систем Microsoft Windows.
Обзор операционных систем Microsoft Windows.Обзор операционных систем Microsoft Windows.
Обзор операционных систем Microsoft Windows.
 
2
22
2
 
история развития операционных систем
история развития операционных системистория развития операционных систем
история развития операционных систем
 
история развития операционных систем
история развития операционных системистория развития операционных систем
история развития операционных систем
 
Операционные системы и среды
Операционные системы и средыОперационные системы и среды
Операционные системы и среды
 
11 операционная система
11 операционная система11 операционная система
11 операционная система
 
User Interface History
User Interface HistoryUser Interface History
User Interface History
 
операционная система
операционная системаоперационная система
операционная система
 
операционная система
операционная системаоперационная система
операционная система
 
лекция 3
лекция 3лекция 3
лекция 3
 
что такое компьютер
что такое компьютерчто такое компьютер
что такое компьютер
 
Кратко о Linux
Кратко о LinuxКратко о Linux
Кратко о Linux
 
Gnu linux
Gnu linuxGnu linux
Gnu linux
 
Linux
LinuxLinux
Linux
 
36 m9o
36 m9o36 m9o
36 m9o
 
лекция 2
лекция 2лекция 2
лекция 2
 
Операционная система Windows
Операционная система WindowsОперационная система Windows
Операционная система Windows
 
лекция 1
лекция 1лекция 1
лекция 1
 
Manual Mac OS X pentru toti in limba rusa
Manual Mac OS X pentru toti in limba rusaManual Mac OS X pentru toti in limba rusa
Manual Mac OS X pentru toti in limba rusa
 
реферат на тему копия
реферат на тему копияреферат на тему копия
реферат на тему копия
 

Конспект вводных занятий практикума по ОС UNIX

  • 1. Т.В. Шапорев Конспект вводных занятий практикума по ОС UNIX. Москва, 2012 Первое занятие 1 На занятиях практикума в качестве подопытного кролика будет использоваться UNIX в варианте Linux. UNIX возник в начале 70-х годов прошлого века. Согласно легенде произошло это следующим образом: в одно из подразделений Bell Laboratories поступил новый компьютер PDP. Компьютер использовался главным образом для подготовки документации. Печатающее устройство работает гораздо медленнее процессора, так что из-за однозадачной операционной системы во время печати центральный процессор практически простаивал. Чтобы в это время можно было играть в «звёздные войны», Томпсон придумал многозадачную систему, которую потом быстренько, всего-то лет за десять, довели до ума и стали распространять как UNIX V7. Вообще подобного рода исторические зарисовки могут быть очень полезными: чтобы лучше понять, почему UNIX получился именно таким, каким получился, надо представлять, в каких условиях его создавали. Итак: когда деревья и компьютеры были большими… Когда-то они были действительно большими. В вашингтонском музее вычислительной техники экскурсовод говорит замечательную фразу: «обратите внимание, слева от вас БИТЫ сумматора с нулевого по седьмой». Один бит информации — это в 40-х годах было устройство с габаритом метра полтора 2 . Это, впрочем, было задолго до меня, а лично я вполне помню БЭСМ-6, которая занимала три этажа в южном крыле лабораторного корпуса, потребляла 360 киловатт электроэнергии, для обслуживания требовались сменные бригады техников под руководством нескольких инженеров… В общем, можно прикинуть, в какие деньги обходилось обслуживание такой конструкции в западных условиях, и неудивительно, что с пользователей брали деньги за каждую секунду работы центрального процессора. (Когда в учебном классе каждому предоставляется индивидуальный компьютер с производительностью больше, чем у БЭСМ-6, этак примерно на пару порядков — это уже полный разврат, раньше такого не было.) Неудивительно, что из таких дорогих игрушек стремились выжать максимум, и, кроме того, чтобы использовать многозадачную операционную систему, к одному компьютеру подключалось много удалённых рабочих мест, так называемых терминалов. Таким терминалом могла быть электрическая пишущая машинка, а если досталось устройство с электронно-лучевой трубкой, так это, считай, повезло. Терминалы могли различаться количеством строк на экране, набором клавиш, их подключали либо напрямую, либо через модем и телефонную линию… На этом разнообразии могли одновременно работать много пользователей… А операционная система должна была более-менее эффективно обслуживать весь этот зверинец. Чтобы в системе могли одновременно работать несколько человек, систему пришлось с самого начала строить как многозадачную и многопользовательскую, и, в частности, позаботиться о том, чтобы люди не могли испортить чужую информацию (без разницы, по ошибке или по злому умыслу). Сейчас пожалуйста включите компьютеры и загрузите UNIX. На клавиатуре нажмите клавиши Ctrl, Alt и, не отпуская их, клавишу F2. Вместо красивой цветной заставки должен появиться скучный чёрный экран, на котором, ближе к левому верхнему углу, есть слово login. Таким образом система изображает старомодное алфавитно-цифровое рабочее место, «терминал», и именно этот режим будет основным на занятиях. Современный цветной интерфейс с окошками и менюшками в принципе-то удобней, проблема в том, что все эти удобства стали обычными уже после того, как сформировался стандарт UNIX, соответственно, они нестандартные. То есть каждый уважающий себя современный UNIX предоставляет интерфейс современного типа, и все такие современные интерфейсы в чём-нибудь друг от друга отличаются, каждую новую систему надо будет разучивать заново. С другой стороны, если уметь работать со старомодным алфавитно-цифровым так называемым command line interface, то худобедно с любым UNIXом можно начать работать сразу. 1 Для расчёта времени необходимо иметь в виду, что первое занятие начинается с постановки задачи, то есть обсуждаются вопросы 1) зачем вообще физику информатика, 2) каким образом будет оцениваться работа в семестре и 3) прочие правила игры — всё это здесь пропущено. 2 Не знаю почему. Уже тогда технически возможно было сделать ламповый триггер, и было бы это во всех отношениях не хуже, но… может быть просто не придумали ещё?
  • 2. Для того, чтобы различать, кто именно работает с системой, у каждого пользователя есть индивидуальная «кличка», именно её система просит ввести после приглашения login, а для того, чтобы убедиться, что это именно вы, потом система спросит секретный пароль. Выполните вход в систему, добейтесь, чтобы все получили приглашение интерпретатора команд. О людях, которые умели бы непосредственно силой мысли управлять компьютером, мне слышать не приходилось. Для взаимодействия с человеком в компьютере, в числе прочего, есть специальная программа, которая ждёт, что будет введено с клавиатуры, а потом пытается это выполнить, если может — такая программа называется интерпретатором команд (или командным интерпретатором). По традиции командные интерпретаторы в UNIX называются словом shell (оболочка). Поскольку система была рассчитана на довольно суровую аппаратуру (даже электрическую пишущую машинку), то разработчики системы экономили как могли: большинство команд UNIX — это аббревиатуры или сокращения. Команда начинает выполняться после того, как нажата клавиша Enter. Наверное самая популярная команда в UNIX — это ls, сокращение от слова list. Выполните команду ls и полюбуйтесь на содержимое текущей директории. Если хочется знать, какая директория текущая, то выполните команду pwd — это аббревиатура от print working directory. Прежде, чем рассказывать, что такое текущая директория, и зачем она нужна, надо сделать важное замечание: Большая часть того, что написано в учебнике, и вообще всё, что связано с практическими занятиями, можно извлечь из самой системы. Традиционная информационно-справочная служба в UNIX называется man (сокращение от manual). Обычно после самой команды man через пробел указывается название того, о чём нужна справка. Команда man man покАжет подсказку о себе самой. Команда man ls выдаст полное описание возможностей команды ls — посмотрите, сколько всего разного умеет эта простенькая на вид команда. Наконец, всё это примеры структуры команд в UNIX: есть собственно команда, которая может вести себя по-разному в зависимости от параметров, аргументов или ключей (все три слова в этом месте обозначают одно и то же), которые перечисляются после команды и разделяются пробелами (или табуляциями). В качестве ещё одного практически полезного примера наберите всё ту же команду ls с ключиками, то есть ls -l, и посмотрите, насколько результат отличается от предыдущего раза. Чтобы понять, что это такое возникло на экране (и не забыть про обещанную текущую директорию), придётся вести рассказ издалека — от структуры файловой системы. Если говорить о файловой системе, то, кстати, что такое файл? Надеюсь, вы помните определение «файл — это именованный набор данных». Но вообще-то, раз уж вы видите компьютер не первый раз в жизни (и даже уже получали зачёты по информатике минимум дважды), то по опыту работы (например с MS Windows) наверное помните, что файловая система имеет (в первом приближении) иерархическую древовидную структуру, а файлы бывают двух типов: собственно файлы с данными и директории 3 , которые содержат другие файлы (в том числе директории) — для первого занятия этого достаточно. Для дальнейшего нам потребуются следующие особенности файловой системы UNIX. Во-первых, все данные в UNIX организованы в ОДНО дерево. Дерево это растёт, начиная с основополагающей, так называемой корневой директории, которая всегда носит имя из единственной косой черты: / (обратите внимание на наклон черты — это так называемый «прямой слэш»). Если файл живёт не в корневой директории, а закопан поглубже, то для точного описания его положения надо перечислить все директории, которые надо пройти, чтобы до него добраться, и в том порядке, в котором их надо пройти, начиная от корня (например /usr/local/bin ...), причём в качестве разделителя используется всё та же косая черта. Такой полный путь к файлу, начиная с левой косой черты, ещё называется абсолютным. Если файл запрятан достаточно глубоко, то набирать его (на электрической пишущей машинке!) может быть довольно утомительно, но можно облегчить себе жизнь с помощью так называемого относительного пути. У каждого процесса 4 в системе есть своя любимая директория, которую он помнит, и которая называется текущей директорией. Так вот, если путь к файлу начинается с чего бы то ни было, отличного от косой черты, то считается, что слева надо приписать текущую директорию. В простейшем случае, если не было указано ни одной косой черты, то это просто имя файла в текущей директории. (Соглашение об абсолютных и относительных именах файлов 3 4 Противники англицизмов в русской речи требуют переводить directory исконно русским словом «каталог». Понятие процесса раскрывается на лекции. Если этой лекции ещё не было — придётся выкручиваться.
  • 3. поддерживается ядром системы — запомните этот факт, потому что когда мы доберёмся до языка C, соглашение останется в силе.) Теперь вернёмся к результату команды ls -l, которая сообщает содержимое текущей директории в деталях и подробностях. О каждом файле перечислены, справа налево: имя файла, время последнего изменения файла, длина файла в байтах, некоторое количество других деталей, включая кличку владельца файла, и в крайней левой позиции — магическая комбинация из десяти букв или знаков минус. В этой комбинации крайний левый символ — это тип файла, для директорий там стоит буква d, а для обычных файлов данных, что называется regular file, указан прочерк (минус). Оставшиеся девять символов называются «маской прав доступа к файлу», «полномочиями файла» и тому подобными словами. Система многопользовательская, так что надо как-то запретить хулиганам (или просто неосторожным людям) портить чужие файлы, не позволить шпионам или конкурентам подглядывать в чужие данные и т.п. Для решения этой задачи, во-первых, все пользователи системы поделены на три категории: сам владелец файла, всякие посторонние люди и (промежуточная ступень) группа владельца файла. В одну группу пользователей обычно, так сказать, «по смыслу», объединяются люди, работающие над одним проектом. Во-вторых, всё, что можно сделать с файлом, тоже сгруппировано в три категории: файлы можно читать, записывать или выполнять. (В отличие от DOS или MS Windows, где возможность выполнения файла определяется по его расширению навроде .EXE, здесь возможность выполнить файл запоминается явно отдельным признаком.) И вот в выводе команды ls -l слева после типа файла присутствуют именно эти типы доступа: группа из трех символов для прав доступа владельца файла, ещё три символа прав доступа группы владельца файла и оставшиеся три — для всех остальных. Если в группе присутствует буква r, то файл можно читать (от слова read), если буква w, то записывать (write), буква x означает разрешение выполнять файл (eXecute). Если какое-то действие для кого-то не разрешено, то вместо соответствующей буквы ставится прочерк (минус). Для того, чтобы изменить маску доступа, в системе есть команда chmod (change mode), но прежде, чем пользоваться этой командой, придётся научиться записывать маску доступа в восьмеричной форме (потому что эта форма пригодится и в языке C тоже). Маска прав доступа к файлу в UNIX — едва ли не последнее место, где сохранилась восьмеричная форма записи; она была популярна на старых системах, но сейчас вместо этого модно использовать шестнадцатеричную запись. Тем не менее, вот как раз в этом месте восьмеричная запись удобней, потому что группа из трех признаков доступа (разрешено/не разрешено) кодируется тремя битами, и три бита ровнёхонько укладываются в одну восьмеричную цифру. На всякий случай имеет смысл напомнить упрощённое правило перевода в восьмеричную систему: в группе из трех битов младший имеет вес единица, средний — двойка, старший — четвёрка, суммируются веса присутствующих признаков. Теперь надо несколько минут потренироваться в переводе: перевести в восьмеричную форму то, что выдала команда ls, потом представить, что какую-то маску надо изменить — как бы она выглядела после этого. Пример: комбинации rwxr-xr-- соответствует набор весов 421 401 400, то есть (после суммирования) восьмеричное значение 754. Нужно это вот зачем: команда chmod умеет много всякого, полный набор её возможностей лучше посмотреть в man, но в простейшем варианте это: chmod восьмеричная-маска имя-файла Команда потребуется в конце занятия. Прежде, чем менять атрибуты файла, надо иметь файл, сейчас самое время научиться создавать файлы. К сожалению, для этого потребуется достаточно длинная преамбула. Итак, каждому нормальному процессу в UNIX совершенно забесплатно, без каких-то специальных действий, что называется «по умолчанию» предоставляются три канала ввода-вывода: канал стандартного ввода, канал стандартного вывода и стандартный канал сообщений об ошибках. (В стандарте языка C они скрываются под псевдонимами stdin, stdout и stderr, так что, в принципе, они должны быть уже известны из программы первого курса.) По умолчанию канал стандартного ввода принимает информацию с клавиатуры, а оба стандартных канала вывода показывают информацию на экране. Это можно изменить. Если в командной строке написать символ < (меньше) и после него имя файла, то канал стандартного ввода будет читать информацию из указанного файла (вместо клавиатуры).
  • 4. Если в командной строке написать символ > (больше) и после него имя файла, то канал стандартного вывода будет складывать информацию в указанный файл (а не на экран). Если такого файла ещё не было, он будет создан. Если такой файл уже есть, он будет «переписан поверх», то есть старое содержимое полностью забыто, вместо него записано новое (если это разрешено маской доступа к файлу). Наконец, символ | (вертикальная черта) делает совсем смешную штуку: стандартный вывод команды слева от черты подаёт на стандартный вход команды справа. По английски это называется pipe (запомните это слово, оно ещё не раз встретится), а на русский переводится... обычно транспортёр или конвейер. Использовать это можно например, так: если команда ls печатает слишком много, так что Вы не успеваете всё рассмотреть, то можно её вывод подать на вход команде more, которая поделит его на кусочки размером в один экран: ls -l | more. Когда команда man выдаёт информацию кусочками по одному экрану, то она внутри себя использует именно этот механизм. Впрочем, сегодня нам pipe не потребуется. До торжественного финала осталось ещё две команды. Первая из них, cat, означает вовсе не кошку, это сокращение от слова конкатенация. Опятьтаки полный набор её возможностей лучше посмотреть в man, а вкратце, этой команде можно подсунуть (в аргументах) несколько имён файлов, она содержимое этих файлов «склеит» один к другому, а результат отправит на стандартный вывод. А вот если ей не указать ни одного входного файла, то команда будет читать стандартный ввод. То есть, если команде cat не указать ни одного входного файла, но при этом переназначить вывод (символом «больше»), то в это файл будет записано то, что Вы наберёте на клавиатуре. Чтобы сказать, что уже хватит, и ввод с клавиатуры закончен, надо нажать одновременно клавиши Ctrl и D, это по традиции записывается ^D. По традиции первой на любом языке программирования пишут программу, которая выдаёт что-нибудь вроде “Hello, world!”. Простейшим средством shell для того, чтобы что-нибудь «напечатать на экран», является команда echo, которая просто повторяет то, что записано после неё в аргументах (будьте осторожны со знаками препинания: восклицательный знак, точка с запятой и тому подобные символы для shell имеют специальное значение, так что эффект от них может быть неожиданным). Таким образом, для практического освоения всего этого материала теперь предлагается до конца занятия… Во-первых с помощью команды cat создать файл из двух 5 строчек, примерно так: cat >myprog #!/bin/sh echo Hello ^D Теперь хорошо бы проверить результат с помощью команды ls, и просмотреть содержимое файла (подумайте, как это можно сделать, я уже рассказал о соответствующем средстве, хотя и не рекламировал, что им это можно сделать). Во-вторых, сделать файл выполняемым с помощью команды chmod (предварительно, конечно же, рассчитав новую маску доступа), и проверить результат с помощью ls. Ну и наконец, выполнить получившуюся программу, подсунув имя файла системе как команду; если файл назван myprog, то команда будет выглядеть как 6 ./myprog 5 Про первую строчку на первом занятии достаточно запомнить, что «так надо», хотя вообще-то эта строчка не просто магический заголовок, а построена по правилам: комментарии в shell начинаются с символа #, а вот если в самом начале файла встречается комментарий, начинающийся с #!, то потом идёт абсолютный путь к той программе, которая должна выполнить файл. Таким образом можно вместо стандартного shell-а указать более продвинутый, или вообще язык программирования Perl, если это нужно. 6 Возможно тут потребуется объяснить, зачем нужен префикс ./ (точка-слэш), но если не будет вопросов, то объяснение и рассказ о том, почему его не было раньше, откуда он взялся, и как от него избавиться быстро или аккуратно —может быть лучше этот рассказ отложить на третье занятие, чтобы связать с переменной PATH.
  • 5. Второе занятие: редактор vi Наверное вы на прошлом занятии уже оценили, что создавать программы командой cat не слишком удобно: даже две строчки набрать без единой ошибки — и то может быть непросто, если же строчек пара тысяч, то это практически нереально. Хотелось бы уметь исправлять ошибки ввода. Естественно, для этой цели придуманы специальные программы, которые называются «текстовый редактор». В принципе это не должно быть новостью: даже если вы не слышали именно этих слов, то всё равно вряд ли могли обойтись без какого-нибудь текстового редактора, изучая программирование на первом курсе. Фактическим стандартом в UNIX является текстовый редактор vi (или vim), и с ним та же история, что и с command line interface-ом: по сравнению с современными текстовыми редакторами vi выглядит, мягко выражаясь, непривычно, но так или иначе, именно он стал стандартом. (У vi есть возможности, за которые ему можно многое простить, в первую очередь поиск и замена с использованием регулярных выражений, но, увы и ах, в рамках наших занятий на них просто не хватит времени; интересующимся рекомендую самостоятельно заглянуть в man.) В принципе, в UNIX можно работать и по-другому, половина моих коллег на работе начинала с того, что приносила с собой и собирала с исходных текстов свой любимый редактор для UNIX. Так тоже можно. Опять же, на заре своей карьеры я на каждой новой системе разучивал новый текстовый редактор, но с некоторого раза мне это надоело и после того, как я выучил vi, у меня такой надобности не возникало. Чтобы понять, почему vi устроен так, а не иначе, полезно вспомнить обстановку, в которой его сочиняли: разнообразные терминалы, начиная с электрической пишущей машинки. Вообще-то vi не предназначен для электрической пишущей машинки, для этого есть другой более старый редактор, а вот любое устройство с электронно-лучевой трубкой (или аналогом) vi обязан был уметь обслуживать. При этом на клавиатуре как правило присутствовали клавиши Shift и Ctrl, а вот насчёт всех остальных — никаких гарантий, даже стрелок могло не оказаться, а уж функциональные клавиши, как на современной клавиатуре — вообще роскошь. Из-за таких ограничений у vi есть особенность, которой нет у современных редакторов: режимы работы (и режимов этих примерно два с половиной). В одном из режимов, так называемом режиме ввода, алфавитно-цифровые клавиши просто запоминаются в файле — так работают современные редакторы. Но основным для vi является другой, так называемый командный режим, в котором те же самые алфавитно-цифровые клавиши являются командами редактору (например, что-нибудь удалить), сами клавиши не отображаются на экране, виден только результат. (Есть старая программистская шутка про похожий редактор: заранее угадать, во что превратится файл, если набрать свою фамилию как команду.) Наконец, есть особая разновидность командного режима, в котором vi изображает из себя тот старый редактор, который умел работать даже с электрической пишущей машинкой, часть возможностей vi доступна только в таком режиме. Такой режим имитации начинается с ввода двоеточия, при этом курсор перемещается в нижний левый угол, и (в отличие от основного командного режима) можно видеть набранную команду (что удобно); команда выполняется после нажатия клавиши Enter. Малый джентельменский набор команд vi состоит из следующего. Чтобы начать редактировать какой-то файл наберите команду vi имя-файла Если такого файла нет, то vi его создаст. Прежде, чем в программу заходить, хорошо бы знать, как из неё выйти. Выход из vi — команда (в режиме эмуляции) :q↵ от слова quit, символом ↵ обозначен Enter. При таком выходе из редактора были бы забыты все изменения в файле, которые вы успели наредактировать, если они есть, то редактор откажется выходить и напечатает диагностику со смыслом, дескать, были изменения, и вся эта работа пропадёт, как же так? Если вы хотите именно этого, то есть в файле получилась полная ерунда, не стоящая запоминания, то надо сказать об этом vi (чтоб выходил и не умничал), указав восклицательный знак: :q!↵ Но обычно всё-таки в результате редактирования получается что-нибудь нужное, и это нужное надо сохранить-запомнить. Это делается командой :x↵ от слова exit. То же самое делает команда основного режима ZZ (надо набрать два Z-большое подряд, хотя их и не видно на экране).
  • 6. Команды h j k l (в основном командном режиме) работают как стрелки влево, вниз, вверх и вправо (←↓↑→) соответственно. Найти терминал без клавиш со стрелками сейчас вряд ли получится, но всё-таки эти команды могут пригодиться, если попадутся терминал и vi, которые не понимают друг друга (редко, но бывало). Чаще (по моему опыту) встречается ситуация, когда редактор не знает о клавишах листания страниц (PgDn/PgUp), в таком случае их можно заменить командами ^F (Ctrl+F, от слова forward) и ^B (Ctrl+B, от слова backward). (Кстати, есть ещё команды «слово вперёд» w и «слово назад» b, но в малый джентельменский набор они не входят.) Так перемещаться по тексту можно, но не всегда удобно: если компилятор пожаловался на ошибку в 1157-й строке, то нажать стрелку вниз нужное число раз (и не ошибиться при этом) — занятие довольно утомительное. Чтобы перемещаться по номеру строки придумана команда G (то есть go to), но сначала придётся выучить ещё одну новую деталь: команды vi могут иметь числовой аргумент; если набрать какое-нибудь десятичное число, то (хотя его не будет видно на экране) это число будет передано следующей команде. Как правило число указывает, сколько раз надо команду повторить, а если число не указано, то это означает единицу. То есть, например, если вместо «простой» стрелки набрать 9→, то курсор подвинется влево на девять символов. Команда G является исключением из обоих этих правил: аргумент означает номер строки, а команда G без аргументов перемещается на последнюю строку файла (как вы думаете, почему не первую?) Чтобы перемещаться по тексту файла, надо для начала этот текст сделать. Для перехода в режим ввода можно использовать как минимум следующие команды: a c i o A C I O Разница между большими и малыми буквами здесь в том, что большие буквы делают дополнительную работу, например, если по команде a (от слова append) текст будет вводиться после текущего положения курсора, то команда A передвинет курсор в конец строки, а потом сделает то же, что и a (то есть A добавляет текст в конец строки). Аналогично, команда i (то есть insert) включит режим ввода перед текущим положением курсора (это аналог общепринятого сейчас в других местах режима ввода, так что и команда из самых популярных), по сравнению с ней команда I передвинет курсор в начало строки, потом включит режим ввода. Вообще изо всего набора из восьми команд мне обычно нужны только три: i, A и С. На устаревших системах могут потребоваться ещё команды o или O (от слова open); дело в том, что современные версии vi адекватно реагируют на Enter в режиме ввода и создают новую строчку, но так сложилась не сразу, и если вдруг попадётся редактор, который этого не умеет, то новые строки придётся создавать специально для того предназначенной командой. Выход из режима ввода — команда Esc. Удаление информации делается в командном режиме командами x — удалить один символ, dw — удалить слово (команда состоит из двух букв) или dd — удалить одну строку. Если нужно удалить много строк, то можно использовать числовой аргумент, но обычно бывает удобней воспользоваться режимом имитации и командой d. Например, команда :3,157d↵ удалит строчки с третьей по сто пятьдесят седьмую. Символ $ в этом месте обозначает последнюю строку файла, так что команда :1,$d↵ удалит содержимое файла полностью. Чтобы не запутаться в номерах, полезно сначала сделать видимой нумерацию строк командой :set nu↵ (или, если без сокращений :set number). Копирование информации в vi сделано способом, который был в моде довольно давно и сейчас выглядит непривычно. Информация, которая удаляется в основном командном режиме, не пропадает сразу, а запоминается в неком внутреннем «кармане», и потом содержимое этого внутреннего кармана можно воспроизвести командами p или P (от слова paste); разница между ними в том, помещают они информацию после или до текущего положения курсора. Так, например, комбинация xp меняет местами два символа. Если нужно скопировать несколько строчек, то придётся сначала их удалить (только командой dd с аргументом), потом вернуть обратно командой P, и только потом переместить курсор и наконец-то сделать нужную копию. Бывают ситуации, когда нужно что-то найти в большом файле, например, известно имя функции, но не известен номер строки, в которой она написана. Для поиска придумана команда /образец для поиска/↵
  • 7. Стоит иметь в виду, что образцы для поиска — это не просто текст, а так называемые регулярные выражения, так что символы . (точка), *, $, ^ и им подобные могут работать совсем не так, как вы ожидаете. Впрочем, с именем C-шной функции сюрпризов быть не должно. Команда / ищет информацию «вперёд» (сверху вниз). Для поиска информации в обратном направлении можно использовать аналогичную команду ?образец для поиска?↵ Напоследок несколько команд, которые непонятно, как уложить в классификацию, но они полезны: Команда D удаляет информацию от текущего положения курсора до конца строки. Команда J склеивает вместе две строчки. Команды 0 (ноль) 7 или $ перемещают курсор в начало или конец строки соответственно. Команда % делает совсем смешную штуку — ищет парную скобку. То есть если курсор стоит на скобке, неважно, открывающей или закрывающей, круглой или фигурной, то по этой команде курсор будет передвинут на соответствующую ей скобку, если такая есть — бывает удобно проверить, правильно ли расставлены скобки в программе, не доводя до компилятора. Отмена предыдущей команды :u↵ Для практического освоения этого материала предлагается за оставшееся от занятия время при помощи vi изменить программу, написанную на прошлом занятии, так, чтобы: 1) она выводила другой текст; 2) она выводила текст другим цветом при помощи escape-последовательностей 8 ; 3) задача повышенной сложности: при помощи цикла for со следующего занятия вывести все возможные комбинации цвета текста и фона. 7 8 Да, ноль — это команда, а не аргумент. Догадайтесь, почему. Основной подвох будет в том, чтобы запомнить в файле сам символ escape — используйте Ctrl+V.
  • 8. Приложение: управляющие коды ANSI для терминалов. Все управляющие коды начинаются с последовательности двух байт esc[, где комбинацией e sc обозначен единственный символ escape с восьмеричным кодом 033 (не имеющий печатного изображения). e sc[m возврат (ранее измененных) атрибутов текста к умалчиваемому значению (как правило белым по черному). e sc[1m жирный шрифт, реально отображается увеличенной яркостью текста. e sc[3?m установка цвета текста, вместо ? подставляется цифра от 0 до 7. e sc[4?m установка цвета фона текста, вместо ? подставляется цифра от 0 до 7. e sc[5m моргающий текст. Эти команды можно комбинировать, например esc[44;31;1m - это яркий красный текст на голубом фоне. e sc[y;xH e sc[J e sc[A вверх. e sc[B вниз. e sc[С вправо. e sc[D установка курсора в заданную позицию (вместо x и y подставляются нужные координаты); верхний левый угол имеет координаты 1,1. Сокращенный вариант команды esc[H устанавливает курсор в верхний левый угол. очистка экрана; какая именно порция экрана будет очищена зависит от типа терминала, поэтому рекомендуется очищать весь экран, предварительно установив курсор в верхний левый угол. Следующие коды не только управляют движением курсора на экране, но и вводятся с клавиатуры при нажатии на соответствующую клавишу (стрелку). влево. Общепринятым названием для терминалов такого типа является ansi, хотя в каждом конкретном случае это может оказаться что-то иное (console, dtterm, vt340, и т.п.). В данной сводке перечислен минимум команд; практически все существующие ANSI-терминалы поддерживают другие полезные возможности, однако набор этих возможностей меняется от терминала к терминалу, так что лучше ими не пользоваться для решения учебных задач. Для более полного понимания проблемы см. описания (man) разделов curses, termcap и terminfo.
  • 9. Третье занятие: азы программирования shell Хотя основное назначение shell — выполнять команды с клавиатуры, можно набор команд записать в файл, и shell будет их выполнять по мере чтения — это называется прямой интерпретацией. Если к этому добавить несколько деталей, то получится более-менее полноценный 9 язык программирования. Как и раньше, и всё по тем же причинам, я буду рассказывать про самый старый и самый традиционный shell 10 . Переменные. Как во всяком уважающем себя языке программирования, в shell есть переменные. В отличие от более уважающих себя языков все переменные только одного типа — это строки. Даже если заставить shell выполнять арифметические операции, то сначала входные данные будут из строк преобразованы в числа, а после вычислений числа переведены обратно в строки. Понятно, что работает это не слишком быстро (ну не для матфизики он придуман). Переменная возникает, если ей присвоить значение инструкцией (сюрприз!) присваивания, например так: NAME1=value Выглядит вполне традиционно, но возможен подвох, в отличие хоть от того же C, вокруг знака равенства нельзя ставить пробелы (это было бы воспринято как команда с именем — в этом примере — NAME1, и вряд ли shell такую команду найдёт). Чтобы использовать значение переменной, надо приписать к нему слева знак $. Например, команда echo $NAME1 напечатала бы (в нашем случае) слово value. Имя переменной можно брать в фигурные скобки (например так: echo ${NAME1}). Бывают ситуации, когда имя переменной нужно брать в скобки. Например, захотите Вы приписать к значению переменной цифру 2 справа примерно так: NAME2=$NAME12 понятно, что shell попытается найти переменную NAME12, и даже если найдёт, это не то, что имелось в виду. Вот в подобных случаях помогают скобки: NAME2=${NAME1}2 Внутри себя shell использует множество переменных для собственных нужд. Сейчас их можно посмотреть командой env. (Обратите внимание на слово «сейчас» — в традиционном shell-е такой команды нет.) Изо всего этого набора на первый случай стоит обратить внимание на две переменных: Переменная с именем TERM содержит некое условное имя терминала. (Посмотрите, какое именно.) Значение этой переменной потребуется для решения некоторых задач из задания (чтобы отличить алфавитно-цифровой интерфейс от графического). Переменная по имени PATH (посмотрите её значение) содержит список директорий, разделённый двоеточиями, в которых shell будет искать команды для выполнения (например выполняемый файл команды ls живёт в /bin). Программа, написанная на первом занятии, могла показаться не совсем настоящей, потому что для её запуска нужно было приписывать префикс ./ (точка-слэш), так вот дело не в программе, а в настройках среды. Самый простой (хотя и не самый правильный) способ сделать самодельную команду «настоящей» — добавить к переменной PATH символ текущей директории — точку (чтобы UNIX вёл себя как DOS или MS Windows). Подумайте, как эту точку добавить попроще. Кроме таких переменных традиционного типа у shell есть ещё набор квазипеременных, имя которых состоит из одного символа, и это не буква! Самые популярные из таких специальных переменных — это, наверное, переменные с «именами» из одной цифры, которые обозначают параметры команды. 9 Насколько именно полноценный — вопрос, конечно, интересный. Не знаю, можно ли на shell написать модель машины Тьюринга или перемножение матриц, но даже если и можно, то это задача для настоящих э… энтузиастов. 10 Интересно было бы прикинуть, так ли уж велик шанс сегодня встретиться с настолько старыми системами, про которые я рассказываю. Не возьмусь назвать процент, но в прошлом году мой хороший знакомый Сергей Вакуленко оживил как раз такую старую систему на новых микроконтроллерах. Дело в том, что микроконтроллеры хотя и новые, но дешёвые настолько, что возможностей аппаратуры не хватает для Linux, а вот UNIX образца годов 70х – 80х вполне себе живёт. Так что вот прямо сейчас этот шанс растёт.
  • 10. Например, если бы команда ls была написана на shell (вообще-то это не так от слова «совсем», но например), то после вызова ls -l переменная $1 указывала бы на строчку –l. Если написать обращение подлиннее, например ls -l –a /usr, то соответствие стало бы таким: $1 → -l $2 → -a $3 → /usr Содержимое $0 указывает на выполняемый файл, из которого команда была запущена (в нашем примере /bin/ls). Вообще механизм передачи параметров из командной строки в shell такой же, как и в C (вспоминайте аргументы функции main!), только иначе оформлен, что впрочем неудивительно, поскольку shell написан на C. Значение переменной $# — это общее число параметров в командной строке. Не видите ли Вы тут какого-нибудь подвоха? Что будет, если аргументов-ключиков больше 9, как достать до десятого? На самом деле способов больше одного: Во-первых, можно использовать специальные переменные $* или $@, которые содержат все аргументы чохом, сколько их ни есть (точную разницу между этими двумя переменными пожалуйста посмотрите в man-е самостоятельно). Во-вторых, предусмотрена специальная команда shift, которая передвигает аргументы по цепочке: в переменной $1 оказывается значение, которое раньше было $2 (а прежнее значение $1 забывается), на месте $2 оказывается то, что было $3, и так далее — на месте $9 появится ранее недоступный десятый аргумент. Метасимволы. Большинство символов на клавиатуре (буквы и цифры) остаются самими собой и передаются программе как есть, но другие, более заковыристые символы, могут привести к тому, что shell сделает что-нибудь особенное (изменит командную строчку), а сами такие символы программа на shell даже и не увидит. Вам уже известно больше одного такого символа, как вы думаете, какие именно? Во-вторых, естественно, символ $. А во-первых символы переназначения ввода-вывода < | >, про которые шла речь на первом занятии. Вообще-то таких символов больше, чем учебного времени, чтобы про них рассказать, а те из метасимволов, которые скорее всего потребуются для решения задания, следующие: Символы * и ? вызывают сопоставление с именами файлов: если встречается строчка с этими символами, то shell пытается её заменить на перечень всех имён файлов 11 , соответствующих строчке (если такие есть), причём символ ? соответствует любому одному символу, а * любой строчке, в том числе пустой. (В принципе этот механизм вам должен быть уже знаком, современный MS Windows с именами файлов работает аналогично.) Примеры: одиночный символ * будет заменён на перечень всех имён в текущей директории, строчка z* будет заменена на имена всех файлов, начинающихся с z, а строчка /bin/* будет заменена на содержимое директории /bin. Если хочется увидеть исходники C-шной программы, то для этого подходит шаблон *.c, для заголовочных файлов подойдёт шаблон *.h, а если хочется увидеть вообще все C-шные тексты, то можно попробовать шаблон *.?, но при этом есть риск зацепить скомпилированные объектные файлы (которые в UNIX заканчиваются на .o). Бывают ситуации, когда хочется метасимволы всё-таки оставить самими собой, передать в программу точку с запятой или вопросительный знак, а не то, что из него получится. «Лобовой» способ отменить специальное значение метасимвола — это, как говорится, «заэкранировать» его значение, написав перед ним обратную косую черту: ?. Чтобы отменить специальное значение обратной косой черты, надо её написать дважды (ничего не напоминает?) Это, наверное, самый надёжный способ, но не самый удобный: некоторые строчки могут анализироваться shell-ом несколько раз, чтобы на выходе получилась обратная косая черта, на входе их должно оказаться… много, в общем, в геометрической прогрессии. Поэтому другой способ — это взять строчку в кавычки, одинарные или двойные. Как вы думаете, зачем предусмотрены две разновидности кавычек? Один ответ достаточно понятен, специальное значение кавычек тоже ведь может захотеться отменить. Второй смысл угадать вряд ли получится: разные кавычки работают всё-таки немного по-разному, внутри 11 Кроме имён, начинающихся с точки. Ну вот так было придумано. Если нужны имена, начинающиеся с точки, то для них надо написать отдельный шаблон, начинающийся с точки.
  • 11. двойных кавычек символ $ сохраняет специальное значение, то есть подставляются значения переменных. Если внимательно присмотреться, то найдётся ещё и третий тип кавычек: одинарные обратные (в верхнем левом углу клавиатуры), их значение совсем не похоже на предыдущие: в обратных кавычках пишется команда, а стандартный вывод этой команды превращается в строку. Например, предписание присваивания FILES=`ls` запомнит в переменной FILES все имена файлов в текущей директории (только пожалуйста не используйте ls в обратных кавычках для решения задания — то же самое можно сделать гораздо, гораздо эффективней, а главное — проще). Управляющие конструкции Прежде, чем обсуждать инструкции if, while и им подобные, хорошо бы вспомнить понятие кода возврата: любой процесс в UNIX, когда завершается, сообщает операционной системе некое целое число. По соглашению, код возврата ноль говорит о том, что всё хорошо, любые другие коды возврата означают, что что-то не так (разные номера могут означать разные ошибки). Условное предписание выглядит следующим образом: if условие then какие-то команды else другие команды fi Была когда-то мода заканчивать инструкции теми же словами, которыми они начинались, только задом наперёд. И вот отголоском этой моды if заканчивается на fi. Естественным образом, если условие выполнено, то выполняется набор команд после слова then, а иначе после слова else, и часть else можно пропустить, если она не нужна. Ключевой момент в том, что такое условие. Условие — это команда, и если она завершилась нормально (вернула ноль), то это означает «да». Уж не знаю, поможет или окончательно запутает сравнение с языком C (но знать об этом приходится): в языке C ноль — это false, «нет»; то есть проверка условия if в shell-е и C устроены наоборот. Стоит запомнить, что условием может быть любая команда — это может потребоваться для решения задания. Хотя эта команда и может быть любой, в 90 с лишним процентах случаев после if стоит команда test, специально придуманная для проверки всяческих условий. Полный набор её возможностей пожалуйста изучите самостоятельно (из man), для примера вот условие, которое проверят, является ли текущая директория директорией (это условие может не выполниться — подумайте, как такое возможно): test –d . В современных версиях shell-а обычно есть синоним команде test — одна или две открывающие скобки, это выглядит гораздо приятнее (if [ -d . ]; then), но стоит помнить, что это всё тот же старый test, чтобы не пропустить нужные пробелы, знать, куда смотреть в man или чем её заменить, если попалась старая система. Хотя в команде test предусмотрен набор операций для сравнения строк, часто строки удобней анализировать специально для того придуманной инструкцией выбора case-esac: case строчка in образец) набор команд ;; другой образец) другой набор команд ;; … и так далее … esac Разберём эту конструкцию на детали. После ключевого слова case присутствует строчка, которая затем будет сравниваться с образцами; обычно в это месте используется значение переменной, например $1, но строчка может быть получена и каким-нибудь более сложным способом, например, в результате выполнения команды (вроде `uname`).
  • 12. Образец устроен примерно так же, как шаблоны имён файлов, но кроме вопроса и звёздочки здесь можно использовать квадратные скобки: внутри пары квадратных скобок перечисляется всё то, что имеет право встретиться на месте одного символа (но если сразу после открывающей скобки поставить «крышку» ^, то это будет, наоборот, перечень того, что встречаться не должно). Закрывающая круглая скобка отделяет образец от команд (парной открывающей для неё, увы, не предусмотрено), команд может быть несколько на нескольких строчках, и две точки с запятой подряд завершают все команды для одного образца. Обработка аргументов командной строки могла бы выглядеть примерно так: case $1 in -a) SMALL_A_FLAG=yes ;; -[Zz]) ANY_CASE_Z=yes ;; -*) обработка чего-то, начинающегося с минуса ;; [a-z]*[0-9]) обработка чего-то, начинающегося на маленькую букву, и заканчивающееся цифрой ;; *.c) echo $1 is C language source code ;; *) echo error! exit 1 ;; esac Стоит пояснить, что образцы проверяются до первого совпадения (если строчка подходит под несколько образцов, то сработает только первый из них). Поскольку со звёздочкой совпадает что угодно, то её пишут последней, и как правило она значит, что строчка ни на что не годится, то есть это ошибка. Чтобы пример стал полным, хорошо бы к нему добавить команду shift (помните?) и «завернуть» в цикл. Как правило для этого используется цикл for. Цикл for устроен так: for имя-переменной in список-значений do собственно тело цикла, список команд done Почему цикл заканчивается словом done, а не od, я не знаю. Примеры: for i in 1 2 3 do echo $i done Напечатает цифры 1, 2 и 3. for i in 1 2 zzz do echo $i done Список значений может быть разнообразным. for name in * do echo $name done Напечатает имена файлов в текущей директории (такой очень примитивный аналог ls). То, что циклу for нужно заранее предоставить список значений, сильно ограничивает его возможности, и если этих возможностей не хватило, то можно использовать цикл общего вида: while условие do собственно тело цикла, список команд done Все элементы этой конструкции, кроме самого слова while, уже встречались раньше: тело цикла такое же, как в for, а условие такое же, как в if.
  • 13. Другие возможности Бывают ситуации, в которых надо задать пользователю вопрос. Чтобы узнать ответ пользователя в shell предусмотрена команда read. Опять-таки, умеет она много всякого и полный перечень её возможностей лучше посмотреть в man, но в простейшем варианте команда read имя-переменной прочитает набранную на клавиатуре строчку и запомнит её в указанной переменной. Приятной особенностью именно этого shell-а является возможность писать функции. Определение функции в shell выглядит следующим образом: имя-функции () { тело функции, список команд } Встретив вот такую пустую пару круглых скобок, shell понимает, что следующий набор команд внутри фигурный скобок надо не выполнять сразу, а запомнить. Зато после того, как его запомнили, функцию можно вызывать как любую другую команду shell. Стоит обратить внимание, что описание параметров отсутствует; параметры доступны обычным образом через $1, … $9, они могут быть любыми, их может быть разное число, но зато и анализировать их внутри функции надо самостоятельно, в отличие от языков вроде Паскаля или Java, проверять ошибки компилятор не будет. 1. 2. 3. 4. Для практического освоения shell на остатке занятия предлагаются следующие задачи: Написать программу, которая печатает идентификатор процесса и идентификатор родительского процесса. Хотя это задача не столько на shell, сколько на чтение man, её надо сделать, чтобы на следующем занятии сравнить с аналогичной C-шной программой. Написать аналог команды echo, который печатает аргументы в столбик. (Теперь это задача нормальной сложности.) С помощью цикла for вывести на экран все возможные сочетания цветов текста и фона. (Задача повышенной сложности.) Решить предыдущую задачу при помощи цикла со счётчиком — его придётся сделать из цикла while и команды expr (команду expr изучить самостоятельно).
  • 14. Приложение: примеры задач на shell 12 1. Написать простейшую “менюшную” систему для выбора и запуска программы из заданного списка на языке любого из UNIX shell-ов (экран раскрасить в разные цвета по вкусу). 2. Написать программу рекурсивного обхода директорий на языке любого командного интерпретатора UNUX, который это позволит. Обязательное требование - программа должна быть в одном файле. Кроме собственно обхода директорий программа должна выполнять какой-либо “сервис”: находить все файлы, содержащие заданное слово (с помощью команды grep), для всех файлов, содержащих в имени большие буквы, печатать исходное имя и вариант имени со всеми маленькими буквами и т.п. 3. По имени команды определить полный путь к исполняемому файлу (аналог команды which). 4. “Напоминалка”: написать программу, которая по достижении заданного момента времени, выведет сообщение или запустит заданную команду. 5. Написать программу, которая для всех имен файлов из заданного списка находит имена, содержащие большие буквы и переименовывает их в имя из только маленьких букв. Указание: имена можно обрабатывать командами tr или sed. Программа должна отличать имена файлов от имён объектов других типов. 6. Написать программу, которая для всех имен файлов из заданного списка директорий (а при пустом списке - в текущей директории) находит имена, содержащие большие буквы и переименовывает их в имя из только маленьких букв. Указание: имена можно обрабатывать командами tr или sed. Программа должна отличать имена файлов от имён объектов других типов. 7. Модифицировать программу из пп. 6 или 7 так, чтобы при наличии соответствующего ключа в командной строке, она заменяла (наоборот) маленькие буквы большими. 8. Модифицировать программу из пп. 7 так, чтобы при наличии соответствующего ключа в командной строке, она рекурсивно обрабатывала вложенные директории. 9. Написать программу сравнения содержимого двух директорий. Для файлов с совпадающими именами сравнить также их содержимое (например командой cmp). 10. Написать программу для экспериментального определения предопределённых макросов компилятора C. Указание: можно использовать команду strings. 11. “Умное копирование”: команда cp сохраняет не все атрибуты файла, например, теряется время модификации. В задаче требуется написать команду, которая сохраняет максимум возможных атрибутов файла, а в остальном полностью аналогична cp. Указание: воспользоваться утилитой tar или cpio. (Обратите внимание, что и tar, и cpio “по умолчанию” рекурсивно обходят поддиректории, а этого как раз НЕ требуется.) 12 Для домашнего задания.