Создаем пользовательские уведомления в Linux и Mac

590
Создаем пользовательские уведомления в Linux и Mac
Создаем пользовательские уведомления в Linux и Mac

Как создавать пользовательские уведомления в Linux и Mac, напоминания на рабочем столе из терминала Linux.

Иногда полезно получать визуальную обратную связь от скрипта. Например, когда сценарий или задание cron завершается. Или когда не удается выполнить длительную сборку. Или при возникновении срочной проблемы во время выполнения скрипта. Настольные приложения могут делать это с помощью всплывающих уведомлений. Но это можно сделать и из сценария! Вы можете использовать команды сценария для отправки себе уведомлений и напоминаний.

уведомления в Linux и Mac

Приведенный ниже код был написан и протестирован на Linux. А как насчет MacOS? Ну… это тоже можно сделать, приложив немного усилий. Некоторые подсказки и советы см. в последней главе.

Отправка уведомлений из терминала Linux

Чтобы отправить уведомление из терминала Linux, используйте команду notify-send. Выполните команду which at, чтобы проверить, присутствует ли она. Если нет, установите его с помощью выбранного вами менеджера пакетов, например

sudo apt install notify-send

Несколько примеров простых уведомлений:

notify-send "Dinner ready!"
notify-send "Tip of the Day" "How about a nap?"

Вы можете настроить уведомление с помощью таких опций, как уровень срочности, пользовательский значок и т.д. Узнайте больше с помощью man notify-send. Вы можете использовать небольшой набор HTML-тегов в теле уведомления, чтобы придать вашим уведомлениям приятный внешний вид. Кроме того, URL отображаются как кликабельные, например:

notify-send -u critical \
  "Build failed!" \
  "There were <b>123</b> errors. Click here to see the results: http://buildserver/latest"

уведомления в Linux и Mac

Отправленные уведомления обрабатываются средой рабочего стола и отображаются так же, как и любые другие уведомления. Они будут иметь одинаковый внешний вид, оформление и поведение.

Объедините уведомление-отправку с AT

Мы все знаем cron, используемый для планирования команд через регулярные промежутки времени. Команда at используется для планирования однократного выполнения команды в определенное время. Если вы запустите ее следующим образом:

at 12:00

Оно запустится в интерактивном режиме, где вы можете вводить команды для выполнения в заданное время. Это не очень удобно для скриптов. К счастью, at принимает параметры из стандартного ввода, поэтому мы можем использовать его таким образом:

echo "npm run build" | at now + 1 minute
echo "backup-db" | at 13:00

Существует множество способов указания времени. От абсолютного времени, например 10:00, относительного времени, например сейчас + 2 часа, до особого времени, например полдень или полночь. Мы можем комбинировать его с notify-send, чтобы, например, показывать себе напоминания в определенное время в будущем:

echo "notify-send 'Stop it and go home now?' 'Enough work for today.' -u critical" | at now

уведомления в Linux и Mac

Запланированные команды выполняются демоном под названием atd. В некоторых системах он не запущен по умолчанию. Вы можете использовать команду systemctl, чтобы включить демон и заставить его запускаться автоматически при перезагрузке системы:

sudo systemctl enable --now atd

Команда REMIND

Теперь давайте создадим пользовательскую команду bash для отправки себе напоминаний. Как насчет чего-то простого и удобного для человека, например:

remind "I'm still here" now
remind "Time to wake up!" in 5 minutes
remind "Dinner" in 1 hour
remind "Take a break" at noon
remind "It's Friday pints time!" at 17:00

Смотрите приведенный ниже код. Он определяет функцию оболочки под названием remind, которая поддерживает приведенный выше синтаксис. Фактическая работа выполняется в последних двух строках. Остальное отвечает за помощь, проверку параметров и т.д., что примерно соответствует соотношению полезного кода и необходимого белого шума в любом большом приложении 😉

Сохраните код где-нибудь, например, в файле ~/bin/remind и пропишите функцию в профиле .bashrc, чтобы она загружалась при входе в систему:

source ~/bin/remind

Перезагрузите терминал, затем введите remind, чтобы увидеть синтаксис. Наслаждайтесь!

