Документация по ОС FreeBSD Суббота, 20.04.2024, 01:15
Приветствую Вас Гость | RSS
Меню сайта

Категории каталога
Shell [40]

Главная » Статьи » Программирование » Shell

Оболочки
Программы-оболочки.

В той статье мы поговорим о неотъемлемой части пользовательского интерфейса Linux – о программах-оболочках. Именно программа-оболочка запускается после регистрации пользователя в системе. Программы-оболочки часто называют командными интерпретаторами, потому что они обрабатывают (интерпретируют) команды, введенные пользователем. Во времена DOS этим занимался файл C:command.com.
В файле /etc/passwd для каждого пользователя указывается, какую оболочку он будет использовать.

root:x:0:0:root:/root:/bin/bash
den:x:501:501:Denis:/home/den:/bin/bash

Из листинга видно, что оба пользователя используют оболочку /bin/bash. Оболочка, как правило, указывается в последнем поле файла passwd.
Список всех установленных в системе программ-оболочек содержится в файле /etc/shells. У меня он выглядит так:

Листинг 1.

/bin/sh
/bin/bash
/bin/ash
/bin/bsh
/bin/tcsh
/bin/csh
/bin/zsh

На любой Unix-системе, даже на самой старой, вы можете увидеть, по крайней мере, два интерпретатора из этого списка: sh, csh. Названия, как вы догадались, исходят от слова shell – оболочка. Csh – это оболочка, использующая командный язык, напоминающий язык программирования C. В ОС Linux по умолчанию используется оболочка bash (Bourne Again Shell). Bash является более «продвинутой» версией обыкновенной оболочки sh.
Все оболочки выполняют одну и туже функцию – интерпретируют команды пользователя. Например, когда вы вводите команду

$ program -s /etc/passwd

Интерпретатор запустит программу program и передаст ей два (точнее три)параметра: первый – это -s, второй – это /etc/passwd. А что делать с этими параметрами разберется сама программа. Я что-то говорит о третьем параметре? Существует еще один так называемый нулевой параметр. Этот параметр содержит полное имя файла программы. Например, если наша программа находится в каталоге /bin, то нулевой параметр будет содержать значение /bin/program.
Обратите внимание на знак доллара возле команды. Это признак того, что сейчас мы работаем как обыкновенный пользователь. Если мы зарегистрируемся как пользователь root (суперпользователь), то знак доллара измениться на решетку – #.
Отличием каждой программы-оболочки является ее командный язык. Вот поэтому одни пользователи предпочитают использовать bash, а другие – tcsh. Командные языки некоторых оболочек очень похожи, например, sh и bash, csh и tsch.
Командный язык используется для создания сценариев. Сценарий – это последовательность команд, которую должен выполнить интерпретатор команд. Пример простейшего сценария (командный язык bash):

Листинг 2.

#!/bin/bash
echo -n "Enter your name"
read name
echo "Hello, $name"

Для определенности скажем, что мы сохранили этот сценарий под именем script1. Чтобы мы могли выполнить этот сценарий нужно сделать этот файл исполнимым (например, с помощью команды chmod 550 ./script1) и ввести команду (я предполагаю, что вы создали этот файл в текущем каталоге):
./script1

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

/bin/bash ./script1

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

#!/usr/bin/myshell -option

При запуске сценария, в первой строке которого стоит такая команда, интерпретатор выполнит команду:
/usr/bin/myshwll -option <имя_файла_сценария>

Обратите внимание на первую строку сценария script1
#!/bin/bash
Это указание программы для обработки этого сценария. Если же вы напишете
# !/bin/bash
то это будет уже обыкновенным комментарием и система не сможет выполнить ваш сценарий, поскольку не будет знать, какую программу-оболочку нужно использовать. В лучшем случае, если сейчас активным является интерпретатор, на языке которого написан сценарий, файл все-таки будет выполнен, а в другом случае вы получите сообщение об ошибке. Например, если вы написали сценарий на bash, не указав (или неправильно указав) интерпретатор, и пытаетесь выполнить его при запущенном интерпретаторе csh, то получите сообщение о синтаксической ошибке.

Интерпретатор bash

В этой статье я рассмотрю оболочку bash, которая стандартна для большинства систем. Однако сам командный язык подробно разобран не будет из-за его объемности. Итак, начнем по порядку с регистрации пользователя. Как я уже отмечал, после успешной аутентификации пользователя, запускается программа-оболочка (в нашем случае это /bin/bash). При запуске оболочки выполняются некоторые действия. Эти действия определены в файле ~/.bash_profile (см. листинг 3).

Листинг 3.

# .bash_profile
# Get the aliases and functions
if [ -f ~/.bashrc ]; then
~/.bashrc
fi
# User specific environment and startup programs
PATH=$PATH:$HOME/bin
BASH_ENV=$HOME/.bashrc
USERNAME="user"
HISTIGNORE=" [ ]*:&:bg:fg"
export USERNAME BASH_ENV PATH HISTIGNORE
clear

Файл .bash_profile представляет собой обыкновенный сценарий. Теперь разберемся, какие действия выполняет этот сценарий. В этом файле определяются переменные окружения и программы, которые должны запускаться автоматически. В листинге 3 сначала проверяется существование файла .bashrc и, если он существует, интерпретатор выполняет его. Файл .bashrc рассмотрим немного позже. Затем устанавливаются переменные окружения: PATH, BASH_ENV, USERNAME, HISTIGNORE. Первая задает путь для поиска программ, вторая определяет среду интерпретатора (файл .bashrc), третья устанавливает имя пользователя, а последняя относится к истории команд, введенных пользователем. Затем переменные экспортируются. Дело в том, что переменные локальны в рамках сценария. При экспорте переменных их значение будет доступно порожденным процессам. Например, создайте такие два сценария (см. листинги 4 и 5).

Листинг 4.

#!/bin/bash
MYVAR="My var"
export MYVAR
./listing5

Листинг 5

#!/bin/bash
echo "$MYVAR"

Запустите сценарий ./listing4. Он экспортирует переменную MYVAR и запустит сценарий listing5, которые выведет значение переменной MYVAR («My var») на экран. Теперь закомментируйте строку:
export MYVAR
в сценарии listing4 и запустите его снова. На экране значение переменной MYVAR не будет отображено.
Теперь вернемся к файлу .bashrc, а потом перейдем к командному языку оболочки bash.

Листинг 6

# .bashrc
# User specific aliases and functions
alias rm='rm -i'
alias mv='mv -i'
alias cp='cp -i'
alias s='cd ..'
alias d='ls'
alias p='cd -'
# Need for a xterm & co if we don't make a -ls
[ -n $DISPLAY ] && {
[ -f /etc/profile.d/color_ls.sh ] && source /etc/profile.d/color_ls.sh
export XAUTHORITY=$HOME/.Xauthority
}
# Read first /etc/inputrc if the variable is not defined, and after
the /etc/inputrc
# include the ~/.inputrc
[ -z $INPUTRC ] && export INPUTRC=/etc/inputrc
# Source global definitions
if [ -f /etc/bashrc ]; then
. /etc/bashrc
fi

Здесь задаются определенные установки. В основном данные установки необходимы для удобства пользователя. Например, определяются псевдонимы команд (alias).
Оболочка bash использует еще один командный файл – .bash_logout. В этом файле указываются действия, которые нужно выполнить при выходе из интерпретатора, то есть выхода из системы.

Командный язык bash. Переменные.

Обязательным атрибутом переменной в любом языке программирования является тип значения переменной. В командном языке bash все переменные текстовые. Например, если вы присваиваете переменной значение A=23, то значением переменной будет строка из двух сиволов – «23».
Имя переменной должно начинаться с буквы и может состоять из латинских букв, цифр, знака подчеркивания.
Оператор присваивания в bash выглядит так:
<имя переменной>=значение.
Например,

NAME=Ivan

Если нужно присвоить значение, содержащее пробелы, нужно использовать кавычки:

NAME="Ivan Ivanov"

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

echo "NAME"
echo "$NAME"

Первая команда выведет на экран слово NAME, а вторая – значение переменной NAME (Ivan Ivanov). Если значение переменной может содержать пробелы, имя переменной нужно заключить в кавычки. Например,

NAME="Ivan Ivanov"
echo $NAME
echo "$NAME"

Первая команда echo выведет на экран слово Ivan, а вторая – Ivan Ivanov.
Интерпретатор bash использует такие метасимволы, имеющее для него особое значение:
* ? ; & ( ) | ^ < > <возврат_каретки> <табуляция> <пробел&qt;
Для того, чтобы использовать эти символы как они есть, нужно их цитировать с помощью символа . Например, символ перевода строки можно цитировать так n, символ табуляции – t, символ вопроса – ?
Особое значение при присваивании переменным значений имеют кавычки. Все символы, заключенные в одинарные кавычки ‘ ’ представляют самих себя. Между двойными кавычками “ ” выполняются команды и подстановки значений.
Символы “”, “,”, “ ‘ ”, “ $ “ могут цитироваться с помощью обратной наклонной черты: \, $, ’

