Benachrichtigungen mit notify-send als root und per cron
Mein Backup-Skript (es dumpt lokale Datenbanken, unterstützt zig Hooks, sichert mit Restic/ Duplicity) kennt einen neuen Trick.
Auf meinem Linux-Desktop wollte ich Popup-Informationen zu einem im Hintergrund (Cronjob als root) gestarteten Skript sehen.
Und wie geht das?
Eine gängige Lösung ist notify-send (aus dem Paket libnotify).
$ notify-send --help Usage: notify-send [OPTION?] <SUMMARY> [BODY] - create a notification Help Options: -?, --help Show help options Application Options: -u, --urgency=LEVEL Specifies the urgency level (low, normal, critical). -t, --expire-time=TIME Specifies the timeout in milliseconds at which to expire the notification. -a, --app-name=APP_NAME Specifies the app name for the icon -i, --icon=ICON Specifies an icon filename or stock icon to display. -c, --category=TYPE[,TYPE...] Specifies the notification category. -e, --transient Create a transient notification -h, --hint=TYPE:NAME:VALUE Specifies basic extra data to pass. Valid types are boolean, int, double, string, byte and variant. -p, --print-id Print the notification ID. -r, --replace-id=REPLACE_ID The ID of the notification to replace. -w, --wait Wait for the notification to be closed before exiting. -A, --action=[NAME=]Text... Specifies the actions to display to the user. Implies --wait to wait for user input. May be set multiple times. The name of the action is output to stdout. If NAME is not specified, the numerical index of the option is used (starting with 0). -v, --version Version of the package.
Das funktioniert problemlos im Kontext des aktuell eingeloggten Benutzers mit einer X-Session.
Aber mit sudo oder als Cronjob als root?
Aber eines nach dem Anderen.
Wenn ich ein Skript mit sudo starte, dann enthält die Umgebungsvariable SUDO_USER denjenigen Benutzer, der das sudo ausgelöst hat. Das Skript läuft dann als User root. Das notify-send soll aber nicht auf einer X-Session des root Users etwas enblenden, sondern einem anderen unprivilegierten Benutzer. Hier kommt die Variable DBUS_SESSION_BUS_ADDRESS ins Spiel. Wenn man die UID des Benutzers kennt, kann man es sich zusammensetzen. Diese bekommt man mit id -u [Benutzername] … und der Benutzername ist ja in SUDO_USER.
Snippet:
if [ -n "$SUDO_USER" ]; then export DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/$(id -u $SUDO_USER)/bus fi
Mit jenem Snippet kann man im selben Skript auslösen
su "$SUDO_USER" -c "notify-send 'Titel' 'Mein Nachrichtentext'"
und es kommt bei … genau: “meinem” Desktop an und nicht bei root. Wunderbar!
Jetzt ist da noch die Sache mit dem Cronjob als root. Hier ist ja kein sudo. Aber das ist gar banaler als man denkt: man setzt einfach die Variable SUDO_USER im Environment - also vor den Deinitionen der Zeitangaben und Aufrufe:
$cat /etc/cron.d/client-backup SUDO_USER=axel 17 * * * * root /usr/local/bin/cronwrapper.sh 1440 /opt/imlbackup/client/backup.sh 'iml-backup'
Feintuning:
ein Simples notify-send “Titel” “Mein Nachrichtentext” verschwindet nach ein paar Sekunden. Wenn ein Fehler auftritt, dann möchte ich die Meldung sehen, lesen und proaktiv verschwinden lassen. Genau das erledigt der Parameter –urgency für uns
notify-send –urgency=critical “Fehler” “Da ging etwas schief :-/”
Hier noch ein kompletteres Bash Snippet:
if [ -n "$SUDO_USER" ]; then export DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/$(id -u $SUDO_USER)/bus fi (...) # show a desktop notification using notify-send # param string summary (aka title) # param string message text # paran integer optional: exitcode; if set it adds a prefix OK or ERRROR on summary and sets urgency on error function notify(){ local _summary="$1" local _body="$( date +%H:%M:%S ) $2" local _rc="$3" local _urgency="normal" if [ -n "$DBUS_SESSION_BUS_ADDRESS" ]; then if [ -n "$_rc" ]; then if [ "$_rc" = "0" ]; then _summary="OK: ${_summary}" else _summary="ERROR: ${_summary}" _urgency="critical" fi fi su "$SUDO_USER" -c "notify-send --urgency=${_urgency} '${_summary}' '${_body}'" fi }
Timeshift und Prozentrechnung
Timeshift speichert Snapshots eines Linux-Systems. Es kann sich u.a. als Hook in den Paketmanager einklinken und vor jedem Update einen Snapshot anlegen, um im Falle eines Nicht-Funktionierens zurückzurollen.
- Wenn die Snapshots auch auf der Systemdisk abgelegt werden, wird das Grub-Menü um die Auswahl der letzten Snapshots erweitert.
- Falls nicht, wird ein Rsync zum Sichern des Snapshots bemüht. Wenn man sein Linux booten kann (also notfalls von USB Stick), kann man Timeshift auch so einen anderen Stand wiederherstellen lassen.
Einen kleinen Schönheitsfehler gibt es aber. Im CLI Modus gibt Timeshift eine Fortschrittsinfo aus. Dumm nur, wenn es bei 100% gar nicht fertig ist.
Naja, ich kann darüber hinwegsehen. Wenn der Moment kommt, wo man mal ein Backup braucht, ist man froh um jeden verfügbaren Zwischenstand von so vielen Informationen wie möglich.
Ich fahre auf meinen Linux-PCs mit einer Kombination von Timeshift und Restic (IML Backup). Aber man will ja selbst keinen interaktiven Aufwand und sich nicht darum kümmern. Aber ich weiss, dass ich mich auf das Funktionieren beider Varianten in deren Kombination mit Snapshots und Datei-Backups verlassen kann.
Weiterführende Links