Linux и UNIX: программирование в shell. Руководство разработчика.

Тейнсли Дэвид

Часть 3

 

 

Регистрация в системе

 

ГЛАВА 13

 

Регистрация в системе

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

В этой главе рассматриваются следующие темы:

   • процесс регистрации

   • файл /etc/profile

   • файл $HOME/.profile

   • настройка пользовательского файла $HOME/.profile

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

[1] [ 2 ] [3] [4] [ 5 ] [ 6 ] [ 7 ]

kvp:JFqMmk9.uRioA:405:413:К.V. Pally:/home/sysdev/kvp:bin/sh dhw:hi/G4UlCUd9aI, B/OJ;407:401:D. Whitley:/home/dept47/dhw:/bin/sh aec:IL.gHtxJ9x. Xt, B/GI:408:401:A. E.Cloody:/b_user/dept47/aec:/bin/sh gdw:iLFu9BB8RNjpc, B/MK:409:401:G. D.Wiicom:/b_user/dept47/gdw:/bin/sh

Рассмотрим некоторые поля файла. Первое поле содержит регистрационное имя, второе поле — зашифрованный пароль, пятое поле — полное имя пользователя, шестое поле — начальный каталог данного пользователя, а седьмое поле описывает интерпретатор shell, применяемый пользователем. В данном случае параметр "/bin/sh" определяет интерпретатор shell, устанавливаемый по умолчанию. Обычно используется интерпретатор Bourne shell.

Существуют и другие типы файлов passwd. В одном из вариантов поле passwd фактически находится в другом файле. Однако приведенный выше формат является наиболее распространенным.

После успешной регистрации выполняются два файла среды. Первым является файл /etc/profile, а вторым — файл .profile, расположенный в начальном каталоге $HOME.

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

 

13.1. Файл /etc/profile

Информация файла профиля, находящегося в каталоге /etc, автоматически считывается при регистрации каждого пользователя. Этот файл обычно содержит: • глобальные или локальные переменные среды;

   • информацию о пути к файлам в переменной path;

   • параметры терминала; а также

   • меры безопасности;

а совет дня или сведения о причинах отказа.

Далее приводится краткое объяснение перечисленных выше пунктов.

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

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

Параметры терминала содержат наиболее общие характеристики используемого терминала.

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

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

Ниже приводится содержимое файла /etc/profile, который рассматривается далее.

$ pg /etc/profile

#!/bin/sh

#

trap "" 2 3

#Установка LOGNAME export LOGNAME

#установка дополнительных путей MAN MANPATH=/usr/opt/sybase/man

export MANPATH

# Установка TZ

if [ -f /etc/TIMEZONE ]

then

. /etc/TIMEZONE

fi

# Установка TERM

if [ -z "$TERM"]

then

TERM=vt220 # для стандартного асинхронного терминала/консоли

export TERM

fi

# Разрешение пользователю на прерывание отображения исключительно совета дня

trap "trap ' '2" 2

if [ -f /usr/bin/cat ] ; then

cat -s /etc/motd

fi

trap "" 2

if [ -f /usr/bin/mail]; then

if mail -e; then

echo "Hey guess what? you have mail"

fi

fi

#установка значения umask для более безопасного осуществления операций

umask 022

#установка сред

SY$HOME=/appdvb/menus

ASLBIN=/asl_b/bin

UDTKOME=/dbms_b/ud

UDTBIN=/dbms_b/ud/bin

PAGER=pg

NOCHKLPREQ=1

PATH=$PATH:$UDBIN:$ASLBIN

export PATH UDTHOME UDTBIN PAGER NOCHKLPREQ SY$HOME

trap 2 3

# Установка переменной SAVEDSTTY так, чтобы переменную можно было

# использовать для восстановления

# настроек stty при выходе из системы аудита.

SAVEDSTTY=`stty -g`; export SAVEDSTTY

# регистрация всех связей в syslog

logger -p lосаl7.info -t login $LOGNAME 'tty'

trap 'logger -p local7.info -t logout $LOGNAME 'tty'' 0

# отмена создания файлов дампа ядра

ulimit -с D

#

# проверка, зарегистрированы ли пользователи более двух раз, не считая…

case $LOGNAME in

idink | psalon | dave)

;;

*)

PID-$($); export PID

Connected=`who | awk '{print $1}' | fgrep -xc ${LOGNAME}`

if [ "$Connected" -gt 2 ]

then

echo

echo 'You are logged in more than twice.'.

echo `who -u | grep $LOGNAME`

echo

echo 'Enter to exit \c'

read FRED

kill -15 $PID

fi

;;

esac

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

P$1="$LOGNAME>"

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

Рассмотрим последовательно, какие действия выполняются в приведенном листинге.

Первая строка является командой, задающей перехват двух сигналов, которые не дают пользователям возможности прервать выполнение файла с помощью нажатия клавиш [Quit] или [Ctrl+C].

Затем экспортируется значение переменной LOGNAME. В данной системе введены дополнительные справочные страницы (страницы man). Переменная MANPATH вносит их в список поиска по страницам уже имеющегося справочного руководства.

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

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

Затем определяется почтовое сообщение (это сообщение пользователь получает, если для него имеется новая почта).

В следующем фрагменте листинга устанавливается значение unmask, разрешающее создание файлов, для которых установлены определенные права доступа, заданные по умолчанию.

Далее инициализируются переменные среды. После установки и экспорта они становятся доступными каждому пользователю.

В следующей строке листинга восстанавливается перехват сигналов, соответствующих клавишам [Quit] или [Ctrl+C].

Затем происходит сохранение заданных по умолчанию параметров стандартного терминала stty. В результате этого при выходе пользователей из системы аудита можно повторно инициализировать параметры терминала.

Потом регистрируются все подключения пользователей в файле /var/adm/mes‑sages, который по умолчанию является журнальным файлом системы.

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

После этого следует небольшой фрагмент кода, который дает пользователям возможность регистрироваться дважды, но только одновременно для двух пользователей. Это правило не распространяется на следующих трех пользователей: idink, psalom, dave. Остальным пользователям будет отказано в доступе, если они попытаются зарегистрироваться более двух раз.

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

