Executar script quando o monitor estiver conectado

12

Estou tentando executar um script localizado usr/local/bin/quando conecto um monitor externo ao meu laptop. Eu tentei adicionar uma nova udevregra, mas isso não funcionou. Eu criei um novo arquivo no /etc/udev/rules.dchamado vga-monitor-connect.rules. O conteúdo do arquivo foi

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

Eu peguei a linha desta resposta

Depois de pesquisar online, também tentei a seguinte regra

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

No entanto, isso também não funcionou.

Executei o script manualmente e posso confirmar que funciona, para que não haja problemas com o meu script.

Também quero deixar claro que não sei muito sobre udeva regra que usei pode estar errada. Se alguém souber a regra adequada para o meu problema, deixe uma resposta.

Minha placa de vídeo é um chipset Intel GM965 integrado

Rumesh
fonte
Deseja especificamente fazê-lo assim? Um pequeno script de fundo seria um pedaço de bolo.
Jacob Vlijm
@JacobVlijm Como seria o script? Você poderia mostrar um exemplo?
Rumesh
É apenas para acionar se (algum) segundo monitor estiver conectado?
Jacob Vlijm
Sim eu preciso para executar o meu próprio roteiro quando eu anexar o segundo monitor
Rumesh
1
Não tem problema, tomar o seu tempo e responder quando você pode :)
Rumesh

Respostas:

7

Uma maneira alternativa de executar um comando se uma tela estiver conectada ou desconectada

Uma solução alternativa seria executar um pequeno script em segundo plano. Executando o script abaixo em segundo plano, não pude medir nenhum aumento na carga do processador.

É uma maneira fácil e conveniente de executar um script ou qualquer outro comando sempre que uma segunda tela for conectada ou desconectada.

O script de exemplo

  • Simplesmente verifica a cada cinco segundos quantas vezes a string "conectado" ocorre na saída do comando xrandr(lembre-se do espaço após "conectado" para evitar correspondências falsas com "desconectado"). Cada ocorrência representa uma tela conectada.
  • Se o número de ocorrências mudar, uma tela foi conectada ou desconectada. A alteração é "notada" pelo script e pode ser conectada a um comando, você pode definir na seção principal do script.

O 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

Como usar

  1. Copie o script em um arquivo vazio, salve-o como connect_screen.py
  2. Na seção principal, defina o comando para executar no connect (defino "gedit" como exemplo, lembre-se das aspas). Também é possível definir um comando para desconectar, da mesma forma. Caso disconnect_command = ""contrário, deixe como está.

    Se você usar um comando de desconexão, descomente também a linha:

    run_command(disconnect_command)

    e comente a linha:

    pass

    Conforme indicado no script

  3. Teste o script a partir de um terminal, conecte sua tela e veja se tudo funciona bem.
  4. Se tudo funcionar bem, adicione-o aos aplicativos de inicialização: Dash> Startup Applications> Add the command:

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

    O sleep 15objetivo é fazer a área de trabalho inicializar completamente antes que o script comece a ser executado. Apenas para ter certeza.


EDITAR

Como executar o script na inicialização de uma maneira "inteligente".

A interrupção de sleep 15deve funcionar em geral, mas como o tempo de inicialização varia de acordo com o sistema, pode levar algumas experiências para encontrar a hora certa. Com uma pequena adição, o script se torna "inteligente" e aguarda o xrandrêxito do comando antes de iniciar o script real. Se você usa a versão abaixo, você só precisa adicionar o comando:

python3 /path/to/connect_screen.py

aos aplicativos de inicialização. O uso adicional é exatamente o mesmo da versão acima.

O 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
fonte
4
Você está dando uma bicicleta para um homem com um carro rápido quebrado em vez de fixar o carro ...
solstício de
1
@solsTiCe 1. Esta não é uma bicicleta, mas uma opção perfeitamente funcional. Lembre-se de que todas as ações orientadas por notificação, evento ou qualquer outra ação existente existe, de alguma forma, executando algum tipo de loop. 2. Sugiro que você conserte a Ferrari então.
Jacob Vlijm
1
O @Rumesh executando scripts $PATH com extensão de arquivo e com o idioma anterior é uma solução não tão elegante. A questão é se você deseja executá-lo para um usuário ou para todos os usuários. No último caso, é necessária outra configuração além da sugerida, mas de preferência não a que você está sugerindo :). Isso sleep 15pode não ser suficiente, mas uma solução mais elegante pode ser tornar a quebra "inteligente", deixe o script tentar / exceto iniciar até que o procedimento de inicialização esteja "pronto" para a execução do script. Seria uma adição menor. Avise-se me.
Jacob Vlijm 6/06/2015
1
Scripts de @Rumesh em $PATHnão deveriam ter extensão da linguagem e ser executável, então corra sem python3ver lintian.debian.org/tags/script-with-language-extension.html
Jacob Vlijm
1
@JacobVlijm eu já tinha configurá-lo para ser executável antes, então eu acho que pode apenas usarconnect_screen
Rumesh
2

Isso pode ser alcançado seguindo o script bash também.

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