Сведения о документе

Интерпретатор командной строки (shell)

Проницательный читатель, несомненно, заметит, что как только речь заходит об устройстве Linux и более или менее профессиональной работе с этой ОС, в примерах немедленно возникает и начинает доминировать командная строка. Из чего несложно сделать вывод, что это главный (и стандартный) интерфейс управления системой в Linux. Тот же проницательный читатель наверняка задастся вопросом — а кто же выполняет команды, введённые в командной строке? Ответ «система» окажется неправильным: в Linux нет отдельного объекта под именем «система». Система — она на то и система, чтобы состоять из многочисленных компонентов, взаимодействующих друг с другом.

Правильный ответ, как водится, оказывается более сложным. Операционная система нужна в частности для того, чтобы программы можно было писать, не думая о подробностях устройства компьютера и его деталей, начиная от процессора и жёсткого диска (скажем, на уровне «открыть файл», а не последовательности команд перемещения головки жёсткого диска). Операционная система управляет оборудованием сама, а программам предоставляет «язык» довольно высокого уровня абстракции, покрывающий все их необходимости, т. н. API1. Но для команд пользователя такой язык не годится, поскольку он всё равно слишком низкоуровневый (для решения даже самой простой задачи пользователя необходимо выполнить несколько таких операций), да и воспользоваться им можно, только написав программу (чаще всего — на языке Си). Возникает необходимость выдумать для пользователя другой — более высокоуровневый и более удобный — язык управления системой. Все команды, которые можно ввести в командной строке, сформулированы именно на этом языке.

Из чего проницательному читателю несложно заключить, что обрабатывать эти команды, переводя их на язык операционной системы, должна тоже какая-нибудь специальная программа, и именно с ней ведёт диалог пользователь, работая с командной строкой. Так оно и есть: программа эта называется интерпретатор командной строки или командная оболочка («shell»). «Оболочкой» она названа как раз потому, что всё управление системой идёт как бы «изнутри» неё: пользователь общается с нею на удобном ему языке (с помощью текстовой командной строки), а она общается с другими частями системы на удобном им языке (вызывая запрограммированные функции).

Конечно, командных интерпретаторов в Linux несколько. Самый простой из них, появившийся в ранних версиях UNIX, назывался sh, или «Bourne Shell» — по имени автора, Стивена Борна (Stephen Bourne). Со временем его — везде, где только можно — заменили на более мощный, bash, «Bourne Again Shell»2. bash превосходит sh во всём, особенно в возможностях редактирования командной строки. Помимо sh и bash в системе может быть установлен «The Z Shell», zsh, самый мощный на сегодняшний день командный интерпретатор (шутка ли, 22 тысячи строк документации), или tcsh, обновлённая и тоже очень мощная версия старой оболочки «C Shell», синтаксис команд которой похож на язык программирования Си.

Синтаксис командной строки

Итак, что же представляет собой этот более удобный для пользователя язык? Больше всего общение на этом языке напоминает письменный диалог с системой — поочерёдный обмен текстами. Высказывание пользователя на этом языке — это команда, каждая команда — это отдельная строка. Пока не нажат enter, строку можно редактировать, затем она передаётся оболочке. Оболочка разбирает полученную команду — переводит её на язык системных объектов и функций, после чего отправляет системе на выполнение.

Результат выполнения очень многих команд также представляет собой текст, выдаваемый в качестве «ответа» пользователю. Хотя это и не обязательно — команда может выполнять свою работу совершенно молчаливо. Кроме того, если в процессе выполнения команды возникли какие-то особые обстоятельства (например, ошибка), оболочка включит в ответ пользователю диагностические сообщения.

Команда и параметры

Простейшая команда состоит из одного «слова», например, команда cal, которая выводит календарь на текущий месяц.


[methody@localhost methody]$ cal
      Июнь 2008
Вс Пн Вт Ср Чт Пт Сб
 1  2  3  4  5  6  7
 8  9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30

[methody@localhost methody]$

Пример 1. Команда cal

