Bildschirme klonen, geskriptet und automatisch

Veröffentlicht von Reinhard Fink am

Benutzt man normalerweise 2 Bildschirme am PC getrennt nebeneinander, stellt sich die Situation für einen Medien-PC im Klassenraum ganz anders dar. Der Bildschirminhalt, den die Lehrperson erstellt, soll natürlich allen Schülerinnen und Schülern per Beamer angezeigt werden. Die beiden Bildschirmausgaben müssen also geklont erscheinen.

Sind für erfahrene BenutzerInnen und wenige Medien-PCs noch die händischen Methoden mittels

  • Windows-Taste + P
  • Einstellungen/Anzeigegeräte

schaffbar, wird das in einer Schule mit 30 bis 40 Medien-PCs so nicht reibungslos funktionieren. Hinzu kommt noch das zusätzliche Problem, dass der Anmeldebildschirm mit Login statt auf dem PC auf dem noch ausgeschalteten Beamer angezeigt wird .

Gesucht wird daher eine Lösung, die Bildschirm und Beamer verlässlich auf allen Medien-PCs und für alle User klont.

Dies bedeutet aber weiter, dass eine Voreinstellung gespeichert in .config/monitors.xml im Homeverzeichnis der BenutzerInnen ausscheidet, weil hier die jeweiligen Bildschirme mit nicht übertragbaren UIDs eingetragen sind.

Aber wie so oft in Linux helfen hier die Universalwerkzeuge

  • Shell – Skripte
  • Konfigurationsdateien der diversen Dienste

Beginnen wir mit dem Shell – Skript unserer Lösung:

Das Shell – Skript:

Unter X11 (in Wayland hoffentlich bald) kann mit dem Befehl (zur besseren Übersicht hier in 2 Zeilen)

>> xrandr --output $SCREEN1 --mode $RESOLUTION     
          --output $SCREEN2 --mode $RESOLUTION  --same-as $SCREEN1

ein Bildschirm $SCREEN1 mit einem Bildschirm $SCREEN2 in der Auflösung $RESOLUTION geklont werden.

Wie können nun die oben verwendeten Variablen $SCREEN1, $SCREEN2 und $RESOLUTION bestimmt werden?

Ein Aufruf von

>> xrandr

liefert all die Information, die wir brauchen, sodass wir eine konkreten Aufruf wie folgenden an eine VGA und Displayport verwenden könnten:

>> xrandr --output VGA-0 --mode 1024x768 --output $DP-0 --mode 1024x768 --same-as VGA-0

Mussten wir oben unsere Variableninhalte noch selbst aus der Ausgabe von xrandr bestimmen, ermöglichen es folgende Befehlszeilen die Information mittels Unix – Konsolenbefehlen automatisch aus der Ausgabe zu extrahieren.

Folgende Befehlsfolge bestimmt unsere Screen – Variablen,

# Find 1. Screen
SCREEN1=$(xrandr --query | awk '/ connected /{ print $1 }' | head -1)
echo $SCREEN1

SCREEN2=$(xrandr --query | awk '/ connected /{ print $1 }' | tail -1) echo $SCREEN2

wobei jede Zeile eigentlich aus 3 Befehlen besteht, die durch Pipes ( | ) miteinander verbunden sind.

xrandr –query schickt seinen Output zu awk ‚/ connected /{ print $1 }‘ und dieser weiter zu head -1, sodass durch weglassen von hinten nach vorne die Arbeitsweise schön dargestellt, ausprobiert bzw. getestet werden kann. Das Einpacken des Befehls in $(…) bewirkt, dass der Output des Befehls und nicht seine Befehlssequenz in die Variablen geschrieben wird.

Zur Bestimmung der Auflösung wird das selbe Prinzip angewandt

# Find Maximum
Resolution in Screen 1 & Screen 2
RESOLUTION=$(xrandr --query | awk '/^ *[0-9]*x[0-9]*/{ print $1 }' |
sort -g -r | uniq -d | head -1)
echo $RESOLUTION

Wieder macht stückweises Kürzen der Pipe von hinten, die Funktionsweise des Befehls ersichtlich.

