Разберем возможности i3status
, программы генерации строки состояния
системы, интегрированную в панель i3bar внутри оконного менеджера i3wm
Почти в любой ОС, или отдельных графических окружениях мы, как пользователи, привыкли к системному бару, панели на экране, на котором в Windows расположена кнопка пуск и иконки запущенных программ, в Mac OS глобальное меню активного приложения. Часто общим для всех систем является то, что на ней расположен трей с иконками запущенных программ, дата, время, и многое другое.
i3bar
Отрисовкой такой панели в i3wm
занимается утилита i3bar
. Она отображается
вверху или внизу экрана, и содержит:
- область с кнопками переключения рабочих областей i3
- системную строку, генерируемую при помощи
i3status
или аналогов - системный трей с иконками программ
i3status
i3status - это небольшая программа, которая генерирует строку состояния
для i3bar
. Для того, чтобы наглядно посмотреть ее в действии, запустим ее
через терминал:
Если вы наблюдаете JSON вместо человекопонятной строки в консоли, то возможно
у вас в конфиге i3 установлен формат вывода output_format
отличный от term
Мы видим не что иное, как обычную строку, содержащую метрики системы, обновляющуюся через определенный интервал времени. По умолчанию метрики отделены разделителем в виде прямой черты, а также могут быть раскрашены в цвета.
Если верить описанию программы, то i3status
хорошо оптимизирован,
порождая не большое количество
системных вызовов, т.к. рассчитан на частое обновление
предоставляемых метрик. Это позволяет занимать минимум процессорного времени,
экономить заряд батареи, и гарантировать, что даже при высокой нагрузке строка
состояния будет обновляться правильно.
Модули
i3status
содержит 16 встроенных модулей, из которых будет состоять выходная
строка статуса. Каждый модуль имеет свой набор индивидуальных настроек,
задаваемых в едином конфигурационном файле.
Есть ряд общих параметров, применимых ко всем модулям. Модули в строке можно
переиспользовать по нескольку раз, управляя порядком вывода.
Список доступных модулей
- IPv6 - Получает и выводит IPv6 адрес
- Disk - Отображает информацию о занятом и свободном месте в файловой системе
- Run-watch - Мониторинг определенного процесса в системе. Может использоваться как индикатор работы какой - нибудь программы, например VPN клиента
- Path-exists - Проверяет на существование путь в файловой системе
- Wireless - Позволяет выводить подключения к WIFI сети, уровень сигнала, имя точки доступа
- Ethernet - Предоставляет IP адрес и скорость соединения сетевого интерфейса
- Battery - Показ уровня заряда батареи
- CPU-Temperature - Показ температуры процессора
- CPU Usage - Использование процессора в процентах
- Memory - Использование оперативной памяти
- Load - Среднее значение загрузки системы за 1, 5 и 15 минут (Load Overage)
- Time - Время в текущей временной зоне
- TzTime - Время в заданной временной зоне
- DDate - Дата
- Volume - Управление громкостью звука
- File Contents - Вывод содержимого указанного файла
Конфигурация
Для того, чтобы начать конфигурировать содержимое данной строки, скопируем файл конфига по умолчанию к себе в домашнюю директорию:
mkdir -p ~/.config/i3status
cp /etc/i3status.conf ~/.config/i3status/config
Конфигурацию условно можно разделить на 3 части:
- блок
general
- содержит общие параметры - переменная
order
- в нее записывается порядок вывода интересующих модулей - блоки конфигурации модулей - непосредственно настройки самих блоков с метриками
Подробную инструкцию о вариантах конфигурирования можно получить в
man i3status
. Я же приложу свою уже готовую конфигурацию с комментариями,
как пример того, что нужно именно мне. Чтобы вывод был не скучный,
предварительно я установил в систему набор шрифтов с иконками Font Awesome:
# arch linux
sudo pacman -S ttf-font-awesome
После чего мы сможем искать подходящие иконки на официальном сайте, и вставлять их прямо в шаблоны вывода модулей i3status
# ~/.config/i3status/config
general {
colors = true # включение/выключение поддержки цветов true/false
interval = 1 # интервал обновления строки статуса, в секундах
output_format = "i3bar" # формат вывода, устанавливаем i3bar (JSON)
}
# порядок вывода модулей
order += "run_watch openvpn"
order += "run_watch openconnect"
order += "volume master"
order += "wireless _first_"
order += "battery all"
order += "disk /"
order += "memory"
order += "cpu_usage"
order += "cpu_temperature 0"
order += "tztime local"
# отслеживание процесса openvpn
# служит как индикатор работы openvpn клиента
# при запуске openvpn необходимо
# указывать параметр --writepid /var/run/openvpn.pid
run_watch openvpn {
pidfile = "/var/run/openvpn.pid"
format = " openvpn"
# если пареметр format_down оставить пустым,
# то при неактивном процессе блок будет отсутствовать
format_down=""
}
# аналогичный блок индикатор openconnect vpn клиента
# требуется запуск клиента с параметром --pid-file=/var/run/openconnect.pid
run_watch openconnect {
pidfile = "/var/run/openconnect.pid"
format = " openconnect vpn"
format_down=""
}
# управление громкостью звука
volume master {
format = " %volume" # шаблон громкости в активном состоянии
format_muted = " %volume" # шаблон громкости в состоянии muted (без звука)
device = "default"
mixer = "Master"
mixer_idx = 0
}
# индикатор WIFI
wireless _first_ {
# шаблон вывода, можно дополнить
# наименованием подключения %essid
# и ip адресом %ip
format_up = "%quality %frequency"
format_down = "W: down"
}
# состояние заряда батареи
battery all {
# шаблон вывода, можно дополнить
# оставшимся временем работы %emptytime
# энергопотреблением %consumption в ваттах
format = "%status %percentage"
# true - показ процента заряда от 0 до 100
# false - показ процента заряда от 0 до n, с учетом
# изношенности аккумулятора
last_full_capacity = true
format_down = "No battery"
status_chr = "" # статус подзарядки
status_bat = "" # статус в режиме работы от батареи
status_unk = "? UNK" # неизвестный статус
status_full = "" # статус полного заряда
path = "/sys/class/power_supply/BAT%d/uevent"
# нижний порог заряда, после которого блок
# будет окрашен в "color_bad" (по умолчанию красный)
# подробнее в man i3status
low_threshold = 10
}
# отслеживаемый накопитель
disk "/" {
# доступные переменные:
# %used, %percentage_used - занятое пространство
# %free, %percentage_free - свободное пространство
# %avail, %percentage_avail - доступное пространство
# %total - всего
format = " %avail"
# будет окрашен в "color_bad" (по умолчанию красный)
# при достижении нижнего порога менее 10GB доступного пространства
low_threshold = "10"
threshold_type = "gbytes_avail"
format_below_threshold = " Warning: %avail"
}
# миниторинг оперативной памяти
memory {
# доступные переменные:
# %total, percentage_total
# %used, percentage_used
# %free, percentage_free
# %available, percentage_available
# %shared, percentage_shared
format = " %used"
# порог, при котором вывод окрасится в
# желтый (degraded) или красный (critical)
# а формат вывода изменится на format_degraded
threshold_degraded = "1G"
threshold_critical = "200M"
format_degraded = "MEMORY < %available"
}
# температура процессора
cpu_temperature 0 {
format = " %degrees"
# верхний порог температуры, при достижении которого
# вывод окрасится красным,
# и формат изменится на format_above_threshold
max_threshold = "80"
format_above_threshold = " %degrees"
path = "/sys/class/thermal/thermal_zone0/temp"
}
# использование центрального процессора
cpu_usage {
# %usage - процентное использование ЦП
# %cpu<N> - начиная с %cpu0 и далее показывает использование ядер
format = " %usage"
# доступны параметры:
# degraded_threshold, окрас в желтый, по умолчанию 90
# max_threshold, окрас в красный, по умолчанию 95
# и кастомные форматы для них
# format_above_degraded_threshold и format_above_threshold
}
# вывод даты и времени по заданному формату
tztime local {
format = " %d %b %H:%M:%S"
}
Расширение штатного функционала
Что касается расширения i3status
сторонними модулями: нет встроенного
механизма запуска сторонних сценариев или команд. Вместо этого
в man i3status
предлагается
при помощи своего bash скрипта оборачивать запуск i3status
, и обогащать его
своими собственными метриками путем дополнения строки вывода
следующим образом:
#!/bin/sh
i3status | while :
do
read line
echo "mystuff | $line" || exit 1
done
Но! Данный способ будет работать только если установлен формат вывода
output_format = "term"
. Также, при расширении подобным способом, теряется
отображение цветов (способ оптимальный, если цвета вам не нужны, и вы и так
установили в блоке general
основного конфига colors = false
)
Если у вас установлен output_format = "i3bar"
, как предлагается в
данной статье, то скрипт будет выглядеть немного иначе, т.к. для i3bar
вывод
реализован в JSON формате. Прийдется вклиниваться в выходной JSON и
изменять его, вставляя свои блоки.
За основу возьмем
пример скрипта обертки из репозитория i3status на github.
Предположим для примера, что мы хотим выводить в i3status
время работы компьютера с момента старта системы, uptime.
Получить uptime нам поможет команда uptime -p
# up 2 hours, 14 minutes
uptime -p
Чтобы добавить результат в выдачу, сначала добавим в конфигурационный файл
~/.config/i3status/config
следующий блок, который назовем custom_uptime
:
tztime custom_uptime {
format = "custom_uptime"
}
добавим его к order
для вывода в нужном нам порядке между другими блоками.
На tztime не обращаем внимания, просто копируем
# ...
order += "tztime custom_uptime"
# ...
Переработаем скрипт обертку, и сохраним в ~/bin/i3status-custom.sh
, и не
забудем дать права на запуск chmod +x ~/bin/i3status-custom.sh
#!/bin/bash
# цвета
COLOR_GREEN="#00FF00"
COLOR_RED="#FF0000"
# служебная функция редактирования блока
function update_holder {
local instance="$1"
local replacement="$2"
echo "$json_array" | jq --argjson arg_j "$replacement" "(.[] | (select(.instance==\"$instance\"))) |= \$arg_j"
}
# служебная функция удаления блока
function remove_holder {
local instance="$1"
echo "$json_array" | jq "del(.[] | (select(.instance==\"$instance\")))"
}
# служебная функция формирования json блока
# возвращает json с переданным текстом и цветом
# по умолчанию без цвета
# example: forming_json_block "any text" "$COLOR_GREEN"
# output: { "full_text": "any text", "color": "#00FF00" }
function forming_json_block {
local body=$1
local color=$2
local json=`echo null | jq "{full_text: \"$body\"}"`
if [[ $color ]]; then
json=`echo null | jq "$json + {color: \"$color\"}"`
fi
echo $json
}
# получение значения uptime
# формирование JSON с полученным текстом
# примешивание нашего JSON к общему JSON
function update_uptime {
# формируем body содержимым, которое собираемся вывести
body=`uptime -p`
# сформируем json блока.
# вторым параметром можно передать цвет
# "$COLOR_GREEN" или "$COLOR_RED"
local json=`forming_json_block "$body"`
# примешивание нашего JSON к общему JSON
# первым параметром передаем имя блока в конфиге
json_array=$(update_holder custom_uptime "$json")
}
# перехват JSON i3status, обогащение его своей выдачей
i3status | (read line; echo "$line"; read line ; echo "$line" ; read line ; echo "$line" ; while true
do
read line
json_array="$(echo $line | sed -e 's/^,//')"
# тут вызов функции обновления uptime
update_uptime
echo ",$json_array"
done)
По аналогии с функцией update_uptime
можно реализовывать другие кастомные
функции, внутри которых важно только записать в переменную body
выводимый
текст, а также по желанию добавить цвет вторым параметром в функцию формирования
json forming_json_block
. Напоследок необходимо добавить вывод своей функции
в цикле.
Осталось только в конфигурационном файле i3wm
заменить запуск i3status
на
наш собственный скрипт
bar {
status_command exec ~/bin/i3status-custom.sh
}
Результат выглядит так:
Внимание! Прежде чем оборачивать i3status
вызовом какой - либо тяжелой функции, посмотрите
в сторону выноса этой функции в фоновый режим, например по расписанию crontab,
а уже в i3status выводите заранее сохраненные результаты работы вашей
тяжелой функции, например модулем File Contents (read_file
).
Особенно, если i3status
обновляется каждую секунду.
Аналоги
Расширение функционала i3status
возможно, но не очень изящно потому,
что программа изначально не содержит для этого никаких штатных возможностей.
Однако есть более настраиваемые аналоги, например: