Наши партнеры








Книги по Linux (с отзывами читателей)

Библиотека сайта rus-linux.net

Массивы

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

Значения элементам массива присваиваются по одному с использованием оператора присваивания. Например,

$ planets[l]=Mercury

$ planets[2]=Venus

$ planets[3]"Earth

$ print ${planets[2]}

Venus

Для ссылки на элементы массива оболочкой Кот поддерживается общий синтаксис имя[индекс}. В качестве индекса могут использоваться целые числа от 0 до 511 или переменные со значением требуемого номера элемента. Номера элементов начинаются с нуля. Таким образом, первый элемент в массиве - ${name[0]}.

Для инициализации нескольких элементов массива одним оператором можно использовать опцию -А команды set. Например, предшествующий код можно было бы переписать следующим образом:

$ set -A palnets Mercury Venus Earth

$ print ${planets[2]} Venus

Можно также подставить в выражение значения всех элементов массива, используя специальную запись ${пате[*]} или ${name[@]}. Например,

$ set -A palnets Mercury Venus Earth

$ set planets[9]=Pluto

$ set planets[7]=Uranus

$ print The known planets are: ${planets[*]}

The known planets are: Mercury Venus Earth Uranus Pluto

При использовании массивов следует помнить о нескольких моментах:

  • При ссылке на имя массива без индекса, значением ссылки является первый элемент массива:

$ print $planets Mercury

  • Массивы не могут экспортироваться.

  • Специальное выражение ${#name[*]} или ${#пате[@]} может использоваться для получения количества ненулевых элементов массива. Например,

  • $ print There are ${#planets[*]} planets: ${planets [*]}

There are 5 planets: Mercury Venus Earth Uranus Pluto

  • Для ссылки на элементы массива необходимо использовать квадратные скобки. Без квадратных скобок оболочка Коrn интерпретирует выражение так же, как это делала бы оболочка Bourne. Например,

$ print The known planets are $planets[*]

The known planets are

$ print The second planet from the Sun is $planets[2]

The second planet from the Sun is Mercury [2]

Арифметические операции с переменными

Впечатляющее дополнение к возможностям оболочки Bourne, обеспечиваемое оболочкой Коrn, - возможность выполнения арифметических операций. Оболочка Bourne не имеет никаких встроенных возможностей вычисления, поэтому выполнение даже простейших арифметических действий требует подстановок команд, которые прибегают к вызову других программ UNIX, например, ехрr. Оболочка Коrn предоставляет некоторые встроенные возможности для выполнения основных арифметических операций.

Два основных инструментальных средства, которые придется использовать при выполнении арифметических операций в среде оболочки Коrn, - команды typeset и let. Команда typeset позволяет форматировать числа, а также определять переменные специально для выполнения арифметических операций. Команда let непосредственно выполняет арифметические операции.

Использование команды typeset

Оболочка Коrn все же является очень медленным инструментальным средством для выполнения повторяющихся вычислений, даже при использовании оператора typeset. Вычисления с плавающей точкой - действительные числа с десятичной точкой, дроби и т.п. - не поддерживаются. Таким образом, во всех вычислениях должны использоваться целые значения, которые будут давать результаты целого типа. Однако арифметических операций, выполняемых в среде оболочки, достаточно для поддержки таких концепций программирования, как управление циклами посредством счетчиков.

Оператор typeset - расширение, предоставляемое оболочкой Коrn для управления форматом и использованием переменных оболочки. Когда оператор typeset используется для управления переменными, его синтаксис следующий:

typeset [ бHLRZilrtux [n] ] [ name{=value} ] ...

Конкретный набор опций, используемых с командой, определяет требуемый формат ее синтаксиса. Не все комбинации опций допустимы. Следует указывать только те опции, что приведены в табл. 11.12.

Таблица 11.12. Опции команды typeset.

  • -Н Опция -Н поддерживается только теми версиями оболочки Коrn, которые выполняются в операционных системах, отличных от UNIX. При указании опции -Н каждая из переменных name считается содержащей имя файла или пути. Присваивание значения переменной приводит к преобразованию значения в формат имен файлов, совместимый с используемой операционной системой. Затем можно использовать переменную в качестве аргумента (имени файла) в последующих командах. С помощью этой опции необходимо указывать один или более аргументов name. Опция -Н игнорируется в операционных системах UNIX.

  • -i Эта опция определяет переменную целого типа. Для указания численного основания, в которое значение должно быть преобразовано при подстановке, необходимо использовать опцию n. Числа всегда передаются с основанием 10, и только десятичные числа должны присваиваться переменным. Однако при подстановке значение переменной преобразуется в эквивалентную строку восьмеричных чисел. Можно также указывать опции -L, -LZ, -R или RZ для именованных переменных.

  • -I Значение именованных переменных при подстановке должно преобразовываться 5 строчные буквы. Не следует указывать эту опцию совместно с опцией -u. Необходимо указывать по меньшей мере один аргумент name, одновременно можно присвоить нескольким или всем именованным переменным начальные значения.

  • -L Значения именованных переменных должны выравниваться по левому краю и дополняться пробелами до правого края, определяемого длиной л при подстановке. Например, -L4 при подстановке раскрывает значение переменной четырьмя символами. Необходимо указывать по меньшей мере один аргумент name, и нескольким или всем именованным переменным можно присваивать начальные значения.

  • -LZ Эта опция аналогична опции -L, но перед подстановкой она убирает из значения переменной любые начальные нули.

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

  • -R Значение именованной переменной (переменных) при подстановке должно выравниваться по правому краю и дополняться пробелами до левого края. определяемого длиной n. Например, при подстановке опция -R4 раскрывает значение переменной четырьмя символами. Необходимо указывать по меньшей мере один аргумент name, и нескольким или всем именованным переменным можно присваивать начальные значения. С опцией -R нельзя указывать опции -L или -LZ.

  • -RZ Эта опция аналогична опции -R, но она дополняет значение слева нулями. Если значение именованной переменной содержит только цифры, результатом является числовое поле длиной n.

  • -u При подстановке значение именованной переменной (переменных) должно быть переведено в верхний регистр. Эту опцию нельзя указывать с опцией -I. Обязательно указание по меньшей мере одного аргумента name, одновременно нескольким или всем именованным переменным можно присваивать начальные значения.

  • -х Именованные переменные должны быть экспортированы для использования в сценариях оболочки и в субоболочках. Обратите внимание, что typeset - единственная команда, предоставляемая оболочкой Коrn для экспорта переменных. Псевдоним команды, именуемый export, используется при запуске оболочки, что эквивалентно команде typeset -х. В отличие от оператора export оболочки Bourne, который допускает только имена переменных, оболочка Коrn (посредством использования псевдонимов команд) поддерживает выражение export name=value ..., обеспечивая начальное значение для каждой из экспортированных переменных. Если переменная уже существует на момент ввода команды typeset -х, оболочка добавляет к переменной атрибут export. Если определяется новая переменная, но при этом никакое значение value не указывается, переменная инициализируется нулевой строкой и помечается как экспортируемая.

  • -Z Эта опция идентична опции -RZ.

Кроме экспорта переменных (обычно посредством псевдонима export), команда typeset используется в основном в двух целях:

р для определения переменных, которые планируется использовать для вычислений в качестве целых переменных;

р для задания специальных опций форматирования переменных.

Хотя оболочка Коrn не требует, чтобы переменная объявлялась целой для выполнения с ней арифметических операций, это дает определенные преимущества. Вычисления более эффективны при использовании в операторе let арифметических переменных, поскольку оболочка может поддерживать численное значение переменной во внутреннем двоичном формате, который гораздо больше соответствует математическим инструкциям компьютера. Аналогично, в ряде случаев оболочка распознает арифметические операции в выражении, если оно содержит целые переменные, но не в состоянии сделать это, если используются стандартные переменные.

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

typeset -i х у sum read х у let sum=x+y print $sum

Оболочка Коrn автоматически определяет псевдоним, названный integer, который является эквивалентом команды typeset -i:

alias integer=typeset -i"

Псевдоним можно использовать для обеспечения лучшей читабельности определений, как в следующем варианте:

integer х у sum

read x у

let sum=x+y

print $sum

Второе применение команды typeset - установка опций форматирования для переменных - представляет интерес прежде всего для разработчиков сценариев оболочки, желающих аккуратно сформатировать вывод. Опции форматирования -L, -R, -LZ и -RZ находят определенное применение также при создании имен файлов. Предположим, что нужно создать ряд файлов, имена которых заканчиваются четырехзначным номером. Записав оператор typeset

typeset -Z4 suffix

можно легко создавать требуемые имена файлов, используя программный код, подобный следующему:

typeset -Z4 suffix=0

while . ..

do

let suffix=suffix+1

print sampfile.$suffix

done

Оболочка Коrn автоматически выравнивает значение переменной Ssuffix по правому краю четырехсимвольного поля и дополняет номер до четырех цифр нулями. Таким образом, оболочка создает последовательность имен файлов sampfile.0001, sampnle.0002 и т.д.

Использование команды let

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

let expr

expr - это выражение, состоящее из членов и операций. Член - это переменная или целая численная константа, например 3 или 512. Предполагается, что целая численная константа, записывается в десятичном формате. Используя формат основание#показатель, где основание - основание системы счисления, а показатель ~ значение показателя степени. Для оснований, превышающих 10, используются цифры 0-9 и буквы A-Z. Например, для основания 16 (шестнадцатеричный формат) используются цифры 0-9 и буквы A-F.

В табл. 11.13 показаны арифметические операции, поддерживаемые оболочкой Когп для использования в арифметических выражениях.

Таблица 11.13. Арифметические операции в оболочке Коrn.

  • - -ехр Унарный минус - изменение знака выражения ехр на противоположный

  • ! !ехр 0, если ехр не равно нулю; в противном случае - 1

  • ~ - ехр Дополнение к ехр

  • * ехр1 * ехр2 Произведение ехр1 и ехр2

  • / ехр1 / ехр2 Частное от деления ехр1 на ехр2

  • % ехр1 % ехр2 Остаток отделения ехр1 на ехр2

  • + ехр1 + ехр2 Сумма ехр1 и ехр2

  • - ехр1 - ехр2 Разность ехр2 и ехр1

  • << ехр1 р ехр2 Сдвиг ехр1 на ехр2 бит влево

  • >> ехр1 р ехр2 Сдвиг ехр 1 на ехр2 бит вправо

  • <= ехр1 <= ехр2 1, если ехр1 меньше или равно ехр2; в противном случае - 0

  • >= ехр1 >= ехр2 1, если ехр1 больше или равно ехр2: в противном случае - 0

  • < ехр1 < ехр2 1, если ехр1 меньше ехр2; в противном случае - 0

  • > ехр 1 > ехр2 1, если ехр1 больше ехр2; в противном случае - 0

  • == ехр1 == ехр2 1, если ехр1 равно ехр2; в противном случае - 0

  • != ехр1 != ехр2 1, если ехр1 не равно ехр2; в противном случае - 0

  • & ехр1 & ехр2 Побитовое И ехр1 и ехр2

  • ^ ехр1^ ехр2 Исключающее ИЛИ ехр 1 и ехр2

  • | ехр1 | ехр2 Побитовое ИЛИ ехр1 и ехр2

  • && ехр1 && ехр2 1, если ехр1 не равно нулю и ехр2 не равно нулю; в противном случае - 0

  • || ехр1 || ехр2 1, если ехр1 не равно нулю или ехр2 не равно нулю; в противном случае - 0

  • = var = exp Присваивает значение ехр идентификатору переменной

  • += var += ехр Добавляет значение ехр к идентификатору переменной

  • -= var -= ехр Вычитает значение ехр из идентификатора переменной

  • *= var *= ехр Умножает var на ехр

  • /= var /= ехр Делит var на ехр

  • %= var %= ехр Присваивает переменной var остаток от деления var на ехр

  • <<= var р= ехр Сдвигает var на ехр бит влево

  • >>= var р= ехр Сдвигает var на ехр бит вправо

  • &= var &= ехр Присваивает переменной var результат побитового И var и ехр

  • |= var |= ехр Присваивает переменной var результат побитового ИЛИ var и ехр

  • ^= var ^= ехр Присваивает переменной var результат исключающего ИЛИ var и ехр

Оболочка Коrn поддерживает также группирование выражений с использованием круглых скобок. Выражение в круглых скобках вычисляется как единое целое перед вычислением любых членов снаружи выражения. Скобки используются для изменения обычного приоритета операций.

Операции в табл. 11.13 перечисляются в порядке снижения приоритета. Оболочка Коrn использует обычный приоритет арифметических операций, известный по программированию на языке С или по использованию обычного калькулятора. В соответствии с приоритетом при вычислении выражения а+b сперва выполняется умножение b*у, а затем результат добавляется к а, как если бы выражение было записано в виде а+(b*у). С помощью круглых скобок можно изменять порядок вычисления. Например, (а+b)*у вычислялось бы сперва суммированием а и b, а затем умножением суммы на у.

Команда let является встроенной командой оболочки. Подобно любой команде, она возвращает значение выхода. Значение выхода команды let равно 0, если значение последнего или единственного вычисленного выражения не равно нулю. Если значение последнего или единственного вычисленного выражения равно 0, значение выхода команды let равно 1. Такая несколько странная инверсия является адаптацией оператора if, где команда возвращающая нулевое значение выхода является истинной (т.е. вызывает выполнение инструкции then), а команда, возвращающая ненулевое значение выхода, - ложна (т.е. вызывает выполнение инструкции else).

Вследствие инвертированного значения выхода команды let результат выполнения оператора if let "a == b", например, считается истинным, если а и b равны. Логический результат сравнения на равенство был бы равен 1, что эквивалентно оператору if let 1. Последнее выражение имеет значение равное 1. Следовательно, значение выхода оператора LET равно 0, и результат оператора if считается истинным, тем самым вызывая инструкцию then, как и ожидалось.

Обратите внимание, что необходимо заключать в кавычки операции, используемые в выражении let и имеющие специальное значение для оболочки. Команда let prod=x|y дала бы очень странный результат, если бы была записана без кавычек. Оболочка увидела бы символ конвейера между двумя командами оператора let prod=x и у. Кавычки приемлемы в любой из следующих форм:

р let "prod=x|y"

р let prod="x|y"

р let prod=x\|у

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

Давайте еще раз присмотримся к синтаксису команды let. Обратите внимание, что каждый из ее членов является произвольным выражением. Такая команда, как let х+у допустима, но обычно используется редко. Это связано с тем, что сумма переменных х и у вычисляется, но результат отбрасывается. Необходимо использовать выражение присваивания, например, let sum=x+y, чтобы сохранить результат вычисления в переменной, названной sum для последующих ссылок. Единственный случай, когда имеет смысл вычислять выражение без присвоения результата новой переменной, - это когда назначением команды let является определение значения выхода команды, скажем, для использования в таких операторах, как if и while. Однако о этих случаях можно использовать более удобную форму оператора let: выражение (( )).

Такой оператор, как

if (( х+у < 25))

then . ..

fi

более читабелен, чем его эквивалент:

if let "x+y < 25"

Дополнительное преимущество здесь в том, что использование кавычек не обязательно для скрытия операций внутри выражения (( )). Операции (( и )), по существу, являются специальными видами круглых скобок. Они уведомляют оболочку Коrn, что заключенный в них текст должен обрабатываться как арифметическое выражение; это отключает обычную интерпретацию таких метасимволов, как < и |, и делает возможным их однозначную интерпретацию в качестве символов операций. В этом случае нарушается совместимость с оболочкой Bourne, т.к. операции (( и )) не используются в сценариях оболочки, написанных для оболочки Bourne.

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

Существует также версия выражения (( )), которая возвращает строковое представление результата вычисления - $(( )). В этой форме результат возвращается оболочке. Например,

$ echo "(( 4+5 ))"

((4+5 ))

$ echo рвТ$ ( ( 4+5 ) ) "

9

Арифметические выражения можно использовать в любом из следующих контекстов:

  • в качестве подсценария массива;

  • в качестве аргументов команды let;

  • внутри двойных круглых скобок (( ));

  • в качестве счетчика сдвига в команде shift;

  • в качестве операндов операций -eq, -ne, -gt, -It, -ge и -1е в командах test, [ и [[;

  • в качестве ограничителей ресурсов в ulimit;

  • в качестве правой части оператора присваивания, но только если присваиваемая переменная была определена в качестве целой переменной оператором typeset или integer.

Практические примеры арифметических операций

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

$ х=4 у=5

$ print x+y

x+y

Первая командная строка присваивает численные значения нецелым переменным х и у. Строка print предпринимает попытку напечатать их сумму, но команда print не поддерживает арифметические выражения. Результат полностью аналогичен использованию оболочки Bourne. Оператор print просто повторяет свои аргументы.

Теперь давайте взглянем на первую попытку решить проблему:

$ let х=4 у=5

$ print $x+$y

4+5

Операторы присваивания были заменены командой let, что не оказало никакого ощутимого воздействия. Знаки доллара ($) в операторе print помогают оболочке распознать х и у в качестве переменных. Ссылки на переменные замещаются их соответствующими значениями, но оболочке Коrn по-прежнему не удается распознать наличие выражения в аргументе команды print. Фактически, не существует никакого способа заставить оболочку распознать выражение и вычислить его в команде print.

Ниже приводится приемлемое решение:

$ integer x=4 у=5

$ let sum=x+y

$ print $sum

9

Основной момент в решении - использование оператора let для вычисления суммы. Он сохраняет вычисленный результат в новой переменной sum, на которую впоследствии можно ссылаться.

Читатели могут подумать, что использование ручного калькулятора было бы более простым способом выполнения простых арифметических действий, чем использование клавиатуры, и с этим можно было бы согласиться. Более эффективный подход к использованию клавиатуры в подобном случае - просто использовать команду ехрr. Например,

$ ехрr 4+5

9

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

Теперь давайте рассмотрим цикл, управляемый счетчиком:

integer i=0

while (( i<5 ))

do

i=i+1

print $i

done

Эта небольшая программа просто печатает цифры от 1 до 5. Обратите внимание на использование оператора присваивания вместо команды let для увеличения значения i. Это работает только потому, что переменная i ранее была объявлена как целая. Пример прекрасно работает при вводе с клавиатуры. Проверьте это.

В качестве более практичного примера давайте рассмотрим следующий:

$typeset -il6 hex

$ hex=125

$ print $hex

16#7d

Здесь переменная hex объявляется целой и представляемой с основанием 16. Вторая строка присваивает переменной hex обычное численное значение, а третья - печатает его.

Однако, словно по волшебству, эффект цифры 16 из команды typeset становится ясен: значение переменной hex отображается в шестнадцатеричной (с основанием 16) записи. Обратная операция - преобразование шестнадцатеричной переменной в десятеричную - столь же проста:

$ integer n

$ n=16#7d

$ print $((n))

125

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

$ hex=4096; print $hex

16#1000

$ n=16#1000; print $((n))

4096

Программирование в оболочке Korn

Хотя основное назначение свойств оболочки Коrn - повышение производительности работы за клавиатурой, оболочка Коrn обеспечивает также ряд преимуществ при написании сценариев оболочки, что делает ее привлекательной средой для разработки программ. В этом разделе приводится обзор усовершенствований оболочки Коrn, ориентированных на разработчиков сценариев оболочки. Конечно, все программные конструкции оболочки Bourne также доступны, поэтому изложенный в главе 9 материал применим и к оболочке Коrn и не повторяется в этой главе.

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

р операторов if, while и until;

р переменных массивов, целых переменных, расширенных выражений со ссылками на переменные и арифметических выражений;

р нового оператора select для создания меню приглашений, из которых пользователь может выбрать нужное;

р расширенной поддержки функций, в том числе функций автозагрузки;

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

р расширенной поддержки передачи данных между процессами с использованием операции |&.

Если создаваемый сценарий оболочки предполагается для использования многими пользователями, имеет смысл в первой строке сценария поместить следующее:

#!/bin/ksh

Эта строка сообщает оболочке пользователя, в среде какой оболочки должен запускаться сценарий оболочки. Например, запуск сценария оболочки Коrn в среде оболочки С просто невозможен, несмотря на все усилия!

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

Условные выражения

Операторы if, while и until поддерживают два новых вида выражений. Операция двойных круглых скобок (( )), вычисляющая арифметическое выражение, позволяет выполнять сложные арифметические проверки. Нулевой результат считается истинным, а ненулевой - ложным. Можно также написать расширенное выражение условной проверки в качестве аргумента оператора if, while или until. Выражение условной проверки имеет следующую общую форму:

[[ условное-выражение ]]

где условное-выражение - любая из форм, показанных в табл. 11.14.

Обратите внимание, что формы условных выражений соответствуют выражениям test и []. Оболочка Коrn поддерживает выражения test и [ ], аналогично оболочке Bourne. Выражение [[ ]] обеспечивает расширенные возможности без ущерба для совместимости с оболочкой Bourne.

Таблица 11.14. Условные выражения.

Выражение Оболочка Bourne Условие истинности

  • -r file Да Файл существует.

  • -w file Да Файл существует и имеет право доступа на запись. Файл может быть непригодным для записи, даже если право доступа на запись установлено, если он находится внутри файловой системы, созданной как система "только для чтения".

  • file Да Файл существует и имеет установленное право доступа для выполнения. В действительности файл может и не быть исполняемым. Каталоги обычно имеют установленный флаг прав доступа Execute

  • -f file Да Файл существует и является регулярным файлом.

  • -d file Да Файл существует и является каталогом.

  • file Да Файл существует и является байт-ориентированным файлом устройства.

  • -b file Да Файл существует и является блок-ориентированным файлом устройства.

  • file Да Файл существует и является именованным каналом.

  • -u file Да Для файла file установлен флаг прав доступа Set User ID (Установить идентификатор пользователя).

  • -g file Да Для файла file установлен флаг прав доступа Set Group ID (Установить идентификатор группы).

  • -k file Да Для файла file установлен флаг прав доступа Sticky.

  • -s file Да Файл имеет размер больше нулевого.

  • -L file Нет Файл является символической ссылкой.

  • file Нет Файл имеет Owner ID (Идентификатор владельца), равный действующему User ID (Идентификатор пользователя) текущего процесса.

  • -G file Нет Файл имеет Group ID (Идентификатор группы), равный действующему Group ID текущего процесса.

  • -S file Нет Файл является сокетом.

  • -t [ fildes ] Да Дескриптор файла fildes, значение которого по умолчанию равно 1, является терминалом.

  • option Нет Указанная опция option установлена.

  • -z string Да Строка string является строкой нулевой длины.

  • -n string Да Строка string не является строкой нулевой длины.

  • string Да Строка string не является строкой нулевой длины или нулевой строкой.

  • string = pat Да Строка string соответствует шаблону pat.

  • string != pat Да Строка string не соответствует шаблону pat.

  • s1 < s2 Нет Строка s1 меньше строки s2. Т.е. pat подбирается раньше, чем строка s2.

  • s1 > s2 Нет Строка s1 больше строки s2. Т.е. pat подбирается позже, чем строка s2.

  • file1 -nt file2 Нет Файл file1 более новый, чем файл file2.

  • fie1 -ot file2 Нет Файл file1 более старый, чем файл file2.

  • file1 -ef file2 Нет Файл file1 тот же, что и файл file2.

  • e1 -eq e2 Нет Выражения e1 и е2 равны.

  • е1 -nе e2 Нет Выражения e1 и e2 не равны.

  • е1 -gt e2 Нет Выражение е1 больше e2.

  • е1 -gе e2 Нет Выражение е1 больше или равно e2.

  • е1 -It e2 Нет Выражение е1 меньше e2.

  • е1 -Ie e2 Нет Выражение е1 меньше или равно e2.

Функции

Оболочка Коrn полностью поддерживает функции оболочки Bourne. Кроме того она обеспечивает некоторые расширения.

Определение функций

В дополнение к синтаксису оболочки Bourne оболочка Коrn поддерживает следующий альтернативный синтаксис определения функции:

function identifier

{

command-list

}

Использование переменных в функциях

Оболочка Коrn позволяет функции иметь локальные переменные. Локальная переменная существует только во время выполнения функции и уничтожается, когда функция выполняет возврат. Локальная переменная может иметь то же имя, что и переменная в вызывающей среде. Во время выполнения функции локальная переменная скрывает внешнюю. Локальные переменные объявляются с помощью команды typeset. Например,

function square

{

typeset product

let "product=$l*$l

print $product

return

}

Использование ловушек в функциях

В оболочке Bourne ловушки, установленные командой trap, остаются в действии после выхода из функции. В оболочке Коrn ловушки, установленные в вызывающей среде, сохраняются и восстанавливаются.

Для управления функциями можно использовать команду typeset с опцией -f. Эта опция имеет четыре формы, перечисленные в табл. 11.15.

Таблица 11.15. Использование опции -f.

  • typeset -f Перечисляет определенные в данный момент функции и их определения. Предопределенный псевдоним functions делает то же самое.

  • typeset -ft name ... Активизирует опцию xtrace при каждом вызове функции name. Трассировка возвращается в исходное состояние после возврата функции.

  • typeset -fx name ... Определяет функцию как экспортированную. Экспортированные функции наследуются сценариями оболочки. Однако функция не может экспортироваться в другой экземпляр оболочки ksh. He существует метода для передачи определений функций за пределы среды команды, это возможно лишь для переменных.

  • typeset -fu name ... Определяет функции для автозагрузки. Вызов функции автозагрузки до ее определения распознается как вызов функции, объявленной командой typeset. Оболочка Коrn ищет в каталоге, названном в переменной FPATH, файл с таким же именем, как у функции. Если она находит такой файл, функция загружается и выполняется, а определение сохраняется.

Использование функций автозагрузки

Функции автозагрузки обеспечивают более высокую производительность по сравнению с обычными сценариями оболочки, поскольку они сохраняются в памяти для быстрого выполнения повторных обращений; однако функции, на которые отсутствуют ссылки, не вызывают никаких дополнительных затрат, кроме обработки команды typeset -fii. Функции автозагрузки создаются во многом подобно сценариям оболочки, за исключением того, что файл определений должен быть создан в форме функции; он должен начинаться с оператора function name. Для использования функций автозагрузки необходимо установить переменную среды FPATH для каталога или каталогов, в которых должен производиться поиск (так же, как устанавливается переменная среды PATH), и заблаговременно объявить функции с помощью команды typeset -fu.

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

Отмена определений функций

Для отмены определения функции используется команда unset:

unset -f name ...

Названные функции удаляются из памяти, а любые определения указанных функций отменяются. Команда unset -f используется не очень часто, но она особенно удобна при отладке функции. Использование этой команды - единственный способ заставить оболочку повторно считать файл определения функции автозагрузки.

Когда следует использовать функции

Функции служат удобным способом создания новых клавиатурных команд. Поскольку функции выполняются в качестве составной части среды текущей оболочки, изменение каталога, выполненное с помощью команды cd, остается в силе после выхода из функции. Это не так для обычных команд и сценариев оболочки. Поскольку автор почти всегда предпочитает быстро просмотреть содержание каталога после перехода к нему, он создал следующее короткое определение функции и добавил его к своему профилю регистрации:

function go {

cd $1

/usr/bin/ls -FC

}

Функция go, используемая в форме go имя_каталога, не только изменяет каталог, но также выводит его упорядоченное содержание, позволяя немедленно видеть, что содержится в каталоге.

Включение функции go в профиль регистрации означает, что она всегда присутствует в памяти оболочки. Поскольку эта функция невелика, это не вызывает никаких проблем, учитывая частоту ее использования. В случае больших функций, лучше хранить их определение в отдельном файле и заместить определение функции в профиле объявлением typeset -fu, тем самым превращая функцию в функцию автозагрузки.

Просмотр аргументов с помощью команды getopts

Оболочка Bourne оказывает весьма незначительную поддержку в обработке опций командной строки. В результате многие сценарии оболочки, написанные пользователями, в лучшем случае оказываются громоздкими и часто не поддерживают обобщенный формат команд UNIX для опций. Команда getopt, уже давно ставшая стандартной частью набора команд UNIX, помогает мало. Однако оболочка Коrn идет на шаг дальше, добавив встроенную команду getopts, которая предоставляет разработчикам сценариев те же возможности и гибкость, которыми давно пользуются программисты С.

Синтаксис встроенной команды getopts прост:

getopts options var [ arg ... ]

В качестве options необходимо вводить строку, определяющую символы, которые могут появляться в качестве опций командной строки. Если за символом опции может следовать строка значения, укажите это в строке options посредством двоеточия после символа. Например, I: представляет синтаксис опции Istring.

Если строка options начинается с двоеточия (:), оболочка Коrn обеспечивает обработку ошибок пользователя. Неверный символ опции помещается в переменную OPTARG, а значение устанавливается равным ?. При отсутствии двоеточия команда getopts выводит сообщение об ошибке при вводе неверной буквы и устанавливает значение var равным ?, чтобы можно было узнать об ошибке и пропустить неверную опцию, однако программа не идентифицирует неверный символ.

В качестве var записывается имя переменной, принимающей символ опции. Распознав букву в качестве опции в командной строке, оболочка сохраняет букву в var

В качестве arg записывается список аргументов командной строки, подлежащей просмотру на предмет опций. Список arg обычно записывается в форме $* или "$@".

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

При вызове getopts она запускается с определением своей текущей позиции в списке arg. Если текущая позиция находится внутри слова и это слово начинается с -, следующий символ в слове воспринимается в качестве символа опции. Если данный вызов команды getopts является первым, или последний вызов завершил просмотр слова, getopts проверяет следующий аргумент arg на предмет головного дефиса.

В любом случае, когда команда getopts идентифицирует опцию, она сохраняет символ в var. Если опция принимает строку значений (указанную в строке option после двоеточия), значение опции просматривается и сохраняется в предопределенной переменной OPTARG. Если команда getopts приступает к новой переменной arg, она увеличивает предопределенную переменную OPTIND для указания того, с каким аргументом она работает - 1, 2 и т.д. Затем она обновляет свою позицию в списке аргументов и осуществляет выход.

После вызова команды getopts можно просмотреть переменную var для выяснения того, какие опции идентифицированы. Если опция принимает какое-либо значение, строка значения будет храниться в предопределенной переменной OPTARG. Возвращаемое значение getopts равно нулю, если она находит опцию, или не равно нулю, если она больше не может найти ни одной опции в списке аргументов командной строки.

Программный код для использования команды getopts почти полностью стандартен, его следует запомнить. В листинге 11.1 приведена программа просмотра опций командной строки, подобных тем, которые можно встретить в файле сценария. В этом примере программа просто выводит распознанные ею опции.

Листинг 11.1. Просмотр опций с помощью команды getopts

# программа для просмотра опций

# Допустимыми опциями являются -а, -с, -R, -Апате или -Iname.

while getopts :acRA:I: KEY $*

do

case $KEY in

a) print Found option -a;;

c) print Found option -c ;;

R) print Found option -R ;;

A) print Found option -A, value is "'$OPTARG'" ;;

I) print Found option -I, value is '"$OPTARG1" ;;

