Журнал LinuxFormat - перейти на главную

LXF113-114:bash

Материал из Linuxformat
Перейти к: навигация, поиск
Hardcore Linux Проверь себя на крутом проекте для продвинутых пользователей

Содержание

Bash: Оболочка может больше

Продвинутые пользователи Linux частенько сидят в оболочке Bash. Джульетта Кемп сделает их общение с командной строкой проще и эффективнее.

Вы наверняка уже поднакопили псевдонимов («алиасов») в вашем файле .bashrc – это укороченные варианты часто используемых команд. Псевдонимам, правда, нельзя передать «внутрь» аргументы из командной строки (по крайней мере, в Bash и связанных с ним оболочках). Функции позволяют вам это сделать, и вы сможете еще более минимизировать свой ввод команд.

Чтобы чуть ускорить поиск по LDAP, можно использовать

function lds() { ldapsearch “($1=$2)”; }

в командной строке или в вашем .bashrc. Затем наберите

 lds cn jkemp

и вы выполните поиск в LDAP всех записей с cn, равной jkemp (ldapsearch “(cn=jkemp)”). Это здорово сокращает набор, и не надо держать в голове, что идет первым – или (.

Функции могут делать почти все, на что способны скрипты – в том числе, быть сложными и саморекурсивными. Следующий код перемножает серию чисел произвольной длины (например, times 3 4 5 выведет 60). Учтите необходимость использования левого слэша перед * в строке вызова expr; без этого командная строка будет воспринимать * как список всех файлов вместо оператора умножения.

 function times() {
 if [ -z “$2” ]; then
 echo $1
 else
 a=$1
 shift
 b = `times $@`
 echo `expr $a \* $b`
 fi
 }

Расширяем автодополнение

Другой трюк, с которым вы уже знакомы – нажатие Tab для автодополнения имен файлов и команд. Шикарно; но есть пара способов сделать его еще шикарнее. Первый из них – не совсем автодополнение, но поможет вам быстрее находить каталоги. $CDPATH для cd выполняет такую же роль, как и $PATH для исполняемых файлов. Иными словами, для каталога в вашем $CDPATH вы можете ввести только его имя, и Bash перенесет вас прямо туда, сэкономив на вводе полного пути.

Допустим, мне постоянно надо попадать в поддиректорию research моего web-сайта. Мой $CDPATH выглядит так:

 .:/home/jkemp:/local/www/html/research

Просто ввожу cd research – и я там. Имейте в виду, что нужно включить начальную точку (.) в $CDPATH, иначе вы не сможете перейти в поддиректории без ввода ./ перед их именем.

Однако это может вызвать проблемы, если я захочу перейти в поддиректорию с именем research-notes. Если, находясь в ее родительской директории, я наберу research и без оглядки нажму Tab и Enter, то нечаянно угожу в /local/www/html/research. Чтобы эффективно использовать этот механизм, необходимо быть внимательными!

Программируемые завершения

Итак, $CDPATH – вещь полезная. Однако серьезным улучшением обычного автодополнения является программируемое завершение. Вы и сами можете написать все необходимые вам функции завершения, но чтобы заново не «изобретать велосипед», рекомендую скачать /etc/bash_completion с http://www.caliban.org/bash (также доступного как пакет в большинстве дистрибутивов) и затем перенести код этого файла в ваш .bashrc (со строкой source /etc/bash_completion).

Сделали? Хорошо. Откройте новое окно терминала и попытайтесь набрать ssh в строке ввода команды, а потом нажмите Tab. Вы должны увидеть список хостов, к которым вы можете захотеть обратиться по ssh, обычно базирующийся на вашем файле known_hosts. Такое умеет куча других команд – попробуйте, например, traceroute или ftp.

А не украсить ли этот механизм автодополнением хоста в наших собственных скриптах? Заглянув в /etc/bash_completion, вы увидите кучу подпрограмм, начинающихся с подчеркивания (например, _known_hosts), а затем строку такого вида:

complete -F _known_hosts traceroute ping telnet host ssh

Если вы хотите добавить свою команду в этот список, допишите ее в конец после ssh, пересохраните файл, и все должно заработать.

-F – опция, определяющая функцию для завершения: все, что возвращается функцией (в данном случае, _known_hosts), является возможным вариантом завершения. – похожая опция: она выполняет команду и принимает ее вывод как вариант завершения.

Можно написать и собственную функцию завершения. Вот простейший образчик функции, которую можно добавить в /etc/bash_completion – она ищет имя хоста в LDAP:

_ldapcomplete() {
COMPREPLY=()
cur=${COMP_WORDS[COMP_CWORD]}
output=`ldapsearch -Q “(&(cn=$cur*) (objectClass=ipHost))” cn |
grep ^cn:`
name=${output#* }
COMPREPLY=( ${COMPREPLY[@]} $name )
return 0
}
complete -F _ldapcomplete ssh

Первая строка устанавливает значение, которое будет использоваться для завершения при возврате (COMPREPLY). Далее, $cur принимает значение, переданное в функцию, т.е. то, что уже было набрано в командной строке. Переменная COMP_WORDS установлена ранее в /etc/bash_completion для использования всеми функциями. Таким образом, $cur – то, что мы пытаемся завершить.

Строка ldapsearch просматривает записи в каталоге LDAP, чьи имена начинаются с введенных символов и которые относятся к объектам типа host, а затем выдает всю выдернутую из LDAP информацию. $output будет выглядеть так:

cn: hostname

что в нынешнем виде не совсем хорошо для завершения. Поэтому следующая строка расчленяет ее на пробеле и берет вторую половину $output, содержащую только имя хоста. Это значение помещается в COMPREPLY, и функция завершается. По сути, мы имеем дело только с одним значением, поэтому строка может быть такой:

COMPREPLY=$name

Но для соответствия остальному файлу и ради возможности дальнейшего совершенствования мы рассматриваем его как массив.

Чтобы воспользоваться функцией, необходима вся строка -F _ldapcomplete ssh: она скажет оболочке, что при использовании ssh эту функцию нужно применить для завершения имени хоста. Я уже упомянула о серьезном недостатке _ldapcomplete(): она не рассматривает нескольких вариантов возврата и будет успешно работать только тогда, когда автодополнение LDAP возвращает одно значение (в противном случае возникают ошибки). Вот вам шанс немного поэкспериментировать; попробуйте исправить ее, чтобы она правильно обрабатывала несколько возвращаемых значений.

Возврат в историю

Предыстория Bash очень полезна: она избавляет от труда по запоминанию сложных команд. Нажатие Ctrl+R вызовет поиск вглубь вашей истории команд (так, чтобы найти нечто с именем файла, начинающегося с dsl, наберите dsl и нажмите Ctrl+R), а при помощи стрелок курсора вы будете двигаться по истории вспять, строка за строкой.

Однако при поиске в предыстории очень раздражает наличие нескольких идентичных команд. Попробуйте применить такую настройку:

 export HISTCONTROL=ignoreboth

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

Если вам часто приходится открывать одновременно несколько окон терминала, попробуйте добавить в файл .bashrc строку

 shopt -s histappend

Она заставит множественные оболочки записывать историю в один и тот же файл – это позволит избежать проблемы, когда при выходе из множества оболочек вы получаете историю лишь последней. Вы также можете расширить вашу историю с помощью строки

 export HISTSIZE=1000000 HISTFILESIZE=1000000

так у вас появится доступ к гораздо более долгой предыстории команд.

Как видите, в Bash куда больше возможностей, чем вы думали. Стоит потратить время на чтение соответствующих man-страниц – они на удивление легко читаются. Не прекращайте изучать новые возможности, обретая опыт в использовании оболочки! LXF

Немного «горячих клавиш» Bash

Ctrl+R and Ctrl+S Инкрементный поиск назад и вперед, соответственно, в предыстории команд.

Ctrl+J и Ctrl+G Эти команды прекращают инкрементный поиск, заменяя его результатом или исходной строкой, соответственно.

Alt+. или ESC потом . (точка). Обе добавляют последний аргумент предыдущей команды в место расположения курсора. Полезно при перемещении файлов и их редактировании.

Ctrl+A и Ctrl+E Переход на начало и конец командной строки, соответственно.

Alt+C+Y Вставка первого аргумента предыдущей команды у места расположения курсора. Если нужен n-й аргумент, сперва нажмите Alt+N. Так, Alt+2 Alt+C+Y даст вам второй аргумент предыдущей команды. Здесь много клавиш для запоминания, но иногда это бывает полезно.

Ctrl+U Удалить все от позиции курсора до начала строки. Также работает при вводе паролей, так что используйте это сочетание, если вы застряли на полпути и забыли место, на котором закончили. При желании снова использовать строку, нажмите C+Y.

Ctrl+T и Alt+T меняют местами символы и слова, соответственно. Заменяется символ/слово до курсора на символ/слово после курсора. К сожалению, в некоторых терминалах (например, Gnome Terminal), Alt+T уже занят, так что это может у вас не сработать.

Персональные инструменты
купить
подписаться
Яндекс.Метрика