2012-05-08 13 views
11

Situazione: sto utilizzando più monitor e voglio ottenere i loro nomi in bash. Attualmente sto usando Ubuntu 10.04.Linux recupera i nomi dei monitor

Conosco xrandr. Da lì posso ottenere solo dati statistici. Quello che voglio è leggere tutti i nomi dei monitor in una matrice per lavorare con loro.

C'è un modo chiaro per farlo senza tagliare i nomi da un tipo di stringa? Un modo chiaro sarebbe leggerli dal file. Un modo non chiaro sarebbe quello di reindirizzare l'output di xrandr ad una sorta di funzione per tagliare i nomi da esso.

+0

Per quanto ne so, è necessario ottenerlo dalle API specifiche del driver. C'era qualcosa in nvidia. Che carta hai? O hai bisogno di qualcosa di generico? – Miquel

+0

@Miquel La mia scheda video è ATI Radeon HD 5000. Ovviamente sarebbe meglio ottenere una soluzione più generica. Ma farà anche una soluzione specifica per la mia macchina attuale. –

+0

Concordo sul fatto che ottenere determinate proprietà mediante l'analisi e la decodifica dell'output di 'xrandr --prop' o' xrandr --verbose' non è un modo chiaro, poiché la formattazione dell'output di xrandr è soggetta a modifiche e non è documentata. Vorrei che xrandr avesse modo di leggere le proprietà individuali di un determinato output (ad esempio, come exiftool ha modi di leggere i singoli tag delle meta-informazioni dei file dati). – jarno

risposta

8

sudo get-edid non ha funzionato per me. (EDIT: ora funziona su un altro computer, Lubuntu 14.10, darei la colpa alle differenze BIOS ma è un'ipotesi casuale ...)

In ogni caso sotto X, xrandr --verbose stampa il blocco EDID. Ecco un modo rapido e sporco per estrarlo e passare a 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

Per le schede Intel, i file edid sono forniti in/sys. 'find/sys -name edid'. Questo non sembra essere il caso di ATI. Impossibile verificare per NVidia. – Dave

+0

Per 'xrandr' in Ubuntu 12.04, sostituire' EDID: 'per' EDID_DATA: 'nella riga 3.Funziona alla grande quando si usa '| stringhe', come da commento nel codice. – MestreLion

+0

Ho scoperto che xrandr conosce l'EDID corrente meglio del file trovato dal comando @Dave, se si cambia monitor al volo. – jarno

1

Puoi provare ddcprobe e/o get-edid

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

Questo output non è stato necessario. xrandr emetterebbe i nomi delle finestre dal file xorg.conf. Quei nomi sono ciò che mi aspettavo. –

2

Se non si desidera analizzare xrandr uscita, scrivere un programma C utilizzando libXrandr che si ottiene solo quello che vuoi. Se tutto quello che vuoi fare è interrogare le informazioni, può essere fatto rapidamente. Read this document.

Se si desidera ottenere il nome del monitor vero, in alternativa al @ di dtmilano soluzione è quella di ottenere la proprietà EDID del monitor mediante libXrandr e poi analizzare manualmente e stampare (leggere le specifiche EDID).

xrandr source code.

+1

Se si sta scrivendo un programma C per fare ciò, è possibile ottenere il nome del fornitore del monitor dall'ID PNP (ad es. "SAM" => "Samsung Electric Company") usando molto facilmente questo: https://github.com/ golightlyb/PNP-ID – HoboBen

0

Si sta cercando informazioni EDID, che vengono passate lungo un bus I²C e interpretate dal driver video. Come dice dtmilano, dovrebbe funzionare get-edit da ddcprobe.

È inoltre possibile ottenere queste informazioni accedendo il vostro inizio X:

startx -- -logverbose 6 

Anni fa, ho usato un pacchetto chiamato read-edid per raccogliere queste informazioni.

Il pacchetto lettura edid possono essere disponibili in Ubuntu già, according to this blog post dal 2009.

9

Ispirato dalla risposta di Beni, questo leggerà i dati EDID utilizzando xrandr ed estrarre i nomi monitor secondo il EDID specification, senza bisogno di alcun strumenti esterni come 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 

Utilizza awk per estrarre con precisione il nome del monitor solo, e nessuna spazzatura extra dal EDID, quindi "numeri magici" come 012., 26 e 0a. Infine utilizza xxd per convertire da esadecimale a ASCII, stampando un nome di monitor per riga.

Sulla base di questa soluzione ho fatto un handy script to switch monitors, che può essere utilizzato anche ad elencare semplicemente monitorare informazioni:

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

Ho testato lo script inline dal mio monitor e non stampa nulla. Ho ispezionato l'EDID e ho notato che ha due descrittori del monitor etichettati come FCh, il primo dei quali è L1715S e il secondo è vuoto. Sul mio portatile non esiste un descrittore di questo tipo per il display integrato, ma due descrittori contrassegnati come FEh, che apparentemente contengono il nome del marchio CPT e il nome del modello CLAA102NA0A. – jarno

+0

Almeno una voce 'FCh' è obbligatoria per le specifiche, quindi è strano che il tuo laptop non ne contenga uno ...' FEh' sta per "testo non specificato", fondamentalmente un campo di testo libero, quindi non posso fare affidamento su di esso contenente rilevanti informazione. Non stampando nulla, apri una domanda incollando entrambi gli EDID in modo da poter modificare lo script per il tuo caso. – MestreLion

+0

Forse il display del portatile non ha un nome dato che non è un prodotto cliente separato. – jarno

2

So che questo è un modo sporco, ma mi dà un po 'il nome del modello del monitor anche meglio sudo get-edid|parse-edid. Legge le informazioni negli array e le emette in un modo che può essere letto come se si leggesse un file. Puoi modificarlo in base alle tue esigenze.

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

Grande sceneggiatura! Non sono sicuro di quale debba essere il quarto parametro, ma rimane vuoto con i miei monitor. Tuttavia, se cambio 000000fe00 a 000000ff00, mostra i numeri di serie dei miei monitor. Questo è ottimo per rilevare quale monitor è collegato a quale connettore. (000000fe00 secondo wiki è un campo di testo non specificato). – Geeklab

1

Funziona su Ubuntu 16.04. (So ​​che la sua troppo tardi per rispondere, ma questa soluzione è rilevante oggi)

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

Ho due monitor collegati. Uno con il portatile e l'altro è un display esterno. Non appena il monitor esterno viene collegato o rimosso, questo comando riflette la modifica. Hai continuamente bisogno di sondare. La rimozione dell'opzione --short fornisce informazioni più dettagliate.

È possibile interrogare lo stato con la seguente processo in background:

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

Il ciclo while true viene eseguito infinite volte. Il sleep 2 interrompe ogni iterazione del ciclo per 2 secondi. E l'output di hwinfo --monitor --short viene aggiunto a monitor.log. Questo file di registro può fornire la cronologia delle attività del plug-in e del plug-in del monitor.

FYI: Sto usando uno script python in background (deamon) utilizzando il comando precedente (e altri simili) per rilevare se qualcuno sta facendo alcuni plug-in HW e plug-in con i sistemi nel laboratorio informatico. In tal caso, ricevo le notifiche appropriate che qualcuno ha scollegato/in un monitor, un mouse o una tastiera quasi in tempo reale!

Ulteriori informazioni sul comando hwinfo sono here. Il suo man page è anche una buona fonte.

Problemi correlati