Specyfikacja POSIX naprawdę zabezpiecza swoje zakłady, jeśli chodzi o Terminal Kontrolujący , i który definiuje w ten sposób:
- Terminal kontrolny
- Pytanie o to, który z kilku ewentualnie specjalnych plików odnoszących się do terminala nie zostało uwzględnione w POSIX.1. Nazwa ścieżki
/dev/tty
jest synonimem terminala sterującego powiązanego z procesem.
To jest na liście Definicje - i to wszystko, co tam jest. Ale w Ogólnym interfejsie terminalowym mówi się coś więcej:
Terminal może należeć do procesu jako terminal sterujący. Każdy proces sesji, który ma terminal kontrolny, ma ten sam terminal kontrolny. Terminal może być terminalem sterującym dla co najwyżej jednej sesji. Terminal sterujący dla sesji jest przydzielany przez lidera sesji w sposób zdefiniowany w implementacji. Jeśli lider sesji nie ma kontrolującego terminala i otworzy plik urządzenia terminala, który nie jest jeszcze powiązany z sesją bez użycia opcji O_NOCTTY (patrz open ()), określa się, czy terminal stanie się kontrolującym terminalem sesji lider.
Terminal sterujący jest dziedziczony przez proces potomny podczas wywołania funkcji fork (). Proces zrzeka się terminala sterującego, gdy tworzy nową sesję zsetsid()
funkcjonować; inne procesy pozostające w starej sesji, które miały ten terminal jako terminal kontrolny, nadal go mają. Po zamknięciu ostatniego deskryptora pliku w systemie (niezależnie od tego, czy znajduje się w bieżącej sesji) powiązanego z terminalem sterującym, nie jest określone, czy wszystkie procesy, które miały ten terminal jako terminal kontrolny, przestają mieć terminal kontrolny. Czy i w jaki sposób lider sesji może ponownie uzyskać terminal kontrolny po tym, jak terminal kontrolny został zrzeczony w ten sposób, nie jest określone. Proces nie zrzeka się terminala sterującego, po prostu zamykając wszystkie deskryptory plików powiązane z terminalem sterującym, jeśli inne procesy nadal go otwierają.
Zostało jeszcze wiele nieokreślonych - i szczerze mówiąc, myślę, że to ma sens. Chociaż terminal jest kluczowym interfejsem użytkownika, w niektórych przypadkach jest to również wiele innych rzeczy - na przykład rzeczywisty sprzęt, a nawet rodzaj drukarki - ale w wielu przypadkach jest to praktycznie nic - jak xterm
emulator, który jest tylko emulatorem . Trudno jest tu określić konkretnie - i nie sądzę, żeby i tak byłby w interesie Uniksa, ponieważ terminale robią znacznie więcej niż Unix.
W każdym razie POSIX jest dość niepewny, jak ps
powinien zachowywać się na molo.
Jest -a
przełącznik:
- Napisz informacje o wszystkich procesach związanych z terminalami. Implementacje mogą pomijać liderów sesji z tej listy.
Wspaniały. Liderzy sesji mogą zostać pominięci. To nie jest bardzo pomocne.
I -t
:
- Napisz informacje o procesach związanych z terminalami podane w termistrze. Wniosek powinien zapewniać, aby termista był pojedynczym argumentem w postaci
<blank>
listy oddzielonej przecinkami. Identyfikatory terminali należy podawać w formacie zdefiniowanym przez implementację .
... co jest kolejnym rozczarowaniem. Ale mówi się tak o systemach XSI:
- W systemach zgodnych z XSI należy je podać w jednej z dwóch form: nazwa pliku urządzenia (na przykład
tty04
) lub, jeśli nazwa pliku urządzenia zaczyna się od tty
, tylko identyfikator następujący po znakach tty
(na przykład 04
) .
To trochę lepiej, ale to nie jest ścieżka. Również w systemach XSI jest -d
przełącznik:
- Napisz informacje dla wszystkich procesów, z wyjątkiem liderów sesji.
... co jest przynajmniej jasne. Możesz także określić -o
przełącznik utput za pomocą ciągu tty
formatu, ale, jak zauważyłeś, jego format wyjściowy jest zdefiniowany w implementacji. Mimo to uważam, że jest tak dobry, jak to tylko możliwe. Myślę, że - przy dużym nakładzie pracy - powyższe przełączniki w połączeniu z innymi narzędziami mogą dać ci całkiem niezły ballpark. Szczerze mówiąc, nie wiem, kiedy / jak to się dla ciebie psuje - i nie byłem w stanie wyobrazić sobie takiej sytuacji. Myślę jednak, że jeśli dodamy fuser
i find
możemy zweryfikować ścieżkę.
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"*}"
Wszystko /dev/null
po to, aby pokazać, że może działać, gdy żadna z podpowłok poszukiwawczych nie ma żadnego z 0,1,2 podłączonego do nabrzeża. W każdym razie, to drukuje:
/dev/pts/3: mikeserv 3342 F.... (mikeserv)zsh
Teraz powyższe uzyskuje pełną ścieżkę na moim komputerze i wyobrażam sobie, że w większości przypadków byłoby to możliwe. Mogę sobie również wyobrazić, że to może zawieść. To tylko szorstka heurystyka.
Może się to nie udać z wielu innych powodów, ale jeśli jesteś w systemie, który pozwala liderowi sesji zrzec się wszystkich deskryptorów na molo, a mimo to pozostać sid, jak pozwala specyfikacja, to na pewno nie pomoże. To powiedziawszy, myślę, że w większości przypadków może to być dość dobre oszacowanie.
Oczywiście najłatwiejszą rzeczą do zrobienia, jeśli masz jakieś deskryptory podłączone do swojego molo, jest po prostu ...
tty <&2
...lub podobne.
ps
rozwiązanie obejmuje większość systemów (iwho
nie pomaga bardziej niżps
), prawdopodobnie z nieco większym kodem do obsługi samego identyfikatora (np. „04”). Zastanawiałem się, czy istnieje jeszcze bardziej przenośne rozwiązanie.