учебники, программирование, основы, введение в,

http://mydean-rus.ru/ MyDean 5347 для Toyota LC Prado 150: land cruiser Prado 150.

 

Командные процессоры

Семейство командных процессоров
При интерактивной работе с системой пользователь постоянно сталкивается с необходимостью отдавать ей команды. В CDE это можно делать, выбирая мышью требуемые пункты меню. В текстовом окне или текстовом режиме команды набираются вручную в командной строке. После нажатия Enter производится интерпретация и синтаксический анализ команды (то есть определяется, где - имя программы, где - ключи, где - аргументы, где - спецсимволы). Затем будут запущены один или несколько процессов.
В UNIX эту работу выполняет программа, которая называется командным процессором (shell). Иногда командный процессор называют шеллом или интерпретатором команд (последнее неточно, потому что круг задач командного процессора шире, чем интерпретация команд).
Существует несколько широко распространенных командных процессоров и еще несколько малораспространенных, специфичных для конкретных вариантов UNIX. В Solaris принято использовать ksh, csh или bash.
Первый в мире UNIX командный интерпретатор в 1976 году написал Стив Баурн (Steve Bourne), когда он работал в Bell Laboratories в AT&T. По другим данным, Стив написал его в 1974 году. Через некоторое время в University of California Berkeley был написан C-shell (csh, произносится "си шелл"), а потом число разных командных процессоров стало быстро расти. Самые популярные из них сейчас - это Bourne again shell (bash), разработанный в рамках проекта GNU, и Korn shell (ksh) Дэвида Корна (David Korn).
С-shell был разработан студентом Университета в Беркли (University of California Berkeley) Биллом Джоем (Bill Joy), который по окончании Berkeley основал компанию Sun Microsystems. Еще Билл Джой написал самый известный в UNIX редактор vi и был одним из авторов первой версии BSD UNIX.


Таблица 10.1. Популярные командные процессоры в UNIX

Название

Имя в системе

Плюсы

Минусы

Bourne Shell

sh

обладает легким и удобным языком скриптов, прост и понятен

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

C Shell

csh

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

сложный язык скриптов, некоторые версии содержат много ошибок

Korn Shell

ksh

совместим с sh по командам и содержит ряд возможностей csh, имеет средства редактирования команд, введенных ранее (history)

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

Bourne Again Shell

bash

похож на ksh по возможностям, имеет легкий удобный интерфейс, простое интуитивно ясное редактирование введенных ранее команд, стандарт де-факто в Linux, в Solaris 9 устанавливается по умолчанию, но не является командным процессором по умолчанию

пока не обнаружено

В конце 1970-х годов был написан tcsh - расширение csh, совместимое с ним по командам, макроопределениям и синтаксису языка скриптов. Кен Грир (Ken Greer) начал работу над tcsh в Университете Карнеги-Мелон (Carnegie-Mellon University), а продолжил ее Пол Плэйсвэй (Paul Placeway) в восьмидесятые годы в Университете Огайо (Ohio State). Основные отличия tcsh от csh сводятся к усовершенствованию редактирования командной строки и ряду дополнений в помощь создателям скриптов (например, переменные среды окружения, доступные только для чтения). В последних версиях UNIX csh обычно является символической ссылкой на tcsh, а оригинальный csh в поставку не включается, чтобы не шокировать пользователей пещерным уровнем редактирования командной строки.
В Solaris по умолчанию устанавливаются несколько командных процессоров, в том числе sh, csh, tcsh, bash и другие; командным процессором по умолчанию является sh.
Командный процессор призван выполнять в системе нижеперечисленные задачи:

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

Некоторые командные процессоры поддерживают не все эти функции (см.).


Таблица 10.2. Основные задачи shell'ов

Функция

sh

csh

tcsh

ksh

bash

History

Нет

Да

Да

Да

Да

Псевдонимы

Нет

Да

Да

Да

Да

Скрипты

Да

Да

Да

Да

Да

Подстановка и завершение имен файлов

Нет

Да*

Да

Да*

Да

Редактирование командной строки

Нет

Нет

Да

Да*

Да

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

Нет

Да

Да

Да

Да