Массивы.

Оболочка bash поддерживает одномерные массивы с неограниченным числом элементов. В других интерпретаторах существуют определенные ограничение на массивы, например, в ksh максимальное число элементов массива ограничено 1024-мя элементами.
Присвоить значение элементу массива можно с помощью такой конструкции:

Имя_массива[индекс]=значение

Например

Array[1]=23
Array[3]=54
Array[0]=77

Нумерация элементов начинается с ноля. Тип элементов массива, как и тип переменных, текстовый.
Присвоить значение элементам массива можно также с помощью инструкции set. Например, выражение

set –A array 3 56 77 12

Аналогично выражениям

array[0]=3
array[1]=56
array[2]=77
array[3]=12

Обратиться ко всем элементам массива сразу можно так:
${array[@]}, где array – имя массива.
Например, echo ${array[@]}

Специальные переменные.

Каждому процессу доступны переменные оболочки, приведенные в таблице 1.

Таблица 1
Специальные переменные Переменная Значение
HOME Домашний каталог
MAIL Имя файла, в который поступает электронная почта
LOGNAME Имя пользователя, которое использовалось для входа в систему
PATH Путь вызова
SHELL Имя интерпретатора команд
PWD Текущий каталог
UID Идентификатор пользователя, запустившего сценарий
RANDOM Случайное число в диапазоне от 0 до 32767
SECONDS Число секунд, прошедшее с момента запуска оболочки

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

Таблица 2.
Переменная Значение
$0 Имя выполняемой команды. Для сценария – путь, указанный при его вызове.
$1 Первый параметр, указанный при вызове сценария. Аналогично, $2 – второй, $n – n-ый параметр.
$# Число параметров, которые были указаны при вызове сценария.
$* Все параметры, заключенные в кавычки: “$1 $2 ...”
$? Код завершения последней команды
$$ Номер текущего процесса (PID)

Арифметические выражения

Подстановка арифметических выражений осуществляется с помощью конструкции

$(( выражение ))

Например,

N = $(( (10+5)/2 ))
echo $N

На экране вы увидите 3, а не 3,5, потому что интерпретатор bash использует целочисленные вычисления.
Количество часов, прошедшее с момента запуски оболочки можно вычислить так:
hrs = $(( $SECONDS/3600 ))

Подстановка переменных. Подстановка значений.

Интерпретатор bash предоставляет нам довольно гибкий механизм подстановки переменных. При этом переменная будет использоваться не всегда, а в зависимости от определенных обстоятельств. (см. таблицу 3).

Таблица 3.
${переменная:=значение} Значение присваивается переменной, если она не определена или является пустой строкой.
${переменная:?сообщение} Если переменная не определена или является пустой строкой, выводится сообщение
${переменная:+значение} Если переменная инициализирована (определена), вместо нее используется указанное в конструкции значение. (*)
${переменная} Если переменная определена, подставляется ее значение. Скобки используются лишь для того, если после переменной стоит символ, который может «приклеиться» к имени переменной.
${переменная:-значение} Если переменная определена и не является пустой строкой, подставляется ее значение, иначе подставляется значение, указанное в конструкции. (*)

(*) Реальное значение переменной не изменяется.
Пример: ${2 :? “Не хватает второго параметра”}

При подстановке команд нужно использовать обратные одинарные кавычки (они расположены под символом тильды на клавиатуре). Подставлять можно не только одну команду, а целые списки команд:

USERS=‘who | wd –l‘
UP=‘date; uptime‘
I=‘whoami‘

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

grep ‘id –un‘ /etc/passwd

Управляющие структуры.

К управляющим структурам относятся:
1. Конструкция if-fi
2. Конструкция case-esac

Общий синтаксис конструкции if-fi

if список1 then
список2
elif список3 then
список4
else
список5
fi

Конструкция if-fi работает так же, как и в других языках программирования.Если список1 (условие) истинный, выполняется список2, иначе выполняется список3 и проверяется его истинность и т.д. Допускается неограниченная вложенность операторов if.
Список – это список команд. Разделителем команд служит символ «;». Список обязательно должен заканчиваться точкой с запятой. Пример списка: ls; dir; cat file;
При программировании на bash есть один подводный камень, относящийся к логическим выражениям. В других языках программирования выражение «истина» обозначается как «true», а «ложь» – как «false». В языке C с выражением «ложь» сопоставляется нулевое значение переменной, а за истину принимается любое ненулеое значение. В bash все немного по-другому. За истину в конструкции if принимается 0, так как 0 – это код нормального завершения программы (команды). Правильнее конструкцию if трактовать так: если код завершения списка команд, задающего условие в конструкции if, равен 0, то будет выполнен список2. Код завершения последней команды можно узнать с помощью переменной $?.
Например,
if [ $? -ne 0 ]; then echo "Ошибка. См. файл протокола"; fi;
В этом примере мы проверяем код завершения последней команды. Если он не равен нулю (-ne), мы выводим сообщение об ошибке. Кроме опции -ne можно использовать такие опции:

-eq – равно
-lt – меньше
-gt – больше
-le – меньше или равно
-ge – больше или равно
Сравнение строк:
= – равно
!= – не равно
Символ "!" является символом логической операции NOT (отрицание). Кроме этого символа, можно использовать опции команды -o и –a, которые обозначают логические операции ИЛИ (OR) и И (AND).
Проверить существование файла можно опцией -e, а существование каталога - d.
Все эти опции являются параметрами программы test. Другими словами, вместо квадратных скобок вы можете использовать команду test, поэтому следующие выражения аналогичны

test –e /etc.passwd
[-e /etc/passwd]

Cинтаксис блока выбора (case – выбор):

case значение in
шаблон1) список1 ;;
...
шаблонN) списокN ;;
esac

Работает этот блок почти также, как в языке С. Однако есть небольшая разница: если найдено совпадение с каким-нибудь шаблоном (например, шаблонN-2) и выполнен соответствующий список команд списокN-2, осуществляется выход из блока. В языке С для достижения этого эффекта нужно было использовать оператор break, иначе выполнялись вы все списки после спискаN-2: списокN-1, списокN.
Вместо дейтсвия по умочанию нужно использовать шаблон *). Этот шаблон будет использоваться, когда не найдено совпадение ни с одним из шаблонов. Например,
case $A in
1) echo "A=1";;
2) echo "A=2";;
*) echo "A<>1 and A<>2";;
esac

Циклы.

Интерпретатор bash поддерживает циклы for, while, until, select, а интерпретатор sh только for и while.
В этой статье я рассмотрю только первые два цикла – for и while.

Синтаксис цикла for:

for имя_переменной in список1
do
список2
done

Простой пример:

for i in 1 2 3 4 5; do echo $i; done

На экране вы увидите
1 2 3 4 5
Еще раз напомню, что любой список в bash должен заканчивать точкой с запятой.
Построчно вывести содержимое файла file.txt мы можем с помощью такого цикла

for str in ‘cat ./file.txt‘
do
echo "$str";
done

Цикл for закончит свою работу, когда будет обработан последний элемент списка, в данном случае, когда на экран будет выведена последняя строка файла file.txt

Синтаксис цикла while:

while список1
do
список2
done

Цикл while будет выполняться, пока условие, заданное в списке список1, будет истинным. Поэтому цикл while иногда называют циклом с истинным условием. Например,

a=1
while [$a –lt 10]
do
echo $a
a = $(( $a + 1 ))
done

На экране вы увидите:
1 2 3 4 5 6 7 8 9
Когда переменная a примет значение 10, цикл завершит свою работу, так как программа test вернет значение false (a уже не меньше, а равен 10).

Подоболочки

Рассмотрим два почти аналогичных сценария

#!/bin/bash
# Сценарий 1
NUM=”one”; (NUM=”two”; echo $NUM;);
echo $NUM

#!/bin/bash
# Сценарий 2
NUM=”one”; {NUM=”two”; echo $NUM;};
echo $NUM

Сценарий 1 выведет на экран следующую информацию:

two
one

А сценарий 2

two
two

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

Aвтор: Денис Колисниченко
Категория: Shell | Добавил: oleg (25.11.2007)
Просмотров: 2481 | Рейтинг: 0.0/0 |
Всего комментариев: 0
Добавлять комментарии могут только зарегистрированные пользователи.
[ Регистрация | Вход ]
Форма входа

Beastie

Друзья сайта

Статистика

Онлайн всего: 1
Гостей: 1
Пользователей: 0
links

Copyright MyCorp © 2024