*) print -u2 Illegal option: -$OPTARG

esac

done

# Удаление аргументов опции с сохранением позиционных аргументов

Shift OPTIND-1

print ARGS: $*

Программный код в листинге 11.1 является исполняемым. Введите операторы в файл и сделайте его исполняемым с помощью команды chmod +x filename. Затем вызовите имя файла с примером набора символов опций и аргументов. Отобразится представление оболочки о введенных опциях и позиционных аргументах.

В листинге 11.1 необходимо отметить два особых момента. Во-первых, строка option команды getopts начинается с двоеточия (:). Когда строка option начинается с двоеточия, команда getopts обеспечивает обработку ошибок пользователя; нераспознанный символ опции помещается в переменную OPTARG, а переменная ключевых символов var устанавливается равной ?. Можно выполнить явную проверку на предмет наличия ? в качестве значения символа, а можно просто обеспечить собственное сообщение об ошибке для любого нераспознанного символа опции.

Если строка string не начинается с двоеточия (:), команда getopts выполняет собственную обработку ошибок. После обнаружения нераспознанного символа опции, команда выводит сообщение об ошибке и устанавливает значение var равным вопросительному знаку (?), но не указывает символ опции в OPARG. Следовательно, хотя и сообщается, что найдена неверная опция, но неизвестно, какая опция неверна. Конечно, неверен тот, символ опции который не отображается в строке option.