В результате описанных выше действий устанавливается среда для глобального применения. А теперь выполним ее настройку, руководствуясь профильным файлом текущего пользователя.

 

13.2. Пользовательский файл $НОМЕ/.profile

После выполнения файла /etc/profile пользователь попадает в собственный начальный каталог $HOME. Если вернуться к файлу passwd, то видно, что имя этого каталога находится во втором поле от конца файла.

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

Если имеется файл .profile, система использует его в качестве исходного файла. Значит, данный процесс обращается к существующему интерпретатору shell. В результате этого все существующие среды {/etc/profile) не будут изменяться под влиянием информации файла (.profile). При создании другого процесса локальные переменные интерпретатора shell фактически переписываются.

Вернемся к файлу .profile. Как правило, если учетная запись уже установлена, профильный файл в каком‑то виде уже существует. Важно помнить, что установки файла /etc/profile могут быть переопределены при добавлении в файл .profile нового элемента с другим значением либо при выполнении команды unset. Специальная настройка данного файла остается в ведении пользователя, поэтому рассмотрим стандартный файл .profile:

$ pg .profile

#.profile

set -a

MAIL=/usr/mail/$(LOGNAME:?)

PATH=$PATH export PATH

#

А теперь приступим к настройке данного файла.

Необходимо установить ряд переменных среды, подобных editor, чтобы утилита cron и другие приложения были осведомлены о применяемом редакторе. Кроме того, нас не устраивает режим эмуляции терминала vt220. Поэтому, изменим это значение на режим эмуляции терминала vt100. Это обстоятельство связано с переменной TERM.

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

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

$ P$1="`имя_сервера`>"

dns‑cepвep>

Или для текущего каталога, в котором вы находитесь,

$ P$1="\`pwd\`>"

\home\dave>

Если в приведенной выше командной строке возвращается слово "pwd", то вместо него воспользуйтесь командной строкой:

P$1='$PWD >';

В качестве дополнительной командной строки (которая обычно применяется при выполнении многострочной команды в командной строке) можно применять знак авторского права ©. Значение этого символа в коде ASCII равно восьмеричному числу 251, или десятичному числу 169.

$ PS2=" `echo "\251" `:"

/home/dave> while read line

©:do

©:echo $LINE

©:done

В Linux…

Для использования в echo восьмеричного значения применяется следующий синтаксис:

$ PS2="`echo -e "\251"`:"

Так как пользователи имеют доступ к параметрам администрирования системы, размещенным в каталоге /usr/admin, этот каталог следует задать в виде переменной среды. Тогда в данный каталог можно переходить с помощью команды cd.

ADMIN=/usr/adm

Кроме того, сразу же после регистрации желательно знать, сколько пользователей находится в системе. Для этого можно воспользоваться командой who или wc.

$ echo "`who | wc -l` users are on today"

19 users are on today

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

. /имя_пути/имя_файла

Чтобы использовать файл .profile в качестве исходного, достаточно ввести следующую команду:

$ . .profile

Если приведенный вариант не действует, можно попробовать следующий: $ . ./profile

Ниже показан измененный файл .profile.

$ pg .profile

#.profile

MAIL=/usr/mai1/${LOGNAME:?}

PATH=$PATH:$HOME:bin

#

EDITOR=vi

TERM=vt100

ADMIN=/usr/adm

P$1=" `hostname`>"

PS2=" `echo "\0251"`:"

export EDITOR TERM ADMIN PATH PS1

echo " `who | wc -l` users are on to‑day"

13.3. Применение команды stty

Команда stty позволяет установить характеристики используемого терминала. Чтобы уточнить текущие установки опций stty, примените команду stty -a.

$ stty -а

speed 9600 baud; rows 24; columns 80; line=0

intr=^C; quit=^\; erase=^?; kill=^U; eof=^D; eol=;

eol2=; start=^Q; stop=^S; susp=^Z, rprnt=^R; werase=^W;

next=^V; flush=^0; min=1, time=0;

-parenb -parodd cs8 -hupci -cstopb cread -clocal -crtscts

-ignbrk -brkint -ignpar -parmrk -inpck -istrip -inlcr -ignor icrnl ixon

-ixoif -iuclc -ixany -imaxbel

opcst -olcuc -ocrnl onlcr -onocr -onlret -ofill -ofdel n10 cr0 tab0 bs0

vt0 ff0 isig icanon iexcen echo echoe echok -echonl

-noflsh -xcase

-tostop -echoprt echoctl echoke

Довольно часто при настройке терминала не работает клавиша [Backspace], т. е. при ее нажатии не происходит удаление символа. Данная команда stty сообщает, что в качестве клавиши [Backspace] используется комбинация клавиш ^?. Однако эта комбинация не действует. С помощью комбинации клавиш [Ctrl+H] можно вернуться на одну позицию и удалить предыдущий символ. Поэтому для устранения данной проблемы воспользуемся командой stty. Общий формат установки параметров команды stty в командной строке:

stty символ

Ниже показана установка управляющей последовательности ^H, соответствующей коду клавиши [Backspace]:

$ stty erase '\^H'

При использовании приведенной выше команды stty в файле .profile могут возникнуть затруднения. Команда stty на самом деле может предполагать наличие управляющей последовательности . Для устранения этого недостатка необходимо во время работы в редакторе vi поступить следующим образом: нажмите клавишу [Ctrl] и одновременно с ней клавишу [V], затем отпустите клавишу [V] и нажмите клавишу [Н].

Ниже приводятся наиболее распространенные наименования команды stty.

Наименование Клавиша Значение
intr ^C Завершение процесса
echo Подключение режима отображения
-echo Отключение режима отображения
eof ^D Конец файла, выход из системы
kill ^Y Удаление строки
start ^Q Начало прокрутки текста на экране
Stop ^S Завершение прокрутки текста на экране

Весьма полезен следующий параметр команды stty:

stty -g

