Zenity: GUI для Bash — руководство и справочник

Zenity позволяет быстро добавлять графические диалоговые окна к скриптам Bash: календари, выбор файлов, уведомления, прогресс-бары, слайдеры и текстовые окна. В статье показаны примеры команд, способы захвата результатов в переменные, практические сценарии использования, рекомендации по совместимости и безопасность, чек-листы и готовые сниппеты для включения в ваши скрипты.
Важное: zenity обычно предустановлен в дистрибутивах GNOME (Ubuntu, Fedora, Manjaro). В окружениях KDE рассмотрите kdialog или yad как альтернативы.
Короткие ссылки
- Приложение zenity
- Окно календаря
- Захват выбранной даты
- Окно выбора файла: открытие
- Окно выбора файла: сохранение
- Уведомления
- Окно прогресса
- Окно слайдера
- Окно ввода текста
- Пример: объединение в скрипт
Что такое zenity (одно предложение)
Zenity — это утилита для создания стандартных графических диалоговых окон из командной строки или скриптов Bash; она выводит результаты в stdout и возвращает коды завершения для принятия решений в скрипте.
Почему добавить GUI к Bash-скрипту
- Улучшение удобства для конечного пользователя — особенно когда скрипт предназначен не только для автора.
- Быстрое прототипирование рабочих процессов без необходимости писать полноценное приложение.
- Возможность комбинировать преимущества командной строки (скрипты, автоматизация) и знакомого GUI.
Краткое сравнение: если нужна высокая производительность и сложная логика — язык компиляции может быть лучше; если нужно быстрое взаимодействие с пользователем и простая интеграция в настольную среду — zenity идеален.
Приложение zenity — основные идеи
Zenity создаёт диалоги, принимает параметры, печатает выбранные значения в stdout и завершает работу с кодом возврата (0 — OK, 1 — Cancel/Close, другие коды — ошибки). Это делает zenity идеальным для использования в условных конструкциях и пайпах.
Если ваше окружение KDE, рассмотрите kdialog; для расширенных возможностей (например, более гибкие поля), есть yad.
Окно календаря
Простейшая команда открывает календарь:
zenity --calendarПоведение: отображается календарь с выделенной сегодняшней датой, можно выбрать день, месяц и год. Нажатие OK возвращает дату в stdout, Esc или Cancel — код 1.
Примеры полезных опций:
- –text: текст-приглашение
- –title: заголовок окна
- –day, –month, –year: предустановленные значения
- –date-format: формат вывода даты (использует токены strftime)
Пример: захват даты в переменную и вывод её в терминал:
ChosenDate=$(zenity --calendar --text "Выберите дату" --title "План" --day 1 --month 9 --year 2019); echo "$ChosenDate"Пример с форматом даты (имена дней недели и европейский порядок):
ChosenDate=$(zenity --calendar --text "Выберите дату" --title "План" --date-format="%A %d/%m/%y" --day 1 --month 9 --year 2019); echo "$ChosenDate"Примечание: токены формата совпадают со strftime: %A — полное имя дня недели, %d — день месяца, %m — месяц, %y — год (две цифры).

Захват значения даты — рекомендации
- Всегда берите вывод zenity в кавычки, чтобы корректно обработать пробелы и локализованные названия (%A может вернуть строку с пробелами).
- Проверяйте код возврата ($?) если хотите обработать ситуацию отмены.
Пример проверки:
ChosenDate=$(zenity --calendar --text "Выберите дату" --title "План")
if [[ $? -ne 0 ]]; then
echo "Выбор даты отменён"
exit 1
fi
# Дальше используем $ChosenDateОкно выбора файла: открытие
Опция –file-selection создаёт диалог выбора файла. Ключи:
- –file-selection: режим выбора файла
- –multiple: разрешить множественный выбор
- –file-filter: фильтр типов файлов
- –title, –text, –filename — дополнительные параметры
Пример:
zenity --file-selection --title "How-To Geek" --multiple --file-filter='*.mm *.png *.page *.sh *.txt'Zenity вернёт список файлов, разделённых символом | по умолчанию. Чтобы преобразовать в массив Bash, используйте IFS:
IFS="|" read -r -a files <<< "$(zenity --file-selection --multiple)"
for f in "${files[@]}"; do
echo "Файл: $f"
done

