- Bash-скрипты, часть 6: функции и разработка библиотек
- Объявление функций
- Использование функций
- Использование команды return
- Запись вывода функции в переменную
- Аргументы функций
- Работа с переменными в функциях
- ▍Глобальные переменные
- ▍Локальные переменные
- Передача функциям массивов в качестве аргументов
- Рекурсивные функции
- Создание и использование библиотек
- Вызов bash-функций из командной строки
- Итоги
- Bash-скрипты для графического интерфейса
- Программа 1: Команда notify-send
- Программа 2: команда tput
- Программа 3: Команда setleds
- Программа 4: Команда zenity
- Программа 5: Команда kdialog
- Программа 6: Dialog
- О других программах создания виджетов
- Программа 7: Команда logger
- Программа 8: Команда setterm
- Программа 9: smbclient: Отправка сообщений на рабочую станцию MS-Windows
- 10: создание сетевых сокетов Bash
- GUI скрипты и Cronjob
Bash-скрипты, часть 6: функции и разработка библиотек
Занимаясь разработкой bash-скриптов, вы рано или поздно столкнётесь с тем, что вам периодически приходится использовать одни и те же фрагменты кода. Постоянно набирать их вручную скучно, а копирование и вставка — не наш метод. Как быть? Хорошо бы найти средство, которое позволяет один раз написать блок кода и, когда он понадобится снова, просто сослаться на него в скрипте.
Оболочка bash предоставляет такую возможность, позволяя создавать функции. Функции bash — это именованные блоки кода, которые можно повторно использовать в скриптах.
Объявление функций
Функцию можно объявить так:
Функцию можно вызвать без аргументов и с аргументами.
Использование функций
Напишем скрипт, содержащий объявление функции и использующий её:
Здесь создана функция с именем myfunc . Для вызова функции достаточно указать её имя.
Результаты вызова функции
Функцию можно вызывать столько раз, сколько нужно. Обратите внимание на то, что попытавшись использовать функцию до её объявления, вы столкнётесь с ошибкой. Напишем демонстрирующий это скрипт:
Как и ожидается, ничего хорошего после его запуска не произошло.
Попытка воспользоваться функцией до её объявления
Придумывая имена для функций, учитывайте то, что они должны быть уникальными, иначе проблем не избежать. Если вы переопределите ранее объявленную функцию, новая функция будет вызываться вместо старой без каких-либо уведомлений или сообщений об ошибках. Продемонстрируем это на примере:
Как видно, новая функция преспокойно затёрла старую.
Использование команды return
Команда return позволяет задавать возвращаемый функцией целочисленный код завершения. Есть два способа работы с тем, что является результатом вызова функции. Вот первый:
Команда echo вывела сумму введённого числа и числа 10.
Вывод значения, возвращаемого функцией
Функция myfunc добавляет 10 к числу, которое содержится в переменной $value , значение которой задаёт пользователь во время работы сценария. Затем она возвращает результат, используя команду return . То, что возвратила функция, выводится командой echo с использованием переменной $? .
Если вы выполните любую другую команду до извлечения из переменной $? значения, возвращённого функцией, это значение будет утеряно. Дело в том, что данная переменная хранит код возврата последней выполненной команды.
Учтите, что максимальное число, которое может вернуть команда return — 255. Если функция должна возвращать большее число или строку, понадобится другой подход.
Запись вывода функции в переменную
Ещё один способ возврата результатов работы функции заключается в записи данных, выводимых функцией, в переменную. Такой подход позволяет обойти ограничения команды return и возвращать из функции любые данные. Рассмотрим пример:
Вот что получится после вызова данного скрипта.
Запись результатов работы функции в переменную
Аргументы функций
Функции bash можно воспринимать как небольшие фрагменты кода, которые позволяют экономить время и место, избавляя нас от необходимости постоянно вводить с клавиатуры или копировать одни и те же наборы команд. Однако, возможности функций гораздо шире. В частности, речь идёт о передаче им аргументов.
Функции могут использовать стандартные позиционные параметры, в которые записывается то, что передаётся им при вызове. Например, имя функции хранится в параметре $0 , первый переданный ей аргумент — в $1 , второй — в $2 , и так далее. Количество переданных функции аргументов можно узнать, обратившись к переменной $# . Если вы знакомы с третьей частью этого цикла материалов, вы не можете не заметить, что всё это очень похоже на то, как скрипты обрабатывают переданные им параметры командной строки.
Аргументы передают функции, записывая их после её имени:
Вот пример, в котором функция вызывается с аргументами и занимается их обработкой:
Вызов функции с аргументами
Функция addnum проверяет число переданных ей при вызове из скрипта аргументов. Если их нет, или их больше двух, функция возвращает значение -1. Если параметр всего один, она прибавляет его к нему самому и возвращает результат. Если параметров два, функция складывает их.
Обратите внимание на то, что функция не может напрямую работать с параметрами, которые переданы скрипту при его запуске из командной строки. Например, напишем такой сценарий:
При его запуске, а точнее, при вызове объявленной в нём функции, будет выведено сообщение об ошибке.
Функция не может напрямую использовать параметры, переданные сценарию
Вместо этого, если в функции планируется использовать параметры, переданные скрипту при вызове из командной строки, надо передать их ей при вызове:
Теперь всё работает правильно.
Передача функции параметров, с которыми запущен скрипт
Работа с переменными в функциях
Переменные, которыми мы пользуемся в сценариях, характеризуются областью видимости. Это — те места кода, из которых можно работать с этими переменными. Переменные, объявленные внутри функций, ведут себя не так, как те переменные, с которыми мы уже сталкивались. Они могут быть скрыты от других частей скриптов.
Существуют два вида переменных:
- Глобальные переменные.
- Локальные переменные.
▍Глобальные переменные
Глобальные переменные — это переменные, которые видны из любого места bash-скрипта. Если вы объявили глобальную переменную в основном коде скрипта, к такой переменной можно обратиться из функции.
Почти то же самое справедливо и для глобальных переменных, объявленных в функциях. Обращаться к ним можно и в основном коде скрипта после вызова функций.
По умолчанию все объявленные в скриптах переменные глобальны. Так, к переменным, объявленным за пределами функций, можно без проблем обращаться из функций:
Вот что выведет этот сценарий.
Обращение к глобальной переменной из функции
Когда переменной присваивается новое значение в функции, это новое значение не теряется когда скрипт обращается к ней после завершения работы функции. Именно это можно видеть в предыдущем примере.
Что если такое поведение нас не устраивает? Ответ прост — надо использовать локальные переменные.
▍Локальные переменные
Переменные, которые объявляют и используют внутри функции, могут быть объявлены локальными. Для того, чтобы это сделать, используется ключевое слово local перед именем переменной:
Если за пределами функции есть переменная с таким же именем, это на неё не повлияет. Ключевое слово local позволяет отделить переменные, используемые внутри функции, от остальных переменных. Рассмотрим пример:
Локальная переменная в функции
Здесь, когда мы работаем с переменной $temp внутри функции, это не влияет на значение, назначенное переменной с таким же именем за её пределами.
Передача функциям массивов в качестве аргументов
Попробуем передать функции в качестве аргумента массив. Сразу хочется сказать, что работать такая конструкция будет неправильно:
Неправильный подход к передаче функциям массивов
Как видно из примера, при передаче функции массива, она получит доступ лишь к его первому элементу.
Для того, чтобы эту проблему решить, из массива надо извлечь имеющиеся в нём данные и передать их функции как самостоятельные аргументы. Если надо, внутри функции полученные ей аргументы можно снова собрать в массив:
Сборка массива внутри функции
Как видно из примера, функция собрала массив из переданных ей аргументов.
Рекурсивные функции
Рекурсия — это когда функция сама себя вызывает. Классический пример рекурсии — функция для вычисления факториала. Факториал числа — это произведение всех натуральных чисел от 1 до этого числа. Например, факториал 5 можно найти так:
Если формулу вычисления факториала написать в рекурсивном виде, получится следующее:
Этой формулой можно воспользоваться для того, чтобы написать рекурсивную функцию:
Проверим, верно ли работает этот скрипт.
Как видите, всё работает как надо.
Создание и использование библиотек
Итак, теперь вы знаете, как писать функции и как вызывать их в том же скрипте, где они объявлены. Что если надо использовать функцию, тот блок кода, который она собой представляет, в другом скрипте, не используя копирование и вставку?
Оболочка bash позволяет создавать так называемые библиотеки — файлы, содержащие функции, а затем использовать эти библиотеки в любых скриптах, где они нужны.
Ключ к использованию библиотек — в команде source . Эта команда используется для подключения библиотек к скриптам. В результате функции, объявленные в библиотеке, становятся доступными в скрипте, в противном же случае функции из библиотек не будут доступны в области видимости других скриптов.
У команды source есть псевдоним — оператор «точка». Для того, чтобы подключить файл в скрипте, в скрипт надо добавить конструкцию такого вида:
Предположим, что у нас имеется файл myfuncs , который содержит следующее:
Это — библиотека. Воспользуемся ей в сценарии:
Только что мы использовали библиотечную функцию внутри скрипта. Всё это замечательно, но что если мы хотим вызвать функцию, объявленную в библиотеке, из командной строки?
Вызов bash-функций из командной строки
Если вы освоили предыдущую часть из этой серии, вы, вероятно, уже догадываетесь, что функцию из библиотеки можно подключить в файле . bashrc , используя команду source . Как результат, вызывать функцию можно будет прямо из командной строки.
Отредактируйте .bashrc , добавив в него такую строку (путь к файлу библиотеки в вашей системе, естественно, будет другим):
Теперь функцию можно вызывать прямо из командной строки:
Вызов функции из командной строки
Ещё приятнее то, что такая вот библиотека оказывается доступной всем дочерним процессам оболочки, то есть — ей можно пользоваться в bash-скриптах, не заботясь о подключении к ним этой библиотеки.
Тут стоит отметить, что для того, чтобы вышеприведённый пример заработал, может понадобиться выйти из системы, а потом войти снова. Кроме того, обратите внимание на то, что если имя функции из библиотеки совпадёт с именем какой-нибудь стандартной команды, вместо этой команды будет вызываться функция. Поэтому внимательно относитесь к именам функций.
Итоги
Функции в bash-скриптах позволяют оформлять блоки кода и вызывать их в скриптах. А наиболее часто используемые функции стоит выделить в библиотеки, которые можно подключать к скриптам, используя оператор source . Если же среди ваших функций найдутся такие, без которых вы прямо таки жить не можете — библиотеки с ними можно подключить в файле .bashrc . Это позволит удобно пользоваться ими в командной строке или в других скриптах. Главное — чтобы имена ваших функций не совпадали с именами встроенных команд.
На сегодня это всё. В следующий раз поговорим об утилите sed — мощном средстве обработки строк.
Уважаемые читатели! А вы пользуетесь функциями собственной разработки для решения повседневных задач?
Источник
Bash-скрипты для графического интерфейса
Считается непреложным, что скрипты оболочки Bash предназначены для интерфейса командной строки. Но существует ряд программ, позволяющих создавать скрипты оболочки Bash, взаимодействующие с графическим интерфейсом пользователя (GUI). Такие скрипты можно использовать в самых различных виджетах, типа меню, всплывающих предупреждений, индикаторов и тому подобных. С их помощью можно контролировать вид и содержание, положение на экране, всевозможные эффекты и так далее.
Создавать графическое приложение долго и сложно. Другое дело программы для создания GUI скриптов. Предлагаемые 10 программ проверены на FreeBSD и на Linux и, несомненно, будут работать и на других Юниксовидных операционных системах.
Программа 1: Команда notify-send
Команда notify-send позволяет посылать на рабочий стол пользователя сообщения и предупреждения прямо из командной строки. Это позволяет информировать пользователя рабочей станции о каком-либо событии, либо выдавать на его рабочий стол любую информацию.
Для начала следует установить необходимый пакет:
Теперь, для примера, пошлем из командной строки простое предупреждение:
Вот что получится:
Вот пример другого кода с дополнительными опциями:
А вот что получится:
В приведенном примере кода:
- -t 5000: Указывает время в миллисекундах (5 000 миллисекунд = 5 секунд)
- -u low : Указывает уровень срочности (низкий=low, средний=normal, срочный=critical)
- -i gtk-dialog-info : Указывает имя файла картинки для вывода (можно указывать путь к готовой картинке как -i /path/to/your-icon.png)
Подробнее об использовании утилиты notify-send читайте в мане этой программы.
Программа 2: команда tput
При помощи команды tput можно контролировать свойства терминала:
- Передвигать курсор в любое место экрана
- Получать информацию о терминале
- Расцвечивать терминал (фон и передний план)
- Включать жирный текст
- Включать инверсию цвета (фон цвета текста, текст цветом фона)
- И многое другое
Вот пример кода скрипта:
Вот что получится:
Подробнее о команде tput расскажут маны:
Программа 3: Команда setleds
Команда setled позволяет регулировать включение светодиодов на клавиатуре, например:
включит огонек на клавише NumLock, а команда
Вот остальные опции:
- -caps : выключить CapsLock
- +caps : включить CapsLock
- -scroll : выключить ScrollLock
- +scroll : включить ScrollLock
В мане команды setleds имеются дополнительные подробности.
Программа 4: Команда zenity
Команда zenity выводит на рабочий стол интерактивные диалоговые окна, а также возвращает ввод пользователя. Это позволяет предоставлять пользователю информацию, запрашивать у него информацию при помощи любых скриптов Bash. Вот пример графического клиента для сервиса whois для определенного домена.
Вот как будет выглядеть получившийся клиент:
Дополнительная информация по команде zenity:
Программа 5: Команда kdialog
Команда kdialog напоминает предыдущую программу zenity, но для KDE и приложений qt. С ее помощью вы можете создавать диалоговые окна. Например, если ввести в командную строку:
То получите такое окно:
Для знакомства с командой kdialog читайте руководство «Shell Scripting with KDE Dialogs» .
Программа 6: Dialog
Dialog ≈ это приложение, которое включается в скрипты Bash и создает виджеты в текстовом интерфейсе. Использует библиотеки curses или ncurses. Вот пример кода:
Подробности в man dialog.
О других программах создания виджетов
- gmessage — GTK-клон программы xmessage;
- xmessage — выводит сообщение или запрос в окне (графический аналог команды /bin/echo);
- whiptail — создает диалоговые окна из скриптов;
- python-dialog — модуль на Python для создания несложных текстовых интерфейсов.
Программа 7: Команда logger
Команда logger записывает информацию в системные логи, такие как /var/log/messages. Это дает возможность видоизменять логи из командной строки, например:
Вот что получится:
Программа 8: Команда setterm
Команда setterm позволяет управлять окном терминала. Вот, например, как заставить терминал стать черным через 15 минут, а через 60 минут отключиться:
А в этом примере продемонстрирован подчеркнутый текст в окне терминала:
Есть возможность включать и отключать курсор:
Детали в мане setterm.
Программа 9: smbclient: Отправка сообщений на рабочую станцию MS-Windows
Команда smbclient умеет общаться с серверами SMB/CIFS. Она способна дать сообщение как отдельным, так и всем пользователям сразу:
10: создание сетевых сокетов Bash
В оболочке Bash предусмотрена возможность создания сокета для получения информации через него. Необязательно применять команды curl или lynx для получения данных с удаленного сервера. Есть два специальных файла устройств, которые можно использовать для создания сетевых сокетов. Выдержка из man bash:
- /dev/tcp/host/port — если host означает существующее имя хоста или адрес Интернет, а порт — целочисленный номер порта, или имя сервиса, то bash попытается установить связь по протоколу TCP с соответствующим сокетом.
Эту технологию можно использовать для определения, открыт ли нужный порт на локальном или удаленном сервере, не прибегая к nmap или другим сканерам портов.
Вы можете использовать скрипт:
Выводом будет что-то вроде:
Подробнее об этом здесь .
Также можно использовать скрипт как клиент HTTP:
Подробности в man bash.
GUI скрипты и Cronjob
Если для запуска скриптов вы используете cronjob , то должны согласовать локальный display/input сервис при помощи команды:
export DISPLAY=[user’s machine]:0
Например, для вызова каждый час скрипта /home/vivek/scripts/monitor.stock.sh, использующего команду zenity, введите:
@hourly DISPLAY=:0.0 /home/vivek/scripts/monitor.stock.sh
А у вас есть любимые GUI скрипты? Напишите нам в комментарии.
Источник