Спецификация POSIX действительно хеджирует свои ставки в отношении управляющего терминала и определяет его таким образом:
- Терминал управления
- Вопрос о том, какой из нескольких специальных файлов, относящихся к терминалу, подразумевается, не рассматривается в POSIX.1. Путь
/dev/tty
является синонимом управляющего терминала, связанного с процессом.
Это в списке определений - и это все, что есть. Но в General Terminal Interface сказано еще кое-что:
Терминал может принадлежать процессу в качестве управляющего терминала. Каждый процесс сеанса, который имеет управляющий терминал, имеет один и тот же управляющий терминал. Терминал может быть управляющим терминалом максимум для одного сеанса. Управляющий терминал для сеанса назначается руководителем сеанса в зависимости от реализации. Если руководитель сеанса не имеет управляющего терминала и открывает файл терминального устройства, который еще не связан с сеансом, без использования опции O_NOCTTY (см. Open ()), то определяется, будет ли реализация становиться управляющим терминалом сеанса. лидер.
Управляющий терминал наследуется дочерним процессом во время вызова функции fork (). Процесс освобождает свой управляющий терминал при создании нового сеанса сsetsid()
функция; другие процессы, оставшиеся в старом сеансе, которые имели этот терминал в качестве управляющего терминала, продолжают иметь его. После закрытия последнего файлового дескриптора в системе (независимо от того, находится ли он в текущем сеансе), связанного с управляющим терминалом, не определено, все ли процессы, которые имели этот терминал в качестве своего управляющего терминала, перестают иметь какой-либо управляющий терминал. Вопрос о том, может ли и как руководитель сеанса повторно получить управляющий терминал после того, как управляющий терминал был освобожден таким образом, не определено. Процесс не отказывается от своего управляющего терминала, просто закрывая все свои файловые дескрипторы, связанные с управляющим терминалом, если другие процессы продолжают открывать его.
Там многое осталось неуказанным - и, честно говоря, я думаю, что это имеет смысл. В то время как терминал является ключевым пользовательским интерфейсом, в некоторых случаях это также все виды других вещей - например, аппаратное обеспечение или даже принтер - но во многих случаях это практически вообще ничего - например, xterm
эмулятор, который просто эмулятор , Здесь сложно конкретизировать - и я не думаю, что это все равно будет в интересах Unix, потому что терминалы делают намного больше, чем Unix.
Во всяком случае, POSIX также довольно сомнительно, как ps
вести себя, когда дело касается ctty.
Там -a
переключатель:
- Запишите информацию для всех процессов, связанных с терминалами. Реализации могут исключить лидеров сеансов из этого списка.
Отлично. Руководители сессий могут быть опущены. Это не очень полезно.
И -t
:
- Запишите информацию для процессов, связанных с терминалами, приведенными в списке терминов. Приложение должно убедиться, что список терминов является единственным аргументом в форме
<blank>
списка, разделенного запятыми. Идентификаторы терминала должны быть заданы в формате, определяемом реализацией .
... что является еще одним разочарованием. Но это говорит о системах XSI:
- В XSI-совместимых системах они должны быть заданы в одной из двух форм: имя файла устройства (например,
tty04
) или, если имя файла устройства начинается с tty
, только идентификатор, следующий за символами tty
(например, 04
) .
Это немного лучше, но это не путь. Также в системах XSI есть -d
переключатель:
- Запишите информацию для всех процессов, кроме руководителей сеансов.
... что по крайней мере понятно. Вы также можете указать -o
переключатель utput со tty
строкой формата, но, как вы заметили, его выходной формат определяется реализацией. Тем не менее, я думаю, что это так же хорошо, как и получается. Я думаю, что - с большой работой - вышеупомянутые переключатели в сочетании с некоторыми другими утилитами могут дать вам довольно хороший пример. Честно говоря, я не знаю, когда / как это сломается для вас - и я не смог представить ситуацию, в которой это произойдет. Но, думаю, возможно, если мы добавим fuser
и find
сможем проверить путь.
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"*}"
Материал /dev/null
был просто для того, чтобы показать, что он может работать, когда ни один из поисковых субоболочек не имеет 0,1,2, связанных с ctty. Во всяком случае, это печатает:
/dev/pts/3: mikeserv 3342 F.... (mikeserv)zsh
Теперь вышесказанное дает полный путь к моей машине, и я думаю, что это будет для большинства людей в большинстве случаев. Я также могу представить, что это может потерпеть неудачу. Это просто грубая эвристика.
Возможно, это может произойти по многим другим причинам, но если вы работаете в системе, которая позволяет руководителю сеанса передавать все дескрипторы на ctty и в то же время оставаться sid, как позволяет спецификация, то это определенно не поможет. Тем не менее, я думаю, что это может получить довольно хорошую оценку в большинстве случаев.
Конечно, проще всего, если у вас есть какие-либо дескрипторы, связанные с вашим ctty, это просто ...
tty <&2
...или похожие.
ps
решение охватывает большинство систем (иwho
не помогает большеps
), возможно, с немного большим количеством кода для обработки только идентификатора (например, «04»). Мне было интересно, есть ли еще более портативное решение.