Этот параметр позволяет сохранить результаты выполнения команды stty в удобочитаемом формате. Затем эти результаты можно назначить команде stty, как показано выше на примере листинга файла /etc/profile. Для этого достаточно разместить содержимое команды stty -g в соответствующей переменной, ввести необходимые изменения в команду stty, а по завершении передать эти изменения команде stty.

Этим приемом удобно воспользоваться, если при изменении параметров команды stty вы нечаянно нарушили нормальную работу терминала. В этом случае можно легко восстановить исходные параметры терминала. Ниже приведен пример сохранения и последующего восстановления текущих установок команды stty. В данном случае команда stty -echo применяется для отключения режима отображения, а в конце сценария восстанавливаются исходные параметры.

$ pg password

#!/bin/sh

#пароль

#отображение процесса восстановления среды

stty SAVEDSTTY=`stty -g`

stty -echo

echo "\nGive me that password :\c"

read PASSWD

echo "\nyour password is $PASSWD

stty $SAVEDSTTY

$ sttypass

Give me that password : your password is bong

В Linux …

Чтобы сообщить Linux, что в строках предполагается применение управляющих символов, команду echo следует вводить как "echo -e".

SAVEDSTTY=`stty -g`

stty -echo

echo "\nGive me that password :\c"

read PASSWD

echo "\nyour password ls $PASSWD"

stty $SAVEDSTTY

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

 

13.4. Создание файла .logout

Одним из недостатков интерпретатора Bourne shell является отсутствие в нем файла .logout. Этот файл содержит команды, которые требуется выполнить непосредственно перед завершением сеанса работы в системе, т. е. до выполнения команды

exit.

Однако собственный файл .logout интерпретатора Bourne shell можно создать с помощью команды trap (более подробные сведения о команде trap и сигналах приведены далее в книге). Рассмотрим, как это делается. Отредактируйте свой файл .profile и разместите на последней строке приведенную ниже команду. Затем сохраните этот файл и выйдите из режима редактирования.

trap "$HOME/.logout" 0

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

$ pg .logout

