Запустить скрипт, когда монитор подключен

13

Я пытаюсь запустить сценарий, расположенный usr/local/bin/при подключении внешнего монитора к ноутбуку. Я пытался добавить новое udevправило, но это не сработало. Я создал новый файл в /etc/udev/rules.dAndroid vga-monitor-connect.rules. Содержимое файла было

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

Я взял строку из этого ответа

После поиска в Интернете я также попробовал следующее правило

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

Однако это тоже не сработало.

Я запустил скрипт вручную, и я могу подтвердить, что он работает, так что это не проблема с моим скриптом.

Я также хочу прояснить, что я не знаю много о том, udevпоэтому правило, которое я использовал, может быть неправильным. Если кто-то знает правильное правило для моей проблемы, пожалуйста, оставьте ответ.

Моя видеокарта представляет собой интегрированный чипсет Intel GM965

Rumesh
источник
Вы специально хотите сделать это так? Крошечный фоновый скрипт был бы куском пирога.
Якоб Влийм
@JacobVlijm Каким будет сценарий? Не могли бы вы показать пример.
Румеш
Это только для запуска, если (любой) второй монитор подключен?
Джейкоб Влейм
Да, мне нужно запустить собственный скрипт, когда я присоединяю второй монитор
Rumesh
1
Нет проблем, не торопитесь и ответьте, когда сможете :)
Румеш

Ответы:

7

Альтернативный способ выполнить команду, если экран подключен или отключен

Альтернативным решением было бы запустить крошечный фоновый скрипт. Запустив приведенный ниже сценарий в фоновом режиме, я не смог измерить какое-либо увеличение загрузки процессора.

Это простой и удобный способ запуска скрипта или любой другой команды, когда второй экран подключен или отключен.

Пример сценария

  • Каждые пять секунд просто проверяется, сколько раз строка «подключен» встречается в выходных данных команды xrandr(обратите внимание на пробел после «подключен», чтобы избежать ложных совпадений с «отключен»). Каждое вхождение представляет собой подключенный экран.
  • Если количество вхождений изменяется, экран был подключен или отключен. Изменение «замечено» скриптом и может быть связано с командой, которую вы можете установить в разделе заголовка скрипта.

Сценарий

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

Как пользоваться

  1. Скопируйте скрипт в пустой файл, сохраните его как connect_screen.py
  2. В разделе заголовка установите команду для запуска по соединению (в качестве примера я привел «gedit», обратите внимание на кавычки). Также можно установить команду на отключение, аналогично. Остальное оставь disconnect_command = ""как есть.

    Если вы используете команду рассоединения, также раскомментируйте строку:

    run_command(disconnect_command)

    и закомментируйте строку:

    pass

    Как указано в сценарии

  3. Протестируйте скрипт из терминала, подключите экран и посмотрите, все ли работает нормально.
  4. Если все работает нормально, добавьте его в автозагрузку приложений: Dash> Startup Applications> Add the command:

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

    sleep 15, Чтобы сделать рабочий стол запустить полностью до того , как скрипт начинает работать. Просто чтобы убедиться.


РЕДАКТИРОВАТЬ

Как запустить скрипт при запуске «умным» способом.

Прерывание sleep 15должно работать в целом, но поскольку время запуска отличается в зависимости от системы, может потребоваться некоторое экспериментирование, чтобы найти правильное время перерыва. С небольшим дополнением сценарий становится «умным» и ожидает xrandrуспешного выполнения команды, прежде чем он запустит реальный сценарий. Если вы используете версию ниже, вам нужно только добавить команду:

python3 /path/to/connect_screen.py

в ваши приложения запуска. Дальнейшее использование точно так же, как версия выше.

Сценарий

#!/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
Якоб Влейм
источник
4
Вы даете велосипед человеку с сломанной быстрой машиной вместо того, чтобы
починить
1
@solsTiCe 1. Это не велосипед, а совершенно функциональный вариант. Имейте в виду, что все уведомления, события или другие управляемые действия существуют для запуска какого-то цикла. 2. Тогда я предлагаю вам починить Ferrari.
Джейкоб Влейм
1
@Rumesh запускает сценарии $PATH с расширением файла и с предыдущим языком - не слишком элегантное решение. Вопрос в том, хотите ли вы запустить его для одного пользователя или для всех пользователей. В последнем случае нужна другая настройка, чем предложенная, но желательно не та, которую вы предлагаете :). sleep 15Не может быть достаточно, но более элегантное решение могло бы сделать перерыв «умный», пусть попробовать скрипт / за исключением того, чтобы запустить до тех пор , пока процедура запуска «готова» для сценария для запуска. Было бы незначительным дополнением. Дай мне знать.
Джейкоб Влейм
1
Скрипты @Rumesh в $PATHне должны иметь языкового расширения и быть исполняемыми, поэтому запускайте без python3просмотра lintian.debian.org/tags/script-with-language-extension.html
Джейкоб Влийм
1
@JacobVlijm Я уже установил, что он должен быть исполняемым ранее, поэтому я думаю, что я могу просто использоватьconnect_screen
Rumesh
2

Это может быть достигнуто с помощью следующего скрипта 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
Бхаскар КЦ
источник