Uploaded by konvergo2

Учебное пособие. Основы Unix

advertisement
Учебное пособие. Основы UNIX
Аннотация
В
учебном
пособии
рассматриваются
основы
командного
интерфейса
операционных систем семейства UNIX. Большое внимание уделено практическому
использованию
команд
системы
и
возможностей
языка
программирования,
предоставляемых оболочкой shell. В пособие включены также некоторые разделы,
посвященные основам администрирования и сетевым средствам ОС. В конце каждого
раздела находятся вопросы для самоконтроля, в приложении содержится большое
количество примеров написания shell-процедур.
Пособие
адресовано
студентам,
изучающим
современные
информационные
технологии по программам бакалавриата, а также всем тем, кто хочет самостоятельно
освоить командный интерфейс ОС семейства UNIX в кратчайшие сроки.
Издание можно также использовать как краткий справочник по основам ОС UNIX.
Оглавление
Учебное пособие. Основы UNIX .................................................................................................. 1
Аннотация ....................................................................................................................................... 2
Оглавление ...................................................................................................................................... 3
Предисловие .................................................................................................................................... 6
1. Введение ...................................................................................................................................... 8
1.1. История развития и состав семейства ОС Unix .................................................... 8
1.2. Интерфейсы пользователя системы ..................................................................... 10
1.3. Архитектура ОС ..................................................................................................... 11
1.4. Процесс загрузки ................................................................................................... 14
1.5 Уровни инициализации .......................................................................................... 16
1.6. Вопросы для самоконтроля: ................................................................................. 17
2. Основы работы с ОС UNIX ..................................................................................................... 18
2.1. Основы работы с командами в консоли .............................................................. 18
2.2. Пользователи и группы ......................................................................................... 21
2.3. Вопросы для самоконтроля .................................................................................. 37
3. Файловая система ..................................................................................................................... 38
3.1. Структура системы каталогов ОС UNIX............................................................. 38
3.2. Управление каталогами ........................................................................................ 39
3.3. Управление файлами ............................................................................................. 42
3.4. Работа со ссылками ............................................................................................... 44
3.5. Перенаправление ввода-вывода ........................................................................... 47
3.6. Регулярные выражения ......................................................................................... 48
3.7. Поиск и фильтрация .............................................................................................. 49
3.8 Каналы ..................................................................................................................... 51
3.9. Вопросы для самоконтроля .................................................................................. 52
4. Права доступа ........................................................................................................................... 53
4.1. Средства управления правами доступа ............................................................... 53
4.2. Управление правами доступа к файлам и каталогам ......................................... 54
4.3. Флаги Sticky Bit и Suid .......................................................................................... 58
4.4. Списки контроля доступа ..................................................................................... 60
4.5. Вопросы для самоконтроля .................................................................................. 63
5. Процессы в UNIX ..................................................................................................................... 64
5.1. Понятие процесса .................................................................................................. 64
5.2. Состояния процесса ............................................................................................... 65
5.3. Интерфейс пользователя. Задания ....................................................................... 67
5.4. Управление приоритетами процессов ................................................................. 72
5.5. Межпроцессное взаимодействие ......................................................................... 74
5.6. Вопросы для самоконтроля .................................................................................. 78
6. Введение в shell-программирование ....................................................................................... 79
6.1. Понятие процедур.................................................................................................. 79
6.2. Shell-функции......................................................................................................... 84
6.3. Управление локальными переменными .............................................................. 91
6.4. Подстановки в языке shell..................................................................................... 93
6.5. Арифметические действия в shell-процедурах ................................................... 97
6.6. Экспортирование локальных переменных ........................................................ 100
6.7. Вопросы для самоконтроля ................................................................................ 103
7. Введение в Shell-программирование. Алгоритмы процедур ............................................. 104
7.1. Проверка условий ................................................................................................ 104
7.2. Ветвление вычислительных процессов ............................................................. 108
7.3. Построение циклов .............................................................................................. 112
7.4. Использование опций и аргументов при обращении к процедурам и
функциям ................................................................................................................................. 122
7.5. Сигналы и прерывания в процедурах и функциях ........................................... 126
7.6. Вопросы для самоконтроля ................................................................................ 129
8. Сетевые средства UNIX ......................................................................................................... 131
8.1. Стек протоколов TCP/IP ..................................................................................... 133
8.2. Простые команды ................................................................................................ 138
8.3. Удаленный сеанс работы .................................................................................... 143
8.4. Пересылка файлов между компьютерами ......................................................... 145
8.5. Вопросы для самоконтроля ................................................................................ 151
9. Управление дисковым пространством ................................................................................. 152
9.1. Управление дисками ........................................................................................... 152
9.2. Назначение и основные концепции технологии LVM ..................................... 168
9.3. Вопросы для самоконтроля ................................................................................ 184
10. Список литературы ............................................................................................................... 186
Приложение 1. Примеры Shell-процедур ................................................................................. 187
П1.1. Передача параметров в процедуру .................................................................. 187
П1.2. Работа с файлами .............................................................................................. 189
П1.3. Работа с символьными строками .................................................................... 192
П1.4. Вычисление арифметических выражений...................................................... 195
П1.5. Использование конвейеров .............................................................................. 197
П1.6. Ветвление в процедурах ................................................................................... 198
П1.7. Циклы в процедурах ......................................................................................... 202
П1.8. Процедуры с использованием таймера........................................................... 208
Предисловие
Бурное развитие
IT-технологий в
последнее время и расширение круга
пользователей информационно-вычислительных систем требуют освоения специалистами
различных средств общения с компьютерными системами. Без знания основных приемов
работы на компьютерах не может сегодня обходиться ни один специалист в области
информационных
технологий, будь
то опытный
программист или начинающий
пользователь. В последние годы все большую популярность приобретают операционные
системы семейства UNIX (или UNIX-подобные системы), такие, как, например, ОС Linux.
Несмотря на достаточно большое число изданной за последнее время учебной и
справочной литературы по операционным системам UNIX спрос на учебные пособия в
этой области не уменьшается.
Однако в силу сложности этих систем, большого объема документации и других
факторов быстро освоить такие системы начинающему пользователю достаточно трудно.
Нужно также принимать во внимание, что многие ОС UNIX разрабатываются,
поддерживаются и распространяются сообществом программистов - энтузиастов, что
неизбежно приводит к появлению многочисленных версий, особенности которых либо
вовсе не отражены в документации, либо отражены недостаточно. В то же время любая ОС
семейства UNIX построена на основе общих принципов с соблюдением соответствующих
стандартов. Это позволяет предложить любому начинающему пользователю на первом
этапе познакомиться с
основами построения UNIX, ограничиваясь минимальными
сведениями из теории без углубления в некоторые детали, и основное внимание уделить
практическому освоению командного интерфейса ОС UNIX. Такой подход полностью
оправдал себя, о чем говорит многолетний опыт преподавания соответствующей
дисциплины в НИЯУ МИФИ на кафедре «Компьютерные системы и технологии».
Предлагаемое читателю учебное пособие как раз и содержит минимально
необходимые сведения по ОС UNIX, в него включены много примеров, упражнений и
вопросов для самоконтроля. В пособии кратко изложены вопросы, освещавшиеся в
читаемых в НИЯУ МИФИ курсах «Командный интерфейс ОС UNIX», «Архитектура ОС
UNIX», «Администрирование ОС UNIX». Следует также иметь в виду, что сегодня
операционная система Linux установлена на огромное число персональных компьютеров,
владельцы которых сталкиваются с необходимостью решать не только свои прикладные
задачи, используя командный или графический интерфейс операционной системы, но
зачастую выполнять и некоторые функции администратора системы. Поэтому авторы
сочли полезным
включить в пособие минимальные сведения об администрировании
системы, а также о сетевых средствах ОС UNIX.
Пособие, прежде всего, предназначено для студентов, изучающих информационные
технологии по программам бакалавриата, а также может быть использовано всеми, кто
самостоятельно изучает основы ОС UNIX и хочет в кратчайшие сроки освоить основы
командного интерфейса этих систем. Оно может также служить кратким справочником по
основам ОС UNIX.
Авторы выражают благодарность профессору Л.Д. Забродину за предоставленную
возможность использовать при написании этой книги материалы его курса лекций и
доценту В.Д. Никитину за возможность ознакомления с документацией по одной из
версий ОС семейства UNIX и материалами практических занятий по курсу «Архитектура
ОС UNIX».
Авторы благодарны рецензентам рукописи профессору д.т.н. В.И. Перекатову и
д.т.н. В.Г. Грибунину за высказанные замечания по содержанию и оформлению книги,
которые были учтены и помогли значительно улучшить качество издания.
1. Введение
1.1. История развития и состав семейства ОС Unix
Операционные системы являются обязательной составной частью любой вычислительной
системы. Под вычислительной системой (ВС) далее будем понимать любую ассоциацию
процессоров, способных выполнять некоторую вычислительную работу. Даже простейший
персональный компьютер представляет собой многопроцессорную систему. Обычно кроме
основного центрального процессора он включает сопроцессоры для ускорения операций
определенного вида (с плавающей запятой), для выполнения операций ввода-вывода и пр.
Развитием
простейших
вычислительные
ассоциаций
системы,
являются
многомашинные
многопроцессорные
комплексы
и
параллельные
компьютерные
сети.
Операционная система в любой ВС выполняет функции организации вычислительного
процесса. Без ОС любая ВС мертва, это просто «железо». ОС — это самая инвариантная
часть ВС. Операционная система (ОС) – это комплекс программ, который обеспечивает
управление всеми аппаратными, программными средствами и всеми данными ВС.
Далее будем использовать обобщающий синоним:
ВС = Аппаратная_платформа (АП) + Программная_платформа (ОС).
На историческом этапе развития ВС было создано и имело хождение множество
операционных систем самого разного назначения и для различных архитектур ВС, и для
различной схемотехнической базы (ОС для мини- и микроЭВМ реального времени, для
больших ЕС ЭВМ, ЭЛЬБРУС и пр. пакетной обработки больших вычислительных
заданий).
Но в последние 3 десятилетия превалирующее значение получили ОС, построенные на
распространенных стандартах, совокупность которых представляет собой некоторую
операционную систему UNIX (название произошло от UNICS – Uniplexed Information and
Computing System). Решения при разработке первых версий UNIX были настолько удачны,
обладали свойствами, базовыми для расширения и построения операционных систем
самого различного назначения, что стали международными стандартами на структуру
управляющих программ ОС. Стандарты UNIX легко “ложились” на различные
архитектуры ВС и были приняты практически всеми ведущими компьютерными фирмами.
Поэтому далее мы будем изучать принципы работы с самыми различными операционными
системами, построенными по стандартам UNIX.
Целью настоящего учебного пособия является изучение командного языка UNIXподобных операционных систем, приемов использования возможностей UNIX и основ
программирования на собственном языке UNIX. Эти возможности составляют интерфейс
пользователя, работающего непосредственно за терминалом ВС при выполнении
прикладного вычислительного задания. Собственно прикладные программы имеют свой
интерфейс для доступа к ресурсам ВС – определенный набор семантических конструкций,
используемых непосредственно в теле программы – набор системных вызовов.
К настоящему времени в мире существует несколько сотен, а может быть и тысяч версий
UNIX-подобных операционных систем. Но так как все эти ОС построены на основе
единых стандартов, то далее мы будем говорить просто ОС UNIX – как некоторое
обобщенное понятие абсолютного большинства UNIX-подобных операционных систем.
Перечень наиболее известных UNIX-подобных ОС ведущих компьютерных фирм:

MS DOS, Xenix, minix;

SUN Solaris;

IBM AIX, System Y;

BSD: FreeBSD, OpenBSD, NetBSD и другие;

Linux: Ubuntu, Fedora, Gentoo, Debian, ArchLinux, RHEL и другие;

MacOS, iOS;

Android и др.
Все теоретические основы, что мы будем далее изучать, одинаковы для всех UNIXподобных операционных систем. Все изучаемые команды применимы ко всем ОС
семейства Linux, BSD, MacOS, Android, но могут отличаться в устаревших системах, таких
как MS DOS. То, что вы изучите в рамках данного учебного пособия и закрепите на
практических занятиях, позволит вам работать на любой UNIX-подобной ОС. Конечно, это
начальные, базовые сведения, но они достаточны для решения конкретных задач и
дальнейшего углубленного изучения принципов построения и функционирования
операционных систем.
Операционная система – система управляющих программ, предназначенная для
обеспечения
эффективного
управления
и
использования
ресурсов
ВС
за
счет
автоматизированного управления их работой и предоставления пользователям удобных
командных средств доступа к ресурсам ВС.
РЕСУРСЫ: процессор, дисковая память, ОП, принтеры, каналы связи, монитор,
устройства ввода-вывода информации, управляющие программы самой ОС и пр.
Различают понятия – программное обеспечение (ПО) ВС и математическое обеспечение
(МО) ВС. Последнее понятие более широкое.
Место ОС в системе математического обеспечения:

ПО = ОС + прикладные программы;

алгоритмы;

инструкции использования ПО.
1.2. Интерфейсы пользователя системы
Интерфейсы пользователя – средства для управления ресурсами ВС и вычислительными
заданиями пользователем. Операционные системы UNIX имеют ярко выраженную
иерархическую централизованную структура. В центре этой структуры – ядро ОС, выше
последовательно располагаются утилиты – тексты программ, реализующих команды и так
называемая оболочка (Shell), интерпретатор команд. Каждый слой программного
обеспечения имеет свой интерфейс с соседним (вышележащим или нижележащим) слоем.
Управляющие программы ОС осуществляют на физическом уровне управление
устройствами, данными, прерываниями.
Разновидности интерфейсов пользователя:
графический
интерфейс
предназначен для массового пользователя, уровень управления
заданиями (уровень так называемого конечного пользователя,
использующего в основном готовые программные продукты);
графический интерфейс, как правило, предоставляет возможность
пользователю использовать окна и управлять системой нажатием на
кнопки
позволяет использовать возможности ОС и ВС более гибко,
командный
интерфейс
предназначен
для
разработки
прикладных
программ
и
вычислительных заданий, управления вычислительными работами
на уровне задач, данных и устройств (уровень прикладного
программиста); командный интерфейс – средство оболочки Shell,
которая выполняет функции интерпретатора команд и собственных
операторов
программный
интерфейс
набор системных вызовов для непосредственного эффективного
управления ресурсами и вычислительными процессами на уровне
архитектуры ОС и ВС из тела системной программы (уровень
системного программиста)
1.3. Архитектура ОС
UNIX-подобные ОС создавались изначально как многопользовательские. Отсюда и
основные особенности и характеристики UNIX, обеспечивающие одновременную работу с
ВС многих пользователей:

ОС поддерживает многопользовательский доступ ко всем ресурсам ВС через
различные удаленные терминалы;

режим разделения времени центрального процессора. Каждому процессу
выделяются
определенные
интервалы
времени,
что
обеспечивает
псевдопараллельное выполнение задач;

свопирование содержимого оперативной памяти на диск позволяет работать
при сильно ограниченном объеме физической ОП. Достигается за счет
страничной организации памяти ВС;

кеширование диска – это использование части оперативной памяти ВС для
временного хранения данных с диска, что существенно ускоряет доступ к
часто используемым программам и задачам;

поддержка нескольких форматов различных файловых систем, в том числе
файловых систем ОС других типов;

возможна
организация
мультипроцессорной
параллельной
обработки
заданий;

работа на различных аппаратных платформах ВС (например, IA-32, x86_64,
SPARC, ARM);

совместимость по прикладным программам различных UNIX-подобных ОС,
а также разработанным и для других ОС (DOS, Windows XP и пр.); в
последнем
случае
с
использованием
соответствующих
программных
эмуляторов;

многозадачность
обеспечивается
независимостью
представления
и
управления в ВС как прикладными, так и системными процессами, а также
фактическим режимом разделения времени между процессами;

многочисленность командных утилит и неограниченные возможности их
наращивания;

открыты для модификаций и развития;

расширяемые функциональные возможности ядра ОС (в основном за счет
установки драйверов устройств);

единый программный и командный интерфейс;

встроенные сетевые средства, обеспечивающие интеграцию ВС в любую сеть
в качестве сервера или клиента. Обеспечиваются сетевыми службами
сетевых протоколов, файловых систем, удаленного доступа и пр.
Все свойства UNIX обеспечиваются, прежде всего, перечисленными выше принципами
построения современных операционных систем и характерными особенностями структуры
ОС семейства UNIX.
ЯДРО ОС UNIX составляют следующие управляющие программы:
Файловая система. Существенным отличием современных версий ОС UNIX от
классической структуры является наличие виртуальной файловой системы (например, в
Linux), позволяющей одновременно работать с файловыми системами различных типов
(Ext4, Proc, VFAT, NTFS и др.). Файловые системы размещаются на устройствах памяти с
блочным принципом обмена информации и используют буферную КЭШ-память
магазинного типа.
Подсистема управления процессами включает:

средства межпроцессного взаимодействия (IPC –Inter Process Communication
– сигналы, семафоры, программные каналы, сокеты, общие области
физической памяти);

супервизор управления памятью, реализующий концепцию виртуальной
памяти и наиболее эффективно использующий ресурсы физической памяти
ВС; каждый процесс выполняется в своем собственном защищенном
адресном пространстве фиксированного размера (4 Гбайт для Linux);

планировщик процессов, выбирающий из очереди процессов наиболее
приоритетный процесс и передающий ему управление на определенный квант
времени (реализует режим разделения времени).
Подсистема управления устройствами обеспечивает управление всеми устройствами
компьютера (кроме процессора и оперативной памяти). Подсистема включает драйверы
устройств с посимвольным принципом передачи информации (com-порт, параллельный
порт) и устройств с блочным принципом обмена информацией (жесткий диск, CD ROM).
Прикладные и системные программы взаимодействуют с ядром посредством системных
вызовов.
Ядро включает также программы, исполняющие функции внутренних команд ОС,
использующихся наиболее часто, и поэтому интегрированные в состав ядра.
Утилиты ОС UNIX реализуют внешние команды. Утилита – это исполняемый файл со
своим именем (имя команды), который может храниться как в системной области памяти
ОС, так и в области памяти, выделяемой пользователю. Содержимое этой памяти
описывается в соответствующих каталогах. Число утилит может быть увеличено
практически без ограничений. Тем самым обеспечивается расширяемость командного
языка ОС. Вызываются утилиты для исполнения по своему имени (имени команды).
Оболочки ОС UNIX (shell) интерпретируют имя введенной команды и вызывают для
исполнения соответствующую утилиту. В UNIX может быть установлено одновременно
несколько оболочек, например, для каждого имеющегося терминала пользователей. Строго
говоря, каждый отдельный терминал может обслуживаться несколькими оболочками, даже
оболочками
разных
типов,
обеспечивающих
отличающиеся
возможности
для
пользователей (различную СРЕДУ работы пользователя). Эта особенность структуры ОС
UNIX обеспечивает одновременную работу многих пользователей, в том числе и работу в
составе компьютерных сетей.
Так, в частности, для UNIX разработаны и имеют хождение множество типов оболочек. И
каждая из них имеет свои возможности настройки среды. Наиболее распространены
следующие оболочки:

bash – Bourne Again Shell – базовая широко используемая оболочка,
размещается в файле /usr/bin/bash;

csh – Berkeley Unix shell (C shell) – развитие sh – /usr/bin/csh;

ksh – Korn shell (по сути, это стандарт Posix) /usr/bin/ksh;

zsh – Z shell.
Для каждого пользователя при настройке ОС может быть сконфигурирована среда для
индивидуальной работы – набор команд, требуемый набор функций ОС, доступные
устройства и пр.
Функции оболочки:

интерпретирует командные строки и передает управление ядру ОС;

формирует характеристики среды (набор глобальных переменных среды);

выдает приглашение на ввод очередной команды;

генерирует имена файлов;

присваивает и подставляет значения переменных;

подставляет результаты выполнения команд;

выполняет перенаправления ввода-вывода и реализует конвейеры команд;

обеспечивает программирование на собственном языке shell и пр.
1.4. Процесс загрузки
При загрузке компьютера происходит последовательная передача управления от BIOS к
загрузчику, а от него — к ядру. Затем ядро запускает планировщик (для реализации
многозадачности) и выполняет программу init, которая настраивает пользовательское
окружение и позволяет осуществлять взаимодействие с пользователем и вход в систему.
После этого ядро переходит в состояние бездействия до тех пор, пока не получит внешний
вызов.
Во многих современных системах Linux вместо скрипта инициализации /sbin/init
используется systemd – демон инициализации других демонов. Его особенностью является
интенсивное распараллеливание запуска служб в процессе загрузки системы, что
позволяет существенно ускорить старт операционной системы.
Основные этапы загрузки:
1. BIOS выполняет загрузочные шаги, специфичные для данного аппаратного
обеспечения.
2. Когда все устройства распознаны и правильно запущены, BIOS загружает и
выполняет загрузочный код с одного из разделов заданного загрузочного
устройства,
который содержит фазу 1 загрузчика
Linux. Наиболее
популярными загрузчиками являются GRUB и LILO. Первая фаза загружает
остальной код загрузчика, который обычно спрашивает пользователя, какую
операционную систему (или вид её сессии) запустить. Код загрузчика
создаётся на основе конфигурационного файла, своего для каждого типа
загрузчика. Этот файл содержит, в частности, информацию о загрузочном
разделе и расположении ядра для каждой из таких систем, а также
дополнительные параметры загрузки, если они заданы. В результате выбора
соответствующее ядро загружается в ОЗУ, минимальная начальная файловая
система настраивается из файла-образа (initrd), а затем, вместе с
соответствующими параметрами управление передаётся новой ОС.
3. Загрузчик
зачастую
предлагает
пользователю
меню
с
доступными
вариантами загрузки. Затем он загружает ядро, которое распаковывается в
память, настраивает системные функции, такие как работа необходимого
оборудования и управление страницами памяти, после чего делает вызов
start_kernel().
4. После этого start_kernel() выполняет основную настройку системы
(прерывания, остальные функции управления памятью, инициализацию
устройств, драйверов и т. д.), а потом порождает процесс бездействия,
диспетчер и отдельно от них — процесс init (выполняющийся в
пользовательском пространстве).
5. Планировщик начинает более эффективно управлять системой, в то время
как ядро переходит к бездействию.
6. Процесс init выполняет необходимые сценарии, которые настраивают все
службы и структуры, не относящиеся к уровню ядра, в результате чего будет
создано пользовательское окружение, и пользователю будет предоставлен
экран входа в систему.
Когда происходит завершение работы, init вызывается для управляемого закрытия
программ пользовательского уровня, тоже согласно сценариям. После этого init
закрывается, а ядро производит свое собственное завершение работы.
1.5 Уровни инициализации
В процессе загрузки, после инициализации ядра, ядро запускает /sbin/init как первый
процесс пользовательского режима. Процесс init отвечает за дальнейшую загрузку
системы. Для этого он запускает так называемые стартовые скрипты, которые выполняют
проверку и монтирование файловых систем, запуск необходимых демонов, настройку ядра
(в том числе загрузку модулей ядра согласно установленному оборудованию, настройку
IP-адресов, таблиц маршрутизации и др.), запуск графической оболочки и другие действия.
В
операционных
системах
Unix
с
помощью
init
можно
изменить
уровень
инициализации. Уровень инициализации — степень загрузки операционной системы. Для
инициализации системы процесс init запускается и анализирует файл /etc/inittab.
Следует отметить, что приведенная здесь система инициализации работает на системах
Linux и Unix System V, и она несколько отличается от стиля инициализации системы в
BSD-подобных системах.
По умолчанию, в системе использовано 7 уровней инициализации:
0
остановка системы
1
загрузка в однопользовательском режиме
2
загрузка в многопользовательском режиме без поддержки сети
3
загрузка в многопользовательском режиме с поддержкой сети
4
не используется
5
загрузка в многопользовательском режиме с поддержкой сети и графического входа
в систему
6
перезагрузка
В большинстве случаев в системах Unix/Linux, узнать текущий уровень инициализации
можно командами:
$ runlevel
$ who -r
Набрав init n в терминале (с правами суперпользователя), где n — номер уровня
инициализации, можно переключиться в любой из вышеперечисленных уровней.
Стартовые скрипты для каждого уровня находятся в каталогах с /etc/rc0.d до
/etc/rc6.d, где цифра после rc соответствует номеру уровня инициализации.
1.6. Вопросы для самоконтроля:
1. Чем обусловлено распространение UNIX в последние десятилетия?
2. Назовите основные подсистемы операционных систем UNUX. Нарисуйте схему их
взаимодействия.
3. Как происходит загрузка операционной системы? В чем роль загрузчика?
4. Чем отличаются различные уровни инициализации системы и для каких целей они
используются?
2. Основы работы с ОС UNIX
2.1. Основы работы с командами в консоли
Системная консоль — это монитор и клавиатура, связанные непосредственно с системой.
Для входа в систему под несколькими учетными записями, используя один монитор и одну
клавиатуру, система обеспечивает доступ к виртуальным консолям, которые позволяют
войти в систему под несколькими именами в одно время. Сеанс работы начинается со
входа в систему, для чего пользователь должен ввести свое имя и пароль, или
авторизоваться каким-либо другим способом. Для завершения сеанса работы с системой
можно воспользоваться командой exit или сочетанием клавиш CTRL-D.
Оболочка (shell, командный интерпретатор) — это программа, которая воспринимает
введенные пользователем данные и транслирует их в системные команды. Оболочка
запускается сразу после входа пользователя в систему. Используя язык обращения к
оболочке можно создавать скрипты.
Список разрешенных оболочек размещается в файле /etc/shells. Оболочку можно
заменить с использованием специальной команды – chsh.
Обобщенный формат ввода команды в строку командного интерфейса ОС для всех типов
shell:
$ ком1 [ – опции ] [аргументы /параметры]; ком2 … <ENTER>
$ – стандартное приглашение для ввода команды в bash, ksh, sh (в csh – %), этот символ не
нужно вводить при начале набора команды.
Заканчивается набор командной строки нажатием клавиши <ENTER>, после чего команды
передаются для интерпретации и выполнения оболочкой ОС. (Далее в примерах <ENTER>
показываться не будет.)
Результат работы команд, как правило, выводится на экран дисплея – стандартного
устройства вывода. (Далее в некоторых примерах результат, выводимый на экран, может
быть прокомментирован строками текста с символом #. Комментарий не интерпретируется
shell.)
Например:
$ls; pwd
#
Здесь командная строка содержит две команды – вывод на экран листинга текущего
каталога и его полного маршрутного имени.
Все элементы командной строки набираются только маленькими символами.
Оболочки UNIX обрабатывают два вида команд:
внешние
каждой из них соответствует своя утилита, путь поиска которой при
интерпретации команды определяется переменной среды оболочки – PATH
внутренние встроенные команды в саму оболочку
Оболочка при некорректном использовании команд предоставляет возможность вывода
полной справочной информацию о команде на экран:
$man [– опции] < команда >
[SPACE] – переход на следующую страницу справочника;
[ENTER] – переход на следующую строку текущей страницы;
[q] – выход из справочника в shell.
Оболочка shell создает среду работы пользователя. Рабочая среда — это множество
переменных, к которым имеют доступ все выполняемые команды.
Начальная среда “по умолчанию” устанавливается при выполнении конфигурационного
файла /etc/profile, который формируется администратором системы и выполняется
автоматически при авторизации пользователя в системе для всех пользователей.
Пользователям этот файл недоступен, но в домашнем каталоге каждого пользователя
может быть создан файл .bash_profile, в который пользователь может внести все
дополнительные переменные, которые должны быть выставлены при авторизации
пользователя. Таким образом, осуществляется адаптация системы к конкретным
функциям, используемому оборудованию и решаемым задачам. Такие файлы по существу
являются “сценариями оболочки” (shell scripts).
Также среда индивидуально может быть настроена посредством присвоения требуемых
значений соответствующим переменным среды. Такие изменения будут действовать до
конца сеанса работы пользователя.
По сути, среда – это набор специальных системных глобальных переменных, которым
присваиваются
требуемые
значения.
Присвоенные
значения
переменных
среды
используются каждый раз, когда выполняется соответствующая функция shell. Команды
присваивания
и
сами
переменные
являются
операторами
собственного
языка
программирования shell.
Примеры переменных среды:
LOGNAME
входное имя пользователя
TERM
описание типа терминала
HOME
маршрутное имя начального («домашнего») каталога
PATH
альтернативные пути поиска утилит введенных команд
PS1
текст первичного приглашения
Для настройки среды используется команда shell:
« = » – присвоить значение указанной переменной.
Пример формирования новой среды:
$ SHELL=/usr/bin/ksh
$ HOME=/home/lev
$ EDITOR=vi
$ TERM=70092
………..
$ PS1=”hello” (по умолчанию для bash, sh, ksh = ”$” )
$ PATH=/ /
/
/
/:/ /:/
/
/
Между разделителями «:» указываются маршрутные имена в системе каталогов ОС, где
оболочкой будет осуществляться поиск утилит.
Проверить текущие параметры среды можно с помощью команды вывода на экран
значений глобальных переменных:
$ env
SHELL=
HOME=
………..
$
Имена системных глобальных переменных используют большие буквы.
Сменить оболочку можно и с помощью команды chsh.
Например:
$chsh ksh
2.2. Пользователи и группы
В
UNIX
для
каждого
пользователя
создается
учетная
запись,
позволяющая
идентифицировать пользователя при регистрации в системе и ассоциировать его с
цифровым идентификатором. При вводе имени пользователя и пароля при входе в систему,
передаче ключа или других данных для авторизации, пользователь представляется
системе, позволяя ей определить и открыть домашний каталог, выдать пользователю права
на нужные объекты в системе и подключить другие специфичные атрибуты.
Все запущенные в системе процессы и файлы хранят в своих метаданных цифровые
идентификаторы пользователей и групп, от имени которых они работают или которым
принадлежат. Именно эти идентификаторы совместно с матрицей прав доступа
определяют возможности процессов взаимодействовать друг с другом и с файлами.
Исторически учетная запись пользователя в UNIX системах храниться в файле
/etc/passwd. Каждый пользователь описывается одной строкой, состоящий из семи
полей, разделенных двоеточием:
имя_пользователя:пароль:uid:gid:комментарий:домашний_каталог:программа
ivanov:x:500:500:Ivanov M. A.:/home/ivanov:/bin/bash
Каждому пользователю соответствует набор сведений:
имя_пользователя Понятное для человека имя пользователя в системе.
Оно
используется при входе в систему, для того чтобы человек мог
идентифицировать себя.
Имя пользователя должно начинаться с буквы, и может состоять из
символов латинского алфавита, цифр, дефисов и символов
подчеркивания.
Несмотря на то, что, как и большинство имен объектов в UNIX, имя
пользователя чувствительно к регистру (то есть пользователи
Administrator и administrator в UNIX будут считаться разными
пользователями), прописные буквы в имени в данном случае
использовать
запрещено.
На
основе
имени
пользователя
формируется адрес его электронной почты, а его формат не
чувствителен к регистру.
В общем случае имя должно подходить под регулярное выражение:
[a-z_][-a-z0-9_-]*
Разные
UNIX-системы
могут
накладывать
ограничения
на
значимую длину имени. В старых версиях UNIX длина не могла
превышать 8 символов. В современных системах длина имени
может достигать 32 символов, однако для обратной совместимости
и корректного взаимодействия с общими сетевыми ресурсами
некоторые администраторы продолжают придерживаться старого
ограничения длины.
пароль
Наряду с именем, пароль используется в процессе аутентификации
пользователя.
Пароль
—
некая
известная
только
данному
пользователю информация, в данном случае некоторая секретная
строка.
В открытом виде пароль в системе не хранится. В старых версиях
UNIX в этом поле хранилась хеш-сумма соответствующая паролю.
Если поле содержит символ «x», то хеш - пароль хранится в файле
/etc/shadow.
Если поле содержит символы «*», «!» или «!!», то учетная запись
заблокирована, и пользователь не может войти в систему.
Если поле пустое, то пользователь может войти в систему без
указания пароля, если это явно не запрещено в настройках ОС.
uid
Цифровой идентификатор пользователя. Именно он, а не имя
пользователя,
используется
системой
для
определения
принадлежности и прав доступа процессов и файлов.
Для обычных пользователей uid возможно задавать в диапазоне
определенном параметрами UID_MIN и UID_MAX в файле
/etc/login.defs. Например, в RHEL значение по умолчанию
UID_MIN = 500, а UID_MAX = 60000.
uid равный 0 предназначен для суперпользователя. Любая учетная
запись независимо от значения имени и пароля, но с uid равным 0
будет считаться привилегированной и получит максимальные права
в системе.
uid в диапазоне больше 0 и меньше UID_MIN предназначены для
системных псевдо-пользователей. Псевдо-пользователи нужны для
обеспечения
безопасной
работы
системных
сервисов,
им
принадлежат некоторые файлы, и от их имени работают некоторые
системные процессы. Но вход таких пользователей в систему
должен быть заблокирован.
gid
Цифровой идентификатор основной группы пользователя.
комментарий
Поле исторически называлось GECOS, в ранних версиях UNIX
было необходимо для идентификации пользователя в операционной
системе General Electric Comprehensive Operating Supervisor. В
современных UNIX поле содержит дополнительную информацию о
пользователе, такую как: полное имя пользователя; номер рабочего
кабинета; рабочий и домашний телефон.
Пользователь может самостоятельно изменить значение этого поля
с помощью команды chfn, однако в больших организациях
изменения пользователем некоторых полей (например, полного
имени) может быть не желательно, и такая возможность должна
быть заблокирована администратором.
домашний_каталог Поле содержит полный путь к каталогу, в который автоматически
будет сделан текущим после успешного входа пользователя в
систему. Обычно пользователь является владельцем этого каталога
и имеет возможность менять его содержимое. В некоторых случаях
несколько разных пользователей (например, гостевых) могут
разделять один домашний каталог.
Если указанный каталог не существует или у пользователя нет прав
сделать его текущим, то после входа в систему в качестве текущего
каталога будет установлен корневой каталог /.
программа
Полный путь к исполняемому файлу программы, которая будет
запущена после успешного входа пользователя в систему. После
завершения
работы
этой
программы,
сессия
пользователя
завершается.
Обычно в качестве такой программы указывается командный
интерпретатор пользователя (оболочка). Например, /bin/bash.
Но в общем случае это может быть произвольная команда,
например, /bin/date. В этом случае после успешного входа в
систему, пользователь увидит на экране текущую дату и время,
после чего вновь появиться приглашения на ввод пароля.
Файл /etc/passwd должен принадлежать администратору системы — пользователю root
с uid 0, и не иметь права на запись для всех других пользователей. Так как изменения в
этом файле влияют на права и пароли пользователей. Но содержимое этого файла
используется для преобразования цифровых идентификаторов пользователей в символьное
имя учетной записи. Например, командами ls -l; who; ps -f. По этой причине файл
/etc/passwd должен быть доступен на чтения всем пользователям без дополнительной
авторизации.
# ls -l /etc/passwd
-rw-r--r--. 1 root root 909 Apr 30 02:12 /etc/passwd
В связи с этим хранение паролей в файле passwd является небезопасным. Современные
возможности вычислительной техники позволяют злоумышленнику, в разумные сроки
подобрать такую парольную фразу, хеш-сумма которой совпадает с той, которая хранится
в файле passwd, то есть фактически подобрать пароль. Особенно в том случае, если
пароль был слабым, а алгоритм хеширования простым. Существуют готовые программы
для подбора пароля по хеш-сумме, например, утилита John the Ripper.
В современных системах принято хранить хеш-сумму пароля в специальном «теневом»
файле паролей /etc/shadow, недоступном на чтение-запись никому.
# ls -l /etc/shadow
----------. 1 root root 717 Apr 30 02:13 /etc/shadow
Если этого файла не существует, и пароли все еще хранятся небезопасно в файле passwd,
то с помощью утилиты pwconv можно создать файл shadow и экспортировать пароли в
него. А с помощью утилиты pwunconv можно наоборот отказаться от файла shadow и
вернуть пароли в passwd.
Файл /etc/shadow также содержит одну строку для каждой учетной записи
пользователя, состоящую из девяти полей, разделенных двоеточием.
имя_пользователя
Имя, с которого начинается соответствующая пользователю строка
в файле /etc/passwd
пароль
Хеш-сумма пароля,
полученная с помощью функции crypt, в
виде:
$идентификатор_алгоритма$соль$хеш-сумма
где идентификатор_алгоритма определяет алгоритм, которым был
получен хеш.
идентификатор алгоритм хеширования
1
MD5
2a
Blowfish
5
SHA-256
6
SHA-512
соль — дополнительная случайная строка символов, которая
смешивается с паролем в процессе хеширования, для усложнения
атаки на хеш пароля. Наличие соли затрудняет использование
заранее подготовленных таблиц хеша, так как для одного и того же
пароля
при
разной
значение
соли
хеш-суммы
получаются
абсолютно разными.
дата смены пароля Дата последней смены пароля. Хранится в виде количество дней,
прошедших с 1-го января 1970 года до дня смены пароля. Это поля
является важным для обеспечения механизма старения пароля и
используется совместно со следующими полями. Если значения
этого поля равно 0, то это значит что пароль должен быть изменен
пользователем при следующем входе в систему, независимо от того
истек максимальный срок действия пароля или нет.
минимальный срок
действия пароля
Значения в днях, которое определяет период времени со дня смены
пароля, в течение которого пользователь не имеет право поменять
себе пароль. Этот лимит ограничивает пользователя в возможности
после принудительной смены пароля тут же вернуть себе старый
пароль.
Пустое значение поля и 0 отключают минимальный срок действия
пароля.
максимальный срок Значение в днях, которое определяет количество дней после смены
действия пароля
пароля, по истечению которых пользователь обязан сменить себе
пароль при следующем входе в систему. Если максимальный срок
действия пароля меньше чем минимальный, то пользователь не
сможет изменить свой пароль. Пустое значение поля означает
отсутствие ограничения на срок действия пароля.
период
предупреждения о
смене пароля
Число дней до истечения срока действия пароля, в течение которых
пользователь, при каждом входе в систему, будет получать
предупреждение об окончании срока действия пароля.
период
неактивности
Число дней после окончания действия пароля, в течение которых
пользователь может войти в систему со старым паролем, и
установить себе новый пароль. Если в течение этого срока
пользователь не установит новый пароль, то вход в систему будет
невозможен. Пустое значение поля означает отсутствие периода
неактивности.
дата истечения
срока действия
учетной записи
Дата, определяющая срок действия учетной записи пользователя.
Хранится в виде количество дней, прошедших с 1-го января 1970
года.
Пустое значение обозначает, что учетная запись никогда не
устаревает.
зарезервированное Это поле зарезервировано для использования в будущем, и в
поле
настоящее время игнорируется.
Пример:
ivanov:$1$U.Y6gfRa$jKQcguexspnseliBCp9ml0:16190:7:180:7:30:17045:
В данном случае для пользователя ivanov:

Метод хеширования 1 - MD5, соль — U.Y6gfRa, хеш-сумма пароля
jKQcguexspnseliBCp9ml0

Пароль был изменен 30-го апреля 2014 года.

Срок, в течение которого пользователь не сможет повторно поменять пароль –
7 дней.

По истечению 180 дней, пользователь будет обязан поменять себе пароль.

За 7 дней до истечения срока действия пароля, при каждом заходе в систему,
пользователь будет получать предупреждение о истечение срока действия
пароля.

Если в течении 30 дней пользователь не сменит пароль после его устаревания,
пользователь больше не сможет войти в систему со старым паролем.

Учетная запись будет окончательно заблокирована 1-го сентября 2016 года.
Пользователь может самостоятельно изменить свой пароль для входа в систему, используя
команду passwd. Администратор системы может задавать время жизни пароля
пользователя и допустимое количество попыток ввода пароля.
Группы пользователей
Пользователи могут быть включены в одну или более групп, для расширения прав и
совместной работы над файлами. Для описания существующих групп и членства
пользователей
в
них
используются
конфигурационные
файлы
/etc/group
и
/etc/gshadow.
Каждый пользователь состоит минимум в одной группе, название которой, как правило,
совпадает с именем пользователя, и которая создается вместе с учетной записью
пользователя.
В
дальнейшем
администратор
может
добавить
пользователя
в
неограниченное число других групп, выдав тем самым ему права доступа ко всем
ресурсам, к которым имеют доступ пользователи группы.
Для просмотра списка групп, в которых состоит пользователь, можно использовать
команду groups:
$ groups [username]
group1 group2 group3
Формат файла /etc/group:
имя_группы:хеш-сумма_пароля:GID:список_пользователей
имя_группы
Понятное для человека, символьное имя группы.
хеш-сумма_пароля
Пароль, требуемый для вхождения в группу с помощью
команды newgrp. Если поле пустое — пароль не требуется, но
команда newgrp сработает успешно только в том случая, если
пользователь явным образом включен в группу.
Если поле содержит символ «x», то сведенья о пароле
храняться в файле /etc/gshadow
GID
Цифровой идентификатор группы. Для групп-пользователей
GID возможно задавать в диапазоне определенном параметрами
GID_MIN и GID_MAX в файле /etc/login.defs.
список_пользователей разделенный
запятыми
перечень
имен
пользователей,
дополнительно включенных в эту группу. Обычно тут не
дублируется информация об основной группе пользователя,
указанной
в
четвертом
поле
учетной
записи
в
файле
/etc/passwd
Формат файла /etc/gshadow:
имя_группы:пароль:администраторы_группы:список_пользователей
Понятное
имя_группы
для
человека,
символьное
имя
группы,
соответствующие записи в файле /etc/group
Пароль, требуемый для вхождения в группу с помощью
хеш-сумма_пароля
команды newgrp. Это может потребоваться, что бы стать
членом группы не будучи явным образом в нее включенным,
но зная пароль.
администраторы_группы разделенный запятыми список пользователей, имеющих
возможность с помощью команды gpasswd устанавливать
пароль на группу, а также управлять членством других
пользователей в этой группе.
список_пользователей
разделенный
запятыми
перечень
имен
пользователей,
дополнительно включенных в эту группу.
Создание, удаление и изменение учетных записей
Для создания новых учетных записей пользователей можно использовать одну из
следующих
команд:
useradd,
adduser
или
newusers.
Также
возможно
отредактировать файлы passwd и shadow, добавив в них соответствующие строки.
Наиболее общей командой для большинства UNIX-подобных систем является команда
useradd. Единственным обязательным аргументом команды является имя создаваемой
учетной записи, то есть то имя, которое будет использовать пользователь при входе в
систему. Настройки по умолчанию для остальных параметров
учетной записи
определяются в файлах /etc/default/useradd и дополнительно для linux-системах в
/etc/login.defs.
Пример:
# useradd student
# grep student /etc/passwd
student:x:501:501::/home/student:/bin/bash
# grep student /etc/shadow
student:!!:16190:0:99999:7:::
# ls -ld /home/student/
drwx------. 2 student student 4096 Apr 30 05:23 /home/student/
Основные опции команды useradd:
-p PASS
хеш-сумма
пароля.
Если
ключ
не
задан,
то
учетная
запись
заблокирована до установки пароля командой passwd
-u UID
цифровой идентификатор пользователя. По
умолчанию команда
проверяет, что его значение уникально и лежит в диапазоне от
UID_MIN до UID_MAX. Если есть необходимость создать системного
псевдо-пользователя с uid меньше UID_MIN, то совместно с ключом -u
необходимо использовать ключ -r. Для создания учетной записи с не
уникальным uid, необходимо также использовать ключ -o
-g GID
цифровой идентификатор или имя основной группы пользователя. Если
ключ не задан, то:
1) если указан ключ -N или параметр USERGROUPS_ENAB в файле
login.defs определен в значение no, то в значения gid основной
группы
определяет
параметр
GROUP
в
файле
/etc/default/useradd
2) если указан ключ -U или USERGROUPS_ENAB установлен в значение
yes, то создается новая индивидуальная группа, имя которой совпадает
с именем пользователя
-G GID[,GID]
список дополнительных групп, в которые пользователь должен быть
включен после создания.
-с COMM
строка с комментарием о пользователе, например полное имя
пользователя
полный путь к домашнему каталогу пользователя. Если ключ не задан,
-d DIR
то имя домашнего каталога формируется из значения базового каталога
(указанного
ключом
-b
или
параметром
в
HOME
файле
/etc/default/useradd) и имени создаваемого пользователя.
Если дополнительно указан ключ -m или параметр CREATE_HOME в
файле login.defs определен в значение yes, то домашний каталог
автоматически создается. И в него копируются содержимое либо
каталога /etc/skel
(это значение по умолчанию определенное
параметром SKEL в файле /etc/default/useradd), либо каталога,
заданного ключом -k.
Если указан ключ -M или параметр CREATE_HOME имеет значение no,
то домашний каталог не создается.
командный интерпретатор пользователя. Если ключ не задан, то
-s SHELL
значение по умолчанию определяет параметр SHELL в файле
/etc/default/useradd
-e ГГГГ-ММ-ДД дата истечения срока действия учетной записи. Значение по умолчанию
определяет параметр EXPIRE в файле /etc/default/useradd
период неактивности. Значение по умолчанию определяет параметр
-f DAYS
INACTIVE в файле /etc/default/useradd
Пример:
# useradd -g 1200 -u 1201 -G students,class -c "Student" \
> -m -d /students/kib02/kib02-01 kib02-01
Команда создает пользователя с именем kib02-01 с uid 1201, домашним каталогом
/students/kib02/kib02-01 и основной группой с gid 1200, а также дополнительно
включает пользователя в группы students и class. Для того, что бы команда сработала
успешно,
группы
с
именами
students
и
class,
gid
1200
и
каталог
/students/kib02/должны существовать в системе. Данный пользователь не сможет
войти в систему, до тех пор пока не будет установлен пароль.
Так же после создания для пользователя будут определены минимальный и максимальные
сроки действия пароля и период предупреждения о смене пароля. Значение этих величин
определяются в файле /etc/login.defs
PASS_MAX_DAYS
максимальный срок действия пароля
PASS_MIN_DAYS
минимальный срок действия пароля
PASS_WARN_AGE
период предупреждения о смене пароля
Эти параметры могут быть переопределены при создание пользователя с помощью ключа
команды useradd -К ИМЯ_ПАРАМЕТРА=ЗНАЧЕНИЕ. Например:
# useradd -К PASS_MAX_DAYS=180 oper
В зависимости от версии UNIX-подобной системы или дистрибутива Linux, команда
adduser может являться либо просто альтернативным именем для команды useradd,
либо самостоятельной командой. Во втором случае главным отличием команды adduser
является интерактивное взаимодействия с администратором, и уточнение некоторых
параметров, незаданных опциями команды или неопределенных в конфигурационном
файле с настройками по умолчанию.
Команда newusers предназначена для создания новых учетных записей пользователей в
пакетном режиме. Команда читает указанный в параметрах файл, или стандартный ввод,
если запустить команду без параметров. Файл должен содержать строки с описанием
учетных записей пользователей в стандартном для файла /etc/passwd виде. Команда
newusers выполняет шифрование паролей, указанных в файле, и создание группы и
домашнего каталога, если в этом есть необходимость.
Для модификации параметров существующей учетной записи применяются команд
usermod. Она имеет схожий с командой useradd набор ключей, плюс некоторые
дополнительный ключи:
-l
поменять имя учетной записи пользователя.
-L
заблокировать учетную запись пользователя. Блокировка может быть
выполнена путем установки символа «!» перед хешем пароля в файле
/etc/shadow.
-U
разблокировать учетную запись пользователя. Удаляет символ «!» перед
хешем пароля в файле /etc/shadow, но только в том случае, если это
не приводит к появлению учетной записи с пустым паролем. Ключ не
меняет дату блокировки учетной записи. Для изменения этой даты
необходимо использовать ключ -e.
используется только совместно с ключом -G большое для того, что бы
-a
додавить пользователя в указанный список групп. Без ключа -a
использования
ключа
-G
приведет
к
полной
замене
списка
дополнительных групп пользователя. Например:
# groups ivanov
ivanov : ivanov wheel games audio student
# usermod -aG ftp,cdrom ivanov
# groups ivanov
ivanov : ivanov wheel games ftp audio cdrom student
# usermod -G video,audio,cdrom ivanov
# groups ivanov
ivanov : ivanov video audio cdrom
Администратор может удалить учетную запись пользователя командой userdel. Например:
# userdel student
Команда сработает успешно, если в текущей момент пользователь не работает в системе.
Будут удалены строки, соответствующие учетной записи пользователя student, из
файлов /etc/passwd и /etc/shadow, а так же упоминания пользователя из файлов
/etc/group и /etc/gshadow. Так же будет удалена индивидуальная группа
пользователя, если нет никаких других пользователей, для которых она является основной.
Домашний каталог пользователя и его почтовый ящик удалены не будут. Если есть
необходимость при удалении пользователя удалить его домашней каталог и почтовый
ящик, необходимо использовать ключ -r у команды userdel. Но даже в этом случае в
системе
могут
остаться
файлы,
принадлежавшие
находящиеся за пределами его домашнего каталога.
удаленному пользователю,
но
Найти
существующие
в
системе
файлы,
не
принадлежащие
ни
одному
из
зарегистрированных в системе пользователей, можно, используя ключ -nouser у
команды find. Аналогично ключ -nogroup команды find поможет найти файлы, не
принадлежащие существующим в системе группам.
# find / -nouser
/home/student
/home/student/.bash_profile
/home/student/.bash_logout
/home/student/.bash_history
/home/student/.bashrc
/tmp/student.project.txt
# ls -l /tmp/student.project.txt
-rw-rw-r--. 1 501 501 0 Апр 30 09:30 /tmp/student.project.txt
Администратор должен принять решение, что делать с этими файлами: удалить их, или,
если эти файлы все еще нужны другим пользователям, командой chown поменять
владельца этих файлов. Обратите внимание на то, что, поскольку команда ls -l не
смогла по цифровому идентификатору определить имя пользователя, в выводе команды
вместо привычного для нас имени мы видим числовое значение uid.
Обычный непривилегированный пользователь может самостоятельно поменять три
параметра своей учетной записи, если это явным образам не запрещено администратором
системы. Пользователь может поменять:
пароль
с помощью команды /usr/bin/passwd
комментарий
с помощью команды /usr/bin/chfn
командный
интерпретатор
с помощью команды /usr/bin/chsh, но только на значения
указанные в файле /etc/shells
Установка пароля и парольных политик
Для изменения собственного пароля обычный пользователь может использовать команду
passwd без дополнительных опций. Администратор может той же командой задать или
удалить пароль любому пользователю, а так же поменять некоторые парольные политики.
Кроме этого в linux-системах администратору доступна команда chage предназначенная
для управления механизмом устаревания паролей. Этот функционал команд passwd и
chage частично пересекается, но не все опции passwd могут быть реализованы в
конкретном дистрибутиве linux.
Опции команды passwd доступные администратору:
имя_пользователя имя пользователя, пароль которого нужно поменять. Если имя не
указано, то будет изменен пароль пользователя, выполняющего
команду
удалить пароль пользователя, сделать пароль пустым. В этом случае
-d
пользователь сможет войти в систему без предъявления пароля, если
это не запрещено другими настройками (например опциями ssh сервера или модулей аутентификации PAM)
заблокировать учетную запись. По сути аналогично команде
-l
usermod с ключом –L
снять блокировку учетной записи. По сути аналогично команде
u
usermod с ключом -U
--stdin
по умолчанию команда passwd запрещает установку пароля с
помощью переправления стандартного ввода команды (из файла или
канала). Данная опция снимает эти ограничения. Она потенциально
опасна и может быть реализована не во всех версиях команды
passwd.
Дополнительные опции команды passwd, которые могу быть реализованы в разных
системах и аналогичные им опции команды chage
Опция команды Опция команды
passwd
chage
Описание
-n
-m
поменять минимальное время жизни пароля (min)
-x
-M
поменять максимальное время жизни пароля (MAX)
-e
-d 0
принудить пользователя сменить пароль при следующем
входе в систему. В общем случае ключ -d меняет дату
последней смены пароля. Дата может быть задана в
количестве дней прошедших с 1-го января 1970 года или в
формате ГГГГ-ММ-ДД
-w
-W
установить период предупреждения о смене пароля
-i
-I
установить
период
неактивности
пользователя
после
устаревания пароля. Аналогично ключу -f у команд
usermod и useradd
- нет -
-E
устанавливает дату истечения срока действия учетной
записи. Аналогично ключу -e у команд usermod и
useradd
-S
-l
посмотреть
информацию
о
параметрах
механизма
устаревания пароля
Пример:
ivanov:$1$U.Y6gfRa$jKQcguexspnseliBCp9ml0:16190:7:180:7:30:17045:
# chage -d 16190 -m 7 -M 180 -W 7 -I 30 -E 17045 ivanov
или аналогично:
# chage -d 2014-04-30 -m 7 -M 180 -W 7 -I 30 -E 2016-09-01 ivanov
Результат можно увидеть в файле /etc/shadow:
# grep ivanov /etc/shadow
ivanov:$1$U.Y6gfRa$jKQcguexspnseliBCp9ml0:16190:7:180:7:30:17045:
Или посмотреть вывод команды: passwd -S ivanov
ivanov PS 2014-04-29 7 180 7 30 (Password set, MD5 crypt.)
Или команды: chage -l ivanov
Last password change
Password expires
Password inactive
: Apr 30, 2014
: Oct 27, 2014
: Nov 26, 2014
Account expires
: Sep 01,
Minimum number of days between password change
Maximum number of days between password change
Number of days of warning before password expires
2016
: 7
: 180
: 7
Получение информации о пользователях, работающих в системе
С помощью команды who можно получить информацию о пользователях, которые вошли в
систему. На экране появится примерно такая информация:
В первом столбце отображается список пользователей, которые вошли в систему, в
последних столбцах — дата и время входа. Данные второго столбца показывают, откуда
пользователь вошел в систему. Первые два пользователя (elvis и root) использовали
для входа tty1 и tty2, что означает первую и вторую виртуальную консоль
соответственно. :0 для пользователя blondie означает вход в с использованием
графического интерфейса, а pts/0 относится к первому из терминалов, открытых в
графической среде.
2.3. Вопросы для самоконтроля
1. Что такое оболочка, какую роль она играет во взаимодействии пользователя с
операционной системой?
2. Что такое среда пользователя, из чего она формируется?
3. В каком формате учетные записи пользователей хранятся в операционной системе?
4. Какие
параметры
свой
учетной
записи
пользователь
может
поменять
самостоятельно, без обращения к системному администратору? Какими командами?
5. Как устроено управление паролями в операционной системе UNIX?
6. Как узнать, какие пользователи сейчас работают в системе, и откуда они
авторизовались?
3. Файловая система
Все данные, хранимые в системе, представлены в виде файлов. Файлы имеют имена,
позволяющие пользователям обращаться к данным файла.
Каталог — это объект в файловой системе, упрощающий организацию файлов путём их
группировки. Представлен в виде файла особого типа, который содержит перечень файлов.
Каталоги организованы в древовидную структуру.
Текущий рабочий каталог — это каталог, в котором находится пользователь, вызывая ту
или иную команду. Узнать текущий рабочий каталог можно, используя команду pwd.
Домашний каталог — каталог, в котором хранятся личные файлы пользователя. Каждый
пользователь в системе имеет свой личный каталог. Независимо от того, где находится
домашний каталог пользователя в структуре каталогов системы, к нему можно перейти
или скопировать в него файлы по ссылке, используя спецсимвол «~».
Корневой каталог – первый каталог в древовидной структуре системы, для которого все
остальные каталоги являются вложенными. Обратиться к корневому каталогу можно,
используя спецсимвол «/». Например, для перехода в корневой каталог необходимо
использовать команду cd /.
3.1. Структура системы каталогов ОС UNIX
Структура каталогов системы начинается с корневого каталога. В нём содержатся
базовые каталоги, которые имеют большое значение для системы. Как правило, во всех
операционных системах UNIX названия этих каталогов одинаковы:
/bin
каталог содержит базовые исполняемые файлы, например, ls, vi, cd, cp
/boot
каталог содержит файлы, необходимые для загрузки системы, например, ядро ОС
Linux и файлы загрузчика (lilo, grub или другого)
/dev
каталог содержит файлы устройств, присоединенных к системе, или файлы
виртуальных устройств, созданных ядром. К любому устройству, будь то flashнакопитель, cdrom или звуковая карта, можно обратиться, используя файлы в этом
каталоге
/etc
каталог содержит файлы конфигурации большей части программ и приложений
/home
каталог, как правило, содержит домашние каталоги пользователей
/lib
каталог содержит библиотеки, необходимые для исполнения приложений из
каталогов /bin и /sbin
/proc
каталог содержит системную информацию о всех процессах, исполняемых в
системе. В каталог монтируется виртуальная файловая система proc, и он будет
пустым, если не загружать ОС
/root
домашний каталог пользователя root
/sbin
каталог содержит исполняемые файлы, используемые при загрузке системы или
для ее администрирования пользователем root (изначально в первых системах
UNIX каталог содержал статические бинарные файлы, не требующие линковки с
библиотеками, отсюда название (sbin = static bin))
/tmp
общий каталог, используемый для хранения временных файлов
/usr
каталог содержит пользовательские приложения и библиотеки. Большая часть
программ и библиотек, не требующихся для загрузки или восстановления системы,
хранится в этом каталоге
/var
каталог содержит часто изменяемые файлы: системные журналы (/var/log),
конфигурационные файлы, сообщения электронной почты, веб-сайты, файловые
архивы ftp и другие данные
Подробное описание структуры каталогов системы можно получить, используя
следующую команду:
[user@station ~]$ man 7 hier
3.2. Управление каталогами
Путь к файлу, находящемуся в корневом каталоге, записывается так: /file. Путь к
файлам в других каталогах, также начинается от «/» и содержит список всех каталогов на
пути от корневого каталога до файла. Например, /home/student/file. Другой вариант
записи пути к файлу — начинать запись не от корня каталогов, а от текущего рабочего
каталога. При этом текущий каталог обозначается символом «.», а родительский каталог «..». Например, если пользователь находится в каталоге /home/student/dir1/, и ему
необходимо открыть файл /home/student/dir2/file, то относительный путь до
этого файла будет ../dir2/file. Файл file1 в текущем каталоге можно открыть без
указания пути, обратившись к нему просто как file1. Еще один вариант записи пути путь относительно домашнего каталога. Путь до вашего домашнего каталога можно
заменить символом «~». Например, путь к файлу /home/student/dir2/file
пользователю student можно записать так: ~/dir2/file.
Таким образом, к файлу всегда можно обратиться двумя способами. Путь к файлу
относительно корневого каталога всегда начинается с «/» и называется абсолютным.
Путь к файлу относительно текущего каталога записывается без «/» и называется
относительным. Запись пути относительно домашнего каталога обычно используется при
обращении к файлам, находящимся в домашнем каталоге и его подкаталогах, и также
является абсолютным, так как система заменяет символ «~» во введённом пользователем
пути на полный путь до домашнего каталога.
Создание каталогов
Для создания каталогов используется команда mkdir (mkdir — сокращенно от «make
directory»). В качестве аргумента команде передается имя каталога, который требуется
создать.
Для создания каталога с подкаталогами необходимо использовать ключ -p, это позволяет
рекурсивно создавать каталог с подкаталогами, иначе команда не выполнится.
Пример использования команды mkdir:
[user@station ~]$ mkdir -p dir1/dir2
Просмотр содержимого каталогов
Для просмотра содержимого каталогов используется команда ls (ls — сокращенная форма
глагола «list»). Команда ls без аргументов отображает содержимое текущего рабочего
каталога. В качестве аргумента можно указать ссылку на каталог, содержимое которого
необходимо просмотреть. Наиболее часто используемые ключи команды ls:
-l
выводит «длинный список» каталогов и файлов, указывая для каждого элемента его
тип (каталог или файл), права доступа, владельца, размер и другие данные
-a
выводит полный список каталогов и файлов, включая скрытые файлы (их названия
начинаются с символа «.»)
-h
выводит размер файла в удобном для восприятия пользователем формате
(Кб/Мб/Гб)
-R
используется для рекурсивного вывода содержимого каталога. При этом выводится
не только содержимое каталога, указанного в качестве аргумента команды, но и
содержимое всех подкаталогов
-S
вывести список, отсортированный по размеру файла
-t
вывести список, отсортированный по дате последнего изменения
Пример использование команды ls:
[user@station ~]$ ls
dir1 file.txt
[user@station ~]$ ls -la
drwx-----31
user user 4096 Jun
drwxr-xr-x
6
root root 4096 Jul
drwxr-xr-x
3
user user 4096 Aug
-rwxr-xr-x
1
user user 2252 Jul
19
12
1
30
00:32
23:19
04:25
20:07
.
..
dir1
file.txt
В результате выполнения команды ls –l выводится «длинный список». В него входят:
тип файла (d — каталог, - — простой файл, l — символьная ссылка, c —
символьное устройство, b — блочное устройство, s — сокет, p — канал)
права доступа к файлу (будет рассмотрено далее)
количество ссылок на файл
имя владельца файла
имя группы пользователей
размер файла (в байтах)
временной штамп
имя файла
Полный список ключей команды ls можно получить, выполнив
[user@station ~]$ man ls
3.3. Управление файлами
Просмотр файлов
Для просмотра файлов существует несколько команд, простейшей из которых является cat.
Если передать ей список файлов в качестве аргумента, то их содержимое будет «склеено»
и выведено на экран. Если указать только один файл, то выведется содержимое этого
файла.
Пример использования команды cat:
[user@station ~]$ cat /etc/hosts
Просмотр статистики файлов
Команда wc позволяет узнать количество символов, слов и строк в текстовом файле.
Пример использования команды:
[user@station ~]$ wc text.txt
20 62 715 text.txt
Здесь, 20 – число строк, 62 – число слов, 715 – число символов в файле.
Для получения только нужной информации можно использовать ключи:
-c
вывести только число символов в файле
-l
вывести только число строк в файле
-w
вывести только число слов в файле
Создание файлов:
Пустые файлы можно создать несколькими способами.
Например, команда touch используется для обновления данных о временах модификации
и последнего доступа к файлу. При отсутствии файла, к которому обращается команда,
будет создан пустой файл.
Аналогично перенаправлению потока вывода в файл можно создавать новые пустые
файлы, перенаправляя в файл отсутствие данных.
Пример создания пустого файла:
[user@station ~]$ > file.txt
Для создания файла с данными можно использовать текстовые редакторы или
специализированные приложения. Например, vi, nano, emacs.
Копирование файлов:
С помощью команды cp (copy) можно создавать копии файлов и каталогов.
Примеры использования команды cp:
[user@station ~]$ cp source target — файл с именем source копируется в
файл с именем target
[user@station ~]$ cp source dir/ — файл с именем source копируется в
каталог dir с тем же именем
[user@station
~]$
cp
-r
source
target — каталог с именем source
копируется в каталог с именем target
Перемещение файлов:
С помощью команды mv (move) файлы можно перемещать из одного каталога в другой или
менять имя файла.
Примеры использования команды mv:
[user@station ~]$ mv source target — файл source переименовывается в
файл target
[user@station ~]$ mv source dir/ —файл source перемещается в каталог dir/
Команда mv интересна тем, что принцип ее работы тесно связан с файловой системой:
UNIX воспринимает имя файла как нечто внешнее по отношению к его содержимому.
Несмотря на то, что название команды происходит от слова «перемещение», она редко
занимается перемещением данных. Вместо этого файловая система просто изменяет имя.
Если имя файла изменяется с /dir/file на /dir/newfile, то это называется
переименованием. Если имя файла изменяется с /dir/file на /newdir/file, то это
называется
перемещением.
Если
имя
файла
изменяется
с
/dir/file
на
/newdir/newfile, то это — перемещение с переименованием. Но, по сути, в UNIX все
это является одним и тем же: изменением полного имени файла.
Удаление файлов и каталогов:
С помощью команды rm (remove) файлы можно удалять.
Для удаления каталога используется команда rmdir. Для ее использования необходимо
предварительно удалить все файлы и подкаталоги, так как rmdir удаляет только пустые
каталоги.
Для рекурсивного удаления каталога с файлами и подкаталогами можно использовать
команду rm с ключом -r.
Пример использования команды rm:
[user@station ~]$ rm file — удаление файла
[user@station ~]$ rm -r dir1 — удаление каталога и всех вложенных файлов
3.4. Работа со ссылками
Файл в UNIX состоит из двух частей:

имя файла;

непосредственно содержимое файла, хранимое на файловой системе.
Существуют два типа ссылок: жесткие и символьные.
Жесткие ссылки привязывают многочисленные имена файлов к одним данным
(содержимому).
Символьные ссылки — это имена, ссылающиеся на другие имена файлов.
Для создания ссылок используется команда ln.
Пример использования жестких ссылок
Иногда требуется, чтобы один и тот же файл находился в нескольких местах или имел два
разных имени. Для этого используются ссылки на файлы. Предположим, пользователи
user1 и user2 хотят вместе работать над одним файлом (file.txt) и иметь
возможность пользоваться работой друг друга. Вместо того, чтобы копировать и обновлять
файл
каждый
раз,
когда
другой
пользователь
изменил
что-то,
и
постоянно
синхронизировать свои личные копии, они решают создать жесткую ссылку.
Пользователь user1 создал каталог ~/dir, выдав другим пользователям права на запись
в этот каталог (о правах доступа в следующем разделе). Пользователь user2 делает то же
самое в своем домашнем каталоге. Затем user1 создает файл ~/dir/file.txt и
использует команду ln, чтобы создать ссылку на файл в каталоге dir пользователя
user2.
[user1@station ~]$ ls -ld dir/
drwxrwxr-x
2
user1
group
[user1@station ~]$ touch dir/file.txt
4096 Jul 13 05:45 dir/
[user1@station ~]$ chgrp group dir/file.txt – выдача прав доступа к файлу
группе group, в которую входит пользователь user2
[user1@station ~]$ ln dir/file.txt /home/user2/dir/file.txt
Поскольку была создана ссылка на файл, а не его копия, то по сути мы работаем с одними
и теми же данными, обращаясь к ним по двум разным именам. Когда пользователь user2
редактирует
файл
/home/user2/dir/file.txt,
/home/user1/dir/file.txt.
он
также
редактирует
файл
Если один из пользователей удалит файл ~/dir/file.txt, то из системы удалится
только имя этого файла. Файл по-прежнему будет виден и доступен второму пользователю
по второму имени в его домашнем каталоге. Сам файл будет удален из файловой системы
только тогда, когда будут удалены все его имена.
Жесткие ссылки нельзя использовать в следующих случаях:

Нельзя создавать жесткие ссылки на каталог.