rm -f $HOME/*.log

rm -f $HOME/*.tmp

echo "Bye…bye $LOGNAME"

Файл .logout вызывается при выходе пользователя из системы. Когда пользователь выходит из среды интерпретатора shell, система посылает сигнал 0, который и означает выход из текущего интерпретатора shell. Прежде чем управление передается обратно интерпретатору shell, для продолжения процесса выхода из системы, упомянутый выше сигнал перехватывается командой trap. Эта команда находится в соответствующей строке файла .profile. Затем выполняется файл .logout.

 

13.5. Заключение

Каждый пользователь может настроить свой файл $HOME/.profile в соответствии с требуемыми задачами. В главе было показано, каким образом можно переопределять общесистемные параметры согласно своим предпочтениям. Существует большое количество способов настройки пользовательской рабочей среды. Можно указывать приветственные сообщения и вносить существенные изменения в параметры терминала.

 

ГЛАВА 14

 

Переменные среды и интерпретатора shell

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

Существуют переменные двух типов — переменные интерпретатора (shell) и переменные среды. На самом деле имеется четыре типа переменных, но оставшиеся предназначены только для чтения. Эти переменные считаются специальными и применяются при передаче параметров в shell–сценарии.

В этой главе рассматриваются следующие темы:

   • переменные интерпретатора shell;

   • переменные среды;

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

   • экспорт переменных;

   • специальные переменные;

   • передача информации в сценарии;

   • применение позиционных параметров в системных командах.

 

14.1. Понятие о переменных интерпретатора shell

Переменные позволяют выполнить настройку среды. Они содержат информацию, которая применяется определенным пользователем. Благодаря этому система получает более подробные сведения о пользователях. Кроме того, переменные используются для хранения констант. Рассмотрим, например, переменную под именем editor. Существует довольно много текстовых редакторов, но как выбрать наиболее подходящий из них? Присвойте имя нужного редактора переменной editor, и тогда именно этот редактор будет применяться, когда используется программа cron или другие приложения. Система обращается к значению переменной editor и применяет указанный редактор как заданный по умолчанию.

Для регистрации в системе sybase следует ввести команду:

$ isql -Udavet -Pabcd -Smethsys

где -S — имя сервера, с которым установлена связь. Переменная, содержащая имя сервера, называется dsquery. Имя сервера присваивается переменной dsquery. При регистрации в системе в случае, если имя сервера не указывается вместе с " — S", приложение обращается к переменной dsquery и использует значение этой переменной в качестве имени сервера. Для регистрации нужно ввести

$ isql -Odawet -Pabcd

Так функционирует большинство приложений.

 

14.2. Локальные переменные

 

Переменные интерпретатора shell могут использоваться сценариями в период функционирования интерпретатора shell. После завершения выполнения интерпретатора действие этих переменных прекращается. Например, локальная переменная имя_файла может иметь значение hops.doc. Это значение важно для пользователя только во время выполнения текущего интерпретатора команд; если запускается на выполнение другой процесс или происходит выход из среды интерпретатора команд, текущее значение локальной переменной не сохраняется. Переменные этого типа недоступны для других интерпретаторов shell или процессов, что имеет свои преимущества.

В табл. 14.1 представлены различные способы присваивания значений переменным.

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

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

$ имя_переменной=значение или ${иня_перемениой=значение}

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

Таблица 14,1. Различные способы присваивания значений переменным

Имя переменной = значение Значение переменной присваивается переменной имя_переменной
Имя переменной + значение Значение переменной присваивается переменной
имя переменной, если оно установлено
Имя_переменной:?значение На экран выводится сообщение об ошибке, если не установлена переменная имя_переменной
Имя переменной? значение На экран выводится сообщение о системной ошибке, если не установлена переменная имя_переменной
Имя_переменной:=значение Значение переменной присваивается переменной имя_переменной, если она не установлена
Имя переменной: — значение Как и выше, но значение переменной имя_переменной не присваивается; оно может быть получено подстановкой

 

14.2.1. Отображение значения переменной

Чтобы отобразить значение отдельной переменной, достаточно применить команду echo и предварить имя переменной знаком $. Рассмотрим несколько примеров.

$ GREAT_PICTURE="die hard"

$ echo ${GREAT_PICTURE}

die hard

$ DOLLAR=99

$ echo $(DOLLAR)

99

$ LAST_FILE=ZLPSO.txt

$ echo ${LAST_FILE}

ZLPSO.txt

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

$ ERROR_MSG="Sorry this file does not exist user $LOGNAME"

$ echo ${ERROR_MSG}

Sorry this file does not exist user dave

В приведенном выше примере интерпретатор shell сначала выводит текст, затем рассматривает переменную $LOGNAME и отображает ее значение.

 

14.2.2. Удаление значения переменной

Чтобы удалить значение переменной, достаточно применить команду unset: unset имя_переменной

$ PC=enterprise

$ echo ${РС}

enterprise

$ unset PC

$ echo ${PC)

$

 

14.2.3. Отображение значений всех переменных интерпретатора shell

Чтобы просмотреть значения всех переменных интерпретатора shell, достаточно воспользоваться командой set.

$ set

PWD=/root

SHELL=/bin/sh

SHLVL=1

TERM=vt100

UID=7

USER=dave

dollar=99

great_picture=die hard

last_file=ZLPSO.txt

Вывод команды set может быть довольно обширен; при его изучении можно заметить, что интерпретатор shell значительно облегчил работу в среде.

 

14.2.4. Объединение значений переменных

Чтобы объединить значения переменных, достаточно последовательно расположить переменные:

echo ${имя_переменной}${имя_переменной}. . ,

$ FIRST="Bruce "

$ SURNAME=Willis

$ echo ${FIRST}${SURNAME}

Bruce Willis

 

14.2.5. Проверка на наличие значения переменной (подстановка)

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

${переменная: — значение}

Если переменная установлена, она применяется. Если переменная не установлена, вместо нее используется значение, например:

$ COLOUR=blue

$ echo "The sky is ${COLOUR:=grey} today"

The sky is blue today

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

$ COLOUR=blue

$ unset COLOUR

$ echo "The sky is ${COLOUR:=grey} today"

The sky is grey today

В приведенном примере переменной не присваивается действительное значение; для присваивания значения следует применить формат:

${переменная:=значение}

Рассмотрим более полезный пример, в котором содержится запрос о времени создания платежной ведомости (payroll), а также относительно ее типа. Если в обоих случаях при указании времени и типа нажать клавишу [Enter], то значения этих переменных не будут установлены пользователем. В этом случае применяются новые значения, заданные по умолчанию (03:00 и Weekly). Затем значения передаются команде at, что свидетельствует о переносе выполнения задания на более поздний срок.

$ pg vartest

#!/bin/sh

# vartest

echo "what time do you wish to start the payroll [03:00]:"

read TIME

echo " process to start at ${TIME:=03:00} OK"

echo "Is it a monthly or weekly run [Weekly]:"

read RUN_TYPE

echo "Run type ls ${RUN_TYPE:=Keekly}"

at -f $RUN_TYPE $TIME

Ниже при выводе данных выбирается клавиша [Enter] в обоих случаях.

$ vartest

what time do you wish to start the payroll [03:00]:

process to start at 03:00 OK ls it a monthly or weekly run [Weekly]:

Run type is Weekly

warning: commands will be executed using /bin/sh job 15 at 1999-05-14 03:00

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

$ echo "The file is ${FILES:?}"

sh: files: parameter null or not set

Приведенное выше сообщение не слишком информативно, но пользователь может задать свое собственное сообщение.

$ echo "The file is $(FILES:?} sorry cannot locate the variable files")"

sh: files: sorry cannot locate the variable files

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

${переменная:+значение)

Для инициализации переменной значением пустой строки примените команду:

variable=""

$ DESTINATION=""

 

14.2.6. Применение переменных, содержащих аргументы системных команд

Переменные можно также использовать для хранения информации, применяемой впоследствии для замены аргументов в командах системы. В следующем примере переменные сохраняют информацию об имени файла, которая необходима для копирования файла. С помощью переменной SOURCE можно узнать путь к файлу passwd, а с помощью переменной DEST — получателя этого файла. Обе эти переменные применяются в команде ср.

$ SOURCE="/etc/passwd"

$ DEST="/tmp/passwd.bak"

$ cp ${SOURCE} ${DEST}

В примере ниже с помощью переменной device получаем путь к накопителю на магнитной ленте. Эти сведения используются затем в команде mt при перемотке ленты.

$ DEVICE="/dev/rmt/0n"

$ mt -f ${DEVICE} rewind

 

14.2.7. Как сделать переменную доступной только для чтения

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

имя_переменной=значение readonly имя_переменной

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

$ TAPE_DEV="/dev/rmt/0n"

$ echo ${TAPE_DEV}

/dev/rmt/0n

$ readonly TAPE_DEV

$ TAPE_DEV="/dev/rmt/1n"

sh: TAPE_DEV: read‑only variable

Чтобы просмотреть все переменные, которые доступны только для чтения, примените команду readonly.

$ readonly

declare -r FILM="Crimson Tide"

declare -ri PPID="1"

declare -r TAPE_DEV="/dev/rmt/0n"

declare -ri UID="0"

 

14.3. Переменные среды

 

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

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

может установить некоторые переменные среды в файле /etc/profile. Поскольку переменные размещаются в профильных файлах, они инициализируются при регистрации в системе.

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

 

14.3.1. Присваивание значений переменным среды

Для присваивания значений переменным среды применяется команда:

VARIABLE_NAME=значение; export VARIABLE_NAME

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

VARIABLE_NAME = значение export VARIABLE_NAME

 

14.3.2. Отображение значений переменных среды

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

$ CONSOLE=tty1; export CONSOLE

$ echo $CONSOLE

tty1

$ MYAPPS=/usr/local/application; export MYAPPS

$ echo $MYAPPS /usr/local/application

Чтобы просмотреть глобально определенные переменные среды, достаточно воспользоваться командой env.

$ env

HISTSIZE=1000

HOSTNAME=localhost.localdomain

LOGNAME=dave

MAIL=/var/spool/mail/root

TERM=vt100

HOSTTYPE=i386

PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/XllR6/bin:/root/bin:

CONSOLE=tty1

HOME=/home/dave

ASD=sdf

SHELL=/bin/sh

P$1=$

USER=dave

 

14.3.3. Удаление значений переменных среды

Чтобы удалить значение переменной, следует применить команду unset.

$ unset MYAPPS $ echo $MYAPPS

$

 

14.3.4. Встроенные переменные интерпретатора shell

Интерпретатор Bourne shell располагает именами, которые зарезервированы для переменных среды. Эти названия переменных нельзя использовать иначе. Обычно они содержатся в файле /etc/profile. Однако так бывает не всегда, поэтому пользователь может самостоятельно устанавливать значения этих переменных. Ниже приводится перечень переменных, встроенных в интерпретатор shell.

Переменная CDPATH

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

$ CDPATH=/home/dave/bin:/usr/local/apps; export CDPATH

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

$ cd apps

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

Переменная EXINIT

При работе с редактором vi переменная EXINIT предоставляет опции для инициализации этого редактора. Например, для установки нумерации всех строк и шага табуляции, равного 10 пробелам, примените следующую команду:

$ EXINIT=='set nu tab=10'; export EXINIT

Переменная HOME

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

$ HOME=/home/dave; export HOME

$ pwd

$ /usr/local

$ cd

$ pwd

$ /home/dave

Можно также применить команду:

$ cd $НОНЕ

Переменная IFS

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

$ export IFS=:

$ echo $PATH

/sbin /bin /usr/sbin /usr/bin /usr/X11R6/bin /root/bin

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

$ IFS=; export IFS

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

Переменная LOGNAME

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

$ LOGNAME=`whoami` ; export LOGNAME

$ echo $LOGNAME

dave

Переменная MAIL

Переменная mail хранит имя пути доступа и имя файла для вашего почтового ящика. По умолчанию ее значение /var/spool/mail/<регистрационное имя>. Интерпретатор shell периодически проверяет почтовый ящик на предмет наличия новых сообщений. Если пользователь получает электронное сообщение, он узнает об этом из командной строки. Если к почтовому ящику имеется другой путь, установите его с помощью переменной mail:

$ MAIL=/usr/mail/dave; export MAIL

Переменная MAILCHECK

Значение переменной mailcheck задается по умолчанию таким образом, чтобы наличие новой электронной почты проверялось каждые 60 секунд. Если электронную почту следует запрашивать реже, допустим каждые 2 минуты, примените команду:

$ MAILCHECK=120; export MAILCHECK

Переменная MAILPATH

Применяйте переменную mailpath, если вы располагаете более чем одним почтовым ящиком. При установке значения этой переменной перекрывается значение переменной mail:

$ MAILPATH=/var/apool/dave:/var/epool/admin; export MAILPATH

В данном примере переменная mail проверяет два почтовых ящика — dave и admin.

Переменная PATH

Переменная path хранит сведения о каталогах, где находятся выполняемые команды или сценарии. Важно, чтобы эта последовательность указывалась правильно, поскольку при обращении к этой переменной существенно сокращается время выполнения команды или сценария. Например, если в каком‑либо каталоге нет заданной команды, то не следует его просматривать. В общем случае лучше сначала задать каталог НОМЕ, за которым будет следовать перечень каталогов. Перечень включает каталоги, отсортированные по частоте применения. Сначала указываются наиболее часто применяемые каталоги, а затем те из них, которые применяются реже всего. Если нужно найти текущий рабочий каталог, то независимо от места его нахождения используйте точку. Каждый каталог отделяется двоеточием. Рассмотрим пример.

$ PATH=$HOME/bin: . :/bin:/usr/bin; export PATH

Согласно приведенному примеру, сначала производится поиск в каталоге НОМЕ/ bin, затем — в текущем каталоге, каталоге /bin и в каталоге /usr/bin.

Значение переменной path для системных каталогов задается в файле /etc/profile. Чтобы воспользоваться переменной path, определяя собственный вариант переменной path, достаточно в конце указать точку с запятой (;}.

$ PATH=$PATH:/$HOME/bin:. ; export PATH

В данном случае используется переменная path, определенная в файле /etc/profile, а также указан каталог $HOME/bin и текущий каталог. В общем случае нежелательно использовать текущий каталог при записи первого пути поиска. Если допустить подобное, то текущий каталог станет доступным и для других пользователей.

Переменная P$1

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

$ P$1="star trek:"; export P$1

star trek:

$ P$1=" ->" ; export P$1

->

Переменная PS2

Значение этой переменной задает вид вторичной командной строки. По умолчанию этот тип командной строки определяется символом >. Подобная командная

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

$ PS2="@:"; export PS2

$ for loop in *

@:do

@:echo $LOOP

Переменная SHELL

Переменная shell включает сведения об интерпретаторе shell, заданном по умолчанию. Интерпретатор команд обычно указан в файле /etc/passwd. Это значение нельзя отменить, даже если приходится использовать другой интерпретатор команд.

$ echo $SHELL

/bin/sh

Переменная TERMINFO

Переменная, определяющая инициализацию терминала, хранит сведения о местонахождении файлов конфигурации терминала. Обычно эти файлы находятся либо в каталоге /usr/lib/terminfo, либо в каталоге /usr/share/terminfo.

$ TERMIHFO=/uer/lib/terminfo; export TERMIHFO

Переменная TERM

Переменная term представляет тип терминала. Эта переменная служит для указания типа управляющих последовательностей, необходимых для правильного функционирования экрана и клавиатуры. Самыми распространенными типами терминалов являются vt100, vt220, vt220-8, wyse и т. д.

$ TERM=vt100; export TERM

Переменная TZ

Эта переменная позволяет определить часовой пояс. Значение переменной TZ устанавливает администратор. Если для интерпретатора shell потребуется изменить значение этой переменной, обратите внимание на следующие примеры:

$ echo $TZ

GMT2EDT

В данном случае возвращается значение, которое свидетельствует о том, что отсчет времени происходит по Гринвичу (Greenwich Mean Time) (временное смещение относительно GMT составляет 0 часов) в диапазоне летнего времени (Eastern Daylight Saving).

 

14.3.5. Другие переменные среды

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

Переменная EDITOR

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

$ EDITOR=vi; export EDITOR

Переменная PWD

Эта переменная представляет имя пути доступа для текущего каталога. Обычно

значение переменной изменяется всякий раз при выполнении команды cd.

Переменная PAGER

Данная переменная хранит сведения о командах программы постраничной разбивки. К подобным командам можно отнести, например, pg, more. Система проверяет значение этой переменной, когда пользователь выполняет просмотр страниц man.

$ PAGER='pg -f -p%d'; export PAGER

Переменная MANPATH

Представляет каталоги, которые включают страницы справочной программы man. Имя каждого каталога отделяется двоеточием.

$ MANPATH=/usr/apps/man:/usr/local/man; export MANPATH

Переменная LPDEST или переменная PRINTER

Эта переменная представляет имя принтера, заданного по умолчанию. При выводе на печать сохраняется имя принтера, заданное пользователем.

$ LPDEST=hp3si_systems

 

14.3.6. Применение команды set

Экспорт переменных среды можно задать при установке этих переменных в файле $HOME .profile. Воспользуйтесь командой set с параметром " -a" в виде "set -а". Это означает, что выполняется экспорт всех переменных. Не применяйте этот метод при работе с файлом /etc/profile. Данный метод применим только при работе с файлом $HOME/.profile.

$ pg .profile

#.profile

set -a

MAIL=/usr/mail/${LOGNAME:?}

PATH=$PATH:$HOME:bin

#

EDITOR=vi

TERM vt220

ADMIN=/usr/adm

P$1="`hostname` >>"

 

14.3.7. Экспорт переменных в дочерние процессы

Для тех, кто только начинает работать с интерпретатором shell, существенное затруднение представляет экспорт переменных в дочерние процессы. Теперь, после рассмотрения основных принципов работы с переменными среды, перейдем к

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

Рассматриваемый листинг включает два небольших сценария под именами father и child. Сценарий father задает переменную с именем film, значение которой "A Few Good Men". Эта переменная отображается на экране, затем вызывается другой сценарий под названием child. Данный сценарий отображает переменную film из первого сценария. Перед отображением на экране значением переменной film становится "Die Hard". Затем управление передается назад, сценарию father, и значение переменной снова выводится на экран.

$ pg father

#!/bin/sh

# сценарий father.

echo "this ls the father"

FILM="A Few Good Men"

echo "I like the film: $FILM"

# вызов сценария child

child

echo "back to father"

echo "and the film ls :$FILM"

$ pg child

#!/bin/sh

# сценарий child

echo "called from father..! am the child"

echo "film name is :$FILM"

FILM="Die Hard"

echo "changing film to :$FILM"

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

$ father

this ls the father

I like the film :A Few Good Men

called from father… i am the child

film name is :

changing film to :Die Hard

back to father

and the film ls :A Few Good Men

Сценарий child не может возвратить переменную film, поскольку эта переменная не может быть экспортирована в сценарий father.

Теперь, если команду export добавить в сценарий father, сценарий child получит всю информацию о переменной film.

$ pg father

#!/bin/sh

# сценарий father.

echo "this ls the father"

FILM="A Few Good Men"

echo "I like the film :$FILM"

#вызов сценария child

#сначала экспортируйте переменную

export FILM

child

echo "back to father"

echo "and the film is :$FILM"

$ father2

this ls the father

I like the film :A Few Good Men

called from father… i am the child

film name ls :A Few Good Men

changing film to :Die Hard

back to father

and the film ls :A Few Good Men

После того как команда export включена в состав сценария, можно выполнить произвольное число процессов. И всем этим процессам известно о наличии переменной FILM.

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

 

14.4. Позиционные параметры командной строки

 

Как указывалось в начале главы, существуют переменные четырех типов. Имеются переменные интерпретатора команд, переменные среды, а также переменные двух других типов, которые являются специальными, поскольку они предназначены только для чтения. Существуют позиционные и специальные параметры. Рассмотрим позиционные параметры.

Если информация передается shell–сценарию, с помощью позиционных параметров можно получить доступ к ней. Каждый параметр передает сценарию заданное количество ссылок. Можно передавать произвольное число аргументов, но доступными являются только первые девять из них. Это ограничение преодолевается путем использования команды shift. Далее в книге будет показано, как работает команда shift. Нумерация параметров начинается с единицы и завершается девятью; каждый параметр, доступ к которому следует получить, предваряется знаком доллара $. Первый параметр, имеющий номер нуль, резервируется для представления действительного названия сценария; это значение может использоваться независимо от того, содержатся ли в сценарии параметры.

В приведенной таблице в качестве примера демонстрируется, как можно получить доступ к каждому параметру, если в сценарий передается строка "Did You See The Full Moon"

$0 $1 $2 $3 $4 $5 $6 $7 $8 $9
Наименование сценария Did You See The Full Moon

 

14.4.1. Применение в сценариях позиционных параметров

Воспользуемся приведенным выше примером в следующем сценарии.

$ pg param

#!/bin/sh # параметры

echo "This ls the script name : $0"

echo "This ls the first parameter : $1"

echo "This ls the second parameter : $2"

echo "This ls the third parameter : $3"

echo "This ls the fourth parameter : $4"

echo "This ls the fifth parameter : $5"

echo "This ls the sixth parameter : S6"

echo "This ls the seventh parameter : $7"

echo "This ls the eighth parameter : $8"

echo "This ls the ninth parameter : $9"

$ param Did You See The Full Moon

This ls the script name : ./param

This ls the first parameter : Did

This ls the second parameter : You

This ls the third parameter : See

This ls the fourth parameter : The

This ls the fifth parameter : Full

This ls the sixth parameter : Moon

This ls the seventh parameter :

This ls the eighth parameter :

This ls the ninth parameter :

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

$ pg param2 .

#!/bin/sh

echo "Hello world this ls $0 calling"

$ param2

Hello world this ls ./param2 calling

Заметьте, что параметр $0 также позволяет получить путь доступа к текущему каталогу. Для получения названия сценария предварите параметр $0 командой

basename.

$ pg param2

#!/bin/sh

echo "Hello world this ls `basename $0` calling"

$ param2

Hello world this ls param2 calling

 

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

Параметры можно передавать внутри сценария в системную команду. В следующем примере используется команда find . Параметр $1 указывает имя искомого файла.

$ pg findfile

#!/bin/sh

# findfile

find / -name $1 -print

$ findfile passwd

/etc/passwd

/etc/uucp/passwd

/usr/bin/passwd

Ниже приводится другой пример. В виде параметра $1 файл user‑id передается команде grep; команда grep использует эти сведения для поиска файла passwd, где содержится полное имя пользователя.

$ pg who_is

#!/bin/sh

# who_is

grep $1 passwd | awk -F: {print $4}'

$ who_is seany

Seany Post

 

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

Теперь, когда вы изучили, как получить доступ к параметрам shell–сценариев и применять их, было бы полезным узнать об этих параметрах больше. Рассмотрим, каким образом сценарий применяет специальные параметры. Существует семь специальных параметров, которые представлены в табл. 14.2.

Таблица 14.2. Специальные параметры интерпретатора shell

$# Число аргументов, передаваемых сценарию
$* В отдельной строке отображаются все аргументы, которые передаются сценарию. Здесь может содержаться более девяти параметров, в отличие от позиционных параметров
$$ Текущий идентификатор PID для выполняющегося сценария
$! Идентификатор PID для последнего процесса, который выполняется в фоновом режиме
$@ Означает то же самое, что и параметр $#, но, если параметр заключен в кавычки, то и каждый аргумент отображается в кавычках
$- Отображение текущих опций интерпретатора команд; аналогично применению команды set
$? Показывает код завершения последней команды. Значение 0 свидетельствует об отсутствии ошибок, любое другое значение -o, их наличии

Преобразуем сценарий param, применяя некоторые специальные параметры. Затем выполним сценарий.

$ pg param

#!/bin/sh

# все параметры

echo "This ls the script name : §0"

echo "This ls the first parameter : $1"

echo "This is the second parameter : $2"

echo "This ls the third parameter : $3"

echo "This ls the fourth parameter : $4"

echo "This ls the fifth parameter : $5"

echo "This ls the sixth parameter : $6"

echo "This ls the seventh parameter : $7"

echo "This ls the eighth parameter : $8"

echo "This ls the ninth parameter : $9"

echo "The number of arguments passed : $#"

echo "Show all arguments : $*"

echo "Show me my process ID : $$"

echo "Show me the arguments in quotes :" "$@"

echo "Did my script go with any errors : $?"

$ param Merry Christmas Mr Lawrence

This ls the script name : ./param

This ls the first parameter : Merry

This ls the second parameter : Christmas

This ls the third parameter : Mr Lawrence

This ls the fourth parameter :

This ls the fifth parameter :

This ls the sixth parameter :

This ls the seventh parameter ;

This ls the eighth parameter :

This ls the ninth parameter :

The number of arguments passed ;3

Show all arguments : Merry Christmas Mr Lawrence

Show me my process ID : 630

Show me the arguments in quotes :"Merry" "Christmas" "Mr Lawrence"

Did my script go with any errors :0

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

 

14.4.4. Код завершения последней команды

Обратите внимание, что параметр $? возвращает значение 0. Этот прием можно использовать во всех командах или сценариях, если необходимо выяснить, успешно ли выполнена последняя команда. С помощью этой информации можно продолжить работу со сценарием. Если возвращается значение 0, значит все идет успешно; значение 1 означает появление ошибки.

Ниже приводится пример. Сначала файл копируется в каталог /tmp и с помощью параметра $? проверяется результат.

$ cр ok.txt /tmp

$ echo $?

0

Скопируем файл в несуществующий каталог:

$ cp ok.txt /usr/local/apps/dsf

cp: cannot create regular file '/usr/local/apps/dsf': No such file or

directory

$ echo $?

1

При проверке состояния возврата с помощью параметра $? отображается 1. Это свидетельствует о наличии ошибок. Появляется сообщение о системной ошибке "cp: cannot…", поэтому не требуется проверять код завершения последней команды. Сценарии функционируют с помощью системных команд. Обычно пользователь не заинтересован в отображении большого количества значений. Поэтому выходной поток перенаправляется в системную корзину /dev/null Каким образом пользователь узнает, что последняя команда была успешной? С помощью кода завершения последней команды. Рассмотрим пример, иллюстрирующий изложенный материал.

$ cp ok.txt /uer/local/appe/dsf >/dev/null 2>&1

$ echo $?

1

Если данные вывода, включая сообщения об ошибках, перенаправить в системную корзину, невозможно установить, выполнялась ли последняя команда. Но благодаря применению параметра $?, который возвращает значение 1, становится известно, что при выполнении команды были допущены ошибки.

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

$ cp ok.txt /usr/local/apps/dsf >/dev/null 2>&1

$ cp_status=$?

$ echo $cp_status

1

 

14.5. Заключение

Работа с переменными значительно облегчает функционирование интерпретатора shell. Автоматизируется ввод данных, повышается производительность труда администратора. Переменная интерпретатора shell может принимать произвольные значения. Использование специальных переменных расширяет функциональные возможности сценариев и позволяет получать больше информации о параметрах, передаваемых в сценарии.

 

ГЛАВА 15

 

Использование кавычек

В главе 14 обсуждались методы работы с переменными и операции подстановки. Чаще всего ошибки в использовании кавычек возникают при выполнении подстановок переменных в сценариях. Кавычки оказывают существенное влияние на формирование командных строк.

В этой главе рассматриваются следующие темы:

   • правила применения кавычек;

   • двойные, одинарные и обратные кавычки;

   • отмена специального значения символов с помощью символа обратной косой черты.

 

15.1. Правила применения кавычек

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

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

$ echo Hit the star button to exit *

Hit the star button to exit DIR_COLORS HOSTNAME Muttrc X11 adjtime aliases alias

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

$ echo "Bit the star button to exit *"

Hit the star button to exit *

Благодаря применению кавычек выражение интерпретируется верно. В табл. 15.1 приведены комментарии к различным типам кавычек.

Таблица 15.1. Использование кавычек интерпретатором shell

"" Двойные кавычки
' ' Одинарные кавычки
`` Символ "тупого ударения" или обратные кавычки
\ Символ обратной косой черты

15.2. Двойные кавычки

Двойные кавычки применяются, когда необходимо буквальное восприятие всех символов, за исключением символов: $, ` , \. Символы доллара, обратной кавычки и символ обратной косой черты сохраняют свое специальное значение при функционировании интерпретатора shell. Если при выводе на экран переменной присваивается текстовая строка, заключенная в двойные кавычки, речь идет о выводе на экран самой переменной.

$ STRING="MAY DAY, MAY DAY, GOING DOWN"

$ echo "$STRING"

MAY DAY, MAY DAY, GOING DOWN

$ echo $STRING

MAY DAY, MAY DAY, GOING DOWN

Предположим, что сведения о системной дате присваиваются переменной с именем mydate.

$ MYDATE="date"

$ echo $MYDATE

date

Интерпретатор команд воспринимает информацию в строке "как есть", т. е. дате не присваивается специальное значение. Поэтому в качестве даты фигурирует слова data

Двойные кавычки следует применять при поиске строки, содержащей пробелы. Воспользуемся командой grep для поиска имени Davey Wire. Если не применять кавычки, команда grep воспримет Davey как строку для поиска, a Wire — как файл.

$ grep Davey Wire /etc/passwd

grep: Wire: No such file or directory

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

$ grep "Davey Hire" /etc/passwd

davyboy:9sdJUK2s:106:Davey Wire:/home/ap

Чтобы включить переменную в строку для вывода на экран, можно применить двойные кавычки. В следующем примере интерпретатор shell выводит на экран строку, считывает знак $, трактует его как переменную и заменяет переменную $BOY значением boy.

$ ВОY="boy"

$ echo " The $BOY did well"

The boy did well

$ echo "The "$BOY" did well"

The boy did well

 

15.3. Одинарные кавычки

Применение одинарных кавычек во многом аналогично применению двойных кавычек. Интерпретатор shell получает указание не выполнять подстановку этих значений; другими словами, символы, заключенные в такие кавычки, лишены специального значения. То, что заключено в одинарные кавычки, воспринимается буквально. Рассмотрим пример, аналогичный примеру с двойными кавычками:

$ GIRL='girl'

$ echo "The '$GIRL' did well"

The 'girl' did well

 

15.4. Обратные кавычки

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

В следующем примере интерпретатор shell пытается выполнить подстановку слова hello. Но, поскольку нет ни команды, ни сценария с таким именем, отображается сообщение об ошибке.

$ echo `hello`

sh: hello: command not found

Применим снова команду date.

$ echo `date`

Sun May 16 16:40:19 GMT 1999

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

Присвоим переменной mydate данные вывода команды date. Ниже приводится формат команды date:

$ date +%A" the "%e" of "%B" "%Y

Sunday the 16 of May 1999

Присвоим значение переменной mydate и отобразим его.

$ mydate=`date +%A" the "%e" of "%В" "%Y`

$ echo $mydate

Sunday the 16 of May 1399

Конечно, переменной mydate можно присвоить весь вывод команды date:

$ mydate=`date`

$ echo $mydate

Sun May 16 16:48:16 GMT 1999

Ниже приводится другой пример. Обратные кавычки содержатся внутри двойных кавычек:

$ echo "The date today ls `date` "

The date today ls Sun May 16 16:56:53 GMT 1999

Выведем на экран небольшое сообщение, включающее сведения о количестве пользователей в системе.

$ echo "There are `who | wc -l` users on the system"

There are 13 users on the system

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

 

15.5. Обратная косая черта

Символ обратной косой черты указывает интерпретатору shell, что следующий за ним символ не имеет специального значения. Специальное значение могут иметь такие символы: & *=^ $ ` " | ?.

В результате применения команды echo вместе с символом * на экран выводится не символ звездочки, а листинг. В этот листинг включается текущий каталог.

$ echo *

conf.linuxconf conf.modules cron.daily cron.hourly cron.monthly cron.weekly crontab csh.cshrc default dosemu.conf dosemu.users exports fdprm fstab gettydefs gpm‑root.c onf group group- host.conf hosts hosts.allow hosts.deny httpd inetd

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

$ echo \*

*

Аналогичный результат можно получить с помощью команды $$. Интерпретатор shell воспринимает ее как текущий PID (ID процесса). Чтобы отключить специальное значение и вывести на экран символ $$, нужно перед этим символом поместить символ обратной косой черты:

$ echo $$

284

$ echo \$$

$$

Для вывода на экран символов, заданных восьмеричными ASCII–кодами, перед ними следует размещать символ обратной косой черты. В противном случае интерпретатор shell воспримет их как обычные числа.

$ echo "This ls a copyright 251 sign"

This is a copyright \251 sign"

$ echo "This is a copyright \251 sign"

This ls a copyright © sign"

В Linux…

He забывайте при выводе управляющих символов указывать параметр " -e".

$ echo -e "This ls a copyright \251 sign"

This ls a copyright © sign

Если при использовании команды expr применить символ * для обозначения операции умножения, то отобразится сообщение об ошибке. Чтобы символ * обозначал операцию умножения, следует поместить перед ним символ обратной косой черты.

$ expr 12 * 12

expr; syntax error

$ expr 12 \* 12

144

Чтобы оператор echo включал метасимволы, воспользуйтесь символом обратной косой черты. В следующем примере отображается цена $19.99. Поскольку не применяется символ обратной косой черты, интерпретатор shell трактует эту цену иначе.

$ echo * "That video looks a good price for $19.99"

That video looks a good price for 9.99

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

$ echo "That video looks a good price for \$19.99"

That video looks a good price for $19.99

 

15.6. Заключение

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

   1. Всегда применяйте двойные кавычки при выводе на экран строк командой echo.

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