Вопрос по xserver, ubuntu, linux – Linux извлекает имена мониторов

11

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

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

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

@Miquel Моя видеокарта ATI Radeon HD 5000. Конечно, лучше было бы получить более общее решение. Но конкретное решение для моей нынешней машины тоже подойдет. Jānis Gruzis
Я не уверен, какие названия мониторов вы хотите. Достаточно ли будет получить выходные имена? Я заметил, что информация EDID портативного компьютера может не иметь названия монитора для встроенного дисплея, но в любом случае она может иметь какое-то фирменное наименование и название детали. jarno
Я согласен, что получение определенных свойств путем анализа и декодирования выходных данныхxrandr --prop или жеxrandr --verbose не совсем понятный способ, так как форматирование выходных данных xrandr может быть изменено и не имеет документов. Хотелось бы, чтобы у xrandr были способы чтения отдельных свойств заданного вывода (например, как у exiftool есть способы считывания отдельных метаинформационных тегов заданных файлов). jarno
Есть похожая тема вunix.stackexchange.com. pevik
Насколько я знаю, вам нужно получить это из специфичных для драйвера API. Раньше что-то было в nvidia. Какая у тебя карта? Или вам нужно что-то общее? Miquel

Ваш Ответ

7   ответов
2

что это грязный способ, но это дает мне название модели монитора даже лучше, чем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
Отличный сценарий! Хотя не уверен, каким должен быть четвертый параметр, он остается пустым с моими мониторами. Однако, если я изменяю 000000fe00 на 000000ff00, он показывает серийные номера моих мониторов. Это отлично подходит для определения того, какой монитор подключен к какому разъему. (000000fe00 в соответствии с вики - это неопределенное текстовое поле.)
8

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 командаВот, этосправочная страница также хороший источник.

14

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 точно извлечь имя монитораonlyи без лишнего мусора от EDID, следовательно, "магические числа" лайк000000fc00, 26 а также0a, Наконец используетxxd преобразовать из шестнадцатеричного в ASCII, печатая одно имя монитора в строке.

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

$ monitor-switch --list
Connected monitors:
# DFP5  HDMI    HT-R391
# DFP7  DVI-I   DELL U2412M
Возможно, у дисплея ноутбука нет названия, поскольку он не является отдельным продуктом для покупателя.
Я протестировал встроенный скрипт на моем мониторе, и он ничего не печатает. Я проверил EDID и заметил, что у него есть два дескриптора монитора, помеченные как FCh, первый из которых - L1715S, а второй - пустой. На моем ноутбуке нет такого дескриптора для встроенного дисплея, но есть два дескриптора, помеченных как FEh, которые, очевидно, содержат фирменное наименование CPT и название модели CLAA102NA0A.
У моего другого ноутбука есть то же самое: название бренда монитора находится в первом дескрипторе, а название детали - во втором дескрипторе, оба помечены FEh.
Хотя бы одинFCh запись обязательна в соответствии со спецификацией, так что это странно, что ваш ноутбук не содержит один ...FEh расшифровывается как «неопределенный текст», в основном это текстовое поле, поэтому я не могу полагаться на него, содержащее соответствующую информацию. Что касается печати ничего, откройте вопрос, вставив оба идентификатора EDID, чтобы мы могли настроить сценарий для вашего случая.
Несколько реальных образцов EDID для тестирования:00ffffffffffff001e6d6f432c340400110f01036e221b78ea2ee5a4574a9c25115054a56b80314f454f614f81800101010101010101302a009851002a4030701300520e1100001e000000fd00384b1e530e000a202020202020000000fc004c31373135530a202020202020000000fc000a2020202020202020202020200098, 00ffffffffffff00320c000000000000000f0102801e16780a74b09657548b282550540000000101010101010101010101010101010164190040410026301888360030e410000018000000000000000000000000000000000000000000fe004c475068696c6970734c43440a000000fe004c503135305830382d544c414100a3
1

ddcprobe и / илиget-edid

$ sudo apt-get install xresprobe read-edid
$ sudo ddcprobe
$ sudo get-edid
Добавление parse-edid после get-edid делает вывод более значимым. Это сработало для меняsudo get-edid | parse-edid   Если у вас есть несколько мониторов, вы можете отобразить детали, используяsudo get-edid -b 0 | parse-edid - & GT; за 1-й монитор.sudo get-edid -b 1 | parse-edid - & GT; для 2-го монитора.
Этот вывод не нужен. xrandr выведет имена окон из файла xorg.conf. Эти имена - то, что я ожидал. Jānis Gruzis
0

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

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

startx -- -logverbose 6

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

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

9

sudo get-edid не работал для меня. (РЕДАКТИРОВАТЬ: теперь работает на другом компьютере, 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 = "";
}'
Для карт Intel файлы edid предоставляются в / sys.find /sys -name edid, Это не похоже на случай с ATI. Не могу проверить NVidia.
Дляxrandr в Ubuntu 12.04 замениEDID: заEDID_DATA: в строке 3. Это прекрасно работает, когда|strings используется согласно комментарию в коде.
Я обнаружил, что xrandr знает текущий EDID лучше, чем файл, найденный командой @Dave, если вы меняете монитор на лету.
2

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

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

xrandr source code.

Если вы пишете программу на C для этого, вы можете действительно легко получить имя поставщика монитора из идентификатора PNP (например, «SAM» = «& gt;» Samsung Electric Company »):github.com/golightlyb/PNP-ID

Похожие вопросы