Во-вторых, обратите внимание на использование оператора shift для идентификации остающихся аргументов исходной командной строки. Сама по себе команда getopts не избавляется от слов, содержащих опции из списка arg. Однако после идентификации опций с помощью команды getopts пользователю не нужно, чтобы они отображались снова во время проверки остающихся аргументов. От просмотренных слов опций необходимо избавляться самостоятельно. Оператор shift, унаследованный от оболочки Bourne, при поддержке синтаксиса обработки арифметических выражений оболочки Коrn весьма успешно справляется с этой задачей. Выражение OPTIND -1 вычисляет количество аргументов, остающихся в командной строке. Обратите внимание, что, поскольку OPTIND -1 располагается в командной строке shift в позиции выражения, OPTIND распознается в качестве ссылки на переменную; перед ней не нужно вставлять знак доллара.

Использование оператора select

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

Фактически, поскольку пользователь может выбрать недопустимую опцию (что требует отступления в процессе выбора из меню) или на случай, если требуется повторно отображать меню до тех пор, пока пользователь не примет решение о выходе, оператор select является по существу интерактивным, во многом подобным операторам while или until. Для прерывания выполнения оператора select необходимо использовать оператор break.

Синтаксис оператора select следующий:

select Identifier [ in word ... ]

do command-list

done

Оператор select сперва отображает список слов (word ...) в одной или нескольких колонках. Если переменная LINES инициализирована и содержит целое число, она берется в качестве максимального числа строк, доступных для отображения в списке слов. Если количество элементов, подлежащих отображению, превышает этот максимум, список разбивается на несколько колонок. Каждой строке word предшествует префикс в виде номера, начиная с 1. Строка word может быть отдельным словом или строкой, заключенной в кавычки. Перед отображением она просматривается на предмет наличия подстановок переменных и команд.

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

Затем оператор select отображает значение переменной PS3 в качестве приглашения меню. По умолчанию значением переменной PS3 является #?, исходя из предположения, что пользователь должен ввести номер пункта. Если требуется другое приглашение то, перед выполнением оператора select необходимо присвоить новое значение переменной PS3.

После этого оператор select считывает ответ пользователя. Вся введенная пользователем строка сохраняется в специальной переменной оболочки REPLY. Если пользователь водит нулевую строку (т.е. нажимает клавишу Enter или Return без ввода чего-либо), select повторно отображает список и снова выводит приглашение без вызова последовательности команд command-list. Если пользователь вводит номер, значение переменной identifier устанавливается равным word, соответствующему этому номеру. Т.е. ввод числа 1 устанавливает identifier на первое слово word, 2 - на второе и т.д. Если номер превышает число слов или если введенное пользователем не является номером, оператор select устанавливает значение переменной identifier равным нулю. В любом случае select выполняет список команд command-list.

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

PS3="Select color by number (e.g., 3):"

select color in Blue Green Yellow Red White Black Burnt-umber "Natural Wool"

do case $color in\

Blue | Green I Yellow | Red | White | Black |

Burnt-umber [ "Natural Wool"| break ;;

*) print "Please enter a number from 1-8. Try again." ;;

esac

done

print "Yor color choice is: $color"

Обратите внимание на использование кавычек для указания Natural Wool в качестве одного из пунктов меню. Если бы слова не были заключены в кавычки, оператор select считал бы их двумя отдельными пунктами меню и пользователь имел бы возможность выбрать Natural (пункт 8) или Wool (пункт 9).

Отметьте себе также, что в примере ничего не делается для повторного выполнения пункта меню до тех пор, пока пользователь не введет допустимый пункт. Итерация в select выполняется автоматически. Оператор выводит список действующих пунктов, которые должны выполнить какое-либо специальное действие для прерывания цикла select - в данном случае посредством выполнения оператора break. Ничто не мешает с помощью оператора select реализовать простую управляемую посредством меню систему. В программе, приведенной в листинге 11.2, оператор select используется для предоставления пользователю возможности выбора действий приложения. Пример продолжает выполняться до тех пор, пока пользователь не выберет пункт Exit. После этого оператор select и любой сценарий оболочки, в котором он содержится, прерываются встроенной командой оболочки exit.