* - по умолчанию выключено
Запуск командного процессора
Командный процессор запускается либо при входе пользователя в систему, и в дальнейшем пользователь отдает команды в его командной строке, либо из какой-нибудь программы (по команде пользователя). Частным случаем является запуск командного процессора из другого командного процессора. Например, вы работаете в sh и хотите получить более удобные средства редактирования командной строки; для этого вызывается bash. Тогда вы просто набираете команду
bash
и оказываетесь в среде командного процессора bash, запущенного по этой команде. При этом обычно меняется вид приглашения командной строки.
Каждый командный процессор при запуске пытается выполнить свои стартовые файлы, вначале системные (общие для всех пользователей), а затем пользовательские. Общие файлы лежат в /etc, индивидуальные - в домашнем каталоге пользователя. Если командный процессор запускается при входе пользователя в систему (в таком случе он называется login shell - командный процессор, запущенный при входе в систему), то после стартовых файлов он выполняет еще и login-файлы в том же порядке: сначала общий login-файл из /etc, затем - индивидуальный, из домашнего каталога. Login-файлы - это тоже стартовые файлы командного процессора, все стартовые файлы фактически представляют собой скрипты на языке командного процессора и служат для инициализации среды окружения командного процессора для конкретного пользователя. Настройка командного процессора для пользователя позволяет, например, задать короткие псевдонимы для длинных часто используемых команд и т.п.
Некоторые командные процессоры при входе в систему выполняют сначала login-файлы, а затем - стартовые файлы, это зависит от того, как они были скомпилированы.


Таблица 10.3. Стартовые файлы командных процессоров

shell

стартовые файлы

login-файлы

sh

/etc/profile, ~/.profile

csh

/etc/csh.cshrc, ~/.cshrc

/etc/csh.login, ~/.login

ksh

/etc/profile, ~/.profile

bash

~/.bashrc

/etc/profile, ~/.bash_profile, ~/.profile

Другие командные процессоры принимаются за выполнение каких-либо стартовых файлов только при входе пользователя в систему. У командного процессора обычно есть ключ, который можно дать, чтобы сымитировать вход в систему и заставить его выполнить login-файлы.
Командный процессор bash, в отличие от других, использует более сложный алгоритм выполнения стартовых и login-файлов. Если он запущен как login shell, то он выполняет /etc/profile, если такой файл есть. Затем делается попытка выполнить ~/.bash_profile. Если такого файла нет, bash пытается выполнить файл ~/.bash_login, а если нет и такого файла, то выполняется ~/.profile. Если bash запущен не как login shell, то при старте он выполняет только файл ~/.bashrc. Если же bash был запущен как sh (т.е. sh является символьной ссылкой на bash), то при старте он ведет себя так же, как и sh.
История команд
Все командные процессоры запоминают введенные пользователем команды (их список называется историей команд). Во время сеанса работы командный процессор хранит историю команд в памяти, а по окончании работы записывает их в файл на диск. Файл истории команд хранится в домашнем каталоге пользователя. В sh, csh, tcsh он называется ~/.history, в bash - ~/.bash_history, в ksh - ~/.shhistory, а в бесплатной версии Korn Shell (public domain Korn shell - pdksh) его по умолчанию нет вообще.
Многие командные процессоры позволяют повторить вызов ранее введенной команды по ее номеру или начальным буквам. О том, как это делать, подробнее сказано ниже в разделе "Повторение и модификация ранее введенных команд".
Имейте в виду, что по умолчанию файл истории команд может быть доступен для чтения не только тому, кто вводил команды, но и другим пользователям. Чтобы не сделать систему уязвимой, следует избегать ввода каких бы то ни было паролей в командной строке. Например, возможно вызвать браузер lynx или программу доступа к серверу баз данных mysql, указывая пароль в командной строке:
lynx ftp://user:password@URL
mysql -u root -p password
Так как эти команды сохранятся в файле истории вместе с другими, кто-то потом сможет прочесть их и узнать какие-то из ваших паролей. Файл истории команд ограничен по размеру. По умолчанию, bash хранит 500 команд, tcsh - 1000, csh - 100, sh - в зависимости от версии. Часто sh не создает файл .history вовсе, и дает доступ только к командам, которые были введены в течение текущего сеанса работы с ним. Можно изменить число хранимых команд, указав иное значение переменной, в которой оно хранится.


Таблица 10.4.

shell

переменная

значение по уполчанию

sh

HISTSIZE

не определено

csh

history

100

ksh

HISTSIZE

128

bash

HISTFILESIZE

500

