julho 23, 2019

Enviando notificações com "notify-send" e "cron"

O cron é uma excelente ferramenta para agendar a execução automática de tarefas. Com ele podemos criar logs periódicos de sistema, rodar diagnósticos, trocar papéis de parede, checar e-mails, o nível da bateria do notebook, atualizações, exibir notificações na área de trabalho... Mas é aí que começam os problemas.

Especificamente no caso do notify-send, o cron irá precisar que pelo menos duas variáveis de ambiente sejam exportadas: DISPLAY e DBUS_SESSION_BUS_ADDRESS. Na maioria das vezes, quando queremos agendar uma tarefa que, de algum modo, deverá exibir alguma coisa no ambiente gráfico, basta exportar a varável DISPLAY na própria linha do crontab, por exemplo...

$ crontab -e

# No editor que for aberto incluir a linha...

*/10 * * * * DISPLAY=:0 feh --bg-scale --randomize ~/Imagens/wallpapers/*

# Salvar e sair...

Isso irá agendar uma troca de papel de parede aleatória a cada 10 minutos utilizando o programa feh. Eventualmente, DISPLAY pode não ser o :0, mas isso é bem fácil de descobrir na tentativa e erro ou, sendo mais técnico, utilizando o comando abaixo no terminal antes de criar o agendamento:

$ echo $DISPLAY
:0

A segunda varável, DBUS_SESSION_BUS_ADDRESS, já é um pouco mais ardilosa. Geralmente, quando existe apenas um usuário do sistema, seu valor será unix:path=/run/user/1000/bus, o que pode ser verificado com o comando abaixo:

$ env | grep DBUS_SESSION_BUS_ADDRESS
DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus

Neste valor, "1000" é o ID do usuário que fez o login (uid), e isso pode mudar. Para descobrir o seu ID de usuário, basta executar o comando id -u. No meu caso...

$ id -u
1000

O problema aqui, é que programas como o notify-send só serão executados se essa variável for passada para o cron. Isso aqui, funcionaria, mas não para todos os usuários, ou se o seu uid for diferente de "1000":

*/10 * * * * export DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus && export DISPLAY=:0 && notify-send "Olá mundo!"

Além de ser uma solução duvidosa, a linha fica horrivelmente longa e ilegível. Uma alternativa bem melhor seria criar um pequeno script e incluí-lo (com o comando source) nos scripts que serão chamados pelo cron.

O script seria basicamente assim:

#!/usr/bin/env bash

export DISPLAY=:0
eval "export DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/\$(id -u)/bus"

No meu caso, eu salvei o meu na pasta ~/.local/bin com o nome cron-exp-vars. Desse modo, sempre que eu quiser utilizar o notify-send através do cron, eu crio um script e incluo, via source, o arquivo cron-exp-vars.

Por exemplo, para me lembrar de pedir a marmita às 10:30h da manhã de segunda a sexta, eu criei o script cron-pedir-rango, com o código abaixo:

#!/usr/bin/env bash

# Aqui, eu incluo o script "cron-exp-vars".
# Lembre-se de que "source" ou "." são a mesma coisa.

. $HOME/.local/bin/cron-exp-vars

# Aqui está a linha do "notify-send" com a mensagem
# e o ícone que eu escolhi...

notify-send -u critical \
            "Pedir almoço!" \
            "Saco vazio não para em pé..." \
            -i $HOME/pics/icons/msg-reminder.svg &

# E eu ainda mando tocar um som de alerta...

aplay $HOME/music/sounds/alert-01.wav

Depois, é só incluir no crontab:

30 10 * * 1-5 ~/.local/bin/cron-pedir-rango

E funciona no meu i3wm!

Claro que a imagem só mostra um teste, já que não são 10:30h da manhã...

Funcionou pra você? Tem uma ideia melhor? Compartilhe conosco nos comentários!

 

Nenhum comentário:

Postar um comentário

O sistema de comentários do Blogspot é um lixo e praticamente me obriga a liberar ou moderar todos os comentários. Portanto, eu peço perdão antecipadamente caso o seu comentário demore para aparecer.

Mas não se acanhe por causa disso! :-)