Листинг 11.2. Реализация системы меню с помощью оператора select.

PS3=Choice?

select choice in "Enter Transactions" \

"Print trial balance" \

"Print invoices" \

"Exit"

do case "$choice" in

"Enter Transactions") . daily-trans ;;

"Print trial balance") . trial-balance ;;

"Print invoices") . invoices ;;

"Exit") print "That's all, folks!"; exit

*) print -u2 "Wrong choice. Enter a number (1-4)."

esac

done

Использование сопроцессов

Оболочка Bourne поддерживает минимальный объем обмена данными между процессами - как правило, посредством операции каналов. Можно вызвать редактор строки ed из сценария оболочки, чтобы выполнить некоторые изменения в тексте, используя команду, подобную показанной в листинге 11.3.

Листинг 11.3. Обмен данными в основном процессе

(echo "/"Payroll

+1

i"

cat newlist

echo ". "

echo "w"

echo "q"

) | ed - paylist

Этой формы обмена данными между задачами достаточно, если нужно всего лишь передать некоторые данные другой команде или считать ее вывод. Однако давайте предположим, что в листинге 11.3 необходимо обеспечить возможность пропуска команд редактора insert, write и quit, если файл paylist не содержит строку, начинающуюся с Payroll. Это нельзя было бы сделать при использовании оболочки Bourne. Однако в среде оболочки Коrn с помощью команды ed можно создать интерактивный сеанс, содержащий программу, которая предоставляет инструкции для ed и отвечает на его вывод.

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

Простейший способ пересылки строки сопроцессу - использование команды print -p. Опция -р указывает команде print выполнять запись в канал ввода сопроцесса. Для считывания вывода сопроцесса используется команда read -p. И в этом случае опция -р предписывает выполнять считывание из канала сопроцесса.

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

Листинг 11.4. Обмен данными между процессами с использованием сопроцесса

ed paylist | &

ехес 3>&р

exec 4<&p

read -u4 #отмена первоначальной строки сообщения

print -u3 Р #Активизация приглашения

print -u3 "/'Payroll" #поиск места вставки

read -u3 # считывание приглашения, указывающего на успешность или неудачность

# поиска

case "$REPLY" in

'*'*) # поиск, вероятно, был успешным print -u3 i

cat text >&3 # вставить файл с данными

print -u3 .

read -u4 # прочитать завершающее приглашение

print -u3 w; read -u4

print -u3 q

;;

*) # не найдено

print -u3 q

echo -invalid paylist file"

exit

;;

esac

done

В примере следует обратить внимание на следующее:

  • Команда ехес (eхес 3>&р) используется для перемещения канала ввода сопроцесса с его исходного местоположения в нумерованный дескриптор файла.

  • Команда ехес (eхес 4<&р) используется снова для перемещения канала вывода сопроцесса в нумерованный дескриптор файла 4.

  • Последующие команды read и print посредством использования опции -u указывают дескриптор файла в качестве источника или места назначения операции.

  • Обычные команды UNIX могут выполнять запись в сопроцесс посредством перенаправления к дескриптору файла 3 (cat filename >&3).

ПРИМЕЧАНИЕ

Команды read -p или print -p следует использовать для считывания или записи в сопроцесс до тех пор, пока ввод или вывод сопроцесса не будет перемещен в нумерованый дескриптор файла. Затем можно выполнять запись или считывание из этого дескриптора файла: read -u4 или print -u3.

 

Безусловно, листинг 11.4, использующий сопроцесс, сложнее листинга 11.3, но он также и надежней. В случае безуспешного поиска строки Payroll версия для оболочки Boume добавила бы новые строки после первой. Оболочка Кот в случае неудачи ведет себя корректно, не повреждая файл paylist.

Обратите внимание, что пример оболочки Коrn с сопроцессом, приведенный в листинге 11.4, содержит неполную команду cat. Это связанно с тем, что требуется специальный синтаксис для транскрибирования файла в канал сопроцесса. Стандартный синтаксис оболочки Bourne - >filеnаmе и >&fildes - в данном случае не подходит. >filеnаmе и >&fitdes не позволяют ссылаться на каналы ввода и вывода сопроцесса.

Действительно, применяя свойство оболочки Коrn, разработанное специально для поддержки сопроцессов, можно использовать перенаправление ввода/вывода для пересылки вывода или считывания ввода из фонового процесса посредством любой команды UNIX. Для переключения каналов ввода и вывода по умолчанию, созданных операцией |&, на явные дескрипторы файлов требуется особая технология. Это делается посредством использования команды ехес:

ехес 3>&р

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

Аналогично, следующий код переприсваивает канал считывания из сопроцесса:

ехес 4<&р

Если поместить эти две строки перед примером ed, команда cat может быть записана знакомым образом, - т.е. с использованием перенаправления ввода/вывода в открытый дескриптор файла. Например:

cat newlist >&3

Конечно, новый синтаксис оператора ехес - ужасен, его трудно запомнить. Однако основные черты сопроцессов, включая операцию |& и опции -р команд print и read, достаточно очевидны, как и лежащая в их основе концепция. Сопроцессы - мощное свойство, делающее возможным в сценариях оболочки то, для чего ранее требовался язык программирования С. А посему, заточите карандаши и попытайтесь набить руку в написании сопроцессов.

Несколько предостережений

Оболочка Коrn - очень мощная оболочка для создания сценариев; однако она не свободна от проблем. Oдна из наиболее серьезных связана с использованием каналов. Давайте рассмотрим следующий сценарий:

person=noone

echo At start: $person

who | while read person tty junk

do

echo $person is logged on at terminal $tty

done echo At end: $person

Каким будет значение переменной person после запуска этого сценария? Ответ неизвестен. У автора этот сценарий дал два различных результата в двух реализациях оболочки Коrn. В одной системе переменная person была пустой (нулевой) строкой. В другой она содержала значение nооnе.

Причина этой неопределенности в том, что выполняется перенаправление вывода в другую команду. При использовании канала для управления выводом, по существу, запускается еще одна оболочка. Однако в другой реализации образование канала может выполняться иначе, поскольку операторы while и read являются внутренними для оболочки, и поэтому не нужно запускать вторую оболочку для управления ими.

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

Настройка оболочки Коrn

Вполне можно было бы сказать, что термин оболочка относится к тому, что имелось перед тем, как пользователь настроил ее, т.е. к пустой оболочке. Конечно, это преувеличение. Оболочка загружена свойствами больше, чем большинство программ, с которыми вам придется столкнуться. И все же, допускаемая оболочкой Коrn степень настройки позволяет без преувеличения сказать, что среда другого пользователя может показаться столь чуждой, что будет почти неприменима. Действительно, кое-где пытаются накладывать ограничения на настройку оболочки пользователями.

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

Настройка оболочки Коrn начинается со сценария профиля регистрации, называющегося .profile и располагающегося в начальном каталоге. Файл $HOME/.profile особенно важен, поскольку оболочка Коrn выполняет его при каждом входе в систему, точнее, при каждом запуске интерактивной оболочки.

Часто системный администратор будет помещать начальный сценарий .profile в начальный каталог пользователя, создавая его конфигурацию входа в систему. Не следует думать, что имеется что-либо "священное" в таком предоставленном файле .profile. Его содержимое влияет только на конкретного пользователя. Сценарий связан с данным регистрационным именем и начальным каталогом. Изменение его любым мыслимым образом могло бы повлиять только на тех, у кого имеется данный пароль и кто может входить в систему под данным именем. Почти всегда этим лицом является только один пользователь. Поэтому можно безбоязненно дополнять, изменять или удалять все что угодно в сценарии .profile, вплоть до удаления всего файла. Это не имеет значения для оболочки. Файл .profile поддерживается только ради удобства пользователя; он не обязателен для функционирования оболочки Коrn.

Сценарий .profile, по существу, является сценарием оболочки. Любые технологии программирования оболочки, допустимые в сценарии оболочки, допустимы и в сценарии .profile. He страшитесь, если вы не программист. Можно создавать весьма полезные профили регистрации, которые не содержат ничего, кроме очевидных команд UNIX и оболочки, без каких-либо операторов if или while. Если же знаете, как использовать условные и итерационные операторы оболочки - тем лучше. Однако не следует думать, что овладение этими операторами - обязательное условие для создания качественных сценариев регистрации. Это не так.

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

р Установка клавиш управления с помощью команды stty.

р Установка переменных среды.

р Установка локальных переменных для управления оболочкой.

р Определение наиболее часто используемых псевдонимов.

р Определение наиболее часто используемых функций, в том числе функций автозагрузки.

р Установка предпочитаемых опций оболочки.

р Запуск команд, которые необходимо выполнять при каждом входе в систему.

Установка клавиш управления с помощью команды stty

Команда stty используется для установки предпочитаемых клавиш управления. По умолчанию клавишей Erase является клавиша #, a Kill - @. Обе эти клавиши - не самый удачный выбор, поскольку их применение в качестве символов управления терминалом конфликтует с применением их в качестве обычных текстовых символов. Необходимо переопределить их с помощью оператора, аналогичного следующему:

stty erase '^H' kill '^U' intr '^C'

В этом примере используется символ (^) перед прописными или строчными буквами для обозначения управляющей комбинации клавиш. Таким образом, erase '^H' определяет комбинацию Ctrl-H как клавишу Backspace. Присутствие символа вставки активизирует использование знаков кавычек. Символ (^) специфичен для оболочки; отсутствие кавычек ведет к неверной интерпретации команды stty. (Для более подробного ознакомления с командой stty обратитесь к справочному руководству пользователя UNIX.)

Управление ресурсами с помощью команды ulimit

Использование команды ulimit для управления ресурсами - полезное свойство, особенно для системных администраторов. Хотя UNIX поставляется с командой ulimit, оболочка Кот предоставляет собственную версию. Синтаксис этой команды следующий:

ulimit [ -HSacdfnstv] [limit]

Флаги Н и S сообщают команде ulimit об установке жесткого (Hard) или мягкого (Soft) предела. Жесткий предел не может быть увеличен после установки. Мягкий предел может быть изменяться вплоть до значения жесткого предела. Если оба эти флаги опущены, указанный предел применяется и к жесткому и к мягкому пределам.

Если аргумент limit опущен, отображается текущее значение указанного предела. Если команда ulimit вызывается без опций, она возвращает число блоков, которые могут быть записаны процессом (это равносильно вводу команды ulimit -f). В таблице 11.16 приведены параметры команды ulimit.

Таблица 11.16. Параметры команды ulimit.

Параметр Функция

-а Перечисляет все пределы ресурсов

-с Указывает количество блоков для файла ядра

-d Указывает размер области данных в килобайтах

-1 Указывает число блоков, которые могут быть записаны в файл

-n Указывает на единицу больше числа файлов, которые могут быть открыты одновременно

-S Указывает размер области стека в килобайтах

-t Указывает время в секундах, которое может использоваться каждым процессом

-v Указывает объем виртуальной памяти в килобайтах

СОВЕТ

Если предполагается выполнять большой объем программирования, полезно в профиль поместить команду ulimit Это предотвращает создание дамп-файла ядра любой разрушающейся программой, тем самым экономя дисковое пространство, Многие дампы ядра могут занимать несколько мегабайт дискового пространства, поэтому любой cпoсоб

уменьшения их количества часто является желанным методом!

Установка переменных среды

По меньшей мере потребуется убедиться, что переменные PATH и MAIL имеют значения Обычно потребуется устанавливать гораздо больше переменных При использовании синтаксиса оболочки Bourne установки переменных будут выглядеть подобно следующим

PATH=/usr/bin:/usr/ucb:/usr/local/bin:$HOME/bin:

MAIL=/var/spool/mail/$LOGNAME

MAILCHECK=60

FCEDIT=/usr/bin/vi

VISUAL=/usr/bin/vi

export PATH MAIL MAILCHECK FCEDIT VISUAL

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

export PATH=/usr/bin:/usr/ucb:/usr/local/bin:$HOME/bin:

export MAIL=/var/spool/mail/$LOGNAME

export MAILCHECK=60

export FCEDIT=/usr/bin/vi

export VISUAL=/usr/bin/vi

При записи установок переменных среды необходимо иметь в виду, что некоторые из них устанавливаются процессором регистрации UNIX. Системный администратор также может создать сценарий регистрации для установки значений перед запуском сценария .profile. Например, переменные PATH и MAIL обычно уже имеют установленные начальные значения в момент запуска сценариев. Замещение определенной по умолчанию переменной PATH - обычно здравая мысль; необходимо располагать полым контролем над путем поиска программы, начиная с его начального значения. Замещение определенных по умолчанию переменных MAIL или MAILPATH - несколько рискованное предприятие, если только точно не известно, какая почтовая подсистема используется.

Установка локальных переменных для управления оболочкой

Локальные переменные - это переменные, которые оболочка использует, но не экспортирует. В их число входят переменные FCEDIT, назначающая текстовый редактор, подлежащий использованию командой fc, и переменная PS1, являющаяся первичной строкой приглашения. Можно также определить несколько локальных переменных для хранения имен каталогов, к которым обычно осуществляется доступ, что позволит использовать cd $dir вместо длинного полного пути.

Определение псевдонимов

Можно определить любые необходимые псевдонимы. Следует придумывать собственные псевдонимы; каждый пользователь стремится иметь отличный от других набор. Большинство пользователей создают какие-либо псевдонимы для команды ls. Можно даже переопределить поведение по умолчанию команды ls, определив псевдоним ls. Ниже приведены примеры нескольких типичных псевдонимов:

alias lx-'/usr/bin/ls -FC' a

lias 1='/usr/bin/ls -l'

alias pg='/usr/bin/pg -ens -p"Page %d:"'

alias mail='/usr/bin/mailx'

alias -t vi

Обратите внимание, что в большинстве случаев используются полные пути команд в определении псевдонима. Тем самым исключается поиск команды в каталогах и обеспечивается эффект, во многом подобный механизму отслеживания псевдонимов оболочки Коrn. Обратите также внимание на явное использование команды alias -t для указания оболочке отслеживать команду vi. Оболочка отыскивает полный путь команды vi и сама определяет псевдоним, названный vi, поэтому простая команда vi обеспечивает максимальную производительность, но не требует утомительного ввода /usr/bin/vi.

Определение функций

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

Установка опций оболочки

Если некоторые опции оболочки часто задаются в командной строке, их можно вместо этого задать в файле .profile. Для установки опций оболочки используется команда set. Если вы предпочитаете использовать режим vi для истории команд и редактирования и при этом требуется полная поддержка управления задачей, можно было бы вставить в файл .profile следующие две строки:

set -о vi set monitor

Выполнение команд при каждом входе в систему

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

Выполнение сценария .profile после его изменения

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

$ . ./.profile

Не забудьте вставить пробел после первой точки: это имя команды, a ./.profile - аргумент команды. (Хотя .profile обычно подходит и сам по себе, может потребоваться использование ./.profile, если текущий каталог не находится в пути поиска.) Команда точки не только выполняет сценарий, но также сохраняет любые изменения среды после прерывания сценария.

Или же можно запустить сценарий командой ksh -v, чтобы оболочка выполняла сценарий и выводила каждый оператор по мере его выполнения:

$ ksh -v ./.profile

Использование опции -n заставило бы оболочку Коrn считать файл .profile и проверить его на предмет синтаксических ошибок, но не выполнять содержащиеся в нем команды.

Создание файла ENV

После настройки файла .profile можно приниматься за файл среды. Файл среды - любой файл сценария оболочки, путь к которому помещен в переменную ENV. Оболочка выполняет переменную ENV при каждом новом вызове оболочки при выполнении команд. Читатели, которым когда-либо приходилось покидать оболочку из таких команд, как pg и vi, знают, что при повторном вызове оболочки, некоторые установки среды, такие как псевдонимы, не переносятся из оболочки регистрации. Путем помещения псевдонимов, определений функций и даже глобальных переменных в отдельный файл и установки в сценарии .profile значения переменной ENV равным его пути можно обеспечить постоянство среды оболочки Кот во всех случаях.

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

ПРИМЕЧАНИЕ

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

Для использования файла среды необходимо создать файл, содержащий требуемые псевдонимы, функции и определения экспортируемых переменных. Затем в файл .profile следует вставить оператор export ENV=pathname, где pathname - полный путь к файлу среды. Файл среды вступает в действие при следующем входе в систему. Если же .profile проверяется с помощью команды

. .profile

файл среды вступает в действие немедленно.

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

СОВЕТ

Очень полезно помещать в файл ENV следующий оператор If

if (t .interactive 3]

then

insert your ENV lines in here

fi

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

ksh -с ls -1

При наличии множества псевдонимов и/или функций здравой мыслью является помещение их в отдельный файл и вызов этого файла из ЕNV для их |установки. Автор, например, в свой файл ENV помещает следующие две строка:

. . ksh_ alias

. .ksh_funcs

В файле .ksh_alias помещены все определения псевдонимов, a a .ksh_funcs - все определения функций. Это существенно сокращает размер файла ENV и придает всему гораздо более стройный вид.

 

 

Добавление в файл .profile установок для других программ

Настройка среды не заканчивается использованием профиля регистрации и файла среды для установки желательных опций оболочки и настроек; здесь удобно помещать также установки, используемые другими программами. Один из способов настройки среды редактирования vi - определение переменной EXINIT, содержащей команды, которые vi будет запускать при каждом своем запуске. Установку переменной EXINIT можно было бы поместить в профиль регистрации, чтобы задать предпочтительные установки редактора vi. Многие команды UNIX реагируют на переменные среды, что позволяет настраивать эти команды в профиле регистрации.

Управление задачами

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

Основная идея фоновых задач проста. Это программа, которая может выполняться без приглашений или иных интерактивных взаимодействий, и которая может выполняться параллельно с другими активными процессами. В среде оболочки Bourne фоновая задача запускается операцией &. Например, команда ее myprog.c & компилирует исходную программу myprog.c, не беспокоя терминал. Можно выполнять другую работу - даже редактировать файлы с помощью полноэкранного редактора - пока команда ее трудится за кулисами.