Псевдонимы команд
Псевдонимы - это сокращения для часто используемых длинных команд или их последовательностей. Если вы часто делаете однотипные опечатки при вводе команд, можно создать такие псевдонимы, чтобы команда с опечаткой была псевдонимом правильной команды, например:
alias telent telnet
Создать псевдоним очень просто:
alias псевдоним команда
Команда может быть последовательностью команд с ключами и аргументами, тогда ее следует заключить в апострофы:
alias ll 'ls -l'
Такая команда приведет к тому, что каждый раз при вводе ll командный процессор будет фактически выполнять команду
ls -l
Синтаксис определения псевдонимов в разных командных процессорах разный. Псевдонимы обычно определяются в стартовых файлах.
Синтаксис команд alias:
командный процессор   команда alias     ключ для экспорта
sh                    alias             ll='ls -l'
csh                   alias             ll 'ls -l'
ksh                   alias             ll='ls -l'   -x
bash                  alias             ll='ls -l'
Так же, как и переменные среды окружения, псевдонимы могут экспортироваться, т.е. передаваться "по наследству" запускаемым из данного сеанса работы другим командным процессорам. Для этого используются ключи команды alias. Команда alias является встроенной командой командного процессора.
Отмена назначенного псевдонима выполняется командой
unalias псевдоним
Переменные среды окружения
Как отмечалось в лекции 7, каждый процесс имеет свою среду окружения - специальную область, в которой хранятся имена переменных и их значения. Если нужно использовать значение переменной в командной строке, применяется конструкция
$имя_переменной
Например, echo $TERM выведет на экран значение переменной TERM. Пользователь может определить свои собственные переменные. Новая переменная появляется, как только вы даете команду присвоить значение несуществующей переменной. Переменная не имеет типа, так как считается, что все переменные имеют тип "строка". При этом если попытаться выполнить арифметическую операцию с переменными, имеющими значение неких чисел, то такая строка будет преобразована в число, число использовано в операции и результат преобразован обратно в строку.
Попробуйте:
i=2
j=3
expr $i \* $j
Присвоение переменной значения во всех командных процессорах, кроме csh, выполняется командой
VAR=value
В csh команда иная:
set VAR=value
или
setenv VAR value
Переменные со специальными названиями типа DISPLAY, TERMINFO и т.п. используют программы, которые проверяют свою среду окружения на наличие таких переменных и их значений. Поведение таких программ может изменяться в зависимости от значения переменных.
Переменные могут экспортироваться, т.е. передаваться от процессов-родителей процессам-потомкам. Для экспорта переменной надо дать команду
export имя_переменной
Если надо удалить переменную среды окружения, можно присвоить ей пустое значение (это неравнозначно удалению, но иногда этого достаточно), а можно удалить ее вовсе командой unset.
В tsch есть возможность создавать переменные только для чтения, без права изменения значений, для этого служит команда
set -r имя=значение
Кроме того, в tcsh можно присвоить переменной значение в виде списка слов, к которым потом можно обращаться по номеру слова, начиная с 1:
set var=(hello world)
echo {$var[1]}
hello
echo {$var[2]}
world
Для вывода на экран списка всех переменных с их значениями надо дать команду set без параметров.

Предопределенные переменные
Предопределенные переменные содержатся в среде окружения командного процессора независимо от установок, которые может сделать пользователь в стартовых скриптах. Имена предопределенных переменных среды окружения во всех командных процессорах, кроме csh (и, в некоторых случаях, tcsh), пишутся символами верхнего регистра: PATH, USER, TERM, PS1, PS2.
В именах переменных среды окружения используются буквы латинского алфавита. пользовательские, добавленные по ходу работы переменные в скриптах принято называть именами из символов нижнего регистра для того, чтобы отличать переменные, введенные разработчиком системы, от тех, что вводит пользователь или требует прикладная программа.
В любых командных процессорах обязательно заранее определены переменные, указанные в.


Таблица 10.5. Предопределенные переменные

Переменная

Смысл

HOME

домашний каталог пользователя

SHELL

текущий shell

PS1

вид приглашения shell'a

PS2

вид приглашения "продолжение команды"

TERM

тип терминала пользователя

USER или LOGNAME

имя пользователя

PATH

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

С другой стороны, многие другие переменные определяются не во всех командных процессорах. Посмотреть список всех переменных среды окружения обычно можно по команде
set
Любой скрипт может быть вызван с аргументами, которые в скрипте называются позиционными параметрами. К аргументам с первого по девятый следует обращаться как к $1..$9. Значение $0 - это имя самого скрипта, по которому его вызвали. Один и тот же скрипт может быть вызван с разными именами, например, если с ним установлены символические связи (symbolic links).
Команда shift n (n - положительное или отрицательное смещение) позволяет двигать "окошко" $1..$9 по всему массиву аргументов скрипта вперед и назад, если аргуменов больше девяти. Shift без параметров эквивалентен shift 1. В csh shift умеет сдвигать "окно" только на одну позицию вперед.
Кроме вышеописанных переменных обычно определены следующие:


Смысл

$

номер процесса текущего shell'a

*

все позиционные параметры

_

последняя вызванная команда

1,2,..9

один позиционный параметр

?

число позиционных параметров

Подстановка имен файлов. Шаблоны
При запуске программ из командной строки часто требуется передать им в качестве аргументов одно или несколько имен файлов. Эти имена удобно задать шаблоном - например, /var/log/messages.?, что означает все файлы из каталога /var/log, имена которых начинаются на messages., а завершаются любым символом. Любой командный процессор умеет подставлять в командную строку имена файлов, соответствующие шаблону:
ls -l /var/log/messages.?
Символ "?" трактуется командным процессором как шаблон, которому соответствует один любой символ.
Обратите внимание на то, что командный процессор не понимает регулярных выражений. Его шаблоны похожи на регулярные выражения, но это - две совершенно разные вещи. Для обработки регулярных выражений в любом приложении используется стандартная функция regex, а шаблоны имен файлов командный процессор обрабатывает по-своему.
Командный процессор распознает и интерпретирует следующие символы в шаблонах (такие символы называются метасимволами, metasymbols или wildcards):


*

любая подстрока, в том числе пустая.

?

один любой символ.

[...]

один любой символ из списка (например, [avgf]) или диапазона (например, [a-z]).

Порядок подстановки имен файлов по шаблону таков: вначале командный процессор находит все файлы, имена которых соответствуют шаблону, а затем подставляет имена всех этих файлов через пробел в строку в то место, где был написан шаблон.
Таким образом, если в текущем каталоге есть файлы money.c, money.bak, money.obj и wallet.x, то команда
ls -l mon*
будет раскрыта в
ls -l money.c money.bak money.obj

Подстановка результата выполнения
Иногда возникает необходимость отыскать в системе файлы по некоему признаку и со всеми этими файлами выполнить одинаковое действие. Например, во всех файлах *.html заменить подстроку Siemens на Nixdorf. Если это требуется сделать только для файлов, лежащих в одном каталоге, то задача решается достаточно просто. Здесь мы приведем пример скрипта для Bourne Shell, но аналогичный скрипт легко написать и для других командных процессоров:
for i in *.html
do
sed 's/Siemens/Nixdorf/g' <$i >tmp
mv tmp $i
done
Переменная i последовательно принимает значения из списка, т.е. на каждой итерации цикла она имеет разное значение, список будет содержать имена всех файлов текущего каталога, соответствующих шаблону *.html.
Команда sed обеспечивает замену всех вхождений Siemens на Nixdorf, причем во входной поток sed перенаправляется содержимое очередного файла, в зависимости от значения переменной i. Результат направляется в файл tmp, а команда mv обеспечивает переименование файла tmp в нужное имя, для замены старого файла из списка *.html новым.
Что делать, если такую процедуру надо проделать со всеми файлами *.html всего дерева каталогов, начиная с текущего каталога?
В UNIX есть уникальная возможность, которая реализована в любом командном процессоре : можно "вложить" одну команду в другую так, чтобы вначале выполнилась одна, а затем результат ее выполнения был подставлен в командную строку для вызова второй команды.
Итак, мы хотим найти все файлы *.html в поддереве файловой системы, начиная с текущего каталога.
Используем find для поиска:
find . -name "*.html"
Теперь воспользуемся конструкцией "подстановка результата выполнения" и перепишем наш скрипт для замены подстрок:
for i in ` find . -name "*.html" `
do
sed 's/Siemens/Nixdorf/g' <$i >tmp
mv tmp $i
done
Команда, заключенная в ` ` (обратные апострофы), выполняется первой, а результат ее выполнения подставляется в командную строку. Затем командная строка запускается на выполнение.
Завершение имен файлов
Функция "подсказки" (можно сказать также - "завершения") имен файлов (file name completion) позволяет набрать только часть имени существующего файла и затем нажать клавишу "Tab". В ответ на это командный процессор "закончит" набор имени файла. Например, если надо обратиться к файлу /usr/sadm/admin/bin/printmgr, то достаточно набрать
/usr/sa<Tab>dm/a<Tab>dmin/b<Tab>in/pr<Tab>intmgr
Все, что в этом примере выделено жирным шрифтом, набираете вы, а все, что не выделено - подставляет командный процессор.
Завершение имен файлов реализовано только в bash и tcsh.
Тем, в чьей системе есть файлы с длинными уникальными именами, подсказка имен файлов отлично экономит время.
При двойном нажатии "Tab" выводятся все возможные варианты завершения имени файла.
Например, если в каталоге есть два файла, имена которых начинаются с букв msg: msg01.txt и msg02.txt и надо просмотреть один из них, можно набрать more msg<Tab><Tab>
Командный процессор bash (или tcsh) подскажет:
msg01.txt      msg02.txt
Теперь достаточно набрать цифру 1 или 2, чтобы указать, какой именно файл требуется, и еще раз нажать "Tab" для окончательного завершения имени. Если после двойного нажатия "Tab" bash видит слишком много возможных вариантов имен, он спросит
There are 1102 possibilities.
Do you really wish to see them all? (y or n)
Стоит ответить n: так много имен не уместится на экран.

