Алексей Федорчук
Шелл (Shell), именуемый по-русски командной оболочкой, командным интерпретатором, командным процессором или иными, столь же неизящными словосочетаниями, - это первая программа, с которой сталкивается пользователь любой POSIX-совместимой ОС. И с ним же последним он расстается, выходя из системы. А все его действия во время работы - суть прямые или опосредованные команды, выполняемые в среде шелла. И даже если основная часть работы пользователя проходит в графическом режиме, в окружении интегрированных сред или оконных менеджеров, - окно терминала с приглашением командной строки быстро станет неотъемлемым атрибутом любого десктопа. Ибо именно команды оболочки - самый простой и эффективный путь к выполнению всех операций по управлению файлами, многих задач обработки текста, да и просто запуска любых программ, что в консоли, что - в графическом режиме.
Кроме того, всегда следует помнить, что вообще функционирование Unix-подобной системы в значительной мере происходит в шелл-среде. Ибо шелл-сценариями являются все скрипты инициализации системы, многие общесистемные и пользовательские конфигурационные файлы, такие системы управления пакетами, как порты FreeBSD и портежи Gentoo Linux. Ну и то, что любой пользователь свободных ОС рано или поздно начинает писать собственные сценарии оболочки - неизбежно, как распад мировой системы социализма (кто еще не начал - уж поверьте мне на слово, хотя скажи мне такое лет пять назад - сам бы не поверил).
Сказанного в преамбуле, думаю, достаточно, чтобы отнестись к выбору шелла со всей ответственностью. Причем при выборе этом должно учитываться два аспекта применения шелла - как среды для пользовательской работы, так и системы для исполнения общесистемных и пользовательских сценариев.
Первый аспект охватывается понятием интерактивный шелл.
Это - любой экземпляр командной оболочки, запущенный пользователем
непосредственно. Если этот экземпляр запускается при входе пользователя
в систему, его называют login shell. Очевидно, что login shell - также интерактивен, однако в сеансе работы каждого пользователя он
будет единственным. Просто же интерактивных шеллов можно запустить
сколько угодно - например, в каждом окне эмулятора терминала в Иксах
будет функционировать собственная копия интерактивного шелла.
Имя исполняемого файла, запускающего login shell (вместе с полным путем к оному - например, /bin/sh)
- атрибут учетной записи каждого реального пользователя системы.
Теоретически в этом качестве могут выступать не только собственно шеллы
(то есть командные оболочки), но и интерпретатор какого-либо языка
программирования (например, Tcl), программа типа Midnight Commander или
даже текстовый редактор. Однако эти случаи - специальные, и ниже далее
рассматриваться не будут.
Второй аспект использования шелла - неинтерактивный. Неинтерактивный шелл - это экземпляр командной оболочки, вызываемый при выполнении пользователем любой команды или любого сценария. Он может быть вызван неявным или явным образом. Первый случай имеет место быть при выполнении команды из строки оболочки - ведь в этом случае создается (посредством системного вызова fork) точная копия породившего процесса (то есть той же интерактивной оболочки), а уже она вызовом exec запускает на исполнение введенную пользователем команду.
При составлении пользовательского или системного сценария шелл, вызываемый для его исполнения, можно указать явным образом - и настоятельно рекомендуется этой возможностью пользоваться. Делается это в первой строке скрипта, называемой sha-bang, которая по правилам должна иметь вид вроде
#!/bin/bash
То есть после символов решетки (#) и восклицания (!
- видимо, для пущей экспрессии:-)) указывать полный абсолютный путь к
исполнимому файлу, оболочку запускающему. Делается это, в том числе, и
во избежание недоразумений - так, просто единичный символ решетки в
первой строке может быть интерпретирован не как комментарий, а как
указание на запуск командной оболочки csh. И если сценарий был написан не для нее (а, например, для того же /bin/sh) - он, в силу различия синтаксиса, просто не будет выполнен.
Подчеркнем еще раз: хотя команда, запускающая интерактивный или
неинтерактивный шелл, может носить то же имя, что и команда на запуск login shell (а в Linux, скажем, обычно так и есть), это - разные экземпляры программы, которые в общем случае могут быть настроены независимо. А
значит - и вести себя разным образом. И потому не следует удивляться,
когда bash в эмуляторе терминала не реагирует на управляющие клавиши, привычные для того же bash в виртуальной консоли. А Midnight Commander отказывается в своей командной строке опознавать пути к исполняемым файлам.
Очевидно, что претензии пользователя к интерактивному (особенно к пользовательскому login shell)
и неинтерактивному шеллам могут быть
разными. В первом случае, как явствует из названия, важнее всего
удобство интерактивной работы - развитые средства автодополнения,
работы с историей команд, возможности гибкой и информативной настройки
приглашения командной строки. Для неинтерактивного же шелла на первый
план выходят быстродействие и совместимость.
С быстродействием все понятно - когда единственной задачей командной оболочки является вызов на исполнение другой команды (или, в случае скрипта, серии связанных команд) - тратить ресурсы на обеспечение дополнительных возможностей может быть излишеством. А вот о совместимости следует сказать особо. Но сначала - несколько слов о том,
Большая часть командных оболочек делится, на основе синтаксиса интерпретируемого ими языка, на две группы - sh- и csh-совместимые (о специфических шеллах, базирующихся, например, на диалекте LISP, я говорить не буду за их незнанием). На самом деле различия между ними синтаксисом команд не исчерпываются, а лежат глубже - в подходе к обработке командных конструкций, однако сейчас это не существенно.
Оболочки, относимые к sh-совместимым, происходят от первой командной оболочки первых Unix-систем, которую так и называют - shell или Bourne Shell (то есть шелл Борна). В ней были заложены многие возможности для интерпретации команд и их конструкций, то есть составления системных и пользовательских сценариев. Однако по своим интерактивным возможностям она оставляла желать лучшего, и потому на базе ее была создана оболочка Корна (Korne Shell).
Шелл Корна сохранил совместимость с борновским шеллом на уровне синтаксиса, однако привнес в него как дополнительные возможности интерпретации, так и приемы, направленные на удобство интерактивной работы. И потому именно он лег в основу стандарта POSIX (Portable Operation System Interface), которому должны удовлетворять командные оболочки POSIX-совместимых систем.
Следует заметить, что соответствие этому стандарту - один из
критериев отнесения некоей ОС к семейству Unix или Unix-подобных. В
частности, именно такой стандартизированный шелл должен вызываться при
исполнении общесистемных сценариев (например, инициализации) любой
POSIX-системы. Сам же по себе POSIX shell - некая мифическая
абстракция, ближе к которой подходят /bin/sh - умолчальная пользовательская оболочка из FreeBSD, и ash, принятая в качестве стандартной в NetBSD (а также широко используемая во всяких мини-дистрибутивах Linux).
Шеллы и Борна, и Корна не были свободно распространяемыми программами в
понимании FSF или BSD. Поэтому ни тот, ни другой не могли
использоваться в таких ОС, как *BSD или Linux, хотя свободная
реализация оболочки Корна (pdksh) и была создана. Однако, как и ее
прототип, шелл Корна, она, несколько развившись относительно
первозданного Bourne shell, обладала интерактивными достижениями,
далекими от идеала. Столь же слабы они были и в ash. И потому наиболее широкое распространение получила оболочка bash (что расшифровывается как "еще одна оболочка Борна", "заново рожденный шелл"
и тому подобным образом), разработанная в рамках проекта GNU.
Популярность bash в немалой степени была
обусловлена его интерактивными возможностями - он аккумулировал все
достижения интерактивной мысли sh- и csh-совместимых оболочек, прибавив
к ним немало собственных. И умудрившись при этом сохранить базовую
совместимость с POSIX shell. Конечно, многие его собственные фичи
("bash'измы") выходили за рамки этого стандарта. Однако для
соответствия оному был предусмотрен режим совместимости - то есть bash был способен эмулировать стандартный POSIX shell.
Однако главным для bash было то, что эта оболочка оказалась тесно интегрирована с операционной системой Linux: именно bash
волею судеб стал одной из первых программ, которые Линус запустил
поверх своего новосозданного ядра. И потому идеи bash-скриптинга
пронизали Linux до самых его оснований. Ну а для совместимости
использовался тот самый
режим эмуляции: в Linux файл, запускающий POSIX shell (по стандарту он
должен именоваться /bin/sh), являет собой жесткую или символическую ссылку на реальный /bin/bash (или /usr/bin/bash).
Последний же, будучи вызванным таким образом, полностью воспроизводит
стандартный POSIX shell (разумеется, путем утраты своих продвинутых
фич).
Клан csh-совместимых оболочек развивался параллельно сынам и пасынкам Борна. Собственно оболочка csh
была создана в Университете Беркли в ходе реализации проекта BSD Unix
(тогда - именно так). Она получила дополнительные интерактивные
возможности, во многом превосходящие таковые у современного ей шелла
Корна. Главное же - языку, ею интерпретируемому, были приданы черты
синтаксического сходства с языком Си (откуда, собственно, и название -
C-Shell, хотя не следует думать, что на всамделишний Си ее
интерпретируемый язык похож). В результате оболочка csh
оказалась весьма эффективной как для интерактивной работы, так и при
создании сценариев. Только вот сценарии эти не были совместимы со
скриптами POSIX shell, обретшего уже силу стандарта. То есть для
создания общесистемных сценариев она оказалась практически не
пригодной.
В отличие от большинства прочих достижений берклианской мысли, оболочка csh,
по не вполне ясным для меня причинам, не обрела статуса свободной
программы. Поэтому она не могла использоваться даже в своих родных
пределах - в BSD-системах. Однако на замену ей была изобретена
свободная оболочка tcsh - не просто функциональное воспроизводство, но дальнейшее развитие оболочки csh. По интерактивным возможностям она, как минимум, не уступает bash и потому утвердилась в стане свободных BSD-клонов.
В частности, оболочка tcsh принята в качестве login shell для суперпользователя во FreeBSD. Правда, вызывается она в режиме совместимости с csh, однако /bin/csh - не более чем жесткая ссылка на /bin/tcsh, в чем легко убедиться, выведя идентификаторы их исполнимых файлов:
$ ls -i /bin/*csh 16548 /bin/csh* 16548 /bin/tcsh*
Оболочка tcsh используется в качестве
универсального "умолчального" пользовательского шелла также в OpenBSD.
Однако характерно, что все общесистемные сценарии в обеих ОС написаны,
тем не менее, в соответствие с требованиями POSIX Shell.
Из приведенного краткого обзора можно видеть, что в плане шеллов
выбор пользователя достаточно обширен. А ведь я остановился только на
самых распространенных. Однако рискну предположить, что большинство
начинающих пользователей Linux'а об этом не особо задумываются. Ведь по
умолчанию во всех его дистрибутивах в качестве шелла по умолчанию
принят bash, обладающий как развитыми средствами интерпретации, так и продвинутыми интерактивными возможностями, да еще при сохранении совместимости со стандартом. Так зачем, казалось бы, искать добра от добра?
Первый вариант ответа очевиден - добро это дополнительное ищется в тех случаях, когда необходима минимизация ресурсов. Когда bash,
занимающий более полумегабайта на диске (и около полутора - в памяти)
оказывается излишне громоздким и медленным. Впрочем, первое играет роль
только для всяких rescue-систем на дискетах (и прочих "мелких"
носителях), а второе на современных машинах нечувствительно. Тем не
менее, маленький и быстрый шелл Альмкивста (ash) может оказаться подходящим не только в спасательных целях, но и для всякого рода скриптинга. Хотя работать в строке ash регулярно мне бы не хотелось...
Вторая причина поиска нового шелла - неудовлетворенность возможностями
имеющегося. Эта проблема остро встает перед пользователями FreeBSD - уж
очень убог его умолчальный login shell для обычного пользователя в плане интерактивной работы. Что особенно наглядно проступает в сравнении с tcsh,каковой по определению получает в свое распоряжение root-оператор. А
потому и простой юзер может поддаться искушению и выбрать себе тот же tcsh - хотя бы ради единства стиля работы (ведь на настольной машине тот же юзер, как правило, сам себе root).
Должен заметить, что именно при первом приобщении к FreeBSD я и перепробовал целый ряд доступных в ней шеллов. Благо через систему портов или коллекцию пакетов они столь же легко удалялись, как и устанавливались. Не обошел я своим вниманием и tcsh - и в целом остался им доволен. Как интерактивная оболочка tcsh, на мой взгляд, несколько превосходит bash (хотя и не принципиально). Однако непривычность синтаксиса (или
необходимость его изучения) способны отвратить от этого шелла. Тем паче, что редактирование системных скриптов или, тем более, сочинение собственных сценариев все равно требует обращения к sh-скриптингу.
И, наконец, третья причина для изысканий - поиски идеала (а не они ли движут, осознанно или нет, изрядной долей пользователей свободных POSIX-систем?). Спору нет, bash - оболочка хорошая, но до такого идеала явно не дотягивающая, слишком много в нем направлено на достижения баланса компактности и
функциональности. Должен сказать, что мои поиски идеала успехом увенчались. И потому наступает время обратиться к рассмотрению того шелла, который я полагаю лучшим в качестве интерактивного инструмента - Z-Shell, или просто zsh.