Жесткая ссылка не может пересекать границы файловой системы.
Пример использования символьных ссылок
Пользователь user держит в своем домашнем каталоге семь файлов со списками дел на
каждый день недели.
[user@station ~]$ ls
friday.todo
monday.todo
saturday.todo sunday.todo
thursday.todo tuesday.todo
wednesday.todo
Чтобы не забывать, какой именно сегодня день недели, и в каком файле нужно смотреть
список дел на сегодня, ему лучше создать файл today.todo, который он будет обновлять
каждое утро. Для этого он решает использовать символьную ссылку. Поскольку сегодня
вторник, он использует ту же команду ln, которая использовалась для создания жесткой
ссылки, но добавляет к ней ключ -s, чтобы указать правильный тип ссылки.
[user@station ~]$ ls
friday.todo
monday.todo
saturday.todo sunday.todo
thursday.todo tuesday.todo
wednesday.todo
[user@station ~]$ ln -s tuesday.todo today.todo
[user@station ~]$ ls -l
total 32
-rw-rw-r-- 1 user group 138
Jul 14 09:54
friday.todo
-rw-rw-r-- 1 user group 29
Jul 14 09:54
monday.todo
-rw-rw-r-- 1 user group 578
Jul 14 09:54
saturday.todo
-rw-rw-r-- 1 user group 252
Jul 14 09:54
sunday.todo
-rw-rw-r-- 1 user group 519
Jul 14 09:54
thursday.todo
lrwxrwxrwx 1 user group 12
Jul 14 09:55
today → tuesday.todo
-rw-rw-r-- 1 user group 37
Jul 14 09:54
tuesday.todo
-rw-rw-r-- 1 user group 657
Jul 14 09:55
wednesday.todo
Созданная ссылка имеет тип l (символьная ссылка), что можно увидеть в первом столбце
вывода команды ls -l. Также в листинге указано, на какой файл ведёт эта ссылка.
В отличие от жесткой ссылки, символьная ссылка действительно создает новый файл.
Однако этот файл имеет тип «символьная ссылка» и вместо реальных данных содержит
имя другого файла.
Если пользователь удалит или переименует исходный файл, на которой сделана
символьная ссылка, то ссылка перестанет быть рабочей, то есть она отсылает пользователя
к несуществующему файлу.
3.5. Перенаправление ввода-вывода
При выполнении команд ls и cat результат их работы отображается на экране. В UNIX
большинство команд, которые выводят текст на экран, использует понятие стандартный
поток вывода. По умолчанию он связан с терминалом. Оболочка bash позволяет
перенаправлять стандартный поток вывода в другие места. Например, в файл. Для этого
используется символ «>».
Пример использования:
[user@station ~]$ ls /tmp > file.txt
Если файл file.txt существует, то его содержимое будет перезаписано выводом
команды ls. Если этого файла не существует, то он будет создан.
Для добавления данных в файл без затирания уже записанной в него ранее информации
используется сочетание символов «>>». При этом новые данные будут добавлены в конец
файла.
При написании bash-скриптов часто используется перенаправление потока стандартного
вывода или потока ошибок, возникших в ходе выполнения скрипта, в специальное
устройство /dev/null (пустое устройство). Запись в него происходит успешно
независимо от объема переданной информации. Чтение из /dev/null эквивалентно
считыванию конца файла (EOF). Например, для перенаправления потока стандартного
вывода при выводе на экран содержимого файла file1.txt в /dev/null используется
следующая команда:
[user@station ~]$ cat file1.txt > /dev/null
При выполнении этой команды содержимое файла не будет выведено на экран, а будет
утеряно.
Для перенаправления ошибок в /dev/null при попытке просмотра содержимого
домашнего каталога пользователя root, на просмотр которого у вас нет прав, используется
следующая команда:
[user@station ~]$ ls /root/ 2> /dev/null
3.6. Регулярные выражения
Для упрощения работы в оболочке bash можно использовать подстановки, обращаясь к
файлам и каталогам, производя поиск текста в файле, используя команду grep. Одна из
подстановок, которая уже рассматривалась ранее:
«~» (Tilde Expansion) обозначает домашний каталог пользователя. Например, команда cd
~ заменяет команду cd /student/group/username и перемещает вас в домашний
каталог. Для перехода в домашний каталог другого пользователя укажите его имя после
символа «~», например «~root».
Пример:
[user1@station /]$ cd ~
[user1@station ~]$ cd ~user2
[user1@station /home/user2]$
Как и многие другие, оболочка bash полноценно поддерживает целый «язык» регулярных
выражений, который также поддерживается разными языками программирования: Perl,
Python, JavaScript, PHP и другими.
Символ «*» заменяет любое число произвольных символов.
Пример:
[user@station ~]$ ls
dir1 f3 file file1 file2 q1
[user@station ~]$ ls file*
file file1 file2
[user@station ~]$ ls *1
dir1 file1 q1
Символ «.» аналогичен по своим свойствам символу «*», но заменяет один произвольный
символ.
Пример:
[user@station ~]$ ls
dir1 f3 file file1 file2 q1
[user@station ~]$ ls file.
file1 file2
[user@station ~]$ ls .1
q1
Использование квадратных скобок ([]) позволяет выбирать произвольные символы для
подстановки.
Пример:
[user@station ~]$ ls
dir1 f3 file file1 file2 q1
[user@station ~]$ ls [f,q]*1
file1 q1
При поиске файлов и текста внутри файла команды grep, expr, sed и awk
поддерживают многие другие спецсимволы:
Символ ^ означает начало строки, но иногда, в зависимости от контекста, означает
отрицание в регулярных выражениях. А знак доллара ($) в конце регулярного выражения
соответствует концу строки. Выражение "^$" соответствует пустой строке.
Обратный слэш (\) служит для экранирования специальных символов, это означает, что
экранированные символы должны интерпретироваться буквально, т.е. как простые
символы (например, "\$" означает, что требуется искать знак доллара, а не в конце
строки).
3.7. Поиск и фильтрация
Поиск файлов и содержимого в них
Команда find используется для поиска в файловой системе файлов, которые
соответствуют особым критериям. Почти все параметры файла могут быть указаны,
например, его имя, размер, время последнего изменения, даже число ссылок. Единственное
ограничение — find не позволяет искать файлы по их содержимому.
Синтаксис использования команды find:
find [каталог поиска] [критерии поиска] [действие]
Для поиска файла в корне каталогов по имени и вывода списка файлов без выполнения
каких-либо действий может использоваться следующая команда:
[user@station ~]$ find / -name “*.conf”
Команда find позволяет выполнять поиск файлов и каталогов по разным критериям.
Некоторые из них:
-empty
поиск пустых файлов
-fstype
поиск файлов, находящихся на файловой системе указанного типа
-group
поиск файлов, принадлежащих указанной группе
-links
поиск файлов с указанным числом ссылок
-name
поиск файлов с указанным именем (с поддержкой регулярных выражений)
-nogroup поиск файлов, принадлежащих несуществующей группе
-nouser
поиск файлов, принадлежащих несуществующему пользователю
-perm
поиск файлов по правам доступа
-size
поиск файлов указанного размера
-type
поиск файлов указанного типа
-user
поиск файлов, принадлежащих указанному пользователю
При использовании find есть возможность указать действия, которые необходимо
выполнить при нахождении файла с именем, удовлетворяющим выражению поиска. Для
этого используется параметр exec.
Пример использования команды find
для удаления всех файлов, размер которых
превышает 100 Мб:
[user@station ~]$ find / -size +100M -exec /bin/rm {} \;
В разных операционных системах команда find может обладать разным расширенным
функционалом. Для более близкого знакомства с командой find воспользуйтесь справкой,
вызвав ее командой man find на своей рабочей станции.
Команда grep традиционно используется для выборки из всех данных только тех, что нас
интересуют.
Пример использования команды grep:
[user@station ~]$ grep root /etc/passwd
root:x:0:0:root:/root:/bin/bash
Первый аргумент команды — текст для поиска, остальные аргументы — файлы для
поиска. Если команда вызывается только с одним аргументом, то в качестве источника
данных она использует стандартный ввод.
3.8 Каналы
Поток вывода (stdout) из одного процесса может быть связан с потоком ввода (stdin)
другого процесса. Это носит название «канал». Для создания канала между двумя
командами в bash используется символ «|».
Пример использования каналов:
Например, пользователю нужно найти самые большие файлы в каталоге /etc. Сначала он
составляет команду find, которая найдет все файлы, размер которых больше 100Кб.
[user@station ~]$ find /etc -size +100k
Заметив, что команда выводит список файлов без сортировки, он решает отсортировать их
в алфавитном порядке. Можно перенаправить вывод команды find в файл, а затем
отсортировать список, используя команду sort. Вместо этого он решает создать канал,
направив результат поиска на вход команды sort.
[user@station ~]$ find /etc -size +100k | sort
При этом файлы будут отсортированы в алфавитном порядке.
3.9. Вопросы для самоконтроля
1. Какие базовые каталоги UNIX вы знаете? Что в них хранится?
2. Как устроена структура каталогов в UNIX?
3. Как пользователь может создавать, изменять и удалять каталоги?
4. Что такое «файл», как пользователь может управлять файлами?
5. Какие типы ссылок вы знаете, чем они различаются?
6. Как используется перенаправление потоков ввода-вывода при работе в командном
интерфейсе UNIX?
7. Для чего используются регулярные выражения? Приведите пример регулярного
выражения?
8. Какие команды для поиска файлов и данных внутри файлов вы знаете? Как их
использовать?
9. Как в UNIX происходит объединение нескольких команд в одну? Что такое
«канал»?
4. Права доступа
4.1. Средства управления правами доступа
Во всех современных операционных системах семейства Unix присутствуют два
механизма управления правами доступа:
4.1.1. Дискреционное управление доступом (DAC, Discretionary Access
Control)
Дискреционное управление доступом подразумевает наличие владельца у каждого
защищаемого объекта (файла, каталога). Данный владелец определяет права доступа к
этому своему объекту, а выполняющиеся приложения имеют те же права, что и
запустивший их пользователь. Пользователи также могут передавать права другим
субъектам.
Механизм DAC опирается в своей работе только на тождество пользователя, игнорируя
другую информацию, например, о роли пользователя в системе, функции и уровне доверия
конкретного приложения и необходимости в целостности данных. Каждая учетная запись
имеет полную свободу действий в пределах своих полномочий.
Подробно работу этого механизма мы рассмотрим в разделе 4.2 этого пособия.
4.1.2. Мандатное управление доступом (MAC, Mandatory access control)
Мандатный контроль доступа позволяет задать явные правила доступа субъектов
(пользователей, процессов) к объектам в виде политики доступа. Способ основывается на
назначении метки конфиденциальности для информации, содержащейся в объектах, и
выдаче официальных разрешений (допуска) субъектам на обращение к информации такого
уровня конфиденциальности. Это способ, сочетающий защиту и ограничение прав,
применяемый по отношению к компьютерным процессам, данным и системным
устройствам и предназначенный для предотвращения их нежелательного использования.
Политика задаётся не владельцем объекта и не может быть изменена. Права на передачу
прав определяются также в политике.
Одним из вариантов мандатного доступа является модель домен-тип. Процесс запускается
в поименованном домене безопасности (то есть имеет определённый уровень доступа), а
каждый объект имеет определённый тип (так сказать, уровень секретности). Не надо
считать, что один уровень выше другого - ранжирование в общем случае не определено.
Политика задаёт список правил, ограничивающий возможности доступа доменов к типам.
При каждом обращении к ядру проверяется, имеет ли право представитель данного домена
на данную операцию к объекту данного типа.
Наиболее распространенный вариант мандатного доступа - многоуровневая иерархическая
система доступа (MLS, Multilevel security). В этой модели уровни доступа и секретности
ранжированы. Нельзя читать объекты более высокого уровня секретности и писать в
объекты с более низким уровнем секретности - модель Белла-Ла Падула (Bell-La Padula,
BLP). Возможен также вариант модели домен-тип или MLS с классификацией данных по
тематике (MCS, Multicategory security).
Мы не будем рассматривать практическую сторону применения мандатного управления
доступом, так как оно не является частью стандартов, общих для семейства UNIX, и в
разных
операционных
системах
реализовано
по-разному.
Наиболее
популярной
реализацией мандатного управления доступом в Linux является SELinux, в BSD и Solaris
есть свои реализации.
4.2. Управление правами доступа к файлам и каталогам
Для каждого файла задаются 3 группы прав: для владельца (u), для членов группы (g) и для
всех прочих (o). Права доступа подразделяются на три типа: чтение (read), запись (write)
и выполнение (execute). Владелец файла обычно является членом группы, пользователям
которой выдаются права доступа, но это не является обязательным условием.
Разрешение на чтение позволяет пользователю читать содержимое файлов, а в случае
каталогов - просматривать перечень имен файлов в каталоге (используя, например, ls).
Разрешение на запись позволяет пользователю писать в файл и изменять его. Для
каталогов это дает право создавать новые файлы и подкаталоги, или удалять файлы в этом
каталоге. Разрешение на выполнение позволяет пользователю выполнять файлы (как
бинарные
программы,
так
и
командные
файлы).
Разрешение
на
выполнение
применительно к каталогам означает возможность переходить к каталогу, используя,
например, команду cd.
Права доступа к обычным файлам и каталогам:
Обычный файл
Каталог
(r) чтение
(w) запись
(x) выполнение
просмотреть
содержимое файла
изменить файл
использовать файл как
команду
вывести список
добавить или удалить
содержащихся в
файлы
каталоге подкаталогов
и файлов
работа с известным
файлом внутри
каталога
Для просмотра прав доступа к файлу или каталогу можно воспользоваться следующей
командой:
$ ls -l
Пользователь, создающий объект, становится его владельцем, а основная группа, в
которую входит пользователь, становится группой, имеющий доступ с указанными
правами к объекту. Пользователь, создавший объект, не может изменить владельца, но
может изменить группу и права доступа всех категорий пользователей к объекту.
Изменить владельца объекта может только суперпользователь root.
Для изменения владельца файла или каталога используется команда chown. Синтаксис
команды:
chown [-ключи] новый пользователь:[новая группа] имя файла
Для рекурсивного изменения владельца каталога и вложенных файлов используется ключ
-R. Если группу-владельца изменять не требуется, то эта часть команды опускается.
Для изменения группы-владельца файла или каталога воспользуйтесь командой chgrp.
Синтаксис команды:
chgrp [-ключи] новая_группа имя_файла
Существует два формата записи прав доступа: символический, который мы видим, работая
с командой ls -l (rwxrwxrwx или r-x------) и восьмеричный (777 или 002). Как работать с
форматами записи прав доступа?
Файл имеет три разных типа разрешений к доступу чтение (r), запись (w) и выполнение (x)
для трех классов пользователей: владелец (u), группа (g) и остальные (o). При
восьмеричной записи каждый тип пользователя с правами доступа получает разряд: место
"сотен" – для владельца (u), место "десяток" для группы (g), а место "единиц" - для
остальных (o). Каждый тип доступа получает цифровое обозначение: чтение (r) получает 4
(100), запись (w) получает 2 (010), а выполнение (x) получает 1 (001). Символы в
восьмеричной записи - это совокупность прав доступа для данного класса пользователя с
правами доступа.
Используя команду chmod можно изменять права доступа к файлу. Синтаксис команды:
chmod [-ключи] права_доступа имя_файла_или_каталога
Для рекурсивного изменения прав доступа используется ключ -R, изменяющий права для
каталога и всех файлов внутри него.
Примеры использования команды chmod:
Исходный файл:
-rw-rw-r--
1
user user 42
Jan 16 08:09
file.txt
Лишить группу права записи:
[user@station ~]$ chmod g-w file.txt
-rw-r—r-- 1
user user 42
Jan 16 08:09
file.txt
Наделить пользователя-владельца и группу правом исполнения:
[user@station ~]$ chmod ug+x file.txt
-rwxrwxr-1
user user 42
Jan 16 08:09
Наделить всех других пользователей правом записи:
file.txt
[user@station ~]$ chmod o+w file.txt
-rw-rw-rw1
user user 42
Jan 16 08:09
file.txt
Лишить группу и всех других пользователей всех прав:
[user@station ~]$ chmod go-rwx file.txt
-rw------1
user user 42
Jan 16 08:09
file.txt
Лишить всех права записи:
[user@station ~]$ chmod a-w file.txt
-r--r--r-1
user user 42
Jan 16 08:09
file.txt
Лишить пользователя-владельца и всех других пользователей права чтения:
[user@station ~]$ chmod uo-r file.txt
--w-rw---1
user user 42
Jan 16 08:09
file.txt
Наделить группу и других пользователей правами чтения и исполнения, но не записи
[user@station ~]$ chmod go=rx file.txt
-rw-r-xr-x
1
user user 42
Jan 16 08:09
file.txt
Наделить пользователя-владельца правами исполнения и лишить группу права записи:
[user@station ~]$ chmod 744 file.txt
-rwxr--r-1
user user 42
Jan 16 08:09
file.txt
Наделить всех пользователей всеми правами:
[user@station ~]$ chmod 777 file.txt
-rwxrwxrwx
1
user user 42
Jan 16 08:09
file.txt
Лишить других пользователей права чтения:
[user@station ~]$ chmod 660 file.txt
-rw-rw-r-1
user user 42
Jan 16 08:09
[user@station ~]$ chmod 744 file.txt
-rw-rw-r-1
user user 42
Jan 16 08:09
file.txt
file.txt
При выставлении прав доступа для создаваемого файла, система считает права доступа,
исходя из режимного глобального кода по умолчанию 666 (rw-rw-rw-) для файлов и 777
(rwxrwxrwx) для каталогов. Затем система применяет umask процесса, который создал
файл (например, bash). Любые значения, установленные в umask, побитно вычитаются из
глобального кода. Например, umask со значением 002 установит права доступа к файлу по
умолчанию 664:
Стандартный код системы:
666 → rw- rw- rw-
umask:
002 → --- --- -w-
----------------------------------------------------------------Стандартные права:
664 → rw- rw- r--
Если umask установлен в 135, то будет создан файл с правами 643:
Стандартный код системы:
umask:
666 → rw- rw- rw135 → --x -wx r-x
----------------------------------------------------------------Права на файл:
643 → rw- r-- -w-
Для изменения маски оболочки bash используется команда umask. Когда команда
выполняется без параметров, она сообщает о текущем значении umask. Когда она
выполняется с восьмеричной записью в качестве единственного аргумента, текущее
значение umask изменяется на новое.
Пример использования команды umask:
[user@station ~]$ umask
0002
[user@station ~]$ umask 077
0077
4.3. Флаги Sticky Bit и Suid
Помимо выдачи прав доступа к файлам и каталогам можно использовать дополнительные
атрибуты файлов для их защиты:
Флаг Sticky bit используется, в основном, для каталогов, чтобы защитить в них файлы. Из
таких каталогов пользователь может удалить только те файлы, владельцем которых он
является. Примером может служить каталог /tmp, в котором запись открыта для всех
пользователей, но нежелательно удаление чужих файлов. Установка флага производится
командой chmod:
[user@station ~]$ chmod +t /tmp
drwxr-xr-t
2
user user 4096
Jan 18 04:02
catalog
Jan 18 04:03
catalog
или
[user@station ~]$ chmod 1755 /tmp
drwxr-xr-t
2
user user 4096
Флаги setuid и setgid (сокращения от set user ID upon execution — «установка ID
пользователя во время выполнения» и set group ID upon execution — «установка ID группы
во время выполнения») являются флагами, которые разрешают пользователям запускать
исполняемые файлы с правами владельца или группы исполняемого файла. Вместе (setuid
и setgid) называются SUID.
Когда флаг setuid установлен файлу, обычный пользователь, запускающий этот файл на
исполнение, получает повышение прав до пользователя-владельца файла (обычно root) в
рамках запущенного процесса. После получения повышенных прав приложение может
выполнять
задачи,
выполнение
которых
обычному
пользователю
недоступно.
Пользователю будет запрещено системой изменение нового процесса. Из-за возможности
проблем безопасности многие операционные системы игнорируют установленный атрибут
к shell-скриптам.
Хотя флаг setuid очень удобен во многих случаях, его неправильное использование
может представлять угрозу безопасности, когда атрибут присваивается исполняемому
файлу, который не тщательно спроектирован. Пользователи могут использовать
уязвимости в недоработанных программах, чтобы получить повышенные привилегии или
непреднамеренно запустить вирус.
Установленный флаг setgid атрибут даёт повышение прав группы.
Флаг setgid для каталога (chmod g+s) заставляет только новые каталоги и файлы,
созданные в нём, наследовать ID группы этого каталога вместо ID группы пользователя,
создавшего файл. Новые подкаталоги также наследуют флаг setgid. Это позволяет
создать общее рабочее пространство для группы. Наследование устанавливается только
для новых файлов и каталогов. Уже существующим файлам и каталогам этот бит нужно
устанавливать вручную.

Флаг setuid, установленный для каталогов игнорируется (в большинстве
дистрибутивов Linux/Unix).
Установка атрибутов производится командой chmod.
Для установки setuid используется флаг 4:
[user@station ~]$ chmod 4755 /tmp
drwsr-xr-x
2
user user 4096
Jan 18 04:02
catalog
Jan 18 04:03
catalog
Для установки setgid используется флаг 2:
[user@station ~]$ chmod 2755 /tmp
drwxr-sr-x
2
user user 4096
Для одновременной установки setuid и setgid можно использовать флаг 6 или +s:
[user@station ~]$ chmod 6755 /tmp
drwsr-sr-x
2
user user 4096
[user@station ~]$ chmod +s /tmp
drwsr-sr-x
2
user user 4096
Jan 18 04:03
catalog
Jan 18 04:03
catalog
4.4. Списки контроля доступа
Списки контроля доступа используются для выдачи доступа к файлу дополнительным
группам и пользователям, если функционала стандартного разграничения прав доступа к
файлу оказывается недостаточно.
Команда getfacl используется для просмотра списка контроля доступа для файла. Если
списки контроля доступа не заданы, но команда выведет на экран стандартные права
доступа UNIX для выбранного файла.
[user1@station ~]$ getfacl file1.txt
# file: file1.txt
# owner: user1
# group: users
user:: rwgroup::rwother::--С помощью команды setfacl можно добавить списки контроля доступа для файла.
Например, чтобы разрешить членам группы developers читать файл file1.txt,
пользователю user2 — читать и обновлять файл, а пользователю user3 — только читать
файл, можно воспользоваться следующими командами:
[user1@station ~]$ setfacl -m g:developers:rw file1.txt
[user1@station ~]$ setfacl -m u:user2:rw file1.txt
[user1@station ~]$ setfacl -m u:user3:r file1.txt
После выполнения этих действий команда getfacl выведет следующую информацию о
файле:
[user1@station ~]$ getfacl file1.txt
# file: file1.txt
# owner: user1
# group: users
user::rwuser:user3:r-user:user2:rwgroup::rwgroup:developers:rwmask::rwother::--Каждая строка, выводимая командой getfacl, называется записью, и может быть одного
из следующих типов:
Запись
Имя acl
Синтаксис
#
Комментарий
пользователь- ACL_USER_OBJ
владелец файла
user::
1
стандартные права доступа для
пользователя-владельца файла
отдельные
пользователи
user:
0+
права доступа для
дополнительных пользователей
группаACL_GROUP_OBJ group::
владелец файла
1
стандартные права доступа для
группа-владельцев файла
отдельные
группы
ACL_GROUP
group:
0+
права доступа для
дополнительных групп
маска
ACL_MASK
mask::
0 или 1 максимально возможные права
доступа, разрешенные для
дополнительных пользователей и
любой группы
все остальные
ACL_OTHER
other::
1
ACL_USER
права доступа для любого
пользователя, который не входит
ни в одну из вышеназванных
категорий
Все записи, кроме маски, должны быть заданы.
Когда процесс пытается получить доступ к файлу, выполняются следующие действия:
1. Если пользователь процесса — владелец файла, то используются стандартные права
пользователя-владельца файла.
2. Если права пользователя процесса заданы одной из записей, описывающих права
доступа дополнительных пользователей, то применяются соответствующие права.
3. Если группы процесса содержат группу-владельца файла, но маски нет, то
применяются стандартные права доступа группы.
4. Если список групп процесса содержит любую группу, права которой заданы одной
из записей, описывающих права доступа дополнительных групп, то применяются
соответствующие права.
5. В остальных случаях применяются права доступа для других пользователей.
Для управления списками контроля доступа используется команда setfacl, которая
позволяет изменить (или добавить) записи (ключ -m) или удалить записи (ключ -x). Можно
указать несколько записей, разделенных запятыми, соблюдая следующий синтаксис:
setfacl [ключ] {user|group|other|mask}:[username|groupname]:{r|}{w|-}{x|-} имя_файла
Первое поле уточняет тип записи и может быть сокращено до первой буквы (u|g|o|m).
Второе поле связано только с пользователем и группой и задает пользователя или группу.
Если оно пустое, используются пользователь-владелец или группа-владелец файла. В
последнем поле указываются права доступа.
Пример использования команды setfacl:
[user1@station ~]$
file1.txt
[user1@station ~]$
# file: file1.txt
# owner: user1
# group: users
user::rwuser:ivan:r-user:petr:rwgroup::rwgroup:physics:rwmask::rwother::--[user1@station ~]$
[user1@station ~]$
# file: file1.txt
# owner: user1
# group: users
user::rwuser:petr:rwgroup::rwgroup:physics:rwmask::rwother::---
setfacl -m g:physics:rw,u:petr:rw,u:ivan:r
getfacl file1.txt
setfacl -x u:ivan file1.txt
getfacl file1.txt
У каталогов в отличие от файлов есть два набора списков контроля доступа: стандартные и
по умолчанию. Стандартные списки отвечают за доступ к самому каталогу, точно так, как
указано выше. Списки по умолчанию не применяются к каталогу, а вместо этого
устанавливают списки контроля доступа для каждого файла, созданного внутри этого
каталога.
Списки контроля доступа по умолчанию задаются так же, как и стандартные, но с
добавлением в начало четвертого поля слова default (которое можно сократить до "d").
[user1@station ~]$ chmod g+s dir – используется для того, чтобы файлы в
каталоге по умолчанию имели ту же группу-владельца, что и каталог
[user1@station ~]$ setfacl -m g:physics:r-x dir/
[user1@station ~]$ setfacl -m default:g:physics:r dir/
[user1@station ~]$ getfacl dir/
# file: dir
# owner: user1
# group: users
user::rwx
group::rwx
group:physics:r-x
mask::rwx
other::--default:user::rwx
default:group::rwx
default:group:physics:r-default:mask::rwx
default:other::---
4.5. Вопросы для самоконтроля
1. Как можно контролировать права пользователей и процессов к объектам в ОС
UNIX? Какие средства для этого предназначены?
2. Какие базовые средства разграничения прав доступа вам известны? Как выдаются
права доступа на файл, на каталог, на каталог с файлами?
3. Что такое Sticky Bit, Suid?
4. Можно ли выдать права доступа к файлам и каталогам нескольких пользователям
или группам, закрыв доступ к этим объектам для других субъектов?
5. Процессы в UNIX
5.1. Понятие процесса
UNIX — многопользовательская многозадачная операционная система. Концепция
процесса является базовой для архитектуры ОС. Процесс создается с помощью системного
вызова fork. Процесс в первом приближении можно определить как экземпляр
выполняющейся программы с необходимым для ее выполнения набором ресурсов. В
рамках ОС процесс представлен некоторым набором структур данных. Базовая структура
данных – таблица процессов, в которой каждый процесс представлен одной записью
(дескриптором процесса). Поля этой структуры описывают различные характеристики
процесса (перечислены некоторые из них):
PID
уникальный числовой идентификатор процесса
PPID
идентификатор родительского процесса
STATUS состояние процесса
TIME
время выполнения процесса (суммарно в режиме ядра и режиме задачи)
START
время запуска процесса
TTY
терминал процесса
PRI
текущий приоритет процесса
NI
значение nice
RUID
реальный идентификатор владельца процесса
EIUD
эффективный идентификатор владельца процесса
RGID
реальный идентификатор группы
EGID
эффективный идентификатор группы
CPU
процент использования процессорного времени
использование физической памяти
MEM
Список процессов с перечнем полей можно получить при помощи команды ps. Различные
опции команды определяют перечень процессов и список выводимых полей.
Процесс в системе может находиться в некотором состоянии (поле STATUS). Только один
процесс в каждый момент времени может выполняться на процессоре (иметь состояние R).
Для многопроцессорных систем таких процессов может быть несколько. В рамках
процесса может выполняться прикладная задача пользователя (пользовательский процесс),
а может – системная задача (системный процесс).
В общем случае процесс может находиться в одном из следующих состояний,
составляющих так называемый жизненный цикл процесса:

готов к запуску;

выполнение в режиме ядра;

выполнение в режиме задачи;

создан;

ожидание;

