Forum: PC-Programmierung Leeres Terminal für Ausgabe aus anderem Prozess öffnen (linux)


von DPA (Gast)


Lesenswert?

Bei meiner Terminal Multiplexer Library (noch in Entwicklung), die ich 
für mein in-terminal Keyboard (auch noch in Entwicklung) brauche, 
brauche ich das momentane Terminal schon, und kann deshalb nicht direkt 
dort Debugger ausgaben machen. Ich löse das so, das ich am Anfang eine 
Environment Variable (habe die TM_DEBUGFD genannt) verwende, und wenn 
die gesetzt ist, ist das der File Deskriptor, in den ich meine 
Debugmeldungen Rausschreibe. [1]

Wenn ich dann diese Debugmeldungen meiner Anwendung 
console-keyboard-multiplexer, die meine libttymultiplex library 
verwendet, anschauen will, kann ich das z.B. so machen:
1
TM_DEBUGFD=99 99<./logfile console-keyboard-multiplexer bash -l

Damit ich das nicht jedes mal davor schreiben muss, ab ich mir in der 
bashrc eine Funktion angelegt, die sieht ungefähr so aus:
1
tmdebug(){
2
  export TM_DEBUGFD=99
3
  exec 99<"$1"
4
}

Dadurch kann muss ich im Terminal nur einmal "tmdebug ./logfile" 
aufrufen, und dann wird dort rein geloggt. Da ich das Logfil aber nicht 
wirklich brauche, und die Debugausgaben gerne live betrachte, starte ich 
normalerweise ein 2tes Terminal, verwende das tty Kommando um das pts 
device file zu finden, und mache die Ausgabe dann darauf, mit "tmdebug 
/dev/pts/X".

Das funktioniert eigentlich ganz gut, aber es ist etwas lästig am Anfang 
manuell das Terminal zu starten, tty einzugeben, und die Ausgabe dann 
bei tmdebug einzusetzen. Ausserdem habe ich dann auf dem TTY, auf den 
ich logge, noch eine unnötige bash am laufen.

Ich würde das gerne noch etwas bequemer gestalten. Gibt es eine 
Möglichkeit, ein Terminal oder etwas vergleichbares mit einem Befehl so 
zu öffnen, dass es mir direkt das pts Device ausgibt? Etwas mit einem 
shortcut um die Ausgabe wieder zu löschen wäre auch ganz praktisch.

Ich will meine "tmdebug" Funktion so anpassen, dass ich nur noch einmal 
am Anfang vor dem Debuggen "tmdebug" eingeben muss, und dann das öffnen 
des Terminalfensters zur Ausgabe usw. automatisch erledigt wird. Wie 
kann ich das machen?

1) 
https://github.com/Daniel-Abrecht/libttymultiplex/blob/master/src/main.c#L32

: Verschoben durch User
von Gerd E. (robberknight)


Lesenswert?

DPA schrieb:
> Ich würde das gerne noch etwas bequemer gestalten. Gibt es eine
> Möglichkeit, ein Terminal oder etwas vergleichbares mit einem Befehl so
> zu öffnen, dass es mir direkt das pts Device ausgibt?

was für ein Terminalprogramm verwendest Du denn?

Ich verwende z.B. Konsole von KDE. Da kann man beim Start mit dem 
Parameter -e ein zu startendes Programm mit angeben. Das kann natürlich 
auch ein bash-Skript sein, welches Deine pts-Device-Anzeige macht.

von foobar (Gast)


Lesenswert?

Für sowas nehm ich "tail -f":
1
export TM_DEBUGFD=99
2
exec 99>>/tmp/logfile
3
xterm -e tail -f /tmp/logfile &
4
5
echo >&99 'Hello World!'

von DPA (Gast)


Lesenswert?

Gerd E. schrieb:
> was für ein Terminalprogramm verwendest Du denn?

Ich bin mir gerade nicht mehr ganz sicher, ob es xfce4-terminal oder 
lxterminal war, ich bin gerade unterwegs und kann gerade nicht 
nachsehen.

