Sessions unter Linux

Während der Session-Begriff unter Windows noch einigermaßen eindeutig ist, haben wir unter Linux mehrere Hierarchie-Ebenen, auf die dieser Begriff bedeutet werden kann.

Von Prozessen über Logins bis hin zu grafischen Sitzungen finden wir hier unterschiedliche Mechanismen vor, die wir jeweils als “Session” bezeichnen können.


Prozessgruppen

Prozessgruppen sind logische Container von einem oder mehreren Prozessen. Intern werden sie als “Sessions” bezeichnet und mit der API setsid() erzeugt. Der erste Prozess einer Session wird zum Session-Leader und seine PID ist gleichzeitig die Session-ID. Nun kann man mit kill Signale an die Session senden, womit alle Kindprozesse der Session angesteuert werden.

Login und Umgebung

Das Programm login ist für das Anmelden eines neuen Benutzers zuständig und startet danach die konfigurierte Shell UND bereitet die Umgebung vor.

Unzählige Funktionen in Unix-Derivaten benötigen bestimmte Environment Variablen. Fehlen diese oder sind falsch eingetragen, treten “seltsame” Seiteneffekte auf.

Da sich die Environment-Tabelle im Normalfall ebenfalls an alle Kindprozesse weitervererbt, kann man auch ein Login als “Session” bezeichnen.

X11

Wird auf einem System auch noch ein X11-Server hochgefahren, bildet sich ein zum Kernsystem paralleles Login-System ab. Der X-Server kann mehrere “Sessions” parallel bedienen und setzt ebenso für alle zusammengehörigen Prozesse bestimmte Environment-Variablen auf, damit (vor allem die grafischen) Prozesse ihre gemeinsamen Ressourcen finden.

Linux APIs

So lange man als Programmierer seine Software nur innerhalb einer solchen Session betreiben möchte, muss man sich weiter keine Gedanken machen, da sich alle Einstellungen in der Regel vererben.

Will man allerdings selbst steuernd eingreifen, wird es in der Folge schwerer.

Prozessgruppen sind als einzige in POSIX standardisiert und haben mit setsid() und getsid() definierte Schnittstellen.

Bei Logins wird es schon schwieriger. Man kann natürlich das Programm login starten um eine neue Session zu erzeugen, was aber User-Eingaben erwartet.
Ist man selbst ein Daemon und will Logins verwalten bzw. Prozesse gezielt in Login Sessions injizieren, kann man die Konfigurationsdaten versuchen selbst auszulesen und das Environment selbst aufsetzen.

Ich experimentiere hierbei mit dynamisch zusammengestellten Shell-Scripts, die per source die Profile-Scripts einbinden und dann das Zielprogramm ausführen. Den Benutzerwechsel kann man mit der API setuid() auslösen und das Script mit dem anderen User so starten. Eine API, die etwas Vergleichbares tut, kenne ich bislang nicht.

Bleibt am Ende noch der X-Server.
Dass man in einer bestehenden X-Sitzung ein Programm ausführt ist von außerhalb der Sitzung recht schwierig, weil es keinen programmatisch standardisierten Weg gibt herauszufinden, welche Sitzungen überhaupt laufen und wie man sein Programm vorbereiten muss um einer Sitzung beizutreten.

Hier nutze ich gerne den Workaround, dass die Environment-Tabelle eines Prozesses innerhalb der Session ausgelesen und für den Zielprozess kopiert wird.
Natürlich benötigt man dafür root Rechte oder entsprechende Privilegien.

Die Liste der Sessions und der Prozesse in Sessions ist leider auch nicht offiziell zugänglich. Allerdings nutzen die aktuellen Implementierung das Verzeichnis /tmp/.ICE-unix/ um dort für jeden Session-Prozess eine Datei anzulegen, deren Name dessen PID ist.

Über das procfs zieht man sich dann die für X11 relevanten Environment-Variablen heraus (z.B.: DISPLAY) und fügt sie dem eigenen Kindprozess bei. Das Kind kann dann über die X11 APIs auf die Umgebung der laufenden X-Session zugreifen und schon tauchen seine Fenster auf der GUI der X-Session auf.