#!/usr/bin/env bash
function remind () {
  local COUNT="$#"
  local COMMAND="$1"
  local MESSAGE="$1"
  local OP="$2"
  shift 2
  local WHEN="$@"
  # Display help if no parameters or help command
  if [[ $COUNT -eq 0 || "$COMMAND" == "help" || "$COMMAND" == "--help" || "$COMMAND" == "-h" ]]; then
    echo "COMMAND"
    echo "    remind <message> <time>"
    echo "    remind <command>"
    echo
    echo "DESCRIPTION"
    echo "    Displays notification at specified time"
    echo
    echo "EXAMPLES"
    echo '    remind "Hi there" now'
    echo '    remind "Time to wake up" in 5 minutes'
    echo '    remind "Dinner" in 1 hour'
    echo '    remind "Take a break" at noon'
    echo '    remind "Are you ready?" at 13:00'
    echo '    remind list'
    echo '    remind clear'
    echo '    remind help'
    echo
    return
  fi
  # Check presence of AT command
  if ! which at >/dev/null; then
    echo "remind: AT utility is required but not installed on your system. Install it with your package manager of choice, for example 'sudo apt install at'."
    return
  fi
  # Run commands: list, clear
  if [[ $COUNT -eq 1 ]]; then
    if [[ "$COMMAND" == "list" ]]; then
      at -l
    elif [[ "$COMMAND" == "clear" ]]; then
      at -r $(atq | cut -f1)
    else
      echo "remind: unknown command $COMMAND. Type 'remind' without any parameters to see syntax."
    fi
    return
  fi
  # Determine time of notification
  if [[ "$OP" == "in" ]]; then
    local TIME="now + $WHEN"
  elif [[ "$OP" == "at" ]]; then
    local TIME="$WHEN"
  elif [[ "$OP" == "now" ]]; then
    local TIME="now"
  else
    echo "remind: invalid time operator $OP"
    return
  fi
  # Schedule the notification
  echo "notify-send '$MESSAGE' 'Reminder' -u critical" | at $TIME 2>/dev/null
  echo "Notification scheduled at $TIME"
}

Уведомления с помощью сценариев в MacOS

Хотя в MacOS нет функции уведомления-отправки, уведомления можно отправлять с помощью ActionScript. Например:

osascript -e 'display notification "Wake up!" with title "Reminder"'

Полную документацию по команде display notification можно найти здесь. Кроме того, имеется at, так что все должно быть просто? А вот и нет. К сожалению, MacOS все больше усложняет использование своих возможностей для опытных пользователей…

Во-первых, команда at по умолчанию отключена. Даже если вы ее запустите, в запланированное время ничего не произойдет, потому что демон atrun отключен, и ни одной учетной записи пользователя по умолчанию не разрешено ее использовать.

Чтобы разрешить себе использовать команду, отредактируйте файл /var/at/at.allow и добавьте свое имя пользователя:

sudo open -a textedit /var/at/at.allow

Затем включите демон atrun:

sudo launchctl load -w /System/Library/LaunchDaemons/com.apple.atrun.plist

Давайте попробуем отправить уведомление:

osascript -e 'display notification "Wake up!" with title "Reminder"' | at now

… и ничего не происходит. Почему?

Демону не разрешено взаимодействовать с рабочим столом и ни с чем другим. Чтобы исправить это, зайдите в System Preferences / Security & Privacy / Privacy / Full Disk Access и добавьте atrun в список. Файл находится по пути /usr/libexec/atrun. Вы хотите видеть следующее:

… только как выбрать этот файл? MacOS не отображает системные папки в селекторе файлов, даже если минуту назад вам было предложено авторизоваться как администратор. Мне удалось обойти это, добавив папку /usr в список избранных папок в Finder:

И последнее, но не менее важное: для некоторых даже это не сработает. AT не будет посылать эти надоедливые уведомления, и точка. Это как-то связано с выполнением скрипта не в пространстве пользователя. Вы можете найти больше информации и решение здесь. Вот что помогает:

# Install reattach-to-user-namespace utility
brew install reattach-to-user-namespace
# Run notification command as follows
reattach-to-user-namespace osascript -e 'display notification "Wake up!" with title "Reminder"' | at now

Надеюсь, у вас сработает уведомления в Linux и Mac, и вы сможете использовать скрипт напоминания remind на вашем Mac!

уведомления в Linux и Mac