Кукушка на bash своими руками

Привет, %username%.

Для организации моей работы удобно видеть или слышать уведомления о том, что прошел час, полчаса и т.д. Это нужно мне для ориентации во временном пространстве и правильного планирования своей работы.
Поскольку у меня стоит Ubuntu, то и статья будет про то, как сделать такие уведомления стандартными средствами Ubuntu.


Итак, мне нужно:
  • каждый час видеть и слышать уведомление о времени
  • уведомление не должно отвлекать
  • решение должно быть легким и экономным с точки зрения ресурсов

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

Уведомления в Ubuntu


Как известно, для уведомлений в Ubuntu применяется утилита notify-send. В последних версиях Ubuntu notify-send используется как основное средство уведомлений. Это действительно очень удобно, когда все сообщения показываются однообразно. Пользоваться ей так:
$ notify-send title message

Запустив эту несложную команду в консоли, вы через некоторое время увидите уведомление с заголовком title и сообщением message. У меня это выглядит так:
пример уведомления
Отлично, выводить сообщения мы уже умеем, осталось научиться показывать их по расписанию.

Задачи по расписанию в linux


Для задач по расписанию есть в linux отличное средство crontab
crontab -e

отрывается редактор, вбиваем в него строку:
0 */1 * * * DISPLAY=:0.0 notify-send "Часовщик" "Прошел 1 час"  

Сохраняем, любуемся результатом. Если хочется поиграться, то можно поставить уведомления раз в минуту, тогда отладочная запись будет выглядеть как-то так:
*/1 * * * * DISPLAY=:0.0 notify-send "Часовщик" "Прошла 1 минута"  

Теперь через равные промежутки времени мы можем что-нибудь выводить пользователю:
пример уведомления каждую минуту
Для пользователей, не умеющих настраивать crontab могу посоветовать online генератор. Например, такой.
Отмечу отдельно, что я не стал возиться с определением номера дисплея. Да, он может меняться, но за несколько месяцев работы у меня он не разу не поменялся, т.к. у меня все-таки десктоп, а скрипт все-таки сделан на коленке.
Поделюсь ещё одним рецептом. Пользоваться crontab -e не очень удобно, т.к. открывается редактор по умолчанию. Обычно это nano. По-моему он ужасен. Я обычно делаю так:

crontab -l > /tmp/crontab.file && cp /tmp/crontab.file /tmp/crontab.file.backup && gedit /tmp/crontab.file && crontab /tmp/crontab.file

Открывается файл в удобном gedit, редактируется, сохраняется или не сохраняется. После закрытия окна gedit настройки попадают в crontab.
Или оформляем все это дело в скрипт и кладем, например, на рабочий стол:

#!/bin/sh
#  _Nicolay
# file editCrontab.sh
crontab -l > /tmp/crontab.file && cp /tmp/crontab.file /tmp/crontab.file.backup && gedit /tmp/crontab.file && crontab /tmp/crontab.file
rm /tmp/crontab.file

Диалоги в скриптах linux


Теперь, частично проблема была решена. Но только частично, ведь я не всегда смотрю на экран монитора и могу пропустить сообщение. На помощь мне пришла утилита zenity. Она также уже была в системе. Пишем смело в crontab
0 */1 * * * DISPLAY=:0.0 zenity --info --title="Часовщик" --text="Прошел один час"

или отладочная запись:
*/1 * * * * DISPLAY=:0.0 zenity --info --title="Часовщик" --text="Прошла одна минута"

В итоге получилось что-то типа такого:
диалог:прошла одна минута
Какое-то время работать было удобно, но со временем окно-уведомление стало меня доставать. Этот факт заставил меня модернизировать свои крон-скрипты. В итоге я наткнулся на 3-ю полезную утилиту: ESpeak.
Она позволяет синтезировать речевые сообщения на разных языках.
Добавляем новую строчку в crontab:
0 */1 * * * espeak  -vru -s130 "прошел 1 час"

или отладочная строка
*/5 * * * * espeak  -vru -s130 "прошло 5 минут"

В итоге, вот что получилось


Синтезатор речи по-русски говорил ужасно. Слушать было противно, и поэтому я переключился на английский и сделал ещё ряд доработок:
  • заставил часовщика говорить ещё и время
  • добавил напоминания о том, что нужно попить кофе.

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

# crontab file
#  _Nicolay
#  ежечасные уведомления о времени
0 */1 * * * /usr/local/scripts/hours.sh
# уведомления о кофе
23 12,16 * * * DISPLAY=:0.0 zenity --info --title="Уведомление" --text="пора бы кофейку!!!"

А файл hours.sh:

#!/bin/sh
# hours.sh
#  _Nicolay
DISPLAY=:0.0 notify-send "часовщик" "`date +%k` часов"
espeak  -ven -s130 "`date +%l` hours"

Я вынес скрипты в файл hours.sh из-за того, что crontab скрипт не поддерживает обработку машинописного обратного апострофа. Если же вы в crontab укажете машинописный обратный апостроф, то скрипт в указанное время не сработает.

Ну и под конец скрины того, как это выглядит у меня.

Каждый час выводится сообщение сколько времени:
23 часа
Сообщение дублируется звуком. Если я рядом с компьютером, я его услышу. И два раза в день мне отправляется напоминание о том, что нужно все-таки передохнуть.


UPD: Доработал скрипт на основе советов и комментариев.

Отдельное спасибо lionsimba за комментарий про festival.

В итоге, получилась новая версия hours.sh:

#!/bin/sh
# hours.sh
#  _Nicolay
#HOURS="`date +%l`"
HOURS="`date +%k`"

HOURS_TXT="Сколько времени?"
HOURS_TXT_SAY=$HOURS_TXT


if [ "$HOURS" -eq 11 ]; then
    HOURS_TXT="$HOURS часов"
    HOURS_TXT_SAY="$HOURS часов"
elif [ "$HOURS" -eq 12 ]; then
    HOURS_TXT="$HOURS часов"
    HOURS_TXT_SAY="$HOURS часов"
elif [ "$HOURS" -eq 13 ]; then
    HOURS_TXT="$HOURS часов"
    HOURS_TXT_SAY="$HOURS часов"
elif [ "$HOURS" -eq 14 ]; then
    HOURS_TXT="$HOURS часов"
    HOURS_TXT_SAY="$HOURS часов"
elif [ "$(($HOURS % 10))" -eq 0 ]; then
    HOURS_TXT="$HOURS часов"
    HOURS_TXT_SAY="$HOURS часов"
elif [ "$(($HOURS % 10))" -eq 1 ]; then
    HOURS_TXT="$HOURS час"
    HOURS_TXT_SAY="$HOURS час"
elif [ $(($HOURS % 10)) -lt 5 ]; then
    HOURS_TXT="$HOURS часа"
    HOURS_TXT_SAY="$HOURS часаa"
else
    HOURS_TXT="$HOURS часов"
    HOURS_TXT_SAY="$HOURS часов"
fi

DISPLAY=:0.0 notify-send -i "typing-monitor" "Часовщик" "$HOURS_TXT"
#espeak  -ven -s130 "`date +%l` hours"
echo "$HOURS_TXT_SAY" | festival --tts --language russian


Скрипт вполне сносно сообщает по-русски о времени.

На этом всё, спасибо за внимание.
Поделиться публикацией
Похожие публикации
Ой, у вас баннер убежал!

Ну. И что?
Реклама
Комментарии 44
  • +3
    Поставьте себе hamster в нём есть всё и дальше больше.
    • +1
      • +1
        Спасибо большое. Обязательно посмотрю.
        • 0
          Поставил. Посмотрел. Разочаровался.
          Это же просто тайм-трекер. А мне уведомления нужны были.
          Так что извините, это — не то.

          • 0
            Тайм трекер я тоже использую, только online: toogl.com.
            Этот тоже ничего, симпатичный, вроде все что нужно — умеет.
            Так что все-равно спасибо.
            • 0
              простите, опечатался с урлом: правильный toggl.com
      • +2
        Суть не том, что уже есть и поставить. Суть в том, что сделал сам, опыт это самое дорогое, ведь мы тут хабравчане и не было бы habr, если бы не умельцы…
      • +34
        Нельзя не вспомнить классику:
        x0: зобацал часы с кукушкой на серваке
        x0: в cron.hourly пешу скрыпт

        KUKU=`/bin/date +%I`
        while [ $KUKU -gt 0 ]; do
        eject /dev/cdrom
        cat /root/xxx/kuku.au > /dev/dsp
        eject -t /dev/cdrom
        KUKU=$((KUKU-1))
        done


        x0: ночальнег в полдень зашел и окуел
        x0: сцуко спасская биг тауэр


        • +1
          KUKU=$((KUKU-1))


          Просто ((KUKU--))
          :)
          • +5
            Как хорошо, что времена падонкафскава языка прошли. :)
            • +4
              Да уж времена «инфы 100% расово гарантирую» ничем особо-то и не лучше.
              • +3
                Закат близится, инфа 100%. «Алсо», «доставляет» и прочее встречаются всё реже.

                Похоже, скоро что-то новенькое придумают.
        • +2
          Я почему-то постоянно забываю про cron когда надо сделать что-то со временем. Поэтому меня будит такой скрипт:
          #!/bin/bash
          
          sh=7 # час
          sm=30 # минуты
          
          H=`date +%k`
          while [ $H -ne "$sh" ]; do 
          	sleep 300
          	H=`date +%k`
          done
          
          M=`date +%M`
          while [ $M -ne "$sm" ]; do
          	sleep 15
          	M=`date +%M`
          done
          
          banshee --play # Включаем плеер
          amixer -c 0 set Master 60 # Поднимаем громкость (в оригинале она постепенно поднимается, начиная с 25)
          • +1
            Спасибо за скриптик. Модифицировал его под себя, теперь использую для напоминания (память дырявая).

            Дописал в конец вместо звукового оповещения (скрипту передаётся час, минуты и тело сообщения):
            kdialog --passivepopup "$3" 120 # вариант для KDE
            sendemail -f name@domain.ru -t +7923xxxxxxx@sms.megafonsib.ru -o message-charset=utf-8 -u "Achtung!" -m "$3" -o message-format=text/html -s mail.domain.ru # отправка смс
            • +2
              Для будильников можно использовать `at`:
              echo -n "banshee --play; amixer -c 0 set Master 60" | at 7:30
            • +5
              Пользоваться crontab -e не очень удобно, т.к. открывается редактор по умолчанию. Обычно это nano.

              Не устраивает — есть update-alternatives (если я что-то помню по дебианообразным) и export $EDITOR. Это лучше.
              • +4
                Можно просто писать:

                EDITOR=gedit crontab -e
                • +1
                  У меня стоит EDITOR=mcedit
                  Для локальной работы вполне хватает. Но я стараюсь не приучать себя к такому, т.к. 90% crontab-ов я изменяю на серверах.

                  Когда заходишь на сервер и открываешь crontab, то каждый раз открывается что-нибудь новое. Этакая рулетка. Каждый разработчик считает своим долгом поставить в переменную EDITOR свой любимый редактор. Поэтому считаю наиболее приемлемым для себя сценарий вида:
                  crontab -l > ctfile
                  cp ctfile file.backup
                  mcedit ctfile # аккуратно редактирую, подписываю коммент, что и зачем и когда менял, сохраняю
                  crontab ctfile
                  

                  по мотивам этого сценария родился и скрипт, указанный в статье.
                  Главное в нем — это бекап того, что было, и контроль того, что есть.

                • +1
                  Синтезатор речи по-русски говорил ужасно. Слушать было противно, и поэтому я переключился на английский

                  Послушал на английском — не лучше :)
                  • +2
                    Стесняюсь спросить: а что означает запись вида "*/1" в кронтабе?
                    • +2
                      каждую 1 (минуту/час/день etc)
                      • +2
                        хорошо, тогда другой вопрос, посложнее: в чём отличие записи
                        * * * * * command
                        от
                        */1 */1 */1 */1 */1 command
                        от
                        * */1 * */1 * command
                        • 0
                          В чем сложность? Ничем не отличается. Я тоже минуты через слеш пишу — мой мозг быстрее охватывает картинку в консоли
                          • 0
                            не дописалось — с цифрами, звездоное небо я люблю вживую рассматривать, а на мониторе цифры люблю +)
                    • +2
                      1. Про $EDITOR уже сказали. Плюсую.

                      2. Есть вполне сносный русскоговорящий синтезатор голоса — festival, который, правда, требует некоторой предварительной настройки.
                      • +1
                        Оказывается, начиная с Ubuntu 10.04 русскоговорящий фестиваль есть в родных репозиториях под именем festvox-ru и ничего настраивать самому даже и не нужно:

                        sudo apt-get install festvox-ru
                        echo 'Привет, хабрахабр!' | festival --tts --language russian
                        • +1
                          Из вариантов:
                          echo 'Прошел 1 час' | festival --tts --language russian

                          echo 'Прошел 1 чааас' | festival --tts --language russian
                          • +1
                            Уже второй раз попадаюсь на ctrl+Enter…

                            Из вариантов:
                            echo 'Прошел 1 час' | festival --tts --language russian
                            echo 'Прошел 1 чаас' | festival --tts --language russian
                            echo 'Прошел 1 чааас' | festival --tts --language russian
                            echo 'Прошел 1 чаааас' | festival --tts --language russian


                            наиболее сносно произносит желаемую фразу — третий.
                            • 0
                              спасибо за подсказку. переделал свой скрипт на использование festival

                              простые слова он говорит шикарно
                              например:
                              echo "8 часов" | festival --tts --language russian
                              echo "18 часов" | festival --tts --language russian

                              Эту фразу говорит так, что со стороны не поймешь человек ли сказал или компьютер.

                              Вот такой вариант тоже вполне сносен:
                              echo 'москооовское время 8 часов' | festival --tts --language russian

                          • 0
                            А есть возможность завернуть звуковой выход festival на skype?
                            • 0
                              Думаю, никаких препятствий к этому нет. Нужно создать виртуальное звуковое устройство типа loopback, которое бы, с одной стороны, было устройством воспроизведения, а с другой стороны, устройством записи, посылающим всё, что воспроизводиться на свой же вход.

                              Тогда, настраиваем festival на воспроизведение через такое устройство, а в Skype вместо микрофона ставим запись с виртуального устройства.

                              Вот, например, человек спрашивает как это сделать в ALSA. И ему даже предложили пару вариантов.
                        • +3
                          чтобы работало с любой сессией вместо DISPLAY=:0.0 лучше использовать небольшое дополнение
                          #!/bin/sh
                          
                          init_notify() {
                          	user=`whoami`
                          	pids=`pgrep -u $user nautilus`
                          	for pid in $pids; do
                          		# find DBUS session bus for this session
                          		DBUS_SESSION_BUS_ADDRESS=`grep -z DBUS_SESSION_BUS_ADDRESS /proc/$pid/environ | sed -e 's/DBUS_SESSION_BUS_ADDRESS=//'`
                          		# use it
                          		export DBUS_SESSION_BUS_ADDRESS=$DBUS_SESSION_BUS_ADDRESS
                          	done
                          }
                          
                          notify() {
                          	if [ -z "$DBUS_SESSION_BUS_ADDRESS" ]; then
                          		init_notify
                          	fi
                          	
                          	title=$1
                          	text=$2
                          	timeout=$3
                          	
                          	if [ -z "$title" ]; then
                          		return
                          	fi
                          	if [ -z "$text" ]; then
                          		text=$title
                          	fi
                          	if [ -z "$timeout" ]; then
                          		timeout=5000
                          	fi
                          	
                          	notify-send "$title" "$text" -t $timeout
                          }
                          

                          и ниже сам вызов

                          notify "title" "text" 5000

                          найдено на просторах G
                          • 0
                            Ради справедливости и для windows дайте что-нибудь подобное. Желательно системными средствами без сторонних утилит.
                            • +3
                              Прошу прощения, написал и не посмотрел в каком блоге находится статься. Не очень красиво получилось.
                              Но если кто-нибудь поделится своими мыслями через личные сообщения, буду весь признателен.
                            • +1
                              Я полтора года наза писал о подобном, только попроще
                              kartz.ru/2010/02/24/at/
                              • +3
                                а у меня был скрипт для показа температуры hdd, если какой-нибудь перегрелся. Извините за внешний линк линк.

                                image

                                Писалось давно и скорее всего содержит ошибки. Хотя 2 года назад ещё работало.

                                • +4
                                  В кедах можно вызывать уведомления через kdialog, кстати.
                                  kdialog --passivepopup 'пора вставать!' 4

                                  • 0
                                    notify-send сработает одинаково и в гноме, и в кедах, а kdialog — только если есть кеды.
                                    • 0
                                      Верно. Но если есть только кеды, kdialog умеет и модальные окна показывать (вообще говоря, это его основное предназначение). Как раз в тему топика.
                                  • 0
                                    Выложил свежий обзор и примеры озвучки 2-х голосовых движков: ESpeak и Festival. Второй еще хоть как-то слушать можно.

                                    Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                                    Самое читаемое