Окно сохранения файла
Добавьте –save для сохранения и –confirm-overwrite для подтверждения перезаписи:
Response=$(zenity --file-selection --save --confirm-overwrite); echo "$Response"Если пользователь выбирает существующий файл и подтверджает перезапись, zenity вернёт имя файла. Если не подтверждает — код возврата будет отличен от нуля.



Уведомления — info, warning, error, question
Стандартные типы уведомлений:
- –error — окно ошибки
- –info — информационное окно
- –warning — предупреждение
- –question — вопрос (возвращает код 0 при OK / Yes)
Примеры:
zenity --error --width 300 --text "Доступ запрещён. Нельзя записать файл."
zenity --info --width 300 --text "Обновление завершено. Нажмите OK для продолжения."
zenity --question --width 300 --text "Продолжить?"; echo $?
zenity --warning --title "Мало места на диске" --width 300 --text "Возможно место для резервной копии недостаточно."Код возврата ($?) — простой способ реагировать в скрипте на ответ пользователя.

Окно прогресса
Zenity поддерживает прогресс-бар, который принимает числовые значения (0–100) из stdin.
Простой демонстрационный пример (линейный шаг):
(for i in $(seq 0 10 100); do echo $i; sleep 1; done) | zenity --progress --title "How-To Geek" --auto-closeИспользуйте –auto-close чтобы автоматически закрыть окно при достижении 100%.
Скрипт-демо, сохраните как progress.sh:
#!/bin/bash
function work-list () {
echo "# Первый этап"
echo "25"
sleep 1
echo "# Второй этап"
echo "50"
sleep 1
echo "# Третий этап"
echo "75"
sleep 1
echo "# Последний этап"
echo "100"
sleep 1
}
work-list | zenity --progress --title "How-To Geek" --auto-close
exit 0chmod +x progress.sh && ./progress.sh
Zenity принимает строки вида “# текст” как подсказку для прогресс-диалога и числа для установки уровня.

Окно слайдера (Scale)
Поля для выбора числового значения:
- –scale — включить слайдер
- –min-value, –max-value — границы
- –step — шаг клавиатурного изменения
- –value — начальное значение
Пример выбора увеличения масштаба:
Response=$(zenity --scale --title "How-To Geek" --text "Выберите масштаб." --min-value=0 --max-value=30 --step=3 --value=15); echo "$Response"
Окно ввода текста (Entry)
Простая форма для ввода строки:
Response=$(zenity --entry --text "Введите поисковый запрос" --title "How-To Geek" --entry-text=""); echo "$Response"Полезно для получения кратких ответов, имён файлов, меток и т. п.
Пример: объединение в рабочий скрипт (Hardware Info)
Функциональный пример с перечислением применённых приёмов: список (радиокнопки), прогресс и текстовый вывод — сохраните как hardware-info.sh:
#!/bin/bash
# Display hardware listing for this computer
TempFile=$(mktemp)
ListType=`zenity --width=400 --height=275 --list --radiolist \
--title 'Hardware Scan' \
--text 'Select the scan type:' \
--column 'Select' \
--column 'Scan Type' TRUE "Short" FALSE "Long"`
if [[ $? -eq 1 ]]; then
zenity --error --title="Scan Declined" --width=200 --text="Hardware scan skipped"
exit 1
elif [ $ListType == "Short" ]; then
Flag="--short"
else
Flag=""
fi
hwinfo $Flag | tee >(zenity --width=200 --height=100 --title="Collating Information" --progress --pulsate --text="Checking hardware..." --auto-kill --auto-close) >${TempFile}
zenity --width=800 --height=600 --title "Hardware Details" --text-info --filename="${TempFile}"
exit 0Пояснения:
- mktemp — создаёт временный файл; важно корректно удалять временные файлы в более сложных скриптах.
- –radiolist — делает первый столбец радиокнопками, вторым столбцом могут быть метки.
- Проверка $? упрощает обработку нажатия Cancel.
- tee >(zenity …) позволяет одновременно записать вывод в файл и в zenity.
- –pulsate используется когда невозможно заранее посчитать прогресс.



