Die POSIX-Spezifikation sichert ihre Wetten in Bezug auf das Controlling-Terminal wirklich ab und definiert sie folgendermaßen:
- Terminal steuern
- Die Frage, welche von möglicherweise mehreren speziellen Dateien, die sich auf das Terminal beziehen, gemeint ist, wird in POSIX.1 nicht behandelt. Der Pfadname
/dev/tty
ist ein Synonym für das steuernde Terminal, das einem Prozess zugeordnet ist.
Das steht in der Definitionsliste - und das ist alles, was es gibt. In der allgemeinen Terminalschnittstelle wird jedoch noch mehr gesagt:
Ein Terminal kann als steuerndes Terminal zu einem Prozess gehören. Jeder Prozess einer Sitzung mit einem steuernden Terminal verfügt über dasselbe steuernde Terminal. Ein Terminal kann das steuernde Terminal für höchstens eine Sitzung sein. Das steuernde Terminal für eine Sitzung wird vom Sitzungsleiter auf implementierungsdefinierte Weise zugewiesen. Wenn ein Sitzungsleiter kein steuerndes Terminal hat und eine Terminalgerätedatei öffnet, die noch keiner Sitzung zugeordnet ist, ohne die Option O_NOCTTY zu verwenden (siehe open ()), wird durch die Implementierung definiert, ob das Terminal zum steuernden Terminal der Sitzung wird Führer.
Das steuernde Terminal wird während eines Funktionsaufrufs von fork () von einem untergeordneten Prozess geerbt. Ein Prozess gibt sein steuerndes Terminal auf, wenn er eine neue Sitzung mit dem erstelltsetsid()
Funktion; Andere Prozesse in der alten Sitzung, die dieses Terminal als steuerndes Terminal hatten, haben es weiterhin. Nach dem Schließen des letzten Dateideskriptors im System (unabhängig davon, ob er sich in der aktuellen Sitzung befindet oder nicht), der dem steuernden Terminal zugeordnet ist, wird nicht angegeben, ob alle Prozesse, die dieses Terminal als steuerndes Terminal hatten, kein steuerndes Terminal mehr haben. Ob und wie ein Sitzungsleiter ein steuerndes Terminal wieder erwerben kann, nachdem das steuernde Terminal auf diese Weise aufgegeben wurde, ist nicht spezifiziert. Ein Prozess gibt sein steuerndes Terminal nicht einfach auf, indem er alle dem steuernden Terminal zugeordneten Dateideskriptoren schließt, wenn andere Prozesse es weiterhin geöffnet haben.
Es gibt eine Menge, die nicht spezifiziert ist - und ehrlich gesagt denke ich, dass es Sinn macht. Während das Terminal eine wichtige Benutzeroberfläche ist, gibt es in einigen Fällen auch alle möglichen anderen Dinge - wie die tatsächliche Hardware oder sogar eine Art Drucker -, aber in vielen Fällen ist es praktisch gar nichts - wie einxterm
ein Emulator, der nur ein Emulator ist . Es ist schwer, dort spezifisch zu werden - und ich denke, es wäre sowieso nicht viel im Interesse von Unix, da Terminals viel mehr als Unix leisten.
Wie auch immer, POSIX ist auch ziemlich zweifelhaft, wie ps
sich verhalten soll, wenn es um die Ctty geht.
Da ist der -a
Schalter:
- Schreiben Sie Informationen für alle Prozesse, die mit Terminals verknüpft sind. Implementierungen können Sitzungsleiter aus dieser Liste auslassen.
Groß. Sitzungsleiter können weggelassen werden. Das ist nicht sehr hilfreich.
Und -t
:
- Schreiben Sie Informationen für Prozesse, die mit Terminals verknüpft sind, die in der Termliste angegeben sind. Der Antrag stellt sicher, dass die Termliste ein einzelnes Argument in Form einer
<blank>
oder durch Kommas getrennten Liste ist. Terminal-IDs müssen in einem implementierungsdefinierten Format angegeben werden.
... was eine weitere Enttäuschung ist. Über XSI-Systeme heißt es jedoch weiter:
- Auf XSI-konformen Systemen müssen sie in einer von zwei Formen angegeben werden: dem Dateinamen des Geräts (z. B.
tty04
) oder, wenn der Dateiname des Geräts mit beginnt tty
, nur der nach den Zeichen folgenden Kennung tty
(z. B. 04
) .
Das ist ein bisschen besser, aber kein Weg. Auch auf XSI-Systemen gibt es den -d
Schalter:
- Schreiben Sie Informationen für alle Prozesse mit Ausnahme der Sitzungsleiter.
... was zumindest klar ist. Sie können den -o
utput-Schalter auch mit der Formatzeichenfolge angeben tty
, aber wie Sie bereits bemerkt haben, ist das Ausgabeformat implementierungsdefiniert. Trotzdem denke ich, dass es so gut ist, wie es nur geht. Ich denke, dass - mit viel Arbeit - die oben genannten Schalter in Kombination mit einigen anderen Dienstprogrammen Ihnen einen ziemlich guten Ballpark bringen können. Um ganz ehrlich zu sein, ich weiß nicht, wann / wie es für Sie kaputt geht - und ich konnte mir keine Situation vorstellen, in der es passieren würde. Aber ich denke wahrscheinlich, wenn wir hinzufügen fuser
und find
den Pfad überprüfen können.
exec 2<>/dev/null
ctty=$(sh -c 'ps -p "$$" -o tty=' <&2)
sid=$(sh -c 'ps -Ao pid= -o tty=|
grep '"$ctty$"' |
grep -Fv "$(ps -do pid=)"' <&2)
find / -type c -name "*${ctty##*/}*" \
-exec fuser -uv {} \; 2>&1 |
grep ".*$ctty.*${sid%%"$ctty"*}"
Das /dev/null
Zeug sollte nur zeigen, dass es funktionieren kann, wenn keine der suchenden Subshells 0,1,2 mit der CTTY verbunden hat. Wie auch immer, das druckt:
/dev/pts/3: mikeserv 3342 F.... (mikeserv)zsh
Jetzt erhält das oben Genannte den vollständigen Pfad auf meiner Maschine, und ich kann mir vorstellen, dass dies in den meisten Fällen für die meisten Menschen der Fall ist. Ich kann mir auch vorstellen, dass es scheitern könnte. Es sind nur grobe Heuristiken.
Dies könnte wahrscheinlich aus vielen anderen Gründen fehlschlagen, aber wenn Sie sich auf einem System befinden, das es dem Sitzungsleiter ermöglicht, alle Deskriptoren an die ctty abzugeben und dennoch die Seite zu bleiben, wie es die Spezifikation zulässt, wird dies definitiv nicht helfen. Trotzdem denke ich, dass dies in den meisten Fällen eine ziemlich gute Schätzung erhalten kann.
Natürlich ist die einfachste zu tun , was , wenn Sie keine Deskriptoren zu Ihrem CTTY verbunden ist nur ...
tty <&2
...o.ä.
ps
Lösung die meisten Systeme abdeckt (undwho
nicht mehr hilft alsps
), möglicherweise mit etwas mehr Code, um den Bezeichner alleine zu behandeln (wie "04"). Ich habe mich gefragt, ob es eine noch tragbarere Lösung gibt.