Je travaille dans un script pour modifier la sortie audio lorsque vous (dés) connectez un écran HDMI/un téléviseur. Fondamentalement, il utilise UDEV pour vérifier tout changement dans la connexion et agit en conséquence.
Tout fonctionne bien, sauf une chose: je ne peux pas utiliser notify-send
pour avertir du changement. J'utilise le code suivant (output
n'est qu'un wrapper pour subprocess.check_output
):
output("Sudo -u {0} notify-send \"{1}\" \"{2}\"".format(user, title, message))
mais je ne reçois aucune notification du tout.
Ce qui est vraiment étrange, c’est que si je lance hdmi_sound_toggle
(en tant qu’utilisateur normal ou avec Sudo
), tout fonctionne parfaitement!
Alors, quel pourrait être le problème ici? Il existe un meilleur moyen de présenter une notification qu'avec notify-send
?
Le notify-send
ne parvient pas à afficher des notifications sur l'écran d'un utilisateur lorsqu'il est appelé à partir d'un script exécuté par root ou par un autre utilisateur.
Tu devrais utiliser:
output("export DISPLAY=:0; Sudo -u {0} notify-send \"{1}\" \"{2}\"".format(user, title, message))
Alors, utilisez:
export DISPLAY=:0
Normalement, un utilisateur est sur l'affichage :0
, mais pour être sûr, vous pouvez trouver l'affichage sur lequel un utilisateur est activé à l'aide de la commande who
comme suit:
who | grep -m1 ^username.*\( | awk '{print $5}' | sed 's/[(|)]//g'
Cela a fonctionné pour moi dans ce script .
Voir aussi: Puis-je lancer un programme graphique sur le bureau d'un autre utilisateur en tant que root?
Avez-vous besoin d'appeler avec sudo? Cela pourrait résoudre le problème.
Alternativement, j’ai trouvé que j’avais besoin de DISPLAY=:0
et de XAUTHORITY=/home/<user_name>/.Xauthority
pour pouvoir fonctionner lorsqu’elle s’exécute en tant que root (à partir d’un service systemd dans ce cas - défini avec Environment=...
).
Je recherchais un moyen cohérent de notifier tous les utilisateurs de X (en tant que root) et mes recherches (portant sur de nombreux endroits sur le réseau) indiquaient que, même s'il était possible d'utiliser notify-send de cette manière, il était nécessaire d'utiliser un script pour trouver DBUS. les informations de session et/ou les affichages en cours d'utilisation et/ou les noms et emplacements de fichiers Xauthority, et même dans certains cas, il était parfois impossible de l'obtenir. En résumé, essayer de plier notify-send à votre volonté pour permettre la diffusion à des utilisateurs X s'avérera peu fiable (particulièrement si vous mettez à jour ou changez de distro à un moment donné).
Cependant ... sur mon système, la commande wall
a fonctionné comme un charme et est incroyablement simple à utiliser. Le seul inconvénient est qu'il diffuse également le message à tous les terminaux/consoles de saisie de texte. Si cela ne vous dérange pas, alors wall
pourrait être une option meilleure et plus fiable. Remarque: l'utilisateur qui appelle wall
doit être root
.
La réponse de Radu ne semble pas fonctionner pour moi le 16.04. Plutôt que d’essayer de combattre le problème d’AFFICHAGE qui semble changer de version à l’autre, je le fais de manière légèrement différente. Je crée un script unique appelé de deux manières. Une règle udev appelle le script, envoyant une sorte de sortie vers un canal nommé. Lors de la connexion, le script est également lancé en mode service. Ici, il écoute le tuyau et exécute la commande d'interface graphique souhaitée.
Par exemple, j'aime recevoir les notifications des périphériques de stockage USB au fur et à mesure de leur connexion, et en particulier savoir quel est le chemin d'accès du périphérique et son numéro de série (cela peut paraître étrange, mais j'ai de bonnes raisons). Voici le script que j'utilise pour accomplir ceci.
#!/bin/bash
# script name: usb-notify.sh
# This script needs to be called at logon with "service" parameter
# This script needs to be called by udev on USB insertion with no parameter
pipe="/tmp/usb-notifications"
if [ "$1" == "service" ]; then
# create the named pipe that will help us trigger events from udev
rm "$pipe"
mkfifo "$pipe"
# This outer while loop ensures that we can process multiple triggers
while true
do
# This inner while loop reads individual trigger events
while read info
do
# run some GUI command. Here, I'm running notify-send
notify-send "USB Inserted" "$(echo -e $info)"
done < "$pipe"
done
else
# Here's where udev triggers our event. If you don't need to pass any arguments
# you could just as easily pass an empty line as a trigger for the service.
[ -e "$pipe" ] && echo "Device: $DEVNAME\\\nSN: $ID_SERIAL_SHORT" > "$pipe"
fi
Ce script doit ensuite être appelé de deux manières. Tout d'abord, une règle udev doit être créée pour appeler ce script. Cela peut être fait avec la commande suivante (évidemment vous devriez changer ceci pour regarder quel périphérique devrait déclencher votre script):
echo 'ACTION=="add",KERNEL=="sd?",RUN+="[path-to-script]/usb-notify.sh"' | Sudo tee -a /etc/udev/rules.d/80-USB.rules
Deuxièmement, vous devez appeler ce script avec le paramètre "service" lors de la connexion. Alors, ouvrez le programme "Applications de démarrage" et ajoutez une entrée qui exécute le service "[chemin d'accès à votre script] /usb-notify.sh"
Ce script peut être modifié pour exécuter à peu près n'importe quelle application graphique sur les événements udev. Si vous ne voulez pas que d'autres utilisateurs puissent regarder votre pipe, vous devriez probablement lui attribuer des autorisations restrictives.