turbo112 schrieb:
Vain schrieb:
Jenachdem, wie genau du es nimmst, musst du den Prozessbaum nach oben durchwandern, bis du einen Prozess findest, der nach einem bekannten Terminal aussieht. Oder ist garantiert, dass dein Skript immer direkt aus einem Terminal heraus gestartet wird? Was, wenn dein Skript mal durch ein anderes Skript aufgerufen wird? Oder von einem Editor?
Wie meinst Du das hier?
Ja, normalerweise wird das Ganze immer aus einem Terminal gestartet. Aus einem anderen Skript habe ich es probiert, auch das geht problemlos. Aus einem Editor? ... Ich wüsste nicht einmal wie das geht, dass müsste ich erst nachlesen! ☺
Möglicherweise bin ich mit dem Editor etwas über das Ziel hinausgeschossen. 😉 Sowieso mutmaße ich, dass das Problem viel komplexer und facettenreicher ist, als dir vielleicht bewusst ist.
Die Problematik ist einfach, dass man nicht blind sagen kann: „Der Elternprozess meines Skriptes ist das Terminal.“ Denn im Prozessbaum können zwischen deinem Skript und dem Terminal noch einige Prozesse dazwischen liegen. Zum Beispiel die Shell – oder eben auch sowas wie ein Editor oder ein Dateimanager oder was auch immer.
Deswegen der Ansatz, den Prozessbaum so lange nach oben zu durchlaufen, bis man einen Prozess gefunden hat, der „nach Terminal aussieht“.
Mir fällt so direkt aber keine tolle Möglichkeit ein, um zu erkennen, wann ein Prozess ein Terminal ist. Da oben habe ich jetzt nach dem „Prozessnamen“ geschaut. Eine Alternative wäre vielleicht, zu schauen, ob der Prozess „/dev/ptmx
“ gerade geöffnet hat – aber wie zuverlässig das funktioniert, kann ich nicht sagen.
Das hier habe ich nicht so wirklich verstanden, um nicht zu sagen ich habe eigentlich nichts verstanden!
Angenommen, im Prozessbaum gibt es folgenden Teilbaum:
systemd(1)---xiate(18430)---bash(24510)---vim(25015)---meintest.sh(25110)
Das muss man von rechts nach links lesen. Ganz rechts ist mein Testskript. Der Elternprozess davon ist Vim. Davon wiederum der Elternprozess die Bash, dann kommt xiate und dann das Initsystem (PID 1, systemd).
Über diesen Teilbaum iterieren meine Skripte aus dem anderen Posting. In jedem Iterationsschritt schauen sie sich eine der PIDs an. Die Frage ist, woran man bei gegebener PID erkennen kann, ob diese PID zu einem Terminalemulator gehört.
Mein Ansatz von oben war, sich die Dateien anzuschauen, die eine PID gerade geöffnet hat. Das kann man unter Linux zum Beispiel herausfinden, indem man sich das Verzeichnis „/proc/$pid/fd
“ anschaut. Für die obige Bash (PID 24510) ist das beispielsweise:
$ l /proc/24510/fd
total 0
dr─x────── 2 void users 0 07-09 18:45 │ ./
dr─xr─xr─x 9 void users 0 07-09 18:45 │ ../
lrwx────── 1 void users 64 07-09 18:45 │ 0 -> /dev/pts/1
lrwx────── 1 void users 64 07-09 18:45 │ 1 -> /dev/pts/1
lrwx────── 1 void users 64 07-09 18:45 │ 2 -> /dev/pts/1
lrwx────── 1 void users 64 07-09 18:50 │ 255 -> /dev/pts/1
Hmm. Das hilft uns nicht weiter. Schauen wir uns stattdessen PID 18430 an:
$ l /proc/18430/fd
total 0
dr─x────── 2 void users 0 07-09 18:51 │ ./
dr─xr─xr─x 9 void users 0 07-09 08:48 │ ../
lr─x────── 1 void users 64 07-09 18:51 │ 0 -> /dev/null
lrwx────── 1 void users 64 07-09 18:51 │ 1 -> socket:[58822]
lrwx────── 1 void users 64 07-09 18:51 │ 10 -> socket:[61655]
...
lrwx────── 1 void users 64 07-09 18:51 │ 21 -> /tmp/#357852 (deleted)
lrwx────── 1 void users 64 07-09 18:51 │ 22 -> /dev/ptmx
...
Aha! Diese PID hat gerade die Datei „/dev/ptmx
“ geöffnet.
Du als Benutzer merkst davon nichts, aber ein Terminalemulator benutzt „/dev/ptmx
“. Ich will jetzt nicht so sehr ins Detail gehen, was der damit macht. Anscheinend halten die Emulatoren aber diese Datei offen – und das ist dann das Merkmal, das in meinem Skript darüber entscheidet, ob eine PID ein Terminalemulator ist oder nicht.
Ich habe nur einen Teil aus der Funktion den ich nicht 100%tig nachvollziehen kann und mir auch nicht klar ist, wofür er gut ist!
Und zwar diesen hier:
[... case mit sshd und login ...]
Ich vermute, dass das Skript nicht über eine kommende "ssh-Verbindung" ausgeführt werden soll. Aber der zweite Teil ist mir überhaupt nicht klar!
Mit deiner Vermutung liegst du richtig, glaube ich.
Wenn man sich per SSH mit einem fremden Rechner verbindet und dort dann das Skript startet, dann gibt es natürlich im Prozessbaum dieses fremden Rechners keinen dazugehörigen Terminalemulator. Denn dieses Terminal läuft ja bei dir auf dem Rechner.
Zumindest gibt es keinen „Terminalemulator“ im Sinne eines grafischen Programms, in das der User direkt Befehle eingeben kann. Was es aber durchaus gibt, ist der SSH-Daemon, der deinem Skript auch ein „Terminal“ präsentiert (auf technischer Ebene). Dieser Fall wird mit dem von dir zitierten Code-Fetzen abgefangen.
Der andere Teil mit dem „login
“ fängt einen weiteren Sonderfall ab. Das ist dann relevant, wenn man sich in der Konsole auf Strg+Alt+F1 oder ähnlich einloggt. Dort gibt es keinen Terminalemulator, der „/dev/ptmx
“ benutzt – die „Linux-Konsole“ funktioniert ein bisschen anders.
So ganz top ist meine Lösung übrigens nicht. In bestimmten Konstellationen hat das Skript nicht die notwendigen Rechte, um die offenen Dateien einer PID zu begutachten. Das ist bei SSH der Fall, aber auch beim Terminalmultiplexer GNU screen (tmux und dtach scheinen kein Problem zu sein). Da ist mir kein toller Workaround eingefallen. Entweder man benutzt sudo oder baut das ins „case
“ mit ein …
Mein Bauchgefühl sagt mir auch so ein bisschen, dass turbos Problem nicht so ganz eindeutig lösbar ist. Man kann nach guten Hinweisen suchen, welche PID der gesuchte Terminalemulator ist. Um sicher zu sein, müsste man aber herausfinden können, welcher Prozess (eigentlich: welche Prozesse) das Master-Gegenstück zum aktiven Pseudo-Terminal-Slave (siehe Ausgabe von „tty
“) geöffnet hält (afaik macht ein Terminalemulator mit „openpty()
“ ein Deskriptorenpaar auf, wovon das Slave-Ende beim Kindprozess ankommt und der Master bleibt im Emulator). Verknüpft sind beide im Kernel. Mir ist nun keine Kernel-Schnittstelle bekannt, mit der man herausfinden kann, wer/wo das Master-Ende ist. Stattdessen suchen meine Skripte halt einen Elternprozess, der irgendeinen pts-Master offen hat, und das ist dann mit recht hoher Wahrscheinlichkeit unser gesuchtes Terminal – aber eben nicht mit Sicherheit.