Простейшие средства SHELL

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

Shell не является необходимым и единственным командным языком (хотя именно он стандартизован в рамках POSIX [POSIX 1003.2] - стандарта мобильных систем). Например, немалой популярностью пользуется язык cshell, есть также kshell, bashell (из наиболее популярных в последнее время) и другие. Более того, каждый пользователь может создать свой командный язык. Может одновременно на одном экземпляре операционной системы работать с разными командными языками.

Обратите внимание:
Shell - это одна из многих команд UNIX. То есть в набор команд оболочки (интерпретатора) "shell" входит команда "sh" - вызов интерпретатора "shell". Первый "shell" вызывается автоматически при вашем входе в систему и выдает на экран промптер. После этого вы можете вызывать на выполнение любые команды, в том числе и снова сам "shell", который вам создаст новую оболочку внутри прежней.

Так, например, если вы подготовите в редакторе файл "f1":

echo Hello!

то это будет обычный текстовый файл, содержащий команду "echo", которая при выполнении выдает все написанное правее ее на экран. Можно сделать файл "f1" выполняемым с помощью команды "chmod 755 f1". Но его можно ВЫПОЛНИТЬ, вызвав явно команду (!) "sh" ("shell"):

sh f1

или

sh < f1

Файл можно выполнить и в текущем экземпляре "shell". Для этого существует специфическая команда "." (точка), т.е.

. f1

Важное предупреждение: Не начинайте командные файлы с символа "#", хотя естественно начинать его с комментария. Дело в том, что такой командный файл в оболочке C-Shell ("csh") будет интерпретирован как выполняемый в "csh", в результате будет активизирован интерпретатор "csh".

Совет:
Начинайте командный sh-файл с пустой строки или пустого оператора ":".

Поскольку UNIX - система многопользовательская, вы можете даже на персональном компьютере работать параллельно, скажем, на 12-ти экранах (переход с экрана на экран ALT/функциональная клавиша), имея на каждом экране нового (или одного и того же) пользователя со своей командной оболочкой. Можете и в графическом режиме X-Window также открыть большое число окон, а в каждом окне может быть свой пользователь со своей командной оболочкой...

Стержневым элементом языка shell является команда.

Структура команд

Команды в shell обычно имеют следующий формат:

<имя команды> <флаги> <аргумент(ы)>

Например:

ls -ls /usr/bin
lsимя команды выдачи содержимого директория,
-lsфлаги ( "-" - признак флагов, l - длинный формат, s - объем файлов в блоках).
/usr/binдиректорий, для которого выполняется команда.

Эта команда выдаст на экран в длинном формате содержимое директория /usr/bin, при этом добавит информацию о размере каждого файла в блоках.

К сожалению, такая структура команды выдерживается далеко не всегда. Не всегда перед флагами ставится минус, не всегда флаги идут одним словом. Есть разнообразие и в представлении аргументов. К числу команд, имеющих экзотические форматы, относятся и такие "ходовые" команды, как сс, tar, dd, find и ряд других.

Как правило (но не всегда), первое слово (т.е. последовательность символов до пробела, табуляции или конца строки) shell воспринимает, как команду. Поэтому в командной строке

cat cat

первое слово будет расшифровано shell, как команда (конкатенации), которая выдаст на экран файл с именем "cat" (второе слово), находящийся в текущем директории.

Группировка команд

Средства группировки:

\n
<перевод строки>
определяют последовательное выполнение команд;
&асинхронное (фоновое) выполнение предшествующей команды;
&&выполнение последующей команды при условии нормального завершения предыдущей, иначе игнорировать;
||выполнение последующей команды при ненормальном завершении предыдущей, иначе игнорировать.

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

Например, наберем (экзотическую) команду "find" в фоновом режиме для поиска в системе , начиная от корня "/", файла с именем "conf", а затем "pwd" в обычном режиме. На экране этот фрагмент будет выглядеть следующим образом:

--------------------------------
$ find / -name conf -print &
ввод команды "find"

