Карта сайта Хакер в RSS Энциклопедия Хакера PDA версия сайта Почтовые рассылки Хакера    Хакер в Twitter
Журналы Новости Форум Видео Life Xakep Live (блоги)
Bugtrack Статьи Блог Поиск English
Исполнители желаний: обзор конструкторов популярных Linux дистрибутивов ИСПОЛНИТЕЛИ ЖЕЛАНИЙ: ОБЗОР КОНСТРУКТОРОВ ПОПУЛЯРНЫХ LINUX ДИСТРИБУТИВОВ
02.09.2010

Практически для каждого популярного дистрибутива можно найти удобное средство для создания респина: будь то веб или локальное приложение...
Ученье – свет и высокая зарплата: обзор программных эмуляторов сетевого оборудования Cisco Systems и Juniper Networks УЧЕНЬЕ – СВЕТ И ВЫСОКАЯ ЗАРПЛАТА: ОБЗОР ПРОГРАММНЫХ ЭМУЛЯТОРОВ СЕТЕВОГО ОБОРУДОВАНИЯ CISCO SYSTEMS И JUNIPER NETWORKS
01.09.2010

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


Содержание
номера

Курс выживания в консоли

Andrushock

Хакер, номер #061, стр. 080

(andrushock@real.xakep.ru)

Изучаем командный интерпретатор Zsh

Дай-ка я попробую угадать, как сейчас выглядит твой рабочий стол. Тэкс... Модный диспетчер окон, антиальясные шрифты, иконки с www.kdelook.org, транспарентные терминалки, gkrellm в правом углу, ну и, конечно же, полуобнаженная девица с томным взором в качестве обоев. Что, в десятку? И немудрено - сейчас именно так выглядит подавляющее большинство юниксоидных десктопов. Стоит отметить, что благодаря графическим оболочкам начался настоящий бум юниксов, который продолжается и сейчас. Но речь в этой статье пойдет совсем о других оболочках - оболочках командной строки, грамотно используя преимущества которых, ты сможешь выделиться из общей массы, почувствуешь истинную мощь *nix и в разы повысишь свои программерские навыки!

Шелл шеллу рознь

Шелл aka командный интерпретатор - это программа, выполняющая без предварительной компиляции вводимые пользователем команды либо сценарии (скрипты), состоящие из набора последовательных команд. Основоположниками оболочек были Стефен Бурн (Stephen R. Bourne) - создатель Bourne Shell (sh) и Уильям Джой (William N. Joy), разработавший C Shell (csh) в университете Беркли специально для версии BSD UNIX. За тридцать с лишним лет существования UNIX-систем было написано огромное количество различных интерпретаторов командной строки. Все они работают примерно одинаково для большинства базовых действий и команд, а основные различия проявляются только в процессе работы. Это сделано для того, чтобы пользователи без особого труда могли переходить от использования одного шелла к другому. В современных дистрибутивах можно встретить такие оболочки, как ash, bash, csh, pdksh (общедоступная реализация Korn Shell), sash, tcsh и zsh. Разработка большинства из них происходит крайне медленно и сводится, как правило, к залатыванию дыр различного радиуса :).

Ода Zshell'у

Zsh - это один из самых новых и быстроразвивающихся командных интерпретаторов с полностью программным интерфейсом (все, что есть в оболочке, может быть настроено по усмотрению пользователя), имеющий множество интересных возможностей. Изначально создаваемый как интерпретатор, совместимый с оболочкой Корна, zsh аккумулирует в себе все лучшее, что есть в bash, ksh и tcsh.

Ниже перечислю некоторые свойства и преимущества zsh по сравнению с другими оболочками:

- расширенное редактирование командной строки;

- настраиваемое автодополнение команд, опций, сообщений, man-страниц, доменных имен и чего душе угодно;

- улучшенное раскрытие имен файлов;

- хешированные каталоги;

- проверка правописания;

- множественные перенаправления (команду tee можно больше не использовать);

- гибкая работа с массивами (включая обратное индексирование);

- большие возможности по решению задач целочисленной арифметики;

- число встроенных команд примерно равно суммарному размеру команд в bash, ksh и tcsh;

- модульная архитектура.

Этот список можно продолжать еще очень долго. Я уже не говорю про такие свойства, которые являются общими для bash, ksh и tcsh: управление заданиями, история введенных пользователем команд, биндинг клавиш, периодические события, работа с псевдонимами команд и конвейерами. Со всеми этими задачами также прекрасно справляется zsh.

Укрощение строптивого

