Как можно получить настоящее имя управляющего терминала (если оно есть, иначе ошибка) в качестве имени пути?
Под «настоящим именем» я подразумеваю /dev/tty
, что другие произвольные процессы не могут ссылаться на один и тот же терминал. Я предпочитаю ответ как простой шелл-код (как в примере ниже), если это возможно, в противном случае как функцию C.
Обратите внимание, что это должно работать, даже если стандартный ввод перенаправлен, так что tty
утилита не может быть использована: not a tty
в таком случае возникнет ошибка, поскольку tty
просто печатается имя файла терминала, подключенного к стандартному вводу.
Под Linux можно использовать:
echo "/dev/`ps -p $$ -o tty | tail -n 1`"
но это не переносимо, так как в соответствии с POSIX формат имени терминала не указан .
Что касается функций C, ctermid (NULL)
возвращает /dev/tty
, что здесь бесполезно.
Примечание: согласно zsh
документации, уметь
zsh -c 'echo $TTY'
но в настоящее время (версия 5.0.7) происходит сбой, когда перенаправляются как стандартный ввод, так и стандартный вывод:
$ zsh -c 'echo $TTY > /dev/tty' < /dev/null
/dev/pts/9
$ zsh -c 'echo $TTY > /dev/tty' < /dev/null > /dev/null
/dev/tty
источник
ps
решение охватывает большинство систем (иwho
не помогает большеps
), возможно, с немного большим количеством кода для обработки только идентификатора (например, «04»). Мне было интересно, есть ли еще более портативное решение.man xterm
:-Sccn
Эта опция позволяетxterm
использовать ее как канал ввода-вывода для существующей программы ... Значение опции - это несколько букв имени pty для использования в подчиненном режиме плюс унаследованный номер fd. Если опция содержит символ «/», она отделяет имя pty от fd.ps
от BusyBox (который используется Android, BTW), даже под GNU / Linux. Что вы подразумеваете под "xterm
может справиться с этим04
"?busybox
не POSIX-совместимый.toybox
Однако, очень хорошо.Ответы:
«Управляющий терминал» ака. CTTY, является distincted от « процесс Терминал взаимодействует с».
Стандартный способ получения пути ctty - ctermid (3). После вызова этого в freebsd начиная с версии 10 ищется фактический путь [1], в то время как более старые реализации freebsd и glibc [2] безоговорочно возвращают "/ dev / tty"].
ps (1) из пакета linux procps 3.2.8, прочитайте числовую запись в / proc / * / stat [3], а затем частично выведите путь , угадав [4, 5] из-за отсутствия системной поддержки [6] ,
Однако, если мы не заинтересованы в ctty, но в любом терминале, связанном с stdio, tty (1) печатает путь терминала, связанный с stdin, который идентичен
ttyname(fileno(stdin))
c, и альтернативой являетсяreadlink /proc/self/fd/0
.Менее важная мысль относительно безусловного поведения "/ dev / tty": спецификации просто говорят, что строка, возвращаемая ctermid "при использовании в качестве имени пути, ссылается на текущий управляющий терминал", а не просто "- это имя пути текущего управляющий терминал ". Это может быть интерпретировано как то, что «/ dev / tty» не является управляющим терминалом, а относится к управляющему терминалу, только если тот же процесс открывает (3) его. Таким образом, не нарушая правило «терминал может быть не более одного сеанса» [7].
Другое следствие состоит в том, что, когда у меня нет какого-либо управляющего терминала, ctermid не выходит из строя - такой сбой допускается спецификациями [8] - так что только я могу узнать о своем ctty'lessness, пока не произойдет сбой последующего открытия (3), это нормально, так как спецификации также говорят, что вызов open (3) не гарантирует успеха.
источник
ps
решение, которое я дал в своем вопросе, поскольку не все ОС имеют/proc
файловую систему. Обратите внимание, чтоps
сам по себе используется ссылка для чтения/proc/self/fd/2
(которая работает, даже если стандартная ошибка перенаправлена).tty
.stderr
вероятно, лучший, потому что он должен быть открытым. Такtty <&2
.ctermid()
постоянного возврата"/dev/tty"
. Это имя всегда относится к управляющему терминалу процесса , который обращается к нему , что зависит от сеанса. Терминал зависит от сеанса, но имя, к которому он обращается, не обязательно.Спецификация POSIX действительно хеджирует свои ставки в отношении управляющего терминала и определяет его таким образом:
/dev/tty
является синонимом управляющего терминала, связанного с процессом.Это в списке определений - и это все, что есть. Но в General Terminal Interface сказано еще кое-что:
Терминал может принадлежать процессу в качестве управляющего терминала. Каждый процесс сеанса, который имеет управляющий терминал, имеет один и тот же управляющий терминал. Терминал может быть управляющим терминалом максимум для одного сеанса. Управляющий терминал для сеанса назначается руководителем сеанса в зависимости от реализации. Если руководитель сеанса не имеет управляющего терминала и открывает файл терминального устройства, который еще не связан с сеансом, без использования опции O_NOCTTY (см. Open ()), то определяется, будет ли реализация становиться управляющим терминалом сеанса. лидер.
Управляющий терминал наследуется дочерним процессом во время вызова функции fork (). Процесс освобождает свой управляющий терминал при создании нового сеанса с
setsid()
функция; другие процессы, оставшиеся в старом сеансе, которые имели этот терминал в качестве управляющего терминала, продолжают иметь его. После закрытия последнего файлового дескриптора в системе (независимо от того, находится ли он в текущем сеансе), связанного с управляющим терминалом, не определено, все ли процессы, которые имели этот терминал в качестве своего управляющего терминала, перестают иметь какой-либо управляющий терминал. Вопрос о том, может ли и как руководитель сеанса повторно получить управляющий терминал после того, как управляющий терминал был освобожден таким образом, не определено. Процесс не отказывается от своего управляющего терминала, просто закрывая все свои файловые дескрипторы, связанные с управляющим терминалом, если другие процессы продолжают открывать его.Там многое осталось неуказанным - и, честно говоря, я думаю, что это имеет смысл. В то время как терминал является ключевым пользовательским интерфейсом, в некоторых случаях это также все виды других вещей - например, аппаратное обеспечение или даже принтер - но во многих случаях это практически вообще ничего - например,
xterm
эмулятор, который просто эмулятор , Здесь сложно конкретизировать - и я не думаю, что это все равно будет в интересах Unix, потому что терминалы делают намного больше, чем Unix.Во всяком случае, POSIX также довольно сомнительно, как
ps
вести себя, когда дело касается ctty.Там
-a
переключатель:Отлично. Руководители сессий могут быть опущены. Это не очень полезно.
И
-t
:<blank>
списка, разделенного запятыми. Идентификаторы терминала должны быть заданы в формате, определяемом реализацией .... что является еще одним разочарованием. Но это говорит о системах XSI:
tty04
) или, если имя файла устройства начинается сtty
, только идентификатор, следующий за символамиtty
(например,04
) .Это немного лучше, но это не путь. Также в системах XSI есть
-d
переключатель:... что по крайней мере понятно. Вы также можете указать
-o
переключатель utput соtty
строкой формата, но, как вы заметили, его выходной формат определяется реализацией. Тем не менее, я думаю, что это так же хорошо, как и получается. Я думаю, что - с большой работой - вышеупомянутые переключатели в сочетании с некоторыми другими утилитами могут дать вам довольно хороший пример. Честно говоря, я не знаю, когда / как это сломается для вас - и я не смог представить ситуацию, в которой это произойдет. Но, думаю, возможно, если мы добавимfuser
иfind
сможем проверить путь.Материал
/dev/null
был просто для того, чтобы показать, что он может работать, когда ни один из поисковых субоболочек не имеет 0,1,2, связанных с ctty. Во всяком случае, это печатает:Теперь вышесказанное дает полный путь к моей машине, и я думаю, что это будет для большинства людей в большинстве случаев. Я также могу представить, что это может потерпеть неудачу. Это просто грубая эвристика.
Возможно, это может произойти по многим другим причинам, но если вы работаете в системе, которая позволяет руководителю сеанса передавать все дескрипторы на ctty и в то же время оставаться sid, как позволяет спецификация, то это определенно не поможет. Тем не менее, я думаю, что это может получить довольно хорошую оценку в большинстве случаев.
Конечно, проще всего, если у вас есть какие-либо дескрипторы, связанные с вашим ctty, это просто ...
...или похожие.
источник