Средства редактирования командной строки
Редактировать командную строку приходится для того, чтобы исправить что-то в только что набранной строке. В sh нельзя передвинуть курсор в любую позицию в строке, в остальных командных процессорах - можно. Удобнее всего редактировать командную строку в bash.
В каждом командном процессоре реализована возможность стирания последнего символа клавишей "backspace" и стирания строки целиком комбинацией клавиш "Ctrl-U".
В самых первых реализациях командных процессоров средства редактирования были еще более примитивными (например, удаление всей строки целиком выполнялось вводом @ и последующим вводом строки заново, при этом все набранные символы все равно оставались на экране). Сейчас такие архаические приемы редактирования не применяются ни в одном командном процессоре.
В bash и tcsh можно перемещаться вперед и назад по уже введенным символам в строке с помощью "стрелок", переместить курсор в середину и в начало строки. Командный процессор bash после нажатия Enter принимает всю строку целиком, независимо от того, в какой позиции строки находился курсор при нажатии Enter. Например, можно вернуть курсор к середине строки, если ввод оказался неверным, исправить ошибку и тут же нажать Enter, чтобы запустить команду на выполнение. В некоторых старых версиях командных процессоров в этом случае следует исправить строку, перейти к ее концу для ввода команды и только после этого нажать Enter.
В ksh редактирование по умолчанию выключено, его надо включить нажанием клавиши Esc. После этого командная строка будет редактироваться средствами того редактора, имя которого задано в переменной среды окружения VISUAL или EDITOR. По умолчанию это редактор vi. Трудно найти такого системного администратора, которому такой громоздкий и неудобный способ исправления команд покажется удачным: ведь ко всему прочему ему придется помнить о переключении режимов редактирования строки ввода!
В csh и tcsh редактирование командной строки выполняется так же, как и в bash.
Повторение и модификация ранее введенных команд
Иногда бывает удобно повторить команду, которую вы недавно уже вводили; особенно это помогает при вводе длинных команд с одинаковыми аргументами. В тех случаях, когда повторяемая команда должна немного отличаться от оригинала, следует модифицировать запись о ранее введенной команде и запустить на выполнение свежий вариант.
Например, введя
lyxn -p proxy.spb.edu:3128 www.macropulos.cam.ac.uk
вы получите в ответ "command not found", потому что, собираясь запустить lynx, вы допустили опечатку в имени программы. Не повторять же теперь ввод всей длинной строки! Если бы опечатка была в конце строки, можно было бы вызвать строку с предыдущей командой клавишей "стрелка вверх", но здесь опечатка в начале строки, и после вызова выполненной строчки придется еще двигать курсор в ее начало. Есть более короткий вариант, доступный в csh, tcsh и bash:
^xn^nx
Эта конструкция требует у командного процессора повторить предыдущую команду, заменив первой вхождение подстроки xn на nx. И это все!
В csh, tcsh, bash есть и другие средства модификации командной строки. Они перечислены ниже:

  • !n (n - число) повтор n-ной команды из истории команд1);
  • !! повтор последней команды;
  • !str выполнение последней команды, начинающейся на str.

Командные процессоры csh и tcsh по-разному интерпретируют конструкцию !nstr, например, `!67r'. Для csh это - команда номер 67, в конец которой добавляется r перед выполнением, а для tcsh это - последняя начинающаяся на 67r команда. Такой синтаксис введен в tsch для удобства повторения команд, имена которых начинаются с цифр. Чтобы заставить tcsh вести себя подобно csh, нужно перед числом поставить обратный слэш, экранирующий его специальное значение: `!\6\7r'.
В bash повторение команд выполняется так же, как и в csh. Дополнительно можно использовать клавиши "вверх" и "вниз" для переходов между командами, введенными раньше или позже.
В ksh для повторения команд используют встроенную команду r, а в sh - команду fc, при этом в sh можно вызвать только такую команду, которая была введена в текущем сеансе, потому что sh не ведет файл истории.

