From: Алексей Федорчук <alv@linux-online.ru>
Newsgroups: http://www.linuxshop.ru/unix4all/
Date: Mon, 25 Dec 2003 14:31:37 +0000 (UTC)
Subject: Введение в Zsh
Zsh, или мой любимый шелл
Откуда всевластье ее взялось - поди, распроси иных.
Но пришла она первой в эти края, и последней оставит их.
Александр Галич
Шелл, именуемый по русски командной оболочкой, командным
интерпретатором, командным процессором или иными, столь же неизящными
словосочетаниями, - это первая программа, с которой сталкивается
пользователь, авторизовавшись в текстовой консоли. И с ним же
последним он расстается, выходя из системы. А все его действия во
время работы - суть прямые или опосредованные команды, выполняемые в
среде шелла. И даже если основная часть работы пользователя проходит в
графическом режиме, в окружении интегрированных сред или оконных
менеджеров, - окно терминала с приглашением командной строки быстро
станет неотъемлемым атрибутом любого десктопа. Ибо именно команды
оболочки - самый простой и эффективный путь к выполнению всех операций
по управлению файлами, многих задач обработки текста, да и просто
запуска любых программ, что в консоли, что - в графическом режиме.
Кроме того, всегда следует помнить, что вообще функционирование
Unix-подобной системы в значительной мере происходит в шелл-среде. Ибо
шелл-сценариями являются все скрипты инициализации системы, многие
общесистемные и пользовательские конфигурационные файлы, такие системы
управления пакетами, как порты FreeBSD и портежи Gentoo Linux. Ну и
то, что любой пользователь свободных ОС рано или поздно начинает
писать собственные сценарии оболочки - неизбежно, как распад мировой
системы социализма (кто еще не начал - уж поверьте мне на слово, хотя
скажи мне такое года четыре назад - сам бы не поверил).
О шеллах вообще
Сказанного в преамбуле, думаю, достаточно, чтобы отнестись к выбору
шелла со всей ответственностью. Причем при выборе этом должно
учитываться два аспекта применения шелла - как среды для
пользовательской работы, так и системы для исполнения общесистемных и
пользовательских сценариев.
Первый аспект охватывается понятием интерактивный шелл. Это - любой
экземпляр командной оболочки, запущенный пользователем
непосредственно. Если этот экземпляр запускается при входе
пользователя в систему, его называют login shell. Очевидно, что login
shell - также интерактивен, однако в сеансе работы каждого
пользователя он будет единственным. Просто же интерактивных шеллов
можно запустить сколько угодно - например, в каждом окне эмулятора
терминала в Иксах будет функционировать собственная копия
интерактивного шелла.
Имя команды, запускающей login shell (например, /bin/bash), - атрибут
учетной записи каждого реального пользователя системы. Теоретически в
этом качестве могут выступать не только собственно шеллы (то есть
командные оболочки), но и интерпретатор какого-либо языка
программирования (например, Tcl) или программа типа Midnight
Commander. Однако эти случаи - специальные, и ниже далее
рассматриваться не будут.
Второй аспект использования шелла - неинтерактивный. Это - экземпляр
командной оболочки, вызываемый при выполнении пользователем любой
команды или любого сценария. Он может быть вызван неявным или явным
образом. Первый случай имеет место быть при выполнении команды из
строки оболочки - ведь в этом случае создается (посредством системного
вызова fork) точная копия породившего процесса (то есть той же
интерактивной оболочки), а уже она вызовом exec запускает на
исполнение введенную пользователем команду.
При составлении пользовательского или системного сценария шелл,
вызываемый для его исполнения, можно указать явным образом - и
настоятельно рекомендуется этой возможностью пользоваться. Делается
это в первой строке скрипта, которая должна иметь вид вроде
#!/bin/bash
То есть после символов решетки (#) и восклицания (! - видимо, для
пущей экспрессии) указывать полный абсолютный путь к исполнимому
файлу, оболочку запускающему. Делается это, в том числе, и во
избежание недоразумений - так, просто единичный символ решетки в
первой строке будет интерпретироваться не как комментарий, а как
указание на запуск командной оболочки csh. И если сценарий был написан
не для нее (а, например, для того же bash) - он, в силу различия
синтаксиса, просто не будет выполнен.
Подчеркнем еще раз: хотя команда, запускающая неинтерактивный или
неинтерактивный шелл, может носить (и часто носит) то же имя, что и
команда на запуск login shell, это - разные экземпляры программы,
которые в общем случае могут быть настроены независимо. А значит -
вести себя разным образом. И потому не следует удивляться, когда 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.
Шеллы и Борна, и Корна не были свободно распространяемыми программами
в понимании FSF. Поэтому ни тот, ни другой не могли использоваться в
таких ОС, как *BSD или Linux, хотя свободная реализация оболочки Корна
(pdksh) и была создана. Однако, как и ее прототип, шелл Корна, она,
несколько развившись относительно первозданного Bourne shell, обладала
интерактивными достижениями, далеки от идеала. Столь же слабы они были
и в другой свободной оболочке - ash, весьма напоминающей /bin/sh из
FreeBSD (вследствие своей компактности она по сей день помещается на
всякого рода спасательные носители). И потому широкое распространение
получила оболочка bash (что расшифровывается как "еще одна оболочка
Борна", "заново рожденный шелл" и тому подобным образом),
разработанная в рамках [61]проекта GNU.
Популярность bash в немалой степени была обусловлена его
интерактивными возможностями - он аккумулировал все достижения
интерактивной мысли sh- и csh-совместимых оболочек, прибавив к ним
немало собственных. И умудрившись при этом сохранить базовую
совместимость с POSIX shell. Конечно, многие его собственные фичи
выходили за рамки этого стандарта. Однако для соответствия оному был
введен режим совместимости - то есть bash был способен эмулировать
стандартный POSIX shell.
Однако главным для bash было то, что эта оболочка оказалась тесно
интегрирована с операционной системой Linux: именно bash волею судеб
стал одной из первых программ, которые Линус запустил поверх своего
новосозданного ядра. И потому идеи bash-скриптинга пронизали Linux до
самых его оснований. Ну а для совместимости использовался тот самый
режим эмуляции: в Linux файл, запускающий POSIX shell (по стандарту он
должен именоваться /bin/sh), являет собой жесткую или символическую
ссылку на реальный /bin/bash. Последний же, будучи вызванным таким
образом, полностью воспроизводит стандартный POSIX shell (разумеется,
путем утраты своих продвинутых фич).
Клан csh-совместимых оболочек развивался параллельно сынам и пасынкам
Борна. Собственно оболочка csh была создана в Университете Беркли в
ходе реализации проекта BSD Unix (тогда - именно так). Она получила
дополнительные интерактивные возможности, во многом превосходящие
таковые современного ей шелла Корна. Главное же - языку, ею
интерпретируемому, были приданы черты синтаксического сходства с
языком Си (откуда, собственно, и название - C-Shell, хотя не следует
думать, что на всамделишний Си она похожа). В результате оболочка Си
оказалась весьма эффективной как для интерактивной работы, так и при
создании сценариев. Только вот сценарии эти не были совместимы со
скриптами POSIX shell, обретшего уже силу стандарта.
В отличие от большинства прочих достижений берклианской мысли,
оболочка csh, по не вполне ясным для меня причинам, не обрела статуса
свободной программы. Поэтому она не могла использоваться даже в своих
родных пределах - в BSD-системах. Однако на замену ей была изобретена
свободная оболочка tcsh - не просто функциональное воспроизводство, но
дальнейшее развитие оболочки csh. По интерактивным возможностям, как
минимум, не уступающая bash и потому утвердившуюся в стане свободных
BSD-клонов.
Проблема выбора
Из приведенного краткого обзора можно видеть, что в плане шеллов выбор
пользователя достаточно обширен. А ведь я остановился только на самых
распространенных. Однако рискну предположить, что большинство
начинающих пользователей Linux'а об этом не особо задумываются. Ведь
по умолчанию во всех его дистрибутивах в качестве шелла по умолчанию
принят bash, обладающий как развитыми средствами интерпретации, так и
продвинутыми интерактивными возможностями, да еще при сохранении
совместимости со стандартом. Так зачем, казалось бы, искать добра от
добра?
Первый вариант ответа очевиден - добро это дополнительное ищется в тех
случаях, когда необходима минимизация ресурсов. Когда bash, занимающий
более полумегабайта на диске (и около полутора - в памяти) оказывается
излишне громоздким и медленным. Впрочем, первое играет роль только для
всяких rescue-систем на дискета, а второе на современных машинах
нечувствительно. Тем не менее, маленький и быстрый шелл Альмкивста
(ash) может оказаться подходящим не только в спасательных целях, но и
для всякого рода скриптинга. Хотя работать в строке ash регулярно мне
бы не хотелось - даже автодополнения, и того нет.
Вторая причина поиска нового шелла - неудовлетворенность возможностями
имеющегося. Эта проблема остро встает перед пользователями FreeBSD -
уж очень убог его умолчальный login shell для обычного пользователя -
/bin/sh, - в плане интерактивной работы. Что особенно наглядно
проступает в сравнении с tcsh, каковой по определению получает в свое
распоряжение root-оператор. А потому и простой юзер может поддаться
искушению и выбрать себе тот же tcsh - хотя бы заради единства стиля
работы (ведь на настольной машине тому же юзеру приходится быть и
root'ом).
Должен заметить, что именно в бытность пользователем FreeBSD я и
перепробовал целый ряд доступных в ней шеллов (благо через систему
портов они столь же легко удалялись, как и устанавливались). Не обойдя
своим вниманием и tcsh - и в целом остался им доволен. Как
интерактивная оболочка tcsh, на мой взгляд, несколько превосходит bash
(хотя и не принципиально). Однако непривычность синтаксиса (или
необходимость его изучения) способны отвратить от этого шелла. Тем
паче, что при возврате в Linux tcsh оказывается далеко не самым
удобным инструментом.
И, наконец, третья причина для изысканий - поиски идеала (а не они ли
движут, осознанно или нет, изрядной долей пользователей Linux?). Спору
нет, bash - оболочка хорошая, но до такого идеала явно не
дотягивающая, слишком много в нем направлено на достижения баланса
компактности и функциональности. Должен сказать, что мои поиски идеала
успехом увенчались. И потому наступает время -
Представление главного героя
Как можно догадаться из названия заметки, главным героем ее является
командная оболочка Z-Shell или, сокращенно, zsh, о которой на
протяжении всего предшествующего повествования не было сказано ни
слова. Настало время исправить это упущение.
Итак, zsh - оболочка из клана sh-совместимых, первоначально
разрабатывавшаяся Паулем Фальстадом (Paul Falstad), ныне развивается в
рамках [62]самостоятельного проекта сообществом энтузиастов при
координации Петера Стефенсона (Peter Stephenson). Прямого (а похоже, и
косвенного) отношения к GNU zsh не имеет, однако распространяется на
условиях лицензии GPL и, следовательно, является полностью свободной
программой.
Существует мнение (и не только мое), что в zsh нашли свое воплощение
все прогрессивные тенденции таких развитых оболочек, как bash и tcsh.
И, ознакомившись с его возможностями, с этим трудно не согласиться - в
zsh есть все, что было хорошего и в bash, и в tcsh, но, если так можно
выразиться, в превосходной степени.
Действительно, какими особенностями определяется в первую очередь
удобство интерактивной работы в командной оболочке? В порядке, котором
с ними сталкивается пользователь, это будут:
* автодополнение командной строки;
* возможности навигации по ней и ее редактирования;
* просмотр буфера истории команд;
* возможность минимизации ввода за счет использования псевдонимов.
Автодополнением клавишей Tab команд, частично введенных в ответ на
приглашение оболочки, трудно удивить пользователей bash или tcsh.
Столь же естественно, что при возможности безальтернативного
дополнения именно оно и происходит, а при наличии некоторых
альтернатив выводятся возможные варианты. Однако zsh идет дальше - и
после вывода таковых в ответ на последующие нажатия клавиши табулятора
начинает автоматический их перебор.
Автодополнение путей к файлам, выступающим в качестве аргументов
команд, - тоже не бог весть какое новшество. И единственное отличие
zsh от прочих выражается здесь в том, что и для путей действует
автоматический перебор вариантов клавишей табулятора. А вот то, что
автодополнение работает также и для аргументов команды man - окажется
приятной неожиданностью. Так, чтобы вызвать полное экранное
руководство по zsh, достаточно набрать
$ man zsha
и нажать табулятор, чтобы развернуть его до полного man zshall.
Более того, автодополнению (и автоматическому перебору его
возможностей) подвержены даже опции многих команд. Это особенно
показательно для таких синтаксически сложных команд, как find. Так,
последовательность
$find / -na
будет автоматически дополнена до
$find / -name
А после указания этого для указания опции действия можно ограничиться
вводом символа дефиса
$find / -name filename -
и выбрать необходимое действие (например, вывод на экран) из
предложенного списка.
И еще один частный случай автодополнения уникален для zsh:
развертывание путей при сокращенном их наборе. Так, что просмотреть
содержимое каталога /usr/portage/distfiles, достаточно набрать в
командной строке
$ ls /u/p/di
и нажать клавишу табуляции: сокращенный ввод пути (разумеется, при
безальтернативности оного) будет автоматически развернут до полного.
Автодополнение в zsh гармонично сочетается с автокоррекцией (т.н.
spelling командной строки). Конечно, и это само по себе не уникально.
Однако проверка правильности ввода и автокоррекция в zsh
распространяются не только на встроенные (как в bash) и даже внешние
(как в tcsh) команды, но даже на пути и аргументы. Причем если
автокоррекция становится назойливой (например, для команд типа cp или
mv она порывается исправить аргументы на имена существующих файлов),
ее можно отключить - и именно только для определенных команд.
Средства навигации по командной строке и ее автоматического
редактирования - необходимое условие комфорта в интерактивной работе
внутри оболочки. Здесь говорить, казалось бы, не о чем - управляющие
клавишные последовательности для таких действий давно уже вошли в
обиход всех командных оболочек, претендующих на развитость. Однако и в
этой области zsh есть чем похвастаться - в нем задействованы все
комбинации клавиш для перемещения и удаления (как посимвольного, так и
командными "словами" и фрагментами строки), которые существуют в bash
и tcsh, причем - построенные по тем же принципам.
Управляющие последовательности в zsh построены по принципу сочетания
клавиши Control+литера или Meta+литера, причем вторая комбинация
обычно выступает в качестве "усиленного" варианта первой. Так, если
Control+D удаляет символ в позиции курсора, то сочетание Meta+D
проделывает это для всех символов от позиции курсора до конца
командного слова.
Предусмотрены в zsh и клавишные комбинации для таких действий, как
преобразование регистра литерных символов, "перетасовки" символов и
командных "слов" в строке, заключения строки в кавычки (а при
необходимости - и экранирования оных символами обратного слэша). Есть,
конечно же, и комбинация для многоуровневой отмены ввода.
Действие большинства простых (двухклавишных) последовательностей
дублируется "сложными", вида Meta+литера-Control+литера, которые
прекрасно работают и при переключении на кириллическую раскладку
клавиатуры.
Легко заметить, что управляющие последовательности в zsh реализованы с
стиле Emacs. Однако это - лишь один из возможных режимов, принятый по
умолчанию. При желании ничего не стоит переключить навигацию и
управление в режим vi, если таковой кажется более привычным для
пользователя.
Оболочка zsh обладает всеми стандартными средствами доступа к буферу
истории команд - перехода к началу и концу буфера истории, просмотра
оного вперед и назад (как клавишами управления курсором, так и
соответствующими управляющими последовательностями), обычного и т.н.
наращиваемого поиска в обоих направлениях, исполнения выуженной из
буфера команды с автоматическим переходом к следующей. Плюс - весьма
изощренные способы вывода в строку отдельных фрагментов команд из
буфера истории - например, отдельного командного "слова", начиная с
последнего, с дальнейшим перебором "слов" буферизованных команд назад.
Или - вывод полного списка команд из буфера с их последовательным
перебором в том или ином направлении.
И, наконец, такое мощное средство минимизации пользовательского ввода,
как псевдонимы команд (aliases). Разумеется, в zsh (как и в bash или
tcsh) псевдоним может быть присвоен любой команде со сколь угодно
длинным набором опций. Так, куда как проще раз и навсегда определить
команду ls как псевдоним самой же себя, но с опциями -FG, нежели
каждый раз вспоминать, как отличить в ее выводе каталоги от обычных
файлов.
Однако zsh идет дальше: в нем это дополняется возможностью определения
псевдонимов для командных конвейеров в форме опции -g (от global
aliases - именно так именуется эта возможность). Так, всем известно,
что для обеспечения постраничного вывода любой команды (например, той
же ls) вывод этот нужно передать по конвейеру (pipe) программе-pager'у
(less или more). Однако не лениво ли - каждый раз вводить что-нибудь
вроде
$ ls | less
да еще и не забывать это делать? Если лениво - на помощь придут
глобальные псевдонимы. Опять же раз и навсегда определяем, что опция
-g со значением L есть псевдоним для конвейера '| less'
$ alias -g L='| less'
после чего имеем возможность, указывая ее после команды, требующей
постраничного ввода, именно его и получать:
$ ls -g L
Казалось бы, не намного проще? Ан нет: ведь ничто не препятствует нам
создать еще один, обычный, псевдоним для команды ls с этой опцией,
например:
$ alias lp='ls -g L'
чтобы при необходимости постраничного вывода списка каталога именно к
нему и прибегнуть.
Важный момент облегчения существования пользователя в любом шелле -
вид приглашения командной строки, должная настройка которого может
часто избавить от лишнего набора команд (уж от команды pwd я по
возможности стараюсь избавиться именно таким образом. Так вот, zsh
поддерживает несколько независимо настраиваемых обычных приглашений -
первичное, для многострочных команд, "выделенное", приглашение при
выводе вариантов автокоррекции и даже специальное "приглашение" в
правой части командной строки. Которое, конечно, собственно
приглашением не является, но позволяет вывести полезную информацию,
например, текущее время или дату, номер виртуальной консоли, и т.д.
Для пущей экспрессии настраивается также передача символов в любом
приглашении - цветом ли, выделением, инверсией, подчеркиванием. Очень
полезная возможность - различение вида приглашения для обычного
пользователя, получившего права root'а в результате команды su без
опций - дабы не забывать о своих временных полномочиях.
Надеюсь, что мне удалось убедить читателя в превосходных интерактивных
возможностях оболочки zsh. Теперь стоит поговорить о функциональности,
которая проявляется не только в интерактивной работе (но и, скажем,
при сочинении скриптов). Функциональность же любой оболочки можно в
первом приближении оценить по количеству встроенных в нее команд. То
есть - команд, выполняемых внутри самого шелла, без порождения новых
процессов, как это происходит при выполнении внешних команд (например,
из стандартного набора base Linux). Очевидно, что такие встроенные
команды будут выполняться быстрее и отъедать меньше ресурсов. Что,
конечно, не скажется при интерактивной работе на современных машинах,
но вот в сложных сценариях - вполне может.
В zsh поддерживается весь набор встроенных команд, стандартизированный
для POSIX shell, большинство команд из развитых оболочек bash и tcsh,
ну и, разумеется, специфичные для этого шелла команды. Общее число их
превышает 80 - примерно столько же, сколько встроено в tcsh и bash,
вместе взятые.
Очень интересна (и удобна) в zsh работа с командными конструкциями
перенаправления. Здесь и множественное перенаправление вывода, когда
результат выполнения команды направляется сразу в несколько файлов, и
множественное перенаправление ввода - когда команда, напротив,
получает аргументы последовательно из более чем одного файла,
перенаправление без команды, когда конструкция типа
$ < filename
просто выведет на экран содержимое указанного файла.
При перенаправлении возможна группировка команд по шаблону. Так, файлы
file1 и file2 можно просмотреть одной командой
$ < file{1,2}
Перенаправление ввода/вывода может иногда заменять конвейеризацию
команд. Так, конструкция вида
$ sort < file{1,2}
отсортирует содержимое обоих файлов точно так же, как это сделал бы
конвейер команд
$ cat file1 file2 | sort
Наконец, еще одна специфическая особенность zsh - т.н. пред-исполнимая
модификация команд (precommand modifier), осуществляющаяся перед их
интерпретацией. Именно таким образом можно отменить чрезмерно
навязчивую автокоррекцию аргументов для одной отдельно взятой команды,
например, копирования:
$ nocorrect cp file1 file2
Легко видеть, что все изобилие возможностей zsh далеко выходит за
рамки стандарта POSIX для командных оболочек. Однако, в подтверждение
своего соответствия оному, zsh, наступая на горло собственной песне,
способен к эмуляции POSIX Shell - для этого достаточно создать файл
/bin/sh как символическую ссылку на исполнимый файл zsh. Кроме того,
имеется и некий режим совместимости с командными оболочками csh-клана.
Здесь описана лишь небольшая часть возможностей оболочки zsh, в
частности, я не останавливался на его встроенных функциях, хотя именно
они и есть та база, что обеспечивает все описанное (и не описанное)
богачество возможностей. Не говорил я и о подгружаемых модулях (по
типу plug-ins) - а ведь среди последних есть даже собственный
ftp-клиент. Ибо для этого потребовалось бы пересказать всю экранную
документацию к нему - более дюжины man-страниц общим объемом (в
*.gz-виде) свыше 250 Кбайт, плюс официальное руководство с сайта
проекта, включающее в pdf-формате 260 страниц (к слову - автором этой
документации является тот же Петер Стефенсон).
Тем не менее надеюсь, что я убедил вас в том, что zsh - штука стоящая.
Если так - то
Приступаем к установке
Оболочка zsh стандартно входит в большинство (я бы сказал - во все из
мне известных) полнофункциональных дистрибутивов Linux, в качестве
портов и пакетов доступна во Free- и OpenBSD (на счет NetBSD - просто
не помню), портирована даже в AtheOS (вернее - ее отпрыска Syllable).
Так что проблем с ее получением быть не должно. Устанавливаем zsh
штатным для данного дистрибутива методом и переходим к следующему
разделу.
Если же почему-либо zsh в составе дистрибутива не обнаружился -
отправляемся на [63]ftp://ftp.zsh.org/pub/ или какое-либо его зеркало
(список - на [64]http://www.zsh.org), можно - в каталог distfiles
ftp-серверов FreeBSD или Gentoo. И качаем в свое удовольствие
исходники последней стабильной версии (на данный момент - 4.06), или,
при желании, разрабатываемой (кажется, 4.11) - различий в стабильности
между ними я не заметил.
Исходники zsh распаковываются и собираются обычным образом -
./configure, make, make install, никаких неожиданностей здесь не
предвидится. Единственно, я предварительно, чисто для интереса,
поинтересовался бы опциями конфигурирования -
$ ./configure --help
Из которых не побрезговал бы опцией --bindir=/bin - это будет полезно,
если zsh будет использоваться как login shell.
И еще: ручная сборка zsh может потребоваться в некоторых пакетных
дистрибутивах, в которых, будучи установленным из бинарников, он может
работать неподобающим образом (о причинах я скажу позже).
Теперь же, установив zsh тем или иным образом, делаем его своей
пользовательским шеллом по умолчанию - login shell (командами типа
usermod, pw, chsh) и -
Начинаем настройку
Без этого нам, скорее всего, не обойтись. Дело в том, что в
свежеустановленном zsh, мы имеем шанс не увидеть почти ничего из
описанных выше прелестей - ни развертывания сокращений путей, ни
автодополнений опций и аргументов, ни выразительных приглашений
командной строки. Перед нами будет безликая строка с именем машины
(типа localhost%), которая едва-то будет справляться с обычным
автодополнением команд и путей (и то - не обязательно). Могут
возникнуть проблемы даже с вызовом собственной экранной документации
man zsh. Почему?
Дело в том, что zsh имеет очень богатый набор собственных
конфигурационных файлов, о которых я скажу чуть ниже. Но при установке
его эти файлы не помещаются автоматически ни в каталог /etc, ни в
домашний каталог пользователя - то есть ни в одно из тех мест, где их
можно было бы ожидать. Конечно, совсем без первичных настроек zsh не
останется: он прекрасно воспринимает их из таких общесистемных
профильных файлов, как /etc/profile, /etc/login и т.д. Однако и вести
себя при этом будет почти точно также, как и соответствующие оболочки
(bash или tcsh, а то и /bin/sh - почему, например, во FreeBSD zsh по
первости не способен даже к автодополнению команд). От одного из этих
профильных файлов zsh унаследует и переменные окружения, включая
MANPATH - почему подчас не сможет найти и свою собственную
документацию.
Так что для придания zsh полного блеска следует прибегнуть к его
собственным конфигурационным файлам. Правда, сначала придется отыскать
их примеры из штатной поставки - должен заметить, что в разных
системах они могут обнаружиться в весьма неожиданных местах. Так, во
FreeBSD их штатное место - каталог /usr/local/share/examples/zsh, в
дистрибутиве Gentoo Linux примеры оказываются в
/usr/share/doc/zsh-XXX-rX/StartupFiles, в иных - вполне могут
оказаться где-нибудь в районе /usr/share/zsh, и т.д.
Для минимизации времени на поиски выдам секрет - примеры
конфигурационных файлов zsh, входящие в штатный комплект, называются -
zlogin, zshenv и zshrc (возможно, с расширением .gz), и благодаря моей
доброте их не трудно будет отыскать командой find - за пределы
каталога /usr файлы эти попасть не должны (даже в том случае, если,
как в Gentoo, сам исполняемый файл zsh оказывается в каталоге /bin).
После изыска конфигов для сердца вольного есть два пути. Первый -
простой, копируем их в наш домашний каталог в качестве dot-файлов
(~/.zlogin, ~/.zshenv и ~/.zshrc, соответственно), после чего
наслаждаемся жизнью. В ряде случаев этого достаточно, чтобы получить
доступ к базовым (но очень даже расширенным, сравнительно с
собратьями) возможностям этого шелла.
Разумеется, суперпользователь может скопировать эти файлы и в каталог
/etc (без точек в имени) - в этом случае они будут определять
конфигурацию zsh для всех пользователей, его запускающих (любым
образом, о чем - чуть ниже).
Второй путь - попытаться разобраться, за что отвечают скопированные
файлы и как они устроены. Это понадобится в двух случаях - а) для
идеальной настройки своего нового шелла и б) если zsh работает не
совсем так хорошо, как вы ожидали (например, не так, как описано
выше). Однако, как это обычно бывает, настройки пользовательских
конфигов будут перекрывать общесистемные (поскольку считываются после
них).
Первый шаг на этом пути - задаться вопросом, а зачем zsh'у так много
конфигов, если другие шеллы спокойно обходятся двумя (а то и одним,
как /bin/sh). На это я отвечу, что конфигов в zsh вовсе не много, а
очень много: в дополнение к трем примерным в разделе FILES его
man-страницы можно найти упоминание еще о zprofile и zlogout (и,
соответственно, ~/.zprofile и ~/.zlogout). А в ходе пользования им вы,
скорее всего, увидите в своем каталоге еще и такие файлы, как
~/.zcompdump и ~/.zhistory.
Так для чего нам такое богачество? Чтобы разобраться в этом, вспомним
о трех видах функционирования любого шелла - неинтерактивном,
интерактивном и подвиде последнего - login shell. Так вот, файл
/etc/zshenv (или ~/.zshenv) считывается при каждом запуске любого
экземпляра zsh, независимо от того, происходит он интерактивно или
опосредованно. Настройки файла /etc/zshrc (и ~/.zshrc) имеют силу для
любого интерактивного запуска zsh. И, наконец, файлы /etc/zlogin и
/etc/zprofile оба вместе (как и соответствующая им пара ~/.zlogin и
~/.zprofile) относятся только к тому экземпляру интерактивно
запущенного zsh, который выступает в качестве login shell.
Зачем так сложно? А для того, чтобы можно было гибко (и индивидуально)
настроить неинтерактивные, интерактивные и пользовательские экземпляры
шеллов. Действительно, очевидно, что на настройку неинтерактивного
шелла влияет только содержимое файла /etc/zshenv (и ~/.zshenv), на
настройку любого интерактивно запущенного экземпляра - уже он же вкупе
с /etc/zshrc (и ~/.zshrc), тогда как поведение login shell
определяется кумулятивным эффектом всех трех (или даже четырех) их
пар.
Хорошо, но зачем же нам два конфига для login shell? Ответ прост - из
соображений совместимости с bash и tcsh. Для пояснения чего вернемся к
истории вопроса. В первозданном шелле Борна существовал только один
конфиг - /etc/profile (~/.profile) для любых экземпляров шелла. В bash
к нему прибавился еще и файл /etc/bashrc (~/.bashrc) для
интерактивного использования (считываемые, естественно, после
предыдущего - как более молодой по происхождению). А csh же изначально
существовали два конфига - /etc/csh.env (~/.csh.env) на все случаи
жизни и /etc/login (~/.login) - в качестве конфигуратора login shell,
считываемые именно в таком порядке.
В zsh же, дабы удовлетворить привычки и тех, и других, были включены
оба "логируемых" конфига, причем порядок их считывания был унаследован
от каждого из родителей. В результате получилась довольно сложная
последовательность при запуске login shell:
zshenv -> zprofile -> zshrc -> zlogin
сначала, естественно, из каталога /etc, а затем из домашнего каталога
пользователя. Разумеется, если все четыре файла присутствуют (и там, и
там). Что, сразу скажем, отнюдь не обязательно. Очевидно, что
совместное использование zprofile и zlogin ни малейшего смысла не
имеет. Просто бывшим пользователям bash привычней первая схема запуска
login shell, бывшим приверженцам tcsh - вторая. Забегая вперед,
замечу, что вообще пользователь может обойтись только одним конфигом в
своем домашнем каталоге (например, ~/.zshrc для любого интерактивного
экземпляра шелла - ведь login shell также будет интерактивным), а все
общие настройки получать из общесистемного конфига (например,
/etc/profile). Более того, в дистрибутиве Gentoo Linux именно так
поступить лучше всего - к причинам вернусь позднее.
Осталось объяснить смысл остальных dot-файлов из пользовательского
каталога. Впрочем, смысл их ясен из названий: ~/.zlogout - это
сценарий, отрабатываем при выходе из login shell, ~/.zhistory хранит
историю команд (это и есть ее буфер), а ~/.zcompdump (насколько я
понимаю) - делает то же самое, но для встроенных функций zsh. Два
последних файла возникают (при выполнении некоторых условий) сами
собой, и речи о них больше почти не будет.
Разобравшись с назначением dot-файлов, можно, наконец, выполнить
Собственно конфигурирование
Процесс этот начнем с того, что отделим зерна от плевел, то есть
решим: а какие же именно файлы нужно настроить. Для начала я оставил
бы в покое все файлы из каталога /etc - вернее, просто не стал бы
копировать туда примеры. Почему? Да потому, что во многих
дистрибутивах Linux имеются либо предварительно настроенные
общесистемные конфиги, либо предусмотрены средства для их
автоматического создания и обновления (ниже я продемонстрирую это на
примере Gentoo).
Так что ограничиваемся только нашим домашним каталогом. И здесь первый
кандидат на удаление (или не-копирование) - файл ~/.zshenv. Конечно,
его можно создать в предельно облегченном виде (например, настройка
приемов неинтерактивной работы здесь абсолютно лишняя). Характерно,
что в штатном примере zshenv присутствует только переменная PATH. Но
ведь ее можно получить из общесистемного /etc/profile, не так ли?
Особенно лишним выглядел бы ~/.zshenv для пользователей Gentoo. Как
можно прочитать в [65]соответствующей документации, здесь существует
прекрасный механизм установки общесистемных переменных - env-update,
автоматически обновляющий главный профильный конфиг /etc/profile. Так
что при отсутствии ~/.zshenv все необходимое (в актуальном виде) будет
браться оттуда. В присутствии же его - zsh откажется от считывания
/etc/profile, в результате чего такие переменные, как локаль, EDITOR,
PAGER и т.д., придется определять дополнительно (проверено на
собственном опыте).
Далее, решаем, а нужен ли нам отдельный конфиг для login shell, и если
нужен - то какой из них - zlogin или zprofile. ИМХО, можно обойтись и
без того, и без другого. Уж без последнего - так наверняка, не зря же
его нет ни среди штатных примеров, ни среди многочисленных конфигов,
которыми поделились с народом активные пользователи zsh на [66]сайте
проекта. А файл ~/.zlogin у меня, например, есть, но состоит он из
одной строки
clear
для очистки экрана от следов прежней жизнедеятельности.
Аналогично и с файлом ~/.zlogout - у меня от включает две строчки
sync
clear
назначение которых более чем понятно.
Остается главный (по крайней мере, самый большой) конфиг - ~/.zshrc.
Что с ним делать? Это легко уяснить, ознакомившись со штатным
примером.
А в примере этом мы найдем и настройку приглашений командной строки, и
определение псевдонимов - обычных и глобальных, для конвейеров команд,
и определение переменной cdpath, и величину буфера истории команд, и
многое, многое другое.
Описывать все опции из примера было бы долго и скучно. Остановлюсь
только на тех, которые создают удобство при интерактивной работе и
определяют внешний вид нашего шелла.
Начнем с последнего, то есть приглашения командной строки. В этом
качестве могут использоваться:
* полное или сокращенное имя хост-машины (последнее принято по
умолчанию для первичного);
* путь к текущему каталогу в различных формах;
* номер текущей команды в буфере истории или строки в данном сеансе
работы;
* имя пользователя, или командной оболочки;
* номер текущего терминала;
* дата и время в разных форматах;
* индикация работы от лица суперпользователя);
* любые символы типа стрелок, крышечек, скобочек;
* текстовые сообщения (например, поздравление с началом трудового
процесса);
* многое другое (подробности - в man zshhmisc).
Плюс к этому приглашения могут быть оформлены визуально различно:
выделением жирным шрифтом (boldface mode) или повышенной яркостью
(underline mode), инвертированием текста/фона (standout mode), а также
цветами. Все это позволяет добиться максимальной информативности
приглашения и его внешней выразительности.
Из опций настройки интерактивности - вспомним о том, что обеспечивает
расширенные возможности автодополнения. А обеспечиваются они строками,
следующими после комментария:
# Setup new style completion system. To see examples of the old style (compctl
# based) programmable completion, check Misc/compctl-examples in the zsh
# distribution.
и имеющими вид
autoload -U compinit
compinit
Вообще, штатный пример файла zshrc очень неплохо прокомментирован - по
аглицки, но разобраться можно:-).
Далее - опции управления историей команд. Здесь для начала следует
определить файл, в котором эта история будет храниться (в примере по
умолчанию таковой отсутствует, и ни какая история по умолчанию не
сохраняется по выходе из сеанса zsh):
HISTFILE=~/.zhistory
Теперь - объем нашей исторической памяти, задаваемый двумя опциями -
HISTSIZE=1000
определяющей память текущего сеанса, и
SAVEHIST=1000
устанавливающая размер буфера, сохраняемого в HISTFILE. Очевидно, что
первую бессмысленно делать больше второй (рекомендуются равные
значения).
Для обеспечивая наращивания файла истории после каждого сеанса работы
(в пределах установленной квоты) определяем:
setopt APPEND_HISTORY
Объем исторической памяти можно установить любым, однако не стоит
расходовать его на повторение дублирующихся команд, ошибочными
нажатиями Enter в пустой строке и т.д.:
Можно настроить и еще много чего, но на этом закончим. Потому что
наступило время подумать, а что представляют из себя установленные
нами опции (типа compinit и т.д.)? А представляют они собой по
преимуществу встроенные функции из комплекта zsh, которые в изобилии
можно обнаружить в каталоге /usr/share/zsh/4.0.6/functions. И именно
благодаря этим функциям и удается все настроить.
А еще - становится понятным, почему иногда zsh в пакетных
дистрибутивах, устанавливаясь из бинарников, ведет себя не вполне
подобающим образом. Да именно потому, что комплект функций в поставке
и их использование в файлах примеров не вполне идентичны (по крайней
мере, мне такие случаи встречались). При сборке же из исходников с
сайта проекта, насколько мне довелось наблюдать, идентичность эта
гарантирована. Тот же результат, естественно, достигается и в Source
Based дистрибутивах (или, скажем, в системе портов FreeBSD).
В общем, достоинства zsh столь многочисленны, что я притомился их
описывать, силы остались только на
Заключительные замечания
Я уже упоминал, что проект zsh прекрасно документирован, один User's
Guide чего стоит. Однако внимание прессы, как онлайновой, так и
бумажной, к нему явно недостаточно. И потому из дополнительных
источников информации на ум приходит только (если не считать
отрывочных упоминаний в паре книжек по Linux) статья Матта Чапмена
(Matt Chapman) - Curtains up: introducing the Z shell.
http://www-106.ibm.com/developerworks/library/l-z.html