Wir nachfolgendes Skript ausführbar mit Namen clone nach /usr/local/bin kopiert, dann kann nun mittels Aufruf von clone auf der Konsole von allen BenutzerInnen der Bildschirm geklont werden.

#!/bin/bash

# Find 1. Screen
SCREEN1=$(xrandr --query | awk '/ connected /{ print $1 }' | head -1)
#echo $SCREEN1

# Find 2. Screen
SCREEN2=$(xrandr --query | awk '/ connected /{ print $1 }' | tail -1)
#echo $SCREEN2

# Find Maximum Resolution in Screen 1 & Screen 2
RESOLUTION=$(xrandr --query | awk '/^ *[0-9]*x[0-9]*/{ print $1 }' | sort -g -r | uniq -d | head -1)
#echo $RESOLUTION

# Set Clone Modus with Maximum Resolution 
xrandr --output $SCREEN1 --mode $RESOLUTION  --output $SCREEN2 --mode $RESOLUTION --same-as $SCREEN1

Die Konfigurationsfiles:

Wenn wir es jetzt noch schaffen, clone beim Starten des gdm – Anmeldebildschirms automatisch aufzurufen, haben wir das Problem des unsichtbaren Loginscreens am ausgeschalteten Beamer gelöst.
Und wirklich bietet der gdm – Loginmanager solche Möglichkeiten an.
Desktopfiles in /usr/share/gdm/greeter/autostart, werden beim Start von gdm automatisch ausgeführt.

Das nachfolgende Skript, legt das notwendige Desktop – File am richtigen Platz an:

#! /bin/bash

# create 
# desktop-file : /usr/share/gdm/greeter/autostart/app-clone.desktop
# with link to 
# shell-script : /usr/local/bin/clone
# to clone greeter screen before login
echo "[Desktop Entry]
Version=1.0
Type=Application
Name=APP Clone Desktop Screens
Name[de]=Skript zum Klonen des Desktops bei Beamerbenutzung
Exec=/usr/local/bin/clone
Terminal=false
NoDisplay=true
" >> /usr/share/gdm/greeter/autostart/app-clone.desktop

Wir sind aber noch nicht ganz fertig, denn beim Anmelden, werden die beiden Bildschirme wieder getrennt und müssen erneut geklont werden.

Dies erledigt ein Desktop – File, in /etc/xdg/autostart/, welches für alle BenutzerInnen nach dem Login ausgeführt wird.

#! /bin/bash

# create 
# desktop-file : /etc/xdg/autostart/app-clone.desktop
# with link to 
# shell-script : /usr/local/bin/clone
# to clone screen after login
echo "[Desktop Entry]
Version=1.0
Type=Application
Name=APP Clone Desktop Screens
Name[de]=Skript zum Klonen des Desktops bei Beamerbenutzung
Exec=/usr/local/bin/clone
Terminal=false
X-GNOME-Autostart-Phase=Applications
NoDisplay=true
" >> /etc/xdg/autostart/app-clone.desktop

Die fertigen Skripte, die obiges automatisch erledigen und zusätzlich noch ein Konfigurationsfile zur fixen Vorgabe einer Auflösung und einer Bildwiederholfrequenz anbieten, sind unter https://github.com/edvapp/autoinstall/tree/master/laus/scriptsForClasses/BEAMER_U2004 zu finden.

Bemerkungen/Achtungs:

Bemerkung zu verschiedenen Login-Managern:

Abschließend so noch bemerkt, dass für verschieden Loginmanager die Skripte auf verschieden Art und Weise eingehängt werden können oder müssen. Zu Ubuntu 16.04 findet sich noch die Lösung für lightdm im git.

Bemerkung zu Windows:

Zu Beginn betreuten wir 2 Medien-PCs mit Windows 7, die hin und wieder, wahrscheinlich nach Updates ihren händisch eingestellten Klone-Modus verloren und händisch wieder mittels Administrator-Login repariert werden mussten. Wie möchten das für unterdessen 40 Geräte NICHT mehr machen.