Работа с заданиями
Работая в режиме командной строки, вы можете запустить несколько программ одновременно, например, организовав конвейер. Совокупность таких одновременно запущенных из среды командного процессора процессов называется заданием.
Задание можно приостановить, потребовать его продолжения или завершить его. Задание может выполняться как в фоновом режиме, так и в интерактивном. Для управления заданиями большинство командных процессоров (точнее, все кроме Bourne Shell) имеют встроенные команды: jobs, fg, bg.
Посмотреть список запущенных ранее заданий можно с помощью команды jobs. Для вывода идентификаторов (PID) процессов, входящих в задание, следует использовать команду
jobs -l
Например, запускаем программу find для поиска файлов *.gif, список найденных файлов перенаправляем в ~/gifs (т.е. наш домашний каталог, файл gifs):
find / -name "*.gif" > ~/gifs &
[1] 33151
jobs -l
[1] + 33151 Running     find / -name "*.gif" > ~/gifs &
То, что в квадратных скобках [ ], и есть номер задания. Задания имеют уникальные номера в пределах текущего сеанса работы с shell-ом. Задание можно перевести в интерактивный режим командой fg (foreground):
fg %1           # %1 - номер задания.
Теперь задание выполняется в интерактивном режиме. Можно остановить его, переведя в режим suspend (sleeping, спящий):
<Сtrl-z>
[1] + Stopped    find / -name "*.gif" > ~/gifs &
Теперь можно продолжить выполнение задания в фоне командой bg (background):
bg %1
С помощью команд управления заданиями можно переключать программы между интерактивным и фоновым режимом выполнения. Если вы случайно забыли поставить знак & в конце команды, но собирались запустить ее в фоновом режиме, еще не все потеряно! Следует нажать Ctrl-Z, чтобы "усыпить" программу, а затем запустить задание в фоновом режиме с помощью команды bg.
Команды bg и fg могут принимать разные аргументы, но знак %, за которым следует число, в любом командном процессоре интерпретируется как ссылка на номер задания.

Язык написания скриптов
В командных процессорах используются всего два типа языков. Это sh-подобный язык и csh-подобный язык. Первый тип поддерживается в sh, ksh, bash. Второй - в csh и tcsh. Язык sh более удобен и стандартен, на нем написаны практически все скрипты во всех системах UNIX, включая стартовые скрипты системы. Язык csh по синтаксису ближе к языку программирования С, но используется для скриптов реже. Однако в некоторых случаях программное обеспечение включает в себя скрипты на языке csh, поэтому здесь мы разберем вкратце конструкции обоих языков.
Первой строкой любого скрипта должна быть строка, содержащая управляющий комментарий специального вида:
#!полное_имя_командного процессора
например
#!/bin/sh
Этот комментарий требует выполнить скрипт с помощью указанного командного процессора. По умолчанию скрипт выполняется в среде /bin/sh, даже если он запущен в среде другого командного процессора. Если вы работаете в tcsh и хотите, чтобы ваши скрипты запускались в tcsh, следует обязательно указать полный путь к tcsh в управляющем комментарии.
Язык sh
В языке sh существуют операторы ветвления и циклов. Ниже дано описание этих операторов. В нем жирным шрифтом выделены ключевые слова. Конструкция "команды" подразумевает одну или несколько команд командного процессора или вызовов программ, которые отделяются друг от друга разделителями (точкой с запятой или переводом строки). При вводе многострочных операторов в командной строке, командный процессор начинает новую строку приглашением "продолжение команды" (его вид определяется значением переменной среды окружения PS2 или prompt2).
В операторах циклов допустимы команды break (прерывание цикла, управление передается за конец цикла) и continue (передача управления на начало цикла, переход к следующей итерации). Эти команды действуют одинаково в любых командных процессорах, так как они реализованы и в языке sh, и в языке csh.
Оператор ветвления if:
if условие then
команды
else
команды
fi
В bash, ksh и новых версиях sh возможна конструкция elseif (вложенное ветвление):
if условие then
команды
elseif условие then
команды
fi
else
команды
fi
Оператор множественного ветвления case:
case значение_переменной in
значение1) команды; break;
значение2) команды; break;
значение3) команды; break;
*) команды;
esac
Знак "звездочка" (*) означает "все остальные значения", т.е. если значение переменной не равно ни значению1, ни значению2, ни значению3.
Операторы цикла while (выполнять, пока условие истинно) и until (выполнять до тех пор, пока условие станет истинным):
while условие do
команды
done

