Linux извлекает имена мониторов

Ситуация: я использую несколько мониторов, и я хочу получить их имена в bash. В настоящее время я использую Ubuntu 10.04.

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

Есть ли ясный способ сделать это, не сокращая имена из какой-то строки? Четкий способ - прочитать их из файла. Непонятным способом было бы передать вывод xrandr в какую-то функцию, чтобы вырезать из нее имена.

Ответ 1

sudo get-edid не работал у меня. (EDIT: теперь работает на другом компьютере, Lubuntu 14.10, я обвиняю различия в BIOS, но это случайное предположение...)

В любом случае под X, xrandr --verbose печатает блок EDID. Вот быстрый и грязный способ извлечь его и перейти к parse-edid:

#!/bin/bash
xrandr --verbose | perl -ne '
if ((/EDID(_DATA)?:/.../:/) && !/:/) {
  s/^\s+//;
  chomp;
  $hex .= $_;
} elsif ($hex) {
  # Use "|strings" if you dont have read-edid package installed 
  # and just want to see (or grep) the human-readable parts.
  open FH, "|parse-edid"; 
  print FH pack("H*", $hex); 
  $hex = "";
}'

Ответ 2

Вдохновленный ответом Бени, это будет читать данные EDID с помощью xrandr и извлекать имена мониторов в соответствии с EDID, без каких-либо внешних инструментов, таких как parse-edid:

#!/bin/sh
xrandr --verbose | awk '
/[:.]/ && hex {
    sub(/.*000000fc00/, "", hex)
    hex = substr(hex, 0, 26) "0a"
    sub(/0a.*/, "0a", hex)
    print hex
    hex=""
}
hex {
    gsub(/[ \t]+/, "")
    hex = hex $0
}
/EDID.*:/ {
    hex=" "
}' | xxd -r -p

Использует awk, чтобы точно извлекать только имя монитора и лишний мусор из EDID, следовательно, "магические числа", такие как 000000fc00, 26 и 0a. Наконец, используется xxd для преобразования из hex в ASCII, для печати одного имени монитора в строке.

На основе этого решения я сделал удобный script для переключения мониторов, который также можно использовать для простого отображения информации о мониторе:

$ monitor-switch --list
Connected monitors:
# DFP5  HDMI    HT-R391
# DFP7  DVI-I   DELL U2412M

Ответ 3

Проверено на Ubuntu 16.04, 18.04. (Я знаю, что уже слишком поздно, чтобы ответить, но это решение актуально сегодня)

$ sudo apt-get install -y hwinfo
...
$ hwinfo --monitor --short
monitor:
                   SONY TV
                   AUO LCD Monitor

У меня есть два монитора прилагается. Один с ноутбуком, а другой - внешний дисплей. Как только внешний монитор подключен или отключен, эта команда отражает изменение. Вам постоянно нужно опросить. Удаление опции --short дает более подробную информацию.

Вы можете опросить состояние с помощью следующей фоновой работы:

$ while true;
>  do
>   hwinfo --monitor --short;
>   sleep 2;
>  done >> monitor.log &

Цикл while true выполняется бесконечное количество раз. sleep 2 приостанавливает каждую итерацию цикла на 2 секунды. И вывод hwinfo --monitor --short добавляется в monitor.log. Этот файл журнала может предоставить вам историю действий подключаемого модуля и подключаемого модуля монитора.

К вашему сведению: я использую фоновый (daemon) python-скрипт, использующий вышеупомянутую команду (и другие подобные), чтобы определить, выполняет ли кто-то некоторые плагины HW и плагины с системами в компьютерном классе. Если это так, я получаю соответствующие уведомления о том, что кто-то подключил/подключил монитор, мышь или клавиатуру практически в режиме реального времени!

Больше информации о команде hwinfo здесь. Его справочная страница также является хорошим источником.

Ответ 4

Если вы не хотите анализировать вывод xrandr, напишите программу на C с помощью libXrandr, которая получит только то, что вы хотите. Если все, что вы хотите сделать, это запросить информацию, это можно сделать быстро. Прочитайте этот документ.

Если вы хотите получить реальное имя монитора, альтернативой решению @dtmilano является получение свойства EDID монитора с помощью libXrandr, а затем его вручную разобрать и распечатать (прочитать спецификацию EDID).

xrandr исходный код.

Ответ 5

Я знаю, что это грязный способ, но он дает мне некоторое название модели монитора даже лучше, чем sudo get-edid|parse-edid. Он считывает информацию в массивах и выводит ее таким образом, который можно прочитать, как если бы вы читали файл. Вы можете изменить его в соответствии с вашими потребностями.

#!/bin/bash
#
#
#    get-monitors.sh
#
#    Get monitor name and some other properties of connected monitors
#    by investigating the output of xrandr command and EDID data
#    provided by it.
#
#    Copyright (C) 2015,2016 Jarno Suni <[email protected]>
#
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation, either version 3 of the License, or
#    (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with this program. See <http://www.gnu.org/licenses/gpl.html>