Gerd E. schrieb:
> Ich verwende z.B. Konsole von KDE. Da kann man beim Start mit dem
> Parameter -e ein zu startendes Programm mit angeben. Das kann natürlich
> auch ein bash-Skript sein, welches Deine pts-Device-Anzeige macht.

Ein Terminal erstellt 2 pty mittles des ptmx device, das ptm  (pseudo 
terminal master) und das pts (pseudo terminal slave). Die Programme im 
Terminal bekommen das pts als standard input, output und error (fd 0, 1 
und 2). Das ptm nutzt das Terminal, um mit den Programmen, die das pts 
haben, zu kommunizieren. Das Terminal macht also unter anderem die 
"Device-Anzeige" von dem, was ins pts geschrieben wird. Ich will dieses 
pts Device eben eigentlich nicht mit einem Programm nutzen, das im 
Terminal gestartet wird, sondern das pts in dem Skript öffnen, mit 
welchem ich auch das terminal gestartet habe, welches dieses erstellt, 
um von dort direkt dorthin schreiben zu können.

foobar schrieb:
> Für sowas nehm ich "tail -f":

Ok, das Löst das eigentliche Problem von mir, Danke.

Es ist zwar etwas unschön, dass dann dafür alles noch in eine Datei 
geschrieben werden muss. Vielleicht kann ich da noch etwas mit fifos 
basteln oder so, muss ich noch schauen, wenn ich wieder zuhause bin

von Boris O. (bohnsorg) Benutzerseite


Lesenswert?

Mir ist noch nicht so ganz klar, wofür das Multiplexing sein soll. Es 
gibt schon soetwas wie das screen-Kommando, mit dem man auf der Konsole 
verschiedene »Fenster« aufmachen kann. Die lassen sich sogar vertikal 
oder horizontal teilen, der Standard ist sie einfach aufeinander zu 
stapeln. Ansonsten lassen sich ja schon in der Bash per & und den 
zugeordneten Kommandos (fg, job usf) lassen sich Prozesse in den 
Hintergrund schieben und wieder in den Vordergrund bringen.

Ein Anwendungsfall ist per SSH vom eigenen Host (Ausgangs-Host) auf 
einen Server zu wechseln, mit Nutzerkonto. Dort startet man dann screen 
und wechselt zuerst in die root-Rolle. Danach öffnet man per Ctrl+a c 
ein weiteres (virtuelles) Terminal, hat wieder die normale Nutzerrolle 
und schiebt per scp ein paar Ergebnisse zurück zum Ausgangs-Host. Per 
Ctrl+a d schickt man die komplette Sitzung (beide virtuelle Terminals) 
in den Hintergrund und meldet sich per exit am Server einfach ab.

Stunden später kann man sich wieder am Server anmelden und nimmt per 
screen -r die beiden vorigen Sitzungen nahtlos wieder auf.

Wie unterscheidet sich deine Unternehmung davon? (Nichts hielte mich 
davon ab, schon am Ausgangs-Host per screen verschiedene Terminals auf 
verschiedene Server zu öffnen und das lokal zusammenzuführen.)

von DPA (Gast)


Lesenswert?

Boris O. schrieb:
> Mir ist noch nicht so ganz klar, wofür das Multiplexing sein soll. Es
> gibt schon soetwas wie das screen-Kommando, mit dem man auf der Konsole
> verschiedene »Fenster« aufmachen kann.

Meine libttymultiplex library ermöglicht es Programmen, beliebige 
bereiche vom Terminal zu definieren, in denen wieder ein anderes 
Terminalprogram läuft. Das Programm könnte stattdessen auch selbst 2 
curses Instanzen in diesen bereichen laufen lassen usw.