until условие do
команды
done
Все эти операторы содержат неотъемлемый элемент, обозначенный нами как условие. Это - вызов любой команды (в том числе другой скрипт или конвейер), возвращающей код завершения.
Условие считается истинным, если код завершения равен нулю, и ложным - если код завершения не равен нулю. Любая программа в UNIX возвращает код завершения: нулевой - в случае успешного выполнения и ненулевой - в противном случае. Значения кодов завершения программ можно выяснить с помощью руководства к ним, например, man.
Для проверки условий, относящихся к объектам файловой системы, применяется программа test. В некоторых командных интерпретаторах есть встроенная команда test , иногда test - это отдельная программа. С помощью test часто проверяется наличие файла или каталога в файловой системе:
if test -e имя_файла then echo <файл существует!>
Язык sh допускает конструкцию [ ] вместо команды test:
if [ -e имя_файла ] then echo <файл существует!>
Эта конструкция эквивалентна вышеприведенной.
С помощью test и [ ] можно проверять различные условия, полный список которых содержится в man test или man sh, man bash.
Некоторые программы всегда возвращают код завершения ноль. Это легко использовать для организации бесконечных циклов. Такие циклы могут понадобиться для перезапуска процессов, имеющих тенденцию к неожиданному и ненужному завершению. Например, так можно запускать процесс pppd для соединения с провайдером по выделенной или коммутируемой линии:
while sleep 10
do
/usr/sbin/pppd
done
Программа sleep всегда будет возвращать ноль, так что цикл никогда не прервется и будет исправно запускать pppd всякий раз, как только он завершится, например, из-за ошибки связи. Десять секунд ожидания добавлены просто для того, чтобы было время переждать неблагоприятную ситуацию, из-за которой произошла ошибка.
В Solaris и других системах System V такое применение менее полезно, чем в BSD-системах, так как того же эффекта можно добиться, указывая вызов pppd в /etc/inittab с указанием режима запуска respawn (запустить, если завершится).
Оператор for (цикл повторяется для каждого значения из списка):
for имя_переменной in список do
команды
done
Оператор цикла for используется особенно часто, например, для однотипной модификации нескольких файлов сразу. Предположим, надо во всех файлах *.html в текущем каталоге изменить ссылку на файл с фотографией:
for i in *.html
do
sed 's/otello.gif/dezdemona.gif/g' $i >tmp
mv -f tmp $i
done
Поскольку sed не меняет файл, а лишь выдает измененный текст в свой выходной поток, приходится перенаправлять вывод во временный файл tmp (назовите ваш файл по вкусу, от названия ничего не зависит) и затем переименовать tmp в файл с тем же именем, что у исходного файла. В момент переименования старый файл, естественно, исчезнет.
При вызове sed: следует писать именно $i, а не просто i, чтобы командный процессор подставил в командную строку значение переменной i, а не символ i.
Сразу перенаправить вывод в файл, имя которого указывается как $i, нельзя, поскольку перенаправление вывода в существующий файл вызовет уничтожение его прежнего содержимого. Это значит, что одновременное перенаправление ввода и вывода из/в один и тот же файл недопустимо.
Программе mv дается ключ -f, который требует от нее выполнить работу, не задавая вопросов типа "а вы действительно хотите уничтожить файл?"
Для вывода информации в sh принято использовать команду echo. Эта команда печатает в стандартный выходной поток свои аргументы, а в конце вывода выполняет перевод строки.
Команда
echo -n строка
выводит строку и не добавляет перевод строки в конце.
Для ввода информации в скриптах на языке sh используют оператор read:
read name
echo "Name is $name"
Язык, реализованный в вашем командном процессоре, может быть богаче, чем описанный здесь минимальный стандарт. Для получения дополнительной информации обратитесь к man по вашему командному процессору.
Язык csh
В операторах циклов языка csh можно использовать команды break (прерывание цикла, управление передается за конец цикла) и continue (передача управления на начало цикла, переход к следующей итерации) так же, как и в языке sh.
Языки sh и csh отличаются синтаксисом операторов и некоторыми командами. Помните, что:

  • в csh имена системных переменных среды окружения пишутся буквами нижнего регистра;
  • в csh нет оператора until; почти все операторы называются иначе, чем в sh.

В csh и tcsh есть свои правила вычисления логических выражений для того, чтобы выяснить истинность или ложность условия в операторах цикла и ветвления. Команда test есть в любом языке, независимо от типа командного процессора:
if (условие)команда