зомби.
5.2. Состояния процесса
Рассмотрим подробнее каждое состояние процесса. Как уже говорилось, процесс создается
системным вызовом fork. В этот момент порождаемый процесс находится в состоянии
«создан». Происходит инициализация необходимых структур данных ядра и выделения
процессу необходимых ресурсов. После чего процесс переходит в состояние «готов к
запуску».
В этом состоянии находятся все процессы, которые обладают всеми необходимыми
ресурсами и конкурируют между собой за доступ к процессору. Планировщик процессов
работает только с процессами, находящимися в этом состоянии. Его роль – определять в
каждый момент времени, какому процессу предоставить процессор.
Далее процесс попадает в состояние «выполнение в режиме ядра». В этом состоянии
процессор выполняет системные инструкции ядра в контексте данного процесса. Процесс
последовательно несколько раз переключается из состояния «выполнение в режиме ядра»
в состояние «выполнение в режиме задачи». В состоянии «выполнение в режиме задачи»
процессор выполняет прикладные инструкции процесса. Переход обратно в состояние
«выполнение в режиме ядра» происходит при выполнении процессом системного вызова
(стандартное обращение к ядру для запроса каких-либо сервисных функций: открыть файл,
создать процесс, запросить системное время и т.п.) либо по прерыванию от таймера. В
режиме ядра процессу доступны все структуры данных ядра, которые он может
модифицировать, но при этом выполняется только код ядра. В режиме задачи процессу
доступно только собственное виртуальное адресное пространство, но при этом процесс
выполняет пользовательские инструкции, решающие конкретную прикладную задачу.
При очередном переключении из состояния «выполнение в режиме ядра» в состояние
«выполнение в режиме задачи» планировщик процессов может принять решение о
переключении контекста. В этом случае текущий процесс будет переведен в состояние
«готов к запуску», а некоторый другой процесс, находящийся в данный момент в
состоянии «готов к запуску будет переведен в состояние «выполнение в режиме ядра».
Переключение контекстов планировщик производит только именно в этот момент
времени, так как только в момент выхода процесса из состояния «выполнение в режиме
ядра» все структуры данных ядра находятся в целостном состоянии. Можно еще так
пояснить это переключение. Все процессы, находящиеся в состоянии «готов к запуску»,
можно считать «замороженными» в момент перехода из состояния «выполнение в режиме
ядра» в состояние «выполнение в режиме задачи». То есть у процесса сохранена вся
информация, которая необходима ему для продолжения выполнения. Планировщик
каждый
раз
«замораживает»
очередной
процесс
(сохраняет
его
состояние)
и
«размораживает» другой процесс (восстанавливает ранее сохраненное состояние).
В состоянии «выполнение в режиме ядра» процессу может понадобиться дождаться
какого-либо события. В этом случае он будет переведен в состояние «ожидание».
Например, процесс запросил ввод данных с клавиатуры. В этом случае будет ожидание
ввода данных с клавиатуры. Процесс с помощью системного вызова pause может запросить
ожидание поступления каких-либо сигналов. Процесс мог попасть в состояние
«выполнение в режиме ядра» из-за страничного прерывания. В этом случае будет
ожидание загрузки в оперативную память необходимой страницы. Возможны и другие
ситуации, в которых процесс будет переведен в состояние «ожидание». После наступления
соответствующего события процесс будет переведен в состояние «готов к запуску» и
продолжит конкуренцию за доступ к процессору.
Последнее состояние процесса – состояние «зомби». В этом состоянии процессу уже не
выделены никакие ресурсы. Осталась только запись в таблице процессов, содержащая
статистику его выполнения и статус завершения, которые могут быть запрошены
родительским процессом. В это состояние процесс может попасть по собственной
инициативе,
выполнив
системный
вызов
exit,
или
принудительно,
получив
соответствующий сигнал от другого процесса. Выход из этого состояния с полным
уничтожением процесса (то есть удалением записи из таблицы процессов) происходит при
выполнении родительским процессом системного вызова wait или при переходе
родительского процесса в состояние «зомби».
Все процессы системы являются частью иерархии отец-сын. То есть у любого процесса,
кроме процесса с PID равным 1 (процесс init), есть родительский процесс,
идентификатор которого записан в поле PPID и который в свое время породил данный
процесс при помощи системного вызова fork.
Особое значение имеет системный процесс init, который запускается в самом начале
работы системы и является предком всех процессов. Его PID фиксирован и всегда равен 1.
Этот процесс должен существовать всегда. Его завершение происходит только при
останове или перезагрузке ОС.
5.3. Интерфейс пользователя. Задания
Рассмотрим теперь процессы с точки зрения интерфейса пользователя, который
реализуется при помощи командного интерпретатора. Основная команда при работе с
процессами – команда ps. По умолчанию (без параметров) она позволяет получить на
экране список процессов, запущенных с текущего терминала. Для каждого процесса
выводится некоторый список его параметров: PID, STATUS, TTY и т.п. Данная команда
имеет большое количество опций, которые позволяют определить набор процессов,
информацию о которых необходимо получить, а также перечень параметров.
Большинство командных интерпретаторов обеспечивает удобное управление процессами
путем организации заданий. Задание в общем случае может включать несколько
процессов, объединенных каким либо образом, например связанные программным
каналом. Управление заданием осуществляется как единым целым.
Задание обычно запускается в интерактивном режиме. Это означает, что терминал
(клавиатура и дисплей) монопольно будут использоваться данным заданием. Ввод с
клавиатуры будет передаваться процессам данного задания. Вывод будет направляться на
экран. Управляющие комбинации клавиш будут приводить к посылке сигналов данному
заданию. Ниже перечислены управляющие комбинации клавиши, которые могут быть
применены к интерактивному заданию.
ctrl-s приостанов диалога с пользователем
ctrl-q возобновление диалога с пользователем
ctrl-d конец ввода информации со стандартного ввода (если нет интерактивного процесса, то эта
комбинация клавиш приведет к завершению работы командного интерпретатора)
ctrl-c прерывание задания
ctrl-\ прерывание задания с созданием аварийного дампа памяти
ctrl-z приостанов задания
Задание может быть запущено в фоновом режиме. В этом случае оно не может обращаться
к терминалу. При необходимости ввод и вывод должны быть перенаправлены в
соответствующие
файлы.
Управление
таким
заданием
может
осуществляться
специальными командами командного интерпретатора.
Каждому заданию командный интерпретатор присваивает числовой идентификатор,
который в отличие от идентификатора процесса уникален только в пределах данного
командного интерпретатора. Поэтому в командах, которые могут быть адресованы не
только заданию, но и процессу (kill) перед идентификатором задания ставится символ %,
чтобы отличить это значение от идентификатора процесса PID.
Для получения списка заданий текущего командного интерпретатора используется
команда jobs. Перед каждым заданием в квадратных скобках выводится его номер,
который необходимо использовать в командах управления заданиями. Рассмотрим
подробнее эти команды. Задание создается и запускается на выполнение при вводе
командной строки. Задание может быть запущено двумя способами: в интерактивном
режиме и в фоновом. Для запуска задания в фоновом режиме необходимо в конце
командной строки указать символ &. Если задание запущено в интерактивном режиме, то
все набираемые на клавиатуре символы предаются процессам этого задания, ввод команд
командного интерпретатора невозможен. С помощью комбинации клавиш ctrl-z можно
приостановить выполнение текущего интерактивного задания и вызвать командный
интерпретатор.
Далее
можно
с
помощью
команды
bg
перевести
выполнение
приостановленного задания в фоновый режим. А другое задание, которое в данный момент
выполняется в фоновом режиме или приостановлено, с помощью команды fg перевести в
интерактивный режим. Команды bg и fg требуют указания параметра – номера задания с
предшествующим ему символом %. Если номер задания не указан, то используется
текущий номер – последнее приостановленное задание. Если трудно определить, какое
задание командный интерпретатор считает текущим, то можно либо указывать номер
задания явно либо посмотреть вывод команды jobs. Текущее задание будет помечено
знаком «+», а предыдущее текущее – знаком «-». Также можно ссылаться на текущее и
предыдущее задания в командах kill, bg и fg с помощью идентификаторов %+ и %-.
Фоновое задание может быть принудительно системой приостановлено при попытке
чтения со стандартного ввода. В этом случае необходимо перевести это задание в
интерактивный режим и ввести с клавиатуры необходимые данные.
Рассмотрим создание и работу процессов на примере процедуры. Выполнение shпроцедуры начинается порождением процесса командного интерпретатора, который будет
выполнять команды, записанные в соответствующем текстовом файле – файле shпроцедуры.
Это
стандартный
процесс,
обладающий
всеми
характеристиками,
рассмотренными выше.
Пример:
$ ps
PID
TTY
6696 pts/0
6715 pts/0
$ cat proc
date
ls
$ proc
< дата>
f2
$ ps
PID
TTY
6696 pts/0
6725 pts/0
$
TIMЕ
00:00:00
00:00:00
CMD
bash
ps
TIMЕ
00:00:00
00:00:00
CMD
bash
ps
Первой командой мы посмотрели список процессов, запущенных с текущего терминала.
Командный интерпретатор bash и сама утилита ps. Поскольку мы не указали никаких
опций, то вывод утилиты предельно лаконичен: всего четыре поля.
Далее с помощью команды cat мы смотрим листинг процедуры proc и запускаем ее,
указав имя процедуры proc. Каждая команда sh-процедуры выполняется порожденным
для неё процессом (как обычно для команды, введенной с клавиатуры). Как только все
команды окажутся выполненными, sh-процесс завершается и управление возвращается
родительскому процессу. Процедура выполнена. Далее с помощью команды ps мы
убеждаемся, что никаких лишних процессов в системе не осталось. Обратим внимание, что
PID процесса bash остался прежним, а утилиты ps изменился. Действительно, каждый раз
при выполнении команды командный интерпретатор создает новый процесс. В данном
примере для выполнения утилиты ps командный интерпретатор два раза создавал новый
процесс. Если мы завершим сеанс работы и заново зарегистрируемся в системе, то
изменится PID и у командного интерпретатора, так старый процесс будет завершен, и при
новом входе в систему будет запущен новый процесс командного интерпретатора.
Рассмотрим теперь пример с использованием фонового процесса.
Пример:
$ cat proc2
while :
do
sleep 1
done
$ proc2
^Z
[1]+ Stopped proc2
$ jobs
[1]+ Stopped proc2
$ fg %1
proc2
^C
$ proc2 &
[1] 6818
$ jobs
[1]+ Running proc2 &
$ fg %1
proc2
^Z
[1]+ Stopped proc2
$ bg %1
[1]+ proc2 &
$ kill %1
$
[1]+ Terminated proc2
$
Первое действие – выполнение команды cat для просмотра листинга процедуры proc2.
Мы видим, что это простая зацикленная процедура. Далее запускаем ее в интерактивном
режиме. Процедура в процессе своей работы ничего не вводит и ничего не выводит, но
поскольку она запущена в интерактивном режиме, то терминал предоставлен данной
процедуре,
и
вводить
команды
командного
интерпретатора
мы
не
можем.
Приостанавливаем выполнение процедуры при помощи комбинации клавиш ctrl-z.
Появляется сообщение командного интерпретатора, что задание, в рамках которого
выполнялась процедура, приостановлена. Номер задания – 1. Данное задание является
текущим. С помощью команды jobs мы видим, что данное задание является
единственным для данного командного интерпретатора. С помощью команды fg
переводим задание в интерактивный режим. Опять терминал полностью предоставляется
интерактивному заданию,
и
ввод
команд
становится
невозможным.
Прерываем
выполнение задания при помощи комбинации клавиш ctrl-c.
Повторно запускаем процедуру proc2. В конце командной строки указываем символ &.
Задание запускается в фоновом режиме. Командный интерпретатор сообщает нам номер
задания и PID процесса. Заметим, что если запускается в фоновом режиме задание,
состоящее из нескольких процессов, то на экран выводится PID процесса лидера задания.
С помощью команды jobs убеждаемся, что задание выполняется в фоновом режиме.
Переводим задание в интерактивный режим (команда fg). Далее при помощи комбинации
клавиш ctrl-z приостанавливаем его и опять переводим в фоновый режим. Завершаем
выполнение задания командой kill.
Рассмотрим еще один вопрос, касающийся выполнения заданий в фоновом режиме –
перенаправление вывода. Эта возможность применима и для интерактивных заданий, но
чаще всего перенаправление вывода используется при выполнении заданий в фоновом
режиме. Действительно, если в текущий момент времени у командного интерпретатора
есть несколько заданий, то только одно задание может выполняться в интерактивном
режиме, все остальные будут фоновые. Интерактивное задание выводит результаты своей
работы на экран, а все фоновые задания с использованием механизма перенаправления
ввода-вывода выводят информацию в соответствующие файлы. Приведем протокол
работы без подробных комментариев, так как все команды уже разобраны в предыдущих
примерах. Отметим только, что указав в конце командной строки, но перед символом & >
имя_файла, мы сообщаем командному интерпретатору, что результат выполнения
соответствующей команды необходимо записывать в файл. Если файл не существовал, то
он будет создан, если существовал, то его содержимое будет потеряно. Использование >>
предотвращает потерю предыдущего содержимого файла и добавляет новую информацию
в конец файла.
Пример:
$ cat proc3
while :
do
echo proc3
sleep 1
done
$ cat proc4
while :
do
echo proc4
sleep 1
done
$ proc3 > f3 &
[1] 11201
$ proc4
proc4
proc4
proc4
^C
$ jobs
[1]+ Running proc3 > f3 &
$ kill %1
$
[1]+ Terminated proc3 > f3
$ cat f3
proc3
proc3
proc3
proc3
proc3
$ proc4 >> f3 &
[1] 11211
$ kill %1
$
[1]+ Terminated proc4 >> f3
$ cat f3
proc3
proc3
proc3
proc3
proc3
proc4
proc4
$
5.4. Управление приоритетами процессов
Не все процессы для системы имеют одинаковое значение. Очевидно, что системный
процесс должен иметь больший приоритет, чем процесс любого пользователя. С другой
стороны, гибкая система должна позволять даже одному пользователю назначать разные
приоритеты своим процессам. Обычно фоновым процессам назначают меньший
приоритет, чем интерактивным. То есть фоновые процессы должны выполняться только
тогда, когда у системы нет в состоянии «готов к запуску» ни одного интерактивного
процесса. Если же появляется интерактивный процесс, то система должна в срочном
порядке предоставить ему процессорное время, так как велика вероятность, что отработав
действие пользователя, он опять перейдет в состояние ожидания следующего действия.
(Пользователи работают гораздо медленнее, чем ОС.)
Приоритет
–
динамическая
характеристика
процесса.
Планировщик
постоянно
пересчитывает приоритеты процессов в зависимости от текущей ситуации в системе.
Пользователи могут влиять на назначение приоритета только опосредованно, меняя
значение так называемой поправки к приоритету NICE. Планировщик при вычислении
динамического приоритета учитывает значение этой поправки. Значение NICE может
меняться в диапазоне от -20 до +19. Причем меньшее значение соответствует большему
приоритету. Например, процессу со значением NICE 0 всегда будет назначаться более
высокий приоритет, чем процессу со значением NICE 5.
Значение динамического приоритета и поправки можно увидеть, если использовать
команду ps с опцией -l (поля PRI и NI). Каждый процесс наследует значение NICE от
своего родительского процесса. Обычно у командного интерпретатора значение NICE
равно 0, то есть все выполняемые команды наследуют это значение 0. Обычные
пользователи могут только увеличивать значение NICE (уменьшать приоритет). А
администратору системы доступно и увеличение приоритета. Запустить команду с
измененным значением NICE можно при помощи команды nice. Без параметров значение
NICE увеличивается на 10. Параметр задает, на сколько единиц увеличить значение
поправки к приоритету. Администратору системы доступно отрицательное значение
параметра.
Пример:
$ nice proc2 &
[1] 11657
$ nice -5 proc2 &
[2] 11663
$ nice --5 proc2 &
[3] 11689
$ nice: cannot set niceness: Permission denied
$ jobs
[1] Running nice proc2 &
[2]- Running nice -5 proc2 &
[3]+ Running nice --5 proc2 &
$ ps -l
PID
PPID PRI NI
TTY
11318
11317
80
0
11657
11318
90
10
11663
11318
85
5
11689
11318
80
0
11741
11663
85
5
11742
11689
80
0
11743
11657
90
10
11744
11318
80
0
$
TIME
pts/0
pts/0
pts/0
pts/0
pts/0
pts/0
pts/0
pts/0
CMD
00:00:00
00:00:00
00:00:00
00:00:00
00:00:00
00:00:00
00:00:00
00:00:00
bash
sh
sh
sh
sleep
sleep
sleep
ps
В представленном примере запускаются три фоновых задания с изменением поправки к
приоритету при помощи команды nice. Без параметров – в этом случае используется
значение по умолчанию 10. С указанием положительного параметра 5. С указанием
отрицательного параметра -5 – в этом случае получаем сообщение об ошибке, так как
обычный пользователь не может уменьшать поправку к приоритету. Задание все равно
запускается, но без изменения поправки к приоритету. Далее убеждаемся при помощи
команды jobs, что все задания выполняются в фоновом режиме. Листинг вывода команды
ps -l требует пояснения. Дело в том, что при выполнении shell-процедуры для каждой
команды порождается отдельный процесс, который наследует поправку к приоритету от
родительского
процесса.
Поэтому
мы
видим
собственно
процесс
командного
интерпретатора и порожденный им процесс sleep. Предлагаем читателю самостоятельно
проанализировать поле PPID (идентификатор родительского процесса) у соответствующих
процессов, что понять их иерархическую взаимосвязь.
5.5. Межпроцессное взаимодействие
Процессы в системе могут между собой взаимодействовать. Более того, процессов,
выполняющихся автономно, практически не существует. В основном встречаются
процессы, которые постоянно обмениваются между собой какой либо информацией.
Например, любая внешняя команда извещает командный интерпретатор о своем
завершении
посылкой
специального
сигнала.
Рассмотрим
основные
способы
межпроцессного взаимодействия.
Самый простой способ информационного взаимодействия, не требующий каких-либо
специальных средств – использование общего файла. Один процесс записывает какуюлибо информацию в файл, а другой процесс ее считывает из файла. Для удобства
организации информационного взаимодействия между процессами в UNIX существуют
также и специальные средства, предназначенные для такого взаимодействия. Это сигналы,
каналы, FIFO-файлы, сокеты, очереди сообщений, семафоры, разделяемые сегменты
памяти.
Следующий способ взаимодействия организован при помощи сигналов. В этом случае
один процесс извещает другой процесс о наступлении какого-либо события. Сигнал
характеризуется номером и определяет, какое событие в данный момент наступило.
Номера сигналов в различных UNIX-подобных ОС могут различаться. Поэтому обычно
используют символьное имя сигнала. При взаимодействии двух процессов между собой
лучше использовать специальные сигналы SIGUSR1 и SIGUSR2, которые специально
предназначены для взаимодействия процессов и на которые не возложены какие-либо
другие функции. Для посылки сигналов используется команда kill и одноименный
системный вызов. Ядро ОС также может извещать процесс о наступлении какого-либо
события. В этом случае используются специальные сигналы, имена которых как раз и
определяют, какое событие наступило. Например, сигнал SIGCHLD извещает процесс о
том, что один из его потомков перешел в состояние зомби.
После получения сигнала процесс выполняет определенные действия, называемые
диспозицией сигнала. Существует три вида диспозиции: диспозиция по умолчанию (для
большинства процессов завершение выполнения), игнорирование, перехват (выполнение
собственной функции-обработчика). Мы уже пользовались механизмом сигналов, когда с
помощью команды kill завершали выполнение фоновых процессов. По умолчанию
команда kill посылает специальный сигнал SIGTERM, который приводит к завершению
процесса. Можно поменять диспозицию сигнала при помощи команды trap, и тогда
процесс уже не будет завершать свое выполнение при поступлении сигнала SIGTERM, а
будет выполнять другое заданное пользователем действие.
Кроме символических имен у сигналов есть номера. Более того система работает с
номерами сигналов, а символические имена введены для удобства работы пользователей.
Соответствие между символическими именами и номерами сигналов можно посмотреть,
использую опцию -l команды kill. Команда kill позволяет задать номер посылаемого
сигнала или его символическое имя. Сигнал SIGTERM имеет номер 15. Еще один
интересный сигнал – SIGKILL, его номер 9. Диспозицию сигнала SIGKILL изменить
невозможно. Посылка этого сигнала всегда приводит к завершению процесса.
Пример:
$ cat proc5
trap "echo signal received" 15
while :
do
sleep 1
done
$ proc5 &
[1] 12311
$ kill %1
signal received
$ jobs
[1]+ Running proc5 &
$ kill -9 %1
$
[1]+ Killed proc5
$
Мы видим, что в процедуре proc5, изменена диспозиция для сигнала с номером 15.
Посылка процессу этого сигнала приводит к появлению соответствующего сообщения и
продолжению выполнения процедуры. Завершить процесс удается только второй командой
kill, указав в опции номер сигнала 9.
Следующее средство межпроцессного взаимодействия – это каналы. Каналы бывают двух
типов: именованные и неименованные. Как следует из их названия основное отличие как
раз в этом и заключается: именованные каналы имеют имя в файловой системе, по
которому к нему может обратиться любой процесс (если позволяют права доступа). У
неименованных каналов имя отсутствует, поэтому использовать это средство могут только
родственные процессы, то есть родительский и дочерний процессы или потомки одного
родителя, так как произвольный процесс получить доступ к этому каналу не сможет. В
остальном именованные и неименованные каналы ничем не отличаются и предназначены
для передачи потока байтов от одного процесса к другому. Канал может обеспечить только
однонаправленную связь. Следовательно, если процессы хотят обеспечить двустороннее
взаимодействие, то им необходимо создать два канала с противоположным направлением
потока данных. Конвейеры команд в командном интерпретаторе используют для
организации связи между процессами неименованные каналы.
Пример:
$ ls
f1 f2 f3 f4
$ ls | wc –w
4
$
В данном примере мы используем конвейер команд между командой ls и командой wc.
Стандартный вывод команды ls направляется на стандартный ввод команды wc. В итоге
команда wc с опцией -w подсчитывает количество слов (имен файлов) в выводе команды
ls.
Рассмотрим теперь сокеты – средство межпроцессного взаимодействия, впервые
появившееся в BSD-версиях ОС UNIX. Оно оказалось очень удобным и в настоящее время
присутствует во всех реализациях ОС UNIX. Более того, сокеты присутствуют даже в не
UNIX-системах, в частности – в Windows. Чаще его так и называют – BSD-сокеты. В
первом приближении сокет можно представить как два канала с противоположным
направлением потока данных. В отличие от каналов сокеты (только определенных типов)
позволяют взаимодействовать процессам, находящимся не только в одной UNIX-системе,
но и в разных системах, соединенных телекоммуникационными каналами связи, с
использованием сетевых протоколов.
Перейдем к рассмотрению сразу трех средств межпроцессного взаимодействия, которые
достаточно сильно отличаются друг от друга по своей сути, но очень похожи по способу
подключения к ним процессов. Впервые они были реализованы в классическом UNIX
AT&T в SYSTEM V. Поэтому их часто называют IPC (Inter Process Communication)
SYSTEM V. Это очереди сообщений, семафоры и разделяемая память. Для начала
взаимодействия при помощи данных средств каждый процесс должен сгенерировать ключ.
Для взаимодействия между собой у процессов должен быть одинаковый ключ. Напротив,
разные ключи говорят о том, что информационные потоки этих процессов не будут
пересекаться между собой. Ключ генерируется при помощи специальной функции,
позволяющей, с одной стороны, сгенерировать один и тот же ключ, когда это необходимо,
с другой стороны, разный ключ, когда процесс хочет организовать изолированный
информационный поток.
Очереди сообщений напоминают почтовый ящик, в который каждый процесс может
поместить сообщение, а другой процесс извлечь сообщение. В самом простом случае
сообщения извлекаются из ящика в порядке поступления, то есть первым будет извлечено
из ящика то сообщение, которое было туда помещено раньше всего. Более сложный режим
работы позволяет организовать приоритетную очередь, где у каждого сообщения будет
приоритет. В этом случае первым извлекается сообщение указанного приоритета,
помещенное в очередь раньше всего. В системе может быть создано несколько почтовых
ящиков (очередей сообщений), каждый из которых будет идентифицироваться своим
ключом.
Семафоры предназначены для синхронизации доступа к некоторому критическому
ресурсу. То есть если ресурсом в данный момент обладает какой-либо процесс, то с
помощью семафора доступ другого процесса к данному ресурсу будет заблокирован до тех
пор, пока первый процесс не освободит данный ресурс. Этот алгоритм работы характерен
для так называемых двоичных семафоров. Но в ОС UNIX семафоры являются общими, то
есть могут принимать любые неотрицательные значения (от 0 до некоторого предельного
значения). Данное свойство UNIX-семафоров позволяет их использовать в более
универсальных случаях, когда некоторый ресурс одновременно может быть занят не более
чем N процессами. ОС обеспечивает атомарность операций над семафорами. То есть
между проверкой значения семафора и его изменением текущий процесс не может быть
прерван другим процессом.
Разделяемая память позволяет организовать самый быстрый способ обмена информацией
между процессами. Страницы разделяемой памяти одновременно доступны в адресном
пространстве нескольких процессов. То есть информация, записанная в такую страницу
одним процессом, становится сразу доступна всем остальным процессом. Разделяемая
память обладает одним недостатком: доступ к ней никак не синхронизируется. Поэтому
процесс, осуществляющий запись в страницу разделяемой памяти, может быть прерван
другим процессом, который прочтет некорректную информацию. Чтобы не допустить этой
ситуации обычно вместе с разделяемой памятью используют какое-либо средство
синхронизации, например семафоры.
5.6. Вопросы для самоконтроля
1. Понятия процесса в ОС UNIX. Состояния процесса.
2. Задание. Управление заданиями. Интерактивные и фоновые задания.
3. Перенаправление вывода фоновых процессов.
4. Принципы назначения приоритета процессу. Управление поправкой к приоритету.
5. Средства межпроцессного взаимодействия. Диспозиция сигналов. Принудительное
завершение процесса.
6. Очереди сообщений. Семафоры. Разделяемая память.
7. Использование конвейера команд.
6. Введение в shell-программирование
6.1. Понятие процедур
Оболочка
shell
является
основным
средством
взаимодействия
пользователя
с
операционной системой в режиме командной строки. Shell обеспечивает интерпретацию и
исполнение команд, вводимых пользователем из командной строки терминала, а также
исполнение
программ,
написанных
на
одном
из
языков
программирования
и
содержащихся (после обработки компилятором и редактором связей) в исполняемом
бинарном файле. Такая программа может быть также написана на языке shell. В этом
случае она называется shell-процедурой и не требует предварительной обработки
компилятором и редактором связей перед ее исполнением, так как будет выполняться
оболочкой в режиме интерпретации. Shell-процедура может содержать любые команды
операционной системы (внешние команды), внутренние (встроенные в оболочку) команды,
а также и вызовы других shell-процедур.
Исполнение shell-процедуры внешне ничем не отличается от исполнения любой команды
Unix. Для передачи информации в процедуру существует 3 способа: через позиционные
параметры при вызове процедуры, через глобальные переменные (переменные среды
операционной системы), путем ввода информации командой read во время выполнения
процедуры.
В процедуре можно использовать любые конструкции, допустимые в командной строке
операционной системы (именованные и неименованные программные каналы, конвейеры
команд, переадресацию ввода-вывода и т.д.).
Текст процедуры набирается как обычный текстовый файл. Для этих целей при создании
большой процедуры целесообразно использовать один из редакторов, например редактор
vi. Для создания простейших процедур можно использовать команду cat или какой-либо
другой способ создания пустых файлов с последующим заполнением командами ОС или
операторами языка shell.
Проверенный и отлаженный shell-файл с именем proc1 может быть вызван на
исполнение, например, следующим способом:
$ chmod u=rx proc1
$ proc1
$
Для выполнения процедуры необходимы права r,x; обычно право r уже задается
администратором для всех создаваемых обыкновенных файлов, поэтому в команде chmod
можно добавить только право доступа на выполнение: chmod u+x.
Такая форма запуска процедуры предполагает, что файл процедуры новый и его надо
сначала сделать выполняемым.
Можно использовать также и следующий способ:
$ sh -c "proc1"
или
$ sh proc1
Здесь файл proc1 предполагается читаемым для shell, т.е. имеет право r.
В этих случаях по команде sh вызывается вторичный интерпретатор shell, и в качестве
аргумента ему передается командная строка, содержащая имя файла процедуры proc1,
находящегося в текущем каталоге. Однако этот способ накладывает ограничения на
исполнение некоторых команд ОС управления процессами (например, nice – см. ниже).
Процедуре при ее запуске могут быть переданы аргументы. В общем случае командная
строка вызова процедуры имеет следующий вид:
$ имя_процедуры $1 $2 ...$9
$
Каждому из девяти передаваемых процедуре при ее вызове из командной строки
позиционных параметров соответствует в теле процедуры переменная $1, $2, ..., $9.
Переменная $0 соответствует имени самой процедуры, т.е. первому полю командной
строки. К каждому из 10 первых параметров можно обратиться из процедуры, указав
номер его позиции в командной строке. Если параметров больше 9, то соответствующий
аргумент в теле процедуры нужно заключить в фигурные скобки, например ${10}, ${11} и
т.д.
Переменная $# в теле процедуры хранит число переданных в процедуру параметров, а $*
хранит символьную строку, содержащую все переданные процедуре параметры.
Переменная $$ хранит текущий идентификатор (PID) процесса. Переменная $! хранит PID
последнего запущенного процесса в фоновом режиме. Переменная
$- хранит опции
интерпретатора.
Передача аргументов функции осуществляется так же, как и процедуре.
В shell-процедурах часто используются, в основном для организации диалога (но не
только), следующие команды Unix:
echo — вывод текста процедуры на экран (в стандартный вывод).
$ echo “начало строки
> продолжение строки”
или
$ echo “строка текста”
$
Символ # используется для обозначения строки комментария в процедуре. (Строка не
будет обрабатываться shell.)
Простейший пример. Здесь оператор echo выполняется также в командном режиме. На
экран выводится третий параметр, передаваемый процедуре при ее запуске:
$shfil p1 pp2 petr
$echo $3
petr
$
Значения параметрам, передаваемым процедуре, можно присваивать и в процессе работы
процедуры с помощью команды
set — присвоить значения позиционным параметрам.
Пример:
$set a1 ab2 abc
$echo $1 $2
a1 ab2
$
В этом примере параметры указываются в явном виде. Количество позиционных
параметров может быть увеличено до необходимого значения путем “сдвига” их в
командной строке влево на одну или заданное количество позиций с помощью команды
shift:
shift [n] — сдвинуть позиционные параметры влево на одну (или n) позиций.
После выполнения shift прежнее значение параметра $1 теряется, $1 принимает
значение $2, а $2 — значение $3 и т.д.
Продолжение предыдущего примера:
$shift
$echo $1 $2
ab2 abc
$
В системе UNIX при написании командных строк и в shell-процедурах особое значение
имеет правильное использование кавычек:
'...' — для блокирования полного набора специальных символов, которые могут быть
интерпретированы как управляющие;
"..." — для блокирования некоторых символов, которые могут использоваться в именах
переменных, или для указания того, что обрабатывается не сам аргумент, а его значение
(подстановка значения), в частности не блокируют $, `…`,\ ;
`...` — (обратные кавычки, или знак тупого ударения) для указания того, что они
обрамляют команду, и здесь будет обрабатываться результат работы этой команды
(подстановка результатов работы указанной команды).
Пример 1:
$ date
Apr 3 14:27:07
$ set `date`
$ echo $3
14:30:25
$
Пример 2:
$echo `ls`
file.1
2007
file.2
...
$echo '`ls`'
`ls`
$
Здесь
одинарные
кавычки
блокируют
действие
обратных
кавычек,
т.е.
они
интерпретируются как обычные символы.
Пример 3.
$ls -al|grep “Mar 30”
#выводится информация о всех файлах текущего каталога,
модифицированных
# 30 марта всех годов.
# Эта же командная строка без кавычек приобретает совершенно
другой смысл:
$ls -al|grep Mar 30
# здесь Mar –шаблон, а 30 – имя файла.
Для ввода строки текста со стандартного устройства ввода используется команда:
read имя1 [имя2 имя3 .] — чтение строки слов со стандартного устройства ввода.
Обычно приглашение на ввод выводится пользователю с помощью команды echo.
Поэтому каждой команде read должна предшествовать команда echo. Команда read
будет задавать список имен переменных, которым в качестве значений будут
присваиваться слова, вводимые пользователем в ответ на приглашение. Если в команде
read указано больше переменных, чем вводится слов, то самым правым переменным
списка присваивается значение NULL. Если оказывается, что количество введенных
пользователем слов больше, чем количество переменных, последней переменной
присваивается весь остаток строки.
Пример (предполагает наличие программы-русификатора):
#Текст процедуры:
echo "Введите значения текущих: гг
мм
чч вв"
read 1v 2v 3v
echo "год 1v"
echo "месяц 2v"
echo "сегодня 3v"
# здесь кавычки используются для блокирования пробелов
#Результат выполнения процедуры:
Введите значения текущих: гг
мм
чч вв
2009
Maрт
21
9:30
<Enter>
год 2009
месяц Maрт
сегодня
21
9:30
6.2. Shell-функции
При программировании на языке shell можно использовать также оформленные
соответствующим образом функции.
Функция - это процедура, используемая внутри другой процедуры. В отличие от вызова
процедуры для функции не порождается отдельный shell (отдельный процесс). Она
исполняется в составе текущего shell, а ее копия хранится в памяти этого shell.
Исполнение функции происходит в текущем окружении. Это означает, что в окружении
вызывающего процесса shell имеется доступ к тому же текущему каталогу, что и в
окружении вызываемого процесса shell.
Синтаксис функции:
function имя_функции
{shell_текст}
или
имя_функции ()
{shell_текст}
Пример:
$ function install
{
echo Install file: $1
chmod +x $1
mv $1 $HOME/bin
echo Install complete
}
или
install ()
{
echo Install file: $1
chmod +x $1
mv $1 $HOME/bin
echo Install complete
}
Обращение к функции:
$ install myfile
Install file: myfile
Install complete
Имя функции должно быть уникальным. Допускается, что функция может иметь имя,
совпадающее с именем уже имеющейся переменной. Но нельзя использовать в качестве
имени зарезервированные слова, а также имена встроенных команд. В последнем случае
может получиться рекурсия, если внутри тела функции используется вызов встроенной
команды, у которой такое же имя, как и у функции.
Чтобы избежать рекурсий иногда используют специальную команду command.
Функции перед использованием загружаются в оперативную память, в результате чего
обеспечивается более быстрый доступ к ним. Функции можно также размещать в
отдельном файле, где содержатся только функции.
При использовании функции в составе некоторой процедуры, она должна быть
предварительно определена.
Определение должно находиться в начале текста процедуры с тем, чтобы функция «попала
в поле зрения» интерпретатора команд до момента, когда будет непосредственное
обращение к этой функции.
Для обращения к функции достаточно указать только имя функции.
При вызове функции ей можно передавать аргументы, используя тот же механизм,
который используется при передаче аргументов в процедуру. При этом значения
специальных переменных 1, 2, 3 и т.д., которые были использованы при передаче значений
аргументов в процедуру, вызывающей функцией будут затерты!!!
Поэтому рекомендуется сразу после входа в функцию запоминать текущие значения
указанных специальных переменных, а перед выходом из функции их восстанавливать.
Внутри функции можно использовать локальные переменные. Их имена начинаются с
префикса «_».
При выходе из функции с помощью оператора return n можно формировать требуемый
код возврата n.
При активном использовании нескольких функций все их определения можно поместить в
один файл функций. Он может иметь произвольное имя, но в его начале должен быть
помещен заголовок вида: #!/bin/ksh, где /bin/ksh – это shell, в среду которого будет
помещен файл функций.
Если файл функций был создан, то прежде, чем использовать включенные в него функции,
необходимо подключить этот файл к текущему shell. Это действие выполняется с
помощью специальной команды «.» и называется загрузкой функций:
$ . имя_файла_функций
Файл функций при этом будет загружен в среду текущего shell и далее можно будет
вызывать функции, которые в нем находятся, либо из командной строки, либо из
вызываемых процедур.
Существует также механизм автозагрузки. Предполагается, что можно создать несколько
файлов функций, каждый из которых содержит некоторое количество текстов различных
функций. Кроме того, эти файлы функций могут находиться в различных каталогах.
Нужно описать место расположения этих файлов с помощью переменной среды FPATH. В
этой переменной находится список каталогов, где следует искать файлы функций.
Элементы списка разделяются двоеточием.
При необходимости загрузки некоторой функции, например, fun13, в память текущего
shell, достаточно выполнить команду:
$ autoload fun13
Эта команда обратится к переменной FPATH, начнет поиск по каталогам, которые указаны
в списке каталогов в этой переменной и будет искать файл, который содержит указанную
функцию fun13. Если функция будет найдена, она загружается в память текущего shell.
После этого ее можно загружать из командной строки текущего shell на исполнение.
С помощью команды autoload можно загружать сразу несколько функций, указывая их
в качестве аргументов. (Команда autoload является синонимом команды typeset –
fu).
После подключения файла функций (или явного определения функций на уровне
командной строки) можно посмотреть содержание памяти функций текущего shell. Это
можно сделать с помощью команды typeset –f. -Тогда будут выведены на экран из
памяти функций все тексты загруженных функций. По команде typeset +f будет
выведен только список имен загруженных функций.
Чтобы удалить какое-либо определение функции из памяти функций следует выполнить в
отношении этой функции команду unset
имя_функции. При этом физического
удаления функции из файла функций не происходит. Его можно, при необходимости,
редактировать.
Пример:
Создать в текущем каталоге файл fun_file, который содержит библиотеку из двух
функций fl и f2. Сделать этот файл автозагрузочным. Далее вызывать на исполнение из
этого файла функции f1 и f2 с уровня командной строки.
1. Содержание файла funflle:
function fl
{
echo “This is function fl”
}
function f2
{
Echo “This is function Ј2”
}
2. Выполнить инициализацию переменной FPATH:
$ FPATH=.
Установить жесткие ссылки на файл fun_file (жесткие ссылки должны быть
именами функций):
$ ln fun_file fl
$ ln fun_file f2
3. Провести автозагрузку файла fun_file:
$ autoload fun_file
4. Проверить наличие в памяти текущего shell двух функций из файла fun_file:
$ typeset -f function f1
{
echo “This is function fl”
}
function f2
{
echo “This is function f2”
}
5. Обратиться к функции f2:
$ f2
This is function f2
6. Обратиться к функции f1:
$ f1
This is function f1
Замечания:
1. В составе имени функции не должен содержаться символ «.».
2. В составе тела одной функции не может быть определения другой функции.
Примеры:
1. Задать синоним pr=echo в составе функции fun, которая загружается в память
текущего shell и исполняется. Использовать данный синоним из текущего shell и из
subshell.
Пусть в текущем каталоге есть файл fun, в котором содержится функция: fun: fun ()
{
echo Function fun Argsi'S0' ”S0" "$*"
echo PID FUNCTION - $$
alias pr=echo
cd..
echo Direct. in fun= `pwd`
}
Загружаем функцию в память текущего shell:
$ . fun
Проверяем память функций текущего shell:
$ typeset -f
fun()
{
echo Function fun Args:'$0=' "$0" "$*"
echo PID FUNCTION - $$
alias pr=echo
cd..
echo Direct. in fun=`pwd`
Вызываем синоним рr:
$ рr хххх
рr: хххх: No such file or directory
Возникла ошибка потому, что синоним еще не был определен. Чтобы его определить
нужно выполнить функцию fun:
$ fun
Function fun Args:$0=ksh
PID FUNCTION - 19344
Direct. in fun= /home/student
Проверяем наличие синонима pr в памяти синонимов текущего shell:
$ alias
autoload=`typeset –fu`
command=`command`
fc=hist
float=`typeset -1E'
functions='typeset -f`
hash=`alias -t --`
history=`hist -l`
integer=`typeset -li`
nameref=`typeset –n`
nohup=`nohup`
pr=echo
r=`hist –s`
redirect=`command exec`
source=`command .`
stop=`kill -s STOP`
suspend=`kill -s STOP $$`
times=`{ {time;} 2>&1;}`
type=`whence –v`
$
Теперь вызываем синоним pr:
$ pr ххх
xxx
$
Все нормально.
Запускаем subshell: $ ksh
Теперь текущим является subshell.
Запускаем синоним:
$ pr ххх
рг: ххх: No such file or directory
$
В текущем subshell синоним оказался недоступным. Чтобы с ним можно было здесь
работать, нужно на предыдущем уровне shell произвести экспортирование синонима или
передать его в subshell с помощью третьего стартового файла.
Если есть третий стартовый файл trc (его имя должно быть прописано в переменной
ENV и она должна быть активизирована):
echo This is trc
alias pr=echo
то при вызове subshell предварительно сработает третий стартовый файл trc:
$ ksh
This is trc
Вот теперь можно будет вызывать синоним:
$ рr хххххсссс
хххххсссс
$
Замечание:
Если на предыдущем уровне subshell выполнить действие вида alias -x, то синоним
не экспортируется в subshell. Его надо передавать с помощью третьего стартового
файла, как показано выше.
6.3. Управление локальными переменными
В отличие от системных переменных среды, переменные языка shell называются
локальными переменными и используются в теле процедур для решения обычных
задач. Локальные переменные связаны только с породившим их процессом. Локальные
переменные могут иметь имя, состоящее из одного или нескольких символов.
Присваивание значений переменным осуществляется с помощью оператора "=" присвоить (установить) значение переменной.
При этом если переменная уже существовала, то ее старое значение замещается новым.
Если переменная не существовала, то она будет создана оболочкой shell. Локальные
переменные хранятся в области локальных данных и могут быть экспортированы в среду с
помощью команды export.
Необходимо различать собственно имя переменной и значение этой переменной. Так, если
variable — имя некоторой переменной, то $variable – ссылка на ее значение.
Собственные имена переменных могут
использоваться только при
объявлении
переменной,
при
присваивании
ей
некоторого
значения,
при
удалении,
при
экспортировании и если переменная — сигнал для управления процессами.
Примеры присваивания значений переменным:
$count=3
$color=”red belt”
$fildir=lev/d1/d12
$
Еще пример:
# текст и результат выполнения процедуры
b=”1 + 2”
echo ”c=$b”
………….
c=1+2
# в результате выполнения процедуры выводится текст,
# включающий значение переменной b; двойные кавычки
# блокируют операцию присваивания и не блокируют символ $
echo `c=$b`
………….
1+2
# здесь обратные кавычки определяют вывод результата операции
присваивания
$
На экране можно с помощью команды set без параметров просмотреть все
установленные локальные переменные:
$ set
$
Значения переменных можно объединять. Для этого достаточно записать эти значения
подряд, без пробелов, в соответствующем месте командной строки. Например:
$num1=123
$num2=456
$num3=$num1$num2
$echo $num3
123456
$
Можно запретить изменения значений переменных, выполнив после соответствующих
присваиваний команду:
$readonly <перем1>[перем2...]
Например:
$num=123
$readonly num
$num=456
bash: num: доступная только на чтение переменная
$echo $num
123
$
Для удаления ранее установленных переменных достаточно выполнить команду:
$unset
$
перем1 [перем2 ........]
6.4. Подстановки в языке shell
В языке shell мощным средством при программировании являются так называемые
подстановки.
Оболочка Shell допускает три типа подстановок:

подстановка переменных;

подстановка команд;

тильда-подстановки.
Подстановка переменных
Синтаксис:
$переменная
Указывает shell'y выполнить подстановку переменной
На место этой конструкции будет подставлено значение переменной.
Соответствующая команда процедуры будет выполнена только после того, как shell
выполнит подстановку всех переменных в командной строке.
Пример:
$ echo $PATH
/usr/bin:/usr/contrib/bin:/usr/local/bin
$ РАТН=$РАТН:$НОМЕ:.
$ echo $PATH
/usr/bin:/usr/contrib/bin:/usr/local/bin:/home/user3
$ echo $HOME
/home/user3
$ file_name=$HOME/filel
$ more $file_name
<contents of /home/user3/filel>
Значения переменных могут представлять собой:

абсолютные числовые или символьные значения;

команды;

аргументы команд или целиком командные строки.
В частности, эту процедуру удобно использовать, например, для переименования часто
используемых длинных маршрутных имен или целых командных строк.
Использование полного маршрутного имени в качестве значения переменной позволяет
независимо от местонахождения в файловой системе получать доступ к требуемому файлу
или каталогу.
Если в строке несколько присваиваний, то последовательность их выполнения в shell –
слева направо.
Пример 1:
$ y=123;z=$y
$ echo $z $y
123 123
$ y=abc ; z=$y
$ echo “$z”
abc
$ echo “$y”
abc
$
# двойные кавычки не блокируют $
Пример 2:
$ var=/user/lab/ivanov
$ cd $var
$ pwd
/udd/lab/ivanov
$
# задано и установлено имя текущего каталога
Подстановка команд
Синтаксис:
$(команда)
или
`команда`
Пример:
$ pwd
/home/user2
$ curdir=$(pwd)
$ echo $curdir
/home/user2
$ cd /tmp
$ pwd
/tmp
$ cd $curdir
$ pwd
/home/user2
Подстановка команд используется для замены команды на результат ее выполнения в той
же командной строке.
Механизм подстановки команд позволяет захватить результат выполнения команды и
использовать его в качестве аргумента в другой команде или присвоить его переменной.
Так же, как и в случае подстановки переменных, подстановка команд осуществляется
перед запуском командной строки. Если результат выполнения команды содержит
символы "возврат каретки" или "перевод строки", они будут заменяться пробелами.
Пример:
$ filname=`ls`
$ echo $filname
fil1
fil2
fil3
...
$
# команда ls непосредственно выполняется уже в первой строке, и
переменной filname #присваивается результат ее работы.
Тильда-подстановки
Тильда - подстановки выполняются в соответствии со следующими правилами:
Отдельный знак ~ или предшествующий знаку / заменяется на значение переменной
НОМЕ.
Следует заметить, что тильда-подстановка выполняется только, если знак «~» указывается
в начале слова, а в случае, например, /~home/user3 тильда - подстановка не
осуществляется.
Тильда с последующим знаком «+» заменяется на значение переменной PWD. Переменная
PWD устанавливается командой cd при переходе в новый текущий каталог.
Тильда с последующим знаком «-» заменяется на значение переменной OLDPWD.
Переменная OLDPWD устанавливается командой cd для предыдущего рабочего каталога.
Например:
$ echo $HOME
/home/user3
$ echo ~
/home/user3
$ echo $PWD
/home/user3/tree
$echo ~+/poodle
/home/user3/tree/poodle
$ echo $OLDPWD
/home/user3/mail
$ ls ~/home/user3/mail/from.mike /home/user3/mail/from.jim
6.5. Арифметические действия в shell-процедурах
Над переменными можно выполнять арифметические действия, как с целыми числами,
используя команду expr.
Для арифметических операций, выполняемых командой expr, используются символы:
+
сложение целых чисел
-
вычитание целых чисел
\*
умножение целых чисел (символ обратный слэш \ используется для отмены специального
действия одного следующего за ним символа)
/
деление нацело
%
остаток от деления нацело
В команде expr можно использовать следующие операции сравнения:
=
равно
!=
не равно
\<
меньше
\<=
меньше или равно
\>
больше
\>=
больше или равно
Символы *,
<,
> необходимо экранировать, как показано, чтобы отменить их
специальный смысл.
Результатом операции арифметического сравнения чисел командой expr является
выработка ею кода возврата – значения результата логического сравнения двух чисел: 0
(false) или 1 (true).
Примечание. Это не код возврата, как результат успешности выполнения команды.
Все операнды и операции являются аргументами команды expr и должны отделяться
друг от друга и от имени команды expr пробелами.
Пример:
# Текст
a=2
a=`expr
b=`expr
c=`expr
d=`expr
e=`expr
echo $a
процедуры:
$a
$a
$a
$c
$d
$b
+ 7`
/ 3`
- 1 + $b`
% 5`
- $b`
$c $d $e
# Результат работы процедуры:
9 3 11 1 -2
Команда expr выводит результат вычисления на экран. Поэтому, если он не присвоен
никакой переменной, то не может быть использован в программе.
При решении логических задач, связанных с обработкой символьных строк (текстов),
команда expr может быть использована, например, как средство для подсчета символов в
строках или для вычленения из строки цепочки символов.
Операция обработки строк символов задается кодом операции ":" и шаблонами. В
частности:
'.*' — шаблон для подсчета числа символов в строке,
'...\(.*\)....' — шаблон для выделения подстроки удалением символов строки,
соответствующих точкам в шаблоне.
Пример:
$ m=aaaaaa
$ expr $m : '.*'
6
$
Пример:
$ n=abcdefgh
$ expr $n : '...\(.*\)..'
def
$
Выводимая информация — количество символов или подстрока — может быть присвоена
некоторой переменной и использована в дальнейших вычислениях.
Пример:
$ A='string n'
$ count=$(expr $A : '.*')
$ echo $count
8
$
#Продолжение примера:
$ B=$(expr $A : '..\(.*\))
$ echo $B
ring
$
Рассмотрим пример простейшей линейной процедуры обработки переменных средствами
языка shell.
Пример:
Создать файл, содержащий процедуру сложения двух чисел. Числа передаются в виде
параметров при обращении к процедуре. Выполнить процедуру:
$ cat>comf
SUM=$(expr $1 + $2)
echo "$1 + $2 = $SUM"
<ctrl>+<d>
$ sh comf 3 5
3 + 5 = 8
$
#двойные кавычки не блокируют действие символа $.
6.6. Экспортирование локальных переменных
При выполнении процедуры ей можно передавать как позиционные параметры (см.
выше), так и ключевые — локальные переменные порожденного процесса. Локальные
переменные помещаются в область локальных переменных, связанную с конкретным
текущим процессом, породившим переменную. Они доступны только этому процессу и
недоступны порожденным процессам-потомкам (например, shell-процедурам).
Переменные другим процессам можно передавать неявно через среду. Для этого
локальная переменная должна быть экспортирована (включена) в среду, в которой
исполняется процедура, использующая эту переменную. Среда пользователя, т.е.
глобальные переменные, доступна всем процессам для чтения и переопределения.
Экспортирования не требуют переменные, созданные в теле самой процедуры. Процедура
является порожденным процессом по отношению к оболочке, т.е. порожденный процесс
не может изменить значения локальных переменных родительского процесса.
Три формата команды экспортирования:
$export список имен локальных переменных
$export
имя_лок_переменной=значение
$export (без параметров) — выводит перечень всех экспортированных
локальных и переменных среды (аналог команды env).
Рассмотрим некоторый фрагмент протокола работы с системой.
$color = red
# переменная определена, но не экспортирована;
$export count = 1
# переменная определена и экспортирована,
# т.е. потенциально доступна всем порождаемым процессам.
$export
PATH = …..
HOME = …..
color = red
count = 1
# это собственные (глобальные) переменные shell
$cat>proc1
# создание порожденного процесса процедуры proc1
echo $color
echo $count
exit
# выход в ОС после завершения процедуры
<ctrl.D>
$proc1
# выполнение процедуры
1
# на экран выводится значение только одной экспортированной
# переменной count; вторая переменная color не определена
$cat>proc2
# еще одна процедура proc2
color = black
count = 2
echo $color
echo $count
exit
$proc2
black
2
# выводятся значения обеих переменных, так как они
# определены в самой процедуре
$echo $color
red
$echo $count
1
$
На экран выводятся первоначальные значения переменных (color и count)
родительского процесса — shell. Новые (измененные) значения локальных переменных
существуют только на время существования установившего их порожденного процесса.
Чтобы изменить значение переменной родительского процесса, ее надо экспортировать в
среду.
Но
после
завершения
порожденного
процесса
среда
родительского
Здесь порожденным процессом является вторичная оболочка Korn
shell. Среда
восстанавливается.
Еще пример:
$export color=black
$ksh
# далее работа в ksh
$echo $color
black
$color = red
$echo $color
red
$exit
# выход из ksh в родительский shell
$echo $color
black
$
родительского процесса не изменена, т.е. сохранилось значение экспортированной в нее
переменной. Порожденные процессы не могут изменить среду родительских
процессов.
6.7. Вопросы для самоконтроля
1. Понятие shell-процедуры. Создание. Исполнение. Завершение работы. Примеры.
2. Понятие процедур в ОС UNIX. Передача и обработка параметров. Примеры.
3. Основные принципы построения операционных систем.
4. Команда ввода строки текста со стандартного устройства ввода. Обработка
элементов строки. Пример.
5. Локальные переменные языка shell. Разновидности и назначение. Присваивание и
подстановка значений переменных. Примеры.
6. Локальные переменные ОС UNIX. Подстановка результатов работы команд,
командных строк и процедур. Примеры.
7. Три вида подстановок значений переменных. Примеры.
8. Обзор команд вычисления выражений арифметических операций. Результаты
операций. Примеры.
9. Обзор команд анализа строк символов. Результаты операций. Примеры.
10. Экспортирование переменных. Назначение. Команды. Примеры.
7. Введение в Shell-программирование.
Алгоритмы процедур
7.1. Проверка условий
Все команды UNIX вырабатывают код завершения (возврата), чтобы в дальнейшем можно
было выполнить диагностику посредством проверки значения кода завершения и
определить: нормально завершилось выполнение команды (=0 или true) или ненормально
(> 0 или false). Например, если (=1), то ошибка синтаксическая.
Код завершения после выполнения каждой команды помещается автоматически в
некоторую специальную системную переменную с именем ? и ее значение можно
вывести на экран:
echo $?
Пример:
$true
# коду завершения присваивается истинное значение
$echo $?
0
$ls
$echo $?
0
$false
# коду завершения присваивается ложное значение
$echo $?
1
$cp
<сообщение о некорректности заданной команды – нет параметров>
$echo $?
1
# некорректное завершение команды cp
$echo $?
0
# корректное завершение команды echo
$
Код завершения используется для программирования условных переходов в shпроцедурах. Проверка истинности условий для последующего ветвления вычислительного
процесса процедур может быть выполнена с помощью команды:
test <проверяемое отношение/условие> или
отношение/условие ]
[ проверяемое
Аргументами этой команды могут быть имена файлов, числовые или нечисловые строки
(цепочки символов). Командой вырабатывается только код завершения (код возврата),
соответствующий закодированному в команде test условию. Код завершения проверяется
следующей командой. При этом обращение к переменной $? возможно только
однократное. Поэтому рекомендуется сохранять его в отдельной переменной, если
предполагается использовать этот результат в дальнейшем. Если закодированное
параметрами условие выполняется, то вырабатывается логический результат (значение
некоторой системной переменной) – true, если нет — false.
Код возврата может обрабатываться как следующей за test командой, так и специальной
конструкцией языка: if-then-else-fi.
Проверка файлов
test -к
имя_файла
Ключи:
-r
файл существует и доступен для чтения
-w
файл существует и доступен для записи
-x
файл существует и доступен для исполнения
-f
файл существует и имеет тип "-", т.е. обычный файл
-s
файл существует, имеет тип "-" и не пуст
-d
файл существует и имеет тип "d", т.е. файл-каталог
Сравнение числовых значений
test число1 –к
число2
Числа могут быть как просто числовыми строками, так и переменными, которым эти
строки присвоены в качестве значений.
Ключи для анализа числовых значений:
-eq
равно
-lt
меньше
-gt
больше
-ne
не равно
-le
меньше или равно
-ge
больше или равно
Пример:
$x=5
$[$x
$echo
0
$[$x
$echo
1
-lt
$?
7]
-gt
$?
7]
$
Сравнение строк:
test [-n] 'строка' — строка не пуста (n – число проверяемых строк);
test -z 'строка' — строка пуста;
test 'строка1' = 'строка2' — строки равны;
test 'строка1' != 'строка2' — строки не равны.
Необходимо заметить, что все аргументы команды test — строки, имена, числа, ключи и
знаки операций являются самостоятельными аргументами и должны разделяться
пробелами.
Пример:
$x = abc
$["$x" = "abc"]
$echo $?
0
$["$x" != "abc"]
$echo $?
1
$
Выражение вида
"$переменная" лучше заключать в двойные кавычки, что
предотвращает в некоторых ситуациях возможную неподходящую замену переменных
shell.
Особенности сравнения чисел и строк
Shell трактует все аргументы как числа в случае, если осуществляется сравнение чисел
(что определяется использованием операций сравнения чисел), и все аргументы как
строки, если осуществляется сравнение строк (что определяется операциями сравнения
строк).
Пример:
$X = 03
$Y =3
$["$X -eq "$Y"]
# сравниваются значения чисел;
$echo $?
0
$["$X = "$Y"]
# числа сравниваются как строки символов.
$echo $?
1
$
Ещё примеры на сравнение строк и чисел:
x=abc;[abc = “$x”];echo $?
0
# «истина», строки равны;
х=05; test 5 = “$x”; echo $?
1
# «ложь», строки не равны;
х=05; [5 –eq “$x”]; echo $?
0
# «истина», сравниваются числовые значения и они равны.
$
7.2. Ветвление вычислительных процессов
Ветвление вычислительного процесса в shell-процедурах осуществляется конструкцией:
if список_команд1
then
список_команд2
[else
список_команд3]
fi
Список_команд — это одна команда, или несколько команд, или фрагмент shellпроцедуры. Если команды записаны на одной строке, то они разделяются точкой с
запятой.
Для задания пустого списка команд следует использовать специальный оператор:
: (двоеточие) — пустой оператор.
Список_команд1 передает оператору if код завершения последней выполненной в нем
команды. Если он равен 0, то выполняется список_команд2. Таким образом, код
возврата 0 эквивалентен логическому значению "истина". В противном случае он
эквивалентен логическому значению "ложь" и выполняется либо список_команд3
после конструкции else, либо завершение конструкции if словом fi.
В качестве списка_команд1 могут использоваться списки любых команд. Однако чаще
других используется команда test.
В операторе if также допускаются две формы записи этой команды:
if test аргументы
или
if
[
Каждый
аргументы
оператор
if
]
произвольного
уровня
вложенности
обязательно
должен
завершаться словом fi.
Пример:
Создать и выполнить файл с процедурой, сравнивающей передаваемый ей параметр с
некоторым набором символов (паролем).
$ cat>com
if test 'param' = "$1"
# сравниваются строки символов;
then
echo Y
else
echo N
fi
<Ctrl*D>
$ chmod u+x com
# запуск процедуры com на исполнение.
$ com param
Y
$ com parm
N
$
Пример:
Организовать ветвление вычислительного процесса в процедуре в зависимости от
значения переменной Х (<10, >10, = 10).
if
[$X -lt 10]
then
echo X is less 10
else
if
[$X -gt 10]
then
echo X is greatr 10
else
echo X is equal to 10
fi
fi
Для
улучшения
восприятия
программ
и
облегчения
отладки
целесообразно
придерживаться структурированного стиля написания программы. Каждому if должен
соответствовать свой fi.
Кроме рассмотренной конструкции для ветвления может использоваться оператор выбора
case.
Конструкция case
Синтаксис: (соответствует передаче управления на одну из множества возможных ветвей)
case слово in
образец 1) список_А ;;
образец 2) список_В ;;
образец N) список_N ;;
esac
Обычно в качестве слова задается имя переменной shell'a.
Образцы задаются по формату имен файлов, несмотря на то, что сравниваются между
собой не имена файлов. Могут использоваться следующие специальные символы:
*
сравнение любой последовательности символов, в том числе и пустой строки
?
сравнение любого одиночного символа
[]
сравнение любого одного символа из указанных между скобками
Может также использоваться символ «|», означающий логический оператор OR ("ИЛИ").
Пример:
case
yes)
no)
esac
case
echo
echo
echo
*)
esac
$ANS
in
echo O.K. ; ;
echo no go ; ;
$OPT in
option 1;
option 2;
option 3;
echo no
;
;
;
option; ;
Пример:
$ cat menu_with_case
echo COMMAND MENU
echo
d to display time and date
echo
w to display logged-in users
echo
l to list contents of current directory
echo
Please enter your choice :
read choice
case $choice in
[dD]*) date ; ;
[wW] *) who ; ;
1*|L*) ls ; ;
*) echo Invalid selection
esac
$
7.3. Построение циклов
Циклы обеспечивают многократное выполнение отдельных участков процедуры до
достижения заданных условий.
Для организации циклических алгоритмов используются следующие конструкции:
while <список команд 1> do <список команд 2> done
или
until <список команд 1> do <список команд 2> done
или
for <переменная> = <строка> do <список команд 2> done
или
for
((expr1; expr2;… exprN ))
do <список команд 2> done
В первой конструкции циклически выполняется список команд 2 до тех пор, пока код
возврата последней команды из списка 1 остается равным 0.
Во второй конструкции выполняется список команд 2 до тех пор, пока код возврата
последней команды из списка 1 остается не равным 0.
В третьей конструкции список команд 2 выполняется 1 раз для каждого значения
переменной, которая последовательно приравнивается к очередному слову из строки.
В четвертой конструкции список команд 2 выполняется по одному разу для каждого из
указанных выражений.
Цикл типа while (пока true)
while список_команд1
do список_команд2
done
Список_команд1 возвращает код возврата последней выполненной команды. Если
условие истинно, выполняется список_команд2, затем снова список_команд1 с
целью проверки условия, а если ложно, выполнение цикла завершается. Таким образом,
циклический список_команд2 (тело цикла) выполняется до тех пор, пока условие
истинно.
Пример:
Простая процедура организации счетчика на заданное число итераций.
var=0
caunt=10
while [“$var” –lt “$caunt”]
do
echo “$var”
var=`expr $var + 1`
done
exit
Пример:
Проверка наличия параметров при обращении к данной процедуре. Вывод на экран
сообщений о наличии параметров и значений параметров.
Текст процедуры, которой присвоено имя Р2:
if $1 –eq 0
then echo “No param”
else echo “Param:”; while test ‘$1’
do
echo “$1”
shift
done
fi
Результат работы процедуры:
$P2
No param
$P1 abc df egh
Param:
abc
df
egh
$
Пример:
Ввод строки из нескольких слов. Подсчет и вывод числа символов в каждом слове.
Текст процедуры, которой присвоено имя P3:
echo “Input string:”
read A
set $A
while [ “$1” ]
do
echo “$1 = `expr ”$1” : ‘.*’`”
shift
done
Результат работы процедуры:
$P3
Input string:
df ghghhhh aqw
df = 2
ghghhhh = 7
aqw = 3
$
Пример:
Вывести на экран слово строки (поле), номер которого (переменная N) указан в параметре
при обращении к процедуре, которой присвоено имя P4. Процедура запрашивает ввод
строки с клавиатуры. Номер слова вводится как аргумент процедуры.
Текст процедуры P4:
i=1
# счетчик номеров слов в строке, формируется при каждом
# выполнении цикла;
N=$1
# значение первого параметра;
echo "Введи строку: "
read a
set $a
while test $i -lt $N
do
i=`expr $i + 1` — формирование номера следующего слова.
shift
done
echo "$N поле строки: \"$1\""
Пример работы процедуры P4:
$P4 2
Введи строку: aa bb cc dd
2 поле строки: "bb"
$
Цикл типа until (пока false)
until список_команд1
do
список_команд2
done
Логическое условие, определяемое по коду возврата списка_команд1, инвертируется,
т.е. цикл выполняется до тех пор, пока условие ложно. Условие цикла проверяется после
каждого (в том числе и первого) выполнения циклического участка процедуры.
Пример процедуры с именем P5, выполняющей заданное число итераций:
$cat>P5
X = 1
# cчетчик числа циклов
until test $X -gt 10
# задано число циклов = 10
do
echo X is $X
X = `expr $X + 1`
done
<Ctrl*D>
$sh P4
X is 1
X is 2
.................
X is 10
$
Пример процедуры, предусматривающей завершение цикла по ключевому слову end:
until [“$var” = end]
do
echo “Введите значение переменной #1”
echo “end – выход”
read var
echo “значение переменной #1 = $var”
done
exit
Цикл типа for
for имя_ переменной [in список_значений]
do
список_команд
done
Переменная с указанным в команде именем заводится автоматически. Переменной
присваивается значение очередного слова из списка_значений и для этого значения
выполняется список_команд. Количество итераций равно количеству значений в
списке, разделенных пробелами (т.е. итерации выполняются, пока список не будет
исчерпан).
Пример текста процедуры, печатающей в столбец список имен файлов текущего каталога:
list =`ls`
for val in $list
do
echo "$val"
done
echo end
Пример процедуры, которая должна скопировать все обычные файлы из текущего
каталога в каталог, который задается в качестве аргумента при обращении к данной
процедуре по имени comfil. Процедура проверяет также наличие каталога-адресата и
сообщает количество скопированных файлов:
m=0 — переменная для счетчика скопированных файлов
if [ -d $HOME/$1 ]
then echo "Каталог $1 существует"
else
mkdir $HOME/$1 .
echo "Каталог $1 создан"
fi
for file in *
do
if [ -f "$file" ]
then cp "$file" $HOME/$1; m=`expr $m + 1`
fi
done
echo "Число скопированных файлов: $m"
Выполнение процедуры:
$sh comfil dir1
Число скопированных файлов:….
$
Здесь символ * означает <список_имен_файлов_текущего_ каталога>.
Пример процедуры PROC, выводящей на экран имена файлов из текущего каталога, число
символов в имени которых не превышает заданного параметром числа:
if [ “$1” = “” ]
then
exit
fi
for nam in *
do
size = `expr $nam : ‘.*’`
if [ “$size” –le “$1” ]
then echo “Длина имени $nam $size символа”
fi
done
Вывод содержимого текущего каталога для проверки работы процедуры:
$ ls –l
total 4
drwxrwxrwx
-rw-rw-r--rwxr-xr-x
-rwxr-xr-x
$
2
lev lev 1024
1 lev lev
1 lev lev
1 lev lev
Результаты работы процедуры:
$ PROC 2
Длина имени
Длина имени
$PROC 3
Длина имени
Длина имени
Длина имени
$
Пример:
f1 2 символа
f2 2 символа
out 3 символа
f1 2 символа
f2 2 символа
Feb 7 18:18 dir1
755 Feb 7 18:24 out
115 Feb 7 17:55 f1
96 Feb 7 18:00 f2
Процедура с именем PR выводит на экран из указанного параметром подкаталога имена
файлов с указанием их типа.
cd $1
for fil in *
do
If [ -d “$fil”]
then echo “$fil – catalog”
else echo “$fil – file”
fi
done
Вывод содержимого подкаталога для проверки работы процедуры:
$ ls –l pdir
total 4
drwxrwxrwx 2
-rw-rw-r--rwxr-xr-x
-rwxr-xr-x
lev lev 1024
1 lev lev
1 lev lev
1 lev lev
Feb 7 18:18 dir1
755 Feb 7 18:24 out
115 Feb 7 17:55 f1
96 Feb 7 18:00 f2
Результаты работы процедуры:
$ PR pdir
dir1 – catalog
out – file
f1 – file
f2 – file
$
Пример циклической процедуры, которая сортирует строки исходных файлов и
переписывает отсортированное содержимое исходных файлов в новые файлы с частично
совпадающими именами:
for i in f1 f2 f3
do
cat $i|sort>${i}_rez
# отсортированные тексты перепишутся в файлы
# f1-rez, f2-rez, f3-rez
done
Команды exit и return
Команда exit будет завершать выполнение shell-процедуры и формировать код возврата.
При нормальном завершении он равен 0, а при возникновении ошибки - не ноль. Если
команда задана без параметров, то код возврата устанавливается равным коду возврата
последней команды, выполненной перед exit.
Иногда бывает нужно получить код завершения из функции при принудительном выходе
из нее. Команда return останавливает выполнение функции и возвращает в вызвавшую
процедуру аргумент, содержащий код завершения. Команда return ведет себя таким
же образом, что и exit, внутри shell — функции.
Если аргумент не указан, то код завершения соответствует последней команде,
выполненной в функции перед выходом из нее. Когда прекращение выполнения функции
обусловлено какими-то внешними по отношению к ней причинами, то это равносильно
exit.
Синтаксис:
exit [аргумент]
return [аргумент]
Пример:
$ cat exit_test
echo exiting program now
exit 99
$ exit_test
exiting program now
$ echo $?
99
return [аргумент]
$ cat rtn_test
function rtn
{
echo return from function
return 99
}
$ rtn_test
return from function
$ echo $?
99
Команды break и continue
Синтаксис:
break[n]
continue[n]
exit [n]
Команда break прекращает выполнение цикла, и управление передается команде,
следующей сразу за ключевым словом done (или команде n).
Команда continue несколько отличается от break. При возникновении ошибки она
обеспечит пропуск оставшихся команд тела цикла и передаст затем управление на начало
цикла. Таким образом, эта команда позволяет только завершить одну итерацию цикла, но
затем продолжить выполнение только что прерванного цикла с начала.
В циклах while и until процесс выполнения каждой итерации начинается с вершины
цикла. В цикле типа for сначала переменной цикла присваивается очередное значение из
списка, а затем он выполняется.
Замечание: Естественный процесс передачи управления при выполнении цикла обычно
должен завершаться по выполнении условия, сформированного в вершине цикла (while,
until)
или
по
исчерпании
списка
(for).
Рассмотренные
команды
должны
использоваться только тогда, когда в цикле возникает ситуация, связанная с неправильно
сформулированным условием его выполнения.
Команда sleep
Синтаксис:
sleep t — приостанавливает выполнение процесса на t секунд
Пример:
Бесконечная (циклическая) процедура выводит каждые пять секунд сообщение в
указанный файл file:
while true
do
echo “текст_сообщения”>file
sleep 5
done
Примечания:
1. Вместо файла (или экрана) может быть использовано фиктивное устройство
/dev/null (например, для отладки процедуры).
2. В процедуре реализуется бесконечный цикл. Для ограничения числа циклов надо
предусмотреть счетчик циклов (см. выше) или прекратить выполнение процесса
процедуры с помощью команды управления процессами $kill (см. ниже).
7.4. Использование опций и аргументов при обращении
к процедурам и функциям
При обращении к функциям и к процедурам можно передавать как список аргументов,
так и список опций. Причем, предполагается, что список опций может быть пустым или
нет и должен предшествовать списку аргументов. В свою очередь список аргументов
может быть пустым или нет. Для обработки этих списков есть специальные средства.
Обработка списка аргументов
Переменные со специальными именами, куда shell заносит требуемые значения:
#
количество элементов в списке аргументов
*
весь список аргументов
@
весь список аргументов
1 2 3
первый, второй, третий элементы из списка аргументов
0
имя вызываемой процедуры
Список аргументов можно «смещать пошагово» влево на заданное количество шагов с
коррекцией значения числа элементов в списке аргументов (на величину шага) с
помощью команды shift.
При передаче аргументов в функцию или процедуру часто нужно узнать значение
последнего элемента в произвольном списке аргументов. Сделать это можно двумя
способами:
last=`eval echo \$$#`
или так:
shift $(expr $#
- 1); last=$1
Обработка списка опций
Для обработки списка опций служит команда getopts.
Синтаксис команды:
getopts список_опций переменная
Команда используется в заголовке цикла while, который строится в процедуре или
функции для того, чтобы разобрать фактический список опций при данном обращении. В
каждом проходе производится считывание из командной строки очередного элемента из
списка опций, пока этот список не будет исчерпан. В зависимости от предназначения (и
корректности) очередной считанной опции в цикле while, программируется некоторая
обработка в составе вызываемой процедуры или функции. После считывания очередной
опции из фактического списка опций в командной строке производится проверка на ее
корректность. Для этого производится обращение к списку_опций в команде getopts.
Если считанная опция там есть, то ее имя присваивается переменной в качестве значения,
и с этим значением выполняется очередная итерация цикла while.
Если считанной опции там нет, то переменной присваивается в качестве значения символ
«?» и с этим значением выполняется очередная итерация цикла while.
При интерпретации команды getopts интерпретатор shell использует внутреннюю
переменную OPTIND, которая содержит значение последней обработанной опции из
фактического списка опций (в момент, когда команда закончит обрабатывать имеющийся
список опций из командной строки).
Когда команда getopts обнаруживает конец фактического списка опций в командной
строке в очередной итерации, она вырабатывает код возврата, отличный от 0. Тем
самым обеспечивается выход из цикла while, в котором производилась разборка списка
опций.
В составе рассматриваемой команды список_опций представляет собой корректный
список из всех допустимых опций, которые можно использовать для данной процедуры
или функции.
При работе с опциями есть некоторый стандарт их построения и использования. Каждая
опция в списке опций - это отдельный символ. Опции при обращении к процедуре или
функции составляют список, в котором каждый элемент может стоять отдельно и
начинается со знака дефис (или дефис предшествует некоторой группе опций). Опции или
группы опций отделяются в списке как минимум одним пробелом. Могут также опции
начинаться со знака +.
Могут также использоваться опции со значением (инициализированные опции). В этом
случае за именем опции, после пробела записывается её значение. Опции со значениями в
списке_опций в команде getopts представляются односимвольным именем, за
которым следует символ «:».
Если в очередной итерации при разборе списка опций в командной строке была
обнаружена опция со значением, то команда getopts производит присвоение имени
этой опции со значением переменной переменная, производит считывание конкретного
значения опции, которое затем присваивается внутренней переменной OPTARG. После
этого выполняется очередная итерация проверочного цикла while или выход из него.
Если при разборке фактического списка опций будет сканирована опция со значением, но
у нее в командной строке не было представлено конкретного значения, то будет выдано
диагностическое сообщение. При этом в переменную переменная будет помещен символ «?».
При желании можно подавить выдачу диагностического сообщения в указанной ситуации,
если указать перед списком опций в команде getopts символ «:».
Примечание:
Как правило, внутри тела цикла while по разборке фактического списка опций
используют оператор case, где для каждой очередной сканированной опции имеется
своя альтернативная ветвь. В поле шаблона каждой ветви записывается имя допустимой
опции. Для переключения между ветвями служит текущее значение переменной
переменная, которое формируется командой getopts в каждой очередной итерации
цикла while при сканировании фактического списка опций.
Альтернативная ветвь, которая должна отрабатывать недопустимую опцию, должна иметь
такое поле шаблона «:».
Переход от обработки списка опций к обработке списка аргументов
Список аргументов в командной строке следует за списком опций. Поэтому, когда
происходит выход из цикла while (цикла разбора фактического списка опций), то это
означает, что далее можно сканировать и разбирать список аргументов в соответствующей
командной строке.
Но при этом нужно откорректировать значения специальных переменных #, @, *,
1,2,3
.., поскольку они при обращении к процедуре или функции содержали
совокупную информацию, как о списке опций, так и о списке аргументов. Поэтому, перед
последующей обработкой списка аргументов, нужно выполнить обязательное действие:
shift $( expr SOPTIND -1)
После этого первый элемент списка аргументов окажется в переменной 1, второй - в
переменной 2 и т.д. В переменной # будет записана длина списка аргументов, в
переменные @ и * будут занесены все элементы списка аргументов.
Элементы списка аргументов удобно разбирать, используя цикл for:
for LOOP in "$@"
do
КОМАНДЫ done
7.5. Сигналы и прерывания в процедурах и функциях
В shell-процедурах можно управлять реакцией (прерыванием) на сигналы, поступающие
от различных процессов в системе, в том числе инициированные клавиатурой терминала
или от других выполняющихся процедур.
Имеются 3 возможные реакции на сигналы:

Сигналы игнорируются (в этом случае сигнал вообще не посылается процессу).

Сигналы перехватываются (реакция на сигнал обеспечивается самим процессом).

Сигналы пропускаются без обработки. Работа процесса завершается.
Для управления прерываниями используются команды trap и kill.

trap (ловушка) – перехват сигнала, блокирование прерывания, восстановление
стандартной реакции на сигнал;

kill – передача сигнала процессу.
Примеры использования команд:
trap
'rm
/tmp/ps$$;
exit'
2 — перехватывает сигнал 2 (прерывание) и
выполняет команду
rm /tmp/ps$$; exit — встроенная команда exit прерывает выполнение командного
файла.
Если при входе в командный файл сигнал игнорируется, то игнорируется и команда trap.
Если аргументом команды trap является пустая строка, то процедура игнорирует
сигналы. В качестве примера можно привести фрагмент команды nohup:
trap '' 1 2 3 15
После выполнения этой команды, как процедура, так и вызывающие ее команды будут
игнорировать перечисленные сигналы.
Стандартная реакция на сигналы может быть восстановлена, например, следующей
командой:
trap 2 3
Список текущих значений сигналов системы может быть получен с помощью команды
trap без параметров.
Ловушка trap является локальной для функции и сбрасывается при ее завершении.
Ловушки trap в функциях не разделяются с ловушкой trap в основной программе.
Сигнал, который не был перехвачен или не был проигнорирован в функции, может
вызвать окончание выполнения основной программы во время отработки функции. А вот
если сигнал был проигнорирован в главной программе, то он будет также
проигнорирован и в функциях, которые вызываются из главной программы. В функции
его перехватить нельзя!
Пример:
Создать в текущем каталоге файл fun_file, который содержит библиотеку из двух
функций fl и Ј2. Сделать этот файл автозагрузочным. Далее вызывать на исполнение из
этого файла функции fl и f2 с уровня командной строки.
Содержание файла funflle:
function fl
{
echo “This is function f”l
}
function f2
{
echo “This is function f2”
}
Выполнить инициализацию переменной FPATH:
$ FPATH=.
Установить жесткие ссылки на файл fun_file (жесткие ссылки должны быть
именами функций):
$ ln fun_file
$ln fun_file
fl
f2
Провести автозагрузку файла fun_file:
$ autoload fun_file
Проверить наличие двух функций из файла fun_file в памяти функций текущего shell:
$ typeset
-f function f1
{
echo “This is function f1”
}
function f2
{
echo “This is function f2”
}
Обратиться к функции f2:
$ f2
This is function f2
7. Обратиться к функции f1:
$ f1
This is function f1
7.6. Вопросы для самоконтроля
1. Понятие кодов завершения выполнения команд. Средства анализа кодов. Примеры.
2. Результаты проверки файлов, сравнения числовых значений и символьных строк.
Как анализируются результаты и для каких целей используются? Примеры.
3. Механизм выработки и проверки условий в shell-процедурах.
4. Команда проверки истинности отношений при проверке файлов, числовых
значений и анализе символьных строк. Синтаксис команды. Примеры.
5. Средства ветвления вычислительных процессов в shell-процедурах. Семантика
конструкции. Пример.
6. Средства проверки условий и организации циклов типа «пока истина» в
процедурах. Семантика конструкции. Пример.
7. Средства проверки условий и организации циклов типа «пока ложь»l в процедурах.
Семантика конструкции. Пример.
8. Средства проверки условий и организации циклов с перебором списка переменных
в процедурах. Семантика конструкции. Пример.
9. Понятие кодов завершения выполнения команд. Средства анализа кодов. Примеры.
10. Результаты проверки файлов, сравнения числовых значений и символьных строк.
Как анализируются результаты и для каких целей используются? Примеры.
11. Механизм выработки и проверки условий в shell-процедурах.
12. Команда проверки истинности отношений при проверке файлов, числовых
значений и анализе символьных строк. Синтаксис команды. Примеры.
13. Средства ветвления вычислительных процессов в shell-процедурах. Семантика
конструкции. Пример.
14. Средства проверки условий и организации циклов типа «пока истина» в
процедурах. Семантика конструкции. Пример.
15. Средства проверки условий и организации циклов типа «пока ложь»l в процедурах.
Семантика конструкции. Пример.
16. Средства проверки условий и организации циклов с перебором списка переменных
в процедурах. Семантика конструкции. Пример.
8. Сетевые средства UNIX
С самого начала ОС UNIX разрабатывалась как операционная система, которая должна
работать в компьютерной сети, т.е. как сетевая операционная система. В первых версиях
проблема связи была решена с помощью утилит UUCP (UNIX to UNIX CoPy). Сети UUCP
— это сети с коммутацией каналов, когда сначала устанавливалась связь между двумя
конкретными компьютерами сети. Затем осуществлялся обмен файлами и электронной
почтой, выполнялись команды в удаленном режиме. Связь сохранялась на все время
сеанса совместной работы. Затем с помощью специальных команд эта связь разрывалась.
Современные собственные сетевые средства ориентированы на сети Ethernet — сети с
коммутацией пакетов. Данные передаются пакетами с заголовком, включающим адрес
компьютера, на который передаются данные. В сетях этого типа все компьютеры имеют
активную связь через линии связи постоянно (коаксиальные кабели, витая пара). В
отличие от UUCP сеть этого типа позволяет совместно использовать файловые системы и
интерпретаторы командных строк одновременно на нескольких компьютерах.
Для управления передачей пакетов используется единый протокол — IP (Internet Protocol),
а каждый компьютер сети имеет собственный IP-адрес. Эти адреса присваиваются
администратором сети и хранятся в файле /etc/hosts каждого компьютера сети. Сети
Ethernet де-факто стали стандартом для UNIX.
Для конечных пользователей UNIX предоставляет ряд сервисов (специальных программ),
дающих возможность пользователям работать на различных компьютерах сети. Сетевые
средства позволяют:

копировать файлы с одного компьютера на другой;

входить в другой компьютер для работы на нем;

выполнять командные строки на другом компьютере, а протокол выполнения команд
анализировать на своем;

получить доступ к файлам другого компьютера без копирования на свой диск.
Здесь и далее имена протоколов мы будем указывать в верхнем регистре, что будет
отличать их от одноименных команд UNIX. Например, протокол или сервис FTP, но
команда ftp.
Первыми из этих сервисов были разработаны сервисы TELNET и FTP:

TELNET — сервис для входа в удаленный компьютер и использования всех его
ресурсов;

FTP — (протокол передачи файлов) сервис для обмена файлами с удаленным
компьютером.
По сути, сервисы — это некоторая надстройка над собственно UNIX или его расширение.
Большинство ОС UNIX предоставляют широкий набор сетевых служб, который
постоянно расширяется и совершенствуется.
Идеи и принципы построения локальных вычислительных сетей, для которых изначально
разрабатывался UNIX, привели к созданию глобальных сетей. Сетевые средства UNIX
были быстро модернизированы для поддержки глобальных сетей. В них реализовано
множество средств и услуг, объединенных общим названием Internet (INTERconnected
NETworks — "связанные сети").
В основе управления сетями лежат одни и те же принципы. В обоих случаях используется
протокол IP (протоколы TCP, FTP и др.). Ценность Internet состоит в том, что они не
зависят ни от типа компьютеров, ни от их конфигурации, ни от способа физического
соединения и пр. Обеспечивает инвариантность набор (стек) протоколов TCP/IP. Этот
набор протоколов, по сути, вытеснил все остальные протоколы и тоже стал стандартом.
Наиболее популярным приложением к Internet является одна из самых больших служб
Internet — World Wide Web (WWW или Web).
8.1. Стек протоколов TCP/IP
Все современные версии ОС UNIX поддерживают стек протоколов TCP/IP, который
является стандартом как для взаимодействия компьютеров в локальной сети, так и в
Internet. В основу стека положен протокол IP. Сервисом этого протокола пользуются
транспортные протоколы: TCP (Transmission Control Protocol) – протокол надежной
передачи данных, ориентированный на установление соединения, и UDP (User Datagram
Protocol) – теоретически ненадежный протокол передачи данных без установления
соединения. Прикладные протоколы, с которыми непосредственно работает сетевое
приложение, используют либо протокол TCP, либо протокол UDP. В настоящее время
существует множество прикладных протоколов, которые разработаны с учетом
специфики конкретных сетевых приложений, использующих эти протоколы. Часто
приложения называются так же, как и протокол: например, telnet-приложение использует
в своей работе TELNET-протокол, но www-приложение использует HTTP-протокол.
Перечислим несколько протоколов прикладного уровня с их кратким описанием.
На базе протокола TCP:
TELNET
(Terminal
Networking)
протокол
удаленного
терминального
доступа
к
командному
интерпретатору, данный протокол позволяет организовать сетевой
терминал, т.е. работать с командным интерпретатором другого
компьютера
FTP (File
Transfer
Protocol)
протокол передачи файлов, позволяющий передавать файлы по сети от
SMTP (Simple
Mail Transfer
Protocol)
протокол передачи электронной почты, позволяющий компьютерам
HTTP (Hyper
Text Transfer
Protocol)
самый популярный протокол Internet, его используют www-приложения,
одного компьютера к другому
обмениваться электронными письмами
например, при загрузке www-страницы браузером
На базе протокола UDP:
DNS (Domain
Name System)
протокол,
обеспечивающий
преобразование
символьных
имен
TFTP (Trivial
File Transfer
Protocol)
простой протокол передачи файлов, используется в случае, когда
компьютеров в их IP-адреса
применение протокола FTP слишком громоздко, например, при
начальной загрузке бездисковых станций, когда необходимо передать по
сети загрузочный образ, причем сделать это должна простая программа,
целиком помещающаяся в ПЗУ
Протокол IP
Рассмотрим теперь основные принципы сетевого взаимодействия при использовании
протоколов стека TCP/IP. Базовым протоколом является протокол IP. На него возлагается
функция маршрутизации пакетов. Именно этот протокол отвечает за то, чтобы
информация, переданная с компьютера, находящегося в России, путем последовательных
передач с компьютера на компьютер, в конце концов оказалась на компьютере в
Австралии, для которого информация собственно и предназначалась. Сразу заметим, что
протокол IP обеспечивает теоретически ненадежную передачу данных, так что может
оказаться так, что информация будет потеряна. Но это не имеет значения, так как в стеке
протоколов TCP/IP функции между протоколами строго разграничены, и за надежную
доставку данных будет отвечать протокол TCP, который будет рассмотрен ниже.
Протокол IP всю передаваемую информацию от протоколов более высокого уровня
разбивает на порции определенного размера, снабжает каждую порцию IP-заголовком,
содержащим кроме всего прочего IP-адрес отправителя и IP-адрес получателя.
Сформированный таким образом IP-пакет отправляется в сеть. Каждый промежуточный
компьютер (сетевой узел, маршрутизатор) анализирует информацию, содержащуюся в
заголовке, и определяет: какому следующему узлу необходимо его передать. Этот процесс
как раз и называется маршрутизацией (определение, какому следующему узлу передать
пакет).
Таким
образом,
пакет,
сформированный
на
компьютере-отправителе,
в
неизменном виде (за исключением некоторых полей IP-заголовка) будет доставлен
компьютеру-получателю (или будет потерян), на котором исходная информация будет
собрана и передана протоколу более высокого уровня (TCP или UDP).
Для идентификации компьютеров в IP-сетях используется IP-адрес, причем для сети
Internet IP-адрес должен быть уникален в пределах всей сети, чтобы для пакета,
содержащего в своем заголовке IP-адрес получателя, был однозначно определен
компьютер-получатель. IP-адрес представляет собой четырехбайтовое (32-разрядное)
число, все байты которого записаны в десятичном виде и разделены точкой, например:
194.67.67.33. В терминах протокола IP каждый компьютер, подключенный к сети,
называется host-компьютером или host. Поэтому часто говорят об IP-адресе host.
Поскольку человек лучше запоминает имена, чем числа, то еще используется DNS —
доменная система имен, о которой будет рассказано далее.
Протокол TCP
Рассмотрим теперь протокол TCP. Как уже говорилось, этот протокол обеспечивает
надежную передачу данных с установлением соединения. Каким же образом этот
протокол, пользуясь сервисом ненадежного протокола IP для доставки своих сообщений,
в то же время обеспечивает надежную связь? Не претендуя на подробное изложение
спецификации протокола, поясним кратко суть, позволяющую понять этот парадокс.
Протокол TCP обеспечивает установление соединения между двумя приложениями,
работающими на разных компьютерах (можно и на одном). Поскольку на одном
компьютере с многопроцессной OC UNIX может одновременно работать несколько
приложений, то для идентификации соединения недостаточно только IP-адресов
компьютеров. Каждое соединение идентифицируется четырьмя значениями: IP-адресами
компьютеров и номерами портов приложений. Поэтому между двумя компьютерами
может быть организовано несколько соединений, они будут различаться номерами портов.
Порт – целое число, под хранение которого выделяется два байта, т.е. максимальное
значение номера порта 65535. Известные приложения, использующие стандартные
протоколы, имеют стандартный номер порта. Например, www-приложения используют
номер 80.
Два приложения в TCP-соединении не равноценны. Одно приложение (сервер) пассивно
ждет запроса на установление соединения, другое приложение (клиент) активно посылает
такой запрос. Таким образом, две стороны в соединении носят название сервер (пассивная
сторона) и клиент (активная сторона), говорят о клиент-серверной архитектуре сетевых
приложений. Установление соединения происходит путем "тройного рукопожатия":
последовательного обмена тремя пакетами. Запрос, подтверждение возможности
соединения, подтверждение получения подтверждения, т.е. клиент посылает два пакета, а
сервер один. Далее стороны обмениваются пакетами, причем каждый пакет содержит
информацию прежде всего о том, к какому соединению он относится (четыре
идентификатора), а также порядковый номер пакета (на самом деле все гораздо сложнее,
но для понимания сути этого достаточно). Каждая сторона нумерует посылаемые пакеты.
При получении пакета каждая сторона посылает подтверждение (квитанцию). Обычно
квитанцию помещают в пакет с передаваемыми данными, т.е. специально квитанцию не
посылают, а при посылке очередного пакета с помощью специального флага указывают,
что этот пакет одновременно является квитанцией на полученные ранее данные.
Так как протокол TCP пользуется ненадежным сервисом IP-протокола, то пакет или
квитанция могут быть потеряны. Каждая сторона при посылке каждого пакета запускает
таймер, который сбрасывается при получении квитанции. Если время таймера истекло, а
квитанция не была получена, то сторона повторно посылает предположительно
потерянный пакет и заново запускает таймер. После определенного числа попыток
соединение считается разорванным, т.е. протокол TCP констатирует, что в данных
условиях надежная связь невозможна. Таким образом, возможно установление надежного
соединения при использовании ненадежных сервисов низкого уровня.
Протокол UDP
Протокол UDP более простой. Установление соединения не происходит. Приложения
могут просто обмениваться пакетами. По сути, протокол UDP представляет собой
удобный интерфейс доступа к IP-протоколу. Он снабжает пакеты UDP-заголовками,
содержащими номера портов отправителя и получателя, позволяющие идентифицировать
приложение, тогда как IP-протокол в чистом виде позволяет идентифицировать только
компьютер. Протокол UDP ненадежный, поэтому приложение должно обеспечивать свои
собственные средства, гарантирующие доставку пакетов. Например, приложение может
запускать таймер и повторно отправлять недоставленные сообщения. Протокол UDP часто
используют приложения, обслуживающие одиночные короткие запросы, так как в этом
случае, не получив ответ, приложение может просто повторить еще раз запрос. Например,
запрос доменного имени в DNS.
Рассмотрим теперь доменную систему имен DNS. Как уже было отмечено, каждый
компьютер в сети имеет уникальный IP-адрес, но человек плохо запоминает числовые
идентификаторы, гораздо лучше символьные имена. Поэтому каждому компьютеру
можно присвоить имя и вместо IP-адреса указывать его имя. Первоначально так и было.
Компьютерные сети были маленькие, и каждому компьютеру не представляло труда
присвоить уникальное имя. Список соответствий имен и адресов хранился на каждом
компьютере в файле /etc/hosts. Но даже уже тогда возникала проблема: при подключении
к сети нового компьютера было необходимо обновить содержимое файла /etc/hosts на
каждом компьютере, подключенном к данной сети, т.е. необходима централизованная
система, обеспечивающая преобразование символьных имен в адреса. С другой стороны,
когда количество компьютеров превышает даже сотню, уже трудно обеспечить
уникальность имени.
В
доменной
системе
имен
имя
компьютера
имеет
следующую
структуру:
name3.name2.name1, где частей namen может быть несколько. Каждая часть носит
название домена, причем нумерация доменов производится справа налево, т.е. name1 –
домен первого уровня, например, www.dozen.mephi.ru, здесь ru – домен первого уровня,
mephi – домен второго уровня, dozen – домен третьего уровня, a www.dozen.mephi.ru
целиком – доменное имя. Доменная система имен обеспечивает преобразование
доменного имени в IP-адрес. DNS также обеспечивает множество других полезных
функций, в частности, обратное преобразование IP-адрес – доменное имя.
Доменная система имен – распределенная по всему миру постоянная обновляемая база
данных, где за каждым DNS-сервером четко закреплена зона ответственности. В
терминологии DNS – зона ответственности так и называется зона, а сервер, отвечающий
за эту зону, называется авторитетным сервером. На администратора авторитетного
сервера возлагается обязанность следить за уникальностью имени в пределах зоны.
Рассмотрим теперь простые команды, с помощью которых рядовой пользователь может
проверить сетевые настройки системы. Средства администрирования мы не будем
рассматривать в этом пособии.
8.2. Простые команды
Проверить настройки сетевых интерфейсов можно при помощи команды ifconfig.
Пример:
$ /sbin/ifconfig
eth0 Link encap:Ethernet HWaddr f8:d1:11:b5:63:eb
inet addr:194.67.67.136 Bcast:194.67.67.255
Mask:255.255.255.0
inet6 addr: fe80::fad1:11ff:feb5:63eb/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:314024 errors:0 dropped:0 overruns:0 frame:0
TX packets:367934 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
bytes:59629722 (56.8 MiB) TX bytes:72918707 (69.5 MiB)
Interrupt:24 Base address:0x4000
lo
Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
inet6 addr: ::1/128 Scope:Host
UP LOOPBACK RUNNING MTU:16436 Metric:1
RX packets:53932 errors:0 dropped:0 overruns:0 frame:0
TX packets:53932 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:6521968 (6.2 MiB)
TX bytes:6521968 (6.2 MiB)
$
В результате работы этой команды выводится информация о всех доступных сетевых
интерфейсах. Обратим внимание, что пришлось вводить полное путевое имя команды, так
как обычно команда ifconfig считается командой администрирования и находится в
каталоге /sbin, путь к которому не прописывается в переменной PATH для рядового
пользователя.
В данном примере доступны два сетевых интерфейса eth0 –реальный сетевой адаптер и lo
(loopback) – так называемый петлевой интерфейс, предназначенный для передачи сетевых
пакетов самому себе. Если компьютер не подключен к реальной сети, но все сетевое
программное обеспечение корректно установлено и настроено, то в системе будет
присутствовать единственный сетевой интерфейс lo.
Рассмотрим параметры интерфейса eth0. В первой строке выводятся параметры
канального уровня: протокол Ethernet, физический адрес сетевого адаптера. Во второй
строке выводятся характеристики сетевого уровня протокола IP версии 4: адрес,
широковещательный адрес и сетевая маска. В третьей строке выводятся характеристики
сетевого уровня протокола IP версии 6. Информация в следующих строках более
интересна для системного администратора: аппаратные параметры сетевого интерфейса и
статистика его использования с момента начальной загрузки.
Нам интересен только IP-адрес. Под этим адресом компьютер известен во всей сети
интернет. (За исключением случаев, когда компьютер находится в рамках локальной сети,
использующей сетевую трансляцию адресов.)
Посмотрим теперь сетевое имя компьютера при помощи команды hostname и доменное
имя c использованием опции –domain.
Пример:
$ hostname
samos
$ hostname --domain
dozen.mephi.ru
$
При помощи команды ping можно проверить доступность любого сетевого хоста, причем
в параметрах команды можно указывать как доменное имя, так и сетевой IP-адрес. Эта
команда инициирует посылку так называемых эхо-запросов, на каждый из которых
сетевой хост посылает эхо-ответ. По умолчанию периодичность – 1 секунда. Команда
работает циклически, пока ее принудительно не завершат комбинацией клавиш ctrl-c.
Пример:
$ ping org.mephi.ru
PING vivaldi.mephi.ru (85.143.112.61) 56(84) bytes of data.
64 bytes from org.mephi.ru (85.143.112.61): icmp_req=1 ttl=62
time=0.418 ms
64 bytes from org.mephi.ru (85.143.112.61): icmp_req=2 ttl=62
time=0.365 ms
64 bytes from org.mephi.ru (85.143.112.61): icmp_req=3 ttl=62
time=0.475 ms
^C
--- vivaldi.mephi.ru ping statistics --3 packets transmitted, 3 received, 0% packet loss, time 2001ms
rtt min/avg/max/mdev = 0.365/0.419/0.475/0.047 ms
$ ping 85.143.112.60
PING 85.143.112.60 (85.143.112.60) 56(84) bytes of data.
64 bytes from 85.143.112.60: icmp_req=1 ttl=62 time=0.421 ms
64 bytes from 85.143.112.60: icmp_req=2 ttl=62 time=0.377 ms
64 bytes from 85.143.112.60: icmp_req=3 ttl=62 time=0.361 ms
^C
--- 85.143.112.60 ping statistics --3 packets transmitted, 3 received, 0% packet loss, time 1998ms
rtt min/avg/max/mdev = 0.361/0.386/0.421/0.030 ms
$ ping 127.0.0.1
PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data.
64 bytes from 127.0.0.1: icmp_req=1 ttl=64 time=0.061 ms
64 bytes from 127.0.0.1: icmp_req=2 ttl=64 time=0.057 ms
64 bytes from 127.0.0.1: icmp_req=3 ttl=64 time=0.050 ms
^C
--- 127.0.0.1 ping statistics --3 packets transmitted, 3 received, 0% packet loss, time 1998ms
rtt min/avg/max/mdev = 0.050/0.056/0.061/0.004 ms
$ ping www.yandex.ru
PING www.yandex.ru (93.158.134.3) 56(84) bytes of data.
64 bytes from www.yandex.ru (93.158.134.3): icmp_req=1 ttl=59
time=1.85 ms
64 bytes from www.yandex.ru (93.158.134.3): icmp_req=2 ttl=59
time=1.71 ms
64 bytes from www.yandex.ru (93.158.134.3): icmp_req=3 ttl=59
time=1.77 ms
^C
--- www.yandex.ru ping statistics --3 packets transmitted, 3 received, 0% packet loss, time 2003ms
rtt min/avg/max/mdev = 1.712/1.781/1.857/0.076 ms
$
В данном примере осуществляется посылка эхо-запросов серверу org.mephi.ru сначала по
доменному имени, а потом и по IP-адресу. Далее тестируется петлевой интерфейс (IPадрес 127.0.0.1), затем сервер www.yandex.ru. Команда выводит много полезной
информации: для каждого запроса время получения ответа, а также общую статистику по
всем запросам. Можно видеть, что программный петлевой интерфейс имеет минимальную
задержку, так как не задействованы сетевые аппаратные средства. Сервер org.mephi.ru
находится в корпоративной сети – задержка больше. Самая большая задержка для сервера
во внешней сети – www.yandex.ru.
Сетевой пакет, передаваясь от отправителя к получателю, в общем случае проходит
несколько промежуточных серверов. Команда traceroute позволяет отследить все
промежуточные серверы (маршрут) на пути от отправителя к получателю. Работа этой
команды основана на возможности протокола IP уничтожать пакет с истекшим временем
жизни (ttl). Формат IP-пакета включает в себя поле ttl, в которое отправитель пакета
заносит некоторое положительное значение. Каждый промежуточный сервер при
обработке пакета обязан уменьшить значение этого поля на единицу. Если при этом
значение поля становится равным нулю, то сервер должен уничтожить такой пакет и
послать отправителю специальное icmp-сообщение.
Как работает команда traceroute? В качестве параметра ей передается имя целевого
сервера, до которого мы хотим проследить маршрут. Эта команда формирует пакеты с
последовательно увеличивающимся полем ttl. По умолчанию для каждого значения ttl
посылается три пакета. Начальное значение поля – 1. Таким образом, первые три пакета со
значением поля ttl равным единице будут уничтожены первым сервером маршрута.
Отправитель получит соответствующие icmp-сообщения. Следующие три пакета с полем
ttl равным 2 будут уничтожены вторым сервером маршрута и т.д. Получение icmpсообщения от целевого сервера будет означать, что весь маршрут отслежен. По
умолчанию команда traceroute увеличивает значение ttl до 30. Следовательно, без указания
специальных опций мы можем отслеживать маршруты, содержащие не более 30
промежуточных серверов.
Пример:
$ traceroute www.mephi.ru
traceroute to www.mephi.ru (85.143.112.50), 30 hops max, 60 byte
packets
1 abc.dozen.mephi.ru (194.67.67.1) 0.105 ms 0.468 ms 0.485 ms
2 85.143.113.1 (85.143.113.1) 0.762 ms 0.933 ms 0.956 ms
3 mephi.ru (85.143.112.50) 0.596 ms 0.586 ms 0.579 ms
$ traceroute www.yandex.ru
traceroute to www.yandex.ru (93.158.134.3), 30 hops max, 60 byte
packets
1 abc.dozen.mephi.ru (194.67.67.1) 0.097 ms 0.269 ms 0.256 ms
2 85.143.113.1 (85.143.113.1) 0.699 ms 0.690 ms 0.917 ms
3 m9-2-gw.msk.runnet.ru (194.85.37.165) 0.808 ms 0.784 ms 0.769
ms
4 msk-ix-m9.yandex.net (193.232.244.93) 1.293 ms 0.971 ms
0.910 ms
5 * * *
6 ugr-b-c1-ae4.yndx.net (87.250.239.75) 2.314 ms ugr-p1be1.yndx.net (87.250.239.79) 2.626 ms ugr-p3-be2.yndx.net
(87.250.239.78) 3.391 ms
7 ugr-b-c1-ae5.yndx.net (87.250.239.97) 2.090 ms * 4.807 ms
8 * * *
9 * * *
10 www.yandex.ru (93.158.134.3) 3.185 ms * *
$ traceroute 127.0.0.1
traceroute to 127.0.0.1 (127.0.0.1), 30 hops max, 60 byte
packets
1 localhost.localdomain (127.0.0.1) 0.044 ms 0.015 ms 0.014 ms
$
Рассмотрим сначала формат выдачи. В первой строке указывается имя и адрес целевого
сервера, а также максимальное значение ttl и размер посылаемых пакетов. Далее в каждой
строке имя сервера и в скобках адрес и три времени получения ответа. В некоторых
строках имя отсутствует, а адрес указан два раза. Дело в том, что от промежуточного
сервера приходит icmp-сообщение, которое содержит только адрес. Команда traceroute
пытается с помощью службы DNS преобразовать адрес в доменное имя. Не всегда
промежуточные серверы имеют запись в базе данных DNS. В этих случаях мы видим
адрес, указанный дважды. Если пакет потерялся, то вместо времени будет напечатан
символ *. Если же все три пакета потерялись, то мы не можем узнать и адрес этого
сервера. Бывает, что промежуточные серверы молча уничтожают пакеты, не посылая
icmp-сообщения.
В данном примере отслеживается маршрут до сервера в корпоративной сети
www.mephi.ru, до сервера www.yandex.ru и до петлевого интерфейса 127.0.0.1.
8.3. Удаленный сеанс работы
Сетевые средства позволяют осуществить удаленный сеанс работы. Мы рассмотрим
возможности, предоставляемые сервисами TELNET и SSH. Отметим, что сервис TELNET
более ранний сейчас практически не используется, так как весь сетевой трафик (в том
числе и пароль) передается в открытом виде, так что злоумышленник может подслушать
пароль и впоследствии войти в систему от имени данного пользователя. При
использовании
сервиса
SSH
весь
сетевой
криптографических алгоритмов.
Рассмотрим сеанс связи при помощи команды telnet.
Пример:
$ telnet samos.dozen.mephi.ru
Trying 194.67.67.136...
Connected to samos.dozen.mephi.ru.
Escape character is '^]'.
трафик
шифруется
при
помощи
Debian GNU/Linux 6.0
samos login: user333
Password:
Last login: Sat Aug 7 11:42:57 MSK 2014 from ppp91-75-38111.pppoe.mtu-net.ru on pts/0
Linux samos 2.6.32 #1 SMP Wed Sep 22 10:12:37 MSD 2010 i686
The programs included with the Debian GNU/Linux system are free
software;
the exact distribution terms for each program are described in
the
individual files in /usr/share/doc/*/copyright.
Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the
extent
permitted by applicable law.
No mail.
$ date
Сбт Авг 9 17:53:10 MSK 2014
abv@samos:~$ logout
Connection closed by foreign host.
$
В качестве параметра команде telnet указывается имя сервера, с которым мы хотим
осуществить удаленный сеанс работы. Можно указывать IP-адрес. Далее удаленная
система запрашивает имя пользователя и пароль аналогично при работе в локальном
режиме и выводит приглашения командного интерпретатора. Сеанс работы начат, и
можно вводить любые команды. В примере вводится команда date. Для завершения сеанса
работы вводится команда logout или комбинация клавиш ctrl-d.
Аналогично можно использовать сервис SSH. Заметим, что в команде ssh с помощью
опции -l задается имя пользователя, а в начале сеанса работы запрашивается только
пароль. Если имя пользователя не указать, то по умолчанию будет использоваться имя
локального
пользователя.
Команда
ssh
имеет
расширенные
возможности
аутентификации пользователей при помощи специальных ключей, позволяющие входить
в удаленную систему без ввода пароля. В рамках данного пособия мы эти возможности
рассматривать не будем.
Пример:
$ ssh –l user333 samos.dozen.mephi.ru
user333@samos.dozen.mephi.ru's password:
Linux samos 2.6.32 #1 SMP Wed Sep 22 10:12:37 MSD 2010 i686
The programs included with the Debian GNU/Linux system are free
software;
the exact distribution terms for each program are described in
the
individual files in /usr/share/doc/*/copyright.
Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the
extent
permitted by applicable law.
No mail.
Last login: Sat Aug 9 17:53:01 2014 from samos.dozen.mephi.ru
$ date
Сбт Авг 9 18:11:17 MSK 2014
$ logout
Connection to samos.dozen.mephi.ru closed.
$
8.4. Пересылка файлов между компьютерами
Традиционно для пересылки файлов используется сервис FTP (одноименная команда
ftp), который обладает рядом недостатков. Главный из них – открытость трафика. Вся
пересылаемая информация: пароль пользователя, содержимое пересылаемых файлов
может быть перехвачена злоумышленником. Несмотря на это, этот сервис по-прежнему
активно используется в тех случаях, когда перечисленные недостатки некритичны.
Например, для пересылки файлов с публичных (общедоступных) ftp-серверов. Ниже мы
рассмотрим и прокомментируем пример работы с публичным ftp-сервером.
Отметим еще одну особенность протокола FTP. При его работе открывается несколько
TCP-соединений. Главное соединение существует в течение всего сеанса работы, по
которому передаются управляющие команды. В рамках этого соединения традиционно
компьютер, с которого пользователь запрашивает пересылку файлов, является клиентом.
Для пересылки каждого файла открывается новое соединение. В первых версиях
протокола FTP это соединение могло быть только обратным, сервером в котором являлся
компьютер, получающий пересылаемый файл. (Напомним, что сервер иначе называется
пассивной стороной соединения, а клиент – активной.) Зачастую эта особенность
приводила к невозможности работы FTP с компьютеров, находящихся в локальных сетях
с трансляцией адресов. Современные версии протокола включают команду passive,
которая позволяет и эти вспомогательные соединения открывать в том же направлении,
что и главное. Некоторые современные ftp-серверы по умолчанию работают в пассивном
режиме и не требуют явного ввода этой команды.
Пример:
$ mkdir forftp
$ ftp dozen.mephi.ru
Connected to dozen.mephi.ru.
220 ProFTPD 1.2.5 Server (Computer Systems and Technologies FTPserver) [dozen.mephi.ru]
Name (dozen.mephi.ru:abv): anonymous
331 Anonymous login ok, send your complete email address as your
password.
Password:
230Hello anonymous from samos.dozen.mephi.ru, host dozen.mephi.ru
pleased to meet you.
*** Welcome dozen.mephi.ru FTP server! ***
Local time: Fri Aug 15 13:57:18 2014
Users at your class: 1, of maximum 50 allowed.
In case of problems:
root@dozen.mephi.ru.
please send e-mail to
230 Anonymous access granted, restrictions apply.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> cd /pub
250 CWD command successful.
ftp> dir
200 PORT command successful.
150 Opening ASCII mode data connection for file list.
drwxr-xr-x 7 dozen dozen 4096 Mar 25 13:39 DIPLOM
drwxr-xr-x 2 dozen dozen 4096 Aug 31 2000 PAR
226 Transfer complete.
ftp> cd DIPLOM
250 CWD command successful.
ftp> dir
200 PORT command successful.
150 Opening ASCII mode data connection for file list.
-rw-r--r-- 1 dozen dozen 67072 Sep 7 2006 rez.doc
-rw-r--r-- 1 dozen dozen 43714 Jan 31 2006 rez.zip
-rw-r--r-- 1 dozen dozen 44032 Nov 4 2013
titul.doc
-rwxr-xr-x 1 dozen dozen 44032 Jan 31 2012 uirt.doc
-rw-r--r-- 1 dozen dozen 206796 Jan 17 2005 unix.zip
-rw-r--r-- 1 dozen dozen 136704 Jan 17 2005 unixcom.doc
-rw-r--r-- 1 dozen dozen 132608 Jan 17 2005 unixjob8.doc
-rw-r--r-- 1 dozen dozen 107520 Jan 17 2005 unixlabs.doc
-rw-r--r-- 1 dozen dozen 503296 Jan 17 2005 unixlect.doc
-rw-r--r-- 1 dozen dozen 20480 Jan 17 2005 unixlit.doc
-rw-r--r-- 1 dozen dozen 23552 Jan 17 2005 unixprog.doc
-rw-r--r-- 1 dozen dozen 26624 Jan 17 2005 unixques.doc
-rw-r--r-- 1 dozen dozen 47616 Feb 1 2010 unixshed.doc
-rw-r--r-- 1 dozen dozen 24576 Jan 17 2005 unixvi.doc
-rw-r--r-- 1 dozen dozen 364540 Sep 3 2003 vhdl.zip
-rw-r--r-- 1 dozen dozen 371040 Sep 26 2003 vhdl1.zip
-rw-r--r-- 1 dozen dozen 1726106 Feb 12
226 Transfer complete.
ftp> lcd forftp
Local directory now /home/abv/forftp
ftp> lcd
Local directory now /home/abv/forftp
ftp> get unix.zip unix1.zip
local: unix1.zip remote: unix.zip
200 PORT command successful.
150 Opening BINARY mode data connection for unix.zip (206796
bytes).
226 Transfer complete.
206796 bytes received in 0.02 secs (10897.9 kB/s)
ftp> hash
Hash mark printing on (1024 bytes/hash mark).
ftp> get unix.zip
local: unix.zip remote: unix.zip
200 PORT command successful.
150 Opening BINARY mode data connection for unix.zip (206796
bytes).
################################################################
################################################################
################################################################
#########
226 Transfer complete.
206796 bytes received in 0.02 secs (10980.3 kB/s)
ftp> mget unix*
mget unix.zip? n
mget unixcom.doc? n
mget unixjob8.doc? n
mget unixlabs.doc? n
mget unixlect.doc? n
mget unixlit.doc? n
mget unixprog.doc? y
200 PORT command successful.
150 Opening BINARY mode data connection for unixprog.doc (23552
bytes).
#######################
226 Transfer complete.
23552 bytes received in 0.02 secs (1275.7 kB/s)
mget unixques.doc? n
mget unixshed.doc? n
mget unixvi.doc? n
ftp> prompt
Interactive mode off.
ftp> mget rez*
local: rez.doc remote: rez.doc
200 PORT command successful.
150 Opening BINARY mode data connection for rez.doc (67072
bytes).
################################################################
#
226 Transfer complete.
67072 bytes received in 0.01 secs (9927.3 kB/s)
local: rez.zip remote: rez.zip
200 PORT command successful.
150 Opening BINARY mode data connection for rez.zip (43714
bytes).
##########################################
226 Transfer complete.
43714 bytes received in 0.00 secs (10374.1 kB/s)
ftp> quit
221 Goodbye.
$ ls forftp
rez.doc rez.zip unix1.zip unixprog.doc unix.zip
$
Рассмотрим подробнее представленный сеанс взаимодействия с ftp-сервером. Первым
действием был создан каталог forftp, в который в дальнейшем будут помещаться
получаемые от сервера файлы. Далее устанавливаем соединение с ftp-сервером. В
качестве параметра команды ftp задается имя сервера. Устанавливается соединение, и
сервер выводит информацию о версии программного обеспечения. Следующим шагом
требуется аутентификация: задание имени и пароля. В данном примере работа
осуществляется с публичным сервером, который предоставляет возможности получения
файлов для всех желающих. В этом случае имя пользователя – anonymous, а в качестве
пароля требуется указать свой почтовый адрес. Впрочем, большинство ftp-серверов не
проверяют корректность почтового адреса, так что единственный след, который останется
в системном журнале ftp-сервера – это ip-адрес клиента.
Анонимная аутентификация прошла успешно, ftp-сервер выводит приглашение ftp>,
требуется вводить команды. Для пересылки файлов необходимо установить два каталога:
удаленный, находящийся на сервере, из которого будет осуществляться пересылка, и
локальный, находящийся на нашем компьютере, в который будут помещаться
пересылаемые файлы. Для изменения удаленного каталога используется команда cd,
просмотра его содержимого – dir. Получить полный путь к текущему удаленному
каталогу
можно
при
помощи
команды
pwd.
Изменение
локального
каталога
осуществляется при помощи команды lcd. Ввод команды lcd без параметров позволяет
получить полный путь к текущему локальному каталогу. Во время ftp-сеанса возможно
выполнение любых локальных команд командного интерпретатора. Для этого следует
перед вводимой командной строкой указать символ !.
Настройка каталогов произведена. Пересылка файлов будет осуществляться из удаленного
каталога DIPLOM в локальный каталог forftp. Для пересылки файлов используется
команда get. В качестве первого параметра указывается имя пересылаемого файла, в
качестве второго – имя, которое получит этот файл на локальной машине. Если второй
параметр не задан, то файл получит то же самое имя, которое он имел на ftp-сервере. С
помощью команды hash можно включить режим отображения пересылки файлов, при
котором каждый килобайт файла будет отображаться символом #. Повторный ввод
команды hash отключает этот режим.
Команда get позволяет за один прием переслать только один файл. Если необходимо
переслать сразу несколько файлов, то используется команда mget. В качестве параметров
перечисляются имена пересылаемых файлов. Можно использовать метасимволы *, ?,
[], !. Команда mget не позволяет переименовывать файлы: все полученные файлы на
локальной машине будут иметь те же имена, что и на сервере. Для каждого пересылаемого
файла команда mget выдает запрос, что позволяет задать с помощью метасимволов более
широкое множество файлов, а потом выбрать только те, которые нужны. Режим запроса
(интерактивный режим) можно отключить при помощи команды prompt. В этом случае
команда
mget
перешлет
все
файлы,
удовлетворяющие
шаблону
имени
без
дополнительных запросов. Повторный ввод команды prompt включает интерактивный
режим.
Выход из команды ftp осуществляется при помощи команды quit. В последней строке
протокола пользователь с помощью команды ls убеждается, что все необходимые файлы
находятся в каталоге forftp. Заметим, что для непубличных серверов этот протокол
использовать нельзя: и пароль, и пересылаемые файлы могут стать достоянием
общественности.
Для конфиденциальной пересылки файлов следует использовать команду scp. Эта
команда использует уже ранее рассмотренный протокол SSH и шифрует весь
передаваемый трафик. Еще одной особенностью данной команды является возможность
управления пересылкой файлов с третьего компьютера, который не является ни
источником, ни приемником. В этом случае команда запросит два пароля: для стороны,
посылающей файл, и стороны, принимающей файл. Для данной команды мы приведем
полный формат, пример использования мы приводить не будем, так как он очевиден.
scp user1@host1:path_to_file1 user2@host2:path_to_file2
Если user1 или user2 не указаны, то используется имя текущего пользователя на
локальном компьютере. Если осуществляется пересылка файла с/на текущий компьютер,
то опускается соответственно host1/host2. Вместо полного имени файла можно
использовать относительное имя относительно домашнего каталога пользователя, в этом
случае путь будет начинаться с символа ~.
8.5. Вопросы для самоконтроля
1. Перечислите основные особенности протоколов IP, TCP и UDP.
2. Для чего предназначена доменная система имен?
3. Каким образом можно проверить сетевые настройки локального компьютера?
4. С помощью каких команд можно проверить доступность удаленного компьютера и
маршрут следования пакетов между ними?
5. Какие особенности удаленного сеанса работы с использованием команды telnet?
6. Какие дополнительные возможности предоставляет протокол SSH?
7. Перечислите известные способы пересылки файлов между компьютерами.
9. Управление дисковым пространством
9.1. Управление дисками
Дисковая
память
длительного
–
наиболее
хранения
и
распространенная
оперативного
энергонезависимая
использования
данных
в
память
для
современных
вычислительных системах. Она, наряду с оперативной памятью и ЦПУ, является важным
системным ресурсом совместного доступа. Системный администратор должен уметь
выполнять следующие задачи, связанные с управлением дисковой памятью:

обеспечение надежного хранения и доступности данных;

разбиение диска на разделы;

создание, мониторинг и обслуживание файловых систем;

выполнение регулярного резервного копирования данных.
Еще до установки системы на этапе планирования необходимо определиться с действиями
на случай:

выхода жесткого диска из строя;

повреждения данных;

недостатка свободного места на диске и файловой системе;

недостаточной пропускной способности дисковой системы.
Ответы на эти вопросы определят метод управления дисковым пространством, тип
файловой системы и методы и политики резервного копирования.
Традиционно, в состав дисковой памяти входит по крайней мере один накопитель на
жестком магнитном диске (НЖМД). Хотя в современных вычислительных системах все
чаще можно встретить твердотельные полупроводниковые накоптили flash и SSD. НЖМД
является самым распространенным, дешевым и емким элементом для построения систем
хранения данных (СХД).
Организация данных на диске построена на блочном принципе - считывание и запись
информации производится блоками. Блоки распределяются по всему пространству
поверхности жесткого диска по определенной схеме, определяющей способ адресации
блоков. Минимальный размер блока равен одному физическому сектору (512 байт). Это
непрерывная часть дорожки на магнитной пластине жесткого диска.
На рисунке 9.1 изображена структура НЖМД. В самом общем случае допустимый объем
данных, хранимых на диске, определяется его «геометрией» C/H/S – количеством
цилиндров/головок_на_цилиндре/секторов_на_дорожке.
Тогда
диск
имеет
объем
C*H*S*512 байт. Учет геометрии при разрешении данных на диске, и разделение диска на
цилиндры были важны с точки зрения производительности, так как обращение к разным
секторам одного цилиндра не приводит к дополнительному позиционированию головок на
дорожке.
Рис. 9.1. Структура и адресация НЖМД
Блоки данных могут распределяться и адресоваться по-разному в трехмерном
пространстве жесткого диска. В настоящее время распространение получила схема, не
учитывающая геометрию диска, - линейная схема распределения блоков по секторам LBA
(Linear
(или
Logical)
Block
Addressing).
Все
сектора
на
диске
нумеруются
последовательно, начиная с первого сектора на нулевой дорожке нулевого цилиндра. Эта
схема ориентирована на большие объемы жестких дисков, ограничение размера диска
обусловлено лишь разрядностью LBA. Сейчас используется 48-битый формат адреса,
каждый сектор получает 48-разрядный логический адрес - его порядковый номер в общем
массиве секторов. Тем самым допускается адресация к 2**48 секторам в пределах одного
диска, что соответствует 128 пебибайт (ПиБ). Но архитектура современны компьютеров
позволяет использовать и 64-битную адресацию, если в этом будет необходимость.
Преобразование логических адресов секторов в физические производят контроллеры
дисков, которые знакомы с истинной «геометрией диска». При этом скорость доступа к
отдельному блоку будет переменной. Она зависит от большого числа факторов: от схемы
распределения и адресации блоков в трехмерной модели C/H/S, от текущего
расположения головок чтения/записи и места расположения искомого блока и т. д.
Адрес блока LBA может быть получен по следующей формуле:
LBA=(номер_цилиндра*количество_головок+номер_головки)*количество
_секторов_на_дорожку+номер_сектора-1
Если диск и BIOS используют LBA, но в какой-то момент требуется получить адрес в
формате C/H/S, то используется схема, зависящая только от размера диска:
Размер диска
Секторов/дорожку Головки
Цилиндры
1 < X ≤ 504 MiB
63
16
X/(63*16*512)
504 MiB < X ≤ 1008 MiB
63
32
X/(63*32*512)
1008 MiB < X ≤ 2016 MiB
63
64
X/(63*64*512)
2016 MiB < X ≤ 4032 MiB
63
128
X/(63*128*512)
4032 MiB < X ≤ 8032.5 MiB 63
255
X/(63*255*512)
Вследствие этого в современных системах отображаемая некоторыми утилитами
«геометрия» диска может ничего общего не иметь с реальными характеристиками.
Каждый диск может иметь один или несколько разделов.
Раздел может быть использован для:

файловой системы

пространства для вытеснения страниц оперативной памяти swap

данных приложения без создания файловой системы

области загрузки операционной системы
Методы управления дисковым пространством:

использование диска целиком без создания разделов;

создание разделов диска утилитами fdisk, parted и т.п.

использование менеджеров томов;

Logical Volume Manager;

Veritas Volume Manager;

и т.п.
Рис. 9.2. Пример разбиения и использования пространства диска
Разделы диска, которые можно использовать для хранения данных (файловых систем и
других), называются логическими дисками. Большинство утилит управления дисковым
пространством (создания избыточного набора дисков (RAID); создания групп томов LVM;
создания файловых систем) могут быть применены как к отдельному физическому диску
целиком, так и к отдельному разделу диска — логическому диску.
Преимущества использования разделов:

на одном физическом жестком диске можно хранить информацию в разных
файловых системах, или в одинаковых файловых системах, но с разным размером
блока;

на одном жестком диске можно установить несколько операционных систем;

обслуживание (форматирование и дефрагментация) каждого раздела не затрагивает
другие;

упрощение создания резервных копий данных;

установка различных квот на разные разделы;