Усовершенствования команды stty и драйвера терминала в новейших версиях UNIX добавили к терминалу новую управляющую последовательность Suspend (Приостановка). Обычно она вводится с помощью комбинации клавиш Ctrl-Z. Это новое инструментальное средство позволяет временно поместить выполняющуюся в данный момент программу, например сеанс редактирования vi, на задний план. Если программе требуется обратиться к терминалу, система приостанавливает программу. В противном случае она продолжает выполняться.

Оболочка Коrn добавляет некоторые инструментальные средства, которые помогают управлять семейством процессов. В число этих инструментальных средств входят команды jobs, kill, wait, bg и fg.

Чтобы воспользоваться инструментальными средствами управления задачами оболочки Коrn, необходимо активизировать опцию monitor. Обычно это делается автоматически; для интерактивных оболочек это задается по умолчанию. Если операционная система не поддерживает управление задачами, опция monitor по умолчанию отключена. Даже без поддержки операционной системы - клавиша Suspend и функция stty являются услугами операционной системы, а не оболочки Korn - все же можно использовать некоторые из инструментальных средств управления задачами оболочки Korn, но в этом случае опцию monitor необходимо установить самостоятельно. Это делается с помощью команды set monitor.

Команда jobs, не имеющая аргументов, просто выводит список активных в данный момент задач. Вывод команды jobs выглядит подобно следующему:

$ jobs

[1] + Running xlogo&

[2] + Running xclock -bg LightGreenfi

[3] + Stopped vi myprog.c

Команды kill, bg и fg используются для управления задачами. При ссылке на задачу используется номер, показанный в выводе команды jobs в квадратных скобках, с префиксом в виде знака процента (%). Например, команда kill %1 прервала бы программу xlogo, выполняющуюся в данный момент. Команды wait, kill, bg и fg могут также ссылаться на фоновые задачи по их идентификатору процесса (Process ID), который в общем случае можно вывести посредством команды ps. Однако использование номеров задач оболочки Korn предпочтительнее, т.к. их проще и безопасней использовать, чем идентификаторы процессов.

Задачи создаются одним из трех способов:

р путем явного назначения команды для выполнения в фоновом режиме с помощью операции &',

р путем переключения задачи в фоновый режим с помощью команды bg оболочки Коrn;

р путем нажатия клавиши Suspend - обычно комбинация клавиш Ctrl-Z - пока задача переднего плана выполняется.

По соглашению запущенная или переключенная в фоновый режим задача продолжает выполняться до тех пор, пока не пытается выполнить считывание с терминала. В этом случае она приостанавливается операционной системой до момента вмешательства пользователя. В этом состоянии команда jobs показывает, что команда является остановленной - Stopped.

Приостановленная задача обычно требует обмена данными с пользователем, прежде чем ее выполнение продолжится. В предыдущем примере команды jobs выполнение команды vi приостановлено. Она не будет выполняться до тех пор, пока пользователь повторно не подключит ее к терминалу. Это делается с помощью команды fg, например fg %3 или fg %vi После этого команда vi становится процессом переднего плана и вновь выполняется в обычной интерактивной форме.

 

 

ПРИМЕЧАНИЕ

Такие полноэкранные программы, как vi, вероятно, не смогут распознать, что экран более не соответствует последнему экрану редактирования Вероятно, придется нажать Ctrt-L для обновления экрана, прежде чем можно будет вернуться к сеансу редактирования Другие программы, которые просто нуждаются в ответе пользователя на приглашение, не требуют никаких специальных действий при вызове их с помощью команды fg

В табл. 11.17 показан полный синтаксис аргумента %, воспринимаемого командами wait, kill, fg и bg

Таблица 11.17. Синтаксис аргумента ссылки на задачу

  • %number Номер задачи

  • %string Задача, команда которой начинается со строки string

  • %?sfrmg Задача, команда которой содержит строку string

  • %% Текущая задача

  • %+ Текущая задача (также %%)

  • %- Предшествующая задача

Синтаксис команд управления задачами оболочки Кокт описывается в последующих разделах.

Отображение фоновых задач и их состояния

Команда jobs используется для отображения фоновых задач и их состояния. Например,

jobs [ -ip I [ job ... ]

Опция -1 приводит к тому, что команда jobs для всех задач в дополнение к номерам задач отображает также идентификаторы процесса (Process ID). Опция -р заставляет команду jobs вместо номера задачи отображать только идентификатор процесса для каждой из задач.

Если аргументы job, команда jobs отображает информацию о всех фоновых задачах, как показано в следующем примере:

$ jobs

[1] + Running xlogo&

[2] + Running xclock -bg LightGreenfi

[3] + Stopped vi myprog.c

При включении в команду аргументов job, команда jobs отображает информацию только об указанных задачах. В качестве job следует указывать идентификатор процесса или ссылку на задачу, начинающуюся с %. Для выяснения того, продолжает ли выполняться задача 2 из предшествующего примера, нужно было бы ввести следующую команду:

$ jobs %2

[2] + Running xclock -bg LightGreen&

Посылка сигналов задаче

Команда kill используется для посылки сигнала указанной задаче. Некоторые сигналы вызывают прерывание задачи. Сигнал TERM - также называемый сигналом 15 или прерыванием - обычно вызывает корректное прерывание задачи, в то время как сигнал 9 всегда прерывает задачу, но может оставить незакрытые файлы или внести какой-либо иной хаос в выполнявшуюся задачу. Команду kill -9 следует использовать только в тех случаях, когда нельзя прервать задачу никаким другим способом.

Вообще говоря, команда kill является командой системы UNIX, но оболочка Коrn обеспечивает встроенную команду kill с расширенными возможностями. Оболочка Коrn поддерживает основные функциональные возможности команды kill UNIX. Ее синтаксис следующий:

kill [ -signal ] job ...

В качестве сигнала signal указывается номер сигнала или его имя. Номера сигналов 1-15 допустимы всегда. Имя сигнала - один из мнемонических символов из предварительно определенного списка, сигналов соответствующих допустимым номерам. Для получения списка допустимых имен сигналов необходимо использовать команду kill -1. Имена TERM (terminate - прервать) и HUP (hang-up - отбой) допустимы всегда. (Для получения дополнительной информации о командах kill и signal обратитесь к справочному руководству пользователя UNIX.)

ПРИМЕЧАНИЕ

Причина неопределенности имен сигналов заключается в том, что они отличаются в различных версиях UNIX. Для выяснения имен, допустимых в конкретной системе, необходимо использовать команду kill -I.

В качестве job вводится один или несколько идентификаторов процессов или ссылок на задачи. Ссылки на задачи начинаются с %. Команду kill обязательно нужно снабдить хотя бы одним аргументом job Предположим, что бьы запущен процесс xclock, отображающий часы на экране терминала Х

$ xclock -bg LightGreenfi

[4] + Running xclock -bg LightGreen

Окно xclock (фоновая задача) можно закрыть любой из следующих команд'

$ kill %4

ИЛИ

$ kill %xclock

Приостановка оболочки до завершения задачи

Команда wait используется для приостановки оболочки до тех пор, пока указанная задача, если таковая существует, не будет завершена Видимый эффект команды wait - просто в том, что оболочка не отображает очередного приглашения. Для получения приглашения, если требуется прервать ожидание, достаточно просто нажать клавишу Enter Это приводит к тому, что оболочка отображает приглашение и прерывает выполнение команды wait. Синтаксис команды wait следующий.

wait [ Job ... ]

В качестве job указывается один или более идентификаторов процессов или ссылок на задачи, назначенные задаче или задачам, для которых необходимо установить ожидание Если ни одна задача не указывается, оболочка дожидается завершения любой задачи При указании двух и более задач, оболочка дожидается завершения всех указанных задач

Команда wait используется не слишком часто, но она удобна при завершении всей интерактивной работы, а также если для продолжения работы требуются результаты одной или нескольких фоновых задач Без команды wait пришлось бы многократно выполнять команду jobs, пока нужные задачи не были бы помечены как Done (Выполнено)

В частности, команда wait удобна при форматировании текстов Можно запустить nroff или troff в качестве фоновых задач, направляя их вывод в дисковый файл для просмотра. Пока задача nroff или troff выполняется, можно редактировать другие текстовые файлы Когда больше нечего редактировать, потребуется дождаться завершения nroff или troff, поскольку остается только просмотреть свою предшествующую работу Гипотетический консольный сеанс мог бы выглядеть подобно показанному в листинге 11 5

Листинг 11.5. Консольный сеанс.

$ vi chapl.nr

$ nroff -me chapl.nr >chapl.nrf &

[4] + Running nroff -me chapl.nr

$ vi chap2.nr

$ nroff -me chap2.nr > chap2.nrf &

[5] Running nroff -me chap2.nr

$ jobs

[4] Running nroff -me chapl.nr

[5] Running nroff -me chap2.nr

$ wait

В этом листинге редактирование chap2.nr перекрывается с форматированной печатью chapl.nr. По завершении редактирования файла chap2.nr при запуске команды jobs выясняется, что обе задачи nroff все еще выполняются. Поскольку не осталось других задач по редактированию, можно использовать команду wait, чтобы дождаться пока одна из фоновых задач не завершится. Оболочка не будет выводить следующее приглашение до тех пор, пока одна из этих двух задач не будет выполнена. Затем будет отображено сообщение Done:

$ wait [5] done nroff -me chap2.nr

$

Другое полезное применение команды wait - управление Х-сеансами. При входе в систему и вызове Х Window, обрабатывается один из двух файлов: .xinitrc или .xsession. Какой именно из файлов обрабатывается, зависит от метода, используемого для запуска Х Window. В частности, когда автор подключается к системе, обрабатывается его файл .xsession. При прерывании рxsession Х-сеанс завершается и осуществляется выход из системы. Фрагмент этого файла xsession выглядит так:

ctwm &

WINM=$!

xv -quit -root etc/pics/space.gif &

xterm -sb -si 2000 -Is -title "Xterm 1" -geometry 80х24+0+86 &

xterm -sb -si 2000 -Is -title "Xterm 2" -geometry 80х24+523+430 &

wait $WINM

В этом программном коде используются два свойства оболочки Коrn. Во-первых, $! используется для получения идентификатора процесса запускающегося Window Manager, ctwm, и для присваивания его переменной WINM. Затем запускаются два xterm и посредством использования xv устанавливается фон рабочего стола. Затем вьщается команда wait, вызывающая ожидание завершения обработки $WINM. В этом случае WINM - идентификатор процесса Window Manager, другими словами, после закрытия Window Manager .xsession прерывается и осуществляется выход из системы.

Перемещение фоновых задач на передний план

Команда fg используется для перемещения фоновых задач на передний план. Выполнение на переднем плане предполагает интерактивную обработку с использованием терминала. Следовательно, использование команды fg для вызова на передний план нескольких задач создает условия гонки; выигрывает та задача, которая добирается до терминала первой, а остальные переводятся в состояние Stopped на заднем плане. Синтаксис команды fg следующий:

fg [ job ... ]

В качестве параметра job указывается один или несколько идентификаторов процессов или ссылок на задачи. Если параметр job опускается, текущий фоновый процесс перемещается на передний план. Текущая задача - это задача, остановленная или запущенная последней.

Необходимость использования команды fg часто является результатом действий, предпринимаемых самим пользователем. Предположим, что выполняется редактирование текстового файла с помощью редактора vi, и при попытке сохранить файл и выйти из редактора выясняется, что нет права доступа для записи в файл. Невозможно сохранить файл, пока не будут изменены условия, но в настоящий момент пользователь заперт внутри редактора. Что делать?

Во-первых, остановить сеанс редактора vi путем нажатия Ctrl-Z. Немедленно будет получен следующий вывод на консоль:

[1] Stopped vi char2.nr $

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

$ ls -1 chap2.nr

-r-r-r- 1 barbara user 21506 May 5 10:52

$ chmod u+w chap2.nr

$ ls -1 chap2.nr

-rw-r-r- 1 barbara user 21506 May 5 10:52

И наконец, необходимо использовать команду fg для повторного вызова сеанса редактирования vi, в настоящий момент приостановленного на заднем плане:

$ fg %vi Для обновления экрана может потребоваться ввод Ctrl-L (команда редактора vi).

Перемещение задач с переднего плана в фон

Команда bg используется для помещения задач, в данный момент находящихся в состоянии Stopped (что указывается командой jobs), в фоновый режим и возобновления выполнения. Обратите внимание, что задача немедленно переключается обратно в состояние Stopped, если она требует ввода с терминала. Синтаксис команды bg следующий:

bg [ job ]

В качестве параметра job указывается один или несколько идентификаторов процессов или ссылок на задачи. Если параметр job опускается, команда относится к текущей задаче, которой является последняя запущенная или остановленная задача.

На практике команда bg не используется для перемещения задач переднего плана в фон, поскольку нет способа выполнения этого; оболочка не обращает внимания на терминал, пока выполняется задача переднего плана. Для привлечения внимания оболочки во время выполнения команды переднего плана необходимо использовать Ctrl-Z, чтобы остановить (приостановить) задачу переднего плана.

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

Предположим, что посредством команды troff было запущенное длительное форматирование текстового файла:

$ troff -me chapl.nr > chapl.trf

Если после нескольких минут ожидания завершения задачи вьысняется, что вместо простого бездействия требуется выполнить что-либо еще, можно использовать следующую последовательность для переключения команды troff на выполнение в фоновом режиме:

[ctrl-z] $ bg $

По умолчанию оболочка считает, что имеется в виду последняя остановленная задача. Теперь, когда команда troff выполняется в фоновом режиме, можно выполнить другую работу.

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

$ troff -me chapl.nr > chapl.trf &

Резюме

В этой главе представлены свойства оболочки Коrn. Поскольку оболочка Коrn обладает многими свойствами, общими с оболочкой Bourne, здесь освещались только свойства, уникальные для Коrn.

Оболочка Коrn - одна из нескольких оболочек, доступных в большинстве современных версий операционной системы UNIX. Это более новая, улучшенная версия первоначальной оболочки Bourne, имеющая историю команд, редактирование команд, командные псевдонимы и управление задачами, и предназначена для увеличения производительности работы за клавиатурой. Оболочка Коrn также предоставляет ряд усовершенствований для разработчиков сценариев оболочки, включая арифметические переменные и арифметические выражения, переменные массивов, оператор select для предоставления пользователю меню и механизм сопроцессов для интерактивного выполнения других команд UNIX из сценария оболочки.

Первоначальным толчком для создания оболочки Коrn было желание предоставить пользователям многие усовершенствования оболочки csh в формате, совместимом с синтаксисом и поведением оболочки Bourne. Оболочка С (csh) была реализована группой Berkeley и первоначально предлагалась только в варианте BSD системы UNIX. Оболочка Коrn перенесла многие ее расширения и многие дополнительные усовершенствования в среду System V. Многие считают оболочку Korn наследницей оболочек Bourne и С.

Свойство истории команд позволяет сохранять в дисковом файле список всех выполнявшихся команд. Файл сохраняется между входами в систему, поэтому при следующем входе в систему можно получить некоторое представление о предыдущем сеансе. Файл истории команд можно использовать для справки или для повторного выполнения команд. При повторном выполнении команды можно использовать ее в первоначальном виде или изменить перед выполнением. Команда fc и псевдонимы history и r обеспечивают интерфейс пользователя к файлу истории команд.

Свойство редактирования команд обеспечивает два стиля текстового редактирования для редактирования команд при их создании. Для использования редактирования команд необходимо явно его активизировать. По умолчанию оболочка Korn обрабатывает командную строку так же, как оболочка Bourne. Режим vi реализует большинство режимов ввода и команд редактора vi и предоставляет возможность доступа и повторного использования команд, сохраненньк в файле истории команд. Режим EMACS совместим с командами редактора EMACS. Большинство пользователей находят режим редактирования команд vi или EMACS более естественным в сравнении с использованием восклицательных знаков (!) в оболочке С.

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

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

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

Команда typeset обеспечивает набор новых свойств, связанных с использованием переменных оболочки. Переменные массива в форме ${name<?[n]} допускают удобную обработку списков. Целые переменные, определенные командой typeset, команда let и запись выражения (( )) дают возможность выполнять основные численные вычисления, не покидая среды оболочки. Больше не нужно прибегать к подстановке команды eхрr или be.

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

Сопроцессы, новое свойство оболочки, позволяют выполнять считывание и запись из фоновых команд, используя их интерактивным образом. Можно отвечать на сообщения об ошибках, созданные вызванной командой, и можно давать запрограммированный ответ. Сопроцесс запускается операцией |&, используемой вместо символа &. Будучи запущен, сопроцесс выполняется параллельно с процессом оболочки. Для записи в команду используется команда print -p. Для считывания ее ввода используется read -p. Можно переназначить каналы ввода и вывода, используя специальные команды exec fd>&p и exec fd<&p. Теперь разработчики сценариев могут делать вещи, доступные ранее только в языке программирования С.

Еще одно преимущество - режим привилегированной оболочки (Privileged shell). В сценариях оболочки можно устанавливать флаги Set User ID и Set Group ID. Можно использовать опции set privileged или set -p для переключения между реальным и действующим идентификатором пользователя. Это свойство используется для создания специальных системных служб - например, системы управления библиотекой записей на ленте, поддержки распределения устройств или системы совместного использования файлов. Однако не забывайте соблюдать осторожность: небрежно написанные сценарии могут открыть двери потенциальным злоумышленникам к материалам более привилегированных пользователей.

И последнее, но немаловажное - оболочка Коrn позволяет обойти проблему невозможности экспортирования псевдонимов и функций. Посредством использования экспортируемой переменной ENV можно определить минипрофиль, подлежащий выполнению при каждом вызове оболочки. Больше не нужно переключаться в оболочку из vi, pg или sdb только для того, чтобы обнаружить один лишь скелет среды, лишенный любимых псевдонимов и функций.

Короче говоря, оболочка Коrn кажется почти последним словом в средах командной строки. Вопрос в том, позволят ли ограничения совместимости использовать оболочку Коrn для написания сценариев. Хотя оболочка Коrn может выполнять сценарии оболочки Bourne, оболочка Bourne не может выполнять сценарии оболочки Коrn, а оболочка С может выполнять сценарии только оболочки С. По крайней мере, можно спокойно использовать оболочку Коrn в качестве интерактивной среды, что, безусловно, является шагом вперед!

Back

К оглавлению