Uruchom skrypt, gdy monitor jest podłączony

13

Próbuję uruchomić skrypt znajdujący się usr/local/bin/po podłączeniu monitora zewnętrznego do laptopa. Próbowałem dodać nową udevregułę, ale to nie zadziałało. Utworzyłem nowy plik o /etc/udev/rules.dnazwie vga-monitor-connect.rules. Zawartość pliku to

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

Wyjąłem linię z tej odpowiedzi

Po przeszukaniu Internetu wypróbowałem również następującą zasadę

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

Jednak to też nie działało.

Uruchomiłem skrypt ręcznie i mogę potwierdzić, że działa, więc nie ma problemu z moim skryptem.

Chcę również wyjaśnić, że niewiele wiem, udevwięc zastosowana przeze mnie zasada może być błędna. Jeśli ktoś zna właściwą zasadę dla mojego problemu, proszę zostawić odpowiedź.

Moja karta graficzna to zintegrowany mikroukład Intel GM965

Rumesh
źródło
Czy chcesz to zrobić w ten sposób? Mały skrypt w tle byłby bułką z masłem.
Jacob Vlijm
@JacobVlijm Jak wyglądałby skrypt? Czy możesz pokazać przykład?
Rumesh
Czy można go uruchomić tylko wtedy, gdy podłączony jest (jakikolwiek) drugi monitor?
Jacob Vlijm
Tak, muszę podłączyć własny skrypt, kiedy podłączam drugi monitor
Rumesh
1
Nie ma problemu, nie
spiesz się

Odpowiedzi:

7

Alternatywny sposób uruchomienia polecenia, jeśli ekran jest podłączony lub odłączony

Alternatywnym rozwiązaniem byłoby uruchomienie małego skryptu w tle. Uruchamiając poniższy skrypt w tle, nie mogłem zmierzyć żadnego wzrostu obciążenia procesora.

Jest to łatwy i wygodny sposób na uruchomienie skryptu lub dowolnego innego polecenia, ilekroć drugi ekran jest podłączony lub odłączony.

Przykładowy skrypt

  • Po prostu co pięć sekund sprawdza, ile razy ciąg „podłączony” występuje w danych wyjściowych polecenia xrandr(pamiętaj o spacji po „podłączonym”, aby zapobiec fałszywym dopasowaniom z „odłączony”). Każde wystąpienie reprezentuje podłączony ekran.
  • Jeśli liczba wystąpień ulegnie zmianie, ekran zostanie podłączony lub odłączony. Zmiana jest „zauważana” przez skrypt i może być połączona z poleceniem, które można ustawić w sekcji head skryptu.

Scenariusz

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

Jak używać

  1. Skopiuj skrypt do pustego pliku i zapisz go jako connect_screen.py
  2. W sekcji nagłówka ustaw polecenie, aby było uruchamiane przy połączeniu (ustawiłem „gedit” jako przykład, pamiętaj o cudzysłowach). Możliwe jest również ustawienie polecenia rozłączenia, podobnie. W przeciwnym razie odejdź disconnect_command = "".

    Jeśli użyjesz polecenia rozłączenia, odkomentuj również wiersz:

    run_command(disconnect_command)

    i skomentuj linię:

    pass

    Jak wskazano w skrypcie

  3. Uruchom skrypt z terminalu, podłącz ekran i sprawdź, czy wszystko działa poprawnie.
  4. Jeśli wszystko działa poprawnie, dodaj go do aplikacji startowych: Dash> Aplikacje startowe> Dodaj polecenie:

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

    Ma sleep 15to na celu całkowite uruchomienie pulpitu przed uruchomieniem skryptu. Dla pewności.


EDYTOWAĆ

Jak uruchomić skrypt podczas uruchamiania w „inteligentny” sposób.

Przerwa sleep 15powinna działać ogólnie, ale ponieważ czas uruchamiania różni się w zależności od systemu, znalezienie odpowiedniego czasu przerwy może wymagać eksperymentów. Z niewielkim dodatkiem skrypt staje się „inteligentny” i czeka na xrandrpomyślne wykonanie polecenia, zanim rozpocznie właściwy skrypt. Jeśli używasz poniższej wersji, wystarczy dodać polecenie:

python3 /path/to/connect_screen.py

do aplikacji startowych. Dalsze użycie jest dokładnie takie samo jak w powyższej wersji.

Scenariusz

#!/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
źródło
4
Dajesz rower mężczyźnie z uszkodzonym szybkim samochodem zamiast naprawiać samochód ...
solsTiCe
1
@solsTiCe 1. To nie jest rower, ale idealnie funkcjonalna opcja. Pamiętaj, że istnieją wszystkie działania związane z powiadomieniem, zdarzeniem lub czymkolwiek innym związane z uruchomieniem pętli. 2. Proponuję naprawić Ferrari.
Jacob Vlijm
1
@Rumesh uruchamianie skryptów $PATH z rozszerzeniem pliku oraz z poprzednim językiem jest niezbyt eleganckim rozwiązaniem. Pytanie brzmi, czy chcesz uruchomić go dla jednego użytkownika lub dla wszystkich użytkowników. W ostatnim przypadku potrzebna jest inna konfiguracja niż sugerowana, ale najlepiej nie ta, którą sugerujesz :). sleep 15Może nie być wystarczające, ale bardziej eleganckim rozwiązaniem byłoby, aby przerwa „smart”, niech spróbować skryptu / z wyjątkiem rozruchu, dopóki procedura rozruchu jest „gotowy” za scenariusz do uruchomienia. Mógłby być niewielkim dodatkiem. Daj mi znać.
Jacob Vlijm,
1
Skrypty @Rumesh w $PATHnie powinny mieć rozszerzenia językowego i powinny być wykonywalne, więc uruchom je bez python3zobaczenia lintian.debian.org/tags/script-with-language-extension.html
Jacob Vlijm
1
@JacobVlijm Już wcześniej ustawiłem, aby był wykonywalny, więc chyba mogę po prostu użyćconnect_screen
Rumesh
2

Można to osiągnąć również po wykonaniu skryptu 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
źródło