set -o nounset
set -o errexit

# EDID format:
# http://en.wikipedia.org/wiki/Extended_Display_Identification_Data#EDID_1.3_data_format
# http://read.pudn.com/downloads110/ebook/456020/E-EDID%20Standard.pdf

declare -r us=';' # separator string;
# If EDID has more than one field with same tag, concatenate them,
# but add this string in between.

declare -r fs=$'\x1f' # Field separator for internal use;
# must be a character that does not occur in data fields.

declare -r invalid_edid_tag='--bad EDID--'
# If base EDID is invalid, don't try to extract information from it,
# but assign this string to the fields.

# Get information in these arrays:
declare -a outs  # Output names
declare -a conns # Connection type names (if available)
declare -a names # Monitor names (but empty for some laptop displays)
declare -a datas # Extra data; may include laptop display brand name
                 # and model name
declare -i no    # number of connected outputs (to be counted)

# xrandr command to use as a source of information:
declare -r xrandr_output_cmd="xrandr --prop"

hex_to_ascii() {
    echo -n "$1" | xxd -r -p
}

ascii_to_hex() {
    echo -n "$1" | xxd -p
}

get_info() {
    no=0
    declare OIFS=$IFS;
    IFS=$fs
    while read -r output conn hexn hexd; do
        outs[no]="${output}"
        conns[no]="${conn}"
        names[no]="$(hex_to_ascii "$hexn")"
        datas[no]="$(hex_to_ascii "$hexd")"
        (( ++no ))
    done < <(eval $xrandr_output_cmd | gawk -v gfs="$fs" '
        function print_fields() {
            print output, conn, hexn, hexd
            conn=""; hexn=""; hexd=""
        }
        function append_hex_field(src_hex,position,app_hex,  n) {
                     n=substr(src_hex,position+10,26)
                     sub(/0a.*/, "", n)
                     # EDID specification says field ends by 0x0a
                     # (\n), if it is shorter than 13 bytes.
                     #sub(/(20)+$/, "", n)
                     # strip whitespace at the end of ascii string
                     if (n && app_hex) return app_hex sp n
                      else return app_hex n
        }
        function get_hex_edid(  hex) {
            getline
            while (/^[ \t]*[[:xdigit:]]+$/) {
                sub(/[ \t]*/, "")
                hex = hex $0
                getline
            }
            return hex
        }
        function valid_edid(hex,  a, sum) {
            if (length(hex)<256) return 0
            for ( a=1; a<=256; a+=2 ) {
                # this requires gawk
                sum+=strtonum("0x" substr(hex,a,2))

                # this requires --non-decimal-data for gawk:
                #sum+=sprintf("%d", "0x" substr(hex,a,2))
            }
            if (sum % 256) return 0
            return 1
        }
        BEGIN {
            OFS=gfs
        }
        /[^[:blank:]]+ connected/ {
            if (unprinted) print_fields()
            unprinted=1
            output=$1
        }
        /[^[:blank:]]+ disconnected/ {
            if (unprinted) print_fields()
            unprinted=0
        }
        /^[[:blank:]]*EDID.*:/ {
            hex=get_hex_edid()
            if (valid_edid(hex)) {
                for ( c=109; c<=217; c+=36 ) {
                    switch (substr(hex,c,10)) {
                        case "000000fc00" :
                         hexn=append_hex_field(hex,c,hexn)
                         break
                        case "000000fe00" :
                         hexd=append_hex_field(hex,c,hexd)
                         break
                    }
                }
            } else {
              # set special value to denote invalid EDID
              hexn=iet; hexd=iet
            }
        }
        /ConnectorType:/ {
            conn=$2
        }
        END {
            if (unprinted) print_fields()
        }' sp=$(ascii_to_hex $us) iet=$(ascii_to_hex $invalid_edid_tag))

    IFS="$OIFS"
}

get_info

# print the colums of each display quoted in one row
for (( i=0; i<$no; i++ )); do
    echo "'${outs[i]}' '${conns[i]}' '${names[i]}' '${datas[i]}'"
done

Ответ 6

Вы можете попробовать ddcprobe и/или get-edid

$ sudo apt-get install xresprobe read-edid
$ sudo ddcprobe
$ sudo get-edid

Ответ 7

Вы ищете EDID информацию, которая передается по шине I²C и интерпретируется вашим видеодрайвером. Как говорит dtmilano, get-edit из ddcprobe должен работать.

Вы также можете получить эту информацию, зарегистрировав свой запуск X:

startx -- -logverbose 6

Несколько лет назад я использовал пакет read-edid, чтобы собрать эту информацию.

Пакет read-edid может быть доступен в Ubuntu уже, в соответствии с этим сообщением в блоге от 2009 года.