Es gibt zwar Programme wie z.B. tmux, die ähnliches können, aber diese 
sind keine Library und deshalb nicht auf die selbe weise durch andere 
Programme verwendbar. Ich brauche das für ein anderes Programm von mir, 
welches damit eine Tastatur auf der Linuxconsole bereitstellen wird. 
(Demovideo einer alten Version: 
http://dpa.li/console-keyboard-multiplexer-demo.mp4 ). Ich will die 
Linuxconsole auf meinem Linuxphone verwenden können, sobald es mal 
kommt. Ein weiterer Grund, warum ich dafür kein screen oder tmux 
verwenden kann, ist, dass ich die Tastatur auch beim Login schon da sein 
muss. Den Loginprozess muss ich als root starten, und würde ich den in 
tmux oder screen starten, könnte man sich dann mit ein paar 
Tastenkombinationen einfach ne root Shell verschaffen und das login 
Programm umgehen.

Da ich für die multiplexer library im Grunde genommen einen kompletten 
terminal emulator schreiben muss, und ich das Backend zur Anzeige mit 
einer recht simplen API getrennt habe 
(https://github.com/Daniel-Abrecht/libttymultiplex/blob/master/include/internal/backend.h), 
ergeben sich ausserdem ein paar weniger offensichtliche Möglichkeiten. 
Würde ich ein X11 oder Wayland oder Qt backend alternativ zum curses 
Backend hinzufügen, könnte man die Library auch einfach für einen 
normalen Terminal Emulator verwenden. Würde ich ein DRM/KMS backend 
hinzufügen, könnte daraus eine alternative zu kmscon entstehen. Und mit 
ein paar anderen kleinen Modifikationen, könnte aus der Lib sogar ein 
ganzes GUI Framework werden. Vermutlich implementiere ich aber mal noch 
Framebuffersupport & Emulation, damit ich die Tastatur etwas Moderner 
und Grafischer erscheinen lassen kann.

von Daniel A. (daniel-a)


Lesenswert?

OK, ich hab das jetzt so gelöst:
1
tmdebug(){
2
  export TM_DEBUGFD=99
3
  f="$(mktemp -u)"
4
  mkfifo "$f"
5
  lxterminal -e bash -c "tty >\"$f\"; while IFS= read -n 1 x; do if [ \"\$x\" == ' ' ]; then clear; fi; done" &
6
  pts="$(cat "$f")"
7
  rm "$f"
8
  exec 99>"$pts"
9
}

So kann ich auch mit der space taste das Terminal wieder leeren.

von Bernd K. (prof7bit)


Lesenswert?

DPA schrieb:
> Ich brauche das für ein anderes Programm von mir,
> welches damit eine Tastatur auf der Linuxconsole bereitstellen wird.
> (Demovideo einer alten Version:
> http://dpa.li/console-keyboard-multiplexer-demo.mp4 ). Ich will die
> Linuxconsole auf meinem Linuxphone verwenden können, sobald es mal
> kommt.

Könnte man das nicht auch weiter unten einbauen, irgendwo an zentraler 
Stelle im Displaytreiber so daß es im Textmodus immer unten eine 
Tastatur einblendet und Tastenereignisse erzeugt?

von DPA (Gast)


Lesenswert?

Bernd K. schrieb:
> Könnte man das nicht auch weiter unten einbauen, irgendwo an zentraler
> Stelle im Displaytreiber so daß es im Textmodus immer unten eine
> Tastatur einblendet und Tastenereignisse erzeugt?

Das ist im Moment etwas Problematisch. Im Grunde müsste man die Anzeige 
in 2 Teile spalten, und auf diese separat zeichnen können. Das müsste 
dann im Kernel gemacht werden. Es gibt 2 Subsysteme, das gute alte 
Framebuffer Subsystem und das neuere DRM (Direct Rendering Manager) 
Subsystem (und noch gralloc in android).

Im Framebuffer Subsystem wäre das vermutlich relativ einfach, solange 
keine GPU Acceleration benötigt wird, denn dort ist das Größtenteils nur 
das Mappen und schreiben/zeichnen in einen Buffer, obwohl, dann gibt es 
da teils noch die Panning und double buffering Geschichten usw. Das 
Framebuffer subsystem soll aber, wenn es nach den DRM Leuten geht, 
abgeschafft werden, und irgendwann nur noch die DRM Emulation davon da 
sein.

Im DRM Subsystem wäre das vermutlich um einiges komplizierter, dort 
werden abstrakte CRTC, Connector und Encoder und Plane Objekte verbunden 
und dazwischen Buffer herum geschoben, meist GEM buffer, und dann nutzt 
NVIDIA noch sein TTM stat GEM zu nehmen. Man müsste vermutlich irgendwie 
bei den Planes ansetzten, aber dann müsste man alle Treiber anpassen und 
testen, das würde Jahre dauern.

Man könnte auch bei der fbcon ansetzen, und die Tastatur versuchen 
direkt in die framebuffer console einzubauen. Dann hätte man sie aber 
auch nur dort, und nur die, die der Kernel gerade bietet. Die fbcon hat 
aber auch so seine Problemchen. Die fbcon kann z.B. nur neue ausgaben 
updaten, die auf der gerade aktiven Konsole gemacht wurden. Das ist echt 
nervig, wenn man 2 verschiedene TTY mit fbcon auf 2 Framebuffer 
unterschiedlicher Monitore rendert, und man mit ALT+Fx erst auf das TTY 
auf dem anderen Bildschirm wechseln muss, damit die neuen Ausgaben auch 
angezeigt werden, und nicht nur die alten da stehen. Dann gibt es 
diverse locking Probleme was vt switches und logging auf die console 
betrifft. Und dann braucht die fbcon auch noch das Framebuffer 
subsystem, welches ja eigentlich abgeschafft werden soll. Es gab schon 
versuche, eine neue linux console im basierend auf dem DRM subsystem zu 
machen, bisherige Versuche wurden aber abgebrochen oder scheiterten. Ich 
glaube der letzte versuch wollte DRM dumb buffer verwenden, welche auch 
vom Framebuffer subsystem verwendet wird. Es geisterte kürzlich auch mal 
eine ebenfalls auf DRM dumb buffer basierendes in-kernel splashscreen 
implementierung herum, keine Ahnung ob das was wurde.

Weil die Entwicklung von sowas im kernel so komplex, langsam, und 
sicherheitsproblematisch ist, will man seit Jahren schon die fbcon ganz 
entfernen, und in userspace machen, daher kam die kmscon. Aber das hat 
sich natürlich nicht durchgesetzt, weil man halt einerseits sehen will, 
woran es hängt, wenn ein kernel im frühen Bootprozess hängt, und man 
andererseits direkt mit init schon die Konsole haben will, ohne sich um 
das "wie führe ich vorher kmscon aus, state dann das eigentliche init, 
und was ist jetzt dort wieder schief gelaufen?" Problem kümmern zu 
müssen.

Und dann gibt es noch das Problem, dass gewisse Tastaturen und 
Eingabemethoden kontext von dort brauchen, wo man schreibt. z.B. bei 
Wortverfollständigungen/Vorschlägen, aber ich glaube auch bei gewissen 
Sprachen wie Chinesisch, wo die Schriftzeichen irgendwie beim Schreiben 
zusammengesetzt werden. Um sowas will man sich nicht im Kernel kümmern 
müssen.

Und dann gibt es noch das Problem, das solche änderungen auch noch in 
den Kernel übernommen/akzeptiert werden müssten.

Aus diesen gründen mach ich das zeug im Userspace und nicht im Kernel.

von Le X. (lex_91)


Lesenswert?

Wie lösen denn andere Nutzer dieses irgendwann erscheinenden Gerätes 
dieses Problem?
Gibts da keine Community?
Ich meine, dass man auf einem touchbasierten Device eine 
Bildschirmtastatur brauchen könnte, das müsste doch schon mal jemandem 
aufgefallen sein?

Mein Termux auf Android zeigt natürlich eine Tastatur an.
Aber gut, wenn du auf deinem Gerät die /bin/bash nutzt, die kann das 
natürlich nicht.
Könnte man nicht einfach zwei unabhängige Terminals im Tiling-Modus 
anzeigen, das eine füttert das andere?

Edit: ja ok, damit bliebe das login-Thema.
Ich bewundere dein Problem.

: Bearbeitet durch User
von Daniel A. (daniel-a)


Lesenswert?

Le X. schrieb:
> Wie lösen denn andere Nutzer dieses irgendwann erscheinenden Gerätes
> dieses Problem?

Nicht allen ist die nicht-grafische Obefläche derart wichtig.

> Gibts da keine Community?

Doch, sicher. Es gibt diverse Matrix Channel, ein Forum, eine 
Mailingliste, ein GitLab, etc. Es gibt einige, aber nicht so extrem 
viele, die man etwas machen sieht, und die arbeiten dann auch noch an 
unterschiedlichsten Dingen. Die meisten portieren eine Distro, 
schreiben, portieren oder passen eine Anwendungen für bessere 
Handynutzbarkeit an, schauen was für Probleme es noch gibt, etc.

> Ich meine, dass man auf einem touchbasierten Device eine
> Bildschirmtastatur brauchen könnte, das müsste doch schon mal jemandem
> aufgefallen sein?

Die Leute von Purism machen am meisten von den essenziellen Dingen, wie 
Treiberentwicklung, die grafische wayland shell "Phosh", oder auch das 
Keyboard (virtboard[1] bzw. squeekboard[2]). Für  X11 gibt es bereits 
bestehende onscreen Keyboards.

Die Konsolentastatur ist halt etwas, was ich haben will. Viele wissen 
vermutlich auch gar nicht, dass viele Terminalemulatoren Maussupport 
haben, wie das bei der Linuxkonsole hinzugefügt werden kann, wie ein 
Terminalemulator funktioniert, etc. Und vermutlich wäre das vielen 
anderen auch zu aufwendig. In anderen Worten, es ist halt sonst keiner 
verrückt genug, um mit dem Versuch sowas zu machen seine Zeit zu 
verschwenden.

Ich könnte natürlich einfach eine X oder Wayland Session machen, die ein 
bestehendes Keyboard und einen normalen grafischen Terminalemulatior 
startet, aber solch ein System wäre etwas fehleranfälliger und ich finde 
einfach nicht das selbe. Plus, wenn die grafische Oberfläche mal 
ausfällt, dann kann ich die Konsole so trotzdem noch verwenden. Und dann 
gibt es eben auch noch andere Dinge, für die ich die Library später 
sowieso noch brauchen könnte.

1) https://source.puri.sm/Librem5/virtboard
2) https://source.puri.sm/Librem5/squeekboard

von Bernd K. (prof7bit)


Lesenswert?

Daniel A. schrieb:
> Plus, wenn die grafische Oberfläche mal
> ausfällt, dann kann ich die Konsole so trotzdem noch verwenden.

In der Praxis ist das halt so gelöst daß bei solchen Geräten ohne 
Tastatur per Definition die GUI das ist was mindestens immer zu 
funktionieren hat um das Gerät irgendwie nutzen zu können. Wenn man es 
wirklich mal kaputtkonfiguriert hat geht man dann halt normalerweise mit 
nem seriellen Terminal dran von nem PC aus der funktionierende Tastatur 
und Bildschirm hat und repariert es von dort aus so weit daß es wieder 
aus eigener Kraft benutzbar wird. Deshalb stellt sich das Problem in der 
Form wahrscheinlich in der Praxis so gut wie nie.

: Bearbeitet durch User
von foobar (Gast)


Lesenswert?

> OK, ich hab das jetzt so gelöst: [mkfifo]

Probier dies mal aus (braucht ein Shell und System, das Process 
Substitution unterstützt, z.B. Bash und Linux):
1
exec 99>  >(xterm 9<&0 -e cat /dev/fd/9)
2
3
echo >&99 'Hello World!'
4
5
clear >&99   # clear xterm
6
7
exec 99>&-   # close xterm

Btw: statt einer clear-screen-Funktion drück ich in dem Log-Fenster 
einfach ein paar mal Return ...

von Daniel A. (daniel-a)


Lesenswert?

foobar schrieb:
> exec 99>  >(xterm 9<&0 -e cat /dev/fd/9)

Das geht mit xterm und Varianten davon. Andere terminal, wie lxterminal 
und xfce4-terminal, schliessen alle Filedeskriptoren.

von foobar (Gast)


Lesenswert?

> Andere terminal, wie lxterminal und xfce4-terminal, schliessen alle
> Filedeskriptoren.

OT, aber ich kann's mir nicht verkneifen: Da wird mal wieder an der 
falschen Stelle repariert :-(

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.