Usando o comando notify-send com o cron

28

Estou usando o Arch Linux com o KDE / Awesome WM. Estou tentando conseguir notify-send para trabalhar com cron .

Eu tentei definir DISPLAY / XAUTHORITY variáveis e executar notify-send com "sudo -u", tudo sem resultado.

Eu posso chamar notificar-enviar interativamente da sessão e receber notificações.

FWIW, a tarefa cron está funcionando bem, o que verifiquei fazendo eco de um arquivo temporário. É apenas o "notificar-enviar" que não funciona.

Código:

[matrix@morpheus ~]$ crontab -l
* * * * *  /home/matrix/scripts/notify.sh

[matrix@morpheus ~]$ cat /home/matrix/scripts/notify.sh
#!/bin/bash
export DISPLAY=127.0.0.1:0.0
export XAUTHORITY=/home/matrix/.Xauthority
echo "testing cron" >/tmp/crontest
sudo -u matrix /usr/bin/notify-send "hello"
echo "now tested notify-send" >>/tmp/crontest

[matrix@morpheus ~]$ cat /tmp/crontest
testing cron
now tested notify-send

[matrix@morpheus ~]$ 

Como você pode ver o eco antes de & depois de notificar-enviar funcionou.
Também tentei definir DISPLAY=:0.0

ATUALIZAÇÃO: Eu procurei um pouco mais e descobriu que DBUS_SESSION_BUS_ADDRESS precisa ser configurado. E depois de codificar isso usando o valor que obtive da minha sessão interativa, a minúscula mensagem "hello" começou a aparecer na tela a cada minuto!

Mas o problema é que essa variável não é permanente por esse post, então tentarei a solução de pipe nomeado aqui sugerida.

[matrix@morpheus ~]$ cat scripts/notify.sh
#!/bin/bash
export DISPLAY=127.0.0.1:0.0
export XAUTHORITY=/home/matrix/.Xauthority
export DBUS_SESSION_BUS_ADDRESS=unix:abstract=/tmp/dbus-BouFPQKgqg,guid=64b483d7678f2196e780849752e67d3c
echo "testing cron" >/tmp/crontest
/usr/bin/notify-send "hello"
echo "now tested notify-send" >>/tmp/crontest

Como cron não parece suportar notificar-enviar (pelo menos não diretamente), existe algum outro sistema de notificação que seja mais cron amigável que eu possa usar?

    
por justsomeone 27.01.2014 / 20:12

12 respostas

26

Você precisa definir a variável DBUS_SESSION_BUS_ADDRESS . Por padrão, o cron faz não tem acesso à variável. Para remediar isso, coloque o seguinte script em algum lugar e chamá-lo quando o usuário fizer login, por exemplo, usando incrível e a função run_once mencionada no wiki. Qualquer método fará, desde que não faz mal se a função é chamada mais frequentemente do que o necessário.

#!/bin/sh

touch $HOME/.dbus/Xdbus
chmod 600 $HOME/.dbus/Xdbus
env | grep DBUS_SESSION_BUS_ADDRESS > $HOME/.dbus/Xdbus
echo 'export DBUS_SESSION_BUS_ADDRESS' >> $HOME/.dbus/Xdbus

exit 0

Isso cria um arquivo contendo a variável necessária do Dbus evironment. Então em o script chamado pelo cron você importa a variável, sourcing o script:

if [ -r "$HOME/.dbus/Xdbus" ]; then
  . "$HOME/.dbus/Xdbus"
fi

Aqui está uma resposta que usa o mesmo mecanismo.

    
por 27.01.2014 / 20:30
15

Você precisa definir as variáveis no próprio crontab:

DISPLAY=:0.0
XAUTHORITY=/home/matrix/.Xauthority

# m h  dom mon dow   command 
* * * * *  /usr/bin/notify-send "hello"

Não é necessário sudo , pelo menos não no meu sistema.

    
por 27.01.2014 / 20:24
7

A maneira mais segura de obter variáveis ambientais relacionadas à sessão X é obtê-las do ambiente de um processo do usuário que está conectado ao X. Aqui está uma adaptação do script que eu uso exatamente com o mesmo propósito (embora DBUS_SESSION_BUS_ADDRESS não parece ser um problema para mim no Debian):

X=Xorg                   # works for the given X command
copy_envs="DISPLAY XAUTHORITY DBUS_SESSION_BUS_ADDRESS"

tty=$(ps h -o tty -C $X | head -1)
[ -z "$tty" ] && exit 1

# calling who with LANG empty ensures a consistent date format
who_line=$(LANG= who -u | grep "^[^ ]\+[ ]\+$tty")

x_user=$(echo $who_line | cut -d ' ' -f 1)  # the user associated with the tty
pid=$(echo $who_line | cut -d ' ' -f 7)     # the user's logon process

for env_name in $copy_envs
do
  # if the variable is not set in the process environment, ensure it does not remain exported here
  unset "$env_name"

  # use the same line as is in the environ file to export the variable
  export "$(grep -az "^$env_name=" /proc/$pid/environ)" >/dev/null
done

sudo -u "$x_user" notify-send "hello"

Isso envia uma mensagem para o primeiro usuário X encontrado, embora você possa adicionar um loop para enviá-lo a todos os usuários. Espero que isso ajude.

Atualizar

Parece que as atualizações no formato utmp fazem com que who imprima uma exibição em vez de uma tty na segunda coluna. Isso realmente torna as coisas mais fáceis, anteriormente ele apenas imprimia a exibição no comentário no final e eu decidi que não era seguro confiar na resposta original. Se este for o caso, tente isto:

X=Xorg                   # works for the given X command
copy_envs="DISPLAY XAUTHORITY DBUS_SESSION_BUS_ADDRESS"