подключение файловых систем в разных режимах («только для чтения», «без
поддержки исполняемых файлов», «без кэширования» и другие).
Соглашения по именованию дисковых устройств и разделов на дисках
В UNIX пользователи получают доступ к аппаратным устройствам через специальные
файлы – файлы устройств. Таким же образом организуется доступ к физическим и
логическим дискам. Исторически, большая часть файлов устройств создается на этапе
установки, но они могут быть также созданы позже вручную при помощи команды
mknod. Создавая файлы устройств, необходимо определить тип, а также старшие и
младшие (major & minor) номера для устройства.
Рис. 9.3. Создание файлов устройств вручную командой mknod
# ll /dev/*
↓ тип файла устройства
b rw-rw---b rw-rw---b rw-rw---c rw------c rw-rw-rw-
1
1
1
1
1
старший номер ↓
root
root
root
root
root
disk
disk
disk
root
root
3,
3,
8,
4,
1,
имя файла устройства ↓
0
1
2
1
5
↑
2008-09-06 16:32
2008-09-06 16:32
2005-02-26 09:38
2008-10-10 11:09
2008-09-06 16:32
младший номер
/dev/hda
/dev/hda1
/dev/sda2
/dev/tty1
/dev/zero
Соответствие старших номеров устройств и названий драйверов можно узнать из
содержимого файла /proc/devices.
#cat /proc/devices
Character devices:
1 mem
4 tty
Block devices:
3 ide0
8 sd
Файлы устройств служат интерфейсом к дискам, обмен данными с которыми происходит
блоками. Когда приложение обращается к файлу устройства диска, то ядро использует
соответствующий
драйвер,
который
и
организует
реальное
взаимодействие
с
соответствующим диском.
Такая схема дает возможность пользователю воспринимать диски (или другие устройства)
как файлы. Следовательно, можно использовать систему именований, принятую при
обращении к файлам – использовать маршрутные имена. Хотя файлы устройств могут
быть созданы где угодно, обычно эти файлы располагаются в каталоге /dev/. Поэтому
маршрутное имя файла устройства представляется в форме /dev/имя_файлаустройства.
Конструкция имя_файла-устройства в Linux следует стилю именования устройств в
UNIX. В частности в UNIX, имена файлов устройств к дискам обычно содержат указание
на тип диска, номер контроллера, логический номер устройства, раздел диска, вид доступа
(блочный или символьный) и т.п. В Linux при именовании физических IDE-дисков
идентифицируется порядок их подключения в системе:
Описание физического Маршрутное имя файла Старший номер Младший
IDE диска
устройства
номер
Primary Master
/dev/hda
3
0
Primary Slave
/dev/hdb
3
64
Secondary Master
/dev/hdc
3
128
Secondary Slave
/dev/hdd
3
192
Первичные разделы на физическом диске обозначаются дополнительной цифрой в имени
устройства (в сквозном порядке, с 1 по 4). Логические разделы обозначаются цифрой
последовательно, начиная с номера 5. Они не могут чередоваться с первичными разделами.
Описание раздела на Маршрутное имя файла Старший номер Младший
физическом IDE диске
устройства
Primary Master, раздел 1 /dev/hda1
номер
3
1
3
2
3
3
3
5
3
6
(первичный)
Primary Master, раздел 2 /dev/hda2
(первичный)
Primary Master, раздел 3 /dev/hda3
(первичный)
Primary Master, раздел 5 /dev/hda5
(логический)
Primary Master, раздел 6 /dev/hda6
(логический)
Именование физических SCSI-дисков производится по аналогичным правилам:
Описание
SCSI диска
физического Маршрутное
файла устройства
имя Старший номер Младший
номер
Диск 0
/dev/sda
8
0
Диск 1
/dev/sdb
8
16
Диск 3
/dev/sdc
8
32
Описание
раздела
физическом SCSI диске
Диск
0,
на Маршрутное
имя Старший номер Младший
файла устройства
номер
раздел
1 /dev/sda1
8
1
раздел
2 /dev/sda2
8
2
раздел
3 /dev/sda3
8
3
(первичный)
Диск
0,
(первичный)
Диск
0,
(первичный)
Из представленных таблиц видно, что имена файлов устройств scsi-дисков не связаны ни с
физическим адресом диска, ни с уникальными аппаратными идентификаторами. На
практике может возникнуть ситуация, когда некий диск в один момент времени имел имя
/dev/sdb, а после очередной перезагрузки системы (например, из-за выхода из строя
другого диска) получил имя /dev/sda. Такая ситуация приводит к проблемам с
загрузкой ОС и угрозам потери данных на диске из-за неверного его использования.
Чтобы этого избежать, в современных Linux-системах в каталоге /dev/disks
автоматически создаются файлы устройств дисков, устойчивые к таким изменениям.
$ tree /dev/disk
/dev/disk
|-- by-id
|
|-- ata-WDC_WD1200JB-00EVA0_WD-WMALC1323712 -> ../../hda
|
|-- ata-WDC_WD1200JB-00EVA0_WD-WMALC1323712-part1 ->
../../hda1
|-- by-label
|
|-- home -> ../../hda3
|
|-- pxe_root -> ../../hda11
|-- by-path
|
|-- pci-0000:00:1f.1-ide-0:0 -> ../../hda
|
|-- pci-0000:00:1f.1-ide-0:0-part1 -> ../../hda1
`-- by-uuid
|-- 130a4553-821b-47e5-ba90-6c1e1706c8c6 -> ../../hda
|-- 44238787-84d9-4dd2-879f-c80a0e205540 -> ../../hda11
Файлы в каталоге /dev/disk/by-id используют в своем имени идентификатор
производителя и модель диска. В каталоге /dev/disk-by-label имена формируются
на основе текстовой метки, установленной администратором ОС. by-path использует
аппаратный
адрес
диска,
а
by-uuid
универсальный
уникальный
цифровой
идентификатор. Чаще всего администраторы предпочитают идентифицировать диск или
раздел диска по его метке или UUID. Метка имеет понятный человеку формат, и может
быть логически связанной с назначением файловой системы на разделе. Но есть
вероятность дублирования метки — ситуации, когда два разных раздела получат
одинаковую метку. Для UUID вероятность такой ситуации крайне мала, но UUID имеет не
удобный для человека формат.
Быстро найти файл устройства диска по его метке или UUID можно с помощью команды
findfs.
$ findfs LABEL=ROOT
/dev/sda6
$ findfs UUID=92ebb352-ba93-49f1-aac5-0d8efbabcaf4
/dev/sda5
Еще одна удобная команда lsscsi, она позволяет узнать, какие диски в системе
присутствуют, и какие файлы устройств им соответствуют:
# lsscsi -d
[0:0:1:0]
cd/dvd
/dev/sr0[11:0]
Optiarc
DVD RW AD-5260S
1.00
[2:0:0:0]
disk
/dev/sda[8:0]
[3:0:0:0]
disk
/dev/sdb[8:16]
ATA
Hitachi HDS72105 JP2O
ATA
WDC WD3200AAKS-0 01.0
Получение информации об устройстве через udef
В современном мире новые устройства могут подключаться к компьютеру без отключения
питания и перезагрузки. Операционная система должна предоставить специальные файлы
для работы с такими устройствами. Для этого либо необходимо заранее создавать файлы
под все возможные существующие устройства, которые в принципе могут появиться в
системе, либо генерировать файлы устройств автоматически, по необходимости, в момент
появления новых устройств. И так же автоматически их удалять, кода устройство
отключается. Для таких задач в Linux разработан и используется менеджер устройств
udef. Администратор может получить информацию об устройствах и созданных для них
файлах с помощью команды udevadm.
Получить дамп всех устройств в базе udev:
$ udevadm info -e
Запросить информацию об отдельных устройствах:
$ udevadm info -a -p /block/sda
Получить путь к устройству по имени устройства:
$ udevadm info -q all -n sda
$ udevadm info -q path -n /dev/sda
$ udevadm info -a -n /dev/sda
А также сформировать правила, по которым udef будет формировать имя файла
устройства
при
его
появлении.
/etc/udev/rules.d/*.rules.
Пример правила udev:
Правила
описываются
в
файлах
BUS="usb", KERNEL="sd*", SYSFS{product}="Drive Key",
SYSFS{serial}="0212330F15006816", NAME="mykey"
В этом примере для usb-электронного ключа с серийным номером 0212330F15006816
создается
файл
устройства
/dev/mykey,
Параметры
SYSFS{product}
и
SYSFS{serial} можно узнать командой udevadm info -a.
Инструментальные средства для работы с разделами
На практике доступны и используются достаточно много средств (программ или утилит),
которые позволяют решать в большей или меньшей степени задачи по управлению
дисками. Утилиты можно оценивать по возможности:

создавать разделы на новом диске, не содержащем таблицы разделов;

создавать, удалять и/или изменять существующие разделы с сохранением
содержимого разделов — данных файловой системы.
Наиболее старым и известным является семейство утилит: fdisk, sfdisk, cfdisk. Эти
утилиты неспособны оперировать с содержимым раздела, не могут изменить размер
файловой системы, а лишь меняют запись в таблице разделов. Такая ситуация может
привести к потере данных файловой системы. Утилиты запускаются в командном режиме
и обладают большим набором опций.
fdisk — работает в интерактивном режиме, не использует расширенные возможности
терминала и спецсимволы.
cfdisk — представляет псевдографический интерфейс, удобен для новичка, но может
некорректно работать на некоторых терминалах.
sfdisk — предназначен для работы в пакетном режиме, без взаимодействия с
пользователем. Имеет возможность создать дамп разметки диска, и использовать его для
создания разметки на другом диске. Пример:
#sfdisk -d /dev/sda | sfdisk /dev/sdb
Использование команды fdisk для просмотра и изменения разделов диска:
В интерактивном режиме утилита может принимать следующие команды:
a
поиск пустых файлов
b
редактировать метки bsd диска
c
переключить флаг совместности с dos
d
удалить раздел
l
вывести список известных типов разделов
m
показать меню
n
добавить новый раздел
o
создать пустую таблицу разделов в стиле DOS
p
показать существующею таблицу разделов
q
выйти без сохранения изменений
s
создать новый раздел с меткой Sun
t
изменить метку типа раздела
u
изменить отображения/записи блоков
v
проверить таблицу разделов
w
сохранить изменения и выйти
x
дополнительные возможности (только для экспертов)
Для просмотра списка разделов без захода в интерактивный режим команды, можно
использовать ключ -l:
# /sbin/fdisk -l /dev/hda
Disk /dev/hda: 40.0 GB, 40020664320 bytes
16 heads, 63 sectors/track, 77545 cylinders
Units = cylinders of 1008 * 512 = 516096 bytes
Device Boot
/dev/hda1
swap
/dev/hda2
*
FAT32 (LBA)
/dev/hda3
/dev/hda4
Ext'd (LBA)
/dev/hda5
/dev/hda6
/dev/hda7
/dev/hda8
/dev/hda9
FAT32
Start
1
End
765
Blocks
385528
Id
82
System
Linux
766
4575
1919736
c
4575
4766
4766
77536
96390
36676395
83
f
Linux
W95
4766
6806
10886
27142
36896
6806
10886
27142
36896
77536
1028128+
2056288+
8193118+
4915858+
20482843+
83
83
83
83
b
Linux
Linux
Linux
Linux
W95
W95
В начале листинга в заголовок выведены обобщенные статусные характеристики
физического диска /dev/hda. Далее представлена детализированная схема разделов на
этом диске.
Видно, что на диске было создано три первичных раздела (/dev/hda1 /dev/hda2
/dev/hda3).
Раздел /dev/hda1 – используется в качестве своп-раздела Linux и содержит 385528
блоков.
Раздел /dev/hda2 – загрузочный раздел типа с - предназначен для поддержки файловой
системы FAT32.
Раздел /dev/hda3 – раздел для системы Linux.
Раздел /dev/hda4 – это расширенный раздел Windows.
Разделы /dev/hda5 - /dev/hda9 – это логические размеры.
По листингу легко проследить, в какой последовательности номеров цилиндров и в каком
объеме были созданы разделы. Следует обратить внимание, что логические разделы 5 - 9
содержатся в расширенном разделе.
Для решения задач преобразования существующих разделов были разработаны и
используются специализированные утилиты. Основной утилитой этого типа в Linux
является программа parted (или GNU/parted), название которой происходит от
PARTition Editor. Она предназначена для создания, удаления, копирования, изменения
размера и размещения разделов диска, а также для проверки целостности данных на
разделе. Утилита может работать как в пакетном, так и в интерактивном режиме, и
обладает простым и понятным набором команд:

команда print выводит таблицу разделов
(parted) print
Модель: ATA ST500LT012-9WS14 (scsi)
Диск /dev/sda: 500GB
Размер сектора (логич./физич.): 512B/4096B
Таблица разделов: msdos
Номер Начало Конец
Размер Тип
Файловая система
1
1049kB 211MB
210MB
primary
fat32
загрузочный, lba
2
211MB
4506MB 4295MB primary
ntfs
3
4508MB 498GB
494GB
extended

Флаги
lba
Команда mkpart создает раздел, не создавая новую файловую систему
(parted) mkpart part-type fs-type start-mb end-mb
o part-type определяет тип раздела: primary, extended или logical
o fs-type тип файловой системы: xt2, ext3, reiserfs, linux-swap
или FAT
o start-mb end-mb начало и конец раздела
Пример: (parted) mkpart primary ext3 0 200

Команда mkpartfs похожа на mkpart, но она не только создает раздел но и
форматирует его в указанный тип файловой системы.
Пример: (parted) mkpartfs primary ext3 201 300

Команда move перемещает раздел,
(parted) move minor-num start-mb end-mb
o minor-num
— младший номер файла устройсва раздела, который
требуется переместить

Команда resize изменяет размер раздела с start-mb на end-mb
(parted) resize minor-num start-mb end-mb

Команда rm удаляет раздел
(parted) rm minor-num
9.2. Назначение и основные концепции технологии LVM
Технология управления логическими томами LVM (Logical Volume Management) была
введена в классических UNIX системах, с целью облегчения процедур управления
файловыми системами с одновременным увеличением функциональности.
LVM обеспечивает общий пул пространства (pool space), состоящий из нескольких дисков
(известных в LVM как физические тома (Physical Volumes)), объединенных в группу
томов (Volume Group). Это пространство возможно разделить между логическими
томами (logical volume), представляющими собой LVM эквивалент для раздела. LVM
снимает ограничения, возникающие при применении подхода “использование диска
целиком“, делая возможным следующее:

создавать логические тома, размещенные на нескольких дисках;

создавать несколько логических томов на одном диске;

увеличивать и уменьшать размер логических томов при необходимости;

добавлять новые диски в дисковую группу, пополняя пул пространства;

переносить логические тома между физическими томами в пределах группы, не
отключая файловую систему, без остановки ввода-вывода приложений;

уменьшить размеры логических томоы и удалить диски из дисковой группы;

создавать внутренне согласованные резервные копии — снимки томов.
Физические тома (Physical Volumes)
LVM управляет физическими томами. Для этого на диске или разделе диска
предварительно создаются специальные структуры данных, необходимые для того, чтобы
его мог использовать LVM. После того, как эти структуры созданы, диск может
рассматриваться как физический диск, и может быть добавлен в группу томов.
Группа томов (Volume Groups)
Группа томов представляет собой группу из одного или нескольких физических томов.
Они образуют общий пул дискового пространства. Это пространство может быть
выделено под один или несколько логических томов.
Логические тома (Logical Volumes)
Дисковое пространство из группы томов выделяется одному или нескольким логическим
томам. Логический том является аналогом раздела и может содержать файловую систему,
своп-область или сырые данные приложения.
Логические тома могут:

содержать все пространство физического тома или любую его часть;

размещаться на нескольких физических томах в группе томов LVM;

изменяться в размерах или передвигаться при необходимости на другие диски в
данной группе томов.
Так же как для физических дисков и их разделов, для логических томов LVM создаются
специальные файлы устройств в каталоге /dev.
/dev/mapper/<Имя_группы_томов>-<Имя_логического_тома>
Например:
/dev/mapper/vg01-lvol1
И для обратной совместимости с классическими UNIX и первой реализации LVM в Linux:
/dev/<Имя_ргуппы_томов>/<Имя_логического_тома>
Например:
/dev/vg01/lvol1
В современных версиях linux оба этих файла являются ссылками на файл типа /dev/dm[номер] (например dm-1). Эти файлы обслуживаются подсистемой Device Mapper,
поверх которой сейчас в Linux реализован функционал LVM, а так же программных и
псевдо-аппаратных RAID и поддержки работы с дисками по нескольким аппаратным
путям.
Посмотреть информацию о них можно командой dmsetup(8)( параметры info, ls,
status и deps).
Минимально доступный квант (unit) пространства в LVM называется экстентом.
Физические тома разбиваются на физические экстенты (PE), которые доступны после
добавления физического тома к группе томов.
Логические тома состоят из серии последовательно нумерующихся логических
экстентов (LE). Каждый логический экстент является просто указателем на физический
экстент на диске. В большем логическом томе больше логических экстентов, а в меньшем
- меньше. Для увеличения размера логического тома достаточно добавить в него
дополнительные экстенты.
Размеры PE и LE одинаковы в пределах группы томов и задаются при ее создании. По
умолчанию, размер экстента равен 4 мегабайтам.
Рис. 9.4. Модель построения группы томов в LVM
На рисунке 9.4 показана конфигурация группы томов /dev/G1, которая содержит два
логических тома /dev/G1/L1 и /dev/G1/L2, составленных по определенным правилам
из PV трех физических дисков: /dev/hdа1 , /dev/hdb2 и /dev/sda. Размеры LE в
составе двух логических томов и размеры PE физических томов – одинаковые. На
логическом томе /dev/G1/L1 построена файловая система /home , а на логическом
томе /dev/G1/L2 – система /var.
Структуры данных LVM
LVM запоминает информацию в структурах данных, находящихся в начале физического
тома.
Physical Volume Reserved Area (PVRA) - зарезервированная область физического тома,
содержащая информацию LVM, специфичную для данного физического тома. Создается
командой pvcreate(8).
Volume Group Reserved Area (VGRA) - зарезервированная область группы томов,
содержит информацию LVM, специфичную для всей группы томов. Полная копия VGRA
может быть обнаружена на каждом из физических томов, входящих в группу томов. В
VGRA находится Volume Group Status Area (VGSA) - статусная область группы томов,
которая содержит информацию о кворуме в группе томов, и Volume Group Descriptor Area
(VGDA) - область описания группы томов, которая содержит информацию о дисках,
необходимую для конфигурирования группы томов для LVM. Область VGRA создается
командой vgcreate(8).
User Data Area (UDA) - область пользовательских данных содержит файловые системы,
виртуальную память (swap), или пользовательские приложения. При создании группы
томов область пользовательских данных делится на физические экстенты фиксированного
размера. Карта логических экстентов содержится в VGRA.
Создание новых физических томов PV и групп томов VG:
С помощью одной из утилит управления разделами диска (fdisk или parted)
необходимо создать новые разделы (например, /dev/sda2 и /dev/sda6) для LVM на
физическом диске. Идентификатор раздела в этом случает длжен быть установлен в
значение LVM: 0x8e
Командой pvcreate инициализировать раздел для использования в группе томов LVM.
# pvcreate /dev/sda2 /dev/sda6
При инициализации на разделах создается разметка под хранения метаданных группы
томов VGRA и о физическом томе PVRA.
Командой vgcreate создается группа томов с желаемым именем root_vg из исходных
физических томов (проинициализированных разделов для LVM):
# vgcreate root_vg /dev/sda2 /dev/sda6
Именно в этот момент пространства физического тома разбивается на экстенды и
заполняются структуры метаданных. Размер экстенда можно задать ключом -s.
Командами vgdisplay и pvdisplay посмотреть информацию о новой группе томов и
физических томах:
#vgdisplay –v root_vg
В листинге представлен суммарный размер двух физических томов, из которых
составлена новая группа томов с именем vg01. Можно оценить количество свободных и
занятых физических экстендов, список физических томов, включенных в группу, и список
логических томов, созданных в ней.
Создание новых логических томов в новой группе томов
Командой lvcreate создать новый логический том LV с желаемым именем (например,
data_lv) и необходимым размером (например, 10 Гб) в составе новой группы томов
root_vg:
#lvcreate –L 10G –n data_lv root_vg
Требуемый размер LV не должен превышать объема свободного пространства в группе
томов. Если указанный объем LV не кратен размеру LE, то он будет округлен до
ближайшего кратного числа в большую сторону. Можно явным образом указывать размер
логического тома в экстандах, используя ключ -l вместо ключа -L. Если размер не
указан, то создается том нулевого размера.
Команда lvdisplay выводит свойства логического тома:
#lvdisplay /dev/root_vg/data_lv
Создание и монтирование файловых систем на новом логическом томе
Создать на логическом диске файловую систему требуемого типа. Например, ext3:
#
#
#
mkfs -t ext3 /dev/root_vg/data_lv
mkdir /data
mount –t ext3 /dev/root_vg/data_lv
Для автоматического монтирования созданной файловой системы во время загрузки
необходимо внести строчку о логическом томе /dev/root_vg/data_lv в файл
/etc/fstab.
Расширение томов и файловых систем
При наличии свободного места в необходимой группе томов – просто выполнить команду
lvextend
#lvextend -L+2G /dev/root_vg/data_lv
Команда увеличивает размер тома на 2 гигабайта. Том не требует предварительного
размонтирования.
Расширить файловую систему внутри логического тома:
#resize2fs /dev/root_vg/data_lv
Файловую систему ext3 можно расширить без размонтирования. В случае других
файловых систем необходимо использовать их специфичные утилиты. Конечный размер
файловой системы можно не указывать, команда автоматически увеличит ФС на весь
доступный размер тома.
При отсутствии достаточного свободного места в группе томов следует добавить
дополнительные физические тома в группу:

Создать или использовать свободный раздел для создания в нем физического тома
LVM. Например, пусть это будет /dev/sda3. Установить его идентификатор равным
0x8e.

Подготовить диск /dev/sda3 к включению в группу:
# pvcreate /dev/sda3

Добавить новый физический том к существующей группе томов ( например, к
vol1):
# vgextend root_vg /dev/sda3

При необходимости сразу можно создавать и добавлять в группу томов сразу
несколько физических томов.
Теперь можно увеличить размер логического тома (в рассматриваемом случае это
логический том lv1):

Можно увеличить до желаемого размера например, до 20 Гб:
# lvextend –L 20G /dev/root_vg/data_lv

Можно увеличить текущий размер тома на указанную величину например, на 5 Гб
# lvextend –L +5G /dev/root_vg/data_lv

Можно указать процент свободного места в VG, которое необходимо использовать
для расширения тома
# lvextend -l +50%FREE /dev/root_vg/data_lv
Уменьшение размеров логических томов
Предварительно требуется размонтировать файловую систему на логическом томе.
Большинство файловых систем не производят уменьшение размера без остановки вводавывода.
#
umount
/dev/root_vg/data_lv
Уменьшение размера файловой системы. Например, уменьшить до 10 Гб:
#
resize2fs
/dev/root_vg/data_lv
10G
Теперь можно уменьшить размер логического тома data_lv:
#
lvreduce -L 10G /dev/root_vg/data_lv
Размер LV должен быть больше или равен размеру файловой системы
Удаление физических томов из группы томов
Освободить удаляемый физический том с помощью утилиты pvmove:

Получить карту распределения физических томов в группе, из которой нужно
удалить некий физический том:
# lvdisplay -m /dev/root_vg/data_lv
# pvdisplay -m /dev/sda6

Переместить данные с освобождаемого физического тома в предварительно
найденные свободные экстенты:
# pvmove /dev/sda6

Операция перемещения может быть достаточно длительной, и в группе должно
быть достаточное количество физических экстендов на других физических томах в
группе.
Помимо использования командного интерфейса пользователи имеют возможность
использовать и графический инструментарий LVM. Он зависит от дистибутива. Так в Red
Hat Enterprise Linux и Fedora было включено средство конфигурации LVM: systemconfig-lvm. На рисунке 9.5 представлен пример графического интерфейса с этой
утилитой.
Рис. 9.5. Графический интерфейс утилиты system-config-lvm
Эта утилита дает возможность администраторам получать информацию о системных
дисках и томах в графическом виде. На основе графического представления системной
памяти LVM в целом администраторы могут в удобной форме управлять этим
пространством через графический интерфейс:

отображать свойства и получать детализированную информацию о группах томов,
о физических томах и логических томах;

расширять и сокращать группы томов;

создавать новые логические тома, изменять размер логического тома;

удалять логические тома;

отображать схему преобразования физических экстентов в логические экстенты.
Дополнительные возможности LVM
В таблице представлены некоторые дополнительные команды для работы с томами в
LVM.
Утилита
Назначение
Управление размером
pvresize
Расширение/сокращение физических томов
pvremove
Уничтожение физических томов из группы томов
vgreduce
Удаление нераспределенных физических томов из группы томов
vgmerge
Объединение групп томов
vgsplit
Разбиение групп томов
Управление параметрами
vgchange
Изменение параметров и прав доступа к группе томов
lvchange
Изменения атрибутов логического том
pvchange
Изменения атрибутов физического том
Диагностика и поиск неисправностей
lvmdump
Сбрасывает дамп активной конфигурации
vgcfgbac
hup
Сделать резервную копию конфигурации группы томов
vgcfgres
tore
Восстановить конфигурации группы томов из резервной копии
vgck
Проверить целостность группы томов
Мониторинг производительности
lvmsadc
Сбор данных о активности томов ( по аналогии с утилитой sadc
lvmsar
Генерация отчетов об активности ( по аналогии с командой sar)
LVM содержит ряд возможностей для повышения доступности данных, защиты данных от
случайного повреждения и от поломки физического диска:

Механизм мгновенных снимков (Snapshots)

Механизм RAID
Механизм Snapshots
Позволяет выполнять резервное копирование логических томов с помощью мгновенных
снимков, получаемых в конкретный момент времени. При этом не требуется
останавливать ввод-вывод для получения резервной копии. Создается новый логический
том, содержащий те данные, которые были в исходном томе на момент создания снимка.
Для минимизации места при ведении снимков используется технология Copy-on-Write
(копирование при записи) – CoW. Логические экстенды снимка изначально указывают на
те же физические экстенды, которые использует исходный том. Собственно копирование
физических экстендов и изменения карты снимка, будет происходить только перед
непосредственным изменением их содержимого. Таким образом, снимок создается
моментально, без полного копирования, и занимает только то физическое место, которое
необходимо для хранения только тех данных, которые отличают снимок от оригинального
тома.
Создание мгновенных снимков
С помощью команды lvcreate с опцией -s можно создать снимок логического тома.
Используя ключ –L необходимо указать, какой объем пространства система должна
зарезервировать под снимок для последующего копирования туда данных.
#lvcreate -s –L 4G -n sn_data /dev/root_vg/data_lv
По сути размер 4G определяет, какой объем данных может измениться в исходном томе за
время существования снимка.
Если необходимо можно подключить файловую систему со снимка на отдельную точку
монтирования и скопировать от туда поврежденные на оригинальном диске файлы.
# mount /dev/root_vg/ sn_data /mnt/snap
Если снимок более не нужен, его можно размонтировать и удалить.
# lvremove /dev/root_vg/sn_data
Механизм RAID (Redundant Array of Independent Disks – избыточный
массив независимых дисков)
RAID – это один из методов объединения нескольких физических дисков для создания
одного логического диска с целью получить том большего размера и скорости или
защитить данные от потери при выходе из строя диска.
Программные RAID в Linux могут быть организованны либо средствами LVM, либо
утилитой mdadm.
В LVM RAID строится для каждого логического тома в отдельности. В пределах группы
томов могут одновременно присутствовать обычные (линейные) логические тома, тома с
чередованием (striping RAID0) и зеркалированные логические тома (RAID1). На данный
момент тома с уровнями RAID 10, 5 и 6 создавать невозможно.
Создание логического тома с чередованием
Первым делом, необходимо убедиться, что в группе присутствует как минимум два
физических тома и существует достаточное количество свободных экстендов на обоих
томах. Если места недостаточно, необходимо расширить группу.
Непосредственно для создания тома, выполнить команду:
#lvcreate -i 2 -I 8 -L 1G -n stripvol root_vg
В данном случае будет создан логический том с именем stripvol, размером 1 Гигабайт
с чередованием поперек двух физических дисков (ключ -i) с размером блока чередования
8 Килобайт (ключ -I)
Далее, используя команду lvdisplay с ключом -m, можно убедиться, что том создан и
размещен с нужной нам политикой.
#lvdisplay -m /dev/root_vg/stripvol
...........
Type
striped
Stripes
2
Stripe size
8 KB
............
Создание логического тома с зеркалированием
Для создания логического тома с зеркалированием в группе должно присутствовать
минимум два физических диски и объем свободного пространство на каждом из них
должен быть не меньше, чем объем создаваемого тома.
Кроме этого, LVM по умолчанию пытается создать журнал транзакция mirrorlog для
зеркалированного логического тома. Система может требовать хранить этот журнал на
третьем диске, неиспользуемом для хранения данных зеркалированного тома (-mirrolog
disk). Таким образом, для создания зеркала может понадобиться 3
физических тома в группе. Если мы не располагаем таким количеством диском, то можно
попросить систему хранить журнал в оперативной памяти, тогда в случае краха системы
журнал будет потерян (--mirrolog core), либо разрешить зеркалировать этот журнал
на те же физические тома, на которые зеркалируются данные нашего логического тома (-mirrolog mirror).
Если места в группе хватает, можно создавать том с зеркалом:
#lvcreate -m 1 -L1G --mirrolog core -n mirrvol root_vg
Ключом -m указывается количество зеркальных копий данных нашего тома. Ключ -mirrolog core указывает, что журнал зеркала будет размещен в оперативной памяти.
Командой lvdisplay с ключом -m можно убедиться, что зеркало создано.
#lvdisplay -m /dev/root_vg/stripvol
...........
Type
mirror
Stripes
2
............
Управление RAID устройствами командой mdadm
Программные RAID также можно создавать без использования LVM. Просто объединяя в
RAID разделы дисков или диски целиком. Для этого служит утилита mdadm.
Возможности этой утилиты при создании RAID гораздо шире, чем в LVM. mdadm может
создавать следующие типы RAID:

LINEAR — простое, линейное объединение ёмкости нескольких разделов, в один
большой раздел

RAID0 (striping) — распределение блоков на нескольких разделах дисков с
чередованием и без избыточности

RAID1 (mirroring) — зеркалирование запись одних и тех же данных одновременно
на два разных раздела на разных физических дисках

RAID4 — запись информации с избыточным данными (четностью) Для создания
требуется минимум три физических диска, один диск будет хранить четность, а на
двух других будут чередоваться данные.

RAID5 — тоже, что RAID4 (данные+ четность), но под хранения четности не
выделяется отдельный диск. Блоки с данными и четностью чередуются поперек
всех дисеков объединенных в RAID. Этот RAID дает лучшую производительность
чем RAID4, но в него сложней расширять.

RAID6 — похож на RAID5, но тут для данных считается две четности по разным
алгоритмам. Это дает возможность не потерять данные при одновременном выходе
из строя двух дисков. Для создания требуется минимум 4 диска.

MULTIPATH — В случае если к диску есть несколько аппаратных путей, Linux
для каждого из этих путей создаст свой собственный файл устройства диска.
Данная опция позволяет объединить эти разные имена в одно псевдо-дисковое
устройства.
Создание новых RAID устройств средствами mdadm:
1.
Первым делом необходимо правильно подготовить разделы дисков для
объединения их в RAID. Для этого утилитами типа fdisk, parted или им подобным, надо
установить идинтификатор раздела в значение fd «Linux raid auto»
2.
Для создания RAID, необходимо использовать ключ --create (или,
сокращенно, -С), указать файл устройства, с которым будет ассоциирован массив
(например, /dev/md0), ключем --auto разрешить системе создать этот файл, если его
не существует. Уровень raid задается ключем --level. Так же необходимо задать
количество устройств объединяемых в RAID (ключ --raid-devices) и перечислить
имена этих устройств. Пример создания массива с RAID 1:
# mdadm --create /dev/md1 --auto=yes \
> --level=raid1 --raid-devices=2 \
> /dev/sdb1 /dev/sdc1
3.
RAID создан, список существующих RAID, можно посмотреть в файле
/proc/mdstat
# cat /proc/mdstat
md1 :
active raidq sdc1[1] sbd1[0]
32000 blocks [2/2] [UU]
Тут видно тип RAID, его размер, диски, на которых он размещен, и состояния этих
дисков. Наиболее детальную информацию о RAID можно посмотреть, используя опцию -detail у команды mdstat
#mdstat --detail /dev/md1
4.
Дальше можно создатьи смонтировать файловую систему на устройстве
/dev/md1, так как раньше мы это делали на разделе диска.
#mkfs -f etx3 /dev/md1
#mount /dev/md1 /mnt/myfs
5.
В
настоящее
время
не
требуется
модификация
каких
либо
конфигурационных файлов для активации RAID устройств при загрузки Linux.
(информация о RAID пишется в специальный суперблок, и считывается при загрузки ОС)
Однако полезно (на случай сбоев) создать файл /etc/mdadm.conf. В котором можно
описать какие RAID на каких разделах у нас были созданы. Этот файл можно
сгенерировать автоматически с помощью команды
#mdadm --detail —scan -v >/dev/mdadm.conf
6.

Для удаления RAID необходимо
размонтировать файловую систему
#umount /mnt/myfs

остановить RAID
#mdadm --stop /dev/md1

очистить суперблок на разделах
mdadm --zero-superblock /dev/sdb1
mdadm --zero-superblock /dev/sdc1
9.3. Вопросы для самоконтроля
1. С какой целью и какими средствами можно управлять дисковым пространством?
2. Для чего предназначены файлы устройств? Каким образом файлы устройств могут
появиться в операционной системе? Как определить взаимосвязь между
физическим диском или его разделом и соответствующим файлом устройства?
3. Какие утилиты Linux могут использоваться для создания разделов на жестком
диске?
4. Какие преимущества дает использования менеджера томов LVM по сравнению с
классическим методом управления разделами?
5. Перечислите компоненты LVM и их свойства.
6. Какие операции допустимы по отношению к логическим томам в LVM?
7. Какие типы RAID возможно создать в Linux командой mdadm?
10. Список литературы
1. Операционная система UNIX: Принципы организации, идеалогия и архитектура,
пользовательский и программный интефрейсы. 2-е издание / А. М. Робачевский –
Издательство: БХВ-Петербург, 2010. – 667 с.
2. Unix и Linux. Руководство системного администратора. / Эви Немет, Гарт Снайдер,
Трент Р. Хейн, Бен Уэйли – Издательство: Вильямс, 2012. – 1312 с.
3. Командная строка Linux и сценарии оболочки. / Ричард Блум, Кристина Бреснахэн
– Издательство: Диалектика, 2013. – 784 с.
4. Linux. Необходимый код и команды. Карманный справочник. / Скотт Граннеман –
Издательство: Вильямс, 2010. – 416 с.
5. UNIX для студента. / Юрий Магда – Издательство: БХВ-Петербург, 2007. – 480 с.
Приложение 1. Примеры Shell-процедур
Язык shell операционной системы UNIX предоставляет программисту очень широкие
возможности и почти всегда позволяет решить любую задачу несколькими способами,
используя различные сочетания команд. Однако для начального ознакомления с
возможностями языка рекомендуется применять простейшие команды, рассмотренные
ранее в настоящем пособии.
Для каждой из процедур предлагается вариант выполнения с передачей ей через
параметры конкретных данных.
Все решения проверены в реальной операционной системе OS Linux в среде shell GNU bash
(версия 3.2.39).
Для лучшего понимания смысла процедур рекомендуется их пошаговое выполнение с анализом
промежуточных результатов выполнения каждой строки.
П1.1. Передача параметров в процедуру
Пример 1
Написать процедуру, выводящую на экран текущую дату и время, полное маршрутное имя
текущего
каталога,
полное
маршрутное
имя
домашнего
каталога
пользователя,
регистрационное имя пользователя, собственное имя процедуры.
Решение:
#proc1.1
#Вывод на экран
date
#Вывод на экран
pwd
#Вывод на экран
пользователя
echo $HOME
#Вывод на экран
who am i
#Вывод на экран
текущей даты и времени
полного маршрутного имени
текущего каталога
полного маршрутного имени
домашнего каталога
регистрационного имени
пользователя
собственного имени процедуры
echo $0
#Конец процедуры proc1.1
Пример выполнения процедуры proc1.1:
$proc1.1
/home/user1/posobie
/home/user1
user1
pts/1
proc1.1
2009-02-05 10:19
Пример 2
Написать процедуру, выводящую на экран все переданные процедуре параметры:
текущую дату и время, полное маршрутное имя текущего каталога, полное маршрутное
имя домашнего каталога пользователя, регистрационное имя пользователя, собственное
имя процедуры, количество переданных в процедуру параметров.
Решение. С помощью одной команды echo можно вывести на экран значения
позиционных параметров, передаваемых в процедуру при ее вызове. В качестве
параметров в процедуру передаются результаты выполнения соответствующих команд
UNIX.
#proc1.2
#Вывод на экран значений первого, второго, третьего и четвертого
позиционных параметров, переданных процедуре при обращении, а
также #нулевого параметра, содержащего имя выполняемой процедуры
echo $1 $2 $3 $4 $0
#Конец процедуры proc1.2
Пример выполнения процедуры proc1.2:
$proc1.2 `date` ` pwd` $HOME ` who am i`
/home/user1/posobie user1 pts/1 2007-02-05 proc1.2
П1.2. Работа с файлами
Пример 2.1
Написать процедуру, выводящую на экран содержимое файла, имя которого передается в
процедуру в качестве параметра.
Решение:
#proc2.1
#Вывод на экран cодержимого файла $1
cat $1
#Конец процедуры proc2.1
Пример выполнения процедуры proc2.1:
$proc2.1 file1.1
#
pwd
#
echo $HOME
#
who am i
#
echo $0
#Конец процедуры proc1.1
Пример 2.2
Написать процедуру, копирующую содержимое первого файла во второй файл. Имена
файлов передаются в процедуру в качестве параметров.
Решение:
#proc2.2
#Копирование содержимого файла $1
#в файл $2
cp $1 $2
#Конец процедуры proc2.2
Пример выполнения процедуры proc2.2:
$proc2.2 file1.1 file1.2
Пример 2.3
Написать процедуру, записывающую в некоторый файл текст, вводимый с клавиатуры
при работе процедуры. Имя файла передается в процедуру в качестве параметра. В конце
текста должна быть текущая дата.
Решение:
#proc2.3
echo Введите текст
read $TEMP1
echo $TEMP1 >$1
date >TEMP2
cat $1 TEMP2 >TEMP1
mv TEMP1 $1
#Конец процедуры proc2.3
Пример выполнения процедуры proc2.3:
$proc2.3 fff
Введите текст
this text is test <ENTER>
$cat fff
this text is test
Сбт Фев 24 17:10:36 MSK 2009
Пример 2.4
Написать процедуру, вводящую в начало файла_1 некоторый текст с клавиатуры, затем
присоединяющего содержимое файла_2, затем снова вводящего текст с клавиатуры в
конец файла_1. Имена файлов передаются в процедуру в качестве параметров.
Решение:
#proc2.4
cat - $1 >TEMP1
cat TEMP1 $2 >$1
#Конец процедуры proc2.4
Пример выполнения процедуры proc2.4:
$cat fff
$proc2.4 fff ffff
$cat ffff
Пример 2.5
Написать процедуру, меняющую взаимно содержимое двух файлов. Имена файлов
передаются в процедуру в качестве параметров.
Решение:
#proc2.5
cp $1 TEMP1
mv $1 $2
mv TEMP1 $2
#Конец процедуры proc2.5
Пример выполнения процедуры proc2.5:
$cat file1
111111111111111111111
$cat file2
222222222222222222222
$proc2.5 file1 file2
$cat file1
222222222222222222222
$cat file2
111111111111111111111
П1.3. Работа с символьными строками
Пример 3.1
Написать процедуру, вводящую в начало существующего файла_1 некоторый текст_1 с
клавиатуры,
затем
присоединяющую
к
нему
содержимое
файла_2,
затем
присоединяющую в конец файла_1 введенный с клавиатуры текст_2. Имена файлов
передаются в процедуру в качестве параметров.
Решение:
#proc3.1
#Ввод с клавиатуры текста_1 в промежуточный #файл file
cat >file
#Присоединение содержимого файла $2 к промежуточному
#файлу и запись результата в файл TEMP
cat file $1 $2 > TEMP
#Присоединение в конец файла $1 текста_2, введенного с
#клавиатуры
cat TEMP - >>$1
#Конец процедуры Proc3.1
Пример выполнения процедуры proc3.1:
$cat f1
111111111111
$cat f2
222222222222
$proc3.1 f1 f2
+++++++++ <ctrl+d>
----------------<ctrl+d>
$cat f1
+++++++++
111111111111
222222222222
---------------------$
Пример 3.2
2. Написать процедуру, находящую в файле, имя которого передается в качестве
параметра, все строки, содержащие вводимую с клавиатуры во время работы процедуры
последовательность символов.
Решение:
#proc3.2
#Ввод с клавиатуры заданной последовательности символов и
#запись ее в переменную A
read A
#Поиск в заданном файле всех строк, содержащих заданную
#последовательность
grep $A $1
#Конец процедуры Proc3.2
Пример выполнения процедуры proc3.2:
$cat f1
1234567890
0987654321
qwe456rtyu
asd34567fg
456456456
$proc3.2 f1
1234567890
qwe456rtyu
asd34567fg
456456456
Пример 3.3
Написать
процедуру,
помещающую
в
заданный
первым
параметром
файл
отсортированные по алфавиту строки с информацией о работающих в системе
пользователях.
Решение:
#proc3.3
who | sort > $1
#Конец процедуры Proc3.3
Пример выполнения процедуры proc3.3:
$proc3.3 testing
$cat testing
user1
:0
user1
pts/0
user1
pts/1
$
2007-02-25 15:57 (console)
2007-02-25 15:57
2007-02-25 16:06
Пример 3.4
Написать
процедуру,
распределяющую
строки
заданного
первым
параметром
символьного файла поровну между двумя другими файлами, имена которых передаются в
качестве второго и третьего параметров.
Решение:
#proc3.4
#Определение числа строк
wc –l $1 >TEMP
L1=`cut -f1 -d' ' TEMP`
#Определение числа строк
L2=`expr $L1 / 2`
#Определение числа строк
L3=`expr $L1 – $L2`
#Запись в файл $2 первой
head -$L2 $1 >$2
#Запись в файл $3 второй
tail -$L3 $1 >$3
#Конец процедуры Proc3.4
в исходном файле
в файле $2
в файле $3
половины файла $1
половины файла $1
Пример выполнения процедуры proc3.4:
$cat f1
1
2
3
4
5
6
$proc3.4 f1 f2 f3
$cat f2
1
2
3
$cat f3
4
5
6
$
П1.4. Вычисление арифметических выражений
Пример 4.1
Написать процедуру, вводящую с клавиатуры два целых числа и выводящую на экран их
сумму, произведение и частное от деления первого числа на второе.
Решение:
#proc4.1
#Ввод с клавиатуры двух целых чисел и присваивание их
#переменным A и B.
read A B
#Вычисление суммы введенных чисел и присваивание ее
#переменной SUM
SUM=`expr $A + $B`
#Вычисление произведения введенных чисел и присваивание
#результата переменной PROD
PROD=`expr $A \* $B`
#Вычисление частного от деления первого введенного числа на
#второе и присваивание результата переменной QUOT
QUOT =`expr $A \/ $B`
#Вывод на экран полученных результатов
echo Сумма введенных чисел равна
echo $SUM
echo Произведение введенных чисел равно
echo $PROD
echo Частное от деления первого числа на второе равно
echo $QUOT
#Конец процедуры Proc4.1
Пример выполнения процедуры proc4.1:
$proc4.1
4 5 <enter>
Сумма введенных чисел равна
9
Произведение введенных чисел равно
20
Частное от деления первого числа на второе равно
0
$
Пример 4.2
Написать процедуру, выводящую на экран время в минутах, остающееся до назначенного
срока от момента запуска процедуры на исполнение. Назначенный срок задается в виде:
номер дня в году (первый параметр), час (второй параметр ), минута (третий параметр).
Решение:
#proc4.2
#Сохранение в файле file текущей даты
date +%j%H%M >file
#Сохранение в переменной TEMP1 текущего дня
TEMP1=`cut -f1 file`
#Сохранение в переменной TEMP2 текущего часа
TEMP2=`cut -f1 file`
#Сохранение в переменной TEMP3 текущей минуты
TEMP3=`cut -f2 file`
#Сохранение в переменной TEMP4 оставшихся суток
TEMP4=`expr $1 - $TEMP1`
TEMP4=`expr $TEMP4 \* 60 \* 24`
#Сохранение в переменной TEMP5 оставшихся часов
TEMP5=`expr $2 - $TEMP2`
TEMP5=`expr $TEMP5 \* 24`
#Сохранение в переменной TEMP6 оставшихся минут
TEMP6=`expr $3 - $TEMP3`
#Вывод на экран результата
echo До назначенного срока остается
echo `expr $TEMP4 + $TEMP5 + $TEMP6` минут
#Конец процедуры Proc4.2
Пример выполнения процедуры proc4.2:
$proc4.2 2010 066 11 35
До назначенного срока остается
4293 минут
П1.5. Использование конвейеров
Пример 5.1
Написать процедуру, которая вставляет в заданный первым параметром файл вводимую
при работе процедуры новую строку после строки, номер которой задается вторым
параметром.
Решение:
#proc5.1
#Ввод новой строки и запись ее в переменную
#TEMP
read TEMP
#Запись в файл file первых $2 строк файла $1
head -$2 $1 >file1
#Запись в файл file2 содержимого TEMP
echo $TEMP > file2
#Присоединение в конец файла file1 новой строки из файла file2
cat file1 file2 >file3
#Определение общего числа строк в исходном файле $1
L1=`wc –l $1`
L1=`echo $L1 |cut -f1 -d" "`
#Определение числа строк во второй части файла $1
L2=`expr $L1 - $2`
#Запись в файл file2 второй части исходного файла
tail -$L2 $1 > file2
#Объединение первой и второй частей результирующего файла
cat file1 file2 >$1
#Конец процедуры Proc5.1
Пример выполнения процедуры proc5.1:
$cat filen
1111111111111111111
2222222222222
3333333333333333333
4444444444444444444
$proc5.1 filen 2
===================
$cat filen
1111111111111111111
2222222222222
====================
3333333333333333333
4444444444444444444
Пример 4.2
Написать процедуру, которая всем пользователям, работающим в данный момент в
системе, посылает сообщение из заданного первым параметром файла.
Решение:
#proc5.2
mail `who |cut -f1 -d” “` <$1
#Конец процедуры Proc5.2
Пример выполнения процедуры proc5.2:
$proc5.2 testing
$
П1.6. Ветвление в процедурах
Пример 6.1
Написать процедуру, которая выводит на экран постранично содержимое одного из двух
символьных файлов, имена которых передаются процедуре в качестве параметров.
Выбрать файл с меньшим числом строк (код завершения 000). Если заданные файлы
имеют одинаковое число строк, то вывести на экран cодержимое обоих файлов (код
завершения 111).
Решение:
#proc6.1
#Запись в переменную TEMP1 числа строк в файле $1
TEMP1=`wc –l $1 | cut -f1 -d “ “`
#Запись в переменную TEMP2 числа строк в файле $2
TEMP2=`wc –l $2 | cut -f1 -d “ “`
#Выбор файла с меньшим числом строк
if test $TEMP1 –lt $TEMP2
then
#Вывод на экран содержимого файла $1
more $1
#Выход из процедуры
exit 000
fi
if test $TEMP2 -lt $TEMP1
test
#Вывод на экран содержимого файла $2
more $2
#Выход из процедуры
exit 000
fi
#Проверка равенства числа строк в файлах $1 и $2
if test $TEMP1 –eq $TEMP2
test
#Вывод на экран содержимого файлов $1 и $2
more $1 $2
#Выход из процедуры
exit 111
fi
#Конец процедуры Proc6.1
Пример выполнения процедуры proc6.1:
$cat f1
11111111111111111111
22222222222222222222
33333333333333333333
44444444444444444444
$cat f2
11111111111111111111
22222222222222222222
$proc6.1 f1 f2
11111111111111111111
22222222222222222222
$
Пример 6.2
Написать процедуру, которая находит во всех подкаталогах заданного первым параметром
каталога обыкновенные файлы с односимвольными именами и изменяет имена найденных
файлов на соответствующие двухсимвольные, например имя f заменяется на ff и т. д. Если
найден хотя бы один такой файл, то процедура возвращает код завершения 0, в противном
случае — 1. Код завершения вывести на экран.
Решение:
#proc6.2
#Поиск во всех подкаталогах файлов с односимвольными
#именами
find –f -name ? $1
#Замена односимвольного имени на двухсимвольное
-exec mv {} {}{} \;
#Сохранение кода завершения в переменной TEMP
TEMP=$?
# Вывод на экран кода завершения
echo $TEMP
#Выход из процедуры
exit $TEMP
#Конец процедуры proc6.2
Пример выполнения процедуры proc6.2:
$ls ~/new
f ggg l s
$ls ~/new/new1
a bbb c dd
$proc6.2 ~/new
0
$ls ~/new
ff ggg ll ss
$ls ~/new/new1
aa bbb cc dd
Пример 6.3
Написать процедуру, которая:

для всех файлов текущего каталога, содержащих заданную первым параметром
подстроку, выводит на экран общее число таких строк в найденных файлах;

для всех файлов текущего каталога, содержащих заданную вторым параметром
подстроку, выводит на экран общее число символов в найденных строках;

для всех файлов текущего каталога, содержащих заданную третьим параметром
подстроку, выводит на экран общее число слов в найденных строках.
Вывести на экран сообщение о максимальном числе строк в указанных категориях.
Решение:
#proc6.3
#Поиск
строк, содержащих заданную подстроку $1
if grep -d skip -h $1 * > file1
then
#Подсчет общего числа найденных строк
TEMP1=`wc -l file1 | cut -f1 -d" "`
echo $TEMP1
rm file1
else
TEMP1=0
echo $TEMP1
fi
#Поиск
строк, содержащих заданную подстроку $2
if grep -d skip -h $2 * > file2
then
#Подсчет общего числа символов в найденных строках
TEMP22=`wc -c file2 | cut -f1 -d" "`
TEMP2=`wc -l file2 | cut -f1 -d" "`
echo $TEMP22
rm file2
else
TEMP22=0
echo $TEMP22
fi
#Поиск
строк, содержащих заданную подстроку $3
if grep -d skip -h $3 * > file3
then
#Подсчет общего числа слов в найденных строках
TEMP33=`wc -w file3 | cut -f1 -d" "`
TEMP3=`wc -l file3 | cut -f1 -d" "`
echo $TEMP33
rm file3
else
TEMP33=0
echo $TEMP33
fi
#Нахождение максимального числа строк
if test $TEMP1 -ge $TEMP2 -a $TEMP1 –ge $TEMP3
then
echo $1 $TEMP1
fi
if test $TEMP2 -ge $TEMP3 -a $TEMP2 -ge $TEMP1
then
echo $2 $TEMP2
fi
if test $TEMP3 -ge $TEMP1 -a $TEMP3 -ge $TEMP2
then
echo $3 $TEMP3
fi
#Конец процедуры Proc6.3
Пример выполнения процедуры proc6.3:
$cat f1
123 456 789
123 456 789
$cat f2
456 123 789
789 789 789
$cat f3
456 456 456
456 456 456
456 456 456
$proc6.3 567 123 456
0
36
18
456 6
$
П1.7. Циклы в процедурах
Пример 7.1
Написать процедуру, которая:

среди пользователей, работающих в данный момент времени в системе, находит
всех пользователей, имена которых содержатся во вводимой в процедуру
символьной строке;

выводит на экран найденные имена пользователей.
Решение:
#proc7.1
#формирование в файле file списка работающих пользователей
who >file
#Ввод заданных имен пользователей
echo “input string:”
read temp
# Присваивание позиционным параметрам заданных в строке
#имен пользователей
set $temp
# Поиск в файле file заданных имен и вывод их на экран
while [ “$1” ]
do
# Поиск в файле file очередного имени
grep $1 file
shift
done
# Конец процедуры proc7.1
Пример выполнения процедуры proc7.1:
$who
user2 tty2
2007-03-12 15:52
user3 tty3
2007-03-12 16:18
user1 :0
2007-03-12 10:43 (console)
user1 pts/0
2007-03-12 10:43
user1 pts/1
2007-03-12 10:50
$proc7.1
“input string:”
user2 user3
user2 tty2
2007-03-12 15:52
user3 tty3
2007-03-12 16:18
$
Пример 7.2
Написать процедуру, которая:

выполняет над вводимыми при работе процедуры целыми положительными
числами указанное первым параметром действие;

выводит на экран при вводе очередного числа результат выполнения указанного
действия;

заканчивает работу при вводе вместо очередного числа слова “stop”.
Решение:
#proc7.2 (вариант 1)
#Инициализация переменной result для сложения и вычитания
if [ $1 –eq “+” ] o [$1 –eq “-” ] then
result=0
fi
# Инициализация переменной result для умножения и деления
if [ $1 –eq “\*” ] o [ $1 –eq “\/” ] then
result=1
else
exit
fi
# Сохранение в переменной action кода заданного действия
action=$1
# Считывание очередного операнда
read TEMP
# Присвоение первому параметру процедуры очередного операнда
set $TEMP
# Цикл выполнения заданного действия
while true do
# Проверка конца ввода операндов
if [ “$1” = “stop” ] then
exit
fi
# Исключение деления на «0»
if [ $action =”/” ] a [ $1 –eq 0 ] then
exit
fi
# Выполнение заданного действия над очередным операндом
result=`expr $result $action $1`
shift
done
# Вывод на экран результата
echo “result=$result”
# Конец процедуры Proc7.2
Решение (вариант 2):
#proc7.2 (вариант 2)
#Ввод первого операнда
echo input first number
read result
#Сохранение операции
action=$1
while true
do
#Ввод второго и последующих операндов
echo input next number or "stop"
read TEMP
set $TEMP
if [ "$1" = "stop" ]
then
exit
fi
#Проверка деления на «0»
if [ $action = "\/" -a $1 = 0 ]
then
exit
fi
echo action $action
#Выполнение очередной операции и вывод результата
if [ $action = "\*" ]
then
result=`expr $result \* $1`
fi
if [ $action = "\/" ]
then
result=`expr $result \/ $1`
fi
if [ $action = "-" ]
then
result=`expr $result - $1`
fi
if [ $action = "+" ]
then
result=`expr $result + $1`
fi
echo "result=$result"
shift
done
#Конец процедуры 7.2
Пример выполнения процедуры proc7.2 (вариант 2):
$proc7.2 "\*"
input first number
25
input next number or stop
2
action \*
result=50
input next number or stop
3
action \*
result=150
input next number or stop
stop
$
Пример 7.3
Написать процедуру, которая:

определяет высоту поддерева каталогов, начиная от каталога, передаваемого в
качестве первого параметра;

выводит на экран полные маршрутные имена всех подкаталогов, являющихся
последними в полном маршрутном имени максимальной длины.
Решение:
#proc7.3
#Нахождение относительных маршрутных имен каталогов и
#сохранение их в файле
find $1 -depth >file
C1=`pwd`
H=0
for i in `cat file`
do
if [ -d $C1/$i ]
then
cd $C1/$i
h=0
C2=$C1/$i
#Определение высоты поддерева каталогов
while [ $C2 != $C1/$1 ]
do
cd ..
C2=`pwd`
h=`expr $h + 1`
done
if [ $H -lt $h ]
then
H=$h
fi
fi
done
echo subtree height is $H
#Нахождение и вывод на экран полных маршрутных имен
cd $C1
for i in `cat file`
do
if [ -d $C1/$i ]
then
cd $C1/$i
h=0
C2=$C1/$i
while [ $C2 != $C1/$1 ]
do
cd ..
C2=`pwd`
h=`expr $h + 1`
done
if [ $H -eq $h ]
then
echo "full routing name"
echo $C1/$i
fi
fi
done
cd $C1
# Конец процедуры Proc7.3
Пример выполнения процедуры proc7.3:
$ pwd
/home/user1
$ mkdir catalog1
$cd catalog1
каталогов
$ mkdir catalog11 catalog12
$ cd catalog11
$ mkdir catalog111 catalog112
$ cd ../..
$ proc7.4 catalog1
subtree height is 2
full routing name
/home/user1/catalog1/catalog11/catalog111
full routing name
/home/user1/catalog1/catalog11/catalog112
$
П1.8. Процедуры с использованием таймера
Пример 8.1
Написать процедуру, которая выполняет следующие действия:

читает содержимое первого файла, передаваемого в качестве первого параметра;

читает содержимое второго файла, передаваемого в качестве второго параметра;

если число строк в первом и втором файлах — различное, то выводит на экран
каждые 10 с попеременно, начиная с первой, строки из первого и второго файлов, а
затем – все оставшиеся строки большего из файлов;

если число строк в файлах одинаковое, то выводит на экран попеременно через
каждые 10 по одной строке, начиная с последней, строки из первого и второго
файлов.
Решение:
#proc8.1
l1=`wc -l $1 | cut -f1 -d" "`
l2=`wc -l $2 | cut -f1 -d" "`
# Сравнение числа строк в заданных файлах
if [ $l1 -ne $l2 ]
then
# Получение разности числа строк в первом и втором файлах
if [ $l1 -gt $l2 ]
then
l3=`expr $l1 - $l2`
flag=0
else
l3=`expr $l2 - $l1`
flag=1
fi
# Вывод на экран попеременно строк первого и второго файлов
#в прямом порядке
l4=1
while [ $l4 -le $l3 ]
do
# Вывод на экран очередной строки из первого файла
head -$l4 $1 >file
tail -1 file
#Пауза 10 с
sleep 10
# Вывод на экран очередной строки из второго файла
head -$l4 $2 >file
tail -1 file
#Пауза 10 с
sleep 10
l4=`expr $l4 + 1`
done
# Вывод на экран оставшихся строк первого или второго файла
if [ $flag -eq 0 ]
then
tail -`expr $l1 - $l4` $1
else
tail -`expr $l2 - $l4` $2
fi
else
l4=1
while [ $l4 -le $l1 ]
do
# Вывод на экран очередной строки из первого файла
tail -$l4 $1 >file
head -1 file
#Пауза 10 с
sleep 10
# Вывод на экран очередной строки из второго файла
tail -$l4 $2 >file
head -1 file
sleep 10
l4=`expr $l4 + 1`
done
fi
# Конец процедуры Proc8.1
Пример выполнения процедуры proc8.1:
$ cat > pp
111111
222222
333333
$ cat > tt
444444
555555
666666
$ proc8.1 pp tt
333333
666666
222222
555555
111111
444444
$
Пример 8.2
Написать бесконечную процедуру, которая периодически, каждые 15 с, опрашивает
систему и выводит на экран сведения о каждом вновь вошедшем в систему пользователе.
Решение:
#proc8.2
# Сохранение сведений о пользователях, работающих в системе
#в момент запуска процедуры на выполнение
who >file1
# Сохранение списка имен работающих пользователей
cut –f1 -d=” “ file1 >file3
# Бесконечный цикл
while true
do
# Пауза 15 с
sleep 15
# Сохранение сведений о работающих пользователях через 15с
who >file2
# Сохранение списка имен работающих пользователей
cut –f1 -d=“ “ file2 >file4
#Поиск каждого нового пользователя в списке старых пользователей
и вывод на экран #сведений о каждом вновь вошедшем в систему
пользователе
for newuser in file4
do
if grep $newuser file3 then
continue
else
grep $newuser file2
fi
done
# Обновление сведений о работающих
cp file4 file3
done
# Конец процедуры Proc8.2
пользователях
Пример выполнения процедуры proc8.2:
$ proc8.2
user3
tty2
$
2009-09-24-03-17 23:05
Download