Библиотека сайта rus-linux.net
Сохрани свое время! Используй псевдонимы и функции в командной строке!
Оригинал статьи : "Save time at the command line with shell aliases and functions"Автор: Marco Fioretti
Дата: 16 сентября 2008 г.
Перевод: Вера Северова
Дата перевода: 26 января 2009 г.
Если вы хотите получить от своей GNU/Linux системы все, на что она способна, то от близких отношений с командной строкой и сценариями оболочки вам не отделаться. И тем не менее - чем меньше времени вы проводите за этой клавиатурной работой, тем лучше! И с этим трудно не согласиться. Добиться этой цели нам помогут два мощных средства, предоставленных самой системой, а именно: псевдонимы оболочки (shell aliases) и функции.
Приведенные в этой статье примеры предназначены для командного процессора bash. Хотя, все концепции, а также большая часть кода подойдет и для других оболочек...
Итак, разберемся же, что есть что. Псевдонимы, (или - как их в народе называют - алиасы) есть ни что иное, как альтернативные, легко запоминающиеся имена для тех длинных команд, которые вы часто используете. Когда вы что-нибудь набираете в командной строке, командный процессор сначала ищет то, что вы написали, в его собственном списке псевдонимов. И если при этом он обнаруживает соответствие, то заменяет псевдоним заданным текстом. Только после этого командный процессор проверяет получившуюся строку еще раз и выполняет ее. Вот несколько примеров объявления псевдонимов:
alias sqlmanage='mysql -p -u my_MySQL_userid MySQL_database_name' alias ssh2rws='ssh -p port_number my_remote_userid@my.remote.web.server' alias findbig='find . -type f -exec ls -s {} \; | sort -n -r | head -5' alias cof='clear;ls -lrt'
Первые два примера понадобятся для замещения более длинных строк: первая - для соединения с локальной базой данных MySQL, вторая - для доступа к удаленному серверу. Третья находит пять самых больших файлов в текущей папке и ее подкаталогах. Последний псевдоним, хотя на вид он проще и короче остальных, приспособлен для большего числа применений. В соответствиии с правилами обработки псевдонимов вы можете использовать "cof" для получения листинга любых файлов или каталогов, причем самые старые файлы будут указаны первыми.
cof # очистка экрана, вывод содержимого текущей директории cof /tmp /usr # очистка экрана, вывод содержимого папок /tmp и /usr cof *.jpg # очистка экрана, вывод файлов с расширением .jpg из текущей директории
Определить псевдонимы для команд можно в командной строке, во время сеанса работы с оболочкой. Но они будут работать только во время текущего сеанса, поэтому более эффективным будет, если вы сделаете их постоянными, определив во внутрисистемном или персональном файле конфигурации оболочки (/etc/bashrc или $HOME/.bashrc). Для того, чтобы узнать, какие псевдонимы уже определены в вашей системе, просто наберите alias в командной строке.
Как видите, псевдонимы достаточно удобное средство, однако они имеют ряд ограничений и особенностей использования. Для начала, они не поддерживаются, если оболочка работает не в интерактивном режиме и при этом вы не установили правильные её параметры (смотрите man страницу команды bash). Кроме того, оболочка загружает как минимум одну полную строку вводимой информации, потом заменяет псевдонимы, и только после этого выполняет всю получившуюся команду. Это означает, что если вы используете более одного предопределенного псевдонима в одной строке-команде, вы можете получить непредсказуемые результаты, но вы также не можете определить псевдоним и затем использовать его в той же строке. По тем же причинам может не получиться ничего хорошего, если вы попытаетесь определить псевдоним внутри функции. Чтобы избежать подобных недоразумений, никогда не помещайте определение псевдонима в одной строке с чем-нибудь еще; не используйте и не определяйте псевдонимы в составных командах или блоках кода, которые выполняются только при соблюдении какого-либо условия.
От псевдонимов к сценариям среды оболочки
Заменить псевдонимом блоки похожего, но не идентичного кода не получится. Алиасы не могут обрабатывать ошибки, возвращать коды выхода, осуществить управление потоком или использовать переменные. Если вы хотите проделать какое-то из этих действий, самое время открыть для себя правила использования функций оболочки.
Функции оболочки представляют собой блоки кода, построенные как законченные подпрограммы. Они пишутся однажды и вызываются из сценария, в котором требуется их выполнение. В оболочке bash существует два равнозначных способа объявления функции. Первый использует ключевое слово function, при использовании второго способа используются круглые скобки после имени функции:
function my_function { code } my_function () { code }
Какой бы синтаксис вы не предпочли, помните, что определение функции должно располагаться раньше первого её вызова. Вы также можете поместить одну функцию внутри другой, или написать рекурсивные функции. Внутри функции вы можете использовать все многообразие конструкций, доступных в вашей оболочке. Что требует особого внимания в коде функции, так это способ ее взаимодействия с вызывающим сценарием, в котором эта функция используется.
Сценарий может использовать функцию только если она или была объявлена и предварительно определена в самом сценарии или уже была известна в выполняющей ее оболочке. Создать и загрузить функцию вы можете как минимум четырьмя различными способами. Один из них - просто набрать ее в командной строке, так, как вы написали бы ее в файле сценария. Альтернативный способ, подходящий для постоянного использования - сохранить все ваши функции в один файл и затем загрузить его командой '.' из командной строки или другого сценария.
Объявление функции иногда может помещаться в весьма неожиданных местах: следующая хитрость определяет функцию в самой командной строке. Вы можете даже имитировать различные варианты объявления функций, зависящие от других переменных.
if [ "$USER" eq "root" ] then . /etc/root_only_functions.sh else . /etc/normal_users_functions.sh fi backup_all_files # depends on user
Функция backup_all_files, которая будет выполнена, может быть написана одним образом в файле /etc/root_only_functions.sh и совершенно другим в /etc/normal_users_functions.sh. Следовательно, в зависимости от того, выполняется сценарий обычным пользователем или суперпользователем root, могут быть выполнены совершенно разные действия. Будьте осторожны: когда функция объявляется несколько раз, при вызове будет выполнена ее последняя версия.
Передаваемые в функцию аргументы помещаются в специальные переменные под названиями $1, $2 и так далее. Можно использовать специальный массив $@, содержащий все входящие аргументы. Ограничиться использованием $1, $2 ... имеет смысл, только если ваша функция использует определенное, постоянное количество параметров. В функциях, количество аргументов которых может меняться в различных вызовах, а также в рекурсивных функциях, влияющих на один и тот же параметр, вместо этого извлекайте значения параметров из массива $@
function partition_maintenance { for partition in $@ do #делаем что-нибудь с текущим разделом done }
В целях диагностики возвращайте код выхода из всех ваших функций. Это можно осуществить, используя ключевое слово return.
function check_treshold { if [ $SOME_VAR -gt 40 ] ; then echo 5; return 5; else echo 4; return 4 ; fi }
Выполнение такой функции приведет к тому, что в специальную переменную оболочки $? будет помещено значение 4, в том случае, если SOME_VAR меньше сорока. Помните, что возвращаемыми значениями могут быть только числа. Если требуется возвратить строки или массивы, у вас есть два варианта. Можно выполнить команду echo с результатом функции и присвоить некоторой переменной имя функции, заключенное в одинарные кавычки:
IS_SOME_VAR_LESS_THAN_40=`check_treshold`
или передать функции ссылку на переменную, и изменять значение переменной с помощью команды выполнения выражения eval.
function set_variable { eval "$1=$2" }
В этом примере команда "set_variable WEBSITE linux.com" (заметьте, что знаки доллара отсутствуют!) присвоит переменной $WEBSITE значение "linux.com".
Чтобы работа с функциями была более продуктивной, запомните когда их использовать не следует. В этом простом сценарии показаны три различных способа выполнить вычисления без использования функций и один - не выполнять их.
#! /bin/bash MY_VAR=40 echo 0: $MY_VAR MY_VAR=`expr $MY_VAR - 10` echo 1: $MY_VAR MY_VAR=$(($MY_VAR + (5**2 /2))) echo 2: $MY_VAR let MY_VAR="$MY_VAR + 7" echo 3: $MY_VAR MY_VAR="$MY_VAR + 7" # это присваивание строки, а не вычисление значения echo 4: $MY_VAR
Результат выполнения этого скрипта показывает, что функции, при всем своем великолепии, необходимы для арифметических операций только в том случае, если приходится иметь дело с длинной, повторяющейся последовательностью формул.
0: 40 1: 30 2: 42 3: 49 4: 49 + 7
Документация по Bash
Существуют два очень полезных ресурса с документацией по оболочке bash: reference manual и Advanced Bash Scripting Guide.