Bemerkung zum Beamerstandby:

xrandr kann die vom Beamer angebotenen Bildschirmauflösungen nur abfragen, wenn der Beamer nicht ausgeschaltet ist. Wird daher ein ausgeschalteter Beamer später hinzu geschaltet schwindelt sich dieser an unserem clone – Skript vorbei und wir erhalten zwei nebeneinanderliegende Bildschirme 🙁

Bei einigen Beamern kann diesem Problem aber Abhilfe geschaffen, in dem der VGA/HDMI – Eingang vom Standby – Modus ausgenommen wird und auch bei ausgeschaltetem Beamer vom Medien-PC abgefragt werden kann.

Ein später zugeschalteter Beamer erscheint dann automatisch richtig geklont. 🙂

Achtung bei der Qualität der Verkabelung:

Auf ein weiteres technisches Problem sei noch sehr deutlich hingewiesen. Obige Lösung ist auf funktionierende Kabelverbindungen vom PC zum Beamer angewiesen, da xrandr sonst grundsätzlich keine Information vom Beamer abfragen kann.

Und hier hapert es nicht selten an der Qualität der Verkabelung. Daher unser Rat: „Kabel nach Verlegung“ entsprechend testen lassen!


8 Kommentare

Thomas Weissel · 16.02.2020 um 16:05

Hallo Reinhard,
Ein Shortcut zu einem Skript, welches dem hier angeführten Skript sehr ähnelt findet sich im LiFE Image sehr prominent am Desktop.

Wie alle Erweiterungen von LiFE ist auch dieses auf Github zu finden.
https://github.com/valueerrorx/life-helperscripts/blob/master/gui-restoreDisplayConfig.sh

Ich freue mich wenn du Zeit findest es dir anzusehen und eventuelle Verbesserungsvorschläge sind sehr willkommen.

Ich habe versucht auch Diskrepanzen zwischen internen und externen Displays abzufangen und auch den Spezialfall 3 Displays 🙂

hier werde ich wegs persönlicher Vorliebe noch nachbessern müssen und eine Kombination aus „clone“ und „erweitert“ (optional) anbieten.

mfg

    Reinhard Fink · 16.02.2020 um 17:25

    Hallo Thomas,

    danke für deine Rückmeldung.

    Wie es scheint sind wir über die gleiche wunderbare Pipe (xrandr –query | awk ‚/^ *[0-9]*x[0-9]*/{ print $1 }‘ | sort -n | uniq -d -c) im Netz gestolpert.
    Ich habe sie nur gegooglet. Falls dir das selbst eingefallen ist Hut ab!

    Bei mir bricht leider
    RESOLUTION=`xrandr … mit einer grep Fehlermeldung ab 🙁 und da ich im Augenblick nur 1 Bildschirm am Laptop habe, komme ich über uniq -d nicht hinaus 🙁

    Obwohl ich ein ganz ähnliches Skript verwende, ist es nicht ganz leicht zu lesen. Die BASH ist mächtig aber eben nicht einfach. Für mich sehr lehrreich, weil es den anderen mit meinen Skripten sicher gleich geht.

    Evt. könnte man RESOLUTION=`xrandr … aufspalten, ich erkenne nicht genau, was es tut und finde so obigen Fehler nicht.

    Kann man davon ausgehen, dass die Auflösung 1024×768 immer vorhanden ist, wenn 2 Ausgabegeräte angeschlossen sind? Dann könnte man auf ein 2.tes Display testen, wie du es machst und dann bei Erfolg die beste Auflösung nur mehr mit RESOLUTION=$(xrandr –query | awk ‚/^ *[0-9]*x[0-9]*/{ print $1 }‘ | sort -g -r | uniq -d | head -1) bestimmen.

    Wenn die Displayabfrage nach TRANSFORM ganz an den Anfang kommt, wird der letzte Teil evt. auch leichter lesbar, denn greifst du mit readarray usw. schon ordentlich in die BASH Trickkiste.

    Machte es bei speziellen Bildschirmeinstellungen nicht überhaupt Sinn, die Systemeinstellungen zu verwenden und Skripte nur zu Automation zu verwenden. D.h. Desktoplink, der Bildschirmeinstellungen öffnet.

    Hoffe mein „Kritik“ kommt nicht in den falschen Hals, denn solche Skripte müssen erst einmal geschrieben und dann getestet werden, Hut ab!
    Ich habe auf alle Fälle gelernt, und weiß wo ich nachfragen kann 🙂
    LG
    Reinhard

