Пользователи системы



страница24/42
Дата01.12.2017
Размер5.38 Mb.
ТипПрограмма
1   ...   20   21   22   23   24   25   26   27   ...   42

Язык программирования sh


Некогда Мефодий выучил несколько языков программирования, и уже собрался было написать кое-какие нужные программы на Си или Python, однако Гуревич его остановил. Большая часть того, что нужно начинающему пользователю Linux, делается с помощью одной правильной команды, или вызовом нескольких команд в конвейере. От пользователя только требуется оформить решение задачи в виде сценария на shell. На самом же деле уже самый первый из командных интерпретаторов, sh, был настоящим высокоуровневым языком программирования - если, конечно, считать все утилиты системы его операторами. При таком подходе от sh требуется совсем немного: возможность вызывать утилиты, возможность свободно манипулировать результатом их работы и несколько алгоритмических конструкций (условия и циклы).

К сожалению, программирование на shell, а также других, более мощных интерпретируемых языках в Linux, остается за рамками нашего курса. Так что, пока Мефодий читает документацию по bash и упражняется в написании сценариев, нам остается только поверхностно рассмотреть свойства shell как языка программирования и интегратора команд. Заметим попутно, что писать сценарии для bash - непрактично, так как исполняться они смогут лишь при помощи bash. Если же ограничить себя рамками sh, совместимость с которым объявлена и в bash, и в zsh, и в ash (наиболее близком по возможностям к sh), и в других командных интерпретаторах, выполняться эти сценарии смогут любым из sh-подобных интерпретаторов, и не только в Linux.


Интеграция процессов


Каждый процесс Linux при завершении передает родительскому код возврата (exit status), который равен нулю, если процесс считает, что его работа была успешной, или номеру ошибки - в противном случае. Командный интерпретатор хранит код возврата последней команды в специальной переменной "?". Что более важно, код возврата используется в условных операторах: если он равен нулю, условие считается выполненным, а если нет - невыполненным:

[methody@localhost methody]$ grep Methody bin/script

echo 'Hello, Methody!'

[methody@localhost methody]$ grep -q Methody bin/script ; echo $?

0

[methody@localhost methody]$ grep -q Shogun bin/script ; echo $?



1

[methody@localhost methody]$ if grep -q Shogun bin/script ; then echo "Yes"; fi

[methody@localhost methody]$ if grep -q Methody bin/script ; then echo "Yes"; fi

Yes


Пример 8.14. Оператор if использует код возврата программы grep (html, txt)

Условный оператор if запускает команду-условие, grep -q, которая ничего не выводит на экран, зато возвращает 0, если шаблон найден, и 1, если нет. В зависимости от кода возврата этой команды, if выполняет или не выполняет тело: список команд, заключенный между then и fi. Точка с запятой разделяет операторы в sh; либо она, либо перевод строки необходимы перед then и fi, иначе все, что идет после grep, интерпретатор посчитает параметрами этой утилиты.

