Utilisation de notify-send avec cron

32

J'utilise Arch Linux avec KDE / Awesome WM. J'essaie notify-sendde travailler avec cron.

J'ai essayé de définir DISPLAY/ XAUTHORITYvariables et de courir notify-sendavec "sudo -u", le tout sans résultat.

Je peux appeler notifier-envoyer de manière interactive depuis la session et recevoir des notifications.

FWIW, le travail cron fonctionne correctement, ce que j'ai vérifié en faisant écho à un fichier temporaire. C'est juste le "notify-send" qui ne fonctionne pas.

Code:

[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 ~]$ 

Comme vous pouvez le voir, l'écho avant et après notification-envoi a fonctionné.
J'ai aussi essayé de réglerDISPLAY=:0.0

MISE À JOUR: J'ai cherché un peu plus et j'ai constaté que DBUS_SESSION_BUS_ADDRESS doit être défini. Et après avoir codé en dur cela en utilisant la valeur que j'ai obtenue de ma session interactive, le minuscule petit message "bonjour" a commencé à apparaître à l'écran toutes les minutes!

Mais le hic, c'est que cette variable n'est pas permanente pour ce poste, je vais donc essayer la solution de tuyau nommée suggérée ici.

[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

Étant donné cronque ne semble pas prendre en charge la notification-envoi (du moins pas directement), existe-t-il un autre système de notification plus cronconvivial que je peux utiliser?

juste quelqu'un
la source
Cela devrait fonctionner pour autant que je puisse voir. Pourquoi n'ajoutez-vous pas un &>>/tmp/crontestà la ligne d'envoi de notification et voyez si notify-senddonne des messages d'erreur.
Graeme
Par curiosité, avez-vous essayé ma solution? Cela semble beaucoup plus simple et fonctionnait parfaitement sur mon Debian. Je demande juste de savoir si c'est spécifique à Debian ou non
terdon
@terdon J'ai essayé votre solution (juste un test rapide) et elle semble fonctionner sur mon système Debian. J'aimerais savoir si c'est généralement applicable car c'est en effet plus simple.
Marco
@Marco Je suis sur LMDE (essentiellement des tests Debian) et j'utilise Cinnamon comme DE. Je ne peux pas vous dire si cela fonctionne au-delà de ceux-ci.
terdon
@Marco & terdon: les gars d'Ubuntu peuvent le faire: ubuntuforums.org/showthread.php?t=1727148
justsomeone

Réponses:

29

Vous devez définir la DBUS_SESSION_BUS_ADDRESSvariable. Par défaut, cron n'a pas accès à la variable. Pour y remédier, placez le script suivant quelque part et appelez-le lorsque l'utilisateur se connecte, par exemple en utilisant awesome et la run_oncefonction mentionnée sur le wiki. N'importe quelle méthode fera l'affaire, car elle ne nuit pas si la fonction est appelée plus souvent que nécessaire.

#!/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

Cela crée un fichier contenant la variable d'environnement Dbus requise. Ensuite, dans le script appelé par cron, vous importez la variable en recherchant le script:

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

Voici une réponse qui utilise le même mécanisme.

Marco
la source
1
Heureux de voir que j'étais presque proche de la solution. Merci Marco, c'est bien!
justsomeone
Très bien
rubo77
Ne serait-ce pas un risque pour la sécurité? security.stackexchange.com/questions/71019/…
rubo77
@Gilles Comment pouvez-vous faire cela en une seule ligne comme vous l'avez mentionné dans le chat?
rubo77
J'ai essayé tant d'autres réponses sans DBUS sur Ubuntu 15.10 et rien n'a fonctionné. Celui-là est simple et fonctionne parfaitement.
Bastian
16

Vous devez définir les variables dans la crontab elle-même:

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

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

Pas sudonécessaire, du moins pas sur mon système.

terdon
la source
Merci Terdon pour votre temps. Cela semble être une solution simple. Malheureusement, cela n'a pas fonctionné pour moi,
justsomeone
@justsomeone hein, OK, cela pourrait alors dépendre de l'environnement de bureau.
terdon
Je pense que cela a quelque chose à voir avec la distribution ou l'environnement de bureau. Pour les utilisateurs d'Ubuntu, les solutions simples semblent bien fonctionner d'après ce que j'ai vu dans les forums en ligne.
justsomeone
@justsomeone Je suis sur Debian (LMDE) en utilisant Cinnamon comme DE. Cela pourrait avoir quelque chose à voir avec la façon dont X est démarré ou avec le système de notifications utilisé par le DE, ne sais pas.
terdon
Confirmé que cela fonctionne sur Ubuntu 14.04 / 14.10. Avec GNOME et Unity.
Jordon Bedwell
8

Le moyen le plus sûr d'obtenir des variables d'environnement liées à la session X est de les extraire de l'environnement d'un processus de l'utilisateur connecté à X. Voici une adaptation du script que j'utilise exactement dans le même but (bien que DBUS_SESSION_BUS_ADDRESS ne le fasse pas) semble être un problème pour moi sur 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"

Cela envoie un message au premier utilisateur X qu'il trouve, bien que vous puissiez ajouter une boucle pour l'envoyer à tous les utilisateurs.

Mise à jour

Il semble que les mises à jour du format utmp provoquent l' whoimpression d'un affichage au lieu d'un tty dans sa deuxième colonne. En fait, cela facilite les choses, auparavant, il n'imprimait que l'affichage dans le commentaire à la fin et j'ai décidé que ce n'était pas sûr de s'appuyer sur la réponse originale. Si tel est le cas, essayez ceci:

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"
Graeme
la source
Cela ne fonctionne pas pour moi sur Trusty car il n'y a pas de tty imprimé dans la who_linecommande. La sortie ressemble me :0 2015-09-23 10:40 ? 17234.
blujay
1
@blujay, mis à jour.
Graeme
Merci, ça marche. Cependant, comme j'ai posté dans une réponse séparée, il existe une solution encore plus simple.
blujay
@blujay ouais, c'était une tentative de réponse portable. Je ne suis pas sûr que ce soit vraiment possible, mais cela devrait toujours fonctionner dans la plupart des cas.
Graeme
2

Ce one-liner a fonctionné pour moi à Manjaro avec 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.'

Sans le très laid DBUS_blah_blah, cela ne fonctionne pas du tout. J'ai aussi trouvé journalctl -xb -u cronieutile. Je ne connais pas encore Cronie, mais j'ai créé mon "crontab" en tant que /etc/cron.d/mycronjobset je ne sais pas si ce nom de fichier est requis, ou s'il lit tout dans le répertoire cron.d.

J'ai trouvé la solution ici https://wiki.archlinux.org/index.php/Desktop_notifications

PJ Brunet
la source
2

J'utilise i3 sur Ubuntu 18.04. Ma façon de résoudre ce problème est la suivante:

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

M. Goferito
la source
1

C'est suffisant pour faire fonctionner notifier-envoyer pour moi dans un cronjob sur Ubuntu Trusty:

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

Il exporte simplement le DISPLAYpour l'utilisateur sous lequel le cronjob s'exécute. Cela fonctionne pour moi sans réglage XAUTHORITYni DBUS_SESSION_BUS_ADDRESS.

blujay
la source
1
Fonctionne également sur Ubuntu 16.04. J'ai en fait cron lancer un script Perl, qui système () est un script bash, qui lance un autre script Perl, qui exécute un système ("notify-send ..."). L'ajout de la commande d'exportation au script bash a modifié l'environnement de ce script, que le dernier script Perl a ensuite hérité et mis à la disposition du système ("notify-send ..."). Bonne trouvaille blujay!
Tim
1

Pour ceux sous Linux qui sont à l'aise pour installer des packages Python, je viens de publier un programme notify-send-headless qui fonctionne bien pour moi. Il recherche /procle nom d'utilisateur et les variables d'environnement requis, puis s'exécute notify-sendavec ces variables (il utilisera sudopour basculer vers l'utilisateur requis si nécessaire).

xolox
la source
1

Vous pouvez également créer un script:

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

Ensuite, exécutez-le avec sudo. Cependant, puisque crontab -eexécute toutes les commandes avec l'utilisateur qui l'a créé, les éléments suivants devraient suffire lorsqu'ils sont appelés sans sudo:

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

Au moins, c'est le cas pour moi. Tout semble dépendre de la configuration de l'environnement.

user1112789
la source
0

J'utilise ce script dans cron pour publier MPD en train de jouer sur twitter toutes les heures

#!/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 similaire utilisant 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

vous pouvez rencontrer des problèmes car KDE utilise son propre IIRC de notification-démon.

cirrus
la source
0

Pour ce que ça vaut ...

J'ai dû utiliser TOUS les éléments suivants sur Debian Jessie pour que cela fonctionne ...

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

L'omission de l'un de ces éléments l'a empêché de fonctionner.

BenJ
la source
Cette dernière ligne ne fera rien comme écrit ici, car il n'y aura aucun fichier appelé littéralement *-0dans votre session-busrépertoire. Vous auriez peut-être voulu dire source "$HOME"/.dbus/session-bus/*-0.
roaima
0

Utilisation de sudo:

sudo -u $currentxuser notify-send $message

Pointe :

Nous pouvons obtenir l'utilisateur x actuel par cette commande

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

En plus...

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

Bon à savoir :

Cron fonctionnant sous root n'a pas accès à x donc toutes les commandes gui ne seront pas affichées, une solution simple est d'ajouter root à l'utilisateur x autorisé pour l'utilisateur x actuel avec cette commande

à partir du shell utilisateur x

xhost local:root

ou

sudo -u $currentxuser xhost local:root
intika
la source
-1

Voici un script moins complexe que celui fourni par Graeme. Son script ne fonctionnait pas pour moi, $who_lineétait toujours vide. Mon script ne perd pas autant de temps à trouver un processus. Au lieu de cela, il essaie tout simplement et sélectionne la dernière valeur utile trouvée. J'exécute xubuntu 14.04 et j'ai quelques conteneurs lxc en cours d'exécution qui confondent probablement ce genre 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"
Daniel Alder
la source
Cela ne fonctionne pas pour moi sur Trusty car l'environnement du processus Xorg n'en a pas DBUS_SESSION_BUS_ADDRESS. Je peux l'obtenir de mes shells, mais pas du processus Xorg.
blujay