Thomas Weissel · 17.02.2020 um 13:56

Hallo Reinhard,
Vielen Dank für das Feedback!
Ich werde bei nächster Gelegenheit das Skript überarbeiten, lesbarer gestalten und dokumentieren 🙂

Die Systemsettings habe ich für die Klassencomputer komplett gesperrt weil Kollegen gerne mehr VERstellen als Einstellen. Dennoch war es in ganz seltenen Fällen (zB. Kabel wird ab- und angesteckt und KDE nahm an wie wollen Bigdesktop statt Clonedesktop) wenn sie die Möglichkeit haben per Mausklick einfach den Standardzustand herzustellen. KScreen hat sich enorm verbessert und speichert sich die Einstellungen und seit 2,3 Versionen brauchen wir das praktisch nicht mehr.

Zur Erklärung der Zeile:

xrandr –query | awk ‚/^ *[0-9]*x[0-9]*/{ print $1 }‘
# listet alle verfügbaren Auflösungen aller Bildschirme

| sort -n | uniq -d -c|
# sortiert das Ergebnis und zeigt nur die einzigartigen Auflösungen an und zählt diese
# diese liste wird dann erneut gefiltert indem sie durch ein grep -w gepiped wird

$(xrandr –query | awk ‚/^ *[0-9]*x[0-9]*/{ print $1 }‘ | sort -n | uniq -d -c|head -n 1|awk ‚{print $1}‘)
# $() legt das Ergebnis der Befehls quasi auf eine Bashvariable die dann für „grep -w“
# zur Verfügung steht der Klammerinhalt macht im Grunde
# das Selbe wie oben, nur dass danach die oberste Zeile abgeschnitten wird
# und nur die erste Spalte zurückgegeben wird (also die Anzahl der
# gefundenen verfügbaren identischen Auflösungen)
# man könnte sagen in $() steht die Anzahl der Bildschirme 😉
# das grep -w gibt also nur jene Auflösungen zurück die
# für alle Bildschirme verfügbar sind.

|tail -1|awk ‚{print $2}‘
# schneidet dann die höchste Auflösung ab und gibt diese aus
# somit haben wir die höchste, für alle Bildschirme verfügbare Auflösung gefunden

Weissel Thomas · 17.02.2020 um 14:05

Deine Zeile:
xrandr –query | awk ‚/^ *[0-9]*x[0-9]*/{ print $1 }‘ | sort -g -r | uniq -d | head -1

