2012-05-08 5 views
11

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

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

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

+0

Насколько я знаю, вам нужно получить это от конкретных API-интерфейсов драйвера. Раньше было что-то в nvidia. Какая у вас карточка? Или вам нужно что-то общее? – Miquel

+0

@Miquel Моя видеокарта ATI Radeon HD 5000. Лучше, конечно, получить более общее решение. Но конкретное решение для моей текущей машины также будет делать. –

+0

Я согласен, что получение определенных свойств путем синтаксического анализа и декодирования вывода 'xrandr --prop' или' xrandr --verbose' не является четким способом, поскольку выходное форматирование xrandr может быть изменено и недокументировано. Я хотел бы, чтобы у xrandr были способы читать отдельные свойства заданного результата (например, например, exiftool имеет способы читать отдельные метаинформационные теги данных файлов). – jarno

ответ

8

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

Для карт Intel файлы edid предоставляются в/sys. 'find/sys -name edid'. Это не похоже на ATI. Невозможно проверить NVidia. – Dave

+0

Для 'xrandr' в Ubuntu 12.04 замените' EDID: 'для' EDID_DATA: 'в строке 3.Он отлично работает, когда используется '| строк', в соответствии с комментарием в коде. – MestreLion

+0

Я узнал, что xrandr знает текущий EDID лучше, чем файл, найденный командой @Dave, если вы меняете монитор на лету. – jarno

1

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

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

Это не удалось. xrandr выводит имена окон из файла xorg.conf. Эти имена я ожидал. –

2

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

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

xrandr source code.

+1

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

0

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

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

startx -- -logverbose 6 

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

Пакет для чтения EDID могут быть доступны в Ubuntu уже according to this blog post с 2009

9

Вдохновленный ответ Бени, это будет читать данные EDID с помощью xrandr и извлекать имена мониторов в соответствии с EDID specification, без необходимости каких-либо внешние инструменты, такие как 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, для печати одного имени монитора в строке.

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

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

Я проверил встроенный скрипт моим монитором, и он ничего не печатает. Я проверил EDID и заметил, что у него есть два дескриптора монитора, отмеченные как FCh, первый из которых L1715S, а второй из них пуст. На моем ноутбуке нет такого дескриптора для интегрированного дисплея, но два дескриптора помечены как FEh, которые, по-видимому, содержат фирменное наименование CPT и название модели CLAA102NA0A. – jarno

+0

По крайней мере одна запись 'FCh' обязательна по спецификации, поэтому странно, что ваш ноутбук не содержит одного ...' FEh' означает «неуказанный текст», в основном свободное текстовое поле, поэтому я не могу полагаться на него, содержащее соответствующие Информация. О печати ничего, откройте вопрос, вставляя оба EDID, чтобы мы могли настроить скрипт для вашего дела. – MestreLion

+0

Возможно, дисплей ноутбука не имеет названия, поскольку он не является отдельным продуктом клиента. – jarno

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 
+0

Отличный сценарий! Не уверен, хотя какой должен быть четвертый параметр, он остается пустым с моими мониторами. Однако, если я меняю 000000fe00 на 000000ff00, он показывает мои серийные номера мониторов. Это отлично подходит для обнаружения того, какой монитор подключен к какому разъему. (000000fe00 согласно wiki - это неопределенное текстовое поле.) – Geeklab

1

Работы на Ubuntu 16.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. Этот файл журнала может предоставить вам историю действий подключаемого модуля и подключаемого модуля.

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

Дополнительная информация о команде hwinfohere. Его man page также является хорошим источником.

Смежные вопросы