# calling who with LANG empty ensures a consistent date format
who_line=$(LANG= who -u | awk '$2 ~ ":[0-9]"')

x_user=$(echo $who_line | cut -d ' ' -f 1)  # the user associated with the tty
pid=$(echo $who_line | cut -d ' ' -f 7)     # the user's logon process

for env_name in $copy_envs
do
  # if the variable is not set in the process environment, ensure it does not remain exported here
  unset "$env_name"

  # use the same line as is in the environ file to export the variable
  export "$(grep -az "^$env_name=" /proc/$pid/environ)" >/dev/null
done

sudo -u "$x_user" notify-send "hello"
    
por 27.01.2014 / 20:51
2

Este one-liner funcionou para mim em Manjaro com Cronie:

# Note: "1000" would be your user id, the output of... "id -u <username>" 
10 * * * * pj DISPLAY=:0 DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus notify-send 'Hello world!' 'This is an example notification.'

Sem o muito feio DBUS_blah_blah, ele não funciona. Eu também achei journalctl -xb -u cronie útil. Eu ainda não estou familiarizado com o Cronie, mas criei o meu "crontab" como /etc/cron.d/mycronjobs e não tenho certeza se esse nome de arquivo é necessário, ou se ele apenas lê tudo no diretório cron.d.

Encontrei a solução aqui link

    
por 16.02.2017 / 20:19
1

Isso é suficiente para fazer o trabalho de enviar notificações para mim em um cronjob no Ubuntu Trusty:

#!/bin/bash
export DISPLAY=$(who -u | awk  '/\s:[0-9]\s/ {print $2}')

Ele simplesmente exporta o DISPLAY para o usuário no qual o cronjob está sendo executado. Funciona para mim sem definir XAUTHORITY ou DBUS_SESSION_BUS_ADDRESS .

    
por 04.10.2015 / 01:33
1

Para aqueles no Linux que estão confortáveis instalando pacotes Python, eu acabei de lançar uma notificação envie-headless programa que está funcionando bem para mim. Ele procura /proc pelo nome de usuário e variáveis de ambiente necessários e, em seguida, executa notify-send com essas variáveis (usará sudo para alternar para o usuário necessário, se necessário).

    
por 22.04.2016 / 00:28
1

Você também pode criar um script:

#!/usr/bin/env bash
runuser -l [yourusername] -c 'DISPLAY=:0 notify-send "hey there user"'

Em seguida, execute-o com sudo . No entanto, como crontab -e executa todos os comandos com o usuário que os criou, o seguinte deve ser suficiente quando chamado sem sudo :

#!/usr/bin/env bash
DISPLAY=:0 notify-send "hey there user"

Pelo menos para mim. Tudo parece depender da configuração do ambiente.

    
por 11.02.2017 / 16:26
0

Eu uso este script no cron para postar MPD agora jogando no twitter a cada hora

#!/bin/bash
export DISPLAY=":0.0"
msg=$(mpc current -h 192.168.1.33)
twitter set "#MPD Server nowplaying $msg :  http://cirrus.turtil.net:9001"
#ttytter -status="#MPD Server nowplaying $msg. http://cirrus.turtil.net:9001"

exit 

script semelhante usando o comando notify-send

#!/bin/bash
export DISPLAY=":0.0"
notify-send -i ~/.icons/48arch.png 'OS- Archlinux x86_64 : DWM Window Manager' 'Installed on Sun Apr 21 2013 at 18:17:22' 
exit

você pode estar tendo problemas, já que o KDE usa seu próprio notificador-deamon IIRC.

    
por 03.09.2015 / 11:26
0

Por que vale a pena ....

Eu tive que usar TODOS os seguintes no Debian Jessie para fazer isso funcionar ...

export DISPLAY=:0.0
export HOME=/home/$user
source "$HOME/.dbus/session-bus/*-0"

Deixar de fora qualquer um deles fez com que parasse de funcionar.

    
por 05.04.2017 / 18:57
0

Usando o sudo:

sudo -u $currentxuser notify-send $message

Dica:

Podemos obter o atual usuário x por meio deste comando

ps auxw | grep -i screen | grep -v grep | cut -f 1 -d ' '

Além disso ...

currentxuser=$(ps auxw | grep -i screen | grep -v grep | cut -f 1 -d ' ')
echo $currentxuser

É bom saber:

Cron rodando sob root não tem acesso a x, portanto, todos os comandos gui não serão exibidos, uma solução simples é adicionar raiz ao usuário x autorizado para o usuário x atual com este comando

do x user shell

xhost local:root

ou

sudo -u $currentxuser xhost local:root
    
por 19.08.2018 / 15:19
0

Eu uso o i3 no Ubuntu 18.04. Minha maneira de resolver isso é:

* * * * * XDG_RUNTIME_DIR=/run/user/$(id -u) notify-send Hey "this is dog!"

    
por 03.12.2018 / 18:10
-1

Aqui está um script menos complexo do que o fornecido por Graeme. Seu script não funcionou para mim, $who_line estava sempre vazio. Meu roteiro não desperdiça muito tempo para encontrar um processo. Em vez disso, apenas tenta tudo e escolhe o último valor útil encontrado. Estou executando o 14.04 do xubuntu e tenho alguns contêineres lxc em execução que provavelmente confundem esse tipo de scripts.

env="$(
  ps -C init -o uid,pid | while read u p; do
    [ "$u" = "'id -u'" ] || continue
    grep -az '^DBUS_SESSION_BUS_ADDRESS=' /proc/$p/environ | xargs -0
  done | tail -1
)"

export "$env"

notify-send "test"
    
por 13.07.2015 / 12:51