Забираем с одного из многочисленных мирроров архив с последней (на момент написания статьи 4.1.1) версией zsh. Несмотря на то, что эта версия относится к ветке devel и предназначена для разработчиков (а значит, имеет самые новые и вкусные фичи), она достаточно стабильна в работе и полностью готова к применению.

$ wget ftp://ftp.fu-berlin.de/pub/unix/shells/zsh/zsh-4.1.1.tar.gz

Распаковываем и переходим в созданный каталог:

$ tar zxvf zsh-4.1.1.tar.gz

$ cd zsh-4.1.1/

К процессу инсталляции zsh можно подойти с разных сторон. Первый путь предельно прост - особо не задумываясь, положиться на работу конфигурационного скрипта:

$ ./configure

Второй способ установки заключается в статической компоновке с совместно используемыми библиотеками (такая линковка необходима для работы программ в chroot()'ных средах) командной оболочки с подключением встроенных средств борьбы с утечками памяти:

$ env LDFLAGS="-static" ./configure --enable-zsh-mem --enable-zsh-secure-free --disable-dynamic

А третий предназначен для "счастливых" обладателей старых компов. Дело в том, что zsh работает заметно медленнее (расплата за широкие возможности) своих конкурентов, поэтому имеет смысл отключить из оболочки все что можно, а именно поддержку больших файлов и локали. Также можно отказаться от использования ограниченного режима оболочки, при работе в котором пользователям запрещено изменять каталоги и переменные окружения, с помощью вызова exec запускать программы и осуществлять перенаправление вывода в файлы.

$ ./configure --disable-lfs --disable-locale --disable-restricted-r

Если же в системе вместо архаичного mbox'а используется почтовый формат Maildir, то не забудь скрипту configure передать дополнительный аргумент "--enable-maildir-support".

Далее компилируем и растасовываем свежеиспеченные бинарики по файловой системе:

$ make

# make install

Абсолютный путь до zsh прописываем в конец файла /etc/shells, где содержится список доступных в системе командных оболочек:

# echo "/usr/local/bin/zsh" >> /etc/shells

После внесения этого изменения у пользователей появится возможность командой chsh изменить свой стандартный командный интерпретатор на zsh:

$ chsh

Shell: /usr/local/bin/zsh

Full Name: Andrushock

Чудеса хардкорного твикинга

При запуске zsh пытается прочитать более десяти своих конфигурационных файлов. Такое обилие не случайно - все сделано для чрезвычайно гибкой настройки интерактивных и неинтерактивных шеллов, а также для большей совместимости с bash и tcsh. Не волнуйся, мы обойдемся написанием всего лишь одного конфига:

$ vi ~/.zshrc

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

cdpath=(~ ..)

fpath=($fpath ~/.zfunc)

path=(/bin /sbin /usr/bin /usr/sbin /usr/local/bin /usr/local/sbin .)

manpath=(/usr/local/man /usr/share/man)

Указываем путь до почтового ящика в формате mbox:

mailpath=(/var/mail/$USERNAME'?You have new spam, Master!')

Удаляем из перечисленных массивов повторяющиеся пути:

typeset -U path cdpath fpath manpath

Используем жесткие лимиты на все параметры, кроме размера стека, и не даем размножаться коркам в нашей файловой системе:

unlimit

limit stack 8192

limit core 0

limit -s

Определяем права доступа (в данном случае 0755), которые будут автоматически назначаться файлу при его создании:

umask 022

Особо параноидальные товарищи могут задуматься о значении umask 077, когда только владелец файла имеет право на чтение и запись.

Во власти переменных

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

BLOCKSIZE=k

TERM=xterm-color

TZ=Europe/Moscow

CVS_RSH=/usr/bin/ssh

CVSROOT=anoncvs@anoncvs1.ca.openbsd.org:/cvs

Как видишь, перед каждой переменной писать команду export совсем не обязательно. Мелочь, а приятно.

Настроить среду и поведение оболочки также можно с помощью специальных переменных, значения которых изменяются встроенными командами setopt и unsetopt:

setopt autocd ignoreeof histignoredups histignorespace

autocd - отказываемся от использования команды "cd". Это может быть удобным при большой многовложенности каталогов. Например, чтобы вернуться на три директории вверх, достаточно набрать "../../../";

ignoreeof - не закрываем терминал по сочетанию клавиш Ctrl+D (выходим, только используя команду exit);

histignoredups и histignorespace - избавляемся от пробелов и дубликатов в истории команд.

Скажите, это ваше настоящее имя?

Псевдонимы (алиасы) - очень удобное свойство оболочек, при грамотном использовании которого можно существенно минимизировать объем введенных команд и рутинных процедур:

alias j='jobs -l'

alias h='history M'

alias o='bg; fg %-'

Элегантно подсчитываем использование дискового пространства:

alias duh="du -h . | grep -v '/.*/' | sort -n"

Корректно завершаем сеанс работы:

alias exit='sync; sync; clear; exit'

Частенько бывает лениво расставлять пробелы, верно? :)

