Exécuter le script lorsque le moniteur est connecté

13

J'essaie d'exécuter un script situé dans usr/local/bin/lorsque je connecte un moniteur externe à mon ordinateur portable. J'ai essayé d'ajouter une nouvelle udevrègle mais cela n'a pas fonctionné. J'ai créé un nouveau fichier /etc/udev/rules.dappelé vga-monitor-connect.rules. Le contenu du dossier a été

SUBSYSTEM=="drm", ACTION=="change", RUN+="/usr/local/bin/panel-fix"

J'ai pris la ligne de cette réponse

Après avoir cherché en ligne, j'ai également essayé la règle suivante

KERNEL=="card0", SUBSYSTEM=="drm", ENV{DISPLAY}=":0", ENV{XAUTHORITY}="/home/rumesh/.Xauthority", RUN+="/usr/local/bin/panel-fix"

Mais cela n'a pas fonctionné non plus.

J'ai exécuté le script manuellement et je peux confirmer qu'il fonctionne donc ce n'est pas un problème avec mon script.

Je tiens également à préciser que je ne sais pas grand-chose, udevdonc la règle que j'ai utilisée peut être erronée. Si quelqu'un connaît la règle appropriée pour mon problème, veuillez laisser une réponse.

Ma carte graphique est un chipset intégré Intel GM965

Rumesh
la source
Voulez-vous spécifiquement le faire comme ça? Un minuscule script d'arrière-plan serait un morceau de gâteau.
Jacob Vlijm
@JacobVlijm Comment serait le script? Pourriez-vous montrer un exemple.
Rumesh
Est-ce uniquement pour se déclencher si (n'importe quel) deuxième moniteur est connecté?
Jacob Vlijm
Oui, je dois exécuter mon propre script lorsque j'attache le deuxième moniteur
Rumesh
1
Pas de problème, prenez votre temps et répondez quand vous le pouvez :)
Rumesh

Réponses:

7

Une autre façon d'exécuter une commande si un écran est connecté ou déconnecté

Une solution alternative serait d'exécuter un minuscule script d'arrière-plan. En exécutant le script ci-dessous en arrière-plan, je n'ai pu mesurer aucune augmentation de la charge du processeur.

C'est un moyen facile et pratique d'exécuter un script ou toute autre commande, lorsqu'un deuxième écran est connecté ou déconnecté.

