Кукушка на 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%. «Алсо», «доставляет» и прочее встречаются всё реже.

                Похоже, скоро что-то новенькое придумают.
                  +9
                  Два чаю.

                    +1
                    Два/четыре снова живы?
                      +2
                      Хотя, да, сентябрь же на носу.
            +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. Второй еще хоть как-то слушать можно.

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

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