Настройка i3status в i3wm - igancev blog

Настройка i3status в i3wm

Разберем возможности i3status, программы генерации строки состояния системы, интегрированную в панель i3bar внутри оконного менеджера i3wm

Почти в любой ОС, или отдельных графических окружениях мы, как пользователи, привыкли к системному бару, панели на экране, на котором в Windows расположена кнопка пуск и иконки запущенных программ, в Mac OS глобальное меню активного приложения. Часто общим для всех систем является то, что на ней расположен трей с иконками запущенных программ, дата, время, и многое другое.

i3bar

Скриншот i3wm i3bar расположенный в верхней части экрана

Отрисовкой такой панели в i3wm занимается утилита i3bar. Она отображается вверху или внизу экрана, и содержит:

  • область с кнопками переключения рабочих областей i3
  • системную строку, генерируемую при помощи i3status или аналогов
  • системный трей с иконками программ

i3status

i3status - это небольшая программа, которая генерирует строку состояния для i3bar. Для того, чтобы наглядно посмотреть ее в действии, запустим ее через терминал:

Скриншот i3wm i3bar расположенный в верхней части экрана + i3status

Если вы наблюдаете 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

Вывод i3status с иконками от font awesome

# ~/.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 расширенный выводом uptime

Внимание! Прежде чем оборачивать i3status вызовом какой - либо тяжелой функции, посмотрите в сторону выноса этой функции в фоновый режим, например по расписанию crontab, а уже в i3status выводите заранее сохраненные результаты работы вашей тяжелой функции, например модулем File Contents (read_file). Особенно, если i3status обновляется каждую секунду.

Аналоги

Расширение функционала i3status возможно, но не очень изящно потому, что программа изначально не содержит для этого никаких штатных возможностей. Однако есть более настраиваемые аналоги, например: