Краткий обзор шелла как ЯП

Нынче немодно говорить, что шелл --- полный ЯП, а BAT --- неполный. Говорят, что CMD полный.

Поговорим про то, что такое скрипт --- сценарий с т. з. юних систем. Уже говорилось, что в юних, а в след за ним и в линух свойство файла быть запускаемым опр. специальным режимом доступа (использование). При этом этот файл внутри себя может быть как бинарником, а может быть и текстовым. Для вып. этого файла запускается интерпретатор, который его интерп. По умолчанию этот интерпретатор --- шелл. Именно поэтому, когда говорят скрипт, имеют в виду шеллскрипт. Это искл, которому доверять не надо. В линух принято след. правило: сценарий --- файл, который начинается с #!<интерпретатор>/ "то первая строка файла, например #!/bin/sh. Эта строчка позволяет системе решить,что этот файл должен исполняться соотв. интерпретатором. Запустили prog 1 2 3, а у prog написано #!/bin/sh, то запустится на самом деле /bin/sh prog 1 2 3, причём шелл делает так, что список аргументов начинается с prog. На самом деле, скрипты пишутся на чём угодно: perl, python, ..., лишь бы интерпретатор проигнорировал sha-bang (эту самую первую строчку). Отсюда замечательное свойство --- во многих языках строка с решётки --- комментарий. Ещё одно свойство --- сказав chmod +x, сделал из скрипта программу.

Практически на тех же правах, что и перем. окруж, определяется куча пареметров разных, в том числе для работы ... . Переменная $0 будет соотв. нулевому аргументу, $1 --- первому, и так далее до 9. Ещё есть такая команда shift, которая без параметров производит сдвижку на 1 параметр вправо (2 в 1, 3 в 2, ..., 10 в 9). Зачем это нужно: у вас там флаги, потом имена файлов. Вы флаги прошифтили, а дальше только имена файлов, можно обрабатывать их в цикле. $* --- строка целиком. $@ тоже содержит строку целиком, заведена она для того, чтобы операцию подстановки внутри кавычек. Разница при квотировании: "$*" --- одна большая строка ("$1 $2 $3"), а результатом "$@" будут отдельные параметры ("$1" "$2" "$3"). Если посмотреть на $@ то кажется, что это специфическая, контексно-зависимая штука, потому что работает иначе, но пользоваться этим удобно. Что ещё есть: $# --- количество параметров командной строки.

  • $_ --- последняя введённая польз. строка
  • $$ --- pid запущенного процесса.
  • $! --- pid последнего из процессов, запущенных в фоне

Списки

Списки --- списки команд. Если захотелось, чтобы несколько команд работало вместе, например, чтобы они выводили в один файл. Можно сделать

 cmd1 > f
 cmd2 >> f
 ...

а можно сделать

 {cmd1; cmd2;} > f

Про скобки: можно рассматривать их как операторные скобки. Одно из свойств фигурных скобок состоит в том, что ввод-вывод объединяется. Если для того, чтобы запустить эти команды, не надо запусктаь отдельного шелла, то они выполн. в текущем. Но если нужно, то запускаются отдельно: echo ... | read A, то ... .Если же записать круглые скобки: (cmd1; cmd2) > f, то обязательно запускается отдельный шелл. Этод удобно для того, чтобы понаопределять переменных, а потом всё забыть

Условный оператор

 if <список>; then <список>; [else <список>;] fi

Точки в запятыми обязательными, чтобы шелл не посчитал then очередным параметров. Встаёт вопрос, когда выполняется then, в других else. Все мы знаем,что 0 --- ложь, всё остальное --- истина. В типизированных языках есть специальный тип. Шелл заточен под работу с программами, поэтому он использует exit status. Программа по завершении возвращает exit status. Существует ячейка, которую программа по окончанию работы она заполняет всегда. Код завершения последней запущенной программы лежит в $?. На exit status распрост. след правило: если он равен 0, то программа заверш. успешно, иначе рпограмма завершилась ошибкой с кодом exit status. Условная команда в шелл выаолн. список команд, и елси он выполняется успешно, то выполняется then, иначе else. Как опр. код заверш. в списке --- по последней команде. Если код завершения --- 0, то выполняется then, иначе else.

Два амперсенда --- более короткий способ записи условного оператора. Последовательность команд может быть объединена не точками с запятыми, а && или ||. Те, кто программировал в си, знает, что там ленивое вычисление лог. выр. В шелле в a || b b выполняется тогда, кгда a завершилдась неуспешно, в && наоборот.

Пример:

 test -r logfile && cat logfile || echo File not found

Цикл

 while <список>; do <список>; done

Есть break, continue. У каждой есть необязательный параметр, из скольки циклов выскочить. Более сложно устроен for.

 for <переменная> in <строка>; do <список>; done

Пример:

 for n in `ls`; do echo $n; done

Тут встречаемся с тем, что разделителем в том числе является и перевод строки

case

 case <список> in
   <шаблон>) список ;;
   ...
 esac

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

Функции

 <имя>()
 {
   ... $1 --- первый позиционный параметр функции
 }

trap

В шелле есть команда trap, которая позволяет перехватывать сигналы, посылаемые процессы. Синтаксис:

 trap <функция> сигнал

B тогда обработчик --- не система, а функция. Никаких специфич. парам. там нет. Единственное, среди списка сигналов есть специальное слово EXIT, которое словом не является, а является флагом выхода из скрипта, функция ыполняется после завершения скрипта. Для чего это нужно --- для того, чтобы удалять файлы, созданные mktemp, например. Делается это следующим образом: пишется функция, которая создаёт временный файл и добавляет его в переменную, написать

  onexit() { trap - EXIT; cleanfile}

Первым делом в ней нужно отключить обработку EXIT, иначе shell будет бесконечно этот обработчик вызывать.

ДЗ: привести пример, что можно, или доказать, что нельзя с использованием сигналов сделать очередь для диспетчеризации процессов на разные процессоры...


Сведения о ресурсах

Продолжительность (ак. ч.)

Подготовка (календ. ч.)

Полный текст (раб. д.)

Предварительные знания

Level

1

1

1

1


CategoryLectures CategoryCmc CategoryUneex