Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Операционные системы. Учебное пособие (лабораторный практикум)

.pdf
Скачиваний:
0
Добавлен:
07.09.2026
Размер:
2 Мб
Скачать
☆
Если команде cat в качестве аргумента задать имя файла, это бу­дет означать, что содержимое файла будет направлено во входной поток, откуда его примет команда cat и выдаст в выходной поток.
Перенаправление ввода/вывода, каналы и фильтры. Хотя обычно ввод/вывод программы связаны со стандартными потоками, в оболочке существуют специальные средства для перенаправления ввода/вывода.
Операторы >, < и >>. Для обозначения перенаправления исполь­зуются символы ">", "<" и ">>". Чаще всего используется перена­правление вывода команды в файл. Вот соответствующий пример:
[user]$ ls -l > /home/jim/dir.txt
По этой команде в файле /home/jim/dir.txt будет сохранен пере­чень файлов и подкаталогов того каталога, который был текущим на момент выполнения команды ls; при этом если указанного файла не существовало, то он будет создан; если он существовал, то будет перезаписан; если же вы хотите, чтобы вывод команды был дописан в конец существующего файла, то надо вместо символа > использо­вать >>. При этом наличие пробелов до или после символов > или >> несущественно и служит только для удобства пользователя.
Вы можете направить вывод не только в файл, но и на вход дру­гой команды или на устройство (например, принтер). Так, для под­счета числа слов в файле /home/jim/report.txt можно использовать следующую команду:
[user]$ cat /home/jim/report.txt > wc -w
а для вывода файла на печать – команду:
[user]$ cat /home/jim/report.txt > lpr
Как видите, оператор > служит для перенаправления выходного потока. По отношению к входному потоку аналогичную функцию выполняет оператор <. Приведенный выше пример команды для под­счета числа слов в определенном файле можно переписать следую­щим образом (обратите внимание на отсутствие команды cat):
[user]$ wc -w < /home/jim/report.txt
Этот вариант перенаправления часто используется в различных скриптах, применительно к тем командам, которые обычно воспри­нимают ввод или ожидают ввода с клавиатуры. В скрипте же, авто­матизирующем какие-то рутинные операции, можно дать команде необходимую информацию из файла, в который заранее записано то, что нужно ввести для выполнения этой команды.
51
В силу того, что символы <, > и >> действуют на стандартные потоки, их можно использовать не только тем привычным образом, как это делается обычно, но и несколько по-другому. Так, следую­щие команды эквивалентны:
[user]$ cat > file
[user]$ cat>file
[user]$ >file cat
[user]$ > file cat
Однако сам по себе (без какой-либо команды, для которой опре- делены стандартные потоки) символ перенаправления не может ис­пользоваться, так что нельзя, например, введя в командной строке
[user]$ file1 > file2
получить копию какого-то файла. Но это не уменьшает значения данного механизма, ведь стандартные потоки определены для лю­бой команды. При этом перенаправить можно не только стандарт­ный ввод и вывод, но и другие потоки. Для этого надо указать перед символом перенаправления номер перенаправляемого потока. Стандартный ввод stdin имеет номер 0, стандартный вывод stdout – номер 1, стандартный поток сообщений об ошибках stderr – номер
2. То есть полный формат команды перенаправления имеет вид (напомним, что пробелы возле > не обязательны): command N > M, где N и M – номера стандартных потоков (0,1,2) или имена файлов. Употребление в некоторых случаях символов <, > и >> без указания номера канала или имени файла возможно только потому, что вме­сто отсутствующего номера по умолчанию подставляется 1, т. е. стандартный вывод. Так, оператор > без указания номера интерпре­тируется как 1 >.
Кроме простого перенаправления стандартных потоков суще­ствует еще возможность не просто перенаправить поток в тот или иной канал, а сделать копию содержимого стандартного потока. Для этого служит специальный символ &, который ставится перед номе­ром канала, на который перенаправляется поток: command N > &M.
Такая команда означает, что выход канала с номером N направ­ляется как на стандартный вывод, так и дублируется в канал с номе­ром M. Например, для того, чтобы сообщения об ошибках дублиро­вались на стандартный вывод, надо дать команду 2>&1, в то время как 1>&2 дублирует stdout в stderr. Такая возможность особенно по­лезна при перенаправлении вывода в файл, так как мы тогда одновре­менно и видим сообщения на экране, и сохраняем их в файле.
52
Особым вариантом перенаправления вывода является органи­зация программного канала (иногда называет трубопроводом или конвейером). Для этого две или несколько команд, таких, что вывод предыдущей служит вводом для следующей, соединяются (или раз­деляются, если вам это больше нравится) символом вертикальной черты – "|". При этом стандартный выходной поток команды, рас­положенной слева от символа |, направляется на стандартный ввод программы, расположенной справа от символа |. Например:
[user]$ cat myfile | grep Linux | wc -l
Эта строка означает, что вывод команды cat, т. е. текст из файла myfile, будет направлен на вход команды grep, которая выделит только строки, содержащие слово "Linux". Вывод команды grep бу­дет, в свою очередь, направлен на вход команды wc -l, которая под­считает число таких строк.
Программные каналы используются для того, чтобы скомбини­ровать несколько маленьких программ, каждая из которых выпол­няет только определенные преобразования над своим входным по­током, для создания обобщенной команды, результатом которой бу­дет какое-то более сложное преобразование.
Надо отметить, что оболочка одновременно вызывает на вы­полнение все команды, включенные в конвейер, запуская для каж­дой из команд отдельный экземпляр оболочки, так что как только первая программа начинает что-либо выдавать в свой выходной по­ток, следующая команда начинает его обрабатывать. Точно так же каждая следующая команда выполняет свою операцию, ожидая данных от предыдущей команды и выдавая свои результаты на вход последующей. Если вы хотите, чтобы какая-то команда полностью завершилась до начала выполнения последующей, вы можете ис­пользовать в одной строке как символ конвейера |, так и точку с за­пятой ;. Перед каждой точкой с запятой оболочка будет останавли­ваться и ожидать, пока завершится выполнение всех предыдущих команд, включенных в конвейер.
Статус выхода (логическое значение, возвращаемое после за­вершения работы программы) из канала совпадает со статусом вы­хода, возвращаемым последней командой конвейера. Перед первой командой конвейера можно поставить символ "!", тогда статус вы­хода из конвейера будет логическим отрицанием статуса выхода из последней команды. Оболочка ожидает завершения всех команд конвейера, прежде чем установить возвращаемое значение.
53
Фильтры. Последний из приведенных выше примеров (с ко­мандой grep) можно использовать для иллюстрации еще одного важного понятия, а именно, программы-фильтра. Фильтры – это ко­манды (или программы), которые воспринимают входной поток данных, производят над ним некоторые преобразования и выдают результат на стандартный вывод (откуда его можно перенаправить куда-то еще по желанию пользователя). К числу команд-фильтров относятся уже упоминавшиеся выше команды cat, more, less, wc,
cmp, diff, grep, fgrep, egrep, tr, comm, pr, sed.
Особым фильтром является команда tee, которая "раздваивает" входной поток, с одной стороны, направляя его на стандартный вы­вод, а с другой – в файл (имя которого вы должны задать).
Параметры и переменные. Окружение оболочки.
Понятие параметра в оболочке bash подобно понятию перемен­ной в обычных языках программирования. Именем (или идентифи­катором) параметра может быть слово, состоящее из алфавитных символов, цифр и знаков подчеркивания (только первый символ этого слова не может быть цифрой), а также число или один из сле­дующих специальных символов: *, @, #, ?, - (дефис), $, !, 0, _ (под­черкивание).
Говорят, что параметр задан или установлен, если ему присво­ено значение. Значением может быть и пустая строка. Чтобы выве­сти значение параметра, используют символ $ перед его именем. Так, команда
[user]$ echo name выдаст на экран слово name, а команда
[user]$ echo $name
выдаст значение переменной name (если таковое, конечно, задано).
Параметры разделяются на три класса: позиционные пара­метры, специальные параметры и переменные оболочки.
Имена (идентификаторы) позиционных параметров состоят из одной или более цифр (только не из одиночного нуля). Значениями позиционных параметров являются аргументы, которые были за­даны при запуске оболочки (первый аргумент является значением позиционного параметра 1 и т. д.). Изменить значение позицион­ного параметра можно с помощью встроенной команды set. Значе­ния этих параметров изменяются также на время выполнения обо­лочкой одной из функций.
54
Специальные параметры являются шаблонами, замена (подста­новка) которых производится следующим образом:
* ‒ заменяется позиционными параметрами, начиная с первого. Если замена производится внутри двойных кавычек, то этот пара­метр заменяется на одно единственное слово, составленное из всех позиционных параметров, разделенных первым символом специ­альной переменной IFS (о ней будет сказано ниже). То есть ``$*'' эквивалентно ``$1c$2c...'', где c – первый символ в значении пере­менной IFS. Если IFS присвоено пустое значение или ее значение не установлено, параметры разделяются пробелами;
@ ‒ заменяется позиционными параметрами, начиная с пер­вого. Если замена производится внутри двойных кавычек, то каж­дый параметр заменяется отдельным словом. Так, `` $@'' эквива­лентно ''$1'' ''$2''... Если позиционных параметров нет, то значение не присваивается (параметр @ просто удаляется);
# ‒ заменяется десятичным значением числа позиционных па­раметров;
? ‒ заменяется статусом выхода последнего из выполнявшихся на переднем плане программных каналов;
- (дефис) ‒ заменяется текущим набором значений флагов,
установленных с помощью встроенной команды set или при запуске самой оболочки;
$ ‒ заменяется идентификатором процесса (PID) оболочки;
! ‒ заменяется идентификатором процесса (PID) последней из выполняющихся фоновых (асинхронно выполнявшихся) команд;
0 ‒ заменяется именем оболочки или запускаемого скрипта.
Если bash запускается для выполнения командного файла, $0 равно имени этого файла. В противном случае это значение равно пол­ному пути к оболочке;
_ (подчеркивание) ‒ заменяется последним аргументом преды­дущей из выполнявшихся команд (если это параметр или перемен­ная, то подставляется ее значение).
Переменная с точки зрения оболочки – это параметр, обознача­емый именем. Значения переменным присваиваются с помощью оператора следующего вида
[user]$ name=value
где name – имя переменной, а value – присваиваемое ей значение (может быть пустой строкой). Имя переменой может состоять
55
только из цифр и букв и не может начинаться с цифры. Значением может быть любой текст. Если значение содержит специальные символы, то его надо взять в кавычки. Присвоенное значение этих кавычек не содержит, естественно. Если переменная задана, то ее можно удалить, используя встроенную команду оболочки unset.
Набор всех установленных переменных оболочки с присвоен­ными им значениями называется окружением (environment) или средой оболочки. Вы можете просмотреть его с помощью команды set без параметров (только, может быть, следует организовать кон­вейер «set | less»). В выводе этой команды все переменные окруже­ния перечисляются в алфавитном порядке. Для того чтобы просмот­реть значение одной конкретной переменной можно воспользо­ваться командой
[user]$ echo $name
Среди переменных, которые вы увидите в выводе команды set, встречаются очень интересные переменные. Обратите, например, внимание на переменную RANDOM. Если вы несколько раз подряд выполните команду
[user]$ echo $RANDOM
вы каждый раз будете получать новое значение. Дело в том, что эта переменная возвращает случайное целое из интервала 0 – 32 768.
Приглашения оболочки. Одна из очень важных переменных имеет имя PS1. Эта переменная задает вид приглашения, которое bash выводит, когда ожидает ввода очередной команды пользовате­лем. По умолчанию этой переменной присвоено значение "\s-\v\$ ". Вообще-то в bash существует четыре приглашения, которые ис­пользуются в разных ситуациях. Переменная PS1 задает вид строки приглашения, которая выдается тогда, когда оболочка ждет ввода команды. Вторичное приглашение, задаваемое переменной PS2, по­является тогда, когда оболочка ожидает от пользователя ввода еще каких-то данных, необходимых для продолжения работы запущен­ной команды или программы. По умолчанию переменная PS2 имеет значение ">". Вы уже имели возможность видеть это приглашение, когда запускали команду cat для ввода данных с клавиатуры в файл. Другой пример – команда ftp, после запуска которой приглашение тоже принимает такой вид.
Приглашение, задаваемое переменной PS3, используется в ко­манде select. Приглашение, задаваемое переменной PS4, выводится
56
перед каждой командой, в то время, когда bash отслеживает процесс выполнения. Значение по умолчанию – "+".
Вы можете изменить вид переменных PS1 и PS2. При этом можно использовать как любые символы, вводимые с клавиатуры, так и некоторое число специальных символов, которые при форми­ровании строки приглашения декодируются в соответствии с ниже:
\a ‒ звуковой сигнал (ASCII-код 07);
\d ‒ дата в формате "День, месяц, число", например, Ср, Окт, 17;
\h ‒ имя хоста (hostname) до первой точки;
\H ‒ полное имя хоста;
\t ‒ текущее время в 24-часовом формате: HH:MM:SS (часы:ми- нуты:секунды);
\T ‒ текущее время в 12-часовом формате: HH:MM:SS;
\@ ‒ текущее время в 12-часовом формате am/pm;
\u ‒ имя пользователя, запустившего оболочку;
\w ‒ полное имя текущего рабочего каталога (начиная с корня);
\W ‒ текущий рабочий каталог (без указания пути);
\$ ‒ символ #, если оболочка запущена суперпользователем, и символ $, если оболочка запущена обычным пользователем;
\nnn ‒ символ, имеющий восьмеричный код nnn;
\n ‒ новая строка (перевод строки);
\s ‒ имя оболочки;
\# ‒ текущий номер команды;
\\ ‒ обратный слэш (a backslash);
\[ ‒ начало последовательности не печатаемых символов (этот
символ может быть использован для того, чтобы включить в текст подсказки последовательность управляющих символов терминала);
\] ‒ конец последовательности не печатаемых символов;
\! ‒ порядковый номер данной команды в истории команд.
Текущий номер команды (порядковый номер выполняемой ко­манды в рамках текущей сессии) может отличаться от номера данной команды в списке истории команд, поскольку последний включает в себя команды, которые были сохранены в файле истории команд.
После того, как значение переменной, определяющей под­сказку, прочитано оболочкой, в нем могут быть произведены под­становки в соответствии с правилами расширения параметров, под­становок в именах команд и арифметических выражениях, а также разбиения слов (word splitting).
57
Например, после выполнения команды (поскольку в строке имеется пробел, кавычки обязательны)
[root]# PS1="[\u@\h \W]\$"
в стандартном приглашении будет выводиться квадратная скобка, имя пользователя, символ @, имя компьютера, пробел, название те­кущего каталога (без указания пути), закрывающая квадратная скобка и символ $ (если в оболочке работает простой пользователь) или # (если оболочка запущена от имени пользователя root).
Переменная PATH. Еще одна очень важная переменная имеет имя PATH. Она задает перечень путей к каталогам, в которых bash осуществляет поиск файлов (в частности, файлов с командами) в тех случаях, когда полный путь к файлу не задан в командной строке. Отдельные каталоги в этом перечне разделяются двоеточи­ями. По умолчанию переменная PATH включает каталоги
/usr/local/bin, /bin, /usr/bin, /usr/X11R6/bin, т. е. имеет вид:
/usr/local/bin:/bin:/usr/bin:/usr/X11R6/bin:
Для того чтобы добавить каталог в этот список, нужно выпол­нить следующую команду:
[root]# PATH=$PATH:new_path.
При осуществлении поиска оболочка просматривает каталоги именно в том порядке, как они перечислены в переменной PATH.
Переменная IFS. Эта переменная задает разделители полей (Internal Field Separator), которые используются при операции раз­деления слов при преобразованиях командной строки, выполняе­мых оболочкой перед тем, как запустить командную строку на ис­полнение. Значение этой переменной по умолчанию – "<Про­бел><Tab><Символ_новой_строки>".
Текущий и домашний каталоги. Имя текущего каталога сохра- няется в переменной окружения (с именем PWD), и значение этой переменной изменяется при каждом запуске программы cd.
Аналогичным образом полное имя (с указанием пути) домаш­него каталога пользователя, запустившего данный процесс, сохра­няется в переменной HOME.
Команда export. Когда оболочка запускает на выполнение ка­кую-то программу или команду, она передает им часть переменных окружения. Для того, чтобы переменная окружения передавалась запускаемому из оболочки процессу, ее нужно задавать с помощью специальной команды export, т. е. вместо
[user]$ name=value
58
надо записать
[user]$ export name=value
В таком случае все запускаемые из оболочки программы (в том числе вторичные экземпляры самой оболочки) будут иметь доступ к заданным таким образом переменным, т. е. могут вызывать их зна­чения по именам.
Раскрытие выражений (expansion). Когда оболочка получает какую-то командную строку на выполнение, она до начала выпол­нения команды осуществляет «грамматический разбор» получен­ной командной строки. Одним из этапов такого «разбора» является раскрытие или подстановка выражений (expansion). В bash имеется семь типов подстановки выражений: раскрытие скобок (brace expansion); замена знака тильды (tilde expansion); подстановка пара­метров и переменных; подстановка команд; арифметические под­становки (выполняемые слева направо); разделение слов (word
splitting); раскрытие шаблонов имен файлов и каталогов (pathname expansion).
Все эти операции выполняются именно в том порядке, как они здесь перечислены. Рассмотрим их последовательно.
Раскрытие скобок. Раскрытие скобок проще всего пояснить на примере. Предположим, что нам нужно создать сразу несколько подкаталогов в каком-то каталоге, или поменять владельца сразу у нескольких файлов. Эти действия можно выполнить с помощью следующих команд:
[user]$ mkdir /usr/local/src/bash/{old,new,dist,bugs}
[root]# chown root /usr/{ucb/{ex,edit},lib/{ex?.?*,how_ex}}
В первом случае в каталоге /usr/local/src/bash/ будут созданы подкаталоги old, new, dist и bugs. Во втором случае владелец будет изменен у файлов: /usr/ucb/ex, /usr/lib/ex?.?*, /usr/ucb/edit,
/usr/lib/ex?.?*, /usr/ucb/ex, /usr/lib/how_ex, /usr/ucb/edit, /usr/lib/how_ex.
То есть для каждой пары скобок генерируются несколько отдель­ных строк (их число равно числу слов, стоящих внутри скобок) путем приписывания к каждому слову из скобок (спереди) того, что стоит пе­ред скобкой, и приписывания в конец каждого полученного слова того, что стоит после скобки. Еще один пример: строка a{d,c,b}e при рас­крытии скобок превращается в три слова "ade ace abe".
Раскрытие скобок выполняется до выполнения других видов подстановок в командной строке, причем все специальные сим-
59
волы, встречающиеся в командной строке, в том числе внутри ско­бок, сохраняются неизменными (они будут интерпретированы на следующих этапах анализа строки).
Замена тильды (Tilde Expansion). Если слово начинается с сим­вола тильды ('~'), все символы до первого слэша (или все символы, если слэша нет) трактуются как имя пользователя (login name). Если это имя есть пустая строка (т. е. вслед за тильдой идет сразу слэш), то тильда заменяется на значение переменной HOME. Если значе­ние переменной HOME не задано, тильда заменяется на полный путь к домашнему каталогу пользователя, запустившего оболочку. Если вслед за знаком тильды (до слэша) стоит слово, совпадающее с именем одного из легальных пользователей, тильда и имя пользо­вателя заменяются полным именем домашнего каталога этого поль­зователя. Если слово, следующее за тильдой, не является именем пользователя (и не пусто), то оно остается неизменным.
Если вслед за знаком тильды стоит ‘+’, эти два знака заменя­ются на полное имя текущего каталога (т. е. значение переменной PWD). Если за знаком тильды следует ‘-‘, подставляется значение переменой OLDPWD.
Подстановка параметров и переменных. Символ $ использу­ется для обозначения операций подстановки параметров, подста­новки команд и подстановок арифметических выражений. Выраже­ние или имя, следующее за $, может быть заключено в скобки; что не обязательно, но удобно, так как позволяет отделить заменяемое выражение от следующих за ним слов или символов. Таким обра­зом, чтобы в командной строке вызвать значение параметра (в част­ности, любой переменной), нужно вставить выражение вида
${parameter}.
Скобки необходимы только в том случае, если имя параметра состоит из нескольких цифр, или когда за именем следует символ, который не должен интерпретироваться как часть имени.
Все значения переменных подвергаются подстановке знака тильды, раскрытию параметров и переменных, подстановке команд, подстановкам арифметических выражений, а также удалению спе­циальных символов цитирования (см. ниже). Разделение слов не производится, за исключением случая "$@". Раскрытие шаблонов имен файлов и каталогов не производится.
60