Множеством функций обладает команда test: она умеет сравнивать числа и строки, проверять ярлык объекта файловой системы и наличие самого этого объекта. У "test" есть второе имя: "[" (как правило, /usr/bin/[ - символьная или даже жесткая ссылка на /usr/bin/test), позволяющее оформлять оператор if более привычным образом:

[methody@localhost methody]$ if test -f examples ; then ls -ld examples ; fi

[methody@localhost methody]$ if [ -d examples ] ; then ls -ld examples ; fi

drwxr-xr-x 2 methody methody 4096 Окт 31 15:26 examples

[methody@localhost methody]$ A=8; B=6; if [ $A -lt $B ] ; then echo "$A<$B" ; fi

[methody@localhost methody]$ A=5; B=6; if [ $A -lt $B ] ; then echo "$A<$B" ; fi

5<6


Пример 8.15. Оператор test (html, txt)

Команда test -f проверяет, не является ли ее аргумент файлом; поскольку examples - это каталог, результат будет неудачным. Команда [ -d - то же самое, что и test -d (не каталог ли первый параметр), только последнимпараметром этой команды - исключительно для красоты - должен быть символ "]". Результат - успешный, и выполняется команда ls -ld. Команда test параметр1 -lt параметр3 проверяет, является ли параметр1 числом, меньшим, чем (less than) параметр3. В более сложных случаях оператор if удобнее записывать "лесенкой", выделяя переводами строки окончание условия и команды внутри тела (их может быть много).

Второй тип подстановки, которую shell делает внутри двойных кавычек - это подстановки вывода команды.Подстановка вывода имеет вид "`команда`" (другой вариант - "$(команда)"). Как и подстановка значения переменной, она происходит перед тем, как начнется разбор командной строки: выполнив команду и получив от нее какой-то текст, shell примется разбирать его, как если бы этот текст пользователь набрал вручную. Это очень удобное средство, если то, что выводит команда, необходимо передать самому интерпретатору:

[methody@localhost methody]$ A=8; B=6

[methody@localhost methody]$ expr $A + $B

14

[methody@localhost methody]$ echo "$A + $B = `expr $A + $B`"



8 + 6 = 14

[methody@localhost methody]$ A=3.1415; B=2.718

[methody@localhost methody]$ echo "$A + $B = `expr $A + $B`"

expr: нечисловой аргумент

3.1415 + 2.718 =

[methody@localhost methody]$ echo "$A + $B" | bc

5.8595

[methody@localhost methody]$ C=`echo "$A + $B" | bc`



[methody@localhost methody]$ echo "$A + $B = $C"

3.1415 + 2.718 = 5.8595



Пример 8.16. Подстановка вывода команды (html, txt)

Сначала для арифметических вычислений Мефодий хотел воспользоваться командой expr, которая работает с параметрами командной строки. С целыми числами expr работает неплохо, и ее результат можно подставить прямо в аргумент команды echo. С действительными числами умеет работать утилита-фильтр bc; арифметическое выражение пришлось сформировать с помощью echo и передать по конвейеру, а результат поместить в переменную C. Во многих современных командных оболочках есть встроенная целочисленная арифметика вида "$(( выражение ))".


Сценарии


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

[methody@localhost methody]$ cat > bin/two

#!/bin/sh

echo "Running $0: $*"

$1 $3

$2 $3


[methody@localhost methody]$ chmod +x bin/two

[methody@localhost methody]$ bin/two file "ls -ld" examples

Running bin/two: file ls -ld examples

examples: directory

drwxr-xr-x 2 methody methody 4096 Окт 31 15:26 examples

[methody@localhost methody]$ two "ls -s" wc "bin/two bin/loop" junk

Running /home/methody/bin/two: ls -s wc bin/two bin/loop junk

4 bin/loop 4 bin/two

4 9 44 bin/two

1 5 26 bin/loop

5 14 70 итого

Пример 8.17. Использование позиционных параметров в сценарии (html, txt)

Как видно из примера, форма "$номер_параметра" позволяет обратиться и к нулевому параметру - команде, а вся строка параметров хранится в переменной "*". Кроме того, свойство подстановки выполняться до разбора командной строки позволило Мефодию передать в качестве одного параметра "ls -ld" или "bin/two bin/loop", а интерпретатору - разбить эти параметры на имя команды и ключи и два имени файла соответственно.

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

[methody@localhost methody]$ for Var in Wuff-Wuff

Miaou-Miaou; do echo $Var; done

Wuff-Wuff

Miaou-Miaou

[methody@localhost methody]$ for F in `date`; do echo -n "<$F>"; done; echo



<Сбт><Ноя><6><12:08:38><2004>

[methody@localhost methody]$ cat > /tmp/setvar

QWERTY="$1"

[methody@localhost methody]$ sh /tmp/setvar 1 2 3; echo $QWERTY

[methody@localhost methody]$ . /tmp/setvar 1 2 3; echo $QWERTY

1

Пример 8.18. Использование for и операции "." (html, txt)

Во втором for Мефодий воспользовался подстановкой вывода команды date, каждое слово которой вывел с помощью echo -n в одну строку, а в конце команды пришлось вывести один перевод строки вручную.

Вторая половина примера иллюстрирует ситуацию, с которой Мефодий столкнулся во время своих экспериментов: все переменные, определяемые в сценарии, после окончания его работы куда-то пропадают. Оно и понятно: для обработки сценария всякий раз запускается новый интерпретатор (дочерний процесс!), и все его переменные принадлежат именно ему и с завершением процесса уничтожаются. Таким образом достигается отсутствиепобочных эффектов: запуская программу, пользователь может быть уверен, что та не изменит окружениякомандной оболочки. Однако в некоторых случаях требуется обратное: запустить сценарий, который нужным образом настроит окружение. Единственный выход - отдавать такой сценарий на обработку текущему, а не новому, интерпретатору (т. е. тому, что разбирает команды пользователя). Это делается с помощью специальной команды ".". Если вдруг в передаваемом сценарии обнаружится команда exit, exec или какая-нибудь другая, приводящая к завершению работы интерпретатора, завершится именно текущая командная оболочка, чем сеанс работы пользователя в системе может и закончиться.





Поделитесь с Вашими друзьями:
1   ...   20   21   22   23   24   25   26   27   ...   42


База данных защищена авторским правом ©vossta.ru 2019
обратиться к администрации

    Главная страница