Benutze notify-send mit cron

32

Ich benutze Arch Linux mit KDE / Awesome WM. Ich versuche mit notify-sendzu arbeiten cron.

Ich habe versucht, DISPLAY/ XAUTHORITYVariablen zu setzen und notify-sendmit "sudo -u" zu laufen , alles ohne Ergebnis.

Ich kann notify-send interaktiv von der Sitzung aus aufrufen und Benachrichtigungen erhalten.

FWIW, der Cron-Job läuft einwandfrei, was ich überprüft habe, indem ich Sachen in eine temporäre Datei zurückgesendet habe. Es ist nur das "Benachrichtigen-Senden", das nicht funktioniert.

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

Wie Sie sehen, hat das Echo vor und nach dem Benachrichtigungsversand funktioniert.
Auch ich habe Einstellung versuchtDISPLAY=:0.0

UPDATE: Ich habe ein bisschen mehr gesucht und festgestellt, dass DBUS_SESSION_BUS_ADDRESS gesetzt werden muss. Und nachdem ich dies mit dem Wert, den ich in meiner interaktiven Sitzung erhalten hatte, fest codiert hatte, tauchte jede Minute die winzige kleine "Hallo" -Meldung auf dem Bildschirm auf!

Aber der Haken ist, dass diese Variable für diesen Beitrag nicht permanent ist, also werde ich versuchen, die dort vorgeschlagene Named-Pipe-Lösung zu verwenden.