Bringt mir nämlich lediglich die größte gefundene Auflösung, nicht jedoch die, die auch für ALLE Screens verfügbar ist.
Lg Thomas

    Reinhard Fink · 17.02.2020 um 15:57

    Hallo Thomas,

    habe deinen RESOLUTION=`xrandr –query … Programmtei nun mit 2 Bildschirmen getestet und natürlich liefert er die beste Auflösung für beide Bildschirme 🙂
    Allerdings scheitert das grep, wenn nur ein Bildschirm zur Verfügung steht, daher mein Vorschlag die Anzahl der Bildschirme vorher zu bestimmen.
    (Wo das grep scheitert, habe ich so schnell gar nicht herausfinden können :-()
    Falls man aber NUR 2 Bildschirme ansteuert liefert aber auch der Befehl

    xrandr –query | awk ‚/^ *[0-9]*x[0-9]*/{ print $1 }‘ | sort -g -r | uniq -d | head -1

    durch uniq – d die größte Auflösung beider Bildschirme und bleibt leer, wenn nur einer angeschlossen ist.

    Die Pipe

    xrandr –query | awk ‚/^ *[0-9]*x[0-9]*/{ print $1 }‘ | sort -g | uniq -d -c | sort -gk1 -gk2

    sortiert bei mir auch 3 Bildschirme der Größe nach, wobei

    uniq -d -c die mehrfachen zählt, und

    sort -gk1 -gk2 nach Anzahl (k1 = Key Spalte 1 … ) sortiert.

    LG
    Reinhard

Thomas Weissel · 17.02.2020 um 17:33

Alles klar!

DISPLAYCOUNT=$(xrandr –query | awk ‚/^ *[0-9]*x[0-9]*/{ print $1 }‘ | sort -n | uniq -d -c|head -n 1|awk ‚{print $1}‘)
RESOLUTION=`xrandr –query | awk ‚/^ *[0-9]*x[0-9]*/{ print $1 }‘ | sort -n | uniq -d -c|grep -w ${DISPLAYCOUNT} |tail -1|awk ‚{print $2}’`

Ich hab mal drübergschaut und bin deinem Vorschlag zuerst zu zählen nachgekommen 🙂
Jetzt klappts auch „mit ohne Beamer“ 😉 Nachdem grep dann nichts zurück gibt hats einfach trotzdem funktioniert.. haha..

Ausserdem hab ich für mein persönliches Infosaal Setup auch noch optional 3 Bildschirme mit „extended desktop“ möglich gemacht..

https://github.com/valueerrorx/life-helperscripts/blob/master/gui-restoreDisplayConfig.sh

lg thomas

Rene Schwarzinger · 19.02.2020 um 19:52

Ich habe Reinis Version mit 2 Bildschirmen für uns adaptiert und mit 3 Bildschirmen erfolgreich getestet:

#!/bin/bash

# Find 1. Screen
SCREEN1=$(xrandr –query | awk ‚/ connected /{ print $1 }‘ | head -1)
#echo $SCREEN1

# Find 2. Screen
SCREEN2=$(xrandr –query | awk ‚/ connected /{ print $1 }‘ | head -2 | tail -1)
#echo $SCREEN2

# Find 3. Screen
SCREEN3=$(xrandr –query | awk ‚/ connected /{ print $1 }‘ | head -3 | tail -1)
#echo $SCREEN2

# Find Maximum Resolution in Screen 1 & Screen 2 & Screen 3
RESOLUTION=$(xrandr –query | awk ‚/^ *[0-9]*x[0-9]*/{ print $1 }‘ | sort -g | uniq -d -c | sort -gk1 -gk2 | tail -1 | awk ‚/[0-9]*x[0-9]*/{ print $2 }‘)
#echo $RESOLUTION

# Set Clone Modus with Maximum Resolution
xrandr –output $SCREEN1 –mode $RESOLUTION –output $SCREEN2 –mode $RESOLUTION –same-as $SCREEN1 –output $SCREEN3 –mode $RESOLUTION –same-as $SCREEN1

Spezialfälle, die es auch bei uns etwa im INF-Saal gibt (2 Bildschirme nebeneinander, 1 davon auf Beamer gespiegelt + zusätzlich ein Wacom Schreibtablet), muss ich noch integrieren bzw. anders ergänzen.

Thomas Weissel · 20.02.2020 um 15:42

@rene
Die Spezialfälle habens in sich.. auf einem neuen System ist zB. kein primär Bildschirm festgelegt. Auch ist es schwer zu entscheiden welcher Screen nach rechts oder links erweitert werden soll und welcher geklont werden soll.. ich habe das in meinem Skript nur mit Benutzerinteraktion gelöst, da man ja unmöglich softwareseitig feststellen kann ob ein Screen links oder rechts vom anderen aufgestellt wurde 😉
wenn man natürlich ein standardsetup hat bei dem man es immer gleich macht, macht es schon sinn das zu automatisieren..

Kscreen ist zum glück mittlerweile sogar fähig sich verschiedene setups zu merken (hat man sie einmalig eingestellt) und schaltet somit mal mit beamer, mal ohne, auf das richtige setup (aber ganz vertrau ich dem noch immer nicht 😉

ps: werde deine zeile für 3 screens gleich mal testen

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.