А если нужно посмотреть календарь на будущий месяц? Верно, не следует для этого изобретать отдельную команду3, cal вполне справится с этой задачей, только её поведение нужно немного модифицировать:


[methody@localhost methody]$ cal 7 2008
      Июль 2008
Вс Пн Вт Ср Чт Пт Сб
       1  2  3  4  5
 6  7  8  9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31

Пример 2. Команда cal с параметрами

Выходит, команда cal 7 2008 состоит как минимум из двух частей — собственно команды cal и «всего остального». Это остальное, что следует за командой, называют параметрами (или аргументами), причём они вводятся для того, чтобы изменить поведение команды. В большинстве случаев при разборе командной строки первое слово считается именем команды, а остальные — её параметрами.

Слова

При разборе командной строки shell использует понятие разделитель (delimiter). Разделитель — это символ, разделяющий слова; таким образом командная строка — это последовательность слов (которые имеют значение) и разделителей (которые значения не имеют). Для shell разделителями являются символ пробела, символ табуляции и символ перевода строки. Количество разделителей между двумя соседними словами значения не имеет.

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


[methody@localhost methody]$ echo One      Two      Three
 One Two Three
[methody@localhost methody]$ echo One      "Two      Three"
 One Two      Three
[methody@localhost methody]$ echo 'One
> 
> Ой. И что дальше?
> А, кавычки забыл!'

 One

 Ой. И что дальше?
 А, кавычки забыл!
[methody@localhost methody]$

Пример 3. Закавычивание в командной строке

Всё сказанное означает, что у команды столько параметров, сколько слов с точки зрения shell следует за ней в командной строке. Первое слово в тройке передаётся команде как первый параметр, второе — как второй и т. д. В первом случае команде echo было передано три параметра — “One”, “Two” и “Three”. Она их и вывела, разделяя пробелом. Во втором случае параметров было два: “One” и “Two Three”. В результате эти два параметра были также выведены через пробел. В третьем случае параметр был всего один — от открывающего апострофа “'One” до закрывающего “...забыл!'”. Всё время ввода bash услужливо выдавал подсказку “> ” — в знак того, что набор командной строки продолжается, но в режиме ввода содержимого кавычек.

Ключи

Для решения разных задач одни и те же действия необходимо выполнять слегка по-разному. Например, для синхронизации работ в разных точках земного шара лучше использовать единое для всех время (по Гринвичу), а для организации собственного рабочего дня — местное время (с учётом сдвига по часовому поясу и разницы зимнего и летнего времени). И то, и другое время показывает команда date, только для работы по Гринвичу ей нужен дополнительный параметр “-u” (он же “--universal”).


[methody@localhost methody]$ date
Пнд Июн 16 18:03:44 MSD 2008
[methody@localhost methody]$ date -u
Пнд Июн 16 14:03:46 UTC 2008

Пример 4. Команда date с ключом

Такого рода параметры называются модификаторами выполнения или ключами (options)4. Ключ принадлежит данной конкретной команде и сам по себе смысла не имеет, чем отличается от прочих параметров (например, имён файлов, чисел), которые имеют собственный смысл, не зависящий ни от какой команды. Каждая команда может распознавать некоторый набор ключей и соответственно изменить своё поведение. В результате «один и тот же» ключ, например, “-s” может значить для разных команд совершенно разные вещи.

Для формата ключей нет жёсткого стандарта, однако существуют договорённости, нарушать которые в наше время уже неприлично. Во-первых, если параметр начинается на “-”, это — однобуквенный ключ. За “-”, как правило, следует один символ, чаще всего — буква, обозначающая действие или свойство, которое этот ключ придаёт команде. Так проще отличать ключи от других параметров — и пользователю при наборе командной строки, и программисту, автору команды.

Во-вторых, желательно, чтобы имя ключа было значащим — как правило, это первая буква названия действия или свойства, обозначаемого ключом. Например, ключ “-a” в man и who происходит от слова «All» (всё), и изменяет работу этих команд так, что они начинают показывать информацию, о которой обычно умалчивают. А в командах cal и who смысл ключа “-m” — разный:


[methody@localhost methody]$ who -m
 methody  tty1        Sep 20 13:56 (localhost)
[methody@localhost methody]$ cal -m
      Июнь 2008
Пн Вт Ср Чт Пт Сб Вс
                   1
 2  3  4  5  6  7  8
 9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30

Пример 5. Использование ключа “-m” в разных командах

Для who ключ “-m” означает «Me», то есть «Я», и в результате who работает похоже на whoami5. А для cal ключ “-m” — это команда выдать календарь, считая первым днём понедельникMonday»), как это принято в России.

Свойство ключа быть, с одной стороны, предельно коротким, а с другой стороны — информативным, называется аббревиативностью. Не только ключи, но и имена наиболее распространённых команд Linux обладают этим свойством.

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


[methody@localhost methody]$ date -s 00:00
date: невозможно установить дату: Operation not permitted
Пнд Июн 16 00:00:00 MSK 2008
[methody@localhost methody]$ date
Пнд Июн 16 18:30:53 MSK 2008

Пример 6. Использование date -s

Ключ “-s” команды date позволяет установить системное время в то значение, которое указывается в качестве параметра этого ключа. Однако в данном примере эта операция не удалась, о чём свидетельствует выведенное сообщение об ошибке. Для изменения системных часов требуются привилегии системного администратора, а в нашем примере эта команда выполнялась от имени обычного пользователя. Тем не менее, date всё равно отобразил время, которое нужно было установить, хотя системные часы и остались не изменёнными.

Аббревиативность ключей трудно соблюсти, когда их у команды слишком много. Некоторые буквы латинского алфавита (например, “s” или “o”) используются очень часто, и могли бы служить сокращением сразу нескольких команд, а некоторые (например, “z”) — редко, под них и название-то осмысленное трудно придумать. На такой случай существует другой, полнословный формат: ключ начинается на два знака “-”, за которыми следует полное имя обозначаемой им сущности. Таков, например, ключ “--help” (аналог “-h”):


[methody@localhost methody]$ head --help
Использование: head [КЛЮЧ]... [ФАЙЛ]...
Печатает первые 10 строк каждого ФАЙЛА на стандартный вывод.
Если задано несколько ФАЙЛОВ, сначала печатает заголовок с именем файла.
Если ФАЙЛ не задан или задан как -, читает стандартный ввод.

Аргументы, обязательные для длинных ключей, обязательны и для коротких.
  -c, --bytes=[-]N         напечатать первые N байт каждого файла;
                             если перед N стоит `-', напечатать все, кроме N
                             последних байт каждого файла
  -n, --lines=[-]N         напечатать первые N строк каждого файла, а не 10;
                             если перед N стоит `-', напечатать все, кроме N
                             последних строк каждого файла
  -q, --quiet, --silent    не печатать заголовки с именами файлов
  -v, --verbose            всегда печатать заголовки с именами файлов
      --help     показать эту справку и выйти
      --version  показать информацию о версии и выйти


N может иметь суффикс-множитель: b 512, k 1024, m 1024*1024.

Об ошибках сообщайте по адресу <bug-coreutils@gnu.org>.

Пример 7. Ключ–help

Видно, что некоторые ключи head имеют и однобуквенный, и полнословный формат, а некоторые — только полнословный. Так обычно и бывает: часто используемые ключи имеют аббревиатуру, а редкие — нет. Значения параметрических полнословных ключей принято передавать не следующим параметром командной строки, а с помощью конструкции “=значение” непосредственно после ключа.

В-четвёртых, есть некоторые менее жёсткие, но популярные договорённости о значении ключей. Ключ “-h” («Help») обычно (но, увы, не всегда) заставляет команды выдать краткую справку. Наконец, бывает необходимо передать команде параметр, а не ключ, начинающийся с “-”. Для этого нужно использовать ключ “--”:


[methody@localhost methody]$ head -1 -filename-with-
head: invalid option -- f
Попробуйте `head --help' для получения более подробного описания.
[methody@localhost methody]$ head -1 -- -filename-with-
Первая строка файла -filename-with-

Пример 8. Параметр–не ключ, начинающийся на “-

Ключ “--” (первый “-” — признак ключа, второй — сам ключ) обычно запрещает команде интерпретировать все последующие параметры командной строки как ключи, независимо от того, начинаются ли они на “-” или нет. Только после “--head согласилась с тем, что -filename-with- — это имя файла.

Синопсис

Из всего вышесказанного ясно, что для каждой команды существует свой собственный небольшой язык — его составляют те ключи и обязательные и необязательные параметры, которые принимает и интерпретирует команда. Чтобы окинуть возможности команды одним взглядом, в различной документации по Linux приводится синопсис — сжатое перечисление всех возможных параметров команды. Выглядит это примерно так:


cal [-smjy13] [[month] year]

Пример 9. Синопсис для команды cal

В синопсисе даётся формализованное описание способов использования объекта (с данном случае — того, как и с какими параметрами запускать команду cal). Параметры перечисляются в том же порядке, в котором их нужно вводить в командной строке, необязательные параметры, как правило, даются в квадратных скобках, обязательные — вообще без скобок, а ключи для компактности собираются в один параметр, в котором каждая буква — это отдельный ключ. Приведённый пример читается так: у команды cal нет обязательных параметров, есть (необязательные) ключи (-s, -m и т. д.), и необязательный параметр year, перед которым может присутствовать необязательный же month (но не может быть указан month без year).

Откуда берутся команды

Дочитав предыдущий раздел, проницательный читатель должен был подумать примерно так: ага, ну с командами и параметрами (т. е. с грамматикой командной строки) мы немного разобрались, вооружите же нас теперь списком всех команд Linux (иначе говоря, словарём), и мы примемся за работу. Почему же нигде не напечатан такой список? Точнее, списков команд много разных и все они очевидно неполные и не во всём сходятся. Ответ на этот вопрос состоит из двух частей.

Часть 1: команды и утилиты

Shell, командный интерпретатор, является «оболочкой» не только для пользователя, но и для команд: сам он почти никакие команды не исполняет, передаёт системе. Его задача сводится к тому, чтобы разобрать командную строку, выделить из неё команду и параметры, а затем запустить утилиту6 — программу, имя которой совпадает с именем команды.

Если смотреть «изнутри» командного интерпретатора, то работа с командной строкой происходит примерно так: пользователь вводит строку (команду), shell считывает её, иногда — преобразует по определённым правилам, получившуюся строку разбивает на команду и параметры, а затем запускает утилиту, передавая ей эти параметры. Утилита, в свою очередь, анализирует параметры, выделяет среди них ключи, и делает что попросили, попутно выводя данные для пользователя, после чего завершается. По завершении утилиты возобновляется работа «отступившего на задний план» командного интерпретатора, он снова считывает командную строку, разбирает её, вызывает команду... Так продолжается до тех пор, пока пользователь не скомандует оболочке завершиться самой (с помощью команды logout или управляющего символа Ctrl+D).

Однако часть команд (меньшую) оболочка всё же выполняет самостоятельно, не вызывая никаких утилит. Некоторые — самые нужные — команды встроены в bash, даже несмотря на то, что они имеются в виде утилит (например, echo). Работает встроенная команда так же, но так как времени на её выполнение уходит существенно меньше, командный интерпретатор выберет именно её, если будет такая возможность. В bash тип команды можно определить с помощью команды type. Собственные команды bash называются builtin (встроенная команда), а для утилит выводится путь, содержащий название каталога, в котором лежит файл с соответствующей программой, и имя этой программы. Ключ “-a” («all», конечно), заставляет type вывести все возможные варианты интерпретации команды, а ключ “-t” — вывести тип команды вместо пути.


[methody@localhost methody]$ type date
 info is /bin/date
[methody@localhost methody]$ type echo
 echo is a shell builtin
[methody@localhost methody]$ type -a echo
 echo is a shell builtin
 echo is /bin/echo
[methody@localhost methody]$ type -a -t echo
 builtin
 file

Пример 10. Определение типа команды

Собственных команд в командном интерпретаторе немного. В основном это — операторы языка программирования и прочие средства управления самим интерпретатором. Все команды, выполняющие содержательную работу для пользователя, представлены в Linux в виде отдельных утилит. Вот и первая часть ответа на вопрос обо всех командах Linux: их столько же, сколько есть программ (утилит), написанных для Linux. Их список — это список установленных в системе утилит, и в разных системах он будет различным.

Часть 2: всему своё руководство

Каждый объект системы: все утилиты, все демоны Linux, все функции ядра и библиотек, структура большинства конфигурационных файлов, наконец, многие умозрительные, но важные понятия — должны обязательно сопровождаться документацией, описывающей их назначение и способы использования. Поэтому от пользователя системы не требуется заучивать все возможные варианты взаимодействия с ней. Достаточно понимать основные принципы её устройства и уметь находить справочную информацию. Эйнштейн говорил на этот счёт так: «Зачем запоминать то, что всегда можно посмотреть в справочнике?».

Больше всего различной полезной информации содержится в страницах руководства (manpages). Каждая страница руководства (для краткости — просто «руководство») посвящена какому-нибудь одному объекту системы. Для того, чтобы посмотреть страницу руководства, нужно дать команду man объект:


[methody@localhost methody]$ man cal
 CAL(1)               BSD General Commands Manual             CAL(1)

 NAME
     cal - displays a calendar

 SYNOPSIS
     cal [-smjy13] [[month] year]

 DESCRIPTION
     Cal displays a simple calendar.  If arguments are not specified, 
	 the current month is displayed.  The options are as follows:
 . . .

Пример 11. Просмотр страницы руководства

«Страница руководства» занимает, как правило, больше одной страницы экрана. Для того, чтобы читать было удобнее, man запускает программу постраничного просмотра текстов — less. Управлять программой less просто: страницы перелистываются пробелом, а когда читать надоест, надо нажать “q” (Quit). Перелистывать страницы можно и клавишами Page Up/Page Down, для сдвига на одну строку вперёд можно применять enter или стрелку вниз, а на одну строку назад — стрелку вверх. Переход на начало и конец текста выполняется по командам “g” и “G” соответственно (Go). Полный список того, что можно делать с текстом в less, выводится по команде “H” (Help).

Страница руководства состоит из полей — стандартных разделов, с разных сторон описывающих объект. При первом изучении руководства стоит начать с полей NAME (краткое описание объекта) и DESCRIPTION (развёрнутое описание объекта, достаточное для того, чтобы им воспользоваться). Одно из самых важных полей руководства находится в конце текста. Если в процессе чтения NAME или DESCRIPTION пользователь понимает, что не нашёл в руководстве того, что искал, он может захотеть посмотреть, а есть ли другие руководства или иные источники информации по той же теме. Список таких источников содержится в поле SEE ALSO:


[methody@localhost methody]$ man man
 . . .
 SEE ALSO
        apropos(1), whatis(1), less(1), groff(1), man.conf(5).
 . . .

Пример 12. Поле SEE ALSO руководства

В поле SEE ALSO обнаружились ссылки на руководства по less, groff (программе форматирования страницы руководства), структуре конфигурационного файла для man, а также по двум сопутствующим командам whatis и apropos, которые помогают отыскать нужное руководство. Обе они работают с базой данных, состоящей из полей NAME всех страниц руководства в системе. Различие между ними — в том, что whatis ищет только среди имён объектов (в левых частях полей NAME), а apropos — по всей базе. В результате у whatis получается список кратких описаний объектов с именами, включающими в себя искомое слово, а у apropos — список, в котором это слово упоминается.

В системе может встретиться несколько объектов разного типа, но с одинаковым названием. Часто совпадают, например, имена системных вызовов (функций ядра) и утилит, которые позволяют пользоваться этими функциями из командной строки. При ссылке на руководство по объекту системы принято непосредственно после имени объекта ставить в круглых скобках номер раздела, в котором содержится руководство по этому объекту: man(1), less(1), passwd(5). По такому формату легко опознать, что имеется в виду руководство.

В системе руководств Linux девять разделов, каждый из которых содержит страницы руководства к объектам определённого типа. Все разделы содержат по одному руководству с именем «intro», в котором в общем виде и на примерах рассказано, что за объекты имеют отношение к данному разделу. Список разделов с названиями можно получить командой whatis intro.

По умолчанию man просматривает все разделы и показывает первое найденное руководство с заданным именем. Чтобы посмотреть руководство по объекту из определённого раздела, необходимо в качестве первого параметра команды man указать номер раздела, например, man 8 passwd.

Другой источник информации о Linux и составляющих его программах — справочная подсистема info. Страница руководства, несмотря на обилие ссылок различного типа, остаётся «линейным» текстом, структурированным только логически. Документ info — это настоящий гипертекст, в котором множество небольших страниц объединены в дерево. В каждом разделе документа info всегда есть оглавление, из которого можно перейти сразу к нужному подразделу, откуда всегда можно вернуться обратно. Кроме того, info-документ можно читать и как непрерывный текст, поэтому в каждом подразделе есть ссылки на предыдущий и последующий подразделы. Можно догадаться, что подробное руководство по тому, как перемещаться между страницами в info можно получить по команде info info. Команда info, введённая без параметров, предлагает пользователю список всех документов info, установленных в системе.

Если некоторый объект системы не имеет документации ни в формате man, ни в формате info, это нехорошо. В этом случае можно надеяться, что при нём есть сопроводительная документация, не имеющая, увы, ни стандартного формата, ни тем более — ссылок на руководства по другим объектам системы. Такая документация (равно как и примеры использования объекта), обычно помещается в каталог /usr/share/doc/имя_объекта.

Документация в подавляющем большинстве случаев пишется на простом английском языке. Если английский — не родной язык для автора документации, она будет только проще. Традиция писать по-английски идёт от немалого вклада США в развитие компьютерной науки вообще и Linux в частности. Кроме того, английский становится языком международного общения во всех областях, не только в компьютерной. Необходимость писать на языке, который будет более или менее понятен большинству пользователей, объясняется постоянным развитием Linux. Дело не в том, что страницу руководства нельзя перевести, а в том, что её придётся переводить всякий раз, когда изменится описываемый ею объект! Например, выход новой версии программного продукта сопровождается изменением его возможностей и особенностей работы, а следовательно, и новой версией документации. Тогда перевод этой документации превращается в «moving target», сизифов труд.

Тем не менее, некоторые наиболее актуальные руководства всё-таки существуют в переводе на русский язык. Наиболее свежие версии таких переводов на русский собраны в пакете man-pages-ru — достаточно установить этот пакет, и те руководства, для которых есть перевод, man будет по умолчанию отображать на русском языке.

Переменные окружения

Помимо параметров, передаваемых в командной строке, в Linux есть ещё один способ модифицировать поведение программы — для этого используются переменные окружения. Чтобы объяснить принцип работы переменных окружения, потребуется небольшой экскурс в механизм взаимодействия процессов в Linux.

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

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

Создание одного процесса другим называется порождением процесса и происходит в два этапа: сначала создаётся точная копия исходного, родительского процесса (системный вызов fork()), а затем копия процесса подменяется новым, дочерним (системный вызов exec()). Для нас сейчас важно, что при этой подмене сохраняются все свойства исходного процесса, и, в частности, окружение.

Вернёмся к работе командного интерпретатора: выполняя команду, он запускает нужную утилиту в качестве дочернего процесса, дожидается окончания её работы (при помощи ещё одного системного вызова, wait()), анализирует результат и продолжает работу. Запущенная утилита получает от родительского процесса (командного интерпретатора) информацию двух типов: параметры командной строки (не в том виде, в котором их ввёл пользователь, а после обработки по правилам командного интерпретатора, в виде последовательного списка) и окружение, то есть все переменные и их значения, которые были определены в окружении родительского процесса.

Одна и та же утилита может быть использована одним и тем же способом, но в изменённом окружении — и выдавать различные результаты. Пользователь может явно изменить окружение для запускаемого процесса, присвоив некоторое значение переменной окружения в командной строке перед именем команды. Командный интерпретатор, увидев “=” внутри первого слова командной строки, приходит к выводу, что это — операция присваивания, а не имя команды, и запоминает, как надо изменить окружение команды, которая последует после.


[methody@localhost methody]$ date
 Пнд Июн 16 18:28:30 MSK 2008
[methody@localhost methody]$ LC_TIME=C date
 Mon Jun 16 18:28:51 MSK 2008

Пример 13. Утилита date пользуется переменной окружения LC_TIME

Переменная окружения LC_TIME предписывает использовать определённый язык при выводе даты и времени а значение “C” соответствует «стандартному системному» языку (чаще всего — английскому).

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


[methody@localhost methody]$ LC_TIME=C
[methody@localhost methody]$ date
 Пнд Июн 16 18:29:17 MSK 2008
[methody@localhost methody]$ export LC_TIME=C
[methody@localhost methody]$ date
 Mon Jun 16 18:29:38 MSK 2008

Пример 14. Экспорт переменных shell в окружение

Во время сеанса работы пользователя командный интерпретатор получает довольно богатое окружение, к которому добавляет и собственные настройки. Большинство заранее определённых переменных используются либо самой командной оболочкой, либо утилитами системы, поэтому их изменение приводит к тому, что оболочка или утилиты начинают работать слегка иначе. Просмотреть окружение в bash можно с помощью команды set.

К значению любой переменной в bash можно обратиться по имени: вместо конструкции $имя_переменной оболочка подставит значение этой переменной. Например, для того, чтобы просмотреть значение некоторой переменной, пользователь может ввести команду echo $имя_переменной.


[methody@localhost methody] echo $PATH
/home/methody/bin:/bin:/usr/bin:/usr/local/bin:/usr/X11R6/bin:/usr/games

Пример 15. Вывод значения переменной

Весьма примечательна переменная окружения PATH. В ней содержится список каталогов, элементы которого разделяются двоеточиями. Если команда в командной строке — не собственная команда shell (вроде cd) и не предствалена в виде пути к запускаемому файлу (как /bin/ls или ./script), то shell будет искать эту команду среди имён запускаемых файлов во всех каталогах PATH, и только в них. По этой причине исполняемые файлы невозможно запускать просто по имени, если они лежат в текущем каталоге, и текущий каталог не входит в PATH. В таких случаях можно воспользоваться кратчайшим из возможных путей, “./” (например, вызывая сценарий ./script).

Переменных окружения, влияющих на работу разных утилит, довольно много. Например, переменные семейства LC_ (полный их список выдаётся командой locale), определяющие язык, на котором выводятся диагностические сообщения, стандарты на формат даты, денежных единиц, чисел, способы преобразования строк и т. п. Если какая-то утилита требует редактирования файла, этот файл передаётся программе, путь к которой хранится в переменной EDITOR (обычно это /usr/bin/vi), а если потребуется открыть html-файл, то многие утилиты вызовут для этого программу, указанную в переменной BROWSER. Наконец, некоторые переменные вроде UID, USER или PWD просто содержат полезную информацию, которую можно было бы добыть и другими способами.


1В Linux основу API составляют системные вызовы и стандартные библиотечные функции.

2Игра слов: «Bourne Again» вслух читается как «born again», т. е. «возрождённый».

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

4Многие склонны вместо слова «ключ» употреблять слово «опция» как аналог английского option, однако это не признак хорошего стиля.

5Кстати, с незапамятных времён who поддерживает один нестандартный набор параметров: who am i делает то же, что и who -m.

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

Сведения о документе