Ejecutar script cuando el monitor está conectado

12

Estoy tratando de ejecutar un script ubicado usr/local/bin/cuando conecto un monitor externo a mi computadora portátil. Intenté agregar una nueva udevregla, pero no funcionó. Creé un nuevo archivo en /etc/udev/rules.dllamado vga-monitor-connect.rules. El contenido del archivo fue

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

Tomé la línea de esta respuesta

Después de buscar en línea también probé la siguiente regla

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

Sin embargo, esto tampoco funcionó.

He ejecutado el script manualmente y puedo confirmar que funciona para que no sea un problema con mi script.

También quiero dejar en claro que no sé mucho, por udevlo que la regla que he usado puede estar equivocada. Si alguien conoce la regla adecuada para mi problema, deje una respuesta.

Mi tarjeta gráfica es un chipset integrado Intel GM965

Rumesh
fuente
¿Quieres específicamente hacerlo así? Un pequeño guión de fondo sería pan comido.
Jacob Vlijm
@JacobVlijm ¿Cómo sería el guión? ¿Podrías mostrar un ejemplo?
Rumesh
¿Es solo para disparar si (cualquier) segundo monitor está conectado?
Jacob Vlijm
Sí, necesito ejecutar mi propio script cuando
conecto
1
No hay problema, tómese su tiempo y responda cuando pueda :)
Rumesh

Respuestas:

7

Una forma alternativa de ejecutar un comando si una pantalla está conectada o desconectada

Una solución alternativa sería ejecutar un pequeño script de fondo. Al ejecutar el siguiente script en segundo plano, no pude medir ningún aumento en la carga del procesador.

Es una manera fácil y conveniente de ejecutar un script, o cualquier otro comando, siempre que una segunda pantalla esté conectada o desconectada.

El guion de ejemplo

  • Simplemente comprueba cada cinco segundos cuántas veces se produce la cadena "conectado" en la salida del comando xrandr(tenga en cuenta el espacio después de "conectado" para evitar coincidencias falsas con "desconectado"). Cada aparición representa una pantalla conectada.
  • Si el número de ocurrencias cambia, se conectó o desconectó una pantalla. El cambio es "notado" por el script y puede conectarse a un comando, puede configurarlo en la sección principal del script.

La secuencia de comandos

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

Cómo utilizar

  1. Copie el script en un archivo vacío, guárdelo como connect_screen.py
  2. En la sección de cabecera, configure el comando para que se ejecute en connect (configuro "gedit" como ejemplo, tenga en cuenta las comillas). También es posible establecer un comando de desconexión, de la misma manera. De lo contrario deja disconnect_command = ""como está.

    Si utiliza un comando de desconexión, también elimine el comentario de la línea:

    run_command(disconnect_command)

    y comentar la línea:

    pass

    Como se indica en el guión

  3. Pruebe a ejecutar el script desde una terminal, conecte su pantalla y vea si todo funciona bien.
  4. Si todo funciona bien, agréguelo a sus aplicaciones de inicio: Tablero> Aplicaciones de inicio> Agregue el comando:

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

    El sleep 15objetivo es hacer que el escritorio se inicie completamente antes de que el script comience a ejecutarse. Solo por asegurar.


EDITAR

Cómo ejecutar el script al inicio de una manera "inteligente".

El descanso de sleep 15debería funcionar en general, pero dado que el tiempo de inicio difiere según el sistema, puede llevar un poco de experimentación encontrar el tiempo de descanso correcto. Con una pequeña adición, el script se vuelve "inteligente" y espera a que el xrandrcomando sea exitoso antes de iniciar el script real. Si usa la versión a continuación, solo necesita agregar el comando:

python3 /path/to/connect_screen.py

a sus aplicaciones de inicio. El uso adicional es exactamente el mismo que la versión anterior.

La secuencia de comandos

#!/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
fuente
44
Usted está dando una bicicleta a un hombre con un coche rápido roto en lugar de arreglar el coche ...
solsticio de
1
@solsTiCe 1. Esta no es una bicicleta, sino una opción perfectamente funcional. Tenga en cuenta que todas las acciones de notificación, evento o lo que sea que exista de ejecutar algún tipo de bucle de alguna manera. 2. Te sugiero que arregles el Ferrari entonces.
Jacob Vlijm
1
@Rumesh ejecuta scripts $PATH con extensión de archivo y con el lenguaje anterior es una solución no tan elegante. La pregunta es si desea ejecutarlo para un usuario o para todos los usuarios. En el último caso, se necesita una configuración diferente a la sugerida, pero preferiblemente no la que está sugiriendo :). Es sleep 15posible que esto no sea suficiente, pero una solución más elegante podría ser hacer el descanso "inteligente", dejar que el script intente / excepto que se inicie hasta que el procedimiento de inicio esté "listo" para que se ejecute el script. Sería una adición menor. Házmelo saber.
Jacob Vlijm
1
Los scripts de @Rumesh $PATHno deberían tener extensión de idioma y ser ejecutables, por lo que debe ejecutarse sin python3ver lintian.debian.org/tags/script-with-language-extension.html
Jacob Vlijm
1
@JacobVlijm Ya lo había configurado para que fuera ejecutable antes, así que supongo que puedo usarloconnect_screen
Rumesh
2

Esto también se puede lograr siguiendo el script bash.

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