288
номер (PID) фонового процесса

$ pwd
ввод команды "pwd"

/mnt/lab/asu
результат работы "pwd"

$
возвращение shell в промптер

/usr/include/sys/conf
результат работы "find"
--------------------------------

Иногда необходимо, чтобы все фоновые процессы завершились, прежде чем будет выполняться какой-то расчет. Для этого служит специальная команда "wait [PID]". Эта команда ждет завершения указанного идентификатором (числом) фонового процесса. Если команда без параметра, то она ждет завершения всех фоновых процессов, дочерних для данного "sh".

Для группировки команд также могут использоваться фигурные "{}" и круглые "()" скобки. Рассмотрим примеры, сочетающие различные способы группировки:

k1 && k2; k3

где k1, k2 и k3 - какие-то команды, то k2 будет выполнена только при успешном завершении k1; после любого из исходов обработки k2 (т.е. k2 будет выполнена или пропущена) будет выполнена k3.

k1 && {k2; k3}

Здесь обе команды (k2 и k3) будут выполнены только при успешном завершении k1.

{k1; k2} &

В фоновом режиме будет выполняться последовательность команд k1 и k2.

Фоновые процессы (как и теневую экономику) сложно уничтожить, поскольку традиционная команда "CTL/C" прерывает только процессы переднего плана. Для уничтожения фонового процесса надо знать его номер. При запуске фонового процесса на экран выдается число, соответствующее номеру (идентификатору) этого процесса (PID). Если этот номер забыт или надо убедиться, что этот процесс не закончен, с помощью команды:

ps -aux

можно получить перечень идентификаторов процессов (PID), имена пользователей, текущее время, затраченное процессами и т.д.

В выведенной таблице можно найти номера процессов, подлежащих уничтожению, например это "849" и "866". Тогда командой:

kill -9 866 849

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

Предупреждение:
Если параллельно обрабатывается или создается файл с ОДНИМ именем (например, несколько пользователей вызвали в редактор один и тот же файл), то в системе продолжит существование тот вариант файла, который возвращен (записан) в систему последним. Это частая ошибка пользователей персональных компьютеров, которые редактируют один файл параллельно с нескольких экранов.

Круглые скобки "()", кроме выполнения функции группировки, выполняют и функцию вызова нового экземпляра интерпретатора shell.

Предположим, что мы находимся в начальном каталоге "/mnt/lab/asu".

cd ..; ls; ls

Две команды "ls" выдадут два экземпляра содержимого каталога "/mnt/lab". Однако, следующая последовательность:

(cd ..; ls) ls

сначала покажет содержимое каталога "/mnt/lab", а затем содержимое "/mnt/lab/asu", потому что при входе в скобки вызывается новый экземпляр shell. При выходе из круглых скобок происходит возврат в старый shell и в старый каталог.

Перенаправление команд

Стандартный ввод (вход) - "stdin" в ОС UNIX осуществляется с клавиатуры терминала, а стандартный вывод (выход) - "stdout" направлен на экран терминала. Существует также стандартный файл диагностических сообщений - "stderr", о котором речь пойдет далее.

Команда, которая может работать со стандартным входом и выходом, называется ФИЛЬТРОМ.

Пользователь имеет удобные средства для перенаправления ввода и вывода на другие файлы или устройства. Символы ">" и ">>" обозначают перенаправление вывода.

ls >f1

Команда "ls" создаст список файлов текущего каталога и поместит его в файл "f1" вместо вывода на экран. Если файл "f1" уже существовал, он будет перезаписан.

pwd >>f1

Команда "pwd" сформирует полное имя текущего каталога и добавит его в конец файла "f1". То есть ">>" добавляет к содержимому файла, если он уже имеет какие-то данные.

Символы "<" и "<<" обозначают перенаправление ввода.

wc -l <f1

Эта команда подсчитает и выдаст на экран количество строк в файле "f1".

ed f2 <<!

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

Можно сочетать перенаправления. Например:

