headermask image



Командные интерпретаторы: сравнения и история

За всю историю операционной системы UNIX для нее было создано огромное количество различных командных интерпретаторов. Некоторые из них предопределили дальнейшее развитие шеллов, единицы стали стандартом, а многие умерли сразу после рождения. Одни продолжают развиваться и сегодня, другие уже не поддерживаются. Как же сориентироваться и сделать правильный выбор?

Thompson shell

История командных интерпретаторов UNIX началась, как и следовало предполагать, вместе с рождением самой операционной системы. Шелл, вошедший в поставку первой редакции UNIX и написанный Кэном Томпсоном (Ken Thompson), был по сегодняшним меркам очень простым и примитивным. Все, что он мог делать, – это читать команды, введенные пользователем, и запускать их на исполнение. Об интегрированном скриптовом языке, автодополнении и истории команд, так привычных сегодняшнему пользователю UNIX, никто тогда даже и не думал. Хотя возможность перенаправления вывода команды в файл уже была реализована.

В шелл третьей версии UNIX по предложению Дугласа Макилроя (Douglas McIlroy) была добавлена возможность перенаправления вывода одной команды на вход другой, а в четвертой версии она обрела свой нынешний облик (оператор «|»). Также были добавлены операторы if и goto, выполненные как отдельные программы.

Разработчики дистрибутива Programmer’s Workbench UNIX модифицировали шелл Томпсона, чтобы сделать его более пригодным для программирования. В результате они выпустили PWB shell (или Mashey shell, по имени главного разработчика).

Bourne shell

Многочисленные ограничения командного интерпретатора Томпсона не позволяли применять его в качестве полноценного скриптового языка и использовать для автоматизации работы. Этот факт волновал не только самих пользователей, но и программистов, привыкших перекладывать свою работу на плечи «железного помощника». И кто знает, сколько бы продолжалась такая несправедливость, если бы в один прекрасный день Стивен Борн (Stephen Bourne) не сел за терминал и не переписал стандартный шелл UNIX.

Именно перу Стивена Борна принадлежит тот синтаксис скриптового языка, который мы видим чуть ли не ежедневно, работая в консоли или программируя скрипты. И сколько бы пользователи не ругали все эти done, fi, esac и другие синтаксические причуды, Борн позволил UNIX сделать большой шаг вперед и на много лет предопределил направление развития командных интерпретаторов.

Основными нововведениями Борна стали:

  • оператор ветвления if … then … elif … else … fi;
  • оператор цикла for … do … done;
  • оператор выбора case … in … esac;
  • переменные окружения;
  • подстановка результата исполнения команды (‘$(…)’);
  • возможность перенаправления файлового дескриптора 2 (2>), позволяющая разделять поток данных и поток ошибок.

Компания AT&T включила командный интерпретатор Борна в базовую поставку седьмой версии UNIX, полностью заменив им шелл Томпсона. Позднее Кэннет Алквист (Kenneth Almquist) создал свободный вариант шелла Борна под названием Almquist shell (ash). Сегодня он используется в Debian, Ubintu и некоторых BSD-системах как интерпретатор стартовых скриптов, а также входит в состав пакета BusyBox, предназначенного для использования во встроенных версиях Linux.

C shell

Можно было бы предположить, что после того как Стивен Борн расширил шелл Томпсона до полноценного скриптового языка программирования, история командных интерпретаторов пойдет эволюционным путем и завершится где-нибудь на отметке 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. Среди них:

  • расширение пути до домашнего каталога (символ «~»);
  • псевдонимы (команда alias);
  • управление заданиями (фоновое исполнение команды с помощью указания символа «&» после команды и встроенная команда jobs);
  • работа с историей (повторное выполнение команды с помощью указания перед ней символа «!» и навигация по истории команд);
  • массивы;
  • математические операции.

C shell вошел в поставку 4.1BSD и до сих пор остается базовой частью всех ее потомков, в том числе FreeBSD и OpenBSD.

TENEX C shell

Кэн Грир (Ken Greer), вдохновленный возможностями командного интерпретатора операционной системы TENEX, создал свою, расширенную версию C shell и назвал ее TENEX C shell (tcsh). Основной инновацией шелла стала одна из самых востребованных сегодня возможностей – автодополнение путей и команд. Именно эта особенность сделала шелл TENEX таким привлекательным и, как следствие, стала главной причиной его популярности. Несколько позднее в tcsh была добавлена другая не менее интересная и востребованная возможность – редактирование командной строки. Теперь можно было стереть введенную строку, заменить в ней слова, переместить курсор в начало или конец строки (большинство современных командных интерпретаторов используют библиотеку readline для выполнения таких манипуляций).