или
if (условие) then
команды
else if (условие) then
команды
else
команды
endif
Допускается любое число вложенных операторов elseif, при этом нужен только один оператор endif.
Отступы в операторе ветвления не важны, но операторы else и endif должны начинаться с новой строки, оператор if должен следовать за else или начинаться с новой строки.
Оператор множественного ветвления в csh называется switch:
switch (строка)
case строка1:
команды
breaksw
case строка2:
команды
breaksw
default:
команды
breaksw
endsw 
Опреатор switch в csh выполняется подобно оператору switch из языка С, команда breaksw передает управление за оператор endsw.
Оператор while действует так же, как while в sh, однако синтаксис у него немного иной:
while (условие)
команды
end
Оператор цикла for в csh назвали foreach, подобно одноименному оператору из Perl:
foreach имя_переменной (список)
команды
end
Если оператор foreach вводится в командной строке, то csh на каждой новой строке выводит приглашение "foreach?" Это означает, что ввод оператора еще не закончен и его можно продолжать, ввод завершается финальным словом end в начале строки.
Для ввода информации в скриптах на языке csh используют конструкцию $< (подстановка строки из входного потока):
echo " Enter your name:"
setenv name $<
echo "Name is $name"

Установка приглашения shell
Командный интерпретатор имеет несколько вариантов приглашений на разные случаи жизни.
По умолчанию в sh - это $, в csh - %. Привилегированный пользователь (root) имеет другое приглашение - #.
В среде окружения каждого командного процессора есть переменные PS1 и PS2. Это - вид обычного приглашения и приглашения к продолжению ввода команды соответственно.
При вводе длинной команды можно набрать ее в две строки. для этого следует в конце первой строки набрать символ обратного слэша и нажать Enter - вот так:
\<Enter>
и продолжить ввод на следующей строке. Команда может быть многострочной, как правило, допустимая длина команды составляет 1024 символа. Обратный слэш экранирует следующий за ним символ перевода строки от интерпретации в качестве символа завершения команды. При переходе к новой строке появится символ >, так как именно это значение по умолчанию имеет PS2.
В csh и tcsh вместо PS1 и PS2 определены переменные prompt и prompt2. Некоторые командные процессоры, в частности, ksh, имеют дополнительные приглашения для специальных случаев. Они хранятся в переменных PS3, PS4 и т.д., а в csh - в prompt3 и prompt4.
Многие реализации командных процессоров (прежде всего, bash) умеют показывать приглашения, включающие в себя динамически подставляемые части (например, имя текущего каталога). В этих командных процессорах есть свои собственные макроопределения для таких подстановок. Например, имя текущего каталога в bash подставляется в приглашение командной строки с помощью макроса \w, а в csh - с помощью %/. Помните, что назначать желаемое значение переменной можно только, указывая макрос внутри апострофов, чтобы экранировать его от интерпретации командным процессором, например в bash:
$PS1='\w$'
Перечень макроопределений для приглашений командной строки обычно содержится в руководстве man по командному интерпретатору.
Перечень спецсимволов
Как уже говорилось, все командные процессоры воспринимают некоторые символы как служебные, придавая им специальное значение при разборе командной строки. Выше рассматривались спецсимволы, связанные с указанием конкретных конструкций. Как было показано, многие служебные символы интерпретируются разными командными процессорами одинаково, хотя бывают и исключения. Основные спецсимволы приведены в.


Таблица 10.6. Специальные символы командных процессоров

командный процессор

основные спецсимволы

sh

$ * ? \ ` ' " [ ] < > &

csh

$ * ? \ ` ' " ! ^ { } [ ] ! % < > &

ksh

$ * ? \ ` ' " ! ^ { } [ ] < > &

bash

$ * ? \ ` ' " ! ^ { } [ ] % < > &

Для ввода специальных символов без учета их специального смысла (например, для вычисления произведения двух чисел выполняется команда expr 2 \* 2, надо передать программе expr просто звездочку, не расшифровывая ее специальное значение для командного процессора) в командной строке предваряйте их символом экранирования \ или заключайте в кавычки или апострофы. Кавычки отличаются от апострофов тем, что они экранируют от интерпретации все специальные символы, за исключением `, $ и \, а апострофы экранируют абсолютно все специальные символы.
Разбор командной строки
Каждый командный процессор выполняет разбор командной строки в строго определенном порядке:

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

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

 

 
На главную | Содержание | < Назад....Вперёд >
С вопросами и предложениями можно обращаться по nicivas@bk.ru. 2013 г.Яндекс.Метрика