Практические советы и лучшие практики
- Всегда валидируйте вывод zenity и код возврата перед использованием значений.
- Оборачивайте подстановки в двойные кавычки — “$(…)”, чтобы избежать проблем с пробелами и спецсимволами.
- Для множественного выбора файлов используйте IFS и read -a для получения массива.
- Для GUI-ориентированных сценариев обрабатывайте локализацию дат и форматов.
- Для взаимодействия с long-running командами применяйте tee и –pulsate или собственное прогресс-значение.
- Удаляйте временные файлы безопасно в trap, если скрипт прерывается.
Пример безопасного удаления temp-файла:
TempFile=$(mktemp)
trap 'rm -f "$TempFile"' EXIT
# ... работа со TempFileЧек-лист перед публикацией скрипта с zenity
- Обработаны все коды возврата от zenity
- Значения окружения и локали не ломают формат дат/времени
- Нет зависимостей от GUI в сценариях, которые должны работать в headless-средах
- Корректная очистка временных файлов
- Сообщения дружелюбны и понятны конечному пользователю
Как отлаживать диалоги zenity
- Запускайте команды вручную в терминале, чтобы увидеть stdout и сообщения об ошибках.
- Включите set -x в скрипте для трассировки.
- Для проверки формата вывода используйте echo “<$(zenity …) >”.
Советы по совместимости и альтернативы
Совместимость:
- Zenity часто предустановлен в окружении GNOME (Ubuntu, Fedora, Manjaro).
- В окружениях KDE zenity работает, но стиль может отличаться; рассмотрите kdialog.
- Для расширенных диалогов используйте yad, который совместим с синтаксисом zenity и предлагает больше опций.
Миграция с zenity на kdialog или yad:
- В kdialog используются другие ключи, но идея схожа: вывод в stdout и коды завершения.
- YAD поддерживает дополнительные виджеты (таблицы, контекстные меню) — полезно для сложных интерфейсов.
Безопасность и приватность
- Никогда не доверяйте пользовательскому вводу без валидации: пути файлов могут быть специально сформированы для инъекции команд в других частях скрипта.
- Если скрипт работает с конфиденциальной информацией, не сохраняйте её в /tmp без специальных прав и шифрования.
- При выводе логов избегайте публикации чувствительных данных, полученных через zenity.
Типичные ошибки и способы их устранения
- «GTKDialog mapped without a transient parent» — предупреждение GTK: можно игнорировать, если всё работает корректно.
- zenity не установлен — проверьте пакетный менеджер: sudo apt install zenity или sudo dnf install zenity.
- В headless-среде (без X11/Wayland) zenity не запустится — проверяйте DISPLAY или запускайте в окружении с GUI.
- Проблемы с кодировкой дат/имен — проверьте локаль (LANG, LC_TIME).
Палитра вариантов использования (когда zenity не подходит)
- Серверные скрипты, запускаемые без GUI: zenity тут не нужен.
- Сложные пользовательские интерфейсы с множеством динамических элементов: лучше написать небольшое Gtk/Qt приложение или использовать Electron/GTK GUI.
Сниппеты: быстрый справочник опций zenity (cheat sheet)
zenity --calendar [--text "..."] [--title "..."] [--day N --month M --year Y] [--date-format "%d/%m/%Y"]
zenity --file-selection [--multiple] [--file-filter='*.txt'] [--save] [--confirm-overwrite]
zenity --info --text "..."
zenity --error --text "..."
zenity --warning --text "..."
zenity --question --text "..."
# progress: принимает числа 0..100 на вход
some-long-task | zenity --progress --title "..." --auto-close
# entry
zenity --entry --text "..."
# scale
zenity --scale --text "..." --min-value=0 --max-value=100 --step=5 --value=50Ролевые чек-листы (быстрые инструкции по внедрению)
Разработчик/автор скрипта:
- Проверить наличие zenity и альтернатив в таргет-системах.
- Обернуть внешние команды в функции и тестировать отдельными шагами.
- Добавить trap для корректного удаления временных файлов.
Системный администратор:
- Убедиться, что скрипты не запускаются от root без нужды.
- Проверить окружение DISPLAY/Wayland и права на X-сервер.
Тестировщик/QA:
- Тестирование сценариев отмены (Cancel) — должен корректно обрабатываться код возврата.
- Тестирование локалей: даты/времена, разделители чисел.
Пользователь/оператор:
- Графические подсказки должны быть короткими и ясными.
- Обучающие подсказки (text) позволяют сократить ошибки ввода.
Мини-методология: как проектировать взаимодействие пользователя с zenity
- Определите сценарии: какие данные нужны пользователю и как они будут использоваться скриптом.
- Минимизируйте количество диалогов: каждый диалог — прерывание потока.
- Предлагайте разумные значения по умолчанию (–value, –day/–month/–year).
- Для долгих операций предоставьте прогресс (точный или –pulsate).
- Логируйте действия для отладки и аудита, но не логируйте секреты.
Критерии приёмки
- Все диалоги открываются и корректно возвращают значения на целевой системе.
- Скрипт корректно обрабатывает отказ пользователя (Cancel/Close).
- Нет утечек временных файлов после завершения или прерывания скрипта.
- Для операций с перезаписью файлов пользователь получает подтверждение.
Тест-кейсы и приёмочные критерии
- Открытие календаря и возврат даты — ожидается формат, заданный –date-format; код возврата 0.
- Отмена календаря — код возврата 1, переменная даты пуста или не используется.
- Множественный выбор файлов — zenity возвращает список, разделённый |; скрипт корректно разбирает список.
- Сохранение файла: выбор существующего файла — появление подтверждения перезаписи; при отказе — файл не перезаписан.
- Прогресс: окно закрывается автоматически при достижении 100% или при завершении процесса.
Decision flow (простое дерево для выбора диалога)
flowchart TD
A[Нужно получить от пользователя информацию?] -->|Да| B{Тип информации}
A -->|Нет| Z[Просто выполняйте команду без GUI]
B --> C[Файл -> file-selection]
B --> D[Дата -> calendar]
B --> E[Короткий текст -> entry]
B --> F[Число -> scale]
B --> G[Подтверждение -> question]
C --> H{Сохранение?}
H -->|Да| I[file-selection --save]
H -->|Нет| J[file-selection --multiple?]Ошибки совместимости и миграция
- Если zenity отсутствует в окружении сервера — переключайте логику на консольные запросы или добавляйте проверку наличия DISPLAY.
- Для пользователей KDE адаптируйте стиль вызова или используйте kdialog для более нативного вида.
Пара примеров расширения сценариев
Интеграция с cron: не размещайте графические диалоги в заданиях cron, предназначенных для среды без дисплея. Для уведомлений используйте D-Bus/notify-send или логи.
Интероперабельность: результат zenity можно передавать в другие утилиты (awk, sed, curl) для дальнейшей автоматизации.
Частые вопросы (FAQ)
Q: Можно ли локализовать текст диалогов?
A: Да, задавайте текстовые строки на нужном языке; учтите, что формат даты зависит от LC_TIME/LANG при использовании %A.
Q: Как захватить множественный выбор файлов?
A: Zenity возвращает список, разделённый символом |. Используйте IFS=’|’ read -r -a arr.
Q: Можно ли установить иконку диалога?
A: Zenity не имеет прямой опции для произвольных иконок; используйте системы тем GTK или альтернативы (yad) для более гибкой стилизации.
Краткое резюме
Zenity — простой и мощный инструмент для добавления GUI в Bash-скрипты. Он покрывает большинство стандартных потребностей: ввод текста, выбор файлов, календарь, уведомления, прогресс и слайдеры. Для стабильной работы проверяйте окружение, корректно обрабатывайте коды возврата и следите за безопасностью ввода.
Краткое объявление для команды (пример, 100–200 слов):
Внедрение zenity в наши административные скрипты позволит предоставлять более понятный интерфейс сотрудникам, снизить число ошибок ввода и ускорить распространение утилит среди пользователей, не знакомых с терминалом. Рекомендуется начать с обёртки существующих скриптов и добавления простых диалогов подтверждения и выбора файлов, затем постепенно внедрять прогресс-бары для долгих операций. В сценариях, запускаемых на серверах без GUI, оставлять консольные варианты.
Похожие материалы
Несколько аккаунтов Skype: Multi Skype Launcher
Журнал для работы: повысить продуктивность
Персональные звуки уведомлений на Android
Скачивание шоу Hulu для офлайн‑просмотра
Microsoft Start: персонализированная новостная лента