За всю историю операционной системы UNIX для нее было создано огромное количество различных командных интерпретаторов. Некоторые из них предопределили дальнейшее развитие шеллов, единицы стали стандартом, а многие умерли сразу после рождения. Одни продолжают развиваться и сегодня, другие уже не поддерживаются. Как же сориентироваться и сделать правильный выбор?
История командных интерпретаторов UNIX началась, как и следовало предполагать, вместе с рождением самой операционной системы. Шелл, вошедший в поставку первой редакции UNIX и написанный Кэном Томпсоном (Ken Thompson), был по сегодняшним меркам очень простым и примитивным. Все, что он мог делать, - это читать команды, введенные пользователем, и запускать их на исполнение. Об интегрированном скриптовом языке, автодополнении и истории команд, так привычных сегодняшнему пользователю UNIX, никто тогда даже и не думал. Хотя возможность перенаправления вывода команды в файл уже была реализована.
В шелл третьей версии UNIX по предложению Дугласа Макилроя (Douglas McIlroy) была добавлена возможность перенаправления вывода одной команды на вход другой, а в четвертой версии она обрела свой нынешний облик (оператор «|»). Также были добавлены операторы if и goto, выполненные как отдельные программы.
Разработчики дистрибутива Programmer's Workbench UNIX модифицировали шелл Томпсона, чтобы сделать его более пригодным для программирования. В результате они выпустили PWB shell (или Mashey shell, по имени главного разработчика).
Многочисленные ограничения командного интерпретатора Томпсона не позволяли применять его в качестве полноценного скриптового языка и использовать для автоматизации работы. Этот факт волновал не только самих пользователей, но и программистов, привыкших перекладывать свою работу на плечи «железного помощника». И кто знает, сколько бы продолжалась такая несправедливость, если бы в один прекрасный день Стивен Борн (Stephen Bourne) не сел за терминал и не переписал стандартный шелл UNIX.
Именно перу Стивена Борна принадлежит тот синтаксис скриптового языка, который мы видим чуть ли не ежедневно, работая в консоли или программируя скрипты. И сколько бы пользователи не ругали все эти done, fi, esac и другие синтаксические причуды, Борн позволил UNIX сделать большой шаг вперед и на много лет предопределил направление развития командных интерпретаторов.
Компания AT&T включила командный интерпретатор Борна в базовую поставку седьмой версии UNIX, полностью заменив им шелл Томпсона. Позднее Кэннет Алквист (Kenneth Almquist) создал свободный вариант шелла Борна под названием Almquist shell (ash). Сегодня он используется в Debian, Ubintu и некоторых BSD-системах как интерпретатор стартовых скриптов, а также входит в состав пакета BusyBox, предназначенного для использования во встроенных версиях Linux.
Можно было бы предположить, что после того как Стивен Борн расширил шелл Томпсона до полноценного скриптового языка программирования, история командных интерпретаторов пойдет эволюционным путем и завершится где-нибудь на отметке zsh. Но все повернулось совершенно иначе. В 1979 году небезызвестный Билл Джой (Bill Joy), активный разработчик BSD UNIX и создатель редактора vi, сделал свою версию командного интерпретатора со встроенным скриптовым языком и назвал его C shell (csh).
C shell не унаследовал нововведений, сделанных Стивеном Борном, потому как базировался на коде командного интерпретатора шестой версии UNIX, который был хоть и расширенным, но все же шеллом Томпсона. Скриптовый язык csh не уступает шеллу Борна по мощности, но отличается синтаксисом. В то время как Борн скопировал все основные операторы с языка Algol68, Билл Джой использовал в качестве макета язык Си, вероятно, руководствуясь своими предпочтениями и предпочтениями других пользователей BSD UNIX.
Некоторым пользователям синтаксис C shell может показаться более правильным и очевидным, нежели синтаксис шелла Борна, но на самом деле это не так. В начале 90-х C shell подвергся большой критике за свою двусмысленность и немногословность интерпретатора, останавливающего выполнение скрипта, но не сообщающего никаких подробностей о том, что же все-таки произошло. Порой скрипты csh работали совсем не так, как этого ожидал пользователь. Также встречались ситуации, когда интерпретатор отбраковывал, казалось бы, непротиворечивые строки кода.
Но все-таки Биллу Джою нужно отдать должное. В csh было сделано несколько нововведений, которые не только стали частью всех современных командных интерпретаторов UNIX, но и вошли в стандарт POSIX. Среди них:
C shell вошел в поставку 4.1BSD и до сих пор остается базовой частью всех ее потомков, в том числе FreeBSD и OpenBSD.
Кэн Грир (Ken Greer), вдохновленный возможностями командного интерпретатора операционной системы TENEX, создал свою, расширенную версию C shell и назвал ее TENEX C shell (tcsh). Основной инновацией шелла стала одна из самых востребованных сегодня возможностей - автодополнение путей и команд. Именно эта особенность сделала шелл TENEX таким привлекательным и, как следствие, стала главной причиной его популярности. Несколько позднее в tcsh была добавлена другая не менее интересная и востребованная возможность - редактирование командной строки. Теперь можно было стереть введенную строку, заменить в ней слова, переместить курсор в начало или конец строки (большинство современных командных интерпретаторов используют библиотеку readline для выполнения таких манипуляций).
По мере развития tcsh в него добавлялось все больше новых функций. Сегодняшняя версия этого шелла обладает такими возможностями, как:
Это лишь некоторые из функций tcsh. По всем признакам это современный и удобный в использовании командный интерпретатор, развитие которого продолжается по сей день.
На tcsh история командных интерпретаторов с Си-подобным синтаксисом фактически заканчивается, и мы возвращаемся к потомкам шелла Борна. В начале 80-х Дэвид Корн (David Korn), один из сотрудников Bell Labs, начал работу над командным интерпретатором, расширяющим возможности шелла Борна. По сложившейся традиции, новый шелл был назван в честь создателя - Korn shell (ksh).
В первую версию ksh вошло несколько изменений, облегчающих создание скриптов, а также скопированные из csh (по просьбам пользователей) функции работы с историей. В шелле Корна впервые появилась возможность редактирования командной строки (стили emacs и vi), позже она была перенесена в tcsh. Кроме того, шелл Корна позволял использовать клавиши «вверх» и «вниз» для навигации по истории. Версия, выпущенная в 1986 году, обрела полную совместимость с мультибайтовыми кодировками.
Версия ksh88 стала частью UNIX System V Release 4 и была одобрена для включения в стандарт POSIX. В последнем релизе ksh, выпущенном в 1993 году, появилась возможность изменения функций горячих клавиш, а также множество дополнений к скриптовому языку. В частности, интерпретатор ksh93 научился работать с ассоциативными массивами (хэш, в терминологии Perl), выполнять операции над числами с плавающей точкой, динамически загружать встроенные команды, работать с «активными» и «смешанными» переменными (это придавало переменным некоторые черты «объектов»). Также в эту версию ksh была добавлена полностью совместимая со стандартом ANSI-C функция printf.
Оригинальная версия ksh до 2000 года оставалась закрытой, и поэтому появилось несколько совместимых командных интерпретаторов, распространяемых свободно. В их число вошли pdksh (Public Domain Korn shell), bash и zsh.
Bourne again shell (bash) - это командный интерпретатор, созданный Браином Фоксом (Brian Fox) в рамках проекта GNU. Вначале он позиционировался как свободная замена закрытому ksh, но позднее вырос в независимый продукт с несколькими оригинальными нововведениями. Bash полностью совместим с шеллом Борна и стандартом POSIX. Многие его возможности взяты из ksh и csh. Редактирование командной строки, история команд, фоновое исполнение заданий, стек каталогов (команды pushd и popd), подстановка результата исполнения команды ('$(...)'), автодополнение имен команд и каталогов, встроенная поддержка арифметических операций ('((...))') - все это есть в bash.
Кроме того, bash обладает несколькими уникальными характеристиками, такими как, например, одновременное перенаправление выходного потока и потока ошибок (&>), перенаправление стандартного входа из строки (<<< 'строка'), открытие и закрытие файлов (exec 3 <file; exec 3 <&-) и работа с сокетами (exec 3<>/dev/tcp/www.host.ru/25; echo -e "HELLO www.myhost.ru" >&3). В третью версию bash были добавлены встроенный отладчик скриптов, возможность сравнения с регулярным выражением ([[ строка =~ шаблон ]]) и новый вид замен (конструкция «{x..y}» заменяется строкой из чисел от x до y).
Bash - наиболее популярный командный интерпретатор на сегодняшний день. Он включен в стандартную поставку абсолютного большинства дистрибутивов Linux, а во многих из них выступает в качестве интерпретатора стартовых скриптов.
«Перенесите большой и тяжелый кухонный комбайн, способный заменить всю остальную бытовую технику на Вашей кухне, в мир командных интерпретаторов - и Вы получите Z shell» - с таких слов должна начинаться web-страница программы zsh.
Z shell (zsh) был написан в 1990 году Полом Фолстадом (Paul Falstad) во время его учебы в университете Принстона. Имя для командного интерпретатора он выбрал практически случайно, использовав логин zsh, которым пользовался ассистент его учителя Zhong Shao для входа в операционную систему.
Описать zsh, даже поверхностно, в таком маленьком обзоре практически невозможно. Zsh - это огромный «комбайн», которым можно заменить все остальные шеллы, представленные в этой статье. Он может быть подобен sh, csh или tcsh. Он может быть полностью совместим с bash, а может быть не похож ни на что. Можно применять zsh как ftp- или irc-клиент, писать с его помощью серверные программы, обрабатывающие запросы клиентов, или вовсе не знать о его мощи и использовать как обычный командный интерпретатор. По заложенному в программу потенциалу и многогранности областей применения zsh сравним разве что с редактором emacs.
Кроме эмуляции функциональности всех рассмотренных выше командных интерпретаторов, zsh также порадует пользователя следующими возможностями:
Практически неограниченная мощь zsh одновременно является и его недостатком. Это очень трудный в освоении командный интерпретатор (имеется в виду освоение всех функций), полное описание которого занимает больше 300 страниц формата A4.
Описанные выше шеллы в большинстве своем достаточно сложны для освоения новичками и не могут быть отнесены к разряду дружелюбных к пользователю программ. Fish, созданный Axel Liljencrantz (не возьмусь за перевод этого имени), выгодно отличается от них в этом отношении. Этот командный интерпретатор не просто наиболее близок к определению «простой в использовании шелл», но и представляет несколько функций, интересных даже профессионалам.
Хотя синтаксис скриптового языка fish несколько отличается от синтаксиса bash и других шеллов, этот факт нас мало волнует. Наиболее «вкусные» его особенности связаны с интерактивным аспектом работы программы. В fish встроен расширенный механизм автодополнений, который печатает не только возможные варианты дополнений, но и их описание (набрав, например, «l», ты получишь на экране таблицу, в которой будут перечислены все команды, начинающиеся с «l», и краткое описание каждой из них). При возникновении ошибки fish выводит не только полное описание ошибки, но и возможные пути ее решения. Кроме этого, fish подсвечивает синтаксис своего скриптового языка прямо в окне терминала.
Оболочка ash представляет собой одну из самых маленьких оболочек, доступных в *nix (за счет малых требований к памяти и дисковому пространству, по сравнению с другими sh-совместимыми оболочками). Этот командный интерпретатор имеет 24 встроенные команды и 10 различных опций командной строки. Обычно ash используется при загрузке Linux в однопользовательском режиме, в защищенном режиме или при загрузке дискетных версий Linux. Также с ее помощью можно проверять скрипты на sh-совместимость. В NetBSD в качестве /bin/sh работает именно ash.
Shell (наиболее близкий аналог в русском языке – оболочка) - программное обеспечение, создающее интерфейс между пользователем и операционной системой. Shell может быть как текстовым (CLI, командный интерпретатор), так и графическим (GUI). К первому типу можно отнести командные интерпретаторы sh, bash, zsh, второй составляют комплексы программ, обеспечивающих графическое окружение пользователя, такие как KDE, Gnome и XFCE.
Для пользователя современных UNIX-подобных операционных систем установка, удаление или замена командного интерпретатора - обычное дело. Но так было не всегда. Шелл, исполняемый как отдельный процесс, впервые появился в ОС Multics, предшественнице UNIX. В более ранних операционных системах он был встроен в ядро.