[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

Da crondas Senden von Benachrichtigungen anscheinend nicht unterstützt wird (zumindest nicht direkt), gibt es ein anderes Benachrichtigungssystem, das cronbenutzerfreundlicher ist, als ich es kann?

nur jemand
quelle
Dies sollte soweit ich sehen kann funktionieren. Fügen Sie &>>/tmp/crontestder Benachrichtigungssendezeile ein hinzu und prüfen Sie, ob notify-sendFehlermeldungen angezeigt werden.
Graeme
Haben Sie aus Neugier meine Lösung ausprobiert? Es scheint viel einfacher zu sein und hat perfekt auf meinem Debian funktioniert. Ich
frage
@terdon Ich habe Ihre Lösung ausprobiert (nur ein kurzer Test) und es scheint auf meinem Debian-System zu funktionieren. Ich würde gerne wissen, ob es allgemein anwendbar ist, da es in der Tat einfacher ist.
Marco
@Marco Ich bin auf LMDE (hauptsächlich Debian-Test) und benutze Cinnamon als DE. Ich kann dir nicht sagen, ob es darüber hinaus funktioniert.
Terdon
@ Marco & Terdon: Ubuntu-Jungs sind dazu in der Lage: ubuntuforums.org/showthread.php?t=1727148
justsomeone

Antworten:

29

Sie müssen die DBUS_SESSION_BUS_ADDRESSVariable einstellen . Standardmäßig hat cron keinen Zugriff auf die Variable. Um dies zu beheben, platzieren Sie das folgende Skript irgendwo und rufen Sie es auf, wenn sich der Benutzer anmeldet, zum Beispiel mit awesome und der run_onceim Wiki erwähnten Funktion. Jede Methode ist geeignet, da es nicht schadet, wenn die Funktion häufiger als erforderlich aufgerufen wird.

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

Dadurch wird eine Datei erstellt, die die erforderliche Dbus-Umgebungsvariable enthält. Dann importieren Sie in dem von cron aufgerufenen Skript die Variable, indem Sie das Skript aufrufen:

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

Hier ist eine Antwort, die denselben Mechanismus verwendet.

Marco
quelle
1
Freut mich zu sehen, dass ich fast der Lösung nahe war. Danke Marco, das ist ordentlich!
Justsomeone
Großartig, ich habe Ihre Antwort erneut verwendet und hier einige detailliertere Anweisungen hinzugefügt: askubuntu.com/a/537721/34298
rubo77
Wäre das nicht ein Sicherheitsrisiko? security.stackexchange.com/questions/71019/…
rubo77
@Gilles Wie kannst du das in einer Zeile machen, wie du es im Chat erwähnt
Rubo77
Ich habe so viele andere Antworten ohne DBUS auf Ubuntu 15.10 ausprobiert und nichts hat funktioniert. Das ist einfach und funktioniert einwandfrei.
Bastian
16

Sie müssen die Variablen in der Crontab selbst einstellen:

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

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

Nicht sudonötig, zumindest nicht auf meinem System.

terdon
quelle
Danke terdon für deine Zeit. Dies scheint eine einfache Lösung zu sein. Leider hat das bei mir nicht
geklappt
@justsomeone huh, OK, könnte dann von der Desktop-Umgebung abhängen.
Terdon
Ich denke, das hat etwas mit der Distribution oder der Desktop-Umgebung zu tun. Für Ubuntu-Benutzer scheinen die einfachen Lösungen gut zu funktionieren, was ich in Online-Foren gesehen habe.
Justsomeone
@justsomeone Ich bin auf Debian (LMDE) und benutze Cinnamon als DE. Kann etwas damit zu tun haben, wie X gestartet wird oder mit dem von der DE verwendeten Benachrichtigungssystem, keine Ahnung.
Terdon
Bestätigt, dass es unter Ubuntu 14.04 / 14.10 funktioniert. Mit GNOME und Unity.
Jordon Bedwell
8

Der sicherste Weg, um auf X-Sitzungen bezogene Umgebungsvariablen abzurufen, besteht darin, sie aus der Umgebung eines Prozesses des an X angemeldeten Benutzers abzurufen. Es scheint ein Problem für mich zu sein (unter 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"

Dies sendet eine Nachricht an den ersten X-Benutzer, den es findet, obwohl Sie eine Schleife hinzufügen können, um sie an alle Benutzer zu senden.

Aktualisieren

Es scheint, dass Aktualisierungen des utmp-Formats dazu führen who, dass eine Anzeige anstelle eines tty in der zweiten Spalte gedruckt wird. Das macht die Sache tatsächlich einfacher, zuvor wurde nur die Anzeige im Kommentar am Ende gedruckt, und ich entschied, dass dies nicht sicher war, um die ursprüngliche Antwort zu erhalten. Wenn dies der Fall ist, versuchen Sie Folgendes:

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
quelle
Dies funktioniert bei Trusty nicht, da der who_lineBefehl keine tty enthält . Die Ausgabe sieht aus wie me :0 2015-09-23 10:40 ? 17234.
blujay
1
@blujay, aktualisiert.
Graeme
Danke, das funktioniert. Wie ich jedoch in einer separaten Antwort gepostet habe, gibt es eine noch einfachere Lösung.
blujay
@blujay ja, das war ein versuch einer portablen antwort. Ich bin mir nicht sicher, ob dies wirklich möglich ist, aber in den meisten Fällen sollte es trotzdem funktionieren.
Graeme
2

Dieser Einzeiler arbeitete für mich in Manjaro mit 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.'

Ohne die sehr hässliche DBUS_blah_blah geht es gar nicht. Ich fand auch journalctl -xb -u croniehilfreich. Ich bin noch nicht mit Cronie vertraut, habe aber meine "crontab" as erstellt /etc/cron.d/mycronjobsund bin mir nicht sicher, ob dieser Dateiname erforderlich ist oder ob er nur alles im Verzeichnis cron.d liest.

Ich habe die Lösung hier gefunden: https://wiki.archlinux.org/index.php/Desktop_notifications

PJ Brunet
quelle
2

Ich benutze i3 unter Ubuntu 18.04. Mein Weg, dies zu lösen, ist:

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

Herr Goferito
quelle
1

Dies reicht aus, um das Senden von Benachrichtigungen in einem Cronjob auf Ubuntu Trusty für mich zu erledigen:

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

Es exportiert einfach das DISPLAYfür den Benutzer, unter dem der Cronjob ausgeführt wird. Es funktioniert bei mir ohne Einstellung XAUTHORITYoder DBUS_SESSION_BUS_ADDRESS.

blujay
quelle
1
Funktioniert auch unter Ubuntu 16.04. Ich habe tatsächlich cron ein Perl-Skript gestartet, welches system () ein bash-Skript ist, welches ein anderes Perl-Skript startet, welches ein System ausführt ("notify-send ..."). Durch das Hinzufügen des Befehls export zum Bash-Skript wurde die Umgebung für dieses Skript geändert, das dann vom letzten Perl-Skript geerbt und dem System zur Verfügung gestellt wurde ("notify-send ..."). Gute Entdeckung, blujay!
Tim
1

Für diejenigen unter Linux, die sich mit der Installation von Python-Paketen wohl fühlen, habe ich gerade ein Benachrichtigungs-Send-Headless- Programm veröffentlicht, das für mich gut funktioniert. Es sucht /procnach den erforderlichen Benutzernamen- und Umgebungsvariablen und wird dann notify-sendmit diesen Variablen ausgeführt (wird verwendet sudo, um bei Bedarf zum erforderlichen Benutzer zu wechseln).

xolox
quelle
1

Sie können auch ein Skript erstellen:

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

Dann starte es mit sudo. Da jedoch crontab -ealle Befehle mit dem Benutzer ausgeführt werden, der sie erstellt hat, sollte beim Aufrufen ohne Folgendes ausreichen sudo:

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

Zumindest für mich. Es scheint alles von der Umgebungskonfiguration abhängig zu sein.

user1112789
quelle
0

Ich benutze dieses Skript in Cron, um MPD zu posten, das jetzt stündlich auf Twitter abgespielt wird

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

ähnliches Skript mit 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

Möglicherweise treten Probleme auf, da KDE seinen eigenen notify-deamon IIRC verwendet.

Cirrus
quelle
0

Für was es wert ist ....

Ich musste auf Debian Jessie ALLE der folgenden Befehle verwenden, um dies zum Laufen zu bringen ...

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

Das Weglassen eines dieser Punkte führte dazu, dass es nicht mehr funktionierte.

BenJ
quelle
In dieser letzten Zeile wird nichts wie hier beschrieben ausgeführt, da *-0in Ihrem session-busVerzeichnis keine Datei mit einem wörtlichen Namen vorhanden ist . Das hättest du wohl gemeint source "$HOME"/.dbus/session-bus/*-0.
Roaima
0

Sudo benutzen:

sudo -u $currentxuser notify-send $message

Tipp:

Mit diesem Befehl können wir den aktuellen x-Benutzer ermitteln

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

Und dazu...

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

Gut zu wissen :

Cron, das unter root ausgeführt wird, hat keinen Zugriff auf x, daher werden nicht alle GUI-Befehle angezeigt. Eine einfache Lösung besteht darin, root für den aktuellen x-Benutzer mit diesem Befehl zu einem autorisierten x-Benutzer hinzuzufügen

aus der x User Shell

xhost local:root

oder

sudo -u $currentxuser xhost local:root
intika
quelle
-1

Hier ist ein weniger komplexes Skript als das, was Graeme bereitgestellt hat. Sein Drehbuch hat bei mir nicht funktioniert, $who_linewar immer leer. Mein Skript verschwendet nicht so viel Zeit damit, einen Prozess zu finden. Stattdessen wird einfach alles versucht und der zuletzt gefundene nützliche Wert ausgewählt. Ich verwende xubuntu 14.04 und habe einige lxc-Container, die diese Art von Skripten wahrscheinlich verwirren.

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
quelle
Dies funktioniert bei Trusty nicht, da die Umgebung des Xorg-Prozesses keine hat DBUS_SESSION_BUS_ADDRESS. Ich kann es aus meinen Muscheln beziehen, aber nicht aus dem Xorg-Prozess.
blujay