LaTeX

2015-03-19

Нотификация продолжительных комманд в bash и KDE

Проблема: При запуске «долгоиграющих» команд в консоли благополучно забываешь о них, переключаясь на другие задачи. Нужна нотификация окончания таких команд, дабы экономить время.

Решение: Для начала, сделаем хорошо нашему .bashrc и нам - вынесем все что касается приглашения коммандной строки в отдельный файл .bash_prompt, а в .bashrc оставим:

if [ -f ~/.bash_prompt ]; then
    . ~/.bash_prompt
fi
Чтобы отслеживать продолжительности комманды, очевидно, необходимо записать время начала команды и ее окончание. К сожалению, прямого пути здесь нет. Сценарий будет следующим:
  1. Записываем время команды в файлик.
  2. По окончании выполнения команды - сравниваем текущее время и записанное.
  3. Если времени много - нофицируем пользователя, что команда закончилась.

Запись времени команды в файлик

Как мы знаем, в bash есть замечательная переменная окружения PROMPT_COMMAND, в которой записанная по имени функция будет вызываться каждый раз при выводе приглашения оболочки. Это было первое что мне пришло на ум - сохранять время в этой точке. Вторая мысль, которая пришла следом - куда сохранять: для каждого tty в отдельный файл. Таким образом, две команды из разных консолек не «пересекутся». Например это было бы примерно так:

command_prompt() {
  FTTY=`tty | sed 's#/#_#g'`
  now=`date '+%s'`                  # Текущее время
  
  # do not overwrite until promt notifies and removes
  if [ ! -f "/tmp/$FTTY" ]; then
    echo $now > "/tmp/$FTTY"
  fi
}
PROMPT_COMMAND=command_prompt
Записать, записали. Как видно, здесь стоит проверка существования файла со временем. Если же файл есть, значит команда уже была и мы можем прочитать его и проверить длительность.
LONG_TIMEOUT=60
command_prompt() {
  FTTY=`tty | sed 's#/#_#g'`
  now=`date '+%s'`                  # Текущее время

  if [ -f "/tmp/$FTTY" ]; then
    last_command_time=`cat "/tmp/$FTTY"`
    if [ `expr $now - $last_command_time` -gt $LONG_TIMEOUT ]; then
      notify_long_command `expr $now - $last_command_time`
    fi
    
    rm -f "/tmp/$FTTY"
  fi
  
  echo $now > "/tmp/$FTTY"

}
PROMPT_COMMAND=command_prompt
Осталось нотифицировать. За что мне понравился в свое время KDE, так это за маленькую удобную консольную утилитку kdialog. Незаменимая вещь для налаживания доброго диалога с пользователем. Она может показывать диалоги:
  • Текстовые (обычные, предупреждающие, извиняющиеся, ошибочные), как просто так и с кнопками да-нет-наверное (kdialog --yesnocancel "Привет, наверное!")
  • Принимать ввод пользователя, простым текстовым полем, выпадающим списком, переключалками или чекбоксами, слайдер, календарь и даже цвет
  • Выводить прогресс бар!
  • запрашивать файловые вещи, путь файла, папки или URL (диалоги выбора файла)
  • ну и определять заголовок диалога, переопределять тексты кнопок и сохранять выбор пользователя "не показывать мне больше"
и все это простой командой kdialog. Ну и использовать я ее буду так:
notify_long_command() {
  if which kdialog > /dev/null; then
    kdialog --passivepopup "\"$1\" completes in `format_time $2`"
  fi
}
--passivepopup позволяет «кинуть» нотификацию, как, например, при отвалившейся сети. И вот тут, захотелось большего - знать конкретную команду, которая выполняется. И иметь, в конце концов, нотификацию вида "rm -rf / завершилась за 00:05:25". Но авто-переменной BASH с текущей командой нет. Максимум что удалось накопать - это переменная, в которой записано "bash" - это и правда текущая команда :)

Комментариев нет:

Отправить комментарий