L'exemple de script

  • Vérifie simplement toutes les cinq secondes combien de fois la chaîne "connecté" apparaît dans la sortie de la commande xrandr(attention à l'espace après "connecté" pour éviter les fausses correspondances avec "déconnecté"). Chaque occurrence représente un écran connecté.
  • Si le nombre d'occurrences change, un écran était connecté ou déconnecté. Le changement est "remarqué" par le script et peut être connecté à une commande, que vous pouvez définir dans la section head du script.

Le script

#!/usr/bin/env python3
import subprocess
import time

#--- set both commands (connect / disconnect) below
connect_command = "gedit"
disconnect_command = ""
#---

def get(cmd): return subprocess.check_output(cmd).decode("utf-8")
# - to count the occurrenc of " connected "
def count_screens(xr): return xr.count(" connected ")
# - to run the connect / disconnect command(s)
def run_command(cmd): subprocess.Popen(["/bin/bash", "-c", cmd])

# first count
xr1 = None

while True:
    time.sleep(5)
    # second count
    xr2 = count_screens(get(["xrandr"]))
    # check if there is a change in the screen state
    if xr2 != xr1:
        print("change")
        if xr2 == 2:

            # command to run if connected (two screens)
            run_command(connect_command)
        elif xr2 == 1:
            # command to run if disconnected (one screen)
            # uncomment run_command(disconnect_command) to enable, then also comment out pass
            pass
            # run_command(disconnect_command)
    # set the second count as initial state for the next loop
    xr1 = xr2

Comment utiliser

  1. Copiez le script dans un fichier vide, enregistrez-le sous connect_screen.py
  2. Dans la section head, définissez la commande à exécuter sur connect (je mets "gedit" à titre d'exemple, faites attention aux guillemets). Il est également possible de définir une commande de déconnexion également. Sinon, laissez disconnect_command = ""tel quel.

    Si vous utilisez une commande de déconnexion, décommentez également la ligne:

    run_command(disconnect_command)

    et commentez la ligne:

    pass

    Comme indiqué dans le script

  3. Testez le script à partir d'un terminal, connectez votre écran et voyez si tout fonctionne bien.
  4. Si tout fonctionne bien, ajoutez-le à vos applications de démarrage: Dash> Startup Applications> Add the command:

    /bin/bash -c "sleep 15&&python3 /path/to/connect_screen.py"

    Il sleep 15s'agit de faire démarrer le bureau complètement avant que le script ne démarre. Juste pour en être certain.


ÉDITER

Comment exécuter le script au démarrage de manière "intelligente".

La pause de sleep 15devrait fonctionner en général, mais comme le temps de démarrage diffère selon le système, il peut falloir quelques essais pour trouver le bon temps de pause. Avec un petit ajout, le script devient «intelligent» et attend que la xrandrcommande réussisse avant de démarrer le script réel. Si vous utilisez la version ci-dessous, il vous suffit d'ajouter la commande:

python3 /path/to/connect_screen.py

à vos applications de démarrage. L'utilisation ultérieure est exactement la même que la version ci-dessus.

Le script

#!/usr/bin/env python3
import subprocess
import time

#--- set both commands (connect / disconnect) below
connect_command = "gedit"
disconnect_command = ""
#---

while True:
    time.sleep(5)
    try:
        subprocess.Popen(["xrandr"])
    except:
        pass
    else:
        break


# function to get the output of xrandr
def get(cmd): return subprocess.check_output(cmd).decode("utf-8")
# - to count the occurrenc of " connected "
def count_screens(xr): return xr.count(" connected ")
# - to run the connect / disconnect command(s)
def run_command(cmd): subprocess.Popen(["/bin/bash", "-c", cmd])

# first count
xr1 = None

while True:
    time.sleep(5)
    # second count
    xr2 = count_screens(get(["xrandr"]))
    # check if there is a change in the screen state
    if xr2 != xr1:
        if xr2 == 2:
            # command to run if connected (two screens)
            run_command(connect_command)
        elif xr2 == 1:
            # command to run if disconnected (one screen)
            # uncomment run_command(disconnect_command) to enable, then also comment out pass
            pass
            # run_command(disconnect_command)
    # set the second count as initial state for the next loop
    xr1 = xr2
Jacob Vlijm
la source
4
Vous donnez un vélo à un homme avec une voiture rapide cassée au lieu de réparer la voiture ...
solsTiCe
1
@solsTiCe 1. Ce n'est pas un vélo, mais une option parfaitement fonctionnelle. Gardez à l'esprit que toutes les actions déclenchées par un avertissement, un événement ou toute autre action entraînée par l'exécution d'une sorte de boucle sont en quelque sorte. 2. Je vous suggère alors de réparer la Ferrari.
Jacob Vlijm
1
@Rumesh exécuter des scripts $PATH avec l' extension de fichier et avec la langue précédente est une solution pas si élégante. La question est de savoir si vous souhaitez l'exécuter pour un utilisateur ou pour tous les utilisateurs. Dans le dernier cas, une autre configuration que celle suggérée est nécessaire, mais de préférence pas celle que vous proposez :). Cela sleep 15peut ne pas être suffisant, mais une solution plus élégante pourrait être de rendre la coupure "intelligente", laissez le script essayer / sauf de démarrer jusqu'à ce que la procédure de démarrage soit "prête" pour l'exécution du script. Ce serait un ajout mineur. Faites le moi savoir.
Jacob Vlijm
1
Les scripts @Rumesh $PATHne doivent pas avoir d'extension de langage et être exécutables, donc exécutez-les sans python3voir lintian.debian.org/tags/script-with-language-extension.html
Jacob Vlijm
1
@JacobVlijm Je l'avais déjà défini pour être exécutable auparavant, donc je suppose que je peux simplement l'utiliserconnect_screen
Rumesh
2

Ceci peut également être réalisé à partir du script bash suivant.

#!/usr/bin/env bash

xrandr=$(xrandr)

con_monitors=$(echo $xrandr | grep -c " connected ")

    if [[ $con_monitors -gt 1 ]]; then
        # All the layouts are saved in "screenlayout" folder.
        # eg cmd. xrandr --output HDMI-1 --mode 2560x1440 --pos 0x0 --rotate normal --output DP-1 --off --output eDP-1 --primary --mode 1920x1080 --pos 283x1440 --rotate normal --output DP-2 --off
        for layout in ~/.screenlayout/*.sh; do
            ./layout
        done
    fi
Bhaskar KC
la source