Jak uzyskać prawdziwą nazwę terminala sterującego (jeśli istnieje, w przeciwnym razie błąd) jako nazwę ścieżki?
Przez „prawdziwą nazwę” mam na myśli nie /dev/tty
, która nie może być używana przez inne arbitralne procesy w odniesieniu do tego samego terminala. Wolę odpowiedź jako prosty kod powłoki (jak w poniższym przykładzie), jeśli to możliwe, w przeciwnym razie jako funkcję C.
Zauważ, że musi to działać, nawet jeśli standardowe wejście jest przekierowane, aby tty
narzędzie nie mogło być użyte: not a tty
w takim przypadku wystąpiłby błąd, ponieważ tty
po prostu drukuje nazwę pliku terminala podłączonego do standardowego wejścia.
Pod Linuksem można użyć:
echo "/dev/`ps -p $$ -o tty | tail -n 1`"
ale nie jest to przenośne, ponieważ zgodnie z POSIX format nazwy terminala nie jest określony .
Jeśli chodzi o funkcje C, ctermid (NULL)
zwraca /dev/tty
, co jest tutaj bezużyteczne.
Uwaga: zgodnie z zsh
dokumentacją należy to zrobić
zsh -c 'echo $TTY'
ale obecnie (wersja 5.0.7) kończy się niepowodzeniem, gdy przekierowywane jest zarówno standardowe wejście, jak i standardowe wyjście:
$ zsh -c 'echo $TTY > /dev/tty' < /dev/null
/dev/pts/9
$ zsh -c 'echo $TTY > /dev/tty' < /dev/null > /dev/null
/dev/tty
źródło
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.man xterm
:-Sccn
Ta opcja pozwalaxterm
na użycie jej jako kanału we / wy dla istniejącego programu ... Wartość opcji to kilka liter nazwy pty używanej w trybie slave plus odziedziczony numer fd. Jeśli opcja zawiera znak „/”, oddziela nazwę pty od fd.ps
z Busybox (który jest wykorzystywany przez Androida, btw), nawet pod GNU / Linux. Co rozumiesz przez „xterm
poradzisz sobie z tym04
”?busybox
nie jest zgodny z POSIX.toybox
robi jednak bardzo dobrze.Odpowiedzi:
„Terminal kontrolujący”, inaczej. ctty jest distincted z „ zacisk procesem interakcji z”.
Standardowym sposobem na uzyskanie ścieżki mola jest ctermid (3). Po wywołaniu tego, we Freebsd od wydania 10, rzeczywista ścieżka jest sprawdzana [1], podczas gdy starsze implementacje Freebsd i glibc [2] bezwarunkowo zwracają „/ dev / tty”].
ps (1) z pakietu linux procps 3.2.8, przeczytaj wpis numeryczny w / proc / * / stat [3], a następnie częściowo odejmij nazwę ścieżki , zgadując [4, 5] z powodu braku obsługi systemu [6] .
Jeśli jednak nie jesteśmy ściśle zainteresowani molem, ale każdy terminal związany ze stdio, tty (1) drukuje ścieżkę terminala podłączoną do stdin, która jest identyczna jak
ttyname(fileno(stdin))
w c, i alternatywą jestreadlink /proc/self/fd/0
.Mniej ważna myśl dotycząca bezwarunkowego zachowania „/ dev / tty”: Określa tylko, że ciąg zwrócony przez ctermid „gdy jest używany jako nazwa ścieżki, odnosi się do bieżącego terminala sterującego”, zamiast jakiegoś prostego ”to nazwa ścieżki bieżącego terminal sterujący ". Można to interpretować jako to, że „/ dev / tty” nie jest terminalem sterującym, ale odnosi się do terminalu sterującego tylko wtedy, gdy ten sam proces go otworzy (3). Nie naruszając w ten sposób zasady „terminal może być pomostem maksymalnie na jedną sesję” [7].
Inną konsekwencją jest to, że kiedy nie mam żadnego kontrolującego terminala, ctermid nie zawodzi - takie awarie są dozwolone przez specyfikacje [8] - więc mogę tylko uświadomić sobie brak mej molo do czasu awarii kolejnego otwarcia (3), co jest w porządku, ponieważ specyfikacje mówią również, że wywołanie open (3) nie jest gwarancją sukcesu.
źródło
ps
rozwiązanie, które podałem w moim pytaniu, ponieważ nie wszystkie systemy operacyjne mają/proc
system plików. Zauważ, żeps
sam używa on readlink/proc/self/fd/2
(który działa nawet jeśli przekierowany jest błąd standardowy).tty
.stderr
jest prawdopodobnie najlepszy, ponieważ zostałby określony jako r / w. Taktty <&2
.ctermid()
zwracaniem"/dev/tty"
. Ta nazwa zawsze odnosi się do terminala sterującego procesu uzyskującego do niego dostęp , który różni się w zależności od sesji. Terminal jest specyficzny dla sesji, ale nazwa, pod którą można uzyskać do niego dostęp, nie musi być.Specyfikacja POSIX naprawdę zabezpiecza swoje zakłady, jeśli chodzi o Terminal Kontrolujący , i który definiuje w ten sposób:
/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ę z
setsid()
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:Wspaniały. Liderzy sesji mogą zostać pominięci. To nie jest bardzo pomocne.
I
-t
:<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:
tty04
) lub, jeśli nazwa pliku urządzenia zaczyna się odtty
, tylko identyfikator następujący po znakachtty
(na przykład04
) .To trochę lepiej, ale to nie jest ścieżka. Również w systemach XSI jest
-d
przełącznik:... co jest przynajmniej jasne. Możesz także określić
-o
przełącznik utput za pomocą ciągutty
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 dodamyfuser
ifind
możemy zweryfikować ścieżkę.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: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 ...
...lub podobne.
źródło