По мере развития tcsh в него добавлялось все больше новых функций. Сегодняшняя версия этого шелла обладает такими возможностями, как:

  • редактирование командной строки с поддержкой стилей vi и emacs;
  • программируемое автодополнение (шелл можно настроить так, чтобы по нажатию <Tab> дополнялись не только имена команд и пути, но и, например, поддерживаемые командой флаги);
  • проверка правописания имен файлов, команд и переменных;
  • расширенный механизм навигации по каталогам (команды pushd, popd, dirs);
  • периодические события (например, отложенное во времени исполнение команды или «сброс» пользователя по истечении тайм-аута).
  • возможность указания в приглашении различной полезной информации (текущий каталог, время, дата).

Это лишь некоторые из функций tcsh. По всем признакам это современный и удобный в использовании командный интерпретатор, развитие которого продолжается по сей день.

Korn shell

На 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

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

«Перенесите большой и тяжелый кухонный комбайн, способный заменить всю остальную бытовую технику на Вашей кухне, в мир командных интерпретаторов – и Вы получите 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 можно научить дополнять по клавише <Tab> все что угодно);
  • расширенные маски файлов (‘*’ и ‘?’ – это лишь начальный уровень, по меркам zsh);
  • расширенные функции работы с переменными и массивами;
  • расширенный механизм редактирования командной строки (zsh использует собственный вариант readline, названный zle, который делает редактирование строк более гибким);
  • расширенный механизм настройки приглашения (zsh позволяет, например, поместить часть приглашения в правую сторону экрана);
  • единая история команд для всех запущенных экземпляров zsh (можно быть уверенным, что история одного экземпляра zsh не перекроет историю другого);
  • загружаемые модули, позволяющие расширять набор встроенных команд без модификации кода (например, модуль zftp для работы с протоколом ftp добавляет в набор одноименную команду);
  • zsh чрезвычайно конфигурируемый, практически любой его параметр поддается настройке.

Практически неограниченная мощь zsh одновременно является и его недостатком. Это очень трудный в освоении командный интерпретатор (имеется в виду освоение всех функций), полное описание которого занимает больше 300 страниц формата A4.

Friendly interactive shell

Описанные выше шеллы в большинстве своем достаточно сложны для освоения новичками и не могут быть отнесены к разряду дружелюбных к пользователю программ. Fish, созданный Axel Liljencrantz (не возьмусь за перевод этого имени), выгодно отличается от них в этом отношении. Этот командный интерпретатор не просто наиболее близок к определению «простой в использовании шелл», но и представляет несколько функций, интересных даже профессионалам.

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

Хронология развития командных интерпретаторов UNIX

  • Thompson shell (1971 год, первая версия UNIX, Ken Thompson);
  • Bourne shell, или sh (1977 год, Version 7 UNIX, Stephen Bourne);
  • C shell, или csh (1979 год, 4.1BSD, Bill Joy);
  • Tenex C shell, или tcsh (конец 70-х, BSD UNIX, Ken Greer);
  • Korn shell, или ksh (1983 год, AT&T UNIX, David Korn);
  • Bourne again shell, или bash (1987 год, POSIX, Brian Fox);
  • Z shell, или zsh (1990 год, POSIX, Paul Falstad);
  • Friendly interactive shell, или fish (2005 год, POSIX, Axel Liljencrantz).

Особенности оболочки ash

Оболочка ash представляет собой одну из самых маленьких оболочек, доступных в *nix (за счет малых требований к памяти и дисковому пространству, по сравнению с другими sh-совместимыми оболочками). Этот командный интерпретатор имеет 24 встроенные команды и 10 различных опций командной строки. Обычно ash используется при загрузке Linux в однопользовательском режиме, в защищенном режиме или при загрузке дискетных версий Linux. Также с ее помощью можно проверять скрипты на sh-совместимость. В NetBSD в качестве /bin/sh работает именно ash.

INFO

Shell (наиболее близкий аналог в русском языке – оболочка) – программное обеспечение, создающее интерфейс между пользователем и операционной системой. Shell может быть как текстовым (CLI, командный интерпретатор), так и графическим (GUI). К первому типу можно отнести командные интерпретаторы sh, bash, zsh, второй составляют комплексы программ, обеспечивающих графическое окружение пользователя, такие как KDE, Gnome и XFCE.

Для пользователя современных UNIX-подобных операционных систем установка, удаление или замена командного интерпретатора – обычное дело. Но так было не всегда. Шелл, исполняемый как отдельный процесс, впервые появился в ОС Multics, предшественнице UNIX. В более ранних операционных системах он был встроен в ядро.

Автор: Евгений «j1m» Зобнин
Опубликовано в апрельском номере журнала Хакер

Похожие посты
  • No related posts
  • Комментарии

    Your email is never published nor shared. Required fields are marked *

    *
    *