alias psaux='ps -aux M'

Ты, наверное, заметил, что в двух примерах участвовала магическая буква М. Это не очепятка, а одна из фич zsh под названием «глобальный псевдоним», работу которого лучше всего объяснить на примере. При установке большого числа программ порядком надоедает вводить одну и ту же команду:

$ ./configure --help | more

Но после определения глобального псевдонима

alias -g M='-help | more'

литера М становится равнозначной конвейеру '-help | more', и теперь можно использовать вот такой формат записи:

$ ./configure M

Tab'у на ][

Zsh выгодно отличается от своих конкурентов потрясающей системой автодополнения, правила которой можно настроить и запрограммировать по своему усмотрению в зависимости от контекста. Но для начала расширим стандартные возможности оболочки:

autoload -U compinit

compinit

Вот теперь есть где разгуляться. Не хватает автодополнения хостов? Пожалуйста:

compctl -k "( www.xakep.ru www.openbsd.org www.zsh.org)" ping

Теперь после набора в командной строке

$ ping www.x<Tab>

имя хоста закомплитится до www.xakep.ru.

Тебе нужно автодополнение пользовательских процессов?

zstyle ':completion:*:processes' command 'ps -au$USER'

Хочешь автодополнение аргументов программ?

compile=(check clean cleandir depend install obj)

compctl -k compile make

Линуксоиды могут смело помещать в этот массив аргументы dep, mrproper, menuconfig, modules, modules_install.

Кстати, тебе не надоело, что bash, выполняя автодополнение при соседстве одноименных подкаталогов и файлов, откровенно тупит и показывает листинг каталога, в котором они находятся? Избавляемся от этого раз и навсегда! К примеру, с помощью "compctl -g" делаем привязку mp3-файлов к музыкальным проигрывателям:

compctl -g "*.(mp3|MP3)" + -g "*(-/) .*(-/)" mpg123 xmms

Теперь на команду

$ mpg123 foobar<Tab>

оболочка больше никогда не побеспокоит тебя одноименными директориями и закомплитит только файлы с расширением mp3.

Еще одна приятная фича - автодополнение с подсказкой. Здесь происходит вывод возможных опций заданной команды с их кратким описанием:

$ tar<Tab>

tar function

A -- append to an archive

c -- create a new archive

f -- specify archive file or device

Работает и автодополнение опций (-na и -pr как по волшебству превращаются в -name и -print):

$ find / -na<Tab> 'foobar' -pr<Tab>

Нельзя не рассказать и о раскрытии путей при их сокращенном наборе:

$ cd /u/p/au/la<Tab>

При нажатии после последнего символа клавиши Tab, команда автоматически дополнится до:

$ cd /usr/ports/audio/lame/

Полезные ресурсы

http://zsh.sunsite.dk/

www.faqs.org/faqs/unix-faq/shell/zsh/

www.acm.uiuc.edu/workshops/zsh/toc.html

http://adamspiers.org/computing/zsh/

Вот так можно перечитать конфиг zsh: ". ~/.zshrc".

Будь осторожен с псевдонимами вида "alias rr='rm -rf'".

На вечеринку без приглашения?

Без сомнения, особое внимание нужно уделить разработке приглашения командного интерпретатора. Грамотный промпт позволит избежать постоянного ввода дополнительных команд (например, pwd, чтобы выяснить текущий каталог), сэкономит драгоценное место в командной строке и позволит вывести на экран дополнительную информацию. Если у тебя нет шелл-аккаунтов, или ты вообще сидишь без Сети, то нет никакого смысла держать в приглашении имя хоста, на котором запущена оболочка. Запись типа "localhost" абсолютно ничего не дает, она только уменьшает твою командную строку на девять символов. Далее имя пользователя. В большинстве случаев можно обойтись и без него. Эта фича может быть полезна, если ты регистрируешься на многочисленных удаленных узлах и всегда под разными именами. Согласись, такое бывает совсем не часто. Поэтому достаточно отображать значок $ или % во время сеанса обычного юзера и решетку # во время сеанса суперпользователя. Лично я в круглые скобки заключаю текущую директорию, а в фигурные - текущую команду буфера истории. Возможно, на первый взгляд следующая строка покажется тебе абракадаброй, но на самом деле это довольно симпатичное и информативное приглашение зеленого цвета:

$ PROMPT=$(echo '%B%{\033[32m%}(%~){%!}%#%{\033[37m%} ')

(~src){139}%

Не хватает часиков? С помощью переменной RPROMPT можно задать правую часть приглашения оболочки:

$ RPROMPT='[%T]'

(~src){140}% [12:40]

В арсенале zsh есть еще одно грозное оружие - поддержка тем для приглашений (themeable prompts). После подгрузки во время сеанса работы модуля promptinit, тебе станут доступны сразу 15 различных видов приглашения командной строки:

$ autoload promptinit

$ promptinit

Выводим список встроенных тем и устанавливаем понравившуюся:

$ prompt -l

Currently available prompt themes:

adam1 adam2 bart bigfade clint elite2 elite fade fire off oliver redhat suse walters zefram

$ prompt clint

[Thu 03/09/11 19:36 MSD][p0][i386/openbsd3.3/3.3][4.1.1]

<andrushock@midian:~>

zsh 63 %

Декорирование окон

Если ты просто жить не можешь без имени пользователя и хоста, то их можно вынести в caption окна терминалки или telnet/ssh клиента вот таким нехитрым способом:

case $TERM in

xterm*)

precmd () {

print -Pn "\033]0;%n@%M (%y) - %/\a"

print -Pn "\033]1;%n@%m (tty%l)\a"

}

preexec () {

print -Pn "\033]0;%n@%M (%y) - %/ - ($1)\a"

print -Pn "\033]1;%n@%m (tty%l)\a"

}

;;

esac

Теперь перед выполнением каждой команды и перед сменой каталога данные в заголовке окна будут изменяться на: "имя_пользователь@полное_имя_хоста (терминал) - текущий_каталог - (выполняемая_команда)". При сворачивании окна инфа будет отображаться в сжатом виде: "имя_пользователь@хост (терминал)".

Забиндим все от А до Я

Для редактирования командной строки можно не только использовать комбинации клавиш vi и emacs, но и устанавливать собственные сочетания. Даже если ты постоянно воркаешь в vi/vim, я рекомендую обратить пристальное внимание на emacs'овские биндинги, так как именно благодаря им работать в консоли станет гораздо комфортнее. Но об этом чуть позже, а пока:

bindkey -e

Следующие записи помогут восстановить работу клавиш Insert, Delete, Home, End, Page Up и Page Down в некоторых терминалах:

bindkey "\e[1~" beginning-of-line

bindkey "\e[2~" transpose-words

bindkey "\e[3~" delete-char

bindkey "\e[4~" end-of-line

bindkey "^[[5~" up-line-or-history

bindkey "^[[6~" down-line-or-history

Подчиняем консоль

Если ты до сих пор перемещаешься по командной строке, используя стрелки влево и вправо, то тогда я понимаю, почему ты тихо ненавидишь консоль и с нескрываемым удивлением поглядываешь на юниксоидов. Фокус заключается в том, что существует несколько комбинаций клавиш, заметно облегчающих передвижение в консоли. Только изучив их, ты сможешь эффективно управляться с командной строкой:

Ctrl+a - перемещает курсор в начало строки;

Ctrl+e - перемещает курсор в конец строки;

Ctrl+f - перемещает курсор на один символ вперед;

Ctrl+b - перемещает курсор на один символ назад;

Alt+f - перемещает курсор на одно слово вперед;

Alt+b - перемещает курсор на одно слово назад;

Ctrl+k - удаляет часть строки от курсора до конца;

Ctrl+w - удаляет часть строки от курсора до начала;

Ctrl+u - удаляет всю строку;

Ctrl+l - очищает экран.

Никогда не любил историю

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

HISTFILE=~/.zhistory

HISTSIZE=1024

SAVEHIST=1024

Я предпочитаю с каждой сессией создавать новую историю команд:

HISTFILE=/dev/null

Существует целый набор встроенных программ и псевдонимов для работы с историей выполненных команд. Приведу часть из них:

$ h (псевдоним) - посмотреть историю команд;

$ fc -l 1 10 - посмотреть историю команд с первой по десятую;

$ fc 2 - отредактировать вторую введенную команду;

$ !! - повторить последнюю команду (на сленге bang-bang);

$ !12 - выполнить 12-ую команду из буфера истории;

$ !p - выполнить из буфера команду, начинающуюся на букву "p".

Работать с историей команд можно с помощью следующих комбинаций клавиш:

Ctrl+r (стрелка вверх) - поиск в обратном направлении;

Ctrl+n (стрелка вниз) - поиск в прямом направлении;

Atl+< - переход к первой команде в буфере истории;

Atl+> - переход к последней команде в буфере истории.

Научите меня писать без ошибок

С помощью проверки правописания можно скорректировать ошибки при написании команд, имен файлов и даже опций. Подключаем автокоррекцию:

$ setopt CORRECT

Теперь попробуем сознательно допустить ошибку:

$ suod ls -alF

zsh: correct 'suod' to 'sudo' [nyae]?

Не нравится появившееся сообщение об ошибке? Меняем!

$ SPROMPT='zsh: correct '%R' to '%r' ? ([Y]es/[N]o/[E]dit/[A]bort) '

% suod ls -alF

zsh: correct suod to sudo ? ([Y]es/[N]o/[E]dit/[A]bort) y

Стоит отметить, что командой nocorrect разработчики предусмотрели своеобразный откат от этой опции, чтобы предотвратить автоматическую коррекцию аргументов для некоторых утилит:

alias mv='nocorrect mv'

alias cp='nocorrect cp'

alias mkdir='nocorrect mkdir'

Хешируем помаленьку

Именованные каталоги чем-то напоминают символические ссылки. Если в системе есть несколько труднодоступных каталогов, к которым тебе нужно периодически обращаться, то эта специфическая возможность оболочки просто создана для тебя:

hash -d ftp=/home/ftp

hash -d src=/home/root/src

hash -d www=/var/www/htdocs

Теперь вместо команды

$ cd /var/www/htdocs

можно использовать своеобразную закладку:

$ cd ~www

Пример шелл-кодинга

Ни для кого не секрет, что в *BSD присутствует несколько обрезанная версия программы kill, которая позволяет оперировать только идентификаторами процессов. А что нам мешает самим написать небольшую функцию, способную восполнить этот серьезный пробел?

pskill()

{

local pid

pid=$(ps -aux | grep $1 | grep -v grep | awk '{ print $2 }')

echo -n "Killing '$1' (process $pid)..."

kill -9 $=pid

echo " done."

}

Вуаля. Теперь можно работать и с именами:

# pskill silc

Killing 'silc' (process 26812)... done.

Постскриптумы

Как видишь, zsh разве что крестиком вышивать еще не научился. Галопом по европам я постарался рассказать о наиболее интересных и заслуживающих внимания свойствах этого уникального командного интерпретатора. К сожалению, информации об этой оболочке в Сети крайне мало, поэтому для домашнего чтения могу только посоветовать солидную справочную страницу zshall(1), руководство пользователя "Zsh Guide" и статьи Алексея Федорчука, посвященные zsh.

Зачем нам нужны оболочки?

Анализируя и выполняя вводимые с терминала команды, оболочка предоставляет пользователю колоссальные возможности для взаимодействия с операционной системой. Такие функции оболочки, как управление потоками ввода/вывода, раскрытие и дополнение имен файлов, обеспечение доступа к ранее выполненным командам, управление заданиями, выполнение циклов и условных переходов позволяют существенно повысить эффективность работы.

Зачем нужно использовать сценарии оболочек?

Сценарий представляет собой файл, содержащий последовательность команд для оболочки. Как правило, сценарии применяются для того, чтобы не повторять ввод одной и той же последовательности команд.

А как работать со стеком каталогов?

Командой pushd текущий каталог помещается на вершину стека, командой popd самый верхний каталог извлекается из стека, и в него производится переход, а с помощью команды dirs можно вывести иерархию каталогов.

Пример автодополнения для справочных страниц

man_glob () {

local a

read -cA a

if [[ $a[2] = [0-9]* ]] then

reply=( $^manpath/man$a[2]/$1*$2(N:t:r) )

else

reply=( $^manpath/man*/$1*$2(N:t:r) )

fi

}

compctl -K man_glob man

Полезные ресурсы

http://freebsd.by.ru/refs/zsh00.html

http://linuxshop.ru/unix4all/?cid=26&id=209

www.daemonnews.org/199910/zsh.html

http://zsh.sourceforge.net/Guide/zshguide.html

http://www-106.ibm.com/developerworks/library/l-z.html

Текущая стабильная версия zsh 4.0.7.

Текущая версия zsh для разработчиков 4.1.1.

В интерактивном режиме работы оболочка передает управление пользователю.

Оболочка переходит в неначальный (порожденный) интерактивный режим, если она запущена из другой оболочки (или из самой себя).

Неинтерактивный сеанс оболочки используется для запуска сценариев.

Существует два вида программирования оболочек: Bourne и csh.

Содержание





Предыдущие номера


    Rambler's Top100