wc -l <f3 >f4
wc -l >f4 <f3

Обе команды подсчитают количество строк в файле "f3", и результат будет сохранён в файле "f4".

Средство, которое соединяет стандартный вывод одной команды со стандартным вводом другой, называется КОНВЕЙЕРОМ и обозначается вертикальной чертой "|".

ls | wc -l

Список файлов текущего каталога будет направлен на вход команды "wc", которая на экран выведет количество строк в каталоге.

Конвейер позволяет объединять несколько команд, особенно когда все они, за исключением возможно первой и последней, являются фильтрами:

cat f1 | grep -h result | sort | cat -b > f2

Этот конвейер считывает содержимое файла "f1", выбирает все строки с словом "result", сортирует их и затем пронумеровывает результат перед выводом в файл "f2".

Устройства в ОС UNIX представляют собой специальные файлы, которые можно найти в каталоге "/dev". Примеры включают "lp" для печати, "console" для консоли, "ttyi" для i-го терминала и "null" для фиктивного файла.

Так, команда:

ls > /dev/lp

напечатает содержимое текущего каталога, в то время как:

f1 < /dev/null

обнулит файл "f1".

И:

sort f1 | tee /dev/lp | tail -20

отсортирует файл "f1", напечатает его и выведет 20 последних строк на экран.

Стандартные файлы имеют номера: 0 для stdin, 1 для stdout и 2 для stderr. Если вы не хотите видеть сообщения об ошибках на экране, вы можете перенаправить их, например:

cat f1 f2 2>f-err

Это перенаправит сообщения об ошибках в файл "f-err". Вы также можете перенаправить всю информацию в один файл:

cat f1 f2 >>ff 2>ff

Это направит все в файл "ff".

Команда:

cat f1 f2 2>>ff 1>&2

перенаправляет "stderr" (в режиме добавления) в файл "ff", а затем стандартный выход перенаправляется на "stderr", который к этому моменту является файлом "ff". Таким образом, оба выхода (стандартный и ошибок) будут записаны в файл "ff".

В конструкции "1>&2", символ "&" указывает на перенаправление, и всё это пишется без пробелов. Так, "1>&2" означает, что стандартный вывод (1) перенаправляется туда, куда уже был перенаправлен стандартный вывод ошибок (2).

<-закрывает стандартный ввод.
>-закрывает стандартный вывод.

Генерация имен файлов

При генерации имен используют метасимволы:

МетасимволОписание
*произвольная (возможно пустая) последовательность символов;
?один произвольный символ;
[...]любой из символов, указанных в скобках перечислением и/или с указанием диапазона;
cat f*выдаст все файлы каталога, начинающиеся с "f";
cat *f*выдаст все файлы, содержащие "f";
cat program.?выдаст файлы данного каталога с однобуквенными расширениями, например, "program.c" и "program.o", но не выдаст "program.com";
cat [a-d]*выдаст файлы, которые начинаются с "a", "b", "c", "d". Аналогичный эффект дадут команды "cat [abcd]*" и "cat [bdac]*".

Командные файлы

Для использования текстового файла в качестве команды существует несколько способов.

Допустим, с помощью редактора был создан файл с именем "cmd", в котором одна строка следующего содержания:

date; pwd; ls

Можно вызвать shell (обозначаемую "sh") и передать ей файл "cmd" в качестве аргумента или перенаправленного ввода:

$ sh cmd

или

$ sh <cmd

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

Более интересный способ работы с командным файлом - превратить его в выполняемый. Это можно сделать, изменив код защиты. Например, команда:

chmod 711 cmd

присвоит файлу код защиты "rwx__x__x". Теперь его можно вызвать просто:

cmd

Результат будет аналогичным, если файл содержит команды в следующем виде:

date
pwd
ls

Потому что переход на новую строку также действует как разделитель команд.

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

Важно отметить, что интерпретатор shell - это лишь одна из многих команд ОС UNIX и имеет равные права с остальными.